Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
committerdnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
commit749497dde0a1dd08c434a73b9d4e93dc3e3326d9 (patch)
tree7c83a55919c0f1aa1267c4dbcd008f1644f961ee
parentd433e567a561f8ae094a535025b02c7dc47026c6 (diff)
v4.03-9408-rtm
-rw-r--r--AUTHORS.TXT38
-rw-r--r--BUILD_UNIX.TXT125
-rw-r--r--BUILD_WINDOWS.TXT42
-rw-r--r--LICENSE2689
-rw-r--r--LICENSE.TXT2350
-rw-r--r--README189
-rw-r--r--README.TXT189
-rwxr-xr-xconfigure76
-rw-r--r--src/BUILD_UNIX.TXT125
-rw-r--r--src/BUILD_WINDOWS.TXT42
-rw-r--r--src/BuildAll.cmd19
-rw-r--r--src/BuildFiles/Library/Win32_Debug/libeay32.libbin0 -> 12372424 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Debug/libintelaes.libbin0 -> 34486 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Debug/ssleay32.libbin0 -> 2012586 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Debug/zlib.libbin0 -> 250160 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Release/libeay32.libbin0 -> 4013936 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Release/libintelaes.libbin0 -> 34486 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Release/ssleay32.libbin0 -> 724496 bytes
-rw-r--r--src/BuildFiles/Library/Win32_Release/zlib.libbin0 -> 86780 bytes
-rw-r--r--src/BuildFiles/Library/x64_Debug/libeay32.libbin0 -> 12714982 bytes
-rw-r--r--src/BuildFiles/Library/x64_Debug/libintelaes.libbin0 -> 40460 bytes
-rw-r--r--src/BuildFiles/Library/x64_Debug/ssleay32.libbin0 -> 1970180 bytes
-rw-r--r--src/BuildFiles/Library/x64_Debug/zlib.libbin0 -> 236526 bytes
-rw-r--r--src/BuildFiles/Library/x64_Release/libeay32.libbin0 -> 5388356 bytes
-rw-r--r--src/BuildFiles/Library/x64_Release/libintelaes.libbin0 -> 40460 bytes
-rw-r--r--src/BuildFiles/Library/x64_Release/ssleay32.libbin0 -> 919990 bytes
-rw-r--r--src/BuildFiles/Library/x64_Release/zlib.libbin0 -> 118630 bytes
-rw-r--r--src/BuildFiles/Manifests/x64_admin.manifest28
-rw-r--r--src/BuildFiles/Manifests/x64_user.manifest28
-rw-r--r--src/BuildFiles/Manifests/x86_admin.manifest28
-rw-r--r--src/BuildFiles/Manifests/x86_user.manifest28
-rw-r--r--src/BuildFiles/OcxCabInf/vpnweb.inf18
-rw-r--r--src/BuildFiles/Utility/cabarc.exebin0 -> 114688 bytes
-rw-r--r--src/BuildFiles/Utility/cabarc_redist.txt74
-rw-r--r--src/BuildFiles/VerScript/ver.rc30
-rw-r--r--src/BuildFiles/VerScript/ver_vg.rc30
-rw-r--r--src/BuildUtil/BuildUtil.csproj181
-rw-r--r--src/BuildUtil/BuildUtilCommands.cs1245
-rw-r--r--src/BuildUtil/BuildUtilIcon.icobin0 -> 30208 bytes
-rw-r--r--src/BuildUtil/BuildUtilMain.cs193
-rw-r--r--src/BuildUtil/CodeSign.cs263
-rw-r--r--src/BuildUtil/CopyBuildUtil.cmd2
-rw-r--r--src/BuildUtil/CoreUtil.dllbin0 -> 346624 bytes
-rw-r--r--src/BuildUtil/PEUtil.cs231
-rw-r--r--src/BuildUtil/Properties/AssemblyInfo.cs18
-rw-r--r--src/BuildUtil/Properties/Settings.Designer.cs115
-rw-r--r--src/BuildUtil/Properties/Settings.settings12
-rw-r--r--src/BuildUtil/Test.cs125
-rw-r--r--src/BuildUtil/UnixBuildSoftwares.cs1015
-rw-r--r--src/BuildUtil/VpnBuilder.cs650
-rw-r--r--src/BuildUtil/VpnBuilderConfig.cs513
-rw-r--r--src/BuildUtil/VpnBuilderConfigTypes.cs303
-rw-r--r--src/BuildUtil/Web References/HvSignService/Reference.cs282
-rw-r--r--src/BuildUtil/Web References/HvSignService/Sign.disco6
-rw-r--r--src/BuildUtil/Web References/HvSignService/Sign.wsdl106
-rw-r--r--src/BuildUtil/Web References/SignService/Reference.cs281
-rw-r--r--src/BuildUtil/Web References/SignService/Sign.disco6
-rw-r--r--src/BuildUtil/Web References/SignService/Sign.wsdl105
-rw-r--r--src/BuildUtil/Win32BuildSoftware.cs160
-rw-r--r--src/BuildUtil/Win32BuildUtil.cs1063
-rw-r--r--src/BuildUtil/app.config18
-rw-r--r--src/Cedar/Account.c1419
-rw-r--r--src/Cedar/Account.h293
-rw-r--r--src/Cedar/Admin.c13742
-rw-r--r--src/Cedar/Admin.h1505
-rw-r--r--src/Cedar/AzureClient.c658
-rw-r--r--src/Cedar/AzureClient.h149
-rw-r--r--src/Cedar/AzureServer.c90
-rw-r--r--src/Cedar/AzureServer.h94
-rw-r--r--src/Cedar/Bridge.c532
-rw-r--r--src/Cedar/Bridge.h152
-rw-r--r--src/Cedar/BridgeUnix.c1813
-rw-r--r--src/Cedar/BridgeUnix.h191
-rw-r--r--src/Cedar/BridgeWin32.c2217
-rw-r--r--src/Cedar/BridgeWin32.h238
-rw-r--r--src/Cedar/CM.c12394
-rw-r--r--src/Cedar/CM.h132
-rw-r--r--src/Cedar/CMInner.h612
-rw-r--r--src/Cedar/Cedar.c1708
-rw-r--r--src/Cedar/Cedar.h1194
-rw-r--r--src/Cedar/Cedar.vcproj1529
-rw-r--r--src/Cedar/CedarPch.c89
-rw-r--r--src/Cedar/CedarPch.h100
-rw-r--r--src/Cedar/CedarType.h720
-rw-r--r--src/Cedar/Client.c11005
-rw-r--r--src/Cedar/Client.h849
-rw-r--r--src/Cedar/Command.c23538
-rw-r--r--src/Cedar/Command.h648
-rw-r--r--src/Cedar/Connection.c3457
-rw-r--r--src/Cedar/Connection.h341
-rw-r--r--src/Cedar/Console.c2510
-rw-r--r--src/Cedar/Console.h222
-rw-r--r--src/Cedar/DDNS.c984
-rw-r--r--src/Cedar/DDNS.h215
-rw-r--r--src/Cedar/Database.c239
-rw-r--r--src/Cedar/Database.h98
-rw-r--r--src/Cedar/EM.c1476
-rw-r--r--src/Cedar/EM.h96
-rw-r--r--src/Cedar/EMInner.h122
-rw-r--r--src/Cedar/EtherLog.c1356
-rw-r--r--src/Cedar/EtherLog.h255
-rw-r--r--src/Cedar/Hub.c7123
-rw-r--r--src/Cedar/Hub.h598
-rw-r--r--src/Cedar/IPsec.c767
-rw-r--r--src/Cedar/IPsec.h179
-rw-r--r--src/Cedar/IPsec_EtherIP.c539
-rw-r--r--src/Cedar/IPsec_EtherIP.h150
-rw-r--r--src/Cedar/IPsec_IKE.c5947
-rw-r--r--src/Cedar/IPsec_IKE.h450
-rw-r--r--src/Cedar/IPsec_IPC.c2028
-rw-r--r--src/Cedar/IPsec_IPC.h243
-rw-r--r--src/Cedar/IPsec_IkePacket.c3129
-rw-r--r--src/Cedar/IPsec_IkePacket.h711
-rw-r--r--src/Cedar/IPsec_L2TP.c2498
-rw-r--r--src/Cedar/IPsec_L2TP.h347
-rw-r--r--src/Cedar/IPsec_PPP.c2689
-rw-r--r--src/Cedar/IPsec_PPP.h311
-rw-r--r--src/Cedar/IPsec_Win7.c530
-rw-r--r--src/Cedar/IPsec_Win7.h121
-rw-r--r--src/Cedar/IPsec_Win7Inner.h160
-rw-r--r--src/Cedar/Interop_OpenVPN.c2942
-rw-r--r--src/Cedar/Interop_OpenVPN.h362
-rw-r--r--src/Cedar/Interop_SSTP.c1222
-rw-r--r--src/Cedar/Interop_SSTP.h238
-rw-r--r--src/Cedar/Layer3.c2173
-rw-r--r--src/Cedar/Layer3.h229
-rw-r--r--src/Cedar/Link.c655
-rw-r--r--src/Cedar/Link.h139
-rw-r--r--src/Cedar/Listener.c1079
-rw-r--r--src/Cedar/Listener.h188
-rw-r--r--src/Cedar/Logging.c2054
-rw-r--r--src/Cedar/Logging.h248
-rw-r--r--src/Cedar/NM.c1516
-rw-r--r--src/Cedar/NM.h96
-rw-r--r--src/Cedar/NMInner.h148
-rw-r--r--src/Cedar/Nat.c1876
-rw-r--r--src/Cedar/Nat.h291
-rw-r--r--src/Cedar/NativeStack.c417
-rw-r--r--src/Cedar/NativeStack.h123
-rw-r--r--src/Cedar/NullLan.c256
-rw-r--r--src/Cedar/NullLan.h117
-rw-r--r--src/Cedar/Protocol.c6535
-rw-r--r--src/Cedar/Protocol.h270
-rw-r--r--src/Cedar/Radius.c90
-rw-r--r--src/Cedar/Radius.h99
-rw-r--r--src/Cedar/Remote.c448
-rw-r--r--src/Cedar/Remote.h127
-rw-r--r--src/Cedar/SM.c20505
-rw-r--r--src/Cedar/SM.h95
-rw-r--r--src/Cedar/SMInner.h801
-rw-r--r--src/Cedar/SW.c6569
-rw-r--r--src/Cedar/SW.h105
-rw-r--r--src/Cedar/SWInner.h425
-rw-r--r--src/Cedar/Sam.c415
-rw-r--r--src/Cedar/Sam.h106
-rw-r--r--src/Cedar/SeLowUser.c772
-rw-r--r--src/Cedar/SeLowUser.h154
-rw-r--r--src/Cedar/SecureInfo.c90
-rw-r--r--src/Cedar/SecureInfo.h94
-rw-r--r--src/Cedar/SecureNAT.c228
-rw-r--r--src/Cedar/SecureNAT.h108
-rw-r--r--src/Cedar/Server.c10466
-rw-r--r--src/Cedar/Server.h664
-rw-r--r--src/Cedar/Session.c2242
-rw-r--r--src/Cedar/Session.h408
-rw-r--r--src/Cedar/UT.c393
-rw-r--r--src/Cedar/UT.h112
-rw-r--r--src/Cedar/UdpAccel.c1157
-rw-r--r--src/Cedar/UdpAccel.h195
-rw-r--r--src/Cedar/VG.c105
-rw-r--r--src/Cedar/VG.h101
-rw-r--r--src/Cedar/VLan.c108
-rw-r--r--src/Cedar/VLan.h112
-rw-r--r--src/Cedar/VLanUnix.c791
-rw-r--r--src/Cedar/VLanUnix.h144
-rw-r--r--src/Cedar/VLanWin32.c1587
-rw-r--r--src/Cedar/VLanWin32.h174
-rw-r--r--src/Cedar/Virtual.c10117
-rw-r--r--src/Cedar/Virtual.h659
-rw-r--r--src/Cedar/WaterMark.c4386
-rw-r--r--src/Cedar/WaterMark.h110
-rw-r--r--src/Cedar/WebUI.c1961
-rw-r--r--src/Cedar/WebUI.h119
-rw-r--r--src/Cedar/Win32Com.cpp979
-rw-r--r--src/Cedar/Win32Com.h400
-rw-r--r--src/Cedar/WinJumpList.cpp759
-rw-r--r--src/Cedar/WinUi.c11339
-rw-r--r--src/Cedar/WinUi.h906
-rw-r--r--src/Cedar/Wpc.c1326
-rw-r--r--src/Cedar/Wpc.h201
-rw-r--r--src/Cedar/netcfgn.h1335
-rw-r--r--src/Cedar/netcfgx.h1941
-rw-r--r--src/Cedar/winpcap/Devioctl.h90
-rw-r--r--src/Cedar/winpcap/Gnuc.h46
-rw-r--r--src/Cedar/winpcap/Ntddndis.h1400
-rw-r--r--src/Cedar/winpcap/Ntddpack.h26
-rw-r--r--src/Cedar/winpcap/Packet32.h423
-rw-r--r--src/Cedar/winpcap/Win32-Extensions.h86
-rw-r--r--src/Cedar/winpcap/bittypes.h135
-rw-r--r--src/Cedar/winpcap/bucket_lookup.h54
-rw-r--r--src/Cedar/winpcap/count_packets.h62
-rw-r--r--src/Cedar/winpcap/ip6_misc.h163
-rw-r--r--src/Cedar/winpcap/memory_t.h132
-rw-r--r--src/Cedar/winpcap/normal_lookup.h56
-rw-r--r--src/Cedar/winpcap/pcap-bpf.h685
-rw-r--r--src/Cedar/winpcap/pcap-int.h368
-rw-r--r--src/Cedar/winpcap/pcap-stdinc.h65
-rw-r--r--src/Cedar/winpcap/pcap.h337
-rw-r--r--src/Cedar/winpcap/pthread.h1300
-rw-r--r--src/Cedar/winpcap/remote-ext.h420
-rw-r--r--src/Cedar/winpcap/sched.h174
-rw-r--r--src/Cedar/winpcap/semaphore.h163
-rw-r--r--src/Cedar/winpcap/tcp_session.h96
-rw-r--r--src/Cedar/winpcap/time_calls.h438
-rw-r--r--src/Cedar/winpcap/tme.h174
-rw-r--r--src/CurrentBuild.txt4
-rw-r--r--src/GlobalConst.h151
-rw-r--r--src/Ham/Cert.icobin0 -> 1078 bytes
-rw-r--r--src/Ham/Ham.c7
-rw-r--r--src/Ham/Ham.h1
-rw-r--r--src/Ham/Ham.rc72
-rw-r--r--src/Ham/Ham.vcproj471
-rw-r--r--src/Ham/Mon.c1
-rw-r--r--src/Ham/Mon.h1
-rw-r--r--src/Ham/NIC.icobin0 -> 111650 bytes
-rw-r--r--src/Ham/Scan.c1
-rw-r--r--src/Ham/Scan.h1
-rw-r--r--src/Ham/resource.h19
-rw-r--r--src/LICENSE2350
-rw-r--r--src/LICENSE.TXT2350
-rw-r--r--src/Mayaqua/Cfg.c2306
-rw-r--r--src/Mayaqua/Cfg.h249
-rw-r--r--src/Mayaqua/Encrypt.c4691
-rw-r--r--src/Mayaqua/Encrypt.h486
-rw-r--r--src/Mayaqua/FileIO.c2738
-rw-r--r--src/Mayaqua/FileIO.h354
-rw-r--r--src/Mayaqua/Internat.c3483
-rw-r--r--src/Mayaqua/Internat.h227
-rw-r--r--src/Mayaqua/Kernel.c2172
-rw-r--r--src/Mayaqua/Kernel.h252
-rw-r--r--src/Mayaqua/MayaType.h553
-rw-r--r--src/Mayaqua/Mayaqua.c1200
-rw-r--r--src/Mayaqua/Mayaqua.h595
-rw-r--r--src/Mayaqua/Mayaqua.vcproj833
-rw-r--r--src/Mayaqua/Memory.c4124
-rw-r--r--src/Mayaqua/Memory.h429
-rw-r--r--src/Mayaqua/Microsoft.c14824
-rw-r--r--src/Mayaqua/Microsoft.h1155
-rw-r--r--src/Mayaqua/Network.c21774
-rw-r--r--src/Mayaqua/Network.h1582
-rw-r--r--src/Mayaqua/OS.c527
-rw-r--r--src/Mayaqua/OS.h220
-rw-r--r--src/Mayaqua/Object.c596
-rw-r--r--src/Mayaqua/Object.h189
-rw-r--r--src/Mayaqua/Pack.c1671
-rw-r--r--src/Mayaqua/Pack.h234
-rw-r--r--src/Mayaqua/Secure.c2197
-rw-r--r--src/Mayaqua/Secure.h297
-rw-r--r--src/Mayaqua/Str.c3391
-rw-r--r--src/Mayaqua/Str.h228
-rw-r--r--src/Mayaqua/Table.c1473
-rw-r--r--src/Mayaqua/Table.h186
-rw-r--r--src/Mayaqua/TcpIp.c3802
-rw-r--r--src/Mayaqua/TcpIp.h876
-rw-r--r--src/Mayaqua/Tick64.c378
-rw-r--r--src/Mayaqua/Tick64.h134
-rw-r--r--src/Mayaqua/Tracking.c975
-rw-r--r--src/Mayaqua/Tracking.h171
-rw-r--r--src/Mayaqua/TunTap.h306
-rw-r--r--src/Mayaqua/Unix.c2741
-rw-r--r--src/Mayaqua/Unix.h239
-rw-r--r--src/Mayaqua/Win32.c3463
-rw-r--r--src/Mayaqua/Win32.h204
-rw-r--r--src/Mayaqua/cryptoki.h66
-rw-r--r--src/Mayaqua/intelaes/iaesni.h147
-rw-r--r--src/Mayaqua/pkcs11.h299
-rw-r--r--src/Mayaqua/pkcs11f.h912
-rw-r--r--src/Mayaqua/pkcs11t.h1440
-rw-r--r--src/Mayaqua/win32_inc/openssl/aes.h148
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1.h1332
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1_mac.h571
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1t.h893
-rw-r--r--src/Mayaqua/win32_inc/openssl/bio.h791
-rw-r--r--src/Mayaqua/win32_inc/openssl/blowfish.h129
-rw-r--r--src/Mayaqua/win32_inc/openssl/bn.h855
-rw-r--r--src/Mayaqua/win32_inc/openssl/buffer.h118
-rw-r--r--src/Mayaqua/win32_inc/openssl/cast.h107
-rw-r--r--src/Mayaqua/win32_inc/openssl/comp.h80
-rw-r--r--src/Mayaqua/win32_inc/openssl/conf.h254
-rw-r--r--src/Mayaqua/win32_inc/openssl/conf_api.h89
-rw-r--r--src/Mayaqua/win32_inc/openssl/crypto.h619
-rw-r--r--src/Mayaqua/win32_inc/openssl/des.h245
-rw-r--r--src/Mayaqua/win32_inc/openssl/des_old.h446
-rw-r--r--src/Mayaqua/win32_inc/openssl/dh.h245
-rw-r--r--src/Mayaqua/win32_inc/openssl/dsa.h324
-rw-r--r--src/Mayaqua/win32_inc/openssl/dso.h368
-rw-r--r--src/Mayaqua/win32_inc/openssl/dtls1.h265
-rw-r--r--src/Mayaqua/win32_inc/openssl/e_os2.h279
-rw-r--r--src/Mayaqua/win32_inc/openssl/ebcdic.h19
-rw-r--r--src/Mayaqua/win32_inc/openssl/ec.h526
-rw-r--r--src/Mayaqua/win32_inc/openssl/ecdh.h123
-rw-r--r--src/Mayaqua/win32_inc/openssl/ecdsa.h271
-rw-r--r--src/Mayaqua/win32_inc/openssl/engine.h804
-rw-r--r--src/Mayaqua/win32_inc/openssl/err.h330
-rw-r--r--src/Mayaqua/win32_inc/openssl/evp.h1059
-rw-r--r--src/Mayaqua/win32_inc/openssl/fips.h126
-rw-r--r--src/Mayaqua/win32_inc/openssl/fips_rand.h74
-rw-r--r--src/Mayaqua/win32_inc/openssl/hmac.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/idea.h103
-rw-r--r--src/Mayaqua/win32_inc/openssl/krb5_asn.h256
-rw-r--r--src/Mayaqua/win32_inc/openssl/kssl.h179
-rw-r--r--src/Mayaqua/win32_inc/openssl/lhash.h200
-rw-r--r--src/Mayaqua/win32_inc/openssl/md2.h95
-rw-r--r--src/Mayaqua/win32_inc/openssl/md4.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/md5.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/mdc2.h98
-rw-r--r--src/Mayaqua/win32_inc/openssl/obj_mac.h3914
-rw-r--r--src/Mayaqua/win32_inc/openssl/objects.h1049
-rw-r--r--src/Mayaqua/win32_inc/openssl/ocsp.h623
-rw-r--r--src/Mayaqua/win32_inc/openssl/opensslconf.h259
-rw-r--r--src/Mayaqua/win32_inc/openssl/opensslv.h89
-rw-r--r--src/Mayaqua/win32_inc/openssl/ossl_typ.h183
-rw-r--r--src/Mayaqua/win32_inc/openssl/pem.h782
-rw-r--r--src/Mayaqua/win32_inc/openssl/pem2.h70
-rw-r--r--src/Mayaqua/win32_inc/openssl/pkcs12.h338
-rw-r--r--src/Mayaqua/win32_inc/openssl/pkcs7.h464
-rw-r--r--src/Mayaqua/win32_inc/openssl/pq_compat.h152
-rw-r--r--src/Mayaqua/win32_inc/openssl/pqueue.h96
-rw-r--r--src/Mayaqua/win32_inc/openssl/rand.h167
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc2.h103
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc4.h90
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc5.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/ripemd.h106
-rw-r--r--src/Mayaqua/win32_inc/openssl/rsa.h496
-rw-r--r--src/Mayaqua/win32_inc/openssl/safestack.h1986
-rw-r--r--src/Mayaqua/win32_inc/openssl/sha.h203
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl.h2125
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl2.h268
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl23.h83
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl3.h585
-rw-r--r--src/Mayaqua/win32_inc/openssl/stack.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/store.h554
-rw-r--r--src/Mayaqua/win32_inc/openssl/symhacks.h429
-rw-r--r--src/Mayaqua/win32_inc/openssl/tls1.h410
-rw-r--r--src/Mayaqua/win32_inc/openssl/tmdiff.h93
-rw-r--r--src/Mayaqua/win32_inc/openssl/txt_db.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/ui.h381
-rw-r--r--src/Mayaqua/win32_inc/openssl/ui_compat.h83
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509.h1357
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509_vfy.h534
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509v3.h922
-rw-r--r--src/Mayaqua/zlib/zconf.h332
-rw-r--r--src/Mayaqua/zlib/zlib.h1357
-rw-r--r--src/Neo/NDIS5.c1704
-rw-r--r--src/Neo/NDIS5.h269
-rw-r--r--src/Neo/Neo.c442
-rw-r--r--src/Neo/Neo.h313
-rw-r--r--src/Neo/Neo.rc63
-rw-r--r--src/Neo/Neo.vcproj280
-rw-r--r--src/Neo/resource.h84
-rw-r--r--src/Neo6/NDIS6.c1745
-rw-r--r--src/Neo6/NDIS6.h239
-rw-r--r--src/Neo6/Neo6.c499
-rw-r--r--src/Neo6/Neo6.h320
-rw-r--r--src/Neo6/Neo6.rc63
-rw-r--r--src/Neo6/Neo6.vcproj282
-rw-r--r--src/Neo6/resource.h84
-rw-r--r--src/PenCore/AboutBox.bmpbin0 -> 64918 bytes
-rw-r--r--src/PenCore/Azure.bmpbin0 -> 210494 bytes
-rw-r--r--src/PenCore/Azure.icobin0 -> 3638 bytes
-rw-r--r--src/PenCore/AzureCn.bmpbin0 -> 210494 bytes
-rw-r--r--src/PenCore/AzureJa.bmpbin0 -> 210494 bytes
-rw-r--r--src/PenCore/BMP_UT.bmpbin0 -> 7414 bytes
-rw-r--r--src/PenCore/Bridge.icobin0 -> 53118 bytes
-rw-r--r--src/PenCore/Cascade.icobin0 -> 60373 bytes
-rw-r--r--src/PenCore/CascadeOffline.icobin0 -> 50184 bytes
-rw-r--r--src/PenCore/CascadeOffline2.icobin0 -> 47123 bytes
-rw-r--r--src/PenCore/Cert.icobin0 -> 27108 bytes
-rw-r--r--src/PenCore/CertX.icobin0 -> 25521 bytes
-rw-r--r--src/PenCore/ClientBanner.bmpbin0 -> 43658 bytes
-rw-r--r--src/PenCore/Coins.bmpbin0 -> 5758 bytes
-rw-r--r--src/PenCore/DDNS.icobin0 -> 6518 bytes
-rw-r--r--src/PenCore/DateTime.icobin0 -> 34878 bytes
-rw-r--r--src/PenCore/Discard.icobin0 -> 25097 bytes
-rw-r--r--src/PenCore/DiscardDisable.icobin0 -> 25149 bytes
-rw-r--r--src/PenCore/Display.icobin0 -> 43119 bytes
-rw-r--r--src/PenCore/Dummy.bin1
-rw-r--r--src/PenCore/EasyInstaller.icobin0 -> 79051 bytes
-rw-r--r--src/PenCore/EtherIP.bmpbin0 -> 11750 bytes
-rw-r--r--src/PenCore/Farm.icobin0 -> 36246 bytes
-rw-r--r--src/PenCore/Group.icobin0 -> 62265 bytes
-rw-r--r--src/PenCore/GroupDeny.icobin0 -> 49508 bytes
-rw-r--r--src/PenCore/Hub.icobin0 -> 50632 bytes
-rw-r--r--src/PenCore/Hub_Offline.icobin0 -> 39325 bytes
-rw-r--r--src/PenCore/IPsec.icobin0 -> 9062 bytes
-rw-r--r--src/PenCore/IX2015.bmpbin0 -> 57398 bytes
-rw-r--r--src/PenCore/Ibaraki.bmpbin0 -> 21446 bytes
-rw-r--r--src/PenCore/Information.icobin0 -> 49761 bytes
-rw-r--r--src/PenCore/Installer.icobin0 -> 4710 bytes
-rw-r--r--src/PenCore/Internet.icobin0 -> 74179 bytes
-rw-r--r--src/PenCore/InternetX.icobin0 -> 64779 bytes
-rw-r--r--src/PenCore/Key.icobin0 -> 36569 bytes
-rw-r--r--src/PenCore/L2TP.bmpbin0 -> 13082 bytes
-rw-r--r--src/PenCore/LANG_CHINESE.icobin0 -> 2238 bytes
-rw-r--r--src/PenCore/LANG_ENGLISH.icobin0 -> 2238 bytes
-rw-r--r--src/PenCore/LANG_JAPANESE.icobin0 -> 2238 bytes
-rw-r--r--src/PenCore/Language.icobin0 -> 39851 bytes
-rw-r--r--src/PenCore/License.icobin0 -> 28037 bytes
-rw-r--r--src/PenCore/Link.icobin0 -> 28199 bytes
-rw-r--r--src/PenCore/Link2.icobin0 -> 27686 bytes
-rw-r--r--src/PenCore/Log.icobin0 -> 26424 bytes
-rw-r--r--src/PenCore/Log2.icobin0 -> 37446 bytes
-rw-r--r--src/PenCore/Machine.icobin0 -> 41512 bytes
-rw-r--r--src/PenCore/ManagerLogo.bmpbin0 -> 37110 bytes
-rw-r--r--src/PenCore/Memory.icobin0 -> 30208 bytes
-rw-r--r--src/PenCore/NIC.icobin0 -> 111650 bytes
-rw-r--r--src/PenCore/NIC_Offline.icobin0 -> 67952 bytes
-rw-r--r--src/PenCore/New.icobin0 -> 52948 bytes
-rw-r--r--src/PenCore/Null.icobin0 -> 1078 bytes
-rw-r--r--src/PenCore/OpenVPN.bmpbin0 -> 45538 bytes
-rw-r--r--src/PenCore/OpenVPN.icobin0 -> 2238 bytes
-rw-r--r--src/PenCore/PKCS12.icobin0 -> 33412 bytes
-rw-r--r--src/PenCore/Pass.icobin0 -> 29802 bytes
-rw-r--r--src/PenCore/PassDisable.icobin0 -> 29130 bytes
-rw-r--r--src/PenCore/PenCore.c8
-rw-r--r--src/PenCore/PenCore.def2
-rw-r--r--src/PenCore/PenCore.rc4890
-rw-r--r--src/PenCore/PenCore.vcproj667
-rw-r--r--src/PenCore/Penguin.icobin0 -> 766 bytes
-rw-r--r--src/PenCore/Police.icobin0 -> 187434 bytes
-rw-r--r--src/PenCore/Progress.avibin0 -> 25600 bytes
-rw-r--r--src/PenCore/Protocol.icobin0 -> 38812 bytes
-rw-r--r--src/PenCore/Protocol2.icobin0 -> 35244 bytes
-rw-r--r--src/PenCore/ProtocolDhcp.icobin0 -> 57368 bytes
-rw-r--r--src/PenCore/ProtocolOffline.icobin0 -> 33881 bytes
-rw-r--r--src/PenCore/Research.icobin0 -> 13206 bytes
-rw-r--r--src/PenCore/Router.icobin0 -> 38375 bytes
-rw-r--r--src/PenCore/RouterBanner.bmpbin0 -> 92758 bytes
-rw-r--r--src/PenCore/RouterLogo.bmpbin0 -> 24638 bytes
-rw-r--r--src/PenCore/SELOGO49x49.bmpbin0 -> 3546 bytes
-rw-r--r--src/PenCore/SSTP.bmpbin0 -> 51318 bytes
-rw-r--r--src/PenCore/SW_LANG_1.bmpbin0 -> 29618 bytes
-rw-r--r--src/PenCore/SW_LANG_2.bmpbin0 -> 29618 bytes
-rw-r--r--src/PenCore/SW_LANG_3.bmpbin0 -> 8198 bytes
-rw-r--r--src/PenCore/Secure.bmpbin0 -> 68070 bytes
-rw-r--r--src/PenCore/Secure.icobin0 -> 32252 bytes
-rw-r--r--src/PenCore/Secure2.bmpbin0 -> 14758 bytes
-rw-r--r--src/PenCore/Secure3.bmpbin0 -> 14758 bytes
-rw-r--r--src/PenCore/Server.icobin0 -> 47851 bytes
-rw-r--r--src/PenCore/ServerCert.icobin0 -> 27479 bytes
-rw-r--r--src/PenCore/Server_Delete.icobin0 -> 42193 bytes
-rw-r--r--src/PenCore/Server_Offline.icobin0 -> 43996 bytes
-rw-r--r--src/PenCore/Server_Offline_Ex.icobin0 -> 46533 bytes
-rw-r--r--src/PenCore/Server_Online_Ex.icobin0 -> 50104 bytes
-rw-r--r--src/PenCore/SessionBridge.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/SessionMonitor.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Setup.icobin0 -> 87079 bytes
-rw-r--r--src/PenCore/SpecialListener.bmpbin0 -> 139998 bytes
-rw-r--r--src/PenCore/SpecialListener.icobin0 -> 71167 bytes
-rw-r--r--src/PenCore/Stop.icobin0 -> 25934 bytes
-rw-r--r--src/PenCore/Switch.icobin0 -> 37678 bytes
-rw-r--r--src/PenCore/SwitchOffline.icobin0 -> 35286 bytes
-rw-r--r--src/PenCore/Test.bmpbin0 -> 15234 bytes
-rw-r--r--src/PenCore/Test.icobin0 -> 40364 bytes
-rw-r--r--src/PenCore/Thumbs.dbbin0 -> 66048 bytes
-rw-r--r--src/PenCore/Tower.icobin0 -> 31063 bytes
-rw-r--r--src/PenCore/Tray0.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Tray1.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Tray2.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Tray3.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Tray4.icobin0 -> 1406 bytes
-rw-r--r--src/PenCore/Tsukuba.bmpbin0 -> 14758 bytes
-rw-r--r--src/PenCore/UnivTsukuba.bmpbin0 -> 2758 bytes
-rw-r--r--src/PenCore/Update.bmpbin0 -> 53834 bytes
-rw-r--r--src/PenCore/User.icobin0 -> 54358 bytes
-rw-r--r--src/PenCore/UserAdmin.icobin0 -> 47086 bytes
-rw-r--r--src/PenCore/UserDeny.icobin0 -> 43596 bytes
-rw-r--r--src/PenCore/VLan.icobin0 -> 34791 bytes
-rw-r--r--src/PenCore/VMBridge.bmpbin0 -> 64998 bytes
-rw-r--r--src/PenCore/VPN.icobin0 -> 139216 bytes
-rw-r--r--src/PenCore/VPNGateBanner.bmpbin0 -> 102846 bytes
-rw-r--r--src/PenCore/VPNGateEN.bmpbin0 -> 154574 bytes
-rw-r--r--src/PenCore/VPNGateJA.bmpbin0 -> 154574 bytes
-rw-r--r--src/PenCore/VPNServerFigure.bmpbin0 -> 69478 bytes
-rw-r--r--src/PenCore/VPNSvr.icobin0 -> 184165 bytes
-rw-r--r--src/PenCore/Warning.icobin0 -> 34114 bytes
-rw-r--r--src/PenCore/WinPC.bmpbin0 -> 10118 bytes
-rw-r--r--src/PenCore/X.icobin0 -> 3638 bytes
-rw-r--r--src/PenCore/ZuruHam.icobin0 -> 33982 bytes
-rw-r--r--src/PenCore/Zurukko.bmpbin0 -> 4838 bytes
-rw-r--r--src/PenCore/Zurukko.icobin0 -> 33982 bytes
-rw-r--r--src/PenCore/resource.h1204
-rw-r--r--src/PenCore/setup_1.bmpbin0 -> 14470 bytes
-rw-r--r--src/PenCore/setup_2.bmpbin0 -> 36698 bytes
-rw-r--r--src/README189
-rw-r--r--src/README.TXT189
-rw-r--r--src/SEVPN.sln377
-rw-r--r--src/SeLow/SeLow.c2104
-rw-r--r--src/SeLow/SeLow.h361
-rw-r--r--src/SeLow/SeLow.rc63
-rw-r--r--src/SeLow/SeLow.vcproj278
-rw-r--r--src/SeLow/SeLowCommon.h175
-rw-r--r--src/SeLow/resource.h84
-rw-r--r--src/See/DEBUG.H63
-rw-r--r--src/See/Devioctl.h90
-rw-r--r--src/See/Ntddndis.h1400
-rw-r--r--src/See/Ntddpack.h26
-rw-r--r--src/See/Openclos.c707
-rw-r--r--src/See/Packet.c1607
-rw-r--r--src/See/Packet.h954
-rw-r--r--src/See/Packet32.h423
-rw-r--r--src/See/Read.c938
-rw-r--r--src/See/See.rc63
-rw-r--r--src/See/See.vcproj462
-rw-r--r--src/See/Write.c426
-rw-r--r--src/See/bucket_lookup.c264
-rw-r--r--src/See/bucket_lookup.h54
-rw-r--r--src/See/count_packets.c64
-rw-r--r--src/See/count_packets.h62
-rw-r--r--src/See/dagc.h225
-rw-r--r--src/See/dump.c570
-rw-r--r--src/See/functions.c95
-rw-r--r--src/See/functions.h78
-rw-r--r--src/See/jitter.c687
-rw-r--r--src/See/jitter.h404
-rw-r--r--src/See/memory_t.h132
-rw-r--r--src/See/normal_lookup.c204
-rw-r--r--src/See/normal_lookup.h56
-rw-r--r--src/See/resource.h84
-rw-r--r--src/See/resource1.h84
-rw-r--r--src/See/tcp_session.c296
-rw-r--r--src/See/tcp_session.h96
-rw-r--r--src/See/time_calls.h486
-rw-r--r--src/See/tme.c385
-rw-r--r--src/See/tme.h174
-rw-r--r--src/See/valid_insns.h117
-rw-r--r--src/See/win_bpf.h417
-rw-r--r--src/See/win_bpf_filter.c1086
-rw-r--r--src/See/win_bpf_filter_init.c509
-rw-r--r--src/See/win_bpf_filter_init.h50
-rw-r--r--src/SeeDll/AdInfo.c1410
-rw-r--r--src/SeeDll/Devioctl.h90
-rw-r--r--src/SeeDll/Ntddndis.h1400
-rw-r--r--src/SeeDll/Ntddpack.h26
-rw-r--r--src/SeeDll/Packet32.c2302
-rw-r--r--src/SeeDll/Packet32.h424
-rw-r--r--src/SeeDll/SeeDll.rc63
-rw-r--r--src/SeeDll/SeeDll.vcproj288
-rw-r--r--src/SeeDll/See_Win32.def34
-rw-r--r--src/SeeDll/See_x64.def34
-rw-r--r--src/SeeDll/dagc.h225
-rw-r--r--src/SeeDll/resource.h84
-rw-r--r--src/VGate/VGate.c109
-rw-r--r--src/VGate/VGate.h89
-rw-r--r--src/VGate/VGate.rc63
-rw-r--r--src/VGate/VGate.vcproj472
-rw-r--r--src/VGate/VGateCommon.h8
-rw-r--r--src/VGate/VGate_Win32.def7
-rw-r--r--src/VGate/VGate_x64.def5
-rw-r--r--src/VGate/resource.h84
-rw-r--r--src/Wfp/Wfp.c1282
-rw-r--r--src/Wfp/Wfp.h126
-rw-r--r--src/Wfp/Wfp.rc63
-rw-r--r--src/Wfp/Wfp.vcproj276
-rw-r--r--src/Wfp/WfpInner.h315
-rw-r--r--src/Wfp/resource1.h84
-rw-r--r--src/bin/BuiltHamcoreFiles/unix/hamcore.se2bin0 -> 1034007 bytes
-rw-r--r--src/bin/hamcore/SeLow_x64.inf65
-rw-r--r--src/bin/hamcore/SeLow_x64.sysbin0 -> 38112 bytes
-rw-r--r--src/bin/hamcore/SeLow_x86.inf65
-rw-r--r--src/bin/hamcore/SeLow_x86.sysbin0 -> 30816 bytes
-rw-r--r--src/bin/hamcore/backup_dir_readme.txt10
-rw-r--r--src/bin/hamcore/egg1.exebin0 -> 66944 bytes
-rw-r--r--src/bin/hamcore/egg2.exebin0 -> 30080 bytes
-rw-r--r--src/bin/hamcore/egg3.exebin0 -> 313728 bytes
-rw-r--r--src/bin/hamcore/empty.config3
-rw-r--r--src/bin/hamcore/empty_sevpnclient.config77
-rw-r--r--src/bin/hamcore/eula.txt444
-rw-r--r--src/bin/hamcore/inf/selow_x64/SeLow_x64.inf70
-rw-r--r--src/bin/hamcore/inf/selow_x64/inf.catbin0 -> 6275 bytes
-rw-r--r--src/bin/hamcore/inf/selow_x86/SeLow_x86.inf70
-rw-r--r--src/bin/hamcore/inf/selow_x86/inf.catbin0 -> 6275 bytes
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN10.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN100.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN101.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN102.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN103.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN104.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN105.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN106.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN107.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN108.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN109.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN11.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN110.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN111.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN112.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN113.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN114.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN115.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN116.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN117.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN118.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN119.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN12.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN120.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN121.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN122.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN123.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN124.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN125.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN126.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN127.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN13.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN14.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN15.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN16.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN17.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN18.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN19.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN2.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN20.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN21.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN22.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN23.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN24.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN25.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN26.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN27.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN28.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN29.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN3.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN30.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN31.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN32.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN33.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN34.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN35.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN36.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN37.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN38.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN39.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN4.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN40.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN41.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN42.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN43.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN44.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN45.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN46.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN47.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN48.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN49.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN5.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN50.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN51.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN52.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN53.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN54.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN55.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN56.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN57.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN58.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN59.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN6.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN60.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN61.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN62.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN63.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN64.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN65.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN66.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN67.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN68.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN69.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN7.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN70.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN71.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN72.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN73.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN74.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN75.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN76.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN77.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN78.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN79.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN8.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN80.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN81.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN82.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN83.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN84.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN85.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN86.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN87.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN88.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN89.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN9.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN90.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN91.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN92.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN93.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN94.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN95.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN96.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN97.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN98.inf109
-rw-r--r--src/bin/hamcore/inf/x64/INF_VPN99.inf109
-rw-r--r--src/bin/hamcore/inf/x64/inf.catbin0 -> 43113 bytes
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN10.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN100.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN101.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN102.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN103.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN104.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN105.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN106.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN107.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN108.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN109.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN11.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN110.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN111.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN112.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN113.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN114.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN115.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN116.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN117.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN118.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN119.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN12.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN120.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN121.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN122.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN123.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN124.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN125.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN126.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN127.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN13.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN14.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN15.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN16.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN17.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN18.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN19.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN2.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN20.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN21.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN22.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN23.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN24.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN25.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN26.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN27.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN28.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN29.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN3.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN30.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN31.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN32.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN33.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN34.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN35.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN36.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN37.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN38.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN39.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN4.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN40.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN41.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN42.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN43.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN44.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN45.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN46.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN47.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN48.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN49.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN5.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN50.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN51.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN52.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN53.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN54.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN55.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN56.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN57.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN58.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN59.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN6.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN60.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN61.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN62.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN63.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN64.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN65.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN66.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN67.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN68.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN69.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN7.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN70.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN71.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN72.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN73.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN74.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN75.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN76.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN77.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN78.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN79.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN8.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN80.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN81.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN82.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN83.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN84.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN85.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN86.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN87.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN88.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN89.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN9.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN90.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN91.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN92.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN93.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN94.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN95.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN96.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN97.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN98.inf109
-rw-r--r--src/bin/hamcore/inf/x86/INF_VPN99.inf109
-rw-r--r--src/bin/hamcore/inf/x86/inf.catbin0 -> 43113 bytes
-rw-r--r--src/bin/hamcore/install_src.dat1
-rw-r--r--src/bin/hamcore/lang.config17
-rw-r--r--src/bin/hamcore/languages.txt8
-rw-r--r--src/bin/hamcore/legal.txt323
-rw-r--r--src/bin/hamcore/openvpn_readme.pdfbin0 -> 490556 bytes
-rw-r--r--src/bin/hamcore/openvpn_readme.txt292
-rw-r--r--src/bin/hamcore/openvpn_sample.ovpn137
-rw-r--r--src/bin/hamcore/pxwfp_x64.sysbin0 -> 22240 bytes
-rw-r--r--src/bin/hamcore/pxwfp_x86.sysbin0 -> 18016 bytes
-rw-r--r--src/bin/hamcore/see.sysbin0 -> 43104 bytes
-rw-r--r--src/bin/hamcore/see_x64.sysbin0 -> 38240 bytes
-rw-r--r--src/bin/hamcore/strtable_cn.stb7088
-rw-r--r--src/bin/hamcore/strtable_en.stb7091
-rw-r--r--src/bin/hamcore/strtable_ja.stb7089
-rw-r--r--src/bin/hamcore/time.htm168
-rw-r--r--src/bin/hamcore/vpn16.exebin0 -> 9472 bytes
-rw-r--r--src/bin/hamcore/vpn_driver.inf107
-rw-r--r--src/bin/hamcore/vpn_driver.sysbin0 -> 25824 bytes
-rw-r--r--src/bin/hamcore/vpn_driver6.sysbin0 -> 26208 bytes
-rw-r--r--src/bin/hamcore/vpn_driver6_x64.sysbin0 -> 28768 bytes
-rw-r--r--src/bin/hamcore/vpn_driver_9x.inf111
-rw-r--r--src/bin/hamcore/vpn_driver_9x.sysbin0 -> 21888 bytes
-rw-r--r--src/bin/hamcore/vpn_driver_x64.inf107
-rw-r--r--src/bin/hamcore/vpn_driver_x64.sysbin0 -> 29536 bytes
-rw-r--r--src/bin/hamcore/vpninstall_cn.inf30
-rw-r--r--src/bin/hamcore/vpninstall_en.inf30
-rw-r--r--src/bin/hamcore/vpninstall_ja.inf35
-rw-r--r--src/bin/hamcore/vpnweb_sample_cn.htm71
-rw-r--r--src/bin/hamcore/vpnweb_sample_en.htm71
-rw-r--r--src/bin/hamcore/vpnweb_sample_ja.htm72
-rw-r--r--src/bin/hamcore/warning_cn.txt137
-rw-r--r--src/bin/hamcore/warning_en.txt136
-rw-r--r--src/bin/hamcore/warning_ja.txt139
-rw-r--r--src/bin/hamcore/webui/cryptcom.cgi49
-rw-r--r--src/bin/hamcore/webui/edituser.cgi32
-rw-r--r--src/bin/hamcore/webui/error.cgi6
-rw-r--r--src/bin/hamcore/webui/hub.cgi51
-rw-r--r--src/bin/hamcore/webui/license.cgi36
-rw-r--r--src/bin/hamcore/webui/listener.cgi13
-rw-r--r--src/bin/hamcore/webui/localbridge.cgi52
-rw-r--r--src/bin/hamcore/webui/login.cgi17
-rw-r--r--src/bin/hamcore/webui/newhub.cgi18
-rw-r--r--src/bin/hamcore/webui/redirect.cgi5
-rw-r--r--src/bin/hamcore/webui/securenat.cgi59
-rw-r--r--src/bin/hamcore/webui/server.cgi42
-rw-r--r--src/bin/hamcore/webui/session.cgi16
-rw-r--r--src/bin/hamcore/webui/user.cgi18
-rw-r--r--src/bin/hamcore/webui/webui.css3
-rw-r--r--src/bin/hamcore/winpcap_installer.exebin0 -> 550560 bytes
-rw-r--r--src/bin/hamcore/winpcap_installer_win9x.exebin0 -> 467181 bytes
-rw-r--r--src/bin/install_src.dat1
-rw-r--r--src/bin/vpnweb.cabbin0 -> 195783 bytes
-rw-r--r--src/bin/vpnweb.ocxbin0 -> 333880 bytes
-rwxr-xr-xsrc/configure10
-rw-r--r--src/makefiles/freebsd_32bit.mak440
-rw-r--r--src/makefiles/freebsd_64bit.mak440
-rw-r--r--src/makefiles/linux_32bit.mak440
-rw-r--r--src/makefiles/linux_64bit.mak440
-rw-r--r--src/makefiles/macos_32bit.mak440
-rw-r--r--src/makefiles/macos_64bit.mak440
-rw-r--r--src/makefiles/solaris_32bit.mak440
-rw-r--r--src/makefiles/solaris_64bit.mak440
-rw-r--r--src/vpnbrand/resource.h17
-rw-r--r--src/vpnbrand/vpnbrand.c7
-rw-r--r--src/vpnbrand/vpnbrand.h113
-rw-r--r--src/vpnbrand/vpnbrand.icobin0 -> 39851 bytes
-rw-r--r--src/vpnbrand/vpnbrand.rc72
-rw-r--r--src/vpnbrand/vpnbrand.vcproj435
-rw-r--r--src/vpnbridge/resource.h17
-rw-r--r--src/vpnbridge/vpnbridge.c141
-rw-r--r--src/vpnbridge/vpnbridge.icobin0 -> 53118 bytes
-rw-r--r--src/vpnbridge/vpnbridge.rc72
-rw-r--r--src/vpnbridge/vpnbridge.vcproj429
-rw-r--r--src/vpnclient/Machine.icobin0 -> 41512 bytes
-rw-r--r--src/vpnclient/resource.h17
-rw-r--r--src/vpnclient/vpnclient.rc72
-rw-r--r--src/vpnclient/vpnclient.vcproj435
-rw-r--r--src/vpnclient/vpncsvc.c128
-rw-r--r--src/vpnclient/vpncsvc.h98
-rw-r--r--src/vpncmd/resource.h17
-rw-r--r--src/vpncmd/vpncmd.c176
-rw-r--r--src/vpncmd/vpncmd.icobin0 -> 47086 bytes
-rw-r--r--src/vpncmd/vpncmd.rc72
-rw-r--r--src/vpncmd/vpncmd.vcproj437
-rw-r--r--src/vpncmdsys/resource.h16
-rw-r--r--src/vpncmdsys/vpncmdsys.c274
-rw-r--r--src/vpncmdsys/vpncmdsys.h96
-rw-r--r--src/vpncmdsys/vpncmdsys.icobin0 -> 47086 bytes
-rw-r--r--src/vpncmdsys/vpncmdsys.rc72
-rw-r--r--src/vpncmdsys/vpncmdsys.vcproj258
-rw-r--r--src/vpncmgr/Server.icobin0 -> 47851 bytes
-rw-r--r--src/vpncmgr/Server_Offline.icobin0 -> 43996 bytes
-rw-r--r--src/vpncmgr/VPN.icobin0 -> 139216 bytes
-rw-r--r--src/vpncmgr/resource.h21
-rw-r--r--src/vpncmgr/vpncmgr.c126
-rw-r--r--src/vpncmgr/vpncmgr.rc74
-rw-r--r--src/vpncmgr/vpncmgr.vcproj441
-rw-r--r--src/vpndrvinst/resource.h19
-rw-r--r--src/vpndrvinst/vpndrvinst.c340
-rw-r--r--src/vpndrvinst/vpndrvinst.h108
-rw-r--r--src/vpndrvinst/vpndrvinst.icobin0 -> 111650 bytes
-rw-r--r--src/vpndrvinst/vpndrvinst.rc72
-rw-r--r--src/vpndrvinst/vpndrvinst.vcproj270
-rw-r--r--src/vpninstall/resource.h86
-rw-r--r--src/vpninstall/vpninstall.c1639
-rw-r--r--src/vpninstall/vpninstall.h212
-rw-r--r--src/vpninstall/vpninstall.icobin0 -> 79051 bytes
-rw-r--r--src/vpninstall/vpninstall.rc221
-rw-r--r--src/vpninstall/vpninstall.vcproj248
-rw-r--r--src/vpnserver/Server.icobin0 -> 60373 bytes
-rw-r--r--src/vpnserver/resource.h17
-rw-r--r--src/vpnserver/vpnserver.c141
-rw-r--r--src/vpnserver/vpnserver.rc72
-rw-r--r--src/vpnserver/vpnserver.vcproj433
-rw-r--r--src/vpnsetup/Installer.icobin0 -> 4710 bytes
-rw-r--r--src/vpnsetup/resource.h33
-rw-r--r--src/vpnsetup/vpnsetup.c120
-rw-r--r--src/vpnsetup/vpnsetup.icobin0 -> 87079 bytes
-rw-r--r--src/vpnsetup/vpnsetup.rc174
-rw-r--r--src/vpnsetup/vpnsetup.vcproj481
-rw-r--r--src/vpnsmgr/VPNSvr.icobin0 -> 184165 bytes
-rw-r--r--src/vpnsmgr/resource.h18
-rw-r--r--src/vpnsmgr/vpnsmgr.c117
-rw-r--r--src/vpnsmgr/vpnsmgr.icobin0 -> 47851 bytes
-rw-r--r--src/vpnsmgr/vpnsmgr.rc72
-rw-r--r--src/vpnsmgr/vpnsmgr.vcproj437
-rw-r--r--src/vpnweb/VPN.icobin0 -> 38768 bytes
-rw-r--r--src/vpnweb/VPNSvr.icobin0 -> 49497 bytes
-rw-r--r--src/vpnweb/VpnWebControl.bmpbin0 -> 246 bytes
-rw-r--r--src/vpnweb/VpnWebControl.cpp4
-rw-r--r--src/vpnweb/VpnWebControl.h382
-rw-r--r--src/vpnweb/VpnWebControl.rgs34
-rw-r--r--src/vpnweb/dlldata.c38
-rw-r--r--src/vpnweb/resource.h80
-rw-r--r--src/vpnweb/stdafx.cpp1
-rw-r--r--src/vpnweb/stdafx.h35
-rw-r--r--src/vpnweb/vpnweb.cpp61
-rw-r--r--src/vpnweb/vpnweb.def7
-rw-r--r--src/vpnweb/vpnweb.h380
-rw-r--r--src/vpnweb/vpnweb.idl51
-rw-r--r--src/vpnweb/vpnweb.rc188
-rw-r--r--src/vpnweb/vpnweb.rgs11
-rw-r--r--src/vpnweb/vpnweb.vcproj369
-rw-r--r--src/vpnweb/vpnweb_i.c85
-rw-r--r--src/vpnweb/vpnweb_p.c783
-rw-r--r--src/vpnweb/vpnwebdlg.c1581
-rw-r--r--src/vpnweb/vpnwebdlg.h122
-rw-r--r--src/vpnweb/vpnwebdlg_inner.h255
986 files changed, 487216 insertions, 339 deletions
diff --git a/AUTHORS.TXT b/AUTHORS.TXT
new file mode 100644
index 00000000..c1a289c6
--- /dev/null
+++ b/AUTHORS.TXT
@@ -0,0 +1,38 @@
+SoftEther VPN is developed by SoftEther VPN Project at University of Tsukuba.
+http://www.softether.org/
+
+AUTHORS OF SOFTETHER VPN
+------------------------
+
+PROGRAMMERS:
+
+ - Daiyuu Nobori
+ Computer Science, Graduate School of University of Tsukuba
+ SoftEther Corporation
+ E-mail: daiyuu-nobori [at] softether.org
+
+ - Tetsuo Sugiyama, Ph. D.
+ SoftEther Corporation
+
+ - Junpei Kuwana
+ Risk Engineering, Graduate School of University of Tsukuba
+ SoftEther Corporation
+
+ - Takao Ito
+ Computer Science, Graduate School of University of Tsukuba
+ SoftEther Corporation
+
+ - Christopher Smith
+ College of Information Science, University of Tsukuba
+
+
+WEB-SITE DESIGNER:
+
+ - Genya Hatakeyama
+ College of Information Science, University of Tsukuba
+
+
+Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+Department of Computer Science has dozens of overly-enthusiastic geeks.
+Join us: http://www.tsukuba.ac.jp/english/admission/
+
diff --git a/BUILD_UNIX.TXT b/BUILD_UNIX.TXT
new file mode 100644
index 00000000..f62295dd
--- /dev/null
+++ b/BUILD_UNIX.TXT
@@ -0,0 +1,125 @@
+How to build SoftEther VPN for UNIX
+===================================
+
+
+Requirements
+------------
+
+You need to install the following software to build SoftEther VPN for UNIX.
+
+- Linux, FreeBSD, Solaris or Mac OS X.
+- GNU Compiler Collectipon (gcc) and binary utilities.
+- GNU Make (gmake).
+- GNU C Library (glibc).
+- POSIX Threads (pthread).
+- OpenSSL (crypto, ssl).
+- libiconv.
+- readline.
+- ncurses.
+
+For example, the following commands help you to install the above programs
+on Fedora or CentOS Linux:
+
+$ yum -y groupinstall "Development Tools"
+$ yum -y install readline-devel ncurses-devel openssl-devel
+
+
+How to Build
+------------
+
+To build the programs from the source code, run the following commands:
+
+$ ./configure
+$ make
+
+If any error occurs, please check the above requirements.
+
+
+How to Install SoftEther VPN Server, Bridge or Client
+-----------------------------------------------------
+
+To install the vpnserver, vpnbridge and vpnclient programs into the
+/usr/bin directory, run the following as the root user:
+
+# make install
+
+After the installation will complete successfully:
+
+- Execute 'vpnserver start' to run the SoftEther VPN Server background service.
+- Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service.
+- Execute 'vpnclient start' to run the SoftEther VPN Client background service.
+- Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure
+ VPN Server, VPN Bridge or VPN Client.
+
+- You can also use VPN Server/Client Manager GUI Tool on other Windows PC to
+ connect to VPN services remotely.
+ You can download the GUI Tools from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Server for Test
+----------------------------------------
+
+To start the SoftEther VPN Server background service, run the following:
+
+$ bin/vpnserver/vpnserver start
+
+To stop the service, run the following:
+
+$ bin/vpnserver/vpnserver stop
+
+To configure the running SoftEther VPN Server service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Server Manager GUI Tool on other Windows PC to
+connect to the VPN Server remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Bridge for Test
+----------------------------------------
+
+To start the SoftEther VPN Bridge background service, run the following:
+
+$ bin/vpnbridge/vpnbridge start
+
+To stop the service, run the following:
+
+$ bin/vpnbridge/vpnbridge stop
+
+To configure the running SoftEther VPN Bridge service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Server Manager GUI Tool on other Windows PC to
+connect to the VPN Bridge remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Client for Test
+----------------------------------------
+
+To start the SoftEther VPN Client background service, run the following:
+
+$ bin/vpnclient/vpnclient start
+
+To stop the service, run the following:
+
+$ bin/vpnclient/vpnclient stop
+
+To configure the running SoftEther VPN Client service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Client Manager GUI Tool on other Windows PC to
+connect to the VPN Client remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+************************************
+Thank You Using SoftEther VPN !
+By SoftEther VPN Open-Source Project
+http://www.softether.org/
diff --git a/BUILD_WINDOWS.TXT b/BUILD_WINDOWS.TXT
new file mode 100644
index 00000000..06e64f72
--- /dev/null
+++ b/BUILD_WINDOWS.TXT
@@ -0,0 +1,42 @@
+How to build SoftEther VPN for Windows
+======================================
+
+
+Requirements
+------------
+
+You need to install the following software to build SoftEther VPN for Windows.
+
+- Microsoft Windows XP, Vista, 7, 8 or later.
+- Microsoft Visual Studio 2008.
+
+* Note:
+ Visual Studio 2008 is required to build SoftEther VPN on Windows.
+ Visual Studio 2010, 2012 or 2013 is currently not supported.
+ Visual Studio 2008 Express Edition is not supported.
+ Standard Edition, Professional Edition, Team System or Team Suite is
+ required.
+
+
+Full Build Instructions
+-----------------------
+
+The following steps will build all SoftEther VPN program files, and also build
+the installer packages of SoftEther VPN. It is very easy.
+
+1. Run the "BuildAll.cmd" batch file in the "src" directory.
+2. Wait until the building process will complete.
+3. The built files are stored on the "output" directory.
+
+
+Partly Build, Debug or Development Instructions on Visual Studio 2008
+---------------------------------------------------------------------
+
+If you are a programmer, you can open the SoftEther VPN solution file
+with Visual Studio 2008 to customize. Open "src\SEVPN.sln" and enjoy it.
+
+
+************************************
+Thank You Using SoftEther VPN !
+By SoftEther VPN Open-Source Project
+http://www.softether.org/
diff --git a/LICENSE b/LICENSE
index d7f10513..52c728da 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,339 +1,2350 @@
-GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- {signature of Ty Coon}, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+SoftEther VPN Server, Client and Bridge are free software, and released as
+open-source. You can redistribute them and/or modify them under the terms of
+the GNU General Public License version 2 as published by the Free Software
+Foundation.
+
+Copyright (c) 2012-2014 Daiyuu Nobori.
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+Copyright (c) 2012-2014 SoftEther Corporation.
+All Rights Reserved.
+http://www.softether.org/
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License version 2 as published by the Free
+Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License version 2
+along with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+Neither the name of SoftEther nor the names of its contributors may be used to
+endorse or promote products derived from this software without specific prior
+written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
+JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
+DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
+JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
+AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
+SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
+OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
+AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
+JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
+ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
+PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
+LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS SOFTWARE
+INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES PROHIBIT ENCRYPTED
+COMMUNICATIONS. USING THIS SOFTWARE IN OTHER COUNTRIES MIGHT BE RESTRICTED.
+
+THE FOLLOWING GPLV2 CONDITIONS APPLY ON ALL SOFTETHER VPN PROGRAMS WHICH ARE
+DEVELOPED BY SOFTETHER VPN PROJECT.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Lesser General Public License instead.) You can apply it
+to your programs, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and modification
+follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included
+without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running the Program
+is not restricted, and the output from the Program is covered only if its
+contents constitute a work based on the Program (independent of having been
+made by running the Program). Whether that is true depends on what the Program
+does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole
+or in part contains or is derived from the Program or any part thereof, to be
+licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+ c) If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the most
+ordinary way, to print or display an announcement including an appropriate
+copyright notice and a notice that there is no warranty (or else, saying that
+you provide a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this License.
+(Exception: if the Program itself is interactive but does not normally print
+such an announcement, your work based on the Program is not required to print
+an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with
+the Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections 1 and
+2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only for
+noncommercial distribution and only if you received the program in object code
+or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the executable. However, as a special exception, the source
+code distributed need not include anything that is normally distributed (in
+either source or binary form) with the major components (compiler, kernel, and
+so on) of the operating system on which the executable runs, unless that
+component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to
+copy from a designated place, then offering equivalent access to copy the
+source code from the same place counts as distribution of the source code,
+even though third parties are not compelled to copy the source along with the
+object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the
+Program (or any work based on the Program), you indicate your acceptance of
+this License to do so, and all its terms and conditions for copying,
+distributing or modifying the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of this License,
+you may choose any version ever published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+Note that the above copyright notices and use conditions do not apply on the
+software components listed in below which are included in this Software. When
+you use or distribute Software with including these libraries, you have to
+follow the conditions of these libraries.
+
+These library's copyright notices and conditions are following;
+
+-------------------
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES
+
+SoftEther provides source codes of some GPL/LGPL/other libraries listed above
+on its web server. Anyone can download, use and re-distribute them under
+individual licenses which are contained on each archive file, available from
+the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES WRITTEN BY SOFTETHER CORPORATION
+
+Note for users of non-Windows version of PacketiX VPN: The enumerated bundle
+of License Agreements above are copies of original License Agreements of each
+library programs which PacketiX VPN uses. PacketiX VPN is not a delivered work
+from these libraries. PacketiX VPN is a separated work from the libraries, but
+it may call functions of the libraries (whether or not PacketiX VPN calls such
+functions are depended on the user's intention to link them or not on user's
+side computer). While some libraries indicate GPL or LGPL as a condition to
+re-distribute, PacketiX VPN is not license under GPL nor LGPL. Therefore, we
+took special care not to make PacketiX VPN become delivered works of any GPL
+or LGPL libraries. In order to achieve that, both PacketiX VPN and GPL/LGPL
+libraries are distributed with isolated forms (means that any program files of
+PacketiX VPN are not bound nor linked to any GPL/LGPL libraries). If a user of
+PacketiX VPN wants to link GPL/LGPL libraries by their own decisions,
+operations and responsibilities, he may do that on his computer. However, if a
+delivered work under copyright law is created as a result of such an
+operation, such a delivered work must not re-distributed to other people,
+because it may violate GPL/LGPL libraries' conditions.
+
+Note for users of Windows version of PacketiX VPN: For technical reason, the
+above texts are exactly same as a file which is also contained on the
+non-Windows version of PacketiX VPN. Actually, the Windows version of PacketiX
+VPN has no relations to any GPL/LGPL libraries enumerated above.
+
+SoftEther Corporation provides source codes of some GPL/LGPL/other libraries
+listed above on its web server. Anyone can download, use and re-distribute
+them under individual licenses which are contained on each archive file,
+available from the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+THE IMPORTANT NOTICES ABOUT SOFTETHER VPN
+
+FUNCTIONS OF VPN COMMUNICATIONS EMBEDDED ON THIS SOFTWARE ARE VERY POWERFUL
+THAN EVER. THIS STRONG VPN ABILITY WILL BRING YOU HUGE BENEFITS. HOWEVER, IF
+YOU MISUSE THIS SOFTWARE, IT MIGHT DAMAGES YOURSELF. IN ORDER TO AVOID SUCH
+RISKS, THIS DOCUMENT ACCOUNTS IMPORTANT NOTICES FOR CUSTOMERS WHO ARE WILLING
+TO USE THIS SOFTWARE. THE FOLLOWING INSTRUCTIONS ARE VERY IMPORTANT. READ AND
+UNDERSTAND IT CAREFULLY. ADDITIONALLY, IF YOU ARE PLANNING TO USE THE DYNAMIC
+DNS, THE NAT TRAVERSAL OR THE VPN AZURE FUNCTIONS, READ THE SECTION 3.5
+CAREFULLY. THESE FUNCTIONS ARE FREE SERVICES PROVIDED VIA THE INTERNET, ARE
+NOT GUARANTEED, AND ARE NOT INTENDED TO BE USED FOR BUSINESS OR COMMERCIAL
+USE. DO NOT USE THESE SERVICES FOR YOUR BUSINESS OR COMMERCIAL USE.
+
+
+1. VPN Communication Protocols
+1.1. SoftEther VPN Protocol
+SoftEther VPN can perform VPN communication. Unlike traditional VPN protocols,
+SoftEther VPN has an implementation of the newly-designed "SoftEther VPN
+Protocol (SE-VPN Protocol)" . SE-VPN protocol encapsulates any Ethernet
+packets into a HTTPS (HTTP over SSL) connection. Therefore SE-VPN protocol can
+communicate beyond firewalls even if the firewall is configured to block
+traditional VPN packets by network administrator. SE-VPN protocol is designed
+and implemented to comply TLS 1.0 (RFC 5246) and HTTPS (RFC 2818). However, it
+sometimes have different behavior to RFCs. If you are a network administrator
+and want to block SE-VPN protocols on the firewall, you can adopt a
+"white-list" policy on the firewall to filter any TCP or UDP packets on the
+border except explicitly allowed packets towards specific web sites and
+servers.
+
+1.2. NAT Traversal Function
+Generally, if you use traditional VPN systems you have to request a network
+administrator to make the NAT or firewall to "open" or "relay" specific TCP or
+UDP ports. However, there are demands somehow to eliminate such working costs
+on network administrators. In order to satisfy such demands, SoftEther VPN has
+the newly-implemented "NAT Traversal" function. NAT Traversal is enabled by
+default. A SoftEther VPN Server running on the computer behind NAT or firewall
+can accept VPN connections from the Internet, without any special
+configurations on firewalls or NATs. If you want to disable the NAT Traversal
+function, modify the "DisableNatTraversal" to "true" on the configuration file
+of SoftEther VPN Server. In order to disable it on the client-side, append
+"/tcp" suffix on the destination hostname.
+
+1.3. Dynamic DNS Function
+Traditional legacy VPN system requires a static global IP address on the VPN
+server. In consideration of shortage of global IP addresses, SoftEther
+Corporation implements the "Dynamic DNS Function" on SoftEther VPN Server.
+Dynamic DNS is enabled by default. Dynamic DNS function notify the current
+global IP address of the PC to the Dynamic DNS Servers which are operated by
+SoftEther Corporation. A globally-unique hostname (FQDN) such as
+"abc.softether.net" ( "abc" varies as unique per a user) will be assigned on
+the VPN Server. If you tell this unique hostname to a VPN user, the user can
+specify it as the destination VPN Sever hostname on the VPN Client and will be
+able to connect the VPN Server. No IP addresses are required to know
+beforehand. If the IP address of the VPN Server varies, the registered IP
+address related to the hostname of Dynamic DNS service will be changed
+automatically. By this mechanism, no longer need a static global IP address
+which costs monthly to ISPs. You can use consumer-level inexpensive Internet
+connection with dynamic IP address in order to operate an enterprise-level VPN
+system. If you want to disable Dynamic DNS, specify "true" on the "Disabled"
+items of the "DDnsClient" directive on the SoftEther VPN Server configuration
+file. * Note for residents in People's Republic of China: If your VPN Server
+is running on the People's Republic of China, the DNS suffix will be replaced
+to "sedns.cn" domain. The "sedns.cn" domain is the service possessed and
+operated by "Beijing Daiyuu SoftEther Technology Co., Ltd" which is a
+Chinese-local enterprise.
+
+1.4. VPN over ICMP / VPN over DNS functions
+If you want to make a VPN connection between SoftEther VPN Client / Bridge and
+SoftEther VPN Server, but if TCP and UDP packets are prohibited by the
+firewall, then you can encapsulates payloads into "ICMP" (as known as Ping) or
+"DNS" packets. This function can realize a VPN connection by using ICMP or DNS
+even if the firewall or router blocks every TCP or UDP connections. VPN over
+ICMP / VPN over DNS functions are designed to comply standard ICMP and DNS
+specifications as possible, however it sometimes has a behavior not to fully
+comply them. Therefore, few poor-quality routers may be caused a
+memory-overflow or something troubles when a lot of ICMP or DNS packets are
+passed, and such routers sometimes freezes or reboots. It might affects other
+users on the same network. To avoid such risks, append the suffix "/tcp" on
+the destination hostname which is specified on the VPN-client side to disable
+VPN over ICMP / DNS functions.
+
+1.5. VPN Azure Cloud Service
+If your SoftEther VPN Server is placed behind the NAT or firwall, and by some
+reason you cannot use NAT Traversal function, Dynamic DNS function or VPN over
+ICMP/DNS function, you can use VPN Azure Clouse Service. SoftEther Corporation
+operates VPN Azure Cloud on Internet. After the VPN Server makes a connection
+to the VPN Azure Cloud, the hostname "abc.vpnazure.net" ( "abc" is a unique
+hostname) can be specified to connect to the VPN Server via the VPN Azure
+Cloud. Practically, such a hostname is pointing a global IP address of one of
+cloud servers which are operated by SoftEther Corporation. If A VPN Client
+connects to such a VPN Azure host, then the VPN Azure host will relay all
+traffics between the VPN Client and the VPN Server. VPN Azure is disabled by
+default. You can activate it easily by using VPN Server Configuration Tool.
+
+1.6. UDP Acceleration
+SoftEther VPN has the UDP Acceleration Function. If a VPN consists of two
+sites detects that UDP channel can be established, UDP will be automatically
+used. By this function, throughput of UDP increases. If direct UDP channel can
+be established, direct UDP packets will be used. However, if there is
+something obstacles such as firewalls or NATs, the "UDP Hole Punching"
+technology will be used, instead. The "UDP Hole Punching" uses the cloud
+servers which SoftEther Corporation operates on Internet. UDP Acceleration can
+be disabled anytime by setting up so on the VPN-client side.
+
+
+2. VPN Software
+2.1. SoftEther VPN Client
+If you use SoftEther VPN Client on Windows, the Virtual Network Adapter device
+driver will be installed on Windows. The Virtual Network Adapter is
+implemented as a kernel-mode driver for Windows. The driver is
+digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed
+by Symantec Corporation. A message to ask you want to sure install the driver
+might be popped up on the screen. SoftEther VPN Client may response the
+message if possible. SoftEther VPN Client also optimizes the configuration of
+MMCSS (Multimedia Class Scheduler Service) on Windows. You can undo the
+optimizations of MMCSS afterwards.
+
+2.2. SoftEther VPN Server / Bridge
+If you use SoftEther VPN Server / Bridge on Windows with "Local Bridge"
+functions, you have to install the low-level Ethernet packet processing driver
+on the computer. The driver is digitally-signed by a certificate issued by
+VeriSign, Inc. and also sub-signed by Symantec Corporation. SoftEther VPN
+Server / Bridge may disable the TCP/IP offloading features on the physical
+network adapter for Local Bridge function. In Windows Vista / 2008 or greater
+version, VPN Server may inject a packet-filter driver which complies Windows
+Filter Platform (WPF) specification into the kernel in order to provide IPsec
+function. The packet-filter driver will be loaded available only if IPsec
+function is enabled. Once you enables IPsec function of SoftEther VPN Server,
+the built-in IPsec function of Windows will be disabled. After you disabled
+IPsec function of SoftEther VPN Server, then the built-in IPsec function of
+Windows will revive. In order to provide the Local Bridge function, SoftEther
+VPN Server / Bridge disables the TCP/IP offloading function on the operating
+system.
+
+2.3. User-mode Installation
+You can install SoftEther VPN Server and SoftEther VPN Bridge as "User-mode"
+on Windows. In other words, even if you don't have Windows system
+administrator's privileges, you can install SoftEther VPN as a normal user.
+User-mode install will disable a few functions, however other most functions
+work well. Therefore, for example, an employee can install SoftEther VPN
+Server on the computer in the office network, and he will be able to connect
+to the server from his home. In order to realize such a system by user-self,
+no system administrative privileges are required in the view-point of
+technical. However, breaking rules of the company to install software on the
+computer without authority might be regarded as an unfavorable behavior. If
+you are an employee and belong to the company, and the company-policy
+prohibits installing software or making communications towards Internet
+without permission, you have to obtain a permission from the network
+administrator or the executive officer of your company in advance to install
+SoftEther VPN. If you install VPN Server / Bridge as User-mode, an icon will
+be appeared on the Windows task-tray. If you feel that the icon disturbs you,
+you can hide it by your operation. However, you must not exploit this hiding
+function to install VPN Server on other person's computer as a spyware. Such
+behavior might be an offence against the criminal law.
+
+2.4. Keep Alive Function
+SoftEther VPN Server and SoftEther VPN Bridge has Keep Alive Function by
+default. The purpose of this function is to sustain the Internet line active.
+The function transmits UDP packets with a random-byte-array-payload
+periodically. This function is useful to avoid automatic disconnection on
+mobile or dial-up connections. You can disable Keep Alive Function anytime.
+
+2.5. Uninstallation
+The uninstallation process of SoftEther VPN software will delete all program
+files. However, non-program files (such as files and data which are generated
+by running of programs) ) will not be deleted. For technical reason, the exe
+and resource files of uninstaller might remain. Such remaining files never
+affects to use the computer, however you can delete it manually. Kernel-mode
+drivers might not be deleted, however such drivers will not be loaded after
+the next boot of Windows. You can use "sc" command of Windows to delete
+kernel-mode drivers manually.
+
+2.6. Security
+You should set the administrator's password on SoftEther VPN Server / Bridge
+after installation. If you neglect to do it, another person can access to
+SoftEther VPN Server / Bridge and can set the password without your
+permission. This caution might be also applied on SoftEther VPN Client for
+Linux.
+
+2.7. Automatic Update Notification
+SoftEther VPN software for Windows has an automatic update notification
+function. It accesses to the SoftEther Update server periodically to check
+whether or not the latest version of software is released. If the latest
+version is released, the notification message will be popped up on the screen.
+In order to achieve this purpose, the version, language settings, the unique
+identifier, the IP address of your computer and the hostname of VPN Server
+which is connected to will be sent to the SoftEther Update server. No personal
+information will be sent. Automatic Update Notification is enabled by default,
+however you can disable it on the configuration screen. The setting whether
+turned on or turned off will be saved individually corresponding to each
+destination VPN server, by VPN Server Manager.
+
+2.8. Virtual NAT Function
+A Virtual Hub on SoftEther VPN Server / Bridge has "Virtual NAT Function" .
+Virtual NAT Function can share a single IP address on the physical network by
+multiple private IP address of VPN Clients. There are two operation mode of
+Virtual NAT: User-mode and Kernel-mode. In the user-mode operation, Virtual
+NAT shares an IP address which is assigned on the host operating system.
+Unlike user-mode, the kernel-mode operation attempts to find DHCP servers on
+the physical network. If there are two or more physical networks, a DHCP
+server will be sought automatically for each segments serially. If a DHCP
+server found, and an IP address is acquired, the IP address will be used by
+the Virtual NAT. In this case, an IP entry as a DHCP client will be registered
+on the IP pool of the physical DHCP Server. The physical default gateway and
+the DNS server will be used by the Virtual NAT in order to communicate with
+hosts in Internet. In kernel-mode operation, a Virtual Hub has a virtual MAC
+address which is operating on the physical Ethernet segment. In order to check
+the connectivity to Internet, SoftEther VPN periodically sends DNS query
+packet to resolve the IP address of host "www.yahoo.com" or "www.baidu.com" ,
+and attempts to connect to the TCP port 80 of such a resulted IP address for
+connectivity check.
+
+2.9. Unattended Installation of Kernel-mode Components
+When SoftEther VPN will detect a necessity to install the kernel-mode
+components on Windows, a confirmation message will be appeared by Windows
+system. In this occasion, SoftEther VPN software will switch to the Unattended
+Installation mode in order to respond "Yes" to Windows. This is a solution to
+prevent dead-locks when a remote-administration is performed from remote
+place.
+
+2.10. Windows Firewall
+SoftEther VPN software will register itself as a safe-program. Such an entry
+will be remain after the uninstallation. You can remove it manually from the
+Control Panel of Windows.
+
+
+3. Internet Services
+3.1. Internet Services which are provided by SoftEther Corporation
+SoftEther Corporation provides Dynamic DNS, NAT Traversal and VPN Azure server
+services on the Internet. These services are free of charge. Customers can
+access to the services by using SoftEther VPN software, via Internet. These
+service will be planned to be available from Open-Source version of "SoftEther
+VPN" which will be released in the future.
+
+3.2. Sent Information and Privacy Protection
+SoftEther VPN software may send an IP address, hostname, the version of VPN
+software on the customer's computer to the cloud service operated by SoftEther
+Corporation, in order to use the above services. These sending of information
+are minimal necessary to use the services. No personal information will be
+sent. SoftEther Corporation records log files of the cloud service servers for
+90 days at least with the received information. Such logs will be used for
+troubleshooting and other legitimate activities. SoftEther Corporation may
+provide logs to a public servant of Japanese government who are belonging to
+courts, police stations and the prosecutor's office, in order to comply such
+authorities' order. (Every Japanese public servants are liable by law to keep
+the information close.) Moreover, the IP addresses or other information will
+be processed statistically and provided to the public, not to expose the each
+concrete IP address, in order to release the release of research activities.
+
+3.3. Communication Data via VPN Azure Service
+Regardless of the above 3.2 rule, if the customer sends or receives VPN
+packets using VPN Azure Cloud Service, the actual payloads will stored and
+forwarded via the volatile memory of the servers for very short period. Such a
+behavior is naturally needed to provide the "VPN relay service" . No payloads
+will be recorded on "fixed" storages such as hard-drives. However, the
+"Wiretapping for Criminals Procedures Act" (The 137th legislation ruled on
+August 18, 1999 in Japan) requires telecommunication companies to allow the
+Japanese government authority to conduct a wire-tapping on the line. VPN Azure
+Servers which are physically placed on Japan are subjects of this law.
+
+3.4. Comply to Japanese Telecommunication Laws
+SoftEther Corporation complies with Japanese Telecommunication Laws as
+necessary to provide online services via Internet.
+
+3.5. Free and Academic Experiment Services
+SoftEther provides Dynamic DNS, NAT Traversal and VPN Azure as academic
+experiment services. Therefore, there services can be used for free of charge.
+These services are not parts of "SoftEther VPN Software Products" . These
+services are provided without any warranty. The services may be suspended or
+discontinued by technical or operational matters. In such occasions, users
+will not be able to use the services. A user have to understand such risks,
+and to acknowledge that such risks are borne by a user-self. SoftEther will
+never be liable to results or damages of use or unable-to-use of the service.
+Even if the user has already paid the license-fee of the commercial version of
+SoftEther VPN, such paid fees don't include any fees of these services.
+Therefore, if the online services will stop or be discontinued, no refunds or
+recoveries of damages will be provided by SoftEther Corporation.
+
+3.6. DNS Proxy Cloud Servers
+In some regions, when a user uses Internet, a DNS query sometimes broken or
+lost when it is passing through the ISP line. If SoftEther VPN Server, Client
+or Bridge detects a possibility that the accessing to the actual VPN server
+might be unstable, then DNS queries will be also transferred to the DNS proxy
+cloud servers which are operated by SoftEther Corporation. A DNS proxy cloud
+server will respond DNS queries with answering correct a IP address.
+
+
+4. General Cautions
+4.1. Needs an Approval from Network Administrator
+SoftEther VPN has powerful functions which don't require special settings by
+network administrators. For example, you need not to ask the administrator to
+configure the existing firewall in order to "open" a TCP/UDP port. Such
+characteristic features are for the purpose to eliminate working times and
+costs of network administrators, and avoid misconfiguration-risks around the
+tasks to open specific exception ports on the firewall. However, any employees
+belong to the company have to obtain an approval from the network
+administrator before installs SoftEther VPN. If your network administrator
+neglects to provide such an approval, you can consider to take an approval
+from an upper authority. (For example, executive officer of the company.) If
+you use SoftEther VPN without any approvals from the authority of your
+company, you might have disadvantage. SoftEther Corporation will be never
+liable for results or damages of using SoftEther VPN.
+
+4.2. Observe Laws of Your Country
+If your country's law prohibits the use of encryption, you have to disable the
+encryption function of SoftEther VPN by yourself. Similarly, in some countries
+or regions, some functions of SoftEther VPN might be prohibited to use by
+laws. Other countries' laws are none of SoftEther Corporation's concern
+because SoftEther Corporation is an enterprise which is located and registered
+in Japan physically. For example, there might be a risk that a part of
+SoftEther VPN conflicts an existing patent which is valid only on the specific
+region. SoftEther Corporation has no interests in such specific region outside
+Japan's territory. Therefore, if you want to use SoftEther VPN in regions
+outside Japan, you have to be careful not to violate third-person's rights.
+You have to verify the legitimacy of the use of SoftEther VPN in the specific
+region before you actually use it in such region. By nature, there are almost
+200 countries in the World, and each country's law is different each other. It
+is practically impossible to verify every countries' laws and regulations and
+make the software comply with all countries' laws in advance to release the
+software. Therefore SoftEther Corporation has verified the legitimacy of
+SoftEther VPN against the laws and regulations of only Japan. If a user uses
+SoftEther VPN in a specific country, and damaged by public servants of the
+government authority, SoftEther Corporation will never be liable to recover or
+compensate such damages or criminal responsibilities.
+
+
+5. VPN Gate Academic Experiment Project
+(This chapter applies only on SoftEther VPN software package which contains
+the extension plug-in for VPN Gate Academic Experiment Project.)
+5.1. About VPN Gate Academic Experiment Project
+VPN Gate Academic Experiment Project is an online service operated for just
+the academic research purpose at the graduate school of University of Tsukuba,
+Japan. The purpose of this research is to expend our knowledge about the
+"Global Distributed Public VPN Relay Server" (GDPVRS) technology. For details,
+please visit http://www.vpngate.net/.
+
+5.2. About VPN Gate Service
+SoftEther VPN Server and SoftEther VPN Client may contain "VPN Gate Service"
+program. However, VPN Gate Service is disabled by default.
+VPN Gate Service should be activated and enabled by the voluntary intention of
+the owner of the computer which SoftEther VPN Server or SoftEther VPN Client
+is installed on. After you activate VPN Gate Service, the computer will be
+start to serve as a part of the Global Distributed Public VPN Relay Servers.
+The IP address, hostname and related information of the computer will be sent
+and registered to the directory server of VPN Gate Academic Experiment
+Project, and they will be published and disclosed to the public. This
+mechanism will allow any VPN Gate Client software's user to connect to the VPN
+Gate Service running on your computer. While the VPN session between a VPN
+Gate Client and your VPN Gate Service is established, the VPN Gate Client's
+user can send/receive any IP packets towards the Internet via the VPN Gate
+Service. The global IP address of the VPN Gate Service's hosing computer will
+be used as the source IP address of such communications which a VPN Gate
+Client initiates.
+VPN Gate Service will send some information to the VPN Gate Academic
+Experiment Service Directory Server. The information includes the operator's
+information which described in section 5.5, logging settings, uptime,
+operating system version, type of protocol, port numbers, quality information,
+statistical information, VPN Gate clients' log history data (includes dates,
+IP addresses, version numbers and IDs) and the version of the software. These
+information will be exposed on the directory. VPN Gate Service also receives a
+key for encoding which is described on the chapter 5.9 from the directory
+server.
+
+5.3. Details of VPN Gate Service's Behavior
+If you enable VPN Gate Service manually, which is disabled by default, the
+"VPNGATE" Virtual Hub will be created on the SoftEther VPN Server. If you are
+using SoftEther VPN Client and attempt to active VPN Gate Service on it, an
+equivalent program to SoftEther VPN Server will be invoked on the same process
+of SoftEther VPN Client, and the "VPNGATE" Virtual Hub will be created. The
+"VPNGATE" Virtual Hub contains a user named "VPN" by default which permits
+anyone on the Internet to make a VPN connection to the Virtual Hub. Once a VPN
+Client connects to the "VPNGATE" Virtual Hub, any communication between the
+user and the Internet will pass through the Virtual Hub, and
+transmitted/received using the physical network interface on the computer
+which SoftEther VPN Server (or SoftEther VPN Client) is running on. This will
+cause the result that a destination host specified by the VPN Client will
+identify that the source of the communication has initiated from the VPN Gate
+Service's hosting computer's IP address. However, for safety, any packets
+which destinations are within 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0
+or 10.0.0.0/255.0.0.0 will be blocked by the "VPNGATE" Virtual Hub in order to
+protect your local network. Therefore, if you run VPN Gate Service on your
+corporate network or private network, it is safe because anonymous VPN Client
+users will not be permitted to access such private networks. VPN Gate Service
+also serves as relay for accessing to the VPN Gate Directory Server.
+In order to make VPN Gate Service familiar with firewalls and NATs, it opens
+an UDP port by using the NAT Traversal function which is described on the
+section 1.2. It also opens and listens on some TCP ports, and some TCP and UDP
+ports will be specified as the target port of Universal Plug and Play (UPnP)
+Port Transfer entries which are requested to your local routers. UPnP request
+packets will be sent periodically. Some routers keep such an opened TCP/UDP
+port permanently on the device. If you wish to close them, do it manually.
+VPN Gate Service also provides the mirror-site function for www.vpngate.net.
+This is a mechanism that a copy of the latest contents from www.vpngate.net
+will be hosted by the mirror-site tiny HTTP server which is running on the VPN
+Gate Service program. It will register itself on the mirror-sites list in
+www.vpngate.net. However, it never relays any other communications which are
+not towards www.vpngate.net.
+
+5.4. Communication between Internet via VPN Gate Service
+VPN Gate Service provides a routing between users and the Internet, by using
+the Virtual NAT Function which is described on the section 2.8. VPN Gate
+Service sends polling Ping packets to the server which is located on
+University of Tsukuba, and the Google Public DNS Server which is identified as
+8.8.8.8, in order to check the latest quality of your Internet line. VPN Gate
+Service also sends and receives a lot of random packets to/from the Speed Test
+Server on University of Tsukuba. These quality data will be reported to VPN
+Gate Directory Server, automatically and periodically. The result will be
+saved and disclosed to the public. These periodical polling communication are
+adjusted not to occupy the Internet line, however in some circumstances they
+might occupy the line.
+
+5.5. Operator's Information of VPN Gate Service
+If you activate VPN Gate Service on your computer, the computer will be a part
+of the Global Distributed Public VPN Relay Servers. Therefore, the Operator's
+administrative information of your VPN Gate Service should be reported and
+registered on the VPN Gate Service Directory. Operator's information contains
+the name of the operator and the abuse-reporting contact e-mail address. These
+information can be inputted on the screen if the VPN Gate configuration.
+Inputted information will be transmitted to the VPN Gate Directory Server,
+stored and disclosed to the public. So you have to be careful to input
+information. By the way, until you specify something as the operator's
+information, the computer's hostname will be used automatically as the field
+of the name of the operator, by appending the "'s owner" string after the
+hostname.
+
+5.6. Observe Laws to Operate VPN Gate Service
+In some countries or regions, a user who is planning to activate and operate
+VPN Gate Service, he are mandated to obtain a license or register a service
+from/to the government. If your region has such a regulation, you must fulfill
+mandated process before activating VPN Gate Service in advance. Neither the
+developers nor operators of the VPN Gate Academic Experiment Project will be
+liable for legal/criminal responsibilities or damages which are occurred from
+failure to comply your local laws.
+
+5.7. Protect Privacy of Communication
+Most of countries have a law which requires communication service's operators,
+including VPN Gate Service operators, to protect the privacy of communication
+of third-persons. When you operate VPN Gate Service, you must always protect
+user's privacy.
+
+5.8. Packet Logs
+The packet logging function is implemented on VPN Gate Service. It records
+essential headers of major TCP/IP packets which are transmitted via the
+Virtual Hub. This function will be helpful to investigate the "original IP
+address" of the initiator of communication who was a connected user of your
+VPN Gate Service, by checking the packet logs and the connection logs. The
+packet logs are recorded only for such legitimate investigates purpose. Do not
+peek nor leak packet logs except the rightful purpose. Such act will be
+violate the section 5.7.
+
+5.9. Packet Logs Automatic Archiving and Encoding Function
+The VPN Gate Academic Experiment Service is operated and running under the
+Japanese constitution and laws. The Japanese constitution laws demand strictly
+protection over the privacy of communication. Because this service is under
+Japanese rules, the program of VPN Gate Service implements this "Automatic Log
+File Encoding" protection mechanism, and enabled by default.
+The VPN Gate Service is currently configured to encode packet log files which
+has passed two or more weeks automatically, by default. In order to protect
+privacy of communication, if a packet log file is once encoded, even the
+administrator of the local computer cannot censor the packet log file. This
+mechanism protects privacy of end-users of VPN Gate Service.
+You can change the VPN Gate Service setting to disable this automatic encoding
+function. Then packet log files will never be encoded even after two weeks
+passed. In such a configuration, all packet logs will remain as plain-text on
+the disk. Therefore you have to take care not to violate user's privacy.
+If you are liable to decode an encoded packet log files (for example: a VPN
+Gate Service's user illegally abused your VPN Gate Service and you have to
+decode the packet logs in order to comply the laws), contact the administrator
+of the VPN Gate Academic Experiment Service at Graduate School of University
+of Tsukuba, Japan. You can find the contact address at
+http://www.vpngate.net/. The administrator of VPN Gate Service will respond to
+decode the packet logs if there is an appropriate and legal request from court
+or other judicial authorities, according to laws.
+
+5.10. Caution if You Operate VPN Gate Service in the Japan's Territories
+When a user operates VPN Gate Service in the Japan's territories, such an act
+may be regulated under the Japanese Telecommunication Laws if the operation is
+a subject to the law. However, in such a circumstance, according to the
+"Japanese Telecommunication Business Compete Manual [supplemental version]" ,
+non- profitable operations of communications are not identified as a
+"telecommunication business" . So usual operators of VPN Gate Service are not
+subjects to "telecommunication business operators" , and not be mandated to
+register to the government. Even so, legalities to protect the privacy of
+communication still imposed. As a conclusion, if you operate VPN Gate Service
+in the Japan's Territories, you must not leak the secrets of communications
+which are transmitted via your operating VPN Gate Service.
+
+5.11. VPN Gate Client
+If SoftEther VPN Client contains the VPN Gate Client plug-in, you can use it
+to obtain the list of current operating VPN Gate Service servers in the
+Internet, and make a VPN connection to a specific server on the list.
+VPN Gate Client always keeps the latest list of the VPN Gate Services
+periodically. Be careful if you are using a pay-per-use Internet line.
+When you start the VPN Gate Client software, the screen which asks you
+activate or not VPN Gate Service will be appeared. For details of VPN Gate
+Service, read the above sections.
+
+5.12. Caution before Joining or Exploiting VPN Gate Academic Experiment
+Project
+The VPN Gate Academic Experiment Service is operated as a research project at
+the graduate school on University of Tsukuba, Japan. The service is governed
+under the Japanese laws. Other countries' laws are none of our concerns nor
+responsibilities.
+By nature, there are almost 200 countries in the World, with different laws.
+It is impossible to verify every countries' laws and regulations and make the
+software comply with all countries' laws in advance to release the software.
+If a user uses VPN Gate service in a specific country, and damaged by public
+servants of the authority, the developer of either the service or software
+will never be liable to recover or compensate such damages or criminal
+responsibilities.
+By using this software and service, the user must observe all concerned laws
+and rules with user's own responsibility. The user will be completely liable
+to any damages and responsibilities which are results of using this software
+and service, regardless of either inside or outside of Japan's territory.
+If you don't agree nor understand the above warnings, do not use any of VPN
+Gate Academic Experiment Service functions.
+VPN Gate is a research project for just academic purpose only. VPN Gate was
+developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN
+Gate were developed on this research project at University of Tsukuba. Any
+parts of VPN Gate are not developed by SoftEther Corporation. The VPN Gate
+Research Project is not a subject to be led, operated, promoted nor guaranteed
+by SoftEther Corporation.
+
+
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 00000000..52c728da
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,2350 @@
+SoftEther VPN Server, Client and Bridge are free software, and released as
+open-source. You can redistribute them and/or modify them under the terms of
+the GNU General Public License version 2 as published by the Free Software
+Foundation.
+
+Copyright (c) 2012-2014 Daiyuu Nobori.
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+Copyright (c) 2012-2014 SoftEther Corporation.
+All Rights Reserved.
+http://www.softether.org/
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License version 2 as published by the Free
+Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License version 2
+along with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+Neither the name of SoftEther nor the names of its contributors may be used to
+endorse or promote products derived from this software without specific prior
+written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
+JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
+DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
+JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
+AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
+SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
+OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
+AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
+JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
+ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
+PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
+LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS SOFTWARE
+INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES PROHIBIT ENCRYPTED
+COMMUNICATIONS. USING THIS SOFTWARE IN OTHER COUNTRIES MIGHT BE RESTRICTED.
+
+THE FOLLOWING GPLV2 CONDITIONS APPLY ON ALL SOFTETHER VPN PROGRAMS WHICH ARE
+DEVELOPED BY SOFTETHER VPN PROJECT.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Lesser General Public License instead.) You can apply it
+to your programs, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and modification
+follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included
+without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running the Program
+is not restricted, and the output from the Program is covered only if its
+contents constitute a work based on the Program (independent of having been
+made by running the Program). Whether that is true depends on what the Program
+does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole
+or in part contains or is derived from the Program or any part thereof, to be
+licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+ c) If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the most
+ordinary way, to print or display an announcement including an appropriate
+copyright notice and a notice that there is no warranty (or else, saying that
+you provide a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this License.
+(Exception: if the Program itself is interactive but does not normally print
+such an announcement, your work based on the Program is not required to print
+an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with
+the Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections 1 and
+2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only for
+noncommercial distribution and only if you received the program in object code
+or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the executable. However, as a special exception, the source
+code distributed need not include anything that is normally distributed (in
+either source or binary form) with the major components (compiler, kernel, and
+so on) of the operating system on which the executable runs, unless that
+component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to
+copy from a designated place, then offering equivalent access to copy the
+source code from the same place counts as distribution of the source code,
+even though third parties are not compelled to copy the source along with the
+object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the
+Program (or any work based on the Program), you indicate your acceptance of
+this License to do so, and all its terms and conditions for copying,
+distributing or modifying the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of this License,
+you may choose any version ever published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+Note that the above copyright notices and use conditions do not apply on the
+software components listed in below which are included in this Software. When
+you use or distribute Software with including these libraries, you have to
+follow the conditions of these libraries.
+
+These library's copyright notices and conditions are following;
+
+-------------------
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES
+
+SoftEther provides source codes of some GPL/LGPL/other libraries listed above
+on its web server. Anyone can download, use and re-distribute them under
+individual licenses which are contained on each archive file, available from
+the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES WRITTEN BY SOFTETHER CORPORATION
+
+Note for users of non-Windows version of PacketiX VPN: The enumerated bundle
+of License Agreements above are copies of original License Agreements of each
+library programs which PacketiX VPN uses. PacketiX VPN is not a delivered work
+from these libraries. PacketiX VPN is a separated work from the libraries, but
+it may call functions of the libraries (whether or not PacketiX VPN calls such
+functions are depended on the user's intention to link them or not on user's
+side computer). While some libraries indicate GPL or LGPL as a condition to
+re-distribute, PacketiX VPN is not license under GPL nor LGPL. Therefore, we
+took special care not to make PacketiX VPN become delivered works of any GPL
+or LGPL libraries. In order to achieve that, both PacketiX VPN and GPL/LGPL
+libraries are distributed with isolated forms (means that any program files of
+PacketiX VPN are not bound nor linked to any GPL/LGPL libraries). If a user of
+PacketiX VPN wants to link GPL/LGPL libraries by their own decisions,
+operations and responsibilities, he may do that on his computer. However, if a
+delivered work under copyright law is created as a result of such an
+operation, such a delivered work must not re-distributed to other people,
+because it may violate GPL/LGPL libraries' conditions.
+
+Note for users of Windows version of PacketiX VPN: For technical reason, the
+above texts are exactly same as a file which is also contained on the
+non-Windows version of PacketiX VPN. Actually, the Windows version of PacketiX
+VPN has no relations to any GPL/LGPL libraries enumerated above.
+
+SoftEther Corporation provides source codes of some GPL/LGPL/other libraries
+listed above on its web server. Anyone can download, use and re-distribute
+them under individual licenses which are contained on each archive file,
+available from the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+THE IMPORTANT NOTICES ABOUT SOFTETHER VPN
+
+FUNCTIONS OF VPN COMMUNICATIONS EMBEDDED ON THIS SOFTWARE ARE VERY POWERFUL
+THAN EVER. THIS STRONG VPN ABILITY WILL BRING YOU HUGE BENEFITS. HOWEVER, IF
+YOU MISUSE THIS SOFTWARE, IT MIGHT DAMAGES YOURSELF. IN ORDER TO AVOID SUCH
+RISKS, THIS DOCUMENT ACCOUNTS IMPORTANT NOTICES FOR CUSTOMERS WHO ARE WILLING
+TO USE THIS SOFTWARE. THE FOLLOWING INSTRUCTIONS ARE VERY IMPORTANT. READ AND
+UNDERSTAND IT CAREFULLY. ADDITIONALLY, IF YOU ARE PLANNING TO USE THE DYNAMIC
+DNS, THE NAT TRAVERSAL OR THE VPN AZURE FUNCTIONS, READ THE SECTION 3.5
+CAREFULLY. THESE FUNCTIONS ARE FREE SERVICES PROVIDED VIA THE INTERNET, ARE
+NOT GUARANTEED, AND ARE NOT INTENDED TO BE USED FOR BUSINESS OR COMMERCIAL
+USE. DO NOT USE THESE SERVICES FOR YOUR BUSINESS OR COMMERCIAL USE.
+
+
+1. VPN Communication Protocols
+1.1. SoftEther VPN Protocol
+SoftEther VPN can perform VPN communication. Unlike traditional VPN protocols,
+SoftEther VPN has an implementation of the newly-designed "SoftEther VPN
+Protocol (SE-VPN Protocol)" . SE-VPN protocol encapsulates any Ethernet
+packets into a HTTPS (HTTP over SSL) connection. Therefore SE-VPN protocol can
+communicate beyond firewalls even if the firewall is configured to block
+traditional VPN packets by network administrator. SE-VPN protocol is designed
+and implemented to comply TLS 1.0 (RFC 5246) and HTTPS (RFC 2818). However, it
+sometimes have different behavior to RFCs. If you are a network administrator
+and want to block SE-VPN protocols on the firewall, you can adopt a
+"white-list" policy on the firewall to filter any TCP or UDP packets on the
+border except explicitly allowed packets towards specific web sites and
+servers.
+
+1.2. NAT Traversal Function
+Generally, if you use traditional VPN systems you have to request a network
+administrator to make the NAT or firewall to "open" or "relay" specific TCP or
+UDP ports. However, there are demands somehow to eliminate such working costs
+on network administrators. In order to satisfy such demands, SoftEther VPN has
+the newly-implemented "NAT Traversal" function. NAT Traversal is enabled by
+default. A SoftEther VPN Server running on the computer behind NAT or firewall
+can accept VPN connections from the Internet, without any special
+configurations on firewalls or NATs. If you want to disable the NAT Traversal
+function, modify the "DisableNatTraversal" to "true" on the configuration file
+of SoftEther VPN Server. In order to disable it on the client-side, append
+"/tcp" suffix on the destination hostname.
+
+1.3. Dynamic DNS Function
+Traditional legacy VPN system requires a static global IP address on the VPN
+server. In consideration of shortage of global IP addresses, SoftEther
+Corporation implements the "Dynamic DNS Function" on SoftEther VPN Server.
+Dynamic DNS is enabled by default. Dynamic DNS function notify the current
+global IP address of the PC to the Dynamic DNS Servers which are operated by
+SoftEther Corporation. A globally-unique hostname (FQDN) such as
+"abc.softether.net" ( "abc" varies as unique per a user) will be assigned on
+the VPN Server. If you tell this unique hostname to a VPN user, the user can
+specify it as the destination VPN Sever hostname on the VPN Client and will be
+able to connect the VPN Server. No IP addresses are required to know
+beforehand. If the IP address of the VPN Server varies, the registered IP
+address related to the hostname of Dynamic DNS service will be changed
+automatically. By this mechanism, no longer need a static global IP address
+which costs monthly to ISPs. You can use consumer-level inexpensive Internet
+connection with dynamic IP address in order to operate an enterprise-level VPN
+system. If you want to disable Dynamic DNS, specify "true" on the "Disabled"
+items of the "DDnsClient" directive on the SoftEther VPN Server configuration
+file. * Note for residents in People's Republic of China: If your VPN Server
+is running on the People's Republic of China, the DNS suffix will be replaced
+to "sedns.cn" domain. The "sedns.cn" domain is the service possessed and
+operated by "Beijing Daiyuu SoftEther Technology Co., Ltd" which is a
+Chinese-local enterprise.
+
+1.4. VPN over ICMP / VPN over DNS functions
+If you want to make a VPN connection between SoftEther VPN Client / Bridge and
+SoftEther VPN Server, but if TCP and UDP packets are prohibited by the
+firewall, then you can encapsulates payloads into "ICMP" (as known as Ping) or
+"DNS" packets. This function can realize a VPN connection by using ICMP or DNS
+even if the firewall or router blocks every TCP or UDP connections. VPN over
+ICMP / VPN over DNS functions are designed to comply standard ICMP and DNS
+specifications as possible, however it sometimes has a behavior not to fully
+comply them. Therefore, few poor-quality routers may be caused a
+memory-overflow or something troubles when a lot of ICMP or DNS packets are
+passed, and such routers sometimes freezes or reboots. It might affects other
+users on the same network. To avoid such risks, append the suffix "/tcp" on
+the destination hostname which is specified on the VPN-client side to disable
+VPN over ICMP / DNS functions.
+
+1.5. VPN Azure Cloud Service
+If your SoftEther VPN Server is placed behind the NAT or firwall, and by some
+reason you cannot use NAT Traversal function, Dynamic DNS function or VPN over
+ICMP/DNS function, you can use VPN Azure Clouse Service. SoftEther Corporation
+operates VPN Azure Cloud on Internet. After the VPN Server makes a connection
+to the VPN Azure Cloud, the hostname "abc.vpnazure.net" ( "abc" is a unique
+hostname) can be specified to connect to the VPN Server via the VPN Azure
+Cloud. Practically, such a hostname is pointing a global IP address of one of
+cloud servers which are operated by SoftEther Corporation. If A VPN Client
+connects to such a VPN Azure host, then the VPN Azure host will relay all
+traffics between the VPN Client and the VPN Server. VPN Azure is disabled by
+default. You can activate it easily by using VPN Server Configuration Tool.
+
+1.6. UDP Acceleration
+SoftEther VPN has the UDP Acceleration Function. If a VPN consists of two
+sites detects that UDP channel can be established, UDP will be automatically
+used. By this function, throughput of UDP increases. If direct UDP channel can
+be established, direct UDP packets will be used. However, if there is
+something obstacles such as firewalls or NATs, the "UDP Hole Punching"
+technology will be used, instead. The "UDP Hole Punching" uses the cloud
+servers which SoftEther Corporation operates on Internet. UDP Acceleration can
+be disabled anytime by setting up so on the VPN-client side.
+
+
+2. VPN Software
+2.1. SoftEther VPN Client
+If you use SoftEther VPN Client on Windows, the Virtual Network Adapter device
+driver will be installed on Windows. The Virtual Network Adapter is
+implemented as a kernel-mode driver for Windows. The driver is
+digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed
+by Symantec Corporation. A message to ask you want to sure install the driver
+might be popped up on the screen. SoftEther VPN Client may response the
+message if possible. SoftEther VPN Client also optimizes the configuration of
+MMCSS (Multimedia Class Scheduler Service) on Windows. You can undo the
+optimizations of MMCSS afterwards.
+
+2.2. SoftEther VPN Server / Bridge
+If you use SoftEther VPN Server / Bridge on Windows with "Local Bridge"
+functions, you have to install the low-level Ethernet packet processing driver
+on the computer. The driver is digitally-signed by a certificate issued by
+VeriSign, Inc. and also sub-signed by Symantec Corporation. SoftEther VPN
+Server / Bridge may disable the TCP/IP offloading features on the physical
+network adapter for Local Bridge function. In Windows Vista / 2008 or greater
+version, VPN Server may inject a packet-filter driver which complies Windows
+Filter Platform (WPF) specification into the kernel in order to provide IPsec
+function. The packet-filter driver will be loaded available only if IPsec
+function is enabled. Once you enables IPsec function of SoftEther VPN Server,
+the built-in IPsec function of Windows will be disabled. After you disabled
+IPsec function of SoftEther VPN Server, then the built-in IPsec function of
+Windows will revive. In order to provide the Local Bridge function, SoftEther
+VPN Server / Bridge disables the TCP/IP offloading function on the operating
+system.
+
+2.3. User-mode Installation
+You can install SoftEther VPN Server and SoftEther VPN Bridge as "User-mode"
+on Windows. In other words, even if you don't have Windows system
+administrator's privileges, you can install SoftEther VPN as a normal user.
+User-mode install will disable a few functions, however other most functions
+work well. Therefore, for example, an employee can install SoftEther VPN
+Server on the computer in the office network, and he will be able to connect
+to the server from his home. In order to realize such a system by user-self,
+no system administrative privileges are required in the view-point of
+technical. However, breaking rules of the company to install software on the
+computer without authority might be regarded as an unfavorable behavior. If
+you are an employee and belong to the company, and the company-policy
+prohibits installing software or making communications towards Internet
+without permission, you have to obtain a permission from the network
+administrator or the executive officer of your company in advance to install
+SoftEther VPN. If you install VPN Server / Bridge as User-mode, an icon will
+be appeared on the Windows task-tray. If you feel that the icon disturbs you,
+you can hide it by your operation. However, you must not exploit this hiding
+function to install VPN Server on other person's computer as a spyware. Such
+behavior might be an offence against the criminal law.
+
+2.4. Keep Alive Function
+SoftEther VPN Server and SoftEther VPN Bridge has Keep Alive Function by
+default. The purpose of this function is to sustain the Internet line active.
+The function transmits UDP packets with a random-byte-array-payload
+periodically. This function is useful to avoid automatic disconnection on
+mobile or dial-up connections. You can disable Keep Alive Function anytime.
+
+2.5. Uninstallation
+The uninstallation process of SoftEther VPN software will delete all program
+files. However, non-program files (such as files and data which are generated
+by running of programs) ) will not be deleted. For technical reason, the exe
+and resource files of uninstaller might remain. Such remaining files never
+affects to use the computer, however you can delete it manually. Kernel-mode
+drivers might not be deleted, however such drivers will not be loaded after
+the next boot of Windows. You can use "sc" command of Windows to delete
+kernel-mode drivers manually.
+
+2.6. Security
+You should set the administrator's password on SoftEther VPN Server / Bridge
+after installation. If you neglect to do it, another person can access to
+SoftEther VPN Server / Bridge and can set the password without your
+permission. This caution might be also applied on SoftEther VPN Client for
+Linux.
+
+2.7. Automatic Update Notification
+SoftEther VPN software for Windows has an automatic update notification
+function. It accesses to the SoftEther Update server periodically to check
+whether or not the latest version of software is released. If the latest
+version is released, the notification message will be popped up on the screen.
+In order to achieve this purpose, the version, language settings, the unique
+identifier, the IP address of your computer and the hostname of VPN Server
+which is connected to will be sent to the SoftEther Update server. No personal
+information will be sent. Automatic Update Notification is enabled by default,
+however you can disable it on the configuration screen. The setting whether
+turned on or turned off will be saved individually corresponding to each
+destination VPN server, by VPN Server Manager.
+
+2.8. Virtual NAT Function
+A Virtual Hub on SoftEther VPN Server / Bridge has "Virtual NAT Function" .
+Virtual NAT Function can share a single IP address on the physical network by
+multiple private IP address of VPN Clients. There are two operation mode of
+Virtual NAT: User-mode and Kernel-mode. In the user-mode operation, Virtual
+NAT shares an IP address which is assigned on the host operating system.
+Unlike user-mode, the kernel-mode operation attempts to find DHCP servers on
+the physical network. If there are two or more physical networks, a DHCP
+server will be sought automatically for each segments serially. If a DHCP
+server found, and an IP address is acquired, the IP address will be used by
+the Virtual NAT. In this case, an IP entry as a DHCP client will be registered
+on the IP pool of the physical DHCP Server. The physical default gateway and
+the DNS server will be used by the Virtual NAT in order to communicate with
+hosts in Internet. In kernel-mode operation, a Virtual Hub has a virtual MAC
+address which is operating on the physical Ethernet segment. In order to check
+the connectivity to Internet, SoftEther VPN periodically sends DNS query
+packet to resolve the IP address of host "www.yahoo.com" or "www.baidu.com" ,
+and attempts to connect to the TCP port 80 of such a resulted IP address for
+connectivity check.
+
+2.9. Unattended Installation of Kernel-mode Components
+When SoftEther VPN will detect a necessity to install the kernel-mode
+components on Windows, a confirmation message will be appeared by Windows
+system. In this occasion, SoftEther VPN software will switch to the Unattended
+Installation mode in order to respond "Yes" to Windows. This is a solution to
+prevent dead-locks when a remote-administration is performed from remote
+place.
+
+2.10. Windows Firewall
+SoftEther VPN software will register itself as a safe-program. Such an entry
+will be remain after the uninstallation. You can remove it manually from the
+Control Panel of Windows.
+
+
+3. Internet Services
+3.1. Internet Services which are provided by SoftEther Corporation
+SoftEther Corporation provides Dynamic DNS, NAT Traversal and VPN Azure server
+services on the Internet. These services are free of charge. Customers can
+access to the services by using SoftEther VPN software, via Internet. These
+service will be planned to be available from Open-Source version of "SoftEther
+VPN" which will be released in the future.
+
+3.2. Sent Information and Privacy Protection
+SoftEther VPN software may send an IP address, hostname, the version of VPN
+software on the customer's computer to the cloud service operated by SoftEther
+Corporation, in order to use the above services. These sending of information
+are minimal necessary to use the services. No personal information will be
+sent. SoftEther Corporation records log files of the cloud service servers for
+90 days at least with the received information. Such logs will be used for
+troubleshooting and other legitimate activities. SoftEther Corporation may
+provide logs to a public servant of Japanese government who are belonging to
+courts, police stations and the prosecutor's office, in order to comply such
+authorities' order. (Every Japanese public servants are liable by law to keep
+the information close.) Moreover, the IP addresses or other information will
+be processed statistically and provided to the public, not to expose the each
+concrete IP address, in order to release the release of research activities.
+
+3.3. Communication Data via VPN Azure Service
+Regardless of the above 3.2 rule, if the customer sends or receives VPN
+packets using VPN Azure Cloud Service, the actual payloads will stored and
+forwarded via the volatile memory of the servers for very short period. Such a
+behavior is naturally needed to provide the "VPN relay service" . No payloads
+will be recorded on "fixed" storages such as hard-drives. However, the
+"Wiretapping for Criminals Procedures Act" (The 137th legislation ruled on
+August 18, 1999 in Japan) requires telecommunication companies to allow the
+Japanese government authority to conduct a wire-tapping on the line. VPN Azure
+Servers which are physically placed on Japan are subjects of this law.
+
+3.4. Comply to Japanese Telecommunication Laws
+SoftEther Corporation complies with Japanese Telecommunication Laws as
+necessary to provide online services via Internet.
+
+3.5. Free and Academic Experiment Services
+SoftEther provides Dynamic DNS, NAT Traversal and VPN Azure as academic
+experiment services. Therefore, there services can be used for free of charge.
+These services are not parts of "SoftEther VPN Software Products" . These
+services are provided without any warranty. The services may be suspended or
+discontinued by technical or operational matters. In such occasions, users
+will not be able to use the services. A user have to understand such risks,
+and to acknowledge that such risks are borne by a user-self. SoftEther will
+never be liable to results or damages of use or unable-to-use of the service.
+Even if the user has already paid the license-fee of the commercial version of
+SoftEther VPN, such paid fees don't include any fees of these services.
+Therefore, if the online services will stop or be discontinued, no refunds or
+recoveries of damages will be provided by SoftEther Corporation.
+
+3.6. DNS Proxy Cloud Servers
+In some regions, when a user uses Internet, a DNS query sometimes broken or
+lost when it is passing through the ISP line. If SoftEther VPN Server, Client
+or Bridge detects a possibility that the accessing to the actual VPN server
+might be unstable, then DNS queries will be also transferred to the DNS proxy
+cloud servers which are operated by SoftEther Corporation. A DNS proxy cloud
+server will respond DNS queries with answering correct a IP address.
+
+
+4. General Cautions
+4.1. Needs an Approval from Network Administrator
+SoftEther VPN has powerful functions which don't require special settings by
+network administrators. For example, you need not to ask the administrator to
+configure the existing firewall in order to "open" a TCP/UDP port. Such
+characteristic features are for the purpose to eliminate working times and
+costs of network administrators, and avoid misconfiguration-risks around the
+tasks to open specific exception ports on the firewall. However, any employees
+belong to the company have to obtain an approval from the network
+administrator before installs SoftEther VPN. If your network administrator
+neglects to provide such an approval, you can consider to take an approval
+from an upper authority. (For example, executive officer of the company.) If
+you use SoftEther VPN without any approvals from the authority of your
+company, you might have disadvantage. SoftEther Corporation will be never
+liable for results or damages of using SoftEther VPN.
+
+4.2. Observe Laws of Your Country
+If your country's law prohibits the use of encryption, you have to disable the
+encryption function of SoftEther VPN by yourself. Similarly, in some countries
+or regions, some functions of SoftEther VPN might be prohibited to use by
+laws. Other countries' laws are none of SoftEther Corporation's concern
+because SoftEther Corporation is an enterprise which is located and registered
+in Japan physically. For example, there might be a risk that a part of
+SoftEther VPN conflicts an existing patent which is valid only on the specific
+region. SoftEther Corporation has no interests in such specific region outside
+Japan's territory. Therefore, if you want to use SoftEther VPN in regions
+outside Japan, you have to be careful not to violate third-person's rights.
+You have to verify the legitimacy of the use of SoftEther VPN in the specific
+region before you actually use it in such region. By nature, there are almost
+200 countries in the World, and each country's law is different each other. It
+is practically impossible to verify every countries' laws and regulations and
+make the software comply with all countries' laws in advance to release the
+software. Therefore SoftEther Corporation has verified the legitimacy of
+SoftEther VPN against the laws and regulations of only Japan. If a user uses
+SoftEther VPN in a specific country, and damaged by public servants of the
+government authority, SoftEther Corporation will never be liable to recover or
+compensate such damages or criminal responsibilities.
+
+
+5. VPN Gate Academic Experiment Project
+(This chapter applies only on SoftEther VPN software package which contains
+the extension plug-in for VPN Gate Academic Experiment Project.)
+5.1. About VPN Gate Academic Experiment Project
+VPN Gate Academic Experiment Project is an online service operated for just
+the academic research purpose at the graduate school of University of Tsukuba,
+Japan. The purpose of this research is to expend our knowledge about the
+"Global Distributed Public VPN Relay Server" (GDPVRS) technology. For details,
+please visit http://www.vpngate.net/.
+
+5.2. About VPN Gate Service
+SoftEther VPN Server and SoftEther VPN Client may contain "VPN Gate Service"
+program. However, VPN Gate Service is disabled by default.
+VPN Gate Service should be activated and enabled by the voluntary intention of
+the owner of the computer which SoftEther VPN Server or SoftEther VPN Client
+is installed on. After you activate VPN Gate Service, the computer will be
+start to serve as a part of the Global Distributed Public VPN Relay Servers.
+The IP address, hostname and related information of the computer will be sent
+and registered to the directory server of VPN Gate Academic Experiment
+Project, and they will be published and disclosed to the public. This
+mechanism will allow any VPN Gate Client software's user to connect to the VPN
+Gate Service running on your computer. While the VPN session between a VPN
+Gate Client and your VPN Gate Service is established, the VPN Gate Client's
+user can send/receive any IP packets towards the Internet via the VPN Gate
+Service. The global IP address of the VPN Gate Service's hosing computer will
+be used as the source IP address of such communications which a VPN Gate
+Client initiates.
+VPN Gate Service will send some information to the VPN Gate Academic
+Experiment Service Directory Server. The information includes the operator's
+information which described in section 5.5, logging settings, uptime,
+operating system version, type of protocol, port numbers, quality information,
+statistical information, VPN Gate clients' log history data (includes dates,
+IP addresses, version numbers and IDs) and the version of the software. These
+information will be exposed on the directory. VPN Gate Service also receives a
+key for encoding which is described on the chapter 5.9 from the directory
+server.
+
+5.3. Details of VPN Gate Service's Behavior
+If you enable VPN Gate Service manually, which is disabled by default, the
+"VPNGATE" Virtual Hub will be created on the SoftEther VPN Server. If you are
+using SoftEther VPN Client and attempt to active VPN Gate Service on it, an
+equivalent program to SoftEther VPN Server will be invoked on the same process
+of SoftEther VPN Client, and the "VPNGATE" Virtual Hub will be created. The
+"VPNGATE" Virtual Hub contains a user named "VPN" by default which permits
+anyone on the Internet to make a VPN connection to the Virtual Hub. Once a VPN
+Client connects to the "VPNGATE" Virtual Hub, any communication between the
+user and the Internet will pass through the Virtual Hub, and
+transmitted/received using the physical network interface on the computer
+which SoftEther VPN Server (or SoftEther VPN Client) is running on. This will
+cause the result that a destination host specified by the VPN Client will
+identify that the source of the communication has initiated from the VPN Gate
+Service's hosting computer's IP address. However, for safety, any packets
+which destinations are within 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0
+or 10.0.0.0/255.0.0.0 will be blocked by the "VPNGATE" Virtual Hub in order to
+protect your local network. Therefore, if you run VPN Gate Service on your
+corporate network or private network, it is safe because anonymous VPN Client
+users will not be permitted to access such private networks. VPN Gate Service
+also serves as relay for accessing to the VPN Gate Directory Server.
+In order to make VPN Gate Service familiar with firewalls and NATs, it opens
+an UDP port by using the NAT Traversal function which is described on the
+section 1.2. It also opens and listens on some TCP ports, and some TCP and UDP
+ports will be specified as the target port of Universal Plug and Play (UPnP)
+Port Transfer entries which are requested to your local routers. UPnP request
+packets will be sent periodically. Some routers keep such an opened TCP/UDP
+port permanently on the device. If you wish to close them, do it manually.
+VPN Gate Service also provides the mirror-site function for www.vpngate.net.
+This is a mechanism that a copy of the latest contents from www.vpngate.net
+will be hosted by the mirror-site tiny HTTP server which is running on the VPN
+Gate Service program. It will register itself on the mirror-sites list in
+www.vpngate.net. However, it never relays any other communications which are
+not towards www.vpngate.net.
+
+5.4. Communication between Internet via VPN Gate Service
+VPN Gate Service provides a routing between users and the Internet, by using
+the Virtual NAT Function which is described on the section 2.8. VPN Gate
+Service sends polling Ping packets to the server which is located on
+University of Tsukuba, and the Google Public DNS Server which is identified as
+8.8.8.8, in order to check the latest quality of your Internet line. VPN Gate
+Service also sends and receives a lot of random packets to/from the Speed Test
+Server on University of Tsukuba. These quality data will be reported to VPN
+Gate Directory Server, automatically and periodically. The result will be
+saved and disclosed to the public. These periodical polling communication are
+adjusted not to occupy the Internet line, however in some circumstances they
+might occupy the line.
+
+5.5. Operator's Information of VPN Gate Service
+If you activate VPN Gate Service on your computer, the computer will be a part
+of the Global Distributed Public VPN Relay Servers. Therefore, the Operator's
+administrative information of your VPN Gate Service should be reported and
+registered on the VPN Gate Service Directory. Operator's information contains
+the name of the operator and the abuse-reporting contact e-mail address. These
+information can be inputted on the screen if the VPN Gate configuration.
+Inputted information will be transmitted to the VPN Gate Directory Server,
+stored and disclosed to the public. So you have to be careful to input
+information. By the way, until you specify something as the operator's
+information, the computer's hostname will be used automatically as the field
+of the name of the operator, by appending the "'s owner" string after the
+hostname.
+
+5.6. Observe Laws to Operate VPN Gate Service
+In some countries or regions, a user who is planning to activate and operate
+VPN Gate Service, he are mandated to obtain a license or register a service
+from/to the government. If your region has such a regulation, you must fulfill
+mandated process before activating VPN Gate Service in advance. Neither the
+developers nor operators of the VPN Gate Academic Experiment Project will be
+liable for legal/criminal responsibilities or damages which are occurred from
+failure to comply your local laws.
+
+5.7. Protect Privacy of Communication
+Most of countries have a law which requires communication service's operators,
+including VPN Gate Service operators, to protect the privacy of communication
+of third-persons. When you operate VPN Gate Service, you must always protect
+user's privacy.
+
+5.8. Packet Logs
+The packet logging function is implemented on VPN Gate Service. It records
+essential headers of major TCP/IP packets which are transmitted via the
+Virtual Hub. This function will be helpful to investigate the "original IP
+address" of the initiator of communication who was a connected user of your
+VPN Gate Service, by checking the packet logs and the connection logs. The
+packet logs are recorded only for such legitimate investigates purpose. Do not
+peek nor leak packet logs except the rightful purpose. Such act will be
+violate the section 5.7.
+
+5.9. Packet Logs Automatic Archiving and Encoding Function
+The VPN Gate Academic Experiment Service is operated and running under the
+Japanese constitution and laws. The Japanese constitution laws demand strictly
+protection over the privacy of communication. Because this service is under
+Japanese rules, the program of VPN Gate Service implements this "Automatic Log
+File Encoding" protection mechanism, and enabled by default.
+The VPN Gate Service is currently configured to encode packet log files which
+has passed two or more weeks automatically, by default. In order to protect
+privacy of communication, if a packet log file is once encoded, even the
+administrator of the local computer cannot censor the packet log file. This
+mechanism protects privacy of end-users of VPN Gate Service.
+You can change the VPN Gate Service setting to disable this automatic encoding
+function. Then packet log files will never be encoded even after two weeks
+passed. In such a configuration, all packet logs will remain as plain-text on
+the disk. Therefore you have to take care not to violate user's privacy.
+If you are liable to decode an encoded packet log files (for example: a VPN
+Gate Service's user illegally abused your VPN Gate Service and you have to
+decode the packet logs in order to comply the laws), contact the administrator
+of the VPN Gate Academic Experiment Service at Graduate School of University
+of Tsukuba, Japan. You can find the contact address at
+http://www.vpngate.net/. The administrator of VPN Gate Service will respond to
+decode the packet logs if there is an appropriate and legal request from court
+or other judicial authorities, according to laws.
+
+5.10. Caution if You Operate VPN Gate Service in the Japan's Territories
+When a user operates VPN Gate Service in the Japan's territories, such an act
+may be regulated under the Japanese Telecommunication Laws if the operation is
+a subject to the law. However, in such a circumstance, according to the
+"Japanese Telecommunication Business Compete Manual [supplemental version]" ,
+non- profitable operations of communications are not identified as a
+"telecommunication business" . So usual operators of VPN Gate Service are not
+subjects to "telecommunication business operators" , and not be mandated to
+register to the government. Even so, legalities to protect the privacy of
+communication still imposed. As a conclusion, if you operate VPN Gate Service
+in the Japan's Territories, you must not leak the secrets of communications
+which are transmitted via your operating VPN Gate Service.
+
+5.11. VPN Gate Client
+If SoftEther VPN Client contains the VPN Gate Client plug-in, you can use it
+to obtain the list of current operating VPN Gate Service servers in the
+Internet, and make a VPN connection to a specific server on the list.
+VPN Gate Client always keeps the latest list of the VPN Gate Services
+periodically. Be careful if you are using a pay-per-use Internet line.
+When you start the VPN Gate Client software, the screen which asks you
+activate or not VPN Gate Service will be appeared. For details of VPN Gate
+Service, read the above sections.
+
+5.12. Caution before Joining or Exploiting VPN Gate Academic Experiment
+Project
+The VPN Gate Academic Experiment Service is operated as a research project at
+the graduate school on University of Tsukuba, Japan. The service is governed
+under the Japanese laws. Other countries' laws are none of our concerns nor
+responsibilities.
+By nature, there are almost 200 countries in the World, with different laws.
+It is impossible to verify every countries' laws and regulations and make the
+software comply with all countries' laws in advance to release the software.
+If a user uses VPN Gate service in a specific country, and damaged by public
+servants of the authority, the developer of either the service or software
+will never be liable to recover or compensate such damages or criminal
+responsibilities.
+By using this software and service, the user must observe all concerned laws
+and rules with user's own responsibility. The user will be completely liable
+to any damages and responsibilities which are results of using this software
+and service, regardless of either inside or outside of Japan's territory.
+If you don't agree nor understand the above warnings, do not use any of VPN
+Gate Academic Experiment Service functions.
+VPN Gate is a research project for just academic purpose only. VPN Gate was
+developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN
+Gate were developed on this research project at University of Tsukuba. Any
+parts of VPN Gate are not developed by SoftEther Corporation. The VPN Gate
+Research Project is not a subject to be led, operated, promoted nor guaranteed
+by SoftEther Corporation.
+
+
diff --git a/README b/README
new file mode 100644
index 00000000..df623ce6
--- /dev/null
+++ b/README
@@ -0,0 +1,189 @@
+SoftEther VPN - An Open-Source Cross-platform Multi-protocol VPN Program
+http://www.softether.org/
+
+We use GitHub as the primary official SoftEther VPN repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+Source code packages (.zip and .tar.gz) and binary files are also available:
+http://www.softether-download.com/
+
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2
+as published by the Free Software Foundation.
+
+SoftEther VPN ("SoftEther" means "Software Ethernet") is one of the
+world's most powerful and easy-to-use multi-protocol VPN software.
+
+SoftEther VPN runs on Windows, Linux, Mac, FreeBSD and Solaris.
+
+SoftEther VPN supports most of widely-used VPN protocols
+including SSL-VPN, OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 and EtherIP
+by the single SoftEther VPN Server program.
+
+More details on http://www.softether.org/.
+
+
+SOFTETHER VPN ADVANTAGES
+------------------------
+
+- Supporting all popular VPN protocols by the single VPN server:
+ SSL-VPN (HTTPS)
+ OpenVPN
+ IPsec
+ L2TP
+ MS-SSTP
+ L2TPv3
+ EtherIP
+- Free and open-source software.
+- Easy to establish both remote-access and site-to-site VPN.
+- SSL-VPN Tunneling on HTTPS to pass through NATs and firewalls.
+- Revolutionary VPN over ICMP and VPN over DNS features.
+- Resistance to highly-restricted firewall.
+- Ethernet-bridging (L2) and IP-routing (L3) over VPN.
+- Embedded dynamic-DNS and NAT-traversal so that no static nor
+ fixed IP address is required.
+- AES 256-bit and RSA 4096-bit encryptions.
+- Sufficient security features such as logging and firewall inner
+ VPN tunnel.
+- 1Gbps-class high-speed throughput performance with low memory and
+ CPU usage.
+- Windows, Linux, Mac, Android, iPhone, iPad and Windows Phone are
+ supported.
+- The OpenVPN clone function supports legacy OpenVPN clients.
+- IPv4 / IPv6 dual-stack.
+- The VPN server runs on Windows, Linux, FreeBSD, Solaris and Mac OS X.
+- Configure All settings on GUI.
+- Multi-languages (English, Japanese and Simplified-Chinese).
+- More details at http://www.softether.org/.
+
+
+GETTING STARTED
+---------------
+
+Visit the SoftEther VPN Project official web site at first:
+ http://www.softether.org/
+
+If you are not a developer, it is recommended to download the binary
+installers from:
+ http://www.softether-download.com/
+
+To build from the source,
+see "BUILD_UNIX.TXT" or "BUILD_WINDOWS.TXT" files.
+
+
+HOW TO DOWNLOAD THE LATEST SOURCE CODE PACKAGE
+----------------------------------------------
+
+Go to http://www.softether-download.com/ and you can find the latest
+source-code package file in both .ZIP and .TAR.GZ format.
+
+This is the easiest way to obtain the source code of SoftEther VPN.
+
+
+HOW TO GET THE LATEST SOURCE CODE TREE FOR DEVELOPERS
+-----------------------------------------------------
+
+If you are an open-source developer, visit our GitHub repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+You can download the up-to-date source-code tree of SoftEther VPN
+from GitHub. You may make your own fork project from our project.
+
+The download and build instruction is following:
+
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+$ cd SoftEtherVPN
+$ make
+$ make install
+
+
+TO CIRCUMVENT YOUR GOVERNMENT'S FIREWALL RESTRICTION
+----------------------------------------------------
+
+Because SoftEther VPN is overly strong tool to build a VPN tunnel,
+some censorship governments want to block your access to the source code
+of SoftEther VPN, by abusing their censorship firewalls.
+
+To circumvent your censor's unjust restriction,
+SoftEther VPN Project distributes the up-to-date source-code
+on all the following open-source repositories:
+
+ - GitHub
+ https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+ - SourceForge
+ https://sourceforge.net/projects/softethervpn/
+
+ - Google Code
+ https://code.google.com/p/softether/
+
+
+To fetch the source code from GitHub:
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+
+To fetch the source code from SourceForge:
+$ git clone http://git.code.sf.net/p/softethervpn/code
+ - or -
+$ git clone git://git.code.sf.net/p/softethervpn/code
+
+To fetch the source code from Google Code:
+$ git clone https://code.google.com/p/softether/
+
+We hope that you can reach one of the above URLs at least!
+
+
+DEAR SECURITY EXPERTS
+---------------------
+
+If you find a bug or a security vulnerability please kindly inform us
+about the problem immediately so that we can fix the security problem
+to protect a lot of users around the world as soon as possible.
+
+Our e-mail address for security reports is:
+softether-vpn-security [at] softether.org
+
+Please note that the above e-mail address is not a technical support
+inquiry address. If you need technical assistance, please visit
+http://www.softether.org/ and ask your question on the users forum.
+
+
+DISCLAIMER
+----------
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+COUNTRIES MIGHT BE RESTRICTED.
+
+
+ADVERTISEMENT
+-------------
+
+SoftEther VPN is developed by SoftEther VPN Project at University of Tsukuba.
+Department of Computer Science has dozens of overly-enthusiastic geeks.
+Join us: http://www.tsukuba.ac.jp/english/admission/
+
diff --git a/README.TXT b/README.TXT
new file mode 100644
index 00000000..df623ce6
--- /dev/null
+++ b/README.TXT
@@ -0,0 +1,189 @@
+SoftEther VPN - An Open-Source Cross-platform Multi-protocol VPN Program
+http://www.softether.org/
+
+We use GitHub as the primary official SoftEther VPN repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+Source code packages (.zip and .tar.gz) and binary files are also available:
+http://www.softether-download.com/
+
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2
+as published by the Free Software Foundation.
+
+SoftEther VPN ("SoftEther" means "Software Ethernet") is one of the
+world's most powerful and easy-to-use multi-protocol VPN software.
+
+SoftEther VPN runs on Windows, Linux, Mac, FreeBSD and Solaris.
+
+SoftEther VPN supports most of widely-used VPN protocols
+including SSL-VPN, OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 and EtherIP
+by the single SoftEther VPN Server program.
+
+More details on http://www.softether.org/.
+
+
+SOFTETHER VPN ADVANTAGES
+------------------------
+
+- Supporting all popular VPN protocols by the single VPN server:
+ SSL-VPN (HTTPS)
+ OpenVPN
+ IPsec
+ L2TP
+ MS-SSTP
+ L2TPv3
+ EtherIP
+- Free and open-source software.
+- Easy to establish both remote-access and site-to-site VPN.
+- SSL-VPN Tunneling on HTTPS to pass through NATs and firewalls.
+- Revolutionary VPN over ICMP and VPN over DNS features.
+- Resistance to highly-restricted firewall.
+- Ethernet-bridging (L2) and IP-routing (L3) over VPN.
+- Embedded dynamic-DNS and NAT-traversal so that no static nor
+ fixed IP address is required.
+- AES 256-bit and RSA 4096-bit encryptions.
+- Sufficient security features such as logging and firewall inner
+ VPN tunnel.
+- 1Gbps-class high-speed throughput performance with low memory and
+ CPU usage.
+- Windows, Linux, Mac, Android, iPhone, iPad and Windows Phone are
+ supported.
+- The OpenVPN clone function supports legacy OpenVPN clients.
+- IPv4 / IPv6 dual-stack.
+- The VPN server runs on Windows, Linux, FreeBSD, Solaris and Mac OS X.
+- Configure All settings on GUI.
+- Multi-languages (English, Japanese and Simplified-Chinese).
+- More details at http://www.softether.org/.
+
+
+GETTING STARTED
+---------------
+
+Visit the SoftEther VPN Project official web site at first:
+ http://www.softether.org/
+
+If you are not a developer, it is recommended to download the binary
+installers from:
+ http://www.softether-download.com/
+
+To build from the source,
+see "BUILD_UNIX.TXT" or "BUILD_WINDOWS.TXT" files.
+
+
+HOW TO DOWNLOAD THE LATEST SOURCE CODE PACKAGE
+----------------------------------------------
+
+Go to http://www.softether-download.com/ and you can find the latest
+source-code package file in both .ZIP and .TAR.GZ format.
+
+This is the easiest way to obtain the source code of SoftEther VPN.
+
+
+HOW TO GET THE LATEST SOURCE CODE TREE FOR DEVELOPERS
+-----------------------------------------------------
+
+If you are an open-source developer, visit our GitHub repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+You can download the up-to-date source-code tree of SoftEther VPN
+from GitHub. You may make your own fork project from our project.
+
+The download and build instruction is following:
+
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+$ cd SoftEtherVPN
+$ make
+$ make install
+
+
+TO CIRCUMVENT YOUR GOVERNMENT'S FIREWALL RESTRICTION
+----------------------------------------------------
+
+Because SoftEther VPN is overly strong tool to build a VPN tunnel,
+some censorship governments want to block your access to the source code
+of SoftEther VPN, by abusing their censorship firewalls.
+
+To circumvent your censor's unjust restriction,
+SoftEther VPN Project distributes the up-to-date source-code
+on all the following open-source repositories:
+
+ - GitHub
+ https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+ - SourceForge
+ https://sourceforge.net/projects/softethervpn/
+
+ - Google Code
+ https://code.google.com/p/softether/
+
+
+To fetch the source code from GitHub:
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+
+To fetch the source code from SourceForge:
+$ git clone http://git.code.sf.net/p/softethervpn/code
+ - or -
+$ git clone git://git.code.sf.net/p/softethervpn/code
+
+To fetch the source code from Google Code:
+$ git clone https://code.google.com/p/softether/
+
+We hope that you can reach one of the above URLs at least!
+
+
+DEAR SECURITY EXPERTS
+---------------------
+
+If you find a bug or a security vulnerability please kindly inform us
+about the problem immediately so that we can fix the security problem
+to protect a lot of users around the world as soon as possible.
+
+Our e-mail address for security reports is:
+softether-vpn-security [at] softether.org
+
+Please note that the above e-mail address is not a technical support
+inquiry address. If you need technical assistance, please visit
+http://www.softether.org/ and ask your question on the users forum.
+
+
+DISCLAIMER
+----------
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+COUNTRIES MIGHT BE RESTRICTED.
+
+
+ADVERTISEMENT
+-------------
+
+SoftEther VPN is developed by SoftEther VPN Project at University of Tsukuba.
+Department of Computer Science has dozens of overly-enthusiastic geeks.
+Join us: http://www.tsukuba.ac.jp/english/admission/
+
diff --git a/configure b/configure
new file mode 100755
index 00000000..7b7c249e
--- /dev/null
+++ b/configure
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+echo '---------------------------------------------------------------------'
+echo 'SoftEther VPN for Unix'
+echo
+echo 'Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan.'
+echo 'Copyright (c) Daiyuu Nobori. All Rights Reserved.'
+echo
+echo 'This program is free software; you can redistribute it and/or'
+echo 'modify it under the terms of the GNU General Public License'
+echo 'version 2 as published by the Free Software Foundation.'
+echo '---------------------------------------------------------------------'
+echo
+
+echo 'Welcome to the corner-cutting configure script !'
+echo
+echo 'Select your operating system below:'
+echo ' 1: Linux'
+echo ' 2: FreeBSD'
+echo ' 3: Solaris'
+echo ' 4: Mac OS X'
+echo
+echo -n 'Which is your operating system (1 - 4) ? : '
+read TMP
+echo
+OS=""
+if test "$TMP" = "1"
+then
+ OS="linux"
+fi
+if test "$TMP" = "2"
+then
+ OS="freebsd"
+fi
+if test "$TMP" = "3"
+then
+ OS="solaris"
+fi
+if test "$TMP" = "4"
+then
+ OS="macos"
+fi
+
+if test "$OS" = ""
+then
+ echo "Wrong number."
+ exit 1
+fi
+
+echo 'Select your CPU bits below:'
+echo ' 1: 32-bit'
+echo ' 2: 64-bit'
+echo
+echo -n 'Which is the type of your CPU (1 - 2) ? : '
+read TMP
+echo
+CPU=""
+if test "$TMP" = "1"
+then
+ CPU="32bit"
+fi
+if test "$TMP" = "2"
+then
+ CPU="64bit"
+fi
+
+if test "$CPU" = ""
+then
+ echo "Wrong number."
+ exit 1
+fi
+
+cp src/makefiles/${OS}_${CPU}.mak Makefile
+
+echo "The Makefile is generated. Run 'make' to build SoftEther VPN."
+
diff --git a/src/BUILD_UNIX.TXT b/src/BUILD_UNIX.TXT
new file mode 100644
index 00000000..f62295dd
--- /dev/null
+++ b/src/BUILD_UNIX.TXT
@@ -0,0 +1,125 @@
+How to build SoftEther VPN for UNIX
+===================================
+
+
+Requirements
+------------
+
+You need to install the following software to build SoftEther VPN for UNIX.
+
+- Linux, FreeBSD, Solaris or Mac OS X.
+- GNU Compiler Collectipon (gcc) and binary utilities.
+- GNU Make (gmake).
+- GNU C Library (glibc).
+- POSIX Threads (pthread).
+- OpenSSL (crypto, ssl).
+- libiconv.
+- readline.
+- ncurses.
+
+For example, the following commands help you to install the above programs
+on Fedora or CentOS Linux:
+
+$ yum -y groupinstall "Development Tools"
+$ yum -y install readline-devel ncurses-devel openssl-devel
+
+
+How to Build
+------------
+
+To build the programs from the source code, run the following commands:
+
+$ ./configure
+$ make
+
+If any error occurs, please check the above requirements.
+
+
+How to Install SoftEther VPN Server, Bridge or Client
+-----------------------------------------------------
+
+To install the vpnserver, vpnbridge and vpnclient programs into the
+/usr/bin directory, run the following as the root user:
+
+# make install
+
+After the installation will complete successfully:
+
+- Execute 'vpnserver start' to run the SoftEther VPN Server background service.
+- Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service.
+- Execute 'vpnclient start' to run the SoftEther VPN Client background service.
+- Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure
+ VPN Server, VPN Bridge or VPN Client.
+
+- You can also use VPN Server/Client Manager GUI Tool on other Windows PC to
+ connect to VPN services remotely.
+ You can download the GUI Tools from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Server for Test
+----------------------------------------
+
+To start the SoftEther VPN Server background service, run the following:
+
+$ bin/vpnserver/vpnserver start
+
+To stop the service, run the following:
+
+$ bin/vpnserver/vpnserver stop
+
+To configure the running SoftEther VPN Server service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Server Manager GUI Tool on other Windows PC to
+connect to the VPN Server remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Bridge for Test
+----------------------------------------
+
+To start the SoftEther VPN Bridge background service, run the following:
+
+$ bin/vpnbridge/vpnbridge start
+
+To stop the service, run the following:
+
+$ bin/vpnbridge/vpnbridge stop
+
+To configure the running SoftEther VPN Bridge service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Server Manager GUI Tool on other Windows PC to
+connect to the VPN Bridge remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+How to Run SoftEther VPN Client for Test
+----------------------------------------
+
+To start the SoftEther VPN Client background service, run the following:
+
+$ bin/vpnclient/vpnclient start
+
+To stop the service, run the following:
+
+$ bin/vpnclient/vpnclient stop
+
+To configure the running SoftEther VPN Client service,
+you can use SoftEther VPN Command Line Management Utility as following:
+
+$ bin/vpncmd/vpncmd
+
+Or you can also use VPN Client Manager GUI Tool on other Windows PC to
+connect to the VPN Client remotely. You can download the GUI Tool
+from http://www.softether-download.com/.
+
+
+************************************
+Thank You Using SoftEther VPN !
+By SoftEther VPN Open-Source Project
+http://www.softether.org/
diff --git a/src/BUILD_WINDOWS.TXT b/src/BUILD_WINDOWS.TXT
new file mode 100644
index 00000000..06e64f72
--- /dev/null
+++ b/src/BUILD_WINDOWS.TXT
@@ -0,0 +1,42 @@
+How to build SoftEther VPN for Windows
+======================================
+
+
+Requirements
+------------
+
+You need to install the following software to build SoftEther VPN for Windows.
+
+- Microsoft Windows XP, Vista, 7, 8 or later.
+- Microsoft Visual Studio 2008.
+
+* Note:
+ Visual Studio 2008 is required to build SoftEther VPN on Windows.
+ Visual Studio 2010, 2012 or 2013 is currently not supported.
+ Visual Studio 2008 Express Edition is not supported.
+ Standard Edition, Professional Edition, Team System or Team Suite is
+ required.
+
+
+Full Build Instructions
+-----------------------
+
+The following steps will build all SoftEther VPN program files, and also build
+the installer packages of SoftEther VPN. It is very easy.
+
+1. Run the "BuildAll.cmd" batch file in the "src" directory.
+2. Wait until the building process will complete.
+3. The built files are stored on the "output" directory.
+
+
+Partly Build, Debug or Development Instructions on Visual Studio 2008
+---------------------------------------------------------------------
+
+If you are a programmer, you can open the SoftEther VPN solution file
+with Visual Studio 2008 to customize. Open "src\SEVPN.sln" and enjoy it.
+
+
+************************************
+Thank You Using SoftEther VPN !
+By SoftEther VPN Open-Source Project
+http://www.softether.org/
diff --git a/src/BuildAll.cmd b/src/BuildAll.cmd
new file mode 100644
index 00000000..5c96ea50
--- /dev/null
+++ b/src/BuildAll.cmd
@@ -0,0 +1,19 @@
+SETLOCAL
+SET BATCH_FILE_NAME=%0
+SET BATCH_DIR_NAME=%0\..
+SET NOW_TMP=%time:~0,2%
+SET NOW=%date:~0,4%%date:~5,2%%date:~8,2%_%NOW_TMP: =0%%time:~3,2%%time:~6,2%
+
+call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
+call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
+echo on
+
+del %BATCH_DIR_NAME%\bin\BuildUtil.exe
+
+C:\windows\Microsoft.NET\Framework\v3.5\MSBuild.exe /toolsversion:3.5 /verbosity:detailed /target:Clean /property:Configuration=Debug "%BATCH_DIR_NAME%\BuildUtil\BuildUtil.csproj"
+
+C:\windows\Microsoft.NET\Framework\v3.5\MSBuild.exe /toolsversion:3.5 /verbosity:detailed /target:Rebuild /property:Configuration=Debug "%BATCH_DIR_NAME%\BuildUtil\BuildUtil.csproj"
+
+cmd /k "%BATCH_DIR_NAME%\bin\BuildUtil.exe /CMD:All"
+
+
diff --git a/src/BuildFiles/Library/Win32_Debug/libeay32.lib b/src/BuildFiles/Library/Win32_Debug/libeay32.lib
new file mode 100644
index 00000000..d0540ea2
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Debug/libeay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Debug/libintelaes.lib b/src/BuildFiles/Library/Win32_Debug/libintelaes.lib
new file mode 100644
index 00000000..cb2bf4c5
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Debug/libintelaes.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Debug/ssleay32.lib b/src/BuildFiles/Library/Win32_Debug/ssleay32.lib
new file mode 100644
index 00000000..e6b41878
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Debug/ssleay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Debug/zlib.lib b/src/BuildFiles/Library/Win32_Debug/zlib.lib
new file mode 100644
index 00000000..cdda429c
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Debug/zlib.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Release/libeay32.lib b/src/BuildFiles/Library/Win32_Release/libeay32.lib
new file mode 100644
index 00000000..3366d3aa
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Release/libeay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Release/libintelaes.lib b/src/BuildFiles/Library/Win32_Release/libintelaes.lib
new file mode 100644
index 00000000..cb2bf4c5
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Release/libintelaes.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Release/ssleay32.lib b/src/BuildFiles/Library/Win32_Release/ssleay32.lib
new file mode 100644
index 00000000..d2645535
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Release/ssleay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/Win32_Release/zlib.lib b/src/BuildFiles/Library/Win32_Release/zlib.lib
new file mode 100644
index 00000000..36f89247
--- /dev/null
+++ b/src/BuildFiles/Library/Win32_Release/zlib.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Debug/libeay32.lib b/src/BuildFiles/Library/x64_Debug/libeay32.lib
new file mode 100644
index 00000000..13a87803
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Debug/libeay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Debug/libintelaes.lib b/src/BuildFiles/Library/x64_Debug/libintelaes.lib
new file mode 100644
index 00000000..c00ae06b
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Debug/libintelaes.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Debug/ssleay32.lib b/src/BuildFiles/Library/x64_Debug/ssleay32.lib
new file mode 100644
index 00000000..d7f7e49e
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Debug/ssleay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Debug/zlib.lib b/src/BuildFiles/Library/x64_Debug/zlib.lib
new file mode 100644
index 00000000..da852576
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Debug/zlib.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Release/libeay32.lib b/src/BuildFiles/Library/x64_Release/libeay32.lib
new file mode 100644
index 00000000..afbe0c2e
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Release/libeay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Release/libintelaes.lib b/src/BuildFiles/Library/x64_Release/libintelaes.lib
new file mode 100644
index 00000000..c00ae06b
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Release/libintelaes.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Release/ssleay32.lib b/src/BuildFiles/Library/x64_Release/ssleay32.lib
new file mode 100644
index 00000000..bf7f3acc
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Release/ssleay32.lib
Binary files differ
diff --git a/src/BuildFiles/Library/x64_Release/zlib.lib b/src/BuildFiles/Library/x64_Release/zlib.lib
new file mode 100644
index 00000000..9be4c609
--- /dev/null
+++ b/src/BuildFiles/Library/x64_Release/zlib.lib
Binary files differ
diff --git a/src/BuildFiles/Manifests/x64_admin.manifest b/src/BuildFiles/Manifests/x64_admin.manifest
new file mode 100644
index 00000000..0fcdb4d9
--- /dev/null
+++ b/src/BuildFiles/Manifests/x64_admin.manifest
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+ </application>
+ </compatibility>
+ <asmv3:application>
+ <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+ <dpiAware>true</dpiAware>
+ </asmv3:windowsSettings>
+ </asmv3:application>
+</assembly>
diff --git a/src/BuildFiles/Manifests/x64_user.manifest b/src/BuildFiles/Manifests/x64_user.manifest
new file mode 100644
index 00000000..21e1e78a
--- /dev/null
+++ b/src/BuildFiles/Manifests/x64_user.manifest
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+ </application>
+ </compatibility>
+ <asmv3:application>
+ <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+ <dpiAware>true</dpiAware>
+ </asmv3:windowsSettings>
+ </asmv3:application>
+</assembly>
diff --git a/src/BuildFiles/Manifests/x86_admin.manifest b/src/BuildFiles/Manifests/x86_admin.manifest
new file mode 100644
index 00000000..0129bc30
--- /dev/null
+++ b/src/BuildFiles/Manifests/x86_admin.manifest
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+ </application>
+ </compatibility>
+ <asmv3:application>
+ <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+ <dpiAware>true</dpiAware>
+ </asmv3:windowsSettings>
+ </asmv3:application>
+</assembly>
diff --git a/src/BuildFiles/Manifests/x86_user.manifest b/src/BuildFiles/Manifests/x86_user.manifest
new file mode 100644
index 00000000..4a3d6fb4
--- /dev/null
+++ b/src/BuildFiles/Manifests/x86_user.manifest
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+ </application>
+ </compatibility>
+ <asmv3:application>
+ <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+ <dpiAware>true</dpiAware>
+ </asmv3:windowsSettings>
+ </asmv3:application>
+</assembly>
diff --git a/src/BuildFiles/OcxCabInf/vpnweb.inf b/src/BuildFiles/OcxCabInf/vpnweb.inf
new file mode 100644
index 00000000..9a7c46dd
--- /dev/null
+++ b/src/BuildFiles/OcxCabInf/vpnweb.inf
@@ -0,0 +1,18 @@
+; VPN Client Web Installer Inf File
+;
+; Copyright (c) SoftEther Project at University of Tsukuba, Japan.
+; All Rights Reserved.
+
+[version]
+signature="$CHICAGO$"
+AdvancedINF=2.0
+
+[Add.Code]
+vpnweb.ocx=vpnweb.ocx
+
+[vpnweb.ocx]
+file-win32-x86=thiscab
+clsid={64F1A16B-C3EE-484C-B551-35338A9BB6D2}
+FileVersion=$CAB_VERSION$
+RegisterServer=yes
+
diff --git a/src/BuildFiles/Utility/cabarc.exe b/src/BuildFiles/Utility/cabarc.exe
new file mode 100644
index 00000000..11f437d9
--- /dev/null
+++ b/src/BuildFiles/Utility/cabarc.exe
Binary files differ
diff --git a/src/BuildFiles/Utility/cabarc_redist.txt b/src/BuildFiles/Utility/cabarc_redist.txt
new file mode 100644
index 00000000..9241359f
--- /dev/null
+++ b/src/BuildFiles/Utility/cabarc_redist.txt
@@ -0,0 +1,74 @@
+
+MICROSOFT CABINET SOFTWARE DEVELOPMENT KIT
+
+END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE
+
+IMPORTANT-READ CAREFULLY: This Microsoft End-User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation for the Microsoft software product identified above, which includes computer software and associated media and printed materials, and may include "online" or electronic documentation ("SOFTWARE PRODUCT" or "SOFTWARE"). By installing, copying, or otherwise using the SOFTWARE PRODUCT, you agree to be bound by the terms of this EULA. If you do not agree to the terms of this EULA; promptly return the unused SOFTWARE PRODUCT to the place from which you obtained it for a full refund; or if you received the SOFTWARE PRODUCT as part of a subscription or other service from Microsoft, you may cancel the subscription and receive a pro rata portion of the subscription price.
+
+SOFTWARE PRODUCT LICENSE
+
+The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The SOFTWARE PRODUCT is licensed, not sold.
+
+1. GRANT OF LICENSE. This EULA grants you the following limited, non-exclusive rights:
+
+Software Product. You may install and use the SOFTWARE PRODUCT on a single computer solely for the purpose of developing applications which create, extract or manipulate files that are compatible with Microsoft CAB file format ("Application"). You may not use the SOFTWARE PRODUCT to create files which are not compatible with the Microsoft CAB file format.
+
+Microsoft Developer Network Subscriber. If you acquired the SOFTWARE PRODUCT through a subscription to the Microsoft Developer Network, and you are either an individual developer or an individual designated within a single entity, you are granted the following additional rights with respect to the SOFTWARE PRODUCT: (a) you may make and use copies of the SOFTWARE PRODUCT on up to ten (10) separate computers, provided that you are the only individual using the SOFTWARE PRODUCT on each such computer, and (b) if you are a single entity, you may designate one individual within your organization to have the right to use the SOFTWARE PRODUCT in the manner described herein.
+
+Sample Code. You may modify the sample source code located in the SOFTWARE PRODUCT's "SAMPLES" directory ("Sample Code") to design, develop, and test your Application. You may also reproduce and distribute the Sample Code in object code form along with any modifications you make to the Sample Code, provided that the modifications do not create files which are not compatible with Microsoft CAB file format and that you comply with the Distribution Requirements described below. For purposes of this section, "modifications" shall mean changes to the functionality of the Sample Code.
+
+Redistributable Code. Portions of the SOFTWARE PRODUCT in the "BIN" and "LIB" directories are designated as "Redistributable Code." You may reproduce and distribute the Redistributable Code provided you comply with the Distribution Requirements described below.
+
+Distribution Requirements. You may copy and redistribute the Sample Code and/or Redistributable Code (collectively "REDISTRIBUTABLE COMPONENTS") as described above, provided that (a) you distribute the REDISTRIBUTABLE COMPONENTS only in conjunction with, and as a part of, your Application; (b) your Application adds significant and primary functionality to the REDISTRIBUTABLE COMPONENTS; (c) the Application does not allow the use of the REDISTRIBUTABLE COMPONENTS for files which are not compatible with the Microsoft CAB files; (d) the executable code in the BIN directory may be redistributed unmodified in conjunction with your Application provided that your Application adds significant and primary functionality to the REDISTRIBUTABLE COMPONENTS; (e) the library code in the LIB directory may only be redistributed when linked into your Application; (f) you do not use Microsoft's name, logo, or trademarks to market your Application; (g) you include a valid copyright notice on your Application; and (h) you agree to indemnify, hold harmless, and defend Microsoft from and against any claims or lawsuits, including attorneys' fees, that arise or result from the use or distribution of your Application. Contact Microsoft for the applicable royalties due and other licensing terms for all other uses and/or distribution of the REDISTRIBUTABLE COMPONENTS.
+
+Microsoft reserves all rights not expressly granted to you.
+
+2. COPYRIGHT. All rights, title, and copyrights in and to the SOFTWARE PRODUCT (including, but not limited to, any images, photographs, animations, video, audio, music, text, and "applets" incorporated into the SOFTWARE PRODUCT) and any copies of the SOFTWARE PRODUCT are owned by Microsoft or its suppliers. The SOFTWARE PRODUCT is protected by copyright laws and international treaty provisions. Therefore, you must treat the SOFTWARE PRODUCT like any other copyrighted material, except that you may either (a) make one copy of the SOFTWARE PRODUCT solely for backup or archival purposes, or (b) install the SOFTWARE PRODUCT on a single computer, provided you keep the original solely for backup or archival purposes. You may not copy the printed materials accompanying the SOFTWARE PRODUCT.
+
+3. PRERELEASE CODE. The SOFTWARE PRODUCT may contain PRERELEASE CODE that is not at the level of performance and compatibility of the final, generally available, product offering. These portions of the SOFTWARE PRODUCT may not operate correctly and may be substantially modified prior to first commercial shipment. Microsoft is not obligated to make this or any later version of the SOFTWARE PRODUCT commercially available. Microsoft grants you the right to distribute test versions of your Application created using the PRERELEASE CODE provided you comply with the Distribution Requirements described in Section 1 and the following additional provisions: (a) you must mark the test version of your Application "BETA" and (b) you are solely responsible for updating your customers with versions of your Application that operate satisfactorily with the final commercial release of the PRERELEASE CODE.
+
+4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS.
+
+Limitations on Reverse-Engineering, Decompilation, and Disassembly. You may not reverse- engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.
+
+Rental. You may not rent or lease the SOFTWARE PRODUCT.
+
+Software Transfer. You may permanently transfer all of your rights under this EULA, provided you retain no copies, you transfer all of the SOFTWARE PRODUCT (including all component parts, the media and printed materials, any upgrades, this EULA, and, if applicable, the Certificate of Authenticity), and the recipient agrees to the terms of this EULA. If the SOFTWARE PRODUCT is an upgrade, any transfer must include all prior versions of the SOFTWARE PRODUCT.
+
+Termination. Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with the terms and conditions of this EULA. In such event, you must destroy all copies of the SOFTWARE PRODUCT and all of its component parts.
+
+5. EXPORT RESTRICTIONS. You agree that neither you nor your customers intend to or will, directly or indirectly, export or transmit (a) the SOFTWARE PRODUCT or related documentation and technical data, or (b) your Application as described in Section 1 of this EULA (or any part thereof), or process, or service that is the direct product of the SOFTWARE PRODUCT to any country to which such export or transmission is restricted by any applicable U.S. regulation or statute, without the prior written consent, if required, of the Bureau of Export Administration of the U.S. Department of Commerce, or such other governmental entity as may have jurisdiction over such export or transmission.
+
+6. U.S. GOVERNMENT RESTRICTED RIGHTS. The SOFTWARE PRODUCT and documentation are provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer Software - Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer is Microsoft Corporation/One Microsoft Way/Redmond, WA 98052-6399.
+
+MISCELLANEOUS
+
+If you acquired this product in the United States, this EULA is governed by the laws of the State of Washington.
+
+If you acquired this product in Canada, this EULA is governed by the laws of the Province of Ontario, Canada. Each of the parties hereto irrevocably attorns to the jurisdiction of the courts of the Province of Ontario and further agrees to commence any litigation that may arise hereunder in the courts located in the Judicial District of York, Province of Ontario.
+
+If this product was acquired outside the United States, local law may apply.
+
+Should you have any questions concerning this EULA, or if you desire to contact Microsoft for any reason, please contact the Microsoft subsidiary serving your country, or write: Microsoft Customer Sales and Service/One Microsoft Way/Redmond, WA 98052-6399.
+
+NO WARRANTIES. To the maximum extent permitted by applicable law, Microsoft expressly disclaims any warranty for the SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any related documentation are provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties of merchantability or fitness for a particular purpose. The entire risk arising out of use or performance of the SOFTWARE PRODUCT remains with you.
+
+LIMITATION OF LIABILITY. Microsoft's entire liability and your exclusive remedy under this EULA shall not exceed five dollars (US$5.00).
+
+NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of, or inability to use, this Microsoft product, even if Microsoft has been advised of the possibility of such damages. Because some states/jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you.
+
+
+Si vous avez acquis votre produit Microsoft au CANADA, la garantie limitée suivante vous concerne:
+
+GARANTIE LIMITÉE
+
+EXCLUSION DE GARANTIES. Microsoft renonce entièrement à toute garantie pour le LOGICIEL. Le LOGICIEL et toute autre documentation s'y rapportant sont fournis « comme tels » sans aucune garantie quelle qu'elle soit, expresse ou implicite, y compris, mais ne se limitant pas aux garanties implicites de la qualité marchande ou un usage particulier. Le risque total découlant de l'utilisation ou de la performance du LOGICIEL est entre vos mains.
+
+RESPONSABILITÉ LIMITÉE. La seule obligation de Microsoft et votre recours exclusif concernant ce contrat n'excèderont pas cinq dollars (US$5.00).
+
+ABSENCE DE RESPONSABILITÉ POUR LES DOMMAGES INDIRECTS. Microsoft ou ses
+fournisseurs ne pourront être tenus responsables en aucune circonstance de tout dommage quel qu'il soit (y compris mais non de façon limitative les dommages directs ou indirects causés par la perte de bénéfices commerciaux, l'interruption des affaires, la perte d'information commerciale ou toute autre perte pécuniaire) résultant de l'utilisation ou de l'impossibilité d'utilisation de ce produit, et ce, même si la société Microsoft a été avisée de l'éventualité de tels dommages. Certains états/juridictions ne permettent pas l'exclusion ou la limitation de responsabilité relative aux dommages indirects ou consécutifs, et la limitation ci-dessus peut ne pas s'appliquer à votre égard.
+La présente Convention est régie par les lois de la province d'Ontario, Canada. Chacune des parties à la Convention reconnaît irrévocablement la compétence des tribunaux de la province d'Ontario et consent à instituer tout litige qui pourrait découler de la Convention auprès des tribunaux situés dans le district judiciaire de York, province d'Ontario.
+Au cas où vous auriez des questions concernant cette licence ou que vous désiriez vous mettre en rapport avec Microsoft pour quelque raison que ce soit, veuillez contacter la succursale Microsoft desservant votre pays, dont l'adresse est fournie dans ce produit, ou écrire à: Microsoft Customer Sales and Service, One Microsoft Way, Redmond, Washington 98052-6399.
+
+3/27/97 10:39 AM 970860004 \ No newline at end of file
diff --git a/src/BuildFiles/VerScript/ver.rc b/src/BuildFiles/VerScript/ver.rc
new file mode 100644
index 00000000..1d937b5e
--- /dev/null
+++ b/src/BuildFiles/VerScript/ver.rc
@@ -0,0 +1,30 @@
+#pragma code_page(932)
+
+1 VERSIONINFO
+ FILEVERSION $VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$
+ PRODUCTVERSION $VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$
+ FILEFLAGSMASK 0x17L
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041104b0"
+ BEGIN
+ VALUE "CompanyName", "SoftEther VPN Project at University of Tsukuba, Japan. (Open-source Customized Build)"
+ VALUE "FileDescription", "$PRODUCTNAME$ (Open-source Customized Build)"
+ VALUE "FileVersion", "$VER_MAJOR$, $VER_MINOR$, 0, $VER_BUILD$"
+ VALUE "InternalName", "$INTERNALNAME$ (Open-source Customized Build)"
+ VALUE "LegalCopyright", "Copyright (C) 2012-$YEAR$ SoftEther VPN Project. All Rights Reserved. (Open-source Customized Build)"
+ VALUE "LegalTrademarks", "SoftEther(R) is a registered trademark of SoftEther Corporation in Japan, United Status and People's Republic of China. SoftEther Corporation is a company founded at University of Tsukuba, Japan."
+ VALUE "OriginalFilename", "$FILENAME$"
+ VALUE "ProductName", "$PRODUCTNAME$ (Open-source Customized Build)"
+ VALUE "ProductVersion", "$VER_MAJOR$, $VER_MINOR$, 0, $VER_BUILD$"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x411, 1200
+ END
+END
diff --git a/src/BuildFiles/VerScript/ver_vg.rc b/src/BuildFiles/VerScript/ver_vg.rc
new file mode 100644
index 00000000..b185c5d5
--- /dev/null
+++ b/src/BuildFiles/VerScript/ver_vg.rc
@@ -0,0 +1,30 @@
+#pragma code_page(932)
+
+1 VERSIONINFO
+ FILEVERSION $VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$
+ PRODUCTVERSION $VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$
+ FILEFLAGSMASK 0x17L
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041104b0"
+ BEGIN
+ VALUE "CompanyName", "University of Tsukuba"
+ VALUE "FileDescription", "VPN Gate Plug-in DLL for SoftEther VPN"
+ VALUE "FileVersion", "$VER_MAJOR$, $VER_MINOR$, 0, $VER_BUILD$"
+ VALUE "InternalName", "$INTERNALNAME$"
+ VALUE "LegalCopyright", "Copyright (C) 2012-$YEAR$ VPN Gate Project at University of Tsukuba. All Rights Reserved."
+ VALUE "LegalTrademarks", ""
+ VALUE "OriginalFilename", "$FILENAME$"
+ VALUE "ProductName", "VPN Gate Software"
+ VALUE "ProductVersion", "$VER_MAJOR$, $VER_MINOR$, 0, $VER_BUILD$"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x411, 1200
+ END
+END
diff --git a/src/BuildUtil/BuildUtil.csproj b/src/BuildUtil/BuildUtil.csproj
new file mode 100644
index 00000000..effc6d26
--- /dev/null
+++ b/src/BuildUtil/BuildUtil.csproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{384815C3-333C-4CEC-9DCD-B6AB2602EBB9}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BuildUtil</RootNamespace>
+ <AssemblyName>BuildUtilTmp</AssemblyName>
+ <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ApplicationIcon>BuildUtilIcon.ico</ApplicationIcon>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <StartupObject>BuildUtil.BuildUtilMain</StartupObject>
+ <NoWin32Manifest>true</NoWin32Manifest>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;BU_SOFTETHER;BU_OSS</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>x86</PlatformTarget>
+ <DocumentationFile>
+ </DocumentationFile>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="CoreUtil, Version=1.1.4781.28908, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>.\CoreUtil.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.EnterpriseServices" />
+ <Reference Include="System.Runtime.Serialization.Formatters.Soap" />
+ <Reference Include="System.Transactions" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BuildUtilCommands.cs" />
+ <Compile Include="BuildUtilMain.cs" />
+ <Compile Include="CodeSign.cs" />
+
+ <Compile Include="PEUtil.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ <DependentUpon>Settings.settings</DependentUpon>
+ </Compile>
+ <Compile Include="Test.cs" />
+ <Compile Include="UnixBuildSoftwares.cs" />
+ <Compile Include="VpnBuilder.cs" />
+ <Compile Include="VpnBuilderConfig.cs" />
+ <Compile Include="VpnBuilderConfigTypes.cs" />
+ <Compile Include="Web References\HvSignService\Reference.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Reference.map</DependentUpon>
+ </Compile>
+ <Compile Include="Web References\SignService\Reference.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Reference.map</DependentUpon>
+ </Compile>
+ <Compile Include="Win32BuildSoftware.cs" />
+ <Compile Include="Win32BuildUtil.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <WebReferences Include="Web References\" />
+ </ItemGroup>
+ <ItemGroup>
+ <WebReferenceUrl Include="http://dv/Sign/Sign.asmx">
+ <UrlBehavior>Dynamic</UrlBehavior>
+ <RelPath>Web References\SignService\</RelPath>
+ <UpdateFromURL>http://dv/Sign/Sign.asmx</UpdateFromURL>
+ <ServiceLocationURL>
+ </ServiceLocationURL>
+ <CachedDynamicPropName>
+ </CachedDynamicPropName>
+ <CachedAppSettingsObjectName>Settings</CachedAppSettingsObjectName>
+ <CachedSettingsPropName>BuildUtil_SignService_Sign</CachedSettingsPropName>
+ </WebReferenceUrl>
+ <WebReferenceUrl Include="http://hvsigncode/Sign.asmx">
+ <UrlBehavior>Dynamic</UrlBehavior>
+ <RelPath>Web References\HvSignService\</RelPath>
+ <UpdateFromURL>http://hvsigncode/Sign.asmx</UpdateFromURL>
+ <ServiceLocationURL>
+ </ServiceLocationURL>
+ <CachedDynamicPropName>
+ </CachedDynamicPropName>
+ <CachedAppSettingsObjectName>Settings</CachedAppSettingsObjectName>
+ <CachedSettingsPropName>BuildUtilTmp_HvSignService_Sign</CachedSettingsPropName>
+ </WebReferenceUrl>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <None Include="Web References\HvSignService\Sign.wsdl" />
+ <None Include="Web References\SignService\Reference.map">
+ <Generator>MSDiscoCodeGenerator</Generator>
+ <LastGenOutput>Reference.cs</LastGenOutput>
+ </None>
+ <None Include="Web References\SignService\Sign.disco" />
+ <None Include="Web References\SignService\Sign.wsdl" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="BuildUtilIcon.ico" />
+ <None Include="Web References\HvSignService\Reference.map">
+ <Generator>MSDiscoCodeGenerator</Generator>
+ <LastGenOutput>Reference.cs</LastGenOutput>
+ </None>
+ <None Include="Web References\HvSignService\Sign.disco" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <PropertyGroup>
+ <PostBuildEvent>$(ProjectDir)CopyBuildUtil.cmd</PostBuildEvent>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/src/BuildUtil/BuildUtilCommands.cs b/src/BuildUtil/BuildUtilCommands.cs
new file mode 100644
index 00000000..9d78477c
--- /dev/null
+++ b/src/BuildUtil/BuildUtilCommands.cs
@@ -0,0 +1,1245 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ public static class BuildUtilCommands
+ {
+ // Perform all
+ [ConsoleCommandMethod(
+ "Builds all sources and releases all packages.",
+ "All [yes|no] [/NORMALIZESRC:yes|no] [/IGNOREERROR:yes|no] [/DEBUG:yes|no] [/SERIAL:yes|no]",
+ "Builds all sources and releases all packages.",
+ "[yes|no]:Specify 'yes' if you'd like to increment the build number.",
+ "NORMALIZESRC:Specity 'yes' if you'd like to normalize the build infomations in the source codes and resource scripts.",
+ "IGNOREERROR:Specify yes if you'd like to ignore the child process to show the error message.",
+ "SERIAL:Specify yes not to use parallel mode.",
+ "DEBUG:Specity yes to enable debug mode. (UNIX only)"
+#if !BU_SOFTETHER
+ , "SEVPN:Build SoftEther VPN Automatically After PacketiX VPN Build"
+#endif
+ )]
+ static int All(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+#if !BU_SOFTETHER
+ new ConsoleParam("[yes|no]", ConsoleService.Prompt, "Increments build number (y/n) ? ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("SEVPN", ConsoleService.Prompt, "Build SoftEther VPN automatically after PacketiX VPN Build (y/n) ? ", ConsoleService.EvalNotEmpty, null),
+#else
+ new ConsoleParam("[yes|no]"),
+#endif
+ new ConsoleParam("IGNOREERROR"),
+ new ConsoleParam("DEBUG"),
+ new ConsoleParam("SERIAL"),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ DateTime start = Time.NowDateTime;
+
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:BuildWin32 {0} /NORMALIZESRC:{1}",
+ vl["[yes|no]"].BoolValue ? "yes" : "no",
+ "yes"));
+
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:ReleaseWin32 all /IGNOREERROR:{0} /SERIAL:{1}",
+ vl["IGNOREERROR"].BoolValue ? "yes" : "no",
+ vl["SERIAL"].BoolValue ? "yes" : "no"));
+
+#if !BU_OSS
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:ReleaseUnix all /IGNOREERROR:{0} /DEBUG:{1} /SERIAL:{2}",
+ vl["IGNOREERROR"].BoolValue ? "yes" : "no",
+ vl["DEBUG"].BoolValue ? "yes" : "no",
+ vl["SERIAL"].BoolValue ? "yes" : "no"));
+#endif
+
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:CopyRelease"));
+
+#if !BU_SOFTETHER
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:MakeOpenSource"));
+
+ Win32BuildUtil.ExecCommand(Env.ExeFileName, string.Format("/CMD:MakeSoftEtherDir"));
+
+ if (vl["SEVPN"].BoolValue)
+ {
+ // Build SEVPN
+ Win32BuildUtil.ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", Path.Combine(Paths.SoftEtherBuildDir, @"Main\BuildAll.cmd")));
+ }
+#endif
+
+ DateTime end = Time.NowDateTime;
+
+ Con.WriteLine("Taken time: {0}.", (end - start));
+
+ return 0;
+ }
+
+#if !BU_SOFTETHER
+ // Create SoftEther Edition source
+ [ConsoleCommandMethod(
+ "Make MakeSoftEtherDir Source Dir.",
+ "MakeSoftEtherDir",
+ "Make MakeSoftEtherDir Source Dir."
+ )]
+ static int MakeSoftEtherDir(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ OpenSourceUtil.MakeSoftEtherDir();
+
+ return 0;
+ }
+
+ // Create an open source version of source
+ [ConsoleCommandMethod(
+ "Make MakeOpenSource Source Dir.",
+ "MakeOpenSource",
+ "Make MakeOpenSource Source Dir."
+ )]
+ static int MakeOpenSource(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ OpenSourceUtil.MakeOpenSource();
+
+ return 0;
+ }
+#endif
+
+ // Copy the released files
+ [ConsoleCommandMethod(
+ "Copies all release files.",
+ "CopyRelease",
+ "Copies all release files."
+ )]
+ static int CopyRelease(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ int build, version;
+ string name;
+ DateTime date;
+ Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ string baseName = string.Format("v{0}-{1}-{2}-{3:D4}.{4:D2}.{5:D2}",
+ BuildHelper.VersionIntToString(version),
+ build,
+ name,
+ date.Year, date.Month, date.Day);
+
+#if !BU_OSS
+ string destDirName = Path.Combine(Paths.ReleaseDestDir,
+ string.Format(@"{0}-{1}-{2}-{3}",
+ Str.DateToStrShort(BuildSoftwareList.ListCreatedDateTime),
+ baseName,
+ Env.MachineName, Env.UserName));
+#else // !BU_OSS
+ string destDirName = Path.Combine(Paths.ReleaseDestDir,
+ string.Format(@"{1}",
+ Str.DateToStrShort(BuildSoftwareList.ListCreatedDateTime),
+ baseName,
+ Env.MachineName, Env.UserName));
+#endif
+
+#if !BU_OSS
+ string publicDir = Path.Combine(destDirName, "Public");
+#else // !BU_OSS
+ string publicDir = destDirName;
+#endif
+
+#if !BU_OSS
+ string filesReleaseDir = Path.Combine(publicDir, baseName);
+#else // !BU_OSS
+ string filesReleaseDir = publicDir;
+#endif
+
+ string autorunReleaseSrcDir = Path.Combine(publicDir, "autorun");
+
+ IO.CopyDir(Paths.ReleaseDir, filesReleaseDir, null, false, true);
+
+#if !BU_OSS
+ IO.CopyDir(Paths.ReleaseSrckitDir, Path.Combine(destDirName, "Private"), null, false, true);
+ IO.CopyDir(Path.Combine(Paths.BaseDirName, @"tmp\lib"), Path.Combine(destDirName, @"Private\lib"), null, false, true);
+#endif
+
+ //IO.MakeDir(autorunReleaseSrcDir);
+
+ /*
+ File.Copy(Path.Combine(Paths.AutorunSrcDir, "Project1.exe"),
+ Path.Combine(autorunReleaseSrcDir, "autorun.exe"), true);
+
+ File.Copy(Path.Combine(Paths.AutorunSrcDir, "autorun.inf"),
+ Path.Combine(autorunReleaseSrcDir, "autorun.inf"), true);
+
+ File.Copy(Path.Combine(Paths.AutorunSrcDir, "packetix.ico"),
+ Path.Combine(autorunReleaseSrcDir, "autorun.ico"), true);*/
+
+ // Create a batch file
+ string batchFileName = Path.Combine(publicDir, "MakeCD.cmd");
+#if !BU_OSS
+ StreamWriter w = new StreamWriter(batchFileName);
+#else // !BU_OSS
+ StringWriter w = new StringWriter();
+#endif
+ w.WriteLine(@"SETLOCAL");
+ w.WriteLine(@"SET BATCH_FILE_NAME=%0");
+ w.WriteLine(@"SET BATCH_DIR_NAME=%0\..");
+ w.WriteLine(@"SET NOW_TMP=%time:~0,2%");
+ w.WriteLine(@"SET NOW=%date:~0,4%%date:~5,2%%date:~8,2%_%NOW_TMP: =0%%time:~3,2%%time:~6,2%");
+ w.WriteLine();
+ w.WriteLine();
+
+ string[] files = Directory.GetFiles(filesReleaseDir, "*", SearchOption.AllDirectories);
+
+ string cddir = "CD";
+ /*string.Format("CD-v{0}.{1}-{2}-{3}-{4:D4}.{5:D2}.{6:D2}",
+ version / 100, version % 100, build, name,
+ date.Year, date.Month, date.Day);*/
+
+ StringWriter txt = new StringWriter();
+
+ foreach (string filename in files)
+ {
+ string file = filename;
+
+ BuildSoftware s = new BuildSoftware(file);
+
+ // Software\Windows\PacketiX VPN Server 4.0\32bit (Intel x86)\filename.exe
+ string cpustr = string.Format("{0} - {1}", CPUBitsUtil.CPUBitsToString(s.Cpu.Bits), s.Cpu.Title).Replace("/", "or");
+ string cpustr2 = cpustr;
+
+ if (s.Cpu == CpuList.intel)
+ {
+ cpustr2 = "";
+ cpustr = "Intel";
+ }
+
+ string tmp = string.Format(@"{1}\{2}\{3}\{5}{4}",
+ 0,
+ s.Os.Title,
+ BuildHelper.GetSoftwareTitle(s.Software),
+ cpustr2,
+ Path.GetFileName(file),
+ ""
+ );
+
+ tmp = Str.ReplaceStr(tmp, "\\\\", "\\");
+
+ w.WriteLine("mkdir \"{1}\\{0}\"", Path.GetDirectoryName(tmp), cddir);
+ w.WriteLine("copy /b /y \"{2}\\{0}\" \"{3}\\{1}\"", IO.GetRelativeFileName(file, filesReleaseDir), tmp, baseName, cddir);
+ w.WriteLine();
+
+ string txt_filename = tmp;
+ txt_filename = Str.ReplaceStr(txt_filename, "\\", "/");
+
+ string txt_description = BuildHelper.GetSoftwareTitle(s.Software);
+
+ string txt_products = BuildHelper.GetSoftwareProductList(s.Software);
+
+ string txt_os = s.Os.Title;
+
+ string txt_cpu = s.Cpu.Title;
+ if (s.Cpu.Bits != CPUBits.Both)
+ {
+ txt_cpu += " (" + CPUBitsUtil.CPUBitsToString(s.Cpu.Bits) + ")";
+ }
+ else
+ {
+ txt_cpu += " (x86 and x64)";
+ }
+
+ string txt_version = BuildHelper.VersionIntToString(version);
+
+ string txt_build = build.ToString();
+
+ string txt_verstr = name;
+
+ string txt_date = Str.DateTimeToStrShortWithMilliSecs(date);
+
+ string txt_lang = "English, Japanese, Simplified Chinese";
+
+ string txt_category = "PacketiX VPN (Commercial)";
+
+#if BU_SOFTETHER
+ txt_category = "SoftEther VPN (Freeware)";
+#endif
+
+ txt.WriteLine("FILENAME\t" + txt_filename);
+ txt.WriteLine("DESCRIPTION\t" + txt_description);
+ txt.WriteLine("CATEGORY\t" + txt_category);
+ txt.WriteLine("PRODUCT\t" + txt_products);
+ txt.WriteLine("OS\t" + txt_os);
+ txt.WriteLine("OSLIST\t" + s.Os.OSSimpleList);
+ txt.WriteLine("CPU\t" + txt_cpu);
+ txt.WriteLine("VERSION\t" + txt_version);
+ txt.WriteLine("BUILD\t" + txt_build);
+ txt.WriteLine("VERSTR\t" + txt_verstr);
+ txt.WriteLine("DATE\t" + txt_date);
+ txt.WriteLine("LANGUAGE\t" + txt_lang);
+ txt.WriteLine("*");
+ txt.WriteLine();
+ }
+
+#if BU_OSS
+ Con.WriteLine("Installer packages are built on '{0}'. Enjoy it !!", publicDir);
+
+ return 0;
+#endif // BU_OSS
+
+ /*
+ w.WriteLine("mkdir \"{0}\\autorun\"", cddir);
+ w.WriteLine("copy /b /y autorun\\autorun.ico \"{0}\\autorun\"", cddir);
+ w.WriteLine("copy /b /y autorun\\autorun.exe \"{0}\\autorun\"", cddir);
+ w.WriteLine("copy /b /y autorun\\autorun.inf \"{0}\\autorun.inf\"", cddir);
+ * */
+
+ string zipFileName = string.Format("VPN-CD-v{0}.{1:D2}-{2}-{3}-{4:D4}.{5:D2}.{6:D2}.zip",
+ version / 100, version % 100, build, name,
+ date.Year, date.Month, date.Day);
+ w.WriteLine("del {0}", zipFileName);
+ w.WriteLine("CD {0}", cddir);
+ w.WriteLine("zip -r -0 ../{0} *", zipFileName);
+ w.WriteLine("cd ..");
+ w.WriteLine("move {0} CD\\", zipFileName);
+ w.WriteLine("rename CD {0}-tree", baseName);
+ w.WriteLine();
+
+ w.Close();
+
+ // Copy of fastcopy
+ string fastcopy_dest = Path.Combine(destDirName, @"Private\fastcopy_bin");
+ IO.MakeDirIfNotExists(fastcopy_dest);
+ File.Copy(Path.Combine(Paths.UtilityDirName, "FastCopy.exe"), Path.Combine(fastcopy_dest, "FastCopy.exe"), true);
+ File.Copy(Path.Combine(Paths.UtilityDirName, "FastEx64.dll"), Path.Combine(fastcopy_dest, "FastEx64.dll"), true);
+ File.Copy(Path.Combine(Paths.UtilityDirName, "FastExt1.dll"), Path.Combine(fastcopy_dest, "FastExt1.dll"), true);
+
+ string fastcopy_exe = @"..\Private\fastcopy_bin\FastCopy.exe";
+
+ // Create a upload batch
+ string uploadBatchFileName = Path.Combine(publicDir, "UploadNow.cmd");
+#if !BU_OSS
+ w = new StreamWriter(uploadBatchFileName);
+#endif // !BU_OSS
+
+ string folder_name = "packetix";
+#if BU_SOFTETHER
+ folder_name = "softether";
+#endif
+ w.WriteLine(@"mkdir \\download\FILES\{1}\{0}-tree", baseName, folder_name);
+ w.WriteLine(@"{0} /cmd=force_copy /exclude={3} /auto_close /force_start /estimate /open_window /error_stop=TRUE /bufsize=128 /disk_mode=diff /speed=full /verify {1}-tree /to=\\download\FILES\{2}\{1}-tree", fastcopy_exe, baseName, folder_name,
+ "\"*files.txt*\"");
+
+ w.WriteLine();
+ /*
+ w.WriteLine(@"mkdir \\downloadjp\FILES\{1}\{0}-tree", baseName, folder_name);
+ w.WriteLine(@"{0} /cmd=force_copy /exclude={3} /auto_close /force_start /estimate /open_window /error_stop=TRUE /bufsize=128 /disk_mode=diff /speed=full /verify {1}-tree /to=\\downloadjp\FILES\{2}\{1}-tree", fastcopy_exe, baseName, folder_name,
+ "\"*files.txt*\"");
+
+ w.WriteLine();*/
+
+ w.WriteLine(@"copy /y /b {0}-tree\files.txt \\download\FILES\{1}\{0}-tree\files.txt", baseName, folder_name);
+ //w.WriteLine(@"copy /y /b {0}-tree\files.txt \\downloadjp\FILES\{1}\{0}-tree\files.txt", baseName, folder_name);
+
+
+ w.WriteLine();
+ w.WriteLine(@"pause");
+ w.WriteLine();
+
+ w.Close();
+
+
+ txt.WriteLine("FILENAME\t" + zipFileName);
+#if BU_SOFTETHER
+ txt.WriteLine("DESCRIPTION\t" + "ZIP CD-ROM Image Package of SoftEther VPN (for Admins)");
+ txt.WriteLine("CATEGORY\t" + "SoftEther VPN (Freeware)");
+ txt.WriteLine("PRODUCT\t" + "ZIP CD-ROM Image Package of SoftEther VPN");
+#else // BU_SOFTETHER
+ txt.WriteLine("DESCRIPTION\t" + "ZIP CD-ROM Image Package of PacketiX VPN (for Admins)");
+ txt.WriteLine("CATEGORY\t" + "PacketiX VPN (Commercial)");
+ txt.WriteLine("PRODUCT\t" + "ZIP CD-ROM Image Package of PacketiX VPN");
+#endif // BU_SOFTETHER
+ txt.WriteLine("OS\t" + "Any");
+ txt.WriteLine("OSLIST\t" + "Any");
+ txt.WriteLine("CPU\t" + "CD-ROM");
+ txt.WriteLine("VERSION\t" + BuildHelper.VersionIntToString(version));
+ txt.WriteLine("BUILD\t" + build.ToString());
+ txt.WriteLine("VERSTR\t" + name);
+ txt.WriteLine("DATE\t" + Str.DateTimeToStrShortWithMilliSecs(date));
+ txt.WriteLine("LANGUAGE\t" + "English, Japanese, Simplified Chinese");
+ txt.WriteLine("*");
+ txt.WriteLine();
+
+ IO.MakeDirIfNotExists(Path.Combine(publicDir, cddir));
+ File.WriteAllText(Path.Combine(Path.Combine(publicDir, cddir), "files.txt"), txt.ToString(), Str.Utf8Encoding);
+
+ // Execution of batch file
+ string old_cd = Environment.CurrentDirectory;
+
+ try
+ {
+ Environment.CurrentDirectory = Path.GetDirectoryName(batchFileName);
+ }
+ catch
+ {
+ }
+
+ Win32BuildUtil.ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", batchFileName));
+
+ try
+ {
+ Environment.CurrentDirectory = old_cd;
+ }
+ catch
+ {
+ }
+
+ Con.WriteLine();
+ Con.WriteLine("'{0}' ã«å‡ºåŠ›ã•ã‚Œã¾ã—ãŸã€‚", destDirName);
+
+ return 0;
+ }
+
+ // UNIX release
+ [ConsoleCommandMethod(
+ "Builds UNIX installer package files.",
+ "ReleaseUnix [id] [/IGNOREERROR:yes|no] [/DEBUG:yes|no] [/SERIAL:yes|no]",
+ "Builds Unix installer package files.",
+ "[id]:Specify target package ID which you'd like to build. If you'd like to erase and rebuild all packages, specify 'all'. Specify 'clean' to delete all release files.",
+ "IGNOREERROR:Specify yes if you'd like to ignore the child process to show the error message.",
+ "SERIAL:Specify yes not to use parallel mode.",
+ "DEBUG:Specity yes to enable debug mode."
+ )]
+ static int ReleaseUnix(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[id]"),
+ new ConsoleParam("IGNOREERROR"),
+ new ConsoleParam("DEBUG"),
+ new ConsoleParam("SERIAL"),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ int version, build;
+ string name;
+ DateTime date;
+ Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+ BuildSoftware[] softs = BuildSoftwareList.List;
+ bool serial = vl["SERIAL"].BoolValue;
+
+ if (Str.IsEmptyStr(vl.DefaultParam.StrValue))
+ {
+ Con.WriteLine("IDs:");
+ foreach (BuildSoftware soft in softs)
+ {
+ if (soft.Os.IsWindows == false)
+ {
+ soft.SetBuildNumberVersionName(build, version, name, date);
+ Con.WriteLine(" {0}", soft.IDString);
+ Con.WriteLine(" - \"{0}\"", soft.OutputFileName);
+ }
+ }
+ }
+ else
+ {
+ string key = vl.DefaultParam.StrValue;
+ bool all = false;
+
+ if ("all".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
+ {
+ all = true;
+ }
+
+ if ("clean".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
+ {
+ // Delete the release directory
+ Paths.DeleteAllReleaseTarGz();
+ Con.WriteLine("Clean completed.");
+ return 0;
+ }
+
+ List<BuildSoftware> o = new List<BuildSoftware>();
+
+ foreach (BuildSoftware soft in softs)
+ {
+ soft.SetBuildNumberVersionName(build, version, name, date);
+
+ if (soft.Os.IsWindows == false)
+ {
+ if (all || soft.IDString.IndexOf(key, StringComparison.InvariantCultureIgnoreCase) != -1)
+ {
+ o.Add(soft);
+ }
+ }
+ }
+
+ if (o.Count == 0)
+ {
+ throw new ApplicationException(string.Format("Software ID '{0}' not found.", key));
+ }
+ else
+ {
+ if (all)
+ {
+ // Delete the release directory
+ Paths.DeleteAllReleaseTarGz();
+ }
+ else
+ {
+ IO.MakeDir(Paths.ReleaseDir);
+ }
+
+ if (serial)
+ {
+ // Build in series
+ int i;
+ for (i = 0; i < o.Count; i++)
+ {
+ Con.WriteLine("{0} / {1}: Executing for '{2}'...",
+ i + 1, o.Count, o[i].IDString);
+
+ BuildHelper.BuildMain(o[i], vl["DEBUG"].BoolValue);
+ }
+ }
+ else if (o.Count == 1)
+ {
+ // To build
+ BuildHelper.BuildMain(o[0], vl["DEBUG"].BoolValue);
+ }
+ else
+ {
+ // Make a child process build
+ Process[] procs = new Process[o.Count];
+
+ int i;
+
+ for (i = 0; i < o.Count; i++)
+ {
+ Con.WriteLine("{0} / {1}: Executing for '{2}'...",
+ i + 1, o.Count, o[i].IDString);
+
+ procs[i] = Kernel.Run(Env.ExeFileName,
+ string.Format("/PAUSEIFERROR:{1} /DT:{2} /CMD:ReleaseUnix /DEBUG:{3} {0}",
+ o[i].IDString, vl["IGNOREERROR"].BoolValue ? "no" : "yes", Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime), vl["DEBUG"].BoolValue ? "yes" : "no")
+ );
+ }
+
+ Con.WriteLine("Waiting child processes...");
+
+ int numError = 0;
+
+ for (i = 0; i < o.Count; i++)
+ {
+ procs[i].WaitForExit();
+
+ bool ok = procs[i].ExitCode == 0;
+
+ if (ok == false)
+ {
+ numError++;
+ }
+
+ Con.WriteLine("{0} / {1} ({2}):", i + 1, o.Count, o[i].IDString);
+ Con.WriteLine(" {0}", ok ? "Success" : "* Error *");
+ }
+
+ Con.WriteLine();
+ if (numError != 0)
+ {
+ throw new ApplicationException(string.Format("{0} Errors.", numError));
+ }
+ Con.WriteLine("No Errors.");
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ // Win32 Release
+ [ConsoleCommandMethod(
+ "Builds Win32 installer package files.",
+ "ReleaseWin32 [id] [/IGNOREERROR:yes|no] [/SERIAL:yes|no]",
+ "Builds Win32 installer package files.",
+ "[id]:Specify target package ID which you'd like to build. If you'd like to erase and rebuild all packages, specify 'all'. Specify 'clean' to delete all release files.",
+ "SERIAL:Specify yes not to use parallel mode.",
+ "IGNOREERROR:Specify yes if you'd like to ignore the child process to show the error message."
+ )]
+ static int ReleaseWin32(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[id]"),
+ new ConsoleParam("IGNOREERROR"),
+ new ConsoleParam("SERIAL"),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ bool serial = vl["SERIAL"].BoolValue;
+ int version, build;
+ string name;
+ DateTime date;
+ Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+ BuildSoftware[] softs = BuildSoftwareList.List;
+
+ if (Str.IsEmptyStr(vl.DefaultParam.StrValue))
+ {
+ Con.WriteLine("IDs:");
+ foreach (BuildSoftware soft in softs)
+ {
+ if (soft.Os.IsWindows)
+ {
+ soft.SetBuildNumberVersionName(build, version, name, date);
+ Con.WriteLine(" {0}", soft.IDString);
+ Con.WriteLine(" - \"{0}\"", soft.OutputFileName);
+ }
+ }
+ }
+ else
+ {
+ string key = vl.DefaultParam.StrValue;
+ bool all = false;
+
+ if ("all".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
+ {
+ all = true;
+ }
+
+ if ("clean".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
+ {
+ // Delete the release directory
+ Paths.DeleteAllReleaseExe();
+ Con.WriteLine("Clean completed.");
+ return 0;
+ }
+
+ List<BuildSoftware> o = new List<BuildSoftware>();
+
+ foreach (BuildSoftware soft in softs)
+ {
+ soft.SetBuildNumberVersionName(build, version, name, date);
+
+ if (soft.Os.IsWindows)
+ {
+ if (all || soft.IDString.IndexOf(key, StringComparison.InvariantCultureIgnoreCase) != -1)
+ {
+ o.Add(soft);
+ }
+ }
+ }
+
+ if (o.Count == 0)
+ {
+ throw new ApplicationException(string.Format("Software ID '{0}' not found.", key));
+ }
+ else
+ {
+ if (all)
+ {
+ // Delete the release directory
+ Paths.DeleteAllReleaseExe();
+ }
+ else
+ {
+ IO.MakeDir(Paths.ReleaseDir);
+ }
+
+ if (serial)
+ {
+ // Build in series
+ int i;
+ for (i = 0; i < o.Count; i++)
+ {
+ Con.WriteLine("{0} / {1}: Executing for '{2}'...",
+ i + 1, o.Count, o[i].IDString);
+
+ BuildHelper.BuildMain(o[i], false);
+ }
+ }
+ else if (o.Count == 1)
+ {
+ // To build
+ BuildHelper.BuildMain(o[0], false);
+ }
+ else
+ {
+ // Make a child process build
+ Process[] procs = new Process[o.Count];
+
+ int i;
+
+ for (i = 0; i < o.Count; i++)
+ {
+ Con.WriteLine("{0} / {1}: Executing for '{2}'...",
+ i + 1, o.Count, o[i].IDString);
+
+ procs[i] = Kernel.Run(Env.ExeFileName,
+ string.Format("/PAUSEIFERROR:{1} /CMD:ReleaseWin32 {0}",
+ o[i].IDString, vl["IGNOREERROR"].BoolValue ? "no" : "yes"));
+ }
+
+ Con.WriteLine("Waiting child processes...");
+
+ int numError = 0;
+
+ for (i = 0; i < o.Count; i++)
+ {
+ procs[i].WaitForExit();
+
+ bool ok = procs[i].ExitCode == 0;
+
+ if (ok == false)
+ {
+ numError++;
+ }
+
+ Con.WriteLine("{0} / {1} ({2}):", i + 1, o.Count, o[i].IDString);
+ Con.WriteLine(" {0}", ok ? "Success" : "* Error *");
+ }
+
+ Con.WriteLine();
+ if (numError != 0)
+ {
+ throw new ApplicationException(string.Format("{0} Errors.", numError));
+ }
+ Con.WriteLine("No Errors.");
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ // Copy the Unix source
+ [ConsoleCommandMethod(
+ "Copies source codes for Unix.",
+ "CopyUnixSrc [destdir]",
+ "Copies source codes for Unix.",
+ "[destdir]:Specify the destination directory."
+ )]
+ static int CopyUnixSrc(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[destdir]", ConsoleService.Prompt, "Destination directory : ", ConsoleService.EvalNotEmpty, null),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ ((BuildSoftwareUnix)BuildSoftwareList.vpnbridge_linux_x86_ja).CopyUnixSrc(vl.DefaultParam.StrValue);
+
+ return 0;
+ }
+
+ // Win32 build
+ [ConsoleCommandMethod(
+ "Builds all executable files for win32 and HamCore for all OS.",
+ "BuildWin32 [yes|no] [/NORMALIZESRC:yes|no]",
+ "Builds all executable files for win32 and HamCore for all OS.",
+ "[yes|no]:Specify 'yes' if you'd like to increment the build number.",
+ "NORMALIZESRC:Specity 'yes' if you'd like to normalize the build infomations in the source codes and resource scripts."
+ )]
+ static int BuildWin32(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[yes|no]", ConsoleService.Prompt, "Increments build number (y/n) ? ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("NORMALIZESRC", ConsoleService.Prompt, "Normalizes source codes (y/n) ? ", ConsoleService.EvalNotEmpty, null)
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ if (vl.DefaultParam.BoolValue)
+ {
+ Win32BuildUtil.IncrementBuildNumber();
+ }
+ if (vl.DefaultParam.BoolValue || vl["NORMALIZESRC"].BoolValue)
+ {
+ Win32BuildUtil.NormalizeBuildInfo();
+ }
+
+ Paths.DeleteAllReleaseTarGz();
+ Paths.DeleteAllReleaseExe();
+ Paths.DeleteAllReleaseManuals();
+ Paths.DeleteAllReleaseAdminKits();
+
+ Win32BuildUtil.BuildMain();
+ Win32BuildUtil.SignAllBinaryFiles();
+ HamCoreBuildUtil.BuildHamcore();
+ Win32BuildUtil.CopyDebugSnapshot();
+
+ return 0;
+ }
+
+ // Process of post-build
+ [ConsoleCommandMethod(
+ "Process necessary tasks after building.",
+ "PostBuild",
+ "Process necessary tasks after building."
+ )]
+ static int PostBuild(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ Win32BuildUtil.SignAllBinaryFiles();
+ HamCoreBuildUtil.BuildHamcore();
+
+ return 0;
+ }
+
+ // Increment the build number
+ [ConsoleCommandMethod(
+ "Increments the build number.",
+ "IncrementBuildNumber",
+ "Increments the build number written in 'CurrentBuild.txt' text file."
+ )]
+ static int IncrementBuildNumber(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ Win32BuildUtil.IncrementBuildNumber();
+
+ return 0;
+ }
+
+
+ // Test processing
+ [ConsoleCommandMethod(
+ "Run Test Procedure.",
+ "Test",
+ "Run Test Procedure."
+ )]
+ static int Test(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ TestClass.Test();
+
+ return 0;
+ }
+
+ // Build a HamCore
+ [ConsoleCommandMethod(
+ "Builds a HamCore file.",
+ "BuildHamCore",
+ "Builds a HamCore file."
+ )]
+ static int BuildHamCore(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ HamCoreBuildUtil.BuildHamcore();
+
+ return 0;
+ }
+
+ // Sign a binary file
+ [ConsoleCommandMethod(
+ "Sign all binary files.",
+ "SignAll",
+ "Sign all binary files."
+ )]
+ static int SignAll(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ Win32BuildUtil.SignAllBinaryFiles();
+
+ return 0;
+ }
+
+ // Create and sign a Inf file of SeLow for Windows 8
+ [ConsoleCommandMethod(
+ "Generate INF files for SeLow.",
+ "SignSeLowInfFiles",
+ "Generate INF files for SeLow."
+ )]
+ static int SignSeLowInfFiles(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[cpu]", ConsoleService.Prompt, "x86 / x64: ", ConsoleService.EvalNotEmpty, null)
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+#if !BU_OSS
+
+ Win32BuildUtil.SignSeLowInfFiles(vl.DefaultParam.StrValue);
+
+#endif
+
+ return 0;
+ }
+
+ // Create Inf file for Windows 8
+ [ConsoleCommandMethod(
+ "Generate INF files for Windows 8.",
+ "GenerateWin8InfFiles",
+ "Generate INF files for Windows 8."
+ )]
+ static int GenerateWin8InfFiles(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[cpu]", ConsoleService.Prompt, "x86 / x64: ", ConsoleService.EvalNotEmpty, null)
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+#if !BU_OSS
+
+ Win32BuildUtil.GenerateINFFilesForWindows8(vl.DefaultParam.StrValue);
+
+#endif
+
+ return 0;
+ }
+
+ // Set the version of the PE to 4
+ [ConsoleCommandMethod(
+ "Set the version of the PE file to 4.",
+ "SetPE4 [filename]",
+ "Set the version of the PE file to 4.",
+ "[filename]:Specify the target filename."
+ )]
+ static int SetPE4(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[filename]", ConsoleService.Prompt, "Filename: ", ConsoleService.EvalNotEmpty, null)
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ PEUtil.SetPEVersionTo4(vl.DefaultParam.StrValue);
+
+ return 0;
+ }
+
+ // Set the Manifest
+ [ConsoleCommandMethod(
+ "Set the manifest to the executable file.",
+ "SetManifest [filename] [/MANIFEST:manifest_file_name]",
+ "Set the manifest to the executable file.",
+ "[filename]:Specify the target executable filename.",
+ "MANIFEST:Specify the manifest XML file."
+ )]
+ static int SetManifest(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[filename]", ConsoleService.Prompt, "Target Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("MANIFEST", ConsoleService.Prompt, "Manifest Filename: ", ConsoleService.EvalNotEmpty, null),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ PEUtil.SetManifest(vl.DefaultParam.StrValue, vl["MANIFEST"].StrValue);
+
+ return 0;
+ }
+
+ // Generate a version information resource
+ [ConsoleCommandMethod(
+ "Generate a Version Information Resource File.",
+ "GenerateVersionResource [targetFileName] [/OUT:destFileName]",
+ "Generate a Version Information Resource File.",
+ "[targetFileName]:Specify the target exe/dll file name.",
+ "OUT:Specify the output .res file.",
+ "RC:Specify a template RC file name.")]
+ static int GenerateVersionResource(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[targetFileName]", ConsoleService.Prompt, "Target Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("OUT", ConsoleService.Prompt, "Dst Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("RC"),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ string targetFilename = vl.DefaultParam.StrValue;
+ string outFilename = vl["OUT"].StrValue;
+
+ Win32BuildUtil.GenerateVersionInfoResource(targetFilename, outFilename, vl["RC"].StrValue);
+
+ return 0;
+ }
+
+ // Measure the number of lines of code
+ [ConsoleCommandMethod(
+ "Count the number of lines of the sources.",
+ "Count [DIR]",
+ "Count the number of lines of the sources.",
+ "[DIR]:dir name.")]
+ static int Count(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[DIR]", null, null, null, null),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ string dir = vl.DefaultParam.StrValue;
+ if (Str.IsEmptyStr(dir))
+ {
+ dir = Paths.BaseDirName;
+ }
+
+ string[] files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
+
+ int numLines = 0;
+ int numBytes = 0;
+ int numComments = 0;
+ int totalLetters = 0;
+
+ Dictionary<string, int> commentsDict = new Dictionary<string, int>();
+
+ foreach (string file in files)
+ {
+ string ext = Path.GetExtension(file);
+
+ if (Str.StrCmpi(ext, ".c") || Str.StrCmpi(ext, ".cpp") || Str.StrCmpi(ext, ".h") ||
+ Str.StrCmpi(ext, ".rc") || Str.StrCmpi(ext, ".stb") || Str.StrCmpi(ext, ".cs")
+ || Str.StrCmpi(ext, ".fx") || Str.StrCmpi(ext, ".hlsl"))
+ {
+ if (Str.InStr(file, "\\.svn\\") == false && Str.InStr(file, "\\seedll\\") == false && Str.InStr(file, "\\see\\") == false && Str.InStr(file, "\\openssl\\") == false)
+ {
+ string[] lines = File.ReadAllLines(file);
+
+ numLines += lines.Length;
+ numBytes += (int)new FileInfo(file).Length;
+
+ foreach (string line in lines)
+ {
+ if (Str.InStr(line, "//") && Str.InStr(line, "// Validate arguments") == false)
+ {
+ if (commentsDict.ContainsKey(line) == false)
+ {
+ commentsDict.Add(line, 1);
+ }
+ numComments++;
+
+ totalLetters += line.Trim().Length - 3;
+ }
+ }
+ }
+ }
+ }
+
+ Con.WriteLine("{0} Lines, {1} Bytes. {2} Comments ({3} distinct, aver: {4})", Str.ToStr3(numLines), Str.ToStr3(numBytes),
+ Str.ToStr3(numComments), commentsDict.Count, totalLetters / numComments);
+
+ return 0;
+ }
+
+ // Add to Cab by compressing OCX
+ [ConsoleCommandMethod(
+ "Compress a OCX and Generate a Cab file.",
+ "GenerateVpnWebOcxCab [src] [/DEST:dest]",
+ "Compress a OCX and Generate a Cab file.",
+ "[src]:Specify the ocx file.",
+ "DEST:Specify the destination cab file.")]
+ static int GenerateVpnWebOcxCab(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[src]", ConsoleService.Prompt, "Src Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("DEST", ConsoleService.Prompt, "Dst Filename: ", ConsoleService.EvalNotEmpty, null),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+#if !BU_OSS
+ string destFileName = vl["DEST"].StrValue;
+ string srcFileName = vl.DefaultParam.StrValue;
+
+ Win32BuildUtil.GenerateVpnWebOcxCab(destFileName, srcFileName);
+#endif
+
+ return 0;
+ }
+
+
+ // Copy the file
+ [ConsoleCommandMethod(
+ "Copy a File.",
+ "FileCopy [src] [/DEST:dest]",
+ "Copy a File.",
+ "[src]:Specify the source file.",
+ "DEST:Specify the destination file.")]
+ static int FileCopy(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[src]", ConsoleService.Prompt, "Src Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("DEST", ConsoleService.Prompt, "Dst Filename: ", ConsoleService.EvalNotEmpty, null),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ string destFileName = vl["DEST"].StrValue;
+ string srcFileName = vl.DefaultParam.StrValue;
+
+ IO.FileCopy(srcFileName, destFileName, true, false);
+
+ return 0;
+ }
+
+ // Sign the file
+ [ConsoleCommandMethod(
+ "Sign files using Authenticode certificates.",
+ "SignCode [filename] [/DEST:destfilename] [/COMMENT:comment] [/KERNEL:yes|no]",
+ "Sign files using Authenticode certificates.",
+ "[filename]:Specify the target filename.",
+ "DEST:Specify the destination filename. If this parameter is not specified, the target file will be overwritten.",
+ "COMMENT:Provide a description of the signed content.",
+ "KERNEL:Specify \"yes\" if Windows Vista / 7 Kernel Mode Driver Signing is needed."
+ )]
+ static int SignCode(ConsoleService c, string cmdName, string str)
+ {
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("[filename]", ConsoleService.Prompt, "Filename: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("DEST"),
+ new ConsoleParam("COMMENT", ConsoleService.Prompt, "Comment: ", ConsoleService.EvalNotEmpty, null),
+ new ConsoleParam("KERNEL"),
+ };
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ string destFileName = vl["DEST"].StrValue;
+ string srcFileName = vl.DefaultParam.StrValue;
+ if (Str.IsEmptyStr(destFileName))
+ {
+ destFileName = srcFileName;
+ }
+ string comment = vl["COMMENT"].StrValue;
+ bool kernel = vl["KERNEL"].BoolValue;
+
+ CodeSign.SignFile(destFileName, srcFileName, comment, kernel);
+
+ return 0;
+ }
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/BuildUtilIcon.ico b/src/BuildUtil/BuildUtilIcon.ico
new file mode 100644
index 00000000..75d3c4aa
--- /dev/null
+++ b/src/BuildUtil/BuildUtilIcon.ico
Binary files differ
diff --git a/src/BuildUtil/BuildUtilMain.cs b/src/BuildUtil/BuildUtilMain.cs
new file mode 100644
index 00000000..a8f2918b
--- /dev/null
+++ b/src/BuildUtil/BuildUtilMain.cs
@@ -0,0 +1,193 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ public class BuildUtilMain
+ {
+ public static bool pause = false;
+
+ // Main function
+ public static int Main(string[] args)
+ {
+ string errMsg = "";
+
+ int ret = 0;
+
+ ret = ConsoleService.EntryPoint("BuildUtil " + Env.CommandLine, "BuildUtil", typeof(BuildUtilMain), out errMsg);
+
+ if (ret != 0)
+ {
+ Con.WriteLine("{0}: fatal error C0001: {1}", Path.GetFileNameWithoutExtension(Env.ExeFileName), errMsg);
+
+ if (pause)
+ {
+ Console.Write("Press any key to exit...");
+ Console.ReadKey();
+ }
+
+ Environment.Exit(1);
+ }
+
+ return ret;
+ }
+
+ // Command execution
+ [ConsoleCommandMethod(
+ "VPN Build Utility",
+ "[/IN:infile] [/OUT:outfile] [/CSV] [/PAUSEIFERROR:yes|no] [/CMD command_line...]",
+ "VPN Build Utility",
+ "IN:This will specify the text file 'infile' that contains the list of commands that are automatically executed after the connection is completed. If the /IN parameter is specified, the vpncmd program will terminate automatically after the execution of all commands in the file are finished. If the file contains multiple-byte characters, the encoding must be Unicode (UTF-8). This cannot be specified together with /CMD (if /CMD is specified, /IN will be ignored).",
+ "OUT:You can specify the text file 'outfile' to write all strings such as onscreen prompts, message, error and execution results. Note that if the specified file already exists, the contents of the existing file will be overwritten. Output strings will be recorded using Unicode (UTF-8) encoding.",
+ "CMD:If the optional command 'command_line...' is included after /CMD, that command will be executed after the connection is complete and the vpncmd program will terminate after that. This cannot be specified together with /IN (if specified together with /IN, /IN will be ignored). Specify the /CMD parameter after all other vpncmd parameters.",
+ "CSV:Enable CSV Mode.",
+ "PAUSEIFERROR:Specify yes if you'd like to pause before exiting the process if there are any errors."
+ )]
+ public static int BuildUtil(ConsoleService c, string cmdName, string str)
+ {
+ Con.WriteLine("");
+ Con.WriteLine("Copyright (c) SoftEther Corporation. All Rights Reserved.");
+ Con.WriteLine("");
+
+ ConsoleParam[] args =
+ {
+ new ConsoleParam("IN", null, null, null, null),
+ new ConsoleParam("OUT", null, null, null, null),
+ new ConsoleParam("CMD", null, null, null, null),
+ new ConsoleParam("CSV", null, null, null, null),
+ new ConsoleParam("PAUSEIFERROR", null, null, null, null),
+ new ConsoleParam("DT", null, null, null, null),
+ };
+
+ ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);
+
+ pause = vl["PAUSEIFERROR"].BoolValue;
+
+ string cmdline = vl["CMD"].StrValue;
+
+ if (vl["DT"].IsEmpty == false)
+ {
+ BuildSoftwareList.ListCreatedDateTime = Str.StrToDateTime(vl["DT"].StrValue);
+ }
+
+ ConsoleService cs = c;
+
+ while (cs.DispatchCommand(cmdline, "BuildUtil>", typeof(BuildUtilCommands), null))
+ {
+ if (Str.IsEmptyStr(cmdline) == false)
+ {
+ break;
+ }
+ }
+
+ return cs.RetCode;
+ }
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/CodeSign.cs b/src/BuildUtil/CodeSign.cs
new file mode 100644
index 00000000..d699716e
--- /dev/null
+++ b/src/BuildUtil/CodeSign.cs
@@ -0,0 +1,263 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+using BuildUtil.HvSignService;
+
+namespace BuildUtil
+{
+ public static class CodeSign
+ {
+ public const int NumRetries = 1;
+ public const int RetryIntervals = 200;
+
+ public const int NumRetriesForCopy = 50;
+ public const int RetryIntervalsForCopy = 10;
+
+ const string in_dir = @"\\hvsigncode\SIGN\IN";
+ const string out_dir = @"\\hvsigncode\SIGN\OUT";
+
+#if !BU_SOFTETHER
+ public static int UsingCertId = 1;
+#else
+ public static int UsingCertId = 2;
+#endif
+
+ static object lockObj = new object();
+
+ // Digital-sign the data on the memory
+ public static byte[] SignMemory(byte[] srcData, string comment, bool kernelModeDriver, int cert_id)
+ {
+#if !BU_OSS
+ int i;
+ string out_filename = null;
+ byte[] ret = null;
+
+ string in_tmp_filename = Path.Combine(in_dir,
+ Str.DateTimeToStrShortWithMilliSecs(DateTime.Now) + "_" +
+ Env.MachineName + "_" +
+ Secure.Rand63i().ToString() + ".dat");
+
+ IO.SaveFile(in_tmp_filename, srcData);
+
+ for (i = 0; i < NumRetries; i++)
+ {
+ Sign sign = new Sign();
+ sign.Proxy = new WebProxy();
+
+ try
+ {
+ out_filename = sign.ExecSign(Path.GetFileName(in_tmp_filename),
+ kernelModeDriver,
+ comment,
+ cert_id);
+ break;
+ }
+ catch (Exception ex)
+ {
+ if (i != (NumRetries - 1))
+ {
+ Kernel.SleepThread(RetryIntervals);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+
+ for (i = 0; i < NumRetriesForCopy; i++)
+ {
+ try
+ {
+ ret = IO.ReadFile(Path.Combine(out_dir, out_filename));
+ }
+ catch (Exception ex)
+ {
+ if (i != (NumRetriesForCopy - 1))
+ {
+ Kernel.SleepThread(RetryIntervalsForCopy);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+
+ string tmpFileName = IO.CreateTempFileNameByExt(".exe");
+ try
+ {
+ File.Delete(tmpFileName);
+ }
+ catch
+ {
+ }
+ File.WriteAllBytes(tmpFileName, ret);
+
+ lock (lockObj)
+ {
+ if (ExeSignChecker.CheckFileDigitalSignature(tmpFileName) == false)
+ {
+ throw new ApplicationException("CheckFileDigitalSignature failed.");
+ }
+
+ if (kernelModeDriver)
+ {
+ if (ExeSignChecker.IsKernelModeSignedFile(tmpFileName) == false)
+ {
+ throw new ApplicationException("IsKernelModeSignedFile failed.");
+ }
+ }
+ }
+
+ try
+ {
+ }
+ catch
+ {
+ File.Delete(tmpFileName);
+ }
+
+ return ret;
+#else // BU_OSS
+ return srcData;
+#endif // BU_OSS
+ }
+
+ // Digital-sign the data on the file
+ public static void SignFile(string destFileName, string srcFileName, string comment, bool kernelModeDriver)
+ {
+ int cert_id = UsingCertId;
+
+ SignFile(destFileName, srcFileName, comment, kernelModeDriver, cert_id);
+ }
+ public static void SignFile(string destFileName, string srcFileName, string comment, bool kernelModeDriver, int cert_id)
+ {
+#if !BU_OSS
+ Con.WriteLine("Signing for '{0}'...", Path.GetFileName(destFileName));
+ byte[] srcData = File.ReadAllBytes(srcFileName);
+
+ byte[] destData = SignMemory(srcData, comment, kernelModeDriver, cert_id);
+
+ try
+ {
+ File.Delete(destFileName);
+ }
+ catch
+ {
+ }
+
+ File.WriteAllBytes(destFileName, destData);
+
+ Con.WriteLine("Done.");
+#else // BU_OSS
+ Con.WriteLine("Skipping the code signing for '{0}' in the build process. You can insert your own authenticode sign process here.", srcFileName);
+#endif // BU_OSS
+ }
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/CopyBuildUtil.cmd b/src/BuildUtil/CopyBuildUtil.cmd
new file mode 100644
index 00000000..18c4d9c5
--- /dev/null
+++ b/src/BuildUtil/CopyBuildUtil.cmd
@@ -0,0 +1,2 @@
+copy %0\..\..\bin\BuildUtilTmp.exe %0\..\..\bin\BuildUtil.exe
+exit /b 0
diff --git a/src/BuildUtil/CoreUtil.dll b/src/BuildUtil/CoreUtil.dll
new file mode 100644
index 00000000..c2da4954
--- /dev/null
+++ b/src/BuildUtil/CoreUtil.dll
Binary files differ
diff --git a/src/BuildUtil/PEUtil.cs b/src/BuildUtil/PEUtil.cs
new file mode 100644
index 00000000..59b71daa
--- /dev/null
+++ b/src/BuildUtil/PEUtil.cs
@@ -0,0 +1,231 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ public static class PEUtil
+ {
+ public const int NumRetries = 5;
+ public const int RetryIntervals = 200;
+ public const string MutexName = "peutil_setmanifest_mutex";
+
+ // Set the version of the PE header to 4 (to work in Windows 98, etc.)
+ public static void SetPEVersionTo4(byte[] srcData)
+ {
+ int offset = 0x140 + (int)((uint)srcData[0x3c] + ((uint)srcData[0x3d] * 256)) - 0xf8;
+
+ if (!((srcData[offset] == 0x04 || srcData[offset] == 0x05) && srcData[offset + 1] == 0x00))
+ {
+ throw new ApplicationException("The specified file is not PE file.");
+ }
+
+ srcData[offset] = 0x04;
+ }
+ public static void SetPEVersionTo4(string fileName)
+ {
+ FileInfo fi = new FileInfo(fileName);
+
+ byte[] data = File.ReadAllBytes(fileName);
+ SetPEVersionTo4(data);
+
+ int i;
+ for (i = 0;; i++)
+ {
+ try
+ {
+ File.WriteAllBytes(fileName, data);
+ break;
+ }
+ catch (Exception ex)
+ {
+ if (i >= (NumRetries - 1))
+ {
+ throw ex;
+ }
+
+ Kernel.SleepThread(RetryIntervals);
+ }
+ }
+
+ File.SetCreationTime(fileName, fi.CreationTime);
+ File.SetLastAccessTime(fileName, fi.LastAccessTime);
+ File.SetLastWriteTime(fileName, fi.LastWriteTime);
+ }
+
+ public static void SetManifest(string exe, string manifestName)
+ {
+ Mutex x = new Mutex(false, MutexName);
+
+ x.WaitOne();
+
+ try
+ {
+ // Manifest file name
+ string filename = Path.Combine(Paths.ManifestsDir, manifestName);
+ if (File.Exists(filename) == false)
+ {
+ throw new FileNotFoundException(filename);
+ }
+
+ FileInfo fi = new FileInfo(exe);
+
+ // Copy exe file to a temporary directory
+ string exeTmp = IO.CreateTempFileNameByExt(".exe");
+ IO.FileCopy(exe, exeTmp);
+
+ // Create a batch file
+ string batFileName = Path.Combine(Paths.TmpDirName, "exec_mt.cmd");
+ StreamWriter bat = new StreamWriter(batFileName, false, Str.ShiftJisEncoding);
+ bat.WriteLine("call \"{0}\"", Paths.VisualStudioVCBatchFileName);
+ bat.WriteLine("echo on");
+ bat.WriteLine("mt.exe -manifest \"{0}\" -outputresource:\"{1}\";1", filename, exeTmp);
+ bat.WriteLine("EXIT /B %ERRORLEVEL%");
+ bat.Close();
+
+ Exception ex = null;
+
+ int i;
+ // Repeated 20 times in order to avoid locking the file by the anti-virus software
+ for (i = 0; i < 20; i++)
+ {
+ try
+ {
+ // Execute
+ Win32BuildUtil.ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", batFileName), true);
+ ex = null;
+
+ break;
+ }
+ catch (Exception ex2)
+ {
+ ex = ex2;
+ }
+
+ ThreadObj.Sleep(Secure.Rand31i() % 50);
+ }
+
+ if (ex != null)
+ {
+ throw new ApplicationException("mt.exe Manifest Processing for '" + exe + "' Failed.");
+ }
+
+ // Revert to the original file
+ IO.FileCopy(exeTmp, exe);
+
+ // Restore the date and time
+ File.SetCreationTime(exe, fi.CreationTime);
+ File.SetLastAccessTime(exe, fi.LastAccessTime);
+ File.SetLastWriteTime(exe, fi.LastWriteTime);
+ }
+ finally
+ {
+ x.ReleaseMutex();
+ }
+ }
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Properties/AssemblyInfo.cs b/src/BuildUtil/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..2cff91e2
--- /dev/null
+++ b/src/BuildUtil/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("PacketiX VPN / SoftEther VPN Build Utility")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("SoftEther Corporation")]
+[assembly: AssemblyProduct("PacketiX VPN / SoftEther VPN Build Utility")]
+[assembly: AssemblyCopyright("Copyright (c) SoftEther Corporation. All Rights Reserved.")]
+[assembly: AssemblyTrademark("PacketiX(R) and SoftEther(R) is a registered trademark of SoftEther Corporation.")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("5bf63a11-27da-4ca4-ba9d-a60a0f8e1fd7")]
+
+[assembly: AssemblyVersion("1.0.*")]
diff --git a/src/BuildUtil/Properties/Settings.Designer.cs b/src/BuildUtil/Properties/Settings.Designer.cs
new file mode 100644
index 00000000..5715f13d
--- /dev/null
+++ b/src/BuildUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,115 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// ã“ã®ã‚³ãƒ¼ãƒ‰ã¯ãƒ„ールã«ã‚ˆã£ã¦ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚
+// ランタイム ãƒãƒ¼ã‚¸ãƒ§ãƒ³:2.0.50727.5466
+//
+// ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¸ã®å¤‰æ›´ã¯ã€ä»¥ä¸‹ã®çŠ¶æ³ä¸‹ã§ä¸æ­£ãªå‹•ä½œã®åŽŸå› ã«ãªã£ãŸã‚Šã€
+// コードãŒå†ç”Ÿæˆã•ã‚Œã‚‹ã¨ãã«æ失ã—ãŸã‚Šã—ã¾ã™ã€‚
+// </auto-generated>
+//------------------------------------------------------------------------------
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+namespace BuildUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
+ [global::System.Configuration.DefaultSettingValueAttribute("http://dv/Sign/Sign.asmx")]
+ public string BuildUtil_SignService_Sign {
+ get {
+ return ((string)(this["BuildUtil_SignService_Sign"]));
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
+ [global::System.Configuration.DefaultSettingValueAttribute("http://hvsigncode/Sign.asmx")]
+ public string BuildUtilTmp_HvSignService_Sign {
+ get {
+ return ((string)(this["BuildUtilTmp_HvSignService_Sign"]));
+ }
+ }
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Properties/Settings.settings b/src/BuildUtil/Properties/Settings.settings
new file mode 100644
index 00000000..5e8d1669
--- /dev/null
+++ b/src/BuildUtil/Properties/Settings.settings
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="BuildUtil.Properties" GeneratedClassName="Settings">
+ <Profiles />
+ <Settings>
+ <Setting Name="BuildUtil_SignService_Sign" Type="(Web Service URL)" Scope="Application">
+ <Value Profile="(Default)">http://dv/Sign/Sign.asmx</Value>
+ </Setting>
+ <Setting Name="BuildUtilTmp_HvSignService_Sign" Type="(Web Service URL)" Scope="Application">
+ <Value Profile="(Default)">http://hvsigncode/Sign.asmx</Value>
+ </Setting>
+ </Settings>
+</SettingsFile> \ No newline at end of file
diff --git a/src/BuildUtil/Test.cs b/src/BuildUtil/Test.cs
new file mode 100644
index 00000000..688be1da
--- /dev/null
+++ b/src/BuildUtil/Test.cs
@@ -0,0 +1,125 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ public static class TestClass
+ {
+ public static void Test()
+ {
+ Language[] langs = BuildHelper.GetLanguageList();
+
+ foreach (Language e in langs)
+ {
+ Con.WriteLine("{0} {1} {2} {3} {5} {4}",
+ e.Number, e.Id, e.Title, e.TitleUnicode, e.UnixLocaleIds, e.WindowsLocaleIds);
+ }
+ }
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/UnixBuildSoftwares.cs b/src/BuildUtil/UnixBuildSoftwares.cs
new file mode 100644
index 00000000..77bd9eb4
--- /dev/null
+++ b/src/BuildUtil/UnixBuildSoftwares.cs
@@ -0,0 +1,1015 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // Build the UNIX software
+ public class BuildSoftwareUnix : BuildSoftware
+ {
+ public readonly string[] SrcDirNameList =
+ {
+ @"bin\BuiltHamcoreFiles",
+ @"bin\hamcore",
+ "Cedar",
+ "Ham",
+ "Mayaqua",
+ "Neo",
+ "VGate",
+ "vpnbridge",
+ "vpnclient",
+ "vpncmd",
+ "vpnserver",
+ };
+
+ public readonly string CrossLibName;
+ public readonly string CrossLibBaseDir = Path.Combine(Paths.BaseDirName, @"BuildFiles\CrossLib");
+ public readonly bool UseGccBitsOption;
+ public readonly string CrossCompilerName;
+ public readonly bool NoPThreadOption;
+ public readonly string CrossCompilerOption;
+ public readonly string SrcKitDefaultDir;
+
+ public BuildSoftwareUnix(Software software, int buildNumber, int version, string buildName, Cpu cpu, OS os,
+ string crossLibName, bool useGccBitsOption, string crossCompilerName, bool noPthreadOption, string crossCompilerOption)
+ : base(software, buildNumber, version, buildName, cpu, os)
+ {
+ this.CrossLibName = crossLibName;
+ this.UseGccBitsOption = useGccBitsOption;
+ this.CrossCompilerName = crossCompilerName;
+ this.NoPThreadOption = noPthreadOption;
+ this.CrossCompilerOption = crossCompilerOption;
+
+#if !BU_SOFTETHER
+ this.SrcKitDefaultDir = Env.SystemDir.Substring(0, 2) + @"\tmp\vpn4_srckit";
+#else
+ this.SrcKitDefaultDir = Env.SystemDir.Substring(0, 2) + @"\tmp\se_vpn_srckit";
+#endif
+ }
+
+ // Run the build
+ public void Build(bool debugMode)
+ {
+ string mutexName = "buildsrckit_" + this.CrossLibName;
+
+ Mutex mutex = new Mutex(false, mutexName);
+
+ mutex.WaitOne();
+
+ try
+ {
+ if (this.BuildSrcKit(SrcKitDefaultDir, debugMode))
+ {
+ this.BuildWithCrossCompiler(SrcKitDefaultDir);
+ }
+ }
+ finally
+ {
+ mutex.ReleaseMutex();
+ }
+
+ this.Release(SrcKitDefaultDir);
+ }
+
+ public override void Build()
+ {
+ throw new NotImplementedException();
+ }
+
+ // Delegate to copy the source code
+ public bool CopySrcFilesDelegate(FileInfo info)
+ {
+ string[] ignoreExts =
+ {
+ ".exe", ".sys", ".dll", ".inf", ".vcproj", ".user",
+ ".ico", ".rc",
+ };
+ string name = info.FullName;
+
+ if (Str.InStr(name, @"\.svn\") ||
+ Str.InStr(name, @"\WinPcap\") ||
+ Str.InStr(name, @"_Debug\") ||
+ Str.InStr(name, @"_Release\") ||
+ Str.InStr(name, @"\BuiltHamcoreFiles\win32_"))
+ {
+ return false;
+ }
+
+ foreach (string ext in ignoreExts)
+ {
+ if (name.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Create a release
+ public virtual void Release(string baseOutputDir)
+ {
+ string srcDir = Path.Combine(baseOutputDir, this.CrossLibName + @"\src");
+ string releaseFileName = Path.Combine(Paths.ReleaseDir, this.OutputFileName);
+ Con.WriteLine("Generating '{0}'...", releaseFileName);
+
+ List<string> files = new List<string>();
+ string gccOptionForLink;
+ string gccOptionForCompile;
+
+ generateGccOptions(srcDir, false, false, out gccOptionForLink, out gccOptionForCompile);
+
+ string targetName = this.Software.ToString();
+
+ // Makefile
+ StringWriter mk = GenerateMakeFileForRelease(srcDir);
+ byte[] mkData = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(mk.ToString()), new byte[] { 10 });
+
+ TarPacker tar = new TarPacker();
+
+ tar.AddFileSimple(targetName + @"\Makefile", mkData, 0, mkData.Length, DateTime.Now);
+
+ // Install Script
+ string isText = File.ReadAllText(Paths.UnixInstallScript);
+ isText = Str.ReplaceStr(isText, "<TITLE>", TitleString, false);
+ byte[] scriptData = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(isText), new byte[] { 10 });
+ tar.AddFileSimple(targetName + @"\.install.sh", scriptData, 0, scriptData.Length, DateTime.Now);
+
+ // EULA
+ Encoding enc = Str.Utf8Encoding;
+
+ if (true)
+ {
+ string srcData = File.ReadAllText(Path.Combine(Paths.BinDirName, @"hamcore\eula.txt"),
+ enc);
+
+ byte[] destData = enc.GetBytes(srcData);
+
+ tar.AddFileSimple(targetName + @"\" + "ReadMeFirst_License.txt", destData, 0, destData.Length, DateTime.Now);
+ }
+
+ if (true)
+ {
+ string srcData = File.ReadAllText(Path.Combine(Paths.BinDirName, @"hamcore\warning_ja.txt"),
+ enc);
+
+ byte[] destData = enc.GetBytes(srcData);
+
+ tar.AddFileSimple(targetName + @"\" + "ReadMeFirst_Important_Notices_ja.txt", destData, 0, destData.Length, DateTime.Now);
+ }
+
+ if (true)
+ {
+ string srcData = File.ReadAllText(Path.Combine(Paths.BinDirName, @"hamcore\warning_en.txt"),
+ enc);
+
+ byte[] destData = enc.GetBytes(srcData);
+
+ tar.AddFileSimple(targetName + @"\" + "ReadMeFirst_Important_Notices_en.txt", destData, 0, destData.Length, DateTime.Now);
+ }
+
+
+ // Codes
+ string[] dirs =
+ {
+ Path.Combine(srcDir, "code"),
+ Path.Combine(srcDir, "lib"),
+ };
+
+ foreach (string dir in dirs)
+ {
+ string[] fileList = Directory.GetFiles(dir, "*.a", SearchOption.TopDirectoryOnly);
+
+ if (Path.GetFileName(dir).Equals("code", StringComparison.InvariantCultureIgnoreCase))
+ {
+ fileList = new string[]
+ {
+ Path.Combine(dir, string.Format("{0}.a", this.Software.ToString())),
+ Path.Combine(dir, "vpncmd.a"),
+ };
+ }
+
+ foreach (string fileName in fileList)
+ {
+ if (Str.StrCmpi(Path.GetFileName(fileName), "libpcap.a") == false)
+ {
+ // Libpcap.a is not included in the release
+ byte[] fileData = File.ReadAllBytes(fileName);
+
+ tar.AddFileSimple(targetName + @"\" + IO.GetRelativeFileName(fileName, srcDir),
+ fileData, 0, fileData.Length, DateTime.Now);
+ }
+ }
+ }
+
+ // License file
+ byte[] lsFileData = File.ReadAllBytes(Path.Combine(CrossLibBaseDir, @"License.txt"));
+ tar.AddFileSimple(targetName + @"\lib\License.txt", lsFileData, 0, lsFileData.Length, DateTime.Now);
+
+ // HamCore
+ byte[] hcData = File.ReadAllBytes(Path.Combine(Paths.BaseDirName, string.Format(@"bin\BuiltHamcoreFiles\hamcore_unix\hamcore.se2")));
+ tar.AddFileSimple(targetName + @"\hamcore.se2", hcData, 0, hcData.Length, DateTime.Now);
+
+ // Generate a tar
+ tar.Finish();
+ byte[] tarData = tar.CompressToGZip();
+
+ File.WriteAllBytes(releaseFileName, tarData);
+
+ Con.WriteLine("Finished.");
+ }
+
+ // Build by cross-compiler
+ public virtual void BuildWithCrossCompiler(string baseOutputDir)
+ {
+ // Create a batch file
+ string outDir = Path.Combine(baseOutputDir, this.CrossLibName);
+ string outSrcDir = Path.Combine(outDir, "src");
+
+ try
+ {
+ string xcDir = Path.Combine(Path.Combine(Paths.CrossCompilerBaseDir, this.CrossCompilerName), "bin");
+
+ if (Directory.Exists(xcDir) == false)
+ {
+ throw new ApplicationException(string.Format("dir '{0}' not found.", xcDir));
+ }
+
+ string batFileName = Path.Combine(outSrcDir, "cross_build.cmd");
+ StreamWriter w = new StreamWriter(batFileName, false, Str.ShiftJisEncoding);
+ w.WriteLine("SET PATH={0};%PATH%", xcDir);
+ w.WriteLine();
+ w.WriteLine(outSrcDir.Substring(0, 2));
+ w.WriteLine("CD {0}", outSrcDir);
+ w.WriteLine();
+ w.WriteLine("make clean");
+ w.WriteLine("make");
+ w.WriteLine();
+ w.WriteLine("EXIT /B %ERRORLEVEL%");
+ w.Close();
+
+ Semaphore sem = new Semaphore(BuildConfig.NumMultipleCompileTasks, BuildConfig.NumMultipleCompileTasks, "vpn_build_cross");
+ Con.WriteLine("Waiting for Semaphore...");
+ sem.WaitOne();
+ Con.WriteLine("Done.");
+ try
+ {
+ Win32BuildUtil.ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", batFileName));
+ }
+ finally
+ {
+ sem.Release();
+ }
+ }
+ catch
+ {
+ string[] files = Directory.GetFiles(Path.Combine(outSrcDir, "code"), "*.a", SearchOption.AllDirectories);
+ foreach (string file in files)
+ {
+ try
+ {
+ File.Delete(file);
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ // SrcKit file name
+ public string SrcKitFileName
+ {
+ get
+ {
+ int build, version;
+ string name;
+ DateTime date;
+ Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+ return string.Format("{0}-{3}-{1}.tar.gz", "srckit", this.CrossLibName,
+ Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime),
+ build);
+ }
+ }
+
+ // Copy the source code
+ public virtual void CopyUnixSrc(string baseOutputDir)
+ {
+ // Generate an Output directory name
+ string outDir = baseOutputDir;
+ string outSrcDir = baseOutputDir;
+ Con.WriteLine("BuildSrcKit for '{0}'...", this.IDString);
+ Con.WriteLine("BuildSrcKit Output Dir = '{0}'.", outDir);
+
+ string tsFile = Path.Combine(outDir, "TimeStamp.txt");
+ string timeStamp = Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime);
+ Con.WriteLine("timestamp={0}", timeStamp);
+
+ if (Directory.Exists(outDir))
+ {
+ }
+ else
+ {
+ Directory.CreateDirectory(outDir);
+ }
+
+ // Copy the source code
+ foreach (string srcDirName in SrcDirNameList)
+ {
+ string srcFullPath = Path.Combine(Paths.BaseDirName, srcDirName);
+ string destFullPath = Path.Combine(outSrcDir, srcDirName);
+
+ IO.CopyDir(srcFullPath, destFullPath, new IO.CopyDirPreCopyDelegate(CopySrcFilesDelegate), false, true, true, true, true);
+ }
+ IO.FileCopy(Path.Combine(Paths.BaseDirName, "CurrentBuild.txt"), Path.Combine(outSrcDir, "CurrentBuild.txt"), true, false);
+ }
+
+ // Build SrcKit
+ public virtual bool BuildSrcKit(string baseOutputDir, bool debugMode)
+ {
+ // Generate an Output directory name
+ string outDir = Path.Combine(baseOutputDir, this.CrossLibName);
+ string outSrcDir = Path.Combine(outDir, "src");
+ Con.WriteLine("BuildSrcKit for '{0}'...", this.IDString);
+ Con.WriteLine("CrossLib Name: '{0}'.", this.CrossLibName);
+ Con.WriteLine("BuildSrcKit Output Dir = '{0}'.", outDir);
+
+ string tsFile = Path.Combine(outDir, "TimeStamp.txt");
+ string timeStamp = Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime);
+ Con.WriteLine("timestamp={0}", timeStamp);
+
+ if (Directory.Exists(outDir))
+ {
+ bool ok = false;
+ // See TimeStamp.txt file if the directory already exists
+ try
+ {
+ string[] ts = File.ReadAllLines(tsFile);
+ if (ts[0] == timeStamp)
+ {
+ ok = true;
+ }
+ }
+ catch
+ {
+ }
+
+ if (ok)
+ {
+ Con.WriteLine("Skipped for '{0}'.", this.IDString);
+ return false;
+ }
+ }
+ else
+ {
+ Directory.CreateDirectory(outDir);
+ }
+
+ // Copy the source code
+ foreach (string srcDirName in SrcDirNameList)
+ {
+ string srcFullPath = Path.Combine(Paths.BaseDirName, srcDirName);
+ string destFullPath = Path.Combine(outSrcDir, srcDirName);
+ bool delete_bom = true;
+
+ if (Str.InStr(srcDirName, "\\hamcore"))
+ {
+ delete_bom = false;
+ }
+
+ IO.CopyDir(srcFullPath, destFullPath, new IO.CopyDirPreCopyDelegate(CopySrcFilesDelegate), false, true, true, delete_bom);
+ }
+ IO.FileCopy(Path.Combine(Paths.BaseDirName, "CurrentBuild.txt"), Path.Combine(outSrcDir, "CurrentBuild.txt"), true, false);
+ IO.FileCopy(Path.Combine(Paths.BaseDirName, "GlobalConst.h"), Path.Combine(outSrcDir, "GlobalConst.h"), true, false);
+ IO.FileCopy(Path.Combine(Paths.BaseDirName, @"DebugFiles\Replace.h"), Path.Combine(outSrcDir, "Replace.h"), true, false);
+ IO.FileCopy(Path.Combine(Paths.BaseDirName, @"bin\BuiltHamcoreFiles\hamcore_unix\hamcore.se2"),
+ Path.Combine(outSrcDir, @"bin\hamcore.se2"), true, false);
+
+ // Copy Crosslibs
+ IO.CopyDir(Path.Combine(this.CrossLibBaseDir, this.CrossLibName), Path.Combine(outSrcDir, @"lib"),
+ delegate(FileInfo fi)
+ {
+ if (fi.DirectoryName.IndexOf(@".svn", StringComparison.InvariantCultureIgnoreCase) != -1)
+ {
+ return false;
+ }
+ return true;
+ }, false, true, true, false);
+
+ // Generate Makefile for compilation
+ byte[] makeFileDataForCross = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(GenerateMakeFileForCompile(outSrcDir, debugMode, true).ToString()), new byte[] { 10, });
+ byte[] makeFileDataForSelf = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(GenerateMakeFileForCompile(outSrcDir, debugMode, false).ToString()), new byte[] { 10, });
+
+ string makeFileName = Path.Combine(outSrcDir, "Makefile");
+ File.WriteAllBytes(makeFileName, makeFileDataForCross);
+
+ // TimeStamp.txt
+ File.WriteAllText(tsFile, timeStamp);
+
+ // Create a tar.gz
+ string tarGzFileName = Path.Combine(outSrcDir, this.SrcKitFileName);
+ Con.WriteLine("Creating '{0}'...", tarGzFileName);
+ List<string> files = new List<string>();
+
+ foreach (string srcDirName in Util.CombineArray<string>(SrcDirNameList, new string[] { "lib" }))
+ {
+ string dirFullPath = Path.Combine(outSrcDir, srcDirName);
+ string[] fileList = Directory.GetFiles(dirFullPath, "*",
+ srcDirName.Equals("lib", StringComparison.InvariantCultureIgnoreCase) ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories);
+ foreach (string fileName in fileList)
+ {
+ files.Add(fileName);
+ }
+ }
+ files.Add(Path.Combine(outSrcDir, @"CurrentBuild.txt"));
+ files.Add(Path.Combine(outSrcDir, @"bin\hamcore.se2"));
+ files.Add(Path.Combine(outSrcDir, @"Replace.h"));
+ files.Add(Path.Combine(outSrcDir, @"GlobalConst.h"));
+
+ files.Sort();
+ TarPacker tar = new TarPacker();
+ foreach (string file in files)
+ {
+ byte[] fileData = File.ReadAllBytes(file);
+ tar.AddFileSimple(@"src\" + IO.GetRelativeFileName(file, outSrcDir),
+ fileData,
+ 0, fileData.Length, File.GetLastWriteTime(file), "0000750", "0000640");
+ }
+ tar.AddFileSimple(@"src\Makefile", makeFileDataForSelf, 0, makeFileDataForSelf.Length, DateTime.Now, "0000750", "0000640");
+ tar.Finish();
+ byte[] tarGzData = tar.CompressToGZip();
+ File.WriteAllBytes(tarGzFileName, tarGzData);
+
+ IO.MakeDir(Paths.ReleaseSrckitDir);
+ File.WriteAllBytes(Path.Combine(Paths.ReleaseSrckitDir, this.SrcKitFileName), tarGzData);
+
+ Con.WriteLine("Completed.");
+
+ return true;
+ }
+
+ // Compilation settings
+ public string Compiler = "gcc";
+ public List<string> GccMacros = new List<string>();
+
+ // Create a Makefile for release
+ public virtual StringWriter GenerateMakeFileForRelease(string srcDir)
+ {
+ string gccOptionForLink;
+ string gccOptionForCompile;
+
+ generateGccOptions(srcDir, false, false, out gccOptionForLink, out gccOptionForCompile);
+
+ string codeDir = Path.Combine(srcDir, "code");
+ string libDir = Path.Combine(srcDir, "lib");
+
+ string[] codeFiles = Directory.GetFiles(codeDir, "*.a");
+ string[] libFiles = Directory.GetFiles(libDir, "*.a");
+
+ StringWriter sr = new StringWriter();
+ sr.WriteLine("# {0}", this.TitleString);
+ sr.WriteLine("# Makefile");
+ sr.WriteLine("# ");
+
+#if !BU_SOFTETHER
+ sr.WriteLine("# Copyright (c) SoftEther Corporation. All Rights Reserved.");
+#else
+ sr.WriteLine("# Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.");
+#endif
+ sr.WriteLine("# Platform: {0}", this.CrossLibName);
+ sr.WriteLine();
+ sr.WriteLine("CC={0}", this.Compiler);
+ sr.WriteLine("OPTIONS={0}", gccOptionForLink);
+ sr.WriteLine();
+ sr.WriteLine("default:");
+ sr.WriteLine("\t@./.install.sh");
+ sr.WriteLine();
+ sr.WriteLine("# NOTE:");
+ sr.WriteLine("# You have to read and agree the license agreement at the same directory");
+ sr.WriteLine("# before using this software.");
+ sr.WriteLine();
+ sr.WriteLine("i_read_and_agree_the_license_agreement:");
+
+ sr.WriteLine("\t@echo \"Preparing {0}...\"", BuildHelper.GetSoftwareTitle(this.Software));
+
+ foreach (string filename in libFiles)
+ {
+ sr.WriteLine("\t-ranlib lib/{0}", Path.GetFileName(filename));
+ }
+
+ sr.WriteLine("\t-ranlib code/{0}.a", this.Software.ToString());
+ sr.WriteLine("\t$(CC) code/{0}.a $(OPTIONS) -o {0}", this.Software.ToString());
+
+ sr.WriteLine("\t-ranlib code/{0}.a", "vpncmd");
+ sr.WriteLine("\t$(CC) code/{0}.a $(OPTIONS) -o {0}", "vpncmd");
+
+ if (this.Software == Software.vpnserver_vpnbridge || this.Software == Software.vpnbridge || this.Software == Software.vpnserver)
+ {
+ sr.WriteLine("\t./vpncmd /tool /cmd:Check");
+ }
+
+ Language[] langs = BuildHelper.GetLanguageList();
+
+ sr.WriteLine("\t@echo");
+ sr.WriteLine("\t@echo \"--------------------------------------------------------------------\"");
+ sr.WriteLine("\t@echo \"The preparation of {0} is completed !\"", BuildHelper.GetSoftwareTitle(this.Software));
+ sr.WriteLine("\t@echo");
+ sr.WriteLine("\t@echo");
+ sr.WriteLine("\t@echo \"*** How to switch the display language of the {0} Service ***\"", BuildHelper.GetSoftwareTitle(this.Software));
+ sr.WriteLine("\t@echo \"{0} supports the following languages:\"", BuildHelper.GetSoftwareTitle(this.Software));
+
+ foreach (Language lang in langs)
+ {
+ sr.WriteLine("\t@echo \" - {0}\"", lang.Title);
+ }
+
+ sr.WriteLine("\t@echo");
+ sr.WriteLine("\t@echo \"You can choose your prefered language of {0} at any time.\"", BuildHelper.GetSoftwareTitle(this.Software));
+ sr.WriteLine("\t@echo \"To switch the current language, open and edit the 'lang.config' file.\"");
+
+ sr.WriteLine("\t@echo");
+ sr.WriteLine("\t@echo");
+
+ sr.WriteLine("\t@echo \"*** How to start the {0} Service ***\"", BuildHelper.GetSoftwareTitle(this.Software));
+ sr.WriteLine("\t@echo");
+
+ sr.WriteLine("\t@echo \"Please execute './{0} start' to run the {1} Background Service.\"", this.Software.ToString(), BuildHelper.GetSoftwareTitle(this.Software));
+#if !BU_SOFTETHER
+ sr.WriteLine("\t@echo \"And please execute './vpncmd' to run the PacketiX VPN Command-Line Utility to configure {0}.\"", BuildHelper.GetSoftwareTitle(this.Software));
+#else
+ sr.WriteLine("\t@echo \"And please execute './vpncmd' to run the SoftEther VPN Command-Line Utility to configure {0}.\"", BuildHelper.GetSoftwareTitle(this.Software));
+#endif
+ sr.WriteLine("\t@echo \"Of course, you can use the VPN Server Manager GUI Application for Windows on the other Windows PC in order to configure the {0} remotely.\"", BuildHelper.GetSoftwareTitle(this.Software));
+
+ sr.WriteLine("\t@echo \"--------------------------------------------------------------------\"");
+ sr.WriteLine("\t@echo");
+
+ sr.WriteLine();
+
+ sr.WriteLine("clean:");
+ sr.WriteLine("\trm -f {0}", this.Software.ToString());
+ sr.WriteLine("\trm -f {0}", "vpncmd");
+ sr.WriteLine();
+
+ return sr;
+ }
+
+ // Generate Makefile for compilation
+ public virtual StringWriter GenerateMakeFileForCompile(string outDir, bool debugMode, bool crossCompile)
+ {
+ string[] programNames =
+ {
+ "Ham",
+ "vpnserver",
+ "vpnbridge",
+ "vpnclient",
+ "vpncmd",
+ };
+
+ string gccOptionForLinkDebug, gccOptionForLinkRelease;
+ string gccOptionForCompileDebug, gccOptionForCompileRelease;
+
+ generateGccOptions(outDir, false, crossCompile, out gccOptionForLinkRelease, out gccOptionForCompileRelease);
+ generateGccOptions(outDir, true, crossCompile, out gccOptionForLinkDebug, out gccOptionForCompileDebug);
+
+ StringWriter sr = new StringWriter();
+#if !BU_SOFTETHER
+ sr.WriteLine("# PacketiX VPN Source Code");
+ sr.WriteLine("# Copyright (c) SoftEther Corporation. All Rights Reserved.");
+#else
+ sr.WriteLine("# SoftEther VPN Source Code");
+ sr.WriteLine("# Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.");
+#endif
+ sr.WriteLine("# Platform: {0}", this.CrossLibName);
+ sr.WriteLine();
+
+ // Variable declaration
+ sr.WriteLine("# Variables");
+ sr.WriteLine("CC={0}", this.Compiler);
+ sr.WriteLine();
+ sr.WriteLine("OPTIONS_COMPILE_DEBUG={0}", gccOptionForCompileDebug);
+ sr.WriteLine();
+ sr.WriteLine("OPTIONS_LINK_DEBUG={0}", gccOptionForLinkDebug);
+ sr.WriteLine();
+ sr.WriteLine("OPTIONS_COMPILE_RELEASE={0}", gccOptionForCompileRelease);
+ sr.WriteLine();
+ sr.WriteLine("OPTIONS_LINK_RELEASE={0}", gccOptionForLinkRelease);
+ sr.WriteLine();
+ sr.WriteLine("ifeq ($(DEBUG),YES)");
+ sr.WriteLine("\tOPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)");
+ sr.WriteLine("\tOPTIONS_LINK=$(OPTIONS_LINK_DEBUG)");
+ sr.WriteLine("else");
+ sr.WriteLine("\tOPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)");
+ sr.WriteLine("\tOPTIONS_LINK=$(OPTIONS_LINK_RELEASE)");
+ sr.WriteLine("endif");
+ sr.WriteLine();
+
+ string[] mayaquaHeaders = generateFileList(Path.Combine(outDir, "Mayaqua"), outDir, "*.h");
+ string[] cedarHeaders = generateFileList(Path.Combine(outDir, "Cedar"), outDir, "*.h");
+ string[] mayaquaSrcs = generateFileList(Path.Combine(outDir, "Mayaqua"), outDir, "*.c");
+ string[] cedarSrcs = generateFileList(Path.Combine(outDir, "Cedar"), outDir, "*.c");
+ List<string> mayaquaObjs = new List<string>();
+ List<string> cedarObjs = new List<string>();
+ List<string> progSrcs = new List<string>();
+ List<string> progObjs = new List<string>();
+ List<string> progAs = new List<string>();
+ List<string> progBins = new List<string>();
+
+ foreach (string progName in programNames)
+ {
+ string progName2 = progName;
+
+ if (progName2.Equals("vpnclient", StringComparison.InvariantCultureIgnoreCase) == false)
+ {
+ progSrcs.Add(string.Format("{0}/{0}.c", progName2));
+ }
+ else
+ {
+ progSrcs.Add(string.Format("{0}/vpncsvc.c", progName2));
+ }
+ progObjs.Add(string.Format("object/{0}.o", progName2));
+ progAs.Add(string.Format("code/{0}.a", progName));
+ progBins.Add(string.Format("bin/{0}", progName.ToLower()));
+ }
+
+ int i;
+ for (i = 0; i < mayaquaSrcs.Length; i++)
+ {
+ mayaquaObjs.Add(string.Format("object/Mayaqua/{0}.o", Path.GetFileNameWithoutExtension(mayaquaSrcs[i])));
+ }
+ for (i = 0; i < cedarSrcs.Length; i++)
+ {
+ cedarObjs.Add(string.Format("object/Cedar/{0}.o", Path.GetFileNameWithoutExtension(cedarSrcs[i])));
+ }
+ sr.WriteLine("# Files");
+ sr.WriteLine("HEADERS_MAYAQUA={0}", Str.CombineStringArray(mayaquaHeaders, " "));
+ sr.WriteLine("HEADERS_CEDAR={0}", Str.CombineStringArray(cedarHeaders, " "));
+ sr.WriteLine("OBJECTS_MAYAQUA={0}", Str.CombineStringArray(mayaquaObjs.ToArray(), " "));
+ sr.WriteLine("OBJECTS_CEDAR={0}", Str.CombineStringArray(cedarObjs.ToArray(), " "));
+ sr.WriteLine();
+
+ // Behavior
+ sr.WriteLine("# Build Action");
+ sr.WriteLine("default:\tbuild");
+ sr.WriteLine();
+ sr.WriteLine("build:\t$(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) {0}", Str.CombineStringArray(progBins.ToArray(), " "));
+ sr.WriteLine();
+
+ sr.WriteLine("# Mayaqua Kernel Code");
+ for (i = 0; i < mayaquaSrcs.Length; i++)
+ {
+ sr.WriteLine("{0}: {1} $(HEADERS_MAYAQUA)", mayaquaObjs[i], mayaquaSrcs[i]);
+ if (i == 0)
+ {
+ sr.WriteLine("\t@mkdir -p object/");
+ sr.WriteLine("\t@mkdir -p object/Mayaqua/");
+ sr.WriteLine("\t@mkdir -p object/Cedar/");
+ sr.WriteLine("\t@mkdir -p code/");
+ }
+ sr.WriteLine("\t$(CC) $(OPTIONS_COMPILE) -c {0} -o {1}", mayaquaSrcs[i], mayaquaObjs[i]);
+ sr.WriteLine();
+ }
+
+ sr.WriteLine("# Cedar Communication Module Code");
+ for (i = 0; i < cedarSrcs.Length; i++)
+ {
+ string line = string.Format("{0}: {1} $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)", cedarObjs[i], cedarSrcs[i]);
+ if (cedarSrcs[i].EndsWith("Bridge.c", StringComparison.InvariantCultureIgnoreCase))
+ {
+ line += " Cedar/BridgeUnix.c";
+ }
+ sr.WriteLine(line);
+ sr.WriteLine("\t$(CC) $(OPTIONS_COMPILE) -c {0} -o {1}", cedarSrcs[i], cedarObjs[i]);
+ sr.WriteLine();
+ }
+
+ for (i = 0; i < programNames.Length; i++)
+ {
+ sr.WriteLine("# {0}", programNames[i]);
+ sr.WriteLine("{0}: {1} $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)",
+ progBins[i], progAs[i]);
+ sr.WriteLine("\t$(CC) {0} $(OPTIONS_LINK) -o {1}", progAs[i], progBins[i]);
+ sr.WriteLine();
+ sr.WriteLine("{0}: {1} $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)",
+ progAs[i], progObjs[i]);
+ sr.WriteLine("\trm -f {0}", progAs[i]);
+ sr.WriteLine("\tar r {0} $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) {1}", progAs[i], progObjs[i]);
+ sr.WriteLine("\tranlib {0}", progAs[i]);
+ sr.WriteLine();
+ sr.WriteLine("{0}: {1} $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)",
+ progObjs[i], progSrcs[i]);
+ sr.WriteLine("\t$(CC) $(OPTIONS_COMPILE) -c {0} -o {1}", progSrcs[i], progObjs[i]);
+ sr.WriteLine();
+ }
+
+ sr.WriteLine("# Clean");
+ sr.WriteLine("clean:");
+ sr.WriteLine("\t-rm -f $(OBJECTS_MAYAQUA)");
+ sr.WriteLine("\t-rm -f $(OBJECTS_CEDAR)");
+ for (i = 0; i < programNames.Length; i++)
+ {
+ sr.WriteLine("\t-rm -f {0}", progObjs[i]);
+ sr.WriteLine("\t-rm -f {0}", progAs[i]);
+ sr.WriteLine("\t-rm -f {0}", progBins[i]);
+ }
+ sr.WriteLine();
+
+ sr.WriteLine("# Help Strings");
+ sr.WriteLine("help:");
+ sr.WriteLine("\t@echo \"make [DEBUG=YES]\"");
+ sr.WriteLine();
+
+ return sr;
+ }
+
+ // Create a file list
+ string[] generateFileList(string dir, string baseDir, string searchPattern)
+ {
+ string[] files = Directory.GetFiles(dir, searchPattern, SearchOption.AllDirectories);
+ List<string> ret = new List<string>();
+
+ foreach (string file in files)
+ {
+ string name = IO.GetRelativeFileName(file, baseDir).Replace(@"\", "/");
+ ret.Add(name);
+ }
+
+ ret.Sort();
+
+ return ret.ToArray();
+ }
+
+ // Generate the GCC option string
+ void generateGccOptions(string outDir, bool debugMode, bool crossCompile, out string gccOptionForLink, out string gccOptionForCompile)
+ {
+ List<string> macros = new List<string>(this.GccMacros.ToArray());
+ List<string> includes = new List<string>();
+ List<string> options = new List<string>();
+ List<string> libs = new List<string>();
+
+ // Determine the macro
+ if (debugMode)
+ {
+ macros.Add("_DEBUG");
+ macros.Add("DEBUG");
+ }
+ else
+ {
+ macros.Add("NDEBUG");
+ macros.Add("VPN_SPEED");
+ macros.Add("MAYAQUA_REPLACE");
+ }
+
+ macros.Add("UNIX");
+ macros.Add("_REENTRANT");
+ macros.Add("REENTRANT");
+ macros.Add("_THREAD_SAFE");
+ macros.Add("_THREADSAFE");
+ macros.Add("THREAD_SAFE");
+ macros.Add("THREADSAFE");
+ macros.Add("_FILE_OFFSET_BITS=64");
+
+ // Decide the include directory
+ includes.Add("./");
+ includes.Add("./Cedar/");
+ includes.Add("./Mayaqua/");
+
+ // Determine options
+ if (debugMode)
+ {
+ options.Add("-g");
+ }
+ else
+ {
+ options.Add("-O2");
+ }
+ options.Add("-fsigned-char");
+ if (this.NoPThreadOption == false)
+ {
+ options.Add("-pthread");
+ }
+ if (this.UseGccBitsOption)
+ {
+ if (this.Cpu.Bits == CPUBits.Bits32)
+ {
+ options.Add("-m32");
+ }
+ else
+ {
+ options.Add("-m64");
+ }
+ }
+
+ // Determine library files
+ string[] libNames =
+ {
+ "libssl",
+ "libcrypto",
+ "libiconv",
+ "libcharset",
+ "libedit",
+ "libncurses",
+ "libz",
+ };
+ foreach (string libName in libNames)
+ {
+ libs.Add(string.Format("lib/{0}.a", libName));
+ }
+
+ if (crossCompile)
+ {
+ if (this.Os == OSList.MacOS)
+ {
+ // Include libpcap.a only when cross-compiling for Mac OS X
+ libs.Add(string.Format("lib/{0}.a", "libpcap"));
+ }
+ }
+
+ if (this.Os == OSList.Linux)
+ {
+ if (this.Cpu == CpuList.x86 || this.Cpu == CpuList.x64)
+ {
+ // Include libintelaes.a only for x86 / x64 in Linux
+ libs.Add(string.Format("lib/{0}.a", "libintelaes"));
+ }
+ }
+
+ gccOptionForCompile = MakeGccOptions(macros.ToArray(), includes.ToArray(), options.ToArray(), null);
+
+ if (crossCompile)
+ {
+ if (Str.IsEmptyStr(this.CrossCompilerOption) == false)
+ {
+ options.Add(this.CrossCompilerOption);
+ }
+ }
+
+ options.Add("-lm");
+
+ if (this.Os == OSList.Solaris)
+ {
+ options.Add("-lrt");
+ options.Add("-lnsl");
+ options.Add("-lsocket");
+ options.Add("-ldl");
+ }
+ else if (this.Os == OSList.Linux)
+ {
+ options.Add("-ldl");
+ options.Add("-lrt");
+ }
+ else if (this.Os == OSList.MacOS)
+ {
+ if (crossCompile == false)
+ {
+ // Include -lpcap for the user environment on Mac OS X
+ options.Add("-lpcap");
+ }
+ }
+
+ if (this.Cpu == CpuList.armeabi)
+ {
+ // Prevent to show a warning on linking in EABI binaries
+ // to EABIHF architecture in ARM
+ options.Add("-Wl,--no-warn-mismatch");
+ }
+
+ options.Add("-lpthread");
+
+ gccOptionForLink = MakeGccOptions(new string[0], new string[0], options.ToArray(), libs.ToArray());
+ }
+
+ public static string MakeGccOptions(string[] macros, string[] includeDirs, string[] options, string[] libs)
+ {
+ List<string> o = new List<string>();
+ foreach (string macro in macros)
+ {
+ o.Add(string.Format("-D{0}", macro));
+ }
+ foreach (string dir in includeDirs)
+ {
+ o.Add(string.Format("-I{0}", dir));
+ }
+ foreach (string opt in options)
+ {
+ o.Add(opt);
+ }
+ if (libs != null)
+ {
+ o.Add("-L./");
+ foreach (string lib in libs)
+ {
+ o.Add(lib);
+ }
+ }
+
+ return Str.CombineStringArray(o.ToArray(), " ");
+ }
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/VpnBuilder.cs b/src/BuildUtil/VpnBuilder.cs
new file mode 100644
index 00000000..c6489c77
--- /dev/null
+++ b/src/BuildUtil/VpnBuilder.cs
@@ -0,0 +1,650 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // Languages
+ public class Language
+ {
+ public int Number;
+ public string Id;
+ public string Title;
+ public string TitleUnicode;
+ public string WindowsLocaleIds;
+ public string UnixLocaleIds;
+ }
+
+ // Build helper class
+ public static class BuildHelper
+ {
+ // loads the language list text file
+ public static Language[] GetLanguageList()
+ {
+ return GetLanguageList(Path.Combine(Paths.BinDirName, @"hamcore\languages.txt"));
+ }
+ public static Language[] GetLanguageList(string filename)
+ {
+ List<Language> ret = new List<Language>();
+ string[] lines = File.ReadAllLines(filename, Str.Utf8Encoding);
+
+ foreach (string line in lines)
+ {
+ string s = line.Trim();
+
+ if (Str.IsEmptyStr(s) == false)
+ {
+ if (s.StartsWith("#", StringComparison.InvariantCultureIgnoreCase) == false)
+ {
+ string[] sps = { " ", "\t", };
+ string[] tokens = s.Split(sps, StringSplitOptions.RemoveEmptyEntries);
+
+ if (tokens.Length == 6)
+ {
+ Language e = new Language();
+
+ e.Number = Str.StrToInt(tokens[0]);
+ e.Id = tokens[1];
+ e.Title = Str.ReplaceStr(tokens[2], "_", " ");
+ e.TitleUnicode = tokens[3];
+ e.WindowsLocaleIds = tokens[4];
+ e.UnixLocaleIds = tokens[5];
+
+ ret.Add(e);
+
+ Con.WriteLine(tokens.Length);
+ }
+ }
+ }
+ }
+
+ return ret.ToArray();
+ }
+
+ // Build
+ public static void BuildMain(BuildSoftware soft, bool debugModeIfUnix)
+ {
+ int version, build;
+ string name;
+ DateTime date;
+
+ string title = Console.Title;
+ Console.Title = string.Format("Building {0}", soft.IDString);
+
+ try
+ {
+ Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ soft.SetBuildNumberVersionName(build, version, name, date);
+
+ Con.WriteLine("Building '{0}' - {1}...", soft.IDString, soft.TitleString);
+
+ BuildSoftwareUnix softUnix = soft as BuildSoftwareUnix;
+
+ if (softUnix == null)
+ {
+ soft.Build();
+ }
+ else
+ {
+ softUnix.Build(debugModeIfUnix);
+ }
+ }
+ finally
+ {
+ Console.Title = title;
+ }
+ }
+
+ // Convert the number to a version number
+ public static string VersionIntToString(int version)
+ {
+ return string.Format("{0}.{1:D2}", version / 100, version % 100);
+ }
+
+ // Get a product list that is included in the software
+ public static string GetSoftwareProductList(Software soft)
+ {
+ string ret = "";
+
+ switch (soft)
+ {
+ case Software.vpnbridge:
+ ret = "PacketiX VPN Bridge";
+ break;
+
+ case Software.vpnclient:
+ ret = "PacketiX VPN Client, PacketiX VPN Command-Line Admin Utility (vpncmd)";
+ break;
+
+ case Software.vpnserver:
+ ret = "PacketiX VPN Server, PacketiX VPN Command-Line Admin Utility (vpncmd)";
+ break;
+
+ case Software.vpnserver_vpnbridge:
+ ret = "PacketiX VPN Server, PacketiX VPN Bridge, PacketiX VPN Server Manager for Windows, PacketiX VPN Command-Line Admin Utility (vpncmd)";
+ break;
+
+ default:
+ throw new ApplicationException("invalid soft.");
+ }
+
+#if BU_SOFTETHER
+ ret = Str.ReplaceStr(ret, "PacketiX", "SoftEther", false);
+#endif
+
+ return ret;
+ }
+
+ // Get the title of the software
+ public static string GetSoftwareTitle(Software soft)
+ {
+ string ret = "";
+
+ switch (soft)
+ {
+ case Software.vpnbridge:
+ ret = "PacketiX VPN Bridge";
+ break;
+
+ case Software.vpnclient:
+ ret = "PacketiX VPN Client";
+ break;
+
+ case Software.vpnserver:
+ ret = "PacketiX VPN Server";
+ break;
+
+ case Software.vpnserver_vpnbridge:
+ ret = "PacketiX VPN Server and VPN Bridge";
+ break;
+
+ default:
+ throw new ApplicationException("invalid soft.");
+ }
+
+#if BU_SOFTETHER
+ ret = Str.ReplaceStr(ret, "PacketiX", "SoftEther", false);
+#endif
+
+ return ret;
+ }
+ }
+
+ // Basic path information
+ public static class Paths
+ {
+ public static readonly string ExeFileName = Env.ExeFileName;
+ public static readonly string ExeDirName = Env.ExeFileDir;
+ public static readonly string BinDirName = ExeDirName;
+ public static readonly string BaseDirName = IO.NormalizePath(Path.Combine(BinDirName, @"..\"));
+ public static readonly string UtilityDirName = IO.NormalizePath(Path.Combine(BinDirName, @"..\BuildFiles\Utility"));
+
+#if !BU_SOFTETHER
+ // PacketiX VPN (build by SoftEther)
+ public static readonly string VPN4SolutionFileName = Path.Combine(BaseDirName, "VPN4.sln");
+ public static readonly string DebugSnapshotBaseDir = @"S:\SE4\DebugFilesSnapshot";
+ public static readonly string ReleaseDestDir = @"s:\SE4\Releases";
+ public const string Prefix = "";
+#else
+#if !BU_OSS
+ // SoftEther VPN (build by SoftEther)
+ public static readonly string VPN4SolutionFileName = Path.Combine(BaseDirName, "SEVPN.sln");
+ public static readonly string DebugSnapshotBaseDir = @"S:\SE4\DebugFilesSnapshot_SEVPN";
+ public static readonly string ReleaseDestDir = @"s:\SE4\Releases_SEVPN";
+ public const string Prefix = "softether-";
+#else
+ // SoftEther VPN (build by Open Source Developers)
+ public static readonly string VPN4SolutionFileName = Path.Combine(BaseDirName, "SEVPN.sln");
+ public static readonly string DebugSnapshotBaseDir = IO.NormalizePath(Path.Combine(BaseDirName, @"..\output\debug"));
+ public static readonly string ReleaseDestDir = IO.NormalizePath(Path.Combine(BaseDirName, @"..\output\pkg"));
+ public const string Prefix = "softether_open-";
+#endif
+#endif
+
+ public static readonly string ReleaseDestDir_SEVPN = @"s:\SE4\Releases_SEVPN";
+
+ public static readonly string BuildHamcoreFilesDirName = Path.Combine(BinDirName, "BuiltHamcoreFiles");
+ public static readonly string VisualStudioVCDir;
+ public static readonly string VisualStudioVCBatchFileName;
+ public static readonly string DotNetFramework35Dir;
+ public static readonly string MSBuildFileName;
+ public static readonly string TmpDirName;
+ public static readonly DateTime StartDateTime = DateTime.Now;
+ public static readonly string StartDateTimeStr;
+ public static readonly string CmdFileName;
+ public static readonly string ManifestsDir = Path.Combine(BaseDirName, @"BuildFiles\Manifests");
+ public static readonly string XCopyExeFileName = Path.Combine(Env.SystemDir, "xcopy.exe");
+ public static readonly string ReleaseDir = Path.Combine(BaseDirName, @"tmp\Release");
+ public static readonly string ReleaseSrckitDir = Path.Combine(BaseDirName, @"tmp\ReleaseSrcKit");
+ public static readonly string StringsDir = Path.Combine(BaseDirName, @"BuildFiles\Strings");
+ public static readonly string CrossCompilerBaseDir = @"S:\CommomDev\xc";
+ public static readonly string UnixInstallScript = Path.Combine(BaseDirName, @"BuildFiles\UnixFiles\InstallScript.txt");
+ public static readonly string OssCommentsFile = Path.Combine(StringsDir, "OssComments.txt");
+ public static readonly string AutorunSrcDir = IO.NormalizePath(Path.Combine(BaseDirName, @"..\Autorun"));
+ public static readonly string MicrosoftSDKDir;
+ public static readonly string MakeCatFilename;
+ public static readonly string RcFilename;
+ public static readonly string SoftEtherBuildDir = Env.SystemDir.Substring(0, 2) + @"\tmp\softether_build_dir";
+ public static readonly string OpenSourceDestDir = Env.SystemDir.Substring(0, 2) + @"\tmp\softether_oss_dest_dir";
+
+ // Initialize
+ static Paths()
+ {
+ // Starting date and time string
+ Paths.StartDateTimeStr = Str.DateTimeToStrShort(Paths.StartDateTime);
+
+ // Check whether the execution path is the bin directory in the VPN directory
+ if (Paths.BinDirName.EndsWith(@"\bin", StringComparison.InvariantCultureIgnoreCase) == false)
+ {
+ throw new ApplicationException(string.Format("'{0}' is not a VPN bin directory.", Paths.BinDirName));
+ }
+ if (File.Exists(Paths.VPN4SolutionFileName) == false)
+ {
+ throw new ApplicationException(string.Format("'{0}' is not a VPN base directory.", Paths.BaseDirName));
+ }
+
+ // Get the VC++ directory
+ // Visual Studio 2008
+ Paths.VisualStudioVCDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VC", "ProductDir"));
+ if (Str.IsEmptyStr(Paths.VisualStudioVCDir))
+ {
+ throw new ApplicationException("Visual C++ directory not found.\n");
+ }
+ if (Directory.Exists(Paths.VisualStudioVCDir) == false)
+ {
+ throw new ApplicationException(string.Format("Directory '{0}' not found.", Paths.VisualStudioVCDir));
+ }
+
+ // Get the VC++ batch file name
+ Paths.VisualStudioVCBatchFileName = Path.Combine(Paths.VisualStudioVCDir, "vcvarsall.bat");
+ if (File.Exists(Paths.VisualStudioVCBatchFileName) == false)
+ {
+ throw new ApplicationException(string.Format("File '{0}' not found.", Paths.VisualStudioVCBatchFileName));
+ }
+
+ bool x86_dir = false;
+
+ // Get Microsoft SDK 6.0a directory
+ Paths.MicrosoftSDKDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A", "InstallationFolder"));
+
+ // Get makecat.exe file name
+ Paths.MakeCatFilename = Path.Combine(Paths.MicrosoftSDKDir, @"bin\" + (x86_dir ? @"x86\" : "") + "makecat.exe");
+
+ // Get the rc.exe file name
+ Paths.RcFilename = Path.Combine(Paths.MicrosoftSDKDir, @"bin\" + (x86_dir ? @"x86\" : "") + "rc.exe");
+
+ // Get the cmd.exe file name
+ Paths.CmdFileName = Path.Combine(Env.SystemDir, "cmd.exe");
+ if (File.Exists(Paths.CmdFileName) == false)
+ {
+ throw new ApplicationException(string.Format("File '{0}' not found.", Paths.CmdFileName));
+ }
+
+ // Get .NET Framework 3.5 directory
+ Paths.DotNetFramework35Dir = Path.Combine(Env.WindowsDir, @"Microsoft.NET\Framework\v3.5");
+
+ // Get msbuild.exe directory
+ Paths.MSBuildFileName = Path.Combine(Paths.DotNetFramework35Dir, "MSBuild.exe");
+ if (File.Exists(Paths.MSBuildFileName) == false)
+ {
+ throw new ApplicationException(string.Format("File '{0}' not found.", Paths.MSBuildFileName));
+ }
+
+ // Get the TMP directory
+ Paths.TmpDirName = Path.Combine(Paths.BaseDirName, "tmp");
+ if (Directory.Exists(Paths.TmpDirName) == false)
+ {
+ Directory.CreateDirectory(Paths.TmpDirName);
+ }
+ }
+
+ public static void DeleteAllReleaseTarGz()
+ {
+ if (Directory.Exists(Paths.ReleaseDir))
+ {
+ string[] files = Directory.GetFiles(Paths.ReleaseDir, "*.gz", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ File.Delete(file);
+ }
+ }
+
+ if (Directory.Exists(Paths.ReleaseSrckitDir))
+ {
+ string[] files = Directory.GetFiles(Paths.ReleaseSrckitDir, "*.gz", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ File.Delete(file);
+ }
+ }
+ }
+
+ public static void DeleteAllReleaseAdminKits()
+ {
+ if (Directory.Exists(Paths.ReleaseDir))
+ {
+ string[] files = Directory.GetFiles(Paths.ReleaseDir, "*.zip", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ if (Str.InStr(file, "vpnadminpak"))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+ }
+
+ public static void DeleteAllReleaseManuals()
+ {
+ if (Directory.Exists(Paths.ReleaseDir))
+ {
+ string[] files = Directory.GetFiles(Paths.ReleaseDir, "*", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ if (Str.InStr(file, "vpnmanual"))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+ }
+
+ public static void DeleteAllReleaseExe()
+ {
+ if (Directory.Exists(Paths.ReleaseDir))
+ {
+ string[] files = Directory.GetFiles(Paths.ReleaseDir, "*.exe", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ if (Str.InStr(file, "vpnmanual") == false)
+ {
+ File.Delete(file);
+ }
+ }
+ }
+ }
+ }
+
+ // HamCore build utility
+ public static class HamCoreBuildUtil
+ {
+ // Identify whether a file is necessary only in the Win32
+ public static bool IsFileForOnlyWin32(string filename)
+ {
+ string[] filesOnlyWin32 =
+ {
+ ".exe",
+ ".dll",
+ ".sys",
+ ".inf",
+ ".wav",
+ };
+
+ foreach (string ext in filesOnlyWin32)
+ {
+ if (filename.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Delete svn file
+ public static void DeleteSVNFilesFromHamCoreBuilder(HamCoreBuilder b)
+ {
+ List<string> removeFiles = new List<string>();
+ foreach (HamCoreBuilderFileEntry f in b.FileList)
+ {
+ string name = f.Name;
+ if (name.StartsWith(".svn", StringComparison.InvariantCultureIgnoreCase) ||
+ name.IndexOf(@"\.svn", StringComparison.InvariantCultureIgnoreCase) != -1)
+ {
+ removeFiles.Add(name);
+ }
+ }
+ foreach (string file in removeFiles)
+ {
+ b.DeleteFile(file);
+ }
+ }
+
+ // Build Hamcore file
+ public static void BuildHamcore()
+ {
+ string srcDirNameBasic = Path.Combine(Paths.BinDirName, "hamcore");
+ // Create the destination directory
+ string win32DestDir = Path.Combine(Paths.BuildHamcoreFilesDirName, "hamcore_win32");
+ string win32DestFileName = Path.Combine(win32DestDir, "hamcore.se2");
+ string unixDestDir = Path.Combine(Paths.BuildHamcoreFilesDirName, "hamcore_unix");
+ string unixDestFileName = Path.Combine(unixDestDir, "hamcore.se2");
+ IO.MakeDir(win32DestDir);
+ IO.MakeDir(unixDestDir);
+
+
+ BuildHamcoreEx(srcDirNameBasic, win32DestFileName, unixDestFileName);
+
+ // Copy to bin\hamcore.se2
+ try
+ {
+ string binHamcoreFileName = Path.Combine(Paths.BinDirName, "hamcore.se2");
+
+ try
+ {
+ File.Delete(binHamcoreFileName);
+ }
+ catch
+ {
+ }
+
+ File.Copy(win32DestFileName, binHamcoreFileName, true);
+ }
+ catch
+ {
+ }
+ }
+
+ public static void BuildHamcoreEx(string srcDirNameBasic, string win32DestFileName, string unixDestFileName)
+ {
+ HamCoreBuilder b = new HamCoreBuilder();
+ b.AddDir(srcDirNameBasic);
+ Con.WriteLine("* Building hamcore ...");
+
+ DeleteSVNFilesFromHamCoreBuilder(b);
+
+ try
+ {
+ File.Delete(win32DestFileName);
+ }
+ catch
+ {
+ }
+ b.Build(win32DestFileName);
+
+ // unix
+ List<string> removeFiles = new List<string>();
+ foreach (HamCoreBuilderFileEntry f in b.FileList)
+ {
+ if (IsFileForOnlyWin32(f.Name))
+ {
+ removeFiles.Add(f.Name);
+ }
+ }
+ foreach (string removeFile in removeFiles)
+ {
+ b.DeleteFile(removeFile);
+ }
+
+ DeleteSVNFilesFromHamCoreBuilder(b);
+
+ try
+ {
+ File.Delete(unixDestFileName);
+ }
+ catch
+ {
+ }
+ b.Build(unixDestFileName);
+ }
+ }
+
+ // Number of bits
+ public enum CPUBits
+ {
+ Both,
+ Bits32,
+ Bits64,
+ }
+
+ // Conversion a string to the number of bits
+ public static class CPUBitsUtil
+ {
+ public static CPUBits StringToCPUBits(string str)
+ {
+ if (str.Equals("32bit", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return CPUBits.Bits32;
+ }
+ else if (str.Equals("64bit", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return CPUBits.Bits64;
+ }
+ else if (str.Equals("intel", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return CPUBits.Both;
+ }
+
+ throw new ApplicationException(string.Format("Invalid bits string '{0}'.", str));
+ }
+
+ public static string CPUBitsToString(CPUBits bits)
+ {
+ switch (bits)
+ {
+ case CPUBits.Bits32:
+ return "32bit";
+
+ case CPUBits.Bits64:
+ return "64bit";
+
+ case CPUBits.Both:
+ return "intel";
+ }
+
+ throw new ApplicationException("bits invalid.");
+ }
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/VpnBuilderConfig.cs b/src/BuildUtil/VpnBuilderConfig.cs
new file mode 100644
index 00000000..d3d74cc7
--- /dev/null
+++ b/src/BuildUtil/VpnBuilderConfig.cs
@@ -0,0 +1,513 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // Build settings
+ public static class BuildConfig
+ {
+ public static readonly int NumMultipleCompileTasks = 4;
+ }
+
+ // Software List
+ public static class BuildSoftwareList
+ {
+ // List creation date and time
+ public static DateTime ListCreatedDateTime = DateTime.Now;
+
+ // ========== Windows ==========
+ // Server and Bridge
+ public static readonly BuildSoftware vpnserver_win32_x86x64_ja =
+ new BuildSoftwareWin32(Software.vpnserver_vpnbridge, 0, 0, "", CpuList.intel, OSList.Windows);
+
+ // Client
+ public static readonly BuildSoftware vpnclient_win32_x86x64_ja =
+ new BuildSoftwareWin32(Software.vpnclient, 0, 0, "", CpuList.intel, OSList.Windows);
+
+ // ========== Linux ==========
+ // Server
+ public static readonly BuildSoftware vpnserver_linux_x86_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x86, OSList.Linux,
+ "linux-x86-32bit", true, "linux-x86-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_x64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x64, OSList.Linux,
+ "linux-x86-64bit", true, "linux-x86-64bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_arm_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.arm, OSList.Linux,
+ "linux-arm-32bit", false, "linux-arm-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_armeabi_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.armeabi, OSList.Linux,
+ "linux-armeabi-32bit", false, "linux-armeabi-32bit-4.3.2", true,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_mipsel_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.mipsel, OSList.Linux,
+ "linux-mipsel-32bit", false, "linux-mipsel-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_ppc_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.ppc32, OSList.Linux,
+ "linux-ppc-32bit", false, "linux-ppc-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_linux_sh4_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.sh4, OSList.Linux,
+ "linux-sh4-32bit", false, "linux-sh4-32bit-3.4.6", false,
+ null);
+
+ // Client
+ public static readonly BuildSoftware vpnclient_linux_x86_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.x86, OSList.Linux,
+ "linux-x86-32bit", true, "linux-x86-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_x64_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.x64, OSList.Linux,
+ "linux-x86-64bit", true, "linux-x86-64bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_arm_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.arm, OSList.Linux,
+ "linux-arm-32bit", false, "linux-arm-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_armeabi_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.armeabi, OSList.Linux,
+ "linux-armeabi-32bit", false, "linux-armeabi-32bit-4.3.2", true,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_mipsel_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.mipsel, OSList.Linux,
+ "linux-mipsel-32bit", false, "linux-mipsel-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_ppc_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.ppc32, OSList.Linux,
+ "linux-ppc-32bit", false, "linux-ppc-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnclient_linux_sh4_ja =
+ new BuildSoftwareUnix(Software.vpnclient, 0, 0, "", CpuList.sh4, OSList.Linux,
+ "linux-sh4-32bit", false, "linux-sh4-32bit-3.4.6", false,
+ null);
+
+ // Bridge
+ public static readonly BuildSoftware vpnbridge_linux_x86_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x86, OSList.Linux,
+ "linux-x86-32bit", true, "linux-x86-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_x64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x64, OSList.Linux,
+ "linux-x86-64bit", true, "linux-x86-64bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_arm_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.arm, OSList.Linux,
+ "linux-arm-32bit", false, "linux-arm-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_armeabi_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.armeabi, OSList.Linux,
+ "linux-armeabi-32bit", false, "linux-armeabi-32bit-4.3.2", true,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_mipsel_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.mipsel, OSList.Linux,
+ "linux-mipsel-32bit", false, "linux-mipsel-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_ppc_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.ppc32, OSList.Linux,
+ "linux-ppc-32bit", false, "linux-ppc-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_linux_sh4_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.sh4, OSList.Linux,
+ "linux-sh4-32bit", false, "linux-sh4-32bit-3.4.6", false,
+ null);
+
+
+ // ========== FreeBSD ==========
+ // Server
+ public static readonly BuildSoftware vpnserver_bsd_x86_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x86, OSList.FreeBSD,
+ "freebsd-x86-32bit", true, "freebsd-x86-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnserver_bsd_x64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x64, OSList.FreeBSD,
+ "freebsd-x86-64bit", true, "freebsd-x86-64bit-3.4.6", false,
+ null);
+
+ // Bridge
+ public static readonly BuildSoftware vpnbridge_bsd_x86_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x86, OSList.FreeBSD,
+ "freebsd-x86-32bit", true, "freebsd-x86-32bit-3.4.6", false,
+ null);
+ public static readonly BuildSoftware vpnbridge_bsd_x64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x64, OSList.FreeBSD,
+ "freebsd-x86-64bit", true, "freebsd-x86-64bit-3.4.6", false,
+ null);
+
+
+ // ========== Mac OS X ==========
+ // Server
+ public static readonly BuildSoftware vpnserver_macos_ppc32_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.ppc32, OSList.MacOS,
+ "macos-ppc-32bit", true, "macos-ppc-32bit-4.0.4", true,
+ "-isysroot /cygdrive/s/CommomDev/xc/common/apple_xcode/xcode_2.4/Developer/SDKs/MacOSX10.4u.sdk");
+ public static readonly BuildSoftware vpnserver_macos_ppc64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.ppc64, OSList.MacOS,
+ "macos-ppc-64bit", true, "macos-ppc-64bit-4.0.4", true,
+ null);
+ public static readonly BuildSoftware vpnserver_macos_x86_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x86, OSList.MacOS,
+ "macos-x86-32bit", true, "macos-x86-32bit-4.0.4", true,
+ "-isysroot /cygdrive/s/CommomDev/xc/common/apple_xcode/xcode_2.4/Developer/SDKs/MacOSX10.4u.sdk");
+ public static readonly BuildSoftware vpnserver_macos_x64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x64, OSList.MacOS,
+ "macos-x86-64bit", true, "macos-x86-64bit-4.0.4", true,
+ null);
+
+ // Bridge
+ public static readonly BuildSoftware vpnbridge_macos_ppc32_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.ppc32, OSList.MacOS,
+ "macos-ppc-32bit", true, "macos-ppc-32bit-4.0.4", true,
+ "-isysroot /cygdrive/s/CommomDev/xc/common/apple_xcode/xcode_2.4/Developer/SDKs/MacOSX10.4u.sdk");
+ public static readonly BuildSoftware vpnbridge_macos_ppc64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.ppc64, OSList.MacOS,
+ "macos-ppc-64bit", true, "macos-ppc-64bit-4.0.4", true,
+ null);
+ public static readonly BuildSoftware vpnbridge_macos_x86_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x86, OSList.MacOS,
+ "macos-x86-32bit", true, "macos-x86-32bit-4.0.4", true,
+ "-isysroot /cygdrive/s/CommomDev/xc/common/apple_xcode/xcode_2.4/Developer/SDKs/MacOSX10.4u.sdk");
+ public static readonly BuildSoftware vpnbridge_macos_x64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x64, OSList.MacOS,
+ "macos-x86-64bit", true, "macos-x86-64bit-4.0.4", true,
+ null);
+
+ // ========== Solaris ==========
+ // Server
+ public static readonly BuildSoftware vpnserver_solaris_sparc32_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.sparc32, OSList.Solaris,
+ "solaris-sparc-32bit", true, "solaris-sparc-32bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnserver_solaris_sparc64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.sparc64, OSList.Solaris,
+ "solaris-sparc-64bit", true, "solaris-sparc-64bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnserver_solaris_x86_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x86, OSList.Solaris,
+ "solaris-x86-32bit", true, "solaris-x86-32bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnserver_solaris_x64_ja =
+ new BuildSoftwareUnix(Software.vpnserver, 0, 0, "", CpuList.x64, OSList.Solaris,
+ "solaris-x86-64bit", true, "solaris-x86-64bit-3.4.6", true,
+ null);
+
+ // Bridge
+ public static readonly BuildSoftware vpnbridge_solaris_sparc32_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.sparc32, OSList.Solaris,
+ "solaris-sparc-32bit", true, "solaris-sparc-32bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnbridge_solaris_sparc64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.sparc64, OSList.Solaris,
+ "solaris-sparc-64bit", true, "solaris-sparc-64bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnbridge_solaris_x86_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x86, OSList.Solaris,
+ "solaris-x86-32bit", true, "solaris-x86-32bit-3.4.6", true,
+ null);
+ public static readonly BuildSoftware vpnbridge_solaris_x64_ja =
+ new BuildSoftwareUnix(Software.vpnbridge, 0, 0, "", CpuList.x64, OSList.Solaris,
+ "solaris-x86-64bit", true, "solaris-x86-64bit-3.4.6", true,
+ null);
+
+ static BuildSoftwareList()
+ {
+ foreach (BuildSoftware soft in List)
+ {
+ BuildSoftwareUnix s = soft as BuildSoftwareUnix;
+ if (s != null)
+ {
+ // Make different settings for each OS
+ if (soft.Os == OSList.Linux)
+ {
+ s.GccMacros.Add("UNIX_LINUX");
+ }
+ else if (soft.Os == OSList.FreeBSD)
+ {
+ s.GccMacros.Add("UNIX_BSD");
+ s.GccMacros.Add("BRIDGE_BPF");
+ s.GccMacros.Add("NO_VLAN");
+ }
+ else if (soft.Os == OSList.MacOS)
+ {
+ s.GccMacros.Add("UNIX_MACOS");
+ s.GccMacros.Add("BRIDGE_PCAP");
+ s.GccMacros.Add("NO_VLAN");
+ }
+ else if (soft.Os == OSList.Solaris)
+ {
+ s.GccMacros.Add("UNIX_SOLARIS");
+ s.GccMacros.Add("NO_VLAN");
+ }
+ if (s.Cpu.Bits == CPUBits.Bits64)
+ {
+ s.GccMacros.Add("CPU_64");
+ }
+ s.GccMacros.Add("CPU_" + s.Cpu.Name.ToUpperInvariant());
+ }
+ }
+ }
+
+ public static BuildSoftware[] List
+ {
+ get
+ {
+ List<BuildSoftware> o = new List<BuildSoftware>();
+ foreach (FieldInfo fi in typeof(BuildSoftwareList).GetFields(BindingFlags.Static | BindingFlags.Public))
+ if (fi.FieldType == typeof(BuildSoftware))
+ o.Add((BuildSoftware)fi.GetValue(null));
+ return o.ToArray();
+ }
+ }
+
+ public static BuildSoftware Find(Software soft, OS os, Cpu cpu)
+ {
+ foreach (BuildSoftware s in List)
+ {
+ if (s.Software == soft && s.Os == os && s.Cpu == cpu)
+ {
+ return s;
+ }
+ }
+ return null;
+ }
+ }
+
+ // OS List
+ public static class OSList
+ {
+ // Windows
+ public static readonly OS Windows = new OS("windows", "Windows",
+ "Windows 98 / 98 SE / ME / NT 4.0 SP6a / 2000 SP4 / XP SP2, SP3 / Server 2003 SP2 / Vista SP1, SP2 / Server 2008 SP1, SP2 / Hyper-V Server 2008 / 7 SP1 / Server 2008 R2 SP1 / Hyper-V Server 2008 R2 / 8 / Server 2012 / Hyper-V Server 2012 / 8.1 / Server 2012 R2 / Hyper-V Server 2012 R2",
+ new Cpu[]
+ {
+ CpuList.intel,
+ });
+
+ // Linux
+ public static readonly OS Linux = new OS("linux", "Linux",
+ "Linux Kernel 2.4 / 2.6 / 3.x",
+ new Cpu[]
+ {
+ CpuList.x86,
+ CpuList.x64,
+ CpuList.mipsel,
+ CpuList.ppc32,
+ CpuList.ppc64,
+ CpuList.sh4,
+ CpuList.arm,
+ CpuList.armeabi,
+ });
+
+ // FreeBSD
+ public static readonly OS FreeBSD = new OS("freebsd", "FreeBSD",
+ "FreeBSD 5 / 6 / 7 / 8 / 9",
+ new Cpu[]
+ {
+ CpuList.x86,
+ CpuList.x64,
+ });
+
+ // Solaris
+ public static readonly OS Solaris = new OS("solaris", "Solaris",
+ "Solaris 8 / 9 / 10 / 11",
+ new Cpu[]
+ {
+ CpuList.x86,
+ CpuList.x64,
+ CpuList.sparc32,
+ CpuList.sparc64,
+ });
+
+ // Mac OS X
+ public static readonly OS MacOS = new OS("macos", "Mac OS X",
+ "Mac OS X 10.4 Tiger / 10.5 Leopard / 10.6 Snow Leopard / 10.7 Lion / 10.8 Mountain Lion",
+ new Cpu[]
+ {
+ CpuList.x86,
+ CpuList.x64,
+ CpuList.ppc32,
+ CpuList.ppc64,
+ });
+
+ static OSList()
+ {
+ OSList.Windows.IsWindows = true;
+ }
+
+ public static OS[] List
+ {
+ get
+ {
+ List<OS> o = new List<OS>();
+ foreach (FieldInfo fi in typeof(OSList).GetFields(BindingFlags.Static | BindingFlags.Public))
+ if (fi.FieldType == typeof(OS))
+ o.Add((OS)fi.GetValue(null));
+ return o.ToArray();
+ }
+ }
+
+ public static OS FindByName(string name)
+ {
+ foreach (OS os in List)
+ {
+ if (os.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return os;
+ }
+ }
+
+ throw new ApplicationException(name);
+ }
+ }
+
+ // CPU List
+ public static class CpuList
+ {
+ public static readonly Cpu x86 = new Cpu("x86", "Intel x86", CPUBits.Bits32);
+ public static readonly Cpu x64 = new Cpu("x64", "Intel x64 / AMD64", CPUBits.Bits64);
+ public static readonly Cpu intel = new Cpu("x86_x64", "Intel", CPUBits.Both);
+ public static readonly Cpu arm = new Cpu("arm", "ARM legacy ABI", CPUBits.Bits32);
+ public static readonly Cpu armeabi = new Cpu("arm_eabi", "ARM EABI", CPUBits.Bits32);
+ public static readonly Cpu mipsel = new Cpu("mips_el", "MIPS Little-Endian", CPUBits.Bits32);
+ public static readonly Cpu ppc32 = new Cpu("powerpc", "PowerPC", CPUBits.Bits32);
+ public static readonly Cpu ppc64 = new Cpu("powerpc64", "PowerPC G5", CPUBits.Bits64);
+ public static readonly Cpu sh4 = new Cpu("sh4", "SH-4", CPUBits.Bits32);
+ public static readonly Cpu sparc32 = new Cpu("sparc", "SPARC", CPUBits.Bits32);
+ public static readonly Cpu sparc64 = new Cpu("sparc64", "SPARC", CPUBits.Bits64);
+
+ public static Cpu[] List
+ {
+ get
+ {
+ List<Cpu> o = new List<Cpu>();
+ foreach (FieldInfo fi in typeof(CpuList).GetFields(BindingFlags.Static | BindingFlags.Public))
+ if (fi.FieldType == typeof(Cpu))
+ o.Add((Cpu)fi.GetValue(null));
+ return o.ToArray();
+ }
+ }
+
+ public static Cpu FindByName(string name)
+ {
+ foreach (Cpu c in List)
+ {
+ if (c.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return c;
+ }
+ }
+
+ throw new ApplicationException(name);
+ }
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/VpnBuilderConfigTypes.cs b/src/BuildUtil/VpnBuilderConfigTypes.cs
new file mode 100644
index 00000000..8ef91a6e
--- /dev/null
+++ b/src/BuildUtil/VpnBuilderConfigTypes.cs
@@ -0,0 +1,303 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // CPU data
+ public class Cpu
+ {
+ public string Name; // CPU name
+ public string Title; // CPU display name
+ public CPUBits Bits; // Bit length
+
+ public Cpu(string name, string title, CPUBits bits)
+ {
+ this.Name = name;
+ this.Title = title;
+ this.Bits = bits;
+ }
+ }
+
+ // OS data
+ public class OS : ICloneable
+ {
+ public string Name; // OS name
+ public string Title; // OS Display Name
+ public string OSSimpleList; // OS simple list
+ public Cpu[] CpuList; // CPU support list
+ public bool IsWindows = false; // Whether Windows
+ public bool IsOnlyFiles = false; // Whether only EXE file package
+
+ public OS(string name, string title, string simpleList, Cpu[] cpuList)
+ {
+ this.Name = name;
+ this.Title = title;
+ this.OSSimpleList = simpleList;
+ this.CpuList = cpuList;
+ }
+
+ public object Clone()
+ {
+ return this.MemberwiseClone();
+ }
+ }
+
+ // Type of software
+ public enum Software
+ {
+ vpnserver,
+ vpnbridge,
+ vpnclient,
+ vpnserver_vpnbridge,
+ }
+
+ // Class to build the software
+ public class BuildSoftware
+ {
+ public Software Software; // Software
+ public int Version; // Version number
+ public int BuildNumber; // Build Number
+ public string BuildName; // Build name
+ public Cpu Cpu; // CPU
+ public OS Os; // OS
+ public DateTime BuildDate; // Build date
+
+ public BuildSoftware(Software software, int buildNumber, int version, string buildName, Cpu cpu, OS os)
+ {
+ this.Software = software;
+ this.BuildNumber = buildNumber;
+ this.Version = version;
+ this.BuildName = buildName;
+ this.Cpu = cpu;
+ this.Os = os;
+ }
+
+ public void SetBuildNumberVersionName(int buildNumber, int version, string buildName, DateTime date)
+ {
+ this.BuildNumber = buildNumber;
+ this.Version = version;
+ this.BuildName = buildName;
+ this.BuildDate = date;
+ }
+
+ public BuildSoftware(string filename)
+ {
+ filename = Path.GetFileName(filename);
+
+ if (filename.StartsWith(Paths.Prefix, StringComparison.InvariantCultureIgnoreCase))
+ {
+ filename = filename.Substring(Paths.Prefix.Length);
+ }
+
+ if (filename.EndsWith(".tar.gz", StringComparison.InvariantCultureIgnoreCase))
+ {
+ filename = Str.ReplaceStr(filename, ".tar.gz", "");
+ }
+ else
+ {
+ filename = Path.GetFileNameWithoutExtension(filename);
+ }
+ char[] sps = {'-'};
+
+ string[] tokens = filename.Split(sps, StringSplitOptions.RemoveEmptyEntries);
+ if (tokens.Length != 8)
+ {
+ throw new ApplicationException(filename);
+ }
+
+ if (tokens[1].StartsWith("v", StringComparison.InvariantCultureIgnoreCase) == false)
+ {
+ throw new ApplicationException(filename);
+ }
+
+ this.Software = (Software)Enum.Parse(typeof(Software), tokens[0], true);
+ this.Version = (int)(double.Parse(tokens[1].Substring(1)) * 100);
+ this.BuildNumber = int.Parse(tokens[2]);
+ this.BuildName = tokens[3];
+
+ string[] ds = tokens[4].Split('.');
+ this.BuildDate = new DateTime(int.Parse(ds[0]), int.Parse(ds[1]), int.Parse(ds[2]));
+ this.Os = OSList.FindByName(tokens[5]);
+ this.Cpu = CpuList.FindByName(tokens[6]);
+ }
+
+ // Generate a string of file name equivalent
+ public virtual string FileNameBaseString
+ {
+ get
+ {
+ return string.Format("{0}-v{6}-{1}-{2}-{8:D4}.{9:D2}.{10:D2}-{4}-{3}-{7}",
+ Paths.Prefix + this.Software.ToString(),
+ this.BuildNumber,
+ this.BuildName,
+ this.Cpu.Name,
+ this.Os.Name,
+ 0,
+ BuildHelper.VersionIntToString(this.Version),
+ CPUBitsUtil.CPUBitsToString(this.Cpu.Bits),
+ BuildDate.Year, BuildDate.Month, BuildDate.Day).ToLower();
+ }
+ }
+
+ // Generate an identifier
+ public virtual string IDString
+ {
+ get
+ {
+ return string.Format("{0}-{2}-{3}-{4}",
+ Paths.Prefix + this.Software.ToString(),
+ 0,
+ this.Os.Name,
+ this.Cpu.Name,
+ CPUBitsUtil.CPUBitsToString(this.Cpu.Bits));
+ }
+ }
+
+ // Generate a title string
+ public virtual string TitleString
+ {
+ get
+ {
+ return string.Format("{0} (Ver {2}, Build {1}, {3}) for {5}", BuildHelper.GetSoftwareTitle(this.Software),
+ this.BuildNumber, BuildHelper.VersionIntToString(this.Version), this.Cpu.Title, 0, this.Os.Title);
+ }
+ }
+
+ // Generate extension
+ public virtual string OutputFileExt
+ {
+ get
+ {
+ if (this.Os.IsWindows)
+ {
+ return ".exe";
+ }
+ else
+ {
+ return ".tar.gz";
+ }
+ }
+ }
+
+ // Generate the output file name
+ public virtual string OutputFileName
+ {
+ get
+ {
+ return this.FileNameBaseString + this.OutputFileExt;
+ }
+ }
+
+ // Run the build
+ public virtual void Build()
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Web References/HvSignService/Reference.cs b/src/BuildUtil/Web References/HvSignService/Reference.cs
new file mode 100644
index 00000000..80e6b8f1
--- /dev/null
+++ b/src/BuildUtil/Web References/HvSignService/Reference.cs
@@ -0,0 +1,282 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// ã“ã®ã‚³ãƒ¼ãƒ‰ã¯ãƒ„ールã«ã‚ˆã£ã¦ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚
+// ランタイム ãƒãƒ¼ã‚¸ãƒ§ãƒ³:2.0.50727.5466
+//
+// ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¸ã®å¤‰æ›´ã¯ã€ä»¥ä¸‹ã®çŠ¶æ³ä¸‹ã§ä¸æ­£ãªå‹•ä½œã®åŽŸå› ã«ãªã£ãŸã‚Šã€
+// コードãŒå†ç”Ÿæˆã•ã‚Œã‚‹ã¨ãã«æ失ã—ãŸã‚Šã—ã¾ã™ã€‚
+// </auto-generated>
+//------------------------------------------------------------------------------
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+//
+// ã“ã®ã‚½ãƒ¼ã‚¹ コード㯠Microsoft.VSDesignerã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.0.50727.5466 ã«ã‚ˆã£ã¦è‡ªå‹•ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚
+//
+#pragma warning disable 1591
+
+namespace BuildUtil.HvSignService {
+ using System.Diagnostics;
+ using System.Web.Services;
+ using System.ComponentModel;
+ using System.Web.Services.Protocols;
+ using System;
+ using System.Xml.Serialization;
+
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.5420")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ [System.Web.Services.WebServiceBindingAttribute(Name="SignSoap", Namespace="http://hvsigncode/")]
+ public partial class Sign : System.Web.Services.Protocols.SoapHttpClientProtocol {
+
+ private System.Threading.SendOrPostCallback HelloWorldOperationCompleted;
+
+ private System.Threading.SendOrPostCallback ExecSignOperationCompleted;
+
+ private bool useDefaultCredentialsSetExplicitly;
+
+ /// <remarks/>
+ public Sign() {
+ this.Url = global::BuildUtil.Properties.Settings.Default.BuildUtilTmp_HvSignService_Sign;
+ if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
+ this.UseDefaultCredentials = true;
+ this.useDefaultCredentialsSetExplicitly = false;
+ }
+ else {
+ this.useDefaultCredentialsSetExplicitly = true;
+ }
+ }
+
+ public new string Url {
+ get {
+ return base.Url;
+ }
+ set {
+ if ((((this.IsLocalFileSystemWebService(base.Url) == true)
+ && (this.useDefaultCredentialsSetExplicitly == false))
+ && (this.IsLocalFileSystemWebService(value) == false))) {
+ base.UseDefaultCredentials = false;
+ }
+ base.Url = value;
+ }
+ }
+
+ public new bool UseDefaultCredentials {
+ get {
+ return base.UseDefaultCredentials;
+ }
+ set {
+ base.UseDefaultCredentials = value;
+ this.useDefaultCredentialsSetExplicitly = true;
+ }
+ }
+
+ /// <remarks/>
+ public event HelloWorldCompletedEventHandler HelloWorldCompleted;
+
+ /// <remarks/>
+ public event ExecSignCompletedEventHandler ExecSignCompleted;
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://hvsigncode/HelloWorld", RequestNamespace="http://hvsigncode/", ResponseNamespace="http://hvsigncode/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public string HelloWorld() {
+ object[] results = this.Invoke("HelloWorld", new object[0]);
+ return ((string)(results[0]));
+ }
+
+ /// <remarks/>
+ public void HelloWorldAsync() {
+ this.HelloWorldAsync(null);
+ }
+
+ /// <remarks/>
+ public void HelloWorldAsync(object userState) {
+ if ((this.HelloWorldOperationCompleted == null)) {
+ this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
+ }
+ this.InvokeAsync("HelloWorld", new object[0], this.HelloWorldOperationCompleted, userState);
+ }
+
+ private void OnHelloWorldOperationCompleted(object arg) {
+ if ((this.HelloWorldCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.HelloWorldCompleted(this, new HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://hvsigncode/ExecSign", RequestNamespace="http://hvsigncode/", ResponseNamespace="http://hvsigncode/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public string ExecSign(string src_filename, bool driver_mode, string description, int cert_id) {
+ object[] results = this.Invoke("ExecSign", new object[] {
+ src_filename,
+ driver_mode,
+ description,
+ cert_id});
+ return ((string)(results[0]));
+ }
+
+ /// <remarks/>
+ public void ExecSignAsync(string src_filename, bool driver_mode, string description, int cert_id) {
+ this.ExecSignAsync(src_filename, driver_mode, description, cert_id, null);
+ }
+
+ /// <remarks/>
+ public void ExecSignAsync(string src_filename, bool driver_mode, string description, int cert_id, object userState) {
+ if ((this.ExecSignOperationCompleted == null)) {
+ this.ExecSignOperationCompleted = new System.Threading.SendOrPostCallback(this.OnExecSignOperationCompleted);
+ }
+ this.InvokeAsync("ExecSign", new object[] {
+ src_filename,
+ driver_mode,
+ description,
+ cert_id}, this.ExecSignOperationCompleted, userState);
+ }
+
+ private void OnExecSignOperationCompleted(object arg) {
+ if ((this.ExecSignCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.ExecSignCompleted(this, new ExecSignCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ public new void CancelAsync(object userState) {
+ base.CancelAsync(userState);
+ }
+
+ private bool IsLocalFileSystemWebService(string url) {
+ if (((url == null)
+ || (url == string.Empty))) {
+ return false;
+ }
+ System.Uri wsUri = new System.Uri(url);
+ if (((wsUri.Port >= 1024)
+ && (string.Compare(wsUri.Host, "localHost", System.StringComparison.OrdinalIgnoreCase) == 0))) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.5420")]
+ public delegate void HelloWorldCompletedEventHandler(object sender, HelloWorldCompletedEventArgs e);
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.5420")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class HelloWorldCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal HelloWorldCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public string Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((string)(this.results[0]));
+ }
+ }
+ }
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.5420")]
+ public delegate void ExecSignCompletedEventHandler(object sender, ExecSignCompletedEventArgs e);
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.5420")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class ExecSignCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal ExecSignCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public string Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((string)(this.results[0]));
+ }
+ }
+ }
+}
+
+#pragma warning restore 1591
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Web References/HvSignService/Sign.disco b/src/BuildUtil/Web References/HvSignService/Sign.disco
new file mode 100644
index 00000000..e5cb0c0b
--- /dev/null
+++ b/src/BuildUtil/Web References/HvSignService/Sign.disco
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
+ <contractRef ref="http://hvsigncode/Sign.asmx?wsdl" docRef="http://hvsigncode/Sign.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
+ <soap address="http://hvsigncode/Sign.asmx" xmlns:q1="http://hvsigncode/" binding="q1:SignSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
+ <soap address="http://hvsigncode/Sign.asmx" xmlns:q2="http://hvsigncode/" binding="q2:SignSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
+</discovery> \ No newline at end of file
diff --git a/src/BuildUtil/Web References/HvSignService/Sign.wsdl b/src/BuildUtil/Web References/HvSignService/Sign.wsdl
new file mode 100644
index 00000000..4a6f0777
--- /dev/null
+++ b/src/BuildUtil/Web References/HvSignService/Sign.wsdl
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://hvsigncode/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://hvsigncode/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+ <wsdl:types>
+ <s:schema elementFormDefault="qualified" targetNamespace="http://hvsigncode/">
+ <s:element name="HelloWorld">
+ <s:complexType />
+ </s:element>
+ <s:element name="HelloWorldResponse">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ <s:element name="ExecSign">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="src_filename" type="s:string" />
+ <s:element minOccurs="1" maxOccurs="1" name="driver_mode" type="s:boolean" />
+ <s:element minOccurs="0" maxOccurs="1" name="description" type="s:string" />
+ <s:element minOccurs="1" maxOccurs="1" name="cert_id" type="s:int" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ <s:element name="ExecSignResponse">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="ExecSignResult" type="s:string" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ </s:schema>
+ </wsdl:types>
+ <wsdl:message name="HelloWorldSoapIn">
+ <wsdl:part name="parameters" element="tns:HelloWorld" />
+ </wsdl:message>
+ <wsdl:message name="HelloWorldSoapOut">
+ <wsdl:part name="parameters" element="tns:HelloWorldResponse" />
+ </wsdl:message>
+ <wsdl:message name="ExecSignSoapIn">
+ <wsdl:part name="parameters" element="tns:ExecSign" />
+ </wsdl:message>
+ <wsdl:message name="ExecSignSoapOut">
+ <wsdl:part name="parameters" element="tns:ExecSignResponse" />
+ </wsdl:message>
+ <wsdl:portType name="SignSoap">
+ <wsdl:operation name="HelloWorld">
+ <wsdl:input message="tns:HelloWorldSoapIn" />
+ <wsdl:output message="tns:HelloWorldSoapOut" />
+ </wsdl:operation>
+ <wsdl:operation name="ExecSign">
+ <wsdl:input message="tns:ExecSignSoapIn" />
+ <wsdl:output message="tns:ExecSignSoapOut" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="SignSoap" type="tns:SignSoap">
+ <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="HelloWorld">
+ <soap:operation soapAction="http://hvsigncode/HelloWorld" style="document" />
+ <wsdl:input>
+ <soap:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="ExecSign">
+ <soap:operation soapAction="http://hvsigncode/ExecSign" style="document" />
+ <wsdl:input>
+ <soap:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:binding name="SignSoap12" type="tns:SignSoap">
+ <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="HelloWorld">
+ <soap12:operation soapAction="http://hvsigncode/HelloWorld" style="document" />
+ <wsdl:input>
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="ExecSign">
+ <soap12:operation soapAction="http://hvsigncode/ExecSign" style="document" />
+ <wsdl:input>
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="Sign">
+ <wsdl:port name="SignSoap" binding="tns:SignSoap">
+ <soap:address location="http://hvsigncode/Sign.asmx" />
+ </wsdl:port>
+ <wsdl:port name="SignSoap12" binding="tns:SignSoap12">
+ <soap12:address location="http://hvsigncode/Sign.asmx" />
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions> \ No newline at end of file
diff --git a/src/BuildUtil/Web References/SignService/Reference.cs b/src/BuildUtil/Web References/SignService/Reference.cs
new file mode 100644
index 00000000..6ad8706a
--- /dev/null
+++ b/src/BuildUtil/Web References/SignService/Reference.cs
@@ -0,0 +1,281 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// ã“ã®ã‚³ãƒ¼ãƒ‰ã¯ãƒ„ールã«ã‚ˆã£ã¦ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚
+// ランタイム ãƒãƒ¼ã‚¸ãƒ§ãƒ³:2.0.50727.4927
+//
+// ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¸ã®å¤‰æ›´ã¯ã€ä»¥ä¸‹ã®çŠ¶æ³ä¸‹ã§ä¸æ­£ãªå‹•ä½œã®åŽŸå› ã«ãªã£ãŸã‚Šã€
+// コードãŒå†ç”Ÿæˆã•ã‚Œã‚‹ã¨ãã«æ失ã—ãŸã‚Šã—ã¾ã™ã€‚
+// </auto-generated>
+//------------------------------------------------------------------------------
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+//
+// ã“ã®ã‚½ãƒ¼ã‚¹ コード㯠Microsoft.VSDesignerã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.0.50727.4927 ã«ã‚ˆã£ã¦è‡ªå‹•ç”Ÿæˆã•ã‚Œã¾ã—ãŸã€‚
+//
+#pragma warning disable 1591
+
+namespace BuildUtil.SignService {
+ using System.Diagnostics;
+ using System.Web.Services;
+ using System.ComponentModel;
+ using System.Web.Services.Protocols;
+ using System;
+ using System.Xml.Serialization;
+
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ [System.Web.Services.WebServiceBindingAttribute(Name="SignSoap", Namespace="http://dv/Sign/")]
+ public partial class Sign : System.Web.Services.Protocols.SoapHttpClientProtocol {
+
+ private System.Threading.SendOrPostCallback HelloWorldOperationCompleted;
+
+ private System.Threading.SendOrPostCallback DoSignOperationCompleted;
+
+ private bool useDefaultCredentialsSetExplicitly;
+
+ /// <remarks/>
+ public Sign() {
+ this.Url = global::BuildUtil.Properties.Settings.Default.BuildUtil_SignService_Sign;
+ if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
+ this.UseDefaultCredentials = true;
+ this.useDefaultCredentialsSetExplicitly = false;
+ }
+ else {
+ this.useDefaultCredentialsSetExplicitly = true;
+ }
+ }
+
+ public new string Url {
+ get {
+ return base.Url;
+ }
+ set {
+ if ((((this.IsLocalFileSystemWebService(base.Url) == true)
+ && (this.useDefaultCredentialsSetExplicitly == false))
+ && (this.IsLocalFileSystemWebService(value) == false))) {
+ base.UseDefaultCredentials = false;
+ }
+ base.Url = value;
+ }
+ }
+
+ public new bool UseDefaultCredentials {
+ get {
+ return base.UseDefaultCredentials;
+ }
+ set {
+ base.UseDefaultCredentials = value;
+ this.useDefaultCredentialsSetExplicitly = true;
+ }
+ }
+
+ /// <remarks/>
+ public event HelloWorldCompletedEventHandler HelloWorldCompleted;
+
+ /// <remarks/>
+ public event DoSignCompletedEventHandler DoSignCompleted;
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://dv/Sign/HelloWorld", RequestNamespace="http://dv/Sign/", ResponseNamespace="http://dv/Sign/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public string HelloWorld() {
+ object[] results = this.Invoke("HelloWorld", new object[0]);
+ return ((string)(results[0]));
+ }
+
+ /// <remarks/>
+ public void HelloWorldAsync() {
+ this.HelloWorldAsync(null);
+ }
+
+ /// <remarks/>
+ public void HelloWorldAsync(object userState) {
+ if ((this.HelloWorldOperationCompleted == null)) {
+ this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
+ }
+ this.InvokeAsync("HelloWorld", new object[0], this.HelloWorldOperationCompleted, userState);
+ }
+
+ private void OnHelloWorldOperationCompleted(object arg) {
+ if ((this.HelloWorldCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.HelloWorldCompleted(this, new HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://dv/Sign/DoSign", RequestNamespace="http://dv/Sign/", ResponseNamespace="http://dv/Sign/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ [return: System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")]
+ public byte[] DoSign([System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] byte[] srcData, bool driverMode, string description) {
+ object[] results = this.Invoke("DoSign", new object[] {
+ srcData,
+ driverMode,
+ description});
+ return ((byte[])(results[0]));
+ }
+
+ /// <remarks/>
+ public void DoSignAsync(byte[] srcData, bool driverMode, string description) {
+ this.DoSignAsync(srcData, driverMode, description, null);
+ }
+
+ /// <remarks/>
+ public void DoSignAsync(byte[] srcData, bool driverMode, string description, object userState) {
+ if ((this.DoSignOperationCompleted == null)) {
+ this.DoSignOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDoSignOperationCompleted);
+ }
+ this.InvokeAsync("DoSign", new object[] {
+ srcData,
+ driverMode,
+ description}, this.DoSignOperationCompleted, userState);
+ }
+
+ private void OnDoSignOperationCompleted(object arg) {
+ if ((this.DoSignCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.DoSignCompleted(this, new DoSignCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ /// <remarks/>
+ public new void CancelAsync(object userState) {
+ base.CancelAsync(userState);
+ }
+
+ private bool IsLocalFileSystemWebService(string url) {
+ if (((url == null)
+ || (url == string.Empty))) {
+ return false;
+ }
+ System.Uri wsUri = new System.Uri(url);
+ if (((wsUri.Port >= 1024)
+ && (string.Compare(wsUri.Host, "localHost", System.StringComparison.OrdinalIgnoreCase) == 0))) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ public delegate void HelloWorldCompletedEventHandler(object sender, HelloWorldCompletedEventArgs e);
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class HelloWorldCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal HelloWorldCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public string Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((string)(this.results[0]));
+ }
+ }
+ }
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ public delegate void DoSignCompletedEventHandler(object sender, DoSignCompletedEventArgs e);
+
+ /// <remarks/>
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class DoSignCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal DoSignCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ /// <remarks/>
+ public byte[] Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((byte[])(this.results[0]));
+ }
+ }
+ }
+}
+
+#pragma warning restore 1591
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Web References/SignService/Sign.disco b/src/BuildUtil/Web References/SignService/Sign.disco
new file mode 100644
index 00000000..2fe47490
--- /dev/null
+++ b/src/BuildUtil/Web References/SignService/Sign.disco
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
+ <contractRef ref="http://dv/Sign/Sign.asmx?wsdl" docRef="http://dv/Sign/Sign.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
+ <soap address="http://dv/Sign/Sign.asmx" xmlns:q1="http://dv/Sign/" binding="q1:SignSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
+ <soap address="http://dv/Sign/Sign.asmx" xmlns:q2="http://dv/Sign/" binding="q2:SignSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
+</discovery> \ No newline at end of file
diff --git a/src/BuildUtil/Web References/SignService/Sign.wsdl b/src/BuildUtil/Web References/SignService/Sign.wsdl
new file mode 100644
index 00000000..fdb6fb28
--- /dev/null
+++ b/src/BuildUtil/Web References/SignService/Sign.wsdl
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://dv/Sign/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://dv/Sign/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+ <wsdl:types>
+ <s:schema elementFormDefault="qualified" targetNamespace="http://dv/Sign/">
+ <s:element name="HelloWorld">
+ <s:complexType />
+ </s:element>
+ <s:element name="HelloWorldResponse">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ <s:element name="DoSign">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="srcData" type="s:base64Binary" />
+ <s:element minOccurs="1" maxOccurs="1" name="driverMode" type="s:boolean" />
+ <s:element minOccurs="0" maxOccurs="1" name="description" type="s:string" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ <s:element name="DoSignResponse">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="DoSignResult" type="s:base64Binary" />
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ </s:schema>
+ </wsdl:types>
+ <wsdl:message name="HelloWorldSoapIn">
+ <wsdl:part name="parameters" element="tns:HelloWorld" />
+ </wsdl:message>
+ <wsdl:message name="HelloWorldSoapOut">
+ <wsdl:part name="parameters" element="tns:HelloWorldResponse" />
+ </wsdl:message>
+ <wsdl:message name="DoSignSoapIn">
+ <wsdl:part name="parameters" element="tns:DoSign" />
+ </wsdl:message>
+ <wsdl:message name="DoSignSoapOut">
+ <wsdl:part name="parameters" element="tns:DoSignResponse" />
+ </wsdl:message>
+ <wsdl:portType name="SignSoap">
+ <wsdl:operation name="HelloWorld">
+ <wsdl:input message="tns:HelloWorldSoapIn" />
+ <wsdl:output message="tns:HelloWorldSoapOut" />
+ </wsdl:operation>
+ <wsdl:operation name="DoSign">
+ <wsdl:input message="tns:DoSignSoapIn" />
+ <wsdl:output message="tns:DoSignSoapOut" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="SignSoap" type="tns:SignSoap">
+ <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="HelloWorld">
+ <soap:operation soapAction="http://dv/Sign/HelloWorld" style="document" />
+ <wsdl:input>
+ <soap:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="DoSign">
+ <soap:operation soapAction="http://dv/Sign/DoSign" style="document" />
+ <wsdl:input>
+ <soap:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:binding name="SignSoap12" type="tns:SignSoap">
+ <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="HelloWorld">
+ <soap12:operation soapAction="http://dv/Sign/HelloWorld" style="document" />
+ <wsdl:input>
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="DoSign">
+ <soap12:operation soapAction="http://dv/Sign/DoSign" style="document" />
+ <wsdl:input>
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="Sign">
+ <wsdl:port name="SignSoap" binding="tns:SignSoap">
+ <soap:address location="http://dv/Sign/Sign.asmx" />
+ </wsdl:port>
+ <wsdl:port name="SignSoap12" binding="tns:SignSoap12">
+ <soap12:address location="http://dv/Sign/Sign.asmx" />
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions> \ No newline at end of file
diff --git a/src/BuildUtil/Win32BuildSoftware.cs b/src/BuildUtil/Win32BuildSoftware.cs
new file mode 100644
index 00000000..8991da55
--- /dev/null
+++ b/src/BuildUtil/Win32BuildSoftware.cs
@@ -0,0 +1,160 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // Build Win32 software
+ public class BuildSoftwareWin32 : BuildSoftware
+ {
+ public BuildSoftwareWin32(Software software, int buildNumber, int version, string buildName, Cpu cpu, OS os)
+ : base(software, buildNumber, version, buildName, cpu, os)
+ {
+ }
+
+ // Run the build
+ public override void Build()
+ {
+ Semaphore sem = new Semaphore(BuildConfig.NumMultipleCompileTasks, BuildConfig.NumMultipleCompileTasks, "vpn_build_cross");
+ Con.WriteLine("Waiting for Semaphore...");
+ sem.WaitOne();
+ Con.WriteLine("Done.");
+ try
+ {
+ // Run the build
+ buildInstaller();
+ }
+ finally
+ {
+ sem.Release();
+ }
+ }
+
+ // Build the installer
+ void buildInstaller()
+ {
+ string outFileName = Path.Combine(Paths.ReleaseDir, this.OutputFileName);
+
+ string vpnsetup_exe = Path.Combine(Paths.BinDirName, "vpnsetup.exe");
+
+ try
+ {
+ File.Delete(outFileName);
+ }
+ catch
+ {
+ }
+
+ Win32BuildUtil.ExecCommand(vpnsetup_exe, string.Format("/SFXMODE:{1} /SFXOUT:\"{0}\"",
+ outFileName, Software.ToString()));
+
+ CodeSign.SignFile(outFileName, outFileName, "VPN Software", false);
+ }
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/Win32BuildUtil.cs b/src/BuildUtil/Win32BuildUtil.cs
new file mode 100644
index 00000000..5f478966
--- /dev/null
+++ b/src/BuildUtil/Win32BuildUtil.cs
@@ -0,0 +1,1063 @@
+// SoftEther VPN Source Code
+// Build Utility
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+using System;
+using System.Threading;
+using System.Text;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Security.Cryptography;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using CoreUtil;
+
+namespace BuildUtil
+{
+ // Build utility for Win32
+ public static class Win32BuildUtil
+ {
+ // Generate vpnweb.ocx
+ public static void GenerateVpnWebOcxCab(string dstFileName, string ocxFileName)
+ {
+ int build, version;
+ string name;
+ DateTime date;
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ string cabVer = string.Format("{0},{1},0,{2}", version / 100, version % 100, build);
+ string cabFileName = IO.CreateTempFileNameByExt(".cab");
+ Mutex m = new Mutex(false, "cabtmp_mutex");
+
+ m.WaitOne();
+
+ try
+ {
+ // Building the cab
+ string cabTmpDir = Path.Combine(Paths.TmpDirName, "cabtmp");
+
+ IO.MakeDir(cabTmpDir);
+ IO.DeleteFilesAndSubDirsInDir(cabTmpDir);
+
+ File.Copy(Path.Combine(Paths.BinDirName, ocxFileName), Path.Combine(cabTmpDir, "vpnweb.ocx"));
+
+ string infText = File.ReadAllText(Path.Combine(Path.Combine(Paths.BaseDirName, @"BuildFiles\OcxCabInf"), "vpnweb.inf"));
+ infText = Str.ReplaceStr(infText, "$CAB_VERSION$", cabVer);
+ File.WriteAllText(Path.Combine(cabTmpDir, "vpnweb.inf"), infText);
+
+ Win32BuildUtil.ExecCommand(Path.Combine(Paths.BaseDirName, @"BuildFiles\Utility\cabarc.exe"),
+ string.Format(@"-s 6144 n {0}\vpnweb.cab {0}\vpnweb.ocx {0}\vpnweb.inf", cabTmpDir));
+
+ File.Copy(Path.Combine(cabTmpDir, "vpnweb.cab"), cabFileName, true);
+ }
+ finally
+ {
+ m.ReleaseMutex();
+ }
+
+ CodeSign.SignFile(cabFileName, cabFileName, "VPN Software", false);
+
+ File.Copy(cabFileName, dstFileName, true);
+ }
+
+ // Generate a version information resource
+ public static void GenerateVersionInfoResource(string targetExeName, string outName, string rc_name)
+ {
+ int build, version;
+ string name;
+ DateTime date;
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ if (Str.IsEmptyStr(rc_name))
+ {
+ rc_name = "ver.rc";
+ }
+
+ string templateFileName = Path.Combine(Paths.BaseDirName, @"BuildFiles\VerScript\" + rc_name);
+ string body = Str.ReadTextFile(templateFileName);
+
+ string exeFileName = Path.GetFileName(targetExeName);
+ string internalName = Path.GetFileNameWithoutExtension(exeFileName);
+
+#if !BU_SOFTETHER
+ body = Str.ReplaceStr(body, "$PRODUCTNAME$", "PacketiX VPN");
+#else
+ body = Str.ReplaceStr(body, "$PRODUCTNAME$", "SoftEther VPN");
+#endif
+ body = Str.ReplaceStr(body, "$INTERNALNAME$", internalName);
+ body = Str.ReplaceStr(body, "$YEAR$", date.Year.ToString());
+ body = Str.ReplaceStr(body, "$FILENAME$", exeFileName);
+ body = Str.ReplaceStr(body, "$VER_MAJOR$", (version / 100).ToString());
+ body = Str.ReplaceStr(body, "$VER_MINOR$", (version % 100).ToString());
+ body = Str.ReplaceStr(body, "$VER_BUILD$", build.ToString());
+
+ IO f = IO.CreateTempFileByExt(".rc");
+ string filename = f.Name;
+
+ f.Write(Str.AsciiEncoding.GetBytes(body));
+
+ f.Close();
+
+ ExecCommand(Paths.RcFilename, "\"" + filename + "\"");
+
+ string rcDir = Path.GetDirectoryName(filename);
+ string rcFilename = Path.GetFileName(filename);
+ string rcFilename2 = Path.GetFileNameWithoutExtension(rcFilename);
+
+ string resFilename = Path.Combine(rcDir, rcFilename2) + ".res";
+
+ IO.MakeDirIfNotExists(Path.GetDirectoryName(outName));
+
+ IO.FileCopy(resFilename, outName, true, false);
+ }
+
+ // Flush to disk
+ public static void Flush()
+ {
+ string txt = IO.CreateTempFileNameByExt(".txt");
+ byte[] ret = Secure.Rand(64);
+
+ FileStream f = File.Create(txt);
+
+ f.Write(ret, 0, ret.Length);
+
+ f.Flush();
+
+ f.Close();
+
+ File.Delete(txt);
+ }
+
+ // Increment the build number
+ public static void IncrementBuildNumber()
+ {
+ int build, version;
+ string name;
+ DateTime date;
+
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+ build++;
+
+ WriteBuildInfoToTextFile(build, version, name, date);
+
+ SetNowDate();
+
+ Con.WriteLine("New build number: {0}", build);
+ }
+
+ // Set the date and time
+ public static void SetNowDate()
+ {
+ int build, version;
+ string name;
+ DateTime date;
+
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ date = DateTime.Now;
+
+ WriteBuildInfoToTextFile(build, version, name, date);
+ }
+
+ // Write the build number and the version number in the text file
+ public static void WriteBuildInfoToTextFile(int build, int version, string name, DateTime date)
+ {
+ string filename = Path.Combine(Paths.BaseDirName, "CurrentBuild.txt");
+
+ WriteBuildInfoToTextFile(build, version, name, date, filename);
+ }
+ public static void WriteBuildInfoToTextFile(int build, int version, string name, DateTime date, string filename)
+ {
+ using (StreamWriter w = new StreamWriter(filename))
+ {
+ w.WriteLine("BUILD_NUMBER {0}", build);
+ w.WriteLine("VERSION {0}", version);
+ w.WriteLine("BUILD_NAME {0}", name);
+ w.WriteLine("BUILD_DATE {0}", Str.DateTimeToStrShort(date));
+
+ w.Flush();
+ w.Close();
+ }
+ }
+
+ // Read the build number and the version number from a text file
+ public static void ReadBuildInfoFromTextFile(out int build, out int version, out string name, out DateTime date)
+ {
+ string filename = Path.Combine(Paths.BaseDirName, "CurrentBuild.txt");
+
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date, filename);
+ }
+ public static void ReadBuildInfoFromTextFile(out int build, out int version, out string name, out DateTime date, string filename)
+ {
+ char[] seps = { '\t', ' ', };
+ name = "";
+ date = new DateTime(0);
+
+ using (StreamReader r = new StreamReader(filename))
+ {
+ build = version = 0;
+
+ while (true)
+ {
+ string line = r.ReadLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ string[] tokens = line.Split(seps, StringSplitOptions.RemoveEmptyEntries);
+ if (tokens.Length == 2)
+ {
+ if (tokens[0].Equals("BUILD_NUMBER", StringComparison.InvariantCultureIgnoreCase))
+ {
+ build = int.Parse(tokens[1]);
+ }
+
+ if (tokens[0].Equals("VERSION", StringComparison.InvariantCultureIgnoreCase))
+ {
+ version = int.Parse(tokens[1]);
+ }
+
+ if (tokens[0].Equals("BUILD_NAME", StringComparison.InvariantCultureIgnoreCase))
+ {
+ name = tokens[1];
+
+ name = Str.ReplaceStr(name, "-", "_");
+ }
+
+ if (tokens[0].Equals("BUILD_DATE", StringComparison.InvariantCultureIgnoreCase))
+ {
+ date = Str.StrToDateTime(tokens[1]);
+ }
+ }
+ }
+
+ r.Close();
+
+ if (build == 0 || version == 0 || Str.IsEmptyStr(name) || date.Ticks == 0)
+ {
+ throw new ApplicationException(string.Format("Wrong file data: '{0}'", filename));
+ }
+ }
+ }
+
+ // Normalize the build information
+ public static void NormalizeBuildInfo()
+ {
+ SetNowDate();
+
+ int build, version;
+ string name;
+ DateTime date;
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+ string username = Env.UserName;
+ string pcname = Env.MachineName;
+
+ NormalizeSourceCode(build, version, username, pcname, date);
+ }
+
+ // Apply build number, version number, user name, and PC name to the source code
+ public static void NormalizeSourceCode(int buildNumber, int version, string userName, string pcName, DateTime date)
+ {
+ DateTime now = date;
+ char[] seps = { '\t', ' ', };
+
+ int i = pcName.IndexOf(".");
+ if (i != -1)
+ {
+ pcName = pcName.Substring(0, i);
+ }
+
+ userName = userName.ToLower();
+ pcName = pcName.ToLower();
+
+ string[] files = Util.CombineArray<string>(
+ Directory.GetFiles(Paths.BaseDirName, "*.h", SearchOption.AllDirectories));
+
+ foreach (string file in files)
+ {
+ string dir = Path.GetDirectoryName(file);
+ if (Str.InStr(dir, @"\.svn\") == false &&
+ Str.InStr(IO.GetRelativeFileName(file, Paths.BaseDirName), @"tmp\") == false)
+ {
+ byte[] srcData = File.ReadAllBytes(file);
+
+ int bomSize;
+ Encoding enc = Str.GetEncoding(srcData, out bomSize);
+ if (enc == null)
+ {
+ enc = Str.Utf8Encoding;
+ }
+ StringReader r = new StringReader(enc.GetString(Util.ExtractByteArray(srcData, bomSize, srcData.Length - bomSize)));
+ StringWriter w = new StringWriter();
+ bool somethingChanged = false;
+
+ while (true)
+ {
+ string line = r.ReadLine();
+ if (line == null)
+ {
+ break;
+ }
+ string newLine = null;
+
+ string[] tokens = line.Split(seps, StringSplitOptions.RemoveEmptyEntries);
+
+ if (tokens.Length >= 1)
+ {
+ if (file.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase))
+ {
+ if (tokens.Length == 3)
+ {
+ // Build number portion of the source code
+ if (tokens[0].Equals("//") && tokens[1].Equals("Build") && Str.IsNumber(tokens[2]))
+ {
+ newLine = line.Replace(tokens[2], buildNumber.ToString());
+ }
+ }
+ }
+
+ if (file.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase))
+ {
+ if (tokens.Length == 3)
+ {
+ // String part of the version information of Cedar.h
+ if (tokens[0].Equals("#define") && tokens[1].Equals("CEDAR_BUILD"))
+ {
+ newLine = line.Replace(tokens[2], buildNumber.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("CEDAR_VER"))
+ {
+ newLine = line.Replace(tokens[2], version.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILDER_NAME"))
+ {
+ newLine = line.Replace(tokens[2], "\"" + userName + "\"");
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_PLACE"))
+ {
+ newLine = line.Replace(tokens[2], "\"" + pcName + "\"");
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_Y"))
+ {
+ newLine = line.Replace(tokens[2], date.Year.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_M"))
+ {
+ newLine = line.Replace(tokens[2], date.Month.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_D"))
+ {
+ newLine = line.Replace(tokens[2], date.Day.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_HO"))
+ {
+ newLine = line.Replace(tokens[2], date.Hour.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_MI"))
+ {
+ newLine = line.Replace(tokens[2], date.Minute.ToString());
+ }
+
+ if (tokens[0].Equals("#define") && tokens[1].Equals("BUILD_DATE_SE"))
+ {
+ newLine = line.Replace(tokens[2], date.Second.ToString());
+ }
+ }
+
+ if (tokens.Length >= 3)
+ {
+ if (tokens[0].Equals("#define") && tokens[1].Equals("SUPPORTED_WINDOWS_LIST"))
+ {
+ newLine = "#define\tSUPPORTED_WINDOWS_LIST\t\t\"" + OSList.Windows.OSSimpleList + "\"";
+ }
+ }
+ }
+ }
+
+ if (newLine == null || newLine == line)
+ {
+ w.WriteLine(line);
+ }
+ else
+ {
+ w.WriteLine(newLine);
+
+ somethingChanged = true;
+ }
+ }
+
+ if (somethingChanged)
+ {
+ byte[] retData = Str.ConvertEncoding(Str.Utf8Encoding.GetBytes(w.ToString()), enc, bomSize != 0);
+
+ File.WriteAllBytes(file, retData);
+
+ Con.WriteLine("Modified: '{0}'.", file);
+ }
+ }
+ }
+ }
+
+ // Get the DebugSnapshot directory name
+ public static string GetDebugSnapstotDirName()
+ {
+ return Path.Combine(Paths.DebugSnapshotBaseDir, Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime));
+ }
+
+ // Copy DebugSnapshot
+ public static void CopyDebugSnapshot()
+ {
+ string snapDir = GetDebugSnapstotDirName();
+
+ CopyDebugSnapshot(snapDir);
+ }
+ public static void CopyDebugSnapshot(string snapDir, params string[] exclude_exts)
+ {
+ IO.CopyDir(Paths.BaseDirName, Path.Combine(snapDir, "Main"),
+ delegate(FileInfo fi)
+ {
+ string srcPath = fi.FullName;
+ string[] exts_default =
+ {
+ ".ncb", ".aps", ".suo", ".old", ".scc", ".vssscc", ".vspscc", ".cache", ".psess", ".tmp", ".dmp",
+ };
+
+ List<string> exts = new List<string>();
+
+ foreach (string ext in exts_default)
+ {
+ exts.Add(ext);
+ }
+
+ foreach (string ext in exclude_exts)
+ {
+ exts.Add(ext);
+ }
+
+ if (Str.InStr(srcPath, @"\.svn\", false))
+ {
+ return false;
+ }
+
+ if (Str.InStr(srcPath.Substring(3), @"\tmp\", false))
+ {
+ return false;
+ }
+
+ if (Str.InStr(srcPath, @"_log\", false))
+ {
+ return false;
+ }
+
+ if (Str.InStr(srcPath, @"\backup.vpn_", false))
+ {
+ return false;
+ }
+
+ foreach (string ext in exts)
+ {
+ if (srcPath.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ }
+
+ if (Str.InStr(srcPath, @"\hamcore\", false))
+ {
+ return true;
+ }
+
+ if (Str.InStr(srcPath, @"\hamcore_", false))
+ {
+ return true;
+ }
+
+ return true;
+ },
+ false, true, false, false);
+ }
+
+ // Execute building in Visual Studio
+ public static void BuildMain()
+ {
+ Mutex x = new Mutex(false, "VpnBuilderWin32_BuildMain");
+
+ x.WaitOne();
+
+ try
+ {
+ // Generate the contents of the batch file
+ string batFileName = Path.Combine(Paths.TmpDirName, "vc_build.cmd");
+ StreamWriter bat = new StreamWriter(batFileName, false, Str.ShiftJisEncoding);
+ bat.WriteLine("call \"{0}\"", Paths.VisualStudioVCBatchFileName);
+ bat.WriteLine("echo on");
+ bat.WriteLine("\"{0}\" /toolsversion:3.5 /verbosity:detailed /target:Clean /property:Configuration=Release /property:Platform=Win32 \"{1}\"",
+ Paths.MSBuildFileName, Paths.VPN4SolutionFileName);
+ bat.WriteLine("IF ERRORLEVEL 1 GOTO LABEL_ERROR");
+
+ bat.WriteLine("\"{0}\" /toolsversion:3.5 /verbosity:detailed /target:Clean /property:Configuration=Release /property:Platform=x64 \"{1}\"",
+ Paths.MSBuildFileName, Paths.VPN4SolutionFileName);
+ bat.WriteLine("IF ERRORLEVEL 1 GOTO LABEL_ERROR");
+
+ bat.WriteLine("\"{0}\" /toolsversion:3.5 /verbosity:detailed /target:Rebuild /property:Configuration=Release /property:Platform=Win32 \"{1}\"",
+ Paths.MSBuildFileName, Paths.VPN4SolutionFileName);
+ bat.WriteLine("IF ERRORLEVEL 1 GOTO LABEL_ERROR");
+
+ bat.WriteLine("\"{0}\" /toolsversion:3.5 /verbosity:detailed /target:Rebuild /property:Configuration=Release /property:Platform=x64 \"{1}\"",
+ Paths.MSBuildFileName, Paths.VPN4SolutionFileName);
+ bat.WriteLine("IF ERRORLEVEL 1 GOTO LABEL_ERROR");
+
+ bat.WriteLine(":LABEL_ERROR");
+
+ bat.WriteLine("EXIT %ERRORLEVEL%");
+
+ bat.Close();
+
+ ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", batFileName));
+
+ BuildReplaceHeader();
+ }
+ finally
+ {
+ x.ReleaseMutex();
+ }
+ }
+
+ // Generate the Replace.h
+ public static void BuildReplaceHeader()
+ {
+ List<string> o = new List<string>();
+ int maxLen = 0;
+
+ // Read the map file
+ string[] lines = File.ReadAllLines(Path.Combine(Paths.BaseDirName, @"DebugFiles\map\Win32_Release\vpnserver.map"));
+ char[] sps = { ' ', '\t', };
+
+ foreach (string line in lines)
+ {
+ string[] tokens = line.Trim().Split(sps, StringSplitOptions.RemoveEmptyEntries);
+
+ if (tokens.Length == 5)
+ {
+ if (tokens[0].StartsWith("0001:", StringComparison.InvariantCultureIgnoreCase))
+ {
+ if (tokens[0].Length == 13)
+ {
+ if (tokens[2].Length == 8)
+ {
+ if (tokens[3].Equals("f", StringComparison.InvariantCultureIgnoreCase))
+ {
+ if (tokens[4].StartsWith("Mayaqua:", StringComparison.InvariantCultureIgnoreCase) ||
+ tokens[4].StartsWith("Cedar:", StringComparison.InvariantCultureIgnoreCase))
+ {
+ string name = tokens[1];
+
+ if (name.Length >= 2)
+ {
+ if (Str.InStr(name, "mktime") == false &&
+ Str.InStr(name, "gmtime") == false &&
+ Str.InStr(name, "stdin") == false &&
+ Str.InStr(name, "stdout") == false &&
+ Str.InStr(name, "@") == false &&
+ Str.InStr(name, "localtime") == false)
+ {
+ string tmp = tokens[4].Split(':')[1];
+
+ if (tmp[0] >= 'A' && tmp[0] <= 'Z' &&
+ Str.InStr(tmp, "_") == false)
+ {
+ o.Add(name.Substring(1));
+
+ maxLen = Math.Max(maxLen, name.Length);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ o.Sort();
+
+ // Generate the Replace.h
+ string filename = Path.Combine(Paths.BaseDirName, @"DebugFiles\Replace.h");
+ StreamWriter w = new StreamWriter(filename);
+
+ w.WriteLine("// PacketiX VPN Function Name Replacement Header File");
+ w.WriteLine("//");
+ w.WriteLine("// Copyright (c) SoftEther Corporation.");
+ w.WriteLine("// All Rights Reserved.");
+ w.WriteLine("//");
+ w.WriteLine("// SoftEther Confidential");
+ w.WriteLine("//");
+ w.WriteLine();
+
+ foreach (string name in o)
+ {
+ if (Str.StrCmpi(name, "VLanGetPacketAdapter") == false)
+ {
+ string tmp = Str.ByteToHex(Secure.HashMD5(Str.Utf8Encoding.GetBytes("xx" + name)), "");
+ string tmp2 = "VPN_" + tmp.Substring(0, 12).ToUpper();
+
+ w.WriteLine("#define {0,-" + maxLen.ToString() + "} {1}",
+ name, tmp2);
+ }
+ }
+
+ w.WriteLine();
+
+ w.Flush();
+ w.Close();
+ }
+
+ // Command execution
+ public static void ExecCommand(string exe, string arg)
+ {
+ ExecCommand(exe, arg, false);
+ }
+ public static void ExecCommand(string exe, string arg, bool shell_execute)
+ {
+ Process p = new Process();
+ p.StartInfo.FileName = exe;
+ p.StartInfo.Arguments = arg;
+ p.StartInfo.UseShellExecute = shell_execute;
+
+ if (shell_execute)
+ {
+ p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ }
+
+ Con.WriteLine("Executing '{0} {1}'...", exe, arg);
+
+ p.Start();
+
+ p.WaitForExit();
+
+ int ret = p.ExitCode;
+ if (ret != 0)
+ {
+ throw new ApplicationException(string.Format("Child process '{0}' returned error code {1}.", exe, ret));
+ }
+
+ Kernel.SleepThread(50);
+ }
+
+ // Get whether the specified fileis a target of signature
+ public static bool IsFileSignable(string fileName)
+ {
+ if (fileName.IndexOf(@".svn", StringComparison.InvariantCultureIgnoreCase) != -1 ||
+ fileName.StartsWith(".svn", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("vpn16.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("BuildUtil.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("BuildUtilTmp.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("CoreUtil.dll", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("npptools.dll", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("winpcap_installer.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("winpcap_installer_win9x.exe", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("VpnGatePlugin_x64.dll", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (fileName.EndsWith("VpnGatePlugin_x86.dll", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return false;
+ }
+ if (Str.InStr(fileName, "_nosign", false))
+ {
+ return false;
+ }
+
+ if (fileName.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase) ||
+ fileName.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) ||
+ fileName.EndsWith(".ocx", StringComparison.InvariantCultureIgnoreCase) ||
+ fileName.EndsWith(".sys", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ // Create and sign the Inf file and the catalog file for SeLow
+ public static void SignSeLowInfFiles(string cpu)
+ {
+ int build, version;
+ string name;
+ DateTime date;
+
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ string hamcore = Path.Combine(Paths.BinDirName, "hamcore");
+ string sys_src = Path.Combine(hamcore, "SeLow_" + cpu + ".sys");
+ string inf_src = Path.Combine(hamcore, "SeLow_" + cpu + ".inf");
+
+ Con.WriteLine("Generating INF Files for SeLow...");
+
+ string dst_dir = Path.Combine(hamcore, @"inf\selow_" + cpu);
+
+ if (ExeSignChecker.CheckFileDigitalSignature(sys_src) == false ||
+ ExeSignChecker.IsKernelModeSignedFile(sys_src) == false)
+ {
+ throw new ApplicationException(sys_src + " is not signed.");
+ }
+
+ generateINFFilesForPlatform(inf_src, sys_src, null, dst_dir, version, build, date, true);
+
+ Con.WriteLine("Generating INF Files for SeLow Ok.");
+ }
+
+ // Create Inf file for Windows 8
+ public static void GenerateINFFilesForWindows8(string cpu)
+ {
+ int build, version;
+ string name;
+ DateTime date;
+ ReadBuildInfoFromTextFile(out build, out version, out name, out date);
+
+ string hamcore = Path.Combine(Paths.BinDirName, "hamcore");
+ string inf_src_x86 = Path.Combine(hamcore, "vpn_driver.inf");
+ string inf_src_x64 = Path.Combine(hamcore, "vpn_driver_x64.inf");
+ string sys_src_x86 = Path.Combine(hamcore, "vpn_driver.sys");
+ string sys_src_x64 = Path.Combine(hamcore, "vpn_driver_x64.sys");
+ string sys6_src_x86 = Path.Combine(hamcore, "vpn_driver6.sys");
+ string sys6_src_x64 = Path.Combine(hamcore, "vpn_driver6_x64.sys");
+
+ Con.WriteLine("Generating INF Files for Windows 8...");
+
+ string dst_x86 = Path.Combine(hamcore, @"inf\x86");
+ string dst_x64 = Path.Combine(hamcore, @"inf\x64");
+
+ if (Str.StrCmpi(cpu, "x64"))
+ {
+ if (ExeSignChecker.CheckFileDigitalSignature(sys_src_x64) == false || ExeSignChecker.IsKernelModeSignedFile(sys_src_x64) == false)
+ {
+ throw new ApplicationException(sys_src_x64 + " is not signed.");
+ }
+
+ generateINFFilesForPlatform(inf_src_x64, sys_src_x64, sys6_src_x64, dst_x64, version, build, date, false);
+ }
+ else
+ {
+ if (ExeSignChecker.CheckFileDigitalSignature(sys_src_x86) == false || ExeSignChecker.IsKernelModeSignedFile(sys_src_x86) == false)
+ {
+ throw new ApplicationException(sys_src_x86 + " is not signed.");
+ }
+
+ generateINFFilesForPlatform(inf_src_x86, sys_src_x86, sys6_src_x86, dst_x86, version, build, date, false);
+ }
+
+ Con.WriteLine("Generating INF Files for Windows 8 Ok.");
+ }
+ static void generateINFFilesForPlatform(string inf, string sys, string sys6, string dstDir, int ver, int build, DateTime date, bool selow)
+ {
+
+ string cdfFileName = Path.Combine(dstDir, "inf.cdf");
+ string catFileName = Path.Combine(dstDir, "inf.cat");
+ StringWriter sw = new StringWriter();
+
+ string txt = File.ReadAllText(inf, Str.ShiftJisEncoding);
+
+ IO.DeleteFilesAndSubDirsInDir(dstDir);
+ IO.MakeDirIfNotExists(dstDir);
+
+ string dst_sys_name = Path.Combine(dstDir, Path.GetFileName(sys));
+ File.Copy(sys, dst_sys_name, true);
+
+ string dst_sys6_name = null;
+ if (sys6 != null)
+ {
+ dst_sys6_name = Path.Combine(dstDir, Path.GetFileName(sys6));
+ File.Copy(sys6, dst_sys6_name, true);
+ }
+
+ sw.WriteLine("[CatalogHeader]");
+ sw.WriteLine("name=inf.cat");
+ sw.WriteLine();
+ sw.WriteLine("[CatalogFiles]");
+ sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_sys_name));
+
+ if (sys6 != null)
+ {
+ sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_sys6_name));
+ }
+
+ int i;
+ for (i = 1; i < 128; i++)
+ {
+ string name = "VPN";
+ if (i >= 2)
+ {
+ name += i.ToString();
+ }
+
+ if (selow)
+ {
+ name = "selow";
+ }
+
+ //string mac = "00AC0011" + i.ToString("X2") + "01";
+ string mac = "000001000001";
+ string sys_name = "Neo_" + name + ".sys";
+
+ string body = txt;
+ body = Str.ReplaceStr(body, "$TAG_SYS_NAME$", sys_name);
+ body = Str.ReplaceStr(body, "$TAG_INSTANCE_NAME$", name);
+ body = Str.ReplaceStr(body, "$TAG_MAC_ADDRESS$", mac);
+ body = Str.ReplaceStr(body, "$YEAR$", date.Year.ToString("D4"));
+ body = Str.ReplaceStr(body, "$MONTH$", date.Month.ToString("D2"));
+ body = Str.ReplaceStr(body, "$DAY$", date.Day.ToString("D2"));
+ body = Str.ReplaceStr(body, "$VER_MAJOR$", (ver / 100).ToString());
+ body = Str.ReplaceStr(body, "$VER_MINOR$", (ver % 100).ToString());
+ body = Str.ReplaceStr(body, "$VER_BUILD$", build.ToString());
+ body = Str.ReplaceStr(body, "[Manufacturer]", "CatalogFile.NT\t\t\t\t= inf_" + name + ".cat\r\n\r\n[Manufacturer]");
+
+ string dst_inf_name = Path.Combine(dstDir, "INF_" + name + ".inf");
+
+ if (selow)
+ {
+ dst_inf_name = Path.Combine(dstDir, Path.GetFileName(inf));
+ }
+
+ if (selow)
+ {
+ body += "\r\n; Auto Generated " + Str.DateTimeToStrShortWithMilliSecs(DateTime.Now) + "\r\n\r\n";
+ }
+
+ File.WriteAllText(dst_inf_name, body, Str.ShiftJisEncoding);
+
+ sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_inf_name));
+
+ if (selow)
+ {
+ break;
+ }
+ }
+ sw.WriteLine();
+
+ File.WriteAllText(cdfFileName, sw.ToString());
+
+ // generate catalog file
+ Directory.SetCurrentDirectory(dstDir);
+ ExecCommand(Paths.MakeCatFilename, string.Format("\"{0}\"", cdfFileName));
+
+ // sign catalog file
+ CodeSign.SignFile(catFileName, catFileName, "Catalog File", false);
+
+ // delete cdf file
+ File.Delete(cdfFileName);
+
+ // delete sys file
+ File.Delete(dst_sys_name);
+
+ if (sys6 != null)
+ {
+ File.Delete(dst_sys6_name);
+ }
+ }
+
+ // Sign for all binary files (series mode)
+ public static void SignAllBinaryFilesSerial()
+ {
+ string[] files = Directory.GetFiles(Paths.BinDirName, "*", SearchOption.AllDirectories);
+
+ foreach (string file in files)
+ {
+ if (IsFileSignable(file))
+ {
+ bool isDriver = file.EndsWith(".sys", StringComparison.InvariantCultureIgnoreCase);
+
+ // Check whether this file is signed
+ bool isSigned = ExeSignChecker.CheckFileDigitalSignature(file);
+ if (isSigned && isDriver)
+ {
+ isSigned = ExeSignChecker.IsKernelModeSignedFile(file);
+ }
+
+ Con.WriteLine("The file '{0}': {1}.", file, isSigned ? "Already signed" : "Not yet signed");
+
+ if (isSigned == false)
+ {
+ Con.WriteLine("Signing...");
+
+ CodeSign.SignFile(file, file, "VPN Software", isDriver);
+ }
+ }
+ }
+ }
+
+ // Sign for all binary files (parallel mode)
+ public static void SignAllBinaryFiles()
+ {
+ string[] files = Directory.GetFiles(Paths.BinDirName, "*", SearchOption.AllDirectories);
+
+ List<string> filename_list = new List<string>();
+
+ foreach (string file in files)
+ {
+ if (IsFileSignable(file))
+ {
+ bool isDriver = file.EndsWith(".sys", StringComparison.InvariantCultureIgnoreCase);
+
+ // Check whether this file is signed
+ bool isSigned = ExeSignChecker.CheckFileDigitalSignature(file);
+ if (isSigned && isDriver)
+ {
+ isSigned = ExeSignChecker.IsKernelModeSignedFile(file);
+ }
+
+ Con.WriteLine("The file '{0}': {1}.", file, isSigned ? "Already signed" : "Not yet signed");
+
+ if (isSigned == false)
+ {
+ filename_list.Add(file);
+ }
+ }
+ }
+
+ Con.WriteLine("Start ProcessWorkQueue for Signing...\n");
+ ThreadObj.ProcessWorkQueue(sign_thread, 40, filename_list.ToArray());
+ Con.WriteLine("ProcessWorkQueue for Signing completed.\n");
+ }
+
+ // Binary file signature thread
+ static void sign_thread(object param)
+ {
+ string filename = (string)param;
+ bool isDriver = filename.EndsWith(".sys", StringComparison.InvariantCultureIgnoreCase);
+
+ Con.WriteLine("Signing...");
+
+ CodeSign.SignFile(filename, filename, "VPN Software", isDriver);
+ }
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/BuildUtil/app.config b/src/BuildUtil/app.config
new file mode 100644
index 00000000..39279829
--- /dev/null
+++ b/src/BuildUtil/app.config
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <configSections>
+ <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+ <section name="BuildUtil.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </sectionGroup>
+ </configSections>
+ <applicationSettings>
+ <BuildUtil.Properties.Settings>
+ <setting name="BuildUtil_SignService_Sign" serializeAs="String">
+ <value>http://dv/Sign/Sign.asmx</value>
+ </setting>
+ <setting name="BuildUtilTmp_HvSignService_Sign" serializeAs="String">
+ <value>http://hvsigncode/Sign.asmx</value>
+ </setting>
+ </BuildUtil.Properties.Settings>
+ </applicationSettings>
+</configuration> \ No newline at end of file
diff --git a/src/Cedar/Account.c b/src/Cedar/Account.c
new file mode 100644
index 00000000..42acda2e
--- /dev/null
+++ b/src/Cedar/Account.c
@@ -0,0 +1,1419 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Account.c
+// Account Manager
+
+#include "CedarPch.h"
+
+// Policy items
+POLICY_ITEM policy_item[] =
+{
+// ID, Value, Omittable, Min, Max, Default, Unit name
+// Ver 2.0
+ {0, false, false, 0, 0, 0, NULL}, // Access
+ {1, false, false, 0, 0, 0, NULL}, // DHCPFilter
+ {2, false, false, 0, 0, 0, NULL}, // DHCPNoServer
+ {3, false, false, 0, 0, 0, NULL}, // DHCPForce
+ {4, false, false, 0, 0, 0, NULL}, // NoBridge
+ {5, false, false, 0, 0, 0, NULL}, // NoRouting
+ {6, false, false, 0, 0, 0, NULL}, // CheckMac
+ {7, false, false, 0, 0, 0, NULL}, // CheckIP
+ {8, false, false, 0, 0, 0, NULL}, // ArpDhcpOnly
+ {9, false, false, 0, 0, 0, NULL}, // PrivacyFilter
+ {10, false, false, 0, 0, 0, NULL}, // NoServer
+ {11, false, false, 0, 0, 0, NULL}, // NoBroadcastLimiter
+ {12, false, false, 0, 0, 0, NULL}, // MonitorPort
+ {13, true, false, 1, 32, 32, "POL_INT_COUNT"}, // MaxConnection
+ {14, true, false, 5, 60, 20, "POL_INT_SEC"}, // TimeOut
+ {15, true, true, 1, 65535, 0, "POL_INT_COUNT"}, // MaxMac
+ {16, true, true, 1, 65535, 0, "POL_INT_COUNT"}, // MaxIP
+ {17, true, true, 1, 4294967295UL, 0, "POL_INT_BPS"}, // MaxUpload
+ {18, true, true, 1, 4294967295UL, 0, "POL_INT_BPS"}, // MaxDownload
+ {19, false, false, 0, 0, 0, NULL}, // FixPassword
+ {20, true, true, 1, 65535, 0, "POL_INT_COUNT"}, // MultiLogins
+ {21, false, false, 0, 0, 0, NULL}, // NoQoS
+// Ver 3.0
+ {22, false, false, 0, 0, 0, NULL}, // RSandRAFilter
+ {23, false, false, 0, 0, 0, NULL}, // RAFilter
+ {24, false, false, 0, 0, 0, NULL}, // DHCPv6Filter
+ {25, false, false, 0, 0, 0, NULL}, // DHCPv6NoServer
+ {26, false, false, 0, 0, 0, NULL}, // NoRoutingV6
+ {27, false, false, 0, 0, 0, NULL}, // CheckIPv6
+ {28, false, false, 0, 0, 0, NULL}, // NoServerV6
+ {29, true, true, 1, 65535, 0, "POL_INT_COUNT"}, // MaxIPv6
+ {30, false, false, 0, 0, 0, NULL}, // NoSavePassword
+ {31, true, true, 1, 4294967295UL, 0, "POL_INT_SEC"}, // AutoDisconnect
+ {32, false, false, 0, 0, 0, NULL}, // FilterIPv4
+ {33, false, false, 0, 0, 0, NULL}, // FilterIPv6
+ {34, false, false, 0, 0, 0, NULL}, // FilterNonIP
+ {35, false, false, 0, 0, 0, NULL}, // NoIPv6DefaultRouterInRA
+ {36, false, false, 0, 0, 0, NULL}, // NoIPv6DefaultRouterInRAWhenIPv6
+ {37, true, true, 1, 4095, 0, "POL_INT_VLAN"}, // VLanId
+};
+
+// Normalize policy name
+char *NormalizePolicyName(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ return PolicyIdToStr(PolicyStrToId(name));
+}
+
+// Format policy value
+void FormatPolicyValue(wchar_t *str, UINT size, UINT id, UINT value)
+{
+ POLICY_ITEM *p;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ p = GetPolicyItem(id);
+
+ if (p->TypeInt == false)
+ {
+ // bool type
+ if (value == 0)
+ {
+ UniStrCpy(str, size, L"No");
+ }
+ else
+ {
+ UniStrCpy(str, size, L"Yes");
+ }
+ }
+ else
+ {
+ // int type
+ if (value == 0 && p->AllowZero)
+ {
+ UniStrCpy(str, size, _UU("CMD_NO_SETTINGS"));
+ }
+ else
+ {
+ UniFormat(str, size, _UU(p->FormatStr), value);
+ }
+ }
+}
+
+// Get description string for range of the policy value
+void GetPolicyValueRangeStr(wchar_t *str, UINT size, UINT id)
+{
+ POLICY_ITEM *p;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ p = GetPolicyItem(id);
+
+ if (p->TypeInt == false)
+ {
+ // bool type
+ UniStrCpy(str, size, _UU("CMD_PolicyList_Range_Bool"));
+ }
+ else
+ {
+ wchar_t *tag;
+ wchar_t tmp1[256], tmp2[256];
+
+ // int type
+ if (p->AllowZero)
+ {
+ tag = _UU("CMD_PolicyList_Range_Int_2");
+ }
+ else
+ {
+ tag = _UU("CMD_PolicyList_Range_Int_1");
+ }
+
+ UniFormat(tmp1, sizeof(tmp1), _UU(p->FormatStr), p->MinValue);
+ UniFormat(tmp2, sizeof(tmp2), _UU(p->FormatStr), p->MaxValue);
+
+ UniFormat(str, size, tag, tmp1, tmp2);
+ }
+}
+
+// Get a policy item for id
+POLICY_ITEM *GetPolicyItem(UINT id)
+{
+ return &policy_item[id];
+}
+
+// Does cascade connection support the specified policy?
+bool PolicyIsSupportedForCascade(UINT i)
+{
+ if (i == 0 || i == 4 || i == 5 || i == 9 || i == 12 || i == 13 ||
+ i == 14 || i == 19 || i == 20 || i == 21 || i == 26 || i == 30 || i == 31 || i == 36)
+ {
+ // These items are not supported by cascade connection.
+ return false;
+ }
+
+ return true;
+}
+
+// Get policy name
+char *PolicyIdToStr(UINT i)
+{
+ switch (i)
+ {
+ // Ver 2.0
+ case 0: return "Access";
+ case 1: return "DHCPFilter";
+ case 2: return "DHCPNoServer";
+ case 3: return "DHCPForce";
+ case 4: return "NoBridge";
+ case 5: return "NoRouting";
+ case 6: return "CheckMac";
+ case 7: return "CheckIP";
+ case 8: return "ArpDhcpOnly";
+ case 9: return "PrivacyFilter";
+ case 10: return "NoServer";
+ case 11: return "NoBroadcastLimiter";
+ case 12: return "MonitorPort";
+ case 13: return "MaxConnection";
+ case 14: return "TimeOut";
+ case 15: return "MaxMac";
+ case 16: return "MaxIP";
+ case 17: return "MaxUpload";
+ case 18: return "MaxDownload";
+ case 19: return "FixPassword";
+ case 20: return "MultiLogins";
+ case 21: return "NoQoS";
+
+ // Ver 3.0
+ case 22: return "RSandRAFilter";
+ case 23: return "RAFilter";
+ case 24: return "DHCPv6Filter";
+ case 25: return "DHCPv6NoServer";
+ case 26: return "NoRoutingV6";
+ case 27: return "CheckIPv6";
+ case 28: return "NoServerV6";
+ case 29: return "MaxIPv6";
+ case 30: return "NoSavePassword";
+ case 31: return "AutoDisconnect";
+ case 32: return "FilterIPv4";
+ case 33: return "FilterIPv6";
+ case 34: return "FilterNonIP";
+ case 35: return "NoIPv6DefaultRouterInRA";
+ case 36: return "NoIPv6DefaultRouterInRAWhenIPv6";
+ case 37: return "VLanId";
+ }
+
+ return NULL;
+}
+
+// Get policy id for name
+UINT PolicyStrToId(char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return INFINITE;
+ }
+
+ for (i = 0;i < NUM_POLICY_ITEM;i++)
+ {
+ if (StartWith(PolicyIdToStr(i), name))
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Get number of policies
+UINT PolicyNum()
+{
+ return NUM_POLICY_ITEM;
+}
+
+// Check the name is valid for account name
+bool IsUserName(char *name)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ name = tmp;
+
+ Trim(name);
+
+ if (StrLen(name) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, "*") == 0)
+ {
+ return true;
+ }
+
+ if (IsSafeStr(name) == false)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, LINK_USER_NAME) == 0)
+ {
+ return false;
+ }
+
+ if (StartWith(name, L3_USERNAME))
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, LINK_USER_NAME_PRINT) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, SNAT_USER_NAME) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, SNAT_USER_NAME_PRINT) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, BRIDGE_USER_NAME) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, BRIDGE_USER_NAME_PRINT) == 0)
+ {
+ return false;
+ }
+
+ if (StrCmpi(name, ADMINISTRATOR_USERNAME) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get policy title
+wchar_t *GetPolicyTitle(UINT id)
+{
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "POL_%u", id);
+
+ return _UU(tmp);
+}
+
+// Get policy description
+wchar_t *GetPolicyDescription(UINT id)
+{
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "POL_EX_%u", id);
+
+ return _UU(tmp);
+}
+
+// Clone the policy value
+POLICY *ClonePolicy(POLICY *policy)
+{
+ POLICY *ret;
+ // Validate arguments
+ if (policy == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(POLICY));
+ Copy(ret, policy, sizeof(POLICY));
+
+ return ret;
+}
+
+// Overwrite policy value (If old version data overwrites new version, leave new version value as it is.)
+void OverwritePolicy(POLICY **target, POLICY *p)
+{
+ // Validate arguments
+ if (target == NULL)
+ {
+ return;
+ }
+
+ if (p == NULL)
+ {
+ // Erase policy
+ if (*target != NULL)
+ {
+ Free(*target);
+ *target = NULL;
+ }
+ }
+ else
+ {
+ if (p->Ver3)
+ {
+ // Ver 3
+ if (*target != NULL)
+ {
+ Free(*target);
+ *target = NULL;
+ }
+
+ *target = ClonePolicy(p);
+ }
+ else
+ {
+ // Ver 2
+ if (*target == NULL)
+ {
+ *target = ClonePolicy(p);
+ }
+ else
+ {
+ Copy(*target, p, NUM_POLICY_ITEM_FOR_VER2 * sizeof(UINT));
+ }
+ }
+ }
+}
+
+// Set user policy
+void SetUserPolicy(USER *u, POLICY *policy)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ Lock(u->lock);
+ {
+ OverwritePolicy(&u->Policy, policy);
+ }
+ Unlock(u->lock);
+}
+
+// Get user policy
+POLICY *GetUserPolicy(USER *u)
+{
+ POLICY *ret;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(u->lock);
+ {
+ if (u->Policy == NULL)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = ClonePolicy(u->Policy);
+ }
+ }
+ Unlock(u->lock);
+
+ return ret;
+}
+
+// Set group policy
+void SetGroupPolicy(USERGROUP *g, POLICY *policy)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Lock(g->lock);
+ {
+ OverwritePolicy(&g->Policy, policy);
+ }
+ Unlock(g->lock);
+}
+
+// Get group policy
+POLICY *GetGroupPolicy(USERGROUP *g)
+{
+ POLICY *ret;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(g->lock);
+ {
+ if (g->Policy == NULL)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = ClonePolicy(g->Policy);
+ }
+ }
+ Unlock(g->lock);
+
+ return ret;
+}
+
+// Get default policy template
+POLICY *GetDefaultPolicy()
+{
+ static POLICY def_policy =
+ {
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 32,
+ 20,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ false,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ false,
+ };
+
+ return &def_policy;
+}
+
+// Create a NT authentication data
+void *NewNTAuthData(wchar_t *username)
+{
+ AUTHNT *a;
+ // Validate arguments
+ a = ZeroMallocEx(sizeof(AUTHNT), true);
+ a->NtUsername = CopyUniStr(username);
+
+ return a;
+}
+
+// Create a Radius authentication data
+void *NewRadiusAuthData(wchar_t *username)
+{
+ AUTHRADIUS *a;
+ // Validate arguments
+ a = ZeroMallocEx(sizeof(AUTHRADIUS), true);
+ a->RadiusUsername = CopyUniStr(username);
+
+ return a;
+}
+
+// Create a root certification authentication data
+void *NewRootCertAuthData(X_SERIAL *serial, wchar_t *common_name)
+{
+ AUTHROOTCERT *a;
+
+ a = ZeroMallocEx(sizeof(AUTHROOTCERT), true);
+ if (common_name != NULL && UniIsEmptyStr(common_name) == false)
+ {
+ a->CommonName = CopyUniStr(common_name);
+ }
+ if (serial != NULL && serial->size >= 1)
+ {
+ a->Serial = CloneXSerial(serial);
+ }
+
+ return a;
+}
+
+// Create an authentication data for user certification
+void *NewUserCertAuthData(X *x)
+{
+ AUTHUSERCERT *a;
+
+ a = ZeroMalloc(sizeof(AUTHUSERCERT));
+ a->UserX = CloneX(x);
+
+ return a;
+}
+
+// Hash the password
+void HashPassword(void *dst, char *username, char *password)
+{
+ BUF *b;
+ char *username_upper;
+ // Validate arguments
+ if (dst == NULL || username == NULL || password == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ username_upper = CopyStr(username);
+ StrUpper(username_upper);
+ WriteBuf(b, password, StrLen(password));
+ WriteBuf(b, username_upper, StrLen(username_upper));
+ Hash(dst, b->Buf, b->Size, true);
+
+ FreeBuf(b);
+ Free(username_upper);
+}
+
+// Create a password authentication data
+void *NewPasswordAuthData(char *username, char *password)
+{
+ AUTHPASSWORD *pw;
+ // Validate arguments
+ if (username == NULL || password == NULL)
+ {
+ return NULL;
+ }
+
+ pw = ZeroMalloc(sizeof(AUTHPASSWORD));
+ HashPassword(pw->HashedKey, username, password);
+ GenerateNtPasswordHash(pw->NtLmSecureHash, password);
+
+ return pw;
+}
+
+// Create a password authentication data for the hashed password
+void *NewPasswordAuthDataRaw(UCHAR *hashed_password, UCHAR *ntlm_secure_hash)
+{
+ AUTHPASSWORD *pw;
+ // Validate arguments
+ if (hashed_password == NULL)
+ {
+ return NULL;
+ }
+
+ pw = ZeroMalloc(sizeof(AUTHPASSWORD));
+ Copy(pw->HashedKey, hashed_password, SHA1_SIZE);
+
+ if (ntlm_secure_hash != NULL)
+ {
+ Copy(pw->NtLmSecureHash, ntlm_secure_hash, MD5_SIZE);
+ }
+
+ return pw;
+}
+
+// Clone authentication data
+void *CopyAuthData(void *authdata, UINT authtype)
+{
+ AUTHPASSWORD *pw = (AUTHPASSWORD *)authdata;
+ AUTHUSERCERT *usercert = (AUTHUSERCERT *)authdata;
+ AUTHROOTCERT *rootcert = (AUTHROOTCERT *)authdata;
+ AUTHRADIUS *radius = (AUTHRADIUS *)authdata;
+ AUTHNT *nt = (AUTHNT *)authdata;
+ // Validate arguments
+ if (authdata == NULL || authtype == AUTHTYPE_ANONYMOUS)
+ {
+ return NULL;
+ }
+
+ switch (authtype)
+ {
+ case AUTHTYPE_PASSWORD:
+ {
+ AUTHPASSWORD *ret = ZeroMalloc(sizeof(AUTHPASSWORD));
+ Copy(ret, pw, sizeof(AUTHPASSWORD));
+ return ret;
+ }
+ break;
+
+ case AUTHTYPE_USERCERT:
+ {
+ AUTHUSERCERT *ret = ZeroMalloc(sizeof(AUTHUSERCERT));
+ ret->UserX = CloneX(usercert->UserX);
+ return ret;
+ }
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ {
+ AUTHROOTCERT *ret = ZeroMalloc(sizeof(AUTHROOTCERT));
+ ret->CommonName = CopyUniStr(rootcert->CommonName);
+ ret->Serial = CloneXSerial(rootcert->Serial);
+ return ret;
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ {
+ AUTHRADIUS *ret = ZeroMalloc(sizeof(AUTHRADIUS));
+ ret->RadiusUsername = UniCopyStr(radius->RadiusUsername);
+ return ret;
+ }
+ break;
+
+ case AUTHTYPE_NT:
+ {
+ AUTHNT *ret = ZeroMalloc(sizeof(AUTHNT));
+ ret->NtUsername = UniCopyStr(nt->NtUsername);
+ return ret;
+ }
+ break;
+ }
+
+ return NULL;
+}
+
+// Set authentication data to the user
+void SetUserAuthData(USER *u, UINT authtype, void *authdata)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+ if (authtype != AUTHTYPE_ANONYMOUS && authdata == NULL)
+ {
+ return;
+ }
+
+ Lock(u->lock);
+ {
+ if (u->AuthType != AUTHTYPE_ANONYMOUS)
+ {
+ if (u->AuthType == AUTHTYPE_PASSWORD && authtype == AUTHTYPE_PASSWORD)
+ {
+ AUTHPASSWORD *pw_old = (AUTHPASSWORD *)u->AuthData;
+ AUTHPASSWORD *pw_new = (AUTHPASSWORD *)authdata;
+
+ // Copy NTLM hash for new password from old data, if the password is not changed
+ // and management tool don't send NTLM hash.
+
+ if (Cmp(pw_old->HashedKey, pw_new->HashedKey, SHA1_SIZE) == 0)
+ {
+ if (IsZero(pw_new->NtLmSecureHash, MD5_SIZE))
+ {
+ Copy(pw_new->NtLmSecureHash, pw_old->NtLmSecureHash, MD5_SIZE);
+ }
+ }
+ }
+
+ // Free current authentication data
+ FreeAuthData(u->AuthType, u->AuthData);
+ }
+ // Set new authentication data
+ u->AuthType = authtype;
+ u->AuthData = authdata;
+ }
+ Unlock(u->lock);
+}
+
+// Cumulate group traffic data
+void AddGroupTraffic(USERGROUP *g, TRAFFIC *diff)
+{
+ // Validate arguments
+ if (g == NULL || diff == NULL)
+ {
+ return;
+ }
+
+ Lock(g->lock);
+ {
+ AddTraffic(g->Traffic, diff);
+ }
+ Unlock(g->lock);
+}
+
+// Cumulate user traffic data
+void AddUserTraffic(USER *u, TRAFFIC *diff)
+{
+ // Validate arguments
+ if (u == NULL || diff == NULL)
+ {
+ return;
+ }
+
+ Lock(u->lock);
+ {
+ AddTraffic(u->Traffic, diff);
+ }
+ Unlock(u->lock);
+}
+
+// Set traffic data for group
+void SetGroupTraffic(USERGROUP *g, TRAFFIC *t)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Lock(g->lock);
+ {
+ if (t != NULL)
+ {
+ Copy(g->Traffic, t, sizeof(TRAFFIC));
+ }
+ else
+ {
+ Zero(g->Traffic, sizeof(TRAFFIC));
+ }
+ }
+ Unlock(g->lock);
+}
+
+// Set traffic data for user
+void SetUserTraffic(USER *u, TRAFFIC *t)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ Lock(u->lock);
+ {
+ if (t != NULL)
+ {
+ Copy(u->Traffic, t, sizeof(TRAFFIC));
+ }
+ else
+ {
+ Zero(u->Traffic, sizeof(TRAFFIC));
+ }
+ }
+ Unlock(u->lock);
+}
+
+// Join the user to the group
+void JoinUserToGroup(USER *u, USERGROUP *g)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ if (g != NULL)
+ {
+ // Join
+ Lock(u->lock);
+ {
+ Lock(g->lock);
+ {
+ if (u->Group != NULL)
+ {
+ // Remove the user from current group first
+ //
+ ReleaseGroup(u->Group);
+ u->Group = NULL;
+ Free(u->GroupName);
+ u->GroupName = NULL;
+ }
+ // Join the user to the group
+ u->GroupName = CopyStr(g->Name);
+ u->Group = g;
+ AddRef(g->ref);
+ }
+ Unlock(g->lock);
+ }
+ Unlock(u->lock);
+ }
+ else
+ {
+ // Withdrawal
+ Lock(u->lock);
+ {
+ if (u->Group != NULL)
+ {
+ // Remove the user from current group
+ ReleaseGroup(u->Group);
+ u->Group = NULL;
+ Free(u->GroupName);
+ u->GroupName = NULL;
+ }
+ }
+ Unlock(u->lock);
+ }
+}
+
+// Validate group name
+bool AcIsGroup(HUB *h, char *name)
+{
+ USERGROUP *g;
+ // Validate arguments
+ if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))
+ {
+ return false;
+ }
+
+ g = AcGetGroup(h, name);
+ if (g == NULL)
+ {
+ return false;
+ }
+ ReleaseGroup(g);
+
+ return true;
+}
+
+// Validate user name
+bool AcIsUser(HUB *h, char *name)
+{
+ USER *u;
+ // Validate arguments
+ if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))
+ {
+ return false;
+ }
+
+ u = AcGetUser(h, name);
+ if (u == NULL)
+ {
+ return false;
+ }
+ ReleaseUser(u);
+
+ return true;
+}
+
+// Get group object
+USERGROUP *AcGetGroup(HUB *h, char *name)
+{
+ USERGROUP *g, t;
+ // Validate arguments
+ if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))
+ {
+ return NULL;
+ }
+
+ t.Name = name;
+ g = Search(h->HubDb->GroupList, &t);
+ if (g == NULL)
+ {
+ return NULL;
+ }
+ AddRef(g->ref);
+
+ return g;
+}
+
+// Get user object
+USER *AcGetUser(HUB *h, char *name)
+{
+ USER *u, t;
+ // Validate arguments
+ if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))
+ {
+ return NULL;
+ }
+
+ t.Name = name;
+ u = Search(h->HubDb->UserList, &t);
+ if (u == NULL)
+ {
+ return NULL;
+ }
+ AddRef(u->ref);
+
+ return u;
+}
+
+// Delete the user
+bool AcDeleteUser(HUB *h, char *name)
+{
+ USER *u;
+ // Validate arguments
+ if (h == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ u = AcGetUser(h, name);
+ if (u == NULL)
+ {
+ return false;
+ }
+
+ if (Delete(h->HubDb->UserList, u))
+ {
+ ReleaseUser(u);
+ }
+
+ ReleaseUser(u);
+
+ return true;
+}
+
+// Delete the group
+bool AcDeleteGroup(HUB *h, char *name)
+{
+ USERGROUP *g;
+ UINT i;
+ // Validate arguments
+ if (h == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ g = AcGetGroup(h, name);
+ if (g == NULL)
+ {
+ return false;
+ }
+
+ if (Delete(h->HubDb->GroupList, g))
+ {
+ ReleaseGroup(g);
+ }
+
+ for (i = 0;i < LIST_NUM(h->HubDb->UserList);i++)
+ {
+ USER *u = LIST_DATA(h->HubDb->UserList, i);
+ Lock(u->lock);
+ {
+ if (u->Group == g)
+ {
+ JoinUserToGroup(u, NULL);
+ }
+ }
+ Unlock(u->lock);
+ }
+
+ ReleaseGroup(g);
+
+ return true;
+}
+
+// Add new group to the hub
+bool AcAddGroup(HUB *h, USERGROUP *g)
+{
+ // Validate arguments
+ if (h == NULL || g == NULL || NO_ACCOUNT_DB(h))
+ {
+ return false;
+ }
+
+ if (LIST_NUM(h->HubDb->GroupList) >= MAX_GROUPS)
+ {
+ return false;
+ }
+
+ if (AcIsGroup(h, g->Name) != false)
+ {
+ return false;
+ }
+
+ Insert(h->HubDb->GroupList, g);
+ AddRef(g->ref);
+
+ return true;
+}
+
+// Add new user in the hub
+bool AcAddUser(HUB *h, USER *u)
+{
+ // Validate arguments
+ if (h == NULL || u == NULL || NO_ACCOUNT_DB(h))
+ {
+ return false;
+ }
+
+ if (LIST_NUM(h->HubDb->UserList) >= MAX_USERS)
+ {
+ return false;
+ }
+
+ if (AcIsUser(h, u->Name) != false)
+ {
+ return false;
+ }
+
+ Insert(h->HubDb->UserList, u);
+ AddRef(u->ref);
+
+ return true;
+}
+
+// Release user object (decrease reference counter)
+void ReleaseUser(USER *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ if (Release(u->ref) == 0)
+ {
+ CleanupUser(u);
+ }
+}
+
+// Cleanup the user object
+void CleanupUser(USER *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(u->lock);
+ Free(u->Name);
+ Free(u->RealName);
+ Free(u->Note);
+ Free(u->GroupName);
+ if (u->Group != NULL)
+ {
+ ReleaseGroup(u->Group);
+ }
+
+ // Free authntication data
+ FreeAuthData(u->AuthType, u->AuthData);
+
+ if (u->Policy)
+ {
+ // Free policy data
+ Free(u->Policy);
+ }
+
+ FreeTraffic(u->Traffic);
+
+ Free(u);
+}
+
+// Free authntication data
+void FreeAuthData(UINT authtype, void *authdata)
+{
+ AUTHPASSWORD *pw = (AUTHPASSWORD *)authdata;
+ AUTHUSERCERT *uc = (AUTHUSERCERT *)authdata;
+ AUTHROOTCERT *rc = (AUTHROOTCERT *)authdata;
+ AUTHRADIUS *rd = (AUTHRADIUS *)authdata;
+ AUTHNT *nt = (AUTHNT *)authdata;
+ // Validate arguments
+ if (authtype == AUTHTYPE_ANONYMOUS || authdata == NULL)
+ {
+ return;
+ }
+
+ switch (authtype)
+ {
+ case AUTHTYPE_PASSWORD:
+ // Password authentication
+ // Nothing to free
+ break;
+
+ case AUTHTYPE_USERCERT:
+ // User certification
+ FreeX(uc->UserX);
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ // Root certification
+ if (rc->Serial != NULL)
+ {
+ FreeXSerial(rc->Serial);
+ }
+ if (rc->CommonName != NULL)
+ {
+ Free(rc->CommonName);
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ // Radius authentication
+ Free(rd->RadiusUsername);
+ break;
+
+ case AUTHTYPE_NT:
+ // Windows NT authentication
+ Free(nt->NtUsername);
+ break;
+ }
+
+ Free(authdata);
+}
+
+// Create new user object
+USER *NewUser(char *name, wchar_t *realname, wchar_t *note, UINT authtype, void *authdata)
+{
+ USER *u;
+ // Validate arguments
+ if (name == NULL || realname == NULL || note == NULL)
+ {
+ return NULL;
+ }
+ if (authtype != AUTHTYPE_ANONYMOUS && authdata == NULL)
+ {
+ return NULL;
+ }
+
+ u = ZeroMalloc(sizeof(USER));
+ u->lock = NewLock();
+ u->ref = NewRef();
+ u->Name = CopyStr(name);
+ u->RealName = CopyUniStr(realname);
+ u->Note = CopyUniStr(note);
+ u->GroupName = NULL;
+ u->Group = NULL;
+ u->AuthType = authtype;
+ u->AuthData = authdata;
+ u->CreatedTime = SystemTime64();
+ u->UpdatedTime = SystemTime64();
+
+ u->Policy = NULL;
+ u->Traffic = NewTraffic();
+
+ return u;
+}
+
+// Release group object (decrease reference counter)
+void ReleaseGroup(USERGROUP *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ if (Release(g->ref) == 0)
+ {
+ CleanupGroup(g);
+ }
+}
+
+// Cleanup the group object
+void CleanupGroup(USERGROUP *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Free(g->Name);
+ Free(g->RealName);
+ Free(g->Note);
+
+ if (g->Policy)
+ {
+ // Free policy data
+ Free(g->Policy);
+ }
+
+
+ FreeTraffic(g->Traffic);
+
+ DeleteLock(g->lock);
+ Free(g);
+}
+
+// Create new group object
+USERGROUP *NewGroup(char *name, wchar_t *realname, wchar_t *note)
+{
+ USERGROUP *g;
+ // Validate arguments
+ if (name == NULL || realname == NULL || note == NULL)
+ {
+ return NULL;
+ }
+
+ g = ZeroMalloc(sizeof(USERGROUP));
+ g->lock = NewLock();
+ g->ref = NewRef();
+ g->Name = CopyStr(name);
+ g->RealName = CopyUniStr(realname);
+ g->Note = CopyUniStr(note);
+ g->Policy = NULL;
+ g->Traffic = NewTraffic();
+
+ return g;
+}
+
+// Lock the account database for the hub
+void AcLock(HUB *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+ if (NO_ACCOUNT_DB(h))
+ {
+ return;
+ }
+
+ // Lock group list and user list
+ LockList(h->HubDb->GroupList);
+ LockList(h->HubDb->UserList);
+}
+
+// Unlock the account database for the hub
+void AcUnlock(HUB *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+ if (NO_ACCOUNT_DB(h))
+ {
+ return;
+ }
+
+ // Unlock group list and user list
+ UnlockList(h->HubDb->UserList);
+ UnlockList(h->HubDb->GroupList);
+}
+
+// Compare group names (for sort)
+int CompareGroupName(void *p1, void *p2)
+{
+ USERGROUP *g1, *g2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ g1 = *(USERGROUP **)p1;
+ g2 = *(USERGROUP **)p2;
+ if (g1 == NULL || g2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(g1->Name, g2->Name);
+}
+
+// Compare user names (for sort)
+int CompareUserName(void *p1, void *p2)
+{
+ USER *u1, *u2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ u1 = *(USER **)p1;
+ u2 = *(USER **)p2;
+ if (u1 == NULL || u2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(u1->Name, u2->Name);
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Account.h b/src/Cedar/Account.h
new file mode 100644
index 00000000..95d1d9fe
--- /dev/null
+++ b/src/Cedar/Account.h
@@ -0,0 +1,293 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Account.h
+// Header of Account.c
+
+#ifndef ACCOUNT_H
+#define ACCOUNT_H
+
+// Policy item
+struct POLICY_ITEM
+{
+ UINT Index;
+ bool TypeInt;
+ bool AllowZero;
+ UINT MinValue;
+ UINT MaxValue;
+ UINT DefaultValue;
+ char *FormatStr;
+};
+
+// Policy
+struct POLICY
+{
+ // For Ver 2.0
+ bool Access; // Grant access
+ bool DHCPFilter; // Filter DHCP packets (IPv4)
+ bool DHCPNoServer; // Prohibit the behavior of the DHCP server (IPv4)
+ bool DHCPForce; // Force DHCP-assigned IP address (IPv4)
+ bool NoBridge; // Prohibit the bridge behavior
+ bool NoRouting; // Prohibit the router behavior (IPv4)
+ bool CheckMac; // Prohibit the duplicate MAC address
+ bool CheckIP; // Prohibit a duplicate IP address (IPv4)
+ bool ArpDhcpOnly; // Prohibit the broadcast other than ARP, DHCP, ICMPv6
+ bool PrivacyFilter; // Privacy filter mode
+ bool NoServer; // Prohibit to operate as a TCP/IP server (IPv4)
+ bool NoBroadcastLimiter; // Not to limit the number of broadcast
+ bool MonitorPort; // Allow monitoring mode
+ UINT MaxConnection; // Maximum number of TCP connections
+ UINT TimeOut; // Communication time-out period
+ UINT MaxMac; // Maximum number of MAC address
+ UINT MaxIP; // Maximum number of IP address (IPv4)
+ UINT MaxUpload; // Upload bandwidth
+ UINT MaxDownload; // Download bandwidth
+ bool FixPassword; // User can not change password
+ UINT MultiLogins; // Multiple logins limit
+ bool NoQoS; // Prohibit the use of VoIP / QoS features
+
+ // For Ver 3.0
+ bool RSandRAFilter; // Filter the Router Solicitation / Advertising packet (IPv6)
+ bool RAFilter; // Filter the router advertisement packet (IPv6)
+ bool DHCPv6Filter; // Filter DHCP packets (IPv6)
+ bool DHCPv6NoServer; // Prohibit the behavior of the DHCP server (IPv6)
+ bool NoRoutingV6; // Prohibit the router behavior (IPv6)
+ bool CheckIPv6; // Prohibit the duplicate IP address (IPv6)
+ bool NoServerV6; // Prohibit to operate as a TCP/IP server (IPv6)
+ UINT MaxIPv6; // Maximum number of IP address (IPv6)
+ bool NoSavePassword; // Prohibit to save the password in the VPN Client
+ UINT AutoDisconnect; // Disconnect the VPN Client automatically at a certain period of time
+ bool FilterIPv4; // Filter all IPv4 packets
+ bool FilterIPv6; // Filter all IPv6 packets
+ bool FilterNonIP; // Filter all non-IP packets
+ bool NoIPv6DefaultRouterInRA; // Delete the default router specification from the IPv6 router advertisement
+ bool NoIPv6DefaultRouterInRAWhenIPv6; // Delete the default router specification from the IPv6 router advertisement (Enable IPv6 connection)
+ UINT VLanId; // Specify the VLAN ID
+
+ bool Ver3; // Whether version 3.0
+};
+
+// Group
+struct USERGROUP
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ char *Name; // Group name
+ wchar_t *RealName; // Display name
+ wchar_t *Note; // Note
+ POLICY *Policy; // Policy
+ TRAFFIC *Traffic; // Traffic data
+};
+
+// User
+struct USER
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ char *Name; // User name
+ wchar_t *RealName; // Real name
+ wchar_t *Note; // Note
+ char *GroupName; // Group name
+ USERGROUP *Group; // Group
+ UINT AuthType; // Authentication type
+ void *AuthData; // Authentication data
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+ UINT64 ExpireTime; // Expiration date
+ UINT64 LastLoginTime; // Last login time
+ UINT NumLogin; // Total number of logins
+ POLICY *Policy; // Policy
+ TRAFFIC *Traffic; // Traffic data
+};
+
+// Password authentication data
+struct AUTHPASSWORD
+{
+ UCHAR HashedKey[SHA1_SIZE]; // Hashed passwords
+ UCHAR NtLmSecureHash[MD5_SIZE]; // Encrypted password for the NTLM
+};
+
+// User certificate authentication data
+struct AUTHUSERCERT
+{
+ X *UserX; // X509 certificate for the user
+};
+
+// Root certification authority authentication data
+struct AUTHROOTCERT
+{
+ X_SERIAL *Serial; // Serial number
+ wchar_t *CommonName; // CommonName
+};
+
+// Radius authentication data
+struct AUTHRADIUS
+{
+ wchar_t *RadiusUsername; // User name in the Radius
+};
+
+// Windows NT authentication data
+struct AUTHNT
+{
+ wchar_t *NtUsername; // User name on NT
+};
+
+
+
+// Macro
+#define POLICY_CURRENT_VERSION 3
+#define NUM_POLICY_ITEM ((sizeof(POLICY) / sizeof(UINT)) - 1)
+#define NUM_POLICY_ITEM_FOR_VER2 22
+#define NUM_POLICY_ITEM_FOR_VER3 38
+
+#define IS_POLICY_FOR_VER2(index) (((index) >= 0) && ((index) < NUM_POLICY_ITEM_FOR_VER2))
+#define IS_POLICY_FOR_VER3(index) (((index) >= 0) && ((index) < NUM_POLICY_ITEM_FOR_VER3))
+
+#define IS_POLICY_FOR_CURRENT_VER(index, ver) ((ver) >= 3 ? IS_POLICY_FOR_VER3(index) : IS_POLICY_FOR_VER2(index))
+
+#define POLICY_BOOL(p, i) (((bool *)(p))[(i)])
+#define POLICY_INT(p, i) (((UINT *)(p))[(i)])
+
+extern POLICY_ITEM policy_item[];
+
+
+
+
+// Function prototype
+int CompareUserName(void *p1, void *p2);
+int CompareGroupName(void *p1, void *p2);
+void AcLock(HUB *h);
+void AcUnlock(HUB *h);
+USERGROUP *NewGroup(char *name, wchar_t *realname, wchar_t *note);
+void ReleaseGroup(USERGROUP *g);
+void CleanupGroup(USERGROUP *g);
+USER *NewUser(char *name, wchar_t *realname, wchar_t *note, UINT authtype, void *authdata);
+void ReleaseUser(USER *u);
+void CleanupUser(USER *u);
+void FreeAuthData(UINT authtype, void *authdata);
+bool AcAddUser(HUB *h, USER *u);
+bool AcAddGroup(HUB *h, USERGROUP *g);
+USER *AcGetUser(HUB *h, char *name);
+USERGROUP *AcGetGroup(HUB *h, char *name);
+bool AcIsUser(HUB *h, char *name);
+bool AcIsGroup(HUB *h, char *name);
+bool AcDeleteUser(HUB *h, char *name);
+bool AcDeleteGroup(HUB *h, char *name);
+void JoinUserToGroup(USER *u, USERGROUP *g);
+void SetUserTraffic(USER *u, TRAFFIC *t);
+void SetGroupTraffic(USERGROUP *g, TRAFFIC *t);
+void AddUserTraffic(USER *u, TRAFFIC *diff);
+void AddGroupTraffic(USERGROUP *g, TRAFFIC *diff);
+void SetUserAuthData(USER *u, UINT authtype, void *authdata);
+void *NewPasswordAuthData(char *username, char *password);
+void *NewPasswordAuthDataRaw(UCHAR *hashed_password, UCHAR *ntlm_secure_hash);
+void *NewUserCertAuthData(X *x);
+void *NewRootCertAuthData(X_SERIAL *serial, wchar_t *common_name);
+void *NewRadiusAuthData(wchar_t *username);
+void *NewNTAuthData(wchar_t *username);
+void HashPassword(void *dst, char *username, char *password);
+POLICY *GetDefaultPolicy();
+POLICY *ClonePolicy(POLICY *policy);
+void SetUserPolicy(USER *u, POLICY *policy);
+void OverwritePolicy(POLICY **target, POLICY *p);
+POLICY *GetUserPolicy(USER *u);
+void SetGroupPolicy(USERGROUP *g, POLICY *policy);
+POLICY *GetGroupPolicy(USERGROUP *g);
+wchar_t *GetPolicyTitle(UINT id);
+wchar_t *GetPolicyDescription(UINT id);
+bool IsUserName(char *name);
+void *CopyAuthData(void *authdata, UINT authtype);
+UINT PolicyNum();
+bool PolicyIsSupportedForCascade(UINT i);
+UINT PolicyStrToId(char *name);
+char *PolicyIdToStr(UINT i);
+POLICY_ITEM *GetPolicyItem(UINT id);
+void GetPolicyValueRangeStr(wchar_t *str, UINT size, UINT id);
+void FormatPolicyValue(wchar_t *str, UINT size, UINT id, UINT value);
+char *NormalizePolicyName(char *name);
+
+
+#endif // ACCOUNT_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Admin.c b/src/Cedar/Admin.c
new file mode 100644
index 00000000..9bec72a4
--- /dev/null
+++ b/src/Cedar/Admin.c
@@ -0,0 +1,13742 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Admin.c
+// RPC Module for Management
+
+#include "CedarPch.h"
+
+// Macro for RPC function declaration
+#define DECLARE_RPC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type *t; \
+ t = ZeroMalloc(sizeof(data_type)); \
+ in_rpc(t, p); \
+ err = function(a, t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, t); \
+ } \
+ free_rpc(t); \
+ Free(t); \
+ ok = true; \
+ }
+#define DECLARE_RPC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type *t; \
+ t = ZeroMalloc(sizeof(data_type)); \
+ in_rpc(t, p); \
+ err = function(a, t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, t); \
+ } \
+ Free(t); \
+ ok = true; \
+ }
+#define DECLARE_SC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ free_rpc(t); \
+ Zero(t, sizeof(data_type)); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+#define DECLARE_SC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+#define CHECK_RIGHT \
+ if (a->ServerAdmin == false && (t->HubName == NULL || StrCmpi(a->HubName, t->HubName) != 0)) \
+ return ERR_NOT_ENOUGH_RIGHT; \
+ if (IsEmptyStr(t->HubName)) \
+ return ERR_INVALID_PARAMETER;
+#define SERVER_ADMIN_ONLY \
+ if (a->ServerAdmin == false) \
+ return ERR_NOT_ENOUGH_RIGHT;
+#define NO_SUPPORT_FOR_BRIDGE \
+ if (a->Server->Cedar->Bridge) \
+ return ERR_NOT_SUPPORTED;
+
+// Get server Caps (Guessing from the build number if failed to get Caps)
+CAPSLIST *ScGetCapsEx(RPC *rpc)
+{
+ RPC_SERVER_INFO info;
+ CAPSLIST *t;
+ bool is_bridge = false;
+ // Validate arguments
+ if (rpc == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&info, sizeof(info));
+ ScGetServerInfo(rpc, &info);
+
+ t = ZeroMalloc(sizeof(CAPSLIST));
+
+ // Try to get Caps by RPC
+ if (ScGetCaps(rpc, t) != ERR_NO_ERROR)
+ {
+ UINT build;
+
+ Free(t);
+ t = NewCapsList();
+
+ // Since acquisition of Caps went wrong, get build number
+ build = info.ServerBuildInt;
+
+ is_bridge = (SearchStrEx(info.ServerProductName, "bridge", 0, false) == INFINITE) ? false : true;
+
+ AddCapsInt(t, "i_max_packet_size", 1514);
+
+ if (is_bridge == false)
+ {
+ AddCapsInt(t, "i_max_hubs", 4096);
+ AddCapsInt(t, "i_max_sessions", 4096);
+
+ if (info.ServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ AddCapsInt(t, "i_max_users_per_hub", 10000);
+ AddCapsInt(t, "i_max_groups_per_hub", 10000);
+ AddCapsInt(t, "i_max_access_lists", 4096);
+ }
+ else
+ {
+ AddCapsInt(t, "i_max_users_per_hub", 0);
+ AddCapsInt(t, "i_max_groups_per_hub", 0);
+ AddCapsInt(t, "i_max_access_lists", 0);
+ }
+ }
+ else
+ {
+ AddCapsInt(t, "i_max_hubs", 0);
+ AddCapsInt(t, "i_max_sessions", 0);
+ AddCapsInt(t, "i_max_users_per_hub", 0);
+ AddCapsInt(t, "i_max_groups_per_hub", 0);
+ AddCapsInt(t, "i_max_access_lists", 0);
+ }
+
+ AddCapsInt(t, "i_max_mac_tables", 10000);
+ AddCapsInt(t, "i_max_ip_tables", 10000);
+
+ if (info.ServerType == SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_support_securenat", (build >= 3600) ? true : false);
+ AddCapsInt(t, "i_max_secnat_tables", 4096);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_securenat", false);
+ AddCapsInt(t, "i_max_secnat_tables", 0);
+ }
+
+ if (is_bridge)
+ {
+ AddCapsBool(t, "b_bridge", true);
+ }
+ else if (info.ServerType == SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_standalone", true);
+ }
+ else if (info.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ AddCapsBool(t, "b_cluster_controller", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_cluster_member", true);
+ }
+
+ AddCapsBool(t, "b_support_config_hub", info.ServerType != SERVER_TYPE_FARM_MEMBER &&
+ is_bridge == false);
+
+ AddCapsBool(t, "b_vpn_client_connect", is_bridge == false ? true : false);
+
+ AddCapsBool(t, "b_support_radius", info.ServerType != SERVER_TYPE_FARM_MEMBER &&
+ is_bridge == false);
+
+ if (build >= 3600)
+ {
+ RPC_BRIDGE_SUPPORT b;
+ Zero(&b, sizeof(b));
+ if (ScGetBridgeSupport(rpc, &b) == ERR_NO_ERROR)
+ {
+ AddCapsBool(t, "b_local_bridge", b.IsBridgeSupportedOs);
+ AddCapsBool(t, "b_must_install_pcap", b.IsWinPcapNeeded);
+ }
+ else
+ {
+ AddCapsBool(t, "b_local_bridge", false);
+ AddCapsBool(t, "b_must_install_pcap", false);
+ }
+ }
+ else
+ {
+ AddCapsBool(t, "b_local_bridge", false);
+ AddCapsBool(t, "b_must_install_pcap", false);
+ }
+
+ AddCapsBool(t, "b_tap_supported", false);
+
+ if (info.ServerType == SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_support_cascade", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_cascade", false);
+ }
+
+ AddCapsBool(t, "b_support_cascade_cert", false);
+ AddCapsBool(t, "b_support_config_log", info.ServerType != SERVER_TYPE_FARM_MEMBER);
+ AddCapsBool(t, "b_support_autodelete", false);
+ }
+ else
+ {
+ // Success getting Caps
+ if (info.ServerBuildInt <= 4350)
+ {
+ if (is_bridge == false)
+ {
+ // b_support_cluster should be true for build 4300 or earlier
+ CAPS *caps = GetCaps(t, "b_support_cluster");
+ if (caps == NULL)
+ {
+ AddCapsBool(t, "b_support_cluster", true);
+ }
+ else
+ {
+ caps->Value = 1;
+ }
+ }
+ }
+ }
+
+ if (true)
+ {
+ TOKEN_LIST *names;
+
+ // Fill items that doesn't exist in server-side as false
+ names = GetTableNameStartWith("CT_b_");
+ if (names != NULL)
+ {
+ UINT i;
+ for (i = 0;i < names->NumTokens;i++)
+ {
+ char *name = names->Token[i] + 3;
+
+ if (GetCaps(t, name) == NULL)
+ {
+ AddCapsBool(t, name, false);
+ }
+ }
+
+ FreeToken(names);
+ }
+ }
+
+ FreeRpcServerInfo(&info);
+
+ return t;
+}
+
+// Dispatch routine for Administration RPC
+PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
+{
+ ADMIN *a;
+ PACK *ret;
+ UINT err;
+ SERVER *server = NULL;
+ CEDAR *cedar = NULL;
+ bool ok = false;
+ // Validate arguments
+ if (rpc == NULL || name == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewPack();
+ err = ERR_NO_ERROR;
+
+ // Administration structure
+ a = (ADMIN *)rpc->Param;
+ if (a == NULL)
+ {
+ FreePack(ret);
+ return NULL;
+ }
+
+ server = a->Server;
+
+ if (server != NULL)
+ {
+ cedar = server->Cedar;
+ }
+
+ Lock(cedar->CedarSuperLock);
+
+ if (true)
+ {
+ char tmp[MAX_PATH];
+ char ip[MAX_PATH];
+ UINT rpc_id = 0;
+
+ StrCpy(ip, sizeof(ip), "Unknown");
+
+ if (rpc->Sock != NULL)
+ {
+ IPToStr(ip, sizeof(ip), &rpc->Sock->RemoteIP);
+ rpc_id = rpc->Sock->socket;
+ }
+
+ Format(tmp, sizeof(tmp), "RPC: RPC-%u (%s): Entering RPC [%s]...",
+ rpc_id, ip, name);
+
+ SiDebugLog(a->Server, tmp);
+ }
+
+ if (0) {}
+
+ // RPC function declaration: from here
+ DECLARE_RPC_EX("Test", RPC_TEST, StTest, InRpcTest, OutRpcTest, FreeRpcTest)
+ DECLARE_RPC_EX("GetServerInfo", RPC_SERVER_INFO, StGetServerInfo, InRpcServerInfo, OutRpcServerInfo, FreeRpcServerInfo)
+ DECLARE_RPC("GetServerStatus", RPC_SERVER_STATUS, StGetServerStatus, InRpcServerStatus, OutRpcServerStatus)
+ DECLARE_RPC("CreateListener", RPC_LISTENER, StCreateListener, InRpcListener, OutRpcListener)
+ DECLARE_RPC_EX("EnumListener", RPC_LISTENER_LIST, StEnumListener, InRpcListenerList, OutRpcListenerList, FreeRpcListenerList)
+ DECLARE_RPC("DeleteListener", RPC_LISTENER, StDeleteListener, InRpcListener, OutRpcListener)
+ DECLARE_RPC("EnableListener", RPC_LISTENER, StEnableListener, InRpcListener, OutRpcListener)
+ DECLARE_RPC("SetServerPassword", RPC_SET_PASSWORD, StSetServerPassword, InRpcSetPassword, OutRpcSetPassword)
+ DECLARE_RPC_EX("SetFarmSetting", RPC_FARM, StSetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)
+ DECLARE_RPC_EX("GetFarmSetting", RPC_FARM, StGetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)
+ DECLARE_RPC_EX("GetFarmInfo", RPC_FARM_INFO, StGetFarmInfo, InRpcFarmInfo, OutRpcFarmInfo, FreeRpcFarmInfo)
+ DECLARE_RPC_EX("EnumFarmMember", RPC_ENUM_FARM, StEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)
+ DECLARE_RPC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, StGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)
+ DECLARE_RPC_EX("SetServerCert", RPC_KEY_PAIR, StSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
+ DECLARE_RPC_EX("GetServerCert", RPC_KEY_PAIR, StGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
+ DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
+ DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
+ DECLARE_RPC("CreateHub", RPC_CREATE_HUB, StCreateHub, InRpcCreateHub, OutRpcCreateHub)
+ DECLARE_RPC("SetHub", RPC_CREATE_HUB, StSetHub, InRpcCreateHub, OutRpcCreateHub)
+ DECLARE_RPC("GetHub", RPC_CREATE_HUB, StGetHub, InRpcCreateHub, OutRpcCreateHub)
+ DECLARE_RPC_EX("EnumHub", RPC_ENUM_HUB, StEnumHub, InRpcEnumHub, OutRpcEnumHub, FreeRpcEnumHub)
+ DECLARE_RPC("DeleteHub", RPC_DELETE_HUB, StDeleteHub, InRpcDeleteHub, OutRpcDeleteHub)
+ DECLARE_RPC("GetHubRadius", RPC_RADIUS, StGetHubRadius, InRpcRadius, OutRpcRadius)
+ DECLARE_RPC("SetHubRadius", RPC_RADIUS, StSetHubRadius, InRpcRadius, OutRpcRadius)
+ DECLARE_RPC_EX("EnumConnection", RPC_ENUM_CONNECTION, StEnumConnection, InRpcEnumConnection, OutRpcEnumConnection, FreeRpcEnumConnetion)
+ DECLARE_RPC("DisconnectConnection", RPC_DISCONNECT_CONNECTION, StDisconnectConnection, InRpcDisconnectConnection, OutRpcDisconnectConnection)
+ DECLARE_RPC("GetConnectionInfo", RPC_CONNECTION_INFO, StGetConnectionInfo, InRpcConnectionInfo, OutRpcConnectionInfo)
+ DECLARE_RPC("SetHubOnline", RPC_SET_HUB_ONLINE, StSetHubOnline, InRpcSetHubOnline, OutRpcSetHubOnline)
+ DECLARE_RPC("GetHubStatus", RPC_HUB_STATUS, StGetHubStatus, InRpcHubStatus, OutRpcHubStatus)
+ DECLARE_RPC("SetHubLog", RPC_HUB_LOG, StSetHubLog, InRpcHubLog, OutRpcHubLog)
+ DECLARE_RPC("GetHubLog", RPC_HUB_LOG, StGetHubLog, InRpcHubLog, OutRpcHubLog)
+ DECLARE_RPC_EX("AddCa", RPC_HUB_ADD_CA, StAddCa, InRpcHubAddCa, OutRpcHubAddCa, FreeRpcHubAddCa)
+ DECLARE_RPC_EX("EnumCa", RPC_HUB_ENUM_CA, StEnumCa, InRpcHubEnumCa, OutRpcHubEnumCa, FreeRpcHubEnumCa)
+ DECLARE_RPC_EX("GetCa", RPC_HUB_GET_CA, StGetCa, InRpcHubGetCa, OutRpcHubGetCa, FreeRpcHubGetCa)
+ DECLARE_RPC("DeleteCa", RPC_HUB_DELETE_CA, StDeleteCa, InRpcHubDeleteCa, OutRpcHubDeleteCa)
+ DECLARE_RPC("SetLinkOnline", RPC_LINK, StSetLinkOnline, InRpcLink, OutRpcLink)
+ DECLARE_RPC("SetLinkOffline", RPC_LINK, StSetLinkOffline, InRpcLink, OutRpcLink)
+ DECLARE_RPC("DeleteLink", RPC_LINK, StDeleteLink, InRpcLink, OutRpcLink)
+ DECLARE_RPC("RenameLink", RPC_RENAME_LINK, StRenameLink, InRpcRenameLink, OutRpcRenameLink)
+ DECLARE_RPC_EX("CreateLink", RPC_CREATE_LINK, StCreateLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+ DECLARE_RPC_EX("GetLink", RPC_CREATE_LINK, StGetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+ DECLARE_RPC_EX("SetLink", RPC_CREATE_LINK, StSetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+ DECLARE_RPC_EX("EnumLink", RPC_ENUM_LINK, StEnumLink, InRpcEnumLink, OutRpcEnumLink, FreeRpcEnumLink)
+ DECLARE_RPC_EX("GetLinkStatus", RPC_LINK_STATUS, StGetLinkStatus, InRpcLinkStatus, OutRpcLinkStatus, FreeRpcLinkStatus)
+ DECLARE_RPC("AddAccess", RPC_ADD_ACCESS, StAddAccess, InRpcAddAccess, OutRpcAddAccess)
+ DECLARE_RPC("DeleteAccess", RPC_DELETE_ACCESS, StDeleteAccess, InRpcDeleteAccess, OutRpcDeleteAccess)
+ DECLARE_RPC_EX("EnumAccess", RPC_ENUM_ACCESS_LIST, StEnumAccess, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)
+ DECLARE_RPC_EX("SetAccessList", RPC_ENUM_ACCESS_LIST, StSetAccessList, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)
+ DECLARE_RPC_EX("CreateUser", RPC_SET_USER, StCreateUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+ DECLARE_RPC_EX("SetUser", RPC_SET_USER, StSetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+ DECLARE_RPC_EX("GetUser", RPC_SET_USER, StGetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+ DECLARE_RPC("DeleteUser", RPC_DELETE_USER, StDeleteUser, InRpcDeleteUser, OutRpcDeleteUser)
+ DECLARE_RPC_EX("EnumUser", RPC_ENUM_USER, StEnumUser, InRpcEnumUser, OutRpcEnumUser, FreeRpcEnumUser)
+ DECLARE_RPC_EX("CreateGroup", RPC_SET_GROUP, StCreateGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+ DECLARE_RPC_EX("SetGroup", RPC_SET_GROUP, StSetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+ DECLARE_RPC_EX("GetGroup", RPC_SET_GROUP, StGetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+ DECLARE_RPC("DeleteGroup", RPC_DELETE_USER, StDeleteGroup, InRpcDeleteUser, OutRpcDeleteUser)
+ DECLARE_RPC_EX("EnumGroup", RPC_ENUM_GROUP, StEnumGroup, InRpcEnumGroup, OutRpcEnumGroup, FreeRpcEnumGroup)
+ DECLARE_RPC_EX("EnumSession", RPC_ENUM_SESSION, StEnumSession, InRpcEnumSession, OutRpcEnumSession, FreeRpcEnumSession)
+ DECLARE_RPC_EX("GetSessionStatus", RPC_SESSION_STATUS, StGetSessionStatus, InRpcSessionStatus, OutRpcSessionStatus, FreeRpcSessionStatus)
+ DECLARE_RPC("DeleteSession", RPC_DELETE_SESSION, StDeleteSession, InRpcDeleteSession, OutRpcDeleteSession)
+ DECLARE_RPC_EX("EnumMacTable", RPC_ENUM_MAC_TABLE, StEnumMacTable, InRpcEnumMacTable, OutRpcEnumMacTable, FreeRpcEnumMacTable)
+ DECLARE_RPC("DeleteMacTable", RPC_DELETE_TABLE, StDeleteMacTable, InRpcDeleteTable, OutRpcDeleteTable)
+ DECLARE_RPC_EX("EnumIpTable", RPC_ENUM_IP_TABLE, StEnumIpTable, InRpcEnumIpTable, OutRpcEnumIpTable, FreeRpcEnumIpTable)
+ DECLARE_RPC("DeleteIpTable", RPC_DELETE_TABLE, StDeleteIpTable, InRpcDeleteTable, OutRpcDeleteTable)
+ DECLARE_RPC("SetKeep", RPC_KEEP, StSetKeep, InRpcKeep, OutRpcKeep)
+ DECLARE_RPC("GetKeep", RPC_KEEP, StGetKeep, InRpcKeep, OutRpcKeep)
+ DECLARE_RPC("EnableSecureNAT", RPC_HUB, StEnableSecureNAT, InRpcHub, OutRpcHub)
+ DECLARE_RPC("DisableSecureNAT", RPC_HUB, StDisableSecureNAT, InRpcHub, OutRpcHub)
+ DECLARE_RPC("SetSecureNATOption", VH_OPTION, StSetSecureNATOption, InVhOption, OutVhOption)
+ DECLARE_RPC("GetSecureNATOption", VH_OPTION, StGetSecureNATOption, InVhOption, OutVhOption)
+ DECLARE_RPC_EX("EnumNAT", RPC_ENUM_NAT, StEnumNAT, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)
+ DECLARE_RPC_EX("EnumDHCP", RPC_ENUM_DHCP, StEnumDHCP, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)
+ DECLARE_RPC("GetSecureNATStatus", RPC_NAT_STATUS, StGetSecureNATStatus, InRpcNatStatus, OutRpcNatStatus)
+ DECLARE_RPC_EX("EnumEthernet", RPC_ENUM_ETH, StEnumEthernet, InRpcEnumEth, OutRpcEnumEth, FreeRpcEnumEth)
+ DECLARE_RPC("AddLocalBridge", RPC_LOCALBRIDGE, StAddLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)
+ DECLARE_RPC("DeleteLocalBridge", RPC_LOCALBRIDGE, StDeleteLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)
+ DECLARE_RPC_EX("EnumLocalBridge", RPC_ENUM_LOCALBRIDGE, StEnumLocalBridge, InRpcEnumLocalBridge, OutRpcEnumLocalBridge, FreeRpcEnumLocalBridge)
+ DECLARE_RPC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, StGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)
+ DECLARE_RPC("RebootServer", RPC_TEST, StRebootServer, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("GetCaps", CAPSLIST, StGetCaps, InRpcCapsList, OutRpcCapsList, FreeRpcCapsList)
+ DECLARE_RPC_EX("GetConfig", RPC_CONFIG, StGetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)
+ DECLARE_RPC_EX("SetConfig", RPC_CONFIG, StSetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)
+ DECLARE_RPC_EX("GetDefaultHubAdminOptions", RPC_ADMIN_OPTION, StGetDefaultHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+ DECLARE_RPC_EX("GetHubAdminOptions", RPC_ADMIN_OPTION, StGetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+ DECLARE_RPC_EX("SetHubAdminOptions", RPC_ADMIN_OPTION, StSetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+ DECLARE_RPC_EX("GetHubExtOptions", RPC_ADMIN_OPTION, StGetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+ DECLARE_RPC_EX("SetHubExtOptions", RPC_ADMIN_OPTION, StSetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+ DECLARE_RPC("AddL3Switch", RPC_L3SW, StAddL3Switch, InRpcL3Sw, OutRpcL3Sw)
+ DECLARE_RPC("DelL3Switch", RPC_L3SW, StDelL3Switch, InRpcL3Sw, OutRpcL3Sw)
+ DECLARE_RPC_EX("EnumL3Switch", RPC_ENUM_L3SW, StEnumL3Switch, InRpcEnumL3Sw, OutRpcEnumL3Sw, FreeRpcEnumL3Sw)
+ DECLARE_RPC("StartL3Switch", RPC_L3SW, StStartL3Switch, InRpcL3Sw, OutRpcL3Sw)
+ DECLARE_RPC("StopL3Switch", RPC_L3SW, StStopL3Switch, InRpcL3Sw, OutRpcL3Sw)
+ DECLARE_RPC("AddL3If", RPC_L3IF, StAddL3If, InRpcL3If, OutRpcL3If)
+ DECLARE_RPC("DelL3If", RPC_L3IF, StDelL3If, InRpcL3If, OutRpcL3If)
+ DECLARE_RPC_EX("EnumL3If", RPC_ENUM_L3IF, StEnumL3If, InRpcEnumL3If, OutRpcEnumL3If, FreeRpcEnumL3If)
+ DECLARE_RPC("AddL3Table", RPC_L3TABLE, StAddL3Table, InRpcL3Table, OutRpcL3Table)
+ DECLARE_RPC("DelL3Table", RPC_L3TABLE, StDelL3Table, InRpcL3Table, OutRpcL3Table)
+ DECLARE_RPC_EX("EnumL3Table", RPC_ENUM_L3TABLE, StEnumL3Table, InRpcEnumL3Table, OutRpcEnumL3Table, FreeRpcEnumL3Table)
+ DECLARE_RPC_EX("EnumCrl", RPC_ENUM_CRL, StEnumCrl, InRpcEnumCrl, OutRpcEnumCrl, FreeRpcEnumCrl)
+ DECLARE_RPC_EX("AddCrl", RPC_CRL, StAddCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+ DECLARE_RPC_EX("DelCrl", RPC_CRL, StDelCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+ DECLARE_RPC_EX("GetCrl", RPC_CRL, StGetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+ DECLARE_RPC_EX("SetCrl", RPC_CRL, StSetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+ DECLARE_RPC_EX("SetAcList", RPC_AC_LIST, StSetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)
+ DECLARE_RPC_EX("GetAcList", RPC_AC_LIST, StGetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)
+ DECLARE_RPC_EX("EnumLogFile", RPC_ENUM_LOG_FILE, StEnumLogFile, InRpcEnumLogFile, OutRpcEnumLogFile, FreeRpcEnumLogFile)
+ DECLARE_RPC_EX("ReadLogFile", RPC_READ_LOG_FILE, StReadLogFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)
+ DECLARE_RPC("AddLicenseKey", RPC_TEST, StAddLicenseKey, InRpcTest, OutRpcTest)
+ DECLARE_RPC("DelLicenseKey", RPC_TEST, StDelLicenseKey, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, StEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)
+ DECLARE_RPC("GetLicenseStatus", RPC_LICENSE_STATUS, StGetLicenseStatus, InRpcLicenseStatus, OutRpcLicenseStatus)
+ DECLARE_RPC("SetSysLog", SYSLOG_SETTING, StSetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)
+ DECLARE_RPC("GetSysLog", SYSLOG_SETTING, StGetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)
+ DECLARE_RPC_EX("EnumEthVLan", RPC_ENUM_ETH_VLAN, StEnumEthVLan, InRpcEnumEthVLan, OutRpcEnumEthVLan, FreeRpcEnumEthVLan)
+ DECLARE_RPC("SetEnableEthVLan", RPC_TEST, StSetEnableEthVLan, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("SetHubMsg", RPC_MSG, StSetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+ DECLARE_RPC_EX("GetHubMsg", RPC_MSG, StGetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+ DECLARE_RPC("Crash", RPC_TEST, StCrash, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("GetAdminMsg", RPC_MSG, StGetAdminMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+ DECLARE_RPC("Flush", RPC_TEST, StFlush, InRpcTest, OutRpcTest)
+ DECLARE_RPC("Debug", RPC_TEST, StDebug, InRpcTest, OutRpcTest)
+ DECLARE_RPC("SetIPsecServices", IPSEC_SERVICES, StSetIPsecServices, InIPsecServices, OutIPsecServices)
+ DECLARE_RPC("GetIPsecServices", IPSEC_SERVICES, StGetIPsecServices, InIPsecServices, OutIPsecServices)
+ DECLARE_RPC("AddEtherIpId", ETHERIP_ID, StAddEtherIpId, InEtherIpId, OutEtherIpId)
+ DECLARE_RPC("GetEtherIpId", ETHERIP_ID, StGetEtherIpId, InEtherIpId, OutEtherIpId)
+ DECLARE_RPC("DeleteEtherIpId", ETHERIP_ID, StDeleteEtherIpId, InEtherIpId, OutEtherIpId)
+ DECLARE_RPC_EX("EnumEtherIpId", RPC_ENUM_ETHERIP_ID, StEnumEtherIpId, InRpcEnumEtherIpId, OutRpcEnumEtherIpId, FreeRpcEnumEtherIpId)
+ DECLARE_RPC("SetOpenVpnSstpConfig", OPENVPN_SSTP_CONFIG, StSetOpenVpnSstpConfig, InOpenVpnSstpConfig, OutOpenVpnSstpConfig)
+ DECLARE_RPC("GetOpenVpnSstpConfig", OPENVPN_SSTP_CONFIG, StGetOpenVpnSstpConfig, InOpenVpnSstpConfig, OutOpenVpnSstpConfig)
+ DECLARE_RPC("GetDDnsClientStatus", DDNS_CLIENT_STATUS, StGetDDnsClientStatus, InDDnsClientStatus, OutDDnsClientStatus)
+ DECLARE_RPC("ChangeDDnsClientHostname", RPC_TEST, StChangeDDnsClientHostname, InRpcTest, OutRpcTest)
+ DECLARE_RPC("RegenerateServerCert", RPC_TEST, StRegenerateServerCert, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("MakeOpenVpnConfigFile", RPC_READ_LOG_FILE, StMakeOpenVpnConfigFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)
+ DECLARE_RPC("SetSpecialListener", RPC_SPECIAL_LISTENER, StSetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
+ DECLARE_RPC("GetSpecialListener", RPC_SPECIAL_LISTENER, StGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
+ DECLARE_RPC("GetAzureStatus", RPC_AZURE_STATUS, StGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
+ DECLARE_RPC("SetAzureStatus", RPC_AZURE_STATUS, StSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
+ DECLARE_RPC("GetDDnsInternetSettng", INTERNET_SETTING, StGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
+ DECLARE_RPC("SetDDnsInternetSettng", INTERNET_SETTING, StSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
+ // RPC function declaration: till here
+
+
+ if (ok == false)
+ {
+ err = ERR_NOT_SUPPORTED;
+ }
+
+ if (err != ERR_NO_ERROR)
+ {
+ PackAddInt(ret, "error", err);
+ }
+
+ if (true)
+ {
+ char tmp[MAX_PATH];
+ char ip[MAX_PATH];
+ UINT rpc_id = 0;
+
+ StrCpy(ip, sizeof(ip), "Unknown");
+
+ if (rpc->Sock != NULL)
+ {
+ IPToStr(ip, sizeof(ip), &rpc->Sock->RemoteIP);
+ rpc_id = rpc->Sock->socket;
+ }
+
+ Format(tmp, sizeof(tmp), "RPC: RPC-%u (%s): Leaving RPC [%s] (Error: %u).",
+ rpc_id, ip, name, err);
+
+ SiDebugLog(a->Server, tmp);
+ }
+
+ Unlock(cedar->CedarSuperLock);
+
+ return ret;
+}
+
+// RPC call function declaration: from here
+DECLARE_SC_EX("Test", RPC_TEST, ScTest, InRpcTest, OutRpcTest, FreeRpcTest)
+DECLARE_SC_EX("GetServerInfo", RPC_SERVER_INFO, ScGetServerInfo, InRpcServerInfo, OutRpcServerInfo, FreeRpcServerInfo)
+DECLARE_SC("GetServerStatus", RPC_SERVER_STATUS, ScGetServerStatus, InRpcServerStatus, OutRpcServerStatus)
+DECLARE_SC("CreateListener", RPC_LISTENER, ScCreateListener, InRpcListener, OutRpcListener)
+DECLARE_SC_EX("EnumListener", RPC_LISTENER_LIST, ScEnumListener, InRpcListenerList, OutRpcListenerList, FreeRpcListenerList)
+DECLARE_SC("DeleteListener", RPC_LISTENER, ScDeleteListener, InRpcListener, OutRpcListener)
+DECLARE_SC("EnableListener", RPC_LISTENER, ScEnableListener, InRpcListener, OutRpcListener)
+DECLARE_SC("SetServerPassword", RPC_SET_PASSWORD, ScSetServerPassword, InRpcSetPassword, OutRpcSetPassword)
+DECLARE_SC_EX("SetFarmSetting", RPC_FARM, ScSetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)
+DECLARE_SC_EX("GetFarmSetting", RPC_FARM, ScGetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)
+DECLARE_SC_EX("GetFarmInfo", RPC_FARM_INFO, ScGetFarmInfo, InRpcFarmInfo, OutRpcFarmInfo, FreeRpcFarmInfo)
+DECLARE_SC_EX("EnumFarmMember", RPC_ENUM_FARM, ScEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)
+DECLARE_SC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, ScGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)
+DECLARE_SC_EX("SetServerCert", RPC_KEY_PAIR, ScSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
+DECLARE_SC_EX("GetServerCert", RPC_KEY_PAIR, ScGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
+DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
+DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
+DECLARE_SC("CreateHub", RPC_CREATE_HUB, ScCreateHub, InRpcCreateHub, OutRpcCreateHub)
+DECLARE_SC("SetHub", RPC_CREATE_HUB, ScSetHub, InRpcCreateHub, OutRpcCreateHub)
+DECLARE_SC("GetHub", RPC_CREATE_HUB, ScGetHub, InRpcCreateHub, OutRpcCreateHub)
+DECLARE_SC_EX("EnumHub", RPC_ENUM_HUB, ScEnumHub, InRpcEnumHub, OutRpcEnumHub, FreeRpcEnumHub)
+DECLARE_SC("DeleteHub", RPC_DELETE_HUB, ScDeleteHub, InRpcDeleteHub, OutRpcDeleteHub)
+DECLARE_SC("GetHubRadius", RPC_RADIUS, ScGetHubRadius, InRpcRadius, OutRpcRadius)
+DECLARE_SC("SetHubRadius", RPC_RADIUS, ScSetHubRadius, InRpcRadius, OutRpcRadius)
+DECLARE_SC_EX("EnumConnection", RPC_ENUM_CONNECTION, ScEnumConnection, InRpcEnumConnection, OutRpcEnumConnection, FreeRpcEnumConnetion)
+DECLARE_SC("DisconnectConnection", RPC_DISCONNECT_CONNECTION, ScDisconnectConnection, InRpcDisconnectConnection, OutRpcDisconnectConnection)
+DECLARE_SC("GetConnectionInfo", RPC_CONNECTION_INFO, ScGetConnectionInfo, InRpcConnectionInfo, OutRpcConnectionInfo)
+DECLARE_SC("SetHubOnline", RPC_SET_HUB_ONLINE, ScSetHubOnline, InRpcSetHubOnline, OutRpcSetHubOnline)
+DECLARE_SC("GetHubStatus", RPC_HUB_STATUS, ScGetHubStatus, InRpcHubStatus, OutRpcHubStatus)
+DECLARE_SC("SetHubLog", RPC_HUB_LOG, ScSetHubLog, InRpcHubLog, OutRpcHubLog)
+DECLARE_SC("GetHubLog", RPC_HUB_LOG, ScGetHubLog, InRpcHubLog, OutRpcHubLog)
+DECLARE_SC_EX("AddCa", RPC_HUB_ADD_CA, ScAddCa, InRpcHubAddCa, OutRpcHubAddCa, FreeRpcHubAddCa)
+DECLARE_SC_EX("EnumCa", RPC_HUB_ENUM_CA, ScEnumCa, InRpcHubEnumCa, OutRpcHubEnumCa, FreeRpcHubEnumCa)
+DECLARE_SC_EX("GetCa", RPC_HUB_GET_CA, ScGetCa, InRpcHubGetCa, OutRpcHubGetCa, FreeRpcHubGetCa)
+DECLARE_SC("DeleteCa", RPC_HUB_DELETE_CA, ScDeleteCa, InRpcHubDeleteCa, OutRpcHubDeleteCa)
+DECLARE_SC_EX("CreateLink", RPC_CREATE_LINK, ScCreateLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+DECLARE_SC_EX("GetLink", RPC_CREATE_LINK, ScGetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+DECLARE_SC_EX("SetLink", RPC_CREATE_LINK, ScSetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+DECLARE_SC_EX("EnumLink", RPC_ENUM_LINK, ScEnumLink, InRpcEnumLink, OutRpcEnumLink, FreeRpcEnumLink)
+DECLARE_SC_EX("GetLinkStatus", RPC_LINK_STATUS, ScGetLinkStatus, InRpcLinkStatus, OutRpcLinkStatus, FreeRpcLinkStatus)
+DECLARE_SC("SetLinkOnline", RPC_LINK, ScSetLinkOnline, InRpcLink, OutRpcLink)
+DECLARE_SC("SetLinkOffline", RPC_LINK, ScSetLinkOffline, InRpcLink, OutRpcLink)
+DECLARE_SC("DeleteLink", RPC_LINK, ScDeleteLink, InRpcLink, OutRpcLink)
+DECLARE_SC("RenameLink", RPC_RENAME_LINK, ScRenameLink, InRpcRenameLink, OutRpcRenameLink)
+DECLARE_SC("AddAccess", RPC_ADD_ACCESS, ScAddAccess, InRpcAddAccess, OutRpcAddAccess)
+DECLARE_SC("DeleteAccess", RPC_DELETE_ACCESS, ScDeleteAccess, InRpcDeleteAccess, OutRpcDeleteAccess)
+DECLARE_SC_EX("EnumAccess", RPC_ENUM_ACCESS_LIST, ScEnumAccess, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)
+DECLARE_SC_EX("SetAccessList", RPC_ENUM_ACCESS_LIST, ScSetAccessList, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)
+DECLARE_SC_EX("CreateUser", RPC_SET_USER, ScCreateUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+DECLARE_SC_EX("SetUser", RPC_SET_USER, ScSetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+DECLARE_SC_EX("GetUser", RPC_SET_USER, ScGetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)
+DECLARE_SC("DeleteUser", RPC_DELETE_USER, ScDeleteUser, InRpcDeleteUser, OutRpcDeleteUser)
+DECLARE_SC_EX("EnumUser", RPC_ENUM_USER, ScEnumUser, InRpcEnumUser, OutRpcEnumUser, FreeRpcEnumUser)
+DECLARE_SC_EX("CreateGroup", RPC_SET_GROUP, ScCreateGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+DECLARE_SC_EX("SetGroup", RPC_SET_GROUP, ScSetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+DECLARE_SC_EX("GetGroup", RPC_SET_GROUP, ScGetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)
+DECLARE_SC("DeleteGroup", RPC_DELETE_USER, ScDeleteGroup, InRpcDeleteUser, OutRpcDeleteUser)
+DECLARE_SC_EX("EnumGroup", RPC_ENUM_GROUP, ScEnumGroup, InRpcEnumGroup, OutRpcEnumGroup, FreeRpcEnumGroup)
+DECLARE_SC_EX("EnumSession", RPC_ENUM_SESSION, ScEnumSession, InRpcEnumSession, OutRpcEnumSession, FreeRpcEnumSession)
+DECLARE_SC_EX("GetSessionStatus", RPC_SESSION_STATUS, ScGetSessionStatus, InRpcSessionStatus, OutRpcSessionStatus, FreeRpcSessionStatus)
+DECLARE_SC("DeleteSession", RPC_DELETE_SESSION, ScDeleteSession, InRpcDeleteSession, OutRpcDeleteSession)
+DECLARE_SC_EX("EnumMacTable", RPC_ENUM_MAC_TABLE, ScEnumMacTable, InRpcEnumMacTable, OutRpcEnumMacTable, FreeRpcEnumMacTable)
+DECLARE_SC("DeleteMacTable", RPC_DELETE_TABLE, ScDeleteMacTable, InRpcDeleteTable, OutRpcDeleteTable)
+DECLARE_SC_EX("EnumIpTable", RPC_ENUM_IP_TABLE, ScEnumIpTable, InRpcEnumIpTable, OutRpcEnumIpTable, FreeRpcEnumIpTable)
+DECLARE_SC("DeleteIpTable", RPC_DELETE_TABLE, ScDeleteIpTable, InRpcDeleteTable, OutRpcDeleteTable)
+DECLARE_SC("SetKeep", RPC_KEEP, ScSetKeep, InRpcKeep, OutRpcKeep)
+DECLARE_SC("GetKeep", RPC_KEEP, ScGetKeep, InRpcKeep, OutRpcKeep)
+DECLARE_SC("EnableSecureNAT", RPC_HUB, ScEnableSecureNAT, InRpcHub, OutRpcHub)
+DECLARE_SC("DisableSecureNAT", RPC_HUB, ScDisableSecureNAT, InRpcHub, OutRpcHub)
+DECLARE_SC("SetSecureNATOption", VH_OPTION, ScSetSecureNATOption, InVhOption, OutVhOption)
+DECLARE_SC("GetSecureNATOption", VH_OPTION, ScGetSecureNATOption, InVhOption, OutVhOption)
+DECLARE_SC_EX("EnumNAT", RPC_ENUM_NAT, ScEnumNAT, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)
+DECLARE_SC_EX("EnumDHCP", RPC_ENUM_DHCP, ScEnumDHCP, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)
+DECLARE_SC("GetSecureNATStatus", RPC_NAT_STATUS, ScGetSecureNATStatus, InRpcNatStatus, OutRpcNatStatus)
+DECLARE_SC_EX("EnumEthernet", RPC_ENUM_ETH, ScEnumEthernet, InRpcEnumEth, OutRpcEnumEth, FreeRpcEnumEth)
+DECLARE_SC("AddLocalBridge", RPC_LOCALBRIDGE, ScAddLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)
+DECLARE_SC("DeleteLocalBridge", RPC_LOCALBRIDGE, ScDeleteLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)
+DECLARE_SC_EX("EnumLocalBridge", RPC_ENUM_LOCALBRIDGE, ScEnumLocalBridge, InRpcEnumLocalBridge, OutRpcEnumLocalBridge, FreeRpcEnumLocalBridge)
+DECLARE_SC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, ScGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)
+DECLARE_SC("RebootServer", RPC_TEST, ScRebootServer, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("GetCaps", CAPSLIST, ScGetCaps, InRpcCapsList, OutRpcCapsList, FreeRpcCapsList)
+DECLARE_SC_EX("GetConfig", RPC_CONFIG, ScGetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)
+DECLARE_SC_EX("SetConfig", RPC_CONFIG, ScSetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)
+DECLARE_SC_EX("GetHubAdminOptions", RPC_ADMIN_OPTION, ScGetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+DECLARE_SC_EX("SetHubAdminOptions", RPC_ADMIN_OPTION, ScSetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+DECLARE_SC_EX("GetHubExtOptions", RPC_ADMIN_OPTION, ScGetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+DECLARE_SC_EX("SetHubExtOptions", RPC_ADMIN_OPTION, ScSetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+DECLARE_SC_EX("GetDefaultHubAdminOptions", RPC_ADMIN_OPTION, ScGetDefaultHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)
+DECLARE_SC("AddL3Switch", RPC_L3SW, ScAddL3Switch, InRpcL3Sw, OutRpcL3Sw)
+DECLARE_SC("DelL3Switch", RPC_L3SW, ScDelL3Switch, InRpcL3Sw, OutRpcL3Sw)
+DECLARE_SC_EX("EnumL3Switch", RPC_ENUM_L3SW, ScEnumL3Switch, InRpcEnumL3Sw, OutRpcEnumL3Sw, FreeRpcEnumL3Sw)
+DECLARE_SC("StartL3Switch", RPC_L3SW, ScStartL3Switch, InRpcL3Sw, OutRpcL3Sw)
+DECLARE_SC("StopL3Switch", RPC_L3SW, ScStopL3Switch, InRpcL3Sw, OutRpcL3Sw)
+DECLARE_SC("AddL3If", RPC_L3IF, ScAddL3If, InRpcL3If, OutRpcL3If)
+DECLARE_SC("DelL3If", RPC_L3IF, ScDelL3If, InRpcL3If, OutRpcL3If)
+DECLARE_SC_EX("EnumL3If", RPC_ENUM_L3IF, ScEnumL3If, InRpcEnumL3If, OutRpcEnumL3If, FreeRpcEnumL3If)
+DECLARE_SC("AddL3Table", RPC_L3TABLE, ScAddL3Table, InRpcL3Table, OutRpcL3Table)
+DECLARE_SC("DelL3Table", RPC_L3TABLE, ScDelL3Table, InRpcL3Table, OutRpcL3Table)
+DECLARE_SC_EX("EnumL3Table", RPC_ENUM_L3TABLE, ScEnumL3Table, InRpcEnumL3Table, OutRpcEnumL3Table, FreeRpcEnumL3Table)
+DECLARE_SC_EX("EnumCrl", RPC_ENUM_CRL, ScEnumCrl, InRpcEnumCrl, OutRpcEnumCrl, FreeRpcEnumCrl)
+DECLARE_SC_EX("AddCrl", RPC_CRL, ScAddCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+DECLARE_SC_EX("DelCrl", RPC_CRL, ScDelCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+DECLARE_SC_EX("GetCrl", RPC_CRL, ScGetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+DECLARE_SC_EX("SetCrl", RPC_CRL, ScSetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)
+DECLARE_SC_EX("SetAcList", RPC_AC_LIST, ScSetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)
+DECLARE_SC_EX("GetAcList", RPC_AC_LIST, ScGetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)
+DECLARE_SC_EX("EnumLogFile", RPC_ENUM_LOG_FILE, ScEnumLogFile, InRpcEnumLogFile, OutRpcEnumLogFile, FreeRpcEnumLogFile)
+DECLARE_SC_EX("ReadLogFile", RPC_READ_LOG_FILE, ScReadLogFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)
+DECLARE_SC("AddLicenseKey", RPC_TEST, ScAddLicenseKey, InRpcTest, OutRpcTest)
+DECLARE_SC("DelLicenseKey", RPC_TEST, ScDelLicenseKey, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, ScEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)
+DECLARE_SC("GetLicenseStatus", RPC_LICENSE_STATUS, ScGetLicenseStatus, InRpcLicenseStatus, OutRpcLicenseStatus)
+DECLARE_SC("SetSysLog", SYSLOG_SETTING, ScSetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)
+DECLARE_SC("GetSysLog", SYSLOG_SETTING, ScGetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)
+DECLARE_SC_EX("EnumEthVLan", RPC_ENUM_ETH_VLAN, ScEnumEthVLan, InRpcEnumEthVLan, OutRpcEnumEthVLan, FreeRpcEnumEthVLan)
+DECLARE_SC("SetEnableEthVLan", RPC_TEST, ScSetEnableEthVLan, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("SetHubMsg", RPC_MSG, ScSetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+DECLARE_SC_EX("GetHubMsg", RPC_MSG, ScGetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+DECLARE_SC("Crash", RPC_TEST, ScCrash, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("GetAdminMsg", RPC_MSG, ScGetAdminMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)
+DECLARE_SC("Flush", RPC_TEST, ScFlush, InRpcTest, OutRpcTest)
+DECLARE_SC("Debug", RPC_TEST, ScDebug, InRpcTest, OutRpcTest)
+DECLARE_SC("SetIPsecServices", IPSEC_SERVICES, ScSetIPsecServices, InIPsecServices, OutIPsecServices)
+DECLARE_SC("GetIPsecServices", IPSEC_SERVICES, ScGetIPsecServices, InIPsecServices, OutIPsecServices)
+DECLARE_SC("AddEtherIpId", ETHERIP_ID, ScAddEtherIpId, InEtherIpId, OutEtherIpId)
+DECLARE_SC("GetEtherIpId", ETHERIP_ID, ScGetEtherIpId, InEtherIpId, OutEtherIpId)
+DECLARE_SC("DeleteEtherIpId", ETHERIP_ID, ScDeleteEtherIpId, InEtherIpId, OutEtherIpId)
+DECLARE_SC_EX("EnumEtherIpId", RPC_ENUM_ETHERIP_ID, ScEnumEtherIpId, InRpcEnumEtherIpId, OutRpcEnumEtherIpId, FreeRpcEnumEtherIpId)
+DECLARE_SC("SetOpenVpnSstpConfig", OPENVPN_SSTP_CONFIG, ScSetOpenVpnSstpConfig, InOpenVpnSstpConfig, OutOpenVpnSstpConfig)
+DECLARE_SC("GetOpenVpnSstpConfig", OPENVPN_SSTP_CONFIG, ScGetOpenVpnSstpConfig, InOpenVpnSstpConfig, OutOpenVpnSstpConfig)
+DECLARE_SC("GetDDnsClientStatus", DDNS_CLIENT_STATUS, ScGetDDnsClientStatus, InDDnsClientStatus, OutDDnsClientStatus)
+DECLARE_SC("ChangeDDnsClientHostname", RPC_TEST, ScChangeDDnsClientHostname, InRpcTest, OutRpcTest)
+DECLARE_SC("RegenerateServerCert", RPC_TEST, ScRegenerateServerCert, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("MakeOpenVpnConfigFile", RPC_READ_LOG_FILE, ScMakeOpenVpnConfigFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)
+DECLARE_SC("SetSpecialListener", RPC_SPECIAL_LISTENER, ScSetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
+DECLARE_SC("GetSpecialListener", RPC_SPECIAL_LISTENER, ScGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
+DECLARE_SC("GetAzureStatus", RPC_AZURE_STATUS, ScGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
+DECLARE_SC("SetAzureStatus", RPC_AZURE_STATUS, ScSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
+DECLARE_SC("GetDDnsInternetSettng", INTERNET_SETTING, ScGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
+DECLARE_SC("SetDDnsInternetSettng", INTERNET_SETTING, ScSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
+// RPC call function declaration: till here
+
+// Setting VPN Gate Server Configuration
+UINT StSetVgsConfig(ADMIN *a, VGS_CONFIG *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Get VPN Gate configuration
+UINT StGetVgsConfig(ADMIN *a, VGS_CONFIG *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Get DDNS proxy configuration
+UINT StGetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->DDnsClient == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(INTERNET_SETTING));
+
+ DCGetInternetSetting(s->DDnsClient, t);
+
+ return ret;
+}
+
+// Set DDNS proxy configuration
+UINT StSetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->DDnsClient == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ DCSetInternetSetting(s->DDnsClient, t);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Get Azure status
+UINT StGetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ AZURE_CLIENT *ac;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (SiIsAzureSupported(s) == false)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ ac = s->AzureClient;
+ if (ac == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(RPC_AZURE_STATUS));
+
+ Lock(ac->Lock);
+ {
+ t->IsConnected = ac->IsConnected;
+ t->IsEnabled = ac->IsEnabled;
+ }
+ Unlock(ac->Lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Set Azure status
+UINT StSetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (SiIsAzureSupported(s) == false)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ SiSetAzureEnable(s, t->IsEnabled);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get special listener status
+UINT StGetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ Zero(t, sizeof(RPC_SPECIAL_LISTENER));
+ t->VpnOverDnsListener = s->EnableVpnOverDns;
+ t->VpnOverIcmpListener = s->EnableVpnOverIcmp;
+
+ return ERR_NO_ERROR;
+}
+
+// Set special listener status
+UINT StSetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ // Check ports
+ if (t->VpnOverDnsListener && (MAKEBOOL(s->EnableVpnOverDns) != MAKEBOOL(t->VpnOverDnsListener)))
+ {
+ if (SiCanOpenVpnOverDnsPort() == false)
+ {
+ return ERR_SPECIAL_LISTENER_DNS_ERROR;
+ }
+ }
+
+ if (t->VpnOverIcmpListener && (MAKEBOOL(s->EnableVpnOverIcmp) != MAKEBOOL(t->VpnOverIcmpListener)))
+ {
+ if (SiCanOpenVpnOverIcmpPort() == false)
+ {
+ return ERR_SPECIAL_LISTENER_ICMP_ERROR;
+ }
+ }
+
+ s->EnableVpnOverDns = t->VpnOverDnsListener;
+ s->EnableVpnOverIcmp = t->VpnOverIcmpListener;
+
+ SiApplySpecialListenerStatus(s);
+
+ ALog(a, NULL, "LA_SET_SPECIAL_LISTENER");
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Set configurations for OpenVPN and SSTP
+UINT StSetOpenVpnSstpConfig(ADMIN *a, OPENVPN_SSTP_CONFIG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ SiSetOpenVPNAndSSTPConfig(s, t);
+
+ ALog(a, NULL, "LA_SET_OVPN_SSTP_CONFIG");
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get configurations for OpenVPN and SSTP
+UINT StGetOpenVpnSstpConfig(ADMIN *a, OPENVPN_SSTP_CONFIG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(OPENVPN_SSTP_CONFIG));
+ SiGetOpenVPNAndSSTPConfig(s, t);
+
+ return ERR_NO_ERROR;
+}
+
+// Get status of DDNS client
+UINT StGetDDnsClientStatus(ADMIN *a, DDNS_CLIENT_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->DDnsClient == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(DDNS_CLIENT_STATUS));
+ DCGetStatus(s->DDnsClient, t);
+
+ return ERR_NO_ERROR;
+}
+
+// Change host-name for DDNS client
+UINT StChangeDDnsClientHostname(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->DDnsClient == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ ret = DCChangeHostName(s->DDnsClient, t->StrValue);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ ALog(a, NULL, "LA_DDNS_HOSTNAME_CHANGED", t->StrValue);
+ }
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Regenerate server certification
+UINT StRegenerateServerCert(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ X *x;
+ K *k;
+
+ SERVER_ADMIN_ONLY;
+
+ SiGenerateDefaultCertEx(&x, &k, t->StrValue);
+
+ SetCedarCert(c, x, k);
+
+ ALog(a, NULL, "LA_REGENERATE_SERVER_CERT", t->StrValue);
+
+ IncrementServerConfigRevision(s);
+
+ FreeX(x);
+ FreeK(k);
+
+ return ERR_NO_ERROR;
+}
+
+// Generate OpenVPN configuration files
+UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ ZIP_PACKER *p;
+ FIFO *f;
+ BUF *readme_buf;
+ BUF *readme_pdf_buf;
+ BUF *sample_buf;
+ OPENVPN_SSTP_CONFIG config;
+ LIST *port_list;
+ char my_hostname[MAX_SIZE];
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ SiGetOpenVPNAndSSTPConfig(s, &config);
+
+ if (config.EnableOpenVPN == false)
+ {
+ return ERR_OPENVPN_IS_NOT_ENABLED;
+ }
+
+ port_list = StrToIntList(config.OpenVPNPortList, true);
+
+ FreeRpcReadLogFile(t);
+ Zero(t, sizeof(RPC_READ_LOG_FILE));
+
+ p = NewZipPacker();
+
+ // readme.txt
+ readme_buf = ReadDump("|openvpn_readme.txt");
+
+ // readme.pdf
+ readme_pdf_buf = ReadDump("|openvpn_readme.pdf");
+
+ // sample.ovpn
+ sample_buf = ReadDump("|openvpn_sample.ovpn");
+
+ // host name
+ GetMachineHostName(my_hostname, sizeof(my_hostname));
+ my_hostname[16] = 0;
+
+ if (readme_buf == NULL || sample_buf == NULL || readme_pdf_buf == NULL)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ BUF *config_l3_buf, *config_l2_buf;
+ X *x = NULL;
+ BUF *x_buf;
+ char protocol[MAX_SIZE];
+ UINT port = OPENVPN_UDP_PORT;
+ char port_str[MAX_SIZE];
+ char hostname[MAX_SIZE];
+ char tag_before_hostname[MAX_SIZE];
+ DDNS_CLIENT_STATUS ddns;
+ UCHAR *zero_buffer;
+ UINT zero_buffer_size = 128 * 1024;
+ char name_tmp[MAX_SIZE];
+ X *dummy_x = NULL;
+ K *dummy_private_k = NULL;
+ K *dummy_public_k = NULL;
+ BUF *dummy_x_buf = NULL;
+ BUF *dummy_k_buf = NULL;
+
+ zero_buffer = ZeroMalloc(zero_buffer_size);
+
+
+ if (x == NULL)
+ {
+ Lock(c->lock);
+ {
+ x = CloneX(c->ServerX);
+ }
+ Unlock(c->lock);
+ }
+
+ x_buf = XToBuf(x, true);
+
+ SeekBufToEnd(x_buf);
+ WriteBufChar(x_buf, 0);
+ SeekBufToBegin(x_buf);
+
+ // Generate dummy certification
+ if (x != NULL)
+ {
+ if (RsaGen(&dummy_private_k, &dummy_public_k, x->bits))
+ {
+ NAME *name;
+ wchar_t cn[128];
+
+ UniToStr64(cn, Rand64());
+
+ name = NewName(cn, cn, cn, L"US", NULL, NULL);
+
+ dummy_x = NewRootX(dummy_public_k, dummy_private_k, name, MAX(GetDaysUntil2038(), SERVER_DEFAULT_CERT_DAYS), NULL);
+
+ FreeName(name);
+
+ dummy_x_buf = XToBuf(dummy_x, true);
+ SeekBufToEnd(dummy_x_buf);
+ WriteBufChar(dummy_x_buf, 0);
+ SeekBufToBegin(dummy_x_buf);
+
+ dummy_k_buf = KToBuf(dummy_private_k, true, NULL);
+ SeekBufToEnd(dummy_k_buf);
+ WriteBufChar(dummy_k_buf, 0);
+ SeekBufToBegin(dummy_k_buf);
+ }
+ }
+
+ FreeX(x);
+ Zero(hostname, sizeof(hostname));
+ Zero(tag_before_hostname, sizeof(tag_before_hostname));
+
+ Zero(&ddns, sizeof(ddns));
+ if (s->DDnsClient != NULL)
+ {
+ DCGetStatus(s->DDnsClient, &ddns);
+
+ if (IsEmptyStr(ddns.CurrentHostName) == false && IsEmptyStr(ddns.DnsSuffix) == false &&
+ ddns.Err_IPv4 == ERR_NO_ERROR)
+ {
+ StrCpy(tag_before_hostname, sizeof(tag_before_hostname),
+ "# Note: The below hostname is came from the Dynamic DNS Client function\r\n"
+ "# which is running on the VPN Server. If you don't want to use\r\n"
+ "# the Dynamic DNS hostname, replace it to either IP address or\r\n"
+ "# other domain's hostname.\r\n\r\n");
+
+ Format(hostname, sizeof(hostname), "%s.v4%s", ddns.CurrentHostName, ddns.DnsSuffix);
+ }
+ }
+
+ if (IsEmptyStr(hostname))
+ {
+ IP myip;
+
+ Zero(&myip, sizeof(myip));
+ GetCurrentGlobalIP(&myip, false);
+
+ if (IsZeroIP(&myip))
+ {
+ GetCurrentGlobalIPGuess(&myip, false);
+ }
+
+ IPToStr(hostname, sizeof(hostname), &myip);
+ }
+
+ SeekBuf(sample_buf, sample_buf->Size, 0);
+ WriteBuf(sample_buf, zero_buffer, zero_buffer_size);
+
+ config_l3_buf = CloneBuf(sample_buf);
+ config_l2_buf = CloneBuf(sample_buf);
+
+ // Generate contents of configuration
+ if (LIST_NUM(port_list) >= 1)
+ {
+ StrCpy(protocol, sizeof(protocol), "udp");
+
+ if (IsIntInList(port_list, OPENVPN_UDP_PORT))
+ {
+ port = OPENVPN_UDP_PORT;
+ }
+ else
+ {
+ port = *((UINT *)(LIST_DATA(port_list, 0)));
+ }
+ }
+ else
+ {
+ RPC_LISTENER_LIST tt;
+ UINT i;
+
+ port = 0;
+
+ StrCpy(protocol, sizeof(protocol), "tcp");
+
+ Zero(&tt, sizeof(tt));
+
+ StEnumListener(a, &tt);
+
+ for (i = 0;i < tt.NumPort;i++)
+ {
+ if (tt.Enables[i] && tt.Errors[i] == false)
+ {
+ port = tt.Ports[i];
+ break;
+ }
+ }
+
+ FreeRpcListenerList(&tt);
+
+ if (port == 0)
+ {
+ StrCpy(protocol, sizeof(protocol), "udp");
+ port = OPENVPN_UDP_PORT;
+ }
+ }
+
+ ToStr(port_str, port);
+
+ if (IsEmptyStr(my_hostname) == false)
+ {
+ StrCat(my_hostname, sizeof(my_hostname), "_");
+
+ StrLower(my_hostname);
+ }
+
+ ZipAddFileSimple(p, "readme.txt", LocalTime64(), 0, readme_buf->Buf, readme_buf->Size);
+ ZipAddFileSimple(p, "readme.pdf", LocalTime64(), 0, readme_pdf_buf->Buf, readme_pdf_buf->Size);
+
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$TAG_TUN_TAP$", "tun", false);
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$TAG_PROTO$", protocol, false);
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$TAG_HOSTNAME$", hostname, false);
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$TAG_BEFORE_REMOTE$", tag_before_hostname, false);
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$TAG_PORT$", port_str, false);
+
+ if (x_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$CA$", x_buf->Buf, false);
+ }
+
+ if (dummy_x_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$CERT$", dummy_x_buf->Buf, false);
+ }
+
+ if (dummy_k_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
+ "$KEY$", dummy_k_buf->Buf, false);
+ }
+
+ Format(name_tmp, sizeof(name_tmp), "%sopenvpn_remote_access_l3.ovpn", my_hostname);
+ ZipAddFileSimple(p, name_tmp, LocalTime64(), 0, config_l3_buf->Buf, StrLen(config_l3_buf->Buf));
+
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$TAG_TUN_TAP$", "tap", false);
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$TAG_PROTO$", protocol, false);
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$TAG_HOSTNAME$", hostname, false);
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$TAG_BEFORE_REMOTE$", tag_before_hostname, false);
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$TAG_PORT$", port_str, false);
+
+ if (x_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$CA$", x_buf->Buf, false);
+ }
+
+ if (dummy_x_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$CERT$", dummy_x_buf->Buf, false);
+ }
+
+ if (dummy_k_buf != NULL)
+ {
+ ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
+ "$KEY$", dummy_k_buf->Buf, false);
+ }
+
+ Format(name_tmp, sizeof(name_tmp), "%sopenvpn_site_to_site_bridge_l2.ovpn", my_hostname);
+ ZipAddFileSimple(p, name_tmp, LocalTime64(), 0, config_l2_buf->Buf, StrLen(config_l2_buf->Buf));
+
+ FreeBuf(config_l3_buf);
+ FreeBuf(config_l2_buf);
+
+ f = ZipFinish(p);
+
+ if (f != NULL)
+ {
+ t->Buffer = NewBuf();
+ WriteBuf(t->Buffer, FifoPtr(f), FifoSize(f));
+ SeekBuf(t->Buffer, 0, 0);
+ }
+
+ FreeBuf(readme_buf);
+ FreeBuf(sample_buf);
+ FreeBuf(readme_pdf_buf);
+ FreeBuf(x_buf);
+
+ FreeX(dummy_x);
+ FreeK(dummy_private_k);
+ FreeK(dummy_public_k);
+
+ FreeBuf(dummy_k_buf);
+ FreeBuf(dummy_x_buf);
+
+ Free(zero_buffer);
+ }
+
+ FreeStrList(port_list);
+
+ FreeZipPacker(p);
+
+ return ERR_NO_ERROR;
+}
+
+// Set IPsec service configuration
+UINT StSetIPsecServices(ADMIN *a, IPSEC_SERVICES *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ IPsecServerSetServices(s->IPsecServer, t);
+
+ ALog(a, NULL, "LA_SET_IPSEC_CONFIG");
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get IPsec service configuration
+UINT StGetIPsecServices(ADMIN *a, IPSEC_SERVICES *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(IPSEC_SERVICES));
+ IPsecServerGetServices(s->IPsecServer, t);
+
+ return ERR_NO_ERROR;
+}
+
+// Add EtherIP ID setting
+UINT StAddEtherIpId(ADMIN *a, ETHERIP_ID *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ AddEtherIPId(s->IPsecServer, t);
+
+ ALog(a, NULL, "LA_ADD_ETHERIP_ID", t->Id);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get EtherIP ID setting
+UINT StGetEtherIpId(ADMIN *a, ETHERIP_ID *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ char id[MAX_SIZE];
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(id, sizeof(id), t->Id);
+
+ Zero(t, sizeof(ETHERIP_ID));
+ if (SearchEtherIPId(s->IPsecServer, t, id) == false)
+ {
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Delete EtherIP ID setting
+UINT StDeleteEtherIpId(ADMIN *a, ETHERIP_ID *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ char id[MAX_SIZE];
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(id, sizeof(id), t->Id);
+
+ if (DeleteEtherIPId(s->IPsecServer, id) == false)
+ {
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, NULL, "LA_DEL_ETHERIP_ID", id);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate EtherIP ID settings
+UINT StEnumEtherIpId(ADMIN *a, RPC_ENUM_ETHERIP_ID *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (GetServerCapsBool(s, "b_support_ipsec") == false || s->IPsecServer == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ FreeRpcEnumEtherIpId(t);
+ Zero(t, sizeof(RPC_ENUM_ETHERIP_ID));
+
+ Lock(s->IPsecServer->LockSettings);
+ {
+ UINT i;
+ UINT num;
+
+ num = LIST_NUM(s->IPsecServer->EtherIPIdList);
+
+ t->NumItem = num;
+ t->IdList = ZeroMalloc(sizeof(ETHERIP_ID) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ ETHERIP_ID *d = &t->IdList[i];
+ ETHERIP_ID *src = LIST_DATA(s->IPsecServer->EtherIPIdList, i);
+
+ Copy(d, src, sizeof(ETHERIP_ID));
+ }
+ }
+ Unlock(s->IPsecServer->LockSettings);
+
+ return ERR_NO_ERROR;
+}
+
+// Set message of today on hub
+UINT StSetHubMsg(ADMIN *a, RPC_MSG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+ if (UniStrLen(t->Msg) > HUB_MAXMSG_LEN)
+ {
+ return ERR_MEMORY_NOT_ENOUGH;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_msg") != 0)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ SetHubMsg(h, t->Msg);
+ }
+
+ ReleaseHub(h);
+ }
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Get message of today on hub
+UINT StGetHubMsg(ADMIN *a, RPC_MSG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+ if (UniStrLen(t->Msg) > HUB_MAXMSG_LEN)
+ {
+ return ERR_MEMORY_NOT_ENOUGH;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ FreeRpcMsg(t);
+ Zero(t, sizeof(t));
+
+ t->Msg = GetHubMsg(h);
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Do debug function
+UINT StDebug(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ RPC_TEST t2;
+
+ SERVER_ADMIN_ONLY;
+
+ Zero(&t2, sizeof(t2));
+
+ ret = SiDebug(s, &t2, t->IntValue, t->StrValue);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ Copy(t, &t2, sizeof(RPC_TEST));
+ }
+ else
+ {
+ Zero(t, sizeof(RPC_TEST));
+ }
+
+ return ret;
+}
+
+// Flush configuration file
+UINT StFlush(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ UINT size;
+
+ SERVER_ADMIN_ONLY;
+
+ size = SiWriteConfigurationFile(s);
+
+ t->IntValue = size;
+
+ return ERR_NO_ERROR;
+}
+
+// Do Crash
+UINT StCrash(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+
+#ifdef OS_WIN32
+ MsSetEnableMinidump(false);
+#endif // OS_WIN32
+
+ CrashNow();
+
+ return ERR_NO_ERROR;
+}
+
+// Get message for administrators
+UINT StGetAdminMsg(ADMIN *a, RPC_MSG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ RPC_WINVER server_ver;
+ RPC_WINVER client_ver;
+ wchar_t winver_msg_client[3800];
+ wchar_t winver_msg_server[3800];
+ UINT tmpsize;
+ wchar_t *tmp;
+
+ FreeRpcMsg(t);
+ Zero(t, sizeof(RPC_MSG));
+
+ // Check for Windows version
+ GetWinVer(&server_ver);
+ Copy(&client_ver, &a->ClientWinVer, sizeof(RPC_WINVER));
+
+ Zero(winver_msg_client, sizeof(winver_msg_client));
+ Zero(winver_msg_server, sizeof(winver_msg_server));
+
+ if (IsSupportedWinVer(&client_ver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ client_ver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ if (IsSupportedWinVer(&server_ver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ server_ver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + 10000;
+
+ tmp = ZeroMalloc(tmpsize);
+
+ if (
+ c->Bridge == false)
+ {
+ if (GetCurrentLangId() != SE_LANG_ENGLISH)
+ {
+ UniStrCat(tmp, tmpsize, _UU("OSS_MSG"));
+ }
+ }
+
+ UniStrCat(tmp, tmpsize, winver_msg_client);
+ UniStrCat(tmp, tmpsize, winver_msg_server);
+
+ t->Msg = tmp;
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate VLAN tag transparent setting
+UINT StEnumEthVLan(ADMIN *a, RPC_ENUM_ETH_VLAN *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+
+#ifdef OS_WIN32
+ if (GetServerCapsBool(s, "b_support_eth_vlan") == false)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ FreeRpcEnumEthVLan(t);
+ Zero(t, sizeof(RPC_ENUM_ETH_VLAN));
+
+ if (EnumEthVLanWin32(t) == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ }
+#else // OS_WIN32
+ ret = ERR_NOT_SUPPORTED;
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Set VLAN tag transparent setting
+UINT StSetEnableEthVLan(ADMIN *a, RPC_TEST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+
+#ifdef OS_WIN32
+ if (GetServerCapsBool(s, "b_support_eth_vlan") == false)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else if (MsIsAdmin() == false)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ if (SetVLanEnableStatus(t->StrValue, MAKEBOOL(t->IntValue)) == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ }
+#else // OS_WIN32
+ ret = ERR_NOT_SUPPORTED;
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Get license status
+UINT StGetLicenseStatus(ADMIN *a, RPC_LICENSE_STATUS *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Enumerate license key
+UINT StEnumLicenseKey(ADMIN *a, RPC_ENUM_LICENSE_KEY *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Add new license key
+UINT StAddLicenseKey(ADMIN *a, RPC_TEST *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Delete a license key
+UINT StDelLicenseKey(ADMIN *a, RPC_TEST *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Download a log file
+BUF *DownloadFileFromServer(RPC *r, char *server_name, char *filepath, UINT total_size, DOWNLOAD_PROC *proc, void *param)
+{
+ UINT offset;
+ BUF *buf;
+ // Validate arguments
+ if (r == NULL || filepath == NULL)
+ {
+ return NULL;
+ }
+
+ if (server_name == NULL)
+ {
+ server_name = "";
+ }
+
+ offset = 0;
+
+ buf = NewBuf();
+
+ while (true)
+ {
+ DOWNLOAD_PROGRESS g;
+ RPC_READ_LOG_FILE t;
+ UINT ret;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.FilePath, sizeof(t.FilePath), filepath);
+ t.Offset = offset;
+ StrCpy(t.ServerName, sizeof(t.ServerName), server_name);
+
+ ret = ScReadLogFile(r, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Failed
+ FreeRpcReadLogFile(&t);
+ FreeBuf(buf);
+ return NULL;
+ }
+
+ if (t.Buffer == NULL)
+ {
+ // read to the end
+ break;
+ }
+
+ // Update current progress
+ offset += t.Buffer->Size;
+ Zero(&g, sizeof(g));
+ g.Param = param;
+ g.CurrentSize = offset;
+ g.TotalSize = MAX(total_size, offset);
+ g.ProgressPercent = (UINT)(MAKESURE((UINT64)g.CurrentSize * 100ULL / (UINT64)(MAX(g.TotalSize, 1)), 0, 100ULL));
+
+ WriteBuf(buf, t.Buffer->Buf, t.Buffer->Size);
+
+ FreeRpcReadLogFile(&t);
+
+ if (proc != NULL)
+ {
+ if (proc(&g) == false)
+ {
+ // Canceled by user
+ FreeBuf(buf);
+ return NULL;
+ }
+ }
+ }
+
+ if (buf->Size == 0)
+ {
+ // Downloading failed
+ FreeBuf(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+// Read a log file
+UINT StReadLogFile(ADMIN *a, RPC_READ_LOG_FILE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ char logfilename[MAX_PATH];
+ char servername[MAX_HOST_NAME_LEN + 1];
+ UINT offset;
+ bool local = true;
+
+ if (IsEmptyStr(t->FilePath))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ StrCpy(logfilename, sizeof(logfilename), t->FilePath);
+ StrCpy(servername, sizeof(servername), t->ServerName);
+ offset = t->Offset;
+
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ GetMachineName(servername, sizeof(servername));
+ }
+
+ // Check the permission to read the log file
+ if (a->LogFileList == NULL)
+ {
+ // Cache not found
+ return ERR_OBJECT_NOT_FOUND;
+ }
+ if (CheckLogFileNameFromEnumList(a->LogFileList, logfilename, servername) == false)
+ {
+ // There is no such file in the log file list
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ FreeRpcReadLogFile(t);
+ Zero(t, sizeof(RPC_READ_LOG_FILE));
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i;
+
+ // When the host name in request is a cluster member, redirect the request
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (f->Me == false)
+ {
+ if (StrCmpi(f->hostname, servername) == 0)
+ {
+ RPC_READ_LOG_FILE tt;
+
+ Zero(&tt, sizeof(tt));
+ local = false;
+
+ StrCpy(tt.ServerName, sizeof(tt.ServerName), servername);
+ StrCpy(tt.FilePath, sizeof(tt.FilePath), logfilename);
+ tt.Offset = offset;
+
+ if (SiCallReadLogFile(s, f, &tt))
+ {
+ if (tt.Buffer != NULL && tt.Buffer->Size > 0)
+ {
+ t->Buffer = NewBuf();
+ WriteBuf(t->Buffer, tt.Buffer->Buf, tt.Buffer->Size);
+ }
+ }
+
+ FreeRpcReadLogFile(&tt);
+
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+
+ // Read a local file
+ if (local)
+ {
+ SiReadLocalLogFile(s, logfilename, offset, t);
+ }
+
+ if (offset == 0)
+ {
+ ALog(a, NULL, "LA_READ_LOG_FILE", servername, logfilename);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate log files
+UINT StEnumLogFile(ADMIN *a, RPC_ENUM_LOG_FILE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT i;
+ bool no_access = false;
+
+ HUB *h;
+
+ if (a->ServerAdmin == false)
+ {
+ h = GetHub(c, a->HubName);
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_read_log_file") != 0)
+ {
+ no_access = true;
+ }
+
+ ReleaseHub(h);
+ }
+ else
+ {
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Since Management session will become unstable if log files are
+ // enumerated on a cluster controller, it forbids.
+ return ERR_NOT_SUPPORTED;
+ }
+ }
+
+ if (no_access)
+ {
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ FreeRpcEnumLogFile(t);
+ Zero(t, sizeof(RPC_ENUM_LOG_FILE));
+
+ // Enumerate local log files
+ SiEnumLocalLogFileList(s, a->ServerAdmin ? NULL : a->HubName, t);
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i;
+ LIST *tt_list = NewListFast(NULL);
+
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (f->Me == false)
+ {
+ // Enumerate log files on other cluster members.
+ RPC_ENUM_LOG_FILE *tt;
+ tt = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE));
+
+ if (SiCallEnumLogFileList(s, f, tt, a->ServerAdmin ? "" : a->HubName))
+ {
+ UINT i;
+ for (i = 0;i < tt->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &tt->Items[i];
+
+ StrCpy(e->ServerName, sizeof(e->ServerName), f->hostname);
+ }
+
+ Add(tt_list, tt);
+ }
+ else
+ {
+ Free(tt);
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ for (i = 0;i < LIST_NUM(tt_list);i++)
+ {
+ RPC_ENUM_LOG_FILE *tt = LIST_DATA(tt_list, i);
+
+ AdjoinRpcEnumLogFile(t, tt);
+ FreeRpcEnumLogFile(tt);
+
+ Free(tt);
+ }
+
+ ReleaseList(tt_list);
+ }
+
+ // Cache the last list of log files on RPC session
+ if (a->LogFileList != NULL)
+ {
+ FreeEnumLogFile(a->LogFileList);
+ }
+
+ a->LogFileList = NewListFast(CmpLogFile);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+ LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));
+
+ f->FileSize = e->FileSize;
+ f->UpdatedTime = e->UpdatedTime;
+ StrCpy(f->Path, sizeof(f->Path), e->FilePath);
+ StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);
+
+ Insert(a->LogFileList, f);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+
+// Get access control list
+UINT StGetAcList(ADMIN *a, RPC_AC_LIST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ FreeRpcAcList(t);
+ Zero(t, sizeof(RPC_AC_LIST));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ HUBDB *db = h->HubDb;
+
+ LockList(db->AcList);
+ {
+ t->o = NewAcList();
+
+ SetAcList(t->o, db->AcList);
+ }
+ UnlockList(db->AcList);
+ }
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Set access control list
+UINT StSetAcList(ADMIN *a, RPC_AC_LIST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+
+ if (c->Bridge)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_control_list") != 0)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ HUBDB *db = h->HubDb;
+
+ LockList(db->AcList);
+ {
+ SetAcList(db->AcList, t->o);
+
+ {
+ ALog(a, h, "LA_SET_AC_LIST", LIST_NUM(t->o));
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ UnlockList(db->AcList);
+ }
+ }
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Set CRL (Certificate Revocation List) entry
+UINT StSetCrl(ADMIN *a, RPC_CRL *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ UINT key;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ key = t->Key;
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ LockList(h->HubDb->CrlList);
+ {
+ CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);
+
+ if (crl == NULL)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ CRL *new_crl = CopyCrl(t->Crl);
+ if (ReplaceListPointer(h->HubDb->CrlList, crl, new_crl))
+ {
+ ALog(a, h, "LA_ADD_CRL");
+ FreeCrl(crl);
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ }
+ UnlockList(h->HubDb->CrlList);
+ }
+ }
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Get CRL (Certificate Revocation List) entry
+UINT StGetCrl(ADMIN *a, RPC_CRL *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ UINT key;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ key = t->Key;
+
+ FreeRpcCrl(t);
+ Zero(t, sizeof(RPC_CRL));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ t->Key = key;
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ LockList(h->HubDb->CrlList);
+ {
+ CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);
+
+ if (crl == NULL)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ t->Crl = CopyCrl(crl);
+ }
+ }
+ UnlockList(h->HubDb->CrlList);
+ }
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Delete CRL (Certificate Revocation List) entry
+UINT StDelCrl(ADMIN *a, RPC_CRL *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ LockList(h->HubDb->CrlList);
+ {
+ CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);
+
+ if (crl == NULL)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ ALog(a, h, "LA_DEL_CRL");
+ FreeCrl(crl);
+ Delete(h->HubDb->CrlList, crl);
+ }
+ }
+ UnlockList(h->HubDb->CrlList);
+ }
+ }
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Add new CRL (Certificate Revocation List) entry
+UINT StAddCrl(ADMIN *a, RPC_CRL *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ if (c->Bridge)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ LockList(h->HubDb->CrlList);
+ {
+ if (LIST_NUM(h->HubDb->CrlList) < MAX_HUB_CRLS)
+ {
+ CRL *crl = CopyCrl(t->Crl);
+
+ Insert(h->HubDb->CrlList, crl);
+
+ ALog(a, h, "LA_SET_CRL");
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ UnlockList(h->HubDb->CrlList);
+ }
+ }
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Get CRL (Certificate Revocation List) index
+UINT StEnumCrl(ADMIN *a, RPC_ENUM_CRL *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcEnumCrl(t);
+ Zero(t, sizeof(RPC_ENUM_CRL));
+
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ h = GetHub(c, hubname);
+
+ if (h == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ if (h->HubDb == NULL)
+ {
+ ret = ERR_NOT_SUPPORTED;
+ }
+ else
+ {
+ LockList(h->HubDb->CrlList);
+ {
+ UINT i;
+
+ t->NumItem = LIST_NUM(h->HubDb->CrlList);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_CRL_ITEM) * t->NumItem);
+
+ for (i = 0;i < LIST_NUM(h->HubDb->CrlList);i++)
+ {
+ CRL *crl = LIST_DATA(h->HubDb->CrlList, i);
+ wchar_t *info = GenerateCrlStr(crl);
+
+ UniStrCpy(t->Items[i].CrlInfo, sizeof(t->Items[i].CrlInfo), info);
+ Free(info);
+
+ t->Items[i].Key = POINTER_TO_KEY(crl);
+ }
+ }
+ UnlockList(h->HubDb->CrlList);
+ }
+
+ ReleaseHub(h);
+ }
+
+ return ret;
+}
+
+// Get routing table on virtual L3 switch
+UINT StEnumL3Table(ADMIN *a, RPC_ENUM_L3TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+ char name[MAX_HUBNAME_LEN + 1];
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ StrCpy(name, sizeof(name), t->Name);
+ FreeRpcEnumL3Table(t);
+ Zero(t, sizeof(RPC_ENUM_L3TABLE));
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ UINT i;
+
+ Lock(sw->lock);
+ {
+ t->NumItem = LIST_NUM(sw->TableList);
+ t->Items = ZeroMalloc(sizeof(RPC_L3TABLE) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ L3TABLE *tbl = LIST_DATA(sw->TableList, i);
+ RPC_L3TABLE *e = &t->Items[i];
+
+ StrCpy(e->Name, sizeof(e->Name), name);
+ e->NetworkAddress = tbl->NetworkAddress;
+ e->SubnetMask = tbl->SubnetMask;
+ e->GatewayAddress = tbl->GatewayAddress;
+ e->Metric = tbl->Metric;
+ }
+ }
+ Unlock(sw->lock);
+
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Delete routing table entry on virtual L3 switch
+UINT StDelL3Table(ADMIN *a, RPC_L3TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ SERVER_ADMIN_ONLY;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ L3TABLE tbl;
+
+ Zero(&tbl, sizeof(tbl));
+ tbl.NetworkAddress = t->NetworkAddress;
+ tbl.SubnetMask = t->SubnetMask;
+ tbl.GatewayAddress = t->GatewayAddress;
+ tbl.Metric = t->Metric;
+
+ if (L3DelTable(sw, &tbl) == false)
+ {
+ ret = ERR_LAYER3_TABLE_DEL_FAILED;
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ IPToStr32(tmp, sizeof(tmp), tbl.NetworkAddress);
+ ALog(a, NULL, "LA_DEL_L3_TABLE", tmp, t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Add new routing table entry on virtual L3 switch
+UINT StAddL3Table(ADMIN *a, RPC_L3TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ if (IsNetworkAddress32(t->NetworkAddress, t->SubnetMask) == false ||
+ IsHostIPAddress32(t->GatewayAddress) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ L3TABLE tbl;
+
+ Zero(&tbl, sizeof(tbl));
+ tbl.NetworkAddress = t->NetworkAddress;
+ tbl.SubnetMask = t->SubnetMask;
+ tbl.GatewayAddress = t->GatewayAddress;
+ tbl.Metric = t->Metric;
+
+ if (L3AddTable(sw, &tbl) == false)
+ {
+ ret = ERR_LAYER3_TABLE_ADD_FAILED;
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ IPToStr32(tmp, sizeof(tmp), tbl.NetworkAddress);
+ ALog(a, NULL, "LA_ADD_L3_TABLE", tmp, t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Enumerate virtual interfaces on virtual L3 switch
+UINT StEnumL3If(ADMIN *a, RPC_ENUM_L3IF *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+ char name[MAX_HUBNAME_LEN + 1];
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ StrCpy(name, sizeof(name), t->Name);
+
+ FreeRpcEnumL3If(t);
+ Zero(t, sizeof(RPC_ENUM_L3IF));
+
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ Lock(sw->lock);
+ {
+ UINT i;
+
+ t->NumItem = LIST_NUM(sw->IfList);
+ t->Items = ZeroMalloc(sizeof(RPC_L3IF) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ L3IF *f = LIST_DATA(sw->IfList, i);
+ RPC_L3IF *e = &t->Items[i];
+
+ StrCpy(e->Name, sizeof(e->Name), sw->Name);
+ StrCpy(e->HubName, sizeof(e->HubName), f->HubName);
+ e->IpAddress = f->IpAddress;
+ e->SubnetMask = f->SubnetMask;
+ }
+ }
+ Unlock(sw->lock);
+
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Delete a virtual interface on virtual L3 switch
+UINT StDelL3If(ADMIN *a, RPC_L3IF *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ if (L3DelIf(sw, t->HubName) == false)
+ {
+ ret = ERR_LAYER3_IF_DEL_FAILED;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_DEL_L3_IF", t->HubName, t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Add new virtual interface on virtual L3 switch
+UINT StAddL3If(ADMIN *a, RPC_L3IF *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+
+ if (IsSubnetMask32(t->SubnetMask) == false || IsHostIPAddress32(t->IpAddress) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ if ((t->IpAddress & (~t->SubnetMask)) == 0)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ Lock(sw->lock);
+ {
+ if (L3SearchIf(sw, t->HubName) != NULL)
+ {
+ // Already exists
+ ret = ERR_LAYER3_IF_EXISTS;
+ }
+ else
+ {
+ if (L3AddIf(sw, t->HubName, t->IpAddress, t->SubnetMask) == false)
+ {
+ ret = ERR_LAYER3_IF_ADD_FAILED;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_ADD_L3_IF", t->HubName, t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ }
+ Unlock(sw->lock);
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Stop a virtual layer-3 switch
+UINT StStopL3Switch(ADMIN *a, RPC_L3SW *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ L3SwStop(sw);
+ ALog(a, NULL, "LA_STOP_L3_SW", sw->Name);
+ ReleaseL3Sw(sw);
+
+ IncrementServerConfigRevision(s);
+ }
+
+ return ret;
+}
+
+// Start a virtual layer-3 switch
+UINT StStartL3Switch(ADMIN *a, RPC_L3SW *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ sw = L3GetSw(c, t->Name);
+
+ if (sw == NULL)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ Lock(sw->lock);
+ {
+ // Count the registered virtual interfaces
+ if (LIST_NUM(sw->IfList) >= 1)
+ {
+ L3SwStart(sw);
+
+ ALog(a, NULL, "LA_START_L3_SW", sw->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+ else
+ {
+ ret = ERR_LAYER3_CANT_START_SWITCH;
+ }
+ }
+ Unlock(sw->lock);
+
+ ReleaseL3Sw(sw);
+ }
+
+ return ret;
+}
+
+// Enumerate virtual layer-3 switches
+UINT StEnumL3Switch(ADMIN *a, RPC_ENUM_L3SW *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ FreeRpcEnumL3Sw(t);
+ Zero(t, sizeof(RPC_ENUM_L3SW));
+
+ LockList(c->L3SwList);
+ {
+ t->NumItem = LIST_NUM(c->L3SwList);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_L3SW_ITEM) * t->NumItem);
+ for (i = 0;i < LIST_NUM(c->L3SwList);i++)
+ {
+ L3SW *sw = LIST_DATA(c->L3SwList, i);
+ RPC_ENUM_L3SW_ITEM *e = &t->Items[i];
+
+ Lock(sw->lock);
+ {
+ StrCpy(e->Name, sizeof(e->Name), sw->Name);
+ e->NumInterfaces = LIST_NUM(sw->IfList);
+ e->NumTables = LIST_NUM(sw->TableList);
+ e->Active = sw->Active;
+ e->Online = sw->Online;
+ }
+ Unlock(sw->lock);
+ }
+ }
+ UnlockList(c->L3SwList);
+
+ return ret;
+}
+
+// Delete a virtual layer-3 switch
+UINT StDelL3Switch(ADMIN *a, RPC_L3SW *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ if (L3DelSw(c, t->Name) == false)
+ {
+ ret = ERR_LAYER3_SW_NOT_FOUND;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_DEL_L3_SW", t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+
+ return ret;
+}
+
+// Add a new virtual layer-3 switch
+UINT StAddL3Switch(ADMIN *a, RPC_L3SW *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ L3SW *sw;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (IsSafeStr(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ // Duplication check
+ sw = L3GetSw(c, t->Name);
+ if (sw != NULL)
+ {
+ // Already exists
+ ReleaseL3Sw(sw);
+ ret = ERR_LAYER3_SW_EXISTS;
+ }
+ else
+ {
+ LockList(c->L3SwList);
+ {
+ if (LIST_NUM(c->L3SwList) >= GetServerCapsInt(s, "i_max_l3_sw"))
+ {
+ // No more virtual interfaces
+ sw = NULL;
+ }
+ else
+ {
+ // Create
+ sw = L3AddSw(c, t->Name);
+
+ if (sw != NULL)
+ {
+ ALog(a, NULL, "LA_ADD_L3_SW", t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ }
+ UnlockList(c->L3SwList);
+
+ if (sw == NULL)
+ {
+ // Failed
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ // Success
+ ReleaseL3Sw(sw);
+ }
+ }
+
+ return ret;
+}
+
+// Set hub extended options
+UINT StSetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ bool not_server_admin = false;
+
+ if (t->NumItem > MAX_HUB_ADMIN_OPTIONS)
+ {
+ return ERR_TOO_MANT_ITEMS;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+
+ CHECK_RIGHT;
+
+ if (a->ServerAdmin == false)
+ {
+ not_server_admin = true;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (GetHubAdminOption(h, "deny_hub_admin_change_ext_option") && not_server_admin)
+ {
+ // Insufficient permission
+ ReleaseHub(h);
+
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ // Update setting
+ Lock(h->lock);
+ {
+ DataToHubOptionStruct(h->Option, t);
+ }
+ Unlock(h->lock);
+
+ ALog(a, NULL, "LA_SET_HUB_EXT_OPTION", h->Name);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get hub extended options
+UINT StGetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ FreeRpcAdminOption(t);
+ Zero(t, sizeof(RPC_ADMIN_OPTION));
+
+ StrCpy(t->HubName, sizeof(t->HubName), h->Name);
+
+ // Get options
+ Lock(h->lock);
+ {
+ HubOptionStructToData(t, h->Option, h->Name);
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Set hub administration options
+UINT StSetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ bool not_server_admin = false;
+
+
+ if (t->NumItem > MAX_HUB_ADMIN_OPTIONS)
+ {
+ return ERR_TOO_MANT_ITEMS;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (a->ServerAdmin == false)
+ {
+ not_server_admin = true;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (GetHubAdminOption(h, "allow_hub_admin_change_option") == false
+ && not_server_admin)
+ {
+ // Insufficient permission
+ ReleaseHub(h);
+
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ LockList(h->AdminOptionList);
+ {
+ DeleteAllHubAdminOption(h, false);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ADMIN_OPTION *e = &t->Items[i];
+ ADMIN_OPTION *a = ZeroMalloc(sizeof(ADMIN_OPTION));
+
+ StrCpy(a->Name, sizeof(a->Name), e->Name);
+ a->Value = e->Value;
+
+ Insert(h->AdminOptionList, a);
+ }
+
+ AddHubAdminOptionsDefaults(h, false);
+ }
+ UnlockList(h->AdminOptionList);
+
+ ALog(a, NULL, "LA_SET_HUB_ADMIN_OPTION", h->Name);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get hub administration options
+UINT StGetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ FreeRpcAdminOption(t);
+ Zero(t, sizeof(RPC_ADMIN_OPTION));
+
+ StrCpy(t->HubName, sizeof(t->HubName), h->Name);
+
+ LockList(h->AdminOptionList);
+ {
+ t->NumItem = LIST_NUM(h->AdminOptionList);
+ t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ADMIN_OPTION *a = LIST_DATA(h->AdminOptionList, i);
+ ADMIN_OPTION *e = &t->Items[i];
+
+ StrCpy(e->Name, sizeof(e->Name), a->Name);
+ e->Value = a->Value;
+ }
+ }
+ UnlockList(h->AdminOptionList);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get default hub administration options
+UINT StGetDefaultHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
+{
+ UINT i;
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (a->Server->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ FreeRpcAdminOption(t);
+ Zero(t, sizeof(RPC_ADMIN_OPTION));
+
+ t->NumItem = num_admin_options;
+ t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ADMIN_OPTION *a = &t->Items[i];
+
+ StrCpy(a->Name, sizeof(a->Name), admin_options[i].Name);
+ a->Value = admin_options[i].Value;
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Get configuration file stream
+UINT StGetConfig(ADMIN *a, RPC_CONFIG *t)
+{
+ SERVER *s;
+
+ SERVER_ADMIN_ONLY;
+
+ FreeRpcConfig(t);
+ Zero(t, sizeof(RPC_CONFIG));
+
+ s = a->Server;
+
+ ALog(a, NULL, "LA_GET_CONFIG");
+
+ if (s->CfgRw != NULL)
+ {
+ FOLDER *f = SiWriteConfigurationToCfg(s);
+ BUF *b = CfgFolderToBuf(f, true);
+
+ StrCpy(t->FileName, sizeof(t->FileName), s->CfgRw->FileName + (s->CfgRw->FileName[0] == '@' ? 1 : 0));
+
+ t->FileData = ZeroMalloc(b->Size + 1);
+ Copy(t->FileData, b->Buf, b->Size);
+
+ CfgDeleteFolder(f);
+ FreeBuf(b);
+
+ return ERR_NO_ERROR;
+ }
+ else
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+}
+
+// Overwrite configuration file by specified data
+UINT StSetConfig(ADMIN *a, RPC_CONFIG *t)
+{
+ SERVER *s;
+ IO *o;
+ char filename[MAX_PATH];
+
+ SERVER_ADMIN_ONLY;
+
+ s = a->Server;
+ if (s->CfgRw == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Write new configuration file
+ Format(filename, sizeof(filename), "%s.new", s->CfgRw->FileName);
+
+ o = FileCreate(filename);
+
+ FileWrite(o, t->FileData, StrLen(t->FileData));
+
+ FileClose(o);
+
+ IncrementServerConfigRevision(s);
+
+ ALog(a, NULL, "LA_SET_CONFIG");
+
+ // Reboot server itself
+ SiRebootServer(s->Cedar->Bridge);
+
+ return ERR_NO_ERROR;
+}
+
+// Get capabilities
+UINT StGetCaps(ADMIN *a, CAPSLIST *t)
+{
+ FreeRpcCapsList(t);
+ Zero(t, sizeof(CAPSLIST));
+
+ GetServerCapsMain(a->Server, t);
+
+ return ERR_NO_ERROR;
+}
+
+// Reboot server itself
+UINT StRebootServer(ADMIN *a, RPC_TEST *t)
+{
+ SERVER_ADMIN_ONLY;
+
+ ALog(a, NULL, "LA_REBOOT_SERVER");
+
+ SiRebootServerEx(a->Server->Cedar->Bridge, t->IntValue);
+
+ return ERR_NO_ERROR;
+}
+
+// Get availability to localbridge function
+UINT StGetBridgeSupport(ADMIN *a, RPC_BRIDGE_SUPPORT *t)
+{
+ Zero(t, sizeof(RPC_BRIDGE_SUPPORT));
+
+ t->IsBridgeSupportedOs = IsBridgeSupported();
+ t->IsWinPcapNeeded = IsNeedWinPcap();
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate Ethernet devices
+UINT StEnumEthernet(ADMIN *a, RPC_ENUM_ETH *t)
+{
+ TOKEN_LIST *o;
+ UINT i;
+ char tmp[MAX_SIZE];
+ bool unix_support = false;
+
+ SERVER_ADMIN_ONLY;
+
+#ifdef OS_UNIX
+ unix_support = EthIsInterfaceDescriptionSupportedUnix();
+#endif // OS_UNIX
+
+ o = GetEthList();
+ if (o == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ FreeRpcEnumEth(t);
+ Zero(t, sizeof(RPC_ENUM_ETH));
+
+ t->NumItem = o->NumTokens;
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *e = &t->Items[i];
+
+ StrCpy(e->DeviceName, sizeof(e->DeviceName), o->Token[i]);
+
+ StrCpy(tmp, sizeof(tmp), e->DeviceName);
+
+#ifdef OS_WIN32
+ GetEthNetworkConnectionName(e->NetworkConnectionName, sizeof(e->NetworkConnectionName), e->DeviceName);
+#else
+ if (unix_support == false)
+ {
+ StrCpy(tmp, sizeof(tmp), "");
+ }
+ else
+ {
+ if (EthGetInterfaceDescriptionUnix(e->DeviceName, tmp, sizeof(tmp)) == false)
+ {
+ StrCpy(tmp, sizeof(tmp), e->DeviceName);
+ }
+ }
+
+ StrToUni(e->NetworkConnectionName, sizeof(e->NetworkConnectionName), tmp);
+#endif
+ }
+
+ FreeToken(o);
+
+ return ERR_NO_ERROR;
+}
+
+// Add a new local bridge
+UINT StAddLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t)
+{
+ if (IsEmptyStr(t->DeviceName) || IsEmptyStr(t->HubName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+
+ if (IsEthSupported() == false)
+ {
+ return ERR_LOCAL_BRIDGE_UNSUPPORTED;
+ }
+
+#ifdef OS_WIN32
+ if (true)
+ {
+ char tmp[MAX_SIZE];
+ UINT id = Win32EthGetNameAndIdFromCombinedName(tmp, sizeof(tmp), t->DeviceName);
+
+ if (id == 0)
+ {
+ // If a ID is not specified in Win32, adding will fail
+ return ERR_OBJECT_NOT_FOUND;
+ }
+ }
+#endif // OS_WIN32
+
+ ALog(a, NULL, "LA_ADD_BRIDGE", t->HubName, t->DeviceName);
+
+ AddLocalBridge(a->Server->Cedar, t->HubName, t->DeviceName, false, false, t->TapMode, NULL, false);
+
+ IncrementServerConfigRevision(a->Server);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete a local bridge
+UINT StDeleteLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t)
+{
+ if (IsEmptyStr(t->DeviceName) || IsEmptyStr(t->HubName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ ALog(a, NULL, "LA_DELETE_BRIDGE", t->HubName, t->DeviceName);
+
+ if (DeleteLocalBridge(a->Server->Cedar, t->HubName, t->DeviceName) == false)
+ {
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ IncrementServerConfigRevision(a->Server);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate local bridges
+UINT StEnumLocalBridge(ADMIN *a, RPC_ENUM_LOCALBRIDGE *t)
+{
+ UINT i;
+ CEDAR *c;
+
+ if (IsEthSupported() == false)
+ {
+ return ERR_LOCAL_BRIDGE_UNSUPPORTED;
+ }
+
+ FreeRpcEnumLocalBridge(t);
+ Zero(t, sizeof(RPC_ENUM_LOCALBRIDGE));
+
+ c = a->Server->Cedar;
+
+ LockList(c->LocalBridgeList);
+ {
+ t->NumItem = LIST_NUM(c->LocalBridgeList);
+ t->Items = ZeroMalloc(sizeof(RPC_LOCALBRIDGE) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t->Items[i];
+ LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
+
+ if (br->Bridge == false)
+ {
+ e->Online = e->Active = false;
+ }
+ else
+ {
+ e->Online = true;
+ if (br->Bridge->Active)
+ {
+ e->Active = true;
+ }
+ else
+ {
+ e->Active = false;
+ }
+ }
+ StrCpy(e->DeviceName, sizeof(e->DeviceName), br->DeviceName);
+ StrCpy(e->HubName, sizeof(e->HubName), br->HubName);
+
+ e->TapMode = br->TapMode;
+ }
+ }
+ UnlockList(c->LocalBridgeList);
+
+ return ERR_NO_ERROR;
+}
+
+// Set syslog function setting
+UINT StSetSysLog(ADMIN *a, SYSLOG_SETTING *t)
+{
+ SERVER *s = a->Server;
+
+ SERVER_ADMIN_ONLY;
+
+ if (GetServerCapsBool(s, "b_support_syslog") == false)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ SiSetSysLogSetting(s, t);
+
+ IncrementServerConfigRevision(s);
+ ALog(a, NULL, "LA_SET_SYSLOG");
+
+ return ERR_NO_ERROR;
+}
+
+// Get syslog function setting
+UINT StGetSysLog(ADMIN *a, SYSLOG_SETTING *t)
+{
+ SERVER *s = a->Server;
+
+ SiGetSysLogSetting(s, t);
+
+ if (a->ServerAdmin == false)
+ {
+ // Hide server name for non-administrator
+ if (t->SaveType == SYSLOG_NONE)
+ {
+ StrCpy(t->Hostname, sizeof(t->Hostname), "");
+ t->Port = 0;
+ }
+ else
+ {
+ StrCpy(t->Hostname, sizeof(t->Hostname), "Secret");
+ t->Port = 0;
+ }
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Set keep-alive function setting
+UINT StSetKeep(ADMIN *a, RPC_KEEP *t)
+{
+ SERVER *s = a->Server;
+
+ if (t->UseKeepConnect)
+ {
+ if (IsEmptyStr(t->KeepConnectHost) ||
+ t->KeepConnectPort == 0 ||
+ t->KeepConnectPort >= 65536)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ Lock(s->Keep->lock);
+ {
+ KEEP *keep = s->Keep;
+ keep->Enable = t->UseKeepConnect;
+ keep->Server = true;
+ StrCpy(keep->ServerName, sizeof(keep->ServerName), t->KeepConnectHost);
+ keep->ServerPort = t->KeepConnectPort;
+ keep->UdpMode = t->KeepConnectProtocol;
+ keep->Interval = t->KeepConnectInterval * 1000;
+ if (keep->Interval < 5000)
+ {
+ keep->Interval = 5000;
+ }
+ else if (keep->Interval > 600000)
+ {
+ keep->Interval = 600000;
+ }
+ }
+ Unlock(s->Keep->lock);
+
+ ALog(a, NULL, "LA_SET_KEEP");
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get keep-alive function setting
+UINT StGetKeep(ADMIN *a, RPC_KEEP *t)
+{
+ SERVER *s = a->Server;
+
+ Zero(t, sizeof(RPC_KEEP));
+
+ Lock(s->Keep->lock);
+ {
+ KEEP *k = s->Keep;
+ t->UseKeepConnect = k->Enable;
+ StrCpy(t->KeepConnectHost, sizeof(t->KeepConnectHost), k->ServerName);
+ t->KeepConnectPort = k->ServerPort;
+ t->KeepConnectProtocol = k->UdpMode;
+ t->KeepConnectInterval = k->Interval / 1000;
+ }
+ Unlock(s->Keep->lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete IP address table entry
+UINT StDeleteIpTable(ADMIN *a, RPC_DELETE_TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_delete_iptable") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ LockList(h->IpTable);
+ {
+ if (IsInListKey(h->IpTable, t->Key))
+ {
+ IP_TABLE_ENTRY *e = ListKeyToPointer(h->IpTable, t->Key);
+ Free(e);
+ Delete(h->IpTable, e);
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(h->IpTable);
+
+ if (ret == ERR_OBJECT_NOT_FOUND)
+ {
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i;
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ SiCallDeleteIpTable(s, f, t->HubName, t->Key);
+ ret = ERR_NO_ERROR;
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Get local IP address table
+UINT SiEnumIpTable(SERVER *s, char *hubname, RPC_ENUM_IP_TABLE *t)
+{
+ CEDAR *c;
+ UINT i;
+ HUB *h = NULL;
+ // Validate arguments
+ if (s == NULL || hubname == NULL || t == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ c = s->Cedar;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, hubname);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ LockList(h->IpTable);
+ {
+ t->NumIpTable = LIST_NUM(h->IpTable);
+ t->IpTables = ZeroMalloc(sizeof(RPC_ENUM_IP_TABLE_ITEM) * t->NumIpTable);
+
+ for (i = 0;i < t->NumIpTable;i++)
+ {
+ RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];
+ IP_TABLE_ENTRY *table = LIST_DATA(h->IpTable, i);
+
+ e->Key = POINTER_TO_KEY(table);
+ StrCpy(e->SessionName, sizeof(e->SessionName), table->Session->Name);
+ e->Ip = IPToUINT(&table->Ip);
+ Copy(&e->IpV6, &table->Ip, sizeof(IP));
+ e->DhcpAllocated = table->DhcpAllocated;
+ e->CreatedTime = TickToTime(table->CreatedTime);
+ e->UpdatedTime = TickToTime(table->UpdatedTime);
+
+ GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));
+ }
+ }
+ UnlockList(h->IpTable);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get IP address table
+UINT StEnumIpTable(ADMIN *a, RPC_ENUM_IP_TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ CHECK_RIGHT;
+
+ // Get local IP address table
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcEnumIpTable(t);
+ Zero(t, sizeof(RPC_ENUM_IP_TABLE));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ ret = SiEnumIpTable(s, hubname, t);
+ if (ret != ERR_NO_ERROR)
+ {
+ return ret;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Get remote IP address table
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_ENUM_IP_TABLE tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallEnumIpTable(s, f, hubname, &tmp);
+
+ AdjoinRpcEnumIpTable(t, &tmp);
+ FreeRpcEnumIpTable(&tmp);
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+
+ return ret;
+}
+
+// Delete MAC address table entry
+UINT StDeleteMacTable(ADMIN *a, RPC_DELETE_TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_delete_mactable") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ LockList(h->MacTable);
+ {
+ if (IsInListKey(h->MacTable, t->Key))
+ {
+ MAC_TABLE_ENTRY *e = ListKeyToPointer(h->MacTable, t->Key);
+ Free(e);
+ Delete(h->MacTable, e);
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(h->MacTable);
+
+ if (ret == ERR_OBJECT_NOT_FOUND)
+ {
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i;
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ SiCallDeleteMacTable(s, f, t->HubName, t->Key);
+ ret = ERR_NO_ERROR;
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Get local MAC address table
+UINT SiEnumMacTable(SERVER *s, char *hubname, RPC_ENUM_MAC_TABLE *t)
+{
+ CEDAR *c;
+ UINT i;
+ HUB *h = NULL;
+ // Validate arguments
+ if (s == NULL || hubname == NULL || t == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ c = s->Cedar;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, hubname);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ LockList(h->MacTable);
+ {
+ t->NumMacTable = LIST_NUM(h->MacTable);
+ t->MacTables = ZeroMalloc(sizeof(RPC_ENUM_MAC_TABLE_ITEM) * t->NumMacTable);
+
+ for (i = 0;i < t->NumMacTable;i++)
+ {
+ RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];
+ MAC_TABLE_ENTRY *mac = LIST_DATA(h->MacTable, i);
+
+ e->Key = POINTER_TO_KEY(mac);
+ StrCpy(e->SessionName, sizeof(e->SessionName), mac->Session->Name);
+ Copy(e->MacAddress, mac->MacAddress, sizeof(e->MacAddress));
+ e->CreatedTime = TickToTime(mac->CreatedTime);
+ e->UpdatedTime = TickToTime(mac->UpdatedTime);
+ e->VlanId = mac->VlanId;
+
+ GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));
+ }
+ }
+ UnlockList(h->MacTable);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get MAC address table
+UINT StEnumMacTable(ADMIN *a, RPC_ENUM_MAC_TABLE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ CHECK_RIGHT;
+
+ // Get local MAC address table
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcEnumMacTable(t);
+ Zero(t, sizeof(RPC_ENUM_MAC_TABLE));
+
+ ret = SiEnumMacTable(s, hubname, t);
+ if (ret != ERR_NO_ERROR)
+ {
+ return ret;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Get remote MAC address table
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_ENUM_MAC_TABLE tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallEnumMacTable(s, f, hubname, &tmp);
+
+ AdjoinRpcEnumMacTable(t, &tmp);
+ FreeRpcEnumMacTable(&tmp);
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+
+ return ret;
+}
+
+// Delete a session
+UINT StDeleteSession(ADMIN *a, RPC_DELETE_SESSION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ char name[MAX_SESSION_NAME_LEN + 1];
+ SESSION *sess;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ StrCpy(name, sizeof(name), t->Name);
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_disconnect_session") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ sess = GetSessionByName(h, name);
+
+ if (sess == NULL)
+ {
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Cluster controller
+ UINT i;
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ // Try to disconnect
+ SiCallDeleteSession(s, f, t->HubName, t->Name);
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ else
+ {
+ if (sess->LinkModeServer)
+ {
+ ret = ERR_LINK_CANT_DISCONNECT;
+ }
+ else if (sess->SecureNATMode)
+ {
+ ret = ERR_SNAT_CANT_DISCONNECT;
+ }
+ else if (sess->BridgeMode)
+ {
+ ret = ERR_BRIDGE_CANT_DISCONNECT;
+ }
+ else if (sess->L3SwitchMode)
+ {
+ ret = ERR_LAYER3_CANT_DISCONNECT;
+ }
+ else
+ {
+ StopSession(sess);
+ }
+ ReleaseSession(sess);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ ALog(a, h, "LA_DELETE_SESSION", t->Name);
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Get session status
+UINT StGetSessionStatus(ADMIN *a, RPC_SESSION_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ char name[MAX_SESSION_NAME_LEN + 1];
+ SESSION *sess;
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ StrCpy(name, sizeof(name), t->Name);
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_query_session") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ FreeRpcSessionStatus(t);
+ Zero(t, sizeof(RPC_SESSION_STATUS));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ sess = GetSessionByName(h, t->Name);
+
+ if (sess == NULL)
+ {
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Session is not found
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ else
+ {
+ UINT i;
+ // Try to find the session on other cluster member
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_SESSION_STATUS tmp;
+ Zero(&tmp, sizeof(tmp));
+ StrCpy(tmp.HubName, sizeof(tmp.HubName), t->HubName);
+ StrCpy(tmp.Name, sizeof(tmp.Name), t->Name);
+
+ if (SiCallGetSessionStatus(s, f, &tmp))
+ {
+ if (StrLen(tmp.HubName) != 0)
+ {
+ // Success to get session status
+ Copy(t, &tmp, sizeof(RPC_SESSION_STATUS));
+ break;
+ }
+ else
+ {
+ FreeRpcSessionStatus(&tmp);
+ }
+ }
+ }
+ }
+
+ if (i == LIST_NUM(s->FarmMemberList))
+ {
+ // not found after all
+ //
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+ else
+ {
+ SESSION *s = sess;
+
+ Lock(s->lock);
+ {
+ StrCpy(t->Username, sizeof(t->Username), s->Username);
+ StrCpy(t->RealUsername, sizeof(t->RealUsername), s->UserNameReal);
+ StrCpy(t->GroupName, sizeof(t->GroupName), s->GroupName);
+ Copy(&t->NodeInfo, &s->NodeInfo, sizeof(NODE_INFO));
+
+ if (s->Connection != NULL)
+ {
+ t->ClientIp = IPToUINT(&s->Connection->ClientIp);
+ if (IsIP6(&s->Connection->ClientIp))
+ {
+ Copy(&t->ClientIp6, &s->Connection->ClientIp.ipv6_addr, sizeof(t->ClientIp6));
+ }
+
+ StrCpy(t->ClientHostName, sizeof(t->ClientHostName), s->Connection->ClientHostname);
+ }
+ }
+ Unlock(s->lock);
+
+ CiGetSessionStatus(&t->Status, s);
+
+ ReleaseSession(s);
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Main routine of session enumeration
+void SiEnumSessionMain(SERVER *s, RPC_ENUM_SESSION *t)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT ret = ERR_NO_ERROR;
+ UINT num;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ FreeRpcEnumSession(t);
+ Zero(t, sizeof(RPC_ENUM_SESSION));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ // Local session enumeration
+ num = 0;
+ SiEnumLocalSession(s, hubname, t);
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ LIST *fm_list;
+
+ fm_list = NewListFast(NULL);
+
+ // Remote session enumeration
+ LockList(s->FarmMemberList);
+ {
+ while (true)
+ {
+ bool escape = true;
+
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsInList(fm_list, f) == false)
+ {
+ Add(fm_list, f);
+ escape = false;
+
+ if (f->Me == false)
+ {
+ RPC_ENUM_SESSION tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallEnumSession(s, f, hubname, &tmp);
+
+ AdjoinRpcEnumSession(t, &tmp);
+ FreeRpcEnumSession(&tmp);
+ }
+
+ break;
+ }
+ }
+
+ if (escape)
+ {
+ break;
+ }
+
+ UnlockList(s->FarmMemberList);
+ LockList(s->FarmMemberList);
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ ReleaseList(fm_list);
+ }
+}
+
+// Enumerate sessions
+UINT StEnumSession(ADMIN *a, RPC_ENUM_SESSION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_enum_session") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ SiEnumSessionMain(s, t);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Enumerate groups
+UINT StEnumGroup(ADMIN *a, RPC_ENUM_GROUP *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ CHECK_RIGHT;
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ AcLock(h);
+ {
+ UINT i, j;
+
+ FreeRpcEnumGroup(t);
+ Zero(t, sizeof(RPC_ENUM_GROUP));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ t->NumGroup = LIST_NUM(h->HubDb->GroupList);
+ t->Groups = ZeroMalloc(sizeof(RPC_ENUM_GROUP_ITEM) * t->NumGroup);
+
+ for (i = 0;i < t->NumGroup;i++)
+ {
+ RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];
+ USERGROUP *g = LIST_DATA(h->HubDb->GroupList, i);
+
+ Lock(g->lock);
+ {
+ StrCpy(e->Name, sizeof(e->Name), g->Name);
+ UniStrCpy(e->Realname, sizeof(e->Realname), g->RealName);
+ UniStrCpy(e->Note, sizeof(e->Note), g->Note);
+ if (g->Policy != NULL)
+ {
+ if (g->Policy->Access == false)
+ {
+ e->DenyAccess = true;
+ }
+ }
+ }
+ Unlock(g->lock);
+
+ e->NumUsers = 0;
+
+
+ LockList(h->HubDb->UserList);
+ {
+ for (j = 0;j < LIST_NUM(h->HubDb->UserList);j++)
+ {
+ USER *u = LIST_DATA(h->HubDb->UserList, j);
+
+ Lock(u->lock);
+ {
+ if (u->Group == g)
+ {
+ e->NumUsers++;
+ }
+ }
+ Unlock(u->lock);
+ }
+ }
+ UnlockList(h->HubDb->UserList);
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete a group
+UINT StDeleteGroup(ADMIN *a, RPC_DELETE_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ AcLock(h);
+ {
+ if (AcDeleteGroup(h, t->Name) == false)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ AcUnlock(h);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ ALog(a, h, "LA_DELETE_GROUP", t->Name);
+ }
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Get group information
+UINT StGetGroup(ADMIN *a, RPC_SET_GROUP *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ AcLock(h);
+ {
+ USERGROUP *g = AcGetGroup(h, t->Name);
+
+ if (g == NULL)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ else
+ {
+ FreeRpcSetGroup(t);
+ Zero(t, sizeof(RPC_SET_GROUP));
+
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ Lock(g->lock);
+ {
+ StrCpy(t->Name, sizeof(t->Name), g->Name);
+ UniStrCpy(t->Realname, sizeof(t->Realname), g->RealName);
+ UniStrCpy(t->Note, sizeof(t->Note), g->Note);
+ Copy(&t->Traffic, g->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(g->lock);
+
+ t->Policy = GetGroupPolicy(g);
+
+ ReleaseGroup(g);
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Set group setting
+UINT StSetGroup(ADMIN *a, RPC_SET_GROUP *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ AcLock(h);
+ {
+ USERGROUP *g = AcGetGroup(h, t->Name);
+ if (g == NULL)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ else
+ {
+ Lock(g->lock);
+ {
+ Free(g->RealName);
+ Free(g->Note);
+ g->RealName = UniCopyStr(t->Realname);
+ g->Note = UniCopyStr(t->Note);
+ }
+ Unlock(g->lock);
+
+ SetGroupPolicy(g, t->Policy);
+
+ ReleaseGroup(g);
+
+ ALog(a, h, "LA_SET_GROUP", t->Name);
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Create a group
+UINT StCreateGroup(ADMIN *a, RPC_SET_GROUP *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+ if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ CHECK_RIGHT;
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ AcLock(h);
+ {
+ if (AcIsGroup(h, t->Name))
+ {
+ ret = ERR_GROUP_ALREADY_EXISTS;
+ }
+ else
+ {
+ USERGROUP *g = NewGroup(t->Name, t->Realname, t->Note);
+ SetGroupPolicy(g, t->Policy);
+
+ if ((LIST_NUM(h->HubDb->GroupList) >= GetServerCapsInt(a->Server, "i_max_users_per_hub")) ||
+ ((GetHubAdminOption(h, "max_groups") != 0) && (LIST_NUM(h->HubDb->GroupList) >= GetHubAdminOption(h, "max_groups"))))
+ {
+ ret = ERR_TOO_MANY_GROUP;
+ }
+ else
+ {
+ AcAddGroup(h, g);
+ }
+
+ ReleaseGroup(g);
+
+ ALog(a, h, "LA_CREATE_GROUP", t->Name);
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Enumerate users
+UINT StEnumUser(ADMIN *a, RPC_ENUM_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i, num;
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ FreeRpcEnumUser(t);
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ Zero(t, sizeof(RPC_ENUM_USER));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ LockList(h->HubDb->UserList);
+ {
+ num = LIST_NUM(h->HubDb->UserList);
+
+ t->NumUser = num;
+ t->Users = ZeroMalloc(sizeof(RPC_ENUM_USER_ITEM) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ USER *u = LIST_DATA(h->HubDb->UserList, i);
+
+ Lock(u->lock);
+ {
+ RPC_ENUM_USER_ITEM *e = &t->Users[i];
+
+ StrCpy(e->Name, sizeof(e->Name), u->Name);
+ StrCpy(e->GroupName, sizeof(e->GroupName), u->GroupName);
+ UniStrCpy(e->Realname, sizeof(e->Realname), u->RealName);
+ UniStrCpy(e->Note, sizeof(e->Note), u->Note);
+ e->AuthType = u->AuthType;
+ e->LastLoginTime = u->LastLoginTime;
+ e->NumLogin = u->NumLogin;
+
+ if (u->Policy != NULL)
+ {
+ e->DenyAccess = u->Policy->Access ? false : true;
+ }
+
+ Copy(&e->Traffic, u->Traffic, sizeof(TRAFFIC));
+ e->IsTrafficFilled = true;
+
+ e->Expires = u->ExpireTime;
+ e->IsExpiresFilled = true;
+ }
+ Unlock(u->lock);
+ }
+ }
+ UnlockList(h->HubDb->UserList);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete a user
+UINT StDeleteUser(ADMIN *a, RPC_DELETE_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+
+
+ if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ ALog(a, h, "LA_DELETE_USER", t->Name);
+
+ AcLock(h);
+ {
+ if (AcDeleteUser(h, t->Name) == false)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Get user setting
+UINT StGetUser(ADMIN *a, RPC_SET_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ USER *u = NULL;
+ USERGROUP *g = NULL;
+ char name[MAX_USERNAME_LEN + 1];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ StrCpy(name, sizeof(name), t->Name);
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ FreeRpcSetUser(t);
+ Zero(t, sizeof(RPC_SET_USER));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ LockHubList(c);
+ {
+ h = GetHub(c, hubname);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ AcLock(h);
+ {
+ u = AcGetUser(h, name);
+ if (u == NULL)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ else
+ {
+ Lock(u->lock);
+ {
+ StrCpy(t->GroupName, sizeof(t->GroupName), u->GroupName);
+ UniStrCpy(t->Realname, sizeof(t->Realname), u->RealName);
+ UniStrCpy(t->Note, sizeof(t->Note), u->Note);
+ t->CreatedTime = u->CreatedTime;
+ t->UpdatedTime = u->UpdatedTime;
+ t->ExpireTime = u->ExpireTime;
+
+ t->AuthType = u->AuthType;
+ t->AuthData = CopyAuthData(u->AuthData, t->AuthType);
+ t->NumLogin = u->NumLogin;
+ Copy(&t->Traffic, u->Traffic, sizeof(TRAFFIC));
+ if (u->Policy != NULL)
+ {
+ t->Policy = ClonePolicy(u->Policy);
+ }
+ }
+ Unlock(u->lock);
+
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Set user setting
+UINT StSetUser(ADMIN *a, RPC_SET_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ USER *u = NULL;
+ USERGROUP *g = NULL;
+
+
+ if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (t->AuthType == AUTHTYPE_USERCERT || t->AuthType == AUTHTYPE_RADIUS || t->AuthType == AUTHTYPE_ROOTCERT || t->AuthType == AUTHTYPE_NT)
+ {
+ return ERR_NOT_SUPPORTED_AUTH_ON_OPENSOURCE;
+ }
+
+ if (StrCmpi(t->Name, "*") == 0)
+ {
+ if (t->AuthType != AUTHTYPE_RADIUS && t->AuthType != AUTHTYPE_NT)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ if (t->AuthType == AUTHTYPE_USERCERT)
+ {
+ AUTHUSERCERT *c = t->AuthData;
+ if (c != NULL && c->UserX != NULL &&
+ c->UserX->is_compatible_bit == false)
+ {
+ return ERR_NOT_RSA_1024;
+ }
+ if (c == NULL || c->UserX == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ AcLock(h);
+ {
+ u = AcGetUser(h, t->Name);
+ if (u == NULL)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ else
+ {
+ Lock(u->lock);
+ {
+ if (StrLen(t->GroupName) != 0)
+ {
+ g = AcGetGroup(h, t->GroupName);
+
+ if (g != NULL)
+ {
+ JoinUserToGroup(u, g);
+ ReleaseGroup(g);
+ }
+ else
+ {
+ ret = ERR_GROUP_NOT_FOUND;
+ }
+ }
+ else
+ {
+ JoinUserToGroup(u, NULL);
+ }
+
+ if (ret != ERR_GROUP_NOT_FOUND)
+ {
+ Free(u->RealName);
+ Free(u->Note);
+ u->RealName = UniCopyStr(t->Realname);
+ u->Note = UniCopyStr(t->Note);
+ SetUserAuthData(u, t->AuthType, CopyAuthData(t->AuthData, t->AuthType));
+ u->ExpireTime = t->ExpireTime;
+ u->UpdatedTime = SystemTime64();
+
+ SetUserPolicy(u, t->Policy);
+ }
+ }
+ Unlock(u->lock);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(h);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ ALog(a, h, "LA_SET_USER", t->Name);
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Create a user
+UINT StCreateUser(ADMIN *a, RPC_SET_USER *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+ UINT ret = ERR_NO_ERROR;
+ USER *u;
+ USERGROUP *g = NULL;
+
+
+ if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (t->AuthType == AUTHTYPE_USERCERT || t->AuthType == AUTHTYPE_RADIUS || t->AuthType == AUTHTYPE_ROOTCERT || t->AuthType == AUTHTYPE_NT)
+ {
+ return ERR_NOT_SUPPORTED_AUTH_ON_OPENSOURCE;
+ }
+
+ if (t->AuthType == AUTHTYPE_USERCERT)
+ {
+ AUTHUSERCERT *c = t->AuthData;
+ if (c != NULL && c->UserX != NULL &&
+ c->UserX->is_compatible_bit == false)
+ {
+ return ERR_NOT_RSA_1024;
+ }
+ if (c == NULL || c->UserX == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ if (IsUserName(t->Name) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (StrCmpi(t->Name, "*") == 0)
+ {
+ if (t->AuthType != AUTHTYPE_RADIUS && t->AuthType != AUTHTYPE_NT)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ u = NewUser(t->Name, t->Realname, t->Note, t->AuthType, CopyAuthData(t->AuthData, t->AuthType));
+ if (u == NULL)
+ {
+ ReleaseHub(h);
+ return ERR_INTERNAL_ERROR;
+ }
+
+ u->ExpireTime = t->ExpireTime;
+
+ SetUserPolicy(u, t->Policy);
+
+ AcLock(h);
+ {
+ if ((LIST_NUM(h->HubDb->UserList) >= GetServerCapsInt(a->Server, "i_max_users_per_hub")) ||
+ ((GetHubAdminOption(h, "max_users") != 0) && (LIST_NUM(h->HubDb->UserList) >= GetHubAdminOption(h, "max_users"))))
+ {
+ ret = ERR_TOO_MANY_USER;
+ }
+ else if (SiTooManyUserObjectsInServer(s, false))
+ {
+ ret = ERR_TOO_MANY_USERS_CREATED;
+ ALog(a, h, "ERR_128");
+ }
+ else if (AcIsUser(h, t->Name))
+ {
+ ret = ERR_USER_ALREADY_EXISTS;
+ }
+ else
+ {
+ if (StrLen(t->GroupName) != 0)
+ {
+ g = AcGetGroup(h, t->GroupName);
+ if (g == NULL)
+ {
+ ret = ERR_GROUP_NOT_FOUND;
+ }
+ }
+
+ if (ret != ERR_GROUP_NOT_FOUND)
+ {
+ if (g != NULL)
+ {
+ JoinUserToGroup(u, g);
+ ReleaseGroup(g);
+ }
+
+ AcAddUser(h, u);
+ ALog(a, h, "LA_CREATE_USER", t->Name);
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ }
+ AcUnlock(h);
+
+ ReleaseUser(u);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Get access list
+UINT StEnumAccess(ADMIN *a, RPC_ENUM_ACCESS_LIST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT i;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcEnumAccessList(t);
+ Zero(t, sizeof(RPC_ENUM_ACCESS_LIST));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ LockList(h->AccessList);
+ {
+ t->NumAccess = LIST_NUM(h->AccessList);
+ t->Accesses = ZeroMalloc(sizeof(ACCESS) * t->NumAccess);
+
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *a = &t->Accesses[i];
+ Copy(a, LIST_DATA(h->AccessList, i), sizeof(ACCESS));
+ a->UniqueId = HashPtrToUINT(LIST_DATA(h->AccessList, i));
+ }
+ }
+ UnlockList(h->AccessList);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete access list entry
+UINT StDeleteAccess(ADMIN *a, RPC_DELETE_ACCESS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT i;
+ bool exists;
+
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ exists = false;
+
+ LockList(h->AccessList);
+ {
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+
+ if ((t->Id < MAX_ACCESSLISTS && access->Id == t->Id) ||
+ (t->Id >= MAX_ACCESSLISTS && HashPtrToUINT(access) == t->Id))
+ {
+ Free(access);
+ Delete(h->AccessList, access);
+ exists = true;
+
+ break;
+ }
+ }
+ }
+ UnlockList(h->AccessList);
+
+ if (exists == false)
+ {
+ ReleaseHub(h);
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, h, "LA_DELETE_ACCESS");
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Set access list
+UINT StSetAccessList(ADMIN *a, RPC_ENUM_ACCESS_LIST *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT i;
+ bool no_jitter = false;
+ bool no_include = false;
+ UINT ret = ERR_NO_ERROR;
+
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (t->NumAccess > GetServerCapsInt(a->Server, "i_max_access_lists"))
+ {
+ return ERR_TOO_MANY_ACCESS_LIST;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ no_jitter = GetHubAdminOption(h, "no_delay_jitter_packet_loss");
+ no_include = GetHubAdminOption(h, "no_access_list_include_file");
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "max_accesslists") != 0 &&
+ t->NumAccess > GetHubAdminOption(h, "max_accesslists"))
+ {
+ ReleaseHub(h);
+ return ERR_TOO_MANY_ACCESS_LIST;
+ }
+
+ LockList(h->AccessList);
+ {
+ UINT i;
+
+ // Confirm whether the access list of form which cannot handle by the old client already exists
+ if (a->ClientBuild < 6560)
+ {
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+ if (access->IsIPv6 ||
+ access->Jitter != 0 || access->Loss != 0 || access->Delay != 0)
+ {
+ ret = ERR_VERSION_INVALID;
+ break;
+ }
+ }
+ }
+
+ if (a->ClientBuild < 8234)
+ {
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+
+ if (IsEmptyStr(access->RedirectUrl) == false)
+ {
+ ret = ERR_VERSION_INVALID;
+ break;
+ }
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Delete whole access list
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+ Free(access);
+ }
+
+ DeleteAll(h->AccessList);
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ ALog(a, h, "LA_SET_ACCESS_LIST", t->NumAccess);
+
+ // Add whole access list
+ for (i = 0;i < t->NumAccess;i++)
+ {
+ ACCESS *a = &t->Accesses[i];
+
+ if (no_jitter)
+ {
+ a->Jitter = a->Loss = a->Delay = 0;
+ }
+
+ if (no_include)
+ {
+ if (StartWith(a->SrcUsername, ACCESS_LIST_INCLUDED_PREFIX) ||
+ StartWith(a->SrcUsername, ACCESS_LIST_EXCLUDED_PREFIX))
+ {
+ ClearStr(a->SrcUsername, sizeof(a->SrcUsername));
+ }
+
+ if (StartWith(a->DestUsername, ACCESS_LIST_INCLUDED_PREFIX) ||
+ StartWith(a->DestUsername, ACCESS_LIST_EXCLUDED_PREFIX))
+ {
+ ClearStr(a->DestUsername, sizeof(a->DestUsername));
+ }
+ }
+
+ if (i == (t->NumAccess - 1))
+ {
+ Sort(h->AccessList);
+ }
+
+ AddAccessListEx(h, a, ((i != (t->NumAccess - 1)) ? true : false), ((i != (t->NumAccess - 1)) ? true : false));
+ }
+
+ UnlockList(h->AccessList);
+
+ IncrementServerConfigRevision(s);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+ }
+ else
+ {
+ UnlockList(h->AccessList);
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Add access list entry
+UINT StAddAccess(ADMIN *a, RPC_ADD_ACCESS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ bool no_jitter = false;
+ bool no_include = false;
+
+
+ NO_SUPPORT_FOR_BRIDGE;
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ no_jitter = GetHubAdminOption(h, "no_delay_jitter_packet_loss");
+ no_include = GetHubAdminOption(h, "no_access_list_include_file");
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ if ((LIST_NUM(h->AccessList) >= GetServerCapsInt(a->Server, "i_max_access_lists") ||
+ (GetHubAdminOption(h, "max_accesslists") != 0) && (LIST_NUM(h->AccessList) >= GetHubAdminOption(h, "max_accesslists"))))
+ {
+ ReleaseHub(h);
+ return ERR_TOO_MANY_ACCESS_LIST;
+ }
+
+ ALog(a, h, "LA_ADD_ACCESS");
+
+ if (no_jitter)
+ {
+ t->Access.Jitter = t->Access.Delay = t->Access.Loss = 0;
+ }
+
+ if (no_include)
+ {
+ if (no_include)
+ {
+ if (StartWith(t->Access.SrcUsername, ACCESS_LIST_INCLUDED_PREFIX) ||
+ StartWith(t->Access.SrcUsername, ACCESS_LIST_EXCLUDED_PREFIX))
+ {
+ ClearStr(t->Access.SrcUsername, sizeof(t->Access.SrcUsername));
+ }
+
+ if (StartWith(t->Access.DestUsername, ACCESS_LIST_INCLUDED_PREFIX) ||
+ StartWith(t->Access.DestUsername, ACCESS_LIST_EXCLUDED_PREFIX))
+ {
+ ClearStr(t->Access.DestUsername, sizeof(t->Access.DestUsername));
+ }
+ }
+ }
+
+ AddAccessList(h, &t->Access);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Rename link (cascade connection)
+UINT StRenameLink(ADMIN *a, RPC_RENAME_LINK *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ LINK *k;
+ bool exists = false;
+
+ if (UniIsEmptyStr(t->OldAccountName) || UniIsEmptyStr(t->NewAccountName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (UniStrCmpi(t->NewAccountName, t->OldAccountName) == 0)
+ {
+ // Noop if new name is same to old name
+ return ERR_NO_ERROR;
+ }
+
+ h = GetHub(c, t->HubName);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ k = NULL;
+
+ // Find specified link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, t->OldAccountName) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+
+ exists = false;
+
+ if (k != NULL)
+ {
+ // Check whether the new link name is same to other links
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, t->NewAccountName) == 0)
+ {
+ // duplicated
+ exists = true;
+ }
+ }
+ Unlock(kk->lock);
+ }
+
+ if (exists)
+ {
+ // Already same name exists
+ ret = ERR_LINK_ALREADY_EXISTS;
+ }
+ else
+ {
+ // Do rename
+ UniStrCpy(k->Option->AccountName, sizeof(k->Option->AccountName), t->NewAccountName);
+
+ ALog(a, h, "LA_RENAME_LINK", t->OldAccountName, t->NewAccountName);
+
+ IncrementServerConfigRevision(s);
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // specified link is not found
+ ReleaseHub(h);
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ReleaseLink(k);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Delete a link
+UINT StDeleteLink(ADMIN *a, RPC_LINK *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];
+ LINK *k;
+
+ if (UniIsEmptyStr(t->AccountName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ UniStrCpy(accountname, sizeof(accountname), t->AccountName);
+ k = NULL;
+
+ // Find specified link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // Specified link is not found
+ ReleaseHub(h);
+
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, h, "LA_DELETE_LINK", t->AccountName);
+
+ SetLinkOffline(k);
+
+ IncrementServerConfigRevision(s);
+
+ DelLink(h, k);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Make a link into off-line
+UINT StSetLinkOffline(ADMIN *a, RPC_LINK *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];
+ LINK *k;
+
+
+ if (UniIsEmptyStr(t->AccountName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ UniStrCpy(accountname, sizeof(accountname), t->AccountName);
+ k = NULL;
+
+ // Find specified link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // Link is not found
+ ReleaseHub(h);
+
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, h, "LA_SET_LINK_OFFLINE", t->AccountName);
+
+ SetLinkOffline(k);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Make a link into on-line
+UINT StSetLinkOnline(ADMIN *a, RPC_LINK *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];
+ LINK *k;
+
+
+ if (UniIsEmptyStr(t->AccountName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ UniStrCpy(accountname, sizeof(accountname), t->AccountName);
+ k = NULL;
+
+ // Find specified link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // Specified link is not found
+ ReleaseHub(h);
+
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, h, "LA_SET_LINK_ONLINE", t->AccountName);
+
+ SetLinkOnline(k);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ret;
+}
+
+// Get link status
+UINT StGetLinkStatus(ADMIN *a, RPC_LINK_STATUS *t)
+{
+ UINT i;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];
+ LINK *k;
+ SESSION *sess;
+
+ if (UniIsEmptyStr(t->AccountName))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ UniStrCpy(accountname, sizeof(accountname), t->AccountName);
+ FreeRpcLinkStatus(t);
+ Zero(t, sizeof(RPC_LINK_STATUS));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ UniStrCpy(t->AccountName, sizeof(t->AccountName), accountname);
+
+ k = NULL;
+
+ // Find the link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // Specified link is not found
+ ReleaseHub(h);
+
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ // Get status infomation from session
+ Lock(k->lock);
+ {
+ sess = k->ClientSession;
+ if (sess != NULL)
+ {
+ AddRef(sess->ref);
+ }
+ }
+ Unlock(k->lock);
+
+ if (sess != NULL && k->Offline == false)
+ {
+ CiGetSessionStatus(&t->Status, sess);
+ }
+ else
+ {
+ ret = ERR_LINK_IS_OFFLINE;
+ }
+ ReleaseSession(sess);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Enumerate links
+UINT StEnumLink(ADMIN *a, RPC_ENUM_LINK *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcEnumLink(t);
+ Zero(t, sizeof(RPC_ENUM_LINK));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ LockList(h->LinkList);
+ {
+ t->NumLink = LIST_NUM(h->LinkList);
+ t->Links = ZeroMalloc(sizeof(RPC_ENUM_LINK_ITEM) * t->NumLink);
+
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *k = LIST_DATA(h->LinkList, i);
+ RPC_ENUM_LINK_ITEM *e = &t->Links[i];
+
+ Lock(k->lock);
+ {
+ UniStrCpy(e->AccountName, sizeof(e->AccountName), k->Option->AccountName);
+ StrCpy(e->Hostname, sizeof(e->Hostname), k->Option->Hostname);
+ StrCpy(e->HubName, sizeof(e->HubName), k->Option->HubName);
+ e->Online = k->Offline ? false : true;
+
+ if (e->Online)
+ {
+ if (k->ClientSession != NULL)
+ {
+ e->ConnectedTime = TickToTime(k->ClientSession->CurrentConnectionEstablishTime);
+ e->Connected = (k->ClientSession->ClientStatus == CLIENT_STATUS_ESTABLISHED);
+ e->LastError = k->ClientSession->Err;
+ }
+ }
+ }
+ Unlock(k->lock);
+ }
+ }
+ UnlockList(h->LinkList);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get link configuration
+UINT StGetLink(ADMIN *a, RPC_CREATE_LINK *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ UINT i;
+ char hubname[MAX_SIZE];
+ LINK *k;
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_LINK_CANT_CREATE_ON_FARM;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ k = NULL;
+
+ // Find the link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // The link is not found
+ ReleaseHub(h);
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ FreeRpcCreateLink(t);
+ Zero(t, sizeof(t));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ Lock(k->lock);
+ {
+ // Get configuration
+ t->Online = k->Offline ? false : true;
+ t->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(t->ClientOption, k->Option, sizeof(CLIENT_OPTION));
+ t->ClientAuth = CopyClientAuth(k->Auth);
+ Copy(&t->Policy, k->Policy, sizeof(POLICY));
+
+ t->CheckServerCert = k->CheckServerCert;
+ t->ServerCert = CloneX(k->ServerCert);
+ }
+ Unlock(k->lock);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Set link configuration
+UINT StSetLink(ADMIN *a, RPC_CREATE_LINK *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ UINT i;
+ LINK *k;
+
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_LINK_CANT_CREATE_ON_FARM;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ k = NULL;
+
+ // Find the link
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k == NULL)
+ {
+ // The link is not found
+ ReleaseHub(h);
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ ALog(a, h, "LA_SET_LINK", t->ClientOption->AccountName);
+
+ Lock(k->lock);
+ {
+ // Update the configuration of the link
+ if (k->ServerCert != NULL)
+ {
+ FreeX(k->ServerCert);
+ k->ServerCert = NULL;
+ }
+
+ Copy(k->Option, t->ClientOption, sizeof(CLIENT_OPTION));
+ StrCpy(k->Option->DeviceName, sizeof(k->Option->DeviceName), LINK_DEVICE_NAME);
+ k->Option->NumRetry = INFINITE;
+ k->Option->RetryInterval = 10;
+ k->Option->NoRoutingTracking = true;
+ CiFreeClientAuth(k->Auth);
+ k->Auth = CopyClientAuth(t->ClientAuth);
+
+ if (t->Policy.Ver3 == false)
+ {
+ Copy(k->Policy, &t->Policy, sizeof(UINT) * NUM_POLICY_ITEM_FOR_VER2);
+ }
+ else
+ {
+ Copy(k->Policy, &t->Policy, sizeof(POLICY));
+ }
+
+ k->Option->RequireBridgeRoutingMode = true; // Enable Bridge / Routing mode
+ k->Option->RequireMonitorMode = false; // Disable monitor mode
+
+ k->CheckServerCert = t->CheckServerCert;
+ k->ServerCert = CloneX(t->ServerCert);
+ }
+ Unlock(k->lock);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseLink(k);
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Create a new link(cascade)
+UINT StCreateLink(ADMIN *a, RPC_CREATE_LINK *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ UINT i;
+ LINK *k;
+
+ CHECK_RIGHT;
+
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ return ERR_LINK_CANT_CREATE_ON_FARM;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ k = NULL;
+
+ // Check for existing a link which has same name
+ LockList(h->LinkList);
+ {
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *kk = LIST_DATA(h->LinkList, i);
+ Lock(kk->lock);
+ {
+ if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)
+ {
+ k = kk;
+ AddRef(kk->ref);
+ }
+ }
+ Unlock(kk->lock);
+
+ if (k != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+
+ if (k != NULL)
+ {
+ // There is a link which has same name
+ ReleaseLink(k);
+ ReleaseHub(h);
+ return ERR_LINK_ALREADY_EXISTS;
+ }
+
+ ALog(a, h, "LA_CREATE_LINK", t->ClientOption->AccountName);
+
+ // Create a new link
+ k = NewLink(c, h, t->ClientOption, t->ClientAuth, &t->Policy);
+
+ if (k == NULL)
+ {
+ // Link creation failed
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ // setting of verifying server certification
+ //
+ k->CheckServerCert = t->CheckServerCert;
+ k->ServerCert = CloneX(t->ServerCert);
+
+ // stay this off-line
+ k->Offline = false;
+ SetLinkOffline(k);
+ ReleaseLink(k);
+
+ IncrementServerConfigRevision(s);
+ }
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Delete a CA(Certificate Authority) setting from the hub
+UINT StDeleteCa(ADMIN *a, RPC_HUB_DELETE_CA *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_cert_list") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ LockList(h->HubDb->RootCertList);
+ {
+ if (IsInListKey(h->HubDb->RootCertList, t->Key))
+ {
+ X *x = ListKeyToPointer(h->HubDb->RootCertList, t->Key);
+ Delete(h->HubDb->RootCertList, x);
+ FreeX(x);
+
+ ALog(a, h, "LA_DELETE_CA");
+
+ IncrementServerConfigRevision(s);
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(h->HubDb->RootCertList);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Get CA(Certificate Authority) setting from the hub
+UINT StGetCa(ADMIN *a, RPC_HUB_GET_CA *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT key;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+ key = t->Key;
+
+ FreeRpcHubGetCa(t);
+ Zero(t, sizeof(RPC_HUB_GET_CA));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ LockList(h->HubDb->RootCertList);
+ {
+ if (IsInListKey(h->HubDb->RootCertList, key))
+ {
+ X *x = ListKeyToPointer(h->HubDb->RootCertList, key);
+
+ t->Cert = CloneX(x);
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(h->HubDb->RootCertList);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Enumerate CA(Certificate Authority) in the hub
+UINT StEnumCa(ADMIN *a, RPC_HUB_ENUM_CA *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ FreeRpcHubEnumCa(t);
+ Zero(t, sizeof(RPC_HUB_ENUM_CA));
+
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, hubname);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ Zero(t, sizeof(RPC_HUB_ENUM_CA));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+
+ if (h->HubDb->RootCertList != NULL)
+ {
+ LockList(h->HubDb->RootCertList);
+ {
+ t->NumCa = LIST_NUM(h->HubDb->RootCertList);
+ t->Ca = ZeroMalloc(sizeof(RPC_HUB_ENUM_CA_ITEM) * t->NumCa);
+
+ for (i = 0;i < t->NumCa;i++)
+ {
+ RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];
+ X *x = LIST_DATA(h->HubDb->RootCertList, i);
+
+ e->Key = POINTER_TO_KEY(x);
+ GetAllNameFromNameEx(e->SubjectName, sizeof(e->SubjectName), x->subject_name);
+ GetAllNameFromNameEx(e->IssuerName, sizeof(e->IssuerName), x->issuer_name);
+ e->Expires = x->notAfter;
+ }
+ }
+ UnlockList(h->HubDb->RootCertList);
+ }
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Add CA(Certificate Authority) into the hub
+UINT StAddCa(ADMIN *a, RPC_HUB_ADD_CA *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (c->Bridge)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ if (t->Cert == NULL)
+ {
+ ERR_INVALID_PARAMETER;
+ }
+
+ if (t->Cert->is_compatible_bit == false)
+ {
+ return ERR_NOT_RSA_1024;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_cert_list") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ IncrementServerConfigRevision(s);
+
+ ALog(a, h, "LA_ADD_CA");
+
+ AddRootCert(h, t->Cert);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get logging configuration of the hub
+UINT StGetHubLog(ADMIN *a, RPC_HUB_LOG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ GetHubLogSetting(h, &t->LogSetting);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Set logging configuration into the hub
+UINT StSetHubLog(ADMIN *a, RPC_HUB_LOG *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_log_config") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ ALog(a, h, "LA_SET_HUB_LOG");
+
+ SetHubLogSettingEx(h, &t->LogSetting,
+ (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_log_switch_type") != 0));
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get hub status
+UINT StGetHubStatus(ADMIN *a, RPC_HUB_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ Zero(t, sizeof(RPC_HUB_STATUS));
+
+ Lock(h->lock);
+ {
+ StrCpy(t->HubName, sizeof(t->HubName), h->Name);
+ t->HubType = h->Type;
+ t->Online = h->Offline ? false : true;
+ t->NumSessions = LIST_NUM(h->SessionList);
+ t->NumSessionsClient = Count(h->NumSessionsClient);
+ t->NumSessionsBridge = Count(h->NumSessionsBridge);
+ t->NumAccessLists = LIST_NUM(h->AccessList);
+
+ if (h->HubDb != NULL)
+ {
+ t->NumUsers = LIST_NUM(h->HubDb->UserList);
+ t->NumGroups = LIST_NUM(h->HubDb->GroupList);
+ }
+
+ t->NumMacTables = LIST_NUM(h->MacTable);
+ t->NumIpTables = LIST_NUM(h->IpTable);
+
+ Lock(h->TrafficLock);
+ {
+ Copy(&t->Traffic, h->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(h->TrafficLock);
+
+ t->NumLogin = h->NumLogin;
+ t->LastCommTime = h->LastCommTime;
+ t->LastLoginTime = h->LastLoginTime;
+ t->CreatedTime = h->CreatedTime;
+ }
+ Unlock(h->lock);
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i;
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ UINT k;
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (f->Me == false)
+ {
+ LockList(f->HubList);
+ {
+ for (k = 0;k < LIST_NUM(f->HubList);k++)
+ {
+ HUB_LIST *h = LIST_DATA(f->HubList, k);
+
+ if (StrCmpi(h->Name, t->HubName) == 0)
+ {
+ t->NumSessions += h->NumSessions;
+ t->NumSessionsClient += h->NumSessionsClient;
+ t->NumSessionsBridge += h->NumSessionsBridge;
+ t->NumMacTables += h->NumMacTables;
+ t->NumIpTables += h->NumIpTables;
+ }
+ }
+ }
+ UnlockList(f->HubList);
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+
+ if (h->Type != HUB_TYPE_FARM_STATIC)
+ {
+ t->SecureNATEnabled = h->EnableSecureNAT;
+ }
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Enable SecureNAT function of the hub
+UINT StEnableSecureNAT(ADMIN *a, RPC_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ ALog(a, h, "LA_ENABLE_SNAT");
+
+ EnableSecureNAT(h, true);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Disable the SecureNAT function of the hub
+UINT StDisableSecureNAT(ADMIN *a, RPC_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ CHECK_RIGHT;
+
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ ALog(a, h, "LA_DISABLE_SNAT");
+
+ EnableSecureNAT(h, false);
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate NAT entries of the SecureNAT
+UINT StEnumNAT(ADMIN *a, RPC_ENUM_NAT *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ CHECK_RIGHT;
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT == NULL)
+ {
+ ret = ERR_SNAT_NOT_RUNNING;
+ }
+ else
+ {
+ NtEnumNatList(h->SecureNAT->Nat, t);
+ }
+ }
+ Unlock(h->lock_online);
+
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ if (ret == ERR_SNAT_NOT_RUNNING)
+ {
+ // Get status of remote SecureNAT
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_ENUM_NAT tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallEnumNat(s, f, hubname, &tmp);
+
+ if (tmp.NumItem >= 1)
+ {
+ FreeRpcEnumNat(t);
+ Copy(t, &tmp, sizeof(RPC_ENUM_NAT));
+ ret = ERR_NO_ERROR;
+ break;
+ }
+ else
+ {
+ FreeRpcEnumNat(&tmp);
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+
+ ReleaseHub(h);
+
+ ret = ERR_NO_ERROR;
+
+ return ret;
+}
+
+// Get status of the SecureNAT
+UINT StGetSecureNATStatus(ADMIN *a, RPC_NAT_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+
+ CHECK_RIGHT;
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT == NULL)
+ {
+ ret = ERR_SNAT_NOT_RUNNING;
+ }
+ else
+ {
+ NtGetStatus(h->SecureNAT->Nat, t);
+ }
+ }
+ Unlock(h->lock_online);
+
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ if (ret == ERR_SNAT_NOT_RUNNING)
+ {
+ // Get status of remote secureNAT
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_NAT_STATUS tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallGetNatStatus(s, f, hubname, &tmp);
+
+ if (tmp.NumDhcpClients == 0 && tmp.NumTcpSessions == 0 && tmp.NumUdpSessions == 0)
+ {
+ }
+ else
+ {
+ Copy(t, &tmp, sizeof(RPC_NAT_STATUS));
+ ret = ERR_NO_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+
+ ReleaseHub(h);
+
+ ret = ERR_NO_ERROR;
+
+ return ret;
+}
+
+// Enumerate DHCP entries
+UINT StEnumDHCP(ADMIN *a, RPC_ENUM_DHCP *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT == NULL)
+ {
+ ret = ERR_SNAT_NOT_RUNNING;
+ }
+ else
+ {
+ NtEnumDhcpList(h->SecureNAT->Nat, t);
+ }
+ }
+ Unlock(h->lock_online);
+
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ if (ret == ERR_SNAT_NOT_RUNNING)
+ {
+ // Get status of remote DHCP service
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me == false)
+ {
+ RPC_ENUM_DHCP tmp;
+
+ Zero(&tmp, sizeof(tmp));
+
+ SiCallEnumDhcp(s, f, hubname, &tmp);
+
+ if (tmp.NumItem >= 1)
+ {
+ FreeRpcEnumDhcp(t);
+ Copy(t, &tmp, sizeof(RPC_ENUM_DHCP));
+ ret = ERR_NO_ERROR;
+ break;
+ }
+ else
+ {
+ FreeRpcEnumDhcp(&tmp);
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+ }
+
+ ReleaseHub(h);
+
+ ret = ERR_NO_ERROR;
+
+ return ret;
+}
+
+// Set SecureNAT options
+UINT StSetSecureNATOption(ADMIN *a, VH_OPTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+
+ if (IsZero(t->MacAddress, sizeof(t->MacAddress)) ||
+ IsHostIPAddress4(&t->Ip) == false ||
+ IsSubnetMask4(&t->Mask) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ if ((IPToUINT(&t->Ip) & (~(IPToUINT(&t->Mask)))) == 0)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ if (h->SecureNATOption->UseNat == false && t->UseNat)
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat_enablenat") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+ }
+
+ if (h->SecureNATOption->UseDhcp == false && t->UseDhcp)
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat_enabledhcp") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+ }
+
+ Copy(h->SecureNATOption, t, sizeof(VH_OPTION));
+
+ if (h->Type != HUB_TYPE_STANDALONE && h->Cedar != NULL && h->Cedar->Server != NULL &&
+ h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption, false);
+ }
+
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT != NULL)
+ {
+ SetVirtualHostOption(h->SecureNAT->Nat->Virtual, t);
+ }
+ }
+ Unlock(h->lock_online);
+
+ ALog(a, h, "LA_SET_SNAT_OPTION");
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get SecureNAT options
+UINT StGetSecureNATOption(ADMIN *a, VH_OPTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ char hubname[MAX_HUBNAME_LEN + 1];
+
+ StrCpy(hubname, sizeof(hubname), t->HubName);
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ Zero(t, sizeof(VH_OPTION));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
+ Copy(t, h->SecureNATOption, sizeof(VH_OPTION));
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Make a hub on-line or off-line
+UINT StSetHubOnline(ADMIN *a, RPC_SET_HUB_ONLINE *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (a->ServerAdmin == false && t->Online && GetHubAdminOption(h, "no_online") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ if (a->ServerAdmin == false && t->Online == false && GetHubAdminOption(h, "no_offline") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ if (t->Online)
+ {
+ ALog(a, h, "LA_SET_HUB_ONLINE");
+ SetHubOnline(h);
+ }
+ else
+ {
+ ALog(a, h, "LA_SET_HUB_OFFLINE");
+ SetHubOffline(h);
+ }
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ IncrementServerConfigRevision(s);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Get connection information
+UINT StGetConnectionInfo(ADMIN *a, RPC_CONNECTION_INFO *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ CONNECTION *connection;
+ char name[MAX_CONNECTION_NAME_LEN + 1];
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ LockList(c->ConnectionList);
+ {
+ CONNECTION tt;
+ Zero(&tt, sizeof(tt));
+ tt.Name = t->Name;
+ StrCpy(name, sizeof(name), t->Name);
+
+ connection = Search(c->ConnectionList, &tt);
+
+ if (connection != NULL)
+ {
+ AddRef(connection->ref);
+ }
+ }
+ UnlockList(c->ConnectionList);
+
+ if (connection == NULL)
+ {
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ Zero(t, sizeof(RPC_CONNECTION_INFO));
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ Lock(connection->lock);
+ {
+ SOCK *s = connection->FirstSock;
+
+ if (s != NULL)
+ {
+ t->Ip = IPToUINT(&s->RemoteIP);
+ t->Port = s->RemotePort;
+ StrCpy(t->Hostname, sizeof(t->Hostname), s->RemoteHostname);
+ }
+
+ StrCpy(t->Name, sizeof(t->Name), connection->Name);
+ t->ConnectedTime = TickToTime(connection->ConnectedTick);
+ t->Type = connection->Type;
+
+ StrCpy(t->ServerStr, sizeof(t->ServerStr), connection->ServerStr);
+ StrCpy(t->ClientStr, sizeof(t->ClientStr), connection->ClientStr);
+ t->ServerVer = connection->ServerVer;
+ t->ServerBuild = connection->ServerBuild;
+ t->ClientVer = connection->ClientVer;
+ t->ClientBuild = connection->ClientBuild;
+ }
+ Unlock(connection->lock);
+
+ ReleaseConnection(connection);
+
+ return ERR_NO_ERROR;
+}
+
+// Disconnect a connection
+UINT StDisconnectConnection(ADMIN *a, RPC_DISCONNECT_CONNECTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ CONNECTION *connection;
+
+ if (IsEmptyStr(t->Name))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ LockList(c->ConnectionList);
+ {
+ CONNECTION tt;
+ Zero(&tt, sizeof(tt));
+ tt.Name = t->Name;
+
+ connection = Search(c->ConnectionList, &tt);
+ if (connection != NULL)
+ {
+ AddRef(connection->ref);
+ }
+ }
+ UnlockList(c->ConnectionList);
+
+ if (connection == NULL)
+ {
+ return ERR_OBJECT_NOT_FOUND;
+ }
+
+ StopConnection(connection, true);
+
+ ReleaseConnection(connection);
+
+ ALog(a, NULL, "LA_DISCONNECT_CONN", t->Name);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate connections
+UINT StEnumConnection(ADMIN *a, RPC_ENUM_CONNECTION *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+
+ SERVER_ADMIN_ONLY;
+
+ FreeRpcEnumConnetion(t);
+ Zero(t, sizeof(RPC_ENUM_CONNECTION));
+
+ LockList(c->ConnectionList);
+ {
+ UINT i;
+ t->NumConnection = LIST_NUM(c->ConnectionList);
+ t->Connections = ZeroMalloc(sizeof(RPC_ENUM_CONNECTION_ITEM) * t->NumConnection);
+
+ for (i = 0;i < t->NumConnection;i++)
+ {
+ RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];
+ CONNECTION *connection = LIST_DATA(c->ConnectionList, i);
+
+ Lock(connection->lock);
+ {
+ SOCK *s = connection->FirstSock;
+
+ if (s != NULL)
+ {
+ e->Ip = IPToUINT(&s->RemoteIP);
+ e->Port = s->RemotePort;
+ StrCpy(e->Hostname, sizeof(e->Hostname), s->RemoteHostname);
+ }
+
+ StrCpy(e->Name, sizeof(e->Name), connection->Name);
+ e->ConnectedTime = TickToTime(connection->ConnectedTick);
+ e->Type = connection->Type;
+ }
+ Unlock(connection->lock);
+ }
+ }
+ UnlockList(c->ConnectionList);
+
+ return ERR_NO_ERROR;
+}
+
+// Set Radius options of the hub
+UINT StSetHubRadius(ADMIN *a, RPC_RADIUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ //SetRadiusServer(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret);
+ SetRadiusServerEx(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret, t->RadiusRetryInterval);
+
+ ALog(a, h, "LA_SET_HUB_RADIUS");
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get Radius options of the hub
+UINT StGetHubRadius(ADMIN *a, RPC_RADIUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+
+ CHECK_RIGHT;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ Zero(t, sizeof(t));
+ //GetRadiusServer(h, t->RadiusServerName, sizeof(t->RadiusServerName),
+ // &t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret));
+ GetRadiusServerEx(h, t->RadiusServerName, sizeof(t->RadiusServerName),
+ &t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret), &t->RadiusRetryInterval);
+
+ ReleaseHub(h);
+
+ return ERR_NO_ERROR;
+}
+
+// Delete a hub
+UINT StDeleteHub(ADMIN *a, RPC_DELETE_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+
+ if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ SERVER_ADMIN_ONLY;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ StopHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ DelHub(c, h);
+ ReleaseHub(h);
+
+ ALog(a, NULL, "LA_DELETE_HUB", t->HubName);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate hubs
+UINT StEnumHub(ADMIN *a, RPC_ENUM_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h = NULL;
+
+ FreeRpcEnumHub(t);
+
+ Zero(t, sizeof(RPC_ENUM_HUB));
+
+ LockHubList(c);
+ {
+ UINT i, num, j;
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+
+ Lock(h->lock);
+
+ if (a->ServerAdmin == false &&
+ h->Option != NULL &&
+ StrCmpi(h->Name, a->HubName) != 0)
+ {
+ // This hub is not listed
+ }
+ else
+ {
+ // This hub is listed
+ num++;
+ }
+ }
+
+ t->NumHub = num;
+
+ t->Hubs = ZeroMalloc(sizeof(RPC_ENUM_HUB_ITEM) * num);
+
+ i = 0;
+ for (j = 0;j < LIST_NUM(c->HubList);j++)
+ {
+ HUB *h = LIST_DATA(c->HubList, j);
+
+ if (a->ServerAdmin == false &&
+ h->Option != NULL &&
+ StrCmpi(h->Name, a->HubName) != 0)
+ {
+ // This hub is not listed
+ }
+ else
+ {
+ // This hub is listed
+ RPC_ENUM_HUB_ITEM *e = &t->Hubs[i++];
+
+ StrCpy(e->HubName, sizeof(e->HubName), h->Name);
+ e->Online = h->Offline ? false : true;
+ e->HubType = h->Type;
+
+ e->NumSessions = LIST_NUM(h->SessionList);
+
+ LockList(h->MacTable);
+ {
+ e->NumMacTables = LIST_NUM(h->MacTable);
+ }
+ UnlockList(h->MacTable);
+
+ LockList(h->IpTable);
+ {
+ e->NumIpTables = LIST_NUM(h->IpTable);
+ }
+ UnlockList(h->IpTable);
+
+ if (h->HubDb != NULL)
+ {
+ LockList(h->HubDb->UserList);
+ {
+ e->NumUsers = LIST_NUM(h->HubDb->UserList);
+ }
+ UnlockList(h->HubDb->UserList);
+
+ LockList(h->HubDb->GroupList);
+ {
+ e->NumGroups = LIST_NUM(h->HubDb->GroupList);
+ }
+ UnlockList(h->HubDb->GroupList);
+ }
+
+ e->LastCommTime = h->LastCommTime;
+ e->LastLoginTime = h->LastLoginTime;
+ e->NumLogin = h->NumLogin;
+ e->CreatedTime = h->CreatedTime;
+
+ Lock(h->TrafficLock);
+ {
+ Copy(&e->Traffic, h->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(h->TrafficLock);
+
+ e->IsTrafficFilled = true;
+ }
+
+ Unlock(h->lock);
+ }
+ }
+ UnlockHubList(c);
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UINT i, j, k;
+ LockList(s->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ LockList(f->HubList);
+ {
+ if (f->Me == false)
+ {
+ for (j = 0;j < LIST_NUM(f->HubList);j++)
+ {
+ HUB_LIST *o = LIST_DATA(f->HubList, j);
+
+ for (k = 0;k < t->NumHub;k++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t->Hubs[k];
+
+ if (StrCmpi(e->HubName, o->Name) == 0)
+ {
+ e->NumIpTables += o->NumIpTables;
+ e->NumMacTables += o->NumMacTables;
+ e->NumSessions += o->NumSessions;
+ }
+ }
+ }
+ }
+ }
+ UnlockList(f->HubList);
+ }
+ }
+ UnlockList(s->FarmMemberList);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Get hub configuration
+UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT ret = ERR_NO_ERROR;
+ HUB *h;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+ CHECK_RIGHT;
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ Zero(t, sizeof(RPC_CREATE_HUB));
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ Lock(h->lock);
+ {
+ StrCpy(t->HubName, sizeof(t->HubName), h->Name);
+ t->Online = h->Offline ? false : true;
+ t->HubOption.MaxSession = h->Option->MaxSession;
+ t->HubOption.NoEnum = h->Option->NoEnum;
+ t->HubType = h->Type;
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Set hub configuration
+UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ UINT ret = ERR_NO_ERROR;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+
+ CHECK_RIGHT;
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ if (t->HubType != HUB_TYPE_STANDALONE)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (t->HubType == HUB_TYPE_STANDALONE)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ LockHubList(c);
+ {
+ h = GetHub(c, t->HubName);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ if (h->Type != t->HubType)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_SUPPORTED;
+ }
+
+ if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&
+ IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)
+ {
+ if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_admin_password") != 0)
+ {
+ ReleaseHub(h);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+ }
+
+ // Is the password to be set blank
+ {
+ UCHAR hash1[SHA1_SIZE], hash2[SHA1_SIZE];
+ HashPassword(hash1, ADMINISTRATOR_USERNAME, "");
+ Hash(hash2, "", 0, true);
+
+ if (Cmp(t->HashedPassword, hash2, SHA1_SIZE) == 0 || Cmp(t->SecurePassword, hash1, SHA1_SIZE) == 0)
+ {
+ if (a->ServerAdmin == false && a->Rpc->Sock->RemoteIP.addr[0] != 127)
+ {
+ // Refuse to set a blank password to hub admin from remote host
+ ReleaseHub(h);
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ Lock(h->lock);
+ {
+ if (a->ServerAdmin == false && h->Type != t->HubType)
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ else
+ {
+ h->Type = t->HubType;
+ h->Option->MaxSession = t->HubOption.MaxSession;
+ h->Option->NoEnum = t->HubOption.NoEnum;
+ if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&
+ IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)
+ {
+ Copy(h->HashedPassword, t->HashedPassword, SHA1_SIZE);
+ Copy(h->SecurePassword, t->SecurePassword, SHA1_SIZE);
+ }
+ }
+ }
+ Unlock(h->lock);
+
+ if (t->Online)
+ {
+ if (a->ServerAdmin || GetHubAdminOption(h, "no_online") == 0)
+ {
+ SetHubOnline(h);
+ }
+ }
+ else
+ {
+ if (a->ServerAdmin || GetHubAdminOption(h, "no_offline") == 0)
+ {
+ SetHubOffline(h);
+ }
+ }
+
+ if (h->Type == HUB_TYPE_FARM_STATIC)
+ {
+ EnableSecureNAT(h, false);
+ }
+
+ h->CurrentVersion++;
+ SiHubUpdateProc(h);
+
+ IncrementServerConfigRevision(s);
+
+ ALog(a, h, "LA_SET_HUB");
+
+ ReleaseHub(h);
+
+ return ret;
+}
+
+// Create a hub
+UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ HUB *h;
+ HUB_OPTION o;
+ UINT current_hub_num;
+ bool b;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+
+
+ if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ NO_SUPPORT_FOR_BRIDGE;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ Trim(t->HubName);
+ if (StrLen(t->HubName) == 0)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ if (StartWith(t->HubName, ".") || EndWith(t->HubName, "."))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ if (t->HubType != HUB_TYPE_STANDALONE)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+ else if (t->HubType != HUB_TYPE_FARM_DYNAMIC && t->HubType != HUB_TYPE_FARM_STATIC)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Create a hub object
+ Zero(&o, sizeof(o));
+ o.MaxSession = t->HubOption.MaxSession;
+ o.NoEnum = t->HubOption.NoEnum;
+
+ // Default setting for hub admin options
+ SiSetDefaultHubOption(&o);
+
+ LockList(c->HubList);
+ {
+ current_hub_num = LIST_NUM(c->HubList);
+ }
+ UnlockList(c->HubList);
+
+ if (current_hub_num > GetServerCapsInt(a->Server, "i_max_hubs"))
+ {
+ return ERR_TOO_MANY_HUBS;
+ }
+
+ LockList(c->HubList);
+ {
+ b = IsHub(c, t->HubName);
+ }
+ UnlockList(c->HubList);
+
+ if (b)
+ {
+ return ERR_HUB_ALREADY_EXISTS;
+ }
+
+ ALog(a, NULL, "LA_CREATE_HUB", t->HubName);
+
+ h = NewHub(c, t->HubName, &o);
+ Copy(h->HashedPassword, t->HashedPassword, SHA1_SIZE);
+ Copy(h->SecurePassword, t->SecurePassword, SHA1_SIZE);
+
+ h->Type = t->HubType;
+
+ AddHub(c, h);
+
+ if (t->Online)
+ {
+ h->Offline = true;
+ SetHubOnline(h);
+ }
+ else
+ {
+ h->Offline = false;
+ SetHubOffline(h);
+ }
+
+ h->CreatedTime = SystemTime64();
+
+ ReleaseHub(h);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Set cipher for SSL to the server
+UINT StSetServerCipher(ADMIN *a, RPC_STR *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+
+ if (IsEmptyStr(t->String))
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ StrUpper(t->String);
+
+ if (CheckCipherListName(t->String) == false)
+ {
+ return ERR_CIPHER_NOT_SUPPORTED;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_SET_SERVER_CIPHER", t->String);
+ }
+
+ Lock(c->lock);
+ {
+ SetCedarCipherList(c, t->String);
+ }
+ Unlock(c->lock);
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get cipher for SSL
+UINT StGetServerCipher(ADMIN *a, RPC_STR *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+
+ FreeRpcStr(t);
+ Zero(t, sizeof(RPC_STR));
+
+ Lock(c->lock);
+ {
+ t->String = CopyStr(c->CipherList);
+ }
+ Unlock(c->lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Get the server certification
+UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
+{
+ bool admin;
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ bool is_vgs_cert = false;
+
+ admin = a->ServerAdmin;
+
+ FreeRpcKeyPair(t);
+ Zero(t, sizeof(RPC_KEY_PAIR));
+
+ Lock(c->lock);
+ {
+
+ t->Cert = CloneX(c->ServerX);
+ if (admin && is_vgs_cert == false)
+ {
+ t->Key = CloneK(c->ServerK);
+ }
+ }
+ Unlock(c->lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Set the server certification
+UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+
+ SERVER_ADMIN_ONLY;
+
+ if (t->Cert == NULL || t->Key == NULL)
+ {
+ return ERR_PROTOCOL_ERROR;
+ }
+
+ if (t->Cert->is_compatible_bit == false)
+ {
+ return ERR_NOT_RSA_1024;
+ }
+
+ if (CheckXandK(t->Cert, t->Key) == false)
+ {
+ return ERR_PROTOCOL_ERROR;
+ }
+
+ SetCedarCert(c, t->Cert, t->Key);
+
+ ALog(a, NULL, "LA_SET_SERVER_CERT");
+
+ IncrementServerConfigRevision(s);
+
+ return ERR_NO_ERROR;
+}
+
+// Get status of connection to cluster controller
+UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ FARM_CONTROLLER *fc;
+
+ if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ return ERR_NOT_FARM_MEMBER;
+ }
+
+ Zero(t, sizeof(RPC_FARM_CONNECTION_STATUS));
+
+ fc = s->FarmController;
+
+ Lock(fc->lock);
+ {
+ if (fc->Sock != NULL)
+ {
+ t->Ip = IPToUINT(&fc->Sock->RemoteIP);
+ t->Port = fc->Sock->RemotePort;
+ }
+
+ t->Online = fc->Online;
+ t->LastError = ERR_NO_ERROR;
+
+ if (t->Online == false)
+ {
+ t->LastError = fc->LastError;
+ }
+ else
+ {
+ t->CurrentConnectedTime = fc->CurrentConnectedTime;
+ }
+
+ t->StartedTime = fc->StartedTime;
+ t->FirstConnectedTime = fc->FirstConnectedTime;
+
+ t->NumConnected = fc->NumConnected;
+ t->NumTry = fc->NumTry;
+ t->NumFailed = fc->NumFailed;
+ }
+ Unlock(fc->lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate cluster members
+UINT StEnumFarmMember(ADMIN *a, RPC_ENUM_FARM *t)
+{
+ SERVER *s = a->Server;
+ CEDAR *c = s->Cedar;
+ UINT i;
+
+ FreeRpcEnumFarm(t);
+ Zero(t, sizeof(RPC_ENUM_FARM));
+
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_FARM));
+
+ LockList(s->FarmMemberList);
+ {
+ t->NumFarm = LIST_NUM(s->FarmMemberList);
+ t->Farms = ZeroMalloc(sizeof(RPC_ENUM_FARM_ITEM) * t->NumFarm);
+
+ for (i = 0;i < t->NumFarm;i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ RPC_ENUM_FARM_ITEM *e = &t->Farms[i];
+
+ e->Id = POINTER_TO_KEY(f);
+ e->Controller = f->Me;
+
+ if (e->Controller)
+ {
+ e->ConnectedTime = TickToTime(c->CreatedTick);
+ e->Ip = 0x0100007f;
+ GetMachineName(e->Hostname, sizeof(e->Hostname));
+ e->Point = f->Point;
+ e->NumSessions = Count(c->CurrentSessions);
+ e->NumTcpConnections = Count(c->CurrentTcpConnections);
+
+ e->AssignedBridgeLicense = Count(c->AssignedBridgeLicense);
+ e->AssignedClientLicense = Count(c->AssignedClientLicense);
+ }
+ else
+ {
+ e->ConnectedTime = f->ConnectedTime;
+ e->Ip = f->Ip;
+ StrCpy(e->Hostname, sizeof(e->Hostname), f->hostname);
+ e->Point = f->Point;
+ e->NumSessions = f->NumSessions;
+ e->NumTcpConnections = f->NumTcpConnections;
+
+ e->AssignedBridgeLicense = f->AssignedBridgeLicense;
+ e->AssignedClientLicense = f->AssignedClientLicense;
+ }
+ e->NumHubs = LIST_NUM(f->HubList);
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ return ERR_NO_ERROR;
+}
+
+// Get cluster member information
+UINT StGetFarmInfo(ADMIN *a, RPC_FARM_INFO *t)
+{
+ SERVER *s = a->Server;
+ UINT id = t->Id;
+ UINT i;
+ UINT ret = ERR_NO_ERROR;
+
+ FreeRpcFarmInfo(t);
+ Zero(t, sizeof(RPC_FARM_INFO));
+
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return ERR_NOT_FARM_CONTROLLER;
+ }
+
+ LockList(s->FarmMemberList);
+ {
+ if (IsInListKey(s->FarmMemberList, id))
+ {
+ FARM_MEMBER *f = ListKeyToPointer(s->FarmMemberList, id);
+
+ t->Id = id;
+ t->Controller = f->Me;
+ t->Weight = f->Weight;
+
+ LockList(f->HubList);
+ {
+ t->NumFarmHub = LIST_NUM(f->HubList);
+ t->FarmHubs = ZeroMalloc(sizeof(RPC_FARM_HUB) * t->NumFarmHub);
+
+ for (i = 0;i < t->NumFarmHub;i++)
+ {
+ RPC_FARM_HUB *h = &t->FarmHubs[i];
+ HUB_LIST *hh = LIST_DATA(f->HubList, i);
+
+ h->DynamicHub = hh->DynamicHub;
+ StrCpy(h->HubName, sizeof(h->HubName), hh->Name);
+ }
+ }
+ UnlockList(f->HubList);
+
+ if (t->Controller)
+ {
+ t->ConnectedTime = TickToTime(s->Cedar->CreatedTick);
+ t->Ip = 0x0100007f;
+ GetMachineName(t->Hostname, sizeof(t->Hostname));
+ t->Point = f->Point;
+
+ LockList(s->ServerListenerList);
+ {
+ UINT i, n;
+ t->NumPort = 0;
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ SERVER_LISTENER *o = LIST_DATA(s->ServerListenerList, i);
+ if (o->Enabled)
+ {
+ t->NumPort++;
+ }
+ }
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ n = 0;
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ SERVER_LISTENER *o = LIST_DATA(s->ServerListenerList, i);
+ if (o->Enabled)
+ {
+ t->Ports[n++] = o->Port;
+ }
+ }
+ }
+ UnlockList(s->ServerListenerList);
+
+ t->ServerCert = CloneX(s->Cedar->ServerX);
+ t->NumSessions = Count(s->Cedar->CurrentSessions);
+ t->NumTcpConnections = Count(s->Cedar->CurrentTcpConnections);
+ }
+ else
+ {
+ t->ConnectedTime = f->ConnectedTime;
+ t->Ip = f->Ip;
+ StrCpy(t->Hostname, sizeof(t->Hostname), f->hostname);
+ t->Point = f->Point;
+ t->NumPort = f->NumPort;
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ Copy(t->Ports, f->Ports, sizeof(UINT) * t->NumPort);
+ t->ServerCert = CloneX(f->ServerCert);
+ t->NumSessions = f->NumSessions;
+ t->NumTcpConnections = f->NumTcpConnections;
+ }
+ }
+ else
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ return ret;
+}
+
+// Get clustering configuration
+UINT StGetFarmSetting(ADMIN *a, RPC_FARM *t)
+{
+ SERVER *s;
+ FreeRpcFarm(t);
+ Zero(t, sizeof(RPC_FARM));
+
+ s = a->Server;
+ t->ServerType = s->ServerType;
+ t->ControllerOnly = s->ControllerOnly;
+ t->Weight = s->Weight;
+
+ if (t->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ t->NumPort = s->NumPublicPort;
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ Copy(t->Ports, s->PublicPorts, sizeof(UINT) * t->NumPort);
+ t->PublicIp = s->PublicIp;
+ StrCpy(t->ControllerName, sizeof(t->ControllerName), s->ControllerName);
+ t->ControllerPort = s->ControllerPort;
+ }
+ else
+ {
+ t->NumPort = 0;
+ t->Ports = ZeroMalloc(0);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Set clustering configuration
+UINT StSetFarmSetting(ADMIN *a, RPC_FARM *t)
+{
+ bool cluster_allowed = false;
+
+ SERVER_ADMIN_ONLY;
+ NO_SUPPORT_FOR_BRIDGE;
+
+
+ cluster_allowed = GetServerCapsInt(a->Server, "b_support_cluster");
+
+ if (t->ServerType != SERVER_TYPE_STANDALONE && cluster_allowed == false)
+ {
+ // When clustering function is disabled, deny turning into clustering mode
+ return ERR_NOT_SUPPORTED;
+ }
+
+ ALog(a, NULL, "LA_SET_FARM_SETTING");
+
+ IncrementServerConfigRevision(a->Server);
+
+ SiSetServerType(a->Server, t->ServerType, t->PublicIp, t->NumPort, t->Ports,
+ t->ControllerName, t->ControllerPort, t->MemberPassword, t->Weight, t->ControllerOnly);
+
+ return ERR_NO_ERROR;
+}
+
+// Set server password
+UINT StSetServerPassword(ADMIN *a, RPC_SET_PASSWORD *t)
+{
+ SERVER_ADMIN_ONLY;
+
+
+ Copy(a->Server->HashedPassword, t->HashedPassword, SHA1_SIZE);
+
+ ALog(a, NULL, "LA_SET_SERVER_PASSWORD");
+
+ IncrementServerConfigRevision(a->Server);
+
+ return ERR_NO_ERROR;
+}
+
+// Enable / Disable listener
+UINT StEnableListener(ADMIN *a, RPC_LISTENER *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+
+
+ LockList(a->Server->ServerListenerList);
+ {
+ if (t->Enable)
+ {
+ if (SiEnableListener(a->Server, t->Port) == false)
+ {
+ ret = ERR_LISTENER_NOT_FOUND;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_ENABLE_LISTENER", t->Port);
+ }
+ }
+ else
+ {
+ if (SiDisableListener(a->Server, t->Port) == false)
+ {
+ ret = ERR_LISTENER_NOT_FOUND;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_DISABLE_LISTENER", t->Port);
+ }
+ }
+ }
+ UnlockList(a->Server->ServerListenerList);
+
+ IncrementServerConfigRevision(a->Server);
+
+ SleepThread(250);
+
+ return ret;
+}
+
+// Delete a listener
+UINT StDeleteListener(ADMIN *a, RPC_LISTENER *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ SERVER_ADMIN_ONLY;
+
+
+ LockList(a->Server->ServerListenerList);
+ {
+ if (SiDeleteListener(a->Server, t->Port) == false)
+ {
+ ret = ERR_LISTENER_NOT_FOUND;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_DELETE_LISTENER", t->Port);
+
+ IncrementServerConfigRevision(a->Server);
+ }
+ }
+ UnlockList(a->Server->ServerListenerList);
+
+ return ret;
+}
+
+// Enumerating listeners
+UINT StEnumListener(ADMIN *a, RPC_LISTENER_LIST *t)
+{
+ CEDAR *c = a->Server->Cedar;
+ UINT i;
+
+ FreeRpcListenerList(t);
+ Zero(t, sizeof(RPC_LISTENER_LIST));
+
+ LockList(a->Server->ServerListenerList);
+ {
+ t->NumPort = LIST_NUM(a->Server->ServerListenerList);
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ t->Enables = ZeroMalloc(sizeof(bool) * t->NumPort);
+ t->Errors = ZeroMalloc(sizeof(bool) * t->NumPort);
+
+ for (i = 0;i < t->NumPort;i++)
+ {
+ SERVER_LISTENER *o = LIST_DATA(a->Server->ServerListenerList, i);
+
+ t->Ports[i] = o->Port;
+ t->Enables[i] = o->Enabled;
+ if (t->Enables[i])
+ {
+ if (o->Listener->Status == LISTENER_STATUS_TRYING)
+ {
+ t->Errors[i] = true;
+ }
+ }
+ }
+ }
+ UnlockList(a->Server->ServerListenerList);
+
+ return ERR_NO_ERROR;
+}
+
+// Create a listener
+UINT StCreateListener(ADMIN *a, RPC_LISTENER *t)
+{
+ UINT ret = ERR_NO_ERROR;
+ CEDAR *c = a->Server->Cedar;
+
+ if (t->Port == 0 || t->Port > 65535)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ SERVER_ADMIN_ONLY;
+
+ LockList(a->Server->ServerListenerList);
+ {
+ if (SiAddListener(a->Server, t->Port, t->Enable) == false)
+ {
+ ret = ERR_LISTENER_ALREADY_EXISTS;
+ }
+ else
+ {
+ ALog(a, NULL, "LA_CREATE_LISTENER", t->Port);
+
+ IncrementServerConfigRevision(a->Server);
+ }
+ }
+ UnlockList(a->Server->ServerListenerList);
+
+ SleepThread(250);
+
+ return ret;
+}
+
+// Get server status
+UINT StGetServerStatus(ADMIN *a, RPC_SERVER_STATUS *t)
+{
+ CEDAR *c;
+ UINT i;
+
+ c = a->Server->Cedar;
+
+ Zero(t, sizeof(RPC_SERVER_STATUS));
+
+ Lock(c->TrafficLock);
+ {
+ Copy(&t->Traffic, c->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(c->TrafficLock);
+
+ GetMemInfo(&t->MemInfo);
+
+ t->ServerType = a->Server->ServerType;
+ t->NumTcpConnections = t->NumTcpConnectionsLocal = t->NumTcpConnectionsRemote = 0;
+ t->NumSessionsTotal = t->NumSessionsLocal = t->NumSessionsRemote = 0;
+
+ t->NumTcpConnectionsLocal = Count(c->CurrentTcpConnections);
+
+ if (a->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ LockList(a->Server->FarmMemberList);
+ {
+ for (i = 0;i < LIST_NUM(a->Server->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(a->Server->FarmMemberList, i);
+
+ if (f->Me == false)
+ {
+ t->NumTcpConnectionsRemote += f->NumTcpConnections;
+ t->NumSessionsRemote += f->NumSessions;
+ AddTraffic(&t->Traffic, &f->Traffic);
+ }
+ }
+ }
+ UnlockList(a->Server->FarmMemberList);
+ }
+
+ t->NumMacTables = t->NumIpTables = t->NumUsers = t->NumGroups = 0;
+
+ // The number of hubs
+ LockList(c->HubList);
+ {
+ t->NumHubTotal = LIST_NUM(c->HubList);
+
+ t->NumHubStandalone = t->NumHubDynamic = t->NumHubStatic = 0;
+
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ Lock(h->lock);
+ {
+ switch (h->Type)
+ {
+ case HUB_TYPE_STANDALONE:
+ t->NumHubStandalone++;
+ break;
+
+ case HUB_TYPE_FARM_STATIC:
+ t->NumHubStatic++;
+ break;
+
+ case HUB_TYPE_FARM_DYNAMIC:
+ t->NumHubDynamic++;
+ break;
+ }
+ }
+
+ t->NumMacTables += LIST_NUM(h->MacTable);
+ t->NumIpTables += LIST_NUM(h->IpTable);
+
+ if (h->HubDb != NULL)
+ {
+ t->NumUsers += LIST_NUM(h->HubDb->UserList);
+ t->NumGroups += LIST_NUM(h->HubDb->GroupList);
+ }
+
+ Unlock(h->lock);
+ }
+ }
+ UnlockList(c->HubList);
+
+ // The number of sessions
+ t->NumSessionsLocal = Count(c->CurrentSessions);
+ t->NumSessionsTotal = t->NumSessionsLocal + t->NumSessionsRemote;
+ t->NumTcpConnections = t->NumTcpConnectionsLocal + t->NumTcpConnectionsRemote;
+
+ t->AssignedBridgeLicenses = Count(c->AssignedBridgeLicense);
+ t->AssignedClientLicenses = Count(c->AssignedClientLicense);
+
+ t->AssignedBridgeLicensesTotal = a->Server->CurrentAssignedBridgeLicense;
+ t->AssignedClientLicensesTotal = a->Server->CurrentAssignedClientLicense;
+
+ t->CurrentTick = Tick64();
+ t->CurrentTime = SystemTime64();
+
+ t->StartTime = a->Server->StartTime;
+
+ return ERR_NO_ERROR;
+}
+
+// Get server information
+UINT StGetServerInfo(ADMIN *a, RPC_SERVER_INFO *t)
+{
+ CEDAR *c;
+ OS_INFO *info;
+ SYSTEMTIME st;
+ // Validate arguments
+ if (a == NULL || t == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ FreeRpcServerInfo(t);
+ Zero(t, sizeof(RPC_SERVER_INFO));
+
+ c = a->Server->Cedar;
+
+ GetServerProductName(a->Server, t->ServerProductName, sizeof(t->ServerProductName));
+
+ StrCpy(t->ServerVersionString, sizeof(t->ServerVersionString), c->VerString);
+ StrCpy(t->ServerBuildInfoString, sizeof(t->ServerBuildInfoString), c->BuildInfo);
+ t->ServerVerInt = c->Version;
+ t->ServerBuildInt = c->Build;
+ GetMachineName(t->ServerHostName, sizeof(t->ServerHostName));
+ t->ServerType = c->Server->ServerType;
+
+ Zero(&st, sizeof(st));
+ st.wYear = BUILD_DATE_Y;
+ st.wMonth = BUILD_DATE_M;
+ st.wDay = BUILD_DATE_D;
+ st.wHour = BUILD_DATE_HO;
+ st.wMinute = BUILD_DATE_MI;
+ st.wSecond = BUILD_DATE_SE;
+
+ t->ServerBuildDate = SystemToUINT64(&st);
+ StrCpy(t->ServerFamilyName, sizeof(t->ServerFamilyName), UPDATE_FAMILY_NAME);
+
+ info = GetOsInfo();
+ if (info != NULL)
+ {
+ CopyOsInfo(&t->OsInfo, info);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Copy OS_INFO
+void CopyOsInfo(OS_INFO *dst, OS_INFO *info)
+{
+ // Validate arguments
+ if (info == NULL || dst == NULL)
+ {
+ return;
+ }
+
+ dst->OsType = info->OsType;
+ dst->OsServicePack = info->OsServicePack;
+ dst->OsSystemName = CopyStr(info->OsSystemName);
+ dst->OsProductName = CopyStr(info->OsProductName);
+ dst->OsVendorName = CopyStr(info->OsVendorName);
+ dst->OsVersion = CopyStr(info->OsVersion);
+ dst->KernelName = CopyStr(info->KernelName);
+ dst->KernelVersion = CopyStr(info->KernelVersion);
+}
+
+// OPENVPN_SSTP_CONFIG
+void InOpenVpnSstpConfig(OPENVPN_SSTP_CONFIG *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(OPENVPN_SSTP_CONFIG));
+
+ t->EnableOpenVPN = PackGetBool(p, "EnableOpenVPN");
+ t->EnableSSTP = PackGetBool(p, "EnableSSTP");
+ PackGetStr(p, "OpenVPNPortList", t->OpenVPNPortList, sizeof(t->OpenVPNPortList));
+}
+void OutOpenVpnSstpConfig(PACK *p, OPENVPN_SSTP_CONFIG *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "EnableOpenVPN", t->EnableOpenVPN);
+ PackAddBool(p, "EnableSSTP", t->EnableSSTP);
+ PackAddStr(p, "OpenVPNPortList", t->OpenVPNPortList);
+}
+
+// DDNS_CLIENT_STATUS
+void InDDnsClientStatus(DDNS_CLIENT_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(DDNS_CLIENT_STATUS));
+
+ t->Err_IPv4 = PackGetInt(p, "Err_IPv4");
+ t->Err_IPv6 = PackGetInt(p, "Err_IPv6");
+
+ PackGetStr(p, "CurrentHostName", t->CurrentHostName, sizeof(t->CurrentHostName));
+ PackGetStr(p, "CurrentFqdn", t->CurrentFqdn, sizeof(t->CurrentFqdn));
+ PackGetStr(p, "DnsSuffix", t->DnsSuffix, sizeof(t->DnsSuffix));
+ PackGetStr(p, "CurrentIPv4", t->CurrentIPv4, sizeof(t->CurrentIPv4));
+ PackGetStr(p, "CurrentIPv6", t->CurrentIPv6, sizeof(t->CurrentIPv6));
+}
+void OutDDnsClientStatus(PACK *p, DDNS_CLIENT_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "Err_IPv4", t->Err_IPv4);
+ PackAddInt(p, "Err_IPv6", t->Err_IPv6);
+ PackAddStr(p, "CurrentHostName", t->CurrentHostName);
+ PackAddStr(p, "CurrentFqdn", t->CurrentFqdn);
+ PackAddStr(p, "DnsSuffix", t->DnsSuffix);
+ PackAddStr(p, "CurrentIPv4", t->CurrentIPv4);
+ PackAddStr(p, "CurrentIPv6", t->CurrentIPv6);
+}
+
+// INTERNET_SETTING
+void InRpcInternetSetting(INTERNET_SETTING *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ t->ProxyType = PackGetInt(p, "ProxyType");
+ PackGetStr(p, "ProxyHostName", t->ProxyHostName, sizeof(t->ProxyHostName));
+ t->ProxyPort = PackGetInt(p, "ProxyPort");
+ PackGetStr(p, "ProxyUsername", t->ProxyUsername, sizeof(t->ProxyUsername));
+ PackGetStr(p, "ProxyPassword", t->ProxyPassword, sizeof(t->ProxyPassword));
+}
+void OutRpcInternetSetting(PACK *p, INTERNET_SETTING *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "ProxyType", t->ProxyType);
+ PackAddStr(p, "ProxyHostName", t->ProxyHostName);
+ PackAddInt(p, "ProxyPort", t->ProxyPort);
+ PackAddStr(p, "ProxyUsername", t->ProxyUsername);
+ PackAddStr(p, "ProxyPassword", t->ProxyPassword);
+}
+
+// RPC_AZURE_STATUS
+void InRpcAzureStatus(RPC_AZURE_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_AZURE_STATUS));
+
+ t->IsConnected = PackGetBool(p, "IsConnected");
+ t->IsEnabled = PackGetBool(p, "IsEnabled");
+}
+void OutRpcAzureStatus(PACK *p, RPC_AZURE_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "IsConnected", t->IsConnected);
+ PackAddBool(p, "IsEnabled", t->IsEnabled);
+}
+
+// RPC_SPECIAL_LISTENER
+void InRpcSpecialListener(RPC_SPECIAL_LISTENER *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SPECIAL_LISTENER));
+
+ t->VpnOverIcmpListener = PackGetBool(p, "VpnOverIcmpListener");
+ t->VpnOverDnsListener = PackGetBool(p, "VpnOverDnsListener");
+}
+void OutRpcSpecialListener(PACK *p, RPC_SPECIAL_LISTENER *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "VpnOverIcmpListener", t->VpnOverIcmpListener);
+ PackAddBool(p, "VpnOverDnsListener", t->VpnOverDnsListener);
+}
+
+
+// ETHERIP_ID
+void InEtherIpId(ETHERIP_ID *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(ETHERIP_ID));
+
+ PackGetStr(p, "Id", t->Id, sizeof(t->Id));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "UserName", t->UserName, sizeof(t->UserName));
+ PackGetStr(p, "Password", t->Password, sizeof(t->Password));
+}
+void OutEtherIpId(PACK *p, ETHERIP_ID *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Id", t->Id);
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "UserName", t->UserName);
+ PackAddStr(p, "Password", t->Password);
+}
+
+// RPC_ENUM_ETHERIP_ID
+void InRpcEnumEtherIpId(RPC_ENUM_ETHERIP_ID *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_ETHERIP_ID));
+
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->IdList = ZeroMalloc(sizeof(ETHERIP_ID) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ETHERIP_ID *e = &t->IdList[i];
+
+ PackGetStrEx(p, "Id", e->Id, sizeof(e->Id), i);
+ PackGetStrEx(p, "HubName", e->HubName, sizeof(e->HubName), i);
+ PackGetStrEx(p, "UserName", e->UserName, sizeof(e->UserName), i);
+ PackGetStrEx(p, "Password", e->Password, sizeof(e->Password), i);
+ }
+}
+void OutRpcEnumEtherIpId(PACK *p, RPC_ENUM_ETHERIP_ID *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ETHERIP_ID *e = &t->IdList[i];
+
+ PackAddStrEx(p, "Id", e->Id, i, t->NumItem);
+ PackAddStrEx(p, "HubName", e->HubName, i, t->NumItem);
+ PackAddStrEx(p, "UserName", e->UserName, i, t->NumItem);
+ PackAddStrEx(p, "Password", e->Password, i, t->NumItem);
+ }
+}
+void FreeRpcEnumEtherIpId(RPC_ENUM_ETHERIP_ID *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->IdList);
+}
+
+// IPSEC_SERVICES
+void InIPsecServices(IPSEC_SERVICES *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(IPSEC_SERVICES));
+
+ t->L2TP_Raw = PackGetBool(p, "L2TP_Raw");
+ t->L2TP_IPsec = PackGetBool(p, "L2TP_IPsec");
+ t->EtherIP_IPsec = PackGetBool(p, "EtherIP_IPsec");
+
+ PackGetStr(p, "IPsec_Secret", t->IPsec_Secret, sizeof(t->IPsec_Secret));
+ PackGetStr(p, "L2TP_DefaultHub", t->L2TP_DefaultHub, sizeof(t->L2TP_DefaultHub));
+}
+void OutIPsecServices(PACK *p, IPSEC_SERVICES *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "L2TP_Raw", t->L2TP_Raw);
+ PackAddBool(p, "L2TP_IPsec", t->L2TP_IPsec);
+ PackAddBool(p, "EtherIP_IPsec", t->EtherIP_IPsec);
+
+ PackAddStr(p, "IPsec_Secret", t->IPsec_Secret);
+ PackAddStr(p, "L2TP_DefaultHub", t->L2TP_DefaultHub);
+}
+
+// RPC_WINVER
+void InRpcWinVer(RPC_WINVER *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_WINVER));
+
+ t->IsWindows = PackGetBool(p, "V_IsWindows");
+ t->IsNT = PackGetBool(p, "V_IsNT");
+ t->IsServer = PackGetBool(p, "V_IsServer");
+ t->IsBeta = PackGetBool(p, "V_IsBeta");
+ t->VerMajor = PackGetInt(p, "V_VerMajor");
+ t->VerMinor = PackGetInt(p, "V_VerMinor");
+ t->Build = PackGetInt(p, "V_Build");
+ t->ServicePack = PackGetInt(p, "V_ServicePack");
+ PackGetStr(p, "V_Title", t->Title, sizeof(t->Title));
+}
+void OutRpcWinVer(PACK *p, RPC_WINVER *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "V_IsWindows", t->IsWindows);
+ PackAddBool(p, "V_IsNT", t->IsNT);
+ PackAddBool(p, "V_IsServer", t->IsServer);
+ PackAddBool(p, "V_IsBeta", t->IsBeta);
+ PackAddInt(p, "V_VerMajor", t->VerMajor);
+ PackAddInt(p, "V_VerMinor", t->VerMinor);
+ PackAddInt(p, "V_Build", t->Build);
+ PackAddInt(p, "V_ServicePack", t->ServicePack);
+ PackAddStr(p, "V_Title", t->Title);
+}
+
+// RPC_MSG
+void InRpcMsg(RPC_MSG *t, PACK *p)
+{
+ UINT size;
+ char *utf8;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_MSG));
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ size = PackGetDataSize(p, "Msg");
+ utf8 = ZeroMalloc(size + 8);
+ PackGetData(p, "Msg", utf8);
+ t->Msg = CopyUtfToUni(utf8);
+ Free(utf8);
+}
+void OutRpcMsg(PACK *p, RPC_MSG *t)
+{
+ UINT size;
+ char *utf8;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ utf8 = CopyUniToUtf(t->Msg);
+ size = StrLen(utf8);
+ PackAddData(p, "Msg", utf8, size);
+ Free(utf8);
+}
+void FreeRpcMsg(RPC_MSG *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Msg);
+}
+
+// RPC_ENUM_ETH_VLAN
+void InRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_ETH_VLAN));
+
+ t->NumItem = PackGetIndexCount(p, "DeviceName");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_ETH_VLAN_ITEM *e = &t->Items[i];
+
+ PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);
+ PackGetStrEx(p, "Guid", e->Guid, sizeof(e->Guid), i);
+ PackGetStrEx(p, "DeviceInstanceId", e->DeviceInstanceId, sizeof(e->DeviceInstanceId), i);
+ PackGetStrEx(p, "DriverName", e->DriverName, sizeof(e->DriverName), i);
+ PackGetStrEx(p, "DriverType", e->DriverType, sizeof(e->DriverType), i);
+ e->Support = PackGetBoolEx(p, "Support", i);
+ e->Enabled = PackGetBoolEx(p, "Enabled", i);
+ }
+}
+void OutRpcEnumEthVLan(PACK *p, RPC_ENUM_ETH_VLAN *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_ETH_VLAN_ITEM *e = &t->Items[i];
+
+ PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);
+ PackAddStrEx(p, "Guid", e->Guid, i, t->NumItem);
+ PackAddStrEx(p, "DeviceInstanceId", e->DeviceInstanceId, i, t->NumItem);
+ PackAddStrEx(p, "DriverName", e->DriverName, i, t->NumItem);
+ PackAddStrEx(p, "DriverType", e->DriverType, i, t->NumItem);
+ PackAddBoolEx(p, "Support", e->Support, i, t->NumItem);
+ PackAddBoolEx(p, "Enabled", e->Enabled, i, t->NumItem);
+ }
+}
+void FreeRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_ENUM_LOG_FILE
+void InRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_LOG_FILE));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+
+ PackGetStrEx(p, "FilePath", e->FilePath, sizeof(e->FilePath), i);
+ PackGetStrEx(p, "ServerName", e->ServerName, sizeof(e->ServerName), i);
+ e->FileSize = PackGetIntEx(p, "FileSize", i);
+ e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);
+ }
+}
+void OutRpcEnumLogFile(PACK *p, RPC_ENUM_LOG_FILE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+
+ PackAddStrEx(p, "FilePath", e->FilePath, i, t->NumItem);
+ PackAddStrEx(p, "ServerName", e->ServerName, i, t->NumItem);
+ PackAddIntEx(p, "FileSize", e->FileSize, i, t->NumItem);
+ PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumItem);
+ }
+}
+void FreeRpcEnumLogFile(RPC_ENUM_LOG_FILE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+void AdjoinRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, RPC_ENUM_LOG_FILE *src)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (t == NULL || src == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(CmpLogFile);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+ LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));
+
+ f->FileSize = e->FileSize;
+ StrCpy(f->Path, sizeof(f->Path), e->FilePath);
+ StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);
+ f->UpdatedTime = e->UpdatedTime;
+
+ Add(o, f);
+ }
+
+ for (i = 0;i < src->NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &src->Items[i];
+ LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));
+
+ f->FileSize = e->FileSize;
+ StrCpy(f->Path, sizeof(f->Path), e->FilePath);
+ StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);
+ f->UpdatedTime = e->UpdatedTime;
+
+ Add(o, f);
+ }
+
+ FreeRpcEnumLogFile(t);
+
+ Sort(o);
+
+ Zero(t, sizeof(RPC_ENUM_LOG_FILE));
+ t->NumItem = LIST_NUM(o);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ LOG_FILE *f = LIST_DATA(o, i);
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+
+ StrCpy(e->FilePath, sizeof(e->FilePath), f->Path);
+ StrCpy(e->ServerName, sizeof(e->ServerName), f->ServerName);
+ e->FileSize = f->FileSize;
+ e->UpdatedTime = f->UpdatedTime;
+ }
+
+ FreeEnumLogFile(o);
+}
+
+// RPC_READ_LOG_FILE
+void InRpcReadLogFile(RPC_READ_LOG_FILE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_READ_LOG_FILE));
+ PackGetStr(p, "FilePath", t->FilePath, sizeof(t->FilePath));
+ PackGetStr(p, "ServerName", t->ServerName, sizeof(t->ServerName));
+ t->Offset = PackGetInt(p, "Offset");
+
+ t->Buffer = PackGetBuf(p, "Buffer");
+}
+void OutRpcReadLogFile(PACK *p, RPC_READ_LOG_FILE *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "FilePath", t->FilePath);
+ PackAddStr(p, "ServerName", t->ServerName);
+ PackAddInt(p, "Offset", t->Offset);
+
+ if (t->Buffer != NULL)
+ {
+ PackAddBuf(p, "Buffer", t->Buffer);
+ }
+}
+void FreeRpcReadLogFile(RPC_READ_LOG_FILE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->Buffer != NULL)
+ {
+ FreeBuf(t->Buffer);
+ }
+}
+
+// RPC_AC_LIST
+void InRpcAcList(RPC_AC_LIST *t, PACK *p)
+{
+ UINT i;
+ LIST *o;
+ UINT num;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_AC_LIST));
+ o = NewAcList();
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ num = PackGetInt(p, "NumItem");
+
+ for (i = 0;i < num;i++)
+ {
+ AC *ac = ZeroMalloc(sizeof(AC));
+
+ ac->Deny = PackGetBoolEx(p, "Deny", i);
+ PackGetIpEx(p, "IpAddress", &ac->IpAddress, i);
+ ac->Masked = PackGetBoolEx(p, "Masked", i);
+
+ if (ac->Masked)
+ {
+ PackGetIpEx(p, "SubnetMask", &ac->SubnetMask, i);
+ }
+
+ ac->Priority = PackGetIntEx(p, "Priority", i);
+
+ AddAc(o, ac);
+
+ Free(ac);
+ }
+
+ t->o = o;
+}
+void OutRpcAcList(PACK *p, RPC_AC_LIST *t)
+{
+ UINT i, num;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ o = t->o;
+ num = LIST_NUM(o);
+
+ PackAddInt(p, "NumItem", num);
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < num;i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ PackAddBoolEx(p, "Deny", ac->Deny, i, num);
+ PackAddIpEx(p, "IpAddress", &ac->IpAddress, i, num);
+ PackAddBoolEx(p, "Masked", ac->Masked, i, num);
+
+ PackAddIpEx(p, "SubnetMask", &ac->SubnetMask, i, num);
+
+ PackAddIntEx(p, "Priority", ac->Priority, i, num);
+ }
+}
+void FreeRpcAcList(RPC_AC_LIST *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeAcList(t->o);
+}
+
+// RPC_INT
+void InRpcInt(RPC_INT *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_INT));
+ t->IntValue = PackGetInt(p, "IntValue");
+}
+void OutRpcInt(PACK *p, RPC_INT *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "IntValue", t->IntValue);
+}
+
+// RPC_ENUM_CRL
+void InRpcEnumCrl(RPC_ENUM_CRL *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_CRL));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumItem = PackGetInt(p, "NumItem");
+
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_CRL_ITEM) * t->NumItem);
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_CRL_ITEM *e = &t->Items[i];
+
+ e->Key = PackGetIntEx(p, "Key", i);
+ PackGetUniStrEx(p, "CrlInfo", e->CrlInfo, sizeof(e->CrlInfo), i);
+ }
+}
+void OutRpcEnumCrl(PACK *p, RPC_ENUM_CRL *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_CRL_ITEM *e = &t->Items[i];
+
+ PackAddIntEx(p, "Key", e->Key, i, t->NumItem);
+ PackAddUniStrEx(p, "CrlInfo", e->CrlInfo, i, t->NumItem);
+ }
+}
+void FreeRpcEnumCrl(RPC_ENUM_CRL *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_CRL
+void InRpcCrl(RPC_CRL *t, PACK *p)
+{
+ BUF *b;
+ NAME *n;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_CRL));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Key = PackGetInt(p, "Key");
+ b = PackGetBuf(p, "Serial");
+ t->Crl = ZeroMalloc(sizeof(CRL));
+ if (b != NULL)
+ {
+ t->Crl->Serial = NewXSerial(b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ t->Crl->Name = ZeroMalloc(sizeof(NAME));
+ n = t->Crl->Name;
+ if (PackGetUniStr(p, "CommonName", tmp, sizeof(tmp)))
+ {
+ n->CommonName = CopyUniStr(tmp);
+ }
+ if (PackGetUniStr(p, "Organization", tmp, sizeof(tmp)))
+ {
+ n->Organization = CopyUniStr(tmp);
+ }
+ if (PackGetUniStr(p, "Unit", tmp, sizeof(tmp)))
+ {
+ n->Unit = CopyUniStr(tmp);
+ }
+ if (PackGetUniStr(p, "Country", tmp, sizeof(tmp)))
+ {
+ n->Country = CopyUniStr(tmp);
+ }
+ if (PackGetUniStr(p, "State", tmp, sizeof(tmp)))
+ {
+ n->State = CopyUniStr(tmp);
+ }
+ if (PackGetUniStr(p, "Local", tmp, sizeof(tmp)))
+ {
+ n->Local = CopyUniStr(tmp);
+ }
+ if (PackGetDataSize(p, "DigestMD5") == MD5_SIZE)
+ {
+ PackGetData(p, "DigestMD5", t->Crl->DigestMD5);
+ }
+ if (PackGetDataSize(p, "DigestSHA1") == SHA1_SIZE)
+ {
+ PackGetData(p, "DigestSHA1", t->Crl->DigestSHA1);
+ }
+}
+void OutRpcCrl(PACK *p, RPC_CRL *t)
+{
+ NAME *n;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "Key", t->Key);
+
+ if (t->Crl == NULL)
+ {
+ return;
+ }
+
+ if (t->Crl->Serial != NULL)
+ {
+ PackAddData(p, "Serial", t->Crl->Serial->data, t->Crl->Serial->size);
+ }
+ n = t->Crl->Name;
+ if (n->CommonName != NULL)
+ {
+ PackAddUniStr(p, "CommonName", n->CommonName);
+ }
+ if (n->Organization != NULL)
+ {
+ PackAddUniStr(p, "Organization", n->Organization);
+ }
+ if (n->Unit != NULL)
+ {
+ PackAddUniStr(p, "Unit", n->Unit);
+ }
+ if (n->Country != NULL)
+ {
+ PackAddUniStr(p, "Country", n->Country);
+ }
+ if (n->State != NULL)
+ {
+ PackAddUniStr(p, "State", n->State);
+ }
+ if (n->Local != NULL)
+ {
+ PackAddUniStr(p, "Local", n->Local);
+ }
+ if (IsZero(t->Crl->DigestMD5, MD5_SIZE) == false)
+ {
+ PackAddData(p, "DigestMD5", t->Crl->DigestMD5, MD5_SIZE);
+ }
+ if (IsZero(t->Crl->DigestSHA1, SHA1_SIZE) == false)
+ {
+ PackAddData(p, "DigestSHA1", t->Crl->DigestSHA1, SHA1_SIZE);
+ }
+}
+void FreeRpcCrl(RPC_CRL *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeCrl(t->Crl);
+}
+
+// RPC_ENUM_L3TABLE
+void InRpcEnumL3Table(RPC_ENUM_L3TABLE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_L3TABLE));
+ t->NumItem = PackGetInt(p, "NumItem");
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ t->Items = ZeroMalloc(sizeof(RPC_L3TABLE) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_L3TABLE *e = &t->Items[i];
+
+ e->NetworkAddress = PackGetIp32Ex(p, "NetworkAddress", i);
+ e->SubnetMask = PackGetIp32Ex(p, "SubnetMask", i);
+ e->GatewayAddress = PackGetIp32Ex(p, "GatewayAddress", i);
+ e->Metric = PackGetIntEx(p, "Metric", i);
+ }
+}
+void OutRpcEnumL3Table(PACK *p, RPC_ENUM_L3TABLE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+ PackAddStr(p, "Name", t->Name);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_L3TABLE *e = &t->Items[i];
+
+ PackAddIp32Ex(p, "NetworkAddress", e->NetworkAddress, i, t->NumItem);
+ PackAddIp32Ex(p, "SubnetMask", e->SubnetMask, i, t->NumItem);
+ PackAddIp32Ex(p, "GatewayAddress", e->GatewayAddress, i, t->NumItem);
+ PackAddIntEx(p, "Metric", e->Metric, i, t->NumItem);
+ }
+}
+void FreeRpcEnumL3Table(RPC_ENUM_L3TABLE *t)
+{
+ Free(t->Items);
+}
+
+// RPC_L3TABLE
+void InRpcL3Table(RPC_L3TABLE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_L3TABLE));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ t->NetworkAddress = PackGetIp32(p, "NetworkAddress");
+ t->SubnetMask = PackGetIp32(p, "SubnetMask");
+ t->GatewayAddress = PackGetIp32(p, "GatewayAddress");
+ t->Metric = PackGetInt(p, "Metric");
+}
+void OutRpcL3Table(PACK *p, RPC_L3TABLE *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Name", t->Name);
+ PackAddIp32(p, "NetworkAddress", t->NetworkAddress);
+ PackAddIp32(p, "SubnetMask", t->SubnetMask);
+ PackAddIp32(p, "GatewayAddress", t->GatewayAddress);
+ PackAddInt(p, "Metric", t->Metric);
+}
+
+// RPC_ENUM_L3IF
+void InRpcEnumL3If(RPC_ENUM_L3IF *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_L3IF));
+ t->NumItem = PackGetInt(p, "NumItem");
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ t->Items = ZeroMalloc(sizeof(RPC_L3IF) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_L3IF *f = &t->Items[i];
+
+ PackGetStrEx(p, "HubName", f->HubName, sizeof(f->HubName), i);
+ f->IpAddress = PackGetIp32Ex(p, "IpAddress", i);
+ f->SubnetMask = PackGetIp32Ex(p, "SubnetMask", i);
+ }
+}
+void OutRpcEnumL3If(PACK *p, RPC_ENUM_L3IF *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+ PackAddStr(p, "Name", t->Name);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_L3IF *f = &t->Items[i];
+
+ PackAddStrEx(p, "HubName", f->HubName, i, t->NumItem);
+ PackAddIp32Ex(p, "IpAddress", f->IpAddress, i, t->NumItem);
+ PackAddIp32Ex(p, "SubnetMask", f->SubnetMask, i, t->NumItem);
+ }
+}
+void FreeRpcEnumL3If(RPC_ENUM_L3IF *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_L3IF
+void InRpcL3If(RPC_L3IF *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_L3IF));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->IpAddress = PackGetIp32(p, "IpAddress");
+ t->SubnetMask = PackGetIp32(p, "SubnetMask");
+}
+void OutRpcL3If(PACK *p, RPC_L3IF *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Name", t->Name);
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddIp32(p, "IpAddress", t->IpAddress);
+ PackAddIp32(p, "SubnetMask", t->SubnetMask);
+}
+
+// RPC_L3SW
+void InRpcL3Sw(RPC_L3SW *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_L3SW));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+}
+void OutRpcL3Sw(PACK *p, RPC_L3SW *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Name", t->Name);
+}
+
+// RPC_ENUM_L3SW
+void InRpcEnumL3Sw(RPC_ENUM_L3SW *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_L3SW));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_L3SW_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *s = &t->Items[i];
+
+ PackGetStrEx(p, "Name", s->Name, sizeof(s->Name), i);
+ s->NumInterfaces = PackGetIntEx(p, "NumInterfaces", i);
+ s->NumTables = PackGetIntEx(p, "NumTables", i);
+ s->Active = PackGetBoolEx(p, "Active", i);
+ s->Online = PackGetBoolEx(p, "Online", i);
+ }
+}
+void OutRpcEnumL3Sw(PACK *p, RPC_ENUM_L3SW *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *s = &t->Items[i];
+
+ PackAddStrEx(p, "Name", s->Name, i, t->NumItem);
+ PackAddIntEx(p, "NumInterfaces", s->NumInterfaces, i, t->NumItem);
+ PackAddIntEx(p, "NumTables", s->NumTables, i, t->NumItem);
+ PackAddBoolEx(p, "Active", s->Active, i, t->NumItem);
+ PackAddBoolEx(p, "Online", s->Online, i, t->NumItem);
+ }
+}
+void FreeRpcEnumL3Sw(RPC_ENUM_L3SW *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_ENUM_ETH
+void InRpcEnumEth(RPC_ENUM_ETH *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_ETH));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *e = &t->Items[i];
+ PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);
+ PackGetUniStrEx(p, "NetworkConnectionName", e->NetworkConnectionName, sizeof(e->NetworkConnectionName), i);
+ }
+}
+void OutRpcEnumEth(PACK *p, RPC_ENUM_ETH *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *e = &t->Items[i];
+ PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);
+ PackAddUniStrEx(p, "NetworkConnectionName", e->NetworkConnectionName, i, t->NumItem);
+ }
+}
+void FreeRpcEnumEth(RPC_ENUM_ETH *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_LOCALBRIDGE
+void InRpcLocalBridge(RPC_LOCALBRIDGE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LOCALBRIDGE));
+ PackGetStr(p, "DeviceName", t->DeviceName, sizeof(t->DeviceName));
+ PackGetStr(p, "HubNameLB", t->HubName, sizeof(t->HubName));
+ t->TapMode = PackGetBool(p, "TapMode");
+}
+void OutRpcLocalBridge(PACK *p, RPC_LOCALBRIDGE *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", t->DeviceName);
+ PackAddStr(p, "HubNameLB", t->HubName);
+ PackAddBool(p, "TapMode", t->TapMode);
+}
+
+// RPC_ENUM_LOCALBRIDGE
+void InRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_LOCALBRIDGE));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_LOCALBRIDGE) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t->Items[i];
+
+ PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);
+ PackGetStrEx(p, "HubNameLB", e->HubName, sizeof(e->HubName), i);
+ e->Online = PackGetBoolEx(p, "Online", i);
+ e->Active = PackGetBoolEx(p, "Active", i);
+ e->TapMode = PackGetBoolEx(p, "TapMode", i);
+ }
+}
+void OutRpcEnumLocalBridge(PACK *p, RPC_ENUM_LOCALBRIDGE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t->Items[i];
+
+ PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);
+ PackAddStrEx(p, "HubNameLB", e->HubName, i, t->NumItem);
+ PackAddBoolEx(p, "Online", e->Online, i, t->NumItem);
+ PackAddBoolEx(p, "Active", e->Active, i, t->NumItem);
+ PackAddBoolEx(p, "TapMode", e->TapMode, i, t->NumItem);
+ }
+}
+void FreeRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+ Free(t->Items);
+}
+
+// MEMINFO
+void InRpcMemInfo(MEMINFO *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(MEMINFO));
+ t->TotalMemory = PackGetInt64(p, "TotalMemory");
+ t->UsedMemory = PackGetInt64(p, "UsedMemory");
+ t->FreeMemory = PackGetInt64(p, "FreeMemory");
+ t->TotalPhys = PackGetInt64(p, "TotalPhys");
+ t->UsedPhys = PackGetInt64(p, "UsedPhys");
+ t->FreePhys = PackGetInt64(p, "FreePhys");
+}
+void OutRpcMemInfo(PACK *p, MEMINFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt64(p, "TotalMemory", t->TotalMemory);
+ PackAddInt64(p, "UsedMemory", t->UsedMemory);
+ PackAddInt64(p, "FreeMemory", t->FreeMemory);
+ PackAddInt64(p, "TotalPhys", t->TotalPhys);
+ PackAddInt64(p, "UsedPhys", t->UsedPhys);
+ PackAddInt64(p, "FreePhys", t->FreePhys);
+}
+
+// OS_INFO
+void InRpcOsInfo(OS_INFO *t, PACK *p)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(OS_INFO));
+ t->OsType = PackGetInt(p, "OsType");
+ t->OsServicePack = PackGetInt(p, "OsServicePack");
+ if (PackGetStr(p, "OsSystemName", tmp, sizeof(tmp)))
+ {
+ t->OsSystemName = CopyStr(tmp);
+ }
+ if (PackGetStr(p, "OsProductName", tmp, sizeof(tmp)))
+ {
+ t->OsProductName = CopyStr(tmp);
+ }
+ if (PackGetStr(p, "OsVendorName", tmp, sizeof(tmp)))
+ {
+ t->OsVendorName = CopyStr(tmp);
+ }
+ if (PackGetStr(p, "OsVersion", tmp, sizeof(tmp)))
+ {
+ t->OsVersion = CopyStr(tmp);
+ }
+ if (PackGetStr(p, "KernelName", tmp, sizeof(tmp)))
+ {
+ t->KernelName = CopyStr(tmp);
+ }
+ if (PackGetStr(p, "KernelVersion", tmp, sizeof(tmp)))
+ {
+ t->KernelVersion = CopyStr(tmp);
+ }
+}
+void OutRpcOsInfo(PACK *p, OS_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "OsType", t->OsType);
+ PackAddInt(p, "OsServicePack", t->OsServicePack);
+ PackAddStr(p, "OsSystemName", t->OsSystemName);
+ PackAddStr(p, "OsProductName", t->OsProductName);
+ PackAddStr(p, "OsVendorName", t->OsVendorName);
+ PackAddStr(p, "OsVersion", t->OsVersion);
+ PackAddStr(p, "KernelName", t->KernelName);
+ PackAddStr(p, "KernelVersion", t->KernelVersion);
+}
+void FreeRpcOsInfo(OS_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->OsSystemName);
+ Free(t->OsProductName);
+ Free(t->OsVendorName);
+ Free(t->OsVersion);
+ Free(t->KernelName);
+ Free(t->KernelVersion);
+}
+
+// Read a local log file
+void SiReadLocalLogFile(SERVER *s, char *filepath, UINT offset, RPC_READ_LOG_FILE *t)
+{
+ char exe_dir[MAX_PATH], full_path[MAX_PATH];
+ IO *o;
+ // Validate arguments
+ if (s == NULL || t == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_READ_LOG_FILE));
+
+ GetExeDir(exe_dir, sizeof(exe_dir));
+ Format(full_path, sizeof(full_path), "%s/%s", exe_dir, filepath);
+
+ // Read file
+ o = FileOpenEx(full_path, false, false);
+ if (o != NULL)
+ {
+ UINT filesize = FileSize(o);
+
+ if (offset < filesize)
+ {
+ UINT readsize = MIN(filesize - offset, FTP_BLOCK_SIZE);
+ void *buf = ZeroMalloc(readsize);
+
+ FileSeek(o, FILE_BEGIN, offset);
+ FileRead(o, buf, readsize);
+
+ t->Buffer = NewBuf();
+ WriteBuf(t->Buffer, buf, readsize);
+ Free(buf);
+ }
+
+ FileClose(o);
+ }
+}
+
+// Enumerate local log files
+void SiEnumLocalLogFileList(SERVER *s, char *hubname, RPC_ENUM_LOG_FILE *t)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_LOG_FILE));
+
+ o = EnumLogFile(hubname);
+
+ t->NumItem = LIST_NUM(o);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LOG_FILE *f = LIST_DATA(o, i);
+ RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
+
+ StrCpy(e->FilePath, sizeof(e->FilePath), f->Path);
+ StrCpy(e->ServerName, sizeof(e->ServerName), f->ServerName);
+ e->FileSize = f->FileSize;
+ e->UpdatedTime = f->UpdatedTime;
+ }
+
+ FreeEnumLogFile(o);
+}
+
+// Enumerate local sessions
+void SiEnumLocalSession(SERVER *s, char *hubname, RPC_ENUM_SESSION *t)
+{
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ LockHubList(s->Cedar);
+ h = GetHub(s->Cedar, hubname);
+ UnlockHubList(s->Cedar);
+
+ if (h == NULL)
+ {
+ t->NumSession = 0;
+ t->Sessions = ZeroMalloc(0);
+ return;
+ }
+
+ LockList(h->SessionList);
+ {
+ UINT i;
+ t->NumSession = LIST_NUM(h->SessionList);
+ t->Sessions = ZeroMalloc(sizeof(RPC_ENUM_SESSION_ITEM) * t->NumSession);
+
+ for (i = 0;i < t->NumSession;i++)
+ {
+ SESSION *s = LIST_DATA(h->SessionList, i);
+ RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];
+ Lock(s->lock);
+ {
+ StrCpy(e->Name, sizeof(e->Name), s->Name);
+ StrCpy(e->Username, sizeof(e->Username), s->Username);
+ e->Ip = IPToUINT(&s->Connection->ClientIp);
+ StrCpy(e->Hostname, sizeof(e->Hostname), s->Connection->ClientHostname);
+ e->MaxNumTcp = s->MaxConnection;
+ e->LinkMode = s->LinkModeServer;
+ e->SecureNATMode = s->SecureNATMode;
+ e->BridgeMode = s->BridgeMode;
+ e->Layer3Mode = s->L3SwitchMode;
+ e->VLanId = s->VLanId;
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ e->CurrentNumTcp = s->Connection->Tcp->TcpSockList->num_item;
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+ Lock(s->TrafficLock);
+ {
+ e->PacketSize = GetTrafficPacketSize(s->Traffic);
+ e->PacketNum = GetTrafficPacketNum(s->Traffic);
+ }
+ Unlock(s->TrafficLock);
+ e->Client_BridgeMode = s->IsBridgeMode;
+ e->Client_MonitorMode = s->IsMonitorMode;
+ Copy(e->UniqueId, s->NodeInfo.UniqueId, 16);
+ }
+ Unlock(s->lock);
+ GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));
+ }
+ }
+ UnlockList(h->SessionList);
+
+ ReleaseHub(h);
+}
+
+// RPC_ENUM_LICENSE_KEY
+void InRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_LICENSE_KEY));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_LICENSE_KEY_ITEM) * t->NumItem);
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LICENSE_KEY_ITEM *e = &t->Items[i];
+
+ e->Id = PackGetIntEx(p, "Id", i);
+ PackGetStrEx(p, "LicenseKey", e->LicenseKey, sizeof(e->LicenseKey), i);
+ PackGetStrEx(p, "LicenseId", e->LicenseId, sizeof(e->LicenseId), i);
+ PackGetStrEx(p, "LicenseName", e->LicenseName, sizeof(e->LicenseName), i);
+ e->Expires = PackGetInt64Ex(p, "Expires", i);
+ e->Status = PackGetIntEx(p, "Status", i);
+ e->ProductId = PackGetIntEx(p, "ProductId", i);
+ e->SystemId = PackGetInt64Ex(p, "SystemId", i);
+ e->SerialId = PackGetIntEx(p, "SerialId", i);
+ }
+}
+void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_LICENSE_KEY_ITEM *e = &t->Items[i];
+
+ PackAddIntEx(p, "Id", e->Id, i, t->NumItem);
+ PackAddStrEx(p, "LicenseKey", e->LicenseKey, i, t->NumItem);
+ PackAddStrEx(p, "LicenseId", e->LicenseId, i, t->NumItem);
+ PackAddStrEx(p, "LicenseName", e->LicenseName, i, t->NumItem);
+ PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumItem);
+ PackAddIntEx(p, "Status", e->Status, i, t->NumItem);
+ PackAddIntEx(p, "ProductId", e->ProductId, i, t->NumItem);
+ PackAddInt64Ex(p, "SystemId", e->SystemId, i, t->NumItem);
+ PackAddIntEx(p, "SerialId", e->SerialId, i, t->NumItem);
+ }
+}
+void FreeRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_LICENSE_STATUS
+void InRpcLicenseStatus(RPC_LICENSE_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LICENSE_STATUS));
+
+ t->EditionId = PackGetInt(p, "EditionId");
+ PackGetStr(p, "EditionStr", t->EditionStr, sizeof(t->EditionStr) );
+ t->SystemId = PackGetInt64(p, "SystemId");
+ t->SystemExpires = PackGetInt64(p, "SystemExpires");
+ t->NumClientConnectLicense = PackGetInt(p, "NumClientConnectLicense");
+ t->NumBridgeConnectLicense = PackGetInt(p, "NumBridgeConnectLicense");
+
+ // v3.0
+ t->NeedSubscription = PackGetBool(p, "NeedSubscription");
+ t->AllowEnterpriseFunction = PackGetBool(p, "AllowEnterpriseFunction");
+ t->SubscriptionExpires = PackGetInt64(p, "SubscriptionExpires");
+ t->IsSubscriptionExpired = PackGetBool(p, "IsSubscriptionExpired");
+ t->NumUserCreationLicense = PackGetInt(p, "NumUserCreationLicense");
+ t->ReleaseDate = PackGetInt64(p, "ReleaseDate");
+}
+void OutRpcLicenseStatus(PACK *p, RPC_LICENSE_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "EditionId", t->EditionId);
+ PackAddStr(p, "EditionStr", t->EditionStr);
+ PackAddInt64(p, "SystemId", t->SystemId);
+ PackAddInt64(p, "SystemExpires", t->SystemExpires);
+ PackAddInt(p, "NumClientConnectLicense", t->NumClientConnectLicense);
+ PackAddInt(p, "NumBridgeConnectLicense", t->NumBridgeConnectLicense);
+
+ // v3.0
+ PackAddBool(p, "NeedSubscription", t->NeedSubscription);
+ PackAddBool(p, "AllowEnterpriseFunction", t->AllowEnterpriseFunction);
+ PackAddInt64(p, "SubscriptionExpires", t->SubscriptionExpires);
+ PackAddBool(p, "IsSubscriptionExpired", t->IsSubscriptionExpired);
+ PackAddInt(p, "NumUserCreationLicense", t->NumUserCreationLicense);
+ PackAddInt64(p, "ReleaseDate", t->ReleaseDate);
+}
+
+// RPC_ADMIN_OPTION
+void InRpcAdminOption(RPC_ADMIN_OPTION *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ADMIN_OPTION));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ADMIN_OPTION *o = &t->Items[i];
+
+ PackGetStrEx(p, "Name", o->Name, sizeof(o->Name), i);
+ o->Value = PackGetIntEx(p, "Value", i);
+ }
+}
+void OutRpcAdminOption(PACK *p, RPC_ADMIN_OPTION *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ ADMIN_OPTION *o = &t->Items[i];
+
+ PackAddStrEx(p, "Name", o->Name, i, t->NumItem);
+ PackAddIntEx(p, "Value", o->Value, i, t->NumItem);
+ }
+}
+void FreeRpcAdminOption(RPC_ADMIN_OPTION *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_CONFIG
+void InRpcConfig(RPC_CONFIG *t, PACK *p)
+{
+ UINT size;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_CONFIG));
+ PackGetStr(p, "FileName", t->FileName, sizeof(t->FileName));
+ size = PackGetDataSize(p, "FileData");
+ t->FileData = ZeroMalloc(size + 1);
+ PackGetData(p, "FileData", t->FileData);
+}
+void OutRpcConfig(PACK *p, RPC_CONFIG *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "FileName", t->FileName);
+ PackAddData(p, "FileData", t->FileData, StrLen(t->FileData));
+}
+void FreeRpcConfig(RPC_CONFIG *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->FileData);
+}
+
+// RPC_BRIDGE_SUPPORT
+void InRpcBridgeSupport(RPC_BRIDGE_SUPPORT *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_BRIDGE_SUPPORT));
+
+ t->IsBridgeSupportedOs = PackGetBool(p, "IsBridgeSupportedOs");
+ t->IsWinPcapNeeded = PackGetBool(p, "IsWinPcapNeeded");
+}
+void OutRpcBridgeSupport(PACK *p, RPC_BRIDGE_SUPPORT *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "IsBridgeSupportedOs", t->IsBridgeSupportedOs);
+ PackAddBool(p, "IsWinPcapNeeded",t->IsWinPcapNeeded);
+}
+
+// RPC_ADD_ACCESS
+void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ADD_ACCESS));
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ InRpcAccess(&t->Access, p);
+}
+void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ OutRpcAccess(p, &t->Access);
+}
+
+// RPC_DELETE_ACCESS
+void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_ACCESS));
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Id = PackGetInt(p, "Id");
+}
+void OutRpcDeleteAccess(PACK *p, RPC_DELETE_ACCESS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "Id", t->Id);
+}
+
+
+// RPC_SERVER_INFO
+void InRpcServerInfo(RPC_SERVER_INFO *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SERVER_INFO));
+
+ PackGetStr(p, "ServerProductName", t->ServerProductName, sizeof(t->ServerProductName));
+ PackGetStr(p, "ServerVersionString", t->ServerVersionString, sizeof(t->ServerVersionString));
+ PackGetStr(p, "ServerBuildInfoString", t->ServerBuildInfoString, sizeof(t->ServerBuildInfoString));
+ t->ServerVerInt = PackGetInt(p, "ServerVerInt");
+ t->ServerBuildInt = PackGetInt(p, "ServerBuildInt");
+ PackGetStr(p, "ServerHostName", t->ServerHostName, sizeof(t->ServerHostName));
+ t->ServerType = PackGetInt(p, "ServerType");
+ t->ServerBuildDate = PackGetInt64(p, "ServerBuildDate");
+ PackGetStr(p, "ServerFamilyName", t->ServerFamilyName, sizeof(t->ServerFamilyName));
+ InRpcOsInfo(&t->OsInfo, p);
+}
+void OutRpcServerInfo(PACK *p, RPC_SERVER_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "ServerProductName", t->ServerProductName);
+ PackAddStr(p, "ServerVersionString", t->ServerVersionString);
+ PackAddStr(p, "ServerBuildInfoString", t->ServerBuildInfoString);
+ PackAddInt(p, "ServerVerInt", t->ServerVerInt);
+ PackAddInt(p, "ServerBuildInt", t->ServerBuildInt);
+ PackAddStr(p, "ServerHostName", t->ServerHostName);
+ PackAddInt(p, "ServerType", t->ServerType);
+ PackAddInt64(p, "ServerBuildDate", t->ServerBuildDate);
+ PackAddStr(p, "ServerFamilyName", t->ServerFamilyName);
+ OutRpcOsInfo(p, &t->OsInfo);
+}
+void FreeRpcServerInfo(RPC_SERVER_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeRpcOsInfo(&t->OsInfo);
+}
+
+// RPC_SERVER_STATUS
+void InRpcServerStatus(RPC_SERVER_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SERVER_STATUS));
+ t->ServerType = PackGetInt(p, "ServerType");
+ t->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
+ t->NumTcpConnectionsLocal = PackGetInt(p, "NumTcpConnectionsLocal");
+ t->NumTcpConnectionsRemote = PackGetInt(p, "NumTcpConnectionsRemote");
+ t->NumHubTotal = PackGetInt(p, "NumHubTotal");
+ t->NumHubStandalone = PackGetInt(p, "NumHubStandalone");
+ t->NumHubStatic = PackGetInt(p, "NumHubStatic");
+ t->NumHubDynamic = PackGetInt(p, "NumHubDynamic");
+ t->NumSessionsTotal = PackGetInt(p, "NumSessionsTotal");
+ t->NumSessionsLocal = PackGetInt(p, "NumSessionsLocal");
+ t->NumSessionsRemote = PackGetInt(p, "NumSessionsRemote");
+ t->NumMacTables = PackGetInt(p, "NumMacTables");
+ t->NumIpTables = PackGetInt(p, "NumIpTables");
+ t->NumUsers = PackGetInt(p, "NumUsers");
+ t->NumGroups = PackGetInt(p, "NumGroups");
+ t->CurrentTime = PackGetInt64(p, "CurrentTime");
+ t->CurrentTick = PackGetInt64(p, "CurrentTick");
+ t->AssignedBridgeLicenses = PackGetInt(p, "AssignedBridgeLicenses");
+ t->AssignedClientLicenses = PackGetInt(p, "AssignedClientLicenses");
+ t->AssignedBridgeLicensesTotal = PackGetInt(p, "AssignedBridgeLicensesTotal");
+ t->AssignedClientLicensesTotal = PackGetInt(p, "AssignedClientLicensesTotal");
+ t->StartTime = PackGetInt64(p, "StartTime");
+
+ InRpcTraffic(&t->Traffic, p);
+
+ InRpcMemInfo(&t->MemInfo, p);
+}
+void OutRpcServerStatus(PACK *p, RPC_SERVER_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "ServerType", t->ServerType);
+ PackAddInt(p, "NumHubTotal", t->NumHubTotal);
+ PackAddInt(p, "NumHubStandalone", t->NumHubStandalone);
+ PackAddInt(p, "NumHubStatic", t->NumHubStatic);
+ PackAddInt(p, "NumHubDynamic", t->NumHubDynamic);
+ PackAddInt(p, "NumSessionsTotal", t->NumSessionsTotal);
+ PackAddInt(p, "NumSessionsLocal", t->NumSessionsLocal);
+ PackAddInt(p, "NumSessionsRemote", t->NumSessionsRemote);
+ PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);
+ PackAddInt(p, "NumTcpConnectionsLocal", t->NumTcpConnectionsLocal);
+ PackAddInt(p, "NumTcpConnectionsRemote", t->NumTcpConnectionsRemote);
+ PackAddInt(p, "NumMacTables", t->NumMacTables);
+ PackAddInt(p, "NumIpTables", t->NumIpTables);
+ PackAddInt(p, "NumUsers", t->NumUsers);
+ PackAddInt(p, "NumGroups", t->NumGroups);
+ PackAddInt64(p, "CurrentTime", t->CurrentTime);
+ PackAddInt64(p, "CurrentTick", t->CurrentTick);
+ PackAddInt(p, "AssignedBridgeLicenses", t->AssignedBridgeLicenses);
+ PackAddInt(p, "AssignedClientLicenses", t->AssignedClientLicenses);
+ PackAddInt(p, "AssignedBridgeLicensesTotal", t->AssignedBridgeLicensesTotal);
+ PackAddInt(p, "AssignedClientLicensesTotal", t->AssignedClientLicensesTotal);
+ PackAddInt64(p, "StartTime", t->StartTime);
+
+ OutRpcTraffic(p, &t->Traffic);
+
+ OutRpcMemInfo(p, &t->MemInfo);
+}
+
+// RPC_LISTENER
+void InRpcListener(RPC_LISTENER *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LISTENER));
+ t->Port = PackGetInt(p, "Port");
+ t->Enable = PackGetBool(p, "Enable");
+}
+void OutRpcListener(PACK *p, RPC_LISTENER *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "Port", t->Port);
+ PackAddBool(p, "Enable", t->Enable);
+}
+
+// RPC_LISTENER_LIST
+void InRpcListenerList(RPC_LISTENER_LIST *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LISTENER_LIST));
+ t->NumPort = PackGetIndexCount(p, "Ports");
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ t->Enables = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ t->Errors = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ for (i = 0;i < t->NumPort;i++)
+ {
+ t->Ports[i] = PackGetIntEx(p, "Ports", i);
+ t->Enables[i] = PackGetBoolEx(p, "Enables", i);
+ t->Errors[i] = PackGetBoolEx(p, "Errors", i);
+ }
+}
+void OutRpcListenerList(PACK *p, RPC_LISTENER_LIST *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumPort;i++)
+ {
+ PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);
+ PackAddBoolEx(p, "Enables", t->Enables[i], i, t->NumPort);
+ PackAddBoolEx(p, "Errors", t->Errors[i], i, t->NumPort);
+ }
+}
+void FreeRpcListenerList(RPC_LISTENER_LIST *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Ports);
+ Free(t->Enables);
+ Free(t->Errors);
+}
+
+// RPC_STR
+void InRpcStr(RPC_STR *t, PACK *p)
+{
+ UINT size = 65536;
+ char *tmp = Malloc(size);
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_STR));
+ if (PackGetStr(p, "String", tmp, size) == false)
+ {
+ t->String = CopyStr("");
+ }
+ else
+ {
+ t->String = CopyStr(tmp);
+ }
+ Free(tmp);
+}
+void OutRpcStr(PACK *p, RPC_STR *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "String", t->String);
+}
+void FreeRpcStr(RPC_STR *t)
+{
+ // Validate arguments
+ if (t == NULL )
+ {
+ return;
+ }
+
+ Free(t->String);
+}
+
+// RPC_SET_PASSWORD
+void InRpcSetPassword(RPC_SET_PASSWORD *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SET_PASSWORD));
+ PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+}
+void OutRpcSetPassword(PACK *p, RPC_SET_PASSWORD *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+}
+
+// RPC_FARM
+void InRpcFarm(RPC_FARM *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_FARM));
+ t->ServerType = PackGetInt(p, "ServerType");
+ t->NumPort = PackGetIndexCount(p, "Ports");
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ for (i = 0;i < t->NumPort;i++)
+ {
+ t->Ports[i] = PackGetIntEx(p, "Ports", i);
+ }
+ t->PublicIp = PackGetIp32(p, "PublicIp");
+ PackGetStr(p, "ControllerName", t->ControllerName, sizeof(t->ControllerName));
+ t->ControllerPort = PackGetInt(p, "ControllerPort");
+ PackGetData2(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));
+ t->Weight = PackGetInt(p, "Weight");
+ t->ControllerOnly = PackGetBool(p, "ControllerOnly");
+}
+void OutRpcFarm(PACK *p, RPC_FARM *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "ServerType", t->ServerType);
+ for (i = 0;i < t->NumPort;i++)
+ {
+ PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);
+ }
+ PackAddIp32(p, "PublicIp", t->PublicIp);
+ PackAddStr(p, "ControllerName", t->ControllerName);
+ PackAddInt(p, "ControllerPort", t->ControllerPort);
+ PackAddData(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));
+ PackAddInt(p, "Weight", t->Weight);
+ PackAddBool(p, "ControllerOnly", t->ControllerOnly);
+}
+void FreeRpcFarm(RPC_FARM *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Ports);
+}
+
+// RPC_FARM_HUB
+void InRpcFarmHub(RPC_FARM_HUB *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_FARM_HUB));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->DynamicHub = PackGetBool(p, "DynamicHub");
+}
+void OutRpcFarmHub(PACK *p, RPC_FARM_HUB *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddBool(p, "DynamicHub", t->DynamicHub);
+}
+
+// RPC_FARM_INFO
+void InRpcFarmInfo(RPC_FARM_INFO *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_FARM_INFO));
+ t->Id = PackGetInt(p, "Id");
+ t->Controller = PackGetBool(p, "Controller");
+ t->ConnectedTime = PackGetInt64(p, "ConnectedTime");
+ t->Ip = PackGetIp32(p, "Ip");
+ PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));
+ t->Point = PackGetInt(p, "Point");
+ t->NumPort = PackGetIndexCount(p, "Ports");
+ t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);
+ for (i = 0;i < t->NumPort;i++)
+ {
+ t->Ports[i] = PackGetIntEx(p, "Ports", i);
+ }
+ t->ServerCert = PackGetX(p, "ServerCert");
+ t->NumFarmHub = PackGetIndexCount(p, "HubName");
+ t->FarmHubs = ZeroMalloc(sizeof(RPC_FARM_HUB) * t->NumFarmHub);
+ for (i = 0;i < t->NumFarmHub;i++)
+ {
+ PackGetStrEx(p, "HubName", t->FarmHubs[i].HubName, sizeof(t->FarmHubs[i].HubName), i);
+ t->FarmHubs[i].DynamicHub = PackGetBoolEx(p, "DynamicHub", i);
+ }
+ t->NumSessions = PackGetInt(p, "NumSessions");
+ t->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
+ t->Weight = PackGetInt(p, "Weight");
+}
+void OutRpcFarmInfo(PACK *p, RPC_FARM_INFO *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "Id", t->Id);
+ PackAddBool(p, "Controller", t->Controller);
+ PackAddInt64(p, "ConnectedTime", t->ConnectedTime);
+ PackAddIp32(p, "Ip", t->Ip);
+ PackAddStr(p, "Hostname", t->Hostname);
+ PackAddInt(p, "Point", t->Point);
+ for (i = 0;i < t->NumPort;i++)
+ {
+ PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);
+ }
+ PackAddX(p, "ServerCert", t->ServerCert);
+ for (i = 0;i < t->NumFarmHub;i++)
+ {
+ PackAddStrEx(p, "HubName", t->FarmHubs[i].HubName, i, t->NumFarmHub);
+ PackAddBoolEx(p, "DynamicHub", t->FarmHubs[i].DynamicHub, i, t->NumFarmHub);
+ }
+ PackAddInt(p, "NumSessions", t->NumSessions);
+ PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);
+ PackAddInt(p, "Weight", t->Weight);
+}
+void FreeRpcFarmInfo(RPC_FARM_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Ports);
+ Free(t->FarmHubs);
+ FreeX(t->ServerCert);
+}
+
+void InRpcEnumFarm(RPC_ENUM_FARM *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_FARM));
+ t->NumFarm = PackGetIndexCount(p, "Id");
+ t->Farms = ZeroMalloc(sizeof(RPC_ENUM_FARM_ITEM) * t->NumFarm);
+
+ for (i = 0;i < t->NumFarm;i++)
+ {
+ RPC_ENUM_FARM_ITEM *e = &t->Farms[i];
+
+ e->Id = PackGetIntEx(p, "Id", i);
+ e->Controller = PackGetBoolEx(p, "Controller", i);
+ e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);
+ e->Ip = PackGetIp32Ex(p, "Ip", i);
+ PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
+ e->Point = PackGetIntEx(p, "Point", i);
+ e->NumSessions = PackGetIntEx(p, "NumSessions", i);
+ e->NumTcpConnections = PackGetIntEx(p, "NumTcpConnections", i);
+ e->NumHubs = PackGetIntEx(p, "NumHubs", i);
+ e->AssignedClientLicense = PackGetIntEx(p, "AssignedClientLicense", i);
+ e->AssignedBridgeLicense = PackGetIntEx(p, "AssignedBridgeLicense", i);
+ }
+}
+void OutRpcEnumFarm(PACK *p, RPC_ENUM_FARM *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumFarm;i++)
+ {
+ RPC_ENUM_FARM_ITEM *e = &t->Farms[i];
+
+ PackAddIntEx(p, "Id", e->Id, i, t->NumFarm);
+ PackAddBoolEx(p, "Controller", e->Controller, i, t->NumFarm);
+ PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumFarm);
+ PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumFarm);
+ PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumFarm);
+ PackAddIntEx(p, "Point", e->Point, i, t->NumFarm);
+ PackAddIntEx(p, "NumSessions", e->NumSessions, i, t->NumFarm);
+ PackAddIntEx(p, "NumTcpConnections", e->NumTcpConnections, i, t->NumFarm);
+ PackAddIntEx(p, "NumHubs", e->NumHubs, i, t->NumFarm);
+ PackAddIntEx(p, "AssignedClientLicense", e->AssignedClientLicense, i, t->NumFarm);
+ PackAddIntEx(p, "AssignedBridgeLicense", e->AssignedBridgeLicense, i, t->NumFarm);
+ }
+}
+void FreeRpcEnumFarm(RPC_ENUM_FARM *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Farms);
+}
+
+// RPC_FARM_CONNECTION_STATUS
+void InRpcFarmConnectionStatus(RPC_FARM_CONNECTION_STATUS *t, PACK *p)
+{
+ Zero(t, sizeof(RPC_FARM_CONNECTION_STATUS));
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ t->Ip = PackGetIp32(p, "Ip");
+ t->Port = PackGetInt(p, "Port");
+ t->Online = PackGetBool(p, "Online");
+ t->LastError = PackGetInt(p, "LastError");
+ t->StartedTime = PackGetInt64(p, "StartedTime");
+ t->CurrentConnectedTime = PackGetInt64(p, "CurrentConnectedTime");
+ t->FirstConnectedTime = PackGetInt64(p, "FirstConnectedTime");
+ t->NumConnected = PackGetInt(p, "NumConnected");
+ t->NumTry = PackGetInt(p, "NumTry");
+ t->NumFailed = PackGetInt(p, "NumFailed");
+}
+void OutRpcFarmConnectionStatus(PACK *p, RPC_FARM_CONNECTION_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddIp32(p, "Ip", t->Ip);
+ PackAddInt(p, "Port", t->Port);
+ PackAddBool(p, "Online", t->Online);
+ PackAddInt(p, "LastError", t->LastError);
+ PackAddInt64(p, "StartedTime", t->StartedTime);
+ PackAddInt64(p, "CurrentConnectedTime", t->CurrentConnectedTime);
+ PackAddInt64(p, "FirstConnectedTime", t->FirstConnectedTime);
+ PackAddInt(p, "NumConnected", t->NumConnected);
+ PackAddInt(p, "NumTry", t->NumTry);
+ PackAddInt(p, "NumFailed", t->NumFailed);
+}
+
+// RPC_HUB_OPTION
+void InRpcHubOption(RPC_HUB_OPTION *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_OPTION));
+ t->MaxSession = PackGetInt(p, "MaxSession");
+ t->NoEnum = PackGetBool(p, "NoEnum");
+}
+void OutRpcHubOption(PACK *p, RPC_HUB_OPTION *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "MaxSession", t->MaxSession);
+ PackAddBool(p, "NoEnum", t->NoEnum);
+}
+
+// RPC_RADIUS
+void InRpcRadius(RPC_RADIUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_RADIUS));
+ PackGetStr(p, "RadiusServerName", t->RadiusServerName, sizeof(t->RadiusServerName));
+ t->RadiusPort = PackGetInt(p, "RadiusPort");
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "RadiusSecret", t->RadiusSecret, sizeof(t->RadiusSecret));
+ t->RadiusRetryInterval = PackGetInt(p, "RadiusRetryInterval");
+}
+void OutRpcRadius(PACK *p, RPC_RADIUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "RadiusServerName", t->RadiusServerName);
+ PackAddInt(p, "RadiusPort", t->RadiusPort);
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "RadiusSecret", t->RadiusSecret);
+ PackAddInt(p, "RadiusRetryInterval", t->RadiusRetryInterval);
+}
+
+// RPC_HUB
+void InRpcHub(RPC_HUB *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+}
+void OutRpcHub(PACK *p, RPC_HUB *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+}
+
+// RPC_CREATE_HUB
+void InRpcCreateHub(RPC_CREATE_HUB *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_CREATE_HUB));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+ PackGetData2(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));
+ t->Online = PackGetBool(p, "Online");
+ InRpcHubOption(&t->HubOption, p);
+ t->HubType = PackGetInt(p, "HubType");
+}
+void OutRpcCreateHub(PACK *p, RPC_CREATE_HUB *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+ PackAddData(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));
+ PackAddBool(p, "Online", t->Online);
+ OutRpcHubOption(p, &t->HubOption);
+ PackAddInt(p, "HubType", t->HubType);
+}
+
+// RPC_ENUM_HUB
+void InRpcEnumHub(RPC_ENUM_HUB *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_HUB));
+ t->NumHub = PackGetIndexCount(p, "HubName");
+ t->Hubs = ZeroMalloc(sizeof(RPC_ENUM_HUB_ITEM) * t->NumHub);
+
+ for (i = 0;i < t->NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t->Hubs[i];
+
+ PackGetStrEx(p, "HubName", e->HubName, sizeof(e->HubName), i);
+ e->Online = PackGetBoolEx(p, "Online", i);
+ e->HubType = PackGetIntEx(p, "HubType", i);
+ e->NumSessions = PackGetIntEx(p, "NumSessions", i);
+ e->NumUsers = PackGetIntEx(p, "NumUsers", i);
+ e->NumGroups = PackGetIntEx(p, "NumGroups", i);
+ e->NumMacTables = PackGetIntEx(p, "NumMacTables", i);
+ e->NumIpTables = PackGetIntEx(p, "NumIpTables", i);
+ e->LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);
+ e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
+ e->LastLoginTime = PackGetInt64Ex(p, "LastLoginTime", i);
+ e->NumLogin = PackGetIntEx(p, "NumLogin", i);
+ e->IsTrafficFilled = PackGetBoolEx(p, "IsTrafficFilled", i);
+
+ InRpcTrafficEx(&e->Traffic, p, i);
+ }
+}
+void OutRpcEnumHub(PACK *p, RPC_ENUM_HUB *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t->Hubs[i];
+
+ PackAddStrEx(p, "HubName", e->HubName, i, t->NumHub);
+ PackAddBoolEx(p, "Online", e->Online, i, t->NumHub);
+ PackAddIntEx(p, "HubType", e->HubType, i, t->NumHub);
+ PackAddIntEx(p, "NumSessions", e->NumSessions, i, t->NumHub);
+ PackAddIntEx(p, "NumUsers", e->NumUsers, i, t->NumHub);
+ PackAddIntEx(p, "NumGroups", e->NumGroups, i, t->NumHub);
+ PackAddIntEx(p, "NumMacTables", e->NumMacTables, i, t->NumHub);
+ PackAddIntEx(p, "NumIpTables", e->NumIpTables, i, t->NumHub);
+ PackAddInt64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumHub);
+ PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumHub);
+ PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumHub);
+ PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumHub);
+ PackAddBoolEx(p, "IsTrafficFilled", e->IsTrafficFilled, i, t->NumHub);
+
+ OutRpcTrafficEx(&e->Traffic, p, i, t->NumHub);
+ }
+}
+void FreeRpcEnumHub(RPC_ENUM_HUB *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Hubs);
+}
+
+// RPC_DELETE_HUB
+void InRpcDeleteHub(RPC_DELETE_HUB *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_HUB));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+}
+void OutRpcDeleteHub(PACK *p, RPC_DELETE_HUB *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+}
+
+// RPC_ENUM_CONNECTION
+void InRpcEnumConnection(RPC_ENUM_CONNECTION *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_CONNECTION));
+ t->NumConnection = PackGetIndexCount(p, "Name");
+ t->Connections = ZeroMalloc(sizeof(RPC_ENUM_CONNECTION_ITEM) * t->NumConnection);
+
+ for (i = 0;i < t->NumConnection;i++)
+ {
+ RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];
+
+ e->Ip = PackGetIp32Ex(p, "Ip", i);
+ e->Port = PackGetIntEx(p, "Port", i);
+ PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);
+ PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
+ e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);
+ e->Type = PackGetIntEx(p, "Type", i);
+ }
+}
+void OutRpcEnumConnection(PACK *p, RPC_ENUM_CONNECTION *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumConnection;i++)
+ {
+ RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];
+
+ PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumConnection);
+ PackAddIntEx(p, "Port", e->Port, i, t->NumConnection);
+ PackAddStrEx(p, "Name", e->Name, i, t->NumConnection);
+ PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumConnection);
+ PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumConnection);
+ PackAddIntEx(p, "Type", e->Type, i, t->NumConnection);
+ }
+}
+void FreeRpcEnumConnetion(RPC_ENUM_CONNECTION *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Connections);
+}
+
+// RPC_DISCONNECT_CONNECTION
+void InRpcDisconnectConnection(RPC_DISCONNECT_CONNECTION *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DISCONNECT_CONNECTION));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+}
+void OutRpcDisconnectConnection(PACK *p, RPC_DISCONNECT_CONNECTION *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Name", t->Name);
+}
+
+// RPC_CONNECTION_INFO
+void InRpcConnectionInfo(RPC_CONNECTION_INFO *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_CONNECTION_INFO));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ t->Ip = PackGetIp32(p, "Ip");
+ t->Port = PackGetInt(p, "Port");
+ t->ConnectedTime = PackGetInt64(p, "ConnectedTime");
+ PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));
+ PackGetStr(p, "ServerStr", t->ServerStr, sizeof(t->ServerStr));
+ PackGetStr(p, "ClientStr", t->ClientStr, sizeof(t->ClientStr));
+ t->ServerVer = PackGetInt(p, "ServerVer");
+ t->ServerBuild = PackGetInt(p, "ServerBuild");
+ t->ClientVer = PackGetInt(p, "ClientVer");
+ t->ClientBuild = PackGetInt(p, "ClientBuild");
+ t->Type = PackGetInt(p, "Type");
+}
+void OutRpcConnectionInfo(PACK *p, RPC_CONNECTION_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Name", t->Name);
+ PackAddIp32(p, "Ip", t->Ip);
+ PackAddInt(p, "Port", t->Port);
+ PackAddInt64(p, "ConnectedTime", t->ConnectedTime);
+ PackAddStr(p, "Hostname", t->Hostname);
+ PackAddStr(p, "ServerStr", t->ServerStr);
+ PackAddStr(p, "ClientStr", t->ClientStr);
+ PackAddInt(p, "ServerVer", t->ServerVer);
+ PackAddInt(p, "ServerBuild", t->ServerBuild);
+ PackAddInt(p, "ClientVer", t->ClientVer);
+ PackAddInt(p, "ClientBuild", t->ClientBuild);
+ PackAddInt(p, "Type", t->Type);
+}
+
+// RPC_SET_HUB_ONLINE
+void InRpcSetHubOnline(RPC_SET_HUB_ONLINE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SET_HUB_ONLINE));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Online = PackGetBool(p, "Online");
+}
+void OutRpcSetHubOnline(PACK *p, RPC_SET_HUB_ONLINE *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddBool(p, "Online", t->Online);
+}
+
+// RPC_HUB_STATUS
+void InRpcHubStatus(RPC_HUB_STATUS *t, PACK *p)
+{
+ Zero(t, sizeof(RPC_HUB_STATUS));
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Online = PackGetBool(p, "Online");
+ t->HubType = PackGetInt(p, "HubType");
+ t->NumSessions = PackGetInt(p, "NumSessions");
+ t->NumSessionsClient = PackGetInt(p, "NumSessionsClient");
+ t->NumSessionsBridge = PackGetInt(p, "NumSessionsBridge");
+ t->NumAccessLists = PackGetInt(p, "NumAccessLists");
+ t->NumUsers = PackGetInt(p, "NumUsers");
+ t->NumGroups = PackGetInt(p, "NumGroups");
+ t->NumMacTables = PackGetInt(p, "NumMacTables");
+ t->NumIpTables = PackGetInt(p, "NumIpTables");
+ t->SecureNATEnabled = PackGetBool(p, "SecureNATEnabled");
+ InRpcTraffic(&t->Traffic, p);
+ t->LastCommTime = PackGetInt64(p, "LastCommTime");
+ t->CreatedTime = PackGetInt64(p, "CreatedTime");
+ t->LastLoginTime = PackGetInt64(p, "LastLoginTime");
+ t->NumLogin = PackGetInt(p, "NumLogin");
+}
+void OutRpcHubStatus(PACK *p, RPC_HUB_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddBool(p, "Online", t->Online);
+ PackAddInt(p, "HubType", t->HubType);
+ PackAddInt(p, "NumSessions", t->NumSessions);
+ PackAddInt(p, "NumSessionsClient", t->NumSessionsClient);
+ PackAddInt(p, "NumSessionsBridge", t->NumSessionsBridge);
+ PackAddInt(p, "NumAccessLists", t->NumAccessLists);
+ PackAddInt(p, "NumUsers", t->NumUsers);
+ PackAddInt(p, "NumGroups", t->NumGroups);
+ PackAddInt(p, "NumMacTables", t->NumMacTables);
+ PackAddInt(p, "NumIpTables", t->NumIpTables);
+ PackAddBool(p, "SecureNATEnabled", t->SecureNATEnabled);
+ OutRpcTraffic(p, &t->Traffic);
+ PackAddInt64(p, "LastCommTime", t->LastCommTime);
+ PackAddInt64(p, "CreatedTime", t->CreatedTime);
+ PackAddInt64(p, "LastLoginTime", t->LastLoginTime);
+ PackAddInt(p, "NumLogin", t->NumLogin);
+}
+
+// RPC_HUB_LOG
+void InRpcHubLog(RPC_HUB_LOG *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_LOG));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->LogSetting.SaveSecurityLog = PackGetBool(p, "SaveSecurityLog");
+ t->LogSetting.SecurityLogSwitchType = PackGetInt(p, "SecurityLogSwitchType");
+ t->LogSetting.SavePacketLog = PackGetBool(p, "SavePacketLog");
+ t->LogSetting.PacketLogSwitchType = PackGetInt(p, "PacketLogSwitchType");
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ t->LogSetting.PacketLogConfig[i] = PackGetIntEx(p, "PacketLogConfig", i);
+ }
+}
+void OutRpcHubLog(PACK *p, RPC_HUB_LOG *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddBool(p, "SaveSecurityLog", t->LogSetting.SaveSecurityLog);
+ PackAddInt(p, "SecurityLogSwitchType", t->LogSetting.SecurityLogSwitchType);
+ PackAddBool(p, "SavePacketLog", t->LogSetting.SavePacketLog);
+ PackAddInt(p, "PacketLogSwitchType", t->LogSetting.PacketLogSwitchType);
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ PackAddIntEx(p, "PacketLogConfig", t->LogSetting.PacketLogConfig[i], i, NUM_PACKET_LOG);
+ }
+}
+
+// RPC_HUB_ADD_CA
+void InRpcHubAddCa(RPC_HUB_ADD_CA *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_ADD_CA));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Cert = PackGetX(p, "Cert");
+}
+void OutRpcHubAddCa(PACK *p, RPC_HUB_ADD_CA *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddX(p, "Cert", t->Cert);
+}
+void FreeRpcHubAddCa(RPC_HUB_ADD_CA *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeX(t->Cert);
+}
+
+// RPC_HUB_ENUM_CA
+void InRpcHubEnumCa(RPC_HUB_ENUM_CA *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_ENUM_CA));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumCa = PackGetIndexCount(p, "Key");
+ t->Ca = ZeroMalloc(sizeof(RPC_HUB_ENUM_CA_ITEM) * t->NumCa);
+
+ for (i = 0;i < t->NumCa;i++)
+ {
+ RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];
+
+ e->Key = PackGetIntEx(p, "Key", i);
+ PackGetUniStrEx(p, "SubjectName", e->SubjectName, sizeof(e->SubjectName), i);
+ PackGetUniStrEx(p, "IssuerName", e->IssuerName, sizeof(e->IssuerName), i);
+ e->Expires = PackGetInt64Ex(p, "Expires", i);
+ }
+}
+void OutRpcHubEnumCa(PACK *p, RPC_HUB_ENUM_CA *t)
+{
+ UINT i;
+ PackAddStr(p, "HubName", t->HubName);
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumCa;i++)
+ {
+ RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];
+
+ PackAddIntEx(p, "Key", e->Key, i, t->NumCa);
+ PackAddUniStrEx(p, "SubjectName", e->SubjectName, i, t->NumCa);
+ PackAddUniStrEx(p, "IssuerName", e->IssuerName, i, t->NumCa);
+ PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumCa);
+ }
+}
+void FreeRpcHubEnumCa(RPC_HUB_ENUM_CA *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Ca);
+}
+
+// RPC_HUB_GET_CA
+void InRpcHubGetCa(RPC_HUB_GET_CA *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_GET_CA));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Key = PackGetInt(p, "Key");
+ t->Cert = PackGetX(p, "Cert");
+}
+void OutRpcHubGetCa(PACK *p, RPC_HUB_GET_CA *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "Key", t->Key);
+ PackAddX(p, "Cert", t->Cert);
+}
+void FreeRpcHubGetCa(RPC_HUB_GET_CA *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeX(t->Cert);
+}
+
+// RPC_HUB_DELETE_CA
+void InRpcHubDeleteCa(RPC_HUB_DELETE_CA *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_HUB_DELETE_CA));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Key = PackGetInt(p, "Key");
+}
+void OutRpcHubDeleteCa(PACK *p, RPC_HUB_DELETE_CA *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "Key", t->Key);
+}
+
+// RPC_CREATE_LINK
+void InRpcCreateLink(RPC_CREATE_LINK *t, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_CREATE_LINK));
+ PackGetStr(p, "HubName_Ex", t->HubName, sizeof(t->HubName));
+ t->Online = PackGetBool(p, "Online");
+ t->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ InRpcClientOption(t->ClientOption, p);
+ t->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+ InRpcClientAuth(t->ClientAuth, p);
+ InRpcPolicy(&t->Policy, p);
+
+ t->CheckServerCert = PackGetBool(p, "CheckServerCert");
+ b = PackGetBuf(p, "ServerCert");
+ if (b != NULL)
+ {
+ t->ServerCert = BufToX(b, false);
+ FreeBuf(b);
+ }
+}
+void OutRpcCreateLink(PACK *p, RPC_CREATE_LINK *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName_Ex",t->HubName);
+ PackAddBool(p, "Online", t->Online);
+ OutRpcClientOption(p, t->ClientOption);
+ OutRpcClientAuth(p, t->ClientAuth);
+ OutRpcPolicy(p, &t->Policy);
+
+ PackAddBool(p, "CheckServerCert", t->CheckServerCert);
+ if (t->ServerCert != NULL)
+ {
+ BUF *b;
+ b = XToBuf(t->ServerCert, false);
+ PackAddBuf(p, "ServerCert", b);
+ FreeBuf(b);
+ }
+}
+void FreeRpcCreateLink(RPC_CREATE_LINK *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->ServerCert != NULL)
+ {
+ FreeX(t->ServerCert);
+ }
+ Free(t->ClientOption);
+ CiFreeClientAuth(t->ClientAuth);
+}
+
+// RPC_ENUM_LINK
+void InRpcEnumLink(RPC_ENUM_LINK *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_LINK));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumLink = PackGetIndexCount(p, "AccountName");
+ t->Links = ZeroMalloc(sizeof(RPC_ENUM_LINK_ITEM) * t->NumLink);
+
+ for (i = 0;i < t->NumLink;i++)
+ {
+ RPC_ENUM_LINK_ITEM *e = &t->Links[i];
+
+ PackGetUniStrEx(p, "AccountName", e->AccountName, sizeof(e->AccountName), i);
+ PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
+ PackGetStrEx(p, "ConnectedHubName", e->HubName, sizeof(e->HubName), i);
+ e->Online = PackGetBoolEx(p, "Online", i);
+ e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);
+ e->Connected = PackGetBoolEx(p, "Connected", i);
+ e->LastError = PackGetIntEx(p, "LastError", i);
+ }
+}
+void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumLink;i++)
+ {
+ RPC_ENUM_LINK_ITEM *e = &t->Links[i];
+
+ PackAddUniStrEx(p, "AccountName", e->AccountName, i, t->NumLink);
+ PackAddStrEx(p, "ConnectedHubName", e->HubName, i, t->NumLink);
+ PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumLink);
+ PackAddBoolEx(p, "Online", e->Online, i, t->NumLink);
+ PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumLink);
+ PackAddBoolEx(p, "Connected", e->Connected, i, t->NumLink);
+ PackAddIntEx(p, "LastError", e->LastError, i, t->NumLink);
+ }
+}
+void FreeRpcEnumLink(RPC_ENUM_LINK *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Links);
+}
+
+// RPC_LINK_STATUS
+void InRpcLinkStatus(RPC_LINK_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LINK_STATUS));
+ PackGetStr(p, "HubName_Ex", t->HubName, sizeof(t->HubName));
+ PackGetUniStr(p, "AccountName", t->AccountName, sizeof(t->AccountName));
+ InRpcClientGetConnectionStatus(&t->Status, p);
+}
+void OutRpcLinkStatus(PACK *p, RPC_LINK_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName_Ex", t->HubName);
+ PackAddUniStr(p, "AccountName", t->AccountName);
+ OutRpcClientGetConnectionStatus(p, &t->Status);
+}
+void FreeRpcLinkStatus(RPC_LINK_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ CiFreeClientGetConnectionStatus(&t->Status);
+}
+
+// RPC_LINK
+void InRpcLink(RPC_LINK *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_LINK));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetUniStr(p, "AccountName", t->AccountName, sizeof(t->AccountName));
+}
+void OutRpcLink(PACK *p, RPC_LINK *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddUniStr(p, "AccountName", t->AccountName);
+}
+
+// RPC_RENAME_LINK
+void InRpcRenameLink(RPC_RENAME_LINK *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_RENAME_LINK));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetUniStr(p, "OldAccountName", t->OldAccountName, sizeof(t->OldAccountName));
+ PackGetUniStr(p, "NewAccountName", t->NewAccountName, sizeof(t->NewAccountName));
+}
+void OutRpcRenameLink(PACK *p, RPC_RENAME_LINK *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddUniStr(p, "OldAccountName", t->OldAccountName);
+ PackAddUniStr(p, "NewAccountName", t->NewAccountName);
+}
+
+// ACCESS
+void InRpcAccessEx(ACCESS *a, PACK *p, UINT index)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(a, sizeof(ACCESS));
+ a->Id = PackGetIntEx(p, "Id", index);
+ PackGetUniStrEx(p, "Note", a->Note, sizeof(a->Note), index);
+ a->Active = PackGetBoolEx(p, "Active", index);
+ a->Priority = PackGetIntEx(p, "Priority", index);
+ a->Discard = PackGetBoolEx(p, "Discard", index);
+ a->SrcIpAddress = PackGetIp32Ex(p, "SrcIpAddress", index);
+ a->SrcSubnetMask = PackGetIp32Ex(p, "SrcSubnetMask", index);
+ a->DestIpAddress = PackGetIp32Ex(p, "DestIpAddress", index);
+ a->DestSubnetMask = PackGetIp32Ex(p, "DestSubnetMask", index);
+ a->Protocol = PackGetIntEx(p, "Protocol", index);
+ a->SrcPortStart = PackGetIntEx(p, "SrcPortStart", index);
+ a->SrcPortEnd = PackGetIntEx(p, "SrcPortEnd", index);
+ a->DestPortStart = PackGetIntEx(p, "DestPortStart", index);
+ a->DestPortEnd = PackGetIntEx(p, "DestPortEnd", index);
+ //a->SrcUsernameHash = PackGetIntEx(p, "SrcUsernameHash", index);
+ PackGetStrEx(p, "SrcUsername", a->SrcUsername, sizeof(a->SrcUsername), index);
+ //a->DestUsernameHash = PackGetIntEx(p, "DestUsernameHash", index);
+ PackGetStrEx(p, "DestUsername", a->DestUsername, sizeof(a->DestUsername), index);
+ a->CheckSrcMac = PackGetBoolEx(p, "CheckSrcMac", index);
+ PackGetDataEx2(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), index);
+ PackGetDataEx2(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), index);
+ a->CheckDstMac = PackGetBoolEx(p, "CheckDstMac", index);
+ PackGetDataEx2(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), index);
+ PackGetDataEx2(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), index);
+ a->CheckTcpState = PackGetBoolEx(p, "CheckTcpState", index);
+ a->Established = PackGetBoolEx(p, "Established", index);
+ a->Delay = PackGetIntEx(p, "Delay", index);
+ a->Jitter = PackGetIntEx(p, "Jitter", index);
+ a->Loss = PackGetIntEx(p, "Loss", index);
+ a->IsIPv6 = PackGetBoolEx(p, "IsIPv6", index);
+ a->UniqueId = PackGetIntEx(p, "UniqueId", index);
+ PackGetStrEx(p, "RedirectUrl", a->RedirectUrl, sizeof(a->RedirectUrl), index);
+ if (a->IsIPv6)
+ {
+ PackGetIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, index);
+ PackGetIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, index);
+ PackGetIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, index);
+ PackGetIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, index);
+ }
+}
+void InRpcAccess(ACCESS *a, PACK *p)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ InRpcAccessEx(a, p, 0);
+}
+void OutRpcAccessEx(PACK *p, ACCESS *a, UINT index, UINT total)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddIntEx(p, "Id", a->Id, index, total);
+ PackAddUniStrEx(p, "Note", a->Note, index, total);
+ PackAddBoolEx(p, "Active", a->Active, index, total);
+ PackAddIntEx(p, "Priority", a->Priority, index, total);
+ PackAddBoolEx(p, "Discard", a->Discard, index, total);
+ if (a->IsIPv6)
+ {
+ PackAddIp32Ex(p, "SrcIpAddress", 0xFDFFFFDF, index, total);
+ PackAddIp32Ex(p, "SrcSubnetMask", 0xFFFFFFFF, index, total);
+ PackAddIp32Ex(p, "DestIpAddress", 0xFDFFFFDF, index, total);
+ PackAddIp32Ex(p, "DestSubnetMask", 0xFFFFFFFF, index, total);
+ }
+ else
+ {
+ PackAddIp32Ex(p, "SrcIpAddress", a->SrcIpAddress, index, total);
+ PackAddIp32Ex(p, "SrcSubnetMask", a->SrcSubnetMask, index, total);
+ PackAddIp32Ex(p, "DestIpAddress", a->DestIpAddress, index, total);
+ PackAddIp32Ex(p, "DestSubnetMask", a->DestSubnetMask, index, total);
+ }
+ PackAddIntEx(p, "Protocol", a->Protocol, index, total);
+ PackAddIntEx(p, "SrcPortStart", a->SrcPortStart, index, total);
+ PackAddIntEx(p, "SrcPortEnd", a->SrcPortEnd, index, total);
+ PackAddIntEx(p, "DestPortStart", a->DestPortStart, index, total);
+ PackAddIntEx(p, "DestPortEnd", a->DestPortEnd, index, total);
+ //PackAddIntEx(p, "SrcUsernameHash", a->SrcUsernameHash, index, total);
+ PackAddStrEx(p, "SrcUsername", a->SrcUsername, index, total);
+ //PackAddIntEx(p, "DestUsernameHash", a->DestUsernameHash, index, total);
+ PackAddStrEx(p, "DestUsername", a->DestUsername, index, total);
+ PackAddBoolEx(p, "CheckSrcMac", a->CheckSrcMac, index, total);
+ PackAddDataEx(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), index, total);
+ PackAddDataEx(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), index, total);
+ PackAddBoolEx(p, "CheckDstMac", a->CheckDstMac, index, total);
+ PackAddDataEx(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), index, total);
+ PackAddDataEx(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), index, total);
+ PackAddBoolEx(p, "CheckTcpState", a->CheckTcpState, index, total);
+ PackAddBoolEx(p, "Established", a->Established, index, total);
+ PackAddIntEx(p, "Delay", a->Delay, index, total);
+ PackAddIntEx(p, "Jitter", a->Jitter, index, total);
+ PackAddIntEx(p, "Loss", a->Loss, index, total);
+ PackAddBoolEx(p, "IsIPv6", a->IsIPv6, index, total);
+ PackAddIntEx(p, "UniqueId", a->UniqueId, index, total);
+ PackAddStrEx(p, "RedirectUrl", a->RedirectUrl, index, total);
+ if (a->IsIPv6)
+ {
+ PackAddIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, index, total);
+ PackAddIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, index, total);
+ PackAddIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, index, total);
+ PackAddIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, index, total);
+ }
+ else
+ {
+ IPV6_ADDR zero;
+
+ Zero(&zero, sizeof(zero));
+
+ PackAddIp6AddrEx(p, "SrcIpAddress6", &zero, index, total);
+ PackAddIp6AddrEx(p, "SrcSubnetMask6", &zero, index, total);
+ PackAddIp6AddrEx(p, "DestIpAddress6", &zero, index, total);
+ PackAddIp6AddrEx(p, "DestSubnetMask6", &zero, index, total);
+ }
+}
+void OutRpcAccess(PACK *p, ACCESS *a)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ OutRpcAccessEx(p, a, 0, 1);
+}
+
+// RPC_ENUM_ACCESS_LIST
+void InRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(a, sizeof(RPC_ENUM_ACCESS_LIST));
+ PackGetStr(p, "HubName", a->HubName, sizeof(a->HubName));
+ a->NumAccess = PackGetIndexCount(p, "Protocol");
+ a->Accesses = ZeroMalloc(sizeof(ACCESS) * a->NumAccess);
+
+ for (i = 0;i < a->NumAccess;i++)
+ {
+ ACCESS *e = &a->Accesses[i];
+
+ InRpcAccessEx(e, p, i);
+ }
+}
+void OutRpcEnumAccessList(PACK *p, RPC_ENUM_ACCESS_LIST *a)
+{
+ UINT i;
+ PackAddStr(p, "HubName", a->HubName);
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < a->NumAccess;i++)
+ {
+ ACCESS *e = &a->Accesses[i];
+
+ OutRpcAccessEx(p, e, i, a->NumAccess);
+ }
+}
+void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Free(a->Accesses);
+}
+
+// AUTHDATA
+void *InRpcAuthData(PACK *p, UINT *authtype)
+{
+ wchar_t tmp[MAX_SIZE];
+ AUTHPASSWORD *pw;
+ AUTHUSERCERT *usercert;
+ AUTHROOTCERT *rootcert;
+ AUTHRADIUS *radius;
+ AUTHNT *nt;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+ if (authtype == NULL)
+ {
+ return NULL;
+ }
+
+ *authtype = PackGetInt(p, "AuthType");
+
+ switch (*authtype)
+ {
+ case AUTHTYPE_PASSWORD:
+ pw = ZeroMalloc(sizeof(AUTHPASSWORD));
+ PackGetData2(p, "HashedKey", pw->HashedKey, sizeof(pw->HashedKey));
+ PackGetData2(p, "NtLmSecureHash", pw->NtLmSecureHash, sizeof(pw->NtLmSecureHash));
+ return pw;
+
+ case AUTHTYPE_USERCERT:
+ usercert = ZeroMalloc(sizeof(AUTHUSERCERT));
+ usercert->UserX = PackGetX(p, "UserX");
+ return usercert;
+
+ case AUTHTYPE_ROOTCERT:
+ rootcert = ZeroMalloc(sizeof(AUTHROOTCERT));
+ b = PackGetBuf(p, "Serial");
+ if (b != NULL)
+ {
+ rootcert->Serial = NewXSerial(b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ if (PackGetUniStr(p, "CommonName", tmp, sizeof(tmp)))
+ {
+ rootcert->CommonName = CopyUniStr(tmp);
+ }
+ return rootcert;
+
+ case AUTHTYPE_RADIUS:
+ radius = ZeroMalloc(sizeof(AUTHRADIUS));
+ if (PackGetUniStr(p, "RadiusUsername", tmp, sizeof(tmp)))
+ {
+ radius->RadiusUsername = CopyUniStr(tmp);
+ }
+ else
+ {
+ radius->RadiusUsername = CopyUniStr(L"");
+ }
+ return radius;
+
+ case AUTHTYPE_NT:
+ nt = ZeroMalloc(sizeof(AUTHNT));
+ if (PackGetUniStr(p, "NtUsername", tmp, sizeof(tmp)))
+ {
+ nt->NtUsername = CopyUniStr(tmp);
+ }
+ else
+ {
+ nt->NtUsername = CopyUniStr(L"");
+ }
+ return nt;
+ }
+
+ return NULL;
+}
+void OutRpcAuthData(PACK *p, void *authdata, UINT authtype)
+{
+ AUTHPASSWORD *pw = authdata;
+ AUTHUSERCERT *usercert = authdata;
+ AUTHROOTCERT *rootcert = authdata;
+ AUTHRADIUS *radius = authdata;
+ AUTHNT *nt = authdata;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "AuthType", authtype);
+
+ switch (authtype)
+ {
+ case AUTHTYPE_PASSWORD:
+ PackAddData(p, "HashedKey", pw->HashedKey, sizeof(pw->HashedKey));
+ PackAddData(p, "NtLmSecureHash", pw->NtLmSecureHash, sizeof(pw->NtLmSecureHash));
+ break;
+
+ case AUTHTYPE_USERCERT:
+ PackAddX(p, "UserX", usercert->UserX);
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ if (rootcert->Serial != NULL)
+ {
+ PackAddData(p, "Serial", rootcert->Serial->data, rootcert->Serial->size);
+ }
+ if (rootcert->CommonName != NULL)
+ {
+ PackAddUniStr(p, "CommonName", rootcert->CommonName);
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ PackAddUniStr(p, "RadiusUsername", radius->RadiusUsername);
+ break;
+
+ case AUTHTYPE_NT:
+ PackAddUniStr(p, "NtUsername", nt->NtUsername);
+ break;
+ }
+}
+void FreeRpcAuthData(void *authdata, UINT authtype)
+{
+ FreeAuthData(authtype, authdata);
+}
+
+// RPC_SET_USER
+void InRpcSetUser(RPC_SET_USER *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SET_USER));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ PackGetStr(p, "GroupName", t->GroupName, sizeof(t->GroupName));
+ PackGetUniStr(p, "Realname", t->Realname, sizeof(t->Realname));
+ PackGetUniStr(p, "Note", t->Note, sizeof(t->Note));
+ t->CreatedTime = PackGetInt64(p, "CreatedTime");
+ t->UpdatedTime = PackGetInt64(p, "UpdatedTime");
+ t->ExpireTime = PackGetInt64(p, "ExpireTime");
+ t->AuthData = InRpcAuthData(p, &t->AuthType);
+ t->NumLogin = PackGetInt(p, "NumLogin");
+ InRpcTraffic(&t->Traffic, p);
+
+ if (PackGetBool(p, "UsePolicy"))
+ {
+ t->Policy = ZeroMalloc(sizeof(POLICY));
+ InRpcPolicy(t->Policy, p);
+ }
+}
+
+void OutRpcSetUser(PACK *p, RPC_SET_USER *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "Name", t->Name);
+ PackAddStr(p, "GroupName", t->GroupName);
+ PackAddUniStr(p, "Realname", t->Realname);
+ PackAddUniStr(p, "Note", t->Note);
+ PackAddInt64(p, "CreatedTime", t->CreatedTime);
+ PackAddInt64(p, "UpdatedTime", t->UpdatedTime);
+ PackAddInt64(p, "ExpireTime", t->ExpireTime);
+ OutRpcAuthData(p, t->AuthData, t->AuthType);
+ PackAddInt(p, "NumLogin", t->NumLogin);
+ OutRpcTraffic(p, &t->Traffic);
+
+ if (t->Policy != NULL)
+ {
+ PackAddBool(p, "UsePolicy", true);
+ OutRpcPolicy(p, t->Policy);
+ }
+}
+void FreeRpcSetUser(RPC_SET_USER *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeRpcAuthData(t->AuthData, t->AuthType);
+ if (t->Policy)
+ {
+ Free(t->Policy);
+ }
+}
+
+// RPC_ENUM_USER
+void InRpcEnumUser(RPC_ENUM_USER *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_USER));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumUser = PackGetIndexCount(p, "Name");
+ t->Users = ZeroMalloc(sizeof(RPC_ENUM_USER_ITEM) * t->NumUser);
+
+ for (i = 0;i < t->NumUser;i++)
+ {
+ RPC_ENUM_USER_ITEM *e = &t->Users[i];
+
+ PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);
+ PackGetStrEx(p, "GroupName", e->GroupName, sizeof(e->GroupName), i);
+ PackGetUniStrEx(p, "Realname", e->Realname, sizeof(e->Realname), i);
+ PackGetUniStrEx(p, "Note", e->Note, sizeof(e->Note), i);
+ e->AuthType = PackGetIntEx(p, "AuthType", i);
+ e->LastLoginTime = PackGetInt64Ex(p, "LastLoginTime", i);
+ e->NumLogin = PackGetIntEx(p, "NumLogin", i);
+ e->DenyAccess = PackGetBoolEx(p, "DenyAccess", i);
+
+ e->IsTrafficFilled = PackGetBoolEx(p, "IsTrafficFilled", i);
+ InRpcTrafficEx(&e->Traffic, p, i);
+
+ e->IsExpiresFilled = PackGetBoolEx(p, "IsExpiresFilled", i);
+ e->Expires = PackGetInt64Ex(p, "Expires", i);
+ }
+}
+void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t)
+{
+ UINT i;
+ PackAddStr(p, "HubName", t->HubName);
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumUser;i++)
+ {
+ RPC_ENUM_USER_ITEM *e = &t->Users[i];
+
+ PackAddStrEx(p, "Name", e->Name, i, t->NumUser);
+ PackAddStrEx(p, "GroupName", e->GroupName, i, t->NumUser);
+ PackAddUniStrEx(p, "Realname", e->Realname, i, t->NumUser);
+ PackAddUniStrEx(p, "Note", e->Note, i, t->NumUser);
+ PackAddIntEx(p, "AuthType", e->AuthType, i, t->NumUser);
+ PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumUser);
+ PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumUser);
+ PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumUser);
+
+ PackAddBoolEx(p, "IsTrafficFilled", e->IsTrafficFilled, i, t->NumUser);
+ OutRpcTrafficEx(&e->Traffic, p, i, t->NumUser);
+
+ PackAddBoolEx(p, "IsExpiresFilled", e->IsExpiresFilled, i, t->NumUser);
+ PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumUser);
+ }
+}
+void FreeRpcEnumUser(RPC_ENUM_USER *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Users);
+}
+
+// RPC_SET_GROUP
+void InRpcSetGroup(RPC_SET_GROUP *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SET_GROUP));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ PackGetUniStr(p, "Realname", t->Realname, sizeof(t->Realname));
+ PackGetUniStr(p, "Note", t->Note, sizeof(t->Note));
+ InRpcTraffic(&t->Traffic, p);
+
+ if (PackGetBool(p, "UsePolicy"))
+ {
+ t->Policy = ZeroMalloc(sizeof(POLICY));
+ InRpcPolicy(t->Policy, p);
+ }
+}
+void OutRpcSetGroup(PACK *p, RPC_SET_GROUP *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "Name", t->Name);
+ PackAddUniStr(p, "Realname", t->Realname);
+ PackAddUniStr(p, "Note", t->Note);
+ OutRpcTraffic(p, &t->Traffic);
+
+ if (t->Policy != NULL)
+ {
+ PackAddBool(p, "UsePolicy", true);
+ OutRpcPolicy(p, t->Policy);
+ }
+}
+void FreeRpcSetGroup(RPC_SET_GROUP *t)
+{
+ Free(t->Policy);
+}
+
+// RPC_ENUM_GROUP
+void InRpcEnumGroup(RPC_ENUM_GROUP *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_GROUP));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumGroup = PackGetIndexCount(p, "Name");
+ t->Groups = ZeroMalloc(sizeof(RPC_ENUM_GROUP_ITEM) * t->NumGroup);
+
+ for (i = 0;i < t->NumGroup;i++)
+ {
+ RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];
+
+ PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);
+ PackGetUniStrEx(p, "Realname", e->Realname, sizeof(e->Realname), i);
+ PackGetUniStrEx(p, "Note", e->Note, sizeof(e->Note), i);
+ e->NumUsers = PackGetIntEx(p, "NumUsers", i);
+ e->DenyAccess = PackGetBoolEx(p, "DenyAccess", i);
+ }
+}
+void OutRpcEnumGroup(PACK *p, RPC_ENUM_GROUP *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumGroup;i++)
+ {
+ RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];
+
+ PackAddStrEx(p, "Name", e->Name, i, t->NumGroup);
+ PackAddUniStrEx(p, "Realname", e->Realname, i, t->NumGroup);
+ PackAddUniStrEx(p, "Note", e->Note, i, t->NumGroup);
+ PackAddIntEx(p, "NumUsers", e->NumUsers, i, t->NumGroup);
+ PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumGroup);
+ }
+}
+void FreeRpcEnumGroup(RPC_ENUM_GROUP *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Groups);
+}
+
+// RPC_DELETE_USER
+void InRpcDeleteUser(RPC_DELETE_USER *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_USER));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+}
+void OutRpcDeleteUser(PACK *p, RPC_DELETE_USER *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "Name", t->Name);
+}
+
+// RPC_ENUM_SESSION
+void InRpcEnumSession(RPC_ENUM_SESSION *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_SESSION));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumSession = PackGetIndexCount(p, "Name");
+ t->Sessions = ZeroMalloc(sizeof(RPC_ENUM_SESSION_ITEM) * t->NumSession);
+
+ for (i = 0;i < t->NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];
+
+ PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);
+ PackGetStrEx(p, "Username", e->Username, sizeof(e->Username), i);
+ e->Ip = PackGetIntEx(p, "Ip", i);
+ PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
+ e->MaxNumTcp = PackGetIntEx(p, "MaxNumTcp", i);
+ e->CurrentNumTcp = PackGetIntEx(p, "CurrentNumTcp", i);
+ e->PacketSize = PackGetInt64Ex(p, "PacketSize", i);
+ e->PacketNum = PackGetInt64Ex(p, "PacketNum", i);
+ e->RemoteSession = PackGetBoolEx(p, "RemoteSession", i);
+ e->LinkMode = PackGetBoolEx(p, "LinkMode", i);
+ e->SecureNATMode = PackGetBoolEx(p, "SecureNATMode", i);
+ e->BridgeMode = PackGetBoolEx(p, "BridgeMode", i);
+ e->Layer3Mode = PackGetBoolEx(p, "Layer3Mode", i);
+ e->Client_BridgeMode = PackGetBoolEx(p, "Client_BridgeMode", i);
+ e->Client_MonitorMode = PackGetBoolEx(p, "Client_MonitorMode", i);
+ PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);
+ e->VLanId = PackGetIntEx(p, "VLanId", i);
+ PackGetDataEx2(p, "UniqueId", e->UniqueId, sizeof(e->UniqueId), i);
+ }
+}
+void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)
+{
+ UINT i;
+ PackAddStr(p, "HubName", t->HubName);
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];
+
+ PackAddStrEx(p, "Name", e->Name, i, t->NumSession);
+ PackAddStrEx(p, "Username", e->Username, i, t->NumSession);
+ PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumSession);
+ PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumSession);
+ PackAddIntEx(p, "MaxNumTcp", e->MaxNumTcp, i, t->NumSession);
+ PackAddIntEx(p, "CurrentNumTcp", e->CurrentNumTcp, i, t->NumSession);
+ PackAddInt64Ex(p, "PacketSize", e->PacketSize, i, t->NumSession);
+ PackAddInt64Ex(p, "PacketNum", e->PacketNum, i, t->NumSession);
+ PackAddBoolEx(p, "RemoteSession", e->RemoteSession, i, t->NumSession);
+ PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumSession);
+ PackAddBoolEx(p, "LinkMode", e->LinkMode, i, t->NumSession);
+ PackAddBoolEx(p, "SecureNATMode", e->SecureNATMode, i, t->NumSession);
+ PackAddBoolEx(p, "BridgeMode", e->BridgeMode, i, t->NumSession);
+ PackAddBoolEx(p, "Layer3Mode", e->Layer3Mode, i, t->NumSession);
+ PackAddBoolEx(p, "Client_BridgeMode", e->Client_BridgeMode, i, t->NumSession);
+ PackAddBoolEx(p, "Client_MonitorMode", e->Client_MonitorMode, i, t->NumSession);
+ PackAddIntEx(p, "VLanId", e->VLanId, i, t->NumSession);
+ PackAddDataEx(p, "UniqueId", e->UniqueId, sizeof(e->UniqueId), i, t->NumSession);
+ }
+}
+void FreeRpcEnumSession(RPC_ENUM_SESSION *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Sessions);
+}
+
+// RPC_KEY_PAIR
+void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ t->Cert = PackGetX(p, "Cert");
+ t->Key = PackGetK(p, "Key");
+}
+void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddX(p, "Cert", t->Cert);
+ PackAddK(p, "Key", t->Key);
+}
+void FreeRpcKeyPair(RPC_KEY_PAIR *t)
+{
+ FreeX(t->Cert);
+ FreeK(t->Key);
+}
+
+// NODE_INFO
+void InRpcNodeInfo(NODE_INFO *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(NODE_INFO));
+ PackGetStr(p, "ClientProductName", t->ClientProductName, sizeof(t->ClientProductName));
+ PackGetStr(p, "ServerProductName", t->ServerProductName, sizeof(t->ServerProductName));
+ PackGetStr(p, "ClientOsName", t->ClientOsName, sizeof(t->ClientOsName));
+ PackGetStr(p, "ClientOsVer", t->ClientOsVer, sizeof(t->ClientOsVer));
+ PackGetStr(p, "ClientOsProductId", t->ClientOsProductId, sizeof(t->ClientOsProductId));
+ PackGetStr(p, "ClientHostname", t->ClientHostname, sizeof(t->ClientHostname));
+ PackGetStr(p, "ServerHostname", t->ServerHostname, sizeof(t->ServerHostname));
+ PackGetStr(p, "ProxyHostname", t->ProxyHostname, sizeof(t->ProxyHostname));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetData2(p, "UniqueId", t->UniqueId, sizeof(t->UniqueId));
+
+ t->ClientProductVer = PackGetInt(p, "ClientProductVer");
+ t->ClientProductBuild = PackGetInt(p, "ClientProductBuild");
+ t->ServerProductVer = PackGetInt(p, "ServerProductVer");
+ t->ServerProductBuild = PackGetInt(p, "ServerProductBuild");
+ t->ClientIpAddress = PackGetIp32(p, "ClientIpAddress");
+ PackGetData2(p, "ClientIpAddress6", t->ClientIpAddress6, sizeof(t->ClientIpAddress6));
+ t->ClientPort = PackGetInt(p, "ClientPort");
+ t->ServerIpAddress = PackGetIp32(p, "ServerIpAddress");
+ PackGetData2(p, "ServerIpAddress6", t->ServerIpAddress6, sizeof(t->ServerIpAddress6));
+ t->ServerPort = PackGetInt(p, "ServerPort2");
+ t->ProxyIpAddress = PackGetIp32(p, "ProxyIpAddress");
+ PackGetData2(p, "ProxyIpAddress6", t->ProxyIpAddress6, sizeof(t->ProxyIpAddress6));
+ t->ProxyPort = PackGetInt(p, "ProxyPort");
+}
+void OutRpcNodeInfo(PACK *p, NODE_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "ClientProductName", t->ClientProductName);
+ PackAddStr(p, "ServerProductName", t->ServerProductName);
+ PackAddStr(p, "ClientOsName", t->ClientOsName);
+ PackAddStr(p, "ClientOsVer", t->ClientOsVer);
+ PackAddStr(p, "ClientOsProductId", t->ClientOsProductId);
+ PackAddStr(p, "ClientHostname", t->ClientHostname);
+ PackAddStr(p, "ServerHostname", t->ServerHostname);
+ PackAddStr(p, "ProxyHostname", t->ProxyHostname);
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddData(p, "UniqueId", t->UniqueId, sizeof(t->UniqueId));
+
+ PackAddInt(p, "ClientProductVer", t->ClientProductVer);
+ PackAddInt(p, "ClientProductBuild", t->ClientProductBuild);
+ PackAddInt(p, "ServerProductVer", t->ServerProductVer);
+ PackAddInt(p, "ServerProductBuild", t->ServerProductBuild);
+ PackAddIp32(p, "ClientIpAddress", t->ClientIpAddress);
+ PackAddData(p, "ClientIpAddress6", t->ClientIpAddress6, sizeof(t->ClientIpAddress6));
+ PackAddInt(p, "ClientPort", t->ClientPort);
+ PackAddIp32(p, "ServerIpAddress", t->ServerIpAddress);
+ PackAddData(p, "ServerIpAddress6", t->ServerIpAddress6, sizeof(t->ServerIpAddress6));
+ PackAddInt(p, "ServerPort2", t->ServerPort);
+ PackAddIp32(p, "ProxyIpAddress", t->ProxyIpAddress);
+ PackAddData(p, "ProxyIpAddress6", t->ProxyIpAddress6, sizeof(t->ProxyIpAddress6));
+ PackAddInt(p, "ProxyPort", t->ProxyPort);
+}
+
+// RPC_SESSION_STATUS
+void InRpcSessionStatus(RPC_SESSION_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_SESSION_STATUS));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+ PackGetStr(p, "Username", t->Username, sizeof(t->Username));
+ PackGetStr(p, "GroupName", t->GroupName, sizeof(t->GroupName));
+ PackGetStr(p, "RealUsername", t->RealUsername, sizeof(t->RealUsername));
+ t->ClientIp = PackGetIp32(p, "SessionStatus_ClientIp");
+ PackGetData2(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));
+ PackGetStr(p, "SessionStatus_ClientHostName", t->ClientHostName, sizeof(t->ClientHostName));
+
+ InRpcClientGetConnectionStatus(&t->Status, p);
+ InRpcNodeInfo(&t->NodeInfo, p);
+}
+void OutRpcSessionStatus(PACK *p, RPC_SESSION_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "Name", t->Name);
+ PackAddStr(p, "Username", t->Username);
+ PackAddStr(p, "GroupName", t->GroupName);
+ PackAddStr(p, "RealUsername", t->RealUsername);
+ PackAddIp32(p, "SessionStatus_ClientIp", t->ClientIp);
+ PackAddData(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));
+ PackAddStr(p, "SessionStatus_ClientHostName", t->ClientHostName);
+
+ OutRpcClientGetConnectionStatus(p, &t->Status);
+ OutRpcNodeInfo(p, &t->NodeInfo);
+}
+void FreeRpcSessionStatus(RPC_SESSION_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ CiFreeClientGetConnectionStatus(&t->Status);
+}
+
+// RPC_DELETE_SESSION
+void InRpcDeleteSession(RPC_DELETE_SESSION *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_SESSION));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ PackGetStr(p, "Name", t->Name, sizeof(t->Name));
+}
+void OutRpcDeleteSession(PACK *p, RPC_DELETE_SESSION *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddStr(p, "Name", t->Name);
+}
+
+// RPC_ENUM_MAC_TABLE
+void InRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_MAC_TABLE));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumMacTable = PackGetIndexCount(p, "SessionName");
+ t->MacTables = ZeroMalloc(sizeof(RPC_ENUM_MAC_TABLE_ITEM) * t->NumMacTable);
+
+ for (i = 0;i < t->NumMacTable;i++)
+ {
+ RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];
+
+ e->Key = PackGetIntEx(p, "Key", i);
+ PackGetStrEx(p, "SessionName", e->SessionName, sizeof(e->SessionName), i);
+ PackGetDataEx2(p, "MacAddress", e->MacAddress, sizeof(e->MacAddress), i);
+ e->VlanId = PackGetIntEx(p, "VlanId", i);
+ e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
+ e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);
+ e->RemoteItem = PackGetBoolEx(p, "RemoteItem", i);
+ PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);
+ }
+}
+void OutRpcEnumMacTable(PACK *p, RPC_ENUM_MAC_TABLE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumMacTable;i++)
+ {
+ RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];
+
+ PackAddIntEx(p, "Key", e->Key, i, t->NumMacTable);
+ PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumMacTable);
+ PackAddDataEx(p, "MacAddress", e->MacAddress, sizeof(e->MacAddress), i, t->NumMacTable);
+ PackAddIntEx(p, "VlanId", e->VlanId, i, t->NumMacTable);
+ PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumMacTable);
+ PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumMacTable);
+ PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumMacTable);
+ PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumMacTable);
+ }
+}
+void FreeRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->MacTables);
+}
+
+// RPC_ENUM_IP_TABLE
+void InRpcEnumIpTable(RPC_ENUM_IP_TABLE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_IP_TABLE));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->NumIpTable = PackGetIndexCount(p, "SessionName");
+ t->IpTables = ZeroMalloc(sizeof(RPC_ENUM_IP_TABLE_ITEM) * t->NumIpTable);
+
+ for (i = 0;i < t->NumIpTable;i++)
+ {
+ RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];
+
+ e->Key = PackGetIntEx(p, "Key", i);
+ PackGetStrEx(p, "SessionName", e->SessionName, sizeof(e->SessionName), i);
+ e->Ip = PackGetIp32Ex(p, "Ip", i);
+ if (PackGetIpEx(p, "IpV6", &e->IpV6, i) == false)
+ {
+ UINTToIP(&e->IpV6, e->Ip);
+ }
+ e->DhcpAllocated = PackGetBoolEx(p, "DhcpAllocated", i);
+ e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
+ e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);
+ e->RemoteItem = PackGetBoolEx(p, "RemoteItem", i);
+ PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);
+ }
+}
+void OutRpcEnumIpTable(PACK *p, RPC_ENUM_IP_TABLE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumIpTable;i++)
+ {
+ RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];
+
+ PackAddIntEx(p, "Key", e->Key, i, t->NumIpTable);
+ PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumIpTable);
+ PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumIpTable);
+ PackAddIpEx(p, "IpV6", &e->IpV6, i, t->NumIpTable);
+ PackAddBoolEx(p, "DhcpAllocated", e->DhcpAllocated, i, t->NumIpTable);
+ PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumIpTable);
+ PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumIpTable);
+ PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumIpTable);
+ PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumIpTable);
+ }
+}
+void FreeRpcEnumIpTable(RPC_ENUM_IP_TABLE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->IpTables);
+}
+
+// RPC_DELETE_TABLE
+void InRpcDeleteTable(RPC_DELETE_TABLE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_TABLE));
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Key = PackGetInt(p, "Key");
+}
+void OutRpcDeleteTable(PACK *p, RPC_DELETE_TABLE *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "Key", t->Key);
+}
+
+// Adjoin RPC_ENUM_IP_TABLE
+void AdjoinRpcEnumIpTable(RPC_ENUM_IP_TABLE *dest, RPC_ENUM_IP_TABLE *src)
+{
+ UINT old_num;
+ UINT i, n;
+ if (dest == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (src->NumIpTable == 0)
+ {
+ return;
+ }
+
+ old_num = dest->NumIpTable;
+ dest->NumIpTable += src->NumIpTable;
+ dest->IpTables = ReAlloc(dest->IpTables, sizeof(RPC_ENUM_IP_TABLE_ITEM) * dest->NumIpTable);
+
+ n = 0;
+ for (i = old_num;i < dest->NumIpTable;i++)
+ {
+ Copy(&dest->IpTables[i], &src->IpTables[n++], sizeof(RPC_ENUM_IP_TABLE_ITEM));
+ }
+}
+
+// Adjoin RPC_ENUM_MAC_TABLE
+void AdjoinRpcEnumMacTable(RPC_ENUM_MAC_TABLE *dest, RPC_ENUM_MAC_TABLE *src)
+{
+ UINT old_num;
+ UINT i, n;
+ if (dest == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (src->NumMacTable == 0)
+ {
+ return;
+ }
+
+ old_num = dest->NumMacTable;
+ dest->NumMacTable += src->NumMacTable;
+ dest->MacTables = ReAlloc(dest->MacTables, sizeof(RPC_ENUM_MAC_TABLE_ITEM) * dest->NumMacTable);
+
+ n = 0;
+ for (i = old_num;i < dest->NumMacTable;i++)
+ {
+ Copy(&dest->MacTables[i], &src->MacTables[n++], sizeof(RPC_ENUM_MAC_TABLE_ITEM));
+ }
+}
+
+// Adjoin RPC_ENUM_SESSION
+void AdjoinRpcEnumSession(RPC_ENUM_SESSION *dest, RPC_ENUM_SESSION *src)
+{
+ UINT old_num;
+ UINT i, n;
+ if (dest == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (src->NumSession == 0)
+ {
+ return;
+ }
+
+ old_num = dest->NumSession;
+ dest->NumSession += src->NumSession;
+ dest->Sessions = ReAlloc(dest->Sessions, sizeof(RPC_ENUM_SESSION_ITEM) * dest->NumSession);
+
+ n = 0;
+ for (i = old_num;i < dest->NumSession;i++)
+ {
+ Copy(&dest->Sessions[i], &src->Sessions[n++], sizeof(RPC_ENUM_SESSION_ITEM));
+ }
+}
+
+// RPC_KEEP
+void InRpcKeep(RPC_KEEP *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_KEEP));
+ t->UseKeepConnect = PackGetBool(p, "UseKeepConnect");
+ PackGetStr(p, "KeepConnectHost", t->KeepConnectHost, sizeof(t->KeepConnectHost));
+ t->KeepConnectPort = PackGetInt(p, "KeepConnectPort");
+ t->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");
+ t->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");
+}
+void OutRpcKeep(PACK *p, RPC_KEEP *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "UseKeepConnect", t->UseKeepConnect);
+ PackAddStr(p, "KeepConnectHost", t->KeepConnectHost);
+ PackAddInt(p, "KeepConnectPort", t->KeepConnectPort);
+ PackAddInt(p, "KeepConnectProtocol", t->KeepConnectProtocol);
+ PackAddInt(p, "KeepConnectInterval", t->KeepConnectInterval);
+}
+
+// test RPC function
+UINT StTest(ADMIN *a, RPC_TEST *t)
+{
+ Format(t->StrValue, sizeof(t->StrValue), "%u", t->IntValue);
+
+ return ERR_NO_ERROR;
+}
+
+// RPC_TEST
+void InRpcTest(RPC_TEST *t, PACK *p)
+{
+ Zero(t, sizeof(RPC_TEST));
+ t->IntValue = PackGetInt(p, "IntValue");
+ t->Int64Value = PackGetInt64(p, "Int64Value");
+ PackGetStr(p, "StrValue", t->StrValue, sizeof(t->StrValue));
+ PackGetUniStr(p, "UniStrValue", t->UniStrValue, sizeof(t->UniStrValue));
+}
+void OutRpcTest(PACK *p, RPC_TEST *t)
+{
+ PackAddInt(p, "IntValue", t->IntValue);
+ PackAddInt64(p, "Int64Value", t->Int64Value);
+ PackAddStr(p, "StrValue", t->StrValue);
+ PackAddUniStr(p, "UniStrValue", t->UniStrValue);
+}
+void FreeRpcTest(RPC_TEST *t)
+{
+}
+
+// Admin RPC call
+PACK *AdminCall(RPC *rpc, char *function_name, PACK *p)
+{
+ // Validate arguments
+ if (rpc == NULL || function_name == NULL)
+ {
+ return NULL;
+ }
+ if (p == NULL)
+ {
+ p = NewPack();
+ }
+
+// Debug("Admin RPC Call: %s\n", function_name);
+
+ return RpcCall(rpc, function_name, p);
+}
+
+// Check whether the source IP address is permitted to admin connection
+bool CheckAdminSourceAddress(SOCK *sock, char *hubname)
+{
+ BUF *b;
+ char *s;
+ bool ok = false;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(ADMINIP_TXT);
+ if (b == NULL)
+ {
+ return true;
+ }
+
+ while (true)
+ {
+ UINT i;
+ TOKEN_LIST *t;
+ IP ip;
+ s = CfgReadNextLine(b);
+
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Trim(s);
+
+ i = SearchStrEx(s, "//", 0, false);
+ if (i != INFINITE)
+ {
+ s[i] = 0;
+ }
+
+ i = SearchStrEx(s, "#", 0, false);
+ if (i != INFINITE)
+ {
+ s[i] = 0;
+ }
+
+ Trim(s);
+
+ t = ParseToken(s, " \t");
+ if (t != NULL)
+ {
+ if (t->NumTokens >= 1)
+ {
+ if (t->NumTokens == 1 || StrCmpi(hubname, t->Token[1]) == 0)
+ {
+ if (StrToIP(&ip, t->Token[0]))
+ {
+ if (CmpIpAddr(&sock->RemoteIP, &ip) == 0)
+ {
+ ok = true;
+ }
+ }
+
+ if (StrCmpi(t->Token[0], "*") == 0)
+ {
+ ok = true;
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ Free(s);
+ }
+
+ FreeBuf(b);
+
+ return ok;
+}
+
+// Accept admin connection
+UINT AdminAccept(CONNECTION *c, PACK *p)
+{
+ ADMIN *a;
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR null_password[SHA1_SIZE];
+ UCHAR secure_null_password[SHA1_SIZE];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ CEDAR *cedar;
+ SOCK *sock;
+ RPC *rpc;
+ UINT err;
+ SERVER *server = NULL;
+ RPC_WINVER ver;
+ bool accept_empty_password;
+ bool is_empty_password = false;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ cedar = c->Cedar;
+ sock = c->FirstSock;
+
+ if (cedar != NULL)
+ {
+ server = cedar->Server;
+ }
+
+ accept_empty_password = PackGetBool(p, "accept_empty_password");
+
+ // Get client OS version
+ InRpcWinVer(&ver, p);
+
+ // Get hub name
+ if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false)
+ {
+ // without hub name
+ StrCpy(hubname, sizeof(hubname), "");
+ }
+
+ // Cehck source IP address
+ if (CheckAdminSourceAddress(sock, hubname) == false)
+ {
+ SLog(c->Cedar, "LA_IP_DENIED", c->Name);
+ return ERR_IP_ADDRESS_DENIED;
+ }
+
+ // Get password information
+ if (PackGetDataSize(p, "secure_password") != SHA1_SIZE)
+ {
+ // Malformed information
+ return ERR_PROTOCOL_ERROR;
+ }
+ PackGetData(p, "secure_password", secure_password);
+
+ if (StrLen(hubname) == 0)
+ {
+ // Server admin mode
+ SLog(c->Cedar, "LA_CONNECTED_1", c->Name);
+ }
+ else
+ {
+ // Hub admin mode
+ if (cedar->Server != NULL && cedar->Server->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ // Connection with hub admin mode to cluster member is not permitted
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+ SLog(c->Cedar, "LA_CONNECTED_2", c->Name, hubname);
+ }
+
+ // Check password
+ err = AdminCheckPassword(cedar, c->Random, secure_password,
+ StrLen(hubname) != 0 ? hubname : NULL, accept_empty_password, &is_empty_password);
+
+ if (err != ERR_NO_ERROR)
+ {
+ // Error occured
+ SLog(c->Cedar, "LA_ERROR", c->Name, GetUniErrorStr(err), err);
+ return err;
+ }
+
+ SLog(c->Cedar, "LA_OK", c->Name);
+
+ HashAdminPassword(null_password, "");
+ SecurePassword(secure_null_password, null_password, c->Random);
+
+ if (Cmp(secure_null_password, secure_password, SHA1_SIZE) == 0)
+ {
+ if (sock->RemoteIP.addr[0] != 127)
+ {
+ // The client tried to use blank password for hub admin mode from remote
+ if (StrLen(hubname) != 0)
+ {
+ return ERR_NULL_PASSWORD_LOCAL_ONLY;
+ }
+ }
+ }
+
+
+ // Reply success result
+ p = NewPack();
+ if (accept_empty_password && is_empty_password)
+ {
+ PackAddBool(p, "empty_password", true);
+ }
+ HttpServerSend(sock, p);
+ FreePack(p);
+
+ // Construct ADMIN object
+ a = ZeroMalloc(sizeof(ADMIN));
+ a->ServerAdmin = ((StrLen(hubname) == 0) ? true : false);
+ a->HubName = (StrLen(hubname) != 0 ? hubname : NULL);
+ a->Server = c->Cedar->Server;
+ a->ClientBuild = c->ClientBuild;
+
+ Copy(&a->ClientWinVer, &ver, sizeof(RPC_WINVER));
+
+ // Timeout setting
+ SetTimeout(sock, INFINITE);
+
+ // RPC Server
+ rpc = StartRpcServer(sock, AdminDispatch, a);
+
+ a->Rpc = rpc;
+
+ SLog(c->Cedar, "LA_RPC_START", c->Name, rpc->Name);
+
+ RpcServer(rpc);
+ RpcFree(rpc);
+
+ if (a->LogFileList != NULL)
+ {
+ // Free cached log file list, if it exists
+ FreeEnumLogFile(a->LogFileList);
+ }
+
+ // Free ADMIN object
+ Free(a);
+
+ return ERR_NO_ERROR;
+}
+
+// Check for admin password
+UINT AdminCheckPassword(CEDAR *c, void *random, void *secure_password, char *hubname,
+ bool accept_empty_password, bool *is_password_empty)
+{
+ UCHAR check[SHA1_SIZE];
+ bool b_dummy;
+ // Validate arguments
+ if (c == NULL || random == NULL || secure_password == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+ if (is_password_empty == NULL)
+ {
+ is_password_empty = &b_dummy;
+ }
+
+ *is_password_empty = false;
+
+ if (hubname == NULL || StrLen(hubname) == 0)
+ {
+ // Server admin mode
+ Lock(c->lock);
+ {
+ if (accept_empty_password && SiIsEmptyPassword(c->Server->HashedPassword))
+ {
+ // blank password
+ *is_password_empty = true;
+ }
+
+ SecurePassword(check, c->Server->HashedPassword, random);
+ }
+ Unlock(c->lock);
+
+ if (Cmp(check, secure_password, SHA1_SIZE) != 0)
+ {
+ // Password incorrect
+ return ERR_ACCESS_DENIED;
+ }
+ }
+ else
+ {
+ HUB *h;
+
+#if 0
+ if (c->Server->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ // In cluster member mode, hub admin mode is disabled
+ return ERR_FARM_MEMBER_HUB_ADMIN;
+ }
+#endif
+
+ // Hub admin mode
+ LockHubList(c);
+ {
+ h = GetHub(c, hubname);
+ }
+ UnlockHubList(c);
+
+ if (h == NULL)
+ {
+ // Specified hub is not found
+ return ERR_HUB_NOT_FOUND;
+ }
+
+ Lock(h->lock);
+ {
+ if (accept_empty_password && SiIsEmptyPassword(h->HashedPassword))
+ {
+ // User specified blank password
+ *is_password_empty = true;
+ }
+
+ SecurePassword(check, h->HashedPassword, random);
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+
+ if (Cmp(check, secure_password, SHA1_SIZE) != 0)
+ {
+ // Incorrect password
+ return ERR_ACCESS_DENIED;
+ }
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Hash admin password
+void HashAdminPassword(void *hash, char *password)
+{
+ // Validate arguments
+ if (hash == NULL || password == NULL)
+ {
+ return;
+ }
+
+ Hash(hash, password, StrLen(password), true);
+}
+
+// Disconnect admin connection
+void AdminDisconnect(RPC *rpc)
+{
+ SESSION *s;
+ SOCK *sock;
+ // Validate arguments
+ if (rpc == NULL)
+ {
+ return;
+ }
+
+ s = (SESSION *)rpc->Param;
+ sock = rpc->Sock;
+
+ EndRpc(rpc);
+
+ Disconnect(sock);
+ ReleaseSession(s);
+}
+
+// Admin connection main routine
+SESSION *AdminConnectMain(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd, bool *empty_password)
+{
+ UCHAR secure_password[SHA1_SIZE];
+ SESSION *s;
+ SOCK *sock;
+ PACK *p;
+ RPC_WINVER ver;
+ // connect
+ s = NewRpcSessionEx2(cedar, o, err, client_name, hWnd);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // Get socket
+ sock = s->Connection->FirstSock;
+
+ // Generate connect method
+ p = NewPack();
+
+ PackAddClientVersion(p, s->Connection);
+
+ PackAddStr(p, "method", "admin");
+ PackAddBool(p, "accept_empty_password", true);
+
+ // Windows version on client
+ GetWinVer(&ver);
+ OutRpcWinVer(p, &ver);
+
+ // Secure Password
+ SecurePassword(secure_password, hashed_password, s->Connection->Random);
+
+ PackAddData(p, "secure_password", secure_password, sizeof(secure_password));
+
+ // HUB name
+ if (hubname != NULL)
+ {
+ PackAddStr(p, "hubname", hubname);
+ }
+
+ if (HttpClientSend(sock, p) == false)
+ {
+ // disconnect
+ FreePack(p);
+ ReleaseSession(s);
+ *err = ERR_DISCONNECTED;
+ return NULL;
+ }
+
+ FreePack(p);
+
+ p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ // disconnect
+ ReleaseSession(s);
+ *err = ERR_DISCONNECTED;
+ return NULL;
+ }
+
+ if (GetErrorFromPack(p) != 0)
+ {
+ // error
+ ReleaseSession(s);
+ *err = GetErrorFromPack(p);
+ FreePack(p);
+ return NULL;
+ }
+
+ if (empty_password != NULL)
+ {
+ *empty_password = PackGetBool(p, "empty_password");
+ }
+
+ FreePack(p);
+
+ return s;
+}
+
+// Admin connection
+RPC *AdminConnect(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err)
+{
+ return AdminConnectEx(cedar, o, hubname, hashed_password, err, NULL);
+}
+RPC *AdminConnectEx(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name)
+{
+ return AdminConnectEx2(cedar, o, hubname, hashed_password, err, client_name, NULL);
+}
+RPC *AdminConnectEx2(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd)
+{
+ SESSION *s;
+ SOCK *sock;
+ RPC *rpc;
+ UCHAR hashed_password_2[SHA1_SIZE];
+ bool empty_password = false;
+ // Validate arguments
+ if (cedar == NULL || o == NULL || hashed_password == NULL || err == NULL)
+ {
+ return NULL;
+ }
+
+ if (client_name == NULL)
+ {
+ client_name = CEDAR_MANAGER_STR;
+ }
+
+ Copy(hashed_password_2, hashed_password, SHA1_SIZE);
+
+ s = AdminConnectMain(cedar, o, hubname, hashed_password_2, err, client_name, hWnd, &empty_password);
+
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ sock = s->Connection->FirstSock;
+
+ // RPC start
+ rpc = StartRpcClient(sock, s);
+
+ rpc->IsVpnServer = true;
+ Copy(&rpc->VpnServerClientOption, o, sizeof(CLIENT_OPTION));
+ StrCpy(rpc->VpnServerHubName, sizeof(rpc->VpnServerHubName), hubname);
+ StrCpy(rpc->VpnServerClientName, sizeof(rpc->VpnServerClientName), client_name);
+
+ if (empty_password == false)
+ {
+ Copy(rpc->VpnServerHashedPassword, hashed_password_2, SHA1_SIZE);
+ }
+ else
+ {
+ HashAdminPassword(rpc->VpnServerHashedPassword, "");
+ }
+
+ // timeout setting
+ SetTimeout(sock, INFINITE);
+
+ return rpc;
+}
+
+// Reconnect admin connection
+UINT AdminReconnect(RPC *rpc)
+{
+ SESSION *s;
+ SOCK *sock;
+ CEDAR *cedar;
+ UINT err;
+ bool empty_password = false;
+ // Validate arguments
+ if (rpc == NULL || rpc->IsVpnServer == false)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ s = (SESSION *)rpc->Param;
+ cedar = s->Cedar;
+ AddRef(cedar->ref);
+
+ sock = rpc->Sock;
+ Disconnect(sock);
+ ReleaseSock(sock);
+ ReleaseSession(s);
+ rpc->Param = NULL;
+
+ rpc->Sock = NULL;
+
+ s = AdminConnectMain(cedar, &rpc->VpnServerClientOption,
+ rpc->VpnServerHubName,
+ rpc->VpnServerHashedPassword,
+ &err,
+ rpc->VpnServerClientName, NULL, &empty_password);
+
+ ReleaseCedar(cedar);
+
+ if (s == NULL)
+ {
+ return err;
+ }
+
+ if (empty_password)
+ {
+ HashAdminPassword(rpc->VpnServerHashedPassword, "");
+ }
+
+ rpc->Param = s;
+ rpc->Sock = s->Connection->FirstSock;
+ AddRef(rpc->Sock->ref);
+
+ return ERR_NO_ERROR;
+}
+
+// Identify blank password
+bool SiIsEmptyPassword(void *hash_password)
+{
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (hash_password == NULL)
+ {
+ return false;
+ }
+
+ Hash(hash, "", 0, true);
+
+ if (Cmp(hash_password, hash, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Admin.h b/src/Cedar/Admin.h
new file mode 100644
index 00000000..b667f609
--- /dev/null
+++ b/src/Cedar/Admin.h
@@ -0,0 +1,1505 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Admin.h
+// Header of Admin.c
+
+#ifndef ADMIN_H
+#define ADMIN_H
+
+// Windows version
+struct RPC_WINVER
+{
+ bool IsWindows;
+ bool IsNT;
+ bool IsServer;
+ bool IsBeta;
+ UINT VerMajor;
+ UINT VerMinor;
+ UINT Build;
+ UINT ServicePack;
+ char Title[128];
+};
+
+// Server-side structure
+struct ADMIN
+{
+ SERVER *Server; // Server
+ bool ServerAdmin; // Server Administrator
+ char *HubName; // HUB name that can be managed
+ RPC *Rpc; // RPC
+ LIST *LogFileList; // Accessible log file list
+ UINT ClientBuild; // Build number of the client
+ RPC_WINVER ClientWinVer; // Windows version of client
+};
+
+// Test
+struct RPC_TEST
+{
+ UINT IntValue;
+ UINT64 Int64Value;
+ char StrValue[1024];
+ wchar_t UniStrValue[1024];
+};
+
+// Server Information *
+struct RPC_SERVER_INFO
+{
+ char ServerProductName[128]; // Server product name
+ char ServerVersionString[128]; // Server version string
+ char ServerBuildInfoString[128]; // Server build information string
+ UINT ServerVerInt; // Server version integer value
+ UINT ServerBuildInt; // Server build number integer value
+ char ServerHostName[MAX_HOST_NAME_LEN + 1]; // Server host name
+ UINT ServerType; // Type of server
+ UINT64 ServerBuildDate; // Build date and time of the server
+ char ServerFamilyName[128]; // Family name
+ OS_INFO OsInfo; // OS information
+};
+
+// Server status
+struct RPC_SERVER_STATUS
+{
+ UINT ServerType; // Type of server
+ UINT NumTcpConnections; // Total number of TCP connections
+ UINT NumTcpConnectionsLocal; // Number of Local TCP connections
+ UINT NumTcpConnectionsRemote; // Number of remote TCP connections
+ UINT NumHubTotal; // Total number of HUBs
+ UINT NumHubStandalone; // Nymber of stand-alone HUB
+ UINT NumHubStatic; // Number of static HUBs
+ UINT NumHubDynamic; // Number of Dynamic HUBs
+ UINT NumSessionsTotal; // Total number of sessions
+ UINT NumSessionsLocal; // Number of Local sessions (only controller)
+ UINT NumSessionsRemote; // The number of remote sessions (other than the controller)
+ UINT NumMacTables; // Number of MAC table entries
+ UINT NumIpTables; // Number of IP table entries
+ UINT NumUsers; // Number of users
+ UINT NumGroups; // Number of groups
+ UINT AssignedBridgeLicenses; // Number of assigned bridge licenses
+ UINT AssignedClientLicenses; // Number of assigned client licenses
+ UINT AssignedBridgeLicensesTotal; // Number of Assigned bridge license (cluster-wide)
+ UINT AssignedClientLicensesTotal; // Number of assigned client licenses (cluster-wide)
+ TRAFFIC Traffic; // Traffic information
+ UINT64 CurrentTime; // Current time
+ UINT64 CurrentTick; // Current tick
+ UINT64 StartTime; // Start-up time
+ MEMINFO MemInfo; // Memory information
+};
+
+// Listener
+struct RPC_LISTENER
+{
+ UINT Port; // Port number
+ bool Enable; // Active state
+};
+
+// List of listeners *
+struct RPC_LISTENER_LIST
+{
+ UINT NumPort; // Number of ports
+ UINT *Ports; // Port List
+ bool *Enables; // Effective state
+ bool *Errors; // An error occurred
+};
+
+// String *
+struct RPC_STR
+{
+ char *String; // String
+};
+
+// Integer
+struct RPC_INT
+{
+ UINT IntValue; // Integer
+};
+
+// Set Password
+struct RPC_SET_PASSWORD
+{
+ UCHAR HashedPassword[SHA1_SIZE]; // Hashed password
+};
+
+// Server farm configuration *
+struct RPC_FARM
+{
+ UINT ServerType; // Type of server
+ UINT NumPort; // Number of public ports
+ UINT *Ports; // Public port list
+ UINT PublicIp; // Public IP
+ char ControllerName[MAX_HOST_NAME_LEN + 1]; // Controller name
+ UINT ControllerPort; // Controller port
+ UCHAR MemberPassword[SHA1_SIZE]; // Member password
+ UINT Weight; // Performance ratio
+ bool ControllerOnly; // Only controller function
+};
+
+// HUB item of each farm member
+struct RPC_FARM_HUB
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool DynamicHub; // Dynamic HUB
+};
+
+// Server farm member information acquisition *
+struct RPC_FARM_INFO
+{
+ UINT Id; // ID
+ bool Controller; // Controller
+ UINT64 ConnectedTime; // Connection time
+ UINT Ip; // IP address
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Point; // Point
+ UINT NumPort; // Number of ports
+ UINT *Ports; // Port
+ X *ServerCert; // Server certificate
+ UINT NumFarmHub; // Number of farm HUB
+ RPC_FARM_HUB *FarmHubs; // Farm HUB
+ UINT NumSessions; // Number of sessions
+ UINT NumTcpConnections; // Number of TCP connections
+ UINT Weight; // Performance ratio
+};
+
+// Server farm members enumeration items
+struct RPC_ENUM_FARM_ITEM
+{
+ UINT Id; // ID
+ bool Controller; // Controller
+ UINT64 ConnectedTime; // Connection time
+ UINT Ip; // IP address
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Point; // Point
+ UINT NumSessions; // Number of sessions
+ UINT NumTcpConnections; // Number of TCP connections
+ UINT NumHubs; // Number of HUBs
+ UINT AssignedClientLicense; // Number of assigned client licenses
+ UINT AssignedBridgeLicense; // Number of assigned bridge licenses
+};
+
+// Server farm member enumeration *
+struct RPC_ENUM_FARM
+{
+ UINT NumFarm; // Number of farm members
+ RPC_ENUM_FARM_ITEM *Farms; // Farm member list
+};
+
+// Connection state to the controller
+struct RPC_FARM_CONNECTION_STATUS
+{
+ UINT Ip; // IP address
+ UINT Port; // Port number
+ bool Online; // Online state
+ UINT LastError; // Last error
+ UINT64 StartedTime; // Connection start time
+ UINT64 FirstConnectedTime; // First connection time
+ UINT64 CurrentConnectedTime; // Connection time of this time
+ UINT NumTry; // Number of trials
+ UINT NumConnected; // Number of connection count
+ UINT NumFailed; // Connection failure count
+};
+
+// Key pair
+struct RPC_KEY_PAIR
+{
+ X *Cert; // Certificate
+ K *Key; // Secret key
+};
+
+// HUB option
+struct RPC_HUB_OPTION
+{
+ UINT MaxSession; // Maximum number of sessions
+ bool NoEnum; // Not listed
+};
+
+// Radius server options
+struct RPC_RADIUS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char RadiusServerName[MAX_HOST_NAME_LEN + 1]; // Radius server name
+ UINT RadiusPort; // Radius port number
+ char RadiusSecret[MAX_PASSWORD_LEN + 1]; // Secret key
+ UINT RadiusRetryInterval; // Radius retry interval
+};
+
+// Specify the HUB
+struct RPC_HUB
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+};
+
+// Create a HUB
+struct RPC_CREATE_HUB
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UCHAR HashedPassword[SHA1_SIZE]; // Administrative password
+ UCHAR SecurePassword[SHA1_SIZE]; // Administrator password
+ bool Online; // Online flag
+ RPC_HUB_OPTION HubOption; // HUB options
+ UINT HubType; // Type of HUB
+};
+
+// Enumeration items of HUB
+struct RPC_ENUM_HUB_ITEM
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool Online; // Online
+ UINT HubType; // Type of HUB
+ UINT NumUsers; // Number of users
+ UINT NumGroups; // Number of groups
+ UINT NumSessions; // Number of sessions
+ UINT NumMacTables; // Number of MAC table entries
+ UINT NumIpTables; // Number of IP table entries
+ UINT64 LastCommTime; // Last communication date and time
+ UINT64 LastLoginTime; // Last login date and time
+ UINT64 CreatedTime; // Creation date and time
+ UINT NumLogin; // Number of logins
+ bool IsTrafficFilled; // Whether the traffic information exists
+ TRAFFIC Traffic; // Traffic
+};
+
+// Enumeration of HUB
+struct RPC_ENUM_HUB
+{
+ UINT NumHub; // Number of HUBs
+ RPC_ENUM_HUB_ITEM *Hubs; // HUB
+};
+
+// Delete the HUB
+struct RPC_DELETE_HUB
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+};
+
+// Connection enumeration items
+struct RPC_ENUM_CONNECTION_ITEM
+{
+ char Name[MAX_SIZE]; // Connection name
+ char Hostname[MAX_SIZE]; // Host name
+ UINT Ip; // IP address
+ UINT Port; // Port number
+ UINT64 ConnectedTime; // Connected time
+ UINT Type; // Type
+};
+
+// Connection enumeration
+struct RPC_ENUM_CONNECTION
+{
+ UINT NumConnection; // Number of connections
+ RPC_ENUM_CONNECTION_ITEM *Connections; // Connection list
+};
+
+// Disconnection
+struct RPC_DISCONNECT_CONNECTION
+{
+ char Name[MAX_SIZE]; // Connection name
+};
+
+// Connection information
+struct RPC_CONNECTION_INFO
+{
+ char Name[MAX_SIZE]; // Connection name
+ UINT Type; // Type
+ char Hostname[MAX_SIZE]; // Host name
+ UINT Ip; // IP address
+ UINT Port; // Port number
+ UINT64 ConnectedTime; // Connected time
+ char ServerStr[MAX_SERVER_STR_LEN + 1]; // Server string
+ UINT ServerVer; // Server version
+ UINT ServerBuild; // Server build number
+ char ClientStr[MAX_CLIENT_STR_LEN + 1]; // Client string
+ UINT ClientVer; // Client version
+ UINT ClientBuild; // Client build number
+};
+
+// Online or offline the HUB
+struct RPC_SET_HUB_ONLINE
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool Online; // Online / offline flag
+};
+
+// Get the state HUB
+struct RPC_HUB_STATUS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool Online; // Online
+ UINT HubType; // Type of HUB
+ UINT NumSessions; // Number of sessions
+ UINT NumSessionsClient; // Number of sessions (client)
+ UINT NumSessionsBridge; // Number of sessions (bridge)
+ UINT NumAccessLists; // Number of Access list entries
+ UINT NumUsers; // Number of users
+ UINT NumGroups; // Number of groups
+ UINT NumMacTables; // Number of MAC table entries
+ UINT NumIpTables; // Number of IP table entries
+ TRAFFIC Traffic; // Traffic
+ bool SecureNATEnabled; // Whether SecureNAT is enabled
+ UINT64 LastCommTime; // Last communication date and time
+ UINT64 LastLoginTime; // Last login date and time
+ UINT64 CreatedTime; // Creation date and time
+ UINT NumLogin; // Number of logins
+};
+
+// HUB log settings
+struct RPC_HUB_LOG
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ HUB_LOG LogSetting; // Log Settings
+};
+
+// Add CA to HUB *
+struct RPC_HUB_ADD_CA
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ X *Cert; // Certificate
+};
+
+// CA enumeration items of HUB
+struct RPC_HUB_ENUM_CA_ITEM
+{
+ UINT Key; // Certificate key
+ wchar_t SubjectName[MAX_SIZE]; // Issued to
+ wchar_t IssuerName[MAX_SIZE]; // Issuer
+ UINT64 Expires; // Expiration date
+};
+
+// CA enumeration of HUB *
+struct RPC_HUB_ENUM_CA
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumCa; // CA number
+ RPC_HUB_ENUM_CA_ITEM *Ca; // CA
+};
+
+// Get the CA of HUB *
+struct RPC_HUB_GET_CA
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT Key; // Certificate key
+ X *Cert; // Certificate
+};
+
+// Delete the CA of HUB
+struct RPC_HUB_DELETE_CA
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT Key; // Certificate key to be deleted
+};
+
+// Create and set of link *
+struct RPC_CREATE_LINK
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool Online; // Online flag
+ CLIENT_OPTION *ClientOption; // Client Option
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ POLICY Policy; // Policy
+ bool CheckServerCert; // Validate the server certificate
+ X *ServerCert; // Server certificate
+};
+
+// Enumeration items of link
+struct RPC_ENUM_LINK_ITEM
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ bool Online; // Online flag
+ bool Connected; // Connection completion flag
+ UINT LastError; // The error that last occurred
+ UINT64 ConnectedTime; // Connection completion time
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+};
+
+// Enumeration of the link *
+struct RPC_ENUM_LINK
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumLink; // Number of links
+ RPC_ENUM_LINK_ITEM *Links; // Link List
+};
+
+// Get the link state *
+struct RPC_LINK_STATUS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ RPC_CLIENT_GET_CONNECTION_STATUS Status; // Status
+};
+
+// Specify the Link
+struct RPC_LINK
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+};
+
+// Rename link
+struct RPC_RENAME_LINK
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ wchar_t OldAccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Old account name
+ wchar_t NewAccountName[MAX_ACCOUNT_NAME_LEN + 1]; // New account name
+};
+
+// Enumeration of the access list *
+struct RPC_ENUM_ACCESS_LIST
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumAccess; // Number of Access list entries
+ ACCESS *Accesses; // Access list
+};
+
+// Add to Access List
+struct RPC_ADD_ACCESS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ ACCESS Access; // Access list
+};
+
+// Delete the access list
+struct RPC_DELETE_ACCESS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT Id; // ID
+};
+
+// Create, configure, and get the user *
+struct RPC_SET_USER
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char Name[MAX_USERNAME_LEN + 1]; // User name
+ char GroupName[MAX_USERNAME_LEN + 1]; // Group name
+ wchar_t Realname[MAX_SIZE]; // Real name
+ wchar_t Note[MAX_SIZE]; // Note
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+ UINT64 ExpireTime; // Expiration date
+ UINT AuthType; // Authentication method
+ void *AuthData; // Authentication data
+ UINT NumLogin; // Number of logins
+ TRAFFIC Traffic; // Traffic data
+ POLICY *Policy; // Policy
+};
+
+// Enumeration item of user
+struct RPC_ENUM_USER_ITEM
+{
+ char Name[MAX_USERNAME_LEN + 1]; // User name
+ char GroupName[MAX_USERNAME_LEN + 1]; // Group name
+ wchar_t Realname[MAX_SIZE]; // Real name
+ wchar_t Note[MAX_SIZE]; // Note
+ UINT AuthType; // Authentication method
+ UINT NumLogin; // Number of logins
+ UINT64 LastLoginTime; // Last login date and time
+ bool DenyAccess; // Access denied
+ bool IsTrafficFilled; // Flag of whether the traffic variable is set
+ TRAFFIC Traffic; // Traffic
+ bool IsExpiresFilled; // Flag of whether expiration date variable is set
+ UINT64 Expires; // Expiration date
+};
+
+// Enumeration of user
+struct RPC_ENUM_USER
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumUser; // Number of users
+ RPC_ENUM_USER_ITEM *Users; // User
+};
+
+// Create, configure, and get the group *
+struct RPC_SET_GROUP
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char Name[MAX_USERNAME_LEN + 1]; // User name
+ wchar_t Realname[MAX_SIZE]; // Real name
+ wchar_t Note[MAX_SIZE]; // Note
+ TRAFFIC Traffic; // Traffic data
+ POLICY *Policy; // Policy
+};
+
+// Enumeration items in the group
+struct RPC_ENUM_GROUP_ITEM
+{
+ char Name[MAX_USERNAME_LEN + 1]; // User name
+ wchar_t Realname[MAX_SIZE]; // Real name
+ wchar_t Note[MAX_SIZE]; // Note
+ UINT NumUsers; // Number of users
+ bool DenyAccess; // Access denied
+};
+
+// Group enumeration
+struct RPC_ENUM_GROUP
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumGroup; // Number of groups
+ RPC_ENUM_GROUP_ITEM *Groups; // Group
+};
+
+// Deleting a user or group
+struct RPC_DELETE_USER
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char Name[MAX_USERNAME_LEN + 1]; // User or group name
+};
+
+// Enumeration items of session
+struct RPC_ENUM_SESSION_ITEM
+{
+ char Name[MAX_SESSION_NAME_LEN + 1]; // Session name
+ bool RemoteSession; // Remote session
+ char RemoteHostname[MAX_HOST_NAME_LEN + 1]; // Remote server name
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ UINT Ip; // IP address (IPv4)
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT MaxNumTcp; // Maximum number of TCP connections
+ UINT CurrentNumTcp; // Number of currentl TCP connections
+ UINT64 PacketSize; // Packet size
+ UINT64 PacketNum; // Number of packets
+ bool LinkMode; // Link mode
+ bool SecureNATMode; // SecureNAT mode
+ bool BridgeMode; // Bridge mode
+ bool Layer3Mode; // Layer 3 mode
+ bool Client_BridgeMode; // Client is bridge mode
+ bool Client_MonitorMode; // Client is monitoring mode
+ UINT VLanId; // VLAN ID
+ UCHAR UniqueId[16]; // Unique ID
+};
+
+// Disconnect the session
+struct RPC_DELETE_SESSION
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char Name[MAX_SESSION_NAME_LEN + 1]; // Session name
+};
+
+// Enumeration items of the MAC table
+struct RPC_ENUM_MAC_TABLE_ITEM
+{
+ UINT Key; // Key
+ char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+ bool RemoteItem; // Remote items
+ char RemoteHostname[MAX_HOST_NAME_LEN + 1]; // Remote host name
+ UINT VlanId; // VLAN ID
+};
+
+// Enumeration of the MAC table
+struct RPC_ENUM_MAC_TABLE
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumMacTable; // Number of tables
+ RPC_ENUM_MAC_TABLE_ITEM *MacTables; // MAC table
+};
+
+// Enumeration items of IP table
+struct RPC_ENUM_IP_TABLE_ITEM
+{
+ UINT Key; // Key
+ char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
+ UINT Ip; // IP address
+ IP IpV6; // IPv6 address
+ bool DhcpAllocated; // Assigned by the DHCP
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+ bool RemoteItem; // Remote items
+ char RemoteHostname[MAX_HOST_NAME_LEN + 1]; // Remote host name
+};
+
+// Enumeration of IP table
+struct RPC_ENUM_IP_TABLE
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumIpTable; // Number of tables
+ RPC_ENUM_IP_TABLE_ITEM *IpTables; // MAC table
+};
+
+// Delete the table
+struct RPC_DELETE_TABLE
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT Key; // Key
+};
+
+// KEEP setting
+struct RPC_KEEP
+{
+ bool UseKeepConnect; // Keep connected to the Internet
+ char KeepConnectHost[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT KeepConnectPort; // Port number
+ UINT KeepConnectProtocol; // Protocol
+ UINT KeepConnectInterval; // Interval
+};
+
+// Ethernet enumeration item
+struct RPC_ENUM_ETH_ITEM
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ wchar_t NetworkConnectionName[MAX_SIZE];// Network connection name
+};
+
+// Ethernet enumeration
+struct RPC_ENUM_ETH
+{
+ UINT NumItem; // Number of items
+ RPC_ENUM_ETH_ITEM *Items; // Item
+};
+
+// Bridge item
+struct RPC_LOCALBRIDGE
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ bool Online; // Online flag
+ bool Active; // Running flag
+ bool TapMode; // Tap mode
+};
+
+// Bridge enumeration
+struct RPC_ENUM_LOCALBRIDGE
+{
+ UINT NumItem; // Number of items
+ RPC_LOCALBRIDGE *Items; // Item
+};
+
+// Bridge support information
+struct RPC_BRIDGE_SUPPORT
+{
+ bool IsBridgeSupportedOs; // Whether the OS supports the bridge
+ bool IsWinPcapNeeded; // Whether WinPcap is necessary
+};
+
+// Config operation
+struct RPC_CONFIG
+{
+ char FileName[MAX_PATH]; // File name
+ char *FileData; // File data
+};
+
+// Administration options list
+struct RPC_ADMIN_OPTION
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ UINT NumItem; // Count
+ ADMIN_OPTION *Items; // Data
+};
+
+// Layer-3 switch
+struct RPC_L3SW
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // L3 switch name
+};
+
+// Layer-3 switch enumeration
+struct RPC_ENUM_L3SW_ITEM
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // Name
+ UINT NumInterfaces; // Number of interfaces
+ UINT NumTables; // Routing table number
+ bool Active; // In operation
+ bool Online; // Online
+};
+struct RPC_ENUM_L3SW
+{
+ UINT NumItem;
+ RPC_ENUM_L3SW_ITEM *Items;
+};
+
+// Layer-3 interface
+struct RPC_L3IF
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // L3 switch name
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ UINT IpAddress; // IP address
+ UINT SubnetMask; // Subnet mask
+};
+
+// Layer-3 interface enumeration
+struct RPC_ENUM_L3IF
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // L3 switch name
+ UINT NumItem;
+ RPC_L3IF *Items;
+};
+
+// Routing table
+struct RPC_L3TABLE
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // L3 switch name
+ UINT NetworkAddress; // Network address
+ UINT SubnetMask; // Subnet mask
+ UINT GatewayAddress; // Gateway address
+ UINT Metric; // Metric
+};
+
+// Routing table enumeration
+struct RPC_ENUM_L3TABLE
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // L3 switch name
+ UINT NumItem;
+ RPC_L3TABLE *Items;
+};
+
+// CRL entry
+struct RPC_CRL
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT Key; // Key
+ CRL *Crl; // CRL body
+};
+
+// CRL enumeration
+struct RPC_ENUM_CRL_ITEM
+{
+ UINT Key; // Key
+ wchar_t CrlInfo[MAX_SIZE]; // Information
+};
+struct RPC_ENUM_CRL
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumItem; // Number of items
+ RPC_ENUM_CRL_ITEM *Items; // List
+};
+
+// AC list
+struct RPC_AC_LIST
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ LIST *o; // List body
+ bool InternalFlag1;
+};
+
+// Log file enumeration
+struct RPC_ENUM_LOG_FILE_ITEM
+{
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ char FilePath[MAX_PATH]; // File Path
+ UINT FileSize; // File size
+ UINT64 UpdatedTime; // Updating date
+};
+struct RPC_ENUM_LOG_FILE
+{
+ UINT NumItem; // Number of items
+ RPC_ENUM_LOG_FILE_ITEM *Items; // List
+};
+
+// Read a Log file
+struct RPC_READ_LOG_FILE
+{
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ char FilePath[MAX_PATH]; // File Path
+ UINT Offset; // Offset
+ BUF *Buffer; // Buffer
+};
+
+// Download information
+struct DOWNLOAD_PROGRESS
+{
+ void *Param; // User define data
+ UINT TotalSize; // The total file size
+ UINT CurrentSize; // Size which has loaded
+ UINT ProgressPercent; // Percent Complete
+};
+
+// Enumerate the license keys
+struct RPC_ENUM_LICENSE_KEY_ITEM
+{
+ UINT Id; // ID
+ char LicenseKey[LICENSE_KEYSTR_LEN + 1]; // License key
+ char LicenseId[LICENSE_LICENSEID_STR_LEN + 1]; // License ID
+ char LicenseName[LICENSE_MAX_PRODUCT_NAME_LEN + 1]; // License name
+ UINT64 Expires; // Expiration date
+ UINT Status; // Situation
+ UINT ProductId; // Product ID
+ UINT64 SystemId; // System ID
+ UINT SerialId; // Serial ID
+};
+struct RPC_ENUM_LICENSE_KEY
+{
+ UINT NumItem; // Number of items
+ RPC_ENUM_LICENSE_KEY_ITEM *Items; // List
+};
+
+// License status of the server
+struct RPC_LICENSE_STATUS
+{
+ UINT EditionId; // Edition ID
+ char EditionStr[LICENSE_MAX_PRODUCT_NAME_LEN + 1]; // Edition name
+ UINT64 SystemId; // System ID
+ UINT64 SystemExpires; // System expiration date
+ UINT NumClientConnectLicense; // Maximum number of concurrent client connections
+ UINT NumBridgeConnectLicense; // Available number of concurrent bridge connections
+
+ // v3.0
+ bool NeedSubscription; // Subscription system is enabled
+ UINT64 SubscriptionExpires; // Subscription expiration date
+ bool IsSubscriptionExpired; // Whether the subscription is expired
+ UINT NumUserCreationLicense; // Maximum number of users
+ bool AllowEnterpriseFunction; // Operation of the enterprise function
+ UINT64 ReleaseDate; // Release date
+};
+
+// Enumeration of VLAN support status of physical LAN card
+struct RPC_ENUM_ETH_VLAN_ITEM
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ char Guid[MAX_SIZE]; // GUID
+ char DeviceInstanceId[MAX_SIZE]; // Device Instance ID
+ char DriverName[MAX_SIZE]; // Driver file name
+ char DriverType[MAX_SIZE]; // Type of driver
+ bool Support; // Check whether it is supported
+ bool Enabled; // Whether it is enabled
+};
+struct RPC_ENUM_ETH_VLAN
+{
+ UINT NumItem; // Number of items
+ RPC_ENUM_ETH_VLAN_ITEM *Items; // List
+};
+
+// Message
+struct RPC_MSG
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ wchar_t *Msg; // Message
+};
+
+// EtherIP setting list
+struct RPC_ENUM_ETHERIP_ID
+{
+ UINT NumItem;
+ ETHERIP_ID *IdList;
+};
+
+// Set the special listener
+struct RPC_SPECIAL_LISTENER
+{
+ bool VpnOverIcmpListener; // VPN over ICMP
+ bool VpnOverDnsListener; // VPN over DNS
+};
+
+// Get / Set the Azure state
+struct RPC_AZURE_STATUS
+{
+ bool IsEnabled; // Whether enabled
+ bool IsConnected; // Whether it's connected
+};
+
+
+// Function prototype
+UINT AdminAccept(CONNECTION *c, PACK *p);
+void HashAdminPassword(void *hash, char *password);
+SESSION *AdminConnectMain(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd, bool *empty_password);
+RPC *AdminConnect(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err);
+RPC *AdminConnectEx(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name);
+RPC *AdminConnectEx2(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd);
+void AdminDisconnect(RPC *rpc);
+UINT AdminReconnect(RPC *rpc);
+UINT AdminCheckPassword(CEDAR *c, void *random, void *secure_password, char *hubname, bool accept_empty_password, bool *is_password_empty);
+PACK *AdminDispatch(RPC *rpc, char *name, PACK *p);
+PACK *AdminCall(RPC *rpc, char *function_name, PACK *p);
+void SiEnumLocalSession(SERVER *s, char *hubname, RPC_ENUM_SESSION *t);
+void CopyOsInfo(OS_INFO *dst, OS_INFO *info);
+CAPSLIST *ScGetCapsEx(RPC *rpc);
+UINT SiEnumMacTable(SERVER *s, char *hubname, RPC_ENUM_MAC_TABLE *t);
+UINT SiEnumIpTable(SERVER *s, char *hubname, RPC_ENUM_IP_TABLE *t);
+void SiEnumLocalLogFileList(SERVER *s, char *hubname, RPC_ENUM_LOG_FILE *t);
+void SiReadLocalLogFile(SERVER *s, char *filepath, UINT offset, RPC_READ_LOG_FILE *t);
+typedef bool (DOWNLOAD_PROC)(DOWNLOAD_PROGRESS *progress);
+BUF *DownloadFileFromServer(RPC *r, char *server_name, char *filepath, UINT total_size, DOWNLOAD_PROC *proc, void *param);
+bool CheckAdminSourceAddress(SOCK *sock, char *hubname);
+void SiEnumSessionMain(SERVER *s, RPC_ENUM_SESSION *t);
+bool SiIsEmptyPassword(void *hash_password);
+
+UINT StTest(ADMIN *a, RPC_TEST *t);
+UINT StGetServerInfo(ADMIN *a, RPC_SERVER_INFO *t);
+UINT StGetServerStatus(ADMIN *a, RPC_SERVER_STATUS *t);
+UINT StCreateListener(ADMIN *a, RPC_LISTENER *t);
+UINT StEnumListener(ADMIN *a, RPC_LISTENER_LIST *t);
+UINT StDeleteListener(ADMIN *a, RPC_LISTENER *t);
+UINT StEnableListener(ADMIN *a, RPC_LISTENER *t);
+UINT StSetServerPassword(ADMIN *a, RPC_SET_PASSWORD *t);
+UINT StSetFarmSetting(ADMIN *a, RPC_FARM *t);
+UINT StGetFarmSetting(ADMIN *a, RPC_FARM *t);
+UINT StGetFarmInfo(ADMIN *a, RPC_FARM_INFO *t);
+UINT StEnumFarmMember(ADMIN *a, RPC_ENUM_FARM *t);
+UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t);
+UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
+UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
+UINT StGetServerCipher(ADMIN *a, RPC_STR *t);
+UINT StSetServerCipher(ADMIN *a, RPC_STR *t);
+UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t);
+UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t);
+UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t);
+UINT StEnumHub(ADMIN *a, RPC_ENUM_HUB *t);
+UINT StDeleteHub(ADMIN *a, RPC_DELETE_HUB *t);
+UINT StGetHubRadius(ADMIN *a, RPC_RADIUS *t);
+UINT StSetHubRadius(ADMIN *a, RPC_RADIUS *t);
+UINT StEnumConnection(ADMIN *a, RPC_ENUM_CONNECTION *t);
+UINT StDisconnectConnection(ADMIN *a, RPC_DISCONNECT_CONNECTION *t);
+UINT StGetConnectionInfo(ADMIN *a, RPC_CONNECTION_INFO *t);
+UINT StSetHubOnline(ADMIN *a, RPC_SET_HUB_ONLINE *t);
+UINT StGetHubStatus(ADMIN *a, RPC_HUB_STATUS *t);
+UINT StSetHubLog(ADMIN *a, RPC_HUB_LOG *t);
+UINT StGetHubLog(ADMIN *a, RPC_HUB_LOG *t);
+UINT StAddCa(ADMIN *a, RPC_HUB_ADD_CA *t);
+UINT StEnumCa(ADMIN *a, RPC_HUB_ENUM_CA *t);
+UINT StGetCa(ADMIN *a, RPC_HUB_GET_CA *t);
+UINT StDeleteCa(ADMIN *a, RPC_HUB_DELETE_CA *t);
+UINT StCreateLink(ADMIN *a, RPC_CREATE_LINK *t);
+UINT StEnumLink(ADMIN *a, RPC_ENUM_LINK *t);
+UINT StGetLinkStatus(ADMIN *a, RPC_LINK_STATUS *t);
+UINT StSetLinkOnline(ADMIN *a, RPC_LINK *t);
+UINT StSetLinkOffline(ADMIN *a, RPC_LINK *t);
+UINT StDeleteLink(ADMIN *a, RPC_LINK *t);
+UINT StRenameLink(ADMIN *a, RPC_RENAME_LINK *t);
+UINT StAddAccess(ADMIN *a, RPC_ADD_ACCESS *t);
+UINT StDeleteAccess(ADMIN *a, RPC_DELETE_ACCESS *t);
+UINT StEnumAccess(ADMIN *a, RPC_ENUM_ACCESS_LIST *t);
+UINT StCreateUser(ADMIN *a, RPC_SET_USER *t);
+UINT StSetUser(ADMIN *a, RPC_SET_USER *t);
+UINT StGetUser(ADMIN *a, RPC_SET_USER *t);
+UINT StDeleteUser(ADMIN *a, RPC_DELETE_USER *t);
+UINT StEnumUser(ADMIN *a, RPC_ENUM_USER *t);
+UINT StCreateGroup(ADMIN *a, RPC_SET_GROUP *t);
+UINT StSetGroup(ADMIN *a, RPC_SET_GROUP *t);
+UINT StGetGroup(ADMIN *a, RPC_SET_GROUP *t);
+UINT StDeleteGroup(ADMIN *a, RPC_DELETE_USER *t);
+UINT StEnumGroup(ADMIN *a, RPC_ENUM_GROUP *t);
+UINT StEnumSession(ADMIN *a, RPC_ENUM_SESSION *t);
+UINT StGetSessionStatus(ADMIN *a, RPC_SESSION_STATUS *t);
+UINT StDeleteSession(ADMIN *a, RPC_DELETE_SESSION *t);
+UINT StEnumMacTable(ADMIN *a, RPC_ENUM_MAC_TABLE *t);
+UINT StDeleteMacTable(ADMIN *a, RPC_DELETE_TABLE *t);
+UINT StEnumIpTable(ADMIN *a, RPC_ENUM_IP_TABLE *t);
+UINT StDeleteIpTable(ADMIN *a, RPC_DELETE_TABLE *t);
+UINT StGetLink(ADMIN *a, RPC_CREATE_LINK *t);
+UINT StSetLink(ADMIN *a, RPC_CREATE_LINK *t);
+UINT StSetAccessList(ADMIN *a, RPC_ENUM_ACCESS_LIST *t);
+UINT StSetKeep(ADMIN *a, RPC_KEEP *t);
+UINT StGetKeep(ADMIN *a, RPC_KEEP *t);
+UINT StEnableSecureNAT(ADMIN *a, RPC_HUB *t);
+UINT StDisableSecureNAT(ADMIN *a, RPC_HUB *t);
+UINT StSetSecureNATOption(ADMIN *a, VH_OPTION *t);
+UINT StGetSecureNATOption(ADMIN *a, VH_OPTION *t);
+UINT StEnumNAT(ADMIN *a, RPC_ENUM_NAT *t);
+UINT StEnumDHCP(ADMIN *a, RPC_ENUM_DHCP *t);
+UINT StGetSecureNATStatus(ADMIN *a, RPC_NAT_STATUS *t);
+UINT StEnumEthernet(ADMIN *a, RPC_ENUM_ETH *t);
+UINT StAddLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t);
+UINT StDeleteLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t);
+UINT StEnumLocalBridge(ADMIN *a, RPC_ENUM_LOCALBRIDGE *t);
+UINT StGetBridgeSupport(ADMIN *a, RPC_BRIDGE_SUPPORT *t);
+UINT StRebootServer(ADMIN *a, RPC_TEST *t);
+UINT StGetCaps(ADMIN *a, CAPSLIST *t);
+UINT StGetConfig(ADMIN *a, RPC_CONFIG *t);
+UINT StSetConfig(ADMIN *a, RPC_CONFIG *t);
+UINT StGetDefaultHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t);
+UINT StGetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t);
+UINT StSetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t);
+UINT StGetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t);
+UINT StSetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t);
+UINT StAddL3Switch(ADMIN *a, RPC_L3SW *t);
+UINT StDelL3Switch(ADMIN *a, RPC_L3SW *t);
+UINT StEnumL3Switch(ADMIN *a, RPC_ENUM_L3SW *t);
+UINT StStartL3Switch(ADMIN *a, RPC_L3SW *t);
+UINT StStopL3Switch(ADMIN *a, RPC_L3SW *t);
+UINT StAddL3If(ADMIN *a, RPC_L3IF *t);
+UINT StDelL3If(ADMIN *a, RPC_L3IF *t);
+UINT StEnumL3If(ADMIN *a, RPC_ENUM_L3IF *t);
+UINT StAddL3Table(ADMIN *a, RPC_L3TABLE *t);
+UINT StDelL3Table(ADMIN *a, RPC_L3TABLE *t);
+UINT StEnumL3Table(ADMIN *a, RPC_ENUM_L3TABLE *t);
+UINT StEnumCrl(ADMIN *a, RPC_ENUM_CRL *t);
+UINT StAddCrl(ADMIN *a, RPC_CRL *t);
+UINT StDelCrl(ADMIN *a, RPC_CRL *t);
+UINT StGetCrl(ADMIN *a, RPC_CRL *t);
+UINT StSetCrl(ADMIN *a, RPC_CRL *t);
+UINT StSetAcList(ADMIN *a, RPC_AC_LIST *t);
+UINT StGetAcList(ADMIN *a, RPC_AC_LIST *t);
+UINT StEnumLogFile(ADMIN *a, RPC_ENUM_LOG_FILE *t);
+UINT StReadLogFile(ADMIN *a, RPC_READ_LOG_FILE *t);
+UINT StAddLicenseKey(ADMIN *a, RPC_TEST *t);
+UINT StDelLicenseKey(ADMIN *a, RPC_TEST *t);
+UINT StEnumLicenseKey(ADMIN *a, RPC_ENUM_LICENSE_KEY *t);
+UINT StGetLicenseStatus(ADMIN *a, RPC_LICENSE_STATUS *t);
+UINT StSetSysLog(ADMIN *a, SYSLOG_SETTING *t);
+UINT StGetSysLog(ADMIN *a, SYSLOG_SETTING *t);
+UINT StEnumEthVLan(ADMIN *a, RPC_ENUM_ETH_VLAN *t);
+UINT StSetEnableEthVLan(ADMIN *a, RPC_TEST *t);
+UINT StSetHubMsg(ADMIN *a, RPC_MSG *t);
+UINT StGetHubMsg(ADMIN *a, RPC_MSG *t);
+UINT StCrash(ADMIN *a, RPC_TEST *t);
+UINT StGetAdminMsg(ADMIN *a, RPC_MSG *t);
+UINT StFlush(ADMIN *a, RPC_TEST *t);
+UINT StDebug(ADMIN *a, RPC_TEST *t);
+UINT StSetIPsecServices(ADMIN *a, IPSEC_SERVICES *t);
+UINT StGetIPsecServices(ADMIN *a, IPSEC_SERVICES *t);
+UINT StAddEtherIpId(ADMIN *a, ETHERIP_ID *t);
+UINT StGetEtherIpId(ADMIN *a, ETHERIP_ID *t);
+UINT StDeleteEtherIpId(ADMIN *a, ETHERIP_ID *t);
+UINT StEnumEtherIpId(ADMIN *a, RPC_ENUM_ETHERIP_ID *t);
+UINT StSetOpenVpnSstpConfig(ADMIN *a, OPENVPN_SSTP_CONFIG *t);
+UINT StGetOpenVpnSstpConfig(ADMIN *a, OPENVPN_SSTP_CONFIG *t);
+UINT StGetDDnsClientStatus(ADMIN *a, DDNS_CLIENT_STATUS *t);
+UINT StChangeDDnsClientHostname(ADMIN *a, RPC_TEST *t);
+UINT StRegenerateServerCert(ADMIN *a, RPC_TEST *t);
+UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t);
+UINT StSetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t);
+UINT StGetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t);
+UINT StGetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t);
+UINT StSetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t);
+UINT StGetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t);
+UINT StSetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t);
+UINT StSetVgsConfig(ADMIN *a, VGS_CONFIG *t);
+UINT StGetVgsConfig(ADMIN *a, VGS_CONFIG *t);
+
+UINT ScTest(RPC *r, RPC_TEST *t);
+UINT ScGetServerInfo(RPC *r, RPC_SERVER_INFO *t);
+UINT ScGetServerStatus(RPC *r, RPC_SERVER_STATUS *t);
+UINT ScCreateListener(RPC *r, RPC_LISTENER *t);
+UINT ScEnumListener(RPC *r, RPC_LISTENER_LIST *t);
+UINT ScDeleteListener(RPC *r, RPC_LISTENER *t);
+UINT ScEnableListener(RPC *r, RPC_LISTENER *t);
+UINT ScSetServerPassword(RPC *r, RPC_SET_PASSWORD *t);
+UINT ScSetFarmSetting(RPC *r, RPC_FARM *t);
+UINT ScGetFarmSetting(RPC *r, RPC_FARM *t);
+UINT ScGetFarmInfo(RPC *r, RPC_FARM_INFO *t);
+UINT ScEnumFarmMember(RPC *r, RPC_ENUM_FARM *t);
+UINT ScGetFarmConnectionStatus(RPC *r, RPC_FARM_CONNECTION_STATUS *t);
+UINT ScSetServerCert(RPC *r, RPC_KEY_PAIR *t);
+UINT ScGetServerCert(RPC *r, RPC_KEY_PAIR *t);
+UINT ScGetServerCipher(RPC *r, RPC_STR *t);
+UINT ScSetServerCipher(RPC *r, RPC_STR *t);
+UINT ScCreateHub(RPC *r, RPC_CREATE_HUB *t);
+UINT ScSetHub(RPC *r, RPC_CREATE_HUB *t);
+UINT ScGetHub(RPC *r, RPC_CREATE_HUB *t);
+UINT ScEnumHub(RPC *r, RPC_ENUM_HUB *t);
+UINT ScDeleteHub(RPC *r, RPC_DELETE_HUB *t);
+UINT ScGetHubRadius(RPC *r, RPC_RADIUS *t);
+UINT ScSetHubRadius(RPC *r, RPC_RADIUS *t);
+UINT ScEnumConnection(RPC *r, RPC_ENUM_CONNECTION *t);
+UINT ScDisconnectConnection(RPC *r, RPC_DISCONNECT_CONNECTION *t);
+UINT ScGetConnectionInfo(RPC *r, RPC_CONNECTION_INFO *t);
+UINT ScSetHubOnline(RPC *r, RPC_SET_HUB_ONLINE *t);
+UINT ScGetHubStatus(RPC *r, RPC_HUB_STATUS *t);
+UINT ScSetHubLog(RPC *r, RPC_HUB_LOG *t);
+UINT ScGetHubLog(RPC *r, RPC_HUB_LOG *t);
+UINT ScAddCa(RPC *r, RPC_HUB_ADD_CA *t);
+UINT ScEnumCa(RPC *r, RPC_HUB_ENUM_CA *t);
+UINT ScGetCa(RPC *r, RPC_HUB_GET_CA *t);
+UINT ScDeleteCa(RPC *r, RPC_HUB_DELETE_CA *t);
+UINT ScCreateLink(RPC *r, RPC_CREATE_LINK *t);
+UINT ScEnumLink(RPC *r, RPC_ENUM_LINK *t);
+UINT ScGetLinkStatus(RPC *r, RPC_LINK_STATUS *t);
+UINT ScSetLinkOnline(RPC *r, RPC_LINK *t);
+UINT ScSetLinkOffline(RPC *r, RPC_LINK *t);
+UINT ScDeleteLink(RPC *r, RPC_LINK *t);
+UINT ScRenameLink(RPC *r, RPC_RENAME_LINK *t);
+UINT ScAddAccess(RPC *r, RPC_ADD_ACCESS *t);
+UINT ScDeleteAccess(RPC *r, RPC_DELETE_ACCESS *t);
+UINT ScEnumAccess(RPC *r, RPC_ENUM_ACCESS_LIST *t);
+UINT ScCreateUser(RPC *r, RPC_SET_USER *t);
+UINT ScSetUser(RPC *r, RPC_SET_USER *t);
+UINT ScGetUser(RPC *r, RPC_SET_USER *t);
+UINT ScDeleteUser(RPC *r, RPC_DELETE_USER *t);
+UINT ScEnumUser(RPC *r, RPC_ENUM_USER *t);
+UINT ScCreateGroup(RPC *r, RPC_SET_GROUP *t);
+UINT ScSetGroup(RPC *r, RPC_SET_GROUP *t);
+UINT ScGetGroup(RPC *r, RPC_SET_GROUP *t);
+UINT ScDeleteGroup(RPC *r, RPC_DELETE_USER *t);
+UINT ScEnumGroup(RPC *r, RPC_ENUM_GROUP *t);
+UINT ScEnumSession(RPC *r, RPC_ENUM_SESSION *t);
+UINT ScGetSessionStatus(RPC *r, RPC_SESSION_STATUS *t);
+UINT ScDeleteSession(RPC *r, RPC_DELETE_SESSION *t);
+UINT ScEnumMacTable(RPC *r, RPC_ENUM_MAC_TABLE *t);
+UINT ScDeleteMacTable(RPC *r, RPC_DELETE_TABLE *t);
+UINT ScEnumIpTable(RPC *r, RPC_ENUM_IP_TABLE *t);
+UINT ScDeleteIpTable(RPC *r, RPC_DELETE_TABLE *t);
+UINT ScGetLink(RPC *a, RPC_CREATE_LINK *t);
+UINT ScSetLink(RPC *a, RPC_CREATE_LINK *t);
+UINT ScSetAccessList(RPC *r, RPC_ENUM_ACCESS_LIST *t);
+UINT ScSetKeep(RPC *r, RPC_KEEP *t);
+UINT ScGetKeep(RPC *r, RPC_KEEP *t);
+UINT ScEnableSecureNAT(RPC *r, RPC_HUB *t);
+UINT ScDisableSecureNAT(RPC *r, RPC_HUB *t);
+UINT ScSetSecureNATOption(RPC *r, VH_OPTION *t);
+UINT ScGetSecureNATOption(RPC *r, VH_OPTION *t);
+UINT ScEnumNAT(RPC *r, RPC_ENUM_NAT *t);
+UINT ScEnumDHCP(RPC *r, RPC_ENUM_DHCP *t);
+UINT ScGetSecureNATStatus(RPC *r, RPC_NAT_STATUS *t);
+UINT ScEnumEthernet(RPC *r, RPC_ENUM_ETH *t);
+UINT ScAddLocalBridge(RPC *r, RPC_LOCALBRIDGE *t);
+UINT ScDeleteLocalBridge(RPC *r, RPC_LOCALBRIDGE *t);
+UINT ScEnumLocalBridge(RPC *r, RPC_ENUM_LOCALBRIDGE *t);
+UINT ScGetBridgeSupport(RPC *r, RPC_BRIDGE_SUPPORT *t);
+UINT ScRebootServer(RPC *r, RPC_TEST *t);
+UINT ScGetCaps(RPC *r, CAPSLIST *t);
+UINT ScGetConfig(RPC *r, RPC_CONFIG *t);
+UINT ScSetConfig(RPC *r, RPC_CONFIG *t);
+UINT ScGetDefaultHubAdminOptions(RPC *r, RPC_ADMIN_OPTION *t);
+UINT ScGetHubAdminOptions(RPC *r, RPC_ADMIN_OPTION *t);
+UINT ScSetHubAdminOptions(RPC *r, RPC_ADMIN_OPTION *t);
+UINT ScGetHubExtOptions(RPC *r, RPC_ADMIN_OPTION *t);
+UINT ScSetHubExtOptions(RPC *r, RPC_ADMIN_OPTION *t);
+UINT ScAddL3Switch(RPC *r, RPC_L3SW *t);
+UINT ScDelL3Switch(RPC *r, RPC_L3SW *t);
+UINT ScEnumL3Switch(RPC *r, RPC_ENUM_L3SW *t);
+UINT ScStartL3Switch(RPC *r, RPC_L3SW *t);
+UINT ScStopL3Switch(RPC *r, RPC_L3SW *t);
+UINT ScAddL3If(RPC *r, RPC_L3IF *t);
+UINT ScDelL3If(RPC *r, RPC_L3IF *t);
+UINT ScEnumL3If(RPC *r, RPC_ENUM_L3IF *t);
+UINT ScAddL3Table(RPC *r, RPC_L3TABLE *t);
+UINT ScDelL3Table(RPC *r, RPC_L3TABLE *t);
+UINT ScEnumL3Table(RPC *r, RPC_ENUM_L3TABLE *t);
+UINT ScEnumCrl(RPC *r, RPC_ENUM_CRL *t);
+UINT ScAddCrl(RPC *r, RPC_CRL *t);
+UINT ScDelCrl(RPC *r, RPC_CRL *t);
+UINT ScGetCrl(RPC *r, RPC_CRL *t);
+UINT ScSetCrl(RPC *r, RPC_CRL *t);
+UINT ScSetAcList(RPC *r, RPC_AC_LIST *t);
+UINT ScGetAcList(RPC *r, RPC_AC_LIST *t);
+UINT ScEnumLogFile(RPC *r, RPC_ENUM_LOG_FILE *t);
+UINT ScReadLogFile(RPC *r, RPC_READ_LOG_FILE *t);
+UINT ScAddLicenseKey(RPC *r, RPC_TEST *t);
+UINT ScDelLicenseKey(RPC *r, RPC_TEST *t);
+UINT ScEnumLicenseKey(RPC *r, RPC_ENUM_LICENSE_KEY *t);
+UINT ScGetLicenseStatus(RPC *r, RPC_LICENSE_STATUS *t);
+UINT ScSetSysLog(RPC *r, SYSLOG_SETTING *t);
+UINT ScGetSysLog(RPC *r, SYSLOG_SETTING *t);
+UINT ScEnumEthVLan(RPC *r, RPC_ENUM_ETH_VLAN *t);
+UINT ScSetEnableEthVLan(RPC *r, RPC_TEST *t);
+UINT ScSetHubMsg(RPC *r, RPC_MSG *t);
+UINT ScGetHubMsg(RPC *r, RPC_MSG *t);
+UINT ScCrash(RPC *r, RPC_TEST *t);
+UINT ScGetAdminMsg(RPC *r, RPC_MSG *t);
+UINT ScFlush(RPC *r, RPC_TEST *t);
+UINT ScDebug(RPC *r, RPC_TEST *t);
+UINT ScSetIPsecServices(RPC *r, IPSEC_SERVICES *t);
+UINT ScGetIPsecServices(RPC *r, IPSEC_SERVICES *t);
+UINT ScAddEtherIpId(RPC *r, ETHERIP_ID *t);
+UINT ScGetEtherIpId(RPC *r, ETHERIP_ID *t);
+UINT ScDeleteEtherIpId(RPC *r, ETHERIP_ID *t);
+UINT ScEnumEtherIpId(RPC *r, RPC_ENUM_ETHERIP_ID *t);
+UINT ScSetOpenVpnSstpConfig(RPC *r, OPENVPN_SSTP_CONFIG *t);
+UINT ScGetOpenVpnSstpConfig(RPC *r, OPENVPN_SSTP_CONFIG *t);
+UINT ScGetDDnsClientStatus(RPC *r, DDNS_CLIENT_STATUS *t);
+UINT ScChangeDDnsClientHostname(RPC *r, RPC_TEST *t);
+UINT ScRegenerateServerCert(RPC *r, RPC_TEST *t);
+UINT ScMakeOpenVpnConfigFile(RPC *r, RPC_READ_LOG_FILE *t);
+UINT ScSetSpecialListener(RPC *r, RPC_SPECIAL_LISTENER *t);
+UINT ScGetSpecialListener(RPC *r, RPC_SPECIAL_LISTENER *t);
+UINT ScGetAzureStatus(RPC *r, RPC_AZURE_STATUS *t);
+UINT ScSetAzureStatus(RPC *r, RPC_AZURE_STATUS *t);
+UINT ScGetDDnsInternetSetting(RPC *r, INTERNET_SETTING *t);
+UINT ScSetDDnsInternetSetting(RPC *r, INTERNET_SETTING *t);
+UINT ScSetVgsConfig(RPC *r, VGS_CONFIG *t);
+UINT ScGetVgsConfig(RPC *r, VGS_CONFIG *t);
+
+void InRpcTest(RPC_TEST *t, PACK *p);
+void OutRpcTest(PACK *p, RPC_TEST *t);
+void FreeRpcTest(RPC_TEST *t);
+void InRpcServerInfo(RPC_SERVER_INFO *t, PACK *p);
+void OutRpcServerInfo(PACK *p, RPC_SERVER_INFO *t);
+void FreeRpcServerInfo(RPC_SERVER_INFO *t);
+void InRpcServerStatus(RPC_SERVER_STATUS *t, PACK *p);
+void OutRpcServerStatus(PACK *p, RPC_SERVER_STATUS *t);
+void InRpcListener(RPC_LISTENER *t, PACK *p);
+void OutRpcListener(PACK *p, RPC_LISTENER *t);
+void InRpcListenerList(RPC_LISTENER_LIST *t, PACK *p);
+void OutRpcListenerList(PACK *p, RPC_LISTENER_LIST *t);
+void FreeRpcListenerList(RPC_LISTENER_LIST *t);
+void InRpcStr(RPC_STR *t, PACK *p);
+void OutRpcStr(PACK *p, RPC_STR *t);
+void FreeRpcStr(RPC_STR *t);
+void InRpcSetPassword(RPC_SET_PASSWORD *t, PACK *p);
+void OutRpcSetPassword(PACK *p, RPC_SET_PASSWORD *t);
+void InRpcFarm(RPC_FARM *t, PACK *p);
+void OutRpcFarm(PACK *p, RPC_FARM *t);
+void FreeRpcFarm(RPC_FARM *t);
+void InRpcFarmHub(RPC_FARM_HUB *t, PACK *p);
+void OutRpcFarmHub(PACK *p, RPC_FARM_HUB *t);
+void InRpcFarmInfo(RPC_FARM_INFO *t, PACK *p);
+void OutRpcFarmInfo(PACK *p, RPC_FARM_INFO *t);
+void FreeRpcFarmInfo(RPC_FARM_INFO *t);
+void InRpcEnumFarm(RPC_ENUM_FARM *t, PACK *p);
+void OutRpcEnumFarm(PACK *p, RPC_ENUM_FARM *t);
+void FreeRpcEnumFarm(RPC_ENUM_FARM *t);
+void InRpcFarmConnectionStatus(RPC_FARM_CONNECTION_STATUS *t, PACK *p);
+void OutRpcFarmConnectionStatus(PACK *p, RPC_FARM_CONNECTION_STATUS *t);
+void InRpcHubOption(RPC_HUB_OPTION *t, PACK *p);
+void OutRpcHubOption(PACK *p, RPC_HUB_OPTION *t);
+void InRpcRadius(RPC_RADIUS *t, PACK *p);
+void OutRpcRadius(PACK *p, RPC_RADIUS *t);
+void InRpcHub(RPC_HUB *t, PACK *p);
+void OutRpcHub(PACK *p, RPC_HUB *t);
+void InRpcCreateHub(RPC_CREATE_HUB *t, PACK *p);
+void OutRpcCreateHub(PACK *p, RPC_CREATE_HUB *t);
+void InRpcEnumHub(RPC_ENUM_HUB *t, PACK *p);
+void OutRpcEnumHub(PACK *p, RPC_ENUM_HUB *t);
+void FreeRpcEnumHub(RPC_ENUM_HUB *t);
+void InRpcDeleteHub(RPC_DELETE_HUB *t, PACK *p);
+void OutRpcDeleteHub(PACK *p, RPC_DELETE_HUB *t);
+void InRpcEnumConnection(RPC_ENUM_CONNECTION *t, PACK *p);
+void OutRpcEnumConnection(PACK *p, RPC_ENUM_CONNECTION *t);
+void FreeRpcEnumConnetion(RPC_ENUM_CONNECTION *t);
+void InRpcDisconnectConnection(RPC_DISCONNECT_CONNECTION *t, PACK *p);
+void OutRpcDisconnectConnection(PACK *p, RPC_DISCONNECT_CONNECTION *t);
+void InRpcConnectionInfo(RPC_CONNECTION_INFO *t, PACK *p);
+void OutRpcConnectionInfo(PACK *p, RPC_CONNECTION_INFO *t);
+void InRpcSetHubOnline(RPC_SET_HUB_ONLINE *t, PACK *p);
+void OutRpcSetHubOnline(PACK *p, RPC_SET_HUB_ONLINE *t);
+void InRpcHubStatus(RPC_HUB_STATUS *t, PACK *p);
+void OutRpcHubStatus(PACK *p, RPC_HUB_STATUS *t);
+void InRpcHubLog(RPC_HUB_LOG *t, PACK *p);
+void OutRpcHubLog(PACK *p, RPC_HUB_LOG *t);
+void InRpcHubAddCa(RPC_HUB_ADD_CA *t, PACK *p);
+void OutRpcHubAddCa(PACK *p, RPC_HUB_ADD_CA *t);
+void FreeRpcHubAddCa(RPC_HUB_ADD_CA *t);
+void InRpcHubEnumCa(RPC_HUB_ENUM_CA *t, PACK *p);
+void OutRpcHubEnumCa(PACK *p, RPC_HUB_ENUM_CA *t);
+void FreeRpcHubEnumCa(RPC_HUB_ENUM_CA *t);
+void InRpcHubGetCa(RPC_HUB_GET_CA *t, PACK *p);
+void OutRpcHubGetCa(PACK *p, RPC_HUB_GET_CA *t);
+void FreeRpcHubGetCa(RPC_HUB_GET_CA *t);
+void InRpcHubDeleteCa(RPC_HUB_DELETE_CA *t, PACK *p);
+void OutRpcHubDeleteCa(PACK *p, RPC_HUB_DELETE_CA *t);
+void InRpcCreateLink(RPC_CREATE_LINK *t, PACK *p);
+void OutRpcCreateLink(PACK *p, RPC_CREATE_LINK *t);
+void FreeRpcCreateLink(RPC_CREATE_LINK *t);
+void InRpcEnumLink(RPC_ENUM_LINK *t, PACK *p);
+void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t);
+void FreeRpcEnumLink(RPC_ENUM_LINK *t);
+void InRpcLinkStatus(RPC_LINK_STATUS *t, PACK *p);
+void OutRpcLinkStatus(PACK *p, RPC_LINK_STATUS *t);
+void FreeRpcLinkStatus(RPC_LINK_STATUS *t);
+void InRpcLink(RPC_LINK *t, PACK *p);
+void OutRpcLink(PACK *p, RPC_LINK *t);
+void InRpcAccessEx(ACCESS *a, PACK *p, UINT index);
+void InRpcAccess(ACCESS *a, PACK *p);
+void OutRpcAccessEx(PACK *p, ACCESS *a, UINT index, UINT total);
+void OutRpcAccess(PACK *p, ACCESS *a);
+void InRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a, PACK *p);
+void OutRpcEnumAccessList(PACK *p, RPC_ENUM_ACCESS_LIST *a);
+void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a);
+void *InRpcAuthData(PACK *p, UINT *authtype);
+void OutRpcAuthData(PACK *p, void *authdata, UINT authtype);
+void FreeRpcAuthData(void *authdata, UINT authtype);
+void InRpcSetUser(RPC_SET_USER *t, PACK *p);
+void OutRpcSetUser(PACK *p, RPC_SET_USER *t);
+void FreeRpcSetUser(RPC_SET_USER *t);
+void InRpcEnumUser(RPC_ENUM_USER *t, PACK *p);
+void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t);
+void FreeRpcEnumUser(RPC_ENUM_USER *t);
+void InRpcSetGroup(RPC_SET_GROUP *t, PACK *p);
+void OutRpcSetGroup(PACK *p, RPC_SET_GROUP *t);
+void InRpcEnumGroup(RPC_ENUM_GROUP *t, PACK *p);
+void OutRpcEnumGroup(PACK *p, RPC_ENUM_GROUP *t);
+void FreeRpcEnumGroup(RPC_ENUM_GROUP *t);
+void InRpcDeleteUser(RPC_DELETE_USER *t, PACK *p);
+void OutRpcDeleteUser(PACK *p, RPC_DELETE_USER *t);
+void InRpcEnumSession(RPC_ENUM_SESSION *t, PACK *p);
+void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t);
+void FreeRpcEnumSession(RPC_ENUM_SESSION *t);
+void InRpcNodeInfo(NODE_INFO *t, PACK *p);
+void OutRpcNodeInfo(PACK *p, NODE_INFO *t);
+void InRpcSessionStatus(RPC_SESSION_STATUS *t, PACK *p);
+void OutRpcSessionStatus(PACK *p, RPC_SESSION_STATUS *t);
+void FreeRpcSessionStatus(RPC_SESSION_STATUS *t);
+void InRpcDeleteSession(RPC_DELETE_SESSION *t, PACK *p);
+void OutRpcDeleteSession(PACK *p, RPC_DELETE_SESSION *t);
+void InRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t, PACK *p);
+void OutRpcEnumMacTable(PACK *p, RPC_ENUM_MAC_TABLE *t);
+void FreeRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t);
+void InRpcEnumIpTable(RPC_ENUM_IP_TABLE *t, PACK *p);
+void OutRpcEnumIpTable(PACK *p, RPC_ENUM_IP_TABLE *t);
+void FreeRpcEnumIpTable(RPC_ENUM_IP_TABLE *t);
+void InRpcDeleteTable(RPC_DELETE_TABLE *t, PACK *p);
+void OutRpcDeleteTable(PACK *p, RPC_DELETE_TABLE *t);
+void InRpcMemInfo(MEMINFO *t, PACK *p);
+void OutRpcMemInfo(PACK *p, MEMINFO *t);
+void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p);
+void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t);
+void FreeRpcKeyPair(RPC_KEY_PAIR *t);
+void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p);
+void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t);
+void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p);
+void OutRpcDeleteAccess(PACK *p, RPC_DELETE_ACCESS *t);
+void FreeRpcSetGroup(RPC_SET_GROUP *t);
+void AdjoinRpcEnumSession(RPC_ENUM_SESSION *dest, RPC_ENUM_SESSION *src);
+void AdjoinRpcEnumMacTable(RPC_ENUM_MAC_TABLE *dest, RPC_ENUM_MAC_TABLE *src);
+void AdjoinRpcEnumIpTable(RPC_ENUM_IP_TABLE *dest, RPC_ENUM_IP_TABLE *src);
+void InRpcKeep(RPC_KEEP *t, PACK *p);
+void OutRpcKeep(PACK *p, RPC_KEEP *t);
+void InRpcOsInfo(OS_INFO *t, PACK *p);
+void OutRpcOsInfo(PACK *p, OS_INFO *t);
+void FreeRpcOsInfo(OS_INFO *t);
+void InRpcEnumEth(RPC_ENUM_ETH *t, PACK *p);
+void OutRpcEnumEth(PACK *p, RPC_ENUM_ETH *t);
+void FreeRpcEnumEth(RPC_ENUM_ETH *t);
+void InRpcLocalBridge(RPC_LOCALBRIDGE *t, PACK *p);
+void OutRpcLocalBridge(PACK *p, RPC_LOCALBRIDGE *t);
+void InRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t, PACK *p);
+void OutRpcEnumLocalBridge(PACK *p, RPC_ENUM_LOCALBRIDGE *t);
+void FreeRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t);
+void InRpcBridgeSupport(RPC_BRIDGE_SUPPORT *t, PACK *p);
+void OutRpcBridgeSupport(PACK *p, RPC_BRIDGE_SUPPORT *t);
+void InRpcConfig(RPC_CONFIG *t, PACK *p);
+void OutRpcConfig(PACK *p, RPC_CONFIG *t);
+void FreeRpcConfig(RPC_CONFIG *t);
+void InRpcAdminOption(RPC_ADMIN_OPTION *t, PACK *p);
+void OutRpcAdminOption(PACK *p, RPC_ADMIN_OPTION *t);
+void FreeRpcAdminOption(RPC_ADMIN_OPTION *t);
+void InRpcEnumL3Table(RPC_ENUM_L3TABLE *t, PACK *p);
+void OutRpcEnumL3Table(PACK *p, RPC_ENUM_L3TABLE *t);
+void FreeRpcEnumL3Table(RPC_ENUM_L3TABLE *t);
+void InRpcL3Table(RPC_L3TABLE *t, PACK *p);
+void OutRpcL3Table(PACK *p, RPC_L3TABLE *t);
+void InRpcEnumL3If(RPC_ENUM_L3IF *t, PACK *p);
+void OutRpcEnumL3If(PACK *p, RPC_ENUM_L3IF *t);
+void FreeRpcEnumL3If(RPC_ENUM_L3IF *t);
+void InRpcL3If(RPC_L3IF *t, PACK *p);
+void OutRpcL3If(PACK *p, RPC_L3IF *t);
+void InRpcL3Sw(RPC_L3SW *t, PACK *p);
+void OutRpcL3Sw(PACK *p, RPC_L3SW *t);
+void InRpcEnumL3Sw(RPC_ENUM_L3SW *t, PACK *p);
+void OutRpcEnumL3Sw(PACK *p, RPC_ENUM_L3SW *t);
+void FreeRpcEnumL3Sw(RPC_ENUM_L3SW *t);
+void InRpcCrl(RPC_CRL *t, PACK *p);
+void OutRpcCrl(PACK *p, RPC_CRL *t);
+void FreeRpcCrl(RPC_CRL *t);
+void InRpcEnumCrl(RPC_ENUM_CRL *t, PACK *p);
+void OutRpcEnumCrl(PACK *p, RPC_ENUM_CRL *t);
+void FreeRpcEnumCrl(RPC_ENUM_CRL *t);
+void InRpcInt(RPC_INT *t, PACK *p);
+void OutRpcInt(PACK *p, RPC_INT *t);
+void InRpcAcList(RPC_AC_LIST *t, PACK *p);
+void OutRpcAcList(PACK *p, RPC_AC_LIST *t);
+void FreeRpcAcList(RPC_AC_LIST *t);
+void InRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, PACK *p);
+void OutRpcEnumLogFile(PACK *p, RPC_ENUM_LOG_FILE *t);
+void FreeRpcEnumLogFile(RPC_ENUM_LOG_FILE *t);
+void AdjoinRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, RPC_ENUM_LOG_FILE *src);
+void InRpcReadLogFile(RPC_READ_LOG_FILE *t, PACK *p);
+void OutRpcReadLogFile(PACK *p, RPC_READ_LOG_FILE *t);
+void FreeRpcReadLogFile(RPC_READ_LOG_FILE *t);
+void InRpcRenameLink(RPC_RENAME_LINK *t, PACK *p);
+void OutRpcRenameLink(PACK *p, RPC_RENAME_LINK *t);
+void InRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t, PACK *p);
+void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t);
+void FreeRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t);
+void InRpcLicenseStatus(RPC_LICENSE_STATUS *t, PACK *p);
+void OutRpcLicenseStatus(PACK *p, RPC_LICENSE_STATUS *t);
+void InRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t, PACK *p);
+void OutRpcEnumEthVLan(PACK *p, RPC_ENUM_ETH_VLAN *t);
+void FreeRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t);
+void InRpcMsg(RPC_MSG *t, PACK *p);
+void OutRpcMsg(PACK *p, RPC_MSG *t);
+void FreeRpcMsg(RPC_MSG *t);
+void InRpcWinVer(RPC_WINVER *t, PACK *p);
+void OutRpcWinVer(PACK *p, RPC_WINVER *t);
+void InIPsecServices(IPSEC_SERVICES *t, PACK *p);
+void OutIPsecServices(PACK *p, IPSEC_SERVICES *t);
+void InRpcEnumEtherIpId(RPC_ENUM_ETHERIP_ID *t, PACK *p);
+void OutRpcEnumEtherIpId(PACK *p, RPC_ENUM_ETHERIP_ID *t);
+void FreeRpcEnumEtherIpId(RPC_ENUM_ETHERIP_ID *t);
+void InEtherIpId(ETHERIP_ID *t, PACK *p);
+void OutEtherIpId(PACK *p, ETHERIP_ID *t);
+void InOpenVpnSstpConfig(OPENVPN_SSTP_CONFIG *t, PACK *p);
+void OutOpenVpnSstpConfig(PACK *p, OPENVPN_SSTP_CONFIG *t);
+void InDDnsClientStatus(DDNS_CLIENT_STATUS *t, PACK *p);
+void OutDDnsClientStatus(PACK *p, DDNS_CLIENT_STATUS *t);
+void InRpcSpecialListener(RPC_SPECIAL_LISTENER *t, PACK *p);
+void OutRpcSpecialListener(PACK *p, RPC_SPECIAL_LISTENER *t);
+void InRpcAzureStatus(RPC_AZURE_STATUS *t, PACK *p);
+void OutRpcAzureStatus(PACK *p, RPC_AZURE_STATUS *t);
+void InRpcInternetSetting(INTERNET_SETTING *t, PACK *p);
+void OutRpcInternetSetting(PACK *p, INTERNET_SETTING *t);
+
+#endif // ADMIN_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/AzureClient.c b/src/Cedar/AzureClient.c
new file mode 100644
index 00000000..7bf2e183
--- /dev/null
+++ b/src/Cedar/AzureClient.c
@@ -0,0 +1,658 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// AzureClient.c
+// VPN Azure Client
+
+#include "CedarPch.h"
+
+// Wait for connection request
+void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
+{
+ // Validate arguments
+ if (ac == NULL || s == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (ac->Halt == false)
+ {
+ UCHAR uc;
+
+ // Receive 1 byte
+ if (RecvAll(s, &uc, 1, false) == 0)
+ {
+ break;
+ }
+
+ if (uc != 0)
+ {
+ // Receive a Pack
+ PACK *p = RecvPackWithHash(s);
+
+ if (p == NULL)
+ {
+ break;
+ }
+ else
+ {
+ // Verify contents of Pack
+ char opcode[MAX_SIZE];
+ char cipher_name[MAX_SIZE];
+ char hostname[MAX_SIZE];
+
+ PackGetStr(p, "opcode", opcode, sizeof(opcode));
+ PackGetStr(p, "cipher_name", cipher_name, sizeof(cipher_name));
+ PackGetStr(p, "hostname", hostname, sizeof(hostname));
+
+ if (StrCmpi(opcode, "relay") == 0)
+ {
+ IP client_ip, server_ip;
+ UINT client_port;
+ UINT server_port;
+ UCHAR session_id[SHA1_SIZE];
+
+ if (PackGetIp(p, "client_ip", &client_ip) &&
+ PackGetIp(p, "server_ip", &server_ip) &&
+ PackGetData2(p, "session_id", session_id, sizeof(session_id)))
+ {
+ client_port = PackGetInt(p, "client_port");
+ server_port = PackGetInt(p, "server_port");
+
+ if (client_port != 0 && server_port != 0)
+ {
+ SOCK *ns;
+ Debug("Connect Request from %r:%u\n", &client_ip, client_port);
+
+ // Create new socket and connect VPN Azure Server
+ if (ac->DDnsStatusCopy.InternetSetting.ProxyType == PROXY_DIRECT)
+ {
+ ns = ConnectEx2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
+ 0, (bool *)&ac->Halt);
+ }
+ else
+ {
+ ns = WpcSockConnect2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
+ &ac->DDnsStatusCopy.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT);
+ }
+
+ if (ns == NULL)
+ {
+ Debug("Connect Error.\n");
+ }
+ else
+ {
+ Debug("Connected to the relay server.\n");
+
+ SetTimeout(ns, param->DataTimeout);
+
+ if (StartSSLEx(ns, NULL, NULL, true, 0, NULL))
+ {
+ // Check certification
+ char server_cert_hash_str[MAX_SIZE];
+ UCHAR server_cert_hash[SHA1_SIZE];
+
+ Zero(server_cert_hash, sizeof(server_cert_hash));
+ GetXDigest(ns->RemoteX, server_cert_hash, true);
+
+ BinToStr(server_cert_hash_str, sizeof(server_cert_hash_str),
+ server_cert_hash, SHA1_SIZE);
+
+ if (IsEmptyStr(ac->DDnsStatusCopy.AzureCertHash) || StrCmpi(server_cert_hash_str, ac->DDnsStatusCopy.AzureCertHash) == 0)
+ {
+ if (SendAll(ns, AZURE_PROTOCOL_DATA_SIANGTURE, 24, true))
+ {
+ PACK *p2 = NewPack();
+
+ PackAddStr(p2, "hostname", hostname);
+ PackAddData(p2, "session_id", session_id, sizeof(session_id));
+
+ if (SendPackWithHash(ns, p2))
+ {
+ UCHAR uc;
+
+ if (RecvAll(ns, &uc, 1, true) != false)
+ {
+ if (uc != 0)
+ {
+ SOCK *accept_sock = GetReverseListeningSock(ac->Cedar);
+
+ if (accept_sock != NULL)
+ {
+ AddRef(ns->ref);
+
+ SetTimeout(ns, INFINITE);
+
+ Copy(&ns->Reverse_MyServerGlobalIp, &server_ip, sizeof(IP));
+ ns->Reverse_MyServerPort = server_port;
+
+ InjectNewReverseSocketToAccept(accept_sock, ns,
+ &client_ip, client_port);
+
+ ReleaseSock(accept_sock);
+ }
+ }
+ }
+ }
+
+ FreePack(p2);
+ }
+ }
+ }
+
+ ReleaseSock(ns);
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+ }
+
+ // Send 1 byte
+ uc = 0;
+ if (SendAll(s, &uc, 1, false) == 0)
+ {
+ break;
+ }
+ }
+}
+
+// VPN Azure client main thread
+void AcMainThread(THREAD *thread, void *param)
+{
+ AZURE_CLIENT *ac = (AZURE_CLIENT *)param;
+ UINT last_ip_revision = INFINITE;
+ UINT64 last_reconnect_tick = 0;
+ UINT64 next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
+ UINT num_reconnect_retry = 0;
+ UINT64 next_ddns_retry_tick = 0;
+ bool last_connect_ok = false;
+ // Validate arguments
+ if (ac == NULL || thread == NULL)
+ {
+ return;
+ }
+
+ while (ac->Halt == false)
+ {
+ UINT64 now = Tick64();
+ bool connect_was_ok = false;
+ // Wait for enabling VPN Azure function
+ if (ac->IsEnabled)
+ {
+ // VPN Azure is enabled
+ DDNS_CLIENT_STATUS st;
+ bool connect_now = false;
+ bool azure_ip_changed = false;
+
+ Lock(ac->Lock);
+ {
+ Copy(&st, &ac->DDnsStatus, sizeof(DDNS_CLIENT_STATUS));
+
+ if (StrCmpi(st.CurrentAzureIp, ac->DDnsStatusCopy.CurrentAzureIp) != 0)
+ {
+ if (IsEmptyStr(st.CurrentAzureIp) == false)
+ {
+ // Destination IP address is changed
+ connect_now = true;
+ num_reconnect_retry = 0;
+ }
+ }
+
+ if (StrCmpi(st.CurrentHostName, ac->DDnsStatusCopy.CurrentHostName) != 0)
+ {
+ // DDNS host name is changed
+ connect_now = true;
+ num_reconnect_retry = 0;
+ }
+
+ Copy(&ac->DDnsStatusCopy, &st, sizeof(DDNS_CLIENT_STATUS));
+ }
+ Unlock(ac->Lock);
+
+ if (last_ip_revision != ac->IpStatusRevision)
+ {
+ last_ip_revision = ac->IpStatusRevision;
+
+ connect_now = true;
+
+ num_reconnect_retry = 0;
+ }
+
+ if (last_reconnect_tick == 0 || (now >= (last_reconnect_tick + next_reconnect_interval)))
+ {
+ UINT r;
+
+ last_reconnect_tick = now;
+ num_reconnect_retry++;
+ next_reconnect_interval = (UINT64)num_reconnect_retry * AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
+ next_reconnect_interval = MIN(next_reconnect_interval, AZURE_CONNECT_MAX_RETRY_INTERVAL);
+
+ r = (UINT)next_reconnect_interval;
+
+ r = GenRandInterval(r / 2, r);
+
+ next_reconnect_interval = r;
+
+ connect_now = true;
+ }
+
+ if (IsEmptyStr(st.CurrentAzureIp) == false && IsEmptyStr(st.CurrentHostName) == false)
+ {
+ if (connect_now)
+ {
+ SOCK *s;
+ char *host = NULL;
+ UINT port = AZURE_SERVER_PORT;
+
+ Debug("VPN Azure: Connecting to %s...\n", st.CurrentAzureIp);
+
+ if (ParseHostPort(st.CurrentAzureIp, &host, &port, AZURE_SERVER_PORT))
+ {
+ if (st.InternetSetting.ProxyType == PROXY_DIRECT)
+ {
+ s = ConnectEx2(host, port, 0, (bool *)&ac->Halt);
+ }
+ else
+ {
+ s = WpcSockConnect2(host, port, &st.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT);
+ }
+
+ if (s != NULL)
+ {
+ PACK *p;
+ UINT64 established_tick = 0;
+
+ Debug("VPN Azure: Connected.\n");
+
+ SetTimeout(s, AZURE_PROTOCOL_CONTROL_TIMEOUT_DEFAULT);
+
+ Lock(ac->Lock);
+ {
+ ac->CurrentSock = s;
+ ac->IsConnected = true;
+ StrCpy(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp), st.CurrentAzureIp);
+ }
+ Unlock(ac->Lock);
+
+ SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), false);
+
+ // Receive parameter
+ p = RecvPackWithHash(s);
+ if (p != NULL)
+ {
+ UCHAR c;
+ AZURE_PARAM param;
+ bool hostname_changed = false;
+
+ Zero(&param, sizeof(param));
+
+ param.ControlKeepAlive = PackGetInt(p, "ControlKeepAlive");
+ param.ControlTimeout = PackGetInt(p, "ControlTimeout");
+ param.DataTimeout = PackGetInt(p, "DataTimeout");
+ param.SslTimeout = PackGetInt(p, "SslTimeout");
+
+ FreePack(p);
+
+ param.ControlKeepAlive = MAKESURE(param.ControlKeepAlive, 1000, AZURE_SERVER_MAX_KEEPALIVE);
+ param.ControlTimeout = MAKESURE(param.ControlTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);
+ param.DataTimeout = MAKESURE(param.DataTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);
+ param.SslTimeout = MAKESURE(param.SslTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);
+
+ Lock(ac->Lock);
+ {
+ Copy(&ac->AzureParam, &param, sizeof(AZURE_PARAM));
+ }
+ Unlock(ac->Lock);
+
+ SetTimeout(s, param.ControlTimeout);
+
+ // Send parameter
+ p = NewPack();
+ PackAddStr(p, "CurrentHostName", st.CurrentHostName);
+ PackAddStr(p, "CurrentAzureIp", st.CurrentAzureIp);
+ PackAddInt64(p, "CurrentAzureTimestamp", st.CurrentAzureTimestamp);
+ PackAddStr(p, "CurrentAzureSignature", st.CurrentAzureSignature);
+
+ Lock(ac->Lock);
+ {
+ if (StrCmpi(st.CurrentHostName, ac->DDnsStatus.CurrentHostName) != 0)
+ {
+ hostname_changed = true;
+ }
+ }
+ Unlock(ac->Lock);
+
+ if (hostname_changed == false)
+ {
+ if (SendPackWithHash(s, p))
+ {
+ // Receive result
+ if (RecvAll(s, &c, 1, false))
+ {
+ if (c && ac->Halt == false)
+ {
+ connect_was_ok = true;
+
+ established_tick = Tick64();
+
+ AcWaitForRequest(ac, s, &param);
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+ else
+ {
+ WHERE;
+ }
+
+ Debug("VPN Azure: Disconnected.\n");
+
+ Lock(ac->Lock);
+ {
+ ac->IsConnected = false;
+ ac->CurrentSock = NULL;
+ ClearStr(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp));
+ }
+ Unlock(ac->Lock);
+
+ if (established_tick != 0)
+ {
+ if ((established_tick + (UINT64)AZURE_CONNECT_MAX_RETRY_INTERVAL) <= Tick64())
+ {
+ // If the connected time exceeds the AZURE_CONNECT_MAX_RETRY_INTERVAL, reset the retry counter.
+ last_reconnect_tick = 0;
+ num_reconnect_retry = 0;
+ next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
+ }
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+ else
+ {
+ Debug("VPN Azure: Error: Connect Failed.\n");
+ }
+
+ Free(host);
+ }
+ }
+ }
+ }
+ else
+ {
+ last_reconnect_tick = 0;
+ num_reconnect_retry = 0;
+ next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
+ }
+
+ if (ac->Halt)
+ {
+ break;
+ }
+
+ if (connect_was_ok)
+ {
+ // If connection goes out after connected, increment connection success count to urge DDNS client query
+ next_ddns_retry_tick = Tick64() + MIN((UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF * (UINT64)(num_reconnect_retry + 1), (UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF_MAX);
+ }
+
+ if ((next_ddns_retry_tick != 0) && (Tick64() >= next_ddns_retry_tick))
+ {
+ next_ddns_retry_tick = 0;
+
+ ac->DDnsTriggerInt++;
+ }
+
+ Wait(ac->Event, rand() % 1000);
+ }
+}
+
+// Get enabled or disabled VPN Azure client
+bool AcGetEnable(AZURE_CLIENT *ac)
+{
+ // Validate arguments
+ if (ac == NULL)
+ {
+ return false;
+ }
+
+ return ac->IsEnabled;
+}
+
+// Enable or disable VPN Azure client
+void AcSetEnable(AZURE_CLIENT *ac, bool enabled)
+{
+ bool old_status;
+ // Validate arguments
+ if (ac == NULL)
+ {
+ return;
+ }
+
+ old_status = ac->IsEnabled;
+
+ ac->IsEnabled = enabled;
+
+ if (ac->IsEnabled && (ac->IsEnabled != old_status))
+ {
+ ac->DDnsTriggerInt++;
+ }
+
+ AcApplyCurrentConfig(ac, NULL);
+}
+
+// Set current configuration to VPN Azure client
+void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status)
+{
+ bool disconnect_now = false;
+ SOCK *disconnect_sock = NULL;
+ // Validate arguments
+ if (ac == NULL)
+ {
+ return;
+ }
+
+ // Get current DDNS configuration
+ Lock(ac->Lock);
+ {
+ if (ddns_status != NULL)
+ {
+ if (StrCmpi(ac->DDnsStatus.CurrentHostName, ddns_status->CurrentHostName) != 0)
+ {
+ // If host name is changed, disconnect current data connection
+ disconnect_now = true;
+ }
+
+ if (Cmp(&ac->DDnsStatus.InternetSetting, &ddns_status->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
+ {
+ // If proxy setting is changed, disconnect current data connection
+ disconnect_now = true;
+ }
+
+ Copy(&ac->DDnsStatus, ddns_status, sizeof(DDNS_CLIENT_STATUS));
+ }
+
+ if (ac->IsEnabled == false)
+ {
+ // If VPN Azure client is disabled, disconnect current data connection
+ disconnect_now = true;
+ }
+
+ if (disconnect_now)
+ {
+ if (ac->CurrentSock != NULL)
+ {
+ disconnect_sock = ac->CurrentSock;
+ AddRef(disconnect_sock->ref);
+ }
+ }
+ }
+ Unlock(ac->Lock);
+
+ if (disconnect_sock != NULL)
+ {
+ Disconnect(disconnect_sock);
+ ReleaseSock(disconnect_sock);
+ }
+
+ Set(ac->Event);
+}
+
+// Free VPN Azure client
+void FreeAzureClient(AZURE_CLIENT *ac)
+{
+ SOCK *disconnect_sock = NULL;
+ // Validate arguments
+ if (ac == NULL)
+ {
+ return;
+ }
+
+ ac->Halt = true;
+
+ Lock(ac->Lock);
+ {
+ if (ac->CurrentSock != NULL)
+ {
+ disconnect_sock = ac->CurrentSock;
+
+ AddRef(disconnect_sock->ref);
+ }
+ }
+ Unlock(ac->Lock);
+
+ if (disconnect_sock != NULL)
+ {
+ Disconnect(disconnect_sock);
+ ReleaseSock(disconnect_sock);
+ }
+
+ Set(ac->Event);
+
+ // Stop main thread
+ WaitThread(ac->MainThread, INFINITE);
+ ReleaseThread(ac->MainThread);
+
+ ReleaseEvent(ac->Event);
+
+ DeleteLock(ac->Lock);
+
+ Free(ac);
+}
+
+// Create new VPN Azure client
+AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server)
+{
+ AZURE_CLIENT *ac;
+ // Validate arguments
+ if (cedar == NULL || server == NULL)
+ {
+ return NULL;
+ }
+
+ ac = ZeroMalloc(sizeof(AZURE_CLIENT));
+
+ ac->Cedar = cedar;
+
+ ac->Server = server;
+
+ ac->Lock = NewLock();
+
+ ac->IsEnabled = false;
+
+ ac->Event = NewEvent();
+
+ // Start main thread
+ ac->MainThread = NewThread(AcMainThread, ac);
+
+ return ac;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/AzureClient.h b/src/Cedar/AzureClient.h
new file mode 100644
index 00000000..1a55a9ca
--- /dev/null
+++ b/src/Cedar/AzureClient.h
@@ -0,0 +1,149 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// AzureClient.h
+// Header of AzureClient.c
+
+#ifndef AZURE_CLIENT_H
+#define AZURE_CLIENT_H
+
+// Constants
+#define AZURE_SERVER_PORT 443
+#define AZURE_PROTOCOL_CONTROL_SIGNATURE "ACTL"
+#define AZURE_PROTOCOL_DATA_SIANGTURE "AZURE_CONNECT_SIGNATURE!"
+#define AZURE_PROTOCOL_CONTROL_TIMEOUT_DEFAULT (5 * 1000) // Default timeout
+#define AZURE_CONNECT_INITIAL_RETRY_INTERVAL (1 * 1000) // Initial re-connection interval (15 * 1000)
+#define AZURE_CONNECT_MAX_RETRY_INTERVAL (60 * 60 * 1000) // Maximum re-connection interval
+
+#define AZURE_DOMAIN_SUFFIX ".vpnazure.net"
+
+#define AZURE_SERVER_MAX_KEEPALIVE (5 * 60 * 1000)
+#define AZURE_SERVER_MAX_TIMEOUT (10 * 60 * 1000)
+
+#define AZURE_VIA_PROXY_TIMEOUT 5000
+
+
+// Communications parameter
+struct AZURE_PARAM
+{
+ UINT ControlKeepAlive;
+ UINT ControlTimeout;
+ UINT DataTimeout;
+ UINT SslTimeout;
+};
+
+// VPN Azure Client
+struct AZURE_CLIENT
+{
+ CEDAR *Cedar;
+ SERVER *Server;
+ LOCK *Lock;
+ DDNS_CLIENT_STATUS DDnsStatus;
+ volatile bool IsEnabled;
+ EVENT *Event;
+ volatile bool Halt;
+ THREAD *MainThread;
+ volatile UINT IpStatusRevision;
+ DDNS_CLIENT_STATUS DDnsStatusCopy;
+ SOCK *CurrentSock;
+ char ConnectingAzureIp[MAX_SIZE];
+ AZURE_PARAM AzureParam;
+ volatile UINT DDnsTriggerInt;
+ volatile bool IsConnected;
+};
+
+
+// Function prototype
+AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server);
+void FreeAzureClient(AZURE_CLIENT *ac);
+void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status);
+void AcMainThread(THREAD *thread, void *param);
+void AcSetEnable(AZURE_CLIENT *ac, bool enabled);
+bool AcGetEnable(AZURE_CLIENT *ac);
+void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param);
+
+
+#endif // AZURE_CLIENT_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/AzureServer.c b/src/Cedar/AzureServer.c
new file mode 100644
index 00000000..caea4c30
--- /dev/null
+++ b/src/Cedar/AzureServer.c
@@ -0,0 +1,90 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// AzureServer.c
+// VPN Azure Server
+
+#include "CedarPch.h"
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/AzureServer.h b/src/Cedar/AzureServer.h
new file mode 100644
index 00000000..c6389c35
--- /dev/null
+++ b/src/Cedar/AzureServer.h
@@ -0,0 +1,94 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// AzureServer.h
+// Header of AzureServer.c
+
+#ifndef AZURE_SERVER_H
+#define AZURE_SERVER_H
+
+
+#endif // AZURE_SERVER_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Bridge.c b/src/Cedar/Bridge.c
new file mode 100644
index 00000000..a2434995
--- /dev/null
+++ b/src/Cedar/Bridge.c
@@ -0,0 +1,532 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Bridge.c
+// Ethernet Bridge Program (Local Bridge)
+
+#include <GlobalConst.h>
+
+#define BRIDGE_C
+
+#ifdef WIN32
+#define OS_WIN32
+#endif
+
+#ifdef OS_WIN32
+
+// Win32
+#include "BridgeWin32.c"
+
+#else
+
+// Unix
+#include "BridgeUnix.c"
+
+#endif // OS_WIN32
+
+// Hash the list of current Ethernet devices
+UINT GetEthDeviceHash()
+{
+#ifdef OS_UNIX
+ // UNIX
+ UINT num;
+ UINT i;
+ char tmp[4096];
+ UCHAR hash[SHA1_SIZE];
+ TOKEN_LIST *t = GetEthList();
+
+ num = t->NumTokens;
+ tmp[0] = 0;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ StrCat(tmp, sizeof(tmp), t->Token[i]);
+ }
+ FreeToken(t);
+
+ Hash(hash, tmp, StrLen(tmp), true);
+
+ Copy(&num, hash, sizeof(UINT));
+
+ return num;
+#else // OS_UNIX
+ // Win32
+ UINT ret = 0;
+ MS_ADAPTER_LIST *a = MsCreateAdapterListEx(true);
+ UINT num;
+ UINT i;
+ char tmp[4096];
+ UCHAR hash[SHA1_SIZE];
+
+ tmp[0] = 0;
+ if (a != NULL)
+ {
+ for (i = 0;i < a->Num;i++)
+ {
+ StrCat(tmp, sizeof(tmp), a->Adapters[i]->Title);
+ }
+ }
+ MsFreeAdapterList(a);
+
+ Hash(hash, tmp, StrLen(tmp), true);
+
+ Copy(&num, hash, sizeof(UINT));
+
+ return num;
+#endif // OS_UNIX
+}
+
+// Get whether WinPcap is needed
+bool IsNeedWinPcap()
+{
+ if (IsBridgeSupported() == false)
+ {
+ // Not in Windows
+ return false;
+ }
+ else
+ {
+ // Windows
+ if (IsEthSupported())
+ {
+ // Already success to access the Ethernet device
+ return false;
+ }
+ else
+ {
+ // Failed to access the Ethernet device
+ return true;
+ }
+ }
+}
+
+// Get whether the local-bridging is supported by current OS
+bool IsBridgeSupported()
+{
+ UINT type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS(type))
+ {
+ if (IsEthSupported())
+ {
+ return true;
+ }
+ else
+ {
+ bool ret = false;
+
+#ifdef OS_WIN32
+ ret = MsIsAdmin();
+#endif // OS_WIN32
+
+ return ret;
+ }
+ }
+ else
+ {
+ return IsEthSupported();
+ }
+}
+
+// Delete a local-bridge
+bool DeleteLocalBridge(CEDAR *c, char *hubname, char *devicename)
+{
+ bool ret = false;
+ // Validate arguments
+ if (c == NULL || hubname == NULL || devicename == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->HubList);
+ {
+ LockList(c->LocalBridgeList);
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
+
+ if (StrCmpi(br->HubName, hubname) == 0)
+ {
+ if (StrCmpi(br->DeviceName, devicename) == 0)
+ {
+ if (br->Bridge != NULL)
+ {
+ BrFreeBridge(br->Bridge);
+ br->Bridge = NULL;
+ }
+
+ Delete(c->LocalBridgeList, br);
+ Free(br);
+
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(c->LocalBridgeList);
+ }
+ UnlockList(c->HubList);
+
+ return ret;
+}
+
+// Add a local-bridge
+void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast)
+{
+ UINT i;
+ HUB *h = NULL;
+ LOCALBRIDGE *br = NULL;
+ // Validate arguments
+ if (c == NULL || hubname == NULL || devicename == NULL)
+ {
+ return;
+ }
+
+ if (OS_IS_UNIX(GetOsInfo()->OsType) == false)
+ {
+ tapmode = false;
+ }
+
+ LockList(c->HubList);
+ {
+ LockList(c->LocalBridgeList);
+ {
+ bool exists = false;
+
+ // Ensure that the same configuration local-bridge doesn't exist already
+ for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
+ if (StrCmpi(br->DeviceName, devicename) == 0)
+ {
+ if (StrCmpi(br->HubName, hubname) == 0)
+ {
+ if (br->TapMode == tapmode)
+ {
+ exists = true;
+ }
+ }
+ }
+ }
+
+ if (exists == false)
+ {
+ // Add configuration
+ br = ZeroMalloc(sizeof(LOCALBRIDGE));
+ StrCpy(br->HubName, sizeof(br->HubName), hubname);
+ StrCpy(br->DeviceName, sizeof(br->DeviceName), devicename);
+ br->Bridge = NULL;
+ br->Local = local;
+ br->TapMode = tapmode;
+ br->LimitBroadcast = limit_broadcast;
+ br->Monitor = monitor;
+ if (br->TapMode)
+ {
+ if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
+ {
+ Copy(br->TapMacAddress, tapaddr, 6);
+ }
+ else
+ {
+ GenMacAddress(br->TapMacAddress);
+ }
+ }
+
+ Add(c->LocalBridgeList, br);
+
+ // Find the hub
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *hub = LIST_DATA(c->HubList, i);
+ if (StrCmpi(hub->Name, br->HubName) == 0)
+ {
+ h = hub;
+ AddRef(h->ref);
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(c->LocalBridgeList);
+ }
+ UnlockList(c->HubList);
+
+ // Start the local-bridge immediately
+ if (h != NULL && br != NULL && h->Type != HUB_TYPE_FARM_DYNAMIC)
+ {
+ Lock(h->lock_online);
+ {
+ if (h->Offline == false)
+ {
+ LockList(c->LocalBridgeList);
+ {
+ if (IsInList(c->LocalBridgeList, br))
+ {
+ if (br->Bridge == NULL)
+ {
+ br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor, br->TapMode, br->TapMacAddress, br->LimitBroadcast, br);
+ }
+ }
+ }
+ UnlockList(c->LocalBridgeList);
+ }
+ }
+ Unlock(h->lock_online);
+ }
+
+ ReleaseHub(h);
+}
+
+// Initialize the local-bridge list
+void InitLocalBridgeList(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->LocalBridgeList = NewList(NULL);
+}
+
+// Free the local-bridge list
+void FreeLocalBridgeList(CEDAR *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
+ Free(br);
+ }
+
+ ReleaseList(c->LocalBridgeList);
+ c->LocalBridgeList = NULL;
+}
+
+// Bridging thread
+void BrBridgeThread(THREAD *thread, void *param)
+{
+ BRIDGE *b;
+ CONNECTION *c;
+ SESSION *s;
+ HUB *h;
+ char name[MAX_SIZE];
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ b = (BRIDGE *)param;
+
+ // Create a connection object
+ c = NewServerConnection(b->Cedar, NULL, thread);
+ c->Protocol = CONNECTION_HUB_BRIDGE;
+
+ // Create a session object
+ s = NewServerSession(b->Cedar, c, b->Hub, BRIDGE_USER_NAME, b->Policy);
+ HLog(b->Hub, "LH_START_BRIDGE", b->Name, s->Name);
+ StrCpy(name, sizeof(name), b->Name);
+ h = b->Hub;
+ AddRef(h->ref);
+ s->BridgeMode = true;
+ s->Bridge = b;
+ c->Session = s;
+ ReleaseConnection(c);
+
+ // Dummy user name for local-bridge
+ s->Username = CopyStr(BRIDGE_USER_NAME_PRINT);
+
+ b->Session = s;
+ AddRef(s->ref);
+
+ // Notify completion
+ NoticeThreadInit(thread);
+
+ // Main procedure of the session
+ Debug("Bridge %s Start.\n", b->Name);
+ SessionMain(s);
+ Debug("Bridge %s Stop.\n", b->Name);
+
+ HLog(h, "LH_STOP_BRIDGE", name);
+
+ ReleaseHub(h);
+
+ ReleaseSession(s);
+}
+
+// Free the local-bridge object
+void BrFreeBridge(BRIDGE *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->ParentLocalBridge != NULL)
+ {
+ b->ParentLocalBridge = NULL;
+ }
+
+ // Stop session thread
+ StopSession(b->Session);
+ ReleaseSession(b->Session);
+
+ Free(b);
+}
+
+// Create new local-bridge
+BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge)
+{
+ BRIDGE *b;
+ POLICY *policy;
+ THREAD *t;
+ // Validate arguments
+ if (h == NULL || name == NULL || parent_local_bridge == NULL)
+ {
+ return NULL;
+ }
+
+ if (p == NULL)
+ {
+ policy = ClonePolicy(GetDefaultPolicy());
+ }
+ else
+ {
+ policy = ClonePolicy(p);
+ }
+
+ b = ZeroMalloc(sizeof(BRIDGE));
+ b->Cedar = h->Cedar;
+ b->Hub = h;
+ StrCpy(b->Name, sizeof(b->Name), name);
+ b->Policy = policy;
+ b->Local = local;
+ b->Monitor = monitor;
+ b->TapMode = tapmode;
+ b->LimitBroadcast = limit_broadcast;
+ b->ParentLocalBridge = parent_local_bridge;
+
+ if (b->TapMode)
+ {
+ if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
+ {
+ Copy(b->TapMacAddress, tapaddr, 6);
+ }
+ else
+ {
+ GenMacAddress(b->TapMacAddress);
+ }
+ }
+
+ if (monitor)
+ {
+ // Enabling monitoring mode
+ policy->MonitorPort = true;
+ }
+
+ if (b->LimitBroadcast == false)
+ {
+ // Disable broadcast limiter
+ policy->NoBroadcastLimiter = true;
+ }
+
+ // Start thread
+ t = NewThread(BrBridgeThread, b);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ return b;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Bridge.h b/src/Cedar/Bridge.h
new file mode 100644
index 00000000..771ef4ef
--- /dev/null
+++ b/src/Cedar/Bridge.h
@@ -0,0 +1,152 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Bridge.h
+// Header of Bridge.c
+
+#ifndef BRIDGE_H
+#define BRIDGE_H
+
+#ifdef OS_WIN32
+
+// For Win32
+#include <Cedar/BridgeWin32.h>
+
+#else
+
+// For Unix
+#include <Cedar/BridgeUnix.h>
+
+#endif // OS_WIN32
+
+// Bridge
+struct BRIDGE
+{
+ bool Active; // Status
+ CEDAR *Cedar; // Cedar
+ HUB *Hub; // HUB
+ SESSION *Session; // Session
+ POLICY *Policy; // Policy
+ ETH *Eth; // Ethernet
+ char Name[MAX_SIZE]; // Device name
+ UINT64 LastBridgeTry; // Time to try to bridge at last
+ bool Local; // Local mode
+ bool Monitor; // Monitor mode
+ bool TapMode; // Tap mode
+ bool LimitBroadcast; // Broadcasts limiting mode
+ UCHAR TapMacAddress[6]; // MAC address of the tap
+ UINT LastNumDevice; // Number of device (Number of last checked)
+ UINT64 LastNumDeviceCheck; // Time at which to check the number of devices at last
+ UINT64 LastChangeMtuError; // Time that recorded the error to change the MTU at last
+ LOCALBRIDGE *ParentLocalBridge; // Parent Local Bridge
+};
+
+// Local bridge
+struct LOCALBRIDGE
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ char DeviceName[MAX_SIZE]; // Device name
+ bool Local; // Local mode
+ bool Monitor; // Monitor mode
+ bool TapMode; // Tap mode
+ bool LimitBroadcast; // Broadcast packets limiting mode
+ UCHAR TapMacAddress[6]; // MAC address of the tap
+ BRIDGE *Bridge; // Bridge
+};
+
+BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge);
+void BrBridgeThread(THREAD *thread, void *param);
+void BrFreeBridge(BRIDGE *b);
+void InitLocalBridgeList(CEDAR *c);
+void FreeLocalBridgeList(CEDAR *c);
+void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast);
+bool DeleteLocalBridge(CEDAR *c, char *hubname, char *devicename);
+bool IsBridgeSupported();
+bool IsNeedWinPcap();
+UINT GetEthDeviceHash();
+
+#endif // BRIDGE_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/BridgeUnix.c b/src/Cedar/BridgeUnix.c
new file mode 100644
index 00000000..ee8c93a2
--- /dev/null
+++ b/src/Cedar/BridgeUnix.c
@@ -0,0 +1,1813 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// BridgeUnix.c
+// Ethernet Bridge Program (for UNIX)
+//#define BRIDGE_C
+//#define UNIX_LINUX
+
+#include <GlobalConst.h>
+
+#ifdef BRIDGE_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+#ifdef UNIX_SOLARIS
+#include <sys/sockio.h>
+#endif
+
+#ifdef BRIDGE_PCAP
+#include <pcap.h>
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+#endif // BRIDGE_BPF
+
+// Initialize
+void InitEth()
+{
+}
+
+// Free
+void FreeEth()
+{
+}
+
+// Check whether interface description string of Ethernet device can be retrieved in this system
+bool EthIsInterfaceDescriptionSupportedUnix()
+{
+ bool ret = false;
+ DIRLIST *d = EnumDir("/etc/sysconfig/networking/devices/");
+
+ if (d == NULL)
+ {
+ return false;
+ }
+
+ if (d->NumFiles >= 1)
+ {
+ ret = true;
+ }
+
+ FreeDir(d);
+
+ return ret;
+}
+
+// Get interface description string
+bool EthGetInterfaceDescriptionUnix(char *name, char *str, UINT size)
+{
+ char tmp[MAX_SIZE];
+ bool ret = false;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(str, size, name);
+
+ Format(tmp, sizeof(tmp), "/etc/sysconfig/networking/devices/ifcfg-%s", name);
+
+ b = ReadDump(tmp);
+ if (b != NULL)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#"))
+ {
+ char tmp[MAX_SIZE];
+
+ StrCpy(tmp, sizeof(tmp), line + 1);
+
+ Trim(tmp);
+ tmp[60] = 0;
+
+ StrCpy(str, size, tmp);
+
+ ret = true;
+ }
+ }
+
+ Free(line);
+
+ FreeBuf(b);
+ }
+
+ return ret;
+}
+
+// Open raw socket
+int UnixEthOpenRawSocket()
+{
+#ifdef UNIX_LINUX
+ int s;
+
+ s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (s < 0)
+ {
+ return INVALID_SOCKET;
+ }
+ else
+ {
+ return s;
+ }
+#else // UNIX_LINUX
+ return -1;
+#endif // UNIX_LINUX
+}
+
+// Is Ethernet device control supported?
+bool IsEthSupported()
+{
+ bool ret = false;
+
+#if defined(UNIX_LINUX)
+ ret = IsEthSupportedLinux();
+#elif defined(UNIX_SOLARIS)
+ ret = IsEthSupportedSolaris();
+#elif defined(BRIDGE_PCAP)
+ ret = true;
+#elif defined(BRIDGE_BPF)
+ ret = true;
+#endif
+ return ret;
+}
+
+#ifdef UNIX_LINUX
+bool IsEthSupportedLinux()
+{
+ int s;
+
+ // Try to open a raw socket
+ s = UnixEthOpenRawSocket();
+ if (s == INVALID_SOCKET)
+ {
+ // fail
+ return false;
+ }
+
+ // success
+ closesocket(s);
+
+ return true;
+}
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+bool IsEthSupportedSolaris()
+{
+ return true;
+}
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_SOLARIS
+// Get Ethernet device list on Solaris
+TOKEN_LIST *GetEthListSolaris()
+{
+ TOKEN_LIST *t;
+ int i, s;
+ LIST *o;
+
+
+ o = NewListFast(CompareStr);
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s != INVALID_SOCKET)
+ {
+ struct lifnum lifn;
+ lifn.lifn_family = AF_INET;
+ lifn.lifn_flags = 0;
+ if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) >= 0)
+ {
+ struct lifconf lifc;
+ struct lifreq *buf;
+ UINT numifs;
+ UINT bufsize;
+
+ numifs = lifn.lifn_count;
+ Debug("NumIFs:%d\n",numifs);
+ bufsize = numifs * sizeof(struct lifreq);
+ buf = Malloc(bufsize);
+
+ lifc.lifc_family = AF_INET;
+ lifc.lifc_flags = 0;
+ lifc.lifc_len = bufsize;
+ lifc.lifc_buf = (char*) buf;
+ if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) >= 0)
+ {
+ for (i = 0; i<numifs; i++)
+ {
+ if(StartWith(buf[i].lifr_name, "lo") == false){
+ Add(o, CopyStr(buf[i].lifr_name));
+ }
+ }
+ }
+ Free(buf);
+ }
+ closesocket(s);
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *name = LIST_DATA(o, i);
+ t->Token[i] = name;
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_LINUX
+// Get Ethernet device list on Linux
+TOKEN_LIST *GetEthListLinux()
+{
+ struct ifreq ifr;
+ TOKEN_LIST *t;
+ UINT i, n;
+ int s;
+ LIST *o;
+ char name[MAX_SIZE];
+
+ o = NewListFast(CompareStr);
+
+ s = UnixEthOpenRawSocket();
+ if (s != INVALID_SOCKET)
+ {
+ n = 0;
+ for (i = 0;;i++)
+ {
+ Zero(&ifr, sizeof(ifr));
+ ifr.ifr_ifindex = i;
+
+ if (ioctl(s, SIOCGIFNAME, &ifr) >= 0)
+ {
+ n = 0;
+ StrCpy(name, sizeof(name), ifr.ifr_name);
+
+ Zero(&ifr, sizeof(ifr));
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
+ if (ioctl(s, SIOCGIFHWADDR, &ifr) >= 0)
+ {
+ UINT type = ifr.ifr_hwaddr.sa_family;
+ if (type == 1 || type == 2 || type == 6 || type == 800 || type == 801)
+ {
+ if (IsInListStr(o, name) == false)
+ {
+ if (StartWith(name, "tap_") == false)
+ {
+ Add(o, CopyStr(name));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ n++;
+ if (n >= 64)
+ {
+ break;
+ }
+ }
+ }
+ closesocket(s);
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *name = LIST_DATA(o, i);
+ t->Token[i] = name;
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+#endif // UNIX_LINUX
+
+#ifdef BRIDGE_PCAP
+// Ethernet device list by Pcap API
+TOKEN_LIST *GetEthListPcap()
+{
+ pcap_if_t *alldevs;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ LIST *o;
+ TOKEN_LIST *t;
+ int i;
+
+ o = NewListFast(CompareStr);
+
+ if( pcap_findalldevs(&alldevs,errbuf) != -1)
+ {
+ pcap_if_t *dev = alldevs;
+ while(dev != NULL)
+ {
+ pcap_t *p;
+ // Device type will be unknown until open the device?
+ p = pcap_open_live(dev->name, 0, false, 0, errbuf);
+ if(p != NULL)
+ {
+ int datalink = pcap_datalink(p);
+ // Debug("type:%s\n",pcap_datalink_val_to_name(datalink));
+ pcap_close(p);
+ if(datalink == DLT_EN10MB){
+ // Enumerate only Ethernet type device
+ Add(o, CopyStr(dev->name));
+ }
+ }
+ dev = dev->next;
+ }
+ pcap_freealldevs(alldevs);
+ }
+
+ Sort(o);
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+ ReleaseList(o);
+ return t;
+}
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+// Ethernet device list by BPF API
+TOKEN_LIST *GetEthListBpf()
+{
+ struct ifaddrs *ifadrs;
+ struct sockaddr_dl *sockadr;
+ LIST *o;
+ TOKEN_LIST *t;
+ int i;
+
+ o = NewListFast(CompareStr);
+
+ // Enumerate network devices
+ if(getifaddrs( &ifadrs ) == 0)
+ {
+ struct ifaddrs *ifadr = ifadrs;
+ while(ifadr)
+ {
+ sockadr = (struct sockaddr_dl*)ifadr->ifa_addr;
+ if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER)
+ {
+ // Is this Ethernet device?
+ if(!IsInListStr(o,ifadr->ifa_name))
+ {
+ // Ignore the foregoing device (for device which have multiple MAC address)
+ Add(o, CopyStr(ifadr->ifa_name));
+ }
+ }
+ ifadr = ifadr -> ifa_next;
+ }
+ freeifaddrs(ifadrs);
+ }
+
+ Sort(o);
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+ ReleaseList(o);
+ return t;
+}
+#endif // BRIDGE_BPF
+
+// Enumerate Ethernet devices
+TOKEN_LIST *GetEthList()
+{
+ TOKEN_LIST *t = NULL;
+
+#if defined(UNIX_LINUX)
+ t = GetEthListLinux();
+#elif defined(UNIX_SOLARIS)
+ t = GetEthListSolaris();
+#elif defined(BRIDGE_PCAP)
+ t = GetEthListPcap();
+#elif defined(BRIDGE_BPF)
+ t = GetEthListBpf();
+#endif
+
+ return t;
+}
+
+#ifdef UNIX_LINUX
+// Open Ethernet device (Linux)
+ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ ETH *e;
+ struct ifreq ifr;
+ struct sockaddr_ll addr;
+ int s;
+ int index;
+ CANCEL *c;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (tapmode)
+ {
+#ifndef NO_VLAN
+ // In tap mode
+ VLAN *v = NewTap(name, tapaddr);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(name);
+ e->Title = CopyStr(name);
+ e->Cancel = VLanGetCancel(v);
+ e->IfIndex = 0;
+ e->Socket = INVALID_SOCKET;
+ e->Tap = v;
+
+ return e;
+#else // NO_VLAN
+ return NULL;
+#endif // NO_VLAN
+ }
+
+ s = UnixEthOpenRawSocket();
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ Zero(&ifr, sizeof(ifr));
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
+
+ if (ioctl(s, SIOCGIFINDEX, &ifr) < 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+
+ index = ifr.ifr_ifindex;
+
+ Zero(&addr, sizeof(addr));
+ addr.sll_family = PF_PACKET;
+ addr.sll_protocol = htons(ETH_P_ALL);
+ addr.sll_ifindex = index;
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+
+ if (local == false)
+ {
+ // Enable promiscious mode
+ Zero(&ifr, sizeof(ifr));
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+ {
+ // Failed
+ closesocket(s);
+ return NULL;
+ }
+
+ ifr.ifr_flags |= IFF_PROMISC;
+
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+ {
+ // Failed
+ closesocket(s);
+ return NULL;
+ }
+ }
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(name);
+ e->Title = CopyStr(name);
+ e->IfIndex = index;
+ e->Socket = s;
+
+ c = NewCancel();
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ c->pipe_read = c->pipe_write = -1;
+
+ UnixSetSocketNonBlockingMode(s, true);
+
+ c->SpecialFlag = true;
+ c->pipe_read = s;
+
+ e->Cancel = c;
+
+ // Get MTU
+ e->InitialMtu = EthGetMtu(e);
+
+ if (tapmode == false)
+ {
+ // Disable hardware offloading
+ UnixDisableInterfaceOffload(name);
+ }
+
+ return e;
+}
+#endif // UNIX_LINUX
+
+// Get the MTU value
+UINT EthGetMtu(ETH *e)
+{
+#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ UINT ret = 0;
+#ifdef UNIX_SOLARIS
+ struct lifreq ifr;
+#else // UNIX_SOLARIS
+ struct ifreq ifr;
+#endif // UNIX_SOLARIS
+ int s;
+ // Validate arguments
+ if (e == NULL || e->Tap != NULL)
+ {
+ return 0;
+ }
+
+ if (e->CurrentMtu != 0)
+ {
+ return e->CurrentMtu;
+ }
+
+#if defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ s = e->SocketBsdIf;
+#else // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ s = e->Socket;
+#endif // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+
+ Zero(&ifr, sizeof(ifr));
+
+#ifdef UNIX_SOLARIS
+ StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
+#else // UNIX_SOLARIS
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_SOLARIS
+ if (ioctl(s, SIOCGLIFMTU, &ifr) < 0)
+ {
+ // failed
+ return 0;
+ }
+#else // UNIX_SOLARIS
+ if (ioctl(s, SIOCGIFMTU, &ifr) < 0)
+ {
+ // failed
+ return 0;
+ }
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_SOLARIS
+ ret = ifr.lifr_mtu + 14;
+#else // UNIX_SOLARIS
+ ret = ifr.ifr_mtu + 14;
+#endif // UNIX_SOLARIS
+
+ e->CurrentMtu = ret;
+
+ Debug("%s: GetMtu: %u\n", e->Name, ret);
+
+ return ret;
+#else // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ return 0;
+#endif // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+}
+
+// Set the MTU value
+bool EthSetMtu(ETH *e, UINT mtu)
+{
+#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ UINT ret = 0;
+#ifdef UNIX_SOLARIS
+ struct lifreq ifr;
+#else // UNIX_SOLARIS
+ struct ifreq ifr;
+#endif // UNIX_SOLARIS
+ int s;
+ // Validate arguments
+ if (e == NULL || e->Tap != NULL || (mtu > 1 && mtu < 1514))
+ {
+ return false;
+ }
+ if (mtu == 0 && e->InitialMtu == 0)
+ {
+ return false;
+ }
+
+ if (mtu == 0)
+ {
+ // Restore initial MTU value when parameter mtu == 0
+ mtu = e->InitialMtu;
+ }
+
+#if defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ s = e->SocketBsdIf;
+#else // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ s = e->Socket;
+#endif // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+
+ if (e->CurrentMtu == mtu)
+ {
+ // No need to change
+ return true;
+ }
+
+ Zero(&ifr, sizeof(ifr));
+
+#ifdef UNIX_SOLARIS
+ StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
+ ifr.lifr_mtu = mtu - 14;
+#else // UNIX_SOLARIS
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
+ ifr.ifr_mtu = mtu - 14;
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_SOLARIS
+ if (ioctl(s, SIOCSLIFMTU, &ifr) < 0)
+ {
+ // Failed
+ return false;
+ }
+#else // UNIX_SOLARIS
+ if (ioctl(s, SIOCSIFMTU, &ifr) < 0)
+ {
+ // Failed
+ return false;
+ }
+#endif // UNIX_SOLARIS
+
+ e->CurrentMtu = mtu;
+
+ Debug("%s: SetMtu: %u\n", e->Name, mtu);
+
+ return true;
+#else // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ return false;
+#endif // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+}
+
+// Is changing MTU supported?
+bool EthIsChangeMtuSupported(ETH *e)
+{
+#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ // Validate arguments
+ if (e == NULL || e->Tap != NULL)
+ {
+ return false;
+ }
+
+ return true;
+#else // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+ return false;
+#endif // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
+}
+
+#ifdef UNIX_SOLARIS
+// Open Ethernet adapter (Solaris)
+ETH *OpenEthSolaris(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ char devname[MAX_SIZE];
+ UINT devid;
+ int fd;
+ ETH *e;
+ CANCEL *c;
+ struct strioctl sioc;
+
+ // Validate arguments
+ if (name == NULL || tapmode != false)
+ {
+ return NULL;
+ }
+
+ // Parse device name
+ if (ParseUnixEthDeviceName(devname, sizeof(devname), &devid, name) == false)
+ {
+ return NULL;
+ }
+
+ // Open the device
+ fd = open(devname, O_RDWR);
+ if (fd == -1)
+ {
+ // Failed
+ return NULL;
+ }
+
+ // Attach to the device
+ if (DlipAttatchRequest(fd, devid) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Verify ACK message
+ if (DlipReceiveAck(fd) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Bind to SAP
+ if (DlipBindRequest(fd) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Verify ACK message
+ if (DlipReceiveAck(fd) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Set to ignore SAP and promiscuous mode
+ if (DlipPromiscuous(fd, DL_PROMISC_SAP) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Verify ACK message
+ if (DlipReceiveAck(fd) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Set to the mode to receive self sending packet
+ if (DlipPromiscuous(fd, DL_PROMISC_PHYS) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Verify ACK message
+ if (DlipReceiveAck(fd) == false)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ // Set to raw mode
+ sioc.ic_cmd = DLIOCRAW;
+ sioc.ic_timout = -1;
+ sioc.ic_len = 0;
+ sioc.ic_dp = NULL;
+ if (ioctl(fd, I_STR, &sioc) < 0)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
+ {
+ // Failed
+ close(fd);
+ return NULL;
+ }
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(name);
+ e->Title = CopyStr(name);
+
+ c = NewCancel();
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ c->pipe_read = c->pipe_write = -1;
+
+ c->SpecialFlag = true;
+ c->pipe_read = fd;
+
+ e->Cancel = c;
+
+ e->IfIndex = -1;
+ e->Socket = fd;
+
+ UnixSetSocketNonBlockingMode(fd, true);
+
+ // Get control interface
+ e->SocketBsdIf = socket(AF_INET, SOCK_DGRAM, 0);
+
+ // Get MTU value
+ e->InitialMtu = EthGetMtu(e);
+
+ return e;
+}
+
+// Set to promiscuous mode
+bool DlipPromiscuous(int fd, UINT level)
+{
+ dl_promiscon_req_t req;
+ struct strbuf ctl;
+ int flags;
+ // Validate arguments
+ if (fd == -1)
+ {
+ return false;
+ }
+
+ Zero(&req, sizeof(req));
+ req.dl_primitive = DL_PROMISCON_REQ;
+ req.dl_level = level;
+
+ Zero(&ctl, sizeof(ctl));
+ ctl.maxlen = 0;
+ ctl.len = sizeof(req);
+ ctl.buf = (char *)&req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, NULL, flags) < 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Bind to a SAP
+bool DlipBindRequest(int fd)
+{
+ dl_bind_req_t req;
+ struct strbuf ctl;
+
+ if (fd == -1)
+ {
+ return false;
+ }
+
+ Zero(&req, sizeof(req));
+ req.dl_primitive = DL_BIND_REQ;
+ req.dl_service_mode = DL_CLDLS;
+ req.dl_sap = 0;
+
+ Zero(&ctl, sizeof(ctl));
+ ctl.maxlen = 0;
+ ctl.len = sizeof(req);
+ ctl.buf = (char *)&req;
+
+ if (putmsg(fd, &ctl, NULL, 0) < 0)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Attach to the device
+bool DlipAttatchRequest(int fd, UINT devid)
+{
+ dl_attach_req_t req;
+ struct strbuf ctl;
+ int flags;
+ // Validate arguments
+ if (fd == -1)
+ {
+ return false;
+ }
+
+ Zero(&req, sizeof(req));
+ req.dl_primitive = DL_ATTACH_REQ;
+ req.dl_ppa = devid;
+
+ Zero(&ctl, sizeof(ctl));
+ ctl.maxlen = 0;
+ ctl.len = sizeof(req);
+ ctl.buf = (char *)&req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, NULL, flags) < 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Verify the ACK message
+bool DlipReceiveAck(int fd)
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags = 0;
+ char *buf;
+ // Validate arguments
+ if (fd == -1)
+ {
+ return false;
+ }
+
+ buf = MallocFast(SOLARIS_MAXDLBUF);
+
+ Zero(&ctl, sizeof(ctl));
+ ctl.maxlen = SOLARIS_MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = buf;
+
+ if (getmsg(fd, &ctl, NULL, &flags) < 0)
+ {
+ return false;
+ }
+
+ dlp = (union DL_primitives *)ctl.buf;
+ if (dlp->dl_primitive != (UINT)DL_OK_ACK && dlp->dl_primitive != (UINT)DL_BIND_ACK)
+ {
+ Free(buf);
+ return false;
+ }
+
+ Free(buf);
+
+ return true;
+}
+
+#endif // UNIX_SOLARIS
+
+// Separate UNIX device name string into device name and id number
+bool ParseUnixEthDeviceName(char *dst_devname, UINT dst_devname_size, UINT *dst_devid, char *src_name)
+{
+ UINT len, i, j;
+
+ // Validate arguments
+ if (dst_devname == NULL || dst_devid == NULL || src_name == NULL)
+ {
+ return false;
+ }
+
+ len = strlen(src_name);
+ // Check string length
+ if(len == 0)
+ {
+ return false;
+ }
+
+ for (i = len-1; i+1 != 0; i--)
+ {
+ // Find last non-numeric character
+ if (src_name[i] < '0' || '9' < src_name[i])
+ {
+ // last character must be a number
+ if(src_name[i+1]==0)
+ {
+ return false;
+ }
+ *dst_devid = ToInt(src_name + i + 1);
+ StrCpy(dst_devname, dst_devname_size, "/dev/");
+ for (j = 0; j<i+1 && j<dst_devname_size-6; j++)
+ {
+ dst_devname[j+5] = src_name[j];
+ }
+ dst_devname[j+5]=0;
+ return true;
+ }
+ }
+ // All characters in the string was numeric: error
+ return false;
+}
+
+#if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP)
+// Initialize captured packet data structure
+struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size){
+ struct CAPTUREBLOCK *block = Malloc(sizeof(struct CAPTUREBLOCK));
+ block->Buf = data;
+ block->Size = size;
+ return block;
+}
+
+// Free captured packet data structure
+void FreeCaptureBlock(struct CAPTUREBLOCK *block){
+ Free(block);
+}
+#endif // BRIDGE_BPF || BRIDGE_PCAP
+
+#ifdef BRIDGE_PCAP
+// Callback function to receive arriving packet (Pcap)
+void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ ETH *e = (ETH*) user;
+ struct CAPTUREBLOCK *block;
+ UCHAR *data;
+
+ data = Malloc(h->caplen);
+ Copy(data, bytes, h->caplen);
+ block = NewCaptureBlock(data, h->caplen);
+ LockQueue(e->Queue);
+ // Discard arriving packet when queue filled
+ if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
+ InsertQueue(e->Queue, block);
+ e->QueueSize += h->caplen;
+ }
+ UnlockQueue(e->Queue);
+ Cancel(e->Cancel);
+ return;
+}
+
+// Relay thread for captured packet (Pcap)
+void PcapThread(THREAD *thread, void *param)
+{
+ ETH *e = (ETH*)param;
+ pcap_t *p = e->Pcap;
+ int ret;
+
+ // Notify initialize completed
+ NoticeThreadInit(thread);
+
+ // Return -1:Error -2:Terminated externally
+ ret = pcap_loop(p, -1, PcapHandler, (u_char*) e);
+ if(ret == -1){
+ e->Socket = INVALID_SOCKET;
+ pcap_perror(p, "capture");
+ }
+ return;
+}
+
+
+// Open Ethernet adapter (Pcap)
+ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ ETH *e;
+ pcap_t *p;
+ CANCEL *c;
+
+ // Validate arguments
+ if (name == NULL || tapmode != false)
+ {
+ return NULL;
+ }
+
+ // Initialize error message buffer
+ errbuf[0] = 0;
+
+ // Open capturing device
+ p = pcap_open_live(name, 65535, (local == false), 1, errbuf);
+ if(p==NULL)
+ {
+ return NULL;
+ }
+
+ // Set to non-block mode
+ // (In old BSD OSs, 'select(2)' don't block normally for BPF device. To prevent busy loop)
+ /*
+ if(pcap_setnonblock(p, true, errbuf) == -1)
+ {
+ Debug("pcap_setnonblock:%s\n",errbuf);
+ pcap_close(p);
+ return NULL;
+ }
+ */
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(name);
+ e->Title = CopyStr(name);
+ e->Queue = NewQueue();
+ e->QueueSize = 0;
+ e->Cancel = NewCancel();
+ e->IfIndex = -1;
+ e->Socket = pcap_get_selectable_fd(p);
+ e->Pcap = p;
+
+ e->CaptureThread = NewThread(PcapThread, e);
+ WaitThreadInit(e->CaptureThread);
+
+ return e;
+}
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+#ifdef BRIDGE_BPF_THREAD
+// Relay thread for captured packet (BPF)
+void BpfThread(THREAD *thread, void *param)
+{
+ ETH *e = (ETH*)param;
+ int fd = e->Socket;
+ int len;
+ int rest; // Rest size in buffer
+ UCHAR *next; // Head of next packet in buffer
+ struct CAPTUREBLOCK *block; // Data to enqueue
+ UCHAR *data;
+ struct bpf_hdr *hdr;
+
+ // Allocate the buffer
+ UCHAR *buf = Malloc(e->BufSize);
+
+ // Notify initialize completed
+ NoticeThreadInit(thread);
+
+ while(1){
+ // Determining to exit loop
+ if(e->Socket == INVALID_SOCKET){
+ break;
+ }
+
+ rest = read(fd, buf, e->BufSize);
+ if(rest < 0 && errno != EAGAIN){
+ // Error
+ close(fd);
+ e->Socket = INVALID_SOCKET;
+ Free(buf);
+ Cancel(e->Cancel);
+ return;
+ }
+ next = buf;
+ LockQueue(e->Queue);
+ while(rest>0){
+ // Cut out a packet
+ hdr = (struct bpf_hdr*)next;
+
+ // Discard arriving packet when queue filled
+ if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
+ data = Malloc(hdr->bh_caplen);
+ Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
+ block = NewCaptureBlock(data, hdr->bh_caplen);
+ InsertQueue(e->Queue, block);
+ e->QueueSize += hdr->bh_caplen;
+ }
+
+ // Find the head of next packet
+ rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
+ next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
+ }
+ UnlockQueue(e->Queue);
+ Cancel(e->Cancel);
+ }
+ Free(buf);
+ Cancel(e->Cancel);
+ return;
+}
+#endif // BRIDGE_BPF_THREAD
+
+// Open Ethernet adapter (BPF)
+ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ ETH *e;
+ CANCEL *c;
+ char devname[MAX_SIZE];
+ int n = 0;
+ int fd;
+ int ret;
+ UINT bufsize;
+ struct ifreq ifr;
+ struct timeval to;
+
+ // Find unused bpf device and open it
+ do{
+ Format(devname, sizeof(devname), "/dev/bpf%d", n++);
+ fd = open (devname, O_RDWR);
+ if(fd<0){
+ perror("open");
+ }
+ }while(fd < 0 && errno == EBUSY);
+
+ // No free bpf device was found
+ if(fd < 0){
+ Debug("BPF: No minor number are free.\n");
+ return NULL;
+ }
+
+ // Enlarge buffer size
+ n = 524288; // Somehow(In libpcap, this size is 32768)
+ while(true){
+ // Specify buffer size
+ ioctl(fd, BIOCSBLEN, &n);
+
+ // Bind to the network device
+ StrCpy(ifr.ifr_name, IFNAMSIZ, name);
+ ret = ioctl(fd, BIOCSETIF, &ifr);
+ if(ret < 0){
+ if(ret == ENOBUFS && n>1500){
+ // Inappropriate buffer size
+ // Retry with half buffer size
+ // If buffer size is under 1500 bytes, something goes wrong
+ n /= 2;
+ continue;
+ }
+ Debug("bpf: binding network failed.\n");
+ close(fd);
+ return NULL;
+ }else{
+ break;
+ }
+ }
+ bufsize = n;
+
+ // Set to promiscuous mode
+ if(local == false){
+ if (ioctl(fd, BIOCPROMISC, NULL) < 0){
+ printf("bpf: promisc mode failed.\n");
+ close(fd);
+ return NULL;
+ }
+ }
+
+
+ // Set to immediate mode (Return immediately when packet arrives)
+ n = 1;
+ if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){
+ Debug("BPF: non-block mode failed.\n");
+ close(fd);
+ return NULL;
+ }
+
+ // Set receiving self sending packet
+ n = 1;
+ if (ioctl(fd, BIOCGSEESENT, &n) < 0){
+ Debug("BPF: see sent mode failed.\n");
+ close(fd);
+ return NULL;
+ }
+
+ // Header complete mode (Generate whole header of sending packet)
+ n = 1;
+ if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){
+ Debug("BPF: Header complete mode failed.\n");
+ close(fd);
+ return NULL;
+ }
+
+ // Set timeout delay to 1 second
+ to.tv_sec = 1;
+ to.tv_usec = 0;
+ if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){
+ Debug("BPF: Read timeout setting failed.\n");
+ close(fd);
+ return NULL;
+ }
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(name);
+ e->Title = CopyStr(name);
+ e->IfIndex = -1;
+ e->Socket = fd;
+ e->BufSize = bufsize;
+
+#ifdef BRIDGE_BPF_THREAD
+ e->Queue = NewQueue();
+ e->QueueSize = 0;
+ e->Cancel = NewCancel();
+
+ // Start capture thread
+ e->CaptureThread = NewThread(BpfThread, e);
+ WaitThreadInit(e->CaptureThread);
+
+#else // BRIDGE_BPF_THREAD
+ c = NewCancel();
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ c->pipe_read = c->pipe_write = -1;
+ c->SpecialFlag = true;
+ c->pipe_read = fd;
+ e->Cancel = c;
+ e->Buffer = Malloc(bufsize);
+ e->Next = e->Buffer;
+ e->Rest = 0;
+
+ // Set to non-blocking mode
+ UnixSetSocketNonBlockingMode(fd, true);
+#endif // BRIDGE_BPF_THREAD
+
+ // Open interface control socket for FreeBSD
+ e->SocketBsdIf = socket(AF_LOCAL, SOCK_DGRAM, 0);
+
+ // Get MTU value
+ e->InitialMtu = EthGetMtu(e);
+
+ return e;
+}
+#endif // BRIDGE_BPF
+
+// Open Ethernet adapter
+ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ ETH *ret = NULL;
+
+#if defined(UNIX_LINUX)
+ ret = OpenEthLinux(name, local, tapmode, tapaddr);
+#elif defined(UNIX_SOLARIS)
+ ret = OpenEthSolaris(name, local, tapmode, tapaddr);
+#elif defined(BRIDGE_PCAP)
+ ret = OpenEthPcap(name, local, tapmode, tapaddr);
+#elif defined(BRIDGE_BPF)
+ ret = OpenEthBpf(name, local, tapmode, tapaddr);
+#endif
+
+ return ret;
+}
+
+typedef struct UNIXTHREAD
+{
+ pthread_t thread;
+ bool finished;
+} UNIXTHREAD;
+
+// Close Ethernet adapter
+void CloseEth(ETH *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (e->Tap != NULL)
+ {
+#ifndef NO_VLAN
+ FreeTap(e->Tap);
+#endif // NO_VLAN
+ }
+
+#ifdef BRIDGE_PCAP
+ {
+ struct CAPTUREBLOCK *block;
+ pcap_breakloop(e->Pcap);
+ WaitThread(e->CaptureThread, INFINITE);
+ ReleaseThread(e->CaptureThread);
+ pcap_close(e->Pcap);
+ while (block = GetNext(e->Queue)){
+ Free(block->Buf);
+ FreeCaptureBlock(block);
+ }
+ ReleaseQueue(e->Queue);
+ }
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+#ifdef BRIDGE_BPF_THREAD
+ {
+ struct CAPTUREBLOCK *block;
+ int fd = e->Socket;
+ e->Socket = INVALID_SOCKET;
+ WaitThread(e->CaptureThread, INFINITE);
+ ReleaseThread(e->CaptureThread);
+ e->Socket = fd; // restore to close after
+ while (block = GetNext(e->Queue)){
+ Free(block->Buf);
+ FreeCaptureBlock(block);
+ }
+ ReleaseQueue(e->Queue);
+ }
+#else // BRIDGE_BPF_THREAD
+ Free(e->Buffer);
+#endif // BRIDGE_BPF_THREAD
+#endif // BRIDGE_BPF
+
+ ReleaseCancel(e->Cancel);
+ Free(e->Name);
+ Free(e->Title);
+
+ // Restore MTU value
+ EthSetMtu(e, 0);
+
+ if (e->Socket != INVALID_SOCKET)
+ {
+#if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP) || defined(UNIX_SOLARIS)
+ close(e->Socket);
+#else // BRIDGE_PCAP
+ closesocket(e->Socket);
+#endif // BRIDGE_PCAP
+#if defined(BRIDGE_BPF) || defined(UNIX_SOLARIS)
+ if (e->SocketBsdIf != INVALID_SOCKET)
+ {
+ close(e->SocketBsdIf);
+ }
+#endif // BRIDGE_BPF || UNIX_SOLARIS
+ }
+
+ Free(e);
+}
+
+// Get cancel object
+CANCEL *EthGetCancel(ETH *e)
+{
+ CANCEL *c;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ c = e->Cancel;
+ AddRef(c->ref);
+
+ return c;
+}
+
+// Read a packet
+UINT EthGetPacket(ETH *e, void **data)
+{
+ UINT ret = 0;
+
+#if defined(UNIX_LINUX)
+ ret = EthGetPacketLinux(e, data);
+#elif defined(UNIX_SOLARIS)
+ ret = EthGetPacketSolaris(e, data);
+#elif defined(BRIDGE_PCAP)
+ ret = EthGetPacketPcap(e, data);
+#elif defined(BRIDGE_BPF)
+ ret = EthGetPacketBpf(e, data);
+#endif
+
+ return ret;
+}
+
+#ifdef UNIX_LINUX
+UINT EthGetPacketLinux(ETH *e, void **data)
+{
+ int s, ret;
+ UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
+ // Validate arguments
+ if (e == NULL || data == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (e->Tap != NULL)
+ {
+#ifndef NO_VLAN
+ // tap mode
+ void *buf;
+ UINT size;
+
+ if (VLanGetNextPacket(e->Tap, &buf, &size) == false)
+ {
+ return INFINITE;
+ }
+
+ *data = buf;
+ return size;
+#else // NO_VLAN
+ return INFINITE;
+#endif
+ }
+
+ s = e->Socket;
+
+ if (s == INVALID_SOCKET)
+ {
+ return INFINITE;
+ }
+
+ // Read
+ ret = read(s, tmp, sizeof(tmp));
+ if (ret == 0 || (ret == -1 && errno == EAGAIN))
+ {
+ // No packet
+ *data = NULL;
+ return 0;
+ }
+ else if (ret == -1 || ret > sizeof(tmp))
+ {
+ // Error
+ *data = NULL;
+ e->Socket = INVALID_SOCKET;
+ return INFINITE;
+ }
+ else
+ {
+ // Success to read a packet
+ *data = MallocFast(ret);
+ Copy(*data, tmp, ret);
+ return ret;
+ }
+
+ return 0;
+}
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+UINT EthGetPacketSolaris(ETH *e, void **data)
+{
+ UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
+ struct strbuf buf;
+ int s;
+ int flags = 0;
+ int ret;
+ // Validate arguments
+ if (e == NULL || data == NULL)
+ {
+ return INFINITE;
+ }
+
+ s = e->Socket;
+ if (s == INVALID_SOCKET)
+ {
+ return INFINITE;
+ }
+
+ Zero(&buf, sizeof(buf));
+ buf.buf = tmp;
+ buf.maxlen = sizeof(tmp);
+
+ ret = getmsg(s, NULL, &buf, &flags);
+
+ if (ret < 0 || ret > sizeof(tmp))
+ {
+ if (errno == EAGAIN)
+ {
+ // No packet
+ *data = NULL;
+ return 0;
+ }
+ // Error
+ *data = NULL;
+ return INFINITE;
+ }
+
+ ret = buf.len;
+
+ *data = MallocFast(ret);
+ Copy(*data, tmp, ret);
+ return ret;
+}
+#endif // UNIX_SOLARIS
+
+#ifdef BRIDGE_PCAP
+UINT EthGetPacketPcap(ETH *e, void **data)
+{
+ struct CAPTUREBLOCK *block;
+ UINT size;
+
+ LockQueue(e->Queue);
+ block = GetNext(e->Queue);
+ if(block != NULL){
+ e->QueueSize -= block->Size;
+ }
+ UnlockQueue(e->Queue);
+
+ if(block == NULL){
+ *data = NULL;
+ if(e->Socket == INVALID_SOCKET){
+ return INFINITE;
+ }
+ return 0;
+ }
+
+ *data = block->Buf;
+ size = block->Size;
+ FreeCaptureBlock(block);
+
+ return size;
+}
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+#ifdef BRIDGE_BPF_THREAD
+UINT EthGetPacketBpf(ETH *e, void **data)
+{
+ struct CAPTUREBLOCK *block;
+ UINT size;
+
+ LockQueue(e->Queue);
+ block = GetNext(e->Queue);
+ if(block != NULL){
+ e->QueueSize -= block->Size;
+ }
+ UnlockQueue(e->Queue);
+
+ if(block == NULL){
+ *data = NULL;
+ if(e->Socket == INVALID_SOCKET){
+ return INFINITE;
+ }
+ return 0;
+ }
+
+ *data = block->Buf;
+ size = block->Size;
+ FreeCaptureBlock(block);
+
+ return size;
+}
+#else // BRIDGE_BPF_THREAD
+UINT EthGetPacketBpf(ETH *e, void **data)
+{
+ struct bpf_hdr *hdr;
+
+ if(e->Rest<=0){
+ e->Rest = read(e->Socket, e->Buffer, e->BufSize);
+ if(e->Rest < 0){
+ *data = NULL;
+ if(errno != EAGAIN){
+ // Error
+ return INFINITE;
+ }
+ // No packet
+ return 0;
+ }
+ e->Next = e->Buffer;
+ }
+ // Cut out a packet
+ hdr = (struct bpf_hdr*)e->Next;
+ *data = Malloc(hdr->bh_caplen);
+ Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);
+
+ // Find the head of next packet
+ e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
+ e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
+
+ return hdr->bh_caplen;
+}
+#endif // BRIDGE_BPF_THREAD
+#endif // BRIDGE_BPF
+
+
+// Send multiple packets
+void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ EthPutPacket(e, datas[i], sizes[i]);
+ }
+}
+
+// Send a packet
+void EthPutPacket(ETH *e, void *data, UINT size)
+{
+ int s, ret;
+ // Validate arguments
+ if (e == NULL || data == NULL)
+ {
+ return;
+ }
+ if (size < 14 || size > MAX_PACKET_SIZE)
+ {
+ Free(data);
+ return;
+ }
+
+ if (e->Tap != NULL)
+ {
+#ifndef NO_VLAN
+ // tap mode
+ VLanPutPacket(e->Tap, data, size);
+#endif // NO_VLAN
+ return;
+ }
+
+ s = e->Socket;
+
+ if (s == INVALID_SOCKET)
+ {
+ Free(data);
+ return;
+ }
+
+ // Send to device
+#ifdef BRIDGE_PCAP
+ ret = pcap_inject(e->Pcap, data, size);
+ if( ret == -1 ){
+#ifdef _DEBUG
+ pcap_perror(e->Pcap, "inject");
+#endif // _DEBUG
+ Debug("EthPutPacket: ret:%d size:%d\n", ret, size);
+ }
+#else // BRIDGE_PCAP
+ ret = write(s, data, size);
+ if (ret<0)
+ {
+ Debug("EthPutPacket: ret:%d errno:%d size:%d\n", ret, errno, size);
+ }
+#endif //BRIDGE_PCAP
+
+ Free(data);
+}
+
+#endif // BRIDGE_C
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/BridgeUnix.h b/src/Cedar/BridgeUnix.h
new file mode 100644
index 00000000..275ce097
--- /dev/null
+++ b/src/Cedar/BridgeUnix.h
@@ -0,0 +1,191 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// BridgeUnix.h
+// Header of BridgeUnix.c
+
+#ifndef BRIDGEUNIX_H
+#define BRIDGEUNIX_H
+
+// Macro
+#ifndef SOL_PACKET
+#define SOL_PACKET 263
+#endif
+#ifndef ifr_newname
+#define ifr_newname ifr_ifru.ifru_slave
+#endif
+
+// Constants
+#define UNIX_ETH_TMP_BUFFER_SIZE (2000)
+#define SOLARIS_MAXDLBUF (32768)
+#define BRIDGE_MAX_QUEUE_SIZE (4096*1500)
+
+// ETH structure
+struct ETH
+{
+ char *Name; // Adapter name
+ char *Title; // Adapter title
+ CANCEL *Cancel; // Cancel object
+ int IfIndex; // Index
+ int Socket; // Socket
+ UINT InitialMtu; // Initial MTU value
+ UINT CurrentMtu; // Current MTU value
+ int SocketBsdIf; // BSD interface operation socket
+ UCHAR MacAddress[6]; // MAC address
+
+#ifdef BRIDGE_PCAP
+ void *Pcap; // Pcap descriptor
+ QUEUE *Queue; // Queue of the relay thread
+ UINT QueueSize; // Number of bytes in Queue
+ THREAD *CaptureThread; // Pcap relay thread
+#endif // BRIDGE_PCAP
+
+#ifdef BRIDGE_BPF
+ UINT BufSize; // Buffer size to read the BPF (error for other)
+#ifdef BRIDGE_BPF_THREAD
+ QUEUE *Queue; // Queue of the relay thread
+ UINT QueueSize; // Number of bytes in Queue
+ THREAD *CaptureThread; // BPF relay thread
+#else // BRIDGE_BPF_THREAD
+ UCHAR *Buffer; // Buffer to read the BPF
+ UCHAR *Next;
+ int Rest;
+#endif // BRIDGE_BPF_THREAD
+#endif // BRIDGE_BPF
+
+ VLAN *Tap; // tap
+};
+
+#if defined( BRIDGE_BPF ) || defined( BRIDGE_PCAP )
+struct CAPTUREBLOCK{
+ UINT Size;
+ UCHAR *Buf;
+};
+#endif // BRIDGE_BPF
+
+
+// Function prototype
+void InitEth();
+void FreeEth();
+bool IsEthSupported();
+bool IsEthSupportedLinux();
+bool IsEthSupportedSolaris();
+bool IsEthSupportedPcap();
+TOKEN_LIST *GetEthList();
+TOKEN_LIST *GetEthListLinux();
+TOKEN_LIST *GetEthListSolaris();
+TOKEN_LIST *GetEthListPcap();
+ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr);
+ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr);
+ETH *OpenEthSolaris(char *name, bool local, bool tapmode, char *tapaddr);
+ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr);
+bool ParseUnixEthDeviceName(char *dst_devname, UINT dst_devname_size, UINT *dst_devid, char *src_name);
+void CloseEth(ETH *e);
+CANCEL *EthGetCancel(ETH *e);
+UINT EthGetPacket(ETH *e, void **data);
+UINT EthGetPacketLinux(ETH *e, void **data);
+UINT EthGetPacketSolaris(ETH *e, void **data);
+UINT EthGetPacketPcap(ETH *e, void **data);
+UINT EthGetPacketBpf(ETH *e, void **data);
+void EthPutPacket(ETH *e, void *data, UINT size);
+void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes);
+UINT EthGetMtu(ETH *e);
+bool EthSetMtu(ETH *e, UINT mtu);
+bool EthIsChangeMtuSupported(ETH *e);
+bool EthGetInterfaceDescriptionUnix(char *name, char *str, UINT size);
+bool EthIsInterfaceDescriptionSupportedUnix();
+
+#ifdef UNIX_SOLARIS
+// Function prototype for Solaris
+bool DlipAttatchRequest(int fd, UINT devid);
+bool DlipReceiveAck(int fd);
+bool DlipPromiscuous(int fd, UINT level);
+bool DlipBindRequest(int fd);
+#endif // OS_SOLARIS
+
+int UnixEthOpenRawSocket();
+
+#endif // BRIDGEUNIX_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/BridgeWin32.c b/src/Cedar/BridgeWin32.c
new file mode 100644
index 00000000..985a5111
--- /dev/null
+++ b/src/Cedar/BridgeWin32.c
@@ -0,0 +1,2217 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// BridgeWin32.c
+// Ethernet Bridge Program (Win32)
+
+#include <GlobalConst.h>
+
+#ifdef BRIDGE_C
+
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Packet32.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+
+static WP *wp = NULL;
+static LIST *eth_list = NULL;
+
+static LOCK *eth_list_lock = NULL;
+static bool is_see_mode = false;
+static bool is_using_selow = false;
+static bool enable_selow = true;
+
+static bool g_bridge_win32_show_all_if = false;
+
+#define LOAD_DLL_ADDR(name) \
+ { \
+ void *addr = GetProcAddress(h, #name); \
+ Copy(&wp->name, &addr, sizeof(void *)); \
+ }
+
+// Set the flag which indicates whether using SeLow
+void Win32SetEnableSeLow(bool b)
+{
+ enable_selow = b;
+}
+
+// Get the flag which indicates whether using SeLow
+bool Win32GetEnableSeLow()
+{
+ return enable_selow;
+}
+
+// Set the flag which indicates whether enumerating all interfaces
+void Win32EthSetShowAllIf(bool b)
+{
+ g_bridge_win32_show_all_if = b;
+}
+
+// Get the flag which indicates whether enumerating all interfaces
+bool Win32EthGetShowAllIf()
+{
+ return g_bridge_win32_show_all_if;
+}
+
+// Compare Ethernet device list
+int CmpRpcEnumEthVLan(void *p1, void *p2)
+{
+ RPC_ENUM_ETH_VLAN_ITEM *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *((RPC_ENUM_ETH_VLAN_ITEM **)p1);
+ v2 = *((RPC_ENUM_ETH_VLAN_ITEM **)p2);
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(v1->DeviceName, v2->DeviceName);
+}
+
+// Get the value of MTU (Not supported in Windows)
+UINT EthGetMtu(ETH *e)
+{
+ return 0;
+}
+
+// Set the value of MTU (Not supported in Windows)
+bool EthSetMtu(ETH *e, UINT mtu)
+{
+ return false;
+}
+
+// Check whether setting MEU value (Not supported in Windows)
+bool EthIsChangeMtuSupported(ETH *e)
+{
+ return false;
+}
+
+// Set the state of VLAN tag pass-through
+bool SetVLanEnableStatus(char *title, bool enable)
+{
+ RPC_ENUM_ETH_VLAN t;
+ RPC_ENUM_ETH_VLAN_ITEM *e;
+ bool ret = false;
+ char key[MAX_SIZE];
+ char tcpkey[MAX_SIZE];
+ char short_key[MAX_SIZE];
+ // Validate arguments
+ if (title == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (EnumEthVLanWin32(&t) == false)
+ {
+ return false;
+ }
+
+ e = FindEthVLanItem(&t, title);
+
+ if (e != NULL)
+ {
+ if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid))
+ {
+ if (StrCmpi(e->DriverType, "Intel") == 0)
+ {
+ if (enable)
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, key, "VlanFiltering", "0");
+ MsRegWriteStr(REG_LOCAL_MACHINE, key, "TaggingMode", "0");
+ MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorMode", 1);
+ MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled", 1);
+ }
+ else
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE, key, "TaggingMode") == 0)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, key, "TaggingMode");
+ }
+
+ if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode") == 1)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorMode");
+ }
+
+ if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled") == 1)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
+ }
+ }
+
+ ret = true;
+ }
+ else if (StrCmpi(e->DriverType, "Broadcom") == 0)
+ {
+ if (enable)
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket", "1");
+ }
+ else
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket");
+ }
+
+ ret = true;
+ }
+ else if (StrCmpi(e->DriverType, "Marvell") == 0)
+ {
+ if (enable)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip", 1);
+ }
+ else
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip");
+ }
+
+ ret = true;
+ }
+
+ Format(tcpkey, sizeof(tcpkey),
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ e->Guid);
+
+ if (enable)
+ {
+ if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, tcpkey, "MTU", 1500);
+ }
+ }
+ else
+ {
+ UINT mtu = MsRegReadInt(REG_LOCAL_MACHINE, tcpkey, "MTU");
+ if (mtu == 1500)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, tcpkey, "MTU");
+ }
+ }
+ }
+ }
+
+ FreeRpcEnumEthVLan(&t);
+
+ return ret;
+}
+
+// Find Ethernet device
+RPC_ENUM_ETH_VLAN_ITEM *FindEthVLanItem(RPC_ENUM_ETH_VLAN *t, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ if (StrCmpi(t->Items[i].DeviceName, name) == 0)
+ {
+ return &t->Items[i];
+ }
+ }
+
+ return NULL;
+}
+
+// Get the state of VLAN tag pass-through
+void GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
+{
+ char key[MAX_SIZE];
+ char short_key[MAX_SIZE];
+ char tcpkey[MAX_SIZE];
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ e->Enabled = false;
+
+ if (e->Support == false)
+ {
+ return;
+ }
+
+ if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid) == false)
+ {
+ return;
+ }
+
+ Format(tcpkey, sizeof(tcpkey),
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ e->Guid);
+
+ if (StrCmpi(e->DriverType, "Intel") == 0)
+ {
+ char *VlanFiltering = MsRegReadStr(REG_LOCAL_MACHINE, key, "VlanFiltering");
+ UINT MonitorMode = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode");
+ UINT MonitorModeEnabled = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
+ char *TaggingMode = MsRegReadStr(REG_LOCAL_MACHINE, key, "TaggingMode");
+
+ if (StrCmpi(VlanFiltering, "0") == 0 &&
+ MonitorMode == 1 &&
+ MonitorModeEnabled == 1 &&
+ StrCmpi(TaggingMode, "0") == 0)
+ {
+ e->Enabled = true;
+ }
+
+ Free(VlanFiltering);
+ Free(TaggingMode);
+ }
+ else if (StrCmpi(e->DriverType, "Broadcom") == 0)
+ {
+ char *PreserveVlanInfoInRxPacket = MsRegReadStr(REG_LOCAL_MACHINE,
+ key, "PreserveVlanInfoInRxPacket");
+
+ if (StrCmpi(PreserveVlanInfoInRxPacket, "1") == 0)
+ {
+ e->Enabled = true;
+ }
+
+ Free(PreserveVlanInfoInRxPacket);
+ }
+ else if (StrCmpi(e->DriverType, "Marvell") == 0)
+ {
+ DWORD SkDisableVlanStrip = MsRegReadInt(REG_LOCAL_MACHINE,
+ key, "SkDisableVlanStrip");
+
+ if (SkDisableVlanStrip == 1)
+ {
+ e->Enabled = true;
+ }
+ }
+
+ if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
+ {
+ e->Enabled = false;
+ }
+}
+
+// Get VLAN tag pass-through availability of the device
+void GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
+{
+ BUF *b;
+ char filename[MAX_SIZE];
+ void *wow;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ wow = MsDisableWow64FileSystemRedirection();
+
+ // Read the device driver file
+ CombinePath(filename, sizeof(filename), MsGetSystem32Dir(), "drivers");
+ CombinePath(filename, sizeof(filename), filename, e->DriverName);
+
+ b = ReadDump(filename);
+
+ if (b != NULL)
+ {
+ char intel1[] = "VlanFiltering";
+ char intel2[] = "V\0l\0a\0n\0F\0i\0l\0t\0e\0r\0i\0n\0g";
+ char intel3[] = "MonitorMode";
+ char intel4[] = "M\0o\0n\0i\0t\0o\0r\0M\0o\0d\0e";
+ char intel5[] = "TaggingMode";
+ char intel6[] = "T\0a\0g\0g\0i\0n\0g\0M\0o\0d\0e";
+ char broadcom1[] = "PreserveVlanInfoInRxPacket";
+ char broadcom2[] = "P\0r\0e\0s\0e\0r\0v\0e\0V\0l\0a\0n\0I\0n\0f\0o\0I\0n\0R\0x\0P\0a\0c\0k\0e\0t";
+ char marvell1[] = "SkDisableVlanStrip";
+ char marvell2[] = "S\0k\0D\0i\0s\0a\0b\0l\0e\0V\0l\0a\0n\0S\0t\0r\0i\0p";
+ char *driver_type = "";
+
+ if (SearchBin(b->Buf, 0, b->Size, intel1, sizeof(intel1)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, intel2, sizeof(intel2)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, intel3, sizeof(intel3)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, intel4, sizeof(intel4)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, intel5, sizeof(intel5)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, intel6, sizeof(intel6)) != INFINITE)
+ {
+ driver_type = "Intel";
+ }
+ else if (SearchBin(b->Buf, 0, b->Size, broadcom1, sizeof(broadcom1)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, broadcom2, sizeof(broadcom2)) != INFINITE)
+ {
+ driver_type = "Broadcom";
+ }
+ else if (SearchBin(b->Buf, 0, b->Size, marvell1, sizeof(marvell1)) != INFINITE
+ || SearchBin(b->Buf, 0, b->Size, marvell2, sizeof(marvell2)) != INFINITE)
+ {
+ driver_type = "Marvell";
+ }
+
+ if (IsEmptyStr(driver_type) == false)
+ {
+ StrCpy(e->DriverType, sizeof(e->DriverType), driver_type);
+ e->Support = true;
+ }
+
+ FreeBuf(b);
+ }
+
+ MsRestoreWow64FileSystemRedirection(wow);
+}
+
+// Get the device instance id from short_key
+char *SearchDeviceInstanceIdFromShortKey(char *short_key)
+{
+ char *ret = NULL;
+ TOKEN_LIST *t1;
+ // Validate arguments
+ if (short_key == NULL)
+ {
+ return NULL;
+ }
+
+ t1 = MsRegEnumKey(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum");
+
+ if (t1 != NULL)
+ {
+ TOKEN_LIST *t2;
+ char tmp[MAX_SIZE];
+ UINT i;
+
+ for (i = 0;i < t1->NumTokens;i++)
+ {
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Enum\\%s", t1->Token[i]);
+
+ t2 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp);
+
+ if (t2 != NULL)
+ {
+ TOKEN_LIST *t3;
+ UINT i;
+
+ for (i = 0;i < t2->NumTokens;i++)
+ {
+ char tmp2[MAX_SIZE];
+
+ Format(tmp2, sizeof(tmp2), "%s\\%s", tmp, t2->Token[i]);
+
+ t3 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp2);
+
+ if (t3 != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t3->NumTokens;i++)
+ {
+ char tmp3[MAX_SIZE];
+ char *s;
+
+ Format(tmp3, sizeof(tmp3), "%s\\%s", tmp2, t3->Token[i]);
+
+ s = MsRegReadStr(REG_LOCAL_MACHINE, tmp3, "Driver");
+
+ if (s != NULL)
+ {
+ if (StrCmpi(s, short_key) == 0)
+ {
+ if (ret != NULL)
+ {
+ Free(ret);
+ }
+
+ ret = CopyStr(tmp3 + StrLen("SYSTEM\\CurrentControlSet\\Enum\\"));
+ }
+
+ Free(s);
+ }
+ }
+
+ FreeToken(t3);
+ }
+ }
+
+ FreeToken(t2);
+ }
+ }
+
+ FreeToken(t1);
+ }
+
+ return ret;
+}
+
+// Get VLAN tag pass-through availability of all devices
+bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_ETH_VLAN));
+
+ if (MsIsWin2000OrGreater() == false)
+ {
+ return false;
+ }
+
+ if (IsEthSupported() == false)
+ {
+ return false;
+ }
+
+ // Get device list
+ Lock(eth_list_lock);
+
+ InitEthAdaptersList();
+
+ o = NewListFast(CmpRpcEnumEthVLan);
+
+ for (i = 0;i < LIST_NUM(eth_list);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+
+ if (IsEmptyStr(a->Guid) == false)
+ {
+ char class_key[MAX_SIZE];
+ char short_key[MAX_SIZE];
+
+ if (GetClassRegKeyWin32(class_key, sizeof(class_key),
+ short_key, sizeof(short_key), a->Guid))
+ {
+ char *device_instance_id = MsRegReadStr(REG_LOCAL_MACHINE, class_key, "DeviceInstanceID");
+
+ if (IsEmptyStr(device_instance_id))
+ {
+ Free(device_instance_id);
+ device_instance_id = SearchDeviceInstanceIdFromShortKey(short_key);
+ }
+
+ if (IsEmptyStr(device_instance_id) == false)
+ {
+ char device_key[MAX_SIZE];
+ char *service_name;
+
+ Format(device_key, sizeof(device_key), "SYSTEM\\CurrentControlSet\\Enum\\%s",
+ device_instance_id);
+
+ service_name = MsRegReadStr(REG_LOCAL_MACHINE, device_key, "Service");
+ if (IsEmptyStr(service_name) == false)
+ {
+ char service_key[MAX_SIZE];
+ char *sys;
+
+ Format(service_key, sizeof(service_key),
+ "SYSTEM\\CurrentControlSet\\services\\%s",
+ service_name);
+
+ sys = MsRegReadStr(REG_LOCAL_MACHINE, service_key, "ImagePath");
+
+ if (IsEmptyStr(sys) == false)
+ {
+ char sysname[MAX_PATH];
+
+ GetFileNameFromFilePath(sysname, sizeof(sysname), sys);
+
+ Trim(sysname);
+
+ if (EndWith(sysname, ".sys"))
+ {
+ // device found
+ RPC_ENUM_ETH_VLAN_ITEM *e = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM));
+
+ StrCpy(e->DeviceName, sizeof(e->DeviceName), a->Title);
+ StrCpy(e->Guid, sizeof(e->Guid), a->Guid);
+ StrCpy(e->DeviceInstanceId, sizeof(e->DeviceInstanceId), device_instance_id);
+ StrCpy(e->DriverName, sizeof(e->DriverName), sysname);
+
+ // Get VLAN tag pass-through availability of the device
+ GetVLanSupportStatus(e);
+
+ // Get current pass-through setting of the device
+ GetVLanEnableStatus(e);
+
+ Insert(o, e);
+ }
+ }
+
+ Free(sys);
+ }
+
+ Free(service_name);
+ }
+
+ Free(device_instance_id);
+ }
+ }
+ }
+
+ t->NumItem = LIST_NUM(o);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * i);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RPC_ENUM_ETH_VLAN_ITEM *e = LIST_DATA(o, i);
+
+ Copy(&t->Items[i], e, sizeof(RPC_ENUM_ETH_VLAN_ITEM));
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+
+ Unlock(eth_list_lock);
+
+ return true;
+}
+
+// Get registry key of the network class data by GUID
+bool GetClassRegKeyWin32(char *key, UINT key_size, char *short_key, UINT short_key_size, char *guid)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (key == NULL || short_key == NULL || guid == NULL)
+ {
+ return false;
+ }
+
+ t = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char keyname[MAX_SIZE];
+ char *value;
+
+ Format(keyname, sizeof(keyname),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
+ t->Token[i]);
+
+ value = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "NetCfgInstanceId");
+
+ if (StrCmpi(value, guid) == 0)
+ {
+ ret = true;
+
+ StrCpy(key, key_size, keyname);
+
+ Format(short_key, short_key_size, "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
+ t->Token[i]);
+ }
+
+ Free(value);
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Send multiple packets
+void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
+{
+ UINT i, total_size;
+ UCHAR *buf;
+ UINT write_pointer;
+ UINT err = 0;
+ // Validate arguments
+ if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
+ {
+ return;
+ }
+ if (e->HasFatalError)
+ {
+ return;
+ }
+
+ if (e->SuAdapter != NULL)
+ {
+ bool ok = true;
+
+ // Send packets with SeLow
+ for (i = 0;i < num;i++)
+ {
+ UCHAR *data = datas[i];
+ UINT size = sizes[i];
+
+ if (ok)
+ {
+ // Actually, only enqueuing
+ ok = SuPutPacket(e->SuAdapter, data, size);
+ }
+
+ if (ok == false)
+ {
+ // Free memory on write error
+ Free(data);
+ }
+ }
+
+ if (ok)
+ {
+ // Send all data in queue at once
+ ok = SuPutPacket(e->SuAdapter, NULL, 0);
+ }
+
+ if (ok == false)
+ {
+ // Error occurred
+ e->HasFatalError = true;
+ }
+
+ return;
+ }
+
+ if (IsWin32BridgeWithSee() == false)
+ {
+ if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())
+ {
+ e->LastSetSingleCpu = Tick64();
+ MsSetThreadSingleCpu();
+ }
+ }
+
+ // Calculate buffer size
+ total_size = 0;
+ for (i = 0;i < num;i++)
+ {
+ void *data = datas[i];
+ UINT size = sizes[i];
+ if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
+ {
+ total_size += size + sizeof(struct dump_bpf_hdr);
+ }
+ }
+
+ buf = MallocFast(total_size * 100 / 75 + 1600);
+
+ write_pointer = 0;
+ // Enqueue
+ for (i = 0;i < num;i++)
+ {
+ void *data = datas[i];
+ UINT size = sizes[i];
+ if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
+ {
+ struct dump_bpf_hdr *h;
+
+ h = (struct dump_bpf_hdr *)(buf + write_pointer);
+ Zero(h, sizeof(struct dump_bpf_hdr));
+ h->caplen = h->len = size;
+ write_pointer += sizeof(struct dump_bpf_hdr);
+ Copy(buf + write_pointer, data, size);
+ write_pointer += size;
+
+ PROBE_DATA2("EthPutPackets", data, size);
+ }
+ // Free original buffer
+ Free(data);
+ }
+
+ // Send
+ if (total_size != 0)
+ {
+ err = wp->PacketSendPackets(e->Adapter, buf, total_size, true);
+ }
+
+ Free(buf);
+
+ if (err == 0x7FFFFFFF)
+ {
+ // Critical error (infinite loop) occurred on sending
+ e->HasFatalError = true;
+ }
+}
+
+// Send a packet
+void EthPutPacket(ETH *e, void *data, UINT size)
+{
+ // Validate arguments
+ if (e == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ EthPutPackets(e, 1, &data, &size);
+}
+
+// Read next packet
+UINT EthGetPacket(ETH *e, void **data)
+{
+ BLOCK *b;
+ bool flag = false;
+ // Validate arguments
+ if (e == NULL || data == NULL)
+ {
+ return INFINITE;
+ }
+ if (e->HasFatalError)
+ {
+ return INFINITE;
+ }
+
+ if (e->SuAdapter != NULL)
+ {
+ // Read packet with SeLow
+ UINT size;
+ if (SuGetNextPacket(e->SuAdapter, data, &size) == false)
+ {
+ // Error occurred
+ e->HasFatalError = true;
+ return INFINITE;
+ }
+
+ return size;
+ }
+
+RETRY:
+ // Check the presence of the packet in queue
+ b = GetNext(e->PacketQueue);
+ if (b != NULL)
+ {
+ UINT size;
+ size = b->Size;
+ *data = b->Buf;
+ Free(b);
+
+ if (e->PacketQueue->num_item == 0)
+ {
+ e->Empty = true;
+ }
+
+ return size;
+ }
+
+ if (e->Empty)
+ {
+ e->Empty = false;
+ return 0;
+ }
+
+ if (flag == false)
+ {
+ // Try to get next packet
+ PROBE_STR("EthGetPacket: PacketInitPacket");
+ wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize);
+ PROBE_STR("EthGetPacket: PacketReceivePacket");
+ if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false)
+ {
+ // Failed
+ return INFINITE;
+ }
+ else
+ {
+ UCHAR *buf;
+ UINT total;
+ UINT offset;
+
+ buf = (UCHAR *)e->Packet->Buffer;
+ total = e->Packet->ulBytesReceived;
+ offset = 0;
+
+ while (offset < total)
+ {
+ struct bpf_hdr *header;
+ UINT packet_size;
+ UCHAR *packet_data;
+
+ header = (struct bpf_hdr *)(buf + offset);
+ packet_size = header->bh_caplen;
+ offset += header->bh_hdrlen;
+ packet_data = buf + offset;
+ offset = Packet_WORDALIGN(offset + packet_size);
+
+ if (packet_size >= 14)
+ {
+ UCHAR *tmp;
+ BLOCK *b;
+
+ PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size);
+
+ tmp = MallocFast(packet_size);
+
+ Copy(tmp, packet_data, packet_size);
+ b = NewBlock(tmp, packet_size, 0);
+ InsertQueue(e->PacketQueue, b);
+ }
+ }
+
+ flag = true;
+ goto RETRY;
+ }
+ }
+
+ // No more packet
+ return 0;
+}
+
+// Get cancel object
+CANCEL *EthGetCancel(ETH *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ AddRef(e->Cancel->ref);
+
+ return e->Cancel;
+}
+
+// Close adapter
+void CloseEth(ETH *e)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ ReleaseCancel(e->Cancel);
+
+ if (e->SuAdapter != NULL)
+ {
+ // Close SeLow adapter
+ SuCloseAdapter(e->SuAdapter);
+ SuFree(e->Su);
+ }
+ else
+ {
+ // Close SEE adapter
+ wp->PacketCloseAdapter(e->Adapter);
+ wp->PacketFreePacket(e->Packet);
+ wp->PacketFreePacket(e->PutPacket);
+ }
+
+ while (b = GetNext(e->PacketQueue))
+ {
+ FreeBlock(b);
+ }
+ ReleaseQueue(e->PacketQueue);
+
+ Free(e->Name);
+ Free(e->Title);
+ Free(e->Buffer);
+
+ Free(e);
+}
+
+// Search adapter with the name
+struct WP_ADAPTER *Win32EthSearch(char *name)
+{
+ UINT i;
+ UINT id;
+ char simple_name[MAX_SIZE];
+ WP_ADAPTER *ret = NULL;
+
+ id = Win32EthGetNameAndIdFromCombinedName(simple_name, sizeof(simple_name), name);
+
+ if (id != 0)
+ {
+ UINT num_match = 0;
+ // Search with ID when ID is specified
+ for (i = 0;i < LIST_NUM(eth_list);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+
+ if (a->Id != 0 && a->Id == id)
+ {
+ ret = a;
+ num_match++;
+ }
+ }
+
+ if (num_match >= 2)
+ {
+ // If the ID matches to 2 or more devices, search with the name
+ for (i = 0;i < LIST_NUM(eth_list);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+
+ if (a->Id != 0 && a->Id == id)
+ {
+ if (StrCmpi(a->Title, name) == 0)
+ {
+ ret = a;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Search with name when ID is not specified
+ for (i = 0;i < LIST_NUM(eth_list);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+
+ if (StrCmpi(a->Title, name) == 0)
+ {
+ ret = a;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Open adapter
+ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ ETH *ret;
+ void *p;
+
+ p = MsDisableWow64FileSystemRedirection();
+
+ ret = OpenEthInternal(name, local, tapmode, tapaddr);
+
+ MsRestoreWow64FileSystemRedirection(p);
+
+ return ret;
+}
+ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr)
+{
+ WP_ADAPTER *t;
+ ETH *e;
+ ADAPTER *a = NULL;
+ HANDLE h;
+ CANCEL *c;
+ MS_ADAPTER *ms;
+ char name_with_id[MAX_SIZE];
+ SU *su = NULL;
+ SU_ADAPTER *su_adapter = NULL;
+ // Validate arguments
+ if (name == NULL || IsEthSupported() == false)
+ {
+ return NULL;
+ }
+
+ if (tapmode)
+ {
+ // Tap is not supported in Windows
+ return NULL;
+ }
+
+ Lock(eth_list_lock);
+
+ InitEthAdaptersList();
+
+ t = Win32EthSearch(name);
+
+ if (t == NULL)
+ {
+ Unlock(eth_list_lock);
+ return NULL;
+ }
+
+ Debug("OpenEthInternal: %s\n", t->Name);
+
+ if (StartWith(t->Name, SL_ADAPTER_ID_PREFIX))
+ {
+ // Open with SU
+ su = SuInit();
+ if (su == NULL)
+ {
+ // Fail to initialize SU
+ Unlock(eth_list_lock);
+ return NULL;
+ }
+
+ su_adapter = SuOpenAdapter(su, t->Name);
+
+ if (su_adapter == NULL)
+ {
+ // Fail to get adapter
+ SuFree(su);
+ Unlock(eth_list_lock);
+ return NULL;
+ }
+
+ is_using_selow = true;
+ }
+ else
+ {
+ // Open with SEE
+ a = wp->PacketOpenAdapter(t->Name);
+ if (a == NULL)
+ {
+ Unlock(eth_list_lock);
+ return NULL;
+ }
+
+ if (IsWin32BridgeWithSee() == false)
+ {
+ MsSetThreadSingleCpu();
+ }
+
+ is_using_selow = false;
+ }
+
+ e = ZeroMalloc(sizeof(ETH));
+ e->Name = CopyStr(t->Name);
+
+ Win32EthMakeCombinedName(name_with_id, sizeof(name_with_id), t->Title, t->Guid);
+ e->Title = CopyStr(name_with_id);
+
+ if (su_adapter != NULL)
+ {
+ // SU
+ e->SuAdapter = su_adapter;
+ e->Su = su;
+
+ // Get event object
+ h = e->SuAdapter->hEvent;
+
+ c = NewCancelSpecial(h);
+ e->Cancel = c;
+ }
+ else
+ {
+ // SEE
+ e->Adapter = a;
+
+ wp->PacketSetBuff(e->Adapter, BRIDGE_WIN32_ETH_BUFFER);
+ wp->PacketSetHwFilter(e->Adapter, local ? 0x0080 : 0x0020);
+ wp->PacketSetMode(e->Adapter, PACKET_MODE_CAPT);
+ wp->PacketSetReadTimeout(e->Adapter, -1);
+ wp->PacketSetNumWrites(e->Adapter, 1);
+
+ if (wp->PacketSetLoopbackBehavior != NULL)
+ {
+ // Filter loopback packet in kernel
+ if (GET_KETA(GetOsType(), 100) >= 3)
+ {
+ if (MsIsWindows8() == false)
+ {
+ // Enable for Windows XP, Server 2003 or later
+ // But disable for Windows 8 or later
+ bool ret = wp->PacketSetLoopbackBehavior(e->Adapter, 1);
+ Debug("*** PacketSetLoopbackBehavior: %u\n", ret);
+
+ e->LoopbackBlock = ret;
+ }
+ }
+ }
+
+ // Get event object
+ h = wp->PacketGetReadEvent(e->Adapter);
+
+ c = NewCancelSpecial(h);
+ e->Cancel = c;
+
+ e->Packet = wp->PacketAllocatePacket();
+
+ e->PutPacket = wp->PacketAllocatePacket();
+ }
+
+ e->Buffer = Malloc(BRIDGE_WIN32_ETH_BUFFER);
+ e->BufferSize = BRIDGE_WIN32_ETH_BUFFER;
+
+ e->PacketQueue = NewQueue();
+
+ // Get MAC address by GUID
+ ms = MsGetAdapterByGuid(t->Guid);
+ if (ms != NULL)
+ {
+ if (ms->AddressSize == 6)
+ {
+ Copy(e->MacAddress, ms->Address, 6);
+ }
+
+ MsFreeAdapter(ms);
+ }
+
+ Unlock(eth_list_lock);
+
+ return e;
+}
+
+// Generate a combined name from NIC name and GUID
+void Win32EthMakeCombinedName(char *dst, UINT dst_size, char *nicname, char *guid)
+{
+ // Validate arguments
+ if (dst == NULL || nicname == NULL || guid == NULL)
+ {
+ return;
+ }
+
+ if (IsEmptyStr(guid) == false)
+ {
+ Format(dst, dst_size, "%s (ID=%010u)", nicname, Win32EthGenIdFromGuid(guid));
+ }
+ else
+ {
+ StrCpy(dst, dst_size, nicname);
+ }
+}
+
+// Decompose combined name
+UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str)
+{
+ UINT ret = 0;
+ char id_str[MAX_SIZE];
+ UINT len;
+ // Validate arguments
+ ClearStr(name, name_size);
+ StrCpy(name, name_size, str);
+ if (name == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ len = StrLen(str);
+
+ if (len >= 16)
+ {
+ StrCpy(id_str, sizeof(id_str), str + len - 16);
+
+ if (StartWith(id_str, " (ID="))
+ {
+ if (EndWith(id_str, ")"))
+ {
+ char num[MAX_SIZE];
+
+ Zero(num, sizeof(num));
+ StrCpy(num, sizeof(num), id_str + 5);
+
+ num[StrLen(num) - 1] = 0;
+
+ ret = ToInt(num);
+
+ if (ret != 0)
+ {
+ name[len - 16] = 0;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Generate an ID from GUID
+UINT Win32EthGenIdFromGuid(char *guid)
+{
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ UINT i;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return 0;
+ }
+
+ StrCpy(tmp, sizeof(tmp), guid);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ HashSha1(hash, tmp, StrLen(tmp));
+
+ Copy(&i, hash, sizeof(UINT));
+
+ i = Endian32(i);
+
+ if (i == 0)
+ {
+ i = 1;
+ }
+
+ return i;
+}
+
+// Get Ethernet adapter list
+TOKEN_LIST *GetEthList()
+{
+ UINT v;
+
+ return GetEthListEx(&v);
+}
+TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ UINT j;
+ UINT dummy_int;
+ MS_ADAPTER_LIST *adapter_list;
+
+ if (IsEthSupported() == false)
+ {
+ return NULL;
+ }
+
+ if (total_num_including_hidden == NULL)
+ {
+ total_num_including_hidden = &dummy_int;
+ }
+
+ *total_num_including_hidden = 0;
+
+ Lock(eth_list_lock);
+
+ InitEthAdaptersList();
+
+ adapter_list = MsCreateAdapterList();
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(eth_list);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ j = 0;
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ char tmp[MAX_SIZE];
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+ MS_ADAPTER *msa = NULL;
+ bool show = true;
+
+ if (Win32EthGetShowAllIf() == false)
+ {
+ msa = MsGetAdapterByGuidFromList(adapter_list, a->Guid);
+
+ if (InStr(a->Title, "vpn client adapter"))
+ {
+ // Hide virtual NIC for VPN client
+ show = false;
+ }
+
+ if (InStr(a->Title, "tunnel adapter"))
+ {
+ // Hide tunnel adapter
+ show = false;
+ }
+
+ if (InStr(a->Title, "teredo tunnel"))
+ {
+ // Hide tunnel adapter
+ show = false;
+ }
+
+ if (InStr(a->Title, "MS Tunnel Interface"))
+ {
+ // Hide tunnel adapter
+ show = false;
+ }
+
+ if (InStr(a->Title, "pseudo-interface"))
+ {
+ // Hide tunnel adapter
+ show = false;
+ }
+ }
+
+ if (msa != NULL)
+ {
+ // Hide except physical Ethernet NIC
+ if (msa->IsNotEthernetLan)
+ {
+ show = false;
+ }
+
+ MsFreeAdapter(msa);
+ }
+
+ Win32EthMakeCombinedName(tmp, sizeof(tmp), a->Title, a->Guid);
+
+ if (show)
+ {
+ ret->Token[j++] = CopyStr(tmp);
+
+ Debug("%s - %s\n", a->Guid, a->Title);
+ }
+ }
+
+ *total_num_including_hidden = ret->NumTokens;
+
+ ret->NumTokens = j;
+
+ Unlock(eth_list_lock);
+
+ MsFreeAdapterList(adapter_list);
+
+ return ret;
+}
+
+// Compare the name of WP_ADAPTER
+int CompareWpAdapter(void *p1, void *p2)
+{
+ int i;
+ WP_ADAPTER *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(WP_ADAPTER **)p1;
+ a2 = *(WP_ADAPTER **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+ i = StrCmpi(a1->Title, a2->Title);
+ return i;
+}
+
+// Get whether the SeLow is used
+bool Win32IsUsingSeLow()
+{
+ return is_using_selow;
+}
+
+// Get Ethernet adapter list
+LIST *GetEthAdapterList()
+{
+ void *p;
+ LIST *o;
+
+ p = MsDisableWow64FileSystemRedirection();
+
+ o = GetEthAdapterListInternal();
+
+ MsRestoreWow64FileSystemRedirection(p);
+
+ return o;
+}
+LIST *GetEthAdapterListInternal()
+{
+ LIST *o;
+ LIST *ret;
+ UINT size;
+ char *buf;
+ UINT i, j;
+ char *qos_tag = " (Microsoft's Packet Scheduler)";
+ SU *su = NULL;
+ LIST *su_adapter_list = NULL;
+
+ // Try to use SeLow
+ if (enable_selow)
+ {
+ su = SuInit();
+ }
+
+ o = NewListFast(CompareWpAdapter);
+
+ size = 200000;
+ buf = ZeroMalloc(size);
+
+ // Try to enumerate with SeLow
+ if (su != NULL)
+ {
+ su_adapter_list = SuGetAdapterList(su);
+
+ if (su_adapter_list == NULL)
+ {
+ // Fail to enumerate
+ SuFree(su);
+ su = NULL;
+ //WHERE;
+ is_using_selow = false;
+ }
+ else
+ {
+ //WHERE;
+ is_using_selow = true;
+ }
+ }
+ else
+ {
+ is_using_selow = false;
+ }
+
+ if (su_adapter_list != NULL)
+ {
+ // If 1 or more adapters are enumerated by SeLow, create adapter list object
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(su_adapter_list);i++)
+ {
+ SU_ADAPTER_LIST *t = LIST_DATA(su_adapter_list, i);
+ WP_ADAPTER *a = ZeroMalloc(sizeof(WP_ADAPTER));
+
+ StrCpy(a->Name, sizeof(a->Name), t->Name);
+ StrCpy(a->Guid, sizeof(a->Guid), t->Guid);
+ StrCpy(a->Title, sizeof(a->Title), t->Info.FriendlyName);
+
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+
+ if (EndWith(a->Title, qos_tag))
+ {
+ a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ }
+
+ Add(o, a);
+ }
+ }
+ else
+ {
+ // When SeLow is not used, create adapter list with SEE or WinPcap
+ if (wp->PacketGetAdapterNames(buf, &size) == false)
+ {
+ Free(buf);
+ return o;
+ }
+
+ i = 0;
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ // Windows NT
+ if (size >= 2 && buf[0] != 0 && buf[1] != 0)
+ {
+ goto ANSI_STR;
+ }
+
+ while (true)
+ {
+ wchar_t tmp[MAX_SIZE];
+ WP_ADAPTER *a;
+ UniStrCpy(tmp, sizeof(tmp), L"");
+
+ if (*((wchar_t *)(&buf[i])) == 0)
+ {
+ i += sizeof(wchar_t);
+ break;
+ }
+
+ for (;*((wchar_t *)(&buf[i])) != 0;i += sizeof(wchar_t))
+ {
+ wchar_t str[2];
+ str[0] = *((wchar_t *)(&buf[i]));
+ str[1] = 0;
+ UniStrCat(tmp, sizeof(tmp), str);
+ }
+
+ i += sizeof(wchar_t);
+
+ a = ZeroMalloc(sizeof(WP_ADAPTER));
+ UniToStr(a->Name, sizeof(a->Name), tmp);
+
+ Add(o, a);
+ }
+ }
+ else
+ {
+ // Windows 9x
+ANSI_STR:
+ while (true)
+ {
+ char tmp[MAX_SIZE];
+ WP_ADAPTER *a;
+ StrCpy(tmp, sizeof(tmp), "");
+
+ if (*((char *)(&buf[i])) == 0)
+ {
+ i += sizeof(char);
+ break;
+ }
+
+ for (;*((char *)(&buf[i])) != 0;i += sizeof(char))
+ {
+ char str[2];
+ str[0] = *((char *)(&buf[i]));
+ str[1] = 0;
+ StrCat(tmp, sizeof(tmp), str);
+ }
+
+ i += sizeof(char);
+
+ a = ZeroMalloc(sizeof(WP_ADAPTER));
+ StrCpy(a->Name, sizeof(a->Name), tmp);
+
+ Add(o, a);
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ WP_ADAPTER *a = LIST_DATA(o, j);
+
+ StrCpy(a->Title, sizeof(a->Title), &buf[i]);
+ i += StrSize(a->Title);
+
+ // If device description is "Unknown" in Win9x, skip 1 byte
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ if (StrCmp(a->Title, "Unknown") == 0)
+ {
+ if (buf[i] == 0)
+ {
+ i+=sizeof(char);
+ }
+ }
+ }
+
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+
+ if (EndWith(a->Title, qos_tag))
+ {
+ a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ TrimCrlf(a->Title);
+ Trim(a->Title);
+ }
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ // Extract GUID
+ WP_ADAPTER *a = LIST_DATA(o, j);
+
+ if (IsEmptyStr(a->Guid))
+ {
+ StrCpy(a->Guid, sizeof(a->Guid), a->Name);
+ ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\SEE_", "");
+ ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\NPF_", "");
+ ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\PCD_", "");
+ }
+ }
+
+ // Sort
+ if (su_adapter_list != NULL)
+ {
+ // Since adapter list made by SeLow is already sorted, don't sort here
+ Sort(o);
+ }
+
+ ret = NewListFast(CompareWpAdapter);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(o, i);
+ ADAPTER *ad;
+ bool is_ethernet = false;
+ bool ok = false;
+
+ if (SearchStrEx(a->Title, "ppp", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "wan", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "dialup", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "pptp", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "telepho", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "modem", 0, false) != INFINITE ||
+ SearchStrEx(a->Title, "ras", 0, false) != INFINITE)
+ {
+ Free(a);
+ continue;
+ }
+
+ // Determine whether the adapter type is Ethernet
+ if (su == NULL)
+ {
+ // Determine with See
+ ad = wp->PacketOpenAdapter(a->Name);
+ if (ad != NULL)
+ {
+ NetType type;
+ if (wp->PacketGetNetType(ad, &type))
+ {
+ if (type.LinkType == 0)
+ {
+ is_ethernet = true;
+ }
+ }
+
+ wp->PacketCloseAdapter(ad);
+ }
+ }
+ else
+ {
+ // In using SeLow, all devices should be Ethernet device
+ is_ethernet = true;
+ }
+
+ if (is_ethernet)
+ {
+ // Add only Ethernet device
+ char tmp[MAX_SIZE];
+ UINT k;
+
+ StrCpy(tmp, sizeof(tmp), a->Title);
+
+ for (k = 0;;k++)
+ {
+ if (k == 0)
+ {
+ StrCpy(tmp, sizeof(tmp), a->Title);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1);
+ }
+
+ ok = true;
+ for (j = 0;j < LIST_NUM(ret);j++)
+ {
+ WP_ADAPTER *aa = LIST_DATA(ret, j);
+ if (StrCmpi(aa->Title, tmp) == 0)
+ {
+ ok = false;
+ }
+ }
+
+ if (ok)
+ {
+ break;
+ }
+ }
+
+ StrCpy(a->Title, sizeof(a->Title), tmp);
+ a->Id = Win32EthGenIdFromGuid(a->Guid);
+ Add(ret, a);
+ }
+
+ if (ok == false)
+ {
+ Free(a);
+ }
+ }
+
+ Free(buf);
+
+ Sort(ret);
+
+ ReleaseList(o);
+
+ if (su != NULL)
+ {
+ SuFreeAdapterList(su_adapter_list);
+
+ SuFree(su);
+ }
+
+ return ret;
+}
+
+// Initialize Ethernet adapter list
+void InitEthAdaptersList()
+{
+ if (eth_list != NULL)
+ {
+ FreeEthAdaptersList();
+ eth_list = NULL;
+ }
+ eth_list = GetEthAdapterList();
+}
+
+// Free Ethernet adapter list
+void FreeEthAdaptersList()
+{
+ UINT i;
+ if (eth_list == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < LIST_NUM(eth_list);i++)
+ {
+ WP_ADAPTER *a = LIST_DATA(eth_list, i);
+ Free(a);
+ }
+ ReleaseList(eth_list);
+ eth_list = NULL;
+}
+
+// Is the SU supported
+bool Win32EthIsSuSupported()
+{
+ bool ret = false;
+ SU *su = SuInit();
+
+ if (su != NULL)
+ {
+ ret = true;
+ }
+
+ SuFree(su);
+
+ return ret;
+}
+
+// Is the Ethernet supported
+bool IsEthSupported()
+{
+ bool ret = IsEthSupportedInner();
+
+ if (ret == false)
+ {
+ ret = Win32EthIsSuSupported();
+ }
+
+ return ret;
+}
+bool IsEthSupportedInner()
+{
+ if (wp == NULL)
+ {
+ return false;
+ }
+
+ return wp->Inited;
+}
+
+// Is the PCD driver supported in current OS
+bool IsPcdSupported()
+{
+ UINT type;
+ OS_INFO *info = GetOsInfo();
+
+ type = info->OsType;
+
+ if (OS_IS_WINDOWS_NT(type) == false)
+ {
+ // Only on Windows NT series
+ return false;
+ }
+
+ if (GET_KETA(type, 100) >= 2)
+ {
+ // Good for Windows 2000 or later
+ return true;
+ }
+
+ // Not good for Windows NT 4.0 or Longhorn
+ return false;
+}
+
+// Save build number of PCD driver
+void SavePcdDriverBuild(UINT build)
+{
+ MsRegWriteInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE,
+ build);
+}
+
+// Load build number of PCD driver
+UINT LoadPcdDriverBuild()
+{
+ return MsRegReadInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE);
+}
+
+// Try to install PCD driver
+HINSTANCE InstallPcdDriver()
+{
+ HINSTANCE ret;
+ void *p = MsDisableWow64FileSystemRedirection();
+
+ ret = InstallPcdDriverInternal();
+
+ MsRestoreWow64FileSystemRedirection(p);
+
+ return ret;
+}
+HINSTANCE InstallPcdDriverInternal()
+{
+ char tmp[MAX_PATH];
+ bool install_driver = true;
+ HINSTANCE h;
+ char *dll_filename;
+
+ // Confirm whether the see.sys is installed in system32\drivers folder
+ Format(tmp, sizeof(tmp), "%s\\drivers\\see.sys", MsGetSystem32Dir());
+
+ if (IsFileExists(tmp))
+ {
+ // If driver file is exist, try to get build number from registry
+ if (LoadPcdDriverBuild() >= CEDAR_BUILD)
+ {
+ // Already latest driver is installed
+ install_driver = false;
+ }
+ }
+
+ if (install_driver)
+ {
+ char *src_filename = BRIDGE_WIN32_PCD_SYS;
+ // If need to install the driver, confirm user is administrator
+ if (MsIsAdmin() == false)
+ {
+ // Non administrator can't install driver
+ return NULL;
+ }
+
+ if (MsIsX64())
+ {
+ src_filename = BRIDGE_WIN32_PCD_SYS_X64;
+ }
+
+ if (MsIsIA64())
+ {
+ src_filename = BRIDGE_WIN32_PCD_SYS_IA64;
+ }
+
+ // Copy see.sys
+ if (FileCopy(src_filename, tmp) == false)
+ {
+ return NULL;
+ }
+
+ // Save build number
+ SavePcdDriverBuild(CEDAR_BUILD);
+ }
+
+ dll_filename = BRIDGE_WIN32_PCD_DLL;
+
+ if (Is64())
+ {
+ if (MsIsX64())
+ {
+ dll_filename = BRIDGE_WIN32_PCD_DLL_X64;
+ }
+ else if (MsIsIA64())
+ {
+ dll_filename = BRIDGE_WIN32_PCD_DLL_IA64;
+ }
+ }
+
+ // Try to load see.dll and initialize
+ h = MsLoadLibrary(dll_filename);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ return h;
+}
+
+// Initialize Ethernet
+void InitEth()
+{
+ HINSTANCE h;
+ if (wp != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ eth_list_lock = NewLock();
+
+ wp = ZeroMalloc(sizeof(WP));
+
+ is_see_mode = false;
+
+ if (IsPcdSupported())
+ {
+ // PCD is supported in this OS
+ h = InstallPcdDriver();
+ if (h != NULL)
+ {
+ // Try to initialize with PCD
+ if (InitWpWithLoadLibrary(wp, h) == false)
+ {
+ Debug("InitEth: SEE Failed.\n");
+ FreeLibrary(h);
+ }
+ else
+ {
+ Debug("InitEth: SEE Loaded.\n");
+ is_see_mode = true;
+ }
+ }
+ }
+
+ if (wp->Inited == false)
+ {
+ // Try to initialize with Packet.dll of WinPcap
+ h = LoadLibrary(BRIDGE_WIN32_PACKET_DLL);
+ if (h != NULL)
+ {
+ if (InitWpWithLoadLibrary(wp, h) == false)
+ {
+ Debug("InitEth: Packet.dll Failed.\n");
+ FreeLibrary(h);
+ }
+ else
+ {
+ Debug("InitEth: Packet.dll Loaded.\n");
+ }
+ }
+ }
+}
+
+// Get whether local-bridge uses see.sys
+bool IsWin32BridgeWithSee()
+{
+ return is_see_mode;
+}
+
+// Initialize WP structure with DLL
+bool InitWpWithLoadLibrary(WP *wp, HINSTANCE h)
+{
+ TOKEN_LIST *o;
+ UINT total_num = 0;
+ // Validate arguments
+ if (wp == NULL || h == NULL)
+ {
+ return false;
+ }
+ wp->Inited = true;
+ wp->hPacketDll = h;
+
+ LOAD_DLL_ADDR(PacketGetVersion);
+ LOAD_DLL_ADDR(PacketGetDriverVersion);
+ LOAD_DLL_ADDR(PacketSetMinToCopy);
+ LOAD_DLL_ADDR(PacketSetNumWrites);
+ LOAD_DLL_ADDR(PacketSetMode);
+ LOAD_DLL_ADDR(PacketSetReadTimeout);
+ LOAD_DLL_ADDR(PacketSetBpf);
+ LOAD_DLL_ADDR(PacketSetSnapLen);
+ LOAD_DLL_ADDR(PacketGetStats);
+ LOAD_DLL_ADDR(PacketGetStatsEx);
+ LOAD_DLL_ADDR(PacketSetBuff);
+ LOAD_DLL_ADDR(PacketGetNetType);
+ LOAD_DLL_ADDR(PacketOpenAdapter);
+ LOAD_DLL_ADDR(PacketSendPacket);
+ LOAD_DLL_ADDR(PacketSendPackets);
+ LOAD_DLL_ADDR(PacketAllocatePacket);
+ LOAD_DLL_ADDR(PacketInitPacket);
+ LOAD_DLL_ADDR(PacketFreePacket);
+ LOAD_DLL_ADDR(PacketReceivePacket);
+ LOAD_DLL_ADDR(PacketSetHwFilter);
+ LOAD_DLL_ADDR(PacketGetAdapterNames);
+ LOAD_DLL_ADDR(PacketGetNetInfoEx);
+ LOAD_DLL_ADDR(PacketRequest);
+ LOAD_DLL_ADDR(PacketGetReadEvent);
+ LOAD_DLL_ADDR(PacketSetDumpName);
+ LOAD_DLL_ADDR(PacketSetDumpLimits);
+ LOAD_DLL_ADDR(PacketSetDumpLimits);
+ LOAD_DLL_ADDR(PacketIsDumpEnded);
+ LOAD_DLL_ADDR(PacketStopDriver);
+ LOAD_DLL_ADDR(PacketCloseAdapter);
+ LOAD_DLL_ADDR(PacketSetLoopbackBehavior);
+
+ if (wp->PacketSetMinToCopy == NULL ||
+ wp->PacketSetNumWrites == NULL ||
+ wp->PacketSetMode == NULL ||
+ wp->PacketSetReadTimeout == NULL ||
+ wp->PacketSetBuff == NULL ||
+ wp->PacketGetNetType == NULL ||
+ wp->PacketOpenAdapter == NULL ||
+ wp->PacketSendPacket == NULL ||
+ wp->PacketSendPackets == NULL ||
+ wp->PacketAllocatePacket == NULL ||
+ wp->PacketInitPacket == NULL ||
+ wp->PacketFreePacket == NULL ||
+ wp->PacketReceivePacket == NULL ||
+ wp->PacketSetHwFilter == NULL ||
+ wp->PacketGetAdapterNames == NULL ||
+ wp->PacketGetNetInfoEx == NULL ||
+ wp->PacketCloseAdapter == NULL)
+ {
+RELEASE:
+ wp->Inited = false;
+ wp->hPacketDll = NULL;
+
+ return false;
+ }
+
+ o = GetEthListEx(&total_num);
+ if (o == NULL || total_num == 0)
+ {
+ FreeToken(o);
+ goto RELEASE;
+ }
+
+ FreeToken(o);
+
+ return true;
+}
+
+// Free Ethernet
+void FreeEth()
+{
+ if (wp == NULL)
+ {
+ // Not initialized
+ return;
+ }
+
+ // Free adapter list
+ FreeEthAdaptersList();
+
+ if (wp->Inited)
+ {
+ // Free DLL
+ FreeLibrary(wp->hPacketDll);
+ }
+
+ Free(wp);
+ wp = NULL;
+
+ DeleteLock(eth_list_lock);
+ eth_list_lock = NULL;
+}
+
+// Get network connection name from Ethernet device name
+void GetEthNetworkConnectionName(wchar_t *dst, UINT size, char *device_name)
+{
+ WP_ADAPTER *t;
+ char *tmp = NULL, guid[MAX_SIZE];
+ wchar_t *ncname = NULL;
+
+ UniStrCpy(dst, size, L"");
+
+ // Validate arguments
+ if (device_name == NULL || IsEthSupported() == false ||
+ IsNt() == false || MsIsWin2000OrGreater() == false)
+ {
+ return;
+ }
+
+ Lock(eth_list_lock);
+
+ InitEthAdaptersList();
+
+ t = Win32EthSearch(device_name);
+
+ if (t == NULL)
+ {
+ Unlock(eth_list_lock);
+ return;
+ }
+
+ tmp = CopyStr(t->Name);
+ Unlock(eth_list_lock);
+
+ if (IsEmptyStr(t->Guid) == false)
+ {
+ StrCpy(guid, sizeof(guid), t->Guid);
+
+ Free(tmp);
+ }
+ else
+ {
+ ReplaceStr(guid, sizeof(guid), tmp, "\\Device\\SEE_", "");
+ Free(tmp);
+
+ ReplaceStr(guid, sizeof(guid), guid, "\\Device\\NPF_", "");
+ ReplaceStr(guid, sizeof(guid), guid, "\\Device\\PCD_", "");
+ }
+
+ if(guid == NULL)
+ {
+ return;
+ }
+
+ ncname = MsGetNetworkConnectionName(guid);
+ if(ncname != NULL)
+ {
+ UniStrCpy(dst, size, ncname);
+ }
+ Free(ncname);
+}
+
+#endif // BRIDGE_C
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/BridgeWin32.h b/src/Cedar/BridgeWin32.h
new file mode 100644
index 00000000..2cc4615c
--- /dev/null
+++ b/src/Cedar/BridgeWin32.h
@@ -0,0 +1,238 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// BridgeWin32.h
+// Header of BridgeWin32.c
+
+#ifndef BRIDGEWIN32_H
+#define BRIDGEWIN32_H
+
+#define BRIDGE_WIN32_PACKET_DLL "Packet.dll"
+#define BRIDGE_WIN32_PCD_DLL "|see.dll"
+#define BRIDGE_WIN32_PCD_SYS "|see.sys"
+#define BRIDGE_WIN32_PCD_DLL_X64 "|see_x64.dll"
+#define BRIDGE_WIN32_PCD_SYS_X64 "|see_x64.sys"
+#define BRIDGE_WIN32_PCD_DLL_IA64 "|see_ia64.dll"
+#define BRIDGE_WIN32_PCD_SYS_IA64 "|see_ia64.sys"
+#define BRIDGE_WIN32_PCD_REGKEY "SYSTEM\\CurrentControlSet\\services\\SEE"
+#define BRIDGE_WIN32_PCD_BUILDVALUE "CurrentInstalledBuild"
+
+#define BRIDGE_WIN32_ETH_BUFFER (1048576)
+
+
+typedef void *HANDLE;
+
+#ifdef BRIDGE_C
+
+// Header for Internal function (for BridgeWin32.c)
+typedef struct WP
+{
+ bool Inited;
+ HINSTANCE hPacketDll;
+ PCHAR (*PacketGetVersion)();
+ PCHAR (*PacketGetDriverVersion)();
+ BOOLEAN (*PacketSetMinToCopy)(LPADAPTER AdapterObject,int nbytes);
+ BOOLEAN (*PacketSetNumWrites)(LPADAPTER AdapterObject,int nwrites);
+ BOOLEAN (*PacketSetMode)(LPADAPTER AdapterObject,int mode);
+ BOOLEAN (*PacketSetReadTimeout)(LPADAPTER AdapterObject,int timeout);
+ BOOLEAN (*PacketSetBpf)(LPADAPTER AdapterObject,struct bpf_program *fp);
+ INT (*PacketSetSnapLen)(LPADAPTER AdapterObject,int snaplen);
+ BOOLEAN (*PacketGetStats)(LPADAPTER AdapterObject,struct bpf_stat *s);
+ BOOLEAN (*PacketGetStatsEx)(LPADAPTER AdapterObject,struct bpf_stat *s);
+ BOOLEAN (*PacketSetBuff)(LPADAPTER AdapterObject,int dim);
+ BOOLEAN (*PacketGetNetType)(LPADAPTER AdapterObject,NetType *type);
+ LPADAPTER (*PacketOpenAdapter)(PCHAR AdapterName);
+ BOOLEAN (*PacketSendPacket)(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+ INT (*PacketSendPackets)(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
+ LPPACKET (*PacketAllocatePacket)(void);
+ VOID (*PacketInitPacket)(LPPACKET lpPacket,PVOID Buffer,UINT Length);
+ VOID (*PacketFreePacket)(LPPACKET lpPacket);
+ BOOLEAN (*PacketReceivePacket)(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
+ BOOLEAN (*PacketSetHwFilter)(LPADAPTER AdapterObject,ULONG Filter);
+ BOOLEAN (*PacketGetAdapterNames)(PTSTR pStr,PULONG BufferSize);
+ BOOLEAN (*PacketGetNetInfoEx)(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
+ BOOLEAN (*PacketRequest)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
+ HANDLE (*PacketGetReadEvent)(LPADAPTER AdapterObject);
+ BOOLEAN (*PacketSetDumpName)(LPADAPTER AdapterObject, void *name, int len);
+ BOOLEAN (*PacketSetDumpLimits)(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+ BOOLEAN (*PacketIsDumpEnded)(LPADAPTER AdapterObject, BOOLEAN sync);
+ BOOL (*PacketStopDriver)();
+ VOID (*PacketCloseAdapter)(LPADAPTER lpAdapter);
+ BOOLEAN (*PacketSetLoopbackBehavior)(LPADAPTER AdapterObject, UINT LoopbackBehavior);
+} WP;
+
+// Adapter list
+typedef struct WP_ADAPTER
+{
+ char Name[MAX_SIZE];
+ char Title[MAX_SIZE];
+ char Guid[MAX_SIZE];
+ UINT Id;
+} WP_ADAPTER;
+
+// Internal function prototype
+void InitEthAdaptersList();
+void FreeEthAdaptersList();
+int CompareWpAdapter(void *p1, void *p2);
+LIST *GetEthAdapterList();
+LIST *GetEthAdapterListInternal();
+bool InitWpWithLoadLibrary(WP *wp, HINSTANCE h);
+bool IsPcdSupported();
+HINSTANCE InstallPcdDriver();
+HINSTANCE InstallPcdDriverInternal();
+UINT LoadPcdDriverBuild();
+void SavePcdDriverBuild(UINT build);
+
+#endif // BRIDGE_C
+
+typedef struct _ADAPTER ADAPTER;
+typedef struct _PACKET PACKET;
+
+// ETH structure
+struct ETH
+{
+ char *Name; // Adapter name
+ char *Title; // Adapter title
+ ADAPTER *Adapter; // Adapter
+ CANCEL *Cancel; // Cancel object
+ UCHAR *Buffer; // Buffer
+ UINT BufferSize; // Buffer size
+ PACKET *Packet; // Packet
+ PACKET *PutPacket; // Write packet
+ QUEUE *PacketQueue; // Packet queue
+ UINT64 LastSetSingleCpu; // Date and time set to a single CPU to last
+ bool LoopbackBlock; // Whether to block the loop back packet
+ bool Empty; // It is empty
+ UCHAR MacAddress[6]; // MAC address
+ bool HasFatalError; // A fatal error occurred on the transmission side
+
+ SU *Su; // SeLow handle
+ SU_ADAPTER *SuAdapter; // SeLow adapter handle
+};
+
+// Function prototype
+void InitEth();
+void FreeEth();
+bool IsEthSupported();
+bool IsEthSupportedInner();
+TOKEN_LIST *GetEthList();
+TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden);
+ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr);
+ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr);
+void CloseEth(ETH *e);
+CANCEL *EthGetCancel(ETH *e);
+UINT EthGetPacket(ETH *e, void **data);
+void EthPutPacket(ETH *e, void *data, UINT size);
+void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes);
+void GetEthNetworkConnectionName(wchar_t *dst, UINT size, char *device_name);
+bool IsWin32BridgeWithSee();
+UINT EthGetMtu(ETH *e);
+bool EthSetMtu(ETH *e, UINT mtu);
+bool EthIsChangeMtuSupported(ETH *e);
+
+bool Win32EthIsSuSupported();
+
+void Win32EthSetShowAllIf(bool b);
+bool Win32EthGetShowAllIf();
+
+bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t);
+bool GetClassRegKeyWin32(char *key, UINT key_size, char *short_key, UINT short_key_size, char *guid);
+int CmpRpcEnumEthVLan(void *p1, void *p2);
+void GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM *e);
+void GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM *e);
+bool SetVLanEnableStatus(char *title, bool enable);
+RPC_ENUM_ETH_VLAN_ITEM *FindEthVLanItem(RPC_ENUM_ETH_VLAN *t, char *name);
+char *SearchDeviceInstanceIdFromShortKey(char *short_key);
+void Win32EthMakeCombinedName(char *dst, UINT dst_size, char *nicname, char *guid);
+UINT Win32EthGenIdFromGuid(char *guid);
+UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str);
+
+struct WP_ADAPTER *Win32EthSearch(char *name);
+bool Win32IsUsingSeLow();
+void Win32SetEnableSeLow(bool b);
+bool Win32GetEnableSeLow();
+
+#endif // BRIDGEWIN32_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/CM.c b/src/Cedar/CM.c
new file mode 100644
index 00000000..379ee9cd
--- /dev/null
+++ b/src/Cedar/CM.c
@@ -0,0 +1,12394 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CM.c
+// VPN Client Connection Manager for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define CM_C
+#define SM_C
+#define MICROSOFT_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <Iphlpapi.h>
+#include <tlhelp32.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <process.h>
+#include <psapi.h>
+#include <wtsapi32.h>
+#include <Ntsecapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "CMInner.h"
+#include "SMInner.h"
+#include "NMInner.h"
+#include "EMInner.h"
+#include "../PenCore/resource.h"
+
+
+// Get the proxy server settings from the registry string of IE
+bool CmGetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL || port == NULL || str == NULL || server_type == NULL)
+ {
+ return false;
+ }
+
+ t = ParseToken(str, ";");
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+ UINT i;
+
+ Trim(s);
+
+ i = SearchStrEx(s, "=", 0, false);
+ if (i != INFINITE)
+ {
+ char tmp[MAX_PATH];
+
+ StrCpy(name, name_size, s);
+ name[i] = 0;
+
+ if (StrCmpi(name, server_type) == 0)
+ {
+ char *host;
+ StrCpy(tmp, sizeof(tmp), s + i + 1);
+
+ if (ParseHostPort(tmp, &host, port, 0))
+ {
+ StrCpy(name, name_size, host);
+ Free(host);
+
+ if (*port != 0)
+ {
+ ret = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+
+// Reflect the contents of the proxy settings to the connection settings
+void CmProxyDlgSet(HWND hWnd, CLIENT_OPTION *o, CM_INTERNET_SETTING *setting)
+{
+ // Validate arguments
+ if(hWnd == NULL || setting == NULL)
+ {
+ return;
+ }
+
+ // Make check in check-box
+ Check(hWnd, R_DIRECT_TCP, setting->ProxyType == PROXY_DIRECT);
+ Check(hWnd, R_HTTPS, setting->ProxyType == PROXY_HTTP);
+ Check(hWnd, R_SOCKS, setting->ProxyType == PROXY_SOCKS);
+
+ // Proxy Settings
+ if(setting->ProxyType != PROXY_DIRECT)
+ {
+ StrCpy(o->ProxyName, sizeof(setting->ProxyHostName), setting->ProxyHostName);
+ o->ProxyPort = setting->ProxyPort;
+ }
+}
+
+// Get the proxy settings of IE
+void CmGetSystemInternetSetting(CM_INTERNET_SETTING *setting)
+{
+ bool use_proxy;
+ // Validate arguments
+ if (setting == NULL)
+ {
+ return;
+ }
+
+ Zero(setting, sizeof(CM_INTERNET_SETTING));
+
+ use_proxy = MsRegReadInt(REG_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
+ "ProxyEnable");
+
+ if (use_proxy)
+ {
+ char *str = MsRegReadStr(REG_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
+ "ProxyServer");
+ if (str != NULL)
+ {
+ char name[MAX_HOST_NAME_LEN + 1];
+ UINT port;
+
+ if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "https"))
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "http"))
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "socks"))
+ {
+ setting->ProxyType = PROXY_SOCKS;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else
+ {
+ if (SearchStrEx(str, "=", 0, false) == INFINITE)
+ {
+ char *host;
+ UINT port;
+ if (ParseHostPort(str, &host, &port, 0))
+ {
+ if (port != 0)
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), host);
+ setting->ProxyPort = port;
+ }
+ Free(host);
+ }
+ }
+ }
+
+ Free(str);
+ }
+ }
+}
+
+// For the proxy settings to go through, use the IE settings
+void CmProxyDlgUseForIE(HWND hWnd, CLIENT_OPTION *o)
+{
+ CM_INTERNET_SETTING s;
+
+ // Validate arguments
+ if(hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&s, sizeof(s));
+ CmGetSystemInternetSetting(&s);
+
+ CmProxyDlgSet(hWnd, o, &s);
+}
+
+// Determine the bitmap ID of the smart card authentication screen
+UINT CmGetSecureBitmapId(char *dest_hostname)
+{
+ // Validate arguments
+ if (dest_hostname == NULL)
+ {
+ return 0;
+ }
+
+ if (EndWith(dest_hostname, ".cc.tsukuba.ac.jp"))
+ {
+ return BMP_TSUKUBA;
+ }
+
+ return 0;
+}
+
+// Activate the window of UAC
+void CmSetUacWindowActive()
+{
+ HWND hWnd;
+
+ if (MsIsVista() == false)
+ {
+ return;
+ }
+
+ hWnd = FindWindowA("$$$Secure UAP Dummy Window Class For Interim Dialog", NULL);
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SwitchToThisWindow(hWnd, true);
+}
+
+// UAC helper thread
+void CmUacHelperThread(THREAD *thread, void *param)
+{
+ CM_UAC_HELPER *c = (CM_UAC_HELPER *)param;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ while (c->Halt == false)
+ {
+ CmSetUacWindowActive();
+
+ Wait(c->HaltEvent, 200);
+ }
+}
+
+// Start the UAC helper
+void *CmStartUacHelper()
+{
+ CM_UAC_HELPER *c = ZeroMalloc(sizeof(CM_UAC_HELPER));
+
+ c->HaltEvent = NewEvent();
+ c->Thread = NewThread(CmUacHelperThread, c);
+
+ return (void *)c;
+}
+
+// Stop the UAC helper
+void CmStopUacHelper(void *p)
+{
+ CM_UAC_HELPER *c = (CM_UAC_HELPER *)p;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->Halt = true;
+ Set(c->HaltEvent);
+ WaitThread(c->Thread, INFINITE);
+ ReleaseEvent(c->HaltEvent);
+ ReleaseThread(c->Thread);
+
+ Free(c);
+}
+
+// Command invocation of the simple connection manager
+void CmEasyDlgOnCommand(HWND hWnd, CM_EASY_DLG *d, WPARAM wParam, LPARAM lParam)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ switch (wParam)
+ {
+ case B_MODE:
+ Command(hWnd, CMD_CM_SETTING);
+ return;
+
+ case B_STATUS:
+ Command(hWnd, CMD_STATUS);
+ return;
+
+ case IDCANCEL:
+ Close(hWnd);
+ return;
+
+ }
+
+ if (wParam == CMD_CONNECT)
+ {
+ cm->ConnectStartedFlag = false;
+ }
+
+ CmMainWindowOnCommandEx(hWnd, wParam, lParam, true);
+
+ if (wParam == CMD_CONNECT && cm->ConnectStartedFlag)
+ {
+ // Close the window when the connection started successfully
+ Close(hWnd);
+ }
+}
+
+// Keyboard pressing of the simple connection manager
+void CmEasyDlgOnKey(HWND hWnd, CM_EASY_DLG *d, bool ctrl, bool alt, UINT key)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Single key
+ switch (key)
+ {
+ case VK_RETURN:
+ Command(hWnd, IDOK);
+ break;
+ case VK_DELETE:
+ // Delete
+ if (IsFocus(hWnd, L_ACCOUNT))
+ {
+ // Operation on the account list
+ Command(hWnd, CMD_DELETE);
+ }
+ else
+ {
+ // Operation on the virtual LAN card list
+ Command(hWnd, CMD_DELETE_VLAN);
+ }
+ break;
+ case VK_F2:
+ // Change the name
+ Command(hWnd, CMD_RENAME);
+ break;
+ case VK_F5:
+ // Update the status
+ Command(hWnd, CMD_REFRESH);
+ break;
+ }
+
+ if (alt)
+ {
+ switch (key)
+ {
+ case 'Q':
+ // Close
+ Command(hWnd, CMD_QUIT);
+ break;
+ }
+ }
+
+ if (ctrl)
+ {
+ switch (key)
+ {
+ case 'G':
+ // Smart Card Manager
+ Command(hWnd, CMD_SECURE_MANAGER);
+ break;
+ case 'S':
+ // Show the status
+ Command(hWnd, CMD_STATUS);
+ break;
+ case 'I':
+ // Disconnect all connections
+ Command(hWnd, CMD_DISCONNECT_ALL);
+ break;
+ case 'D':
+ // Disconnect
+ Command(hWnd, CMD_DISCONNECT);
+ break;
+ case 'N':
+ // Create a new connection setting
+ Command(hWnd, CMD_NEW);
+ break;
+ case 'C':
+ // Creating a copy
+ Command(hWnd, CMD_CLONE);
+ break;
+ case 'T':
+ // Set to start-up connection
+ Command(hWnd, CMD_STARTUP);
+ break;
+ case 'A':
+ // Select all
+ Command(hWnd, CMD_SELECT_ALL);
+ break;
+ case 'L':
+ // Create a new virtual LAN card
+ Command(hWnd, CMD_NEW_VLAN);
+ break;
+ case 'P':
+ // Set the password
+ Command(hWnd, CMD_PASSWORD);
+ break;
+ case 'O':
+ // Option settings
+ Command(hWnd, CMD_TRAFFIC);
+ break;
+ case 'R':
+ // Certificate management
+ Command(hWnd, CMD_TRUST);
+ break;
+ case 'Q':
+ // Throughput
+ Command(hWnd, CMD_TRAFFIC);
+ break;
+ }
+ }
+}
+
+// Operation on the list view of the simple connection manager
+void CmEasyDlgOnNotify(HWND hWnd, CM_EASY_DLG *d, NMHDR *n)
+{
+ NMLVDISPINFOW *disp_info;
+ NMLVKEYDOWN *key;
+
+ // Validate arguments
+ if (hWnd == NULL || n == NULL)
+ {
+ return;
+ }
+
+ switch (n->idFrom)
+ {
+ case L_ACCOUNT:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CmEasyDlgUpdate(hWnd, d);
+ break;
+ case NM_DBLCLK:
+ // Double click
+ Command(hWnd, CMD_EASY_DBLCLICK);
+ break;
+ case NM_RCLICK:
+ // Right click
+ CmAccountListRightClick(hWnd);
+ break;
+ case LVN_ENDLABELEDITW:
+ // Change the name
+ disp_info = (NMLVDISPINFOW *)n;
+ if (disp_info->item.pszText != NULL)
+ {
+ wchar_t *new_name = disp_info->item.pszText;
+ wchar_t *old_name = LvGetStr(hWnd, L_ACCOUNT, disp_info->item.iItem, 0);
+
+ if (old_name != NULL)
+ {
+ if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)
+ {
+ RPC_RENAME_ACCOUNT a;
+ Zero(&a, sizeof(a));
+ UniStrCpy(a.OldName, sizeof(a.OldName), old_name);
+ UniStrCpy(a.NewName, sizeof(a.NewName), new_name);
+ if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))
+ {
+ LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);
+ }
+ }
+
+ Free(old_name);
+ }
+ }
+ break;
+ case LVN_KEYDOWN:
+ // Key-press
+ key = (NMLVKEYDOWN *)n;
+ if (key != NULL)
+ {
+ bool ctrl, alt;
+ UINT code = key->wVKey;
+ ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
+ alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
+ CmEasyDlgOnKey(hWnd, d, ctrl, alt, code);
+ }
+ break;
+ }
+ break;
+ }
+}
+
+// Send an update notification to the Simple Connection Manager
+void CmRefreshEasy()
+{
+ if (cm->hEasyWnd == NULL)
+ {
+ return;
+ }
+
+ SendMessage(cm->hEasyWnd, WM_CM_EASY_REFRESH, 0, 0);
+}
+
+// Initialze the Simple Connect Manager
+void CmEasyDlgInit(HWND hWnd, CM_EASY_DLG *d)
+{
+ HFONT hFontForList;
+ HFONT hFontButton;
+ HFONT hFontTitle;
+ HFONT hFontInfo;
+ HFONT hFontOther;
+ UINT i, num, num2, j;
+ bool b = false;
+ char *font_name = NULL;
+ bool font_bold = true;
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_VPN);
+
+ // Window handle registration
+ cm->hEasyWnd = hWnd;
+
+ // Show in the center
+ Center(hWnd);
+
+ // Update the account list
+ CmInitAccountListEx(hWnd, true);
+
+ // Font settings of the list
+ if (cm->VistaStyle)
+ {
+ if (_GETLANG() == 0)
+ {
+ font_name = "Meiryo";
+ font_bold = false;
+ }
+ else if (_GETLANG() == 2)
+ {
+ font_name = "Microsoft YaHei";
+ font_bold = false;
+ }
+ }
+
+ hFontForList = GetFont(font_name, 14, font_bold, false, false, false);
+ hFontButton = GetFont(font_name, 13, font_bold, false, false, false);
+ hFontTitle = GetFont(font_name, 14, font_bold, false, false, false);
+ hFontInfo = GetFont(font_name, 11, font_bold, false, false, false);
+ hFontOther = GetDialogDefaultFont();
+
+ if (cm->VistaStyle)
+ {
+ hFontOther = GetMeiryoFont();
+ }
+
+ SetFont(hWnd, L_ACCOUNT, hFontForList);
+ SetFont(hWnd, IDOK, hFontButton);
+ SetFont(hWnd, S_TITLE, hFontTitle);
+ SetFont(hWnd, S_INFO, hFontInfo);
+ SetFont(hWnd, B_MODE, hFontOther);
+ SetFont(hWnd, IDCANCEL, hFontOther);
+ SetFont(hWnd, B_VGC, hFontOther);
+
+ SetShow(hWnd, B_VGC, cm->Client->IsVgcSupported);
+
+ CmEasyDlgRefresh(hWnd, d);
+
+ num = LvNum(hWnd, L_ACCOUNT);
+ num2 = 0;
+ j = 0;
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+
+ if (str != NULL)
+ {
+ if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ num2++;
+ j = i;
+ }
+ Free(str);
+ }
+ }
+
+ if (num2 == 1)
+ {
+ LvSelect(hWnd, L_ACCOUNT, j);
+ b = true;
+ }
+
+ if (b == false)
+ {
+ if (UniIsEmptyStr(cm->EasyLastSelectedAccountName) == false)
+ {
+ i = LvSearchStr(hWnd, L_ACCOUNT, 0, cm->EasyLastSelectedAccountName);
+ if (i != INFINITE)
+ {
+ LvSelect(hWnd, L_ACCOUNT, i);
+ b = true;
+ }
+ }
+ }
+
+ if (b == false)
+ {
+ if (LvNum(hWnd, L_ACCOUNT) != 0)
+ {
+ LvSelect(hWnd, L_ACCOUNT, 0);
+ }
+ }
+
+ Focus(hWnd, L_ACCOUNT);
+
+ CmEasyDlgUpdate(hWnd, d);
+}
+
+// Update the Simple Connection Manager control
+void CmEasyDlgUpdate(HWND hWnd, CM_EASY_DLG *d)
+{
+ bool ok = true;
+ bool show_status = false;
+ wchar_t *button_str = _UU("CM_EASY_CONNECT_BUTTON_1");
+ wchar_t *info_str = _UU("CM_EASY_INFO_1");
+ wchar_t *title_str = _UU("CM_EASY_TITLE");
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSingleSelected(hWnd, L_ACCOUNT) == false)
+ {
+ ok = false;
+ }
+
+ if (ok)
+ {
+ UINT i = LvGetSelected(hWnd, L_ACCOUNT);
+ wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+
+ info_str = _UU("CM_EASY_INFO_2");
+
+ if (str != NULL)
+ {
+ if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ button_str = _UU("CM_EASY_CONNECT_BUTTON_2");
+ show_status = true;
+ info_str = _UU("CM_EASY_INFO_3");
+
+ if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0)
+ {
+ title_str = _UU("CM_EASY_CONNECTED");
+ }
+ else
+ {
+ title_str = _UU("CM_EASY_CONNECTING");
+ }
+ }
+ Free(str);
+ }
+ }
+
+ SetShow(hWnd, B_STATUS, show_status);
+
+ SetText(hWnd, IDOK, button_str);
+ SetText(hWnd, S_INFO, info_str);
+ SetText(hWnd, S_TITLE, title_str);
+
+ SetShow(hWnd, IDOK, ok);
+}
+
+// Update the Simple Connect Manager content
+void CmEasyDlgRefresh(HWND hWnd, CM_EASY_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ // Update the account list
+ CmRefreshAccountListEx(hWnd, true);
+
+ CmEasyDlgUpdate(hWnd, d);
+}
+
+// Dialog procedure of the simple connection manager
+UINT CmEasyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_EASY_DLG *d = (CM_EASY_DLG *)param;
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmEasyDlgInit(hWnd, d);
+ SetTimer(hWnd, 1, 10, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ SetForegroundWindow(hWnd);
+ SetActiveWindow(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CM_EASY_REFRESH:
+ CmEasyDlgRefresh(hWnd, d);
+ break;
+
+ case WM_COMMAND:
+ CmEasyDlgOnCommand(hWnd, d, wParam, lParam);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ CmEasyDlgOnNotify(hWnd, d, n);
+ break;
+
+ case WM_CLOSE:
+ i = LvGetSelected(hWnd, L_ACCOUNT);
+ if (i != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 0);
+ if (s != NULL)
+ {
+ UniStrCpy(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName),
+ s);
+ Free(s);
+ }
+ }
+ else
+ {
+ Zero(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName));
+ }
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the window of the simple connection manager (This is called by a delaying timer)
+void CmMainWindowOnShowEasy(HWND hWnd)
+{
+ CM_EASY_DLG d;
+
+ Zero(&d, sizeof(d));
+
+ if (cm->CmSetting.EasyMode == false)
+ {
+ // Not in simple mode
+ return;
+ }
+
+ if (cm->hEasyWnd != NULL)
+ {
+ // It is shown already
+ SetForegroundWindow(cm->hEasyWnd);
+ SetActiveWindow(cm->hEasyWnd);
+ return;
+ }
+
+ Dialog(NULL, D_CM_EASY, CmEasyDlg, &d);
+
+ cm->hEasyWnd = NULL;
+}
+
+// Show the window of the simple connection manager
+void CmShowEasy()
+{
+ SetTimer(cm->hMainWnd, 4, 2, NULL);
+}
+
+// Close the window of the simple connection manager
+void CmCloseEasy()
+{
+ if (cm->hEasyWnd == NULL)
+ {
+ return;
+ }
+
+ SendMessage(cm->hEasyWnd, WM_CLOSE, 0, 0);
+}
+
+// Message processing for such as clicking on the tray icon
+void CmMainWindowOnTrayClicked(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+ bool easymode = cm->CmSetting.EasyMode;
+
+ switch (wParam)
+ {
+ case 1:
+ switch (lParam)
+ {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ // Click
+ if (easymode == false)
+ {
+ if (IsEnable(hWnd, 0))
+ {
+ CmShowTrayMenu(hWnd);
+ }
+ else
+ {
+ CmShowOrHideWindow(hWnd);
+ }
+ }
+ else
+ {
+ if (cm->hEasyWnd == NULL || IsEnable(cm->hEasyWnd, 0))
+ {
+ CmShowTrayMenu(hWnd);
+ }
+ else
+ {
+ //CmShowOrHideWindow(hWnd);
+ }
+ }
+ break;
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ // Double click
+ if (easymode == false)
+ {
+ if (IsEnable(hWnd, 0))
+ {
+ CmShowOrHideWindow(hWnd);
+ }
+ }
+ else
+ {
+ if (cm->hEasyWnd == NULL)
+ {
+ CmShowEasy();
+ }
+ else
+ {
+ SetForegroundWindow(cm->hEasyWnd);
+ SetActiveWindow(cm->hEasyWnd);
+ }
+ }
+ break;
+ }
+ break;
+ }
+}
+
+// Apply the setting of the operation mode
+void CmApplyCmSetting()
+{
+ CM_SETTING a;
+ bool changed = false;
+
+ if (cm->CmSettingSupported == false)
+ {
+ return;
+ }
+
+ // Get the configuration of the current vpnclient
+ Zero(&a, sizeof(a));
+ CcGetCmSetting(cm->Client, &a);
+
+ // Check whether there is change point as compared to the previous CM_SETTING
+ if (cm->CmSetting.EasyMode != a.EasyMode)
+ {
+ changed = true;
+ }
+ if (cm->CmSetting.LockMode != a.LockMode)
+ {
+ changed = true;
+ }
+
+ Copy(&cm->CmSetting, &a, sizeof(CM_SETTING));
+
+ if (changed == false)
+ {
+ return;
+ }
+
+ if (cm->StartupFinished)
+ {
+ if (IsShow(cm->hMainWnd, 0) && cm->CmSetting.EasyMode)
+ {
+ // Close the main window if it is shown
+ Hide(cm->hMainWnd, 0);
+ }
+ else
+ {
+ WINDOWPLACEMENT current_pos;
+ if (cm->CmSetting.EasyMode == false && IsShow(cm->hMainWnd, 0) == false)
+ {
+ // When restored to normal mode, restore the main window
+ if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)
+ {
+ cm->FakeWindowPlacement.flags = cm->FakeWindowPlacement.flags & ~SW_MINIMIZE;
+ SetWindowPlacement(cm->hMainWnd, &cm->FakeWindowPlacement);
+ Zero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));
+ Hide(cm->hMainWnd, 0);
+ }
+ CmShowOrHideWindow(cm->hMainWnd);
+ }
+
+ if (cm->CmSetting.EasyMode == false)
+ {
+ if (GetWindowPlacement(cm->hMainWnd, &current_pos))
+ {
+ if (current_pos.rcNormalPosition.right < 0 ||
+ current_pos.rcNormalPosition.bottom < 0)
+ {
+ // If the window is off the screen for some reason,
+ // return it in a visible place
+ SetWindowPos(cm->hMainWnd, NULL, 0, 0, CM_DEFAULT_WIDTH, CM_DEFAULT_HEIGHT, SWP_NOREDRAW | SWP_SHOWWINDOW);
+ Center(cm->hMainWnd);
+ }
+ }
+ }
+ }
+
+ Command(cm->hMainWnd, CMD_REFRESH);
+ }
+
+ if (cm->CmSetting.EasyMode)
+ {
+ if (cm->StartupFinished == false && cm->StartupMode)
+ {
+ // Don't show in the case of /startup
+ }
+ else
+ {
+ CmShowEasy();
+ }
+ }
+ else
+ {
+ CmCloseEasy();
+ }
+}
+
+// Initialize the operation mode changing dialog
+void CmSettingDlgInit(HWND hWnd, CM_SETTING_DLG *d)
+{
+ CM_SETTING a;
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ // Get the configuration of the current vpnclient
+ Zero(&a, sizeof(a));
+ CcGetCmSetting(cm->Client, &a);
+
+ Check(hWnd, R_EASY, a.EasyMode);
+ Check(hWnd, R_NORMAL, a.EasyMode == false);
+
+ if (a.EasyMode == false)
+ {
+ Focus(hWnd, R_NORMAL);
+ }
+ else
+ {
+ Focus(hWnd, R_EASY);
+ }
+
+ Check(hWnd, R_LOCK, a.LockMode);
+
+ SetEnable(hWnd, R_EASY, cm->CmEasyModeSupported);
+
+ if (a.LockMode)
+ {
+ if (IsZero(a.HashedPassword, sizeof(a.HashedPassword)) == false)
+ {
+ // Password is set
+ SetText(hWnd, S_PASSWORD1, _UU("CM_SETTING_PASSWORD"));
+ Hide(hWnd, S_PASSWORD3);
+ Hide(hWnd, E_PASSWORD2);
+
+ d->CheckPassword = true;
+ Copy(d->HashedPassword, a.HashedPassword, sizeof(d->HashedPassword));
+ }
+ }
+
+ SetShow(hWnd, S_VGS1, cm->Client->IsVgcSupported);
+ SetShow(hWnd, S_VGS2, cm->Client->IsVgcSupported);
+ SetShow(hWnd, S_VGS3, cm->Client->IsVgcSupported);
+ SetShow(hWnd, B_VGS, cm->Client->IsVgcSupported);
+
+ CmSettingDlgUpdate(hWnd, d);
+}
+
+// Update the operation mode changing dialog
+void CmSettingDlgUpdate(HWND hWnd, CM_SETTING_DLG *d)
+{
+ bool ok = true;
+ char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+
+ if (d->CheckPassword == false)
+ {
+ if (IsChecked(hWnd, R_LOCK))
+ {
+ if (StrCmp(tmp1, tmp2) != 0)
+ {
+ ok = false;
+ }
+ }
+ }
+ else
+ {
+ bool password_ok = false;
+ UCHAR hash[SHA1_SIZE];
+
+ Hash(hash, tmp1, StrLen(tmp1), true);
+ if (Cmp(hash, d->HashedPassword, sizeof(hash)) == 0)
+ {
+ password_ok = true;
+ }
+
+ if (password_ok == false)
+ {
+ Check(hWnd, R_LOCK, true);
+ Disable(hWnd, R_LOCK);
+ }
+ else
+ {
+ Enable(hWnd, R_LOCK);
+ }
+ }
+
+ SetEnable(hWnd, S_PASSWORD1, IsChecked(hWnd, R_LOCK));
+ SetEnable(hWnd, S_PASSWORD2, IsChecked(hWnd, R_LOCK));
+ SetEnable(hWnd, S_PASSWORD3, IsChecked(hWnd, R_LOCK));
+ SetEnable(hWnd, E_PASSWORD1, IsChecked(hWnd, R_LOCK));
+ SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_LOCK));
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Operation mode changing dialog OK
+void CmSettingDlgOnOk(HWND hWnd, CM_SETTING_DLG *d)
+{
+ CM_SETTING a;
+ char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+
+ Zero(&a, sizeof(a));
+
+ a.EasyMode = IsChecked(hWnd, R_EASY);
+ a.LockMode = IsChecked(hWnd, R_LOCK);
+
+ if (a.LockMode)
+ {
+ if (d->CheckPassword && IsEnable(hWnd, R_LOCK) == false)
+ {
+ Copy(a.HashedPassword, d->HashedPassword, sizeof(a.HashedPassword));
+ }
+ else
+ {
+ if (StrLen(tmp1) >= 1)
+ {
+ Hash(a.HashedPassword, tmp1, StrLen(tmp1), true);
+ }
+ }
+ }
+
+ CcSetCmSetting(cm->Client, &a);
+
+ EndDialog(hWnd, true);
+}
+
+// Operation mode changing dialog
+UINT CmSettingDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_SETTING_DLG *d = (CM_SETTING_DLG *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmSettingDlgInit(hWnd, d);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_EASY:
+ case R_NORMAL:
+ case R_LOCK:
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ case IDOK:
+ case IDCANCEL:
+ CmSettingDlgUpdate(hWnd, d);
+ break;
+ }
+ switch (wParam)
+ {
+ case IDOK:
+ CmSettingDlgOnOk(hWnd, d);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_LOCK:
+ if (IsChecked(hWnd, R_LOCK))
+ {
+ if (IsEmpty(hWnd, E_PASSWORD1))
+ {
+ Focus(hWnd, E_PASSWORD1);
+ }
+ }
+ break;
+
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+
+// Change operation mode
+bool CmSetting(HWND hWnd)
+{
+ CM_SETTING_DLG d;
+
+ Zero(&d, sizeof(d));
+
+ return Dialog(hWnd, D_CM_SETTING, CmSettingDlg, &d);
+}
+
+
+// Attempting thread for starting the UI Helper
+void CmTryToExecUiHelperThread(THREAD *thread, void *param)
+{
+ bool first_flag = true;
+
+ while (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)
+ {
+ if (first_flag == false)
+ {
+ // Wait a little for other than the first time
+ Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);
+
+ if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
+ {
+ break;
+ }
+ }
+ first_flag = false;
+
+ if (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)
+ {
+ if (cm->TryExecUiHelperProcessHandle == NULL)
+ {
+ CmTryToExecUiHelper();
+ }
+ }
+
+ if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
+ {
+ break;
+ }
+
+ if (cm->TryExecUiHelperProcessHandle == NULL)
+ {
+ Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL);
+ }
+ else
+ {
+ HANDLE handles[2];
+ handles[0] = cm->TryExecUiHelperProcessHandle;
+ handles[1] = (HANDLE)cm->TryExecUiHelperHaltEvent->pData;
+ WaitForMultipleObjects(2, handles, false, CM_TRY_EXEC_UI_HELPER_INTERVAL);
+
+ if (WaitForSingleObject(cm->TryExecUiHelperProcessHandle, 0) != WAIT_TIMEOUT)
+ {
+ CloseHandle(cm->TryExecUiHelperProcessHandle);
+ cm->TryExecUiHelperProcessHandle = NULL;
+ if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
+ {
+ break;
+ }
+ Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);
+ }
+ }
+ }
+}
+
+// Stop the UI Helper
+void CmFreeTryToExecUiHelper()
+{
+ cm->TryExecUiHelperHalt = true;
+ Set(cm->TryExecUiHelperHaltEvent);
+
+ WaitThread(cm->TryExecUiHelperThread, INFINITE);
+
+ ReleaseThread(cm->TryExecUiHelperThread);
+ cm->TryExecUiHelperThread = NULL;
+
+ ReleaseEvent(cm->TryExecUiHelperHaltEvent);
+ cm->TryExecUiHelperHaltEvent = NULL;
+
+ cm->TryExecUiHelperHalt = false;
+ cm->TryExecUiHelperProcessHandle = NULL;
+}
+
+// Initialize the UI Helper starting
+void CmInitTryToExecUiHelper()
+{
+ cm->TryExecUiHelperProcessHandle = NULL;
+ cm->TryExecUiHelperHalt = false;
+ cm->TryExecUiHelperHaltEvent = NewEvent();
+ cm->TryExecUiHelperThread = NewThread(CmTryToExecUiHelperThread, NULL);
+}
+
+// Start the UI Helper
+void *CmExecUiHelperMain()
+{
+ HANDLE h;
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), L"%s\\%S", MsGetExeDirNameW(), CiGetVpnClientExeFileName());
+
+ // Start
+ h = Win32RunExW(tmp, SVC_ARG_UIHELP_W, false);
+
+ return (void *)h;
+}
+
+// Attempt to start the UI Helper
+void CmTryToExecUiHelper()
+{
+ HANDLE h;
+ // Check that it isn't already running
+ if (CnCheckAlreadyExists(false))
+ {
+ // It have already started
+ return;
+ }
+
+ h = (HANDLE)CmExecUiHelperMain();
+
+ if (h != NULL)
+ {
+ cm->TryExecUiHelperProcessHandle = h;
+ }
+}
+
+// Initialize the dialog
+void CmTrafficResultDlgInit(HWND hWnd, TT_RESULT *res)
+{
+ LVB *ct;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || res == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SWITCH);
+
+ SetFont(hWnd, L_STATUS, GetFont(_SS("DEFAULT_FONT_2"), 10, false, false, false, false));
+
+ LvInit(hWnd, L_STATUS);
+ LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("TTC_RES_COLUMN_1"), 100);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("TTC_RES_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_STATUS, 2, _UU("TTC_RES_COLUMN_3"), 100);
+
+ ct = LvInsertStart();
+
+ // Time that was used to measure
+ GetSpanStrMilli(str, sizeof(str), res->Span);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(ct, ICO_DATETIME, NULL, 3, _UU("TTC_RES_SPAN"), tmp, L"");
+
+ // Correct the data for Ethernet frame
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_ETHER"), res->Raw ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
+
+ // Amount of communication data of download direction
+ ToStr3(str, sizeof(str), res->NumBytesDownload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesDownload);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_DOWNLOAD"), tmp1, tmp2);
+
+ // Amount of communication data of upload direction
+ ToStr3(str, sizeof(str), res->NumBytesUpload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesUpload);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_UPLOAD"), tmp1, tmp2);
+
+ // Total amount of communication data
+ ToStr3(str, sizeof(str), res->NumBytesTotal);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesTotal);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_TOTAL"), tmp1, tmp2);
+
+ // Calculate the total throughput of input and output of the relay equipment
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_DOUBLE"), (res->Double == false) ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
+
+ // Average throughput of download direction
+ ToStr3(str, sizeof(str), res->BpsDownload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsDownload);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_DOWNLOAD"), tmp1, tmp2);
+
+ // Average throughput of upload direction
+ ToStr3(str, sizeof(str), res->BpsUpload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsUpload);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_UPLOAD"), tmp1, tmp2);
+
+ // Total average throughput
+ ToStr3(str, sizeof(str), res->BpsTotal);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsTotal);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_TOTAL"), tmp1, tmp2);
+
+ LvInsertEnd(ct, hWnd, L_STATUS);
+
+ LvAutoSize(hWnd, L_STATUS);
+}
+
+// Dialog procedure to display results of traffic measurements
+UINT CmTrafficResultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ TT_RESULT *r = (TT_RESULT *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmTrafficResultDlgInit(hWnd, r);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Display results of traffic measurement
+void CmTrafficResult(HWND hWnd, TT_RESULT *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_CM_TRAFFIC_RESULT, CmTrafficResultDlg, r);
+}
+
+// Thread to wait for the termination of the client
+void CmTrafficRunDlgClientWaitThread(THREAD *t, void *param)
+{
+ CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
+ TT_RESULT result;
+ UINT ret;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ Zero(&result, sizeof(result));
+ ret = FreeTtc(d->Ttc, &result);
+ d->Ttc = NULL;
+
+ d->RetCode = ret;
+ Copy(&d->Result, &result, sizeof(TT_RESULT));
+
+ PostMessage(d->hWnd, WM_APP + 66, 0, 0);
+}
+
+// Append the string
+void CmTrafficRunDlgAddStr(HWND hWnd, wchar_t *str)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+
+ tmp_size = UniStrSize(str) + 32;
+ tmp = Malloc(tmp_size);
+ UniStrCpy(tmp, tmp_size, str);
+ if (UniEndWith(str, L"\n") == false)
+ {
+ UniStrCat(tmp, tmp_size, L"\n");
+ }
+
+ UniReplaceStrEx(tmp, tmp_size, tmp, L"\r\n", L"\n", false);
+ UniReplaceStrEx(tmp, tmp_size, tmp, L"\n", L"\r\n", false);
+
+ if (MsIsNt())
+ {
+ SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);
+ SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)tmp);
+ }
+ else
+ {
+ char *s = CopyUniToStr(tmp);
+ UINT len;
+
+ len = GetWindowTextLength(DlgItem(hWnd, E_EDIT));
+ SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);
+ SendMsg(hWnd, E_EDIT, EM_SETSEL, len, len);
+ SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)s);
+ Free(s);
+ }
+
+ Free(tmp);
+}
+
+// Show the string
+void CmTrafficRunDlgPrintProc(void *param, wchar_t *str)
+{
+ CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
+ HWND hWnd;
+ // Validate arguments
+ if (param == NULL || str == NULL)
+ {
+ return;
+ }
+
+ hWnd = d->hWnd;
+
+ PostMessage(hWnd, WM_APP + 64, 0, (LPARAM)UniCopyStr(str));
+}
+
+// Thread for stop the measurement program
+void CmTrafficRunDlgHaltThread(THREAD *t, void *param)
+{
+ CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ if (d->Setting->ServerMode)
+ {
+ // Stop the server
+ d->RetCode = FreeTts(d->Tts);
+
+ PostMessage(d->hWnd, WM_APP + 65, 0, 0);
+ }
+}
+
+// Stop the measurement program
+void CmTrafficRunDlgHalt(HWND hWnd, CM_TRAFFIC_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (d->Started == false)
+ {
+ return;
+ }
+
+ if (d->Setting->ServerMode)
+ {
+ if (d->HaltThread == NULL)
+ {
+ Disable(hWnd, IDCANCEL);
+ d->HaltThread = NewThread(CmTrafficRunDlgHaltThread, d);
+ }
+ }
+ else
+ {
+ if (d->ClientEndWaitThread != NULL)
+ {
+ StopTtc(d->Ttc);
+ }
+ else
+ {
+ EndDialog(hWnd, 0);
+ }
+ }
+}
+
+// Start the operation of traffic measurement
+void CmTrafficRunDlgStart(HWND hWnd, CM_TRAFFIC_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (d->Setting->ServerMode)
+ {
+ // Start the measurement server
+ d->Tts = NewTts(d->Setting->Port, d, CmTrafficRunDlgPrintProc);
+ }
+ else
+ {
+ // Start the measurement client
+ d->Ttc = NewTtc(d->Setting->Host, d->Setting->Port,
+ d->Setting->NumTcp, d->Setting->Type, d->Setting->Span * 1000ULL,
+ d->Setting->Double, d->Setting->Raw, CmTrafficRunDlgPrintProc, d);
+
+ d->ClientEndWaitThread = NewThread(CmTrafficRunDlgClientWaitThread, d);
+ }
+
+ d->Started = true;
+}
+
+// Traffic measurement operation dialog initialization
+void CmTrafficRunDlgInit(HWND hWnd, CM_TRAFFIC_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ d->hWnd = hWnd;
+
+ SetIcon(hWnd, 0, ICO_SWITCH);
+ DlgFont(hWnd, S_INFO, 11, false);
+ SetFont(hWnd, E_EDIT, GetFont(_SS("DEFAULT_FONT_2"), 0, false, false,
+ false, false));
+
+ Focus(hWnd, IDCANCEL);
+}
+
+// Traffic measurement operation dialog procedure
+UINT CmTrafficRunDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmTrafficRunDlgInit(hWnd, d);
+
+ SetTimer(hWnd, 1, 10, NULL);
+ break;
+
+ case WM_APP + 64:
+ // Add a string
+ s = (wchar_t *)lParam;
+ if (s != NULL)
+ {
+ CmTrafficRunDlgAddStr(hWnd, s);
+ Free(s);
+ }
+ break;
+
+ case WM_APP + 65:
+ // Stopping complete
+ if (d->HaltThread != NULL)
+ {
+ WaitThread(d->HaltThread, INFINITE);
+ ReleaseThread(d->HaltThread);
+ d->HaltThread = NULL;
+ EndDialog(hWnd, 0);
+ }
+ break;
+
+ case WM_APP + 66:
+ // Show results
+ if (d->RetCode == ERR_NO_ERROR)
+ {
+ CmTrafficResult(hWnd, &d->Result);
+ }
+
+ if (d->ClientEndWaitThread != NULL)
+ {
+ WaitThread(d->ClientEndWaitThread, INFINITE);
+ ReleaseThread(d->ClientEndWaitThread);
+ d->ClientEndWaitThread = NULL;
+ }
+
+ if (d->CloseDialogAfter)
+ {
+ EndDialog(hWnd, 0);
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ CmTrafficRunDlgStart(hWnd, d);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ d->CloseDialogAfter = true;
+ CmTrafficRunDlgHalt(hWnd, d);
+ return 1;
+ }
+
+ return 0;
+}
+
+// Execute a traffic measurement
+void CmExecTraffic(HWND hWnd, CM_TRAFFIC *t)
+{
+ CM_TRAFFIC_DLG d;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Zero(&d, sizeof(d));
+ d.Setting = t;
+ d.ResultShowEvent = NewEvent();
+
+ MsSetThreadPriorityHigh();
+ Dialog(hWnd, D_CM_TRAFFIC_RUN, CmTrafficRunDlg, &d);
+ MsRestoreThreadPriority();
+
+ ReleaseEvent(d.ResultShowEvent);
+}
+
+// Write the settings to the registry
+void CmTrafficSaveToReg(CM_TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode", t->ServerMode ? 1 : 0);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double", t->Double ? 1 : 0);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw", t->Raw ? 1 : 0);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port", t->Port);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp", t->NumTcp);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type", t->Type);
+ MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span", t->Span);
+ MsRegWriteStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host", t->Host);
+}
+
+// Read the settings from the registry
+bool CmTrafficLoadFromReg(CM_TRAFFIC *t)
+{
+ char *s;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ Zero(t, sizeof(CM_TRAFFIC));
+
+ if (MsRegIsKey(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY) == false)
+ {
+ return false;
+ }
+
+ t->Double = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double") == 0 ? false : true;
+ t->Raw = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw") == 0 ? false : true;
+ t->Port = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port");
+ if (t->Port == 0)
+ {
+ t->Port = TRAFFIC_DEFAULT_PORT;
+ }
+
+ s = MsRegReadStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host");
+
+ if (IsEmptyStr(s) == false)
+ {
+ Trim(s);
+ StrCpy(t->Host, sizeof(t->Host), s);
+ }
+
+ Free(s);
+
+ t->NumTcp = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp");
+ t->NumTcp = MAKESURE(t->NumTcp, 1, TRAFFIC_NUMTCP_MAX);
+ t->Type = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type");
+
+ if (t->Type != TRAFFIC_TYPE_DOWNLOAD && t->Type != TRAFFIC_TYPE_UPLOAD &&
+ t->Type != TRAFFIC_TYPE_FULL)
+ {
+ t->Type = TRAFFIC_TYPE_FULL;
+ }
+
+ t->Span = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span");
+ if (t->Span == 0)
+ {
+ t->Span = TRAFFIC_SPAN_DEFAULT;
+ }
+
+ t->ServerMode = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode") == 0 ? false : true;
+
+ return true;
+}
+
+// Get the default settings
+void CmTrafficGetDefaultSetting(CM_TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(CM_TRAFFIC));
+
+ t->Double = false;
+ t->Raw = false;
+ t->Port = TRAFFIC_DEFAULT_PORT;
+ t->NumTcp = TRAFFIC_NUMTCP_DEFAULT;
+ t->Type = TRAFFIC_TYPE_FULL;
+ t->Span = TRAFFIC_SPAN_DEFAULT;
+ t->ServerMode = false;
+}
+
+// Communication throughput measurement tool dialog initialization
+void CmTrafficDlgInit(HWND hWnd)
+{
+ CM_TRAFFIC t;
+ LIST *c1, *c2;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ DlgFont(hWnd, S_8, 9, true);
+ DlgFont(hWnd, S_3, 9, true);
+
+ Zero(&t, sizeof(t));
+ if (CmTrafficLoadFromReg(&t) == false)
+ {
+ CmTrafficGetDefaultSetting(&t);
+ }
+
+ // Write the settings to the dialog
+ Check(hWnd, R_SERVER, t.ServerMode);
+ Check(hWnd, R_CLIENT, t.ServerMode == false);
+
+ c1 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");
+ if (c1 != NULL)
+ {
+ UINT i;
+
+ CbReset(hWnd, C_HOST);
+
+ for (i = 0;i < LIST_NUM(c1);i++)
+ {
+ CANDIDATE *c = LIST_DATA(c1, i);
+
+ CbAddStr(hWnd, C_HOST, c->Str, 0);
+ }
+
+ FreeCandidateList(c1);
+ }
+
+ if (CbNum(hWnd, C_HOST) == 0)
+ {
+ CbAddStr(hWnd, C_HOST, L"speed.softether.com", 0);
+ }
+
+ if (IsEmptyStr(t.Host) == false)
+ {
+ SetTextA(hWnd, C_HOST, t.Host);
+ }
+
+ c2 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");
+ if (c2 != NULL)
+ {
+ UINT i;
+
+ if (t.Port != 0)
+ {
+ wchar_t tmp[32];
+
+ UniToStru(tmp, t.Port);
+
+ AddCandidate(c2, tmp, 0);
+ }
+
+ CbReset(hWnd, C_PORT);
+
+ for (i = 0;i < LIST_NUM(c2);i++)
+ {
+ CANDIDATE *c = LIST_DATA(c2, i);
+
+ CbAddStr(hWnd, C_PORT, c->Str, 0);
+ }
+
+ FreeCandidateList(c2);
+ }
+
+ CbReset(hWnd, C_NUM);
+
+ for (i = 1;i <= TRAFFIC_NUMTCP_MAX;i++)
+ {
+ wchar_t tmp[32];
+
+ UniToStru(tmp, i);
+
+ CbAddStr(hWnd, C_NUM, tmp, i);
+ }
+
+ CbSelect(hWnd, C_NUM, t.NumTcp);
+
+ Check(hWnd, R_DOWNLOAD, t.Type == TRAFFIC_TYPE_DOWNLOAD);
+ Check(hWnd, R_UPLOAD, t.Type == TRAFFIC_TYPE_UPLOAD);
+ Check(hWnd, R_FULL, t.Type == TRAFFIC_TYPE_FULL);
+
+ Check(hWnd, R_ETHERNET, t.Raw ? false : true);
+ Check(hWnd, R_DOUBLE, t.Double);
+
+ SetIntEx(hWnd, E_SPAN, t.Span);
+
+ CmTrafficDlgUpdate(hWnd);
+}
+
+// Put the contents of the dialog to structure
+void CmTrafficDlgToStruct(HWND hWnd, CM_TRAFFIC *t)
+{
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(CM_TRAFFIC));
+ t->ServerMode = IsChecked(hWnd, R_SERVER);
+ GetTxtA(hWnd, C_HOST, t->Host, sizeof(t->Host));
+ Trim(t->Host);
+
+ t->Port = GetInt(hWnd, C_PORT);
+ t->NumTcp = CbGetSelect(hWnd, C_NUM);
+ t->Span = GetInt(hWnd, E_SPAN);
+ t->Raw = IsChecked(hWnd, R_ETHERNET) ? false : true;
+ t->Double = IsChecked(hWnd, R_DOUBLE);
+
+ if (IsChecked(hWnd, R_DOWNLOAD))
+ {
+ t->Type = TRAFFIC_TYPE_DOWNLOAD;
+ }
+ else if (IsChecked(hWnd, R_UPLOAD))
+ {
+ t->Type = TRAFFIC_TYPE_UPLOAD;
+ }
+ else
+ {
+ t->Type = TRAFFIC_TYPE_FULL;
+ }
+}
+
+// Communication throughput measurement tool dialog update
+bool CmTrafficDlgUpdate(HWND hWnd)
+{
+ CM_TRAFFIC t;
+ bool ok = true;
+ bool client_only;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ CmTrafficDlgToStruct(hWnd, &t);
+
+ client_only = t.ServerMode ? false : true;
+
+ SetEnable(hWnd, C_HOST, client_only);
+ SetEnable(hWnd, S_5, client_only);
+ SetEnable(hWnd, S_8, client_only);
+ SetEnable(hWnd, S_9, client_only);
+ SetEnable(hWnd, R_DOWNLOAD, client_only);
+ SetEnable(hWnd, R_UPLOAD, client_only);
+ SetEnable(hWnd, R_FULL, client_only);
+ SetEnable(hWnd, S_10, client_only);
+ SetEnable(hWnd, S_11, client_only);
+ SetEnable(hWnd, C_NUM, client_only);
+ SetEnable(hWnd, S_14, client_only);
+ SetEnable(hWnd, S_12, client_only);
+ SetEnable(hWnd, E_SPAN, client_only);
+ SetEnable(hWnd, S_13, client_only);
+ SetEnable(hWnd, R_ETHERNET, client_only);
+ SetEnable(hWnd, R_DOUBLE, client_only);
+
+ if (t.Port == 0 || t.Port >= 65536)
+ {
+ ok = false;
+ }
+
+ if (t.ServerMode == false)
+ {
+ if (IsEmptyStr(t.Host))
+ {
+ ok = false;
+ }
+
+ if (t.NumTcp == 0 || t.NumTcp >= 33)
+ {
+ ok = false;
+ }
+
+ if (t.Span == 0)
+ {
+ ok = false;
+ }
+
+ if (t.Type == TRAFFIC_TYPE_FULL && ((t.NumTcp % 2) != 0))
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+
+ return ok;
+}
+
+// Communication throughput measurement tool dialog OK button
+void CmTrafficDlgOnOk(HWND hWnd)
+{
+ CM_TRAFFIC t;
+ LIST *c;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Get the basic data
+ CmTrafficDlgToStruct(hWnd, &t);
+
+ // Save to registry
+ CmTrafficSaveToReg(&t);
+
+ // Retrieve and save the server name candidate
+ if (IsEmptyStr(t.Host) == false)
+ {
+ c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");
+ if (c != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ StrToUni(tmp, sizeof(tmp), t.Host);
+ AddCandidate(c, tmp, 0);
+
+ WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "HostCandidate");
+
+ FreeCandidateList(c);
+ }
+ }
+
+ if (t.Port != 0 && t.Port <= 65536)
+ {
+ // Retrieve and store the port number candidate
+ c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");
+ if (c != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniToStru(tmp, t.Port);
+ AddCandidate(c, tmp, 0);
+
+ WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "PortCandidate");
+
+ FreeCandidateList(c);
+ }
+ }
+
+ // Execute
+ CmExecTraffic(hWnd, &t);
+
+ // Update the dialog
+ CmTrafficDlgInit(hWnd);
+}
+
+// Communication throughput measurement tool dialog procedure
+UINT CmTrafficDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_SWITCH);
+ CmTrafficDlgInit(hWnd);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_SERVER:
+ case R_CLIENT:
+ case C_HOST:
+ case C_PORT:
+ case R_DOWNLOAD:
+ case R_UPLOAD:
+ case R_FULL:
+ case C_NUM:
+ case E_SPAN:
+ case R_ETHERNET:
+ case R_DOUBLE:
+ CmTrafficDlgUpdate(hWnd);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ CmTrafficDlgOnOk(hWnd);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Communication throughput measurement tool
+void CmTraffic(HWND hWnd)
+{
+ Dialog(hWnd, D_CM_TRAFFIC, CmTrafficDlgProc, NULL);
+}
+
+// Delete old startup file
+void CmDeleteOldStartupTrayFile()
+{
+ char tmp[MAX_SIZE];
+ char *tag = _SS("CM_JAPANESE_ONLY_OLD_STARTUP");
+ if (IsEmptyStr(tag))
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), tag, MsGetCommonStartupDir());
+
+ FileDelete(tmp);
+}
+
+// PKCS license confirmation dialog
+UINT CmPkcsEulaDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT id;
+ SECURE_DEVICE *dev;
+ char *name;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ id = (UINT)param;
+ dev = GetSecureDevice(id);
+ if (dev == NULL)
+ {
+ EndDialog(hWnd, 0);
+ return 0;
+ }
+
+ name = dev->ModuleName;
+
+ FormatText(hWnd, S_INFO_1, name);
+ FormatText(hWnd, S_INFO_2, name, name);
+ FormatText(hWnd, S_INFO_3, name);
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Confirmation screen of whether the user accepts the EULA of the PKCS DLL
+bool CmCheckPkcsEula(HWND hWnd, UINT id)
+{
+ return (Dialog(hWnd, D_CM_PKCSEULA, CmPkcsEulaDlg, (void *)id) == 0) ? false : true;
+}
+
+// Update controls
+void CmSecurePinDlgUpdate(HWND hWnd)
+{
+ char *tmp1, *tmp2, *tmp3;
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ tmp1 = GetTextA(hWnd, E_PIN1);
+ tmp2 = GetTextA(hWnd, E_PIN2);
+ tmp3 = GetTextA(hWnd, E_PIN3);
+ if (IsEmptyStr(tmp1))
+ {
+ ok = false;
+ }
+ if (IsEmptyStr(tmp2))
+ {
+ ok = false;
+ }
+ if (IsEmptyStr(tmp3))
+ {
+ ok = false;
+ }
+ if (StrCmp(tmp2, tmp3) != 0)
+ {
+ ok = false;
+ }
+ Free(tmp1);
+ Free(tmp2);
+ Free(tmp3);
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// PIN code changing dialog
+UINT CmSecurePinDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT id = (UINT)param;
+ char *src, *dst;
+ SECURE *s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmSecurePinDlgUpdate(hWnd);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_PIN1:
+ case E_PIN2:
+ case E_PIN3:
+ CmSecurePinDlgUpdate(hWnd);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ src = GetTextA(hWnd, E_PIN1);
+ dst = GetTextA(hWnd, E_PIN3);
+
+ Disable(hWnd, IDOK);
+ Disable(hWnd, IDCANCEL);
+
+ s = OpenSec(id);
+ if (s == NULL)
+ {
+ if (GetSecureDevice(id) != NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
+ GetSecureDevice(id)->DeviceName);
+ }
+ else
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
+ "Unknown");
+ }
+ }
+ else
+ {
+ if (OpenSecSession(s, 0) == false)
+ {
+ if (GetSecureDevice(id) != NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
+ GetSecureDevice(id)->DeviceName);
+ }
+ else
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
+ "Unknown");
+ }
+ }
+ else
+ {
+ if (LoginSec(s, src) == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CURRENT_BAD"));
+ FocusEx(hWnd, E_PIN1);
+ }
+ else
+ {
+ if (ChangePin(s, src, dst) == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CHANGE_FAILED"));
+ FocusEx(hWnd, E_PIN1);
+ }
+ else
+ {
+ // Clear the cache for PIN code
+ cached_pin_code_expires = 0;
+ cached_pin_code[0] = 0;
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_PIN_OK"));
+ EndDialog(hWnd, true);
+ }
+
+ LogoutSec(s);
+ }
+
+ CloseSecSession(s);
+ }
+ CloseSec(s);
+ }
+
+ Enable(hWnd, IDOK);
+ Enable(hWnd, IDCANCEL);
+
+ Free(src);
+ Free(dst);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Change the PIN code
+void CmSecurePin(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL || id == 0 || CheckSecureDeviceId(id) == false)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_CM_SECURE_PIN, CmSecurePinDlg, (void *)id);
+}
+
+// Object type selection dialog
+UINT CmSecureTypeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT type;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ type = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType");
+ Check(hWnd, R_DATA, type == SEC_DATA);
+ Check(hWnd, R_CERT, type == SEC_X);
+ Check(hWnd, R_KEY, type == SEC_K);
+ goto UPDATE_CONTROL;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ type = SEC_DATA;
+ if (IsChecked(hWnd, R_CERT))
+ {
+ type = SEC_X;
+ }
+ else if (IsChecked(hWnd, R_KEY))
+ {
+ type = SEC_K;
+ }
+
+ MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType", type);
+
+ EndDialog(hWnd, type);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case R_CERT:
+ case R_KEY:
+ case R_DATA:
+UPDATE_CONTROL:
+ SetEnable(hWnd, IDOK, IsChecked(hWnd, R_CERT) ||
+ IsChecked(hWnd, R_KEY) ||
+ IsChecked(hWnd, R_DATA));
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, INFINITE);
+ break;
+ }
+
+ return 0;
+}
+
+// Object type selection
+UINT CmSecureType(HWND hWnd)
+{
+ return Dialog(hWnd, D_CM_SECURE_TYPE, CmSecureTypeDlg, NULL);
+}
+
+// Initialize the dialog
+void CmSecureManagerDlgInit(HWND hWnd, UINT id)
+{
+ SECURE_DEVICE *dev;
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SECURE);
+
+ dev = GetSecureDevice(id);
+ if (dev != NULL)
+ {
+ FormatText(hWnd, S_INFO, dev->DeviceName);
+ }
+
+ SetFont(hWnd, B_BOLD, Font(0, true));
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_MGR_COLUMN1"), 200);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_MGR_COLUMN2"), 110);
+
+ CmSecureManagerDlgUpdate(hWnd, id);
+}
+
+// Update controls
+void CmSecureManagerDlgUpdate(HWND hWnd, UINT id)
+{
+ bool b = true;
+ bool read_only = IsJPKI(id);
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSingleSelected(hWnd, L_LIST) == false)
+ {
+ b = false;
+ }
+
+ SetEnable(hWnd, B_EXPORT, b && ((UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST)) != SEC_K));
+ SetEnable(hWnd, B_DELETE, b && (read_only == false));
+ SetEnable(hWnd, B_PIN, (read_only == false));
+ SetEnable(hWnd, B_IMPORT, (read_only == false));
+ SetEnable(hWnd, B_NEW_CERT, (read_only == false));
+}
+
+// Content update
+void CmSecureManagerDlgRefresh(HWND hWnd, UINT id)
+{
+ bool ret;
+ LIST *o;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ ret = SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0);
+
+ if (ret == false)
+ {
+ return;
+ }
+
+ o = batch[0].EnumList;
+ if (o != NULL)
+ {
+ CmSecureManagerDlgPrintList(hWnd, o);
+
+ FreeEnumSecObject(o);
+ }
+
+ // update controls
+ CmSecureManagerDlgUpdate(hWnd, id);
+}
+
+// Show the list of secure objects
+void CmSecureManagerDlgPrintList(HWND hWnd, LIST *o)
+{
+ CmSecureManagerDlgPrintListEx(hWnd, L_LIST, o, INFINITE);
+}
+void CmSecureManagerDlgPrintListEx(HWND hWnd, UINT id, LIST *o, UINT type)
+{
+ UINT i;
+ LVB *v;
+ // Validate arguments
+ if (hWnd == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LvReset(hWnd, id);
+
+ v = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT icon = ICO_LOG2;
+ wchar_t tmp1[MAX_SIZE], *tmp2, *tmp3;
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ if (type == INFINITE || obj->Type == type)
+ {
+ StrToUni(tmp1, sizeof(tmp1), obj->Name);
+ tmp2 = CmSecureObjTypeToStr(obj->Type);
+ tmp3 = obj->Private ? _UU("SEC_YES") : _UU("SEC_NO");
+
+ if (obj->Type == SEC_X)
+ {
+ icon = ICO_CERT;
+ }
+ else if (obj->Type == SEC_K || obj->Type == SEC_P)
+ {
+ icon = ICO_KEY;
+ }
+
+ LvInsertAdd(v, icon, (void *)obj->Type, 2, tmp1, tmp2);
+ }
+ }
+
+ LvInsertEnd(v, hWnd, id);
+}
+
+// Convert the type of secure object to a string
+wchar_t *CmSecureObjTypeToStr(UINT type)
+{
+ wchar_t *ret = _UU("SEC_TYPE_DATA");
+
+ if (type == SEC_X)
+ {
+ ret = _UU("SEC_TYPE_CERT");
+ }
+ else if (type == SEC_K)
+ {
+ ret = _UU("SEC_TYPE_KEY");
+ }
+ else if (type == SEC_P)
+ {
+ ret = _UU("SEC_TYPE_PUB");
+ }
+
+ return ret;
+}
+
+// Write by creating a new certificate
+void CmSecureManagerDlgNewCert(HWND hWnd, UINT id)
+{
+ X *x;
+ K *k;
+ char default_name[MAX_SIZE];
+ char *object_name;
+ bool ok = false;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_WRITE_CERT, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_WRITE_KEY, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ // Dialog for creating certificate
+ if (SmCreateCert(hWnd, &x, &k, true, NULL, false) == false)
+ {
+ return;
+ }
+ // Generate the default name
+ GetPrintNameFromXA(default_name, sizeof(default_name), x);
+ ConvertSafeFileName(default_name, sizeof(default_name), default_name);
+
+ object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
+ _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);
+
+ if (object_name != NULL)
+ {
+ // Enumerate and write
+ batch[0].InputX = x;
+ batch[0].Name = object_name;
+ batch[1].InputK = k;
+ batch[1].Name = object_name;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ // Failure
+ }
+ else
+ {
+ ok = true;
+ }
+
+ Free(object_name);
+ }
+
+ if (ok)
+ {
+ LIST *o = batch[2].EnumList;
+
+ CmSecureManagerDlgPrintList(hWnd, o);
+
+ FreeEnumSecObject(o);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NEW_CERT_IMPORT_OK"));
+ }
+
+ FreeX(x);
+ FreeK(k);
+}
+
+// Import
+void CmSecureManagerDlgImport(HWND hWnd, UINT id)
+{
+ UINT type;
+ char name[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t *tmp;
+ wchar_t *filename;
+ BUF *b;
+ K *k;
+ bool ok = false;
+ X *x;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_WRITE_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ // Select the type of secure object
+ type = CmSecureType(hWnd);
+
+ switch (type)
+ {
+ case SEC_DATA:
+ // Data
+ tmp = OpenDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("SEC_IMPORT_DATA"));
+ if (tmp == NULL)
+ {
+ return;
+ }
+
+ filename = CopyUniStr(tmp);
+ Free(tmp);
+
+ // Read the file
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ // Read failure
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SEC_READ_FAILED"));
+ }
+ else
+ {
+ if (b->Size > MAX_SEC_DATA_SIZE)
+ {
+ // File size is too large
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_DATA_TOO_BIG"), MAX_SEC_DATA_SIZE);
+ }
+ else
+ {
+ // Generate the default name
+ char default_name[MAX_SIZE];
+ wchar_t default_name_w[MAX_SIZE];
+ char *object_name;
+ GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), filename);
+ UniToStr(default_name, sizeof(default_name), default_name_w);
+ ConvertSafeFileName(default_name, sizeof(default_name), default_name);
+
+ object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
+ _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_LOG2, false, false);
+
+ if (object_name != NULL)
+ {
+ // Enumerate and write
+ batch[0].InputData = b;
+ batch[0].Name = object_name;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ // Failure
+ }
+ else
+ {
+ ok = true;
+ }
+
+ Free(object_name);
+ }
+ }
+
+ FreeBuf(b);
+ }
+
+ Free(filename);
+ break;
+
+ case SEC_X:
+ // Read a certificate
+ if (CmLoadXExW(hWnd, &x, tmp2, sizeof(tmp2)))
+ {
+ // Generate the default name
+ char default_name[MAX_SIZE];
+ wchar_t default_name_w[MAX_PATH];
+ char *object_name;
+ GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);
+ UniToStr(default_name, sizeof(default_name), default_name_w);
+ ConvertSafeFileName(default_name, sizeof(default_name), default_name);
+
+ object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
+ _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);
+
+ if (object_name != NULL)
+ {
+ // Enumerate and write
+ batch[0].Type = WINUI_SECURE_WRITE_CERT;
+ batch[0].InputX = x;
+ batch[0].Name = object_name;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ // Failure
+ }
+ else
+ {
+ ok = true;
+ }
+
+ Free(object_name);
+ }
+
+ FreeX(x);
+ }
+
+ break;
+
+ case SEC_K:
+ // Secret key
+ if (CmLoadKExW(hWnd, &k, tmp2, sizeof(tmp2)))
+ {
+ // Generate the default name
+ char default_name[MAX_SIZE];
+ wchar_t default_name_w[MAX_PATH];
+ char *object_name;
+ GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);
+ UniToStr(default_name, sizeof(default_name), default_name_w);
+ ConvertSafeFileName(default_name, sizeof(default_name), default_name);
+
+ object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
+ _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_KEY, false, false);
+
+ if (object_name != NULL)
+ {
+ // Enumerate and write
+ batch[0].Type = WINUI_SECURE_WRITE_KEY;
+ batch[0].InputK = k;
+ batch[0].Name = object_name;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ // Failure
+ }
+ else
+ {
+ ok = true;
+ }
+
+ Free(object_name);
+ }
+
+ FreeK(k);
+ }
+ break;
+
+ default:
+ // Invalid
+ return;
+ }
+
+ if (ok)
+ {
+ LIST *o = batch[1].EnumList;
+
+ CmSecureManagerDlgPrintList(hWnd, o);
+
+ FreeEnumSecObject(o);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_IMPORT_OK"));
+ }
+}
+
+// Export the object
+void CmSecureManagerDlgExport(HWND hWnd, UINT id)
+{
+ char name[MAX_SIZE];
+ UINT method = WINUI_SECURE_READ_DATA;
+ char *tmp;
+ UINT type;
+ wchar_t filename[MAX_PATH];
+ wchar_t *uni_tmp;
+ X *x;
+ BUF *b;
+ wchar_t default_name[128];
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_READ_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i == INFINITE)
+ {
+ return;
+ }
+
+ tmp = LvGetStrA(hWnd, L_LIST, i, 0);
+ StrCpy(name, sizeof(name), tmp);
+ Free(tmp);
+
+ type = (UINT)LvGetParam(hWnd, L_LIST, i);
+
+ switch (type)
+ {
+ case SEC_X:
+ method = WINUI_SECURE_READ_CERT;
+ break;
+
+ default:
+ method = WINUI_SECURE_READ_DATA;
+ break;
+ }
+
+ batch[0].Type = method;
+
+ // Operate the smart card
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ return;
+ }
+
+ switch (type)
+ {
+ case SEC_X:
+ // Certificate
+ x = batch[0].OutputX;
+
+ CertDlg(hWnd, x, NULL, true);
+
+ FreeX(x);
+ break;
+
+ default:
+ // File
+ b = batch[0].OutputData;
+ StrToUni(default_name, sizeof(default_name), name);
+ uni_tmp = SaveDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("DLG_SAVE_FILE"), default_name, NULL);
+
+ if (uni_tmp != NULL)
+ {
+ UniStrCpy(filename, sizeof(filename), uni_tmp);
+
+ DumpBufW(b, filename);
+
+ Free(uni_tmp);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_EXPORT_OK"));
+ }
+
+
+ FreeBuf(b);
+ break;
+ }
+}
+
+// Delete the object
+void CmSecureManagerDlgDelete(HWND hWnd, UINT id)
+{
+ char name[MAX_SIZE];
+ UINT method = WINUI_SECURE_DELETE_DATA;
+ char *tmp;
+ UINT type;
+ LIST *o;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_DELETE_OBJECT, name, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i == INFINITE)
+ {
+ return;
+ }
+
+ tmp = LvGetStrA(hWnd, L_LIST, i, 0);
+ StrCpy(name, sizeof(name), tmp);
+ Free(tmp);
+
+ type = (UINT)LvGetParam(hWnd, L_LIST, i);
+
+ switch (type)
+ {
+ case SEC_X:
+ method = WINUI_SECURE_DELETE_CERT;
+ break;
+
+ case SEC_K:
+ method = WINUI_SECURE_DELETE_KEY;
+ break;
+
+ default:
+ method = WINUI_SECURE_DELETE_DATA;
+ break;
+ }
+
+ batch[0].Type = method;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
+ {
+ return;
+ }
+
+ o = batch[1].EnumList;
+
+ CmSecureManagerDlgPrintList(hWnd, o);
+
+ FreeEnumSecObject(o);
+}
+
+static bool cm_secure_manager_no_new_cert = false;
+
+// Smart Card Manager dialog
+UINT CmSecureManagerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ UINT id = (UINT)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmSecureManagerDlgInit(hWnd, id);
+
+ if (cm_secure_manager_no_new_cert)
+ {
+ Hide(hWnd, B_NEW_CERT);
+ }
+
+ SetTimer(hWnd, 1, 1, NULL);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_REFRESH:
+ CmSecureManagerDlgRefresh(hWnd, id);
+ break;
+
+ case B_IMPORT:
+ CmSecureManagerDlgImport(hWnd, id);
+ break;
+
+ case B_EXPORT:
+ CmSecureManagerDlgExport(hWnd, id);
+ break;
+
+ case B_DELETE:
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2,
+ _UU("SEC_DELETE_MSG")) == IDYES)
+ {
+ CmSecureManagerDlgDelete(hWnd, id);
+ }
+ break;
+
+ case B_NEW_CERT:
+ CmSecureManagerDlgNewCert(hWnd, id);
+ break;
+
+ case B_PIN:
+ CmSecurePin(hWnd, id);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ CmSecureManagerDlgRefresh(hWnd, id);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CmSecureManagerDlgUpdate(hWnd, id);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Smart Card Manager
+void CmSecureManager(HWND hWnd, UINT id)
+{
+ CmSecureManagerEx(hWnd, id, false);
+}
+void CmSecureManagerEx(HWND hWnd, UINT id, bool no_new_cert)
+{
+ // Validate arguments
+ if (hWnd == NULL || id == 0)
+ {
+ return;
+ }
+
+ // ID check
+ if (CheckSecureDeviceId(id) == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_INVALID_ID"));
+ return;
+ }
+
+ if (no_new_cert)
+ {
+ cm_secure_manager_no_new_cert = true;
+ }
+ else
+ {
+ cm_secure_manager_no_new_cert = false;
+ }
+
+ Dialog(hWnd, D_CM_SECURE_MANAGER, CmSecureManagerDlg, (void *)id);
+}
+
+// Smart Card Manager for Client
+void CmClientSecureManager(HWND hWnd)
+{
+ RPC_USE_SECURE t;
+ UINT id;
+
+ Zero(&t, sizeof(t));
+ CcGetUseSecure(cm->Client, &t);
+
+ id = t.DeviceId;
+
+ if (id == 0 || CheckSecureDeviceId(id) == false)
+ {
+ id = CmClientSelectSecure(hWnd);
+ }
+
+ if (id == 0)
+ {
+ return;
+ }
+
+ CmSecureManager(hWnd, id);
+}
+
+// Initialize the dialog
+void CmSelectSecureDlgInit(HWND hWnd, UINT default_id)
+{
+ UINT i;
+ LIST *o;
+ LVB *v;
+
+ SetIcon(hWnd, 0, ICO_SECURE);
+
+ o = GetSecureDeviceList();
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_COLUMN1"), 150);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_COLUMN2"), 100);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SEC_COLUMN3"), 130);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SEC_COLUMN4"), 100);
+
+ v = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t *tmp2;
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ SECURE_DEVICE *dev = LIST_DATA(o, i);
+
+ StrToUni(tmp1, sizeof(tmp1), dev->DeviceName);
+ tmp2 = (dev->Type == SECURE_IC_CARD) ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN");
+ StrToUni(tmp3, sizeof(tmp3), dev->Manufacturer);
+ StrToUni(tmp4, sizeof(tmp4), dev->ModuleName);
+
+ LvInsertAdd(v, ICO_SECURE, (void *)dev->Id, 4, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ LvInsertEnd(v, hWnd, L_LIST);
+
+ if (default_id != 0)
+ {
+ LvSelect(hWnd, L_LIST, LvSearchParam(hWnd, L_LIST, (void *)default_id));
+ }
+
+ ReleaseList(o);
+
+ // Control update
+ CmSelectSecureDlgUpdate(hWnd);
+}
+
+// Update controls of the dialog
+void CmSelectSecureDlgUpdate(HWND hWnd)
+{
+ SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));
+}
+
+// Smart card selection dialog
+UINT CmSelectSecureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT default_id = (UINT)param;
+ NMHDR *n = NULL;
+ static UINT old_id;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ old_id = default_id;
+ CmSelectSecureDlgInit(hWnd, default_id);
+
+ if (LvNum(hWnd, L_LIST) == 0)
+ {
+ // There is no smart card
+ SetTimer(hWnd, 1, 100, NULL);
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ Disable(hWnd, L_LIST);
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NO_SECURE_DEVICE"));
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ UINT id = (UINT)LvGetParam(hWnd, L_LIST, i);
+
+ if (old_id != id)
+ {
+ if (CmCheckPkcsEula(hWnd, id) == false)
+ {
+ break;
+ }
+ }
+ EndDialog(hWnd, id);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CmSelectSecureDlgUpdate(hWnd);
+ break;
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Select the smart card device to be used
+UINT CmSelectSecure(HWND hWnd, UINT current_id)
+{
+ return Dialog(hWnd, D_CM_SELECT_SECURE, CmSelectSecureDlg, (void *)current_id);
+}
+
+// Select the smart card device to be used (client)
+UINT CmClientSelectSecure(HWND hWnd)
+{
+ UINT id;
+ RPC_USE_SECURE t;
+
+ if (cm->server_name != NULL)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_SECURE_MUST_LOCAL"));
+ return 0;
+ }
+
+ Zero(&t, sizeof(t));
+ CcGetUseSecure(cm->Client, &t);
+
+ id = t.DeviceId;
+
+ id = CmSelectSecure(hWnd, id);
+ if (id != 0)
+ {
+ Zero(&t, sizeof(t));
+ t.DeviceId = id;
+
+ CALL(hWnd, CcUseSecure(cm->Client, &t));
+
+ SmWriteSelectSecureIdReg(id);
+ }
+
+ return id;
+}
+
+// Shortcut connection
+void CmConnectShortcut(UCHAR *key)
+{
+ UINT ret;
+ // Validate arguments
+ if (key == NULL)
+ {
+ return;
+ }
+
+ // Attempt to connect
+ ret = CcShortcut(key);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ if (ret == ERR_ACCOUNT_ACTIVE)
+ {
+ // Because it is currently connected, to query whether or not to disconnect
+ if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_SHORTCUT_DISCONNECT")) == IDYES)
+ {
+ // Try to disconnect
+ ret = CcShortcutDisconnect(key);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error
+ MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));
+ }
+ }
+ }
+ else
+ {
+ // Other errors
+ MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));
+ }
+ }
+}
+
+// Play the audio guide
+void CmVoice(char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ // Voice guidance features disappeared!!
+ return;
+
+ if (cm->DisableVoice)
+ {
+ return;
+ }
+
+ for (i = 0;i < sizeof(cm_voice) / sizeof(CM_VOICE);i++)
+ {
+ if (cm_voice[i].voice_id == cm->VoiceId)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "%s_%s.wav", cm_voice[i].perfix, name);
+ MsPlaySound(tmp);
+ return;
+ }
+ }
+}
+
+// Update the password changing dialog
+void CmChangePasswordUpdate(HWND hWnd, CM_CHANGE_PASSWORD *p)
+{
+ bool ok = true;
+ char *s1, *s2;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsEmpty(hWnd, E_USERNAME))
+ {
+ ok = false;
+ }
+
+ s1 = GetTextA(hWnd, E_NEW_PASSWORD1);
+ s2 = GetTextA(hWnd, E_NEW_PASSWORD2);
+
+ if (StrCmp(s1, s2) != 0)
+ {
+ ok = false;
+ }
+
+ Free(s1);
+ Free(s2);
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Password changing dialog procedure
+UINT CmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_CHANGE_PASSWORD *p = (CM_CHANGE_PASSWORD *)param;
+ char username[MAX_USERNAME_LEN + 1];
+ char old_pass[MAX_PASSWORD_LEN + 1];
+ char new_pass[MAX_PASSWORD_LEN + 1];
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetTextA(hWnd, E_HUBNAME, p->HubName);
+ SetTextA(hWnd, E_USERNAME, p->Username);
+ FormatText(hWnd, S_TITLE, p->ClientOption->Hostname);
+
+ if (IsEmpty(hWnd, E_USERNAME))
+ {
+ FocusEx(hWnd, E_USERNAME);
+ }
+ else
+ {
+ FocusEx(hWnd, E_OLD_PASSWORD);
+ }
+
+ CmChangePasswordUpdate(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_USERNAME:
+ case E_OLD_PASSWORD:
+ case E_NEW_PASSWORD1:
+ case E_NEW_PASSWORD2:
+ CmChangePasswordUpdate(hWnd, p);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_USERNAME, username, sizeof(username));
+ GetTxtA(hWnd, E_OLD_PASSWORD, old_pass, sizeof(old_pass));
+ GetTxtA(hWnd, E_NEW_PASSWORD1, new_pass, sizeof(new_pass));
+
+ Disable(hWnd, E_USERNAME);
+ Disable(hWnd, E_OLD_PASSWORD);
+ Disable(hWnd, E_NEW_PASSWORD1);
+ Disable(hWnd, E_NEW_PASSWORD2);
+ Disable(hWnd, IDOK);
+ Disable(hWnd, IDCANCEL);
+
+ ret = ChangePassword(cm->Cedar, p->ClientOption, p->HubName, username, old_pass, new_pass);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_CHANGED"));
+ EndDialog(hWnd, true);
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _E(ret));
+ Enable(hWnd, E_USERNAME);
+ Enable(hWnd, E_OLD_PASSWORD);
+ Enable(hWnd, E_NEW_PASSWORD1);
+ Enable(hWnd, E_NEW_PASSWORD2);
+ Enable(hWnd, IDOK);
+ Enable(hWnd, IDCANCEL);
+
+ SetTextA(hWnd, E_OLD_PASSWORD, "");
+ SetTextA(hWnd, E_NEW_PASSWORD1, "");
+ SetTextA(hWnd, E_NEW_PASSWORD2, "");
+
+ Focus(hWnd, E_OLD_PASSWORD);
+ }
+
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ }
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the password changing dialog
+void CmChangePassword(HWND hWnd, CLIENT_OPTION *o, char *hubname, char *username)
+{
+ CM_CHANGE_PASSWORD p;
+ // Validate arguments
+ if (hWnd == NULL || o == NULL || hubname == NULL || username == NULL)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ StrCpy(p.Username, sizeof(p.Username), username);
+ StrCpy(p.HubName, sizeof(p.HubName), hubname);
+ p.ClientOption = o;
+
+ CmVoice("password");
+
+ Dialog(hWnd, D_CM_CHANGE_PASSWORD, CmChangePasswordProc, &p);
+}
+
+// Prohibit the installation of the virtual LAN card
+bool CmStopInstallVLan(HWND hWnd)
+{
+ if (cm->Client->Unix)
+ {
+ // There is no need to be prohibited if the client is an UNIX
+ return true;
+ }
+ if (cm->Client->Win9x)
+ {
+ // There is no need to prohibit if the client is a Win9x
+ return true;
+ }
+
+ return true;
+
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ if (MsGetCurrentTerminalSessionId() == 0)
+ {
+ // There is no need to prohibit
+ return true;
+ }
+ else
+ {
+ // Prohibit to install the device drivers since
+ // the user logged in other than the console session
+ wchar_t *user = MsGetSessionUserName(0);
+
+ if (user == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CM_STOP_INST_VLAN_2"),
+ MsIsTerminalServiceInstalled() ? _UU("CM_DESKTOP_MSG_LOCAL_TS") : _UU("CM_DESKTOP_MSG_LOCAL_SW"),
+ MsGetCurrentTerminalSessionId());
+ }
+ else
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CM_STOP_INST_VLAN_1"),
+ MsIsTerminalServiceInstalled() ? _UU("CM_DESKTOP_MSG_LOCAL_TS") : _UU("CM_DESKTOP_MSG_LOCAL_SW"),
+ MsGetCurrentTerminalSessionId(), 0, user);
+ }
+
+ if (user != NULL)
+ {
+ Free(user);
+ }
+ return false;
+ }
+ }
+ else
+ {
+ // There is no need to prohibit
+ return true;
+ }
+}
+
+// Desktop difference warning message dialog initialization
+void CmDesktopDlgInit(HWND hWnd, wchar_t *account_name)
+{
+ wchar_t tmp[2048];
+ bool remote = false;
+ bool user_switching = false;
+ bool console_active = false;
+ wchar_t *console_user = NULL;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ FormatText(hWnd, 0, account_name);
+ FormatText(hWnd, S_TITLE, account_name);
+ DlgFont(hWnd, S_TITLE, 11, true);
+ DlgFont(hWnd, S_INFO, 11, true);
+ if (cm->server_name == NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_DESKTOP_LOCAL_PC"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_REMOTE_PC"), cm->server_name);
+ }
+ FormatText(hWnd, S_WARNING, tmp);
+
+ if (cm->server_name != NULL)
+ {
+ remote = true;
+ }
+ else
+ {
+ if (MsIsTerminalServiceInstalled())
+ {
+ user_switching = false;
+ }
+ else
+ {
+ user_switching = true;
+ }
+
+ console_user = MsGetSessionUserName(0);
+
+ if (console_user == NULL)
+ {
+ console_active = false;
+ }
+ else
+ {
+ console_active = true;
+ }
+ }
+
+ // MSG1
+ if (remote == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_1"),
+ user_switching ? _UU("CM_DESKTOP_MSG_LOCAL_SW") : _UU("CM_DESKTOP_MSG_LOCAL_TS"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_1"),
+ cm->server_name);
+ }
+ SetText(hWnd, S_MSG_1, tmp);
+
+ // MSG2
+ if (remote == false)
+ {
+ if (console_active)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_21"),
+ console_user, MsGetCurrentTerminalSessionId());
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_22"),
+ MsGetCurrentTerminalSessionId());
+ }
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_2"), cm->server_name);
+ }
+ SetText(hWnd, S_MSG_2, tmp);
+
+ // MSG3
+ if (remote == false)
+ {
+ if (console_active)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_31"),
+ console_user, account_name);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_32"),
+ account_name);
+ }
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_3"), cm->server_name,
+ account_name);
+ }
+ SetText(hWnd, S_MSG_3, tmp);
+
+ if (console_user != NULL)
+ {
+ Free(console_user);
+ }
+}
+
+// Desktop difference warning message dialog
+UINT CmDesktopDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ wchar_t *account_name = (wchar_t *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmDesktopDlgInit(hWnd, account_name);
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog(hWnd, true);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show a warning message that the desktop is different, if necessary
+bool CmWarningDesktop(HWND hWnd, wchar_t *account_name)
+{
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return false;
+ }
+
+ if (cm->Client->Unix)
+ {
+ //There is no need for warning if the client is an UNIX
+ return true;
+ }
+
+ if (/*MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled() ||*/ (cm->server_name != NULL))
+ {
+ if (cm->server_name == NULL)
+ {
+ //if (MsGetCurrentTerminalSessionId() == 0)
+ {
+ // No need for warning
+ return true;
+ }
+ }
+ // There is a need for warning
+ return Dialog(hWnd, D_CM_DESKTOP, CmDesktopDlgProc, account_name);
+ }
+ else
+ {
+ // No need for warning
+ return true;
+ }
+}
+
+// Update the password setting dialog
+void CmPasswordRefresh(HWND hWnd)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, E_PASSWORD, IsChecked(hWnd, R_USE_PASSWORD));
+ SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_USE_PASSWORD));
+ SetEnable(hWnd, IDC_STATIC1, IsChecked(hWnd, R_USE_PASSWORD));
+ SetEnable(hWnd, IDC_STATIC2, IsChecked(hWnd, R_USE_PASSWORD));
+ SetEnable(hWnd, R_REMOTE_ONLY, IsChecked(hWnd, R_USE_PASSWORD));
+
+ if (IsChecked(hWnd, R_USE_PASSWORD))
+ {
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ if (IsEmpty(hWnd, E_PASSWORD))
+ {
+ ok = false;
+ }
+ GetTxtA(hWnd, E_PASSWORD, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+ if (StrCmp(tmp1, tmp2) != 0)
+ {
+ ok = false;
+ }
+ if (StrCmp(tmp1, HIDDEN_PASSWORD) == 0)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Password setting procedure
+UINT CmPasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ RPC_CLIENT_PASSWORD_SETTING c;
+ RPC_CLIENT_PASSWORD p;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Get the password setting
+ if (CALL(hWnd, CcGetPasswordSetting(cm->Client, &c)))
+ {
+ Check(hWnd, R_USE_PASSWORD, c.IsPasswordPresented);
+ if (c.IsPasswordPresented)
+ {
+ SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
+ SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);
+ FocusEx(hWnd, E_PASSWORD);
+ Check(hWnd, R_REMOTE_ONLY, c.PasswordRemoteOnly);
+ }
+ else
+ {
+ Focus(hWnd, R_USE_PASSWORD);
+ }
+ }
+ CmPasswordRefresh(hWnd);
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case R_USE_PASSWORD:
+ if (IsChecked(hWnd, R_USE_PASSWORD))
+ {
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ break;
+ case IDOK:
+ GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));
+ Zero(&p, sizeof(p));
+ if (IsChecked(hWnd, R_USE_PASSWORD))
+ {
+ StrCpy(p.Password, sizeof(p.Password), tmp);
+ p.PasswordRemoteOnly = IsChecked(hWnd, R_REMOTE_ONLY);
+ }
+
+ if (CALL(hWnd, CcSetPassword(cm->Client, &p)))
+ {
+ if (StrLen(p.Password) > 0)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_SET"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_REMOVE"));
+ }
+ EndDialog(hWnd, true);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ switch (LOWORD(wParam))
+ {
+ case R_USE_PASSWORD:
+ case R_REMOTE_ONLY:
+ case E_PASSWORD:
+ case E_PASSWORD2:
+ CmPasswordRefresh(hWnd);
+ break;
+ }
+ switch (wParam)
+ {
+ case R_REMOTE_ONLY:
+ case R_USE_PASSWORD:
+ if (IsChecked(hWnd, R_USE_PASSWORD))
+ {
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Set the password
+void CmPassword(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_CM_PASSWORD, CmPasswordProc, NULL);
+}
+
+// CA dialog update
+void CmTrustDlgUpdate(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, B_EXPORT, LvIsSelected(hWnd, L_CERT));
+ SetEnable(hWnd, B_DELETE, LvIsSelected(hWnd, L_CERT) && cm->CmSetting.LockMode == false);
+ SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_CERT));
+ SetEnable(hWnd, B_IMPORT, cm->CmSetting.LockMode == false);
+}
+
+// Update the list of certificates
+void CmTrustDlgRefresh(HWND hWnd)
+{
+ RPC_CLIENT_ENUM_CA c;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (CALL(hWnd, CcEnumCa(cm->Client, &c)))
+ {
+ UINT i;
+ LVB *b = LvInsertStart();
+ for (i = 0;i < c.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_CA_ITEM *cert = c.Items[i];
+ wchar_t tmp[MAX_SIZE];
+
+ GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(cert->Expires), NULL);
+ LvInsertAdd(b, ICO_CERT, (void *)cert->Key, 3,
+ cert->SubjectName, cert->IssuerName, tmp);
+ }
+ LvInsertEnd(b, hWnd, L_CERT);
+ CiFreeClientEnumCa(&c);
+ }
+
+ CmTrustDlgUpdate(hWnd);
+}
+
+// Import
+void CmTrustImport(HWND hWnd)
+{
+ X *x;
+ RPC_CERT c;
+ if (CmLoadXFromFileOrSecureCard(hWnd, &x) == false)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+ c.x = x;
+
+ CALL(hWnd, CcAddCa(cm->Client, &c));
+ CmVoice("new_cert");
+
+ FreeX(c.x);
+ CmTrustDlgRefresh(hWnd);
+}
+
+// Export
+void CmTrustExport(HWND hWnd)
+{
+ UINT key;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));
+ if (key != INFINITE)
+ {
+ RPC_GET_CA a;
+ Zero(&a, sizeof(a));
+ a.Key = key;
+
+ if (CALL(hWnd, CcGetCa(cm->Client, &a)))
+ {
+ wchar_t *name;
+ X *x = CloneX(a.x);
+ CiFreeGetCa(&a);
+
+ // Save
+ name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
+ if (name != NULL)
+ {
+ wchar_t str[MAX_SIZE];
+ UniStrCpy(str, sizeof(str), name);
+ if (XToFileW(x, str, true))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
+ }
+ Free(name);
+ }
+ FreeX(x);
+ }
+ }
+}
+
+// Display
+void CmTrustView(HWND hWnd)
+{
+ UINT key;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));
+ if (key != INFINITE)
+ {
+ RPC_GET_CA a;
+ Zero(&a, sizeof(a));
+ a.Key = key;
+
+ if (CALL(hWnd, CcGetCa(cm->Client, &a)))
+ {
+ X *x = CloneX(a.x);
+ X *x_issuer;
+ CiFreeGetCa(&a);
+
+ x_issuer = CmGetIssuer(x);
+ CertDlg(hWnd, x, x_issuer, true);
+ FreeX(x);
+ FreeX(x_issuer);
+ }
+ }
+}
+
+// CA dialog procedure
+UINT CmTrustDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ LvInit(hWnd, L_CERT);
+ LvInsertColumn(hWnd, L_CERT, 0, _UU("CM_CERT_COLUMN_1"), 190);
+ LvInsertColumn(hWnd, L_CERT, 1, _UU("CM_CERT_COLUMN_2"), 190);
+ LvInsertColumn(hWnd, L_CERT, 2, _UU("CM_CERT_COLUMN_3"), 160);
+ CmTrustDlgRefresh(hWnd);
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_IMPORT:
+ CmTrustImport(hWnd);
+ break;
+ case B_EXPORT:
+ CmTrustExport(hWnd);
+ break;
+ case B_DELETE:
+ index = LvGetSelected(hWnd, L_CERT);
+ if (index != INFINITE)
+ {
+ UINT key = (UINT)LvGetParam(hWnd, L_CERT, index);
+ if (key != INFINITE)
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_CERT_DELETE_MSG")) == IDYES)
+ {
+ RPC_CLIENT_DELETE_CA c;
+ Zero(&c, sizeof(c));
+ c.Key = key;
+ if (CALL(hWnd, CcDeleteCa(cm->Client, &c)))
+ {
+ CmTrustDlgRefresh(hWnd);
+ }
+ }
+ }
+ }
+ break;
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ CmTrustView(hWnd);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_CERT:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CmTrustDlgUpdate(hWnd);
+ break;
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, L_CERT);
+
+ return 0;
+}
+
+// Show the CA dialog
+void CmTrustDlg(HWND hWnd)
+{
+ Dialog(hWnd, D_CM_TRUST, CmTrustDlgProc, NULL);
+}
+
+// Main window procedure
+UINT CmMainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ static UINT taskbar_msg = 0;
+ COPYDATASTRUCT *cpy;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ if (taskbar_msg != 0 && msg == taskbar_msg)
+ {
+ // The task-bar is regenerated
+ if (cm->TrayInited)
+ {
+ MsRestoreIconOnTray();
+ }
+ }
+
+ // CmSetForegroundProcessToCnService();
+
+ switch (msg)
+ {
+ case WM_CM_SETTING_CHANGED_MESSAGE:
+ // CM_SETTING has changed
+ CmApplyCmSetting();
+ break;
+ case WM_INITDIALOG:
+ CmMainWindowOnInit(hWnd);
+ taskbar_msg = RegisterWindowMessage("TaskbarCreated");
+ CmEndStartupMutex();
+ break;
+ case WM_CM_SHOW:
+ // Received a display request from another process
+ if (cm->CmSetting.EasyMode == false)
+ {
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ }
+ else
+ {
+ if (cm->hEasyWnd == NULL)
+ {
+ CmShowEasy();
+ }
+ else
+ {
+ SetForegroundWindow(cm->hEasyWnd);
+ SetActiveWindow(cm->hEasyWnd);
+ }
+ }
+ break;
+ case WM_COMMAND:
+ CmMainWindowOnCommand(hWnd, wParam, lParam);
+ break;
+ case WM_SIZE:
+ CmMainWindowOnSize(hWnd);
+ break;
+ case WM_CLOSE:
+ if (cm->CmSetting.EasyMode == false)
+ {
+ CmShowOrHideWindow(hWnd);
+ }
+ else
+ {
+ if (cm->hEasyWnd == NULL)
+ {
+ CmShowEasy();
+ }
+ else
+ {
+ SetForegroundWindow(cm->hEasyWnd);
+ SetActiveWindow(cm->hEasyWnd);
+ }
+ }
+ return 1;
+ case WM_INITMENUPOPUP:
+ if (HIWORD(lParam) == false)
+ {
+ CmMainWindowOnPopupMenu(hWnd, (HMENU)wParam, LOWORD(lParam));
+ }
+ break;
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ if (n->idFrom == L_ACCOUNT && (n->code == LVN_BEGINLABELEDITW || n->code == LVN_BEGINLABELEDITA))
+ {
+ wchar_t *tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (tmp != NULL)
+ {
+ if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_LINK")) == 0
+ )
+ {
+ SendMsg(hWnd, L_ACCOUNT, LVM_CANCELEDITLABEL, 0, 0);
+ Free(tmp);
+ return true;
+ }
+ Free(tmp);
+ }
+ }
+ CmMainWindowOnNotify(hWnd, (NMHDR *)lParam);
+ break;
+ case WM_CM_NOTIFY:
+ CmRefreshVLanList(hWnd);
+ CmRefreshAccountList(hWnd);
+ CmRefreshStatusBar(hWnd);
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ CmSetForegroundProcessToCnService();
+ break;
+ case 2:
+ CmPollingTray(hWnd);
+ break;
+ case 3:
+ KillTimer(hWnd, 3);
+ Hide(hWnd, 0);
+ break;
+ case 4:
+ KillTimer(hWnd, 4);
+ CmMainWindowOnShowEasy(hWnd);
+ break;
+ case 6:
+ if (cm->Update == NULL)
+ {
+ if (cm->server_name == NULL)
+ {
+ if (CmGetNumConnected(hWnd) == 0)
+ {
+ cm->Update = InitUpdateUi(_UU("PRODUCT_NAME_VPN_CMGR"), NAME_OF_VPN_CLIENT_MANAGER, NULL,
+ GetCurrentBuildDate(), CEDAR_BUILD, CEDAR_VER, ((cm->Client == NULL) ? NULL : cm->Client->ClientId));
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_CM_TRAY_MESSAGE:
+ // Message from the icon in the task tray
+ CmMainWindowOnTrayClicked(hWnd, wParam, lParam);
+ break;
+ case WM_COPYDATA:
+ cpy = (COPYDATASTRUCT *)lParam;
+ if (cpy != NULL)
+ {
+ if (cpy->dwData == CM_IMPORT_FILENAME_MSG || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)
+ {
+ char *filename = (char *)cpy->lpData;
+
+ if (cm->CmSetting.LockMode == false || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)
+ {
+ wchar_t fullpath[MAX_PATH];
+
+ if (StrLen(filename) >= 2 && IsFileExists(filename))
+ {
+ StrToUni(fullpath, sizeof(fullpath), filename);
+ }
+ else
+ {
+ UniStrCpy(fullpath, sizeof(fullpath), (wchar_t *)filename);
+ }
+
+ CmImportAccountMainEx(cm->hEasyWnd ? cm->hEasyWnd : hWnd, fullpath, cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE);
+ }
+ else
+ {
+ MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_TOPMOST, _UU("CM_VPN_FILE_IMPORT_NG"));
+ }
+ }
+ }
+ break;
+ case WM_QUERYENDSESSION:
+ // Windows is about to terminate
+ cm->WindowsShutdowning = true;
+ CmSaveMainWindowPos(hWnd);
+ SleepThread(256);
+ break;
+ case WM_ENDSESSION:
+ // Windows has terminated
+ _exit(0);
+ break;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, L_ACCOUNT);
+ LvSortHander(hWnd, msg, wParam, lParam, L_VLAN);
+
+ return 0;
+}
+
+// Specify the notification service to the foreground process
+void CmSetForegroundProcessToCnService()
+{
+ if (cm->MenuPopuping)
+ {
+ return;
+ }
+ if (cm->server_name == NULL)
+ {
+ if (CnCheckAlreadyExists(false))
+ {
+ AllowFGWindow(MsRegReadInt(REG_CURRENT_USER,
+ CM_REG_KEY, "NotifyServerProcessId"));
+ }
+ }
+}
+
+// Show the [recent destination] sub-menu
+HMENU CmCreateRecentSubMenu(HWND hWnd, UINT start_id)
+{
+ HMENU h = NULL;
+ UINT i;
+ RPC_CLIENT_ENUM_ACCOUNT a;
+ LIST *o;
+ bool easy;
+
+ easy = cm->CmSetting.EasyMode;
+
+ Zero(&a, sizeof(a));
+
+ if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)
+ {
+ o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);
+
+ for (i = 0;i < a.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];
+
+ item->tmp1 = i;
+
+ if (item->LastConnectDateTime != 0)
+ {
+ Add(o, item);
+ }
+ }
+
+ Sort(o);
+
+ for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);
+ wchar_t tmp[MAX_PATH];
+ wchar_t *account_name;
+ char *server_name;
+ char *hub_name;
+ UINT pos;
+
+ if (h == NULL)
+ {
+ h = CreatePopupMenu();
+ }
+
+ account_name = item->AccountName;
+ server_name = item->ServerName;
+ hub_name = item->HubName;
+
+ UniStrCpy(tmp, sizeof(tmp), account_name);
+
+ pos = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);
+ if (pos != INFINITE)
+ {
+ MsAppendMenu(h, MF_STRING, start_id + pos, tmp);
+ }
+ }
+
+ ReleaseList(o);
+
+ CiFreeClientEnumAccount(&a);
+ }
+
+ return h;
+}
+
+// Show the sub-menu of the right-click menu in the task tray
+HMENU CmCreateTraySubMenu(HWND hWnd, bool flag, UINT start_id)
+{
+ HMENU h = NULL;
+ UINT i, num;
+ bool easy;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ easy = cm->CmSetting.EasyMode;
+
+ num = LvNum(hWnd, L_ACCOUNT);
+
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *status_str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+
+ if (status_str != NULL)
+ {
+ bool b = false;
+ bool is_account = false;
+
+ if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_OFFLINE")) == 0)
+ {
+ if (flag == false)
+ {
+ b = true;
+ }
+
+ is_account = true;
+ }
+
+ if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_ONLINE")) == 0 ||
+ UniStrCmpi(status_str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ if (flag == true)
+ {
+ b = true;
+ }
+
+ is_account = true;
+ }
+
+ if (b)
+ {
+ wchar_t tmp[MAX_PATH];
+ wchar_t *account_name, *server_name;
+ wchar_t *hub_name;
+ if (h == NULL)
+ {
+ h = CreatePopupMenu();
+ }
+
+ account_name = LvGetStr(hWnd, L_ACCOUNT, i, 0);
+ server_name = LvGetStr(hWnd, L_ACCOUNT, i, 2);
+ hub_name = LvGetStr(hWnd, L_ACCOUNT, i, 3);
+
+ if (easy == false)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s\t- %s [%s]", account_name, server_name, hub_name);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), account_name);
+ }
+
+ MsAppendMenu(h, MF_STRING, start_id + i, tmp);
+
+ Free(account_name);
+ Free(server_name);
+ Free(hub_name);
+ }
+
+ Free(status_str);
+ }
+ }
+
+ return h;
+}
+
+// Display the right-click menu of the task tray
+void CmShowTrayMenu(HWND hWnd)
+{
+ HMENU h;
+ POINT p;
+ HMENU sub1, sub2, sub3, sub4;
+ bool locked;
+ bool easy;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ cm->MenuPopuping = true;
+
+ locked = cm->CmSetting.LockMode;
+ easy = cm->CmSetting.EasyMode;
+
+ // Create a menu
+ h = CreatePopupMenu();
+
+ // Cancel
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, 100007, _UU("CM_TRAY_MENU_CANCEL"));
+
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10006, NULL);
+
+ if (locked == false && easy == false)
+ {
+ // Creating a new connection settings
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NEW, _UU("CM_TRAY_MENU_NEW"));
+
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10005, NULL);
+ }
+
+ // Connection menu
+ sub1 = CmCreateTraySubMenu(hWnd, false, CM_TRAY_MENU_CONNECT_ID_START);
+ if (sub1 != NULL)
+ {
+ MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
+ (UINT_PTR)sub1, _UU("CM_TRAY_MENU_CONNECT"));
+ }
+
+ // Disconnection menu
+ sub2 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_DISCONNECT_ID_START);
+ if (sub2 != NULL)
+ {
+ MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
+ (UINT_PTR)sub2, _UU("CM_TRAY_MENU_DISCONNECT"));
+ }
+
+ // Status Display menu
+ sub3 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_STATUS_ID_START);
+ if (sub3 != NULL)
+ {
+ MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
+ (UINT_PTR)sub3, _UU("CM_TRAY_MENU_STATUS"));
+ }
+
+ if (sub3 != NULL)
+ {
+ // Disconnect all connections
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_DISCONNECT_ALL, _UU("CM_TRAY_MENU_DISCONNECT_ALL"));
+ }
+
+ if (sub1 != NULL || sub2 != NULL || sub3 != NULL)
+ {
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10003, NULL);
+ }
+
+ // Connect to the recently connected VPN server
+ sub4 = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);
+ if (sub4 != NULL)
+ {
+ MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
+ (UINT_PTR)sub4, _UU("CM_TRAY_MENU_RECENT"));
+ MsAppendMenu(h, MF_SEPARATOR, 10008, NULL);
+ }
+
+ if (locked == false && easy == false)
+ {
+ // Communication throughput measurement
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAFFIC, _UU("CM_TRAY_MENU_TRAFFIC"));
+ }
+
+ if (easy == false)
+ {
+ // Network device status
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NETIF, _UU("CM_TRAY_MENU_NETIF"));
+ }
+
+ // Version information
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_ABOUT, _UU("CM_TRAY_MENU_ABOUT"));
+
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
+
+ // Change the operating mode
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_CM_SETTING, _UU("CM_TRAY_MENU_SETTING"));
+
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
+
+ // Hide the icon
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAYICON, _UU("CM_MENU@CMD_TRAYICON"));
+
+ // Separator
+ MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
+
+ // Show or hide
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_EXIT,
+ IsHide(hWnd, 0) ? _UU("CM_TRAY_MENU_1_SHOW") : _UU("CM_TRAY_MENU_1_HIDE"));
+
+ // Quit
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_QUIT, _UU("CM_TRAY_MENU_2_QUIT"));
+
+ // Show the menu
+ GetCursorPos(&p);
+
+ SetForegroundWindow(hWnd);
+ TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
+ PostMessage(hWnd, WM_NULL, 0, 0);
+
+ if (sub1 != NULL)
+ {
+ DestroyMenu(sub1);
+ }
+
+ if (sub2 != NULL)
+ {
+ DestroyMenu(sub2);
+ }
+
+ if (sub3 != NULL)
+ {
+ DestroyMenu(sub3);
+ }
+
+ DestroyMenu(h);
+
+ cm->MenuPopuping = false;
+}
+
+// Hide or show the main window
+void CmShowOrHideWindow(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsHide(hWnd, 0))
+ {
+ Show(hWnd, 0);
+ if (IsIconic(hWnd))
+ {
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ }
+ SetForegroundWindow(hWnd);
+ SetActiveWindow(hWnd);
+ }
+ else
+ {
+ CmSaveMainWindowPos(hWnd);
+ Hide(hWnd, 0);
+
+ if (cm->TrayInited == false)
+ {
+ Command(hWnd, CMD_QUIT);
+ return;
+ }
+ }
+}
+
+// Right-clicked on the account list
+void CmAccountListRightClick(HWND hWnd)
+{
+ HMENU h;
+ HMENU parent;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Load the menu
+ h = LoadSubMenu(M_MAIN, 0, &parent);
+ if (h == NULL)
+ {
+ return;
+ }
+
+ InitMenuInternational(h, "CM_MENU");
+
+ // Remove the shortcut key
+ RemoveShortcutKeyStrFromMenu(h);
+
+ // Delete the exit menu
+ i = GetMenuItemPos(h, CMD_QUIT);
+ if (i != INFINITE)
+ {
+ DeleteMenuItem(h, i);
+ DeleteMenuItem(h, i - 1);
+ DeleteMenuItem(h, i - 2);
+ DeleteMenuItem(h, i - 3);
+ }
+
+ // Set enable / disable
+ CmMainWindowOnPopupMenu(hWnd, h, INFINITE);
+
+ if (h != NULL)
+ {
+ // Determine whether the selected account is under connecting
+ UINT i = LvGetSelected(hWnd, L_ACCOUNT);
+ wchar_t *str;
+ bool is_connected = false;
+ if (i != INFINITE)
+ {
+ str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+ if (str != NULL)
+ {
+ if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ // Connecting
+ is_connected = true;
+ }
+ Free(str);
+ }
+ }
+
+ if (i == INFINITE)
+ {
+ // Bold the New menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW), true);
+ }
+ else
+ {
+ if (is_connected == false)
+ {
+ // Bold the connection menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_CONNECT), true);
+ }
+ else
+ {
+ // Bold the status menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_STATUS), true);
+ }
+ }
+ }
+
+ // Show the menu
+ PrintMenu(hWnd, h);
+
+ DestroyMenu(parent);
+}
+
+// Right-clicked on the virtual LAN card list
+void CmVLanListRightClick(HWND hWnd)
+{
+ HMENU h;
+ HMENU parent;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Load the menu
+ h = LoadSubMenu(M_MAIN, 3, &parent);
+ if (h == NULL)
+ {
+ return;
+ }
+
+ InitMenuInternational(h, "CM_MENU");
+
+ // Remove the shortcut key
+ RemoveShortcutKeyStrFromMenu(h);
+
+ // Set enable / disable
+ CmMainWindowOnPopupMenu(hWnd, h, INFINITE);
+
+ if (h != NULL)
+ {
+ // Examine whether the selected device is enabled
+ UINT i = LvGetSelected(hWnd, L_VLAN);
+ wchar_t *str;
+ bool is_active = false;
+ if (i != INFINITE)
+ {
+ str = LvGetStr(hWnd, L_VLAN, i, 1);
+ if (str != NULL)
+ {
+ if (UniStrCmpi(str, _UU("CM_VLAN_ENABLED")) == 0)
+ {
+ // Enabled
+ is_active = true;
+ }
+ Free(str);
+ }
+ }
+
+ if (i == INFINITE)
+ {
+ // Bold the New menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW_VLAN), true);
+ }
+ else
+ {
+ if (is_active == false)
+ {
+ // Bold the enable menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_ENABLE_VLAN), true);
+ }
+ else
+ {
+ // Bold the Windows Network Setup menu
+ SetMenuItemBold(h, GetMenuItemPos(h, CMD_WINNET), true);
+ }
+ }
+ }
+
+ // Show the menu
+ PrintMenu(hWnd, h);
+
+ DestroyMenu(parent);
+}
+
+// Notify to the main window
+void CmMainWindowOnNotify(HWND hWnd, NMHDR *n)
+{
+ bool item_vlan;
+ NMLVDISPINFOW *disp_info;
+ NMLVKEYDOWN *key;
+
+ // Validate arguments
+ if (hWnd == NULL || n == NULL)
+ {
+ return;
+ }
+
+ switch (n->idFrom)
+ {
+ case L_ACCOUNT:
+ case L_VLAN:
+ if (n->idFrom == L_ACCOUNT)
+ {
+ item_vlan = false;
+ }
+ else
+ {
+ item_vlan = true;
+ }
+
+ switch (n->code)
+ {
+ case NM_DBLCLK:
+ // Double click
+ CmOnKey(hWnd, false, false, VK_RETURN);
+ break;
+ case NM_RCLICK:
+ // Right click
+ if (item_vlan == false)
+ {
+ CmAccountListRightClick(hWnd);
+ }
+ else
+ {
+ CmVLanListRightClick(hWnd);
+ }
+ break;
+ case LVN_ENDLABELEDITW:
+ // Change the name
+ disp_info = (NMLVDISPINFOW *)n;
+ if (disp_info->item.pszText != NULL)
+ {
+ wchar_t *new_name = disp_info->item.pszText;
+ wchar_t *old_name = LvGetStr(hWnd, L_ACCOUNT, disp_info->item.iItem, 0);
+
+ if (old_name != NULL)
+ {
+ if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)
+ {
+ RPC_RENAME_ACCOUNT a;
+ Zero(&a, sizeof(a));
+ UniStrCpy(a.OldName, sizeof(a.OldName), old_name);
+ UniStrCpy(a.NewName, sizeof(a.NewName), new_name);
+ if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))
+ {
+ LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);
+ }
+ }
+
+ Free(old_name);
+ }
+ }
+ break;
+ case LVN_KEYDOWN:
+ // Key pressed
+ key = (NMLVKEYDOWN *)n;
+ if (key != NULL)
+ {
+ bool ctrl, alt;
+ UINT code = key->wVKey;
+ ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
+ alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
+ CmOnKey(hWnd, ctrl, alt, code);
+ }
+ break;
+ }
+ break;
+ }
+}
+
+// Keyboard pressed
+void CmOnKey(HWND hWnd, bool ctrl, bool alt, UINT key)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Single key
+ switch (key)
+ {
+ case VK_RETURN:
+ Command(hWnd, IDOK);
+ break;
+ case VK_DELETE:
+ // Delete
+ if (IsFocus(hWnd, L_ACCOUNT))
+ {
+ // Operation on the account list
+ Command(hWnd, CMD_DELETE);
+ }
+ else
+ {
+ // Operation on the virtual LAN card list
+ Command(hWnd, CMD_DELETE_VLAN);
+ }
+ break;
+ case VK_F2:
+ // Change the name
+ Command(hWnd, CMD_RENAME);
+ break;
+ case VK_F5:
+ // Update the status
+ Command(hWnd, CMD_REFRESH);
+ break;
+ }
+
+ if (alt)
+ {
+ switch (key)
+ {
+ case 'Q':
+ // Close
+ Command(hWnd, CMD_QUIT);
+ break;
+ }
+ }
+
+ if (ctrl)
+ {
+ switch (key)
+ {
+ case 'G':
+ // Smart Card Manager
+ Command(hWnd, CMD_SECURE_MANAGER);
+ break;
+ case 'S':
+ // Show the state
+ Command(hWnd, CMD_STATUS);
+ break;
+ case 'I':
+ // Disconnect all connections
+ Command(hWnd, CMD_DISCONNECT_ALL);
+ break;
+ case 'D':
+ // Disconnect
+ Command(hWnd, CMD_DISCONNECT);
+ break;
+ case 'N':
+ // Create a new connection settings
+ Command(hWnd, CMD_NEW);
+ break;
+ case 'C':
+ // Creating a copy
+ Command(hWnd, CMD_CLONE);
+ break;
+ case 'T':
+ // Set to start-up connection
+ Command(hWnd, CMD_STARTUP);
+ break;
+ case 'A':
+ // Select all
+ Command(hWnd, CMD_SELECT_ALL);
+ break;
+ case 'L':
+ // Create a new virtual LAN card
+ Command(hWnd, CMD_NEW_VLAN);
+ break;
+ case 'E':
+ // Enable the virtual LAN card
+ Command(hWnd, CMD_ENABLE_VLAN);
+ break;
+ case 'B':
+ // Disable the virtual LAN card
+ Command(hWnd, CMD_DISABLE_VLAN);
+ break;
+ case 'U':
+ // Reinstall the driver
+ Command(hWnd, CMD_REINSTALL);
+ break;
+ case 'W':
+ // Configure Windows network connection
+ Command(hWnd, CMD_WINNET);
+ break;
+ case 'P':
+ // Set the password
+ Command(hWnd, CMD_PASSWORD);
+ break;
+ case 'O':
+ // Option settings
+ Command(hWnd, CMD_TRAFFIC);
+ break;
+ case 'R':
+ // Certificate management
+ Command(hWnd, CMD_TRUST);
+ break;
+ case 'Q':
+ // Throughput
+ Command(hWnd, CMD_TRAFFIC);
+ break;
+ }
+ }
+}
+
+// Command of the main window
+void CmMainWindowOnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+ CmMainWindowOnCommandEx(hWnd, wParam, lParam, false);
+}
+void CmMainWindowOnCommandEx(HWND hWnd, WPARAM wParam, LPARAM lParam, bool easy)
+{
+ wchar_t *tmp;
+ char *name;
+ UINT index;
+ UINT id;
+ bool ctrl, alt;
+ UINT flag = 0;
+ // Validate arguments
+ wchar_t *selected_name = NULL;
+ UINT starter_id = 0;
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
+ alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
+
+ if (wParam == IDOK)
+ {
+ tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (tmp != NULL)
+ {
+ if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0)
+ {
+ Free(tmp);
+ Command(hWnd, CMD_NEW);
+ return;
+ }
+ if (UniStrCmpi(tmp, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_LINK")) == 0)
+ {
+ Free(tmp);
+ Command(hWnd, CMD_VGC_CONNECT);
+ return;
+ }
+ Free(tmp);
+ }
+ }
+
+ if (CmIsEnabled(hWnd, (UINT)wParam) == false)
+ {
+ return;
+ }
+
+ if (CM_TRAY_IS_CONNECT_ID(wParam))
+ {
+ // Connection request
+ starter_id = CM_TRAY_MENU_CONNECT_ID_START;
+ flag = 1;
+ }
+
+ if (CM_TRAY_IS_STATUS_ID(wParam))
+ {
+ // Information display request
+ starter_id = CM_TRAY_MENU_STATUS_ID_START;
+ flag = 2;
+ }
+
+ if (CM_TRAY_IS_DISCONNECT_ID(wParam))
+ {
+ // Disconnect request
+ starter_id = CM_TRAY_MENU_DISCONNECT_ID_START;
+ flag = 3;
+ }
+
+ if (CM_TRAY_IS_RECENT_ID(wParam))
+ {
+ // Recent destinations
+ starter_id = CM_TRAY_MENU_RECENT_ID_START;
+ flag = 1;
+ }
+
+ if (starter_id != 0)
+ {
+ UINT num;
+
+ id = (UINT)wParam - starter_id;
+
+ num = LvNum(hWnd, L_ACCOUNT);
+
+ if (id < num)
+ {
+ selected_name = LvGetStr(hWnd, L_ACCOUNT, id, 0);
+
+ if (selected_name != NULL)
+ {
+ if (UniStrCmpi(selected_name, _UU("CM_NEW_ICON")) != 0 &&
+ UniStrCmpi(selected_name, _UU("CM_VGC_ICON")) != 0 &&
+ UniStrCmpi(selected_name, _UU("CM_VGC_LINK")) != 0)
+ {
+ switch (flag)
+ {
+ case 1:
+ CmConnect(hWnd, selected_name);
+ break;
+
+ case 2:
+ CmStatus(hWnd, selected_name);
+ break;
+
+ case 3:
+ CmDisconnect(hWnd, selected_name);
+ break;
+ }
+ }
+ }
+
+ Free(selected_name);
+ }
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ case CMD_EASY_DBLCLICK:
+ // Property or connection
+ if (IsFocus(hWnd, L_ACCOUNT) || (hWnd == cm->hEasyWnd))
+ {
+ // Operation about the account list
+ if (alt == false)
+ {
+ UINT index = LvGetSelected(hWnd, L_ACCOUNT);
+ bool b = false;
+ if (index != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, index, 1);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ b = true;
+ }
+ Free(s);
+ }
+ }
+
+ if (b == false)
+ {
+ // Connection
+ Command(hWnd, CMD_CONNECT);
+ }
+ else
+ {
+ if (hWnd != cm->hEasyWnd || wParam == CMD_EASY_DBLCLICK)
+ {
+ // Display status
+ Command(hWnd, CMD_STATUS);
+ }
+ else
+ {
+ // Disconnect
+ Command(hWnd, CMD_DISCONNECT);
+ }
+ }
+ }
+ else
+ {
+ // Property
+ Command(hWnd, CMD_PROPERTY);
+ }
+ }
+ else
+ {
+ // Configure Windows network connection
+ Command(hWnd, CMD_WINNET);
+ }
+ break;
+ case CMD_CONNECT:
+ // Connection
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmConnect(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_STATUS:
+ // Show the status
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmStatus(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_DISCONNECT_ALL:
+ // Disconnect all connections
+ CmDisconnectAll(hWnd);
+ break;
+ case CMD_DISCONNECT:
+ // Disconnect
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmDisconnect(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_NEW:
+ // Create new
+ CmNewAccount(hWnd);
+ break;
+
+
+ case CMD_CLONE:
+ // Copy
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmCopyAccount(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_SHORTCUT:
+ // Create a shortcut
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmSortcut(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_EXPORT_ACCOUNT:
+ // Export settings
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmExportAccount(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_IMPORT_ACCOUNT:
+ // Import settings
+ CmImportAccount(hWnd);
+ break;
+ case CMD_STARTUP:
+ // Set to start-up connection
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT c;
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);
+ CALL(hWnd, CcSetStartupAccount(cm->Client, &c));
+ CmVoice("set_startup");
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_SET_STARTUP"), tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_NOSTARTUP:
+ // Unset the start-up connection
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("CM_REMOVE_STARTUP"), tmp) == IDYES)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT c;
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);
+ CALL(hWnd, CcRemoveStartupAccount(cm->Client, &c));
+ CmVoice("remove_startup");
+ }
+ Free(tmp);
+ }
+ break;
+ case CMD_DELETE:
+ // Delete
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmDeleteAccount(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case CMD_RENAME:
+ // Change the name
+ Focus(hWnd, L_ACCOUNT);
+ LvRename(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT));
+ break;
+ case CMD_PROPERTY:
+ // Property
+ tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
+ if (tmp != NULL)
+ {
+ CmEditAccount(hWnd, tmp);
+ Free(tmp);
+ }
+ break;
+ case IDCANCEL:
+ case CMD_EXIT:
+ // Close
+ Close(hWnd);
+ break;
+ case CMD_QUIT:
+ // Exit
+ CmMainWindowOnQuit(hWnd);
+ break;
+ case CMD_SELECT_ALL:
+ // Select all
+ LvSelectAll(hWnd, L_ACCOUNT);
+ LvSelectAll(hWnd, L_VLAN);
+ break;
+ case CMD_SWITCH_SELECT:
+ // Invert selection
+ LvSwitchSelect(hWnd, L_ACCOUNT);
+ LvSwitchSelect(hWnd, L_VLAN);
+ break;
+ case CMD_GRID:
+ // Show grid
+ cm->ShowGrid = !cm->ShowGrid;
+ CmRefreshVLanListEx(hWnd, true);
+ CmRefreshAccountListEx2(hWnd, false, true);
+ break;
+ case CMD_STATUSBAR:
+ // Show the status bar
+ if (cm->HideStatusBar == false)
+ {
+ cm->HideStatusBar = true;
+ Hide(hWnd, S_STATUSBAR);
+ CmMainWindowOnSize(hWnd);
+ }
+ else
+ {
+ cm->HideStatusBar = false;
+ Show(hWnd, S_STATUSBAR);
+ CmMainWindowOnSize(hWnd);
+ }
+ CmSaveMainWindowPos(hWnd);
+ break;
+ case CMD_VISTASTYLE:
+ cm->VistaStyle = !cm->VistaStyle;
+ CmRefreshEx(hWnd, true);
+ CmSaveMainWindowPos(hWnd);
+ break;
+ case CMD_TRAYICON:
+ // Tray icon display
+ if (cm->HideTrayIcon == false)
+ {
+ cm->HideTrayIcon = true;
+ CmFreeTray(hWnd);
+
+ if (IsHide(hWnd, 0))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TRAY_ICON_RESTORE"));
+ }
+ }
+ else
+ {
+ cm->HideTrayIcon = false;
+ if (cm->server_name == NULL)
+ {
+ CmInitTray(hWnd);
+ }
+ }
+ break;
+ case CMD_SHOWPORT:
+ // Show the port number
+ cm->ShowPort = !cm->ShowPort;
+ CmRefresh(hWnd);
+ break;
+ case CMD_ICON:
+ // Show the icon
+ if (cm->IconView == false)
+ {
+ cm->IconView = true;
+ CmRefresh(hWnd);
+ }
+ break;
+ case CMD_DETAIL:
+ // Show details
+ if (cm->IconView)
+ {
+ cm->IconView = false;
+ CmRefresh(hWnd);
+ }
+ break;
+ case CMD_REFRESH:
+ if (easy == false)
+ {
+ // Display update
+ LvReset(hWnd, L_ACCOUNT);
+ LvReset(hWnd, L_VLAN);
+ CmRefresh(hWnd);
+ }
+ break;
+ case CMD_NEW_VLAN:
+ // Create a Virtual LAN card
+ if (CmStopInstallVLan(hWnd) == false)
+ {
+ // Installation is prohibited
+ break;
+ }
+ name = CmNewVLanDlg(hWnd);
+ if (name != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ void *helper = NULL;
+ RPC_CLIENT_CREATE_VLAN c;
+ Zero(&c, sizeof(c));
+ StrCpy(c.DeviceName, sizeof(c.DeviceName), name);
+ if (MsIsNt() == false)
+ {
+ // Change the title of the window
+ GetTxt(hWnd, 0, tmp, sizeof(tmp));
+ SetText(hWnd, 0, _UU("CM_VLAN_INSTALLING"));
+ }
+ // Minimize
+ if (MsIsVista() == false)
+ {
+ ShowWindow(hWnd, SW_SHOWMINIMIZED);
+ }
+
+ if (MsIsVista())
+ {
+ helper = CmStartUacHelper();
+ }
+
+ if (CALL(hWnd, CcCreateVLan(cm->Client, &c)))
+ {
+ CmVoice("new_vlan");
+ }
+
+ CmStopUacHelper(helper);
+
+ if (MsIsNt() == false)
+ {
+ // Restore the title of the window
+ SetText(hWnd, 0, tmp);
+ }
+ // Restore
+ if (MsIsVista() == false)
+ {
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ }
+ Free(name);
+ }
+ break;
+ case CMD_DELETE_VLAN:
+ // Delete the Virtual LAN card
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index != INFINITE)
+ {
+ if (cm->Client->Win9x == false)
+ {
+ // Windows 2000 or later
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
+ if (s != NULL)
+ {
+ RPC_CLIENT_CREATE_VLAN c;
+ char str[MAX_SIZE];
+ CmVoice("delete_vlan_1");
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_VLAN"), s) == IDYES)
+ {
+ Zero(&c, sizeof(c));
+ UniToStr(str, sizeof(str), s);
+ if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
+ {
+ if (CALL(hWnd, CcDeleteVLan(cm->Client, &c)))
+ {
+ CmVoice("delete_vlan_2");
+ }
+ }
+ }
+ Free(s);
+ }
+ }
+ else
+ {
+ // Windows 9x
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_9X_VLAN_UNINSTALL")) == IDYES)
+ {
+ Run("rundll32.exe", "shell32.dll,Control_RunDLL NETCPL.CPL",
+ false, false);
+ }
+ }
+ }
+ break;
+ case CMD_ENABLE_VLAN:
+ // Enable the virtual LAN card
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
+ if (s != NULL)
+ {
+ RPC_CLIENT_CREATE_VLAN c;
+ char str[MAX_SIZE];
+ Zero(&c, sizeof(c));
+ UniToStr(str, sizeof(str), s);
+ if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
+ {
+ CALL(hWnd, CcEnableVLan(cm->Client, &c));
+ }
+ Free(s);
+ }
+ }
+ break;
+ case CMD_DISABLE_VLAN:
+ // Disable the virtual LAN card
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
+ if (s != NULL)
+ {
+ RPC_CLIENT_CREATE_VLAN c;
+ char str[MAX_SIZE];
+ Zero(&c, sizeof(c));
+ UniToStr(str, sizeof(str), s);
+ if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
+ {
+ CALL(hWnd, CcDisableVLan(cm->Client, &c));
+ }
+ Free(s);
+ }
+ }
+ break;
+ case CMD_REINSTALL:
+ // Reinstall the virtual LAN card
+ if (CmStopInstallVLan(hWnd) == false)
+ {
+ // Installation is prohibited
+ break;
+ }
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
+ if (s != NULL)
+ {
+ RPC_CLIENT_CREATE_VLAN c;
+ char str[MAX_SIZE];
+ Zero(&c, sizeof(c));
+ UniToStr(str, sizeof(str), s);
+ if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
+ {
+ void *helper = NULL;
+
+ if (MsIsVista() == false)
+ {
+ ShowWindow(hWnd, SW_SHOWMINIMIZED);
+ }
+
+ if (MsIsVista())
+ {
+ helper = CmStartUacHelper();
+ }
+
+ CALL(hWnd, CcUpgradeVLan(cm->Client, &c));
+
+ CmStopUacHelper(helper);
+
+ if (MsIsVista() == false)
+ {
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ }
+ }
+ Free(s);
+ }
+ }
+ break;
+ case CMD_PASSWORD:
+ // Password setting
+ CmPassword(hWnd);
+ break;
+ case CMD_OPTION:
+ // Option
+ CmConfigDlg(hWnd);
+ break;
+ case CMD_LANGUAGE:
+ // Language settings
+ if (true)
+ {
+ wchar_t path[MAX_SIZE];
+
+ CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"vpnsetup.exe");
+
+ if (MsExecuteW(path, L"/language:yes") == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
+ }
+ }
+ break;
+ case CMD_TRUST:
+ // Certificate management
+ CmTrustDlg(hWnd);
+ break;
+ case CMD_ABOUT:
+ // Version information
+ if (IsEnable(hWnd, 0))
+ {
+ AboutEx(hWnd, cm->Cedar, _UU("PRODUCT_NAME_VPN_CMGR"), cm->Update);
+ }
+ break;
+ case CMD_VOIDE_NONE:
+ cm->DisableVoice = true;
+ break;
+ case CMD_VOICE_NORMAL:
+ cm->DisableVoice = false;
+ cm->VoiceId = VOICE_SSK;
+ break;
+ case CMD_VOICE_ODD:
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_EXT_VOICE_MSG")) == IDYES)
+ {
+ cm->DisableVoice = false;
+ cm->VoiceId = VOICE_AHO;
+ }
+ break;
+ case CMD_SECURE_MANAGER:
+ // Smart Card Manager
+ CmClientSecureManager(hWnd);
+ break;
+ case CMD_SECURE_SELECT:
+ // Select a smart card
+ CmClientSelectSecure(hWnd);
+ break;
+ case CMD_NETIF:
+ // State of the network device
+ if (IsEnable(hWnd, 0))
+ {
+ UtSpeedMeterEx(hWnd);
+ }
+ break;
+ case CMD_MMCSS:
+ // Optimization utility for Windows Vista
+ if (MsIsVista() == false)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_4"));
+ }
+ else
+ {
+ if (MsIsAdmin() == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("VISTA_MMCSS_MSG_4"));
+ }
+ else
+ {
+ if (MsIsMMCSSNetworkThrottlingEnabled())
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("VISTA_MMCSS_MSG")) == IDYES)
+ {
+ MsSetMMCSSNetworkThrottlingEnable(false);
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_5"));
+ }
+ }
+ else
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("VISTA_MMCSS_MSG_2")) == IDYES)
+ {
+ MsSetMMCSSNetworkThrottlingEnable(true);
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_6"));
+ }
+ }
+ }
+ }
+ break;
+ case CMD_TRAFFIC:
+ // Communication traffic measurement
+ if (IsEnable(hWnd, 0))
+ {
+ CmTraffic(hWnd);
+ }
+ break;
+ case CMD_CM_SETTING:
+ // Operation mode setting
+ if (IsEnable(hWnd, 0))
+ {
+ if (CmSetting(hWnd))
+ {
+ CmApplyCmSetting();
+ }
+ }
+ break;
+ case CMD_WINNET:
+ // Windows network settings
+ ShowWindowsNetworkConnectionDialog();
+ break;
+ }
+}
+
+// Option dialog
+void CmConfigDlg(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_CM_CONFIG, CmConfigDlgProc, NULL);
+}
+
+// Initialize the option dialog
+void CmConfigDlgInit(HWND hWnd)
+{
+ bool use_alpha;
+ UINT alpha_value;
+ UINT os;
+ CLIENT_CONFIG c;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ DlgFont(hWnd, S_WARNING, 10, true);
+ DlgFont(hWnd, S_INFO, 10, false);
+
+ Zero(&c, sizeof(c));
+ if (CALL(hWnd, CcGetClientConfig(cm->Client, &c)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ Check(hWnd, R_ALLOW_REMOTE_CONFIG, c.AllowRemoteConfig);
+
+ Check(hWnd, R_USE_KEEP_CONNECT, c.UseKeepConnect);
+ SetTextA(hWnd, E_HOSTNAME, c.KeepConnectHost);
+ SetIntEx(hWnd, E_PORT, c.KeepConnectPort);
+ SetIntEx(hWnd, E_INTERVAL, c.KeepConnectInterval);
+
+ Check(hWnd, R_TCP, c.KeepConnectProtocol == CONNECTION_TCP);
+ Check(hWnd, R_UDP, c.KeepConnectProtocol == CONNECTION_UDP);
+
+ use_alpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha") == 0 ? false : true;
+ alpha_value = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");
+ alpha_value = MAKESURE(alpha_value, 0, 100);
+
+ SetInt(hWnd, E_ALPHA_VALUE, alpha_value == 0 ? 50 : alpha_value);
+ Check(hWnd, R_ALPHA, use_alpha);
+
+ os = GetOsInfo()->OsType;
+ if (OS_IS_WINDOWS_NT(os) && GET_KETA(os, 100) >= 2)
+ {
+ Enable(hWnd, R_ALPHA);
+ }
+ else
+ {
+ Disable(hWnd, R_ALPHA);
+ }
+
+ CmConfigDlgRefresh(hWnd);
+}
+
+// Update the option dialog
+void CmConfigDlgRefresh(HWND hWnd)
+{
+ bool ok = true;
+ bool use_keep_connect;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ use_keep_connect = IsChecked(hWnd, R_USE_KEEP_CONNECT);
+ SetEnable(hWnd, S_HOSTNAME, use_keep_connect);
+ SetEnable(hWnd, S_PORT, use_keep_connect);
+ SetEnable(hWnd, S_INTERVAL, use_keep_connect);
+ SetEnable(hWnd, S_INTERVAL2, use_keep_connect);
+ SetEnable(hWnd, S_PROTOCOL, use_keep_connect);
+ SetEnable(hWnd, S_INFO, use_keep_connect);
+ SetEnable(hWnd, S_INFO2, use_keep_connect);
+ SetEnable(hWnd, E_HOSTNAME, use_keep_connect);
+ SetEnable(hWnd, E_PORT, use_keep_connect);
+ SetEnable(hWnd, E_INTERVAL, use_keep_connect);
+ SetEnable(hWnd, R_TCP, use_keep_connect);
+ SetEnable(hWnd, R_UDP, use_keep_connect);
+
+ SetEnable(hWnd, S_WARNING, IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG));
+
+ if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
+ {
+ if (IsEmpty(hWnd, E_HOSTNAME))
+ {
+ ok = false;
+ }
+ if (IsChecked(hWnd, R_TCP) == false && IsChecked(hWnd, R_UDP) == false)
+ {
+ ok = false;
+ }
+ if (GetInt(hWnd, E_PORT) == 0 || GetInt(hWnd, E_PORT) >= 65536)
+ {
+ ok = false;
+ }
+ if (GetInt(hWnd, E_INTERVAL) == 0)
+ {
+ ok = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_ALPHA))
+ {
+ UINT i = GetInt(hWnd, E_ALPHA_VALUE);
+ if (i < 20 || i >= 100)
+ {
+ ok = false;
+ }
+ Enable(hWnd, E_ALPHA_VALUE);
+ }
+ else
+ {
+ Disable(hWnd, E_ALPHA_VALUE);
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Save the setting of the option dialog
+void CmConfigDlgOnOk(HWND hWnd)
+{
+ CLIENT_CONFIG c;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+ c.AllowRemoteConfig = IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG);
+ c.UseKeepConnect = IsChecked(hWnd, R_USE_KEEP_CONNECT);
+ GetTxtA(hWnd, E_HOSTNAME, c.KeepConnectHost, sizeof(c.KeepConnectHost));
+ c.KeepConnectPort = GetInt(hWnd, E_PORT);
+ c.KeepConnectInterval = GetInt(hWnd, E_INTERVAL);
+ if (IsChecked(hWnd, R_TCP))
+ {
+ c.KeepConnectProtocol = CONNECTION_TCP;
+ }
+ else if (IsChecked(hWnd, R_UDP))
+ {
+ c.KeepConnectProtocol = CONNECTION_UDP;
+ }
+ else
+ {
+ return;
+ }
+
+ if (c.UseKeepConnect)
+ {
+ if (c.KeepConnectInterval < KEEP_INTERVAL_MIN || c.KeepConnectInterval > KEEP_INTERVAL_MAX)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_KEEP_INTERVAL_MSG"),
+ KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);
+ FocusEx(hWnd, E_INTERVAL);
+ return;
+ }
+ }
+
+ if (CALL(hWnd, CcSetClientConfig(cm->Client, &c)) == false)
+ {
+ return;
+ }
+
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue", GetInt(hWnd, E_ALPHA_VALUE));
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha", IsChecked(hWnd, R_ALPHA));
+
+ EndDialog(hWnd, true);
+}
+
+// Option setting dialog procedure
+UINT CmConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmConfigDlgInit(hWnd);
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_ALLOW_REMOTE_CONFIG:
+ case R_USE_KEEP_CONNECT:
+ case E_HOSTNAME:
+ case E_PORT:
+ case E_INTERVAL:
+ case R_ALPHA:
+ case E_ALPHA_VALUE:
+ CmConfigDlgRefresh(hWnd);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ CmConfigDlgRefresh(hWnd);
+ CmConfigDlgOnOk(hWnd);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case R_ALLOW_REMOTE_CONFIG:
+ if (IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG) == false)
+ {
+ if (cm->server_name != NULL)
+ {
+ // If the current user is remotely connected, show a warning
+ // when the user choose to disable the remote management
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_DEFBUTTON2 | MB_YESNO, _UU("CM_REMOTE_WARNING"),
+ cm->server_name, cm->server_name) == IDNO)
+ {
+ Check(hWnd, R_ALLOW_REMOTE_CONFIG, true);
+ }
+ }
+ }
+ break;
+ case R_USE_KEEP_CONNECT:
+ if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
+ {
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+ break;
+ case R_ALPHA:
+ if (IsChecked(hWnd, R_ALPHA))
+ {
+ FocusEx(hWnd, E_ALPHA_VALUE);
+ }
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Create a shortcut
+void CmSortcut(HWND hWnd, wchar_t *account_name)
+{
+ wchar_t tmp[MAX_SIZE];
+ CM_ACCOUNT *a;
+ wchar_t *filename;
+ UCHAR key[SHA1_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ // Get the account information
+ a = CmGetExistAccountObject(hWnd, account_name);
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Copy(key, a->ShortcutKey, SHA1_SIZE);
+
+ if (IsZero(key, SHA1_SIZE))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));
+ }
+ else
+ {
+ // Determine the file name
+ UniFormat(tmp, sizeof(tmp), L"%s.lnk", account_name);
+ UniSafeFileName(tmp);
+
+ filename = SaveDlg(hWnd, _UU("CM_SHORTCUT_FILE"),
+ _UU("CM_SHORTCUT_SAVE_TITLE"), tmp, L".vpn");
+
+ if (filename != NULL)
+ {
+ char key_str[64];
+ wchar_t target[MAX_PATH];
+ wchar_t workdir[MAX_PATH];
+ wchar_t args[MAX_PATH];
+ wchar_t comment[MAX_SIZE];
+ wchar_t icon[MAX_PATH];
+
+ BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);
+
+ // Create a shortcut
+ UniStrCpy(target, sizeof(target), MsGetExeFileNameW());
+ UniStrCpy(workdir, sizeof(workdir), MsGetExeDirNameW());
+ StrToUni(args, sizeof(args), key_str);
+ UniFormat(comment, sizeof(comment), _UU("CM_SHORTCUT_COMMENT"), account_name);
+ UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());
+
+ if (CreateLink(filename, target, workdir, args, comment, icon, 1) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("CM_SHORTCUT_ERROR"));
+ }
+
+ Free(filename);
+ }
+ }
+
+ CmFreeAccountObject(hWnd, a);
+}
+
+// Export the account
+void CmExportAccount(HWND hWnd, wchar_t *account_name)
+{
+ wchar_t tmp[MAX_SIZE];
+ CM_ACCOUNT *a;
+ wchar_t *filename;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ // Get the account information
+ a = CmGetExistAccountObject(hWnd, account_name);
+ if (a == NULL)
+ {
+ return;
+ }
+
+ // Determine the file name
+ UniFormat(tmp, sizeof(tmp), L"%s.vpn", account_name);
+ UniSafeFileName(tmp);
+
+ filename = SaveDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"),
+ _UU("CM_ACCOUNT_SAVE_TITLE"), tmp, L".vpn");
+
+ if (filename != NULL)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT t;
+ BUF *b;
+ BUF *b2;
+ wchar_t tmp[MAX_SIZE];
+ UCHAR *buf;
+ UINT buf_size;
+ UCHAR bom[] = {0xef, 0xbb, 0xbf, };
+
+ Zero(&t, sizeof(t));
+ t.ClientOption = a->ClientOption;
+ t.ClientAuth = a->ClientAuth;
+ t.StartupAccount = a->Startup;
+ t.CheckServerCert = a->CheckServerCert;
+ t.ServerCert = a->ServerCert;
+ t.ClientOption->FromAdminPack = false;
+
+ b = CiAccountToCfg(&t);
+
+ SeekBuf(b, 0, 0);
+
+ // Check whether the password is contained
+ if (CiHasAccountSensitiveInformation(b))
+ {
+ SeekBuf(b, 0, 0);
+
+ // Confirm that the user want to clear the password
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONQUESTION, _UU("CM_ACCOUNT_MSG_SENSITIVE")) == IDYES)
+ {
+ // Erase
+ CiEraseSensitiveInAccount(b);
+ }
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ b2 = NewBuf();
+
+ WriteBuf(b2, bom, sizeof(bom));
+
+ // Add a header part
+ buf_size = CalcUniToUtf8(_UU("CM_ACCOUNT_FILE_BANNER"));
+ buf = ZeroMalloc(buf_size + 32);
+ UniToUtf8(buf, buf_size, _UU("CM_ACCOUNT_FILE_BANNER"));
+
+ WriteBuf(b2, buf, StrLen((char *)buf));
+ WriteBuf(b2, b->Buf, b->Size);
+ SeekBuf(b2, 0, 0);
+
+ FreeBuf(b);
+
+ if (DumpBufW(b2, tmp) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_SAVE_FILE"));
+ }
+
+ Free(filename);
+ FreeBuf(b2);
+ Free(buf);
+ }
+
+ CmFreeAccountObject(hWnd, a);
+}
+
+// Main process of importing account
+void CmImportAccountMain(HWND hWnd, wchar_t *filename)
+{
+ CmImportAccountMainEx(hWnd, filename, false);
+}
+void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite)
+{
+ wchar_t name[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ BUF *b;
+ RPC_CLIENT_CREATE_ACCOUNT *t;
+ // Validate arguments
+ if (hWnd == NULL || filename == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), filename);
+
+ b = ReadDumpW(tmp);
+ if (b == NULL)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_OPEN_FILE"));
+ return;
+ }
+
+ t = CiCfgToAccount(b);
+ if (t == NULL)
+ {
+ FreeBuf(b);
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED"));
+ return;
+ }
+
+ if (overwrite)
+ {
+ // If the same name already exists, remove it
+ if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->ClientOption->AccountName) != INFINITE)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT d;
+ RPC_CLIENT_GET_ACCOUNT get;
+ HWND h = cm->hEasyWnd == NULL ? hWnd : cm->hEasyWnd;
+
+ Zero(&d, sizeof(d));
+ UniStrCpy(d.AccountName, sizeof(d.AccountName), t->ClientOption->AccountName);
+
+ Zero(&get, sizeof(get));
+ UniStrCpy(get.AccountName, sizeof(get.AccountName), t->ClientOption->AccountName);
+ if (CcGetAccount(cm->Client, &get) == ERR_NO_ERROR)
+ {
+ // Inherit the information of some of the client option by getting
+ // the account information of the same name that already exists
+ if (get.ClientOption != NULL && get.ClientAuth != NULL)
+ {
+ CLIENT_OPTION *old_option = get.ClientOption;
+ CLIENT_AUTH *old_auth = get.ClientAuth;
+
+ // Inherit the connection parameters
+ t->ClientOption->ProxyType = old_option->ProxyType;
+ StrCpy(t->ClientOption->ProxyName, sizeof(t->ClientOption->ProxyName),
+ old_option->ProxyName);
+ t->ClientOption->ProxyPort = old_option->ProxyPort;
+ StrCpy(t->ClientOption->ProxyUsername, sizeof(t->ClientOption->ProxyUsername),
+ old_option->ProxyUsername);
+ StrCpy(t->ClientOption->ProxyPassword, sizeof(t->ClientOption->ProxyPassword),
+ old_option->ProxyPassword);
+ t->ClientOption->NumRetry = old_option->NumRetry;
+ t->ClientOption->RetryInterval = old_option->RetryInterval;
+ t->ClientOption->MaxConnection = old_option->MaxConnection;
+ t->ClientOption->UseEncrypt = old_option->UseEncrypt;
+ t->ClientOption->UseCompress = old_option->UseCompress;
+ t->ClientOption->HalfConnection = old_option->HalfConnection;
+ t->ClientOption->NoRoutingTracking = old_option->NoRoutingTracking;
+ StrCpy(t->ClientOption->DeviceName, sizeof(t->ClientOption->DeviceName),
+ old_option->DeviceName);
+ t->ClientOption->AdditionalConnectionInterval = old_option->AdditionalConnectionInterval;
+ t->ClientOption->ConnectionDisconnectSpan = old_option->ConnectionDisconnectSpan;
+ t->ClientOption->HideStatusWindow = old_option->HideStatusWindow;
+ t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode;
+ t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode;
+ t->ClientOption->DisableQoS = old_option->DisableQoS;
+ t->ClientOption->NoTls1 = old_option->NoTls1;
+
+ // Inherit the authentication data
+ CiFreeClientAuth(t->ClientAuth);
+ t->ClientAuth = CopyClientAuth(old_auth);
+
+ // Other Settings
+ t->StartupAccount = get.StartupAccount;
+ t->CheckServerCert = get.CheckServerCert;
+ if (t->ServerCert != NULL)
+ {
+ FreeX(t->ServerCert);
+ }
+ t->ServerCert = NULL;
+ if (get.ServerCert != NULL)
+ {
+ t->ServerCert = CloneX(get.ServerCert);
+ }
+ Copy(t->ShortcutKey, get.ShortcutKey, sizeof(t->ShortcutKey));
+ }
+
+ CiFreeClientGetAccount(&get);
+ }
+
+ if (CALL(h, CcDeleteAccount(cm->Client, &d)) == false)
+ {
+ CiFreeClientCreateAccount(t);
+ Free(t);
+ return;
+ }
+
+ CmRefreshAccountList(hWnd);
+ }
+ }
+
+ CmGenerateImportName(hWnd, name, sizeof(name), t->ClientOption->AccountName);
+ UniStrCpy(t->ClientOption->AccountName, sizeof(t->ClientOption->AccountName), name);
+
+ if (overwrite)
+ {
+ t->ClientOption->FromAdminPack = true;
+ }
+
+ CALL(hWnd, CcCreateAccount(cm->Client, t));
+
+ CiFreeClientCreateAccount(t);
+ Free(t);
+
+ FreeBuf(b);
+
+ if (overwrite)
+ {
+ // Start to connect the VPN
+ CmConnect(hWnd, name);
+ }
+
+ //MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_IMPORT_MESSAGE"), filename, name);
+}
+
+// Import an account
+void CmImportAccount(HWND hWnd)
+{
+ wchar_t *filename;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Open the file
+ filename = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE"));
+ if (filename == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ Free(filename);
+
+ CmImportAccountMain(hWnd, tmp);
+}
+
+// Create a copy of the account
+void CmCopyAccount(HWND hWnd, wchar_t *account_name)
+{
+ wchar_t tmp[MAX_SIZE];
+ CM_ACCOUNT *a;
+ RPC_CLIENT_CREATE_ACCOUNT c;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ CmGenerateCopyName(hWnd, tmp, sizeof(tmp), account_name);
+
+ // Get an account information
+ a = CmGetExistAccountObject(hWnd, account_name);
+ if (a == NULL)
+ {
+ return;
+ }
+
+ // Change the account name
+ UniStrCpy(a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName), tmp);
+
+ // Write
+ Zero(&c, sizeof(c));
+ c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+ c.ClientAuth = CopyClientAuth(a->ClientAuth);
+ if (a->ServerCert)
+ {
+ c.ServerCert = CloneX(a->ServerCert);
+ }
+ c.CheckServerCert = a->CheckServerCert;
+ c.StartupAccount = false; // Don't copy the startup attribute
+
+ CALL(hWnd, CcCreateAccount(cm->Client, &c));
+ CiFreeClientCreateAccount(&c);
+
+ CmFreeAccountObject(hWnd, a);
+}
+
+// Update the Virtual LAN Card Name dialog
+void CmNewVLanDlgUpdate(HWND hWnd)
+{
+ bool ok = true;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_NAME, tmp, sizeof(tmp));
+ if (IsSafeStr(tmp) == false)
+ {
+ ok = false;
+ }
+ if (SearchStrEx(tmp, " ", 0, false) != INFINITE)
+ {
+ ok = false;
+ }
+
+ Trim(tmp);
+ if (StrLen(tmp) == 0)
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Virtual LAN card name decision dialog procedure
+UINT CmNewVLanDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ char *tmp = (char *)param;
+ char default_name[MAX_SIZE];
+ RPC_CLIENT_VERSION ver;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ LimitText(hWnd, E_NAME, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);
+ FormatText(hWnd, S_INFO, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);
+
+ Zero(&ver, sizeof(ver));
+
+ if (CcGetClientVersion(cm->Client, &ver) == ERR_NO_ERROR)
+ {
+ if (ver.IsVLanNameRegulated)
+ {
+ Show(hWnd, S_WIN8);
+ }
+ }
+
+ if (CiGetNextRecommendedVLanName(cm->Client, default_name, sizeof(default_name)))
+ {
+ // Show a default virtual LAN card name candidate
+ SetTextA(hWnd, E_NAME, default_name);
+ }
+
+ CmNewVLanDlgUpdate(hWnd);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (cm->Client->Win9x)
+ {
+ // For Windows 9x, show a confirmation message
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_OKCANCEL, _UU("CM_9X_VLAN_INSTALL")) == IDCANCEL)
+ {
+ break;
+ }
+ }
+ GetTxtA(hWnd, E_NAME, tmp, (cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN) + 1);
+ Trim(tmp);
+
+ if (CcGetClientVersion(cm->Client, &ver) == ERR_NO_ERROR)
+ {
+ if (ver.IsVLanNameRegulated)
+ {
+ if (CiIsValidVLanRegulatedName(tmp) == false)
+ {
+ // Virtual LAN card name isn't meeting the format
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("D_CM_NEW_VLAN@S_WIN8"));
+
+ FocusEx(hWnd, E_NAME);
+ break;
+ }
+ }
+ }
+
+ EndDialog(hWnd, true);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ switch (LOWORD(wParam))
+ {
+ case E_NAME:
+ CmNewVLanDlgUpdate(hWnd);
+ break;
+
+ case R_USE_DISCONNECT:
+ if (IsChecked(hWnd, R_USE_DISCONNECT))
+ {
+ FocusEx(hWnd, E_DISCONNECT_SPAN);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Dialog to determine the new virtual LAN card name
+char *CmNewVLanDlg(HWND hWnd)
+{
+ char tmp[MAX_DEVICE_NAME_LEN + 1];
+
+ if (Dialog(hWnd, D_CM_NEW_VLAN, CmNewVLanDlgProc, tmp) == false)
+ {
+ return NULL;
+ }
+
+ return CopyStr(tmp);
+}
+
+// Update the advanced settings dialog
+void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a)
+{
+ bool ok = true;
+ bool locked;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ locked = a->LockMode;
+
+ if (a->LinkMode || a->NatMode)
+ {
+ Disable(hWnd, R_NO_ROUTING);
+ }
+ else
+ {
+ if (cm->Client->Unix)
+ {
+ Disable(hWnd, R_NO_ROUTING);
+ }
+ }
+
+ SetEnable(hWnd, E_DISCONNECT_SPAN, IsChecked(hWnd, R_USE_DISCONNECT));
+
+ SetEnable(hWnd, IDOK, ok);
+
+ if (locked)
+ {
+ Disable(hWnd, C_NUM_TCP);
+ Disable(hWnd, S_STATIC5);
+ Disable(hWnd, S_STATIC8);
+ Disable(hWnd, E_INTERVAL);
+ Disable(hWnd, S_STATIC9);
+ Disable(hWnd, E_DISCONNECT_SPAN);
+ Disable(hWnd, S_STATIC10);
+ Disable(hWnd, S_STATIC11);
+ Disable(hWnd, R_USE_DISCONNECT);
+ Disable(hWnd, R_USE_HALF_CONNECTION);
+ Disable(hWnd, R_DISABLE_QOS);
+ Disable(hWnd, R_USE_ENCRYPT);
+ Disable(hWnd, R_USE_COMPRESS);
+ Disable(hWnd, R_BRIDGE);
+ Disable(hWnd, R_MONITOR);
+ Disable(hWnd, R_NO_ROUTING);
+ }
+}
+
+// Advanced Settings dialog procedure
+UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_ACCOUNT *a = (CM_ACCOUNT *)param;
+ UINT i;
+ UINT num;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Number of TCP connections
+ for (i = 1;i <= MAX_TCP_CONNECTION;i++)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%u", i);
+ CbAddStr(hWnd, C_NUM_TCP, tmp, i);
+ }
+ CbSelect(hWnd, C_NUM_TCP, a->ClientOption->MaxConnection);
+
+ // Connection establishment interval
+ SetInt(hWnd, E_INTERVAL, a->ClientOption->AdditionalConnectionInterval);
+
+ // Lifetime
+ SetIntEx(hWnd, E_DISCONNECT_SPAN, a->ClientOption->ConnectionDisconnectSpan);
+ Check(hWnd, R_USE_DISCONNECT, a->ClientOption->ConnectionDisconnectSpan != 0);
+ Check(hWnd, R_USE_HALF_CONNECTION, a->ClientOption->HalfConnection);
+ Check(hWnd, R_USE_ENCRYPT, a->ClientOption->UseEncrypt);
+ Check(hWnd, R_USE_COMPRESS, a->ClientOption->UseCompress);
+ Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking);
+ Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS);
+ Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration);
+
+ // Select the Connection Mode
+ if (a->LinkMode == false)
+ {
+ Check(hWnd, R_BRIDGE, a->ClientOption->RequireBridgeRoutingMode);
+ Check(hWnd, R_MONITOR, a->ClientOption->RequireMonitorMode);
+ }
+ else
+ {
+ Check(hWnd, R_BRIDGE, true);
+ Check(hWnd, R_MONITOR, false);
+
+ SetText(hWnd, S_MODE, _UU("CM_DETAIL_MODE_LINK_STR"));
+ Disable(hWnd, R_BRIDGE);
+ Disable(hWnd, R_MONITOR);
+ }
+
+ CmDetailDlgUpdate(hWnd, a);
+ Focus(hWnd, IDOK);
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsChecked(hWnd, R_USE_DISCONNECT) && GetInt(hWnd, E_DISCONNECT_SPAN) == 0)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_NO_DISCONNECT_SPAN"));
+ FocusEx(hWnd, E_DISCONNECT_SPAN);
+ break;
+ }
+ num = GetInt(hWnd, C_NUM_TCP);
+ if (num == 0)
+ {
+ break;
+ }
+ if (num == 1 && IsChecked(hWnd, R_USE_HALF_CONNECTION))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_HALF_MSG"));
+ Focus(hWnd, C_NUM_TCP);
+ break;
+ }
+ if (GetInt(hWnd, E_INTERVAL) < 1)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TOO_SMALL_INTERVAL"));
+ Focus(hWnd, E_INTERVAL);
+ break;
+ }
+
+ a->ClientOption->MaxConnection = num;
+ a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL);
+ if (IsChecked(hWnd, R_USE_DISCONNECT) == false)
+ {
+ a->ClientOption->ConnectionDisconnectSpan = 0;
+ }
+ else
+ {
+ a->ClientOption->ConnectionDisconnectSpan = GetInt(hWnd, E_DISCONNECT_SPAN);
+ }
+ a->ClientOption->HalfConnection = IsChecked(hWnd, R_USE_HALF_CONNECTION);
+ a->ClientOption->UseEncrypt = IsChecked(hWnd, R_USE_ENCRYPT);
+ a->ClientOption->UseCompress = IsChecked(hWnd, R_USE_COMPRESS);
+ a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING);
+ a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS);
+ a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP);
+
+ if (a->LinkMode)
+ {
+ a->ClientOption->RequireBridgeRoutingMode = true;
+ a->ClientOption->RequireMonitorMode = false;
+ }
+ else
+ {
+ a->ClientOption->RequireBridgeRoutingMode = IsChecked(hWnd, R_BRIDGE);
+ a->ClientOption->RequireMonitorMode = IsChecked(hWnd, R_MONITOR);
+ }
+
+ EndDialog(hWnd, true);
+
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ switch (LOWORD(wParam))
+ {
+ case C_NUM_TCP:
+ case E_INTERVAL:
+ case E_DISCONNECT_SPAN:
+ case R_USE_DISCONNECT:
+ case R_USE_HALF_CONNECTION:
+ CmDetailDlgUpdate(hWnd, a);
+ break;
+ }
+ switch (wParam)
+ {
+ case R_USE_DISCONNECT:
+ if (IsChecked(hWnd, R_USE_DISCONNECT))
+ {
+ FocusEx(hWnd, E_DISCONNECT_SPAN);
+ }
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Advanced Settings dialog
+bool CmDetailDlg(HWND hWnd, CM_ACCOUNT *a)
+{
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_CM_DETAIL, CmDetailDlgProc, a);
+}
+
+// Update the account editing dialog procedure
+void CmEditAccountDlgUpdate(HWND hWnd, CM_ACCOUNT *a)
+{
+ bool ok = true;
+ char str[MAX_SIZE];
+ bool locked;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ locked = a->LockMode;
+
+ if (a->Inited == false)
+ {
+ return;
+ }
+
+ if (a->EditMode)
+ {
+ Disable(hWnd, E_ACCOUNT_NAME);
+ }
+
+ // The name of connection settings
+ GetTxt(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));
+ UniTrim(a->ClientOption->AccountName);
+
+ // Host name
+ GetTxtA(hWnd, E_HOSTNAME, a->ClientOption->Hostname, sizeof(a->ClientOption->Hostname));
+ Trim(a->ClientOption->Hostname);
+
+ // Port number
+ a->ClientOption->Port = GetInt(hWnd, C_PORT);
+
+ // HUB name
+ GetTxtA(hWnd,C_HUBNAME, a->ClientOption->HubName, sizeof(a->ClientOption->HubName));
+
+ // Type of proxy
+ a->ClientOption->ProxyType = PROXY_DIRECT;
+ if (IsChecked(hWnd, R_HTTPS))
+ {
+ a->ClientOption->ProxyType = PROXY_HTTP;
+ }
+ if (IsChecked(hWnd, R_SOCKS))
+ {
+ a->ClientOption->ProxyType = PROXY_SOCKS;
+ }
+
+ // To validate the server certificate
+ a->CheckServerCert = IsChecked(hWnd, R_CHECK_CERT);
+
+ if (a->NatMode)
+ {
+ Disable(hWnd, R_CHECK_CERT);
+ Disable(hWnd, B_TRUST);
+ }
+
+ if (a->HideTrustCert)
+ {
+ Disable(hWnd, B_TRUST);
+ }
+
+ // Device name
+ StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), "");
+ if (LvIsSelected(hWnd, L_VLAN))
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, LvGetSelected(hWnd, L_VLAN), 0);
+ if (s != NULL)
+ {
+ char str[MAX_SIZE];
+ UniToStr(str, sizeof(str), s);
+ CmPrintNameToVLanName(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), str);
+ Free(s);
+ }
+ }
+
+ // User authentication
+ a->ClientAuth->AuthType = CbGetSelect(hWnd, C_TYPE);
+ GetTxtA(hWnd, E_USERNAME, a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
+ Trim(a->ClientAuth->Username);
+ switch (a->ClientAuth->AuthType)
+ {
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // Password authentication
+ GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));
+ if (StrCmp(str, HIDDEN_PASSWORD) != 0)
+ {
+ HashPassword(a->ClientAuth->HashedPassword, a->ClientAuth->Username, str);
+ }
+ break;
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ // Plaintext password authentication
+ GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));
+ if (StrCmp(str, HIDDEN_PASSWORD) != 0)
+ {
+ StrCpy(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword), str);
+ }
+ break;
+ }
+
+ // Reconnection option
+ if ((a->LinkMode || a->NatMode) || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
+ {
+ Disable(hWnd, R_RETRY);
+ }
+ else
+ {
+ Enable(hWnd, R_RETRY);
+ }
+
+ if (IsChecked(hWnd, R_RETRY) == false)
+ {
+ a->ClientOption->NumRetry = 0;
+ }
+ else
+ {
+ if (IsChecked(hWnd, R_INFINITE))
+ {
+ a->ClientOption->NumRetry = INFINITE;
+ }
+ else
+ {
+ a->ClientOption->NumRetry = GetInt(hWnd, E_RETRY_NUM);
+ }
+ }
+ a->ClientOption->RetryInterval = GetInt(hWnd, E_RETRY_SPAN);
+
+ a->ClientOption->NoTls1 = IsChecked(hWnd, R_NOTLS1);
+
+ // Information determining
+ if (UniStrLen(a->ClientOption->AccountName) == 0 && a->NatMode == false)
+ {
+ ok = false;
+ }
+ if (StrLen(a->ClientOption->Hostname) == 0)
+ {
+ ok = false;
+ }
+ if (a->ClientOption->Port == 0 || a->ClientOption->Port >= 65536)
+ {
+ ok = false;
+ }
+ if (StrLen(a->ClientOption->HubName) == 0)
+ {
+ ok = false;
+ }
+ if (StrLen(a->ClientAuth->Username) == 0)
+ {
+ ok = false;
+ }
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (a->ClientAuth->ClientK == NULL || a->ClientAuth->ClientX == NULL)
+ {
+ ok = false;
+ }
+ }
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
+ {
+ if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))
+ {
+ ok = false;
+ }
+ }
+
+ // Display update
+ if (IsChecked(hWnd, R_RETRY) && IsEnable(hWnd, R_RETRY))
+ {
+ if (a->LinkMode == false && a->NatMode == false)
+ {
+ Enable(hWnd, R_INFINITE);
+ Enable(hWnd, E_RETRY_SPAN);
+ Enable(hWnd, S_RETRY_SPAN_1);
+ Enable(hWnd, S_RETRY_SPAN_2);
+ }
+ else
+ {
+ Disable(hWnd, R_INFINITE);
+ Disable(hWnd, E_RETRY_SPAN);
+ Disable(hWnd, S_RETRY_SPAN_1);
+ Disable(hWnd, S_RETRY_SPAN_2);
+ }
+ if (IsChecked(hWnd, R_INFINITE) == false)
+ {
+ Enable(hWnd, E_RETRY_NUM);
+ Enable(hWnd, S_RETRY_NUM_1);
+ Enable(hWnd, S_RETRY_NUM_2);
+ if (GetInt(hWnd, E_RETRY_NUM) == 0)
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ Disable(hWnd, E_RETRY_NUM);
+ Disable(hWnd, S_RETRY_NUM_1);
+ Disable(hWnd, S_RETRY_NUM_2);
+ }
+ }
+ else
+ {
+ Disable(hWnd, E_RETRY_NUM);
+ Disable(hWnd, E_RETRY_SPAN);
+ Disable(hWnd, R_INFINITE);
+ Disable(hWnd, S_RETRY_NUM_1);
+ Disable(hWnd, S_RETRY_NUM_2);
+ Disable(hWnd, S_RETRY_SPAN_1);
+ Disable(hWnd, S_RETRY_SPAN_2);
+ }
+
+ if (a->NatMode == false)
+ {
+ if (a->ServerCert == NULL)
+ {
+ SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_1"));
+ Disable(hWnd, B_VIEW_SERVER_CERT);
+ }
+ else
+ {
+ SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_2"));
+ Enable(hWnd, B_VIEW_SERVER_CERT);
+ }
+ }
+ else
+ {
+ Disable(hWnd, B_VIEW_SERVER_CERT);
+ Disable(hWnd, B_SERVER_CERT);
+ }
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
+ {
+ wchar_t tmp[MAX_SIZE * 2];
+ wchar_t issuer[MAX_SIZE];
+ wchar_t subject[MAX_SIZE];
+ wchar_t expires[MAX_SIZE];
+
+ SetIcon(hWnd, S_CERT, (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT) ? ICO_CERT : ICO_SECURE);
+
+ Hide(hWnd, S_PASSWORD);
+ Hide(hWnd, E_PASSWORD);
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (a->ClientAuth->ClientX != NULL)
+ {
+ Enable(hWnd, B_VIEW_CLIENT_CERT);
+ SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_2"));
+ GetPrintNameFromName(issuer, sizeof(issuer), a->ClientAuth->ClientX->issuer_name);
+ GetPrintNameFromName(subject, sizeof(subject), a->ClientAuth->ClientX->subject_name);
+ GetDateStrEx64(expires, sizeof(expires), SystemToLocal64(a->ClientAuth->ClientX->notAfter), NULL);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_INFO"), subject, issuer, expires);
+ }
+ else
+ {
+ Disable(hWnd, B_VIEW_CLIENT_CERT);
+ SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_1"));
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_CERT"));
+ }
+ SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_VIEW_CLIENT_CERT"));
+
+ Enable(hWnd, B_REGIST_CLIENT_CERT);
+ }
+ else
+ {
+ if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_SECURE"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_SECURE_INFO"),
+ a->ClientAuth->SecurePublicCertName, a->ClientAuth->SecurePrivateKeyName);
+ }
+
+ SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_SELECT_SECURE_DEVICE"));
+ SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_SELECT_CERT_INCARD"));
+ Enable(hWnd, B_VIEW_CLIENT_CERT);
+
+ if (SmGetCurrentSecureIdFromReg() == 0)
+ {
+ Disable(hWnd, B_REGIST_CLIENT_CERT);
+ }
+ else
+ {
+ Enable(hWnd, B_REGIST_CLIENT_CERT);
+ }
+ }
+ SetText(hWnd, S_CERT_INFO, tmp);
+ Show(hWnd, S_CERT);
+ Show(hWnd, S_CERT_INFO);
+ Show(hWnd, B_VIEW_CLIENT_CERT);
+ Show(hWnd, B_REGIST_CLIENT_CERT);
+ }
+ else
+ {
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_ANONYMOUS)
+ {
+ Hide(hWnd, S_PASSWORD);
+ Hide(hWnd, E_PASSWORD);
+ }
+ else
+ {
+ Show(hWnd, S_PASSWORD);
+ Show(hWnd, E_PASSWORD);
+ }
+ Hide(hWnd, S_CERT);
+ Hide(hWnd, S_CERT_INFO);
+ Hide(hWnd, B_VIEW_CLIENT_CERT);
+ Hide(hWnd, B_REGIST_CLIENT_CERT);
+ }
+
+ if (a->ClientOption->ProxyType != PROXY_DIRECT)
+ {
+ Enable(hWnd, B_PROXY_CONFIG);
+ if (StrLen(a->ClientOption->ProxyName) == 0)
+ {
+ ok = false;
+ }
+ if (a->ClientOption->ProxyPort == 0)
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ Disable(hWnd, B_PROXY_CONFIG);
+ }
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ bool b = true;
+
+ if (ok == false)
+ {
+ b = false;
+ }
+
+ if (a->LinkMode == false && a->NatMode == false)
+ {
+ SetEnable(hWnd, B_CHANGE_PASSWORD, b);
+ SetEnable(hWnd, S_CHANGE_PASSWORD, b);
+ Show(hWnd, B_CHANGE_PASSWORD);
+ Show(hWnd, S_CHANGE_PASSWORD);
+ }
+ else
+ {
+ Hide(hWnd, B_CHANGE_PASSWORD);
+ Hide(hWnd, S_CHANGE_PASSWORD);
+ }
+ }
+ else
+ {
+ Hide(hWnd, B_CHANGE_PASSWORD);
+ Hide(hWnd, S_CHANGE_PASSWORD);
+ }
+
+ if ((StrLen(a->ClientOption->DeviceName) == 0) && (a->LinkMode == false && a->NatMode == false))
+ {
+ ok = false;
+ }
+
+ if (a->LinkMode || a->NatMode)
+ {
+ Disable(hWnd, L_VLAN);
+ }
+
+ if (a->EditMode == false)
+ {
+ char tmp[MAX_SIZE];
+ GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));
+ Trim(tmp);
+
+ if (StartWith(tmp, "127.") || (StrCmpi(tmp, "localhost") == 0))
+ {
+ if (a->Flag1 == false)
+ {
+ a->Flag1 = true;
+ a->ClientOption->UseEncrypt = a->ClientOption->UseCompress = false;
+ a->ClientOption->MaxConnection = 1;
+ }
+ }
+ }
+
+ a->ClientOption->HideStatusWindow = IsChecked(hWnd, R_HIDE);
+ a->ClientOption->HideNicInfoWindow = IsChecked(hWnd, R_HIDE2);
+
+ if (locked)
+ {
+ SetEnable(hWnd, E_HOSTNAME, false);
+ SetEnable(hWnd, C_PORT, false);
+ SetEnable(hWnd, C_HUBNAME, false);
+ SetEnable(hWnd, S_STATIC2, false);
+ SetEnable(hWnd, S_STATIC3, false);
+ SetEnable(hWnd, S_STATIC4, false);
+ SetEnable(hWnd, S_STATIC5, false);
+ SetEnable(hWnd, S_STATIC66, false);
+ SetEnable(hWnd, S_STATIC7, false);
+ SetEnable(hWnd, S_STATIC11, false);
+ SetEnable(hWnd, R_CHECK_CERT, false);
+ SetEnable(hWnd, B_TRUST, false);
+ SetEnable(hWnd, B_SERVER_CERT, false);
+ SetEnable(hWnd, B_VIEW_SERVER_CERT, false);
+ SetEnable(hWnd, R_RETRY, false);
+ SetEnable(hWnd, S_RETRY_NUM_1, false);
+ SetEnable(hWnd, E_RETRY_NUM, false);
+ SetEnable(hWnd, S_RETRY_NUM_2, false);
+ SetEnable(hWnd, S_RETRY_SPAN_1, false);
+ SetEnable(hWnd, E_RETRY_SPAN, false);
+ SetEnable(hWnd, S_RETRY_SPAN_2, false);
+ SetEnable(hWnd, R_INFINITE, false);
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Initialize the account editing dialog
+void CmEditAccountDlgInit(HWND hWnd, CM_ACCOUNT *a)
+{
+ RPC_CLIENT_ENUM_VLAN v;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ if (a->LockMode)
+ {
+ SetText(hWnd, S_STATIC1, _UU("CM_EASY_ACCOUNT_WARNING"));
+ }
+
+ // Connection settings name
+ if (a->EditMode || a->NatMode)
+ {
+ Disable(hWnd, E_ACCOUNT_NAME);
+ }
+
+ if (a->NatMode || a->LinkMode)
+ {
+ Hide(hWnd, R_HIDE);
+ Hide(hWnd, R_HIDE2);
+ }
+
+ Check(hWnd, R_HIDE, a->ClientOption->HideStatusWindow);
+ Check(hWnd, R_HIDE2, a->ClientOption->HideNicInfoWindow);
+
+ if (a->NatMode)
+ {
+ Hide(hWnd, E_ACCOUNT_NAME);
+ Hide(hWnd, S_ACCOUNT_NAME);
+ }
+
+ if ((cm != NULL && cm->server_name != NULL) || a->LinkMode)
+ {
+ Hide(hWnd, B_IE);
+ }
+
+ SetText(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName);
+
+ // Host name
+ SetTextA(hWnd, E_HOSTNAME, a->ClientOption->Hostname);
+ StrCpy(a->old_server_name, sizeof(a->old_server_name), a->ClientOption->Hostname);
+
+ // Port number
+ CbSetHeight(hWnd, C_PORT, 18);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_1"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_2"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_3"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_4"), 0);
+ SetInt(hWnd, C_PORT, a->ClientOption->Port);
+
+ // Virtual HUB name
+ CbSetHeight(hWnd, C_HUBNAME, 18);
+ SetTextA(hWnd, C_HUBNAME, a->ClientOption->HubName);
+
+ // Type of proxy
+ Check(hWnd, R_DIRECT_TCP, a->ClientOption->ProxyType == PROXY_DIRECT);
+ Check(hWnd, R_HTTPS, a->ClientOption->ProxyType == PROXY_HTTP);
+ Check(hWnd, R_SOCKS, a->ClientOption->ProxyType == PROXY_SOCKS);
+
+ // Verify the server certificate
+ Check(hWnd, R_CHECK_CERT, a->CheckServerCert);
+
+ // LAN card list
+ if (a->NatMode == false && a->LinkMode == false)
+ {
+ Zero(&v, sizeof(v));
+ CcEnumVLan(cm->Client, &v);
+ LvInit(hWnd, L_VLAN);
+ LvInsertColumn(hWnd, L_VLAN, 0, L"DeviceName", 345);
+ for (i = 0;i < v.NumItem;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ CmVLanNameToPrintName(str, sizeof(str), v.Items[i]->DeviceName);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsert(hWnd, L_VLAN, ICO_NIC_ONLINE, NULL, 1, tmp);
+ }
+// LvAutoSize(hWnd, L_VLAN);
+
+ if (v.NumItem == 1)
+ {
+ // If only one virtual LAN card exists, initially select it
+ LvSelect(hWnd, L_VLAN, 0);
+ }
+
+ CiFreeClientEnumVLan(&v);
+ }
+
+ // Select the LAN card
+ if (StrLen(a->ClientOption->DeviceName) != 0)
+ {
+ char str[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ UINT index;
+ CmVLanNameToPrintName(str, sizeof(str), a->ClientOption->DeviceName);
+ StrToUni(tmp, sizeof(tmp), str);
+ index = LvSearchStr(hWnd, L_VLAN, 0, tmp);
+ if (index != INFINITE)
+ {
+ LvSelect(hWnd, L_VLAN, index);
+ }
+ }
+
+ // Authentication type
+ CbSetHeight(hWnd, C_TYPE, 18);
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_0"), CLIENT_AUTHTYPE_ANONYMOUS);
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);
+
+ if (a->HideClientCertAuth == false)
+ {
+ // Certificate authentication is not available when HideClientCertAuth is true
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_3"), CLIENT_AUTHTYPE_CERT);
+ }
+
+ if (a->HideSecureAuth == false)
+ {
+ // Authentication using a smart card
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_4"), CLIENT_AUTHTYPE_SECURE);
+ }
+
+ // Select an authentication
+ CbSelect(hWnd, C_TYPE, a->ClientAuth->AuthType);
+
+ // User name
+ SetTextA(hWnd, E_USERNAME, a->ClientAuth->Username);
+
+ // Password
+ if (a->EditMode)
+ {
+ SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
+ }
+
+ // Reconnection times
+ if (a->ClientOption->NumRetry == 0)
+ {
+ Check(hWnd, R_RETRY, false);
+ }
+ else
+ {
+ Check(hWnd, R_RETRY, true);
+ if (a->ClientOption->NumRetry == INFINITE)
+ {
+ Check(hWnd, R_INFINITE, true);
+ }
+ else
+ {
+ Check(hWnd, R_INFINITE, false);
+ SetInt(hWnd, E_RETRY_NUM, a->ClientOption->NumRetry);
+ }
+ }
+ SetIntEx(hWnd, E_RETRY_SPAN, a->ClientOption->RetryInterval);
+
+ Check(hWnd, R_NOTLS1, a->ClientOption->NoTls1);
+
+ // Title
+ if (a->NatMode == false)
+ {
+ if (a->EditMode == false)
+ {
+ SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_1"));
+ FocusEx(hWnd, E_ACCOUNT_NAME);
+ }
+ else
+ {
+ SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_2"));
+ FormatText(hWnd, 0, a->ClientOption->AccountName);
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+ }
+ else
+ {
+ SetText(hWnd, 0, _UU("NM_ACCOUNT_TITLE"));
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+
+ if (a->LinkMode || a->NatMode)
+ {
+ Hide(hWnd, L_VLAN);
+
+ if (a->NatMode == false)
+ {
+ SetText(hWnd, S_VLAN_GROUP, _UU("SM_LINK_POLICY_GROUP"));
+ Show(hWnd, S_POLICY_1);
+ Show(hWnd, S_POLICY_2);
+ Show(hWnd, B_POLICY);
+ }
+ else
+ {
+ Hide(hWnd, S_VLAN_GROUP);
+ Show(hWnd, S_ROUTER_LOGO);
+ }
+ }
+
+ // Display update
+ a->Inited = true;
+ CmEditAccountDlgUpdate(hWnd, a);
+}
+
+// Account editing dialog procedure
+UINT CmEditAccountDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_ACCOUNT *a = (CM_ACCOUNT *)param;
+ NMHDR *n;
+ X *x;
+ K *k;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmEditAccountDlgInit(hWnd, a);
+ if (a->EditMode == false && a->LinkMode == false && a->NatMode == false)
+ {
+ SetTimer(hWnd, 1, 100, NULL);
+ }
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ {
+ CM_INTERNET_SETTING s;
+
+ KillTimer(hWnd, 1);
+
+ Zero(&s, sizeof(s));
+ CmGetSystemInternetSetting(&s);
+
+ if (s.ProxyType != PROXY_DIRECT)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO,
+ _UU("CM_WOULDYOULOAD_IE_PROXY"),
+ s.ProxyHostName) == IDYES)
+ {
+ Command(hWnd, B_IE);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_ACCOUNT_NAME:
+ case E_HOSTNAME:
+ case C_PORT:
+ case C_HUBNAME:
+ case R_DIRECT_TCP:
+ case R_HTTPS:
+ case R_SOCKS:
+ case R_CHECK_CERT:
+ case C_TYPE:
+ case E_USERNAME:
+ case E_PASSWORD:
+ case R_RETRY:
+ case E_RETRY_NUM:
+ case E_RETRY_SPAN:
+ case R_INFINITE:
+ CmEditAccountDlgUpdate(hWnd, a);
+ break;
+ }
+ switch (HIWORD(wParam))
+ {
+ case EN_KILLFOCUS:
+ switch (LOWORD(wParam))
+ {
+ case E_HOSTNAME:
+ CmEditAccountDlgStartEnumHub(hWnd, a);
+ break;
+ }
+ break;
+ case BN_KILLFOCUS:
+ switch (LOWORD(wParam))
+ {
+ case R_DIRECT_TCP:
+ case R_HTTPS:
+ case R_SOCKS:
+ CmEditAccountDlgStartEnumHub(hWnd, a);
+ break;
+ }
+ break;
+ case CBN_KILLFOCUS:
+ switch (LOWORD(wParam))
+ {
+ case C_PORT:
+ CmEditAccountDlgStartEnumHub(hWnd, a);
+ break;
+ }
+ break;
+ }
+ if (HIWORD(wParam) == 0)
+ {
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ switch (wParam)
+ {
+ case B_POLICY:
+ // Policy
+ if (a->LinkMode || a->NatMode)
+ {
+ a->Policy.Access = true;
+ a->Policy.MonitorPort = false;
+ SmPolicyDlgEx2(hWnd, &a->Policy, _UU("SM_LINK_POLICY_CAPTION"), true, a->PolicyVer);
+ a->Policy.Access = true;
+ a->Policy.MonitorPort = false;
+ }
+ break;
+ case IDOK:
+ CmEditAccountDlgUpdate(hWnd, a);
+ CmEditAccountDlgOnOk(hWnd, a);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case B_PROXY_CONFIG:
+ // Proxy Settings
+ if (CmProxyDlg(hWnd, a->ClientOption))
+ {
+ UINT n = GetInt(hWnd, C_PORT);
+ if (a->ClientOption->ProxyType == PROXY_HTTP &&
+ n != 443)
+ {
+ // Show a warning message if the destination port is
+ // other than 443 and HTTP proxy is used
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_HTTP_PROXY_WARNING"), n) == IDYES)
+ {
+ // Change the port number to 443
+ SetText(hWnd, C_PORT, _UU("CM_PORT_2"));
+ }
+ }
+ CmEditAccountDlgStartEnumHub(hWnd, a);
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ break;
+ case B_IE:
+ // Use the IE settings
+ if(cm->server_name == NULL)
+ {
+ CmProxyDlgUseForIE(hWnd, a->ClientOption);
+ CmEditAccountDlgUpdate(hWnd, a);
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PROXY_FROM_IE"));
+ }
+ break;
+ case B_TRUST:
+ // CA
+ if (a->LinkMode == false)
+ {
+ CmTrustDlg(hWnd);
+ }
+ else
+ {
+ SmCaDlg(hWnd, a->Hub);
+ }
+ break;
+ case B_SERVER_CERT:
+ // Server certificate registration / delete
+ if (a->ServerCert == NULL)
+ {
+ if (CmLoadXFromFileOrSecureCard(hWnd, &x))
+ {
+ a->ServerCert = x;
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ }
+ else
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_SERVER_CERT")) == IDYES)
+ {
+ FreeX(a->ServerCert);
+ a->ServerCert = NULL;
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ }
+ break;
+ case B_VIEW_SERVER_CERT:
+ // Show the server certificate
+ if (a->ServerCert != NULL)
+ {
+ X *issuer = CmGetIssuer(a->ServerCert);
+ CertDlg(hWnd, a->ServerCert, issuer, true);
+ FreeX(issuer);
+ }
+ break;
+ case B_VIEW_CLIENT_CERT:
+ if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)
+ {
+ // Show the client certificate
+ if (a->ClientAuth->ClientX != NULL)
+ {
+ X *issuer = CmGetIssuer(a->ClientAuth->ClientX);
+ CertDlg(hWnd, a->ClientAuth->ClientX, issuer, true);
+ FreeX(issuer);
+ }
+ }
+ else
+ {
+ UINT id;
+ // Select the type of smart card
+ SmSelectSecureId(hWnd);
+ id = SmGetCurrentSecureIdFromReg();
+ if (id != 0)
+ {
+ if (cm->server_name == NULL)
+ {
+ RPC_USE_SECURE t;
+
+ Zero(&t, sizeof(t));
+ t.DeviceId = id;
+ CcUseSecure(cm->Client, &t);
+ }
+ }
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ break;
+ case B_REGIST_CLIENT_CERT:
+ if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)
+ {
+ // Client certificate registration / deletion
+ if (a->ClientAuth->ClientX == NULL)
+ {
+ if (CmLoadXAndK(hWnd, &x, &k))
+ {
+ a->ClientAuth->ClientX = x;
+ a->ClientAuth->ClientK = k;
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ }
+ else
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_CLIENT_CERT")) == IDYES)
+ {
+ FreeX(a->ClientAuth->ClientX);
+ FreeK(a->ClientAuth->ClientK);
+ a->ClientAuth->ClientX = NULL;
+ a->ClientAuth->ClientK = NULL;
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ }
+ }
+ else
+ {
+ char cert[MAX_SECURE_DEVICE_FILE_LEN + 1], priv[MAX_SECURE_DEVICE_FILE_LEN + 1];
+
+ // Select a certificate in the smart card
+ if (SmSelectKeyPairEx(hWnd, cert, sizeof(cert), priv, sizeof(priv), CmGetSecureBitmapId(a->ClientOption->Hostname)))
+ {
+ StrCpy(a->ClientAuth->SecurePublicCertName, sizeof(a->ClientAuth->SecurePublicCertName), cert);
+ StrCpy(a->ClientAuth->SecurePrivateKeyName, sizeof(a->ClientAuth->SecurePrivateKeyName), priv);
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ }
+ break;
+ case B_DETAIL:
+ // Advanced communication settings
+ if (CmDetailDlg(hWnd, a))
+ {
+ CmEditAccountDlgUpdate(hWnd, a);
+ }
+ break;
+ case B_CHANGE_PASSWORD:
+ // Change the password
+ CmChangePassword(hWnd, a->ClientOption, a->ClientOption->HubName,
+ a->ClientAuth->Username);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_VLAN:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CmEditAccountDlgUpdate(hWnd, a);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Update the proxy server settings
+void CmProxyDlgUpdate(HWND hWnd, CLIENT_OPTION *a)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ if (IsEmpty(hWnd, E_HOSTNAME))
+ {
+ ok = false;
+ }
+ if (GetInt(hWnd, C_PORT) == 0)
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Proxy server settings dialog c
+UINT CmProxyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CLIENT_OPTION *a = (CLIENT_OPTION *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetTextA(hWnd, E_HOSTNAME, a->ProxyName);
+ CbSetHeight(hWnd, C_PORT, 18);
+ CbAddStr(hWnd, C_PORT, L"8080", 0);
+ CbAddStr(hWnd, C_PORT, L"1080", 0);
+ CbAddStr(hWnd, C_PORT, L"80", 0);
+ CbAddStr(hWnd, C_PORT, L"3128", 0);
+ CbAddStr(hWnd, C_PORT, L"443", 0);
+ CbAddStr(hWnd, C_PORT, L"9821", 0);
+ CbAddStr(hWnd, C_PORT, L"9801", 0);
+ SetIntEx(hWnd, C_PORT, a->ProxyPort);
+ SetTextA(hWnd, E_USERNAME, a->ProxyUsername);
+ SetTextA(hWnd, E_PASSWORD, a->ProxyPassword);
+ if (a->ProxyPort == 0)
+ {
+ if (a->ProxyType == PROXY_HTTP)
+ {
+ SetInt(hWnd, C_PORT, 8080);
+ }
+ else
+ {
+ SetInt(hWnd, C_PORT, 1080);
+ }
+ }
+ CmProxyDlgUpdate(hWnd, a);
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_HOSTNAME:
+ case C_PORT:
+ case E_USERNAME:
+ case E_PASSWORD:
+ CmProxyDlgUpdate(hWnd, a);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_HOSTNAME, a->ProxyName, sizeof(a->ProxyName));
+ GetTxtA(hWnd, E_USERNAME, a->ProxyUsername, sizeof(a->ProxyUsername));
+ GetTxtA(hWnd, E_PASSWORD, a->ProxyPassword, sizeof(a->ProxyPassword));
+ a->ProxyPort = GetInt(hWnd, C_PORT);
+ EndDialog(hWnd, true);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Proxy server settings
+bool CmProxyDlg(HWND hWnd, CLIENT_OPTION *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_CM_PROXY, CmProxyDlgProc, a);
+}
+
+// Get issuer of the specified certificate if it is known
+X *CmGetIssuer(X *x)
+{
+ RPC_GET_ISSUER a;
+ X *ret;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&a, sizeof(a));
+ a.x = CloneX(x);
+ if (CALLEX(cm->hMainWnd, CcGetIssuer(cm->Client, &a)) == 0)
+ {
+ ret = CloneX(a.issuer_x);
+ }
+ else
+ {
+ ret = NULL;
+ }
+
+ CiFreeGetIssuer(&a);
+
+ return ret;
+}
+
+// Initialize the dialog
+void CmLoadXFromFileOrSecureCardDlgInit(HWND hWnd, CM_LOADX *p)
+{
+ UINT current;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ current = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource");
+
+ Check(hWnd, R_FROM_FILE, current == 0);
+ Check(hWnd, R_FROM_SECURE, current != 0);
+
+ SetFont(hWnd, S_INFO, Font(0, true));
+
+ CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
+}
+
+// Update the dialog control
+void CmLoadXFromFileOrSecureCardDlgUpdate(HWND hWnd, CM_LOADX *p)
+{
+ SECURE_DEVICE *dev;
+ wchar_t tmp[MAX_SIZE];
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ dev = GetSecureDevice(SmGetCurrentSecureIdFromReg());
+ if (dev == NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SEC_CURRENT_NO_DEVICE"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SEC_CURRENT_DEVICE"), dev->DeviceName);
+ }
+
+ SetText(hWnd, S_INFO, tmp);
+
+ if (IsChecked(hWnd, R_FROM_SECURE))
+ {
+ if (dev == NULL)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+ SetEnable(hWnd, B_SELECT, IsChecked(hWnd, R_FROM_SECURE));
+ SetEnable(hWnd, S_CERT, IsChecked(hWnd, R_FROM_SECURE));
+ SetEnable(hWnd, S_FILE, IsChecked(hWnd, R_FROM_FILE));
+}
+
+// Certificate reading selection dialog procedure
+UINT CmLoadXFromFileOrSecureCardDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_LOADX *p = (CM_LOADX *)param;
+ X *x;
+ UINT current;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CmLoadXFromFileOrSecureCardDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ current = (IsChecked(hWnd, R_FROM_FILE)) ? 0 : 1;
+ MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource", current);
+
+ if (current == 0)
+ {
+ // From file
+ if (CmLoadX(hWnd, &x))
+ {
+ p->x = x;
+ EndDialog(hWnd, true);
+ }
+ }
+ else
+ {
+ // From the smart card
+ char name[MAX_SIZE];
+
+ // Select the certificate name in the card
+ if (SmSelectKeyPair(hWnd, name, sizeof(name), NULL, 0))
+ {
+ // Read
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_READ_CERT, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+
+ // Do reading
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), SmGetCurrentSecureIdFromReg(), 0))
+ {
+ // Success
+ p->x = batch[0].OutputX;
+ EndDialog(hWnd, true);
+ }
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_FROM_FILE:
+ CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
+ break;
+
+ case R_FROM_SECURE:
+ CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
+ break;
+
+ case B_SELECT:
+ SmSelectSecureId(hWnd);
+ CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Read certificate from a file or a smart card
+bool CmLoadXFromFileOrSecureCard(HWND hWnd, X **x)
+{
+ CM_LOADX p;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ if (Dialog(hWnd, D_CM_LOAD_X, CmLoadXFromFileOrSecureCardDlgProc, &p) == false)
+ {
+ return false;
+ }
+
+ *x = p.x;
+
+ return true;
+}
+
+// Read the certificate
+bool CmLoadX(HWND hWnd, X **x)
+{
+ return CmLoadXEx(hWnd, x, NULL, 0);
+}
+bool CmLoadXEx(HWND hWnd, X **x, char *filename, UINT size)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret;
+
+ ret = CmLoadXExW(hWnd, x, filename_w, size);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool CmLoadXExW(HWND hWnd, X **x, wchar_t *filename, UINT size)
+{
+ wchar_t *s;
+ bool is_p12;
+ wchar_t tmp[MAX_SIZE];
+ K *k;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ // Read the certificate
+ s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));
+ if (s == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(tmp, sizeof(tmp), s);
+ if (filename != NULL)
+ {
+ UniStrCpy(filename, size, tmp);
+ }
+ Free(s);
+ if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
+ {
+ is_p12 = true;
+ }
+ else
+ {
+ is_p12 = false;
+ }
+
+ if (is_p12)
+ {
+ // Processing of PKCS#12
+ BUF *b = ReadDumpW(tmp);
+ P12 *p12;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+ p12 = BufToP12(b);
+ if (p12 == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeBuf(b);
+ return false;
+ }
+ if (IsEncryptedP12(p12) == false)
+ {
+ if (ParseP12(p12, x, &k, NULL) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ }
+ else
+ {
+ char password[MAX_SIZE];
+ if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
+ {
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ else
+ {
+ if (ParseP12(p12, x, &k, password) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ }
+ }
+ FreeP12(p12);
+ FreeBuf(b);
+ FreeK(k);
+ return true;
+ }
+ else
+ {
+ // Processing of X509
+ BUF *b = ReadDumpW(tmp);
+ X *x509;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+
+ x509 = BufToX(b, IsBase64(b));
+ FreeBuf(b);
+ if (x509 == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);
+ return false;
+ }
+
+ *x = x509;
+ return true;
+ }
+}
+
+// Read the secret key
+bool CmLoadK(HWND hWnd, K **k)
+{
+ return CmLoadKEx(hWnd, k, NULL, 0);
+}
+bool CmLoadKEx(HWND hWnd, K **k, char *filename, UINT size)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret;
+
+ ret = CmLoadKExW(hWnd, k, filename_w, size);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size)
+{
+ wchar_t *s;
+ bool is_p12;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (k == NULL)
+ {
+ return false;
+ }
+
+ // Read the certificate
+ s = OpenDlg(hWnd, _UU("DLG_KEY_OR_P12_FILTER"), _UU("DLG_OPEN_KEY"));
+ if (s == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(tmp, sizeof(tmp), s);
+ Free(s);
+ if (filename != NULL)
+ {
+ UniStrCpy(filename, size, tmp);
+ }
+ if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
+ {
+ is_p12 = true;
+ }
+ else
+ {
+ is_p12 = false;
+ }
+
+ if (is_p12)
+ {
+ // Processing of PKCS#12
+ BUF *b = ReadDumpW(tmp);
+ P12 *p12;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+ p12 = BufToP12(b);
+ if (p12 == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeBuf(b);
+ return false;
+ }
+ if (IsEncryptedP12(p12) == false)
+ {
+ X *x;
+ if (ParseP12(p12, &x, k, NULL) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeX(x);
+ }
+ else
+ {
+ char password[MAX_SIZE];
+ if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
+ {
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ else
+ {
+ X *x;
+ if (ParseP12(p12, &x, k, password) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeX(x);
+ }
+ }
+ FreeP12(p12);
+ FreeBuf(b);
+ return true;
+ }
+ else
+ {
+ // Processing of private key
+ BUF *b = ReadDumpW(tmp);
+ K *key;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+
+ if (IsEncryptedK(b, true) == false)
+ {
+ key = BufToK(b, true, IsBase64(b), NULL);
+ }
+ else
+ {
+ char pass[MAX_SIZE];
+ if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+ key = BufToK(b, true, IsBase64(b), pass);
+ }
+
+ if (key == NULL)
+ {
+ FreeBuf(b);
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);
+ return false;
+ }
+
+ FreeBuf(b);
+ *k = key;
+ return true;
+ }
+}
+
+// Read a set of certificate and private key
+bool CmLoadXAndK(HWND hWnd, X **x, K **k)
+{
+ wchar_t *s;
+ bool is_p12;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+START_FIRST:
+
+ // Read the certificate
+ s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));
+ if (s == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(tmp, sizeof(tmp), s);
+ Free(s);
+ if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
+ {
+ is_p12 = true;
+ }
+ else
+ {
+ is_p12 = false;
+ }
+
+ if (is_p12)
+ {
+ // Processing of PKCS#12
+ BUF *b = ReadDumpW(tmp);
+ P12 *p12;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+ p12 = BufToP12(b);
+ if (p12 == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeBuf(b);
+ return false;
+ }
+ if (IsEncryptedP12(p12) == false)
+ {
+ if (ParseP12(p12, x, k, NULL) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ }
+ else
+ {
+ char password[MAX_SIZE];
+ if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
+ {
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ else
+ {
+ if (ParseP12(p12, x, k, password) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
+ FreeP12(p12);
+ FreeBuf(b);
+ return false;
+ }
+ }
+ }
+ if (CheckXandK(*x, *k) == false)
+ {
+ FreeX(*x);
+ FreeK(*k);
+ FreeP12(p12);
+ FreeBuf(b);
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
+ {
+ goto START_FIRST;
+ }
+ return false;
+ }
+ FreeP12(p12);
+ FreeBuf(b);
+ return true;
+ }
+ else
+ {
+ // Processing of X509
+ BUF *b = ReadDumpW(tmp);
+ X *x509;
+ K *key;
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ return false;
+ }
+
+ x509 = BufToX(b, IsBase64(b));
+ FreeBuf(b);
+ if (x509 == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);
+ return false;
+ }
+
+ // Read the secret key
+ s = OpenDlg(hWnd, _UU("DLG_KEY_FILTER"), _UU("DLG_OPEN_KEY_WITH_CERT"));
+ if (s == NULL)
+ {
+ FreeX(x509);
+ return false;
+ }
+ UniStrCpy(tmp, sizeof(tmp), s);
+ Free(s);
+
+ b = ReadDumpW(tmp);
+ if (b == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
+ FreeX(x509);
+ return false;
+ }
+
+ if (IsEncryptedK(b, true) == false)
+ {
+ key = BufToK(b, true, IsBase64(b), NULL);
+ }
+ else
+ {
+ char pass[MAX_SIZE];
+ if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)
+ {
+ FreeBuf(b);
+ FreeX(x509);
+ return false;
+ }
+ key = BufToK(b, true, IsBase64(b), pass);
+ }
+
+ if (key == NULL)
+ {
+ FreeBuf(b);
+ FreeX(x509);
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);
+ return false;
+ }
+
+ if (CheckXandK(x509, key) == false)
+ {
+ FreeBuf(b);
+ FreeX(x509);
+ FreeK(key);
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
+ {
+ goto START_FIRST;
+ }
+ return false;
+ }
+
+ FreeBuf(b);
+ *x = x509;
+ *k = key;
+ return true;
+ }
+}
+
+// Virtual HUB enumeration start
+void CmEditAccountDlgStartEnumHub(HWND hWnd, CM_ACCOUNT *a)
+{
+ char server_name[MAX_HOST_NAME_LEN + 1];
+ UINT old_proxy_type;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+
+ if (StrLen(a->ClientOption->Hostname) == 0)
+ {
+ return;
+ }
+ if (a->ClientOption->Port == 0)
+ {
+ return;
+ }
+ if (a->ClientOption->ProxyType != PROXY_DIRECT &&
+ (StrLen(a->ClientOption->ProxyName) == 0 ||
+ a->ClientOption->ProxyPort == 0))
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_HOSTNAME, server_name, sizeof(server_name));
+
+ if (StrCmpi(server_name, a->old_server_name) == 0)
+ {
+ if (CbNum(hWnd, C_HUBNAME) != 0)
+ {
+ return;
+ }
+ }
+ else
+ {
+ StrCpy(a->old_server_name, sizeof(a->old_server_name), server_name);
+ CbReset(hWnd, C_HUBNAME);
+ }
+
+ old_proxy_type = a->ClientOption->ProxyType;
+
+ if (IsChecked(hWnd, R_DIRECT_TCP))
+ {
+ a->ClientOption->ProxyType = PROXY_DIRECT;
+ }
+ if (IsChecked(hWnd, R_HTTPS))
+ {
+ a->ClientOption->ProxyType = PROXY_HTTP;
+ }
+ if (IsChecked(hWnd, R_SOCKS))
+ {
+ a->ClientOption->ProxyType = PROXY_SOCKS;
+ }
+
+ CmEnumHubStart(hWnd, a->ClientOption);
+
+ a->ClientOption->ProxyType = old_proxy_type;
+}
+
+// [OK] button
+void CmEditAccountDlgOnOk(HWND hWnd, CM_ACCOUNT *a)
+{
+ RPC_CLIENT_CREATE_ACCOUNT c;
+ bool b;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+ if (a->ClientOption->NumRetry != 0 && a->ClientOption->RetryInterval < 5)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_RETRY_INTERVAL_ERROR"));
+ FocusEx(hWnd, E_RETRY_SPAN);
+ return;
+ }
+
+ CmEditAccountDlgUpdate(hWnd, a);
+
+ if (a->LinkMode == false && a->NatMode == false)
+ {
+ // Save the account
+ Zero(&c, sizeof(c));
+ c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+ c.ClientAuth = CopyClientAuth(a->ClientAuth);
+ c.CheckServerCert = a->CheckServerCert;
+ if (a->ServerCert != NULL)
+ {
+ c.ServerCert = CloneX(a->ServerCert);
+ }
+ c.StartupAccount = a->Startup;
+
+ if (a->EditMode == false)
+ {
+ b = CALL(hWnd, CcCreateAccount(cm->Client, &c));
+ }
+ else
+ {
+ b = CALL(hWnd, CcSetAccount(cm->Client, &c));
+ }
+
+ CiFreeClientCreateAccount(&c);
+
+ // Check whether this account is currently running
+ if (b)
+ {
+ RPC_CLIENT_GET_CONNECTION_STATUS st;
+ Zero(&st, sizeof(st));
+ UniStrCpy(st.AccountName, sizeof(st.AccountName), a->ClientOption->AccountName);
+ if (CALL(hWnd, CcGetAccountStatus(cm->Client, &st)))
+ {
+ if (st.Active)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_CURRENT_ACTIVE"),
+ st.AccountName);
+ }
+ }
+ }
+
+ if (b)
+ {
+ EndDialog(hWnd, true);
+ }
+ }
+ else
+ {
+ if (a->LinkMode)
+ {
+ // Link mode
+ RPC_CREATE_LINK t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), a->Hub->HubName);
+ t.Online = a->OnlineFlag;
+ Copy(&t.Policy, &a->Policy, sizeof(POLICY));
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+ t.ClientAuth = CopyClientAuth(a->ClientAuth);
+ t.CheckServerCert = a->CheckServerCert;
+ t.ServerCert = CloneX(a->ServerCert);
+
+ // Save the settings for cascade connection
+ if (a->EditMode)
+ {
+ if (CALL(hWnd, ScSetLink(a->Hub->Rpc, &t)))
+ {
+ if (a->OnlineFlag)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_LINK_SAVE_ONLINE"), a->ClientOption->AccountName);
+ }
+ EndDialog(hWnd, true);
+ }
+ }
+ else
+ {
+ if (CALL(hWnd, ScCreateLink(a->Hub->Rpc, &t)))
+ {
+ if (a->Link_ConnectNow)
+ {
+ RPC_LINK tt;
+
+ Zero(&tt, sizeof(tt));
+ UniStrCpy(tt.AccountName, sizeof(tt.AccountName), a->ClientOption->AccountName);
+ StrCpy(tt.HubName, sizeof(tt.HubName), a->Hub->HubName);
+
+ CALL(hWnd, ScSetLinkOnline(a->Hub->Rpc, &tt));
+ }
+ EndDialog(hWnd, true);
+ }
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+ else
+ {
+ // NAT mode
+ RPC_CREATE_LINK t;
+ Zero(&t, sizeof(t));
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+ t.ClientAuth = CopyClientAuth(a->ClientAuth);
+
+ if (CALL(hWnd, NcSetClientConfig(a->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+ }
+}
+
+// Show the account editing dialog
+bool CmEditAccountDlg(HWND hWnd, CM_ACCOUNT *a)
+{
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_CM_ACCOUNT, CmEditAccountDlgProc, a);
+}
+
+// Edit the account
+void CmEditAccount(HWND hWnd, wchar_t *account_name)
+{
+ CM_ACCOUNT *a;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ a = CmGetExistAccountObject(hWnd, account_name);
+ if (a == NULL)
+ {
+ return;
+ }
+
+ CmVoice("input_config");
+ if (CmEditAccountDlg(hWnd, a))
+ {
+ CmVoice("set_config");
+ }
+
+ CmFreeAccountObject(hWnd, a);
+}
+
+// Create an account
+void CmNewAccount(HWND hWnd)
+{
+ CM_ACCOUNT *a;
+ RPC_CLIENT_ENUM_VLAN t;
+ UINT num_vlan = 0;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsEnable(hWnd, 0) == false)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CcEnumVLan(cm->Client, &t) == ERR_NO_ERROR)
+ {
+ num_vlan = t.NumItem;
+
+ CiFreeClientEnumVLan(&t);
+ }
+
+ if (num_vlan == 0)
+ {
+ if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN")) == IDNO)
+ {
+ return;
+ }
+ else
+ {
+ if (cm->server_name == NULL)
+ {
+ Command(hWnd, CMD_NEW_VLAN);
+ return;
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));
+ }
+ return;
+ }
+ }
+
+ a = CmCreateNewAccountObject(hWnd);
+ if (a == NULL)
+ {
+ return;
+ }
+
+ CmVoice("input_config");
+ if (CmEditAccountDlg(hWnd, a))
+ {
+ CmVoice("new_config");
+ }
+
+ CmFreeAccountObject(hWnd, a);
+}
+
+// Release the account object
+void CmFreeAccountObject(HWND hWnd, CM_ACCOUNT *a)
+{
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ Free(a->ClientOption);
+ CiFreeClientAuth(a->ClientAuth);
+ if (a->ServerCert != NULL)
+ {
+ FreeX(a->ServerCert);
+ }
+ Free(a);
+}
+
+// Get an existing account object
+CM_ACCOUNT *CmGetExistAccountObject(HWND hWnd, wchar_t *account_name)
+{
+ RPC_CLIENT_GET_ACCOUNT c;
+ CM_ACCOUNT *a;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
+ if (CALL(hWnd, CcGetAccount(cm->Client, &c)) == false)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(CM_ACCOUNT));
+ a->EditMode = true;
+ a->CheckServerCert = c.CheckServerCert;
+ a->Startup = c.StartupAccount;
+ if (c.ServerCert != NULL)
+ {
+ a->ServerCert = CloneX(c.ServerCert);
+ }
+ a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(a->ClientOption, c.ClientOption, sizeof(CLIENT_OPTION));
+ a->ClientAuth = CopyClientAuth(c.ClientAuth);
+ Copy(a->ShortcutKey, c.ShortcutKey, SHA1_SIZE);
+ CiFreeClientGetAccount(&c);
+
+ a->LockMode = cm->CmSetting.LockMode;
+
+ return a;
+}
+
+// Create a new account object
+CM_ACCOUNT *CmCreateNewAccountObject(HWND hWnd)
+{
+ CM_ACCOUNT *a;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(CM_ACCOUNT));
+ a->EditMode = false;
+ a->CheckServerCert = false;
+ a->Startup = false;
+ a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+
+ // Initialize the client options
+ CmGenerateNewAccountName(hWnd, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));
+ a->ClientOption->Port = 443; // Default port number
+ a->ClientOption->NumRetry = INFINITE;
+ a->ClientOption->RetryInterval = 15;
+ a->ClientOption->MaxConnection = 1;
+ a->ClientOption->HalfConnection = false;
+ a->ClientOption->UseEncrypt = true;
+ a->ClientOption->AdditionalConnectionInterval = 1;
+
+ if (cm->Client->Unix)
+ {
+ a->ClientOption->NoRoutingTracking = true;
+ }
+
+ a->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+
+ // Password authentication
+ a->ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
+
+ return a;
+}
+
+// Create an imported account name
+void CmGenerateImportName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ for (i = 1;;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ if (i == 1)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_1"), old_name);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_2"), old_name, i);
+ }
+
+ if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
+ {
+ UniStrCpy(name, size, tmp);
+ return;
+ }
+ }
+}
+
+// Create a copy name
+void CmGenerateCopyName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ for (i = 1;;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ if (i == 1)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_COPY_NAME_1"), old_name);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_COPY_NAME_2"), i, old_name);
+ }
+
+ if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
+ {
+ UniStrCpy(name, size, tmp);
+ return;
+ }
+ }
+}
+
+// Create a new account name
+void CmGenerateNewAccountName(HWND hWnd, wchar_t *name, UINT size)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ for (i = 1;;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ if (i == 1)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_1"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_2"), i);
+ }
+
+ if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
+ {
+ UniStrCpy(name, size, tmp);
+ return;
+ }
+ }
+}
+
+// Show the policy list
+void CmPolicyDlgPrint(HWND hWnd, CM_POLICY *p)
+{
+ CmPolicyDlgPrintEx(hWnd, p, false);
+}
+void CmPolicyDlgPrintEx(HWND hWnd, CM_POLICY *p, bool cascade_mode)
+{
+ CmPolicyDlgPrintEx2(hWnd, p, cascade_mode, POLICY_CURRENT_VERSION);
+}
+void CmPolicyDlgPrintEx2(HWND hWnd, CM_POLICY *p, bool cascade_mode, UINT ver)
+{
+ POLICY *pol;
+ UINT i;
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ pol = p->Policy;
+
+ b = LvInsertStart();
+
+ for (i = 0;i < NUM_POLICY_ITEM;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ if (cascade_mode)
+ {
+ if (PolicyIsSupportedForCascade(i) == false)
+ {
+ continue;
+ }
+ }
+
+ if (IS_POLICY_FOR_CURRENT_VER(i, ver))
+ {
+ if (policy_item[i].TypeInt == false)
+ {
+ // bool type
+ UniStrCpy(tmp, sizeof(tmp), POLICY_BOOL(pol, i) ? _UU("POL_BOOL_ENABLE") : (p->Extension ? _UU("POL_BOOL_DISABLE_EX") : _UU("POL_BOOL_DISABLE")));
+ }
+ else
+ {
+ // int type
+ if (policy_item[i].AllowZero && POLICY_INT(pol, i) == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("POL_INT_ZERO"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU(policy_item[i].FormatStr), POLICY_INT(pol, i));
+ }
+ }
+
+ LvInsertAdd(b, ICO_MACHINE, (void *)i, 2, GetPolicyTitle(i), tmp);
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_POLICY);
+}
+
+// Policy list dialog box
+UINT CmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CM_POLICY *p = (CM_POLICY *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, 0, p->AccountName);
+ FormatText(hWnd, S_TITLE, p->AccountName);
+ p->hWnd = hWnd;
+ if (p->CmStatus != NULL)
+ {
+ p->CmStatus->hWndPolicy = hWnd;
+ }
+
+ // Initialize the column
+ LvInit(hWnd, L_POLICY);
+ LvInsertColumn(hWnd, L_POLICY, 0, _UU("POL_TITLE_STR"), 375);
+ LvInsertColumn(hWnd, L_POLICY, 1, _UU("POL_VALUE_STR"), 100);
+
+ // Display
+ CmPolicyDlgPrint(hWnd, p);
+
+ // Select the first
+ LvSelect(hWnd, L_POLICY, 0);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_POLICY:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ // Change selection
+ if (LvIsSelected(hWnd, L_POLICY) == false)
+ {
+ SetText(hWnd, S_DESCRIPTION, L"");
+ }
+ else
+ {
+ UINT index = LvGetSelected(hWnd, L_POLICY);
+ UINT id = (UINT)LvGetParam(hWnd, L_POLICY, index);
+ if (id < NUM_POLICY_ITEM)
+ {
+ SetText(hWnd, S_DESCRIPTION, GetPolicyDescription(id));
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, L_POLICY);
+
+ return 0;
+}
+
+// Show the policy list dialog
+void CmPolicyDlg(HWND hWnd, CM_STATUS *st)
+{
+ RPC_CLIENT_GET_CONNECTION_STATUS s;
+ POLICY *policy;
+ CM_POLICY cp;
+ // Validate arguments
+ if (hWnd == NULL || st == NULL)
+ {
+ return;
+ }
+
+ // Get the policy
+ Zero(&s, sizeof(s));
+ UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);
+ if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
+ {
+ return;
+ }
+ if (s.Active == false)
+ {
+ return;
+ }
+
+ policy = &s.Policy;
+
+ Zero(&cp, sizeof(cp));
+ UniStrCpy(cp.AccountName, sizeof(cp.AccountName), st->AccountName);
+ cp.Policy = policy;
+ cp.CmStatus = st;
+
+ Dialog(hWnd, D_CM_POLICY, CmPolicyDlgProc, &cp);
+
+ st->hWndPolicy = NULL;
+
+ CiFreeClientGetConnectionStatus(&s);
+}
+
+// Show the certificate
+void CmStatusDlgPrintCert(HWND hWnd, CM_STATUS *st, bool server)
+{
+ RPC_CLIENT_GET_CONNECTION_STATUS s;
+ X *x, *issuer;
+ // Validate arguments
+ if (hWnd == NULL || st == NULL)
+ {
+ return;
+ }
+
+ // Get the latest information
+ Zero(&s, sizeof(s));
+ UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);
+ if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ if (s.Active == false)
+ {
+ // Disconnect
+ Close(hWnd);
+ return;
+ }
+
+ if (server == false)
+ {
+ // Show the client certificate
+ x = s.ClientX;
+ }
+ else
+ {
+ // Show the server certificate
+ x = s.ServerX;
+ }
+
+ cm->WindowCount++;
+ issuer = CmGetIssuer(x);
+ CertDlg(hWnd, x, issuer, true);
+ FreeX(issuer);
+ cm->WindowCount--;
+
+ CiFreeClientGetConnectionStatus(&s);
+}
+
+// Show the information of the status dialog
+void CmStatusDlgPrint(HWND hWnd, CM_STATUS *cmst)
+{
+ RPC_CLIENT_GET_CONNECTION_STATUS s;
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || cmst == NULL)
+ {
+ return;
+ }
+
+ // Get the latest information
+ Zero(&s, sizeof(s));
+ UniStrCpy(s.AccountName, sizeof(s.AccountName), cmst->AccountName);
+ if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ if (s.Active == false)
+ {
+ // Disconnect
+ Close(hWnd);
+ return;
+ }
+
+ // Show the status in the list box in the status dialog
+ b = LvInsertStart();
+ CmPrintStatusToListView(b, &s);
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ LvAutoSize(hWnd, L_STATUS);
+
+ SetEnable(hWnd, B_POLICY, s.Connected);
+
+ SetEnable(hWnd, B_SERVER_CERT, s.ServerX != NULL);
+ SetEnable(hWnd, B_CLIENT_CERT, s.ClientX != NULL);
+
+ CiFreeClientGetConnectionStatus(&s);
+}
+
+// Show the status in the list box in the status dialog
+void CmPrintStatusToListView(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s)
+{
+ CmPrintStatusToListViewEx(b, s, false);
+}
+void CmPrintStatusToListViewEx(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode)
+{
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ char vv[128];
+ // Validate arguments
+ if (b == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (server_mode == false)
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_ACCOUNT_NAME"), s->AccountName);
+
+ if (s->Connected == false)
+ {
+ wchar_t *st = _UU("CM_ST_CONNECTED_FALSE");
+ switch (s->SessionStatus)
+ {
+ case CLIENT_STATUS_CONNECTING:
+ st = _UU("CM_ST_CONNECTING");
+ break;
+ case CLIENT_STATUS_NEGOTIATION:
+ st = _UU("CM_ST_NEGOTIATION");
+ break;
+ case CLIENT_STATUS_AUTH:
+ st = _UU("CM_ST_AUTH");
+ break;
+ case CLIENT_STATUS_ESTABLISHED:
+ st = _UU("CM_ST_ESTABLISHED");
+ break;
+ case CLIENT_STATUS_RETRY:
+ st = _UU("CM_ST_RETRY");
+ break;
+ case CLIENT_STATUS_IDLE:
+ st = _UU("CM_ST_IDLE");
+ break;
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), st);
+ }
+ else
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), _UU("CM_ST_CONNECTED_TRUE"));
+ }
+ }
+
+ if (s->Connected)
+ {
+ if (s->VLanId == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_NO_VLAN"));
+ }
+ else
+ {
+ UniToStru(tmp, s->VLanId);
+ }
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_VLAN_ID"), tmp);
+
+ if (server_mode == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->ServerName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), s->ServerPort);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_PORT"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), s->ServerProductName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", s->ServerProductVer / 100, s->ServerProductVer % 100);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_VER"), tmp);
+ UniFormat(tmp, sizeof(tmp), L"Build %u", s->ServerProductBuild);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_BUILD"), tmp);
+ }
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->StartTime), NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_START_TIME"), tmp);
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->FirstConnectionEstablisiedTime), NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_FIRST_ESTAB_TIME"), s->FirstConnectionEstablisiedTime == 0 ? _UU("CM_ST_NONE") : tmp);
+
+ if (s->Connected)
+ {
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->CurrentConnectionEstablishTime), NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CURR_ESTAB_TIME"), tmp);
+ }
+
+ if (server_mode == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_STR"), s->NumConnectionsEatablished);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_ESTABLISHED"), tmp);
+ }
+
+ if (s->Connected)
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_HALF_CONNECTION"), s->HalfConnection ? _UU("CM_ST_HALF_TRUE") : _UU("CM_ST_HALF_FALSE"));
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_QOS"), s->QoS ? _UU("CM_ST_QOS_TRUE") : _UU("CM_ST_QOS_FALSE"));
+
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnections);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP"), tmp);
+
+ if (s->HalfConnection)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsUpload);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_UPLOAD"), tmp);
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsDownload);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_DOWNLOAD"), tmp);
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%u", s->MaxTcpConnections);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MAX_TCP"), tmp);
+
+ if (s->UseEncrypt == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_FALSE"));
+ }
+ else
+ {
+ if (StrLen(s->CipherName) != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE"), s->CipherName);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE2"));
+ }
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_ENCRYPT"), tmp);
+
+ if (s->UseCompress)
+ {
+ UINT percent = 0;
+ if ((s->TotalRecvSize + s->TotalSendSize) > 0)
+ {
+ percent = (UINT)((UINT64)100 - (UINT64)(s->TotalRecvSizeReal + s->TotalSendSizeReal) * (UINT64)100 /
+ (s->TotalRecvSize + s->TotalSendSize));
+ percent = MAKESURE(percent, 0, 100);
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_TRUE"), percent);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_FALSE"));
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_COMPRESS"), tmp);
+
+ if (IsEmptyStr(s->UnderlayProtocol) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->UnderlayProtocol);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UNDERLAY_PROTOCOL"), tmp);
+ }
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_ENABLED"), (s->IsUdpAccelerationEnabled ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_USING"), (s->IsUsingUdpAcceleration ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
+
+ StrToUni(tmp, sizeof(tmp), s->SessionName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), s->ConnectionName);
+ if (UniStrCmpi(tmp, L"INITING") != 0)
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTION_NAME"), tmp);
+ }
+
+ BinToStr(str, sizeof(str), s->SessionKey, sizeof(s->SessionKey));
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_KEY"), tmp);
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_BRIDGE_MODE"), s->IsBridgeMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MONITOR_MODE"), s->IsMonitorMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
+
+ ToStr3(vv, sizeof(vv), s->TotalSendSize);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->TotalRecvSize);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_SIZE"), tmp);
+ }
+}
+
+// Status dialog procedure
+UINT CmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ wchar_t tmp[MAX_SIZE];
+ CM_STATUS *s = (CM_STATUS *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_TOWER);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), s->AccountName);
+ SetText(hWnd, 0, tmp);
+ FormatText(hWnd, S_TITLE, s->AccountName);
+ DlgFont(hWnd, S_TITLE, 0, 1);
+
+ Add(cm->StatusWindowList, hWnd);
+
+ SetTimer(hWnd, 1, 500, NULL);
+
+ LvInitEx(hWnd, L_STATUS, true);
+ ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_NORMAL);
+ ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_SMALL);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("CM_ST_COLUMN_1"), 160);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("CM_ST_COLUMN_2"), 270);
+
+ CmStatusDlgPrint(hWnd, s);
+
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ CmStatusDlgPrint(hWnd, s);
+ SetTimer(hWnd, 1, 500, NULL);
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ // Close
+ Close(hWnd);
+ break;
+ case B_POLICY:
+ // Show the policy
+ CmPolicyDlg(hWnd, s);
+ break;
+ case B_SERVER_CERT:
+ CmStatusDlgPrintCert(hWnd, s, true);
+ break;
+ case B_CLIENT_CERT:
+ CmStatusDlgPrintCert(hWnd, s, false);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ Delete(cm->StatusWindowList, hWnd);
+ if (s->hWndPolicy != NULL)
+ {
+ EndDialog(s->hWndPolicy, false);
+ s->hWndPolicy = NULL;
+ }
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the status dialog
+void CmStatusDlg(HWND hWnd, wchar_t *account_name)
+{
+ CM_STATUS *s;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ s = ZeroMalloc(sizeof(CM_STATUS));
+ UniStrCpy(s->AccountName, sizeof(s->AccountName), account_name);
+
+ Dialog(hWnd, D_CONNECTION_STATUS, CmStatusDlgProc, s);
+
+ Free(s);
+}
+
+// Show the status
+void CmStatus(HWND hWnd, wchar_t *account_name)
+{
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), account_name);
+
+ for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)
+ {
+ HWND h = LIST_DATA(cm->StatusWindowList, i);
+ if (h != NULL)
+ {
+ wchar_t tmp2[MAX_SIZE];
+ if (GetTxt(h, 0, tmp2, sizeof(tmp2)))
+ {
+ if (UniStrCmpi(tmp2, tmp) == 0)
+ {
+ SetActiveWindow(h);
+ return;
+ }
+ }
+ }
+ }
+
+ CmStatusDlg(hWnd, account_name);
+}
+
+// Delete
+void CmDeleteAccount(HWND hWnd, wchar_t *account_name)
+{
+ RPC_CLIENT_DELETE_ACCOUNT c;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
+
+ CmVoice("delete_config_1");
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_ACCOUNT_MSG"), account_name)
+ == IDNO)
+ {
+ return;
+ }
+
+ CALL(hWnd, CcDeleteAccount(cm->Client, &c));
+ CmVoice("delete_config_2");
+}
+
+// Disconnect
+void CmDisconnect(HWND hWnd, wchar_t *account_name)
+{
+ RPC_CLIENT_CONNECT c;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
+
+ cm->PositiveDisconnectFlag = true;
+
+ CALL(hWnd, CcDisconnect(cm->Client, &c));
+}
+
+// Show the promotional window
+void SmShowPublicVpnServerHtml(HWND hWnd)
+{
+ char *langstr = _SS("LANGSTR");
+
+ if(StrCmpi(langstr, "Japanese") == 0)
+ {
+ ShowHtml(hWnd, PUBLIC_SERVER_HTML, PUBLIC_SERVER_TAG);
+ }
+ else
+ {
+ ShowHtml(hWnd, PUBLIC_SERVER_HTML_EN, PUBLIC_SERVER_TAG);
+ }
+}
+
+// Connection
+void CmConnect(HWND hWnd, wchar_t *account_name)
+{
+ RPC_CLIENT_CONNECT c;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || account_name == NULL)
+ {
+ return;
+ }
+
+ if (IsEnable(hWnd, 0) == false)
+ {
+ return;
+ }
+
+ if (hWnd == cm->hMainWnd)
+ {
+ if (LvNum(hWnd, L_VLAN) == 0 && cm->Client->Win9x)
+ {
+ if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN_2")) == IDNO)
+ {
+ return;
+ }
+ else
+ {
+ if (cm->server_name == NULL || cm->Client->Unix)
+ {
+ Command(hWnd, CMD_NEW_VLAN);
+ return;
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));
+ }
+ return;
+ }
+ }
+ }
+
+ // (If necessary) display a warning
+ if (CmWarningDesktop(hWnd, account_name) == false)
+ {
+ return;
+ }
+
+ if (cm->server_name == NULL)
+ {
+ if (cm->BadProcessChecked == false)
+ {
+ cm->BadProcessChecked = true;
+
+ CheckBadProcesses(hWnd);
+ }
+ }
+
+ if (cm->server_name == NULL)
+ {
+ // Check the Windows version
+ RPC_WINVER winver;
+ wchar_t winver_msg_client[3800];
+
+ GetWinVer(&winver);
+ Zero(winver_msg_client, sizeof(winver_msg_client));
+
+ if (IsSupportedWinVer(&winver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ winver.Title,
+ _UU("WINVER_ERROR_VPNCLIENT"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ _UU("WINVER_ERROR_VPNCLIENT"),
+ _UU("WINVER_ERROR_VPNCLIENT"),
+ _UU("WINVER_ERROR_VPNCLIENT"),
+ st.wYear, st.wMonth);
+ }
+
+ if (UniIsEmptyStr(winver_msg_client) == false)
+ {
+ OnceMsgEx(hWnd, _UU("WINVER_TITLE"), winver_msg_client,
+ true, ICO_WARNING, NULL);
+ }
+ }
+
+ i = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);
+ if (i != INFINITE)
+ {
+ wchar_t *tmp = LvGetStr(hWnd, L_ACCOUNT, i, 2);
+ if (tmp != NULL)
+ {
+ wchar_t tag[MAX_SIZE];
+ StrToUni(tag, sizeof(tag), PUBLIC_SERVER_NAME);
+
+ if (UniSearchStrEx(tmp, tag, 0, false) != INFINITE)
+ {
+ SmShowPublicVpnServerHtml(hWnd);
+ }
+
+ Free(tmp);
+ }
+ }
+
+ if (cm->CheckedAndShowedAdminPackMessage == false)
+ {
+ cm->CheckedAndShowedAdminPackMessage = true;
+ //CmCheckAndShowAdminPackTrialVersionNoticeMessage(NULL);
+ }
+
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
+
+ CmSetForegroundProcessToCnService();
+
+ if (CALL(hWnd, CcConnect(cm->Client, &c)))
+ {
+ cm->ConnectStartedFlag = true;
+ }
+}
+
+// Determine whether to bold the specified menu item
+bool CmIsBold(UINT id)
+{
+ return false;
+}
+
+// Determine whether to enable the specified menu item
+bool CmIsEnabled(HWND hWnd, UINT id)
+{
+ UINT index;
+ wchar_t *name;
+ bool locked = false;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ locked = cm->CmSetting.LockMode;
+
+ if (locked)
+ {
+ switch (id)
+ {
+ case CMD_NEW:
+ case CMD_CLONE:
+ case CMD_IMPORT_ACCOUNT:
+ case CMD_DELETE:
+ case CMD_OPTION:
+ case CMD_VOIDE_NONE:
+ case CMD_VOICE_NORMAL:
+ case CMD_VOICE_ODD:
+ case CMD_STARTUP:
+ case CMD_NOSTARTUP:
+ case CMD_TRAFFIC:
+ case CMD_MMCSS:
+ return false;
+ case CMD_NEW_VLAN:
+ case CMD_ENABLE_VLAN:
+ case CMD_DISABLE_VLAN:
+ case CMD_DELETE_VLAN:
+ case CMD_REINSTALL:
+ case CMD_WINNET:
+ if (cm->CmEasyModeSupported)
+ {
+ return false;
+ }
+ }
+ }
+
+ switch (id)
+ {
+ case CMD_LANGUAGE:
+ return MsIsNt();
+ case CMD_SHOWPORT:
+ case CMD_GRID:
+ if (cm->IconView)
+ {
+ return false;
+ }
+ return true;
+ case CMD_MMCSS:
+ if (MsIsVista() == false || IsEmptyStr(cm->server_name) == false)
+ {
+ return false;
+ }
+ if (OS_IS_SERVER(GetOsType()))
+ {
+ return false;
+ }
+ return true;
+ case CMD_TRAYICON:
+ case CMD_TRAFFIC:
+ return (cm->server_name == NULL);
+ case CMD_NETIF:
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+ return (cm->server_name == NULL);
+ case CMD_CM_SETTING:
+ return cm->CmSettingSupported;
+ case CMD_CONNECT:
+ case CMD_DISCONNECT:
+ case CMD_STATUS:
+ case CMD_RENAME:
+ case CMD_DELETE:
+ if (LvIsMultiMasked(hWnd, L_ACCOUNT))
+ {
+ return false;
+ }
+ if (LvIsSelected(hWnd, L_ACCOUNT) == false)
+ {
+ return false;
+ }
+ else
+ {
+ // Determine whether the selected account is under connecting
+ UINT i = LvGetSelected(hWnd, L_ACCOUNT);
+ wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+ wchar_t *name = LvGetStr(hWnd, L_ACCOUNT, i, 0);
+ bool is_connected = false;
+ if (str != NULL)
+ {
+ if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ is_connected = true;
+ }
+ Free(str);
+ }
+ if (name != NULL)
+ {
+ if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0)
+ {
+ Free(name);
+ return false;
+ }
+ Free(name);
+ }
+ if (id == CMD_CONNECT || id == CMD_RENAME || id == CMD_DELETE)
+ {
+ return !is_connected;
+ }
+ else
+ {
+ return is_connected;
+ }
+ }
+ break;
+ case CMD_DISCONNECT_ALL:
+ if (CmGetNumConnected(hWnd) == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ case CMD_SHORTCUT:
+ // Create a shortcut
+ if (cm->Client->Rpc->Sock->RemoteIP.addr[0] != 127)
+ {
+ return false;
+ }
+ case CMD_EXPORT_ACCOUNT:
+ if (LvIsMultiMasked(hWnd, L_ACCOUNT))
+ {
+ return false;
+ }
+ name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (name != NULL)
+ {
+ if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
+ )
+ {
+ Free(name);
+ return false;
+ }
+ Free(name);
+ }
+ return LvIsSelected(hWnd, L_ACCOUNT);
+ case CMD_CLONE:
+ if (LvIsMultiMasked(hWnd, L_ACCOUNT))
+ {
+ return false;
+ }
+ name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (name != NULL)
+ {
+ if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
+ )
+ {
+ Free(name);
+ return false;
+ }
+ Free(name);
+ }
+ return LvIsSelected(hWnd, L_ACCOUNT);
+ case CMD_STARTUP:
+ case CMD_NOSTARTUP:
+ name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (name != NULL)
+ {
+ if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
+ )
+ {
+ Free(name);
+ return false;
+ }
+ Free(name);
+ }
+ if (LvIsMultiMasked(hWnd, L_ACCOUNT))
+ {
+ return false;
+ }
+ if (LvIsSelected(hWnd, L_ACCOUNT) == false)
+ {
+ return false;
+ }
+ else
+ {
+ // Determine whether the selected account is a startup account
+ UINT i = LvGetSelected(hWnd, L_ACCOUNT);
+ bool is_startup = (bool)LvGetParam(hWnd, L_ACCOUNT, i);
+ if (id == CMD_STARTUP)
+ {
+ return !is_startup;
+ }
+ else
+ {
+ return is_startup;
+ }
+ }
+ break;
+ case CMD_NEW_VLAN:
+ if (cm->Client->Unix == false && cm->Client->Win9x == false)
+ {
+ if (cm->server_name != NULL)
+ {
+ return false;
+ }
+ }
+ if (cm->Client->Win9x)
+ {
+ if (LvNum(hWnd, L_VLAN) >= 1)
+ {
+ // You can not install two or more virtual LAN cards in Win9x
+ return false;
+ }
+ }
+ break;
+ case CMD_PROPERTY:
+ name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
+ if (name != NULL)
+ {
+ if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0)
+ {
+ Free(name);
+ return false;
+ }
+ Free(name);
+ }
+ if (LvIsMultiMasked(hWnd, L_ACCOUNT))
+ {
+ return false;
+ }
+ return LvIsSelected(hWnd, L_ACCOUNT);
+ case CMD_DELETE_VLAN:
+ if (LvIsMultiMasked(hWnd, L_VLAN))
+ {
+ return false;
+ }
+ return LvIsSelected(hWnd, L_VLAN);
+ case CMD_ENABLE_VLAN:
+ if (cm->Client->Win9x)
+ {
+ return false;
+ }
+ if (LvIsMultiMasked(hWnd, L_VLAN))
+ {
+ return false;
+ }
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index == INFINITE)
+ {
+ return false;
+ }
+ else
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, _UU("CM_VLAN_DISABLED")) == 0)
+ {
+ Free(s);
+ return true;
+ }
+ Free(s);
+ }
+ return false;
+ }
+ break;
+ case CMD_DISABLE_VLAN:
+ if (cm->Client->Win9x)
+ {
+ return false;
+ }
+ if (LvIsMultiMasked(hWnd, L_VLAN))
+ {
+ return false;
+ }
+ index = LvGetSelected(hWnd, L_VLAN);
+ if (index == INFINITE)
+ {
+ return false;
+ }
+ else
+ {
+ wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, _UU("CM_VLAN_ENABLED")) == 0)
+ {
+ Free(s);
+ return true;
+ }
+ Free(s);
+ }
+ return false;
+ }
+ break;
+ case CMD_REINSTALL:
+ if (cm->server_name != NULL)
+ {
+ return false;
+ }
+ if (cm->Client->Win9x || cm->Client->Unix)
+ {
+ // Upgrading the virtual LAN card on a UNIX system or Win9x is unavailable
+ return false;
+ }
+ if (LvIsMultiMasked(hWnd, L_VLAN))
+ {
+ return false;
+ }
+ return LvIsSelected(hWnd, L_VLAN);
+ case CMD_WINNET:
+ {
+ UINT os_type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS_NT(os_type) && GET_KETA(os_type, 100) >= 2)
+ {
+ if (cm->server_name != NULL)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ break;
+ case CMD_EXIT:
+ return cm->TrayInited;
+ }
+ return true;
+}
+
+// Convert a VLAN device name to the display name
+void CmVLanNameToPrintName(char *str, UINT size, char *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, VLAN_ADAPTER_NAME_TAG, name);
+}
+
+// Convert a display name to a VLAN device name
+bool CmPrintNameToVLanName(char *name, UINT size, char *str)
+{
+ // Validate arguments
+ if (name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (StartWith(str, VLAN_ADAPTER_NAME))
+ {
+ if (StrLen(str) < (StrLen(VLAN_ADAPTER_NAME) + 3))
+ {
+ return false;
+ }
+
+ StrCpy(name, size, str + StrLen(VLAN_ADAPTER_NAME) + 3);
+
+ return true;
+ }
+
+ if (StartWith(str, VLAN_ADAPTER_NAME_OLD))
+ {
+ if (StrLen(str) < (StrLen(VLAN_ADAPTER_NAME_OLD) + 3))
+ {
+ return false;
+ }
+
+ StrCpy(name, size, str + StrLen(VLAN_ADAPTER_NAME_OLD) + 3);
+
+ return true;
+ }
+
+ return false;
+}
+
+// Initialize the account list
+void CmInitAccountList(HWND hWnd)
+{
+ CmInitAccountListEx(hWnd, false);
+}
+void CmInitAccountListEx(HWND hWnd, bool easy)
+{
+ UINT width[5];
+ BUF *b;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Read the setting
+ b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth");
+ if ((b != NULL) && (b->Size == sizeof(width)))
+ {
+ Copy(width, b->Buf, sizeof(width));
+ }
+ else if ((b != NULL) && (b->Size == (sizeof(width) - sizeof(UINT))))
+ {
+ // Migrating from previous versions
+ Zero(width, sizeof(width));
+ Copy(width, b->Buf, sizeof(width) - sizeof(UINT));
+ width[4] = width[3];
+ width[3] = 0;
+ }
+ else
+ {
+ Zero(width, sizeof(width));
+ }
+ FreeBuf(b);
+
+ LvInitEx2(hWnd, L_ACCOUNT, false, easy);
+
+// LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);
+
+ // Initialize the column
+ if (easy == false)
+ {
+ LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), width[0] == 0 ? 215 : width[0]);
+ LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), width[1] == 0 ? 80 : width[1]);
+ LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), width[2] == 0 ? 220 : width[2]);
+ LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), width[3] == 0 ? 90 : width[3]);
+ LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), (width[4] == 0 || width[4] == 250) ? 120 : width[4]);
+ }
+ else
+ {
+ LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), 345);
+ LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), 140);
+ LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), 0);
+ LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), 0);
+ LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), 0);
+ }
+}
+
+// Release the account list
+void CmSaveAccountListPos(HWND hWnd)
+{
+ UINT width[5];
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < 5;i++)
+ {
+ width[i] = LvGetColumnWidth(hWnd, L_ACCOUNT, i);
+ }
+
+ MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth", width, sizeof(width));
+}
+
+// Initialize the VLAN list
+void CmInitVLanList(HWND hWnd)
+{
+ UINT width[4];
+ BUF *b;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Read the setting
+ b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth");
+ if ((b != NULL) && (b->Size == sizeof(width)))
+ {
+ Copy(width, b->Buf, sizeof(width));
+ }
+ else
+ {
+ Zero(width, sizeof(width));
+ }
+ FreeBuf(b);
+
+ LvInit(hWnd, L_VLAN);
+
+// LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);
+
+ // Initialize the column
+ LvInsertColumn(hWnd, L_VLAN, 0, _UU("CM_VLAN_COLUMN_1"), width[0] == 0 ? 310 : width[0]);
+ LvInsertColumn(hWnd, L_VLAN, 1, _UU("CM_VLAN_COLUMN_2"), width[1] == 0 ? 120 : width[1]);
+ LvInsertColumn(hWnd, L_VLAN, 2, _UU("CM_VLAN_COLUMN_3"), width[2] == 0 ? 175 : width[2]);
+ LvInsertColumn(hWnd, L_VLAN, 3, _UU("CM_VLAN_COLUMN_4"), width[3] == 0 ? 120 : width[3]);
+}
+
+// Release the VLAN list
+void CmSaveVLanListPos(HWND hWnd)
+{
+ UINT width[4];
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < 4;i++)
+ {
+ width[i] = LvGetColumnWidth(hWnd, L_VLAN, i);
+ }
+
+ MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth", width, sizeof(width));
+}
+
+// Update the account list
+void CmRefreshAccountList(HWND hWnd)
+{
+ CmRefreshAccountListEx(hWnd, false);
+ CmRefreshEasy();
+}
+void CmRefreshAccountListEx(HWND hWnd, bool easy)
+{
+ CmRefreshAccountListEx2(hWnd, easy, false);
+}
+void CmRefreshAccountListEx2(HWND hWnd, bool easy, bool style_changed)
+{
+ UINT num = 0;
+ RPC_CLIENT_ENUM_ACCOUNT a;
+ UINT num_connecting = 0, num_connected = 0;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t new_inserted_item[MAX_ACCOUNT_NAME_LEN + 1];
+ bool select_new_insteted_item = true;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Switching of icon / detail view
+ LvSetView(hWnd, L_ACCOUNT, cm->IconView == false || easy);
+
+ // Show grid
+ if (cm->ShowGrid || easy)
+ {
+ LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);
+ }
+ else
+ {
+ LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);
+ }
+
+ if (style_changed)
+ {
+ // Change the font
+ if (easy == false)
+ {
+ if (cm->VistaStyle)
+ {
+ SetFontMeiryo(hWnd, L_ACCOUNT, 9);
+ }
+ else
+ {
+ SetFontDefault(hWnd, L_ACCOUNT);
+ }
+
+ if (cm->VistaStyle && (cm->IconView == false))
+ {
+ LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);
+ }
+ else
+ {
+ LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);
+ }
+ }
+ }
+
+ Zero(new_inserted_item, sizeof(new_inserted_item));
+
+ if (LvNum(hWnd, L_ACCOUNT) == 0)
+ {
+ select_new_insteted_item = false;
+ }
+
+ // Enumerate the account list
+ if (CALL(hWnd, CcEnumAccount(cm->Client, &a)))
+ {
+ UINT i;
+ LVB *b = LvInsertStart();
+
+ if (cm->CmSetting.LockMode == false && (easy == false))
+ {
+ // Creating a new connection
+ LvInsertAdd(b, ICO_NEW, NULL, 4, _UU("CM_NEW_ICON"), L"", L"", L"");
+
+ if (cm->Client->IsVgcSupported)
+ {
+ // VPN Gate
+ LvInsertAdd(b, ICO_RESEARCH, NULL, 4, _UU("CM_VGC_ICON"), L"", L"", L"");
+ }
+ else if (cm->Client->ShowVgcLink)
+ {
+ // VPN Gate Link
+ LvInsertAdd(b, ICO_INTERNET, NULL, 4, _UU("CM_VGC_LINK"), L"", L"", L"");
+ }
+ }
+
+ for (i = 0;i < a.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = a.Items[i];
+ UINT icon;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ IP ip;
+ char ip_str[MAX_SIZE];
+
+ // Special treatment in the case of IPv6 address
+ if (StrToIP6(&ip, t->ServerName) && StartWith(t->ServerName, "[") == false)
+ {
+ Format(ip_str, sizeof(ip_str),
+ "[%s]", t->ServerName);
+ }
+ else
+ {
+ StrCpy(ip_str, sizeof(ip_str), t->ServerName);
+ }
+
+ // Determine the icon
+ if (t->Active == false)
+ {
+ if (t->StartupAccount == false)
+ {
+ icon = ICO_SERVER_OFFLINE;
+ }
+ else
+ {
+ icon = ICO_SERVER_OFFLINE_EX;
+ }
+ }
+ else
+ {
+ num++;
+ if (t->StartupAccount == false)
+ {
+ icon = ICO_SERVER_ONLINE;
+ }
+ else
+ {
+ icon = ICO_SERVER_ONLINE_EX;
+ }
+ }
+
+ // Adding
+ if (easy == false)
+ {
+ //CmVLanNameToPrintName(tmp3, sizeof(tmp3), t->DeviceName);
+ StrCpy(tmp3, sizeof(tmp3), t->DeviceName);
+ StrToUni(tmp, sizeof(tmp), tmp3);
+ }
+ else
+ {
+ StrToUni(tmp, sizeof(tmp), t->DeviceName);
+ }
+
+ if (t->Port == 0 || cm->ShowPort == false)
+ {
+ // Port number is unknown
+ UniFormat(tmp2, sizeof(tmp2), L"%S (%s)", ip_str, CmGetProtocolName(t->ProxyType));
+ }
+ else
+ {
+ // Port number are also shown
+ UniFormat(tmp2, sizeof(tmp2), L"%S:%u (%s)", ip_str, t->Port, CmGetProtocolName(t->ProxyType));
+ }
+
+ if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->AccountName) == INFINITE)
+ {
+ UniStrCpy(new_inserted_item, sizeof(new_inserted_item), t->AccountName);
+ }
+
+ // Virtual HUB name
+ StrToUni(tmp4, sizeof(tmp4), t->HubName);
+
+ if (easy == false)
+ {
+ LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,
+ t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :
+ (t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),
+ tmp2, tmp4,
+ tmp);
+ }
+ else
+ {
+ LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,
+ t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :
+ (t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),
+ tmp2, tmp4,
+ tmp);
+ }
+
+ if (t->Active)
+ {
+ if (t->Connected)
+ {
+ num_connected++;
+ }
+ else
+ {
+ num_connecting++;
+ }
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_ACCOUNT);
+
+ CiFreeClientEnumAccount(&a);
+
+ if (select_new_insteted_item)
+ {
+ if (UniStrLen(new_inserted_item) >= 1)
+ {
+ LvSelect(hWnd, L_ACCOUNT, INFINITE);
+ LvSelect(hWnd, L_ACCOUNT, LvSearchStr(hWnd, L_ACCOUNT, 0, new_inserted_item));
+ }
+ }
+ }
+
+ if (easy == false)
+ {
+ // For voice guidance, detect new connection and connection lost
+ if (cm->UpdateConnectedNumFlag == false)
+ {
+ cm->UpdateConnectedNumFlag = true;
+ cm->OldConnectedNum = num;
+ }
+ else
+ {
+ if (cm->OldConnectedNum != num)
+ {
+ if (cm->OldConnectedNum < num)
+ {
+ CmVoice("connect");
+ }
+ else
+ {
+ CmVoice("disconnect");
+
+ if (cm->CmSetting.EasyMode && cm->PositiveDisconnectFlag == false)
+ {
+ CmShowEasy();
+ }
+
+ cm->PositiveDisconnectFlag = false;
+ }
+ cm->OldConnectedNum = num;
+ }
+ }
+
+ if (num_connecting == 0 && num_connected == 0)
+ {
+ // There is no connecting or connected account
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_TRAY_NOT_CONNECTED"));
+ }
+ else if (num_connected == 0)
+ {
+ // There is only connecting account
+ UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_1"), num_connecting);
+ }
+ else if (num_connecting == 0)
+ {
+ // There is only connected account
+ UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_2"), num_connected);
+ }
+ else
+ {
+ // There are both
+ UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_0"), num_connected, num_connecting);
+ }
+
+ if (num_connecting == 0 && num_connected == 0)
+ {
+ cm->TrayAnimation = false;
+ cm->TraySpeedAnimation = false;
+ }
+ else
+ {
+ cm->TrayAnimation = true;
+
+ if (num_connecting == 0)
+ {
+ cm->TraySpeedAnimation = false;
+ }
+ else
+ {
+ cm->TraySpeedAnimation = true;
+ }
+ }
+
+ CmChangeTrayString(hWnd, tmp);
+ }
+
+ Refresh(hWnd);
+
+ //Updated the Jump List
+ CmUpdateJumpList(0);
+}
+
+// Updating the VLAN list
+void CmRefreshVLanList(HWND hWnd)
+{
+ CmRefreshVLanListEx(hWnd, false);
+}
+void CmRefreshVLanListEx(HWND hWnd, bool style_changed)
+{
+ RPC_CLIENT_ENUM_VLAN e;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ LvSetView(hWnd, L_VLAN, cm->IconView == false);
+
+ // Show grid
+ if (cm->ShowGrid)
+ {
+ LvSetStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);
+ }
+ else
+ {
+ LvRemoveStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);
+ }
+
+ if (style_changed)
+ {
+ // Change the font
+ if (cm->VistaStyle)
+ {
+ SetFontMeiryo(hWnd, L_VLAN, 9);
+ }
+ else
+ {
+ SetFontDefault(hWnd, L_VLAN);
+ }
+
+ if (cm->VistaStyle && (cm->IconView == false))
+ {
+ LvSetStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);
+ }
+ else
+ {
+ LvRemoveStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);
+ }
+ }
+
+ // Enumeration
+ Zero(&e, sizeof(e));
+ if (CALL(hWnd, CcEnumVLan(cm->Client, &e)))
+ {
+ LVB *b = LvInsertStart();
+ UINT i;
+ for (i = 0;i < e.NumItem;i++)
+ {
+ wchar_t name[MAX_SIZE];
+ wchar_t mac[MAX_SIZE];
+ wchar_t ver[MAX_SIZE];
+ char str[MAX_SIZE];
+ wchar_t *status;
+ RPC_CLIENT_ENUM_VLAN_ITEM *v = e.Items[i];
+
+ // Device name
+ CmVLanNameToPrintName(str, sizeof(str), v->DeviceName);
+ StrToUni(name, sizeof(name), str);
+
+ // Status
+ status = v->Enabled ? _UU("CM_VLAN_ENABLED") : _UU("CM_VLAN_DISABLED");
+
+ // MAC address
+ StrToUni(mac, sizeof(mac), v->MacAddress);
+
+ // Version
+ StrToUni(ver, sizeof(ver), v->Version);
+
+ LvInsertAdd(b, v->Enabled ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE, NULL, 4,
+ name, status, mac, ver);
+ }
+ LvInsertEnd(b, hWnd, L_VLAN);
+
+ CiFreeClientEnumVLan(&e);
+ }
+}
+
+// Get a protocol name string
+wchar_t *CmGetProtocolName(UINT n)
+{
+ return GetProtocolName(n);
+}
+
+// Display update
+void CmRefresh(HWND hWnd)
+{
+ CmRefreshEx(hWnd, false);
+}
+void CmRefreshEx(HWND hWnd, bool style_changed)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Update size
+ CmMainWindowOnSize(hWnd);
+
+ // Updating the VLAN list
+ CmRefreshVLanListEx(hWnd, style_changed);
+
+ // Update the account list
+ CmRefreshAccountListEx2(hWnd, false, style_changed);
+
+ // Update the status bar
+ CmRefreshStatusBar(hWnd);
+}
+
+// Determine whether to check the specified menu item
+bool CmIsChecked(UINT id)
+{
+ switch (id)
+ {
+ case CMD_TRAYICON:
+ return cm->HideTrayIcon == false;
+ case CMD_STATUSBAR:
+ return cm->HideStatusBar == false;
+ case CMD_VISTASTYLE:
+ return cm->VistaStyle;
+ case CMD_ICON:
+ return cm->IconView;
+ case CMD_DETAIL:
+ return cm->IconView == false;
+ case CMD_GRID:
+ return cm->ShowGrid;
+ case CMD_VOIDE_NONE:
+ return cm->DisableVoice;
+ case CMD_SHOWPORT:
+ return cm->ShowPort;
+ case CMD_VOICE_NORMAL:
+ if (cm->DisableVoice)
+ {
+ return false;
+ }
+ else
+ {
+ return cm->VoiceId == VOICE_SSK;
+ }
+ case CMD_VOICE_ODD:
+ if (cm->DisableVoice)
+ {
+ return false;
+ }
+ else
+ {
+ return cm->VoiceId == VOICE_AHO;
+ }
+ }
+ return false;
+}
+
+// The menu popped-up
+void CmMainWindowOnPopupMenu(HWND hWnd, HMENU hMenu, UINT pos)
+{
+ UINT num_menu, i, id;
+ // Validate arguments
+ if (hWnd == NULL || hMenu == NULL)
+ {
+ return;
+ }
+
+ num_menu = GetMenuItemCount(hMenu);
+ for (i = 0;i < num_menu;i++)
+ {
+ id = GetMenuItemID(hMenu, i);
+
+ if (id != INFINITE)
+ {
+ bool enable_flag = CmIsEnabled(hWnd, id);
+ bool checked_flag = CmIsChecked(id);
+ bool bold_flag = CmIsBold(id);
+ MENUITEMINFO info;
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+ info.fState = (enable_flag ? MFS_ENABLED : MFS_DISABLED) |
+ (checked_flag ? MFS_CHECKED : MFS_UNCHECKED) |
+ (bold_flag ? MFS_DEFAULT : 0);
+
+ if (id == CMD_ICON || id == CMD_DETAIL || id == CMD_VOIDE_NONE ||
+ id == CMD_VOICE_NORMAL || id == CMD_VOICE_ODD)
+ {
+ info.fMask |= MIIM_FTYPE;
+ info.fType = MFT_RADIOCHECK;
+ }
+
+ SetMenuItemInfo(hMenu, id, false, &info);
+ }
+
+ if (id == CMD_RECENT)
+ {
+ HMENU sub = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);
+
+ if (sub != NULL)
+ {
+ DeleteMenu(hMenu, i, MF_BYPOSITION);
+ MsInsertMenu(hMenu, i, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
+ (UINT_PTR)sub, _UU("CM_TRAY_MENU_RECENT"));
+ }
+ else
+ {
+ MENUITEMINFO info;
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+ info.fState = MFS_DISABLED;
+
+ SetMenuItemInfo(hMenu, id, false, &info);
+ }
+ }
+ }
+}
+
+// Set the main window title
+wchar_t *CmGenerateMainWindowTitle()
+{
+ wchar_t tmp[MAX_SIZE];
+ if (cm->server_name == NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s", _UU("CM_TITLE"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s - %S", _UU("CM_TITLE"), cm->server_name);
+ }
+
+ return CopyUniStr(tmp);
+}
+
+// Initialize the task tray
+void CmInitTray(HWND hWnd)
+{
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (cm->server_name != NULL)
+ {
+ return;
+ }
+
+ if (cm->TrayInited)
+ {
+ return;
+ }
+
+ ret = MsShowIconOnTray(hWnd, LoadSmallIcon(CmGetTrayIconId(false, 0)), _UU("CM_TRAY_INITING"), WM_CM_TRAY_MESSAGE);
+
+ cm->TrayInited = true;
+ cm->TrayAnimation = false;
+ cm->TraySucceed = ret;
+
+ SetTimer(hWnd, 2, CM_TRAY_ANIMATION_INTERVAL / 4, NULL);
+}
+
+// Change the string in the task tray
+void CmChangeTrayString(HWND hWnd, wchar_t *str)
+{
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+ if (cm->TrayInited == false)
+ {
+ return;
+ }
+
+ MsChangeIconOnTray(NULL, str);
+}
+
+// Release the task tray
+void CmFreeTray(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (cm->TrayInited == false)
+ {
+ return;
+ }
+
+ MsHideIconOnTray();
+
+ cm->TrayInited = false;
+}
+void CmFreeTrayExternal(void *hWnd)
+{
+ CmFreeTray((HWND)hWnd);
+}
+
+// Periodical processing to the task tray
+void CmPollingTray(HWND hWnd)
+{
+ UINT interval;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (cm->TrayInited == false)
+ {
+ return;
+ }
+
+ ret = MsChangeIconOnTrayEx(LoadSmallIcon(CmGetTrayIconId(cm->TrayAnimation, cm->TrayAnimationCounter)),
+ NULL, NULL, NULL, NIIF_NONE, !cm->TraySucceed);
+
+ if (cm->TraySucceed == false)
+ {
+ cm->TraySucceed = ret;
+ }
+
+ cm->TrayAnimationCounter++;
+
+ KillTimer(hWnd, 2);
+ interval = CM_TRAY_ANIMATION_INTERVAL / 4;
+ if (cm->TraySpeedAnimation)
+ {
+ interval /= 4;
+ }
+ SetTimer(hWnd, 2, interval, NULL);
+}
+
+// Get the icon ID of the task tray for animation
+UINT CmGetTrayIconId(bool animation, UINT animation_counter)
+{
+ if (animation == false)
+ {
+ return ICO_TRAY0;
+ }
+ else
+ {
+ switch (animation_counter % 4)
+ {
+ case 0:
+ return ICO_TRAY1;
+
+ case 1:
+ return ICO_TRAY2;
+
+ case 2:
+ return ICO_TRAY3;
+
+ default:
+ return ICO_TRAY4;
+ }
+ }
+}
+
+// Initialize the main window
+void CmMainWindowOnInit(HWND hWnd)
+{
+ wchar_t *s;
+ BUF *b;
+ bool startup_mode = cm->StartupMode;
+ CM_SETTING a;
+ bool fake = false;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Font settings of list
+ SetFontMeiryo(hWnd, L_ACCOUNT, 9);
+ SetFontMeiryo(hWnd, L_VLAN, 9);
+
+ // Get the configuration of the current vpnclient
+ Zero(&a, sizeof(a));
+ CcGetCmSetting(cm->Client, &a);
+
+ if (a.EasyMode)
+ {
+ fake = true;
+ }
+
+ InitMenuInternational(GetMenu(hWnd), "CM_MENU");
+
+ cm->HideStatusBar = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar");
+ cm->HideTrayIcon = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon");
+ cm->IconView = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "IconView");
+ cm->ShowGrid = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid");
+
+ if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle"))
+ {
+ cm->VistaStyle = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle");
+ }
+ else
+ {
+ cm->VistaStyle = MsIsVista();
+ }
+
+ if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "ShowPort"))
+ {
+ cm->ShowPort = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort");
+ }
+ else
+ {
+ cm->ShowPort = false;
+ }
+
+ if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice"))
+ {
+ cm->DisableVoice = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice");
+ }
+ else
+ {
+ cm->DisableVoice = true;
+ }
+ cm->VoiceId = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId");
+
+ cm->StatusWindowList = NewList(NULL);
+
+ SetIcon(hWnd, 0, ICO_VPN);
+
+ s = CmGenerateMainWindowTitle();
+ SetText(hWnd, 0, s);
+ Free(s);
+
+ // Initialize the window position
+ b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement");
+ if (b != NULL && b->Size == sizeof(WINDOWPLACEMENT))
+ {
+ // Restore the window position
+ WINDOWPLACEMENT *p;
+ p = ZeroMalloc(b->Size);
+ Copy(p, b->Buf, b->Size);
+
+ if (startup_mode)
+ {
+ p->showCmd = SW_SHOWMINIMIZED;
+ }
+
+ if (fake)
+ {
+ Copy(&cm->FakeWindowPlacement, p, sizeof(WINDOWPLACEMENT));
+ }
+ else
+ {
+ SetWindowPlacement(hWnd, p);
+ }
+ Free(p);
+ }
+ else
+ {
+ // Initialize the window position
+ SetWindowPos(hWnd, NULL, 0, 0, CM_DEFAULT_WIDTH, CM_DEFAULT_HEIGHT, SWP_NOREDRAW);
+ Center(hWnd);
+ if (startup_mode)
+ {
+ ShowWindow(hWnd, SW_SHOWMINIMIZED);
+ }
+
+ if (fake)
+ {
+ WINDOWPLACEMENT p;
+
+ Zero(&p, sizeof(p));
+ p.length = sizeof(p);
+ GetWindowPlacement(hWnd, &p);
+ Copy(&cm->FakeWindowPlacement, &p, sizeof(WINDOWPLACEMENT));
+ }
+ }
+ FreeBuf(b);
+
+ if (fake)
+ {
+ SetWindowPos(hWnd, NULL, -200, -200, 100, 100,
+ SWP_NOREDRAW | SWP_SHOWWINDOW);
+ }
+
+ // Initialize the status bar related items
+ cm->hMainWnd = hWnd;
+ cm->hStatusBar = CreateStatusWindowW(WS_CHILD |
+ (cm->HideStatusBar == false ? WS_VISIBLE : 0),
+ _UU("CM_TITLE"),
+ hWnd, S_STATUSBAR);
+
+ UniStrCpy(cm->StatudBar1, sizeof(cm->StatudBar1), _UU("CM_TITLE"));
+ UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));
+ UniFormat(cm->StatudBar3, sizeof(cm->StatudBar3), _UU("CM_PRODUCT_NAME"), CEDAR_BUILD);
+
+ cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);
+ cm->Icon3 = LoadSmallIcon(ICO_VPN);
+
+ // Initialize the account list
+ CmInitAccountList(hWnd);
+
+ // Initialize the VLAN list
+ CmInitVLanList(hWnd);
+
+ // Display update
+ CmRefreshEx(hWnd, true);
+
+ // Start a thread of notification client
+ CmInitNotifyClientThread();
+
+ // Timer setting
+ SetTimer(hWnd, 1, 128, NULL);
+ SetTimer(hWnd, 6, 5000, NULL);
+
+ // Initialize the task tray
+ if (cm->server_name == NULL)
+ {
+ if (cm->HideTrayIcon == false)
+ {
+ CmInitTray(hWnd);
+ }
+ }
+
+ CmVoice("start");
+
+ if (startup_mode || a.EasyMode)
+ {
+ SetTimer(hWnd, 3, 1, NULL);
+ }
+
+ if (cm->import_file_name != NULL)
+ {
+ // Import a file specified as an argument
+ CmSendImportMessage(hWnd, cm->import_file_name, cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE ? CM_IMPORT_FILENAME_MSG : CM_IMPORT_FILENAME_MSG_OVERWRITE);
+ /*if (a.LockMode == false)
+ {
+ CmImportAccountMainEx(hWnd, cm->import_file_name, cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE);
+ }
+ else
+ {
+ MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION, _UU("CM_VPN_FILE_IMPORT_NG"));
+ }*/
+ }
+
+ // Apply the CM_SETTING
+ CmApplyCmSetting();
+
+ cm->StartupFinished = true;
+}
+
+// Start a thread of notification client
+void CmInitNotifyClientThread()
+{
+ cm->NotifyClient = CcConnectNotify(cm->Client);
+ if (cm->NotifyClient == false)
+ {
+ Close(cm->hMainWnd);
+ exit(0);
+ }
+ cm->NotifyClientThread = NewThread(CmNotifyClientThread, NULL);
+}
+
+// Notification client thread
+void CmNotifyClientThread(THREAD *thread, void *param)
+{
+ NOTIFY_CLIENT *nc;
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+ nc = cm->NotifyClient;
+
+ // Wait for the next notification
+ while (cm->Halt == false)
+ {
+ if (CcWaitNotify(nc))
+ {
+ // Send a message
+ PostMessage(cm->hMainWnd, WM_CM_NOTIFY, 0, 0);
+ }
+ else
+ {
+ // Disconnected
+ if (cm->Halt == false)
+ {
+ if (cm != NULL)
+ {
+ CmFreeTrayExternal((void *)cm->hMainWnd);
+ }
+ CncExit();
+ exit(0);
+ }
+ break;
+ }
+ }
+}
+
+// Stop the thread of the notification client
+void CmFreeNotifyClientThread()
+{
+ cm->Halt = true;
+
+ // Disconnect
+ CcStopNotify(cm->NotifyClient);
+
+ // Wait for the termination of the thread
+ WaitThread(cm->NotifyClientThread, INFINITE);
+
+ // Connection termination
+ CcDisconnectNotify(cm->NotifyClient);
+ ReleaseThread(cm->NotifyClientThread);
+}
+
+// Resize the main window
+void CmMainWindowOnSize(HWND hWnd)
+{
+ RECT r;
+ UINT client_width, client_height;
+ UINT status_height;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Get the size of the client area of the main window
+ GetClientRect(hWnd, &r);
+ client_width = MAX(r.right - r.left, 0);
+ client_height = MAX(r.bottom - r.top, 0);
+
+ SendMsg(hWnd, S_STATUSBAR, WM_SIZE, 0, 0);
+
+ // Get the size of the status bar
+ GetWindowRect(DlgItem(hWnd, S_STATUSBAR), &r);
+ status_height = MAX(r.bottom - r.top, 0);
+
+ if (cm->HideStatusBar == false)
+ {
+ client_height = MAX(client_height - status_height, 0);
+ }
+
+ MoveWindow(DlgItem(hWnd, L_ACCOUNT), 0, 0, client_width, client_height * 3 / 5 - 3, true);
+ MoveWindow(DlgItem(hWnd, L_VLAN), 0, client_height * 3 / 5, client_width, client_height * 2 / 5, true);
+
+ // Re-draw the status bar
+ CmRedrawStatusBar(hWnd);
+}
+
+// Disconnect all accounts currently connected
+void CmDisconnectAll(HWND hWnd)
+{
+ UINT i, num;
+ LIST *o;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Display a warning
+ num = CmGetNumConnected(hWnd);
+ if (num == 0)
+ {
+ return;
+ }
+
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DISCONNECT_ALL"), num) == IDNO)
+ {
+ return;
+ }
+
+ cm->PositiveDisconnectFlag = true;
+
+ // Create a list of connected items
+ o = NewListFast(NULL);
+
+ num = LvNum(hWnd, L_ACCOUNT);
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ Add(o, LvGetStr(hWnd, L_ACCOUNT, i, 0));
+ }
+ Free(s);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ if (s != NULL)
+ {
+ CmDisconnect(hWnd, s);
+ Free(s);
+ }
+ }
+
+ ReleaseList(o);
+}
+
+// Get a number of currently connected connection settings
+UINT CmGetNumConnected(HWND hWnd)
+{
+ UINT i, num, num_active;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ num_active = 0;
+ num = LvNum(hWnd, L_ACCOUNT);
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
+ {
+ num_active++;
+ }
+ Free(s);
+ }
+ }
+
+ return num_active;
+}
+
+// Update the status bar information
+void CmRefreshStatusBar(HWND hWnd)
+{
+ UINT num_active = CmGetNumConnected(hWnd);
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (num_active == 0)
+ {
+ UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));
+ cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);
+ }
+ else
+ {
+ UniFormat(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_NUM_CONN_COUNT"), num_active);
+ cm->Icon2 = LoadSmallIcon(ICO_SERVER_ONLINE);
+ }
+
+ CmRedrawStatusBar(hWnd);
+}
+
+// Re-draw the status bar
+void CmRedrawStatusBar(HWND hWnd)
+{
+ HWND h;
+ RECT r;
+ int width;
+ int x1, x2, x3;
+ int xx[3];
+ wchar_t tmp[MAX_SIZE];
+ HICON icon;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ h = cm->hStatusBar;
+
+ // Get the width of the status bar
+ GetWindowRect(h, &r);
+ width = MAX(r.right - r.left, 0);
+ x2 = (UINT)(180.0 * GetTextScalingFactor());
+ x3 = (UINT)(245.0 * GetTextScalingFactor());
+ x1 = MAX(width - x2 - x3, 0);
+
+ // Divide into three parts
+ xx[0] = x1;
+ xx[1] = x2 + x1;
+ xx[2] = x3 + x2 + x1;
+ SendMsg(h, 0, SB_SETPARTS, 3, (LPARAM)xx);
+
+ // Set an icon
+ icon = (HICON)SendMsg(h, 0, SB_GETICON, 1, 0);
+ if (icon != cm->Icon2)
+ {
+ SendMsg(h, 0, SB_SETICON, 1, (LPARAM)cm->Icon2);
+ }
+
+ icon = (HICON)SendMsg(h, 0, SB_GETICON, 2, 0);
+ if (icon != cm->Icon3)
+ {
+ SendMsg(h, 0, SB_SETICON, 2, (LPARAM)cm->Icon3);
+ }
+
+ // Set a string
+ SendMsg(h, 0, SB_GETTEXTW, 0, (LPARAM)tmp);
+ if (UniStrCmp(tmp, cm->StatudBar1))
+ {
+ SendMsg(h, 0, SB_SETTEXTW, 0, (LPARAM)cm->StatudBar1);
+ }
+
+ SendMsg(h, 0, SB_GETTEXTW, 1, (LPARAM)tmp);
+ if (UniStrCmp(tmp, cm->StatudBar2))
+ {
+ SendMsg(h, 0, SB_SETTEXTW, 1, (LPARAM)cm->StatudBar2);
+ }
+
+ SendMsg(h, 0, SB_GETTEXTW, 2, (LPARAM)tmp);
+ if (UniStrCmp(tmp, cm->StatudBar3))
+ {
+ SendMsg(h, 0, SB_SETTEXTW, 2, (LPARAM)cm->StatudBar3);
+ }
+}
+
+// Save the position information of the main window
+void CmSaveMainWindowPos(HWND hWnd)
+{
+ WINDOWPLACEMENT p;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Save settings
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar", cm->HideStatusBar);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon", cm->HideTrayIcon);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "IconView", cm->IconView);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid", cm->ShowGrid);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice", cm->DisableVoice);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId", cm->VoiceId);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle", cm->VistaStyle);
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort", cm->ShowPort);
+
+ // Save the window position
+ Zero(&p, sizeof(p));
+ p.length = sizeof(p);
+ GetWindowPlacement(hWnd, &p);
+
+ if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)
+ {
+ Copy(&p, &cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));
+ }
+
+ MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement", &p, sizeof(p));
+
+ CmSaveAccountListPos(hWnd);
+ CmSaveVLanListPos(hWnd);
+}
+
+// Close the main window
+void CmMainWindowOnQuit(HWND hWnd)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (cm->TrayInited)
+ {
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONQUESTION,
+ _UU("CM_EXIT_MESSAGE")) == IDNO)
+ {
+ return;
+ }
+ }
+
+ if (cm->OnCloseDispatched)
+ {
+ return;
+ }
+ cm->OnCloseDispatched = true;
+
+ CmCloseEasy();
+
+ // Release the tray icon
+ CmFreeTray(hWnd);
+
+ // Save the position information of the main window
+ CmSaveMainWindowPos(hWnd);
+
+ // Close the status window
+ for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)
+ {
+ HWND h = LIST_DATA(cm->StatusWindowList, i);
+ //EndDialog(h, 0);
+ PostMessage(h, WM_CLOSE, 0, 0);
+ }
+
+ ReleaseList(cm->StatusWindowList);
+ cm->StatusWindowList = NULL;
+
+ if (cm->WindowCount != 0)
+ {
+ // Abort
+ exit(0);
+ }
+
+ // Close
+ CmFreeNotifyClientThread();
+
+ EndDialog(hWnd, false);
+}
+
+// Start the mutex to be used in starting
+bool CmStartStartupMutex()
+{
+ INSTANCE *o = NewSingleInstance(STARTUP_MUTEX_NAME);
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ cm->StartupMutex = o;
+
+ return true;
+}
+
+// Release the mutex to be used in starting
+void CmEndStartupMutex()
+{
+ if (cm->StartupMutex != NULL)
+ {
+ FreeSingleInstance(cm->StartupMutex);
+
+ cm->StartupMutex = NULL;
+ }
+}
+
+// Main window
+void MainCMWindow()
+{
+ HWND h;
+ wchar_t *s;
+ CM_SETTING a;
+
+ if (CmStartStartupMutex() == false)
+ {
+ return;
+ }
+
+ s = CmGenerateMainWindowTitle();
+ h = SearchWindow(s);
+ Free(s);
+
+ Zero(&a, sizeof(a));
+ CcGetCmSetting(cm->Client, &a);
+ if (cm->server_name != NULL && a.EasyMode)
+ {
+ CmEndStartupMutex();
+ MsgBox(NULL, MB_ICONEXCLAMATION, _UU("CM_EASY_MODE_NOT_ON_REMOTE"));
+ return;
+ }
+
+ // Change the operating mode
+ if (cm->CmSettingSupported)
+ {
+ if (cm->CmSettingInitialFlag == CM_SETTING_INIT_SELECT)
+ {
+ if (h != NULL)
+ {
+ CmEndStartupMutex();
+ }
+
+ // Show the selection screen
+ CmSetting(NULL);
+
+ if (h != NULL)
+ {
+ goto SEND_MESSAGES;
+ }
+ else
+ {
+ return;
+ }
+ }
+ else if ((cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY && cm->CmEasyModeSupported) || cm->CmSettingInitialFlag == CM_SETTING_INIT_NORMAL)
+ {
+ // State transition
+ CM_SETTING a;
+
+ Zero(&a, sizeof(a));
+ CcGetCmSetting(cm->Client, &a);
+
+ if (cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY)
+ {
+ a.EasyMode = true;
+ }
+ else
+ {
+ a.EasyMode = false;
+ }
+
+ CcSetCmSetting(cm->Client, &a);
+ }
+ }
+
+ if (h == NULL)
+ {
+ // Create a window because there is no window of the same title
+ if (cm->server_name == NULL)
+ {
+ CmInitTryToExecUiHelper();
+
+ if (IsDebug() == false)
+ {
+ CnWaitForCnServiceReady();
+ }
+ }
+ Dialog(NULL, D_CM_MAIN, CmMainWindowProc, NULL);
+ CmFreeTryToExecUiHelper();
+ }
+ else
+ {
+SEND_MESSAGES:
+ CmEndStartupMutex();
+
+ // If a window of the same title already exists, activate it and exit itself
+ SetForegroundWindow(h);
+ SendMessage(h, WM_CM_SHOW, 0, 0);
+ SetForegroundWindow(h);
+
+ if (cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE && cm->CmSettingInitialFlag != CM_SETTING_INIT_CONNECT)
+ {
+ // Notify since CM_SETTING has been changed
+ SendMessage(h, WM_CM_SETTING_CHANGED_MESSAGE, 0, 0);
+ }
+
+ if (cm->import_file_name != NULL)
+ {
+ UINT msg;
+ if (cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE)
+ {
+ msg = CM_IMPORT_FILENAME_MSG;
+ }
+ else
+ {
+ msg = CM_IMPORT_FILENAME_MSG_OVERWRITE;
+ }
+
+ CmSendImportMessage(h, cm->import_file_name, msg);
+ }
+ }
+
+ CmEndStartupMutex();
+}
+
+// Send an import message
+void CmSendImportMessage(HWND hWnd, wchar_t *filename, UINT msg)
+{
+ COPYDATASTRUCT cpy;
+ // Validate arguments
+ if (hWnd == NULL || filename == NULL)
+ {
+ return;
+ }
+
+ // Specify the file to be imported
+ Zero(&cpy, sizeof(cpy));
+
+ cpy.cbData = UniStrSize(filename);
+ cpy.lpData = filename;
+ cpy.dwData = msg;
+
+ SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cpy);
+}
+
+// Login dialog
+UINT CmLoginDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ // Validate arguments
+ wchar_t server_name[MAX_SIZE];
+ char password[MAX_PASSWORD_LEN + 1];
+ bool bad_pass;
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (cm->server_name != NULL)
+ {
+ StrToUni(server_name, sizeof(server_name), cm->server_name);
+ }
+ else
+ {
+ UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
+ }
+ FormatText(hWnd, S_TITLE, server_name);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (cm->server_name != NULL)
+ {
+ StrToUni(server_name, sizeof(server_name), cm->server_name);
+ }
+ else
+ {
+ UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
+ }
+ GetTxtA(hWnd, E_PASSWORD, password, sizeof(password));
+ cm->Client = CcConnectRpc(cm->server_name == NULL ? "127.0.0.1" : cm->server_name,
+ password, &bad_pass, NULL, 0);
+ if (cm->Client == NULL)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("CM_BAD_PASSWORD"));
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ else
+ {
+ EndDialog(hWnd, true);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Login
+bool LoginCM()
+{
+ // Try to login with an empty password first
+ bool bad_pass, no_remote;
+ wchar_t server_name[MAX_SIZE];
+ RPC_CLIENT_VERSION a;
+
+RETRY:
+ if (cm->server_name != NULL)
+ {
+ StrToUni(server_name, sizeof(server_name), cm->server_name);
+ }
+ else
+ {
+ UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
+ }
+
+ // Attempt to connect
+ if ((cm->Client = CcConnectRpc(
+ cm->server_name == NULL ? "localhost" : cm->server_name,
+ "", &bad_pass, &no_remote, cm->StartupMode == false ? 0 : 60000)) == NULL)
+ {
+ if (no_remote)
+ {
+ // Remote connection was denied
+ if (MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_NO_REMOTE"), server_name) == IDRETRY)
+ {
+ // Retry
+ goto RETRY;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (bad_pass)
+ {
+ if (Dialog(NULL, D_CM_LOGIN, CmLoginDlgProc, NULL) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Connection failure
+ if (cm->StartupMode == false && MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_CONNECT_FAILED"), server_name) == IDRETRY)
+ {
+ // Retry
+ goto RETRY;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ Zero(&a, sizeof(a));
+ CcGetClientVersion(cm->Client, &a);
+ if (a.ClientBuildInt >= 5192)
+ {
+ cm->CmSettingSupported = true;
+ cm->CmEasyModeSupported = true;
+ if (OS_IS_WINDOWS_9X(a.OsType))
+ {
+ cm->CmEasyModeSupported = false;
+ }
+ }
+
+ return true;
+}
+
+// Main process
+void MainCM()
+{
+ // If there is /remote in the argument, show the screen of the remote connection
+ char *cmdline = GetCommandLineStr();
+
+ if (StrCmpi(cmdline, "/remote") == 0)
+ {
+ char *hostname = RemoteDlg(NULL, CM_REG_KEY, ICO_VPN, _UU("CM_TITLE"), _UU("CM_REMOTE_TITLE"), NULL);
+ if (hostname == NULL)
+ {
+ return;
+ }
+ if (cm->server_name != NULL)
+ {
+ Free(cm->server_name);
+ }
+ cm->server_name = NULL;
+ if (StrCmpi(hostname, "localhost") != 0 && StrCmpi(hostname, "127.0.0.1") != 0 )
+ {
+ cm->server_name = hostname;
+ }
+ }
+
+ if (StrCmpi(cmdline, "/startup") == 0)
+ {
+ // Startup mode
+ cm->StartupMode = true;
+ }
+
+ Free(cmdline);
+
+ if (IsZero(cm->ShortcutKey, SHA1_SIZE) == false)
+ {
+ //if (MsGetCurrentTerminalSessionId() == 0)
+ {
+ // Start the shortcut connection
+ CmConnectShortcut(cm->ShortcutKey);
+ }/*
+ else
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("CM_SHORTCUT_DESKTOP_MSG"),
+ MsGetCurrentTerminalSessionId());
+ }*/
+ return;
+ }
+
+ // Login
+ if (LoginCM() == false)
+ {
+ return;
+ }
+
+ //Update the jump list
+ CmUpdateJumpList(0);
+
+ // Main window
+ MainCMWindow();
+
+ // Log out
+ LogoutCM();
+
+ if (cm->Update != NULL)
+ {
+ FreeUpdateUi(cm->Update);
+ cm->Update = NULL;
+ }
+}
+
+// Log out
+void LogoutCM()
+{
+ if (cm->Client != NULL)
+ {
+ CcDisconnectRpc(cm->Client);
+ }
+}
+
+// Client Connection Manager start function
+void CMExec()
+{
+ // Initialize
+ InitCM(true);
+
+ // Main process
+ MainCM();
+
+ // Release
+ FreeCM();
+}
+
+// HUB enumeration thread
+void CmEnumHubThread(THREAD *t, void *param)
+{
+ CM_ENUM_HUB *e = (CM_ENUM_HUB *)param;
+ HWND hWnd;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ e->Thread = t;
+ hWnd = e->hWnd;
+ LockList(cm->EnumHubList);
+ {
+ Add(cm->EnumHubList, e);
+ }
+ UnlockList(cm->EnumHubList);
+
+ // Thread initialization is completed
+ NoticeThreadInit(t);
+
+ // Create a session
+ e->Session = NewRpcSession(cm->Cedar, e->ClientOption);
+ if (e->Session)
+ {
+ // Enumeration of HUB
+ e->Hub = EnumHub(e->Session);
+
+ if (e->Hub != NULL)
+ {
+ // Enumeration completed
+ // Add to the combo box
+ if (CbNum(hWnd, C_HUBNAME) == 0)
+ {
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ for (i = 0;i < e->Hub->NumTokens;i++)
+ {
+ StrToUni(tmp, sizeof(tmp), e->Hub->Token[i]);
+ CbAddStr(hWnd, C_HUBNAME, tmp, 0);
+ }
+ }
+
+ // Release the memory
+ FreeToken(e->Hub);
+ }
+
+ // Release the session
+ ReleaseSession(e->Session);
+ }
+
+ LockList(cm->EnumHubList);
+ {
+ Delete(cm->EnumHubList, e);
+ }
+ UnlockList(cm->EnumHubList);
+
+ Free(e->ClientOption);
+ Free(e);
+}
+
+// The start of the HUB enumeration
+void CmEnumHubStart(HWND hWnd, CLIENT_OPTION *o)
+{
+ CM_ENUM_HUB *e;
+ THREAD *t;
+ // Validate arguments
+ if (hWnd == NULL || o == NULL)
+ {
+ return;
+ }
+
+ if (StrLen(o->Hostname) == 0 ||
+ o->Port == 0)
+ {
+ return;
+ }
+
+ if (o->ProxyType != PROXY_DIRECT)
+ {
+ if (StrLen(o->ProxyName) == 0 ||
+ o->ProxyPort == 0)
+ {
+ return;
+ }
+ }
+
+ if (LvNum(hWnd, C_HUBNAME) != 0)
+ {
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(CM_ENUM_HUB));
+ e->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ e->hWnd = hWnd;
+ Copy(e->ClientOption, o, sizeof(CLIENT_OPTION));
+
+ t = NewThread(CmEnumHubThread, e);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+}
+
+// Initialize the HUB enumeration process
+void CmInitEnumHub()
+{
+ cm->EnumHubList = NewList(NULL);
+}
+
+// Release the HUB enumeration process
+void CmFreeEnumHub()
+{
+ LIST *o;
+ UINT i;
+ if (cm->EnumHubList == NULL)
+ {
+ return;
+ }
+
+ o = NewList(NULL);
+ LockList(cm->EnumHubList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(cm->EnumHubList);i++)
+ {
+ CM_ENUM_HUB *e = LIST_DATA(cm->EnumHubList, i);
+ Add(o, e->Thread);
+ AddRef(e->Thread->ref);
+ }
+ }
+ UnlockList(cm->EnumHubList);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+ }
+ ReleaseList(o);
+
+ ReleaseList(cm->EnumHubList);
+}
+
+// Initialize the Client Connection Manager
+
+void InitCM(bool set_app_id)
+{
+ UNI_TOKEN_LIST *ut;
+ if (cm != NULL)
+ {
+ return;
+ }
+
+ if (set_app_id)
+ {
+ if(JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM) != S_OK)
+ {
+ }
+ }
+
+ CmDeleteOldStartupTrayFile();
+
+ MsSetShutdownParameters(0x4ff, SHUTDOWN_NORETRY);
+
+ // Memory allocation
+ cm = ZeroMalloc(sizeof(CM));
+
+ // If the command line argument is set treat it as a server name
+ ut = GetCommandLineUniToken();
+
+ if (ut->NumTokens >= 1)
+ {
+ if (UniStrLen(ut->Token[0]) != 0)
+ {
+ if (UniStrCmpi(ut->Token[0], L"cm") != 0 && ut->Token[0][0] != L'/')
+ {
+ BUF *b = UniStrToBin(ut->Token[0]);
+ if (b->Size == SHA1_SIZE)
+ {
+ // Treated as a shortcut key for the connection settings
+ Copy(cm->ShortcutKey, b->Buf, SHA1_SIZE);
+ }
+ else
+ {
+ if (UniEndWith(ut->Token[0], L".vpn") == false)
+ {
+ // Treated as a server name
+ cm->server_name = CopyUniToStr(ut->Token[0]);
+ }
+ else
+ {
+ // Treated as import file name
+ cm->import_file_name = CopyUniStr(ut->Token[0]);
+ }
+ }
+ FreeBuf(b);
+ }
+ else if (UniStrCmpi(ut->Token[0], L"/easy") == 0)
+ {
+ // Simple mode
+ if (ut->NumTokens >= 2)
+ {
+ // Connection settings to be imported is specified
+ cm->import_file_name = CopyUniStr(ut->Token[1]);
+ }
+
+ cm->CmSettingInitialFlag = CM_SETTING_INIT_EASY;
+ }
+ else if (UniStrCmpi(ut->Token[0], L"/normal") == 0)
+ {
+ // Normal mode
+ if (ut->NumTokens >= 2)
+ {
+ // Connection settings to be imported is specified
+ cm->import_file_name = CopyUniStr(ut->Token[1]);
+ }
+
+ cm->CmSettingInitialFlag = CM_SETTING_INIT_NORMAL;
+ }
+ else if (UniStrCmpi(ut->Token[0], L"/connect") == 0)
+ {
+ // Import process by the simple installer
+ if (ut->NumTokens >= 2)
+ {
+ // Connection settings to be imported is specified
+ cm->import_file_name = CopyUniStr(ut->Token[1]);
+ }
+
+ cm->CmSettingInitialFlag = CM_SETTING_INIT_CONNECT;
+ }
+ else if (UniStrCmpi(ut->Token[0], L"/select") == 0)
+ {
+ // Selection screen
+ cm->CmSettingInitialFlag = CM_SETTING_INIT_SELECT;
+ }
+ }
+ }
+
+ UniFreeToken(ut);
+
+ InitWinUi(_UU("CM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ // Alpha blending related
+ UseAlpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha");
+ AlphaValue = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");
+
+ cm->Cedar = NewCedar(NULL, NULL);
+ CmInitEnumHub();
+}
+
+// Stop the Client Connection Manager
+void FreeCM()
+{
+ if (cm == NULL)
+ {
+ return;
+ }
+
+ CmFreeEnumHub();
+ ReleaseCedar(cm->Cedar);
+
+ FreeWinUi();
+
+ // Release the memory
+ if (cm->server_name != NULL)
+ {
+ Free(cm->server_name);
+ }
+ Free(cm);
+ cm = NULL;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+//JumpList ToDo
+// By Takao Ito
+void *CmUpdateJumpList(UINT start_id)
+{
+ HMENU h = NULL;
+ UINT i;
+ RPC_CLIENT_ENUM_ACCOUNT a;
+ LIST *o;
+ bool easy;
+
+ JL_PCustomDestinationList pcdl;
+ JL_PObjectCollection poc;
+ JL_PShellLink shell;
+ JL_PObjectArray poaRemoved;
+
+ HRESULT hr;
+
+ if (cm->server_name != NULL)
+ {
+ // Is not used in the case of an external PC
+ return NULL;
+ }
+
+ //Try to add
+ if(SUCCEEDED(JL_CreateCustomDestinationList(&pcdl,APPID_CM)))
+ {
+
+ JL_DeleteJumpList(pcdl,APPID_CM);
+
+ easy = cm->CmSetting.EasyMode;
+
+ Zero(&a, sizeof(a));
+
+
+ if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)
+ {
+ o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);
+
+ for (i = 0;i < a.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];
+
+ item->tmp1 = i;
+
+ if (item->LastConnectDateTime != 0)
+ {
+ Add(o, item);
+ }
+ }
+
+ Sort(o);
+
+ if(LIST_NUM(o) > 0)
+ {
+
+ if(SUCCEEDED(JL_BeginList(pcdl, &poaRemoved)))
+ {
+
+
+ //Create a collection
+ if(SUCCEEDED(JL_CreateObjectCollection(&poc)))
+ {
+
+ for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)
+ {
+
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);
+// wchar_t tmp[MAX_PATH];
+ wchar_t *account_name;
+ char *server_name;
+ char *hub_name;
+// CM_ACCOUNT *a;
+ UCHAR key[SHA1_SIZE];
+ RPC_CLIENT_GET_ACCOUNT c;
+
+
+ account_name = item->AccountName;
+ server_name = item->ServerName;
+ hub_name = item->HubName;
+
+
+
+ //
+ //a = CmGetExistAccountObject(hWnd, account_name);
+
+
+ //if (a == NULL)
+ //{
+ //continue;
+ //}
+
+ //Copy(key, a->ShortcutKey, SHA1_SIZE);
+ //
+
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
+ if (CALL(NULL, CcGetAccount(cm->Client, &c)) == false)
+ {
+ break;
+ }
+
+ Copy(key, c.ShortcutKey, SHA1_SIZE);
+
+ if (IsZero(key, SHA1_SIZE))
+ {
+ //MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));
+ }
+ else
+ {
+
+ //wchar_t target[MAX_PATH];
+ ////wchar_t workdir[MAX_PATH];
+ //wchar_t args[MAX_PATH];
+ ////wchar_t comment[MAX_SIZE];
+ //wchar_t icon[MAX_PATH];
+
+ char key_str[64];
+ wchar_t target[MAX_PATH];
+ //wchar_t workdir[MAX_PATH];
+ wchar_t args[MAX_PATH];
+ wchar_t commentW[MAX_SIZE];
+ wchar_t icon[MAX_PATH];
+ int iconNum;
+
+ //char icon = "C:\\Server.ico";
+
+ BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);
+ UniStrCpy(target, sizeof(target), MsGetExeFileNameW());
+ StrToUni(args, sizeof(args), key_str);
+ UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());
+ UniFormat(commentW, sizeof(commentW), _UU("CM_SHORTCUT_COMMENT"), account_name);
+
+ if(item->Connected)
+ {
+ iconNum = 1;
+ }
+ else
+ {
+ iconNum = 2;
+ }
+
+ hr = JL_CreateShellLink(
+ target,
+ args,
+ account_name,
+ icon,iconNum,
+ commentW,
+ &shell);
+
+ if(SUCCEEDED(hr))
+ {
+
+ if(SUCCEEDED(JL_ObjectCollectionAddShellLink(poc, shell)))
+ {
+ //Print("Add JumpList %d c:%s\n",i, comment);
+ //wprintf(comment);
+ }
+ JL_ReleaseShellLink(shell);
+ }
+ }
+
+ CiFreeClientGetAccount(&c);
+ }
+
+ hr = JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);
+
+ if(SUCCEEDED(hr))
+ {
+ //wprintf(L"AddCategory\n");
+
+ hr = JL_CommitList(pcdl);
+ if(SUCCEEDED(hr))
+ {
+ //wprintf(L"JumpList Commit\n");
+ }
+ }
+ else
+ {
+ //wprintf(L"Erro JumpList AddCategory %x\n", hr);
+ }
+
+ //Release
+ JL_ReleaseObjectCollection(poc);
+ }
+ }
+
+ }
+
+
+ ReleaseList(o);
+
+ CiFreeClientEnumAccount(&a);
+ }
+
+
+
+
+ /*
+ JL_BeginList(pcdl, &poaRemoved);
+
+ JL_CreateObjectCollection(&poc);
+
+ // Tesht
+ for (i = 0; i < 5; i++)
+ {
+
+ JL_CreateShellLink(
+ "",
+ "",
+ L"Connect",
+ NULL,0,
+ NULL,
+ &shell);
+ JL_ObjectCollectionAddShellLink(poc, shell);
+
+ JL_ReleaseShellLink(shell);
+
+ }
+
+ JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);
+ JL_CommitList(pcdl);
+ JL_ReleaseObjectCollection(poc);
+
+ JL_ReleaseCustomDestinationList(pcdl);
+ */
+
+ }
+
+ return h;
+}
+
+
+
+#endif // WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/CM.h b/src/Cedar/CM.h
new file mode 100644
index 00000000..3aae95c0
--- /dev/null
+++ b/src/Cedar/CM.h
@@ -0,0 +1,132 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CM.h
+// Header of CM.c
+
+#ifndef CM_H
+#define CM_H
+
+// Constants
+#define CM_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Client Manager"
+#define SECURE_MANAGER_KEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\SmartCard Manager"
+#define CM_TRAFFIC_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Traffic Test Tool"
+#define CM_VGC_REG_KEY "Software\\University of Tsukuba\\VPN Gate Client Plugin"
+
+
+#define CM_TRY_EXEC_UI_HELPER_INTERVAL 5000
+
+#define CM_DEFAULT_WIDTH 800
+#define CM_DEFAULT_HEIGHT 600
+
+#define WM_CM_NOTIFY (WM_APP + 999)
+
+#define CM_IMPORT_FILENAME_MSG 1267
+#define CM_IMPORT_FILENAME_MSG_OVERWRITE 1268
+
+#define CM_NUM_RECENT 8
+
+#define PUBLIC_SERVER_HTML "http://www.softether.com/jp/special/se2hub.aspx"
+#define PUBLIC_SERVER_HTML_EN "http://www.softether.com/jp/special/se2hub_en.aspx"
+#define PUBLIC_SERVER_TAG L"help:no; status:no; DialogWidth:600px; dialogHeight=700px"
+#define PUBLIC_SERVER_NAME "public.softether.com"
+
+#define VOICE_SSK 0 // ssk
+#define VOICE_AHO 1 // aho
+
+// The code for external export
+
+// Structure
+
+// Function prototype
+void CMExec();
+void CmTraffic(HWND hWnd);
+void *CmStartUacHelper();
+void CmStopUacHelper(void *p);
+void *CmExecUiHelperMain();
+UINT CmGetSecureBitmapId(char *dest_hostname);
+
+#endif // CM_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/CMInner.h b/src/Cedar/CMInner.h
new file mode 100644
index 00000000..cc65d259
--- /dev/null
+++ b/src/Cedar/CMInner.h
@@ -0,0 +1,612 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CMInner.h
+// Internal header for the CM.c
+
+#define STARTUP_MUTEX_NAME GC_SW_SOFTETHER_PREFIX "vpncmgr_startup_mutex"
+
+#define NAME_OF_VPN_CLIENT_MANAGER "vpncmgr"
+
+void CmVoice(char *name);
+
+typedef struct CM_UAC_HELPER
+{
+ THREAD *Thread;
+ volatile bool Halt;
+ EVENT *HaltEvent;
+} CM_UAC_HELPER;
+
+typedef struct CM_VOICE
+{
+ UINT voice_id;
+ char *perfix;
+} CM_VOICE;
+
+static CM_VOICE cm_voice[] =
+{
+ {VOICE_SSK, "ssk" },
+ {VOICE_AHO, "aho" },
+};
+
+typedef struct CM_ENUM_HUB
+{
+ HWND hWnd;
+ THREAD *Thread;
+ SESSION *Session;
+ CLIENT_OPTION *ClientOption;
+ TOKEN_LIST *Hub;
+} CM_ENUM_HUB;
+
+#define CM_SETTING_INIT_NONE 0
+#define CM_SETTING_INIT_EASY 1 // Transition to the simple mode
+#define CM_SETTING_INIT_NORMAL 2 // Transition to the normal mode
+#define CM_SETTING_INIT_SELECT 3 // Show a selection screen
+#define CM_SETTING_INIT_CONNECT 4 // Import process by the simple installer
+
+typedef struct CM
+{
+ HWND hMainWnd;
+ HWND hStatusBar;
+ REMOTE_CLIENT *Client;
+ char *server_name;
+ wchar_t *import_file_name;
+ bool HideStatusBar;
+ bool HideTrayIcon;
+ bool ShowGrid;
+ bool VistaStyle;
+ bool ShowPort;
+ wchar_t StatudBar1[MAX_SIZE];
+ wchar_t StatudBar2[MAX_SIZE];
+ wchar_t StatudBar3[MAX_SIZE];
+ HICON Icon2, Icon3;
+ bool IconView;
+ THREAD *NotifyClientThread;
+ NOTIFY_CLIENT *NotifyClient;
+ volatile bool Halt;
+ bool OnCloseDispatched;
+ LIST *StatusWindowList;
+ CEDAR *Cedar;
+ LIST *EnumHubList;
+ UINT WindowCount;
+ bool DisableVoice;
+ UINT VoiceId;
+ UINT OldConnectedNum;
+ bool UpdateConnectedNumFlag;
+ UCHAR ShortcutKey[SHA1_SIZE];
+ bool TrayInited;
+ bool TraySucceed;
+ bool TrayAnimation;
+ bool TraySpeedAnimation;
+ UINT TrayAnimationCounter;
+ bool StartupMode;
+ THREAD *TryExecUiHelperThread;
+ volatile bool TryExecUiHelperHalt;
+ HANDLE TryExecUiHelperProcessHandle;
+ EVENT *TryExecUiHelperHaltEvent;
+ bool WindowsShutdowning;
+ bool CmSettingSupported;
+ bool CmEasyModeSupported;
+ bool CmSettingInitialFlag;
+ CM_SETTING CmSetting;
+ HWND hEasyWnd;
+ bool StartupFinished;
+ bool ConnectStartedFlag;
+ bool PositiveDisconnectFlag;
+ wchar_t EasyLastSelectedAccountName[MAX_ACCOUNT_NAME_LEN + 1];
+ WINDOWPLACEMENT FakeWindowPlacement;
+ bool CheckedAndShowedAdminPackMessage;
+ INSTANCE *StartupMutex;
+ bool BadProcessChecked;
+ bool MenuPopuping;
+ WINUI_UPDATE *Update;
+} CM;
+
+typedef struct CM_STATUS
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ HWND hWndPolicy; // Policy dialog
+} CM_STATUS;
+
+typedef struct CM_POLICY
+{
+ HWND hWnd;
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ POLICY *Policy; // Policy dialog
+ CM_STATUS *CmStatus; // CM_STATUS
+ bool Extension; // Extension
+} CM_POLICY;
+
+typedef struct CM_ACCOUNT
+{
+ bool EditMode; // Edit mode (false: New mode)
+ bool LinkMode; // Link mode
+ bool NatMode; // NAT mode
+ CLIENT_OPTION *ClientOption; // Client option
+ CLIENT_AUTH *ClientAuth; // Authentication data
+ bool Startup; // Startup account
+ bool CheckServerCert; // Check the server certificate
+ X *ServerCert; // Server certificate
+ char old_server_name[MAX_HOST_NAME_LEN + 1]; // Old server name
+ bool Inited; // Initialization flag
+ POLICY Policy; // Policy (only link mode)
+ struct SM_HUB *Hub; // HUB
+ RPC *Rpc; // RPC
+ bool OnlineFlag; // Online flag
+ bool Flag1; // Flag 1
+ bool HideClientCertAuth; // Hide the client authentication
+ bool HideSecureAuth; // Hide the smart card authentication
+ bool HideTrustCert; // Hide the trusted certificate authority button
+ UCHAR ShortcutKey[SHA1_SIZE]; // Shortcut key
+ bool LockMode; // Setting lock mode
+ bool Link_ConnectNow; // Start the connection immediately
+ UINT PolicyVer; // Policy version
+} CM_ACCOUNT;
+
+typedef struct CM_CHANGE_PASSWORD
+{
+ CLIENT_OPTION *ClientOption; // Client Option
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+} CM_CHANGE_PASSWORD;
+
+typedef struct CM_TRAFFIC
+{
+ bool ServerMode; // Server mode
+ bool Double; // 2x mode
+ bool Raw; // Raw data mode
+ UINT Port; // Port number
+ char Host[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT NumTcp; // Number of TCP connections
+ UINT Type; // Type
+ UINT Span; // Period
+} CM_TRAFFIC;
+
+typedef struct CM_TRAFFIC_DLG
+{
+ HWND hWnd; // Window handle
+ CM_TRAFFIC *Setting; // Setting
+ TTS *Tts; // Measurement server
+ TTC *Ttc; // Measurement client
+ THREAD *HaltThread; // Thread for stopping
+ THREAD *ClientEndWaitThread; // Thread to wait for the client to finish
+ bool Started; // Started flag
+ bool Stopping; // Stopping
+ UINT RetCode; // Return value
+ TT_RESULT Result; // Result
+ EVENT *ResultShowEvent; // Display result event
+ bool CloseDialogAfter; // Flag of whether or not to close the dialog
+} CM_TRAFFIC_DLG;
+
+// Internet connection settings
+typedef struct CM_INTERNET_SETTING
+{
+ UINT ProxyType; // Type of proxy server
+ char ProxyHostName[MAX_HOST_NAME_LEN + 1]; // Proxy server host name
+ UINT ProxyPort; // Proxy server port number
+ char ProxyUsername[MAX_USERNAME_LEN + 1]; // Proxy server user name
+ char ProxyPassword[MAX_USERNAME_LEN + 1]; // Proxy server password
+} CM_INTERNET_SETTING;
+
+static CM *cm = NULL;
+
+void CmFreeTrayExternal(void *hWnd);
+
+// Normal RPC call macro
+__forceinline static bool CALL(HWND hWnd, UINT code)
+{
+ UINT ret = code;
+ if (ret != ERR_NO_ERROR)
+ {
+ if (ret == ERR_DISCONNECTED)
+ {
+ if (cm != NULL)
+ {
+ Close(cm->hMainWnd);
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_DISCONNECTED"));
+ }
+
+ if (cm != NULL)
+ {
+ CmFreeTrayExternal((void *)cm->hMainWnd);
+ }
+ exit(0);
+ }
+ else
+ {
+ UINT flag = MB_ICONEXCLAMATION;
+ if (ret == ERR_VLAN_IS_USED)
+ {
+ CmVoice("using_vlan");
+ }
+ if (hWnd != NULL && cm != NULL && cm->hEasyWnd != NULL)
+ {
+ hWnd = cm->hEasyWnd;
+ }
+ if (hWnd != NULL && cm != NULL && hWnd == cm->hEasyWnd)
+ {
+ flag |= MB_SETFOREGROUND | MB_TOPMOST;
+ }
+ MsgBox(hWnd, flag, _E(ret));
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Extended RPC call macro (get an error value)
+__forceinline static UINT CALLEX(HWND hWnd, UINT code)
+{
+ UINT ret = code;
+ if (ret != ERR_NO_ERROR)
+ {
+ if (ret == ERR_DISCONNECTED)
+ {
+ if (cm != NULL)
+ {
+ Close(cm->hMainWnd);
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_DISCONNECTED"));
+ }
+ if (cm != NULL)
+ {
+ CmFreeTrayExternal((void *)cm->hMainWnd);
+ }
+ exit(0);
+ }
+ }
+
+ return ret;
+}
+
+typedef struct CM_LOADX
+{
+ X *x;
+} CM_LOADX;
+
+typedef struct CM_SETTING_DLG
+{
+ bool CheckPassword;
+ UCHAR HashedPassword[SHA1_SIZE];
+} CM_SETTING_DLG;
+
+typedef struct CM_EASY_DLG
+{
+ bool EndDialogCalled;
+} CM_EASY_DLG;
+
+
+
+// Task tray related
+#define WM_CM_TRAY_MESSAGE (WM_APP + 44)
+#define WM_CM_SETTING_CHANGED_MESSAGE (WM_APP + 45)
+#define WM_CM_EASY_REFRESH (WM_APP + 46)
+#define WM_CM_SHOW (WM_APP + 47)
+#define CMD_EASY_DBLCLICK 40697
+#define CMD_VGC_CONNECT 40698
+#define CM_TRAY_ANIMATION_INTERVAL 3000
+#define CM_TRAY_MAX_ITEMS 4096
+#define CM_TRAY_MENU_ID_START 12000
+#define CM_TRAY_MENU_CONNECT_ID_START (CM_TRAY_MENU_ID_START + CM_TRAY_MAX_ITEMS)
+#define CM_TRAY_MENU_STATUS_ID_START (CM_TRAY_MENU_CONNECT_ID_START + CM_TRAY_MAX_ITEMS)
+#define CM_TRAY_MENU_DISCONNECT_ID_START (CM_TRAY_MENU_STATUS_ID_START + CM_TRAY_MAX_ITEMS)
+#define CM_TRAY_MENU_RECENT_ID_START (CM_TRAY_MENU_DISCONNECT_ID_START + CM_TRAY_MAX_ITEMS)
+#define CM_TRAY_IS_CONNECT_ID(id) (((id) >= CM_TRAY_MENU_CONNECT_ID_START) && (id) < CM_TRAY_MENU_STATUS_ID_START)
+#define CM_TRAY_IS_STATUS_ID(id) (((id) >= CM_TRAY_MENU_STATUS_ID_START) && (id) < CM_TRAY_MENU_DISCONNECT_ID_START)
+#define CM_TRAY_IS_DISCONNECT_ID(id) (((id) >= CM_TRAY_MENU_DISCONNECT_ID_START) && (id) < (CM_TRAY_MENU_DISCONNECT_ID_START + CM_TRAY_MAX_ITEMS))
+#define CM_TRAY_IS_RECENT_ID(id) (((id) >= CM_TRAY_MENU_RECENT_ID_START) && (id) < (CM_TRAY_MENU_RECENT_ID_START + CM_TRAY_MAX_ITEMS))
+
+
+// Function prototype
+void InitCM(bool set_app_id);
+void FreeCM();
+void MainCM();
+bool LoginCM();
+void LogoutCM();
+UINT CmLoginDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void MainCMWindow();
+void CmSendImportMessage(HWND hWnd, wchar_t *filename, UINT msg);
+UINT CmMainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmMainWindowOnSize(HWND hWnd);
+void CmMainWindowOnInit(HWND hWnd);
+void CmMainWindowOnQuit(HWND hWnd);
+void CmSaveMainWindowPos(HWND hWnd);
+void CmMainWindowOnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
+void CmMainWindowOnCommandEx(HWND hWnd, WPARAM wParam, LPARAM lParam, bool easy);
+bool CmIsEnabled(HWND hWnd, UINT id);
+bool CmIsChecked(UINT id);
+bool CmIsBold(UINT id);
+void CmMainWindowOnPopupMenu(HWND hWnd, HMENU hMenu, UINT pos);
+void CmSaveMainWindowPos(HWND hWnd);
+void CmRedrawStatusBar(HWND hWnd);
+void CmRefresh(HWND hWnd);
+void CmRefreshEx(HWND hWnd, bool style_changed);
+void CmSetForegroundProcessToCnService();
+void CmInitAccountList(HWND hWnd);
+void CmInitAccountListEx(HWND hWnd, bool easy);
+void CmInitVLanList(HWND hWnd);
+void CmRefreshAccountList(HWND hWnd);
+void CmRefreshAccountListEx(HWND hWnd, bool easy);
+void CmRefreshAccountListEx2(HWND hWnd, bool easy, bool style_changed);
+void CmRefreshVLanList(HWND hWnd);
+void CmRefreshVLanListEx(HWND hWnd, bool style_changed);
+void CmSaveAccountListPos(HWND hWnd);
+void CmSaveVLanListPos(HWND hWnd);
+wchar_t *CmGetProtocolName(UINT n);
+void CmVLanNameToPrintName(char *str, UINT size, char *name);
+bool CmPrintNameToVLanName(char *name, UINT size, char *str);
+void CmMainWindowOnNotify(HWND hWnd, NMHDR *n);
+void CmOnKey(HWND hWnd, bool ctrl, bool alt, UINT key);
+void CmAccountListRightClick(HWND hWnd);
+void CmVLanListRightClick(HWND hWnd);
+void CmConnect(HWND hWnd, wchar_t *account_name);
+void CmDisconnect(HWND hWnd, wchar_t *account_name);
+void CmInitNotifyClientThread();
+void CmFreeNotifyClientThread();
+void CmNotifyClientThread(THREAD *thread, void *param);
+void CmDeleteAccount(HWND hWnd, wchar_t *account_name);
+void CmStatus(HWND hWnd, wchar_t *account_name);
+void CmStatusDlg(HWND hWnd, wchar_t *account_name);
+UINT CmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmStatusDlgPrint(HWND hWnd, CM_STATUS *cmst);
+void CmPrintStatusToListView(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s);
+void CmPrintStatusToListViewEx(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode);
+void CmStatusDlgPrintCert(HWND hWnd, CM_STATUS *st, bool server);
+void CmPolicyDlg(HWND hWnd, CM_STATUS *st);
+UINT CmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmPolicyDlgPrint(HWND hWnd, CM_POLICY *p);
+void CmPolicyDlgPrintEx(HWND hWnd, CM_POLICY *p, bool cascade_mode);
+void CmPolicyDlgPrintEx2(HWND hWnd, CM_POLICY *p, bool cascade_mode, bool ver);
+void CmNewAccount(HWND hWnd);
+void CmEditAccount(HWND hWnd, wchar_t *account_name);
+void CmGenerateNewAccountName(HWND hWnd, wchar_t *name, UINT size);
+void CmGenerateCopyName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name);
+void CmGenerateImportName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name);
+CM_ACCOUNT *CmCreateNewAccountObject(HWND hWnd);
+CM_ACCOUNT *CmGetExistAccountObject(HWND hWnd, wchar_t *account_name);
+void CmEnumHubStart(HWND hWnd, CLIENT_OPTION *o);
+void CmInitEnumHub();
+void CmFreeEnumHub();
+void CmFreeAccountObject(HWND hWnd, CM_ACCOUNT *a);
+bool CmEditAccountDlg(HWND hWnd, CM_ACCOUNT *a);
+UINT CmEditAccountDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmEditAccountDlgUpdate(HWND hWnd, CM_ACCOUNT *a);
+void CmEditAccountDlgInit(HWND hWnd, CM_ACCOUNT *a);
+void CmEditAccountDlgOnOk(HWND hWnd, CM_ACCOUNT *a);
+void CmEditAccountDlgStartEnumHub(HWND hWnd, CM_ACCOUNT *a);
+bool CmLoadXAndK(HWND hWnd, X **x, K **k);
+bool CmLoadK(HWND hWnd, K **k);
+bool CmLoadKEx(HWND hWnd, K **k, char *filename, UINT size);
+bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size);
+bool CmLoadXFromFileOrSecureCard(HWND hWnd, X **x);
+void CmLoadXFromFileOrSecureCardDlgInit(HWND hWnd, CM_LOADX *p);
+void CmLoadXFromFileOrSecureCardDlgUpdate(HWND hWnd, CM_LOADX *p);
+UINT CmLoadXFromFileOrSecureCardDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool CmLoadX(HWND hWnd, X **x);
+bool CmLoadXEx(HWND hWnd, X **x, char *filename, UINT size);
+bool CmLoadXExW(HWND hWnd, X **x, wchar_t *filename, UINT size);
+X *CmGetIssuer(X *x);
+bool CmProxyDlg(HWND hWnd, CLIENT_OPTION *a);
+void CmProxyDlgUpdate(HWND hWnd, CLIENT_OPTION *a);
+UINT CmProxyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool CmDetailDlg(HWND hWnd, CM_ACCOUNT *a);
+UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+char *CmNewVLanDlg(HWND hWnd);
+UINT CmNewVLanDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmCopyAccount(HWND hWnd, wchar_t *account_name);
+void CmExportAccount(HWND hWnd, wchar_t *account_name);
+void CmSortcut(HWND hWnd, wchar_t *account_name);
+void CmImportAccount(HWND hWnd);
+void CmImportAccountMain(HWND hWnd, wchar_t *filename);
+void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite);
+void CmTrustDlg(HWND hWnd);
+UINT CmTrustDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmTrustDlgUpdate(HWND hWnd);
+void CmTrustDlgRefresh(HWND hWnd);
+void CmTrustImport(HWND hWnd);
+void CmTrustExport(HWND hWnd);
+void CmTrustView(HWND hWnd);
+void CmPassword(HWND hWnd);
+UINT CmPasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmPasswordRefresh(HWND hWnd);
+void CmRefreshStatusBar(HWND hWnd);
+UINT CmGetNumConnected(HWND hWnd);
+void CmDisconnectAll(HWND hWnd);
+wchar_t *CmGenerateMainWindowTitle();
+void CmConfigDlg(HWND hWnd);
+UINT CmConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmConfigDlgInit(HWND hWnd);
+void CmConfigDlgRefresh(HWND hWnd);
+void CmConfigDlgOnOk(HWND hWnd);
+bool CmWarningDesktop(HWND hWnd, wchar_t *account_name);
+UINT CmDesktopDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmDesktopDlgInit(HWND hWnd, wchar_t *account_name);
+bool CmStopInstallVLan(HWND hWnd);
+void CmChangePassword(HWND hWnd, CLIENT_OPTION *o, char *hubname, char *username);
+UINT CmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmChangePasswordUpdate(HWND hWnd, CM_CHANGE_PASSWORD *p);
+void SmShowPublicVpnServerHtml(HWND hWnd);
+void CmConnectShortcut(UCHAR *key);
+UINT CmSelectSecure(HWND hWnd, UINT current_id);
+void CmClientSecureManager(HWND hWnd);
+UINT CmClientSelectSecure(HWND hWnd);
+UINT CmSelectSecureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmSelectSecureDlgInit(HWND hWnd, UINT default_id);
+void CmSelectSecureDlgUpdate(HWND hWnd);
+void CmSecureManager(HWND hWnd, UINT id);
+void CmSecureManagerEx(HWND hWnd, UINT id, bool no_new_cert);
+UINT CmSecureManagerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmSecureManagerDlgInit(HWND hWnd, UINT id);
+void CmSecureManagerDlgUpdate(HWND hWnd, UINT id);
+void CmSecureManagerDlgRefresh(HWND hWnd, UINT id);
+void CmSecureManagerDlgPrintList(HWND hWnd, LIST *o);
+void CmSecureManagerDlgPrintListEx(HWND hWnd, UINT id, LIST *o, UINT type);
+wchar_t *CmSecureObjTypeToStr(UINT type);
+UINT CmSecureType(HWND hWnd);
+UINT CmSecureTypeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmSecureManagerDlgImport(HWND hWnd, UINT id);
+void CmSecureManagerDlgDelete(HWND hWnd, UINT id);
+void CmSecureManagerDlgExport(HWND hWnd, UINT id);
+void CmSecureManagerDlgNewCert(HWND hWnd, UINT id);
+void CmSecurePin(HWND hWnd, UINT id);
+UINT CmSecurePinDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmSecurePinDlgUpdate(HWND hWnd);
+void CmInitTray(HWND hWnd);
+void CmPollingTray(HWND hWnd);
+void CmFreeTray(HWND hWnd);
+void CmChangeTrayString(HWND hWnd, wchar_t *str);
+UINT CmGetTrayIconId(bool animation, UINT animation_counter);
+void CmShowOrHideWindow(HWND hWnd);
+void CmShowTrayMenu(HWND hWnd);
+HMENU CmCreateTraySubMenu(HWND hWnd, bool flag, UINT start_id);
+HMENU CmCreateRecentSubMenu(HWND hWnd, UINT start_id);
+bool CmCheckPkcsEula(HWND hWnd, UINT id);
+UINT CmPkcsEulaDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmDeleteOldStartupTrayFile();
+UINT CmTrafficDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmTrafficDlgInit(HWND hWnd);
+bool CmTrafficDlgUpdate(HWND hWnd);
+void CmTrafficDlgOnOk(HWND hWnd);
+bool CmTrafficLoadFromReg(CM_TRAFFIC *t);
+void CmTrafficGetDefaultSetting(CM_TRAFFIC *t);
+void CmTrafficSaveToReg(CM_TRAFFIC *t);
+void CmTrafficDlgToStruct(HWND hWnd, CM_TRAFFIC *t);
+void CmExecTraffic(HWND hWnd, CM_TRAFFIC *t);
+UINT CmTrafficRunDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmTrafficRunDlgInit(HWND hWnd, CM_TRAFFIC_DLG *d);
+void CmTrafficRunDlgStart(HWND hWnd, CM_TRAFFIC_DLG *d);
+void CmTrafficRunDlgPrintProc(void *param, wchar_t *str);
+void CmTrafficRunDlgAddStr(HWND hWnd, wchar_t *str);
+void CmTrafficRunDlgHalt(HWND hWnd, CM_TRAFFIC_DLG *d);
+void CmTrafficRunDlgHaltThread(THREAD *t, void *param);
+void CmTrafficRunDlgClientWaitThread(THREAD *t, void *param);
+void CmTrafficResult(HWND hWnd, TT_RESULT *r);
+UINT CmTrafficResultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmTrafficResultDlgInit(HWND hWnd, TT_RESULT *res);
+void CmTryToExecUiHelper();
+void CmInitTryToExecUiHelper();
+void CmFreeTryToExecUiHelper();
+void CmTryToExecUiHelperThread(THREAD *thread, void *param);
+bool CmSetting(HWND hWnd);
+UINT CmSettingDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmSettingDlgInit(HWND hWnd, CM_SETTING_DLG *d);
+void CmSettingDlgUpdate(HWND hWnd, CM_SETTING_DLG *d);
+void CmSettingDlgOnOk(HWND hWnd, CM_SETTING_DLG *d);
+void CmApplyCmSetting();
+void CmMainWindowOnTrayClicked(HWND hWnd, WPARAM wParam, LPARAM lParam);
+void CmShowEasy();
+void CmCloseEasy();
+void CmMainWindowOnShowEasy(HWND hWnd);
+UINT CmEasyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CmEasyDlgInit(HWND hWnd, CM_EASY_DLG *d);
+void CmEasyDlgUpdate(HWND hWnd, CM_EASY_DLG *d);
+void CmEasyDlgRefresh(HWND hWnd, CM_EASY_DLG *d);
+void CmRefreshEasy();
+void CmEasyDlgOnNotify(HWND hWnd, CM_EASY_DLG *d, NMHDR *n);
+void CmEasyDlgOnKey(HWND hWnd, CM_EASY_DLG *d, bool ctrl, bool alt, UINT key);
+void CmEasyDlgOnCommand(HWND hWnd, CM_EASY_DLG *d, WPARAM wParam, LPARAM lParam);
+
+bool CmStartStartupMutex();
+void CmEndStartupMutex();
+void CmSetUacWindowActive();
+void CmUacHelperThread(THREAD *thread, void *param);
+void CmProxyDlgUseForIE(HWND hWnd, CLIENT_OPTION *o);
+void CmGetSystemInternetSetting(CM_INTERNET_SETTING *setting);
+void CmProxyDlgSet(HWND hWnd, CLIENT_OPTION *o, CM_INTERNET_SETTING *setting);
+bool CmGetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type);
+void *CmUpdateJumpList(UINT start_id);
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Cedar.c b/src/Cedar/Cedar.c
new file mode 100644
index 00000000..2505dcef
--- /dev/null
+++ b/src/Cedar/Cedar.c
@@ -0,0 +1,1708 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cedar.c
+// Cedar Communication Module
+
+
+#include "CedarPch.h"
+
+static UINT init_cedar_counter = 0;
+static REF *cedar_log_ref = NULL;
+static LOG *cedar_log;
+
+// Get build date of current code
+UINT64 GetCurrentBuildDate()
+{
+ SYSTEMTIME st;
+
+ Zero(&st, sizeof(st));
+
+ st.wYear = BUILD_DATE_Y;
+ st.wMonth = BUILD_DATE_M;
+ st.wDay = BUILD_DATE_D;
+ st.wHour = BUILD_DATE_HO;
+ st.wMinute = BUILD_DATE_MI;
+ st.wSecond = BUILD_DATE_SE;
+
+ return SystemToUINT64(&st);
+}
+
+// Check current windows version is supported
+bool IsSupportedWinVer(RPC_WINVER *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+
+ if (v->IsWindows == false)
+ {
+ return true;
+ }
+
+ if (v->IsNT == false)
+ {
+ return true;
+ }
+
+ if (v->IsBeta)
+ {
+ return true;
+ }
+
+ if (v->VerMajor <= 4)
+ {
+ // Windows NT
+ return true;
+ }
+
+ if (v->VerMajor == 5 && v->VerMinor == 0)
+ {
+ // Windows 2000
+ if (v->ServicePack <= 4)
+ {
+ // SP4 or earlier
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 5 && v->VerMinor == 1)
+ {
+ // Windows XP x86
+ if (v->ServicePack <= 3)
+ {
+ // SP3 or earlier
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 5 && v->VerMinor == 2)
+ {
+ // Windows XP x64, Windows Server 2003
+ if (v->ServicePack <= 2)
+ {
+ // SP2 or earlier
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 6 && v->VerMinor == 0)
+ {
+ // Windows Vista, Server 2008
+ if (v->ServicePack <= 2)
+ {
+ // SP2 or earlier
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 6 && v->VerMinor == 1)
+ {
+ // Windows 7, Server 2008 R2
+ if (v->ServicePack <= 1)
+ {
+ // SP1 or earlier
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 6 && v->VerMinor == 2)
+ {
+ // Windows 8, Server 2012
+ if (v->ServicePack <= 0)
+ {
+ // SP0 only
+ return true;
+ }
+ }
+
+ if (v->VerMajor == 6 && v->VerMinor == 3)
+ {
+ // Windows 8.1, Server 2012 R2
+ if (v->ServicePack <= 0)
+ {
+ // SP0 only
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get version of Windows
+void GetWinVer(RPC_WINVER *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32GetWinVer(v);
+#else // OS_WIN32
+ Zero(v, sizeof(RPC_WINVER));
+ StrCpy(v->Title, sizeof(v->Title), GetOsInfo()->OsProductName);
+#endif // OS_WIN32
+}
+
+// Close tiny log
+void FreeTinyLog(TINY_LOG *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FileClose(t->io);
+ DeleteLock(t->Lock);
+ Free(t);
+}
+
+// Write to tiny log
+void WriteTinyLog(TINY_LOG *t, char *str)
+{
+ BUF *b;
+ char dt[MAX_PATH];
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ GetDateTimeStrMilli64(dt, sizeof(dt), LocalTime64());
+ StrCat(dt, sizeof(dt), ": ");
+
+ b = NewBuf();
+
+ WriteBuf(b, dt, StrLen(dt));
+ WriteBuf(b, str, StrLen(str));
+ WriteBuf(b, "\r\n", 2);
+
+ Lock(t->Lock);
+ {
+ FileWrite(t->io, b->Buf, b->Size);
+ //FileFlush(t->io);
+ }
+ Unlock(t->Lock);
+
+ FreeBuf(b);
+}
+
+// Initialize tiny log
+TINY_LOG *NewTinyLog()
+{
+ char name[MAX_PATH];
+ SYSTEMTIME st;
+ TINY_LOG *t;
+
+ LocalTime(&st);
+
+ MakeDir(TINY_LOG_DIRNAME);
+
+ Format(name, sizeof(name), TINY_LOG_FILENAME,
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+
+ t = ZeroMalloc(sizeof(TINY_LOG));
+
+ StrCpy(t->FileName, sizeof(t->FileName), name);
+ t->io = FileCreate(name);
+ t->Lock = NewLock();
+
+ return t;
+}
+
+// Compare entries of No-SSL connection list
+int CompareNoSslList(void *p1, void *p2)
+{
+ NON_SSL *n1, *n2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ n1 = *(NON_SSL **)p1;
+ n2 = *(NON_SSL **)p2;
+ if (n1 == NULL || n2 == NULL)
+ {
+ return 0;
+ }
+ return CmpIpAddr(&n1->IpAddress, &n2->IpAddress);
+}
+
+// Check whether the specified IP address is in Non-SSL connection list
+bool IsInNoSsl(CEDAR *c, IP *ip)
+{
+ bool ret = false;
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->NonSslList);
+ {
+ NON_SSL *n = SearchNoSslList(c, ip);
+
+ if (n != NULL)
+ {
+ if (n->EntryExpires > Tick64() && n->Count > NON_SSL_MIN_COUNT)
+ {
+ n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;
+ ret = true;
+ }
+ }
+ }
+ UnlockList(c->NonSslList);
+
+ return ret;
+}
+
+// Decrement connection count of Non-SSL connection list entry
+void DecrementNoSsl(CEDAR *c, IP *ip, UINT num_dec)
+{
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ LockList(c->NonSslList);
+ {
+ NON_SSL *n = SearchNoSslList(c, ip);
+
+ if (n != NULL)
+ {
+ if (n->Count >= num_dec)
+ {
+ n->Count -= num_dec;
+ }
+ }
+ }
+ UnlockList(c->NonSslList);
+}
+
+// Add new entry to Non-SSL connection list
+bool AddNoSsl(CEDAR *c, IP *ip)
+{
+ NON_SSL *n;
+ bool ret = true;
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return true;
+ }
+
+ LockList(c->NonSslList);
+ {
+ DeleteOldNoSsl(c);
+
+ n = SearchNoSslList(c, ip);
+
+ if (n == NULL)
+ {
+ n = ZeroMalloc(sizeof(NON_SSL));
+ Copy(&n->IpAddress, ip, sizeof(IP));
+ n->Count = 0;
+
+ Add(c->NonSslList, n);
+ }
+
+ n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;
+
+ n->Count++;
+
+ if (n->Count > NON_SSL_MIN_COUNT)
+ {
+ ret = false;
+ }
+ }
+ UnlockList(c->NonSslList);
+
+ return ret;
+}
+
+// Delete old entries in Non-SSL connection list
+void DeleteOldNoSsl(CEDAR *c)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(c->NonSslList);i++)
+ {
+ NON_SSL *n = LIST_DATA(c->NonSslList, i);
+
+ if (n->EntryExpires <= Tick64())
+ {
+ Add(o, n);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NON_SSL *n = LIST_DATA(o, i);
+
+ Delete(c->NonSslList, n);
+ Free(n);
+ }
+
+ ReleaseList(o);
+}
+
+// Search entry in Non-SSL connection list
+NON_SSL *SearchNoSslList(CEDAR *c, IP *ip)
+{
+ NON_SSL *n, t;
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ n = Search(c->NonSslList, &t);
+
+ if (n == NULL)
+ {
+ return NULL;
+ }
+
+ return n;
+}
+
+// Initialize Non-SSL connection list
+void InitNoSslList(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->NonSslList = NewList(CompareNoSslList);
+}
+
+// Free Non-SSL connection list
+void FreeNoSslList(CEDAR *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(c->NonSslList);i++)
+ {
+ NON_SSL *n = LIST_DATA(c->NonSslList, i);
+
+ Free(n);
+ }
+
+ ReleaseList(c->NonSslList);
+ c->NonSslList = NULL;
+}
+
+// Write a message into Cedar log
+void CedarLog(char *str)
+{
+ char *tmp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ if (cedar_log_ref == NULL)
+ {
+ return;
+ }
+
+ tmp = CopyStr(str);
+
+ if (StrLen(tmp) > 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == '\n')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ if (StrLen(tmp) > 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == '\r')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+ }
+
+ InsertStringRecord(cedar_log, tmp);
+
+ Free(tmp);
+}
+
+// Start Cedar log
+void StartCedarLog()
+{
+ if (cedar_log_ref == NULL)
+ {
+ cedar_log_ref = NewRef();
+ }
+ else
+ {
+ AddRef(cedar_log_ref);
+ }
+
+ cedar_log = NewLog("debug_log", "debug", LOG_SWITCH_DAY);
+}
+
+// Stop Cedar log
+void StopCedarLog()
+{
+ if (cedar_log_ref == NULL)
+ {
+ return;
+ }
+
+ if (Release(cedar_log_ref) == 0)
+ {
+ FreeLog(cedar_log);
+ cedar_log = NULL;
+ cedar_log_ref = NULL;
+ }
+}
+
+
+// Get sum of traffic data size
+UINT64 GetTrafficPacketSize(TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ return t->Recv.BroadcastBytes + t->Recv.UnicastBytes +
+ t->Send.BroadcastBytes + t->Send.UnicastBytes;
+}
+
+// Get sum of the number of packets in traffic
+UINT64 GetTrafficPacketNum(TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ return t->Recv.BroadcastCount + t->Recv.UnicastCount +
+ t->Send.BroadcastCount + t->Send.UnicastCount;
+}
+
+// Get whether hidden password is changed in UI
+bool IsHiddenPasswordChanged(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return true;
+ }
+
+ if (StrCmpi(str, HIDDEN_PASSWORD) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Initialize hidden password in UI
+void InitHiddenPassword(char *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ StrCpy(str, size, HIDDEN_PASSWORD);
+}
+
+// Check whether the certificate is signed by CA which is trusted by the hub
+bool CheckSignatureByCaLinkMode(SESSION *s, X *x)
+{
+ LINK *k;
+ HUB *h;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ if (s->LinkModeClient == false || (k = s->Link) == NULL)
+ {
+ return false;
+ }
+
+ h = k->Hub;
+
+ if (h->HubDb != NULL)
+ {
+ LockList(h->HubDb->RootCertList);
+ {
+ X *root_cert;
+ root_cert = GetIssuerFromList(h->HubDb->RootCertList, x);
+ if (root_cert != NULL)
+ {
+ ret = true;
+ }
+ }
+ UnlockList(h->HubDb->RootCertList);
+ }
+
+ return ret;
+}
+
+// Check whether the certificate is signed by CA which is trusted by Cedar
+bool CheckSignatureByCa(CEDAR *cedar, X *x)
+{
+ X *ca;
+ // Validate arguments
+ if (cedar == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ // Get the CA which signed the certificate
+ ca = FindCaSignedX(cedar->CaList, x);
+ if (ca == NULL)
+ {
+ // Not found
+ return false;
+ }
+
+ // Found
+ FreeX(ca);
+ return true;
+}
+
+// Get the CA which signed the certificate
+X *FindCaSignedX(LIST *o, X *x)
+{
+ X *ret;
+ // Validate arguments
+ if (o == NULL || x == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NULL;
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ X *ca = LIST_DATA(o, i);
+ if (CheckXDateNow(ca))
+ {
+ if (CompareName(ca->subject_name, x->issuer_name))
+ {
+ K *k = GetKFromX(ca);
+ if (k != NULL)
+ {
+ if (CheckSignature(x, k))
+ {
+ ret = CloneX(ca);
+ }
+ FreeK(k);
+ }
+ }
+ else if (CompareX(ca, x))
+ {
+ ret = CloneX(ca);
+ }
+ }
+
+ if (ret != NULL)
+ {
+ break;
+ }
+ }
+ }
+ UnlockList(o);
+
+ return ret;
+}
+
+// Delete trusted CA from Cedar
+bool DeleteCa(CEDAR *cedar, UINT ptr)
+{
+ bool b = false;
+ // Validate arguments
+ if (cedar == NULL || ptr == 0)
+ {
+ return false;
+ }
+
+ LockList(cedar->CaList);
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(cedar->CaList);i++)
+ {
+ X *x = LIST_DATA(cedar->CaList, i);
+
+ if (POINTER_TO_KEY(x) == ptr)
+ {
+ Delete(cedar->CaList, x);
+ FreeX(x);
+
+ b = true;
+
+ break;
+ }
+ }
+ }
+ UnlockList(cedar->CaList);
+
+ return b;
+}
+
+// Add trusted CA to Cedar
+void AddCa(CEDAR *cedar, X *x)
+{
+ // Validate arguments
+ if (cedar == NULL || x == NULL)
+ {
+ return;
+ }
+
+ LockList(cedar->CaList);
+ {
+ UINT i;
+ bool ok = true;
+
+ for (i = 0;i < LIST_NUM(cedar->CaList);i++)
+ {
+ X *exist_x = LIST_DATA(cedar->CaList, i);
+ if (CompareX(exist_x, x))
+ {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ Insert(cedar->CaList, CloneX(x));
+ }
+ }
+ UnlockList(cedar->CaList);
+}
+
+// Delete connection from Cedar
+void DelConnection(CEDAR *cedar, CONNECTION *c)
+{
+ // Validate arguments
+ if (cedar == NULL || c == NULL)
+ {
+ return;
+ }
+
+ LockList(cedar->ConnectionList);
+ {
+ Debug("Connection %s Deleted from Cedar.\n", c->Name);
+ if (Delete(cedar->ConnectionList, c))
+ {
+ ReleaseConnection(c);
+ }
+ }
+ UnlockList(cedar->ConnectionList);
+}
+
+// Get the number of unestablished connections
+UINT GetUnestablishedConnections(CEDAR *cedar)
+{
+ UINT i, ret;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+
+ LockList(cedar->ConnectionList);
+ {
+ for (i = 0;i < LIST_NUM(cedar->ConnectionList);i++)
+ {
+ CONNECTION *c = LIST_DATA(cedar->ConnectionList, i);
+
+ switch (c->Type)
+ {
+ case CONNECTION_TYPE_CLIENT:
+ case CONNECTION_TYPE_INIT:
+ case CONNECTION_TYPE_LOGIN:
+ case CONNECTION_TYPE_ADDITIONAL:
+ switch (c->Status)
+ {
+ case CONNECTION_STATUS_ACCEPTED:
+ case CONNECTION_STATUS_NEGOTIATION:
+ case CONNECTION_STATUS_USERAUTH:
+ ret++;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ UnlockList(cedar->ConnectionList);
+
+ return ret + Count(cedar->AcceptingSockets);
+}
+
+// Add connection to Cedar
+void AddConnection(CEDAR *cedar, CONNECTION *c)
+{
+ char tmp[MAX_SIZE];
+ UINT i;
+ // Validate arguments
+ if (cedar == NULL || c == NULL)
+ {
+ return;
+ }
+
+ // Determine the name of the connection
+ i = Inc(cedar->ConnectionIncrement);
+ Format(tmp, sizeof(tmp), "CID-%u", i);
+ Lock(c->lock);
+ {
+ Free(c->Name);
+ c->Name = CopyStr(tmp);
+ }
+ Unlock(c->lock);
+
+ LockList(cedar->ConnectionList);
+ {
+ Add(cedar->ConnectionList, c);
+ AddRef(c->ref);
+ Debug("Connection %s Inserted to Cedar.\n", c->Name);
+ }
+ UnlockList(cedar->ConnectionList);
+}
+
+// Stop all connections
+void StopAllConnection(CEDAR *c)
+{
+ UINT num;
+ UINT i;
+ CONNECTION **connections;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ LockList(c->ConnectionList);
+ {
+ connections = ToArray(c->ConnectionList);
+ num = LIST_NUM(c->ConnectionList);
+ DeleteAll(c->ConnectionList);
+ }
+ UnlockList(c->ConnectionList);
+
+ for (i = 0;i < num;i++)
+ {
+ StopConnection(connections[i], false);
+ ReleaseConnection(connections[i]);
+ }
+ Free(connections);
+}
+
+// Delete a hub in Cedar
+void DelHub(CEDAR *c, HUB *h)
+{
+ DelHubEx(c, h, false);
+}
+void DelHubEx(CEDAR *c, HUB *h, bool no_lock)
+{
+ // Validate arguments
+ if (c == NULL || h == NULL)
+ {
+ return;
+ }
+
+ if (no_lock == false)
+ {
+ LockHubList(c);
+ }
+
+ if (Delete(c->HubList, h))
+ {
+ ReleaseHub(h);
+ }
+
+ if (no_lock == false)
+ {
+ UnlockHubList(c);
+ }
+}
+
+// Add a new hub to Cedar
+void AddHub(CEDAR *c, HUB *h)
+{
+ // Validate arguments
+ if (c == NULL || h == NULL)
+ {
+ return;
+ }
+
+ LockHubList(c);
+ {
+#if 0
+ // We shall not check here the number of hub
+ if (LIST_NUM(c->HubList) >= MAX_HUBS)
+ {
+ // over limit
+ UnlockHubList(c);
+ return;
+ }
+#endif
+
+ // Confirm there is no hub which have same name
+ if (IsHub(c, h->Name))
+ {
+ // exist
+ UnlockHubList(c);
+ return;
+ }
+
+ // Register the hub
+ Insert(c->HubList, h);
+ AddRef(h->ref);
+ }
+ UnlockHubList(c);
+}
+
+// Stop all hubs in Cedar
+void StopAllHub(CEDAR *c)
+{
+ HUB **hubs;
+ UINT i, num;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ LockHubList(c);
+ {
+ hubs = ToArray(c->HubList);
+ num = LIST_NUM(c->HubList);
+ DeleteAll(c->HubList);
+ }
+ UnlockHubList(c);
+
+ for (i = 0;i < num;i++)
+ {
+ StopHub(hubs[i]);
+ ReleaseHub(hubs[i]);
+ }
+
+ Free(hubs);
+}
+
+// Get reverse listener socket in Cedar
+SOCK *GetReverseListeningSock(CEDAR *c)
+{
+ SOCK *s = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(c->ListenerList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->ListenerList);i++)
+ {
+ LISTENER *r = LIST_DATA(c->ListenerList, i);
+
+ if (r->Protocol == LISTENER_REVERSE)
+ {
+ Lock(r->lock);
+ {
+ s = r->Sock;
+
+ AddRef(s->ref);
+ }
+ Unlock(r->lock);
+ break;
+ }
+ }
+ }
+ UnlockList(c->ListenerList);
+
+ return s;
+}
+
+// Get in-process listener socket in Cedar
+SOCK *GetInProcListeningSock(CEDAR *c)
+{
+ SOCK *s = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(c->ListenerList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->ListenerList);i++)
+ {
+ LISTENER *r = LIST_DATA(c->ListenerList, i);
+
+ if (r->Protocol == LISTENER_INPROC)
+ {
+ Lock(r->lock);
+ {
+ s = r->Sock;
+
+ if (s != NULL)
+ {
+ AddRef(s->ref);
+ }
+ }
+ Unlock(r->lock);
+ break;
+ }
+ }
+ }
+ UnlockList(c->ListenerList);
+
+ return s;
+}
+
+// Add a new listener to Cedar
+void AddListener(CEDAR *c, LISTENER *r)
+{
+ // Validate arguments
+ if (c == NULL || r == NULL)
+ {
+ return;
+ }
+
+ LockList(c->ListenerList);
+ {
+ Add(c->ListenerList, r);
+ AddRef(r->ref);
+ }
+ UnlockList(c->ListenerList);
+}
+
+// Stop all listener in Cedar
+void StopAllListener(CEDAR *c)
+{
+ LISTENER **array;
+ UINT i, num;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ LockList(c->ListenerList);
+ {
+ array = ToArray(c->ListenerList);
+ num = LIST_NUM(c->ListenerList);
+ DeleteAll(c->ListenerList);
+ }
+ UnlockList(c->ListenerList);
+
+ for (i = 0;i < num;i++)
+ {
+ StopListener(array[i]);
+ ReleaseListener(array[i]);
+ }
+ Free(array);
+}
+
+// Stop Cedar
+void StopCedar(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Stop flag
+ c->Halt = true;
+
+ // Stop all listener
+ StopAllListener(c);
+ // Stop all connections
+ StopAllConnection(c);
+ // Stop all hubs
+ StopAllHub(c);
+ // Free all virtual L3 switch
+ L3FreeAllSw(c);
+}
+
+// Clean up Cedar
+void CleanupCedar(CEDAR *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ WuFreeWebUI(c->WebUI);
+ FreeCedarLayer3(c);
+
+/*
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ }
+*/
+ for (i = 0;i < LIST_NUM(c->CaList);i++)
+ {
+ X *x = LIST_DATA(c->CaList, i);
+ FreeX(x);
+ }
+ ReleaseList(c->CaList);
+
+ ReleaseList(c->ListenerList);
+ ReleaseList(c->HubList);
+ ReleaseList(c->ConnectionList);
+ //CleanupUDPEntry(c);
+ ReleaseList(c->UDPEntryList);
+ DeleteLock(c->lock);
+ DeleteCounter(c->ConnectionIncrement);
+ DeleteCounter(c->CurrentSessions);
+
+ if (c->DebugLog != NULL)
+ {
+ FreeLog(c->DebugLog);
+ }
+
+ if (c->ServerX)
+ {
+ FreeX(c->ServerX);
+ }
+ if (c->ServerK)
+ {
+ FreeK(c->ServerK);
+ }
+
+ if (c->CipherList)
+ {
+ Free(c->CipherList);
+ }
+
+ for (i = 0;i < LIST_NUM(c->TrafficDiffList);i++)
+ {
+ TRAFFIC_DIFF *d = LIST_DATA(c->TrafficDiffList, i);
+ Free(d->Name);
+ Free(d->HubName);
+ Free(d);
+ }
+
+ ReleaseList(c->TrafficDiffList);
+
+ Free(c->ServerStr);
+ Free(c->MachineName);
+
+ Free(c->HttpUserAgent);
+ Free(c->HttpAccept);
+ Free(c->HttpAcceptLanguage);
+ Free(c->HttpAcceptEncoding);
+
+ FreeTraffic(c->Traffic);
+
+ DeleteLock(c->TrafficLock);
+
+ FreeNetSvcList(c);
+
+ Free(c->VerString);
+ Free(c->BuildInfo);
+
+ FreeLocalBridgeList(c);
+
+ DeleteCounter(c->AssignedBridgeLicense);
+ DeleteCounter(c->AssignedClientLicense);
+
+ FreeNoSslList(c);
+
+ DeleteLock(c->CedarSuperLock);
+
+ DeleteCounter(c->AcceptingSockets);
+
+ ReleaseIntList(c->UdpPortList);
+
+ DeleteLock(c->OpenVPNPublicPortsLock);
+
+ Free(c);
+}
+
+// Release reference of the Cedar
+void ReleaseCedar(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ CleanupCedar(c);
+ }
+}
+
+// Set cipher list entry
+void SetCedarCipherList(CEDAR *cedar, char *name)
+{
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+
+ if (cedar->CipherList != NULL)
+ {
+ Free(cedar->CipherList);
+ }
+ if (name != NULL)
+ {
+ cedar->CipherList = CopyStr(name);
+ }
+ else
+ {
+ cedar->CipherList = NULL;
+ }
+}
+
+// Compare net service list entries
+int CompareNetSvc(void *p1, void *p2)
+{
+ NETSVC *n1, *n2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ n1 = *(NETSVC **)p1;
+ n2 = *(NETSVC **)p2;
+ if (n1 == NULL || n2 == NULL)
+ {
+ return 0;
+ }
+ if (n1->Port > n2->Port)
+ {
+ return 1;
+ }
+ else if (n1->Port < n2->Port)
+ {
+ return -1;
+ }
+ else if (n1->Udp > n2->Udp)
+ {
+ return 1;
+ }
+ else if (n1->Udp < n2->Udp)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Initialize net service list
+void InitNetSvcList(CEDAR *cedar)
+{
+ char filename[MAX_PATH] = "/etc/services";
+ BUF *b;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Format(filename, sizeof(filename), "%s\\drivers\\etc\\services", MsGetSystem32Dir());
+#endif
+
+ cedar->NetSvcList = NewList(CompareNetSvc);
+
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ char *s = CfgReadNextLine(b);
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Trim(s);
+ if (s[0] != '#')
+ {
+ TOKEN_LIST *t = ParseToken(s, " \t/");
+ if (t->NumTokens >= 3)
+ {
+ NETSVC *n = ZeroMalloc(sizeof(NETSVC));
+ n->Name = CopyStr(t->Token[0]);
+ n->Udp = (StrCmpi(t->Token[2], "udp") == 0 ? true : false);
+ n->Port = ToInt(t->Token[1]);
+ Add(cedar->NetSvcList, n);
+ }
+ FreeToken(t);
+ }
+ Free(s);
+ }
+
+ FreeBuf(b);
+}
+
+// Get net service name
+char *GetSvcName(CEDAR *cedar, bool udp, UINT port)
+{
+ char *ret = NULL;
+ NETSVC t;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ t.Udp = (udp == 0 ? false : true);
+ t.Port = port;
+
+ LockList(cedar->NetSvcList);
+ {
+ NETSVC *n = Search(cedar->NetSvcList, &t);
+ if (n != NULL)
+ {
+ ret = n->Name;
+ }
+ }
+ UnlockList(cedar->NetSvcList);
+
+ return ret;
+}
+
+// Free net service list
+void FreeNetSvcList(CEDAR *cedar)
+{
+ UINT i;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(cedar->NetSvcList);i++)
+ {
+ NETSVC *n = LIST_DATA(cedar->NetSvcList, i);
+ Free(n->Name);
+ Free(n);
+ }
+ ReleaseList(cedar->NetSvcList);
+}
+
+// Change certificate of Cedar
+void SetCedarCert(CEDAR *c, X *server_x, K *server_k)
+{
+ // Validate arguments
+ if (server_x == NULL || server_k == NULL)
+ {
+ return;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->ServerX != NULL)
+ {
+ FreeX(c->ServerX);
+ }
+
+ if (c->ServerK != NULL)
+ {
+ FreeK(c->ServerK);
+ }
+
+ c->ServerX = CloneX(server_x);
+ c->ServerK = CloneK(server_k);
+ }
+ Unlock(c->lock);
+}
+
+// Enable debug log
+void EnableDebugLog(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL || c->DebugLog != NULL)
+ {
+ return;
+ }
+
+ c->DebugLog = NewLog("cedar_debug_log", "cedar", LOG_SWITCH_NO);
+}
+
+// Set the Cedar into VPN Bridge mode
+void SetCedarVpnBridge(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->Bridge = true;
+
+ Free(c->ServerStr);
+ c->ServerStr = CopyStr(CEDAR_BRIDGE_STR);
+}
+
+void CedarForceLink()
+{
+}
+
+// Get version of the Cedar
+void GetCedarVersion(char *tmp, UINT size)
+{
+ // Validate arguments
+ if (tmp == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, size, "%u.%02u.%u",
+ CEDAR_VER / 100, CEDAR_VER - (CEDAR_VER / 100) * 100,
+ CEDAR_BUILD);
+}
+
+// Create Cedar object
+CEDAR *NewCedar(X *server_x, K *server_k)
+{
+ CEDAR *c;
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ char *beta_str;
+
+ CedarForceLink();
+
+ c = ZeroMalloc(sizeof(CEDAR));
+
+ c->AcceptingSockets = NewCounter();
+
+ c->CedarSuperLock = NewLock();
+
+#ifdef BETA_NUMBER
+ c->Beta = BETA_NUMBER;
+#endif // BETA_NUMBER
+
+ InitNoSslList(c);
+
+ c->AssignedBridgeLicense = NewCounter();
+ c->AssignedClientLicense = NewCounter();
+
+ Rand(c->UniqueId, sizeof(c->UniqueId));
+
+ c->CreatedTick = Tick64();
+
+ c->lock = NewLock();
+ c->ref = NewRef();
+
+ c->OpenVPNPublicPortsLock = NewLock();
+ c->CurrentTcpConnections = GetNumTcpConnectionsCounter();
+
+ c->ListenerList = NewList(CompareListener);
+ c->UDPEntryList = NewList(CompareUDPEntry);
+ c->HubList = NewList(CompareHub);
+ c->ConnectionList = NewList(CompareConnection);
+
+ c->ConnectionIncrement = NewCounter();
+ c->CurrentSessions = NewCounter();
+
+ if (server_k && server_x)
+ {
+ c->ServerK = CloneK(server_k);
+ c->ServerX = CloneX(server_x);
+ }
+
+ c->Version = CEDAR_VER;
+ c->Build = CEDAR_BUILD;
+ c->ServerStr = CopyStr(CEDAR_SERVER_STR);
+
+ GetMachineName(tmp, sizeof(tmp));
+ c->MachineName = CopyStr(tmp);
+
+ c->HttpUserAgent = CopyStr(DEFAULT_USER_AGENT);
+ c->HttpAccept = CopyStr(DEFAULT_ACCEPT);
+ c->HttpAcceptLanguage = CopyStr("ja");
+ c->HttpAcceptEncoding = CopyStr(DEFAULT_ENCODING);
+
+ c->Traffic = NewTraffic();
+ c->TrafficLock = NewLock();
+ c->CaList = NewList(CompareCert);
+
+ c->TrafficDiffList = NewList(NULL);
+
+ SetCedarCipherList(c, "RC4-MD5");
+
+ c->ClientId = _II("CLIENT_ID");
+
+ c->UdpPortList = NewIntList(false);
+
+ InitNetSvcList(c);
+
+ InitLocalBridgeList(c);
+
+ InitCedarLayer3(c);
+
+ c->WebUI = WuNewWebUI(c);
+
+#ifdef ALPHA_VERSION
+ beta_str = "Alpha";
+#else // ALPHA_VERSION
+#ifndef RELEASE_CANDIDATE
+ beta_str = "Beta";
+#else // RELEASE_CANDIDATE
+ beta_str = "Release Candidate";
+#endif // RELEASE_CANDIDATE
+#endif // ALPHA_VERSION
+
+ ToStr(tmp2, c->Beta);
+
+ Format(tmp, sizeof(tmp), "Version %u.%02u Build %u %s %s (%s)",
+ CEDAR_VER / 100, CEDAR_VER - (CEDAR_VER / 100) * 100,
+ CEDAR_BUILD,
+ c->Beta == 0 ? "" : beta_str,
+ c->Beta == 0 ? "" : tmp2,
+ _SS("LANGSTR"));
+ Trim(tmp);
+
+ if (true)
+ {
+ SYSTEMTIME st;
+ Zero(&st, sizeof(st));
+
+ st.wYear = BUILD_DATE_Y;
+ st.wMonth = BUILD_DATE_M;
+ st.wDay = BUILD_DATE_D;
+
+ c->BuiltDate = SystemToUINT64(&st);
+ }
+
+ c->VerString = CopyStr(tmp);
+
+ Format(tmp, sizeof(tmp), "Compiled %04u/%02u/%02u %02u:%02u:%02u by %s at %s",
+ BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D, BUILD_DATE_HO, BUILD_DATE_MI, BUILD_DATE_SE, BUILDER_NAME, BUILD_PLACE);
+
+ c->BuildInfo = CopyStr(tmp);
+
+ return c;
+}
+
+// Check whether the Cedar was build after the specified date
+bool IsLaterBuild(CEDAR *c, UINT64 t)
+{
+ SYSTEMTIME sb, st;
+ UINT64 b;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Zero(&sb, sizeof(sb));
+ Zero(&st, sizeof(st));
+
+ UINT64ToSystem(&sb, c->BuiltDate);
+ UINT64ToSystem(&st, t);
+
+ // Ignore time of the day
+ sb.wHour = sb.wMinute = sb.wSecond = sb.wMilliseconds = 0;
+ st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
+
+ b = SystemToUINT64(&sb);
+ t = SystemToUINT64(&st);
+
+ if (b > t)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Cumulate traffic size
+void AddTraffic(TRAFFIC *dst, TRAFFIC *diff)
+{
+ // Validate arguments
+ if (dst == NULL || diff == NULL)
+ {
+ return;
+ }
+
+ dst->Recv.BroadcastBytes += diff->Recv.BroadcastBytes;
+ dst->Recv.BroadcastCount += diff->Recv.BroadcastCount;
+ dst->Recv.UnicastBytes += diff->Recv.UnicastBytes;
+ dst->Recv.UnicastCount += diff->Recv.UnicastCount;
+
+ dst->Send.BroadcastBytes += diff->Send.BroadcastBytes;
+ dst->Send.BroadcastCount += diff->Send.BroadcastCount;
+ dst->Send.UnicastBytes += diff->Send.UnicastBytes;
+ dst->Send.UnicastCount += diff->Send.UnicastCount;
+}
+
+// Create new traffic size object
+TRAFFIC *NewTraffic()
+{
+ TRAFFIC *t;
+
+ t = ZeroMalloc(sizeof(TRAFFIC));
+ return t;
+}
+
+// Free traffic size object
+void FreeTraffic(TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t);
+}
+
+// Initialize Cedar communication module
+void InitCedar()
+{
+ if ((init_cedar_counter++) > 0)
+ {
+ return;
+ }
+
+ // Initialize protocol module
+ InitProtocol();
+}
+
+// Free Cedar communication module
+void FreeCedar()
+{
+ if ((--init_cedar_counter) > 0)
+ {
+ return;
+ }
+
+ // Free protocol module
+ FreeProtocol();
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h
new file mode 100644
index 00000000..bdb725bf
--- /dev/null
+++ b/src/Cedar/Cedar.h
@@ -0,0 +1,1194 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cedar.h
+// Header of Cedar.c
+
+#ifndef CEDAR_H
+#define CEDAR_H
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Products related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+// Replace the function name
+#ifdef VPN_SPEED
+
+#define DecryptSecurePacket __dsp
+#define CreateSecurePacket __csp
+#define GetSecureRandomSize __gsrs
+
+#endif // VPN_SPEED
+
+#define bool UINT
+#define BOOL UINT
+
+
+// Version number
+#define CEDAR_VER 403
+
+// Build Number
+#define CEDAR_BUILD 9408
+
+// Beta number
+//#define BETA_NUMBER 3
+
+// RC or not
+#define RELEASE_CANDIDATE
+
+// Specify the name of the person in charge building
+#ifndef BUILDER_NAME
+#define BUILDER_NAME "yagi"
+#endif // BUILDER_NAME
+
+// Specify the location to build
+#ifndef BUILD_PLACE
+#define BUILD_PLACE "pc25"
+#endif // BUILD_PLACE
+
+// Specifies the build date
+#define BUILD_DATE_Y 2014
+#define BUILD_DATE_M 1
+#define BUILD_DATE_D 4
+#define BUILD_DATE_HO 19
+#define BUILD_DATE_MI 10
+#define BUILD_DATE_SE 55
+
+// Tolerable time difference
+#define ALLOW_TIMESTAMP_DIFF (UINT64)(3 * 24 * 60 * 60 * 1000)
+
+
+// Configuration of communication related control switch
+#define USE_DOS_ATTACK_DETECTION // Enable the DOS attack detection
+//#define USE_SECURE_PACKET // Enable the scrambled packet
+
+// Designate the IDS detection signatures
+#define CEDAR_SIGNATURE_STR "SE-VPN4-PROTOCOL"
+
+// Default RSA certificate name of the smart card
+#define SECURE_DEFAULT_CERT_NAME "VPN_RSA_CERT"
+
+// Default RSA private key name of the smart card
+#define SECURE_DEFAULT_KEY_NAME "VPN_RSA_KEY"
+
+// Hidden password string of 8 characters
+#define HIDDEN_PASSWORD "********"
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Definition of the maximum length of various string
+//
+//////////////////////////////////////////////////////////////////////
+
+#define MAX_ACCOUNT_NAME_LEN 255 // Maximum account name length
+#define MAX_USERNAME_LEN 255 // User name maximum length
+#define MAX_PASSWORD_LEN 255 // Password name maximum length
+#define MAX_PROXY_USERNAME_LEN 255 // Proxy user name maximum length
+#define MAX_PROXY_PASSWORD_LEN 255 // Proxy Password maximum length
+#define MAX_SERVER_STR_LEN 255 // Maximum length of server string
+#define MAX_CLIENT_STR_LEN 255 // Maximum length of client string
+#define MAX_HUBNAME_LEN 255 // Maximum length of HUB name
+#define MAX_SESSION_NAME_LEN 255 // Session name maximum length
+#define MAX_CONNECTION_NAME_LEN 255 // Maximum length of connection name
+#define MAX_DEVICE_NAME_LEN 31 // Device name maximum length
+#define MAX_DEVICE_NAME_LEN_9X 4 // Maximum length of Virtual LAN card name in Win9x
+#define MAX_ACCESSLIST_NOTE_LEN 255 // Maximum length of the note of access list entry
+#define MAX_SECURE_DEVICE_FILE_LEN 255 // Secure device file name maximum length
+#define MAX_ADMIN_OPTION_NAME_LEN 63 // Management option name
+#define MAX_REDIRECT_URL_LEN 255 // URL length to redirect
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Server and session management related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+#define SERVER_MAX_SESSIONS 4096 // Maximum number of sessions that the server supports
+#define SERVER_MAX_SESSIONS_FOR_CARRIER_EDITION 100000 // Maximum number of sessions that the server supports (Carrier Edition)
+#define NAT_MAX_SESSIONS 4096 // Maximum number of sessions that are supported by NAT
+#define NAT_MAX_SESSIONS_KERNEL 65536 // Maximum number of sessions that are supported by NAT (In the case of kernel-mode NAT)
+#define MAX_HUBS 4096 // The maximum number of virtual HUB
+#define MAX_HUBS_FOR_CARRIER_EDITION 100000 // The maximum number of virtual HUB (Carrier Edition)
+#define MAX_ACCESSLISTS (4096 * 8) // Maximum number of access list entries
+#define MAX_USERS 10000 // The maximum number of users
+#define MAX_GROUPS 10000 // Maximum number of groups
+#define MAX_MAC_TABLES 65536 // Maximum number of MAC address table entries
+#define MAX_IP_TABLES 65536 // Maximum number of IP address table entries
+#define MAX_HUB_CERTS 4096 // Maximum number of Root CA that can be registered
+#define MAX_HUB_CRLS 4096 // Maximum number of CRL that can be registered
+#define MAX_HUB_ACS 4096 // Maximum number of AC that can be registered
+#define MAX_HUB_LINKS 128 // Maximum number of Cascade that can be registered
+#define MAX_HUB_ADMIN_OPTIONS 4096 // Maximum number of Virtual HUB management options that can be registered
+
+#define MAX_PACKET_SIZE 1560 // Maximum packet size
+#define UDP_BUF_SIZE (32 * 1024) // Aim of the UDP packet size
+
+#define MAX_SEND_SOCKET_QUEUE_SIZE (1600 * 1600 * 1) // Maximum transmit queue size
+#define MIN_SEND_SOCKET_QUEUE_SIZE (1600 * 200 * 1)
+#define MAX_SEND_SOCKET_QUEUE_NUM 128 // Maximum transmission queue items
+#define MAX_TCP_CONNECTION 32 // The maximum number of TCP connections
+#define NUM_TCP_CONNECTION_FOR_UDP_RECOVERY 2 // Maximum number of connections when using UDP recovery
+#define SELECT_TIME 256
+#define SELECT_TIME_FOR_NAT 30
+#define SELECT_TIME_FOR_DELAYED_PKT 1 // If there is a delayed packet
+#define MAX_STORED_QUEUE_NUM 1024 // The number of queues that can be stored in each session
+#define MAX_BUFFERING_PACKET_SIZE (1600 * 1600) // Maximum packet size can be buffered
+
+#define TIMEOUT_MIN (5 * 1000) // Minimum timeout in seconds
+#define TIMEOUT_MAX (60 * 1000) // Maximum timeout in seconds
+#define TIMEOUT_DEFAULT (30 * 1000) // Default number of seconds to timeout
+#define CONNECTING_TIMEOUT (15 * 1000) // Timeout in seconds of being connected
+#define CONNECTING_TIMEOUT_PROXY (4 * 1000) // Timeout in seconds of being connected (Proxy)
+#define CONNECTING_POOLING_SPAN (3 * 1000) // Polling interval of connected
+#define MIN_RETRY_INTERVAL (5 * 1000) // Minimum retry interval
+#define MAX_RETRY_INTERVAL (300 * 1000) // Maximum retry interval
+#define RETRY_INTERVAL_SPECIAL (60 * 1000) // Reconnection interval of a special case
+
+#define MAX_ADDITONAL_CONNECTION_FAILED_COUNTER 16 // Allowable number that can be serially failed to additional connection
+#define ADDITIONAL_CONNECTION_COUNTER_RESET_INTERVAL (30 * 60 * 1000) // Reset period of additional connection failure counter
+
+#define MAC_MIN_LIMIT_COUNT 3 // Minimum number of MAC addresses
+#define IP_MIN_LIMIT_COUNT 4 // Number of IPv4 addresses minimum
+#define IP_MIN_LIMIT_COUNT_V6 5 // Number of IPv6 addresses minimum
+#define IP_LIMIT_WHEN_NO_ROUTING_V6 15 // Maximum number of IPv6 addresses when NoRouting policy is enabled
+
+#define MAC_TABLE_EXCLUSIVE_TIME (13 * 1000) // Period that can occupy the MAC address
+#define IP_TABLE_EXCLUSIVE_TIME (13 * 1000) // Period that can occupy the IP address
+#define MAC_TABLE_EXPIRE_TIME (600 * 1000) // MAC address table expiration date
+#define IP_TABLE_EXPIRE_TIME (60 * 1000) // IP address table expiration date
+#define IP_TABLE_EXPIRE_TIME_DHCP (5 * 60 * 1000) // IP address table expiration date (In the case of DHCP)
+#define HUB_ARP_SEND_INTERVAL (5 * 1000) // ARP packet transmission interval (alive check)
+
+#define LIMITER_SAMPLING_SPAN 1000 // Sampling interval of the traffic limiting device
+
+#define STORM_CHECK_SPAN 500 // Broadcast storm check interval
+#define STORM_DISCARD_VALUE_START 3 // Broadcast packet discard value start value
+#define STORM_DISCARD_VALUE_END 1024 // Broadcast packet discard value end value
+
+#define KEEP_INTERVAL_MIN 5 // Packet transmission interval minimum value
+#define KEEP_INTERVAL_DEFAULT 50 // Packet transmission interval default value
+#define KEEP_INTERVAL_MAX 600 // Packet transmission interval maximum value
+#define KEEP_TCP_TIMEOUT 1000 // TCP time-out value
+
+#define TICKET_EXPIRES (60 * 1000) // Expiration date of ticket
+
+#define SEND_KILL_NUM_X 256 // Number of 'X' characters to send the Kill
+
+
+#define FARM_BASE_POINT 100000 // Reference value of the cluster score
+#define FARM_DEFAULT_WEIGHT 100 // Standard performance ratio
+
+
+
+#define SE_UDP_SIGN "SE2P" // Not used (only old UDP mode)
+
+// R-UDP service name
+#define VPN_RUDP_SVC_NAME "SoftEther_VPN"
+
+// Traffic information update interval
+#define INCREMENT_TRAFFIC_INTERVAL (10 * 1000)
+
+// State of the client session
+#define CLIENT_STATUS_CONNECTING 0 // Connecting
+#define CLIENT_STATUS_NEGOTIATION 1 // Negotiating
+#define CLIENT_STATUS_AUTH 2 // During user authentication
+#define CLIENT_STATUS_ESTABLISHED 3 // Connection complete
+#define CLIENT_STATUS_RETRY 4 // Wait to retry
+#define CLIENT_STATUS_IDLE 5 // Idle state
+
+// Expiration date of the black list
+#define BLACK_LIST_EXPIRES (30 * 10000)
+
+// Number Blacklist entries
+#define MAX_BLACK_LIST 4096
+#define BLACK_LIST_CHECK_SPAN 1000
+
+// Blocks to be transmitted at one during the file transfer
+#define FTP_BLOCK_SIZE (640 * 1024)
+
+// Syslog configuration
+#define SYSLOG_NONE 0 // Do not use syslog
+#define SYSLOG_SERVER_LOG 1 // Only server log
+#define SYSLOG_SERVER_AND_HUB_SECURITY_LOG 2 // Server and Virtual HUB security log
+#define SYSLOG_SERVER_AND_HUB_ALL_LOG 3 // Server, Virtual HUB security, and packet log
+
+#define SYSLOG_PORT 514 // Syslog port number
+#define SYSLOG_POLL_IP_INTERVAL (UINT64)(3600 * 1000) // Interval to examine the IP address
+#define SYSLOG_POLL_IP_INTERVAL_NG (UINT64)(60 * 1000) // Interval to examine the IP address (previous failure)
+
+//////////////////////////////////////////////////////////////////////
+//
+// Connection-related constant
+//
+//////////////////////////////////////////////////////////////////////
+
+// Internet connection maintenance function (KeepAlive)
+
+#define KEEP_RETRY_INTERVAL (60 * 1000) // Reconnection interval on connection failure
+#define KEEP_MIN_PACKET_SIZE 1 // Minimum packet size
+#define KEEP_MAX_PACKET_SIZE 128 // Maximum packet size
+#define KEEP_POLLING_INTERVAL 250 // KEEP polling interval
+
+// Constants
+#define RECV_BUF_SIZE 65536 // Buffer size to be received at a time
+
+// Type of proxy
+#define PROXY_DIRECT 0 // Direct TCP connection
+#define PROXY_HTTP 1 // Connection via HTTP proxy server
+#define PROXY_SOCKS 2 // Connection via SOCKS proxy server
+
+// Direction of data flow
+#define TCP_BOTH 0 // Bi-directional
+#define TCP_SERVER_TO_CLIENT 1 // Only server -> client direction
+#define TCP_CLIENT_TO_SERVER 2 // Only client -> server direction
+
+// Type of connection
+#define CONNECTION_TYPE_CLIENT 0 // Client
+#define CONNECTION_TYPE_INIT 1 // During initialization
+#define CONNECTION_TYPE_LOGIN 2 // Login connection
+#define CONNECTION_TYPE_ADDITIONAL 3 // Additional connection
+#define CONNECTION_TYPE_FARM_RPC 4 // RPC for server farm
+#define CONNECTION_TYPE_ADMIN_RPC 5 // RPC for Management
+#define CONNECTION_TYPE_ENUM_HUB 6 // HUB enumeration
+#define CONNECTION_TYPE_PASSWORD 7 // Password change
+#define CONNECTION_TYPE_SSTP 8 // SSTP
+#define CONNECTION_TYPE_OPENVPN 9 // OpenVPN
+
+// Protocol
+#define CONNECTION_TCP 0 // TCP protocol
+#define CONNECTION_UDP 1 // UDP protocol
+#define CONNECTION_HUB_LAYER3 6 // Layer-3 switch session
+#define CONNECTION_HUB_BRIDGE 7 // Bridge session
+#define CONNECTION_HUB_SECURE_NAT 8 // Secure NAT session
+#define CONNECTION_HUB_LINK_SERVER 9 // HUB link session
+
+
+// Status
+#define CONNECTION_STATUS_ACCEPTED 0 // The connection is accepted (client side)
+#define CONNECTION_STATUS_NEGOTIATION 1 // Negotiating
+#define CONNECTION_STATUS_USERAUTH 2 // During user authentication
+#define CONNECTION_STATUS_ESTABLISHED 3 // Connection has been established
+#define CONNECTION_STATUS_CONNECTING 0 // Connecting (client side)
+
+// Magic number of KeepAlive packet
+#define KEEP_ALIVE_MAGIC 0xffffffff
+#define MAX_KEEPALIVE_SIZE 512
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Virtual HUB-related constant
+//
+//////////////////////////////////////////////////////////////////////
+
+#define SE_HUB_MAC_ADDR_SIGN 0xAE // Sign virtual HUB MAC address
+
+// Traffic difference value
+#define TRAFFIC_DIFF_USER 0 // User
+#define TRAFFIC_DIFF_HUB 1 // Virtual HUB
+#define MAX_TRAFFIC_DIFF 30000 // Maximum number of items
+
+// Type of HUB
+#define HUB_TYPE_STANDALONE 0 // Stand-alone HUB
+#define HUB_TYPE_FARM_STATIC 1 // Static HUB
+#define HUB_TYPE_FARM_DYNAMIC 2 // Dynamic HUB
+
+// Related to delay, jitter, packet loss in the access list
+#define HUB_ACCESSLIST_DELAY_MAX 10000 // Maximum delay
+#define HUB_ACCESSLIST_JITTER_MAX 100 // Maximum jitter
+#define HUB_ACCESSLIST_LOSS_MAX 100 // Maximum packet loss
+
+// Message related
+#define HUB_MAXMSG_LEN 20000 // The maximum number of characters in a message
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Type of user authentication
+//
+//////////////////////////////////////////////////////////////////////
+
+// Constant in the server-side
+#define AUTHTYPE_ANONYMOUS 0 // Anonymous authentication
+#define AUTHTYPE_PASSWORD 1 // Password authentication
+#define AUTHTYPE_USERCERT 2 // User certificate authentication
+#define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority
+#define AUTHTYPE_RADIUS 4 // Radius authentication
+#define AUTHTYPE_NT 5 // Windows NT authentication
+#define AUTHTYPE_TICKET 99 // Ticket authentication
+
+// Constant of the client side
+#define CLIENT_AUTHTYPE_ANONYMOUS 0 // Anonymous authentication
+#define CLIENT_AUTHTYPE_PASSWORD 1 // Password authentication
+#define CLIENT_AUTHTYPE_PLAIN_PASSWORD 2 // Plain password authentication
+#define CLIENT_AUTHTYPE_CERT 3 // Certificate authentication
+#define CLIENT_AUTHTYPE_SECURE 4 // Secure device authentication
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// TCP listener related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+// Retries in case it fails to Listen
+#define LISTEN_RETRY_TIME (2 * 1000) // If fail to Listen normally
+#define LISTEN_RETRY_TIME_NOIPV6 (60 * 1000) // If IPv6 support is disabled
+
+#define DOS_TABLE_EXPIRES_FIRST 250 // Initial value of the expiration date of DOS attack list
+#define DOS_TABLE_EXPIRES_MAX 1000 // Maximum value of the expiration date of DOS attack list
+#define DOS_TABLE_REFRESH_INTERVAL (10 * 1000) // Interval to update the DOS attack list
+#define DOS_TABLE_MAX_LIMIT_PER_IP 16 // Accessible number per an IP
+#define DOS_TABLE_EXPIRES_TOTAL (3000 * 1000) // Time to force delete the entry
+
+
+// Protocol to be used for the listener
+#define LISTENER_TCP 0 // TCP/IP
+#define LISTENER_UDP 1 // UDP/IP (not being used)
+#define LISTENER_INPROC 2 // In-process communication
+#define LISTENER_RUDP 3 // R-UDP with NAT-T
+#define LISTENER_ICMP 4 // VPN over ICMP
+#define LISTENER_DNS 5 // VPN over DNS
+#define LISTENER_REVERSE 6 // Reverse socket
+
+// Status of the listener
+#define LISTENER_STATUS_TRYING 0 // While attempting
+#define LISTENER_STATUS_LISTENING 1 // Listening
+
+// Largest packet size of UDP
+#define UDP_PACKET_SIZE 65536
+
+// Number of standard connections per IP address
+#define DEFAULT_MAX_CONNECTIONS_PER_IP 256
+#define MIN_MAX_CONNECTIONS_PER_IP 10 // Minimum value
+
+// Allowed number of outstanding connections
+#define DEFAULT_MAX_UNESTABLISHED_CONNECTIONS 1000
+#define MIN_MAX_UNESTABLISHED_CONNECTIONS 30 // Minimum value
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Log related constant
+//
+//////////////////////////////////////////////////////////////////////
+
+#define LOG_ENGINE_SAVE_START_CACHE_COUNT 100000 // Number to start saving forcibly
+#define LOG_ENGINE_BUFFER_CACHE_SIZE_MAX (10 * 1024 * 1024) // Write cache size
+
+// Constant such as a file name
+#define SERVER_LOG_DIR_NAME "@server_log"
+#define BRIDGE_LOG_DIR_NAME SERVER_LOG_DIR_NAME
+#define SERVER_LOG_PERFIX "vpn"
+
+#define HUB_SECURITY_LOG_DIR_NAME "@security_log"
+#define HUB_SECURITY_LOG_FILE_NAME "@security_log/%s"
+#define HUB_SECURITY_LOG_PREFIX "sec"
+#define HUB_PACKET_LOG_DIR_NAME "@packet_log"
+#define HUB_PACKET_LOG_FILE_NAME "@packet_log/%s"
+#define HUB_PACKET_LOG_PREFIX "pkt"
+
+#define NAT_LOG_DIR_NAME "@secure_nat_log"
+#define NAT_LOG_FILE_NAME "@secure_nat_log/%s"
+#define NAT_LOG_PREFIX "snat"
+
+#define CLIENT_LOG_DIR_NAME "@client_log"
+#define CLIENT_LOG_PREFIX "client"
+
+// Packet log settings
+#define NUM_PACKET_LOG 16
+#define PACKET_LOG_TCP_CONN 0 // TCP connection log
+#define PACKET_LOG_TCP 1 // TCP packet log
+#define PACKET_LOG_DHCP 2 // DHCP Log
+#define PACKET_LOG_UDP 3 // UDP log
+#define PACKET_LOG_ICMP 4 // ICMP log
+#define PACKET_LOG_IP 5 // IP log
+#define PACKET_LOG_ARP 6 // ARP log
+#define PACKET_LOG_ETHERNET 7 // Ethernet log
+
+#define PACKET_LOG_NONE 0 // Not save
+#define PACKET_LOG_HEADER 1 // Only header
+#define PACKET_LOG_ALL 2 // Store also data
+
+// Timing of log switching
+#define LOG_SWITCH_NO 0 // Without switching
+#define LOG_SWITCH_SECOND 1 // Secondly basis
+#define LOG_SWITCH_MINUTE 2 // Minutely basis
+#define LOG_SWITCH_HOUR 3 // Hourly basis
+#define LOG_SWITCH_DAY 4 // Daily basis
+#define LOG_SWITCH_MONTH 5 // Monthly basis
+
+// Minimum amount of free disk space
+#define DISK_FREE_SPACE_MIN 1048576 // 1 MBytes
+#define DISK_FREE_SPACE_DEFAULT (DISK_FREE_SPACE_MIN * 100) // 100 Mbytes
+#define DISK_FREE_SPACE_DEFAULT_WINDOWS ((UINT64)(8ULL * 1024ULL * 1024ULL * 1024ULL)) // 8GBytes
+
+// Interval to check the free space
+#define DISK_FREE_CHECK_INTERVAL (5 * 60 * 1000)
+
+// Simple log
+#define TINY_LOG_DIRNAME "@tiny_log"
+#define TINY_LOG_FILENAME "@tiny_log/%04u%02u%02u_%02u%02u%02u.log"
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Constant related to Carrier Edition
+//
+//////////////////////////////////////////////////////////////////////
+
+#define CE_SNAPSHOT_INTERVAL ((UINT64)(3600 * 1000))
+//#define CE_SNAPSHOT_INTERVAL ((UINT64)(3000))
+#define CE_SNAPSHOT_POLLING_INTERVAL (1 * 1000)
+#define CE_SNAPSHOT_POLLING_INTERVAL_LICENSE (30 * 1000)
+#define CE_SNAPSHOT_DIR_NAME "@carrier_log"
+#define CE_SNAPSHOT_PREFIX "carrier"
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Communication protocol related constant
+//
+//////////////////////////////////////////////////////////////////////
+
+// Administrator Username
+#define ADMINISTRATOR_USERNAME "administrator"
+// Maximum value of random size
+#define RAND_SIZE_MAX 4096
+// Expiration date of random size cache
+#define RAND_SIZE_CACHE_EXPIRE (24 * 60 * 60 * 1000)
+// Management allowed IP address list file name
+#define ADMINIP_TXT "@adminip.txt"
+
+#define NON_SSL_MIN_COUNT 60
+#define NON_SSL_ENTRY_EXPIRES (10 * 60 * 1000)
+
+//////////////////////////////////////////////////////////////////////
+//
+// The cascade related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+#define LINK_DEVICE_NAME "_SEHUBLINKCLI_"
+#define LINK_USER_NAME "link"
+#define LINK_USER_NAME_PRINT "Cascade"
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Constant related to SecureNAT connection
+//
+//////////////////////////////////////////////////////////////////////
+
+#define SNAT_DEVICE_NAME "_SEHUBSECURENAT_"
+#define SNAT_USER_NAME "securenat"
+#define SNAT_USER_NAME_PRINT "SecureNAT"
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Constant related to bridge connection
+//
+//////////////////////////////////////////////////////////////////////
+
+#define BRIDGE_DEVICE_NAME "_SEHUBBRIDGE_"
+#define BRIDGE_USER_NAME "localbridge"
+#define BRIDGE_USER_NAME_PRINT "Local Bridge"
+#define BRIDGE_TRY_SPAN 1000
+#define BRIDGE_NUM_DEVICE_CHECK_SPAN (5 * 60 * 1000)
+#define BRIDGE_NETWORK_CONNECTION_STR L"%s [%S]"
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// EtherLogger related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+#define EL_ADMIN_PORT 22888
+#define EL_CONFIG_FILENAME "@etherlogger.config"
+#define EL_PACKET_LOG_DIR_NAME "@etherlogger_log"
+#define EL_PACKET_LOG_FILE_NAME "@etherlogger_log/%s"
+#define EL_PACKET_LOG_PREFIX "pkt"
+#define EL_LICENSE_CHECK_SPAN (10 * 1000)
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Layer-3 Switch related constants
+//
+//////////////////////////////////////////////////////////////////////
+
+#define MAX_NUM_L3_SWITCH 4096
+#define MAX_NUM_L3_IF 4096
+#define MAX_NUM_L3_TABLE 4096
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Constant related to User-mode Router
+//
+//////////////////////////////////////////////////////////////////////
+
+#define ARP_ENTRY_EXPIRES (30 * 1000) // ARP table expiration date
+#define ARP_ENTRY_POLLING_TIME (1 * 1000) // ARP table cleaning timer
+#define ARP_REQUEST_TIMEOUT (200) // ARP request time-out period
+#define ARP_REQUEST_GIVEUP (5 * 1000) // Time to give up sending the ARP request
+#define IP_WAIT_FOR_ARP_TIMEOUT (5 * 1000) // Total time that an IP packet waiting for ARP table
+#define IP_COMBINE_TIMEOUT (10 * 1000) // Time-out of IP packet combining
+#define NAT_TCP_MAX_TIMEOUT (2000000 * 1000) // Maximum TCP session timeout in seconds
+#define NAT_UDP_MAX_TIMEOUT (2000000 * 1000) // Maximum UDP session timeout in seconds
+#define NAT_TCP_MIN_TIMEOUT (1 * 60 * 1000) // Minimum TCP session timeout in seconds
+#define NAT_UDP_MIN_TIMEOUT (10 * 1000) // Minimum UDP session timeout in seconds
+#define NAT_TCP_RECV_WINDOW_SIZE 64512 // TCP receive window size
+#define NAT_TCP_SYNACK_SEND_TIMEOUT 250 // Sending TCP SYN+ACK interval
+#define NAT_ICMP_TIMEOUT (10 * 1000) // ICMP timeout in seconds
+#define NAT_ICMP_TIMEOUT_WITH_API (3 * 1000) // Timeout in seconds in the case of using the ICMP API
+#define NAT_SEND_BUF_SIZE (64 * 1024) // TCP send buffer size
+#define NAT_RECV_BUF_SIZE (64 * 1024) // TCP receive buffer size
+#define NAT_TMPBUF_SIZE (128 * 1024) // TCP temporally memory area size
+#define NAT_ACK_KEEPALIVE_SPAN (5 * 1000) // ACK transmission interval for TCP keep alive
+#define NAT_INITIAL_RTT_VALUE 500 // Initial RTT value
+#define NAT_FIN_SEND_INTERVAL 1000 // FIN transmission interval
+#define NAT_FIN_SEND_MAX_COUNT 5 // Total number of FIN transmissions
+#define NAT_DNS_PROXY_PORT 53 // DNS proxy port number
+#define NAT_DNS_RESPONSE_TTL (20 * 60) // TTL of the DNS response
+#define NAT_DHCP_SERVER_PORT 67 // DHCP server port number
+#define NAT_DHCP_CLIENT_PORT 68 // DHCP client port number
+#define DHCP_MIN_EXPIRE_TIMESPAN (15 * 1000) // DHCP minimum expiration date
+#define DHCP_POLLING_INTERVAL 1000 // DHCP polling interval
+#define X32 ((UINT64)4294967296ULL) // 32bit + 1
+#define NAT_DNS_QUERY_TIMEOUT (512) // Time-out value of DNS queries
+
+// Beacon transmission interval
+#define BEACON_SEND_INTERVAL (5 * 1000)
+
+// Total size quota allowed in the queue for the combining the IP packet
+#define IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA (50 * 1024 * 1024)
+
+// Header size constant
+#define MAC_HEADER_SIZE (sizeof(MAC_HEADER))
+#define ARP_HEADER_SIZE (sizeof(ARP_HEADER))
+#define IP_HEADER_SIZE (sizeof(IPV4_HEADER))
+#define TCP_HEADER_SIZE (sizeof(TCP_HEADER))
+#define UDP_HEADER_SIZE (sizeof(UDP_HEADER))
+
+// Data maximum size constant
+#define MAX_L3_DATA_SIZE (1500)
+#define MAX_IP_DATA_SIZE (MAX_L3_DATA_SIZE - IP_HEADER_SIZE)
+#define MAX_TCP_DATA_SIZE (MAX_IP_DATA_SIZE - TCP_HEADER_SIZE)
+#define MAX_UDP_DATA_SIZE (MAX_IP_DATA_SIZE - UDP_HEADER_SIZE)
+#define MAX_IP_DATA_SIZE_TOTAL (65535)
+
+// IP packet option constant
+#define DEFAULT_IP_TOS 0 // TOS in the IP header
+#define DEFAULT_IP_TTL 128 // TTL in the IP header
+
+// Type of NAT session
+#define NAT_TCP 0 // TCP NAT
+#define NAT_UDP 1 // UDP NAT
+#define NAT_DNS 2 // DNS NAT
+#define NAT_ICMP 3 // ICMP NAT
+
+// State of NAT session
+#define NAT_TCP_CONNECTING 0 // Connecting
+#define NAT_TCP_SEND_RESET 1 // Send the RST (Connection failure or disconnected)
+#define NAT_TCP_CONNECTED 2 // Connection complete
+#define NAT_TCP_ESTABLISHED 3 // Connection established
+#define NAT_TCP_WAIT_DISCONNECT 4 // Wait for socket disconnection
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// For UNIX virtual LAN card related constant
+//
+//////////////////////////////////////////////////////////////////////
+
+#define TAP_FILENAME_1 "/dev/net/tun"
+#define TAP_FILENAME_2 "/dev/tun"
+#define TAP_MACOS_FILENAME "/dev/tap0"
+
+
+
+
+
+#define LICENSE_EDITION_VPN3_NO_LICENSE 0 // Without license
+
+#define LICENSE_MAX_PRODUCT_NAME_LEN 255 // Maximum length of license product name
+#define LICENSE_NUM_SHA 10000 // Number of times to hash with SHA
+#define LICENSE_SYSTEM_KEY_NUM 2048 // Key number for system
+#define LICENSE_SYSTEM_KEYSIZE_BIT 144 // Number of key bits for system
+#define LICENSE_PRODUCT_KEY_NUM 16384 // Number of keys for product
+#define LICENSE_PRODUCT_KEYSIZE_BIT 56 // Number of key bits for product
+#define LICENSE_PRODUCT_COMMON_KEYSIZE_BIT 48 // Number of common key bits for product
+#define LICENSE_MASTER_KEYSIZE_BIT 1024 // Number of master key bits
+#define LICENSE_SYSTEM_ID_MIN 0ULL // System ID minimum value
+#define LICENSE_SYSTEM_ID_MAX 549755813887ULL // System ID maximum value
+#define LICENSE_SERIAL_ID_MIN 0 // Serial ID minimum value
+#define LICENSE_SERIAL_ID_MAX 65535 // Serial ID maximum value
+#define LICENSE_EXPIRES_MIN 0 // Expiration date minimum
+#define LICENSE_EXPIRES_MAX 16383 // Expiration date maximum
+#define LICENSE_KEYSTR_LEN 41 // Length of the license key
+#define LICENSE_LICENSEID_STR_LEN 33 // Length of the license ID
+
+#define LICENSE_STATUS_OK 0 // Enabled
+#define LICENSE_STATUS_EXPIRED 1 // Invalid (expired)
+#define LICENSE_STATUS_ID_DIFF 2 // Invalid (System ID mismatch)
+#define LICENSE_STATUS_DUP 3 // Invalid (duplicated)
+#define LICENSE_STATUS_INSUFFICIENT 4 // Invalid (other necessary license shortage)
+#define LICENSE_STATUS_COMPETITION 5 // Invalid (conflict with other licenses)
+#define LICENSE_STATUS_NONSENSE 6 // Invalid (meaningless in the current edition)
+#define LICENSE_STATUS_CPU 7 // Invalid (CPU type mismatch)
+
+#define BIT_TO_BYTE(x) (((x) + 7) / 8)
+#define BYTE_TO_BIT(x) ((x) * 8)
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Error code
+//
+//////////////////////////////////////////////////////////////////////
+
+#define ERR_NO_ERROR 0 // No error
+#define ERR_CONNECT_FAILED 1 // Connection to the server has failed
+#define ERR_SERVER_IS_NOT_VPN 2 // The destination server is not a VPN server
+#define ERR_DISCONNECTED 3 // The connection has been interrupted
+#define ERR_PROTOCOL_ERROR 4 // Protocol error
+#define ERR_CLIENT_IS_NOT_VPN 5 // Connecting client is not a VPN client
+#define ERR_USER_CANCEL 6 // User cancel
+#define ERR_AUTHTYPE_NOT_SUPPORTED 7 // Specified authentication method is not supported
+#define ERR_HUB_NOT_FOUND 8 // The HUB does not exist
+#define ERR_AUTH_FAILED 9 // Authentication failure
+#define ERR_HUB_STOPPING 10 // HUB is stopped
+#define ERR_SESSION_REMOVED 11 // Session has been deleted
+#define ERR_ACCESS_DENIED 12 // Access denied
+#define ERR_SESSION_TIMEOUT 13 // Session times out
+#define ERR_INVALID_PROTOCOL 14 // Protocol is invalid
+#define ERR_TOO_MANY_CONNECTION 15 // Too many connections
+#define ERR_HUB_IS_BUSY 16 // Too many sessions of the HUB
+#define ERR_PROXY_CONNECT_FAILED 17 // Connection to the proxy server fails
+#define ERR_PROXY_ERROR 18 // Proxy Error
+#define ERR_PROXY_AUTH_FAILED 19 // Failed to authenticate on the proxy server
+#define ERR_TOO_MANY_USER_SESSION 20 // Too many sessions of the same user
+#define ERR_LICENSE_ERROR 21 // License error
+#define ERR_DEVICE_DRIVER_ERROR 22 // Device driver error
+#define ERR_INTERNAL_ERROR 23 // Internal error
+#define ERR_SECURE_DEVICE_OPEN_FAILED 24 // The secure device cannot be opened
+#define ERR_SECURE_PIN_LOGIN_FAILED 25 // PIN code is incorrect
+#define ERR_SECURE_NO_CERT 26 // Specified certificate is not stored
+#define ERR_SECURE_NO_PRIVATE_KEY 27 // Specified private key is not stored
+#define ERR_SECURE_CANT_WRITE 28 // Write failure
+#define ERR_OBJECT_NOT_FOUND 29 // Specified object can not be found
+#define ERR_VLAN_ALREADY_EXISTS 30 // Virtual LAN card with the specified name already exists
+#define ERR_VLAN_INSTALL_ERROR 31 // Specified virtual LAN card cannot be created
+#define ERR_VLAN_INVALID_NAME 32 // Specified name of the virtual LAN card is invalid
+#define ERR_NOT_SUPPORTED 33 // Unsupported
+#define ERR_ACCOUNT_ALREADY_EXISTS 34 // Account already exists
+#define ERR_ACCOUNT_ACTIVE 35 // Account is operating
+#define ERR_ACCOUNT_NOT_FOUND 36 // Specified account doesn't exist
+#define ERR_ACCOUNT_INACTIVE 37 // Account is offline
+#define ERR_INVALID_PARAMETER 38 // Parameter is invalid
+#define ERR_SECURE_DEVICE_ERROR 39 // Error has occurred in the operation of the secure device
+#define ERR_NO_SECURE_DEVICE_SPECIFIED 40 // Secure device is not specified
+#define ERR_VLAN_IS_USED 41 // Virtual LAN card in use by account
+#define ERR_VLAN_FOR_ACCOUNT_NOT_FOUND 42 // Virtual LAN card of the account can not be found
+#define ERR_VLAN_FOR_ACCOUNT_USED 43 // Virtual LAN card of the account is already in use
+#define ERR_VLAN_FOR_ACCOUNT_DISABLED 44 // Virtual LAN card of the account is disabled
+#define ERR_INVALID_VALUE 45 // Value is invalid
+#define ERR_NOT_FARM_CONTROLLER 46 // Not a farm controller
+#define ERR_TRYING_TO_CONNECT 47 // Attempting to connect
+#define ERR_CONNECT_TO_FARM_CONTROLLER 48 // Failed to connect to the farm controller
+#define ERR_COULD_NOT_HOST_HUB_ON_FARM 49 // A virtual HUB on farm could not be created
+#define ERR_FARM_MEMBER_HUB_ADMIN 50 // HUB cannot be managed on a farm member
+#define ERR_NULL_PASSWORD_LOCAL_ONLY 51 // Accepting only local connections for an empty password
+#define ERR_NOT_ENOUGH_RIGHT 52 // Right is insufficient
+#define ERR_LISTENER_NOT_FOUND 53 // Listener can not be found
+#define ERR_LISTENER_ALREADY_EXISTS 54 // Listener already exists
+#define ERR_NOT_FARM_MEMBER 55 // Not a farm member
+#define ERR_CIPHER_NOT_SUPPORTED 56 // Encryption algorithm is not supported
+#define ERR_HUB_ALREADY_EXISTS 57 // HUB already exists
+#define ERR_TOO_MANY_HUBS 58 // Too many HUBs
+#define ERR_LINK_ALREADY_EXISTS 59 // Link already exists
+#define ERR_LINK_CANT_CREATE_ON_FARM 60 // The link can not be created on the server farm
+#define ERR_LINK_IS_OFFLINE 61 // Link is off-line
+#define ERR_TOO_MANY_ACCESS_LIST 62 // Too many access list
+#define ERR_TOO_MANY_USER 63 // Too many users
+#define ERR_TOO_MANY_GROUP 64 // Too many Groups
+#define ERR_GROUP_NOT_FOUND 65 // Group can not be found
+#define ERR_USER_ALREADY_EXISTS 66 // User already exists
+#define ERR_GROUP_ALREADY_EXISTS 67 // Group already exists
+#define ERR_USER_AUTHTYPE_NOT_PASSWORD 68 // Authentication method of the user is not a password authentication
+#define ERR_OLD_PASSWORD_WRONG 69 // The user does not exist or the old password is wrong
+#define ERR_LINK_CANT_DISCONNECT 73 // Cascade session cannot be disconnected
+#define ERR_ACCOUNT_NOT_PRESENT 74 // Not completed configure the connection to the VPN server
+#define ERR_ALREADY_ONLINE 75 // It is already online
+#define ERR_OFFLINE 76 // It is offline
+#define ERR_NOT_RSA_1024 77 // The certificate is not RSA 1024bit
+#define ERR_SNAT_CANT_DISCONNECT 78 // SecureNAT session cannot be disconnected
+#define ERR_SNAT_NEED_STANDALONE 79 // SecureNAT works only in stand-alone HUB
+#define ERR_SNAT_NOT_RUNNING 80 // SecureNAT function is not working
+#define ERR_SE_VPN_BLOCK 81 // Stopped by PacketiX VPN Block
+#define ERR_BRIDGE_CANT_DISCONNECT 82 // Bridge session can not be disconnected
+#define ERR_LOCAL_BRIDGE_STOPPING 83 // Bridge function is stopped
+#define ERR_LOCAL_BRIDGE_UNSUPPORTED 84 // Bridge feature is not supported
+#define ERR_CERT_NOT_TRUSTED 85 // Certificate of the destination server can not be trusted
+#define ERR_PRODUCT_CODE_INVALID 86 // Product code is different
+#define ERR_VERSION_INVALID 87 // Version is different
+#define ERR_CAPTURE_DEVICE_ADD_ERROR 88 // Adding capture device failure
+#define ERR_VPN_CODE_INVALID 89 // VPN code is different
+#define ERR_CAPTURE_NOT_FOUND 90 // Capture device can not be found
+#define ERR_LAYER3_CANT_DISCONNECT 91 // Layer-3 session cannot be disconnected
+#define ERR_LAYER3_SW_EXISTS 92 // L3 switch of the same already exists
+#define ERR_LAYER3_SW_NOT_FOUND 93 // Layer-3 switch can not be found
+#define ERR_INVALID_NAME 94 // Name is invalid
+#define ERR_LAYER3_IF_ADD_FAILED 95 // Failed to add interface
+#define ERR_LAYER3_IF_DEL_FAILED 96 // Failed to delete the interface
+#define ERR_LAYER3_IF_EXISTS 97 // Interface that you specified already exists
+#define ERR_LAYER3_TABLE_ADD_FAILED 98 // Failed to add routing table
+#define ERR_LAYER3_TABLE_DEL_FAILED 99 // Failed to delete the routing table
+#define ERR_LAYER3_TABLE_EXISTS 100 // Routing table entry that you specified already exists
+#define ERR_BAD_CLOCK 101 // Time is queer
+#define ERR_LAYER3_CANT_START_SWITCH 102 // The Virtual Layer 3 Switch can not be started
+#define ERR_CLIENT_LICENSE_NOT_ENOUGH 103 // Client connection licenses shortage
+#define ERR_BRIDGE_LICENSE_NOT_ENOUGH 104 // Bridge connection licenses shortage
+#define ERR_SERVER_CANT_ACCEPT 105 // Not Accept on the technical issues
+#define ERR_SERVER_CERT_EXPIRES 106 // Destination VPN server has expired
+#define ERR_MONITOR_MODE_DENIED 107 // Monitor port mode was rejected
+#define ERR_BRIDGE_MODE_DENIED 108 // Bridge-mode or Routing-mode was rejected
+#define ERR_IP_ADDRESS_DENIED 109 // Client IP address is denied
+#define ERR_TOO_MANT_ITEMS 110 // Too many items
+#define ERR_MEMORY_NOT_ENOUGH 111 // Out of memory
+#define ERR_OBJECT_EXISTS 112 // Object already exists
+#define ERR_FATAL 113 // A fatal error occurred
+#define ERR_SERVER_LICENSE_FAILED 114 // License violation has occurred on the server side
+#define ERR_SERVER_INTERNET_FAILED 115 // Server side is not connected to the Internet
+#define ERR_CLIENT_LICENSE_FAILED 116 // License violation occurs on the client side
+#define ERR_BAD_COMMAND_OR_PARAM 117 // Command or parameter is invalid
+#define ERR_INVALID_LICENSE_KEY 118 // License key is invalid
+#define ERR_NO_VPN_SERVER_LICENSE 119 // There is no valid license for the VPN Server
+#define ERR_NO_VPN_CLUSTER_LICENSE 120 // There is no cluster license
+#define ERR_NOT_ADMINPACK_SERVER 121 // Not trying to connect to a server with the Administrator Pack license
+#define ERR_NOT_ADMINPACK_SERVER_NET 122 // Not trying to connect to a server with the Administrator Pack license (for .NET)
+#define ERR_BETA_EXPIRES 123 // Destination Beta VPN Server has expired
+#define ERR_BRANDED_C_TO_S 124 // Branding string of connection limit is different (Authentication on the server side)
+#define ERR_BRANDED_C_FROM_S 125 // Branding string of connection limit is different (Authentication for client-side)
+#define ERR_AUTO_DISCONNECTED 126 // VPN session is disconnected for a certain period of time has elapsed
+#define ERR_CLIENT_ID_REQUIRED 127 // Client ID does not match
+#define ERR_TOO_MANY_USERS_CREATED 128 // Too many created users
+#define ERR_SUBSCRIPTION_IS_OLDER 129 // Subscription expiration date Is earlier than the build date of the VPN Server
+#define ERR_ILLEGAL_TRIAL_VERSION 130 // Many trial license is used continuously
+#define ERR_NAT_T_TWO_OR_MORE 131 // There are multiple servers in the back of a global IP address in the NAT-T connection
+#define ERR_DUPLICATE_DDNS_KEY 132 // DDNS host key duplicate
+#define ERR_DDNS_HOSTNAME_EXISTS 133 // Specified DDNS host name already exists
+#define ERR_DDNS_HOSTNAME_INVALID_CHAR 134 // Characters that can not be used for the host name is included
+#define ERR_DDNS_HOSTNAME_TOO_LONG 135 // Host name is too long
+#define ERR_DDNS_HOSTNAME_IS_EMPTY 136 // Host name is not specified
+#define ERR_DDNS_HOSTNAME_TOO_SHORT 137 // Host name is too short
+#define ERR_MSCHAP2_PASSWORD_NEED_RESET 138 // Necessary that password is changed
+#define ERR_DDNS_DISCONNECTED 139 // Communication to the dynamic DNS server is disconnected
+#define ERR_SPECIAL_LISTENER_ICMP_ERROR 140 // The ICMP socket can not be opened
+#define ERR_SPECIAL_LISTENER_DNS_ERROR 141 // Socket for DNS port can not be opened
+#define ERR_OPENVPN_IS_NOT_ENABLED 142 // OpenVPN server feature is not enabled
+#define ERR_NOT_SUPPORTED_AUTH_ON_OPENSOURCE 143 // It is the type of user authentication that are not supported in the open source version
+#define ERR_VPNGATE 144 // Operation on VPN Gate Server is not available
+#define ERR_VPNGATE_CLIENT 145 // Operation on VPN Gate Client is not available
+#define ERR_VPNGATE_INCLIENT_CANT_STOP 146 // Can not be stopped if operating within VPN Client mode
+#define ERR_NOT_SUPPORTED_FUNCTION_ON_OPENSOURCE 147 // It is a feature that is not supported in the open source version
+
+
+////////////////////////////
+// Generally used structure
+
+// Network Services
+typedef struct NETSVC
+{
+ bool Udp; // false=TCP, true=UDP
+ UINT Port; // Port number
+ char *Name; // Name
+} NETSVC;
+
+// Traffic data entry
+typedef struct TRAFFIC_ENTRY
+{
+ UINT64 BroadcastCount; // Number of broadcast packets
+ UINT64 BroadcastBytes; // Broadcast bytes
+ UINT64 UnicastCount; // Unicast count
+ UINT64 UnicastBytes; // Unicast bytes
+} TRAFFIC_ENTRY;
+
+// Traffic data
+typedef struct TRAFFIC
+{
+ TRAFFIC_ENTRY Send; // Transmitted data
+ TRAFFIC_ENTRY Recv; // Received data
+} TRAFFIC;
+
+// Non-SSL connection source
+typedef struct NON_SSL
+{
+ IP IpAddress; // IP address
+ UINT64 EntryExpires; // Expiration date of entry
+ UINT Count; // Number of connection count
+} NON_SSL;
+
+// Simple log storage
+typedef struct TINY_LOG
+{
+ char FileName[MAX_PATH]; // File name
+ IO *io; // File
+ LOCK *Lock; // Lock
+} TINY_LOG;
+
+// CEDAR structure
+typedef struct CEDAR
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ COUNTER *AcceptingSockets; // Number of sockets in Accept
+ UINT Type; // Type
+ LIST *ListenerList; // Listener list
+ LIST *HubList; // HUB list
+ LIST *ConnectionList; // Negotiating connection list
+ LIST *CaList; // List of CA
+ volatile bool Halt; // Halt flag
+ COUNTER *ConnectionIncrement; // Connection increment counter
+ X *ServerX; // Server certificate
+ K *ServerK; // Private key of the server certificate
+ char *CipherList; // List of encryption algorithms
+ UINT Version; // Version information
+ UINT Build; // Build Number
+ char *ServerStr; // Server string
+ char *MachineName; // Computer name
+ char *HttpUserAgent; // HTTP user agent
+ char *HttpAccept; // HTTP Accept
+ char *HttpAcceptLanguage; // HTTP Accept Language
+ char *HttpAcceptEncoding; // HTTP Accept Encoding
+ TRAFFIC *Traffic; // Traffic information
+ LOCK *TrafficLock; // Traffic information lock
+ LIST *UDPEntryList; // UDP entry list
+ COUNTER *CurrentSessions; // The current number of sessions
+ COUNTER *CurrentTcpConnections; // Number of current TCP connections
+ LIST *NetSvcList; // Network service list
+ char *VerString; // Version string
+ char *BuildInfo; // Build Information
+ struct CLIENT *Client; // Client
+ struct SERVER *Server; // Server
+ UINT64 CreatedTick; // Generation date and time
+ bool CheckExpires; // Check the expiration date
+ LIST *TrafficDiffList; // Traffic difference list
+ struct LOG *DebugLog; // Debug log
+ UCHAR UniqueId[16]; // Unique ID
+ LIST *LocalBridgeList; // Local bridge list
+ bool Bridge; // Bridge version
+ LIST *L3SwList; // Layer-3 switch list
+ COUNTER *AssignedClientLicense; // Number of assigned client licenses
+ COUNTER *AssignedBridgeLicense; // Number of assigned bridge licenses
+ UINT64 LicenseViolationTick; // License violation occurs
+ LIST *NonSslList; // Non-SSL connection list
+ struct WEBUI *WebUI; // Data for WebUI service
+ UINT Beta; // Beta number
+ LOCK *CedarSuperLock; // Cedar super lock!
+ bool DisableIPv6Listener; // Disable IPv6 listener
+ UINT ClientId; // Client ID
+ UINT64 BuiltDate; // Build Date
+ LIST *UdpPortList; // UDP port list in use
+ char CurrentDDnsFqdn[MAX_SIZE]; // FQDN of the current DDNS
+ char OpenVPNPublicPorts[MAX_SIZE]; // OpenVPN public UDP port list
+ LOCK *OpenVPNPublicPortsLock; // Lock of OpenVPN public UDP port list
+} CEDAR;
+
+// Type of CEDAR
+#define CEDAR_CLIENT 0 // Client
+#define CEDAR_STANDALONE_SERVER 1 // Stand-alone server
+#define CEDAR_FARM_CONTROLLER 2 // Server farm controller
+#define CEDAR_FARM_MEMBER 3 // Server farm member
+
+
+////////////////////////////
+// Read the header file
+
+// Type
+#include <Cedar/CedarType.h>
+// Account Manager
+#include <Cedar/Account.h>
+// Listener module
+#include <Cedar/Listener.h>
+// Log storage module
+#include <Cedar/Logging.h>
+// Connection management
+#include <Cedar/Connection.h>
+// Session Management
+#include <Cedar/Session.h>
+// RPC
+#include <Cedar/Remote.h>
+// HUB management
+#include <Cedar/Hub.h>
+// Security Accounts Manager
+#include <Cedar/Sam.h>
+// Radius authentication module
+#include <Cedar/Radius.h>
+// Protocol
+#include <Cedar/Protocol.h>
+// Inter-HUB link
+#include <Cedar/Link.h>
+// User-mode virtual host
+#include <Cedar/Virtual.h>
+// SecureNAT
+#include <Cedar/SecureNAT.h>
+// Digital watermark
+#include <Cedar/WaterMark.h>
+// Secure data
+#include <Cedar/SecureInfo.h>
+// Console service
+#include <Cedar/Console.h>
+// Vpncmd utility
+#include <Cedar/Command.h>
+// RPC over HTTP
+#include <Cedar/Wpc.h>
+// IPsec
+#include <Cedar/IPsec.h>
+#include <Cedar/IPsec_L2TP.h>
+#include <Cedar/IPsec_PPP.h>
+#include <Cedar/IPsec_IPC.h>
+#include <Cedar/IPsec_IkePacket.h>
+#include <Cedar/IPsec_IKE.h>
+#include <Cedar/IPsec_Win7.h>
+#include <Cedar/IPsec_EtherIP.h>
+// SSTP
+#include <Cedar/Interop_SSTP.h>
+// OpenVPN
+#include <Cedar/Interop_OpenVPN.h>
+// UDP Acceleration
+#include <Cedar/UdpAccel.h>
+// DDNS Client
+#include <Cedar/DDNS.h>
+// VPN Azure Client
+#include <Cedar/AzureClient.h>
+// VPN Azure Server
+#include <Cedar/AzureServer.h>
+// Native IP Stack
+#include <Cedar/NativeStack.h>
+
+#ifdef OS_WIN32
+// Neo device driver
+#include <Neo/Neo.h>
+// SeLow User-mode
+#include <Cedar/SeLowUser.h>
+#endif // OS_WIN32
+
+// Neo device driver manipulation library
+#include <Cedar/VLan.h>
+// Bridge
+#include <Cedar/Bridge.h>
+// Layer-3 switch
+#include <Cedar/Layer3.h>
+// Virtual LAN card for test
+#include <Cedar/NullLan.h>
+// Client
+#include <Cedar/Client.h>
+// Server
+#include <Cedar/Server.h>
+// License database
+#include <Cedar/Database.h>
+// EtherLogger
+#include <Cedar/EtherLog.h>
+// Management RPC
+#include <Cedar/Admin.h>
+// User-mode Router
+#include <Cedar/Nat.h>
+
+// Web UI
+#include <Cedar/WebUI.h>
+
+// VPN Gate Plugin DLL
+#include <VGate/VGateCommon.h>
+
+// VPN Gate Main Implementation
+#include <Cedar/VG.h>
+
+
+#ifdef OS_WIN32
+
+// Win32 user interface
+#include <Cedar/WinUi.h>
+// Win32 Client Connection Manager
+#include <Cedar/CM.h>
+// Win32 Server Manager
+#include <Cedar/SM.h>
+// Win32 User-mode Router Manager
+#include <Cedar/NM.h>
+// Win32 EtherLogger Manager
+#include <Cedar/EM.h>
+// Win32 Network Utility
+#include <Cedar/UT.h>
+// Win32 Setup Wizard
+#include <Cedar/SW.h>
+// Win32 COM calling module
+#include <Cedar/Win32Com.h>
+
+#endif
+
+
+
+
+////////////////////////////
+// Function prototype
+
+TRAFFIC *NewTraffic();
+void FreeTraffic(TRAFFIC *t);
+CEDAR *NewCedar(X *server_x, K *server_k);
+void CedarForceLink();
+void SetCedarVpnBridge(CEDAR *c);
+void SetCedarCert(CEDAR *c, X *server_x, K *server_k);
+void ReleaseCedar(CEDAR *c);
+void CleanupCedar(CEDAR *c);
+void StopCedar(CEDAR *c);
+void AddListener(CEDAR *c, LISTENER *r);
+void StopAllListener(CEDAR *c);
+void AddTraffic(TRAFFIC *dst, TRAFFIC *diff);
+void AddHub(CEDAR *c, HUB *h);
+void DelHub(CEDAR *c, HUB *h);
+void DelHubEx(CEDAR *c, HUB *h, bool no_lock);
+void StopAllHub(CEDAR *c);
+void StopAllConnection(CEDAR *c);
+void AddConnection(CEDAR *cedar, CONNECTION *c);
+UINT GetUnestablishedConnections(CEDAR *cedar);
+void DelConnection(CEDAR *cedar, CONNECTION *c);
+void SetCedarCipherList(CEDAR *cedar, char *name);
+void InitCedar();
+void FreeCedar();
+void AddCa(CEDAR *cedar, X *x);
+bool DeleteCa(CEDAR *cedar, UINT ptr);
+bool CheckSignatureByCa(CEDAR *cedar, X *x);
+bool CheckSignatureByCaLinkMode(SESSION *s, X *x);
+X *FindCaSignedX(LIST *o, X *x);
+void InitNetSvcList(CEDAR *cedar);
+void FreeNetSvcList(CEDAR *cedar);
+int CompareNetSvc(void *p1, void *p2);
+char *GetSvcName(CEDAR *cedar, bool udp, UINT port);
+void InitHiddenPassword(char *str, UINT size);
+bool IsHiddenPasswordChanged(char *str);
+UINT64 GetTrafficPacketSize(TRAFFIC *t);
+UINT64 GetTrafficPacketNum(TRAFFIC *t);
+void EnableDebugLog(CEDAR *c);
+void StartCedarLog();
+void StopCedarLog();
+void CedarLog(char *str);
+int CompareNoSslList(void *p1, void *p2);
+void InitNoSslList(CEDAR *c);
+void FreeNoSslList(CEDAR *c);
+bool AddNoSsl(CEDAR *c, IP *ip);
+void DecrementNoSsl(CEDAR *c, IP *ip, UINT num_dec);
+void DeleteOldNoSsl(CEDAR *c);
+NON_SSL *SearchNoSslList(CEDAR *c, IP *ip);
+bool IsInNoSsl(CEDAR *c, IP *ip);
+void FreeTinyLog(TINY_LOG *t);
+void WriteTinyLog(TINY_LOG *t, char *str);
+TINY_LOG *NewTinyLog();
+void GetWinVer(RPC_WINVER *v);
+bool IsSupportedWinVer(RPC_WINVER *v);
+bool IsLaterBuild(CEDAR *c, UINT64 t);
+SOCK *GetInProcListeningSock(CEDAR *c);
+SOCK *GetReverseListeningSock(CEDAR *c);
+void GetCedarVersion(char *tmp, UINT size);
+UINT64 GetCurrentBuildDate();
+
+
+
+#endif // CEDAR_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Cedar.vcproj b/src/Cedar/Cedar.vcproj
new file mode 100644
index 00000000..c84d7379
--- /dev/null
+++ b/src/Cedar/Cedar.vcproj
@@ -0,0 +1,1529 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Cedar"
+ ProjectGUID="{2928D768-DEC3-40D3-8E51-26E364497C9B}"
+ RootNamespace="Cedar"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);WinPcap"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="CedarPch.h"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);WinPcap"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="CedarPch.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);WinPcap"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="CedarPch.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);WinPcap"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="CedarPch.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Account.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Admin.c"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureClient.c"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureServer.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Bridge.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\BridgeUnix.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\BridgeWin32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Cedar.c"
+ >
+ </File>
+ <File
+ RelativePath=".\CedarPch.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Client.c"
+ >
+ </File>
+ <File
+ RelativePath=".\CM.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Command.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Connection.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Console.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Database.c"
+ >
+ </File>
+ <File
+ RelativePath=".\DDNS.c"
+ >
+ </File>
+ <File
+ RelativePath=".\EM.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\EtherLog.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Hub.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Interop_OpenVPN.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Interop_SSTP.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_EtherIP.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IKE.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IkePacket.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IPC.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_L2TP.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_PPP.c"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_Win7.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Layer3.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Link.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Listener.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Logging.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Nat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\NativeStack.c"
+ >
+ </File>
+ <File
+ RelativePath=".\NM.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\NullLan.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Protocol.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Radius.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Remote.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Sam.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SecureInfo.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SecureNAT.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLowUser.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Server.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Session.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SM.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\SW.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\UdpAccel.c"
+ >
+ </File>
+ <File
+ RelativePath=".\UT.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\VG.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Virtual.c"
+ >
+ </File>
+ <File
+ RelativePath=".\VLan.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\VLanUnix.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\VLanWin32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\WaterMark.c"
+ >
+ </File>
+ <File
+ RelativePath=".\WebUI.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32Com.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ExceptionHandling="2"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ExceptionHandling="2"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ExceptionHandling="2"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ExceptionHandling="2"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\WinJumpList.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\WinUi.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Wpc.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Account.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Admin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureClient.h"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureServer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Bridge.h"
+ >
+ </File>
+ <File
+ RelativePath=".\BridgeUnix.h"
+ >
+ </File>
+ <File
+ RelativePath=".\BridgeWin32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Cedar.h"
+ >
+ </File>
+ <File
+ RelativePath=".\CedarPch.h"
+ >
+ </File>
+ <File
+ RelativePath=".\CedarType.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Client.h"
+ >
+ </File>
+ <File
+ RelativePath=".\CM.h"
+ >
+ </File>
+ <File
+ RelativePath=".\CMInner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Command.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Connection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Console.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Database.h"
+ >
+ </File>
+ <File
+ RelativePath=".\DDNS.h"
+ >
+ </File>
+ <File
+ RelativePath=".\EM.h"
+ >
+ </File>
+ <File
+ RelativePath=".\EMInner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\EtherLog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Hub.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Interop_OpenVPN.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Interop_SSTP.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_EtherIP.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IKE.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IkePacket.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_IPC.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_L2TP.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_PPP.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_Win7.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec_Win7Inner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Layer3.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Link.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Listener.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Logging.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Nat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\NativeStack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\NM.h"
+ >
+ </File>
+ <File
+ RelativePath=".\NMInner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\NullLan.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Protocol.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Radius.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Remote.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Sam.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SecureInfo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SecureNAT.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLowUser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Server.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SM.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SMInner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SW.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SWInner.h"
+ >
+ </File>
+ <File
+ RelativePath=".\UdpAccel.h"
+ >
+ </File>
+ <File
+ RelativePath=".\UT.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VG.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Virtual.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VLan.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VLanUnix.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VLanWin32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WaterMark.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WebUI.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32Com.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinUi.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Wpc.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="winpcap"
+ >
+ <File
+ RelativePath=".\WinPcap\bittypes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\bucket_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\count_packets.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Devioctl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Gnuc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\ip6_misc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\memory_t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\normal_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Ntddndis.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Ntddpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Packet32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\pcap-bpf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\pcap-int.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\pcap-stdinc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\pcap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\pthread.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\remote-ext.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\sched.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\semaphore.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\tcp_session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\time_calls.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\tme.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPcap\Win32-Extensions.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Cedar/CedarPch.c b/src/Cedar/CedarPch.c
new file mode 100644
index 00000000..af2b83c7
--- /dev/null
+++ b/src/Cedar/CedarPch.c
@@ -0,0 +1,89 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CedarPch.c
+// Cedar Pre-compile Header Generating Code
+
+#include "CedarPch.h"
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/CedarPch.h b/src/Cedar/CedarPch.h
new file mode 100644
index 00000000..c71673b3
--- /dev/null
+++ b/src/Cedar/CedarPch.h
@@ -0,0 +1,100 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CedarPch.h
+// Header file for grecompile header generation for Cedar
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/CedarType.h b/src/Cedar/CedarType.h
new file mode 100644
index 00000000..0937db60
--- /dev/null
+++ b/src/Cedar/CedarType.h
@@ -0,0 +1,720 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// CedarType.h
+// List of types that Cedar using
+
+#ifndef CEDARTYPE_H
+#define CEDARTYPE_H
+
+
+// ==============================================================
+// Remote Procedure Call
+// ==============================================================
+
+typedef struct RPC RPC;
+
+
+// ==============================================================
+// Account
+// ==============================================================
+
+typedef struct POLICY_ITEM POLICY_ITEM;
+typedef struct POLICY POLICY;
+typedef struct USERGROUP USERGROUP;
+typedef struct USER USER;
+typedef struct AUTHPASSWORD AUTHPASSWORD;
+typedef struct AUTHUSERCERT AUTHUSERCERT;
+typedef struct AUTHROOTCERT AUTHROOTCERT;
+typedef struct AUTHRADIUS AUTHRADIUS;
+typedef struct AUTHNT AUTHNT;
+
+
+// ==============================================================
+// Listener
+// ==============================================================
+
+typedef struct DOS DOS;
+typedef struct LISTENER LISTENER;
+typedef struct TCP_ACCEPTED_PARAM TCP_ACCEPTED_PARAM;
+typedef struct UDP_ENTRY UDP_ENTRY;
+typedef struct DYNAMIC_LISTENER DYNAMIC_LISTENER;
+
+
+// ==============================================================
+// Logging
+// ==============================================================
+
+typedef struct PACKET_LOG PACKET_LOG;
+typedef struct HUB_LOG HUB_LOG;
+typedef struct RECORD RECORD;
+typedef struct LOG LOG;
+typedef struct ERASER ERASER;
+typedef struct SLOG SLOG;
+
+
+// ==============================================================
+// Connection
+// ==============================================================
+
+typedef struct KEEP KEEP;
+typedef struct SECURE_SIGN SECURE_SIGN;
+typedef struct RC4_KEY_PAIR RC4_KEY_PAIR;
+typedef struct CLIENT_OPTION CLIENT_OPTION;
+typedef struct CLIENT_AUTH CLIENT_AUTH;
+typedef struct TCPSOCK TCPSOCK;
+typedef struct TCP TCP;
+typedef struct UDP UDP;
+typedef struct BLOCK BLOCK;
+typedef struct CONNECTION CONNECTION;
+
+
+// ==============================================================
+// Session
+// ==============================================================
+
+typedef struct NODE_INFO NODE_INFO;
+typedef struct PACKET_ADAPTER PACKET_ADAPTER;
+typedef struct SESSION SESSION;
+typedef struct UI_PASSWORD_DLG UI_PASSWORD_DLG;
+typedef struct UI_MSG_DLG UI_MSG_DLG;
+typedef struct UI_NICINFO UI_NICINFO;
+typedef struct UI_CONNECTERROR_DLG UI_CONNECTERROR_DLG;
+typedef struct UI_CHECKCERT UI_CHECKCERT;
+
+
+// ==============================================================
+// Hub
+// ==============================================================
+
+typedef struct SE_LINK SE_LINK;
+typedef struct TEST_HISTORY TEST_HISTORY;
+typedef struct SE_TEST SE_TEST;
+typedef struct HUBDB HUBDB;
+typedef struct TRAFFIC_LIMITER TRAFFIC_LIMITER;
+typedef struct STORM STORM;
+typedef struct HUB_PA HUB_PA;
+typedef struct HUB_OPTION HUB_OPTION;
+typedef struct MAC_TABLE_ENTRY MAC_TABLE_ENTRY;
+typedef struct IP_TABLE_ENTRY IP_TABLE_ENTRY;
+typedef struct LOOP_LIST LOOP_LIST;
+typedef struct ACCESS ACCESS;
+typedef struct TICKET TICKET;
+typedef struct TRAFFIC_DIFF TRAFFIC_DIFF;
+typedef struct HUB HUB;
+typedef struct ADMIN_OPTION ADMIN_OPTION;
+typedef struct CRL CRL;
+typedef struct AC AC;
+typedef struct USERLIST USERLIST;
+
+
+// ==============================================================
+// Protocol
+// ==============================================================
+
+typedef struct CHECK_CERT_THREAD_PROC CHECK_CERT_THREAD_PROC;
+typedef struct SECURE_SIGN_THREAD_PROC SECURE_SIGN_THREAD_PROC;
+typedef struct RAND_CACHE RAND_CACHE;
+typedef struct BLACK BLACK;
+typedef struct SEND_SIGNATURE_PARAM SEND_SIGNATURE_PARAM;
+typedef struct UPDATE_CLIENT UPDATE_CLIENT;
+typedef struct UPDATE_CLIENT_SETTING UPDATE_CLIENT_SETTING;
+
+
+// ==============================================================
+// Link
+// ==============================================================
+
+typedef struct LINK LINK;
+
+
+// ==============================================================
+// Virtual
+// ==============================================================
+
+typedef struct ARP_ENTRY ARP_ENTRY;
+typedef struct ARP_WAIT ARP_WAIT;
+typedef struct IP_WAIT IP_WAIT;
+typedef struct IP_PART IP_PART;
+typedef struct IP_COMBINE IP_COMBINE;
+typedef struct NAT_ENTRY NAT_ENTRY;
+typedef struct TCP_OPTION TCP_OPTION;
+typedef struct VH VH;
+typedef struct VH_OPTION VH_OPTION;
+typedef struct DHCP_LEASE DHCP_LEASE;
+typedef struct NATIVE_NAT NATIVE_NAT;
+typedef struct NATIVE_NAT_ENTRY NATIVE_NAT_ENTRY;
+typedef struct DNS_PARSED_PACKET DNS_PARSED_PACKET;
+
+
+// ==============================================================
+// WPC
+// ==============================================================
+
+typedef struct INTERNET_SETTING INTERNET_SETTING;
+typedef struct URL_DATA URL_DATA;
+typedef struct WPC_ENTRY WPC_ENTRY;
+typedef struct WPC_PACKET WPC_PACKET;
+typedef struct WPC_CONNECT WPC_CONNECT;
+
+// ==============================================================
+// VLAN
+// ==============================================================
+
+typedef struct ROUTE_TRACKING ROUTE_TRACKING;
+typedef struct VLAN VLAN;
+typedef struct INSTANCE_LIST INSTANCE_LIST;
+typedef struct VLAN_PARAM VLAN_PARAM;
+
+#ifdef OS_UNIX
+typedef struct UNIX_VLAN_LIST UNIX_VLAN_LIST;
+#endif // OS_UNIX
+
+// ==============================================================
+// Null LAN
+// ==============================================================
+
+typedef struct NULL_LAN NULL_LAN;
+
+
+// ==============================================================
+// Bridge
+// ==============================================================
+
+typedef struct ETH ETH;
+typedef struct BRIDGE BRIDGE;
+typedef struct LOCALBRIDGE LOCALBRIDGE;
+
+
+// ==============================================================
+// Layer-3 Switch
+// ==============================================================
+
+typedef struct L3IF L3IF;
+typedef struct L3SW L3SW;
+typedef struct L3TABLE L3TABLE;
+typedef struct L3ARPENTRY L3ARPENTRY;
+typedef struct L3ARPWAIT L3ARPWAIT;
+typedef struct L3PACKET L3PACKET;
+
+
+// ==============================================================
+// Client
+// ==============================================================
+
+typedef struct ACCOUNT ACCOUNT;
+typedef struct CLIENT_CONFIG CLIENT_CONFIG;
+typedef struct RPC_CLIENT_VERSION RPC_CLIENT_VERSION;
+typedef struct RPC_CLIENT_PASSWORD RPC_CLIENT_PASSWORD;
+typedef struct RPC_CLIENT_PASSWORD_SETTING RPC_CLIENT_PASSWORD_SETTING;
+typedef struct RPC_CLIENT_ENUM_CA_ITEM RPC_CLIENT_ENUM_CA_ITEM;
+typedef struct RPC_CLIENT_ENUM_CA RPC_CLIENT_ENUM_CA;
+typedef struct RPC_CERT RPC_CERT;
+typedef struct RPC_CLIENT_DELETE_CA RPC_CLIENT_DELETE_CA;
+typedef struct RPC_GET_CA RPC_GET_CA;
+typedef struct RPC_GET_ISSUER RPC_GET_ISSUER;
+typedef struct RPC_CLIENT_ENUM_SECURE_ITEM RPC_CLIENT_ENUM_SECURE_ITEM;
+typedef struct RPC_CLIENT_ENUM_SECURE RPC_CLIENT_ENUM_SECURE;
+typedef struct RPC_USE_SECURE RPC_USE_SECURE;
+typedef struct RPC_ENUM_OBJECT_IN_SECURE RPC_ENUM_OBJECT_IN_SECURE;
+typedef struct RPC_CLIENT_CREATE_VLAN RPC_CLIENT_CREATE_VLAN;
+typedef struct RPC_CLIENT_GET_VLAN RPC_CLIENT_GET_VLAN;
+typedef struct RPC_CLIENT_SET_VLAN RPC_CLIENT_SET_VLAN;
+typedef struct RPC_CLIENT_ENUM_VLAN_ITEM RPC_CLIENT_ENUM_VLAN_ITEM;
+typedef struct RPC_CLIENT_ENUM_VLAN RPC_CLIENT_ENUM_VLAN;
+typedef struct RPC_CLIENT_CREATE_ACCOUNT RPC_CLIENT_CREATE_ACCOUNT;
+typedef struct RPC_CLIENT_ENUM_ACCOUNT_ITEM RPC_CLIENT_ENUM_ACCOUNT_ITEM;
+typedef struct RPC_CLIENT_ENUM_ACCOUNT RPC_CLIENT_ENUM_ACCOUNT;
+typedef struct RPC_CLIENT_DELETE_ACCOUNT RPC_CLIENT_DELETE_ACCOUNT;
+typedef struct RPC_RENAME_ACCOUNT RPC_RENAME_ACCOUNT;
+typedef struct RPC_CLIENT_GET_ACCOUNT RPC_CLIENT_GET_ACCOUNT;
+typedef struct RPC_CLIENT_CONNECT RPC_CLIENT_CONNECT;
+typedef struct RPC_CLIENT_GET_CONNECTION_STATUS RPC_CLIENT_GET_CONNECTION_STATUS;
+typedef struct CLIENT_RPC_CONNECTION CLIENT_RPC_CONNECTION;
+typedef struct CLIENT CLIENT;
+typedef struct RPC_CLIENT_NOTIFY RPC_CLIENT_NOTIFY;
+typedef struct REMOTE_CLIENT REMOTE_CLIENT;
+typedef struct NOTIFY_CLIENT NOTIFY_CLIENT;
+typedef struct UNIX_VLAN UNIX_VLAN;
+typedef struct CM_SETTING CM_SETTING;
+
+
+// ==============================================================
+// Server
+// ==============================================================
+
+typedef struct HUB_LIST HUB_LIST;
+typedef struct FARM_TASK FARM_TASK;
+typedef struct FARM_MEMBER FARM_MEMBER;
+typedef struct FARM_CONTROLLER FARM_CONTROLLER;
+typedef struct SERVER_LISTENER SERVER_LISTENER;
+typedef struct SERVER SERVER;
+typedef struct RPC_ENUM_SESSION RPC_ENUM_SESSION;
+typedef struct RPC_SESSION_STATUS RPC_SESSION_STATUS;
+typedef struct CAPS CAPS;
+typedef struct CAPSLIST CAPSLIST;
+typedef struct LOG_FILE LOG_FILE;
+typedef struct SYSLOG_SETTING SYSLOG_SETTING;
+typedef struct HUB_SNAPSHOT HUB_SNAPSHOT;
+typedef struct SERVER_SNAPSHOT SERVER_SNAPSHOT;
+typedef struct SERVER_HUB_CREATE_HISTORY SERVER_HUB_CREATE_HISTORY;
+typedef struct OPENVPN_SSTP_CONFIG OPENVPN_SSTP_CONFIG;
+
+// ==============================================================
+// Server Admin Tool
+// ==============================================================
+
+typedef struct ADMIN ADMIN;
+typedef struct RPC_TEST RPC_TEST;
+typedef struct RPC_SERVER_INFO RPC_SERVER_INFO;
+typedef struct RPC_SERVER_STATUS RPC_SERVER_STATUS;
+typedef struct RPC_LISTENER RPC_LISTENER;
+typedef struct RPC_LISTENER_LIST RPC_LISTENER_LIST;
+typedef struct RPC_STR RPC_STR;
+typedef struct RPC_SET_PASSWORD RPC_SET_PASSWORD;
+typedef struct RPC_FARM RPC_FARM;
+typedef struct RPC_FARM_HUB RPC_FARM_HUB;
+typedef struct RPC_FARM_INFO RPC_FARM_INFO;
+typedef struct RPC_ENUM_FARM_ITEM RPC_ENUM_FARM_ITEM;
+typedef struct RPC_ENUM_FARM RPC_ENUM_FARM;
+typedef struct RPC_FARM_CONNECTION_STATUS RPC_FARM_CONNECTION_STATUS;
+typedef struct RPC_KEY_PAIR RPC_KEY_PAIR;
+typedef struct RPC_HUB_OPTION RPC_HUB_OPTION;
+typedef struct RPC_RADIUS RPC_RADIUS;
+typedef struct RPC_HUB RPC_HUB;
+typedef struct RPC_CREATE_HUB RPC_CREATE_HUB;
+typedef struct RPC_ENUM_HUB_ITEM RPC_ENUM_HUB_ITEM;
+typedef struct RPC_ENUM_HUB RPC_ENUM_HUB;
+typedef struct RPC_DELETE_HUB RPC_DELETE_HUB;
+typedef struct RPC_ENUM_CONNECTION_ITEM RPC_ENUM_CONNECTION_ITEM;
+typedef struct RPC_ENUM_CONNECTION RPC_ENUM_CONNECTION;
+typedef struct RPC_DISCONNECT_CONNECTION RPC_DISCONNECT_CONNECTION;
+typedef struct RPC_CONNECTION_INFO RPC_CONNECTION_INFO;
+typedef struct RPC_SET_HUB_ONLINE RPC_SET_HUB_ONLINE;
+typedef struct RPC_HUB_STATUS RPC_HUB_STATUS;
+typedef struct RPC_HUB_LOG RPC_HUB_LOG;
+typedef struct RPC_HUB_ADD_CA RPC_HUB_ADD_CA;
+typedef struct RPC_HUB_ENUM_CA_ITEM RPC_HUB_ENUM_CA_ITEM;
+typedef struct RPC_HUB_ENUM_CA RPC_HUB_ENUM_CA;
+typedef struct RPC_HUB_GET_CA RPC_HUB_GET_CA;
+typedef struct RPC_HUB_DELETE_CA RPC_HUB_DELETE_CA;
+typedef struct RPC_CREATE_LINK RPC_CREATE_LINK;
+typedef struct RPC_ENUM_LINK_ITEM RPC_ENUM_LINK_ITEM;
+typedef struct RPC_ENUM_LINK RPC_ENUM_LINK;
+typedef struct RPC_LINK_STATUS RPC_LINK_STATUS;
+typedef struct RPC_LINK RPC_LINK;
+typedef struct RPC_ENUM_ACCESS_LIST RPC_ENUM_ACCESS_LIST;
+typedef struct RPC_ADD_ACCESS RPC_ADD_ACCESS;
+typedef struct RPC_DELETE_ACCESS RPC_DELETE_ACCESS;
+typedef struct RPC_SET_USER RPC_SET_USER;
+typedef struct RPC_ENUM_USER_ITEM RPC_ENUM_USER_ITEM;
+typedef struct RPC_ENUM_USER RPC_ENUM_USER;
+typedef struct RPC_SET_GROUP RPC_SET_GROUP;
+typedef struct RPC_ENUM_GROUP_ITEM RPC_ENUM_GROUP_ITEM;
+typedef struct RPC_ENUM_GROUP RPC_ENUM_GROUP;
+typedef struct RPC_DELETE_USER RPC_DELETE_USER;
+typedef struct RPC_ENUM_SESSION_ITEM RPC_ENUM_SESSION_ITEM;
+typedef struct RPC_DELETE_SESSION RPC_DELETE_SESSION;
+typedef struct RPC_ENUM_MAC_TABLE_ITEM RPC_ENUM_MAC_TABLE_ITEM;
+typedef struct RPC_ENUM_MAC_TABLE RPC_ENUM_MAC_TABLE;
+typedef struct RPC_ENUM_IP_TABLE_ITEM RPC_ENUM_IP_TABLE_ITEM;
+typedef struct RPC_ENUM_IP_TABLE RPC_ENUM_IP_TABLE;
+typedef struct RPC_DELETE_TABLE RPC_DELETE_TABLE;
+typedef struct RPC_KEEP RPC_KEEP;
+typedef struct RPC_ENUM_ETH_ITEM RPC_ENUM_ETH_ITEM;
+typedef struct RPC_ENUM_ETH RPC_ENUM_ETH;
+typedef struct RPC_LOCALBRIDGE RPC_LOCALBRIDGE;
+typedef struct RPC_ENUM_LOCALBRIDGE RPC_ENUM_LOCALBRIDGE;
+typedef struct RPC_BRIDGE_SUPPORT RPC_BRIDGE_SUPPORT;
+typedef struct RPC_CONFIG RPC_CONFIG;
+typedef struct RPC_ADMIN_OPTION RPC_ADMIN_OPTION;
+typedef struct RPC_L3SW RPC_L3SW;
+typedef struct RPC_L3IF RPC_L3IF;
+typedef struct RPC_L3TABLE RPC_L3TABLE;
+typedef struct RPC_ENUM_L3SW_ITEM RPC_ENUM_L3SW_ITEM;
+typedef struct RPC_ENUM_L3SW RPC_ENUM_L3SW;
+typedef struct RPC_ENUM_L3IF RPC_ENUM_L3IF;
+typedef struct RPC_ENUM_L3TABLE RPC_ENUM_L3TABLE;
+typedef struct RPC_CRL RPC_CRL;
+typedef struct RPC_ENUM_CRL_ITEM RPC_ENUM_CRL_ITEM;
+typedef struct RPC_ENUM_CRL RPC_ENUM_CRL;
+typedef struct RPC_INT RPC_INT;
+typedef struct RPC_AC_LIST RPC_AC_LIST;
+typedef struct RPC_ENUM_LOG_FILE_ITEM RPC_ENUM_LOG_FILE_ITEM;
+typedef struct RPC_ENUM_LOG_FILE RPC_ENUM_LOG_FILE;
+typedef struct RPC_READ_LOG_FILE RPC_READ_LOG_FILE;
+typedef struct DOWNLOAD_PROGRESS DOWNLOAD_PROGRESS;
+typedef struct RPC_RENAME_LINK RPC_RENAME_LINK;
+typedef struct RPC_ENUM_LICENSE_KEY RPC_ENUM_LICENSE_KEY;
+typedef struct RPC_ENUM_LICENSE_KEY_ITEM RPC_ENUM_LICENSE_KEY_ITEM;
+typedef struct RPC_LICENSE_STATUS RPC_LICENSE_STATUS;
+typedef struct RPC_ENUM_ETH_VLAN_ITEM RPC_ENUM_ETH_VLAN_ITEM;
+typedef struct RPC_ENUM_ETH_VLAN RPC_ENUM_ETH_VLAN;
+typedef struct RPC_MSG RPC_MSG;
+typedef struct RPC_WINVER RPC_WINVER;
+typedef struct RPC_ENUM_ETHERIP_ID RPC_ENUM_ETHERIP_ID;
+typedef struct RPC_SPECIAL_LISTENER RPC_SPECIAL_LISTENER;
+typedef struct RPC_AZURE_STATUS RPC_AZURE_STATUS;
+
+
+// ==============================================================
+// NAT
+// ==============================================================
+
+typedef struct NAT NAT;
+typedef struct NAT_ADMIN NAT_ADMIN;
+typedef struct RPC_DUMMY RPC_DUMMY;
+typedef struct RPC_NAT_STATUS RPC_NAT_STATUS;
+typedef struct RPC_NAT_INFO RPC_NAT_INFO;
+typedef struct RPC_ENUM_NAT_ITEM RPC_ENUM_NAT_ITEM;
+typedef struct RPC_ENUM_NAT RPC_ENUM_NAT;
+typedef struct RPC_ENUM_DHCP_ITEM RPC_ENUM_DHCP_ITEM;
+typedef struct RPC_ENUM_DHCP RPC_ENUM_DHCP;
+
+
+// ==============================================================
+// SecureNAT
+// ==============================================================
+
+typedef struct SNAT SNAT;
+
+
+// ==============================================================
+// WinUI
+// ==============================================================
+
+typedef struct LED LED;
+typedef struct WIZARD WIZARD;
+typedef struct WIZARD_PAGE WIZARD_PAGE;
+typedef struct WINUI_UPDATE WINUI_UPDATE;
+typedef struct WINUI_UPDATE_DLG_PARAM WINUI_UPDATE_DLG_PARAM;
+
+
+
+// ==============================================================
+// Console
+// ==============================================================
+
+typedef struct PARAM PARAM;
+typedef struct PARAM_VALUE PARAM_VALUE;
+typedef struct CONSOLE CONSOLE;
+typedef struct LOCAL_CONSOLE_PARAM LOCAL_CONSOLE_PARAM;
+typedef struct CMD CMD;
+typedef struct CMD_EVAL_MIN_MAX CMD_EVAL_MIN_MAX;
+
+
+// ==============================================================
+// Command
+// ==============================================================
+
+typedef struct PS PS;
+typedef struct PC PC;
+typedef struct CT CT;
+typedef struct CTC CTC;
+typedef struct CTR CTR;
+typedef struct TTC TTC;
+typedef struct TTS TTS;
+typedef struct TT_RESULT TT_RESULT;
+typedef struct TTS_SOCK TTS_SOCK;
+typedef struct TTC_SOCK TTC_SOCK;
+typedef struct PT PT;
+
+// ==============================================================
+// EtherLogger
+// ==============================================================
+
+typedef struct EL EL;
+typedef struct EL_DEVICE EL_DEVICE;
+typedef struct EL_LICENSE_STATUS EL_LICENSE_STATUS;
+typedef struct RPC_ADD_DEVICE RPC_ADD_DEVICE;
+typedef struct RPC_DELETE_DEVICE RPC_DELETE_DEVICE;
+typedef struct RPC_ENUM_DEVICE_ITEM RPC_ENUM_DEVICE_ITEM;
+typedef struct RPC_ENUM_DEVICE RPC_ENUM_DEVICE;
+typedef struct RPC_EL_LICENSE_STATUS RPC_EL_LICENSE_STATUS;
+
+
+// ==============================================================
+// Database
+// ==============================================================
+
+typedef struct LICENSE_PRODUCT LICENSE_PRODUCT;
+typedef struct LICENSE_SYSTEM LICENSE_SYSTEM;
+typedef struct LICENSE_DATA LICENSE_DATA;
+typedef struct LICENSE LICENSE;
+typedef struct LICENSE_STATUS LICENSE_STATUS;
+typedef struct SECURE_PACK_FOLDER SECURE_PACK_FOLDER;
+typedef struct WIDE_MACHINE_ID WIDE_MACHINE_ID;
+typedef struct TRIAL_INFO TRIAL_INFO;
+
+
+// ==============================================================
+// IPsec
+// ==============================================================
+
+typedef struct IPSEC_SERVER IPSEC_SERVER;
+typedef struct IPSEC_SERVICES IPSEC_SERVICES;
+typedef struct ETHERIP_ID ETHERIP_ID;
+
+
+// ==============================================================
+// L2TP
+// ==============================================================
+
+typedef struct L2TP_SERVER L2TP_SERVER;
+typedef struct L2TP_TUNNEL L2TP_TUNNEL;
+typedef struct L2TP_SESSION L2TP_SESSION;
+typedef struct L2TP_PACKET L2TP_PACKET;
+typedef struct L2TP_AVP L2TP_AVP;
+typedef struct L2TP_QUEUE L2TP_QUEUE;
+
+
+// ==============================================================
+// PPP
+// ==============================================================
+
+typedef struct PPP_SESSION PPP_SESSION;
+typedef struct PPP_OPTION PPP_OPTION;
+typedef struct PPP_LCP PPP_LCP;
+typedef struct PPP_PACKET PPP_PACKET;
+typedef struct PPP_IPOPTION PPP_IPOPTION;
+
+
+// ==============================================================
+// EtherIP
+// ==============================================================
+
+typedef struct ETHERIP_SERVER ETHERIP_SERVER;
+
+
+// ==============================================================
+// IKE
+// ==============================================================
+
+typedef struct IKE_SERVER IKE_SERVER;
+typedef struct IKE_SA IKE_SA;
+typedef struct IKE_SA_TRANSFORM_SETTING IKE_SA_TRANSFORM_SETTING;
+typedef struct IKE_CLIENT IKE_CLIENT;
+typedef struct IPSECSA IPSECSA;
+typedef struct IKE_CAPS IKE_CAPS;
+
+// ==============================================================
+// IPSec Packet
+// ==============================================================
+
+typedef struct IKE_COMMON_HEADER IKE_COMMON_HEADER;
+typedef struct IKE_SA_HEADER IKE_SA_HEADER;
+typedef struct IKE_PROPOSAL_HEADER IKE_PROPOSAL_HEADER;
+typedef struct IKE_TRANSFORM_HEADER IKE_TRANSFORM_HEADER;
+typedef struct IKE_TRANSFORM_VALUE IKE_TRANSFORM_VALUE;
+typedef struct IKE_ID_HEADER IKE_ID_HEADER;
+typedef struct IKE_CERT_HEADER IKE_CERT_HEADER;
+typedef struct IKE_CERT_REQUEST_HEADER IKE_CERT_REQUEST_HEADER;
+typedef struct IKE_NOTICE_HEADER IKE_NOTICE_HEADER;
+typedef struct IKE_DELETE_HEADER IKE_DELETE_HEADER;
+typedef struct IKE_NAT_OA_HEADER IKE_NAT_OA_HEADER;
+typedef struct IPSEC_SA_TRANSFORM_SETTING IPSEC_SA_TRANSFORM_SETTING;
+
+typedef struct IKE_PACKET_SA_PAYLOAD IKE_PACKET_SA_PAYLOAD;
+typedef struct IKE_PACKET_PROPOSAL_PAYLOAD IKE_PACKET_PROPOSAL_PAYLOAD;
+typedef struct IKE_PACKET_TRANSFORM_PAYLOAD IKE_PACKET_TRANSFORM_PAYLOAD;
+typedef struct IKE_PACKET_TRANSFORM_VALUE IKE_PACKET_TRANSFORM_VALUE;
+typedef struct IKE_PACKET_DATA_PAYLOAD IKE_PACKET_DATA_PAYLOAD;
+typedef struct IKE_PACKET_ID_PAYLOAD IKE_PACKET_ID_PAYLOAD;
+typedef struct IKE_PACKET_CERT_PAYLOAD IKE_PACKET_CERT_PAYLOAD;
+typedef struct IKE_PACKET_CERT_REQUEST_PAYLOAD IKE_PACKET_CERT_REQUEST_PAYLOAD;
+typedef struct IKE_PACKET_NOTICE_PAYLOAD IKE_PACKET_NOTICE_PAYLOAD;
+typedef struct IKE_PACKET_DELETE_PAYLOAD IKE_PACKET_DELETE_PAYLOAD;
+typedef struct IKE_PACKET_NAT_OA_PAYLOAD IKE_PACKET_NAT_OA_PAYLOAD;
+
+typedef struct IKE_PACKET_PAYLOAD IKE_PACKET_PAYLOAD;
+typedef struct IKE_PACKET IKE_PACKET;
+
+typedef struct IKE_P1_KEYSET IKE_P1_KEYSET;
+
+typedef struct IKE_CRYPTO IKE_CRYPTO;
+typedef struct IKE_HASH IKE_HASH;
+typedef struct IKE_DH IKE_DH;
+typedef struct IKE_ENGINE IKE_ENGINE;
+typedef struct IKE_CRYPTO_KEY IKE_CRYPTO_KEY;
+typedef struct IKE_CRYPTO_PARAM IKE_CRYPTO_PARAM;
+
+
+// ==============================================================
+// IPSec for Windows 7 / Vista / 2008 / 2008 R2
+// ==============================================================
+
+typedef struct IPSEC_WIN7 IPSEC_WIN7;
+
+
+// ==============================================================
+// In-Process VPN Client
+// ==============================================================
+
+typedef struct IPC IPC;
+typedef struct IPC_ARP IPC_ARP;
+typedef struct IPC_ASYNC IPC_ASYNC;
+typedef struct IPC_PARAM IPC_PARAM;
+typedef struct IPC_DHCP_RELESAE_QUEUE IPC_DHCP_RELESAE_QUEUE;
+typedef struct IPC_MSCHAP_V2_AUTHINFO IPC_MSCHAP_V2_AUTHINFO;
+
+
+// ==============================================================
+// UDP Acceleration
+// ==============================================================
+
+typedef struct UDP_ACCEL UDP_ACCEL;
+
+
+// ==============================================================
+// SSTP (Microsoft Secure Socket Tunneling Protocol) Stack
+// ==============================================================
+
+typedef struct SSTP_SERVER SSTP_SERVER;
+typedef struct SSTP_PACKET SSTP_PACKET;
+typedef struct SSTP_ATTRIBUTE SSTP_ATTRIBUTE;
+
+
+// ==============================================================
+// OpenVPN Protocol Stack
+// ==============================================================
+
+typedef struct OPENVPN_SERVER OPENVPN_SERVER;
+typedef struct OPENVPN_SERVER_UDP OPENVPN_SERVER_UDP;
+typedef struct OPENVPN_SESSION OPENVPN_SESSION;
+typedef struct OPENVPN_CHANNEL OPENVPN_CHANNEL;
+typedef struct OPENVPN_PACKET OPENVPN_PACKET;
+typedef struct OPENVPN_CONTROL_PACKET OPENVPN_CONTROL_PACKET;
+typedef struct OPENVPN_KEY_METHOD_2 OPENVPN_KEY_METHOD_2;
+
+
+// ==============================================================
+// Dynamic DNS Client
+// ==============================================================
+
+typedef struct DDNS_CLIENT DDNS_CLIENT;
+typedef struct DDNS_REGISTER_PARAM DDNS_REGISTER_PARAM;
+typedef struct DDNS_CLIENT_STATUS DDNS_CLIENT_STATUS;
+
+
+// ==============================================================
+// VPN Azure Client
+// ==============================================================
+typedef struct AZURE_CLIENT AZURE_CLIENT;
+typedef struct AZURE_PARAM AZURE_PARAM;
+
+
+// ==============================================================
+// VPN Gate Service
+// ==============================================================
+
+typedef struct VGS VGS;
+typedef struct VGS_CONFIG VGS_CONFIG;
+typedef struct VGC VGC;
+typedef struct VGHOST VGHOST;
+typedef struct VGHOSTLIST VGHOSTLIST;
+typedef struct VGHOSTDAT VGHOSTDAT;
+typedef struct VGCPOLLTASK VGCPOLLTASK;
+typedef struct VGS_LOG VGS_LOG;
+typedef struct VGC_UDPHOST VGC_UDPHOST;
+typedef struct MIRROR_SERVER MIRROR_SERVER;
+
+
+// ==============================================================
+// Native Stack
+// ==============================================================
+
+typedef struct NATIVE_STACK NATIVE_STACK;
+
+
+// ==============================================================
+// SeLow User-mode
+// ==============================================================
+
+typedef struct SU SU;
+typedef struct SU_ADAPTER SU_ADAPTER;
+typedef struct SU_ADAPTER_LIST SU_ADAPTER_LIST;
+
+
+
+#endif // CEDARTYPE_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c
new file mode 100644
index 00000000..16062e7f
--- /dev/null
+++ b/src/Cedar/Client.c
@@ -0,0 +1,11005 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Client.c
+// Client Manager
+
+#include "CedarPch.h"
+
+static CLIENT *client = NULL;
+static LISTENER *cn_listener = NULL;
+static LOCK *cn_listener_lock = NULL;
+static UINT64 cn_next_allow = 0;
+static LOCK *ci_active_sessions_lock = NULL;
+static UINT ci_num_active_sessions = 0;
+
+
+// In Windows 8 or later, change unreasonable setting of WCM to ensure normal VPN communication
+void CiDisableWcmNetworkMinimize(CLIENT *c)
+{
+#ifdef OS_WIN32
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->Config.NoChangeWcmNetworkSettingOnWindows8)
+ {
+ return;
+ }
+
+ MsDisableWcmNetworkMinimize();
+#endif // OS_WIN32
+}
+
+// Compare RPC_CLIENT_ENUM_ACCOUNT_ITEM items by last connected date (Reverse)
+int CiCompareClientAccountEnumItemByLastConnectDateTime(void *p1, void *p2)
+{
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p1;
+ a2 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+ if (a1->LastConnectDateTime > a2->LastConnectDateTime)
+ {
+ return -1;
+ }
+ else if (a1->LastConnectDateTime < a2->LastConnectDateTime)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+// If machine changed, reshuffle MAC address for all virtual NIC
+void CiChangeAllVLanMacAddressIfMachineChanged(CLIENT *c)
+{
+ UCHAR current_hash_new[SHA1_SIZE];
+ UCHAR current_hash[SHA1_SIZE];
+ UCHAR current_hash_old[SHA1_SIZE];
+ UCHAR saved_hash[SHA1_SIZE];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ if (MsIsAdmin() == false)
+ {
+ return;
+ }
+#endif
+
+ CiGetCurrentMachineHashNew(current_hash_new);
+ CiGetCurrentMachineHash(current_hash);
+ CiGetCurrentMachineHashOld(current_hash_old);
+
+ if (CiReadLastMachineHash(saved_hash) == false)
+ {
+ CiWriteLastMachineHash(current_hash_new);
+ return;
+ }
+
+ if (Cmp(saved_hash, current_hash_old, SHA1_SIZE) == 0)
+ {
+ CiWriteLastMachineHash(current_hash_new);
+ return;
+ }
+
+ if (Cmp(saved_hash, current_hash, SHA1_SIZE) == 0)
+ {
+ CiWriteLastMachineHash(current_hash_new);
+ return;
+ }
+
+ if (Cmp(saved_hash, current_hash_new, SHA1_SIZE) == 0)
+ {
+ return;
+ }
+
+ if (CiWriteLastMachineHash(current_hash_new) == false)
+ {
+ return;
+ }
+
+ CiChangeAllVLanMacAddress(c);
+}
+
+// Get current machine hash (Old)
+void CiGetCurrentMachineHashOld(void *data)
+{
+ char name[MAX_PATH];
+ char *product_id = NULL;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ // Priduct ID
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+
+ StrCpy(name, sizeof(name), product_id);
+
+ Free(product_id);
+
+#else // OS_WIN32
+ GetMachineName(name, sizeof(name));
+#endif // OS_WIN32
+
+ Trim(name);
+ StrUpper(name);
+
+ Hash(data, name, StrLen(name), true);
+}
+
+// Get current machine hash
+void CiGetCurrentMachineHash(void *data)
+{
+ char name[MAX_PATH];
+ char *product_id = NULL;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ GetMachineName(name, sizeof(name));
+
+ Trim(name);
+ StrUpper(name);
+
+ Hash(data, name, StrLen(name), true);
+}
+
+// Get current machine hash (without using domain name)
+void CiGetCurrentMachineHashNew(void *data)
+{
+ char name[MAX_PATH];
+ char *p;
+
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ GetMachineName(name, sizeof(name));
+
+ // Ignore after first period(.)
+ for(p=name; *p; p++)
+ if(*p == '.')
+ *p = 0;
+
+ Trim(name);
+ StrUpper(name);
+
+ Hash(data, name, StrLen(name), true);
+}
+
+
+// Write machine hash
+bool CiWriteLastMachineHash(void *data)
+{
+ // Validate arguments
+ if (data == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ if (MsRegWriteBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", data, SHA1_SIZE, true) == false)
+ {
+ return false;
+ }
+
+ return true;
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// Get previous machine hash
+bool CiReadLastMachineHash(void *data)
+{
+ BUF *b = NULL;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ b = MsRegReadBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", true);
+ if (b == NULL)
+ {
+ return false;
+ }
+ if (b->Size == SHA1_SIZE)
+ {
+ Copy(data, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return true;
+ }
+
+ FreeBuf(b);
+ return false;
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// If the MAC address of each virtual LAN card has been eliminated, set it to random numbers
+// (measures for Windows 8 -> 8.1 upgrade problem)
+void CiChangeAllVLanMacAddressIfCleared(CLIENT *c)
+{
+#ifdef OS_WIN32
+ RPC_CLIENT_ENUM_VLAN t;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (MsIsInfCatalogRequired() == false)
+ {
+ // Not required for other than Windows 8
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CtEnumVLan(c, &t))
+ {
+ UINT i;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
+ UCHAR mac[6];
+
+ if (StrToMac(mac, e->MacAddress))
+ {
+ if (mac[0] == 0x00 &&
+ mac[1] == 0x00 &&
+ mac[2] == 0x01 &&
+ mac[3] == 0x00 &&
+ mac[4] == 0x00 &&
+ mac[5] == 0x01)
+ {
+ char *name = e->DeviceName;
+ RPC_CLIENT_SET_VLAN s;
+ UCHAR mac[6];
+
+ GenMacAddress(mac);
+
+ Zero(&s, sizeof(s));
+ StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
+
+ MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
+
+ CtSetVLan(c, &s);
+ }
+ }
+ }
+
+ CiFreeClientEnumVLan(&t);
+ }
+#endif // OS_WIN32
+}
+
+// Set the MAC address of all virtual LAN cards to random number
+void CiChangeAllVLanMacAddress(CLIENT *c)
+{
+ RPC_CLIENT_ENUM_VLAN t;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CtEnumVLan(c, &t))
+ {
+ UINT i;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
+ UCHAR mac[6];
+
+ if (StrToMac(mac, e->MacAddress) && mac[1] == 0xAC)
+ {
+ char *name = e->DeviceName;
+ RPC_CLIENT_SET_VLAN s;
+ UCHAR mac[6];
+
+ GenMacAddress(mac);
+
+ Zero(&s, sizeof(s));
+ StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
+
+ MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
+
+ CtSetVLan(c, &s);
+ }
+ }
+
+ CiFreeClientEnumVLan(&t);
+ }
+}
+
+// Wait for preparation of notification service to complete
+void CnWaitForCnServiceReady()
+{
+ UINT64 start_time = Tick64();
+
+ while ((start_time + (UINT64)CLIENT_WAIT_CN_READY_TIMEOUT) >= Tick64())
+ {
+ if (CnIsCnServiceReady())
+ {
+ break;
+ }
+
+ SleepThread(100);
+ }
+}
+
+// Check whether preparation of notification service completed
+bool CnIsCnServiceReady()
+{
+ SOCK *s;
+ // Confirm running the notification service
+ if (CnCheckAlreadyExists(false) == false)
+ {
+ // Not running
+ return false;
+ }
+
+ // Try to connect to the TCP port
+ s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, 500);
+ if (s == NULL)
+ {
+ // The TCP port is not opened
+ return false;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ // Running
+ return true;
+}
+
+// Check whether the notification service is already running
+bool CnCheckAlreadyExists(bool lock)
+{
+ bool ret = false;
+
+#ifdef OS_WIN32
+ ret = Win32CnCheckAlreadyExists(lock);
+#endif
+
+ return ret;
+}
+
+typedef struct CNC_STATUS_PRINTER_WINDOW_PARAM
+{
+ THREAD *Thread;
+ SESSION *Session;
+ SOCK *Sock;
+} CNC_STATUS_PRINTER_WINDOW_PARAM;
+
+typedef struct CNC_CONNECT_ERROR_DLG_THREAD_PARAM
+{
+ SESSION *Session;
+ SOCK *Sock;
+ bool HaltThread;
+ EVENT *Event;
+} CNC_CONNECT_ERROR_DLG_THREAD_PARAM;
+
+
+// Get the file name of vpnclient.exe in Win32
+char *CiGetVpnClientExeFileName()
+{
+ if (Is64() == false)
+ {
+ return CLIENT_WIN32_EXE_FILENAME;
+ }
+ else
+ {
+ if (IsX64())
+ {
+ return CLIENT_WIN32_EXE_FILENAME_X64;
+ }
+ else
+ {
+ return CLIENT_WIN32_EXE_FILENAME_IA64;
+ }
+ }
+}
+
+// Thread to stop forcibly the Certificate check dialog client
+void CncCheckCertHaltThread(THREAD *thread, void *param)
+{
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ if (dp->Session->Halt || dp->HaltThread)
+ {
+ break;
+ }
+
+ Wait(dp->Event, 100);
+ }
+
+ Disconnect(dp->Sock);
+}
+
+// Show the certification check dialog
+void CncCheckCert(SESSION *session, UI_CHECKCERT *dlg)
+{
+ SOCK *s;
+ PACK *p;
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
+ THREAD *t;
+ // Validate arguments
+ if (dlg == NULL || session == NULL)
+ {
+ return;
+ }
+
+ s = CncConnect();
+ if (s == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "check_cert");
+ PackAddUniStr(p, "AccountName", dlg->AccountName);
+ PackAddStr(p, "ServerName", dlg->ServerName);
+ PackAddX(p, "x", dlg->x);
+ PackAddX(p, "parent_x", dlg->parent_x);
+ PackAddX(p, "old_x", dlg->old_x);
+ PackAddBool(p, "DiffWarning", dlg->DiffWarning);
+ PackAddBool(p, "Ok", dlg->Ok);
+ PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
+ dp->Sock = s;
+ dp->Event = NewEvent();
+ dp->Session = session;
+
+ t = NewThread(CncCheckCertHaltThread, dp);
+
+ p = RecvPack(s);
+ if (p != NULL)
+ {
+ dlg->Ok = PackGetBool(p, "Ok");
+ dlg->DiffWarning = PackGetBool(p, "DiffWarning");
+ dlg->SaveServerCert = PackGetBool(p, "SaveServerCert");
+
+ FreePack(p);
+ }
+
+ dp->HaltThread = true;
+ Set(dp->Event);
+
+ WaitThread(t, INFINITE);
+
+ ReleaseEvent(dp->Event);
+ Free(dp);
+ ReleaseThread(t);
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// Smart card signature dialog
+bool CncSecureSignDlg(SECURE_SIGN *sign)
+{
+ SOCK *s;
+ PACK *p;
+ bool ret = false;
+ // Validate arguments
+ if (sign == NULL)
+ {
+ return false;
+ }
+
+ s = CncConnect();
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "secure_sign");
+ OutRpcSecureSign(p, sign);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ p = RecvPack(s);
+ if (p != NULL)
+ {
+ ret = PackGetBool(p, "ret");
+
+ if (ret)
+ {
+ FreeRpcSecureSign(sign);
+
+ Zero(sign, sizeof(SECURE_SIGN));
+ InRpcSecureSign(sign, p);
+ }
+
+ FreePack(p);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return ret;
+}
+
+// Show the NIC information dialog
+SOCK *CncNicInfo(UI_NICINFO *info)
+{
+ SOCK *s;
+ PACK *p;
+ bool ret = false;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return NULL;
+ }
+
+ s = CncConnectEx(200);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "nicinfo");
+ PackAddStr(p, "NicName", info->NicName);
+ PackAddUniStr(p, "AccountName", info->AccountName);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ return s;
+}
+
+// Close the NIC information dialog
+void CncNicInfoFree(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// Show the message dialog
+SOCK *CncMsgDlg(UI_MSG_DLG *dlg)
+{
+ SOCK *s;
+ PACK *p;
+ bool ret = false;
+ char *utf;
+ // Validate arguments
+ if (dlg == NULL)
+ {
+ return NULL;
+ }
+
+ s = CncConnectEx(200);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "msg_dialog");
+ PackAddStr(p, "ServerName", dlg->ServerName);
+ PackAddStr(p, "HubName", dlg->HubName);
+ utf = CopyUniToUtf(dlg->Msg);
+ PackAddData(p, "Msg", utf, StrLen(utf));
+ Free(utf);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ return s;
+}
+
+// Close the message dialog
+void CndMsgDlgFree(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// The thread to stop the password input dialog client forcibly
+void CncPasswordDlgHaltThread(THREAD *thread, void *param)
+{
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ if (dp->Session->Halt || dp->HaltThread)
+ {
+ break;
+ }
+
+ Wait(dp->Event, 100);
+ }
+
+ Disconnect(dp->Sock);
+}
+
+// Show the password input dialog
+bool CncPasswordDlg(SESSION *session, UI_PASSWORD_DLG *dlg)
+{
+ SOCK *s;
+ PACK *p;
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
+ THREAD *t;
+ bool ret = false;
+ // Validate arguments
+ if (dlg == NULL || session == NULL)
+ {
+ return false;
+ }
+
+ s = CncConnect();
+ if (s == NULL)
+ {
+ Wait(session->HaltEvent, session->RetryInterval);
+ return true;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "password_dialog");
+ PackAddInt(p, "Type", dlg->Type);
+ PackAddStr(p, "Username", dlg->Username);
+ PackAddStr(p, "Password", dlg->Password);
+ PackAddStr(p, "ServerName", dlg->ServerName);
+ PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
+ PackAddBool(p, "ProxyServer", dlg->ProxyServer);
+ PackAddBool(p, "AdminMode", dlg->AdminMode);
+ PackAddBool(p, "ShowNoSavePassword", dlg->ShowNoSavePassword);
+ PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
+ dp->Session = session;
+ dp->Sock = s;
+ dp->Event = NewEvent();
+
+ t = NewThread(CncConnectErrorDlgHaltThread, dp);
+
+ p = RecvPack(s);
+ if (p != NULL)
+ {
+ ret = PackGetBool(p, "ok");
+ dlg->NoSavePassword = PackGetBool(p, "NoSavePassword");
+ dlg->ProxyServer = PackGetBool(p, "ProxyServer");
+ dlg->Type = PackGetInt(p, "Type");
+ PackGetStr(p, "Username", dlg->Username, sizeof(dlg->Username));
+ PackGetStr(p, "Password", dlg->Password, sizeof(dlg->Password));
+
+ FreePack(p);
+ }
+
+ dp->HaltThread = true;
+ Set(dp->Event);
+
+ WaitThread(t, INFINITE);
+
+ ReleaseEvent(dp->Event);
+ Free(dp);
+ ReleaseThread(t);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return ret;
+}
+
+// Thread to stop the connection error dialog client forcibly
+void CncConnectErrorDlgHaltThread(THREAD *thread, void *param)
+{
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ if (dp->Session->Halt || dp->HaltThread)
+ {
+ break;
+ }
+
+ Wait(dp->Event, 100);
+ }
+
+ Disconnect(dp->Sock);
+}
+
+// Show the connection error dialog
+bool CncConnectErrorDlg(SESSION *session, UI_CONNECTERROR_DLG *dlg)
+{
+ SOCK *s;
+ PACK *p;
+ CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
+ THREAD *t;
+ bool ret = false;
+ // Validate arguments
+ if (dlg == NULL || session == NULL)
+ {
+ return false;
+ }
+
+ s = CncConnect();
+ if (s == NULL)
+ {
+ Wait(session->HaltEvent, session->RetryInterval);
+ return true;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "connecterror_dialog");
+ PackAddUniStr(p, "AccountName", dlg->AccountName);
+ PackAddStr(p, "ServerName", dlg->ServerName);
+ PackAddInt(p, "Err", dlg->Err);
+ PackAddInt(p, "CurrentRetryCount", dlg->CurrentRetryCount);
+ PackAddInt(p, "RetryLimit", dlg->RetryLimit);
+ PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
+ PackAddBool(p, "HideWindow", dlg->HideWindow);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
+ dp->Session = session;
+ dp->Sock = s;
+ dp->Event = NewEvent();
+
+ t = NewThread(CncConnectErrorDlgHaltThread, dp);
+
+ p = RecvPack(s);
+ if (p != NULL)
+ {
+ ret = PackGetBool(p, "ok");
+ dlg->HideWindow = PackGetBool(p, "HideWindow");
+
+ FreePack(p);
+ }
+
+ dp->HaltThread = true;
+ Set(dp->Event);
+
+ WaitThread(t, INFINITE);
+
+ ReleaseEvent(dp->Event);
+ Free(dp);
+ ReleaseThread(t);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return ret;
+}
+
+// Thread for the status indicator client
+void CncStatusPrinterWindowThreadProc(THREAD *thread, void *param)
+{
+ CNC_STATUS_PRINTER_WINDOW_PARAM *pp;
+ SOCK *sock;
+ PACK *p;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ pp = (CNC_STATUS_PRINTER_WINDOW_PARAM *)param;
+ sock = pp->Sock;
+ pp->Thread = thread;
+ AddRef(pp->Thread->ref);
+
+ NoticeThreadInit(thread);
+
+ p = RecvPack(sock);
+ if (p != NULL)
+ {
+ // Stop the session
+ StopSessionEx(pp->Session, true);
+
+ FreePack(p);
+ }
+}
+
+// Create a status indicator client
+SOCK *CncStatusPrinterWindowStart(SESSION *s)
+{
+ SOCK *sock;
+ PACK *p;
+ THREAD *t;
+ CNC_STATUS_PRINTER_WINDOW_PARAM *param;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ sock = CncConnect();
+
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "status_printer");
+ PackAddUniStr(p, "account_name", s->Account->ClientOption->AccountName);
+
+ if (SendPack(sock, p) == false)
+ {
+ FreePack(p);
+ ReleaseSock(sock);
+
+ return NULL;
+ }
+
+ FreePack(p);
+
+ param = ZeroMalloc(sizeof(CNC_STATUS_PRINTER_WINDOW_PARAM));
+ param->Sock = sock;
+ param->Session = s;
+
+ sock->Param = param;
+
+ t = NewThread(CncStatusPrinterWindowThreadProc, param);
+ WaitThreadInit(t);
+
+ ReleaseThread(t);
+
+ return sock;
+}
+
+// Send a string to the status indicator
+void CncStatusPrinterWindowPrint(SOCK *s, wchar_t *str)
+{
+ CNC_STATUS_PRINTER_WINDOW_PARAM *param;
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return;
+ }
+
+ param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;
+
+ p = NewPack();
+ PackAddUniStr(p, "string", str);
+ SendPack(s, p);
+ FreePack(p);
+}
+
+// Stop the status indicator client
+void CncStatusPrinterWindowStop(SOCK *s)
+{
+ CNC_STATUS_PRINTER_WINDOW_PARAM *param;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;
+
+ // Disconnect the client socket
+ Disconnect(s);
+
+ // Terminate the thread
+ WaitThread(param->Thread, INFINITE);
+ ReleaseThread(param->Thread);
+
+ Free(param);
+ ReleaseSock(s);
+}
+
+// Start the driver installer for Windows Vista
+bool CncExecDriverInstaller(char *arg)
+{
+ SOCK *s = CncConnect();
+ PACK *p;
+ bool ret;
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "exec_driver_installer");
+ PackAddStr(p, "arg", arg);
+
+ SendPack(s, p);
+ FreePack(p);
+
+ p = RecvPack(s);
+ if (p == NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ return false;
+ }
+
+ ret = PackGetBool(p, "ret");
+
+ FreePack(p);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return ret;
+}
+
+// Let the current running client notification services releasing the socket
+void CncReleaseSocket()
+{
+ SOCK *s = CncConnect();
+ PACK *p;
+ if (s == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "release_socket");
+
+#ifdef OS_WIN32
+ PackAddInt(p, "pid", MsGetProcessId());
+#endif // OS_WIN32
+
+ SendPack(s, p);
+ FreePack(p);
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// Get the Session ID of the client notification service
+UINT CncGetSessionId()
+{
+ SOCK *s = CncConnect();
+ PACK *p;
+ UINT ret;
+ if (s == NULL)
+ {
+ return INFINITE;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "function", "get_session_id");
+
+ SendPack(s, p);
+ FreePack(p);
+
+ p = RecvPack(s);
+ if (p == NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ return INFINITE;
+ }
+
+ ret = PackGetInt(p, "session_id");
+
+ FreePack(p);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return ret;
+}
+
+// Terminate the process of the client notification service
+void CncExit()
+{
+ SOCK *s = CncConnectEx(256);
+ PACK *p;
+ if (s != NULL)
+ {
+ p = NewPack();
+ PackAddStr(p, "function", "exit");
+
+ SendPack(s, p);
+
+ FreePack(p);
+
+ FreePack(RecvPack(s));
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+#ifdef OS_WIN32
+ MsKillOtherInstanceEx("vpnclient");
+#endif // OS_WIN32
+}
+
+// Connect to the client notification service
+SOCK *CncConnect()
+{
+ return CncConnectEx(0);
+}
+SOCK *CncConnectEx(UINT timeout)
+{
+ SOCK *s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, timeout);
+
+ return s;
+}
+
+#ifdef OS_WIN32
+
+// Thread for the certificate check dialog
+void Win32CnCheckCertThreadProc(THREAD *thread, void *param)
+{
+ UI_CHECKCERT *dlg;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ dlg = (UI_CHECKCERT *)param;
+
+ CheckCertDlg(dlg);
+ {
+ PACK *p = NewPack();
+
+ PackAddBool(p, "Ok", dlg->Ok);
+ PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
+
+ SendPack(dlg->Sock, p);
+ FreePack(p);
+
+ FreePack(RecvPack(dlg->Sock));
+ }
+
+ Disconnect(dlg->Sock);
+}
+
+// Certificate check dialog
+void Win32CnCheckCert(SOCK *s, PACK *p)
+{
+ UI_CHECKCERT dlg;
+ THREAD *t;
+ Zero(&dlg, sizeof(dlg));
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
+ PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
+ dlg.x = PackGetX(p, "x");
+ dlg.parent_x = PackGetX(p, "parent_x");
+ dlg.old_x = PackGetX(p, "old_x");
+ dlg.DiffWarning = PackGetBool(p, "DiffWarning");
+ dlg.Ok = PackGetBool(p, "Ok");
+ dlg.SaveServerCert = PackGetBool(p, "SaveServerCert");
+ dlg.Sock = s;
+
+ t = NewThread(Win32CnCheckCertThreadProc, &dlg);
+
+ FreePack(RecvPack(s));
+
+ dlg.Halt = true;
+
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+
+ FreeX(dlg.parent_x);
+ FreeX(dlg.old_x);
+ FreeX(dlg.x);
+}
+
+// Message display dialog thread procedure
+void Win32CnMsgDlgThreadProc(THREAD *thread, void *param)
+{
+ UI_MSG_DLG *dlg = (UI_MSG_DLG *)param;
+ wchar_t tmp[MAX_SIZE];
+ char url[MAX_SIZE];
+ // Validate arguments
+ if (thread == NULL || dlg == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_MSG_TITLE"),
+ dlg->ServerName, dlg->HubName);
+
+ if (IsURLMsg(dlg->Msg, url, sizeof(url)) == false)
+ {
+ OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
+ }
+ else
+ {
+ if (MsExecute(url, NULL) == false)
+ {
+ OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
+ }
+ }
+
+ Disconnect(dlg->Sock);
+}
+
+// NIC information dialog thread procedure
+void Win32CnNicInfoThreadProc(THREAD *thread, void *param)
+{
+ UI_NICINFO *info = (UI_NICINFO *)param;
+ // Validate arguments
+ if (thread == NULL || info == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt())
+ {
+ // Do not show a dialog on Windows 9x system
+ NicInfo(info);
+ }
+
+ Disconnect(info->Sock);
+}
+
+// NIC information dialog
+void Win32CnNicInfo(SOCK *s, PACK *p)
+{
+ UI_NICINFO info;
+ THREAD *t;
+ Zero(&info, sizeof(info));
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetStr(p, "NicName", info.NicName, sizeof(info.NicName));
+ PackGetUniStr(p, "AccountName", info.AccountName, sizeof(info.AccountName));
+
+ info.Sock = s;
+
+ t = NewThread(Win32CnNicInfoThreadProc, &info);
+
+ FreePack(RecvPack(s));
+
+ info.Halt = true;
+
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+}
+
+// Message display dialog
+void Win32CnMsgDlg(SOCK *s, PACK *p)
+{
+ UI_MSG_DLG dlg;
+ THREAD *t;
+ UINT utf_size;
+ char *utf;
+ wchar_t *msg;
+ Zero(&dlg, sizeof(dlg));
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
+ PackGetStr(p, "HubName", dlg.HubName, sizeof(dlg.HubName));
+
+ utf_size = PackGetDataSize(p, "Msg");
+ utf = ZeroMalloc(utf_size + 8);
+
+ PackGetData(p, "Msg", utf);
+
+ msg = CopyUtfToUni(utf);
+ Free(utf);
+
+ dlg.Sock = s;
+ dlg.Msg = msg;
+
+ t = NewThread(Win32CnMsgDlgThreadProc, &dlg);
+
+ FreePack(RecvPack(s));
+
+ dlg.Halt = true;
+
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+
+ Free(msg);
+}
+
+// Thread for Password input dialog
+void Win32CnPasswordDlgThreadProc(THREAD *thread, void *param)
+{
+ UI_PASSWORD_DLG *dlg;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ dlg = (UI_PASSWORD_DLG *)param;
+
+ if (PasswordDlg(NULL, dlg))
+ {
+ PACK *p = NewPack();
+
+ PackAddBool(p, "ok", true);
+ PackAddStr(p, "Username", dlg->Username);
+ PackAddStr(p, "Password", dlg->Password);
+ PackAddInt(p, "Type", dlg->Type);
+ PackAddBool(p, "ProxyServer", dlg->ProxyServer);
+ PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
+
+ SendPack(dlg->Sock, p);
+ FreePack(p);
+
+ FreePack(RecvPack(dlg->Sock));
+ }
+
+ Disconnect(dlg->Sock);
+}
+
+// Password input dialog
+void Win32CnPasswordDlg(SOCK *s, PACK *p)
+{
+ UI_PASSWORD_DLG dlg;
+ THREAD *t = NULL;
+ Zero(&dlg, sizeof(dlg));
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ dlg.Type = PackGetInt(p, "Type");
+ PackGetStr(p, "Username", dlg.Username, sizeof(dlg.Username));
+ PackGetStr(p, "Password", dlg.Password, sizeof(dlg.Password));
+ PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
+ dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
+ dlg.ProxyServer = PackGetBool(p, "ProxyServer");
+ dlg.AdminMode = PackGetBool(p, "AdminMode");
+ dlg.ShowNoSavePassword = PackGetBool(p, "ShowNoSavePassword");
+ dlg.NoSavePassword = PackGetBool(p, "NoSavePassword");
+ dlg.CancelEvent = NewEvent();
+ dlg.Sock = s;
+
+ t = NewThread(Win32CnPasswordDlgThreadProc, &dlg);
+
+ FreePack(RecvPack(s));
+
+ Set(dlg.CancelEvent);
+
+ WaitThread(t, INFINITE);
+ ReleaseEvent(dlg.CancelEvent);
+ ReleaseThread(t);
+}
+
+// Thread for the connection error dialog
+void Win32CnConnectErrorDlgThreadProc(THREAD *thread, void *param)
+{
+ UI_CONNECTERROR_DLG *dlg;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ dlg = (UI_CONNECTERROR_DLG *)param;
+
+ if (ConnectErrorDlg(dlg))
+ {
+ PACK *p = NewPack();
+
+ PackAddBool(p, "ok", true);
+ PackAddBool(p, "HideWindow", dlg->HideWindow);
+
+ SendPack(dlg->Sock, p);
+ FreePack(p);
+
+ FreePack(RecvPack(dlg->Sock));
+ }
+
+ Disconnect(dlg->Sock);
+}
+
+// Connection Error dialog (Win32)
+void Win32CnConnectErrorDlg(SOCK *s, PACK *p)
+{
+ UI_CONNECTERROR_DLG dlg;
+ THREAD *t;
+ Zero(&dlg, sizeof(dlg));
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
+ PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
+ dlg.Err = PackGetInt(p, "Err");
+ dlg.CurrentRetryCount = PackGetInt(p, "CurrentRetryCount");
+ dlg.RetryLimit = PackGetInt(p, "RetryLimit");
+ dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
+ dlg.HideWindow = PackGetBool(p, "HideWindow");
+ dlg.CancelEvent = NewEvent();
+ dlg.Sock = s;
+
+ t = NewThread(Win32CnConnectErrorDlgThreadProc, &dlg);
+
+ FreePack(RecvPack(s));
+
+ Set(dlg.CancelEvent);
+
+ WaitThread(t, INFINITE);
+ ReleaseEvent(dlg.CancelEvent);
+ ReleaseThread(t);
+}
+
+// Status indicator (Win32)
+void Win32CnStatusPrinter(SOCK *s, PACK *p)
+{
+ STATUS_WINDOW *w;
+ wchar_t account_name[MAX_ACCOUNT_NAME_LEN + 1];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetUniStr(p, "account_name", account_name, sizeof(account_name));
+
+ w = StatusPrinterWindowStart(s, account_name);
+
+ while (true)
+ {
+ PACK *p = RecvPack(s);
+
+ if (p == NULL)
+ {
+ // Exit the dialog because it is disconnected
+ break;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // Rewrite the string
+ PackGetUniStr(p, "string", tmp, sizeof(tmp));
+
+ StatusPrinterWindowPrint(w, tmp);
+
+ FreePack(p);
+ }
+ }
+
+ StatusPrinterWindowStop(w);
+}
+
+// Start the driver installer (for Windows Vista)
+void Win32CnExecDriverInstaller(SOCK *s, PACK *p)
+{
+ char arg[MAX_SIZE];
+ bool ret;
+ void *helper = NULL;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (PackGetStr(p, "arg", arg, sizeof(arg)) == false)
+ {
+ return;
+ }
+
+ if (MsIsVista())
+ {
+ helper = CmStartUacHelper();
+ }
+
+ ret = MsExecDriverInstaller(arg);
+
+ CmStopUacHelper(helper);
+
+ p = NewPack();
+ PackAddBool(p, "ret", ret);
+ SendPack(s, p);
+
+ FreePack(p);
+}
+
+#endif // OS_WIN32
+
+// Start the driver installer
+void CnExecDriverInstaller(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnExecDriverInstaller(s, p);
+#endif // OS_WIN32
+}
+
+// Certificate confirmation dialog
+void CnCheckCert(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnCheckCert(s, p);
+#endif // OS_WIN32
+}
+
+// NIC information dialog
+void CnNicInfo(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnNicInfo(s, p);
+#endif // OS_WIN32
+}
+
+// Message display dialog
+void CnMsgDlg(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnMsgDlg(s, p);
+#endif // OS_WIN32
+}
+
+// Password input dialog
+void CnPasswordDlg(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnPasswordDlg(s, p);
+#endif // OS_WIN32
+}
+
+// Connection Error dialog
+void CnConnectErrorDlg(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnConnectErrorDlg(s, p);
+#endif // OS_WIN32
+}
+
+// Status indicator
+void CnStatusPrinter(SOCK *s, PACK *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32CnStatusPrinter(s, p);
+#endif // OS_WIN32
+}
+// Client notification service listener thread
+void CnListenerProc(THREAD *thread, void *param)
+{
+ TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param;
+ SOCK *s;
+ PACK *p;
+ // Validate arguments
+ if (data == NULL || thread == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ //Set Application ID
+ JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM);
+#endif // OS_WIN32
+
+ s = data->s;
+ AddRef(s->ref);
+ NoticeThreadInit(thread);
+
+ if (s->LocalIP.addr[0] == 127)
+ {
+ p = RecvPack(s);
+
+ if (p != NULL)
+ {
+ char function[MAX_SIZE];
+
+ if (PackGetStr(p, "function", function, sizeof(function)))
+ {
+ if (StrCmpi(function, "status_printer") == 0)
+ {
+ CnStatusPrinter(s, p);
+ }
+ else if (StrCmpi(function, "connecterror_dialog") == 0)
+ {
+ CnConnectErrorDlg(s, p);
+ }
+ else if (StrCmpi(function, "msg_dialog") == 0)
+ {
+ CnMsgDlg(s, p);
+ }
+ else if (StrCmpi(function, "nicinfo") == 0)
+ {
+ CnNicInfo(s, p);
+ }
+ else if (StrCmpi(function, "password_dialog") == 0)
+ {
+ CnPasswordDlg(s, p);
+ }
+ else if (StrCmpi(function, "secure_sign") == 0)
+ {
+ CnSecureSign(s, p);
+ }
+ else if (StrCmpi(function, "check_cert") == 0)
+ {
+ CnCheckCert(s, p);
+ }
+ else if (StrCmpi(function, "exit") == 0)
+ {
+#ifdef OS_WIN32
+ MsTerminateProcess();
+#else // OS_WIN32
+ _exit(0);
+#endif // OS_WIN32
+ }
+ else if (StrCmpi(function, "get_session_id") == 0)
+ {
+ PACK *p = NewPack();
+#ifdef OS_WIN32
+ PackAddInt(p, "session_id", MsGetCurrentTerminalSessionId());
+#endif // OS_WIN32
+ SendPack(s, p);
+ FreePack(p);
+ }
+ else if (StrCmpi(function, "exec_driver_installer") == 0)
+ {
+ CnExecDriverInstaller(s, p);
+ }
+ else if (StrCmpi(function, "release_socket") == 0)
+ {
+ // Stop the listener
+ CnReleaseSocket(s, p);
+ }
+ }
+
+ FreePack(p);
+ }
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// Do the Secure Sign
+void CnSecureSign(SOCK *s, PACK *p)
+{
+ SECURE_SIGN sign;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&sign, sizeof(sign));
+ InRpcSecureSign(&sign, p);
+
+#ifdef OS_WIN32
+ // Win32: Show dialog
+ ret = Win32CiSecureSign(&sign);
+#else // OS_WIN32
+ // UNIX: not implemented
+ ret = false;
+#endif // OS_WIN32
+
+ p = NewPack();
+
+ OutRpcSecureSign(p, &sign);
+ FreeRpcSecureSign(&sign);
+
+ PackAddBool(p, "ret", ret);
+
+ SendPack(s, p);
+ FreePack(p);
+}
+
+// Stop the listener
+void CnReleaseSocket(SOCK *s, PACK *p)
+{
+ UINT pid = 0;
+ UINT current_pid = 0;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ pid = PackGetInt(p, "pid");
+
+#ifdef OS_WIN32
+ current_pid = MsGetProcessId();
+#endif // OS_WIN32
+
+ if (current_pid == pid)
+ {
+ return;
+ }
+
+ Lock(cn_listener_lock);
+ {
+ if (cn_listener != NULL)
+ {
+ if (cn_listener->Halt == false)
+ {
+ StopListener(cn_listener);
+
+ cn_next_allow = Tick64() + (6 * 1000);
+ }
+ }
+ }
+ Unlock(cn_listener_lock);
+}
+
+// Start the client notification service
+void CnStart()
+{
+ CEDAR *cedar;
+ LISTENER *o;
+ UINT last_cursor_hash = 0;
+ bool last_session_active = false;
+
+ cn_next_allow = 0;
+ cn_listener_lock = NewLock();
+
+#ifdef OS_WIN32
+ MsSetShutdownParameters(0xff, 0x00000001);
+ InitWinUi(_UU("CN_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+#endif // OS_WIN32
+
+ cedar = NewCedar(NULL, NULL);
+
+ if (CnCheckAlreadyExists(true))
+ {
+ // Already started
+ ReleaseCedar(cedar);
+#ifdef OS_WIN32
+ FreeWinUi();
+#endif // OS_WIN32
+ return;
+ }
+
+#ifdef OS_WIN32
+ MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY,
+ "NotifyServerProcessId", MsGetProcessId());
+#endif // OS_WIN32
+
+ DisableDosProtect();
+
+BEGIN_LISTENER:
+ Lock(cn_listener_lock);
+ cn_listener = o = NewListenerEx(cedar, LISTENER_TCP, CLIENT_NOTIFY_PORT, CnListenerProc, NULL);
+ Unlock(cn_listener_lock);
+
+ while (true)
+ {
+ UINT current_cursor_hash = 0;
+ bool cursor_changed = false;
+
+#ifdef OS_WIN32
+ // Get the current cursor position
+ current_cursor_hash = MsGetCursorPosHash();
+#endif // OS_WIN32
+
+ if (last_cursor_hash != current_cursor_hash)
+ {
+ // Check the cursor position
+ cursor_changed = true;
+ last_cursor_hash = current_cursor_hash;
+ }
+
+ Lock(cn_listener_lock);
+
+ // Check the status periodically after that the listener has started
+ if (cn_listener->Status == LISTENER_STATUS_TRYING || cn_listener->Halt)
+ {
+ bool session_active = false;
+#ifdef OS_WIN32
+ session_active = MsIsCurrentTerminalSessionActive();
+ if (cursor_changed)
+ {
+ // If the cursor position is changed but the terminal session is
+ // not active, the cursor position is regarded as not changed.
+ if (session_active == false)
+ {
+ cursor_changed = false;
+ }
+ }
+ if (last_session_active != session_active)
+ {
+ //If the cursor position doesn't changed but the terminal session
+ // became active than previous, the cursor position is regarded as changed.
+ last_session_active = session_active;
+
+ if (session_active)
+ {
+ cursor_changed = true;
+ }
+ }
+#endif // OS_WIN32
+
+ // If the port cannot be opened
+ if (cn_next_allow <= Tick64())
+ {
+ if (cursor_changed || cn_listener->Halt)
+ {
+ if (cursor_changed)
+ {
+ // It can be judged to have the rights to open the port
+ // since the mouse cursor is moving.
+ // So, take over the port which is owned by other process forcibly
+ CncReleaseSocket();
+ }
+
+ if (cn_listener->Halt)
+ {
+ ReleaseListener(cn_listener);
+ cn_listener = NULL;
+
+ Unlock(cn_listener_lock);
+ goto BEGIN_LISTENER;
+ }
+ }
+ }
+ }
+
+ Unlock(cn_listener_lock);
+
+ SleepThread(1000);
+ }
+}
+
+// Confirm whether the account file is parsed successfully
+bool CiTryToParseAccount(BUF *b)
+{
+ RPC_CLIENT_CREATE_ACCOUNT *a;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ a = CiCfgToAccount(b);
+ if (a != NULL)
+ {
+ CiFreeClientCreateAccount(a);
+ Free(a);
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+bool CiTryToParseAccountFile(wchar_t *name)
+{
+ bool ret;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = CiTryToParseAccount(b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Confirm whether the account information includes sensitive information
+bool CiHasAccountSensitiveInformation(BUF *b)
+{
+ RPC_CLIENT_CREATE_ACCOUNT *a;
+ bool ret = false;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ a = CiCfgToAccount(b);
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ ret = true;
+ }
+ else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
+ {
+ ret = true;
+ }
+
+ CiFreeClientCreateAccount(a);
+ Free(a);
+
+ return ret;
+}
+bool CiHasAccountSensitiveInformationFile(wchar_t *name)
+{
+ bool ret = false;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = CiHasAccountSensitiveInformation(b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Delete the sensitive information in the account information
+bool CiEraseSensitiveInAccount(BUF *b)
+{
+ RPC_CLIENT_CREATE_ACCOUNT *a;
+ BUF *b2;
+ bool ret = false;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ a = CiCfgToAccount(b);
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ Zero(a->ClientAuth->HashedPassword, sizeof(a->ClientAuth->HashedPassword));
+ ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
+ }
+ else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
+ {
+ ClearStr(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword));
+ ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
+ }
+
+ b2 = CiAccountToCfg(a);
+ if (b2 != NULL)
+ {
+ ret = true;
+
+ ClearBuf(b);
+
+ WriteBuf(b, b2->Buf, b2->Size);
+ SeekBuf(b, 0, 0);
+
+ FreeBuf(b2);
+ }
+
+ CiFreeClientCreateAccount(a);
+ Free(a);
+
+ return ret;
+}
+
+// Read the account information from the buffer
+RPC_CLIENT_CREATE_ACCOUNT *CiCfgToAccount(BUF *b)
+{
+ RPC_CLIENT_CREATE_ACCOUNT *t;
+ FOLDER *f;
+ ACCOUNT *a;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ f = CfgBufTextToFolder(b);
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ a = CiLoadClientAccount(f);
+
+ CfgDeleteFolder(f);
+
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ DeleteLock(a->lock);
+
+ t = ZeroMalloc(sizeof(RPC_CLIENT_CREATE_ACCOUNT));
+ t->ClientOption = a->ClientOption;
+ t->ClientAuth = a->ClientAuth;
+ t->StartupAccount = a->StartupAccount;
+ t->CheckServerCert = a->CheckServerCert;
+ t->ServerCert = a->ServerCert;
+ Free(a);
+
+ return t;
+}
+
+// Write the account information to a buffer
+BUF *CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT *t)
+{
+ BUF *b;
+ FOLDER *root;
+ ACCOUNT a;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+ Zero(&a, sizeof(a));
+ a.ClientOption = t->ClientOption;
+ a.ClientAuth = t->ClientAuth;
+ a.CheckServerCert = t->CheckServerCert;
+ a.ServerCert = t->ServerCert;
+ a.StartupAccount = t->StartupAccount;
+
+ CiWriteAccountData(root, &a);
+
+ b = CfgFolderToBufEx(root, true, true);
+ CfgDeleteFolder(root);
+
+ return b;
+}
+
+// RPC dispatch routine
+PACK *CiRpcDispatch(RPC *rpc, char *name, PACK *p)
+{
+ CLIENT *c = rpc->Param;
+ PACK *ret;
+ // Validate arguments
+ if (rpc == NULL || name == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewPack();
+
+ if (StrCmpi(name, "GetClientVersion") == 0)
+ {
+ RPC_CLIENT_VERSION a;
+ if (CtGetClientVersion(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientVersion(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "GetCmSetting") == 0)
+ {
+ CM_SETTING a;
+ if (CtGetCmSetting(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcCmSetting(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "SetCmSetting") == 0)
+ {
+ CM_SETTING a;
+ Zero(&a, sizeof(a));
+ InRpcCmSetting(&a, p);
+ if (CtSetCmSetting(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "SetPassword") == 0)
+ {
+ RPC_CLIENT_PASSWORD a;
+ InRpcClientPassword(&a, p);
+ if (CtSetPassword(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetPasswordSetting") == 0)
+ {
+ RPC_CLIENT_PASSWORD_SETTING a;
+ if (CtGetPasswordSetting(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientPasswordSetting(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "EnumCa") == 0)
+ {
+ RPC_CLIENT_ENUM_CA a;
+ if (CtEnumCa(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientEnumCa(ret, &a);
+ CiFreeClientEnumCa(&a);
+ }
+ }
+ else if (StrCmpi(name, "AddCa") == 0)
+ {
+ RPC_CERT a;
+ InRpcCert(&a, p);
+ if (CtAddCa(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ FreeX(a.x);
+ }
+ else if (StrCmpi(name, "DeleteCa") == 0)
+ {
+ RPC_CLIENT_DELETE_CA a;
+ InRpcClientDeleteCa(&a, p);
+ if (CtDeleteCa(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetCa") == 0)
+ {
+ RPC_GET_CA a;
+ InRpcGetCa(&a, p);
+ if (CtGetCa(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcGetCa(ret, &a);
+ }
+ CiFreeGetCa(&a);
+ }
+ else if (StrCmpi(name, "EnumSecure") == 0)
+ {
+ RPC_CLIENT_ENUM_SECURE a;
+ if (CtEnumSecure(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientEnumSecure(ret, &a);
+ CiFreeClientEnumSecure(&a);
+ }
+ }
+ else if (StrCmpi(name, "UseSecure") == 0)
+ {
+ RPC_USE_SECURE a;
+ InRpcUseSecure(&a, p);
+ if (CtUseSecure(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetUseSecure") == 0)
+ {
+ RPC_USE_SECURE a;
+ Zero(&a, sizeof(a));
+ if (CtGetUseSecure(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcUseSecure(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "EnumObjectInSecure") == 0)
+ {
+ RPC_ENUM_OBJECT_IN_SECURE a;
+ if (CtEnumObjectInSecure(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcEnumObjectInSecure(ret, &a);
+ CiFreeEnumObjectInSecure(&a);
+ }
+ }
+ else if (StrCmpi(name, "CreateVLan") == 0)
+ {
+ RPC_CLIENT_CREATE_VLAN a;
+ InRpcCreateVLan(&a, p);
+ if (CtCreateVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "UpgradeVLan") == 0)
+ {
+ RPC_CLIENT_CREATE_VLAN a;
+ InRpcCreateVLan(&a, p);
+ if (CtUpgradeVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetVLan") == 0)
+ {
+ RPC_CLIENT_GET_VLAN a;
+ InRpcClientGetVLan(&a, p);
+ if (CtGetVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientGetVLan(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "SetVLan") == 0)
+ {
+ RPC_CLIENT_SET_VLAN a;
+ InRpcClientSetVLan(&a, p);
+ if (CtSetVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "EnumVLan") == 0)
+ {
+ RPC_CLIENT_ENUM_VLAN a;
+ if (CtEnumVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientEnumVLan(ret, &a);
+ CiFreeClientEnumVLan(&a);
+ }
+ }
+ else if (StrCmpi(name, "DeleteVLan") == 0)
+ {
+ RPC_CLIENT_CREATE_VLAN a;
+ InRpcCreateVLan(&a, p);
+ if (CtDeleteVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "EnableVLan") == 0)
+ {
+ RPC_CLIENT_CREATE_VLAN a;
+ InRpcCreateVLan(&a, p);
+ if (CtEnableVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "DisableVLan") == 0)
+ {
+ RPC_CLIENT_CREATE_VLAN a;
+ InRpcCreateVLan(&a, p);
+ if (CtDisableVLan(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "CreateAccount") == 0)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT a;
+ InRpcClientCreateAccount(&a, p);
+ if (CtCreateAccount(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ CiFreeClientCreateAccount(&a);
+ }
+ else if (StrCmpi(name, "EnumAccount") == 0)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT a;
+ if (CtEnumAccount(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientEnumAccount(ret, &a);
+ CiFreeClientEnumAccount(&a);
+ }
+ }
+ else if (StrCmpi(name, "DeleteAccount") == 0)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT a;
+ InRpcClientDeleteAccount(&a, p);
+ if (CtDeleteAccount(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "SetStartupAccount") == 0)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT a;
+ InRpcClientDeleteAccount(&a, p);
+ if (CtSetStartupAccount(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "RemoveStartupAccount") == 0)
+ {
+ RPC_CLIENT_DELETE_ACCOUNT a;
+ InRpcClientDeleteAccount(&a, p);
+ if (CtRemoveStartupAccount(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetIssuer") == 0)
+ {
+ RPC_GET_ISSUER a;
+ InRpcGetIssuer(&a, p);
+ if (CtGetIssuer(c, &a))
+ {
+ OutRpcGetIssuer(ret, &a);
+ }
+ else
+ {
+ RpcError(ret, c->Err);
+ }
+ CiFreeGetIssuer(&a);
+ }
+ else if (StrCmpi(name, "GetCommonProxySetting") == 0)
+ {
+ INTERNET_SETTING t;
+ InRpcInternetSetting(&t, p);
+ if (CtGetCommonProxySetting(c, &t))
+ {
+ OutRpcInternetSetting(ret, &t);
+ }
+ else
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "SetCommonProxySetting") == 0)
+ {
+ INTERNET_SETTING t;
+ InRpcInternetSetting(&t, p);
+ if (CtSetCommonProxySetting(c, &t))
+ {
+ OutRpcInternetSetting(ret, &t);
+ }
+ else
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "SetAccount") == 0)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT a;
+ InRpcClientCreateAccount(&a, p);
+ if (CtSetAccount(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ CiFreeClientCreateAccount(&a);
+ }
+ else if (StrCmpi(name, "GetAccount") == 0)
+ {
+ RPC_CLIENT_GET_ACCOUNT a;
+ InRpcClientGetAccount(&a, p);
+ if (CtGetAccount(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientGetAccount(ret, &a);
+ }
+ CiFreeClientGetAccount(&a);
+ }
+ else if (StrCmpi(name, "RenameAccount") == 0)
+ {
+ RPC_RENAME_ACCOUNT a;
+ InRpcRenameAccount(&a, p);
+ if (CtRenameAccount(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "SetClientConfig") == 0)
+ {
+ CLIENT_CONFIG a;
+ InRpcClientConfig(&a, p);
+ if (CtSetClientConfig(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetClientConfig") == 0)
+ {
+ CLIENT_CONFIG a;
+ if (CtGetClientConfig(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientConfig(ret, &a);
+ }
+ }
+ else if (StrCmpi(name, "Connect") == 0)
+ {
+ RPC_CLIENT_CONNECT a;
+ InRpcClientConnect(&a, p);
+ if (CtConnect(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "Disconnect") == 0)
+ {
+ RPC_CLIENT_CONNECT a;
+ InRpcClientConnect(&a, p);
+ if (CtDisconnect(c, &a, false) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ }
+ else if (StrCmpi(name, "GetAccountStatus") == 0)
+ {
+ RPC_CLIENT_GET_CONNECTION_STATUS a;
+ InRpcClientGetConnectionStatus(&a, p);
+ if (CtGetAccountStatus(c, &a) == false)
+ {
+ RpcError(ret, c->Err);
+ }
+ else
+ {
+ OutRpcClientGetConnectionStatus(ret, &a);
+ }
+ CiFreeClientGetConnectionStatus(&a);
+ }
+ else
+ {
+ FreePack(ret);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+// Set the CM_SETTING
+UINT CcSetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
+{
+ PACK *ret, *p;
+ UINT err;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCmSetting(p, a);
+
+ ret = RpcCall(r->Rpc, "SetCmSetting", p);
+
+ if (RpcIsOk(ret))
+ {
+ FreePack(ret);
+ return 0;
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ FreePack(ret);
+ return err;
+ }
+}
+
+// Get the CM_SETTING
+UINT CcGetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
+{
+ PACK *ret;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "GetCmSetting", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcCmSetting(a, ret);
+ FreePack(ret);
+ return 0;
+ }
+ else
+ {
+ UINT err = RpcGetError(ret);
+ FreePack(ret);
+ return err;
+ }
+}
+
+// Get the client version
+UINT CcGetClientVersion(REMOTE_CLIENT *r, RPC_CLIENT_VERSION *a)
+{
+ PACK *ret;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "GetClientVersion", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientVersion(a, ret);
+ FreePack(ret);
+ return 0;
+ }
+ else
+ {
+ UINT err = RpcGetError(ret);
+ FreePack(ret);
+ return err;
+ }
+}
+
+// Set the password
+UINT CcSetPassword(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD *pass)
+{
+ PACK *ret, *p;
+ // Validate arguments
+ if (r == NULL || pass == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+
+ OutRpcClientPassword(p, pass);
+
+ ret = RpcCall(r->Rpc, "SetPassword", p);
+
+ if (RpcIsOk(ret))
+ {
+ FreePack(ret);
+ return 0;
+ }
+ else
+ {
+ UINT err = RpcGetError(ret);
+ FreePack(ret);
+ return err;
+ }
+}
+
+// Get the password setting
+UINT CcGetPasswordSetting(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD_SETTING *a)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "GetPasswordSetting", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientPasswordSetting(a, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+ return err;
+}
+
+// Enumerate the CA
+UINT CcEnumCa(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_CA *e)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || e == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "EnumCa", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientEnumCa(e, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Add the CA
+UINT CcAddCa(REMOTE_CLIENT *r, RPC_CERT *cert)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || cert == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCert(p, cert);
+
+ ret = RpcCall(r->Rpc, "AddCa", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Delete the CA
+UINT CcDeleteCa(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_CA *c)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || c == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientDeleteCa(p, c);
+
+ ret = RpcCall(r->Rpc, "DeleteCa", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+
+// Get the proxy setting
+UINT CcGetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcInternetSetting(p, a);
+
+ ret = RpcCall(r->Rpc, "GetCommonProxySetting", p);
+
+ if (RpcIsOk(ret))
+ {
+ Zero(a, sizeof(INTERNET_SETTING));
+ InRpcInternetSetting(a, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Set the proxy setting
+UINT CcSetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcInternetSetting(p, a);
+
+ ret = RpcCall(r->Rpc, "SetCommonProxySetting", p);
+
+ if (RpcIsOk(ret))
+ {
+ Zero(a, sizeof(INTERNET_SETTING));
+ InRpcInternetSetting(a, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the issuer
+UINT CcGetIssuer(REMOTE_CLIENT *r, RPC_GET_ISSUER *a)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcGetIssuer(p, a);
+
+ ret = RpcCall(r->Rpc, "GetIssuer", p);
+
+ if (RpcIsOk(ret))
+ {
+ if (a->x != NULL)
+ {
+ FreeX(a->x);
+ a->x = NULL;
+ }
+ InRpcGetIssuer(a, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the CA
+UINT CcGetCa(REMOTE_CLIENT *r, RPC_GET_CA *get)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || get == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcGetCa(p, get);
+
+ ret = RpcCall(r->Rpc, "GetCa", p);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcGetCa(get, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Enumeration of the secure devices
+UINT CcEnumSecure(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_SECURE *e)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || e == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "EnumSecure", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientEnumSecure(e, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the secure device that the user is using
+UINT CcGetUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || sec == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+
+ ret = RpcCall(r->Rpc, "GetUseSecure", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+ else
+ {
+ InRpcUseSecure(sec, ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Use the secure device
+UINT CcUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || sec == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcUseSecure(p, sec);
+
+ ret = RpcCall(r->Rpc, "UseSecure", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Enumerate objects in the secure device
+UINT CcEnumObjectInSecure(REMOTE_CLIENT *r, RPC_ENUM_OBJECT_IN_SECURE *e)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || e == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "EnumObjectInSecure", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcEnumObjectInSecure(e, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get a next recommended virtual LAN card name
+bool CiGetNextRecommendedVLanName(REMOTE_CLIENT *r, char *name, UINT size)
+{
+ RPC_CLIENT_ENUM_VLAN t;
+ UINT i;
+ bool b;
+ UINT j;
+ bool ok = false;
+ // Validate arguments
+ if (r == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CcEnumVLan(r, &t) != ERR_NO_ERROR)
+ {
+ return false;
+ }
+
+ for (i = 1;i < 128;i++)
+ {
+ char tmp[MAX_SIZE];
+
+ CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
+
+ b = false;
+
+ for (j = 0;j < t.NumItem;j++)
+ {
+ if (StrCmpi(t.Items[j]->DeviceName, tmp) == 0)
+ {
+ b = true;
+ break;
+ }
+ }
+
+ if (b == false)
+ {
+ ok = true;
+
+ StrCpy(name, size, tmp);
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ CiFreeClientEnumVLan(&t);
+ }
+
+ return true;
+}
+
+// Generate a virtual LAN card name automatically
+void CiGenerateVLanRegulatedName(char *name, UINT size, UINT i)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (i == 1)
+ {
+ StrCpy(name, size, "VPN");
+ }
+ else
+ {
+ Format(name, size, "VPN%u", i);
+ }
+}
+
+// Examine whether the specified name is valid as a virtual LAN card name of Windows 8 and later?
+bool CiIsValidVLanRegulatedName(char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ for (i = 1;i < 128;i++)
+ {
+ char tmp[MAX_SIZE];
+
+ CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
+
+ if (StrCmpi(name, tmp) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Create a VLAN
+UINT CcCreateVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ char *s = NULL;
+ // Validate arguments
+ if (r == NULL || create == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCreateVLan(p, create);
+
+#ifdef OS_WIN32
+ s = MsNoWarningSoundInit();
+#endif // OS_WIN32
+
+ ret = RpcCall(r->Rpc, "CreateVLan", p);
+
+#ifdef OS_WIN32
+ MsNoWarningSoundFree(s);
+#endif // OS_WIN32
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Upgrade the VLAN
+UINT CcUpgradeVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ char *s = NULL;
+ // Validate arguments
+ if (r == NULL || create == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCreateVLan(p, create);
+
+#ifdef OS_WIN32
+ s = MsNoWarningSoundInit();
+#endif // OS_WIN32
+
+ ret = RpcCall(r->Rpc, "UpgradeVLan", p);
+
+#ifdef OS_WIN32
+ MsNoWarningSoundFree(s);
+#endif // OS_WIN32
+
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the VLAN
+UINT CcGetVLan(REMOTE_CLIENT *r, RPC_CLIENT_GET_VLAN *get)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || get == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientGetVLan(p, get);
+
+ ret = RpcCall(r->Rpc, "GetVLan", p);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientGetVLan(get, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// VLAN configuration
+UINT CcSetVLan(REMOTE_CLIENT *r, RPC_CLIENT_SET_VLAN *set)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || set == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientSetVLan(p, set);
+
+ ret = RpcCall(r->Rpc, "SetVLan", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Enumeration of VLAN
+UINT CcEnumVLan(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_VLAN *e)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || e == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "EnumVLan", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientEnumVLan(e, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Delete the VLAN
+UINT CcDeleteVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *d)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || d == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCreateVLan(p, d);
+
+ ret = RpcCall(r->Rpc, "DeleteVLan", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Enable the VLAN
+UINT CcEnableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || vlan == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCreateVLan(p, vlan);
+
+ ret = RpcCall(r->Rpc, "EnableVLan", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Disable the VLAN
+UINT CcDisableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || vlan == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcCreateVLan(p, vlan);
+
+ ret = RpcCall(r->Rpc, "DisableVLan", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Create an Account
+UINT CcCreateAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientCreateAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "CreateAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Enumeration of accounts
+UINT CcEnumAccount(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_ACCOUNT *e)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || e == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "EnumAccount", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ UINT i;
+ InRpcClientEnumAccount(e, ret);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = e->Items[i];
+
+ if (IsEmptyStr(t->HubName) && t->Port == 0)
+ {
+ UINT err2;
+ RPC_CLIENT_GET_ACCOUNT a;
+
+ // Because the Client Manager can not get the port number and HUB name
+ // when enumerating in the VPN Client of the old version, get these separately.
+ Zero(&a, sizeof(a));
+ UniStrCpy(a.AccountName, sizeof(a.AccountName), t->AccountName);
+ err2 = CcGetAccount(r, &a);
+ if (err2 == ERR_NO_ERROR)
+ {
+ StrCpy(t->HubName, sizeof(t->HubName), a.ClientOption->HubName);
+ t->Port = a.ClientOption->Port;
+
+ CiFreeClientGetAccount(&a);
+ }
+ }
+ }
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Unset the startup flag of the accout
+UINT CcRemoveStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientDeleteAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "RemoveStartupAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Set to start-up flag of the account
+UINT CcSetStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientDeleteAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "SetStartupAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Delete the account
+UINT CcDeleteAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientDeleteAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "DeleteAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Account setting
+UINT CcSetAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientCreateAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "SetAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the account
+UINT CcGetAccount(REMOTE_CLIENT *r, RPC_CLIENT_GET_ACCOUNT *a)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || a == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientGetAccount(p, a);
+
+ ret = RpcCall(r->Rpc, "GetAccount", p);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientGetAccount(a, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Change the account name
+UINT CcRenameAccount(REMOTE_CLIENT *r, RPC_RENAME_ACCOUNT *rename)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || rename == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcRenameAccount(p, rename);
+
+ ret = RpcCall(r->Rpc, "RenameAccount", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Set the Client configuration
+UINT CcSetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
+{
+ PACK *p, *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || o == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientConfig(p, o);
+
+ ret = RpcCall(r->Rpc, "SetClientConfig", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the client configuration
+UINT CcGetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
+{
+ PACK *ret;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || o == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = RpcCall(r->Rpc, "GetClientConfig", NULL);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientConfig(o, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Set the service to foreground process
+void CcSetServiceToForegroundProcess(REMOTE_CLIENT *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+ // Abolition
+/*
+ if (r->Rpc != NULL && r->Rpc->Sock != NULL && r->Rpc->Sock->RemoteIP.addr[0] == 127)
+ {
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&
+ GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ // Only on a Windows 2000 or later
+ RPC_CLIENT_VERSION v;
+ Zero(&v, sizeof(v));
+
+ if (r->ClientBuildInt == 0)
+ {
+ CcGetClientVersion(r, &v);
+ r->ClientBuildInt = v.ClientBuildInt;
+ r->ProcessId = v.ProcessId;
+ }
+ if (r->ProcessId != 0 && r->ClientBuildInt <= 5080)
+ {
+#ifdef OS_WIN32
+ // Set the service process as a foreground window
+ AllowFGWindow(v.ProcessId);
+#endif // OS_WIN32
+ }
+ }
+ }*/
+}
+
+// Connect
+UINT CcConnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || connect == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ CcSetServiceToForegroundProcess(r);
+
+ p = NewPack();
+ OutRpcClientConnect(p, connect);
+
+ ret = RpcCall(r->Rpc, "Connect", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Disconnect
+UINT CcDisconnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || connect == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ CcSetServiceToForegroundProcess(r);
+
+ p = NewPack();
+ OutRpcClientConnect(p, connect);
+
+ ret = RpcCall(r->Rpc, "Disconnect", p);
+
+ if (RpcIsOk(ret) == false)
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+// Get the account status
+UINT CcGetAccountStatus(REMOTE_CLIENT *r, RPC_CLIENT_GET_CONNECTION_STATUS *st)
+{
+ PACK *ret, *p;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || st == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ p = NewPack();
+ OutRpcClientGetConnectionStatus(p, st);
+
+ ret = RpcCall(r->Rpc, "GetAccountStatus", p);
+
+ if (RpcIsOk(ret))
+ {
+ InRpcClientGetConnectionStatus(st, ret);
+ }
+ else
+ {
+ err = RpcGetError(ret);
+ }
+
+ FreePack(ret);
+
+ return err;
+}
+
+
+// Client service sends a notification to the connection manager
+void CiNotify(CLIENT *c)
+{
+ CiNotifyInternal(c);
+}
+void CiNotifyInternal(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Set all the notification event
+ LockList(c->NotifyCancelList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
+ {
+ CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
+ Cancel(cancel);
+ }
+ }
+ UnlockList(c->NotifyCancelList);
+}
+
+// Release the RPC_CLIENT_ENUM_ACCOUNT
+void CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *a)
+{
+ UINT i;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < a->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = a->Items[i];
+ Free(e);
+ }
+ Free(a->Items);
+}
+
+
+// Thread to save the configuration file periodically
+void CiSaverThread(THREAD *t, void *param)
+{
+ CLIENT *c = (CLIENT *)param;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ NoticeThreadInit(t);
+
+ // Wait for a certain period of time
+ while (c->Halt == false)
+ {
+ Wait(c->SaverHalter, CLIENT_SAVER_INTERVAL);
+
+ // Save
+ CiSaveConfigurationFile(c);
+ }
+}
+
+// Initialize the Saver
+void CiInitSaver(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->SaverHalter = NewEvent();
+
+ c->SaverThread = NewThread(CiSaverThread, c);
+ WaitThreadInit(c->SaverThread);
+}
+
+// Release the Saver
+void CiFreeSaver(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->Halt = true;
+ Set(c->SaverHalter);
+ WaitThread(c->SaverThread, INFINITE);
+ ReleaseThread(c->SaverThread);
+
+ ReleaseEvent(c->SaverHalter);
+}
+
+// CM_SETTING
+void InRpcCmSetting(CM_SETTING *c, PACK *p)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(CM_SETTING));
+ c->EasyMode = PackGetBool(p, "EasyMode");
+ c->LockMode = PackGetBool(p, "LockMode");
+ PackGetData2(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
+}
+void OutRpcCmSetting(PACK *p, CM_SETTING *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "EasyMode", c->EasyMode);
+ PackAddBool(p, "LockMode", c->LockMode);
+ PackAddData(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
+}
+
+// CLIENT_CONFIG
+void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(CLIENT_CONFIG));
+ c->UseKeepConnect = PackGetInt(p, "UseKeepConnect") == 0 ? false : true;
+ c->KeepConnectPort = PackGetInt(p, "KeepConnectPort");
+ c->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");
+ c->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");
+ c->AllowRemoteConfig = PackGetInt(p, "AllowRemoteConfig") == 0 ? false : true;
+ PackGetStr(p, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
+}
+void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "UseKeepConnect", c->UseKeepConnect);
+ PackAddInt(p, "KeepConnectPort", c->KeepConnectPort);
+ PackAddInt(p, "KeepConnectProtocol", c->KeepConnectProtocol);
+ PackAddInt(p, "KeepConnectInterval", c->KeepConnectInterval);
+ PackAddInt(p, "AllowRemoteConfig", c->AllowRemoteConfig);
+ PackAddStr(p, "KeepConnectHost", c->KeepConnectHost);
+}
+
+// RPC_CLIENT_VERSION
+void InRpcClientVersion(RPC_CLIENT_VERSION *ver, PACK *p)
+{
+ // Validate arguments
+ if (ver == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(ver, sizeof(RPC_CLIENT_VERSION));
+ PackGetStr(p, "ClientProductName", ver->ClientProductName, sizeof(ver->ClientProductName));
+ PackGetStr(p, "ClientVersionString", ver->ClientVersionString, sizeof(ver->ClientVersionString));
+ PackGetStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString));
+ ver->ClientVerInt = PackGetInt(p, "ClientVerInt");
+ ver->ClientBuildInt = PackGetInt(p, "ClientBuildInt");
+ ver->ProcessId = PackGetInt(p, "ProcessId");
+ ver->OsType = PackGetInt(p, "OsType");
+ ver->IsVLanNameRegulated = PackGetBool(p, "IsVLanNameRegulated");
+ ver->IsVgcSupported = PackGetBool(p, "IsVgcSupported");
+ ver->ShowVgcLink = PackGetBool(p, "ShowVgcLink");
+ PackGetStr(p, "ClientId", ver->ClientId, sizeof(ver->ClientId));
+}
+void OutRpcClientVersion(PACK *p, RPC_CLIENT_VERSION *ver)
+{
+ // Validate arguments
+ if (ver == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "ClientProductName", ver->ClientProductName);
+ PackAddStr(p, "ClientVersionString", ver->ClientVersionString);
+ PackAddStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString);
+ PackAddInt(p, "ClientVerInt", ver->ClientVerInt);
+ PackAddInt(p, "ClientBuildInt", ver->ClientBuildInt);
+ PackAddInt(p, "ProcessId", ver->ProcessId);
+ PackAddInt(p, "OsType", ver->OsType);
+ PackAddBool(p, "IsVLanNameRegulated", ver->IsVLanNameRegulated);
+ PackAddBool(p, "IsVgcSupported", ver->IsVgcSupported);
+ PackAddBool(p, "ShowVgcLink", ver->ShowVgcLink);
+ PackAddStr(p, "ClientId", ver->ClientId);
+}
+
+// RPC_CLIENT_PASSWORD
+void InRpcClientPassword(RPC_CLIENT_PASSWORD *pw, PACK *p)
+{
+ // Validate arguments
+ if (pw == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(pw, sizeof(RPC_CLIENT_PASSWORD));
+ PackGetStr(p, "Password", pw->Password, sizeof(pw->Password));
+ pw->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly");
+}
+void OutRpcClientPassword(PACK *p, RPC_CLIENT_PASSWORD *pw)
+{
+ // Validate arguments
+ if (pw == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "Password", pw->Password);
+ PackAddInt(p, "PasswordRemoteOnly", pw->PasswordRemoteOnly);
+}
+
+// RPC_CLIENT_PASSWORD_SETTING
+void InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING *a, PACK *p)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(a, sizeof(RPC_CLIENT_PASSWORD_SETTING));
+
+ a->IsPasswordPresented = PackGetInt(p, "IsPasswordPresented") == 0 ? false : true;
+ a->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly") == 0 ? false : true;
+}
+void OutRpcClientPasswordSetting(PACK *p, RPC_CLIENT_PASSWORD_SETTING *a)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "IsPasswordPresented", a->IsPasswordPresented);
+ PackAddInt(p, "PasswordRemoteOnly", a->PasswordRemoteOnly);
+}
+
+// RPC_CLIENT_ENUM_CA
+void InRpcClientEnumCa(RPC_CLIENT_ENUM_CA *e, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
+ e->NumItem = PackGetNum(p, "NumItem");
+
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_CA_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
+ e->Items[i] = item;
+
+ item->Key = PackGetIntEx(p, "Key", i);
+ PackGetUniStrEx(p, "SubjectName", item->SubjectName, sizeof(item->SubjectName), i);
+ PackGetUniStrEx(p, "IssuerName", item->IssuerName, sizeof(item->IssuerName), i);
+ item->Expires = PackGetInt64Ex(p, "Expires", i);
+ }
+}
+void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddNum(p, "NumItem", e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_CA_ITEM *item = e->Items[i];
+ PackAddIntEx(p, "Key", item->Key, i, e->NumItem);
+ PackAddUniStrEx(p, "SubjectName", item->SubjectName, i, e->NumItem);
+ PackAddUniStrEx(p, "IssuerName", item->IssuerName, i, e->NumItem);
+ PackAddInt64Ex(p, "Expires", item->Expires, i, e->NumItem);
+ }
+}
+
+// RPC_GET_ISSUER
+void InRpcGetIssuer(RPC_GET_ISSUER *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_GET_ISSUER));
+ b = PackGetBuf(p, "x");
+ if (b != NULL)
+ {
+ if (c->x != NULL)
+ {
+ FreeX(c->x);
+ }
+ c->x = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ b = PackGetBuf(p, "issuer_x");
+ if (b != NULL)
+ {
+ c->issuer_x = BufToX(b, false);
+ FreeBuf(b);
+ }
+}
+void OutRpcGetIssuer(PACK *p, RPC_GET_ISSUER *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->x != NULL)
+ {
+ b = XToBuf(c->x, false);
+
+ PackAddBuf(p, "x", b);
+ FreeBuf(b);
+ }
+
+ if (c->issuer_x != NULL)
+ {
+ b = XToBuf(c->issuer_x, false);
+
+ PackAddBuf(p, "issuer_x", b);
+ FreeBuf(b);
+ }
+}
+
+// TRAFFIC_EX
+void InRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(TRAFFIC));
+ t->Recv.BroadcastBytes = PackGetInt64Ex(p, "Ex.Recv.BroadcastBytes", i);
+ t->Recv.BroadcastCount = PackGetInt64Ex(p, "Ex.Recv.BroadcastCount", i);
+ t->Recv.UnicastBytes = PackGetInt64Ex(p, "Ex.Recv.UnicastBytes", i);
+ t->Recv.UnicastCount = PackGetInt64Ex(p, "Ex.Recv.UnicastCount", i);
+ t->Send.BroadcastBytes = PackGetInt64Ex(p, "Ex.Send.BroadcastBytes", i);
+ t->Send.BroadcastCount = PackGetInt64Ex(p, "Ex.Send.BroadcastCount", i);
+ t->Send.UnicastBytes = PackGetInt64Ex(p, "Ex.Send.UnicastBytes", i);
+ t->Send.UnicastCount = PackGetInt64Ex(p, "Ex.Send.UnicastCount", i);
+}
+void OutRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i, UINT num)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt64Ex(p, "Ex.Recv.BroadcastBytes", t->Recv.BroadcastBytes, i, num);
+ PackAddInt64Ex(p, "Ex.Recv.BroadcastCount", t->Recv.BroadcastCount, i, num);
+ PackAddInt64Ex(p, "Ex.Recv.UnicastBytes", t->Recv.UnicastBytes, i, num);
+ PackAddInt64Ex(p, "Ex.Recv.UnicastCount", t->Recv.UnicastCount, i, num);
+ PackAddInt64Ex(p, "Ex.Send.BroadcastBytes", t->Send.BroadcastBytes, i, num);
+ PackAddInt64Ex(p, "Ex.Send.BroadcastCount", t->Send.BroadcastCount, i, num);
+ PackAddInt64Ex(p, "Ex.Send.UnicastBytes", t->Send.UnicastBytes, i, num);
+ PackAddInt64Ex(p, "Ex.Send.UnicastCount", t->Send.UnicastCount, i, num);
+}
+
+// TRAFFIC
+void InRpcTraffic(TRAFFIC *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(TRAFFIC));
+ t->Recv.BroadcastBytes = PackGetInt64(p, "Recv.BroadcastBytes");
+ t->Recv.BroadcastCount = PackGetInt64(p, "Recv.BroadcastCount");
+ t->Recv.UnicastBytes = PackGetInt64(p, "Recv.UnicastBytes");
+ t->Recv.UnicastCount = PackGetInt64(p, "Recv.UnicastCount");
+ t->Send.BroadcastBytes = PackGetInt64(p, "Send.BroadcastBytes");
+ t->Send.BroadcastCount = PackGetInt64(p, "Send.BroadcastCount");
+ t->Send.UnicastBytes = PackGetInt64(p, "Send.UnicastBytes");
+ t->Send.UnicastCount = PackGetInt64(p, "Send.UnicastCount");
+}
+void OutRpcTraffic(PACK *p, TRAFFIC *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt64(p, "Recv.BroadcastBytes", t->Recv.BroadcastBytes);
+ PackAddInt64(p, "Recv.BroadcastCount", t->Recv.BroadcastCount);
+ PackAddInt64(p, "Recv.UnicastBytes", t->Recv.UnicastBytes);
+ PackAddInt64(p, "Recv.UnicastCount", t->Recv.UnicastCount);
+ PackAddInt64(p, "Send.BroadcastBytes", t->Send.BroadcastBytes);
+ PackAddInt64(p, "Send.BroadcastCount", t->Send.BroadcastCount);
+ PackAddInt64(p, "Send.UnicastBytes", t->Send.UnicastBytes);
+ PackAddInt64(p, "Send.UnicastCount", t->Send.UnicastCount);
+}
+
+// RPC_CERT
+void InRpcCert(RPC_CERT *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_CERT));
+ b = PackGetBuf(p, "x");
+ if (b == NULL)
+ {
+ return;
+ }
+
+ c->x = BufToX(b, false);
+ FreeBuf(b);
+}
+void OutRpcCert(PACK *p, RPC_CERT *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->x != NULL)
+ {
+ b = XToBuf(c->x, false);
+
+ PackAddBuf(p, "x", b);
+
+ FreeBuf(b);
+ }
+}
+
+// RPC_CLIENT_DELETE_CA
+void InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA *c, PACK *p)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_CLIENT_DELETE_CA));
+ c->Key = PackGetInt(p, "Key");
+}
+void OutRpcClientDeleteCa(PACK *p, RPC_CLIENT_DELETE_CA *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "Key", c->Key);
+}
+
+// RPC_GET_CA
+void InRpcGetCa(RPC_GET_CA *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_GET_CA));
+
+ c->Key = PackGetInt(p, "Key");
+
+ b = PackGetBuf(p, "x");
+ if (b != NULL)
+ {
+ c->x = BufToX(b, false);
+
+ FreeBuf(b);
+ }
+}
+void OutRpcGetCa(PACK *p, RPC_GET_CA *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "Key", c->Key);
+
+ if (c->x != NULL)
+ {
+ BUF *b = XToBuf(c->x, false);
+
+ PackAddBuf(p, "x", b);
+
+ FreeBuf(b);
+ }
+}
+
+// RPC_CLIENT_ENUM_SECURE
+void InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(e, sizeof(RPC_CLIENT_ENUM_SECURE));
+
+ e->NumItem = PackGetNum(p, "NumItem");
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
+
+ item->DeviceId = PackGetIntEx(p, "DeviceId", i);
+ item->Type = PackGetIntEx(p, "Type", i);
+ PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
+ PackGetStrEx(p, "Manufacturer", item->Manufacturer, sizeof(item->Manufacturer), i);
+ }
+}
+void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddNum(p, "NumItem", e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i];
+
+ PackAddIntEx(p, "DeviceId", item->DeviceId, i, e->NumItem);
+ PackAddIntEx(p, "Type", item->Type, i, e->NumItem);
+ PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
+ PackAddStrEx(p, "Manufacturer", item->Manufacturer, i, e->NumItem);
+ }
+}
+
+// RPC_USE_SECURE
+void InRpcUseSecure(RPC_USE_SECURE *u, PACK *p)
+{
+ // Validate arguments
+ if (u == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(u, sizeof(RPC_USE_SECURE));
+ u->DeviceId = PackGetInt(p, "DeviceId");
+}
+void OutRpcUseSecure(PACK *p, RPC_USE_SECURE *u)
+{
+ // Validate arguments
+ if (u == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "DeviceId", u->DeviceId);
+}
+
+// Release the RPC_ENUM_OBJECT_IN_SECURE
+void CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *a)
+{
+ UINT i;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < a->NumItem;i++)
+ {
+ Free(a->ItemName[i]);
+ }
+ Free(a->ItemName);
+ Free(a->ItemType);
+}
+
+// RPC_ENUM_OBJECT_IN_SECURE
+void InRpcEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *e, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(e, sizeof(RPC_ENUM_OBJECT_IN_SECURE));
+
+ e->NumItem = PackGetNum(p, "NumItem");
+ e->hWnd = PackGetInt(p, "hWnd");
+ e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);
+ e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ char name[MAX_SIZE];
+
+ Zero(name, sizeof(name));
+ PackGetStrEx(p, "ItemName", name, sizeof(name), i);
+ e->ItemName[i] = CopyStr(name);
+
+ e->ItemType[i] = PackGetIntEx(p, "ItemType", i) ? true : false;
+ }
+}
+void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddNum(p, "NumItem", e->NumItem);
+ PackAddInt(p, "hWnd", e->hWnd);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ PackAddStrEx(p, "ItemName", e->ItemName[i], i, e->NumItem);
+ PackAddIntEx(p, "ItemType", e->ItemType[i], i, e->NumItem);
+ }
+}
+
+// RPC_CLIENT_CREATE_VLAN
+void InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN *v, PACK *p)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(v, sizeof(RPC_CLIENT_CREATE_VLAN));
+ PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
+}
+void OutRpcCreateVLan(PACK *p, RPC_CLIENT_CREATE_VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", v->DeviceName);
+}
+
+// RPC_CLIENT_GET_VLAN
+void InRpcClientGetVLan(RPC_CLIENT_GET_VLAN *v, PACK *p)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(v, sizeof(RPC_CLIENT_GET_VLAN));
+ PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
+ v->Enabled = PackGetInt(p, "Enabled") ? true : false;
+ PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
+ PackGetStr(p, "Version", v->Version, sizeof(v->Version));
+ PackGetStr(p, "FileName", v->FileName, sizeof(v->FileName));
+ PackGetStr(p, "Guid", v->Guid, sizeof(v->Guid));
+}
+void OutRpcClientGetVLan(PACK *p, RPC_CLIENT_GET_VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", v->DeviceName);
+ PackAddInt(p, "Enabled", v->Enabled);
+ PackAddStr(p, "MacAddress", v->MacAddress);
+ PackAddStr(p, "Version", v->Version);
+ PackAddStr(p, "FileName", v->FileName);
+ PackAddStr(p, "Guid", v->Guid);
+}
+
+// RPC_CLIENT_SET_VLAN
+void InRpcClientSetVLan(RPC_CLIENT_SET_VLAN *v, PACK *p)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(v, sizeof(RPC_CLIENT_SET_VLAN));
+ PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
+ PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
+}
+void OutRpcClientSetVLan(PACK *p, RPC_CLIENT_SET_VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", v->DeviceName);
+ PackAddStr(p, "MacAddress", v->MacAddress);
+}
+
+// RPC_CLIENT_ENUM_VLAN
+void InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN *v, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(v, sizeof(RPC_CLIENT_ENUM_VLAN));
+ v->NumItem = PackGetNum(p, "NumItem");
+ v->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * v->NumItem);
+
+ for (i = 0;i < v->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i] =
+ ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
+
+ PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
+ item->Enabled = PackGetIntEx(p, "Enabled", i) ? true : false;
+ PackGetStrEx(p, "MacAddress", item->MacAddress, sizeof(item->MacAddress), i);
+ PackGetStrEx(p, "Version", item->Version, sizeof(item->Version), i);
+ }
+}
+void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddNum(p, "NumItem", v->NumItem);
+
+ for (i = 0;i < v->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i];
+
+ PackAddStrEx(p, "DeviceName", item->DeviceName, i, v->NumItem);
+ PackAddIntEx(p, "Enabled", item->Enabled, i, v->NumItem);
+ PackAddStrEx(p, "MacAddress", item->MacAddress, i, v->NumItem);
+ PackAddStrEx(p, "Version", item->Version, i, v->NumItem);
+ }
+}
+
+// CLIENT_OPTION
+void InRpcClientOption(CLIENT_OPTION *c, PACK *p)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(CLIENT_OPTION));
+
+ PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
+ PackGetStr(p, "Hostname", c->Hostname, sizeof(c->Hostname));
+ c->Port = PackGetInt(p, "Port");
+ c->PortUDP = PackGetInt(p, "PortUDP");
+ c->ProxyType = PackGetInt(p, "ProxyType");
+ c->ProxyPort = PackGetInt(p, "ProxyPort");
+ c->NumRetry = PackGetInt(p, "NumRetry");
+ c->RetryInterval = PackGetInt(p, "RetryInterval");
+ c->MaxConnection = PackGetInt(p, "MaxConnection");
+ c->AdditionalConnectionInterval = PackGetInt(p, "AdditionalConnectionInterval");
+ c->ConnectionDisconnectSpan = PackGetInt(p, "ConnectionDisconnectSpan");
+ c->HideStatusWindow = PackGetBool(p, "HideStatusWindow");
+ c->HideNicInfoWindow = PackGetBool(p, "HideNicInfoWindow");
+ c->DisableQoS = PackGetBool(p, "DisableQoS");
+ PackGetStr(p, "ProxyName", c->ProxyName, sizeof(c->ProxyName));
+ PackGetStr(p, "ProxyUsername", c->ProxyUsername, sizeof(c->ProxyUsername));
+ PackGetStr(p, "ProxyPassword", c->ProxyPassword, sizeof(c->ProxyPassword));
+ PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName));
+ PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName));
+ c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
+ c->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
+ c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
+ c->NoRoutingTracking = PackGetInt(p, "NoRoutingTracking") ? true : false;
+ c->RequireMonitorMode = PackGetBool(p, "RequireMonitorMode");
+ c->RequireBridgeRoutingMode = PackGetBool(p, "RequireBridgeRoutingMode");
+ c->FromAdminPack = PackGetBool(p, "FromAdminPack");
+ c->NoTls1 = PackGetBool(p, "NoTls1");
+ c->NoUdpAcceleration = PackGetBool(p, "NoUdpAcceleration");
+ PackGetData2(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
+}
+void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "AccountName", c->AccountName);
+ PackAddStr(p, "Hostname", c->Hostname);
+ PackAddStr(p, "ProxyName", c->ProxyName);
+ PackAddStr(p, "ProxyUsername", c->ProxyUsername);
+ PackAddStr(p, "ProxyPassword", c->ProxyPassword);
+ PackAddStr(p, "HubName", c->HubName);
+ PackAddStr(p, "DeviceName", c->DeviceName);
+ PackAddInt(p, "Port", c->Port);
+ PackAddInt(p, "PortUDP", c->PortUDP);
+ PackAddInt(p, "ProxyType", c->ProxyType);
+ PackAddInt(p, "ProxyPort", c->ProxyPort);
+ PackAddInt(p, "NumRetry", c->NumRetry);
+ PackAddInt(p, "RetryInterval", c->RetryInterval);
+ PackAddInt(p, "MaxConnection", c->MaxConnection);
+ PackAddInt(p, "UseEncrypt", c->UseEncrypt);
+ PackAddInt(p, "UseCompress", c->UseCompress);
+ PackAddInt(p, "HalfConnection", c->HalfConnection);
+ PackAddInt(p, "NoRoutingTracking", c->NoRoutingTracking);
+ PackAddInt(p, "AdditionalConnectionInterval", c->AdditionalConnectionInterval);
+ PackAddInt(p, "ConnectionDisconnectSpan", c->ConnectionDisconnectSpan);
+ PackAddBool(p, "HideStatusWindow", c->HideStatusWindow);
+ PackAddBool(p, "HideNicInfoWindow", c->HideNicInfoWindow);
+ PackAddBool(p, "RequireMonitorMode", c->RequireMonitorMode);
+ PackAddBool(p, "RequireBridgeRoutingMode", c->RequireBridgeRoutingMode);
+ PackAddBool(p, "DisableQoS", c->DisableQoS);
+ PackAddBool(p, "FromAdminPack", c->FromAdminPack);
+ PackAddBool(p, "NoTls1", c->NoTls1);
+ PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration);
+ PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
+}
+
+// CLIENT_AUTH
+void InRpcClientAuth(CLIENT_AUTH *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(CLIENT_AUTH));
+ c->AuthType = PackGetInt(p, "AuthType");
+ PackGetStr(p, "Username", c->Username, sizeof(c->Username));
+
+ switch (c->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ if (PackGetDataSize(p, "HashedPassword") == SHA1_SIZE)
+ {
+ PackGetData(p, "HashedPassword", c->HashedPassword);
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ PackGetStr(p, "PlainPassword", c->PlainPassword, sizeof(c->PlainPassword));
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ b = PackGetBuf(p, "ClientX");
+ if (b != NULL)
+ {
+ c->ClientX = BufToX(b, false);
+ FreeBuf(b);
+ }
+ b = PackGetBuf(p, "ClientK");
+ if (b != NULL)
+ {
+ c->ClientK = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ PackGetStr(p, "SecurePublicCertName", c->SecurePublicCertName, sizeof(c->SecurePublicCertName));
+ PackGetStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName, sizeof(c->SecurePrivateKeyName));
+ break;
+ }
+}
+void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "AuthType", c->AuthType);
+ PackAddStr(p, "Username", c->Username);
+
+ switch (c->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ PackAddData(p, "HashedPassword", c->HashedPassword, SHA1_SIZE);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ PackAddStr(p, "PlainPassword", c->PlainPassword);
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ b = XToBuf(c->ClientX, false);
+ if (b != NULL)
+ {
+ PackAddBuf(p, "ClientX", b);
+ FreeBuf(b);
+ }
+ b = KToBuf(c->ClientK, false, NULL);
+ if (b != NULL)
+ {
+ PackAddBuf(p, "ClientK", b);
+ FreeBuf(b);
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ PackAddStr(p, "SecurePublicCertName", c->SecurePublicCertName);
+ PackAddStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName);
+ break;
+ }
+}
+
+// RPC_CLIENT_CREATE_ACCOUNT
+void InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_CLIENT_CREATE_ACCOUNT));
+ c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+
+ InRpcClientOption(c->ClientOption, p);
+ InRpcClientAuth(c->ClientAuth, p);
+
+ c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
+ c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
+ b = PackGetBuf(p, "ServerCert");
+ if (b != NULL)
+ {
+ c->ServerCert = BufToX(b, false);
+ FreeBuf(b);
+ }
+ PackGetData2(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
+}
+void OutRpcClientCreateAccount(PACK *p, RPC_CLIENT_CREATE_ACCOUNT *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ OutRpcClientOption(p, c->ClientOption);
+ OutRpcClientAuth(p, c->ClientAuth);
+
+ PackAddInt(p, "StartupAccount", c->StartupAccount);
+ PackAddInt(p, "CheckServerCert", c->CheckServerCert);
+ if (c->ServerCert != NULL)
+ {
+ b = XToBuf(c->ServerCert, false);
+ if (b != NULL)
+ {
+ PackAddBuf(p, "ServerCert", b);
+ FreeBuf(b);
+ }
+ }
+ PackAddData(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
+}
+
+// RPC_CLIENT_ENUM_ACCOUNT
+void InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *e, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(e, sizeof(RPC_CLIENT_ENUM_ACCOUNT));
+
+ e->NumItem = PackGetNum(p, "NumItem");
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i] =
+ ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
+
+ PackGetUniStrEx(p, "AccountName", item->AccountName, sizeof(item->AccountName), i);
+ PackGetStrEx(p, "UserName", item->UserName, sizeof(item->UserName), i);
+ PackGetStrEx(p, "ServerName", item->ServerName, sizeof(item->ServerName), i);
+ PackGetStrEx(p, "ProxyName", item->ProxyName, sizeof(item->ProxyName), i);
+ PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
+ item->ProxyType = PackGetIntEx(p, "ProxyType", i);
+ item->Active = PackGetIntEx(p, "Active", i) ? true : false;
+ item->StartupAccount = PackGetIntEx(p, "StartupAccount", i) ? true : false;
+ item->Connected = PackGetBoolEx(p, "Connected", i);
+ item->Port = PackGetIntEx(p, "Port", i);
+ PackGetStrEx(p, "HubName", item->HubName, sizeof(item->HubName), i);
+ item->CreateDateTime = PackGetInt64Ex(p, "CreateDateTime", i);
+ item->UpdateDateTime = PackGetInt64Ex(p, "UpdateDateTime", i);
+ item->LastConnectDateTime = PackGetInt64Ex(p, "LastConnectDateTime", i);
+ }
+}
+void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddNum(p, "NumItem", e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i];
+
+ PackAddUniStrEx(p, "AccountName", item->AccountName, i, e->NumItem);
+ PackAddStrEx(p, "UserName", item->UserName, i, e->NumItem);
+ PackAddStrEx(p, "ServerName", item->ServerName, i, e->NumItem);
+ PackAddStrEx(p, "ProxyName", item->ProxyName, i, e->NumItem);
+ PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
+ PackAddIntEx(p, "ProxyType", item->ProxyType, i, e->NumItem);
+ PackAddIntEx(p, "Active", item->Active, i, e->NumItem);
+ PackAddIntEx(p, "StartupAccount", item->StartupAccount, i, e->NumItem);
+ PackAddBoolEx(p, "Connected", item->Connected, i, e->NumItem);
+ PackAddIntEx(p, "Port", item->Port, i, e->NumItem);
+ PackAddStrEx(p, "HubName", item->HubName, i, e->NumItem);
+ PackAddInt64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
+ PackAddInt64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
+ PackAddInt64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
+ }
+}
+
+// RPC_CLIENT_DELETE_ACCOUNT
+void InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT *a, PACK *p)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(a, sizeof(RPC_CLIENT_DELETE_ACCOUNT));
+ PackGetUniStr(p, "AccountName", a->AccountName, sizeof(a->AccountName));
+}
+void OutRpcClientDeleteAccount(PACK *p, RPC_CLIENT_DELETE_ACCOUNT *a)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "AccountName", a->AccountName);
+}
+
+// RPC_RENAME_ACCOUNT
+void InRpcRenameAccount(RPC_RENAME_ACCOUNT *a, PACK *p)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(a, sizeof(RPC_RENAME_ACCOUNT));
+
+ PackGetUniStr(p, "OldName", a->OldName, sizeof(a->OldName));
+ PackGetUniStr(p, "NewName", a->NewName, sizeof(a->NewName));
+}
+void OutRpcRenameAccount(PACK *p, RPC_RENAME_ACCOUNT *a)
+{
+ // Validate arguments
+ if (a == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "OldName", a->OldName);
+ PackAddUniStr(p, "NewName", a->NewName);
+}
+
+// RPC_CLIENT_GET_ACCOUNT
+void InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT *c, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_CLIENT_GET_ACCOUNT));
+
+ c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+
+ PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
+ c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
+ c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
+ b = PackGetBuf(p, "ServerCert");
+ if (b != NULL)
+ {
+ c->ServerCert = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ InRpcClientOption(c->ClientOption, p);
+ InRpcClientAuth(c->ClientAuth, p);
+
+ c->CreateDateTime = PackGetInt64(p, "CreateDateTime");
+ c->UpdateDateTime = PackGetInt64(p, "UpdateDateTime");
+ c->LastConnectDateTime = PackGetInt64(p, "LastConnectDateTime");
+
+ PackGetData2(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
+}
+void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "AccountName", c->AccountName);
+ PackAddInt(p, "StartupAccount", c->StartupAccount);
+ PackAddInt(p, "CheckServerCert", c->CheckServerCert);
+
+ if (c->ServerCert != NULL)
+ {
+ b = XToBuf(c->ServerCert, false);
+ if (b != NULL)
+ {
+ PackAddBuf(p, "ServerCert", b);
+ FreeBuf(b);
+ }
+ }
+
+ OutRpcClientOption(p, c->ClientOption);
+ OutRpcClientAuth(p, c->ClientAuth);
+
+ PackAddData(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
+
+ PackAddInt64(p, "CreateDateTime", c->CreateDateTime);
+ PackAddInt64(p, "UpdateDateTime", c->UpdateDateTime);
+ PackAddInt64(p, "LastConnectDateTime", c->LastConnectDateTime);
+}
+
+// RPC_CLIENT_CONNECT
+void InRpcClientConnect(RPC_CLIENT_CONNECT *c, PACK *p)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(RPC_CLIENT_CONNECT));
+
+ PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
+}
+void OutRpcClientConnect(PACK *p, RPC_CLIENT_CONNECT *c)
+{
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "AccountName", c->AccountName);
+}
+
+// POLICY
+void InRpcPolicy(POLICY *o, PACK *p)
+{
+ POLICY *pol;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ pol = PackGetPolicy(p);
+ Copy(o, pol, sizeof(POLICY));
+ Free(pol);
+}
+void OutRpcPolicy(PACK *p, POLICY *o)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddPolicy(p, o);
+}
+
+// RPC_CLIENT_GET_CONNECTION_STATUS
+void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(s, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
+
+ PackGetUniStr(p, "AccountName", s->AccountName, sizeof(s->AccountName));
+
+ PackGetStr(p, "ServerName", s->ServerName, sizeof(s->ServerName));
+ PackGetStr(p, "ServerProductName", s->ServerProductName, sizeof(s->ServerProductName));
+ PackGetStr(p, "CipherName", s->CipherName, sizeof(s->CipherName));
+ PackGetStr(p, "SessionName", s->SessionName, sizeof(s->SessionName));
+ PackGetStr(p, "ConnectionName", s->ConnectionName, sizeof(s->ConnectionName));
+
+ if (PackGetDataSize(p, "SessionKey") == SHA1_SIZE)
+ {
+ PackGetData(p, "SessionKey", s->SessionKey);
+ }
+
+ s->SessionStatus = PackGetInt(p, "SessionStatus");
+ s->ServerPort = PackGetInt(p, "ServerPort");
+ s->ServerProductVer = PackGetInt(p, "ServerProductVer");
+ s->ServerProductBuild = PackGetInt(p, "ServerProductBuild");
+ s->NumConnectionsEatablished = PackGetInt(p, "NumConnectionsEatablished");
+ s->MaxTcpConnections = PackGetInt(p, "MaxTcpConnections");
+ s->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
+ s->NumTcpConnectionsUpload = PackGetInt(p, "NumTcpConnectionsUpload");
+ s->NumTcpConnectionsDownload = PackGetInt(p, "NumTcpConnectionsDownload");
+
+ s->StartTime = PackGetInt64(p, "StartTime");
+ s->FirstConnectionEstablisiedTime = PackGetInt64(p, "FirstConnectionEstablisiedTime");
+ s->CurrentConnectionEstablishTime = PackGetInt64(p, "CurrentConnectionEstablishTime");
+ s->TotalSendSize = PackGetInt64(p, "TotalSendSize");
+ s->TotalRecvSize = PackGetInt64(p, "TotalRecvSize");
+ s->TotalSendSizeReal = PackGetInt64(p, "TotalSendSizeReal");
+ s->TotalRecvSizeReal = PackGetInt64(p, "TotalRecvSizeReal");
+
+ s->Active = PackGetInt(p, "Active") ? true : false;
+ s->Connected = PackGetInt(p, "Connected") ? true : false;
+ s->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
+ s->QoS = PackGetInt(p, "QoS") ? true : false;
+ s->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
+ s->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
+ s->IsRUDPSession = PackGetInt(p, "IsRUDPSession") ? true : false;
+ PackGetStr(p, "UnderlayProtocol", s->UnderlayProtocol, sizeof(s->UnderlayProtocol));
+ s->IsUdpAccelerationEnabled = PackGetInt(p, "IsUdpAccelerationEnabled") ? true : false;
+ s->IsUsingUdpAcceleration = PackGetInt(p, "IsUsingUdpAcceleration") ? true : false;
+
+ s->IsBridgeMode = PackGetBool(p, "IsBridgeMode");
+ s->IsMonitorMode = PackGetBool(p, "IsMonitorMode");
+
+ s->VLanId = PackGetInt(p, "VLanId");
+
+ b = PackGetBuf(p, "ServerX");
+ if (b != NULL)
+ {
+ s->ServerX = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ b = PackGetBuf(p, "ClientX");
+ if (b != NULL)
+ {
+ s->ClientX = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ InRpcPolicy(&s->Policy, p);
+
+ InRpcTraffic(&s->Traffic, p);
+}
+void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *c)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || c == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStr(p, "AccountName", c->AccountName);
+
+ PackAddStr(p, "ServerName", c->ServerName);
+ PackAddStr(p, "ServerProductName", c->ServerProductName);
+ PackAddStr(p, "CipherName", c->CipherName);
+ PackAddStr(p, "SessionName", c->SessionName);
+ PackAddStr(p, "ConnectionName", c->ConnectionName);
+
+ PackAddData(p, "SessionKey", c->SessionKey, SHA1_SIZE);
+
+ PackAddInt(p, "Active", c->Active);
+ PackAddInt(p, "Connected", c->Connected);
+ PackAddInt(p, "SessionStatus", c->SessionStatus);
+ PackAddInt(p, "ServerPort", c->ServerPort);
+ PackAddInt(p, "ServerProductVer", c->ServerProductVer);
+ PackAddInt(p, "ServerProductBuild", c->ServerProductBuild);
+ PackAddInt(p, "NumConnectionsEatablished", c->NumConnectionsEatablished);
+ PackAddInt(p, "HalfConnection", c->HalfConnection);
+ PackAddInt(p, "QoS", c->QoS);
+ PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);
+ PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);
+ PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);
+ PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);
+ PackAddInt(p, "UseEncrypt", c->UseEncrypt);
+ PackAddInt(p, "UseCompress", c->UseCompress);
+ PackAddInt(p, "IsRUDPSession", c->IsRUDPSession);
+ PackAddStr(p, "UnderlayProtocol", c->UnderlayProtocol);
+ PackAddInt(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
+ PackAddInt(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
+
+ PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);
+ PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);
+
+ PackAddInt64(p, "StartTime", c->StartTime);
+ PackAddInt64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
+ PackAddInt64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);
+ PackAddInt64(p, "TotalSendSize", c->TotalSendSize);
+ PackAddInt64(p, "TotalRecvSize", c->TotalRecvSize);
+ PackAddInt64(p, "TotalSendSizeReal", c->TotalSendSizeReal);
+ PackAddInt64(p, "TotalRecvSizeReal", c->TotalRecvSizeReal);
+
+ PackAddInt(p, "VLanId", c->VLanId);
+
+ OutRpcPolicy(p, &c->Policy);
+
+ OutRpcTraffic(p, &c->Traffic);
+
+ if (c->ServerX != NULL)
+ {
+ b = XToBuf(c->ServerX, false);
+ PackAddBuf(p, "ServerX", b);
+ FreeBuf(b);
+ }
+
+ if (c->ClientX != NULL)
+ {
+ b = XToBuf(c->ClientX, false);
+ PackAddBuf(p, "ClientX", b);
+ FreeBuf(b);
+ }
+}
+
+void InRpcClientNotify(RPC_CLIENT_NOTIFY *n, PACK *p)
+{
+ // Validate arguments
+ if (n == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(n, sizeof(RPC_CLIENT_NOTIFY));
+
+ n->NotifyCode = PackGetInt(p, "NotifyCode");
+}
+void OutRpcClientNotify(PACK *p, RPC_CLIENT_NOTIFY *n)
+{
+ // Validate arguments
+ if (n == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NotifyCode", n->NotifyCode);
+}
+
+// Notification main
+void CiNotifyMain(CLIENT *c, SOCK *s)
+{
+ CANCEL *cancel;
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ // Register a Cencel
+ cancel = NewCancel();
+ LockList(c->NotifyCancelList);
+ {
+ Add(c->NotifyCancelList, cancel);
+ }
+ UnlockList(c->NotifyCancelList);
+
+ // Wait
+ while (true)
+ {
+ char ch = '@';
+ SOCKSET set;
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+ Select(&set, INFINITE, cancel, NULL);
+
+ if (c->Halt)
+ {
+ // Abort
+ break;
+ }
+
+ // 1 byte transmission
+ if (Send(s, &ch, 1, false) == 0)
+ {
+ // Disconnected
+ break;
+ }
+ }
+
+ // Disconnect
+ Disconnect(s);
+
+ // Unregister the Cancel
+ LockList(c->NotifyCancelList);
+ {
+ Delete(c->NotifyCancelList, cancel);
+ }
+ UnlockList(c->NotifyCancelList);
+
+ ReleaseCancel(cancel);
+}
+
+// RPC acceptance code
+void CiRpcAccepted(CLIENT *c, SOCK *s)
+{
+ UCHAR hashed_password[SHA1_SIZE];
+ UINT rpc_mode;
+ UINT retcode;
+ RPC *rpc;
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ // Receive the RPC mode
+ if (RecvAll(s, &rpc_mode, sizeof(UINT), false) == false)
+ {
+ return;
+ }
+
+ rpc_mode = Endian32(rpc_mode);
+
+ if (rpc_mode == CLIENT_RPC_MODE_NOTIFY)
+ {
+ // Notification mode
+ CiNotifyMain(c, s);
+ return;
+ }
+ else if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT || rpc_mode == CLIENT_RPC_MODE_SHORTCUT_DISCONNECT)
+ {
+ // Shortcut key received
+ UCHAR key[SHA1_SIZE];
+ UINT err = ERR_NO_ERROR;
+ if (RecvAll(s, key, SHA1_SIZE, false))
+ {
+ UINT i;
+ wchar_t title[MAX_ACCOUNT_NAME_LEN + 1];
+ bool ok = false;
+ // Connect to the specified setting
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ Lock(a->lock);
+ {
+ if (Cmp(a->ShortcutKey, key, SHA1_SIZE) == 0)
+ {
+ ok = true;
+ UniStrCpy(title, sizeof(title), a->ClientOption->AccountName);
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ UnlockList(c->AccountList);
+
+ if (ok == false)
+ {
+ err = ERR_ACCOUNT_NOT_FOUND;
+ }
+ else
+ {
+ RPC_CLIENT_CONNECT t;
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), title);
+
+ if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT)
+ {
+ // Connect
+ if (CtConnect(c, &t))
+ {
+ err = ERR_NO_ERROR;
+ }
+ else
+ {
+ err = c->Err;
+ }
+ }
+ else
+ {
+ // Connect
+ if (CtDisconnect(c, &t, false))
+ {
+ err = ERR_NO_ERROR;
+ }
+ else
+ {
+ err = c->Err;
+ }
+ }
+ }
+
+ err = Endian32(err);
+ SendAll(s, &err, sizeof(UINT), false);
+ RecvAll(s, &err, sizeof(UINT), false);
+ }
+ return;
+ }
+
+ // Password reception
+ if (RecvAll(s, hashed_password, SHA1_SIZE, false) == false)
+ {
+ return;
+ }
+
+ retcode = 0;
+
+ // Password comparison
+ if (Cmp(hashed_password, c->EncryptedPassword, SHA1_SIZE) != 0)
+ {
+ retcode = 1;
+ }
+
+ if (c->PasswordRemoteOnly && s->RemoteIP.addr[0] == 127)
+ {
+ // If in a mode that requires a password only remote,
+ // the password sent from localhost is considered to be always correct
+ retcode = 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Config.AllowRemoteConfig == false)
+ {
+ // If the remote control is prohibited,
+ // identify whether this connection is from remote
+ if (s->RemoteIP.addr[0] != 127)
+ {
+ retcode = 2;
+ }
+ }
+ }
+ Unlock(c->lock);
+
+ retcode = Endian32(retcode);
+ // Error code transmission
+ if (SendAll(s, &retcode, sizeof(UINT), false) == false)
+ {
+ return;
+ }
+
+
+
+ if (retcode != 0)
+ {
+ // Disconnect due to an error
+ return;
+ }
+
+ // Create a RPC server
+ rpc = StartRpcServer(s, CiRpcDispatch, c);
+
+ // RPC server operation
+ RpcServer(rpc);
+
+ // Release the RPC server
+ EndRpc(rpc);
+}
+
+// RPC acceptance thread
+void CiRpcAcceptThread(THREAD *thread, void *param)
+{
+ CLIENT_RPC_CONNECTION *conn;
+ CLIENT *c;
+ SOCK *s;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ conn = (CLIENT_RPC_CONNECTION *)param;
+ s = conn->Sock;
+ c = conn->Client;
+ AddRef(s->ref);
+
+ // Add to the RPC connection list
+ LockList(c->RpcConnectionList);
+ {
+ Add(c->RpcConnectionList, conn);
+ }
+ UnlockList(c->RpcConnectionList);
+
+ NoticeThreadInit(thread);
+
+ // Main process
+ CiRpcAccepted(c, s);
+
+ // Release from the connection list
+ LockList(c->RpcConnectionList);
+ {
+ Delete(c->RpcConnectionList, conn);
+ }
+ UnlockList(c->RpcConnectionList);
+
+ ReleaseSock(conn->Sock);
+ ReleaseThread(conn->Thread);
+ Free(conn);
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// RPC server thread
+void CiRpcServerThread(THREAD *thread, void *param)
+{
+ CLIENT *c;
+ SOCK *listener;
+ UINT i;
+ LIST *thread_list;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ c = (CLIENT *)param;
+
+ // RPC connection list
+ c->RpcConnectionList = NewList(NULL);
+
+ // Open the port
+ listener = NULL;
+ for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++)
+ {
+ listener = Listen(i);
+ if (listener != NULL)
+ {
+ break;
+ }
+ }
+
+ if (listener == NULL)
+ {
+ // Error
+ Alert(CEDAR_PRODUCT_STR " VPN Client RPC Port Open Failed.", CEDAR_CLIENT_STR);
+ return;
+ }
+
+ c->RpcListener = listener;
+ AddRef(listener->ref);
+
+ NoticeThreadInit(thread);
+
+ while (true)
+ {
+ // Wait for client connection
+ CLIENT_RPC_CONNECTION *conn;
+ SOCK *s = Accept(listener);
+ if (s == NULL)
+ {
+ // Stop
+ break;
+ }
+
+ // Create a client processing thread
+ conn = ZeroMalloc(sizeof(CLIENT_RPC_CONNECTION));
+ conn->Client = c;
+ conn->Sock = s;
+ AddRef(s->ref);
+
+ conn->Thread = NewThread(CiRpcAcceptThread, (void *)conn);
+ WaitThreadInit(conn->Thread);
+
+ ReleaseSock(s);
+ }
+
+ // Release the listener
+ ReleaseSock(listener);
+
+ thread_list = NewListFast(NULL);
+
+ // Set all the event notification
+ LockList(c->NotifyCancelList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
+ {
+ CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
+ Cancel(cancel);
+ }
+ }
+ UnlockList(c->NotifyCancelList);
+
+ // Disconnect all the connections of connected yet
+ LockList(c->RpcConnectionList);
+ {
+ for (i = 0;i < LIST_NUM(c->RpcConnectionList);i++)
+ {
+ CLIENT_RPC_CONNECTION *cc = LIST_DATA(c->RpcConnectionList, i);
+ AddRef(cc->Thread->ref);
+ Add(thread_list, cc->Thread);
+ Disconnect(cc->Sock);
+ }
+ }
+ UnlockList(c->RpcConnectionList);
+
+ for (i = 0;i < LIST_NUM(thread_list);i++)
+ {
+ THREAD *t = LIST_DATA(thread_list, i);
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+ }
+
+ ReleaseList(c->RpcConnectionList);
+ ReleaseList(thread_list);
+}
+
+// Start the Keep
+void CiInitKeep(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->Keep = StartKeep();
+
+ // Apply settings
+ if (c->Config.UseKeepConnect)
+ {
+ KEEP *k = c->Keep;
+ Lock(k->lock);
+ {
+ StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
+ k->ServerPort = c->Config.KeepConnectPort;
+ k->Interval = c->Config.KeepConnectInterval * 1000;
+ k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
+ k->Enable = true;
+ }
+ Unlock(k->lock);
+ }
+}
+
+// Stop the Keep
+void CiFreeKeep(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ StopKeep(c->Keep);
+ c->Keep = NULL;
+}
+
+// Start the RPC
+void CiStartRpcServer(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->RpcThread = NewThread(CiRpcServerThread, (void *)c);
+ WaitThreadInit(c->RpcThread);
+}
+
+// Stop the RPC
+void CiStopRpcServer(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Disconnect(c->RpcListener);
+ ReleaseSock(c->RpcListener);
+
+ WaitThread(c->RpcThread, INFINITE);
+ ReleaseThread(c->RpcThread);
+}
+
+// Wait for the next notification
+bool CcWaitNotify(NOTIFY_CLIENT *n)
+{
+ UCHAR c;
+ // Validate arguments
+ if (n == NULL)
+ {
+ return false;
+ }
+
+ // 1 character reception
+ if (RecvAll(n->Sock, &c, 1, false) == false)
+ {
+ // Disconnected
+ return false;
+ }
+
+ return true;
+}
+
+// Connect as a notification client
+NOTIFY_CLIENT *CcConnectNotify(REMOTE_CLIENT *rc)
+{
+ NOTIFY_CLIENT *n;
+ SOCK *s;
+ char tmp[MAX_SIZE];
+ bool rpc_mode = false;
+ UINT port;
+ // Validate arguments
+ if (rc == NULL || rc->Rpc == NULL || rc->Rpc->Sock == NULL)
+ {
+ return NULL;
+ }
+
+ // Connect
+ IPToStr(tmp, sizeof(tmp), &rc->Rpc->Sock->RemoteIP);
+ port = rc->Rpc->Sock->RemotePort;
+
+ s = Connect(tmp, port);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ rpc_mode = Endian32(rpc_mode);
+ if (SendAll(s, &rpc_mode, sizeof(rpc_mode), false) == false)
+ {
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ n = ZeroMalloc(sizeof(NOTIFY_CLIENT));
+ n->Sock = s;
+
+ return n;
+}
+
+// Stop the notification client
+void CcStopNotify(NOTIFY_CLIENT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ Disconnect(n->Sock);
+}
+
+// Delete the notification client
+void CcDisconnectNotify(NOTIFY_CLIENT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Disconnect
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+
+ // Memory release
+ Free(n);
+}
+
+// Disconnect the remote connection
+void CcDisconnectRpc(REMOTE_CLIENT *rc)
+{
+ // Validate arguments
+ if (rc == NULL)
+ {
+ return;
+ }
+
+ RpcFree(rc->Rpc);
+ Free(rc);
+}
+
+// Connect to the client to start the shortcut connection setting
+UINT CcShortcut(UCHAR *key)
+{
+ UINT ret;
+ // Validate arguments
+ if (key == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, false, 0);
+
+ return ret;
+}
+
+// Disconnect the connected shortcut connection
+UINT CcShortcutDisconnect(UCHAR *key)
+{
+ UINT ret;
+ // Validate arguments
+ if (key == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, true, 0);
+
+ return ret;
+}
+
+// Connect to the remote client
+REMOTE_CLIENT *CcConnectRpc(char *server_name, char *password, bool *bad_pass, bool *no_remote, UINT wait_retry)
+{
+ return CcConnectRpcEx(server_name, password, bad_pass, no_remote, NULL, NULL, false, wait_retry);
+}
+REMOTE_CLIENT *CcConnectRpcEx(char *server_name, char *password, bool *bad_pass, bool *no_remote, UCHAR *key, UINT *key_error_code, bool shortcut_disconnect, UINT wait_retry)
+{
+ SOCK *s;
+ UINT i;
+ UINT retcode;
+ UINT rpc_mode = CLIENT_RPC_MODE_MANAGEMENT;
+ RPC *rpc;
+ REMOTE_CLIENT *ret;
+ UCHAR hash_password[SHA1_SIZE];
+ UINT port_start;
+ UINT64 try_started = 0;
+ bool ok;
+ // Validate arguments
+ if (server_name == NULL)
+ {
+ return NULL;
+ }
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ if (key_error_code != NULL)
+ {
+ *key_error_code = ERR_NO_ERROR;
+ }
+
+ if (bad_pass != NULL)
+ {
+ *bad_pass = false;
+ }
+
+ if (no_remote != NULL)
+ {
+ *no_remote = false;
+ }
+
+ port_start = CLIENT_CONFIG_PORT - 1;
+
+RETRY:
+ port_start++;
+
+ if (port_start >= (CLIENT_CONFIG_PORT + 5))
+ {
+ return NULL;
+ }
+
+ ok = false;
+
+ while (true)
+ {
+ for (i = port_start;i < (CLIENT_CONFIG_PORT + 5);i++)
+ {
+ if (CheckTCPPort(server_name, i))
+ {
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ break;
+ }
+
+ if (wait_retry == 0)
+ {
+ break;
+ }
+
+ if (try_started == 0)
+ {
+ try_started = Tick64();
+ }
+
+ if ((try_started + (UINT64)wait_retry) <= Tick64())
+ {
+ break;
+ }
+ }
+
+ if (ok == false)
+ {
+ if (key_error_code)
+ {
+ *key_error_code = ERR_CONNECT_FAILED;
+ }
+ return NULL;
+ }
+
+ port_start = i;
+
+ s = Connect(server_name, i);
+ if (s == NULL)
+ {
+ if (key_error_code)
+ {
+ *key_error_code = ERR_CONNECT_FAILED;
+ }
+ goto RETRY;
+ }
+
+ Hash(hash_password, password, StrLen(password), true);
+
+ if (key != NULL)
+ {
+ if (shortcut_disconnect == false)
+ {
+ rpc_mode = CLIENT_RPC_MODE_SHORTCUT;
+ }
+ else
+ {
+ rpc_mode = CLIENT_RPC_MODE_SHORTCUT_DISCONNECT;
+ }
+ }
+
+ rpc_mode = Endian32(rpc_mode);
+ SendAdd(s, &rpc_mode, sizeof(UINT));
+
+ if (key != NULL)
+ {
+ SendAdd(s, key, SHA1_SIZE);
+ }
+ else
+ {
+ SendAdd(s, hash_password, SHA1_SIZE);
+ }
+
+ if (SendNow(s, false) == false)
+ {
+ ReleaseSock(s);
+ goto RETRY;
+ }
+
+ if (RecvAll(s, &retcode, sizeof(UINT), false) == false)
+ {
+ ReleaseSock(s);
+ goto RETRY;
+ }
+
+ retcode = Endian32(retcode);
+
+ if (retcode >= 1024)
+ {
+ goto RETRY;
+ }
+
+ if (key != NULL)
+ {
+ if (key_error_code)
+ {
+ *key_error_code = retcode;
+ }
+ SendAll(s, &retcode, sizeof(UINT), false);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ switch (retcode)
+ {
+ case 1:
+ if (bad_pass != NULL)
+ {
+ *bad_pass = true;
+ }
+ break;
+ case 2:
+ if (no_remote != NULL)
+ {
+ *no_remote = true;
+ }
+ break;
+ }
+
+ if (retcode != 0)
+ {
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ rpc = StartRpcClient(s, NULL);
+
+ ReleaseSock(s);
+
+ ret = ZeroMalloc(sizeof(REMOTE_CLIENT));
+ ret->Rpc = rpc;
+ rpc->Param = ret;
+
+ if (ret != NULL)
+ {
+ RPC_CLIENT_VERSION t;
+ Zero(&t, sizeof(t));
+ CcGetClientVersion(ret, &t);
+ ret->OsType = t.OsType;
+ ret->Unix = OS_IS_UNIX(ret->OsType);
+ ret->Win9x = OS_IS_WINDOWS_9X(ret->OsType);
+ ret->IsVgcSupported = t.IsVgcSupported;
+ ret->ShowVgcLink = t.ShowVgcLink;
+ StrCpy(ret->ClientId, sizeof(ret->ClientId), t.ClientId);
+ }
+
+ return ret;
+}
+
+// Get a RPC_CLIENT_GET_CONNECTION_STATUS from the session
+void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s)
+{
+ // Validate arguments
+ if (st == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->lock);
+ {
+ // Operation flag
+ st->Active = true;
+
+ // Session status
+ st->SessionStatus = s->ClientStatus;
+
+ // Account name
+ UniStrCpy(st->AccountName, sizeof(st->AccountName), s->ClientOption->AccountName);
+
+ if (s->ClientStatus == CLIENT_STATUS_ESTABLISHED && s->Connection != NULL)
+ {
+ Lock(s->Connection->lock);
+ {
+ // Connected flag
+ st->Connected = true;
+ // Product name
+ StrCpy(st->ServerProductName, sizeof(st->ServerProductName), s->Connection->ServerStr);
+ // Version
+ st->ServerProductVer = s->Connection->ServerVer;
+ // Build Number
+ st->ServerProductBuild = s->Connection->ServerBuild;
+ // Server certificate
+ st->ServerX = CloneX(s->Connection->ServerX);
+ // Client certificate
+ st->ClientX = CloneX(s->Connection->ClientX);
+ // Connection completion time of this connection
+ st->CurrentConnectionEstablishTime = TickToTime(s->CurrentConnectionEstablishTime);
+ // Maximum number of the TCP connections
+ st->MaxTcpConnections = s->MaxConnection;
+ // Half-connection
+ st->HalfConnection = s->HalfConnection;
+ // VLAN
+ st->VLanId = s->VLanId;
+ // VoIP / QoS
+ st->QoS = s->QoS;
+ if (s->Connection->Protocol == CONNECTION_TCP)
+ {
+ UINT i;
+ // Number of current TCP connections
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ st->NumTcpConnections = LIST_NUM(s->Connection->Tcp->TcpSockList);
+ if (st->HalfConnection)
+ {
+ for (i = 0;i < st->NumTcpConnections;i++)
+ {
+ TCPSOCK *ts = LIST_DATA(s->Connection->Tcp->TcpSockList, i);
+ if (ts->Direction & TCP_SERVER_TO_CLIENT)
+ {
+ st->NumTcpConnectionsDownload++;
+ }
+ else
+ {
+ st->NumTcpConnectionsUpload++;
+ }
+ }
+ }
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+ }
+ // Use of encryption
+ st->UseEncrypt = s->UseEncrypt;
+ if (st->UseEncrypt)
+ {
+ StrCpy(st->CipherName, sizeof(st->CipherName), s->Connection->CipherName);
+ }
+ // Use of compression
+ st->UseCompress = s->UseCompress;
+ // R-UDP
+ st->IsRUDPSession = s->IsRUDPSession;
+ // Physical communication protocol
+ StrCpy(st->UnderlayProtocol, sizeof(st->UnderlayProtocol), s->UnderlayProtocol);
+ // UDP acceleration function
+ st->IsUdpAccelerationEnabled = s->UseUdpAcceleration;
+ st->IsUsingUdpAcceleration = s->IsUsingUdpAcceleration;
+ // Session key
+ Copy(st->SessionKey, s->SessionKey, SHA1_SIZE);
+ // Policy
+ Copy(&st->Policy, s->Policy, sizeof(POLICY));
+ // Data size
+ if (s->ServerMode == false)
+ {
+ st->TotalSendSize = s->TotalSendSize;
+ st->TotalRecvSize = s->TotalRecvSize;
+ st->TotalRecvSizeReal = s->TotalRecvSizeReal;
+ st->TotalSendSizeReal = s->TotalSendSizeReal;
+ }
+ else
+ {
+ st->TotalSendSize = s->TotalRecvSize;
+ st->TotalRecvSize = s->TotalSendSize;
+ st->TotalRecvSizeReal = s->TotalSendSizeReal;
+ st->TotalSendSizeReal = s->TotalRecvSizeReal;
+ }
+ // Session name
+ StrCpy(st->SessionName, sizeof(st->SessionName), s->Name);
+ // Connection name
+ StrCpy(st->ConnectionName, sizeof(st->ConnectionName), s->Connection->Name);
+ // Server name
+ StrCpy(st->ServerName, sizeof(st->ServerName), s->Connection->ServerName);
+ // Port number
+ st->ServerPort = s->Connection->ServerPort;
+ // Traffic data
+ Lock(s->TrafficLock);
+ {
+ Copy(&st->Traffic, s->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(s->TrafficLock);
+
+ st->IsBridgeMode = s->IsBridgeMode;
+ st->IsMonitorMode = s->IsMonitorMode;
+ }
+ Unlock(s->Connection->lock);
+ }
+ // Connection start time
+ st->StartTime = TickToTime(s->CreatedTime);
+ // Connection completion time of the first connection
+ st->FirstConnectionEstablisiedTime = TickToTime(s->FirstConnectionEstablisiedTime);
+ // Number of connections have been established so far
+ st->NumConnectionsEatablished = s->NumConnectionsEatablished;
+ }
+ Unlock(s->lock);
+}
+
+// Get the connection status
+bool CtGetAccountStatus(CLIENT *c, RPC_CLIENT_GET_CONNECTION_STATUS *st)
+{
+ // Validate arguments
+ if (c == NULL || st == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+
+ // Search for account
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), st->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account is not found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ Zero(st, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
+ if (r->ClientSession != NULL)
+ {
+ SESSION *s = r->ClientSession;
+ CiGetSessionStatus(st, s);
+ }
+ }
+ Unlock(r->lock);
+ }
+ UnlockList(c->AccountList);
+
+ return true;
+}
+
+// Release the connection status
+void CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st)
+{
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ if (st->ServerX != NULL)
+ {
+ FreeX(st->ServerX);
+ }
+
+ if (st->ClientX != NULL)
+ {
+ FreeX(st->ClientX);
+ }
+}
+
+// Verification procedure of the server certificate
+bool CiCheckCertProc(SESSION *s, CONNECTION *c, X *server_x, bool *expired)
+{
+#ifdef OS_WIN32
+ ACCOUNT *a;
+ X *old_x = NULL;
+ UI_CHECKCERT dlg;
+ // Validate arguments
+ if (s == NULL || c == NULL || server_x == NULL)
+ {
+ return false;
+ }
+
+ if (expired != NULL)
+ {
+ *expired = false;
+ }
+
+ Zero(&dlg, sizeof(dlg));
+
+ a = s->Account;
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ Lock(a->lock);
+ {
+ if (a->CheckServerCert == false)
+ {
+ // Not to validate the server certificate
+ Unlock(a->lock);
+ return true;
+ }
+
+ if (a->ServerCert != NULL)
+ {
+ old_x = CloneX(a->ServerCert);
+ }
+ }
+ Unlock(a->lock);
+
+ if (CheckXDateNow(server_x) == false)
+ {
+ // Expired
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+
+ if (expired != NULL)
+ {
+ *expired = true;
+ }
+
+ return false;
+ }
+
+ if (old_x != NULL)
+ {
+ if (CompareX(old_x, server_x))
+ {
+ // Matched exactly to the certificate that is already registered
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+ return true;
+ }
+ else
+ {
+ dlg.DiffWarning = true;
+ }
+ }
+
+ // Because this certificate can not be trusted, confirm to be trusted by showing a dialog box
+ UniStrCpy(dlg.AccountName, sizeof(dlg.AccountName), a->ClientOption->AccountName);
+ StrCpy(dlg.ServerName, sizeof(dlg.ServerName), a->ClientOption->Hostname);
+ dlg.x = server_x;
+ dlg.old_x = old_x;
+
+ dlg.Session = s;
+ AddRef(s->ref);
+
+ CncCheckCert(s, &dlg);
+
+ ReleaseSession(s);
+
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+
+ if (dlg.Ok && dlg.SaveServerCert)
+ {
+ // Save the server certificate and trust it from the next time
+ Lock(a->lock);
+ {
+ if (a->ServerCert != NULL)
+ {
+ FreeX(a->ServerCert);
+ }
+
+ a->ServerCert = CloneX(server_x);
+ }
+ Unlock(a->lock);
+ CiSaveConfigurationFile(s->Cedar->Client);
+ }
+
+ return dlg.Ok;
+#else // OS_WIN32
+ ACCOUNT *a;
+ X *old_x = NULL;
+ // Validate arguments
+ if (s == NULL || c == NULL || server_x == NULL)
+ {
+ return false;
+ }
+
+ if (expired != NULL)
+ {
+ *expired = false;
+ }
+
+ a = s->Account;
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ Lock(a->lock);
+ {
+ if (a->CheckServerCert == false)
+ {
+ // Not to validate the server certificate
+ Unlock(a->lock);
+ return true;
+ }
+
+ if (a->ServerCert != NULL)
+ {
+ old_x = CloneX(a->ServerCert);
+ }
+ }
+ Unlock(a->lock);
+
+ if (CheckXDateNow(server_x) == false)
+ {
+ // Expired
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+
+ if (expired != NULL)
+ {
+ *expired = true;
+ }
+
+ return false;
+ }
+
+ if (old_x != NULL)
+ {
+ if (CompareX(old_x, server_x))
+ {
+ // Exactly matched to the certificate that is already registered
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+ return true;
+ }
+ else
+ {
+ // Mismatch
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+ return false;
+ }
+ }
+
+ if (old_x != NULL)
+ {
+ FreeX(old_x);
+ }
+
+ return false;
+#endif // OS_WIN32
+}
+
+// Signature procedure with a secure device
+bool CiSecureSignProc(SESSION *s, CONNECTION *c, SECURE_SIGN *sign)
+{
+ // The UI is available in Win32
+ return CncSecureSignDlg(sign);
+}
+
+#ifdef OS_WIN32
+// Signing procedure (for Win32)
+bool Win32CiSecureSign(SECURE_SIGN *sign)
+{
+ bool ret = false;
+ BUF *random;
+ // Validate arguments
+ if (sign == NULL)
+ {
+ return false;
+ }
+
+ random = NewBuf();
+ WriteBuf(random, sign->Random, SHA1_SIZE);
+
+ // Batch processing
+ {
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_READ_CERT, sign->SecurePublicCertName, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_SIGN_WITH_KEY, sign->SecurePrivateKeyName, true, random, NULL, NULL, NULL, NULL, NULL}
+ };
+
+ if (SecureDeviceWindow(NULL, batch, sizeof(batch) / sizeof(batch[0]),
+ sign->UseSecureDeviceId, sign->BitmapId) == false)
+ {
+ // Failure
+ if (batch[0].OutputX != 0)
+ {
+ FreeX(batch[0].OutputX);
+ }
+ ret = false;
+ }
+ else
+ {
+ // Success
+ ret = true;
+ sign->ClientCert = batch[0].OutputX;
+ Copy(sign->Signature, batch[1].OutputSign, 128);
+ }
+ }
+
+ FreeBuf(random);
+
+ return ret;
+}
+#endif // OS_WIN32
+
+// Disconnect
+bool CtDisconnect(CLIENT *c, RPC_CLIENT_CONNECT *connect, bool inner)
+{
+ bool ret = false;
+ ACCOUNT t, *r;
+ SESSION *s = NULL;
+ // Validate arguments
+ if (c == NULL || connect == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->AccountList);
+ {
+ // Search for account
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account isn't found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ if (r->ClientSession == NULL)
+ {
+ // Not connected
+ CiSetError(c, ERR_ACCOUNT_INACTIVE);
+ }
+ else
+ {
+ s = r->ClientSession;
+ AddRef(s->ref);
+ // Disconnect complete
+ r->ClientSession = NULL;
+ ret = true;
+ }
+ }
+ Unlock(r->lock);
+ }
+ UnlockList(c->AccountList);
+
+ if (s != NULL)
+ {
+ // Disconnect the connection (Wait until the disconnection is complete)
+ CLog(c, "LC_DISCONNECT", connect->AccountName);
+ StopSession(s);
+ ReleaseSession(s);
+ }
+
+
+ if (ret != false)
+ {
+ CiNotify(c);
+ }
+
+ return ret;
+}
+
+// Connect
+bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)
+{
+ bool ret = false;
+ RPC_CLIENT_ENUM_VLAN t;
+ // Validate arguments
+ if (c == NULL || connect == NULL)
+ {
+ return false;
+ }
+
+ Lock(c->lockForConnect);
+ {
+ Zero(&t, sizeof(t));
+ if (CtEnumVLan(c, &t))
+ {
+ if (t.NumItem == 0)
+ {
+ // There are no virtual LAN cards in the system
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) || OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ // Only in Linux system or Windows NT system,
+ // create a new virtual LAN card which named as "VPN" automatically
+ RPC_CLIENT_CREATE_VLAN t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), "VPN");
+ CtCreateVLan(c, &t);
+ }
+ }
+
+ CiFreeClientEnumVLan(&t);
+ }
+ }
+ Unlock(c->lockForConnect);
+
+ CiNormalizeAccountVLan(c);
+
+ // Ensure successfully VPN communication by changing the irrational WCM settings in the case of Windows 8 or later
+ CiDisableWcmNetworkMinimize(c);
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+ bool unix_disabled = false;
+
+ // Search for account
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account isn't found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+#ifndef OS_WIN32
+ // Search for the virtual LAN card
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN *v, t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), r->ClientOption->DeviceName);
+
+ v = Search(c->UnixVLanList, &t);
+ if (v == NULL)
+ {
+ UnlockList(c->UnixVLanList);
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ unix_disabled = v->Enabled ? false : true;
+ }
+ UnlockList(c->UnixVLanList);
+#endif // OS_WIN32
+
+ Lock(r->lock);
+ {
+ bool already_used = false;
+ UINT i;
+
+ if (r->ClientSession != NULL)
+ {
+ // Already in connecting
+ CiSetError(c, ERR_ACCOUNT_ACTIVE);
+ }
+ else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE &&
+ client->UseSecureDeviceId == 0)
+ {
+ // Secure device is not specified
+ CiSetError(c, ERR_NO_SECURE_DEVICE_SPECIFIED);
+ }
+#ifdef OS_WIN32
+ else if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, r->ClientOption->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, r->ClientOption->DeviceName) == false)
+ {
+ // Virtual LAN card can not be found
+ CiSetError(c, ERR_VLAN_FOR_ACCOUNT_NOT_FOUND);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ }
+ else if (MsIsVLanEnabled(r->ClientOption->DeviceName) == false)
+ {
+ // The virtual LAN card is disabled
+ CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ }
+#else // OS_WIN32
+ else if (unix_disabled)
+ {
+ // The virtual LAN card is disabled
+ CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ }
+#endif // OS_WIN32
+ else
+ {
+ // Check whether the virtual LAN card is being used by a different account already
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ if (a != r)
+ {
+ if (StrCmpi(a->ClientOption->DeviceName,
+ r->ClientOption->DeviceName) == 0)
+ {
+ if (a->ClientSession != NULL)
+ {
+ already_used = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (already_used)
+ {
+ CiSetError(c, ERR_VLAN_FOR_ACCOUNT_USED);
+ }
+ else
+ {
+ // Start the connection
+ PACKET_ADAPTER *pa = VLanGetPacketAdapter();
+
+ if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
+ {
+ // Register a procedure for secure device authentication
+ r->ClientAuth->SecureSignProc = CiSecureSignProc;
+ }
+ else
+ {
+ r->ClientAuth->SecureSignProc = NULL;
+ }
+
+ if (r->CheckServerCert)
+ {
+ // Register a procedure to validate the server certificate
+ r->ClientAuth->CheckCertProc = CiCheckCertProc;
+ }
+ else
+ {
+ r->ClientAuth->CheckCertProc = NULL;
+ }
+
+ r->StatusPrinter = CiClientStatusPrinter;
+ r->LastConnectDateTime = SystemTime64();
+
+ CLog(c, "LC_CONNECT", connect->AccountName);
+
+ r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r);
+ Notify(r->ClientSession, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+ ret = true;
+ }
+ }
+ }
+ Unlock(r->lock);
+
+ }
+ UnlockList(c->AccountList);
+
+ CiSaveConfigurationFile(c);
+
+ return ret;
+}
+
+// Get the account information
+bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a)
+{
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+
+ // Search for account
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account can not be found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ // Copy the client option
+ if (a->ClientOption != NULL)
+ {
+ Free(a->ClientOption);
+ }
+ a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(a->ClientOption, r->ClientOption, sizeof(CLIENT_OPTION));
+
+ // Copy the authentication data
+ if (a->ClientAuth != NULL)
+ {
+ CiFreeClientAuth(a->ClientAuth);
+ }
+ a->ClientAuth = CopyClientAuth(r->ClientAuth);
+
+ a->StartupAccount = r->StartupAccount;
+
+ a->CheckServerCert = r->CheckServerCert;
+ a->ServerCert = NULL;
+ if (r->ServerCert != NULL)
+ {
+ a->ServerCert = CloneX(r->ServerCert);
+ }
+
+ // Shortcut Key
+ Copy(a->ShortcutKey, r->ShortcutKey, SHA1_SIZE);
+
+ a->CreateDateTime = r->CreateDateTime;
+ a->LastConnectDateTime = r->LastConnectDateTime;
+ a->UpdateDateTime = r->UpdateDateTime;
+ }
+ Unlock(r->lock);
+
+ }
+ UnlockList(c->AccountList);
+
+ return true;
+}
+
+// Change the account name
+bool CtRenameAccount(CLIENT *c, RPC_RENAME_ACCOUNT *rename, bool inner)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || rename == NULL)
+ {
+ return false;
+ }
+
+
+ ret = false;
+
+ if (UniStrCmp(rename->NewName, rename->OldName) == 0)
+ {
+ // The name has not been changed
+ return true;
+ }
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r, *r2;
+
+ if (UniStrLen(rename->NewName) == 0)
+ {
+ // Name is invalid
+ CiSetError(c, ERR_INVALID_VALUE);
+ UnlockList(c->AccountList);
+ return false;
+ }
+
+ // Search for old account name
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->OldName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account can not be found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ // Search for a new account name
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->NewName);
+
+ r2 = Search(c->AccountList, &t);
+ if (r2 != NULL)
+ {
+ // Account with the specified name already exists
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ // Check the operating state of the account
+ if (r->ClientSession != NULL)
+ {
+ // The Account is working
+ Unlock(r->lock);
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_ACCOUNT_ACTIVE);
+
+ return false;
+ }
+
+ // Update the account name
+ UniStrCpy(r->ClientOption->AccountName, sizeof(r->ClientOption->AccountName),
+ rename->NewName);
+
+ CLog(c, "LC_RENAME_ACCOUNT", rename->OldName, rename->NewName);
+
+ ret = true;
+ }
+ Unlock(r->lock);
+
+ Sort(c->AccountList);
+
+ }
+ UnlockList(c->AccountList);
+
+ CiSaveConfigurationFile(c);
+
+ CiNotify(c);
+
+ return ret;
+}
+
+// Set the client configuration
+bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
+{
+ KEEP *k;
+ // Validate arguments
+ if (c == NULL || o == NULL)
+ {
+ return false;
+ }
+
+ if (o->UseKeepConnect)
+ {
+ if (IsEmptyStr(o->KeepConnectHost) ||
+ o->KeepConnectPort == 0 ||
+ o->KeepConnectPort >= 65536)
+ {
+ CiSetError(c, ERR_INVALID_PARAMETER);
+ return false;
+ }
+ }
+
+ Lock(c->lock);
+ {
+ Copy(&c->Config, o, sizeof(CLIENT_CONFIG));
+ }
+ Unlock(c->lock);
+
+ // Save the settings
+ CiSaveConfigurationFile(c);
+
+ // Apply the Keep Connect
+ k = c->Keep;
+ Lock(k->lock);
+ {
+ if (o->UseKeepConnect)
+ {
+ StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
+ k->ServerPort = c->Config.KeepConnectPort;
+ k->Interval = c->Config.KeepConnectInterval * 1000;
+ k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
+ k->Enable = true;
+ }
+ else
+ {
+ k->Enable = false;
+ }
+ }
+ Unlock(k->lock);
+
+ return true;
+}
+
+// Get the network client configuration
+bool CtGetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
+{
+ // Validate arguments
+ if (c == NULL || o == NULL)
+ {
+ return false;
+ }
+
+ Lock(c->lock);
+ {
+ Copy(o, &c->Config, sizeof(CLIENT_CONFIG));
+ }
+ Unlock(c->lock);
+
+ return true;
+}
+
+// Unset the startup attribute of the account
+bool CtRemoveStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+ // Search for an Account
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account can not be found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ // Unset the startup account
+ ret = true;
+ r->StartupAccount = false;
+ }
+ Unlock(r->lock);
+ }
+ UnlockList(c->AccountList);
+
+ if (ret)
+ {
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ }
+
+ return ret;
+}
+
+// Set the account as a start-up account
+bool CtSetStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+
+ ret = false;
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+ // Search for an account
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account can not be found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ // Set to a start-up account
+ ret = true;
+ r->StartupAccount = true;
+ }
+ Unlock(r->lock);
+ }
+ UnlockList(c->AccountList);
+
+ if (ret)
+ {
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ }
+
+ return ret;
+}
+
+// Delete the account
+bool CtDeleteAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ if (c->Halt)
+ {
+ // Don't allow the removal of the account in the process of stopping
+ CiSetError(c, ERR_INTERNAL_ERROR);
+ return false;
+ }
+
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *r;
+ // Search for an Account
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
+
+ r = Search(c->AccountList, &t);
+ if (r == NULL)
+ {
+ // Specified account can not be found
+ UnlockList(c->AccountList);
+
+ Free(t.ClientOption);
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ Lock(r->lock);
+ {
+ // Check the operating state of the account
+ if (r->ClientSession != NULL)
+ {
+ // The account is active
+ Unlock(r->lock);
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_ACCOUNT_ACTIVE);
+
+ return false;
+ }
+
+ // Remove this account from the list
+ Delete(c->AccountList, r);
+ }
+ Unlock(r->lock);
+
+ // Free the memory of this account
+ CiFreeAccount(r);
+
+ CLog(c, "LC_DELETE_ACCOUNT", a->AccountName);
+ ret = true;
+
+ }
+ UnlockList(c->AccountList);
+
+ if (ret)
+ {
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ }
+
+ return ret;
+}
+
+// Enumeration of accounts
+bool CtEnumAccount(CLIENT *c, RPC_CLIENT_ENUM_ACCOUNT *e)
+{
+ // Validate arguments
+ if (c == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->AccountList);
+ {
+ UINT i;
+ // Number of accounts
+ e->NumItem = LIST_NUM(c->AccountList);
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
+ e->Items[i] = item;
+
+ // Account name
+ UniStrCpy(item->AccountName, sizeof(item->AccountName), a->ClientOption->AccountName);
+
+ // User name
+ StrCpy(item->UserName, sizeof(item->UserName), a->ClientAuth->Username);
+
+ // Server name
+ StrCpy(item->ServerName, sizeof(item->ServerName), a->ClientOption->Hostname);
+
+ // Proxy type
+ item->ProxyType = a->ClientOption->ProxyType;
+
+ // Device name
+ StrCpy(item->DeviceName, sizeof(item->DeviceName), a->ClientOption->DeviceName);
+
+ // Proxy information
+ if (item->ProxyType != PROXY_DIRECT)
+ {
+ StrCpy(item->ProxyName, sizeof(item->ProxyName), a->ClientOption->ProxyName);
+ }
+
+ // Startup
+ item->StartupAccount = a->StartupAccount;
+
+ // Active flag
+ item->Active = (a->ClientSession == NULL ? false : true);
+
+ // Connection flag
+ item->Connected = (item->Active == false) ? false : a->ClientSession->ConnectSucceed;
+
+ // Port number
+ item->Port = a->ClientOption->Port;
+
+ // Virtual HUB name
+ StrCpy(item->HubName, sizeof(item->HubName), a->ClientOption->HubName);
+
+ item->CreateDateTime = a->CreateDateTime;
+ item->LastConnectDateTime = a->LastConnectDateTime;
+ item->UpdateDateTime = a->UpdateDateTime;
+ }
+ }
+ UnlockList(c->AccountList);
+
+ return true;
+}
+
+// Configure the account
+bool CtSetAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
+{
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+
+ // Check whether an account already exists
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *ret;
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
+ a->ClientOption->AccountName);
+
+ ret = Search(c->AccountList, &t);
+ if (ret == NULL)
+ {
+ // Not exist
+ UnlockList(c->AccountList);
+ Free(t.ClientOption);
+
+ CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
+
+ return false;
+ }
+ Free(t.ClientOption);
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (a->ClientAuth->ClientX == NULL ||
+ a->ClientAuth->ClientX->is_compatible_bit == false ||
+ a->ClientAuth->ClientK == NULL)
+ {
+ // Client certificate is invalid
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_NOT_RSA_1024);
+ return false;
+ }
+ }
+
+ if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
+ {
+ // Server certificate is invalid
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_NOT_RSA_1024);
+ return false;
+ }
+
+ Lock(ret->lock);
+ {
+
+#if 0
+ // Rewriting of the configuration is done even account running in the current version
+ // (New setting isn't applied until connecting next time)
+ if (ret->ClientSession != NULL)
+ {
+ // The account is operating
+ Unlock(ret->lock);
+ UnlockList(c->AccountList);
+
+ CiSetError(c, ERR_ACCOUNT_ACTIVE);
+
+ return false;
+ }
+#endif
+
+ // Delete the client authentication data
+ CiFreeClientAuth(ret->ClientAuth);
+
+ // Copy the client authentication data
+ ret->ClientAuth = CopyClientAuth(a->ClientAuth);
+
+ // Delete the client option
+ Free(ret->ClientOption);
+
+ // Copy the client option
+ ret->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(ret->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+
+ ret->StartupAccount = a->StartupAccount;
+
+ ret->CheckServerCert = a->CheckServerCert;
+
+ if (a->ServerCert != NULL)
+ {
+ if (ret->ServerCert != NULL)
+ {
+ FreeX(ret->ServerCert);
+ }
+ ret->ServerCert = CloneX(a->ServerCert);
+ }
+ else
+ {
+ if (ret->ServerCert != NULL)
+ {
+ FreeX(ret->ServerCert);
+ }
+ ret->ServerCert = false;
+ }
+
+ ret->UpdateDateTime = SystemTime64();
+ }
+ Unlock(ret->lock);
+ }
+ UnlockList(c->AccountList);
+
+ CiSaveConfigurationFile(c);
+
+ CiNotify(c);
+
+ return true;
+}
+
+// Create an account
+bool CtCreateAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
+{
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+
+ // Check whether an account already exists
+ LockList(c->AccountList);
+ {
+ ACCOUNT t, *ret, *new_account;
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
+ a->ClientOption->AccountName);
+
+ ret = Search(c->AccountList, &t);
+ if (ret != NULL)
+ {
+ // Already exist
+ UnlockList(c->AccountList);
+ Free(t.ClientOption);
+
+ CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
+
+ return false;
+ }
+
+ Free(t.ClientOption);
+
+ if (UniStrLen(a->ClientOption->AccountName) == 0)
+ {
+ // The name is invalid
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_INVALID_VALUE);
+ return false;
+ }
+
+ if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (a->ClientAuth->ClientX == NULL ||
+ a->ClientAuth->ClientX->is_compatible_bit == false ||
+ a->ClientAuth->ClientK == NULL)
+ {
+ // The client certificate is invalid
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_NOT_RSA_1024);
+ return false;
+ }
+ }
+
+ if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
+ {
+ // The server certificate is invalid
+ UnlockList(c->AccountList);
+ CiSetError(c, ERR_NOT_RSA_1024);
+ return false;
+ }
+
+ // Add a new account
+ new_account = ZeroMalloc(sizeof(ACCOUNT));
+ new_account->lock = NewLock();
+
+ // Copy the client authentication data
+ new_account->ClientAuth = CopyClientAuth(a->ClientAuth);
+
+ // Copy the client option
+ new_account->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(new_account->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
+
+ new_account->StartupAccount = a->StartupAccount;
+
+ new_account->CheckServerCert = a->CheckServerCert;
+ if (a->ServerCert != NULL)
+ {
+ new_account->ServerCert = CloneX(a->ServerCert);
+ }
+
+ // Shortcut Key
+ if (IsZero(a->ShortcutKey, SHA1_SIZE))
+ {
+ Rand(new_account->ShortcutKey, SHA1_SIZE);
+ }
+ else
+ {
+ Copy(new_account->ShortcutKey, a->ShortcutKey, SHA1_SIZE);
+ }
+
+ new_account->CreateDateTime = new_account->UpdateDateTime = SystemTime64();
+
+ // Insert into the list
+ Insert(c->AccountList, new_account);
+
+ CLog(c, "LC_NEW_ACCOUNT", a->ClientOption->AccountName);
+ }
+ UnlockList(c->AccountList);
+
+ CiNormalizeAccountVLan(c);
+
+ CiSaveConfigurationFile(c);
+
+ CiNotify(c);
+
+ return true;
+}
+
+// Release the account acquisition structure
+void CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ // Release the account information
+ if (a->ServerCert != NULL)
+ {
+ FreeX(a->ServerCert);
+ }
+ CiFreeClientAuth(a->ClientAuth);
+ Free(a->ClientOption);
+}
+
+// Release the account creation structure
+void CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ // Release the account information
+ if (a->ServerCert != NULL)
+ {
+ FreeX(a->ServerCert);
+ }
+ CiFreeClientAuth(a->ClientAuth);
+ Free(a->ClientOption);
+}
+
+// Stop the virtual LAN card
+bool CtDisableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
+{
+ UINT i;
+ bool used;
+ // Validate arguments
+ if (c == NULL || vlan == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // Can not be added or removed the virtual LAN card in MacOS X
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Check whether the virtual LAN card with the specified name is not
+ // being used by one or more accounts
+ used = false;
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
+ {
+ Lock(a->lock);
+ {
+ if (a->ClientSession != NULL)
+ {
+ used = true;
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ }
+ UnlockList(c->AccountList);
+
+ // Search for the virtual LAN card
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN *v, t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
+
+ v = Search(c->UnixVLanList, &t);
+ if (v == NULL)
+ {
+ UnlockList(c->UnixVLanList);
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Stop
+ v->Enabled = false;
+ }
+ UnlockList(c->UnixVLanList);
+
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#else // OS_WIN32
+
+ // Check whether the virtual LAN card with the specified name is not
+ // being used by one or more accounts
+ used = false;
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
+ {
+ Lock(a->lock);
+ {
+ if (a->ClientSession != NULL)
+ {
+ used = true;
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ }
+ UnlockList(c->AccountList);
+
+#if 0
+ if (used)
+ {
+ // In using
+ CiSetError(c, ERR_VLAN_IS_USED);
+ return false;
+ }
+#endif
+
+
+ // Check whether the virtual LAN card are present
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+
+
+ if (MsIs64BitWindows() && Is32() && MsIsAdmin())
+ {
+ // Execute the driver_installer to process since this Windows is 64 bit
+ // but this code is 32 bit
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "disablevlan %s", vlan->DeviceName);
+
+ if (MsExecDriverInstaller(tmp) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+ else
+ {
+ // Stop the virtual LAN card
+ if (MsDisableVLan(vlan->DeviceName) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#endif // OS_WIN32
+
+}
+
+// Start the virtual LAN card
+bool CtEnableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
+{
+ // Validate arguments
+ if (c == NULL || vlan == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // Can not be added or removed the virtual LAN card in MacOS X
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Search the virtual LAN card
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN *v, t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
+
+ v = Search(c->UnixVLanList, &t);
+ if (v == NULL)
+ {
+ UnlockList(c->UnixVLanList);
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Enable
+ v->Enabled = true;
+ }
+ UnlockList(c->UnixVLanList);
+
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#else // OS_WIN32
+
+ // Check whether the virtual LAN card are present
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+
+ if (MsIs64BitWindows() && Is32() && MsIsAdmin())
+ {
+ // Execute the driver_installer to process since this Windows is 64 bit
+ // but this code is 32 bit
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "enablevlan %s", vlan->DeviceName);
+
+ if (MsExecDriverInstaller(tmp) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+ else
+ {
+ // Start the virtual LAN card
+ if (MsEnableVLan(vlan->DeviceName) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#endif // OS_WIN32
+
+}
+
+// Delete the virtual LAN card
+bool CtDeleteVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *d)
+{
+ UINT i;
+ bool used;
+ // Validate arguments
+ if (c == NULL || d == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // Can not be added or removed the virtual LAN card in MacOS X
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Check whether the virtual LAN card with the specified name is not
+ // being used by one or more accounts
+ used = false;
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
+ {
+ used = true;
+ }
+ }
+ }
+ UnlockList(c->AccountList);
+
+#if 0
+ if (used)
+ {
+ // In using
+ CiSetError(c, ERR_VLAN_IS_USED);
+ return false;
+ }
+#endif
+
+ // Search for the virtual LAN card
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN *v, t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), d->DeviceName);
+
+ v = Search(c->UnixVLanList, &t);
+ if (v == NULL)
+ {
+ UnlockList(c->UnixVLanList);
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Remove
+ if (Delete(c->UnixVLanList, v))
+ {
+ Free(v);
+ }
+
+ CLog(c, "LC_DELETE_VLAN", d->DeviceName);
+
+ UnixVLanDelete(d->DeviceName);
+ }
+ UnlockList(c->UnixVLanList);
+
+ CiNormalizeAccountVLan(c);
+
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#else // OS_WIN32
+
+ if (MsIsNt() == false)
+ {
+ // Not available in Win9x
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Check whether the virtual LAN card are present
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, d->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, d->DeviceName) == false)
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Check whether the virtual LAN card with the specified name is not
+ // being used by one or more accounts
+ used = false;
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
+ {
+ used = true;
+ }
+ }
+ }
+ UnlockList(c->AccountList);
+
+#if 0
+ if (used)
+ {
+ // In using
+ CiSetError(c, ERR_VLAN_IS_USED);
+ return false;
+ }
+#endif
+
+ if (MsIs64BitWindows() && Is32() && MsIsAdmin())
+ {
+ // Execute the driver_installer to process since this Windows is 64 bit
+ // but this code is 32 bit
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "uninstvlan %s", d->DeviceName);
+
+ if (MsExecDriverInstaller(tmp) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ return false;
+ }
+ }
+ else
+ {
+ // Delete the virtual LAN card directly
+ if (MsUninstallVLan(d->DeviceName) == false)
+ {
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+
+ CLog(c, "LC_DELETE_VLAN", d->DeviceName);
+
+ CiNormalizeAccountVLan(c);
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#endif // OS_WIN32
+
+}
+
+// Get the name of the first VLAN
+char *CiGetFirstVLan(CLIENT *c)
+{
+ char *ret = NULL;
+ RPC_CLIENT_ENUM_VLAN t;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CtEnumVLan(c, &t) == false)
+ {
+ return NULL;
+ }
+
+ if (t.NumItem >= 1)
+ {
+ UINT i;
+ char *tmp = t.Items[0]->DeviceName;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ if (t.Items[i]->Enabled)
+ {
+ tmp = t.Items[i]->DeviceName;
+ }
+ }
+
+ ret = CopyStr(tmp);
+ }
+
+ CiFreeClientEnumVLan(&t);
+
+ return ret;
+}
+
+// Enumerate virtual LAN cards
+bool CtEnumVLan(CLIENT *c, RPC_CLIENT_ENUM_VLAN *e)
+{
+ UINT i;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (c == NULL || e == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ LockList(c->UnixVLanList);
+ {
+ e->NumItem = LIST_NUM(c->UnixVLanList);
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_VLAN_ITEM *item;
+ UNIX_VLAN *v;
+
+ v = LIST_DATA(c->UnixVLanList, i);
+ e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
+ item = e->Items[i];
+
+ item->Enabled = v->Enabled;
+ BinToStr(item->MacAddress, sizeof(item->MacAddress), v->MacAddress, 6);
+ StrCpy(item->DeviceName, sizeof(item->DeviceName), v->Name);
+ StrCpy(item->Version, sizeof(item->Version), c->Cedar->VerString);
+ }
+ }
+ UnlockList(c->UnixVLanList);
+
+ return true;
+
+#else // OS_WIN32
+
+ // Enumeration
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t == NULL)
+ {
+ // Enumeration failure
+ e->NumItem = 0;
+ e->Items = ZeroMalloc(0);
+ }
+ else
+ {
+ // Enumeration success
+ e->NumItem = t->NumTokens;
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ char *tmp;
+ RPC_CLIENT_ENUM_VLAN_ITEM *item;
+ e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
+ item = e->Items[i];
+
+ StrCpy(item->DeviceName, sizeof(item->DeviceName), t->Token[i]);
+ item->Enabled = MsIsVLanEnabled(item->DeviceName);
+
+ tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
+ }
+
+ StrCpy(item->MacAddress, sizeof(item->MacAddress), tmp);
+ Free(tmp);
+
+ tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
+ }
+
+ StrCpy(item->Version, sizeof(item->Version), tmp);
+ Free(tmp);
+ }
+
+ FreeToken(t);
+ }
+
+ return true;
+
+#endif // OS_WIN32
+}
+
+// Release the virtual LAN card enumeration
+void CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ Free(e->Items[i]);
+ }
+ Free(e->Items);
+}
+
+// Set the information about the virtual LAN card
+bool CtSetVLan(CLIENT *c, RPC_CLIENT_SET_VLAN *set)
+{
+ // Validate arguments
+ if (c == NULL || set == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN t, *r;
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), set->DeviceName);
+
+ r = Search(c->UnixVLanList, &t);
+ if (r == NULL)
+ {
+ // Not exist
+ CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
+ UnlockList(c->UnixVLanList);
+ return false;
+ }
+
+ StrToMac(r->MacAddress, set->MacAddress);
+ }
+ UnlockList(c->UnixVLanList);
+
+ CiSaveConfigurationFile(c);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#else // OS_WIN32
+
+ // Check whether the virtual LAN card with the specified name already exists
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, set->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName) == false)
+ {
+ // Not exist
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Configuring MAC address
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, set->DeviceName, set->MacAddress);
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName, set->MacAddress);
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#endif // OS_WIN32
+}
+
+// Get the information about the virtual LAN card
+bool CtGetVLan(CLIENT *c, RPC_CLIENT_GET_VLAN *get)
+{
+ char *tmp;
+ // Validate arguments
+ if (c == NULL || get == NULL)
+ {
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ // Unsupported
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+
+#else // OS_WIN32
+
+ // Check whether the virtual LAN card with the specified name already exists
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, get->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName) == false)
+ {
+ // Not exist
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+
+ // Activity
+ get->Enabled = MsIsVLanEnabled(get->DeviceName);
+
+ // MAC address
+ tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
+ }
+ StrCpy(get->MacAddress, sizeof(get->MacAddress), tmp);
+ Free(tmp);
+
+ // Version
+ tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
+ }
+ StrCpy(get->Version, sizeof(get->Version), tmp);
+ Free(tmp);
+
+ // File name
+ tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
+ }
+ StrCpy(get->FileName, sizeof(get->FileName), tmp);
+ Free(tmp);
+
+ // GUID
+ tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
+ if (tmp == NULL)
+ {
+ tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
+ }
+ StrCpy(get->Guid, sizeof(get->Guid), tmp);
+ Free(tmp);
+
+ return true;
+
+#endif // OS_WIN32
+}
+
+#ifdef OS_WIN32
+// Initialize the driver version information structure
+void CiInitDriverVerStruct(MS_DRIVER_VER *ver)
+{
+ UINT cedar_ver = CEDAR_VER;
+ // Validate arguments
+ if (ver == NULL)
+ {
+ return;
+ }
+
+ Zero(ver, sizeof(MS_DRIVER_VER));
+
+ ver->Year = BUILD_DATE_Y;
+ ver->Month = BUILD_DATE_M;
+ ver->Day = BUILD_DATE_D;
+ ver->Major = cedar_ver / 100;
+ ver->Minor = cedar_ver % 100;
+ ver->Build = CEDAR_BUILD;
+}
+#endif // OS_WIN32
+
+// Upgrade the virtual LAN card
+bool CtUpgradeVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
+{
+ bool use_old_name = false;
+
+#ifdef OS_WIN32
+ KAKUSHI *k = NULL;
+ MS_DRIVER_VER ver;
+#endif // OS_WIN32
+
+ // Validate arguments
+ if (c == NULL || create == NULL)
+ {
+ return false;
+ }
+
+
+#ifndef OS_WIN32
+
+ // Always succeed
+ return true;
+
+#else // OS_WIN32
+
+ CiInitDriverVerStruct(&ver);
+
+ if (MsIsNt() == false)
+ {
+ // Not available in Win9x
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Check whether the LAN card with the specified name already exists
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) == false &&
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName) == false)
+ {
+ // Not exist
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
+ {
+ use_old_name = true;
+ }
+
+ if (MsIsVista() == false)
+ {
+ k = InitKakushi();
+ }
+
+
+ if (MsIsVista() == false)
+ {
+ // Perform the installation (other than Windows Vista)
+ if (MsUpgradeVLan(use_old_name ? VLAN_ADAPTER_NAME_TAG_OLD : VLAN_ADAPTER_NAME_TAG,
+ use_old_name ? VLAN_CONNECTION_NAME_OLD : VLAN_CONNECTION_NAME,
+ create->DeviceName, &ver) == false)
+ {
+ // Installation Failed
+ FreeKakushi(k);
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+ else
+ {
+ // Perform the installation (Windows Vista)
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "upgradevlan %s", create->DeviceName);
+
+ if (CncExecDriverInstaller(tmp) == false)
+ {
+ // Installation Failed
+ FreeKakushi(k);
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+
+ FreeKakushi(k);
+
+ CLog(c, "LC_UPDATE_VLAN", create->DeviceName);
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ return true;
+
+#endif // OS_WIN32
+}
+
+// Create a virtual LAN card
+bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
+{
+ TOKEN_LIST *t;
+ UINT max_len;
+
+#ifdef OS_WIN32
+ KAKUSHI *k = NULL;
+#endif // OS_WIN32
+
+ // Validate arguments
+ if (c == NULL || create == NULL)
+ {
+ return false;
+ }
+
+ if (SearchStrEx(create->DeviceName, " ", 0, false) != INFINITE)
+ {
+ // Spaces in the name is not allowed
+ CiSetError(c, ERR_INVALID_PARAMETER);
+ return false;
+ }
+
+#ifndef OS_WIN32
+
+ // Non-Win32
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // A virtual LAN card can not be added or removed in MacOS X
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Check whether the specified name is valid or not
+ if (IsSafeStr(create->DeviceName) == false)
+ {
+ // Name is invalid
+ CiSetError(c, ERR_VLAN_INVALID_NAME);
+ return false;
+ }
+
+ // Check whether the LAN card of the specified name already exists
+ LockList(c->UnixVLanList);
+ {
+ UNIX_VLAN t, *r;
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), create->DeviceName);
+
+ r = Search(c->UnixVLanList, &t);
+ if (r != NULL)
+ {
+ // Already exist
+ CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
+ UnlockList(c->UnixVLanList);
+ return false;
+ }
+
+ // Register
+ r = ZeroMalloc(sizeof(UNIX_VLAN));
+ r->Enabled = true;
+ GenMacAddress(r->MacAddress);
+ StrCpy(r->Name, sizeof(r->Name), create->DeviceName);
+
+ // Create a Tap
+ if (UnixVLanCreate(r->Name, r->MacAddress) == false)
+ {
+ // Failure
+ Free(r);
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ UnlockList(c->UnixVLanList);
+ return false;
+ }
+
+ CLog(c, "LC_CREATE_VLAN", create->DeviceName);
+
+ Add(c->UnixVLanList, r);
+ }
+ UnlockList(c->UnixVLanList);
+
+ CiNormalizeAccountVLan(c);
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ CiSaveConfigurationFile(c);
+
+ return true;
+
+#else // OS_WIN32
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ // Only one LAN card is available in the Win9x
+ TOKEN_LIST *t;
+
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t != NULL)
+ {
+ if (t->NumTokens >= 1)
+ {
+ FreeToken(t);
+ CiSetError(c, ERR_NOT_SUPPORTED);
+ return false;
+ }
+ FreeToken(t);
+ }
+ }
+
+ // Check whether the specified name is valid or not
+ if (IsSafeStr(create->DeviceName) == false)
+ {
+ // Name is invalid
+ CiSetError(c, ERR_VLAN_INVALID_NAME);
+ return false;
+ }
+
+ max_len = MsIsNt() ? MAX_DEVICE_NAME_LEN : MAX_DEVICE_NAME_LEN_9X;
+ if (StrLen(create->DeviceName) > max_len)
+ {
+ // Name is too long
+ CiSetError(c, ERR_VLAN_INVALID_NAME);
+ return false;
+ }
+
+ // Regulation in Windows 8
+ if (MsIsInfCatalogRequired())
+ {
+ if (CiIsValidVLanRegulatedName(create->DeviceName) == false)
+ {
+ // Name is invalid
+ CiSetError(c, ERR_VLAN_INVALID_NAME);
+ return false;
+ }
+ }
+
+ // Check whether the LAN card with the specified name already exists
+ if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) ||
+ MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
+ {
+ // Already exist
+ CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
+ return false;
+ }
+
+ if (MsIsNt())
+ {
+ if (MsIsVista() == false)
+ {
+ k = InitKakushi();
+ }
+ }
+
+ if (MsIsVista() == false)
+ {
+ MS_DRIVER_VER ver;
+
+ CiInitDriverVerStruct(&ver);
+
+ // Perform the installation (other than Windows Vista)
+ if (MsInstallVLan(VLAN_ADAPTER_NAME_TAG, VLAN_CONNECTION_NAME, create->DeviceName, &ver) == false)
+ {
+ // Installation Failed
+ FreeKakushi(k);
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+ else
+ {
+ // Perform the installation (Windows Vista)
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "instvlan %s", create->DeviceName);
+
+ if (CncExecDriverInstaller(tmp) == false)
+ {
+ // Installation Failed
+ FreeKakushi(k);
+ CiSetError(c, ERR_VLAN_INSTALL_ERROR);
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ return false;
+ }
+ }
+
+ FreeKakushi(k);
+
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t->NumTokens == 1)
+ {
+ UINT i;
+ // If the result of the installation, virtual LAN card is only one,
+ // set virtual LAN card setting of all existing accounts to this virtual LAN card
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+ Lock(a->lock);
+ {
+ if (a->ClientOption != NULL)
+ {
+ StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), create->DeviceName);
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ UnlockList(c->AccountList);
+ }
+ FreeToken(t);
+
+ CLog(c, "LC_CREATE_VLAN", create->DeviceName);
+
+ CiNormalizeAccountVLan(c);
+
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+
+ CiSaveConfigurationFile(c);
+
+ if (MsIsNt() == false)
+ {
+ if (GetOsInfo()->OsType == OSTYPE_WINDOWS_ME)
+ {
+ // Show the warning in the case of Windows Me
+ MsgBox(NULL, 0x00000040L, _UU("CM_9X_VLAN_ME_MESSAGE"));
+ }
+
+ ReleaseThread(NewThread(Win9xRebootThread, NULL));
+ }
+
+ return true;
+
+#endif // OS_WIN32
+}
+
+// Enumerate objects in the secure device
+bool CtEnumObjectInSecure(CLIENT *c, RPC_ENUM_OBJECT_IN_SECURE *e)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ e->NumItem = 5;
+ e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);
+ e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "Test Object %u", i);
+ e->ItemName[i] = CopyStr(tmp);
+ e->ItemType[i] = (i % 2 == 0) ? false : true;
+ }
+
+ return true;
+}
+
+// Get the secure device to be used
+bool CtGetUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
+{
+ // Validate arguments
+ if (c == NULL || sec == NULL)
+ {
+ return false;
+ }
+
+ sec->DeviceId = c->UseSecureDeviceId;
+
+ return true;
+}
+
+// Specifying a secure device to be used
+bool CtUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
+{
+ // Validate arguments
+ if (c == NULL || sec == NULL)
+ {
+ return false;
+ }
+
+// Do not check whether there is the specified device on the client manager
+/* if (CheckSecureDeviceId(sec->DeviceId))
+ {
+ c->UseSecureDeviceId = sec->DeviceId;
+ }
+ else
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ return false;
+ }
+*/
+ c->UseSecureDeviceId = sec->DeviceId;
+
+ CiSaveConfigurationFile(c);
+
+ return true;
+}
+
+// Enumeration of secure devices
+bool CtEnumSecure(CLIENT *c, RPC_CLIENT_ENUM_SECURE *e)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (c == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ o = GetSecureDeviceList();
+
+ e->NumItem = LIST_NUM(o);
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RPC_CLIENT_ENUM_SECURE_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
+ SECURE_DEVICE *s = LIST_DATA(o, i);
+
+ item->DeviceId = s->Id;
+ StrCpy(item->DeviceName, sizeof(item->DeviceName), s->DeviceName);
+ StrCpy(item->Manufacturer, sizeof(item->Manufacturer), s->Manufacturer);
+ item->Type = s->Type;
+
+ e->Items[i] = item;
+ }
+
+ return true;
+}
+
+// Release the secure device enumeration
+void CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ Free(e->Items[i]);
+ }
+ Free(e->Items);
+}
+
+// Release the RPC_GET_ISSUER
+void CiFreeGetIssuer(RPC_GET_ISSUER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (a->issuer_x != NULL)
+ {
+ FreeX(a->issuer_x);
+ }
+ if (a->x != NULL)
+ {
+ FreeX(a->x);
+ }
+}
+
+// Get the common proxy settings
+bool CtGetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
+{
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ Copy(a, &c->CommonProxySetting, sizeof(INTERNET_SETTING));
+
+ return true;
+}
+
+// Set the common proxy settings
+bool CtSetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
+{
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ Copy(&c->CommonProxySetting, a, sizeof(INTERNET_SETTING));
+
+
+ CiSaveConfigurationFile(c);
+
+ return true;
+}
+
+// Get the issuer
+bool CtGetIssuer(CLIENT *c, RPC_GET_ISSUER *a)
+{
+ X *x;
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ x = FindCaSignedX(c->Cedar->CaList, a->x);
+ if (x == NULL)
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);;
+ return false;
+ }
+ else
+ {
+ a->issuer_x = x;
+ if (a->x != NULL)
+ {
+ FreeX(a->x);
+ a->x = NULL;
+ }
+ return true;
+ }
+}
+
+// Get the CA certificate
+bool CtGetCa(CLIENT *c, RPC_GET_CA *get)
+{
+ bool ret = true;
+ X *cert = NULL;
+ // Validate arguments
+ if (c == NULL || get == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->Cedar->CaList);
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(c->Cedar->CaList);i++)
+ {
+ X *x = LIST_DATA(c->Cedar->CaList, i);
+
+ if (POINTER_TO_KEY(x) == get->Key)
+ {
+ cert = CloneX(x);
+ break;
+ }
+ }
+ }
+ UnlockList(c->Cedar->CaList);
+
+ if (cert == NULL)
+ {
+ // Certificate does not exist
+ ret = false;
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ }
+ else
+ {
+ ret = true;
+ get->x = cert;
+ }
+
+ return ret;
+}
+
+// Delete the CA certificate
+bool CtDeleteCa(CLIENT *c, RPC_CLIENT_DELETE_CA *p)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ ret = DeleteCa(c->Cedar, p->Key);
+
+ if (ret == false)
+ {
+ CiSetError(c, ERR_OBJECT_NOT_FOUND);
+ }
+
+ CiSaveConfigurationFile(c);
+
+ return ret;
+}
+
+// Add a CA certificate
+bool CtAddCa(CLIENT *c, RPC_CERT *cert)
+{
+ // Validate arguments
+ if (c == NULL || cert == NULL)
+ {
+ return false;
+ }
+
+ if (cert->x->is_compatible_bit == false)
+ {
+ CiSetError(c, ERR_NOT_RSA_1024);
+ return false;
+ }
+
+ AddCa(c->Cedar, cert->x);
+
+ CiSaveConfigurationFile(c);
+
+ return true;
+}
+
+// Enumerate the trusted CA
+bool CtEnumCa(CLIENT *c, RPC_CLIENT_ENUM_CA *e)
+{
+ // Validate arguments
+ if (c == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
+
+ LockList(c->Cedar->CaList);
+ {
+ UINT i;
+ e->NumItem = LIST_NUM(c->Cedar->CaList);
+ e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ X *x = LIST_DATA(c->Cedar->CaList, i);
+ e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
+ GetAllNameFromNameEx(e->Items[i]->SubjectName, sizeof(e->Items[i]->SubjectName), x->subject_name);
+ GetAllNameFromNameEx(e->Items[i]->IssuerName, sizeof(e->Items[i]->IssuerName), x->issuer_name);
+ e->Items[i]->Expires = x->notAfter;
+ e->Items[i]->Key = POINTER_TO_KEY(x);
+ }
+ }
+ UnlockList(c->Cedar->CaList);
+
+ return true;
+}
+
+// Release the CA enumeration
+void CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < e->NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_CA_ITEM *ca = e->Items[i];
+ Free(ca);
+ }
+ Free(e->Items);
+}
+
+// Get the password setting
+bool CtGetPasswordSetting(CLIENT *c, RPC_CLIENT_PASSWORD_SETTING *a)
+{
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (c == NULL || a == NULL)
+ {
+ return false;
+ }
+
+ Hash(hash, "", 0, true);
+ if (Cmp(hash, c->EncryptedPassword, SHA1_SIZE) == 0)
+ {
+ a->IsPasswordPresented = false;
+ }
+ else
+ {
+ a->IsPasswordPresented = true;
+ }
+
+ a->PasswordRemoteOnly = c->PasswordRemoteOnly;
+
+ return true;
+}
+
+// Set the password
+bool CtSetPassword(CLIENT *c, RPC_CLIENT_PASSWORD *pass)
+{
+ char *str;
+ if (c == NULL)
+ {
+ return false;
+ }
+ if (pass->Password == NULL)
+ {
+ str = "";
+ }
+ else
+ {
+ str = pass->Password;
+ }
+
+ if (StrCmp(str, "********") != 0)
+ {
+ // Hash the password
+ Hash(c->EncryptedPassword, str, StrLen(str), true);
+ }
+
+ c->PasswordRemoteOnly = pass->PasswordRemoteOnly;
+
+ CLog(c, "LC_SET_PASSWORD");
+
+ CiSaveConfigurationFile(c);
+
+ return true;
+}
+
+void CiFreeIni(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ FreeIni(o);
+}
+
+// Read the custom.ini file
+LIST *CiLoadIni()
+{
+ BUF *b = ReadDump(CLIENT_CUSTOM_INI_FILENAME);
+ LIST *ini;
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ ini = ReadIni(b);
+
+ FreeBuf(b);
+
+ return ini;
+
+}
+
+// Reflect the settings of the custom.ini
+void CiLoadIniSettings(CLIENT *c)
+{
+ LIST *o;
+ //char *log;
+ //char *config;
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ o = CiLoadIni();
+
+ if (o == NULL)
+ {
+ return;
+ }
+
+ /*log = IniStrValue(o, "NoSaveLog");
+ config = IniStrValue(o, "NoSaveConfig");
+
+ if(StrCmpi(log, "true") == 0)
+ {
+ c->NoSaveLog = true;
+ }
+ if(StrCmpi(config, "true") == 0)
+ {
+ c->NoSaveConfig = true;
+ }*/
+
+ c->NoSaveLog = ToBool(IniStrValue(o, "NoSaveLog"));
+ c->NoSaveConfig = ToBool(IniStrValue(o, "NoSaveConfig"));
+
+ CiFreeIni(o);
+
+}
+
+bool CiLoadConfigFilePathFromIni(char *path, UINT size)
+{
+ char *tmp;
+ LIST *o;
+ bool ret = false;
+
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ o = CiLoadIni();
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(path, size, "");
+
+ tmp = IniStrValue(o, "ConfigPath");
+ NormalizePath(path, size, tmp);
+
+ if (IsEmptyStr(path) == false)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ CiFreeIni(o);
+
+ return ret;
+}
+
+// Set the client error code
+void CiSetError(CLIENT *c, UINT err)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->Err = err;
+}
+
+// UNIX virtual LAN card comparison function
+int CiCompareUnixVLan(void *p1, void *p2)
+{
+ UNIX_VLAN *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(UNIX_VLAN **)p1;
+ v2 = *(UNIX_VLAN **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// Modify the account settings that an incorrect VLAN name is specified
+void CiNormalizeAccountVLan(CLIENT *c)
+{
+ bool b = false;
+ char *name;
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ name = CiGetFirstVLan(c);
+
+ if (name != NULL)
+ {
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+
+ Lock(a->lock);
+ {
+ if (a->ClientOption != NULL)
+ {
+ if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
+ {
+ StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
+ name);
+ b = true;
+ }
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ UnlockList(c->AccountList);
+
+ Free(name);
+ }
+
+ if (b)
+ {
+ CiNotify(c);
+ CiSendGlobalPulse(c);
+ CiSaveConfigurationFile(c);
+ }
+}
+
+// Check whether a virtual LAN card of the specified name exists
+bool CiIsVLan(CLIENT *c, char *name)
+{
+ // Validate arguments
+ if (c == NULL || name == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ {
+ TOKEN_LIST *t;
+ UINT i;
+
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (StrCmpi(t->Token[i], name) == 0)
+ {
+ FreeToken(t);
+ return true;
+ }
+ }
+
+ FreeToken(t);
+
+ return false;
+ }
+#else // OS_WIN32
+ {
+ UNIX_VLAN *v;
+ UINT i;
+ bool ret = false;
+
+ LockList(c->UnixVLanList);
+ {
+ for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
+ {
+ v = (UNIX_VLAN *)LIST_DATA(c->UnixVLanList, i);
+ if (StrCmpi(v->Name, name) == 0)
+ {
+ ret = true;
+ }
+ }
+ }
+ UnlockList(c->UnixVLanList);
+
+ return ret;
+ }
+#endif // OS_WIN32
+}
+
+// If a non-existent virtual LAN card is specified in any Account, and only
+// one virtual LAN card is installed, set the virtual LAN card to the account
+void CiSetVLanToDefault(CLIENT *c)
+{
+ char device_name[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ {
+ TOKEN_LIST *t;
+
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t == NULL)
+ {
+ return;
+ }
+ if (t->NumTokens != 1)
+ {
+ FreeToken(t);
+ return;
+ }
+ StrCpy(device_name, sizeof(device_name), t->Token[0]);
+ FreeToken(t);
+ }
+#else // OS_WIN32
+ {
+ UINT i;
+ UNIX_VLAN *v;
+
+ LockList(c->UnixVLanList);
+
+ if (LIST_NUM(c->UnixVLanList) != 1)
+ {
+ UnlockList(c->UnixVLanList);
+ return;
+ }
+ v = LIST_DATA(c->UnixVLanList, 0);
+ StrCpy(device_name, sizeof(device_name), v->Name);
+
+ UnlockList(c->UnixVLanList);
+ }
+#endif // OS_WIN32
+
+ {
+ UINT i;
+ LockList(c->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+
+ Lock(a->lock);
+ {
+ if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
+ {
+ StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
+ device_name);
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ UnlockList(c->AccountList);
+ }
+}
+
+// Initialize the settings
+void CiInitConfiguration(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_UNIX
+ // Initialize the VLAN
+ UnixVLanInit();
+#endif // OS_UNIX
+
+ // Account list
+ c->AccountList = NewList(CiCompareAccount);
+
+ // Unix version VLAN list
+ if (OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ c->UnixVLanList = NewList(CiCompareUnixVLan);
+ }
+
+ // Read the configuration file
+ CLog(c, "LC_LOAD_CONFIG_1");
+ if (CiLoadConfigurationFile(c) == false)
+ {
+ CLog(c, "LC_LOAD_CONFIG_3");
+ // Do the initial setup because the configuration file does not exist
+ // Clear the password
+ Hash(c->EncryptedPassword, "", 0, true);
+ // Initialize the client configuration
+ if (OS_IS_WINDOWS(GetOsInfo()->OsType))
+ {
+ // Disable remote management in Windows
+ c->Config.AllowRemoteConfig = false;
+ }
+ else
+ {
+ // Disable the remote management also in case of UNIX
+ c->Config.AllowRemoteConfig = false;
+ }
+ StrCpy(c->Config.KeepConnectHost, sizeof(c->Config.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
+ c->Config.KeepConnectPort = CLIENT_DEFAULT_KEEPALIVE_PORT;
+ c->Config.KeepConnectProtocol = CONNECTION_UDP;
+ c->Config.KeepConnectInterval = CLIENT_DEFAULT_KEEPALIVE_INTERVAL;
+ c->Config.UseKeepConnect = false; // Don't use the connection maintenance function by default in the Client
+ // Eraser
+ c->Eraser = NewEraser(c->Logger, 0);
+ }
+ else
+ {
+ CLog(c, "LC_LOAD_CONFIG_2");
+ }
+
+ // Appropriate setting for virtual LAN card
+ CiSetVLanToDefault(c);
+}
+
+// Release the settings
+void CiFreeConfiguration(CLIENT *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Write to the configuration file
+ CiSaveConfigurationFile(c);
+
+ // Release the configuration file
+ FreeCfgRw(c->CfgRw);
+
+ // Release the account list
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+
+ CiFreeAccount(a);
+ }
+ ReleaseList(c->AccountList);
+
+ if (c->UnixVLanList != NULL)
+ {
+ // Release of UNIX version VLAN list
+ for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
+ {
+ UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
+ Free(v);
+ }
+ ReleaseList(c->UnixVLanList);
+ }
+ c->UnixVLanList = NULL;
+
+#ifdef OS_UNIX
+ // Release the VLAN
+ UnixVLanFree();
+#endif // OS_UNIX
+}
+
+// Release the certificate data acquisition
+void CiFreeGetCa(RPC_GET_CA *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ FreeX(a->x);
+}
+
+// Release the client authentication data
+void CiFreeClientAuth(CLIENT_AUTH *auth)
+{
+ // Validate arguments
+ if (auth == NULL)
+ {
+ return;
+ }
+
+ if (auth->ClientX != NULL)
+ {
+ FreeX(auth->ClientX);
+ }
+ if (auth->ClientK != NULL)
+ {
+ FreeK(auth->ClientK);
+ }
+
+ Free(auth);
+}
+
+// Release the account
+void CiFreeAccount(ACCOUNT *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ // Release the lock
+ DeleteLock(a->lock);
+
+ // Release the client option
+ Free(a->ClientOption);
+
+ // Release the client authentication data
+ CiFreeClientAuth(a->ClientAuth);
+
+ if (a->ServerCert != NULL)
+ {
+ FreeX(a->ServerCert);
+ }
+
+ Free(a);
+}
+
+// Sort accounts
+int CiCompareAccount(void *p1, void *p2)
+{
+ ACCOUNT *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(ACCOUNT **)p1;
+ a2 = *(ACCOUNT **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+
+ return UniStrCmpi(a1->ClientOption->AccountName, a2->ClientOption->AccountName);
+}
+
+// Read the client configuration
+void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f)
+{
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ c->UseKeepConnect = CfgGetBool(f, "UseKeepConnect");
+ CfgGetStr(f, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
+ c->KeepConnectPort = CfgGetInt(f, "KeepConnectPort");
+ c->KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");
+ c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig");
+ c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);
+ c->NoChangeWcmNetworkSettingOnWindows8 = CfgGetBool(f, "NoChangeWcmNetworkSettingOnWindows8");
+}
+
+// Read the client authentication data
+CLIENT_AUTH *CiLoadClientAuth(FOLDER *f)
+{
+ CLIENT_AUTH *a;
+ char *s;
+ BUF *b;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(CLIENT_AUTH));
+
+ a->AuthType = CfgGetInt(f, "AuthType");
+ CfgGetStr(f, "Username", a->Username, sizeof(a->Username));
+
+ switch (a->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ CfgGetByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ b = CfgGetBuf(f, "EncryptedPassword");
+ if (b != NULL)
+ {
+ s = DecryptPassword(b);
+ StrCpy(a->PlainPassword, sizeof(a->PlainPassword), s);
+ Free(s);
+ FreeBuf(b);
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ b = CfgGetBuf(f, "ClientCert");
+ if (b != NULL)
+ {
+ a->ClientX = BufToX(b, false);
+ }
+ FreeBuf(b);
+ b = CfgGetBuf(f, "ClientKey");
+ if (b != NULL)
+ {
+ a->ClientK = BufToK(b, true, false, NULL);
+ }
+ FreeBuf(b);
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ CfgGetStr(f, "SecurePublicCertName", a->SecurePublicCertName, sizeof(a->SecurePublicCertName));
+ CfgGetStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName, sizeof(a->SecurePrivateKeyName));
+ break;
+ }
+
+ return a;
+}
+
+// Read the client option
+CLIENT_OPTION *CiLoadClientOption(FOLDER *f)
+{
+ CLIENT_OPTION *o;
+ char *s;
+ BUF *b;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(CLIENT_OPTION));
+
+ CfgGetUniStr(f, "AccountName", o->AccountName, sizeof(o->AccountName));
+ CfgGetStr(f, "Hostname", o->Hostname, sizeof(o->Hostname));
+ o->Port = CfgGetInt(f, "Port");
+ o->PortUDP = CfgGetInt(f, "PortUDP");
+ o->ProxyType = CfgGetInt(f, "ProxyType");
+ CfgGetStr(f, "ProxyName", o->ProxyName, sizeof(o->ProxyName));
+ o->ProxyPort = CfgGetInt(f, "ProxyPort");
+ CfgGetStr(f, "ProxyUsername", o->ProxyUsername, sizeof(o->ProxyUsername));
+ b = CfgGetBuf(f, "ProxyPassword");
+ s = DecryptPassword(b);
+ StrCpy(o->ProxyPassword, sizeof(o->ProxyPassword), s);
+ Free(s);
+ FreeBuf(b);
+ o->NumRetry = CfgGetInt(f, "NumRetry");
+ o->RetryInterval = CfgGetInt(f, "RetryInterval");
+ CfgGetStr(f, "HubName", o->HubName, sizeof(o->HubName));
+ o->MaxConnection = CfgGetInt(f, "MaxConnection");
+ o->UseEncrypt = CfgGetBool(f, "UseEncrypt");
+ o->UseCompress = CfgGetBool(f, "UseCompress");
+ o->HalfConnection = CfgGetBool(f, "HalfConnection");
+ o->NoRoutingTracking = CfgGetBool(f, "NoRoutingTracking");
+ CfgGetStr(f, "DeviceName", o->DeviceName, sizeof(o->DeviceName));
+ o->AdditionalConnectionInterval = CfgGetInt(f, "AdditionalConnectionInterval");
+ o->HideStatusWindow = CfgGetBool(f, "HideStatusWindow");
+ o->HideNicInfoWindow = CfgGetBool(f, "HideNicInfoWindow");
+ o->ConnectionDisconnectSpan = CfgGetInt(f, "ConnectionDisconnectSpan");
+ o->RequireMonitorMode = CfgGetBool(f, "RequireMonitorMode");
+ o->RequireBridgeRoutingMode = CfgGetBool(f, "RequireBridgeRoutingMode");
+ o->DisableQoS = CfgGetBool(f, "DisableQoS");
+ o->FromAdminPack = CfgGetBool(f, "FromAdminPack");
+ o->NoTls1 = CfgGetBool(f, "NoTls1");
+ o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration");
+
+ b = CfgGetBuf(f, "HostUniqueKey");
+ if (b != NULL)
+ {
+ if (b->Size == SHA1_SIZE)
+ {
+ Copy(o->HostUniqueKey, b->Buf, SHA1_SIZE);
+ }
+
+ FreeBuf(b);
+ }
+
+ return o;
+}
+
+// Read the account data
+ACCOUNT *CiLoadClientAccount(FOLDER *f)
+{
+ ACCOUNT *a;
+ FOLDER *client_option_folder, *client_auth_folder;
+ BUF *b;
+ char tmp[64];
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ client_option_folder = CfgGetFolder(f, "ClientOption");
+
+ if (client_option_folder != NULL)
+ {
+ // Compare whether it matches to the account name that is already registered
+ }
+
+ client_auth_folder = CfgGetFolder(f, "ClientAuth");
+
+ if (client_option_folder == NULL || client_auth_folder == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(ACCOUNT));
+ a->lock = NewLock();
+
+ a->ClientOption = CiLoadClientOption(client_option_folder);
+ a->ClientAuth = CiLoadClientAuth(client_auth_folder);
+
+ a->StartupAccount = CfgGetBool(f, "StartupAccount");
+ a->CheckServerCert = CfgGetBool(f, "CheckServerCert");
+ a->CreateDateTime = CfgGetInt64(f, "CreateDateTime");
+ a->UpdateDateTime = CfgGetInt64(f, "UpdateDateTime");
+ a->LastConnectDateTime = CfgGetInt64(f, "LastConnectDateTime");
+
+ b = CfgGetBuf(f, "ServerCert");
+ if (b != NULL)
+ {
+ a->ServerCert = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ if (CfgGetStr(f, "ShortcutKey", tmp, sizeof(tmp)))
+ {
+ BUF *b = StrToBin(tmp);
+ if (b->Size == SHA1_SIZE)
+ {
+ Copy(a->ShortcutKey, b->Buf, SHA1_SIZE);
+ }
+ FreeBuf(b);
+ }
+
+ if (IsZero(a->ShortcutKey, SHA1_SIZE))
+ {
+ Rand(a->ShortcutKey, SHA1_SIZE);
+ }
+
+ return a;
+}
+
+// Read the account database
+void CiLoadAccountDatabase(CLIENT *c, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(f, t->Token[i]);
+
+ if (ff != NULL)
+ {
+ ACCOUNT *a = CiLoadClientAccount(ff);
+ if (a != NULL)
+ {
+ {
+ Add(c->AccountList, a);
+ }
+ }
+ }
+ }
+
+ Sort(c->AccountList);
+
+ FreeToken(t);
+}
+
+// Read the root CA certificate
+void CiLoadCACert(CLIENT *c, FOLDER *f)
+{
+ BUF *b;
+ X *x;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ b = CfgGetBuf(f, "X509");
+ if (b == NULL)
+ {
+ return;
+ }
+
+ x = BufToX(b, false);
+
+ AddCa(c->Cedar, x);
+
+ FreeX(x);
+
+ FreeBuf(b);
+}
+
+// Read the root CA list
+void CiLoadCAList(CLIENT *c, FOLDER *f)
+{
+ CEDAR *cedar;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ cedar = c->Cedar;
+
+ LockList(cedar->CaList);
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *folder = CfgGetFolder(f, t->Token[i]);
+ CiLoadCACert(c, folder);
+ }
+ }
+ UnlockList(cedar->CaList);
+
+ FreeToken(t);
+}
+
+// Read a VLAN
+void CiLoadVLan(CLIENT *c, FOLDER *f)
+{
+ char tmp[MAX_SIZE];
+ UCHAR addr[6];
+ BUF *b;
+ UNIX_VLAN *v;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ if (CfgGetStr(f, "MacAddress", tmp, sizeof(tmp)) == false)
+ {
+ return;
+ }
+
+ b = StrToBin(tmp);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->Size != 6)
+ {
+ FreeBuf(b);
+ return;
+ }
+
+ Copy(addr, b->Buf, 6);
+
+ FreeBuf(b);
+
+ if (IsZero(addr, 6))
+ {
+ return;
+ }
+
+ v = ZeroMalloc(sizeof(UNIX_VLAN));
+ Copy(v->MacAddress, addr, 6);
+ StrCpy(v->Name, sizeof(v->Name), f->Name);
+ v->Enabled = CfgGetBool(f, "Enabled");
+
+ Add(c->UnixVLanList, v);
+
+#ifdef OS_UNIX
+ UnixVLanCreate(v->Name, v->MacAddress);
+#endif // OS_UNIX
+}
+
+// Read a VLAN list
+void CiLoadVLanList(CLIENT *c, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ LockList(c->UnixVLanList);
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *folder = CfgGetFolder(f, t->Token[i]);
+ CiLoadVLan(c, folder);
+ }
+ }
+ UnlockList(c->UnixVLanList);
+
+ FreeToken(t);
+}
+
+// Read the configuration from the configuration file
+bool CiReadSettingFromCfg(CLIENT *c, FOLDER *root)
+{
+ FOLDER *config;
+ FOLDER *cert;
+ FOLDER *db;
+ FOLDER *vlan;
+ FOLDER *cmsetting;
+ FOLDER *proxy;
+ char user_agent[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || root == NULL)
+ {
+ return false;
+ }
+
+ // Initialize the setting if there isn't either of AccountDatabase and Config
+ config = CfgGetFolder(root, "Config");
+ if (config == NULL)
+ {
+ return false;
+ }
+
+ db = CfgGetFolder(root, "AccountDatabase");
+ if (db == NULL)
+ {
+ return false;
+ }
+
+ cmsetting = CfgGetFolder(root, "ClientManagerSetting");
+
+ CiLoadClientConfig(&c->Config, config);
+
+
+ proxy = CfgGetFolder(root, "CommonProxySetting");
+
+ if (proxy != NULL)
+ {
+ INTERNET_SETTING t;
+ BUF *pw;
+
+ // Proxy Setting
+ Zero(&t, sizeof(t));
+ t.ProxyType = CfgGetInt(proxy, "ProxyType");
+ CfgGetStr(proxy, "ProxyHostName", t.ProxyHostName, sizeof(t.ProxyHostName));
+ t.ProxyPort = CfgGetInt(proxy, "ProxyPort");
+ CfgGetStr(proxy, "ProxyUsername", t.ProxyUsername, sizeof(t.ProxyUsername));
+ pw = CfgGetBuf(proxy, "ProxyPassword");
+ if (pw != NULL)
+ {
+ char *pw_str = DecryptPassword(pw);
+ StrCpy(t.ProxyPassword, sizeof(t.ProxyPassword), pw_str);
+
+ Free(pw_str);
+ FreeBuf(pw);
+ }
+
+ Copy(&c->CommonProxySetting, &t, sizeof(INTERNET_SETTING));
+ }
+
+ // Eraser
+ c->Eraser = NewEraser(c->Logger, CfgGetInt64(config, "AutoDeleteCheckDiskFreeSpaceMin"));
+
+ if (OS_IS_UNIX(GetOsInfo()->OsType) && GetOsInfo()->OsType != OSTYPE_MACOS_X)
+ {
+ // Read the UNIX version virtual LAN card list (except MacOS)
+ vlan = CfgGetFolder(root, "UnixVLan");
+ if (vlan != NULL)
+ {
+ CiLoadVLanList(c, vlan);
+ }
+ }
+
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+#ifdef OS_UNIX
+ UNIX_VLAN *uv;
+
+ // Create a Tap for MacOS X
+ if (UnixVLanCreate(CLIENT_MACOS_TAP_NAME, NULL) == false)
+ {
+ // Fail (abort)
+ CLog(c, "LC_TAP_NOT_FOUND");
+ Alert("tun/tap driver not found.", NULL);
+ exit(0);
+ }
+
+ uv = ZeroMalloc(sizeof(UNIX_VLAN));
+ uv->Enabled = true;
+ StrCpy(uv->Name, sizeof(uv->Name), CLIENT_MACOS_TAP_NAME);
+ Add(c->UnixVLanList, uv);
+#endif // OS_UNIX
+ }
+
+ CiLoadAccountDatabase(c, db);
+
+ if (CfgGetByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE) == false)
+ {
+ Hash(c->EncryptedPassword, "", 0, true);
+ }
+
+ c->PasswordRemoteOnly = CfgGetBool(root, "PasswordRemoteOnly");
+ c->UseSecureDeviceId = CfgGetInt(root, "UseSecureDeviceId");
+
+ if (CfgGetStr(root, "UserAgent", user_agent, sizeof(user_agent)))
+ {
+ if (IsEmptyStr(user_agent) == false)
+ {
+ Free(c->Cedar->HttpUserAgent);
+ c->Cedar->HttpUserAgent = CopyStr(user_agent);
+ }
+ }
+
+ cert = CfgGetFolder(root, "RootCA");
+ if (cert != NULL)
+ {
+ CiLoadCAList(c, cert);
+ }
+
+ c->DontSavePassword = CfgGetBool(root, "DontSavePassword");
+
+ if (cmsetting != NULL)
+ {
+ UINT ostype = GetOsInfo()->OsType;
+ // CM_SETTING
+ CM_SETTING *s = c->CmSetting;
+
+ if (OS_IS_UNIX(ostype) || OS_IS_WINDOWS_NT(ostype))
+ {
+ s->EasyMode = CfgGetBool(cmsetting, "EasyMode");
+ }
+
+ s->LockMode = CfgGetBool(cmsetting, "LockMode");
+ CfgGetByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
+ }
+
+ return true;
+}
+
+// Read the configuration file
+bool CiLoadConfigurationFile(CLIENT *c)
+{
+ bool ret;
+ FOLDER *root;
+ char path[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // Read the configuration file
+ if (CiLoadConfigFilePathFromIni(path, sizeof(path)))
+ {
+ c->CfgRw = NewCfgRw(&root, path);
+ }
+ else
+ {
+ c->CfgRw = NewCfgRw(&root, CLIENT_CONFIG_FILE_NAME);
+ }
+
+ if (root == NULL)
+ {
+ return false;
+ }
+
+ ret = CiReadSettingFromCfg(c, root);
+
+ CfgDeleteFolder(root);
+
+ return ret;
+}
+
+// Write the CLIENT_CONFIG
+void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config)
+{
+ // Validate arguments
+ if (cc == NULL || config == NULL)
+ {
+ return;
+ }
+
+ CfgAddBool(cc, "UseKeepConnect", config->UseKeepConnect);
+ CfgAddStr(cc, "KeepConnectHost", config->KeepConnectHost);
+ CfgAddInt(cc, "KeepConnectPort", config->KeepConnectPort);
+ CfgAddInt(cc, "KeepConnectProtocol", config->KeepConnectProtocol);
+ CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig);
+ CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval);
+ CfgAddBool(cc, "NoChangeWcmNetworkSettingOnWindows8", config->NoChangeWcmNetworkSettingOnWindows8);
+}
+
+// Write the client authentication data
+void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a)
+{
+ BUF *b;
+ // Validate arguments
+ if (f == NULL || a == NULL)
+ {
+ return;
+ }
+
+ CfgAddInt(f, "AuthType", a->AuthType);
+ CfgAddStr(f, "Username", a->Username);
+
+ switch (a->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ CfgAddByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ b = EncryptPassword(a->PlainPassword);
+ CfgAddByte(f, "EncryptedPassword", b->Buf, b->Size);
+ FreeBuf(b);
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ if (a->ClientK != NULL && a->ClientX != NULL)
+ {
+ b = XToBuf(a->ClientX, false);
+ CfgAddByte(f, "ClientCert", b->Buf, b->Size);
+ FreeBuf(b);
+
+ b = KToBuf(a->ClientK, false, NULL);
+ CfgAddByte(f, "ClientKey", b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ CfgAddStr(f, "SecurePublicCertName", a->SecurePublicCertName);
+ CfgAddStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName);
+ break;
+ }
+}
+
+// Write the client option
+void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o)
+{
+ BUF *b;
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ CfgAddUniStr(f, "AccountName", o->AccountName);
+ CfgAddStr(f, "Hostname", o->Hostname);
+ CfgAddInt(f, "Port", o->Port);
+ CfgAddInt(f, "PortUDP", o->PortUDP);
+ CfgAddInt(f, "ProxyType", o->ProxyType);
+ CfgAddStr(f, "ProxyName", o->ProxyName);
+ CfgAddInt(f, "ProxyPort", o->ProxyPort);
+ CfgAddStr(f, "ProxyUsername", o->ProxyUsername);
+ b = EncryptPassword(o->ProxyPassword);
+ CfgAddByte(f, "ProxyPassword", b->Buf, b->Size);
+ FreeBuf(b);
+ CfgAddInt(f, "NumRetry", o->NumRetry);
+ CfgAddInt(f, "RetryInterval", o->RetryInterval);
+ CfgAddStr(f, "HubName", o->HubName);
+ CfgAddInt(f, "MaxConnection", o->MaxConnection);
+ CfgAddBool(f, "UseEncrypt", o->UseEncrypt);
+ CfgAddBool(f, "UseCompress", o->UseCompress);
+ CfgAddBool(f, "HalfConnection", o->HalfConnection);
+ CfgAddBool(f, "NoRoutingTracking", o->NoRoutingTracking);
+ CfgAddStr(f, "DeviceName", o->DeviceName);
+ CfgAddInt(f, "AdditionalConnectionInterval", o->AdditionalConnectionInterval);
+ CfgAddBool(f, "HideStatusWindow", o->HideStatusWindow);
+ CfgAddBool(f, "HideNicInfoWindow", o->HideNicInfoWindow);
+ CfgAddInt(f, "ConnectionDisconnectSpan", o->ConnectionDisconnectSpan);
+ CfgAddBool(f, "RequireMonitorMode", o->RequireMonitorMode);
+ CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode);
+ CfgAddBool(f, "DisableQoS", o->DisableQoS);
+ CfgAddBool(f, "NoTls1", o->NoTls1);
+ CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration);
+
+ if (o->FromAdminPack)
+ {
+ CfgAddBool(f, "FromAdminPack", o->FromAdminPack);
+ }
+
+ if (IsZero(o->HostUniqueKey, SHA1_SIZE) == false)
+ {
+ BUF *b = MemToBuf(o->HostUniqueKey, SHA1_SIZE);
+ CfgAddBuf(f, "HostUniqueKey", b);
+ FreeBuf(b);
+ }
+}
+
+// Decrypt the password
+char *DecryptPassword(BUF *b)
+{
+ char *str;
+ char *key = "EncryptPassword";
+ CRYPT *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return CopyStr("");
+ }
+
+ str = ZeroMalloc(b->Size + 1);
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, str, b->Buf, b->Size);
+ FreeCrypt(c);
+
+ str[b->Size] = 0;
+
+ return str;
+}
+char *DecryptPassword2(BUF *b)
+{
+ char *str;
+ char *key = "EncryptPassword2";
+ CRYPT *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return CopyStr("");
+ }
+
+ str = ZeroMalloc(b->Size + 1);
+ c = NewCrypt(key, StrLen(key));
+ Encrypt(c, str, b->Buf, b->Size);
+ FreeCrypt(c);
+
+ str[b->Size] = 0;
+
+ return str;
+}
+
+// Encrypt the password
+BUF *EncryptPassword(char *password)
+{
+ UCHAR *tmp;
+ UINT size;
+ char *key = "EncryptPassword";
+ CRYPT *c;
+ BUF *b;
+ // Validate arguments
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ size = StrLen(password) + 1;
+ tmp = ZeroMalloc(size);
+
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, tmp, password, size - 1);
+ FreeCrypt(c);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size - 1);
+ SeekBuf(b, 0, 0);
+ Free(tmp);
+
+ return b;
+}
+BUF *EncryptPassword2(char *password)
+{
+ UCHAR *tmp;
+ UINT size;
+ char *key = "EncryptPassword2";
+ CRYPT *c;
+ BUF *b;
+ // Validate arguments
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ size = StrLen(password) + 1;
+ tmp = ZeroMalloc(size);
+
+ c = NewCrypt(key, StrLen(key));
+ Encrypt(c, tmp, password, size - 1);
+ FreeCrypt(c);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size - 1);
+ SeekBuf(b, 0, 0);
+ Free(tmp);
+
+ return b;
+}
+
+// Write the account data
+void CiWriteAccountData(FOLDER *f, ACCOUNT *a)
+{
+ // Validate arguments
+ if (f == NULL || a == NULL)
+ {
+ return;
+ }
+
+ // Client Option
+ CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), a->ClientOption);
+
+ // Client authentication data
+ CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), a->ClientAuth);
+
+ // Startup account
+ CfgAddBool(f, "StartupAccount", a->StartupAccount);
+
+ // Server certificate check flag
+ CfgAddBool(f, "CheckServerCert", a->CheckServerCert);
+
+ // Date and time
+ CfgAddInt64(f, "CreateDateTime", a->CreateDateTime);
+ CfgAddInt64(f, "UpdateDateTime", a->UpdateDateTime);
+ CfgAddInt64(f, "LastConnectDateTime", a->LastConnectDateTime);
+
+ // Server certificate body
+ if (a->ServerCert != NULL)
+ {
+ BUF *b = XToBuf(a->ServerCert, false);
+ if (b != NULL)
+ {
+ CfgAddBuf(f, "ServerCert", b);
+ FreeBuf(b);
+ }
+ }
+
+ // Shortcut Key
+ if (IsZero(a->ShortcutKey, SHA1_SIZE) == false)
+ {
+ char tmp[64];
+ BinToStr(tmp, sizeof(tmp), a->ShortcutKey, SHA1_SIZE);
+ CfgAddStr(f, "ShortcutKey", tmp);
+ }
+}
+
+// Write the account database
+void CiWriteAccountDatabase(CLIENT *c, FOLDER *f)
+{
+ char name[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ LockList(c->AccountList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(c->AccountList, i);
+
+ {
+ Format(name, sizeof(name), "Account%u", i);
+ Lock(a->lock);
+ {
+ CiWriteAccountData(CfgCreateFolder(f, name), a);
+ }
+ Unlock(a->lock);
+ }
+ }
+ }
+ UnlockList(c->AccountList);
+}
+
+// Write the CA certificate
+void CiWriteCACert(CLIENT *c, FOLDER *f, X *x)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || f == NULL || x == NULL)
+ {
+ return;
+ }
+
+ b = XToBuf(x, false);
+ CfgAddBuf(f, "X509", b);
+ FreeBuf(b);
+}
+
+// Write a VLAN
+void CiWriteVLan(CLIENT *c, FOLDER *f, UNIX_VLAN *v)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || f == NULL || v == NULL)
+ {
+ return;
+ }
+
+ MacToStr(tmp, sizeof(tmp), v->MacAddress);
+ CfgAddStr(f, "MacAddress", tmp);
+ CfgAddBool(f, "Enabled", v->Enabled);
+}
+
+// Write a VLAN list
+void CiWriteVLanList(CLIENT *c, FOLDER *f)
+{
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ LockList(c->UnixVLanList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
+ {
+ UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
+ CiWriteVLan(c, CfgCreateFolder(f, v->Name), v);
+ }
+ }
+ UnlockList(c->UnixVLanList);
+}
+
+// Write the CA list
+void CiWriteCAList(CLIENT *c, FOLDER *f)
+{
+ CEDAR *cedar;
+ // Validate arguments
+ if (c == NULL || f == NULL)
+ {
+ return;
+ }
+
+ cedar = c->Cedar;
+
+ LockList(cedar->CaList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(cedar->CaList);i++)
+ {
+ char tmp[MAX_SIZE];
+ X *x = LIST_DATA(cedar->CaList, i);
+ Format(tmp, sizeof(tmp), "Certificate%u", i);
+ CiWriteCACert(c, CfgCreateFolder(f, tmp), x);
+ }
+ }
+ UnlockList(cedar->CaList);
+}
+
+// Write the current settings to ROOT
+void CiWriteSettingToCfg(CLIENT *c, FOLDER *root)
+{
+ FOLDER *cc;
+ FOLDER *account_database;
+ FOLDER *ca;
+ FOLDER *vlan;
+ FOLDER *cmsetting;
+ FOLDER *proxy;
+ // Validate arguments
+ if (c == NULL || root == NULL)
+ {
+ return;
+ }
+
+ cmsetting = CfgCreateFolder(root, "ClientManagerSetting");
+
+ // CLIENT_CONFIG
+ cc = CfgCreateFolder(root, "Config");
+ CiWriteClientConfig(cc, &c->Config);
+
+
+ // Eraser
+ CfgAddInt64(cc, "AutoDeleteCheckDiskFreeSpaceMin", c->Eraser->MinFreeSpace);
+
+ // Account Database
+ account_database = CfgCreateFolder(root, "AccountDatabase");
+ CiWriteAccountDatabase(c, account_database);
+
+ // Proxy
+ proxy = CfgCreateFolder(root, "CommonProxySetting");
+ if (proxy != NULL)
+ {
+ INTERNET_SETTING *t = &c->CommonProxySetting;
+ BUF *pw;
+
+ CfgAddInt(proxy, "ProxyType", t->ProxyType);
+ CfgAddStr(proxy, "ProxyHostName", t->ProxyHostName);
+ CfgAddInt(proxy, "ProxyPort", t->ProxyPort);
+ CfgAddStr(proxy, "ProxyUsername", t->ProxyUsername);
+
+ if (IsEmptyStr(t->ProxyPassword) == false)
+ {
+ pw = EncryptPassword(t->ProxyPassword);
+
+ CfgAddBuf(proxy, "ProxyPassword", pw);
+
+ FreeBuf(pw);
+ }
+ }
+
+ // CA
+ ca = CfgCreateFolder(root, "RootCA");
+ CiWriteCAList(c, ca);
+
+ // VLAN
+ if (OS_IS_UNIX(GetOsInfo()->OsType) && GetOsInfo()->OsType != OSTYPE_MACOS_X)
+ {
+ vlan = CfgCreateFolder(root, "UnixVLan");
+ CiWriteVLanList(c, vlan);
+ }
+
+ // Password
+ CfgAddByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE);
+ CfgAddBool(root, "PasswordRemoteOnly", c->PasswordRemoteOnly);
+
+ // UseSecureDeviceId
+ CfgAddInt(root, "UseSecureDeviceId", c->UseSecureDeviceId);
+
+ // DontSavePassword
+ CfgAddBool(root, "DontSavePassword", c->DontSavePassword);
+
+ // UserAgent
+ if (c->Cedar != NULL)
+ {
+ CfgAddStr(root, "UserAgent", c->Cedar->HttpUserAgent);
+ }
+
+ if (cmsetting != NULL)
+ {
+ CM_SETTING *s = c->CmSetting;
+
+ CfgAddBool(cmsetting, "EasyMode", s->EasyMode);
+ CfgAddBool(cmsetting, "LockMode", s->LockMode);
+
+ if (IsZero(s->HashedPassword, sizeof(s->HashedPassword)) == false)
+ {
+ CfgAddByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
+ }
+ }
+}
+
+// Create the inner VPN Server
+SERVER *CiNewInnerVPNServer(CLIENT *c)
+{
+ SERVER *s = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ SetNatTLowPriority();
+
+ s = SiNewServerEx(false, true);
+
+ return s;
+}
+
+// Stop the inner VPN Server
+void CiFreeInnerVPNServer(CLIENT *c, SERVER *s)
+{
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SiReleaseServer(s);
+}
+
+// Apply settings of Inner VPN Server
+void CiApplyInnerVPNServerConfig(CLIENT *c)
+{
+}
+
+// Write to the configuration file
+void CiSaveConfigurationFile(CLIENT *c)
+{
+ FOLDER *root;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Do not save the configuration file
+ if(c->NoSaveConfig)
+ {
+ return;
+ }
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+ CiWriteSettingToCfg(c, root);
+
+ SaveCfgRw(c->CfgRw, root);
+
+ CfgDeleteFolder(root);
+}
+
+// Set the CM_SETTING
+bool CtSetCmSetting(CLIENT *c, CM_SETTING *s)
+{
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Copy(c->CmSetting, s, sizeof(CM_SETTING));
+
+ CiSaveConfigurationFile(c);
+
+ return true;
+}
+
+// Get the CM_SETTING
+bool CtGetCmSetting(CLIENT *c, CM_SETTING *s)
+{
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Copy(s, c->CmSetting, sizeof(CM_SETTING));
+
+ return true;
+}
+
+// Get the client version
+bool CtGetClientVersion(CLIENT *c, RPC_CLIENT_VERSION *ver)
+{
+ // Validate arguments
+ if (ver == NULL)
+ {
+ return false;
+ }
+
+ Zero(ver, sizeof(RPC_CLIENT_VERSION));
+ StrCpy(ver->ClientProductName, sizeof(ver->ClientProductName), CEDAR_CLIENT_STR);
+ StrCpy(ver->ClientVersionString, sizeof(ver->ClientVersionString), c->Cedar->VerString);
+ StrCpy(ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString), c->Cedar->BuildInfo);
+ ver->ClientVerInt = c->Cedar->Version;
+ ver->ClientBuildInt = c->Cedar->Build;
+
+
+#ifdef OS_WIN32
+ ver->ProcessId = MsGetProcessId();
+ ver->IsVLanNameRegulated = MsIsInfCatalogRequired();
+
+#endif // OS_WIN32
+
+ ver->OsType = GetOsInfo()->OsType;
+
+ return true;
+}
+
+// Creating a Client object
+CLIENT *CiNewClient()
+{
+ CLIENT *c = ZeroMalloc(sizeof(CLIENT));
+
+// StartCedarLog();
+
+ if (ci_active_sessions_lock == NULL)
+ {
+ ci_active_sessions_lock = NewLock();
+ ci_num_active_sessions = 0;
+ }
+
+
+ c->CmSetting = ZeroMalloc(sizeof(CM_SETTING));
+
+ c->SockList = NewSockList();
+
+ c->lock = NewLock();
+ c->lockForConnect = NewLock();
+ c->ref = NewRef();
+
+ c->Cedar = NewCedar(NULL, NULL);
+
+ c->Cedar->Client = c;
+
+ c->NotifyCancelList = NewList(NULL);
+
+ Hash(c->EncryptedPassword, "", 0, true);
+
+#ifdef OS_WIN32
+ c->GlobalPulse = MsOpenOrCreateGlobalPulse(CLIENT_GLOBAL_PULSE_NAME);
+#endif // OS_WIN32
+
+ if (c->GlobalPulse != NULL)
+ {
+ c->PulseRecvThread = NewThread(CiPulseRecvThread, c);
+ }
+
+ CiLoadIniSettings(c);
+
+ // Log Settings
+ if(c->NoSaveLog == false)
+ {
+ MakeDir(CLIENT_LOG_DIR_NAME);
+ c->Logger = NewLog(CLIENT_LOG_DIR_NAME, CLIENT_LOG_PREFIX, LOG_SWITCH_DAY);
+ }
+
+ CLog(c, "L_LINE");
+ CLog(c, "LC_START_2", CEDAR_CLIENT_STR, c->Cedar->VerString);
+ CLog(c, "LC_START_3", c->Cedar->BuildInfo);
+ CLog(c, "LC_START_1");
+
+#ifdef OS_WIN32
+ {
+ // Initialize the Win32 UI
+ wchar_t tmp[MAX_SIZE];
+ StrToUni(tmp, sizeof(tmp), CEDAR_CLIENT_STR);
+
+ InitWinUi(tmp, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+ }
+#endif // OS_WIN32
+
+ // Initialize the settings
+ CiInitConfiguration(c);
+
+ // Raise the priority
+ OSSetHighPriority();
+
+
+
+#ifdef OS_WIN32
+ // For Win9x, release the DHCP address of all the virtual LAN card
+ if (MsIsNt() == false)
+ {
+ Win32ReleaseAllDhcp9x(true);
+ }
+#endif // OS_WIN32
+
+ CiChangeAllVLanMacAddressIfMachineChanged(c);
+
+ CiChangeAllVLanMacAddressIfCleared(c);
+
+ // Initialize the internal VPN server
+ CiApplyInnerVPNServerConfig(c);
+
+ return c;
+}
+
+// Examine whether two proxy server settings equal
+bool CompareInternetSetting(INTERNET_SETTING *s1, INTERNET_SETTING *s2)
+{
+ // Validate arguments
+ if (s1 == NULL || s2 == NULL)
+ {
+ return false;
+ }
+
+ if (s1->ProxyType != s2->ProxyType)
+ {
+ return false;
+ }
+
+ if (s1->ProxyType == PROXY_DIRECT)
+ {
+ return true;
+ }
+
+ if (s1->ProxyPort != s2->ProxyPort)
+ {
+ return false;
+ }
+
+ if (StrCmp(s1->ProxyHostName, s2->ProxyHostName) != 0)
+ {
+ return false;
+ }
+
+ if (StrCmp(s1->ProxyUsername, s2->ProxyUsername) != 0)
+ {
+ return false;
+ }
+
+ if (StrCmp(s1->ProxyPassword, s2->ProxyPassword) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Send a global pulse
+void CiSendGlobalPulse(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ MsSendGlobalPulse(c->GlobalPulse);
+#endif // OS_WIN32
+}
+
+// Pulse reception thread
+void CiPulseRecvThread(THREAD *thread, void *param)
+{
+#ifdef OS_WIN32
+ CLIENT *c = (CLIENT *)param;
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ if (c->HaltPulseThread)
+ {
+ break;
+ }
+
+ MsWaitForGlobalPulse(c->GlobalPulse, INFINITE);
+
+ if (c->HaltPulseThread)
+ {
+ break;
+ }
+
+ CiNotifyInternal(c);
+ }
+#endif // OS_WIN32
+}
+
+// Clean-up the client
+void CiCleanupClient(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+
+ // Release the settings
+ CiFreeConfiguration(c);
+
+#ifdef OS_WIN32
+ // Release the Win32 UI
+ FreeWinUi();
+#endif // OS_WIN32
+
+ CLog(c, "LC_END");
+ CLog(c, "L_LINE");
+ FreeEraser(c->Eraser);
+ FreeLog(c->Logger);
+ c->Logger = NULL;
+
+
+ ReleaseCedar(c->Cedar);
+
+ DeleteLock(c->lockForConnect);
+ DeleteLock(c->lock);
+
+ c->HaltPulseThread = true;
+
+ if (c->GlobalPulse != NULL)
+ {
+#ifdef OS_WIN32
+ MsSendGlobalPulse(c->GlobalPulse);
+#endif // OS_WIN32
+ }
+
+ if (c->PulseRecvThread != NULL)
+ {
+ WaitThread(c->PulseRecvThread, INFINITE);
+ ReleaseThread(c->PulseRecvThread);
+ }
+
+ if (c->GlobalPulse != NULL)
+ {
+#ifdef OS_WIN32
+ MsCloseGlobalPulse(c->GlobalPulse);
+#endif // OS_WIN32
+ }
+
+ ReleaseList(c->NotifyCancelList);
+
+ FreeSockList(c->SockList);
+
+ Free(c->CmSetting);
+
+
+ Free(c);
+
+#ifdef OS_WIN32
+ // For Win9x, release the DHCP address of all the virtual LAN card
+ if (MsIsNt() == false)
+ {
+ Win32ReleaseAllDhcp9x(true);
+ }
+#endif // OS_WIN32
+
+ StopCedarLog();
+
+ if (ci_active_sessions_lock != NULL)
+ {
+ DeleteLock(ci_active_sessions_lock);
+ ci_active_sessions_lock = NULL;
+
+ ci_num_active_sessions = 0;
+ }
+}
+
+// Increment of the number of active sessions
+void CiIncrementNumActiveSessions()
+{
+ Lock(ci_active_sessions_lock);
+ {
+ ci_num_active_sessions++;
+ }
+ Unlock(ci_active_sessions_lock);
+}
+
+// Decrement of the number of active sessions
+void CiDecrementNumActiveSessions()
+{
+ Lock(ci_active_sessions_lock);
+ {
+ if (ci_num_active_sessions >= 1)
+ {
+ ci_num_active_sessions--;
+ }
+ }
+ Unlock(ci_active_sessions_lock);
+}
+
+// Get the number of active sessions
+UINT CiGetNumActiveSessions()
+{
+ UINT ret;
+
+ Lock(ci_active_sessions_lock);
+ {
+ ret = ci_num_active_sessions;
+ }
+ Unlock(ci_active_sessions_lock);
+
+ return ret;
+}
+
+// Release the client
+void CtReleaseClient(CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ CiCleanupClient(c);
+ }
+}
+
+// Start the operation of the client program
+void CtStartClient()
+{
+ UINT i;
+ LIST *o;
+ if (client != NULL)
+ {
+ // It is already in running
+ return;
+ }
+
+ // OS check
+ CiCheckOs();
+
+#ifdef OS_WIN32
+ RegistWindowsFirewallAll();
+#endif
+
+ // Creating a client
+ client = CiNewClient();
+
+ // Start the Keep
+ CiInitKeep(client);
+
+ // Start the RPC server
+ CiStartRpcServer(client);
+
+ // Start the Saver
+ CiInitSaver(client);
+
+ // Start the startup connection
+ o = NewListFast(NULL);
+ LockList(client->AccountList);
+ {
+ for (i = 0;i < LIST_NUM(client->AccountList);i++)
+ {
+ ACCOUNT *a = LIST_DATA(client->AccountList, i);
+ Lock(a->lock);
+ {
+ if (a->StartupAccount)
+ {
+ Add(o, CopyUniStr(a->ClientOption->AccountName));
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+ UnlockList(client->AccountList);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ RPC_CLIENT_CONNECT c;
+ Zero(&c, sizeof(c));
+ UniStrCpy(c.AccountName, sizeof(c.AccountName), s);
+ CtConnect(client, &c);
+ Free(s);
+ }
+ ReleaseList(o);
+}
+
+// Stop the operation of the client program
+void CtStopClient()
+{
+ UINT i, num;
+ ACCOUNT **account_list;
+ if (client == NULL)
+ {
+ // It is not running yet
+ return;
+ }
+
+ // Halting flag
+ client->Halt = true;
+
+ // Disconnect all the RPC
+ CiStopRpcServer(client);
+
+ // Exit the client notification service
+ CncExit();
+
+ // Exit the Keep
+ CiFreeKeep(client);
+
+ // Disconnect all accounts connected
+ LockList(client->AccountList);
+ {
+ num = LIST_NUM(client->AccountList);
+ account_list = ToArray(client->AccountList);
+ }
+ UnlockList(client->AccountList);
+
+ for (i = 0;i < num;i++)
+ {
+ ACCOUNT *a = account_list[i];
+ SESSION *s = NULL;
+
+ Lock(a->lock);
+ {
+ if (a->ClientSession != NULL)
+ {
+ s = a->ClientSession;
+ AddRef(s->ref);
+ }
+ }
+ Unlock(a->lock);
+
+ if (s != NULL)
+ {
+ StopSession(s);
+ ReleaseSession(s);
+ Lock(a->lock);
+ {
+ if (a->ClientSession != NULL)
+ {
+ ReleaseSession(a->ClientSession);
+ a->ClientSession = NULL;
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+
+ Free(account_list);
+
+ // Stop the Saver
+ CiFreeSaver(client);
+
+ // Release the client
+ CtReleaseClient(client);
+ client = NULL;
+}
+
+// OS check
+void CiCheckOs()
+{
+ // Get the OS type
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS(info->OsType))
+ {
+ bool ok = IS_CLIENT_SUPPORTED_OS(info->OsType);
+
+ if (ok == false)
+ {
+ Alert(
+ CEDAR_PRODUCT_STR " VPN Client doesn't support this Windows Operating System.\n"
+ CEDAR_PRODUCT_STR " VPN Client requires Windows 98, Windows Me, Windows 2000, Windows XP, Windows Server 2003 or Greater.\n\n"
+ "Please contact your system administrator.", CEDAR_PRODUCT_STR " VPN Client");
+ exit(0);
+ }
+ }
+}
+
+// Get the client object
+CLIENT *CtGetClient()
+{
+ if (client == NULL)
+ {
+ return NULL;
+ }
+
+ AddRef(client->ref);
+
+ return client;
+}
+
+// Client status indicator
+void CiClientStatusPrinter(SESSION *s, wchar_t *status)
+{
+#ifdef OS_WIN32
+ ACCOUNT *a;
+ // Validate arguments
+ if (s == NULL || status == NULL)
+ {
+ return;
+ }
+
+ a = s->Account;
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (UniStrCmpi(status, L"init") == 0)
+ {
+ if (a->StatusWindow == NULL && s->Win32HideConnectWindow == false)
+ {
+ a->StatusWindow = CncStatusPrinterWindowStart(s);
+ }
+ }
+ else if (UniStrCmpi(status, L"free") == 0)
+ {
+ if (a->StatusWindow != NULL)
+ {
+ CncStatusPrinterWindowStop(a->StatusWindow);
+ a->StatusWindow = NULL;
+ }
+ }
+ else
+ {
+ if (a->StatusWindow != NULL)
+ {
+ CncStatusPrinterWindowPrint(a->StatusWindow, status);
+ }
+ }
+#else // OS_WIN32
+ UniPrint(L"Status: %s\n", status);
+#endif // OS_WIN32
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Client.h b/src/Cedar/Client.h
new file mode 100644
index 00000000..345f8e76
--- /dev/null
+++ b/src/Cedar/Client.h
@@ -0,0 +1,849 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Client.h
+// Header of Client.c
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#define CLIENT_CONFIG_PORT GC_CLIENT_CONFIG_PORT // Client port number
+#define CLIENT_NOTIFY_PORT GC_CLIENT_NOTIFY_PORT // Client notification port number
+#define CLIENT_WAIT_CN_READY_TIMEOUT (10 * 1000) // Standby time to start the client notification service
+
+
+// Check whether the client can run on the specified OS_TYPE
+#define IS_CLIENT_SUPPORTED_OS(t) \
+ ((OS_IS_WINDOWS_NT(t) && GET_KETA(t, 100) >= 2) || (OS_IS_WINDOWS_9X(t)))
+
+
+// Constants
+#define CLIENT_CONFIG_FILE_NAME "@vpn_client.config"
+#define CLIENT_DEFAULT_KEEPALIVE_HOST "keepalive.softether.org"
+#define CLIENT_DEFAULT_KEEPALIVE_PORT 80
+#define CLIENT_DEFAULT_KEEPALIVE_INTERVAL KEEP_INTERVAL_DEFAULT
+
+#define CLIENT_RPC_MODE_NOTIFY 0
+#define CLIENT_RPC_MODE_MANAGEMENT 1
+#define CLIENT_RPC_MODE_SHORTCUT 2
+#define CLIENT_RPC_MODE_SHORTCUT_DISCONNECT 3
+
+#define CLIENT_MACOS_TAP_NAME "tap0"
+
+#define CLIENT_SAVER_INTERVAL (30 * 1000)
+
+#define CLIENT_NOTIFY_SERVICE_INSTANCENAME GC_SW_SOFTETHER_PREFIX "vpnclient_uihelper"
+
+#define CLIENT_WIN32_EXE_FILENAME "vpnclient.exe"
+#define CLIENT_WIN32_EXE_FILENAME_X64 "vpnclient_x64.exe"
+#define CLIENT_WIN32_EXE_FILENAME_IA64 "vpnclient_ia64.exe"
+
+#define CLIENT_CUSTOM_INI_FILENAME "@custom.ini"
+
+#define CLIENT_GLOBAL_PULSE_NAME "clientglobalpulse"
+
+
+// List of virtual LAN cards in UNIX
+struct UNIX_VLAN
+{
+ bool Enabled; // Enable flag
+ char Name[MAX_SIZE]; // Name
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+};
+
+// Account
+struct ACCOUNT
+{
+ // Static data
+ CLIENT_OPTION *ClientOption; // Client Option
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ bool CheckServerCert; // Check the server certificate
+ X *ServerCert; // Server certificate
+ bool StartupAccount; // Start-up account
+ UCHAR ShortcutKey[SHA1_SIZE]; // Key
+ UINT64 CreateDateTime; // Creation date and time
+ UINT64 UpdateDateTime; // Updating date
+ UINT64 LastConnectDateTime; // Last connection date and time
+
+ // Dynamic data
+ LOCK *lock; // Lock
+ SESSION *ClientSession; // Client session
+ CLIENT_STATUS_PRINTER *StatusPrinter; // Status indicator
+
+ SOCK *StatusWindow; // Status window
+};
+
+// Client Settings
+struct CLIENT_CONFIG
+{
+ bool AllowRemoteConfig; // Allow the remote configuration
+ bool UseKeepConnect; // Keep connected to the Internet
+ char KeepConnectHost[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT KeepConnectPort; // Port number
+ UINT KeepConnectProtocol; // Protocol
+ UINT KeepConnectInterval; // Interval
+ bool NoChangeWcmNetworkSettingOnWindows8; // Don't change the WCM network settings on Windows 8
+};
+
+// Version acquisition
+struct RPC_CLIENT_VERSION
+{
+ char ClientProductName[128]; // Client product name
+ char ClientVersionString[128]; // Client version string
+ char ClientBuildInfoString[128]; // Build client information string
+ UINT ClientVerInt; // Client version integer value
+ UINT ClientBuildInt; // Client build number integer value
+ UINT ProcessId; // Process ID
+ UINT OsType; // OS type
+ bool IsVLanNameRegulated; // Whether a virtual LAN card name must be "VLAN" + number
+ bool IsVgcSupported; // Whether the VPN Gate Client is supported
+ bool ShowVgcLink; // Display a VPN Gate Client link
+ char ClientId[128]; // Client OD
+};
+
+// Password Setting
+struct RPC_CLIENT_PASSWORD
+{
+ char Password[MAX_PASSWORD_LEN + 1]; // Password
+ bool PasswordRemoteOnly; // The password is required only remote access
+};
+
+// Get the password setting
+struct RPC_CLIENT_PASSWORD_SETTING
+{
+ bool IsPasswordPresented; // Password exists
+ bool PasswordRemoteOnly; // The password is required only remote access
+};
+
+// Certificate enumeration item
+struct RPC_CLIENT_ENUM_CA_ITEM
+{
+ UINT Key; // Certificate key
+ wchar_t SubjectName[MAX_SIZE]; // Issued to
+ wchar_t IssuerName[MAX_SIZE]; // Issuer
+ UINT64 Expires; // Expiration date
+};
+
+// Certificate enumeration
+struct RPC_CLIENT_ENUM_CA
+{
+ UINT NumItem; // Number of items
+ RPC_CLIENT_ENUM_CA_ITEM **Items; // Item
+};
+
+// Certificate item
+struct RPC_CERT
+{
+ X *x; // Certificate
+};
+
+// Delete the certificate
+struct RPC_CLIENT_DELETE_CA
+{
+ UINT Key; // Certificate key
+};
+
+// Get the certificate
+struct RPC_GET_CA
+{
+ UINT Key; // Certificate key
+ X *x; // Certificate
+};
+
+// Get the issuer
+struct RPC_GET_ISSUER
+{
+ X *x; // Certificate
+ X *issuer_x; // Issuer
+};
+
+// Secure device enumeration item
+struct RPC_CLIENT_ENUM_SECURE_ITEM
+{
+ UINT DeviceId; // Device ID
+ UINT Type; // Type
+ char DeviceName[MAX_SIZE]; // Device name
+ char Manufacturer[MAX_SIZE]; // Manufacturer
+};
+
+// Enumeration of secure devices
+struct RPC_CLIENT_ENUM_SECURE
+{
+ UINT NumItem; // Number of items
+ RPC_CLIENT_ENUM_SECURE_ITEM **Items; // Item
+};
+
+// Specify a secure device
+struct RPC_USE_SECURE
+{
+ UINT DeviceId; // Device ID
+};
+
+// Enumerate objects in the secure device
+struct RPC_ENUM_OBJECT_IN_SECURE
+{
+ UINT hWnd; // Window handle
+ UINT NumItem; // Number of items
+ char **ItemName; // Item name
+ bool *ItemType; // Type (true = secret key, false = public key)
+};
+
+// Create a virtual LAN
+struct RPC_CLIENT_CREATE_VLAN
+{
+ char DeviceName[MAX_SIZE]; // Device name
+};
+
+// Get a Virtual LAN information
+struct RPC_CLIENT_GET_VLAN
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ bool Enabled; // Flag of whether it works or not
+ char MacAddress[MAX_SIZE]; // MAC address
+ char Version[MAX_SIZE]; // Version
+ char FileName[MAX_SIZE]; // Driver file name
+ char Guid[MAX_SIZE]; // GUID
+};
+
+// Set the virtual LAN information
+struct RPC_CLIENT_SET_VLAN
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ char MacAddress[MAX_SIZE]; // MAC address
+};
+
+// Virtual LAN enumeration item
+struct RPC_CLIENT_ENUM_VLAN_ITEM
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ bool Enabled; // Operation flag
+ char MacAddress[MAX_SIZE]; // MAC address
+ char Version[MAX_SIZE]; // Version
+};
+
+// Enumerate the virtual LANs
+struct RPC_CLIENT_ENUM_VLAN
+{
+ UINT NumItem; // Item count
+ RPC_CLIENT_ENUM_VLAN_ITEM **Items; // Item
+};
+
+// Create an account
+struct RPC_CLIENT_CREATE_ACCOUNT
+{
+ CLIENT_OPTION *ClientOption; // Client Option
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ bool StartupAccount; // Startup account
+ bool CheckServerCert; // Checking of the server certificate
+ X *ServerCert; // Server certificate
+ UCHAR ShortcutKey[SHA1_SIZE]; // Shortcut Key
+};
+
+// Enumeration item of account
+struct RPC_CLIENT_ENUM_ACCOUNT_ITEM
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ char UserName[MAX_USERNAME_LEN + 1]; // User name
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ char DeviceName[MAX_DEVICE_NAME_LEN + 1]; // Device name
+ UINT ProxyType; // Type of proxy connection
+ char ProxyName[MAX_HOST_NAME_LEN + 1]; // Host name
+ bool Active; // Operation flag
+ bool Connected; // Connection completion flag
+ bool StartupAccount; // Startup account
+ UINT Port; // Port number (Ver 3.0 or later)
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name (Ver 3.0 or later)
+ UINT64 CreateDateTime; // Creation date and time (Ver 3.0 or later)
+ UINT64 UpdateDateTime; // Modified date (Ver 3.0 or later)
+ UINT64 LastConnectDateTime; // Last connection date and time (Ver 3.0 or later)
+ UINT tmp1; // Temporary data
+};
+
+// Enumeration of accounts
+struct RPC_CLIENT_ENUM_ACCOUNT
+{
+ UINT NumItem; // Item count
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM **Items; // Items
+};
+
+// Delete the Account
+struct RPC_CLIENT_DELETE_ACCOUNT
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+};
+
+// Change the account name
+struct RPC_RENAME_ACCOUNT
+{
+ wchar_t OldName[MAX_ACCOUNT_NAME_LEN + 1]; // Old name
+ wchar_t NewName[MAX_ACCOUNT_NAME_LEN + 1]; // New Name
+};
+
+// Get the account
+struct RPC_CLIENT_GET_ACCOUNT
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ CLIENT_OPTION *ClientOption; // Client Option
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ bool StartupAccount; // Startup account
+ bool CheckServerCert; // Check the server certificate
+ X *ServerCert; // Server certificate
+ UCHAR ShortcutKey[SHA1_SIZE]; // Shortcut Key
+ UINT64 CreateDateTime; // Creation date and time (Ver 3.0 or later)
+ UINT64 UpdateDateTime; // Modified date (Ver 3.0 or later)
+ UINT64 LastConnectDateTime; // Last connection date and time (Ver 3.0 or later)
+};
+
+// Connection
+struct RPC_CLIENT_CONNECT
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+};
+
+// Get the Connection status
+struct RPC_CLIENT_GET_CONNECTION_STATUS
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ bool Active; // Operation flag
+ bool Connected; // Connected flag
+ UINT SessionStatus; // Session status
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT ServerPort; // Port number of the server
+ char ServerProductName[MAX_SIZE]; // Server product name
+ UINT ServerProductVer; // Server product version
+ UINT ServerProductBuild; // Server product build number
+ X *ServerX; // Server certificate
+ X *ClientX; // Client certificate
+ UINT64 StartTime; // Connection start time
+ UINT64 FirstConnectionEstablisiedTime; // Connection completion time of the first connection
+ UINT64 CurrentConnectionEstablishTime; // Connection completion time of this connection
+ UINT NumConnectionsEatablished; // Number of connections have been established so far
+ bool HalfConnection; // Half-connection
+ bool QoS; // VoIP / QoS
+ UINT MaxTcpConnections; // Maximum number of the TCP connections
+ UINT NumTcpConnections; // Number of current TCP connections
+ UINT NumTcpConnectionsUpload; // Number of inbound connections
+ UINT NumTcpConnectionsDownload; // Number of outbound connections
+ bool UseEncrypt; // Use of encryption
+ char CipherName[32]; // Cipher algorithm name
+ char ProtocolName[64]; // Protocol name
+ bool UseCompress; // Use of compression
+ bool IsRUDPSession; // R-UDP session
+ char UnderlayProtocol[64]; // Physical communication protocol
+ bool IsUdpAccelerationEnabled; // The UDP acceleration is enabled
+ bool IsUsingUdpAcceleration; // Using the UDP acceleration function
+ char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
+ char ConnectionName[MAX_CONNECTION_NAME_LEN + 1]; // Connection name
+ UCHAR SessionKey[SHA1_SIZE]; // Session key
+ POLICY Policy; // Policy
+ UINT64 TotalSendSize; // Total transmitted data size
+ UINT64 TotalRecvSize; // Total received data size
+ UINT64 TotalSendSizeReal; // Total transmitted data size (no compression)
+ UINT64 TotalRecvSizeReal; // Total received data size (no compression)
+ TRAFFIC Traffic; // Traffic data
+ bool IsBridgeMode; // Bridge Mode
+ bool IsMonitorMode; // Monitor mode
+ UINT VLanId; // VLAN ID
+};
+
+
+// RPC connection
+struct CLIENT_RPC_CONNECTION
+{
+ struct CLIENT *Client; // Client
+ bool RpcMode; // True: RPC mode, false: notification mode
+ THREAD *Thread; // Processing thread
+ SOCK *Sock; // Socket
+};
+
+// Client object
+struct CLIENT
+{
+ LOCK *lock; // Lock
+ LOCK *lockForConnect; // Lock to be used in the CtConnect
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ volatile bool Halt; // Halting flag
+ UINT Err; // Error code
+ CFG_RW *CfgRw; // Configuration file R/W
+ LIST *AccountList; // Account list
+ UCHAR EncryptedPassword[SHA1_SIZE]; // Password
+ bool PasswordRemoteOnly; // Password is required only remote access
+ UINT UseSecureDeviceId; // Secure device ID to be used
+ CLIENT_CONFIG Config; // Client Settings
+ LIST *RpcConnectionList; // RPC connection list
+ SOCK *RpcListener; // RPC listener
+ THREAD *RpcThread; // RPC thread
+ LOCK *HelperLock; // Auxiliary lock
+ THREAD *SaverThread; // Saver thread
+ EVENT *SaverHalter; // The event to stop the Saver thread
+ LIST *NotifyCancelList; // Notification event list
+ KEEP *Keep; // Keep Connection
+ LIST *UnixVLanList; // List of virtual LAN cards in UNIX
+ LOG *Logger; // Logger
+ bool DontSavePassword; // Flag for not to save the password
+ ERASER *Eraser; // Eraser
+ SOCKLIST *SockList; // Socket list
+ CM_SETTING *CmSetting; // CM configuration
+ void *GlobalPulse; // Global pulse
+ THREAD *PulseRecvThread; // Pulse reception thread
+ volatile bool HaltPulseThread; // Stop flag for the pulse reception thread
+ bool NoSaveLog; // Do not save the log
+ bool NoSaveConfig; // Do not save the settings
+ INTERNET_SETTING CommonProxySetting; // Common proxy settings
+
+};
+
+// Notification to the remote client
+struct RPC_CLIENT_NOTIFY
+{
+ UINT NotifyCode; // Code
+};
+
+// Type of notification
+#define CLIENT_NOTIFY_ACCOUNT_CHANGED 1 // Account change notification
+#define CLIENT_NOTIFY_VLAN_CHANGED 2 // Virtual LAN card change notification
+
+// Remote client
+struct REMOTE_CLIENT
+{
+ RPC *Rpc;
+ UINT OsType;
+ bool Unix;
+ bool Win9x;
+ UINT ProcessId;
+ UINT ClientBuildInt;
+ bool IsVgcSupported;
+ bool ShowVgcLink;
+ char ClientId[128];
+};
+
+// Notification client
+struct NOTIFY_CLIENT
+{
+ SOCK *Sock;
+};
+
+// CM configuration
+struct CM_SETTING
+{
+ bool EasyMode; // Simple mode
+ bool LockMode; // Setting lock mode
+ UCHAR HashedPassword[SHA1_SIZE]; // Password
+};
+
+
+
+
+// Function prototype
+REMOTE_CLIENT *CcConnectRpc(char *server_name, char *password, bool *bad_pass, bool *no_remote, UINT wait_retry);
+REMOTE_CLIENT *CcConnectRpcEx(char *server_name, char *password, bool *bad_pass, bool *no_remote, UCHAR *key, UINT *key_error_code, bool shortcut_disconnect, UINT wait_retry);
+UINT CcShortcut(UCHAR *key);
+UINT CcShortcutDisconnect(UCHAR *key);
+void CcDisconnectRpc(REMOTE_CLIENT *rc);
+NOTIFY_CLIENT *CcConnectNotify(REMOTE_CLIENT *rc);
+void CcDisconnectNotify(NOTIFY_CLIENT *n);
+void CcStopNotify(NOTIFY_CLIENT *n);
+bool CcWaitNotify(NOTIFY_CLIENT *n);
+UINT CcGetClientVersion(REMOTE_CLIENT *r, RPC_CLIENT_VERSION *a);
+UINT CcSetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a);
+UINT CcGetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a);
+UINT CcSetPassword(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD *pass);
+UINT CcGetPasswordSetting(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD_SETTING *a);
+UINT CcEnumCa(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_CA *e);
+UINT CcAddCa(REMOTE_CLIENT *r, RPC_CERT *cert);
+UINT CcDeleteCa(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_CA *p);
+UINT CcGetCa(REMOTE_CLIENT *r, RPC_GET_CA *get);
+UINT CcEnumSecure(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_SECURE *e);
+UINT CcUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec);
+UINT CcGetUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec);
+UINT CcEnumObjectInSecure(REMOTE_CLIENT *r, RPC_ENUM_OBJECT_IN_SECURE *e);
+UINT CcCreateVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create);
+UINT CcUpgradeVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create);
+UINT CcGetVLan(REMOTE_CLIENT *r, RPC_CLIENT_GET_VLAN *get);
+UINT CcSetVLan(REMOTE_CLIENT *r, RPC_CLIENT_SET_VLAN *set);
+UINT CcEnumVLan(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_VLAN *e);
+UINT CcDeleteVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *d);
+UINT CcEnableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan);
+UINT CcDisableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan);
+UINT CcCreateAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a);
+UINT CcEnumAccount(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_ACCOUNT *e);
+UINT CcDeleteAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a);
+UINT CcSetAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a);
+UINT CcGetAccount(REMOTE_CLIENT *r, RPC_CLIENT_GET_ACCOUNT *a);
+UINT CcRenameAccount(REMOTE_CLIENT *r, RPC_RENAME_ACCOUNT *rename);
+UINT CcSetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o);
+UINT CcGetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o);
+UINT CcConnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect);
+UINT CcDisconnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect);
+UINT CcGetAccountStatus(REMOTE_CLIENT *r, RPC_CLIENT_GET_CONNECTION_STATUS *st);
+UINT CcSetStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a);
+UINT CcRemoveStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a);
+UINT CcGetIssuer(REMOTE_CLIENT *r, RPC_GET_ISSUER *a);
+UINT CcGetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a);
+UINT CcSetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a);
+
+
+void CcSetServiceToForegroundProcess(REMOTE_CLIENT *r);
+char *CiGetFirstVLan(CLIENT *c);
+void CiNormalizeAccountVLan(CLIENT *c);
+
+bool CompareInternetSetting(INTERNET_SETTING *s1, INTERNET_SETTING *s2);
+
+
+void CnStart();
+void CnListenerProc(THREAD *thread, void *param);
+
+void CnReleaseSocket(SOCK *s, PACK *p);
+
+void CnStatusPrinter(SOCK *s, PACK *p);
+void Win32CnStatusPrinter(SOCK *s, PACK *p);
+
+void CnConnectErrorDlg(SOCK *s, PACK *p);
+void Win32CnConnectErrorDlg(SOCK *s, PACK *p);
+void Win32CnConnectErrorDlgThreadProc(THREAD *thread, void *param);
+
+void CnPasswordDlg(SOCK *s, PACK *p);
+void Win32CnPasswordDlg(SOCK *s, PACK *p);
+void Win32CnPasswordDlgThreadProc(THREAD *thread, void *param);
+
+void CnMsgDlg(SOCK *s, PACK *p);
+void Win32CnMsgDlg(SOCK *s, PACK *p);
+void Win32CnMsgDlgThreadProc(THREAD *thread, void *param);
+
+void CnNicInfo(SOCK *s, PACK *p);
+void Win32CnNicInfo(SOCK *s, PACK *p);
+void Win32CnNicInfoThreadProc(THREAD *thread, void *param);
+
+void CnCheckCert(SOCK *s, PACK *p);
+void Win32CnCheckCert(SOCK *s, PACK *p);
+void Win32CnCheckCertThreadProc(THREAD *thread, void *param);
+
+void CnExecDriverInstaller(SOCK *s, PACK *p);
+void Win32CnExecDriverInstaller(SOCK *s, PACK *p);
+
+bool CnCheckAlreadyExists(bool lock);
+bool CnIsCnServiceReady();
+void CnWaitForCnServiceReady();
+
+void CnSecureSign(SOCK *s, PACK *p);
+
+SOCK *CncConnect();
+SOCK *CncConnectEx(UINT timeout);
+void CncReleaseSocket();
+void CncExit();
+UINT CncGetSessionId();
+bool CncExecDriverInstaller(char *arg);
+SOCK *CncStatusPrinterWindowStart(SESSION *s);
+void CncStatusPrinterWindowPrint(SOCK *s, wchar_t *str);
+void CncStatusPrinterWindowStop(SOCK *s);
+void CncStatusPrinterWindowThreadProc(THREAD *thread, void *param);
+bool CncConnectErrorDlg(SESSION *session, UI_CONNECTERROR_DLG *dlg);
+void CncConnectErrorDlgHaltThread(THREAD *thread, void *param);
+bool CncPasswordDlg(SESSION *session, UI_PASSWORD_DLG *dlg);
+void CncPasswordDlgHaltThread(THREAD *thread, void *param);
+void CncCheckCert(SESSION *session, UI_CHECKCERT *dlg);
+void CncCheckCertHaltThread(THREAD *thread, void *param);
+bool CncSecureSignDlg(SECURE_SIGN *sign);
+SOCK *CncMsgDlg(UI_MSG_DLG *dlg);
+void CndMsgDlgFree(SOCK *s);
+SOCK *CncNicInfo(UI_NICINFO *info);
+void CncNicInfoFree(SOCK *s);
+
+void CtStartClient();
+void CtStopClient();
+CLIENT *CtGetClient();
+void CtReleaseClient(CLIENT *c);
+bool CtGetClientVersion(CLIENT *c, RPC_CLIENT_VERSION *ver);
+bool CtGetCmSetting(CLIENT *c, CM_SETTING *s);
+bool CtSetCmSetting(CLIENT *c, CM_SETTING *s);
+bool CtSetPassword(CLIENT *c, RPC_CLIENT_PASSWORD *pass);
+bool CtGetPasswordSetting(CLIENT *c, RPC_CLIENT_PASSWORD_SETTING *a);
+bool CtEnumCa(CLIENT *c, RPC_CLIENT_ENUM_CA *e);
+bool CtAddCa(CLIENT *c, RPC_CERT *cert);
+bool CtDeleteCa(CLIENT *c, RPC_CLIENT_DELETE_CA *p);
+bool CtGetCa(CLIENT *c, RPC_GET_CA *get);
+bool CtEnumSecure(CLIENT *c, RPC_CLIENT_ENUM_SECURE *e);
+bool CtUseSecure(CLIENT *c, RPC_USE_SECURE *sec);
+bool CtGetUseSecure(CLIENT *c, RPC_USE_SECURE *sec);
+bool CtEnumObjectInSecure(CLIENT *c, RPC_ENUM_OBJECT_IN_SECURE *e);
+bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create);
+bool CtUpgradeVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create);
+bool CtGetVLan(CLIENT *c, RPC_CLIENT_GET_VLAN *get);
+bool CtSetVLan(CLIENT *c, RPC_CLIENT_SET_VLAN *set);
+bool CtEnumVLan(CLIENT *c, RPC_CLIENT_ENUM_VLAN *e);
+bool CtDeleteVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *d);
+bool CtEnableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan);
+bool CtDisableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan);
+bool CtCreateAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner);
+bool CtEnumAccount(CLIENT *c, RPC_CLIENT_ENUM_ACCOUNT *e);
+bool CtDeleteAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner);
+bool CtSetAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner);
+bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a);
+bool CtRenameAccount(CLIENT *c, RPC_RENAME_ACCOUNT *rename, bool inner);
+bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o);
+bool CtGetClientConfig(CLIENT *c, CLIENT_CONFIG *o);
+bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect);
+bool CtDisconnect(CLIENT *c, RPC_CLIENT_CONNECT *connect, bool inner);
+bool CtGetAccountStatus(CLIENT *c, RPC_CLIENT_GET_CONNECTION_STATUS *st);
+bool CtSetStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner);
+bool CtRemoveStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a);
+bool CtGetIssuer(CLIENT *c, RPC_GET_ISSUER *a);
+bool CtGetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a);
+bool CtSetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a);
+
+
+// Internal function prototype
+void CiSendGlobalPulse(CLIENT *c);
+void CiPulseRecvThread(THREAD *thread, void *param);
+char *CiGetVpnClientExeFileName();
+void CiServerThread(THREAD *t, void *param);
+void CiInitSaver(CLIENT *c);
+void CiFreeSaver(CLIENT *c);
+void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s);
+PACK *CiRpcDispatch(RPC *rpc, char *name, PACK *p);
+void CiRpcAccepted(CLIENT *c, SOCK *s);
+void CiNotifyMain(CLIENT *c, SOCK *s);
+void CiRpcAcceptThread(THREAD *thread, void *param);
+void CiRpcServerThread(THREAD *thread, void *param);
+void CiStartRpcServer(CLIENT *c);
+void CiStopRpcServer(CLIENT *c);
+CLIENT_OPTION *CiLoadClientOption(FOLDER *f);
+CLIENT_AUTH *CiLoadClientAuth(FOLDER *f);
+ACCOUNT *CiLoadClientAccount(FOLDER *f);
+void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f);
+void CiLoadAccountDatabase(CLIENT *c, FOLDER *f);
+void CiLoadCAList(CLIENT *c, FOLDER *f);
+void CiLoadCACert(CLIENT *c, FOLDER *f);
+void CiLoadVLanList(CLIENT *c, FOLDER *f);
+void CiLoadVLan(CLIENT *c, FOLDER *f);
+bool CiReadSettingFromCfg(CLIENT *c, FOLDER *root);
+void CiWriteAccountDatabase(CLIENT *c, FOLDER *f);
+void CiWriteAccountData(FOLDER *f, ACCOUNT *a);
+void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o);
+void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a);
+void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config);
+void CiWriteSettingToCfg(CLIENT *c, FOLDER *root);
+void CiWriteCAList(CLIENT *c, FOLDER *f);
+void CiWriteCACert(CLIENT *c, FOLDER *f, X *x);
+void CiWriteVLanList(CLIENT *c, FOLDER *f);
+void CiWriteVLan(CLIENT *c, FOLDER *f, UNIX_VLAN *v);
+void CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st);
+bool CiCheckCertProc(SESSION *s, CONNECTION *c, X *server_x, bool *expired);
+bool CiSecureSignProc(SESSION *s, CONNECTION *c, SECURE_SIGN *sign);
+bool Win32CiSecureSign(SECURE_SIGN *sign);
+void CiFreeClientAuth(CLIENT_AUTH *auth);
+void CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *a);
+void CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT *a);
+void CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN *e);
+void CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e);
+void CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA *e);
+void CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *a);
+void CiFreeGetCa(RPC_GET_CA *a);
+void CiFreeGetIssuer(RPC_GET_ISSUER *a);
+void CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *a);
+void CiSetError(CLIENT *c, UINT err);
+void CiCheckOs();
+CLIENT *CiNewClient();
+void CiCleanupClient(CLIENT *c);
+bool CiLoadConfigurationFile(CLIENT *c);
+void CiSaveConfigurationFile(CLIENT *c);
+void CiInitConfiguration(CLIENT *c);
+void CiSetVLanToDefault(CLIENT *c);
+bool CiIsVLan(CLIENT *c, char *name);
+void CiFreeConfiguration(CLIENT *c);
+int CiCompareAccount(void *p1, void *p2);
+void CiFreeAccount(ACCOUNT *a);
+void CiNotify(CLIENT *c);
+void CiNotifyInternal(CLIENT *c);
+void CiClientStatusPrinter(SESSION *s, wchar_t *status);
+void CiInitKeep(CLIENT *c);
+void CiFreeKeep(CLIENT *c);
+int CiCompareUnixVLan(void *p1, void *p2);
+BUF *CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT *t);
+RPC_CLIENT_CREATE_ACCOUNT *CiCfgToAccount(BUF *b);
+void CiChangeAllVLanMacAddressIfCleared(CLIENT *c);
+void CiChangeAllVLanMacAddress(CLIENT *c);
+void CiChangeAllVLanMacAddressIfMachineChanged(CLIENT *c);
+bool CiReadLastMachineHash(void *data);
+bool CiWriteLastMachineHash(void *data);
+void CiGetCurrentMachineHash(void *data);
+void CiGetCurrentMachineHashOld(void *data);
+void CiGetCurrentMachineHashNew(void *data);
+LIST *CiLoadIni();
+void CiFreeIni(LIST *o);
+void CiLoadIniSettings(CLIENT *c);
+bool CiLoadConfigFilePathFromIni(char *path, UINT size);
+int CiCompareClientAccountEnumItemByLastConnectDateTime(void *p1, void *p2);
+bool CiIsValidVLanRegulatedName(char *name);
+void CiGenerateVLanRegulatedName(char *name, UINT size, UINT i);
+bool CiGetNextRecommendedVLanName(REMOTE_CLIENT *r, char *name, UINT size);
+void CiDisableWcmNetworkMinimize(CLIENT *c);
+bool CiTryToParseAccount(BUF *b);
+bool CiTryToParseAccountFile(wchar_t *name);
+bool CiEraseSensitiveInAccount(BUF *b);
+bool CiHasAccountSensitiveInformation(BUF *b);
+bool CiHasAccountSensitiveInformationFile(wchar_t *name);
+void CiApplyInnerVPNServerConfig(CLIENT *c);
+SERVER *CiNewInnerVPNServer(CLIENT *c);
+void CiFreeInnerVPNServer(CLIENT *c, SERVER *s);
+void CiIncrementNumActiveSessions();
+void CiDecrementNumActiveSessions();
+UINT CiGetNumActiveSessions();
+
+BUF *EncryptPassword(char *password);
+BUF *EncryptPassword2(char *password);
+char *DecryptPassword(BUF *b);
+char *DecryptPassword2(BUF *b);
+
+void InRpcGetIssuer(RPC_GET_ISSUER *c, PACK *p);
+void OutRpcGetIssuer(PACK *p, RPC_GET_ISSUER *c);
+void InRpcClientVersion(RPC_CLIENT_VERSION *ver, PACK *p);
+void OutRpcClientVersion(PACK *p, RPC_CLIENT_VERSION *ver);
+void InRpcClientPassword(RPC_CLIENT_PASSWORD *pw, PACK *p);
+void OutRpcClientPassword(PACK *p, RPC_CLIENT_PASSWORD *pw);
+void InRpcClientEnumCa(RPC_CLIENT_ENUM_CA *e, PACK *p);
+void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e);
+void InRpcCert(RPC_CERT *c, PACK *p);
+void OutRpcCert(PACK *p, RPC_CERT *c);
+void InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA *c, PACK *p);
+void OutRpcClientDeleteCa(PACK *p, RPC_CLIENT_DELETE_CA *c);
+void InRpcGetCa(RPC_GET_CA *c, PACK *p);
+void OutRpcGetCa(PACK *p, RPC_GET_CA *c);
+void InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e, PACK *p);
+void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e);
+void InRpcUseSecure(RPC_USE_SECURE *u, PACK *p);
+void OutRpcUseSecure(PACK *p, RPC_USE_SECURE *u);
+void InRpcEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *e, PACK *p);
+void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e);
+void InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN *v, PACK *p);
+void OutRpcCreateVLan(PACK *p, RPC_CLIENT_CREATE_VLAN *v);
+void InRpcClientGetVLan(RPC_CLIENT_GET_VLAN *v, PACK *p);
+void OutRpcClientGetVLan(PACK *p, RPC_CLIENT_GET_VLAN *v);
+void InRpcClientSetVLan(RPC_CLIENT_SET_VLAN *v, PACK *p);
+void OutRpcClientSetVLan(PACK *p, RPC_CLIENT_SET_VLAN *v);
+void InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN *v, PACK *p);
+void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v);
+void InRpcClientOption(CLIENT_OPTION *c, PACK *p);
+void OutRpcClientOption(PACK *p, CLIENT_OPTION *c);
+void InRpcClientAuth(CLIENT_AUTH *c, PACK *p);
+void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c);
+void InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *c, PACK *p);
+void OutRpcClientCreateAccount(PACK *p, RPC_CLIENT_CREATE_ACCOUNT *c);
+void InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *e, PACK *p);
+void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e);
+void InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT *a, PACK *p);
+void OutRpcClientDeleteAccount(PACK *p, RPC_CLIENT_DELETE_ACCOUNT *a);
+void InRpcRenameAccount(RPC_RENAME_ACCOUNT *a, PACK *p);
+void OutRpcRenameAccount(PACK *p, RPC_RENAME_ACCOUNT *a);
+void InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT *c, PACK *p);
+void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c);
+void InRpcClientConnect(RPC_CLIENT_CONNECT *c, PACK *p);
+void OutRpcClientConnect(PACK *p, RPC_CLIENT_CONNECT *c);
+void InRpcPolicy(POLICY *o, PACK *p);
+void OutRpcPolicy(PACK *p, POLICY *o);
+void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p);
+void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *c);
+void InRpcClientNotify(RPC_CLIENT_NOTIFY *n, PACK *p);
+void OutRpcClientNotify(PACK *p, RPC_CLIENT_NOTIFY *n);
+void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p);
+void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c);
+void InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING *a, PACK *p);
+void OutRpcClientPasswordSetting(PACK *p, RPC_CLIENT_PASSWORD_SETTING *a);
+void InRpcTraffic(TRAFFIC *t, PACK *p);
+void OutRpcTraffic(PACK *p, TRAFFIC *t);
+void InRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i);
+void OutRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i, UINT num);
+void OutRpcCmSetting(PACK *p, CM_SETTING *c);
+void InRpcCmSetting(CM_SETTING *c, PACK *p);
+
+
+#ifdef OS_WIN32
+void CiInitDriverVerStruct(MS_DRIVER_VER *ver);
+#endif // OS_EIN32
+
+#endif // CLIENT_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Command.c b/src/Cedar/Command.c
new file mode 100644
index 00000000..1d762b45
--- /dev/null
+++ b/src/Cedar/Command.c
@@ -0,0 +1,23538 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Command.c
+// vpncmd Command Line Management Utility
+
+#include "CedarPch.h"
+
+// System checker definition
+typedef bool (CHECKER_PROC_DEF)();
+typedef struct CHECKER_PROC
+{
+ char *Title;
+ CHECKER_PROC_DEF *Proc;
+} CHECKER_PROC;
+
+static CHECKER_PROC checker_procs[] =
+{
+ {"CHECK_PROC_KERNEL", CheckKernel},
+ {"CHECK_PROC_MEMORY", CheckMemory},
+ {"CHECK_PROC_STRINGS", CheckStrings},
+ {"CHECK_PROC_FILESYSTEM", CheckFileSystem},
+ {"CHECK_PROC_THREAD", CheckThread},
+ {"CHECK_PROC_NETWORK", CheckNetwork},
+};
+
+typedef struct CHECK_NETWORK_1
+{
+ SOCK *ListenSocket;
+} CHECK_NETWORK_1;
+
+typedef struct CHECK_NETWORK_2
+{
+ SOCK *s;
+ X *x;
+ K *k;
+} CHECK_NETWORK_2;
+
+
+// Convert the TT_RESULT to RPC
+void OutRpcTtResult(PACK *p, TT_RESULT *t)
+{
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "Raw", t->Raw);
+ PackAddBool(p, "Double", t->Double);
+ PackAddInt64(p, "NumBytesUpload", t->NumBytesUpload);
+ PackAddInt64(p, "NumBytesDownload", t->NumBytesDownload);
+ PackAddInt64(p, "NumBytesTotal", t->NumBytesTotal);
+ PackAddInt64(p, "Span", t->Span);
+ PackAddInt64(p, "BpsUpload", t->BpsUpload);
+ PackAddInt64(p, "BpsDownload", t->BpsDownload);
+ PackAddInt64(p, "BpsTotal", t->BpsTotal);
+}
+
+// Convert an RPC to a TT_RESULT
+void InRpcTtResult(PACK *p, TT_RESULT *t)
+{
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(TT_RESULT));
+
+ t->Raw = PackGetBool(p, "Raw");
+ t->Double = PackGetBool(p, "Double");
+ t->NumBytesUpload = PackGetInt64(p, "NumBytesUpload");
+ t->NumBytesDownload = PackGetInt64(p, "NumBytesDownload");
+ t->NumBytesTotal = PackGetInt64(p, "NumBytesTotal");
+ t->Span = PackGetInt64(p, "Span");
+ t->BpsUpload = PackGetInt64(p, "BpsUpload");
+ t->BpsDownload = PackGetInt64(p, "BpsDownload");
+ t->BpsTotal = PackGetInt64(p, "BpsTotal");
+}
+
+// Accept thread
+void CheckNetworkAcceptThread(THREAD *thread, void *param)
+{
+ CHECK_NETWORK_2 *c = (CHECK_NETWORK_2 *)param;
+ SOCK *s = c->s;
+ UINT i = 0;
+
+ if (StartSSL(s, c->x, c->k))
+ {
+ while (true)
+ {
+ i++;
+ if (Send(s, &i, sizeof(UINT), true) == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+
+// Listen thread
+void CheckNetworkListenThread(THREAD *thread, void *param)
+{
+ CHECK_NETWORK_1 *c = (CHECK_NETWORK_1 *)param;
+ SOCK *s;
+ UINT i;
+ K *pub, *pri;
+ X *x;
+ LIST *o = NewList(NULL);
+ NAME *name = NewName(L"Test", L"Test", L"Test", L"JP", L"Ibaraki", L"Tsukuba");
+
+ RsaGen(&pri, &pub, 1024);
+ x = NewRootX(pub, pri, name, 1000, NULL);
+
+ FreeName(name);
+
+ for (i = 1025;;i++)
+ {
+ s = Listen(i);
+ if (s != NULL)
+ {
+ break;
+ }
+ }
+
+ c->ListenSocket = s;
+ AddRef(s->ref);
+
+ NoticeThreadInit(thread);
+
+ while (true)
+ {
+ SOCK *new_sock = Accept(s);
+
+ if (new_sock == NULL)
+ {
+ break;
+ }
+ else
+ {
+ CHECK_NETWORK_2 c;
+ THREAD *t;
+
+ Zero(&c, sizeof(c));
+ c.s = new_sock;
+ c.k = pri;
+ c.x = x;
+
+ t = NewThread(CheckNetworkAcceptThread, &c);
+ Insert(o, t);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+ }
+
+ FreeK(pri);
+ FreeK(pub);
+
+ FreeX(x);
+
+ ReleaseSock(s);
+ ReleaseList(o);
+}
+
+// Network function check
+bool CheckNetwork()
+{
+ CHECK_NETWORK_1 c;
+ THREAD *t;
+ SOCK *listen_socket;
+ UINT port;
+ UINT i, num;
+ bool ok = true;
+ SOCK **socks;
+ SOCK_EVENT *se = NewSockEvent();
+
+ Zero(&c, sizeof(c));
+ t = NewThread(CheckNetworkListenThread, &c);
+ WaitThreadInit(t);
+
+ listen_socket = c.ListenSocket;
+
+ port = listen_socket->LocalPort;
+
+ num = 8;
+ socks = ZeroMalloc(sizeof(SOCK *) * num);
+ for (i = 0;i < num;i++)
+ {
+ socks[i] = Connect("localhost", port);
+ if (socks[i] == NULL)
+ {
+ Print("Connect Failed. (%u)\n", i);
+ ok = false;
+ num = i;
+ break;
+ }
+ if (StartSSL(socks[i], NULL, NULL) == false)
+ {
+ ReleaseSock(socks[i]);
+ Print("Connect Failed. (%u)\n", i);
+ ok = false;
+ num = i;
+ break;
+ }
+
+ JoinSockToSockEvent(socks[i], se);
+ }
+
+ if (ok)
+ {
+ while (true)
+ {
+ UINT i;
+ bool end = false;
+ bool all_blocked = true;
+
+ for (i = 0;i < num;i++)
+ {
+ UINT n;
+ UINT ret;
+
+ n = 0;
+ ret = Recv(socks[i], &n, sizeof(UINT), true);
+ if (ret == 0)
+ {
+ Print("Recv Failed (Disconnected).\n", ret);
+ end = true;
+ ok = false;
+ }
+ if (ret != SOCK_LATER)
+ {
+ all_blocked = false;
+ }
+
+ if (n >= 128)
+ {
+ end = true;
+ }
+ }
+
+ if (end)
+ {
+ break;
+ }
+
+ if (all_blocked)
+ {
+ WaitSockEvent(se, INFINITE);
+ }
+ }
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ Disconnect(socks[i]);
+ ReleaseSock(socks[i]);
+ }
+ Free(socks);
+
+ Disconnect(listen_socket);
+
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+
+ ReleaseSock(listen_socket);
+
+ ReleaseSockEvent(se);
+
+ return ok;
+}
+
+typedef struct CHECK_THREAD_1
+{
+ UINT num;
+ LOCK *lock;
+ THREAD *wait_thread;
+} CHECK_THREAD_1;
+
+static UINT check_thread_global_1 = 0;
+
+#define CHECK_THREAD_INCREMENT_COUNT 32
+
+// Test thread 1
+void CheckThread1(THREAD *thread, void *param)
+{
+ CHECK_THREAD_1 *ct1 = (CHECK_THREAD_1 *)param;
+ UINT i;
+ UINT num = CHECK_THREAD_INCREMENT_COUNT;
+
+ WaitThread(ct1->wait_thread, INFINITE);
+
+ for (i = 0;i < num;i++)
+ {
+ Lock(ct1->lock);
+ check_thread_global_1 = ct1->num;
+ InputToNull((void *)check_thread_global_1);
+ check_thread_global_1 = check_thread_global_1 + 1 + RetZero();
+ ct1->num = check_thread_global_1;
+ Unlock(ct1->lock);
+ }
+}
+
+// Test thread 2
+void CheckThread2(THREAD *thread, void *param)
+{
+ EVENT *e = (EVENT *)param;
+ Wait(e, INFINITE);
+}
+
+typedef struct CHECK_THREAD_3
+{
+ UINT num, a;
+} CHECK_THREAD_3;
+
+// Test thread 3
+void CheckThread3(THREAD *thread, void *param)
+{
+ CHECK_THREAD_3 *c = (CHECK_THREAD_3 *)param;
+ THREAD *t;
+
+ if (c->num == 0)
+ {
+ return;
+ }
+ c->num--;
+ c->a++;
+
+ t = NewThread(CheckThread3, c);
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+}
+
+// Thread check
+bool CheckThread()
+{
+ bool ok = true;
+ CHECK_THREAD_1 ct1;
+ UINT num = 32;
+ UINT i;
+ THREAD **threads;
+ EVENT *e;
+ THREAD *t2;
+ THREAD *t;
+ CHECK_THREAD_3 c;
+
+ e = NewEvent();
+
+ Zero(&ct1, sizeof(ct1));
+ ct1.lock = NewLock();
+
+ t2 = NewThread(CheckThread2, e);
+ ct1.wait_thread = t2;
+
+ threads = ZeroMalloc(sizeof(THREAD *) * num);
+ for (i = 0;i < num;i++)
+ {
+ threads[i] = NewThread(CheckThread1, &ct1);
+ if (threads[i] == NULL)
+ {
+ Print("Thread %u Create Failed.\n", i);
+ ok = false;
+ }
+ }
+
+ Set(e);
+
+ for (i = 0;i < num;i++)
+ {
+ WaitThread(threads[i], INFINITE);
+ ReleaseThread(threads[i]);
+ }
+
+ Free(threads);
+
+ if (ct1.num != (num * CHECK_THREAD_INCREMENT_COUNT))
+ {
+ Print("Threading: %u != %u\n", ct1.num, num * CHECK_THREAD_INCREMENT_COUNT);
+ ok = false;
+ }
+
+ DeleteLock(ct1.lock);
+
+ WaitThread(t2, INFINITE);
+ ReleaseThread(t2);
+
+ ReleaseEvent(e);
+
+ num = 32;
+
+ Zero(&c, sizeof(c));
+ c.num = num;
+ t = NewThread(CheckThread3, &c);
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+
+ if (c.a != num)
+ {
+ Print("Threading: %u != %u\n", c.a, num);
+ ok = false;
+ }
+
+ return ok;
+}
+
+// File system check
+bool CheckFileSystem()
+{
+ bool ok = true;
+ char exe[MAX_PATH];
+ char exe_dir[MAX_PATH];
+ DIRLIST *dirs;
+ UINT i;
+
+ GetExeName(exe, sizeof(exe));
+ GetExeDir(exe_dir, sizeof(exe_dir));
+
+ ok = false;
+ dirs = EnumDir(exe_dir);
+ for (i = 0;i < dirs->NumFiles;i++)
+ {
+ if (EndWith(exe, dirs->File[i]->FileName))
+ {
+ ok = true;
+ break;
+ }
+ }
+ FreeDir(dirs);
+
+ if (ok == false)
+ {
+ Print("EnumDir Failed.\n");
+ return false;
+ }
+ else
+ {
+ UINT size = 1234567;
+ UCHAR *buf;
+ IO *io;
+#ifndef OS_WIN32
+ wchar_t *filename = L"/tmp/vpn_checker_tmp";
+#else // OS_WIN32
+ wchar_t filename[MAX_PATH];
+ CombinePathW(filename, sizeof(filename), MsGetMyTempDirW(), L"vpn_checker_tmp");
+#endif // OS_WIN32
+
+ buf = Malloc(size);
+ for (i = 0;i < size;i++)
+ {
+ buf[i] = i % 256;
+ }
+
+ io = FileCreateW(filename);
+ if (io == NULL)
+ {
+ Print("FileCreate Failed.\n");
+ Free(buf);
+ return false;
+ }
+ else
+ {
+ FileWrite(io, buf, size);
+ Free(buf);
+ FileClose(io);
+
+ io = FileOpenW(filename, false);
+ if (FileSize(io) != 1234567)
+ {
+ Print("FileSize Failed.\n");
+ FileClose(io);
+ return false;
+ }
+ else
+ {
+ BUF *b;
+
+ FileClose(io);
+ b = ReadDumpW(filename);
+
+ for (i = 0;i < b->Size;i++)
+ {
+ UCHAR c = ((UCHAR *)b->Buf)[i];
+
+ if (c != (i % 256))
+ {
+ Print("FileToBuf Failed.\n");
+ FreeBuf(b);
+ return false;
+ }
+ }
+
+ FreeBuf(b);
+ }
+ }
+
+ FileDeleteW(filename);
+ }
+
+ return ok;
+}
+
+// String check
+bool CheckStrings()
+{
+ wchar_t *numstr = _UU("CHECK_TEST_123456789");
+ char tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ UINT i;
+ UINT sum, sum2;
+ UNI_TOKEN_LIST *t;
+
+ UniStrCpy(tmp2, sizeof(tmp2), L"");
+
+ sum2 = 0;
+ for (i = 0;i < 64;i++)
+ {
+ sum2 += i;
+ UniFormat(tmp2, sizeof(tmp2), L"%s,%u", tmp2, i);
+ }
+
+ t = UniParseToken(tmp2, L",");
+
+ sum = 0;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *s = t->Token[i];
+ UINT n = UniToInt(s);
+
+ sum += n;
+ }
+
+ UniFreeToken(t);
+
+ if (sum != sum2)
+ {
+ Print("UniParseToken Failed.\n");
+ return false;
+ }
+
+ if (UniToInt(numstr) != 123456789)
+ {
+ Print("UniToInt Failed.\n");
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), numstr);
+ if (ToInt(tmp) != 123456789)
+ {
+ Print("UniToStr Failed.\n");
+ return false;
+ }
+
+ return true;
+}
+
+// Memory check
+bool CheckMemory()
+{
+ UINT i, num, size, j;
+ void **pp;
+ bool ok = true;
+ UINT old_size;
+
+ num = 2000;
+ size = 1000;
+ pp = ZeroMalloc(sizeof(void *) * num);
+ for (i = 0;i < num;i++)
+ {
+ pp[i] = ZeroMalloc(size);
+ InputToNull(pp[i]);
+ for (j = 0;j < size;j++)
+ {
+ ((UCHAR *)pp[i])[j] = j % 256;
+ }
+ }
+ old_size = size;
+ size = size * 3;
+ for (i = 0;i < num;i++)
+ {
+ pp[i] = ReAlloc(pp[i], size);
+ for (j = old_size;j < size;j++)
+ {
+ InputToNull((void *)(UINT)(((UCHAR *)pp[i])[j] = j % 256));
+ }
+ }
+ for (i = 0;i < num;i++)
+ {
+ for (j = 0;j < size;j++)
+ {
+ if (((UCHAR *)pp[i])[j] != (j % 256))
+ {
+ ok = false;
+ }
+ }
+ Free(pp[i]);
+ }
+ Free(pp);
+
+ return ok;
+}
+
+// Function that do not do anything
+void InputToNull(void *p)
+{
+ if (RetZero() == 1)
+ {
+ UCHAR *c = (UCHAR *)p;
+ c[0] = 0x32;
+ }
+}
+
+// Function that returns 0
+UINT RetZero()
+{
+ if (g_debug == 0x123455)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+// Kernel check
+bool CheckKernel()
+{
+ UINT num = 10, i;
+ UINT64 s = Tick64();
+ UINT64 t = Tick64();
+
+ for (i = 0;i < num;i++)
+ {
+ UINT64 q = Tick64();
+ if (t > q)
+ {
+ Print("Tick64 #1 Failed.\n");
+ return false;
+ }
+
+ t = q;
+
+ SleepThread(100);
+ }
+
+ t = (Tick64() - s);
+ if (t <= 500 || t >= 2000)
+ {
+ Print("Tick64 #2 Failed.\n");
+ return false;
+ }
+ else if (false)
+ {
+ UINT64 tick1 = Tick64();
+ UINT64 time1;
+ UINT64 tick2, time2;
+
+ SleepThread(1000);
+
+ tick2 = Tick64();
+ time2 = LocalTime64();
+ time1 = SystemToLocal64(TickToTime(tick1));
+
+ if (time2 > time1)
+ {
+ s = time2 - time1;
+ }
+ else
+ {
+ s = time1 - time2;
+ }
+
+ if (s <= 500 || s >= 2000)
+ {
+ Print("TickToTime Failed.\n");
+ return false;
+ }
+ }
+
+#ifdef OS_UNIX
+ {
+ // Test of child process
+ UINT pid;
+ char exe[MAX_SIZE];
+
+ GetExeName(exe, sizeof(exe));
+
+ pid = fork();
+
+ if (pid == -1)
+ {
+ Print("fork Failed.\n");
+ return false;
+ }
+
+ if (pid == 0)
+ {
+ char *param = UNIX_ARG_EXIT;
+ char **args;
+
+ args = ZeroMalloc(sizeof(char *) * 3);
+ args[0] = exe;
+ args[1] = param;
+ args[2] = NULL;
+
+ setsid();
+
+ // Close the standard I/O
+ UnixCloseIO();
+
+ // Stop unwanted signals
+ signal(SIGHUP, SIG_IGN);
+
+ execvp(exe, args);
+ AbortExit();
+ }
+ else
+ {
+ int status = 0, ret;
+
+ // Wait for the termination of the child process
+ ret = waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status) == 0)
+ {
+ // Aborted
+ Print("waitpid Failed: 0x%x\n", ret);
+ return false;
+ }
+ }
+ }
+#endif // OS_UNIX
+
+ return true;
+}
+
+// System checker
+bool SystemCheck()
+{
+ UINT i;
+ bool ng = false;
+
+ UniPrint(_UU("CHECK_TITLE"));
+ UniPrint(_UU("CHECK_NOTE"));
+ for (i = 0;i < sizeof(checker_procs) / sizeof(checker_procs[0]);i++)
+ {
+ wchar_t *title;
+ bool ret = false;
+ CHECKER_PROC *p = &checker_procs[i];
+
+ title = _UU(p->Title);
+
+ UniPrint(_UU("CHECK_EXEC_TAG"), title);
+
+ ret = p->Proc();
+
+ if (ret == false)
+ {
+ ng = true;
+ }
+
+ UniPrint(L" %s\n", ret ? _UU("CHECK_PASS") : _UU("CHECK_FAIL"));
+ }
+
+ UniPrint(L"\n");
+ if (ng == false)
+ {
+ UniPrint(L"%s\n\n", _UU("CHECK_RESULT_1"));
+ }
+ else
+ {
+ UniPrint(L"%s\n\n", _UU("CHECK_RESULT_2"));
+ }
+
+ return true;
+}
+
+
+// Behavior checker
+UINT PtCheck(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ UINT ret = ERR_NO_ERROR;
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (SystemCheck() == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// VPN Tools main function
+void PtMain(PT *pt)
+{
+ char prompt[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (pt == NULL)
+ {
+ return;
+ }
+
+ // Display a message that start-up is complete
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_TOOLS_CONNECTED"));
+ pt->Console->Write(pt->Console, tmp);
+ pt->Console->Write(pt->Console, L"");
+
+ while (true)
+ {
+ // Definition of command
+ CMD cmd[] =
+ {
+ {"About", PsAbout},
+ {"MakeCert", PtMakeCert},
+ {"TrafficClient", PtTrafficClient},
+ {"TrafficServer", PtTrafficServer},
+ {"Check", PtCheck},
+ };
+
+ // Generate a prompt
+ StrCpy(prompt, sizeof(prompt), "VPN Tools>");
+
+ if (DispatchNextCmdEx(pt->Console, pt->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), pt) == false)
+ {
+ break;
+ }
+ pt->LastError = pt->Console->RetCode;
+
+ if (pt->LastError == ERR_NO_ERROR && pt->Console->ConsoleType != CONSOLE_CSV)
+ {
+ pt->Console->Write(pt->Console, _UU("CMD_MSG_OK"));
+ pt->Console->Write(pt->Console, L"");
+ }
+
+ if (pt->CmdLine != NULL)
+ {
+ break;
+ }
+ }
+}
+
+// Create a VPN Tools context
+PT *NewPt(CONSOLE *c, wchar_t *cmdline)
+{
+ PT *pt;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ if (UniIsEmptyStr(cmdline))
+ {
+ cmdline = NULL;
+ }
+
+ pt = ZeroMalloc(sizeof(PT));
+ pt->Console = c;
+ pt->CmdLine = CopyUniStr(cmdline);
+
+ return pt;
+}
+
+// Release the VPN Tools context
+void FreePt(PT *pt)
+{
+ // Validate arguments
+ if (pt == NULL)
+ {
+ return;
+ }
+
+ Free(pt->CmdLine);
+ Free(pt);
+}
+
+// Start VPN Tools
+UINT PtConnect(CONSOLE *c, wchar_t *cmdline)
+{
+ PT *pt;
+ UINT ret = 0;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ pt = NewPt(c, cmdline);
+
+ PtMain(pt);
+
+ ret = pt->LastError;
+
+ FreePt(pt);
+
+ return ret;
+}
+
+// Initialize the execution path information of vpncmd command
+void VpnCmdInitBootPath()
+{
+#ifdef OS_WIN32
+ char exe_path[MAX_PATH];
+ char tmp[MAX_PATH];
+ GetExeName(exe_path, sizeof(exe_path));
+
+ if (SearchStrEx(exe_path, "ham.exe", 0, false) != INFINITE || SearchStrEx(exe_path, "ham_x64.exe", 0, false) != INFINITE || SearchStrEx(exe_path, "ham_ia64.exe", 0, false) != INFINITE)
+ {
+ return;
+ }
+
+ if (MsIsAdmin())
+ {
+ UINT current_ver;
+
+ // Get the version of vpncmd that is currently installed
+ current_ver = MsRegReadInt(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER);
+
+ if ((CEDAR_BUILD >= current_ver) ||
+ MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)
+ {
+ char *src_filename;
+ bool b = false;
+ // Copy the vpncmdsys.exe to system32
+ if (MsIsNt())
+ {
+ Format(tmp, sizeof(tmp), "%s\\vpncmd.exe", MsGetSystem32Dir());
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "%s\\vpncmd.exe", MsGetWindowsDir());
+ }
+
+ src_filename = VPNCMD_BOOTSTRAP_FILENAME;
+
+ if (IsX64())
+ {
+ src_filename = VPNCMD_BOOTSTRAP_FILENAME_X64;
+ }
+
+ if (IsIA64())
+ {
+ src_filename = VPNCMD_BOOTSTRAP_FILENAME_IA64;
+ }
+
+ b = true;
+
+ if (MsIs64BitWindows() == false || Is64())
+ {
+ if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)
+ {
+ b = FileCopy(src_filename, tmp);
+ }
+ }
+ else
+ {
+ void *wow;
+
+ wow = MsDisableWow64FileSystemRedirection();
+
+ if (true)
+ {
+ if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)
+ {
+ b = FileCopy(src_filename, tmp);
+ }
+ }
+
+ MsRestoreWow64FileSystemRedirection(wow);
+
+ if (true)
+ {
+ if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)
+ {
+ b = FileCopy(src_filename, tmp);
+ }
+ }
+ }
+
+ // Because the currently running prompt is newer version, overwrite the registry
+ if (MsIs64BitWindows() == false)
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path);
+ MsRegWriteInt(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD);
+ }
+ else
+ {
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path, true, false);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD, true, false);
+
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD, false, true);
+ }
+ }
+ }
+#endif // OS_WIN32
+}
+
+// Show the string
+void TtPrint(void *param, TT_PRINT_PROC *print_proc, wchar_t *str)
+{
+ // Validate arguments
+ if (print_proc == NULL || str == NULL)
+ {
+ return;
+ }
+
+ print_proc(param, str);
+}
+
+// Generate new random data
+void TtGenerateRandomData(UCHAR **buf, UINT *size)
+{
+ UCHAR *tmp;
+ UINT sz;
+ UINT i;
+ // Validate arguments
+ if (buf == NULL || size == NULL)
+ {
+ return;
+ }
+
+ sz = TRAFFIC_BUF_SIZE;
+ tmp = Malloc(sz);
+ for (i = 0;i < sz;i++)
+ {
+ tmp[i] = rand() % 256;
+
+ if (tmp[i] == '!')
+ {
+ tmp[i] = '_';
+ }
+ }
+
+ *buf = tmp;
+ *size = sz;
+}
+
+// Communication throughput measurement server worker thread
+void TtsWorkerThread(THREAD *thread, void *param)
+{
+ TTS *tts;
+ UINT buf_size;
+ UCHAR *send_buf_data, *recv_buf_data;
+ bool all_sockets_blocked = false;
+ UINT64 tmp64;
+ LIST *o;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ bool dont_block_next_time = false;
+ char *ver_str = TRAFFIC_VER_STR;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Allocate the data area
+ TtGenerateRandomData(&send_buf_data, &buf_size);
+ TtGenerateRandomData(&recv_buf_data, &buf_size);
+
+ tts = (TTS *)param;
+
+ // Preparation of socket events
+ tts->SockEvent = NewSockEvent();
+ AddRef(tts->SockEvent->ref);
+
+ // Preparing the Server socket list
+ tts->TtsSockList = NewList(NULL);
+
+ // Notify completion of preparation to parent thread
+ NoticeThreadInit(thread);
+
+ o = NewList(NULL);
+
+ while (tts->Halt == false)
+ {
+ UINT64 now = Tick64();
+
+ // Wait for all sockets
+ if (dont_block_next_time == false)
+ {
+ WaitSockEvent(tts->SockEvent, 50);
+ }
+ dont_block_next_time = false;
+
+ // Process for sockets that are currently registered
+ LockList(tts->TtsSockList);
+ {
+ UINT i;
+
+ all_sockets_blocked = false;
+
+ // Continue to send and receive data
+ // until all sockets become block state
+ while (all_sockets_blocked == false)
+ {
+ all_sockets_blocked = true;
+
+ for (i = 0;i < LIST_NUM(tts->TtsSockList);i++)
+ {
+ UINT ret = SOCK_LATER;
+ UCHAR *send_data = NULL, *recv_data = NULL;
+ UINT send_size = 0, recv_size = 0;
+ TTS_SOCK *ts = LIST_DATA(tts->TtsSockList, i);
+ bool blocked_for_this_socket = false;
+
+ if (ts->SockJoined == false)
+ {
+ JoinSockToSockEvent(ts->Sock, tts->SockEvent);
+ ts->SockJoined = true;
+ }
+
+ switch (ts->State)
+ {
+ case 0:
+ // Return the version string
+ ret = Send(ts->Sock, ver_str, TRAFFIC_VER_STR_SIZE, false);
+ if (ret != 0 && ret != SOCK_LATER)
+ {
+ ts->State = 5;
+ }
+ break;
+
+ case 5:
+ // Receive the direction from the client
+ ret = Recv(ts->Sock, recv_buf_data, buf_size, false);
+ if (ret != 0 && ret != SOCK_LATER)
+ {
+ UCHAR c;
+
+ // Direction of the data is in the first byte that is received
+ c = recv_buf_data[0];
+
+ if (c == 0)
+ {
+ // In the case of 0, Client -> Server
+ ts->State = 1;
+ }
+ else
+ {
+ // Otherwise Server -> Client
+ ts->State = 2;
+ }
+
+ if (ret >= (sizeof(UINT64) + sizeof(UINT64) + 1))
+ {
+ // Session ID
+ ts->SessionId = READ_UINT64(recv_buf_data + 1);
+
+ // Span
+ ts->Span = READ_UINT64(recv_buf_data + sizeof(UINT64) + 1);
+ }
+ }
+ break;
+
+ case 1:
+ // Client -> Server
+ ret = Recv(ts->Sock, recv_buf_data, buf_size, false);
+
+ if (ret != 0 && ret != SOCK_LATER)
+ {
+ // Checking the first byte of received
+ UCHAR c = recv_buf_data[0];
+
+ if (ts->FirstRecvTick == 0)
+ {
+ // Record the time at which the data has been received for the first
+ ts->FirstRecvTick = now;
+ }
+ else
+ {
+ // Check whether the span didn't finish yet
+ if (ts->FirstRecvTick <= now)
+ {
+ if (ts->Span != 0)
+ {
+ UINT64 giveup_tick = ts->FirstRecvTick + ts->Span;
+
+ if (now > giveup_tick)
+ {
+ // Span has expired
+ c = '!';
+ }
+ }
+ }
+ }
+
+ if (c == '!')
+ {
+ // Notice the size information from the server to the client
+ ts->State = 3;
+ Debug("!");
+ }
+ }
+ break;
+
+ case 2:
+ // Server -> Client
+ if (ts->NoMoreSendData == false)
+ {
+ ret = Send(ts->Sock, send_buf_data, buf_size, false);
+ }
+ else
+ {
+ ret = Recv(ts->Sock, recv_buf_data, buf_size, false);
+ }
+ break;
+
+ case 3:
+ // Notice the size information from the server to the client
+ tmp64 = Endian64(ts->NumBytes);
+
+ Recv(ts->Sock, recv_buf_data, buf_size, false);
+
+ if (ts->LastWaitTick == 0 || ts->LastWaitTick <= Tick64())
+ {
+ ret = Send(ts->Sock, &tmp64, sizeof(tmp64), false);
+
+ if (ret != SOCK_LATER)
+ {
+ UINT j;
+
+ ts->LastWaitTick = Tick64() + 100;
+
+ if (ts->SessionId != 0)
+ {
+ // Not to send more data to the socket of the
+ // transmission direction in the same session ID
+ for (j = 0;j < LIST_NUM(tts->TtsSockList);j++)
+ {
+ TTS_SOCK *ts2 = LIST_DATA(tts->TtsSockList, j);
+
+ if (ts2->SessionId == ts->SessionId &&
+ ts2 != ts)
+ {
+ ts2->NoMoreSendData = true;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ if (ret == 0)
+ {
+ // Mark as deleting the socket because it is disconnected
+ Insert(o, ts);
+ }
+ else if (ret == SOCK_LATER)
+ {
+ // Delay has occurred
+ blocked_for_this_socket = true;
+ dont_block_next_time = false;
+ }
+ else
+ {
+ if (ts->State == 1)
+ {
+ ts->NumBytes += (UINT64)ret;
+ }
+ }
+
+ if (blocked_for_this_socket == false)
+ {
+ all_sockets_blocked = false;
+ }
+ }
+
+ if (LIST_NUM(o) != 0)
+ {
+ UINT i;
+ // One or more sockets is disconnected
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TTS_SOCK *ts = LIST_DATA(o, i);
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_DISCONNECTED"), ts->Id, ts->Sock->RemoteHostname);
+ TtPrint(tts->Param, tts->Print, tmp);
+
+ Disconnect(ts->Sock);
+ ReleaseSock(ts->Sock);
+
+ Delete(tts->TtsSockList, ts);
+
+ Free(ts);
+ }
+
+ DeleteAll(o);
+ }
+
+ if (tts->NewSocketArrived || tts->Halt)
+ {
+ tts->NewSocketArrived = false;
+ all_sockets_blocked = true;
+ dont_block_next_time = true;
+ }
+ }
+ }
+ UnlockList(tts->TtsSockList);
+ }
+
+ LockList(tts->TtsSockList);
+ {
+ // Release the sockets of all remaining
+ for (i = 0;i < LIST_NUM(tts->TtsSockList);i++)
+ {
+ TTS_SOCK *ts = LIST_DATA(tts->TtsSockList, i);
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_DISCONNECT"), ts->Id, ts->Sock->RemoteHostname);
+ TtPrint(tts->Param, tts->Print, tmp);
+
+ Disconnect(ts->Sock);
+ ReleaseSock(ts->Sock);
+
+ Free(ts);
+ }
+ }
+ UnlockList(tts->TtsSockList);
+
+ // Cleanup
+ ReleaseList(o);
+ ReleaseList(tts->TtsSockList);
+ ReleaseSockEvent(tts->SockEvent);
+ Free(send_buf_data);
+ Free(recv_buf_data);
+}
+
+// Accept thread for IPv6
+void TtsIPv6AcceptThread(THREAD *thread, void *param)
+{
+ TTS *tts = (TTS *)param;
+ // Validate arguments
+ if (tts == NULL || param == NULL)
+ {
+ return;
+ }
+
+ TtsAcceptProc(tts, tts->ListenSocketV6);
+}
+
+// Accept procedure
+void TtsAcceptProc(TTS *tts, SOCK *listen_socket)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (tts == NULL || listen_socket == NULL)
+ {
+ return;
+ }
+
+ while (tts->Halt == false)
+ {
+ SOCK *s;
+ // Accept
+ s = Accept(listen_socket);
+
+ if (s == NULL)
+ {
+ if (tts->Halt == false)
+ {
+ SleepThread(10);
+ }
+ continue;
+ }
+ else
+ {
+ // Connected from the client
+ AcceptInit(s);
+ tts->NewSocketArrived = true;
+ LockList(tts->TtsSockList);
+ {
+ TTS_SOCK *ts = ZeroMalloc(sizeof(TTS_SOCK));
+
+ ts->Id = (++tts->IdSeed);
+ ts->Sock = s;
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_ACCEPTED"), ts->Id,
+ s->RemoteHostname, s->RemotePort);
+ TtPrint(tts->Param, tts->Print, tmp);
+
+ Insert(tts->TtsSockList, ts);
+ tts->NewSocketArrived = true;
+ }
+ UnlockList(tts->TtsSockList);
+
+ SetSockEvent(tts->SockEvent);
+ }
+ }
+}
+
+// Communication throughput measurement server wait thread
+void TtsListenThread(THREAD *thread, void *param)
+{
+ TTS *tts;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ tts = (TTS *)param;
+
+ tts->ListenSocket = NULL;
+ tts->ListenSocket = ListenEx(tts->Port, false);
+ tts->ListenSocketV6 = ListenEx6(tts->Port, false);
+
+ if (tts->ListenSocket == NULL && tts->ListenSocketV6 == NULL)
+ {
+ // Failed to Listen
+ UniFormat(tmp, sizeof(tmp), _UU("TT_LISTEN_FAILED"), tts->Port);
+ TtPrint(tts->Param, tts->Print, tmp);
+
+ // Notify completion of preparation to parent thread
+ NoticeThreadInit(thread);
+
+ tts->ErrorCode = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_STARTED"), tts->Port);
+ TtPrint(tts->Param, tts->Print, tmp);
+
+ if (tts->ListenSocketV6 != NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_STARTED_V6"), tts->Port);
+ TtPrint(tts->Param, tts->Print, tmp);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_FAILED_V6"), tts->Port);
+ TtPrint(tts->Param, tts->Print, tmp);
+ }
+
+ if (tts->ListenSocket != NULL)
+ {
+ AddRef(tts->ListenSocket->ref);
+ }
+ if (tts->ListenSocketV6 != NULL)
+ {
+ AddRef(tts->ListenSocketV6->ref);
+ }
+
+ // Start the worker thread
+ tts->WorkThread = NewThread(TtsWorkerThread, tts);
+ WaitThreadInit(tts->WorkThread);
+
+ // Notify completion of preparation to parent thread
+ NoticeThreadInit(thread);
+
+ // Prepare for IPv6 Accept thread
+ tts->IPv6AcceptThread = NULL;
+ if (tts->ListenSocketV6 != NULL)
+ {
+ tts->IPv6AcceptThread = NewThread(TtsIPv6AcceptThread, tts);
+ }
+
+ TtsAcceptProc(tts, tts->ListenSocket);
+
+ if (tts->IPv6AcceptThread != NULL)
+ {
+ WaitThread(tts->IPv6AcceptThread, INFINITE);
+ ReleaseThread(tts->IPv6AcceptThread);
+ }
+
+ TtPrint(tts->Param, tts->Print, _UU("TTS_LISTEN_STOP"));
+
+ ReleaseSock(tts->ListenSocket);
+ ReleaseSock(tts->ListenSocketV6);
+ SetSockEvent(tts->SockEvent);
+
+ // Wait for stopping the worker thread
+ WaitThread(tts->WorkThread, INFINITE);
+ ReleaseThread(tts->WorkThread);
+ ReleaseSockEvent(tts->SockEvent);
+ }
+}
+
+// String of the direction in which data flows
+wchar_t *GetTtcTypeStr(UINT type)
+{
+ switch (type)
+ {
+ case TRAFFIC_TYPE_DOWNLOAD:
+ return _UU("TTC_TYPE_DOWNLOAD");
+
+ case TRAFFIC_TYPE_UPLOAD:
+ return _UU("TTC_TYPE_UPLOAD");
+
+ default:
+ return _UU("TTC_TYPE_FULL");
+ }
+}
+
+// Show a Summary
+void TtcPrintSummary(TTC *ttc)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t *tag = L"%-35s %s";
+ // Validate arguments
+ if (ttc == NULL)
+ {
+ return;
+ }
+
+ TtPrint(ttc->Param, ttc->Print, L"");
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_BAR"));
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_TITLE"));
+ TtPrint(ttc->Param, ttc->Print, L"");
+
+ // Destination host name
+ StrToUni(tmp2, sizeof(tmp2), ttc->Host);
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_HOST"), tmp2);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Destination TCP port number
+ UniToStru(tmp2, ttc->Port);
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_PORT"), tmp2);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Number of TCP connections to establish
+ UniToStru(tmp2, ttc->NumTcp);
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_NUMTCP"), tmp2);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Data transmission direction
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_TYPE"), GetTtcTypeStr(ttc->Type));
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Data transmission span
+ UniFormat(tmp2, sizeof(tmp2), _UU("TTC_SPAN_STR"), (double)(ttc->Span) / 1000.0);
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_SPAN"), tmp2);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Correct the data for Ethernet frame
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_ETHER"), ttc->Raw ? _UU("SEC_NO") : _UU("SEC_YES"));
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Measure the total amount of input and output throughput of relay equipment
+ UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_DOUBLE"), ttc->Double ? _UU("SEC_YES") : _UU("SEC_NO"));
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_BAR"));
+ TtPrint(ttc->Param, ttc->Print, L"");
+}
+
+// Stop the communication throughput measurement client
+void StopTtc(TTC *ttc)
+{
+ // Validate arguments
+ if (ttc == NULL)
+ {
+ return;
+ }
+
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_STOPPING"));
+
+ ttc->Halt = true;
+ SetSockEvent(ttc->SockEvent);
+}
+
+// Generate a result
+void TtcGenerateResult(TTC *ttc)
+{
+ TT_RESULT *res;
+ UINT i;
+ // Validate arguments
+ if (ttc == NULL)
+ {
+ return;
+ }
+
+ res = &ttc->Result;
+
+ Zero(res, sizeof(TT_RESULT));
+
+ res->Raw = ttc->Raw;
+ res->Double = ttc->Double;
+ res->Span = ttc->RealSpan;
+
+ for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)
+ {
+ TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);
+
+ if (ts->Download == false)
+ {
+ // Upload
+ res->NumBytesUpload += ts->NumBytes;
+ }
+ else
+ {
+ // Download
+ res->NumBytesDownload += ts->NumBytes;
+ }
+ }
+
+ if (res->Raw == false)
+ {
+ // Correct to match the Ethernet
+ res->NumBytesDownload = (UINT64)((double)res->NumBytesDownload * 1514.0 / 1460.0);
+ res->NumBytesUpload = (UINT64)((double)res->NumBytesUpload * 1514.0 / 1460.0);
+ }
+
+ res->NumBytesTotal = res->NumBytesDownload + res->NumBytesUpload;
+
+ // Measure the throughput
+ if (res->Span != 0)
+ {
+ res->BpsUpload = (UINT64)((double)res->NumBytesUpload * 8.0 / ((double)res->Span / 1000.0));
+ res->BpsDownload = (UINT64)((double)res->NumBytesDownload * 8.0 / ((double)res->Span / 1000.0));
+ }
+
+ if (res->Double)
+ {
+ res->BpsUpload *= 2ULL;
+ res->BpsDownload *= 2ULL;
+ }
+
+ res->BpsTotal = res->BpsUpload + res->BpsDownload;
+}
+
+// Client thread
+void TtcThread(THREAD *thread, void *param)
+{
+ TTC *ttc;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ bool ok = false;
+ UINT buf_size;
+ UCHAR *send_buf_data, *recv_buf_data;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Allocate the data area
+ TtGenerateRandomData(&send_buf_data, &buf_size);
+ TtGenerateRandomData(&recv_buf_data, &buf_size);
+
+ ttc = (TTC *)param;
+
+ ttc->SockEvent = NewSockEvent();
+ AddRef(ttc->SockEvent->ref);
+
+ // Ready
+ NoticeThreadInit(thread);
+
+ TtcPrintSummary(ttc);
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_START"),
+ ttc->Host, ttc->Port, ttc->NumTcp);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Establish all connections to the client
+ ttc->ItcSockList = NewList(NULL);
+
+ ok = true;
+
+ for (i = 0;i < ttc->NumTcp;i++)
+ {
+ SOCK *s;
+ TTC_SOCK *ts = ZeroMalloc(sizeof(TTC_SOCK));
+
+ ts->Id = i + 1;
+
+ if (ttc->Type == TRAFFIC_TYPE_DOWNLOAD)
+ {
+ ts->Download = true;
+ }
+ else if (ttc->Type == TRAFFIC_TYPE_UPLOAD)
+ {
+ ts->Download = false;
+ }
+ else
+ {
+ ts->Download = ((i % 2) == 0) ? true : false;
+ }
+
+ s = ConnectEx2(ttc->Host, ttc->Port, 0, ttc->Cancel);
+
+ if (s == NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_FAILED"), i + 1);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+ ok = false;
+ Free(ts);
+ break;
+ }
+ else
+ {
+ char buffer[TRAFFIC_VER_STR_SIZE];
+
+ SetTimeout(s, 5000);
+
+ Zero(buffer, sizeof(buffer));
+ if (Recv(s, buffer, sizeof(buffer), false) != sizeof(buffer) || Cmp(buffer, TRAFFIC_VER_STR, TRAFFIC_VER_STR_SIZE) != 0)
+ {
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_CONNECT_NOT_SERVER"));
+ ok = false;
+ ReleaseSock(s);
+ Free(ts);
+ break;
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_OK"), i + 1);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_OK_2"), GetTtcTypeStr(ts->Download ? TRAFFIC_TYPE_DOWNLOAD : TRAFFIC_TYPE_UPLOAD));
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ ts->Sock = s;
+
+ SetTimeout(s, TIMEOUT_INFINITE);
+
+ JoinSockToSockEvent(s, ttc->SockEvent);
+ }
+
+ Insert(ttc->ItcSockList, ts);
+ }
+
+ Set(ttc->InitedEvent);
+
+ if (ttc->StartEvent != NULL)
+ {
+ Wait(ttc->StartEvent, INFINITE);
+ SleepThread(500);
+ }
+
+ if (ok)
+ {
+ bool all_sockets_blocked;
+ bool dont_block_next_time = false;
+ bool halt_flag = false;
+ UINT64 start_tick, end_tick;
+ UINT64 halt_timeout = 0;
+ wchar_t tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+ UINT check_clock_seed = 0;
+ bool halting = false;
+ UINT64 tmp64;
+ UINT64 session_id = Rand64();
+
+ // Record the current time
+ start_tick = Tick64();
+ end_tick = start_tick + ttc->Span;
+
+ // Show start message
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(TickToTime(start_tick)), NULL);
+ GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(TickToTime(end_tick)), NULL);
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_START"), tmp1, tmp2);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+
+ // Main loop
+ while (true)
+ {
+ UINT i;
+
+ if (dont_block_next_time == false)
+ {
+ WaitSockEvent(ttc->SockEvent, 50);
+ }
+
+ dont_block_next_time = false;
+
+ if (ttc->AbnormalTerminated)
+ {
+ // Abnormal termination occured
+ break;
+ }
+
+ if (ttc->Halt || end_tick <= Tick64() || (ttc->Cancel != NULL && (*ttc->Cancel)))
+ {
+ // End measurement
+ if (halting == false)
+ {
+ if (ttc->Halt || (ttc->Cancel != NULL && (*ttc->Cancel)))
+ {
+ // User cancel
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_COMM_USER_CANCEL"));
+ }
+ else
+ {
+ // Time elapsed
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_END"),
+ (double)ttc->Span / 1000.0);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+ }
+
+ ttc->RealSpan = Tick64() - start_tick;
+
+ halting = true;
+
+ // Wait for reporting data from the server
+ halt_timeout = Tick64() + 60000ULL;
+ }
+ }
+
+ if (halt_timeout != 0)
+ {
+ bool ok = true;
+
+ // Wait that all TCP connections to finish processing
+ for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)
+ {
+ TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);
+
+ if (ts->Download == false)
+ {
+ if (ts->ServerUploadReportReceived == false)
+ {
+ ok = false;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ // Measurement completed
+ // Show the result
+ TtcGenerateResult(ttc);
+ break;
+ }
+ else
+ {
+ if (halt_timeout <= Tick64())
+ {
+ // An error occured
+ ttc->AbnormalTerminated = true;
+ ttc->ErrorCode = ERR_PROTOCOL_ERROR;
+ break;
+ }
+ }
+ }
+
+ all_sockets_blocked = false;
+
+ // Continue to send and receive data
+ // until all sockets become block state
+ while (all_sockets_blocked == false)
+ {
+ all_sockets_blocked = true;
+
+ for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)
+ {
+ UINT ret = SOCK_LATER;
+ TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);
+ bool blocked_for_this_socket = false;
+ UCHAR c = 0;
+ UCHAR c_and_session_id[1 + sizeof(UINT64) + sizeof(UINT64)];
+
+ if (halt_timeout != 0)
+ {
+ if (ts->State != 3 && ts->State != 4)
+ {
+ if (ts->Download == false)
+ {
+ if (ts->State != 0)
+ {
+ ts->State = 3;
+ }
+ else
+ {
+ ts->ServerUploadReportReceived = true;
+ ts->State = 4;
+ }
+ }
+ else
+ {
+ ts->State = 4;
+ }
+ }
+ }
+
+ switch (ts->State)
+ {
+ case 0:
+ // Initial state: Specify the direction of
+ // the data flow between client-server
+ if (ts->Download)
+ {
+ c = 1;
+ }
+ else
+ {
+ c = 0;
+ }
+
+ c_and_session_id[0] = c;
+ WRITE_UINT64(c_and_session_id + 1, session_id);
+ WRITE_UINT64(c_and_session_id + sizeof(UINT64) + 1, ttc->Span);
+
+ ret = Send(ts->Sock, c_and_session_id, 1 + sizeof(UINT64) + sizeof(UINT64), false);
+
+ if (ret != 0 && ret != SOCK_LATER)
+ {
+ if (ts->Download)
+ {
+ ts->State = 1;
+ }
+ else
+ {
+ ts->State = 2;
+ }
+ }
+ break;
+
+ case 1:
+ // Server -> Client (download)
+ ret = Recv(ts->Sock, recv_buf_data, buf_size, false);
+ break;
+
+ case 2:
+ // Client -> Server (upload)
+ ret = Send(ts->Sock, send_buf_data, buf_size, false);
+ break;
+
+ case 3:
+ // Transmission completion client -> server (upload)
+ // Request the data size
+ if (ts->NextSendRequestReportTick == 0 ||
+ (Tick64() >= ts->NextSendRequestReportTick))
+ {
+ UCHAR suprise[MAX_SIZE];
+ UINT i;
+
+ ts->NextSendRequestReportTick = Tick64() + 200ULL;
+
+ for (i = 0;i < sizeof(suprise);i++)
+ {
+ suprise[i] = '!';
+ }
+
+ ret = Send(ts->Sock, suprise, sizeof(suprise), false);
+ }
+
+ ret = Recv(ts->Sock, &tmp64, sizeof(tmp64), false);
+ if (ret != 0 && ret != SOCK_LATER && ret == sizeof(tmp64))
+ {
+ ts->NumBytes = Endian64(tmp64);
+
+ ts->ServerUploadReportReceived = true;
+
+ ts->State = 4;
+ }
+ break;
+
+ case 4:
+ // Do Nothing
+ if (Recv(ts->Sock, recv_buf_data, buf_size, false) == SOCK_LATER)
+ {
+ ret = SOCK_LATER;
+ }
+ break;
+ }
+
+ if (ret == 0)
+ {
+ // The socket is disconnected
+ ttc->AbnormalTerminated = true;
+ ttc->ErrorCode = ERR_PROTOCOL_ERROR;
+ blocked_for_this_socket = true;
+ dont_block_next_time = false;
+
+ if (ts->HideErrMsg == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_DISCONNECTED"), ts->Id);
+ TtPrint(ttc->Param, ttc->Print, tmp);
+ ts->HideErrMsg = true;
+ }
+ }
+ else if (ret == SOCK_LATER)
+ {
+ // Delay has occurred
+ blocked_for_this_socket = true;
+ dont_block_next_time = false;
+ }
+ else
+ {
+ if (ts->Download)
+ {
+ ts->NumBytes += (UINT64)ret;
+ }
+ }
+
+ if (blocked_for_this_socket == false)
+ {
+ all_sockets_blocked = false;
+ }
+ }
+
+ if (ttc->Halt || (ttc->Cancel != NULL && (*ttc->Cancel)))
+ {
+ all_sockets_blocked = true;
+ dont_block_next_time = true;
+ }
+
+ if (end_tick <= Tick64())
+ {
+ all_sockets_blocked = true;
+ dont_block_next_time = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Abort
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_ERROR_ABORTED"));
+ ttc->ErrorCode = ERR_CONNECT_FAILED;
+ }
+
+ // Cleanup
+ for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)
+ {
+ TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);
+
+ Disconnect(ts->Sock);
+ ReleaseSock(ts->Sock);
+ Free(ts);
+ }
+
+ ReleaseSockEvent(ttc->SockEvent);
+ ReleaseList(ttc->ItcSockList);
+ Free(send_buf_data);
+ Free(recv_buf_data);
+}
+
+// Start the communication throughput measurement client
+TTC *NewTtc(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param)
+{
+ return NewTtcEx(host, port, numtcp, type, span, dbl, raw, print_proc, param, NULL, NULL);
+}
+TTC *NewTtcEx(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param, EVENT *start_event, bool *cancel)
+{
+ TTC *ttc;
+
+ ttc = ZeroMalloc(sizeof(TTC));
+ ttc->InitedEvent = NewEvent();
+ ttc->Port = port;
+ StrCpy(ttc->Host, sizeof(ttc->Host), host);
+ ttc->NumTcp = numtcp;
+ ttc->Type = type;
+ ttc->Span = span;
+ ttc->Double = dbl;
+ ttc->Raw = raw;
+ ttc->StartEvent = start_event;
+ ttc->Cancel = cancel;
+
+ if (ttc->Type == TRAFFIC_TYPE_FULL && ttc->NumTcp < 2)
+ {
+ ttc->NumTcp = 2;
+ }
+
+ ttc->Print = print_proc;
+ ttc->Param = param;
+ ttc->ErrorCode = ERR_NO_ERROR;
+
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_INIT"));
+
+ ttc->Thread = NewThread(TtcThread, ttc);
+ WaitThreadInit(ttc->Thread);
+
+ return ttc;
+}
+
+// Wait for stopping the communication throughput measurement client
+UINT FreeTtc(TTC *ttc, TT_RESULT *result)
+{
+ UINT ret;
+ // Validate arguments
+ if (ttc == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ WaitThread(ttc->Thread, INFINITE);
+ ReleaseThread(ttc->Thread);
+
+ TtPrint(ttc->Param, ttc->Print, _UU("TTC_FREE"));
+
+ ret = ttc->ErrorCode;
+
+ if (ret == ERR_NO_ERROR)
+ {
+ if (result != NULL)
+ {
+ Copy(result, &ttc->Result, sizeof(TT_RESULT));
+ }
+ }
+
+ ReleaseSockEvent(ttc->SockEvent);
+ ReleaseEvent(ttc->InitedEvent);
+
+ Free(ttc);
+
+ return ret;
+}
+
+// Start the communication throughput measurement server
+TTS *NewTts(UINT port, void *param, TT_PRINT_PROC *print_proc)
+{
+ TTS *tts;
+ THREAD *t;
+
+ tts = ZeroMalloc(sizeof(TTS));
+ tts->Port = port;
+ tts->Param = param;
+ tts->Print = print_proc;
+
+ TtPrint(param, print_proc, _UU("TTS_INIT"));
+
+ // Creating a thread
+ t = NewThread(TtsListenThread, tts);
+ WaitThreadInit(t);
+
+ tts->Thread = t;
+
+ return tts;
+}
+
+// Wait for stopping the communication throughput measurement server
+UINT FreeTts(TTS *tts)
+{
+ UINT ret;
+ // Validate arguments
+ if (tts == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ TtPrint(tts->Param, tts->Print, _UU("TTS_STOP_INIT"));
+
+ tts->Halt = true;
+ Disconnect(tts->ListenSocket);
+ ReleaseSock(tts->ListenSocket);
+ Disconnect(tts->ListenSocketV6);
+ ReleaseSock(tts->ListenSocketV6);
+
+ // Wait for the termination of the thread
+ WaitThread(tts->Thread, INFINITE);
+
+ ReleaseThread(tts->Thread);
+
+ TtPrint(tts->Param, tts->Print, _UU("TTS_STOP_FINISHED"));
+
+ ret = tts->ErrorCode;
+
+ Free(tts);
+
+ return ret;
+}
+
+// Show the measurement tools prompt
+void PtTrafficPrintProc(void *param, wchar_t *str)
+{
+ CONSOLE *c;
+ // Validate arguments
+ if (param == NULL || str == NULL)
+ {
+ return;
+ }
+
+ c = (CONSOLE *)param;
+
+ if (c->ConsoleType == CONSOLE_LOCAL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // Display only if the local console
+ // (Can not be displayed because threads aren't synchronized otherwise?)
+ UniStrCpy(tmp, sizeof(tmp), str);
+ if (UniEndWith(str, L"\n") == false)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"\n");
+ }
+ UniPrint(L"%s", tmp);
+ }
+}
+
+// Display the communication throughput results
+void TtcPrintResult(CONSOLE *c, TT_RESULT *res)
+{
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || res == NULL)
+ {
+ return;
+ }
+
+ c->Write(c, _UU("TTC_RES_TITLE"));
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("TTC_RES_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("TTC_RES_COLUMN_2"), true);
+ CtInsertColumn(ct, _UU("TTC_RES_COLUMN_3"), true);
+
+ // Time that was used to measure
+ GetSpanStrMilli(str, sizeof(str), res->Span);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("TTC_RES_SPAN"), tmp, L"");
+
+ // Correct the data for Ethernet frame
+ CtInsert(ct, _UU("TTC_RES_ETHER"), res->Raw ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
+
+ // Amount of communication data of download direction
+ ToStr3(str, sizeof(str), res->NumBytesDownload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesDownload);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BYTES_DOWNLOAD"), tmp1, tmp2);
+
+ // Amount of communication data of upload direction
+ ToStr3(str, sizeof(str), res->NumBytesUpload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesUpload);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BYTES_UPLOAD"), tmp1, tmp2);
+
+ // Total amount of communication data
+ ToStr3(str, sizeof(str), res->NumBytesTotal);
+ UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
+ ToStrByte1000(str, sizeof(str), res->NumBytesTotal);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BYTES_TOTAL"), tmp1, tmp2);
+
+ // Calculate the total throughput of input and output of the relay equipment
+ CtInsert(ct, _UU("TTC_RES_DOUBLE"), (res->Double == false) ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
+
+ // Average throughput of download direction
+ ToStr3(str, sizeof(str), res->BpsDownload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsDownload);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BPS_DOWNLOAD"), tmp1, tmp2);
+
+ // Average throughput of upload direction
+ ToStr3(str, sizeof(str), res->BpsUpload);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsUpload);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BPS_UPLOAD"), tmp1, tmp2);
+
+ // Total average throughput
+ ToStr3(str, sizeof(str), res->BpsTotal);
+ UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
+ ToStrByte1000(str, sizeof(str), res->BpsTotal);
+ ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
+ StrToUni(tmp2, sizeof(tmp2), str);
+ CtInsert(ct, _UU("TTC_RES_BPS_TOTAL"), tmp1, tmp2);
+
+ CtFree(ct, c);
+}
+
+// Execute the communication throughput measurement tool server
+UINT PtTrafficServer(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ UINT ret = ERR_NO_ERROR;
+ UINT port;
+ TTS *tts;
+ PARAM args[] =
+ {
+ {"[port]", NULL, NULL, NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ port = GetParamInt(o, "[port]");
+ if (port == 0)
+ {
+ port = TRAFFIC_DEFAULT_PORT;
+ }
+
+ tts = NewTts(port, c, PtTrafficPrintProc);
+
+ c->Write(c, _UU("TTS_ENTER_TO_EXIT"));
+
+ Free(c->ReadLine(c, L"", true));
+
+ ret = tts->ErrorCode;
+
+ FreeTts(tts);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Execute the communication throughput measurement tool client
+UINT PtTrafficClient(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ TTC *ttc;
+ LIST *o;
+ UINT ret = ERR_NO_ERROR;
+ char *host = NULL;
+ UINT port;
+ UINT num, type;
+ bool dbl = false, raw = false;
+ UINT64 span;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_TrafficClient_EVAL_NUMTCP",
+ 0, TRAFFIC_NUMTCP_MAX,
+ };
+ PARAM args[] =
+ {
+ {"[host:port]", CmdPrompt, _UU("CMD_TrafficClient_PROMPT_HOST"), CmdEvalNotEmpty, NULL},
+ {"NUMTCP", NULL, NULL, CmdEvalMinMax, &minmax},
+ {"TYPE", NULL, NULL, NULL, NULL},
+ {"SPAN", NULL, NULL, NULL, NULL},
+ {"DOUBLE", NULL, NULL, NULL, NULL},
+ {"RAW", NULL, NULL, NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (ParseHostPort(GetParamStr(o, "[host:port]"), &host, &port, TRAFFIC_DEFAULT_PORT) == false)
+ {
+ c->Write(c, _UU("CMD_TrafficClient_ERROR_HOSTPORT"));
+ ret = ERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ char *s;
+ UINT i;
+
+ Trim(host);
+
+ num = GetParamInt(o, "NUMTCP");
+ if (num == 0)
+ {
+ num = TRAFFIC_NUMTCP_DEFAULT;
+ }
+ s = GetParamStr(o, "TYPE");
+
+ if (StartWith("download", s))
+ {
+ type = TRAFFIC_TYPE_DOWNLOAD;
+ }
+ else if (StartWith("upload", s))
+ {
+ type = TRAFFIC_TYPE_UPLOAD;
+ }
+ else
+ {
+ type = TRAFFIC_TYPE_FULL;
+ }
+
+ i = GetParamInt(o, "SPAN");
+
+ if (i == 0)
+ {
+ i = TRAFFIC_SPAN_DEFAULT;
+ }
+
+ span = (UINT64)i * 1000ULL;
+
+ dbl = GetParamYes(o, "DOUBLE");
+ raw = GetParamYes(o, "RAW");
+
+ if (type == TRAFFIC_TYPE_FULL)
+ {
+ if ((num % 2) != 0)
+ {
+ ret = ERR_INVALID_PARAMETER;
+ c->Write(c, _UU("CMD_TrafficClient_ERROR_NUMTCP"));
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ TT_RESULT result;
+ ttc = NewTtc(host, port, num, type, span, dbl, raw, PtTrafficPrintProc, c);
+
+ if (c->ConsoleType == CONSOLE_LOCAL)
+ {
+ if (c->Param != NULL && (((LOCAL_CONSOLE_PARAM *)c->Param)->InBuf == NULL))
+ {
+// c->Write(c, _UU("TTC_ENTER_TO_EXIT"));
+// GetLine(NULL, 0);
+// StopTtc(ttc);
+ }
+ }
+
+
+ Zero(&result, sizeof(result));
+ ret = FreeTtc(ttc, &result);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ TtcPrintResult(c, &result);
+ }
+ }
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ Free(host);
+
+ return ret;
+}
+
+// Certificate easy creation tool
+UINT PtMakeCert(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ UINT ret = ERR_NO_ERROR;
+ X *x = NULL;
+ K *pub = NULL;
+ K *pri = NULL;
+ NAME *n;
+ X_SERIAL *x_serial = NULL;
+ BUF *buf;
+ UINT days;
+ X *root_x = NULL;
+ K *root_k = NULL;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_MakeCert_EVAL_EXPIRES",
+ 0,
+ 10950,
+ };
+ PARAM args[] =
+ {
+ {"CN", CmdPrompt, _UU("CMD_MakeCert_PROMPT_CN"), NULL, NULL},
+ {"O", CmdPrompt, _UU("CMD_MakeCert_PROMPT_O"), NULL, NULL},
+ {"OU", CmdPrompt, _UU("CMD_MakeCert_PROMPT_OU"), NULL, NULL},
+ {"C", CmdPrompt, _UU("CMD_MakeCert_PROMPT_C"), NULL, NULL},
+ {"ST", CmdPrompt, _UU("CMD_MakeCert_PROMPT_ST"), NULL, NULL},
+ {"L", CmdPrompt, _UU("CMD_MakeCert_PROMPT_L"), NULL, NULL},
+ {"SERIAL", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SERIAL"), NULL, NULL},
+ {"EXPIRES", CmdPrompt, _UU("CMD_MakeCert_PROMPT_EXPIRES"), CmdEvalMinMax, &minmax},
+ {"SIGNCERT", NULL, NULL, CmdEvalIsFile, NULL},
+ {"SIGNKEY", NULL, NULL, CmdEvalIsFile, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},
+ {"SAVEKEY", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SAVEKEY"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "SIGNCERT")) == false && IsEmptyStr(GetParamStr(o, "SIGNKEY")) == false)
+ {
+ root_x = FileToXW(GetParamUniStr(o, "SIGNCERT"));
+ root_k = FileToKW(GetParamUniStr(o, "SIGNKEY"), true, NULL);
+
+ if (root_x == NULL || root_k == NULL || CheckXandK(root_x, root_k) == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+
+ c->Write(c, _UU("CMD_MakeCert_ERROR_SIGNKEY"));
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ buf = StrToBin(GetParamStr(o, "SERIAL"));
+ if (buf != NULL && buf->Size >= 1)
+ {
+ x_serial = NewXSerial(buf->Buf, buf->Size);
+ }
+ FreeBuf(buf);
+
+ n = NewName(GetParamUniStr(o, "CN"), GetParamUniStr(o, "O"), GetParamUniStr(o, "OU"),
+ GetParamUniStr(o, "C"), GetParamUniStr(o, "ST"), GetParamUniStr(o, "L"));
+
+ days = GetParamInt(o, "EXPIRES");
+ if (days == 0)
+ {
+ days = 3650;
+ }
+
+ RsaGen(&pri, &pub, 1024);
+
+ if (root_x == NULL)
+ {
+ x = NewRootX(pub, pri, n, days, x_serial);
+ }
+ else
+ {
+ x = NewX(pub, root_k, root_x, n, days, x_serial);
+ }
+
+ FreeXSerial(x_serial);
+ FreeName(n);
+
+ if (x == NULL)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ c->Write(c, _UU("CMD_MakeCert_ERROR_GEN_FAILED"));
+ }
+ else
+ {
+ if (XToFileW(x, GetParamUniStr(o, "SAVECERT"), true) == false)
+ {
+ c->Write(c, _UU("CMD_SAVECERT_FAILED"));
+ }
+ else if (KToFileW(pri, GetParamUniStr(o, "SAVEKEY"), true, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_SAVEKEY_FAILED"));
+ }
+ }
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ FreeX(root_x);
+ FreeK(root_k);
+
+ FreeX(x);
+ FreeK(pri);
+ FreeK(pub);
+
+ return ret;
+}
+
+
+// Client management tool main
+void PcMain(PC *pc)
+{
+ char prompt[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (pc == NULL)
+ {
+ return;
+ }
+
+ // Display a message that the connection has been made
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_CLIENT_CONNECTED"),
+ pc->ServerName);
+ pc->Console->Write(pc->Console, tmp);
+ pc->Console->Write(pc->Console, L"");
+
+ while (true)
+ {
+ // Definition of command
+ CMD cmd[] =
+ {
+ {"About", PsAbout},
+ {"Check", PtCheck},
+ {"VersionGet", PcVersionGet},
+ {"PasswordSet", PcPasswordSet},
+ {"PasswordGet", PcPasswordGet},
+ {"CertList", PcCertList},
+ {"CertAdd", PcCertAdd},
+ {"CertDelete", PcCertDelete},
+ {"CertGet", PcCertGet},
+ {"SecureList", PcSecureList},
+ {"SecureSelect", PcSecureSelect},
+ {"SecureGet", PcSecureGet},
+ {"NicCreate", PcNicCreate},
+ {"NicDelete", PcNicDelete},
+ {"NicUpgrade", PcNicUpgrade},
+ {"NicGetSetting", PcNicGetSetting},
+ {"NicSetSetting", PcNicSetSetting},
+ {"NicEnable", PcNicEnable},
+ {"NicDisable", PcNicDisable},
+ {"NicList", PcNicList},
+ {"AccountList", PcAccountList},
+ {"AccountCreate", PcAccountCreate},
+ {"AccountSet", PcAccountSet},
+ {"AccountGet", PcAccountGet},
+ {"AccountDelete", PcAccountDelete},
+ {"AccountUsernameSet", PcAccountUsernameSet},
+ {"AccountAnonymousSet", PcAccountAnonymousSet},
+ {"AccountPasswordSet", PcAccountPasswordSet},
+ {"AccountCertSet", PcAccountCertSet},
+ {"AccountCertGet", PcAccountCertGet},
+ {"AccountEncryptDisable", PcAccountEncryptDisable},
+ {"AccountEncryptEnable", PcAccountEncryptEnable},
+ {"AccountCompressEnable", PcAccountCompressEnable},
+ {"AccountCompressDisable", PcAccountCompressDisable},
+ {"AccountProxyNone", PcAccountProxyNone},
+ {"AccountProxyHttp", PcAccountProxyHttp},
+ {"AccountProxySocks", PcAccountProxySocks},
+ {"AccountServerCertEnable", PcAccountServerCertEnable},
+ {"AccountServerCertDisable", PcAccountServerCertDisable},
+ {"AccountServerCertSet", PcAccountServerCertSet},
+ {"AccountServerCertDelete", PcAccountServerCertDelete},
+ {"AccountServerCertGet", PcAccountServerCertGet},
+ {"AccountDetailSet", PcAccountDetailSet},
+ {"AccountRename", PcAccountRename},
+ {"AccountConnect", PcAccountConnect},
+ {"AccountDisconnect", PcAccountDisconnect},
+ {"AccountStatusGet", PcAccountStatusGet},
+ {"AccountNicSet", PcAccountNicSet},
+ {"AccountStatusShow", PcAccountStatusShow},
+ {"AccountStatusHide", PcAccountStatusHide},
+ {"AccountSecureCertSet", PcAccountSecureCertSet},
+ {"AccountRetrySet", PcAccountRetrySet},
+ {"AccountStartupSet", PcAccountStartupSet},
+ {"AccountStartupRemove", PcAccountStartupRemove},
+ {"AccountExport", PcAccountExport},
+ {"AccountImport", PcAccountImport},
+ {"RemoteEnable", PcRemoteEnable},
+ {"RemoteDisable", PcRemoteDisable},
+ {"KeepEnable", PcKeepEnable},
+ {"KeepDisable", PcKeepDisable},
+ {"KeepSet", PcKeepSet},
+ {"KeepGet", PcKeepGet},
+ {"MakeCert", PtMakeCert},
+ {"TrafficClient", PtTrafficClient},
+ {"TrafficServer", PtTrafficServer},
+ };
+
+ // Generate a prompt
+ StrCpy(prompt, sizeof(prompt), "VPN Client>");
+
+ if (DispatchNextCmdEx(pc->Console, pc->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), pc) == false)
+ {
+ break;
+ }
+ pc->LastError = pc->Console->RetCode;
+
+ if (pc->LastError == ERR_NO_ERROR && pc->Console->ConsoleType != CONSOLE_CSV)
+ {
+ pc->Console->Write(pc->Console, _UU("CMD_MSG_OK"));
+ pc->Console->Write(pc->Console, L"");
+ }
+
+ if (pc->CmdLine != NULL)
+ {
+ break;
+ }
+ }
+}
+
+// Retrieve the version information of VPN Client service
+UINT PcVersionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_VERSION t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientVersion(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct;
+
+ // Success
+ ct = CtNewStandard();
+
+ StrToUni(tmp, sizeof(tmp), t.ClientProductName);
+ CtInsert(ct, _UU("CMD_VersionGet_1"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.ClientVersionString);
+ CtInsert(ct, _UU("CMD_VersionGet_2"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.ClientBuildInfoString);
+ CtInsert(ct, _UU("CMD_VersionGet_3"), tmp);
+
+ UniToStru(tmp, t.ProcessId);
+ CtInsert(ct, _UU("CMD_VersionGet_4"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), OsTypeToStr(t.OsType));
+ CtInsert(ct, _UU("CMD_VersionGet_5"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set a password to connect to the VPN Client Service
+UINT PcPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_PASSWORD t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},
+ {"REMOTEONLY", NULL, NULL, NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.Password, sizeof(t.Password), GetParamStr(o, "[password]"));
+ t.PasswordRemoteOnly = GetParamYes(o, "REMOTEONLY");
+
+ ret = CcSetPassword(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the settings of the password to connect to the VPN Client service
+UINT PcPasswordGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_PASSWORD_SETTING t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetPasswordSetting(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_PasswordGet_1"),
+ t.IsPasswordPresented ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ CtInsert(ct, _UU("CMD_PasswordGet_2"),
+ t.PasswordRemoteOnly ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ CtFree(ct, c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the list of certificates of the trusted certification authority
+UINT PcCertList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_ENUM_CA t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcEnumCa(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ UINT i;
+ CT *ct = CtNewStandard();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[64];
+ RPC_CLIENT_ENUM_CA_ITEM *e = t.Items[i];
+
+ GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);
+
+ UniToStru(tmp2, e->Key);
+
+ CtInsert(ct, _UU("CMD_CAList_COLUMN_ID"), tmp2);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_1"), e->SubjectName);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_2"), e->IssuerName);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_3"), tmp);
+
+ if (i != (t.NumItem - 1))
+ {
+ CtInsert(ct, L"---", L"---");
+ }
+ }
+
+ CtFree(ct, c);
+
+ CiFreeClientEnumCa(&t);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Add a certificate of the trusted certification authority
+UINT PcCertAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CERT t;
+ X *x;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[path]", CmdPrompt, _UU("CMD_CAAdd_PROMPT_PATH"), CmdEvalIsFile, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+
+ x = FileToXW(GetParamUniStr(o, "[path]"));
+
+ if (x == NULL)
+ {
+ FreeParamValueList(o);
+ c->Write(c, _UU("CMD_MSG_LOAD_CERT_FAILED"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ t.x = x;
+
+ ret = CcAddCa(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ FreeX(x);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Delete the certificate of the trusted certification authority
+UINT PcCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_DELETE_CA t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[id]", CmdPrompt, _UU("CMD_CADelete_PROMPT_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ t.Key = GetParamInt(o, "[id]");
+
+ ret = CcDeleteCa(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the certificate of the trusted certification authority
+UINT PcCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_GET_CA t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[id]", CmdPrompt, _UU("CMD_CAGet_PROMPT_ID"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_CAGet_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ t.Key = GetParamInt(o, "[id]");
+
+ ret = CcGetCa(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ if (XToFileW(t.x, GetParamUniStr(o, "SAVECERT"), true))
+ {
+ // Success
+ }
+ else
+ {
+ // Failure
+ ret = ERR_INTERNAL_ERROR;
+ c->Write(c, _UU("CMD_MSG_SAVE_CERT_FAILED"));
+ }
+
+ CiFreeGetCa(&t);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the list of the type of smart card that can be used
+UINT PcSecureList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_ENUM_SECURE t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcEnumSecure(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ CT *ct;
+ UINT i;
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t *tmp3;
+
+ // Success
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("SEC_COLUMN1"), false);
+ CtInsertColumn(ct, _UU("SEC_COLUMN2"), false);
+ CtInsertColumn(ct, _UU("SEC_COLUMN3"), false);
+ CtInsertColumn(ct, _UU("SEC_COLUMN4"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_SECURE_ITEM *e = t.Items[i];
+
+ // ID
+ UniToStru(tmp1, e->DeviceId);
+
+ // Device name
+ StrToUni(tmp2, sizeof(tmp2), e->DeviceName);
+
+ // Type
+ tmp3 = (e->Type == SECURE_IC_CARD) ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN");
+
+ // Manufacturer
+ StrToUni(tmp4, sizeof(tmp4), e->Manufacturer);
+
+ CtInsert(ct, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ CtFreeEx(ct, c, true);
+
+ CiFreeClientEnumSecure(&t);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Select the type of smart card to be used
+UINT PcSecureSelect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_USE_SECURE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[id]", CmdPrompt, _UU("CMD_SecureSelect_PROMPT_ID"), NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ t.DeviceId = GetParamInt(o, "[id]");
+
+ ret = CcUseSecure(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the type ID of smart card to be used
+UINT PcSecureGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_USE_SECURE t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetUseSecure(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ wchar_t tmp[MAX_SIZE];
+
+ if (t.DeviceId != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_SecureGet_Print"), t.DeviceId);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CMD_SecureGet_NoPrint"));
+ }
+ c->Write(c, tmp);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Create a new virtual LAN card
+UINT PcNicCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcCreateVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Delete the virtual LAN card
+UINT PcNicDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcDeleteVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Upgrading the device driver of the virtual LAN card
+UINT PcNicUpgrade(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcUpgradeVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the settings of the virtual LAN card
+UINT PcNicGetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcGetVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ CT *ct = CtNewStandard();
+ wchar_t tmp[MAX_SIZE];
+
+ StrToUni(tmp, sizeof(tmp), t.DeviceName);
+ CtInsert(ct, _UU("CMD_NicGetSetting_1"), tmp);
+
+ CtInsert(ct, _UU("CMD_NicGetSetting_2"), t.Enabled ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ StrToUni(tmp, sizeof(tmp), t.MacAddress);
+ CtInsert(ct, _UU("CMD_NicGetSetting_3"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.Version);
+ CtInsert(ct, _UU("CMD_NicGetSetting_4"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.FileName);
+ CtInsert(ct, _UU("CMD_NicGetSetting_5"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.Guid);
+ CtInsert(ct, _UU("CMD_NicGetSetting_6"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Change the settings for the virtual LAN card
+UINT PcNicSetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_SET_VLAN t;
+ UCHAR mac_address[6];
+ BUF *b;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"MAC", CmdPrompt, _UU("CMD_NicSetSetting_PROMPT_MAC"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Inspect the MAC address
+ Zero(mac_address, sizeof(mac_address));
+ b = StrToBin(GetParamStr(o, "MAC"));
+ if (b != NULL && b->Size == 6)
+ {
+ Copy(mac_address, b->Buf, 6);
+ }
+ FreeBuf(b);
+
+ if (IsZero(mac_address, 6))
+ {
+ // MAC address is invalid
+ FreeParamValueList(o);
+
+ CmdPrintError(c, ERR_INVALID_PARAMETER);
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+ NormalizeMacAddress(t.MacAddress, sizeof(t.MacAddress), GetParamStr(o, "MAC"));
+
+ ret = CcSetVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable the virtual LAN card
+UINT PcNicEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcEnableVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable the virtual LAN card
+UINT PcNicDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_VLAN t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));
+
+ ret = CcDisableVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the Virtual LAN card list
+UINT PcNicList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_ENUM_VLAN t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcEnumVLan(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ CT *ct;
+ UINT i;
+
+ // Success
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t name[MAX_SIZE];
+ wchar_t mac[MAX_SIZE];
+ wchar_t ver[MAX_SIZE];
+ wchar_t *status;
+ RPC_CLIENT_ENUM_VLAN_ITEM *v = t.Items[i];
+
+ // Device name
+ StrToUni(name, sizeof(name), v->DeviceName);
+
+ // State
+ status = v->Enabled ? _UU("CM_VLAN_ENABLED") : _UU("CM_VLAN_DISABLED");
+
+ // MAC address
+ StrToUni(mac, sizeof(mac), v->MacAddress);
+
+ // Version
+ StrToUni(ver, sizeof(ver), v->Version);
+
+ CtInsert(ct,
+ name, status, mac, ver);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientEnumVLan(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the protocol name string from ID
+wchar_t *GetProtocolName(UINT n)
+{
+ switch (n)
+ {
+ case PROXY_DIRECT:
+ return _UU("PROTO_DIRECT_TCP");
+ case PROXY_HTTP:
+ return _UU("PROTO_HTTP_PROXY");
+ case PROXY_SOCKS:
+ return _UU("PROTO_SOCKS_PROXY");
+ }
+
+ return _UU("PROTO_UNKNOWN");
+}
+
+// Get the connection settings list
+UINT PcAccountList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_ENUM_ACCOUNT t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcEnumAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ UINT i;
+ CT *ct;
+
+ // Success
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_3_2"), false);
+ CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = t.Items[i];
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ IP ip;
+ char ip_str[MAX_SIZE];
+
+ // Special treatment for IPv6 addresses
+ if (StrToIP6(&ip, e->ServerName) && StartWith(e->ServerName, "[") == false)
+ {
+ Format(ip_str, sizeof(ip_str),
+ "[%s]", e->ServerName);
+ }
+ else
+ {
+ StrCpy(ip_str, sizeof(ip_str), e->ServerName);
+ }
+
+ if (e->Port == 0)
+ {
+ // Port number unknown
+ UniFormat(tmp2, sizeof(tmp2), L"%S (%s)", ip_str, GetProtocolName(e->ProxyType));
+ }
+ else
+ {
+ // Port number are also shown
+ UniFormat(tmp2, sizeof(tmp2), L"%S:%u (%s)", ip_str, e->Port, GetProtocolName(e->ProxyType));
+ }
+
+ // Virtual HUB name
+ StrToUni(tmp4, sizeof(tmp4), e->HubName);
+
+ // Add
+ StrToUni(tmp, sizeof(tmp), e->DeviceName);
+
+ CtInsert(ct,
+ e->AccountName,
+ e->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :
+ (e->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),
+ tmp2, tmp4,
+ tmp);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ CiFreeClientEnumAccount(&t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Create new connection settings
+UINT PcAccountCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CREATE_ACCOUNT t;
+ UINT port = 443;
+ char *host = NULL;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Hub"), CmdEvalSafe, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},
+ {"NICNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Nicname"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+ t.ClientOption->Port = port;
+ StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);
+ StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));
+ t.ClientOption->NumRetry = INFINITE;
+ t.ClientOption->RetryInterval = 15;
+ t.ClientOption->MaxConnection = 1;
+ t.ClientOption->UseEncrypt = true;
+ t.ClientOption->AdditionalConnectionInterval = 1;
+ StrCpy(t.ClientOption->DeviceName, sizeof(t.ClientOption->DeviceName), GetParamStr(o, "NICNAME"));
+
+ t.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;
+ StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));
+
+ Free(host);
+
+ ret = CcCreateAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ CiFreeClientCreateAccount(&t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the destination of the connection settings
+UINT PcAccountSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ char *host = NULL;
+ UINT port = 443;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Hub"), CmdEvalSafe, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);
+
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT c;
+ // Success
+ t.ClientOption->Port = port;
+ StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);
+ StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));
+
+ Zero(&c, sizeof(c));
+
+ c.ClientAuth = t.ClientAuth;
+ c.ClientOption = t.ClientOption;
+ c.CheckServerCert = t.CheckServerCert;
+ c.ServerCert = t.ServerCert;
+ c.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ Free(host);
+
+ return ret;
+}
+
+// Get the configuration of the connection settings
+UINT PcAccountGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Show the contents of the connection settings
+ wchar_t tmp[MAX_SIZE];
+
+ CT *ct = CtNewStandard();
+
+ // Connection settings name
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NAME"), t.ClientOption->AccountName);
+
+ // Host name of the destination VPN Server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->Hostname);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HOSTNAME"), tmp);
+
+ // The port number to connect to VPN Server
+ UniToStru(tmp, t.ClientOption->Port);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PORT"), tmp);
+
+ // Virtual HUB name of the destination VPN Server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->HubName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HUBNAME"), tmp);
+
+ // Type of proxy server to go through
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_TYPE"), GetProxyTypeStr(t.ClientOption->ProxyType));
+
+ if (t.ClientOption->ProxyType != PROXY_DIRECT)
+ {
+ // Host name of the proxy server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME"), tmp);
+
+ // Port number of the proxy server
+ UniToStru(tmp, t.ClientOption->ProxyPort);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_PORT"), tmp);
+
+ // User name of the proxy server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyUsername);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_USERNAME"), tmp);
+ }
+
+ // Verify the server certificate
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_USE"),
+ t.CheckServerCert ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Registered specific certificate
+ if (t.ServerCert != NULL)
+ {
+ GetAllNameFromX(tmp, sizeof(tmp), t.ServerCert);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME"), tmp);
+ }
+
+ // Device name to be used for the connection
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->DeviceName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_DEVICE_NAME"), tmp);
+
+ // Authentication type
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_TYPE"), GetClientAuthTypeStr(t.ClientAuth->AuthType));
+
+ // User name
+ StrToUni(tmp, sizeof(tmp), t.ClientAuth->Username);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_USERNAME"), tmp);
+
+ if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (t.ClientAuth->ClientX != NULL)
+ {
+ // Client certificate name
+ GetAllNameFromX(tmp, sizeof(tmp), t.ClientAuth->ClientX);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME"), tmp);
+ }
+ }
+
+ // Number of TCP connections to be used for VPN communication
+ UniToStru(tmp, t.ClientOption->MaxConnection);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NUMTCP"), tmp);
+
+ // Establishment interval of each TCP connection
+ UniToStru(tmp, t.ClientOption->AdditionalConnectionInterval);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_INTERVAL"), tmp);
+
+ // Life span of each TCP connection
+ if (t.ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ UniToStru(tmp, t.ClientOption->ConnectionDisconnectSpan);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));
+ }
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_TTL"), tmp);
+
+ // Use of half-duplex mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_HALF"),
+ t.ClientOption->HalfConnection ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Encryption by SSL
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_ENCRYPT"),
+ t.ClientOption->UseEncrypt ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Data compression
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_COMPRESS"),
+ t.ClientOption->UseCompress ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Connect in bridge / router mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER"),
+ t.ClientOption->RequireBridgeRoutingMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Connect in monitoring mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_MONITOR"),
+ t.ClientOption->RequireMonitorMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Not to rewrite the routing table
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NO_TRACKING"),
+ t.ClientOption->NoRoutingTracking ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Disable the QoS control
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_QOS_DISABLE"),
+ t.ClientOption->DisableQoS ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ CtFree(ct, c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Delete the connection settings
+UINT PcAccountDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_DELETE_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcDeleteAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the user name used to connect with connection settings
+UINT PcAccountUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));
+
+ if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ c->Write(c, _UU("CMD_AccountUsername_Notice"));
+ }
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the type of user authentication of connection settings to anonymous authentication
+UINT PcAccountAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the type of user authentication of connection settings to the password authentication
+UINT PcAccountPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ {"TYPE", CmdPrompt, _UU("CMD_CascadePasswordSet_Prompt_Type"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ char *typestr = GetParamStr(o, "TYPE");
+ RPC_CLIENT_CREATE_ACCOUNT z;
+
+ // Change the settings
+ if (StartWith("standard", typestr))
+ {
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
+ HashPassword(t.ClientAuth->HashedPassword, t.ClientAuth->Username,
+ GetParamStr(o, "PASSWORD"));
+ }
+ else if (StartWith("radius", typestr) || StartWith("ntdomain", typestr))
+ {
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PLAIN_PASSWORD;
+
+ StrCpy(t.ClientAuth->PlainPassword, sizeof(t.ClientAuth->PlainPassword),
+ GetParamStr(o, "PASSWORD"));
+ }
+ else
+ {
+ // Error has occured
+ c->Write(c, _UU("CMD_CascadePasswordSet_Type_Invalid"));
+ ret = ERR_INVALID_PARAMETER;
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the type of user authentication of connection settings to the client certificate authentication
+UINT PcAccountCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ X *x;
+ K *k;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (CmdLoadCertAndKey(c, &x, &k, GetParamUniStr(o, "LOADCERT"), GetParamUniStr(o, "LOADKEY")) == false)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_CERT;
+ if (t.ClientAuth->ClientX != NULL)
+ {
+ FreeX(t.ClientAuth->ClientX);
+ }
+ if (t.ClientAuth->ClientK != NULL)
+ {
+ FreeK(t.ClientAuth->ClientK);
+ }
+
+ t.ClientAuth->ClientX = CloneX(x);
+ t.ClientAuth->ClientK = CloneK(k);
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ FreeX(x);
+ FreeK(k);
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the client certificate to be used for the connection settings
+UINT PcAccountCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT)
+ {
+ c->Write(c, _UU("CMD_CascadeCertSet_Not_Auth_Cert"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else if (t.ClientAuth->ClientX == NULL)
+ {
+ c->Write(c, _UU("CMD_CascadeCertSet_Cert_Not_Exists"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ XToFileW(t.ClientAuth->ClientX, GetParamUniStr(o, "SAVECERT"), true);
+ }
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable communication encryption with the connection settings
+UINT PcAccountEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->UseEncrypt = false;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable communication encryption with the connection settings
+UINT PcAccountEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->UseEncrypt = true;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable communication data compression with the connection settings
+UINT PcAccountCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->UseCompress = true;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable communication data compression with the connection settings
+UINT PcAccountCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->UseCompress = false;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the connection method of the connection settings to the direct TCP/IP connection
+UINT PcAccountProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->ProxyType = PROXY_DIRECT;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the connection method of the connection settings to the HTTP proxy server connection
+UINT PcAccountProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_AccountProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"USERNAME", NULL, NULL, NULL, NULL},
+ {"PASSWORD", NULL, NULL, NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ char *host;
+ UINT port;
+
+ // Data change
+ if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))
+ {
+ t.ClientOption->ProxyType = PROXY_HTTP;
+ StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);
+ t.ClientOption->ProxyPort = port;
+ StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));
+ StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));
+ Free(host);
+ }
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the connection method of the connection settings to the SOCKS proxy server connection
+UINT PcAccountProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_AccountProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"USERNAME", NULL, NULL, NULL, NULL},
+ {"PASSWORD", NULL, NULL, NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ char *host;
+ UINT port;
+
+ // Data change
+ if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))
+ {
+ t.ClientOption->ProxyType = PROXY_SOCKS;
+ StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);
+ t.ClientOption->ProxyPort = port;
+ StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));
+ StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));
+ Free(host);
+ }
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable validation option for server certificate of connection settings
+UINT PcAccountServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.CheckServerCert = true;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable validation option of the server certificate of connection settings
+UINT PcAccountServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.CheckServerCert = false;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the server-specific certificate of connection settings
+UINT PcAccountServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ X *x;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ x = FileToXW(GetParamUniStr(o, "LOADCERT"));
+ if (x == NULL)
+ {
+ FreeParamValueList(o);
+ c->Write(c, _UU("CMD_LOADCERT_FAILED"));
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ if (t.ServerCert != NULL)
+ {
+ FreeX(t.ServerCert);
+ }
+ t.ServerCert = CloneX(x);
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ FreeX(x);
+
+ return ret;
+}
+
+// Delete a server-specific certificate of connection settings
+UINT PcAccountServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ if (t.ServerCert != NULL)
+ {
+ FreeX(t.ServerCert);
+ }
+ t.ServerCert = NULL;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get a server-specific certificate of connection settings
+UINT PcAccountServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ if (t.ServerCert != NULL)
+ {
+ FreeX(t.ServerCert);
+ }
+ t.ServerCert = NULL;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the advanced settings of connection settings
+UINT PcAccountDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ CMD_EVAL_MIN_MAX mm_maxtcp =
+ {
+ "CMD_CascadeDetailSet_Eval_MaxTcp", 1, 32
+ };
+ CMD_EVAL_MIN_MAX mm_interval =
+ {
+ "CMD_CascadeDetailSet_Eval_Interval", 1, 4294967295UL
+ };
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"MAXTCP", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_MaxTcp"), CmdEvalMinMax, &mm_maxtcp},
+ {"INTERVAL", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_Interval"), CmdEvalMinMax, &mm_interval},
+ {"TTL", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_TTL"), NULL, NULL},
+ {"HALF", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_HALF"), NULL, NULL},
+ {"BRIDGE", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_BRIDGE"), NULL, NULL},
+ {"MONITOR", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_MONITOR"), NULL, NULL},
+ {"NOTRACK", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOTRACK"), NULL, NULL},
+ {"NOQOS", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOQOS"), NULL, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Data change
+ t.ClientOption->MaxConnection = GetParamInt(o, "MAXTCP");
+ t.ClientOption->AdditionalConnectionInterval = GetParamInt(o, "INTERVAL");
+ t.ClientOption->ConnectionDisconnectSpan = GetParamInt(o, "TTL");
+ t.ClientOption->HalfConnection = GetParamYes(o, "HALF");
+ t.ClientOption->RequireBridgeRoutingMode = GetParamYes(o, "BRIDGE");
+ t.ClientOption->RequireMonitorMode = GetParamYes(o, "MONITOR");
+ t.ClientOption->NoRoutingTracking = GetParamYes(o, "NOTRACK");
+ t.ClientOption->DisableQoS = GetParamYes(o, "NOQOS");
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Change the name of the connection settings
+UINT PcAccountRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_RENAME_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountRename_PROMPT_OLD"), CmdEvalNotEmpty, NULL},
+ {"NEW", CmdPrompt, _UU("CMD_AccountRename_PROMPT_NEW"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.NewName, sizeof(t.NewName), GetParamUniStr(o, "NEW"));
+ UniStrCpy(t.OldName, sizeof(t.OldName), GetParamUniStr(o, "[name]"));
+
+ ret = CcRenameAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Start to connect to the VPN Server using the connection settings
+UINT PcAccountConnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CONNECT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcConnect(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disconnect the connection settings of connected
+UINT PcAccountDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_CONNECT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcDisconnect(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the current state of the connection settings
+UINT PcAccountStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_CONNECTION_STATUS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccountStatus(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ if (t.Active == false)
+ {
+ // Has been disconnected
+ ret = ERR_ACCOUNT_INACTIVE;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+
+ CmdPrintStatusToListView(ct, &t);
+
+ CtFree(ct, c);
+ }
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetConnectionStatus(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set a virtual LAN card to be used in the connection settings
+UINT PcAccountNicSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"NICNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Nicname"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT c;
+ // Success
+ StrCpy(t.ClientOption->DeviceName, sizeof(t.ClientOption->DeviceName),
+ GetParamStr(o, "NICNAME"));
+
+ Zero(&c, sizeof(c));
+
+ c.ClientAuth = t.ClientAuth;
+ c.ClientOption = t.ClientOption;
+ c.CheckServerCert = t.CheckServerCert;
+ c.ServerCert = t.ServerCert;
+ c.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set to display error screens and connection status while connecting to the VPN Server
+UINT PcAccountStatusShow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->HideStatusWindow = false;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Configure not to display error screens and connection status while connecting to the VPN Server
+UINT PcAccountStatusHide(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientOption->HideStatusWindow = true;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the type of user authentication of connection settings to the smart card authentication
+UINT PcAccountSecureCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"CERTNAME", CmdPrompt, _UU("CMD_AccountSecureCertSet_PROMPT_CERTNAME"), CmdEvalNotEmpty, NULL},
+ {"KEYNAME", CmdPrompt, _UU("CMD_AccountSecureCertSet_PROMPT_KEYNAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_SECURE;
+ StrCpy(t.ClientAuth->SecurePublicCertName, sizeof(t.ClientAuth->SecurePublicCertName),
+ GetParamStr(o, "CERTNAME"));
+ StrCpy(t.ClientAuth->SecurePrivateKeyName, sizeof(t.ClientAuth->SecurePrivateKeyName),
+ GetParamStr(o, "KEYNAME"));
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the retry interval and number of retries when disconnect or connection failure of connection settings
+UINT PcAccountRetrySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_AccountRetrySet_EVAL_INTERVAL",
+ 5,
+ 4294967295UL,
+ };
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"NUM", CmdPrompt, _UU("CMD_AccountRetrySet_PROMPT_NUM"), CmdEvalNotEmpty, NULL},
+ {"INTERVAL", CmdPrompt, _UU("CMD_AccountRetrySet_PROMPY_INTERVAL"), CmdEvalMinMax, &minmax},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ UINT num = GetParamInt(o, "NUM");
+ UINT interval = GetParamInt(o, "INTERVAL");
+
+ t.ClientOption->NumRetry = (num == 999) ? INFINITE : num;
+ t.ClientOption->RetryInterval = interval;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+
+// Set to start-up connection the connection settings
+UINT PcAccountStartupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.StartupAccount = true;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Unset the start-up connection of the connection settings
+UINT PcAccountStartupRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ // Change the settings
+ t.StartupAccount = false;
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ ret = CcSetAccount(pc->RemoteClient, &z);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Export the connection settings
+UINT PcAccountExport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ RPC_CLIENT_GET_ACCOUNT t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SAVEPATH", CmdPrompt, _UU("CMD_AccountExport_PROMPT_SAVEPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = CcGetAccount(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ RPC_CLIENT_CREATE_ACCOUNT z;
+ BUF *b;
+ BUF *b2;
+ char tmp[MAX_SIZE];
+ UCHAR *buf;
+ UINT buf_size;
+ UCHAR bom[] = {0xef, 0xbb, 0xbf, };
+
+ Zero(&z, sizeof(z));
+ z.CheckServerCert = t.CheckServerCert;
+ z.ClientAuth = t.ClientAuth;
+ z.ClientOption = t.ClientOption;
+ z.ServerCert = t.ServerCert;
+ z.StartupAccount = t.StartupAccount;
+
+ b = CiAccountToCfg(&z);
+
+ StrCpy(tmp, sizeof(tmp), GetParamStr(o, "SAVEPATH"));
+ b2 = NewBuf();
+
+ WriteBuf(b2, bom, sizeof(bom));
+
+ // Add the header part
+ buf_size = CalcUniToUtf8(_UU("CM_ACCOUNT_FILE_BANNER"));
+ buf = ZeroMalloc(buf_size + 32);
+ UniToUtf8(buf, buf_size, _UU("CM_ACCOUNT_FILE_BANNER"));
+
+ WriteBuf(b2, buf, StrLen((char *)buf));
+ WriteBuf(b2, b->Buf, b->Size);
+ SeekBuf(b2, 0, 0);
+
+ FreeBuf(b);
+
+ if (DumpBuf(b2, tmp) == false)
+ {
+ c->Write(c, _UU("CMD_SAVEFILE_FAILED"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+
+ FreeBuf(b2);
+ Free(buf);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ CiFreeClientGetAccount(&t);
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Check whether the specified account name exists
+bool CmdIsAccountName(REMOTE_CLIENT *r, wchar_t *name)
+{
+ UINT i;
+ RPC_CLIENT_ENUM_ACCOUNT t;
+ wchar_t tmp[MAX_SIZE];
+ bool b = false;
+ // Validate arguments
+ if (r == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ if (CcEnumAccount(r, &t) != ERR_NO_ERROR)
+ {
+ return false;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), name);
+ UniTrim(tmp);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ if (UniStrCmpi(t.Items[i]->AccountName, tmp) == 0)
+ {
+ b = true;
+ break;
+ }
+ }
+
+ CiFreeClientEnumAccount(&t);
+
+ return b;
+}
+
+// Generate an import name
+void CmdGenerateImportName(REMOTE_CLIENT *r, wchar_t *name, UINT size, wchar_t *old_name)
+{
+ UINT i;
+ // Validate arguments
+ if (r == NULL || name == NULL || old_name == NULL)
+ {
+ return;
+ }
+
+ for (i = 1;;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ if (i == 1)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_1"), old_name);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_2"), old_name, i);
+ }
+
+ if (CmdIsAccountName(r, tmp) == false)
+ {
+ UniStrCpy(name, size, tmp);
+ return;
+ }
+ }
+}
+
+// Import a connection setting
+UINT PcAccountImport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ BUF *b;
+ wchar_t name[MAX_SIZE];
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[path]", CmdPrompt, _UU("CMD_AccountImport_PROMPT_PATH"), CmdEvalIsFile, NULL},
+ };
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Read the file
+ b = ReadDumpW(GetParamUniStr(o, "[path]"));
+
+ if (b == NULL)
+ {
+ // Read failure
+ c->Write(c, _UU("CMD_LOADFILE_FAILED"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ RPC_CLIENT_CREATE_ACCOUNT *t;
+
+ t = CiCfgToAccount(b);
+
+ if (t == NULL)
+ {
+ // Failed to parse
+ c->Write(c, _UU("CMD_AccountImport_FAILED_PARSE"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ CmdGenerateImportName(pc->RemoteClient, name, sizeof(name), t->ClientOption->AccountName);
+ UniStrCpy(t->ClientOption->AccountName, sizeof(t->ClientOption->AccountName), name);
+
+ ret = CcCreateAccount(pc->RemoteClient, t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_AccountImport_OK"), name);
+ c->Write(c, tmp);
+ }
+
+ CiFreeClientCreateAccount(t);
+ Free(t);
+ }
+
+ FreeBuf(b);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Allow remote management of the VPN Client Service
+UINT PcRemoteEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ t.AllowRemoteConfig = true;
+ ret = CcSetClientConfig(pc->RemoteClient, &t);
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Prohibit remote management of the VPN Client Service
+UINT PcRemoteDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ t.AllowRemoteConfig = false;
+ ret = CcSetClientConfig(pc->RemoteClient, &t);
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable the maintenance function of the Internet connection
+UINT PcKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Change the settings
+ t.UseKeepConnect = true;
+ ret = CcSetClientConfig(pc->RemoteClient, &t);
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable the maintenance function of the Internet connection
+UINT PcKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+
+ // Get the parameter list
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Change the settings
+ t.UseKeepConnect = false;
+ ret = CcSetClientConfig(pc->RemoteClient, &t);
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the maintenance function of the Internet connection
+UINT PcKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+ char *host;
+ UINT port;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"HOST", CmdPrompt, _UU("CMD_KeepSet_PROMPT_HOST"), CmdEvalHostAndPort, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_PROTOCOL"), CmdEvalTcpOrUdp, NULL},
+ {"INTERVAL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_INTERVAL"), NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, 0))
+ {
+ StrCpy(t.KeepConnectHost, sizeof(t.KeepConnectHost), host);
+ t.KeepConnectPort = port;
+ t.KeepConnectInterval = GetParamInt(o, "INTERVAL");
+ t.KeepConnectProtocol = (StrCmpi(GetParamStr(o, "PROTOCOL"), "tcp") == 0) ? 0 : 1;
+ Free(host);
+
+ ret = CcSetClientConfig(pc->RemoteClient, &t);
+ }
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the maintenance function of the Internet connection
+UINT PcKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PC *pc = (PC *)param;
+ UINT ret = ERR_NO_ERROR;
+ CLIENT_CONFIG t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ Zero(&t, sizeof(t));
+
+ ret = CcGetClientConfig(pc->RemoteClient, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ StrToUni(tmp, sizeof(tmp), t.KeepConnectHost);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_1"), tmp);
+
+ UniToStru(tmp, t.KeepConnectPort);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_2"), tmp);
+
+ UniToStru(tmp, t.KeepConnectInterval);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_3"), tmp);
+
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_4"),
+ t.KeepConnectProtocol == 0 ? L"TCP/IP" : L"UDP/IP");
+
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_5"),
+ t.UseKeepConnect ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"));
+
+ CtFree(ct, c);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // Error has occurred
+ CmdPrintError(c, ret);
+ }
+
+ // Release of the parameter list
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+
+// Creat a new client management tool context
+PC *NewPc(CONSOLE *c, REMOTE_CLIENT *remote_client, char *servername, wchar_t *cmdline)
+{
+ PC *pc;
+ // Validate arguments
+ if (c == NULL || remote_client == NULL || servername == NULL)
+ {
+ return NULL;
+ }
+ if (UniIsEmptyStr(cmdline))
+ {
+ cmdline = NULL;
+ }
+
+ pc = ZeroMalloc(sizeof(PC));
+ pc->ConsoleForServer = false;
+ pc->ServerName = CopyStr(servername);
+ pc->Console = c;
+ pc->LastError = 0;
+ pc->RemoteClient = remote_client;
+ pc->CmdLine = CopyUniStr(cmdline);
+
+ return pc;
+}
+
+// Release the client management tools context
+void FreePc(PC *pc)
+{
+ // Validate arguments
+ if (pc == NULL)
+ {
+ return;
+ }
+
+ Free(pc->ServerName);
+ Free(pc->CmdLine);
+ Free(pc);
+}
+
+// Client management tool
+UINT PcConnect(CONSOLE *c, char *target, wchar_t *cmdline, char *password)
+{
+ CEDAR *cedar;
+ REMOTE_CLIENT *client;
+ bool bad_pass;
+ bool no_remote;
+ char pass[MAX_SIZE];
+ UINT ret = 0;
+ // Validate arguments
+ if (c == NULL || target == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ StrCpy(pass, sizeof(pass), password);
+
+ cedar = NewCedar(NULL, NULL);
+
+RETRY:
+ client = CcConnectRpc(target, pass, &bad_pass, &no_remote, 0);
+
+ if (client == NULL)
+ {
+ if (no_remote)
+ {
+ // Remote connection refusal
+ c->Write(c, _UU("CMD_VPNCMD_CLIENT_NO_REMODE"));
+ ReleaseCedar(cedar);
+ return ERR_INTERNAL_ERROR;
+ }
+ else if (bad_pass)
+ {
+ char *tmp;
+ // Password is different
+ c->Write(c, _UU("CMD_VPNCMD_PASSWORD_1"));
+ tmp = c->ReadPassword(c, _UU("CMD_VPNCMD_PASSWORD_2"));
+ c->Write(c, L"");
+
+ if (tmp == NULL)
+ {
+ // Cancel
+ ReleaseCedar(cedar);
+ return ERR_ACCESS_DENIED;
+ }
+ else
+ {
+ StrCpy(pass, sizeof(pass), tmp);
+ Free(tmp);
+ }
+
+ goto RETRY;
+ }
+ else
+ {
+ // Connection failure
+ CmdPrintError(c, ERR_CONNECT_FAILED);
+ ReleaseCedar(cedar);
+ return ERR_CONNECT_FAILED;
+ }
+ }
+ else
+ {
+ // Connection complete
+ PC *pc = NewPc(c, client, target, cmdline);
+ PcMain(pc);
+ ret = pc->LastError;
+ FreePc(pc);
+ }
+
+ CcDisconnectRpc(client);
+
+ ReleaseCedar(cedar);
+
+ return ret;
+}
+
+
+// Server Administration Tool Processor Main
+void PsMain(PS *ps)
+{
+ char prompt[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (ps == NULL)
+ {
+ return;
+ }
+
+ // If it's not in CSV mode, to display a message that the connection has been made
+ if(ps->Console->ConsoleType != CONSOLE_CSV)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_SERVER_CONNECTED"),
+ ps->ServerName, ps->ServerPort);
+ ps->Console->Write(ps->Console, tmp);
+ ps->Console->Write(ps->Console, L"");
+
+ if (ps->HubName == NULL)
+ {
+ // Server management mode
+ ps->Console->Write(ps->Console, _UU("CMD_VPNCMD_SERVER_CONNECTED_1"));
+ }
+ else
+ {
+ // Virtual HUB management mode
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_SERVER_CONNECTED_2"),
+ ps->HubName);
+ ps->Console->Write(ps->Console, tmp);
+ }
+ ps->Console->Write(ps->Console, L"");
+ }
+
+ // Get the Caps
+ ps->CapsList = ScGetCapsEx(ps->Rpc);
+
+ if (ps->AdminHub != NULL)
+ {
+ RPC_HUB_STATUS t;
+ UINT ret;
+ wchar_t tmp[MAX_SIZE];
+
+ // Choose the Virtual HUB that is specified in the ADMINHUB
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->AdminHub);
+
+ ret = ScGetHubStatus(ps->Rpc, &t);
+ if (ret == ERR_NO_ERROR)
+ {
+ // Success
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Selected"), t.HubName);
+
+ if (ps->HubName != NULL)
+ {
+ Free(ps->HubName);
+ }
+ ps->HubName = CopyStr(t.HubName);
+
+ if( ps->Console->ConsoleType != CONSOLE_CSV)
+ {
+ ps->Console->Write(ps->Console, tmp);
+ }
+ }
+ else
+ {
+ // Failure
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Select_Failed"), ps->AdminHub);
+
+ ps->Console->Write(ps->Console, tmp);
+ CmdPrintError(ps->Console, ret);
+ }
+ }
+
+ while (true)
+ {
+ // Definition of command
+ CMD cmd[] =
+ {
+ {"About", PsAbout},
+ {"Check", PtCheck},
+ {"Crash", PsCrash},
+ {"Flush", PsFlush},
+ {"Debug", PsDebug},
+ {"ServerInfoGet", PsServerInfoGet},
+ {"ServerStatusGet", PsServerStatusGet},
+ {"ListenerCreate", PsListenerCreate},
+ {"ListenerDelete", PsListenerDelete},
+ {"ListenerList", PsListenerList},
+ {"ListenerEnable", PsListenerEnable},
+ {"ListenerDisable", PsListenerDisable},
+ {"ServerPasswordSet", PsServerPasswordSet},
+ {"ClusterSettingGet", PsClusterSettingGet},
+ {"ClusterSettingStandalone", PsClusterSettingStandalone},
+ {"ClusterSettingController", PsClusterSettingController},
+ {"ClusterSettingMember", PsClusterSettingMember},
+ {"ClusterMemberList", PsClusterMemberList},
+ {"ClusterMemberInfoGet", PsClusterMemberInfoGet},
+ {"ClusterMemberCertGet", PsClusterMemberCertGet},
+ {"ClusterConnectionStatusGet", PsClusterConnectionStatusGet},
+ {"ServerCertGet", PsServerCertGet},
+ {"ServerKeyGet", PsServerKeyGet},
+ {"ServerCertSet", PsServerCertSet},
+ {"ServerCipherGet", PsServerCipherGet},
+ {"ServerCipherSet", PsServerCipherSet},
+ {"KeepEnable", PsKeepEnable},
+ {"KeepDisable", PsKeepDisable},
+ {"KeepSet", PsKeepSet},
+ {"KeepGet", PsKeepGet},
+ {"SyslogGet", PsSyslogGet},
+ {"SyslogDisable", PsSyslogDisable},
+ {"SyslogEnable", PsSyslogEnable},
+ {"ConnectionList", PsConnectionList},
+ {"ConnectionGet", PsConnectionGet},
+ {"ConnectionDisconnect", PsConnectionDisconnect},
+ {"BridgeDeviceList", PsBridgeDeviceList},
+ {"BridgeList", PsBridgeList},
+ {"BridgeCreate", PsBridgeCreate},
+ {"BridgeDelete", PsBridgeDelete},
+ {"Caps", PsCaps},
+ {"Reboot", PsReboot},
+ {"ConfigGet", PsConfigGet},
+ {"ConfigSet", PsConfigSet},
+ {"RouterList", PsRouterList},
+ {"RouterAdd", PsRouterAdd},
+ {"RouterDelete", PsRouterDelete},
+ {"RouterStart", PsRouterStart},
+ {"RouterStop", PsRouterStop},
+ {"RouterIfList", PsRouterIfList},
+ {"RouterIfAdd", PsRouterIfAdd},
+ {"RouterIfDel", PsRouterIfDel},
+ {"RouterTableList", PsRouterTableList},
+ {"RouterTableAdd", PsRouterTableAdd},
+ {"RouterTableDel", PsRouterTableDel},
+ {"LogFileList", PsLogFileList},
+ {"LogFileGet", PsLogFileGet},
+ {"HubCreate", PsHubCreate},
+ {"HubCreateDynamic", PsHubCreateDynamic},
+ {"HubCreateStatic", PsHubCreateStatic},
+ {"HubDelete", PsHubDelete},
+ {"HubSetStatic", PsHubSetStatic},
+ {"HubSetDynamic", PsHubSetDynamic},
+ {"HubList", PsHubList},
+ {"Hub", PsHub},
+ {"Online", PsOnline},
+ {"Offline", PsOffline},
+ {"SetMaxSession", PsSetMaxSession},
+ {"SetHubPassword", PsSetHubPassword},
+ {"SetEnumAllow", PsSetEnumAllow},
+ {"SetEnumDeny", PsSetEnumDeny},
+ {"OptionsGet", PsOptionsGet},
+ {"RadiusServerSet", PsRadiusServerSet},
+ {"RadiusServerDelete", PsRadiusServerDelete},
+ {"RadiusServerGet", PsRadiusServerGet},
+ {"StatusGet", PsStatusGet},
+ {"LogGet", PsLogGet},
+ {"LogEnable", PsLogEnable},
+ {"LogDisable", PsLogDisable},
+ {"LogSwitchSet", PsLogSwitchSet},
+ {"LogPacketSaveType", PsLogPacketSaveType},
+ {"CAList", PsCAList},
+ {"CAAdd", PsCAAdd},
+ {"CADelete", PsCADelete},
+ {"CAGet", PsCAGet},
+ {"CascadeList", PsCascadeList},
+ {"CascadeCreate", PsCascadeCreate},
+ {"CascadeSet", PsCascadeSet},
+ {"CascadeGet", PsCascadeGet},
+ {"CascadeDelete", PsCascadeDelete},
+ {"CascadeUsernameSet", PsCascadeUsernameSet},
+ {"CascadeAnonymousSet", PsCascadeAnonymousSet},
+ {"CascadePasswordSet", PsCascadePasswordSet},
+ {"CascadeCertSet", PsCascadeCertSet},
+ {"CascadeCertGet", PsCascadeCertGet},
+ {"CascadeEncryptEnable", PsCascadeEncryptEnable},
+ {"CascadeEncryptDisable", PsCascadeEncryptDisable},
+ {"CascadeCompressEnable", PsCascadeCompressEnable},
+ {"CascadeCompressDisable", PsCascadeCompressDisable},
+ {"CascadeProxyNone", PsCascadeProxyNone},
+ {"CascadeProxyHttp", PsCascadeProxyHttp},
+ {"CascadeProxySocks", PsCascadeProxySocks},
+ {"CascadeServerCertEnable", PsCascadeServerCertEnable},
+ {"CascadeServerCertDisable", PsCascadeServerCertDisable},
+ {"CascadeServerCertSet", PsCascadeServerCertSet},
+ {"CascadeServerCertDelete", PsCascadeServerCertDelete},
+ {"CascadeServerCertGet", PsCascadeServerCertGet},
+ {"CascadeDetailSet", PsCascadeDetailSet},
+ {"CascadePolicySet", PsCascadePolicySet},
+ {"PolicyList", PsPolicyList},
+ {"CascadeStatusGet", PsCascadeStatusGet},
+ {"CascadeRename", PsCascadeRename},
+ {"CascadeOnline", PsCascadeOnline},
+ {"CascadeOffline", PsCascadeOffline},
+ {"AccessAdd", PsAccessAdd},
+ {"AccessAddEx", PsAccessAddEx},
+ {"AccessAdd6", PsAccessAdd6},
+ {"AccessAddEx6", PsAccessAddEx6},
+ {"AccessList", PsAccessList},
+ {"AccessDelete", PsAccessDelete},
+ {"AccessEnable", PsAccessEnable},
+ {"AccessDisable", PsAccessDisable},
+ {"UserList", PsUserList},
+ {"UserCreate", PsUserCreate},
+ {"UserSet", PsUserSet},
+ {"UserDelete", PsUserDelete},
+ {"UserGet", PsUserGet},
+ {"UserAnonymousSet", PsUserAnonymousSet},
+ {"UserPasswordSet", PsUserPasswordSet},
+ {"UserCertSet", PsUserCertSet},
+ {"UserCertGet", PsUserCertGet},
+ {"UserSignedSet", PsUserSignedSet},
+ {"UserRadiusSet", PsUserRadiusSet},
+ {"UserNTLMSet", PsUserNTLMSet},
+ {"UserPolicyRemove", PsUserPolicyRemove},
+ {"UserPolicySet", PsUserPolicySet},
+ {"UserExpiresSet", PsUserExpiresSet},
+ {"GroupList", PsGroupList},
+ {"GroupCreate", PsGroupCreate},
+ {"GroupSet", PsGroupSet},
+ {"GroupDelete", PsGroupDelete},
+ {"GroupGet", PsGroupGet},
+ {"GroupJoin", PsGroupJoin},
+ {"GroupUnjoin", PsGroupUnjoin},
+ {"GroupPolicyRemove", PsGroupPolicyRemove},
+ {"GroupPolicySet", PsGroupPolicySet},
+ {"SessionList", PsSessionList},
+ {"SessionGet", PsSessionGet},
+ {"SessionDisconnect", PsSessionDisconnect},
+ {"MacTable", PsMacTable},
+ {"MacDelete", PsMacDelete},
+ {"IpTable", PsIpTable},
+ {"IpDelete", PsIpDelete},
+ {"SecureNatEnable", PsSecureNatEnable},
+ {"SecureNatDisable", PsSecureNatDisable},
+ {"SecureNatStatusGet", PsSecureNatStatusGet},
+ {"SecureNatHostGet", PsSecureNatHostGet},
+ {"SecureNatHostSet", PsSecureNatHostSet},
+ {"NatGet", PsNatGet},
+ {"NatEnable", PsNatEnable},
+ {"NatDisable", PsNatDisable},
+ {"NatSet", PsNatSet},
+ {"NatTable", PsNatTable},
+ {"DhcpGet", PsDhcpGet},
+ {"DhcpEnable", PsDhcpEnable},
+ {"DhcpDisable", PsDhcpDisable},
+ {"DhcpSet", PsDhcpSet},
+ {"DhcpTable", PsDhcpTable},
+ {"AdminOptionList", PsAdminOptionList},
+ {"AdminOptionSet", PsAdminOptionSet},
+ {"ExtOptionList", PsExtOptionList},
+ {"ExtOptionSet", PsExtOptionSet},
+ {"CrlList", PsCrlList},
+ {"CrlAdd", PsCrlAdd},
+ {"CrlDel", PsCrlDel},
+ {"CrlGet", PsCrlGet},
+ {"AcList", PsAcList},
+ {"AcAdd", PsAcAdd},
+ {"AcAdd6", PsAcAdd6},
+ {"AcDel", PsAcDel},
+ {"MakeCert", PtMakeCert},
+ {"TrafficClient", PtTrafficClient},
+ {"TrafficServer", PtTrafficServer},
+ {"LicenseAdd", PsLicenseAdd},
+ {"LicenseDel", PsLicenseDel},
+ {"LicenseList", PsLicenseList},
+ {"LicenseStatus", PsLicenseStatus},
+ {"IPsecEnable", PsIPsecEnable},
+ {"IPsecGet", PsIPsecGet},
+ {"EtherIpClientAdd", PsEtherIpClientAdd},
+ {"EtherIpClientDelete", PsEtherIpClientDelete},
+ {"EtherIpClientList", PsEtherIpClientList},
+ {"OpenVpnEnable", PsOpenVpnEnable},
+ {"OpenVpnGet", PsOpenVpnGet},
+ {"OpenVpnMakeConfig", PsOpenVpnMakeConfig},
+ {"SstpEnable", PsSstpEnable},
+ {"SstpGet", PsSstpGet},
+ {"ServerCertRegenerate", PsServerCertRegenerate},
+ {"VpnOverIcmpDnsEnable", PsVpnOverIcmpDnsEnable},
+ {"VpnOverIcmpDnsGet", PsVpnOverIcmpDnsGet},
+ {"DynamicDnsGetStatus", PsDynamicDnsGetStatus},
+ {"DynamicDnsSetHostname", PsDynamicDnsSetHostname},
+ {"VpnAzureGetStatus", PsVpnAzureGetStatus},
+ {"VpnAzureSetEnable", PsVpnAzureSetEnable},
+ };
+
+ // Generate a prompt
+ if (ps->HubName == NULL)
+ {
+ Format(prompt, sizeof(prompt), "VPN Server>");
+ }
+ else
+ {
+ Format(prompt, sizeof(prompt), "VPN Server/%s>", ps->HubName);
+ }
+
+ if (DispatchNextCmdEx(ps->Console, ps->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), ps) == false)
+ {
+ break;
+ }
+ ps->LastError = ps->Console->RetCode;
+
+ if (ps->LastError == ERR_NO_ERROR && ps->Console->ConsoleType != CONSOLE_CSV)
+ {
+ ps->Console->Write(ps->Console, _UU("CMD_MSG_OK"));
+ ps->Console->Write(ps->Console, L"");
+ }
+
+ if (ps->CmdLine != NULL)
+ {
+ break;
+ }
+ }
+
+ // Release the Caps
+ FreeCapsList(ps->CapsList);
+ ps->CapsList = NULL;
+}
+
+// A template for a new command function
+UINT PsXxx(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER t;
+ PARAM args[] =
+ {
+ {"[port]", CmdPromptPort, _UU("CMD_ListenerCreate_PortPrompt"), CmdEvalPort, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = ToInt(GetParamStr(o, "[port]"));
+
+ ret = ScCreateListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set to the stand-alone mode
+UINT PsClusterSettingStandalone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.ServerType = SERVER_TYPE_STANDALONE;
+
+ // RPC call
+ ret = ScSetFarmSetting(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set to the cluster controller mode
+UINT PsClusterSettingController(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM t;
+ UINT weight;
+ PARAM args[] =
+ {
+ {"WEIGHT", NULL, NULL, NULL, NULL},
+ {"ONLY", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ weight = GetParamInt(o, "WEIGHT");
+ if (weight == 0)
+ {
+ weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ Zero(&t, sizeof(t));
+ t.ServerType = SERVER_TYPE_FARM_CONTROLLER;
+ t.Weight = weight;
+ t.ControllerOnly = GetParamYes(o, "ONLY");
+
+ // RPC call
+ ret = ScSetFarmSetting(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Evaluate the IP address
+bool CmdEvalIp(CONSOLE *c, wchar_t *str, void *param)
+{
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (UniIsEmptyStr(str))
+ {
+ return true;
+ }
+
+ if (UniStrToIP32(str) == 0 && UniStrCmpi(str, L"0.0.0.0") != 0)
+ {
+ wchar_t *msg = (param == NULL) ? _UU("CMD_IP_EVAL_FAILED") : (wchar_t *)param;
+ c->Write(c, msg);
+ return false;
+ }
+
+ return true;
+}
+
+// Convert a string to port list
+LIST *StrToPortList(char *str)
+{
+ LIST *o;
+ TOKEN_LIST *t;
+ UINT i;
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert to token
+ t = ParseToken(str, ", ");
+ if (t == NULL)
+ {
+ return NULL;
+ }
+ if (t->NumTokens == 0)
+ {
+ FreeToken(t);
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+ UINT n;
+ if (IsNum(s) == false)
+ {
+ ReleaseList(o);
+ FreeToken(t);
+ return NULL;
+ }
+ n = ToInt(s);
+ if (n == 0 || n >= 65536)
+ {
+ ReleaseList(o);
+ FreeToken(t);
+ return NULL;
+ }
+ if (IsInList(o, (void *)n))
+ {
+ ReleaseList(o);
+ FreeToken(t);
+ return NULL;
+ }
+ Add(o, (void *)n);
+ }
+
+ FreeToken(t);
+
+ if (LIST_NUM(o) > MAX_PUBLIC_PORT_NUM)
+ {
+ ReleaseList(o);
+ return NULL;
+ }
+
+ return o;
+}
+
+// Set to the cluster member mode
+UINT PsClusterSettingMember(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM t;
+ char *host_and_port;
+ char *host;
+ UINT port;
+ UINT weight;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[server:port]", CmdPrompt, _UU("CMD_ClusterSettingMember_Prompt_HOST_1"), CmdEvalHostAndPort, NULL},
+ {"IP", PsClusterSettingMemberPromptIp, NULL, CmdEvalIp, NULL},
+ {"PORTS", PsClusterSettingMemberPromptPorts, NULL, CmdEvalPortList, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ {"WEIGHT", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ weight = GetParamInt(o, "WEIGHT");
+
+ if (weight == 0)
+ {
+ weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ Zero(&t, sizeof(t));
+ host_and_port = GetParamStr(o, "[server:port]");
+ if (ParseHostPort(host_and_port, &host, &port, 0))
+ {
+ char *pw;
+ char *ports_str;
+ LIST *ports;
+ UINT i;
+
+ StrCpy(t.ControllerName, sizeof(t.ControllerName), host);
+ t.ControllerPort = port;
+ Free(host);
+
+ pw = GetParamStr(o, "PASSWORD");
+
+ Hash(t.MemberPassword, pw, StrLen(pw), true);
+ t.PublicIp = StrToIP32(GetParamStr(o, "IP"));
+ t.ServerType = SERVER_TYPE_FARM_MEMBER;
+
+ ports_str = GetParamStr(o, "PORTS");
+
+ ports = StrToPortList(ports_str);
+
+ t.NumPort = LIST_NUM(ports);
+ t.Ports = ZeroMalloc(sizeof(UINT) * t.NumPort);
+
+ for (i = 0;i < t.NumPort;i++)
+ {
+ t.Ports[i] = (UINT)LIST_DATA(ports, i);
+ }
+
+ t.Weight = weight;
+
+ ReleaseList(ports);
+
+ // RPC call
+ ret = ScSetFarmSetting(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcFarm(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Evaluate the port list
+bool CmdEvalPortList(CONSOLE *c, wchar_t *str, void *param)
+{
+ char *s;
+ bool ret = false;
+ LIST *o;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ s = CopyUniToStr(str);
+
+ o = StrToPortList(s);
+
+ if (o != NULL)
+ {
+ ret = true;
+ }
+
+ ReleaseList(o);
+
+ Free(s);
+
+ if (ret == false)
+ {
+ c->Write(c, _UU("CMD_PORTLIST_EVAL_FAILED"));
+ }
+
+ return ret;
+}
+
+// Check the string of the form of the host name and port number
+bool CmdEvalHostAndPort(CONSOLE *c, wchar_t *str, void *param)
+{
+ char *tmp;
+ bool ret = false;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ tmp = CopyUniToStr(str);
+
+ ret = ParseHostPort(tmp, NULL, NULL, (UINT)param);
+
+ if (ret == false)
+ {
+ c->Write(c, param == NULL ? _UU("CMD_HOSTPORT_EVAL_FAILED") : (wchar_t *)param);
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Input the public port number
+wchar_t *PsClusterSettingMemberPromptPorts(CONSOLE *c, void *param)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ c->Write(c, _UU("CMD_ClusterSettingMember_Prompt_PORT_1"));
+ c->Write(c, L"");
+
+ ret = c->ReadLine(c, _UU("CMD_ClusterSettingMember_Prompt_PORT_2"), true);
+
+ return ret;
+}
+
+// Input the public IP address
+wchar_t *PsClusterSettingMemberPromptIp(CONSOLE *c, void *param)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ c->Write(c, _UU("CMD_ClusterSettingMember_Prompt_IP_1"));
+ c->Write(c, L"");
+
+ ret = c->ReadLine(c, _UU("CMD_ClusterSettingMember_Prompt_IP_2"), true);
+
+ return ret;
+}
+
+// Show the cluster members list
+UINT PsClusterMemberList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_FARM t;
+ CT *ct;
+ UINT i;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumFarmMember(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("CMD_ID"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_4"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_5"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_6"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_7"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_8"), true);
+ CtInsertColumn(ct, _UU("SM_FM_COLUMN_9"), true);
+
+ for (i = 0;i < t.NumFarm;i++)
+ {
+ RPC_ENUM_FARM_ITEM *e = &t.Farms[i];
+ wchar_t tmp0[64];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[64];
+ wchar_t tmp4[64];
+ wchar_t tmp5[64];
+ wchar_t tmp6[64];
+ wchar_t tmp7[64];
+ wchar_t tmp8[64];
+
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);
+ StrToUni(tmp2, sizeof(tmp2), e->Hostname);
+ UniToStru(tmp3, e->Point);
+ UniToStru(tmp4, e->NumSessions);
+ UniToStru(tmp5, e->NumTcpConnections);
+ UniToStru(tmp6, e->NumHubs);
+ UniToStru(tmp7, e->AssignedClientLicense);
+ UniToStru(tmp8, e->AssignedBridgeLicense);
+
+ UniToStru(tmp0, e->Id);
+
+ CtInsert(ct, tmp0,
+ e->Controller ? _UU("SM_FM_CONTROLLER") : _UU("SM_FM_MEMBER"),
+ tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8);
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcEnumFarm(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get information of cluster members
+UINT PsClusterMemberInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM_INFO t;
+ CT *ct;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_ClusterMemberInfoGet_PROMPT_ID"), NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Id = UniToInt(GetParamUniStr(o, "[id]"));
+
+ // RPC call
+ ret = ScGetFarmInfo(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNewStandard();
+
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ UINT i;
+
+ CtInsert(ct, _UU("SM_FMINFO_TYPE"),
+ t.Controller ? _UU("SM_FARM_CONTROLLER") : _UU("SM_FARM_MEMBER"));
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);
+ CtInsert(ct, _UU("SM_FMINFO_CONNECT_TIME"), tmp);
+
+ IPToStr32(str, sizeof(str), t.Ip);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_FMINFO_IP"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.Hostname);
+ CtInsert(ct, _UU("SM_FMINFO_HOSTNAME"), tmp);
+
+ UniToStru(tmp, t.Point);
+ CtInsert(ct, _UU("SM_FMINFO_POINT"), tmp);
+
+ UniToStru(tmp, t.Weight);
+ CtInsert(ct, _UU("SM_FMINFO_WEIGHT"), tmp);
+
+ UniToStru(tmp, t.NumPort);
+ CtInsert(ct, _UU("SM_FMINFO_NUM_PORT"), tmp);
+
+ for (i = 0;i < t.NumPort;i++)
+ {
+ wchar_t tmp2[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_PORT"), i + 1);
+ UniToStru(tmp2, t.Ports[i]);
+ CtInsert(ct, tmp, tmp2);
+ }
+
+ UniToStru(tmp, t.NumFarmHub);
+ CtInsert(ct, _UU("SM_FMINFO_NUM_HUB"), tmp);
+
+ for (i = 0;i < t.NumFarmHub;i++)
+ {
+ wchar_t tmp2[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_HUB"), i + 1);
+ UniFormat(tmp2, sizeof(tmp2),
+ t.FarmHubs[i].DynamicHub ? _UU("SM_FMINFO_HUB_TAG_2") : _UU("SM_FMINFO_HUB_TAG_1"),
+ t.FarmHubs[i].HubName);
+ CtInsert(ct, tmp, tmp2);
+ }
+
+ UniToStru(tmp, t.NumSessions);
+ CtInsert(ct, _UU("SM_FMINFO_NUM_SESSION"), tmp);
+
+ UniToStru(tmp, t.NumTcpConnections);
+ CtInsert(ct, _UU("SM_FMINFO_NUN_CONNECTION"), tmp);
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcFarmInfo(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get certificates of cluster members
+UINT PsClusterMemberCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM_INFO t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_ClusterMemberCertGet_PROMPT_ID"), NULL, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ t.Id = UniToInt(GetParamUniStr(o, "[id]"));
+
+ // RPC call
+ ret = ScGetFarmInfo(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ X *x = t.ServerCert;
+ wchar_t *filename = GetParamUniStr(o, "SAVECERT");
+
+ if (XToFileW(x, filename, true) == false)
+ {
+ c->Write(c, _UU("CMD_SAVECERT_FAILED"));
+
+ ret = ERR_INTERNAL_ERROR;
+ }
+ }
+
+ FreeRpcFarmInfo(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the status of the connection to the cluster controller
+UINT PsClusterConnectionStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_FARM_CONNECTION_STATUS t;
+ wchar_t tmp[MAX_SIZE];
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetFarmConnectionStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+ char str[MAX_SIZE];
+
+ if (t.Online == false)
+ {
+ CtInsert(ct, _UU("SM_FC_IP"), _UU("SM_FC_NOT_CONNECTED"));
+
+ CtInsert(ct, _UU("SM_FC_PORT"), _UU("SM_FC_NOT_CONNECTED"));
+ }
+ else
+ {
+ IPToStr32(str, sizeof(str), t.Ip);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_FC_IP"), tmp);
+
+ UniToStru(tmp, t.Port);
+ CtInsert(ct, _UU("SM_FC_PORT"), tmp);
+ }
+
+ CtInsert(ct,
+ _UU("SM_FC_STATUS"),
+ t.Online ? _UU("SM_FC_ONLINE") : _UU("SM_FC_OFFLINE"));
+
+ if (t.Online == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FC_ERROR_TAG"), _E(t.LastError), t.LastError);
+ CtInsert(ct,
+ _UU("SM_FC_LAST_ERROR"), tmp);
+ }
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartedTime), NULL);
+ CtInsert(ct, _UU("SM_FC_START_TIME"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.FirstConnectedTime), NULL);
+ CtInsert(ct, _UU("SM_FC_FIRST_TIME"), tmp);
+
+ //if (t.Online == false)
+ {
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CurrentConnectedTime), NULL);
+ CtInsert(ct, _UU("SM_FC_CURRENT_TIME"), tmp);
+ }
+
+ UniToStru(tmp, t.NumTry);
+ CtInsert(ct, _UU("SM_FC_NUM_TRY"), tmp);
+
+ UniToStru(tmp, t.NumConnected);
+ CtInsert(ct, _UU("SM_FC_NUM_CONNECTED"), tmp);
+
+ UniToStru(tmp, t.NumFailed);
+ CtInsert(ct, _UU("SM_FC_NUM_FAILED"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the SSL certificate of the VPN Server
+UINT PsServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEY_PAIR t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[cert]", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetServerCert(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (XToFileW(t.Cert, GetParamUniStr(o, "[cert]"), true) == false)
+ {
+ c->Write(c, _UU("CMD_SAVECERT_FAILED"));
+ }
+
+ FreeRpcKeyPair(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the private key of the SSL certificate of the VPN Server
+UINT PsServerKeyGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEY_PAIR t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[key]", CmdPrompt, _UU("CMD_SAVEKEYPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetServerCert(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (t.Key != NULL)
+ {
+ if (KToFileW(t.Key, GetParamUniStr(o, "[key]"), true, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_SAVEKEY_FAILED"));
+ }
+ }
+ else
+ {
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ CmdPrintError(c, ret);
+ }
+
+ FreeRpcKeyPair(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Read the certificate and the private key
+bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar_t *key_filename)
+{
+ X *x;
+ K *k;
+ // Validate arguments
+ if (c == NULL || cert_filename == NULL || key_filename == NULL || xx == NULL || kk == NULL)
+ {
+ return false;
+ }
+
+ x = FileToXW(cert_filename);
+ if (x == NULL)
+ {
+ c->Write(c, _UU("CMD_LOADCERT_FAILED"));
+ return false;
+ }
+
+ k = CmdLoadKey(c, key_filename);
+ if (k == NULL)
+ {
+ c->Write(c, _UU("CMD_LOADKEY_FAILED"));
+ FreeX(x);
+ return false;
+ }
+
+ if (CheckXandK(x, k) == false)
+ {
+ c->Write(c, _UU("CMD_KEYPAIR_FAILED"));
+ FreeX(x);
+ FreeK(k);
+
+ return false;
+ }
+
+ *xx = x;
+ *kk = k;
+
+ return true;
+}
+
+// Read the secret key
+K *CmdLoadKey(CONSOLE *c, wchar_t *filename)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ c->Write(c, _UU("CMD_LOADCERT_FAILED"));
+ return NULL;
+ }
+ else
+ {
+ K *key;
+ if (IsEncryptedK(b, true) == false)
+ {
+ key = BufToK(b, true, IsBase64(b), NULL);
+ }
+ else
+ {
+ c->Write(c, _UU("CMD_LOADKEY_ENCRYPTED_1"));
+
+ while (true)
+ {
+ char *pass = c->ReadPassword(c, _UU("CMD_LOADKEY_ENCRYPTED_2"));
+
+ if (pass == NULL)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+
+ key = BufToK(b, true, IsBase64(b), pass);
+ Free(pass);
+
+ if (key != NULL)
+ {
+ break;
+ }
+
+ c->Write(c, _UU("CMD_LOADKEY_ENCRYPTED_3"));
+ }
+ }
+
+ FreeBuf(b);
+
+ return key;
+ }
+}
+
+// Set the SSL certificate and the private key of the VPN Server
+UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEY_PAIR t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CmdLoadCertAndKey(c, &t.Cert, &t.Key,
+ GetParamUniStr(o, "LOADCERT"),
+ GetParamUniStr(o, "LOADKEY")))
+ {
+ // RPC call
+ ret = ScSetServerCert(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ else
+ {
+ ret = ERR_INTERNAL_ERROR;
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the encryption algorithm used for the VPN communication
+UINT PsServerCipherGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_STR t;
+ TOKEN_LIST *ciphers;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetServerCipher(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ciphers = GetCipherList();
+
+ c->Write(c, _UU("CMD_ServerCipherGet_SERVER"));
+
+ UniFormat(tmp, sizeof(tmp), L" %S", t.String);
+ c->Write(c, tmp);
+
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_ServerCipherGet_CIPHERS"));
+
+ for (i = 0;i < ciphers->NumTokens;i++)
+ {
+ UniFormat(tmp, sizeof(tmp), L" %S", ciphers->Token[i]);
+ c->Write(c, tmp);
+ }
+
+ FreeRpcStr(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the encryption algorithm used for the VPN communication
+UINT PsServerCipherSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_STR t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_ServerCipherSet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.String = CopyStr(GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScSetServerCipher(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcStr(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enabling the maintenance function of the Internet connection
+UINT PsKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEEP t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.UseKeepConnect = true;
+
+ ret = ScSetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disabling the maintenance function of the Internet connection
+UINT PsKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEEP t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.UseKeepConnect = false;
+
+ ret = ScSetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Evaluate the UDP or the TCP
+bool CmdEvalTcpOrUdp(CONSOLE *c, wchar_t *str, void *param)
+{
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (UniStrCmpi(str, L"tcp") == 0 || UniStrCmpi(str, L"udp") == 0)
+ {
+ return true;
+ }
+
+ c->Write(c, _UU("CMD_KeepSet_EVAL_TCP_UDP"));
+
+ return false;
+}
+
+// Enable the syslog configuration
+UINT PsSyslogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ SYSLOG_SETTING t;
+ CMD_EVAL_MIN_MAX minmax = {"CMD_SyslogEnable_MINMAX", 1, 3};
+ char *host;
+ UINT port;
+
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[1|2|3]", CmdPrompt, _UU("CMD_SyslogEnable_Prompt_123"), CmdEvalMinMax, &minmax},
+ {"HOST", CmdPrompt, _UU("CMD_SyslogEnable_Prompt_HOST"), CmdEvalHostAndPort, (void *)SYSLOG_PORT},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, SYSLOG_PORT))
+ {
+ StrCpy(t.Hostname, sizeof(t.Hostname), host);
+ t.Port = port;
+ t.SaveType = GetParamInt(o, "[1|2|3]");
+
+ Free(host);
+
+ // RPC call
+ ret = ScSetSysLog(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the syslog configuration
+UINT PsSyslogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ SYSLOG_SETTING t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetSysLog(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.SaveType = SYSLOG_NONE;
+
+ // RPC call
+ ret = ScSetSysLog(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the syslog configuration
+UINT PsSyslogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ SYSLOG_SETTING t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetSysLog(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_1"), GetSyslogSettingName(t.SaveType));
+
+ if (t.SaveType != SYSLOG_NONE)
+ {
+ StrToUni(tmp, sizeof(tmp), t.Hostname);
+ CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_2"), tmp);
+
+ UniToStru(tmp, t.Port);
+ CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_3"), tmp);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the syslog configuration name
+wchar_t *GetSyslogSettingName(UINT n)
+{
+ char tmp[MAX_PATH];
+
+ Format(tmp, sizeof(tmp), "SM_SYSLOG_%u", n);
+
+ return _UU(tmp);
+}
+
+// Setting of maintenance function of the Internet connection
+UINT PsKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEEP t;
+ char *host;
+ UINT port;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"HOST", CmdPrompt, _UU("CMD_KeepSet_PROMPT_HOST"), CmdEvalHostAndPort, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_PROTOCOL"), CmdEvalTcpOrUdp, NULL},
+ {"INTERVAL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_INTERVAL"), NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, 0))
+ {
+ StrCpy(t.KeepConnectHost, sizeof(t.KeepConnectHost), host);
+ t.KeepConnectPort = port;
+ t.KeepConnectInterval = GetParamInt(o, "INTERVAL");
+ t.KeepConnectProtocol = (StrCmpi(GetParamStr(o, "PROTOCOL"), "tcp") == 0) ? 0 : 1;
+ Free(host);
+
+ // RPC call
+ ret = ScSetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the maintenance function of the Internet connection
+UINT PsKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_KEEP t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetKeep(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ StrToUni(tmp, sizeof(tmp), t.KeepConnectHost);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_1"), tmp);
+
+ UniToStru(tmp, t.KeepConnectPort);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_2"), tmp);
+
+ UniToStru(tmp, t.KeepConnectInterval);
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_3"), tmp);
+
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_4"),
+ t.KeepConnectProtocol == 0 ? L"TCP/IP" : L"UDP/IP");
+
+ CtInsert(ct, _UU("CMD_KeepGet_COLUMN_5"),
+ t.UseKeepConnect ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the connection type string
+wchar_t *GetConnectionTypeStr(UINT type)
+{
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "SM_CONNECTION_TYPE_%u", type);
+
+ return _UU(tmp);
+}
+
+// Get the list of TCP connections connected to VPN Server
+UINT PsConnectionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_CONNECTION t;
+ UINT i;
+ CT *ct;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumConnection(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("SM_CONN_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_CONN_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_CONN_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_CONN_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumConnection;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t name[MAX_SIZE];
+ wchar_t datetime[MAX_SIZE];
+ RPC_ENUM_CONNECTION_ITEM *e = &t.Connections[i];
+
+ StrToUni(name, sizeof(name), e->Name);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_HOSTNAME_AND_PORT"), e->Hostname, e->Port);
+ GetDateTimeStrEx64(datetime, sizeof(datetime), SystemToLocal64(e->ConnectedTime), NULL);
+
+ CtInsert(ct, name, tmp, datetime,
+ GetConnectionTypeStr(e->Type));
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcEnumConnetion(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the TCP connection information currently connected to the VPN Server
+UINT PsConnectionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CONNECTION_INFO t;
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_ConnectionGet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetConnectionInfo(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ ct = CtNewStandard();
+
+ StrToUni(tmp, sizeof(tmp), t.Name);
+ CtInsert(ct, _UU("SM_CONNINFO_NAME"), tmp);
+
+ CtInsert(ct, _UU("SM_CONNINFO_TYPE"), GetConnectionTypeStr(t.Type));
+
+ StrToUni(tmp, sizeof(tmp), t.Hostname);
+ CtInsert(ct, _UU("SM_CONNINFO_HOSTNAME"), tmp);
+
+ UniToStru(tmp, t.Port);
+ CtInsert(ct, _UU("SM_CONNINFO_PORT"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);
+ CtInsert(ct, _UU("SM_CONNINFO_TIME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.ServerStr);
+ CtInsert(ct, _UU("SM_CONNINFO_SERVER_STR"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ServerVer / 100, t.ServerVer % 100);
+ CtInsert(ct, _UU("SM_CONNINFO_SERVER_VER"), tmp);
+
+ UniToStru(tmp, t.ServerBuild);
+ CtInsert(ct, _UU("SM_CONNINFO_SERVER_BUILD"), tmp);
+
+ if (StrLen(t.ClientStr) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.ClientStr);
+ CtInsert(ct, _UU("SM_CONNINFO_CLIENT_STR"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ClientVer / 100, t.ClientVer % 100);
+ CtInsert(ct, _UU("SM_CONNINFO_CLIENT_VER"), tmp);
+
+ UniToStru(tmp, t.ClientBuild);
+ CtInsert(ct, _UU("SM_CONNINFO_CLIENT_BUILD"), tmp);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disconnect the TCP connection connected to the VPN Server
+UINT PsConnectionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DISCONNECT_CONNECTION t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_ConnectionDisconnect_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDisconnectConnection(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the LAN card list that can be used for local bridge
+UINT PsBridgeDeviceList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_ETH t;
+ UINT i;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumEthernet(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *item = &t.Items[i];
+ wchar_t tmp[MAX_SIZE * 2];
+
+ StrToUni(tmp, sizeof(tmp), item->DeviceName);
+ c->Write(c, tmp);
+ }
+
+ FreeRpcEnumEth(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of local bridge connection
+UINT PsBridgeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_LOCALBRIDGE t;
+ UINT i;
+ CT *ct;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumLocalBridge(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t.Items[i];
+ wchar_t name[MAX_SIZE];
+ wchar_t nic[MAX_SIZE];
+ wchar_t hub[MAX_SIZE];
+ wchar_t *status = _UU("SM_BRIDGE_OFFLINE");
+
+ UniToStru(name, i + 1);
+ StrToUni(nic, sizeof(nic), e->DeviceName);
+ StrToUni(hub, sizeof(hub), e->HubName);
+
+ if (e->Online)
+ {
+ status = e->Active ? _UU("SM_BRIDGE_ONLINE") : _UU("SM_BRIDGE_ERROR");
+ }
+
+ CtInsert(ct, name, hub, nic, status);
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcEnumLocalBridge(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Create a local bridge connection
+UINT PsBridgeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LOCALBRIDGE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[hubname]", CmdPrompt, _UU("CMD_BridgeCreate_PROMPT_HUBNAME"), CmdEvalNotEmpty, NULL},
+ {"DEVICE", CmdPrompt, _UU("CMD_BridgeCreate_PROMPT_DEVICE"), CmdEvalNotEmpty, NULL},
+ {"TAP", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ t.Active = true;
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "DEVICE"));
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[hubname]"));
+ t.Online = true;
+ t.TapMode = GetParamYes(o, "TAP");
+
+ // RPC call
+ ret = ScAddLocalBridge(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ c->Write(c, _UU("SM_BRIDGE_INTEL"));
+ c->Write(c, L"");
+
+ if (GetCapsBool(ps->CapsList, "b_is_in_vm"))
+ {
+ // Message in the case of operating in a VM
+ c->Write(c, _UU("D_SM_VMBRIDGE@CAPTION"));
+ c->Write(c, _UU("D_SM_VMBRIDGE@S_1"));
+ c->Write(c, _UU("D_SM_VMBRIDGE@S_2"));
+ c->Write(c, L"");
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the local bridge connection
+UINT PsBridgeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LOCALBRIDGE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[hubname]", CmdPrompt, _UU("CMD_BridgeDelete_PROMPT_HUBNAME"), CmdEvalNotEmpty, NULL},
+ {"DEVICE", CmdPrompt, _UU("CMD_BridgeDelete_PROMPT_DEVICE"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "DEVICE"));
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[hubname]"));
+
+ // RPC call
+ ret = ScDeleteLocalBridge(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of features and capabilities of the server
+UINT PsCaps(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ CAPSLIST *t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // RPC call
+ t = ScGetCapsEx(ps->Rpc);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ CT *ct;
+
+ ct = CtNewStandard();
+
+ for (i = 0;i < LIST_NUM(t->CapsList);i++)
+ {
+ CAPS *c = LIST_DATA(t->CapsList, i);
+ wchar_t title[MAX_SIZE];
+ char name[256];
+
+ Format(name, sizeof(name), "CT_%s", c->Name);
+
+ UniStrCpy(title, sizeof(title), _UU(name));
+
+ if (UniIsEmptyStr(title))
+ {
+ UniFormat(title, sizeof(title), L"%S", (StrLen(c->Name) >= 2) ? c->Name + 2 : c->Name);
+ }
+
+ if (StartWith(c->Name, "b_"))
+ {
+ bool icon_pass = c->Value == 0 ? false : true;
+ if (StrCmpi(c->Name, "b_must_install_pcap") == 0)
+ {
+ // Reverse only item of WinPcap
+ icon_pass = !icon_pass;
+ }
+ CtInsert(ct, title, c->Value == 0 ? _UU("CAPS_NO") : _UU("CAPS_YES"));
+ }
+ else
+ {
+ wchar_t str[64];
+ UniToStru(str, c->Value);
+ CtInsert(ct, title, str);
+ }
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeCapsList(t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Restart the VPN Server service
+UINT PsReboot(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_TEST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"RESETCONFIG", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ t.IntValue = GetParamYes(o, "RESETCONFIG") ? 1 : 0;
+
+ // RPC call
+ ret = ScRebootServer(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcTest(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current configuration of the VPN Server
+UINT PsConfigGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CONFIG t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[path]", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t *filename = GetParamUniStr(o, "[path]");
+
+ if (IsEmptyUniStr(filename))
+ {
+ // Display on the screen
+ wchar_t tmp[MAX_SIZE];
+ UINT buf_size;
+ wchar_t *buf;
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_ConfigGet_FILENAME"), t.FileName,
+ StrLen(t.FileData));
+ c->Write(c, tmp);
+ c->Write(c, L"");
+
+ buf_size = CalcUtf8ToUni((BYTE *)t.FileData, StrLen(t.FileData));
+ buf = ZeroMalloc(buf_size + 32);
+
+ Utf8ToUni(buf, buf_size, (BYTE *)t.FileData, StrLen(t.FileData));
+
+ c->Write(c, buf);
+ c->Write(c, L"");
+
+ Free(buf);
+ }
+ else
+ {
+ // Save to the file
+ IO *io = FileCreateW(filename);
+
+ if (io == NULL)
+ {
+ c->Write(c, _UU("CMD_ConfigGet_FILE_SAVE_FAILED"));
+
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ FileWrite(io, t.FileData, StrLen(t.FileData));
+ FileClose(io);
+ }
+ }
+ }
+
+ FreeRpcConfig(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Write the configuration to the VPN Server
+UINT PsConfigSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CONFIG t;
+ wchar_t *filename;
+ BUF *buf;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[path]", CmdPrompt, _UU("CMD_ConfigSet_PROMPT_PATH"), CmdEvalIsFile, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ filename = GetParamUniStr(o, "[path]");
+
+ buf = ReadDumpW(filename);
+ if (buf == NULL)
+ {
+ c->Write(c, _UU("CMD_ConfigSet_FILE_LOAD_FAILED"));
+ }
+ else
+ {
+ Zero(&t, sizeof(t));
+
+ t.FileData = ZeroMalloc(buf->Size + 1);
+ Copy(t.FileData, buf->Buf, buf->Size);
+ FreeBuf(buf);
+
+ // RPC call
+ ret = ScSetConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcConfig(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the Virtual Layer 3 switch list
+UINT PsRouterList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_L3SW t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumL3Switch(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN1"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN2"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN3"), true);
+ CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN4"), true);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *e = &t.Items[i];
+ wchar_t tmp1[MAX_SIZE], *tmp2, tmp3[64], tmp4[64];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ if (e->Active == false)
+ {
+ tmp2 = _UU("SM_L3_SW_ST_F_F");
+ }
+ else if (e->Online == false)
+ {
+ tmp2 = _UU("SM_L3_SW_ST_T_F");
+ }
+ else
+ {
+ tmp2 = _UU("SM_L3_SW_ST_T_T");
+ }
+ UniToStru(tmp3, e->NumInterfaces);
+ UniToStru(tmp4, e->NumTables);
+
+ CtInsert(ct,
+ tmp1, tmp2, tmp3, tmp4);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcEnumL3Sw(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Define a new virtual layer 3 switch
+UINT PsRouterAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3SW t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScAddL3Switch(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the Virtual Layer 3 Switch
+UINT PsRouterDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3SW t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterDelete_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDelL3Switch(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Start the Virtual Layer 3 Switch
+UINT PsRouterStart(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3SW t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterStart_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScStartL3Switch(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Stop the Virtual Layer 3 Switch
+UINT PsRouterStop(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3SW t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterStop_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScStopL3Switch(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the interface list registered on Virtual Layer 3 Switch
+UINT PsRouterIfList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_L3IF t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterIfList_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScEnumL3If(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN1"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN2"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN3"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_L3IF *e = &t.Items[i];
+
+ IPToUniStr32(tmp1, sizeof(tmp1), e->IpAddress);
+ IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);
+ StrToUni(tmp3, sizeof(tmp3), e->HubName);
+
+ CtInsert(ct, tmp1, tmp2, tmp3);
+ }
+
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcEnumL3If(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Evaluate the IP address and mask
+bool CmdEvalIpAndMask4(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ UINT ip, mask;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParseIpAndMask4(tmp, &ip, &mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_MASK_ERROR_1"));
+ return false;
+ }
+
+ return true;
+}
+bool CmdEvalIpAndMask6(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ IP ip, mask;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParseIpAndMask6(tmp, &ip, &mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_MASK_ERROR_1_6"));
+ return false;
+ }
+
+ return true;
+}
+bool CmdEvalIpAndMask46(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ bool ret = false;
+
+ Zero(tmp, sizeof(tmp));
+ UniToStr(tmp, sizeof(tmp), str);
+
+ t = ParseToken(tmp, "/");
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (t->NumTokens >= 1)
+ {
+ Trim(t->Token[0]);
+
+ if (IsIpStr4(t->Token[0]))
+ {
+ ret = CmdEvalIpAndMask4(c, str, param);
+ }
+ else
+ {
+ ret = CmdEvalIpAndMask6(c, str, param);
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Evaluate the network address and the subnet mask
+bool CmdEvalNetworkAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ UINT ip, mask;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParseIpAndSubnetMask4(tmp, &ip, &mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1"));
+ return false;
+ }
+
+ if (IsNetworkAddress32(ip, mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_2"));
+ return false;
+ }
+
+ return true;
+}
+bool CmdEvalNetworkAndSubnetMask6(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ IP ip, mask;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParseIpAndSubnetMask6(tmp, &ip, &mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1_6"));
+ return false;
+ }
+
+ if (IsNetworkPrefixAddress6(&ip, &mask) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_3"));
+ return false;
+ }
+
+ return true;
+}
+bool CmdEvalNetworkAndSubnetMask46(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ bool ret = false;
+
+ Zero(tmp, sizeof(tmp));
+ UniToStr(tmp, sizeof(tmp), str);
+
+ t = ParseToken(tmp, "/");
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (t->NumTokens >= 1)
+ {
+ Trim(t->Token[0]);
+
+ if (IsIpStr4(t->Token[0]))
+ {
+ ret = CmdEvalNetworkAndSubnetMask4(c, str, param);
+ }
+ else
+ {
+ ret = CmdEvalNetworkAndSubnetMask6(c, str, param);
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Evaluate the IP address and subnet mask
+bool CmdEvalHostAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParseIpAndSubnetMask4(tmp, NULL, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1"));
+ return false;
+ }
+
+ return true;
+}
+
+// Add a virtual interface to the virtual layer 3 switch
+UINT PsRouterIfAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3IF t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_HUB"), CmdEvalNotEmpty, NULL},
+ {"IP", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_IP"), CmdEvalHostAndSubnetMask4, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ ParseIpAndSubnetMask4(GetParamStr(o, "IP"), &t.IpAddress, &t.SubnetMask);
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "HUB"));
+
+ // RPC call
+ ret = ScAddL3If(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the virtual interface of the virtual layer 3 switch
+UINT PsRouterIfDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3IF t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_HUB"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "HUB"));
+
+ // RPC call
+ ret = ScDelL3If(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the routing table of the Virtual Layer 3 Switch
+UINT PsRouterTableList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_L3TABLE t;
+ CT *ct;
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_RouterTableList_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScEnumL3Table(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN1"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN2"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN3"), false);
+ CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN4"), true);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_L3TABLE *e = &t.Items[i];
+
+ IPToUniStr32(tmp1, sizeof(tmp1), e->NetworkAddress);
+ IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);
+ IPToUniStr32(tmp3, sizeof(tmp3), e->GatewayAddress);
+ UniToStru(tmp4, e->Metric);
+
+ CtInsert(ct, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcEnumL3Table(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add a routing table entry to the Virtual Layer 3 Switch
+UINT PsRouterTableAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3TABLE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"NETWORK", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NETWORK"), CmdEvalNetworkAndSubnetMask4, NULL},
+ {"GATEWAY", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_GATEWAY"), CmdEvalIp, NULL},
+ {"METRIC", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_METRIC"), CmdEvalInt1, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ ParseIpAndSubnetMask4(GetParamStr(o, "NETWORK"), &t.NetworkAddress, &t.SubnetMask);
+ t.Metric = GetParamInt(o, "METRIC");
+ t.GatewayAddress = StrToIP32(GetParamStr(o, "GATEWAY"));
+
+ // RPC call
+ ret = ScAddL3Table(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the routing table entry of the Virtual Layer 3 Switch
+UINT PsRouterTableDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_L3TABLE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"NETWORK", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NETWORK"), CmdEvalNetworkAndSubnetMask4, NULL},
+ {"GATEWAY", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_GATEWAY"), CmdEvalIp, NULL},
+ {"METRIC", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_METRIC"), CmdEvalInt1, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ ParseIpAndSubnetMask4(GetParamStr(o, "NETWORK"), &t.NetworkAddress, &t.SubnetMask);
+ t.Metric = GetParamInt(o, "METRIC");
+ t.GatewayAddress = StrToIP32(GetParamStr(o, "GATEWAY"));
+
+ // RPC call
+ ret = ScDelL3Table(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the log files list
+UINT PsLogFileList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_LOG_FILE t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ c->Write(c, _UU("CMD_LogFileList_START"));
+ c->Write(c, L"");
+
+ // RPC call
+ ret = ScEnumLogFile(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ CT *ct;
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_LogFileList_NUM_LOGS"), t.NumItem);
+ c->Write(c, tmp);
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_2"), true);
+ CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t.Items[i];
+ wchar_t tmp1[MAX_PATH], tmp2[128], tmp3[128], tmp4[MAX_HOST_NAME_LEN + 1];
+ char tmp[MAX_SIZE];
+
+ StrToUni(tmp1, sizeof(tmp1), e->FilePath);
+
+ ToStrByte(tmp, sizeof(tmp), e->FileSize);
+ StrToUni(tmp2, sizeof(tmp2), tmp);
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->UpdatedTime));
+
+ StrToUni(tmp4, sizeof(tmp4), e->ServerName);
+
+ CtInsert(ct, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumLogFile(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Download a log file
+UINT PsLogFileGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ BUF *buf;
+ char *filename = NULL;
+ char *server_name;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_LogFileGet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"SERVER", NULL, NULL, NULL, NULL},
+ {"SAVEPATH", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ filename = GetParamStr(o, "SAVE");
+
+ c->Write(c, _UU("CMD_LogFileGet_START"));
+
+ server_name = GetParamStr(o, "SERVER");
+
+ buf = DownloadFileFromServer(ps->Rpc, server_name,
+ GetParamStr(o, "[name]"), 0, NULL, NULL);
+
+ if (buf == NULL)
+ {
+ c->Write(c, _UU("CMD_LogFileGet_FAILED"));
+
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ if (IsEmptyStr(filename) == false)
+ {
+ // Save to the file
+ if (DumpBuf(buf, filename) == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+ c->Write(c, _UU("CMD_LogFileGet_SAVE_FAILED"));
+ }
+ }
+ else
+ {
+ // Display on the screen
+ wchar_t tmp[MAX_SIZE];
+ UINT buf_size;
+ wchar_t *uni_buf;
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_LogFileGet_FILESIZE"),
+ buf->Size);
+ c->Write(c, tmp);
+ c->Write(c, L"");
+
+ buf_size = CalcUtf8ToUni((BYTE *)buf->Buf, buf->Size);
+ uni_buf = ZeroMalloc(buf_size + 32);
+
+ Utf8ToUni(uni_buf, buf_size, (BYTE *)buf->Buf, buf->Size);
+
+ c->Write(c, uni_buf);
+ c->Write(c, L"");
+
+ Free(uni_buf);
+ }
+
+ FreeBuf(buf);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Create a New Virtual HUB
+UINT PsHubCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ char *pass = "";
+ UINT hub_type = HUB_TYPE_STANDALONE;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ RPC_SERVER_INFO t;
+ Zero(&t, sizeof(t));
+ if (ScGetServerInfo(ps->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ hub_type = HUB_TYPE_FARM_DYNAMIC;
+ }
+ FreeRpcServerInfo(&t);
+ }
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+ t.HubType = hub_type;
+
+ if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)
+ {
+ pass = GetParamStr(o, "PASSWORD");
+ }
+
+ Hash(t.HashedPassword, pass, StrLen(pass), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);
+ t.Online = true;
+
+ // RPC call
+ ret = ScCreateHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Create a New Virtual HUB (dynamic mode)
+UINT PsHubCreateDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ char *pass = "";
+ UINT hub_type = HUB_TYPE_FARM_DYNAMIC;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+ t.HubType = hub_type;
+
+ if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)
+ {
+ pass = GetParamStr(o, "PASSWORD");
+ }
+
+ Hash(t.HashedPassword, pass, StrLen(pass), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);
+ t.Online = true;
+
+ // RPC call
+ ret = ScCreateHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Create a New Virtual HUB (static mode)
+UINT PsHubCreateStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ char *pass = "";
+ UINT hub_type = HUB_TYPE_FARM_STATIC;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+ t.HubType = hub_type;
+
+ if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)
+ {
+ pass = GetParamStr(o, "PASSWORD");
+ }
+
+ Hash(t.HashedPassword, pass, StrLen(pass), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);
+ t.Online = true;
+
+ // RPC call
+ ret = ScCreateHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete a Virtual HUB
+UINT PsHubDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_HUB t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_HubDelete_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDeleteHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the Virtual HUB to static
+UINT PsHubSetStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_HubChange_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+
+ // Retrieve the current setting first
+ ret = ScGetHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Change the settings
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+ t.HubType = HUB_TYPE_FARM_STATIC;
+
+ // Write
+ ret = ScSetHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Change the type of Virtual HUB to dynamic Virtual HUB
+UINT PsHubSetDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_HubChange_PROMPT_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+
+ // Retrieve the current setting first
+ ret = ScGetHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Change the settings
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+ t.HubType = HUB_TYPE_FARM_DYNAMIC;
+
+ // Write
+ ret = ScSetHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of Virtual HUB
+UINT PsHubList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_HUB t;
+ UINT i;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_5"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_6"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_7"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_8"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_9"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_10"), false);
+ CtInsertColumn(ct, _UU("SM_HUB_COLUMN_11"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_6"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_7"), false);
+
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+ wchar_t name[MAX_HUBNAME_LEN + 1];
+ wchar_t s1[64], s2[64], s3[64], s4[64], s5[64];
+ wchar_t s6[64], s7[128], s8[128];
+ wchar_t s9[64], s10[64];
+
+ UniToStru(s1, e->NumUsers);
+ UniToStru(s2, e->NumGroups);
+ UniToStru(s3, e->NumSessions);
+ UniToStru(s4, e->NumMacTables);
+ UniToStru(s5, e->NumIpTables);
+
+ UniToStru(s6, e->NumLogin);
+
+ if (e->LastLoginTime != 0)
+ {
+ GetDateTimeStr64Uni(s7, sizeof(s7), SystemToLocal64(e->LastLoginTime));
+ }
+ else
+ {
+ UniStrCpy(s7, sizeof(s7), _UU("COMMON_UNKNOWN"));
+ }
+
+ if (e->LastCommTime != 0)
+ {
+ GetDateTimeStr64Uni(s8, sizeof(s8), SystemToLocal64(e->LastCommTime));
+ }
+ else
+ {
+ UniStrCpy(s8, sizeof(s8), _UU("COMMON_UNKNOWN"));
+ }
+
+ if (e->IsTrafficFilled == false)
+ {
+ UniStrCpy(s9, sizeof(s9), _UU("CM_ST_NONE"));
+ UniStrCpy(s10, sizeof(s10), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ UniToStr3(s9, sizeof(s9),
+ e->Traffic.Recv.BroadcastBytes + e->Traffic.Recv.UnicastBytes +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastBytes);
+
+ UniToStr3(s10, sizeof(s10),
+ e->Traffic.Recv.BroadcastCount + e->Traffic.Recv.UnicastCount +
+ e->Traffic.Send.BroadcastCount + e->Traffic.Send.UnicastCount);
+ }
+
+ StrToUni(name, sizeof(name), e->HubName);
+
+ CtInsert(ct,
+ name,
+ e->Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"),
+ GetHubTypeStr(e->HubType),
+ s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumHub(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Select a Virtual HUB to manage
+UINT PsHub(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_STATUS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "[name]")) == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ Zero(&t, sizeof(t));
+
+ // Examine whether the specified Virtual HUB is accessible
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetHubStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Change the selection
+ if (ps->HubName != NULL)
+ {
+ Free(ps->HubName);
+ }
+ ps->HubName = CopyStr(t.HubName);
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Selected"), t.HubName);
+ c->Write(c, tmp);
+ }
+ else
+ {
+ // Deselect
+ if (ps->HubName != NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Unselected"));
+ Free(ps->HubName);
+ }
+ ps->HubName = NULL;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the Virtual HUB to online
+UINT PsOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_HUB_ONLINE t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Online = true;
+
+ // RPC call
+ ret = ScSetHubOnline(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the Virtual HUB to offline
+UINT PsOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_HUB_ONLINE t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Online = false;
+
+ // RPC call
+ ret = ScSetHubOnline(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the maximum number of concurrent connecting sessions of the Virtual HUB
+UINT PsSetMaxSession(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[max_session]", CmdPrompt, _UU("CMD_SetMaxSession_Prompt"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Get current settings of Virtual HUB
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScGetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.HubOption.MaxSession = GetParamInt(o, "[max_session]");
+
+ // Write the configuration of Virtual HUB
+ ret = ScSetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the administrative password of the Virtual HUB
+UINT PsSetHubPassword(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+ char *pw;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Get current settings of Virtual HUB
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScGetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Change the settings
+ pw = GetParamStr(o, "[password]");
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pw);
+ Hash(t.HashedPassword, pw, StrLen(pw), true);
+
+ // Write the configuration of Virtual HUB
+ ret = ScSetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the Virtual HUB to permit to be enumerated for anonymous users
+UINT PsSetEnumAllow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Get current settings of Virtual HUB
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScGetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.HubOption.NoEnum = false;
+
+ // Write the configuration of Virtual HUB
+ ret = ScSetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the Virtual HUB to deny to be enumerated for anonymous users
+UINT PsSetEnumDeny(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Get current settings of Virtual HUB
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScGetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.HubOption.NoEnum = true;
+
+ // Write the configuration of Virtual HUB
+ ret = ScSetHub(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the option settings for the virtual HUB
+UINT PsOptionsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_HUB t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHub(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_OptionsGet_TITLE"), ps->HubName);
+ c->Write(c, tmp);
+
+ // Display settings
+ ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_OptionsGet_ENUM"),
+ t.HubOption.NoEnum ? _UU("CMD_MSG_DENY") : _UU("CMD_MSG_ALLOW"));
+
+ if (t.HubOption.MaxSession == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, t.HubOption.MaxSession);
+ }
+ CtInsert(ct, _UU("CMD_OptionsGet_MAXSESSIONS"), tmp);
+
+ CtInsert(ct, _UU("CMD_OptionsGet_STATUS"), t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));
+
+ CtInsert(ct, _UU("CMD_OptionsGet_TYPE"), GetHubTypeStr(t.HubType));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Setting the Radius server to use for user authentication
+UINT PsRadiusServerSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_RADIUS t;
+ char *host;
+ UINT port;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_RadiusServerSet_EVAL_NUMINTERVAL", RADIUS_RETRY_INTERVAL, RADIUS_RETRY_TIMEOUT,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[server_name:port]", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_Host"), CmdEvalNotEmpty, NULL},
+ {"SECRET", CmdPromptChoosePassword, _UU("CMD_RadiusServerSet_Prompt_Secret"), NULL, NULL},
+ {"RETRY_INTERVAL", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_RetryInterval"), CmdEvalMinMax, &minmax},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (ParseHostPort(GetParamStr(o, "[server_name:port]"), &host, &port, 1812))
+ {
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.RadiusPort = port;
+ StrCpy(t.RadiusServerName, sizeof(t.RadiusServerName), host);
+ StrCpy(t.RadiusSecret, sizeof(t.RadiusSecret), GetParamStr(o, "SECRET"));
+ t.RadiusRetryInterval = GetParamInt(o, "RETRY_INTERVAL");
+
+ Free(host);
+
+ // RPC call
+ ret = ScSetHubRadius(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the Radius server configuration to be used for user authentication
+UINT PsRadiusServerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_RADIUS t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.RadiusPort = 1812;
+
+ // RPC call
+ ret = ScSetHubRadius(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the Radius server settings to use for user authentication
+UINT PsRadiusServerGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_RADIUS t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubRadius(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+
+ ct = CtNewStandard();
+
+ if (IsEmptyStr(t.RadiusServerName))
+ {
+ CtInsert(ct, _UU("CMD_RadiusServerGet_STATUS"), _UU("CMD_MSG_DISABLE"));
+ }
+ else
+ {
+ CtInsert(ct, _UU("CMD_RadiusServerGet_STATUS"), _UU("CMD_MSG_ENABLE"));
+
+ StrToUni(tmp, sizeof(tmp), t.RadiusServerName);
+ CtInsert(ct, _UU("CMD_RadiusServerGet_HOST"), tmp);
+
+ UniToStri(tmp, t.RadiusPort);
+ CtInsert(ct, _UU("CMD_RadiusServerGet_PORT"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.RadiusSecret);
+ CtInsert(ct, _UU("CMD_RadiusServerGet_SECRET"), tmp);
+
+ UniToStri(tmp, t.RadiusRetryInterval);
+ CtInsert(ct, _UU("CMD_RadiusServerGet_RetryInterval"), tmp);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current status of the Virtual HUB
+UINT PsStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_STATUS t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+ wchar_t *s;
+ wchar_t tmp[MAX_SIZE];
+
+ // HUB name
+ s = CopyStrToUni(t.HubName);
+ CtInsert(ct, _UU("SM_HUB_STATUS_HUBNAME"), s);
+ Free(s);
+
+ // Online
+ CtInsert(ct, _UU("SM_HUB_STATUS_ONLINE"),
+ t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));
+
+ // Type of HUB
+ CtInsert(ct, _UU("SM_HUB_TYPE"),
+ GetHubTypeStr(t.HubType));
+
+ if (t.HubType == HUB_TYPE_STANDALONE)
+ {
+ // Enable / Disable the SecureNAT
+ CtInsert(ct, _UU("SM_HUB_SECURE_NAT"),
+ t.SecureNATEnabled ? _UU("SM_HUB_SECURE_NAT_YES") : _UU("SM_HUB_SECURE_NAT_NO"));
+ }
+
+ // Other values
+ UniToStru(tmp, t.NumSessions);
+ CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS"), tmp);
+
+ if (t.NumSessionsClient != 0 || t.NumSessionsBridge != 0)
+ {
+ UniToStru(tmp, t.NumSessionsClient);
+ CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS_CLIENT"), tmp);
+ UniToStru(tmp, t.NumSessionsBridge);
+ CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS_BRIDGE"), tmp);
+ }
+
+ UniToStru(tmp, t.NumAccessLists);
+ CtInsert(ct, _UU("SM_HUB_NUM_ACCESSES"), tmp);
+
+ UniToStru(tmp, t.NumUsers);
+ CtInsert(ct, _UU("SM_HUB_NUM_USERS"), tmp);
+ UniToStru(tmp, t.NumGroups);
+ CtInsert(ct, _UU("SM_HUB_NUM_GROUPS"), tmp);
+
+ UniToStru(tmp, t.NumMacTables);
+ CtInsert(ct, _UU("SM_HUB_NUM_MAC_TABLES"), tmp);
+ UniToStru(tmp, t.NumIpTables);
+ CtInsert(ct, _UU("SM_HUB_NUM_IP_TABLES"), tmp);
+
+ // Usage status
+ UniToStru(tmp, t.NumLogin);
+ CtInsert(ct, _UU("SM_HUB_NUM_LOGIN"), tmp);
+
+ if (t.LastLoginTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastLoginTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ CtInsert(ct, _UU("SM_HUB_LAST_LOGIN_TIME"), tmp);
+
+ if (t.LastCommTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastCommTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ CtInsert(ct, _UU("SM_HUB_LAST_COMM_TIME"), tmp);
+
+ if (t.CreatedTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ CtInsert(ct, _UU("SM_HUB_CREATED_TIME"), tmp);
+
+ // Traffic information
+ CmdInsertTrafficInfo(ct, &t.Traffic);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the log switching string
+wchar_t *GetLogSwitchStr(UINT i)
+{
+ char tmp[64];
+
+ Format(tmp, sizeof(tmp), "SM_LOG_SWITCH_%u", i);
+
+ return _UU(tmp);
+}
+
+// Get the packet log name string
+wchar_t *GetPacketLogNameStr(UINT i)
+{
+ char tmp[64];
+
+ Format(tmp, sizeof(tmp), "CMD_Log_%u", i);
+
+ return _UU(tmp);
+}
+
+// Get the log storage settings for the virtual HUB
+UINT PsLogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_LOG t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubLog(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_Log_SecurityLog"),
+ t.LogSetting.SaveSecurityLog ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+ if (t.LogSetting.SaveSecurityLog)
+ {
+ CtInsert(ct, _UU("CMD_Log_SwitchType"), GetLogSwitchStr(t.LogSetting.SecurityLogSwitchType));
+ }
+
+ CtInsert(ct, L"", L"");
+
+ CtInsert(ct, _UU("CMD_Log_PacketLog"),
+ t.LogSetting.SavePacketLog ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+ if (t.LogSetting.SavePacketLog)
+ {
+ UINT i;
+
+ CtInsert(ct, _UU("CMD_Log_SwitchType"), GetLogSwitchStr(t.LogSetting.PacketLogSwitchType));
+
+ for (i = 0;i <= 7;i++)
+ {
+ wchar_t *tmp = NULL;
+
+ switch (t.LogSetting.PacketLogConfig[i])
+ {
+ case PACKET_LOG_NONE:
+ tmp = _UU("D_SM_LOG@B_PACKET_0_0");
+ break;
+
+ case PACKET_LOG_HEADER:
+ tmp = _UU("D_SM_LOG@B_PACKET_0_1");
+ break;
+
+ case PACKET_LOG_ALL:
+ tmp = _UU("D_SM_LOG@B_PACKET_0_2");
+ break;
+ }
+
+ CtInsert(ct, GetPacketLogNameStr(i),
+ tmp);
+ }
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// LogEnable command
+UINT PsLogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_LOG t;
+ bool packet_log = false;
+ char *tmp;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ tmp = GetParamStr(o, "[security|packet]");
+
+ if (StartWith(tmp, "p"))
+ {
+ packet_log = true;
+ }
+ else if (StartWith(tmp, "s") == false)
+ {
+ c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (packet_log == false)
+ {
+ t.LogSetting.SaveSecurityLog = true;
+ }
+ else
+ {
+ t.LogSetting.SavePacketLog = true;
+ }
+
+ // RPC call
+ ret = ScSetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the packet log or the security log
+UINT PsLogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_LOG t;
+ bool packet_log = false;
+ char *tmp;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ tmp = GetParamStr(o, "[security|packet]");
+
+ if (StartWith(tmp, "p"))
+ {
+ packet_log = true;
+ }
+ else if (StartWith(tmp, "s") == false)
+ {
+ c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));
+ FreeParamValueList(o);
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (packet_log == false)
+ {
+ t.LogSetting.SaveSecurityLog = false;
+ }
+ else
+ {
+ t.LogSetting.SavePacketLog = false;
+ }
+
+ // RPC call
+ ret = ScSetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Convert the string to log switching type
+UINT StrToLogSwitchType(char *str)
+{
+ UINT ret = INFINITE;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (IsEmptyStr(str) || StartWith("none", str))
+ {
+ ret = LOG_SWITCH_NO;
+ }
+ else if (StartWith("second", str))
+ {
+ ret = LOG_SWITCH_SECOND;
+ }
+ else if (StartWith("minute", str))
+ {
+ ret = LOG_SWITCH_MINUTE;
+ }
+ else if (StartWith("hour", str))
+ {
+ ret = LOG_SWITCH_HOUR;
+ }
+ else if (StartWith("day", str))
+ {
+ ret = LOG_SWITCH_DAY;
+ }
+ else if (StartWith("month", str))
+ {
+ ret = LOG_SWITCH_MONTH;
+ }
+
+ return ret;
+}
+
+// Set the switching period of the log file
+UINT PsLogSwitchSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_LOG t;
+ bool packet_log = false;
+ char *tmp;
+ UINT new_switch_type = 0;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},
+ {"SWITCH", CmdPrompt, _UU("CMD_LogSwitchSet_Prompt"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ tmp = GetParamStr(o, "[security|packet]");
+
+ if (StartWith(tmp, "p"))
+ {
+ packet_log = true;
+ }
+ else if (StartWith(tmp, "s") == false)
+ {
+ c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));
+ FreeParamValueList(o);
+ return ERR_INVALID_PARAMETER;
+ }
+
+ new_switch_type = StrToLogSwitchType(GetParamStr(o, "SWITCH"));
+
+ if (new_switch_type == INFINITE)
+ {
+ c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));
+ FreeParamValueList(o);
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (packet_log == false)
+ {
+ t.LogSetting.SecurityLogSwitchType = new_switch_type;
+ }
+ else
+ {
+ t.LogSetting.PacketLogSwitchType = new_switch_type;
+ }
+
+ // RPC call
+ ret = ScSetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Convert the type string of the packet log contents to an integer
+UINT StrToPacketLogSaveInfoType(char *str)
+{
+ UINT ret = INFINITE;
+ if (str == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (StartWith("none", str) || IsEmptyStr(str))
+ {
+ ret = PACKET_LOG_NONE;
+ }
+ else if (StartWith("header", str))
+ {
+ ret = PACKET_LOG_HEADER;
+ }
+ else if (StartWith("full", str) || StartWith("all", str))
+ {
+ ret = PACKET_LOG_ALL;
+ }
+
+ return ret;
+}
+
+// Convert a packet type string of the packet log to an integer
+UINT StrToPacketLogType(char *str)
+{
+ UINT ret = INFINITE;
+ if (str == NULL || IsEmptyStr(str))
+ {
+ return INFINITE;
+ }
+
+ if (StartWith("tcpconn", str))
+ {
+ ret = PACKET_LOG_TCP_CONN;
+ }
+ else if (StartWith("tcpdata", str))
+ {
+ ret = PACKET_LOG_TCP;
+ }
+ else if (StartWith("dhcp", str))
+ {
+ ret = PACKET_LOG_DHCP;
+ }
+ else if (StartWith("udp", str))
+ {
+ ret = PACKET_LOG_UDP;
+ }
+ else if (StartWith("icmp", str))
+ {
+ ret = PACKET_LOG_ICMP;
+ }
+ else if (StartWith("ip", str))
+ {
+ ret = PACKET_LOG_IP;
+ }
+ else if (StartWith("arp", str))
+ {
+ ret = PACKET_LOG_ARP;
+ }
+ else if (StartWith("ethernet", str))
+ {
+ ret = PACKET_LOG_ETHERNET;
+ }
+
+ return ret;
+}
+
+// Set the detail level and type of packet to be stored in the packet log
+UINT PsLogPacketSaveType(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_LOG t;
+ bool packet_log = false;
+ UINT packet_type = INFINITE;
+ UINT packet_save_info_type = INFINITE;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"TYPE", CmdPrompt, _UU("CMD_LogPacketSaveType_Prompt_TYPE"), NULL, NULL},
+ {"SAVE", CmdPrompt, _UU("CMD_LogPacketSaveType_Prompt_SAVE"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ packet_type = StrToPacketLogType(GetParamStr(o, "TYPE"));
+ packet_save_info_type = StrToPacketLogSaveInfoType(GetParamStr(o, "SAVE"));
+
+ if (packet_type == INFINITE || packet_save_info_type == INFINITE)
+ {
+ c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));
+ FreeParamValueList(o);
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.LogSetting.PacketLogConfig[packet_type] = packet_save_info_type;
+
+ // RPC call
+ ret = ScSetHubLog(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of certificates of the trusted certification authority
+UINT PsCAList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_ENUM_CA t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumCa(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ CT *ct = CtNewStandard();
+
+ for (i = 0;i < t.NumCa;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[64];
+ RPC_HUB_ENUM_CA_ITEM *e = &t.Ca[i];
+
+ GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);
+
+ UniToStru(tmp2, e->Key);
+
+ CtInsert(ct, _UU("CMD_CAList_COLUMN_ID"), tmp2);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_1"), e->SubjectName);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_2"), e->IssuerName);
+ CtInsert(ct, _UU("CM_CERT_COLUMN_3"), tmp);
+
+ if (i != (t.NumCa - 1))
+ {
+ CtInsert(ct, L"---", L"---");
+ }
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcHubEnumCa(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add a certificate to the trusted certification authority
+UINT PsCAAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_ADD_CA t;
+ X *x;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[path]", CmdPrompt, _UU("CMD_CAAdd_PROMPT_PATH"), CmdEvalIsFile, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ x = FileToXW(GetParamUniStr(o, "[path]"));
+
+ if (x == NULL)
+ {
+ FreeParamValueList(o);
+ c->Write(c, _UU("CMD_MSG_LOAD_CERT_FAILED"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Cert = x;
+
+ // RPC call
+ ret = ScAddCa(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcHubAddCa(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the certificate of the trusted certification authority
+UINT PsCADelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_DELETE_CA t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_CADelete_PROMPT_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDeleteCa(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the certificate of the trusted certification authority
+UINT PsCAGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB_GET_CA t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_CAGet_PROMPT_ID"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_CAGet_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScGetCa(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ if (XToFileW(t.Cert, GetParamUniStr(o, "SAVECERT"), true))
+ {
+ // Success
+ }
+ else
+ {
+ ret = ERR_INTERNAL_ERROR;
+ c->Write(c, _UU("CMD_MSG_SAVE_CERT_FAILED"));
+ }
+ }
+
+ FreeRpcHubGetCa(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the cascade connection list
+UINT PsCascadeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_LINK t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("SM_LINK_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_LINK_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_LINK_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_LINK_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_LINK_COLUMN_5"), false);
+
+ for (i = 0;i < t.NumLink;i++)
+ {
+ RPC_ENUM_LINK_ITEM *e = &t.Links[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);
+ StrToUni(tmp2, sizeof(tmp2), e->Hostname);
+ StrToUni(tmp3, sizeof(tmp3), e->HubName);
+
+ if (e->Online == false)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_OFFLINE"));
+ }
+ else
+ {
+ if (e->Connected)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ONLINE"));
+ }
+ else
+ {
+ if (e->LastError != 0)
+ {
+ UniFormat(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ERROR"), e->LastError, _E(e->LastError));
+ }
+ else
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_CONNECTING"));
+ }
+ }
+ }
+
+ CtInsert(ct, e->AccountName, tmp4, tmp1, tmp2, tmp3);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumLink(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Creat a new cascade
+UINT PsCascadeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ char *host = NULL;
+ UINT port = 443;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Hub"), CmdEvalSafe, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ t.Online = false;
+
+ Copy(&t.Policy, GetDefaultPolicy(), sizeof(POLICY));
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+ t.ClientOption->Port = port;
+ StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);
+ StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));
+ t.ClientOption->NumRetry = INFINITE;
+ t.ClientOption->RetryInterval = 15;
+ t.ClientOption->MaxConnection = 8;
+ t.ClientOption->UseEncrypt = true;
+ t.ClientOption->AdditionalConnectionInterval = 1;
+ t.ClientOption->RequireBridgeRoutingMode = true;
+
+ t.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;
+ StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));
+
+ Free(host);
+
+ // RPC call
+ ret = ScCreateLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the user name and destination of the cascade connection
+UINT PsCascadeSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ char *host = NULL;
+ UINT port = 443;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Hub"), CmdEvalSafe, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ ret = ScGetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ Free(host);
+ return ret;
+ }
+
+ t.ClientOption->Port = port;
+ StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);
+ StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));
+
+ Free(host);
+
+ // RPC call
+ ret = ScSetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the type string of proxy
+wchar_t *GetProxyTypeStr(UINT i)
+{
+ switch (i)
+ {
+ case PROXY_DIRECT:
+
+ return _UU("PROTO_DIRECT_TCP");
+
+ case PROXY_HTTP:
+ return _UU("PROTO_HTTP_PROXY");
+
+ case PROXY_SOCKS:
+ return _UU("PROTO_SOCKS_PROXY");
+
+ default:
+ return _UU("PROTO_UNKNOWN");
+ }
+}
+
+// Get type string in user authentication for client
+wchar_t *GetClientAuthTypeStr(UINT i)
+{
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "PW_TYPE_%u", i);
+
+ return _UU(tmp);
+}
+
+// Get the setting of cascade connection
+UINT PsCascadeGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
+ GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Show the contents of the connection settings
+ wchar_t tmp[MAX_SIZE];
+
+ CT *ct = CtNewStandard();
+
+ // Connection settings name
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NAME"), t.ClientOption->AccountName);
+
+ // Host name of the destination VPN Server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->Hostname);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HOSTNAME"), tmp);
+
+ // The port number to connect to VPN Server
+ UniToStru(tmp, t.ClientOption->Port);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PORT"), tmp);
+
+ // Virtual HUB name of the destination VPN Server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->HubName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HUBNAME"), tmp);
+
+ // Type of proxy server to go through
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_TYPE"), GetProxyTypeStr(t.ClientOption->ProxyType));
+
+ if (t.ClientOption->ProxyType != PROXY_DIRECT)
+ {
+ // Host name of the proxy server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME"), tmp);
+
+ // Port number of the proxy server
+ UniToStru(tmp, t.ClientOption->ProxyPort);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_PORT"), tmp);
+
+ // User name of the proxy server
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyUsername);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_USERNAME"), tmp);
+ }
+
+ // To verify the server certificate
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_USE"),
+ t.CheckServerCert ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Registered specific certificate
+ if (t.ServerCert != NULL)
+ {
+ GetAllNameFromX(tmp, sizeof(tmp), t.ServerCert);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME"), tmp);
+ }
+
+ // Device name to be used for the connection
+ StrToUni(tmp, sizeof(tmp), t.ClientOption->DeviceName);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_DEVICE_NAME"), tmp);
+
+ // Authentication type
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_TYPE"), GetClientAuthTypeStr(t.ClientAuth->AuthType));
+
+ // User name
+ StrToUni(tmp, sizeof(tmp), t.ClientAuth->Username);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_USERNAME"), tmp);
+
+ if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
+ {
+ if (t.ClientAuth->ClientX != NULL)
+ {
+ // Client certificate name
+ GetAllNameFromX(tmp, sizeof(tmp), t.ClientAuth->ClientX);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME"), tmp);
+ }
+ }
+
+ // Number of TCP connections to be used for VPN communication
+ UniToStru(tmp, t.ClientOption->MaxConnection);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NUMTCP"), tmp);
+
+ // Establishment interval of each TCP connection
+ UniToStru(tmp, t.ClientOption->AdditionalConnectionInterval);
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_INTERVAL"), tmp);
+
+ // Life span of each TCP connection
+ if (t.ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ UniToStru(tmp, t.ClientOption->ConnectionDisconnectSpan);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));
+ }
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_TTL"), tmp);
+
+ // Use of half-duplex mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_HALF"),
+ t.ClientOption->HalfConnection ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Encryption by SSL
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_ENCRYPT"),
+ t.ClientOption->UseEncrypt ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Data compression
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_COMPRESS"),
+ t.ClientOption->UseCompress ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Connect in bridge / router mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER"),
+ t.ClientOption->RequireBridgeRoutingMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Connect in monitoring mode
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_MONITOR"),
+ t.ClientOption->RequireMonitorMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Not to rewrite the routing table
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NO_TRACKING"),
+ t.ClientOption->NoRoutingTracking ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ // Disable the QoS control
+ CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_QOS_DISABLE"),
+ t.ClientOption->DisableQoS ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));
+
+ CtFree(ct, c);
+
+ // Security policy
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_CascadeGet_Policy"));
+ PrintPolicy(c, &t.Policy, true);
+ }
+
+ FreeRpcCreateLink(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the cascade connection
+UINT PsCascadeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScDeleteLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the user name to use for the cascade connection
+UINT PsCascadeUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Change the settings for the cascade connection
+ StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username),
+ GetParamStr(o, "USERNAME"));
+
+ if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ c->Write(c, _UU("CMD_CascadeUsername_Notice"));
+ }
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+//Set the type of user authentication of cascade connection to the anonymous authentication
+UINT PsCascadeAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Change the settings for the cascade connection
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the type of user authentication of cascade connection to the password authentication
+UINT PsCascadePasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ {"TYPE", CmdPrompt, _UU("CMD_CascadePasswordSet_Prompt_Type"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Change the settings for the cascade connection
+ char *typestr = GetParamStr(o, "TYPE");
+
+ if (StartWith("standard", typestr))
+ {
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
+ HashPassword(t.ClientAuth->HashedPassword, t.ClientAuth->Username,
+ GetParamStr(o, "PASSWORD"));
+ }
+ else if (StartWith("radius", typestr) || StartWith("ntdomain", typestr))
+ {
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PLAIN_PASSWORD;
+
+ StrCpy(t.ClientAuth->PlainPassword, sizeof(t.ClientAuth->PlainPassword),
+ GetParamStr(o, "PASSWORD"));
+ }
+ else
+ {
+ // An error has occured
+ c->Write(c, _UU("CMD_CascadePasswordSet_Type_Invalid"));
+ FreeRpcCreateLink(&t);
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the type of user authentication of cascade connection to the client certificate authentication
+UINT PsCascadeCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ X *x;
+ K *k;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (CmdLoadCertAndKey(c, &x, &k, GetParamUniStr(o, "LOADCERT"), GetParamUniStr(o, "LOADKEY")) == false)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ FreeX(x);
+ FreeK(k);
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Change authentication data
+ t.ClientAuth->AuthType = CLIENT_AUTHTYPE_CERT;
+ if (t.ClientAuth->ClientX != NULL)
+ {
+ FreeX(t.ClientAuth->ClientX);
+ }
+ if (t.ClientAuth->ClientK != NULL)
+ {
+ FreeK(t.ClientAuth->ClientK);
+ }
+
+ t.ClientAuth->ClientX = x;
+ t.ClientAuth->ClientK = k;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the client certificate to be used in the cascade connection
+UINT PsCascadeCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT)
+ {
+ c->Write(c, _UU("CMD_CascadeCertSet_Not_Auth_Cert"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else if (t.ClientAuth->ClientX == NULL)
+ {
+ c->Write(c, _UU("CMD_CascadeCertSet_Cert_Not_Exists"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ XToFileW(t.ClientAuth->ClientX, GetParamUniStr(o, "SAVECERT"), true);
+ }
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable encryption of communication at the time of the cascade connection
+UINT PsCascadeEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->UseEncrypt = true;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable encryption of communication at the time of the cascade connection
+UINT PsCascadeEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->UseEncrypt = false;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable data compression at the time of communication of the cascade connection
+UINT PsCascadeCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->UseCompress = true;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable data compression at the time of communication of the cascade connection
+UINT PsCascadeCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->UseCompress = false;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the cascade connection method to the TCP/IP direct connection mode
+UINT PsCascadeProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->ProxyType = PROXY_DIRECT;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the cascade connection method as the mode via HTTP proxy server
+UINT PsCascadeProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_CascadeProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"USERNAME", NULL, NULL, NULL, NULL},
+ {"PASSWORD", NULL, NULL, NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ char *host;
+ UINT port;
+
+ // Data change
+ if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))
+ {
+ t.ClientOption->ProxyType = PROXY_HTTP;
+ StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);
+ t.ClientOption->ProxyPort = port;
+ StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));
+ StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));
+ Free(host);
+ }
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the cascade connection method as the mode via SOCKS proxy server
+UINT PsCascadeProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SERVER", CmdPrompt, _UU("CMD_CascadeProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},
+ {"USERNAME", NULL, NULL, NULL, NULL},
+ {"PASSWORD", NULL, NULL, NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ char *host;
+ UINT port;
+
+ // Data change
+ if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))
+ {
+ t.ClientOption->ProxyType = PROXY_SOCKS;
+ StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);
+ t.ClientOption->ProxyPort = port;
+ StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));
+ StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));
+ Free(host);
+ }
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the validation options for the server certificate of cascade connection
+UINT PsCascadeServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.CheckServerCert = true;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the validation options for the server certificate of cascade connection
+UINT PsCascadeServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.CheckServerCert = false;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Server-specific certificate settings of cascade connection
+UINT PsCascadeServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ X *x;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ x = FileToXW(GetParamUniStr(o, "LOADCERT"));
+ if (x == NULL)
+ {
+ FreeParamValueList(o);
+ c->Write(c, _UU("CMD_LOADCERT_FAILED"));
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeX(x);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ if (t.ServerCert != NULL)
+ {
+ FreeX(t.ServerCert);
+ }
+ t.ServerCert = x;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the server-specific certificate of cascade connection
+UINT PsCascadeServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ if (t.ServerCert != NULL)
+ {
+ FreeX(t.ServerCert);
+ }
+ t.ServerCert = NULL;
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the server-specific certificate of cascade connection
+UINT PsCascadeServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Save the certificate
+ if (t.ServerCert == NULL)
+ {
+ c->Write(c, _UU("CMD_CERT_NOT_EXISTS"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ if (XToFileW(t.ServerCert, GetParamUniStr(o, "SAVECERT"), true) == false)
+ {
+ c->Write(c, _UU("CMD_SAVECERT_FAILED"));
+ ret = ERR_INTERNAL_ERROR;
+ }
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the advanced settings of the cascade connection
+UINT PsCascadeDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ CMD_EVAL_MIN_MAX mm_maxtcp =
+ {
+ "CMD_CascadeDetailSet_Eval_MaxTcp", 1, 32
+ };
+ CMD_EVAL_MIN_MAX mm_interval =
+ {
+ "CMD_CascadeDetailSet_Eval_Interval", 1, 4294967295UL
+ };
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"MAXTCP", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_MaxTcp"), CmdEvalMinMax, &mm_maxtcp},
+ {"INTERVAL", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_Interval"), CmdEvalMinMax, &mm_interval},
+ {"TTL", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_TTL"), NULL, NULL},
+ {"HALF", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_HALF"), NULL, NULL},
+ {"NOQOS", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOQOS"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Data change
+ t.ClientOption->MaxConnection = GetParamInt(o, "MAXTCP");
+ t.ClientOption->AdditionalConnectionInterval = GetParamInt(o, "INTERVAL");
+ t.ClientOption->ConnectionDisconnectSpan = GetParamInt(o, "TTL");
+ t.ClientOption->HalfConnection = GetParamYes(o, "HALF");
+ t.ClientOption->DisableQoS = GetParamYes(o, "NOQOS");
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Show a security policy
+void PrintPolicy(CONSOLE *c, POLICY *pol, bool cascade_mode)
+{
+ UINT i;
+ CT *ct;
+ PACK *p;
+ // Validate arguments
+ if (c == NULL || pol == NULL)
+ {
+ return;
+ }
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("CMD_PolicyList_Column_1"), false);
+ CtInsertColumn(ct, _UU("CMD_PolicyList_Column_2"), false);
+ CtInsertColumn(ct, _UU("CMD_PolicyList_Column_3"), false);
+
+ p = NewPack();
+ OutRpcPolicy(p, pol);
+
+ // Show the list of all policies
+ for (i = 0; i < PolicyNum();i++)
+ {
+ char name[64];
+ wchar_t *tmp;
+
+ if (cascade_mode == false || PolicyIsSupportedForCascade(i))
+ {
+ wchar_t value_str[256];
+ UINT value;
+ char tmp2[256];
+
+ Format(tmp2, sizeof(tmp2), "policy:%s", PolicyIdToStr(i));
+ value = PackGetInt(p, tmp2);
+
+ tmp = CopyStrToUni(PolicyIdToStr(i));
+
+ FormatPolicyValue(value_str, sizeof(value_str),
+ i, value);
+
+ Format(name, sizeof(name), "POL_%u", i);
+ CtInsert(ct, tmp, _UU(name), value_str);
+
+ Free(tmp);
+ }
+ }
+
+ FreePack(p);
+
+ CtFree(ct, c);
+}
+
+// Show the security policy list
+void PrintPolicyList(CONSOLE *c, char *name)
+{
+ UINT id;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+ if (IsEmptyStr(name))
+ {
+ name = NULL;
+ }
+
+ if (name != NULL)
+ {
+ id = PolicyStrToId(name);
+ if (id == INFINITE)
+ {
+ // Invalid ID
+ c->Write(c, _UU("CMD_PolicyList_Invalid_Name"));
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char name1[64], name2[64];
+ wchar_t *title, *descript;
+ wchar_t policy_name[MAX_SIZE];
+
+ Format(name1, sizeof(name1), "POL_%u", id);
+ Format(name2, sizeof(name2), "POL_EX_%u", id);
+
+ title = _UU(name1);
+ descript = _UU(name2);
+
+ StrToUni(policy_name, sizeof(policy_name), PolicyIdToStr(id));
+
+ // Policy name
+ c->Write(c, _UU("CMD_PolicyList_Help_1"));
+ UniFormat(tmp2, sizeof(tmp2), L" %s", policy_name);
+ c->Write(c, tmp2);
+ c->Write(c, L"");
+
+ // Simple description of the policy
+ c->Write(c, _UU("CMD_PolicyList_Help_2"));
+ UniFormat(tmp2, sizeof(tmp2), L" %s", title);
+ c->Write(c, tmp2);
+ c->Write(c, L"");
+
+ // Range of the value that can be set
+ GetPolicyValueRangeStr(tmp, sizeof(tmp), id);
+ c->Write(c, _UU("CMD_PolicyList_Help_3"));
+ UniFormat(tmp2, sizeof(tmp2), L" %s", tmp);
+ c->Write(c, tmp2);
+ c->Write(c, L"");
+
+ // Default value
+ FormatPolicyValue(tmp, sizeof(tmp), id, GetPolicyItem(id)->DefaultValue);
+ c->Write(c, _UU("CMD_PolicyList_Help_4"));
+ UniFormat(tmp2, sizeof(tmp2), L" %s", tmp);
+ c->Write(c, tmp2);
+ c->Write(c, L"");
+
+ // Detailed description of the policy
+ c->Write(c, _UU("CMD_PolicyList_Help_5"));
+ c->Write(c, descript);
+ c->Write(c, L"");
+ }
+ }
+ else
+ {
+ UINT i;
+ CT *ct = CtNew();
+ CtInsertColumn(ct, _UU("CMD_PolicyList_Column_1"), false);
+ CtInsertColumn(ct, _UU("CMD_PolicyList_Column_2"), false);
+
+ // Show the list of all policies
+ for (i = 0; i < PolicyNum();i++)
+ {
+ char name[64];
+ wchar_t *tmp;
+
+ tmp = CopyStrToUni(PolicyIdToStr(i));
+
+ Format(name, sizeof(name), "POL_%u", i);
+ CtInsert(ct, tmp, _UU(name));
+
+ Free(tmp);
+ }
+
+ CtFree(ct, c);
+ }
+}
+
+// Editing the contents of the policy
+bool EditPolicy(CONSOLE *c, POLICY *pol, char *name, char *value, bool cascade_mode)
+{
+ PACK *p;
+ ELEMENT *e;
+ POLICY_ITEM *item;
+ UINT id;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char pack_name[128];
+ // Validate arguments
+ if (c == NULL || pol == NULL || name == NULL || value == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+
+ OutRpcPolicy(p, pol);
+
+ Format(pack_name, sizeof(pack_name), "policy:%s", PolicyIdToStr(PolicyStrToId(name)));
+
+ if ((e = GetElement(p, pack_name, VALUE_INT)) == NULL || (id = PolicyStrToId(name)) == INFINITE)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_CascadePolicySet_Invalid_Name"), name);
+ c->Write(c, tmp);
+ FreePack(p);
+ return false;
+ }
+
+ if (cascade_mode && (PolicyIsSupportedForCascade(id) == false))
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_CascadePolicySet_Invalid_Name_For_Cadcade"), name);
+ c->Write(c, tmp);
+ FreePack(p);
+ return false;
+ }
+
+ item = GetPolicyItem(id);
+
+ if (item->TypeInt == false)
+ {
+ // bool type
+ e->values[0]->IntValue = (
+ StartWith(value, "y") || StartWith(value, "t") ||
+ ToInt(value) != 0) ? 1 : 0;
+ }
+ else
+ {
+ UINT n = ToInt(value);
+ bool b = true;
+
+ // int type
+ GetPolicyValueRangeStr(tmp, sizeof(tmp), id);
+
+ if (item->AllowZero == false)
+ {
+ if (n == 0)
+ {
+ b = false;
+ }
+ }
+
+ if (n != 0 && (n < item->MinValue || n > item->MaxValue))
+ {
+ b = false;
+ }
+
+ if (b == false)
+ {
+ UniFormat(tmp2, sizeof(tmp2), _UU("CMD_CascadePolicySet_Invalid_Range"), PolicyIdToStr(id), tmp);
+ c->Write(c, tmp2);
+ FreePack(p);
+ return false;
+ }
+
+ e->values[0]->IntValue = n;
+ }
+
+ Zero(pol, sizeof(POLICY));
+
+ InRpcPolicy(pol, p);
+
+ FreePack(p);
+
+ return true;
+}
+
+// Show the list of the type of security policy and possible values
+UINT PsPolicyList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", NULL, NULL, NULL, NULL}
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ PrintPolicyList(c, GetParamStr(o, "[name]"));
+
+ FreeParamValueList(o);
+
+ return ERR_NO_ERROR;
+}
+
+// Set the security policy of the cascade session
+UINT PsCascadePolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CREATE_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},
+ {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ if (EditPolicy(c, &t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), true) == false)
+ {
+ // An error has occured
+ FreeRpcCreateLink(&t);
+ FreeParamValueList(o);
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = ScSetLink(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCreateLink(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Display the status information of the session
+void CmdPrintStatusToListView(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s)
+{
+ CmdPrintStatusToListViewEx(ct, s, false);
+}
+void CmdPrintStatusToListViewEx(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode)
+{
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ char vv[128];
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (server_mode == false)
+ {
+ CtInsert(ct, _UU("CM_ST_ACCOUNT_NAME"), s->AccountName);
+
+ if (s->Connected == false)
+ {
+ wchar_t *st = _UU("CM_ST_CONNECTED_FALSE");
+ switch (s->SessionStatus)
+ {
+ case CLIENT_STATUS_CONNECTING:
+ st = _UU("CM_ST_CONNECTING");
+ break;
+ case CLIENT_STATUS_NEGOTIATION:
+ st = _UU("CM_ST_NEGOTIATION");
+ break;
+ case CLIENT_STATUS_AUTH:
+ st = _UU("CM_ST_AUTH");
+ break;
+ case CLIENT_STATUS_ESTABLISHED:
+ st = _UU("CM_ST_ESTABLISHED");
+ break;
+ case CLIENT_STATUS_RETRY:
+ st = _UU("CM_ST_RETRY");
+ break;
+ case CLIENT_STATUS_IDLE:
+ st = _UU("CM_ST_IDLE");
+ break;
+ }
+ CtInsert(ct, _UU("CM_ST_CONNECTED"), st);
+ }
+ else
+ {
+ CtInsert(ct, _UU("CM_ST_CONNECTED"), _UU("CM_ST_CONNECTED_TRUE"));
+ }
+ }
+
+ if (s->Connected)
+ {
+ if (s->VLanId == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_NO_VLAN"));
+ }
+ else
+ {
+ UniToStru(tmp, s->VLanId);
+ }
+
+ CtInsert(ct, _UU("CM_ST_VLAN_ID"), tmp);
+
+ if (server_mode == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->ServerName);
+ CtInsert(ct, _UU("CM_ST_SERVER_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), s->ServerPort);
+ CtInsert(ct, _UU("CM_ST_SERVER_PORT"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), s->ServerProductName);
+ CtInsert(ct, _UU("CM_ST_SERVER_P_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", s->ServerProductVer / 100, s->ServerProductVer % 100);
+ CtInsert(ct, _UU("CM_ST_SERVER_P_VER"), tmp);
+ UniFormat(tmp, sizeof(tmp), L"Build %u", s->ServerProductBuild);
+ CtInsert(ct, _UU("CM_ST_SERVER_P_BUILD"), tmp);
+ }
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->StartTime), NULL);
+ CtInsert(ct, _UU("CM_ST_START_TIME"), tmp);
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->FirstConnectionEstablisiedTime), NULL);
+ CtInsert(ct, _UU("CM_ST_FIRST_ESTAB_TIME"), s->FirstConnectionEstablisiedTime == 0 ? _UU("CM_ST_NONE") : tmp);
+
+ if (s->Connected)
+ {
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->CurrentConnectionEstablishTime), NULL);
+ CtInsert(ct, _UU("CM_ST_CURR_ESTAB_TIME"), tmp);
+ }
+
+ if (server_mode == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_STR"), s->NumConnectionsEatablished);
+ CtInsert(ct, _UU("CM_ST_NUM_ESTABLISHED"), tmp);
+ }
+
+ if (s->Connected)
+ {
+ CtInsert(ct, _UU("CM_ST_HALF_CONNECTION"), s->HalfConnection ? _UU("CM_ST_HALF_TRUE") : _UU("CM_ST_HALF_FALSE"));
+
+ CtInsert(ct, _UU("CM_ST_QOS"), s->QoS ? _UU("CM_ST_QOS_TRUE") : _UU("CM_ST_QOS_FALSE"));
+
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnections);
+ CtInsert(ct, _UU("CM_ST_NUM_TCP"), tmp);
+
+ if (s->HalfConnection)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsUpload);
+ CtInsert(ct, _UU("CM_ST_NUM_TCP_UPLOAD"), tmp);
+ UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsDownload);
+ CtInsert(ct, _UU("CM_ST_NUM_TCP_DOWNLOAD"), tmp);
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%u", s->MaxTcpConnections);
+ CtInsert(ct, _UU("CM_ST_MAX_TCP"), tmp);
+
+ if (s->UseEncrypt == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_FALSE"));
+ }
+ else
+ {
+ if (StrLen(s->CipherName) != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE"), s->CipherName);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE2"));
+ }
+ }
+ CtInsert(ct, _UU("CM_ST_USE_ENCRYPT"), tmp);
+
+ if (s->UseCompress)
+ {
+ UINT percent = 0;
+ if ((s->TotalRecvSize + s->TotalSendSize) > 0)
+ {
+ percent = (UINT)((UINT64)100 - (UINT64)(s->TotalRecvSizeReal + s->TotalSendSizeReal) * (UINT64)100 /
+ (s->TotalRecvSize + s->TotalSendSize));
+ percent = MAKESURE(percent, 0, 100);
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_TRUE"), percent);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_FALSE"));
+ }
+ CtInsert(ct, _UU("CM_ST_USE_COMPRESS"), tmp);
+
+ if (IsEmptyStr(s->UnderlayProtocol) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->UnderlayProtocol);
+ CtInsert(ct, _UU("CM_ST_UNDERLAY_PROTOCOL"), tmp);
+ }
+
+ CtInsert(ct, _UU("CM_ST_UDP_ACCEL_ENABLED"), (s->IsUdpAccelerationEnabled ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
+ CtInsert(ct, _UU("CM_ST_UDP_ACCEL_USING"), (s->IsUsingUdpAcceleration ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
+
+ StrToUni(tmp, sizeof(tmp), s->SessionName);
+ CtInsert(ct, _UU("CM_ST_SESSION_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), s->ConnectionName);
+ if (UniStrCmpi(tmp, L"INITING") != 0)
+ {
+ CtInsert(ct, _UU("CM_ST_CONNECTION_NAME"), tmp);
+ }
+
+ BinToStr(str, sizeof(str), s->SessionKey, sizeof(s->SessionKey));
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("CM_ST_SESSION_KEY"), tmp);
+
+ CtInsert(ct, _UU("CM_ST_BRIDGE_MODE"), s->IsBridgeMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
+
+ CtInsert(ct, _UU("CM_ST_MONITOR_MODE"), s->IsMonitorMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
+
+ ToStr3(vv, sizeof(vv), s->TotalSendSize);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_SEND_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->TotalRecvSize);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_RECV_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_SEND_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_SEND_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_SEND_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_SEND_BCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_RECV_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_RECV_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_RECV_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("CM_ST_RECV_BCAST_SIZE"), tmp);
+ }
+}
+
+// Get the current state of the cascade connection
+UINT PsCascadeStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LINK_STATUS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetLinkStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Get the cascade connection state
+ CT *ct = CtNewStandard();
+
+ CmdPrintStatusToListView(ct, &t.Status);
+
+ CtFree(ct, c);
+
+ FreeRpcLinkStatus(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Rename the cascade connection
+UINT PsCascadeRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_RENAME_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeRename_PROMPT_OLD"), CmdEvalNotEmpty, NULL},
+ {"NEW", CmdPrompt, _UU("CMD_CascadeRename_PROMPT_NEW"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ UniStrCpy(t.NewAccountName, sizeof(t.NewAccountName), GetParamUniStr(o, "NEW"));
+ UniStrCpy(t.OldAccountName, sizeof(t.OldAccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScRenameLink(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the cascade connection to on-line state
+UINT PsCascadeOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScSetLinkOnline(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the cascade connection to the off-line state
+UINT PsCascadeOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LINK t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
+
+ // RPC call
+ ret = ScSetLinkOffline(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Convert the string to pass / discard flag
+bool StrToPassOrDiscard(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (ToInt(str) != 0)
+ {
+ return true;
+ }
+
+ if (StartWith(str, "p") || StartWith(str, "y") || StartWith(str, "t"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Convert the string to the protocol
+UINT StrToProtocol(char *str)
+{
+ if (IsEmptyStr(str))
+ {
+ return 0;
+ }
+
+ if (StartWith("ip", str))
+ {
+ return 0;
+ }
+ else if (StartWith("tcp", str))
+ {
+ return IP_PROTO_TCP;
+ }
+ else if (StartWith("udp", str))
+ {
+ return IP_PROTO_UDP;
+ }
+ else if (StartWith("icmpv4", str))
+ {
+ return IP_PROTO_ICMPV4;
+ }
+ else if (StartWith("icmpv6", str))
+ {
+ return IP_PROTO_ICMPV6;
+ }
+
+ if (ToInt(str) == 0)
+ {
+ if (StrCmpi(str, "0") == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+
+ if (ToInt(str) >= 256)
+ {
+ return INFINITE;
+ }
+
+ return ToInt(str);
+}
+
+// Check the protocol name
+bool CmdEvalProtocol(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[64];
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (StrToProtocol(tmp) == INFINITE)
+ {
+ c->Write(c, _UU("CMD_PROTOCOL_EVAL_FAILED"));
+ return false;
+ }
+
+ return true;
+}
+
+// Parse the port range
+bool ParsePortRange(char *str, UINT *start, UINT *end)
+{
+ UINT a = 0, b = 0;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(str) == false)
+ {
+
+ t = ParseToken(str, "\t -");
+
+ if (t->NumTokens == 1)
+ {
+ a = b = ToInt(t->Token[0]);
+ }
+ else if (t->NumTokens == 2)
+ {
+ a = ToInt(t->Token[0]);
+ b = ToInt(t->Token[1]);
+ }
+
+ FreeToken(t);
+
+ if (a > b)
+ {
+ return false;
+ }
+
+ if (a >= 65536 || b >= 65536)
+ {
+ return false;
+ }
+
+ if (a == 0 && b != 0)
+ {
+ return false;
+ }
+ }
+
+ if (start != NULL)
+ {
+ *start = a;
+ }
+ if (end != NULL)
+ {
+ *end = b;
+ }
+
+ return true;
+}
+
+// Check the port range
+bool CmdEvalPortRange(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[64];
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if (ParsePortRange(tmp, NULL, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_PORT_RANGE_EVAL_FAILED"));
+ return false;
+ }
+
+ return true;
+}
+
+// Parse the MAC address and the mask
+bool ParseMacAddressAndMask(char *src, bool *check_mac, UCHAR *mac_bin, UCHAR *mask_bin)
+{
+ TOKEN_LIST *t;
+ char *macstr, *maskstr;
+ UCHAR mac[6], mask[6];
+ bool ok = false;
+
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+
+ //Zero(mac, sizeof(mac));
+ //Zero(mask, sizeof(mask));
+
+ if(check_mac != NULL && mac_bin != NULL && mask_bin != NULL)
+ {
+ ok = true;
+ }
+ if(IsEmptyStr(src) != false)
+ {
+ if(ok != false)
+ {
+ *check_mac = false;
+ Zero(mac_bin, 6);
+ Zero(mask_bin, 6);
+ }
+ return true;
+ }
+
+ t = ParseToken(src, "/");
+ if(t->NumTokens != 2)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ macstr = t->Token[0];
+ maskstr = t->Token[1];
+
+ Trim(macstr);
+ Trim(maskstr);
+
+ if(StrToMac(mac, macstr) == false || StrToMac(mask, maskstr) == false)
+ {
+ FreeToken(t);
+ return false;
+ }
+ else
+ {
+ if(ok != false)
+ {
+ Copy(mac_bin, mac, 6);
+ Copy(mask_bin, mask, 6);
+ *check_mac = true;
+ }
+ }
+ FreeToken(t);
+
+ return true;
+}
+
+// Check the MAC address and mask
+bool CmdEvalMacAddressAndMask(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[64];
+ // Validate arguments
+ if(c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+
+ if(ParseMacAddressAndMask(tmp, NULL, NULL, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_MAC_ADDRESS_AND_MASK_EVAL_FAILED"));
+ return false;
+ }
+
+ return true;
+}
+// Parse the status of TCP connection
+bool ParseTcpState(char *src, bool *check_tcp_state, bool *established)
+{
+ bool ok = false;
+ // Validate arguments
+ if(src == NULL)
+ {
+ return false;
+ }
+
+ if(check_tcp_state != NULL && established != NULL)
+ {
+ ok = true;
+ }
+
+ if (IsEmptyStr(src) == false)
+ {
+ if (StartWith("Established", src) == 0)
+ {
+ if(ok != false)
+ {
+ *check_tcp_state = true;
+ *established = true;
+ }
+ }
+ else if (StartWith("Unestablished", src) == 0)
+ {
+ if(ok != false)
+ {
+ *check_tcp_state = true;
+ *established = false;
+ }
+ }
+ else
+ {
+ // Illegal string
+ return false;
+ }
+ }
+ else
+ {
+ if(ok != false)
+ {
+ *check_tcp_state = false;
+ *established = false;
+ }
+ }
+
+ return true;
+}
+// Check the status of the TCP connection
+bool CmdEvalTcpState(CONSOLE *c, wchar_t *str, void *param)
+{
+ char tmp[64];
+ // Validate arguments
+ if(c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ if(ParseTcpState(tmp, NULL, NULL) == false)
+ {
+ c->Write(c, _UU("CMD_TCP_CONNECTION_STATE_EVAL_FAILED"));
+ return false;
+ }
+
+ return true;
+}
+
+// Adding a rule to the access list (Standard, IPv4)
+UINT PsAccessAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADD_ACCESS t;
+ ACCESS *a;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_AccessAdd_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TYPE"), CmdEvalNotEmpty, NULL},
+ {"MEMO", CmdPrompt, _UU("CMD_AccessAdd_Prompt_MEMO"), NULL, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},
+ {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCUSERNAME"), NULL, NULL},
+ {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTUSERNAME"), NULL, NULL},
+ {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCIP"), CmdEvalIpAndMask4, NULL},
+ {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTIP"), CmdEvalIpAndMask4, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},
+ {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCPORT"), CmdEvalPortRange, NULL},
+ {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTPORT"), CmdEvalPortRange, NULL},
+ {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ a = &t.Access;
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));
+ a->Active = true;
+ a->Priority = GetParamInt(o, "PRIORITY");
+ a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;
+ StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));
+ StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));
+ ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);
+ ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);
+ ParseIpAndMask4(GetParamStr(o, "SRCIP"), &a->SrcIpAddress, &a->SrcSubnetMask);
+ ParseIpAndMask4(GetParamStr(o, "DESTIP"), &a->DestIpAddress, &a->DestSubnetMask);
+ a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));
+ ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);
+ ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);
+ ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);
+
+ // RPC call
+ ret = ScAddAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Adding a rule to the access list (Extended, IPv4)
+UINT PsAccessAddEx(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADD_ACCESS t;
+ ACCESS *a;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_AccessAdd_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ CMD_EVAL_MIN_MAX minmax_delay =
+ {
+ "CMD_AccessAddEx_Eval_DELAY", 0, HUB_ACCESSLIST_DELAY_MAX,
+ };
+ CMD_EVAL_MIN_MAX minmax_jitter =
+ {
+ "CMD_AccessAddEx_Eval_JITTER", 0, HUB_ACCESSLIST_JITTER_MAX,
+ };
+ CMD_EVAL_MIN_MAX minmax_loss =
+ {
+ "CMD_AccessAddEx_Eval_LOSS", 0, HUB_ACCESSLIST_LOSS_MAX,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TYPE"), CmdEvalNotEmpty, NULL},
+ {"MEMO", CmdPrompt, _UU("CMD_AccessAdd_Prompt_MEMO"), NULL, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},
+ {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCUSERNAME"), NULL, NULL},
+ {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTUSERNAME"), NULL, NULL},
+ {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCIP"), CmdEvalIpAndMask4, NULL},
+ {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTIP"), CmdEvalIpAndMask4, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},
+ {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCPORT"), CmdEvalPortRange, NULL},
+ {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTPORT"), CmdEvalPortRange, NULL},
+ {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},
+ {"DELAY", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_DELAY"), CmdEvalMinMax, &minmax_delay},
+ {"JITTER", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_JITTER"), CmdEvalMinMax, &minmax_jitter},
+ {"LOSS", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_LOSS"), CmdEvalMinMax, &minmax_loss},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Check whether it is supported
+ if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)
+ {
+ c->Write(c, _E(ERR_NOT_SUPPORTED));
+ return ERR_NOT_SUPPORTED;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ a = &t.Access;
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));
+ a->Active = true;
+ a->Priority = GetParamInt(o, "PRIORITY");
+ a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;
+ StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));
+ StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));
+ ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);
+ ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);
+ ParseIpAndMask4(GetParamStr(o, "SRCIP"), &a->SrcIpAddress, &a->SrcSubnetMask);
+ ParseIpAndMask4(GetParamStr(o, "DESTIP"), &a->DestIpAddress, &a->DestSubnetMask);
+ a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));
+ ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);
+ ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);
+ ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);
+ a->Delay = GetParamInt(o, "DELAY");
+ a->Jitter = GetParamInt(o, "JITTER");
+ a->Loss = GetParamInt(o, "LOSS");
+
+ // RPC call
+ ret = ScAddAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Adding a rule to the access list (Standard, IPv6)
+UINT PsAccessAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADD_ACCESS t;
+ ACCESS *a;
+ IP ip, mask;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_AccessAdd6_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TYPE"), CmdEvalNotEmpty, NULL},
+ {"MEMO", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_MEMO"), NULL, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},
+ {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCUSERNAME"), NULL, NULL},
+ {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTUSERNAME"), NULL, NULL},
+ {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCIP"), CmdEvalIpAndMask6, NULL},
+ {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTIP"), CmdEvalIpAndMask6, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},
+ {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCPORT"), CmdEvalPortRange, NULL},
+ {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTPORT"), CmdEvalPortRange, NULL},
+ {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Check whether it is supported
+ if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)
+ {
+ c->Write(c, _E(ERR_NOT_SUPPORTED));
+ return ERR_NOT_SUPPORTED;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ a = &t.Access;
+
+ a->IsIPv6 = true;
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));
+ a->Active = true;
+ a->Priority = GetParamInt(o, "PRIORITY");
+ a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;
+ StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));
+ StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));
+ ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);
+ ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);
+
+ Zero(&ip, sizeof(ip));
+ Zero(&mask, sizeof(mask));
+
+ ParseIpAndMask6(GetParamStr(o, "SRCIP"), &ip, &mask);
+ IPToIPv6Addr(&a->SrcIpAddress6, &ip);
+ IPToIPv6Addr(&a->SrcSubnetMask6, &mask);
+
+ ParseIpAndMask6(GetParamStr(o, "DESTIP"), &ip, &mask);
+ IPToIPv6Addr(&a->DestIpAddress6, &ip);
+ IPToIPv6Addr(&a->DestSubnetMask6, &mask);
+
+ a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));
+ ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);
+ ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);
+ ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);
+
+ // RPC call
+ ret = ScAddAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Adding a rule to the access list (Extended, IPv6)
+UINT PsAccessAddEx6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADD_ACCESS t;
+ ACCESS *a;
+ IP ip, mask;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX minmax =
+ {
+ "CMD_AccessAdd6_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ CMD_EVAL_MIN_MAX minmax_delay =
+ {
+ "CMD_AccessAddEx6_Eval_DELAY", 0, HUB_ACCESSLIST_DELAY_MAX,
+ };
+ CMD_EVAL_MIN_MAX minmax_jitter =
+ {
+ "CMD_AccessAddEx6_Eval_JITTER", 0, HUB_ACCESSLIST_JITTER_MAX,
+ };
+ CMD_EVAL_MIN_MAX minmax_loss =
+ {
+ "CMD_AccessAddEx6_Eval_LOSS", 0, HUB_ACCESSLIST_LOSS_MAX,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TYPE"), CmdEvalNotEmpty, NULL},
+ {"MEMO", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_MEMO"), NULL, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},
+ {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCUSERNAME"), NULL, NULL},
+ {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTUSERNAME"), NULL, NULL},
+ {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},
+ {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCIP"), CmdEvalIpAndMask6, NULL},
+ {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTIP"), CmdEvalIpAndMask6, NULL},
+ {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},
+ {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCPORT"), CmdEvalPortRange, NULL},
+ {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTPORT"), CmdEvalPortRange, NULL},
+ {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},
+ {"DELAY", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_DELAY"), CmdEvalMinMax, &minmax_delay},
+ {"JITTER", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_JITTER"), CmdEvalMinMax, &minmax_jitter},
+ {"LOSS", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_LOSS"), CmdEvalMinMax, &minmax_loss},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Check whether it is supported
+ if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)
+ {
+ c->Write(c, _E(ERR_NOT_SUPPORTED));
+ return ERR_NOT_SUPPORTED;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ a = &t.Access;
+
+ a->IsIPv6 = true;
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));
+ a->Active = true;
+ a->Priority = GetParamInt(o, "PRIORITY");
+ a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;
+ StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));
+ StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));
+ ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);
+ ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);
+
+ Zero(&ip, sizeof(ip));
+ Zero(&mask, sizeof(mask));
+
+ ParseIpAndMask6(GetParamStr(o, "SRCIP"), &ip, &mask);
+ IPToIPv6Addr(&a->SrcIpAddress6, &ip);
+ IPToIPv6Addr(&a->SrcSubnetMask6, &mask);
+
+ ParseIpAndMask6(GetParamStr(o, "DESTIP"), &ip, &mask);
+ IPToIPv6Addr(&a->DestIpAddress6, &ip);
+ IPToIPv6Addr(&a->DestSubnetMask6, &mask);
+
+ a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));
+ ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);
+ ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);
+ ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);
+ a->Delay = GetParamInt(o, "DELAY");
+ a->Jitter = GetParamInt(o, "JITTER");
+ a->Loss = GetParamInt(o, "LOSS");
+
+ // RPC call
+ ret = ScAddAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+
+// Get the list of rules in the access list
+UINT PsAccessList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_ACCESS_LIST t;
+ CT *ct;
+ UINT i;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_0"), true);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_1"), true);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_2"), true);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_3"), true);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_6"), true);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_5"), false);
+ CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_4"), false);
+
+ for (i = 0;i < t.NumAccess;i++)
+ {
+ ACCESS *a = &t.Accesses[i];
+ char tmp[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+
+ GetAccessListStr(tmp, sizeof(tmp), a);
+ UniToStru(tmp1, a->Priority);
+ StrToUni(tmp2, sizeof(tmp2), tmp);
+ UniToStru(tmp4, a->UniqueId);
+ if (a->UniqueId == 0)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SEC_NONE"));
+ }
+
+ UniToStru(tmp3, a->Id);
+
+ CtInsert(ct,
+ tmp3,
+ a->Discard ? _UU("SM_ACCESS_DISCARD") : _UU("SM_ACCESS_PASS"),
+ a->Active ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"),
+ tmp1,
+ tmp4,
+ tmp2,
+ a->Note);
+ }
+
+ CtFreeEx(ct, c, true);
+
+ FreeRpcEnumAccessList(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Remove a rule from the access list
+UINT PsAccessDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_ACCESS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Id = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDeleteAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the rule of access list
+UINT PsAccessEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_ACCESS_LIST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ bool b = false;
+ for (i = 0;i < t.NumAccess;i++)
+ {
+ ACCESS *a = &t.Accesses[i];
+
+ if (a->Id == GetParamInt(o, "[id]"))
+ {
+ b = true;
+
+ a->Active = true;
+ }
+ }
+
+ if (b == false)
+ {
+ // The specified ID is not found
+ ret = ERR_OBJECT_NOT_FOUND;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeRpcEnumAccessList(&t);
+ return ret;
+ }
+
+ ret = ScSetAccessList(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcEnumAccessList(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Disable the rule of access list
+UINT PsAccessDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_ACCESS_LIST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumAccess(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ bool b = false;
+ for (i = 0;i < t.NumAccess;i++)
+ {
+ ACCESS *a = &t.Accesses[i];
+
+ if (a->Id == GetParamInt(o, "[id]"))
+ {
+ b = true;
+
+ a->Active = false;
+ }
+ }
+
+ if (b == false)
+ {
+ // The specified ID is not found
+ ret = ERR_OBJECT_NOT_FOUND;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeRpcEnumAccessList(&t);
+ return ret;
+ }
+
+ ret = ScSetAccessList(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcEnumAccessList(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Get the user list
+UINT PsUserList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_USER t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_5"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_6"), false);
+ CtInsertColumn(ct, _UU("SM_USER_COLUMN_7"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_5"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_6"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_7"), false);
+
+ for (i = 0;i < t.NumUser;i++)
+ {
+ RPC_ENUM_USER_ITEM *e = &t.Users[i];
+ wchar_t name[MAX_SIZE];
+ wchar_t group[MAX_SIZE];
+ wchar_t num[MAX_SIZE];
+ wchar_t time[MAX_SIZE];
+ wchar_t exp[MAX_SIZE];
+ wchar_t num1[64], num2[64];
+
+ StrToUni(name, sizeof(name), e->Name);
+
+ if (StrLen(e->GroupName) != 0)
+ {
+ StrToUni(group, sizeof(group), e->GroupName);
+ }
+ else
+ {
+ UniStrCpy(group, sizeof(group), _UU("SM_NO_GROUP"));
+ }
+
+ UniToStru(num, e->NumLogin);
+
+ GetDateTimeStrEx64(time, sizeof(time), SystemToLocal64(e->LastLoginTime), NULL);
+
+ if (e->IsExpiresFilled == false)
+ {
+ UniStrCpy(exp, sizeof(exp), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ if (e->Expires == 0)
+ {
+ UniStrCpy(exp, sizeof(exp), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateTimeStrEx64(exp, sizeof(exp), SystemToLocal64(e->Expires), NULL);
+ }
+ }
+
+ if (e->IsTrafficFilled == false)
+ {
+ UniStrCpy(num1, sizeof(num1), _UU("CM_ST_NONE"));
+ UniStrCpy(num2, sizeof(num2), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ UniToStr3(num1, sizeof(num1),
+ e->Traffic.Recv.BroadcastBytes + e->Traffic.Recv.UnicastBytes +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastBytes);
+
+ UniToStr3(num2, sizeof(num2),
+ e->Traffic.Recv.BroadcastCount + e->Traffic.Recv.UnicastCount +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastCount);
+ }
+
+ CtInsert(ct,
+ name, e->Realname, group, e->Note, GetAuthTypeStr(e->AuthType),
+ num, time, exp, num1, num2);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get a string of user authentication method
+wchar_t *GetAuthTypeStr(UINT id)
+{
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "SM_AUTHTYPE_%u", id);
+
+ return _UU(tmp);
+}
+
+// Creating a user
+UINT PsUserCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"GROUP", CmdPrompt, _UU("CMD_UserCreate_Prompt_GROUP"), NULL, NULL},
+ {"REALNAME", CmdPrompt, _UU("CMD_UserCreate_Prompt_REALNAME"), NULL, NULL},
+ {"NOTE", CmdPrompt, _UU("CMD_UserCreate_Prompt_NOTE"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "GROUP"));
+ UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));
+ UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));
+
+ Trim(t.Name);
+ if (StrCmpi(t.Name, "*") == 0)
+ {
+ t.AuthType = AUTHTYPE_RADIUS;
+ t.AuthData = NewRadiusAuthData(NULL);
+ }
+ else
+ {
+ UCHAR random_pass[SHA1_SIZE];
+ UCHAR random_pass2[MD5_SIZE];
+
+ Rand(random_pass, sizeof(random_pass));
+ Rand(random_pass2, sizeof(random_pass2));
+ t.AuthType = AUTHTYPE_PASSWORD;
+ t.AuthData = NewPasswordAuthDataRaw(random_pass, random_pass2);
+ }
+
+ // RPC call
+ ret = ScCreateUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Change the user information
+UINT PsUserSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"GROUP", CmdPrompt, _UU("CMD_UserCreate_Prompt_GROUP"), NULL, NULL},
+ {"REALNAME", CmdPrompt, _UU("CMD_UserCreate_Prompt_REALNAME"), NULL, NULL},
+ {"NOTE", CmdPrompt, _UU("CMD_UserCreate_Prompt_NOTE"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "GROUP"));
+ UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));
+ UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the user
+UINT PsUserDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDeleteUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the user information
+UINT PsUserGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct;
+
+ // Display the user's data
+ ct = CtNewStandard();
+
+ // User name
+ StrToUni(tmp, sizeof(tmp), t.Name);
+ CtInsert(ct, _UU("CMD_UserGet_Column_Name"), tmp);
+
+ // Real name
+ CtInsert(ct, _UU("CMD_UserGet_Column_RealName"), t.Realname);
+
+ // Description
+ CtInsert(ct, _UU("CMD_UserGet_Column_Note"), t.Note);
+
+ // Group name
+ if (IsEmptyStr(t.GroupName) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.GroupName);
+ CtInsert(ct, _UU("CMD_UserGet_Column_Group"), tmp);
+ }
+
+ // Expiration date
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ExpireTime), NULL);
+ CtInsert(ct, _UU("CMD_UserGet_Column_Expires"), tmp);
+
+ // Authentication method
+ CtInsert(ct, _UU("CMD_UserGet_Column_AuthType"), GetAuthTypeStr(t.AuthType));
+
+ switch (t.AuthType)
+ {
+ case AUTHTYPE_USERCERT:
+ if (t.AuthData != NULL)
+ {
+ AUTHUSERCERT *auc = (AUTHUSERCERT *)t.AuthData;
+
+ if (auc != NULL && auc->UserX != NULL)
+ {
+ // Registered user-specific certificate
+ GetAllNameFromX(tmp, sizeof(tmp), auc->UserX);
+ CtInsert(ct, _UU("CMD_UserGet_Column_UserCert"), tmp);
+ }
+ }
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ if (t.AuthData != NULL)
+ {
+ AUTHROOTCERT *arc = (AUTHROOTCERT *)t.AuthData;
+
+ if (IsEmptyUniStr(arc->CommonName) == false)
+ {
+ // Limitation the value of the certificate's CN
+ CtInsert(ct, _UU("CMD_UserGet_Column_RootCert_CN"), arc->CommonName);
+ }
+
+ if (arc->Serial != NULL && arc->Serial->size >= 1)
+ {
+ char tmp2[MAX_SIZE];
+
+ // Limitation the serial number of the certificate
+ BinToStrEx(tmp2, sizeof(tmp2), arc->Serial->data, arc->Serial->size);
+ StrToUni(tmp, sizeof(tmp), tmp2);
+ CtInsert(ct, _UU("CMD_UserGet_Column_RootCert_SERIAL"), tmp);
+ }
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ case AUTHTYPE_NT:
+ if (t.AuthData != NULL)
+ {
+ AUTHRADIUS *ar = (AUTHRADIUS *)t.AuthData;
+
+ // Authentication user name of the external authentication server
+ if (IsEmptyUniStr(ar->RadiusUsername) == false)
+ {
+ CtInsert(ct, _UU("CMD_UserGet_Column_RadiusAlias"), ar->RadiusUsername);
+ }
+ }
+ break;
+ }
+
+ CtInsert(ct, L"---", L"---");
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime), NULL);
+ CtInsert(ct, _UU("SM_USERINFO_CREATE"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.UpdatedTime), NULL);
+ CtInsert(ct, _UU("SM_USERINFO_UPDATE"), tmp);
+
+ CmdInsertTrafficInfo(ct, &t.Traffic);
+
+ UniToStru(tmp, t.NumLogin);
+ CtInsert(ct, _UU("SM_USERINFO_NUMLOGIN"), tmp);
+
+
+ CtFree(ct, c);
+
+ if (t.Policy != NULL)
+ {
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_UserGet_Policy"));
+ PrintPolicy(c, t.Policy, false);
+ }
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the authentication method for the user to the anonymous authentication
+UINT PsUserAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ // Set to anonymous authentication
+ t.AuthType = AUTHTYPE_ANONYMOUS;
+ t.AuthData = NULL;
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the authentication method for the user to the password authentication and set a password
+UINT PsUserPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ {
+ AUTHPASSWORD *pw;
+
+ pw = NewPasswordAuthData(t.Name, GetParamStr(o, "PASSWORD"));
+
+ // Set to the password authentication
+ t.AuthType = AUTHTYPE_PASSWORD;
+ t.AuthData = pw;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the authentication method for the user to the specific certificate authentication and set a certificate
+UINT PsUserCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ X *x;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Read the certificate
+ x = FileToXW(GetParamUniStr(o, "LOADCERT"));
+ if (x == NULL)
+ {
+ c->Write(c, _UU("CMD_LOADCERT_FAILED"));
+
+ FreeParamValueList(o);
+
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeX(x);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ {
+ AUTHUSERCERT *c;
+
+ c = NewUserCertAuthData(x);
+
+ FreeX(x);
+
+ // Set to the password authentication
+ t.AuthType = AUTHTYPE_USERCERT;
+ t.AuthData = c;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get certificates that are registered in the user which uses certificate authentication
+UINT PsUserCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ AUTHUSERCERT *a;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ a = (AUTHUSERCERT *)t.AuthData;
+
+ if (t.AuthType != AUTHTYPE_USERCERT || a == NULL || a->UserX == NULL)
+ {
+ // The user is not using specific certificate authentication
+ ret = ERR_INVALID_PARAMETER;
+
+ c->Write(c, _UU("CMD_UserCertGet_Not_Cert"));
+ }
+ else
+ {
+ if (XToFileW(a->UserX, GetParamUniStr(o, "SAVECERT"), true) == false)
+ {
+ c->Write(c, _UU("CMD_SAVECERT_FAILED"));
+ }
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Set the authentication method for the user to the signed certificate authentication
+UINT PsUserSignedSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"CN", CmdPrompt, _UU("CMD_UserSignedSet_Prompt_CN"), NULL, NULL},
+ {"SERIAL", CmdPrompt, _UU("CMD_UserSignedSet_Prompt_SERIAL"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ {
+ AUTHROOTCERT *c;
+ BUF *b;
+ X_SERIAL *serial = NULL;
+
+ b = StrToBin(GetParamStr(o, "SERIAL"));
+
+ if (b != NULL && b->Size >= 1)
+ {
+ serial = NewXSerial(b->Buf, b->Size);
+ }
+
+ FreeBuf(b);
+
+ c = NewRootCertAuthData(serial, GetParamUniStr(o, "CN"));
+
+ FreeXSerial(serial);
+
+ // Set to the signed certificate authentication
+ t.AuthType = AUTHTYPE_ROOTCERT;
+ t.AuthData = c;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the authentication method for the user to the Radius authentication
+UINT PsUserRadiusSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"ALIAS", CmdPrompt, _UU("CMD_UserRadiusSet_Prompt_ALIAS"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ {
+ AUTHRADIUS *a;
+
+ a = NewRadiusAuthData(GetParamUniStr(o, "ALIAS"));
+
+ // Set to Radius authentication
+ t.AuthType = AUTHTYPE_RADIUS;
+ t.AuthData = a;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the authentication method for the user to the NT domain authentication
+UINT PsUserNTLMSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"ALIAS", CmdPrompt, _UU("CMD_UserRadiusSet_Prompt_ALIAS"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ FreeAuthData(t.AuthType, t.AuthData);
+
+ {
+ AUTHRADIUS *a;
+
+ a = NewRadiusAuthData(GetParamUniStr(o, "ALIAS"));
+
+ // Set to the NT domain authentication
+ t.AuthType = AUTHTYPE_NT;
+ t.AuthData = a;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the security policy of the user
+UINT PsUserPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update
+ if (t.Policy != NULL)
+ {
+ Free(t.Policy);
+ t.Policy = NULL;
+ }
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set a security policy of the user
+UINT PsUserPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},
+ {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update
+ if (t.Policy == NULL)
+ {
+ t.Policy = ClonePolicy(GetDefaultPolicy());
+ }
+
+ // Edit
+ if (EditPolicy(c, t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), false) == false)
+ {
+ ret = ERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Convert the string to a date and time
+UINT64 StrToDateTime64(char *str)
+{
+ UINT64 ret = 0;
+ TOKEN_LIST *t;
+ UINT a, b, c, d, e, f;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (IsEmptyStr(str) || StrCmpi(str, "none") == 0)
+ {
+ return 0;
+ }
+
+ t = ParseToken(str, ":/,. \"");
+ if (t->NumTokens != 6)
+ {
+ FreeToken(t);
+ return INFINITE;
+ }
+
+ a = ToInt(t->Token[0]);
+ b = ToInt(t->Token[1]);
+ c = ToInt(t->Token[2]);
+ d = ToInt(t->Token[3]);
+ e = ToInt(t->Token[4]);
+ f = ToInt(t->Token[5]);
+
+ ret = INFINITE;
+
+ if (a >= 1000 && a <= 9999 && b >= 1 && b <= 12 && c >= 1 && c <= 31 &&
+ d >= 0 && d <= 23 && e >= 0 && e <= 59 && f >= 0 && f <= 59)
+ {
+ SYSTEMTIME t;
+
+ Zero(&t, sizeof(t));
+ t.wYear = a;
+ t.wMonth = b;
+ t.wDay = c;
+ t.wHour = d;
+ t.wMinute = e;
+ t.wSecond = f;
+
+ ret = SystemToUINT64(&t);
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Evaluate the date and time string
+bool CmdEvalDateTime(CONSOLE *c, wchar_t *str, void *param)
+{
+ UINT64 ret;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniToStr(tmp, sizeof(tmp), str);
+
+ ret = StrToDateTime64(tmp);
+
+ if (ret == INFINITE)
+ {
+ c->Write(c, _UU("CMD_EVAL_DATE_TIME_FAILED"));
+ return false;
+ }
+
+ return true;
+}
+
+// Set the expiration date of the user
+UINT PsUserExpiresSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ UINT64 expires;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"EXPIRES", CmdPrompt, _UU("CMD_UserExpiresSet_Prompt_EXPIRES"), CmdEvalDateTime, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ // Get the user object
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ ret = ScGetUser(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Update the information
+ expires = StrToDateTime64(GetParamStr(o, "EXPIRES"));
+
+ if (expires != 0)
+ {
+ expires = LocalToSystem64(expires);
+ }
+
+ t.ExpireTime = expires;
+
+ // Write the user object
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the group list
+UINT PsGroupList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_GROUP t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("SM_GROUPLIST_NAME"), false);
+ CtInsertColumn(ct, _UU("SM_GROUPLIST_REALNAME"), false);
+ CtInsertColumn(ct, _UU("SM_GROUPLIST_NOTE"), false);
+ CtInsertColumn(ct, _UU("SM_GROUPLIST_NUMUSERS"), false);
+
+ for (i = 0;i < t.NumGroup;i++)
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ RPC_ENUM_GROUP_ITEM *e = &t.Groups[i];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ UniToStru(tmp2, e->NumUsers);
+
+ CtInsert(ct, tmp1, e->Realname, e->Note, tmp2);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Create a group
+UINT PsGroupCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_GROUP t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"REALNAME", CmdPrompt, _UU("CMD_GroupCreate_Prompt_REALNAME"), NULL, NULL},
+ {"NOTE", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NOTE"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+ UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));
+ UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));
+
+ // RPC call
+ ret = ScCreateGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the group information
+UINT PsGroupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_GROUP t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"REALNAME", CmdPrompt, _UU("CMD_GroupCreate_Prompt_REALNAME"), NULL, NULL},
+ {"NOTE", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NOTE"), NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ // Information update
+ UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));
+ UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));
+
+ // RPC call
+ ret = ScSetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcSetGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete a group
+UINT PsGroupDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDeleteGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the group information and the list of users who belong to the group
+UINT PsGroupGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_GROUP t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ char groupname[MAX_USERNAME_LEN + 1];
+ CT *ct = CtNewStandard();
+
+ StrCpy(groupname, sizeof(groupname), t.Name);
+
+ StrToUni(tmp, sizeof(tmp), t.Name);
+ CtInsert(ct, _UU("CMD_GroupGet_Column_NAME"), tmp);
+ CtInsert(ct, _UU("CMD_GroupGet_Column_REALNAME"), t.Realname);
+ CtInsert(ct, _UU("CMD_GroupGet_Column_NOTE"), t.Note);
+
+ CtFree(ct, c);
+
+ if (t.Policy != NULL)
+ {
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_GroupGet_Column_POLICY"));
+
+ PrintPolicy(c, t.Policy, false);
+ }
+
+ {
+ RPC_ENUM_USER t;
+ bool b = false;
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ if (ScEnumUser(ps->Rpc, &t) == ERR_NO_ERROR)
+ {
+ UINT i;
+
+ for (i = 0;i < t.NumUser;i++)
+ {
+ RPC_ENUM_USER_ITEM *u = &t.Users[i];
+
+ if (StrCmpi(u->GroupName, groupname) == 0)
+ {
+ if (b == false)
+ {
+ b = true;
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_GroupGet_Column_MEMBERS"));
+ }
+
+ UniFormat(tmp, sizeof(tmp), L" %S", u->Name);
+ c->Write(c, tmp);
+ }
+ }
+ FreeRpcEnumUser(&t);
+
+ if (b)
+ {
+ c->Write(c, L"");
+ }
+ }
+ }
+
+ }
+
+ FreeRpcSetGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add an user to the group
+UINT PsGroupJoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_GroupJoin_Prompt_USERNAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "USERNAME"));
+
+ // RPC call
+ ret = ScGetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Update the Group
+ StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "[name]"));
+
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the user from a group
+UINT PsGroupUnjoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_USER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupUnjoin_Prompt_name"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Update the Group
+ StrCpy(t.GroupName, sizeof(t.GroupName), "");
+
+ ret = ScSetUser(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcSetUser(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the security policy of the group
+UINT PsGroupPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_GROUP t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Update
+ if (t.Policy != NULL)
+ {
+ Free(t.Policy);
+ t.Policy = NULL;
+ }
+
+ ret = ScSetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcSetGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set a security policy to a group
+UINT PsGroupPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SET_GROUP t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},
+ {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Update
+ if (t.Policy == NULL)
+ {
+ t.Policy = ClonePolicy(GetDefaultPolicy());
+ }
+
+ if (EditPolicy(c, t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), false) == false)
+ {
+ // An error has occured
+ FreeRpcSetGroup(&t);
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ERR_INTERNAL_ERROR;
+ }
+
+ ret = ScSetGroup(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcSetGroup(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the connected session list
+UINT PsSessionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_SESSION t;
+ UINT server_type = 0;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ {
+ // Get the server type
+ RPC_SERVER_INFO t;
+
+ Zero(&t, sizeof(t));
+
+ if (ScGetServerInfo(ps->Rpc, &t) == ERR_NO_ERROR)
+ {
+ server_type = t.ServerType;
+
+ FreeRpcServerInfo(&t);
+ }
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumSession(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_8"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_5"), true);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_6"), true);
+ CtInsertColumn(ct, _UU("SM_SESS_COLUMN_7"), true);
+
+ for (i = 0;i < t.NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t *tmp2;
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+ wchar_t tmp7[MAX_SIZE];
+ wchar_t tmp8[MAX_SIZE];
+ bool free_tmp2 = false;
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+
+ tmp2 = _UU("SM_SESS_NORMAL");
+ if (server_type != SERVER_TYPE_STANDALONE)
+ {
+ if (e->RemoteSession)
+ {
+ tmp2 = ZeroMalloc(MAX_SIZE);
+ UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_REMOTE"), e->RemoteHostname);
+ free_tmp2 = true;
+ }
+ else
+ {
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ tmp2 = _UU("SM_SESS_LOCAL");
+ }
+ else
+ {
+ tmp2 = ZeroMalloc(MAX_SIZE);
+ UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_LOCAL_2"), e->RemoteHostname);
+ free_tmp2 = true;
+ }
+ }
+ }
+ if (e->LinkMode)
+ {
+ if (free_tmp2)
+ {
+ Free(tmp2);
+ free_tmp2 = false;
+ }
+ tmp2 = _UU("SM_SESS_LINK");
+ }
+ else if (e->SecureNATMode)
+ {
+ /*if (free_tmp2)
+ {
+ Free(tmp2);
+ free_tmp2 = false;
+ }*/
+ tmp2 = _UU("SM_SESS_SNAT");
+ }
+
+ StrToUni(tmp3, sizeof(tmp3), e->Username);
+
+ StrToUni(tmp4, sizeof(tmp4), e->Hostname);
+ if (e->LinkMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LINK_HOSTNAME"));
+ }
+ else if (e->SecureNATMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_SNAT_HOSTNAME"));
+ }
+ else if (e->BridgeMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_BRIDGE_HOSTNAME"));
+ }
+ else if (StartWith(e->Username, L3_USERNAME))
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LAYER3_HOSTNAME"));
+ }
+
+ UniFormat(tmp5, sizeof(tmp5), L"%u / %u", e->CurrentNumTcp, e->MaxNumTcp);
+ if (e->LinkMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_LINK_TCP"));
+ }
+ else if (e->SecureNATMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_SNAT_TCP"));
+ }
+ else if (e->BridgeMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_BRIDGE_TCP"));
+ }
+
+ UniToStr3(tmp6, sizeof(tmp6), e->PacketSize);
+ UniToStr3(tmp7, sizeof(tmp7), e->PacketNum);
+
+ if (e->VLanId == 0)
+ {
+ UniStrCpy(tmp8, sizeof(tmp8), _UU("CM_ST_NO_VLAN"));
+ }
+ else
+ {
+ UniToStru(tmp8, e->VLanId);
+ }
+
+ CtInsert(ct, tmp1, tmp8, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
+
+ if (free_tmp2)
+ {
+ Free(tmp2);
+ }
+ }
+
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumSession(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Display the NODE_INFO
+void CmdPrintNodeInfo(CT *ct, NODE_INFO *info)
+{
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (ct == NULL || info == NULL)
+ {
+ return;
+ }
+
+ StrToUni(tmp, sizeof(tmp), info->ClientProductName);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", Endian32(info->ClientProductVer) / 100, Endian32(info->ClientProductVer) % 100);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_VER"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"Build %u", Endian32(info->ClientProductBuild));
+ CtInsert(ct, _UU("SM_NODE_CLIENT_BUILD"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsName);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_OS_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsVer);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_OS_VER"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsProductId);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_OS_PID"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientHostname);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_HOST"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ClientIpAddress, info->ClientIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_NODE_CLIENT_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ClientPort));
+ CtInsert(ct, _UU("SM_NODE_CLIENT_PORT"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ServerHostname);
+ CtInsert(ct, _UU("SM_NODE_SERVER_HOST"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ServerIpAddress, info->ServerIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_NODE_SERVER_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ServerPort));
+ CtInsert(ct, _UU("SM_NODE_SERVER_PORT"), tmp);
+
+ if (StrLen(info->ProxyHostname) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), info->ProxyHostname);
+ CtInsert(ct, _UU("SM_NODE_PROXY_HOSTNAME"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ProxyIpAddress, info->ProxyIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_NODE_PROXY_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ProxyPort));
+ CtInsert(ct, _UU("SM_NODE_PROXY_PORT"), tmp);
+ }
+}
+
+// Get the session information
+UINT PsSessionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SESSION_STATUS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_SessionGet_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScGetSessionStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ if (t.ClientIp != 0)
+ {
+ IPToStr4or6(str, sizeof(str), t.ClientIp, t.ClientIp6);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("SM_CLIENT_IP"), tmp);
+ }
+
+ if (StrLen(t.ClientHostName) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.ClientHostName);
+ CtInsert(ct, _UU("SM_CLIENT_HOSTNAME"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), t.Username);
+ CtInsert(ct, _UU("SM_SESS_STATUS_USERNAME"), tmp);
+
+ if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.RealUsername);
+ CtInsert(ct, _UU("SM_SESS_STATUS_REALUSER"), tmp);
+ }
+
+ if (IsEmptyStr(t.GroupName) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.GroupName);
+ CtInsert(ct, _UU("SM_SESS_STATUS_GROUPNAME"), tmp);
+ }
+
+
+ CmdPrintStatusToListViewEx(ct, &t.Status, true);
+
+ if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0 &&
+ StartWith(t.Username, L3_USERNAME) == false)
+ {
+ CmdPrintNodeInfo(ct, &t.NodeInfo);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcSessionStatus(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disconnect the session
+UINT PsSessionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_SESSION t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_SessionGet_Prompt_NAME"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));
+
+ // RPC call
+ ret = ScDeleteSession(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the MAC address table database
+UINT PsMacTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_MAC_TABLE t;
+ UINT i;
+
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[session_name]", NULL, NULL, NULL, NULL,}
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumMacTable(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ char *session_name = GetParamStr(o, "[session_name]");
+
+ if (IsEmptyStr(session_name))
+ {
+ session_name = NULL;
+ }
+
+ CtInsertColumn(ct, _UU("CMD_ID"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_1A"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_MAC_COLUMN_5"), false);
+
+ for (i = 0;i < t.NumMacTable;i++)
+ {
+ char str[MAX_SIZE];
+ wchar_t tmp0[128];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+
+ RPC_ENUM_MAC_TABLE_ITEM *e = &t.MacTables[i];
+
+ if (session_name == NULL || StrCmpi(e->SessionName, session_name) == 0)
+ {
+ UniToStru(tmp0, e->Key);
+
+ StrToUni(tmp1, sizeof(tmp1), e->SessionName);
+
+ MacToStr(str, sizeof(str), e->MacAddress);
+ StrToUni(tmp2, sizeof(tmp2), str);
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));
+
+ GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));
+
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));
+ }
+ else
+ {
+ UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);
+ }
+
+ UniToStru(tmp6, e->VlanId);
+ if (e->VlanId == 0)
+ {
+ UniStrCpy(tmp6, sizeof(tmp6), _UU("CM_ST_NONE"));
+ }
+
+ CtInsert(ct,
+ tmp0, tmp1, tmp6, tmp2, tmp3, tmp4, tmp5);
+ }
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumMacTable(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete a MAC address table entry
+UINT PsMacDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_TABLE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_MacDelete_Prompt"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDeleteMacTable(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the IP address table database
+UINT PsIpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_IP_TABLE t;
+ UINT i;
+
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[session_name]", NULL, NULL, NULL, NULL,}
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumIpTable(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ char *session_name = GetParamStr(o, "[session_name]");
+
+ if (IsEmptyStr(session_name))
+ {
+ session_name = NULL;
+ }
+
+ CtInsertColumn(ct, _UU("CMD_ID"), false);
+ CtInsertColumn(ct, _UU("SM_IP_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_IP_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_IP_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_IP_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_IP_COLUMN_5"), false);
+
+ for (i = 0;i < t.NumIpTable;i++)
+ {
+ char str[MAX_SIZE];
+ wchar_t tmp0[128];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ RPC_ENUM_IP_TABLE_ITEM *e = &t.IpTables[i];
+
+ if (session_name == NULL || StrCmpi(e->SessionName, session_name) == 0)
+ {
+ UniToStru(tmp0, e->Key);
+
+ StrToUni(tmp1, sizeof(tmp1), e->SessionName);
+
+ if (e->DhcpAllocated == false)
+ {
+ IPToStr(str, sizeof(str), &e->IpV6);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ }
+ else
+ {
+ IPToStr(str, sizeof(str), &e->IpV6);
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_MAC_IP_DHCP"), str);
+ }
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));
+
+ GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));
+
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));
+ }
+ else
+ {
+ UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);
+ }
+
+ CtInsert(ct,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumIpTable(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the IP address table entry
+UINT PsIpDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_DELETE_TABLE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_MacDelete_Prompt"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDeleteIpTable(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the DHCP server function and the virtual NAT (SecureNAT function)
+UINT PsSecureNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnableSecureNAT(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the DHCP server function and the virtual NAT (SecureNAT function)
+UINT PsSecureNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_HUB t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScDisableSecureNAT(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the operating status of the DHCP server function and the virtual NAT (SecureNAT function)
+UINT PsSecureNatStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_NAT_STATUS t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ StrToUni(tmp, sizeof(tmp), ps->HubName);
+ CtInsert(ct, _UU("SM_HUB_COLUMN_1"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumTcpSessions);
+ CtInsert(ct, _UU("NM_STATUS_TCP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumUdpSessions);
+ CtInsert(ct, _UU("NM_STATUS_UDP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumIcmpSessions);
+ CtInsert(ct, _UU("NM_STATUS_ICMP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumDnsSessions);
+ CtInsert(ct, _UU("NM_STATUS_DNS"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_CLIENT"), t.NumDhcpClients);
+ CtInsert(ct, _UU("NM_STATUS_DHCP"), tmp);
+
+ CtInsert(ct, _UU("SM_SNAT_IS_KERNEL"), t.IsKernelMode ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcNatStatus(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the network interface settings for a virtual host of SecureNAT function
+UINT PsSecureNatHostGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ // Flags
+ // MAC Address
+ MacToStr(str, sizeof(str), t.MacAddress);
+ StrToUni(tmp, sizeof(tmp), str);
+ CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_MAC"), tmp);
+
+ // IP address
+ IPToUniStr(tmp, sizeof(tmp), &t.Ip);
+ CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_IP"), tmp);
+
+ // Subnet mask
+ IPToUniStr(tmp, sizeof(tmp), &t.Mask);
+ CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_MASK"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Change the network interface settings for a virtual host of SecureNAT function
+UINT PsSecureNatHostSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"MAC", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_MAC"), NULL, NULL},
+ {"IP", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_IP"), CmdEvalIp, NULL},
+ {"MASK", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_MASK"), CmdEvalIp, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ char *mac, *ip, *mask;
+ bool ok = true;
+
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ mac = GetParamStr(o, "MAC");
+ ip = GetParamStr(o, "IP");
+ mask = GetParamStr(o, "MASK");
+
+ if (IsEmptyStr(mac) == false)
+ {
+ BUF *b = StrToBin(mac);
+
+ if (b == NULL || b->Size != 6)
+ {
+ ok = false;
+ }
+ else
+ {
+ Copy(t.MacAddress, b->Buf, 6);
+ }
+
+ FreeBuf(b);
+ }
+
+ if (IsEmptyStr(ip) == false)
+ {
+ if (IsIpStr4(ip) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ UINT u = StrToIP32(ip);
+
+ if (u == 0 || u == 0xffffffff)
+ {
+ ok = false;
+ }
+ else
+ {
+ UINTToIP(&t.Ip, u);
+ }
+ }
+ }
+
+ if (IsEmptyStr(mask) == false)
+ {
+ if (IsIpStr4(mask) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ StrToIP(&t.Mask, mask);
+ }
+ }
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the settings for the virtual NAT function of the SecureNAT function
+UINT PsNatGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ // Use the virtual NAT function
+ CtInsert(ct, _UU("CMD_NatGet_Column_USE"), t.UseNat ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ // MTU value
+ UniToStru(tmp, t.Mtu);
+ CtInsert(ct, _UU("CMD_NetGet_Column_MTU"), tmp);
+
+ // TCP session timeout (in seconds)
+ UniToStru(tmp, t.NatTcpTimeout);
+ CtInsert(ct, _UU("CMD_NatGet_Column_TCP"), tmp);
+
+ // UDP session timeout (in seconds)
+ UniToStru(tmp, t.NatUdpTimeout);
+ CtInsert(ct, _UU("CMD_NatGet_Column_UDP"), tmp);
+
+ // To save the log
+ CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_LOG"), t.SaveLog ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the virtual NAT function of the SecureNAT function
+UINT PsNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ t.UseNat = true;
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the virtual NAT function of the SecureNAT function
+UINT PsNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ t.UseNat = false;
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Change the settings for the virtual NAT function of the SecureNAT function
+UINT PsNatSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX mtu_mm =
+ {
+ "CMD_NatSet_Eval_MTU", TCP_HEADER_SIZE + IP_HEADER_SIZE + MAC_HEADER_SIZE + 8, MAX_L3_DATA_SIZE,
+ };
+ CMD_EVAL_MIN_MAX tcp_mm =
+ {
+ "CMD_NatSet_Eval_TCP", NAT_TCP_MIN_TIMEOUT / 1000, NAT_TCP_MAX_TIMEOUT / 1000,
+ };
+ CMD_EVAL_MIN_MAX udp_mm =
+ {
+ "CMD_NatSet_Eval_UDP", NAT_UDP_MIN_TIMEOUT / 1000, NAT_UDP_MAX_TIMEOUT / 1000,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"MTU", CmdPrompt, _UU("CMD_NatSet_Prompt_MTU"), CmdEvalMinMax, &mtu_mm},
+ {"TCPTIMEOUT", CmdPrompt, _UU("CMD_NatSet_Prompt_TCPTIMEOUT"), CmdEvalMinMax, &tcp_mm},
+ {"UDPTIMEOUT", CmdPrompt, _UU("CMD_NatSet_Prompt_UDPTIMEOUT"), CmdEvalMinMax, &udp_mm},
+ {"LOG", CmdPrompt, _UU("CMD_NatSet_Prompt_LOG"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ t.Mtu = GetParamInt(o, "MTU");
+ t.NatTcpTimeout = GetParamInt(o, "TCPTIMEOUT");
+ t.NatUdpTimeout = GetParamInt(o, "UDPTIMEOUT");
+ t.SaveLog = GetParamYes(o, "LOG");
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the session table of the virtual NAT function of the SecureNAT function
+UINT PsNatTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_NAT t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumNAT(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("NM_NAT_ID"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_PROTOCOL"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_SRC_HOST"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_SRC_PORT"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_DST_HOST"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_DST_PORT"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_CREATED"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_LAST_COMM"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_SIZE"), false);
+ CtInsertColumn(ct, _UU("NM_NAT_TCP_STATUS"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_NAT_ITEM *e = &t.Items[i];
+ wchar_t tmp0[MAX_SIZE];
+ wchar_t *tmp1 = L"";
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+ wchar_t tmp7[MAX_SIZE];
+ wchar_t tmp8[MAX_SIZE];
+ wchar_t *tmp9 = L"";
+ char v1[128], v2[128];
+
+ // ID
+ UniToStru(tmp0, e->Id);
+
+ // Protocol
+ switch (e->Protocol)
+ {
+ case NAT_TCP:
+ tmp1 = _UU("NM_NAT_PROTO_TCP");
+ break;
+ case NAT_UDP:
+ tmp1 = _UU("NM_NAT_PROTO_UDP");
+ break;
+ case NAT_DNS:
+ tmp1 = _UU("NM_NAT_PROTO_DNS");
+ break;
+ case NAT_ICMP:
+ tmp1 = _UU("NM_NAT_PROTO_ICMP");
+ break;
+ }
+
+ // Source host
+ StrToUni(tmp2, sizeof(tmp2), e->SrcHost);
+
+ // Source port
+ UniToStru(tmp3, e->SrcPort);
+
+ // Destination host
+ StrToUni(tmp4, sizeof(tmp4), e->DestHost);
+
+ // Destination port
+ UniToStru(tmp5, e->DestPort);
+
+ // Creation date and time of the session
+ GetDateTimeStrEx64(tmp6, sizeof(tmp6), SystemToLocal64(e->CreatedTime), NULL);
+
+ // Last communication date and time
+ GetDateTimeStrEx64(tmp7, sizeof(tmp7), SystemToLocal64(e->LastCommTime), NULL);
+
+ // Communication amount
+ ToStr3(v1, sizeof(v1), e->RecvSize);
+ ToStr3(v2, sizeof(v2), e->SendSize);
+ UniFormat(tmp8, sizeof(tmp8), L"%S / %S", v1, v2);
+
+ // TCP state
+ if (e->Protocol == NAT_TCP)
+ {
+ switch (e->TcpStatus)
+ {
+ case NAT_TCP_CONNECTING:
+ tmp9 = _UU("NAT_TCP_CONNECTING");
+ break;
+ case NAT_TCP_SEND_RESET:
+ tmp9 = _UU("NAT_TCP_SEND_RESET");
+ break;
+ case NAT_TCP_CONNECTED:
+ tmp9 = _UU("NAT_TCP_CONNECTED");
+ break;
+ case NAT_TCP_ESTABLISHED:
+ tmp9 = _UU("NAT_TCP_ESTABLISHED");
+ break;
+ case NAT_TCP_WAIT_DISCONNECT:
+ tmp9 = _UU("NAT_TCP_WAIT_DISCONNECT");
+ break;
+ }
+ }
+
+ CtInsert(ct,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumNat(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the settings for a virtual DHCP server function of the SecureNAT function
+UINT PsDhcpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ CT *ct = CtNewStandard();
+
+ // To use the virtual DHCP function
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_USE"), t.UseDhcp ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ // Start address of the distributing address zone
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpLeaseIPStart);
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_IP1"), tmp);
+
+ // End address of the distributing address zone
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpLeaseIPEnd);
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_IP2"), tmp);
+
+ // Subnet mask
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpSubnetMask);
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_MASK"), tmp);
+
+ // Lease time (in seconds)
+ UniToStru(tmp, t.DhcpExpireTimeSpan);
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_LEASE"), tmp);
+
+ // Default gateway address
+ UniStrCpy(tmp, sizeof(tmp), _UU("SEC_NONE"));
+ if (IPToUINT(&t.DhcpGatewayAddress) != 0)
+ {
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpGatewayAddress);
+ }
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_GW"), tmp);
+
+ // DNS server address 1
+ UniStrCpy(tmp, sizeof(tmp), _UU("SEC_NONE"));
+ if (IPToUINT(&t.DhcpDnsServerAddress) != 0)
+ {
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpDnsServerAddress);
+ }
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_DNS"), tmp);
+
+ // DNS server address 2
+ UniStrCpy(tmp, sizeof(tmp), _UU("SEC_NONE"));
+ if (IPToUINT(&t.DhcpDnsServerAddress2) != 0)
+ {
+ IPToUniStr(tmp, sizeof(tmp), &t.DhcpDnsServerAddress2);
+ }
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_DNS2"), tmp);
+
+ // Domain name
+ StrToUni(tmp, sizeof(tmp), t.DhcpDomainName);
+ CtInsert(ct, _UU("CMD_DhcpGet_Column_DOMAIN"), tmp);
+
+ // To save the log
+ CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_LOG"), t.SaveLog ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the Virtual DHCP server function of SecureNAT function
+UINT PsDhcpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ t.UseDhcp = true;
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Disable the virtual DHCP server function of SecureNAT function
+UINT PsDhcpDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ t.UseDhcp = false;
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Change the settings for a virtual DHCP server function of the SecureNAT function
+UINT PsDhcpSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ VH_OPTION t;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX mm =
+ {
+ "CMD_NatSet_Eval_UDP", NAT_UDP_MIN_TIMEOUT / 1000, NAT_UDP_MAX_TIMEOUT / 1000,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"START", CmdPrompt, _UU("CMD_DhcpSet_Prompt_START"), CmdEvalIp, NULL},
+ {"END", CmdPrompt, _UU("CMD_DhcpSet_Prompt_END"), CmdEvalIp, NULL},
+ {"MASK", CmdPrompt, _UU("CMD_DhcpSet_Prompt_MASK"), CmdEvalIp, NULL},
+ {"EXPIRE", CmdPrompt, _UU("CMD_DhcpSet_Prompt_EXPIRE"), CmdEvalMinMax, &mm},
+ {"GW", CmdPrompt, _UU("CMD_DhcpSet_Prompt_GW"), CmdEvalIp, NULL},
+ {"DNS", CmdPrompt, _UU("CMD_DhcpSet_Prompt_DNS"), CmdEvalIp, NULL},
+ {"DNS2", CmdPrompt, _UU("CMD_DhcpSet_Prompt_DNS2"), CmdEvalIp, NULL},
+ {"DOMAIN", CmdPrompt, _UU("CMD_DhcpSet_Prompt_DOMAIN"), NULL, NULL},
+ {"LOG", CmdPrompt, _UU("CMD_NatSet_Prompt_LOG"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ bool ok = true;
+
+ StrToIP(&t.DhcpLeaseIPStart, GetParamStr(o, "START"));
+ StrToIP(&t.DhcpLeaseIPEnd, GetParamStr(o, "END"));
+ StrToIP(&t.DhcpSubnetMask, GetParamStr(o, "MASK"));
+ t.DhcpExpireTimeSpan = GetParamInt(o, "EXPIRE");
+ StrToIP(&t.DhcpGatewayAddress, GetParamStr(o, "GW"));
+ StrToIP(&t.DhcpDnsServerAddress, GetParamStr(o, "DNS"));
+ StrToIP(&t.DhcpDnsServerAddress2, GetParamStr(o, "DNS2"));
+ StrCpy(t.DhcpDomainName, sizeof(t.DhcpDomainName), GetParamStr(o, "DOMAIN"));
+ t.SaveLog = GetParamYes(o, "LOG");
+
+ if (ok == false)
+ {
+ // Parameter is invalid
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetSecureNATOption(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the lease table of virtual DHCP server function of the SecureNAT function
+UINT PsDhcpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_DHCP t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumDHCP(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNew();
+ UINT i;
+
+ CtInsertColumn(ct, _UU("DHCP_DHCP_ID"), false);
+ CtInsertColumn(ct, _UU("DHCP_LEASED_TIME"), false);
+ CtInsertColumn(ct, _UU("DHCP_EXPIRE_TIME"), false);
+ CtInsertColumn(ct, _UU("DHCP_MAC_ADDRESS"), false);
+ CtInsertColumn(ct, _UU("DHCP_IP_ADDRESS"), false);
+ CtInsertColumn(ct, _UU("DHCP_HOSTNAME"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_DHCP_ITEM *e = &t.Items[i];
+ wchar_t tmp0[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ char str[MAX_SIZE];
+
+ // ID
+ UniToStru(tmp0, e->Id);
+
+ // Time
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->LeasedTime), NULL);
+ GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(e->ExpireTime), NULL);
+
+ MacToStr(str, sizeof(str), e->MacAddress);
+ StrToUni(tmp3, sizeof(tmp3), str);
+
+ IPToStr32(str, sizeof(str), e->IpAddress);
+ StrToUni(tmp4, sizeof(tmp4), str);
+
+ StrToUni(tmp5, sizeof(tmp5), e->Hostname);
+
+ CtInsert(ct,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumDhcp(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of Virtual HUB management options
+UINT PsAdminOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADMIN_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubAdminOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandardEx();
+ UINT i;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ ADMIN_OPTION *e = &t.Items[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ UniToStru(tmp2, e->Value);
+
+ CtInsert(ct, tmp1, tmp2, GetHubAdminOptionHelpString(e->Name));
+
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcAdminOption(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the value of a Virtual HUB management option
+UINT PsAdminOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADMIN_OPTION t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_name"), CmdEvalNotEmpty, NULL},
+ {"VALUE", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_VALUE"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubAdminOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ bool b = false;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ if (StrCmpi(t.Items[i].Name, GetParamStr(o, "[name]")) == 0)
+ {
+ t.Items[i].Value = GetParamInt(o, "VALUE");
+ b = true;
+ }
+ }
+
+ if (b == false)
+ {
+ // An error has occured
+ ret = ERR_OBJECT_NOT_FOUND;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeRpcAdminOption(&t);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetHubAdminOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeRpcAdminOption(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of Virtual HUB extended options
+UINT PsExtOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADMIN_OPTION t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubExtOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandardEx();
+ UINT i;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ ADMIN_OPTION *e = &t.Items[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ UniToStru(tmp2, e->Value);
+
+ CtInsert(ct, tmp1, tmp2, GetHubAdminOptionHelpString(e->Name));
+
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcAdminOption(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the value of a Virtual HUB extended option
+UINT PsExtOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ADMIN_OPTION t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[name]", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_name"), CmdEvalNotEmpty, NULL},
+ {"VALUE", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_VALUE"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetHubExtOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ bool b = false;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ if (StrCmpi(t.Items[i].Name, GetParamStr(o, "[name]")) == 0)
+ {
+ t.Items[i].Value = GetParamInt(o, "VALUE");
+ b = true;
+ }
+ }
+
+ if (b == false)
+ {
+ // An error has occured
+ ret = ERR_OBJECT_NOT_FOUND;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ FreeRpcAdminOption(&t);
+ return ret;
+ }
+ else
+ {
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ ret = ScSetHubExtOptions(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+ }
+
+ FreeRpcAdminOption(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the list of revoked certificate list
+UINT PsCrlList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_CRL t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScEnumCrl(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("CMD_ID"), false);
+ CtInsertColumn(ct, _UU("SM_CRL_COLUMN_1"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp[64];
+ RPC_ENUM_CRL_ITEM *e = &t.Items[i];
+
+ UniToStru(tmp, e->Key);
+ CtInsert(ct, tmp, e->CrlInfo);
+ }
+
+ CtFreeEx(ct, c, true);
+ }
+
+ FreeRpcEnumCrl(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add a revoked certificate
+UINT PsCrlAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CRL t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ {"SERIAL", NULL, NULL, NULL, NULL},
+ {"MD5", NULL, NULL, NULL, NULL},
+ {"SHA1", NULL, NULL, NULL, NULL},
+ {"CN", NULL, NULL, NULL, NULL},
+ {"O", NULL, NULL, NULL, NULL},
+ {"OU", NULL, NULL, NULL, NULL},
+ {"C", NULL, NULL, NULL, NULL},
+ {"ST", NULL, NULL, NULL, NULL},
+ {"L", NULL, NULL, NULL, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ {
+ bool param_exists = false;
+ CRL *crl = ZeroMalloc(sizeof(CRL));
+ NAME *n;
+ n = crl->Name = ZeroMalloc(sizeof(NAME));
+
+ if (IsEmptyStr(GetParamStr(o, "CN")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "CN"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "O")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "O"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "OU")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "OU"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "C")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "C"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "ST")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "ST"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "L")) == false)
+ {
+ n->CommonName = CopyUniStr(GetParamUniStr(o, "L"));
+ param_exists = true;
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "SERIAL")) == false)
+ {
+ BUF *b;
+
+ b = StrToBin(GetParamStr(o, "SERIAL"));
+
+ if (b != NULL && b->Size >= 1)
+ {
+ crl->Serial = NewXSerial(b->Buf, b->Size);
+ param_exists = true;
+ }
+
+ FreeBuf(b);
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "MD5")) == false)
+ {
+ BUF *b;
+
+ b = StrToBin(GetParamStr(o, "MD5"));
+
+ if (b != NULL && b->Size == MD5_SIZE)
+ {
+ Copy(crl->DigestMD5, b->Buf, MD5_SIZE);
+ param_exists = true;
+ }
+
+ FreeBuf(b);
+ }
+
+ if (IsEmptyStr(GetParamStr(o, "SHA1")) == false)
+ {
+ BUF *b;
+
+ b = StrToBin(GetParamStr(o, "SHA1"));
+
+ if (b != NULL && b->Size == SHA1_SIZE)
+ {
+ Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);
+ param_exists = true;
+ }
+
+ FreeBuf(b);
+ }
+
+ t.Crl = crl;
+
+ if (param_exists == false)
+ {
+ FreeRpcCrl(&t);
+ ret = ERR_INVALID_PARAMETER;
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ // RPC call
+ ret = ScAddCrl(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCrl(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the revoked certificate
+UINT PsCrlDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CRL t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_CrlDel_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDelCrl(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeRpcCrl(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the revoked certificate
+UINT PsCrlGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_CRL t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_CrlGet_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+ t.Key = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScGetCrl(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Show contents
+ CT *ct = CtNewStandard();
+ CRL *crl = t.Crl;
+ NAME *n;
+
+ if (crl != NULL)
+ {
+ n = crl->Name;
+
+ if (n != NULL)
+ {
+ if (UniIsEmptyStr(n->CommonName) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_CN"), n->CommonName);
+ }
+ if (UniIsEmptyStr(n->Organization) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_O"), n->Organization);
+ }
+ if (UniIsEmptyStr(n->Unit) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_OU"), n->Unit);
+ }
+ if (UniIsEmptyStr(n->Country) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_C"), n->Country);
+ }
+ if (UniIsEmptyStr(n->State) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_ST"), n->State);
+ }
+ if (UniIsEmptyStr(n->Local) == false)
+ {
+ CtInsert(ct, _UU("CMD_CrlGet_L"), n->Local);
+ }
+ }
+
+ if (crl->Serial != NULL && crl->Serial->size >= 1)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+
+ BinToStrEx(str, sizeof(str), crl->Serial->data, crl->Serial->size);
+ StrToUni(tmp, sizeof(tmp), str);
+
+ CtInsert(ct, _UU("CMD_CrlGet_SERI"), tmp);
+ }
+
+ if (IsZero(crl->DigestMD5, MD5_SIZE) == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+
+ BinToStrEx(str, sizeof(str), crl->DigestMD5, MD5_SIZE);
+ StrToUni(tmp, sizeof(tmp), str);
+
+ CtInsert(ct, _UU("CMD_CrlGet_MD5_HASH"), tmp);
+ }
+
+ if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+
+ BinToStrEx(str, sizeof(str), crl->DigestSHA1, SHA1_SIZE);
+ StrToUni(tmp, sizeof(tmp), str);
+
+ CtInsert(ct, _UU("CMD_CrlGet_SHA1_HASH"), tmp);
+ }
+ }
+ CtFree(ct, c);
+ }
+
+ FreeRpcCrl(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the rules of IP access control list
+UINT PsAcList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AC_LIST t;
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetAcList(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ UINT i;
+ CT *ct;
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("SM_AC_COLUMN_1"), true);
+ CtInsertColumn(ct, _UU("SM_AC_COLUMN_2"), true);
+ CtInsertColumn(ct, _UU("SM_AC_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_AC_COLUMN_4"), false);
+
+ for (i = 0;i < LIST_NUM(t.o);i++)
+ {
+ wchar_t tmp1[32], *tmp2, tmp3[MAX_SIZE], tmp4[32];
+ char *tmp_str;
+ AC *ac = LIST_DATA(t.o, i);
+
+ UniToStru(tmp1, ac->Id);
+ tmp2 = ac->Deny ? _UU("SM_AC_DENY") : _UU("SM_AC_PASS");
+ tmp_str = GenerateAcStr(ac);
+ StrToUni(tmp3, sizeof(tmp3), tmp_str);
+
+ Free(tmp_str);
+
+ UniToStru(tmp4, ac->Priority);
+
+ CtInsert(ct, tmp1, tmp4, tmp2, tmp3);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeRpcAcList(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add a rule to the IP access control list (IPv4)
+UINT PsAcAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AC_LIST t;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX mm =
+ {
+ "CMD_AcAdd_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[allow|deny]", CmdPrompt, _UU("CMD_AcAdd_Prompt_AD"), CmdEvalNotEmpty, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AcAdd_Prompt_PRIORITY"), CmdEvalMinMax, &mm},
+ {"IP", CmdPrompt, _UU("CMD_AcAdd_Prompt_IP"), CmdEvalIpAndMask4, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetAcList(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Add a new item to the list
+ AC *ac = ZeroMalloc(sizeof(AC));
+ char *test = GetParamStr(o, "[allow|deny]");
+ UINT u_ip, u_mask;
+
+ if (StartWith("deny", test))
+ {
+ ac->Deny = true;
+ }
+
+ ParseIpAndMask4(GetParamStr(o, "IP"), &u_ip, &u_mask);
+ UINTToIP(&ac->IpAddress, u_ip);
+
+ if (u_mask == 0xffffffff)
+ {
+ ac->Masked = false;
+ }
+ else
+ {
+ ac->Masked = true;
+ UINTToIP(&ac->SubnetMask, u_mask);
+ }
+
+ ac->Priority = GetParamInt(o, "PRIORITY");
+
+ Insert(t.o, ac);
+
+ ret = ScSetAcList(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcAcList(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add a rule to the IP access control list (IPv6)
+UINT PsAcAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AC_LIST t;
+ // Parameter list that can be specified
+ CMD_EVAL_MIN_MAX mm =
+ {
+ "CMD_AcAdd6_Eval_PRIORITY", 1, 4294967295UL,
+ };
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[allow|deny]", CmdPrompt, _UU("CMD_AcAdd6_Prompt_AD"), CmdEvalNotEmpty, NULL},
+ {"PRIORITY", CmdPrompt, _UU("CMD_AcAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &mm},
+ {"IP", CmdPrompt, _UU("CMD_AcAdd6_Prompt_IP"), CmdEvalIpAndMask6, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetAcList(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Add a new item to the list
+ AC *ac = ZeroMalloc(sizeof(AC));
+ char *test = GetParamStr(o, "[allow|deny]");
+ IP u_ip, u_mask;
+
+ if (StartWith("deny", test))
+ {
+ ac->Deny = true;
+ }
+
+ ParseIpAndMask6(GetParamStr(o, "IP"), &u_ip, &u_mask);
+ Copy(&ac->IpAddress, &u_ip, sizeof(IP));
+
+ if (SubnetMaskToInt6(&u_mask) == 128)
+ {
+ ac->Masked = false;
+ }
+ else
+ {
+ ac->Masked = true;
+ Copy(&ac->SubnetMask, &u_mask, sizeof(IP));
+ }
+
+ ac->Priority = GetParamInt(o, "PRIORITY");
+
+ Insert(t.o, ac);
+
+ ret = ScSetAcList(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcAcList(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Run the debug command
+UINT PsDebug(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ UINT id;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", NULL, NULL, NULL, NULL},
+ {"ARG", NULL, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ id = GetParamInt(o, "[id]");
+
+ if (true)
+ {
+ RPC_TEST t;
+ UINT ret;
+
+ c->Write(c, _UU("CMD_Debug_Msg1"));
+
+ Zero(&t, sizeof(t));
+
+ t.IntValue = id;
+ StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "ARG"));
+
+ ret = ScDebug(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[sizeof(t.StrValue)];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_Debug_Msg2"), t.StrValue);
+ c->Write(c, tmp);
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Flush the configuration file on the server
+UINT PsFlush(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (true)
+ {
+ RPC_TEST t;
+ UINT ret;
+ wchar_t tmp[MAX_SIZE];
+ char sizestr[MAX_SIZE];
+
+ c->Write(c, _UU("CMD_Flush_Msg1"));
+
+ Zero(&t, sizeof(t));
+
+ ret = ScFlush(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ToStr3(sizestr, sizeof(sizestr), (UINT64)t.IntValue);
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_Flush_Msg2"), sizestr);
+ c->Write(c, tmp);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Crash
+UINT PsCrash(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ char *yes;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[yes]", CmdPrompt, _UU("CMD_Crash_Confirm"), NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ yes = GetParamStr(o, "[yes]");
+
+ if (StrCmpi(yes, "yes") != 0)
+ {
+ c->Write(c, _UU("CMD_Crash_Aborted"));
+ }
+ else
+ {
+ RPC_TEST t;
+ UINT ret;
+
+ c->Write(c, _UU("CMD_Crash_Msg"));
+
+ Zero(&t, sizeof(t));
+
+ ret = ScCrash(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Remove a rule in the IP access control list
+UINT PsAcDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AC_LIST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_AcDel_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ // If virtual HUB is not selected, it's an error
+ if (ps->HubName == NULL)
+ {
+ c->Write(c, _UU("CMD_Hub_Not_Selected"));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
+
+ // RPC call
+ ret = ScGetAcList(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Remove matched ID
+ UINT i;
+ bool b = false;
+
+ for (i = 0;i < LIST_NUM(t.o);i++)
+ {
+ AC *ac = LIST_DATA(t.o, i);
+
+ if (ac->Id == GetParamInt(o, "[id]"))
+ {
+ Delete(t.o, ac);
+ Free(ac);
+ b = true;
+ break;
+ }
+ }
+
+ if (b == false)
+ {
+ ret = ERR_OBJECT_NOT_FOUND;
+ FreeRpcAcList(&t);
+ }
+ else
+ {
+ ret = ScSetAcList(ps->Rpc, &t);
+ }
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ }
+
+ FreeRpcAcList(&t);
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable / Disable the IPsec VPN server function
+UINT PsIPsecEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ IPSEC_SERVICES t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"L2TP", CmdPrompt, _UU("CMD_IPsecEnable_Prompt_L2TP"), CmdEvalNotEmpty, NULL},
+ {"L2TPRAW", CmdPrompt, _UU("CMD_IPsecEnable_Prompt_L2TPRAW"), CmdEvalNotEmpty, NULL},
+ {"ETHERIP", CmdPrompt, _UU("CMD_IPsecEnable_Prompt_ETHERIP"), CmdEvalNotEmpty, NULL},
+ {"PSK", CmdPrompt, _UU("CMD_IPsecEnable_Prompt_PSK"), CmdEvalNotEmpty, NULL},
+ {"DEFAULTHUB", CmdPrompt, _UU("CMD_IPsecEnable_Prompt_DEFAULTHUB"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.L2TP_IPsec = GetParamYes(o, "L2TP");
+ t.L2TP_Raw = GetParamYes(o, "L2TPRAW");
+ t.EtherIP_IPsec = GetParamYes(o, "ETHERIP");
+ StrCpy(t.IPsec_Secret, sizeof(t.IPsec_Secret), GetParamStr(o, "PSK"));
+ StrCpy(t.L2TP_DefaultHub, sizeof(t.L2TP_DefaultHub), GetParamStr(o, "DEFAULTHUB"));
+
+ // RPC call
+ ret = ScSetIPsecServices(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current configuration of IPsec VPN server function
+UINT PsIPsecGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ IPSEC_SERVICES t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetIPsecServices(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_PATH];
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_IPsecGet_PRINT_L2TP"), _UU(t.L2TP_IPsec ? "SEC_YES" : "SEC_NO"));
+ CtInsert(ct, _UU("CMD_IPsecGet_PRINT_L2TPRAW"), _UU(t.L2TP_Raw ? "SEC_YES" : "SEC_NO"));
+ CtInsert(ct, _UU("CMD_IPsecGet_PRINT_ETHERIP"), _UU(t.EtherIP_IPsec ? "SEC_YES" : "SEC_NO"));
+
+ StrToUni(tmp, sizeof(tmp), t.IPsec_Secret);
+ CtInsert(ct, _UU("CMD_IPsecGet_PRINT_PSK"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.L2TP_DefaultHub);
+ CtInsert(ct, _UU("CMD_IPsecGet_PRINT_DEFAULTHUB"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add connection settings for accepting connections from client devices of EtherIP / L2TPv3 over IPsec server function
+UINT PsEtherIpClientAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ ETHERIP_ID t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[ID]", CmdPrompt, _UU("CMD_EtherIpClientAdd_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ {"HUB", CmdPrompt, _UU("CMD_EtherIpClientAdd_Prompt_HUB"), CmdEvalNotEmpty, NULL},
+ {"USERNAME", CmdPrompt, _UU("CMD_EtherIpClientAdd_Prompt_USERNAME"), CmdEvalNotEmpty, NULL},
+ {"PASSWORD", CmdPrompt, _UU("CMD_EtherIpClientAdd_Prompt_PASSWORD"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Id, sizeof(t.Id), GetParamStr(o, "[ID]"));
+ StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "HUB"));
+ StrCpy(t.UserName, sizeof(t.UserName), GetParamStr(o, "USERNAME"));
+ StrCpy(t.Password, sizeof(t.Password), GetParamStr(o, "PASSWORD"));
+
+ // RPC call
+ ret = ScAddEtherIpId(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the connection settings for accepting connections from client devices of EtherIP / L2TPv3 over IPsec server function
+UINT PsEtherIpClientDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ ETHERIP_ID t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[ID]", CmdPrompt, _UU("CMD_EtherIpClientDelete_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Id, sizeof(t.Id), GetParamStr(o, "[ID]"));
+
+ // RPC call
+ ret = ScDeleteEtherIpId(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Show the list of connection settings for accepting connections from client devices of EtherIP / L2TPv3 over IPsec server function
+UINT PsEtherIpClientList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_ETHERIP_ID t;
+ UINT i;
+ CT *b;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumEtherIpId(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ b = CtNew();
+
+ CtInsertColumn(b, _UU("SM_ETHERIP_COLUMN_0"), false);
+ CtInsertColumn(b, _UU("SM_ETHERIP_COLUMN_1"), false);
+ CtInsertColumn(b, _UU("SM_ETHERIP_COLUMN_2"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ ETHERIP_ID *d = &t.IdList[i];
+ wchar_t id[MAX_SIZE], hubname[MAX_SIZE], username[MAX_SIZE];
+
+ StrToUni(id, sizeof(id), d->Id);
+ StrToUni(hubname, sizeof(hubname), d->HubName);
+ StrToUni(username, sizeof(username), d->UserName);
+
+ CtInsert(b, id, hubname, username);
+ }
+
+ CtFree(b, c);
+
+ FreeRpcEnumEtherIpId(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable / disable the OpenVPN compatible server function
+UINT PsOpenVpnEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ OPENVPN_SSTP_CONFIG t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[yes|no]", CmdPrompt, _UU("CMD_OpenVpnEnable_Prompt_[yes|no]"), CmdEvalNotEmpty, NULL},
+ {"PORTS", CmdPrompt, _UU("CMD_OpenVpnEnable_Prompt_PORTS"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.EnableOpenVPN = GetParamYes(o, "[yes|no]");
+ StrCpy(t.OpenVPNPortList, sizeof(t.OpenVPNPortList), GetParamStr(o, "PORTS"));
+
+ // RPC call
+ ret = ScSetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current settings for the OpenVPN compatible server function
+UINT PsOpenVpnGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ OPENVPN_SSTP_CONFIG t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ wchar_t tmp[MAX_PATH];
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_OpenVpnGet_PRINT_Enabled"), _UU(t.EnableOpenVPN ? "SEC_YES" : "SEC_NO"));
+
+ StrToUni(tmp, sizeof(tmp), t.OpenVPNPortList);
+ CtInsert(ct, _UU("CMD_OpenVpnGet_PRINT_Ports"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Generate a OpenVPN sample configuration file that can connect to the OpenVPN compatible server function
+UINT PsOpenVpnMakeConfig(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_READ_LOG_FILE t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[ZIP_FileName]", CmdPrompt, _UU("CMD_OpenVpnMakeConfig_Prompt_ZIP"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScMakeOpenVpnConfigFile(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ // Determine the file name to save
+ wchar_t filename[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+
+ UniStrCpy(filename, sizeof(filename), GetParamUniStr(o, "[ZIP_FileName]"));
+
+ if (UniEndWith(filename, L".zip") == false)
+ {
+ UniStrCat(filename, sizeof(filename), L".zip");
+ }
+
+ if (DumpBufW(t.Buffer, filename) == false)
+ {
+ ret = ERR_INTERNAL_ERROR;
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_OpenVpnMakeConfig_ERROR"), filename);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_OpenVpnMakeConfig_OK"), filename);
+ }
+
+ c->Write(c, tmp);
+
+ FreeRpcReadLogFile(&t);
+ }
+
+ FreeParamValueList(o);
+
+ return ret;
+}
+
+// Enable / disable the Microsoft SSTP VPN compatible server function
+UINT PsSstpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ OPENVPN_SSTP_CONFIG t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[yes|no]", CmdPrompt, _UU("CMD_SstpEnable_Prompt_[yes|no]"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ t.EnableSSTP = GetParamYes(o, "[yes|no]");
+
+ // RPC call
+ ret = ScSetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current settings for the Microsoft SSTP VPN compatible server function
+UINT PsSstpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ OPENVPN_SSTP_CONFIG t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_SstpEnable_PRINT_Enabled"), _UU(t.EnableSSTP ? "SEC_YES" : "SEC_NO"));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Register to the VPN Server by creating a new self-signed certificate with the specified CN (Common Name)
+UINT PsServerCertRegenerate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_TEST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[CN]", CmdPrompt, _UU("CMD_ServerCertRegenerate_Prompt_CN"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "[CN]"));
+
+ // RPC call
+ ret = ScRegenerateServerCert(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable / disable the VPN over ICMP / VPN over DNS server function
+UINT PsVpnOverIcmpDnsEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SPECIAL_LISTENER t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"ICMP", CmdPrompt, _UU("CMD_VpnOverIcmpDnsEnable_Prompt_ICMP"), CmdEvalNotEmpty, NULL},
+ {"DNS", CmdPrompt, _UU("CMD_VpnOverIcmpDnsEnable_Prompt_DNS"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.VpnOverIcmpListener = GetParamYes(o, "ICMP");
+ t.VpnOverDnsListener = GetParamYes(o, "DNS");
+
+ // RPC call
+ ret = ScSetSpecialListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get current settings of VPN over ICMP / VPN over DNS server function
+UINT PsVpnOverIcmpDnsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_SPECIAL_LISTENER t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetSpecialListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_VpnOverIcmpDnsGet_PRINT_ICMP"), _UU(t.VpnOverIcmpListener ? "SEC_YES" : "SEC_NO"));
+ CtInsert(ct, _UU("CMD_VpnOverIcmpDnsGet_PRINT_DNS"), _UU(t.VpnOverDnsListener ? "SEC_YES" : "SEC_NO"));
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable / disable the VPN Azure function
+UINT PsVpnAzureSetEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AZURE_STATUS t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[yes|no]", CmdPrompt, _UU("VpnAzureSetEnable_PROMPT"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.IsEnabled = GetParamYes(o, "[yes|no]");
+
+ // RPC call
+ ret = ScSetAzureStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current state of the VPN Azure function
+UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_AZURE_STATUS t;
+ DDNS_CLIENT_STATUS t2;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ Zero(&t2, sizeof(t2));
+
+ // RPC call
+ ret = ScGetAzureStatus(ps->Rpc, &t);
+
+ if (ret == ERR_NO_ERROR)
+ {
+ ret = ScGetDDnsClientStatus(ps->Rpc, &t2);
+ }
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_ENABLED"), _UU(t.IsEnabled ? "SEC_YES" : "SEC_NO"));
+
+ if (t.IsEnabled)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), L"%S%S", t2.CurrentHostName, AZURE_DOMAIN_SUFFIX);
+
+ CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_CONNECTED"), _UU(t.IsConnected ? "SEC_YES" : "SEC_NO"));
+ CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_HOSTNAME"), tmp);
+ }
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the current state of the dynamic DNS function
+UINT PsDynamicDnsGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ DDNS_CLIENT_STATUS t;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScGetDDnsClientStatus(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+ else
+ {
+ CT *ct = CtNewStandard();
+ wchar_t tmp[MAX_SIZE];
+
+ // FQDN
+ if (IsEmptyStr(t.CurrentFqdn) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.CurrentFqdn);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+ CtInsert(ct, _UU("CMD_DynamicDnsGetStatus_PRINT_FQDN"), tmp);
+
+ // Hostname
+ if (IsEmptyStr(t.CurrentHostName) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.CurrentHostName);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+ CtInsert(ct, _UU("CMD_DynamicDnsGetStatus_PRINT_HOSTNAME"), tmp);
+
+ // Suffix
+ if (IsEmptyStr(t.DnsSuffix) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.DnsSuffix);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+ CtInsert(ct, _UU("CMD_DynamicDnsGetStatus_PRINT_SUFFIX"), tmp);
+
+ // IPv4
+ if (t.Err_IPv4 == ERR_NO_ERROR)
+ {
+ StrToUni(tmp, sizeof(tmp), t.CurrentIPv4);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _E(t.Err_IPv4));
+ }
+ CtInsert(ct, _UU("CMD_DynamicDnsGetStatus_PRINT_IPv4"), tmp);
+
+ // IPv6
+ if (t.Err_IPv6 == ERR_NO_ERROR)
+ {
+ StrToUni(tmp, sizeof(tmp), t.CurrentIPv6);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _E(t.Err_IPv6));
+ }
+ CtInsert(ct, _UU("CMD_DynamicDnsGetStatus_PRINT_IPv6"), tmp);
+
+ CtFree(ct, c);
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Configure the dynamic DNS host name
+UINT PsDynamicDnsSetHostname(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_TEST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[hostname]", CmdPrompt, _UU("CMD_DynamicDnsSetHostname_Prompt_hostname"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "[hostname]"));
+
+ // RPC call
+ ret = ScChangeDDnsClientHostname(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Register a new license key
+UINT PsLicenseAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_TEST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[key]", CmdPrompt, _UU("CMD_LicenseAdd_Prompt_Key"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "[key]"));
+
+ // RPC call
+ ret = ScAddLicenseKey(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the registered license
+UINT PsLicenseDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_TEST t;
+ // Parameter list that can be specified
+ PARAM args[] =
+ {
+ // "name", prompt_proc, prompt_param, eval_proc, eval_param
+ {"[id]", CmdPrompt, _UU("CMD_LicenseDel_Prompt_ID"), CmdEvalNotEmpty, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.IntValue = GetParamInt(o, "[id]");
+
+ // RPC call
+ ret = ScDelLicenseKey(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+
+
+// Get the registered license list
+UINT PsLicenseList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_ENUM_LICENSE_KEY t;
+ CT *ct;
+ UINT i;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ // RPC call
+ ret = ScEnumLicenseKey(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_3"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_4"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_5"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_6"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_7"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_8"), false);
+ CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_9"), false);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp1[32], tmp2[LICENSE_KEYSTR_LEN + 1], tmp3[LICENSE_MAX_PRODUCT_NAME_LEN + 1],
+ *tmp4, tmp5[128], tmp6[LICENSE_LICENSEID_STR_LEN + 1], tmp7[64],
+ tmp8[64], tmp9[64];
+ RPC_ENUM_LICENSE_KEY_ITEM *e = &t.Items[i];
+
+ UniToStru(tmp1, e->Id);
+ StrToUni(tmp2, sizeof(tmp2), e->LicenseKey);
+ StrToUni(tmp3, sizeof(tmp3), e->LicenseName);
+ tmp4 = LiGetLicenseStatusStr(e->Status);
+ if (e->Expires == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp5, sizeof(tmp5), e->Expires, NULL);
+ }
+ StrToUni(tmp6, sizeof(tmp6), e->LicenseId);
+ UniToStru(tmp7, e->ProductId);
+ UniFormat(tmp8, sizeof(tmp8), L"%I64u", e->SystemId);
+ UniToStru(tmp9, e->SerialId);
+
+ CtInsert(ct,
+ tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);
+ }
+
+ CtFreeEx(ct, c, true);
+
+ FreeRpcEnumLicenseKey(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the license status of the current VPN Server
+UINT PsLicenseStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret = 0;
+ RPC_LICENSE_STATUS st;
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&st, sizeof(st));
+
+ // RPC call
+ ret = ScGetLicenseStatus(ps->Rpc, &st);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ // An error has occured
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNewStandard();
+
+ if (st.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE)
+ {
+ CtInsert(ct, _UU("SM_NO_LICENSE_COLUMN"), _UU("SM_NO_LICENSE"));
+ }
+ else
+ {
+ // Product edition name
+ StrToUni(tmp, sizeof(tmp), st.EditionStr);
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_EDITION"), tmp);
+
+ // Release date
+ if (st.ReleaseDate != 0)
+ {
+ GetDateStrEx64(tmp, sizeof(tmp), st.ReleaseDate, NULL);
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_RELEASE"), tmp);
+ }
+
+ // Current system ID
+ UniFormat(tmp, sizeof(tmp), L"%I64u", st.SystemId);
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_SYSTEM_ID"), tmp);
+
+ // Expiration date of the current license product
+ if (st.SystemExpires == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp, sizeof(tmp), st.SystemExpires, NULL);
+ }
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_EXPIRES"), tmp);
+
+ // Subscription (support) contract
+ if (st.NeedSubscription == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONEED"));
+ }
+ else
+ {
+ if (st.SubscriptionExpires == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONE"));
+ }
+ else
+ {
+ wchar_t dtstr[MAX_PATH];
+
+ GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);
+
+ UniFormat(tmp, sizeof(tmp),
+ st.IsSubscriptionExpired ? _UU("SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED") : _UU("SM_LICENSE_STATUS_SUBSCRIPTION_VALID"),
+ dtstr);
+ }
+ }
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_SUBSCRIPTION"), tmp);
+
+ if (st.NeedSubscription == false && st.SubscriptionExpires != 0)
+ {
+ wchar_t dtstr[MAX_PATH];
+
+ GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);
+
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), tmp);
+ }
+
+ if (GetCapsBool(ps->CapsList, "b_vpn3"))
+ {
+ // Maximum creatable number of users
+ if (st.NumClientConnectLicense == INFINITE)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, st.NumClientConnectLicense);
+ }
+ CtInsert(ct, _UU("SM_LICENSE_NUM_CLIENT"), tmp);
+ }
+
+ // Available number of concurrent client connections
+ if (st.NumBridgeConnectLicense == INFINITE)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, st.NumBridgeConnectLicense);
+ }
+ CtInsert(ct, _UU("SM_LICENSE_NUM_BRIDGE"), tmp);
+
+ // Availability of enterprise features
+ CtInsert(ct, _UU("SM_LICENSE_STATUS_ENTERPRISE"),
+ st.AllowEnterpriseFunction ? _UU("SM_LICENSE_STATUS_ENTERPRISE_YES") : _UU("SM_LICENSE_STATUS_ENTERPRISE_NO"));
+ }
+
+ CtFreeEx(ct, c, false);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+
+// Get the cluster configuration
+UINT PsClusterSettingGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_FARM t;
+ CT *ct;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ ret = ScGetFarmSetting(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ if (t.Weight == 0)
+ {
+ t.Weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ // Show the cluster configuration
+ ct = CtNewStandard();
+
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_Current"),
+ GetServerTypeStr(t.ServerType));
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_ControllerOnly"), t.ControllerOnly ? _UU("SEC_YES") : _UU("SEC_NO"));
+ }
+
+ if (t.ServerType != SERVER_TYPE_STANDALONE)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniToStru(tmp, t.Weight);
+
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_Weight"), tmp);
+ }
+
+ if (t.ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ wchar_t tmp[MAX_SIZE];
+ UINT i;
+
+ // Public IP address
+ if (t.PublicIp != 0)
+ {
+ IPToUniStr32(tmp, sizeof(tmp), t.PublicIp);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("CMD_ClusterSettingGet_None"));
+ }
+
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_PublicIp"), tmp);
+
+ // Public port list
+ tmp[0] = 0;
+ for (i = 0;i < t.NumPort;i++)
+ {
+ wchar_t tmp2[64];
+
+ UniFormat(tmp2, sizeof(tmp2), L"%u, ", t.Ports[i]);
+
+ UniStrCat(tmp, sizeof(tmp), tmp2);
+ }
+
+ if (UniEndWith(tmp, L", "))
+ {
+ tmp[UniStrLen(tmp) - 2] = 0;
+ }
+
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_PublicPorts"), tmp);
+
+ // Controller to connect
+ UniFormat(tmp, sizeof(tmp), L"%S:%u", t.ControllerName, t.ControllerPort);
+ CtInsert(ct, _UU("CMD_ClusterSettingGet_Controller"), tmp);
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcFarm(&t);
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Set the server password
+UINT PsServerPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_SET_PASSWORD t;
+ char *pw;
+ PARAM args[] =
+ {
+ {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ pw = GetParamStr(o, "[password]");
+
+ Zero(&t, sizeof(t));
+ Hash(t.HashedPassword, pw, StrLen(pw), true);
+
+ ret = ScSetServerPassword(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Password decision prompt (for Prompt function)
+wchar_t *CmdPromptChoosePassword(CONSOLE *c, void *param)
+{
+ char *s;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ s = CmdPasswordPrompt(c);
+
+ if (s == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ wchar_t *ret = CopyStrToUni(s);
+
+ Free(s);
+
+ return ret;
+ }
+}
+
+// Password input prompt (general-purpose)
+char *CmdPasswordPrompt(CONSOLE *c)
+{
+ char *pw1, *pw2;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ c->Write(c, _UU("CMD_VPNCMD_PWPROMPT_0"));
+
+RETRY:
+ c->Write(c, L"");
+
+
+ pw1 = c->ReadPassword(c, _UU("CMD_VPNCMD_PWPROMPT_1"));
+ if (pw1 == NULL)
+ {
+ return NULL;
+ }
+
+ pw2 = c->ReadPassword(c, _UU("CMD_VPNCMD_PWPROMPT_2"));
+ if (pw2 == NULL)
+ {
+ Free(pw1);
+ return NULL;
+ }
+
+ c->Write(c, L"");
+
+ if (StrCmp(pw1, pw2) != 0)
+ {
+ Free(pw1);
+ Free(pw2);
+ c->Write(c, _UU("CMD_VPNCMD_PWPROMPT_3"));
+ goto RETRY;
+ }
+
+ Free(pw1);
+
+ return pw2;
+}
+
+// Disable the listener
+UINT PsListenerDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER t;
+ PARAM args[] =
+ {
+ {"[port]", CmdPromptPort, _UU("CMD_ListenerDisable_PortPrompt"), CmdEvalPort, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Enable = false;
+ t.Port = ToInt(GetParamStr(o, "[port]"));
+
+ ret = ScEnableListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Enable the listener
+UINT PsListenerEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER t;
+ PARAM args[] =
+ {
+ {"[port]", CmdPromptPort, _UU("CMD_ListenerEnable_PortPrompt"), CmdEvalPort, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = ToInt(GetParamStr(o, "[port]"));
+
+ ret = ScEnableListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Draw a row of console table
+void CtPrintRow(CONSOLE *c, UINT num, UINT *widths, wchar_t **strings, bool *rights, char separate_char)
+{
+ UINT i;
+ wchar_t *buf;
+ UINT buf_size;
+ bool is_sep_line = true;
+ // Validate arguments
+ if (c == NULL || num == 0 || widths == NULL || strings == NULL || rights == NULL)
+ {
+ return;
+ }
+
+ buf_size = 32;
+ for (i = 0;i < num;i++)
+ {
+ buf_size += sizeof(wchar_t) * widths[i] + 6;
+ }
+
+ buf = ZeroMalloc(buf_size);
+
+ for (i = 0;i < num;i++)
+ {
+ char *tmp;
+ wchar_t *space_string;
+ UINT w;
+ UINT space = 0;
+ wchar_t *string = strings[i];
+ wchar_t *tmp_line = NULL;
+
+ if (UniStrCmpi(string, L"---") == 0)
+ {
+ char *s = MakeCharArray('-', widths[i]);
+ tmp_line = string = CopyStrToUni(s);
+
+ Free(s);
+ }
+ else
+ {
+ is_sep_line = false;
+ }
+
+ w = UniStrWidth(string);
+
+ if (widths[i] >= w)
+ {
+ space = widths[i] - w;
+ }
+
+ tmp = MakeCharArray(' ', space);
+ space_string = CopyStrToUni(tmp);
+
+ if (rights[i] != false)
+ {
+ UniStrCat(buf, buf_size, space_string);
+ }
+
+ UniStrCat(buf, buf_size, string);
+
+ if (rights[i] == false)
+ {
+ UniStrCat(buf, buf_size, space_string);
+ }
+
+ Free(space_string);
+ Free(tmp);
+
+ if (i < (num - 1))
+ {
+ wchar_t tmp[4];
+ char str[2];
+
+ if (UniStrCmpi(strings[i], L"---") == 0)
+ {
+ str[0] = '+';
+ }
+ else
+ {
+ str[0] = separate_char;
+ }
+ str[1] = 0;
+
+ StrToUni(tmp, sizeof(tmp), str);
+
+ UniStrCat(buf, buf_size, tmp);
+ }
+
+ if (tmp_line != NULL)
+ {
+ Free(tmp_line);
+ }
+ }
+
+ UniTrimRight(buf);
+
+ if (is_sep_line)
+ {
+ if (UniStrLen(buf) > (c->GetWidth(c) - 1))
+ {
+ buf[c->GetWidth(c) - 1] = 0;
+ }
+ }
+
+ c->Write(c, buf);
+
+ Free(buf);
+}
+
+// Draw the console table in standard format
+void CtPrintStandard(CT *ct, CONSOLE *c)
+{
+ CT *t;
+ UINT i, j;
+ // Validate arguments
+ if (ct == NULL || c == NULL)
+ {
+ return;
+ }
+
+ t = CtNewStandard();
+ for (i = 0;i < LIST_NUM(ct->Rows);i++)
+ {
+ CTR *row = LIST_DATA(ct->Rows, i);
+
+ for (j = 0;j < LIST_NUM(ct->Columns);j++)
+ {
+ CTC *column = LIST_DATA(ct->Columns, j);
+
+ CtInsert(t, column->String, row->Strings[j]);
+ }
+
+ if (i != (LIST_NUM(ct->Rows) - 1))
+ {
+ CtInsert(t, L"---", L"---");
+ }
+ }
+
+ CtFree(t, c);
+}
+
+// Draw the console table
+void CtPrint(CT *ct, CONSOLE *c)
+{
+ UINT *widths;
+ UINT num;
+ UINT i, j;
+ wchar_t **header_strings;
+ bool *rights;
+ // Validate arguments
+ if (ct == NULL || c == NULL)
+ {
+ return;
+ }
+
+ num = LIST_NUM(ct->Columns);
+ widths = ZeroMalloc(sizeof(UINT) * num);
+
+ // Calculate the maximum character width of each column
+ for (i = 0;i < num;i++)
+ {
+ CTC *ctc = LIST_DATA(ct->Columns, i);
+ UINT w;
+
+ w = UniStrWidth(ctc->String);
+ widths[i] = MAX(widths[i], w);
+ }
+ for (j = 0;j < LIST_NUM(ct->Rows);j++)
+ {
+ CTR *ctr = LIST_DATA(ct->Rows, j);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT w;
+
+ w = UniStrWidth(ctr->Strings[i]);
+ widths[i] = MAX(widths[i], w);
+ }
+ }
+
+ // Display the header part
+ header_strings = ZeroMalloc(sizeof(wchar_t *) * num);
+ rights = ZeroMalloc(sizeof(bool) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ CTC *ctc = LIST_DATA(ct->Columns, i);
+
+ header_strings[i] = ctc->String;
+ rights[i] = ctc->Right;
+ }
+
+ CtPrintRow(c, num, widths, header_strings, rights, '|');
+
+ for (i = 0;i < num;i++)
+ {
+ char *s;
+
+ s = MakeCharArray('-', widths[i]);
+ header_strings[i] = CopyStrToUni(s);
+ Free(s);
+ }
+
+ CtPrintRow(c, num, widths, header_strings, rights, '+');
+
+ for (i = 0;i < num;i++)
+ {
+ Free(header_strings[i]);
+ }
+
+ // Display the data part
+ for (j = 0;j < LIST_NUM(ct->Rows);j++)
+ {
+ CTR *ctr = LIST_DATA(ct->Rows, j);
+
+ CtPrintRow(c, num, widths, ctr->Strings, rights, '|');
+ }
+
+ Free(rights);
+ Free(header_strings);
+ Free(widths);
+}
+
+// Escape the meta-characters in CSV
+void CtEscapeCsv(wchar_t *dst, UINT size, wchar_t *src){
+ UINT i;
+ UINT len = UniStrLen(src);
+ UINT idx;
+ BOOL need_to_escape = false;
+ wchar_t tmp[2]=L"*";
+
+ // Check the input value
+ if (src==NULL || dst==NULL)
+ {
+ return;
+ }
+
+ // If there is no character that need to be escaped in the input characters, copy it to the output
+ len = UniStrLen(src);
+ for (i=0; i<len; i++)
+ {
+ tmp[0] = src[i];
+ if (tmp[0] == L","[0] || tmp[0] == L"\n"[0] || tmp[0] == L"\""[0])
+ {
+ need_to_escape = true;
+ }
+ }
+ if (need_to_escape == false)
+ {
+ UniStrCpy(dst,size,src);
+ return;
+ }
+
+ // If it contains meta characters (newline, comma, double quote), enclose with "
+ UniStrCpy(dst, size, L"\"");
+ idx = UniStrLen(dst);
+ if(idx<size-1)
+ {
+ for (i=0; i<len; i++)
+ {
+ tmp[0] = src[i];
+ // Convert " to "" in contents(MS-Excel method)
+ if (tmp[0] == L"\""[0])
+ {
+ UniStrCat(dst, size, tmp);
+ }
+ UniStrCat(dst, size, tmp);
+ }
+ }
+ UniStrCat(dst, size, L"\"");
+ return;
+}
+
+// Show a CSV format of console table
+void CtPrintCsv(CT *ct, CONSOLE *c)
+{
+ UINT i, j;
+ UINT num_columns = LIST_NUM(ct->Columns);
+ wchar_t buf[MAX_SIZE];
+ wchar_t fmtbuf[MAX_SIZE];
+
+ // Show the heading row
+ buf[0] = 0;
+ for(i=0; i<num_columns; i++)
+ {
+ CTC *ctc = LIST_DATA(ct->Columns, i);
+ CtEscapeCsv(fmtbuf, MAX_SIZE, ctc->String);
+ UniStrCat(buf, MAX_SIZE, fmtbuf);
+ if(i != num_columns-1)
+ UniStrCat(buf, MAX_SIZE, L",");
+ }
+ c->Write(c, buf);
+
+ // Show the table body
+ for(j=0; j<LIST_NUM(ct->Rows); j++)
+ {
+ CTR *ctr = LIST_DATA(ct->Rows, j);
+ buf[0] = 0;
+ for(i=0; i<num_columns; i++)
+ {
+ CtEscapeCsv(fmtbuf, MAX_SIZE, ctr->Strings[i]);
+ UniStrCat(buf, MAX_SIZE, fmtbuf);
+ if(i != num_columns-1)
+ UniStrCat(buf, MAX_SIZE, L",");
+ }
+ c->Write(c, buf);
+ }
+}
+
+// Delete the console table
+void CtFreeEx(CT *ct, CONSOLE *c, bool standard_view)
+{
+ UINT i, num;
+ // Validate arguments
+ if (ct == NULL)
+ {
+ return;
+ }
+
+ if (c != NULL)
+ {
+ if (c->ConsoleType == CONSOLE_CSV)
+ {
+ CtPrintCsv(ct, c);
+ }
+ else
+ {
+ if (standard_view == false)
+ {
+ CtPrint(ct, c);
+ }
+ else
+ {
+ CtPrintStandard(ct, c);
+ }
+ }
+ }
+
+ num = LIST_NUM(ct->Columns);
+
+ for (i = 0;i < LIST_NUM(ct->Rows);i++)
+ {
+ UINT j;
+ CTR *ctr = LIST_DATA(ct->Rows, i);
+
+ for (j = 0;j < num;j++)
+ {
+ Free(ctr->Strings[j]);
+ }
+
+ Free(ctr->Strings);
+ Free(ctr);
+ }
+
+ for (i = 0;i < LIST_NUM(ct->Columns);i++)
+ {
+ CTC *ctc = LIST_DATA(ct->Columns, i);
+
+ Free(ctc->String);
+ Free(ctc);
+ }
+
+ ReleaseList(ct->Columns);
+ ReleaseList(ct->Rows);
+
+ Free(ct);
+}
+void CtFree(CT *ct, CONSOLE *c)
+{
+ CtFreeEx(ct, c, false);
+}
+
+// Add a row to the table
+void CtInsert(CT *ct, ...)
+{
+ CTR *ctr;
+ UINT num, i;
+ va_list va;
+ // Validate arguments
+ if (ct == NULL)
+ {
+ return;
+ }
+
+ num = LIST_NUM(ct->Columns);
+
+ va_start(va, ct);
+
+ ctr = ZeroMalloc(sizeof(CTR));
+ ctr->Strings = ZeroMalloc(sizeof(wchar_t *) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *s = va_arg(va, wchar_t *);
+
+ ctr->Strings[i] = CopyUniStr(s);
+ }
+
+ va_end(va);
+
+ Insert(ct->Rows, ctr);
+}
+
+// Add a column to the table
+void CtInsertColumn(CT *ct, wchar_t *str, bool right)
+{
+ CTC *ctc;
+ // Validate arguments
+ if (ct == NULL)
+ {
+ return;
+ }
+ if (str == NULL)
+ {
+ str = L"";
+ }
+
+ ctc = ZeroMalloc(sizeof(CTC));
+ ctc->String = CopyUniStr(str);
+ ctc->Right = right;
+
+ Insert(ct->Columns, ctc);
+}
+
+// Create a new console table
+CT *CtNew()
+{
+ CT *ct;
+
+ ct = ZeroMalloc(sizeof(CT));
+ ct->Columns = NewList(NULL);
+ ct->Rows = NewList(NULL);
+
+ return ct;
+}
+
+// Add a standard column to a column in a table
+CT *CtNewStandard()
+{
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_2"), false);
+
+ return ct;
+}
+CT *CtNewStandardEx()
+{
+ CT *ct = CtNew();
+
+ CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_2"), false);
+ CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_3"), false);
+
+ return ct;
+}
+
+// Get the TCP listener list
+UINT PsListenerList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER_LIST t;
+ UINT i;
+ CT *ct;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+
+ ret = ScEnumListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("CM_LISTENER_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("CM_LISTENER_COLUMN_2"), false);
+
+ for (i = 0;i < t.NumPort;i++)
+ {
+ wchar_t *status = _UU("CM_LISTENER_OFFLINE");
+ wchar_t tmp[128];
+
+ if (t.Errors[i])
+ {
+ status = _UU("CM_LISTENER_ERROR");
+ }
+ else if (t.Enables[i])
+ {
+ status = _UU("CM_LISTENER_ONLINE");
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CM_LISTENER_TCP_PORT"), t.Ports[i]);
+
+ CtInsert(ct, tmp, status);
+ }
+
+ CtFree(ct, c);
+
+ FreeRpcListenerList(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Delete the TCP listener
+UINT PsListenerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER t;
+ PARAM args[] =
+ {
+ {"[port]", CmdPromptPort, _UU("CMD_ListenerDelete_PortPrompt"), CmdEvalPort, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = ToInt(GetParamStr(o, "[port]"));
+
+ ret = ScDeleteListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Draw a row
+void CmdPrintRow(CONSOLE *c, wchar_t *title, wchar_t *tag, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ wchar_t buf2[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (title == NULL || c == NULL || tag == NULL)
+ {
+ return;
+ }
+
+ va_start(args, tag);
+ UniFormatArgs(buf, sizeof(buf), tag, args);
+
+ UniFormat(buf2, sizeof(buf2), L"[%s] %s", title, buf);
+
+ va_end(args);
+
+ c->Write(c, buf2);
+}
+
+// ServerInfoGet command
+UINT PsServerInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_SERVER_INFO t;
+ CT *ct;
+ wchar_t tmp[MAX_SIZE];
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ ret = ScGetServerInfo(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_2"), false);
+
+ // Product name
+ StrToUni(tmp, sizeof(tmp), t.ServerProductName);
+ CtInsert(ct, _UU("SM_INFO_PRODUCT_NAME"), tmp);
+
+ // Version
+ StrToUni(tmp, sizeof(tmp), t.ServerVersionString);
+ CtInsert(ct, _UU("SM_INFO_VERSION"), tmp);
+
+ // Build
+ StrToUni(tmp, sizeof(tmp), t.ServerBuildInfoString);
+ CtInsert(ct, _UU("SM_INFO_BUILD"), tmp);
+
+ // Host name
+ StrToUni(tmp, sizeof(tmp), t.ServerHostName);
+ CtInsert(ct, _UU("SM_INFO_HOSTNAME"), tmp);
+
+ // Type
+ CtInsert(ct, _UU("SM_ST_SERVER_TYPE"), GetServerTypeStr(t.ServerType));
+
+ // OS
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);
+ CtInsert(ct, _UU("SM_OS_SYSTEM_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);
+ CtInsert(ct, _UU("SM_OS_PRODUCT_NAME"), tmp);
+
+ if (t.OsInfo.OsServicePack != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack);
+ CtInsert(ct, _UU("SM_OS_SERVICE_PACK"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);
+ CtInsert(ct, _UU("SM_OS_VENDER_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);
+ CtInsert(ct, _UU("SM_OS_VERSION"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);
+ CtInsert(ct, _UU("SM_OS_KERNEL_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);
+ CtInsert(ct, _UU("SM_OS_KERNEL_VERSION"), tmp);
+
+ CtFree(ct, c);
+
+ FreeRpcServerInfo(&t);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Get the string for type of the HUB
+wchar_t *GetHubTypeStr(UINT type)
+{
+ if (type == HUB_TYPE_FARM_STATIC)
+ {
+ return _UU("SM_HUB_STATIC");
+ }
+ else if (type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ return _UU("SM_HUB_DYNAMIC");
+ }
+ return _UU("SM_HUB_STANDALONE");
+}
+
+// Get a string of the type of server
+wchar_t *GetServerTypeStr(UINT type)
+{
+ if (type == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return _UU("SM_FARM_CONTROLLER");
+ }
+ else if (type == SERVER_TYPE_FARM_MEMBER)
+ {
+ return _UU("SM_FARM_MEMBER");
+ }
+ return _UU("SM_SERVER_STANDALONE");
+}
+
+// ServerStatusGet command
+UINT PsServerStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_SERVER_STATUS t;
+ wchar_t tmp[MAX_PATH];
+ char tmp2[MAX_PATH];
+ CT *ct;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ ret = ScGetServerStatus(ps->Rpc, &t);
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ ct = CtNew();
+
+ CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_1"), false);
+ CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_2"), false);
+
+ // Type of server
+ CtInsert(ct, _UU("SM_ST_SERVER_TYPE"),
+ t.ServerType == SERVER_TYPE_STANDALONE ? _UU("SM_SERVER_STANDALONE") :
+ t.ServerType == SERVER_TYPE_FARM_MEMBER ? _UU("SM_FARM_MEMBER") : _UU("SM_FARM_CONTROLLER"));
+
+ // Number of TCP connections
+ UniToStru(tmp, t.NumTcpConnections);
+ CtInsert(ct, _UU("SM_ST_NUM_TCP"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Number of local TCP connections
+ UniToStru(tmp, t.NumTcpConnectionsLocal);
+ CtInsert(ct, _UU("SM_ST_NUM_TCP_LOCAL"), tmp);
+
+ // Number of remote TCP connections
+ UniToStru(tmp, t.NumTcpConnectionsRemote);
+ CtInsert(ct, _UU("SM_ST_NUM_TCP_REMOTE"), tmp);
+ }
+
+ // Number of Virtual HUBs
+ UniToStru(tmp, t.NumHubTotal);
+ CtInsert(ct, _UU("SM_ST_NUM_HUB_TOTAL"), tmp);
+
+ if (t.ServerType != SERVER_TYPE_STANDALONE)
+ {
+ // Number of static HUBs
+ UniToStru(tmp, t.NumHubStatic);
+ CtInsert(ct, _UU("SM_ST_NUM_HUB_STATIC"), tmp);
+
+ // Number of dynamic HUBs
+ UniToStru(tmp, t.NumHubDynamic);
+ CtInsert(ct, _UU("SM_ST_NUM_HUB_DYNAMIC"), tmp);
+ }
+
+ // Number of sessions
+ UniToStru(tmp, t.NumSessionsTotal);
+ CtInsert(ct, _UU("SM_ST_NUM_SESSION_TOTAL"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Number of local sessions
+ UniToStru(tmp, t.NumSessionsLocal);
+ CtInsert(ct, _UU("SM_ST_NUM_SESSION_LOCAL"), tmp);
+
+ // Number of remote sessions
+ UniToStru(tmp, t.NumSessionsRemote);
+ CtInsert(ct, _UU("SM_ST_NUM_SESSION_REMOTE"), tmp);
+ }
+
+ // Number of MAC tables
+ UniToStru(tmp, t.NumMacTables);
+ CtInsert(ct, _UU("SM_ST_NUM_MAC_TABLE"), tmp);
+
+ // Number of IP tables
+ UniToStru(tmp, t.NumIpTables);
+ CtInsert(ct, _UU("SM_ST_NUM_IP_TABLE"), tmp);
+
+ // Number of users
+ UniToStru(tmp, t.NumUsers);
+ CtInsert(ct, _UU("SM_ST_NUM_USERS"), tmp);
+
+ // Number of groups
+ UniToStru(tmp, t.NumGroups);
+ CtInsert(ct, _UU("SM_ST_NUM_GROUPS"), tmp);
+
+ // Number of assigned licenses
+ UniToStru(tmp, t.AssignedClientLicenses);
+ CtInsert(ct, _UU("SM_ST_CLIENT_LICENSE"), tmp);
+
+ UniToStru(tmp, t.AssignedBridgeLicenses);
+ CtInsert(ct, _UU("SM_ST_BRIDGE_LICENSE"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UniToStru(tmp, t.AssignedClientLicensesTotal);
+ CtInsert(ct, _UU("SM_ST_CLIENT_LICENSE_EX"), tmp);
+
+ UniToStru(tmp, t.AssignedBridgeLicensesTotal);
+ CtInsert(ct, _UU("SM_ST_BRIDGE_LICENSE_EX"), tmp);
+ }
+
+ // Traffic
+ CmdInsertTrafficInfo(ct, &t.Traffic);
+
+ // Server start-up time
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartTime), NULL);
+ CtInsert(ct, _UU("SM_ST_START_TIME"), tmp);
+
+ // Current time
+ GetDateTimeStrMilli64(tmp2, sizeof(tmp2), SystemToLocal64(t.CurrentTime));
+ StrToUni(tmp, sizeof(tmp), tmp2);
+ CtInsert(ct, _UU("SM_ST_CURRENT_TIME"), tmp);
+
+ // Tick value
+ UniFormat(tmp, sizeof(tmp), L"%I64u", t.CurrentTick);
+ CtInsert(ct, _UU("SM_ST_CURRENT_TICK"), tmp);
+
+ // Memory information
+ if (t.MemInfo.TotalMemory != 0)
+ {
+ char vv[128];
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_TOTAL_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_USED_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_FREE_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_TOTAL_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_USED_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ CtInsert(ct, _UU("SM_ST_FREE_PHYS"), tmp);
+ }
+
+ CtFree(ct, c);
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// Add traffic information to LVB
+void CmdInsertTrafficInfo(CT *ct, TRAFFIC *t)
+{
+ wchar_t tmp[MAX_SIZE];
+ char vv[128];
+ // Validate arguments
+ if (ct == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // Transmission information
+ ToStr3(vv, sizeof(vv), t->Send.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_SEND_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_SEND_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_SEND_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_SEND_BCAST_SIZE"), tmp);
+
+ // Reception information
+ ToStr3(vv, sizeof(vv), t->Recv.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_RECV_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_RECV_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_RECV_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ CtInsert(ct, _UU("SM_ST_RECV_BCAST_SIZE"), tmp);
+}
+
+// Input a port number
+wchar_t *CmdPromptPort(CONSOLE *c, void *param)
+{
+ wchar_t *prompt_str;
+
+ if (param != NULL)
+ {
+ prompt_str = (wchar_t *)param;
+ }
+ else
+ {
+ prompt_str = _UU("CMD_PROPMT_PORT");
+ }
+
+ return c->ReadLine(c, prompt_str, true);
+}
+
+// Verify the port number
+bool CmdEvalPort(CONSOLE *c, wchar_t *str, void *param)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ i = UniToInt(str);
+
+ if (i >= 1 && i <= 65535)
+ {
+ return true;
+ }
+
+ c->Write(c, _UU("CMD_EVAL_PORT"));
+
+ return false;
+}
+
+// ListenerCreate command
+UINT PsListenerCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ PS *ps = (PS *)param;
+ UINT ret;
+ RPC_LISTENER t;
+ PARAM args[] =
+ {
+ {"[port]", CmdPromptPort, _UU("CMD_ListenerCreate_PortPrompt"), CmdEvalPort, NULL},
+ };
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = ToInt(GetParamStr(o, "[port]"));
+
+ ret = ScCreateListener(ps->Rpc, &t);
+
+ if (ret != ERR_NO_ERROR)
+ {
+ CmdPrintError(c, ret);
+ FreeParamValueList(o);
+ return ret;
+ }
+
+ FreeParamValueList(o);
+
+ return 0;
+}
+
+// About command
+UINT PsAbout(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ BUF *b;
+
+ o = ParseCommandList(c, cmd_name, str, NULL, 0);
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ b = ReadDump("|legal.txt");
+
+ CmdPrintAbout(c);
+ c->Write(c, L"\r\n");
+
+ if (b != NULL)
+ {
+ wchar_t *s;
+
+ SeekBufToEnd(b);
+ WriteBufChar(b, 13);
+ WriteBufChar(b, 10);
+ WriteBufChar(b, 0);
+
+ s = CopyUtfToUni(b->Buf);
+
+ c->Write(c, s);
+
+ Free(s);
+ }
+
+ // Display the version information
+ c->Write(c, _UU("D_ABOUT@S_INFO3"));
+ c->Write(c, L"\r\n");
+ c->Write(c, _UU("D_ABOUT@S_INFO4"));
+ c->Write(c, L"\r\n");
+ CmdPrintAbout(c);
+ c->Write(c, L"\r\n");
+
+ FreeParamValueList(o);
+
+ FreeBuf(b);
+
+ return 0;
+}
+
+// Creat a new server management context
+PS *NewPs(CONSOLE *c, RPC *rpc, char *servername, UINT serverport, char *hubname, char *adminhub, wchar_t *cmdline)
+{
+ PS *ps;
+ // Validate arguments
+ if (c == NULL || rpc == NULL || servername == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsEmptyStr(hubname))
+ {
+ hubname = NULL;
+ }
+ if (IsEmptyStr(adminhub))
+ {
+ adminhub = NULL;
+ }
+ if (UniIsEmptyStr(cmdline))
+ {
+ cmdline = NULL;
+ }
+
+ ps = ZeroMalloc(sizeof(PS));
+ ps->ConsoleForServer = true;
+ ps->ServerPort = serverport;
+ ps->ServerName = CopyStr(servername);
+ ps->Console = c;
+ ps->Rpc = rpc;
+ ps->HubName = CopyStr(hubname);
+ ps->LastError = 0;
+ ps->AdminHub = CopyStr(adminhub);
+ ps->CmdLine = CopyUniStr(cmdline);
+
+ return ps;
+}
+
+// Release the server management context
+void FreePs(PS *ps)
+{
+ // Validate arguments
+ if (ps == NULL)
+ {
+ return;
+ }
+
+ Free(ps->HubName);
+ Free(ps->AdminHub);
+ Free(ps->CmdLine);
+ Free(ps->ServerName);
+
+ Free(ps);
+}
+
+// Server Administration Tool
+UINT PsConnect(CONSOLE *c, char *host, UINT port, char *hub, char *adminhub, wchar_t *cmdline, char *password)
+{
+ UINT retcode = 0;
+ RPC *rpc = NULL;
+ CEDAR *cedar;
+ CLIENT_OPTION o;
+ UCHAR hashed_password[SHA1_SIZE];
+ bool b = false;
+ // Validate arguments
+ if (c == NULL || host == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+ if (port == 0)
+ {
+ port = 443;
+ }
+ if (hub != NULL)
+ {
+ adminhub = NULL;
+ }
+
+ cedar = NewCedar(NULL, NULL);
+
+ Zero(&o, sizeof(o));
+ UniStrCpy(o.AccountName, sizeof(o.AccountName), L"VPNCMD");
+ StrCpy(o.Hostname, sizeof(o.Hostname), host);
+ o.Port = port;
+ o.ProxyType = PROXY_DIRECT;
+
+ Hash(hashed_password, password, StrLen(password), true);
+
+ if (IsEmptyStr(password) == false)
+ {
+ b = true;
+ }
+
+ // Connect
+ while (true)
+ {
+ UINT err;
+
+ rpc = AdminConnectEx(cedar, &o, hub, hashed_password, &err, CEDAR_CUI_STR);
+ if (rpc == NULL)
+ {
+ // Failure
+ retcode = err;
+
+ if (err == ERR_ACCESS_DENIED)
+ {
+ char *pass;
+ // Password is incorrect
+ if (b)
+ {
+ // Input the password
+ c->Write(c, _UU("CMD_VPNCMD_PASSWORD_1"));
+ }
+
+ b = true;
+
+ pass = c->ReadPassword(c, _UU("CMD_VPNCMD_PASSWORD_2"));
+ c->Write(c, L"");
+
+ if (pass != NULL)
+ {
+ Hash(hashed_password, pass, StrLen(pass), true);
+ Free(pass);
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ // Other errors
+ CmdPrintError(c, err);
+ break;
+ }
+ }
+ else
+ {
+ PS *ps;
+
+ // Success
+ ps = NewPs(c, rpc, host, port, hub, adminhub, cmdline);
+ PsMain(ps);
+ retcode = ps->LastError;
+ FreePs(ps);
+ AdminDisconnect(rpc);
+ break;
+ }
+ }
+
+ ReleaseCedar(cedar);
+
+ return retcode;
+}
+
+// Display the error
+void CmdPrintError(CONSOLE *c, UINT err)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_ERROR"),
+ err, GetUniErrorStr(err));
+ c->Write(c, tmp);
+
+ if (err == ERR_DISCONNECTED)
+ {
+ c->Write(c, _UU("CMD_DISCONNECTED_MSG"));
+ }
+}
+
+// Display the version information
+void CmdPrintAbout(CONSOLE *c)
+{
+ CEDAR *cedar;
+ wchar_t tmp[MAX_SIZE];
+ char exe[MAX_PATH];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ cedar = NewCedar(NULL, NULL);
+
+ GetExeName(exe, sizeof(exe));
+
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_VPNCMD_ABOUT"),
+ cedar->VerString, cedar->BuildInfo);
+
+ c->Write(c, tmp);
+
+ ReleaseCedar(cedar);
+}
+
+// Parse the host name and port number (Separated by @)
+bool ParseHostPortAtmark(char *src, char **host, UINT *port, UINT default_port)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+
+ t = ParseToken(src, "@");
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (port != NULL)
+ {
+ *port = 0;
+ }
+
+ if (default_port == 0)
+ {
+ if (t->NumTokens < 2)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ if (ToInt(t->Token[1]) == 0)
+ {
+ FreeToken(t);
+ return false;
+ }
+ }
+
+ if (t->NumTokens >= 2 && ToInt(t->Token[1]) == 0)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ if (t->NumTokens >= 1 && IsEmptyStr(t->Token[0]) == false)
+ {
+ ret = true;
+
+ if (host != NULL)
+ {
+ *host = CopyStr(t->Token[0]);
+ Trim(*host);
+ }
+
+ if (t->NumTokens >= 2)
+ {
+ if (port != NULL)
+ {
+ *port = ToInt(t->Token[1]);
+ }
+ }
+ }
+
+ if (port != NULL)
+ {
+ if (*port == 0)
+ {
+ *port = default_port;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Parse the host name and port number
+bool ParseHostPort(char *src, char **host, UINT *port, UINT default_port)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+
+ if (StartWith(src, "["))
+ {
+ if (InStr(src, "]"))
+ {
+ // Format of [target]:port
+ UINT i, n;
+ char tmp[MAX_SIZE];
+
+ StrCpy(tmp, sizeof(tmp), src);
+
+ n = SearchStrEx(tmp, "]", 0, false);
+ if (n != INFINITE)
+ {
+ UINT len = StrLen(tmp);
+
+ for (i = n;i < len;i++)
+ {
+ if (tmp[i] == ':')
+ {
+ tmp[i] = '@';
+ }
+ }
+ }
+
+ return ParseHostPortAtmark(tmp, host, port, default_port);
+ }
+ }
+
+ if (InStr(src, "@"))
+ {
+ // It is separated by @
+ return ParseHostPortAtmark(src, host, port, default_port);
+ }
+
+ t = ParseToken(src, ":");
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (port != NULL)
+ {
+ *port = 0;
+ }
+
+ if (default_port == 0)
+ {
+ if (t->NumTokens < 2)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ if (ToInt(t->Token[1]) == 0)
+ {
+ FreeToken(t);
+ return false;
+ }
+ }
+
+ if (t->NumTokens >= 2 && ToInt(t->Token[1]) == 0)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ if (t->NumTokens >= 1 && IsEmptyStr(t->Token[0]) == false)
+ {
+ ret = true;
+
+ if (host != NULL)
+ {
+ *host = CopyStr(t->Token[0]);
+ Trim(*host);
+ }
+
+ if (t->NumTokens >= 2)
+ {
+ if (port != NULL)
+ {
+ *port = ToInt(t->Token[1]);
+ }
+ }
+ }
+
+ if (port != NULL)
+ {
+ if (*port == 0)
+ {
+ *port = default_port;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Vpncmd command procedure
+UINT VpnCmdProc(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
+{
+ LIST *o;
+ char *target;
+ bool server = false;
+ bool client = false;
+ bool tools = false;
+ char *hostname = NULL;
+ char *password;
+ wchar_t *cmdline;
+ bool host_inputted = false;
+ UINT port = 0;
+ UINT retcode = 0;
+ PARAM args[] =
+ {
+ {"[host:port]", NULL, NULL, NULL, NULL},
+ {"CLIENT", NULL, NULL, NULL, NULL},
+ {"SERVER", NULL, NULL, NULL, NULL},
+ {"TOOLS", NULL, NULL, NULL, NULL},
+ {"HUB", NULL, NULL, NULL, NULL},
+ {"ADMINHUB", NULL, NULL, NULL, NULL},
+ {"PASSWORD", NULL, NULL, NULL, NULL},
+ {"IN", NULL, NULL, NULL, NULL},
+ {"OUT", NULL, NULL, NULL, NULL},
+ {"CMD", NULL, NULL, NULL, NULL},
+ {"CSV", NULL, NULL, NULL, NULL},
+ };
+
+#ifdef OS_WIN32
+ if (UniStrCmpi(str, L"/debug") == 0)
+ {
+ // Debug information write mode
+ Win32CmdDebug(false);
+ return 0;
+ }
+ if (UniStrCmpi(str, L"/debug_uac") == 0)
+ {
+ // Debug information write mode
+ Win32CmdDebug(true);
+ return 0;
+ }
+#endif // OS_WIN32
+
+ if (c->ConsoleType == CONSOLE_LOCAL)
+ {
+ // Initialize the execute path information
+ VpnCmdInitBootPath();
+ }
+
+ if(c->ConsoleType != CONSOLE_CSV)
+ {
+ CmdPrintAbout(c);
+ c->Write(c, L"");
+ }
+
+ o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
+
+ if (o == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Specification of the mode of Tools or Server or Client
+ if ((GetParamStr(o, "CLIENT") == NULL && GetParamStr(o, "SERVER") == NULL && GetParamStr(o, "TOOLS") == NULL) ||
+ (GetParamStr(o, "CLIENT") != NULL && GetParamStr(o, "SERVER") != NULL && GetParamStr(o, "TOOLS") != NULL))
+ {
+ wchar_t *ret;
+ UINT code;
+ // The mode of Tools or Server or Client is not specified
+ c->Write(c, _UU("CMD_VPNCMD_CS_1"));
+
+ ret = c->ReadLine(c, _UU("CMD_VPNCMD_CS_2"), true);
+
+ code = UniToInt(ret);
+ Free(ret);
+
+ switch (code)
+ {
+ case 1:
+ // Server
+ server = true;
+ break;
+
+ case 2:
+ // Client
+ client = true;
+ break;
+
+ case 3:
+ // Tools
+ tools = true;
+ break;
+
+ default:
+ // Unspecified
+ FreeParamValueList(o);
+ return ERR_USER_CANCEL;
+ }
+
+ c->Write(c, L"");
+ }
+ else
+ {
+ if (GetParamStr(o, "SERVER") != NULL)
+ {
+ server = true;
+ }
+ else if (GetParamStr(o, "CLIENT") != NULL)
+ {
+ client = true;
+ }
+ else
+ {
+ tools = true;
+ }
+ }
+
+ // Destination host name
+ target = CopyStr(GetParamStr(o, "[host:port]"));
+
+ if (target == NULL && tools == false)
+ {
+ wchar_t *str;
+ // Input a host name
+ if (server)
+ {
+ c->Write(c, _UU("CMD_VPNCMD_HOST_1"));
+ }
+ else if (client)
+ {
+ c->Write(c, _UU("CMD_VPNCMD_HOST_2"));
+ }
+
+ str = c->ReadLine(c, _UU("CMD_VPNCMD_HOST_3"), true);
+ c->Write(c, L"");
+ target = CopyUniToStr(str);
+ Free(str);
+
+ if (target == NULL)
+ {
+ // Cancel
+ FreeParamValueList(o);
+ return ERR_USER_CANCEL;
+ }
+
+ if (IsEmptyStr(target))
+ {
+ Free(target);
+ target = CopyStr("localhost");
+ }
+ }
+ else
+ {
+ // User specifies a host name
+ host_inputted = true;
+ }
+
+ if (tools == false)
+ {
+ if (ParseHostPort(target, &hostname, &port, 443) == false)
+ {
+ c->Write(c, _UU("CMD_MSG_INVALID_HOSTNAME"));
+ Free(target);
+ FreeParamValueList(o);
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+
+ // Password
+ password = GetParamStr(o, "PASSWORD");
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ // Command line
+ cmdline = GetParamUniStr(o, "CMD");
+
+ if (server)
+ {
+ // Process as the server
+ char *hub;
+ char *adminhub = NULL;
+
+ hub = CopyStr(GetParamStr(o, "HUB"));
+ adminhub = GetParamStr(o, "ADMINHUB");
+
+ // Decide the Virtual HUB to be specified in the Virtual HUB management mode
+ if (hub == NULL)
+ {
+ if (host_inputted == false)
+ {
+ wchar_t *s;
+ // If the user does not specify a host name on the command line,
+ // get also a Virtual HUB name by displaying the prompt
+ c->Write(c, _UU("CMD_VPNCMD_HUB_1"));
+
+ s = c->ReadLine(c, _UU("CMD_VPNCMD_HUB_2"), true);
+
+ hub = CopyUniToStr(s);
+ Free(s);
+ }
+ }
+
+ if (IsEmptyStr(hub))
+ {
+ Free(hub);
+ hub = NULL;
+ }
+ if (IsEmptyStr(adminhub))
+ {
+ adminhub = NULL;
+ }
+
+ retcode = PsConnect(c, hostname, port, hub, adminhub, cmdline, password);
+
+ Free(hub);
+ }
+ else if (client)
+ {
+ // Treated as a client
+ Trim(target);
+
+ retcode = PcConnect(c, target, cmdline, password);
+ }
+ else if (tools)
+ {
+ // Treated as a VPN Tools
+ retcode = PtConnect(c, cmdline);
+ }
+
+ Free(hostname);
+ Free(target);
+ FreeParamValueList(o);
+
+ return retcode;
+}
+
+// Entry point of vpncmd
+UINT CommandMain(wchar_t *command_line)
+{
+ UINT ret = 0;
+ wchar_t *infile, *outfile;
+ char *a_infile, *a_outfile;
+ wchar_t *csvmode;
+ CONSOLE *c;
+
+ // Validate arguments
+ if (command_line == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ // Look ahead only items of /in and /out
+ infile = ParseCommand(command_line, L"in");
+ outfile = ParseCommand(command_line, L"out");
+ if (UniIsEmptyStr(infile))
+ {
+ Free(infile);
+ infile = NULL;
+ }
+ if (UniIsEmptyStr(outfile))
+ {
+ Free(outfile);
+ outfile = NULL;
+ }
+
+ a_infile = CopyUniToStr(infile);
+ a_outfile = CopyUniToStr(outfile);
+
+ // Allocate the local console
+ c = NewLocalConsole(infile, outfile);
+ if (c != NULL)
+ {
+ // Definition of commands of vpncmd
+ CMD cmd[] =
+ {
+ {"vpncmd", VpnCmdProc},
+ };
+
+ // Read ahead to check the CSV mode
+ csvmode = ParseCommand(command_line, L"csv");
+ if(csvmode != NULL)
+ {
+ Free(csvmode);
+ c->ConsoleType = CONSOLE_CSV;
+ }
+
+ if (DispatchNextCmdEx(c, command_line, ">", cmd, sizeof(cmd) / sizeof(cmd[0]), NULL) == false)
+ {
+ ret = ERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ ret = c->RetCode;
+ }
+
+ // Release the local console
+ c->Free(c);
+ }
+ else
+ {
+ Print("Error: Couldn't open local console.\n");
+ }
+
+ Free(a_infile);
+ Free(a_outfile);
+ Free(infile);
+ Free(outfile);
+
+ return ret;
+}
+
+#ifdef OS_WIN32
+// Debug information write mode
+void Win32CmdDebug(bool is_uac)
+{
+ wchar_t *dst;
+ wchar_t def_filename[MAX_SIZE];
+ SYSTEMTIME st;
+
+ InitWinUi(_UU("CMD_DEBUG_SOFTNAME"), NULL, 0);
+
+ UniPrint(_UU("CMD_DEBUG_PRINT"));
+
+ if (MsIsWin2000OrGreater() == false)
+ {
+ MsgBox(NULL, 0x00000040L, _UU("CMD_DEBUG_NOT_2000"));
+ goto LABEL_CLEANUP;
+ }
+
+ if ((MsIsVista() == false || is_uac) && MsIsAdmin() == false)
+ {
+ MsgBox(NULL, 0x00000040L, _UU("CMD_DEBUG_NOT_ADMIN"));
+ goto LABEL_CLEANUP;
+ }
+
+ if (MsIsVista() && MsIsAdmin() == false)
+ {
+ void *process_handle = NULL;
+
+ // Launch myself using the UAC
+ if (MsExecuteEx2W(MsGetExeFileNameW(), L"/debug_uac", &process_handle, true) == false)
+ {
+ MsgBox(NULL, 0x00000030L, _UU("CMD_DEBUG_UAC_FAILED"));
+ return;
+ }
+
+ MsCloseHandle(process_handle);
+ goto LABEL_CLEANUP;
+ }
+
+ LocalTime(&st);
+
+ UniFormat(def_filename, sizeof(def_filename), L"vpn_debuginfo_%04u%02u%02u_%02u%02u%02u.zip",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+
+ // Specify the destination
+ dst = SaveDlg(NULL, _UU("DLG_ZIP_FILER"), _UU("CMD_DEBUG_SAVE_TITLE"), def_filename, L".zip");
+ if (dst != NULL)
+ {
+ if (MsSaveSystemInfo(dst) == false)
+ {
+ // Failure
+ MsgBoxEx(NULL, 0x00000030L, _UU("CMD_DEBUG_NG"), dst);
+ }
+ else
+ {
+ // Success
+ MsgBoxEx(NULL, 0x00000040L, _UU("CMD_DEBUG_OK"), dst);
+ }
+
+ Free(dst);
+ }
+
+LABEL_CLEANUP:
+ FreeWinUi();
+}
+
+#endif // OS_WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Command.h b/src/Cedar/Command.h
new file mode 100644
index 00000000..104b7869
--- /dev/null
+++ b/src/Cedar/Command.h
@@ -0,0 +1,648 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Command.h
+// Header of Command.c
+
+#ifndef COMMAND_H
+#define COMMAND_H
+
+// Constants
+#define TRAFFIC_DEFAULT_PORT 9821
+#define TRAFFIC_NUMTCP_MAX 32
+#define TRAFFIC_NUMTCP_DEFAULT 32
+#define TRAFFIC_SPAN_DEFAULT 15
+#define TRAFFIC_TYPE_DOWNLOAD 1
+#define TRAFFIC_TYPE_UPLOAD 2
+#define TRAFFIC_TYPE_FULL 0
+#define TRAFFIC_BUF_SIZE 65535
+#define TRAFFIC_VER_STR_SIZE 16
+#define TRAFFIC_VER_STR "TrafficServer\r\n"
+
+// Constants for Win32
+#define VPNCMD_BOOTSTRAP_REG_KEYNAME "Software\\" GC_REG_COMPANY_NAME "\\VPN Command Line Utility"
+#define VPNCMD_BOOTSTRAP_REG_VALUENAME_VER "InstalledVersion"
+#define VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH "InstalledPath"
+#define VPNCMD_BOOTSTRAP_FILENAME "|vpncmdsys.exe"
+#define VPNCMD_BOOTSTRAP_FILENAME_X64 "|vpncmdsys_x64.exe"
+#define VPNCMD_BOOTSTRAP_FILENAME_IA64 "|vpncmdsys_ia64.exe"
+
+
+// Traffic test results
+struct TT_RESULT
+{
+ bool Raw; // Whether raw data
+ bool Double; // Whether it is doubled
+ UINT64 NumBytesUpload; // Uploaded size
+ UINT64 NumBytesDownload; // Downloaded size
+ UINT64 NumBytesTotal; // Total size
+ UINT64 Span; // Period (in milliseconds)
+ UINT64 BpsUpload; // Upload throughput
+ UINT64 BpsDownload; // Download throughput
+ UINT64 BpsTotal; // Total throughput
+};
+
+// Text display function
+typedef void (TT_PRINT_PROC)(void *param, wchar_t *str);
+
+// Client side socket
+struct TTC_SOCK
+{
+ SOCK *Sock; // Socket
+ UINT State; // State
+ UINT64 NumBytes; // Transmitted bytes
+ bool Download; // Download socket
+ bool ServerUploadReportReceived; // Complete to receive the report of upload amount from the server
+ UINT64 NextSendRequestReportTick; // Time to request a next report
+ UINT Id;
+ bool HideErrMsg;
+};
+
+// Traffic test Client
+struct TTC
+{
+ TT_PRINT_PROC *Print; // Text display function
+ void *Param; // Any parameters
+ bool Double; // Double mode
+ bool Raw; // Raw data mode
+ UINT Port; // Port number
+ char Host[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT NumTcp; // Number of TCP connections
+ UINT Type; // Type
+ UINT64 Span; // Period
+ UINT64 RealSpan; // The actual span
+ THREAD *Thread; // Thread
+ volatile bool Halt; // Halting flag
+ bool *Cancel; // Halting flag 2
+ SOCK_EVENT *SockEvent; // Socket event
+ LIST *ItcSockList; // Client socket list
+ TT_RESULT Result; // Result
+ UINT ErrorCode; // Error code
+ bool AbnormalTerminated; // Abnormal termination
+ EVENT *StartEvent; // Start event
+ EVENT *InitedEvent; // Initialize completion notification event
+};
+
+// Server side socket
+struct TTS_SOCK
+{
+ SOCK *Sock; // Socket
+ UINT State; // State
+ UINT64 NumBytes; // Transmitted bytes
+ bool SockJoined; // Whether it has been added to the event
+ UINT Id; // ID
+ UINT64 LastWaitTick; // Retry waiting time to notify the size information to the client
+ UINT64 SessionId; // Session ID
+ bool NoMoreSendData; // Flag not to send more data
+ UINT64 FirstRecvTick; // Time which the data has been received last
+ UINT64 Span; // Period
+};
+
+// Traffic test server
+struct TTS
+{
+ TT_PRINT_PROC *Print; // Text display function
+ void *Param; // Any parameters
+ volatile bool Halt; // Halting flag
+ UINT Port; // Port number
+ THREAD *Thread; // Thread
+ THREAD *WorkThread; // Worker thread
+ THREAD *IPv6AcceptThread; // IPv6 Accept thread
+ SOCK *ListenSocket; // Socket to wait
+ SOCK *ListenSocketV6; // Socket to wait (IPv6)
+ UINT ErrorCode; // Error code
+ SOCK_EVENT *SockEvent; // Socket event
+ LIST *TtsSockList; // Server socket list
+ bool NewSocketArrived; // New socket has arrived
+ UINT IdSeed; // ID value
+};
+
+// VPN Tools context
+struct PT
+{
+ CONSOLE *Console; // Console
+ UINT LastError; // Last error
+ wchar_t *CmdLine; // Command line to execute
+};
+
+// Server management context
+struct PS
+{
+ bool ConsoleForServer; // Console for the server (always true)
+ CONSOLE *Console; // Console
+ RPC *Rpc; // RPC
+ char *ServerName; // Server name
+ UINT ServerPort; // Port number
+ char *HubName; // Virtual HUB name in the currently managed
+ UINT LastError; // Last error
+ char *AdminHub; // Virtual HUB to be managed by default
+ wchar_t *CmdLine; // Command line to execute
+ CAPSLIST *CapsList; // Caps list
+};
+
+// Client management context
+struct PC
+{
+ bool ConsoleForServer; // Console for the server (always false)
+ CONSOLE *Console; // Console
+ REMOTE_CLIENT *RemoteClient; // Remote client
+ char *ServerName; // Server name
+ UINT LastError; // Last error
+ wchar_t *CmdLine; // Command line
+};
+
+// A column of the table
+struct CTC
+{
+ wchar_t *String; // String
+ bool Right; // Right justification
+};
+
+// A row of the table
+struct CTR
+{
+ wchar_t **Strings; // String list
+};
+
+// Table for console
+struct CT
+{
+ LIST *Columns; // Column list
+ LIST *Rows; // Row list
+};
+
+UINT CommandMain(wchar_t *command_line);
+UINT VpnCmdProc(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+bool ParseHostPort(char *src, char **host, UINT *port, UINT default_port);
+bool ParseHostPortAtmark(char *src, char **host, UINT *port, UINT default_port);
+CT *CtNew();
+void CtFree(CT *ct, CONSOLE *c);
+void CtFreeEx(CT *ct, CONSOLE *c, bool standard_view);
+void CtInsertColumn(CT *ct, wchar_t *str, bool right);
+CT *CtNewStandard();
+CT *CtNewStandardEx();
+void CtInsert(CT *ct, ...);
+void CtPrint(CT *ct, CONSOLE *c);
+void CtPrintStandard(CT *ct, CONSOLE *c);
+void CtPrintRow(CONSOLE *c, UINT num, UINT *widths, wchar_t **strings, bool *rights, char separate_char);
+void VpnCmdInitBootPath();
+void OutRpcTtResult(PACK *p, TT_RESULT *t);
+void InRpcTtResult(PACK *p, TT_RESULT *t);
+
+void CmdPrintError(CONSOLE *c, UINT err);
+void CmdPrintAbout(CONSOLE *c);
+void CmdPrintRow(CONSOLE *c, wchar_t *title, wchar_t *tag, ...);
+wchar_t *CmdPromptPort(CONSOLE *c, void *param);
+wchar_t *CmdPromptChoosePassword(CONSOLE *c, void *param);
+bool CmdEvalPort(CONSOLE *c, wchar_t *str, void *param);
+void CmdInsertTrafficInfo(CT *ct, TRAFFIC *t);
+wchar_t *GetHubTypeStr(UINT type);
+wchar_t *GetServerTypeStr(UINT type);
+char *CmdPasswordPrompt(CONSOLE *c);
+bool CmdEvalIp(CONSOLE *c, wchar_t *str, void *param);
+wchar_t *PsClusterSettingMemberPromptIp(CONSOLE *c, void *param);
+bool CmdEvalHostAndPort(CONSOLE *c, wchar_t *str, void *param);
+LIST *StrToPortList(char *str);
+bool CmdEvalPortList(CONSOLE *c, wchar_t *str, void *param);
+wchar_t *PsClusterSettingMemberPromptPorts(CONSOLE *c, void *param);
+K *CmdLoadKey(CONSOLE *c, wchar_t *filename);
+bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar_t *key_filename);
+bool CmdEvalTcpOrUdp(CONSOLE *c, wchar_t *str, void *param);
+wchar_t *GetConnectionTypeStr(UINT type);
+bool CmdEvalHostAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalNetworkAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalNetworkAndSubnetMask6(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalNetworkAndSubnetMask46(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalIpAndMask4(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalIpAndMask6(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalIpAndMask46(CONSOLE *c, wchar_t *str, void *param);
+wchar_t *GetLogSwitchStr(UINT i);
+wchar_t *GetPacketLogNameStr(UINT i);
+UINT StrToLogSwitchType(char *str);
+UINT StrToPacketLogType(char *str);
+UINT StrToPacketLogSaveInfoType(char *str);
+wchar_t *GetProxyTypeStr(UINT i);
+wchar_t *GetClientAuthTypeStr(UINT i);
+void PrintPolicyList(CONSOLE *c, char *name);
+void PrintPolicy(CONSOLE *c, POLICY *pol, bool cascade_mode);
+bool EditPolicy(CONSOLE *c, POLICY *pol, char *name, char *value, bool cascade_mode);
+void CmdPrintStatusToListView(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s);
+void CmdPrintStatusToListViewEx(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode);
+bool CmdEvalPassOrDiscard(CONSOLE *c, wchar_t *str, void *param);
+bool StrToPassOrDiscard(char *str);
+bool CmdEvalProtocol(CONSOLE *c, wchar_t *str, void *param);
+UINT StrToProtocol(char *str);
+bool CmdEvalPortRange(CONSOLE *c, wchar_t *str, void *param);
+bool ParsePortRange(char *str, UINT *start, UINT *end);
+wchar_t *GetAuthTypeStr(UINT id);
+UINT64 StrToDateTime64(char *str);
+bool CmdEvalDateTime(CONSOLE *c, wchar_t *str, void *param);
+void CmdPrintNodeInfo(CT *ct, NODE_INFO *info);
+wchar_t *GetProtocolName(UINT n);
+void CmdGenerateImportName(REMOTE_CLIENT *r, wchar_t *name, UINT size, wchar_t *old_name);
+bool CmdIsAccountName(REMOTE_CLIENT *r, wchar_t *name);
+wchar_t *GetSyslogSettingName(UINT n);
+
+
+void TtPrint(void *param, TT_PRINT_PROC *print_proc, wchar_t *str);
+void TtGenerateRandomData(UCHAR **buf, UINT *size);
+void TtsWorkerThread(THREAD *thread, void *param);
+void TtsListenThread(THREAD *thread, void *param);
+void TtsAcceptProc(TTS *tts, SOCK *listen_socket);
+void TtsIPv6AcceptThread(THREAD *thread, void *param);
+wchar_t *GetTtcTypeStr(UINT type);
+void TtcPrintSummary(TTC *ttc);
+void StopTtc(TTC *ttc);
+void TtcGenerateResult(TTC *ttc);
+void TtcThread(THREAD *thread, void *param);
+TTC *NewTtcEx(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param, EVENT *start_event, bool *cancel);
+TTC *NewTtc(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param);
+UINT FreeTtc(TTC *ttc, TT_RESULT *result);
+TTS *NewTts(UINT port, void *param, TT_PRINT_PROC *print_proc);
+UINT FreeTts(TTS *tts);
+void PtTrafficPrintProc(void *param, wchar_t *str);
+void TtcPrintResult(CONSOLE *c, TT_RESULT *res);
+
+
+bool SystemCheck();
+bool CheckKernel();
+bool CheckMemory();
+bool CheckStrings();
+bool CheckFileSystem();
+bool CheckThread();
+bool CheckNetwork();
+void InputToNull(void *p);
+UINT RetZero();
+
+void Win32CmdDebug(bool is_uac);
+
+
+UINT PtConnect(CONSOLE *c, wchar_t *cmdline);
+PT *NewPt(CONSOLE *c, wchar_t *cmdline);
+void FreePt(PT *pt);
+void PtMain(PT *pt);
+UINT PtMakeCert(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PtTrafficClient(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PtTrafficServer(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PtCheck(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+
+
+UINT PcConnect(CONSOLE *c, char *target, wchar_t *cmdline, char *password);
+PC *NewPc(CONSOLE *c, REMOTE_CLIENT *remote_client, char *servername, wchar_t *cmdline);
+void FreePc(PC *pc);
+void PcMain(PC *pc);
+UINT PcAbout(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcVersionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcPasswordGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcCertList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcCertAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcSecureList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcSecureSelect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcSecureGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicUpgrade(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicGetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicSetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcNicList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountConnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountNicSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountStatusShow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountStatusHide(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountSecureCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountRetrySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountStartupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountStartupRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountExport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcAccountImport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcRemoteEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcRemoteDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PcKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+
+
+PS *NewPs(CONSOLE *c, RPC *rpc, char *servername, UINT serverport, char *hubname, char *adminhub, wchar_t *cmdline);
+void FreePs(PS *ps);
+UINT PsConnect(CONSOLE *c, char *host, UINT port, char *hub, char *adminhub, wchar_t *cmdline, char *password);
+void PsMain(PS *ps);
+UINT PsAbout(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsListenerCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsListenerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsListenerList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsListenerEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsListenerDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterSettingGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterSettingStandalone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterSettingController(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterSettingMember(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterMemberList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterMemberInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterMemberCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsClusterConnectionStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCrash(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsFlush(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDebug(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerKeyGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerCipherGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerCipherSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSyslogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSyslogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSyslogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsConnectionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsConnectionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsConnectionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsBridgeDeviceList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsBridgeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsBridgeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsBridgeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCaps(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsReboot(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsConfigGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsConfigSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterStart(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterStop(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterIfList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterIfAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterIfDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterTableList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterTableAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRouterTableDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogFileList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogFileGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubCreateDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubCreateStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubSetStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubSetDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHubList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsHub(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSetMaxSession(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSetHubPassword(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSetEnumAllow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSetEnumDeny(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOptionsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRadiusServerSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRadiusServerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsRadiusServerGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogSwitchSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLogPacketSaveType(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCAList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCAAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCADelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCAGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadePasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadePolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadePolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsPolicyList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCascadeOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessAddEx(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessAddEx6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAccessDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserSignedSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserRadiusSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserNTLMSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsUserExpiresSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupJoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupUnjoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsGroupPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSessionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSessionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSessionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsMacTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsMacDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsIpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsIpDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSecureNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSecureNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSecureNatStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSecureNatHostGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSecureNatHostSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsNatGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsNatSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsNatTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDhcpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDhcpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDhcpDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDhcpSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDhcpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAdminOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAdminOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsExtOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsExtOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCrlList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCrlAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCrlDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsCrlGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAcList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAcAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAcAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAcGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsAcDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLicenseAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLicenseDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLicenseList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsLicenseStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsIPsecEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsIPsecGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsEtherIpClientAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsEtherIpClientDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsEtherIpClientList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOpenVpnEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOpenVpnGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsOpenVpnMakeConfig(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSstpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsSstpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsServerCertRegenerate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsVpnOverIcmpDnsEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsVpnOverIcmpDnsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDynamicDnsGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsDynamicDnsSetHostname(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsVpnAzureSetEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+
+
+#endif // COMMAND_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Connection.c b/src/Cedar/Connection.c
new file mode 100644
index 00000000..5cc0296c
--- /dev/null
+++ b/src/Cedar/Connection.c
@@ -0,0 +1,3457 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Connection.c
+// Connection Manager
+
+#include "CedarPch.h"
+
+// Determine whether the socket is to use to send
+#define IS_SEND_TCP_SOCK(ts) \
+ ((ts->Direction == TCP_BOTH) || ((ts->Direction == TCP_SERVER_TO_CLIENT) && (s->ServerMode)) || ((ts->Direction == TCP_CLIENT_TO_SERVER) && (s->ServerMode == false)))
+
+// Determine whether the socket is to use to receive
+#define IS_RECV_TCP_SOCK(ts) \
+ ((ts->Direction == TCP_BOTH) || ((ts->Direction == TCP_SERVER_TO_CLIENT) && (s->ServerMode == false)) || ((ts->Direction == TCP_CLIENT_TO_SERVER) && (s->ServerMode)))
+
+// Conversion of SECURE_SIGN
+void InRpcSecureSign(SECURE_SIGN *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(SECURE_SIGN));
+ PackGetStr(p, "SecurePublicCertName", t->SecurePublicCertName, sizeof(t->SecurePublicCertName));
+ PackGetStr(p, "SecurePrivateKeyName", t->SecurePrivateKeyName, sizeof(t->SecurePrivateKeyName));
+ t->ClientCert = PackGetX(p, "ClientCert");
+ PackGetData2(p, "Random", t->Random, sizeof(t->Random));
+ PackGetData2(p, "Signature", t->Signature, sizeof(t->Signature));
+ t->UseSecureDeviceId = PackGetInt(p, "UseSecureDeviceId");
+ t->BitmapId = PackGetInt(p, "BitmapId");
+}
+void OutRpcSecureSign(PACK *p, SECURE_SIGN *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "SecurePublicCertName", t->SecurePublicCertName);
+ PackAddStr(p, "SecurePrivateKeyName", t->SecurePrivateKeyName);
+ PackAddX(p, "ClientCert", t->ClientCert);
+ PackAddData(p, "Random", t->Random, sizeof(t->Random));
+ PackAddData(p, "Signature", t->Signature, sizeof(t->Signature));
+ PackAddInt(p, "UseSecureDeviceId", t->UseSecureDeviceId);
+ PackAddInt(p, "BitmapId", t->BitmapId);
+}
+void FreeRpcSecureSign(SECURE_SIGN *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeX(t->ClientCert);
+}
+
+// Generate the next packet
+BUF *NewKeepPacket(bool server_mode)
+{
+ BUF *b = NewBuf();
+ char *string = KEEP_ALIVE_STRING;
+
+ WriteBuf(b, string, StrLen(string));
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// KEEP thread
+void KeepThread(THREAD *thread, void *param)
+{
+ KEEP *k = (KEEP *)param;
+ SOCK *s;
+ char server_name[MAX_HOST_NAME_LEN + 1];
+ UINT server_port;
+ bool udp_mode;
+ bool enabled;
+ // Validate arguments
+ if (thread == NULL || k == NULL)
+ {
+ return;
+ }
+
+WAIT_FOR_ENABLE:
+ Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
+
+ // Wait until it becomes enabled
+ while (true)
+ {
+ enabled = false;
+ Lock(k->lock);
+ {
+ if (k->Enable)
+ {
+ if (StrLen(k->ServerName) != 0 && k->ServerPort != 0 && k->Interval != 0)
+ {
+ StrCpy(server_name, sizeof(server_name), k->ServerName);
+ server_port = k->ServerPort;
+ udp_mode = k->UdpMode;
+ enabled = true;
+ }
+ }
+ }
+ Unlock(k->lock);
+ if (enabled)
+ {
+ break;
+ }
+ if (k->Halt)
+ {
+ return;
+ }
+ Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
+ }
+
+ if (udp_mode == false)
+ {
+ // TCP mode
+ // Try until a success to connection
+ while (true)
+ {
+ UINT64 connect_started_tick;
+ bool changed = false;
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+ if (changed)
+ {
+ // Settings are changed
+ goto WAIT_FOR_ENABLE;
+ }
+
+ if (k->Halt)
+ {
+ // Stop
+ return;
+ }
+
+ // Attempt to connect to the server
+ connect_started_tick = Tick64();
+ s = ConnectEx2(server_name, server_port, KEEP_TCP_TIMEOUT, (bool *)&k->Halt);
+ if (s != NULL)
+ {
+ // Successful connection
+ break;
+ }
+
+ // Connection failure: Wait until timeout or the setting is changed
+ while (true)
+ {
+ changed = false;
+ if (k->Halt)
+ {
+ // Stop
+ return;
+ }
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+
+ if (changed)
+ {
+ // Settings are changed
+ goto WAIT_FOR_ENABLE;
+ }
+
+ if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)
+ {
+ break;
+ }
+
+ Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
+ }
+ }
+
+ // Success to connect the server
+ // Send and receive packet data periodically
+ if (s != NULL)
+ {
+ UINT64 last_packet_sent_time = 0;
+ while (true)
+ {
+ SOCKSET set;
+ UINT ret;
+ UCHAR buf[MAX_SIZE];
+ bool changed;
+
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+
+ Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);
+
+ ret = Recv(s, buf, sizeof(buf), false);
+ if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ }
+
+ if (s != NULL)
+ {
+ if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)
+ {
+ BUF *b;
+
+ // Send the next packet
+ last_packet_sent_time = Tick64();
+
+ b = NewKeepPacket(k->Server);
+
+ ret = Send(s, b->Buf, b->Size, false);
+ FreeBuf(b);
+
+ if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ }
+ }
+ }
+
+ changed = false;
+
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+
+ if (changed || s == NULL)
+ {
+ // Setting has been changed or disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ goto WAIT_FOR_ENABLE;
+ }
+ else
+ {
+ if (k->Halt)
+ {
+ // Stop
+ Disconnect(s);
+ ReleaseSock(s);
+ return;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ IP dest_ip;
+ // UDP mode
+ // Try to create socket until it successes
+ while (true)
+ {
+ UINT64 connect_started_tick;
+ bool changed = false;
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode == false)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+ if (changed)
+ {
+ // Settings are changed
+ goto WAIT_FOR_ENABLE;
+ }
+
+ if (k->Halt)
+ {
+ // Stop
+ return;
+ }
+
+ // Attempt to create a socket
+ connect_started_tick = Tick64();
+
+ // Attempt to resolve the name first
+ if (GetIP(&dest_ip, server_name))
+ {
+ // After successful name resolution, create a socket
+ s = NewUDP(0);
+ if (s != NULL)
+ {
+ // Creating success
+ break;
+ }
+ }
+
+ // Failure to create: wait until timeout or the setting is changed
+ while (true)
+ {
+ changed = false;
+ if (k->Halt)
+ {
+ // Stop
+ return;
+ }
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+
+ if (changed)
+ {
+ // Settings are changed
+ goto WAIT_FOR_ENABLE;
+ }
+
+ if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)
+ {
+ break;
+ }
+
+ Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
+ }
+ }
+
+ // Send the packet data periodically
+ if (s != NULL)
+ {
+ UINT64 last_packet_sent_time = 0;
+ UINT num_ignore_errors = 0;
+ while (true)
+ {
+ SOCKSET set;
+ UINT ret;
+ UCHAR buf[MAX_SIZE];
+ bool changed;
+ IP src_ip;
+ UINT src_port;
+
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+
+ Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);
+
+ // Receive
+ ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));
+ if (ret == 0)
+ {
+ if (s->IgnoreRecvErr == false)
+ {
+LABEL_DISCONNECTED:
+ // Disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto LABEL_DISCONNECTED;
+ }
+ }
+ }
+
+ if (s != NULL)
+ {
+ if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)
+ {
+ BUF *b;
+
+ // Send the next packet
+ last_packet_sent_time = Tick64();
+
+ b = NewKeepPacket(k->Server);
+
+ ret = SendTo(s, &dest_ip, server_port, b->Buf, b->Size);
+ FreeBuf(b);
+
+ if (ret == 0 && s->IgnoreSendErr == false)
+ {
+ // Disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ }
+ }
+ }
+
+ changed = false;
+
+ Lock(k->lock);
+ {
+ if (StrCmpi(k->ServerName, server_name) != 0 ||
+ k->ServerPort != server_port || k->Enable == false ||
+ k->UdpMode == false)
+ {
+ changed = true;
+ }
+ }
+ Unlock(k->lock);
+
+ if (changed || s == NULL)
+ {
+ // Setting has been changed or disconnected
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ goto WAIT_FOR_ENABLE;
+ }
+ else
+ {
+ if (k->Halt)
+ {
+ // Stop
+ Disconnect(s);
+ ReleaseSock(s);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+// Stop the KEEP
+void StopKeep(KEEP *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ k->Halt = true;
+ Set(k->HaltEvent);
+ Cancel(k->Cancel);
+
+ WaitThread(k->Thread, INFINITE);
+ ReleaseThread(k->Thread);
+ DeleteLock(k->lock);
+
+ ReleaseCancel(k->Cancel);
+ ReleaseEvent(k->HaltEvent);
+
+ Free(k);
+}
+
+// Start the KEEP
+KEEP *StartKeep()
+{
+ KEEP *k = ZeroMalloc(sizeof(KEEP));
+
+ k->lock = NewLock();
+ k->HaltEvent = NewEvent();
+ k->Cancel = NewCancel();
+
+ // Thread start
+ k->Thread = NewThread(KeepThread, k);
+
+ return k;
+}
+
+// Copy the client authentication data
+CLIENT_AUTH *CopyClientAuth(CLIENT_AUTH *a)
+{
+ CLIENT_AUTH *ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMallocEx(sizeof(CLIENT_AUTH), true);
+
+ ret->AuthType = a->AuthType;
+ StrCpy(ret->Username, sizeof(ret->Username), a->Username);
+
+ switch (a->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ // Anonymous authentication
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // Password authentication
+ Copy(ret->HashedPassword, a->HashedPassword, SHA1_SIZE);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ // Plaintext password authentication
+ StrCpy(ret->PlainPassword, sizeof(ret->PlainPassword), a->PlainPassword);
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ // Certificate authentication
+ ret->ClientX = CloneX(a->ClientX);
+ ret->ClientK = CloneK(a->ClientK);
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ // Secure device authentication
+ StrCpy(ret->SecurePublicCertName, sizeof(ret->SecurePublicCertName), a->SecurePublicCertName);
+ StrCpy(ret->SecurePrivateKeyName, sizeof(ret->SecurePrivateKeyName), a->SecurePrivateKeyName);
+ break;
+ }
+
+ return ret;
+}
+
+// Write data to the transmit FIFO (automatic encryption)
+void WriteSendFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)
+{
+ // Validate arguments
+ if (s == NULL || ts == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (s->UseFastRC4)
+ {
+ Encrypt(ts->SendKey, data, data, size);
+ }
+
+ WriteFifo(ts->SendFifo, data, size);
+}
+
+// Write data to the reception FIFO (automatic deccyption)
+void WriteRecvFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)
+{
+ // Validate arguments
+ if (s == NULL || ts == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (s->UseFastRC4)
+ {
+ Encrypt(ts->RecvKey, data, data, size);
+ }
+
+ WriteFifo(ts->RecvFifo, data, size);
+}
+
+// TCP socket receive
+UINT TcpSockRecv(SESSION *s, TCPSOCK *ts, void *data, UINT size)
+{
+ // Receive
+ return Recv(ts->Sock, data, size, s->UseSSLDataEncryption);
+}
+
+// TCP socket send
+UINT TcpSockSend(SESSION *s, TCPSOCK *ts, void *data, UINT size)
+{
+ // Transmission
+ return Send(ts->Sock, data, size, s->UseSSLDataEncryption);
+}
+
+// Send the data as UDP packet
+void SendDataWithUDP(SOCK *s, CONNECTION *c)
+{
+ UCHAR *buf;
+ BUF *b;
+ UINT64 dummy_64 = 0;
+ UCHAR dummy_buf[16];
+ UINT64 now = Tick64();
+ UINT ret;
+ bool force_flag = false;
+ bool packet_sent = false;
+ // Validate arguments
+ if (s == NULL || c == NULL)
+ {
+ return;
+ }
+
+ // Allocate the temporary buffer in heap
+ if (c->RecvBuf == NULL)
+ {
+ c->RecvBuf = Malloc(RECV_BUF_SIZE);
+ }
+ buf = c->RecvBuf;
+
+ if (c->Udp->NextKeepAliveTime == 0 || c->Udp->NextKeepAliveTime <= now)
+ {
+ force_flag = true;
+ }
+
+ // Creating a buffer
+ while ((c->SendBlocks->num_item > 0) || force_flag)
+ {
+ UINT *key32;
+ UINT64 *seq;
+ char *sign;
+
+ force_flag = false;
+
+ // Assemble a buffer from the current queue
+ b = NewBuf();
+
+ // Keep an area for packet header (16 bytes)
+ WriteBuf(b, dummy_buf, sizeof(dummy_buf));
+
+ // Pack the packets in transmission queue
+ LockQueue(c->SendBlocks);
+ {
+ while (true)
+ {
+ BLOCK *block;
+
+ if (b->Size > UDP_BUF_SIZE)
+ {
+ break;
+ }
+ block = GetNext(c->SendBlocks);
+ if (block == NULL)
+ {
+ break;
+ }
+
+ if (block->Size != 0)
+ {
+ WriteBufInt(b, block->Size);
+ WriteBuf(b, block->Buf, block->Size);
+
+ c->Session->TotalSendSize += (UINT64)block->SizeofData;
+ c->Session->TotalSendSizeReal += (UINT64)block->Size;
+ }
+
+ FreeBlock(block);
+ break;
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+
+ // Write sequence number and session key
+ sign = (char *)(((UCHAR *)b->Buf));
+ key32 = (UINT *)(((UCHAR *)b->Buf + 4));
+ seq = (UINT64 *)(((UCHAR *)b->Buf + 8));
+ Copy(sign, SE_UDP_SIGN, 4);
+ *key32 = Endian32(c->Session->SessionKey32);
+ *seq = Endian64(c->Udp->Seq++); // Increment the sequence number
+
+// InsertQueue(c->Udp->BufferQueue, b);
+
+ packet_sent = true;
+/* }
+
+ // Send a buffer
+ while (c->Udp->BufferQueue->num_item != 0)
+ {
+ FIFO *f = c->Udp->BufferQueue->fifo;
+ BUF **pb = (BUF**)(((UCHAR *)f->p) + f->pos);
+ BUF *b = *pb;
+
+*/ ret = SendTo(s, &c->Udp->ip, c->Udp->port, b->Buf, b->Size);
+ if (ret == SOCK_LATER)
+ {
+ // Blocking
+ Debug(".");
+// break;
+ }
+ if (ret != b->Size)
+ {
+ if (s->IgnoreSendErr == false)
+ {
+ // Error
+ Debug("******* SendTo Error !!!\n");
+ }
+ }
+
+ // Memory release
+ FreeBuf(b);
+// GetNext(c->Udp->BufferQueue);
+ }
+
+ if (packet_sent)
+ {
+ // KeepAlive time update
+ c->Udp->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
+ }
+}
+
+// Write the data of the UDP packet to the connection
+void PutUDPPacketData(CONNECTION *c, void *data, UINT size)
+{
+ BUF *b;
+ char sign[4];
+ // Validate arguments
+ if (c == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Examine the protocol
+ if (c->Protocol != CONNECTION_UDP)
+ {
+ // UDP protocol is not used
+ return;
+ }
+
+ // Buffer configuration
+ b = NewBuf();
+ WriteBuf(b, data, size);
+
+ SeekBuf(b, 0, 0);
+ ReadBuf(b, sign, 4);
+
+ // Signature confirmation
+ if (Cmp(sign, SE_UDP_SIGN, 4) == 0)
+ {
+ UINT key32;
+
+ // Session key number
+ key32 = ReadBufInt(b);
+
+ if (c->Session->SessionKey32 == key32)
+ {
+ UINT64 seq;
+
+ // Read the Sequence number
+ ReadBuf(b, &seq, sizeof(seq));
+ seq = Endian64(seq);
+
+ if ((UINT)(seq - c->Udp->RecvSeq - (UINT64)1))
+ {
+ //Debug("** UDP Seq Lost %u\n", (UINT)(seq - c->Udp->RecvSeq - (UINT64)1));
+ }
+ c->Udp->RecvSeq = seq;
+
+ //Debug("SEQ: %I32u\n", seq);
+
+ while (true)
+ {
+ UINT size;
+
+ size = ReadBufInt(b);
+ if (size == 0)
+ {
+ break;
+ }
+ else if (size <= MAX_PACKET_SIZE)
+ {
+ void *tmp;
+ BLOCK *block;
+
+ tmp = Malloc(size);
+ if (ReadBuf(b, tmp, size) != size)
+ {
+ Free(tmp);
+ break;
+ }
+
+ // Block configuration
+ block = NewBlock(tmp, size, 0);
+
+ // Insert Block
+ InsertReveicedBlockToQueue(c, block);
+ }
+ }
+
+ // Update the last communication time
+ c->Session->LastCommTime = Tick64();
+ }
+ else
+ {
+ Debug("Invalid SessionKey: 0x%X\n", key32);
+ }
+ }
+
+ FreeBuf(b);
+}
+
+// Add a block to the receive queue
+void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block)
+{
+ SESSION *s;
+ // Validate arguments
+ if (c == NULL || block == NULL)
+ {
+ return;
+ }
+
+ s = c->Session;
+
+ if (c->Protocol == CONNECTION_TCP)
+ {
+ s->TotalRecvSizeReal += block->SizeofData;
+ s->TotalRecvSize += block->Size;
+ }
+
+ LockQueue(c->ReceivedBlocks);
+ {
+ InsertQueue(c->ReceivedBlocks, block);
+ }
+ UnlockQueue(c->ReceivedBlocks);
+}
+
+// Generate the interval to the next Keep-Alive packet
+// (This should be a random number for the network load reduction)
+UINT GenNextKeepAliveSpan(CONNECTION *c)
+{
+ UINT a, b;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return INFINITE;
+ }
+
+ a = c->Session->Timeout;
+ b = rand() % (a / 2);
+ b = MAX(b, a / 5);
+
+ return b;
+}
+
+// send a Keep-Alive packet
+void SendKeepAlive(CONNECTION *c, TCPSOCK *ts)
+{
+ UINT size, i, num;
+ UINT size_be;
+ SESSION *s;
+ UCHAR *buf;
+ bool insert_natt_port = false;
+ // Validate arguments
+ if (c == NULL || ts == NULL)
+ {
+ return;
+ }
+
+ s = c->Session;
+
+ size = rand() % MAX_KEEPALIVE_SIZE;
+ num = KEEP_ALIVE_MAGIC;
+
+ if (s != NULL && s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ if (s->UdpAccel->MyPortByNatTServer != 0)
+ {
+ size = MAX(size, (StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE) + sizeof(USHORT)));
+
+ insert_natt_port = true;
+ }
+ }
+
+ buf = MallocFast(size);
+
+ for (i = 0;i < size;i++)
+ {
+ buf[i] = rand();
+ }
+
+ if (insert_natt_port)
+ {
+ USHORT myport = Endian16((USHORT)s->UdpAccel->MyPortByNatTServer);
+
+ Copy(buf, UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE, StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE));
+ Copy(buf + StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE), &myport, sizeof(USHORT));
+ }
+
+ num = Endian32(num);
+ size_be = Endian32(size);
+ WriteSendFifo(c->Session, ts, &num, sizeof(UINT));
+ WriteSendFifo(c->Session, ts, &size_be, sizeof(UINT));
+ WriteSendFifo(c->Session, ts, buf, size);
+
+ c->Session->TotalSendSize += sizeof(UINT) * 2 + size;
+ c->Session->TotalSendSizeReal += sizeof(UINT) * 2 + size;
+
+ Free(buf);
+}
+
+// Transmission of block
+void ConnectionSend(CONNECTION *c)
+{
+ UINT i, num;
+ UINT64 now;
+ UINT min_count;
+ UINT64 max_recv_tick;
+ TCPSOCK **tcpsocks;
+ UINT size;
+ SESSION *s;
+ HUB *hub = NULL;
+ bool use_qos;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ s = c->Session;
+ use_qos = s->QoS;
+
+ if (s != NULL)
+ {
+ hub = s->Hub;
+ }
+
+ now = Tick64();
+
+ // Protocol
+ if (c->Protocol == CONNECTION_TCP)
+ {
+ // TCP
+ TCP *tcp = c->Tcp;
+ TCPSOCK *ts;
+ TCPSOCK *ts_hp;
+ UINT num_available;
+ bool is_rudp = false;
+ LockList(tcp->TcpSockList);
+ {
+ num = LIST_NUM(tcp->TcpSockList);
+ tcpsocks = ToArrayEx(tcp->TcpSockList, true);
+ }
+ UnlockList(tcp->TcpSockList);
+
+ if (s != NULL)
+ {
+ is_rudp = s->IsRUDPSession;
+ }
+
+ // Select the socket that will be used to send
+ // Select a socket which have least delay count
+ min_count = INFINITE;
+ max_recv_tick = 0;
+ ts = NULL;
+ ts_hp = NULL;
+
+ num_available = 0;
+
+ if (c->IsInProc == false)
+ {
+ for (i = 0;i < num;i++)
+ {
+ TCPSOCK *tcpsock = tcpsocks[i];
+ if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&
+ IS_SEND_TCP_SOCK(tcpsock))
+ {
+ // Processing of KeepAlive
+ if (now >= tcpsock->NextKeepAliveTime || tcpsock->NextKeepAliveTime == 0 ||
+ (s != NULL && s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->MyPortByNatTServerChanged))
+ {
+ // Send the KeepAlive
+ SendKeepAlive(c, tcpsock);
+ tcpsock->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ s->UdpAccel->MyPortByNatTServerChanged = false;
+ }
+ }
+
+ // Count the number of available sockets to send
+ num_available++;
+
+ ts_hp = tcpsock;
+ }
+ }
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ TCPSOCK *tcpsock = tcpsocks[i];
+ if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&
+ IS_SEND_TCP_SOCK(tcpsock))
+ {
+ // Selection of the socket
+ bool b = false;
+
+ if (use_qos == false)
+ {
+ b = true;
+ }
+ else if (num_available < 2)
+ {
+ b = true;
+ }
+ else if (tcpsock != ts_hp)
+ {
+ b = true;
+ }
+
+ if (b)
+ {
+ if (is_rudp == false)
+ {
+ // Use a socket which have minimum delay occurrences in the case of such as a TCP socket
+ if (tcpsock->LateCount <= min_count)
+ {
+ min_count = tcpsock->LateCount;
+ ts = tcpsock;
+ }
+ }
+ else
+ {
+ // Use socket which have the largest last received time in the case of R-UDP socket
+ if (tcpsock->LastRecvTime >= max_recv_tick)
+ {
+ max_recv_tick = tcpsock->LastRecvTime;
+ ts = tcpsock;
+ }
+ }
+ }
+ }
+ }
+
+ if (ts_hp == NULL)
+ {
+ ts_hp = ts;
+ }
+
+ if (use_qos == false)
+ {
+ ts_hp = ts;
+ }
+
+ if (ts == NULL || ts_hp == NULL)
+ {
+ // The socket available to send doesn't currently exist
+ }
+ else
+ {
+ TCPSOCK *tss;
+ UINT j;
+ QUEUE *q;
+
+ if (s->UdpAccel != NULL)
+ {
+ UdpAccelSetTick(s->UdpAccel, now);
+ }
+
+ for (j = 0;j < 2;j++)
+ {
+ if (j == 0)
+ {
+ q = c->SendBlocks2;
+ tss = ts_hp;
+ }
+ else
+ {
+ q = c->SendBlocks;
+ tss = ts;
+ }
+ // I reserve the data to send on the selected socket ts
+ LockQueue(c->SendBlocks);
+ if (q->num_item != 0)
+ {
+ UINT num_data;
+ BLOCK *b;
+
+ if (tss->SendFifo->size >= MAX((MAX_SEND_SOCKET_QUEUE_SIZE / s->MaxConnection), MIN_SEND_SOCKET_QUEUE_SIZE))
+ {
+ // The size of the socket send queue is exceeded
+ // Unable to send
+ while (b = GetNext(q))
+ {
+ if (b != NULL)
+ {
+ c->CurrentSendQueueSize -= b->Size;
+ FreeBlock(b);
+ }
+ }
+ }
+ else
+ {
+ if (c->IsInProc == false)
+ {
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL && UdpAccelIsSendReady(s->UdpAccel, true))
+ {
+ // UDP acceleration mode
+ while (b = GetNext(q))
+ {
+ UdpAccelSendBlock(s->UdpAccel, b);
+
+ s->TotalSendSize += b->Size;
+ s->TotalSendSizeReal += b->Size;
+
+ c->CurrentSendQueueSize -= b->Size;
+
+ FreeBlock(b);
+ }
+ }
+ else if (s->IsRUDPSession && s->EnableBulkOnRUDP && ts->Sock != NULL && ts->Sock->BulkSendTube != NULL)
+ {
+ // R-UDP bulk transfer
+ TUBE *t = ts->Sock->BulkSendTube;
+ bool flush = false;
+ TCP_PAIR_HEADER h;
+
+ Zero(&h, sizeof(h));
+ h.EnableHMac = s->EnableHMacOnBulkOfRUDP;
+
+ while (b = GetNext(q))
+ {
+ if (b->Compressed == false)
+ {
+ // Uncompressed
+ TubeSendEx(t, b->Buf, b->Size, &h, true);
+
+ s->TotalSendSize += b->Size;
+ s->TotalSendSizeReal += b->Size;
+
+ c->CurrentSendQueueSize -= b->Size;
+ }
+ else
+ {
+ // Compressed
+ UCHAR *new_buf = Malloc(b->Size + sizeof(UINT64));
+
+ WRITE_UINT64(new_buf, CONNECTION_BULK_COMPRESS_SIGNATURE);
+
+ Copy(new_buf + sizeof(UINT64), b->Buf, b->Size);
+
+ TubeSendEx(t, new_buf, b->Size + sizeof(UINT64), &h, true);
+
+ s->TotalSendSize += b->SizeofData;
+ s->TotalSendSizeReal += b->Size;
+
+ c->CurrentSendQueueSize -= b->Size;
+ }
+
+ FreeBlock(b);
+
+ flush = true;
+ }
+
+ if (flush)
+ {
+ TubeFlush(t);
+ }
+ }
+ else
+ {
+ // TCP/IP socket
+ bool update_keepalive_timer = false;
+ // Number of data
+ num_data = Endian32(q->num_item);
+ PROBE_DATA2("WriteSendFifo num", &num_data, sizeof(UINT));
+ WriteSendFifo(s, tss, &num_data, sizeof(UINT));
+
+ s->TotalSendSize += sizeof(UINT);
+ s->TotalSendSizeReal += sizeof(UINT);
+
+ while (b = GetNext(q))
+ {
+ // Size data
+ UINT size_data;
+ size_data = Endian32(b->Size);
+ PROBE_DATA2("WriteSendFifo size", &size_data, sizeof(UINT));
+ WriteSendFifo(s, tss, &size_data, sizeof(UINT));
+
+ c->CurrentSendQueueSize -= b->Size;
+
+ s->TotalSendSize += sizeof(UINT);
+ s->TotalSendSizeReal += sizeof(UINT);
+
+ // Data body
+ PROBE_DATA2("WriteSendFifo data", b->Buf, b->Size);
+ WriteSendFifo(s, tss, b->Buf, b->Size);
+
+ s->TotalSendSize += b->SizeofData;
+ s->TotalSendSizeReal += b->Size;
+
+ update_keepalive_timer = true;
+
+ // Block release
+ FreeBlock(b);
+ }
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL && UdpAccelIsSendReady(s->UdpAccel, false))
+ {
+ update_keepalive_timer = false;
+ }
+
+ if (update_keepalive_timer)
+ {
+ // Increase the KeepAlive timer
+ tss->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
+ }
+ }
+ }
+ else
+ {
+ bool flush = false;
+ // In-process socket
+ while (b = GetNext(q))
+ {
+ TubeSendEx(ts->Sock->SendTube, b->Buf, b->Size, NULL, true);
+ flush = true;
+
+ s->TotalSendSize += b->Size;
+ s->TotalSendSizeReal += b->Size;
+
+ c->CurrentSendQueueSize -= b->Size;
+
+ FreeBlock(b);
+ }
+
+ if (flush)
+ {
+ TubeFlush(ts->Sock->SendTube);
+ }
+ }
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ }
+
+ // Send the reserved data to send registered in each socket now
+ if (c->IsInProc == false)
+ {
+ for (i = 0;i < num;i++)
+ {
+ ts = tcpsocks[i];
+
+SEND_START:
+ if (ts->Sock->Connected == false)
+ {
+ s->LastTryAddConnectTime = Tick64();
+ // Communication is disconnected
+ LockList(tcp->TcpSockList);
+ {
+ // Remove the socket from socket list
+ Delete(tcp->TcpSockList, ts);
+ // Release of TCPSOCK
+ FreeTcpSock(ts);
+ // Decrement the count
+ Dec(c->CurrentNumConnection);
+ Debug("--- TCP Connection Decremented: %u (%s Line %u)\n", Count(c->CurrentNumConnection), __FILE__, __LINE__);
+ Debug("LIST_NUM(tcp->TcpSockList): %u\n", LIST_NUM(tcp->TcpSockList));
+ }
+ UnlockList(tcp->TcpSockList);
+
+ continue;
+ }
+
+ // Get Fifo size
+ if (ts->SendFifo->size != 0)
+ {
+ UCHAR *buf;
+ UINT want_send_size;
+ // Send only if the data to send exists by 1 byte or more
+ // Get the pointer to the buffer
+ buf = (UCHAR *)ts->SendFifo->p + ts->SendFifo->pos;
+ want_send_size = ts->SendFifo->size;
+
+ PROBE_DATA2("TcpSockSend", buf, want_send_size);
+ size = TcpSockSend(s, ts, buf, want_send_size);
+
+ if (size == 0)
+ {
+ // Disconnected
+ continue;
+ }
+ else if (size == SOCK_LATER)
+ {
+ // Packet is jammed
+ ts->LateCount++; // Increment of the delay counter
+ PROBE_STR("ts->LateCount++;");
+ }
+ else
+ {
+ // Packet is sent only by 'size'
+ // Advance FIFO
+ ReadFifo(ts->SendFifo, NULL, size);
+ if (size < want_send_size)
+ {
+ // Fail to transmit all of the data that has been scheduled
+#ifdef USE_PROBE
+ {
+ char tmp[MAX_SIZE];
+
+ snprintf(tmp, sizeof(tmp), "size < want_send_size: %u < %u",
+ size, want_send_size);
+
+ PROBE_STR(tmp);
+ }
+#endif // USE_PROBE
+ }
+ else
+ {
+ // Because sending all the packets is completed
+ // (The queue is exhausted), reset the delay counter
+ ts->LateCount = 0;
+
+ PROBE_STR("TcpSockSend All Completed");
+ }
+ // Updated the last communication date and time
+ c->Session->LastCommTime = now;
+
+ goto SEND_START;
+ }
+ }
+ }
+ }
+
+ Free(tcpsocks);
+ }
+ else if (c->Protocol == CONNECTION_UDP)
+ {
+ // UDP
+ UDP *udp = c->Udp;
+ SOCK *sock = NULL;
+
+ Lock(c->lock);
+ {
+ sock = udp->s;
+ if (sock != NULL)
+ {
+ AddRef(sock->ref);
+ }
+ }
+ Unlock(c->lock);
+
+ if (sock != NULL)
+ {
+ // Send with UDP
+
+ // KeepAlive sending
+ if ((udp->NextKeepAliveTime == 0 || udp->NextKeepAliveTime <= now) ||
+ (c->SendBlocks->num_item != 0) || (udp->BufferQueue->num_item != 0))
+ {
+ // Send the current queue with UDP
+ SendDataWithUDP(sock, c);
+ }
+ }
+
+ if (sock != NULL)
+ {
+ ReleaseSock(sock);
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)
+ {
+ // SecureNAT session
+ SNAT *snat = s->SecureNAT;
+ VH *v = snat->Nat->Virtual;
+
+ LockQueue(c->SendBlocks);
+ {
+ BLOCK *block;
+ UINT num_packet = 0;
+
+ if (hub != NULL)
+ {
+ NatSetHubOption(v, hub->Option);
+ }
+
+ while (block = GetNext(c->SendBlocks))
+ {
+ num_packet++;
+ c->CurrentSendQueueSize -= block->Size;
+ VirtualPutPacket(v, block->Buf, block->Size);
+ Free(block);
+ }
+
+ if (num_packet != 0)
+ {
+ VirtualPutPacket(v, NULL, 0);
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ else if (c->Protocol == CONNECTION_HUB_LAYER3)
+ {
+ // Layer-3 session
+ L3IF *f = s->L3If;
+
+ LockQueue(c->SendBlocks);
+ {
+ BLOCK *block;
+ UINT num_packet = 0;
+
+ while (block = GetNext(c->SendBlocks))
+ {
+ num_packet++;
+ c->CurrentSendQueueSize -= block->Size;
+ L3PutPacket(f, block->Buf, block->Size);
+ Free(block);
+ }
+
+ if (num_packet != 0)
+ {
+ L3PutPacket(f, NULL, 0);
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)
+ {
+ // HUB Link
+ LINK *k = (LINK *)s->Link;
+
+ if (k != NULL)
+ {
+ LockQueue(c->SendBlocks);
+ {
+ UINT num_blocks = 0;
+ LockQueue(k->SendPacketQueue);
+ {
+ BLOCK *block;
+
+ // Transfer the packet queue to the client thread
+ while (block = GetNext(c->SendBlocks))
+ {
+ num_blocks++;
+ c->CurrentSendQueueSize -= block->Size;
+ InsertQueue(k->SendPacketQueue, block);
+ }
+ }
+ UnlockQueue(k->SendPacketQueue);
+
+ if (num_blocks != 0)
+ {
+ // Issue of cancellation
+ Cancel(k->ClientSession->Cancel1);
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_BRIDGE)
+ {
+ // Local bridge
+ BRIDGE *b = s->Bridge;
+
+ if (b != NULL)
+ {
+ if (b->Active)
+ {
+ LockQueue(c->SendBlocks);
+ {
+ BLOCK *block;
+ UINT num_packet = c->SendBlocks->num_item; // Packet count
+
+ if (num_packet != 0)
+ {
+ // Packet data array
+ void **datas = MallocFast(sizeof(void *) * num_packet);
+ UINT *sizes = MallocFast(sizeof(UINT *) * num_packet);
+ UINT i;
+
+ i = 0;
+ while (block = GetNext(c->SendBlocks))
+ {
+ if (hub != NULL && hub->Option != NULL && hub->Option->DisableUdpFilterForLocalBridgeNic == false &&
+ b->Eth != NULL && IsDhcpPacketForSpecificMac(block->Buf, block->Size, b->Eth->MacAddress))
+ {
+ // DHCP Packet is filtered
+ datas[i] = NULL;
+ sizes[i] = 0;
+
+ Free(block->Buf);
+ }
+ else
+ {
+ datas[i] = block->Buf;
+ sizes[i] = block->Size;
+
+ if (block->Size > 1514)
+ {
+ NormalizeEthMtu(b, c, block->Size);
+ }
+ }
+
+ c->CurrentSendQueueSize -= block->Size;
+ Free(block);
+ i++;
+ }
+
+ // Write the packet
+ EthPutPackets(b->Eth, num_packet, datas, sizes);
+
+ Free(datas);
+ Free(sizes);
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ }
+ }
+}
+
+// Reception of the block
+void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
+{
+ UINT i, num;
+ SOCKSET set;
+ SESSION *s;
+ TCPSOCK **tcpsocks;
+ UCHAR *buf;
+ UINT size;
+ UINT64 now;
+ UINT time;
+ UINT num_delayed = 0;
+ bool no_spinlock_for_delay = false;
+ HUB *hub = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ PROBE_STR("ConnectionReceive");
+
+ s = c->Session;
+
+ if (s != NULL)
+ {
+ hub = s->Hub;
+ }
+
+ if (hub != NULL)
+ {
+ no_spinlock_for_delay = hub->Option->NoSpinLockForPacketDelay;
+ }
+
+ now = Tick64();
+
+ if (c->RecvBuf == NULL)
+ {
+ c->RecvBuf = Malloc(RECV_BUF_SIZE);
+ }
+ buf = c->RecvBuf;
+
+ // Protocol
+ if (c->Protocol == CONNECTION_TCP)
+ {
+ // TCP
+ TCP *tcp = c->Tcp;
+ UINT next_delay_packet_diff = 0;
+
+ // Disconnect if disconnection interval is specified
+ if (s->ServerMode == false)
+ {
+ if (s->ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ LockList(tcp->TcpSockList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(tcp->TcpSockList);i++)
+ {
+ TCPSOCK *ts = LIST_DATA(tcp->TcpSockList, i);
+ if (ts->DisconnectTick != 0 &&
+ ts->DisconnectTick <= now)
+ {
+ Debug("ts->DisconnectTick <= now\n");
+ Disconnect(ts->Sock);
+ }
+ }
+ }
+ UnlockList(tcp->TcpSockList);
+ }
+ }
+
+ if (s->HalfConnection && (s->ServerMode == false))
+ {
+ // Check the direction of the current TCP connections.
+ // Disconnect one if the number of connections reaches
+ // the limit and has only one direction
+ LockList(tcp->TcpSockList);
+ {
+ UINT i, num;
+ UINT c2s, s2c;
+ c2s = s2c = 0;
+ num = LIST_NUM(tcp->TcpSockList);
+ if (num >= s->MaxConnection)
+ {
+ TCPSOCK *ts;
+ for (i = 0;i < num;i++)
+ {
+ ts = LIST_DATA(tcp->TcpSockList, i);
+ if (ts->Direction == TCP_SERVER_TO_CLIENT)
+ {
+ s2c++;
+ }
+ else
+ {
+ c2s++;
+ }
+ }
+ if (s2c == 0 || c2s == 0)
+ {
+ // Disconnect the last socket
+ Disconnect(ts->Sock);
+ Debug("Disconnect (s2c=%u, c2s=%u)\n", s2c, c2s);
+ }
+ }
+ }
+ UnlockList(tcp->TcpSockList);
+ }
+
+ // Initializing the socket set
+ InitSockSet(&set);
+ LockList(tcp->TcpSockList);
+ {
+ num = LIST_NUM(tcp->TcpSockList);
+ tcpsocks = ToArrayEx(tcp->TcpSockList, true);
+ }
+ UnlockList(tcp->TcpSockList);
+
+ for (i = 0;i < num;i++)
+ {
+ AddSockSet(&set, tcpsocks[i]->Sock);
+ }
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ if (s->UdpAccel->UdpSock != NULL)
+ {
+ AddSockSet(&set, s->UdpAccel->UdpSock);
+ }
+ }
+
+ // Select
+ time = SELECT_TIME;
+ if (s->VirtualHost)
+ {
+ time = MIN(time, SELECT_TIME_FOR_NAT);
+ }
+ next_delay_packet_diff = GetNextDelayedPacketTickDiff(s);
+ time = MIN(time, next_delay_packet_diff);
+ num_delayed = LIST_NUM(s->DelayedPacketList);
+
+ PROBE_STR("ConnectionReceive: Select 0");
+
+ if (s->Flag1 != set.NumSocket)
+ {
+ Select(&set, (num_delayed == 0 ? time : 1), c1, c2);
+ s->Flag1 = set.NumSocket;
+ }
+ else
+ {
+ if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
+ {
+ Select(&set, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
+ s->Flag1 = set.NumSocket;
+ }
+ else
+ {
+ YieldCpu();
+ }
+ }
+
+ PROBE_STR("ConnectionReceive: Select 1");
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ // Read the data received by the UDP If using the UDP acceleration mode
+ UdpAccelSetTick(s->UdpAccel, now);
+ UdpAccelPoll(s->UdpAccel);
+
+ if (s->UdpAccelMss == 0)
+ {
+ s->UdpAccelMss = UdpAccelCalcMss(s->UdpAccel);
+ }
+
+ while (true)
+ {
+ BLOCK *b = GetNext(s->UdpAccel->RecvBlockQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ if (b->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(b);
+ }
+ else
+ {
+ // Add the data block to queue
+ InsertReveicedBlockToQueue(c, b);
+ }
+ }
+ }
+
+ {
+ bool new_status = UdpAccelIsSendReady(s->UdpAccel, true);
+
+ if (s->IsUsingUdpAcceleration != new_status)
+ {
+ Debug("UDP Status Changed: %u\n", new_status);
+ }
+
+ s->IsUsingUdpAcceleration = new_status;
+ }
+
+ // Read all the data that has arrived to the TCP socket
+ for (i = 0;i < num;i++)
+ {
+ TCPSOCK *ts = tcpsocks[i];
+ SOCK *sock = ts->Sock;
+
+ if (s->IsRUDPSession)
+ {
+ TUBE *t = sock->BulkRecvTube;
+
+ if (s->EnableBulkOnRUDP)
+ {
+ // R-UDP bulk transfer data reception
+ if (t != NULL && IsTubeConnected(t))
+ {
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(t);
+ BLOCK *block;
+ if (d == NULL)
+ {
+ // All reception complete
+ break;
+ }
+
+ if (d->DataSize > sizeof(UINT64) && READ_UINT64(d->Data) == CONNECTION_BULK_COMPRESS_SIGNATURE)
+ {
+ // Compression
+ block = NewBlock(Clone(((UCHAR *)d->Data) + sizeof(UINT64),
+ d->DataSize - sizeof(UINT64)),
+ d->DataSize - sizeof(UINT64),
+ -1);
+ }
+ else
+ {
+ // Uncompressed
+ block = NewBlock(Clone(d->Data, d->DataSize), d->DataSize, 0);
+ }
+
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(block);
+ }
+ else
+ {
+ // Add the data block to queue
+ InsertReveicedBlockToQueue(c, block);
+ }
+
+ FreeTubeData(d);
+
+ ts->LastCommTime = now;
+ ts->LastRecvTime = now;
+ c->Session->LastCommTime = now;
+ }
+ }
+ }
+ }
+
+ if (c->IsInProc)
+ {
+ TUBEDATA *d;
+ // Socket for in-process connection
+ if (IsTubeConnected(sock->RecvTube) == false)
+ {
+ // Communication is disconnected
+ goto DISCONNECT_THIS_TCP;
+ }
+
+ while (true)
+ {
+ BLOCK *block;
+ // Get the packet data from the tube
+ d = TubeRecvAsync(sock->RecvTube);
+ if (d == NULL)
+ {
+ // All acquisition completed
+ break;
+ }
+
+ block = NewBlock(Clone(d->Data, d->DataSize), d->DataSize, 0);
+
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(block);
+ }
+ else
+ {
+ // Add the data block to queue
+ InsertReveicedBlockToQueue(c, block);
+ }
+
+ FreeTubeData(d);
+ }
+
+ c->Session->LastCommTime = now;
+ }
+ else
+ {
+ // A normal socket (Not in-process)
+ if (ts->WantSize == 0)
+ {
+ // Read for sizeof(UINT) first
+ ts->WantSize = sizeof(UINT);
+ }
+
+RECV_START:
+ // Receive
+ size = TcpSockRecv(s, ts, buf, RECV_BUF_SIZE);
+/*
+ // Experiment
+ if (c->ServerMode)
+ {
+ if ((ts->EstablishedTick + (UINT64)3000) <= now)
+ {
+ size = 0;
+ WHERE;
+ }
+ }*/
+
+ if (size == 0)
+ {
+DISCONNECT_THIS_TCP:
+ s->LastTryAddConnectTime = Tick64();
+ s->NumDisconnected++;
+ // Communication is disconnected
+ LockList(tcp->TcpSockList);
+ {
+ // Remove the socket from socket list
+ Delete(tcp->TcpSockList, ts);
+ // Release of TCPSOCK
+ FreeTcpSock(ts);
+ // Decrement
+ Dec(c->CurrentNumConnection);
+ Debug("--- TCP Connection Decremented: %u (%s Line %u)\n", Count(c->CurrentNumConnection), __FILE__, __LINE__);
+ Debug("LIST_NUM(tcp->TcpSockList): %u\n", LIST_NUM(tcp->TcpSockList));
+ }
+ UnlockList(tcp->TcpSockList);
+
+ continue;
+ }
+ else if (size == SOCK_LATER)
+ {
+ // State of waiting reception : don't do anything
+ if (IS_RECV_TCP_SOCK(ts))
+ {
+ if ((now > ts->LastCommTime) && ((now - ts->LastCommTime) >= ((UINT64)s->Timeout)))
+ {
+ // The connection has timed out
+ Debug("Connection %u Timeouted.\n", i);
+ goto DISCONNECT_THIS_TCP;
+ }
+ }
+ }
+ else
+ {
+ // Update the last communication time
+ ts->LastCommTime = now;
+ c->Session->LastCommTime = now;
+ ts->LastRecvTime = now;
+
+ // Write the received data into the FIFO
+ PROBE_DATA2("WriteRecvFifo", buf, size);
+ WriteRecvFifo(s, ts, buf, size);
+
+ // Stop receiving when the receive buffer is full
+ if (ts->RecvFifo->size < MAX_SEND_SOCKET_QUEUE_SIZE)
+ {
+ goto RECV_START;
+ }
+ }
+
+ // process the data written to FIFO
+ while (ts->RecvFifo->size >= ts->WantSize)
+ {
+ UCHAR *buf;
+ void *data;
+ BLOCK *block;
+ UINT sz;
+ // A sufficient amount of data is already stored
+ // Get the pointer of the data
+ buf = (UCHAR *)ts->RecvFifo->p + ts->RecvFifo->pos;
+
+ switch (ts->Mode)
+ {
+ case 0:
+ // The number of Data blocks
+ ts->WantSize = sizeof(UINT);
+ Copy(&sz, buf, sizeof(UINT));
+ PROBE_DATA2("ReadFifo 0", buf, sizeof(UINT));
+ sz = Endian32(sz);
+ ts->NextBlockNum = sz;
+ ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
+
+ s->TotalRecvSize += sizeof(UINT);
+ s->TotalRecvSizeReal += sizeof(UINT);
+
+ ts->CurrentPacketNum = 0;
+ if (ts->NextBlockNum != 0)
+ {
+ if (ts->NextBlockNum == KEEP_ALIVE_MAGIC)
+ {
+ ts->Mode = 3;
+ }
+ else
+ {
+ ts->Mode = 1;
+ }
+ }
+ break;
+
+ case 1:
+ // Data block size
+ Copy(&sz, buf, sizeof(UINT));
+ sz = Endian32(sz);
+ PROBE_DATA2("ReadFifo 1", buf, sizeof(UINT));
+ if (sz > (MAX_PACKET_SIZE * 2))
+ {
+ // received a strange data size
+ // TCP/IP Error?
+ Debug("%s %u sz > (MAX_PACKET_SIZE * 2)\n", __FILE__, __LINE__);
+ Disconnect(ts->Sock);
+ }
+ ts->NextBlockSize = MIN(sz, MAX_PACKET_SIZE * 2);
+ ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
+
+ s->TotalRecvSize += sizeof(UINT);
+ s->TotalRecvSizeReal += sizeof(UINT);
+
+ ts->WantSize = ts->NextBlockSize;
+ if (ts->WantSize != 0)
+ {
+ ts->Mode = 2;
+ }
+ else
+ {
+ ts->Mode = 1;
+ ts->WantSize = sizeof(UINT);
+ ts->CurrentPacketNum++;
+ if (ts->CurrentPacketNum >= ts->NextBlockNum)
+ {
+ ts->Mode = 0;
+ }
+ }
+ break;
+
+ case 2:
+ // Data block body
+ ts->WantSize = sizeof(UINT);
+ ts->CurrentPacketNum++;
+ data = MallocFast(ts->NextBlockSize);
+ Copy(data, buf, ts->NextBlockSize);
+ PROBE_DATA2("ReadFifo 2", buf, ts->NextBlockSize);
+ ReadFifo(ts->RecvFifo, NULL, ts->NextBlockSize);
+ block = NewBlock(data, ts->NextBlockSize, s->UseCompress ? -1 : 0);
+
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(block);
+ }
+ else
+ {
+ // Add the data block to queue
+ InsertReveicedBlockToQueue(c, block);
+ }
+
+ if (ts->CurrentPacketNum >= ts->NextBlockNum)
+ {
+ // Reception of all the data blocks completed
+ ts->Mode = 0;
+ }
+ else
+ {
+ // Receive next data block size
+ ts->Mode = 1;
+ }
+ break;
+
+ case 3:
+ // Keep-Alive packet size
+ ts->Mode = 4;
+ Copy(&sz, buf, sizeof(UINT));
+ PROBE_DATA2("ReadFifo 3", buf, sizeof(UINT));
+ sz = Endian32(sz);
+ if (sz > MAX_KEEPALIVE_SIZE)
+ {
+ // received a strange data size
+ // TCP/IP Error?
+ Debug("%s %u sz > MAX_KEEPALIVE_SIZE\n", __FILE__, __LINE__);
+ Disconnect(ts->Sock);
+ }
+ ts->NextBlockSize = MIN(sz, MAX_KEEPALIVE_SIZE);
+ ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
+
+ s->TotalRecvSize += sizeof(UINT);
+ s->TotalRecvSizeReal += sizeof(UINT);
+
+ ts->WantSize = sz;
+ break;
+
+ case 4:
+ // Keep-Alive packet body
+ //Debug("KeepAlive Recved.\n");
+ ts->Mode = 0;
+ sz = ts->NextBlockSize;
+
+ if (sz >= (StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE) + sizeof(USHORT)))
+ {
+ UCHAR *keep_alive_buffer = FifoPtr(ts->RecvFifo);
+
+ if (Cmp(keep_alive_buffer, UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE, StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE)) == 0)
+ {
+ USHORT us = READ_USHORT(keep_alive_buffer + StrLen(UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE));
+
+ if (us != 0)
+ {
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ UINT port = (UINT)us;
+
+ if (s->UdpAccel->YourPortByNatTServer != port)
+ {
+ s->UdpAccel->YourPortByNatTServer = port;
+ s->UdpAccel->YourPortByNatTServerChanged = true;
+
+ Debug("s->UdpAccel->YourPortByNatTServer: %u\n",
+ s->UdpAccel->YourPortByNatTServer);
+ }
+ }
+ }
+ }
+ }
+
+ PROBE_DATA2("ReadFifo 4", NULL, 0);
+ ReadFifo(ts->RecvFifo, NULL, sz);
+
+ s->TotalRecvSize += sz;
+ s->TotalRecvSizeReal += sz;
+
+ ts->WantSize = sizeof(UINT);
+ break;
+ }
+ }
+ }
+ }
+
+ Free(tcpsocks);
+ }
+ else if (c->Protocol == CONNECTION_UDP)
+ {
+ // UDP
+ UDP *udp = c->Udp;
+ SOCK *sock = NULL;
+
+ if (s->ServerMode == false)
+ {
+ Lock(c->lock);
+ {
+ if (c->Udp->s != NULL)
+ {
+ sock = c->Udp->s;
+ if (sock != NULL)
+ {
+ AddRef(sock->ref);
+ }
+ }
+ }
+ Unlock(c->lock);
+
+ InitSockSet(&set);
+
+ if (sock != NULL)
+ {
+ AddSockSet(&set, sock);
+ }
+
+ Select(&set, SELECT_TIME, c1, c2);
+
+ if (sock != NULL)
+ {
+ IP ip;
+ UINT port;
+ UCHAR *buf;
+ UINT size;
+
+ while (true)
+ {
+ buf = c->RecvBuf;
+ size = RecvFrom(sock, &ip, &port, buf, RECV_BUF_SIZE);
+ if (size == 0 && sock->IgnoreRecvErr == false)
+ {
+ Debug("UDP Socket Disconnected.\n");
+ Lock(c->lock);
+ {
+ ReleaseSock(udp->s);
+ udp->s = NULL;
+ }
+ Unlock(c->lock);
+ break;
+ }
+ else if (size == SOCK_LATER)
+ {
+ break;
+ }
+ else
+ {
+ if (size)
+ {
+ PutUDPPacketData(c, buf, size);
+ }
+ }
+ }
+ }
+
+ if (sock != NULL)
+ {
+ Release(sock->ref);
+ }
+ }
+ else
+ {
+ Select(NULL, SELECT_TIME, c1, c2);
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)
+ {
+ SNAT *snat = c->Session->SecureNAT;
+ VH *v = snat->Nat->Virtual;
+ UINT size;
+ void *data;
+ UINT num;
+ UINT select_wait_time = SELECT_TIME_FOR_NAT;
+ UINT next_delay_packet_diff = 0;
+
+ if (snat->Nat != NULL && snat->Nat->Option.UseNat == false)
+ {
+ select_wait_time = SELECT_TIME;
+ }
+ else
+ {
+ if (snat->Nat != NULL)
+ {
+ LockList(v->NatTable);
+ {
+ if (LIST_NUM(v->NatTable) == 0 && LIST_NUM(v->ArpWaitTable) == 0)
+ {
+ select_wait_time = SELECT_TIME;
+ }
+ }
+ UnlockList(v->NatTable);
+ }
+ }
+
+ next_delay_packet_diff = GetNextDelayedPacketTickDiff(s);
+ select_wait_time = MIN(select_wait_time, next_delay_packet_diff);
+ num_delayed = LIST_NUM(s->DelayedPacketList);
+
+ if (no_spinlock_for_delay || select_wait_time >= 50 || num_delayed == false)
+ {
+ Select(NULL, (num_delayed == 0 ? select_wait_time :
+ (select_wait_time > 100 ? (select_wait_time - 100) : 1)), c1, c2);
+ }
+ else
+ {
+ YieldCpu();
+ }
+
+ num = 0;
+
+ if (hub != NULL)
+ {
+ NatSetHubOption(v, hub->Option);
+ }
+
+ // Receive a packet from the virtual machine
+ while (size = VirtualGetNextPacket(v, &data))
+ {
+ BLOCK *block;
+
+ // Generate packet block
+ block = NewBlock(data, size, 0);
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(block);
+ }
+ else
+ {
+ // Add the data block to queue
+ InsertReveicedBlockToQueue(c, block);
+ }
+ num++;
+ if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
+ {
+// WHERE;
+ break;
+ }
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)
+ {
+ // HUB Link
+ // Waiting Cancel simply
+ if (c->SendBlocks->num_item == 0)
+ {
+ UINT time = SELECT_TIME;
+ UINT next_delay_packet_diff = 0;
+
+ next_delay_packet_diff = GetNextDelayedPacketTickDiff(s);
+ time = MIN(time, next_delay_packet_diff);
+ num_delayed = LIST_NUM(s->DelayedPacketList);
+
+ if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
+ {
+ Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
+ }
+ else
+ {
+ YieldCpu();
+ }
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_LAYER3)
+ {
+ // Layer-3 switch session
+ L3IF *f = s->L3If;
+ UINT size, num = 0;
+ void *data;
+
+ if (f->SendQueue->num_item == 0)
+ {
+ UINT time = SELECT_TIME_FOR_NAT;
+ UINT next_delay_packet_diff = 0;
+
+ if (f->ArpWaitTable != NULL)
+ {
+ LockList(f->ArpWaitTable);
+ {
+ if (LIST_NUM(f->ArpWaitTable) == 0)
+ {
+ time = SELECT_TIME;
+ }
+ }
+ UnlockList(f->ArpWaitTable);
+ }
+
+ next_delay_packet_diff = GetNextDelayedPacketTickDiff(s);
+ time = MIN(time, next_delay_packet_diff);
+ num_delayed = LIST_NUM(s->DelayedPacketList);
+
+ if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
+ {
+ Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
+ }
+ else
+ {
+ YieldCpu();
+ }
+ }
+
+ // Get the next packet
+ while (size = L3GetNextPacket(f, &data))
+ {
+ BLOCK *block = NewBlock(data, size, 0);
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ FreeBlock(block);
+ }
+ else
+ {
+ InsertReveicedBlockToQueue(c, block);
+ }
+
+ num++;
+ if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
+ {
+ break;
+ }
+ }
+ }
+ else if (c->Protocol == CONNECTION_HUB_BRIDGE)
+ {
+ BRIDGE *b = c->Session->Bridge;
+
+ // Bridge session
+ if (b->Active)
+ {
+ void *data;
+ UINT ret;
+ UINT num = 0;
+ bool check_device_num = false;
+ UINT time = SELECT_TIME;
+ UINT next_delay_packet_diff = 0;
+
+ next_delay_packet_diff = GetNextDelayedPacketTickDiff(s);
+ time = MIN(time, next_delay_packet_diff);
+ num_delayed = LIST_NUM(s->DelayedPacketList);
+
+ // Bridge is operating
+ if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
+ {
+ Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
+ }
+ else
+ {
+ YieldCpu();
+ }
+
+ if ((b->LastNumDeviceCheck + BRIDGE_NUM_DEVICE_CHECK_SPAN) <= Tick64())
+ {
+ check_device_num = true;
+ b->LastNumDeviceCheck = Tick64();
+ }
+
+ // Get the next packet from the bridge
+ while (true)
+ {
+ if (check_device_num && b->LastNumDevice != GetEthDeviceHash())
+ {
+ ret = INFINITE;
+ }
+ else
+ {
+ ret = EthGetPacket(b->Eth, &data);
+ }
+
+#ifdef OS_WIN32
+ if (c->Session != NULL)
+ {
+ c->Session->BridgeIsEthLoopbackBlock = false;
+ if (b->Eth != NULL && b->Eth->LoopbackBlock)
+ {
+ // Check whether The Ethernet device in the bridge
+ // has the ability to block the loopback packet
+ c->Session->BridgeIsEthLoopbackBlock = true;
+ }
+ }
+#endif // OS_WIN32
+
+ if (ret == INFINITE)
+ {
+ // Error occured: stop the bridge
+ CloseEth(b->Eth);
+ b->Eth = NULL;
+ b->Active = false;
+ ReleaseCancel(s->Cancel2);
+ s->Cancel2 = NULL;
+
+ HLog(s->Hub, "LH_BRIDGE_2", s->Name, b->Name);
+ Debug("Bridge Device Error.\n");
+
+ break;
+ }
+ else if (ret == 0)
+ {
+ // There is no more packet to receive
+ break;
+ }
+ else
+ {
+ if (hub != NULL && hub->Option != NULL && hub->Option->DisableUdpFilterForLocalBridgeNic == false &&
+ b->Eth != NULL && IsDhcpPacketForSpecificMac(data, ret, b->Eth->MacAddress))
+ {
+ // DHCP Packet is filtered.
+ Free(data);
+ }
+ else
+ {
+ // Add the packet to queue
+ BLOCK *block = NewBlock(data, ret, 0);
+
+ PROBE_DATA2("ConnectionReceive: NewBlock", data, ret);
+
+ if (ret > 1514)
+ {
+ NormalizeEthMtu(b, c, ret);
+ }
+
+ if (block->Size > MAX_PACKET_SIZE)
+ {
+ // Packet size exceeded
+ FreeBlock(block);
+ }
+ else
+ {
+ InsertReveicedBlockToQueue(c, block);
+ }
+ num++;
+ if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
+ {
+ // WHERE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ETH *e;
+ // Bridge is stopped cureently
+ Select(NULL, SELECT_TIME, c1, NULL);
+
+ if (b->LastBridgeTry == 0 || (b->LastBridgeTry + BRIDGE_TRY_SPAN) <= Tick64())
+ {
+ b->LastBridgeTry = Tick64();
+
+ // Try to open an Ethernet device
+ e = OpenEth(b->Name, b->Local, b->TapMode, b->TapMacAddress);
+ if (e != NULL)
+ {
+ // Success
+ b->Eth = e;
+ b->Active = true;
+ b->LastNumDeviceCheck = Tick64();
+ b->LastNumDevice = GetEthDeviceHash();
+
+ // Update the NIC name of the bridge
+#ifdef OS_WIN32
+ if (IsEmptyStr(e->Title) == false)
+ {
+ StrCpy(b->Name, sizeof(b->Name), e->Title);
+
+ if (b->ParentLocalBridge != NULL)
+ {
+ StrCpy(b->ParentLocalBridge->DeviceName, sizeof(b->ParentLocalBridge->DeviceName), e->Title);
+ }
+ }
+#endif // OS_WIN32
+
+ Debug("Bridge Open Succeed.\n");
+
+ HLog(c->Session->Hub, "LH_BRIDGE_1", c->Session->Name, b->Name);
+
+ s->Cancel2 = EthGetCancel(b->Eth);
+ }
+ }
+ }
+ }
+}
+
+// Normalize the MTU of the Ethernet device
+void NormalizeEthMtu(BRIDGE *b, CONNECTION *c, UINT packet_size)
+{
+ // Validate arguments
+ if (packet_size == 0 || b == NULL || c == NULL)
+ {
+ return;
+ }
+
+ // Raise the MTU when the packet exceeds the current MTU
+ if (EthIsChangeMtuSupported(b->Eth))
+ {
+ UINT currentMtu = EthGetMtu(b->Eth);
+ if (currentMtu != 0)
+ {
+ if (packet_size > currentMtu)
+ {
+ bool ok = EthSetMtu(b->Eth, packet_size);
+
+ if (ok)
+ {
+ HLog(c->Session->Hub, "LH_SET_MTU", c->Session->Name,
+ b->Name, currentMtu, packet_size, packet_size);
+ }
+ else
+ {
+ UINT64 now = Tick64();
+
+ if (b->LastChangeMtuError == 0 ||
+ now >= (b->LastChangeMtuError + 60000ULL))
+ {
+ HLog(c->Session->Hub, "LH_SET_MTU_ERROR", c->Session->Name,
+ b->Name, currentMtu, packet_size, packet_size);
+
+ b->LastChangeMtuError = now;
+ }
+ }
+ }
+ }
+ }
+}
+
+// Release of the block
+void FreeBlock(BLOCK *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Free(b->Buf);
+ Free(b);
+}
+
+// Create a new block
+BLOCK *NewBlock(void *data, UINT size, int compress)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ b = MallocFast(sizeof(BLOCK));
+
+ b->PriorityQoS = b->Ttl = b->Param1 = 0;
+
+ if (compress == 0)
+ {
+ // Uncompressed
+ b->Compressed = FALSE;
+ b->Buf = data;
+ b->Size = size;
+ b->SizeofData = size;
+ }
+ else if (compress == 1)
+ {
+ UINT max_size;
+
+ // Compressed
+ b->Compressed = TRUE;
+ max_size = CalcCompress(size);
+ b->Buf = MallocFast(max_size);
+ b->Size = Compress(b->Buf, max_size, data, size);
+ b->SizeofData = size;
+
+ // Discard old data block
+ Free(data);
+ }
+ else
+ {
+ // Expand
+ UINT max_size;
+
+ b->Compressed = FALSE;
+ max_size = MAX_PACKET_SIZE;
+ b->Buf = MallocFast(max_size);
+ b->Size = Uncompress(b->Buf, max_size, data, size);
+ b->SizeofData = size;
+
+ // Discard old data
+ Free(data);
+ }
+
+ return b;
+}
+
+// Create a TCP socket
+TCPSOCK *NewTcpSock(SOCK *s)
+{
+ TCPSOCK *ts;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ ts = ZeroMalloc(sizeof(TCPSOCK));
+
+ ts->Sock = s;
+ AddRef(s->ref);
+
+ ts->RecvFifo = NewFifo();
+ ts->SendFifo = NewFifo();
+ ts->EstablishedTick = ts->LastRecvTime = ts->LastCommTime = Tick64();
+
+ // Unset the time-out value
+ SetTimeout(s, TIMEOUT_INFINITE);
+
+ return ts;
+}
+
+// Set a encryption key for the TCP socket
+void InitTcpSockRc4Key(TCPSOCK *ts, bool server_mode)
+{
+ RC4_KEY_PAIR *pair;
+ CRYPT *c1, *c2;
+ // Validate arguments
+ if (ts == NULL)
+ {
+ return;
+ }
+
+ pair = &ts->Rc4KeyPair;
+
+ c1 = NewCrypt(pair->ClientToServerKey, sizeof(pair->ClientToServerKey));
+ c2 = NewCrypt(pair->ServerToClientKey, sizeof(pair->ServerToClientKey));
+
+ if (server_mode)
+ {
+ ts->RecvKey = c1;
+ ts->SendKey = c2;
+ }
+ else
+ {
+ ts->SendKey = c1;
+ ts->RecvKey = c2;
+ }
+}
+
+// Release of TCP socket
+void FreeTcpSock(TCPSOCK *ts)
+{
+ // Validate arguments
+ if (ts == NULL)
+ {
+ return;
+ }
+
+ Disconnect(ts->Sock);
+ ReleaseSock(ts->Sock);
+ ReleaseFifo(ts->RecvFifo);
+ ReleaseFifo(ts->SendFifo);
+
+ if (ts->SendKey)
+ {
+ FreeCrypt(ts->SendKey);
+ }
+ if (ts->RecvKey)
+ {
+ FreeCrypt(ts->RecvKey);
+ }
+
+ Free(ts);
+}
+
+// Exit the tunneling mode of connection
+void EndTunnelingMode(CONNECTION *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Protocol
+ if (c->Protocol == CONNECTION_TCP)
+ {
+ // TCP
+ DisconnectTcpSockets(c);
+ }
+ else
+ {
+ // UDP
+ DisconnectUDPSockets(c);
+ }
+}
+
+// Shift the connection to tunneling mode
+void StartTunnelingMode(CONNECTION *c)
+{
+ SOCK *s;
+ TCP *tcp;
+ TCPSOCK *ts;
+ IP ip;
+ UINT port;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ tcp = c->Tcp;
+
+ // Protocol
+ if (c->Protocol == CONNECTION_TCP)
+ {
+ // TCP
+ s = c->FirstSock;
+
+ if (c->IsInProc)
+ {
+ AddRef(s->ref);
+ c->TubeSock = s;
+ }
+
+ ts = NewTcpSock(s);
+
+ if (c->ServerMode == false)
+ {
+ if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
+ }
+ }
+
+ LockList(tcp->TcpSockList);
+ {
+ Add(tcp->TcpSockList, ts);
+ }
+ UnlockList(tcp->TcpSockList);
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ }
+ else
+ {
+ // UDP
+ s = c->FirstSock;
+ Copy(&ip, &s->RemoteIP, sizeof(IP));
+ // May disconnect TCP connection at this point
+ c->FirstSock = NULL;
+ Disconnect(s);
+ ReleaseSock(s);
+
+ // Initialization of UDP structure
+ c->Udp = ZeroMalloc(sizeof(UDP));
+
+ if (c->ServerMode)
+ {
+ // Server mode
+ // Add an UDP Entry
+ AddUDPEntry(c->Cedar, c->Session);
+ c->Udp->s = NULL;
+ }
+ else
+ {
+ port = c->Session->ClientOption->PortUDP;
+ // Client mode
+ c->Udp->s = NewUDP(0);
+ // Write the IP address and port number
+ Copy(&c->Udp->ip, &ip, sizeof(IP));
+ c->Udp->port = port;
+ }
+
+ // Queue
+ c->Udp->BufferQueue = NewQueue();
+ }
+}
+
+// Generate a random value that depends on each machine
+UINT GetMachineRand()
+{
+ char pcname[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+
+ Zero(pcname, sizeof(pcname));
+ GetMachineName(pcname, sizeof(pcname));
+
+ HashSha1(hash, pcname, StrLen(pcname));
+
+ return READ_UINT(hash);
+}
+
+// Function that accepts a new connection
+void ConnectionAccept(CONNECTION *c)
+{
+ SOCK *s;
+ X *x;
+ K *k;
+ char tmp[128];
+ UCHAR openssl_check_buf[2];
+ char *error_details = NULL;
+ SERVER *server;
+ UCHAR *peek_buf = NULL;
+ UINT peek_buf_size = 1500;
+ char sni[128] = {0};
+ bool native1 = false; // Non-SNI flag
+ bool native2 = false; // Non-TLS flag
+ bool native3 = false; // SSLv2 flag
+ bool no_native = false;
+ UINT peek_size = 0;
+ UINT initial_timeout = CONNECTING_TIMEOUT;
+ bool no_peek_log = false;
+ UCHAR ctoken_hash[SHA1_SIZE];
+ bool no_write_ctoken_log = false;
+
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Zero(ctoken_hash, sizeof(ctoken_hash));
+
+ peek_buf = ZeroMalloc(peek_buf_size);
+
+ Debug("ConnectionAccept()\n");
+
+ server = c->Cedar->Server;
+
+ // get a socket
+ s = c->FirstSock;
+ AddRef(s->ref);
+
+ Dec(c->Cedar->AcceptingSockets);
+
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+
+ SLog(c->Cedar, "LS_CONNECTION_START_1", tmp, s->RemoteHostname, (IS_SPECIAL_PORT(s->RemotePort) ? 0 : s->RemotePort), c->Name);
+
+ // Timeout setting
+ initial_timeout += GetMachineRand() % (CONNECTING_TIMEOUT / 2);
+ SetTimeout(s, initial_timeout);
+
+
+ // Peek whether OpenSSL packet
+ if (s->IsReverseAcceptedSocket == false)
+ {
+ if (s->Type == SOCK_TCP && (c->Cedar != NULL && c->Cedar->Server != NULL && c->Cedar->Server->DisableOpenVPNServer == false))
+ {
+ if (Peek(s, openssl_check_buf, sizeof(openssl_check_buf)) == sizeof(openssl_check_buf))
+ {
+ if (OvsCheckTcpRecvBufIfOpenVPNProtocol(openssl_check_buf, sizeof(openssl_check_buf)))
+ {
+ // Detect OpenSSL packet
+ Debug("Detect OpenSSL on TCP!\n");
+
+ no_native = true;
+
+ if (OvsGetNoOpenVpnTcp() == false)
+ {
+ // Do OpenSSL processing
+ c->Type = CONNECTION_TYPE_OPENVPN;
+ if (OvsPerformTcpServer(c->Cedar, s) == false)
+ {
+ error_details = "OpenVPN_TCP_Aborted";
+ }
+ }
+
+ goto ERROR;
+ }
+ }
+ }
+
+
+ }
+
+ // Specify the encryption algorithm
+ Lock(c->Cedar->lock);
+ {
+ if (c->Cedar->CipherList != NULL)
+ {
+ SetWantToUseCipher(s, c->Cedar->CipherList);
+ }
+
+ x = CloneX(c->Cedar->ServerX);
+ k = CloneK(c->Cedar->ServerK);
+ }
+ Unlock(c->Cedar->lock);
+
+ // Start the SSL communication
+ Debug("StartSSL()\n");
+ if (StartSSL(s, x, k) == false)
+ {
+ // Failed
+ AddNoSsl(c->Cedar, &s->RemoteIP);
+ Debug("Failed to StartSSL.\n");
+ FreeX(x);
+ FreeK(k);
+
+ error_details = "StartSSL";
+
+ goto ERROR;
+ }
+
+ FreeX(x);
+ FreeK(k);
+
+ SLog(c->Cedar, "LS_SSL_START", c->Name, s->CipherName);
+
+ Copy(c->CToken_Hash, ctoken_hash, SHA1_SIZE);
+
+ // Accept the connection
+ if (ServerAccept(c) == false)
+ {
+ // Failed
+ Debug("ServerAccept Failed. Err = %u\n", c->Err);
+ goto ERROR;
+ }
+
+ if (c->flag1 == false)
+ {
+ Debug("%s %u c->flag1 == false\n", __FILE__, __LINE__);
+ Disconnect(s);
+ }
+ DelConnection(c->Cedar, c);
+ ReleaseSock(s);
+
+ Free(peek_buf);
+ return;
+
+ERROR:
+ Debug("ConnectionAccept() Error.\n");
+
+
+ Disconnect(s);
+ DelConnection(c->Cedar, c);
+ ReleaseSock(s);
+ Free(peek_buf);
+}
+
+// Stop the threads putting additional connection of all that are currently running
+void StopAllAdditionalConnectThread(CONNECTION *c)
+{
+ UINT i, num;
+ SOCK **socks;
+ THREAD **threads;
+ // Validate arguments
+ if (c == NULL || c->ServerMode != false)
+ {
+ return;
+ }
+
+ // Disconnect the socket first
+ LockList(c->ConnectingSocks);
+ {
+ num = LIST_NUM(c->ConnectingSocks);
+ socks = ToArray(c->ConnectingSocks);
+ DeleteAll(c->ConnectingSocks);
+ }
+ UnlockList(c->ConnectingSocks);
+ for (i = 0;i < num;i++)
+ {
+ Disconnect(socks[i]);
+ ReleaseSock(socks[i]);
+ }
+ Free(socks);
+
+ // Then, wait for the suspension of the thread
+ LockList(c->ConnectingThreads);
+ {
+ num = LIST_NUM(c->ConnectingThreads);
+ Debug("c->ConnectingThreads: %u\n", num);
+ threads = ToArray(c->ConnectingThreads);
+ DeleteAll(c->ConnectingThreads);
+ }
+ UnlockList(c->ConnectingThreads);
+ for (i = 0;i < num;i++)
+ {
+ WaitThread(threads[i], INFINITE);
+ ReleaseThread(threads[i]);
+ }
+ Free(threads);
+}
+
+// Stop the connection
+void StopConnection(CONNECTION *c, bool no_wait)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Debug("Stop Connection: %s\n", c->Name);
+
+ // Stop flag
+ c->Halt = true;
+ Disconnect(c->FirstSock);
+
+ if (no_wait == false)
+ {
+ // Wait until the thread terminates
+ WaitThread(c->Thread, INFINITE);
+ }
+}
+
+// Close all the UDP socket
+void DisconnectUDPSockets(CONNECTION *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+ if (c->Protocol != CONNECTION_UDP)
+ {
+ return;
+ }
+
+ // Delete entry
+ if (c->ServerMode)
+ {
+ DelUDPEntry(c->Cedar, c->Session);
+ }
+
+ // Delete the UDP structure
+ if (c->Udp != NULL)
+ {
+ if (c->Udp->s != NULL)
+ {
+ ReleaseSock(c->Udp->s);
+ }
+ if (c->Udp->BufferQueue != NULL)
+ {
+ // Release of the queue
+ BUF *b;
+ while (b = GetNext(c->Udp->BufferQueue))
+ {
+ FreeBuf(b);
+ }
+ ReleaseQueue(c->Udp->BufferQueue);
+ }
+ Free(c->Udp);
+ c->Udp = NULL;
+ }
+
+ if (c->FirstSock != NULL)
+ {
+ Disconnect(c->FirstSock);
+ ReleaseSock(c->FirstSock);
+ c->FirstSock = NULL;
+ }
+}
+
+// Close all TCP connections
+void DisconnectTcpSockets(CONNECTION *c)
+{
+ UINT i, num;
+ TCP *tcp;
+ TCPSOCK **tcpsocks;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+ if (c->Protocol != CONNECTION_TCP)
+ {
+ return;
+ }
+
+ tcp = c->Tcp;
+ LockList(tcp->TcpSockList);
+ {
+ tcpsocks = ToArray(tcp->TcpSockList);
+ num = LIST_NUM(tcp->TcpSockList);
+ DeleteAll(tcp->TcpSockList);
+ }
+ UnlockList(tcp->TcpSockList);
+
+ if (num != 0)
+ {
+ Debug("--- SOCKET STATUS ---\n");
+ for (i = 0;i < num;i++)
+ {
+ TCPSOCK *ts = tcpsocks[i];
+ Debug(" SOCK %2u: %u\n", i, ts->Sock->SendSize);
+ FreeTcpSock(ts);
+ }
+ }
+
+ Free(tcpsocks);
+}
+
+// Clean up of the connection
+void CleanupConnection(CONNECTION *c)
+{
+ UINT i, num;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(c->lock);
+ ReleaseCedar(c->Cedar);
+
+ switch (c->Protocol)
+ {
+ case CONNECTION_TCP:
+ // Release of TCP connection list
+ DisconnectTcpSockets(c);
+ break;
+
+ case CONNECTION_UDP:
+ break;
+ }
+
+ ReleaseList(c->Tcp->TcpSockList);
+ Free(c->Tcp);
+
+ ReleaseSock(c->FirstSock);
+ c->FirstSock = NULL;
+
+ ReleaseSock(c->TubeSock);
+ c->TubeSock = NULL;
+
+ ReleaseThread(c->Thread);
+ Free(c->Name);
+
+ // Release all the receive block and send block
+ if (c->SendBlocks)
+ {
+ LockQueue(c->SendBlocks);
+ {
+ BLOCK *b;
+ while (b = GetNext(c->SendBlocks))
+ {
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+ }
+ if (c->SendBlocks2)
+ {
+ LockQueue(c->SendBlocks2);
+ {
+ BLOCK *b;
+ while (b = GetNext(c->SendBlocks2))
+ {
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(c->SendBlocks2);
+ }
+ if (c->ReceivedBlocks)
+ {
+ LockQueue(c->ReceivedBlocks);
+ {
+ BLOCK *b;
+ while (b = GetNext(c->ReceivedBlocks))
+ {
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(c->ReceivedBlocks);
+ }
+
+ if (c->ConnectingThreads)
+ {
+ THREAD **threads;
+ LockList(c->ConnectingThreads);
+ {
+ num = LIST_NUM(c->ConnectingThreads);
+ threads = ToArray(c->ConnectingThreads);
+ for (i = 0;i < num;i++)
+ {
+ ReleaseThread(threads[i]);
+ }
+ Free(threads);
+ }
+ UnlockList(c->ConnectingThreads);
+ ReleaseList(c->ConnectingThreads);
+ }
+
+ if (c->ConnectingSocks)
+ {
+ SOCK **socks;
+ LockList(c->ConnectingSocks);
+ {
+ num = LIST_NUM(c->ConnectingSocks);
+ socks = ToArray(c->ConnectingSocks);
+ for (i = 0;i < num;i++)
+ {
+ Disconnect(socks[i]);
+ ReleaseSock(socks[i]);
+ }
+ Free(socks);
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseList(c->ConnectingSocks);
+ }
+
+ if (c->RecvBuf)
+ {
+ Free(c->RecvBuf);
+ }
+
+ if (c->ServerX != NULL)
+ {
+ FreeX(c->ServerX);
+ }
+
+ if (c->ClientX != NULL)
+ {
+ FreeX(c->ClientX);
+ }
+
+ ReleaseQueue(c->ReceivedBlocks);
+ ReleaseQueue(c->SendBlocks);
+ ReleaseQueue(c->SendBlocks2);
+
+ DeleteCounter(c->CurrentNumConnection);
+
+ if (c->CipherName != NULL)
+ {
+ Free(c->CipherName);
+ }
+
+ Free(c);
+}
+
+// Release of the connection
+void ReleaseConnection(CONNECTION *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ CleanupConnection(c);
+ }
+}
+
+// Comparison of connection
+int CompareConnection(void *p1, void *p2)
+{
+ CONNECTION *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(CONNECTION **)p1;
+ c2 = *(CONNECTION **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(c1->Name, c2->Name);
+}
+
+// Creating a server connection
+CONNECTION *NewServerConnection(CEDAR *cedar, SOCK *s, THREAD *t)
+{
+ CONNECTION *c;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CONNECTION));
+ c->ConnectedTick = Tick64();
+ c->lock = NewLock();
+ c->ref = NewRef();
+ c->Cedar = cedar;
+ AddRef(c->Cedar->ref);
+ c->Protocol = CONNECTION_TCP;
+ c->Type = CONNECTION_TYPE_INIT;
+ c->FirstSock = s;
+ if (s != NULL)
+ {
+ AddRef(c->FirstSock->ref);
+ Copy(&c->ClientIp, &s->RemoteIP, sizeof(IP));
+ StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
+ }
+ c->Tcp = ZeroMalloc(sizeof(TCP));
+ c->Tcp->TcpSockList = NewList(NULL);
+ c->ServerMode = true;
+ c->Status = CONNECTION_STATUS_ACCEPTED;
+ c->Name = CopyStr("INITING");
+ c->Thread = t;
+ AddRef(t->ref);
+ c->CurrentNumConnection = NewCounter();
+ Inc(c->CurrentNumConnection);
+
+ c->ServerVer = cedar->Version;
+ c->ServerBuild = cedar->Build;
+ StrCpy(c->ServerStr, sizeof(c->ServerStr), cedar->ServerStr);
+ GetServerProductName(cedar->Server, c->ServerStr, sizeof(c->ServerStr));
+
+ if (s != NULL && s->RemoteX != NULL)
+ {
+ c->ServerX = CloneX(s->RemoteX);
+ }
+
+ if (s != NULL && s->Type == SOCK_INPROC)
+ {
+ // In-process socket
+ c->IsInProc = true;
+ }
+
+ // Creating a Queue
+ c->ReceivedBlocks = NewQueue();
+ c->SendBlocks = NewQueue();
+ c->SendBlocks2 = NewQueue();
+
+ return c;
+}
+
+// Creating a Client Connection
+CONNECTION *NewClientConnection(SESSION *s)
+{
+ return NewClientConnectionEx(s, NULL, 0, 0);
+}
+CONNECTION *NewClientConnectionEx(SESSION *s, char *client_str, UINT client_ver, UINT client_build)
+{
+ CONNECTION *c;
+
+ // Initialization of CONNECTION object
+ c = ZeroMalloc(sizeof(CONNECTION));
+ c->ConnectedTick = Tick64();
+ c->lock = NewLock();
+ c->ref = NewRef();
+ c->Cedar = s->Cedar;
+ AddRef(c->Cedar->ref);
+ c->Protocol = CONNECTION_TCP;
+ c->Tcp = ZeroMalloc(sizeof(TCP));
+ c->Tcp->TcpSockList = NewList(NULL);
+ c->ServerMode = false;
+ c->Status = CONNECTION_STATUS_CONNECTING;
+ c->Name = CopyStr("CLIENT_CONNECTION");
+ c->Session = s;
+ c->CurrentNumConnection = NewCounter();
+ c->LastCounterResetTick = Tick64();
+ Inc(c->CurrentNumConnection);
+
+ c->ConnectingThreads = NewList(NULL);
+ c->ConnectingSocks = NewList(NULL);
+
+ if (client_str == NULL)
+ {
+ c->ClientVer = s->Cedar->Version;
+ c->ClientBuild = s->Cedar->Build;
+
+ if (c->Session->VirtualHost == false)
+ {
+ if (c->Session->LinkModeClient == false)
+ {
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_CLIENT_STR);
+ }
+ else
+ {
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_SERVER_LINK_STR);
+ }
+ }
+ else
+ {
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_ROUTER_STR);
+ }
+ }
+ else
+ {
+ c->ClientVer = client_ver;
+ c->ClientBuild = client_build;
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), client_str);
+ }
+
+ // Server name and port number
+ StrCpy(c->ServerName, sizeof(c->ServerName), s->ClientOption->Hostname);
+ c->ServerPort = s->ClientOption->Port;
+
+ // TLS 1.0 using flag
+ c->DontUseTls1 = s->ClientOption->NoTls1;
+
+ // Create queues
+ c->ReceivedBlocks = NewQueue();
+ c->SendBlocks = NewQueue();
+ c->SendBlocks2 = NewQueue();
+
+ return c;
+}
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Connection.h b/src/Cedar/Connection.h
new file mode 100644
index 00000000..b83c3188
--- /dev/null
+++ b/src/Cedar/Connection.h
@@ -0,0 +1,341 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Connection.h
+// Header of Connection.c
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+// Magic number indicating that the packet is compressed
+#define CONNECTION_BULK_COMPRESS_SIGNATURE 0xDEADBEEFCAFEFACEULL
+
+#define KEEP_ALIVE_STRING "Internet Connection Keep Alive Packet"
+
+// KEEP CONNECT structure
+struct KEEP
+{
+ LOCK *lock; // Lock
+ bool Server; // Server mode
+ volatile bool Halt; // Stop flag
+ bool Enable; // Enable flag
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT ServerPort; // Server port number
+ bool UdpMode; // UDP mode
+ UINT Interval; // Packet transmission interval
+ THREAD *Thread; // Connection thread
+ EVENT *HaltEvent; // Stop event
+ CANCEL *Cancel; // Cancel
+};
+
+// SECURE_SIGN Structure
+struct SECURE_SIGN
+{
+ char SecurePublicCertName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device certificate name
+ char SecurePrivateKeyName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device secret key name
+ X *ClientCert; // Client certificate
+ UCHAR Random[SHA1_SIZE]; // Random value for signature
+ UCHAR Signature[128]; // Signed data
+ UINT UseSecureDeviceId;
+ UINT BitmapId; // Bitmap ID
+};
+
+// Function type declaration
+typedef bool (CHECK_CERT_PROC)(SESSION *s, CONNECTION *c, X *server_x, bool *expired);
+typedef bool (SECURE_SIGN_PROC)(SESSION *s, CONNECTION *c, SECURE_SIGN *sign);
+
+// RC4 key pair
+struct RC4_KEY_PAIR
+{
+ UCHAR ServerToClientKey[16];
+ UCHAR ClientToServerKey[16];
+};
+
+// Client Options
+struct CLIENT_OPTION
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Connection setting name
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+ UINT PortUDP; // UDP port number (0: Use only TCP)
+ UINT ProxyType; // Type of proxy
+ char ProxyName[MAX_HOST_NAME_LEN + 1]; // Proxy server name
+ UINT ProxyPort; // Port number of the proxy server
+ char ProxyUsername[MAX_PROXY_USERNAME_LEN + 1]; // Maximum user name length
+ char ProxyPassword[MAX_PROXY_PASSWORD_LEN + 1]; // Maximum password length
+ UINT NumRetry; // Automatic retries
+ UINT RetryInterval; // Retry interval
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UINT MaxConnection; // Maximum number of concurrent TCP connections
+ bool UseEncrypt; // Use encrypted communication
+ bool UseCompress; // Use data compression
+ bool HalfConnection; // Use half connection in TCP
+ bool NoRoutingTracking; // Disable the routing tracking
+ char DeviceName[MAX_DEVICE_NAME_LEN + 1]; // VLAN device name
+ UINT AdditionalConnectionInterval; // Connection attempt interval when additional connection establish
+ UINT ConnectionDisconnectSpan; // Disconnection interval
+ bool HideStatusWindow; // Hide the status window
+ bool HideNicInfoWindow; // Hide the NIC status window
+ bool RequireMonitorMode; // Monitor port mode
+ bool RequireBridgeRoutingMode; // Bridge or routing mode
+ bool DisableQoS; // Disable the VoIP / QoS function
+ bool FromAdminPack; // For Administration Pack
+ bool NoTls1; // Do not use TLS 1.0
+ bool NoUdpAcceleration; // Do not use UDP acceleration mode
+ UCHAR HostUniqueKey[SHA1_SIZE]; // Host unique key
+};
+
+// Client authentication data
+struct CLIENT_AUTH
+{
+ UINT AuthType; // Authentication type
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ UCHAR HashedPassword[SHA1_SIZE]; // Hashed passwords
+ char PlainPassword[MAX_PASSWORD_LEN + 1]; // Password
+ X *ClientX; // Client certificate
+ K *ClientK; // Client private key
+ char SecurePublicCertName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device certificate name
+ char SecurePrivateKeyName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device secret key name
+ CHECK_CERT_PROC *CheckCertProc; // Server certificate confirmation procedure
+ SECURE_SIGN_PROC *SecureSignProc; // Security signing procedure
+};
+
+// TCP socket data structure
+struct TCPSOCK
+{
+ SOCK *Sock; // Socket
+ FIFO *RecvFifo; // Reception buffer
+ FIFO *SendFifo; // Transmission buffer
+ UINT Mode; // Read mode
+ UINT WantSize; // Requested data size
+ UINT NextBlockNum; // Total number of blocks that can be read next
+ UINT NextBlockSize; // Block size that is planned to read next
+ UINT CurrentPacketNum; // Current packet number
+ UINT64 LastCommTime; // Last communicated time
+ UINT64 LastRecvTime; // Time the last data received
+ UINT LateCount; // The number of delay occurences
+ UINT Direction; // Direction
+ UINT64 NextKeepAliveTime; // Next time to send a KeepAlive packet
+ RC4_KEY_PAIR Rc4KeyPair; // RC4 key pair
+ CRYPT *SendKey; // Transmission key
+ CRYPT *RecvKey; // Reception key
+ UINT64 DisconnectTick; // Time to disconnect this connection
+ UINT64 EstablishedTick; // Establishment time
+};
+
+// TCP communication data structure
+struct TCP
+{
+ LIST *TcpSockList; // TCP socket list
+};
+
+// UDP communication data structure
+struct UDP
+{
+ SOCK *s; // UDP socket (for transmission)
+ IP ip; // Destination IP address
+ UINT port; // Destination port number
+ UINT64 NextKeepAliveTime; // Next time to send a KeepAlive packet
+ UINT64 Seq; // Packet sequence number
+ UINT64 RecvSeq;
+ QUEUE *BufferQueue; // Queue of buffer to be sent
+};
+
+// Data block
+struct BLOCK
+{
+ BOOL Compressed; // Compression flag
+ UINT Size; // Block size
+ UINT SizeofData; // Data size
+ UCHAR *Buf; // Buffer
+ bool PriorityQoS; // Priority packet for VoIP / QoS function
+ UINT Ttl; // TTL value (Used only in ICMP NAT of Virtual.c)
+ UINT Param1; // Parameter 1
+};
+
+// Connection structure
+struct CONNECTION
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ struct SESSION *Session; // Session
+ UINT Protocol; // Protocol
+ SOCK *FirstSock; // Socket for negotiation
+ SOCK *TubeSock; // Socket for in-process communication
+ TCP *Tcp; // TCP communication data structure
+ UDP *Udp; // UDP communication data structure
+ bool ServerMode; // Server mode
+ UINT Status; // Status
+ char *Name; // Connection name
+ THREAD *Thread; // Thread
+ volatile bool Halt; // Stop flag
+ UCHAR Random[SHA1_SIZE]; // Random number for Authentication
+ UINT ServerVer; // Server version
+ UINT ServerBuild; // Server build number
+ UINT ClientVer; // Client version
+ UINT ClientBuild; // Client build number
+ char ServerStr[MAX_SERVER_STR_LEN + 1]; // Server string
+ char ClientStr[MAX_CLIENT_STR_LEN + 1]; // Client string
+ UINT Err; // Error value
+ bool ClientConnectError_NoSavePassword; // Don't save the password for the specified user name
+ QUEUE *ReceivedBlocks; // Block queue that is received
+ QUEUE *SendBlocks; // Block queue planned to be sent
+ QUEUE *SendBlocks2; // Send queue (high priority)
+ COUNTER *CurrentNumConnection; // Counter of the number of current connections
+ LIST *ConnectingThreads; // List of connected threads
+ LIST *ConnectingSocks; // List of the connected sockets
+ bool flag1; // Flag 1
+ UCHAR *RecvBuf; // Receive buffer
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT ServerPort; // Port number
+ bool RestoreServerNameAndPort; // Flag to restore the server name and port number to original
+ bool UseTicket; // Ticket using flag
+ UCHAR Ticket[SHA1_SIZE]; // Ticket
+ UINT CurrentSendQueueSize; // Total size of the transmission queue
+ X *ServerX; // Server certificate
+ X *ClientX; // Client certificate
+ char *CipherName; // Encryption algorithm name
+ UINT64 ConnectedTick; // Time it is connected
+ IP ClientIp; // Client IP address
+ char ClientHostname[MAX_HOST_NAME_LEN + 1]; // Client host name
+ UINT Type; // Type
+ bool DontUseTls1; // Do not use TLS 1.0
+ void *hWndForUI; // Parent window
+ bool IsInProc; // In-process
+ char InProcPrefix[64]; // Prefix
+ UINT AdditionalConnectionFailedCounter; // Additional connection failure counter
+ UINT64 LastCounterResetTick; // Time the counter was reset finally
+ bool WasSstp; // Processed the SSTP
+ bool WasDatProxy; // DAT proxy processed
+ UCHAR CToken_Hash[SHA1_SIZE]; // CTOKEN_HASH
+};
+
+
+
+// Function prototypes
+
+CONNECTION *NewClientConnection(SESSION *s);
+CONNECTION *NewClientConnectionEx(SESSION *s, char *client_str, UINT client_ver, UINT client_build);
+CONNECTION *NewServerConnection(CEDAR *cedar, SOCK *s, THREAD *t);
+void ReleaseConnection(CONNECTION *c);
+void CleanupConnection(CONNECTION *c);
+int CompareConnection(void *p1, void *p2);
+void StopConnection(CONNECTION *c, bool no_wait);
+void ConnectionAccept(CONNECTION *c);
+void StartTunnelingMode(CONNECTION *c);
+void EndTunnelingMode(CONNECTION *c);
+void DisconnectTcpSockets(CONNECTION *c);
+void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2);
+void ConnectionSend(CONNECTION *c);
+TCPSOCK *NewTcpSock(SOCK *s);
+void FreeTcpSock(TCPSOCK *ts);
+BLOCK *NewBlock(void *data, UINT size, int compress);
+void FreeBlock(BLOCK *b);
+void StopAllAdditionalConnectThread(CONNECTION *c);
+UINT GenNextKeepAliveSpan(CONNECTION *c);
+void SendKeepAlive(CONNECTION *c, TCPSOCK *ts);
+void DisconnectUDPSockets(CONNECTION *c);
+void PutUDPPacketData(CONNECTION *c, void *data, UINT size);
+void SendDataWithUDP(SOCK *s, CONNECTION *c);
+void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block);
+void InitTcpSockRc4Key(TCPSOCK *ts, bool server_mode);
+UINT TcpSockRecv(SESSION *s, TCPSOCK *ts, void *data, UINT size);
+UINT TcpSockSend(SESSION *s, TCPSOCK *ts, void *data, UINT size);
+void WriteSendFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size);
+void WriteRecvFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size);
+CLIENT_AUTH *CopyClientAuth(CLIENT_AUTH *a);
+BUF *NewKeepPacket(bool server_mode);
+void KeepThread(THREAD *thread, void *param);
+KEEP *StartKeep();
+void StopKeep(KEEP *k);
+void InRpcSecureSign(SECURE_SIGN *t, PACK *p);
+void OutRpcSecureSign(PACK *p, SECURE_SIGN *t);
+void FreeRpcSecureSign(SECURE_SIGN *t);
+void NormalizeEthMtu(BRIDGE *b, CONNECTION *c, UINT packet_size);
+UINT GetMachineRand();
+
+
+
+#endif // CONNECTION_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Console.c b/src/Cedar/Console.c
new file mode 100644
index 00000000..9c887feb
--- /dev/null
+++ b/src/Cedar/Console.c
@@ -0,0 +1,2510 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Console.c
+// Console Service
+
+#include "CedarPch.h"
+
+
+// Display the help for the command
+void PrintCmdHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *param_list)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t *buf;
+ UINT buf_size;
+ wchar_t *description, *args, *help;
+ UNI_TOKEN_LIST *t;
+ UINT width;
+ UINT i;
+ char *space;
+ // Validate arguments
+ if (c == NULL || cmd_name == NULL || param_list == NULL)
+ {
+ return;
+ }
+
+ width = GetConsoleWidth(c) - 2;
+
+ buf_size = sizeof(wchar_t) * (width + 32);
+ buf = Malloc(buf_size);
+
+ GetCommandHelpStr(cmd_name, &description, &args, &help);
+
+ space = MakeCharArray(' ', 2);
+
+ // Title
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_TITLE"), cmd_name);
+ c->Write(c, tmp);
+ c->Write(c, L"");
+
+ // Purpose
+ c->Write(c, _UU("CMD_HELP_DESCRIPTION"));
+ t = SeparateStringByWidth(description, width - 2);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
+ c->Write(c, buf);
+ }
+ UniFreeToken(t);
+ c->Write(c, L"");
+
+ // Description
+ c->Write(c, _UU("CMD_HELP_HELP"));
+ t = SeparateStringByWidth(help, width - 2);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
+ c->Write(c, buf);
+ }
+ UniFreeToken(t);
+ c->Write(c, L"");
+
+ // Usage
+ c->Write(c, _UU("CMD_HELP_USAGE"));
+ t = SeparateStringByWidth(args, width - 2);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
+ c->Write(c, buf);
+ }
+ UniFreeToken(t);
+
+ // Arguments
+ if (param_list->NumTokens >= 1)
+ {
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_HELP_ARGS"));
+ PrintCandidateHelp(c, cmd_name, param_list, 2);
+ }
+
+ Free(space);
+
+ Free(buf);
+}
+
+// Evaluate whether it is SafeStr
+bool CmdEvalSafe(CONSOLE *c, wchar_t *str, void *param)
+{
+ wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_SAFE") : (wchar_t *)param;
+
+ if (IsSafeUniStr(str))
+ {
+ return true;
+ }
+
+ c->Write(c, p);
+
+ return false;
+}
+
+// String input prompt
+wchar_t *CmdPrompt(CONSOLE *c, void *param)
+{
+ wchar_t *p = (param == NULL) ? _UU("CMD_PROMPT") : (wchar_t *)param;
+
+ return c->ReadLine(c, p, true);
+}
+
+// Evaluation whether the specified file exists
+bool CmdEvalIsFile(CONSOLE *c, wchar_t *str, void *param)
+{
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), str);
+
+ if (IsEmptyUniStr(tmp))
+ {
+ c->Write(c, _UU("CMD_FILE_NAME_EMPTY"));
+ return false;
+ }
+
+ if (IsFileExistsW(tmp) == false)
+ {
+ wchar_t tmp2[MAX_SIZE];
+
+ UniFormat(tmp2, sizeof(tmp2), _UU("CMD_FILE_NOT_FOUND"), tmp);
+ c->Write(c, tmp2);
+
+ return false;
+ }
+
+ return true;
+}
+
+// Evaluation of integer
+bool CmdEvalInt1(CONSOLE *c, wchar_t *str, void *param)
+{
+ wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_INT") : (wchar_t *)param;
+
+ if (UniToInt(str) == 0)
+ {
+ c->Write(c, p);
+
+ return false;
+ }
+
+ return true;
+}
+
+// Evaluation of the parameters that a blank cannot be specified to
+bool CmdEvalNotEmpty(CONSOLE *c, wchar_t *str, void *param)
+{
+ wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_NOT_EMPTY") : (wchar_t *)param;
+
+ if (UniIsEmptyStr(str) == false)
+ {
+ return true;
+ }
+
+ c->Write(c, p);
+
+ return false;
+}
+
+// Evaluation function for minimum / maximum value of the parameter
+bool CmdEvalMinMax(CONSOLE *c, wchar_t *str, void *param)
+{
+ CMD_EVAL_MIN_MAX *e;
+ wchar_t *tag;
+ UINT v;
+ // Validate arguments
+ if (param == NULL)
+ {
+ return false;
+ }
+
+ e = (CMD_EVAL_MIN_MAX *)param;
+
+ if (e->StrName == NULL)
+ {
+ tag = _UU("CMD_EVAL_MIN_MAX");
+ }
+ else
+ {
+ tag = _UU(e->StrName);
+ }
+
+ v = UniToInt(str);
+
+ if (v >= e->MinValue && v <= e->MaxValue)
+ {
+ return true;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), tag, e->MinValue, e->MaxValue);
+ c->Write(c, tmp);
+
+ return false;
+ }
+}
+
+// Get the help string of command
+void GetCommandHelpStr(char *command_name, wchar_t **description, wchar_t **args, wchar_t **help)
+{
+ char tmp1[128], tmp2[128], tmp3[128];
+
+ Format(tmp1, sizeof(tmp1), "CMD_%s", command_name);
+ Format(tmp2, sizeof(tmp2), "CMD_%s_ARGS", command_name);
+ Format(tmp3, sizeof(tmp3), "CMD_%s_HELP", command_name);
+
+ if (description != NULL)
+ {
+ *description = _UU(tmp1);
+ if (UniIsEmptyStr(*description))
+ {
+ *description = _UU("CMD_UNKNOWM");
+ }
+ }
+
+ if (args != NULL)
+ {
+ *args = _UU(tmp2);
+ if (UniIsEmptyStr(*args))
+ {
+ *args = _UU("CMD_UNKNOWN_ARGS");
+ }
+ }
+
+ if (help != NULL)
+ {
+ *help = _UU(tmp3);
+ if (UniIsEmptyStr(*help))
+ {
+ *help = _UU("CMD_UNKNOWN_HELP");
+ }
+ }
+}
+
+// Get the help string for parameter
+void GetCommandParamHelpStr(char *command_name, char *param_name, wchar_t **description)
+{
+ char tmp[160];
+ if (description == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), "CMD_%s_%s", command_name, param_name);
+
+ *description = _UU(tmp);
+
+ if (UniIsEmptyStr(*description))
+ {
+ *description = _UU("CMD_UNKNOWN_PARAM");
+ }
+}
+
+// String comparison function
+int CompareCandidateStr(void *p1, void *p2)
+{
+ char *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(char **)p1;
+ s2 = *(char **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ if (s1[0] == '[' && s2[0] != '[')
+ {
+ return -1;
+ }
+ else if (s2[0] == '[' && s1[0] != '[')
+ {
+ return 1;
+ }
+
+ return StrCmp(s1, s2);
+}
+
+// Display the help of the candidate list
+void PrintCandidateHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *candidate_list, UINT left_space)
+{
+ UINT console_width;
+ UINT max_keyword_width;
+ LIST *o;
+ UINT i;
+ wchar_t *tmpbuf;
+ UINT tmpbuf_size;
+ char *left_space_array;
+ char *max_space_array;
+ // Validate arguments
+ if (c == NULL || candidate_list == NULL)
+ {
+ return;
+ }
+
+ // Get the width of the screen
+ console_width = GetConsoleWidth(c) - 1;
+
+ tmpbuf_size = sizeof(wchar_t) * (console_width + 32);
+ tmpbuf = Malloc(tmpbuf_size);
+
+ left_space_array = MakeCharArray(' ', left_space);
+
+ // Sort and enlist the command name
+ // no need to sort the parameter name
+ o = NewListFast(cmd_name == NULL ? CompareCandidateStr : NULL);
+
+ max_keyword_width = 0;
+
+ for (i = 0;i < candidate_list->NumTokens;i++)
+ {
+ UINT keyword_width;
+
+ // Get the width of each keyword
+ Insert(o, candidate_list->Token[i]);
+
+ keyword_width = StrWidth(candidate_list->Token[i]);
+ if (cmd_name != NULL)
+ {
+ if (candidate_list->Token[i][0] != '[')
+ {
+ keyword_width += 1;
+ }
+ else
+ {
+ keyword_width -= 2;
+ }
+ }
+
+ max_keyword_width = MAX(max_keyword_width, keyword_width);
+ }
+
+ max_space_array = MakeCharArray(' ', max_keyword_width);
+
+ // Display the candidate
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp[128];
+ char *name = LIST_DATA(o, i);
+ UNI_TOKEN_LIST *t;
+ wchar_t *help;
+ UINT j;
+ UINT keyword_start_width = left_space;
+ UINT descript_start_width = left_space + max_keyword_width + 1;
+ UINT descript_width;
+ char *space;
+
+ if (console_width >= (descript_start_width + 5))
+ {
+ descript_width = console_width - descript_start_width - 3;
+ }
+ else
+ {
+ descript_width = 2;
+ }
+
+ // Generate the name
+ if (cmd_name != NULL && name[0] != '[')
+ {
+ // Prepend a "/" in the case of a parameter
+ Format(tmp, sizeof(tmp), "/%s", name);
+ }
+ else
+ {
+ // Use the characters as it is in the case of a command name
+ if (cmd_name == NULL)
+ {
+ StrCpy(tmp, sizeof(tmp), name);
+ }
+ else
+ {
+ StrCpy(tmp, sizeof(tmp), name + 1);
+ if (StrLen(tmp) >= 1)
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+ }
+
+ // Get the help string
+ if (cmd_name == NULL)
+ {
+ GetCommandHelpStr(name, &help, NULL, NULL);
+ }
+ else
+ {
+ GetCommandParamHelpStr(cmd_name, name, &help);
+ }
+
+ space = MakeCharArray(' ', max_keyword_width - StrWidth(name) - (cmd_name == NULL ? 0 : (name[0] != '[' ? 1 : -2)));
+
+ t = SeparateStringByWidth(help, descript_width);
+
+ for (j = 0;j < t->NumTokens;j++)
+ {
+ if (j == 0)
+ {
+ UniFormat(tmpbuf, tmpbuf_size, L"%S%S%S - %s",
+ left_space_array, tmp, space, t->Token[j]);
+ }
+ else
+ {
+ UniFormat(tmpbuf, tmpbuf_size, L"%S%S %s",
+ left_space_array, max_space_array, t->Token[j]);
+ }
+
+ c->Write(c, tmpbuf);
+ }
+
+ Free(space);
+
+ UniFreeToken(t);
+ }
+
+ ReleaseList(o);
+
+ Free(max_space_array);
+ Free(tmpbuf);
+ Free(left_space_array);
+}
+
+// Acquisition whether word characters
+bool IsWordChar(wchar_t c)
+{
+ if (c >= L'a' && c <= 'z')
+ {
+ return true;
+ }
+ if (c >= L'A' && c <= 'Z')
+ {
+ return true;
+ }
+ if (c >= L'0' && c <= '9')
+ {
+ return true;
+ }
+ if (c == L'_')
+ {
+ return true;
+ }
+ if (c == L'.')
+ {
+ return true;
+ }
+ if (c == L'\"')
+ {
+ return true;
+ }
+ if (c == L'\'')
+ {
+ return true;
+ }
+ if (c == L',')
+ {
+ return true;
+ }
+ if (c == L')')
+ {
+ return true;
+ }
+ if (c == L']')
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the character width of the word that comes next
+UINT GetNextWordWidth(wchar_t *str)
+{
+ UINT i;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+
+ for (i = 0;;i++)
+ {
+ wchar_t c = str[i];
+
+ if (c == 0)
+ {
+ break;
+ }
+
+ if (IsWordChar(c) == false)
+ {
+ break;
+ }
+
+ ret++;
+ }
+
+ return ret;
+}
+
+// Split a string into specified width
+UNI_TOKEN_LIST *SeparateStringByWidth(wchar_t *str, UINT width)
+{
+ UINT wp;
+ wchar_t *tmp;
+ UINT len, i;
+ LIST *o;
+ UNI_TOKEN_LIST *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return UniNullToken();
+ }
+ if (width == 0)
+ {
+ width = 1;
+ }
+
+ o = NewListFast(NULL);
+
+ len = UniStrLen(str);
+ tmp = ZeroMalloc(sizeof(wchar_t) * (len + 32));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ wchar_t c = str[i];
+ UINT next_word_width;
+ UINT remain_width;
+
+ switch (c)
+ {
+ case 0:
+ case L'\r':
+ case L'\n':
+ if (c == L'\r')
+ {
+ if (str[i + 1] == L'\n')
+ {
+ i++;
+ }
+ }
+
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, UniCopyStr(tmp));
+ break;
+
+ default:
+ next_word_width = GetNextWordWidth(&str[i]);
+ remain_width = (width - UniStrWidth(tmp));
+
+ if ((remain_width >= 1) && (next_word_width > remain_width) && (next_word_width <= width))
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, UniCopyStr(tmp));
+ }
+
+ tmp[wp++] = c;
+ tmp[wp] = 0;
+ if (UniStrWidth(tmp) >= width)
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, UniCopyStr(tmp));
+ }
+ break;
+ }
+ }
+
+ if (LIST_NUM(o) == 0)
+ {
+ Insert(o, CopyUniStr(L""));
+ }
+
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(o);
+ ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+
+ UniTrimLeft(s);
+
+ ret->Token[i] = s;
+ }
+
+ ReleaseList(o);
+ Free(tmp);
+
+ return ret;
+}
+
+// Check whether the specified string means 'help'
+bool IsHelpStr(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrCmpi(str, "help") == 0 || StrCmpi(str, "?") == 0 ||
+ StrCmpi(str, "man") == 0 || StrCmpi(str, "/man") == 0 ||
+ StrCmpi(str, "-man") == 0 || StrCmpi(str, "--man") == 0 ||
+ StrCmpi(str, "/help") == 0 || StrCmpi(str, "/?") == 0 ||
+ StrCmpi(str, "-help") == 0 || StrCmpi(str, "-?") == 0 ||
+ StrCmpi(str, "/h") == 0 || StrCmpi(str, "--help") == 0 ||
+ StrCmpi(str, "--?") == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Execution of the command
+bool DispatchNextCmd(CONSOLE *c, char *prompt, CMD cmd[], UINT num_cmd, void *param)
+{
+ return DispatchNextCmdEx(c, NULL, prompt, cmd, num_cmd, param);
+}
+bool DispatchNextCmdEx(CONSOLE *c, wchar_t *exec_command, char *prompt, CMD cmd[], UINT num_cmd, void *param)
+{
+ wchar_t *str;
+ wchar_t *tmp;
+ char *cmd_name;
+ bool b_exit = false;
+ wchar_t *cmd_param;
+ UINT ret = ERR_NO_ERROR;
+ TOKEN_LIST *t;
+ TOKEN_LIST *candidate;
+ bool no_end_crlf = false;
+ UINT i;
+ // Validate arguments
+ if (c == NULL || (num_cmd >= 1 && cmd == NULL))
+ {
+ return false;
+ }
+
+ if (exec_command == NULL)
+ {
+ // Show the prompt
+RETRY:
+ tmp = CopyStrToUni(prompt);
+ str = c->ReadLine(c, tmp, false);
+ Free(tmp);
+
+ if (str != NULL && IsEmptyUniStr(str))
+ {
+ Free(str);
+ goto RETRY;
+ }
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ // Use exec_command
+ if (UniStartWith(exec_command, L"vpncmd") == false)
+ {
+ if (prompt != NULL)
+ {
+ if (c->ConsoleType != CONSOLE_CSV)
+ {
+ UniFormat(tmp, sizeof(tmp), L"%S%s", prompt, exec_command);
+ c->Write(c, tmp);
+ }
+ }
+ }
+ str = CopyUniStr(exec_command);
+ }
+
+ if (str == NULL)
+ {
+ // User canceled
+ return false;
+ }
+
+ UniTrimCrlf(str);
+ UniTrim(str);
+
+ if (UniIsEmptyStr(str))
+ {
+ // Do Nothing
+ Free(str);
+ return true;
+ }
+
+ // Divide into command name and parameter
+ if (SeparateCommandAndParam(str, &cmd_name, &cmd_param) == false)
+ {
+ // Do Nothing
+ Free(str);
+ return true;
+ }
+
+ if (StrLen(cmd_name) >= 2 && cmd_name[0] == '?' && cmd_name[1] != '?')
+ {
+ char tmp[MAX_SIZE];
+ wchar_t *s;
+
+ StrCpy(tmp, sizeof(tmp), cmd_name + 1);
+ StrCpy(cmd_name, 0, tmp);
+
+ s = UniCopyStr(L"/?");
+ Free(cmd_param);
+
+ cmd_param = s;
+ }
+
+ if (StrLen(cmd_name) >= 2 && EndWith(cmd_name, "?") && cmd_name[StrLen(cmd_name) - 2] != '?')
+ {
+ wchar_t *s;
+
+ cmd_name[StrLen(cmd_name) - 1] = 0;
+
+ s = UniCopyStr(L"/?");
+ Free(cmd_param);
+
+ cmd_param = s;
+ }
+
+ // Get the candidate of command
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = num_cmd;
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = CopyStr(cmd[i].Name);
+ }
+
+ if (IsHelpStr(cmd_name))
+ {
+ if (UniIsEmptyStr(cmd_param))
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // Display the list of commands that can be used
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_1"), t->NumTokens);
+ c->Write(c, tmp);
+
+ PrintCandidateHelp(c, NULL, t, 1);
+
+ c->Write(c, L"");
+ c->Write(c, _UU("CMD_HELP_2"));
+ }
+ else
+ {
+ char *cmd_name;
+
+ // Display the help for the specified command
+ if (SeparateCommandAndParam(cmd_param, &cmd_name, NULL))
+ {
+ bool b = true;
+
+ if (IsHelpStr(cmd_name))
+ {
+ b = false;
+ }
+
+ if (b)
+ {
+ wchar_t str[MAX_SIZE];
+
+ UniFormat(str, sizeof(str), L"%S /help", cmd_name);
+ DispatchNextCmdEx(c, str, NULL, cmd, num_cmd, param);
+ no_end_crlf = true;
+ }
+
+ Free(cmd_name);
+ }
+ }
+ }
+ else if (StrCmpi(cmd_name, "exit") == 0 || StrCmpi(cmd_name, "quit") == 0)
+ {
+ // Exit
+ b_exit = true;
+ }
+ else
+ {
+ candidate = GetRealnameCandidate(cmd_name, t);
+
+ if (candidate == NULL || candidate->NumTokens == 0)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // No candidate
+ UniFormat(tmp, sizeof(tmp), _UU("CON_UNKNOWN_CMD"), cmd_name);
+ c->Write(c, tmp);
+
+ c->RetCode = ERR_BAD_COMMAND_OR_PARAM;
+ }
+ else if (candidate->NumTokens >= 2)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // There is more than one candidate
+ UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_CMD"), cmd_name);
+ c->Write(c, tmp);
+ c->Write(c, _UU("CON_AMBIGIOUS_CMD_1"));
+ PrintCandidateHelp(c, NULL, candidate, 1);
+ c->Write(c, _UU("CON_AMBIGIOUS_CMD_2"));
+
+ c->RetCode = ERR_BAD_COMMAND_OR_PARAM;
+ }
+ else
+ {
+ char *real_cmd_name;
+ UINT i;
+
+ // The candidate was shortlisted to one
+ real_cmd_name = candidate->Token[0];
+
+ for (i = 0;i < num_cmd;i++)
+ {
+ if (StrCmpi(cmd[i].Name, real_cmd_name) == 0)
+ {
+ if (cmd[i].Proc != NULL)
+ {
+ // Show the description of the command if it isn't in CSV mode
+ if(c->ConsoleType != CONSOLE_CSV)
+ {
+ wchar_t tmp[256];
+ wchar_t *note;
+
+ GetCommandHelpStr(cmd[i].Name, &note, NULL, NULL);
+ UniFormat(tmp, sizeof(tmp), _UU("CMD_EXEC_MSG_NAME"), cmd[i].Name, note);
+ c->Write(c, tmp);
+ }
+
+ // Call the procedure of the command
+ ret = cmd[i].Proc(c, cmd[i].Name, cmd_param, param);
+
+ if (ret == INFINITE)
+ {
+ // Exit command
+ b_exit = true;
+ }
+ else
+ {
+ c->RetCode = ret;
+ }
+ }
+ }
+ }
+ }
+
+ FreeToken(candidate);
+ }
+
+ FreeToken(t);
+ Free(str);
+ Free(cmd_name);
+ Free(cmd_param);
+
+ if (no_end_crlf == false)
+ {
+ //c->Write(c, L"");
+ }
+
+ if (b_exit)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the width of the current console
+UINT GetConsoleWidth(CONSOLE *c)
+{
+ UINT size;
+
+ size = c->GetWidth(c);
+
+ if (size == 0)
+ {
+ size = 80;
+ }
+
+ if (size < 32)
+ {
+ size = 32;
+ }
+
+ if (size > 65536)
+ {
+ size = 65535;
+ }
+
+ return size;
+}
+
+// Separate the command line into the command and the parameters
+bool SeparateCommandAndParam(wchar_t *src, char **cmd, wchar_t **param)
+{
+ UINT i, len, wp;
+ wchar_t *tmp;
+ wchar_t *src_tmp;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+ if (cmd != NULL)
+ {
+ *cmd = NULL;
+ }
+ if (param != NULL)
+ {
+ *param = NULL;
+ }
+
+ src_tmp = UniCopyStr(src);
+ UniTrimCrlf(src_tmp);
+ UniTrim(src_tmp);
+
+ len = UniStrLen(src_tmp);
+ tmp = Malloc(sizeof(wchar_t) * (len + 32));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ wchar_t c = src_tmp[i];
+
+ switch (c)
+ {
+ case 0:
+ case L' ':
+ case L'\t':
+ tmp[wp] = 0;
+ if (UniIsEmptyStr(tmp))
+ {
+ Free(tmp);
+ Free(src_tmp);
+ return false;
+ }
+ if (cmd != NULL)
+ {
+ *cmd = CopyUniToStr(tmp);
+ Trim(*cmd);
+ }
+ goto ESCAPE;
+
+ default:
+ tmp[wp++] = c;
+ break;
+ }
+ }
+
+ESCAPE:
+ if (param != NULL)
+ {
+ *param = CopyUniStr(&src_tmp[wp]);
+ UniTrim(*param);
+ }
+
+ Free(tmp);
+ Free(src_tmp);
+
+ return true;
+}
+
+// Get the candidates list of of the real command name whose abbreviation matches to the command specified by the user
+TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list)
+{
+ TOKEN_LIST *ret;
+ LIST *o;
+ UINT i;
+ bool ok = false;
+ // Validate arguments
+ if (input_name == NULL || real_name_list == NULL)
+ {
+ return NullToken();
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < real_name_list->NumTokens;i++)
+ {
+ char *name = real_name_list->Token[i];
+
+ // Search for an exact match with the highest priority first
+ if (StrCmpi(name, input_name) == 0)
+ {
+ Insert(o, name);
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok == false)
+ {
+ // If there is no command to exact match, check whether it matches to a short form command
+ for (i = 0;i < real_name_list->NumTokens;i++)
+ {
+ char *name = real_name_list->Token[i];
+
+ if (IsOmissionName(input_name, name) || IsNameInRealName(input_name, name))
+ {
+ // A abbreviation is found
+ Insert(o, name);
+ ok = true;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ // One or more candidate is found
+ ret = ListToTokenList(o);
+ }
+ else
+ {
+ ret = NullToken();
+ }
+
+ ReleaseList(o);
+
+ return ret;
+}
+
+// Check whether the command specified by the user is a abbreviation of existing commands
+bool IsOmissionName(char *input_name, char *real_name)
+{
+ char oname[128];
+ // Validate arguments
+ if (input_name == NULL || real_name == NULL)
+ {
+ return false;
+ }
+
+ if (IsAllUpperStr(real_name))
+ {
+ // Command of all capital letters do not take abbreviations
+ return false;
+ }
+
+ GetOmissionName(oname, sizeof(oname), real_name);
+
+ if (IsEmptyStr(oname))
+ {
+ return false;
+ }
+
+ if (StartWith(oname, input_name))
+ {
+ // Example: The oname of AccountSecureCertSet is "ascs".
+ // But if the user enters "asc", returns true
+ return true;
+ }
+
+ if (StartWith(input_name, oname))
+ {
+ // Example: When two commands AccountCreate and AccountConnect exist,
+ // if the user enter "aconnect" , only AccountConnect is true
+
+ if (EndWith(real_name, &input_name[StrLen(oname)]))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get the short name of the specified command
+void GetOmissionName(char *dst, UINT size, char *src)
+{
+ UINT i, len;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ StrCpy(dst, size, "");
+ len = StrLen(src);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = src[i];
+
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z'))
+ {
+ char tmp[2];
+ tmp[0] = c;
+ tmp[1] = 0;
+
+ StrCat(dst, size, tmp);
+ }
+ }
+}
+
+// Check whether the command specified by the user matches the existing commands
+bool IsNameInRealName(char *input_name, char *real_name)
+{
+ // Validate arguments
+ if (input_name == NULL || real_name == NULL)
+ {
+ return false;
+ }
+
+ if (StartWith(real_name, input_name))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Parse the command list
+LIST *ParseCommandList(CONSOLE *c, char *cmd_name, wchar_t *command, PARAM param[], UINT num_param)
+{
+ UINT i;
+ LIST *o;
+ bool ok = true;
+ TOKEN_LIST *param_list;
+ TOKEN_LIST *real_name_list;
+ bool help_mode = false;
+ wchar_t *tmp;
+ // Validate arguments
+ if (c == NULL || command == NULL || (num_param >= 1 && param == NULL) || cmd_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialization
+ for (i = 0;i < num_param;i++)
+ {
+ if (IsEmptyStr(param[i].Name) == false)
+ {
+ if (param[i].Name[0] == '[')
+ {
+ param[i].Tmp = "";
+ }
+ else
+ {
+ param[i].Tmp = NULL;
+ }
+ }
+ else
+ {
+ param[i].Tmp = "";
+ }
+ }
+
+ real_name_list = ZeroMalloc(sizeof(TOKEN_LIST));
+ real_name_list->NumTokens = num_param;
+ real_name_list->Token = ZeroMalloc(sizeof(char *) * real_name_list->NumTokens);
+
+ for (i = 0;i < real_name_list->NumTokens;i++)
+ {
+ real_name_list->Token[i] = CopyStr(param[i].Name);
+ }
+
+ // Generate a list of parameter name specified by the user
+ param_list = GetCommandNameList(command);
+
+ for (i = 0;i < param_list->NumTokens;i++)
+ {
+ char *s = param_list->Token[i];
+
+ if (StrCmpi(s, "help") == 0 || StrCmpi(s, "?") == 0)
+ {
+ help_mode = true;
+ break;
+ }
+ }
+
+ tmp = ParseCommand(command, L"");
+ if (tmp != NULL)
+ {
+ if (UniStrCmpi(tmp, L"?") == 0)
+ {
+ help_mode = true;
+ }
+ Free(tmp);
+ }
+
+ if (help_mode)
+ {
+ // Show the help
+ PrintCmdHelp(c, cmd_name, real_name_list);
+ FreeToken(param_list);
+ FreeToken(real_name_list);
+ return NULL;
+ }
+
+ for (i = 0;i < param_list->NumTokens;i++)
+ {
+ // Get the corresponding commands for all parameter names which is specified by the user
+ TOKEN_LIST *candidate = GetRealnameCandidate(param_list->Token[i], real_name_list);
+
+ if (candidate != NULL && candidate->NumTokens >= 1)
+ {
+ if (candidate->NumTokens >= 2)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // There is more than one candidate
+ UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM"), param_list->Token[i]);
+ c->Write(c, tmp);
+ UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM_1"), cmd_name);
+ c->Write(c, tmp);
+
+ PrintCandidateHelp(c, cmd_name, candidate, 1);
+
+ c->Write(c, _UU("CON_AMBIGIOUS_PARAM_2"));
+
+ ok = false;
+ }
+ else
+ {
+ UINT j;
+ char *real_name = candidate->Token[0];
+
+ // There is only one candidate
+ for (j = 0;j < num_param;j++)
+ {
+ if (StrCmpi(param[j].Name, real_name) == 0)
+ {
+ param[j].Tmp = param_list->Token[i];
+ }
+ }
+ }
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ // No candidate
+ UniFormat(tmp, sizeof(tmp), _UU("CON_INVALID_PARAM"), param_list->Token[i], cmd_name, cmd_name);
+ c->Write(c, tmp);
+
+ ok = false;
+ }
+
+ FreeToken(candidate);
+ }
+
+ if (ok == false)
+ {
+ FreeToken(param_list);
+ FreeToken(real_name_list);
+
+ return NULL;
+ }
+
+ // Creating a list
+ o = NewParamValueList();
+
+ // Read all the parameters of the specified name in the parameter list
+ for (i = 0;i < num_param;i++)
+ {
+ bool prompt_input_value = false;
+ PARAM *p = &param[i];
+
+ if (p->Tmp != NULL || p->PromptProc != NULL)
+ {
+ wchar_t *name = CopyStrToUni(p->Name);
+ wchar_t *tmp;
+ wchar_t *str;
+
+ if (p->Tmp != NULL)
+ {
+ tmp = CopyStrToUni(p->Tmp);
+ }
+ else
+ {
+ tmp = CopyStrToUni(p->Name);
+ }
+
+ str = ParseCommand(command, tmp);
+ Free(tmp);
+ if (str != NULL)
+ {
+ wchar_t *unistr;
+ bool ret;
+EVAL_VALUE:
+ // Reading succeeded
+ unistr = str;
+
+ if (p->EvalProc != NULL)
+ {
+ // Evaluate the value if EvalProc is specified
+ ret = p->EvalProc(c, unistr, p->EvalProcParam);
+ }
+ else
+ {
+ // Accept any value if EvalProc is not specified
+ ret = true;
+ }
+
+ if (ret == false)
+ {
+ // The specified value is invalid
+ if (p->PromptProc == NULL)
+ {
+ // Cancel
+ ok = false;
+ Free(name);
+ Free(str);
+ break;
+ }
+ else
+ {
+ // Request to re-enter
+ Free(str);
+ str = NULL;
+ goto SHOW_PROMPT;
+ }
+ }
+ else
+ {
+ PARAM_VALUE *v;
+ // Finished loading, add it to the list
+ v = ZeroMalloc(sizeof(PARAM_VALUE));
+ v->Name = CopyStr(p->Name);
+ v->StrValue = CopyUniToStr(str);
+ v->UniStrValue = CopyUniStr(str);
+ v->IntValue = ToInt(v->StrValue);
+ Insert(o, v);
+ }
+ }
+ else
+ {
+ // Failed to read. The parameter is not specified
+ if (p->PromptProc != NULL)
+ {
+ wchar_t *tmp;
+SHOW_PROMPT:
+ // Prompt because it is a mandatory parameter
+ tmp = p->PromptProc(c, p->PromptProcParam);
+ if (tmp == NULL)
+ {
+ // User canceled
+ ok = false;
+ Free(str);
+ Free(name);
+ break;
+ }
+ else
+ {
+ // Entered by the user
+ c->Write(c, L"");
+ str = tmp;
+ prompt_input_value = true;
+ goto EVAL_VALUE;
+ }
+ }
+ }
+
+ Free(str);
+ Free(name);
+ }
+ }
+
+ FreeToken(param_list);
+ FreeToken(real_name_list);
+
+ if (ok)
+ {
+ return o;
+ }
+ else
+ {
+ FreeParamValueList(o);
+ return NULL;
+ }
+}
+
+// Acquisition of [Yes] or [No]
+bool GetParamYes(LIST *o, char *name)
+{
+ char *s;
+ char tmp[64];
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ s = GetParamStr(o, name);
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), s);
+ Trim(tmp);
+
+ if (StartWith(tmp, "y"))
+ {
+ return true;
+ }
+
+ if (StartWith(tmp, "t"))
+ {
+ return true;
+ }
+
+ if (ToInt(tmp) != 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Acquisition of parameter value Int
+UINT GetParamInt(LIST *o, char *name)
+{
+ PARAM_VALUE *v;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ v = FindParamValue(o, name);
+ if (v == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ return v->IntValue;
+ }
+}
+
+// Acquisition of parameter value Unicode string
+wchar_t *GetParamUniStr(LIST *o, char *name)
+{
+ PARAM_VALUE *v;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ v = FindParamValue(o, name);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ return v->UniStrValue;
+ }
+}
+
+// Acquisition of the parameter value string
+char *GetParamStr(LIST *o, char *name)
+{
+ PARAM_VALUE *v;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ v = FindParamValue(o, name);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ return v->StrValue;
+ }
+}
+
+// Acquisition of parameter value
+PARAM_VALUE *FindParamValue(LIST *o, char *name)
+{
+ PARAM_VALUE t, *ret;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ if (name == NULL)
+ {
+ name = "";
+ }
+
+ Zero(&t, sizeof(t));
+ t.Name = name;
+
+ ret = Search(o, &t);
+
+ return ret;
+}
+
+// Release of the parameter value list
+void FreeParamValueList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PARAM_VALUE *v = LIST_DATA(o, i);
+
+ Free(v->StrValue);
+ Free(v->UniStrValue);
+ Free(v->Name);
+ Free(v);
+ }
+
+ ReleaseList(o);
+}
+
+// Parameter value list sort function
+int CmpParamValue(void *p1, void *p2)
+{
+ PARAM_VALUE *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(PARAM_VALUE **)p1;
+ v2 = *(PARAM_VALUE **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ if (IsEmptyStr(v1->Name) && IsEmptyStr(v2->Name))
+ {
+ return 0;
+ }
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// Generation of the parameter value list
+LIST *NewParamValueList()
+{
+ return NewListFast(CmpParamValue);
+}
+
+// Get the list of parameter names that were included in the entered command
+TOKEN_LIST *GetCommandNameList(wchar_t *str)
+{
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+
+ Free(ParseCommandEx(str, L"dummy_str", &t));
+
+ return t;
+}
+
+// Get the commands that start with the specified name
+wchar_t *ParseCommand(wchar_t *str, wchar_t *name)
+{
+ return ParseCommandEx(str, name, NULL);
+}
+wchar_t *ParseCommandEx(wchar_t *str, wchar_t *name, TOKEN_LIST **param_list)
+{
+ UNI_TOKEN_LIST *t;
+ UINT i;
+ wchar_t *tmp;
+ wchar_t *ret = NULL;
+ LIST *o;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+ if (name != NULL && UniIsEmptyStr(name))
+ {
+ name = NULL;
+ }
+
+ o = NULL;
+ if (param_list != NULL)
+ {
+ o = NewListFast(CompareStr);
+ }
+
+ tmp = CopyUniStr(str);
+ UniTrim(tmp);
+
+ i = UniSearchStrEx(tmp, L"/CMD ", 0, false);
+
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
+ {
+ i = INFINITE;
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"/CMD\t", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"/CMD:", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"/CMD=", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"-CMD ", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"-CMD\t", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"-CMD:", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
+ {
+ i = INFINITE;
+ }
+ }
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(tmp, L"-CMD=", 0, false);
+ if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
+ {
+ i = INFINITE;
+ }
+ }
+
+ if (i != INFINITE)
+ {
+ char *s = CopyStr("CMD");
+ if (InsertStr(o, s) == false)
+ {
+ Free(s);
+ }
+ if (UniStrCmpi(name, L"CMD") == 0)
+ {
+ ret = CopyUniStr(&str[i + 5]);
+ UniTrim(ret);
+ }
+ else
+ {
+ tmp[i] = 0;
+ }
+ }
+
+ if (ret == NULL)
+ {
+ t = UniParseCmdLine(tmp);
+
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *token = t->Token[i];
+
+ if ((token[0] == L'-' && token[1] != L'-') ||
+ (UniStrCmpi(token, L"--help") == 0) ||
+ (token[0] == L'/' && token[1] != L'/'))
+ {
+ UINT i;
+
+ // Named parameter
+ // Examine whether there is a colon character
+
+ if (UniStrCmpi(token, L"--help") == 0)
+ {
+ token++;
+ }
+
+ i = UniSearchStrEx(token, L":", 0, false);
+ if (i == INFINITE)
+ {
+ i = UniSearchStrEx(token, L"=", 0, false);
+ }
+ if (i != INFINITE)
+ {
+ wchar_t *tmp;
+ char *a;
+
+ // There is a colon character
+ tmp = CopyUniStr(token);
+ tmp[i] = 0;
+
+ a = CopyUniToStr(&tmp[1]);
+ if (InsertStr(o, a) == false)
+ {
+ Free(a);
+ }
+
+ if (UniStrCmpi(name, &tmp[1]) == 0)
+ {
+ if (ret == NULL)
+ {
+ // Content
+ ret = UniCopyStr(&token[i + 1]);
+ }
+ }
+
+ Free(tmp);
+ }
+ else
+ {
+ // There is no colon character
+ char *a;
+
+ a = CopyUniToStr(&token[1]);
+ if (InsertStr(o, a) == false)
+ {
+ Free(a);
+ }
+
+ if (UniStrCmpi(name, &token[1]) == 0)
+ {
+ if (ret == NULL)
+ {
+ // Empty character
+ ret = UniCopyStr(L"");
+ }
+ }
+ }
+ }
+ else
+ {
+ // Nameless argument
+ if (name == NULL)
+ {
+ if (ret == NULL)
+ {
+ if (token[0] == L'-' && token[1] == L'-')
+ {
+ ret = UniCopyStr(&token[1]);
+ }
+ else if (token[0] == L'/' && token[1] == L'/')
+ {
+ ret = UniCopyStr(&token[1]);
+ }
+ else
+ {
+ ret = UniCopyStr(token);
+ }
+ }
+ }
+ }
+ }
+
+ UniFreeToken(t);
+ }
+ }
+
+ Free(tmp);
+
+ if (o != NULL)
+ {
+ TOKEN_LIST *t = ZeroMalloc(sizeof(TOKEN_LIST));
+ UINT i;
+
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ *param_list = t;
+ }
+
+ if (UniStrCmpi(ret, L"none") == 0 || UniStrCmpi(ret, L"null") == 0)
+ {
+ // Null and none are reserved words
+ ret[0] = 0;
+ }
+
+ return ret;
+}
+char *ParseCommandA(wchar_t *str, char *name)
+{
+ wchar_t *tmp1, *tmp2;
+ char *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ if (name != NULL)
+ {
+ tmp1 = CopyStrToUni(name);
+ }
+ else
+ {
+ tmp1 = NULL;
+ }
+
+ tmp2 = ParseCommand(str, tmp1);
+
+ if (tmp2 == NULL)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = CopyUniToStr(tmp2);
+ Free(tmp2);
+ }
+
+ Free(tmp1);
+
+ return ret;
+}
+
+// Password prompt
+bool PasswordPrompt(char *password, UINT size)
+{
+ UINT wp;
+ bool escape = false;
+ void *console;
+ // Validate arguments
+ if (password == NULL || size <= 1)
+ {
+ if (size >= 1)
+ {
+ password[0] = 0;
+ }
+ return false;
+ }
+
+ wp = 0;
+
+ Zero(password, size);
+
+ console = SetConsoleRaw();
+
+ while (true)
+ {
+ int c;
+
+#ifdef OS_WIN32
+ c = getch();
+#else // OS_WIN32
+ c = getc(stdin);
+#endif // OS_WIN32
+
+ if (c >= 0x20 && c <= 0x7E)
+ {
+ // Character
+ if ((wp + 1) < size)
+ {
+ password[wp++] = (char)c;
+ putc('*', stdout);
+ }
+ }
+ else if (c == 0x03)
+ {
+ // Break
+ exit(0);
+ }
+ else if (c == 0x04 || c == 0x1a || c == 0x0D || c==0x0A)
+ {
+ // Exit
+ if (c == 0x04 || c == 0x1a)
+ {
+ escape = true;
+ }
+ break;
+ }
+ else if (c == 0xE0)
+ {
+ // Read one more character
+ c = getch();
+ if (c == 0x4B || c == 0x53)
+ {
+ // Backspace
+ goto BACKSPACE;
+ }
+ }
+ else if (c == 0x08)
+ {
+BACKSPACE:
+ // Backspace
+ if (wp >= 1)
+ {
+ password[--wp] = 0;
+ putc(0x08, stdout);
+ putc(' ', stdout);
+ putc(0x08, stdout);
+ }
+ }
+ }
+ Print("\n");
+
+ RestoreConsole(console);
+
+ return (escape ? false : true);
+}
+
+// Show the prompt
+wchar_t *Prompt(wchar_t *prompt_str)
+{
+ wchar_t *ret = NULL;
+ wchar_t *tmp = NULL;
+ // Validate arguments
+ if (prompt_str == NULL)
+ {
+ prompt_str = L"";
+ }
+
+#ifdef OS_WIN32
+ UniPrint(L"%s", prompt_str);
+ tmp = Malloc(MAX_PROMPT_STRSIZE);
+ if (fgetws(tmp, MAX_PROMPT_STRSIZE - 1, stdin) != NULL)
+ {
+ bool escape = false;
+ UINT i, len;
+
+ len = UniStrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == 0x04 || tmp[i] == 0x1A)
+ {
+ escape = true;
+ break;
+ }
+ }
+
+ if (escape == false)
+ {
+ UniTrimCrlf(tmp);
+
+ ret = UniCopyStr(tmp);
+ }
+ }
+ Free(tmp);
+#else // OS_WIN32
+ {
+ char *prompt = CopyUniToStr(prompt_str);
+ char *s = readline(prompt);
+ Free(prompt);
+
+ if (s != NULL)
+ {
+ TrimCrlf(s);
+ Trim(s);
+
+ if (IsEmptyStr(s) == false)
+ {
+ add_history(s);
+ }
+
+ ret = CopyStrToUni(s);
+
+ free(s);
+ }
+ }
+#endif // OS_WIN32
+
+ if (ret == NULL)
+ {
+ Print("\n");
+ }
+
+ return ret;
+}
+char *PromptA(wchar_t *prompt_str)
+{
+ wchar_t *str = Prompt(prompt_str);
+
+ if (str == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ char *ret = CopyUniToStr(str);
+
+ Free(str);
+ return ret;
+ }
+}
+
+// Set the console to raw mode
+void *SetConsoleRaw()
+{
+#ifdef OS_UNIX
+ struct termios t, *ret;
+
+ Zero(&t, sizeof(t));
+ if (tcgetattr(0, &t) != 0)
+ {
+ // Failed
+ return NULL;
+ }
+
+ // Copy the current settings
+ ret = Clone(&t, sizeof(t));
+
+ // Change the settings
+ t.c_lflag &= (~ICANON);
+ t.c_lflag &= (~ECHO);
+ t.c_cc[VTIME] = 0;
+ t.c_cc[VMIN] = 1;
+ tcsetattr(0, TCSANOW, &t);
+
+ return ret;
+#else // OS_UNIX
+ return Malloc(0);
+#endif // OS_UNIX
+}
+
+// Restore the mode of the console
+void RestoreConsole(void *p)
+{
+#ifdef OS_UNIX
+ struct termios *t;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ t = (struct termios *)p;
+
+ // Restore the settings
+ tcsetattr(0, TCSANOW, t);
+
+ Free(t);
+#else // OS_UNIX
+ if (p != NULL)
+ {
+ Free(p);
+ }
+#endif // OS_UNIX
+}
+
+////////////////////////////
+// Local console function
+
+// Creating a new local console
+CONSOLE *NewLocalConsole(wchar_t *infile, wchar_t *outfile)
+{
+ IO *in_io = NULL, *out_io = NULL;
+ CONSOLE *c = ZeroMalloc(sizeof(CONSOLE));
+ LOCAL_CONSOLE_PARAM *p;
+ UINT old_size = 0;
+
+#ifdef OS_WIN32
+ if (MsGetConsoleWidth() == 80)
+ {
+ //old_size = MsSetConsoleWidth(WIN32_DEFAULT_CONSOLE_WIDTH);
+ }
+#endif // OS_WIN32
+
+ c->ConsoleType = CONSOLE_LOCAL;
+ c->Free = ConsoleLocalFree;
+ c->ReadLine = ConsoleLocalReadLine;
+ c->ReadPassword = ConsoleLocalReadPassword;
+ c->Write = ConsoleLocalWrite;
+ c->GetWidth = ConsoleLocalGetWidth;
+
+ if (UniIsEmptyStr(infile) == false)
+ {
+ // Input file is specified
+ in_io = FileOpenW(infile, false);
+ if (in_io == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_ERROR"), infile);
+ c->Write(c, tmp);
+ Free(c);
+ return NULL;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_START"), infile);
+ c->Write(c, tmp);
+ }
+ }
+
+ if (UniIsEmptyStr(outfile) == false)
+ {
+ // Output file is specified
+ out_io = FileCreateW(outfile);
+ if (out_io == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_ERROR"), outfile);
+ c->Write(c, tmp);
+ Free(c);
+
+ if (in_io != NULL)
+ {
+ FileClose(in_io);
+ }
+ return NULL;
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_START"), outfile);
+ c->Write(c, tmp);
+ }
+ }
+
+ p = ZeroMalloc(sizeof(LOCAL_CONSOLE_PARAM));
+ c->Param = p;
+
+ p->InFile = in_io;
+ p->OutFile = out_io;
+ p->Win32_OldConsoleWidth = old_size;
+
+ if (in_io != NULL)
+ {
+ UINT size;
+ void *buf;
+
+ size = FileSize(in_io);
+ buf = ZeroMalloc(size + 1);
+ FileRead(in_io, buf, size);
+
+ p->InBuf = NewBuf();
+ WriteBuf(p->InBuf, buf, size);
+ Free(buf);
+
+ p->InBuf->Current = 0;
+ }
+
+ return c;
+}
+
+// Release Console
+void ConsoleLocalFree(CONSOLE *c)
+{
+ LOCAL_CONSOLE_PARAM *p;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ p = (LOCAL_CONSOLE_PARAM *)c->Param;
+
+#ifdef OS_WIN32
+ if (p->Win32_OldConsoleWidth != 0)
+ {
+ MsSetConsoleWidth(p->Win32_OldConsoleWidth);
+ }
+#endif // OS_WIN32
+
+ if (p != NULL)
+ {
+ if (p->InFile != NULL)
+ {
+ FileClose(p->InFile);
+ FreeBuf(p->InBuf);
+ }
+
+ if (p->OutFile != NULL)
+ {
+ FileClose(p->OutFile);
+ }
+
+ Free(p);
+ }
+
+ // Memory release
+ Free(c);
+}
+
+// Get the width of the screen
+UINT ConsoleLocalGetWidth(CONSOLE *c)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+
+#ifdef OS_WIN32
+ ret = MsGetConsoleWidth();
+#else // OS_WIN32
+ {
+ struct winsize t;
+
+ Zero(&t, sizeof(t));
+
+ if (ioctl(1, TIOCGWINSZ, &t) == 0)
+ {
+ ret = t.ws_col;
+ }
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Read one line from the console
+wchar_t *ConsoleLocalReadLine(CONSOLE *c, wchar_t *prompt, bool nofile)
+{
+ wchar_t *ret;
+ LOCAL_CONSOLE_PARAM *p;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+ p = (LOCAL_CONSOLE_PARAM *)c->Param;
+ if (prompt == NULL)
+ {
+ prompt = L">";
+ }
+
+ ConsoleWriteOutFile(c, prompt, false);
+
+ if (nofile == false && p->InBuf != NULL)
+ {
+ // Read the next line from the file
+ ret = ConsoleReadNextFromInFile(c);
+
+ if (ret != NULL)
+ {
+ // Display the pseudo prompt
+ UniPrint(L"%s", prompt);
+
+ // Display on the screen
+ UniPrint(L"%s\n", ret);
+ }
+ }
+ else
+ {
+ // Read the following line from the console
+ ret = Prompt(prompt);
+ }
+
+ if (ret != NULL)
+ {
+ ConsoleWriteOutFile(c, ret, true);
+ }
+ else
+ {
+ ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);
+ }
+
+ return ret;
+}
+
+// Read the password from the console
+char *ConsoleLocalReadPassword(CONSOLE *c, wchar_t *prompt)
+{
+ char tmp[64];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+ if (prompt == NULL)
+ {
+ prompt = L"Password>";
+ }
+
+ UniPrint(L"%s", prompt);
+ ConsoleWriteOutFile(c, prompt, false);
+
+ if (PasswordPrompt(tmp, sizeof(tmp)))
+ {
+ ConsoleWriteOutFile(c, L"********", true);
+ return CopyStr(tmp);
+ }
+ else
+ {
+ ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);
+ return NULL;
+ }
+}
+
+// Display a string to the console
+bool ConsoleLocalWrite(CONSOLE *c, wchar_t *str)
+{
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ UniPrint(L"%s%s", str, (UniEndWith(str, L"\n") ? L"" : L"\n"));
+
+ ConsoleWriteOutFile(c, str, true);
+
+ return true;
+}
+
+// Read the next line from the input file
+wchar_t *ConsoleReadNextFromInFile(CONSOLE *c)
+{
+ LOCAL_CONSOLE_PARAM *p;
+ char *str;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ p = (LOCAL_CONSOLE_PARAM *)c->Param;
+
+ if (p->InBuf == NULL)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ str = CfgReadNextLine(p->InBuf);
+
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ Trim(str);
+
+ if (IsEmptyStr(str) == false)
+ {
+ UINT size;
+ wchar_t *ret;
+
+ size = CalcUtf8ToUni((BYTE *)str, StrLen(str));
+ ret = ZeroMalloc(size + 32);
+ Utf8ToUni(ret, size, (BYTE *)str, StrLen(str));
+
+ Free(str);
+
+ return ret;
+ }
+
+ Free(str);
+ }
+}
+
+// Write when the output file is specified
+void ConsoleWriteOutFile(CONSOLE *c, wchar_t *str, bool add_last_crlf)
+{
+ LOCAL_CONSOLE_PARAM *p;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return;
+ }
+
+ p = (LOCAL_CONSOLE_PARAM *)c->Param;
+
+ if (p != NULL && p->OutFile != NULL)
+ {
+ wchar_t *tmp = UniNormalizeCrlf(str);
+ UINT utf8_size;
+ UCHAR *utf8;
+
+ utf8_size = CalcUniToUtf8(tmp);
+ utf8 = ZeroMalloc(utf8_size + 1);
+ UniToUtf8(utf8, utf8_size + 1, tmp);
+
+ FileWrite(p->OutFile, utf8, utf8_size);
+
+ if (UniEndWith(str, L"\n") == false && add_last_crlf)
+ {
+ char *crlf = "\r\n";
+ FileWrite(p->OutFile, "\r\n", StrLen(crlf));
+ }
+
+ Free(utf8);
+ Free(tmp);
+ }
+
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Console.h b/src/Cedar/Console.h
new file mode 100644
index 00000000..45f111a6
--- /dev/null
+++ b/src/Cedar/Console.h
@@ -0,0 +1,222 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Console.h
+// Header of Console.c
+
+#ifndef CONSOLE_H
+#define CONSOLE_H
+
+// Constant
+#define MAX_PROMPT_STRSIZE 65536
+#define WIN32_DEFAULT_CONSOLE_WIDTH 100
+
+// Types of console
+#define CONSOLE_LOCAL 0 // Local console
+#define CONSOLE_CSV 1 // CSV output mode
+
+// Parameters completion prompt function
+typedef wchar_t *(PROMPT_PROC)(CONSOLE *c, void *param);
+
+// Parameter validation prompt function
+typedef bool (EVAL_PROC)(CONSOLE *c, wchar_t *str, void *param);
+
+// Definition of the parameter item
+struct PARAM
+{
+ char *Name; // Parameter name
+ PROMPT_PROC *PromptProc; // Prompt function that automatically invoked if the parameter is not specified
+ // (This is not called in the case of NULL)
+ void *PromptProcParam; // Any pointers to pass to the prompt function
+ EVAL_PROC *EvalProc; // Parameter string validation function
+ void *EvalProcParam; // Any pointers to be passed to the validation function
+ char *Tmp; // Temporary variable
+};
+
+// Parameter value of the internal data
+struct PARAM_VALUE
+{
+ char *Name; // Name
+ char *StrValue; // String value
+ wchar_t *UniStrValue; // Unicode string value
+ UINT IntValue; // Integer value
+};
+
+// Console service structure
+struct CONSOLE
+{
+ UINT ConsoleType; // Type of console
+ UINT RetCode; // The last exit code
+ void *Param; // Data of any
+ void (*Free)(CONSOLE *c); // Release function
+ wchar_t *(*ReadLine)(CONSOLE *c, wchar_t *prompt, bool nofile); // Function to read one line
+ char *(*ReadPassword)(CONSOLE *c, wchar_t *prompt); // Function to read the password
+ bool (*Write)(CONSOLE *c, wchar_t *str); // Function to write a string
+ UINT (*GetWidth)(CONSOLE *c); // Get the width of the screen
+};
+
+// Local console parameters
+struct LOCAL_CONSOLE_PARAM
+{
+ IO *InFile; // Input file
+ BUF *InBuf; // Input buffer
+ IO *OutFile; // Output file
+ UINT Win32_OldConsoleWidth; // Previous console size
+};
+
+// Command procedure
+typedef UINT (COMMAND_PROC)(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+
+// Definition of command
+struct CMD
+{
+ char *Name; // Command name
+ COMMAND_PROC *Proc; // Procedure function
+};
+
+// Evaluate the minimum / maximum value of the parameter
+struct CMD_EVAL_MIN_MAX
+{
+ char *StrName;
+ UINT MinValue, MaxValue;
+};
+
+
+// Function prototype
+wchar_t *Prompt(wchar_t *prompt_str);
+char *PromptA(wchar_t *prompt_str);
+bool PasswordPrompt(char *password, UINT size);
+void *SetConsoleRaw();
+void RestoreConsole(void *p);
+wchar_t *ParseCommandEx(wchar_t *str, wchar_t *name, TOKEN_LIST **param_list);
+wchar_t *ParseCommand(wchar_t *str, wchar_t *name);
+TOKEN_LIST *GetCommandNameList(wchar_t *str);
+char *ParseCommandA(wchar_t *str, char *name);
+LIST *NewParamValueList();
+int CmpParamValue(void *p1, void *p2);
+void FreeParamValueList(LIST *o);
+PARAM_VALUE *FindParamValue(LIST *o, char *name);
+char *GetParamStr(LIST *o, char *name);
+wchar_t *GetParamUniStr(LIST *o, char *name);
+UINT GetParamInt(LIST *o, char *name);
+bool GetParamYes(LIST *o, char *name);
+LIST *ParseCommandList(CONSOLE *c, char *cmd_name, wchar_t *command, PARAM param[], UINT num_param);
+bool IsNameInRealName(char *input_name, char *real_name);
+void GetOmissionName(char *dst, UINT size, char *src);
+bool IsOmissionName(char *input_name, char *real_name);
+TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list);
+bool SeparateCommandAndParam(wchar_t *src, char **cmd, wchar_t **param);
+UINT GetConsoleWidth(CONSOLE *c);
+bool DispatchNextCmd(CONSOLE *c, char *prompt, CMD cmd[], UINT num_cmd, void *param);
+bool DispatchNextCmdEx(CONSOLE *c, wchar_t *exec_command, char *prompt, CMD cmd[], UINT num_cmd, void *param);
+void PrintCandidateHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *candidate_list, UINT left_space);
+UNI_TOKEN_LIST *SeparateStringByWidth(wchar_t *str, UINT width);
+UINT GetNextWordWidth(wchar_t *str);
+bool IsWordChar(wchar_t c);
+void GetCommandHelpStr(char *command_name, wchar_t **description, wchar_t **args, wchar_t **help);
+void GetCommandParamHelpStr(char *command_name, char *param_name, wchar_t **description);
+bool CmdEvalMinMax(CONSOLE *c, wchar_t *str, void *param);
+wchar_t *CmdPrompt(CONSOLE *c, void *param);
+bool CmdEvalNotEmpty(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalInt1(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalIsFile(CONSOLE *c, wchar_t *str, void *param);
+bool CmdEvalSafe(CONSOLE *c, wchar_t *str, void *param);
+void PrintCmdHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *param_list);
+int CompareCandidateStr(void *p1, void *p2);
+bool IsHelpStr(char *str);
+
+CONSOLE *NewLocalConsole(wchar_t *infile, wchar_t *outfile);
+void ConsoleLocalFree(CONSOLE *c);
+wchar_t *ConsoleLocalReadLine(CONSOLE *c, wchar_t *prompt, bool nofile);
+char *ConsoleLocalReadPassword(CONSOLE *c, wchar_t *prompt);
+bool ConsoleLocalWrite(CONSOLE *c, wchar_t *str);
+void ConsoleWriteOutFile(CONSOLE *c, wchar_t *str, bool add_last_crlf);
+wchar_t *ConsoleReadNextFromInFile(CONSOLE *c);
+UINT ConsoleLocalGetWidth(CONSOLE *c);
+
+
+#endif // CONSOLE_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/DDNS.c b/src/Cedar/DDNS.c
new file mode 100644
index 00000000..a74bb7a3
--- /dev/null
+++ b/src/Cedar/DDNS.c
@@ -0,0 +1,984 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// DDNS.c
+// Dynamic DNS Client
+
+#include "CedarPch.h"
+
+// Get the current status of the DDNS client
+void DCGetStatus(DDNS_CLIENT *c, DDNS_CLIENT_STATUS *st)
+{
+ // Validate arguments
+ if (c == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Zero(st, sizeof(DDNS_CLIENT_STATUS));
+
+ Lock(c->Lock);
+ {
+ st->Err_IPv4 = c->Err_IPv4;
+ st->Err_IPv6 = c->Err_IPv6;
+
+ StrCpy(st->CurrentHostName, sizeof(st->CurrentHostName), c->CurrentHostName);
+ StrCpy(st->CurrentFqdn, sizeof(st->CurrentFqdn), c->CurrentFqdn);
+ StrCpy(st->DnsSuffix, sizeof(st->DnsSuffix), c->DnsSuffix);
+ StrCpy(st->CurrentIPv4, sizeof(st->CurrentIPv4), c->CurrentIPv4);
+ StrCpy(st->CurrentIPv6, sizeof(st->CurrentIPv6), c->CurrentIPv6);
+
+ StrCpy(st->CurrentAzureIp, sizeof(st->CurrentAzureIp), c->CurrentAzureIp);
+ st->CurrentAzureTimestamp = c->CurrentAzureTimestamp;
+ StrCpy(st->CurrentAzureSignature, sizeof(st->CurrentAzureSignature), c->CurrentAzureSignature);
+ StrCpy(st->AzureCertHash, sizeof(st->AzureCertHash), c->AzureCertHash);
+
+ Copy(&st->InternetSetting, &c->InternetSetting, sizeof(INTERNET_SETTING));
+ }
+ Unlock(c->Lock);
+}
+
+// Set the Internet settings
+void DCSetInternetSetting(DDNS_CLIENT *c, INTERNET_SETTING *t)
+{
+ // Validate arguments
+ if (c == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Copy(&c->InternetSetting, t, sizeof(INTERNET_SETTING));
+}
+
+// Get the Internet settings
+void DCGetInternetSetting(DDNS_CLIENT *c, INTERNET_SETTING *t)
+{
+ // Validate arguments
+ if (c == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Copy(t, &c->InternetSetting, sizeof(INTERNET_SETTING));
+}
+
+// Changing the host name
+UINT DCChangeHostName(DDNS_CLIENT *c, char *hostname)
+{
+ UINT ret;
+ DDNS_REGISTER_PARAM p;
+ // Validate arguments
+ if (c == NULL || hostname == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ if (StrLen(hostname) > 32)
+ {
+ // The host name is too long
+ return ERR_DDNS_HOSTNAME_TOO_LONG;
+ }
+
+ Zero(&p, sizeof(p));
+
+ StrCpy(p.NewHostname, sizeof(p.NewHostname), hostname);
+
+ // Use one of IPv4 or IPv6 if it seems to be communication
+ if (c->Err_IPv4 == ERR_NO_ERROR)
+ {
+ // IPv4
+ ret = DCRegister(c, false, &p, NULL);
+ }
+ else if (c->Err_IPv6 == ERR_NO_ERROR)
+ {
+ // IPv6
+ ret = DCRegister(c, true, &p, NULL);
+ }
+ else
+ {
+ // Try both
+ ret = DCRegister(c, true, &p, NULL);
+ if (ret != ERR_NO_ERROR)
+ {
+ ret = DCRegister(c, false, &p, NULL);
+ }
+ }
+
+ if (ret == ERR_NO_ERROR)
+ {
+ DDNS_CLIENT_STATUS st;
+
+ DCGetStatus(c, &st);
+
+ SiApplyAzureConfig(c->Cedar->Server, &st);
+ }
+
+ return ret;
+}
+
+// DDNS client thread
+void DCThread(THREAD *thread, void *param)
+{
+ DDNS_CLIENT *c;
+ INTERRUPT_MANAGER *interrput;
+ UINT last_ip_hash = 0;
+ void *route_change_poller = NULL;
+ bool last_time_ip_changed = false;
+ UINT last_azure_ddns_trigger_int = 0;
+ UINT last_vgs_ddns_trigger_int = 0;
+ UINT n;
+ INTERNET_SETTING last_t;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ c = (DDNS_CLIENT *)param;
+
+ interrput = NewInterruptManager();
+
+ route_change_poller = NewRouteChange();
+ IsRouteChanged(route_change_poller);
+
+ Zero(&last_t, sizeof(last_t));
+
+ n = 0;
+
+ while (c->Halt == false)
+ {
+ UINT ip_hash = GetHostIPAddressHash32();
+ UINT interval;
+ UINT64 now = Tick64();
+ bool ip_changed = false;
+ bool azure_client_triggered = false;
+ bool internet_setting_changed = false;
+ bool vgs_server_triggered = false;
+
+
+ if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
+ {
+ if (c->Cedar->Server->AzureClient->DDnsTriggerInt != last_azure_ddns_trigger_int)
+ {
+ azure_client_triggered = true;
+ last_azure_ddns_trigger_int = c->Cedar->Server->AzureClient->DDnsTriggerInt;
+ last_time_ip_changed = false;
+ Debug("DDNS Thread Triggered by AzureClient.\n");
+ }
+ }
+
+ if (Cmp(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
+ {
+ Copy(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING));
+ internet_setting_changed = true;
+ last_time_ip_changed = false;
+ }
+
+ if (ip_hash != last_ip_hash)
+ {
+ last_time_ip_changed = false;
+ Debug("DDNS Thread Triggered by IP Hash Changed.\n");
+ }
+
+ if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)) || azure_client_triggered || internet_setting_changed || vgs_server_triggered)
+ {
+ if (last_time_ip_changed == false)
+ {
+ // Call all getting functions from the beginning if the routing
+ // table or the IP address of this host has changed
+ c->NextRegisterTick_IPv4 = 0;
+ c->NextRegisterTick_IPv6 = 0;
+ c->NextGetMyIpTick_IPv4 = 0;
+ c->NextGetMyIpTick_IPv6 = 0;
+
+ last_ip_hash = ip_hash;
+
+ last_time_ip_changed = true;
+
+ ip_changed = true;
+
+ Debug("DDNS Internet Condition Changed.\n");
+ }
+ }
+ else
+ {
+ last_time_ip_changed = false;
+ }
+
+ if ((n++) >= 1)
+ {
+ // Self IPv4 address acquisition
+ if (c->NextGetMyIpTick_IPv4 == 0 || now >= c->NextGetMyIpTick_IPv4)
+ {
+ UINT next_interval;
+ char ip[MAX_SIZE];
+
+ Zero(ip, sizeof(ip));
+ c->Err_IPv4_GetMyIp = DCGetMyIp(c, false, ip, sizeof(ip), NULL);
+
+ if (c->Err_IPv4_GetMyIp == ERR_NO_ERROR)
+ {
+ if (StrCmpi(c->LastMyIPv4, ip) != 0)
+ {
+ ip_changed = true;
+ StrCpy(c->LastMyIPv4, sizeof(c->LastMyIPv4), ip);
+ }
+
+ next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
+ }
+ else
+ {
+ if (IsEmptyStr(c->LastMyIPv4) == false)
+ {
+ ip_changed = true;
+ }
+
+ Zero(c->LastMyIPv4, sizeof(c->LastMyIPv4));
+ next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
+ }
+
+ c->NextGetMyIpTick_IPv4 = Tick64() + (UINT64)next_interval;
+
+ AddInterrupt(interrput, c->NextGetMyIpTick_IPv4);
+ }
+
+ // Self IPv6 address acquisition
+ if (c->NextGetMyIpTick_IPv6 == 0 || now >= c->NextGetMyIpTick_IPv6)
+ {
+ UINT next_interval;
+ char ip[MAX_SIZE];
+
+ Zero(ip, sizeof(ip));
+ c->Err_IPv6_GetMyIp = DCGetMyIp(c, true, ip, sizeof(ip), NULL);
+
+ if (c->Err_IPv6_GetMyIp == ERR_NO_ERROR)
+ {
+ if (StrCmpi(c->LastMyIPv6, ip) != 0)
+ {
+ ip_changed = true;
+ StrCpy(c->LastMyIPv6, sizeof(c->LastMyIPv6), ip);
+ }
+
+ next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
+ }
+ else
+ {
+ if (IsEmptyStr(c->LastMyIPv6) == false)
+ {
+ ip_changed = true;
+ }
+
+ Zero(c->LastMyIPv6, sizeof(c->LastMyIPv6));
+ next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
+ }
+
+ c->NextGetMyIpTick_IPv6 = Tick64() + (UINT64)next_interval;
+
+ AddInterrupt(interrput, c->NextGetMyIpTick_IPv6);
+ }
+ }
+
+ if (ip_changed)
+ {
+ c->NextRegisterTick_IPv4 = 0;
+ c->NextRegisterTick_IPv6 = 0;
+ }
+
+ // IPv4 host registration
+ if (c->NextRegisterTick_IPv4 == 0 || now >= c->NextRegisterTick_IPv4)
+ {
+ UINT next_interval;
+
+ c->Err_IPv4 = DCRegister(c, false, NULL, NULL);
+
+ if (c->Err_IPv4 == ERR_NO_ERROR)
+ {
+ next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
+ }
+ else
+ {
+ next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
+ }
+ //next_interval = 0;
+
+ c->NextRegisterTick_IPv4 = Tick64() + (UINT64)next_interval;
+
+ if (true)
+ {
+ DDNS_CLIENT_STATUS st;
+
+ DCGetStatus(c, &st);
+
+ SiApplyAzureConfig(c->Cedar->Server, &st);
+ }
+
+ AddInterrupt(interrput, c->NextRegisterTick_IPv4);
+ }
+
+ if (c->Halt)
+ {
+ break;
+ }
+
+ // IPv6 host registration
+ if (c->NextRegisterTick_IPv6 == 0 || now >= c->NextRegisterTick_IPv6)
+ {
+ UINT next_interval;
+
+ c->Err_IPv6 = DCRegister(c, true, NULL, NULL);
+
+ if (c->Err_IPv6 == ERR_NO_ERROR)
+ {
+ next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
+ }
+ else
+ {
+ next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
+ }
+
+ c->NextRegisterTick_IPv6 = Tick64() + (UINT64)next_interval;
+
+ if (true)
+ {
+ DDNS_CLIENT_STATUS st;
+
+ DCGetStatus(c, &st);
+
+ SiApplyAzureConfig(c->Cedar->Server, &st);
+ }
+
+ AddInterrupt(interrput, c->NextRegisterTick_IPv6);
+ }
+
+ interval = GetNextIntervalForInterrupt(interrput);
+ interval = MIN(interval, 1234);
+
+ if (n == 1)
+ {
+ interval = MIN(interval, 0);
+ }
+
+ if (c->Halt)
+ {
+ break;
+ }
+
+ if (c->KeyChanged)
+ {
+ c->KeyChanged = false;
+ c->NextRegisterTick_IPv4 = c->NextRegisterTick_IPv6 = 0;
+
+ interval = 0;
+ }
+
+ if (last_time_ip_changed)
+ {
+ if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
+ {
+ c->Cedar->Server->AzureClient->IpStatusRevision++;
+ }
+ }
+
+ Wait(c->Event, interval);
+ }
+
+ FreeRouteChange(route_change_poller);
+ FreeInterruptManager(interrput);
+}
+
+// Command to update immediately
+void DCUpdateNow(DDNS_CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->NextRegisterTick_IPv4 = c->NextRegisterTick_IPv6 = 0;
+
+ Set(c->Event);
+}
+
+// Execution of registration
+UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace_v6)
+{
+ char *url;
+ char url2[MAX_SIZE];
+ char url3[MAX_SIZE];
+ PACK *req, *ret;
+ char key_str[MAX_SIZE];
+ UCHAR machine_key[SHA1_SIZE];
+ char machine_key_str[MAX_SIZE];
+ char machine_name[MAX_SIZE];
+ BUF *cert_hash;
+ UINT err = ERR_INTERNAL_ERROR;
+ UCHAR key_hash[SHA1_SIZE];
+ char key_hash_str[MAX_SIZE];
+ bool use_azure = false;
+ char current_azure_ip[MAX_SIZE];
+ INTERNET_SETTING t;
+ UINT build = 0;
+ bool use_https = false;
+ bool use_vgs = false;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Zero(current_azure_ip, sizeof(current_azure_ip));
+
+ GetCurrentMachineIpProcessHash(machine_key);
+ BinToStr(machine_key_str, sizeof(machine_key_str), machine_key, sizeof(machine_key));
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ StrLower(machine_name);
+
+ if (ipv6 == false)
+ {
+ url = DDNS_URL_V4_GLOBAL;
+
+ if (IsUseAlternativeHostname())
+ {
+ url = DDNS_URL_V4_ALT;
+ }
+ }
+ else
+ {
+ url = DDNS_URL_V6_GLOBAL;
+
+ if (IsUseAlternativeHostname())
+ {
+ url = DDNS_URL_V6_ALT;
+ }
+
+ if (replace_v6)
+ {
+ url = replace_v6;
+ }
+ }
+
+ Zero(&t, sizeof(t));
+ if (ipv6 == false)
+ {
+ // Proxy Setting
+ Copy(&t, &c->InternetSetting, sizeof(INTERNET_SETTING));
+ }
+
+ if (ipv6 == false)
+ {
+ // Get the current status of the VPN Azure Client
+ if (c->Cedar->Server != NULL)
+ {
+ AZURE_CLIENT *ac = c->Cedar->Server->AzureClient;
+
+ if (ac != NULL)
+ {
+ use_azure = SiIsAzureEnabled(c->Cedar->Server);
+
+ if (use_azure)
+ {
+ Lock(ac->Lock);
+ {
+ StrCpy(current_azure_ip, sizeof(current_azure_ip), ac->ConnectingAzureIp);
+ }
+ Unlock(ac->Lock);
+ }
+ }
+ }
+ }
+
+ req = NewPack();
+ BinToStr(key_str, sizeof(key_str), c->Key, sizeof(c->Key));
+ StrUpper(key_str);
+ PackAddStr(req, "key", key_str);
+
+ // Build Number
+ build = c->Cedar->Build;
+
+
+ PackAddInt(req, "build", build);
+ PackAddInt(req, "osinfo", GetOsInfo()->OsType);
+ PackAddInt(req, "is_64bit", Is64());
+#ifdef OS_WIN32
+ PackAddInt(req, "is_windows_64bit", MsIs64BitWindows());
+#endif // OS_WIN32
+ PackAddBool(req, "is_softether", true);
+ PackAddBool(req, "is_packetix", false);
+ PackAddStr(req, "machine_key", machine_key_str);
+ PackAddStr(req, "machine_name", machine_name);
+ PackAddInt(req, "lasterror_ipv4", c->Err_IPv4_GetMyIp);
+ PackAddInt(req, "lasterror_ipv6", c->Err_IPv6_GetMyIp);
+ PackAddBool(req, "use_azure", use_azure);
+ PackAddStr(req, "product_str", CEDAR_PRODUCT_STR);
+ PackAddInt(req, "ddns_protocol_version", DDNS_VERSION);
+
+
+ if (use_azure)
+ {
+ Debug("current_azure_ip = %s\n", current_azure_ip);
+ PackAddStr(req, "current_azure_ip", current_azure_ip);
+ }
+
+ HashSha1(key_hash, key_str, StrLen(key_str));
+ BinToStr(key_hash_str, sizeof(key_hash_str), key_hash, sizeof(key_hash));
+ StrLower(key_hash_str);
+
+ if (p != NULL)
+ {
+ if (IsEmptyStr(p->NewHostname) == false)
+ {
+ PackAddStr(req, "new_hostname", p->NewHostname);
+ }
+ }
+
+
+
+ cert_hash = StrToBin(DDNS_CERT_HASH);
+
+ Format(url2, sizeof(url2), "%s?v=%I64u", url, Rand64());
+ Format(url3, sizeof(url3), url2, key_hash_str[0], key_hash_str[1], key_hash_str[2], key_hash_str[3]);
+
+ if (use_https == false)
+ {
+ ReplaceStr(url3, sizeof(url3), url3, "https://", "http://");
+ }
+
+ ReplaceStr(url3, sizeof(url3), url3, ".servers", ".open.servers");
+
+ Debug("WpcCall: %s\n", url3);
+ ret = WpcCallEx(url3, &t, DDNS_CONNECT_TIMEOUT, DDNS_COMM_TIMEOUT, "register", req,
+ NULL, NULL, ((cert_hash != NULL && cert_hash->Size == SHA1_SIZE) ? cert_hash->Buf : NULL), NULL, DDNS_RPC_MAX_RECV_SIZE);
+ Debug("WpcCall Ret: %u\n", ret);
+
+ FreeBuf(cert_hash);
+
+ FreePack(req);
+
+ err = GetErrorFromPack(ret);
+
+ ExtractAndApplyDynList(ret);
+
+ // Status update
+ Lock(c->Lock);
+ {
+ if (err == ERR_NO_ERROR)
+ {
+ char snat_t[MAX_SIZE];
+
+ // Current host name
+ PackGetStr(ret, "current_hostname", c->CurrentHostName, sizeof(c->CurrentHostName));
+ PackGetStr(ret, "current_fqdn", c->CurrentFqdn, sizeof(c->CurrentFqdn));
+ PackGetStr(ret, "current_ipv4", c->CurrentIPv4, sizeof(c->CurrentIPv4));
+ PackGetStr(ret, "current_ipv6", c->CurrentIPv6, sizeof(c->CurrentIPv6));
+ PackGetStr(ret, "dns_suffix", c->DnsSuffix, sizeof(c->DnsSuffix));
+
+ // SecureNAT connectivity check parameters
+ Zero(snat_t, sizeof(snat_t));
+ PackGetStr(ret, "snat_t", snat_t, sizeof(snat_t));
+ NnSetSecureNatTargetHostname(snat_t);
+
+ if (ipv6 == false)
+ {
+ char cert_hash[MAX_SIZE];
+
+ PackGetStr(ret, "current_azure_ip", c->CurrentAzureIp, sizeof(c->CurrentAzureIp));
+ c->CurrentAzureTimestamp = PackGetInt64(ret, "current_azure_timestamp");
+ PackGetStr(ret, "current_azure_signature", c->CurrentAzureSignature, sizeof(c->CurrentAzureSignature));
+
+ Zero(cert_hash, sizeof(cert_hash));
+ PackGetStr(ret, "azure_cert_hash", cert_hash, sizeof(cert_hash));
+
+ if (IsEmptyStr(cert_hash) == false)
+ {
+ StrCpy(c->AzureCertHash, sizeof(c->AzureCertHash), cert_hash);
+ }
+ }
+
+ StrCpy(c->Cedar->CurrentDDnsFqdn, sizeof(c->Cedar->CurrentDDnsFqdn), c->CurrentFqdn);
+
+ Debug("current_hostname=%s, current_fqdn=%s, current_ipv4=%s, current_ipv6=%s, current_azure_ip=%s, CurrentAzureTimestamp=%I64u, CurrentAzureSignature=%s, CertHash=%s\n",
+ c->CurrentHostName, c->CurrentFqdn,
+ c->CurrentIPv4, c->CurrentIPv6,
+ c->CurrentAzureIp, c->CurrentAzureTimestamp, c->CurrentAzureSignature, c->AzureCertHash);
+ }
+ }
+ Unlock(c->Lock);
+
+ if (IsEmptyStr(c->CurrentFqdn) == false)
+ {
+ SetCurrentDDnsFqdn(c->CurrentFqdn);
+ }
+
+
+ FreePack(ret);
+
+ UniDebug(L"DCRegister Error: %s\n", _E(err));
+
+ if (err == ERR_DUPLICATE_DDNS_KEY)
+ {
+ // Key duplication
+ DCGenNewKey(c->Key);
+ c->KeyChanged = true;
+ }
+
+ if (err == ERR_DISCONNECTED)
+ {
+ err = ERR_DDNS_DISCONNECTED;
+ }
+
+ if (IsUseAlternativeHostname() == false)
+ {
+ if (err == ERR_CONNECT_FAILED)
+ {
+ if (ipv6 && replace_v6 == NULL)
+ {
+ UINT type = DetectFletsType();
+
+ if (type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE && err != ERR_NO_ERROR)
+ {
+ err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_EAST_BFLETS);
+ }
+
+ if (type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE && err != ERR_NO_ERROR)
+ {
+ err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_EAST_NGN);
+ }
+
+ if (type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE && err != ERR_NO_ERROR)
+ {
+ err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_WEST_NGN);
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+// Get the self IP address
+UINT DCGetMyIp(DDNS_CLIENT *c, bool ipv6, char *dst, UINT dst_size, char *replace_v6)
+{
+ UINT ret = ERR_INTERNAL_ERROR;
+
+ ret = DCGetMyIpMain(c, ipv6, dst, dst_size, false, replace_v6);
+
+
+ if (ret == ERR_NO_ERROR)
+ {
+ IP ip;
+
+ if (StrToIP(&ip, dst))
+ {
+ if (ipv6 == false && IsIP4(&ip))
+ {
+ SetCurrentGlobalIP(&ip, false);
+ }
+ else if (ipv6 && IsIP6(&ip))
+ {
+ SetCurrentGlobalIP(&ip, true);
+ }
+ }
+ }
+
+ return ret;
+}
+UINT DCGetMyIpMain(DDNS_CLIENT *c, bool ipv6, char *dst, UINT dst_size, bool use_ssl, char *replace_v6)
+{
+ char *url;
+ char url2[MAX_SIZE];
+ UINT ret = ERR_INTERNAL_ERROR;
+ URL_DATA data;
+ BUF *recv;
+ BUF *cert_hash;
+ // Validate arguments
+ if (dst == NULL || c == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ if (ipv6 == false)
+ {
+ url = DDNS_URL2_V4_GLOBAL;
+
+ if (IsUseAlternativeHostname())
+ {
+ url = DDNS_URL2_V4_ALT;
+ }
+ }
+ else
+ {
+ url = DDNS_URL2_V6_GLOBAL;
+
+ if (IsUseAlternativeHostname())
+ {
+ url = DDNS_URL2_V6_ALT;
+ }
+
+ if (replace_v6)
+ {
+ url = replace_v6;
+ }
+ }
+
+ Format(url2, sizeof(url2), "%s?v=%I64u", url, Rand64());
+
+ if (use_ssl)
+ {
+ ReplaceStr(url2, sizeof(url2), url2, "http://", "https://");
+ }
+
+ if (ParseUrl(&data, url2, false, NULL) == false)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ cert_hash = StrToBin(DDNS_CERT_HASH);
+
+ recv = HttpRequest(&data, (ipv6 ? NULL : &c->InternetSetting), DDNS_CONNECT_TIMEOUT, DDNS_COMM_TIMEOUT, &ret, false, NULL, NULL,
+ NULL, ((cert_hash != NULL && cert_hash->Size == SHA1_SIZE) ? cert_hash->Buf : NULL));
+
+ FreeBuf(cert_hash);
+
+ if (recv != NULL)
+ {
+ char *str = ZeroMalloc(recv->Size + 1);
+ Copy(str, recv->Buf, recv->Size);
+
+ if (StartWith(str, "IP=") == false)
+ {
+ ret = ERR_PROTOCOL_ERROR;
+ }
+ else
+ {
+ StrCpy(dst, dst_size, str + 3);
+ ret = ERR_NO_ERROR;
+ }
+
+ Free(str);
+ FreeBuf(recv);
+ }
+
+ if (IsUseAlternativeHostname() == false)
+ {
+ if (ret == ERR_CONNECT_FAILED)
+ {
+ if (ipv6 && replace_v6 == NULL && use_ssl == false)
+ {
+ UINT type = DetectFletsType();
+
+ if (type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE && ret != ERR_NO_ERROR)
+ {
+ ret = DCGetMyIpMain(c, ipv6, dst, dst_size, use_ssl, DDNS_REPLACE_URL2_FOR_EAST_BFLETS);
+ }
+
+ if (type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE && ret != ERR_NO_ERROR)
+ {
+ ret = DCGetMyIpMain(c, ipv6, dst, dst_size, use_ssl, DDNS_REPLACE_URL2_FOR_EAST_NGN);
+ }
+
+ if (type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE && ret != ERR_NO_ERROR)
+ {
+ ret = DCGetMyIpMain(c, ipv6, dst, dst_size, use_ssl, DDNS_REPLACE_URL2_FOR_WEST_NGN);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Creating a DDNS client
+DDNS_CLIENT *NewDDNSClient(CEDAR *cedar, UCHAR *key, INTERNET_SETTING *t)
+{
+ DDNS_CLIENT *c;
+ UCHAR key_hash[SHA1_SIZE];
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(DDNS_CLIENT));
+ c->Cedar = cedar;
+ AddRef(c->Cedar->ref);
+
+ c->Err_IPv4 = c->Err_IPv6 = ERR_TRYING_TO_CONNECT;
+
+ if (key == NULL)
+ {
+ // Create a new key
+ DCGenNewKey(c->Key);
+ }
+ else
+ {
+ // Set the key
+ Copy(c->Key, key, SHA1_SIZE);
+ }
+
+ HashSha1(key_hash, c->Key, sizeof(c->Key));
+
+
+ if (t != NULL)
+ {
+ Copy(&c->InternetSetting, t, sizeof(INTERNET_SETTING));
+ }
+
+ c->Lock = NewLock();
+
+ // Thread creation
+ c->Event = NewEvent();
+ c->Thread = NewThread(DCThread, c);
+
+ return c;
+}
+
+// Release of DDNS client
+void FreeDDNSClient(DDNS_CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Stop the thread
+ c->Halt = true;
+ Set(c->Event);
+
+ WaitThread(c->Thread, INFINITE);
+ ReleaseThread(c->Thread);
+
+ ReleaseEvent(c->Event);
+
+ ReleaseCedar(c->Cedar);
+ DeleteLock(c->Lock);
+
+ Free(c);
+}
+
+// Create a new key
+void DCGenNewKey(UCHAR *key)
+{
+ BUF *b;
+ UINT64 tick;
+ UCHAR hash[SHA1_SIZE];
+ UCHAR rand[SHA1_SIZE];
+ UINT i;
+ // Validate arguments
+ if (key == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+
+ Rand(rand, sizeof(rand));
+ WriteBuf(b, rand, sizeof(rand));
+
+ tick = TickHighres64();
+ WriteBufInt64(b, tick);
+
+ tick = Tick64();
+ WriteBufInt64(b, tick);
+
+ tick = SystemTime64();
+ WriteBufInt64(b, tick);
+
+ GetCurrentMachineIpProcessHash(hash);
+ WriteBuf(b, hash, sizeof(hash));
+
+ HashSha1(key, b->Buf, b->Size);
+ Rand(rand, sizeof(rand));
+
+ for (i = 0;i < SHA1_SIZE;i++)
+ {
+ key[i] = key[i] ^ rand[i];
+ }
+
+ FreeBuf(b);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/DDNS.h b/src/Cedar/DDNS.h
new file mode 100644
index 00000000..a2c05761
--- /dev/null
+++ b/src/Cedar/DDNS.h
@@ -0,0 +1,215 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// DDNS.h
+// Header of DDNS.c
+
+#ifndef DDNS_H
+#define DDNS_H
+
+// Certificate hash
+#define DDNS_CERT_HASH "EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3"
+
+// Destination URL
+#define DDNS_URL_V4_GLOBAL "https://x%c.x%c.x%c.x%c.servers.ddns.softether-network.net/ddns/ddns.aspx"
+#define DDNS_URL_V6_GLOBAL "https://x%c.x%c.x%c.x%c.servers-v6.ddns.softether-network.net/ddns/ddns.aspx"
+#define DDNS_URL2_V4_GLOBAL "http://get-my-ip.ddns.softether-network.net/ddns/getmyip.ashx"
+#define DDNS_URL2_V6_GLOBAL "http://get-my-ip-v6.ddns.softether-network.net/ddns/getmyip.ashx"
+
+#define DDNS_REPLACE_URL_FOR_EAST_BFLETS "https://senet-flets.v6.softether.co.jp/ddns/ddns.aspx"
+#define DDNS_REPLACE_URL_FOR_EAST_NGN "https://senet.aoi.flets-east.jp/ddns/ddns.aspx"
+#define DDNS_REPLACE_URL_FOR_WEST_NGN "https://senet.p-ns.flets-west.jp/ddns/ddns.aspx"
+
+#define DDNS_REPLACE_URL2_FOR_EAST_BFLETS "http://senet-flets.v6.softether.co.jp/ddns/getmyip.ashx"
+#define DDNS_REPLACE_URL2_FOR_EAST_NGN "http://senet.aoi.flets-east.jp/ddns/getmyip.ashx"
+#define DDNS_REPLACE_URL2_FOR_WEST_NGN "http://senet.p-ns.flets-west.jp/ddns/getmyip.ashx"
+
+// For China: Free version
+#define DDNS_URL_V4_ALT "https://x%c.x%c.x%c.x%c.servers.ddns.uxcom.jp/ddns/ddns.aspx"
+#define DDNS_URL_V6_ALT "https://x%c.x%c.x%c.x%c.servers-v6.ddns.uxcom.jp/ddns/ddns.aspx"
+#define DDNS_URL2_V4_ALT "http://get-my-ip.ddns.uxcom.jp/ddns/getmyip.ashx"
+#define DDNS_URL2_V6_ALT "http://get-my-ip-v6.ddns.uxcom.jp/ddns/getmyip.ashx"
+
+#define DDNS_RPC_MAX_RECV_SIZE DYN32(DDNS_RPC_MAX_RECV_SIZE, (128 * 1024 * 1024))
+
+// Connection Timeout
+#define DDNS_CONNECT_TIMEOUT DYN32(DDNS_CONNECT_TIMEOUT, (15 * 1000))
+
+// Communication time-out
+#define DDNS_COMM_TIMEOUT DYN32(DDNS_COMM_TIMEOUT, (60 * 1000))
+
+// Maximum length of the host name
+#define DDNS_MAX_HOSTNAME 31
+
+// DDNS Version
+#define DDNS_VERSION 1
+
+// Period until the next registration in case of success
+#define DDNS_REGISTER_INTERVAL_OK_MIN DYN32(DDNS_REGISTER_INTERVAL_OK_MIN, (1 * 60 * 60 * 1000))
+#define DDNS_REGISTER_INTERVAL_OK_MAX DYN32(DDNS_REGISTER_INTERVAL_OK_MAX, (2 * 60 * 60 * 1000))
+
+// Period until the next registration in case of failure
+#define DDNS_REGISTER_INTERVAL_NG_MIN DYN32(DDNS_REGISTER_INTERVAL_NG_MIN, (1 * 60 * 1000))
+#define DDNS_REGISTER_INTERVAL_NG_MAX DYN32(DDNS_REGISTER_INTERVAL_NG_MAX, (5 * 60 * 1000))
+
+// The self IP address acquisition interval (If last trial succeeded)
+#define DDNS_GETMYIP_INTERVAL_OK_MIN DYN32(DDNS_GETMYIP_INTERVAL_OK_MIN, (10 * 60 * 1000))
+#define DDNS_GETMYIP_INTERVAL_OK_MAX DYN32(DDNS_GETMYIP_INTERVAL_OK_MAX, (20 * 60 * 1000))
+
+// The self IP address acquisition interval (If last trial failed)
+#define DDNS_GETMYIP_INTERVAL_NG_MIN DYN32(DDNS_GETMYIP_INTERVAL_NG_MIN, (1 * 60 * 1000))
+#define DDNS_GETMYIP_INTERVAL_NG_MAX DYN32(DDNS_GETMYIP_INTERVAL_NG_MAX, (5 * 60 * 1000))
+
+// Time difference to communicate with the DDNS server after a predetermined time has elapsed since the VPN Azure is disconnected
+#define DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF DYN32(DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF, (120 * 1000))
+#define DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF_MAX DYN32(DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF_MAX, (10 * 60 * 1000))
+
+// DDNS Client
+struct DDNS_CLIENT
+{
+ CEDAR *Cedar; // Cedar
+ THREAD *Thread; // Thread
+ UCHAR Key[SHA1_SIZE]; // Key
+ LOCK *Lock; // Lock
+ volatile bool Halt; // Halt flag
+ EVENT *Event; // Halt event
+ char CurrentHostName[DDNS_MAX_HOSTNAME + 1]; // Current host name
+ char CurrentFqdn[MAX_SIZE]; // Current FQDN
+ char DnsSuffix[MAX_SIZE]; // DNS suffix
+ char CurrentIPv4[MAX_SIZE]; // Current IPv4 address
+ char CurrentIPv6[MAX_SIZE]; // Current IPv6 address
+ UINT Err_IPv4, Err_IPv6; // Last error
+ UINT Err_IPv4_GetMyIp, Err_IPv6_GetMyIp; // Last error (obtaining self IP address)
+ bool KeyChanged; // Flag to indicate that the key has been changed
+ char LastMyIPv4[MAX_SIZE]; // Self IPv4 address that were acquired on last
+ char LastMyIPv6[MAX_SIZE]; // Self IPv6 address that were acquired on last
+ char CurrentAzureIp[MAX_SIZE]; // IP address of Azure Server to be used
+ UINT64 CurrentAzureTimestamp; // Time stamp to be presented to the Azure Server
+ char CurrentAzureSignature[MAX_SIZE]; // Signature to be presented to the Azure Server
+ char AzureCertHash[MAX_SIZE]; // Azure Server certificate hash
+ INTERNET_SETTING InternetSetting; // Internet connection settings
+
+ UINT64 NextRegisterTick_IPv4, NextRegisterTick_IPv6; // Next register time
+ UINT64 NextGetMyIpTick_IPv4, NextGetMyIpTick_IPv6; // Next self IP acquisition time
+};
+
+// DDNS Register Param
+struct DDNS_REGISTER_PARAM
+{
+ char NewHostname[DDNS_MAX_HOSTNAME + 1]; // Host name after the change
+};
+
+// The current status of the DDNS
+struct DDNS_CLIENT_STATUS
+{
+ UINT Err_IPv4, Err_IPv6; // Last error
+ char CurrentHostName[DDNS_MAX_HOSTNAME + 1]; // Current host name
+ char CurrentFqdn[MAX_SIZE]; // Current FQDN
+ char DnsSuffix[MAX_SIZE]; // DNS suffix
+ char CurrentIPv4[MAX_SIZE]; // Current IPv4 address
+ char CurrentIPv6[MAX_SIZE]; // Current IPv6 address
+ char CurrentAzureIp[MAX_SIZE]; // IP address of Azure Server to be used
+ UINT64 CurrentAzureTimestamp; // Time stamp to be presented to the Azure Server
+ char CurrentAzureSignature[MAX_SIZE]; // Signature to be presented to the Azure Server
+ char AzureCertHash[MAX_SIZE]; // Azure Server certificate hash
+ INTERNET_SETTING InternetSetting; // Internet settings
+};
+
+// Function prototype
+DDNS_CLIENT *NewDDNSClient(CEDAR *cedar, UCHAR *key, INTERNET_SETTING *t);
+void FreeDDNSClient(DDNS_CLIENT *c);
+void DCGenNewKey(UCHAR *key);
+void DCThread(THREAD *thread, void *param);
+UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace_v6);
+UINT DCGetMyIpMain(DDNS_CLIENT *c, bool ipv6, char *dst, UINT dst_size, bool use_ssl, char *replace_v6);
+UINT DCGetMyIp(DDNS_CLIENT *c, bool ipv6, char *dst, UINT dst_size, char *replace_v6);
+void DCUpdateNow(DDNS_CLIENT *c);
+void DCGetStatus(DDNS_CLIENT *c, DDNS_CLIENT_STATUS *st);
+UINT DCChangeHostName(DDNS_CLIENT *c, char *hostname);
+void DCSetInternetSetting(DDNS_CLIENT *c, INTERNET_SETTING *t);
+void DCGetInternetSetting(DDNS_CLIENT *c, INTERNET_SETTING *t);
+
+#endif // DDNS_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Database.c b/src/Cedar/Database.c
new file mode 100644
index 00000000..5e1b3dd1
--- /dev/null
+++ b/src/Cedar/Database.c
@@ -0,0 +1,239 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Database.c
+// License database
+
+#include "CedarPch.h"
+
+// Get the License status string
+wchar_t *LiGetLicenseStatusStr(UINT i)
+{
+ wchar_t *ret = _UU("LICENSE_STATUS_OTHERERROR");
+
+ switch (i)
+ {
+ case LICENSE_STATUS_OK:
+ ret = _UU("LICENSE_STATUS_OK");
+ break;
+
+ case LICENSE_STATUS_EXPIRED:
+ ret = _UU("LICENSE_STATUS_EXPIRED");
+ break;
+
+ case LICENSE_STATUS_ID_DIFF:
+ ret = _UU("LICENSE_STATUS_ID_DIFF");
+ break;
+
+ case LICENSE_STATUS_DUP:
+ ret = _UU("LICENSE_STATUS_DUP");
+ break;
+
+ case LICENSE_STATUS_INSUFFICIENT:
+ ret = _UU("LICENSE_STATUS_INSUFFICIENT");
+ break;
+
+ case LICENSE_STATUS_COMPETITION:
+ ret = _UU("LICENSE_STATUS_COMPETITION");
+ break;
+
+ case LICENSE_STATUS_NONSENSE:
+ ret = _UU("LICENSE_STATUS_NONSENSE");
+ break;
+
+ case LICENSE_STATUS_CPU:
+ ret = _UU("LICENSE_STATUS_CPU");
+ break;
+ }
+
+ return ret;
+}
+
+static char *li_keybit_chars = "ABCDEFGHJKLMNPQRSTUVWXYZ12345678";
+
+// Convert the string to a key bit
+bool LiStrToKeyBit(UCHAR *keybit, char *keystr)
+{
+ UINT x[36];
+ UINT i, wp;
+ char *str;
+ // Validate arguments
+ if (keybit == NULL || keystr == NULL)
+ {
+ return false;
+ }
+
+ str = CopyStr(keystr);
+ Trim(str);
+
+ wp = 0;
+ if (StrLen(str) != 41)
+ {
+ Free(str);
+ return false;
+ }
+
+ for (i = 0;i < 36;i++)
+ {
+ char c = str[wp++];
+ UINT j;
+
+ if (((i % 6) == 5) && (i != 35))
+ {
+ if (str[wp++] != '-')
+ {
+ Free(str);
+ return false;
+ }
+ }
+
+ x[i] = INFINITE;
+ for (j = 0;j < 32;j++)
+ {
+ if (ToUpper(c) == li_keybit_chars[j])
+ {
+ x[i] = j;
+ }
+ }
+
+ if (x[i] == INFINITE)
+ {
+ Free(str);
+ return false;
+ }
+ }
+
+ Zero(keybit, 23);
+
+ keybit[0] = x[0] << 1 | x[1] >> 4;
+ keybit[1] = x[1] << 4 | x[2] >> 1;
+ keybit[2] = x[2] << 7 | x[3] << 2 | x[4] >> 3;
+ keybit[3] = x[4] << 5 | x[5];
+
+ keybit[4] = x[6] << 3 | x[7] >> 2;
+ keybit[5] = x[7] << 6 | x[8] << 1 | x[9] >> 4;
+ keybit[6] = x[9] << 4 | x[10] >> 1;
+ keybit[7] = x[10] << 7 | x[11] << 2 | x[12] >> 3;
+ keybit[8] = x[12] << 5 | x[13];
+
+ keybit[9] = x[14] << 3 | x[15] >> 2;
+ keybit[10] = x[15] << 6 | x[16] << 1 | x[17] >> 4;
+ keybit[11] = x[17] << 4 | x[18] >> 1;
+ keybit[12] = x[18] << 7 | x[19] << 2 | x[20] >> 3;
+ keybit[13] = x[20] << 5 | x[21];
+
+ keybit[14] = x[22] << 3 | x[23] >> 2;
+ keybit[15] = x[23] << 6 | x[24] << 1 | x[25] >> 4;
+ keybit[16] = x[25] << 4 | x[26] >> 1;
+ keybit[17] = x[26] << 7 | x[27] << 2 | x[28] >> 3;
+ keybit[18] = x[28] << 5 | x[29];
+
+ keybit[19] = x[30] << 3 | x[31] >> 2;
+ keybit[20] = x[31] << 6 | x[32] << 1 | x[33] >> 4;
+ keybit[21] = x[33] << 4 | x[34] >> 1;
+ keybit[22] = x[34] << 7 | x[35] << 2;
+
+ Free(str);
+
+ return true;
+}
+
+// Determine whether the string is a license key
+bool LiIsLicenseKey(char *str)
+{
+ UCHAR keybit[23];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (LiStrToKeyBit(keybit, str) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Database.h b/src/Cedar/Database.h
new file mode 100644
index 00000000..e62680e2
--- /dev/null
+++ b/src/Cedar/Database.h
@@ -0,0 +1,98 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Database.h
+// Header of Database.c
+
+#ifndef DATABASE_H
+#define DATABASE_H
+
+wchar_t *LiGetLicenseStatusStr(UINT i);
+bool LiIsLicenseKey(char *str);
+bool LiStrToKeyBit(UCHAR *keybit, char *keystr);
+
+
+#endif // DATABASE_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/EM.c b/src/Cedar/EM.c
new file mode 100644
index 00000000..dafcc6ea
--- /dev/null
+++ b/src/Cedar/EM.c
@@ -0,0 +1,1476 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// EM.c
+// EtherLogger Manager for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define SM_C
+#define CM_C
+#define NM_C
+#define EM_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "CMInner.h"
+#include "SMInner.h"
+#include "NMInner.h"
+#include "EMInner.h"
+#include "../PenCore/resource.h"
+
+
+// License registration process
+void EmLicenseAddDlgOnOk(HWND hWnd, RPC *s)
+{
+}
+
+// Shift treatment of text input
+void EmLicenseAddDlgShiftTextItem(HWND hWnd, UINT id1, UINT id2, UINT *next_focus)
+{
+ char *s;
+ // Validate arguments
+ if (hWnd == NULL || next_focus == NULL)
+ {
+ return;
+ }
+
+ s = GetTextA(hWnd, id1);
+ if (StrLen(s) >= 6)
+ {
+ char *s2 = CopyStr(s);
+ char tmp[MAX_SIZE];
+ s2[6] = 0;
+ SetTextA(hWnd, id1, s2);
+ Free(s2);
+
+ if (id2 != 0)
+ {
+ GetTxtA(hWnd, id2, tmp, sizeof(tmp));
+
+ StrCat(tmp, sizeof(tmp), s + 6);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "-", "", false);
+
+ SetTextA(hWnd, id2, tmp);
+
+ *next_focus = id2;
+ }
+ else
+ {
+ *next_focus = IDOK;
+ }
+ }
+
+ Free(s);
+}
+
+// Make a text from the input data
+void EmLicenseAddDlgGetText(HWND hWnd, char *str, UINT size)
+{
+ char *k1, *k2, *k3, *k4, *k5, *k6;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ k1 = GetTextA(hWnd, B_KEY1);
+ k2 = GetTextA(hWnd, B_KEY2);
+ k3 = GetTextA(hWnd, B_KEY3);
+ k4 = GetTextA(hWnd, B_KEY4);
+ k5 = GetTextA(hWnd, B_KEY5);
+ k6 = GetTextA(hWnd, B_KEY6);
+
+ Format(str, size, "%s-%s-%s-%s-%s-%s", k1, k2, k3, k4, k5, k6);
+
+ Free(k1);
+ Free(k2);
+ Free(k3);
+ Free(k4);
+ Free(k5);
+ Free(k6);
+}
+
+// License addition dialog update
+void EmLicenseAddDlgUpdate(HWND hWnd, RPC *s)
+{
+}
+
+// License addition dialog initialization
+void EmLicenseAddDlgInit(HWND hWnd, RPC *s)
+{
+ HFONT h;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ h = GetFont("Arial", 10, true, false, false, false);
+ SetFont(hWnd, B_KEY1, h);
+ SetFont(hWnd, B_KEY2, h);
+ SetFont(hWnd, B_KEY3, h);
+ SetFont(hWnd, B_KEY4, h);
+ SetFont(hWnd, B_KEY5, h);
+ SetFont(hWnd, B_KEY6, h);
+
+ DlgFont(hWnd, S_INFO, 10, true);
+
+ EmLicenseAddDlgUpdate(hWnd, s);
+}
+
+// License addition dialog
+UINT EmLicenseAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ RPC *s = (RPC *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ EmLicenseAddDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case B_KEY1:
+ case B_KEY2:
+ case B_KEY3:
+ case B_KEY4:
+ case B_KEY5:
+ case B_KEY6:
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ EmLicenseAddDlgUpdate(hWnd, s);
+
+ switch (LOWORD(wParam))
+ {
+ case B_KEY2:
+ if (GetTextLen(hWnd, B_KEY2, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY1);
+ }
+ break;
+ case B_KEY3:
+ if (GetTextLen(hWnd, B_KEY3, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY2);
+ }
+ break;
+ case B_KEY4:
+ if (GetTextLen(hWnd, B_KEY4, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY3);
+ }
+ break;
+ case B_KEY5:
+ if (GetTextLen(hWnd, B_KEY5, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY4);
+ }
+ break;
+ case B_KEY6:
+ if (GetTextLen(hWnd, B_KEY6, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY5);
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ EmLicenseAddDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Add a license
+bool EmLicenseAdd(HWND hWnd, RPC *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_EM_LICENSE_ADD, EmLicenseAddDlg, s);
+}
+
+// License dialog initialization
+void EmLicenseDlgInit(HWND hWnd, RPC *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_CERT);
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+ DlgFont(hWnd, S_BOLD2, 0, true);
+
+ LvInit(hWnd, L_LIST);
+ LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_LICENSE_COLUMN_1"), 50);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_LICENSE_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_LICENSE_COLUMN_3"), 290);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_LICENSE_COLUMN_4"), 150);
+ LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_LICENSE_COLUMN_5"), 120);
+ LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_LICENSE_COLUMN_6"), 250);
+ LvInsertColumn(hWnd, L_LIST, 6, _UU("SM_LICENSE_COLUMN_7"), 100);
+ LvInsertColumn(hWnd, L_LIST, 7, _UU("SM_LICENSE_COLUMN_8"), 100);
+ LvInsertColumn(hWnd, L_LIST, 8, _UU("SM_LICENSE_COLUMN_9"), 100);
+
+ LvInitEx(hWnd, L_STATUS, true);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 100);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 100);
+
+ EmLicenseDlgRefresh(hWnd, s);
+}
+
+// License dialog update
+void EmLicenseDlgRefresh(HWND hWnd, RPC *s)
+{
+ RPC_ENUM_LICENSE_KEY t;
+ RPC_EL_LICENSE_STATUS st;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, EcEnumLicenseKey(s, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp1[32], tmp2[LICENSE_KEYSTR_LEN + 1], tmp3[LICENSE_MAX_PRODUCT_NAME_LEN + 1],
+ *tmp4, tmp5[128], tmp6[LICENSE_LICENSEID_STR_LEN + 1], tmp7[64],
+ tmp8[64], tmp9[64];
+ RPC_ENUM_LICENSE_KEY_ITEM *e = &t.Items[i];
+
+ UniToStru(tmp1, e->Id);
+ StrToUni(tmp2, sizeof(tmp2), e->LicenseKey);
+ StrToUni(tmp3, sizeof(tmp3), e->LicenseName);
+ tmp4 = LiGetLicenseStatusStr(e->Status);
+ if (e->Expires == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp5, sizeof(tmp5), e->Expires, NULL);
+ }
+ StrToUni(tmp6, sizeof(tmp6), e->LicenseId);
+ UniToStru(tmp7, e->ProductId);
+ UniFormat(tmp8, sizeof(tmp8), L"%I64u", e->SystemId);
+ UniToStru(tmp9, e->SerialId);
+
+ LvInsertAdd(b,
+ e->Status == LICENSE_STATUS_OK ? ICO_PASS : ICO_DISCARD,
+ (void *)e->Id, 9,
+ tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumLicenseKey(&t);
+
+ Zero(&st, sizeof(st));
+
+ if (CALL(hWnd, EcGetLicenseStatus(s, &st)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ if (st.Valid == false)
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("EM_NO_LICENSE_COLUMN"), _UU("EM_NO_LICENSE"));
+ }
+ else
+ {
+ // Current system ID
+ UniFormat(tmp, sizeof(tmp), L"%I64u", st.SystemId);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SYSTEM_ID"), tmp);
+
+ // Expiration date of the current license product
+ if (st.SystemExpires == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp, sizeof(tmp), st.SystemExpires, NULL);
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_EXPIRES"), tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ if (LvNum(hWnd, L_STATUS) >= 1)
+ {
+ LvAutoSize(hWnd, L_STATUS);
+ }
+
+ EmLicenseDlgUpdate(hWnd, s);
+}
+
+// License dialog control update
+void EmLicenseDlgUpdate(HWND hWnd, RPC *s)
+{
+ bool b = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b = LvIsSingleSelected(hWnd, L_LIST);
+
+ SetEnable(hWnd, B_DEL, b);
+ SetEnable(hWnd, IDOK, b);
+}
+
+// License dialog
+UINT EmLicenseDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ RPC *s = (RPC *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ EmLicenseDlgInit(hWnd, s);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ case L_STATUS:
+ EmLicenseDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+
+ if (i != INFINITE)
+ {
+ char *s = LvGetStrA(hWnd, L_LIST, i, 5);
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), _SS("LICENSE_SUPPORT_URL"), s);
+ ShellExecute(hWnd, "open", tmp, NULL, NULL, SW_SHOW);
+
+ Free(s);
+ }
+ }
+ break;
+
+ case B_OBTAIN:
+ ShellExecute(hWnd, "open", _SS("LICENSE_INFO_URL"), NULL, NULL, SW_SHOW);
+ break;
+
+ case B_ADD:
+ if (EmLicenseAdd(hWnd, s))
+ {
+ EmLicenseDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DEL:
+ if (IsEnable(hWnd, B_DEL))
+ {
+ UINT id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (id != 0)
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_LICENSE_DELETE_MSG")) == IDYES)
+ {
+ RPC_TEST t;
+
+ Zero(&t, sizeof(t));
+ t.IntValue = id;
+
+ if (CALL(hWnd, EcDelLicenseKey(s, &t)))
+ {
+ EmLicenseDlgRefresh(hWnd, s);
+ }
+ }
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+
+
+
+
+// Change Password dialog
+UINT EmPasswordDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ RPC *r = (RPC *)param;
+ char pass1[MAX_PATH];
+ char pass2[MAX_PATH];
+ UCHAR hash[SHA1_SIZE];
+ RPC_SET_PASSWORD t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ Focus(hWnd, E_PASSWORD1);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_PASSWORD1, pass1, sizeof(pass1));
+ Hash(hash, pass1, StrLen(pass1), true);
+ Zero(&t, sizeof(t));
+ Copy(t.HashedPassword, hash, SHA1_SIZE);
+ if (CALL(hWnd, EcSetPassword(r, &t)) == false)
+ {
+ break;
+ }
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_SET"));
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+
+ switch (LOWORD(wParam))
+ {
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ GetTxtA(hWnd, E_PASSWORD1, pass1, sizeof(pass1));
+ GetTxtA(hWnd, E_PASSWORD2, pass2, sizeof(pass2));
+ SetEnable(hWnd, IDOK, StrCmp(pass1, pass2) == 0 ? true : false);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Copy the state of the dialog to the HUB_LOG
+void EmDlgToHubLog(HWND hWnd, HUB_LOG *g)
+{
+ // Validate arguments
+ if (hWnd == NULL || g == NULL)
+ {
+ return;
+ }
+
+ Zero(g, sizeof(HUB_LOG));
+ g->PacketLogSwitchType = CbGetSelect(hWnd, C_PACKET_SWITCH);
+ g->PacketLogConfig[0] = IsChecked(hWnd, B_PACKET_0_0) ? 0 : IsChecked(hWnd, B_PACKET_0_1) ? 1 : 2;
+ g->PacketLogConfig[1] = IsChecked(hWnd, B_PACKET_1_0) ? 0 : IsChecked(hWnd, B_PACKET_1_1) ? 1 : 2;
+ g->PacketLogConfig[2] = IsChecked(hWnd, B_PACKET_2_0) ? 0 : IsChecked(hWnd, B_PACKET_2_1) ? 1 : 2;
+ g->PacketLogConfig[3] = IsChecked(hWnd, B_PACKET_3_0) ? 0 : IsChecked(hWnd, B_PACKET_3_1) ? 1 : 2;
+ g->PacketLogConfig[4] = IsChecked(hWnd, B_PACKET_4_0) ? 0 : IsChecked(hWnd, B_PACKET_4_1) ? 1 : 2;
+ g->PacketLogConfig[5] = IsChecked(hWnd, B_PACKET_5_0) ? 0 : IsChecked(hWnd, B_PACKET_5_1) ? 1 : 2;
+ g->PacketLogConfig[6] = IsChecked(hWnd, B_PACKET_6_0) ? 0 : IsChecked(hWnd, B_PACKET_6_1) ? 1 : 2;
+ g->PacketLogConfig[7] = IsChecked(hWnd, B_PACKET_7_0) ? 0 : IsChecked(hWnd, B_PACKET_7_1) ? 1 : 2;
+}
+
+// Copy the HUB_LOG to the state of the dialog
+void EmHubLogToDlg(HWND hWnd, HUB_LOG *g)
+{
+ // Validate arguments
+ if (hWnd == NULL || g == NULL)
+ {
+ return;
+ }
+
+ CbSelect(hWnd, C_PACKET_SWITCH, g->PacketLogSwitchType);
+
+ Check(hWnd, B_PACKET_0_0, g->PacketLogConfig[0] == 0);
+ Check(hWnd, B_PACKET_0_1, g->PacketLogConfig[0] == 1);
+ Check(hWnd, B_PACKET_0_2, g->PacketLogConfig[0] == 2);
+
+ Check(hWnd, B_PACKET_1_0, g->PacketLogConfig[1] == 0);
+ Check(hWnd, B_PACKET_1_1, g->PacketLogConfig[1] == 1);
+ Check(hWnd, B_PACKET_1_2, g->PacketLogConfig[1] == 2);
+
+ Check(hWnd, B_PACKET_2_0, g->PacketLogConfig[2] == 0);
+ Check(hWnd, B_PACKET_2_1, g->PacketLogConfig[2] == 1);
+ Check(hWnd, B_PACKET_2_2, g->PacketLogConfig[2] == 2);
+
+ Check(hWnd, B_PACKET_3_0, g->PacketLogConfig[3] == 0);
+ Check(hWnd, B_PACKET_3_1, g->PacketLogConfig[3] == 1);
+ Check(hWnd, B_PACKET_3_2, g->PacketLogConfig[3] == 2);
+
+ Check(hWnd, B_PACKET_4_0, g->PacketLogConfig[4] == 0);
+ Check(hWnd, B_PACKET_4_1, g->PacketLogConfig[4] == 1);
+ Check(hWnd, B_PACKET_4_2, g->PacketLogConfig[4] == 2);
+
+ Check(hWnd, B_PACKET_5_0, g->PacketLogConfig[5] == 0);
+ Check(hWnd, B_PACKET_5_1, g->PacketLogConfig[5] == 1);
+ Check(hWnd, B_PACKET_5_2, g->PacketLogConfig[5] == 2);
+
+ Check(hWnd, B_PACKET_6_0, g->PacketLogConfig[6] == 0);
+ Check(hWnd, B_PACKET_6_1, g->PacketLogConfig[6] == 1);
+ Check(hWnd, B_PACKET_6_2, g->PacketLogConfig[6] == 2);
+
+ Check(hWnd, B_PACKET_7_0, g->PacketLogConfig[7] == 0);
+ Check(hWnd, B_PACKET_7_1, g->PacketLogConfig[7] == 1);
+ Check(hWnd, B_PACKET_7_2, g->PacketLogConfig[7] == 2);
+}
+
+// Initialize
+void EmAddInit(HWND hWnd, EM_ADD *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Initialize controls
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_0"), 0);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_1"), 1);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_2"), 2);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_3"), 3);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_4"), 4);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_5"), 5);
+
+ if (p->NewMode)
+ {
+ // Newly creation mode
+ RPC_ENUM_DEVICE t;
+ HUB_LOG g;
+
+ Zero(&g, sizeof(g));
+ g.PacketLogSwitchType = LOG_SWITCH_DAY;
+ g.PacketLogConfig[PACKET_LOG_TCP_CONN] = g.PacketLogConfig[PACKET_LOG_DHCP] = 1;
+
+ EmHubLogToDlg(hWnd, &g);
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, EcEnumAllDevice(p->Rpc, &t)))
+ {
+ UINT i;
+ CbSetHeight(hWnd, C_DEVICE, 18);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_DEVICE_ITEM *dev = &t.Items[i];
+ wchar_t tmp[MAX_SIZE];
+
+ StrToUni(tmp, sizeof(tmp), dev->DeviceName);
+
+ CbAddStr(hWnd, C_DEVICE, tmp, 0);
+ }
+
+ FreeRpcEnumDevice(&t);
+ }
+
+ SetText(hWnd, 0, _UU("EM_ADD_NEW"));
+ }
+ else
+ {
+ // Edit mode (to obtain a configuration)
+ wchar_t tmp[MAX_PATH];
+ RPC_ADD_DEVICE t;
+ Hide(hWnd, R_PROMISCUS);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), p->DeviceName);
+
+ if (CALL(hWnd, EcGetDevice(p->Rpc, &t)))
+ {
+ EmHubLogToDlg(hWnd, &t.LogSetting);
+ }
+ else
+ {
+ Close(hWnd);
+ }
+
+ StrToUni(tmp, sizeof(tmp), p->DeviceName);
+ CbAddStr(hWnd, C_DEVICE, tmp, 0);
+
+ Disable(hWnd, C_DEVICE);
+
+ SetText(hWnd, 0, _UU("EM_ADD_EDIT"));
+ }
+
+ EmAddUpdate(hWnd, p);
+}
+
+// [OK] button
+void EmAddOk(HWND hWnd, EM_ADD *p)
+{
+ RPC_ADD_DEVICE t;
+ wchar_t *tmp;
+ char *name;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ EmDlgToHubLog(hWnd, &t.LogSetting);
+ tmp = CbGetStr(hWnd, C_DEVICE);
+ name = CopyUniToStr(tmp);
+
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+
+ if (p->NewMode)
+ {
+ t.NoPromiscus = IsChecked(hWnd, R_PROMISCUS);
+ }
+
+ if (p->NewMode)
+ {
+ if (CALL(hWnd, EcAddDevice(p->Rpc, &t)))
+ {
+ Close(hWnd);
+ }
+ }
+ else
+ {
+ if (CALL(hWnd, EcSetDevice(p->Rpc, &t)))
+ {
+ Close(hWnd);
+ }
+ }
+
+ Free(name);
+ Free(tmp);
+}
+
+// Control update
+void EmAddUpdate(HWND hWnd, EM_ADD *p)
+{
+ wchar_t *tmp;
+ char *name;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ tmp = CbGetStr(hWnd, C_DEVICE);
+ name = CopyUniToStr(tmp);
+
+ Trim(name);
+
+ if (StrLen(name) == 0)
+ {
+ Disable(hWnd, IDOK);
+ }
+ else
+ {
+ Enable(hWnd, IDCANCEL);
+ }
+
+ Free(name);
+ Free(tmp);
+}
+
+// Device Add / Edit dialog
+UINT EmAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ EM_ADD *p = (EM_ADD *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ EmAddInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ EmAddUpdate(hWnd, p);
+ switch (wParam)
+ {
+ case IDOK:
+ EmAddOk(hWnd, p);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Add or edit
+void EmAdd(HWND hWnd, RPC *r, char *device_name)
+{
+ EM_ADD p;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+
+ p.Rpc = r;
+
+ if (device_name != NULL)
+ {
+ StrCpy(p.DeviceName, sizeof(p.DeviceName), device_name);
+ }
+ else
+ {
+ p.NewMode = true;
+ }
+
+ Dialog(hWnd, D_EM_ADD, EmAddDlg, &p);
+}
+
+// Initialize
+void EmMainInit(HWND hWnd, RPC *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("EM_MAIN_COLUMN_1"), 300);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("EM_MAIN_COLUMN_2"), 150);
+
+ SetIcon(hWnd, 0, ICO_NIC_ONLINE);
+
+ EmMainRefresh(hWnd, r);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+}
+
+// Control update
+void EmMainUpdate(HWND hWnd, RPC *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, IDOK, LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false);
+ SetEnable(hWnd, B_DELETE, LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false);
+}
+
+// Update
+void EmMainRefresh(HWND hWnd, RPC *r)
+{
+ RPC_ENUM_DEVICE t;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, EcEnumDevice(r, &t)))
+ {
+ UINT i;
+ LVB *b;
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp[MAX_PATH];
+ RPC_ENUM_DEVICE_ITEM *dev = &t.Items[i];
+
+ StrToUni(tmp, sizeof(tmp), dev->DeviceName);
+
+ LvInsertAdd(b,
+ dev->Active ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE,
+ NULL,
+ 2,
+ tmp,
+ dev->Active ? _UU("EM_MAIN_OK") : _UU("EM_MAIN_ERROR"));
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumDevice(&t);
+
+ SetShow(hWnd, B_LICENSE, t.IsLicenseSupported);
+ }
+ else
+ {
+ Close(hWnd);
+ }
+
+ EmMainUpdate(hWnd, r);
+}
+
+// Main dialog procedure
+UINT EmMainDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ RPC *r = (RPC *)param;
+ UINT i;
+ char *name;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ EmMainInit(hWnd, r);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Edit
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ wchar_t *tmp;
+ tmp = LvGetStr(hWnd, L_LIST, i, 0);
+ if (tmp != NULL)
+ {
+ name = CopyUniToStr(tmp);
+ EmAdd(hWnd, r, name);
+ Free(tmp);
+ Free(name);
+ }
+ }
+ break;
+
+ case B_PASSWORD:
+ // Admin password
+ Dialog(hWnd, D_EM_PASSWORD, EmPasswordDlg, r);
+ break;
+
+ case B_LICENSE:
+ // Admin password
+ Dialog(hWnd, D_EM_LICENSE, EmLicenseDlg, r);
+ break;
+
+ case B_ADD:
+ // Add
+ EmAdd(hWnd, r, NULL);
+ EmMainRefresh(hWnd, r);
+ break;
+
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ wchar_t *tmp;
+ tmp = LvGetStr(hWnd, L_LIST, i, 0);
+ if (tmp != NULL)
+ {
+ RPC_DELETE_DEVICE t;
+ wchar_t msg[MAX_SIZE];
+ name = CopyUniToStr(tmp);
+ UniFormat(msg, sizeof(msg), _UU("EM_DELETE_CONFIRM"), name);
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2, msg) == IDYES)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+ if (CALL(hWnd, EcDelDevice(r, &t)))
+ {
+ EmMainRefresh(hWnd, r);
+ }
+ }
+ Free(tmp);
+ Free(name);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ EmMainRefresh(hWnd, r);
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case NM_DBLCLK:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ if (IsEnable(hWnd, IDOK))
+ {
+ Command(hWnd, IDOK);
+ }
+ break;
+ }
+ break;
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ EmMainUpdate(hWnd, r);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Installation of WinPcap
+void EmInstallWinPcap(HWND hWnd, RPC *r)
+{
+ wchar_t temp_name[MAX_SIZE];
+ HGLOBAL g;
+ HINSTANCE h;
+ HRSRC hr;
+ UINT size;
+ void *data;
+ IO *io;
+
+ // Ask whether the user want to start the installation
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("EM_WPCAP_INSTALL")) == IDNO)
+ {
+ return;
+ }
+
+ // Generate a temporary file name
+ UniFormat(temp_name, sizeof(temp_name), L"%s\\winpcap_installer.exe", MsGetTempDirW());
+
+ // Read from the resource
+ h = GetUiDll();
+ hr = FindResource(h, MAKEINTRESOURCE(BIN_WINPCAP), "BIN");
+ if (hr == NULL)
+ {
+RES_ERROR:
+ MsgBox(hWnd, MB_ICONSTOP, _UU("EM_RESOURCE"));
+ return;
+ }
+
+ g = LoadResource(h, hr);
+ if (g == NULL)
+ {
+ goto RES_ERROR;
+ }
+
+ size = SizeofResource(h, hr);
+ data = LockResource(g);
+
+ if (data == NULL)
+ {
+ goto RES_ERROR;
+ }
+
+ // Write to a temporary file
+ io = FileCreateW(temp_name);
+ if (io == NULL)
+ {
+ goto RES_ERROR;
+ }
+
+ FileWrite(io, data, size);
+ FileClose(io);
+
+ // Run
+ if (RunW(temp_name, NULL, false, true) == false)
+ {
+ // Failure
+ FileDeleteW(temp_name);
+ goto RES_ERROR;
+ }
+
+ FileDeleteW(temp_name);
+
+ if (r == NULL)
+ {
+ return;
+ }
+
+ // Message after the end
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) == false)
+ {
+ // Need to restart the computer
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("EM_WPCAP_REBOOT1"));
+ }
+ else
+ {
+ // Need to restart the service
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("EM_WPCAP_REBOOT2")) == IDNO)
+ {
+ // Not restart
+ }
+ else
+ {
+ // Restart
+ RPC_TEST t;
+ RPC_BRIDGE_SUPPORT t2;
+ Zero(&t, sizeof(t));
+ EcRebootServer(r, &t);
+
+ SleepThread(500);
+
+ Zero(&t2, sizeof(t2));
+ CALL(hWnd, EcGetBridgeSupport(r, &t2));
+ }
+ }
+}
+
+// Main screen
+void EMMain(RPC *r)
+{
+ RPC_BRIDGE_SUPPORT t;
+
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ // Examine the bridge support status of the server side first
+ Zero(&t, sizeof(t));
+ if (CALLEX(NULL, ScGetBridgeSupport(r, &t)) == ERR_NO_ERROR)
+ {
+ if (t.IsBridgeSupportedOs == false)
+ {
+ // OS does not support the bridge
+ MsgBox(NULL, MB_ICONEXCLAMATION, _UU("EM_UNSUPPORTED"));
+ return;
+ }
+
+ if (t.IsWinPcapNeeded)
+ {
+ if (r->Sock->RemoteIP.addr[0] != 127)
+ {
+ // WinPcap is required, but can not do anything because it is in remote management mode
+ MsgBox(NULL, MB_ICONINFORMATION, _UU("EM_WPCAP_REMOTE"));
+ return;
+ }
+ else
+ {
+ // WinPcap is required, and it's in local management mode
+ if (MsIsAdmin())
+ {
+ // Administrators
+ EmInstallWinPcap(NULL, r);
+ return;
+ }
+ else
+ {
+ // Non-Administrators
+ MsgBox(NULL, MB_ICONINFORMATION, _UU("EM_WPCAP_ROOT"));
+ return;
+ }
+ }
+ }
+ }
+
+ Dialog(NULL, D_EM_MAIN, EmMainDlg, r);
+}
+
+// Remote connection dialog procedure
+UINT EmRemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINUI_REMOTE *r = (WINUI_REMOTE *)param;
+ CEDAR *c;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ RemoteDlgInit(hWnd, r);
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ RemoteDlgRefresh(hWnd, r);
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case R_LOCAL:
+ if (IsChecked(hWnd, R_LOCAL) == false)
+ {
+ SetTextA(hWnd, C_HOSTNAME, "");
+ RemoteDlgRefresh(hWnd, r);
+ FocusEx(hWnd, C_HOSTNAME);
+ }
+ else
+ {
+ SetTextA(hWnd, C_HOSTNAME, "localhost");
+ RemoteDlgRefresh(hWnd, r);
+ Focus(hWnd, IDOK);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case IDOK:
+ RemoteDlgOnOk(hWnd, r);
+ break;
+ case B_ABOUT:
+ c = NewCedar(NULL, NULL);
+ About(hWnd, c, _UU("PRODUCT_NAME_ELOGMGR"));
+ ReleaseCedar(c);
+ }
+ switch (LOWORD(wParam))
+ {
+ case R_LOCAL:
+ case C_HOSTNAME:
+ RemoteDlgRefresh(hWnd, r);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ FreeCandidateList(r->CandidateList);
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Remote connection dialog
+char *EmRemoteDlg()
+{
+ WINUI_REMOTE r;
+
+ Zero(&r, sizeof(r));
+ r.RegKeyName = EM_REG_KEY;
+ r.Caption = _UU("EM_TITLE");
+ r.Title = _UU("EM_REMOTE_TITLE");
+ r.Icon = ICO_USER_ADMIN;
+ r.DefaultHostname = NULL;
+
+ if (Dialog(NULL, D_EM_REMOTE, EmRemoteDlgProc, &r) == false)
+ {
+ return NULL;
+ }
+
+ return r.Hostname;
+}
+
+// Start the EtherLogger Manager
+void EMExec()
+{
+ char *host;
+ char *ret;
+ bool cancel_now = false;
+ TOKEN_LIST *t;
+ UINT port = EL_ADMIN_PORT;
+ InitWinUi(_UU("EM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ while (true)
+ {
+ ret = EmRemoteDlg();
+
+ if (ret != NULL)
+ {
+ t = ParseToken(ret, ":");
+ if (t->NumTokens == 1 || t->NumTokens == 2)
+ {
+ RPC *rpc = NULL;
+ bool ok = false;
+ UINT ret;
+ host = t->Token[0];
+ if (t->NumTokens == 2)
+ {
+ port = ToInt(t->Token[1]);
+ }
+ else
+ {
+ port = EL_ADMIN_PORT;
+ }
+
+ // Try without a password first
+ ret = EcConnect(host, port, "", &rpc);
+RETRY:
+ if (ret != ERR_NO_ERROR && ret != ERR_AUTH_FAILED)
+ {
+ // Connection failed
+ CALL(NULL, ret);
+ }
+ else
+ {
+ if (ret == ERR_NO_ERROR)
+ {
+ // Successful connection
+ ok = true;
+ }
+ else
+ {
+ // Password required
+ char *pass = SmPassword(NULL, host);
+ if (pass == NULL)
+ {
+ // Cancel
+ cancel_now = true;
+ }
+ else
+ {
+ // Retry
+ ret = EcConnect(host, port, pass, &rpc);
+ Free(pass);
+ if (ret == ERR_NO_ERROR)
+ {
+ ok = true;
+ }
+ else
+ {
+ goto RETRY;
+ }
+ }
+ }
+ }
+
+ if (ok)
+ {
+ // Main screen
+ EMMain(rpc);
+
+ // Disconnect
+ EcDisconnect(rpc);
+ cancel_now = true;
+ }
+ FreeToken(t);
+ }
+ Free(ret);
+ }
+ else
+ {
+ cancel_now = true;
+ }
+
+ if (cancel_now)
+ {
+ break;
+ }
+ }
+
+ FreeWinUi();
+}
+
+#endif // WIN32
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/EM.h b/src/Cedar/EM.h
new file mode 100644
index 00000000..fd133fe9
--- /dev/null
+++ b/src/Cedar/EM.h
@@ -0,0 +1,96 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// EM.h
+// Header of EM.c
+
+#ifndef EM_H
+#define EM_H
+
+// Public function
+void EMExec();
+
+#endif // EM_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/EMInner.h b/src/Cedar/EMInner.h
new file mode 100644
index 00000000..b6aea06d
--- /dev/null
+++ b/src/Cedar/EMInner.h
@@ -0,0 +1,122 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// EMInner.h
+// Inner header of EM.c
+
+// Constants
+#define EM_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\EtherLogger\\Manager"
+
+// Innner structure
+typedef struct EM_ADD
+{
+ RPC *Rpc;
+ bool NewMode;
+ char DeviceName[MAX_SIZE];
+} EM_ADD;
+
+// Inner functions
+void EMMain(RPC *r);
+UINT EmMainDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void EmMainInit(HWND hWnd, RPC *r);
+void EmMainUpdate(HWND hWnd, RPC *r);
+void EmMainRefresh(HWND hWnd, RPC *r);
+void EmAdd(HWND hWnd, RPC *r, char *device_name);
+UINT EmAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void EmAddInit(HWND hWnd, EM_ADD *p);
+void EmDlgToHubLog(HWND hWnd, HUB_LOG *g);
+void EmHubLogToDlg(HWND hWnd, HUB_LOG *g);
+void EmAddOk(HWND hWnd, EM_ADD *p);
+void EmAddUpdate(HWND hWnd, EM_ADD *p);
+UINT EmPasswordDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+UINT EmLicenseDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void EmLicenseDlgInit(HWND hWnd, RPC *s);
+void EmLicenseDlgRefresh(HWND hWnd, RPC *s);
+void EmLicenseDlgUpdate(HWND hWnd, RPC *s);
+bool EmLicenseAdd(HWND hWnd, RPC *s);
+UINT EmLicenseAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void EmLicenseAddDlgInit(HWND hWnd, RPC *s);
+void EmLicenseAddDlgUpdate(HWND hWnd, RPC *s);
+void EmLicenseAddDlgShiftTextItem(HWND hWnd, UINT id1, UINT id2, UINT *next_focus);
+void EmLicenseAddDlgGetText(HWND hWnd, char *str, UINT size);
+void EmLicenseAddDlgOnOk(HWND hWnd, RPC *s);
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/EtherLog.c b/src/Cedar/EtherLog.c
new file mode 100644
index 00000000..c3d44955
--- /dev/null
+++ b/src/Cedar/EtherLog.c
@@ -0,0 +1,1356 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// EtherLog.c
+// EtherLogger program
+
+#include "CedarPch.h"
+
+static LOCK *el_lock = NULL;
+static EL *el = NULL;
+
+// RPC functional related macro
+#define DECLARE_RPC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type t; \
+ Zero(&t, sizeof(t)); \
+ in_rpc(&t, p); \
+ err = function(e, &t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, &t); \
+ } \
+ free_rpc(&t); \
+ ok = true; \
+ }
+#define DECLARE_RPC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type t; \
+ Zero(&t, sizeof(t)); \
+ in_rpc(&t, p); \
+ err = function(e, &t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, &t); \
+ } \
+ ok = true; \
+ }
+#define DECLARE_SC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ free_rpc(t); \
+ Zero(t, sizeof(data_type)); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+#define DECLARE_SC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+
+// RPC client disconnect
+void EcDisconnect(RPC *rpc)
+{
+ // Validate arguments
+ if (rpc == NULL)
+ {
+ return;
+ }
+
+ RpcFree(rpc);
+}
+
+// RPC client connect
+UINT EcConnect(char *host, UINT port, char *password, RPC **rpc)
+{
+ SOCK *s;
+ UCHAR password_hash[SHA1_SIZE];
+ UCHAR rand[SHA1_SIZE];
+ UCHAR response[SHA1_SIZE];
+ bool retcode;
+ // Validate arguments
+ if (host == NULL)
+ {
+ host = "localhost";
+ }
+ if (port == 0)
+ {
+ port = EL_ADMIN_PORT;
+ }
+ if (password == NULL)
+ {
+ password = "";
+ }
+ if (rpc == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Connect to the server
+ s = Connect(host, port);
+ if (s == NULL)
+ {
+ // Connection failure
+ return ERR_CONNECT_FAILED;
+ }
+
+ SetTimeout(s, 5000);
+
+ // Hash the password
+ Hash(password_hash, password, StrLen(password), true);
+
+ // Receive the random number
+ Zero(rand, sizeof(rand));
+ RecvAll(s, rand, sizeof(rand), false);
+ SecurePassword(response, password_hash, rand);
+
+ // Send a response
+ SendAll(s, response, sizeof(response), false);
+
+ // Receive results
+ retcode = false;
+ if (RecvAll(s, &retcode, sizeof(retcode), false) == false)
+ {
+ // Disconnect
+ ReleaseSock(s);
+ return ERR_PROTOCOL_ERROR;
+ }
+ retcode = Endian32(retcode);
+
+ if (retcode == false)
+ {
+ // Password incorrect
+ ReleaseSock(s);
+ return ERR_AUTH_FAILED;
+ }
+
+ // Successful connection
+ SetTimeout(s, INFINITE);
+
+ *rpc = StartRpcClient(s, NULL);
+
+ ReleaseSock(s);
+
+ return ERR_NO_ERROR;
+}
+
+// RPC server function
+PACK *ElRpcServer(RPC *r, char *name, PACK *p)
+{
+ EL *e = (EL *)r->Param;
+ PACK *ret;
+ UINT err;
+ bool ok;
+ // Validate arguments
+ if (r == NULL || name == NULL || p == NULL || e == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewPack();
+ err = ERR_NO_ERROR;
+ ok = false;
+
+ if (0) {}
+
+ DECLARE_RPC("AddDevice", RPC_ADD_DEVICE, EtAddDevice, InRpcAddDevice, OutRpcAddDevice)
+ DECLARE_RPC("DelDevice", RPC_DELETE_DEVICE, EtDelDevice, InRpcDeleteDevice, OutRpcDeleteDevice)
+ DECLARE_RPC("SetDevice", RPC_ADD_DEVICE, EtSetDevice, InRpcAddDevice, OutRpcAddDevice)
+ DECLARE_RPC("GetDevice", RPC_ADD_DEVICE, EtGetDevice, InRpcAddDevice, OutRpcAddDevice)
+ DECLARE_RPC_EX("EnumDevice", RPC_ENUM_DEVICE, EtEnumDevice, InRpcEnumDevice, OutRpcEnumDevice, FreeRpcEnumDevice)
+ DECLARE_RPC("SetPassword", RPC_SET_PASSWORD, EtSetPassword, InRpcSetPassword, OutRpcSetPassword)
+ DECLARE_RPC_EX("EnumAllDevice", RPC_ENUM_DEVICE, EtEnumAllDevice, InRpcEnumDevice, OutRpcEnumDevice, FreeRpcEnumDevice)
+ DECLARE_RPC("AddLicenseKey", RPC_TEST, EtAddLicenseKey, InRpcTest, OutRpcTest)
+ DECLARE_RPC("DelLicenseKey", RPC_TEST, EtDelLicenseKey, InRpcTest, OutRpcTest)
+ DECLARE_RPC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, EtEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)
+ DECLARE_RPC("GetLicenseStatus", RPC_EL_LICENSE_STATUS, EtGetLicenseStatus, InRpcElLicenseStatus, OutRpcElLicenseStatus)
+ DECLARE_RPC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, EtGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)
+ DECLARE_RPC("RebootServer", RPC_TEST, EtRebootServer, InRpcTest, OutRpcTest)
+
+ if (ok == false)
+ {
+ err = ERR_NOT_SUPPORTED;
+ }
+
+ PackAddInt(ret, "error", err);
+
+ return ret;
+}
+
+DECLARE_SC("AddDevice", RPC_ADD_DEVICE, EcAddDevice, InRpcAddDevice, OutRpcAddDevice)
+DECLARE_SC("DelDevice", RPC_DELETE_DEVICE, EcDelDevice, InRpcDeleteDevice, OutRpcDeleteDevice)
+DECLARE_SC("SetDevice", RPC_ADD_DEVICE, EcSetDevice, InRpcAddDevice, OutRpcAddDevice)
+DECLARE_SC("GetDevice", RPC_ADD_DEVICE, EcGetDevice, InRpcAddDevice, OutRpcAddDevice)
+DECLARE_SC_EX("EnumDevice", RPC_ENUM_DEVICE, EcEnumDevice, InRpcEnumDevice, OutRpcEnumDevice, FreeRpcEnumDevice)
+DECLARE_SC("SetPassword", RPC_SET_PASSWORD, EcSetPassword, InRpcSetPassword, OutRpcSetPassword)
+DECLARE_SC_EX("EnumAllDevice", RPC_ENUM_DEVICE, EcEnumAllDevice, InRpcEnumDevice, OutRpcEnumDevice, FreeRpcEnumDevice)
+DECLARE_SC("AddLicenseKey", RPC_TEST, EcAddLicenseKey, InRpcTest, OutRpcTest)
+DECLARE_SC("DelLicenseKey", RPC_TEST, EcDelLicenseKey, InRpcTest, OutRpcTest)
+DECLARE_SC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, EcEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)
+DECLARE_SC("GetLicenseStatus", RPC_EL_LICENSE_STATUS, EcGetLicenseStatus, InRpcElLicenseStatus, OutRpcElLicenseStatus)
+DECLARE_SC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, EcGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)
+DECLARE_SC("RebootServer", RPC_TEST, EcRebootServer, InRpcTest, OutRpcTest)
+
+// Thread to restart the server
+void EiRebootServerThread(THREAD *thread, void *param)
+{
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+ if (el == NULL)
+ {
+ return;
+ }
+
+ // Stopping the server
+ ElStop();
+
+ // Starting the server
+ ElStart();
+}
+
+// Restarting the server
+void EiRebootServer()
+{
+ THREAD *t;
+
+ t = NewThread(EiRebootServerThread, NULL);
+ ReleaseThread(t);
+}
+
+// RPC to restart server
+UINT EtRebootServer(EL *a, RPC_TEST *t)
+{
+
+ EiRebootServer();
+
+ return ERR_NO_ERROR;
+}
+
+// Get support information for the local bridge
+UINT EtGetBridgeSupport(EL *a, RPC_BRIDGE_SUPPORT *t)
+{
+ Zero(t, sizeof(RPC_BRIDGE_SUPPORT));
+
+ t->IsBridgeSupportedOs = IsBridgeSupported();
+ t->IsWinPcapNeeded = IsNeedWinPcap();
+
+ return ERR_NO_ERROR;
+}
+
+// Update the status by checking the all licenses
+void ElCheckLicense(EL_LICENSE_STATUS *st, LICENSE *e)
+{
+}
+
+// Save by analyzing the status of the current license
+void ElParseCurrentLicenseStatus(LICENSE_SYSTEM *s, EL_LICENSE_STATUS *st)
+{
+}
+
+// Get a license status
+UINT EtGetLicenseStatus(EL *e, RPC_EL_LICENSE_STATUS *t)
+{
+ UINT ret = ERR_NO_ERROR;
+ LICENSE_SYSTEM *ls = e->LicenseSystem;
+
+ if (ls == NULL)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ Zero(t, sizeof(RPC_EL_LICENSE_STATUS));
+
+ // Get the current license status
+ ElParseCurrentLicenseStatus(ls, e->LicenseStatus);
+
+ t->Valid = e->LicenseStatus->Valid;
+ t->SystemId = e->LicenseStatus->SystemId;
+ t->SystemExpires = e->LicenseStatus->Expires;
+
+ return ret;
+}
+
+// Enumerate the license keys
+UINT EtEnumLicenseKey(EL *el, RPC_ENUM_LICENSE_KEY *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Add a license key
+UINT EtAddLicenseKey(EL *e, RPC_TEST *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Delete the license key
+UINT EtDelLicenseKey(EL *e, RPC_TEST *t)
+{
+ return ERR_NOT_SUPPORTED;
+}
+
+// Password setting
+UINT EtSetPassword(EL *e, RPC_SET_PASSWORD *t)
+{
+ Copy(e->HashedPassword, t->HashedPassword, SHA1_SIZE);
+
+ ElSaveConfig(e);
+
+ return ERR_NO_ERROR;
+}
+
+// Add a device
+UINT EtAddDevice(EL *e, RPC_ADD_DEVICE *t)
+{
+ if (ElAddCaptureDevice(e, t->DeviceName, &t->LogSetting, t->NoPromiscus) == false)
+ {
+ return ERR_CAPTURE_DEVICE_ADD_ERROR;
+ }
+
+ ElSaveConfig(e);
+
+ return ERR_NO_ERROR;
+}
+
+// Remove the device
+UINT EtDelDevice(EL *e, RPC_DELETE_DEVICE *t)
+{
+ if (ElDeleteCaptureDevice(e, t->DeviceName) == false)
+ {
+ return ERR_CAPTURE_NOT_FOUND;
+ }
+
+ ElSaveConfig(e);
+
+ return ERR_NO_ERROR;
+}
+
+// Get the device
+UINT EtGetDevice(EL *e, RPC_ADD_DEVICE *t)
+{
+ UINT ret = ERR_CAPTURE_NOT_FOUND;
+
+ LockList(e->DeviceList);
+ {
+ EL_DEVICE *d, a;
+ Zero(&a, sizeof(a));
+ StrCpy(a.DeviceName, sizeof(a.DeviceName), t->DeviceName);
+
+ d = Search(e->DeviceList, &a);
+
+ if (d != NULL)
+ {
+ ret = ERR_NO_ERROR;
+
+ Copy(&t->LogSetting, &d->LogSetting, sizeof(HUB_LOG));
+ t->NoPromiscus = d->NoPromiscus;
+ }
+ }
+ UnlockList(e->DeviceList);
+
+ return ret;
+}
+
+// Device Setting
+UINT EtSetDevice(EL *e, RPC_ADD_DEVICE *t)
+{
+ if (ElSetCaptureDeviceLogSetting(e, t->DeviceName, &t->LogSetting) == false)
+ {
+ return ERR_CAPTURE_NOT_FOUND;
+ }
+
+ ElSaveConfig(e);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate all devices
+UINT EtEnumAllDevice(EL *e, RPC_ENUM_DEVICE *t)
+{
+ TOKEN_LIST *eth;
+ UINT i;
+ if (IsEthSupported() == false)
+ {
+ return ERR_NOT_SUPPORTED;
+ }
+
+ FreeRpcEnumDevice(t);
+ Zero(t, sizeof(RPC_ENUM_DEVICE));
+
+ eth = GetEthList();
+
+ t->NumItem = eth->NumTokens;
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_DEVICE_ITEM) * t->NumItem);
+
+ for (i = 0;i < eth->NumTokens;i++)
+ {
+ char *name = eth->Token[i];
+ RPC_ENUM_DEVICE_ITEM *item = &t->Items[i];
+
+ StrCpy(item->DeviceName, sizeof(item->DeviceName), name);
+ }
+
+ FreeToken(eth);
+
+ return ERR_NO_ERROR;
+}
+
+// Device enumeration
+UINT EtEnumDevice(EL *e, RPC_ENUM_DEVICE *t)
+{
+ bool is_beta_expired = ElIsBetaExpired();
+
+ if (is_beta_expired)
+ {
+ // The beta version has expired
+ return ERR_BETA_EXPIRES;
+ }
+
+ FreeRpcEnumDevice(t);
+ Zero(t, sizeof(RPC_ENUM_DEVICE));
+
+ LockList(e->DeviceList);
+ {
+ UINT i;
+
+ t->NumItem = LIST_NUM(e->DeviceList);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_DEVICE_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_DEVICE_ITEM *d = &t->Items[i];
+ EL_DEVICE *eld = LIST_DATA(e->DeviceList, i);
+
+ StrCpy(d->DeviceName, sizeof(d->DeviceName), eld->DeviceName);
+ d->Active = eld->Active && ((ELOG_IS_BETA || e->LicenseStatus->Valid) ? true : false);
+ }
+ }
+ UnlockList(e->DeviceList);
+
+ return ERR_NO_ERROR;
+}
+
+void InRpcAddDevice(RPC_ADD_DEVICE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ADD_DEVICE));
+ PackGetStr(p, "DeviceName", t->DeviceName, sizeof(t->DeviceName));
+ t->NoPromiscus = PackGetInt(p, "NoPromiscus");
+ t->LogSetting.PacketLogSwitchType = PackGetInt(p, "PacketLogSwitchType");
+
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ t->LogSetting.PacketLogConfig[i] = PackGetIntEx(p, "PacketLogConfig", i);
+ }
+}
+
+void OutRpcAddDevice(PACK *p, RPC_ADD_DEVICE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", t->DeviceName);
+ PackAddInt(p, "NoPromiscus", t->NoPromiscus);
+ PackAddInt(p, "PacketLogSwitchType", t->LogSetting.PacketLogSwitchType);
+
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ PackAddIntEx(p, "PacketLogConfig", t->LogSetting.PacketLogConfig[i], i, NUM_PACKET_LOG);
+ }
+}
+
+void InRpcDeleteDevice(RPC_DELETE_DEVICE *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DELETE_DEVICE));
+ PackGetStr(p, "DeviceName", t->DeviceName, sizeof(t->DeviceName));
+}
+
+void OutRpcDeleteDevice(PACK *p, RPC_DELETE_DEVICE *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "DeviceName", t->DeviceName);
+}
+
+void InRpcEnumDevice(RPC_ENUM_DEVICE *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_DEVICE));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_DEVICE_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_DEVICE_ITEM *d = &t->Items[i];
+
+ PackGetStrEx(p, "DeviceName", d->DeviceName, sizeof(d->DeviceName), i);
+ d->Active = PackGetBoolEx(p, "Active", i);
+ }
+
+ t->IsLicenseSupported = PackGetBool(p, "IsLicenseSupported");
+}
+
+void OutRpcEnumDevice(PACK *p, RPC_ENUM_DEVICE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_DEVICE_ITEM *d = &t->Items[i];
+
+ PackAddStrEx(p, "DeviceName", d->DeviceName, i, t->NumItem);
+ PackAddBoolEx(p, "Active", d->Active, i, t->NumItem);
+ }
+
+ PackAddBool(p, "IsLicenseSupported", t->IsLicenseSupported);
+}
+
+void FreeRpcEnumDevice(RPC_ENUM_DEVICE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_LICENSE_STATUS
+void InRpcElLicenseStatus(RPC_EL_LICENSE_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_EL_LICENSE_STATUS));
+
+ t->Valid = PackGetBool(p, "Valid");
+ t->SystemId = PackGetInt64(p, "SystemId");
+ t->SystemExpires = PackGetInt64(p, "SystemExpires");
+}
+void OutRpcElLicenseStatus(PACK *p, RPC_EL_LICENSE_STATUS *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddBool(p, "Valid", t->Valid);
+ PackAddInt64(p, "SystemId", t->SystemId);
+ PackAddInt64(p, "SystemExpires", t->SystemExpires);
+}
+
+// Listener thread
+void ElListenerProc(THREAD *thread, void *param)
+{
+ TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param;
+ EL *e;
+ SOCK *s;
+ UCHAR rand[SHA1_SIZE];
+ UCHAR pass1[SHA1_SIZE], pass2[SHA1_SIZE];
+ // Validate arguments
+ if (data == NULL || thread == NULL)
+ {
+ return;
+ }
+
+ e = (EL *)data->r->ThreadParam;
+ s = data->s;
+ AddRef(s->ref);
+ SetTimeout(s, 5000);
+ LockList(e->AdminThreadList);
+ {
+ AddRef(thread->ref);
+ AddRef(s->ref);
+ Insert(e->AdminThreadList, thread);
+ Insert(e->AdminSockList, s);
+ }
+ UnlockList(e->AdminThreadList);
+ NoticeThreadInit(thread);
+
+ // Submit a challenge
+ Rand(rand, sizeof(rand));
+ SendAll(s, rand, sizeof(rand), false);
+
+ // Receive a response
+ SecurePassword(pass1, e->HashedPassword, rand);
+ Zero(pass2, sizeof(pass2));
+ RecvAll(s, pass2, sizeof(pass2), false);
+
+ if (Cmp(pass1, pass2, SHA1_SIZE) != 0)
+ {
+ // Password incorrect
+ bool code = false;
+ code = Endian32(code);
+ SendAll(s, &code, sizeof(code), false);
+ }
+ else
+ {
+ // Password match
+ bool code = true;
+ RPC *r;
+
+ code = Endian32(code);
+ SendAll(s, &code, sizeof(code), false);
+
+ SetTimeout(s, INFINITE);
+
+ // Start operation as a RPC server
+ r = StartRpcServer(s, ElRpcServer, e);
+ RpcServer(r);
+ RpcFree(r);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ LockList(e->AdminThreadList);
+ {
+ if (Delete(e->AdminThreadList, thread))
+ {
+ ReleaseThread(thread);
+ }
+ if (Delete(e->AdminSockList, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(e->AdminThreadList);
+}
+
+// Listener start
+void ElStartListener(EL *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ e->AdminThreadList = NewList(NULL);
+ e->AdminSockList = NewList(NULL);
+
+ e->Listener = NewListenerEx(e->Cedar, LISTENER_TCP, e->Port == 0 ? EL_ADMIN_PORT : e->Port,
+ ElListenerProc, e);
+}
+
+// Listener stop
+void ElStopListener(EL *e)
+{
+ UINT i;
+ THREAD **threads;
+ SOCK **socks;
+ UINT num_threads, num_socks;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ StopAllListener(e->Cedar);
+
+ LockList(e->AdminThreadList);
+ {
+ threads = ToArray(e->AdminThreadList);
+ num_threads = LIST_NUM(e->AdminThreadList);
+ DeleteAll(e->AdminThreadList);
+
+ socks = ToArray(e->AdminSockList);
+ num_socks = LIST_NUM(e->AdminSockList);
+ DeleteAll(e->AdminSockList);
+ }
+ UnlockList(e->AdminThreadList);
+
+ for (i = 0;i < num_socks;i++)
+ {
+ Disconnect(socks[i]);
+ ReleaseSock(socks[i]);
+ }
+
+ for (i = 0;i < num_threads;i++)
+ {
+ WaitThread(threads[i], INFINITE);
+ ReleaseThread(threads[i]);
+ }
+
+ Free(threads);
+ Free(socks);
+
+ ReleaseList(e->AdminSockList);
+ ReleaseList(e->AdminThreadList);
+
+ ReleaseListener(e->Listener);
+}
+
+// Update the log configuration of the capture device
+bool ElSetCaptureDeviceLogSetting(EL *e, char *name, HUB_LOG *log)
+{
+ EL_DEVICE *d;
+ bool ret = false;
+ // Validate arguments
+ if (e == NULL || log == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ LockList(e->DeviceList);
+ {
+ EL_DEVICE t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+
+ d = Search(e->DeviceList, &t);
+
+ if (d != NULL)
+ {
+ Copy(&d->LogSetting, log, sizeof(HUB_LOG));
+
+ SetLogSwitchType(d->Logger, log->PacketLogSwitchType);
+
+ ret = true;
+ }
+ }
+ UnlockList(e->DeviceList);
+
+ return ret;
+}
+
+// Confirm whether the beta version has expired
+bool ElIsBetaExpired()
+{
+ SYSTEMTIME st;
+ UINT64 expires64;
+ UINT64 now64;
+ if (ELOG_IS_BETA == false)
+ {
+ return false;
+ }
+
+ Zero(&st, sizeof(st));
+
+ st.wYear = ELOG_BETA_EXPIRES_YEAR;
+ st.wMonth = ELOG_BETA_EXPIRES_MONTH;
+ st.wDay = ELOG_BETA_EXPIRES_DAY;
+
+ expires64 = SystemToUINT64(&st);
+ now64 = LocalTime64();
+
+ if (now64 >= expires64)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Capture thread
+void ElCaptureThread(THREAD *thread, void *param)
+{
+}
+
+// Delete the capture device
+bool ElDeleteCaptureDevice(EL *e, char *name)
+{
+ bool ret = false;
+ EL_DEVICE *d, t;
+ // Validate arguments
+ if (e == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ LockList(e->DeviceList);
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+
+ d = Search(e->DeviceList, &t);
+
+ if (d != NULL)
+ {
+ // Stop capture
+ d->Halt = true;
+ Cancel(d->Cancel1);
+
+ // Wait for thread stop
+ WaitThread(d->Thread, INFINITE);
+ ReleaseThread(d->Thread);
+
+ // Release the memory
+ Delete(e->DeviceList, d);
+ Free(d);
+
+ ret = true;
+ }
+ }
+ UnlockList(e->DeviceList);
+
+ return ret;
+}
+
+// Add a capture device
+bool ElAddCaptureDevice(EL *e, char *name, HUB_LOG *log, bool no_promiscus)
+{
+ EL_DEVICE *d, t;
+ // Validate arguments
+ if (e == NULL || name == NULL || log == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+
+ LockList(e->DeviceList);
+ {
+ d = Search(e->DeviceList, &t);
+ if (d != NULL)
+ {
+ // Capture settings with the same name already exists
+ UnlockList(e->DeviceList);
+ return false;
+ }
+
+ // Add a device
+ d = ZeroMalloc(sizeof(EL_DEVICE));
+ StrCpy(d->DeviceName, sizeof(d->DeviceName), name);
+ Copy(&d->LogSetting, log, sizeof(HUB_LOG));
+ d->NoPromiscus = no_promiscus;
+ d->el = e;
+ Insert(e->DeviceList, d);
+
+ // Start the thread
+ d->Thread = NewThread(ElCaptureThread, d);
+ WaitThreadInit(d->Thread);
+ }
+ UnlockList(e->DeviceList);
+
+ ElSaveConfig(e);
+
+ return true;
+}
+
+// Write the license List
+void EiWriteLicenseManager(FOLDER *f, EL *s)
+{
+}
+
+// Read the license list
+void EiLoadLicenseManager(EL *s, FOLDER *f)
+{
+}
+
+// Configuration initialization
+void ElInitConfig(EL *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Device list initialization
+ e->DeviceList = NewList(ElCompareDevice);
+
+ // Read configuration file
+ ElLoadConfig(e);
+
+ // Write configuration file
+ ElSaveConfig(e);
+}
+
+// Write the configuration
+void ElSaveConfig(EL *e)
+{
+ FOLDER *root;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+
+ ElSaveConfigToFolder(e, root);
+
+ SaveCfgRw(e->CfgRw, root);
+
+ CfgDeleteFolder(root);
+}
+
+// Write the configuration to the folder
+void ElSaveConfigToFolder(EL *e, FOLDER *root)
+{
+ UINT i;
+ FOLDER *devices;
+ // Validate arguments
+ if (e == NULL || root == NULL)
+ {
+ return;
+ }
+
+ CfgAddInt64(root, "AutoDeleteCheckDiskFreeSpaceMin", e->AutoDeleteCheckDiskFreeSpaceMin);
+
+ CfgAddInt(root, "AdminPort", e->Port);
+
+ CfgAddByte(root, "AdminPassword", e->HashedPassword, sizeof(e->HashedPassword));
+
+ if (ELOG_IS_BETA == false)
+ {
+ EiWriteLicenseManager(CfgCreateFolder(root, "LicenseManager"), e);
+ }
+
+ devices = CfgCreateFolder(root,"Devices");
+
+ LockList(e->DeviceList);
+ {
+ for (i = 0;i < LIST_NUM(e->DeviceList);i++)
+ {
+ FOLDER *f;
+ EL_DEVICE *d = LIST_DATA(e->DeviceList, i);
+
+ f = CfgCreateFolder(devices, d->DeviceName);
+ SiWriteHubLogCfgEx(f, &d->LogSetting, true);
+ CfgAddBool(f, "NoPromiscusMode", d->NoPromiscus);
+ }
+ }
+ UnlockList(e->DeviceList);
+}
+
+// Read the configuration from the folder
+void ElLoadConfigFromFolder(EL *e, FOLDER *root)
+{
+ UINT i;
+ TOKEN_LIST *t;
+ FOLDER *devices;
+
+ // Validate arguments
+ if (e == NULL || root == NULL)
+ {
+ return;
+ }
+
+ i = CfgGetInt(root, "AdminPort");
+ if (i >= 1 && i <= 65535)
+ {
+ e->Port = i;
+ }
+
+ e->AutoDeleteCheckDiskFreeSpaceMin = CfgGetInt64(root, "AutoDeleteCheckDiskFreeSpaceMin");
+ if (CfgIsItem(root, "AutoDeleteCheckDiskFreeSpaceMin") == false && e->AutoDeleteCheckDiskFreeSpaceMin == 0)
+ {
+ e->AutoDeleteCheckDiskFreeSpaceMin = DISK_FREE_SPACE_DEFAULT;
+ }
+
+ if (e->AutoDeleteCheckDiskFreeSpaceMin != 0)
+ {
+ if (e->AutoDeleteCheckDiskFreeSpaceMin < DISK_FREE_SPACE_MIN)
+ {
+ e->AutoDeleteCheckDiskFreeSpaceMin = DISK_FREE_SPACE_MIN;
+ }
+ }
+
+ if (CfgGetByte(root, "AdminPassword", e->HashedPassword, sizeof(e->HashedPassword)) != sizeof(e->HashedPassword))
+ {
+ Hash(e->HashedPassword, "", 0, true);
+ }
+
+ if (ELOG_IS_BETA == false)
+ {
+ EiLoadLicenseManager(e, CfgGetFolder(root, "LicenseManager"));
+ }
+
+ devices = CfgGetFolder(root, "Devices");
+ if(devices != NULL)
+ {
+ LockList(e->DeviceList);
+ {
+ t = CfgEnumFolderToTokenList(devices);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ FOLDER *f = CfgGetFolder(devices, name);
+
+ if (f != NULL)
+ {
+ HUB_LOG g;
+
+ Zero(&g, sizeof(g));
+ SiLoadHubLogCfg(&g, f);
+ ElAddCaptureDevice(e, name, &g, CfgGetBool(f, "NoPromiscusMode"));
+ }
+ }
+ FreeToken(t);
+ }
+ UnlockList(e->DeviceList);
+ }
+}
+
+// Reading configuration
+bool ElLoadConfig(EL *e)
+{
+ FOLDER *root;
+ bool ret = false;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ e->Port = EL_ADMIN_PORT;
+
+ e->CfgRw = NewCfgRw(&root, EL_CONFIG_FILENAME);
+
+ if (root != NULL)
+ {
+ ElLoadConfigFromFolder(e, root);
+
+ CfgDeleteFolder(root);
+ }
+ else
+ {
+ char *pass = "";
+ Hash(e->HashedPassword, pass, StrLen(pass), true);
+ e->AutoDeleteCheckDiskFreeSpaceMin = DISK_FREE_SPACE_DEFAULT;
+ }
+
+ return ret;
+}
+
+// Configuration release
+void ElFreeConfig(EL *e)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Write the configuration file
+ ElSaveConfig(e);
+ FreeCfgRw(e->CfgRw);
+
+ // Stop all capture
+ o = NewList(NULL);
+ LockList(e->DeviceList);
+ {
+ for (i = 0;i < LIST_NUM(e->DeviceList);i++)
+ {
+ EL_DEVICE *d = LIST_DATA(e->DeviceList, i);
+ Insert(o, CopyStr(d->DeviceName));
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *name = LIST_DATA(o, i);
+ ElDeleteCaptureDevice(e, name);
+ Free(name);
+ }
+ ReleaseList(o);
+ }
+ UnlockList(e->DeviceList);
+
+ ReleaseList(e->DeviceList);
+}
+
+// Comparison function of the device
+int ElCompareDevice(void *p1, void *p2)
+{
+ EL_DEVICE *d1, *d2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ d1 = *(EL_DEVICE **)p1;
+ d2 = *(EL_DEVICE **)p2;
+ if (d1 == NULL || d2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(d1->DeviceName, d2->DeviceName);
+}
+
+// Clean-up the EL
+void CleanupEl(EL *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Stop Eraser
+ FreeEraser(e->Eraser);
+
+ // Stop Listener
+ ElStopListener(e);
+
+ // Setting release
+ ElFreeConfig(e);
+
+ // Free the license system
+ if(e->LicenseSystem != NULL)
+ {
+ }
+
+ // Free the license status
+ if(e->LicenseStatus != NULL)
+ {
+ Free(e->LicenseStatus);
+ }
+
+ // Ethernet release
+ FreeEth();
+
+ ReleaseCedar(e->Cedar);
+
+ DeleteLock(e->lock);
+
+ Free(e);
+}
+
+// Release the EL
+void ReleaseEl(EL *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (Release(e->ref) == 0)
+ {
+ CleanupEl(e);
+ }
+}
+
+// Create the EL
+EL *NewEl()
+{
+ EL *e;
+
+#ifdef OS_WIN32
+ RegistWindowsFirewallAll();
+#endif
+
+ e = ZeroMalloc(sizeof(EL));
+ e->lock = NewLock();
+ e->ref = NewRef();
+
+ e->Cedar = NewCedar(NULL, NULL);
+
+
+ // Ethernet initialization
+ InitEth();
+
+ // Setting initialization
+ ElInitConfig(e);
+
+ // Listener start
+ ElStartListener(e);
+
+ // Initialize the license status
+ ElParseCurrentLicenseStatus(e->LicenseSystem, e->LicenseStatus);
+
+ // Eraser start
+ e->Eraser = NewEraser(NULL, e->AutoDeleteCheckDiskFreeSpaceMin);
+
+ return e;
+}
+
+// EL start
+void ElStart()
+{
+ // Raise the priority
+ OSSetHighPriority();
+
+ Lock(el_lock);
+ {
+ el = NewEl();
+ }
+ Unlock(el_lock);
+}
+
+// EL stop
+void ElStop()
+{
+ Lock(el_lock);
+ {
+ ReleaseEl(el);
+ el = NULL;
+ }
+ Unlock(el_lock);
+}
+
+// EL initialization
+void ElInit()
+{
+ // Lock initialization
+ el_lock = NewLock();
+}
+
+// EL release
+void ElFree()
+{
+ // Lock release
+ DeleteLock(el_lock);
+ el_lock = NULL;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/EtherLog.h b/src/Cedar/EtherLog.h
new file mode 100644
index 00000000..499fd359
--- /dev/null
+++ b/src/Cedar/EtherLog.h
@@ -0,0 +1,255 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// EtherLog.h
+// Header of EtherLog.c
+
+#ifndef ETHERLOG_H
+#define ETHERLOG_H
+
+// Whether this is a beta version
+#define ELOG_IS_BETA true
+
+// Beta expiration date
+#define ELOG_BETA_EXPIRES_YEAR 2008
+#define ELOG_BETA_EXPIRES_MONTH 12
+#define ELOG_BETA_EXPIRES_DAY 2
+
+// Version information
+//#define EL_VER 201
+//#define EL_BUILD 1600
+//#define EL_BETA 1
+#define MAX_LOGGING_QUEUE_LEN 100000
+
+// RPC related
+struct RPC_ADD_DEVICE
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ HUB_LOG LogSetting; // Log settings
+ bool NoPromiscus; // Without promiscuous mode
+};
+
+struct RPC_DELETE_DEVICE
+{
+ char DeviceName[MAX_SIZE]; // Device name
+};
+
+struct RPC_ENUM_DEVICE_ITEM
+{
+ char DeviceName[MAX_SIZE]; // Device name
+ bool Active; // Running flag
+};
+
+struct RPC_ENUM_DEVICE
+{
+ UINT NumItem; // Number of items
+ RPC_ENUM_DEVICE_ITEM *Items; // Items
+ bool IsLicenseSupported; // Whether the license system is supported
+};
+
+// License status of the service
+struct RPC_EL_LICENSE_STATUS
+{
+ BOOL Valid; // Enable flag
+ UINT64 SystemId; // System ID
+ UINT64 SystemExpires; // System expiration date
+};
+
+// Device
+struct EL_DEVICE
+{
+ EL *el; // EL
+ char DeviceName[MAX_SIZE]; // Device name
+ HUB_LOG LogSetting; // Log settings
+ THREAD *Thread; // Thread
+ CANCEL *Cancel1; // Cancel 1
+ CANCEL *Cancel2; // Cancel 2
+ volatile bool Halt; // Halting flag
+ bool Active; // Running flag
+ bool NoPromiscus; // Without promiscuous mode
+ LOG *Logger; // Logger
+};
+
+// License status
+struct EL_LICENSE_STATUS
+{
+ BOOL Valid; // Enable flag
+ UINT64 SystemId; // System ID
+ UINT64 Expires; // Expiration date
+};
+
+// EtherLogger
+struct EL
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ LIST *DeviceList; // Device list
+ CFG_RW *CfgRw; // Config R/W
+ UINT Port; // Port number
+ LISTENER *Listener; // Listener
+ UCHAR HashedPassword[SHA1_SIZE]; // Password
+ LIST *AdminThreadList; // Management thread list
+ LIST *AdminSockList; // Management socket list
+ LICENSE_SYSTEM *LicenseSystem; // License system
+ EL_LICENSE_STATUS *LicenseStatus; // License status
+ UINT64 AutoDeleteCheckDiskFreeSpaceMin; // Minimum free disk space
+ ERASER *Eraser; // Eraser
+};
+
+// Function prototype
+void ElInit();
+void ElFree();
+void ElStart();
+void ElStop();
+EL *NewEl();
+void ReleaseEl(EL *e);
+void CleanupEl(EL *e);
+void ElInitConfig(EL *e);
+void ElFreeConfig(EL *e);
+bool ElLoadConfig(EL *e);
+void ElLoadConfigFromFolder(EL *e, FOLDER *root);
+void ElSaveConfig(EL *e);
+void ElSaveConfigToFolder(EL *e, FOLDER *root);
+int ElCompareDevice(void *p1, void *p2);
+bool ElAddCaptureDevice(EL *e, char *name, HUB_LOG *log, bool no_promiscus);
+bool ElDeleteCaptureDevice(EL *e, char *name);
+bool ElSetCaptureDeviceLogSetting(EL *e, char *name, HUB_LOG *log);
+void ElCaptureThread(THREAD *thread, void *param);
+void ElStartListener(EL *e);
+void ElStopListener(EL *e);
+void ElListenerProc(THREAD *thread, void *param);
+PACK *ElRpcServer(RPC *r, char *name, PACK *p);
+void ElCheckLicense(EL_LICENSE_STATUS *st, LICENSE *e);
+void ElParseCurrentLicenseStatus(LICENSE_SYSTEM *s, EL_LICENSE_STATUS *st);
+bool ElIsBetaExpired();
+
+
+UINT EtAddDevice(EL *e, RPC_ADD_DEVICE *t);
+UINT EtDelDevice(EL *e, RPC_DELETE_DEVICE *t);
+UINT EtSetDevice(EL *e, RPC_ADD_DEVICE *t);
+UINT EtGetDevice(EL *e, RPC_ADD_DEVICE *t);
+UINT EtEnumDevice(EL *e, RPC_ENUM_DEVICE *t);
+UINT EtEnumAllDevice(EL *e, RPC_ENUM_DEVICE *t);
+UINT EtSetPassword(EL *e, RPC_SET_PASSWORD *t);
+UINT EtAddLicenseKey(EL *a, RPC_TEST *t);
+UINT EtDelLicenseKey(EL *a, RPC_TEST *t);
+UINT EtEnumLicenseKey(EL *a, RPC_ENUM_LICENSE_KEY *t);
+UINT EtGetLicenseStatus(EL *a, RPC_EL_LICENSE_STATUS *t);
+UINT EtGetBridgeSupport(EL *a, RPC_BRIDGE_SUPPORT *t);
+UINT EtRebootServer(EL *a, RPC_TEST *t);
+
+UINT EcAddDevice(RPC *r, RPC_ADD_DEVICE *t);
+UINT EcDelDevice(RPC *r, RPC_DELETE_DEVICE *t);
+UINT EcSetDevice(RPC *r, RPC_ADD_DEVICE *t);
+UINT EcGetDevice(RPC *r, RPC_ADD_DEVICE *t);
+UINT EcEnumDevice(RPC *r, RPC_ENUM_DEVICE *t);
+UINT EcEnumAllDevice(RPC *r, RPC_ENUM_DEVICE *t);
+UINT EcSetPassword(RPC *r, RPC_SET_PASSWORD *t);
+UINT EcAddLicenseKey(RPC *r, RPC_TEST *t);
+UINT EcDelLicenseKey(RPC *r, RPC_TEST *t);
+UINT EcEnumLicenseKey(RPC *r, RPC_ENUM_LICENSE_KEY *t);
+UINT EcGetLicenseStatus(RPC *r, RPC_EL_LICENSE_STATUS *t);
+UINT EcGetBridgeSupport(RPC *r, RPC_BRIDGE_SUPPORT *t);
+UINT EcRebootServer(RPC *r, RPC_TEST *t);
+
+UINT EcConnect(char *host, UINT port, char *password, RPC **rpc);
+void EcDisconnect(RPC *rpc);
+
+void InRpcAddDevice(RPC_ADD_DEVICE *t, PACK *p);
+void OutRpcAddDevice(PACK *p, RPC_ADD_DEVICE *t);
+void InRpcDeleteDevice(RPC_DELETE_DEVICE *t, PACK *p);
+void OutRpcDeleteDevice(PACK *p, RPC_DELETE_DEVICE *t);
+void InRpcEnumDevice(RPC_ENUM_DEVICE *t, PACK *p);
+void OutRpcEnumDevice(PACK *p, RPC_ENUM_DEVICE *t);
+void FreeRpcEnumDevice(RPC_ENUM_DEVICE *t);
+void InRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t, PACK *p);
+void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t);
+void FreeRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t);
+void InRpcElLicenseStatus(RPC_EL_LICENSE_STATUS *t, PACK *p);
+void OutRpcElLicenseStatus(PACK *p, RPC_EL_LICENSE_STATUS *t);
+
+#endif // ETHERLOG_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Hub.c b/src/Cedar/Hub.c
new file mode 100644
index 00000000..bdd28564
--- /dev/null
+++ b/src/Cedar/Hub.c
@@ -0,0 +1,7123 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Hub.c
+// Virtual HUB module
+
+#include "CedarPch.h"
+
+static UCHAR broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static char vgs_ua_str[9] = {0};
+static bool g_vgs_emb_tag = false;
+
+// A list of administration options that are currently supported and its default values
+// These names must be shorter than 64 bytes
+ADMIN_OPTION admin_options[] =
+{
+ {"allow_hub_admin_change_option", 0},
+ {"max_users", 0},
+ {"max_multilogins_per_user", 0},
+ {"max_groups", 0},
+ {"max_accesslists", 0},
+ {"max_sessions_client_bridge_apply", 0},
+ {"max_sessions", 0},
+ {"max_sessions_client", 0},
+ {"max_sessions_bridge", 0},
+ {"max_bitrates_download", 0},
+ {"max_bitrates_upload", 0},
+ {"deny_empty_password", 0},
+ {"deny_bridge", 0},
+ {"deny_routing", 0},
+ {"deny_qos", 0},
+ {"deny_change_user_password", 0},
+ {"no_change_users", 0},
+ {"no_change_groups", 0},
+ {"no_securenat", 0},
+ {"no_securenat_enablenat", 0},
+ {"no_securenat_enabledhcp", 0},
+ {"no_cascade", 0},
+ {"no_online", 0},
+ {"no_offline", 0},
+ {"no_change_log_config", 0},
+ {"no_disconnect_session", 0},
+ {"no_delete_iptable", 0},
+ {"no_delete_mactable", 0},
+ {"no_enum_session", 0},
+ {"no_query_session", 0},
+ {"no_change_admin_password", 0},
+ {"no_change_log_switch_type", 0},
+ {"no_change_access_list", 0},
+ {"no_change_access_control_list", 0},
+ {"no_change_cert_list", 0},
+ {"no_change_crl_list", 0},
+ {"no_read_log_file", 0},
+ {"deny_hub_admin_change_ext_option", 0},
+ {"no_delay_jitter_packet_loss", 0},
+ {"no_change_msg", 0},
+ {"no_access_list_include_file", 0},
+};
+
+UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION);
+
+// Create a user list
+LIST *NewUserList()
+{
+ LIST *o = NewList(CompareUserList);
+
+ return o;
+}
+
+// Search whether the specified user matches to the user list (with cache expiration)
+bool IsUserMatchInUserListWithCacheExpires(LIST *o, char *filename, UINT64 user_hash, UINT64 lifetime)
+{
+ bool ret = false;
+ UINT64 now = Tick64();
+ // Validate arguments
+ if (o == NULL || filename == NULL || user_hash == 0)
+ {
+ return false;
+ }
+
+ LockList(o);
+ {
+ if (lifetime != 0)
+ {
+ if (o->Param1 == 0 || (now >= (o->Param1 + lifetime)))
+ {
+ DeleteAllUserListCache(o);
+
+ o->Param1 = now;
+ }
+ }
+
+ ret = IsUserMatchInUserList(o, filename, user_hash);
+ }
+ UnlockList(o);
+
+ return ret;
+}
+bool IsUserMatchInUserListWithCacheExpiresAcl(LIST *o, char *name_in_acl, UINT64 user_hash, UINT64 lifetime)
+{
+ char tmp[16];
+ bool exclude = false;
+ char filename[MAX_SIZE];
+ char filename2[MAX_SIZE];
+ bool is_full_path = false;
+ bool ret = false;
+ // Validate arguments
+ if (o == NULL || name_in_acl == NULL || user_hash == 0 || StrLen(name_in_acl) < 9)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name_in_acl);
+ StrLower(tmp);
+
+ tmp[8] = 0;
+
+ if (Cmp(tmp, ACCESS_LIST_INCLUDED_PREFIX, 8) == 0)
+ {
+ // include
+ exclude = false;
+ }
+ else
+ {
+ // exclude
+ exclude = true;
+ }
+
+ // Extract the file name
+ StrCpy(filename, sizeof(filename), name_in_acl + 8);
+ Trim(filename);
+
+ // Identify whether the file name is an absolute path
+ if (filename[0] == '\\' || filename[0] == '/' || (filename[1] == ':' && filename[2] == '\\'))
+ {
+ is_full_path = true;
+ }
+
+ if (is_full_path == false)
+ {
+ // Prepend a '@' if the file name is a relative path
+ StrCpy(filename2, sizeof(filename2), "@");
+ StrCat(filename2, sizeof(filename2), filename);
+ StrCpy(filename, sizeof(filename), filename2);
+ }
+
+ ret = IsUserMatchInUserListWithCacheExpires(o, filename, user_hash, lifetime);
+
+ if (exclude)
+ {
+ ret = NEGATIVE_BOOL(ret);
+ }
+
+ return ret;
+}
+
+// Search whether the specified user matches to the user list
+bool IsUserMatchInUserList(LIST *o, char *filename, UINT64 user_hash)
+{
+ USERLIST *u;
+ bool ret = false;
+ // Validate arguments
+ if (o == NULL || filename == NULL || user_hash == 0)
+ {
+ return false;
+ }
+
+ LockList(o);
+ {
+ u = FindUserList(o, filename);
+ if (u == NULL)
+ {
+ u = LoadUserList(o, filename);
+ }
+
+ if (u != NULL)
+ {
+ ret = IsInt64InList(u->UserHashList, user_hash);
+ }
+ }
+ UnlockList(o);
+
+ return ret;
+}
+
+// Read the user list
+USERLIST *LoadUserList(LIST *o, char *filename)
+{
+ USERLIST *u;
+ BUF *b;
+ // Validate arguments
+ if (o == NULL || filename == NULL)
+ {
+ return NULL;
+ }
+
+ u = FindUserList(o, filename);
+
+ if (u != NULL)
+ {
+ Delete(o, u);
+
+ FreeUserListEntry(u);
+ }
+
+ u = ZeroMalloc(sizeof(USERLIST));
+
+ StrCpy(u->Filename, sizeof(u->Filename), filename);
+
+ u->UserHashList = NewInt64List(false);
+
+ b = ReadDumpWithMaxSize(filename, ACCESS_LIST_INCLUDE_FILE_MAX_SIZE);
+ if (b != NULL)
+ {
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ UINT64 ui;
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#") == false &&
+ StartWith(line, "//") == false &&
+ StartWith(line, ";") == false)
+ {
+ ui = UsernameToInt64(line);
+
+ AddInt64Distinct(u->UserHashList, ui);
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+ }
+
+ Add(o, u);
+
+ return u;
+}
+
+// Release the user list entry
+void FreeUserListEntry(USERLIST *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ ReleaseInt64List(u->UserHashList);
+
+ Free(u);
+}
+
+// Search in user list
+USERLIST *FindUserList(LIST *o, char *filename)
+{
+ USERLIST t, *u;
+ // Validate arguments
+ if (o == NULL || filename == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Filename, sizeof(t.Filename), filename);
+
+ u = Search(o, &t);
+
+ return u;
+}
+
+// User list entry comparison function
+int CompareUserList(void *p1, void *p2)
+{
+ USERLIST *u1, *u2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ u1 = *(USERLIST **)p1;
+ u2 = *(USERLIST **)p2;
+ if (u1 == NULL || u2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(u1->Filename, u2->Filename);
+}
+
+// Delete the cache of the all user list
+void DeleteAllUserListCache(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ USERLIST *u = LIST_DATA(o, i);
+
+ FreeUserListEntry(u);
+ }
+
+ DeleteAll(o);
+ }
+ UnlockList(o);
+}
+
+// Release the user list
+void FreeUserList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ USERLIST *u = LIST_DATA(o, i);
+
+ FreeUserListEntry(u);
+ }
+
+ ReleaseList(o);
+}
+
+// Get whether the specified message is a URL string
+bool IsURLMsg(wchar_t *str, char *url, UINT url_size)
+{
+ UNI_TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ UINT n = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ t = UniParseToken(str, L"\r\n");
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *str = t->Token[i];
+
+ if (IsEmptyUniStr(str) == false)
+ {
+ n++;
+
+ UniTrim(str);
+
+ if (n == 1)
+ {
+ if (UniStartWith(str, L"http://") ||
+ UniStartWith(str, L"https://") ||
+ UniStartWith(str, L"ftp://"))
+ {
+ ret = true;
+
+ UniToStr(url, url_size, str);
+ }
+ }
+ }
+ }
+
+ if (n != 1)
+ {
+ ret = false;
+ }
+
+ UniFreeToken(t);
+
+ return ret;
+}
+
+// Get data from RPC_ADMIN_OPTION
+UINT GetHubAdminOptionData(RPC_ADMIN_OPTION *ao, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (ao == NULL || name == NULL)
+ {
+ return INFINITE;
+ }
+
+ for (i = 0;i < ao->NumItem;i++)
+ {
+ ADMIN_OPTION *a = &ao->Items[i];
+
+ if (StrCmpi(a->Name, name) == 0)
+ {
+ return a->Value;
+ }
+ }
+
+ return INFINITE;
+}
+void GetHubAdminOptionDataAndSet(RPC_ADMIN_OPTION *ao, char *name, UINT *dest)
+{
+ UINT value;
+ // Validate arguments
+ if (ao == NULL || name == NULL || dest == NULL)
+ {
+ return;
+ }
+
+ value = GetHubAdminOptionData(ao, name);
+ if (value == INFINITE)
+ {
+ return;
+ }
+
+ *dest = value;
+}
+
+// Set the contents of the HUB_OPTION based on the data
+void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
+{
+ // Validate arguments
+ if (o == NULL || ao == NULL)
+ {
+ return;
+ }
+
+ GetHubAdminOptionDataAndSet(ao, "NoAddressPollingIPv4", &o->NoArpPolling);
+ GetHubAdminOptionDataAndSet(ao, "NoAddressPollingIPv6", &o->NoIPv6AddrPolling);
+ GetHubAdminOptionDataAndSet(ao, "NoIpTable", &o->NoIpTable);
+ GetHubAdminOptionDataAndSet(ao, "NoMacAddressLog", &o->NoMacAddressLog);
+ GetHubAdminOptionDataAndSet(ao, "ManageOnlyPrivateIP", &o->ManageOnlyPrivateIP);
+ GetHubAdminOptionDataAndSet(ao, "ManageOnlyLocalUnicastIPv6", &o->ManageOnlyLocalUnicastIPv6);
+ GetHubAdminOptionDataAndSet(ao, "DisableIPParsing", &o->DisableIPParsing);
+ GetHubAdminOptionDataAndSet(ao, "YieldAfterStorePacket", &o->YieldAfterStorePacket);
+ GetHubAdminOptionDataAndSet(ao, "NoSpinLockForPacketDelay", &o->NoSpinLockForPacketDelay);
+ GetHubAdminOptionDataAndSet(ao, "BroadcastStormDetectionThreshold", &o->BroadcastStormDetectionThreshold);
+ GetHubAdminOptionDataAndSet(ao, "ClientMinimumRequiredBuild", &o->ClientMinimumRequiredBuild);
+ GetHubAdminOptionDataAndSet(ao, "FilterPPPoE", &o->FilterPPPoE);
+ GetHubAdminOptionDataAndSet(ao, "FilterOSPF", &o->FilterOSPF);
+ GetHubAdminOptionDataAndSet(ao, "FilterIPv4", &o->FilterIPv4);
+ GetHubAdminOptionDataAndSet(ao, "FilterIPv6", &o->FilterIPv6);
+ GetHubAdminOptionDataAndSet(ao, "FilterNonIP", &o->FilterNonIP);
+ GetHubAdminOptionDataAndSet(ao, "NoIPv4PacketLog", &o->NoIPv4PacketLog);
+ GetHubAdminOptionDataAndSet(ao, "NoIPv6PacketLog", &o->NoIPv6PacketLog);
+ GetHubAdminOptionDataAndSet(ao, "FilterBPDU", &o->FilterBPDU);
+ GetHubAdminOptionDataAndSet(ao, "NoIPv6DefaultRouterInRAWhenIPv6", &o->NoIPv6DefaultRouterInRAWhenIPv6);
+ GetHubAdminOptionDataAndSet(ao, "NoLookBPDUBridgeId", &o->NoLookBPDUBridgeId);
+ GetHubAdminOptionDataAndSet(ao, "NoManageVlanId", &o->NoManageVlanId);
+ GetHubAdminOptionDataAndSet(ao, "VlanTypeId", &o->VlanTypeId);
+ GetHubAdminOptionDataAndSet(ao, "FixForDLinkBPDU", &o->FixForDLinkBPDU);
+ GetHubAdminOptionDataAndSet(ao, "RequiredClientId", &o->RequiredClientId);
+ GetHubAdminOptionDataAndSet(ao, "AdjustTcpMssValue", &o->AdjustTcpMssValue);
+ GetHubAdminOptionDataAndSet(ao, "DisableAdjustTcpMss", &o->DisableAdjustTcpMss);
+ GetHubAdminOptionDataAndSet(ao, "NoDhcpPacketLogOutsideHub", &o->NoDhcpPacketLogOutsideHub);
+ GetHubAdminOptionDataAndSet(ao, "DisableHttpParsing", &o->DisableHttpParsing);
+ GetHubAdminOptionDataAndSet(ao, "DisableUdpAcceleration", &o->DisableUdpAcceleration);
+ GetHubAdminOptionDataAndSet(ao, "DisableUdpFilterForLocalBridgeNic", &o->DisableUdpFilterForLocalBridgeNic);
+ GetHubAdminOptionDataAndSet(ao, "ApplyIPv4AccessListOnArpPacket", &o->ApplyIPv4AccessListOnArpPacket);
+ GetHubAdminOptionDataAndSet(ao, "RemoveDefGwOnDhcpForLocalhost", &o->RemoveDefGwOnDhcpForLocalhost);
+ GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxTcpSessionsPerIp", &o->SecureNAT_MaxTcpSessionsPerIp);
+ GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxTcpSynSentPerIp", &o->SecureNAT_MaxTcpSynSentPerIp);
+ GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxUdpSessionsPerIp", &o->SecureNAT_MaxUdpSessionsPerIp);
+ GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxDnsSessionsPerIp", &o->SecureNAT_MaxDnsSessionsPerIp);
+ GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxIcmpSessionsPerIp", &o->SecureNAT_MaxIcmpSessionsPerIp);
+ GetHubAdminOptionDataAndSet(ao, "AccessListIncludeFileCacheLifetime", &o->AccessListIncludeFileCacheLifetime);
+ GetHubAdminOptionDataAndSet(ao, "DisableKernelModeSecureNAT", &o->DisableKernelModeSecureNAT);
+ GetHubAdminOptionDataAndSet(ao, "DisableUserModeSecureNAT", &o->DisableUserModeSecureNAT);
+ GetHubAdminOptionDataAndSet(ao, "DisableCheckMacOnLocalBridge", &o->DisableCheckMacOnLocalBridge);
+ GetHubAdminOptionDataAndSet(ao, "DisableCorrectIpOffloadChecksum", &o->DisableCorrectIpOffloadChecksum);
+ GetHubAdminOptionDataAndSet(ao, "BroadcastLimiterStrictMode", &o->BroadcastLimiterStrictMode);
+ GetHubAdminOptionDataAndSet(ao, "MaxLoggedPacketsPerMinute", &o->MaxLoggedPacketsPerMinute);
+ GetHubAdminOptionDataAndSet(ao, "DoNotSaveHeavySecurityLogs", &o->DoNotSaveHeavySecurityLogs);
+}
+
+// Convert the contents of the HUB_OPTION to data
+void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
+{
+ LIST *aol;
+ UINT i;
+ // Validate arguments
+ if (ao == NULL || o == NULL || hub_name == NULL)
+ {
+ return;
+ }
+
+ aol = NewListFast(NULL);
+
+ Add(aol, NewAdminOption("NoAddressPollingIPv4", o->NoArpPolling));
+ Add(aol, NewAdminOption("NoAddressPollingIPv6", o->NoIPv6AddrPolling));
+ Add(aol, NewAdminOption("NoIpTable", o->NoIpTable));
+ Add(aol, NewAdminOption("NoMacAddressLog", o->NoMacAddressLog));
+ Add(aol, NewAdminOption("ManageOnlyPrivateIP", o->ManageOnlyPrivateIP));
+ Add(aol, NewAdminOption("ManageOnlyLocalUnicastIPv6", o->ManageOnlyLocalUnicastIPv6));
+ Add(aol, NewAdminOption("DisableIPParsing", o->DisableIPParsing));
+ Add(aol, NewAdminOption("YieldAfterStorePacket", o->YieldAfterStorePacket));
+ Add(aol, NewAdminOption("NoSpinLockForPacketDelay", o->NoSpinLockForPacketDelay));
+ Add(aol, NewAdminOption("BroadcastStormDetectionThreshold", o->BroadcastStormDetectionThreshold));
+ Add(aol, NewAdminOption("ClientMinimumRequiredBuild", o->ClientMinimumRequiredBuild));
+ Add(aol, NewAdminOption("FilterPPPoE", o->FilterPPPoE));
+ Add(aol, NewAdminOption("FilterOSPF", o->FilterOSPF));
+ Add(aol, NewAdminOption("FilterIPv4", o->FilterIPv4));
+ Add(aol, NewAdminOption("FilterIPv6", o->FilterIPv6));
+ Add(aol, NewAdminOption("FilterNonIP", o->FilterNonIP));
+ Add(aol, NewAdminOption("NoIPv4PacketLog", o->NoIPv4PacketLog));
+ Add(aol, NewAdminOption("NoIPv6PacketLog", o->NoIPv6PacketLog));
+ Add(aol, NewAdminOption("FilterBPDU", o->FilterBPDU));
+ Add(aol, NewAdminOption("NoIPv6DefaultRouterInRAWhenIPv6", o->NoIPv6DefaultRouterInRAWhenIPv6));
+ Add(aol, NewAdminOption("NoLookBPDUBridgeId", o->NoLookBPDUBridgeId));
+ Add(aol, NewAdminOption("NoManageVlanId", o->NoManageVlanId));
+ Add(aol, NewAdminOption("VlanTypeId", o->VlanTypeId));
+ Add(aol, NewAdminOption("FixForDLinkBPDU", o->FixForDLinkBPDU));
+ Add(aol, NewAdminOption("RequiredClientId", o->RequiredClientId));
+ Add(aol, NewAdminOption("AdjustTcpMssValue", o->AdjustTcpMssValue));
+ Add(aol, NewAdminOption("DisableAdjustTcpMss", o->DisableAdjustTcpMss));
+ Add(aol, NewAdminOption("NoDhcpPacketLogOutsideHub", o->NoDhcpPacketLogOutsideHub));
+ Add(aol, NewAdminOption("DisableHttpParsing", o->DisableHttpParsing));
+ Add(aol, NewAdminOption("DisableUdpAcceleration", o->DisableUdpAcceleration));
+ Add(aol, NewAdminOption("DisableUdpFilterForLocalBridgeNic", o->DisableUdpFilterForLocalBridgeNic));
+ Add(aol, NewAdminOption("ApplyIPv4AccessListOnArpPacket", o->ApplyIPv4AccessListOnArpPacket));
+ Add(aol, NewAdminOption("RemoveDefGwOnDhcpForLocalhost", o->RemoveDefGwOnDhcpForLocalhost));
+ Add(aol, NewAdminOption("SecureNAT_MaxTcpSessionsPerIp", o->SecureNAT_MaxTcpSessionsPerIp));
+ Add(aol, NewAdminOption("SecureNAT_MaxTcpSynSentPerIp", o->SecureNAT_MaxTcpSynSentPerIp));
+ Add(aol, NewAdminOption("SecureNAT_MaxUdpSessionsPerIp", o->SecureNAT_MaxUdpSessionsPerIp));
+ Add(aol, NewAdminOption("SecureNAT_MaxDnsSessionsPerIp", o->SecureNAT_MaxDnsSessionsPerIp));
+ Add(aol, NewAdminOption("SecureNAT_MaxIcmpSessionsPerIp", o->SecureNAT_MaxIcmpSessionsPerIp));
+ Add(aol, NewAdminOption("AccessListIncludeFileCacheLifetime", o->AccessListIncludeFileCacheLifetime));
+ Add(aol, NewAdminOption("DisableKernelModeSecureNAT", o->DisableKernelModeSecureNAT));
+ Add(aol, NewAdminOption("DisableUserModeSecureNAT", o->DisableUserModeSecureNAT));
+ Add(aol, NewAdminOption("DisableCheckMacOnLocalBridge", o->DisableCheckMacOnLocalBridge));
+ Add(aol, NewAdminOption("DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum));
+ Add(aol, NewAdminOption("BroadcastLimiterStrictMode", o->BroadcastLimiterStrictMode));
+ Add(aol, NewAdminOption("MaxLoggedPacketsPerMinute", o->MaxLoggedPacketsPerMinute));
+ Add(aol, NewAdminOption("DoNotSaveHeavySecurityLogs", o->DoNotSaveHeavySecurityLogs));
+
+ Zero(ao, sizeof(RPC_ADMIN_OPTION));
+
+ StrCpy(ao->HubName, sizeof(ao->HubName), hub_name);
+
+ ao->NumItem = LIST_NUM(aol);
+ ao->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * ao->NumItem);
+
+ for (i = 0;i < LIST_NUM(aol);i++)
+ {
+ ADMIN_OPTION *a = LIST_DATA(aol, i);
+
+ Copy(&ao->Items[i], a, sizeof(ADMIN_OPTION));
+
+ Free(a);
+ }
+
+ ReleaseList(aol);
+}
+
+// Create a new ADMIN OPTION
+ADMIN_OPTION *NewAdminOption(char *name, UINT value)
+{
+ ADMIN_OPTION *a;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(ADMIN_OPTION));
+ StrCpy(a->Name, sizeof(a->Name), name);
+ a->Value = value;
+
+ return a;
+}
+
+// Clone the AC list
+LIST *CloneAcList(LIST *o)
+{
+ LIST *ret;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewAcList();
+ SetAcList(ret, o);
+
+ return ret;
+}
+
+// Set all the AC list
+void SetAcList(LIST *o, LIST *src)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || src == NULL)
+ {
+ return;
+ }
+
+ DelAllAc(o);
+
+ for (i = 0;i < LIST_NUM(src);i++)
+ {
+ AC *ac = LIST_DATA(src, i);
+
+ AddAc(o, ac);
+ }
+}
+
+// Remove all AC from the AC list
+void DelAllAc(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ Free(ac);
+ }
+
+ DeleteAll(o);
+}
+
+// Release the AC list
+void FreeAcList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ Free(ac);
+ }
+
+ ReleaseList(o);
+}
+
+// Generate a string that indicates the contents of the AC
+char *GenerateAcStr(AC *ac)
+{
+ char tmp[MAX_SIZE];
+ char ip[64], mask[64];
+
+ if (ac == NULL)
+ {
+ return NULL;
+ }
+
+ IPToStr(ip, sizeof(ip), &ac->IpAddress);
+ MaskToStr(mask, sizeof(mask), &ac->SubnetMask);
+
+ if (ac->Masked == false)
+ {
+ Format(tmp, sizeof(tmp), "%s", ip);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "%s/%s", ip, mask);
+ }
+
+ return CopyStr(tmp);
+}
+
+// Calculate whether the specified IP address is rejected by the access list
+bool IsIpDeniedByAcList(IP *ip, LIST *o)
+{
+ return false;
+}
+
+// Calculate whether the specified IP address is masked by the AC
+bool IsIpMaskedByAc(IP *ip, AC *ac)
+{
+ return false;
+}
+
+// Set the AC
+void SetAc(LIST *o, UINT id, AC *ac)
+{
+ // Validate arguments
+ if (o == NULL || id == 0 || ac == NULL)
+ {
+ return;
+ }
+
+ if (DelAc(o, id))
+ {
+ AddAc(o, ac);
+ }
+}
+
+// Get the AC
+AC *GetAc(LIST *o, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ if (ac->Id == id)
+ {
+ return Clone(ac, sizeof(AC));
+ }
+ }
+
+ return NULL;
+}
+
+// Delete the AC
+bool DelAc(LIST *o, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || id == 0)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ if (ac->Id == id)
+ {
+ if (Delete(o, ac))
+ {
+ Free(ac);
+
+ NormalizeAcList(o);
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Add an AC to the list
+void AddAc(LIST *o, AC *ac)
+{
+ // Validate arguments
+ if (o == NULL || ac == NULL)
+ {
+ return;
+ }
+
+ if (LIST_NUM(o) < MAX_HUB_ACS)
+ {
+ Insert(o, Clone(ac, sizeof(AC)));
+
+ NormalizeAcList(o);
+ }
+}
+
+// Normalize the AC list
+void NormalizeAcList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ AC *ac = LIST_DATA(o, i);
+
+ if (IsIP6(&ac->IpAddress))
+ {
+ ac->IpAddress.ipv6_scope_id = 0;
+ }
+
+ ac->Id = (i + 1);
+ }
+}
+
+// Create a new AC list
+LIST *NewAcList()
+{
+ return NewList(CmpAc);
+}
+
+// AC comparison
+int CmpAc(void *p1, void *p2)
+{
+ AC *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(AC **)p1;
+ a2 = *(AC **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+ if (a1->Priority > a2->Priority)
+ {
+ return 1;
+ }
+ else if (a1->Priority < a2->Priority)
+ {
+ return -1;
+ }
+ else if (a1->Deny > a2->Deny)
+ {
+ return 1;
+ }
+ else if (a1->Deny < a2->Deny)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Copy the CRL
+CRL *CopyCrl(CRL *crl)
+{
+ CRL *ret;
+ // Validate arguments
+ if (crl == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(CRL));
+
+ if (crl->Serial != NULL)
+ {
+ ret->Serial = NewXSerial(crl->Serial->data, crl->Serial->size);
+ }
+
+ ret->Name = CopyName(crl->Name);
+
+ Copy(ret->DigestMD5, crl->DigestMD5, MD5_SIZE);
+ Copy(ret->DigestSHA1, crl->DigestSHA1, SHA1_SIZE);
+
+ return ret;
+}
+
+// Release the CRL
+void FreeCrl(CRL *crl)
+{
+ // Validate arguments
+ if (crl == NULL)
+ {
+ return;
+ }
+
+ if (crl->Serial != NULL)
+ {
+ FreeXSerial(crl->Serial);
+ }
+
+ if (crl->Name != NULL)
+ {
+ FreeName(crl->Name);
+ }
+
+ Free(crl);
+}
+
+// Check whether the certificate has been disabled by searching the CRL list of Virtual HUB
+bool IsValidCertInHub(HUB *h, X *x)
+{
+ bool ret;
+ // Validate arguments
+ if (h == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ if (h->HubDb == NULL)
+ {
+ return false;
+ }
+
+ if (IsXRevoked(x))
+ {
+ // Disabled by the CRL stored in the file
+ return false;
+ }
+
+ LockList(h->HubDb->CrlList);
+ {
+ ret = IsCertMatchCrlList(x, h->HubDb->CrlList);
+ }
+ UnlockList(h->HubDb->CrlList);
+
+ if (ret)
+ {
+ // This is invalid because it was matched
+ return false;
+ }
+
+ // This is valid because it wasn't matched
+ return true;
+}
+
+// Search whether the certificate matches the CRL list
+bool IsCertMatchCrlList(X *x, LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (x == NULL || o == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CRL *crl = LIST_DATA(o, i);
+
+ if (IsCertMatchCrl(x, crl))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Convert the CRL to a string
+wchar_t *GenerateCrlStr(CRL *crl)
+{
+ wchar_t tmp[2048];
+ // Validate arguments
+ if (crl == NULL)
+ {
+ return NULL;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), L"");
+
+ if (crl->Name != NULL)
+ {
+ // Name information
+ wchar_t name[MAX_SIZE];
+
+ UniStrCat(tmp, sizeof(tmp), L"Subject=\"");
+
+ GetAllNameFromName(name, sizeof(name), crl->Name);
+ UniStrCat(tmp, sizeof(tmp), name);
+ UniStrCat(tmp, sizeof(tmp), L"\", ");
+ }
+
+ if (crl->Serial != NULL)
+ {
+ // Serial information
+ char str[128];
+ wchar_t uni[128];
+
+ BinToStrEx(str, sizeof(str), crl->Serial->data, crl->Serial->size);
+ StrToUni(uni, sizeof(uni), str);
+ UniStrCat(tmp, sizeof(tmp), L"Serial=\"");
+ UniStrCat(tmp, sizeof(tmp), uni);
+ UniStrCat(tmp, sizeof(tmp), L"\", ");
+ }
+
+ if (IsZero(crl->DigestMD5, MD5_SIZE) == false)
+ {
+ // MD5
+ char str[128];
+ wchar_t uni[128];
+
+ BinToStrEx(str, sizeof(str), crl->DigestMD5, MD5_SIZE);
+ StrToUni(uni, sizeof(uni), str);
+ UniStrCat(tmp, sizeof(tmp), L"MD5=\"");
+ UniStrCat(tmp, sizeof(tmp), uni);
+ UniStrCat(tmp, sizeof(tmp), L"\", ");
+ }
+
+ if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)
+ {
+ // MD5
+ char str[128];
+ wchar_t uni[128];
+
+ BinToStrEx(str, sizeof(str), crl->DigestSHA1, SHA1_SIZE);
+ StrToUni(uni, sizeof(uni), str);
+ UniStrCat(tmp, sizeof(tmp), L"SHA1=\"");
+ UniStrCat(tmp, sizeof(tmp), uni);
+ UniStrCat(tmp, sizeof(tmp), L"\", ");
+ }
+
+ if (UniEndWith(tmp, L", "))
+ {
+ tmp[UniStrLen(tmp) - 2] = 0;
+ }
+
+ return CopyUniStr(tmp);
+}
+
+// Check whether it matches the Certificate Revocation List entry
+bool IsCertMatchCrl(X *x, CRL *crl)
+{
+ bool b = true;
+ // Validate arguments
+ if (x == NULL || crl == NULL)
+ {
+ return false;
+ }
+
+ if (crl->Serial != NULL)
+ {
+ // If a serial number is defined in the CRL
+ if (x->serial == NULL || CompareXSerial(x->serial, crl->Serial) == false)
+ {
+ // Serial number mismatch
+ b = false;
+ }
+ }
+
+ if (IsZero(crl->DigestMD5, sizeof(crl->DigestMD5)) == false)
+ {
+ UCHAR test[MD5_SIZE];
+ // If a DigestMD5 is defined in the CRL
+ GetXDigest(x, test, false);
+
+ if (Cmp(test, crl->DigestMD5, MD5_SIZE) != 0)
+ {
+ b = false;
+ }
+ }
+
+ if (IsZero(crl->DigestSHA1, sizeof(crl->DigestSHA1)) == false)
+ {
+ UCHAR test[SHA1_SIZE];
+ // If a DigestSHA1 is defined in the CRL
+ GetXDigest(x, test, true);
+
+ if (Cmp(test, crl->DigestSHA1, SHA1_SIZE) != 0)
+ {
+ b = false;
+ }
+ }
+
+ if (crl->Name != NULL)
+ {
+ // If a name is defined in the CRL
+ NAME *xn, *cn;
+ xn = x->subject_name;
+ cn = crl->Name;
+
+ if (cn->CommonName != NULL && (UniIsEmptyStr(cn->CommonName) == false))
+ {
+ if (xn->CommonName == NULL || UniSoftStrCmp(xn->CommonName, cn->CommonName) != 0)
+ {
+ // CommonName mismatch
+ b = false;
+ }
+ }
+
+ if (cn->Organization != NULL && (UniIsEmptyStr(cn->Organization) == false))
+ {
+ if (xn->Organization == NULL || UniSoftStrCmp(xn->Organization, cn->Organization) != 0)
+ {
+ // Organization mismatch
+ b = false;
+ }
+ }
+
+ if (cn->Unit != NULL && (UniIsEmptyStr(cn->Unit) == false))
+ {
+ if (xn->Unit == NULL || UniSoftStrCmp(xn->Unit, cn->Unit) != 0)
+ {
+ // Unit mismatch
+ b = false;
+ }
+ }
+
+ if (cn->Country != NULL && (UniIsEmptyStr(cn->Country) == false))
+ {
+ if (xn->Country == NULL || UniSoftStrCmp(xn->Country, cn->Country) != 0)
+ {
+ // Country mismatch
+ b = false;
+ }
+ }
+
+ if (cn->State != NULL && (UniIsEmptyStr(cn->State) == false))
+ {
+ if (xn->State == NULL || UniSoftStrCmp(xn->State, cn->State) != 0)
+ {
+ // State mismatch
+ b = false;
+ }
+ }
+
+ if (cn->Local != NULL && (UniIsEmptyStr(cn->Local) == false))
+ {
+ if (xn->Local == NULL || UniSoftStrCmp(xn->Local, cn->Local) != 0)
+ {
+ // Local mismatch
+ b = false;
+ }
+ }
+ }
+
+ return b;
+}
+
+// Get the help string of administration options
+wchar_t *GetHubAdminOptionHelpString(char *name)
+{
+ char tmp[MAX_SIZE];
+ wchar_t *ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return L"";
+ }
+
+ Format(tmp, sizeof(tmp), "HUB_AO_%s", name);
+
+ ret = _UU(tmp);
+ if (UniIsEmptyStr(ret))
+ {
+ ret = _UU("HUB_AO_UNKNOWN");
+ }
+
+ return ret;
+}
+
+// Add the default administration options to the Virtual HUB
+void AddHubAdminOptionsDefaults(HUB *h, bool lock)
+{
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (lock)
+ {
+ LockList(h->AdminOptionList);
+ }
+
+ for (i = 0;i < num_admin_options;i++)
+ {
+ ADMIN_OPTION *e = &admin_options[i];
+ ADMIN_OPTION t, *r;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), e->Name);
+
+ r = Search(h->AdminOptionList, &t);
+ if (r == NULL)
+ {
+ ADMIN_OPTION *a = ZeroMalloc(sizeof(ADMIN_OPTION));
+
+ StrCpy(a->Name, sizeof(a->Name), e->Name);
+ a->Value = e->Value;
+
+ Insert(h->AdminOptionList, a);
+ }
+ }
+
+ if (lock)
+ {
+ UnlockList(h->AdminOptionList);
+ }
+}
+
+// Delete all administration options of Virtual HUB
+void DeleteAllHubAdminOption(HUB *h, bool lock)
+{
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (lock)
+ {
+ LockList(h->AdminOptionList);
+ }
+
+ for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
+ {
+ Free(LIST_DATA(h->AdminOptionList, i));
+ }
+
+ DeleteAll(h->AdminOptionList);
+
+ if (lock)
+ {
+ UnlockList(h->AdminOptionList);
+ }
+}
+
+// Get the administration options for the virtual HUB
+UINT GetHubAdminOptionEx(HUB *h, char *name, UINT default_value)
+{
+ UINT ret = default_value;
+ // Validate arguments
+ if (h == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ LockList(h->AdminOptionList);
+ {
+ ADMIN_OPTION *a, t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), name);
+ Trim(t.Name);
+
+ a = Search(h->AdminOptionList, &t);
+
+ if (a != NULL)
+ {
+ ret = a->Value;
+ }
+ }
+ UnlockList(h->AdminOptionList);
+
+ return ret;
+}
+UINT GetHubAdminOption(HUB *h, char *name)
+{
+ return GetHubAdminOptionEx(h, name, 0);
+}
+
+// Administration options
+int CompareAdminOption(void *p1, void *p2)
+{
+ ADMIN_OPTION *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(ADMIN_OPTION **)p1;
+ a2 = *(ADMIN_OPTION **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(a1->Name, a2->Name);
+}
+
+// Start the watchdog
+void StartHubWatchDog(HUB *h)
+{
+ THREAD *t;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ h->HaltWatchDog = false;
+ h->WatchDogEvent = NewEvent();
+
+ t = NewThread(HubWatchDogThread, h);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+}
+
+// Stop the watchdog
+void StopHubWatchDog(HUB *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ h->HaltWatchDog = true;
+ Set(h->WatchDogEvent);
+
+ WaitThread(h->WatchDogThread, INFINITE);
+ ReleaseThread(h->WatchDogThread);
+ h->WatchDogThread = NULL;
+ h->HaltWatchDog = false;
+
+ ReleaseEvent(h->WatchDogEvent);
+ h->WatchDogEvent = NULL;
+}
+
+// Watchdog thread
+void HubWatchDogThread(THREAD *t, void *param)
+{
+ UINT num_packets_v4 = 0;
+ UINT num_packets_v6 = 0;
+ HUB *hub;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hub = (HUB *)param;
+
+ hub->WatchDogThread = t;
+ AddRef(t->ref);
+
+ NoticeThreadInit(t);
+
+ while (true)
+ {
+ LIST *o;
+ LIST *o2;
+ UINT i, num;
+ UINT interval;
+ UINT wait_time = 100;
+ if (hub->HaltWatchDog)
+ {
+ break;
+ }
+
+ o = NewListFast(NULL);
+ o2 = NewListFast(NULL);
+
+ // Send an ARP packet
+ LockList(hub->IpTable);
+ {
+ num = LIST_NUM(hub->IpTable);
+ for (i = 0;i < LIST_NUM(hub->IpTable);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
+
+ if ((e->UpdatedTime + (UINT64)(IP_TABLE_EXPIRE_TIME)) > Tick64())
+ {
+ if (e->MacAddress[0] != 0xff || e->MacAddress[1] != 0xff || e->MacAddress[2] != 0xff ||
+ e->MacAddress[3] != 0xff || e->MacAddress[4] != 0xff || e->MacAddress[5] != 0xff)
+ {
+ if (hub->Option != NULL && hub->Option->NoArpPolling == false)
+ {
+ if (IsIP4(&e->Ip))
+ {
+ // IPv4
+ MAC_HEADER *mac = ZeroMalloc(sizeof(MAC_HEADER) + sizeof(ARPV4_HEADER));
+ ARPV4_HEADER *p = (ARPV4_HEADER *)(((UCHAR *)mac) + sizeof(MAC_HEADER));
+
+ Copy(mac->DestAddress, e->MacAddress, 6);
+ Copy(mac->SrcAddress, hub->HubMacAddr, 6);
+ mac->Protocol = Endian16(MAC_PROTO_ARPV4);
+
+ p->HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ p->ProtocolType = Endian16(MAC_PROTO_IPV4);
+ p->HardwareSize = 6;
+ p->ProtocolSize = 4;
+ p->Operation = Endian16(ARP_OPERATION_REQUEST);
+ Copy(p->SrcAddress, hub->HubMacAddr, 6);
+ p->SrcIP = IPToUINT(&hub->HubIp);
+ p->TargetAddress[0] =
+ p->TargetAddress[1] =
+ p->TargetAddress[2] =
+ p->TargetAddress[3] =
+ p->TargetAddress[4] =
+ p->TargetAddress[5] = 0x00;
+ p->TargetIP = IPToUINT(&e->Ip);
+ Insert(o, mac);
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->NoIPv6AddrPolling == false)
+ {
+ if (IsIP6(&e->Ip))
+ {
+ // IPv6
+ BUF *buf;
+ IPV6_ADDR ip6addr;
+
+ if (IPToIPv6Addr(&ip6addr, &e->Ip))
+ {
+ buf = BuildICMPv6NeighborSoliciation(&hub->HubIpV6,
+ &ip6addr,
+ hub->HubMacAddr, ++hub->HubIP6Id);
+
+ if (buf != NULL)
+ {
+ BUF *buf2 = NewBuf();
+ MAC_HEADER mac;
+
+ Zero(&mac, sizeof(mac));
+
+ Copy(mac.DestAddress, e->MacAddress, 6);
+ Copy(mac.SrcAddress, hub->HubMacAddr, 6);
+ mac.Protocol = Endian16(MAC_PROTO_IPV6);
+
+ WriteBuf(buf2, &mac, sizeof(MAC_HEADER));
+
+ WriteBuf(buf2, buf->Buf, buf->Size);
+
+ FreeBuf(buf);
+
+ Insert(o2, buf2);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ UnlockList(hub->IpTable);
+
+ if ((LIST_NUM(o) + LIST_NUM(o2)) != 0)
+ {
+ interval = HUB_ARP_SEND_INTERVAL / (LIST_NUM(o) + LIST_NUM(o2));
+ }
+ else
+ {
+ interval = HUB_ARP_SEND_INTERVAL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PKT *packet;
+ void *p = LIST_DATA(o, i);
+
+ Wait(hub->WatchDogEvent, interval);
+ if (hub->HaltWatchDog)
+ {
+ for (;i < LIST_NUM(o);i++)
+ {
+ Free(LIST_DATA(o, i));
+ }
+ ReleaseList(o);
+
+ for (i = 0;i < LIST_NUM(o2);i++)
+ {
+ FreeBuf(LIST_DATA(o2, i));
+ }
+ ReleaseList(o2);
+ goto ESCAPE;
+ }
+
+ packet = ParsePacket((UCHAR *)p, sizeof(MAC_HEADER) + sizeof(ARPV4_HEADER));
+ if (packet != NULL)
+ {
+ StorePacket(hub, NULL, packet);
+ num_packets_v4++;
+ }
+ else
+ {
+ Free(p);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o2);i++)
+ {
+ PKT *packet;
+ BUF *buf = LIST_DATA(o2, i);
+
+ Wait(hub->WatchDogEvent, interval);
+ if (hub->HaltWatchDog)
+ {
+ ReleaseList(o);
+
+ for (;i < LIST_NUM(o2);i++)
+ {
+ FreeBuf(LIST_DATA(o2, i));
+ }
+ ReleaseList(o2);
+ goto ESCAPE;
+ }
+
+ packet = ParsePacket(buf->Buf, buf->Size);
+ if (packet != NULL)
+ {
+ StorePacket(hub, NULL, packet);
+ num_packets_v6++;
+ }
+ else
+ {
+ Free(buf->Buf);
+ }
+
+ Free(buf);
+ }
+
+ ReleaseList(o);
+ ReleaseList(o2);
+
+ if (num == 0)
+ {
+ wait_time = HUB_ARP_SEND_INTERVAL;
+ }
+
+ Wait(hub->WatchDogEvent, wait_time);
+ }
+ESCAPE:
+ return;
+}
+
+// Eable / disable the SecureNAT
+void EnableSecureNAT(HUB *h, bool enable)
+{
+ EnableSecureNATEx(h, enable, false);
+}
+void EnableSecureNATEx(HUB *h, bool enable, bool no_change)
+{
+ bool for_cluster = false;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ for_cluster = true;
+ }
+ }
+
+ Lock(h->lock_online);
+ {
+ if (no_change == false)
+ {
+ h->EnableSecureNAT = enable;
+ }
+
+ if (h->EnableSecureNAT == false)
+ {
+STOP:
+ // Stop if it's already started
+ if (h->SecureNAT != NULL)
+ {
+ SnFreeSecureNAT(h->SecureNAT);
+ h->SecureNAT = NULL;
+ }
+ }
+ else
+ {
+ if (for_cluster)
+ {
+ if ((h->SecureNAT != NULL && LIST_NUM(h->SessionList) <= 1) ||
+ (h->SecureNAT == NULL && LIST_NUM(h->SessionList) == 0))
+ {
+ // It is in a start mode, but stop when there is no other sessions
+ // in the case of dynamic Virtual HUB
+ goto STOP;
+ }
+ }
+
+ // Start if the HUB is online and not started
+ if (h->SecureNAT == NULL && h->Offline == false)
+ {
+ h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);
+ }
+ }
+ }
+ Unlock(h->lock_online);
+}
+
+// Convert an access list to a string
+void GetAccessListStr(char *str, UINT size, ACCESS *a)
+{
+ char tmp[MAX_SIZE];
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ bool l3 = false;
+ bool asterisk = false;
+ // Validate arguments
+ if (str == NULL || a == NULL)
+ {
+ return;
+ }
+
+ StrCpy(str, size, "");
+
+ if (a->IsIPv6 == false)
+ {
+ if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)
+ {
+ IPToStr32(tmp1, sizeof(tmp1), a->SrcIpAddress);
+ MaskToStr32(tmp2, sizeof(tmp2), a->SrcSubnetMask);
+ Format(tmp, sizeof(tmp), "SrcIPv4=%s/%s, ", tmp1, tmp2);
+ StrCat(str, size, tmp);
+
+ l3 = true;
+ }
+
+ if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)
+ {
+ IPToStr32(tmp1, sizeof(tmp1), a->DestIpAddress);
+ MaskToStr32(tmp2, sizeof(tmp2), a->DestSubnetMask);
+ Format(tmp, sizeof(tmp), "DstIPv4=%s/%s, ", tmp1, tmp2);
+ StrCat(str, size, tmp);
+
+ l3 = true;
+ }
+ }
+ else
+ {
+ if (IsZeroIP6Addr(&a->SrcIpAddress6) == false || IsZeroIP6Addr(&a->SrcSubnetMask6) == false)
+ {
+ IP6AddrToStr(tmp1, sizeof(tmp1), &a->SrcIpAddress6);
+ Mask6AddrToStr(tmp2, sizeof(tmp2), &a->SrcSubnetMask6);
+ Format(tmp, sizeof(tmp), "SrcIPv6=%s/%s, ", tmp1, tmp2);
+ StrCat(str, size, tmp);
+
+ l3 = true;
+ }
+
+ if (IsZeroIP6Addr(&a->DestIpAddress6) == false || IsZeroIP6Addr(&a->DestSubnetMask6) == false)
+ {
+ IP6AddrToStr(tmp1, sizeof(tmp1), &a->DestIpAddress6);
+ Mask6AddrToStr(tmp2, sizeof(tmp2), &a->DestSubnetMask6);
+ Format(tmp, sizeof(tmp), "DstIPv6=%s/%s, ", tmp1, tmp2);
+ StrCat(str, size, tmp);
+
+ l3 = true;
+ }
+ }
+
+ if (a->Protocol != 0)
+ {
+ StrCpy(tmp1, sizeof(tmp1), "");
+ switch (a->Protocol)
+ {
+ case 1:
+ StrCpy(tmp1, sizeof(tmp1), "ICMPv4");
+ break;
+ case 3:
+ StrCpy(tmp1, sizeof(tmp1), "GGP");
+ break;
+ case 6:
+ StrCpy(tmp1, sizeof(tmp1), "TCP");
+ break;
+ case 8:
+ StrCpy(tmp1, sizeof(tmp1), "EGP");
+ break;
+ case 12:
+ StrCpy(tmp1, sizeof(tmp1), "PUP");
+ break;
+ case 17:
+ StrCpy(tmp1, sizeof(tmp1), "UDP");
+ break;
+ case 20:
+ StrCpy(tmp1, sizeof(tmp1), "HMP");
+ break;
+ case 22:
+ StrCpy(tmp1, sizeof(tmp1), "XNS-IDP");
+ break;
+ case 27:
+ StrCpy(tmp1, sizeof(tmp1), "RDP");
+ break;
+ case 58:
+ StrCpy(tmp1, sizeof(tmp1), "ICMPv6");
+ break;
+ case 66:
+ StrCpy(tmp1, sizeof(tmp1), "RVD");
+ break;
+ }
+
+ if (IsEmptyStr(tmp1))
+ {
+ Format(tmp, sizeof(tmp), "Protocol=%s(%u), ", tmp1, a->Protocol);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "Protocol=%s, ", tmp1);
+ }
+
+ StrCat(str, size, tmp);
+
+ l3 = true;
+ }
+
+ if (a->SrcPortStart != 0)
+ {
+ if (a->SrcPortEnd == a->SrcPortStart)
+ {
+ Format(tmp, sizeof(tmp), "SrcPort=%u, ", a->SrcPortStart);
+ StrCat(str, size, tmp);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "SrcPort=%u-%u, ", a->SrcPortStart, a->SrcPortEnd);
+ StrCat(str, size, tmp);
+ }
+
+ l3 = true;
+ }
+
+ if (a->DestPortStart != 0)
+ {
+ if (a->DestPortEnd == a->DestPortStart)
+ {
+ Format(tmp, sizeof(tmp), "DstPort=%u, ", a->DestPortStart);
+ StrCat(str, size, tmp);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "DstPort=%u-%u, ", a->DestPortStart, a->DestPortEnd);
+ StrCat(str, size, tmp);
+ }
+
+ l3 = true;
+ }
+
+ if (StrLen(a->SrcUsername) != 0)
+ {
+ Format(tmp, sizeof(tmp), "SrcUser=%s, ", a->SrcUsername);
+ StrCat(str, size, tmp);
+ }
+
+ if (StrLen(a->DestUsername) != 0)
+ {
+ Format(tmp, sizeof(tmp), "DstUser=%s, ", a->DestUsername);
+ StrCat(str, size, tmp);
+ }
+
+ if (a->CheckSrcMac != false)
+ {
+ char mac[MAX_SIZE], mask[MAX_SIZE];
+ MacToStr(mac, sizeof(mac), a->SrcMacAddress);
+ MacToStr(mask, sizeof(mask), a->SrcMacMask);
+ Format(tmp, sizeof(tmp), "SrcMac=%s/%s, ", mac, mask);
+ StrCat(str, size, tmp);
+ }
+ if (a->CheckDstMac != false)
+ {
+ char mac[MAX_SIZE], mask[MAX_SIZE];
+ MacToStr(mac, sizeof(mac), a->DstMacAddress);
+ MacToStr(mask, sizeof(mask), a->DstMacMask);
+ Format(tmp, sizeof(tmp), "DstMac=%s/%s, ", mac, mask);
+ StrCat(str, size, tmp);
+ }
+
+ if (a->CheckTcpState)
+ {
+ if(a->Established)
+ {
+ StrCat(str, size, "Established, ");
+ }
+ else
+ {
+ StrCat(str, size, "Unestablished, ");
+ }
+
+ l3 = true;
+ }
+
+ if (a->Discard == false)
+ {
+ if (a->Delay >= 1)
+ {
+ Format(tmp, sizeof(tmp), "Delay=%u, ", a->Delay);
+ StrCat(str, size, tmp);
+ }
+
+ if (a->Jitter >= 1)
+ {
+ Format(tmp, sizeof(tmp), "Jitter=%u, ", a->Jitter);
+ StrCat(str, size, tmp);
+ }
+
+ if (a->Loss >= 1)
+ {
+ Format(tmp, sizeof(tmp), "Loss=%u, " , a->Loss);
+ StrCat(str, size, tmp);
+ }
+ }
+
+ if (IsEmptyStr(a->RedirectUrl) == false)
+ {
+ Format(tmp, sizeof(tmp), "RedirectUrl=%s, ", a->RedirectUrl);
+ StrCat(str, size, tmp);
+ }
+
+ if (StrLen(str) == 0)
+ {
+ asterisk = true;
+ }
+
+ if (l3)
+ {
+ if (a->IsIPv6)
+ {
+ StrCatLeft(str, size, "(ipv6) ");
+ }
+ else
+ {
+ StrCatLeft(str, size, "(ipv4) ");
+ }
+ }
+ else
+ {
+ StrCatLeft(str, size, "(ether) ");
+ }
+
+ if (EndWith(str, ", "))
+ {
+ str[StrLen(str) - 2] = 0;
+ }
+
+ if (asterisk)
+ {
+ StrCat(str, size, "*");
+ }
+}
+
+// Determine whether the access list can mask the packet
+bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT64 dest_username, UINT64 dest_groupname, SESSION *dest_session)
+{
+ UINT64 src_username;
+ UINT64 src_username_simple;
+ UINT64 src_groupname;
+ HUB_PA *pa;
+ IPV4_HEADER *ip = NULL;
+ IPV6_HEADER *ip6 = NULL;
+ bool is_ipv4_packet = false;
+ bool is_ipv6_packet = false;
+ // Validate arguments
+ if (s == NULL || p == NULL || a == NULL)
+ {
+ return false;
+ }
+ if (a->Active == false)
+ {
+ // Access list is inactive
+ return false;
+ }
+
+ pa = (HUB_PA *)s->PacketAdapter->Param;
+
+ // Hash of the source user name
+ src_username = pa->UsernameHash;
+ src_username_simple = pa->UsernameHashSimple;
+ src_groupname = pa->GroupnameHash;
+
+ // Determine the source and destination MAC address
+ if (a->CheckSrcMac != false)
+ {
+ UINT i;
+ for (i = 0; i < 6; i++)
+ {
+ if((a->SrcMacAddress[i] & a->SrcMacMask[i]) != (a->SrcMacMask[i] & p->MacAddressSrc[i]))
+ {
+ return false;
+ }
+ }
+ }
+
+ if (a->CheckDstMac != false)
+ {
+ UINT i;
+ for (i = 0; i < 6; i++)
+ {
+ if ((a->DstMacAddress[i] & a->DstMacMask[i]) != (a->DstMacMask[i] & p->MacAddressDest[i]))
+ {
+ return false;
+ }
+ }
+ }
+
+ // Check the source user name / group name
+ if (a->SrcUsernameHash != 0)
+ {
+ if (a->IsSrcUsernameIncludeOrExclude == false)
+ {
+ // It is specified as a regular user name
+ if ((a->SrcUsernameHash != src_username) && (a->SrcUsernameHash != src_groupname))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // It is specified in the form of a exclude:FILENAME or include:FILENAME
+ HUB *hub = s->Hub;
+
+ if (hub != NULL)
+ {
+ LIST *o = hub->UserList;
+
+ if (s->NormalClient == false)
+ {
+ // The internal session don't become target for format exclude: or include:
+ return false;
+ }
+
+ if (IsUserMatchInUserListWithCacheExpiresAcl(o, a->SrcUsername, src_username,
+ hub->Option->AccessListIncludeFileCacheLifetime * 1000) == false)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Check the destination user name / group name
+ if (a->DestUsernameHash != 0)
+ {
+ if (a->IsDestUsernameIncludeOrExclude == false)
+ {
+ // It is specified as a regular user name
+ if ((a->DestUsernameHash != dest_username) && (a->DestUsernameHash != dest_groupname))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // It is specified in the form of a exclude:FILENAME or include:FILENAME
+ HUB *hub = s->Hub;
+
+ if (hub != NULL)
+ {
+ LIST *o = hub->UserList;
+
+ if (dest_session != NULL && dest_session->NormalClient == false)
+ {
+ // The internal session don't become target for format exclude: or include:
+ return false;
+ }
+
+ if (IsUserMatchInUserListWithCacheExpiresAcl(o, a->DestUsername, dest_username,
+ hub->Option->AccessListIncludeFileCacheLifetime * 1000) == false)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Determine of the IP packet
+ if (p->TypeL3 != L3_IPV4)
+ {
+ is_ipv4_packet = false;
+ }
+ else
+ {
+ is_ipv4_packet = true;
+ }
+
+ if (p->TypeL3 != L3_IPV6)
+ {
+ is_ipv6_packet = false;
+ }
+ else
+ {
+ is_ipv6_packet = true;
+ }
+
+ if (is_ipv4_packet)
+ {
+ ip = p->L3.IPv4Header;
+ }
+
+ if (is_ipv6_packet)
+ {
+ ip6 = p->L3.IPv6Header;
+ }
+
+ if (a->IsIPv6 == false)
+ {
+ // IPv4
+
+ // Check the source IP address
+ if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)
+ {
+ if (is_ipv4_packet == false)
+ {
+ if (p->TypeL3 == L3_ARPV4)
+ {
+ bool arp_match = false;
+ if (p->L3.ARPv4Header->HardwareSize == 6 &&
+ Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
+ p->L3.ARPv4Header->ProtocolSize == 4 &&
+ Endian16(p->L3.ARPv4Header->ProtocolType) == 0x0800)
+ {
+ UINT uint_ip = p->L3.ARPv4Header->SrcIP;
+
+ if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))
+ {
+ if ((uint_ip & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))
+ {
+ }
+ else
+ {
+ arp_match = true;
+ }
+ }
+ }
+
+ if (arp_match == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if ((ip->SrcIP & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))
+ {
+ return false;
+ }
+ }
+ }
+
+ // Check the destination IP address
+ if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)
+ {
+ if (is_ipv4_packet == false)
+ {
+ if (p->TypeL3 == L3_ARPV4)
+ {
+ bool arp_match = false;
+ if (p->L3.ARPv4Header->HardwareSize == 6 &&
+ Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
+ p->L3.ARPv4Header->ProtocolSize == 4 &&
+ Endian16(p->L3.ARPv4Header->ProtocolType) == 0x0800)
+ {
+ UINT uint_ip = p->L3.ARPv4Header->TargetIP;
+
+ if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))
+ {
+ if ((uint_ip & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))
+ {
+ }
+ else
+ {
+ arp_match = true;
+ }
+ }
+ }
+
+ if (arp_match == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if ((ip->DstIP & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ // IPv6
+
+ // Check the source IP address
+ if (IsZeroIP6Addr(&a->SrcIpAddress6) == false ||
+ IsZeroIP6Addr(&a->SrcSubnetMask6) == false)
+ {
+ if (is_ipv6_packet == false)
+ {
+ return false;
+ }
+ else
+ {
+ IP a_ip, a_subnet, p_ip;
+ IP and1, and2;
+
+ IPv6AddrToIP(&a_ip, &a->SrcIpAddress6);
+ IPv6AddrToIP(&a_subnet, &a->SrcSubnetMask6);
+ IPv6AddrToIP(&p_ip, &ip6->SrcAddress);
+
+ IPAnd6(&and1, &a_ip, &a_subnet);
+ IPAnd6(&and2, &p_ip, &a_subnet);
+
+ if (CmpIpAddr(&and1, &and2) != 0)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Check the destination IP address
+ if (IsZeroIP6Addr(&a->DestIpAddress6) == false ||
+ IsZeroIP6Addr(&a->DestSubnetMask6) == false)
+ {
+ if (is_ipv6_packet == false)
+ {
+ return false;
+ }
+ else
+ {
+ IP a_ip, a_subnet, p_ip;
+ IP and1, and2;
+
+ IPv6AddrToIP(&a_ip, &a->DestIpAddress6);
+ IPv6AddrToIP(&a_subnet, &a->DestSubnetMask6);
+ IPv6AddrToIP(&p_ip, &ip6->DestAddress);
+
+ IPAnd6(&and1, &a_ip, &a_subnet);
+ IPAnd6(&and2, &p_ip, &a_subnet);
+
+ if (CmpIpAddr(&and1, &and2) != 0)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Don't match the packet of non-IPv4 and non-IPv6
+ if (is_ipv4_packet == false && is_ipv6_packet==false)
+ {
+ if (s->Hub != NULL && s->Hub->Option != NULL && s->Hub->Option->ApplyIPv4AccessListOnArpPacket)
+ {
+ // Match the ARP only if ApplyIPv4AccessListOnArpPacket option is enabled
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Check the protocol number
+ if (a->Protocol != 0)
+ {
+ if (a->IsIPv6 == false)
+ {
+ if (is_ipv4_packet == false)
+ {
+ return false;
+ }
+ else
+ {
+ if (ip->Protocol != a->Protocol)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (is_ipv6_packet == false)
+ {
+ return false;
+ }
+ else
+ {
+ if (p->IPv6HeaderPacketInfo.Protocol != a->Protocol)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Check the port number
+ if (a->SrcPortStart != 0 || a->DestPortStart != 0 ||
+ a->SrcPortEnd != 0 || a->DestPortEnd != 0)
+ {
+ if ((a->IsIPv6 == false && is_ipv4_packet == false) ||
+ (a->IsIPv6 && is_ipv6_packet == false))
+ {
+ return false;
+ }
+ else
+ {
+ if (p->TypeL4 == L4_TCP)
+ {
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+ // Check the source port
+ if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)
+ {
+ UINT src_port = Endian16(tcp->SrcPort);
+ if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)
+ {
+ return false;
+ }
+ }
+
+ // Check the destination port number
+ if (a->DestPortStart != 0 || a->DestPortEnd != 0)
+ {
+ UINT dest_port = Endian16(tcp->DstPort);
+ if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)
+ {
+ return false;
+ }
+ }
+ }
+ else if (p->TypeL4 == L4_UDP)
+ {
+ UDP_HEADER *udp = p->L4.UDPHeader;
+ // Check the source port
+ if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)
+ {
+ UINT src_port = Endian16(udp->SrcPort);
+ if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)
+ {
+ return false;
+ }
+ }
+
+ // Check the destination port number
+ if (a->DestPortStart != 0 || a->DestPortEnd != 0)
+ {
+ UINT dest_port = Endian16(udp->DstPort);
+ if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // When the port number is specified in the access list,
+ // The rule is applied only for UDP or TCP packets
+ return false;
+ }
+ }
+ }
+
+ // Check the status of the TCP connection
+ if (a->CheckTcpState != false)
+ {
+ if ((a->IsIPv6 == false && is_ipv4_packet == false) ||
+ (a->IsIPv6 && is_ipv6_packet == false))
+ {
+ return false;
+ }
+ else
+ {
+ if(p->TypeL4 == L4_TCP)
+ {
+ // by shimizu
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+ bool est = true;
+
+ if ((tcp->Flag & TCP_SYN) && (!(tcp->Flag & TCP_ACK)))
+ {
+ est = false;
+ }
+
+ if((MAKEBOOL(a->Established) ^ MAKEBOOL(est)))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Apply the access list for packets to forward
+bool ApplyAccessListToForwardPacket(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *p)
+{
+ UINT i;
+ bool pass = true; // Pass by default
+ bool skip = true;
+ // Validate arguments
+ if (hub == NULL || src_session == NULL || p == NULL || dest_session == NULL)
+ {
+ return false;
+ }
+
+ // The access list is not re-applied for packets that have been already checked
+ if (p->AccessChecked)
+ {
+ return true;
+ }
+
+ LockList(hub->AccessList);
+ {
+ for (i = 0;i < LIST_NUM(hub->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(hub->AccessList, i);
+
+ // Scan the entry only after the destination user name is specified.
+ if (a->DestUsernameHash != 0)
+ {
+ skip = false;
+ }
+
+ if (skip == false)
+ {
+ if (IsPacketMaskedByAccessList(src_session, p, a,
+ ((HUB_PA *)dest_session->PacketAdapter->Param)->UsernameHash,
+ ((HUB_PA *)dest_session->PacketAdapter->Param)->GroupnameHash,
+ dest_session))
+ {
+ // Determine the pass or discard the packet
+ pass = a->Discard ? false : true;
+
+ // Complete the scanning of the list here
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(hub->AccessList);
+
+ return pass;
+}
+
+// Generate a HTTP payload for redirect
+BUF *BuildRedirectToUrlPayload(HUB *hub, SESSION *s, char *redirect_url)
+{
+ char html[MAX_REDIRECT_URL_LEN * 2 + 1 + MAX_SIZE];
+ char header[MAX_REDIRECT_URL_LEN * 2 + 1 + MAX_SIZE];
+ char redirect_url2[MAX_REDIRECT_URL_LEN * 2];
+ BUF *b;
+ // Validate arguments
+ if (hub == NULL || s == NULL || redirect_url == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(redirect_url2, sizeof(redirect_url2), redirect_url);
+ Trim(redirect_url2);
+
+ if (InStr(redirect_url2, ACCESS_LIST_URL_INFO_TAG))
+ {
+ // Get the secret key string
+ char secret[MAX_SIZE];
+ char tmp[MAX_SIZE];
+ SYSTEMTIME st;
+ UINT i, len, isp;
+
+ isp = INFINITE;
+
+ SystemTime(&st);
+ ClearStr(secret, sizeof(secret));
+
+ len = StrLen(redirect_url2);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = redirect_url2[i];
+ if (c == '|')
+ {
+ isp = i;
+ }
+ }
+
+ if (isp != INFINITE)
+ {
+ StrCpy(secret, sizeof(secret), redirect_url2 + isp + 1);
+ redirect_url2[isp] = 0;
+ }
+
+ Format(tmp, sizeof(tmp), "%s|%s|%r|%04u%02u%02u%02u%02u%02u%s",
+ s->Username, s->Name, &s->Connection->ClientIp,
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, (IsEmptyStr(secret) ? "" : "|"));
+
+ if (IsEmptyStr(secret) == false)
+ {
+ // Calculate the hash
+ UCHAR hash[SHA1_SIZE];
+ char hash_str[MAX_SIZE];
+ BUF *b2 = NewBuf();
+
+ WriteBuf(b2, tmp, StrLen(tmp));
+ WriteBuf(b2, secret, StrLen(secret));
+
+ HashSha1(hash, b2->Buf, b2->Size);
+
+ BinToStr(hash_str, sizeof(hash_str), hash, sizeof(hash));
+
+ FreeBuf(b2);
+
+ StrCat(tmp, sizeof(tmp), hash_str);
+
+ // Replace
+ ReplaceStrEx(redirect_url2, sizeof(redirect_url2), redirect_url2,
+ ACCESS_LIST_URL_INFO_TAG, tmp, false);
+ }
+ }
+
+ Format(html, sizeof(html),
+ "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved to <a href=\"%s\">here</a>.</h2>\r\n</body></html>\r\n\r\n",
+ redirect_url2);
+
+ Format(header, sizeof(header),
+ "HTTP/1.1 302 Found\r\nLocation: %s\r\nCache-Control: private\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %u\r\n\r\n",
+ redirect_url2, StrLen(redirect_url2));
+
+ b = NewBuf();
+
+ WriteBuf(b, header, StrLen(header));
+ WriteBuf(b, html, StrLen(html));
+
+ return b;
+}
+
+// Rpely a TCP response packet to redirect forcibly to the specified URL
+void ForceRedirectToUrl(HUB *hub, SESSION *src_session, PKT *p, char *redirect_url)
+{
+ BUF *payload;
+ UINT tcp_size;
+ TCP_HEADER *tcp_data;
+ TCP_HEADER *src_tcp;
+ BUF *b;
+ // Validate arguments
+ if (hub == NULL || src_session == NULL || p == NULL || redirect_url == NULL)
+ {
+ return;
+ }
+ if (p->TypeL3 != L3_IPV4 && p->TypeL3 != L3_IPV6)
+ {
+ return;
+ }
+ if (p->TypeL4 != L4_TCP)
+ {
+ return;
+ }
+
+ src_tcp = p->L4.TCPHeader;
+ if (src_tcp == NULL)
+ {
+ return;
+ }
+
+ // Generate a payload to be sent
+ payload = BuildRedirectToUrlPayload(hub, src_session, redirect_url);
+ if (payload == NULL)
+ {
+ return;
+ }
+
+ // Generate a TCP packet
+ tcp_size = sizeof(TCP_HEADER) + payload->Size;
+ tcp_data = (TCP_HEADER *)ZeroMalloc(tcp_size);
+ tcp_data->SrcPort = src_tcp->DstPort;
+ tcp_data->DstPort = src_tcp->SrcPort;
+ tcp_data->SeqNumber = src_tcp->AckNumber;
+ tcp_data->AckNumber = Endian32(Endian32(src_tcp->SeqNumber) + p->PayloadSize);
+ TCP_SET_HEADER_SIZE(tcp_data, 5);
+ tcp_data->Flag = TCP_ACK | TCP_PSH;
+ tcp_data->WindowSize = Endian16(0xFFFF);
+ Copy(((UCHAR *)tcp_data) + sizeof(TCP_HEADER), payload->Buf, payload->Size);
+
+ // Calculate the TCP checksum
+ if (p->TypeL3 == L3_IPV4)
+ {
+ // IPv4
+ tcp_data->Checksum = CalcChecksumForIPv4(p->L3.IPv4Header->DstIP, p->L3.IPv4Header->SrcIP, IP_PROTO_TCP,
+ tcp_data, tcp_size, 0);
+ }
+ else
+ {
+ // IPv6
+ tcp_data->Checksum = CalcChecksumForIPv6(&p->IPv6HeaderPacketInfo.IPv6Header->DestAddress,
+ &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress, IP_PROTO_TCP, tcp_data, tcp_size, 0);
+ }
+
+ // Generate the Ethernet and IP packet
+ b = NewBuf();
+
+ // Destination MAC address
+ WriteBuf(b, p->MacHeader->SrcAddress, 6);
+ WriteBuf(b, p->MacHeader->DestAddress, 6);
+ WriteBuf(b, &p->MacHeader->Protocol, 2);
+
+ if (p->TypeL3 == L3_IPV4)
+ {
+ // IPv4
+ IPV4_HEADER v4;
+
+ Zero(&v4, sizeof(v4));
+
+ IPV4_SET_VERSION(&v4, 4);
+ IPV4_SET_HEADER_LEN(&v4, 5);
+ v4.TotalLength = Endian16((USHORT)(sizeof(IPV4_HEADER) + tcp_size));
+ v4.Identification = Endian16(Rand16());
+ IPV4_SET_FLAGS(&v4, 0x02);
+ v4.TimeToLive = 128;
+ v4.Protocol = IP_PROTO_TCP;
+ v4.SrcIP = p->L3.IPv4Header->DstIP;
+ v4.DstIP = p->L3.IPv4Header->SrcIP;
+ v4.Checksum = IpChecksum(&v4, sizeof(v4));
+
+ WriteBuf(b, &v4, sizeof(v4));
+ }
+ else
+ {
+ // IPv6
+ IPV6_HEADER v6;
+
+ Zero(&v6, sizeof(v6));
+
+ IPV6_SET_VERSION(&v6, 6);
+ v6.PayloadLength = Endian16(tcp_size);
+ v6.NextHeader = IP_PROTO_TCP;
+ v6.HopLimit = 64;
+
+ Copy(&v6.SrcAddress, &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress, sizeof(IPV6_ADDR));
+ Copy(&v6.DestAddress, &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress, sizeof(IPV6_ADDR));
+
+ WriteBuf(b, &v6, sizeof(v6));
+ }
+
+ WriteBuf(b, tcp_data, tcp_size);
+
+ // Reply packet
+ StorePacketToHubPa((HUB_PA *)src_session->PacketAdapter->Param,
+ NULL, b->Buf, b->Size, NULL);
+
+ // Release the memory
+ Free(tcp_data);
+ FreeBuf(payload);
+ Free(b);
+}
+
+// Apply the access list for packets stored
+bool ApplyAccessListToStoredPacket(HUB *hub, SESSION *s, PKT *p)
+{
+ UINT i;
+ bool pass = true; // Pass by default
+ bool use_redirect_url = false;
+ char redirect_url[MAX_REDIRECT_URL_LEN + 1];
+ // Validate arguments
+ if (hub == NULL || s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterPPPoE)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (proto == 0x8863 || proto == 0x8864)
+ {
+ // PPPoE Filter
+ return false;
+ }
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterOSPF)
+ {
+ if (p->TypeL3 == L3_IPV4)
+ {
+ if (p->L3.IPv4Header != NULL)
+ {
+ if (p->L3.IPv4Header->Protocol == 89)
+ {
+ // OSPF Filter
+ return false;
+ }
+ }
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterIPv4)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (proto == 0x0800 || proto == 0x0806)
+ {
+ // IPv4 Filter
+ return false;
+ }
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterIPv6)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (proto == 0x86dd)
+ {
+ // IPv6 Filter
+ return false;
+ }
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterNonIP)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))
+ {
+ // Non-IP Filter
+ return false;
+ }
+ }
+ }
+
+ if (hub->Option != NULL && hub->Option->FilterBPDU)
+ {
+ if (p->MacHeader != NULL)
+ {
+ if (p->TypeL3 == L3_BPDU)
+ {
+ // BPDU Filter
+ return false;
+ }
+ }
+ }
+
+ LockList(hub->AccessList);
+ {
+ for (i = 0;i < LIST_NUM(hub->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(hub->AccessList, i);
+
+ if (a->DestUsernameHash != 0)
+ {
+ // If a destination user name is specified, suspend the scanning of the list.
+ break;
+ }
+
+ if (IsPacketMaskedByAccessList(s, p, a, 0, 0, NULL))
+ {
+ // Determine the pass or discard the packet
+ pass = a->Discard ? false : true;
+
+ // Packets determined processing here is not scanned when leaving the HUB.
+ p->AccessChecked = true;
+
+ // Copy of the parameters of the delay jitter packet loss
+ p->Delay = a->Delay;
+ p->Jitter = a->Jitter;
+ p->Loss = a->Loss;
+
+ if (a->RedirectUrl[0] != 0)
+ {
+ // There is a setting of URL redirection in the access list
+ if ((p->TypeL3 == L3_IPV4 || p->TypeL3 == L3_IPV6) &&
+ p->TypeL4 == L4_TCP)
+ {
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ // Examine whether this packet is a TCP data packet
+ if (tcp != NULL)
+ {
+ if (tcp->Flag & TCP_ACK)
+ {
+ if ((tcp->Flag & TCP_SYN) == 0 &&
+ (tcp->Flag & TCP_RST) == 0 &&
+ (tcp->Flag & TCP_URG) == 0)
+ {
+ if (p->PayloadSize != 0)
+ {
+ // Do URL redirection
+ use_redirect_url = true;
+ StrCpy(redirect_url, sizeof(redirect_url), a->RedirectUrl);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Complete the scanning of the list here
+ break;
+ }
+ }
+ }
+ UnlockList(hub->AccessList);
+
+ if (pass)
+ {
+ if (s != NULL && s->FirstTimeHttpRedirect && s->FirstTimeHttpAccessCheckIp != 0)
+ {
+ if ((p->TypeL3 == L3_IPV4 || p->TypeL3 == L3_IPV6) &&
+ p->TypeL4 == L4_TCP)
+ {
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ // Examine whether this packet is a TCP data packet
+ if (tcp != NULL)
+ {
+ if (tcp->DstPort == Endian16(80))
+ {
+ if (p->L3.IPv4Header->DstIP == s->FirstTimeHttpAccessCheckIp)
+ {
+ s->FirstTimeHttpRedirect = false;
+ }
+ else if (tcp->Flag & TCP_ACK)
+ {
+ if ((tcp->Flag & TCP_SYN) == 0 &&
+ (tcp->Flag & TCP_RST) == 0 &&
+ (tcp->Flag & TCP_URG) == 0)
+ {
+ if (p->PayloadSize != 0)
+ {
+ if (IsTcpPacketNcsiHttpAccess(p) == false)
+ {
+/* char tmp[4000];
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, p->Payload, p->PayloadSize);
+ Debug("HTTP: %s\n", tmp);*/
+ if (IsEmptyStr(s->FirstTimeHttpRedirectUrl) == false)
+ {
+ use_redirect_url = true;
+ StrCpy(redirect_url, sizeof(redirect_url), s->FirstTimeHttpRedirectUrl);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (use_redirect_url)
+ {
+ if (s->NormalClient)
+ {
+ // In the case of a normal VPN client (Not a local bridge, a SecureNAT, and not a virtual L3 switch),
+ // process URL redirection and discard the packet
+ ForceRedirectToUrl(hub, s, p, redirect_url);
+ }
+ else
+ {
+ // Discard packets that is sent from the sessions such as local bridge,
+ // SecureNAT, virtual L3 switch
+ }
+
+ pass = false;
+ }
+
+ return pass;
+}
+
+// Check whether the TCP packet is NCSI accessing
+bool IsTcpPacketNcsiHttpAccess(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ if (p->TypeL4 != L4_TCP)
+ {
+ return false;
+ }
+
+ if (p->Payload == NULL || p->PayloadSize == 0)
+ {
+ return false;
+ }
+
+ if (SearchBin(p->Payload, 0, p->PayloadSize, "NCSI", 4) != INFINITE)
+ {
+ return true;
+ }
+
+ if (SearchBin(p->Payload, 0, p->PayloadSize, ".jpeg", 5) != INFINITE)
+ {
+ return true;
+ }
+
+ if (SearchBin(p->Payload, 0, p->PayloadSize, ".jpg", 4) != INFINITE)
+ {
+ return true;
+ }
+
+ if (SearchBin(p->Payload, 0, p->PayloadSize, ".gif", 4) != INFINITE)
+ {
+ return true;
+ }
+
+ if (SearchBin(p->Payload, 0, p->PayloadSize, ".css", 4) != INFINITE)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Set the URL to which to redirect first
+bool SetSessionFirstRedirectHttpUrl(SESSION *s, char *url)
+{
+ URL_DATA d;
+ IP ip;
+ // Validate arguments
+ if (s == NULL || url == NULL || IsEmptyStr(url))
+ {
+ return false;
+ }
+
+ if (ParseUrl(&d, url, false, NULL) == false)
+ {
+ return false;
+ }
+
+ if (StrToIP(&ip, d.HostName) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(&ip) == false)
+ {
+ return false;
+ }
+
+ s->FirstTimeHttpAccessCheckIp = IPToUINT(&ip);
+ StrCpy(s->FirstTimeHttpRedirectUrl, sizeof(s->FirstTimeHttpRedirectUrl), url);
+ s->FirstTimeHttpRedirect = true;
+
+ return true;
+}
+
+// Adding Access List
+void AddAccessList(HUB *hub, ACCESS *a)
+{
+ AddAccessListEx(hub, a, false, false);
+}
+void AddAccessListEx(HUB *hub, ACCESS *a, bool no_sort, bool no_reassign_id)
+{
+ // Validate arguments
+ if (hub == NULL || a == NULL)
+ {
+ return;
+ }
+
+ LockList(hub->AccessList);
+ {
+ ACCESS *access;
+ UINT i;
+
+ // Check the number of items
+ if (LIST_NUM(hub->AccessList) >= MAX_ACCESSLISTS)
+ {
+ UnlockList(hub->AccessList);
+ return;
+ }
+
+ access = Malloc(sizeof(ACCESS));
+ Copy(access, a, sizeof(ACCESS));
+
+ access->IsSrcUsernameIncludeOrExclude = false;
+ access->IsDestUsernameIncludeOrExclude = false;
+
+ // User name correction
+ if (IsEmptyStr(access->SrcUsername) == false)
+ {
+ if (StartWith(access->SrcUsername, ACCESS_LIST_INCLUDED_PREFIX) == false && StartWith(access->SrcUsername, ACCESS_LIST_EXCLUDED_PREFIX) == false)
+ {
+ MakeSimpleUsernameRemoveNtDomain(access->SrcUsername, sizeof(access->SrcUsername), access->SrcUsername);
+ }
+ else
+ {
+ access->IsSrcUsernameIncludeOrExclude = true;
+ }
+ }
+ if (IsEmptyStr(access->DestUsername) == false)
+ {
+ if (StartWith(access->DestUsername, ACCESS_LIST_INCLUDED_PREFIX) == false && StartWith(access->DestUsername, ACCESS_LIST_EXCLUDED_PREFIX) == false)
+ {
+ MakeSimpleUsernameRemoveNtDomain(access->DestUsername, sizeof(access->DestUsername), access->DestUsername);
+ }
+ else
+ {
+ access->IsDestUsernameIncludeOrExclude = true;
+ }
+ }
+
+ access->SrcUsernameHash = UsernameToInt64(access->SrcUsername);
+ access->DestUsernameHash = UsernameToInt64(access->DestUsername);
+
+ // Port number correction
+ if (access->SrcPortStart != 0)
+ {
+ access->SrcPortEnd = MAX(access->SrcPortEnd, access->SrcPortStart);
+ }
+ if (access->DestPortStart != 0)
+ {
+ access->DestPortEnd = MAX(access->DestPortEnd, access->DestPortStart);
+ }
+
+ // Correct delay, jitter, and packet loss
+ access->Delay = MAKESURE(access->Delay, 0, HUB_ACCESSLIST_DELAY_MAX);
+ access->Jitter = MAKESURE(access->Jitter, 0, HUB_ACCESSLIST_JITTER_MAX);
+ access->Loss = MAKESURE(access->Loss, 0, HUB_ACCESSLIST_LOSS_MAX);
+
+ if (no_sort == false)
+ {
+ Insert(hub->AccessList, access);
+ }
+ else
+ {
+ Add(hub->AccessList, access);
+ }
+
+ // Reassign the ID
+ if (no_reassign_id == false)
+ {
+ for (i = 0;i < LIST_NUM(hub->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(hub->AccessList, i);
+ a->Id = (i + 1);
+ }
+ }
+ }
+ UnlockList(hub->AccessList);
+}
+
+// Initialize the access list
+void InitAccessList(HUB *hub)
+{
+ // Validate arguments
+ if (hub == NULL)
+ {
+ return;
+ }
+
+ hub->AccessList = NewList(CmpAccessList);
+}
+
+// Release the access list
+void FreeAccessList(HUB *hub)
+{
+ UINT i;
+ // Validate arguments
+ if (hub == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(hub->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(hub->AccessList, i);
+ Free(a);
+ }
+
+ ReleaseList(hub->AccessList);
+ hub->AccessList = NULL;
+}
+
+// Comparison of the access list entry
+int CmpAccessList(void *p1, void *p2)
+{
+ ACCESS *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(ACCESS **)p1;
+ a2 = *(ACCESS **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+ // Sort by priority
+ if (a1->Priority > a2->Priority)
+ {
+ return 1;
+ }
+ else if (a1->Priority < a2->Priority)
+ {
+ return -1;
+ }
+ else if (a1->Discard > a2->Discard)
+ {
+ return 1;
+ }
+ else if (a1->Discard < a2->Discard)
+ {
+ return -1;
+ }
+ else
+ {
+ UINT64 size64 = ((UINT64)(&a1->UniqueId) - (UINT64)(&a1->Active));
+ UINT size32 = (UINT)size64;
+
+ return Cmp(&a1->Active, &a2->Active, size32);
+ }
+}
+
+// Generate a user name without domain name of the Windows NT
+void MakeSimpleUsernameRemoveNtDomain(char *dst, UINT dst_size, char *src)
+{
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ ParseNtUsername(src, tmp1, sizeof(tmp1), tmp2, sizeof(tmp2), false);
+
+ StrCpy(dst, dst_size, tmp1);
+}
+
+// Convert the user name to UINT
+UINT64 UsernameToInt64(char *name)
+{
+ UCHAR hash[SHA1_SIZE];
+ UINT64 ret;
+ char tmp[MAX_USERNAME_LEN + 1];
+ // Validate arguments
+ if (name == 0 || IsEmptyStr(name))
+ {
+ return 0;
+ }
+
+ if (StartWith(name, ACCESS_LIST_INCLUDED_PREFIX) || StartWith(name, ACCESS_LIST_EXCLUDED_PREFIX))
+ {
+ return Rand64();
+ }
+
+ MakeSimpleUsernameRemoveNtDomain(tmp, sizeof(tmp), name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ if (StrLen(tmp) == 0)
+ {
+ return 0;
+ }
+
+ Hash(hash, tmp, StrLen(tmp), true);
+ Copy(&ret, hash, sizeof(ret));
+
+ return ret;
+}
+
+// Search the session from the session pointer
+SESSION *GetSessionByPtr(HUB *hub, void *ptr)
+{
+ // Validate arguments
+ if (hub == NULL || ptr == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(hub->SessionList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(hub->SessionList);i++)
+ {
+ SESSION *s = LIST_DATA(hub->SessionList, i);
+ if (s == (SESSION *)ptr)
+ {
+ // Found
+ AddRef(s->ref);
+ UnlockList(hub->SessionList);
+ return s;
+ }
+ }
+ }
+ UnlockList(hub->SessionList);
+
+ return NULL;
+}
+
+// Search the session from the session name
+SESSION *GetSessionByName(HUB *hub, char *name)
+{
+ // Validate arguments
+ if (hub == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(hub->SessionList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(hub->SessionList);i++)
+ {
+ SESSION *s = LIST_DATA(hub->SessionList, i);
+ if (StrCmpi(s->Name, name) == 0)
+ {
+ // Found
+ AddRef(s->ref);
+ UnlockList(hub->SessionList);
+ return s;
+ }
+ }
+ }
+ UnlockList(hub->SessionList);
+
+ return NULL;
+}
+
+// Sort of the STORM list
+int CompareStormList(void *p1, void *p2)
+{
+ STORM *s1, *s2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(STORM **)p1;
+ s2 = *(STORM **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+ if (s1->StrictMode == false && s2->StrictMode == false)
+ {
+ // Normal mode
+ r = CmpIpAddr(&s1->DestIp, &s2->DestIp);
+ if (r != 0)
+ {
+ return r;
+ }
+ r = CmpIpAddr(&s1->SrcIp, &s2->SrcIp);
+ if (r != 0)
+ {
+ return r;
+ }
+ }
+ else
+ {
+ // Strict mode
+ int r1, r2;
+ r1 = CmpIpAddr(&s1->DestIp, &s2->DestIp);
+ r2 = CmpIpAddr(&s1->SrcIp, &s2->SrcIp);
+ if (r1 == 0 || r2 == 0)
+ {
+ // Either the source IP, and destination IP match
+ }
+ else
+ {
+ // Mismatch
+ if (r1 != 0)
+ {
+ return r1;
+ }
+
+ if (r2 != 0)
+ {
+ return r2;
+ }
+ }
+ }
+ r = Cmp(s1->MacAddress, s2->MacAddress, 6);
+ return r;
+}
+
+// Packet adapter initialization
+bool HubPaInit(SESSION *s)
+{
+ // Initialize the packet adapter information
+ HUB_PA *pa = ZeroMalloc(sizeof(HUB_PA));
+ pa->Cancel = NewCancel();
+ pa->PacketQueue = NewQueue();
+ pa->Now = Tick64();
+ pa->Session = s;
+ pa->StormList = NewList(CompareStormList);
+ pa->UsernameHash = UsernameToInt64(s->Username);
+ pa->GroupnameHash = UsernameToInt64(s->GroupName);
+
+ s->PacketAdapter->Param = pa;
+
+ if (s->Policy->MonitorPort)
+ {
+ // Mark this port as monitoring port
+ pa->MonitorPort = true;
+
+ // Add this session to the list of monitoring port of the HUB
+ LockList(s->Hub->MonitorList);
+ {
+ Insert(s->Hub->MonitorList, s);
+ }
+ UnlockList(s->Hub->MonitorList);
+ }
+
+ return true;
+}
+
+// Release the Packet adapter
+void HubPaFree(SESSION *s)
+{
+ HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
+ HUB *hub = s->Hub;
+
+ if (pa->MonitorPort)
+ {
+ // Remove the session from the list of monitor port of the HUB
+ LockList(s->Hub->MonitorList);
+ {
+ Delete(s->Hub->MonitorList, s);
+ }
+ UnlockList(s->Hub->MonitorList);
+ }
+
+ // Erase MAC address table entries that is associated with this session
+ LockList(hub->MacTable);
+ {
+ UINT i, num = LIST_NUM(hub->MacTable);
+ LIST *o = NewListFast(NULL);
+ for (i = 0;i < num;i++)
+ {
+ MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(hub->MacTable, i);
+ if (e->Session == s)
+ {
+ Add(o, e);
+ }
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(o, i);
+ Delete(hub->MacTable, e);
+ Free(e);
+ }
+ ReleaseList(o);
+ }
+ {
+ UINT i, num = LIST_NUM(hub->IpTable);
+ LIST *o = NewListFast(NULL);
+ for (i = 0;i < num;i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
+ if (e->Session == s)
+ {
+ Add(o, e);
+ }
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(o, i);
+ Delete(hub->IpTable, e);
+ Free(e);
+ }
+ ReleaseList(o);
+ }
+ UnlockList(hub->MacTable);
+
+ // Release the STORM list
+ LockList(pa->StormList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(pa->StormList);i++)
+ {
+ STORM *s = (STORM *)LIST_DATA(pa->StormList, i);
+ Free(s);
+ }
+ DeleteAll(pa->StormList);
+ }
+ UnlockList(pa->StormList);
+
+ ReleaseList(pa->StormList);
+
+ // Release the packets remaining in the queue
+ LockQueue(pa->PacketQueue);
+ {
+ BLOCK *b;
+
+ while (b = GetNext(pa->PacketQueue))
+ {
+ // Release the block
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(pa->PacketQueue);
+
+ // Release the queue
+ ReleaseQueue(pa->PacketQueue);
+
+ // Release the cancel object
+ ReleaseCancel(pa->Cancel);
+
+ // Release the packet adapter information
+ Free(pa);
+ s->PacketAdapter->Param = NULL;
+}
+
+// Get the cancel object
+CANCEL *HubPaGetCancel(SESSION *s)
+{
+ HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
+
+ AddRef(pa->Cancel->ref);
+ return pa->Cancel;
+}
+
+// Get the packet to be transmitted next
+UINT HubPaGetNextPacket(SESSION *s, void **data)
+{
+ UINT ret = 0;
+ HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
+
+ // Get one from the head of the queue
+ LockQueue(pa->PacketQueue);
+ {
+ BLOCK *block = GetNext(pa->PacketQueue);
+ if (block == NULL)
+ {
+ // No queue
+ ret = 0;
+ }
+ else
+ {
+ // Found
+ *data = block->Buf;
+ ret = block->Size;
+ // Release the memory of the structure of the block
+ Free(block);
+ }
+ }
+ UnlockQueue(pa->PacketQueue);
+
+ return ret;
+}
+
+// Receive a packet
+bool HubPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ PKT *packet;
+ HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
+ bool b = false;
+ HUB *hub;
+ bool no_l3 = false;
+ bool no_http = false;
+ LIST *o = NULL;
+ UINT i;
+ UINT vlan_type_id = 0;
+ bool no_look_bpdu_bridge_id = false;
+ bool no_parse_dhcp = false;
+ bool no_correct_checksum = false;
+
+ hub = s->Hub;
+
+ pa->Now = Tick64();
+
+ // Processing of Adjust TCP MSS
+ if (hub->Option != NULL && hub->Option->DisableAdjustTcpMss == false && s != NULL)
+ {
+ UINT target_mss = (hub->Option->AdjustTcpMssValue == 0 ? INFINITE : hub->Option->AdjustTcpMssValue);
+ UINT session_mss = (s->AdjustMss == 0 ? INFINITE : s->AdjustMss);
+
+ target_mss = MIN(target_mss, session_mss);
+
+ if (s->IsUsingUdpAcceleration && s->UdpAccelMss != 0)
+ {
+ // If the link is established with UDP acceleration function, use optimum value of the UDP acceleration function
+ target_mss = MIN(target_mss, s->UdpAccelMss);
+ }
+ else if (s->IsRUDPSession && s->RUdpMss != 0)
+ {
+ // If the link with UDP acceleration is not established, use the optimum value for R-UDP in the case of using R-UDP connection
+ target_mss = MIN(target_mss, s->RUdpMss);
+ }
+
+ if (target_mss != INFINITE)
+ {
+ AdjustTcpMssL2(data, size, target_mss, hub->Option->VlanTypeId);
+ }
+ }
+
+ if (data == NULL)
+ {
+ // Check the delayed packet
+ o = NULL;
+ LockList(s->DelayedPacketList);
+ {
+ UINT i;
+ if (LIST_NUM(s->DelayedPacketList) >= 1)
+ {
+ UINT64 now = TickHighres64();
+ for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
+ {
+ PKT *p = LIST_DATA(s->DelayedPacketList, i);
+
+ if (now >= p->DelayedForwardTick)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, p);
+ }
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PKT *p = LIST_DATA(o, i);
+
+ Delete(s->DelayedPacketList, p);
+ }
+ }
+ }
+ UnlockList(s->DelayedPacketList);
+
+ // If there is a delayed packet, store it
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PKT *p = LIST_DATA(o, i);
+
+ StorePacket(s->Hub, s, p);
+ }
+
+ ReleaseList(o);
+ }
+
+ // Reception of all packets from this session is complete
+ CancelList(s->CancelList);
+
+ // Yield
+ if (hub->Option != NULL && hub->Option->YieldAfterStorePacket)
+ {
+ YieldCpu();
+ }
+
+ return true;
+ }
+
+ if (hub != NULL && hub->Option != NULL)
+ {
+ no_l3 = hub->Option->DisableIPParsing;
+ no_http = hub->Option->DisableHttpParsing;
+ vlan_type_id = hub->Option->VlanTypeId;
+ no_look_bpdu_bridge_id = hub->Option->NoLookBPDUBridgeId;
+ no_correct_checksum = hub->Option->DisableCorrectIpOffloadChecksum;
+ }
+
+ // Insert a VLAN tag
+ if (s->VLanId != 0)
+ {
+ VLanInsertTag(&data, &size, s->VLanId, vlan_type_id);
+ }
+
+LABEL_TRY_AGAIN:
+ // Parse the packet
+ packet = ParsePacketEx4(data, size, no_l3, vlan_type_id, !no_look_bpdu_bridge_id, no_http, !no_correct_checksum);
+
+ if (packet != NULL)
+ {
+ if (packet->InvalidSourcePacket)
+ {
+ // Packet which have illegal source
+ FreePacket(packet);
+ packet = NULL;
+ }
+ }
+
+
+ if (packet != NULL)
+ {
+ if (packet->TypeL7 == L7_DHCPV4)
+ {
+ if (packet->TypeL3 == L3_IPV4 && packet->TypeL4 == L4_UDP)
+ {
+ if (packet->L7.DHCPv4Header != NULL)
+ {
+ DHCPV4_HEADER *dhcp = packet->L7.DHCPv4Header;
+
+ if (dhcp->OpCode == 1)
+ {
+ if (NsIsMacAddressOnLocalhost(dhcp->ClientMacAddress))
+ {
+ // Filter DHCP requests sent from local kernel-mode virtual NAT
+ // not to re-enter it to the virtual HUB along the local bridge
+ FreePacket(packet);
+ packet = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (no_parse_dhcp == false && packet != NULL)
+ {
+ if (hub->Option != NULL && hub->Option->RemoveDefGwOnDhcpForLocalhost)
+ {
+ // Remove the designation of the DHCP server from the DHCP response packet addressed to localhost
+ if (packet->TypeL7 == L7_DHCPV4)
+ {
+ if (packet->TypeL3 == L3_IPV4)
+ {
+ if (packet->TypeL4 == L4_UDP)
+ {
+ if (packet->L7.DHCPv4Header != NULL)
+ {
+ DHCPV4_HEADER *dhcp = packet->L7.DHCPv4Header;
+
+ if (dhcp->OpCode == 2)
+ {
+ if (IsMacAddressLocalFast(dhcp->ClientMacAddress))
+ {
+ BUF *new_buf;
+ DHCP_MODIFY_OPTION m;
+ WHERE;
+
+ Zero(&m, sizeof(m));
+ m.RemoveDefaultGatewayOnReply = true;
+
+ new_buf = DhcpModifyIPv4(&m, data, size);
+
+ if (new_buf != NULL)
+ {
+ Free(data);
+
+ data = new_buf->Buf;
+ size = new_buf->Size;
+
+ Free(new_buf);
+
+ no_parse_dhcp = true;
+
+ FreePacket(packet);
+
+ goto LABEL_TRY_AGAIN;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (packet != NULL)
+ {
+ // Store packet
+ StorePacket(s->Hub, s, packet);
+ }
+ else
+ {
+ // Release the packet data because it is a bad packet (not a correct MAC frame)
+ Free(data);
+ }
+
+ return true;
+}
+
+// VGS: Setting for embedding UA tag
+void VgsSetEmbTag(bool b)
+{
+ g_vgs_emb_tag = b;
+}
+
+// VGS: Setting for the User-Agent value
+void VgsSetUserAgentValue(char *str)
+{
+ // Validate arguments
+ if (str == NULL || StrLen(str) != 8)
+ {
+ Zero(vgs_ua_str, sizeof(vgs_ua_str));
+ }
+ else
+ {
+ StrCpy(vgs_ua_str, sizeof(vgs_ua_str), str);
+ }
+}
+
+// Checking algorithm to prevent broadcast-storm
+// If broadcast from a specific endpoint came frequently, filter it
+bool CheckBroadcastStorm(HUB *hub, SESSION *s, PKT *p)
+{
+ IP src_ip, dest_ip;
+ HUB_PA *pa;
+ UINT64 now = Tick64();
+ UINT limit_start_count;
+ SESSION *sess = s;
+ bool ret = true;
+ bool strict = false;
+ bool no_heavy = false;
+ // Validate arguments
+ if (s == NULL || p == NULL || hub == NULL)
+ {
+ return false;
+ }
+
+ if (s->Policy->NoBroadcastLimiter)
+ {
+ // Unlimited the number of broadcasts
+ return true;
+ }
+
+ if (hub != NULL && hub->Option != NULL)
+ {
+ strict = hub->Option->BroadcastLimiterStrictMode;
+ no_heavy = hub->Option->DoNotSaveHeavySecurityLogs;
+ }
+
+ pa = (HUB_PA *)s->PacketAdapter->Param;
+
+ Zero(&src_ip, sizeof(IP));
+ Zero(&dest_ip, sizeof(IP));
+
+ if (p->TypeL3 == L3_IPV4)
+ {
+ UINTToIP(&src_ip, p->L3.IPv4Header->SrcIP);
+ UINTToIP(&dest_ip, p->L3.IPv4Header->DstIP);
+ }
+ else if (p->TypeL3 == L3_ARPV4)
+ {
+ UINTToIP(&src_ip, p->L3.ARPv4Header->SrcIP);
+ Zero(&dest_ip, sizeof(IP));
+ }
+ else if (p->TypeL3 == L3_IPV6)
+ {
+ IPv6AddrToIP(&src_ip, &p->L3.IPv6Header->SrcAddress);
+ IPv6AddrToIP(&dest_ip, &p->L3.IPv6Header->DestAddress);
+ }
+
+ // Number of broadcast to start limitation for a single interval
+ limit_start_count = 32;
+
+ if (s->Hub != NULL && s->Hub->Option->BroadcastStormDetectionThreshold != 0)
+ {
+ limit_start_count = s->Hub->Option->BroadcastStormDetectionThreshold;
+ }
+
+ LockList(pa->StormList);
+ {
+ STORM *s;
+ UINT num;
+ s = SearchStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip, strict);
+ if (s == NULL)
+ {
+ s = AddStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip, strict);
+ }
+
+ s->CurrentBroadcastNum++;
+
+ if ((s->CheckStartTick + STORM_CHECK_SPAN) < now ||
+ s->CheckStartTick == 0 || s->CheckStartTick > now)
+ {
+ // Measure the number of broadcast periodically
+ UINT64 diff_time;
+ if (s->CheckStartTick < now)
+ {
+ diff_time = now - s->CheckStartTick;
+ }
+ else
+ {
+ diff_time = 0;
+ }
+ s->CheckStartTick = now;
+ num = (UINT)((UINT64)s->CurrentBroadcastNum * (UINT64)1000 / (UINT64)STORM_CHECK_SPAN);
+ s->CurrentBroadcastNum = 0;
+ if (num >= limit_start_count)
+ {
+ char ip1[64];
+ char ip2[64];
+ char mac[MAX_SIZE];
+ IPToStr(ip1, sizeof(ip1), &src_ip);
+ IPToStr(ip2, sizeof(ip2), &dest_ip);
+ ret = false;
+ if (s->DiscardValue < STORM_DISCARD_VALUE_END)
+ {
+ s->DiscardValue = MAX(s->DiscardValue, 1) * 2;
+ }
+ Debug("s->DiscardValue: %u (%u)\n", s->DiscardValue, num);
+
+ MacToStr(mac, sizeof(mac), p->MacAddressSrc);
+
+ if (no_heavy == false)
+ {
+ HLog(sess->Hub, "LH_BCAST_STORM", sess->Name, mac, ip1, ip2, num);
+ }
+ }
+ else
+ {
+ if (s->DiscardValue >= 1)
+ {
+ s->DiscardValue = (UINT)((UINT64)s->DiscardValue / MAX((UINT64)2, (UINT64)diff_time / (UINT64)STORM_CHECK_SPAN));
+ }
+ }
+ }
+
+ if (s->DiscardValue >= STORM_DISCARD_VALUE_START)
+ {
+ if (s->DiscardValue >= 128)
+ {
+ ret = false;
+ }
+ else if ((rand() % s->DiscardValue) != 0)
+ {
+ ret = false;
+ }
+ }
+
+ }
+ UnlockList(pa->StormList);
+
+ return ret;
+}
+
+// Store packet
+void StorePacket(HUB *hub, SESSION *s, PKT *packet)
+{
+ MAC_TABLE_ENTRY *entry = NULL;
+ MAC_TABLE_ENTRY t;
+ void *data;
+ UINT size;
+ bool broadcast_mode;
+ HUB_PA *dest_pa;
+ SESSION *dest_session;
+ TRAFFIC traffic;
+ UINT64 now = Tick64();
+ bool no_heavy = false;
+ // Validate arguments
+ if (hub == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ if (s != NULL)
+ {
+ if (((HUB_PA *)s->PacketAdapter->Param)->MonitorPort)
+ {
+ // Not to forward packets received from the monitor port
+ Free(packet->PacketData);
+ FreePacket(packet);
+ return;
+ }
+ }
+
+ if (hub->Option != NULL)
+ {
+ no_heavy = hub->Option->DoNotSaveHeavySecurityLogs;
+ }
+
+ // Lock the entire MAC address table
+ LockList(hub->MacTable);
+ {
+ // Filtering
+ if (s != NULL && (packet->DelayedForwardTick == 0 && StorePacketFilter(s, packet) == false))
+ {
+DISCARD_PACKET:
+ // Release a packet since passing has been disallowed
+ Free(packet->PacketData);
+ FreePacket(packet);
+ }
+ else // Passing is allowed
+ {
+ bool forward_now = true;
+
+ if (packet->Loss >= 1)
+ {
+ // Cause packet loss
+ UINT r = rand() % 100;
+ if ((packet->Loss >= 100) || (r < packet->Loss))
+ {
+ // Packet loss
+ goto DISCARD_PACKET;
+ }
+ }
+
+ if (packet->Delay >= 1)
+ {
+ float delay = (float)packet->Delay;
+ float jitter;
+ UINT delay_uint;
+ bool f = Rand1();
+ if (packet->Jitter == 0)
+ {
+ jitter = 0;
+ }
+ else
+ {
+ jitter = (float)(Rand32() % (int)((float)packet->Jitter * delay / 100.0f));
+ }
+
+ delay += jitter * (f ? 1 : -1);
+ delay_uint = (UINT)delay;
+
+ if (delay_uint >= 1)
+ {
+ // Cause delay
+ forward_now = false;
+ packet->Loss = packet->Jitter = packet->Delay = 0;
+ packet->DelayedForwardTick = TickHighres64() + (UINT64)delay_uint;
+ packet->DelayedSrcSession = s;
+
+ LockList(s->DelayedPacketList);
+ {
+ Add(s->DelayedPacketList, packet);
+ }
+ UnlockList(s->DelayedPacketList);
+ }
+ }
+
+ if (forward_now)
+ {
+ if (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) == 0)
+ {
+ if (s != NULL)
+ {
+ // Packets that this HUB itself sent is input from the outside
+ goto DISCARD_PACKET;
+ }
+ }
+ if (s != NULL && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0))
+ {
+ // Check whether the source MAC address is registered in the table
+ Copy(t.MacAddress, packet->MacAddressSrc, 6);
+ if (hub->Option->NoManageVlanId == false)
+ {
+ t.VlanId = packet->VlanId;
+ }
+ else
+ {
+ t.VlanId = 0;
+ }
+ entry = Search(hub->MacTable, &t);
+
+ if (entry == NULL)
+ {
+ // Remove old entries
+ DeleteExpiredMacTableEntry(hub->MacTable);
+
+ // Register since it is not registered
+ if ((s->Policy->MaxMac != 0 || s->Policy->NoBridge) && (s->IsOpenVPNL3Session == false))
+ {
+ UINT i, num_mac_for_me = 0;
+ UINT limited_count;
+
+ // Examine a number of MAC addresses that are registered in this current session
+ for (i = 0;i < LIST_NUM(hub->MacTable);i++)
+ {
+ MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
+ if (e->Session == s)
+ {
+ num_mac_for_me++;
+ }
+ }
+
+ limited_count = 0xffffffff;
+ if (s->Policy->NoBridge)
+ {
+ limited_count = MIN(limited_count, MAC_MIN_LIMIT_COUNT);
+ }
+ if (s->Policy->MaxMac != 0)
+ {
+ limited_count = MIN(limited_count, s->Policy->MaxMac);
+ }
+ limited_count = MAX(limited_count, MAC_MIN_LIMIT_COUNT);
+
+ if (num_mac_for_me >= limited_count)
+ {
+ // Number of MAC addresses that are registered already exceeds the upper limit
+ char mac_str[64];
+
+ if (s != NULL)
+ {
+ MacToStr(mac_str, sizeof(mac_str), packet->MacAddressSrc);
+ if (s->Policy->NoBridge)
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_BRIDGE_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);
+ }
+ }
+ else
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_MAC_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);
+ }
+ }
+ }
+
+ goto DISCARD_PACKET; // Drop the packet
+ }
+ }
+
+ if (LIST_NUM(hub->MacTable) >= MAX_MAC_TABLES)
+ {
+ // Delete the oldest entry because the MAC table database is
+ // exceeded the maximum number of entries
+ UINT i;
+ UINT64 old_time = 0xffffffffffffffffULL;
+ MAC_TABLE_ENTRY *old_entry = NULL;
+ for (i = 0;i < LIST_NUM(hub->MacTable);i++)
+ {
+ MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
+ if (e->UpdatedTime <= old_time)
+ {
+ old_time = e->UpdatedTime;
+ old_entry = e;
+ }
+ }
+ if (old_entry != NULL)
+ {
+ Delete(hub->MacTable, old_entry);
+ Free(old_entry);
+ }
+ }
+
+ entry = ZeroMalloc(sizeof(MAC_TABLE_ENTRY));
+ entry->HubPa = (HUB_PA *)s->PacketAdapter->Param;
+ Copy(entry->MacAddress, packet->MacAddressSrc, 6);
+ if (hub->Option->NoManageVlanId == false)
+ {
+ entry->VlanId = packet->VlanId;
+ }
+ else
+ {
+ entry->VlanId = 0;
+ }
+ entry->Session = s;
+ entry->UpdatedTime = entry->CreatedTime = now;
+
+ Insert(hub->MacTable, entry);
+
+ if (hub->Option->NoMacAddressLog == false)
+ {
+ // Debug display
+ char mac_address[32];
+
+ if (s != NULL)
+ {
+ MacToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc);
+// Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
+
+ if (packet->VlanId == 0)
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
+ }
+ }
+ else
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (entry->Session == s)
+ {
+ // Do not do anything because it is already registered
+ entry->UpdatedTime = now;
+ }
+ else
+ {
+ // Read the value of the policy CheckMac
+ bool check_mac = s->Policy->CheckMac;
+
+ if (check_mac == false)
+ {
+ if (s->BridgeMode)
+ {
+ // Enable the CheckMac policy for the local bridge session forcibly
+ check_mac = true;
+
+ if (hub->Option != NULL && hub->Option->DisableCheckMacOnLocalBridge)
+ {
+ // Disable if DisableCheckMacOnLocalBridge option is set
+ check_mac = false;
+ }
+ }
+ }
+
+ // It's already registered and it's in another session
+ if (check_mac && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0) &&
+ ((entry->UpdatedTime + MAC_TABLE_EXCLUSIVE_TIME) >= now))
+ {
+ UCHAR *mac = packet->MacAddressSrc;
+ if (hub->Option != NULL && hub->Option->FixForDLinkBPDU &&
+ (mac[0] == 0x00 && mac[1] == 0x80 && mac[2] == 0xc8 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00) ||
+ (mac[0] == 0x00 && mac[1] == 0x0d && mac[2] == 0x88 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00))
+ {
+ // Measures for D-Link. Spanning tree packet of D-Link is sent from the above address.
+ //CheckMac options for the local bridge may cause an adverse effect. So process this exceptionally.
+ UCHAR hash[MD5_SIZE];
+ UINT64 tick_diff = Tick64() - s->LastDLinkSTPPacketSendTick;
+
+ Hash(hash, packet->PacketData, packet->PacketSize, false);
+
+ if ((s->LastDLinkSTPPacketSendTick != 0) &&
+ (tick_diff < 750ULL) &&
+ (Cmp(hash, s->LastDLinkSTPPacketDataHash, MD5_SIZE) == 0))
+ {
+ // Discard if the same packet sent before 750ms ago
+ Debug("D-Link Discard %u\n", (UINT)tick_diff);
+ goto DISCARD_PACKET; // Drop the packet
+ }
+ else
+ {
+ goto UPDATE_FDB;
+ }
+ }
+ else
+ {
+ if (0)
+ {
+ // If the CheckMac policy-enabled, owning same
+ // MAC address by other sessions are prohibited
+ // (If the second byte is 0xAE, don't perform this check)
+ char mac_address[32];
+ BinToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc, 6);
+ }
+ }
+
+ goto DISCARD_PACKET; // Drop the packet
+ }
+ else
+ {
+ // Rewrite the session of MAC address table and the HUB_PA
+ char mac_address[32];
+UPDATE_FDB:
+ BinToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc, 6);
+
+ entry->Session = s;
+ entry->HubPa = (HUB_PA *)s->PacketAdapter->Param;
+ entry->UpdatedTime = entry->CreatedTime = now;
+
+ if (1)
+ {
+ // Debug display
+ char mac_address[32];
+
+ if (s != NULL)
+ {
+ MacToStr(mac_address, sizeof(mac_address), packet->MacHeader->SrcAddress);
+ Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
+ if (packet->VlanId == 0)
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
+ }
+ }
+ else
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ broadcast_mode = false;
+ dest_pa = NULL;
+ dest_session = NULL;
+
+ if (packet->BroadcastPacket)
+ {
+ // Broadcast packet
+ broadcast_mode = true;
+ }
+ else
+ {
+ // Examine whether the destination MAC address is registered in the table
+ Copy(t.MacAddress, packet->MacAddressDest, 6);
+ if (hub->Option->NoManageVlanId == false)
+ {
+ t.VlanId = packet->VlanId;
+ }
+ else
+ {
+ t.VlanId = 0;
+ }
+ entry = Search(hub->MacTable, &t);
+
+ if (entry == NULL)
+ {
+ // Broadcast because the destination isn't found
+ broadcast_mode = true;
+ }
+ else
+ {
+ if (entry->Session != s)
+ {
+ // Destination is found
+ dest_pa = entry->HubPa;
+ dest_session = entry->Session;
+ }
+ else
+ {
+ // Bad packet whose destination is its own
+ goto DISCARD_PACKET;
+ }
+ }
+ }
+
+ if (s != NULL && hub->Option->NoIpTable == false)
+ {
+ if (packet->TypeL3 == L3_IPV6)
+ {
+ // IPv6 packet
+ IP ip;
+ bool b = true;
+ UINT ip_type;
+ bool dhcp_or_ra = false;
+
+ IPv6AddrToIP(&ip, &packet->L3.IPv6Header->SrcAddress);
+ ip_type = GetIPv6AddrType(&packet->L3.IPv6Header->SrcAddress);
+
+ if (!(ip_type & IPV6_ADDR_UNICAST))
+ {
+ // Multicast address
+ b = false;
+ }
+ else if ((ip_type & IPV6_ADDR_LOOPBACK) || (ip_type & IPV6_ADDR_ZERO))
+ {
+ // Loop-back address or all-zero address
+ b = false;
+ }
+
+ if (packet->TypeL4 == L4_ICMPV6)
+ {
+ if (packet->ICMPv6HeaderPacketInfo.Type == 133 ||
+ packet->ICMPv6HeaderPacketInfo.Type == 134)
+ {
+ // ICMPv6 RS/RA
+ dhcp_or_ra = true;
+ }
+ }
+ else if (packet->TypeL4 == L4_UDP)
+ {
+ if (Endian16(packet->L4.UDPHeader->DstPort) == 546 ||
+ Endian16(packet->L4.UDPHeader->DstPort) == 547)
+ {
+ // DHCPv6
+ dhcp_or_ra = true;
+ }
+ }
+
+ if (IsHubMacAddress(packet->MacAddressSrc) &&
+ IsHubIpAddress64(&packet->L3.IPv6Header->SrcAddress))
+ {
+ // The source address of the Virtual HUB for polling
+ b = false;
+ }
+
+ if (b)
+ {
+ // Other than ICMPv6 RS/RA nor DHCPv6 packet
+ IP_TABLE_ENTRY t, *e;
+
+ Copy(&t.Ip, &ip, sizeof(IP));
+
+ // Check whether it is registered to an existing table
+ e = Search(hub->IpTable, &t);
+
+ if (e == NULL)
+ {
+ // Register since it is not registered
+ if (s->Policy->NoRoutingV6 || s->Policy->MaxIPv6 != 0)
+ {
+ UINT i, num_ip_for_me = 0;
+ UINT limited_count = 0xffffffff;
+
+ for (i = 0;i < LIST_NUM(hub->IpTable);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
+
+ if (e->Session == s)
+ {
+ if (IsIP6(&e->Ip))
+ {
+ num_ip_for_me++;
+ }
+ }
+ }
+
+ if (s->Policy->NoRoutingV6)
+ {
+ limited_count = MIN(limited_count, IP_LIMIT_WHEN_NO_ROUTING_V6);
+ }
+ if (s->Policy->MaxIPv6 != 0)
+ {
+ limited_count = MIN(limited_count, s->Policy->MaxIPv6);
+ }
+ limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT_V6);
+
+ if (dhcp_or_ra)
+ {
+ limited_count = 0xffffffff;
+ }
+
+ if (num_ip_for_me >= limited_count)
+ {
+ // Discard the packet because it exceeded the
+ // upper limit of the IP address that can be used
+ char tmp[64];
+ IPToStr(tmp, sizeof(tmp), &ip);
+ if (s->Policy->NoRoutingV6 == false)
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
+ }
+ }
+ else
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
+ }
+ }
+ goto DISCARD_PACKET;
+ }
+ }
+
+ if (IsIPManagementTargetForHUB(&ip, hub))
+ {
+ // Create a entry
+ e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));
+ e->CreatedTime = e->UpdatedTime = now;
+ e->DhcpAllocated = false;
+ Copy(&e->Ip, &ip, sizeof(IP));
+ Copy(e->MacAddress, packet->MacAddressSrc, 6);
+ e->Session = s;
+
+ DeleteExpiredIpTableEntry(hub->IpTable);
+
+ if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
+ {
+ // Delete old IP table entries
+ DeleteOldIpTableEntry(hub->IpTable);
+ }
+
+ Insert(hub->IpTable, e);
+
+ if (0)
+ {
+ char ip_address[64];
+ IPToStr(ip_address, sizeof(ip_address), &ip);
+ Debug("Registered IP Address %s to Session %X.\n",
+ ip_address, s);
+ }
+ }
+ }
+ else
+ {
+ if (e->Session == s)
+ {
+ // Do not do anything because it is self session
+ // Renew updated time
+ e->UpdatedTime = now;
+ Copy(e->MacAddress, packet->MacAddressSrc, 6);
+ }
+ else
+ {
+ // Another session was using this IP address before
+ if ((s->Policy->CheckIPv6) &&
+ ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))
+ {
+ // Discard the packet because another session uses this IP address
+ char ip_address[32];
+ char mac_str[48];
+ IPToStr(ip_address, sizeof(ip_address), &ip);
+
+ Debug("IP Address %s is Already used by Session %X.\n",
+ ip_address, s);
+
+ MacToStr(mac_str, sizeof(mac_str), e->MacAddress);
+
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name, mac_str,
+ e->CreatedTime, e->UpdatedTime, e->DhcpAllocated, now);
+ }
+
+ goto DISCARD_PACKET;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (
+ (s != NULL) &&
+ (hub->Option->NoIpTable == false) &&
+ (
+ (packet->TypeL3 == L3_IPV4 ||
+ (packet->TypeL3 == L3_ARPV4 && packet->L3.ARPv4Header->HardwareSize == 6 &&
+ Endian16(packet->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
+ packet->L3.ARPv4Header->ProtocolSize == 4 &&
+ Endian16(packet->L3.ARPv4Header->ProtocolType) == 0x0800)
+ ) &&
+ (packet->TypeL7 != L7_DHCPV4)
+ )
+ ) // Other than DHCP packets
+ {
+ // In the case of the ARP response packet or the IP packet, search in the IP address table
+ IP_TABLE_ENTRY t, *e;
+ IP ip;
+ UINT uint_ip = 0;
+
+ if (packet->TypeL3 == L3_IPV4)
+ {
+ uint_ip = packet->L3.IPv4Header->SrcIP;
+ }
+ else if (packet->TypeL3 == L3_ARPV4)
+ {
+ uint_ip = packet->L3.ARPv4Header->SrcIP;
+ }
+
+ if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(packet->MacAddressSrc)))
+ {
+ UINTToIP(&ip, uint_ip);
+ Copy(&t.Ip, &ip, sizeof(IP));
+
+ // Check whether it is registered to an existing table
+ e = Search(hub->IpTable, &t);
+
+ if (e == NULL)
+ {
+ // Register since it is not registered
+ if (s->Policy->DHCPForce)
+ {
+ char ipstr[MAX_SIZE];
+
+ // Discard the packet because this IP address isn't
+ // assigned by the DHCP server
+ IPToStr32(ipstr, sizeof(ipstr), uint_ip);
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);
+ }
+ goto DISCARD_PACKET;
+ }
+
+ // if (packet->TypeL3 == L3_ARPV4)
+ {
+ // Examine the number that are registered in this session already
+ if (s->Policy->NoRouting || s->Policy->MaxIP != 0)
+ {
+ UINT i, num_ip_for_me = 0;
+ UINT limited_count = 0xffffffff;
+
+ for (i = 0;i < LIST_NUM(hub->IpTable);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
+
+ if (e->Session == s)
+ {
+ if (IsIP4(&e->Ip))
+ {
+ num_ip_for_me++;
+ }
+ }
+ }
+
+ if (s->Policy->NoRouting)
+ {
+ limited_count = MIN(limited_count, IP_MIN_LIMIT_COUNT);
+ }
+ if (s->Policy->MaxIP != 0)
+ {
+ limited_count = MIN(limited_count, s->Policy->MaxIP);
+ }
+ limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT);
+
+ if (num_ip_for_me >= limited_count)
+ {
+ // Discard the packet because it exceeded the
+ // upper limit of the IP address that can be used
+ char tmp[64];
+ IPToStr32(tmp, sizeof(tmp), uint_ip);
+ if (s->Policy->NoRouting == false)
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
+ }
+ }
+ else
+ {
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
+ }
+ }
+ goto DISCARD_PACKET;
+ }
+ }
+
+ if (IsIPManagementTargetForHUB(&ip, hub))
+ {
+ // Create a entry
+ e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));
+ e->CreatedTime = e->UpdatedTime = now;
+ e->DhcpAllocated = false;
+ Copy(&e->Ip, &ip, sizeof(IP));
+ Copy(e->MacAddress, packet->MacAddressSrc, 6);
+ e->Session = s;
+
+ DeleteExpiredIpTableEntry(hub->IpTable);
+
+ if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
+ {
+ // Delete old IP table entries
+ DeleteOldIpTableEntry(hub->IpTable);
+ }
+
+ Insert(hub->IpTable, e);
+
+ if (0)
+ {
+ char ip_address[64];
+ IPToStr(ip_address, sizeof(ip_address), &ip);
+ Debug("Registered IP Address %s to Session %X.\n",
+ ip_address, s);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (e->Session == s)
+ {
+ // Do not do anything because it is self session
+ // Renew update time
+ e->UpdatedTime = now;
+ Copy(e->MacAddress, packet->MacAddressSrc, 6);
+ }
+ else
+ {
+ // Another session was using this IP address before
+ if ((s->Policy->CheckIP || s->Policy->DHCPForce) &&
+ ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))
+ {
+ // Discard the packet because another session uses
+ // this IP address
+ char ip_address[32];
+ char mac_str[48];
+ IPToStr(ip_address, sizeof(ip_address), &ip);
+
+ Debug("IP Address %s is Already used by Session %X.\n",
+ ip_address, s);
+
+ MacToStr(mac_str, sizeof(mac_str), e->MacAddress);
+
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name, mac_str,
+ e->CreatedTime, e->UpdatedTime, e->DhcpAllocated, now);
+ }
+
+ goto DISCARD_PACKET;
+ }
+
+ if (s->Policy->DHCPForce)
+ {
+ if (e->DhcpAllocated == false)
+ {
+ char ipstr[MAX_SIZE];
+
+ // Discard the packet because this IP address
+ // isn't assigned by the DHCP server
+ IPToStr32(ipstr, sizeof(ipstr), uint_ip);
+ if (no_heavy == false)
+ {
+ HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);
+ }
+ goto DISCARD_PACKET;
+ }
+ }
+
+ // Overwrite the entry
+ e->Session = s;
+ e->UpdatedTime = now;
+ Copy(e->MacAddress, packet->MacAddressSrc, 6);
+ }
+ }
+ }
+ }
+
+ if (s != NULL && broadcast_mode)
+ {
+ // Calling Broadcast Storm avoidance algorithm
+ // in order to prevent occurrence of a broadcast packet loop
+ // or a large number of broadcast
+ if (CheckBroadcastStorm(hub, s, packet) == false)
+ {
+ goto DISCARD_PACKET;
+ }
+ }
+
+ // Adding traffic
+ Zero(&traffic, sizeof(traffic));
+ if (packet->BroadcastPacket)
+ {
+ // Broadcast
+ traffic.Send.BroadcastBytes = packet->PacketSize;
+ traffic.Send.BroadcastCount = 1;
+ }
+ else
+ {
+ // Unicast
+ traffic.Send.UnicastBytes = packet->PacketSize;
+ traffic.Send.UnicastCount = 1;
+ }
+
+ if (s != NULL)
+ {
+ AddTrafficForSession(s, &traffic);
+ }
+
+ // Invert the Recv and Send of traffic information
+ Copy(&traffic.Recv, &traffic.Send, sizeof(TRAFFIC_ENTRY));
+ Zero(&traffic.Send, sizeof(TRAFFIC_ENTRY));
+
+ // Broadcast this packet to the monitor port of the HUB
+ if (hub->MonitorList->num_item != 0)
+ {
+ LockList(hub->MonitorList);
+ {
+ UINT i;
+ void *data;
+ UINT size = packet->PacketSize;
+ for (i = 0;i < LIST_NUM(hub->MonitorList);i++)
+ {
+ SESSION *monitor_session = (SESSION *)LIST_DATA(hub->MonitorList, i);
+
+ // Flood the packet
+ if (monitor_session->PacketAdapter->Param != NULL)
+ {
+ data = MallocFast(size);
+ Copy(data, packet->PacketData, size);
+ StorePacketToHubPa((HUB_PA *)monitor_session->PacketAdapter->Param,
+ s, data, size, packet);
+ }
+ }
+ }
+ UnlockList(hub->MonitorList);
+ }
+
+ if (broadcast_mode == false)
+ {
+ if (dest_pa != NULL)
+ {
+ if (dest_session->Policy->NoIPv6DefaultRouterInRA ||
+ (dest_session->Policy->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session) ||
+ (hub->Option->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session))
+ {
+ DeleteIPv6DefaultRouterInRA(packet);
+ }
+ if (dest_session->Policy->RSandRAFilter)
+ {
+ if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_ICMPV6 &&
+ (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||
+ packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ if (dest_session->Policy->DHCPFilter)
+ {
+ if (packet->TypeL3 == L3_IPV4 &&
+ packet->TypeL4 == L4_UDP &&
+ packet->TypeL7 == L7_DHCPV4)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ if (dest_session->Policy->DHCPv6Filter)
+ {
+ if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_UDP &&
+ (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ if (dest_session->Policy->ArpDhcpOnly)
+ {
+ if (packet->BroadcastPacket)
+ {
+ bool b = true;
+
+ if (packet->TypeL3 == L3_IPV4 &&
+ packet->TypeL4 == L4_UDP &&
+ packet->TypeL7 == L7_DHCPV4)
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_ARPV4)
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_UDP &&
+ (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_ICMPV6)
+ {
+ b = false;
+ }
+
+ if (b)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ }
+ if (dest_session->Policy->FilterIPv4)
+ {
+ if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ if (dest_session->Policy->FilterIPv6)
+ {
+ if (packet->TypeL3 == L3_IPV6)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+ if (dest_session->Policy->FilterNonIP)
+ {
+ if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+
+ if (s != NULL &&
+ (packet->BroadcastPacket == false &&
+ s->Policy->PrivacyFilter &&
+ dest_session->Policy->PrivacyFilter)
+ )
+ {
+ // Privacy filter
+ if (packet->TypeL3 != L3_ARPV4)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+
+ if (s != NULL)
+ {
+ if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
+ Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
+ {
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+
+ // Take a packet log
+ if (s != NULL)
+ {
+ if (PacketLog(s->Hub, s, dest_session, packet, now) == false)
+ {
+ // The packet drops because it have exceeded the allowable amount
+ goto DISCARD_UNICAST_PACKET;
+ }
+ }
+
+ // Store to the destination HUB_PA
+ StorePacketToHubPa(dest_pa, s, packet->PacketData, packet->PacketSize, packet);
+
+ // Adding traffic
+ AddTrafficForSession(dest_session, &traffic);
+ }
+ else
+ {
+DISCARD_UNICAST_PACKET:
+ Free(packet->PacketData);
+ }
+ }
+ else
+ {
+ // Take a packet log
+ if (s != NULL)
+ {
+ if (PacketLog(s->Hub, s, NULL, packet, now) == false)
+ {
+ // The packet drops because It have exceeded the allowable amount
+ goto DISCARD_BROADCAST_PACKET;
+ }
+ }
+
+ // Store for all sessions
+ LockList(hub->SessionList);
+ {
+ UINT i, num = LIST_NUM(hub->SessionList);
+ for (i = 0;i < num;i++)
+ {
+ SESSION *dest_session = LIST_DATA(hub->SessionList, i);
+ HUB_PA *dest_pa = (HUB_PA *)dest_session->PacketAdapter->Param;
+ bool discard = false;
+
+ if (dest_session != s)
+ {
+ bool delete_default_router_in_ra = false;
+
+ if (dest_session->IsMonitorMode)
+ {
+ discard = true;
+ }
+
+ if (dest_session->VLanId != 0 && packet->TypeL3 == L3_TAGVLAN &&
+ packet->VlanId != dest_session->VLanId)
+ {
+ discard = true;
+ }
+
+ if (dest_session->Policy->NoIPv6DefaultRouterInRA ||
+ (dest_session->Policy->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session) ||
+ (hub->Option->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session))
+ {
+ if (packet->TypeL3 == L3_IPV6 && packet->TypeL4 == L4_ICMPV6 &&
+ (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
+ {
+ if (packet->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)
+ {
+ delete_default_router_in_ra = true;
+ }
+ }
+ }
+ if (dest_session->Policy->RSandRAFilter)
+ {
+ if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_ICMPV6 &&
+ (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||
+ packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
+ {
+ discard = true;
+ }
+ }
+
+ if (dest_session->Policy->DHCPFilter)
+ {
+ if (packet->TypeL3 == L3_IPV4 &&
+ packet->TypeL4 == L4_UDP &&
+ packet->TypeL7 == L7_DHCPV4)
+ {
+ discard = true;
+ }
+ }
+
+ if (dest_session->Policy->DHCPv6Filter)
+ {
+ if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_UDP &&
+ (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))
+ {
+ discard = true;
+ }
+ }
+
+ if (dest_session->Policy->ArpDhcpOnly)
+ {
+ if (packet->BroadcastPacket)
+ {
+ bool b = true;
+
+ if (packet->TypeL3 == L3_IPV4 &&
+ packet->TypeL4 == L4_UDP &&
+ packet->TypeL7 == L7_DHCPV4)
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_ARPV4)
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_UDP &&
+ (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))
+ {
+ b = false;
+ }
+ else if (packet->TypeL3 == L3_IPV6 &&
+ packet->TypeL4 == L4_ICMPV6)
+ {
+ b = false;
+ }
+
+ if (discard == false)
+ {
+ discard = b;
+ }
+ }
+ }
+
+ if (dest_session->Policy->FilterIPv4)
+ {
+ if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)
+ {
+ discard = true;
+ }
+ }
+ if (dest_session->Policy->FilterIPv6)
+ {
+ if (packet->TypeL3 == L3_IPV6)
+ {
+ discard = true;
+ }
+ }
+ if (dest_session->Policy->FilterNonIP)
+ {
+ if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)
+ {
+ discard = true;
+ }
+ }
+
+ if (s != NULL &&
+ (packet->BroadcastPacket == false &&
+ s->Policy->PrivacyFilter &&
+ dest_session->Policy->PrivacyFilter)
+ )
+ {
+ // Privacy filter
+ if (packet->TypeL3 != L3_ARPV4)
+ {
+ discard = true;
+ }
+ }
+
+ if (s != NULL)
+ {
+ if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
+ Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
+ {
+ discard = true;
+ }
+ }
+
+ if (discard == false && dest_pa != NULL)
+ {
+ // Store in session other than its own
+ data = MallocFast(packet->PacketSize);
+ Copy(data, packet->PacketData, packet->PacketSize);
+ size = packet->PacketSize;
+
+ if (delete_default_router_in_ra)
+ {
+ PKT *pkt2 = ParsePacket(data, size);
+
+ DeleteIPv6DefaultRouterInRA(pkt2);
+
+ FreePacket(pkt2);
+ }
+
+ StorePacketToHubPa(dest_pa, s, data, size, packet);
+
+ // Adding traffic
+ AddTrafficForSession(dest_session, &traffic);
+ }
+ }
+ }
+ }
+ UnlockList(hub->SessionList);
+
+DISCARD_BROADCAST_PACKET:
+ Free(packet->PacketData);
+ }
+ FreePacket(packet);
+ }
+ }
+ }
+ UnlockList(hub->MacTable);
+}
+
+// Examine the maximum number of logging target packets per minute
+bool CheckMaxLoggedPacketsPerMinute(SESSION *s, UINT max_packets, UINT64 now)
+{
+ UINT64 minute = 60 * 1000;
+ // Validate arguments
+ if (s == NULL || max_packets == 0)
+ {
+ return true;
+ }
+
+ if ((s->Policy != NULL && s->Policy->NoBroadcastLimiter) ||
+ s->SecureNATMode || s->BridgeMode || s->LinkModeServer || s->LinkModeClient ||
+ s->L3SwitchMode)
+ {
+ return true;
+ }
+
+ if (s->MaxLoggedPacketsPerMinuteStartTick == 0 ||
+ ((s->MaxLoggedPacketsPerMinuteStartTick + minute) <= now))
+ {
+ s->MaxLoggedPacketsPerMinuteStartTick = now;
+ s->CurrentNumPackets = 0;
+ }
+
+ s->CurrentNumPackets++;
+ if (s->CurrentNumPackets > max_packets)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Confirm whether the specified IP address is managed by Virtual HUB
+bool IsIPManagementTargetForHUB(IP *ip, HUB *hub)
+{
+ // Validate arguments
+ if (ip == NULL || hub == NULL)
+ {
+ return false;
+ }
+
+ if (hub->Option == NULL)
+ {
+ return true;
+ }
+
+ if (IsIP4(ip))
+ {
+ if (hub->Option->ManageOnlyPrivateIP)
+ {
+ if (IsIPPrivate(ip) == false)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (hub->Option->ManageOnlyLocalUnicastIPv6)
+ {
+ UINT ip_type = GetIPAddrType6(ip);
+
+ if (!(ip_type & IPV6_ADDR_LOCAL_UNICAST))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Delete old IP table entries
+void DeleteOldIpTableEntry(LIST *o)
+{
+ UINT i;
+ UINT64 oldest_time = 0xffffffffffffffffULL;
+ IP_TABLE_ENTRY *old = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(o, i);
+
+ if (e->UpdatedTime <= oldest_time)
+ {
+ old = e;
+ }
+ }
+
+ if (old != NULL)
+ {
+ Delete(o, old);
+ Free(old);
+ }
+}
+
+
+// Add to Storm list
+STORM *AddStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip, bool strict)
+{
+ STORM *s;
+ // Validate arguments
+ if (pa == NULL || mac_address == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(STORM));
+ if (src_ip != NULL)
+ {
+ Copy(&s->SrcIp, src_ip, sizeof(IP));
+ }
+ if (dest_ip != NULL)
+ {
+ Copy(&s->DestIp, dest_ip, sizeof(IP));
+ }
+ Copy(s->MacAddress, mac_address, 6);
+ s->StrictMode = strict;
+
+ Insert(pa->StormList, s);
+
+ return s;
+}
+
+// Search in Storm list
+STORM *SearchStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip, bool strict)
+{
+ STORM t, *s;
+ // Validate arguments
+ if (pa == NULL || mac_address == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ if (src_ip != NULL)
+ {
+ Copy(&t.SrcIp, src_ip, sizeof(IP));
+ }
+ if (dest_ip != NULL)
+ {
+ Copy(&t.DestIp, dest_ip, sizeof(IP));
+ }
+ Copy(t.MacAddress, mac_address, 6);
+
+ t.StrictMode = strict;
+
+ s = Search(pa->StormList, &t);
+
+ return s;
+}
+
+// Store the packet to destination HUB_PA
+void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (dest == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (size < 14)
+ {
+ Free(data);
+ return;
+ }
+
+ if (src != NULL)
+ {
+ // Apply the access list for forwarding
+ if (ApplyAccessListToForwardPacket(src->Hub, src, dest->Session, packet) == false)
+ {
+ Free(data);
+ return;
+ }
+ }
+
+ if (src != NULL)
+ {
+ if (dest->Session->Policy->MaxDownload != 0)
+ {
+ // Traffic limit
+ if (packet != NULL && IsMostHighestPriorityPacket(dest->Session, packet) == false)
+ {
+ TRAFFIC_LIMITER *tr = &dest->DownloadLimiter;
+ IntoTrafficLimiter(tr, packet);
+
+ if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > dest->Session->Policy->MaxDownload)
+ {
+ // Limit
+ Free(data);
+ return;
+ }
+ }
+ }
+ }
+
+ if (src != NULL && src->Hub != NULL && src->Hub->Option != NULL && src->Hub->Option->FixForDLinkBPDU)
+ {
+ // Measures for D-Link bug
+ UCHAR *mac = packet->MacAddressSrc;
+ if ((mac[0] == 0x00 && mac[1] == 0x80 && mac[2] == 0xc8 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00) ||
+ (mac[0] == 0x00 && mac[1] == 0x0d && mac[2] == 0x88 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00))
+ {
+ SESSION *session = dest->Session;
+
+ if (session != NULL)
+ {
+ if (session->Policy != NULL && session->Policy->CheckMac)
+ {
+ UCHAR hash[MD5_SIZE];
+ Hash(hash, packet->PacketData, packet->PacketSize, false);
+
+ Copy(session->LastDLinkSTPPacketDataHash, hash, MD5_SIZE);
+ session->LastDLinkSTPPacketSendTick = Tick64();
+ }
+ }
+ }
+ }
+
+ // Remove the VLAN tag
+ if (dest->Session != NULL && dest->Session->VLanId != 0)
+ {
+ UINT vlan_tpid = 0;
+ if (src != NULL && src->Hub != NULL && src->Hub->Option != NULL)
+ {
+ vlan_tpid = src->Hub->Option->VlanTypeId;
+ }
+ if (VLanRemoveTag(&data, &size, dest->Session->VLanId, vlan_tpid) == false)
+ {
+ Free(data);
+ return;
+ }
+ }
+
+ if (dest != NULL && src != NULL && dest->Session != NULL && src->Hub != NULL && src->Hub->Option != NULL)
+ {
+ if (dest->Session->AdjustMss != 0 ||
+ (dest->Session->IsUsingUdpAcceleration && dest->Session->UdpAccelMss != 0) ||
+ (dest->Session->IsRUDPSession && dest->Session->RUdpMss != 0))
+ {
+ if (src->Hub->Option->DisableAdjustTcpMss == false)
+ {
+ UINT target_mss = INFINITE;
+
+ if (dest->Session->AdjustMss != 0)
+ {
+ target_mss = MIN(target_mss, dest->Session->AdjustMss);
+ }
+
+ if (dest->Session->IsUsingUdpAcceleration && dest->Session->UdpAccelMss != 0)
+ {
+ target_mss = MIN(target_mss, dest->Session->UdpAccelMss);
+ }
+ else if (dest->Session->IsRUDPSession && dest->Session->RUdpMss != 0)
+ {
+ target_mss = MIN(target_mss, dest->Session->RUdpMss);
+ }
+
+ // Processing of Adjust TCP MSS
+ if (target_mss != INFINITE)
+ {
+ AdjustTcpMssL2(data, size, target_mss, src->Hub->Option->VlanTypeId);
+ }
+ }
+ }
+ }
+
+ // Create a block
+ b = NewBlock(data, size, 0);
+
+ LockQueue(dest->PacketQueue);
+ {
+ // Measure the length of queue
+ if ((dest->PacketQueue->num_item < MAX_STORED_QUEUE_NUM) ||
+ (((UCHAR *)data)[12] == 'S' && ((UCHAR *)data)[13] == 'E'))
+ {
+ // Store
+ InsertQueue(dest->PacketQueue, b);
+ }
+ else
+ {
+ // Drop the packet
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(dest->PacketQueue);
+
+ // Issue of cancellation
+ if (src != NULL)
+ {
+ AddCancelList(src->CancelList, dest->Cancel);
+ }
+ else
+ {
+ Cancel(dest->Cancel);
+ }
+}
+
+// Remove the default router specification from the IPv6 router advertisement
+bool DeleteIPv6DefaultRouterInRA(PKT *p)
+{
+ if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
+ (p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
+ {
+ if (p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)
+ {
+ p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime = 0;
+
+ p->L4.ICMPHeader->Checksum = 0;
+ p->L4.ICMPHeader->Checksum =
+ CalcChecksumForIPv6(&p->L3.IPv6Header->SrcAddress,
+ &p->L3.IPv6Header->DestAddress, IP_PROTO_ICMPV6,
+ p->L4.ICMPHeader, p->IPv6HeaderPacketInfo.PayloadSize, 0);
+ }
+ }
+
+ return false;
+}
+
+// Packet filter by policy
+bool StorePacketFilterByPolicy(SESSION *s, PKT *p)
+{
+ POLICY *pol;
+ HUB *hub;
+ bool no_heavy = false;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ hub = s->Hub;
+
+ if (hub->Option != NULL)
+ {
+ no_heavy = hub->Option->DoNotSaveHeavySecurityLogs;
+ }
+
+ // Policy
+ pol = s->Policy;
+
+ // To prohibit the operation as a server
+ if (pol->NoServer)
+ {
+ if (p->TypeL3 == L3_IPV4)
+ {
+ if (p->TypeL4 == L4_TCP)
+ {
+ UCHAR flag = p->L4.TCPHeader->Flag;
+ if ((flag & TCP_SYN) && (flag & TCP_ACK))
+ {
+ char ip1[64], ip2[64];
+ // Not to send a SYN + ACK packet
+ Debug("pol->NoServer: Discard SYN+ACK Packet.\n");
+
+ IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);
+ IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);
+
+ if (no_heavy == false)
+ {
+ HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,
+ ip1, p->L4.TCPHeader->SrcPort);
+ }
+
+ return false;
+ }
+ }
+ }
+ }
+
+ // Prohibit the operation as a server (IPv6)
+ if (pol->NoServerV6)
+ {
+ if (p->TypeL3 == L3_IPV6)
+ {
+ if (p->TypeL4 == L4_TCP)
+ {
+ UCHAR flag = p->L4.TCPHeader->Flag;
+ if ((flag & TCP_SYN) && (flag & TCP_ACK))
+ {
+ char ip1[128], ip2[128];
+ // Not to send a SYN + ACK packet
+ Debug("pol->NoServerV6: Discard SYN+ACK Packet.\n");
+
+ IP6AddrToStr(ip1, sizeof(ip1), &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress);
+ IP6AddrToStr(ip2, sizeof(ip2), &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress);
+
+ if (no_heavy == false)
+ {
+ HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,
+ ip1, p->L4.TCPHeader->SrcPort);
+ }
+
+ return false;
+ }
+ }
+ }
+ }
+
+ // Allow broadcast only DHCP and ARP
+ if (pol->ArpDhcpOnly && p->BroadcastPacket)
+ {
+ bool ok = false;
+
+ if (p->TypeL3 == L3_ARPV4)
+ {
+ ok = true;
+ }
+ if (p->TypeL3 == L3_IPV4)
+ {
+ if (p->TypeL4 == L4_UDP)
+ {
+ if (p->TypeL7 == L7_DHCPV4)
+ {
+ ok = true;
+ }
+ }
+ }
+ if (p->TypeL3 == L3_IPV6)
+ {
+ if (p->TypeL4 == L4_ICMPV6)
+ {
+ ok = true;
+ }
+ }
+
+ if (p->TypeL3 == L3_IPV6 &&
+ p->TypeL4 == L4_UDP &&
+ (Endian16(p->L4.UDPHeader->DstPort) == 546 || Endian16(p->L4.UDPHeader->DstPort) == 547))
+ {
+ ok = true;
+ }
+
+ if (ok == false)
+ {
+ return false;
+ }
+ }
+
+ // Filter IPv4 packets
+ if (pol->FilterIPv4)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (proto == 0x0800 || proto == 0x0806)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Filter IPv6 packets
+ if (pol->FilterIPv6)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (proto == 0x86dd)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Filter non-IP packets
+ if (pol->FilterNonIP)
+ {
+ if (p->MacHeader != NULL)
+ {
+ USHORT proto = Endian16(p->MacHeader->Protocol);
+ if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))
+ {
+ return false;
+ }
+ }
+ }
+
+ // Filter DHCP packets
+ if (pol->DHCPFilter)
+ {
+ if (p->TypeL3 == L3_IPV4 &&
+ p->TypeL4 == L4_UDP &&
+ p->TypeL7 == L7_DHCPV4)
+ {
+ // Discard the DHCP packet
+ Debug("pol->DHCPFilter: Discard DHCP Packet.\n");
+
+ return false;
+ }
+ }
+
+ // DHCPv6 packet filtering
+ if (pol->DHCPv6Filter)
+ {
+ if (p->TypeL3 == L3_IPV6 &&
+ p->TypeL4 == L4_UDP)
+ {
+ if (Endian16(p->L4.UDPHeader->DstPort) == 546 ||
+ Endian16(p->L4.UDPHeader->DstPort) == 547)
+ {
+ // Discard the DHCPv6 packet
+ Debug("pol->DHCPv6Filter: Discard DHCPv6 Packet.\n");
+
+ return false;
+ }
+ }
+ }
+
+ // The behavior as a DHCP server is prohibited
+ if (pol->DHCPNoServer)
+ {
+ if (p->TypeL3 == L3_IPV4 &&
+ p->TypeL4 == L4_UDP &&
+ p->TypeL7 == L7_DHCPV4)
+ {
+ DHCPV4_HEADER *h = p->L7.DHCPv4Header;
+ if (h->OpCode == 2)
+ {
+ char ip1[64], ip2[64];
+
+ // Discard the DHCP packet
+ IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);
+ IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);
+
+ if (no_heavy == false)
+ {
+ HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);
+ }
+
+ // Discard the DHCP response packet
+ Debug("pol->DHCPNoServer: Discard DHCP Response Packet.\n");
+ return false;
+ }
+ }
+ }
+
+ // The behavior as a DHCPv6 server is prohibited
+ if (pol->DHCPv6NoServer)
+ {
+ if (p->TypeL3 == L3_IPV6 &&
+ p->TypeL4 == L4_UDP &&
+ (Endian16(p->L4.UDPHeader->DstPort) == 546 || Endian16(p->L4.UDPHeader->SrcPort) == 547))
+ {
+ char ip1[128], ip2[128];
+
+ // Discard the DHCP packet
+ IP6AddrToStr(ip1, sizeof(ip1), &p->L3.IPv6Header->SrcAddress);
+ IP6AddrToStr(ip2, sizeof(ip2), &p->L3.IPv6Header->DestAddress);
+
+ if (no_heavy == false)
+ {
+ HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);
+ }
+
+ // Discard the DHCP response packet
+ Debug("pol->DHCPv6NoServer: Discard DHCPv6 Response Packet.\n");
+ return false;
+ }
+ }
+
+ // Filter the Router Solicitation / Advertising packet (IPv6)
+ if (pol->RSandRAFilter)
+ {
+ if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
+ (p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||
+ p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
+ {
+ return false;
+ }
+ }
+
+ // Filter the router advertisement packet (IPv6)
+ if (pol->RAFilter)
+ {
+ if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
+ p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT)
+ {
+ return false;
+ }
+ }
+
+ // Register to the IP table by recording the DHCP response packet
+ if (p->TypeL3 == L3_IPV4 &&
+ p->TypeL4 == L4_UDP &&
+ p->TypeL7 == L7_DHCPV4 &&
+ (s->Hub != NULL && s->Hub->Option->NoIpTable == false))
+ {
+ DHCPV4_HEADER *h = p->L7.DHCPv4Header;
+ if (h->OpCode == 2 && p->DhcpOpCode == DHCP_ACK)
+ {
+ // Register to the IP table by peeking the contents of the DHCP response packet
+ if (h->HardwareType == ARP_HARDWARE_TYPE_ETHERNET)
+ {
+ if (h->HardwareAddressSize == 6)
+ {
+ if (h->YourIP != 0 && h->YourIP != 0xffffffff)
+ {
+ UINT ip_uint = h->YourIP;
+ IP ip;
+ IP_TABLE_ENTRY *e, t;
+ MAC_TABLE_ENTRY *mac_table, mt;
+ mt.VlanId = 0;
+ Copy(&mt.MacAddress, &h->ClientMacAddress, 6);
+ mac_table = Search(hub->MacTable, &mt);
+
+ if (mac_table != NULL)
+ {
+ bool new_entry = true;
+ UINTToIP(&ip, ip_uint);
+ Copy(&t.Ip, &ip, sizeof(IP));
+
+ e = Search(hub->IpTable, &t);
+ if (e == NULL)
+ {
+ // Register as a new item
+ e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));
+UPDATE_DHCP_ALLOC_ENTRY:
+ e->CreatedTime = e->UpdatedTime = Tick64();
+ e->DhcpAllocated = true;
+ Copy(&e->Ip, &ip, sizeof(IP));
+ e->Session = mac_table->Session;
+ Copy(e->MacAddress, p->MacAddressDest, 6);
+
+ if (new_entry)
+ {
+ // Delete the expired IP table entries
+ DeleteExpiredIpTableEntry(hub->IpTable);
+ if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
+ {
+ // Remove old entries
+ DeleteOldIpTableEntry(hub->IpTable);
+ }
+ Insert(hub->IpTable, e);
+ }
+
+ if (new_entry)
+ {
+ if ((hub->Option != NULL && hub->Option->NoDhcpPacketLogOutsideHub == false) || mac_table->Session != s)
+ {
+ char dhcp_mac_addr[64];
+ char dest_mac_addr[64];
+ char dest_ip_addr[64];
+ char server_ip_addr[64];
+ MacToStr(dhcp_mac_addr, sizeof(dhcp_mac_addr), p->MacAddressSrc);
+ MacToStr(dest_mac_addr, sizeof(dest_mac_addr), h->ClientMacAddress);
+ IPToStr(dest_ip_addr, sizeof(dest_ip_addr), &ip);
+ IPToStr32(server_ip_addr, sizeof(server_ip_addr), p->L3.IPv4Header->SrcIP);
+ Debug("DHCP Allocated; dhcp server: %s, client: %s, new_ip: %s\n",
+ dhcp_mac_addr, dest_mac_addr, dest_ip_addr);
+
+ if (no_heavy == false)
+ {
+ HLog(s->Hub, "LH_REGIST_DHCP", s->Name, dhcp_mac_addr, server_ip_addr,
+ mac_table->Session->Name, dest_mac_addr, dest_ip_addr);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Update
+ new_entry = false;
+ goto UPDATE_DHCP_ALLOC_ENTRY;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Delete the expired MAC table entries
+void DeleteExpiredMacTableEntry(LIST *o)
+{
+ LIST *o2;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o2 = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MAC_TABLE_ENTRY *e = LIST_DATA(o, i);
+ if ((e->UpdatedTime + (UINT64)MAC_TABLE_EXPIRE_TIME) <= Tick64())
+ {
+ Add(o2, e);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o2);i++)
+ {
+ MAC_TABLE_ENTRY *e = LIST_DATA(o2, i);
+ Delete(o, e);
+ Free(e);
+ }
+
+ ReleaseList(o2);
+}
+
+// Delete the expired IP table entries
+void DeleteExpiredIpTableEntry(LIST *o)
+{
+ LIST *o2;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o2 = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(o, i);
+ if ((e->UpdatedTime + (UINT64)(e->DhcpAllocated ? IP_TABLE_EXPIRE_TIME_DHCP : IP_TABLE_EXPIRE_TIME)) <= Tick64())
+ {
+ Add(o2, e);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o2);i++)
+ {
+ IP_TABLE_ENTRY *e = LIST_DATA(o2, i);
+ Delete(o, e);
+ Free(e);
+ }
+
+ ReleaseList(o2);
+}
+
+// Determine whether the packet to be handled with priority
+bool IsMostHighestPriorityPacket(SESSION *s, PKT *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ if (p->TypeL3 == L3_ARPV4)
+ {
+ // ARP packets
+ return true;
+ }
+
+ if (p->TypeL3 == L3_IPV4)
+ {
+ if (p->TypeL4 == L4_ICMPV4)
+ {
+ // ICMP packets
+ return true;
+ }
+
+ if (p->TypeL4 == L4_TCP)
+ {
+ if ((p->L4.TCPHeader->Flag & TCP_SYN) || (p->L4.TCPHeader->Flag & TCP_FIN)
+ || (p->L4.TCPHeader->Flag & TCP_RST))
+ {
+ // SYN, FIN, RST packet
+ return true;
+ }
+ }
+
+ if (p->TypeL4 == L4_UDP)
+ {
+ if (p->TypeL7 == L7_DHCPV4)
+ {
+ // DHCP packets
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Add a packet to traffic limiter
+void IntoTrafficLimiter(TRAFFIC_LIMITER *tr, PKT *p)
+{
+ UINT64 now = Tick64();
+ // Validate arguments
+ if (tr == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (tr->LastTime == 0 || tr->LastTime > now ||
+ (tr->LastTime + LIMITER_SAMPLING_SPAN) < now)
+ {
+ // Sampling initialization
+ tr->Value = 0;
+ tr->LastTime = now;
+ }
+
+ // Value increase
+ tr->Value += (UINT64)(p->PacketSize * 8);
+}
+
+// The bandwidth reduction by traffic limiter
+bool StorePacketFilterByTrafficLimiter(SESSION *s, PKT *p)
+{
+ HUB_PA *pa;
+ TRAFFIC_LIMITER *tr;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ if (s->Policy->MaxUpload == 0)
+ {
+ // Unlimited
+ return true;
+ }
+
+ pa = (HUB_PA *)s->PacketAdapter->Param;
+ tr = &pa->UploadLimiter;
+
+ // Restrictions are not applied for priority packets
+ if (IsMostHighestPriorityPacket(s, p))
+ {
+ return true;
+ }
+
+ // Input packets to the limiter
+ IntoTrafficLimiter(tr, p);
+
+ // Compare the current bandwidth and limit value
+ if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > s->Policy->MaxUpload)
+ {
+ // Discard the packet
+ return false;
+ }
+
+ return true;
+}
+
+// Filtering of packets to store
+bool StorePacketFilter(SESSION *s, PKT *packet)
+{
+ // Validate arguments
+ if (s == NULL || packet == NULL)
+ {
+ return false;
+ }
+
+ // The bandwidth reduction by traffic limiter
+ if (StorePacketFilterByTrafficLimiter(s, packet) == false)
+ {
+ return false;
+ }
+
+ // Packet filter by policy
+ if (StorePacketFilterByPolicy(s, packet) == false)
+ {
+ return false;
+ }
+
+ // The packet filter with Access Lists
+ if (ApplyAccessListToStoredPacket(s->Hub, s, packet) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the packet adapter for the HUB
+PACKET_ADAPTER *GetHubPacketAdapter()
+{
+ // Hand over by creating a function list
+ PACKET_ADAPTER *pa = NewPacketAdapter(HubPaInit,
+ HubPaGetCancel, HubPaGetNextPacket, HubPaPutPacket, HubPaFree);
+
+ return pa;
+}
+
+// Stop all the SESSION of the HUB
+void StopAllSession(HUB *h)
+{
+ SESSION **s;
+ UINT i, num;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->SessionList);
+ {
+ num = LIST_NUM(h->SessionList);
+ s = ToArray(h->SessionList);
+ DeleteAll(h->SessionList);
+ }
+ UnlockList(h->SessionList);
+
+ for (i = 0;i < num;i++)
+ {
+ StopSession(s[i]);
+ ReleaseSession(s[i]);
+ }
+
+ Free(s);
+}
+
+// Remove the SESSION from HUB
+void DelSession(HUB *h, SESSION *s)
+{
+ // Validate arguments
+ if (h == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(h->SessionList);
+ {
+ if (Delete(h->SessionList, s))
+ {
+ Debug("Session %s was Deleted from %s.\n", s->Name, h->Name);
+ ReleaseSession(s);
+ }
+ }
+ UnlockList(h->SessionList);
+}
+
+// Add a SESSION to the HUB
+void AddSession(HUB *h, SESSION *s)
+{
+ // Validate arguments
+ if (h == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(h->SessionList);
+ {
+ Insert(h->SessionList, s);
+ AddRef(s->ref);
+ Debug("Session %s Inserted to %s.\n", s->Name, h->Name);
+
+ if (s->InProcMode)
+ {
+ s->UniqueId = GetNewUniqueId(h);
+ }
+ }
+ UnlockList(h->SessionList);
+}
+
+// Create a new unique ID of the HUB
+UINT GetNewUniqueId(HUB *h)
+{
+ UINT id;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return 0;
+ }
+
+ for (id = 1;;id++)
+ {
+ if (SearchSessionByUniqueId(h, id) == NULL)
+ {
+ return id;
+ }
+ }
+}
+
+// Search for a session by the unique session ID
+SESSION *SearchSessionByUniqueId(HUB *h, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(h->SessionList);i++)
+ {
+ SESSION *s = LIST_DATA(h->SessionList, i);
+
+ if (s->UniqueId == id)
+ {
+ return s;
+ }
+ }
+
+ return NULL;
+}
+
+// Stop the operation of the HUB
+void StopHub(HUB *h)
+{
+ bool old_status = false;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ old_status = h->Offline;
+ h->HubIsOnlineButHalting = true;
+
+ SetHubOffline(h);
+
+ if (h->Halt == false)
+ {
+ SLog(h->Cedar, "LS_HUB_STOP", h->Name);
+ h->Halt = true;
+ }
+
+ h->Offline = old_status;
+ h->HubIsOnlineButHalting = false;
+}
+
+// Online the Virtual HUB
+void SetHubOnline(HUB *h)
+{
+ bool for_cluster = false;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ for_cluster = true;
+ }
+ }
+
+ Lock(h->lock_online);
+ {
+ if (h->Offline == false)
+ {
+ Unlock(h->lock_online);
+ return;
+ }
+ HLog(h, "LH_ONLINE");
+
+ // Start all links
+ StartAllLink(h);
+
+ // Start the SecureNAT
+ if (h->EnableSecureNAT)
+ {
+ if (h->SecureNAT == NULL)
+ {
+ if (for_cluster == false)
+ {
+ h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);
+ }
+ }
+ }
+
+ // Start all of the local bridges that is associated with this HUB
+ if (h->Type != HUB_TYPE_FARM_DYNAMIC)
+ {
+ LockList(h->Cedar->LocalBridgeList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);
+
+ if (StrCmpi(br->HubName, h->Name) == 0)
+ {
+ if (br->Bridge == NULL)
+ {
+ br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor,
+ br->TapMode, br->TapMacAddress, br->LimitBroadcast, br);
+ }
+ }
+ }
+ }
+ UnlockList(h->Cedar->LocalBridgeList);
+ }
+
+ h->Offline = false;
+ }
+ Unlock(h->lock_online);
+
+ if (h->Cedar->Server != NULL)
+ {
+ SiHubOnlineProc(h);
+ }
+}
+
+// Offline the Virtual HUB
+void SetHubOffline(HUB *h)
+{
+ UINT i;
+ bool for_cluster = false;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ for_cluster = true;
+ }
+ }
+
+ h->BeingOffline = true;
+
+ Lock(h->lock_online);
+ {
+ if (h->Offline || h->Halt)
+ {
+ Unlock(h->lock_online);
+ h->BeingOffline = false;
+ return;
+ }
+
+ HLog(h, "LH_OFFLINE");
+
+ // Stop all links
+ StopAllLink(h);
+
+ // Stop the SecureNAT
+ SnFreeSecureNAT(h->SecureNAT);
+ h->SecureNAT = NULL;
+
+ // Stop all the local bridges that is associated with this HUB
+ LockList(h->Cedar->LocalBridgeList);
+ {
+ for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);
+
+ if (StrCmpi(br->HubName, h->Name) == 0)
+ {
+ BrFreeBridge(br->Bridge);
+ br->Bridge = NULL;
+ }
+ }
+ }
+ UnlockList(h->Cedar->LocalBridgeList);
+
+ // Offline
+ h->Offline = true;
+
+ // Disconnect all sessions
+ StopAllSession(h);
+ }
+ Unlock(h->lock_online);
+
+ h->BeingOffline = false;
+
+ if (h->Cedar->Server != NULL)
+ {
+ SiHubOfflineProc(h);
+ }
+}
+
+// Get whether a HUB which have the specified name exists
+bool IsHub(CEDAR *cedar, char *name)
+{
+ HUB *h;
+ // Validate arguments
+ if (cedar == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ h = GetHub(cedar, name);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ReleaseHub(h);
+
+ return true;
+}
+
+// Get the HUB
+HUB *GetHub(CEDAR *cedar, char *name)
+{
+ HUB *h, t;
+ // Validate arguments
+ if (cedar == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ LockHubList(cedar);
+
+ t.Name = name;
+ h = Search(cedar->HubList, &t);
+ if (h == NULL)
+ {
+ UnlockHubList(cedar);
+ return NULL;
+ }
+
+ AddRef(h->ref);
+
+ UnlockHubList(cedar);
+
+ return h;
+}
+
+// Lock the HUB list
+void LockHubList(CEDAR *cedar)
+{
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+
+ LockList(cedar->HubList);
+}
+
+// Unlock the HUB list
+void UnlockHubList(CEDAR *cedar)
+{
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+
+ UnlockList(cedar->HubList);
+}
+
+// Release the HUB
+void ReleaseHub(HUB *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (Release(h->ref) == 0)
+ {
+ CleanupHub(h);
+ }
+}
+
+// Get the Radius server information
+bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size)
+{
+ UINT interval;
+ return GetRadiusServerEx(hub, name, size, port, secret, secret_size, &interval);
+}
+bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval)
+{
+ return GetRadiusServerEx2(hub, name, size, port, secret, secret_size, interval, NULL, 0);
+}
+bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, char *suffix_filter, UINT suffix_filter_size)
+{
+ bool ret = false;
+ // Validate arguments
+ if (hub == NULL || name == NULL || port == NULL || secret == NULL || interval == NULL)
+ {
+ return false;
+ }
+
+ Lock(hub->RadiusOptionLock);
+ {
+ if (hub->RadiusServerName != NULL)
+ {
+ char *tmp;
+ UINT tmp_size;
+ StrCpy(name, size, hub->RadiusServerName);
+ *port = hub->RadiusServerPort;
+ *interval = hub->RadiusRetryInterval;
+
+ tmp_size = hub->RadiusSecret->Size + 1;
+ tmp = ZeroMalloc(tmp_size);
+ Copy(tmp, hub->RadiusSecret->Buf, hub->RadiusSecret->Size);
+ StrCpy(secret, secret_size, tmp);
+ Free(tmp);
+
+ if (suffix_filter != NULL)
+ {
+ StrCpy(suffix_filter, suffix_filter_size, hub->RadiusSuffixFilter);
+ }
+
+ ret = true;
+ }
+ }
+ Unlock(hub->RadiusOptionLock);
+
+ return ret;
+}
+
+// Set the Radius server information
+void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret)
+{
+ SetRadiusServerEx(hub, name, port, secret, RADIUS_RETRY_INTERVAL);
+}
+void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval)
+{
+ // Validate arguments
+ if (hub == NULL)
+ {
+ return;
+ }
+
+ Lock(hub->RadiusOptionLock);
+ {
+ if (hub->RadiusServerName != NULL)
+ {
+ Free(hub->RadiusServerName);
+ }
+
+ if (name == NULL)
+ {
+ hub->RadiusServerName = NULL;
+ hub->RadiusServerPort = 0;
+ hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
+ FreeBuf(hub->RadiusSecret);
+ }
+ else
+ {
+ hub->RadiusServerName = CopyStr(name);
+ hub->RadiusServerPort = port;
+ if (interval == 0)
+ {
+ hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
+ }
+ else if (interval > RADIUS_RETRY_TIMEOUT)
+ {
+ hub->RadiusRetryInterval = RADIUS_RETRY_TIMEOUT;
+ }
+ else
+ {
+ hub->RadiusRetryInterval = interval;
+ }
+ FreeBuf(hub->RadiusSecret);
+
+ if (secret == NULL)
+ {
+ hub->RadiusSecret = NewBuf();
+ }
+ else
+ {
+ hub->RadiusSecret = NewBuf();
+ WriteBuf(hub->RadiusSecret, secret, StrLen(secret));
+ SeekBuf(hub->RadiusSecret, 0, 0);
+ }
+ }
+ }
+ Unlock(hub->RadiusOptionLock);
+}
+
+// Get the difference between the traffic data
+void CalcTrafficEntryDiff(TRAFFIC_ENTRY *diff, TRAFFIC_ENTRY *old, TRAFFIC_ENTRY *current)
+{
+ // Validate arguments
+ Zero(diff, sizeof(TRAFFIC_ENTRY));
+ if (old == NULL || current == NULL || diff == NULL)
+ {
+ return;
+ }
+
+ if (current->BroadcastCount >= old->BroadcastCount)
+ {
+ diff->BroadcastCount = current->BroadcastCount - old->BroadcastCount;
+ }
+ if (current->BroadcastBytes >= old->BroadcastBytes)
+ {
+ diff->BroadcastBytes = current->BroadcastBytes - old->BroadcastBytes;
+ }
+ if (current->UnicastCount >= old->UnicastCount)
+ {
+ diff->UnicastCount = current->UnicastCount - old->UnicastCount;
+ }
+ if (current->UnicastBytes >= old->UnicastBytes)
+ {
+ diff->UnicastBytes = current->UnicastBytes - old->UnicastBytes;
+ }
+}
+void CalcTrafficDiff(TRAFFIC *diff, TRAFFIC *old, TRAFFIC *current)
+{
+ Zero(diff, sizeof(TRAFFIC));
+ if (old == NULL || current == NULL || diff == NULL)
+ {
+ return;
+ }
+
+ CalcTrafficEntryDiff(&diff->Send, &old->Send, &current->Send);
+ CalcTrafficEntryDiff(&diff->Recv, &old->Recv, &current->Recv);
+}
+
+// Add the traffic information for Virtual HUB
+void IncrementHubTraffic(HUB *h)
+{
+ TRAFFIC t;
+ // Validate arguments
+ if (h == NULL || h->FarmMember == false)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ Lock(h->TrafficLock);
+ {
+ t.Send.BroadcastBytes =
+ h->Traffic->Send.BroadcastBytes - h->OldTraffic->Send.BroadcastBytes;
+ t.Send.BroadcastCount =
+ h->Traffic->Send.BroadcastCount - h->OldTraffic->Send.BroadcastCount;
+ t.Send.UnicastBytes =
+ h->Traffic->Send.UnicastBytes - h->OldTraffic->Send.UnicastBytes;
+ t.Send.UnicastCount =
+ h->Traffic->Send.UnicastCount - h->OldTraffic->Send.UnicastCount;
+ t.Recv.BroadcastBytes =
+ h->Traffic->Recv.BroadcastBytes - h->OldTraffic->Recv.BroadcastBytes;
+ t.Recv.BroadcastCount =
+ h->Traffic->Recv.BroadcastCount - h->OldTraffic->Recv.BroadcastCount;
+ t.Recv.UnicastBytes =
+ h->Traffic->Recv.UnicastBytes - h->OldTraffic->Recv.UnicastBytes;
+ t.Recv.UnicastCount =
+ h->Traffic->Recv.UnicastCount - h->OldTraffic->Recv.UnicastCount;
+ Copy(h->OldTraffic, h->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(h->TrafficLock);
+
+ if (IsZero(&t, sizeof(TRAFFIC)))
+ {
+ return;
+ }
+
+ AddTrafficDiff(h, h->Name, TRAFFIC_DIFF_HUB, &t);
+}
+
+// Adding Traffic information
+void AddTrafficDiff(HUB *h, char *name, UINT type, TRAFFIC *traffic)
+{
+ TRAFFIC_DIFF *d;
+ // Validate arguments
+ if (h == NULL || h->FarmMember == false || name == NULL || traffic == NULL)
+ {
+ return;
+ }
+
+ if (LIST_NUM(h->Cedar->TrafficDiffList) > MAX_TRAFFIC_DIFF)
+ {
+ return;
+ }
+
+ d = ZeroMallocFast(sizeof(TRAFFIC_DIFF));
+ d->HubName = CopyStr(h->Name);
+ d->Name = CopyStr(name);
+ d->Type = type;
+ Copy(&d->Traffic, traffic, sizeof(TRAFFIC));
+
+ LockList(h->Cedar->TrafficDiffList);
+ {
+ Insert(h->Cedar->TrafficDiffList, d);
+ }
+ UnlockList(h->Cedar->TrafficDiffList);
+}
+
+// Cleanup of HUB
+void CleanupHub(HUB *h)
+{
+ UINT i;
+ char name[MAX_SIZE];
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ StrCpy(name, sizeof(name), h->Name);
+
+ if (h->WatchDogStarted)
+ {
+ StopHubWatchDog(h);
+ }
+
+ FreeAccessList(h);
+
+ if (h->RadiusServerName != NULL)
+ {
+ Free(h->RadiusServerName);
+ FreeBuf(h->RadiusSecret);
+ }
+ ReleaseAllLink(h);
+ DeleteHubDb(h->HubDb);
+ ReleaseCedar(h->Cedar);
+ DeleteLock(h->lock);
+ DeleteLock(h->lock_online);
+ Free(h->Name);
+ ReleaseList(h->SessionList);
+ ReleaseList(h->MacTable);
+ ReleaseList(h->IpTable);
+ ReleaseList(h->MonitorList);
+ ReleaseList(h->LinkList);
+ DeleteCounter(h->NumSessions);
+ DeleteCounter(h->NumSessionsClient);
+ DeleteCounter(h->NumSessionsBridge);
+ DeleteCounter(h->SessionCounter);
+ FreeTraffic(h->Traffic);
+ FreeTraffic(h->OldTraffic);
+ Free(h->Option);
+
+ Free(h->SecureNATOption);
+
+ DeleteLock(h->TrafficLock);
+
+ for (i = 0;i < LIST_NUM(h->TicketList);i++)
+ {
+ Free(LIST_DATA(h->TicketList, i));
+ }
+
+ ReleaseList(h->TicketList);
+
+ DeleteLock(h->RadiusOptionLock);
+
+ FreeLog(h->PacketLogger);
+ FreeLog(h->SecurityLogger);
+
+ for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
+ {
+ Free(LIST_DATA(h->AdminOptionList, i));
+ }
+ ReleaseList(h->AdminOptionList);
+
+ if (h->Msg != NULL)
+ {
+ Free(h->Msg);
+ }
+
+ FreeUserList(h->UserList);
+
+ Free(h);
+}
+
+// Comparison function of IP table entries
+int CompareIpTable(void *p1, void *p2)
+{
+ IP_TABLE_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(IP_TABLE_ENTRY **)p1;
+ e2 = *(IP_TABLE_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+ return CmpIpAddr(&e1->Ip, &e2->Ip);
+}
+
+// Comparison function of the MAC table entries
+int CompareMacTable(void *p1, void *p2)
+{
+ int r;
+ MAC_TABLE_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(MAC_TABLE_ENTRY **)p1;
+ e2 = *(MAC_TABLE_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+ r = Cmp(e1->MacAddress, e2->MacAddress, 6);
+ if (r != 0)
+ {
+ return r;
+ }
+ if (e1->VlanId > e2->VlanId)
+ {
+ return 1;
+ }
+ else if (e1->VlanId < e2->VlanId)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Comparison function of HUB
+int CompareHub(void *p1, void *p2)
+{
+ HUB *h1, *h2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ h1 = *(HUB **)p1;
+ h2 = *(HUB **)p2;
+ if (h1 == NULL || h2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(h1->Name, h2->Name);
+}
+
+// Examine whether the MAC address is for the ARP polling of the Virtual HUB
+bool IsHubMacAddress(UCHAR *mac)
+{
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ if (mac[0] == 0x00 && mac[1] == SE_HUB_MAC_ADDR_SIGN)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether the IP address is for the ARP polling of the Virtual HUB
+bool IsHubIpAddress32(UINT ip32)
+{
+ IP ip;
+
+ UINTToIP(&ip, ip32);
+
+ return IsHubIpAddress(&ip);
+}
+bool IsHubIpAddress(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 172 && ip->addr[1] == 31)
+ {
+ if (ip->addr[2] >= 1 && ip->addr[2] <= 254)
+ {
+ if (ip->addr[3] >= 1 && ip->addr[3] <= 254)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+bool IsHubIpAddress64(IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ if (addr->Value[0] == 0xfe && addr->Value[1] == 0x80 &&
+ addr->Value[2] == 0 &&
+ addr->Value[3] == 0 &&
+ addr->Value[4] == 0 &&
+ addr->Value[5] == 0 &&
+ addr->Value[6] == 0 &&
+ addr->Value[7] == 0 &&
+ addr->Value[8] == 0x02 && addr->Value[9] == 0xae &&
+ addr->Value[11] == 0xff && addr->Value[12] == 0xfe)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Generate an IP address for the Virtual HUB
+void GenHubIpAddress(IP *ip, char *name)
+{
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (ip == NULL || name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp1, sizeof(tmp1), name);
+ Trim(tmp1);
+ GenerateMachineUniqueHash(hash);
+ BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));
+ StrCat(tmp2, sizeof(tmp2), tmp1);
+ StrUpper(tmp2);
+
+ Hash(hash, tmp2, StrLen(tmp2), true);
+
+ Zero(ip, sizeof(IP));
+ ip->addr[0] = 172;
+ ip->addr[1] = 31;
+ ip->addr[2] = hash[0] % 254 + 1;
+ ip->addr[3] = hash[1] % 254 + 1;
+}
+
+// Generate a MAC address for the Virtual HUB
+void GenHubMacAddress(UCHAR *mac, char *name)
+{
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (mac == NULL || name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp1, sizeof(tmp1), name);
+ Trim(tmp1);
+ GenerateMachineUniqueHash(hash);
+ BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));
+ StrCat(tmp2, sizeof(tmp2), tmp1);
+ StrUpper(tmp2);
+
+ Hash(hash, tmp2, StrLen(tmp2), true);
+
+ mac[0] = 0x00;
+ mac[1] = SE_HUB_MAC_ADDR_SIGN;
+ mac[2] = hash[0];
+ mac[3] = hash[1];
+ mac[4] = hash[2];
+ mac[5] = hash[3];
+}
+
+// Get a message from HUB
+wchar_t *GetHubMsg(HUB *h)
+{
+ wchar_t *ret = NULL;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(h->lock);
+ {
+ if (h->Msg != NULL)
+ {
+ ret = CopyUniStr(h->Msg);
+ }
+ }
+ Unlock(h->lock);
+
+ return ret;
+}
+
+// Set a message to the HUB
+void SetHubMsg(HUB *h, wchar_t *msg)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Lock(h->lock);
+ {
+ if (h->Msg != NULL)
+ {
+ Free(h->Msg);
+ h->Msg = NULL;
+ }
+
+ if (UniIsEmptyStr(msg) == false)
+ {
+ h->Msg = UniCopyStr(msg);
+ }
+ }
+ Unlock(h->lock);
+}
+
+// Creating a new HUB
+HUB *NewHub(CEDAR *cedar, char *HubName, HUB_OPTION *option)
+{
+ HUB *h;
+ char packet_logger_name[MAX_SIZE];
+ char tmp[MAX_SIZE];
+ char safe_hub_name[MAX_HUBNAME_LEN + 1];
+ UCHAR hash[SHA1_SIZE];
+ IP ip6;
+ // Validate arguments
+ if (cedar == NULL || option == NULL || HubName == NULL)
+ {
+ return NULL;
+ }
+
+ h = ZeroMalloc(sizeof(HUB));
+ Hash(h->HashedPassword, "", 0, true);
+ HashPassword(h->SecurePassword, ADMINISTRATOR_USERNAME, "");
+ h->lock = NewLock();
+ h->lock_online = NewLock();
+ h->ref = NewRef();
+ h->Cedar = cedar;
+ AddRef(h->Cedar->ref);
+ h->Type = HUB_TYPE_STANDALONE;
+
+ ConvertSafeFileName(safe_hub_name, sizeof(safe_hub_name), HubName);
+ h->Name = CopyStr(safe_hub_name);
+
+
+ h->AdminOptionList = NewList(CompareAdminOption);
+ AddHubAdminOptionsDefaults(h, true);
+
+ h->LastCommTime = SystemTime64();
+ h->LastLoginTime = SystemTime64();
+ h->NumLogin = 0;
+
+ h->TrafficLock = NewLock();
+
+ h->HubDb = NewHubDb();
+
+ h->SessionList = NewList(NULL);
+ h->SessionCounter = NewCounter();
+ h->NumSessions = NewCounter();
+ h->NumSessionsClient = NewCounter();
+ h->NumSessionsBridge = NewCounter();
+ h->MacTable = NewList(CompareMacTable);
+ h->IpTable = NewList(CompareIpTable);
+ h->MonitorList = NewList(NULL);
+ h->LinkList = NewList(NULL);
+
+ h->Traffic = NewTraffic();
+ h->OldTraffic = NewTraffic();
+
+ h->Option = ZeroMalloc(sizeof(HUB_OPTION));
+ Copy(h->Option, option, sizeof(HUB_OPTION));
+
+ if (h->Option->VlanTypeId == 0)
+ {
+ h->Option->VlanTypeId = MAC_PROTO_TAGVLAN;
+ }
+
+ Rand(h->HubSignature, sizeof(h->HubSignature));
+
+ // SecureNAT related
+ h->EnableSecureNAT = false;
+ h->SecureNAT = NULL;
+ h->SecureNATOption = ZeroMalloc(sizeof(VH_OPTION));
+ NiSetDefaultVhOption(NULL, h->SecureNATOption);
+
+ if (h->Cedar != NULL && h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption, true);
+ }
+
+ // Generate a temporary MAC address for the HUB
+ GenerateMachineUniqueHash(hash);
+ GenHubMacAddress(h->HubMacAddr, h->Name);
+ GenHubIpAddress(&h->HubIp, h->Name);
+
+ // IPv6 address for the HUB
+ GenerateEui64LocalAddress(&ip6, h->HubMacAddr);
+ IPToIPv6Addr(&h->HubIpV6, &ip6);
+
+ h->RadiusOptionLock = NewLock();
+ h->RadiusServerPort = RADIUS_DEFAULT_PORT;
+
+ h->TicketList = NewList(NULL);
+
+ InitAccessList(h);
+
+ // Create a user list
+ h->UserList = NewUserList();
+
+ // Default logging settings
+ h->LogSetting.SavePacketLog = h->LogSetting.SaveSecurityLog = true;
+ h->LogSetting.PacketLogConfig[PACKET_LOG_TCP_CONN] =
+ h->LogSetting.PacketLogConfig[PACKET_LOG_DHCP] = PACKET_LOG_HEADER;
+ h->LogSetting.SecurityLogSwitchType = LOG_SWITCH_DAY;
+ h->LogSetting.PacketLogSwitchType = LOG_SWITCH_DAY;
+
+ MakeDir(HUB_SECURITY_LOG_DIR_NAME);
+ MakeDir(HUB_PACKET_LOG_DIR_NAME);
+
+ // Start the packet logger
+ Format(packet_logger_name, sizeof(packet_logger_name), HUB_PACKET_LOG_FILE_NAME, h->Name);
+ h->PacketLogger = NewLog(packet_logger_name, HUB_PACKET_LOG_PREFIX, h->LogSetting.PacketLogSwitchType);
+
+ // Start the security logger
+ Format(tmp, sizeof(tmp), HUB_SECURITY_LOG_FILE_NAME, h->Name);
+ h->SecurityLogger = NewLog(tmp, HUB_SECURITY_LOG_PREFIX, h->LogSetting.SecurityLogSwitchType);
+
+ if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ h->FarmMember = true;
+ }
+
+ // Start the HUB
+ SetHubOnline(h);
+
+ if (h->Cedar->Bridge)
+ {
+ h->Option->NoArpPolling = true;
+ }
+
+ if (h->Option->NoArpPolling == false && h->Option->NoIpTable == false)
+ {
+ StartHubWatchDog(h);
+ h->WatchDogStarted = true;
+ }
+
+ SLog(h->Cedar, "LS_HUB_START", h->Name);
+
+ MacToStr(tmp, sizeof(tmp), h->HubMacAddr);
+ SLog(h->Cedar, "LS_HUB_MAC", h->Name, tmp);
+
+ return h;
+}
+
+// Delete the HUBDB
+void DeleteHubDb(HUBDB *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ LockList(d->UserList);
+ {
+ LockList(d->GroupList);
+ {
+ // Release all users and groups
+ UINT i;
+ USER **users;
+ USERGROUP **groups;
+
+ users = ToArray(d->UserList);
+ groups = ToArray(d->GroupList);
+
+ for (i = 0;i < LIST_NUM(d->UserList);i++)
+ {
+ ReleaseUser(users[i]);
+ }
+ for (i = 0;i < LIST_NUM(d->GroupList);i++)
+ {
+ ReleaseGroup(groups[i]);
+ }
+
+ Free(users);
+ Free(groups);
+ }
+ UnlockList(d->GroupList);
+ }
+ UnlockList(d->UserList);
+
+ // Release the root certificate list
+ LockList(d->RootCertList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(d->RootCertList);i++)
+ {
+ X *x = LIST_DATA(d->RootCertList, i);
+ FreeX(x);
+ }
+ }
+ UnlockList(d->RootCertList);
+
+ // Release the CRL
+ LockList(d->CrlList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(d->CrlList);i++)
+ {
+ CRL *crl = LIST_DATA(d->CrlList, i);
+ FreeCrl(crl);
+ }
+ }
+ UnlockList(d->CrlList);
+
+ // Release the AC list
+ FreeAcList(d->AcList);
+
+ ReleaseList(d->GroupList);
+ ReleaseList(d->UserList);
+ ReleaseList(d->RootCertList);
+ ReleaseList(d->CrlList);
+ Free(d);
+}
+
+// Get a log setting of the HUB
+void GetHubLogSetting(HUB *h, HUB_LOG *setting)
+{
+ // Validate arguments
+ if (setting == NULL || h == NULL)
+ {
+ return;
+ }
+
+ Copy(setting, &h->LogSetting, sizeof(HUB_LOG));
+}
+
+// Update the log settings of the HUB
+void SetHubLogSettingEx(HUB *h, HUB_LOG *setting, bool no_change_switch_type)
+{
+ UINT i1, i2;
+ // Validate arguments
+ if (setting == NULL || h == NULL)
+ {
+ return;
+ }
+
+ i1 = h->LogSetting.PacketLogSwitchType;
+ i2 = h->LogSetting.SecurityLogSwitchType;
+
+ Copy(&h->LogSetting, setting, sizeof(HUB_LOG));
+
+ if (no_change_switch_type)
+ {
+ h->LogSetting.PacketLogSwitchType = i1;
+ h->LogSetting.SecurityLogSwitchType = i2;
+ }
+
+ // Packet logger configuration
+ SetLogSwitchType(h->PacketLogger, setting->PacketLogSwitchType);
+ SetLogSwitchType(h->SecurityLogger, setting->SecurityLogSwitchType);
+}
+void SetHubLogSetting(HUB *h, HUB_LOG *setting)
+{
+ SetHubLogSettingEx(h, setting, false);
+}
+
+// Add the trusted root certificate to the HUB
+void AddRootCert(HUB *hub, X *x)
+{
+ HUBDB *db;
+ // Validate arguments
+ if (hub == NULL || x == NULL)
+ {
+ return;
+ }
+
+ db = hub->HubDb;
+ if (db != NULL)
+ {
+ LockList(db->RootCertList);
+ {
+ if (LIST_NUM(db->RootCertList) < MAX_HUB_CERTS)
+ {
+ UINT i;
+ bool ok = true;
+
+ for (i = 0;i < LIST_NUM(db->RootCertList);i++)
+ {
+ X *exist_x = LIST_DATA(db->RootCertList, i);
+ if (CompareX(exist_x, x))
+ {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ Insert(db->RootCertList, CloneX(x));
+ }
+ }
+ }
+ UnlockList(db->RootCertList);
+ }
+}
+
+// Compare the list of certificates
+int CompareCert(void *p1, void *p2)
+{
+ X *x1, *x2;
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ x1 = *(X **)p1;
+ x2 = *(X **)p2;
+ if (x1 == NULL || x2 == NULL)
+ {
+ return 0;
+ }
+
+ GetPrintNameFromX(tmp1, sizeof(tmp1), x1);
+ GetPrintNameFromX(tmp2, sizeof(tmp2), x2);
+
+ return UniStrCmpi(tmp1, tmp2);
+}
+
+// Creating a new HUBDB
+HUBDB *NewHubDb()
+{
+ HUBDB *d = ZeroMalloc(sizeof(HUBDB));
+
+ d->GroupList = NewList(CompareGroupName);
+ d->UserList = NewList(CompareUserName);
+ d->RootCertList = NewList(CompareCert);
+ d->CrlList = NewList(NULL);
+ d->AcList = NewAcList();
+
+ return d;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Hub.h b/src/Cedar/Hub.h
new file mode 100644
index 00000000..ae671d89
--- /dev/null
+++ b/src/Cedar/Hub.h
@@ -0,0 +1,598 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Hub.h
+// Header of Hub.c
+
+#ifndef HUB_H
+#define HUB_H
+
+
+// Prefix in the access list for investigating whether the user name which is contained in a particular file
+#define ACCESS_LIST_INCLUDED_PREFIX "include:" // Included
+#define ACCESS_LIST_EXCLUDED_PREFIX "exclude:" // Not included
+
+// The default value for the cache expiration of the user name reference file of the access list (in seconds)
+#define ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME 30
+
+// The maximum length of the include file in the access list
+#define ACCESS_LIST_INCLUDE_FILE_MAX_SIZE (1024 * 1024)
+
+// <INFO> tags of the URL in the access list
+#define ACCESS_LIST_URL_INFO_TAG "<INFO>"
+
+
+// SoftEther link control packet
+struct SE_LINK
+{
+ UCHAR DestMacAddress[6]; // Destination MAC address
+ UCHAR SrcMacAddress[6]; // Source MAC address
+ UCHAR SignatureS; // 'S'
+ UCHAR SignatureE; // 'E'
+ UCHAR Padding[2]; // Padding
+ UINT Type; // Type
+ UCHAR HubSignature[16]; // HUB signature
+ UINT TransactionId; // Transaction ID
+ UINT Data; // Data
+ UCHAR Dummy[20]; // Dummy
+ UCHAR Checksum[SHA1_SIZE]; // Checksum
+};
+
+
+// Test packet reception record
+struct TEST_HISTORY
+{
+ SESSION *s1;
+ SESSION *s2;
+};
+
+// State machine for link test
+struct SE_TEST
+{
+ LOCK *lock; // Lock
+ UINT64 LastTestPacketSentTime; // Time that sent the test packet at the last
+ UINT NextTestPacketSendInterval; // Next test packet transmission interval
+ bool CurrentTesting; // Test by sending a test packet currently
+ UINT TransactionId; // Transaction ID
+ LIST *TestHistory; // Reception history
+};
+
+// Macro
+#define NO_ACCOUNT_DB(h) ((h)->FarmMember)
+
+// Database in the case of a stand-alone or a farm master HUB
+struct HUBDB
+{
+ LIST *UserList; // User List
+ LIST *GroupList; // Group List
+ LIST *RootCertList; // Certificate list to trust
+ LIST *CrlList; // CRL list
+ LIST *AcList; // AC List
+};
+
+// Traffic limiter
+struct TRAFFIC_LIMITER
+{
+ UINT64 LastTime; // Time of last measured
+ UINT64 Value; // The current value
+};
+
+// Record the number of broadcast of each endpoint
+struct STORM
+{
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2]; // Padding
+ IP SrcIp; // Source IP address
+ IP DestIp; // Destination IP address
+ UINT64 CheckStartTick; // Time that checking is started
+ UINT CurrentBroadcastNum; // The current number of broadcasts
+ UINT DiscardValue; // Ratio to discard the broadcast packet
+ bool StrictMode; // Strict mode
+};
+
+// Packet adapter information structure for HUB
+struct HUB_PA
+{
+ CANCEL *Cancel; // Cancel object
+ QUEUE *PacketQueue; // Packet queue
+ bool MonitorPort; // Monitor port
+ UINT64 Now; // Current time
+ TRAFFIC_LIMITER UploadLimiter; // Upload bandwidth limit
+ TRAFFIC_LIMITER DownloadLimiter; // Download bandwidth limitation
+ SESSION *Session; // Session
+ LIST *StormList; // Broadcast storm recording list
+ UINT64 UsernameHash; // User name hash
+ UINT64 UsernameHashSimple; // User name hash (simple)
+ UINT64 GroupnameHash; // Group name hash
+};
+
+// HUB options
+struct HUB_OPTION
+{
+ // Standard options
+ UINT MaxSession; // Maximum number of simultaneous connections
+ bool NoEnum; // Excluded from the enumeration
+ // Advanced options
+ bool NoArpPolling; // No ARP polling
+ bool NoIPv6AddrPolling; // No IPv6 address polling
+ bool NoIpTable; // Do not generate an IP address table
+ bool NoMacAddressLog; // Not to write the registration log of the MAC address
+ bool ManageOnlyPrivateIP; // Manage only private IP
+ bool ManageOnlyLocalUnicastIPv6; // Manage only local unicast IPv6 addresses
+ bool DisableIPParsing; // Disable the IP interpretation
+ bool YieldAfterStorePacket; // Yield after the packet is stored
+ bool NoSpinLockForPacketDelay; // Do not use the spin lock
+ UINT BroadcastStormDetectionThreshold; // Broadcast number limit threshold
+ bool FilterPPPoE; // Filtering the PPPoE (0x8863, 0x8864)
+ bool FilterOSPF; // Filtering the OSPF (ip_proto = 89)
+ bool FilterIPv4; // Filter IPv4 packets
+ bool FilterIPv6; // Filter IPv6 packets
+ bool FilterNonIP; // Filter all non-IP packets
+ bool FilterBPDU; // Filter the BPDU packets
+ UINT ClientMinimumRequiredBuild; // If the build number of the client is lower than a certain value, deny it
+ bool NoIPv6DefaultRouterInRAWhenIPv6; // Delete the default router specification from the IPv6 router advertisement (only in the case of IPv6 physical connection)
+ bool NoIPv4PacketLog; // Do not save the packet log for the IPv4 packet
+ bool NoIPv6PacketLog; // Do not save the packet log of IPv6 packets
+ bool NoLookBPDUBridgeId; // Don't look the BPDU bridge ID for switching
+ bool NoManageVlanId; // Don't manage the VLAN ID
+ UINT VlanTypeId; // Type ID of VLAN packets (usually 0x8100)
+ bool FixForDLinkBPDU; // Apply the fix for the BPDU of the strange behavior of the D-Link
+ UINT RequiredClientId; // Client ID
+ UINT AdjustTcpMssValue; // TCP MSS adjustment value
+ bool DisableAdjustTcpMss; // Completely disable the TCP MSS adjustment function
+ bool NoDhcpPacketLogOutsideHub; // Suppress DHCP unrelated log
+ bool DisableHttpParsing; // Prohibit the HTTP interpretation
+ bool DisableUdpAcceleration; // Prohibit the UDP acceleration function
+ bool DisableUdpFilterForLocalBridgeNic; // Not to perform filtering DHCP packets associated with local bridge NIC
+ bool ApplyIPv4AccessListOnArpPacket; // Apply an IPv4 access list to the ARP packet
+ bool RemoveDefGwOnDhcpForLocalhost; // Remove the designation of the DHCP server from the DHCP response packet addressed to localhost
+ UINT SecureNAT_MaxTcpSessionsPerIp; // Maximum number of TCP sessions per IP address
+ UINT SecureNAT_MaxTcpSynSentPerIp; // Maximum number of TCP sessions of SYN_SENT state per IP address
+ UINT SecureNAT_MaxUdpSessionsPerIp; // Maximum number of UDP sessions per IP address
+ UINT SecureNAT_MaxDnsSessionsPerIp; // Maximum number of DNS sessions per IP address
+ UINT SecureNAT_MaxIcmpSessionsPerIp; // Maximum number of ICMP sessions per IP address
+ UINT AccessListIncludeFileCacheLifetime; // Expiration of the access list external file (in seconds)
+ bool DisableKernelModeSecureNAT; // Disable the kernel mode NAT
+ bool DisableUserModeSecureNAT; // Disable the user mode NAT
+ bool DisableCheckMacOnLocalBridge; // Disable the MAC address verification in local bridge
+ bool DisableCorrectIpOffloadChecksum; // Disable the correction of checksum that is IP-Offloaded
+ bool BroadcastLimiterStrictMode; // Strictly broadcast packets limiting mode
+ UINT MaxLoggedPacketsPerMinute; // Maximum number of logging target packets per minute
+ bool DoNotSaveHeavySecurityLogs; // Do not take heavy security log
+};
+
+// MAC table entry
+struct MAC_TABLE_ENTRY
+{
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT VlanId; // VLAN ID
+ SESSION *Session; // Session
+ HUB_PA *HubPa; // HUB packet adapter
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+};
+
+// IP table entry
+struct IP_TABLE_ENTRY
+{
+ IP Ip; // IP address
+ SESSION *Session; // Session
+ bool DhcpAllocated; // Assigned by DHCP
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 UpdatedTime; // Updating date
+ UCHAR MacAddress[6]; // MAC address
+};
+
+// Loop List
+struct LOOP_LIST
+{
+ UINT NumSessions;
+ SESSION **Session;
+};
+
+// Access list
+struct ACCESS
+{
+ // IPv4
+ UINT Id; // ID
+ wchar_t Note[MAX_ACCESSLIST_NOTE_LEN + 1]; // Note
+
+ // --- Please add items to the bottom of here for enhancements ---
+ bool Active; // Enable flag
+ UINT Priority; // Priority
+ bool Discard; // Discard flag
+ UINT SrcIpAddress; // Source IP address
+ UINT SrcSubnetMask; // Source subnet mask
+ UINT DestIpAddress; // Destination IP address
+ UINT DestSubnetMask; // Destination subnet mask
+ UINT Protocol; // Protocol
+ UINT SrcPortStart; // Source port number starting point
+ UINT SrcPortEnd; // Source port number end point
+ UINT DestPortStart; // Destination port number starting point
+ UINT DestPortEnd; // Destination port number end point
+ UINT64 SrcUsernameHash; // Source user name hash
+ bool IsSrcUsernameIncludeOrExclude; // The source user name is formed as the "include:" or "exclude:"
+ char SrcUsername[MAX_USERNAME_LEN + 1];
+ bool IsDestUsernameIncludeOrExclude; // The destination user name is formed as "include:" or "exclude:"
+ UINT64 DestUsernameHash; // Destination user name hash
+ char DestUsername[MAX_USERNAME_LEN + 1];
+ bool CheckSrcMac; // Presence of a source MAC address setting
+ UCHAR SrcMacAddress[6]; // Source MAC address
+ UCHAR SrcMacMask[6]; // Source MAC address mask
+ bool CheckDstMac; // Whether the setting of the destination MAC address exists
+ UCHAR DstMacAddress[6]; // Destination MAC address
+ UCHAR DstMacMask[6]; // Destination MAC address mask
+ bool CheckTcpState; // The state of the TCP connection
+ bool Established; // Establieshed(TCP)
+ UINT Delay; // Delay
+ UINT Jitter; // Jitter
+ UINT Loss; // Packet loss
+ char RedirectUrl[MAX_REDIRECT_URL_LEN + 1]; // URL to redirect to
+
+ // IPv6
+ bool IsIPv6; // Whether it's an IPv6
+ IPV6_ADDR SrcIpAddress6; // The source IP address (IPv6)
+ IPV6_ADDR SrcSubnetMask6; // Source subnet mask (IPv6)
+ IPV6_ADDR DestIpAddress6; // Destination IP address (IPv6)
+ IPV6_ADDR DestSubnetMask6; // Destination subnet mask (IPv6)
+
+ // --- Please add items to the above of here for enhancements ---
+
+ // For management
+ UINT UniqueId; // Unique ID
+};
+
+// Ticket
+struct TICKET
+{
+ UINT64 CreatedTick; // Creation date and time
+ UCHAR Ticket[SHA1_SIZE]; // Ticket
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ char UsernameReal[MAX_USERNAME_LEN + 1]; // Real user name
+ char GroupName[MAX_USERNAME_LEN + 1]; // Group name
+ char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
+ POLICY Policy; // Policy
+};
+
+// Traffic difference
+struct TRAFFIC_DIFF
+{
+ UINT Type; // Type
+ TRAFFIC Traffic; // Traffic
+ char *HubName; // HUB name
+ char *Name; // Name
+};
+
+// Administration options
+struct ADMIN_OPTION
+{
+ char Name[MAX_ADMIN_OPTION_NAME_LEN + 1]; // Name
+ UINT Value; // Data
+};
+
+// Certificate Revocation List entry
+struct CRL
+{
+ X_SERIAL *Serial; // Serial number
+ NAME *Name; // Name information
+ UCHAR DigestMD5[MD5_SIZE]; // MD5 hash
+ UCHAR DigestSHA1[SHA1_SIZE]; // SHA-1 hash
+};
+
+// Access control
+struct AC
+{
+ UINT Id; // ID
+ UINT Priority; // Priority
+ bool Deny; // Deny access
+ bool Masked; // Is masked
+ IP IpAddress; // IP address
+ IP SubnetMask; // Subnet mask
+};
+
+// User List
+struct USERLIST
+{
+ char Filename[MAX_PATH]; // File name
+ LIST *UserHashList; // Hash list of user names
+};
+
+// HUB structure
+struct HUB
+{
+ LOCK *lock; // Lock
+ LOCK *lock_online; // Lock for Online
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ UINT Type; // Type
+ HUBDB *HubDb; // Database
+ char *Name; // The name of the HUB
+ LOCK *RadiusOptionLock; // Lock for Radius option
+ char *RadiusServerName; // Radius server name
+ UINT RadiusServerPort; // Radius server port number
+ UINT RadiusRetryInterval; // Radius retry interval
+ BUF *RadiusSecret; // Radius shared key
+ char RadiusSuffixFilter[MAX_SIZE]; // Radius suffix filter
+ volatile bool Halt; // Halting flag
+ bool Offline; // Offline
+ bool BeingOffline; // Be Doing Offline
+ LIST *SessionList; // Session list
+ COUNTER *SessionCounter; // Session number generation counter
+ TRAFFIC *Traffic; // Traffic information
+ TRAFFIC *OldTraffic; // Old traffic information
+ LOCK *TrafficLock; // Traffic lock
+ COUNTER *NumSessions; // The current number of sessions
+ COUNTER *NumSessionsClient; // The current number of sessions (client)
+ COUNTER *NumSessionsBridge; // The current number of sessions (bridge)
+ HUB_OPTION *Option; // HUB options
+ LIST *MacTable; // MAC address table
+ LIST *IpTable; // IP address table
+ LIST *MonitorList; // Monitor port session list
+ LIST *LinkList; // Linked list
+ UCHAR HubSignature[16]; // HUB signature
+ UCHAR HubMacAddr[6]; // MAC address of the HUB
+ IP HubIp; // IP address of the HUB (IPv4)
+ IPV6_ADDR HubIpV6; // IP address of the HUB (IPv6)
+ UINT HubIP6Id; // IPv6 packet ID of the HUB
+ UCHAR Padding[2]; // Padding
+ LOCK *LoopListLock; // Lock for the loop list
+ UINT NumLoopList; // Number of loop lists
+ LOOP_LIST **LoopLists; // Loop List
+ LIST *AccessList; // Access list
+ HUB_LOG LogSetting; // Log Settings
+ LOG *PacketLogger; // Packet logger
+ LOG *SecurityLogger; // Security logger
+ UCHAR HashedPassword[SHA1_SIZE]; // Password
+ UCHAR SecurePassword[SHA1_SIZE]; // Secure password
+ LIST *TicketList; // Ticket list
+ bool FarmMember; // Farm member
+ UINT64 LastIncrementTraffic; // Traffic reporting time
+ UINT64 LastSendArpTick; // ARP transmission time of the last
+ SNAT *SecureNAT; // SecureNAT
+ bool EnableSecureNAT; // SecureNAT enable / disable flag
+ VH_OPTION *SecureNATOption; // SecureNAT Option
+ THREAD *WatchDogThread; // Watchdog thread
+ EVENT *WatchDogEvent; // Watchdog event
+ bool WatchDogStarted; // Whether the watchdog thread is used
+ volatile bool HaltWatchDog; // Stop the watchdog thread
+ LIST *AdminOptionList; // Administration options list
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 LastCommTime; // Last communication date and time
+ UINT64 LastLoginTime; // Last login date and time
+ UINT NumLogin; // Number of logins
+ bool HubIsOnlineButHalting; // Virtual HUB is really online, but it is in offline state to stop
+ UINT FarmMember_MaxSessionClient; // Maximum client connection sessions for cluster members
+ UINT FarmMember_MaxSessionBridge; // Maximum bridge connection sessions for cluster members
+ bool FarmMember_MaxSessionClientBridgeApply; // Apply the FarmMember_MaxSession*
+ UINT CurrentVersion; // The current version
+ UINT LastVersion; // Version of when the update notification is issued at the last
+ wchar_t *Msg; // Message to be displayed when the client is connected
+ LIST *UserList; // Cache of the user list file
+ bool IsVgsHub; // Whether it's a VGS Virtual HUB
+};
+
+
+// Global variable
+extern ADMIN_OPTION admin_options[];
+extern UINT num_admin_options;
+
+
+// Function prototype
+HUBDB *NewHubDb();
+void DeleteHubDb(HUBDB *d);
+HUB *NewHub(CEDAR *cedar, char *HubName, HUB_OPTION *option);
+void SetHubMsg(HUB *h, wchar_t *msg);
+wchar_t *GetHubMsg(HUB *h);
+void GenHubMacAddress(UCHAR *mac, char *name);
+void GenHubIpAddress(IP *ip, char *name);
+bool IsHubIpAddress(IP *ip);
+bool IsHubIpAddress32(UINT ip32);
+bool IsHubIpAddress64(IPV6_ADDR *addr);
+bool IsHubMacAddress(UCHAR *mac);
+void ReleaseHub(HUB *h);
+void CleanupHub(HUB *h);
+int CompareHub(void *p1, void *p2);
+void LockHubList(CEDAR *cedar);
+void UnlockHubList(CEDAR *cedar);
+HUB *GetHub(CEDAR *cedar, char *name);
+bool IsHub(CEDAR *cedar, char *name);
+void StopHub(HUB *h);
+void AddSession(HUB *h, SESSION *s);
+void DelSession(HUB *h, SESSION *s);
+SESSION *SearchSessionByUniqueId(HUB *h, UINT id);
+UINT GetNewUniqueId(HUB *h);
+void StopAllSession(HUB *h);
+bool HubPaInit(SESSION *s);
+void HubPaFree(SESSION *s);
+CANCEL *HubPaGetCancel(SESSION *s);
+UINT HubPaGetNextPacket(SESSION *s, void **data);
+bool HubPaPutPacket(SESSION *s, void *data, UINT size);
+PACKET_ADAPTER *GetHubPacketAdapter();
+int CompareMacTable(void *p1, void *p2);
+void StorePacket(HUB *hub, SESSION *s, PKT *packet);
+bool StorePacketFilter(SESSION *s, PKT *packet);
+void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet);
+void SetHubOnline(HUB *h);
+void SetHubOffline(HUB *h);
+SESSION *GetSessionByPtr(HUB *hub, void *ptr);
+SESSION *GetSessionByName(HUB *hub, char *name);
+int CompareIpTable(void *p1, void *p2);
+bool StorePacketFilterByPolicy(SESSION *s, PKT *p);
+bool DeleteIPv6DefaultRouterInRA(PKT *p);
+bool StorePacketFilterByTrafficLimiter(SESSION *s, PKT *p);
+void IntoTrafficLimiter(TRAFFIC_LIMITER *tr, PKT *p);
+bool IsMostHighestPriorityPacket(SESSION *s, PKT *p);
+bool IsPriorityPacketForQoS(PKT *p);
+int CompareStormList(void *p1, void *p2);
+STORM *SearchStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip, bool strict);
+STORM *AddStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip, bool strict);
+bool CheckBroadcastStorm(HUB *hub, SESSION *s, PKT *p);
+void AddRootCert(HUB *hub, X *x);
+int CmpAccessList(void *p1, void *p2);
+void InitAccessList(HUB *hub);
+void FreeAccessList(HUB *hub);
+void AddAccessList(HUB *hub, ACCESS *a);
+void AddAccessListEx(HUB *hub, ACCESS *a, bool no_sort, bool no_reassign_id);
+bool SetSessionFirstRedirectHttpUrl(SESSION *s, char *url);
+bool IsTcpPacketNcsiHttpAccess(PKT *p);
+UINT64 UsernameToInt64(char *name);
+void MakeSimpleUsernameRemoveNtDomain(char *dst, UINT dst_size, char *src);
+bool ApplyAccessListToStoredPacket(HUB *hub, SESSION *s, PKT *p);
+void ForceRedirectToUrl(HUB *hub, SESSION *src_session, PKT *p, char *redirect_url);
+BUF *BuildRedirectToUrlPayload(HUB *hub, SESSION *s, char *redirect_url);
+bool ApplyAccessListToForwardPacket(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *p);
+bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT64 dest_username, UINT64 dest_groupname, SESSION *dest_session);
+void GetAccessListStr(char *str, UINT size, ACCESS *a);
+void DeleteOldIpTableEntry(LIST *o);
+void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret);
+void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval);
+bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size);
+bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval);
+bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, char *suffix_filter, UINT suffix_filter_size);
+int CompareCert(void *p1, void *p2);
+void GetHubLogSetting(HUB *h, HUB_LOG *setting);
+void SetHubLogSetting(HUB *h, HUB_LOG *setting);
+void SetHubLogSettingEx(HUB *h, HUB_LOG *setting, bool no_change_switch_type);
+void DeleteExpiredIpTableEntry(LIST *o);
+void DeleteExpiredMacTableEntry(LIST *o);
+void AddTrafficDiff(HUB *h, char *name, UINT type, TRAFFIC *traffic);
+void IncrementHubTraffic(HUB *h);
+void EnableSecureNAT(HUB *h, bool enable);
+void EnableSecureNATEx(HUB *h, bool enable, bool no_change);
+void StartHubWatchDog(HUB *h);
+void StopHubWatchDog(HUB *h);
+void HubWatchDogThread(THREAD *t, void *param);
+int CompareAdminOption(void *p1, void *p2);
+UINT GetHubAdminOptionEx(HUB *h, char *name, UINT default_value);
+UINT GetHubAdminOption(HUB *h, char *name);
+void DeleteAllHubAdminOption(HUB *h, bool lock);
+void AddHubAdminOptionsDefaults(HUB *h, bool lock);
+bool IsCertMatchCrl(X *x, CRL *crl);
+bool IsCertMatchCrlList(X *x, LIST *o);
+wchar_t *GenerateCrlStr(CRL *crl);
+bool IsValidCertInHub(HUB *h, X *x);
+void FreeCrl(CRL *crl);
+CRL *CopyCrl(CRL *crl);
+int CmpAc(void *p1, void *p2);
+LIST *NewAcList();
+void AddAc(LIST *o, AC *ac);
+bool DelAc(LIST *o, UINT id);
+AC *GetAc(LIST *o, UINT id);
+void SetAc(LIST *o, UINT id, AC *ac);
+void DelAllAc(LIST *o);
+void SetAcList(LIST *o, LIST *src);
+void NormalizeAcList(LIST *o);
+bool IsIpMaskedByAc(IP *ip, AC *ac);
+bool IsIpDeniedByAcList(IP *ip, LIST *o);
+char *GenerateAcStr(AC *ac);
+void FreeAcList(LIST *o);
+LIST *CloneAcList(LIST *o);
+bool IsIPManagementTargetForHUB(IP *ip, HUB *hub);
+wchar_t *GetHubAdminOptionHelpString(char *name);
+void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name);
+ADMIN_OPTION *NewAdminOption(char *name, UINT value);
+void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao);
+UINT GetHubAdminOptionData(RPC_ADMIN_OPTION *ao, char *name);
+void GetHubAdminOptionDataAndSet(RPC_ADMIN_OPTION *ao, char *name, UINT *dest);
+bool IsURLMsg(wchar_t *str, char *url, UINT url_size);
+LIST *NewUserList();
+void DeleteAllUserListCache(LIST *o);
+void FreeUserList(LIST *o);
+void FreeUserListEntry(USERLIST *u);
+int CompareUserList(void *p1, void *p2);
+USERLIST *LoadUserList(LIST *o, char *filename);
+USERLIST *FindUserList(LIST *o, char *filename);
+bool IsUserMatchInUserList(LIST *o, char *filename, UINT64 user_hash);
+bool IsUserMatchInUserListWithCacheExpires(LIST *o, char *filename, UINT64 user_hash, UINT64 lifetime);
+bool IsUserMatchInUserListWithCacheExpiresAcl(LIST *o, char *name_in_acl, UINT64 user_hash, UINT64 lifetime);
+void CalcTrafficEntryDiff(TRAFFIC_ENTRY *diff, TRAFFIC_ENTRY *old, TRAFFIC_ENTRY *current);
+void CalcTrafficDiff(TRAFFIC *diff, TRAFFIC *old, TRAFFIC *current);
+bool CheckMaxLoggedPacketsPerMinute(SESSION *s, UINT max_packets, UINT64 now);
+void VgsSetUserAgentValue(char *str);
+void VgsSetEmbTag(bool b);
+
+#endif // HUB_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec.c b/src/Cedar/IPsec.c
new file mode 100644
index 00000000..7288e0b5
--- /dev/null
+++ b/src/Cedar/IPsec.c
@@ -0,0 +1,767 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec.c
+// IPsec module
+
+#include "CedarPch.h"
+
+
+static bool ipsec_disable = false;
+
+// Disabling whole IPsec
+void IPSecSetDisable(bool b)
+{
+ ipsec_disable = b;
+}
+
+
+// Monitor the IPsec service of the OS, and stop it if it will conflict
+void IPsecOsServiceCheckThread(THREAD *t, void *p)
+{
+ UINT interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
+ IPSEC_SERVER *s = (IPSEC_SERVER *)p;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ s->HostIPAddressListChanged = true;
+ s->OsServiceStoped = false;
+
+ while (s->Halt == false)
+ {
+ if (IPsecCheckOsService(s))
+ {
+ interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
+ }
+
+ if (Wait(s->OsServiceCheckThreadEvent, interval) == false)
+ {
+ interval = MIN(interval * 2, IPSEC_CHECK_OS_SERVICE_INTERVAL_MAX);
+ }
+ else
+ {
+ interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
+ }
+ }
+
+ IPsecCheckOsService(s);
+}
+
+// Monitoring process main
+bool IPsecCheckOsService(IPSEC_SERVER *s)
+{
+ bool b_ipsec;
+ IPSEC_SERVICES sl;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ IPsecServerGetServices(s, &sl);
+
+ b_ipsec = (sl.EtherIP_IPsec || sl.L2TP_IPsec);
+
+ if (b_ipsec != s->Check_LastEnabledStatus)
+ {
+ s->Check_LastEnabledStatus = b_ipsec;
+
+ if (b_ipsec)
+ {
+ // Use of IPsec has been started
+#ifdef OS_WIN32
+ if (s->Win7 == NULL)
+ {
+ s->Win7 = IPsecWin7Init();
+ s->HostIPAddressListChanged = true;
+ }
+
+ s->OsServiceStoped = false;
+#else // OS_WIN32
+#endif // OS_WIN32
+ }
+ else
+ {
+ // Use of IPsec is stopped
+#ifdef OS_WIN32
+ if (s->Win7 != NULL)
+ {
+ IPsecWin7Free(s->Win7);
+ s->Win7 = NULL;
+ }
+
+ if (s->OsServiceStoped)
+ {
+ MsStartIPsecService();
+ s->OsServiceStoped = false;
+ }
+#else // OS_WIN32
+ UnixSetEnableKernelEspProcessing(true);
+#endif // OS_WIN32
+ }
+ }
+
+ if (b_ipsec)
+ {
+#ifdef OS_WIN32
+ if (MsStopIPsecService())
+ {
+ s->OsServiceStoped = true;
+ ret = true;
+ }
+#else // OS_WIN32
+ UnixSetEnableKernelEspProcessing(false);
+#endif // OS_WIN32
+ }
+
+#ifdef OS_WIN32
+ if (s->Win7 != NULL)
+ {
+ IPsecWin7UpdateHostIPAddressList(s->Win7);
+ s->HostIPAddressListChanged = false;
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Processing of UDP packets (one by one)
+void IPsecProcPacket(IPSEC_SERVER *s, UDPPACKET *p)
+{
+ L2TP_SERVER *l2tp;
+ IKE_SERVER *ike;
+ void *old_data_ptr;
+ UINT old_data_size;
+ bool proc_this_packet = true;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ old_data_ptr = p->Data;
+ old_data_size = p->Size;
+
+ l2tp = s->L2TP;
+ ike = s->Ike;
+
+ // UDP decapsulation process
+ if (p->DestPort == IPSEC_PORT_IPSEC_ESP_UDP)
+ {
+#ifdef OS_WIN32
+ if (p->Size >= 12 && IsZero(p->Data, 4))
+ {
+ if (((*((UINT *)(((UCHAR *)p->Data) + sizeof(UINT) * 1))) == WFP_ESP_PACKET_TAG_1) &&
+ ((*((UINT *)(((UCHAR *)p->Data) + sizeof(UINT) * 2))) == WFP_ESP_PACKET_TAG_2))
+ {
+ // Truncate the head because the packet was modified by WFP
+ p->Data = ((UCHAR *)p->Data) + 12;
+ p->Size -= 12;
+ }
+ }
+#endif // OS_WIN32
+
+ if (p->Size >= 4 && IsZero(p->Data, 4))
+ {
+ // Truncate the Non-ESP Marker
+ p->Data = ((UCHAR *)p->Data) + 4;
+ p->Size -= 4;
+
+ p->Type = IKE_UDP_TYPE_ISAKMP;
+ }
+ else
+ {
+ p->Type = IKE_UDP_TYPE_ESP;
+ }
+ }
+ else if (p->DestPort == IPSEC_PORT_IPSEC_ISAKMP)
+ {
+ if (p->Size >= 8 && IsZero(p->Data, 8))
+ {
+ // Truncate the Non-IKE Maker
+ p->Data = ((UCHAR *)p->Data) + 8;
+ p->Size -= 8;
+
+ p->Type = IKE_UDP_TYPE_ESP;
+ }
+ else
+ {
+ p->Type = IKE_UDP_TYPE_ISAKMP;
+ }
+ }
+ else if (p->DestPort == IPSEC_PORT_IPSEC_ESP_RAW)
+ {
+ // Raw ESP
+ p->Type = IKE_UDP_TYPE_ESP;
+ }
+
+
+ if (proc_this_packet)
+ {
+ switch (p->DestPort)
+ {
+ case IPSEC_PORT_L2TP:
+ // L2TP
+ ProcL2TPPacketRecv(l2tp, p);
+ break;
+
+ case IPSEC_PORT_IPSEC_ISAKMP:
+ case IPSEC_PORT_IPSEC_ESP_UDP:
+ case IPSEC_PORT_IPSEC_ESP_RAW:
+ // IPsec
+ ProcIKEPacketRecv(ike, p);
+ break;
+ }
+ }
+
+ p->Data = old_data_ptr;
+ p->Size = old_data_size;
+}
+
+// Packet reception procedure of UDP listener
+void IPsecServerUdpPacketRecvProc(UDPLISTENER *u, LIST *packet_list)
+{
+ UINT i;
+ IPSEC_SERVER *s;
+ L2TP_SERVER *l2tp;
+ IKE_SERVER *ike;
+ UINT64 now;
+ static UCHAR zero8[8] = {0, 0, 0, 0, 0, 0, 0, 0, };
+ // Validate arguments
+ if (u == NULL || packet_list == NULL)
+ {
+ return;
+ }
+ s = (IPSEC_SERVER *)u->Param;
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (u->HostIPAddressListChanged)
+ {
+ u->HostIPAddressListChanged = false;
+
+ s->HostIPAddressListChanged = true;
+
+ Set(s->OsServiceCheckThreadEvent);
+ }
+
+ now = Tick64();
+
+ // Adjustment about L2TP server timing
+ l2tp = s->L2TP;
+
+ if (l2tp->Interrupts == NULL)
+ {
+ l2tp->Interrupts = u->Interrupts;
+ }
+
+ if (l2tp->SockEvent == NULL)
+ {
+ SetL2TPServerSockEvent(l2tp, u->Event);
+ }
+
+ l2tp->Now = now;
+
+ // Adjustment about IKE server timing
+ ike = s->Ike;
+
+ if (ike->Interrupts == NULL)
+ {
+ ike->Interrupts = u->Interrupts;
+ }
+
+ if (ike->SockEvent == NULL)
+ {
+ SetIKEServerSockEvent(ike, u->Event);
+ }
+
+ ike->Now = now;
+
+ if (ipsec_disable == false)
+ {
+ // Process the received packet
+ for (i = 0;i < LIST_NUM(packet_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(packet_list, i);
+
+ IPsecProcPacket(s, p);
+ }
+ }
+
+ // Interrupt processing of L2TP server
+ L2TPProcessInterrupts(l2tp);
+
+ // L2TP packet transmission processing
+ UdpListenerSendPackets(u, l2tp->SendPacketList);
+ DeleteAll(l2tp->SendPacketList);
+
+ // Interrupt processing of IKE server
+ ProcessIKEInterrupts(ike);
+
+ // UDP encapsulation process of IKE server packet scheduled for transmission
+ for (i = 0;i < LIST_NUM(ike->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(ike->SendPacketList, i);
+
+ if (p->Type == IKE_UDP_TYPE_ISAKMP && p->SrcPort == IPSEC_PORT_IPSEC_ESP_UDP)
+ {
+ // Add the Non-ESP Marker
+ void *old_data = p->Data;
+
+ p->Data = AddHead(p->Data, p->Size, zero8, 4);
+ p->Size += 4;
+
+ Free(old_data);
+ }
+ else if (p->Type == IKE_UDP_TYPE_ESP && p->SrcPort == IPSEC_PORT_IPSEC_ISAKMP)
+ {
+ // Add the Non-IKE Marker
+ void *old_data = p->Data;
+
+ p->Data = AddHead(p->Data, p->Size, zero8, 8);
+ p->Size += 8;
+
+ Free(old_data);
+ }
+ }
+
+ // IKE server packet transmission processing
+ UdpListenerSendPackets(u, ike->SendPacketList);
+ DeleteAll(ike->SendPacketList);
+}
+
+// Get the service list
+void IPsecServerGetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl)
+{
+ // Validate arguments
+ if (s == NULL || sl == NULL)
+ {
+ return;
+ }
+
+ Lock(s->LockSettings);
+ {
+ IPsecNormalizeServiceSetting(s);
+
+ Copy(sl, &s->Services, sizeof(IPSEC_SERVICES));
+ }
+ Unlock(s->LockSettings);
+}
+
+// Normalize the IPsec service setttings
+void IPsecNormalizeServiceSetting(IPSEC_SERVER *s)
+{
+ CEDAR *c;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ c = s->Cedar;
+
+ Lock(s->LockSettings);
+ {
+ bool reset_hub_setting = false;
+
+ if (IsEmptyStr(s->Services.IPsec_Secret))
+ {
+ // If the secret is not set, set the default one
+ StrCpy(s->Services.IPsec_Secret, sizeof(s->Services.IPsec_Secret), IPSEC_DEFAULT_SECRET);
+ }
+
+ LockList(c->HubList);
+ {
+ if (IsEmptyStr(s->Services.L2TP_DefaultHub))
+ {
+ reset_hub_setting = true;
+ }
+ else
+ {
+ if (IsHub(c, s->Services.L2TP_DefaultHub) == false)
+ {
+ reset_hub_setting = true;
+ }
+ }
+
+ if (reset_hub_setting)
+ {
+ // Select the first Virtual HUB if there is no HUB
+ HUB *h = NULL;
+
+ if (LIST_NUM(c->HubList) >= 1)
+ {
+ h = LIST_DATA(c->HubList, 0);
+ }
+
+ if (h != NULL)
+ {
+ StrCpy(s->Services.L2TP_DefaultHub, sizeof(s->Services.L2TP_DefaultHub), h->Name);
+ }
+ else
+ {
+ StrCpy(s->Services.L2TP_DefaultHub, sizeof(s->Services.L2TP_DefaultHub), "");
+ }
+ }
+ }
+ UnlockList(c->HubList);
+ }
+ Unlock(s->LockSettings);
+}
+
+// Set the service list
+void IPsecServerSetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl)
+{
+ // Validate arguments
+ if (s == NULL || sl == NULL)
+ {
+ return;
+ }
+
+ if (IsZero(sl, sizeof(IPSEC_SERVICES)) == false)
+ {
+ if (s->NoMoreChangeSettings)
+ {
+ return;
+ }
+ }
+
+ Lock(s->LockSettings);
+ {
+ Copy(&s->Services, sl, sizeof(IPSEC_SERVICES));
+
+ if (sl->L2TP_Raw)
+ {
+ AddPortToUdpListener(s->UdpListener, IPSEC_PORT_L2TP);
+ }
+ else
+ {
+ DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_L2TP);
+ }
+
+ if (sl->L2TP_IPsec || sl->EtherIP_IPsec)
+ {
+ AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ISAKMP);
+ AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_UDP);
+ AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW);
+ AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW_WPF);
+ }
+ else
+ {
+ DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ISAKMP);
+ DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_UDP);
+ DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW);
+ DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW_WPF);
+ }
+
+ if (IsEmptyStr(sl->IPsec_Secret) == false)
+ {
+ StrCpy(s->Ike->Secret, sizeof(s->Ike->Secret), sl->IPsec_Secret);
+ }
+
+ IPsecNormalizeServiceSetting(s);
+ }
+ Unlock(s->LockSettings);
+
+ Set(s->OsServiceCheckThreadEvent);
+}
+
+// Add the EtherIP key
+void AddEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id)
+{
+ // Validate arguments
+ if (s == NULL || id == NULL)
+ {
+ return;
+ }
+
+ Lock(s->LockSettings);
+ {
+ // If there is the same key, remove them
+ ETHERIP_ID t, *k;
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Id, sizeof(t.Id), id->Id);
+
+ k = Search(s->EtherIPIdList, &t);
+
+ if (k != NULL)
+ {
+ Delete(s->EtherIPIdList, k);
+
+ Free(k);
+ }
+
+ // Add
+ k = Clone(id, sizeof(ETHERIP_ID));
+
+ Insert(s->EtherIPIdList, k);
+
+ s->EtherIPIdListSettingVerNo++;
+ }
+ Unlock(s->LockSettings);
+}
+
+// Delete the EtherIP key
+bool DeleteEtherIPId(IPSEC_SERVER *s, char *id_str)
+{
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || id_str == NULL)
+ {
+ return false;
+ }
+
+ Lock(s->LockSettings);
+ {
+ // If there is the same key, remove them
+ ETHERIP_ID t, *k;
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Id, sizeof(t.Id), id_str);
+
+ k = Search(s->EtherIPIdList, &t);
+
+ if (k != NULL)
+ {
+ Delete(s->EtherIPIdList, k);
+
+ Free(k);
+
+ ret = true;
+
+ s->EtherIPIdListSettingVerNo++;
+ }
+ }
+ Unlock(s->LockSettings);
+
+ return ret;
+}
+
+// Search the EtherIP key
+bool SearchEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id, char *id_str)
+{
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || id == NULL || id_str == NULL)
+ {
+ return false;
+ }
+
+ Lock(s->LockSettings);
+ {
+ ETHERIP_ID t, *k;
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.Id, sizeof(t.Id), id_str);
+
+ k = Search(s->EtherIPIdList, &t);
+
+ if (k != NULL)
+ {
+ Copy(id, k, sizeof(ETHERIP_ID));
+
+ ret = true;
+ }
+ }
+ Unlock(s->LockSettings);
+
+ return ret;
+}
+
+// Comparison of key EtherIP list entries
+int CmpEtherIPId(void *p1, void *p2)
+{
+ ETHERIP_ID *k1, *k2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ k1 = *(ETHERIP_ID **)p1;
+ k2 = *(ETHERIP_ID **)p2;
+ if (k1 == NULL || k2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(k1->Id, k2->Id);
+}
+
+// Release and stop the IPsec server
+void FreeIPsecServer(IPSEC_SERVER *s)
+{
+ UINT i;
+ IPSEC_SERVICES sl;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->NoMoreChangeSettings = true;
+
+ // Stopp the L2TP server
+ StopL2TPServer(s->L2TP, false);
+
+ // Stop the IKE server
+ StopIKEServer(s->Ike);
+
+ // Stop all the services explicitly
+ Zero(&sl, sizeof(sl));
+ IPsecServerSetServices(s, &sl);
+
+ // Releasing process
+ FreeUdpListener(s->UdpListener);
+
+ ReleaseCedar(s->Cedar);
+
+ FreeL2TPServer(s->L2TP);
+
+ FreeIKEServer(s->Ike);
+
+ for (i = 0;i < LIST_NUM(s->EtherIPIdList);i++)
+ {
+ ETHERIP_ID *k = LIST_DATA(s->EtherIPIdList, i);
+
+ Free(k);
+ }
+
+ ReleaseList(s->EtherIPIdList);
+
+ // Stop the OS monitoring thread
+ s->Halt = true;
+ Set(s->OsServiceCheckThreadEvent);
+ WaitThread(s->OsServiceCheckThread, INFINITE);
+ ReleaseThread(s->OsServiceCheckThread);
+ ReleaseEvent(s->OsServiceCheckThreadEvent);
+
+ DeleteLock(s->LockSettings);
+
+ Free(s);
+}
+
+// Initialize the IPsec server
+IPSEC_SERVER *NewIPsecServer(CEDAR *cedar)
+{
+ IPSEC_SERVER *s;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(IPSEC_SERVER));
+
+ s->LockSettings = NewLock();
+
+ s->Cedar = cedar;
+
+ AddRef(s->Cedar->ref);
+
+ s->L2TP = NewL2TPServer(cedar);
+
+ s->Ike = NewIKEServer(cedar, s);
+ StrCpy(s->Ike->Secret, sizeof(s->Ike->Secret), IPSEC_DEFAULT_SECRET);
+
+ s->UdpListener = NewUdpListener(IPsecServerUdpPacketRecvProc, s);
+
+ s->EtherIPIdList = NewList(CmpEtherIPId);
+
+ // Start an OS service monitoring thread
+ s->OsServiceCheckThreadEvent = NewEvent();
+ s->OsServiceCheckThread = NewThread(IPsecOsServiceCheckThread, s);
+
+ return s;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec.h b/src/Cedar/IPsec.h
new file mode 100644
index 00000000..48b297c8
--- /dev/null
+++ b/src/Cedar/IPsec.h
@@ -0,0 +1,179 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec.h
+// Header of IPsec.c
+
+#ifndef IPSEC_H
+#define IPSEC_H
+
+//// Constants
+
+// UDP port number
+#define IPSEC_PORT_L2TP 1701 // L2TP
+#define IPSEC_PORT_IPSEC_ISAKMP 500 // ISAKMP
+#define IPSEC_PORT_IPSEC_ESP_UDP 4500 // IPsec ESP over UDP
+#define IPSEC_PORT_IPSEC_ESP_RAW MAKE_SPECIAL_PORT(50) // Raw mode ESP Protocol No: 50
+#define IPSEC_PORT_IPSEC_ESP_RAW_WPF MAKE_SPECIAL_PORT(52) // Raw mode ESP Protocol No: 52 (WPF)
+#define IPSEC_PORT_L2TPV3_VIRTUAL 1000001 // L2TPv3 virtual port
+
+// IP protocol number
+#define IPSEC_IP_PROTO_ETHERIP IP_PROTO_ETHERIP // EtherIP
+#define IPSEC_IP_PROTO_L2TPV3 IP_PROTO_L2TPV3 // L2TPv3
+
+// WFP tag
+#define WFP_ESP_PACKET_TAG_1 0x19841117
+#define WFP_ESP_PACKET_TAG_2 0x1accafe1
+
+// Monitoring interval of OS service
+#define IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL 1024
+#define IPSEC_CHECK_OS_SERVICE_INTERVAL_MAX (5 * 60 * 1000)
+
+// Default IPsec pre-shared key
+#define IPSEC_DEFAULT_SECRET "vpn"
+
+
+//// Type
+
+// List of services provided by IPsec server
+struct IPSEC_SERVICES
+{
+ bool L2TP_Raw; // Raw L2TP
+ bool L2TP_IPsec; // L2TP over IPsec
+ bool EtherIP_IPsec; // EtherIP over IPsec
+
+ char IPsec_Secret[MAX_SIZE]; // IPsec pre-shared key
+ char L2TP_DefaultHub[MAX_SIZE]; // Default Virtual HUB name for L2TP connection
+};
+
+// EtherIP key list entry
+struct ETHERIP_ID
+{
+ char Id[MAX_SIZE]; // ID
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ char UserName[MAX_USERNAME_LEN + 1]; // User name
+ char Password[MAX_USERNAME_LEN + 1]; // Password
+};
+
+// IPsec server
+struct IPSEC_SERVER
+{
+ CEDAR *Cedar;
+ UDPLISTENER *UdpListener;
+ bool Halt;
+ bool NoMoreChangeSettings;
+ LOCK *LockSettings;
+ IPSEC_SERVICES Services;
+ L2TP_SERVER *L2TP; // L2TP server
+ IKE_SERVER *Ike; // IKE server
+ LIST *EtherIPIdList; // EtherIP setting list
+ UINT EtherIPIdListSettingVerNo; // EtherIP setting list version number
+ THREAD *OsServiceCheckThread; // OS Service monitoring thread
+ EVENT *OsServiceCheckThreadEvent; // Event for OS Service monitoring thread
+ IPSEC_WIN7 *Win7; // Helper module for Windows Vista / 7
+ bool Check_LastEnabledStatus;
+ bool HostIPAddressListChanged;
+ bool OsServiceStoped;
+};
+
+
+//// Function prototype
+IPSEC_SERVER *NewIPsecServer(CEDAR *cedar);
+void FreeIPsecServer(IPSEC_SERVER *s);
+void IPsecServerUdpPacketRecvProc(UDPLISTENER *u, LIST *packet_list);
+void IPsecServerSetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl);
+void IPsecNormalizeServiceSetting(IPSEC_SERVER *s);
+void IPsecServerGetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl);
+void IPsecProcPacket(IPSEC_SERVER *s, UDPPACKET *p);
+int CmpEtherIPId(void *p1, void *p2);
+bool SearchEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id, char *id_str);
+void AddEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id);
+bool DeleteEtherIPId(IPSEC_SERVER *s, char *id_str);
+void IPsecOsServiceCheckThread(THREAD *t, void *p);
+bool IPsecCheckOsService(IPSEC_SERVER *s);
+void IPSecSetDisable(bool b);
+
+
+#endif // IPSEC_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_EtherIP.c b/src/Cedar/IPsec_EtherIP.c
new file mode 100644
index 00000000..632df40b
--- /dev/null
+++ b/src/Cedar/IPsec_EtherIP.c
@@ -0,0 +1,539 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_EtherIP.c
+// EtherIP protocol stack
+
+#include "CedarPch.h"
+
+// IPC connection processing thread
+void EtherIPIpcConnectThread(THREAD *t, void *p)
+{
+ ETHERIP_SERVER *s;
+ IPC *ipc = NULL;
+ UINT error_code = 0;
+ char tmp[MAX_SIZE];
+ ETHERIP_ID id;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ s = (ETHERIP_SERVER *)p;
+
+ GetHostName(tmp, sizeof(tmp), &s->ClientIP);
+
+ // Get the setting of the virtual HUB to be connected based on the client ID presented
+ if (SearchEtherIPId(s->Ike->IPsec, &id, s->ClientId) == false &&
+ SearchEtherIPId(s->Ike->IPsec, &id, "*") == false)
+ {
+ // Failed to get the settings for the virtual HUB
+ Debug("Not Found: EtherIP Settings for Client ID \"%s\".\n", s->ClientId);
+
+ EtherIPLog(s, "LE_NO_SETTING", s->ClientId);
+ }
+ else
+ {
+ UINT mss = CalcEtherIPTcpMss(s);
+ char client_name[MAX_SIZE];
+
+ if (s->L2TPv3 == false)
+ {
+ StrCpy(client_name, sizeof(client_name), ETHERIP_CLIENT_NAME);
+ }
+ else
+ {
+ if (IsEmptyStr(s->VendorName))
+ {
+ StrCpy(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME);
+ }
+ else
+ {
+ Format(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME_EX, s->VendorName);
+ }
+ }
+
+ // Execution of IPC connection process
+ EtherIPLog(s, "LE_START_IPC", id.HubName, id.UserName, mss);
+ ipc = NewIPC(s->Cedar, client_name,
+ (s->L2TPv3 ? ETHERIP_L2TPV3_POSTFIX : ETHERIP_POSTFIX),
+ id.HubName, id.UserName, id.Password,
+ &error_code,
+ &s->ClientIP, s->ClientPort,
+ &s->ServerIP, s->ServerPort,
+ tmp,
+ s->CryptName, true, mss);
+
+ if (ipc != NULL)
+ {
+ Copy(&s->CurrentEtherIPIdSetting, &id, sizeof(ETHERIP_ID));
+ EtherIPLog(s, "LE_IPC_CONNECT_OK", id.HubName);
+ }
+ else
+ {
+ EtherIPLog(s, "LE_IPC_CONNECT_ERROR", id.HubName, error_code, _E(error_code));
+ }
+ }
+
+ Lock(s->Lock);
+ {
+ // Set the results
+ ReleaseThread(s->IpcConnectThread);
+ s->IpcConnectThread = NULL;
+
+ s->Ipc = ipc;
+
+ s->LastConnectFailedTick = Tick64();
+ }
+ Unlock(s->Lock);
+
+ // Hit the event to cause interrupt
+ SetSockEvent(s->SockEvent);
+
+ // Release the EtherIP object that is hold by this thread
+ ReleaseEtherIPServer(s);
+}
+
+// Processing of the interrupt
+void EtherIPProcInterrupts(ETHERIP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // If EtherIP settings have been changed, and the change may effect to this connection, disconnect
+ if (s->Ipc != NULL)
+ {
+ if (s->Ike->IPsec->EtherIPIdListSettingVerNo != s->LastEtherIPSettingVerNo)
+ {
+ ETHERIP_ID id;
+ bool ok = true;
+
+ s->LastEtherIPSettingVerNo = s->Ike->IPsec->EtherIPIdListSettingVerNo;
+
+ if (SearchEtherIPId(s->IPsec, &id, s->ClientId) == false &&
+ SearchEtherIPId(s->IPsec, &id, "*") == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ if (StrCmpi(s->CurrentEtherIPIdSetting.HubName, id.HubName) != 0 ||
+ StrCmpi(s->CurrentEtherIPIdSetting.UserName, id.UserName) != 0 ||
+ StrCmp(s->CurrentEtherIPIdSetting.Password, id.Password) != 0)
+ {
+ ok = false;
+ }
+ }
+
+ if (ok == false)
+ {
+ // Disconnect immediately since setting of EtherIP seems to have been changed
+ FreeIPC(s->Ipc);
+ s->Ipc = NULL;
+
+ EtherIPLog(s, "LE_RECONNECT");
+ }
+ }
+ }
+
+ // Connect if IPC connection is not completed
+ Lock(s->Lock);
+ {
+ if (s->Ipc == NULL)
+ {
+ if (s->IpcConnectThread == NULL)
+ {
+ if ((s->LastConnectFailedTick == 0) || ((s->LastConnectFailedTick + (UINT64)ETHERIP_VPN_CONNECT_RETRY_INTERVAL) <= s->Now))
+ {
+ Lock(s->IPsec->LockSettings);
+ {
+ Copy(&s->CurrentIPSecServiceSetting, &s->IPsec->Services, sizeof(IPSEC_SERVICES));
+ }
+ Unlock(s->IPsec->LockSettings);
+
+ s->IpcConnectThread = NewThread(EtherIPIpcConnectThread, s);
+ AddThreadToThreadList(s->Ike->ThreadList, s->IpcConnectThread);
+ AddRef(s->Ref);
+ }
+ }
+ }
+ }
+ Unlock(s->Lock);
+
+ if (s->Ipc != NULL)
+ {
+ // Set to get hit the SockEvent when a packet arrives via the IPC
+ IPCSetSockEventWhenRecvL2Packet(s->Ipc, s->SockEvent);
+
+ // IPC interrupt processing
+ IPCProcessInterrupts(s->Ipc);
+
+ // Receive the MAC frame which arrived via the IPC
+ while (true)
+ {
+ BLOCK *b = IPCRecvL2(s->Ipc);
+ UCHAR *dst;
+ UINT dst_size;
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ if (b->Size >= 14)
+ {
+ BLOCK *block;
+
+ // Store the arrived MAC frame by adding an EtherIP header to the reception packet queue
+
+ if (s->L2TPv3 == false)
+ {
+ dst_size = b->Size + 2;
+ dst = Malloc(dst_size);
+
+ dst[0] = 0x30;
+ dst[1] = 0x00;
+
+ Copy(dst + 2, b->Buf, b->Size);
+ }
+ else
+ {
+ dst = Clone(b->Buf, b->Size);
+ dst_size = b->Size;
+ }
+
+ block = NewBlock(dst, dst_size, 0);
+
+ Add(s->SendPacketList, block);
+ }
+
+ FreeBlock(b);
+ }
+
+ if (IsIPCConnected(s->Ipc) == false)
+ {
+ // IPC connection is disconnected
+ FreeIPC(s->Ipc);
+ s->Ipc = NULL;
+ }
+ }
+}
+
+// Process the received packet
+void EtherIPProcRecvPackets(ETHERIP_SERVER *s, BLOCK *b)
+{
+ UCHAR *src;
+ UINT src_size;
+ // Validate arguments
+ if (s == NULL || b == NULL)
+ {
+ return;
+ }
+
+ if (s->Ipc == NULL)
+ {
+ // Not connected to the Virtual HUB
+ return;
+ }
+
+ src = b->Buf;
+ src_size = b->Size;
+
+ if (s->L2TPv3 == false)
+ {
+ // EtherIP header confirmation
+ if (src_size < 2)
+ {
+ return;
+ }
+
+ if ((src[0] & 0xf0) != 0x30)
+ {
+ return;
+ }
+
+ src += 2;
+ src_size -= 2;
+ }
+
+ if (src_size < 14)
+ {
+ // The size of the MAC frame is less than 14 bytes
+ return;
+ }
+
+ // Send by IPC since a MAC frame has been received
+ IPCSendL2(s->Ipc, src, src_size);
+}
+
+// Create a new EtherIP server
+ETHERIP_SERVER *NewEtherIPServer(CEDAR *cedar, IPSEC_SERVER *ipsec, IKE_SERVER *ike,
+ IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *crypt_name,
+ bool is_tunnel_mode, UINT crypt_block_size,
+ char *client_id, UINT id)
+{
+ ETHERIP_SERVER *s;
+ // Validate arguments
+ if (cedar == NULL || ipsec == NULL || ike == NULL || client_ip == NULL || server_ip == NULL || client_id == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(ETHERIP_SERVER));
+
+ s->Ref = NewRef();
+
+ s->Id = id;
+
+ s->Cedar = cedar;
+ AddRef(s->Cedar->ref);
+ s->IPsec = ipsec;
+ s->Ike = ike;
+ s->IsTunnelMode = is_tunnel_mode;
+
+ StrCpy(s->ClientId, sizeof(s->ClientId), client_id);
+
+ s->SendPacketList = NewList(NULL);
+
+ s->Now = Tick64();
+
+ s->Lock = NewLock();
+
+ Copy(&s->ClientIP, client_ip, sizeof(IP));
+ s->ClientPort = client_port;
+
+ Copy(&s->ServerIP, server_ip, sizeof(IP));
+ s->ServerPort = server_port;
+
+ StrCpy(s->CryptName, sizeof(s->CryptName), crypt_name);
+ s->CryptBlockSize = crypt_block_size;
+
+ EtherIPLog(s, "LE_START_MODULE");
+
+ return s;
+}
+
+// Release the EtherIP server
+void ReleaseEtherIPServer(ETHERIP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->Ref) == 0)
+ {
+ CleanupEtherIPServer(s);
+ }
+}
+void CleanupEtherIPServer(ETHERIP_SERVER *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ EtherIPLog(s, "LE_STOP");
+
+ if (s->IpcConnectThread != NULL)
+ {
+ ReleaseThread(s->IpcConnectThread);
+ }
+
+ if (s->Ipc != NULL)
+ {
+ FreeIPC(s->Ipc);
+ }
+
+ for (i = 0;i < LIST_NUM(s->SendPacketList);i++)
+ {
+ BLOCK *b = LIST_DATA(s->SendPacketList, i);
+
+ FreeBlock(b);
+ }
+
+ ReleaseList(s->SendPacketList);
+
+ ReleaseSockEvent(s->SockEvent);
+
+ ReleaseCedar(s->Cedar);
+
+ DeleteLock(s->Lock);
+
+ Free(s);
+}
+
+
+// Set SockEvent to EtherIP server
+void SetEtherIPServerSockEvent(ETHERIP_SERVER *s, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ if (s->SockEvent != NULL)
+ {
+ ReleaseSockEvent(s->SockEvent);
+ s->SockEvent = NULL;
+ }
+
+ s->SockEvent = e;
+}
+
+// Calculate the proper TCP MSS in EtherIP communication
+UINT CalcEtherIPTcpMss(ETHERIP_SERVER *s)
+{
+ UINT ret = MTU_FOR_PPPOE;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ // IPv4 / IPv6
+ if (IsIP4(&s->ClientIP))
+ {
+ ret -= 20;
+ }
+ else
+ {
+ ret -= 40;
+ }
+
+ // IPsec UDP
+ ret -= 8;
+
+ // IPsec ESP
+ ret -= 20;
+ ret -= s->CryptBlockSize * 2;
+
+ // IPsec Tunnel Mode IPv4 / IPv6 Header
+ if (s->IsTunnelMode)
+ {
+ if (IsIP4(&s->ClientIP))
+ {
+ ret -= 20;
+ }
+ else
+ {
+ ret -= 40;
+ }
+ }
+
+ if (s->L2TPv3 == false)
+ {
+ // EtherIP
+ ret -= 2;
+ }
+ else
+ {
+ // L2TPv3
+ ret -= 2;
+ }
+
+ // Ethernet
+ ret -= 14;
+
+ // IPv4
+ ret -= 20;
+
+ // TCP
+ ret -= 20;
+
+ return ret;
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_EtherIP.h b/src/Cedar/IPsec_EtherIP.h
new file mode 100644
index 00000000..a0be2bf5
--- /dev/null
+++ b/src/Cedar/IPsec_EtherIP.h
@@ -0,0 +1,150 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_EtherIP.h
+// Header of IPsec_EtherIP.c
+
+#ifndef IPSEC_ETHERIP_H
+#define IPSEC_ETHERIP_H
+
+//// Macro
+
+
+//// Constants
+#define ETHERIP_VPN_CONNECT_RETRY_INTERVAL (15 * 1000) // VPN connection retry interval
+#define ETHERIP_CLIENT_NAME "EtherIP Client"
+#define ETHERIP_POSTFIX "ETHERIP"
+#define ETHERIP_L2TPV3_CLIENT_NAME "L2TPv3 Client"
+#define ETHERIP_L2TPV3_CLIENT_NAME_EX "L2TPv3 Client - %s"
+#define ETHERIP_L2TPV3_POSTFIX "L2TPV3"
+
+//// Type
+
+// EtherIP server
+struct ETHERIP_SERVER
+{
+ REF *Ref;
+ CEDAR *Cedar;
+ IPSEC_SERVER *IPsec;
+ LOCK *Lock;
+ UINT Id;
+ IKE_SERVER *Ike;
+ UINT64 Now; // Current time
+ INTERRUPT_MANAGER *Interrupts; // Interrupt manager
+ SOCK_EVENT *SockEvent; // SockEvent
+ char CryptName[MAX_SIZE]; // Cipher algorithm name
+ LIST *SendPacketList; // Transmission packet list
+ UINT64 LastConnectFailedTick; // Time that it fails to connect at the last
+ IPC *Ipc; // IPC
+ THREAD *IpcConnectThread; // IPC connection thread
+ IPSEC_SERVICES CurrentIPSecServiceSetting; // Copy of the current IPsec service settings
+ IP ClientIP, ServerIP;
+ UINT ClientPort, ServerPort;
+ bool IsTunnelMode; // Whether the IPsec is in the tunnel mode
+ UINT CryptBlockSize; // Encryption block size of IPsec
+ char ClientId[MAX_SIZE]; // Client ID has been presented by the IPsec connection
+ UINT LastEtherIPSettingVerNo; // Version number of EtherIP settings last checked
+ ETHERIP_ID CurrentEtherIPIdSetting; // Current EtherIP ID settings
+ bool L2TPv3; // L2TPv3 mode
+ char VendorName[MAX_SIZE]; // Vendor name
+};
+
+
+//// Function prototype
+ETHERIP_SERVER *NewEtherIPServer(CEDAR *cedar, IPSEC_SERVER *ipsec, IKE_SERVER *ike,
+ IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *crypt_name,
+ bool is_tunnel_mode, UINT crypt_block_size,
+ char *client_id, UINT id);
+void ReleaseEtherIPServer(ETHERIP_SERVER *s);
+void CleanupEtherIPServer(ETHERIP_SERVER *s);
+void SetEtherIPServerSockEvent(ETHERIP_SERVER *s, SOCK_EVENT *e);
+void EtherIPProcInterrupts(ETHERIP_SERVER *s);
+void EtherIPProcRecvPackets(ETHERIP_SERVER *s, BLOCK *b);
+void EtherIPIpcConnectThread(THREAD *t, void *p);
+UINT CalcEtherIPTcpMss(ETHERIP_SERVER *s);
+
+
+#endif // IPSEC_ETHERIP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IKE.c b/src/Cedar/IPsec_IKE.c
new file mode 100644
index 00000000..7156b735
--- /dev/null
+++ b/src/Cedar/IPsec_IKE.c
@@ -0,0 +1,5947 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IKE.c
+// IKE (ISAKMP) and ESP protocol stack
+
+#include "CedarPch.h"
+
+
+// Processing of IKE received packet
+void ProcIKEPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
+{
+ // Validate arguments
+ if (ike == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (p->Type == IKE_UDP_TYPE_ISAKMP)
+ {
+ // ISAKMP (IKE) packet
+ IKE_PACKET *header;
+
+ header = ParseIKEPacketHeader(p);
+ if (header == NULL)
+ {
+ return;
+ }
+
+ //Debug("InitiatorCookie: %I64u, ResponderCookie: %I64u\n", header->InitiatorCookie, header->ResponderCookie);
+
+ switch (header->ExchangeType)
+ {
+ case IKE_EXCHANGE_TYPE_MAIN: // Main mode
+ ProcIkeMainModePacketRecv(ike, p, header);
+ break;
+
+ case IKE_EXCHANGE_TYPE_AGGRESSIVE: // Aggressive mode
+ ProcIkeAggressiveModePacketRecv(ike, p, header);
+ break;
+
+ case IKE_EXCHANGE_TYPE_QUICK: // Quick mode
+ ProcIkeQuickModePacketRecv(ike, p, header);
+ break;
+
+ case IKE_EXCHANGE_TYPE_INFORMATION: // Information exchange
+ ProcIkeInformationalExchangePacketRecv(ike, p, header);
+ break;
+ }
+
+ IkeFree(header);
+ }
+ else if (p->Type == IKE_UDP_TYPE_ESP)
+ {
+ // ESP packet
+ ProcIPsecEspPacketRecv(ike, p);
+ }
+}
+
+// Send a packet via IPsec
+void IPsecSendPacketByIPsecSa(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id)
+{
+ bool is_tunnel_mode;
+ IKE_CLIENT *c;
+ // Validate arguments
+ if (ike == NULL || sa == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ is_tunnel_mode = IsIPsecSaTunnelMode(sa);
+
+ c = sa->IkeClient;
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (is_tunnel_mode)
+ {
+ // Add an IPv4 / IPv6 header in the case of tunnel mode
+ if (IsZeroIP(&c->TunnelModeClientIP) == false || IsZeroIP(&c->TunnelModeServerIP) == false)
+ {
+ BUF *b;
+ UCHAR esp_proto_id;
+
+ b = NewBuf();
+
+ if (IsIP4(&c->TunnelModeClientIP))
+ {
+ // IPv4 header
+ IPV4_HEADER h;
+
+ h.VersionAndHeaderLength = 0;
+ h.TypeOfService = 0;
+ IPV4_SET_VERSION(&h, 4);
+ IPV4_SET_HEADER_LEN(&h, sizeof(IPV4_HEADER) / 4);
+ h.TotalLength = Endian16((USHORT)(data_size + sizeof(IPV4_HEADER)));
+ h.Identification = Endian16(c->TunnelSendIpId++);
+ h.FlagsAndFlagmentOffset[0] = h.FlagsAndFlagmentOffset[1] = 0;
+ h.TimeToLive = DEFAULT_IP_TTL;
+ h.Protocol = protocol_id;
+ h.SrcIP = IPToUINT(&c->TunnelModeServerIP);
+ h.DstIP = IPToUINT(&c->TunnelModeClientIP);
+ h.Checksum = 0;
+ h.Checksum = IpChecksum(&h, sizeof(IPV4_HEADER));
+
+ WriteBuf(b, &h, sizeof(IPV4_HEADER));
+
+ esp_proto_id = IKE_PROTOCOL_ID_IPV4;
+ }
+ else
+ {
+ // IPv6 header
+ IPV6_HEADER h;
+
+ Zero(&h, sizeof(h));
+ h.VersionAndTrafficClass1 = 0;
+ IPV6_SET_VERSION(&h, 6);
+ h.TrafficClass2AndFlowLabel1 = 0;
+ h.FlowLabel2 = h.FlowLabel3 = 0;
+ h.PayloadLength = Endian16(data_size);
+ h.NextHeader = protocol_id;
+ h.HopLimit = 64;
+ Copy(h.SrcAddress.Value, c->TunnelModeServerIP.ipv6_addr, 16);
+ Copy(h.DestAddress.Value, c->TunnelModeClientIP.ipv6_addr, 16);
+
+ WriteBuf(b, &h, sizeof(IPV6_HEADER));
+
+ esp_proto_id = IKE_PROTOCOL_ID_IPV6;
+ }
+
+ WriteBuf(b, data, data_size);
+
+ IPsecSendPacketByIPsecSaInner(ike, sa, b->Buf, b->Size, esp_proto_id);
+
+ FreeBuf(b);
+ }
+ }
+ else
+ {
+ // Send as it is in the case of transport mode
+ IPsecSendPacketByIPsecSaInner(ike, sa, data, data_size, protocol_id);
+ }
+}
+void IPsecSendPacketByIPsecSaInner(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id)
+{
+ UINT esp_size;
+ UINT encrypted_payload_size;
+ UCHAR *esp;
+ UINT i;
+ UINT size_of_padding;
+ IKE_CRYPTO_PARAM cp;
+ BUF *enc;
+ IKE_CLIENT *c;
+ // Validate arguments
+ if (ike == NULL || sa == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ c = sa->IkeClient;
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Calculate the payload size after encryption
+ encrypted_payload_size = data_size + 2;
+ if ((encrypted_payload_size % sa->TransformSetting.Crypto->BlockSize) != 0)
+ {
+ encrypted_payload_size = ((encrypted_payload_size / sa->TransformSetting.Crypto->BlockSize) + 1) * sa->TransformSetting.Crypto->BlockSize;
+ }
+ size_of_padding = encrypted_payload_size - data_size - 2;
+
+ // Calculate the size of the ESP packet
+ esp_size = sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + encrypted_payload_size + IKE_ESP_HASH_SIZE;
+
+ // Build the ESP packet
+ esp = Malloc(esp_size + IKE_MAX_HASH_SIZE);
+
+ // SPI
+ WRITE_UINT(esp, sa->Spi);
+
+ // Sequence number
+ sa->CurrentSeqNo++;
+ WRITE_UINT(esp + sizeof(UINT), sa->CurrentSeqNo);
+
+ // IV
+ Copy(esp + sizeof(UINT) * 2, sa->EspIv, sa->TransformSetting.Crypto->BlockSize);
+
+ // Payload data
+ Copy(esp + sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize, data, data_size);
+
+ // Padding
+ for (i = 0;i < size_of_padding;i++)
+ {
+ esp[sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + data_size + i] = (UCHAR)(i + 1);
+ }
+
+ // Padding length
+ esp[sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + data_size + size_of_padding] = (UCHAR)size_of_padding;
+
+ // Next header number
+ esp[sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + data_size + size_of_padding + 1] = protocol_id;
+
+ // Encryption
+ Copy(cp.Iv, sa->EspIv, sa->TransformSetting.Crypto->BlockSize);
+ cp.Key = sa->CryptoKey;
+
+ enc = IkeEncrypt(esp + sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize, encrypted_payload_size, &cp);
+ if (enc != NULL)
+ {
+ bool start_qm = false;
+ UINT server_port = c->ServerPort;
+ UINT client_port = c->ClientPort;
+
+ // Overwrite the encrypted result
+ Copy(esp + sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize, enc->Buf, encrypted_payload_size);
+
+ FreeBuf(enc);
+
+ // Calculate the HMAC
+ IkeHMac(sa->TransformSetting.Hash,
+ esp + sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + encrypted_payload_size,
+ sa->HashKey,
+ sa->TransformSetting.Hash->HashSize,
+ esp,
+ sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + encrypted_payload_size);
+
+ //*(UCHAR *)(esp + sizeof(UINT) * 2 + sa->TransformSetting.Crypto->BlockSize + encrypted_payload_size) = 0xff;
+
+ if (sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_TRANSPORT ||
+ sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_TUNNEL)
+ {
+ server_port = client_port = IPSEC_PORT_IPSEC_ESP_RAW;
+ }
+
+ // Add the completed packet to the transmission list
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ESP, &c->ServerIP, server_port, &c->ClientIP, client_port,
+ esp, esp_size);
+
+ // Feedback the IV
+ Copy(sa->EspIv, cp.NextIv, sa->TransformSetting.Crypto->BlockSize);
+
+ sa->TotalSize += esp_size;
+
+ if (sa->CurrentSeqNo >= 0xf0000000)
+ {
+ start_qm = true;
+ }
+
+ if (sa->TransformSetting.LifeKilobytes != 0)
+ {
+ UINT64 hard_size = (UINT64)sa->TransformSetting.LifeKilobytes * (UINT64)1000;
+ UINT64 soft_size = hard_size * (UINT64)2 / (UINT64)3;
+
+ if (sa->TotalSize >= soft_size)
+ {
+ start_qm = true;
+ }
+ }
+
+ if (start_qm)
+ {
+ if (sa->StartQM_FlagSet == false)
+ {
+ sa->StartQM_FlagSet = true;
+ c->StartQuickModeAsSoon = true;
+ }
+ }
+ }
+ else
+ {
+ // Encryption failure
+ Free(esp);
+ }
+}
+void IPsecSendPacketByIkeClient(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, UCHAR protocol_id)
+{
+ // Validate arguments
+ if (ike == NULL || c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ if (c->CurrentIpSecSaSend == NULL)
+ {
+ return;
+ }
+
+ IPsecSendPacketByIPsecSa(ike, c->CurrentIpSecSaSend, data, data_size, protocol_id);
+}
+
+// Send an UDP packet via IPsec
+void IPsecSendUdpPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT src_port, UINT dst_port, UCHAR *data, UINT data_size)
+{
+ UCHAR *udp;
+ UINT udp_size;
+ UDP_HEADER *u;
+ UCHAR tmp1600[1600];
+ bool no_free = false;
+ // Validate arguments
+ if (ike == NULL || c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ // Build an UDP packet
+ udp_size = sizeof(UDP_HEADER) + data_size;
+
+ if (udp_size > sizeof(tmp1600))
+ {
+ udp = Malloc(udp_size);
+ }
+ else
+ {
+ udp = tmp1600;
+ no_free = true;
+ }
+
+ // UDP header
+ u = (UDP_HEADER *)udp;
+ u->SrcPort = Endian16(src_port);
+ u->DstPort = Endian16(dst_port);
+ u->PacketLength = Endian16(udp_size);
+ u->Checksum = 0;
+
+ //Debug("IPsec UDP Send: %u -> %u %u\n", src_port, dst_port, data_size);
+#ifdef RAW_DEBUG
+ IPsecIkeSendUdpForDebug(IPSEC_PORT_L2TP, 1, data, data_size);
+#endif // RAW_DEBUG
+
+ // Payload
+ Copy(udp + sizeof(UDP_HEADER), data, data_size);
+
+ if (IsIP6(&c->ClientIP))
+ {
+ if (IsIPsecSaTunnelMode(c->CurrentIpSecSaSend) == false)
+ {
+ u->Checksum = CalcChecksumForIPv6((IPV6_ADDR *)c->TransportModeServerIP.ipv6_addr,
+ (IPV6_ADDR *)c->TransportModeClientIP.ipv6_addr,
+ IP_PROTO_UDP,
+ u,
+ udp_size, 0);
+ }
+ else
+ {
+ u->Checksum = CalcChecksumForIPv6((IPV6_ADDR *)c->TunnelModeServerIP.ipv6_addr,
+ (IPV6_ADDR *)c->TunnelModeClientIP.ipv6_addr,
+ IP_PROTO_UDP,
+ u,
+ udp_size, 0);
+ }
+ }
+
+ IPsecSendPacketByIkeClient(ike, c, udp, udp_size, IP_PROTO_UDP);
+
+ if (no_free == false)
+ {
+ Free(udp);
+ }
+}
+
+// Get whether the specified IPsec SA is in tunnel mode
+bool IsIPsecSaTunnelMode(IPSECSA *sa)
+{
+ // Validate arguments
+ if (sa == NULL)
+ {
+ return false;
+ }
+
+ if (sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_TUNNEL ||
+ sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_NAT_TUNNEL_1 ||
+ sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_NAT_TUNNEL_2)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Reception process of ESP packet
+void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
+{
+ UCHAR *src;
+ UINT src_size;
+ UINT spi;
+ UINT seq;
+ IPSECSA *ipsec_sa;
+ IKE_CLIENT *c;
+ UINT block_size;
+ UINT hash_size;
+ bool update_status = false;
+ UCHAR *iv;
+ UCHAR *hash;
+ UCHAR *encrypted_payload_data;
+ UINT size_of_payload_data;
+ IKE_CRYPTO_PARAM cp;
+ BUF *dec;
+ UCHAR calced_hash[IKE_MAX_HASH_SIZE];
+ bool is_tunnel_mode = false;
+ // Validate arguments
+ if (ike == NULL || p == NULL)
+ {
+ return;
+ }
+
+ src = (UCHAR *)p->Data;
+ src_size = p->Size;
+
+ if (p->DestPort == IPSEC_PORT_IPSEC_ESP_RAW)
+ {
+ if (IsIP4(&p->DstIP))
+ {
+ // Skip the IP header when received in Raw mode (only in the case of IPv4)
+ UINT ip_header_size = GetIpHeaderSize(src, src_size);
+
+ src += ip_header_size;
+ src_size -= ip_header_size;
+ }
+ }
+
+ // Get the SPI
+ if (src_size < sizeof(UINT))
+ {
+ return;
+ }
+
+ spi = READ_UINT(src + 0);
+ if (spi == 0)
+ {
+ return;
+ }
+
+ // Get the sequence number
+ if (src_size < (sizeof(UINT) * 2))
+ {
+ return;
+ }
+ seq = READ_UINT(src + sizeof(UINT));
+
+ // Search and retrieve the IPsec SA from SPI
+ ipsec_sa = SearchClientToServerIPsecSaBySpi(ike, spi);
+ if (ipsec_sa == NULL)
+ {
+ // Invalid SPI
+ UINT64 init_cookie = Rand64();
+ UINT64 resp_cookie = 0;
+ IKE_CLIENT *c = NULL;
+ IKE_CLIENT t;
+
+
+ Copy(&t.ClientIP, &p->SrcIP, sizeof(IP));
+ t.ClientPort = p->SrcPort;
+ Copy(&t.ServerIP, &p->DstIP, sizeof(IP));
+ t.ServerPort = p->DestPort;
+ t.CurrentIkeSa = NULL;
+
+ if (p->DestPort == IPSEC_PORT_IPSEC_ESP_RAW)
+ {
+ t.ClientPort = t.ServerPort = IPSEC_PORT_IPSEC_ISAKMP;
+ }
+
+ c = Search(ike->ClientList, &t);
+
+ if (c != NULL && c->CurrentIkeSa != NULL)
+ {
+ init_cookie = c->CurrentIkeSa->InitiatorCookie;
+ resp_cookie = c->CurrentIkeSa->ResponderCookie;
+ }
+
+ SendInformationalExchangePacketEx(ike, (c == NULL ? &t : c), IkeNewNoticeErrorInvalidSpiPayload(spi), false,
+ init_cookie, resp_cookie);
+
+ SendDeleteIPsecSaPacket(ike, (c == NULL ? &t : c), spi);
+ return;
+ }
+
+ is_tunnel_mode = IsIPsecSaTunnelMode(ipsec_sa);
+
+ c = ipsec_sa->IkeClient;
+ if (c == NULL)
+ {
+ return;
+ }
+
+ block_size = ipsec_sa->TransformSetting.Crypto->BlockSize;
+ hash_size = IKE_ESP_HASH_SIZE;
+
+ // Get the IV
+ if (src_size < (sizeof(UINT) * 2 + block_size + hash_size + block_size))
+ {
+ return;
+ }
+ iv = src + sizeof(UINT) * 2;
+
+ // Get the hash
+ hash = src + src_size - hash_size;
+
+ // Inspect the HMAC
+ IkeHMac(ipsec_sa->TransformSetting.Hash, calced_hash, ipsec_sa->HashKey,
+ ipsec_sa->TransformSetting.Hash->HashSize, src, src_size - hash_size);
+
+ if (Cmp(calced_hash, hash, hash_size) != 0)
+ {
+ //Debug("IPsec SA 0x%X: Invalid HMAC Value.\n", ipsec_sa->Spi);
+ return;
+ }
+
+ // Get the payload data
+ encrypted_payload_data = src + sizeof(UINT) * 2 + block_size;
+ size_of_payload_data = src_size - hash_size - block_size - sizeof(UINT) * 2;
+ if (size_of_payload_data == 0 || (size_of_payload_data % block_size) != 0)
+ {
+ // Payload data don't exist or is not a multiple of block size
+ return;
+ }
+
+ // Decrypt the payload data
+ cp.Key = ipsec_sa->CryptoKey;
+ Copy(&cp.Iv, iv, block_size);
+
+ dec = IkeDecrypt(encrypted_payload_data, size_of_payload_data, &cp);
+ if (dec != NULL)
+ {
+ UCHAR *dec_data = dec->Buf;
+ UINT dec_size = dec->Size;
+ UCHAR size_of_padding = dec_data[dec_size - 2];
+ UCHAR next_header = dec_data[dec_size - 1];
+ if ((dec_size - 2) >= size_of_padding)
+ {
+ UINT orig_size = dec_size - 2 - size_of_padding;
+
+ ipsec_sa->TotalSize += dec_size;
+
+ if (is_tunnel_mode)
+ {
+ // Tunnel Mode
+ if (next_header == IKE_PROTOCOL_ID_IPV4 || next_header == IKE_PROTOCOL_ID_IPV6)
+ {
+ // Check the contents by parsing the IPv4 / IPv6 header in the case of tunnel mode
+ BUF *b = NewBuf();
+ static UCHAR src_mac_dummy[6] = {0, 0, 0, 0, 0, 0, };
+ static UCHAR dst_mac_dummy[6] = {0, 0, 0, 0, 0, 0, };
+ USHORT tpid = Endian16(next_header == IKE_PROTOCOL_ID_IPV4 ? MAC_PROTO_IPV4 : MAC_PROTO_IPV6);
+ PKT *pkt;
+
+ WriteBuf(b, src_mac_dummy, sizeof(src_mac_dummy));
+ WriteBuf(b, dst_mac_dummy, sizeof(dst_mac_dummy));
+ WriteBuf(b, &tpid, sizeof(tpid));
+
+ WriteBuf(b, dec_data, dec_size);
+
+ // Parse
+ pkt = ParsePacket(b->Buf, b->Size);
+
+#ifdef RAW_DEBUG
+ IPsecIkeSendUdpForDebug(IPSEC_PORT_L2TP, 1, b->Buf, b->Size);
+#endif // RAW_DEBUG
+
+ if (pkt == NULL)
+ {
+ // Parsing failure
+ dec_data = NULL;
+ dec_size = 0;
+ }
+ else
+ {
+ // Parsing success
+ switch (pkt->TypeL3)
+ {
+ case L3_IPV4:
+ // Save the internal IP address information
+ UINTToIP(&c->TunnelModeServerIP, pkt->L3.IPv4Header->DstIP);
+ UINTToIP(&c->TunnelModeClientIP, pkt->L3.IPv4Header->SrcIP);
+
+ if (IPV4_GET_OFFSET(pkt->L3.IPv4Header) == 0)
+ {
+ if ((IPV4_GET_FLAGS(pkt->L3.IPv4Header) & 0x01) == 0)
+ {
+ if (pkt->L3.IPv4Header->Protocol == IPSEC_IP_PROTO_ETHERIP)
+ {
+ // EtherIP
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // An EtherIP packet has been received
+ ProcIPsecEtherIPPacketRecv(ike, c, pkt->IPv4PayloadData, pkt->IPv4PayloadSize, true);
+ }
+ }
+ else if (pkt->L3.IPv4Header->Protocol == IPSEC_IP_PROTO_L2TPV3)
+ {
+ // L2TPv3
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // A L2TPv3 packet has been received
+ ProcL2TPv3PacketRecv(ike, c, pkt->IPv4PayloadData, pkt->IPv4PayloadSize, true);
+ }
+ }
+ }
+ }
+ break;
+
+ case L3_IPV6:
+ // Save the internal IP address information
+ SetIP6(&c->TunnelModeServerIP, pkt->IPv6HeaderPacketInfo.IPv6Header->DestAddress.Value);
+ SetIP6(&c->TunnelModeClientIP, pkt->IPv6HeaderPacketInfo.IPv6Header->SrcAddress.Value);
+
+ if (pkt->IPv6HeaderPacketInfo.IsFragment == false)
+ {
+ if (pkt->IPv6HeaderPacketInfo.FragmentHeader == NULL || (IPV6_GET_FLAGS(pkt->IPv6HeaderPacketInfo.FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS) == 0)
+ {
+ if (pkt->IPv6HeaderPacketInfo.Protocol == IPSEC_IP_PROTO_ETHERIP)
+ {
+ // EtherIP
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // An EtherIP packet has been received
+ ProcIPsecEtherIPPacketRecv(ike, c, pkt->IPv6HeaderPacketInfo.Payload, pkt->IPv6HeaderPacketInfo.PayloadSize, true);
+ }
+ }
+ else if (pkt->IPv6HeaderPacketInfo.Protocol == IPSEC_IP_PROTO_L2TPV3)
+ {
+ // L2TPv3
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // A L2TPv3 packet has been received
+ ProcL2TPv3PacketRecv(ike, c, pkt->IPv6HeaderPacketInfo.Payload, pkt->IPv6HeaderPacketInfo.PayloadSize, true);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ FreePacket(pkt);
+ }
+
+ FreeBuf(b);
+ }
+ }
+ else
+ {
+ // Transport mode
+ if (next_header == IP_PROTO_UDP)
+ {
+ if (ike->IPsec->Services.L2TP_IPsec)
+ {
+ // An UDP packet has been received
+ ProcIPsecUdpPacketRecv(ike, c, dec_data, dec_size);
+ }
+ }
+ else if (next_header == IPSEC_IP_PROTO_ETHERIP)
+ {
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // An EtherIP packet has been received
+ ProcIPsecEtherIPPacketRecv(ike, c, dec_data, dec_size, false);
+ }
+ }
+ else if (next_header == IPSEC_IP_PROTO_L2TPV3)
+ {
+ if (ike->IPsec->Services.EtherIP_IPsec)
+ {
+ // A L2TPv3 packet has been received
+ ProcL2TPv3PacketRecv(ike, c, dec_data, dec_size, false);
+ }
+ }
+ }
+
+ update_status = true;
+ }
+
+ FreeBuf(dec);
+ }
+
+ if (update_status)
+ {
+ bool start_qm = false;
+ // Update the status of the client
+ c->CurrentIpSecSaRecv = ipsec_sa;
+ if (ipsec_sa->PairIPsecSa != NULL)
+ {
+ c->CurrentIpSecSaSend = ipsec_sa->PairIPsecSa;
+ }
+ c->LastCommTick = ike->Now;
+ ipsec_sa->LastCommTick = ike->Now;
+ if (ipsec_sa->PairIPsecSa != NULL)
+ {
+ ipsec_sa->PairIPsecSa->LastCommTick = ike->Now;
+ }
+
+ SetIkeClientEndpoint(ike, c, &p->SrcIP, p->SrcPort, &p->DstIP, p->DestPort);
+
+ if (seq >= 0xf0000000)
+ {
+ // Execute a QuickMode forcibly since sequence number is going to exhaust
+ start_qm = true;
+ }
+
+ if (ipsec_sa->TransformSetting.LifeKilobytes != 0)
+ {
+ UINT64 hard_size = (UINT64)ipsec_sa->TransformSetting.LifeKilobytes * (UINT64)1000;
+ UINT64 soft_size = hard_size * (UINT64)2 / (UINT64)3;
+
+ if (ipsec_sa->TotalSize >= soft_size)
+ {
+ // Execute a QuickMode forcibly because the capacity limit is going to exceed
+ start_qm = true;
+ }
+ }
+
+ if (start_qm)
+ {
+ if (ipsec_sa->StartQM_FlagSet == false)
+ {
+ c->StartQuickModeAsSoon = true;
+ ipsec_sa->StartQM_FlagSet = true;
+ }
+ }
+ }
+}
+
+// Received the L2TPv3 packet via the IPsec tunnel
+void ProcL2TPv3PacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode)
+{
+ UDPPACKET p;
+ // Validate arguments
+ if (ike == NULL || c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ c->IsL2TPOnIPsecTunnelMode = is_tunnel_mode;
+
+ IPsecIkeClientManageL2TPServer(ike, c);
+
+ // Pass the received packet to the L2TP server
+ p.Type = 0;
+ p.Data = data;
+ p.DestPort = IPSEC_PORT_L2TPV3_VIRTUAL;
+ p.Size = data_size;
+
+ if (is_tunnel_mode)
+ {
+ Copy(&p.DstIP, &c->TunnelModeServerIP, sizeof(IP));
+ Copy(&p.SrcIP, &c->TunnelModeClientIP, sizeof(IP));
+ }
+ else
+ {
+ Copy(&p.DstIP, &c->L2TPServerIP, sizeof(IP));
+ Copy(&p.SrcIP, &c->L2TPClientIP, sizeof(IP));
+ }
+ p.SrcPort = IPSEC_PORT_L2TPV3_VIRTUAL;
+
+#ifdef RAW_DEBUG
+ IPsecIkeSendUdpForDebug(IPSEC_PORT_L2TP, 1, ((UCHAR *)p.Data) + 4, p.Size - 4);
+#endif // RAW_DEBUG
+
+ ProcL2TPPacketRecv(c->L2TP, &p);
+}
+
+// An EtherIP packet has been received via an IPsec tunnel
+void ProcIPsecEtherIPPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (ike == NULL || c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ c->IsEtherIPOnIPsecTunnelMode = is_tunnel_mode;
+
+ IPsecIkeClientManageEtherIPServer(ike, c);
+
+ b = NewBlock(data, data_size, 0);
+
+ EtherIPProcRecvPackets(c->EtherIP, b);
+
+ Free(b);
+}
+
+// An UDP packet has been received via the IPsec tunnel
+void ProcIPsecUdpPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size)
+{
+ UDP_HEADER *u;
+ UINT payload_size;
+ UINT src_port, dst_port;
+ UINT packet_length;
+ // Validate arguments
+ if (ike == NULL || c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ if (data_size <= sizeof(UDP_HEADER))
+ {
+ // There is no UDP header or the data is 0 bytes
+ return;
+ }
+
+ // UDP header
+ u = (UDP_HEADER *)data;
+
+ packet_length = Endian16(u->PacketLength);
+
+ if (packet_length <= sizeof(UDP_HEADER))
+ {
+ return;
+ }
+
+ payload_size = packet_length - sizeof(UDP_HEADER);
+
+ if (payload_size == 0)
+ {
+ // No data
+ return;
+ }
+
+ if (data_size < (sizeof(UDP_HEADER) + payload_size))
+ {
+ // Data is not followed
+ return;
+ }
+
+ src_port = Endian16(u->SrcPort);
+ dst_port = Endian16(u->DstPort);
+
+ if (dst_port == IPSEC_PORT_L2TP)
+ {
+ UDPPACKET p;
+ // A L2TP packet has been received
+ IPsecIkeClientManageL2TPServer(ike, c);
+
+ // Update Port number
+ c->L2TPClientPort = src_port;
+
+ // Pass the received packet to the L2TP server
+ p.Type = 0;
+ p.Data = data + sizeof(UDP_HEADER);
+ p.DestPort = IPSEC_PORT_L2TP;
+ Copy(&p.DstIP, &c->L2TPServerIP, sizeof(IP));
+ p.Size = payload_size;
+ Copy(&p.SrcIP, &c->L2TPClientIP, sizeof(IP));
+ p.SrcPort = IPSEC_PORT_L2TP;
+
+ ProcL2TPPacketRecv(c->L2TP, &p);
+
+ //Debug("IPsec UDP Recv: %u <= %u %u\n", dst_port, src_port, p.Size);
+
+#ifdef RAW_DEBUG
+ IPsecIkeSendUdpForDebug(IPSEC_PORT_L2TP, 1, p.Data, p.Size);
+#endif // RAW_DEBUG
+ }
+}
+
+// Send a raw packet for debugging
+void IPsecIkeSendUdpForDebug(UINT dst_port, UINT dst_ip, void *data, UINT size)
+{
+ SOCK *s = NewUDP(0);
+ IP d;
+
+ SetIP(&d, dst_ip, dst_ip, dst_ip, dst_ip);
+
+ SendTo(s, &d, dst_port, data, size);
+
+ ReleaseSock(s);
+}
+
+// L2TP packet transmission (via IPsec SA tunnel)
+void IPsecIkeClientSendL2TPPackets(IKE_SERVER *ike, IKE_CLIENT *c, L2TP_SERVER *l2tp)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || c == NULL || l2tp == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(l2tp->SendPacketList);i++)
+ {
+ UDPPACKET *u = LIST_DATA(l2tp->SendPacketList, i);
+
+ if (u->SrcPort != IPSEC_PORT_L2TPV3_VIRTUAL)
+ {
+ // L2TP UDP packet transmission
+ IPsecSendUdpPacket(ike, c, IPSEC_PORT_L2TP, c->L2TPClientPort,
+ u->Data, u->Size);
+ }
+ else
+ {
+ // L2TPv3 special IP packet transmission
+ IPsecSendPacketByIkeClient(ike, c, u->Data, u->Size, IPSEC_IP_PROTO_L2TPV3);
+
+#ifdef RAW_DEBUG
+ IPsecIkeSendUdpForDebug(IPSEC_PORT_L2TP, 1, ((UCHAR *)u->Data) + 4, u->Size - 4);
+#endif // RAW_DEBUG
+ }
+
+ FreeUdpPacket(u);
+ }
+
+ DeleteAll(l2tp->SendPacketList);
+}
+
+// Manage the L2TP server that is associated with the IKE_CLIENT
+void IPsecIkeClientManageL2TPServer(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ L2TP_SERVER *l2tp;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->L2TP == NULL)
+ {
+ UINT crypt_block_size = IKE_MAX_BLOCK_SIZE;
+
+ if (c->CurrentIpSecSaRecv != NULL)
+ {
+ crypt_block_size = c->CurrentIpSecSaRecv->TransformSetting.Crypto->BlockSize;
+ }
+
+ c->L2TP = NewL2TPServerEx(ike->Cedar, ike, IsIP6(&c->ClientIP), crypt_block_size);
+ c->L2TP->IkeClient = c;
+
+ Copy(&c->L2TPServerIP, &c->ServerIP, sizeof(IP));
+ Copy(&c->L2TPClientIP, &c->ClientIP, sizeof(IP));
+
+ if (c->CurrentIpSecSaRecv != NULL)
+ {
+ Format(c->L2TP->CryptName, sizeof(c->L2TP->CryptName),
+ "IPsec - %s (%u bits)",
+ c->CurrentIpSecSaRecv->TransformSetting.Crypto->Name,
+ c->CurrentIpSecSaRecv->TransformSetting.CryptoKeySize * 8);
+ }
+
+ Debug("IKE_CLIENT 0x%X: L2TP Server Started.\n", c);
+
+ IPsecLog(ike, c, NULL, NULL, "LI_L2TP_SERVER_STARTED");
+ }
+
+ l2tp = c->L2TP;
+
+ if (l2tp->Interrupts == NULL)
+ {
+ l2tp->Interrupts = ike->Interrupts;
+ }
+
+ if (l2tp->SockEvent == NULL)
+ {
+ SetL2TPServerSockEvent(l2tp, ike->SockEvent);
+ }
+
+ l2tp->Now = ike->Now;
+}
+
+// Manage the EtherIP server that is associated with the IKE_CLIENT
+void IPsecIkeClientManageEtherIPServer(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ ETHERIP_SERVER *s;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->EtherIP == NULL)
+ {
+ char crypt_name[MAX_SIZE];
+ UINT crypt_block_size = IKE_MAX_BLOCK_SIZE;
+
+ Zero(crypt_name, sizeof(crypt_name));
+
+ if (c->CurrentIpSecSaRecv != NULL)
+ {
+ Format(crypt_name, sizeof(crypt_name),
+ "IPsec - %s (%u bits)",
+ c->CurrentIpSecSaRecv->TransformSetting.Crypto->Name,
+ c->CurrentIpSecSaRecv->TransformSetting.CryptoKeySize * 8);
+
+ crypt_block_size = c->CurrentIpSecSaRecv->TransformSetting.Crypto->BlockSize;
+ }
+
+ c->EtherIP = NewEtherIPServer(ike->Cedar, ike->IPsec, ike,
+ &c->ClientIP, c->ClientPort,
+ &c->ServerIP, c->ServerPort, crypt_name,
+ c->IsEtherIPOnIPsecTunnelMode, crypt_block_size, c->ClientId,
+ ++ike->CurrentEtherId);
+
+ Debug("IKE_CLIENT 0x%X: EtherIP Server Started.\n", c);
+
+ IPsecLog(ike, c, NULL, NULL, NULL, "LI_ETHERIP_SERVER_STARTED", ike->CurrentEtherId);
+ }
+ else
+ {
+ StrCpy(c->EtherIP->ClientId, sizeof(c->EtherIP->ClientId), c->ClientId);
+ }
+
+ s = c->EtherIP;
+
+ if (s->Interrupts == NULL)
+ {
+ s->Interrupts = ike->Interrupts;
+ }
+
+ if (s->SockEvent == NULL)
+ {
+ SetEtherIPServerSockEvent(s, ike->SockEvent);
+ }
+
+ s->Now = ike->Now;
+}
+
+// EtherIP packet transmission (via IPsec SA tunnel)
+void IPsecIkeClientSendEtherIPPackets(IKE_SERVER *ike, IKE_CLIENT *c, ETHERIP_SERVER *s)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(s->SendPacketList);i++)
+ {
+ BLOCK *b = LIST_DATA(s->SendPacketList, i);
+
+ // Packet transmission
+ IPsecSendPacketByIkeClient(ike, c, b->Buf, b->Size, IPSEC_IP_PROTO_ETHERIP);
+
+ FreeBlock(b);
+ }
+
+ DeleteAll(s->SendPacketList);
+}
+
+// Handle the deletion payload
+void ProcDeletePayload(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_DELETE_PAYLOAD *d)
+{
+ // Validate arguments
+ if (ike == NULL || c == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (d->ProtocolId == IKE_PROTOCOL_ID_IPSEC_ESP)
+ {
+ UINT i;
+ // Remove the IPsec SA
+ for (i = 0;i < LIST_NUM(d->SpiList);i++)
+ {
+ BUF *b = LIST_DATA(d->SpiList, i);
+
+ if (b->Size == 4)
+ {
+ UINT spi = READ_UINT(b->Buf);
+ MarkIPsecSaAsDeleted(ike, SearchIPsecSaBySpi(ike, c, spi));
+ }
+ }
+ }
+ else if (d->ProtocolId == IKE_PROTOCOL_ID_IKE)
+ {
+ UINT i;
+ // Remove the IKE SA
+ for (i = 0;i < LIST_NUM(d->SpiList);i++)
+ {
+ BUF *b = LIST_DATA(d->SpiList, i);
+
+ if (b->Size == 16)
+ {
+ UINT64 v1 = READ_UINT64(((UCHAR *)b->Buf) + 0);
+ UINT64 v2 = READ_UINT64(((UCHAR *)b->Buf) + 8);
+
+ IKE_SA *sa = FindIkeSaByResponderCookie(ike, v2);
+
+ if (sa != NULL && sa->IkeClient == c)
+ {
+ MarkIkeSaAsDeleted(ike, sa);
+ }
+ }
+ }
+ }
+}
+
+// Mark the IKE_CLIENT for deletion
+void MarkIkeClientAsDeleted(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ char client_ip_str[MAX_SIZE];
+ char server_ip_str[MAX_SIZE];
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->Deleting)
+ {
+ return;
+ }
+
+ ike->StateHasChanged = true;
+
+ c->Deleting = true;
+
+ IPToStr(client_ip_str, sizeof(client_ip_str), &c->ClientIP);
+ IPToStr(server_ip_str, sizeof(server_ip_str), &c->ServerIP);
+
+ Debug("Deleting IKE_CLIENT: %p: %s:%u -> %s:%u\n", c, client_ip_str, c->ClientPort, server_ip_str, c->ServerPort);
+
+ IPsecLog(ike, c, NULL, NULL, "LI_DELETE_IKE_CLIENT");
+}
+
+// Mark the IKE SA for deletion
+void MarkIkeSaAsDeleted(IKE_SERVER *ike, IKE_SA *sa)
+{
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ if (sa->Deleting)
+ {
+ return;
+ }
+
+ ike->StateHasChanged = true;
+
+ sa->Deleting = true;
+
+ Debug("IKE SA %I64u - %I64u has been marked as being deleted.\n", sa->InitiatorCookie, sa->ResponderCookie);
+
+ SendDeleteIkeSaPacket(ike, sa->IkeClient, sa->InitiatorCookie, sa->ResponderCookie);
+
+ IPsecLog(ike, NULL, sa, NULL, "LI_DELETE_IKE_SA");
+}
+
+// Mark the IPsec SA for deletion
+void MarkIPsecSaAsDeleted(IKE_SERVER *ike, IPSECSA *sa)
+{
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ if (sa->Deleting)
+ {
+ return;
+ }
+
+ ike->StateHasChanged = true;
+
+ sa->Deleting = true;
+
+ Debug("IPsec SA 0x%X has been marked as being deleted.\n", sa->Spi);
+
+ SendDeleteIPsecSaPacket(ike, sa->IkeClient, sa->Spi);
+
+ IPsecLog(ike, NULL, NULL, sa, "LI_DELETE_IPSEC_SA");
+}
+
+// IPsec SA Deletion packet transmission process
+void SendDeleteIPsecSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi)
+{
+ IKE_PACKET_PAYLOAD *payload;
+ BUF *buf;
+ // Validate arguments
+ if (ike == NULL || c == NULL || spi == 0)
+ {
+ return;
+ }
+
+ buf = NewBuf();
+ WriteBufInt(buf, spi);
+
+ payload = IkeNewDeletePayload(IKE_PROTOCOL_ID_IPSEC_ESP, NewListSingle(buf));
+
+ SendInformationalExchangePacket(ike, c, payload);
+}
+
+// IKE SA deletion packet transmission process
+void SendDeleteIkeSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT64 resp_cookie)
+{
+ IKE_PACKET_PAYLOAD *payload;
+ BUF *buf;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ buf = NewBuf();
+ WriteBufInt64(buf, init_cookie);
+ WriteBufInt64(buf, resp_cookie);
+
+ payload = IkeNewDeletePayload(IKE_PROTOCOL_ID_IKE, NewListSingle(buf));
+
+ SendInformationalExchangePacket(ike, c, payload);
+}
+
+// Information exchange packet transmission process
+void SendInformationalExchangePacket(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload)
+{
+ SendInformationalExchangePacketEx(ike, c, payload, false, 0, 0);
+}
+void SendInformationalExchangePacketEx(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload, bool force_plain, UINT64 init_cookie, UINT64 resp_cookie)
+{
+ IKE_SA *sa;
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ UCHAR dummy_hash_data[IKE_MAX_HASH_SIZE];
+ IKE_PACKET_PAYLOAD *hash_payload;
+ BUF *ps_buf;
+ UINT after_hash_offset, after_hash_size;
+ BUF *ps_buf_after_hash;
+ BUF *tmp_buf;
+ UCHAR hash[IKE_MAX_HASH_SIZE];
+ IKE_CRYPTO_PARAM cp;
+ bool plain = false;
+ // Validate arguments
+ if (ike == NULL || c == NULL || payload == NULL)
+ {
+ IkeFreePayload(payload);
+ return;
+ }
+
+ sa = c->CurrentIkeSa;
+ if (sa == NULL)
+ {
+ plain = true;
+ }
+
+ if (force_plain)
+ {
+ plain = true;
+ }
+
+ if (plain && (init_cookie == 0 && resp_cookie == 0))
+ {
+ init_cookie = Rand64();
+ resp_cookie = 0;
+ }
+
+ payload_list = NewListFast(NULL);
+
+ Zero(dummy_hash_data, sizeof(dummy_hash_data));
+
+ // Hash payload
+ if (plain == false)
+ {
+ hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, dummy_hash_data, sa->HashSize);
+ Add(payload_list, hash_payload);
+ }
+
+ // Body
+ Add(payload_list, payload);
+
+ // Packet creation
+ ps = IkeNew((plain ? init_cookie : sa->InitiatorCookie), (plain ? resp_cookie : sa->ResponderCookie),
+ IKE_EXCHANGE_TYPE_INFORMATION, false, false, false,
+ GenerateNewMessageId(ike), payload_list);
+
+ if (plain == false)
+ {
+ // Build a temporary packet
+ ps_buf = IkeBuild(ps, NULL);
+
+ // Get the payload after the hash part
+ after_hash_offset = sizeof(IKE_HEADER) + hash_payload->BitArray->Size + sizeof(IKE_COMMON_HEADER);
+ after_hash_size = ((ps_buf->Size > after_hash_offset) ? (ps_buf->Size - after_hash_offset) : 0);
+
+ ps_buf_after_hash = MemToBuf(((UCHAR *)ps_buf->Buf) + after_hash_offset, after_hash_size);
+ FreeBuf(ps_buf);
+
+ // Calculate the hash
+ tmp_buf = NewBuf();
+ WriteBufInt(tmp_buf, ps->MessageId);
+ WriteBufBuf(tmp_buf, ps_buf_after_hash);
+ IkeHMac(sa->TransformSetting.Hash, hash, sa->SKEYID_a, sa->HashSize, tmp_buf->Buf, tmp_buf->Size);
+ FreeBuf(tmp_buf);
+
+ // Overwrite the hash
+ Copy(hash_payload->Payload.Hash.Data->Buf, hash, sa->HashSize);
+
+ ps->FlagEncrypted = true;
+ FreeBuf(ps_buf_after_hash);
+ }
+
+ // Packet reply
+ Zero(&cp, sizeof(cp));
+
+ if (plain == false)
+ {
+ cp.Key = sa->CryptoKey;
+ IkeCalcPhase2InitialIv(cp.Iv, sa, ps->MessageId);
+ }
+
+ ps_buf = IkeBuild(ps, &cp);
+
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ISAKMP, &c->ServerIP, c->ServerPort,
+ &c->ClientIP, c->ClientPort,
+ ps_buf->Buf, ps_buf->Size);
+
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(ps);
+#endif // RAW_DEBUG
+
+ Free(ps_buf);
+
+ IkeFree(ps);
+}
+
+// Information exchange packet reception process
+void ProcIkeInformationalExchangePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header)
+{
+ IKE_CLIENT *c;
+ IKE_SA *ike_sa;
+ // Validate arguments
+ if (ike == NULL || p == NULL || header == NULL || header->InitiatorCookie == 0 || header->ResponderCookie == 0
+ || header->MessageId == 0 || header->FlagEncrypted == false)
+ {
+ return;
+ }
+
+ c = SearchOrCreateNewIkeClientForIkePacket(ike, &p->SrcIP, p->SrcPort, &p->DstIP, p->DestPort, header);
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ ike_sa = FindIkeSaByResponderCookieAndClient(ike, header->ResponderCookie, c);
+
+ if (ike_sa != NULL && ike_sa->Established)
+ {
+ IKE_PACKET *pr;
+ IKE_CRYPTO_PARAM cp;
+
+ // Packet decoding
+ Zero(&cp, sizeof(cp));
+ cp.Key = ike_sa->CryptoKey;
+ IkeCalcPhase2InitialIv(cp.Iv, ike_sa, header->MessageId);
+
+ pr = IkeParse(p->Data, p->Size, &cp);
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(pr);
+#endif // RAW_DEBUG
+ if (pr != NULL)
+ {
+ // Get the hash payload
+ IKE_PACKET_PAYLOAD *hash_payload;
+
+ hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+ if (hash_payload != NULL)
+ {
+ // Get the payload after the hash
+ UINT header_and_hash_size = sizeof(IKE_COMMON_HEADER) + hash_payload->BitArray->Size;
+ void *after_hash_data = ((UCHAR *)pr->DecryptedPayload->Buf) + header_and_hash_size;
+ if (pr->DecryptedPayload->Size > header_and_hash_size)
+ {
+ UINT after_hash_size = pr->DecryptedPayload->Size - header_and_hash_size;
+ UCHAR hash1[IKE_MAX_HASH_SIZE];
+ BUF *hash1_buf;
+
+ hash1_buf = NewBuf();
+ WriteBufInt(hash1_buf, header->MessageId);
+ WriteBuf(hash1_buf, after_hash_data, after_hash_size);
+
+ IkeHMac(ike_sa->TransformSetting.Hash, hash1, ike_sa->SKEYID_a, ike_sa->HashSize,
+ hash1_buf->Buf, hash1_buf->Size);
+
+ // Compare the hash value
+ if (IkeCompareHash(hash_payload, hash1, ike_sa->HashSize))
+ {
+ UINT i, num;
+ // Handle the deletion payload
+ num = IkeGetPayloadNum(pr->PayloadList, IKE_PAYLOAD_DELETE);
+ for (i = 0;i < num;i++)
+ {
+ IKE_PACKET_PAYLOAD *payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_DELETE, i);
+ IKE_PACKET_DELETE_PAYLOAD *del = &payload->Payload.Delete;
+
+ ProcDeletePayload(ike, c, del);
+ }
+ num = IkeGetPayloadNum(pr->PayloadList, IKE_PAYLOAD_NOTICE);
+ // Handle the notification payload
+ for (i = 0;i < num;i++)
+ {
+ IKE_PACKET_PAYLOAD *payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NOTICE, i);
+ IKE_PACKET_NOTICE_PAYLOAD *n = &payload->Payload.Notice;
+
+ if (n->MessageType == IKE_NOTICE_DPD_REQUEST || n->MessageType == IKE_NOTICE_DPD_RESPONSE)
+ {
+ if (n->MessageData != NULL && n->MessageData->Size == sizeof(UINT))
+ {
+ UINT seq_no = READ_UINT(n->MessageData->Buf);
+
+ if (n->Spi->Size == (sizeof(UINT64) * 2))
+ {
+ UINT64 init_cookie = READ_UINT64(((UCHAR *)n->Spi->Buf));
+ UINT64 resp_cookie = READ_UINT64(((UCHAR *)n->Spi->Buf) + sizeof(UINT64));
+
+ if (init_cookie != 0 && resp_cookie != 0)
+ {
+ IKE_SA *found_ike_sa = SearchIkeSaByCookie(ike, init_cookie, resp_cookie);
+
+ if (found_ike_sa != NULL && found_ike_sa->IkeClient == c)
+ {
+ if (n->MessageType == IKE_NOTICE_DPD_REQUEST)
+ {
+ // Return the DPD Response (ACK) for the DPD Request
+ SendInformationalExchangePacket(ike, c,
+ IkeNewNoticeDpdPayload(true, init_cookie, resp_cookie,
+ seq_no));
+ }
+
+ // Update the status of the IKE SA
+ found_ike_sa->LastCommTick = ike->Now;
+ ike_sa->LastCommTick = ike->Now;
+ found_ike_sa->IkeClient->LastCommTick = ike->Now;
+ ike_sa->IkeClient->LastCommTick = ike->Now;
+ ike_sa->IkeClient->CurrentIkeSa = ike_sa;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeBuf(hash1_buf);
+ }
+ }
+
+ IkeFree(pr);
+ }
+ }
+}
+
+// Create a new message ID
+UINT GenerateNewMessageId(IKE_SERVER *ike)
+{
+ UINT ret;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ ret = Rand32();
+
+ if (ret != 0 && ret != 0xffffffff)
+ {
+ UINT i;
+ bool ok = true;
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->MessageId == ret)
+ {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ return ret;
+ }
+ }
+ }
+}
+
+// Start the quick mode
+void StartQuickMode(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ IPSEC_SA_TRANSFORM_SETTING setting;
+ IKE_SA *ike_sa;
+ UINT message_id;
+ UCHAR iv[IKE_MAX_BLOCK_SIZE];
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (IsZero(&c->CachedTransformSetting, sizeof(IPSEC_SA_TRANSFORM_SETTING)))
+ {
+ // Cached transform setting does not exist
+ Debug("Error: c->CachedTransformSetting is not existing.\n");
+ return;
+ }
+
+ ike_sa = c->CurrentIkeSa;
+ if (ike_sa == NULL)
+ {
+ return;
+ }
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_START_QM_FROM_SERVER");
+
+ Copy(&setting, &c->CachedTransformSetting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ message_id = GenerateNewMessageId(ike);
+
+ IkeCalcPhase2InitialIv(iv, ike_sa, message_id);
+
+#ifdef FORCE_LIFETIME_QM
+ setting.LifeSeconds = FORCE_LIFETIME_QM;
+#endif // FORCE_LIFETIME_QM
+
+ if (true)
+ {
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *send_hash_payload;
+ IKE_PACKET_PAYLOAD *send_sa_payload;
+ IKE_PACKET_PAYLOAD *send_proposal_payload;
+ IKE_PACKET_PAYLOAD *send_transform_payload;
+ IKE_PACKET_PAYLOAD *send_rand_payload;
+ IKE_PACKET_PAYLOAD *send_key_payload = NULL;
+ IKE_PACKET_PAYLOAD *send_id_1 = NULL, *send_id_2 = NULL;
+ UINT shared_key_size = 0;
+ UCHAR *shared_key = NULL;
+ BUF *initiator_rand;
+ IPSECSA *ipsec_sa_s_c, *ipsec_sa_c_s;
+ BUF *ps_buf;
+ UINT after_hash_offset, after_hash_size;
+ BUF *ps_buf_after_hash;
+ BUF *tmp_buf;
+ UINT spi;
+ UINT spi_be;
+ UCHAR hash1[IKE_MAX_HASH_SIZE];
+ UCHAR zero = 0;
+ DH_CTX *dh = NULL;
+ UCHAR dummy_hash_data[IKE_MAX_HASH_SIZE];
+
+ initiator_rand = RandBuf(IKE_SA_RAND_SIZE);
+
+ if (setting.Dh != NULL)
+ {
+ // Generate DH
+ dh = IkeDhNewCtx(setting.Dh);
+
+ if (dh != NULL)
+ {
+ send_key_payload = IkeNewDataPayload(IKE_PAYLOAD_KEY_EXCHANGE,
+ dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+ }
+ }
+
+ Zero(dummy_hash_data, sizeof(dummy_hash_data));
+
+ // Dummy hash value
+ payload_list = NewListFast(NULL);
+ send_hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, dummy_hash_data, ike_sa->HashSize);
+ Add(payload_list, send_hash_payload);
+
+ // Determine the SPI
+ spi = GenerateNewIPsecSaSpi(ike, 0);
+ spi_be = Endian32(spi);
+
+ // SA
+ send_transform_payload = TransformSettingToTransformPayloadForIPsec(ike, &setting);
+ send_proposal_payload = IkeNewProposalPayload(1, IKE_PROTOCOL_ID_IPSEC_ESP, &spi_be, sizeof(spi_be),
+ NewListSingle(send_transform_payload));
+ send_sa_payload = IkeNewSaPayload(NewListSingle(send_proposal_payload));
+ Add(payload_list, send_sa_payload);
+
+ // Random number
+ send_rand_payload = IkeNewDataPayload(IKE_PAYLOAD_RAND, initiator_rand->Buf, initiator_rand->Size);
+ Add(payload_list, send_rand_payload);
+
+ // Key exchange
+ if (send_key_payload != NULL)
+ {
+ Add(payload_list, send_key_payload);
+ }
+
+ if (c->SendID1andID2)
+ {
+ // Add the ID payload
+ if (setting.CapsuleMode == IKE_P2_CAPSULE_NAT_TUNNEL_1 || setting.CapsuleMode == IKE_P2_CAPSULE_NAT_TUNNEL_2)
+ {
+ UCHAR zero[32];
+
+ Zero(zero, sizeof(zero));
+
+ // Tunnel Mode
+ send_id_1 = IkeNewIdPayload((IsIP4(&c->ServerIP) ? IKE_ID_IPV4_ADDR_SUBNET : IKE_ID_IPV6_ADDR_SUBNET),
+ 0, 0,
+ zero, (IsIP4(&c->ServerIP) ? 8 : 32));
+
+ send_id_2 = IkeNewIdPayload(c->SendID1_Type,
+ c->SendID1_Protocol, c->SendID1_Port,
+ c->SendID1_Buf->Buf, c->SendID1_Buf->Size);
+ }
+ else
+ {
+ // Transport mode
+ // Specify in the reverse order in which the client has been specified
+ send_id_2 = IkeNewIdPayload(c->SendID1_Type,
+ c->SendID1_Protocol, c->SendID1_Port,
+ c->SendID1_Buf->Buf, c->SendID1_Buf->Size);
+
+ send_id_1 = IkeNewIdPayload(c->SendID2_Type,
+ c->SendID2_Protocol, c->SendID2_Port,
+ c->SendID2_Buf->Buf, c->SendID2_Buf->Size);
+ }
+
+ Add(payload_list, send_id_1);
+ Add(payload_list, send_id_2);
+ }
+
+ if (true)
+ {
+ // NAT-OA payload
+ if (c->SendNatOaDraft1)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA_DRAFT, &c->ServerIP));
+ }
+
+ if (c->SendNatOaDraft2)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA_DRAFT_2, &c->ServerIP));
+ }
+
+ if (c->SendNatOaRfc)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA, &c->ClientIP));
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA, &c->ServerIP));
+ }
+ }
+
+ // Build a packet
+ ps = IkeNew(ike_sa->InitiatorCookie, ike_sa->ResponderCookie, IKE_EXCHANGE_TYPE_QUICK,
+ false, false, false, message_id, payload_list);
+
+ // Build a temporary packet
+ ps_buf = IkeBuild(ps, NULL);
+
+ // Get the payload after the hash part
+ after_hash_offset = sizeof(IKE_HEADER) + send_hash_payload->BitArray->Size + sizeof(IKE_COMMON_HEADER);
+ after_hash_size = ((ps_buf->Size > after_hash_offset) ? (ps_buf->Size - after_hash_offset) : 0);
+
+ ps_buf_after_hash = MemToBuf(((UCHAR *)ps_buf->Buf) + after_hash_offset, after_hash_size);
+ FreeBuf(ps_buf);
+
+ // Calculate the hash #1
+ tmp_buf = NewBuf();
+ WriteBufInt(tmp_buf, message_id);
+ WriteBufBuf(tmp_buf, ps_buf_after_hash);
+ IkeHMac(ike_sa->TransformSetting.Hash, hash1, ike_sa->SKEYID_a, ike_sa->HashSize, tmp_buf->Buf, tmp_buf->Size);
+ FreeBuf(tmp_buf);
+
+ // Overwrite hash #1
+ Copy(send_hash_payload->Payload.Hash.Data->Buf, hash1, ike_sa->HashSize);
+
+ // Create an IPsec SA
+ ipsec_sa_c_s = NewIPsecSa(ike, c, ike_sa, true, message_id, false, iv, spi,
+ initiator_rand->Buf, initiator_rand->Size, NULL, 0,
+ &setting, shared_key, shared_key_size);
+
+ ipsec_sa_s_c = NewIPsecSa(ike, c, ike_sa, true, message_id, true, iv, 0,
+ initiator_rand->Buf, initiator_rand->Size, NULL, 0,
+ &setting, shared_key, shared_key_size);
+
+ ipsec_sa_c_s->PairIPsecSa = ipsec_sa_s_c;
+ ipsec_sa_s_c->PairIPsecSa = ipsec_sa_c_s;
+
+ ipsec_sa_s_c->Dh = dh;
+
+ Insert(ike->IPsecSaList, ipsec_sa_c_s);
+ Insert(ike->IPsecSaList, ipsec_sa_s_c);
+
+ // Packet transmission
+ ps->FlagEncrypted = true;
+ IPsecSaSendPacket(ike, ipsec_sa_s_c, ps);
+ ipsec_sa_s_c->NumResends = 3;
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(ps);
+#endif // RAW_DEBUG
+
+ IkeFree(ps);
+ Free(shared_key);
+ FreeBuf(ps_buf_after_hash);
+ FreeBuf(initiator_rand);
+ }
+}
+
+// Process the quick mode received packet
+void ProcIkeQuickModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header)
+{
+ IKE_CLIENT *c;
+ IKE_SA *ike_sa;
+ // Validate arguments
+ if (ike == NULL || p == NULL || header == NULL || header->InitiatorCookie == 0 || header->ResponderCookie == 0
+ || header->MessageId == 0 || header->FlagEncrypted == false)
+ {
+ return;
+ }
+
+ c = SearchOrCreateNewIkeClientForIkePacket(ike, &p->SrcIP, p->SrcPort, &p->DstIP, p->DestPort, header);
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ ike_sa = FindIkeSaByResponderCookieAndClient(ike, header->ResponderCookie, c);
+
+ if (ike_sa == NULL)
+ {
+ // IKE SA does not exist
+ SendInformationalExchangePacketEx(ike, c, IkeNewNoticeErrorInvalidCookiePayload(header->InitiatorCookie,
+ header->ResponderCookie), true, header->InitiatorCookie, header->ResponderCookie);
+ }
+
+ if (ike_sa != NULL && ike_sa->Established)
+ {
+ // Update the status of the IKE SA
+ ike_sa->LastCommTick = ike->Now;
+ ike_sa->IkeClient->LastCommTick = ike->Now;
+ ike_sa->IkeClient->CurrentIkeSa = ike_sa;
+
+ // Search whether the Message ID is already in the database
+ if (SearchIPsecSaByMessageId(ike, c, header->MessageId) == NULL)
+ {
+ IKE_PACKET *pr;
+ IKE_CRYPTO_PARAM cp;
+
+ // Message ID does not exist. Start a new Quick Mode session
+ Zero(&cp, sizeof(cp));
+ cp.Key = ike_sa->CryptoKey;
+ IkeCalcPhase2InitialIv(cp.Iv, ike_sa, header->MessageId);
+
+ pr = IkeParse(p->Data, p->Size, &cp);
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(pr);
+#endif // RAW_DEBUG
+ if (pr != NULL)
+ {
+ // Get the hash payload
+ IKE_PACKET_PAYLOAD *hash_payload;
+
+ hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+ if (hash_payload != NULL)
+ {
+ // Get the payload after the hash
+ UINT header_and_hash_size = sizeof(IKE_COMMON_HEADER) + hash_payload->BitArray->Size;
+ void *after_hash_data = ((UCHAR *)pr->DecryptedPayload->Buf) + header_and_hash_size;
+ if (pr->DecryptedPayload->Size > header_and_hash_size)
+ {
+ UINT after_hash_size = pr->DecryptedPayload->Size - header_and_hash_size;
+ UCHAR hash1[IKE_MAX_HASH_SIZE];
+ BUF *hash1_buf;
+
+ hash1_buf = NewBuf();
+ WriteBufInt(hash1_buf, header->MessageId);
+ WriteBuf(hash1_buf, after_hash_data, after_hash_size);
+
+ IkeHMac(ike_sa->TransformSetting.Hash, hash1, ike_sa->SKEYID_a, ike_sa->HashSize,
+ hash1_buf->Buf, hash1_buf->Size);
+
+ // Compare the hash value
+ if (IkeCompareHash(hash_payload, hash1, ike_sa->HashSize))
+ {
+ IKE_PACKET_PAYLOAD *sa_payload, *rand_payload, *key_payload, *id_payload_1, *id_payload_2;
+
+ // Get the payload of other
+ sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ rand_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_RAND, 0);
+ key_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_KEY_EXCHANGE, 0);
+ id_payload_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 0);
+ id_payload_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 1);
+
+ if (sa_payload != NULL && rand_payload != NULL)
+ {
+ IPSEC_SA_TRANSFORM_SETTING setting;
+
+ Zero(&setting, sizeof(setting));
+
+ // Interpret the SA payload
+ if (GetBestTransformSettingForIPsecSa(ike, pr, &setting, &p->DstIP) && (GetNumberOfIPsecSaOfIkeClient(ike, c) <= IKE_QUOTA_MAX_SA_PER_CLIENT))
+ {
+ // Appropriate transform setting is selected
+ Debug("P2 Transform: %s %s %s(%u) %u %u\n",
+ (setting.Dh == NULL ? NULL : setting.Dh->Name), setting.Hash->Name, setting.Crypto->Name, setting.CryptoKeySize,
+ setting.LifeKilobytes, setting.LifeSeconds);
+
+#ifdef FORCE_LIFETIME_QM
+ setting.LifeSeconds = FORCE_LIFETIME_QM;
+#endif // FORCE_LIFETIME_QM
+
+ // Cache the transform attribute value
+ Copy(&c->CachedTransformSetting, &setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ // Check the key exchange payload if the PFS is specified
+ if (setting.Dh == NULL || (setting.Dh != NULL && key_payload != NULL &&
+ key_payload->Payload.KeyExchange.Data->Size <= setting.Dh->KeySize))
+ {
+ // Create a payload for response
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *send_hash_payload;
+ IKE_PACKET_PAYLOAD *send_sa_payload;
+ IKE_PACKET_PAYLOAD *send_proposal_payload;
+ IKE_PACKET_PAYLOAD *send_transform_payload;
+ IKE_PACKET_PAYLOAD *send_rand_payload;
+ IKE_PACKET_PAYLOAD *send_key_payload = NULL;
+ IKE_PACKET_PAYLOAD *send_id_1 = NULL, *send_id_2 = NULL;
+ UCHAR dummy_hash_data[IKE_MAX_HASH_SIZE];
+ DH_CTX *dh = NULL;
+ UINT shared_key_size = 0;
+ UCHAR *shared_key = NULL;
+ BUF *initiator_rand, *responder_rand;
+ IPSECSA *ipsec_sa_s_c, *ipsec_sa_c_s;
+ BUF *ps_buf;
+ UINT after_hash_offset, after_hash_size;
+ BUF *ps_buf_after_hash;
+ BUF *tmp_buf;
+ UINT spi;
+ UINT spi_be;
+ UCHAR hash2[IKE_MAX_HASH_SIZE];
+ UCHAR hash3[IKE_MAX_HASH_SIZE];
+ UCHAR zero = 0;
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_START_QM_FROM_CLIENT");
+
+ initiator_rand = CloneBuf(rand_payload->Payload.Rand.Data);
+ responder_rand = RandBuf(IKE_SA_RAND_SIZE);
+
+ if (setting.Dh != NULL)
+ {
+ // Calculate DH
+ dh = IkeDhNewCtx(setting.Dh);
+ shared_key_size = (dh == NULL ? 0 : dh->Size);
+ shared_key = ZeroMalloc(shared_key_size);
+
+ if (DhCompute(dh, shared_key, key_payload->Payload.KeyExchange.Data->Buf, key_payload->Payload.KeyExchange.Data->Size))
+ {
+ // DH calculation success
+ Debug("P2 DH Ok.\n");
+
+ send_key_payload = IkeNewDataPayload(IKE_PAYLOAD_KEY_EXCHANGE,
+ dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+
+ IkeDhFreeCtx(dh);
+ }
+ else
+ {
+ // DH calculation failure
+ Debug("P2 DhCompute failed.\n");
+
+ shared_key = NULL;
+ Free(shared_key);
+ shared_key_size = 0;
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_QM_DH_ERROR");
+ }
+ }
+
+ Zero(dummy_hash_data, sizeof(dummy_hash_data));
+
+ // Dummy hash value
+ payload_list = NewListFast(NULL);
+ send_hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, dummy_hash_data, ike_sa->HashSize);
+ Add(payload_list, send_hash_payload);
+
+ // Determine the SPI
+ spi = GenerateNewIPsecSaSpi(ike, setting.SpiServerToClient);
+ spi_be = Endian32(spi);
+
+ // SA
+ send_transform_payload = TransformSettingToTransformPayloadForIPsec(ike, &setting);
+ send_proposal_payload = IkeNewProposalPayload(1, IKE_PROTOCOL_ID_IPSEC_ESP, &spi_be, sizeof(spi_be),
+ NewListSingle(send_transform_payload));
+ send_sa_payload = IkeNewSaPayload(NewListSingle(send_proposal_payload));
+ Add(payload_list, send_sa_payload);
+
+ // Random number
+ send_rand_payload = IkeNewDataPayload(IKE_PAYLOAD_RAND, responder_rand->Buf, responder_rand->Size);
+ Add(payload_list, send_rand_payload);
+
+ // Key exchange
+ if (send_key_payload != NULL)
+ {
+ Add(payload_list, send_key_payload);
+ }
+
+ // ID
+ if (id_payload_1 != NULL && id_payload_2 != NULL)
+ {
+ send_id_1 = IkeNewIdPayload(id_payload_1->Payload.Id.Type,
+ id_payload_1->Payload.Id.ProtocolId, id_payload_1->Payload.Id.Port,
+ id_payload_1->Payload.Id.IdData->Buf, id_payload_1->Payload.Id.IdData->Size);
+
+ send_id_2 = IkeNewIdPayload(id_payload_2->Payload.Id.Type,
+ id_payload_2->Payload.Id.ProtocolId, id_payload_2->Payload.Id.Port,
+ id_payload_2->Payload.Id.IdData->Buf, id_payload_2->Payload.Id.IdData->Size);
+
+ Add(payload_list, send_id_1);
+ Add(payload_list, send_id_2);
+
+ if (c->SendID1_Buf != NULL)
+ {
+ FreeBuf(c->SendID1_Buf);
+ }
+
+ if (c->SendID2_Buf != NULL)
+ {
+ FreeBuf(c->SendID2_Buf);
+ }
+
+ c->SendID1_Type = id_payload_1->Payload.Id.Type;
+ c->SendID1_Protocol = id_payload_1->Payload.Id.ProtocolId;
+ c->SendID1_Port = id_payload_1->Payload.Id.Port;
+ c->SendID1_Buf = CloneBuf(id_payload_1->Payload.Id.IdData);
+
+ c->SendID2_Type = id_payload_2->Payload.Id.Type;
+ c->SendID2_Protocol = id_payload_2->Payload.Id.ProtocolId;
+ c->SendID2_Port = id_payload_2->Payload.Id.Port;
+ c->SendID2_Buf = CloneBuf(id_payload_2->Payload.Id.IdData);
+
+ c->SendID1andID2 = true;
+ }
+ else
+ {
+ c->SendID1andID2 = false;
+ }
+
+ if (true)
+ {
+ // Reply if NAT-OA payload is presented by the client
+ IKE_PACKET_PAYLOAD *nat_oa_draft1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_OA_DRAFT, 0);
+ IKE_PACKET_PAYLOAD *nat_oa_draft2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_OA_DRAFT_2, 0);
+ IKE_PACKET_PAYLOAD *nat_oa_rfc_0 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_OA, 0);
+ IKE_PACKET_PAYLOAD *nat_oa_rfc_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_OA, 1);
+
+ c->SendNatOaDraft1 = c->SendNatOaDraft2 = c->SendNatOaRfc = false;
+
+ c->ShouldCalcChecksumForUDP = false;
+
+ if (nat_oa_draft1 != NULL)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA_DRAFT, &c->ServerIP));
+ c->SendNatOaDraft1 = true;
+
+ if (IsIP4(&nat_oa_draft1->Payload.NatOa.IpAddress) == IsIP4(&c->ServerIP))
+ {
+ Copy(&c->TransportModeClientIP, &nat_oa_draft1->Payload.NatOa.IpAddress, sizeof(IP));
+ Copy(&c->TransportModeServerIP, &c->ServerIP, sizeof(IP));
+
+ c->ShouldCalcChecksumForUDP = true;
+ }
+ }
+
+ if (nat_oa_draft2 != NULL)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA_DRAFT_2, &c->ServerIP));
+ c->SendNatOaDraft2 = true;
+
+ if (IsIP4(&nat_oa_draft2->Payload.NatOa.IpAddress) == IsIP4(&c->ServerIP))
+ {
+ Copy(&c->TransportModeClientIP, &nat_oa_draft2->Payload.NatOa.IpAddress, sizeof(IP));
+ Copy(&c->TransportModeServerIP, &c->ServerIP, sizeof(IP));
+
+ c->ShouldCalcChecksumForUDP = true;
+ }
+ }
+
+ if (nat_oa_rfc_0 != NULL && nat_oa_rfc_1 != NULL)
+ {
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA, &c->ClientIP));
+ Add(payload_list, IkeNewNatOaPayload(IKE_PAYLOAD_NAT_OA, &c->ServerIP));
+ c->SendNatOaRfc = true;
+
+ if (IsIP4(&nat_oa_rfc_0->Payload.NatOa.IpAddress) == IsIP4(&c->ServerIP))
+ {
+ Copy(&c->TransportModeClientIP, &nat_oa_rfc_0->Payload.NatOa.IpAddress, sizeof(IP));
+ Copy(&c->TransportModeServerIP, &c->ServerIP, sizeof(IP));
+
+ c->ShouldCalcChecksumForUDP = true;
+ }
+ }
+ }
+
+ // Build a packet
+ ps = IkeNew(ike_sa->InitiatorCookie, ike_sa->ResponderCookie, IKE_EXCHANGE_TYPE_QUICK,
+ false, false, false, header->MessageId, payload_list);
+
+ // Build a temporary packet
+ ps_buf = IkeBuild(ps, NULL);
+
+ // Get the payload after the hash part
+ after_hash_offset = sizeof(IKE_HEADER) + send_hash_payload->BitArray->Size + sizeof(IKE_COMMON_HEADER);
+ after_hash_size = ((ps_buf->Size > after_hash_offset) ? (ps_buf->Size - after_hash_offset) : 0);
+
+ ps_buf_after_hash = MemToBuf(((UCHAR *)ps_buf->Buf) + after_hash_offset, after_hash_size);
+ FreeBuf(ps_buf);
+
+ // Calculate the hash #2
+ tmp_buf = NewBuf();
+ WriteBufInt(tmp_buf, header->MessageId);
+ WriteBufBuf(tmp_buf, initiator_rand);
+ WriteBufBuf(tmp_buf, ps_buf_after_hash);
+ IkeHMac(ike_sa->TransformSetting.Hash, hash2, ike_sa->SKEYID_a, ike_sa->HashSize, tmp_buf->Buf, tmp_buf->Size);
+ FreeBuf(tmp_buf);
+
+ // Calculate the hash #3
+ tmp_buf = NewBuf();
+ WriteBuf(tmp_buf, &zero, 1);
+ WriteBufInt(tmp_buf, header->MessageId);
+ WriteBufBuf(tmp_buf, initiator_rand);
+ WriteBufBuf(tmp_buf, responder_rand);
+ IkeHMac(ike_sa->TransformSetting.Hash, hash3, ike_sa->SKEYID_a, ike_sa->HashSize, tmp_buf->Buf, tmp_buf->Size);
+ FreeBuf(tmp_buf);
+
+ // Create an IPsec SA
+ ipsec_sa_c_s = NewIPsecSa(ike, c, ike_sa, false, header->MessageId, false, cp.NextIv, spi,
+ initiator_rand->Buf, initiator_rand->Size, responder_rand->Buf, responder_rand->Size,
+ &setting, shared_key, shared_key_size);
+ ipsec_sa_s_c = NewIPsecSa(ike, c, ike_sa, false, header->MessageId, true, cp.NextIv, setting.SpiServerToClient,
+ initiator_rand->Buf, initiator_rand->Size, responder_rand->Buf, responder_rand->Size,
+ &setting, shared_key, shared_key_size);
+
+ ipsec_sa_c_s->PairIPsecSa = ipsec_sa_s_c;
+ ipsec_sa_s_c->PairIPsecSa = ipsec_sa_c_s;
+
+ Insert(ike->IPsecSaList, ipsec_sa_c_s);
+ Insert(ike->IPsecSaList, ipsec_sa_s_c);
+
+ Copy(ipsec_sa_c_s->Hash3, hash3, ike_sa->HashSize);
+
+ // Overwrite hash #2
+ Copy(send_hash_payload->Payload.Hash.Data->Buf, hash2, ike_sa->HashSize);
+
+ // Packet reply
+ ps->FlagEncrypted = true;
+ IPsecSaSendPacket(ike, ipsec_sa_s_c, ps);
+ IkeSaSendPacket(ike, ike_sa, NULL);
+
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(ps);
+#endif // RAW_DEBUG
+
+ IkeFree(ps);
+ Free(shared_key);
+ FreeBuf(ps_buf_after_hash);
+ FreeBuf(initiator_rand);
+ FreeBuf(responder_rand);
+ }
+ }
+ else
+ {
+ // No appropriate transform setting
+ Debug("No Appropriate Transform was Found.\n");
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_IPSEC_NO_TRANSFORM");
+
+ SendInformationalExchangePacket(ike, c, IkeNewNoticeErrorNoProposalChosenPayload(true, header->InitiatorCookie, header->ResponderCookie));
+ }
+ }
+ }
+ else
+ {
+ Debug("QM-1: Hash 1 is invalid.\n");
+ }
+
+ FreeBuf(hash1_buf);
+ }
+ }
+
+ IkeFree(pr);
+ }
+ }
+ else
+ {
+ // Get the IPsec SA
+ IPSECSA *ipsec_sa_cs = SearchIPsecSaByMessageId(ike, c, header->MessageId);
+ if (ipsec_sa_cs != NULL)
+ {
+ IPSECSA *ipsec_sa_sc = ipsec_sa_cs->PairIPsecSa;
+ if (ipsec_sa_sc != NULL)
+ {
+ if (ipsec_sa_sc->Established == false && ipsec_sa_cs->Established == false)
+ {
+ IKE_PACKET *pr = IPsecSaRecvPacket(ike, ipsec_sa_cs, p->Data, p->Size);
+
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(pr);
+#endif // RAW_DEBUG
+
+ if (pr != NULL)
+ {
+ if (ipsec_sa_cs->Initiated == false)
+ {
+ // Initiator is client-side
+ // Check hash3 payload
+ IKE_PACKET_PAYLOAD *hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+
+ if (hash_payload != NULL)
+ {
+ BUF *hash_buf = hash_payload->Payload.Hash.Data;
+ if (hash_buf != NULL)
+ {
+ if (hash_buf->Size == ipsec_sa_cs->IkeSa->HashSize)
+ {
+ if (Cmp(hash_buf->Buf, ipsec_sa_cs->Hash3, hash_buf->Size) == 0)
+ {
+ ipsec_sa_cs->Established = ipsec_sa_sc->Established = true;
+ ipsec_sa_cs->EstablishedTick = ipsec_sa_sc->EstablishedTick = ike->Now;
+ ipsec_sa_cs->LastCommTick = ipsec_sa_sc->LastCommTick = ike->Now;
+
+ c->CurrentIpSecSaRecv = ipsec_sa_cs;
+ c->CurrentIpSecSaSend = ipsec_sa_sc;
+
+ Debug("IPsec SA 0x%X & 0x%X Established.\n",
+ ipsec_sa_cs->Spi,
+ ipsec_sa_sc->Spi);
+
+ IPsecLog(ike, NULL, NULL, ipsec_sa_sc, "LI_IPSEC_SA_ESTABLISHED");
+
+ IPsecSaSendPacket(ike, ipsec_sa_sc, NULL);
+ }
+ else
+ {
+ Debug("QM-3: Hash 3 is invalid.\n");
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Initiator is server-side
+ // Get hash payload
+ IKE_PACKET_PAYLOAD *hash_payload;
+
+ hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+ if (hash_payload != NULL && ipsec_sa_sc->InitiatorRand != NULL)
+ {
+ // Get the payload after the hash
+ UINT header_and_hash_size = sizeof(IKE_COMMON_HEADER) + hash_payload->BitArray->Size;
+ void *after_hash_data = ((UCHAR *)pr->DecryptedPayload->Buf) + header_and_hash_size;
+ if (pr->DecryptedPayload->Size > header_and_hash_size)
+ {
+ UINT after_hash_size = pr->DecryptedPayload->Size - header_and_hash_size;
+ UCHAR hash2[IKE_MAX_HASH_SIZE];
+ BUF *hash2_buf;
+
+ hash2_buf = NewBuf();
+ WriteBufInt(hash2_buf, header->MessageId);
+ WriteBufBuf(hash2_buf, ipsec_sa_sc->InitiatorRand);
+ WriteBuf(hash2_buf, after_hash_data, after_hash_size);
+
+ IkeHMac(ipsec_sa_sc->SKEYID_Hash, hash2, ipsec_sa_sc->SKEYID_a, ipsec_sa_sc->SKEYID_Hash->HashSize,
+ hash2_buf->Buf, hash2_buf->Size);
+
+ FreeBuf(hash2_buf);
+
+ // Compare the hash value
+ if (IkeCompareHash(hash_payload, hash2, ike_sa->HashSize))
+ {
+ IKE_PACKET_PAYLOAD *sa_payload, *rand_payload, *key_payload, *id_payload_1, *id_payload_2;
+
+ // Get the payload of other
+ sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ rand_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_RAND, 0);
+ key_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_KEY_EXCHANGE, 0);
+ id_payload_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 0);
+ id_payload_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 1);
+
+ if (sa_payload != NULL && rand_payload != NULL)
+ {
+ IPSEC_SA_TRANSFORM_SETTING setting;
+
+ // Interpret the SA payload
+ if (GetBestTransformSettingForIPsecSa(ike, pr, &setting, &p->DstIP))
+ {
+ // Appropriate transform setting is selected
+ Debug("P2 Transform: %s %s %s(%u) %u %u\n",
+ (setting.Dh == NULL ? NULL : setting.Dh->Name), setting.Hash->Name, setting.Crypto->Name, setting.CryptoKeySize,
+ setting.LifeKilobytes, setting.LifeSeconds);
+
+#ifdef FORCE_LIFETIME_QM
+ setting.LifeSeconds = FORCE_LIFETIME_QM;
+#endif // FORCE_LIFETIME_QM
+
+ // Check the key exchange payload if the PFS is specified
+ if (setting.Dh == NULL || (setting.Dh != NULL && key_payload != NULL && ipsec_sa_sc->Dh != NULL &&
+ key_payload->Payload.KeyExchange.Data->Size <= setting.Dh->KeySize))
+ {
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *send_hash_payload;
+ IKE_PACKET_PAYLOAD *send_key_payload = NULL;
+ IKE_PACKET_PAYLOAD *send_id_1 = NULL, *send_id_2 = NULL;
+ DH_CTX *dh = NULL;
+ UINT shared_key_size = 0;
+ UCHAR *shared_key = NULL;
+ BUF *initiator_rand, *responder_rand;
+ BUF *tmp_buf;
+ UCHAR hash3[IKE_MAX_HASH_SIZE];
+ char tmp[MAX_SIZE];
+ UCHAR zero = 0;
+
+ initiator_rand = ipsec_sa_sc->InitiatorRand;
+ responder_rand = CloneBuf(rand_payload->Payload.Rand.Data);
+
+ if (setting.Dh != NULL)
+ {
+ // Calculate DH
+ DH_CTX *dh = ipsec_sa_sc->Dh;
+
+ shared_key_size = (dh == NULL ? 0 : dh->Size);
+ shared_key = ZeroMalloc(shared_key_size);
+
+ if (DhCompute(dh, shared_key, key_payload->Payload.KeyExchange.Data->Buf, key_payload->Payload.KeyExchange.Data->Size))
+ {
+ // DH calculation success
+ Debug("P2 DH Ok.\n");
+ }
+ else
+ {
+ // DH calculation failure
+ Debug("P2 DhCompute failed.\n");
+
+ shared_key = NULL;
+ Free(shared_key);
+ shared_key_size = 0;
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_QM_DH_ERROR");
+ }
+ }
+
+ // Update the information of IPsec SA
+ if (shared_key != NULL)
+ {
+ ipsec_sa_sc->SharedKey = NewBuf(shared_key, shared_key_size);
+ ipsec_sa_cs->SharedKey = NewBuf(shared_key, shared_key_size);
+ }
+
+ ipsec_sa_sc->Spi = setting.SpiServerToClient;
+ IPsecLog(ike, NULL, NULL, ipsec_sa_sc, "LI_IPSEC_SA_SPI_SET", ipsec_sa_sc->Spi);
+ ike->IPsecSaList->sorted = false;
+
+ ipsec_sa_sc->ResponderRand = CloneBuf(responder_rand);
+ ipsec_sa_cs->ResponderRand = CloneBuf(responder_rand);
+
+ Copy(&ipsec_sa_sc->TransformSetting, &setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+ Copy(&ipsec_sa_cs->TransformSetting, &setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ ipsec_sa_sc->Established = true;
+ ipsec_sa_cs->Established = true;
+
+ IPsecLog(ike, NULL, NULL, ipsec_sa_sc, "LI_IPSEC_SA_ESTABLISHED");
+
+ ipsec_sa_sc->LastCommTick = ike->Now;
+ ipsec_sa_cs->LastCommTick = ike->Now;
+
+ c->CurrentIpSecSaRecv = ipsec_sa_cs;
+ c->CurrentIpSecSaSend = ipsec_sa_sc;
+
+ // Calculate the KEYMAT
+ IPsecCalcKeymat(ike, ipsec_sa_sc->SKEYID_Hash, ipsec_sa_sc->KeyMat, sizeof(ipsec_sa_sc->KeyMat),
+ ipsec_sa_sc->SKEYID_d, ipsec_sa_sc->SKEYID_Hash->HashSize, IKE_PROTOCOL_ID_IPSEC_ESP,
+ ipsec_sa_sc->Spi, initiator_rand->Buf, initiator_rand->Size,
+ responder_rand->Buf, responder_rand->Size,
+ shared_key, shared_key_size);
+
+ IPsecCalcKeymat(ike, ipsec_sa_cs->SKEYID_Hash, ipsec_sa_cs->KeyMat, sizeof(ipsec_sa_cs->KeyMat),
+ ipsec_sa_cs->SKEYID_d, ipsec_sa_cs->SKEYID_Hash->HashSize, IKE_PROTOCOL_ID_IPSEC_ESP,
+ ipsec_sa_cs->Spi, initiator_rand->Buf, initiator_rand->Size,
+ responder_rand->Buf, responder_rand->Size,
+ shared_key, shared_key_size);
+
+ IkeFreeKey(ipsec_sa_sc->CryptoKey);
+ IkeFreeKey(ipsec_sa_cs->CryptoKey);
+
+ ipsec_sa_sc->CryptoKey = IkeNewKey(setting.Crypto, ipsec_sa_sc->KeyMat, setting.CryptoKeySize);
+ ipsec_sa_cs->CryptoKey = IkeNewKey(setting.Crypto, ipsec_sa_cs->KeyMat, setting.CryptoKeySize);
+
+ Copy(ipsec_sa_sc->HashKey, ipsec_sa_sc->KeyMat + setting.CryptoKeySize, setting.Hash->HashSize);
+ Copy(ipsec_sa_cs->HashKey, ipsec_sa_cs->KeyMat + setting.CryptoKeySize, setting.Hash->HashSize);
+
+ BinToStrEx(tmp, sizeof(tmp), ipsec_sa_sc->KeyMat, ipsec_sa_sc->TransformSetting.CryptoKeySize);
+ Debug(" KEYMAT (SC): %s\n", tmp);
+
+ BinToStrEx(tmp, sizeof(tmp), ipsec_sa_cs->KeyMat, ipsec_sa_cs->TransformSetting.CryptoKeySize);
+ Debug(" KEYMAT (CS): %s\n", tmp);
+
+ Debug("IPsec SA 0x%X & 0x%X Established (Server is Initiator).\n",
+ ipsec_sa_cs->Spi,
+ ipsec_sa_sc->Spi);
+
+ // Calculate the hash #3
+ tmp_buf = NewBuf();
+ WriteBuf(tmp_buf, &zero, 1);
+ WriteBufInt(tmp_buf, header->MessageId);
+ WriteBufBuf(tmp_buf, initiator_rand);
+ WriteBufBuf(tmp_buf, responder_rand);
+ IkeHMac(ipsec_sa_cs->SKEYID_Hash, hash3, ipsec_sa_cs->SKEYID_a, ipsec_sa_cs->SKEYID_Hash->HashSize, tmp_buf->Buf, tmp_buf->Size);
+ FreeBuf(tmp_buf);
+
+ // Return the hash #3
+ send_hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, hash3, ipsec_sa_cs->SKEYID_Hash->HashSize);
+
+ payload_list = NewListSingle(send_hash_payload);
+ ps = IkeNew(ike_sa->InitiatorCookie, ike_sa->ResponderCookie,
+ IKE_EXCHANGE_TYPE_QUICK, true, false, false, header->MessageId, payload_list);
+
+ IPsecSaSendPacket(ike, ipsec_sa_sc, ps);
+#ifdef RAW_DEBUG
+ IkeDebugUdpSendRawPacket(ps);
+#endif // RAW_DEBUG
+ ipsec_sa_sc->NumResends = 3;
+
+ if (false)
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa != ipsec_sa_sc && sa != ipsec_sa_cs)
+ {
+ MarkIPsecSaAsDeleted(ike, sa);
+ }
+ }
+ }
+
+ IkeFree(ps);
+
+ // Release the memory
+ FreeBuf(responder_rand);
+ }
+ }
+ else
+ {
+ // No appropriate transform setting
+ Debug("No Appropriate Transform was Found.\n");
+
+ IPsecLog(ike, NULL, ike_sa, NULL, "LI_IPSEC_NO_TRANSFORM");
+
+ SendInformationalExchangePacket(ike, c, IkeNewNoticeErrorNoProposalChosenPayload(true, header->InitiatorCookie, header->ResponderCookie));
+ }
+ }
+ }
+ }
+ }
+ }
+ IkeFree(pr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Calculate the KEYMAT
+void IPsecCalcKeymat(IKE_SERVER *ike, IKE_HASH *h, void *dst, UINT dst_size, void *skeyid_d_data, UINT skeyid_d_size, UCHAR protocol, UINT spi, void *rand_init_data, UINT rand_init_size,
+ void *rand_resp_data, UINT rand_resp_size, void *df_key_data, UINT df_key_size)
+{
+ BUF *k;
+ BUF *ret;
+ // Validate arguments
+ if (ike == NULL || dst == NULL || h == NULL || rand_init_data == NULL || rand_resp_data == NULL||
+ (df_key_size != 0 && df_key_data == NULL))
+ {
+ return;
+ }
+
+ ret = NewBuf();
+
+ k = NULL;
+
+ while (true)
+ {
+ BUF *tmp = NewBuf();
+ UCHAR hash[IKE_MAX_HASH_SIZE];
+
+ if (k != NULL)
+ {
+ WriteBufBuf(tmp, k);
+ }
+
+ if (df_key_data != NULL)
+ {
+ WriteBuf(tmp, df_key_data, df_key_size);
+ }
+
+ WriteBuf(tmp, &protocol, 1);
+
+ WriteBufInt(tmp, spi);
+
+ WriteBuf(tmp, rand_init_data, rand_init_size);
+ WriteBuf(tmp, rand_resp_data, rand_resp_size);
+
+ if (k != NULL)
+ {
+ FreeBuf(k);
+ }
+
+ IkeHMac(h, hash, skeyid_d_data, skeyid_d_size, tmp->Buf, tmp->Size);
+
+ FreeBuf(tmp);
+
+ k = MemToBuf(hash, h->HashSize);
+
+ WriteBufBuf(ret, k);
+
+ if (ret->Size >= dst_size)
+ {
+ break;
+ }
+ }
+
+ Copy(dst, ret->Buf, dst_size);
+
+ FreeBuf(ret);
+ FreeBuf(k);
+}
+
+// Search for IPsec SA from Message ID
+IPSECSA *SearchIPsecSaByMessageId(IKE_SERVER *ike, IKE_CLIENT *c, UINT message_id)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || c == NULL || message_id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ if (sa->MessageId == message_id)
+ {
+ if (sa->ServerToClient == false)
+ {
+ if (sa->Established == false)
+ {
+ return sa;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Search for IPsec SA from SPI value
+IPSECSA *SearchClientToServerIPsecSaBySpi(IKE_SERVER *ike, UINT spi)
+{
+ IPSECSA t;
+ // Validate arguments
+ if (ike == NULL || spi == 0)
+ {
+ return NULL;
+ }
+
+ t.ServerToClient = false;
+ t.Spi = spi;
+
+ return Search(ike->IPsecSaList, &t);
+}
+IPSECSA *SearchIPsecSaBySpi(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || c == NULL || spi == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->Spi == spi)
+ {
+ if (sa->IkeClient == c)
+ {
+ return sa;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Search an IKE SA from the value of the Cookie
+IKE_SA *SearchIkeSaByCookie(IKE_SERVER *ike, UINT64 init_cookie, UINT64 resp_cookie)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->InitiatorCookie == init_cookie && sa->ResponderCookie == resp_cookie)
+ {
+ return sa;
+ }
+ }
+
+ return NULL;
+}
+
+// Generate the SPI value of new IPsec SA
+UINT GenerateNewIPsecSaSpi(IKE_SERVER *ike, UINT counterpart_spi)
+{
+ UINT ret;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ ret = Rand32();
+
+ if (ret != counterpart_spi)
+ {
+ if (ret >= 4096 && ret != INFINITE)
+ {
+ if (SearchClientToServerIPsecSaBySpi(ike, ret) == NULL)
+ {
+ return ret;
+ }
+ }
+ }
+ }
+}
+
+// Calculate the initial IV for Phase 2
+void IkeCalcPhase2InitialIv(void *iv, IKE_SA *sa, UINT message_id)
+{
+ BUF *b;
+ UCHAR hash[IKE_MAX_HASH_SIZE];
+ // Validate arguments
+ if (iv == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ message_id = Endian32(message_id);
+
+ b = NewBuf();
+ WriteBuf(b, sa->Iv, sa->BlockSize);
+ WriteBuf(b, &message_id, sizeof(UINT));
+
+ IkeHash(sa->TransformSetting.Hash, hash, b->Buf, b->Size);
+
+ Copy(iv, hash, sa->TransformSetting.Crypto->BlockSize);
+
+ FreeBuf(b);
+}
+
+// Create a new IPsec SA
+IPSECSA *NewIPsecSa(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, bool initiate, UINT message_id, bool server_to_client, void *iv, UINT spi, void *init_rand_data, UINT init_rand_size, void *res_rand_data, UINT res_rand_size, IPSEC_SA_TRANSFORM_SETTING *setting, void *shared_key_data, UINT shared_key_size)
+{
+ IPSECSA *sa;
+ char tmp[MAX_SIZE];
+ UINT total_key_size;
+ // Validate arguments
+ if (ike == NULL || c == NULL || ike_sa == NULL || message_id == 0 || iv == NULL || setting == NULL ||
+ (shared_key_data == NULL && shared_key_size != 0))
+ {
+ return NULL;
+ }
+
+ sa = ZeroMalloc(sizeof(IPSECSA));
+
+ if (server_to_client == false)
+ {
+ ike->CurrentIPsecSaId++;
+ }
+ sa->Id = ike->CurrentIPsecSaId;
+
+ sa->IkeClient = c;
+ sa->IkeSa = ike_sa;
+
+ sa->MessageId = message_id;
+ sa->FirstCommTick = ike->Now;
+ sa->LastCommTick = ike->Now;
+ sa->Initiated = initiate;
+
+ sa->ServerToClient = server_to_client;
+
+ sa->Spi = spi;
+
+ sa->SKEYID_Hash = ike_sa->TransformSetting.Hash;
+ Copy(sa->SKEYID_a, ike_sa->SKEYID_a, sa->SKEYID_Hash->HashSize);
+ Copy(sa->SKEYID_d, ike_sa->SKEYID_d, sa->SKEYID_Hash->HashSize);
+
+ sa->InitiatorRand = MemToBuf(init_rand_data, init_rand_size);
+
+ if (initiate == false)
+ {
+ sa->ResponderRand = MemToBuf(res_rand_data, res_rand_size);
+ }
+
+ Copy(sa->Iv, iv, ike_sa->BlockSize);
+
+ Copy(&sa->TransformSetting, setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ if (shared_key_data != NULL)
+ {
+ sa->SharedKey = MemToBuf(shared_key_data, shared_key_size);
+ }
+
+ total_key_size = sa->TransformSetting.CryptoKeySize + sa->TransformSetting.Hash->HashSize;
+
+ if (initiate == false)
+ {
+ IPsecCalcKeymat(ike, ike_sa->TransformSetting.Hash, sa->KeyMat, total_key_size,
+ ike_sa->SKEYID_d, ike_sa->HashSize, IKE_PROTOCOL_ID_IPSEC_ESP, spi, sa->InitiatorRand->Buf,
+ sa->InitiatorRand->Size, sa->ResponderRand->Buf, sa->ResponderRand->Size,
+ shared_key_data, shared_key_size);
+
+ sa->CryptoKey = IkeNewKey(sa->TransformSetting.Crypto, sa->KeyMat, sa->TransformSetting.CryptoKeySize);
+
+ Copy(sa->HashKey, sa->KeyMat + sa->TransformSetting.CryptoKeySize, sa->TransformSetting.Hash->HashSize);
+ }
+
+ Debug("New IPsec SA (StoC = %u): 0x%X 0x%X (%s %s %s(%u) %u %u)\n",
+ sa->ServerToClient,
+ sa->MessageId,
+ sa->Spi,
+ (setting->Dh == NULL ? NULL : setting->Dh->Name), setting->Hash->Name, setting->Crypto->Name, setting->CryptoKeySize,
+ setting->LifeKilobytes, setting->LifeSeconds);
+
+ IPsecLog(ike, c, NULL, sa, "LI_NEW_IPSEC_SA",
+ (sa->ServerToClient ? _UU("LI_TAG_SERVER_TO_CLIENT") : _UU("LI_TAG_CLIENT_TO_SERVER")),
+ sa->Spi,
+ (setting->Dh == NULL ? NULL : setting->Dh->Name), setting->Hash->Name, setting->Crypto->Name, setting->CryptoKeySize * 8,
+ setting->LifeKilobytes, setting->LifeSeconds);
+
+ Rand(sa->EspIv, sizeof(sa->EspIv));
+
+ if (initiate == false)
+ {
+ BinToStrEx(tmp, sizeof(tmp), sa->KeyMat, sa->TransformSetting.CryptoKeySize);
+ Debug(" KEYMAT: %s\n", tmp);
+ }
+
+ // Set the expiration time
+ if (setting->LifeSeconds != 0)
+ {
+ UINT64 span = (UINT64)(setting->LifeSeconds * 1000) + (UINT64)IKE_SOFT_EXPIRES_MARGIN;
+ sa->ExpiresHardTick = ike->Now + span;
+ sa->ExpiresSoftTick = ike->Now + span;
+ //sa->ExpiresSoftTick = ike->Now + (UINT64)5000;
+
+ AddInterrupt(ike->Interrupts, sa->ExpiresSoftTick);
+ }
+
+ return sa;
+}
+
+// Treat aggressive mode packet reception
+void ProcIkeAggressiveModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header)
+{
+ IKE_CLIENT *c;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ike == NULL || p == NULL || header == NULL || header->InitiatorCookie == 0)
+ {
+ return;
+ }
+
+ c = SearchOrCreateNewIkeClientForIkePacket(ike, &p->SrcIP, p->SrcPort, &p->DstIP, p->DestPort, header);
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (header->ResponderCookie == 0)
+ {
+ // Start process of the state 1
+ IKE_CAPS caps;
+ IKE_SA *sa;
+ IKE_PACKET *pr = IkeParse(p->Data, p->Size, NULL);
+
+ if (pr != NULL)
+ {
+ // Determine the CAPS
+ IkeCheckCaps(&caps, pr);
+ if (caps.MS_L2TPIPSecVPNClient || caps.MS_NT5_ISAKMP_OAKLEY || caps.MS_Vid_InitialContact)
+ {
+ c->IsMicrosoft = true;
+ }
+
+ if ((caps.NatTraversalDraftIetf || caps.NatTraversalRfc3947) || (IsUdpPortOpened(ike->IPsec->UdpListener, &p->DstIP, IPSEC_PORT_IPSEC_ESP_RAW)))
+ {
+ sa = FindIkeSaByEndPointAndInitiatorCookie(ike, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, header->InitiatorCookie, IKE_SA_AGRESSIVE_MODE);
+
+ if (sa == NULL)
+ {
+ // Check whether there is acceptable SA parameters by analyzing proposed parameters
+ IKE_SA_TRANSFORM_SETTING setting;
+
+ if (GetBestTransformSettingForIkeSa(ike, pr, &setting) && (GetNumberOfIkeSaOfIkeClient(ike, c) <= IKE_QUOTA_MAX_SA_PER_CLIENT))
+ {
+ IKE_PACKET_PAYLOAD *tp;
+ IKE_PACKET_PAYLOAD *pp;
+ IKE_PACKET_PAYLOAD *sap;
+ IKE_PACKET_PAYLOAD *client_sa_payload;
+ IKE_PACKET_PAYLOAD *your_key_payload;
+ IKE_PACKET_PAYLOAD *your_rand_payload;
+ IKE_PACKET_PAYLOAD *your_id_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 0);
+
+ // Appropriate transform setting is selected
+ Debug("P1 Transform: %s %s %s(%u) %u %u\n",
+ setting.Dh->Name, setting.Hash->Name, setting.Crypto->Name, setting.CryptoKeySize,
+ setting.LifeKilobytes, setting.LifeSeconds);
+
+ // Receive a key exchange packet
+ your_key_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_KEY_EXCHANGE, 0);
+ your_rand_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_RAND, 0);
+ if (your_key_payload != NULL && your_rand_payload != NULL && your_id_payload != NULL)
+ {
+ // Check the key payload
+ BUF *your_key_buf = your_key_payload->Payload.KeyExchange.Data;
+ BUF *your_rand_buf = your_rand_payload->Payload.Rand.Data;
+
+ // DH generation
+ DH_CTX *dh = IkeDhNewCtx(setting.Dh);
+ UINT shared_key_size = (dh == NULL ? 0 : dh->Size);
+ UCHAR *shared_key = ZeroMalloc(shared_key_size);
+
+ // DH calculation
+ if (DhCompute(dh, shared_key, your_key_buf->Buf, your_key_buf->Size))
+ {
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *my_key_payload;
+ IKE_PACKET_PAYLOAD *my_rand_payload;
+ BUF *nat_buf1, *nat_buf2;
+ BUF *iv_buf;
+ UCHAR iv_hashed_data[IKE_MAX_HASH_SIZE];
+ UCHAR initiator_hash[IKE_MAX_HASH_SIZE];
+ BUF *b;
+ IKE_PACKET_PAYLOAD *my_id_payload, *my_hash_payload;
+ UCHAR responder_hash[IKE_MAX_HASH_SIZE];
+ BUF *idir_b;
+ IKE_PACKET_PAYLOAD *your_nat_d_1 = NULL;
+ IKE_PACKET_PAYLOAD *your_nat_d_2 = NULL;
+
+ // Create an IKE SA
+ sa = NewIkeSa(ike, c, header->InitiatorCookie, IKE_SA_AGRESSIVE_MODE, &setting);
+ Copy(&sa->Caps, &caps, sizeof(IKE_CAPS));
+ sa->State= IKE_SA_AM_STATE_1_SA;
+ Insert(ike->IkeSaList, sa);
+
+ sa->HashSize = sa->TransformSetting.Hash->HashSize;
+ sa->KeySize = sa->TransformSetting.CryptoKeySize;
+ sa->BlockSize = sa->TransformSetting.Crypto->BlockSize;
+
+ // Get the Caps additionally
+ if (sa->Caps.NatTraversalRfc3947)
+ {
+ sa->Caps.UsingNatTraversalRfc3947 = true;
+
+ your_nat_d_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D, 0);
+ your_nat_d_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D, 1);
+ }
+ else if (sa->Caps.NatTraversalDraftIetf)
+ {
+ sa->Caps.UsingNatTraversalDraftIetf = true;
+
+ your_nat_d_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D_DRAFT, 0);
+ your_nat_d_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D_DRAFT, 1);
+ }
+
+ // Calculation success
+ sa->DhSharedKey = MemToBuf(shared_key, shared_key_size);
+ sa->InitiatorRand = RandBuf(IKE_SA_RAND_SIZE);
+ sa->ResponderRand = CloneBuf(your_rand_buf);
+
+ // Save a bit array of SA payload presented by the client
+ client_sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ sa->SAi_b = CloneBuf(client_sa_payload->BitArray);
+
+ // Save the ID payload presented by the client
+ sa->YourIDPayloadForAM = CloneBuf(your_id_payload->BitArray);
+
+ //// Assemble the SA payload
+ // Construct transform payload
+ tp = TransformSettingToTransformPayloadForIke(ike, &setting);
+
+ // Build a proposal payload
+ pp = IkeNewProposalPayload(1, IKE_PROTOCOL_ID_IKE, NULL, 0, NewListSingle(tp));
+
+ // Build the SA payload
+ sap = IkeNewSaPayload(NewListSingle(pp));
+
+ payload_list = NewListSingle(sap);
+
+ // Send a key exchange packet
+ my_key_payload = IkeNewDataPayload(IKE_PAYLOAD_KEY_EXCHANGE, dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+ my_rand_payload = IkeNewDataPayload(IKE_PAYLOAD_RAND, sa->InitiatorRand->Buf, sa->InitiatorRand->Size);
+
+ Add(payload_list, my_key_payload);
+ Add(payload_list, my_rand_payload);
+
+ // NAT-D Packet
+ // Address of the opponent. Randomize in order to be forced to use NAT
+ nat_buf1 = IkeCalcNatDetectHash(ike, sa->TransformSetting.Hash, Rand64(), Rand64(), &c->ClientIP, Rand16());
+
+ // My address
+ if (c->IsMicrosoft == false || (your_nat_d_1 == NULL || your_nat_d_2 == NULL || your_nat_d_1->BitArray == NULL))
+ {
+ // Calculate exactly
+ nat_buf2 = IkeCalcNatDetectHash(ike, sa->TransformSetting.Hash,
+ sa->InitiatorCookie, sa->ResponderCookie, &c->ServerIP, c->ServerPort);
+ }
+ else
+ {
+ // Parrot the NAT_D payload indicating myself I got from
+ // the other if it has connected from a Microsoft VPN Client
+ nat_buf2 = CloneBuf(your_nat_d_1->BitArray);
+ }
+
+ // Save DH information
+ sa->GXi = CloneBuf(your_key_buf);
+ sa->GXr = CloneBuf(dh->MyPublicKey);
+
+ // Calculate the key set
+ IkeCalcSaKeySet(ike, sa, NULL);
+
+ // Calculate the initiator side hash value
+ b = NewBuf();
+ WriteBufBuf(b, sa->GXi);
+ WriteBufBuf(b, sa->GXr);
+ WriteBufInt64(b, sa->InitiatorCookie);
+ WriteBufInt64(b, sa->ResponderCookie);
+ WriteBufBuf(b, sa->SAi_b);
+ WriteBufBuf(b, sa->YourIDPayloadForAM);
+
+ IkeHMac(sa->TransformSetting.Hash, initiator_hash, sa->SKEYID, sa->HashSize,
+ b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Copy(sa->InitiatorHashForAM, initiator_hash, sa->HashSize);
+
+ // Prepare the response ID payload
+ // Generate the ID payload
+ if (IsIP6(&sa->IkeClient->ServerIP))
+ {
+ // IPv6 address
+ my_id_payload = IkeNewIdPayload(IKE_ID_IPV6_ADDR, 0, 0, sa->IkeClient->ServerIP.ipv6_addr, 16);
+ }
+ else
+ {
+ // IPv4 address
+ my_id_payload = IkeNewIdPayload(IKE_ID_IPV4_ADDR, 0, 0, sa->IkeClient->ServerIP.addr, 4);
+ }
+
+ // Build the ID payload tentatively
+ idir_b = IkeBuildIdPayload(&my_id_payload->Payload.Id);
+
+ b = NewBuf();
+ WriteBufBuf(b, sa->GXr);
+ WriteBufBuf(b, sa->GXi);
+ WriteBufInt64(b, sa->ResponderCookie);
+ WriteBufInt64(b, sa->InitiatorCookie);
+ WriteBufBuf(b, sa->SAi_b);
+ WriteBufBuf(b, idir_b);
+
+ IkeHMac(sa->TransformSetting.Hash, responder_hash, sa->SKEYID, sa->HashSize,
+ b->Buf, b->Size);
+
+ FreeBuf(b);
+ FreeBuf(idir_b);
+
+ my_hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, responder_hash, sa->HashSize);
+
+ Add(payload_list, my_id_payload);
+ Add(payload_list, my_hash_payload);
+
+ ps = IkeNew(sa->InitiatorCookie, sa->ResponderCookie, IKE_EXCHANGE_TYPE_AGGRESSIVE,
+ false, false, false, 0, payload_list);
+
+ // Add the vendor ID
+ IkeAddVendorIdPayloads(ps);
+
+ // NAT-D related
+ if (sa->Caps.UsingNatTraversalRfc3947)
+ {
+ // RFC-compliant
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D, nat_buf1->Buf, nat_buf1->Size));
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D, nat_buf2->Buf, nat_buf2->Size));
+ }
+
+ if (sa->Caps.UsingNatTraversalDraftIetf)
+ {
+ // Draft compliant
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D_DRAFT, nat_buf1->Buf, nat_buf1->Size));
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D_DRAFT, nat_buf2->Buf, nat_buf2->Size));
+ }
+
+ FreeBuf(nat_buf1);
+ FreeBuf(nat_buf2);
+
+ StrCpy(c->ClientId, sizeof(c->ClientId), your_id_payload->Payload.Id.StrData);
+ Debug("Client ID = %s\n", c->ClientId);
+
+ IPsecLog(ike, c, NULL, NULL, NULL, "LI_SET_CLIENT_ID", c->ClientId);
+
+ // Initial IV setting
+ iv_buf = NewBuf();
+ WriteBuf(iv_buf, your_key_buf->Buf, your_key_buf->Size);
+ WriteBuf(iv_buf, dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+ IkeHash(sa->TransformSetting.Hash, iv_hashed_data, iv_buf->Buf, iv_buf->Size);
+
+ BinToStrEx(tmp, sizeof(tmp), iv_hashed_data, sa->BlockSize);
+ Debug("Initial IV: %s\n", tmp);
+
+ IkeSaUpdateIv(sa, iv_hashed_data, sa->HashSize);
+
+ FreeBuf(iv_buf);
+
+ // Transmission
+ IkeSaSendPacket(ike, sa, ps);
+
+ IkeFree(ps);
+ }
+ else
+ {
+ // DH calculation failure
+ Debug("DhCompute failed.\n");
+ }
+
+ Free(shared_key);
+ DhFree(dh);
+ }
+ }
+ else
+ {
+ // No appropriate transform setting
+ Debug("No Appropriate Transform was Found.\n");
+
+ IPsecLog(ike, c, NULL, NULL, "LI_IKE_NO_TRANSFORM");
+
+ SendInformationalExchangePacket(ike, c, IkeNewNoticeErrorNoProposalChosenPayload(false, header->InitiatorCookie, header->ResponderCookie));
+ }
+ }
+ }
+ else
+ {
+ // Client does not support NAT Traversal
+ Debug("Client doesn't support NAT-T.\n");
+
+ IPsecLog(ike, c, NULL, NULL, "LI_IKE_NO_NAT_T");
+ }
+
+ IkeFree(pr);
+ }
+ }
+ else
+ {
+ // Process of state 2
+ IKE_SA *sa;
+
+ sa = FindIkeSaByResponderCookieAndClient(ike, header->ResponderCookie, c);
+
+ if (sa == NULL)
+ {
+ SendInformationalExchangePacketEx(ike, c, IkeNewNoticeErrorInvalidCookiePayload(header->InitiatorCookie,
+ header->ResponderCookie), true, header->InitiatorCookie, header->ResponderCookie);
+ }
+
+ if (sa != NULL && sa->Mode == IKE_SA_AGRESSIVE_MODE)
+ {
+ IKE_PACKET *pr = NULL;
+
+ sa->LastCommTick = ike->Now;
+
+ switch (sa->State)
+ {
+ case IKE_SA_AM_STATE_1_SA:
+ pr = IkeSaRecvPacket(ike, sa, p->Data, p->Size);
+ if (pr != NULL)
+ {
+ IKE_PACKET_PAYLOAD *your_hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+
+ if (your_hash_payload != NULL)
+ {
+ // Compare the hash
+ if (IkeCompareHash(your_hash_payload, sa->InitiatorHashForAM, sa->HashSize))
+ {
+ // Transit to the established state
+ Debug("IKE SA 0x%X Established.\n", sa);
+ sa->State = IKE_SA_AM_STATE_2_ESTABLISHED;
+ sa->EstablishedTick = ike->Now;
+ sa->Established = true;
+ c->CurrentIkeSa = sa;
+ c->NextDpdSendTick = ike->Now + (UINT64)IKE_INTERVAL_DPD_KEEPALIVE;
+ StrCpy(c->Secret, sizeof(c->Secret), sa->Secret);
+
+ IPsecLog(ike, NULL, sa, NULL, "LI_IKE_SA_ESTABLISHED");
+
+ IkeSaSendPacket(ike, sa, NULL);
+ }
+ else
+ {
+ Debug("IKE SA 0x%X Invalid Hash.\n", sa);
+ }
+ }
+ }
+ break;
+ }
+
+ if (pr != NULL)
+ {
+ IkeFree(pr);
+ }
+ }
+ }
+}
+
+// Process of the main mode packet reception
+void ProcIkeMainModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header)
+{
+ IKE_CLIENT *c;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ike == NULL || p == NULL || header == NULL || header->InitiatorCookie == 0)
+ {
+ return;
+ }
+
+ c = SearchOrCreateNewIkeClientForIkePacket(ike, &p->SrcIP, p->SrcPort, &p->DstIP, p->DestPort, header);
+
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (header->ResponderCookie == 0)
+ {
+ // Start process of the state 1
+ IKE_CAPS caps;
+ IKE_SA *sa;
+ IKE_PACKET *pr = IkeParse(p->Data, p->Size, NULL);
+
+ if (pr != NULL)
+ {
+ // Determine the CAPS
+ IkeCheckCaps(&caps, pr);
+ if (caps.MS_L2TPIPSecVPNClient || caps.MS_NT5_ISAKMP_OAKLEY || caps.MS_Vid_InitialContact)
+ {
+ c->IsMicrosoft = true;
+ }
+
+ if ((caps.NatTraversalDraftIetf || caps.NatTraversalRfc3947) || (IsUdpPortOpened(ike->IPsec->UdpListener, &p->DstIP, IPSEC_PORT_IPSEC_ESP_RAW)))
+ {
+ sa = FindIkeSaByEndPointAndInitiatorCookie(ike, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, header->InitiatorCookie, IKE_SA_MAIN_MODE);
+
+ if (sa == NULL)
+ {
+ // Check whether there is acceptable SA parameters by analyzing proposed parameters
+ IKE_SA_TRANSFORM_SETTING setting;
+
+ if (GetBestTransformSettingForIkeSa(ike, pr, &setting) && (GetNumberOfIkeSaOfIkeClient(ike, c) <= IKE_QUOTA_MAX_SA_PER_CLIENT))
+ {
+ IKE_PACKET *ps;
+ IKE_PACKET_PAYLOAD *tp;
+ IKE_PACKET_PAYLOAD *pp;
+ IKE_PACKET_PAYLOAD *sap;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *client_sa_payload;
+
+ // Appropriate transform setting is selected
+ Debug("P1 Transform: %s %s %s(%u) %u %u\n",
+ setting.Dh->Name, setting.Hash->Name, setting.Crypto->Name, setting.CryptoKeySize,
+ setting.LifeKilobytes, setting.LifeSeconds);
+
+#ifdef FORCE_LIFETIME_MM
+ setting.LifeSeconds = FORCE_LIFETIME_MM;
+#endif // FORCE_LIFETIME_MM
+
+ // Create an IKE SA
+ sa = NewIkeSa(ike, c, header->InitiatorCookie, IKE_SA_MAIN_MODE, &setting);
+
+ Copy(&sa->Caps, &caps, sizeof(IKE_CAPS));
+
+ Insert(ike->IkeSaList, sa);
+
+ // Answer the SA parameter selection results
+ sa->State = IKE_SA_MM_STATE_1_SA;
+
+ // Save a bit array of SA payload presented by the client
+ client_sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ sa->SAi_b = CloneBuf(client_sa_payload->BitArray);
+
+ //// Assemble the SA payload
+ // Construct a transform payload
+ tp = TransformSettingToTransformPayloadForIke(ike, &setting);
+
+ // Build a proposal payload
+ pp = IkeNewProposalPayload(1, IKE_PROTOCOL_ID_IKE, NULL, 0, NewListSingle(tp));
+
+ // Build a SA payload
+ sap = IkeNewSaPayload(NewListSingle(pp));
+
+ payload_list = NewListSingle(sap);
+
+ ps = IkeNew(sa->InitiatorCookie, sa->ResponderCookie, IKE_EXCHANGE_TYPE_MAIN,
+ false, false, false, 0, payload_list);
+
+ // Add the vendor ID payload
+ IkeAddVendorIdPayloads(ps);
+
+ IkeSaSendPacket(ike, sa, ps);
+
+ sa->HashSize = sa->TransformSetting.Hash->HashSize;
+ sa->KeySize = sa->TransformSetting.CryptoKeySize;
+ sa->BlockSize = sa->TransformSetting.Crypto->BlockSize;
+
+ IkeFree(ps);
+ }
+ else
+ {
+ // No appropriate transform setting
+ Debug("No Appropriate Transform was Found.\n");
+
+ IPsecLog(ike, c, NULL, NULL, "LI_IKE_NO_TRANSFORM");
+
+ SendInformationalExchangePacket(ike, c, IkeNewNoticeErrorNoProposalChosenPayload(false, header->InitiatorCookie, header->ResponderCookie));
+ }
+ }
+ else
+ {
+ // Ignore for IKE SA which already exists (Because it's likely to be a re-transmission)
+ }
+ }
+ else
+ {
+ // It does not support NAT Traversal
+ Debug("Client doesn't support NAT-T.\n");
+
+ IPsecLog(ike, c, NULL, NULL, "LI_IKE_NO_NAT_T");
+ }
+ IkeFree(pr);
+ }
+ }
+ else
+ {
+ // Process of state 2 or later
+ IKE_SA *sa;
+
+ sa = FindIkeSaByResponderCookieAndClient(ike, header->ResponderCookie, c);
+
+ if (sa == NULL)
+ {
+ SendInformationalExchangePacketEx(ike, c, IkeNewNoticeErrorInvalidCookiePayload(header->InitiatorCookie,
+ header->ResponderCookie), true, header->InitiatorCookie, header->ResponderCookie);
+ }
+
+ if (sa != NULL && sa->Mode == IKE_SA_MAIN_MODE)
+ {
+ IKE_PACKET *pr = NULL;
+
+ sa->LastCommTick = ike->Now;
+
+ switch (sa->State)
+ {
+ case IKE_SA_MM_STATE_1_SA:
+ pr = IkeSaRecvPacket(ike, sa, p->Data, p->Size);
+ if (pr != NULL)
+ {
+ // Receive a key exchange packet
+ IKE_PACKET_PAYLOAD *your_key_payload;
+ IKE_PACKET_PAYLOAD *your_rand_payload;
+ IKE_PACKET_PAYLOAD *your_nat_d_1 = NULL;
+ IKE_PACKET_PAYLOAD *your_nat_d_2 = NULL;
+
+ your_key_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_KEY_EXCHANGE, 0);
+ your_rand_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_RAND, 0);
+
+ if (IkeGetPayloadNum(pr->PayloadList, IKE_PAYLOAD_NAT_D) != 0)
+ {
+ sa->Caps.UsingNatTraversalRfc3947 = true;
+
+ your_nat_d_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D, 0);
+ your_nat_d_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D, 1);
+ }
+
+ if (IkeGetPayloadNum(pr->PayloadList, IKE_PAYLOAD_NAT_D_DRAFT) != 0)
+ {
+ sa->Caps.UsingNatTraversalDraftIetf = true;
+
+ your_nat_d_1 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D_DRAFT, 0);
+ your_nat_d_2 = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_NAT_D_DRAFT, 1);
+ }
+
+ if (your_key_payload != NULL && your_rand_payload != NULL)
+ {
+ // Check the key payload
+ BUF *your_key_buf = your_key_payload->Payload.KeyExchange.Data;
+ BUF *your_rand_buf = your_rand_payload->Payload.Rand.Data;
+
+ // DH generation
+ DH_CTX *dh = IkeDhNewCtx(sa->TransformSetting.Dh);
+ UINT shared_key_size = (dh == NULL ? 0 : dh->Size);
+ UCHAR *shared_key = ZeroMalloc(shared_key_size);
+
+ // DH calculation
+ if (DhCompute(dh, shared_key, your_key_buf->Buf, your_key_buf->Size))
+ {
+ IKE_PACKET *ps;
+ LIST *payload_list;
+ IKE_PACKET_PAYLOAD *my_key_payload;
+ IKE_PACKET_PAYLOAD *my_rand_payload;
+ BUF *nat_buf1, *nat_buf2;
+ BUF *iv_buf;
+ UCHAR iv_hashed_data[IKE_MAX_HASH_SIZE];
+
+ // Calculation success
+ sa->DhSharedKey = MemToBuf(shared_key, shared_key_size);
+ sa->InitiatorRand = RandBuf(IKE_SA_RAND_SIZE);
+ sa->ResponderRand = CloneBuf(your_rand_buf);
+
+ // Send a key exchange packet
+ my_key_payload = IkeNewDataPayload(IKE_PAYLOAD_KEY_EXCHANGE, dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+ my_rand_payload = IkeNewDataPayload(IKE_PAYLOAD_RAND, sa->InitiatorRand->Buf, sa->InitiatorRand->Size);
+
+ payload_list = NewListSingle(my_key_payload);
+ Add(payload_list, my_rand_payload);
+
+ // NAT-D packet
+ // Address of the opponent. Randomize in order to be forced to use NAT
+ nat_buf1 = IkeCalcNatDetectHash(ike, sa->TransformSetting.Hash, Rand64(), Rand64(), &c->ClientIP, Rand16());
+ //nat_buf1 = IkeCalcNatDetectHash(ike, sa->TransformSetting.Hash, sa->InitiatorCookie, sa->ResponderCookie, &c->ClientIP, c->ClientPort);
+ // My address
+
+ if (c->IsMicrosoft == false || (your_nat_d_1 == NULL || your_nat_d_2 == NULL || your_nat_d_1->BitArray == NULL))
+ {
+ // Calculate exactly
+ nat_buf2 = IkeCalcNatDetectHash(ike, sa->TransformSetting.Hash,
+ sa->InitiatorCookie, sa->ResponderCookie, &c->ServerIP, c->ServerPort);
+ }
+ else
+ {
+ // Parrot the NAT_D payload indicating myself I got from
+ // the other if it has connected from a Microsoft VPN Client
+ nat_buf2 = CloneBuf(your_nat_d_1->BitArray);
+ }
+
+ if (sa->Caps.UsingNatTraversalRfc3947)
+ {
+ // RFC-compliant
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D, nat_buf1->Buf, nat_buf1->Size));
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D, nat_buf2->Buf, nat_buf2->Size));
+ }
+
+ if (sa->Caps.UsingNatTraversalDraftIetf)
+ {
+ // Draft compliant
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D_DRAFT, nat_buf1->Buf, nat_buf1->Size));
+ Add(payload_list, IkeNewDataPayload(IKE_PAYLOAD_NAT_D_DRAFT, nat_buf2->Buf, nat_buf2->Size));
+ }
+
+ FreeBuf(nat_buf1);
+ FreeBuf(nat_buf2);
+
+ ps = IkeNew(sa->InitiatorCookie, sa->ResponderCookie, IKE_EXCHANGE_TYPE_MAIN,
+ false, false, false, 0, payload_list);
+
+ // Initial IV setting
+ iv_buf = NewBuf();
+ WriteBuf(iv_buf, your_key_buf->Buf, your_key_buf->Size);
+ WriteBuf(iv_buf, dh->MyPublicKey->Buf, dh->MyPublicKey->Size);
+ IkeHash(sa->TransformSetting.Hash, iv_hashed_data, iv_buf->Buf, iv_buf->Size);
+
+ BinToStrEx(tmp, sizeof(tmp), iv_hashed_data, sa->BlockSize);
+ Debug("Initial IV: %s\n", tmp);
+
+ IkeSaUpdateIv(sa, iv_hashed_data, sa->HashSize);
+
+ FreeBuf(iv_buf);
+
+ // Save the DH information
+ sa->GXi = CloneBuf(your_key_buf);
+ sa->GXr = CloneBuf(dh->MyPublicKey);
+
+ // Transmission
+ IkeSaSendPacket(ike, sa, ps);
+
+ IkeFree(ps);
+
+ // Calculate the key set
+ IkeCalcSaKeySet(ike, sa, NULL);
+
+ sa->State = IKE_SA_MM_STATE_2_KEY;
+ }
+ else
+ {
+ // DH calculation failure
+ Debug("DhCompute failed.\n");
+ }
+
+ Free(shared_key);
+ DhFree(dh);
+ }
+ }
+ break;
+
+ case IKE_SA_MM_STATE_2_KEY:
+ pr = IkeSaRecvPacket(ike, sa, p->Data, p->Size);
+ if (pr != NULL && pr->FlagEncrypted)
+ {
+ // Receive an ID exchange packet
+ IKE_PACKET_PAYLOAD *your_id_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_ID, 0);
+ IKE_PACKET_PAYLOAD *your_hash_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_HASH, 0);
+
+ if (your_id_payload && your_hash_payload)
+ {
+ UCHAR initiator_hash[IKE_MAX_HASH_SIZE];
+ BUF *b;
+
+ // Calculate the initiator side hash value
+ b = NewBuf();
+ WriteBufBuf(b, sa->GXi);
+ WriteBufBuf(b, sa->GXr);
+ WriteBufInt64(b, sa->InitiatorCookie);
+ WriteBufInt64(b, sa->ResponderCookie);
+ WriteBufBuf(b, sa->SAi_b);
+ WriteBufBuf(b, your_id_payload->BitArray);
+
+ StrCpy(c->ClientId, sizeof(c->ClientId), your_id_payload->Payload.Id.StrData);
+ Debug("Client ID = %s\n", c->ClientId);
+ IPsecLog(ike, c, NULL, NULL, NULL, "LI_SET_CLIENT_ID", c->ClientId);
+
+ IkeHMac(sa->TransformSetting.Hash, initiator_hash, sa->SKEYID, sa->HashSize,
+ b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ // Hash comparison
+ if (IkeCompareHash(your_hash_payload, initiator_hash, sa->HashSize))
+ {
+ // Generate a response packet
+ IKE_PACKET *ps;
+ LIST *payload_list = NewListFast(NULL);
+ IKE_PACKET_PAYLOAD *my_id_payload, *my_hash_payload;
+ UCHAR responder_hash[IKE_MAX_HASH_SIZE];
+ BUF *idir_b;
+
+ // Generate an ID payload
+ if (IsIP6(&sa->IkeClient->ServerIP))
+ {
+ // IPv6 address
+ my_id_payload = IkeNewIdPayload(IKE_ID_IPV6_ADDR, 0, 0, sa->IkeClient->ServerIP.ipv6_addr, 16);
+ }
+ else
+ {
+ // IPv4 address
+ my_id_payload = IkeNewIdPayload(IKE_ID_IPV4_ADDR, 0, 0, sa->IkeClient->ServerIP.addr, 4);
+ }
+
+ // Build the ID payload tentatively
+ idir_b = IkeBuildIdPayload(&my_id_payload->Payload.Id);
+
+ // Generate the hash payload
+ b = NewBuf();
+ WriteBufBuf(b, sa->GXr);
+ WriteBufBuf(b, sa->GXi);
+ WriteBufInt64(b, sa->ResponderCookie);
+ WriteBufInt64(b, sa->InitiatorCookie);
+ WriteBufBuf(b, sa->SAi_b);
+ WriteBufBuf(b, idir_b);
+
+ IkeHMac(sa->TransformSetting.Hash, responder_hash, sa->SKEYID, sa->HashSize,
+ b->Buf, b->Size);
+
+ FreeBuf(b);
+ FreeBuf(idir_b);
+
+ my_hash_payload = IkeNewDataPayload(IKE_PAYLOAD_HASH, responder_hash, sa->HashSize);
+
+ Add(payload_list, my_id_payload);
+ Add(payload_list, my_hash_payload);
+
+ ps = IkeNew(sa->InitiatorCookie, sa->ResponderCookie, IKE_EXCHANGE_TYPE_MAIN, true, false,
+ false, 0, payload_list);
+
+ // Transmission
+ IkeSaSendPacket(ike, sa, ps);
+ sa->NumResends = 3;
+
+ IkeFree(ps);
+
+ StrCpy(c->ClientId, sizeof(c->ClientId), your_id_payload->Payload.Id.StrData);
+
+ // Transit to the established state
+ Debug("IKE SA 0x%X Established. Client ID=%s\n", sa, c->ClientId);
+ sa->State = IKE_SA_MM_STATE_3_ESTABLISHED;
+ sa->EstablishedTick = ike->Now;
+ c->CurrentIkeSa = sa;
+ c->NextDpdSendTick = ike->Now + (UINT64)IKE_INTERVAL_DPD_KEEPALIVE;
+ StrCpy(c->Secret, sizeof(c->Secret), sa->Secret);
+ sa->Established = true;
+
+ IPsecLog(ike, NULL, sa, NULL, "LI_IKE_SA_ESTABLISHED");
+ }
+ else
+ {
+ Debug("IKE SA 0x%X Invalid Hash.\n", sa);
+ }
+ }
+ }
+ break;
+ }
+
+ if (pr != NULL)
+ {
+ IkeFree(pr);
+ }
+ }
+ }
+}
+
+// Update the IV of IPsec SA
+void IPsecSaUpdateIv(IPSECSA *sa, void *iv, UINT iv_size)
+{
+ // Validate arguments
+ if (sa == NULL || iv == NULL)
+ {
+ return;
+ }
+
+ Copy(sa->Iv, iv, MIN(sa->IkeSa->BlockSize, iv_size));
+
+ if (iv_size < sa->IkeSa->BlockSize)
+ {
+ Zero(sa->Iv + sa->IkeSa->BlockSize, sa->IkeSa->BlockSize - iv_size);
+ }
+
+ sa->IsIvExisting = true;
+}
+
+// Update the IV of the IKE SA
+void IkeSaUpdateIv(IKE_SA *sa, void *iv, UINT iv_size)
+{
+ // Validate arguments
+ if (sa == NULL || iv == NULL)
+ {
+ return;
+ }
+
+ Copy(sa->Iv, iv, MIN(sa->BlockSize, iv_size));
+
+ if (iv_size < sa->BlockSize)
+ {
+ Zero(sa->Iv + sa->BlockSize, sa->BlockSize - iv_size);
+ }
+
+ sa->IsIvExisting = true;
+}
+
+// Calculate the key set of the IKE SA
+void IkeCalcSaKeySet(IKE_SERVER *ike, IKE_SA *sa, char *secret)
+{
+ BUF *secret_buf;
+ BUF *rand_buf;
+ BUF *d_buf, *a_buf, *e_buf;
+ UCHAR u;
+ IKE_HASH *h;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ h = sa->TransformSetting.Hash;
+
+ // Calculation of SKEYID
+ StrCpy(sa->Secret, sizeof(sa->Secret), secret == NULL ? ike->Secret : secret);
+ secret_buf = IkeStrToPassword(sa->Secret);
+ rand_buf = CloneBuf(sa->ResponderRand);
+ SeekBufToEnd(rand_buf);
+ BinToStrEx(tmp, sizeof(tmp), rand_buf->Buf, rand_buf->Size);
+ Debug("ResponderRand: %s\n", tmp);
+ BinToStrEx(tmp, sizeof(tmp), sa->InitiatorRand->Buf, sa->InitiatorRand->Size);
+ Debug("InitiatorRand: %s\n", tmp);
+
+ WriteBufBuf(rand_buf, sa->InitiatorRand);
+
+ IkeHMacBuf(h, sa->SKEYID, secret_buf, rand_buf);
+
+ BinToStrEx(tmp, sizeof(tmp), sa->SKEYID, sa->HashSize);
+ Debug("SKEYID: %s\n", tmp);
+
+ // SKEYID_d
+ d_buf = CloneBuf(sa->DhSharedKey);
+ SeekBufToEnd(d_buf);
+ WriteBufInt64(d_buf, sa->InitiatorCookie);
+ WriteBufInt64(d_buf, sa->ResponderCookie);
+ u = 0;
+ WriteBuf(d_buf, &u, 1);
+ IkeHMac(h, sa->SKEYID_d, sa->SKEYID, sa->HashSize, d_buf->Buf, d_buf->Size);
+
+ BinToStrEx(tmp, sizeof(tmp), sa->SKEYID_d, sa->HashSize);
+ Debug("SKEYID_d: %s\n", tmp);
+
+ // SKEYID_a
+ a_buf = MemToBuf(sa->SKEYID_d, sa->HashSize);
+ SeekBufToEnd(a_buf);
+ WriteBufBuf(a_buf, sa->DhSharedKey);
+ WriteBufInt64(a_buf, sa->InitiatorCookie);
+ WriteBufInt64(a_buf, sa->ResponderCookie);
+ u = 1;
+ WriteBuf(a_buf, &u, 1);
+ IkeHMac(h, sa->SKEYID_a, sa->SKEYID, sa->HashSize, a_buf->Buf, a_buf->Size);
+
+ BinToStrEx(tmp, sizeof(tmp), sa->SKEYID_a, sa->HashSize);
+ Debug("SKEYID_a: %s\n", tmp);
+
+ // SKEYID_e
+ e_buf = MemToBuf(sa->SKEYID_a, sa->HashSize);
+ SeekBufToEnd(e_buf);
+ WriteBufBuf(e_buf, sa->DhSharedKey);
+ WriteBufInt64(e_buf, sa->InitiatorCookie);
+ WriteBufInt64(e_buf, sa->ResponderCookie);
+ u = 2;
+ WriteBuf(e_buf, &u, 1);
+ IkeHMac(h, sa->SKEYID_e, sa->SKEYID, sa->HashSize, e_buf->Buf, e_buf->Size);
+
+ BinToStrEx(tmp, sizeof(tmp), sa->SKEYID_e, sa->HashSize);
+ Debug("SKEYID_e: %s\n", tmp);
+
+ if (sa->CryptoKey != NULL)
+ {
+ IkeFreeKey(sa->CryptoKey);
+ }
+
+ sa->CryptoKey = IkeNewCryptoKeyFromK(ike, sa->SKEYID_e, sa->HashSize, sa->TransformSetting.Hash,
+ sa->TransformSetting.Crypto, sa->TransformSetting.CryptoKeySize);
+
+ // Release the memory
+ FreeBuf(secret_buf);
+ FreeBuf(rand_buf);
+ FreeBuf(d_buf);
+ FreeBuf(a_buf);
+ FreeBuf(e_buf);
+}
+
+// Extend the key size
+BUF *IkeExpandKeySize(IKE_HASH *h, void *k, UINT k_size, UINT target_size)
+{
+ BUF *b1, *b2;
+ UCHAR tmp[IKE_MAX_HASH_SIZE];
+ UINT tmp_size;
+ // Validate arguments
+ if (h == NULL || k == NULL || k_size == 0)
+ {
+ return NULL;
+ }
+
+ if (k_size >= target_size)
+ {
+ return MemToBuf(k, target_size);
+ }
+
+ tmp[0] = 0;
+ tmp_size = 1;
+ b1 = NewBuf();
+
+ do
+ {
+ IkeHMac(h, tmp, k, k_size, tmp, tmp_size);
+ WriteBuf(b1, tmp, h->HashSize);
+
+ tmp_size = h->HashSize;
+ }
+ while (b1->Size < target_size);
+
+ b2 = MemToBuf(b1->Buf, target_size);
+
+ FreeBuf(b1);
+
+ return b2;
+}
+
+// Generate a key from K
+IKE_CRYPTO_KEY *IkeNewCryptoKeyFromK(IKE_SERVER *ike, void *k, UINT k_size, IKE_HASH *h, IKE_CRYPTO *c, UINT crypto_key_size)
+{
+ BUF *key_buf;
+ IKE_CRYPTO_KEY *ret;
+ // Validate arguments
+ if (ike == NULL || k == NULL || k_size == 0 || h == NULL || c == NULL || crypto_key_size == 0)
+ {
+ return NULL;
+ }
+
+ key_buf = IkeExpandKeySize(h, k, k_size, crypto_key_size);
+ if (key_buf == NULL)
+ {
+ return NULL;
+ }
+
+ ret = IkeNewKey(c, key_buf->Buf, key_buf->Size);
+
+ FreeBuf(key_buf);
+
+ return ret;
+}
+
+// Generate a hash for NAT detection
+BUF *IkeCalcNatDetectHash(IKE_SERVER *ike, IKE_HASH *hash, UINT64 initiator_cookie, UINT64 responder_cookie, IP *ip, UINT port)
+{
+ BUF *b;
+ USHORT us;
+ USHORT hash_data[IKE_MAX_HASH_SIZE];
+ // Validate arguments
+ if (ike == NULL || ip == NULL || hash == NULL)
+ {
+ return NewBuf();
+ }
+
+ b = NewBuf();
+
+ WriteBufInt64(b, initiator_cookie);
+ WriteBufInt64(b, responder_cookie);
+
+ if (IsIP6(ip))
+ {
+ WriteBuf(b, ip->ipv6_addr, sizeof(ip->ipv6_addr));
+ }
+ else
+ {
+ WriteBuf(b, ip->addr, sizeof(ip->addr));
+ }
+
+ us = Endian16((USHORT)port);
+
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ IkeHash(hash, hash_data, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return MemToBuf(hash_data, hash->HashSize);
+}
+
+// Check the capacity of the opposite IPsec client
+void IkeCheckCaps(IKE_CAPS *caps, IKE_PACKET *p)
+{
+ // Validate arguments
+ if (caps == NULL || p == NULL)
+ {
+ Zero(caps, sizeof(IKE_CAPS));
+ return;
+ }
+
+ Zero(caps, sizeof(IKE_CAPS));
+
+ caps->NatTraversalRfc3947 = IkeIsVendorIdExists(p, IKE_VENDOR_ID_RFC3947_NAT_T);
+
+ caps->NatTraversalDraftIetf = IkeIsVendorIdExists(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_03) ||
+ IkeIsVendorIdExists(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02) ||
+ IkeIsVendorIdExists(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02_2) ||
+ IkeIsVendorIdExists(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_00);
+
+ caps->DpdRfc3706 = IkeIsVendorIdExists(p, IKE_VENDOR_ID_RFC3706_DPD);
+
+ caps->MS_L2TPIPSecVPNClient = IkeIsVendorIdExists(p, IKE_VENDOR_ID_MICROSOFT_L2TP);
+ caps->MS_NT5_ISAKMP_OAKLEY = IkeIsVendorIdExists(p, IKE_VENDOR_ID_MS_NT5_ISAKMPOAKLEY);
+ caps->MS_Vid_InitialContact = IkeIsVendorIdExists(p, IKE_VENDOR_ID_MS_VID_INITIALCONTACT);
+}
+
+// Check whether the specified vendor ID is contained in the packet
+bool IkeIsVendorIdExists(IKE_PACKET *p, char *str)
+{
+ BUF *buf;
+ UINT i, num;
+ bool ok = false;
+ // Validate arguments
+ if (p == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ buf = IkeStrToVendorId(str);
+ if (buf == NULL)
+ {
+ return false;
+ }
+
+ num = IkeGetPayloadNum(p->PayloadList, IKE_PAYLOAD_VENDOR_ID);
+ for (i = 0;i < num;i++)
+ {
+ IKE_PACKET_PAYLOAD *payload = IkeGetPayload(p->PayloadList, IKE_PAYLOAD_VENDOR_ID, i);
+
+ if (CompareBuf(payload->Payload.VendorId.Data, buf))
+ {
+ ok = true;
+ }
+ else
+ {
+ if (payload->Payload.VendorId.Data != NULL)
+ {
+ if (payload->Payload.VendorId.Data->Size >= buf->Size)
+ {
+ if (Cmp(payload->Payload.VendorId.Data->Buf, buf->Buf, buf->Size) == 0)
+ {
+ ok = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeBuf(buf);
+
+ return ok;
+}
+
+// Add the vendor ID payload list
+void IkeAddVendorIdPayloads(IKE_PACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ IkeAddVendorId(p, IKE_VENDOR_ID_RFC3947_NAT_T);
+ IkeAddVendorId(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_03);
+ IkeAddVendorId(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02);
+ IkeAddVendorId(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02_2);
+ IkeAddVendorId(p, IKE_VENDOR_ID_IPSEC_NAT_T_IKE_00);
+ IkeAddVendorId(p, IKE_VENDOR_ID_RFC3706_DPD);
+}
+
+// Add the vendor ID payload
+void IkeAddVendorId(IKE_PACKET *p, char *str)
+{
+ BUF *buf;
+ IKE_PACKET_PAYLOAD *payload;
+ // Validate arguments
+ if (p == NULL || str == NULL)
+ {
+ return;
+ }
+
+ buf = IkeStrToVendorId(str);
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ payload = IkeNewDataPayload(IKE_PAYLOAD_VENDOR_ID, buf->Buf, buf->Size);
+
+ Add(p->PayloadList, payload);
+
+ FreeBuf(buf);
+}
+
+// Convert string to the vendor ID
+BUF *IkeStrToVendorId(char *str)
+{
+ // Validate arguments
+ if (IsEmptyStr(str))
+ {
+ return NULL;
+ }
+
+ if (StartWith(str, "0x"))
+ {
+ BUF *buf = StrToBin(str + 2);
+
+ if (buf == NULL || buf->Size == 0)
+ {
+ FreeBuf(buf);
+ return NULL;
+ }
+
+ return buf;
+ }
+ else
+ {
+ BUF *buf;
+ UCHAR hash[MD5_SIZE];
+
+ Hash(hash, str, StrLen(str), false);
+
+ buf = MemToBuf(hash, sizeof(hash));
+
+ return buf;
+ }
+}
+
+// Receive a packet using the IKE SA
+IKE_PACKET *IkeSaRecvPacket(IKE_SERVER *ike, IKE_SA *sa, void *data, UINT size)
+{
+ IKE_PACKET *ret;
+ // Validate arguments
+ if (ike == NULL || sa == NULL || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+
+ if (sa->IsIvExisting == false || sa->CryptoKey == NULL)
+ {
+ ret = IkeParse(data, size, NULL);
+ }
+ else
+ {
+ IKE_CRYPTO_PARAM cp;
+
+ Copy(&cp.Iv, sa->Iv, sa->BlockSize);
+ cp.Key = sa->CryptoKey;
+
+ ret = IkeParse(data, size, &cp);
+
+ if (ret->FlagEncrypted)
+ {
+ IkeSaUpdateIv(sa, cp.NextIv, sa->BlockSize);
+ }
+ }
+
+ return ret;
+}
+
+// Receive a packet using IPsec SA (Quick Mode received)
+IKE_PACKET *IPsecSaRecvPacket(IKE_SERVER *ike, IPSECSA *sa, void *data, UINT size)
+{
+ IKE_PACKET *ret;
+ // Validate arguments
+ if (ike == NULL || sa == NULL || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+
+ if (sa->IsIvExisting == false || sa->IkeSa->CryptoKey == NULL)
+ {
+ ret = IkeParse(data, size, NULL);
+ }
+ else
+ {
+ IKE_CRYPTO_PARAM cp;
+
+ Copy(&cp.Iv, sa->Iv, sa->IkeSa->BlockSize);
+ cp.Key = sa->IkeSa->CryptoKey;
+
+ ret = IkeParse(data, size, &cp);
+
+ if (ret->FlagEncrypted)
+ {
+ IPsecSaUpdateIv(sa, cp.NextIv, sa->IkeSa->BlockSize);
+ IPsecSaUpdateIv(sa->PairIPsecSa, cp.NextIv, sa->IkeSa->BlockSize);
+ }
+ }
+
+ return ret;
+}
+
+// Send a packet using IPsec SA (Quick Mode transmission)
+void IPsecSaSendPacket(IKE_SERVER *ike, IPSECSA *sa, IKE_PACKET *p)
+{
+ BUF *buf;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ if (p == NULL)
+ {
+ FreeBuf(sa->SendBuffer);
+ sa->SendBuffer = NULL;
+ sa->NextSendTick = 0;
+ return;
+ }
+
+ // Build a packet
+ if (p->FlagEncrypted == false)
+ {
+ buf = IkeBuild(p, NULL);
+ }
+ else
+ {
+ IKE_CRYPTO_PARAM cp;
+
+ Copy(cp.Iv, sa->Iv, sa->IkeSa->BlockSize);
+ cp.Key = sa->IkeSa->CryptoKey;
+
+ buf = IkeBuild(p, &cp);
+
+ IPsecSaUpdateIv(sa, cp.NextIv, sa->IkeSa->BlockSize);
+ IPsecSaUpdateIv(sa->PairIPsecSa, cp.NextIv, sa->IkeSa->BlockSize);
+ }
+
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Register the last packet to re-transmit
+ if (sa->SendBuffer != NULL)
+ {
+ FreeBuf(sa->SendBuffer);
+ }
+
+ sa->SendBuffer = CloneBuf(buf);
+ sa->NextSendTick = ike->Now + (UINT64)(IKE_SA_RESEND_INTERVAL);
+ AddInterrupt(ike->Interrupts, sa->NextSendTick);
+
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ISAKMP, &sa->IkeClient->ServerIP, sa->IkeClient->ServerPort,
+ &sa->IkeClient->ClientIP, sa->IkeClient->ClientPort,
+ buf->Buf, buf->Size);
+
+ Free(buf);
+}
+
+// Send a packet using the IKE SA
+void IkeSaSendPacket(IKE_SERVER *ike, IKE_SA *sa, IKE_PACKET *p)
+{
+ BUF *buf;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ if (p == NULL)
+ {
+ FreeBuf(sa->SendBuffer);
+ sa->SendBuffer = NULL;
+ sa->NextSendTick = 0;
+ return;
+ }
+
+ // Build a packet
+ if (p->FlagEncrypted == false)
+ {
+ buf = IkeBuild(p, NULL);
+ }
+ else
+ {
+ IKE_CRYPTO_PARAM cp;
+
+ Copy(cp.Iv, sa->Iv, sa->BlockSize);
+ cp.Key = sa->CryptoKey;
+
+ buf = IkeBuild(p, &cp);
+
+ IkeSaUpdateIv(sa, cp.NextIv, sa->BlockSize);
+ }
+
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ if (p->ExchangeType != IKE_EXCHANGE_TYPE_INFORMATION)
+ {
+ // Register the last packet to re-transmit
+ if (sa->SendBuffer != NULL)
+ {
+ FreeBuf(sa->SendBuffer);
+ }
+
+ sa->SendBuffer = CloneBuf(buf);
+ sa->NextSendTick = ike->Now + (UINT64)(IKE_SA_RESEND_INTERVAL);
+ AddInterrupt(ike->Interrupts, sa->NextSendTick);
+ }
+
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ISAKMP, &sa->IkeClient->ServerIP, sa->IkeClient->ServerPort,
+ &sa->IkeClient->ClientIP, sa->IkeClient->ClientPort,
+ buf->Buf, buf->Size);
+
+ Free(buf);
+}
+
+// Send an UDP packet
+void IkeSendUdpPacket(IKE_SERVER *ike, UINT type, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, void *data, UINT size)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (ike == NULL || server_ip == NULL || client_ip == NULL || server_port == 0 || client_port == 0 || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ p = NewUdpPacket(server_ip, server_port, client_ip, client_port, data, size);
+
+ p->Type = type;
+
+ Add(ike->SendPacketList, p);
+}
+
+// Create an IKE SA
+IKE_SA *NewIkeSa(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT mode, IKE_SA_TRANSFORM_SETTING *setting)
+{
+ IKE_SA *sa;
+ // Validate arguments
+ if (ike == NULL || c == NULL || init_cookie == 0 || setting == NULL)
+ {
+ return NULL;
+ }
+
+ sa = ZeroMalloc(sizeof(IKE_SA));
+
+ sa->Id = ++ike->CurrentIkeSaId;
+
+ sa->IkeClient = c;
+ sa->InitiatorCookie = init_cookie;
+ sa->ResponderCookie = GenerateNewResponserCookie(ike);
+ sa->Mode = mode;
+ sa->FirstCommTick = sa->LastCommTick = ike->Now;
+ Copy(&sa->TransformSetting, setting, sizeof(IKE_SA_TRANSFORM_SETTING));
+
+ Debug("New IKE SA (Mode = %u): %I64u <--> %I64u (%s %s %s(%u) %u %u)\n",
+ mode,
+ sa->InitiatorCookie,
+ sa->ResponderCookie,
+ setting->Dh->Name, setting->Hash->Name, setting->Crypto->Name, setting->CryptoKeySize,
+ setting->LifeKilobytes, setting->LifeSeconds);
+
+ IPsecLog(ike, NULL, sa, NULL, "LI_NEW_IKE_SA",
+ (mode == IKE_SA_MAIN_MODE ? _UU("LI_TAG_MAINMODE") : _UU("LI_TAG_AGGRESSIVE")),
+ sa->InitiatorCookie, sa->ResponderCookie,
+ setting->Dh->Name, setting->Hash->Name, setting->Crypto->Name, setting->CryptoKeySize * 8,
+ setting->LifeKilobytes, setting->LifeSeconds);
+
+ return sa;
+}
+
+// Search an IKE SA from the Responder Cookie
+IKE_SA *FindIkeSaByResponderCookie(IKE_SERVER *ike, UINT64 responder_cookie)
+{
+ IKE_SA t;
+ // Validate arguments
+ if (ike == NULL || responder_cookie == 0)
+ {
+ return NULL;
+ }
+
+ t.ResponderCookie = responder_cookie;
+
+ return Search(ike->IkeSaList, &t);
+}
+
+// Search an IKE SA from the Responder Cookie and the IKE_CLIENT
+IKE_SA *FindIkeSaByResponderCookieAndClient(IKE_SERVER *ike, UINT64 responder_cookie, IKE_CLIENT *c)
+{
+ IKE_SA *sa;
+ // Validate arguments
+ if (ike == NULL || responder_cookie == 0 || c == NULL)
+ {
+ return NULL;
+ }
+
+ sa = FindIkeSaByResponderCookie(ike, responder_cookie);
+ if (sa == NULL)
+ {
+ return NULL;
+ }
+
+ if (sa->IkeClient != c)
+ {
+ return NULL;
+ }
+
+ return sa;
+}
+
+// Search an IKE SA from the endpoint and the Initiator Cookie
+IKE_SA *FindIkeSaByEndPointAndInitiatorCookie(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, UINT64 init_cookie, UINT mode)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || client_ip == NULL || server_ip == NULL || client_port == 0 || server_port == 0 || init_cookie == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+ IKE_CLIENT *c;
+
+ c = sa->IkeClient;
+
+ if (CmpIpAddr(&c->ClientIP, client_ip) == 0 &&
+ CmpIpAddr(&c->ServerIP, server_ip) == 0 &&
+ c->ClientPort == client_port &&
+ c->ServerPort == server_port &&
+ sa->InitiatorCookie == init_cookie &&
+ sa->Mode == mode)
+ {
+ return sa;
+ }
+ }
+
+ return NULL;
+}
+
+// Get the number of IPsec SA that is associated with the IKE_CLIENT
+UINT GetNumberOfIPsecSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ UINT num = 0, i;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+// Get the number of IKE SA that is associated with the IKE_CLIENT
+UINT GetNumberOfIkeSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ UINT num = 0, i;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+// Get the number of clients that are connected from the specified IP address
+UINT GetNumberOfIkeClientsFromIP(IKE_SERVER *ike, IP *client_ip)
+{
+ UINT i, num;
+ // Validate arguments
+ if (ike == NULL || client_ip == NULL)
+ {
+ return 0;
+ }
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+
+ if (CmpIpAddr(&c->ClientIP, client_ip) == 0)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+// Find the appropriate IKE client. Create if it is absent
+IKE_CLIENT *SearchOrCreateNewIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr)
+{
+ IKE_CLIENT *c;
+ // Validate arguments
+ if (ike == NULL || pr == NULL || client_ip == NULL || server_ip == NULL || client_port == 0 || server_port == 0 || pr == NULL)
+ {
+ return NULL;
+ }
+
+ c = SearchIkeClientForIkePacket(ike, client_ip, client_port, server_ip, server_port, pr);
+ if (c == NULL)
+ {
+ if (GetNumberOfIkeClientsFromIP(ike, client_ip) > IKE_QUOTA_MAX_NUM_CLIENTS_PER_IP ||
+ LIST_NUM(ike->ClientList) > IKE_QUOTA_MAX_NUM_CLIENTS)
+ {
+ return NULL;
+ }
+
+
+ c = NewIkeClient(ike, client_ip, client_port, server_ip, server_port);
+
+ Insert(ike->ClientList, c);
+ }
+
+ return SetIkeClientEndpoint(ike, c, client_ip, client_port, server_ip, server_port);
+}
+
+// Create an IKE client
+IKE_CLIENT *NewIkeClient(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ IKE_CLIENT *c;
+ char client_ip_str[MAX_SIZE];
+ char server_ip_str[MAX_SIZE];
+ // Validate arguments
+ if (ike == NULL || client_ip == NULL || server_ip == NULL || client_port == 0 || server_port == 0)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(IKE_CLIENT));
+
+ c->Id = ++ike->CurrentIkeClientId;
+
+ Copy(&c->ClientIP, client_ip, sizeof(IP));
+ c->ClientPort = client_port;
+
+ Copy(&c->ServerIP, server_ip, sizeof(IP));
+ Copy(&c->TransportModeServerIP, server_ip, sizeof(IP));
+ Copy(&c->TransportModeClientIP, client_ip, sizeof(IP));
+ c->ServerPort = server_port;
+
+ c->LastCommTick = ike->Now;
+ c->FirstCommTick = ike->Now;
+
+ IPToStr(client_ip_str, sizeof(client_ip_str), client_ip);
+ IPToStr(server_ip_str, sizeof(server_ip_str), server_ip);
+
+ Debug("New IKE_CLIENT: %p: %s:%u -> %s:%u\n", c, client_ip_str, client_port, server_ip_str, server_port);
+
+ IPsecLog(ike, c, NULL, NULL, "LI_NEW_IKE_CLIENT");
+
+ return c;
+}
+
+// Search for the best associated IKE client when an IKE packet has been received
+IKE_CLIENT *SearchIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr)
+{
+ IKE_CLIENT t;
+ IKE_CLIENT *c = NULL;
+ // Validate arguments
+ if (ike == NULL || pr == NULL || client_ip == NULL || server_ip == NULL || client_port == 0 || server_port == 0)
+ {
+ return NULL;
+ }
+
+ if (true)
+ {
+ UINT i;
+
+ if (pr->InitiatorCookie != 0 && pr->ResponderCookie != 0)
+ {
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ // Extract what Cookie matches exactly
+ if (sa->InitiatorCookie == pr->InitiatorCookie && sa->ResponderCookie == pr->ResponderCookie)
+ {
+ IKE_CLIENT *cc = sa->IkeClient;
+
+ if (CmpIpAddr(&cc->ServerIP, server_ip) == 0 &&
+ CmpIpAddr(&cc->ClientIP, client_ip) == 0)
+ {
+ c = cc;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (c == NULL)
+ {
+ // Search by a pair of IP address and port number
+ Copy(&t.ClientIP, client_ip, sizeof(IP));
+ t.ClientPort = client_port;
+ Copy(&t.ServerIP, server_ip, sizeof(IP));
+ t.ServerPort = server_port;
+
+ c = Search(ike->ClientList, &t);
+
+ if (c != NULL)// && server_port == IPSEC_PORT_IPSEC_ISAKMP)
+ {
+ // Search that the IKE_SA that points to this IKE_CLIENT exists and match the Cookie
+ bool ok = false;
+ UINT i;
+
+ if (server_port == IPSEC_PORT_IPSEC_ESP_UDP)
+ {
+ // Regard as OK if the port number exactly match in the case of connecting to a server-side 4500
+ ok = true;
+ }
+ else
+ {
+ if (c->CurrentIkeSa != NULL &&
+ c->CurrentIkeSa->InitiatorCookie == pr->InitiatorCookie &&
+ c->CurrentIkeSa->ResponderCookie == pr->ResponderCookie)
+ {
+ ok = true;
+ }
+ else
+ {
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ if (sa->InitiatorCookie == pr->InitiatorCookie &&
+ sa->ResponderCookie == pr->ResponderCookie)
+ {
+ ok = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ // Not found
+ c = NULL;
+ }
+ }
+ }
+
+ return c;
+}
+
+// Comparison of IPsec SA
+int CmpIPsecSa(void *p1, void *p2)
+{
+ IPSECSA *sa1, *sa2;
+ int r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ sa1 = *(IPSECSA **)p1;
+ sa2 = *(IPSECSA **)p2;
+ if (sa1 == NULL || sa2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(sa1->ServerToClient, sa2->ServerToClient);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(sa1->Spi, sa2->Spi);
+
+ return r;
+}
+
+// Comparison of IKE_SA
+int CmpIkeSa(void *p1, void *p2)
+{
+ IKE_SA *sa1, *sa2;
+ int r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ sa1 = *(IKE_SA **)p1;
+ sa2 = *(IKE_SA **)p2;
+ if (sa1 == NULL || sa2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(sa1->ResponderCookie, sa2->ResponderCookie);
+
+ return r;
+}
+
+// Comparison of IKE_CLIENT
+int CmpIkeClient(void *p1, void *p2)
+{
+ IKE_CLIENT *c1, *c2;
+ int r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(IKE_CLIENT **)p1;
+ c2 = *(IKE_CLIENT **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ r = CmpIpAddr(&c1->ClientIP, &c2->ClientIP);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = CmpIpAddr(&c1->ServerIP, &c2->ServerIP);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(c1->ClientPort, c2->ClientPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(c1->ServerPort, c2->ServerPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ return 0;
+}
+
+// Update the endpoint information of IKE_CLIENT
+IKE_CLIENT *SetIkeClientEndpoint(IKE_SERVER *ike, IKE_CLIENT *c, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ char client_ip_str[MAX_SIZE];
+ char server_ip_str[MAX_SIZE];
+ IKE_CLIENT *ret = c;
+ IKE_CLIENT *cc;
+ IKE_CLIENT t;
+ // Validate arguments
+ if (ike == NULL || c == NULL || client_ip == NULL || client_port == 0 || server_ip == NULL || server_port == 0)
+ {
+ return NULL;
+ }
+
+ if (CmpIpAddr(&c->ClientIP, client_ip) == 0 &&
+ CmpIpAddr(&c->ServerIP, server_ip) == 0 &&
+ c->ClientPort == client_port &&
+ c->ServerPort == server_port)
+ {
+ // No change
+ return ret;
+ }
+
+ if (IS_SPECIAL_PORT(client_port) || IS_SPECIAL_PORT(server_port))
+ {
+ // Don't change in the case of Raw socket
+ return ret;
+ }
+
+ // Search for an existing IKE_CLIENT which exactly matches to combination of the new IP address and the port number
+ Copy(&t.ClientIP, client_ip, sizeof(IP));
+ t.ClientPort = client_port;
+ Copy(&t.ServerIP, server_ip, sizeof(IP));
+ t.ServerPort = server_port;
+
+ cc = Search(ike->ClientList, &t);
+ if (cc != NULL && c != cc && cc->Deleting == false && c->L2TP == NULL)
+ {
+ UINT i;
+ // Merge into this existing IKE_CLIENT since it found
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ sa->IkeClient = cc;
+ }
+ }
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ sa->IkeClient = cc;
+ }
+ }
+
+ if (cc->LastCommTick < c->LastCommTick)
+ {
+ StrCpy(cc->ClientId, sizeof(cc->ClientId), c->ClientId);
+ }
+
+ cc->FirstCommTick = MIN(cc->FirstCommTick, c->FirstCommTick);
+ cc->LastCommTick = MAX(cc->LastCommTick, c->LastCommTick);
+
+ ret = cc;
+
+ IPToStr(client_ip_str, sizeof(client_ip_str), client_ip);
+ IPToStr(server_ip_str, sizeof(server_ip_str), server_ip);
+
+ Debug("Merge IKE_CLIENT: %p->%p: %s:%u -> %s:%u\n", c, cc, client_ip_str, client_port, server_ip_str, server_port);
+
+ IPsecLog(ike, c, NULL, NULL, "LI_CLIENT_MERGE", c->Id, cc->Id, cc->Id);
+
+ // Remove old IKE_CLIENT from the list and free
+ Delete(ike->ClientList, c);
+ FreeIkeClient(ike, c);
+ }
+ else
+ {
+ // Rewrite the end point information of this IKE_CLIENT because not found
+ Copy(&c->ClientIP, client_ip, sizeof(IP));
+ Copy(&c->ServerIP, server_ip, sizeof(IP));
+ c->ClientPort = client_port;
+ c->ServerPort = server_port;
+
+ IPToStr(client_ip_str, sizeof(client_ip_str), client_ip);
+ IPToStr(server_ip_str, sizeof(server_ip_str), server_ip);
+
+ Debug("Update IKE_CLIENT: %p: %s:%u -> %s:%u\n", c, client_ip_str, client_port, server_ip_str, server_port);
+
+ IPsecLog(ike, c, NULL, NULL, "LI_CLIENT_UPDATE");
+
+ ike->ClientList->sorted = false;
+ }
+
+ return ret;
+}
+
+// Select the optimal transform setting for IPsec SA
+bool GetBestTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET *pr, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip)
+{
+ IKE_PACKET_PAYLOAD *sa_payload;
+ IKE_PACKET_SA_PAYLOAD *sa;
+ UINT i, num;
+ bool ocmii_flag = false;
+ // Validate arguments
+ if (ike == NULL || pr == NULL || setting == NULL || server_ip == NULL)
+ {
+ return false;
+ }
+
+ Zero(setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ // Get the SA payload
+ sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ if (sa_payload == NULL)
+ {
+ return false;
+ }
+
+ sa = &sa_payload->Payload.Sa;
+
+ // Scan all proposal payloads
+ num = IkeGetPayloadNum(sa->PayloadList, IKE_PAYLOAD_PROPOSAL);
+ for (i = 0;i < num;i++)
+ {
+ IKE_PACKET_PAYLOAD *proposal_payload = IkeGetPayload(sa->PayloadList, IKE_PAYLOAD_PROPOSAL, i);
+
+ if (proposal_payload != NULL)
+ {
+ IKE_PACKET_PROPOSAL_PAYLOAD *proposal = &proposal_payload->Payload.Proposal;
+
+ // Examine the contents of the proposal payload
+ if (proposal->ProtocolId == IKE_PROTOCOL_ID_IPSEC_ESP && proposal->Spi->Size == 4)
+ {
+ // Scan all transform payloads
+ UINT j, num2;
+
+ num2 = IkeGetPayloadNum(proposal->PayloadList, IKE_PAYLOAD_TRANSFORM);
+ for (j = 0;j < num2;j++)
+ {
+ IKE_PACKET_PAYLOAD *transform_payload = IkeGetPayload(proposal->PayloadList, IKE_PAYLOAD_TRANSFORM, j);
+ if (transform_payload != NULL)
+ {
+ IKE_PACKET_TRANSFORM_PAYLOAD *transform = &transform_payload->Payload.Transform;
+ IPSEC_SA_TRANSFORM_SETTING set;
+
+ if (TransformPayloadToTransformSettingForIPsecSa(ike, transform, &set, server_ip))
+ {
+ Copy(setting, &set, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ setting->SpiServerToClient = READ_UINT(proposal->Spi->Buf);
+
+ return true;
+ }
+ else
+ {
+ if (set.OnlyCapsuleModeIsInvalid)
+ {
+ if (ocmii_flag == false)
+ {
+ Copy(setting, &set, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+ ocmii_flag = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// Select the optimal transform settings for the IKE SA
+bool GetBestTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET *pr, IKE_SA_TRANSFORM_SETTING *setting)
+{
+ IKE_PACKET_PAYLOAD *sa_payload;
+ IKE_PACKET_SA_PAYLOAD *sa;
+ UINT i, num;
+ // Validate arguments
+ if (ike == NULL || pr == NULL || setting == NULL)
+ {
+ return false;
+ }
+
+ // Get the SA payload
+ sa_payload = IkeGetPayload(pr->PayloadList, IKE_PAYLOAD_SA, 0);
+ if (sa_payload == NULL)
+ {
+ return false;
+ }
+
+ sa = &sa_payload->Payload.Sa;
+
+ // Scan all proposal payloads
+ num = IkeGetPayloadNum(sa->PayloadList, IKE_PAYLOAD_PROPOSAL);
+ for (i = 0;i < num;i++)
+ {
+ IKE_PACKET_PAYLOAD *proposal_payload = IkeGetPayload(sa->PayloadList, IKE_PAYLOAD_PROPOSAL, i);
+
+ if (proposal_payload != NULL)
+ {
+ IKE_PACKET_PROPOSAL_PAYLOAD *proposal = &proposal_payload->Payload.Proposal;
+
+ // Examine the contents of the proposal payload
+ if (proposal->ProtocolId == IKE_PROTOCOL_ID_IKE)
+ {
+ // Scan all transform payloads
+ UINT j, num2;
+
+ num2 = IkeGetPayloadNum(proposal->PayloadList, IKE_PAYLOAD_TRANSFORM);
+ for (j = 0;j < num2;j++)
+ {
+ IKE_PACKET_PAYLOAD *transform_payload = IkeGetPayload(proposal->PayloadList, IKE_PAYLOAD_TRANSFORM, j);
+ if (transform_payload != NULL)
+ {
+ IKE_PACKET_TRANSFORM_PAYLOAD *transform = &transform_payload->Payload.Transform;
+
+ if (transform->TransformId == IKE_TRANSFORM_ID_P1_KEY_IKE)
+ {
+ IKE_SA_TRANSFORM_SETTING set;
+
+ if (TransformPayloadToTransformSettingForIkeSa(ike, transform, &set))
+ {
+ Copy(setting, &set, sizeof(IKE_SA_TRANSFORM_SETTING));
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// Convert a structure to the transform payload (for IPsec SA)
+IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIPsec(IKE_SERVER *ike, IPSEC_SA_TRANSFORM_SETTING *setting)
+{
+ LIST *value_list;
+ // Validate arguments
+ if (ike == NULL || setting == NULL)
+ {
+ return NULL;
+ }
+
+ value_list = NewListFast(NULL);
+
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_HMAC, setting->HashId));
+
+ if (setting->Dh != NULL)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_DH_GROUP, setting->DhId));
+ }
+
+ if (setting->LifeSeconds != INFINITE)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_LIFE_TYPE, IKE_P2_LIFE_TYPE_SECONDS));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_LIFE_VALUE, setting->LifeSeconds));
+ }
+
+ if (setting->LifeKilobytes != INFINITE)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_LIFE_TYPE, IKE_P2_LIFE_TYPE_KILOBYTES));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_LIFE_VALUE, setting->LifeKilobytes));
+ }
+
+ if (setting->Crypto->VariableKeySize)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_KEY_SIZE, setting->CryptoKeySize * 8));
+ }
+
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P2_CAPSULE, setting->CapsuleMode));
+
+ return IkeNewTransformPayload(1, setting->CryptoId, value_list);
+}
+
+// Convert a structure to the transform payload (for IKE SA)
+IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIke(IKE_SERVER *ike, IKE_SA_TRANSFORM_SETTING *setting)
+{
+ LIST *value_list;
+ // Validate arguments
+ if (ike == NULL || setting == NULL)
+ {
+ return NULL;
+ }
+
+ value_list = NewListFast(NULL);
+
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_CRYPTO, setting->CryptoId));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_HASH, setting->HashId));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_AUTH_METHOD, IKE_P1_AUTH_METHOD_PRESHAREDKEY));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_DH_GROUP, setting->DhId));
+
+ if (setting->LifeSeconds != INFINITE)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_LIFE_TYPE, IKE_P1_LIFE_TYPE_SECONDS));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_LIFE_VALUE, setting->LifeSeconds));
+ }
+
+ if (setting->LifeKilobytes != INFINITE)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_LIFE_TYPE, IKE_P1_LIFE_TYPE_KILOBYTES));
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_LIFE_VALUE, setting->LifeKilobytes));
+ }
+
+ if (setting->Crypto->VariableKeySize)
+ {
+ Add(value_list, IkeNewTransformValue(IKE_TRANSFORM_VALUE_P1_KET_SIZE, setting->CryptoKeySize * 8));
+ }
+
+ return IkeNewTransformPayload(1, IKE_TRANSFORM_ID_P1_KEY_IKE, value_list);
+}
+
+// Convert a transform payload to a structure (for IPsec SA)
+bool TransformPayloadToTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip)
+{
+ UINT i;
+ UINT capsule_mode;
+ bool is_esp_supported;
+ // Validate arguments
+ if (ike == NULL || transform == NULL || setting == NULL || server_ip == NULL)
+ {
+ return false;
+ }
+
+ is_esp_supported = IsUdpPortOpened(ike->IPsec->UdpListener, server_ip, IPSEC_PORT_IPSEC_ESP_RAW);
+
+ Zero(setting, sizeof(IPSEC_SA_TRANSFORM_SETTING));
+
+ setting->CryptoId = transform->TransformId;
+ setting->HashId = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_HMAC, 0);
+
+ setting->DhId = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_DH_GROUP, 0);
+
+ setting->LifeKilobytes = INFINITE;
+ setting->LifeSeconds = INFINITE;
+
+ for (i = 0;i < IkeGetTransformValueNum(transform, IKE_TRANSFORM_VALUE_P2_LIFE_TYPE);i++)
+ {
+ UINT life_type = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_LIFE_TYPE, i);
+
+ switch (life_type)
+ {
+ case IKE_P2_LIFE_TYPE_SECONDS: // Number of seconds
+ setting->LifeSeconds = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_LIFE_VALUE, i);
+ break;
+
+ case IKE_P2_LIFE_TYPE_KILOBYTES: // Kilobytes
+ setting->LifeKilobytes = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_LIFE_VALUE, i);
+ break;
+
+ default:
+ // Unsupported expiration type
+ return false;
+ }
+ }
+
+ setting->Crypto = GetIkeCrypto(ike->Engine, true, setting->CryptoId);
+ setting->Hash = GetIkeHash(ike->Engine, true, setting->HashId);
+ setting->Dh = GetIkeDh(ike->Engine, true, setting->DhId);
+
+ if (setting->Crypto == NULL || setting->Hash == NULL)
+ {
+ // Unsupported algorithm
+ return false;
+ }
+
+ if (setting->Crypto->VariableKeySize)
+ {
+ // Get the actual key size in the case of variable key size
+ setting->CryptoKeySize = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_KEY_SIZE, 0);
+
+ // bits -> bytes
+ setting->CryptoKeySize = setting->CryptoKeySize / 8;
+
+ if (setting->CryptoKeySize == 0 || IkeCheckKeySize(setting->Crypto, setting->CryptoKeySize) == false)
+ {
+ // The key size is not specified or inappropriate
+ return false;
+ }
+ }
+ else
+ {
+ // Get a fixed key length for fixed key size
+ setting->CryptoKeySize = setting->Crypto->KeySizes[0];
+ }
+
+ capsule_mode = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P2_CAPSULE, 0);
+ if (capsule_mode != IKE_P2_CAPSULE_NAT_TUNNEL_1 && capsule_mode != IKE_P2_CAPSULE_NAT_TUNNEL_2 &&
+ capsule_mode != IKE_P2_CAPSULE_NAT_TRANSPORT_1 && capsule_mode != IKE_P2_CAPSULE_NAT_TRANSPORT_2)
+ {
+ // No support for UDP encapsulation mode except for the NAT-Traversal
+ if (capsule_mode == IKE_P2_CAPSULE_TRANSPORT || capsule_mode == IKE_P2_CAPSULE_TUNNEL)
+ {
+ if (is_esp_supported == false)
+ {
+ setting->OnlyCapsuleModeIsInvalid = true;
+ return false;
+ }
+ else
+ {
+ // It is an environment that can send and receive ESP packets
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ setting->CapsuleMode = capsule_mode;
+
+ return true;
+}
+
+// Convert a transform payload to a structure (for IKE SA)
+bool TransformPayloadToTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IKE_SA_TRANSFORM_SETTING *setting)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || transform == NULL || setting == NULL)
+ {
+ return false;
+ }
+
+ Zero(setting, sizeof(IKE_SA_TRANSFORM_SETTING));
+
+ setting->CryptoId = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_CRYPTO, 0);
+ setting->HashId = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_HASH, 0);
+
+ if (IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_AUTH_METHOD, 0) != IKE_P1_AUTH_METHOD_PRESHAREDKEY)
+ {
+ // Only PSK authentication method is supported
+ return false;
+ }
+
+ setting->DhId = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_DH_GROUP, 0);
+
+ setting->LifeKilobytes = INFINITE;
+ setting->LifeSeconds = INFINITE;
+
+ for (i = 0;i < IkeGetTransformValueNum(transform, IKE_TRANSFORM_VALUE_P1_LIFE_TYPE);i++)
+ {
+ UINT life_type = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_LIFE_TYPE, i);
+
+ switch (life_type)
+ {
+ case IKE_P1_LIFE_TYPE_SECONDS: // Number of seconds
+ setting->LifeSeconds = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_LIFE_VALUE, i);
+ break;
+
+ case IKE_P1_LIFE_TYPE_KILOBYTES: // Kilobytes
+ setting->LifeKilobytes = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_LIFE_VALUE, i);
+ break;
+
+ default:
+ // Unsupported expiration type
+ return false;
+ }
+ }
+
+ setting->Crypto = GetIkeCrypto(ike->Engine, false, setting->CryptoId);
+ setting->Hash = GetIkeHash(ike->Engine, false, setting->HashId);
+ setting->Dh = GetIkeDh(ike->Engine, false, setting->DhId);
+
+ if (setting->Crypto == NULL || setting->Hash == NULL || setting->Dh == NULL)
+ {
+ // Unsupported algorithm
+ return false;
+ }
+
+ if (setting->Crypto->VariableKeySize)
+ {
+ // Get the actual key size in the case of variable key size
+ setting->CryptoKeySize = IkeGetTransformValue(transform, IKE_TRANSFORM_VALUE_P1_KET_SIZE, 0);
+
+ // bits -> bytes
+ setting->CryptoKeySize = setting->CryptoKeySize / 8;
+
+ if (setting->CryptoKeySize == 0 || IkeCheckKeySize(setting->Crypto, setting->CryptoKeySize) == false)
+ {
+ // The key size is not specified or inappropriate
+ return false;
+ }
+ }
+ else
+ {
+ // Get a fixed key length for fixed key size
+ setting->CryptoKeySize = setting->Crypto->KeySizes[0];
+ }
+
+ return true;
+}
+
+// Creating a new Responder Cookie
+UINT64 GenerateNewResponserCookie(IKE_SERVER *ike)
+{
+ UINT64 c;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ bool b = false;
+ UINT i;
+
+ c = Rand64();
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->ResponderCookie == c)
+ {
+ b = true;
+ break;
+ }
+ }
+
+ if (b == false)
+ {
+ return c;
+ }
+ }
+}
+
+// Parse the IKE packet header
+IKE_PACKET *ParseIKEPacketHeader(UDPPACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ return IkeParseHeader(p->Data, p->Size, NULL);
+}
+
+// Search for another IPsec SA belonging to the IKE_CLIENT which have same conditions to the specified IPsec SA
+IPSECSA *GetOtherLatestIPsecSa(IKE_SERVER *ike, IPSECSA *sa)
+{
+ UINT i;
+ UINT64 min_value = 0;
+ IPSECSA *max_sa = NULL;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return NULL;
+ }
+
+ if (sa->IkeClient == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa2 = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa2 != sa)
+ {
+ if (sa2->IkeClient == sa->IkeClient)
+ {
+ if (sa2->ServerToClient == sa->ServerToClient)
+ {
+ if (sa2->Deleting == false)
+ {
+ if (sa2->Established)
+ {
+ UINT64 last_comm_tick = sa2->LastCommTick;
+
+ if (sa2->ServerToClient)
+ {
+ if (sa2->PairIPsecSa != NULL)
+ {
+ last_comm_tick = sa2->PairIPsecSa->LastCommTick;
+ }
+ }
+
+ if (min_value < last_comm_tick)
+ {
+ min_value = last_comm_tick;
+
+ max_sa = sa2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return max_sa;
+}
+
+// Search for another IKE_SA belonging to the IKE_CLIENT which have same conditions to the specified IKE_SA
+IKE_SA *GetOtherLatestIkeSa(IKE_SERVER *ike, IKE_SA *sa)
+{
+ UINT i;
+ UINT64 min_value = 0;
+ IKE_SA *max_sa = NULL;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return NULL;
+ }
+
+ if (sa->IkeClient == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa2 = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa2 != sa)
+ {
+ if (sa2->IkeClient == sa->IkeClient)
+ {
+ if (sa2->Deleting == false)
+ {
+ if (sa2->Established)
+ {
+ if (min_value < sa2->LastCommTick)
+ {
+ min_value = sa2->LastCommTick;
+
+ max_sa = sa2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return max_sa;
+}
+
+// Purge the IPsec SA
+void PurgeIPsecSa(IKE_SERVER *ike, IPSECSA *sa)
+{
+ UINT i;
+ IPSECSA *other_sa;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ other_sa = GetOtherLatestIPsecSa(ike, sa);
+
+ // Rewrite the pairing partner by looking for IPsec SA that are paired
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa2 = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa2->PairIPsecSa == sa)
+ {
+ sa2->PairIPsecSa = other_sa;
+ }
+ }
+
+ // Rewrite the IKE_CLIENT using this IPsec SA to use alternate
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+
+ if (c->CurrentIpSecSaRecv == sa)
+ {
+ c->CurrentIpSecSaRecv = other_sa;
+ }
+
+ if (c->CurrentIpSecSaSend == sa)
+ {
+ c->CurrentIpSecSaSend = other_sa;
+ }
+ }
+
+ Delete(ike->IPsecSaList, sa);
+ FreeIPsecSa(sa);
+}
+
+// Remove the IKE SA
+void PurgeIkeSa(IKE_SERVER *ike, IKE_SA *sa)
+{
+ IKE_SA *other_sa;
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || sa == NULL)
+ {
+ return;
+ }
+
+ Debug("Purging IKE SA %I64u-%I64u\n", sa->InitiatorCookie, sa->ResponderCookie);
+
+ // Rewrite to alternative IKE_SA of all IPsec SA that are using this IKE_SA
+ other_sa = GetOtherLatestIkeSa(ike, sa);
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *ipsec_sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (ipsec_sa->IkeSa == sa)
+ {
+ if (other_sa == NULL)
+ {
+ // Remove this IPsec SA because there is no alternative IKE_SA
+ Debug(" Deleting IPsec SA 0x%X of this IKE SA (no alternatives)\n", ipsec_sa->Spi);
+ MarkIPsecSaAsDeleted(ike, ipsec_sa);
+ ipsec_sa->IkeSa = NULL;
+ }
+ else
+ {
+ // Replace to the alternative IKE_SA
+ Debug(" Replacing IKE SA of IPsec SA 0x%X from %I64u-%I64u to %I64u-%I64u\n", ipsec_sa->Spi,
+ sa->InitiatorCookie, sa->ResponderCookie,
+ other_sa->InitiatorCookie, other_sa->ResponderCookie);
+ ipsec_sa->IkeSa = other_sa;
+ }
+ }
+ }
+
+ // Substitute the IKE_SA of all IKE_CLIENT that are using this IKE_SA with alternative
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+
+ if (c->CurrentIkeSa == sa)
+ {
+ c->CurrentIkeSa = other_sa;
+ }
+ }
+
+ Delete(ike->IkeSaList, sa);
+ FreeIkeSa(sa);
+}
+
+// Purge the IKE_CLIENT
+void PurgeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL || c == NULL)
+ {
+ return;
+ }
+
+ // Delete all of IPsec SA and IKE SA that belong to this IKE Client
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ MarkIkeSaAsDeleted(ike, sa);
+ }
+ }
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ if (sa->IkeClient == c)
+ {
+ MarkIPsecSaAsDeleted(ike, sa);
+ }
+ }
+
+ Delete(ike->ClientList, c);
+ FreeIkeClient(ike, c);
+}
+
+// Remove the SA that has been marked to delete
+void PurgeDeletingSAsAndClients(IKE_SERVER *ike)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+ if (sa->Deleting)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, sa);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_SA *sa = LIST_DATA(o, i);
+
+ PurgeIkeSa(ike, sa);
+ }
+
+ ReleaseList(o);
+
+ o = NULL;
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+ if (sa->Deleting)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, sa);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IPSECSA *sa = LIST_DATA(o, i);
+
+ PurgeIPsecSa(ike, sa);
+ }
+
+ ReleaseList(o);
+
+ o = NULL;
+
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+ if (c->Deleting)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, c);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(o, i);
+
+ PurgeIkeClient(ike, c);
+ }
+
+ ReleaseList(o);
+}
+
+// IKE interrupt process
+void ProcessIKEInterrupts(IKE_SERVER *ike)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+
+ c->CurrentExpiresSoftTick_CtoS = 0;
+ c->CurrentExpiresSoftTick_StoC = 0;
+ c->CurrentNumEstablishedIPsecSA_CtoS = 0;
+ c->CurrentNumEstablishedIPsecSA_StoC = 0;
+ c->CurrentNumHealtyIPsecSA_CtoS = 0;
+ c->CurrentNumHealtyIPsecSA_StoC = 0;
+ }
+
+ // Packet retransmission by scanning all IKE SA
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ if (sa->SendBuffer != NULL)
+ {
+ if (ike->Now >= sa->NextSendTick)
+ {
+ IKE_CLIENT *c = sa->IkeClient;
+
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ISAKMP, &c->ServerIP, c->ServerPort, &c->ClientIP, c->ClientPort,
+ Clone(sa->SendBuffer->Buf, sa->SendBuffer->Size), sa->SendBuffer->Size);
+
+ sa->NextSendTick += (UINT64)(IKE_SA_RESEND_INTERVAL);
+
+ AddInterrupt(ike->Interrupts, sa->NextSendTick);
+
+ if (sa->NumResends != 0)
+ {
+ sa->NumResends--;
+ if (sa->NumResends == 0)
+ {
+ sa->NextSendTick = 0;
+ FreeBuf(sa->SendBuffer);
+ sa->SendBuffer = NULL;
+ }
+ }
+ }
+ }
+
+ // Remove those of non-communication
+ if (sa->IkeClient == NULL || (sa->IkeClient->CurrentIkeSa != sa))
+ {
+ // When the IKE_CLIENT don't point this
+ if (sa->Established == false)
+ {
+ // Make time-out in a short time when it is not established
+ if ((sa->LastCommTick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT_FOR_NOT_ESTABLISHED) <= ike->Now)
+ {
+ WHERE;
+ MarkIkeSaAsDeleted(ike, sa);
+ }
+ }
+ else
+ {
+ // Timeout in a long time in the case of established
+ if ((sa->LastCommTick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT) <= ike->Now)
+ {
+ WHERE;
+ MarkIkeSaAsDeleted(ike, sa);
+ }
+ }
+ }
+ }
+
+ // Packet retransmission by scanning all IPsec SA
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+ IKE_CLIENT *c = sa->IkeClient;
+
+ if (sa->SendBuffer != NULL)
+ {
+ if (ike->Now >= sa->NextSendTick)
+ {
+ IKE_CLIENT *c = sa->IkeClient;
+
+ IkeSendUdpPacket(ike, IKE_UDP_TYPE_ISAKMP, &c->ServerIP, c->ServerPort, &c->ClientIP, c->ClientPort,
+ Clone(sa->SendBuffer->Buf, sa->SendBuffer->Size), sa->SendBuffer->Size);
+
+ sa->NextSendTick += (UINT64)(IKE_SA_RESEND_INTERVAL);
+
+ AddInterrupt(ike->Interrupts, sa->NextSendTick);
+
+ if (sa->NumResends != 0)
+ {
+ sa->NumResends--;
+
+ if (sa->NumResends == 0)
+ {
+ sa->NextSendTick = 0;
+ FreeBuf(sa->SendBuffer);
+ sa->SendBuffer = NULL;
+ }
+ }
+ }
+ }
+
+ if (sa->Established && sa->Deleting == false && c != NULL)
+ {
+ // Get the flexible expiration date of SA for each IKE_CLIENT
+ if (sa->ServerToClient)
+ {
+ c->CurrentExpiresSoftTick_StoC = MAX(c->CurrentExpiresSoftTick_StoC, sa->ExpiresSoftTick);
+ c->CurrentNumEstablishedIPsecSA_StoC++;
+
+ if (sa->ExpiresSoftTick == 0 || sa->ExpiresSoftTick > ike->Now)
+ {
+ c->CurrentNumHealtyIPsecSA_StoC++;
+ }
+ }
+ else
+ {
+ c->CurrentExpiresSoftTick_CtoS = MAX(c->CurrentExpiresSoftTick_CtoS, sa->ExpiresSoftTick);
+ c->CurrentNumEstablishedIPsecSA_CtoS++;
+
+ if (sa->ExpiresSoftTick == 0 || sa->ExpiresSoftTick > ike->Now)
+ {
+ c->CurrentNumHealtyIPsecSA_CtoS++;
+ }
+ }
+ }
+
+ // Remove those of non-communication
+ if (sa->IkeClient == NULL || (sa->IkeClient->CurrentIpSecSaRecv != sa && sa->IkeClient->CurrentIpSecSaSend != sa))
+ {
+ // When the IKE_CLIENT don't point this
+ UINT64 last_comm_tick = sa->LastCommTick;
+
+ if (sa->ServerToClient && sa->PairIPsecSa != NULL)
+ {
+ last_comm_tick = sa->PairIPsecSa->LastCommTick;
+ }
+
+ if (sa->Established == false)
+ {
+ // Make time-out in a short time when it is not established
+ if ((last_comm_tick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT_FOR_NOT_ESTABLISHED) <= ike->Now)
+ {
+ WHERE;
+ MarkIPsecSaAsDeleted(ike, sa);
+ }
+ }
+ else
+ {
+ // Timeout in a long time in the case of established
+ if ((last_comm_tick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT) <= ike->Now)
+ {
+ WHERE;
+ MarkIPsecSaAsDeleted(ike, sa);
+ }
+ }
+ }
+ }
+
+ // IKE_CLIENT scanning process
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+ UINT64 tick;
+ UCHAR data[1];
+ bool need_qm = false;
+ bool need_qm_hard = false;
+ UINT64 qm_soft_tick = 0;
+
+ // Determine whether it is necessary to start a new Quick Mode
+ if (c->CurrentExpiresSoftTick_StoC != 0 && ike->Now >= c->CurrentExpiresSoftTick_StoC)
+ {
+ need_qm = true;
+ qm_soft_tick = MAX(qm_soft_tick, c->CurrentExpiresSoftTick_StoC);
+ }
+
+ if (c->CurrentExpiresSoftTick_CtoS != 0 && ike->Now >= c->CurrentExpiresSoftTick_CtoS)
+ {
+ need_qm = true;
+ qm_soft_tick = MAX(qm_soft_tick, c->CurrentExpiresSoftTick_StoC);
+ }
+
+ if (c->CurrentNumHealtyIPsecSA_CtoS == 0 || c->CurrentNumHealtyIPsecSA_StoC == 0)
+ {
+ need_qm = true;
+ need_qm_hard = true;
+ }
+
+ if (c->StartQuickModeAsSoon)
+ {
+ need_qm = true;
+ need_qm_hard = true;
+ }
+
+ if (c->Deleting || c->CurrentIkeSa == NULL || c->CurrentIkeSa->Deleting)
+ {
+ need_qm = false;
+ need_qm_hard = true;
+ }
+
+ if (need_qm)
+ {
+ if (c->StartQuickModeAsSoon || ((c->LastQuickModeStartTick + (UINT64)IKE_QUICKMODE_START_INTERVAL) <= ike->Now))
+ {
+ // Start the Quick Mode
+ Debug("IKE_CLIENT 0x%X: Begin QuickMode\n", c);
+ c->StartQuickModeAsSoon = false;
+ c->LastQuickModeStartTick = ike->Now;
+
+ AddInterrupt(ike->Interrupts, c->LastQuickModeStartTick + (UINT64)IKE_QUICKMODE_START_INTERVAL);
+
+ StartQuickMode(ike, c);
+ }
+ }
+
+ if (need_qm_hard)
+ {
+ if (c->NeedQmBeginTick == 0)
+ {
+ c->NeedQmBeginTick = ike->Now;
+ }
+ }
+ else
+ {
+ c->NeedQmBeginTick = 0;
+ }
+
+ if (((c->LastCommTick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT) <= ike->Now) ||
+ ((c->CurrentIkeSa == NULL && c->CurrentIpSecSaRecv == NULL && c->CurrentIpSecSaSend == NULL) && (c->LastCommTick + (UINT64)IKE_TIMEOUT_FOR_IKE_CLIENT_FOR_NOT_ESTABLISHED) <= ike->Now) ||
+ (c->NeedQmBeginTick != 0 && ((c->NeedQmBeginTick + (UINT64)IKE_QUICKMODE_FAILED_TIMEOUT) <= ike->Now)))
+ {
+ // Remove IKE_CLIENT not communicating for a certain period of time
+ WHERE;
+ MarkIkeClientAsDeleted(ike, c);
+ }
+
+ // L2TP processing
+ if (c->L2TP != NULL)
+ {
+ IPsecIkeClientManageL2TPServer(ike, c);
+
+ // Interrupt processing occurs
+ L2TPProcessInterrupts(c->L2TP);
+
+ // Packet transmission
+ IPsecIkeClientSendL2TPPackets(ike, c, c->L2TP);
+ }
+
+ // EtherIP processing
+ if (c->EtherIP != NULL)
+ {
+ IPsecIkeClientManageEtherIPServer(ike, c);
+
+ // Interrupt processing occurs
+ EtherIPProcInterrupts(c->EtherIP);
+
+ // Packet transmission
+ IPsecIkeClientSendEtherIPPackets(ike, c, c->EtherIP);
+ }
+
+ // KeepAlive transmission
+ tick = MAX(c->LastCommTick + (UINT64)IKE_INTERVAL_UDP_KEEPALIVE, c->NextKeepAliveSendTick);
+
+ if (tick <= ike->Now && c->ServerPort == IPSEC_PORT_IPSEC_ESP_UDP)
+ {
+ c->NextKeepAliveSendTick = ike->Now + (UINT64)IKE_INTERVAL_UDP_KEEPALIVE;
+
+ AddInterrupt(ike->Interrupts, c->NextKeepAliveSendTick);
+
+ Zero(data, sizeof(data));
+ data[0] = 0xff;
+
+ IkeSendUdpPacket(ike, IKE_UDP_KEEPALIVE, &c->ServerIP, c->ServerPort, &c->ClientIP, c->ClientPort, Clone(data, sizeof(data)), sizeof(data));
+ }
+
+ // DPD transmission
+ if (c->NextDpdSendTick == 0 || c->NextDpdSendTick <= ike->Now)
+ {
+ if (c->CurrentIkeSa != NULL && c->CurrentIkeSa->Established)
+ {
+ if (c->CurrentIkeSa->Caps.DpdRfc3706)
+ {
+ c->NextDpdSendTick = ike->Now + (UINT64)IKE_INTERVAL_DPD_KEEPALIVE;
+
+ AddInterrupt(ike->Interrupts, c->NextDpdSendTick);
+
+ SendInformationalExchangePacket(ike, c,
+ IkeNewNoticeDpdPayload(false, c->CurrentIkeSa->InitiatorCookie, c->CurrentIkeSa->ResponderCookie,
+ c->DpdSeqNo++));
+ }
+ }
+ }
+ }
+
+ do
+ {
+ ike->StateHasChanged = false;
+
+ // Deletion process
+ PurgeDeletingSAsAndClients(ike);
+ }
+ while (ike->StateHasChanged);
+
+ // Maintenance of the thread list
+ MainteThreadList(ike->ThreadList);
+ /*Debug("ike->ThreadList: %u\n", LIST_NUM(ike->ThreadList));
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(ike->ThreadList);i++)
+ {
+ THREAD *t = LIST_DATA(ike->ThreadList, i);
+
+ Debug(" Thread %u: 0x%p ID: %u Stop: %u Ref: %u\n", i, t, t->ThreadId, t->Stopped, t->ref->c->c);
+ }
+ }*/
+}
+
+// Stop the IKE server
+void StopIKEServer(IKE_SERVER *ike)
+{
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+}
+
+// Set the socket events in IKE server
+void SetIKEServerSockEvent(IKE_SERVER *ike, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ if (ike->SockEvent != NULL)
+ {
+ ReleaseSockEvent(ike->SockEvent);
+ }
+
+ ike->SockEvent = e;
+}
+
+// Release the IKE client
+void FreeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL || ike == NULL)
+ {
+ return;
+ }
+
+ if (c->L2TP != NULL)
+ {
+ StopL2TPServer(c->L2TP, true);
+ FreeL2TPServer(c->L2TP);
+ }
+
+ if (c->EtherIP != NULL)
+ {
+ ReleaseEtherIPServer(c->EtherIP);
+ }
+
+ FreeBuf(c->SendID1_Buf);
+ FreeBuf(c->SendID2_Buf);
+
+ Free(c);
+}
+
+// Release the IPsec SA
+void FreeIPsecSa(IPSECSA *sa)
+{
+ // Validate arguments
+ if (sa == NULL)
+ {
+ return;
+ }
+
+ IkeFreeKey(sa->CryptoKey);
+
+ FreeBuf(sa->SendBuffer);
+
+ FreeBuf(sa->InitiatorRand);
+ FreeBuf(sa->ResponderRand);
+
+ FreeBuf(sa->SharedKey);
+
+ IkeDhFreeCtx(sa->Dh);
+
+ Free(sa);
+}
+
+// Release the IKE SA
+void FreeIkeSa(IKE_SA *sa)
+{
+ // Validate arguments
+ if (sa == NULL)
+ {
+ return;
+ }
+
+ FreeBuf(sa->SendBuffer);
+
+ FreeBuf(sa->InitiatorRand);
+ FreeBuf(sa->ResponderRand);
+ FreeBuf(sa->DhSharedKey);
+ FreeBuf(sa->YourIDPayloadForAM);
+
+ FreeBuf(sa->GXi);
+ FreeBuf(sa->GXr);
+
+ FreeBuf(sa->SAi_b);
+
+ IkeFreeKey(sa->CryptoKey);
+
+ Free(sa);
+}
+
+// Release the IKE server
+void FreeIKEServer(IKE_SERVER *ike)
+{
+ UINT i;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+
+ IPsecLog(ike, NULL, NULL, NULL, "LI_STOPPING");
+
+ for (i = 0;i < LIST_NUM(ike->SendPacketList);i++)
+ {
+ UDPPACKET *udp = LIST_DATA(ike->SendPacketList, i);
+
+ FreeUdpPacket(udp);
+ }
+
+ ReleaseList(ike->SendPacketList);
+
+ Debug("Num of IPsec SAs: %u\n", LIST_NUM(ike->IPsecSaList));
+ IPsecLog(ike, NULL, NULL, NULL, "LI_NUM_IPSEC_SA", LIST_NUM(ike->IPsecSaList));
+
+ for (i = 0;i < LIST_NUM(ike->IPsecSaList);i++)
+ {
+ IPSECSA *sa = LIST_DATA(ike->IPsecSaList, i);
+
+ FreeIPsecSa(sa);
+ }
+
+ ReleaseList(ike->IPsecSaList);
+
+ Debug("Num of IKE SAs: %u\n", LIST_NUM(ike->IkeSaList));
+ IPsecLog(ike, NULL, NULL, NULL, "LI_NUM_IKE_SA", LIST_NUM(ike->IkeSaList));
+
+ for (i = 0;i < LIST_NUM(ike->IkeSaList);i++)
+ {
+ IKE_SA *sa = LIST_DATA(ike->IkeSaList, i);
+
+ FreeIkeSa(sa);
+ }
+
+ ReleaseList(ike->IkeSaList);
+
+ Debug("Num of IKE_CLIENTs: %u\n", LIST_NUM(ike->ClientList));
+ IPsecLog(ike, NULL, NULL, NULL, "LI_NUM_IKE_CLIENTS", LIST_NUM(ike->ClientList));
+
+ for (i = 0;i < LIST_NUM(ike->ClientList);i++)
+ {
+ IKE_CLIENT *c = LIST_DATA(ike->ClientList, i);
+
+ FreeIkeClient(ike, c);
+ }
+
+ ReleaseList(ike->ClientList);
+
+ ReleaseSockEvent(ike->SockEvent);
+
+ IPsecLog(ike, NULL, NULL, NULL, "LI_STOP");
+
+ ReleaseCedar(ike->Cedar);
+
+ FreeIkeEngine(ike->Engine);
+
+ Debug("FreeThreadList()...\n");
+ FreeThreadList(ike->ThreadList);
+ Debug("FreeThreadList() Done.\n");
+
+ Free(ike);
+}
+
+// Create a new IKE server
+IKE_SERVER *NewIKEServer(CEDAR *cedar, IPSEC_SERVER *ipsec)
+{
+ IKE_SERVER *ike;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ ike = ZeroMalloc(sizeof(IKE_SERVER));
+
+ ike->Cedar = cedar;
+ AddRef(cedar->ref);
+
+ ike->IPsec = ipsec;
+
+ ike->Now = Tick64();
+
+ ike->SendPacketList = NewList(NULL);
+
+ ike->IkeSaList = NewList(CmpIkeSa);
+
+ ike->IPsecSaList = NewList(CmpIPsecSa);
+
+ ike->ClientList = NewList(CmpIkeClient);
+
+ ike->Engine = NewIkeEngine();
+
+ ike->ThreadList = NewThreadList();
+
+ IPsecLog(ike, NULL, NULL, NULL, "LI_START");
+
+ return ike;
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IKE.h b/src/Cedar/IPsec_IKE.h
new file mode 100644
index 00000000..85e319b1
--- /dev/null
+++ b/src/Cedar/IPsec_IKE.h
@@ -0,0 +1,450 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IKE.h
+// Header of IPsec_IKE.c
+
+#ifndef IPSEC_IKE_H
+#define IPSEC_IKE_H
+
+//// Macro
+
+//// Constants
+
+// State
+#define IKE_SA_MAIN_MODE 0 // Main mode
+#define IKE_SA_AGRESSIVE_MODE 1 // Aggressive mode
+
+#define IKE_SA_MM_STATE_1_SA 0 // Main mode state 1 (SA exchange is complete. Wait for key exchange)
+#define IKE_SA_MM_STATE_2_KEY 1 // Main mode state 2 (Key exchange is complete. Wait for exchange ID)
+#define IKE_SA_MM_STATE_3_ESTABLISHED 2 // Main mode state 3 (ID exchange is complete. Established)
+
+#define IKE_SA_AM_STATE_1_SA 0 // Aggressive mode state 1 (SA exchange is completed. Wait for hash)
+#define IKE_SA_AM_STATE_2_ESTABLISHED 1 // Aggressive mode state 2 (Hash exchange is completed. Established)
+
+#define IKE_SA_RESEND_INTERVAL (2 * 1000) // IKE SA packet retransmission interval
+#define IKE_SA_RAND_SIZE 16 // Size of the random number
+
+// ESP
+#define IKE_ESP_HASH_SIZE 12 // The hash size for the ESP packet
+
+// Type of UDP packet
+#define IKE_UDP_TYPE_ISAKMP 0 // ISAKMP packet (destination 500)
+#define IKE_UDP_TYPE_ESP 1 // ESP packet (destination 4500)
+#define IKE_UDP_KEEPALIVE 2 // KeepAlive packet
+#define IKE_UDP_SPECIAL 3 // Special packet
+
+// String for Vendor ID
+#define IKE_VENDOR_ID_RFC3947_NAT_T "0x4a131c81070358455c5728f20e95452f"
+#define IKE_VENDOR_ID_IPSEC_NAT_T_IKE_03 "0x7d9419a65310ca6f2c179d9215529d56"
+#define IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02 "0x90cb80913ebb696e086381b5ec427b1f"
+#define IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02_2 "0xcd60464335df21f87cfdb2fc68b6a448"
+#define IKE_VENDOR_ID_IPSEC_NAT_T_IKE_00 "0x4485152d18b6bbcd0be8a8469579ddcc"
+#define IKE_VENDOR_ID_RFC3706_DPD "0xafcad71368a1f1c96b8696fc77570100"
+#define IKE_VENDOR_ID_MICROSOFT_L2TP "0x4048b7d56ebce88525e7de7f00d6c2d3"
+#define IKE_VENDOR_ID_MS_NT5_ISAKMPOAKLEY "0x1e2b516905991c7d7c96fcbfb587e461"
+#define IKE_VENDOR_ID_MS_VID_INITIALCONTACT "0x26244d38eddb61b3172a36e3d0cfb819"
+
+// Quota
+#define IKE_QUOTA_MAX_NUM_CLIENTS_PER_IP 1000 // The number of IKE_CLIENT per IP address
+#define IKE_QUOTA_MAX_NUM_CLIENTS 30000 // Limit number of IKE_CLIENT
+#define IKE_QUOTA_MAX_SA_PER_CLIENT 100 // The limit number of SA for each IKE_CLIENT
+
+// Time-out
+#define IKE_TIMEOUT_FOR_IKE_CLIENT 150000 // IKE_CLIENT non-communication disconnect time
+#define IKE_TIMEOUT_FOR_IKE_CLIENT_FOR_NOT_ESTABLISHED 10000 // IKE_CLIENT non-communication disconnect time (connection incomplete)
+#define IKE_INTERVAL_UDP_KEEPALIVE 5000 // UDP KeepAlive transmission interval
+#define IKE_QUICKMODE_START_INTERVAL 2000 // QuickMode start interval
+#define IKE_QUICKMODE_FAILED_TIMEOUT 10000 // Maximum time to tolerant that to fail to establish a QuickMode
+#define IKE_INTERVAL_DPD_KEEPALIVE 10000 // DPD KeepAlive transmission interval
+
+// Expiration margin
+#define IKE_SOFT_EXPIRES_MARGIN 1000 // Expiration margin
+
+
+//// Type
+
+// IKE SA transform data
+struct IKE_SA_TRANSFORM_SETTING
+{
+ IKE_CRYPTO *Crypto;
+ UINT CryptoKeySize;
+ IKE_HASH *Hash;
+ IKE_DH *Dh;
+ UINT CryptoId;
+ UINT HashId;
+ UINT DhId;
+ UINT LifeKilobytes;
+ UINT LifeSeconds;
+};
+
+// IPsec SA transforms data
+struct IPSEC_SA_TRANSFORM_SETTING
+{
+ IKE_CRYPTO *Crypto;
+ UINT CryptoKeySize;
+ IKE_HASH *Hash;
+ IKE_DH *Dh;
+ UINT CryptoId;
+ UINT HashId;
+ UINT DhId;
+ UINT LifeKilobytes;
+ UINT LifeSeconds;
+ UINT SpiServerToClient;
+ UINT CapsuleMode;
+ bool OnlyCapsuleModeIsInvalid;
+};
+
+// Function support information
+struct IKE_CAPS
+{
+ // Support Information
+ bool NatTraversalRfc3947; // RFC 3947 Negotiation of NAT-Traversal in the IKE
+ bool NatTraversalDraftIetf; // draft-ietf-ipsec-nat-t-ike
+ bool DpdRfc3706; // RFC 3706 A Traffic-Based Method of Detecting Dead Internet Key Exchange (IKE) Peers
+ bool MS_L2TPIPSecVPNClient; // Vendor ID: Microsoft L2TP/IPSec VPN Client
+ bool MS_NT5_ISAKMP_OAKLEY; // Vendor ID: MS NT5 ISAKMPOAKLEY
+ bool MS_Vid_InitialContact; // Vendor ID: Microsoft Vid-Initial-Contact
+
+ // Use information
+ bool UsingNatTraversalRfc3947;
+ bool UsingNatTraversalDraftIetf;
+};
+
+// IKE / IPsec client
+struct IKE_CLIENT
+{
+ UINT Id;
+ IP ClientIP;
+ UINT ClientPort;
+ IP ServerIP;
+ UINT ServerPort;
+ IKE_SA *CurrentIkeSa; // IKE SA to be used currently
+ IPSECSA *CurrentIpSecSaRecv; // IPsec SA to be used currently (receive direction)
+ IPSECSA *CurrentIpSecSaSend; // IPsec SA to be currently in use (transmit direction)
+ UINT64 FirstCommTick; // Time the first data communication
+ UINT64 LastCommTick; // Time that made the last communication (received data) time
+ bool Deleting; // Deleting
+ UINT64 NextKeepAliveSendTick; // Time to send the next KeepAlive
+ UINT64 NextDpdSendTick; // Time to send the next DPD
+ UINT DpdSeqNo; // DPD sequence number
+ char ClientId[128]; // ID presented by the client
+ char Secret[MAX_SIZE]; // Secret value of the authentication is successful
+
+ bool IsMicrosoft; // Whether the client is Microsoft's
+
+ IPSEC_SA_TRANSFORM_SETTING CachedTransformSetting; // Cached transform attribute value
+ UINT64 CurrentExpiresSoftTick_StoC; // The maximum value of the flexible expiration date of the current (server -> client)
+ UINT64 CurrentExpiresSoftTick_CtoS; // The maximum value of the flexible expiration date of the current (client -> server)
+ UINT CurrentNumEstablishedIPsecSA_StoC; // The number of IPsec SA currently active (server -> client)
+ UINT CurrentNumEstablishedIPsecSA_CtoS; // The number of IPsec SA currently active (client -> server)
+ UINT CurrentNumHealtyIPsecSA_CtoS; // The number of currently available IPsec SA which expiration well within (client -> server)
+ UINT CurrentNumHealtyIPsecSA_StoC; // The number of currently available IPsec SA which expiration well within (server -> client)
+ bool SendID1andID2; // Whether to send the ID in QM
+ UCHAR SendID1_Type, SendID2_Type;
+ UCHAR SendID1_Protocol, SendID2_Protocol;
+ USHORT SendID1_Port, SendID2_Port;
+ BUF *SendID1_Buf, *SendID2_Buf;
+ bool SendNatOaDraft1, SendNatOaDraft2, SendNatOaRfc; // Whether to send the NAT-OA in QM
+ bool StartQuickModeAsSoon; // Flag to indicate to the start of the Quick Mode as soon as possible
+ UINT64 LastQuickModeStartTick; // Time which the last QuickMode started
+ UINT64 NeedQmBeginTick; // Time which a start-up of QuickMode is required
+
+ // L2TP related
+ L2TP_SERVER *L2TP; // L2TP server
+ UINT L2TPClientPort; // Client-side port number of L2TP
+ IP L2TPServerIP, L2TPClientIP; // IP address used by the L2TP processing
+ bool IsL2TPOnIPsecTunnelMode; // Whether the L2TP is working on IPsec tunnel mode
+
+ // EtherIP related
+ ETHERIP_SERVER *EtherIP; // EtherIP server
+ bool IsEtherIPOnIPsecTunnelMode; // Whether the EtherIP is working on IPsec tunnel mode
+
+ // Transport mode related
+ IP TransportModeServerIP;
+ IP TransportModeClientIP;
+ bool ShouldCalcChecksumForUDP; // Flag to calculate the checksum for the UDP packet
+
+ // Tunnel mode related
+ IP TunnelModeServerIP; // Server-side internal IP address
+ IP TunnelModeClientIP; // Client-side internal IP address
+ USHORT TunnelSendIpId; // ID of the transmission IP header
+};
+
+// IKE SA
+struct IKE_SA
+{
+ UINT Id;
+ IKE_CLIENT *IkeClient; // Pointer to the IKE client
+ UINT64 InitiatorCookie, ResponderCookie; // Cookie
+ UINT Mode; // Mode
+ UINT State; // State
+ BUF *SendBuffer; // Buffer during transmission
+ UINT64 NextSendTick; // Next transmission time
+ UINT64 FirstCommTick; // Time that the first data communication
+ UINT64 EstablishedTick; // Time that the SA has been established
+ UINT64 LastCommTick; // Time that made the last communication (received data) time
+ IKE_SA_TRANSFORM_SETTING TransformSetting; // Transform Configuration
+ IKE_CAPS Caps; // IKE Caps
+ BUF *InitiatorRand, *ResponderRand; // Random number
+ BUF *DhSharedKey; // DH common key
+ BUF *GXi, *GXr; // DH exchange data
+ BUF *SAi_b; // Data needed for authentication
+ BUF *YourIDPayloadForAM; // Copy the ID payload of the client-side
+ UCHAR SKEYID[IKE_MAX_HASH_SIZE]; // Key set
+ UCHAR SKEYID_d[IKE_MAX_HASH_SIZE];
+ UCHAR SKEYID_a[IKE_MAX_HASH_SIZE];
+ UCHAR SKEYID_e[IKE_MAX_HASH_SIZE];
+ UCHAR InitiatorHashForAM[IKE_MAX_HASH_SIZE];
+ IKE_CRYPTO_KEY *CryptoKey; // Common encryption key
+ UINT HashSize; // Hash size
+ UINT KeySize; // Key size
+ UINT BlockSize; // Block size
+ UCHAR Iv[IKE_MAX_BLOCK_SIZE]; // IV
+ bool IsIvExisting; // Whether an IV exists
+ bool Established; // Established flag
+ bool Deleting; // Deleting
+ UINT NumResends; // The number of retransmissions
+ char Secret[MAX_SIZE]; // Secret value of the authentication is successful
+};
+
+// IPsec SA
+struct IPSECSA
+{
+ UINT Id;
+ IKE_CLIENT *IkeClient; // Pointer to the IKE client
+ IKE_SA *IkeSa; // Pointer to IKE_SA to use for transmission
+ UCHAR Iv[IKE_MAX_BLOCK_SIZE]; // IV used in the Quick Mode exchange
+ bool IsIvExisting; // Whether the IV exists
+ UINT MessageId; // Message ID used in Quick Mode exchange
+ UINT Spi; // SPI
+ UINT CurrentSeqNo; // Send sequence number
+ BUF *SendBuffer; // Buffer during transmission
+ UINT NumResends; // The number of retransmissions
+ UINT64 NextSendTick; // Next transmission date and time
+ UINT64 FirstCommTick; // Time the last data sent
+ UINT64 EstablishedTick; // Time that the SA has been established
+ UINT64 LastCommTick; // Time that made the last communication (received data) time
+ UINT64 ExpiresHardTick; // Exact expiration time
+ UINT64 ExpiresSoftTick; // Flexible expiration time
+ UINT64 TotalSize; // Size sent to and received
+ IPSEC_SA_TRANSFORM_SETTING TransformSetting; // Transform Configuration
+ bool ServerToClient; // Whether is upload direction
+ IPSECSA *PairIPsecSa; // IPsec SA that are paired
+ bool Established; // Established flag
+ BUF *InitiatorRand, *ResponderRand; // Random number
+ BUF *SharedKey; // PFS shared key
+ UCHAR Hash3[IKE_MAX_HASH_SIZE]; // Hash 3
+ UCHAR KeyMat[IKE_MAX_KEY_SIZE + IKE_MAX_HASH_SIZE]; // Encryption key
+ UCHAR HashKey[IKE_MAX_HASH_SIZE]; // Hash key
+ IKE_CRYPTO_KEY *CryptoKey; // Key data
+ bool Deleting; // Deleting
+ UCHAR EspIv[IKE_MAX_BLOCK_SIZE]; // IV for ESP communication
+ bool Initiated; // The server-side is initiator
+ DH_CTX *Dh; // DH (only if the server-side is initiator)
+ bool StartQM_FlagSet; // Whether the flag to indicate to do the QM is set to the IKE_CLIENT
+ UCHAR SKEYID_d[IKE_MAX_HASH_SIZE];
+ UCHAR SKEYID_a[IKE_MAX_HASH_SIZE];
+ IKE_HASH *SKEYID_Hash;
+};
+
+// IKE server
+struct IKE_SERVER
+{
+ CEDAR *Cedar;
+ IPSEC_SERVER *IPsec;
+ UINT64 Now; // Current time
+ LIST *SendPacketList; // Transmission packet
+ INTERRUPT_MANAGER *Interrupts; // Interrupt manager
+ SOCK_EVENT *SockEvent; // SockEvent
+ IKE_ENGINE *Engine; // Encryption engine
+ LIST *ClientList; // Client list
+ LIST *IkeSaList; // SA list
+ LIST *IPsecSaList; // IPsec SA list
+ LIST *ThreadList; // L2TP thread list
+ bool StateHasChanged; // Flag whether the state has changed
+ UINT CurrentIkeSaId, CurrentIPsecSaId, CurrentIkeClientId, CurrentEtherId; // Serial number ID
+
+ // Setting data
+ char Secret[MAX_SIZE]; // Pre-shared key
+};
+
+
+//// Function prototype
+IKE_SERVER *NewIKEServer(CEDAR *cedar, IPSEC_SERVER *ipsec);
+void FreeIKEServer(IKE_SERVER *ike);
+void SetIKEServerSockEvent(IKE_SERVER *ike, SOCK_EVENT *e);
+void ProcIKEPacketRecv(IKE_SERVER *ike, UDPPACKET *p);
+void StopIKEServer(IKE_SERVER *ike);
+void ProcessIKEInterrupts(IKE_SERVER *ike);
+IKE_PACKET *ParseIKEPacketHeader(UDPPACKET *p);
+void ProcIkeMainModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
+void ProcIkeQuickModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
+void ProcIkeAggressiveModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
+void ProcIkeInformationalExchangePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
+void FreeIkeSa(IKE_SA *sa);
+void FreeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
+UINT64 GenerateNewResponserCookie(IKE_SERVER *ike);
+bool GetBestTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET *pr, IKE_SA_TRANSFORM_SETTING *setting);
+bool TransformPayloadToTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IKE_SA_TRANSFORM_SETTING *setting);
+IKE_CLIENT *SearchIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr);
+IKE_CLIENT *SearchOrCreateNewIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr);
+UINT GetNumberOfIkeClientsFromIP(IKE_SERVER *ike, IP *client_ip);
+UINT GetNumberOfIPsecSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
+UINT GetNumberOfIkeSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
+int CmpIkeClient(void *p1, void *p2);
+int CmpIkeSa(void *p1, void *p2);
+int CmpIPsecSa(void *p1, void *p2);
+IKE_SA *FindIkeSaByEndPointAndInitiatorCookie(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, UINT64 init_cookie, UINT mode);
+IKE_SA *FindIkeSaByResponderCookie(IKE_SERVER *ike, UINT64 responder_cookie);
+IKE_SA *FindIkeSaByResponderCookieAndClient(IKE_SERVER *ike, UINT64 responder_cookie, IKE_CLIENT *c);
+IKE_CLIENT *NewIkeClient(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+IKE_CLIENT *SetIkeClientEndpoint(IKE_SERVER *ike, IKE_CLIENT *c, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+IKE_SA *NewIkeSa(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT mode, IKE_SA_TRANSFORM_SETTING *setting);
+IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIke(IKE_SERVER *ike, IKE_SA_TRANSFORM_SETTING *setting);
+void IkeSaSendPacket(IKE_SERVER *ike, IKE_SA *sa, IKE_PACKET *p);
+IKE_PACKET *IkeSaRecvPacket(IKE_SERVER *ike, IKE_SA *sa, void *data, UINT size);
+void IkeSendUdpPacket(IKE_SERVER *ike, UINT type, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, void *data, UINT size);
+void IkeAddVendorIdPayloads(IKE_PACKET *p);
+BUF *IkeStrToVendorId(char *str);
+void IkeAddVendorId(IKE_PACKET *p, char *str);
+bool IkeIsVendorIdExists(IKE_PACKET *p, char *str);
+void IkeCheckCaps(IKE_CAPS *caps, IKE_PACKET *p);
+BUF *IkeCalcNatDetectHash(IKE_SERVER *ike, IKE_HASH *hash, UINT64 initiator_cookie, UINT64 responder_cookie, IP *ip, UINT port);
+void IkeCalcSaKeySet(IKE_SERVER *ike, IKE_SA *sa, char *secret);
+IKE_CRYPTO_KEY *IkeNewCryptoKeyFromK(IKE_SERVER *ike, void *k, UINT k_size, IKE_HASH *h, IKE_CRYPTO *c, UINT crypto_key_size);
+BUF *IkeExpandKeySize(IKE_HASH *h, void *k, UINT k_size, UINT target_size);
+void IkeSaUpdateIv(IKE_SA *sa, void *iv, UINT iv_size);
+IPSECSA *NewIPsecSa(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, bool initiate, UINT message_id, bool server_to_client, void *iv, UINT spi, void *init_rand_data, UINT init_rand_size, void *res_rand_data, UINT res_rand_size, IPSEC_SA_TRANSFORM_SETTING *setting, void *shared_key_data, UINT shared_key_size);
+void IkeCalcPhase2InitialIv(void *iv, IKE_SA *sa, UINT message_id);
+bool GetBestTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET *pr, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip);
+bool TransformPayloadToTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip);
+IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIPsec(IKE_SERVER *ike, IPSEC_SA_TRANSFORM_SETTING *setting);
+UINT GenerateNewIPsecSaSpi(IKE_SERVER *ike, UINT counterpart_spi);
+IPSECSA *SearchClientToServerIPsecSaBySpi(IKE_SERVER *ike, UINT spi);
+IPSECSA *SearchIPsecSaBySpi(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi);
+IPSECSA *SearchIPsecSaByMessageId(IKE_SERVER *ike, IKE_CLIENT *c, UINT message_id);
+void IPsecSaSendPacket(IKE_SERVER *ike, IPSECSA *sa, IKE_PACKET *p);
+IKE_PACKET *IPsecSaRecvPacket(IKE_SERVER *ike, IPSECSA *sa, void *data, UINT size);
+void IPsecSaUpdateIv(IPSECSA *sa, void *iv, UINT iv_size);
+void ProcDeletePayload(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_DELETE_PAYLOAD *d);
+void MarkIPsecSaAsDeleted(IKE_SERVER *ike, IPSECSA *sa);
+void MarkIkeSaAsDeleted(IKE_SERVER *ike, IKE_SA *sa);
+void PurgeDeletingSAsAndClients(IKE_SERVER *ike);
+void PurgeIPsecSa(IKE_SERVER *ike, IPSECSA *sa);
+void PurgeIkeSa(IKE_SERVER *ike, IKE_SA *sa);
+void PurgeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
+void FreeIPsecSa(IPSECSA *sa);
+void MarkIkeClientAsDeleted(IKE_SERVER *ike, IKE_CLIENT *c);
+IKE_SA *GetOtherLatestIkeSa(IKE_SERVER *ike, IKE_SA *sa);
+IPSECSA *GetOtherLatestIPsecSa(IKE_SERVER *ike, IPSECSA *sa);
+void SendInformationalExchangePacket(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload);
+void SendInformationalExchangePacketEx(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload, bool force_plain, UINT64 init_cookie, UINT64 resp_cookie);
+void SendDeleteIkeSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT64 resp_cookie);
+void SendDeleteIPsecSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi);
+void IPsecCalcKeymat(IKE_SERVER *ike, IKE_HASH *h, void *dst, UINT dst_size, void *skeyid_d_data, UINT skeyid_d_size, UCHAR protocol, UINT spi, void *rand_init_data, UINT rand_init_size,
+ void *rand_resp_data, UINT rand_resp_size, void *df_key_data, UINT df_key_size);
+
+void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p);
+void ProcIPsecUdpPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size);
+void IPsecSendPacketByIPsecSa(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id);
+void IPsecSendPacketByIPsecSaInner(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id);
+void IPsecSendPacketByIkeClient(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, UCHAR protocol_id);
+void IPsecSendUdpPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT src_port, UINT dst_port, UCHAR *data, UINT data_size);
+void IPsecIkeClientManageL2TPServer(IKE_SERVER *ike, IKE_CLIENT *c);
+void IPsecIkeClientSendL2TPPackets(IKE_SERVER *ike, IKE_CLIENT *c, L2TP_SERVER *l2tp);
+void IPsecIkeSendUdpForDebug(UINT dst_port, UINT dst_ip, void *data, UINT size);
+void StartQuickMode(IKE_SERVER *ike, IKE_CLIENT *c);
+UINT GenerateNewMessageId(IKE_SERVER *ike);
+
+void IPsecIkeClientManageEtherIPServer(IKE_SERVER *ike, IKE_CLIENT *c);
+void IPsecIkeClientSendEtherIPPackets(IKE_SERVER *ike, IKE_CLIENT *c, ETHERIP_SERVER *s);
+void ProcIPsecEtherIPPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode);
+bool IsIPsecSaTunnelMode(IPSECSA *sa);
+void ProcL2TPv3PacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode);
+
+IKE_SA *SearchIkeSaByCookie(IKE_SERVER *ike, UINT64 init_cookie, UINT64 resp_cookie);
+
+#endif // IPSEC_IKE_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IPC.c b/src/Cedar/IPsec_IPC.c
new file mode 100644
index 00000000..de883ade
--- /dev/null
+++ b/src/Cedar/IPsec_IPC.c
@@ -0,0 +1,2028 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IPC.c
+// In-process VPN client module
+
+#include "CedarPch.h"
+
+// Extract the MS-CHAP v2 authentication information by parsing the password string
+bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (d == NULL || password == NULL)
+ {
+ return false;
+ }
+
+ Zero(d, sizeof(IPC_MSCHAP_V2_AUTHINFO));
+
+ if (StartWith(password, IPC_PASSWORD_MSCHAPV2_TAG) == false)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithNullStr(password, ":");
+
+ if (t->NumTokens == 5)
+ {
+ BUF *b1, *b2, *b3;
+
+ b1 = StrToBin(t->Token[2]);
+ b2 = StrToBin(t->Token[3]);
+ b3 = StrToBin(t->Token[4]);
+
+ if (IsEmptyStr(t->Token[1]) == false && b1->Size == 16 && b2->Size == 16 && b3->Size == 24)
+ {
+ StrCpy(d->MsChapV2_PPPUsername, sizeof(d->MsChapV2_PPPUsername), t->Token[1]);
+ Copy(d->MsChapV2_ServerChallenge, b1->Buf, 16);
+ Copy(d->MsChapV2_ClientChallenge, b2->Buf, 16);
+ Copy(d->MsChapV2_ClientResponse, b3->Buf, 24);
+
+ ret = true;
+ }
+
+ FreeBuf(b1);
+ FreeBuf(b2);
+ FreeBuf(b3);
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Start an IPC connection asynchronously
+IPC_ASYNC *NewIPCAsync(CEDAR *cedar, IPC_PARAM *param, SOCK_EVENT *sock_event)
+{
+ IPC_ASYNC *a;
+ // Validate arguments
+ if (cedar == NULL || param == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(IPC_ASYNC));
+
+ a->TubeForDisconnect = NewTube(0);
+
+ a->Cedar = cedar;
+ AddRef(a->Cedar->ref);
+
+ Copy(&a->Param, param, sizeof(IPC_PARAM));
+
+ if (sock_event != NULL)
+ {
+ a->SockEvent = sock_event;
+ AddRef(a->SockEvent->ref);
+ }
+
+ a->Thread = NewThread(IPCAsyncThreadProc, a);
+
+ return a;
+}
+
+// asynchronous IPC connection creation thread
+void IPCAsyncThreadProc(THREAD *thread, void *param)
+{
+ IPC_ASYNC *a;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ a = (IPC_ASYNC *)param;
+
+ // Attempt to connect
+ a->Ipc = NewIPCByParam(a->Cedar, &a->Param, &a->ErrorCode);
+
+ if (a->Ipc != NULL)
+ {
+ if (a->Param.IsL3Mode)
+ {
+ DHCP_OPTION_LIST cao;
+
+ Zero(&cao, sizeof(cao));
+
+ // Get an IP address from the DHCP server in the case of L3 mode
+ Debug("IPCDhcpAllocateIPEx() start...\n");
+ if (IPCDhcpAllocateIPEx(a->Ipc, &cao, a->TubeForDisconnect, a->Param.IsOpenVPN))
+ {
+ UINT t;
+ IP ip, subnet, gw;
+
+ Debug("IPCDhcpAllocateIPEx() Ok.\n");
+
+ // Calculate the DHCP update interval
+ t = cao.LeaseTime;
+ if (t == 0)
+ {
+ t = 600;
+ }
+
+ t = t / 3;
+
+ if (t == 0)
+ {
+ t = 1;
+ }
+
+ // Save the options list
+ Copy(&a->L3ClientAddressOption, &cao, sizeof(DHCP_OPTION_LIST));
+ a->L3DhcpRenewInterval = t * 1000;
+
+ // Set the obtained IP address parameters to the IPC virtual host
+ UINTToIP(&ip, cao.ClientAddress);
+ UINTToIP(&subnet, cao.SubnetMask);
+ UINTToIP(&gw, cao.Gateway);
+
+ IPCSetIPv4Parameters(a->Ipc, &ip, &subnet, &gw);
+
+ a->L3NextDhcpRenewTick = Tick64() + a->L3DhcpRenewInterval;
+ }
+ else
+ {
+ Debug("IPCDhcpAllocateIPEx() Error.\n");
+
+ a->DhcpAllocFailed = true;
+
+ FreeIPC(a->Ipc);
+ a->Ipc = NULL;
+ }
+ }
+ }
+
+ // Procedure complete
+ a->Done = true;
+
+ if (a->SockEvent != NULL)
+ {
+ SetSockEvent(a->SockEvent);
+ }
+}
+
+// Release the IPC asynchronous connection object
+void FreeIPCAsync(IPC_ASYNC *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ TubeDisconnect(a->TubeForDisconnect);
+ WaitThread(a->Thread, INFINITE);
+ ReleaseThread(a->Thread);
+
+ if (a->Ipc != NULL)
+ {
+ FreeIPC(a->Ipc);
+ a->Ipc = NULL;
+ }
+
+ if (a->SockEvent != NULL)
+ {
+ ReleaseSockEvent(a->SockEvent);
+ }
+
+ ReleaseCedar(a->Cedar);
+
+ ReleaseTube(a->TubeForDisconnect);
+ Free(a);
+}
+
+// Start a new IPC connection by specifying the parameter structure
+IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
+{
+ IPC *ipc;
+ // Validate arguments
+ if (cedar == NULL || param == NULL)
+ {
+ return NULL;
+ }
+
+ ipc = NewIPC(cedar, param->ClientName, param->Postfix, param->HubName,
+ param->UserName, param->Password, error_code, &param->ClientIp,
+ param->ClientPort, &param->ServerIp, param->ServerPort,
+ param->ClientHostname, param->CryptName,
+ param->BridgeMode, param->Mss);
+
+ return ipc;
+}
+
+// Start a new IPC connection
+IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
+ UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
+ char *client_hostname, char *crypt_name,
+ bool bridge_mode, UINT mss)
+{
+ IPC *ipc;
+ UINT dummy_int = 0;
+ SOCK *a;
+ SOCK *s;
+ PACK *p;
+ UINT err = ERR_INTERNAL_ERROR;
+ char server_str[MAX_SIZE];
+ char macstr[30];
+ UINT server_ver, server_build;
+ UCHAR unique[SHA1_SIZE];
+ NODE_INFO info;
+ BUF *b;
+ UCHAR mschap_v2_server_response_20[20];
+ // Validate arguments
+ if (cedar == NULL || username == NULL || password == NULL || client_hostname == NULL)
+ {
+ return NULL;
+ }
+ if (IsEmptyStr(client_name))
+ {
+ client_name = "InProc VPN Connection";
+ }
+ if (IsEmptyStr(crypt_name))
+ {
+ crypt_name = "";
+ }
+ if (error_code == NULL)
+ {
+ error_code = &dummy_int;
+ }
+
+ Zero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
+
+ err = *error_code = ERR_INTERNAL_ERROR;
+
+ a = GetInProcListeningSock(cedar);
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ ipc = ZeroMalloc(sizeof(IPC));
+
+ ipc->Cedar = cedar;
+ AddRef(cedar->ref);
+
+ ipc->FlushList = NewTubeFlushList();
+
+ StrCpy(ipc->ClientHostname, sizeof(ipc->ClientHostname), client_hostname);
+ StrCpy(ipc->HubName, sizeof(ipc->HubName), hubname);
+ StrCpy(ipc->UserName, sizeof(ipc->UserName), username);
+ StrCpy(ipc->Password, sizeof(ipc->Password), password);
+
+ // Connect the in-process socket
+ s = ConnectInProc(a, client_ip, client_port, server_ip, server_port);
+ if (s == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Protocol initialization process
+ if (ClientUploadSignature(s) == false)
+ {
+ err = ERR_DISCONNECTED;
+ goto LABEL_ERROR;
+ }
+
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ err = ERR_DISCONNECTED;
+ goto LABEL_ERROR;
+ }
+
+ err = GetErrorFromPack(p);
+ if (err != ERR_NO_ERROR)
+ {
+ FreePack(p);
+ goto LABEL_ERROR;
+ }
+
+ if (GetHello(p, ipc->random, &server_ver, &server_build, server_str, sizeof(server_str)) == false)
+ {
+ FreePack(p);
+ err = ERR_DISCONNECTED;
+ goto LABEL_ERROR;
+ }
+
+ FreePack(p);
+
+ // Upload the authentication data
+ p = PackLoginWithPlainPassword(hubname, username, password);
+ PackAddInt64(p, "timestamp", SystemTime64());
+ PackAddStr(p, "hello", client_name);
+ PackAddInt(p, "client_ver", cedar->Version);
+ PackAddInt(p, "client_build", cedar->Build);
+ PackAddInt(p, "max_connection", 1);
+ PackAddInt(p, "use_encrypt", 0);
+ PackAddInt(p, "use_compress", 0);
+ PackAddInt(p, "half_connection", 0);
+ PackAddInt(p, "adjust_mss", mss);
+ PackAddBool(p, "require_bridge_routing_mode", bridge_mode);
+ PackAddBool(p, "require_monitor_mode", false);
+ PackAddBool(p, "qos", false);
+
+ // Unique ID is determined by the sum of the connecting client IP address and the client_name
+ b = NewBuf();
+ WriteBuf(b, client_ip, sizeof(IP));
+ WriteBufStr(b, client_name);
+ WriteBufStr(b, crypt_name);
+
+ HashSha1(unique, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ PackAddData(p, "unique_id", unique, SHA1_SIZE);
+
+ PackAddStr(p, "inproc_postfix", postfix);
+ PackAddStr(p, "inproc_cryptname", crypt_name);
+
+ // Node information
+ Zero(&info, sizeof(info));
+ StrCpy(info.ClientProductName, sizeof(info.ClientProductName), client_name);
+ info.ClientProductVer = Endian32(cedar->Version);
+ info.ClientProductBuild = Endian32(cedar->Build);
+ StrCpy(info.ServerProductName, sizeof(info.ServerProductName), server_str);
+ info.ServerProductVer = Endian32(server_ver);
+ info.ServerProductBuild = Endian32(server_build);
+ StrCpy(info.ClientOsName, sizeof(info.ClientOsName), client_name);
+ StrCpy(info.ClientOsVer, sizeof(info.ClientOsVer), "-");
+ StrCpy(info.ClientOsProductId, sizeof(info.ClientOsProductId), "-");
+ info.ClientIpAddress = IPToUINT(&s->LocalIP);
+ info.ClientPort = Endian32(s->LocalPort);
+ StrCpy(info.ClientHostname, sizeof(info.ClientHostname), ipc->ClientHostname);
+ IPToStr(info.ServerHostname, sizeof(info.ServerHostname), &s->RemoteIP);
+ info.ServerIpAddress = IPToUINT(&s->RemoteIP);
+ info.ServerPort = Endian32(s->RemotePort);
+ StrCpy(info.HubName, sizeof(info.HubName), hubname);
+ Copy(info.UniqueId, unique, 16);
+ if (IsIP6(&s->LocalIP))
+ {
+ Copy(info.ClientIpAddress6, s->LocalIP.ipv6_addr, 16);
+ }
+ if (IsIP6(&s->RemoteIP))
+ {
+ Copy(info.ServerIpAddress6, s->RemoteIP.ipv6_addr, 16);
+ }
+ OutRpcNodeInfo(p, &info);
+
+ if (HttpClientSend(s, p) == false)
+ {
+ FreePack(p);
+ err = ERR_DISCONNECTED;
+ goto LABEL_ERROR;
+ }
+
+ FreePack(p);
+
+ // Receive a Welcome packet
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ err = ERR_DISCONNECTED;
+ goto LABEL_ERROR;
+ }
+
+ err = GetErrorFromPack(p);
+ if (err != ERR_NO_ERROR)
+ {
+ FreePack(p);
+ goto LABEL_ERROR;
+ }
+
+ if (ParseWelcomeFromPack(p, ipc->SessionName, sizeof(ipc->SessionName),
+ ipc->ConnectionName, sizeof(ipc->ConnectionName), &ipc->Policy) == false)
+ {
+ err = ERR_PROTOCOL_ERROR;
+ FreePack(p);
+ goto LABEL_ERROR;
+ }
+
+ if (PackGetData2(p, "IpcMacAddress", ipc->MacAddress, 6) == false || IsZero(ipc->MacAddress, 6))
+ {
+ err = ERR_PROTOCOL_ERROR;
+ FreePack(p);
+ goto LABEL_ERROR;
+ }
+
+ if (PackGetData2(p, "IpcMsChapV2ServerResponse", mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20)))
+ {
+ Copy(ipc->MsChapV2_ServerResponse, mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
+ }
+
+ PackGetStr(p, "IpcHubName", ipc->HubName, sizeof(ipc->HubName));
+ Debug("IPC Hub Name: %s\n", ipc->HubName);
+
+ MacToStr(macstr, sizeof(macstr), ipc->MacAddress);
+
+ Debug("IPC: Session = %s, Connection = %s, Mac = %s\n", ipc->SessionName, ipc->ConnectionName, macstr);
+
+ FreePack(p);
+
+ ReleaseSock(a);
+ ipc->Sock = s;
+
+ Debug("NewIPC() Succeed.\n");
+
+ ipc->Interrupt = NewInterruptManager();
+
+ // Create an ARP table
+ ipc->ArpTable = NewList(IPCCmpArpTable);
+
+ // Create an IPv4 reception queue
+ ipc->IPv4RecviedQueue = NewQueue();
+
+ return ipc;
+
+LABEL_ERROR:
+ Debug("NewIPC() Failed: Err = %u\n", err);
+ Disconnect(s);
+ ReleaseSock(s);
+ ReleaseSock(a);
+ FreeIPC(ipc);
+ *error_code = err;
+ return NULL;
+}
+
+// Create a new IPC based on SOCK
+IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address)
+{
+ IPC *ipc;
+ // Validate arguments
+ if (cedar == NULL || mac_address == NULL || s == NULL)
+ {
+ return NULL;
+ }
+
+ ipc = ZeroMalloc(sizeof(IPC));
+
+ ipc->Cedar = cedar;
+ AddRef(cedar->ref);
+
+ ipc->Sock = s;
+ AddRef(s->ref);
+
+ Copy(ipc->MacAddress, mac_address, 6);
+
+ ipc->Interrupt = NewInterruptManager();
+
+ // Create an ARP table
+ ipc->ArpTable = NewList(IPCCmpArpTable);
+
+ // Create an IPv4 reception queue
+ ipc->IPv4RecviedQueue = NewQueue();
+
+ ipc->FlushList = NewTubeFlushList();
+
+ return ipc;
+}
+
+// Get whether the IPC is connected
+bool IsIPCConnected(IPC *ipc)
+{
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return false;
+ }
+
+ if (IsTubeConnected(ipc->Sock->RecvTube) == false || IsTubeConnected(ipc->Sock->SendTube) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get to hit the SOCK_EVENT when a new data has arrived in the IPC
+void IPCSetSockEventWhenRecvL2Packet(IPC *ipc, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (ipc == NULL || e == NULL)
+ {
+ return;
+ }
+
+ JoinSockToSockEvent(ipc->Sock, e);
+}
+
+// End of IPC connection
+void FreeIPC(IPC *ipc)
+{
+ UINT i;
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return;
+ }
+
+ FreeTubeFlushList(ipc->FlushList);
+
+ Disconnect(ipc->Sock);
+ ReleaseSock(ipc->Sock);
+
+ if (ipc->Policy != NULL)
+ {
+ Free(ipc->Policy);
+ }
+
+ ReleaseCedar(ipc->Cedar);
+
+ FreeInterruptManager(ipc->Interrupt);
+
+ for (i = 0;i < LIST_NUM(ipc->ArpTable);i++)
+ {
+ IPC_ARP *a = LIST_DATA(ipc->ArpTable, i);
+ IPCFreeARP(a);
+ }
+
+ ReleaseList(ipc->ArpTable);
+
+ while (true)
+ {
+ BLOCK *b = GetNext(ipc->IPv4RecviedQueue);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+
+ ReleaseQueue(ipc->IPv4RecviedQueue);
+
+ Free(ipc);
+}
+
+// Release the IP address from the DHCP server
+void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server)
+{
+ DHCP_OPTION_LIST req;
+ UINT tran_id = Rand32();
+ // Validate arguments
+ if (ipc == NULL || dhcp_server == NULL)
+ {
+ return;
+ }
+
+ Zero(&req, sizeof(req));
+ req.Opcode = DHCP_RELEASE;
+ req.ServerAddress = IPToUINT(dhcp_server);
+
+ FreeDHCPv4Data(IPCSendDhcpRequest(ipc, NULL, tran_id, &req, 0, 0, NULL));
+}
+
+// Update the IP address using the DHCP
+void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server)
+{
+ DHCP_OPTION_LIST req;
+ UINT tran_id = Rand32();
+ // Validate arguments
+ if (ipc == NULL || dhcp_server == NULL)
+ {
+ return;
+ }
+
+ // Send a DHCP Request
+ Zero(&req, sizeof(req));
+ req.Opcode = DHCP_REQUEST;
+ StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+ req.RequestedIp = IPToUINT(&ipc->ClientIPAddress);
+
+ FreeDHCPv4Data(IPCSendDhcpRequest(ipc, dhcp_server, tran_id, &req, 0, 0, NULL));
+}
+
+// Get the information other than the IP address with using DHCP
+bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, IP *client_ip)
+{
+ DHCP_OPTION_LIST req;
+ DHCPV4_DATA *d;
+ UINT tran_id = Rand32();
+ bool ok;
+ // Validate arguments
+ if (ipc == NULL || opt == NULL || client_ip == NULL)
+ {
+ return false;
+ }
+
+ // Send a DHCP Inform
+ Zero(&req, sizeof(req));
+ req.Opcode = DHCP_INFORM;
+ req.ClientAddress = IPToUINT(client_ip);
+ StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+
+ d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_ACK, IPC_DHCP_TIMEOUT, discon_poll_tube);
+ if (d == NULL)
+ {
+ return false;
+ }
+
+ // Analyze the DHCP Ack
+ ok = true;
+ if (d->ParsedOptionList->SubnetMask == 0)
+ {
+ ok = false;
+ }
+
+ if (ok == false)
+ {
+ FreeDHCPv4Data(d);
+ return false;
+ }
+
+ Copy(opt, d->ParsedOptionList, sizeof(DHCP_OPTION_LIST));
+
+ FreeDHCPv4Data(d);
+
+ return true;
+}
+
+// Make a request for IP addresses using DHCP
+bool IPCDhcpAllocateIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube)
+{
+ return IPCDhcpAllocateIPEx(ipc, opt, discon_poll_tube, false);
+}
+bool IPCDhcpAllocateIPEx(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, bool openvpn_compatible)
+{
+ DHCP_OPTION_LIST req;
+ DHCPV4_DATA *d, *d2;
+ UINT tran_id = Rand32();
+ bool ok;
+ UINT request_ip = 0;
+ IP current_scanning_ip;
+ UCHAR current_scanning_addr8;
+ UCHAR begin_scanning_addr8;
+ UINT64 giveup = Tick64() + (UINT64)IPC_DHCP_TIMEOUT_TOTAL_GIVEUP;
+ LIST *release_list;
+ bool ret = false;
+ // Validate arguments
+ if (ipc == NULL || opt == NULL)
+ {
+ return false;
+ }
+
+ release_list = NewListFast(NULL);
+
+ Zero(&current_scanning_ip, sizeof(current_scanning_ip));
+ current_scanning_addr8 = 0;
+ begin_scanning_addr8 = 0;
+
+LABEL_RETRY_FOR_OPENVPN:
+ tran_id = Rand32();
+ // Send a DHCP Discover
+ Zero(&req, sizeof(req));
+ req.RequestedIp = request_ip;
+ req.Opcode = DHCP_DISCOVER;
+ StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+
+ d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_OFFER, IPC_DHCP_TIMEOUT, discon_poll_tube);
+ if (d == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Analyze the DHCP Offer
+ ok = true;
+ if (IsValidUnicastIPAddressUINT4(d->ParsedOptionList->ClientAddress) == false)
+ {
+ ok = false;
+ }
+ if (IsValidUnicastIPAddressUINT4(d->ParsedOptionList->ServerAddress) == false)
+ {
+ ok = false;
+ }
+ if (d->ParsedOptionList->SubnetMask == 0)
+ {
+ ok = false;
+ }
+ if (d->ParsedOptionList->LeaseTime == 0)
+ {
+ d->ParsedOptionList->LeaseTime = IPC_DHCP_DEFAULT_LEASE;
+ }
+ if (d->ParsedOptionList->LeaseTime <= IPC_DHCP_MIN_LEASE)
+ {
+ d->ParsedOptionList->LeaseTime = IPC_DHCP_MIN_LEASE;
+ }
+
+ if (ok == false)
+ {
+ FreeDHCPv4Data(d);
+ goto LABEL_CLEANUP;
+ }
+
+ if (openvpn_compatible)
+ {
+ UINT ip = d->ParsedOptionList->ClientAddress;
+
+ if (OvsIsCompatibleL3IP(ip) == false)
+ {
+ char tmp[64];
+
+ DHCP_OPTION_LIST req;
+ IPC_DHCP_RELESAE_QUEUE *q;
+
+ // If the offered IP address is not used, place the address
+ // in release memo list to release at the end of this function
+ Zero(&req, sizeof(req));
+ req.Opcode = DHCP_RELEASE;
+ req.ServerAddress = d->ParsedOptionList->ServerAddress;
+
+ q = ZeroMalloc(sizeof(IPC_DHCP_RELESAE_QUEUE));
+ Copy(&q->Req, &req, sizeof(DHCP_OPTION_LIST));
+ q->TranId = tran_id;
+ Copy(q->MacAddress, ipc->MacAddress, 6);
+
+ Add(release_list, q);
+
+ FreeDHCPv4Data(d);
+
+ if (Tick64() >= giveup)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ if (IsZero(&current_scanning_ip, sizeof(IP)))
+ {
+ UINTToIP(&current_scanning_ip, ip);
+ current_scanning_addr8 = current_scanning_ip.addr[3];
+
+ if ((current_scanning_addr8 % 4) != 1)
+ {
+ current_scanning_addr8 = (UCHAR)(((((UINT)current_scanning_addr8 - 1) / 4) + 1) * 4 + 1);
+ }
+
+ begin_scanning_addr8 = current_scanning_addr8;
+ }
+ else
+ {
+ current_scanning_addr8 += 4;
+
+ if (current_scanning_addr8 == begin_scanning_addr8)
+ {
+ goto LABEL_CLEANUP;
+ }
+ }
+
+ current_scanning_ip.addr[3] = current_scanning_addr8;
+
+ request_ip = IPToUINT(&current_scanning_ip);
+
+ IPToStr32(tmp, sizeof(tmp), request_ip);
+
+ // Generate another MAC address
+ ipc->MacAddress[5]++;
+
+ Debug("Trying Allocating IP for OpenVPN: %s\n", tmp);
+
+ goto LABEL_RETRY_FOR_OPENVPN;
+ }
+ }
+
+ // Send a DHCP Request
+ Zero(&req, sizeof(req));
+ req.Opcode = DHCP_REQUEST;
+ StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+ req.ServerAddress = d->ParsedOptionList->ServerAddress;
+ req.RequestedIp = d->ParsedOptionList->ClientAddress;
+
+ d2 = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_ACK, IPC_DHCP_TIMEOUT, discon_poll_tube);
+ if (d2 == NULL)
+ {
+ FreeDHCPv4Data(d);
+ goto LABEL_CLEANUP;
+ }
+
+ // Analyze the DHCP Ack
+ ok = true;
+ if (IsValidUnicastIPAddressUINT4(d2->ParsedOptionList->ClientAddress) == false)
+ {
+ ok = false;
+ }
+ if (IsValidUnicastIPAddressUINT4(d2->ParsedOptionList->ServerAddress) == false)
+ {
+ ok = false;
+ }
+ if (d2->ParsedOptionList->SubnetMask == 0)
+ {
+ ok = false;
+ }
+ if (d2->ParsedOptionList->LeaseTime == 0)
+ {
+ d2->ParsedOptionList->LeaseTime = IPC_DHCP_DEFAULT_LEASE;
+ }
+ if (d2->ParsedOptionList->LeaseTime <= IPC_DHCP_MIN_LEASE)
+ {
+ d2->ParsedOptionList->LeaseTime = IPC_DHCP_MIN_LEASE;
+ }
+
+ if (ok == false)
+ {
+ FreeDHCPv4Data(d);
+ FreeDHCPv4Data(d2);
+ goto LABEL_CLEANUP;
+ }
+
+ Copy(opt, d2->ParsedOptionList, sizeof(DHCP_OPTION_LIST));
+
+ FreeDHCPv4Data(d);
+ FreeDHCPv4Data(d2);
+
+ ret = true;
+
+LABEL_CLEANUP:
+ if (release_list != NULL)
+ {
+ // Release the IP address that was acquired from the DHCP server to no avail on the way
+ UINT i;
+ UCHAR mac_backup[6];
+
+ Copy(mac_backup, ipc->MacAddress, 6);
+
+ for (i = 0;i < LIST_NUM(release_list);i++)
+ {
+ IPC_DHCP_RELESAE_QUEUE *q = LIST_DATA(release_list, i);
+
+ Copy(ipc->MacAddress, q->MacAddress, 6);
+ FreeDHCPv4Data(IPCSendDhcpRequest(ipc, NULL, q->TranId, &q->Req, 0, 0, NULL));
+
+ IPCProcessInterrupts(ipc);
+
+ Free(q);
+ }
+
+ Copy(ipc->MacAddress, mac_backup, 6);
+
+ ReleaseList(release_list);
+ }
+ return ret;
+}
+
+// Send out a DHCP request, and wait for a corresponding response
+DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt, UINT expecting_code, UINT timeout, TUBE *discon_poll_tube)
+{
+ UINT resend_interval;
+ UINT64 giveup_time;
+ UINT64 next_send_time = 0;
+ TUBE *tubes[3];
+ UINT num_tubes = 0;
+ // Validate arguments
+ if (ipc == NULL || opt == NULL || (expecting_code != 0 && timeout == 0))
+ {
+ return NULL;
+ }
+
+ // Retransmission interval
+ resend_interval = MAX(1, (timeout / 3) - 100);
+
+ // Time-out time
+ giveup_time = Tick64() + (UINT64)timeout;
+
+ AddInterrupt(ipc->Interrupt, giveup_time);
+
+ tubes[num_tubes++] = ipc->Sock->RecvTube;
+ tubes[num_tubes++] = ipc->Sock->SendTube;
+
+ if (discon_poll_tube != NULL)
+ {
+ tubes[num_tubes++] = discon_poll_tube;
+ }
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ BUF *dhcp_packet;
+
+ IPCFlushArpTable(ipc);
+
+ // Time-out inspection
+ if ((expecting_code != 0) && (now >= giveup_time))
+ {
+ return NULL;
+ }
+
+ // Send by building a DHCP packet periodically
+ if (next_send_time == 0 || next_send_time <= now)
+ {
+ dhcp_packet = IPCBuildDhcpRequest(ipc, dest_ip, tran_id, opt);
+ if (dhcp_packet == NULL)
+ {
+ return NULL;
+ }
+
+ IPCSendIPv4(ipc, dhcp_packet->Buf, dhcp_packet->Size);
+
+ FreeBuf(dhcp_packet);
+
+ if (expecting_code == 0)
+ {
+ return NULL;
+ }
+
+ next_send_time = now + (UINT64)resend_interval;
+
+ AddInterrupt(ipc->Interrupt, next_send_time);
+ }
+
+ // Happy processing
+ IPCProcessL3Events(ipc);
+
+ while (true)
+ {
+ // Receive a packet
+ BLOCK *b = IPCRecvIPv4(ipc);
+ PKT *pkt;
+ DHCPV4_DATA *dhcp;
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ // Parse the packet
+ pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
+
+ dhcp = ParseDHCPv4Data(pkt);
+
+ if (dhcp != NULL)
+ {
+ if (Endian32(dhcp->Header->TransactionId) == tran_id && dhcp->OpCode == expecting_code)
+ {
+ // Expected operation code and transaction ID are returned
+ FreePacketWithData(pkt);
+ FreeBlock(b);
+
+ return dhcp;
+ }
+
+ FreeDHCPv4Data(dhcp);
+ }
+
+ FreePacketWithData(pkt);
+
+ FreeBlock(b);
+ }
+
+ if (IsTubeConnected(ipc->Sock->RecvTube) == false || IsTubeConnected(ipc->Sock->SendTube) == false ||
+ (discon_poll_tube != NULL && IsTubeConnected(discon_poll_tube) == false))
+ {
+ // Session is disconnected
+ return NULL;
+ }
+
+ // Keep the CPU waiting
+ WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(ipc->Interrupt));
+ }
+
+ return NULL;
+}
+
+// Build a DHCP request packet
+BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt)
+{
+ IPV4_HEADER ip;
+ UDP_HEADER* udp;
+ DHCPV4_HEADER dhcp;
+ UINT blank_size = 128 + 64;
+ BUF *ret;
+ BUF *b;
+ UDPV4_PSEUDO_HEADER *ph;
+ UINT ph_size;
+ UINT udp_size;
+ UINT magic_number = Endian32(DHCP_MAGIC_COOKIE);
+ USHORT checksum;
+ // Validate arguments
+ if (ipc == NULL || opt == NULL)
+ {
+ return NULL;
+ }
+
+ // DHCPv4 Options
+ b = IPCBuildDhcpRequestOptions(ipc, opt);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // DHCPv4 Header
+ Zero(&dhcp, sizeof(dhcp));
+ dhcp.OpCode = 1;
+ dhcp.HardwareType = ARP_HARDWARE_TYPE_ETHERNET;
+ dhcp.HardwareAddressSize = 6;
+ dhcp.Hops = 0;
+ dhcp.TransactionId = Endian32(tran_id);
+ dhcp.ClientIP = IPToUINT(&ipc->ClientIPAddress);
+ if (dhcp.ClientIP == 0)
+ {
+ dhcp.ClientIP = opt->ClientAddress;
+ }
+ Copy(dhcp.ClientMacAddress, ipc->MacAddress, 6);
+
+ // UDP pseudo header
+ ph_size = b->Size + sizeof(dhcp) + blank_size + sizeof(UINT) + sizeof(UDPV4_PSEUDO_HEADER);
+ udp_size = b->Size + sizeof(dhcp) + blank_size + sizeof(UINT) + sizeof(UDP_HEADER);
+
+ ph = ZeroMalloc(ph_size);
+ ph->SrcIP = IPToUINT(&ipc->ClientIPAddress);
+ ph->DstIP = IPToUINT(dest_ip);
+ ph->Protocol = IP_PROTO_UDP;
+ ph->PacketLength1 = Endian16(udp_size);
+ ph->SrcPort = Endian16(NAT_DHCP_CLIENT_PORT);
+ ph->DstPort = Endian16(NAT_DHCP_SERVER_PORT);
+ ph->PacketLength2 = Endian16(udp_size);
+
+ Copy(((UCHAR *)(ph)) + sizeof(UDPV4_PSEUDO_HEADER), &dhcp, sizeof(dhcp));
+ Copy(((UCHAR *)(ph)) + sizeof(UDPV4_PSEUDO_HEADER) + sizeof(dhcp) + blank_size, &magic_number, sizeof(UINT));
+ Copy(((UCHAR *)(ph)) + sizeof(UDPV4_PSEUDO_HEADER) + sizeof(dhcp) + blank_size + sizeof(UINT),
+ b->Buf, b->Size);
+
+ // UDP Header
+ udp = (UDP_HEADER *)(((UCHAR *)ph) + 12);
+
+ // Calculate the checksum
+ checksum = IpChecksum(ph, ph_size);
+ if (checksum == 0x0000)
+ {
+ checksum = 0xffff;
+ }
+ udp->Checksum = checksum;
+
+ // IP Header
+ Zero(&ip, sizeof(ip));
+ IPV4_SET_VERSION(&ip, 4);
+ IPV4_SET_HEADER_LEN(&ip, 5);
+ ip.Identification = Rand16();
+ ip.TimeToLive = 128;
+ ip.Protocol = IP_PROTO_UDP;
+ ip.SrcIP = IPToUINT(&ipc->ClientIPAddress);
+ if (dest_ip != NULL)
+ {
+ ip.DstIP = IPToUINT(dest_ip);
+ }
+ else
+ {
+ ip.DstIP = Endian32(0xffffffff);
+ }
+ ip.TotalLength = Endian16((USHORT)(sizeof(IPV4_HEADER) + udp_size));
+ ip.Checksum = IpChecksum(&ip, sizeof(IPV4_HEADER));
+
+ ret = NewBuf();
+
+ WriteBuf(ret, &ip, sizeof(IPV4_HEADER));
+ WriteBuf(ret, udp, udp_size);
+
+ FreeBuf(b);
+ Free(ph);
+
+ return ret;
+}
+
+// Build a option data in the DHCP request packet
+BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt)
+{
+ LIST *o;
+ UCHAR opcode;
+ UCHAR client_id[7];
+ BUF *ret;
+ // Validate arguments
+ if (ipc == NULL || opt == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ // Opcode
+ opcode = opt->Opcode;
+ Add(o, NewDhcpOption(DHCP_ID_MESSAGE_TYPE, &opcode, sizeof(opcode)));
+
+ // Server ID
+ if (opt->ServerAddress != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_SERVER_ADDRESS, &opt->ServerAddress, 4));
+ }
+
+ // Client MAC Address
+ client_id[0] = ARP_HARDWARE_TYPE_ETHERNET;
+ Copy(client_id + 1, ipc->MacAddress, 6);
+ Add(o, NewDhcpOption(DHCP_ID_CLIENT_ID, client_id, sizeof(client_id)));
+
+ // Requested IP Address
+ if (opt->RequestedIp != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_REQUEST_IP_ADDRESS, &opt->RequestedIp, 4));
+ }
+
+ // Hostname
+ if (IsEmptyStr(opt->Hostname) == false)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_HOST_NAME, opt->Hostname, StrLen(opt->Hostname)));
+ }
+
+ // Vendor
+ Add(o, NewDhcpOption(DHCP_ID_VENDOR_ID, IPC_DHCP_VENDOR_ID, StrLen(IPC_DHCP_VENDOR_ID)));
+
+ // Parameter Request List
+ if (opcode == DHCP_DISCOVER || opcode == DHCP_REQUEST || opcode == DHCP_INFORM)
+ {
+ UCHAR param_list[12];
+
+ param_list[0] = 1;
+ param_list[1] = 15;
+ param_list[2] = 3;
+ param_list[3] = 6;
+ param_list[4] = 44;
+ param_list[5] = 46;
+ param_list[6] = 47;
+ param_list[7] = 31;
+ param_list[8] = 33;
+ param_list[9] = 121;
+ param_list[10] = 249;
+ param_list[11] = 43;
+
+ Add(o, NewDhcpOption(DHCP_ID_REQ_PARAM_LIST, param_list, sizeof(param_list)));
+ }
+
+ ret = BuildDhcpOptionsBuf(o);
+
+ FreeDhcpOptions(o);
+
+ return ret;
+}
+
+// Process the received ARP
+void IPCProcessArp(IPC *ipc, BLOCK *b)
+{
+ UCHAR *dest_mac;
+ UCHAR *src_mac;
+ ARPV4_HEADER *arp;
+ UCHAR *sender_mac;
+ IP sender_ip;
+ UCHAR *target_mac;
+ IP target_ip;
+ // Validate arguments
+ if (ipc == NULL || b == NULL || b->Size < (14 + sizeof(ARPV4_HEADER)))
+ {
+ return;
+ }
+
+ dest_mac = b->Buf + 0;
+ src_mac = b->Buf + 6;
+
+ arp = (ARPV4_HEADER *)(b->Buf + 14);
+
+ if (arp->HardwareType != Endian16(ARP_HARDWARE_TYPE_ETHERNET))
+ {
+ return;
+ }
+ if (arp->ProtocolType != Endian16(MAC_PROTO_IPV4))
+ {
+ return;
+ }
+ if (arp->HardwareSize != 6 || arp->ProtocolSize != 4)
+ {
+ return;
+ }
+
+ sender_mac = arp->SrcAddress;
+ UINTToIP(&sender_ip, arp->SrcIP);
+
+ target_mac = arp->TargetAddress;
+ UINTToIP(&target_ip, arp->TargetIP);
+
+ if (CmpIpAddr(&sender_ip, &ipc->ClientIPAddress) == 0)
+ {
+ // Source is myself
+ return;
+ }
+
+ IPCAssociateOnArpTable(ipc, &sender_ip, sender_mac);
+ IPCAssociateOnArpTable(ipc, &target_ip, target_mac);
+
+ if (Endian16(arp->Operation) == ARP_OPERATION_REQUEST)
+ {
+ // Received an ARP request
+ if (CmpIpAddr(&target_ip, &ipc->ClientIPAddress) == 0)
+ {
+ // Create a response since a request for its own IP address have received
+ if (IsValidUnicastMacAddress(sender_mac))
+ {
+ UCHAR tmp[14 + sizeof(ARPV4_HEADER)];
+ ARPV4_HEADER *arp = (ARPV4_HEADER *)(tmp + 14);
+
+ Copy(tmp + 0, sender_mac, 6);
+ Copy(tmp + 6, ipc->MacAddress, 6);
+ WRITE_USHORT(tmp + 12, MAC_PROTO_ARPV4);
+
+ arp->HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp->ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp->HardwareSize = 6;
+ arp->ProtocolSize = 4;
+ arp->Operation = Endian16(ARP_OPERATION_RESPONSE);
+
+ Copy(arp->SrcAddress, ipc->MacAddress, 6);
+ arp->SrcIP = IPToUINT(&ipc->ClientIPAddress);
+
+ Copy(arp->TargetAddress, sender_mac, 6);
+ arp->TargetIP = IPToUINT(&sender_ip);
+
+ IPCSendL2(ipc, tmp, sizeof(tmp));
+ }
+ }
+ }
+}
+
+// Associate the MAC address and IP address on the ARP table
+void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address)
+{
+ IPC_ARP *a;
+ // Validate arguments
+ if (ipc == NULL || ip == NULL || IsValidUnicastIPAddress4(ip) == false || IsValidUnicastMacAddress(mac_address) == false)
+ {
+ return;
+ }
+ if (CmpIpAddr(&ipc->ClientIPAddress, ip) == 0 || Cmp(ipc->MacAddress, mac_address, 6) == 0)
+ {
+ return;
+ }
+ if (IsInSameNetwork4(ip, &ipc->ClientIPAddress, &ipc->SubnetMask) == false)
+ {
+ // Not to learn the IP address of outside the subnet
+ return;
+ }
+
+ if (CmpIpAddr(&ipc->BroadcastAddress, ip) == 0)
+ {
+ // Not to learn the broadcast IP address
+ return;
+ }
+
+ // Search whether there is ARP table entry already
+ a = IPCSearchArpTable(ipc, ip);
+ if (a == NULL)
+ {
+ // Add to the ARP table
+ a = IPCNewARP(ip, mac_address);
+
+ Insert(ipc->ArpTable, a);
+ }
+ else
+ {
+ Copy(a->MacAddress, mac_address, 6);
+
+ // There is the ARP table entry already
+ if (a->Resolved == false)
+ {
+ a->Resolved = true;
+ a->GiveupTime = 0;
+
+ // Send all the packets that are accumulated to be sent
+ while (true)
+ {
+ BLOCK *b = GetNext(a->PacketQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ IPCSendIPv4WithDestMacAddr(ipc, b->Buf, b->Size, a->MacAddress);
+
+ FreeBlock(b);
+ }
+ }
+
+ // Extend the expiration date
+ a->ExpireTime = Tick64() + (UINT64)IPC_ARP_LIFETIME;
+ }
+}
+
+// Identifiy whether the MAC address is a normal unicast address
+bool IsValidUnicastMacAddress(UCHAR *mac)
+{
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ if (mac[0] & 0x01)
+ {
+ return false;
+ }
+
+ if (IsZero(mac, 6))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Identify whether the IP address is a normal unicast address
+bool IsValidUnicastIPAddress4(IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP4(ip) == false)
+ {
+ return false;
+ }
+
+ if (IsZeroIP(ip))
+ {
+ return false;
+ }
+
+ if (ip->addr[0] >= 224 && ip->addr[0] <= 239)
+ {
+ // IPv4 Multicast
+ return false;
+ }
+
+ for (i = 0;i < 4;i++)
+ {
+ if (ip->addr[i] != 255)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+bool IsValidUnicastIPAddressUINT4(UINT ip)
+{
+ IP a;
+
+ UINTToIP(&a, ip);
+
+ return IsValidUnicastIPAddress4(&a);
+}
+
+// Interrupt process (This is called periodically)
+void IPCProcessInterrupts(IPC *ipc)
+{
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return;
+ }
+
+ FlushTubeFlushList(ipc->FlushList);
+}
+
+// Process the L3 event by the IPC
+void IPCProcessL3Events(IPC *ipc)
+{
+ IPCProcessL3EventsEx(ipc, 0);
+}
+void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
+{
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return;
+ }
+ if (now == 0)
+ {
+ now = Tick64();
+ }
+
+ // Remove old ARP table entries
+ IPCFlushArpTableEx(ipc, now);
+
+ // Receive all the L2 packet
+ while (true)
+ {
+ BLOCK *b = IPCRecvL2(ipc);
+ if (b == NULL)
+ {
+ // All reception completed
+ break;
+ }
+
+ if (b->Size >= 14)
+ {
+ UCHAR *dest_mac = b->Buf + 0;
+ UCHAR *src_mac = b->Buf + 6;
+ USHORT protocol = READ_USHORT(b->Buf + 12);
+
+ // Confirm the destination MAC address
+ // (Receive if the destination MAC address is the IPC address or a broadcast address)
+ if (Cmp(dest_mac, ipc->MacAddress, 6) == 0 || dest_mac[0] & 0x01)
+ {
+ // If the source MAC address is itselves or invalid address, ignore the packet
+ if (Cmp(src_mac, ipc->MacAddress, 6) != 0 && IsValidUnicastMacAddress(src_mac))
+ {
+ if (protocol == MAC_PROTO_ARPV4)
+ {
+ // ARP receiving process
+ IPCProcessArp(ipc, b);
+ }
+ else if (protocol == MAC_PROTO_IPV4)
+ {
+ // IPv4 receiving process
+ if (b->Size >= (14 + 20))
+ {
+ UCHAR *data = Clone(b->Buf + 14, b->Size - 14);
+ UINT size = b->Size - 14;
+ IP ip_src, ip_dst;
+ bool ok = false;
+
+ // Extract the IP address portion
+ UINTToIP(&ip_src, *((UINT *)(((UCHAR *)data) + 12)));
+ UINTToIP(&ip_dst, *((UINT *)(((UCHAR *)data) + 16)));
+
+ // Receive only if the IPv4 destination address is its own
+ // or 255.255.255.255 or a multicast address or a broadcast address
+ if (CmpIpAddr(&ip_dst, &ipc->ClientIPAddress) == 0)
+ {
+ ok = true;
+ }
+ else if (ip_dst.addr[0] == 255 && ip_dst.addr[1] == 255 &&
+ ip_dst.addr[2] == 255 && ip_dst.addr[3] == 255)
+ {
+ ok = true;
+ }
+ else if (ip_dst.addr[0] >= 224 && ip_dst.addr[0] <= 239)
+ {
+ ok = true;
+ }
+ else
+ {
+ if (CmpIpAddr(&ipc->BroadcastAddress, &ip_dst) == 0)
+ {
+ ok = true;
+ }
+
+ if (IsZeroIP(&ipc->ClientIPAddress))
+ {
+ // Client IP address is undetermined
+ ok = true;
+ }
+ }
+
+ if (ok)
+ {
+ IPCAssociateOnArpTable(ipc, &ip_src, src_mac);
+
+ // Place in the reception queue
+ InsertQueue(ipc->IPv4RecviedQueue, NewBlock(data, size, 0));
+ }
+ else
+ {
+ // This packet is discarded because it is irrelevant for me
+ Free(data);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeBlock(b);
+ }
+
+ IPCProcessInterrupts(ipc);
+}
+
+// Configure IPv4 parameters
+bool IPCSetIPv4Parameters(IPC *ipc, IP *ip, IP *subnet, IP *gw)
+{
+ bool changed = false;
+ // Validate arguments
+ if (ipc == NULL || ip == NULL || subnet == NULL)
+ {
+ return false;
+ }
+
+ if (CmpIpAddr(&ipc->ClientIPAddress, ip) != 0)
+ {
+ changed = true;
+ }
+ Copy(&ipc->ClientIPAddress, ip, sizeof(IP));
+
+ if (CmpIpAddr(&ipc->SubnetMask, subnet) != 0)
+ {
+ changed = true;
+ }
+ Copy(&ipc->SubnetMask, subnet, sizeof(IP));
+
+ if (gw != NULL)
+ {
+ if (CmpIpAddr(&ipc->DefaultGateway, gw) != 0)
+ {
+ changed = true;
+ }
+
+ Copy(&ipc->DefaultGateway, gw, sizeof(IP));
+ }
+ else
+ {
+ if (IsZeroIP(&ipc->DefaultGateway) == false)
+ {
+ changed = true;
+ }
+
+ Zero(&ipc->DefaultGateway, sizeof(IP));
+ }
+
+ GetBroadcastAddress4(&ipc->BroadcastAddress, ip, subnet);
+
+ return changed;
+}
+
+// Send an IPv4 packet (client -> server)
+void IPCSendIPv4(IPC *ipc, void *data, UINT size)
+{
+ IP ip_src, ip_dst;
+ IP ip_dst_local;
+ bool is_broadcast = false;
+ UCHAR uc;
+ // Validate arguments
+ if (ipc == NULL || data == NULL || size < 20 || size > 1500)
+ {
+ return;
+ }
+
+ uc = ((UCHAR *)data)[0];
+ if (((uc >> 4) & 0x0f) != 4)
+ {
+ // Not an IPv4
+ return;
+ }
+
+ // Extract the IP address portion
+ UINTToIP(&ip_src, *((UINT *)(((UCHAR *)data) + 12)));
+ UINTToIP(&ip_dst, *((UINT *)(((UCHAR *)data) + 16)));
+
+ // Filter the source IP address
+ if (CmpIpAddr(&ip_src, &ipc->ClientIPAddress) != 0)
+ {
+ // Cut off packets from illegal IP address
+ return;
+ }
+
+ if (IsZeroIP(&ip_dst))
+ {
+ // Illegal destination address
+ return;
+ }
+
+ if (CmpIpAddr(&ip_dst, &ipc->ClientIPAddress) == 0)
+ {
+ // Packet destined for myself
+ return;
+ }
+
+ // Get the IP address of the relayed destination
+ Copy(&ip_dst_local, &ip_dst, sizeof(IP));
+ if (ip_dst.addr[0]==8)
+ DoNothing();
+ if (IsInSameNetwork4(&ip_dst, &ipc->ClientIPAddress, &ipc->SubnetMask) == false)
+ {
+ Copy(&ip_dst_local, &ipc->DefaultGateway, sizeof(IP));
+ }
+
+ if (CmpIpAddr(&ipc->BroadcastAddress, &ip_dst) == 0)
+ {
+ // Local Broadcast
+ is_broadcast = true;
+ }
+
+ if (ip_dst.addr[0] == 255 && ip_dst.addr[1] == 255 && ip_dst.addr[2] == 255 && ip_dst.addr[3] == 255)
+ {
+ // Global Broadcast
+ is_broadcast = true;
+ }
+
+ if (ip_dst.addr[0] >= 224 && ip_dst.addr[0] <= 239)
+ {
+ // IPv4 Multicast
+ is_broadcast = true;
+ }
+
+ if (is_broadcast)
+ {
+ // Send a broadcast packet
+ UCHAR dest[6];
+ UINT i;
+
+ // Destination
+ for (i = 0;i < 6;i++)
+ {
+ dest[i] = 0xff;
+ }
+
+ // Send
+ IPCSendIPv4WithDestMacAddr(ipc, data, size, dest);
+
+ return;
+ }
+
+ if (IsZeroIP(&ip_dst_local))
+ {
+ return;
+ }
+
+ IPCSendIPv4Unicast(ipc, data, size, &ip_dst_local);
+}
+
+// Send an IPv4 packet with a specified destination MAC address
+void IPCSendIPv4WithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac_addr)
+{
+ UCHAR tmp[1514];
+ // Validate arguments
+ if (ipc == NULL || data == NULL || size < 20 || size > 1500 || dest_mac_addr == NULL)
+ {
+ return;
+ }
+
+ // Destination
+ Copy(tmp + 0, dest_mac_addr, 6);
+
+ // Source
+ Copy(tmp + 6, ipc->MacAddress, 6);
+
+ // Protocol number
+ WRITE_USHORT(tmp + 12, MAC_PROTO_IPV4);
+
+ // Data
+ Copy(tmp + 14, data, size);
+
+ // Send
+ IPCSendL2(ipc, tmp, size + 14);
+}
+
+// Remove old ARP table entries
+void IPCFlushArpTable(IPC *ipc)
+{
+ IPCFlushArpTableEx(ipc, 0);
+}
+void IPCFlushArpTableEx(IPC *ipc, UINT64 now)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return;
+ }
+ if (now == 0)
+ {
+ now = Tick64();
+ }
+
+ for (i = 0;i < LIST_NUM(ipc->ArpTable);i++)
+ {
+ IPC_ARP *a = LIST_DATA(ipc->ArpTable, i);
+ bool b = false;
+
+ if (a->Resolved && a->ExpireTime <= now)
+ {
+ b = true;
+ }
+ else if (a->Resolved == false && a->GiveupTime <= now)
+ {
+ b = true;
+ }
+
+ if (b)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, a);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IPC_ARP *a = LIST_DATA(o, i);
+
+ IPCFreeARP(a);
+
+ Delete(ipc->ArpTable, a);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Send an IPv4 unicast packet
+void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip)
+{
+ IPC_ARP *a;
+ // Validate arguments
+ if (ipc == NULL || data == NULL || size < 20 || size > 1500 || next_ip == NULL)
+ {
+ return;
+ }
+
+ a = IPCSearchArpTable(ipc, next_ip);
+
+ if (a != NULL)
+ {
+ // ARP entry is found
+ if (a->Resolved)
+ {
+ // Send
+ a->ExpireTime = Tick64() + (UINT64)IPC_ARP_LIFETIME;
+
+ IPCSendIPv4WithDestMacAddr(ipc, data, size, a->MacAddress);
+ }
+ else
+ {
+ // Undeliverable because of unresolved table. Accumulate in the queue
+ if (a->PacketQueue->num_item < IPC_MAX_PACKET_QUEUE_LEN)
+ {
+ InsertQueue(a->PacketQueue, NewBlock(Clone(data, size), size, false));
+ }
+ }
+ }
+ else
+ {
+ ARPV4_HEADER arp;
+ UCHAR tmp[14 + sizeof(ARPV4_HEADER)];
+ UINT i;
+
+ // Because there is no such ARP entry, create a new one
+ a = IPCNewARP(next_ip, NULL);
+
+ // Send an ARP request
+ Zero(&arp, sizeof(arp));
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_REQUEST);
+ Copy(&arp.SrcAddress, &ipc->MacAddress, 6);
+ arp.SrcIP = IPToUINT(&ipc->ClientIPAddress);
+ arp.TargetIP = IPToUINT(next_ip);
+
+ for (i = 0;i < 6;i++)
+ {
+ tmp[i] = 0xff;
+ }
+
+ Copy(tmp + 6, ipc->MacAddress, 6);
+
+ WRITE_USHORT(tmp + 12, MAC_PROTO_ARPV4);
+ Copy(tmp + 14, &arp, sizeof(ARPV4_HEADER));
+
+ IPCSendL2(ipc, tmp, 14 + sizeof(ARPV4_HEADER));
+
+ // Accumulate the IP packet to be transmitted in the queue
+ if (a->PacketQueue->num_item < IPC_MAX_PACKET_QUEUE_LEN)
+ {
+ InsertQueue(a->PacketQueue, NewBlock(Clone(data, size), size, false));
+ }
+
+ Insert(ipc->ArpTable, a);
+ }
+}
+
+// Search the ARP table
+IPC_ARP *IPCSearchArpTable(IPC *ipc, IP *ip)
+{
+ IPC_ARP t;
+ IPC_ARP *a;
+ // Validate arguments
+ if (ipc == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ Copy(&t.Ip, ip, sizeof(IP));
+
+ a = Search(ipc->ArpTable, &t);
+
+ return a;
+}
+
+// Release the ARP entry
+void IPCFreeARP(IPC_ARP *a)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ b = GetNext(a->PacketQueue);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+
+ ReleaseQueue(a->PacketQueue);
+
+ Free(a);
+}
+
+// Create a new ARP entry
+IPC_ARP *IPCNewARP(IP *ip, UCHAR *mac_address)
+{
+ IPC_ARP *a;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(IPC_ARP));
+
+ Copy(&a->Ip, ip, sizeof(IP));
+ if (mac_address != NULL)
+ {
+ Copy(a->MacAddress, mac_address, 6);
+ a->Resolved = true;
+ a->ExpireTime = Tick64() + (UINT64)IPC_ARP_LIFETIME;
+ }
+ else
+ {
+ a->GiveupTime = Tick64() + (UINT64)IPC_ARP_GIVEUPTIME;
+ }
+
+ a->PacketQueue = NewQueueFast();
+
+ return a;
+}
+
+// Compare ARP entries
+int IPCCmpArpTable(void *p1, void *p2)
+{
+ IPC_ARP *a1, *a2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(IPC_ARP **)p1;
+ a2 = *(IPC_ARP **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+
+ return CmpIpAddr(&a1->Ip, &a2->Ip);
+}
+
+// Send an Ethernet packet (client -> server)
+void IPCSendL2(IPC *ipc, void *data, UINT size)
+{
+ // Validate arguments
+ if (ipc == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (ipc->Sock == NULL)
+ {
+ return;
+ }
+
+ TubeSendEx(ipc->Sock->SendTube, data, size, NULL, true);
+ AddTubeToFlushList(ipc->FlushList, ipc->Sock->SendTube);
+}
+
+// Receive an IPv4 packet (server -> client)
+BLOCK *IPCRecvIPv4(IPC *ipc)
+{
+ BLOCK *b;
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return NULL;
+ }
+
+ b = GetNext(ipc->IPv4RecviedQueue);
+
+ return b;
+}
+
+// Receive an Ethernet packet (server -> client)
+BLOCK *IPCRecvL2(IPC *ipc)
+{
+ TUBEDATA *d;
+ BLOCK *b;
+ // Validate arguments
+ if (ipc == NULL)
+ {
+ return NULL;
+ }
+
+ if (ipc->Sock == NULL)
+ {
+ return NULL;
+ }
+
+ d = TubeRecvAsync(ipc->Sock->RecvTube);
+
+ if (d == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBlock(d->Data, d->DataSize, 0);
+
+ Free(d->Header);
+ Free(d);
+
+ return b;
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IPC.h b/src/Cedar/IPsec_IPC.h
new file mode 100644
index 00000000..0861c13f
--- /dev/null
+++ b/src/Cedar/IPsec_IPC.h
@@ -0,0 +1,243 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IPC.h
+// Header of IPsec_IPC.c
+
+#ifndef IPSEC_IPC
+#define IPSEC_IPC
+
+// Constants
+#define IPC_ARP_LIFETIME (3 * 60 * 1000)
+#define IPC_ARP_GIVEUPTIME (1 * 1000)
+#define IPC_DHCP_TIMEOUT (5 * 1000)
+#define IPC_DHCP_TIMEOUT_TOTAL_GIVEUP (20 * 1000)
+#define IPC_DHCP_MIN_LEASE 5
+#define IPC_DHCP_DEFAULT_LEASE 3600
+
+#define IPC_MAX_PACKET_QUEUE_LEN 10000
+
+#define IPC_DHCP_VENDOR_ID "MSFT 5.0"
+
+#define IPC_PASSWORD_MSCHAPV2_TAG "xH7DiNlurDhcYV4a:"
+
+// ARP table entry
+struct IPC_ARP
+{
+ IP Ip; // IP address
+ bool Resolved; // Whether the MAC address have been resolved
+ UCHAR MacAddress[6]; // MAC address
+ UINT64 GiveupTime; // Time to give up (in the case of unresolved)
+ UINT64 ExpireTime; // Expiration date (If resolved)
+ QUEUE *PacketQueue; // Transmission packet queue
+};
+
+// DHCP release queue
+struct IPC_DHCP_RELESAE_QUEUE
+{
+ DHCP_OPTION_LIST Req;
+ UINT TranId;
+ UCHAR MacAddress[6];
+};
+
+// IPC_PARAM
+struct IPC_PARAM
+{
+ char ClientName[MAX_SIZE];
+ char Postfix[MAX_SIZE];
+ char HubName[MAX_HUBNAME_LEN + 1];
+ char UserName[MAX_USERNAME_LEN + 1];
+ char Password[MAX_PASSWORD_LEN + 1];
+ IP ClientIp;
+ UINT ClientPort;
+ IP ServerIp;
+ UINT ServerPort;
+ char ClientHostname[MAX_SIZE];
+ char CryptName[MAX_SIZE];
+ bool BridgeMode;
+ UINT Mss;
+ bool IsL3Mode;
+ bool IsOpenVPN;
+};
+
+// IPC_ASYNC object
+struct IPC_ASYNC
+{
+ CEDAR *Cedar; // Cedar
+ IPC_PARAM Param; // Parameters for creating IPC
+ THREAD *Thread; // Thread
+ SOCK_EVENT *SockEvent; // Socket events that is set when the connection is completed
+ bool Done; // Processing completion flag
+ IPC *Ipc; // IPC object (if it fails to connect, the value is NULL)
+ TUBE *TubeForDisconnect; // Tube for disconnection notification
+ UINT ErrorCode; // Error code in the case of failing to connect
+ DHCP_OPTION_LIST L3ClientAddressOption; // Client IP address option (Only in the case of L3 mode)
+ UINT64 L3DhcpRenewInterval; // DHCP update interval
+ UINT64 L3NextDhcpRenewTick; // DHCP renewal time of the next
+ bool DhcpAllocFailed; // Failed to get IP address from the DHCP server
+};
+
+// IPC object
+struct IPC
+{
+ CEDAR *Cedar;
+ char HubName[MAX_HUBNAME_LEN + 1];
+ char UserName[MAX_USERNAME_LEN + 1];
+ char Password[MAX_PASSWORD_LEN + 1];
+ char ClientHostname[MAX_SIZE];
+ UCHAR random[SHA1_SIZE];
+ char SessionName[MAX_SESSION_NAME_LEN + 1];
+ char ConnectionName[MAX_CONNECTION_NAME_LEN + 1];
+ POLICY *Policy;
+ SOCK *Sock;
+ INTERRUPT_MANAGER *Interrupt; // Interrupt manager
+ IP ClientIPAddress; // IP address of the client
+ IP SubnetMask; // Subnet mask of the client
+ IP DefaultGateway; // Default gateway address
+ IP BroadcastAddress; // Broadcast address
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ LIST *ArpTable; // ARP table
+ QUEUE *IPv4RecviedQueue; // IPv4 reception queue
+ TUBE_FLUSH_LIST *FlushList; // Tube Flush List
+ UCHAR MsChapV2_ServerResponse[20]; // Server response
+};
+
+// MS-CHAPv2 authentication information
+struct IPC_MSCHAP_V2_AUTHINFO
+{
+ char MsChapV2_PPPUsername[MAX_SIZE]; // MS-CHAPv2 Username
+ UCHAR MsChapV2_ServerChallenge[16]; // MS-CHAPv2 Server Challenge
+ UCHAR MsChapV2_ClientChallenge[16]; // MS-CHAPv2 Client Challenge
+ UCHAR MsChapV2_ClientResponse[24]; // MS-CHAPv2 Client Response
+};
+
+IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
+ UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
+ char *client_hostname, char *crypt_name,
+ bool bridge_mode, UINT mss);
+IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code);
+IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address);
+void FreeIPC(IPC *ipc);
+bool IsIPCConnected(IPC *ipc);
+void IPCSetSockEventWhenRecvL2Packet(IPC *ipc, SOCK_EVENT *e);
+void IPCSendL2(IPC *ipc, void *data, UINT size);
+void IPCSendIPv4(IPC *ipc, void *data, UINT size);
+BLOCK *IPCRecvL2(IPC *ipc);
+BLOCK *IPCRecvIPv4(IPC *ipc);
+void IPCProcessInterrupts(IPC *ipc);
+void IPCProcessL3Events(IPC *ipc);
+void IPCProcessL3EventsEx(IPC *ipc, UINT64 now);
+bool IPCSetIPv4Parameters(IPC *ipc, IP *ip, IP *subnet, IP *gw);
+IPC_ARP *IPCNewARP(IP *ip, UCHAR *mac_address);
+void IPCFreeARP(IPC_ARP *a);
+int IPCCmpArpTable(void *p1, void *p2);
+void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip);
+IPC_ARP *IPCSearchArpTable(IPC *ipc, IP *ip);
+void IPCSendIPv4WithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac_addr);
+void IPCFlushArpTable(IPC *ipc);
+void IPCFlushArpTableEx(IPC *ipc, UINT64 now);
+void IPCProcessArp(IPC *ipc, BLOCK *b);
+void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address);
+bool IsValidUnicastMacAddress(UCHAR *mac);
+bool IsValidUnicastIPAddress4(IP *ip);
+bool IsValidUnicastIPAddressUINT4(UINT ip);
+DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt, UINT expecting_code, UINT timeout, TUBE *discon_poll_tube);
+BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt);
+BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt);
+bool IPCDhcpAllocateIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube);
+bool IPCDhcpAllocateIPEx(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, bool openvpn_compatible);
+bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, IP *client_ip);
+void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server);
+void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server);
+IPC_ASYNC *NewIPCAsync(CEDAR *cedar, IPC_PARAM *param, SOCK_EVENT *sock_event);
+void IPCAsyncThreadProc(THREAD *thread, void *param);
+void FreeIPCAsync(IPC_ASYNC *a);
+
+bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password);
+
+#endif // IPSEC_IPC
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IkePacket.c b/src/Cedar/IPsec_IkePacket.c
new file mode 100644
index 00000000..8fa02e90
--- /dev/null
+++ b/src/Cedar/IPsec_IkePacket.c
@@ -0,0 +1,3129 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IkePacket.c
+// IKE (ISAKMP) packet processing
+
+#include "CedarPch.h"
+
+// Convert the string to a password
+BUF *IkeStrToPassword(char *str)
+{
+ BUF *b;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NewBuf();
+ }
+
+ if (StartWith(str, "0x") == false)
+ {
+ // Accept the string as is
+ b = NewBuf();
+ WriteBuf(b, str, StrLen(str));
+ }
+ else
+ {
+ // Interpret as a hexadecimal value
+ b = StrToBin(str + 2);
+ }
+
+ return b;
+}
+
+// Phase 1: Convert the encryption algorithm name to key size
+UINT IkePhase1CryptIdToKeySize(UCHAR id)
+{
+ switch (id)
+ {
+ case IKE_P1_CRYPTO_3DES_CBC:
+ return DES3_KEY_SIZE;
+
+ case IKE_P1_CRYPTO_DES_CBC:
+ return DES_KEY_SIZE;
+ }
+
+ return 0;
+}
+
+// Phase 2: Convert the encryption algorithm name to key size
+UINT IkePhase2CryptIdToKeySize(UCHAR id)
+{
+ switch (id)
+ {
+ case IKE_TRANSFORM_ID_P2_ESP_3DES:
+ return DES3_KEY_SIZE;
+
+ case IKE_TRANSFORM_ID_P2_ESP_DES:
+ return DES_KEY_SIZE;
+ }
+
+ return 0;
+}
+
+// Convert a string to an algorithm name
+UCHAR IkeStrToPhase1CryptId(char *name)
+{
+ if (StartWith(name, "3DES") || StartWith("3DES", name))
+ {
+ return IKE_P1_CRYPTO_3DES_CBC;
+ }
+ else if (StartWith(name, "DES") || StartWith("DES", name))
+ {
+ return IKE_P1_CRYPTO_DES_CBC;
+ }
+ else
+ {
+ return 0;
+ }
+}
+UCHAR IkeStrToPhase1HashId(char *name)
+{
+ if (StartWith(name, "SHA-1") || StartWith("SHA-1", name))
+ {
+ return IKE_P1_HASH_SHA1;
+ }
+
+ return 0;
+}
+UCHAR IkeStrToPhase2CryptId(char *name)
+{
+ if (StartWith(name, "3DES") || StartWith("3DES", name))
+ {
+ return IKE_TRANSFORM_ID_P2_ESP_3DES;
+ }
+ else if (StartWith(name, "DES") || StartWith("DES", name))
+ {
+ return IKE_TRANSFORM_ID_P2_ESP_DES;
+ }
+ else
+ {
+ return 0;
+ }
+}
+UCHAR IkeStrToPhase2HashId(char *name)
+{
+ if (StartWith(name, "SHA-1") || StartWith("SHA-1", name))
+ {
+ return IKE_P2_HMAC_SHA1_96;
+ }
+
+ return 0;
+}
+
+// Build a data payload
+BUF *IkeBuildDataPayload(IKE_PACKET_DATA_PAYLOAD *t)
+{
+ BUF *b;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, t->Data->Buf, t->Data->Size);
+
+ return b;
+}
+
+// Build a SA payload
+BUF *IkeBuildSaPayload(IKE_PACKET_SA_PAYLOAD *t)
+{
+ IKE_SA_HEADER h;
+ BUF *ret;
+ BUF *b;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.DoI = Endian32(IKE_SA_DOI_IPSEC);
+ h.Situation = Endian32(IKE_SA_SITUATION_IDENTITY);
+
+ ret = NewBuf();
+
+ WriteBuf(ret, &h, sizeof(h));
+
+ b = IkeBuildPayloadList(t->PayloadList);
+ WriteBufBuf(ret, b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Build a proposal payload
+BUF *IkeBuildProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t)
+{
+ IKE_PROPOSAL_HEADER h;
+ BUF *ret, *b;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.Number = t->Number;
+ h.NumTransforms = LIST_NUM(t->PayloadList);
+ h.ProtocolId = t->ProtocolId;
+ h.SpiSize = t->Spi->Size;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBufBuf(ret, t->Spi);
+
+ b = IkeBuildPayloadList(t->PayloadList);
+ WriteBufBuf(ret, b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Build the transform value list
+BUF *IkeBuildTransformValueList(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_TRANSFORM_VALUE *v = LIST_DATA(o, i);
+ BUF *tmp = IkeBuildTransformValue(v);
+
+ WriteBufBuf(b, tmp);
+
+ FreeBuf(tmp);
+ }
+
+ return b;
+}
+
+// Build a transform value
+BUF *IkeBuildTransformValue(IKE_PACKET_TRANSFORM_VALUE *v)
+{
+ BUF *b;
+ UCHAR af_bit, type;
+ USHORT size_or_value;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ type = v->Type;
+
+ if (v->Value >= 65536)
+ {
+ // 32 bit
+ af_bit = 0;
+ size_or_value = Endian16(sizeof(UINT));
+ }
+ else
+ {
+ // 16 bit
+ af_bit = 0x80;
+ size_or_value = Endian16((USHORT)v->Value);
+ }
+
+ b = NewBuf();
+ WriteBuf(b, &af_bit, sizeof(af_bit));
+ WriteBuf(b, &type, sizeof(type));
+ WriteBuf(b, &size_or_value, sizeof(size_or_value));
+
+ if (af_bit == 0)
+ {
+ UINT value = Endian32(v->Value);
+ WriteBuf(b, &value, sizeof(UINT));
+ }
+
+ return b;
+}
+
+// Build a transform payload
+BUF *IkeBuildTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t)
+{
+ IKE_TRANSFORM_HEADER h;
+ BUF *ret, *b;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.Number = t->Number;
+ h.TransformId = t->TransformId;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+
+ b = IkeBuildTransformValueList(t->ValueList);
+ WriteBufBuf(ret, b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the value from the transform payload
+UINT IkeGetTransformValue(IKE_PACKET_TRANSFORM_PAYLOAD *t, UINT type, UINT index)
+{
+ UINT i;
+ UINT num;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(t->ValueList);i++)
+ {
+ IKE_PACKET_TRANSFORM_VALUE *v = LIST_DATA(t->ValueList, i);
+
+ if (v->Type == type)
+ {
+ if (num == index)
+ {
+ return v->Value;
+ }
+
+ num++;
+ }
+ }
+
+ return 0;
+}
+
+// Get the number of values from the transform payload
+UINT IkeGetTransformValueNum(IKE_PACKET_TRANSFORM_PAYLOAD *t, UINT type)
+{
+ UINT i;
+ UINT num;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(t->ValueList);i++)
+ {
+ IKE_PACKET_TRANSFORM_VALUE *v = LIST_DATA(t->ValueList, i);
+
+ if (v->Type == type)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+// Build the ID payload
+BUF *IkeBuildIdPayload(IKE_PACKET_ID_PAYLOAD *t)
+{
+ IKE_ID_HEADER h;
+ BUF *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.IdType = t->Type;
+ h.Port = Endian16(t->Port);
+ h.ProtocolId = t->ProtocolId;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+
+ WriteBufBuf(ret, t->IdData);
+
+ return ret;
+}
+
+// Build a certificate payload
+BUF *IkeBuildCertPayload(IKE_PACKET_CERT_PAYLOAD *t)
+{
+ IKE_CERT_HEADER h;
+ BUF *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.CertType = t->CertType;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBufBuf(ret, t->CertData);
+
+ return ret;
+}
+
+// Build a certificate request payload
+BUF *IkeBuildCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t)
+{
+ IKE_CERT_REQUEST_HEADER h;
+ BUF *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.CertType = t->CertType;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBufBuf(ret, t->Data);
+
+ return ret;
+}
+
+// Build a notification payload
+BUF *IkeBuildNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t)
+{
+ IKE_NOTICE_HEADER h;
+ BUF *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.DoI = Endian32(IKE_SA_DOI_IPSEC);
+ h.MessageType = Endian16(t->MessageType);
+ h.ProtocolId = t->ProtocolId;
+ h.SpiSize = t->Spi->Size;
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBuf(ret, t->Spi->Buf, t->Spi->Size);
+
+ if (t->MessageData != NULL)
+ {
+ WriteBuf(ret, t->MessageData->Buf, t->MessageData->Size);
+ }
+
+ return ret;
+}
+
+// Build a NAT-OA payload
+BUF *IkeBuildNatOaPayload(IKE_PACKET_NAT_OA_PAYLOAD *t)
+{
+ IKE_NAT_OA_HEADER h;
+ BUF *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+
+ if (IsIP6(&t->IpAddress))
+ {
+ h.IdType = IKE_ID_IPV6_ADDR;
+ }
+ else
+ {
+ h.IdType = IKE_ID_IPV4_ADDR;
+ }
+
+ ret = NewBuf();
+
+ WriteBuf(ret, &h, sizeof(h));
+
+ if (IsIP6(&t->IpAddress))
+ {
+ WriteBuf(ret, t->IpAddress.ipv6_addr, 16);
+ }
+ else
+ {
+ WriteBuf(ret, t->IpAddress.addr, 4);
+ }
+
+ return ret;
+}
+
+// Build a deletion payload
+BUF *IkeBuildDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t)
+{
+ IKE_DELETE_HEADER h;
+ BUF *ret;
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.DoI = Endian32(IKE_SA_DOI_IPSEC);
+ h.NumSpis = Endian16(LIST_NUM(t->SpiList));
+ h.ProtocolId = t->ProtocolId;
+
+ if (LIST_NUM(t->SpiList) >= 1)
+ {
+ BUF *b = LIST_DATA(t->SpiList, 0);
+
+ h.SpiSize = b->Size;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+
+ for (i = 0;i < LIST_NUM(t->SpiList);i++)
+ {
+ BUF *b = LIST_DATA(t->SpiList, i);
+
+ WriteBuf(ret, b->Buf, b->Size);
+ }
+
+ return ret;
+}
+
+// Build a bit array from the payload
+BUF *IkeBuildPayload(IKE_PACKET_PAYLOAD *p)
+{
+ BUF *b = NULL;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ switch (p->PayloadType)
+ {
+ case IKE_PAYLOAD_SA: // SA payload
+ b = IkeBuildSaPayload(&p->Payload.Sa);
+ break;
+
+ case IKE_PAYLOAD_PROPOSAL: // Proposal payload
+ b = IkeBuildProposalPayload(&p->Payload.Proposal);
+ break;
+
+ case IKE_PAYLOAD_TRANSFORM: // Transform payload
+ b = IkeBuildTransformPayload(&p->Payload.Transform);
+ break;
+
+ case IKE_PAYLOAD_ID: // ID payload
+ b = IkeBuildIdPayload(&p->Payload.Id);
+ break;
+
+ case IKE_PAYLOAD_CERT: // Certificate payload
+ b = IkeBuildCertPayload(&p->Payload.Cert);
+ break;
+
+ case IKE_PAYLOAD_CERT_REQUEST: // Certificate request payload
+ b = IkeBuildCertRequestPayload(&p->Payload.CertRequest);
+ break;
+
+ case IKE_PAYLOAD_NOTICE: // Notification Payload
+ b = IkeBuildNoticePayload(&p->Payload.Notice);
+ break;
+
+ case IKE_PAYLOAD_DELETE: // Deletion payload
+ b = IkeBuildDeletePayload(&p->Payload.Delete);
+ break;
+
+ case IKE_PAYLOAD_NAT_OA: // NAT-OA payload
+ case IKE_PAYLOAD_NAT_OA_DRAFT:
+ case IKE_PAYLOAD_NAT_OA_DRAFT_2:
+ b = IkeBuildNatOaPayload(&p->Payload.NatOa);
+ break;
+
+ case IKE_PAYLOAD_KEY_EXCHANGE: // Key exchange payload
+ case IKE_PAYLOAD_HASH: // Hash payload
+ case IKE_PAYLOAD_SIGN: // Signature payload
+ case IKE_PAYLOAD_RAND: // Random number payload
+ case IKE_PAYLOAD_VENDOR_ID: // Vendor ID payload
+ case IKE_PAYLOAD_NAT_D: // NAT-D payload
+ case IKE_PAYLOAD_NAT_D_DRAFT: // NAT-D payload (draft)
+ default:
+ b = IkeBuildDataPayload(&p->Payload.GeneralData);
+ break;
+ }
+
+ if (b != NULL)
+ {
+ if (p->BitArray != NULL)
+ {
+ FreeBuf(p->BitArray);
+ }
+ p->BitArray = CloneBuf(b);
+ }
+
+ return b;
+}
+
+// Get the payload type of the first item
+UCHAR IkeGetFirstPayloadType(LIST *o)
+{
+ IKE_PACKET_PAYLOAD *p;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return IKE_PAYLOAD_NONE;
+ }
+
+ if (LIST_NUM(o) == 0)
+ {
+ return IKE_PAYLOAD_NONE;
+ }
+
+ p = (IKE_PACKET_PAYLOAD *)LIST_DATA(o, 0);
+
+ return p->PayloadType;
+}
+
+// Build a bit array from the payload list
+BUF *IkeBuildPayloadList(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_PAYLOAD *p = LIST_DATA(o, i);
+ IKE_PACKET_PAYLOAD *next = NULL;
+ IKE_COMMON_HEADER h;
+ BUF *tmp;
+
+ if (i < (LIST_NUM(o) - 1))
+ {
+ next = LIST_DATA(o, i + 1);
+ }
+
+ Zero(&h, sizeof(h));
+ if (next != NULL)
+ {
+ h.NextPayload = next->PayloadType;
+ }
+ else
+ {
+ h.NextPayload = IKE_PAYLOAD_NONE;
+ }
+
+ tmp = IkeBuildPayload(p);
+ if (tmp != NULL)
+ {
+ h.PayloadSize = Endian16(tmp->Size + (USHORT)sizeof(h));
+
+ WriteBuf(b, &h, sizeof(h));
+ WriteBuf(b, tmp->Buf, tmp->Size);
+
+ FreeBuf(tmp);
+ }
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Get the specified payload
+IKE_PACKET_PAYLOAD *IkeGetPayload(LIST *o, UINT payload_type, UINT index)
+{
+ UINT i, num;
+ IKE_PACKET_PAYLOAD *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_PAYLOAD *p = LIST_DATA(o, i);
+
+ if (p->PayloadType == payload_type)
+ {
+ if (num == index)
+ {
+ ret = p;
+ break;
+ }
+
+ num++;
+ }
+ }
+
+ return ret;
+}
+
+// Get the number of the payload of the specified type
+UINT IkeGetPayloadNum(LIST *o, UINT payload_type)
+{
+ UINT i, num;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_PAYLOAD *p = LIST_DATA(o, i);
+
+ if (p->PayloadType == payload_type)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+// Create a deletion payload
+IKE_PACKET_PAYLOAD *IkeNewDeletePayload(UCHAR protocol_id, LIST *spi_list)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (spi_list == NULL)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_DELETE);
+ p->Payload.Delete.ProtocolId = protocol_id;
+ p->Payload.Delete.SpiList = spi_list;
+
+ return p;
+}
+
+// Create a Notification payload
+IKE_PACKET_PAYLOAD *IkeNewNoticePayload(UCHAR protocol_id, USHORT message_type,
+ void *spi, UINT spi_size,
+ void *message, UINT message_size)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (spi == NULL && spi_size != 0)
+ {
+ return NULL;
+ }
+ if (message == NULL && message_size != 0)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_NOTICE);
+ p->Payload.Notice.MessageType = message_type;
+ p->Payload.Notice.MessageData = MemToBuf(message, message_size);
+ p->Payload.Notice.Spi = MemToBuf(spi, spi_size);
+ p->Payload.Notice.ProtocolId = protocol_id;
+
+ return p;
+}
+
+// Create a Invalid Cookie Payload
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidCookiePayload(UINT64 init_cookie, UINT64 resp_cookie)
+{
+ IKE_PACKET_PAYLOAD *ret;
+ BUF *b = NewBuf();
+
+ WriteBufInt64(b, init_cookie);
+ WriteBufInt64(b, resp_cookie);
+
+ ret = IkeNewNoticePayload(IKE_PROTOCOL_ID_IKE, IKE_NOTICE_ERROR_INVALID_COOKIE, b->Buf, b->Size,
+ b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Create an Invalid Exchange Type Payload
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidExchangeTypePayload(UINT64 init_cookie, UINT64 resp_cookie, UCHAR exchange_type)
+{
+ IKE_PACKET_PAYLOAD *ret;
+ BUF *b = NewBuf();
+
+ WriteBufInt64(b, init_cookie);
+ WriteBufInt64(b, resp_cookie);
+
+ ret = IkeNewNoticePayload(IKE_PROTOCOL_ID_IKE, IKE_NOTICE_ERROR_INVALID_EXCHANGE_TYPE, b->Buf, b->Size,
+ &exchange_type, 1);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Create an Invalid SPI payload
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidSpiPayload(UINT spi)
+{
+ IKE_PACKET_PAYLOAD *ret;
+ spi = Endian32(spi);
+
+ ret = IkeNewNoticePayload(IKE_PROTOCOL_ID_IPSEC_ESP, IKE_NOTICE_ERROR_INVALID_SPI, &spi, sizeof(UINT),
+ &spi, sizeof(UINT));
+
+ return ret;
+}
+
+// Create a No Proposal Chosen payload
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorNoProposalChosenPayload(bool quick_mode, UINT64 init_cookie, UINT64 resp_cookie)
+{
+ BUF *b = NewBuf();
+ IKE_PACKET_PAYLOAD *ret;
+
+ WriteBufInt64(b, init_cookie);
+ WriteBufInt64(b, resp_cookie);
+
+ ret = IkeNewNoticePayload((quick_mode ? IKE_PROTOCOL_ID_IPSEC_ESP : IKE_PROTOCOL_ID_IKE),
+ IKE_NOTICE_ERROR_NO_PROPOSAL_CHOSEN, b->Buf, b->Size,
+ NULL, 0);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Create a DPD payload
+IKE_PACKET_PAYLOAD *IkeNewNoticeDpdPayload(bool ack, UINT64 init_cookie, UINT64 resp_cookie, UINT seq_no)
+{
+ IKE_PACKET_PAYLOAD *ret;
+ BUF *b = NewBuf();
+
+ seq_no = Endian32(seq_no);
+
+ WriteBufInt64(b, init_cookie);
+ WriteBufInt64(b, resp_cookie);
+
+ ret = IkeNewNoticePayload(IKE_PROTOCOL_ID_IKE, (ack ? IKE_NOTICE_DPD_RESPONSE : IKE_NOTICE_DPD_REQUEST),
+ b->Buf, b->Size,
+ &seq_no, sizeof(UINT));
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Create a Certificate Request Payload
+IKE_PACKET_PAYLOAD *IkeNewCertRequestPayload(UCHAR cert_type, void *data, UINT size)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (data == NULL && size != 0)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_CERT_REQUEST);
+ p->Payload.CertRequest.CertType = cert_type;
+ p->Payload.CertRequest.Data = MemToBuf(data, size);
+
+ return p;
+}
+
+// Create a Certificate payload
+IKE_PACKET_PAYLOAD *IkeNewCertPayload(UCHAR cert_type, void *cert_data, UINT cert_size)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (cert_data == NULL && cert_size != 0)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_CERT);
+ p->Payload.Cert.CertType = cert_type;
+ p->Payload.Cert.CertData = MemToBuf(cert_data, cert_size);
+
+ return p;
+}
+
+// Create an ID payload
+IKE_PACKET_PAYLOAD *IkeNewIdPayload(UCHAR id_type, UCHAR protocol_id, USHORT port, void *id_data, UINT id_size)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (id_data == NULL && id_size != 0)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_ID);
+ p->Payload.Id.IdData = MemToBuf(id_data, id_size);
+ p->Payload.Id.Port = port;
+ p->Payload.Id.ProtocolId = protocol_id;
+ p->Payload.Id.Type = id_type;
+
+ return p;
+}
+
+// Create a transform payload
+IKE_PACKET_PAYLOAD *IkeNewTransformPayload(UCHAR number, UCHAR transform_id, LIST *value_list)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (value_list == NULL)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_TRANSFORM);
+ p->Payload.Transform.Number = number;
+ p->Payload.Transform.TransformId = transform_id;
+ p->Payload.Transform.ValueList = value_list;
+
+ return p;
+}
+
+// Create a proposal payload
+IKE_PACKET_PAYLOAD *IkeNewProposalPayload(UCHAR number, UCHAR protocol_id, void *spi, UINT spi_size, LIST *payload_list)
+{
+ IKE_PACKET_PAYLOAD *p;
+ if (payload_list == NULL || (spi == NULL && spi_size != 0))
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_PROPOSAL);
+ p->Payload.Proposal.Number = number;
+ p->Payload.Proposal.ProtocolId = protocol_id;
+ p->Payload.Proposal.Spi = MemToBuf(spi, spi_size);
+ p->Payload.Proposal.PayloadList = payload_list;
+
+ return p;
+}
+
+// Create an SA payload
+IKE_PACKET_PAYLOAD *IkeNewSaPayload(LIST *payload_list)
+{
+ IKE_PACKET_PAYLOAD *p;
+ // Validate arguments
+ if (payload_list == NULL)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(IKE_PAYLOAD_SA);
+ p->Payload.Sa.PayloadList = payload_list;
+
+ return p;
+}
+
+// Create a NAT-OA payload
+IKE_PACKET_PAYLOAD *IkeNewNatOaPayload(UCHAR payload_type, IP *ip)
+{
+ IKE_PACKET_PAYLOAD *p;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(payload_type);
+ Copy(&p->Payload.NatOa.IpAddress, ip, sizeof(IP));
+ p->PayloadType = payload_type;
+
+ return p;
+}
+
+// Create a data payload
+IKE_PACKET_PAYLOAD *IkeNewDataPayload(UCHAR payload_type, void *data, UINT size)
+{
+ IKE_PACKET_PAYLOAD *p;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ p = IkeNewPayload(payload_type);
+ p->Payload.GeneralData.Data = MemToBuf(data, size);
+
+ return p;
+}
+
+// Create a new payload
+IKE_PACKET_PAYLOAD *IkeNewPayload(UINT payload_type)
+{
+ IKE_PACKET_PAYLOAD *p;
+
+ p = ZeroMalloc(sizeof(IKE_PACKET_PAYLOAD));
+
+ p->PayloadType = payload_type;
+
+ return p;
+}
+
+// Analyse the IKE payload body
+IKE_PACKET_PAYLOAD *IkeParsePayload(UINT payload_type, BUF *b)
+{
+ IKE_PACKET_PAYLOAD *p = NULL;
+ bool ok = true;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(IKE_PACKET_PAYLOAD));
+ p->PayloadType = payload_type;
+
+ switch (p->PayloadType)
+ {
+ case IKE_PAYLOAD_SA: // SA payload
+ ok = IkeParseSaPayload(&p->Payload.Sa, b);
+ break;
+
+ case IKE_PAYLOAD_PROPOSAL: // Proposal payload
+ ok = IkeParseProposalPayload(&p->Payload.Proposal, b);
+ break;
+
+ case IKE_PAYLOAD_TRANSFORM: // Proposal payload
+ ok = IkeParseTransformPayload(&p->Payload.Transform, b);
+ break;
+
+ case IKE_PAYLOAD_ID: // ID payload
+ ok = IkeParseIdPayload(&p->Payload.Id, b);
+ break;
+
+ case IKE_PAYLOAD_CERT: // Certificate payload
+ ok = IkeParseCertPayload(&p->Payload.Cert, b);
+ break;
+
+ case IKE_PAYLOAD_CERT_REQUEST: // Certificate request payload
+ ok = IkeParseCertRequestPayload(&p->Payload.CertRequest, b);
+ break;
+
+ case IKE_PAYLOAD_NOTICE: // Notification Payload
+ ok = IkeParseNoticePayload(&p->Payload.Notice, b);
+ break;
+
+ case IKE_PAYLOAD_DELETE: // Deletion payload
+ ok = IkeParseDeletePayload(&p->Payload.Delete, b);
+ break;
+
+ case IKE_PAYLOAD_NAT_OA:
+ case IKE_PAYLOAD_NAT_OA_DRAFT:
+ case IKE_PAYLOAD_NAT_OA_DRAFT_2:
+ ok = IkeParseNatOaPayload(&p->Payload.NatOa, b);
+ break;
+
+ case IKE_PAYLOAD_KEY_EXCHANGE: // Key exchange payload
+ case IKE_PAYLOAD_HASH: // Hash payload
+ case IKE_PAYLOAD_SIGN: // Signature payload
+ case IKE_PAYLOAD_RAND: // Random number payload
+ case IKE_PAYLOAD_VENDOR_ID: // Vendor ID payload
+ case IKE_PAYLOAD_NAT_D: // NAT-D payload
+ case IKE_PAYLOAD_NAT_D_DRAFT: // NAT-D payload (draft)
+ default:
+ ok = IkeParseDataPayload(&p->Payload.GeneralData, b);
+ break;
+ }
+
+ if (ok == false)
+ {
+ Free(p);
+ p = NULL;
+ }
+ else
+ {
+ p->BitArray = CloneBuf(b);
+ }
+
+ return p;
+}
+
+// Parse the SA payload
+bool IkeParseSaPayload(IKE_PACKET_SA_PAYLOAD *t, BUF *b)
+{
+ IKE_SA_HEADER *h;
+ UCHAR *buf;
+ UINT size;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size < sizeof(IKE_SA_HEADER))
+ {
+ return false;
+ }
+
+ h = (IKE_SA_HEADER *)b->Buf;
+ buf = (UCHAR *)b->Buf;
+ buf += sizeof(IKE_SA_HEADER);
+ size = b->Size - sizeof(IKE_SA_HEADER);
+
+ if (Endian32(h->DoI) != IKE_SA_DOI_IPSEC)
+ {
+ Debug("ISAKMP: Invalid DoI Value: 0x%x\n", Endian32(h->DoI));
+ return false;
+ }
+
+ if (Endian32(h->Situation) != IKE_SA_SITUATION_IDENTITY)
+ {
+ Debug("ISAKMP: Invalid Situation Value: 0x%x\n", Endian32(h->Situation));
+ return false;
+ }
+
+ t->PayloadList = IkeParsePayloadList(buf, size, IKE_PAYLOAD_PROPOSAL);
+
+ return true;
+}
+
+// Release the SA payload
+void IkeFreeSaPayload(IKE_PACKET_SA_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->PayloadList != NULL)
+ {
+ IkeFreePayloadList(t->PayloadList);
+ t->PayloadList = NULL;
+ }
+}
+
+// Parse the proposal payload
+bool IkeParseProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t, BUF *b)
+{
+ IKE_PROPOSAL_HEADER *h;
+ UCHAR *buf;
+ UINT size;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size < sizeof(IKE_PROPOSAL_HEADER))
+ {
+ return false;
+ }
+
+ h = (IKE_PROPOSAL_HEADER *)b->Buf;
+
+ t->Number = h->Number;
+ t->ProtocolId = h->ProtocolId;
+
+ buf = (UCHAR *)b->Buf;
+ buf += sizeof(IKE_PROPOSAL_HEADER);
+ size = b->Size - sizeof(IKE_PROPOSAL_HEADER);
+
+ if (size < (UINT)h->SpiSize)
+ {
+ return false;
+ }
+
+ t->Spi = MemToBuf(buf, h->SpiSize);
+
+ buf += h->SpiSize;
+ size -= h->SpiSize;
+
+ t->PayloadList = IkeParsePayloadList(buf, size, IKE_PAYLOAD_TRANSFORM);
+
+ return true;
+}
+
+// Release the proposal payload
+void IkeFreeProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->Spi != NULL)
+ {
+ FreeBuf(t->Spi);
+ t->Spi = NULL;
+ }
+
+ if (t->PayloadList != NULL)
+ {
+ IkeFreePayloadList(t->PayloadList);
+ t->PayloadList = NULL;
+ }
+}
+
+// Parse the transform payload
+bool IkeParseTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t, BUF *b)
+{
+ IKE_TRANSFORM_HEADER h;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ t->Number = h.Number;
+ t->TransformId = h.TransformId;
+ t->ValueList = IkeParseTransformValueList(b);
+
+ return true;
+}
+
+// Create a new transform value
+IKE_PACKET_TRANSFORM_VALUE *IkeNewTransformValue(UCHAR type, UINT value)
+{
+ IKE_PACKET_TRANSFORM_VALUE *v = ZeroMalloc(sizeof(IKE_PACKET_TRANSFORM_VALUE));
+
+ v->Type = type;
+ v->Value = value;
+
+ return v;
+}
+
+// Parse the transform value list
+LIST *IkeParseTransformValueList(BUF *b)
+{
+ LIST *o;
+ bool ok = true;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ while (b->Current < b->Size)
+ {
+ UCHAR af_bit, type;
+ USHORT size;
+ UINT value = 0;
+ IKE_PACKET_TRANSFORM_VALUE *v;
+
+ if (ReadBuf(b, &af_bit, sizeof(af_bit)) != sizeof(af_bit))
+ {
+ ok = false;
+ break;
+ }
+
+ if (ReadBuf(b, &type, sizeof(type)) != sizeof(type))
+ {
+ ok = false;
+ break;
+ }
+
+ if (ReadBuf(b, &size, sizeof(size)) != sizeof(size))
+ {
+ ok = false;
+ }
+
+ size = Endian16(size);
+
+ if (af_bit == 0)
+ {
+ UCHAR *tmp = Malloc(size);
+
+ if (ReadBuf(b, tmp, size) != size)
+ {
+ ok = false;
+ Free(tmp);
+ break;
+ }
+
+ switch (size)
+ {
+ case sizeof(UINT):
+ value = READ_UINT(tmp);
+ break;
+
+ case sizeof(USHORT):
+ value = READ_USHORT(tmp);
+ break;
+
+ case sizeof(UCHAR):
+ value = *((UCHAR *)tmp);
+ break;
+ }
+
+ Free(tmp);
+ }
+ else
+ {
+ value = (UINT)size;
+ }
+
+ v = ZeroMalloc(sizeof(IKE_PACKET_TRANSFORM_VALUE));
+ v->Type = type;
+ v->Value = value;
+
+ Add(o, v);
+ }
+
+ if (ok == false)
+ {
+ IkeFreeTransformValueList(o);
+ o = NULL;
+ }
+
+ return o;
+}
+
+// Release the transform value list
+void IkeFreeTransformValueList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_TRANSFORM_VALUE *v = LIST_DATA(o, i);
+
+ Free(v);
+ }
+
+ ReleaseList(o);
+}
+
+// Release the transform payload
+void IkeFreeTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->ValueList != NULL)
+ {
+ IkeFreeTransformValueList(t->ValueList);
+ t->ValueList = NULL;
+ }
+}
+
+// Parse the ID payload
+bool IkeParseIdPayload(IKE_PACKET_ID_PAYLOAD *t, BUF *b)
+{
+ IKE_ID_HEADER h;
+ IP ip;
+ IP subnet;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ t->Type = h.IdType;
+ t->ProtocolId = h.ProtocolId;
+ t->Port = Endian16(h.Port);
+ t->IdData = ReadRemainBuf(b);
+ if (t->IdData == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip, sizeof(ip));
+ Zero(&subnet, sizeof(subnet));
+
+ // Convert to string
+ Zero(t->StrData, sizeof(t->StrData));
+ switch (t->Type)
+ {
+ case IKE_ID_FQDN:
+ case IKE_ID_USER_FQDN:
+ case IKE_ID_KEY_ID:
+ Copy(t->StrData, t->IdData->Buf, MIN(t->IdData->Size, sizeof(t->StrData) - 1));
+ break;
+
+ case IKE_ID_IPV4_ADDR:
+ if (t->IdData->Size == 4)
+ {
+ Copy(ip.addr, t->IdData->Buf, 4);
+
+ IPToStr(t->StrData, sizeof(t->StrData), &ip);
+ }
+ break;
+
+ case IKE_ID_IPV6_ADDR:
+ if (t->IdData->Size == 16)
+ {
+ SetIP6(&ip, t->IdData->Buf);
+
+ IPToStr(t->StrData, sizeof(t->StrData), &ip);
+ }
+ break;
+
+ case IKE_ID_IPV4_ADDR_SUBNET:
+ if (t->IdData->Size == 8)
+ {
+ char ipstr[MAX_SIZE];
+ char subnetstr[MAX_SIZE];
+ Copy(ip.addr, t->IdData->Buf, 4);
+ Copy(subnet.addr, ((UCHAR *)t->IdData->Buf) + 4, 4);
+
+ IPToStr(ipstr, sizeof(ipstr), &ip);
+ MaskToStr(subnetstr, sizeof(subnetstr), &subnet);
+
+ Format(t->StrData, sizeof(t->StrData), "%s/%s", ipstr, subnetstr);
+ }
+ break;
+
+ case IKE_ID_IPV6_ADDR_SUBNET:
+ if (t->IdData->Size == 32)
+ {
+ char ipstr[MAX_SIZE];
+ char subnetstr[MAX_SIZE];
+ SetIP6(&ip, t->IdData->Buf);
+ SetIP6(&subnet, ((UCHAR *)t->IdData->Buf) + 16);
+
+ IPToStr(ipstr, sizeof(ipstr), &ip);
+ MaskToStr(subnetstr, sizeof(subnetstr), &subnet);
+
+ Format(t->StrData, sizeof(t->StrData), "%s/%s", ipstr, subnetstr);
+ }
+ break;
+ }
+
+ return true;
+}
+
+// Release the ID payload
+void IkeFreeIdPayload(IKE_PACKET_ID_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->IdData != NULL)
+ {
+ FreeBuf(t->IdData);
+ t->IdData = NULL;
+ }
+}
+
+// Parse the certificate payload
+bool IkeParseCertPayload(IKE_PACKET_CERT_PAYLOAD *t, BUF *b)
+{
+ IKE_CERT_HEADER h;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ t->CertType = h.CertType;
+ t->CertData = ReadRemainBuf(b);
+ if (t->CertData == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Release the certificate payload
+void IkeFreeCertPayload(IKE_PACKET_CERT_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->CertData != NULL)
+ {
+ FreeBuf(t->CertData);
+ t->CertData = NULL;
+ }
+}
+
+// Parse the certificate request payload
+bool IkeParseCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t, BUF *b)
+{
+ IKE_CERT_REQUEST_HEADER h;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ t->CertType = h.CertType;
+ t->Data = ReadRemainBuf(b);
+ if (t->Data == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Release the certificate request payload
+void IkeFreeCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->Data != NULL)
+ {
+ FreeBuf(t->Data);
+ t->Data = NULL;
+ }
+}
+
+// Parse the notification payload
+bool IkeParseNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t, BUF *b)
+{
+ IKE_NOTICE_HEADER h;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ if (Endian32(h.DoI) != IKE_SA_DOI_IPSEC)
+ {
+ Debug("ISAKMP: Invalid DoI Value: 0x%x\n", Endian32(h.DoI));
+ return false;
+ }
+
+ t->MessageType = Endian16(h.MessageType);
+ t->ProtocolId = h.ProtocolId;
+ t->Spi = ReadBufFromBuf(b, h.SpiSize);
+ if (t->Spi == NULL)
+ {
+ return false;
+ }
+ t->MessageData = ReadRemainBuf(b);
+
+ return true;
+}
+
+// Release the notification payload
+void IkeFreeNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->MessageData != NULL)
+ {
+ FreeBuf(t->MessageData);
+ t->MessageData = NULL;
+ }
+
+ if (t->Spi != NULL)
+ {
+ FreeBuf(t->Spi);
+ t->Spi = NULL;
+ }
+}
+
+// Parse the NAT-OA payload
+bool IkeParseNatOaPayload(IKE_PACKET_NAT_OA_PAYLOAD *t, BUF *b)
+{
+ IKE_NAT_OA_HEADER h;
+ UCHAR ip4[4];
+ UCHAR ip6[16];
+ IP ip;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip, sizeof(ip));
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ if (h.IdType != IKE_ID_IPV4_ADDR && h.IdType != IKE_ID_IPV6_ADDR)
+ {
+ return false;
+ }
+
+ switch (h.IdType)
+ {
+ case IKE_ID_IPV4_ADDR: // IPv4
+ if (ReadBuf(b, ip4, sizeof(ip4)) != sizeof(ip4))
+ {
+ return false;
+ }
+
+ SetIP(&ip, ip4[0], ip4[1], ip4[2], ip4[3]);
+
+ break;
+
+ case IKE_ID_IPV6_ADDR: // IPv6
+ if (ReadBuf(b, ip6, sizeof(ip6)) != sizeof(ip6))
+ {
+ return false;
+ }
+
+ SetIP6(&ip, ip6);
+
+ break;
+
+ default:
+ return false;
+ }
+
+ Copy(&t->IpAddress, &ip, sizeof(IP));
+
+ return true;
+}
+
+// Parse the deletion payload
+bool IkeParseDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t, BUF *b)
+{
+ IKE_DELETE_HEADER h;
+ UINT num_spi;
+ UINT spi_size;
+ UINT i;
+ bool ok = true;
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &h, sizeof(h)) != sizeof(h))
+ {
+ return false;
+ }
+
+ if (Endian32(h.DoI) != IKE_SA_DOI_IPSEC)
+ {
+ Debug("ISAKMP: Invalid DoI Value: 0x%x\n", Endian32(h.DoI));
+ return false;
+ }
+
+ t->ProtocolId = h.ProtocolId;
+ t->SpiList = NewListFast(NULL);
+ num_spi = Endian16(h.NumSpis);
+ spi_size = h.SpiSize;
+
+ for (i = 0;i < num_spi;i++)
+ {
+ BUF *spi = ReadBufFromBuf(b, spi_size);
+
+ if (spi == NULL)
+ {
+ ok = false;
+ break;
+ }
+
+ Add(t->SpiList, spi);
+ }
+
+ if (ok == false)
+ {
+ IkeFreeDeletePayload(t);
+ return false;
+ }
+
+ return true;
+}
+
+// Release the deletion payload
+void IkeFreeDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->SpiList != NULL)
+ {
+ for (i = 0;i < LIST_NUM(t->SpiList);i++)
+ {
+ BUF *spi = LIST_DATA(t->SpiList, i);
+
+ FreeBuf(spi);
+ }
+
+ ReleaseList(t->SpiList);
+
+ t->SpiList = NULL;
+ }
+}
+
+// Check whether the hash matches
+bool IkeCompareHash(IKE_PACKET_PAYLOAD *hash_payload, void *hash_data, UINT hash_size)
+{
+ //char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+ // Validate arguments
+ if (hash_payload == NULL || hash_data == NULL || hash_size == 0)
+ {
+ return false;
+ }
+
+ if (hash_payload->PayloadType != IKE_PAYLOAD_HASH)
+ {
+ return false;
+ }
+
+ if (hash_payload->Payload.Hash.Data == NULL)
+ {
+ return false;
+ }
+
+ if (hash_payload->Payload.Hash.Data->Size != hash_size)
+ {
+ return false;
+ }
+
+ //BinToStrEx(tmp1, sizeof(tmp1), hash_payload->Payload.Hash.Data->Buf, hash_size);
+ //BinToStrEx(tmp2, sizeof(tmp2), hash_data, hash_size);
+
+ //Debug("IkeCompareHash\n 1: %s\n 2: %s\n", tmp1, tmp2);
+
+ if (Cmp(hash_payload->Payload.Hash.Data->Buf, hash_data, hash_size) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Parse the data payload
+bool IkeParseDataPayload(IKE_PACKET_DATA_PAYLOAD *t, BUF *b)
+{
+ // Validate arguments
+ if (t == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ t->Data = MemToBuf(b->Buf, b->Size);
+
+ return true;
+}
+
+// Release the data payload
+void IkeFreeDataPayload(IKE_PACKET_DATA_PAYLOAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeBuf(t->Data);
+}
+
+// Release the IKE payload body
+void IkeFreePayload(IKE_PACKET_PAYLOAD *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ switch (p->PayloadType)
+ {
+ case IKE_PAYLOAD_SA: // SA payload
+ IkeFreeSaPayload(&p->Payload.Sa);
+ break;
+
+ case IKE_PAYLOAD_PROPOSAL: // Proposal payload
+ IkeFreeProposalPayload(&p->Payload.Proposal);
+ break;
+
+ case IKE_PAYLOAD_TRANSFORM: // Proposal payload
+ IkeFreeTransformPayload(&p->Payload.Transform);
+ break;
+
+ case IKE_PAYLOAD_ID: // ID payload
+ IkeFreeIdPayload(&p->Payload.Id);
+ break;
+
+ case IKE_PAYLOAD_CERT: // Certificate payload
+ IkeFreeCertPayload(&p->Payload.Cert);
+ break;
+
+ case IKE_PAYLOAD_CERT_REQUEST: // Certificate request payload
+ IkeFreeCertRequestPayload(&p->Payload.CertRequest);
+ break;
+
+ case IKE_PAYLOAD_NOTICE: // Notification Payload
+ IkeFreeNoticePayload(&p->Payload.Notice);
+ break;
+
+ case IKE_PAYLOAD_DELETE: // Deletion payload
+ IkeFreeDeletePayload(&p->Payload.Delete);
+ break;
+
+ case IKE_PAYLOAD_NAT_OA: // NAT-OD payload
+ case IKE_PAYLOAD_NAT_OA_DRAFT:
+ case IKE_PAYLOAD_NAT_OA_DRAFT_2:
+ // Do Nothing
+ break;
+
+ case IKE_PAYLOAD_KEY_EXCHANGE: // Key exchange payload
+ case IKE_PAYLOAD_HASH: // Hash payload
+ case IKE_PAYLOAD_SIGN: // Signature payload
+ case IKE_PAYLOAD_RAND: // Random number payload
+ case IKE_PAYLOAD_VENDOR_ID: // Vendor ID payload
+ case IKE_PAYLOAD_NAT_D: // NAT-D payload
+ case IKE_PAYLOAD_NAT_D_DRAFT: // NAT-D payload (draft)
+ default:
+ IkeFreeDataPayload(&p->Payload.GeneralData);
+ break;
+ }
+
+ if (p->BitArray != NULL)
+ {
+ FreeBuf(p->BitArray);
+ }
+
+ Free(p);
+}
+
+// Analyse the IKE payload list
+LIST *IkeParsePayloadList(void *data, UINT size, UCHAR first_payload)
+{
+ return IkeParsePayloadListEx(data, size, first_payload, NULL);
+}
+LIST *IkeParsePayloadListEx(void *data, UINT size, UCHAR first_payload, UINT *total_read_size)
+{
+ LIST *o;
+ BUF *b;
+ UCHAR payload_type = first_payload;
+ UINT total = 0;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+ b = MemToBuf(data, size);
+
+ while (payload_type != IKE_PAYLOAD_NONE)
+ {
+ // Read the common header
+ IKE_COMMON_HEADER header;
+ USHORT payload_size;
+ BUF *payload_data;
+ IKE_PACKET_PAYLOAD *pay;
+
+ if (ReadBuf(b, &header, sizeof(header)) != sizeof(header))
+ {
+ Debug("ISAKMP: Broken Packet (Invalid Payload Size)\n");
+
+LABEL_ERROR:
+ // Header reading failure
+ IkeFreePayloadList(o);
+ o = NULL;
+
+ break;
+ }
+
+ total += sizeof(header);
+
+ // Get the payload size
+ payload_size = Endian16(header.PayloadSize);
+
+ if (payload_size < sizeof(header))
+ {
+ Debug("ISAKMP: Broken Packet (Invalid Payload Size)\n");
+ goto LABEL_ERROR;
+ }
+
+ payload_size -= sizeof(header);
+
+ // Read the payload data
+ payload_data = ReadBufFromBuf(b, payload_size);
+ if (payload_data == NULL)
+ {
+ // Data read failure
+ Debug("ISAKMP: Broken Packet (Invalid Payload Data)\n");
+ goto LABEL_ERROR;
+ }
+
+ total += payload_size;
+
+ // Analyse the payload body
+ if (IKE_IS_SUPPORTED_PAYLOAD_TYPE(payload_type))
+ {
+ // Supported payload type
+ pay = IkeParsePayload(payload_type, payload_data);
+
+ if (pay == NULL)
+ {
+ FreeBuf(payload_data);
+ Debug("ISAKMP: Broken Packet (Payload Data Parse Failed)\n");
+ goto LABEL_ERROR;
+ }
+
+ Add(o, pay);
+ }
+ else
+ {
+ // Unsupported payload type
+ Debug("ISAKMP: Ignored Payload Type: %u\n", payload_type);
+ pay = IkeParsePayload(payload_type, payload_data);
+
+ if (pay == NULL)
+ {
+ FreeBuf(payload_data);
+ Debug("ISAKMP: Broken Packet (Payload Data Parse Failed)\n");
+ goto LABEL_ERROR;
+ }
+
+ Add(o, pay);
+ }
+
+ payload_type = header.NextPayload;
+
+ FreeBuf(payload_data);
+ }
+
+ FreeBuf(b);
+
+ if (total_read_size != NULL)
+ {
+ *total_read_size = total;
+ }
+
+ return o;
+}
+
+// Release the IKE payload list
+void IkeFreePayloadList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_PAYLOAD *p = LIST_DATA(o, i);
+
+ IkeFreePayload(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Build an IKE packet
+BUF *IkeBuild(IKE_PACKET *p, IKE_CRYPTO_PARAM *cparam)
+{
+ return IkeBuildEx(p, cparam, false);
+}
+BUF *IkeBuildEx(IKE_PACKET *p, IKE_CRYPTO_PARAM *cparam, bool use_original_decrypted)
+{
+ IKE_HEADER h;
+ BUF *msg_buf;
+ BUF *ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ if (p->PayloadList == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+ h.InitiatorCookie = Endian64(p->InitiatorCookie);
+ h.ResponderCookie = Endian64(p->ResponderCookie);
+ h.NextPayload = IkeGetFirstPayloadType(p->PayloadList);
+ h.Version = IKE_VERSION;
+ h.ExchangeType = p->ExchangeType;
+ h.Flag = (p->FlagEncrypted ? IKE_HEADER_FLAG_ENCRYPTED : 0) |
+ (p->FlagCommit ? IKE_HEADER_FLAG_COMMIT : 0) |
+ (p->FlagAuthOnly ? IKE_HEADER_FLAG_AUTH_ONLY : 0);
+ h.MessageId = Endian32(p->MessageId);
+
+ if (p->DecryptedPayload != NULL && use_original_decrypted)
+ {
+ msg_buf = CloneBuf(p->DecryptedPayload);
+ }
+ else
+ {
+ msg_buf = IkeBuildPayloadList(p->PayloadList);
+ }
+
+ if (p->DecryptedPayload != NULL)
+ {
+ FreeBuf(p->DecryptedPayload);
+ }
+
+ p->DecryptedPayload = CloneBuf(msg_buf);
+
+ if (p->FlagEncrypted)
+ {
+ BUF *b;
+ // Encryption
+ b = IkeEncryptWithPadding(msg_buf->Buf, msg_buf->Size, cparam);
+
+ if (b == NULL)
+ {
+ Debug("ISAKMP: Packet Encrypt Failed\n");
+ FreeBuf(msg_buf);
+ return NULL;
+ }
+
+ FreeBuf(msg_buf);
+
+ msg_buf = b;
+ }
+
+ h.MessageSize = Endian32(msg_buf->Size + sizeof(h));
+
+ ret = NewBuf();
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBufBuf(ret, msg_buf);
+
+ FreeBuf(msg_buf);
+
+ SeekBuf(ret, 0, 0);
+
+ return ret;
+}
+
+// Analyse the IKE packet
+IKE_PACKET *IkeParseEx(void *data, UINT size, IKE_CRYPTO_PARAM *cparam, bool header_only)
+{
+ IKE_PACKET *p = NULL;
+ BUF *b;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ b = MemToBuf(data, size);
+
+ if (b->Size < sizeof(IKE_HEADER))
+ {
+ Debug("ISAKMP: Invalid Packet Size\n");
+ }
+ else
+ {
+ // Header analysis
+ IKE_HEADER *h = (IKE_HEADER *)b->Buf;
+
+ p = ZeroMalloc(sizeof(IKE_PACKET));
+
+ p->MessageSize = Endian32(h->MessageSize);
+ p->InitiatorCookie = Endian64(h->InitiatorCookie);
+ p->ResponderCookie = Endian64(h->ResponderCookie);
+ p->ExchangeType = h->ExchangeType;
+ p->FlagEncrypted = (h->Flag & IKE_HEADER_FLAG_ENCRYPTED) ? true : false;
+ p->FlagCommit = (h->Flag & IKE_HEADER_FLAG_COMMIT) ? true : false;
+ p->FlagAuthOnly = (h->Flag & IKE_HEADER_FLAG_AUTH_ONLY) ? true : false;
+ p->MessageId = Endian32(h->MessageId);
+
+ if (b->Size < Endian32(h->MessageSize) ||
+ Endian32(h->MessageSize) < sizeof(IKE_HEADER))
+ {
+ Debug("ISAKMP: Invalid Packet Size\n");
+
+ IkeFree(p);
+ p = NULL;
+ }
+ else
+ {
+ if (header_only == false)
+ {
+ bool ok = false;
+ UCHAR *payload_data;
+ UINT payload_size;
+ BUF *buf = NULL;
+
+ payload_data = ((UCHAR *)h) + sizeof(IKE_HEADER);
+ payload_size = Endian32(h->MessageSize) - sizeof(IKE_HEADER);
+
+ // Decrypt if it is encrypted
+ if (p->FlagEncrypted)
+ {
+ buf = IkeDecrypt(payload_data, payload_size, cparam);
+
+ if (buf != NULL)
+ {
+ ok = true;
+
+ payload_data = buf->Buf;
+ payload_size = buf->Size;
+
+ p->DecryptedPayload = CloneBuf(buf);
+ }
+ }
+ else
+ {
+ ok = true;
+ }
+
+ if (ok == false)
+ {
+ Debug("ISAKMP: Decrypt Failed\n");
+
+ IkeFree(p);
+ p = NULL;
+ }
+ else
+ {
+ UINT total_read_size;
+
+ // Payload analysis
+ p->PayloadList = IkeParsePayloadListEx(payload_data,
+ payload_size,
+ h->NextPayload,
+ &total_read_size);
+
+ if (p->DecryptedPayload != NULL)
+ {
+ p->DecryptedPayload->Size = MIN(p->DecryptedPayload->Size, total_read_size);
+ }
+ else
+ {
+ p->DecryptedPayload = MemToBuf(payload_data, payload_size);
+ }
+ }
+
+ if (buf != NULL)
+ {
+ FreeBuf(buf);
+ }
+ }
+ }
+ }
+
+ FreeBuf(b);
+
+ return p;
+}
+IKE_PACKET *IkeParseHeader(void *data, UINT size, IKE_CRYPTO_PARAM *cparam)
+{
+ return IkeParseEx(data, size, cparam, true);
+}
+IKE_PACKET *IkeParse(void *data, UINT size, IKE_CRYPTO_PARAM *cparam)
+{
+ return IkeParseEx(data, size, cparam, false);
+}
+
+// Send packet for debugging by UDP (For debugging with Ethereal)
+void IkeDebugUdpSendRawPacket(IKE_PACKET *p)
+{
+ BUF *b;
+ IP ip;
+ SOCK *udp;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->FlagEncrypted = false;
+
+ b = NULL;
+
+ if (b == NULL)
+ {
+ b = IkeBuildEx(p, NULL, true);
+ }
+
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Zero(&ip, sizeof(ip));
+ SetIP(&ip, 1, 2, 3, 4);
+
+ udp = NewUDP(0);
+
+ SendTo(udp, &ip, 500, b->Buf, b->Size);
+
+ ReleaseSock(udp);
+ FreeBuf(b);
+}
+
+// Output the payload list
+void IkeDebugPrintPayloads(LIST *o, UINT depth)
+{
+ UINT i;
+ char space[MAX_SIZE];
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ MakeCharArray2(space, ' ', depth * 2);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IKE_PACKET_PAYLOAD *payload = LIST_DATA(o, i);
+
+ Debug("%s%u: Type = %u, Size = %u\n", space, i, payload->PayloadType, payload->BitArray->Size);
+
+ switch (payload->PayloadType)
+ {
+ case IKE_PAYLOAD_SA:
+ IkeDebugPrintPayloads(payload->Payload.Sa.PayloadList, depth + 1);
+ break;
+
+ case IKE_PAYLOAD_PROPOSAL:
+ IkeDebugPrintPayloads(payload->Payload.Proposal.PayloadList, depth + 1);
+ break;
+ }
+ }
+}
+
+// Encryption (also with padding)
+BUF *IkeEncryptWithPadding(void *data, UINT size, IKE_CRYPTO_PARAM *cparam)
+{
+ UINT total_size;
+ UINT i;
+ UCHAR n = 0;
+ UCHAR *tmp;
+ BUF *ret;
+ UCHAR tmp1600[1600];
+ bool no_free = false;
+ // Validate arguments
+ if (data == NULL || cparam == NULL)
+ {
+ return NULL;
+ }
+
+ total_size = ((size / cparam->Key->Crypto->BlockSize) + ((size % cparam->Key->Crypto->BlockSize) == 0 ? 0 : 1))
+ * cparam->Key->Crypto->BlockSize;
+ if (total_size == 0)
+ {
+ total_size = cparam->Key->Crypto->BlockSize;
+ }
+
+ if (total_size > sizeof(tmp1600))
+ {
+ tmp = Malloc(total_size);
+ }
+ else
+ {
+ tmp = tmp1600;
+ no_free = true;
+ }
+
+ Copy(tmp, data, size);
+
+ for (i = size;i < total_size;i++)
+ {
+ tmp[i] = ++n;
+ }
+
+ ret = IkeEncrypt(tmp, total_size, cparam);
+
+ if (no_free == false)
+ {
+ Free(tmp);
+ }
+
+ return ret;
+}
+
+// Encryption
+BUF *IkeEncrypt(void *data, UINT size, IKE_CRYPTO_PARAM *cparam)
+{
+ void *tmp;
+ BUF *b;
+ UCHAR tmp1600[1600];
+ bool no_free = false;
+ // Validate arguments
+ if (data == NULL || cparam == NULL)
+ {
+ return NULL;
+ }
+
+ if ((size % cparam->Key->Crypto->BlockSize) != 0)
+ {
+ // Not an integral multiple of block size
+ return NULL;
+ }
+
+ if (size > sizeof(tmp1600))
+ {
+ tmp = Malloc(size);
+ }
+ else
+ {
+ tmp = tmp1600;
+ no_free = true;
+ }
+
+ IkeCryptoEncrypt(cparam->Key, tmp, data, size, cparam->Iv);
+
+ if (size >= cparam->Key->Crypto->BlockSize)
+ {
+ Copy(cparam->NextIv, ((UCHAR *)tmp) + (size - cparam->Key->Crypto->BlockSize), cparam->Key->Crypto->BlockSize);
+ }
+ else
+ {
+ Zero(cparam->NextIv, cparam->Key->Crypto->BlockSize);
+ }
+
+ b = MemToBuf(tmp, size);
+
+ if (no_free == false)
+ {
+ Free(tmp);
+ }
+
+ return b;
+}
+
+// Decryption
+BUF *IkeDecrypt(void *data, UINT size, IKE_CRYPTO_PARAM *cparam)
+{
+ void *tmp;
+ BUF *b;
+ UCHAR tmp1600[1600];
+ bool no_free = false;
+ // Validate arguments
+ if (data == NULL || cparam == NULL)
+ {
+ return NULL;
+ }
+
+ if ((size % cparam->Key->Crypto->BlockSize) != 0)
+ {
+ // Not an integral multiple of block size
+ return NULL;
+ }
+
+ if (size > sizeof(tmp1600))
+ {
+ tmp = Malloc(size);
+ }
+ else
+ {
+ tmp = tmp1600;
+ no_free = true;
+ }
+
+ IkeCryptoDecrypt(cparam->Key, tmp, data, size, cparam->Iv);
+
+ if (size >= cparam->Key->Crypto->BlockSize)
+ {
+ Copy(cparam->NextIv, ((UCHAR *)data) + (size - cparam->Key->Crypto->BlockSize), cparam->Key->Crypto->BlockSize);
+ }
+ else
+ {
+ Zero(cparam->NextIv, cparam->Key->Crypto->BlockSize);
+ }
+
+ b = MemToBuf(tmp, size);
+
+ if (no_free == false)
+ {
+ Free(tmp);
+ }
+
+ return b;
+}
+
+// Release the IKE packet
+void IkeFree(IKE_PACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->PayloadList != NULL)
+ {
+ IkeFreePayloadList(p->PayloadList);
+ }
+
+ if (p->DecryptedPayload != NULL)
+ {
+ FreeBuf(p->DecryptedPayload);
+ }
+
+ Free(p);
+}
+
+// Create an IKE packet
+IKE_PACKET *IkeNew(UINT64 init_cookie, UINT64 resp_cookie, UCHAR exchange_type,
+ bool encrypted, bool commit, bool auth_only, UINT msg_id,
+ LIST *payload_list)
+{
+ IKE_PACKET *p = ZeroMalloc(sizeof(IKE_PACKET));
+
+ p->InitiatorCookie = init_cookie;
+ p->ResponderCookie = resp_cookie;
+ p->ExchangeType = exchange_type;
+ p->FlagEncrypted = encrypted;
+ p->FlagCommit = commit;
+ p->FlagAuthOnly = auth_only;
+ p->MessageId = msg_id;
+ p->PayloadList = payload_list;
+
+ return p;
+}
+
+// Create a new SPI value
+UINT IkeNewSpi()
+{
+ while (true)
+ {
+ UINT i = Rand32();
+
+ if (i >= 4096)
+ {
+ return i;
+ }
+ }
+}
+
+
+// Create an encryption engine for IKE
+IKE_ENGINE *NewIkeEngine()
+{
+ IKE_ENGINE *e = ZeroMalloc(sizeof(IKE_ENGINE));
+ IKE_CRYPTO *des, *des3, *aes;
+ IKE_HASH *sha1, *md5;
+ IKE_DH *dh1, *dh2, *dh5;
+ UINT des_key_sizes[] =
+ {
+ 8,
+ };
+ UINT des3_key_sizes[] =
+ {
+ 24,
+ };
+ UINT aes_key_sizes[] =
+ {
+ 16, 24, 32,
+ };
+
+ e->CryptosList = NewListFast(NULL);
+ e->HashesList = NewListFast(NULL);
+ e->DhsList = NewListFast(NULL);
+
+ //// Encryption algorithm
+ // DES
+ des = NewIkeCrypto(e, IKE_CRYPTO_DES_ID, IKE_CRYPTO_DES_STRING,
+ des_key_sizes, sizeof(des_key_sizes) / sizeof(UINT), 8);
+
+ // 3DES
+ des3 = NewIkeCrypto(e, IKE_CRYPTO_3DES_ID, IKE_CRYPTO_3DES_STRING,
+ des3_key_sizes, sizeof(des3_key_sizes) / sizeof(UINT), 8);
+
+ // AES
+ aes = NewIkeCrypto(e, IKE_CRYPTO_AES_ID, IKE_CRYPTO_AES_STRING,
+ aes_key_sizes, sizeof(aes_key_sizes) / sizeof(UINT), 16);
+
+ //// Hash algorithm
+ // SHA-1
+ sha1 = NewIkeHash(e, IKE_HASH_SHA1_ID, IKE_HASH_SHA1_STRING, 20);
+
+ // MD5
+ md5 = NewIkeHash(e, IKE_HASH_MD5_ID, IKE_HASH_MD5_STRING, 16);
+
+ //// DH algorithm
+ dh1 = NewIkeDh(e, IKE_DH_1_ID, IKE_DH_1_STRING, 96);
+ dh2 = NewIkeDh(e, IKE_DH_2_ID, IKE_DH_2_STRING, 128);
+ dh5 = NewIkeDh(e, IKE_DH_5_ID, IKE_DH_5_STRING, 192);
+
+ // Define the IKE algorithm
+ e->IkeCryptos[IKE_P1_CRYPTO_DES_CBC] = des;
+ e->IkeCryptos[IKE_P1_CRYPTO_3DES_CBC] = des3;
+ e->IkeCryptos[IKE_P1_CRYPTO_AES_CBC] = aes;
+ e->IkeHashes[IKE_P1_HASH_MD5] = md5;
+ e->IkeHashes[IKE_P1_HASH_SHA1] = sha1;
+
+ // Definition of ESP algorithm
+ e->EspCryptos[IKE_TRANSFORM_ID_P2_ESP_DES] = des;
+ e->EspCryptos[IKE_TRANSFORM_ID_P2_ESP_3DES] = des3;
+ e->EspCryptos[IKE_TRANSFORM_ID_P2_ESP_AES] = aes;
+ e->EspHashes[IKE_P2_HMAC_MD5_96] = md5;
+ e->EspHashes[IKE_P2_HMAC_SHA1_96] = sha1;
+
+ // Definition of the DH algorithm
+ e->IkeDhs[IKE_P1_DH_GROUP_768_MODP] = e->EspDhs[IKE_P2_DH_GROUP_768_MODP] = dh1;
+ e->IkeDhs[IKE_P1_DH_GROUP_1024_MODP] = e->EspDhs[IKE_P2_DH_GROUP_1024_MODP] = dh2;
+ e->IkeDhs[IKE_P1_DH_GROUP_1536_MODP] = e->EspDhs[IKE_P2_DH_GROUP_1536_MODP] = dh5;
+
+ return e;
+}
+
+// Release the encryption engine for IKE
+void FreeIkeEngine(IKE_ENGINE *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(e->CryptosList);i++)
+ {
+ IKE_CRYPTO *c = LIST_DATA(e->CryptosList, i);
+
+ FreeIkeCrypto(c);
+ }
+
+ ReleaseList(e->CryptosList);
+
+ for (i = 0;i < LIST_NUM(e->HashesList);i++)
+ {
+ IKE_HASH *h = LIST_DATA(e->HashesList, i);
+
+ FreeIkeHash(h);
+ }
+ ReleaseList(e->HashesList);
+
+ for (i = 0;i < LIST_NUM(e->DhsList);i++)
+ {
+ IKE_DH *d = LIST_DATA(e->DhsList, i);
+
+ FreeIkeDh(d);
+ }
+ ReleaseList(e->DhsList);
+
+ Free(e);
+}
+
+// Definition of a new DH algorithm for IKE
+IKE_DH *NewIkeDh(IKE_ENGINE *e, UINT dh_id, char *name, UINT key_size)
+{
+ IKE_DH *d;
+ // Validate arguments
+ if (e == NULL || name == NULL || key_size == 0)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(IKE_DH));
+
+ d->DhId = dh_id;
+ d->Name = name;
+ d->KeySize = key_size;
+
+ Add(e->DhsList, d);
+
+ return d;
+}
+
+// Definition of a new encryption algorithm for IKE
+IKE_CRYPTO *NewIkeCrypto(IKE_ENGINE *e, UINT crypto_id, char *name, UINT *key_sizes, UINT num_key_sizes, UINT block_size)
+{
+ IKE_CRYPTO *c;
+ UINT i;
+ // Validate arguments
+ if (e == NULL || name == NULL || key_sizes == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(IKE_CRYPTO));
+
+ c->CryptoId = crypto_id;
+ c->Name = name;
+
+ for (i = 0;i < MIN(num_key_sizes, 16);i++)
+ {
+ c->KeySizes[i] = key_sizes[i];
+ }
+
+ if (num_key_sizes >= 2)
+ {
+ c->VariableKeySize = true;
+ }
+
+ c->BlockSize = block_size;
+
+ Add(e->CryptosList, c);
+
+ return c;
+}
+
+// Release the definition of Encryption algorithm for IKE
+void FreeIkeCrypto(IKE_CRYPTO *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Free(c);
+}
+
+// Release the definition of IKE hash algorithm
+void FreeIkeHash(IKE_HASH *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Free(h);
+}
+
+// Release the definition of the DH algorithm for IKE
+void FreeIkeDh(IKE_DH *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Free(d);
+}
+
+// Definition of a new hash algorithm for IKE
+IKE_HASH *NewIkeHash(IKE_ENGINE *e, UINT hash_id, char *name, UINT size)
+{
+ IKE_HASH *h;
+ // Validate arguments
+ if (e == NULL || name == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ h = ZeroMalloc(sizeof(IKE_HASH));
+
+ h->HashId = hash_id;
+ h->Name = name;
+ h->HashSize = size;
+
+ Add(e->HashesList, h);
+
+ return h;
+}
+
+// Get the encryption algorithm that is used in IKE
+IKE_CRYPTO *GetIkeCrypto(IKE_ENGINE *e, bool for_esp, UINT i)
+{
+ // Validate arguments
+ if (e == NULL || i == 0 || i >= MAX_IKE_ENGINE_ELEMENTS)
+ {
+ return NULL;
+ }
+
+ if (for_esp)
+ {
+ return e->EspCryptos[i];
+ }
+ else
+ {
+ return e->IkeCryptos[i];
+ }
+}
+
+// Get the hash algorithm used in the IKE
+IKE_HASH *GetIkeHash(IKE_ENGINE *e, bool for_esp, UINT i)
+{
+ // Validate arguments
+ if (e == NULL || i == 0 || i >= MAX_IKE_ENGINE_ELEMENTS)
+ {
+ return NULL;
+ }
+
+ if (for_esp)
+ {
+ return e->EspHashes[i];
+ }
+ else
+ {
+ return e->IkeHashes[i];
+ }
+}
+
+// Get the DH algorithm used in the IKE
+IKE_DH *GetIkeDh(IKE_ENGINE *e, bool for_esp, UINT i)
+{
+ // Validate arguments
+ if (e == NULL || i == 0 || i >= MAX_IKE_ENGINE_ELEMENTS)
+ {
+ return NULL;
+ }
+
+ if (for_esp)
+ {
+ return e->EspDhs[i];
+ }
+ else
+ {
+ return e->IkeDhs[i];
+ }
+}
+
+// Perform encryption
+void IkeCryptoEncrypt(IKE_CRYPTO_KEY *k, void *dst, void *src, UINT size, void *ivec)
+{
+ // Validate arguments
+ if (k == NULL || dst == NULL || src == NULL || size == 0 || ivec == NULL)
+ {
+ Zero(dst, size);
+ return;
+ }
+
+ if ((size % k->Crypto->BlockSize) != 0)
+ {
+ Zero(dst, size);
+ return;
+ }
+
+ switch (k->Crypto->CryptoId)
+ {
+ case IKE_CRYPTO_DES_ID: // DES
+ DesEncrypt(dst, src, size, k->DesKey1, ivec);
+ break;
+
+ case IKE_CRYPTO_3DES_ID: // 3DES
+ Des3Encrypt2(dst, src, size, k->DesKey1, k->DesKey2, k->DesKey3, ivec);
+ break;
+
+ case IKE_CRYPTO_AES_ID: // AES
+ AesEncrypt(dst, src, size, k->AesKey, ivec);
+ break;
+
+ default:
+ // Unknown
+ Zero(dst, size);
+ break;
+ }
+}
+
+// Perform decryption
+void IkeCryptoDecrypt(IKE_CRYPTO_KEY *k, void *dst, void *src, UINT size, void *ivec)
+{
+ // Validate arguments
+ if (k == NULL || dst == NULL || src == NULL || size == 0 || ivec == NULL)
+ {
+ Zero(dst, size);
+ return;
+ }
+
+ if ((size % k->Crypto->BlockSize) != 0)
+ {
+ Zero(dst, size);
+ return;
+ }
+
+ switch (k->Crypto->CryptoId)
+ {
+ case IKE_CRYPTO_DES_ID: // DES
+ DesDecrypt(dst, src, size, k->DesKey1, ivec);
+ break;
+
+ case IKE_CRYPTO_3DES_ID: // 3DES
+ Des3Decrypt2(dst, src, size, k->DesKey1, k->DesKey2, k->DesKey3, ivec);
+ break;
+
+ case IKE_CRYPTO_AES_ID: // AES
+ AesDecrypt(dst, src, size, k->AesKey, ivec);
+ break;
+
+ default:
+ // Unknown
+ Zero(dst, size);
+ break;
+ }
+}
+
+// Calculate a hash
+void IkeHash(IKE_HASH *h, void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (h == NULL || dst == NULL || (size != 0 && src == NULL))
+ {
+ Zero(dst, size);
+ return;
+ }
+
+ switch (h->HashId)
+ {
+ case IKE_HASH_MD5_ID:
+ // MD5
+ Md5(dst, src, size);
+ break;
+
+ case IKE_HASH_SHA1_ID:
+ // SHA-1
+ Sha1(dst, src, size);
+ break;
+
+ default:
+ // Unknown
+ Zero(dst, size);
+ break;
+ }
+}
+
+// Calculation of HMAC
+void IkeHMac(IKE_HASH *h, void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR k[HMAC_BLOCK_SIZE];
+ UCHAR *data1;
+ UCHAR hash1[IKE_MAX_HASH_SIZE];
+ UINT data1_size;
+ UCHAR data2[IKE_MAX_HASH_SIZE + HMAC_BLOCK_SIZE];
+ UINT data2_size;
+ UCHAR tmp1600[1600];
+ bool no_free = false;
+ UINT i;
+ // Validate arguments
+ if (h == NULL || dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ if (h->HashId == IKE_HASH_SHA1_ID)
+ {
+ // Use special function (fast) in the case of SHA-1
+ HMacSha1(dst, key, key_size, data, data_size);
+ return;
+ }
+ else if (h->HashId == IKE_HASH_MD5_ID)
+ {
+ // Use the special function (fast) in the case of MD5
+ HMacMd5(dst, key, key_size, data, data_size);
+ return;
+ }
+
+ // Creating a K
+ Zero(k, sizeof(k));
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ Copy(k, key, key_size);
+ }
+ else
+ {
+ IkeHash(h, k, key, key_size);
+ }
+
+ // Generation of data 1
+ data1_size = data_size + HMAC_BLOCK_SIZE;
+
+ if (data1_size > sizeof(tmp1600))
+ {
+ data1 = Malloc(data1_size);
+ }
+ else
+ {
+ data1 = tmp1600;
+ no_free = true;
+ }
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data1[i] = k[i] ^ 0x36;
+ }
+
+ Copy(data1 + HMAC_BLOCK_SIZE, data, data_size);
+
+ // Calculate the hash value
+ IkeHash(h, hash1, data1, data1_size);
+
+ if (no_free == false)
+ {
+ Free(data1);
+ }
+
+ // Generation of data 2
+ data2_size = h->HashSize + HMAC_BLOCK_SIZE;
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = k[i] ^ 0x5c;
+ }
+
+ Copy(data2 + HMAC_BLOCK_SIZE, hash1, h->HashSize);
+
+ // Calculate the hash value
+ IkeHash(h, dst, data2, data2_size);
+}
+void IkeHMacBuf(IKE_HASH *h, void *dst, BUF *key, BUF *data)
+{
+ // Validate arguments
+ if (h == NULL || dst == NULL || key == NULL || data == NULL)
+ {
+ return;
+ }
+
+ IkeHMac(h, dst, key->Buf, key->Size, data->Buf, data->Size);
+}
+
+// Check whether the key size is valid
+bool IkeCheckKeySize(IKE_CRYPTO *c, UINT size)
+{
+ bool ok = false;
+ UINT i;
+ // Validate arguments
+ if (c == NULL || size == 0)
+ {
+ return false;
+ }
+
+ for (i = 0;i < sizeof(c->KeySizes) / sizeof(UINT);i++)
+ {
+ if (c->KeySizes[i] == size)
+ {
+ ok = true;
+ break;
+ }
+ }
+
+ return ok;
+}
+
+// Create a key
+IKE_CRYPTO_KEY *IkeNewKey(IKE_CRYPTO *c, void *data, UINT size)
+{
+ IKE_CRYPTO_KEY *k;
+ // Validate arguments
+ if (c == NULL || data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ if (IkeCheckKeySize(c, size) == false)
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(IKE_CRYPTO_KEY));
+ k->Crypto = c;
+ k->Data = Clone(data, size);
+ k->Size = size;
+
+ switch (k->Crypto->CryptoId)
+ {
+ case IKE_CRYPTO_DES_ID:
+ // DES 64bit key
+ k->DesKey1 = DesNewKeyValue(data);
+ break;
+
+ case IKE_CRYPTO_3DES_ID:
+ // 3DES 192bit key
+ k->DesKey1 = DesNewKeyValue(((UCHAR *)data) + DES_KEY_SIZE * 0);
+ k->DesKey2 = DesNewKeyValue(((UCHAR *)data) + DES_KEY_SIZE * 1);
+ k->DesKey3 = DesNewKeyValue(((UCHAR *)data) + DES_KEY_SIZE * 2);
+ break;
+
+ case IKE_CRYPTO_AES_ID:
+ // AES variable length key
+ k->AesKey = AesNewKey(data, size);
+ break;
+ }
+
+ return k;
+}
+
+// Release the key
+void IkeFreeKey(IKE_CRYPTO_KEY *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ DesFreeKeyValue(k->DesKey1);
+ DesFreeKeyValue(k->DesKey2);
+ DesFreeKeyValue(k->DesKey3);
+
+ AesFreeKey(k->AesKey);
+
+ Free(k->Data);
+
+ Free(k);
+}
+
+// Create a DH object
+DH_CTX *IkeDhNewCtx(IKE_DH *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return NULL;
+ }
+
+ switch (d->DhId)
+ {
+ case IKE_DH_1_ID:
+ return DhNewGroup1();
+
+ case IKE_DH_2_ID:
+ return DhNewGroup2();
+
+ case IKE_DH_5_ID:
+ return DhNewGroup5();
+ }
+
+ return NULL;
+}
+
+// Release the DH object
+void IkeDhFreeCtx(DH_CTX *dh)
+{
+ // Validate arguments
+ if (dh == NULL)
+ {
+ return;
+ }
+
+ DhFree(dh);
+}
+
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_IkePacket.h b/src/Cedar/IPsec_IkePacket.h
new file mode 100644
index 00000000..98a10392
--- /dev/null
+++ b/src/Cedar/IPsec_IkePacket.h
@@ -0,0 +1,711 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_IkePacket.h
+// Header of IPsec_IkePacket.c
+
+#ifndef IPSEC_PACKET_H
+#define IPSEC_PACKET_H
+
+// Constants
+#ifdef OS_WIN32
+#pragma pack(push, 1)
+#endif // OS_WIN32
+
+// Maximum hash size
+#define IKE_MAX_HASH_SIZE 20 // Size of SHA-1 is the maximum for now
+
+// Maximum block size
+#define IKE_MAX_BLOCK_SIZE 16 // Size of AES is maximum at the moment
+
+// Maximum key size
+#define IKE_MAX_KEY_SIZE 32 // Size of AES-256 is the maximum for now
+
+// IKE version
+#define IKE_VERSION 0x10 // 1.0
+
+// IKE payload type
+#define IKE_PAYLOAD_NONE 0 // No payload
+#define IKE_PAYLOAD_SA 1 // SA payload
+#define IKE_PAYLOAD_PROPOSAL 2 // Proposal payload
+#define IKE_PAYLOAD_TRANSFORM 3 // Transform payload
+#define IKE_PAYLOAD_KEY_EXCHANGE 4 // Key exchange payload
+#define IKE_PAYLOAD_ID 5 // ID payload
+#define IKE_PAYLOAD_CERT 6 // Certificate payload
+#define IKE_PAYLOAD_CERT_REQUEST 7 // Certificate request payload
+#define IKE_PAYLOAD_HASH 8 // Hash payload
+#define IKE_PAYLOAD_SIGN 9 // Signature payload
+#define IKE_PAYLOAD_RAND 10 // Random number payload
+#define IKE_PAYLOAD_NOTICE 11 // Notification Payload
+#define IKE_PAYLOAD_DELETE 12 // Deletion payload
+#define IKE_PAYLOAD_VENDOR_ID 13 // Vendor ID payload
+#define IKE_PAYLOAD_NAT_D 20 // NAT-D payload
+#define IKE_PAYLOAD_NAT_OA 21 // NAT-OA payload
+#define IKE_PAYLOAD_NAT_D_DRAFT 130 // NAT-D payload draft
+#define IKE_PAYLOAD_NAT_OA_DRAFT 16 // NAT-OA payload draft
+#define IKE_PAYLOAD_NAT_OA_DRAFT_2 131 // NAT-OA payload draft 2
+
+// Macro to check whether the payload type is supported
+#define IKE_IS_SUPPORTED_PAYLOAD_TYPE(i) ((((i) >= IKE_PAYLOAD_SA) && ((i) <= IKE_PAYLOAD_VENDOR_ID)) || ((i) == IKE_PAYLOAD_NAT_D) || ((i) == IKE_PAYLOAD_NAT_OA) || ((i) == IKE_PAYLOAD_NAT_OA_DRAFT) || ((i) == IKE_PAYLOAD_NAT_OA_DRAFT_2) || ((i) == IKE_PAYLOAD_NAT_D_DRAFT))
+
+// IKE header flag
+#define IKE_HEADER_FLAG_ENCRYPTED 1 // Encryption
+#define IKE_HEADER_FLAG_COMMIT 2 // Commit
+#define IKE_HEADER_FLAG_AUTH_ONLY 4 // Only authentication
+
+// IKE payload common header
+struct IKE_COMMON_HEADER
+{
+ UCHAR NextPayload;
+ UCHAR Reserved;
+ USHORT PayloadSize;
+} GCC_PACKED;
+
+// IKE SA payload header
+struct IKE_SA_HEADER
+{
+ UINT DoI; // DOI value
+ UINT Situation; // Situation value
+} GCC_PACKED;
+
+// DOI value in the IKE SA payload
+#define IKE_SA_DOI_IPSEC 1 // IPsec
+
+// Situation value in the IKE SA payload
+#define IKE_SA_SITUATION_IDENTITY 1 // Only authentication
+
+// IKE proposal payload header
+struct IKE_PROPOSAL_HEADER
+{
+ UCHAR Number; // Number
+ UCHAR ProtocolId; // Protocol ID
+ UCHAR SpiSize; // Length of SPI
+ UCHAR NumTransforms; // Transform number
+} GCC_PACKED;
+
+// Protocol ID in the IKE proposal payload header
+#define IKE_PROTOCOL_ID_IKE 1 // IKE
+#define IKE_PROTOCOL_ID_IPSEC_AH 2 // AH
+#define IKE_PROTOCOL_ID_IPSEC_ESP 3 // ESP
+#define IKE_PROTOCOL_ID_IPV4 4 // IP
+#define IKE_PROTOCOL_ID_IPV6 41 // IPv6
+
+// IKE transform payload header
+struct IKE_TRANSFORM_HEADER
+{
+ UCHAR Number; // Number
+ UCHAR TransformId; // Transform ID
+ USHORT Reserved; // Reserved
+} GCC_PACKED;
+
+// Transform ID (Phase 1) in IKE transform payload header
+#define IKE_TRANSFORM_ID_P1_KEY_IKE 1 // IKE
+
+// Transform ID (Phase 2) in IKE transform payload header
+#define IKE_TRANSFORM_ID_P2_ESP_DES 2 // DES-CBC
+#define IKE_TRANSFORM_ID_P2_ESP_3DES 3 // 3DES-CBC
+#define IKE_TRANSFORM_ID_P2_ESP_CAST 6 // CAST
+#define IKE_TRANSFORM_ID_P2_ESP_BLOWFISH 7 // BLOWFISH
+#define IKE_TRANSFORM_ID_P2_ESP_AES 12 // AES
+
+// IKE transform value (fixed length)
+struct IKE_TRANSFORM_VALUE
+{
+ UCHAR AfBit; // AF bit (0: Fixed length, 1: Variable length)
+ UCHAR Type; // Type
+ USHORT Value; // Value data (16bit)
+} GCC_PACKED;
+
+// The Type value in IKE transform value (Phase 1)
+#define IKE_TRANSFORM_VALUE_P1_CRYPTO 1 // Encryption algorithm
+#define IKE_TRANSFORM_VALUE_P1_HASH 2 // Hash algorithm
+#define IKE_TRANSFORM_VALUE_P1_AUTH_METHOD 3 // Authentication method
+#define IKE_TRANSFORM_VALUE_P1_DH_GROUP 4 // DH group number
+#define IKE_TRANSFORM_VALUE_P1_LIFE_TYPE 11 // Expiration date type
+#define IKE_TRANSFORM_VALUE_P1_LIFE_VALUE 12 // Expiration date
+#define IKE_TRANSFORM_VALUE_P1_KET_SIZE 14 // Key size
+
+// The Type value in IKE transform values (Phase 2)
+#define IKE_TRANSFORM_VALUE_P2_LIFE_TYPE 1 // Expiration date type
+#define IKE_TRANSFORM_VALUE_P2_LIFE_VALUE 2 // Expiration date
+#define IKE_TRANSFORM_VALUE_P2_DH_GROUP 3 // DH group number
+#define IKE_TRANSFORM_VALUE_P2_CAPSULE 4 // Encapsulation mode
+#define IKE_TRANSFORM_VALUE_P2_HMAC 5 // HMAC algorithm
+#define IKE_TRANSFORM_VALUE_P2_KEY_SIZE 6 // Key size
+
+// Phase 1: The encryption algorithm in the IKE transform value
+#define IKE_P1_CRYPTO_DES_CBC 1
+#define IKE_P1_CRYPTO_BLOWFISH 3
+#define IKE_P1_CRYPTO_3DES_CBC 5
+#define IKE_P1_CRYPTO_CAST_CBC 6
+#define IKE_P1_CRYPTO_AES_CBC 7
+
+// Phase 1: The hash algorithm in IKE transform value
+#define IKE_P1_HASH_MD5 1
+#define IKE_P1_HASH_SHA1 2
+
+// Phase 1: The authentication method in the IKE transform value
+#define IKE_P1_AUTH_METHOD_PRESHAREDKEY 1
+#define IKE_P1_AUTH_METHOD_RSA_SIGN 3
+
+// Phase 1: The DH group number in the IKE transform value
+#define IKE_P1_DH_GROUP_768_MODP 1
+#define IKE_P1_DH_GROUP_1024_MODP 2
+#define IKE_P1_DH_GROUP_1536_MODP 5
+
+// Phase 1: The expiration date type in IKE transform value
+#define IKE_P1_LIFE_TYPE_SECONDS 1
+#define IKE_P1_LIFE_TYPE_KILOBYTES 2
+
+// Phase 2: The HMAC algorithm in IPsec transform value
+#define IKE_P2_HMAC_MD5_96 1
+#define IKE_P2_HMAC_SHA1_96 2
+
+// Phase 2: The DH group number in the IPsec transform value
+#define IKE_P2_DH_GROUP_768_MODP 1
+#define IKE_P2_DH_GROUP_1024_MODP 2
+#define IKE_P2_DH_GROUP_1536_MODP 5
+
+// Phase 2: The encapsulation mode in IPsec transform value
+#define IKE_P2_CAPSULE_TUNNEL 1
+#define IKE_P2_CAPSULE_TRANSPORT 2
+#define IKE_P2_CAPSULE_NAT_TUNNEL_1 3
+#define IKE_P2_CAPSULE_NAT_TUNNEL_2 61443
+#define IKE_P2_CAPSULE_NAT_TRANSPORT_1 4
+#define IKE_P2_CAPSULE_NAT_TRANSPORT_2 61444
+
+// Phase 2: The expiration date type in IPsec transform value
+#define IKE_P2_LIFE_TYPE_SECONDS 1
+#define IKE_P2_LIFE_TYPE_KILOBYTES 2
+
+
+// IKE ID payload header
+struct IKE_ID_HEADER
+{
+ UCHAR IdType; // Type of ID
+ UCHAR ProtocolId; // Protocol ID
+ USHORT Port; // Port
+} GCC_PACKED;
+
+// Type of ID in the IKE ID payload header
+#define IKE_ID_IPV4_ADDR 1 // IPv4 address (32 bit)
+#define IKE_ID_FQDN 2 // FQDN
+#define IKE_ID_USER_FQDN 3 // User FQDN
+#define IKE_ID_IPV4_ADDR_SUBNET 4 // IPv4 + subnet (64 bit)
+#define IKE_ID_IPV6_ADDR 5 // IPv6 address (128 bit)
+#define IKE_ID_IPV6_ADDR_SUBNET 6 // IPv6 + subnet (256 bit)
+#define IKE_ID_DER_ASN1_DN 9 // X.500 Distinguished Name
+#define IKE_ID_DER_ASN1_GN 10 // X.500 General Name
+#define IKE_ID_KEY_ID 11 // Key
+
+// The protocol ID in the IKE ID payload
+#define IKE_ID_PROTOCOL_UDP IP_PROTO_UDP // UDP
+
+// IKE certificate payload header
+struct IKE_CERT_HEADER
+{
+ UCHAR CertType; // Certificate Type
+} GCC_PACKED;
+
+// The certificate type in IKE certificate payload header
+#define IKE_CERT_TYPE_X509 4 // X.509 certificate (for digital signature)
+
+// IKE certificate payload header
+struct IKE_CERT_REQUEST_HEADER
+{
+ UCHAR CertType; // Certificate Type
+} GCC_PACKED;
+
+// IKE notification payload header
+struct IKE_NOTICE_HEADER
+{
+ UINT DoI; // DOI value
+ UCHAR ProtocolId; // Protocol ID
+ // Same to the protocol ID in the IKE proposal payload header
+ UCHAR SpiSize; // SPI size
+ USHORT MessageType; // Message type
+} GCC_PACKED;
+
+// IKE Deletion payload header
+struct IKE_DELETE_HEADER
+{
+ UINT DoI; // DOI value
+ UCHAR ProtocolId; // Protocol ID
+ // Same to the protocol ID in the IKE proposal payload header
+ UCHAR SpiSize; // SPI size
+ USHORT NumSpis; // SPI number
+} GCC_PACKED;
+
+// IKE NAT-OA payload header
+struct IKE_NAT_OA_HEADER
+{
+ UCHAR IdType; // Type of ID
+ UCHAR Reserved1;
+ USHORT Reserved2;
+} GCC_PACKED;
+
+
+#ifdef OS_WIN32
+#pragma pack(pop)
+#endif // OS_WIN32
+
+
+
+//
+// IKE internal data structure
+//
+
+// IKE packet SA payload
+struct IKE_PACKET_SA_PAYLOAD
+{
+ LIST *PayloadList; // Proposal payload list
+};
+
+// IKE proposal packet payload
+struct IKE_PACKET_PROPOSAL_PAYLOAD
+{
+ UCHAR Number; // Number
+ UCHAR ProtocolId; // Protocol ID
+ BUF *Spi; // SPI data
+
+ LIST *PayloadList; // Payload list
+};
+
+// IKE packet transform payload
+struct IKE_PACKET_TRANSFORM_PAYLOAD
+{
+ UCHAR Number; // Number
+ UCHAR TransformId; // Transform ID
+
+ LIST *ValueList; // Value list
+};
+
+// IKE packet transform value
+struct IKE_PACKET_TRANSFORM_VALUE
+{
+ UCHAR Type; // Type
+ UINT Value; // Value
+};
+
+// IKE generic data payload
+struct IKE_PACKET_DATA_PAYLOAD
+{
+ BUF *Data; // Generic data
+};
+
+// IKE packet ID payload
+struct IKE_PACKET_ID_PAYLOAD
+{
+ UCHAR Type; // Type
+ UCHAR ProtocolId; // Protocol ID
+ USHORT Port; // Port number
+ BUF *IdData; // ID data
+ char StrData[128]; // Data of the result of converting to a string
+};
+
+// IKE packet certificate payload
+struct IKE_PACKET_CERT_PAYLOAD
+{
+ UCHAR CertType; // Certificate type
+ BUF *CertData; // Certificate data
+};
+
+// IKE packet certificate request payload
+struct IKE_PACKET_CERT_REQUEST_PAYLOAD
+{
+ UCHAR CertType; // Certificate type
+ BUF *Data; // Request data
+};
+
+// IKE packet notification payload
+struct IKE_PACKET_NOTICE_PAYLOAD
+{
+ UCHAR ProtocolId; // Protocol ID
+ USHORT MessageType; // Message type
+ BUF *Spi; // SPI data
+ BUF *MessageData; // Message data
+};
+
+// IKE notification message type
+// Error
+#define IKE_NOTICE_ERROR_INVALID_COOKIE 4 // Invalid cookie
+#define IKE_NOTICE_ERROR_INVALID_EXCHANGE_TYPE 7 // Invalid exchange type
+#define IKE_NOTICE_ERROR_INVALID_SPI 11 // Invalid SPI
+#define IKE_NOTICE_ERROR_NO_PROPOSAL_CHOSEN 14 // There is nothing worth mentioning in the presented proposal
+
+// DPD
+#define IKE_NOTICE_DPD_REQUEST 36136 // R-U-THERE
+#define IKE_NOTICE_DPD_RESPONSE 36137 // R-U-THERE-ACK
+
+
+// IKE packet deletion payload
+struct IKE_PACKET_DELETE_PAYLOAD
+{
+ UCHAR ProtocolId; // Protocol ID
+ LIST *SpiList; // SPI list
+};
+
+// IKE NAT-OA payload
+struct IKE_PACKET_NAT_OA_PAYLOAD
+{
+ IP IpAddress; // IP address
+};
+
+// IKE packet payload
+struct IKE_PACKET_PAYLOAD
+{
+ UCHAR PayloadType; // Payload type
+ UCHAR Padding[3];
+ BUF *BitArray; // Bit array
+
+ union
+ {
+ IKE_PACKET_SA_PAYLOAD Sa; // SA payload
+ IKE_PACKET_PROPOSAL_PAYLOAD Proposal; // Proposal payload
+ IKE_PACKET_TRANSFORM_PAYLOAD Transform; // Transform payload
+ IKE_PACKET_DATA_PAYLOAD KeyExchange; // Key exchange payload
+ IKE_PACKET_ID_PAYLOAD Id; // ID payload
+ IKE_PACKET_CERT_PAYLOAD Cert; // Certificate payload
+ IKE_PACKET_CERT_REQUEST_PAYLOAD CertRequest; // Certificate request payload
+ IKE_PACKET_DATA_PAYLOAD Hash; // Hash payload
+ IKE_PACKET_DATA_PAYLOAD Sign; // Signature payload
+ IKE_PACKET_DATA_PAYLOAD Rand; // Random number payload
+ IKE_PACKET_NOTICE_PAYLOAD Notice; // Notification Payload
+ IKE_PACKET_DELETE_PAYLOAD Delete; // Deletion payload
+ IKE_PACKET_DATA_PAYLOAD VendorId; // Vendor ID payload
+ IKE_PACKET_NAT_OA_PAYLOAD NatOa; // NAT-OA payload
+ IKE_PACKET_DATA_PAYLOAD GeneralData; // Generic data payload
+ } Payload;
+};
+
+struct IKE_PACKET
+{
+ UINT64 InitiatorCookie; // Initiator cookie
+ UINT64 ResponderCookie; // Responder cookie
+ UCHAR ExchangeType; // Exchange type
+ bool FlagEncrypted; // Encryption flag
+ bool FlagCommit; // Commit flag
+ bool FlagAuthOnly; // Flag only authentication
+ UINT MessageId; // Message ID
+ LIST *PayloadList; // Payload list
+ BUF *DecryptedPayload; // Decrypted payload
+ UINT MessageSize; // Original size
+};
+
+// IKE P1 key set
+struct IKE_P1_KEYSET
+{
+ BUF *SKEYID_d; // IPsec SA key
+ BUF *SKEYID_a; // IKE SA authentication key
+ BUF *SKEYID_e; // IKE SA encryption key
+};
+
+// Number and name of the encryption algorithm for IKE
+#define IKE_CRYPTO_DES_ID 0
+#define IKE_CRYPTO_DES_STRING "DES-CBC"
+
+#define IKE_CRYPTO_3DES_ID 1
+#define IKE_CRYPTO_3DES_STRING "3DES-CBC"
+
+#define IKE_CRYPTO_AES_ID 2
+#define IKE_CRYPTO_AES_STRING "AES-CBC"
+
+#define IKE_CRYPTO_BLOWFISH_ID 3
+#define IKE_CRYPTO_BLOWFISH_STRING "Blowfish-CBC"
+
+#define IKE_CRYPTO_CAST_ID 4
+#define IKE_CRYPTO_CAST_STRING "CAST-128-CBC"
+
+// Number and name of the IKE hash algorithm
+#define IKE_HASH_MD5_ID 0
+#define IKE_HASH_MD5_STRING "MD5"
+
+#define IKE_HASH_SHA1_ID 1
+#define IKE_HASH_SHA1_STRING "SHA-1"
+
+// Number and name of DH algorithm for IKE
+#define IKE_DH_1_ID 0
+#define IKE_DH_1_STRING "MODP 768 (Group 1)"
+
+#define IKE_DH_2_ID 1
+#define IKE_DH_2_STRING "MODP 1024 (Group 2)"
+
+#define IKE_DH_5_ID 2
+#define IKE_DH_5_STRING "MODP 1536 (Group 5)"
+
+
+// Encryption algorithm for IKE
+struct IKE_CRYPTO
+{
+ UINT CryptoId; // ID
+ char *Name; // Name
+ UINT KeySizes[16]; // Key size candidate
+ UINT BlockSize; // Block size
+ bool VariableKeySize; // Whether the key size is variable
+};
+
+// IKE encryption key
+struct IKE_CRYPTO_KEY
+{
+ IKE_CRYPTO *Crypto;
+ void *Data; // Key data
+ UINT Size; // Key size
+
+ DES_KEY_VALUE *DesKey1, *DesKey2, *DesKey3; // DES key
+ AES_KEY_VALUE *AesKey; // AES key
+};
+
+// IKE hash algorithm
+struct IKE_HASH
+{
+ UINT HashId; // ID
+ char *Name; // Name
+ UINT HashSize; // Output size
+};
+
+// DH algorithm for IKE
+struct IKE_DH
+{
+ UINT DhId; // ID
+ char *Name; // Name
+ UINT KeySize; // Key size
+};
+
+#define MAX_IKE_ENGINE_ELEMENTS 16
+
+// Encryption engine for IKE
+struct IKE_ENGINE
+{
+ IKE_CRYPTO *IkeCryptos[MAX_IKE_ENGINE_ELEMENTS]; // Encryption algorithm list that is used in the IKE
+ IKE_HASH *IkeHashes[MAX_IKE_ENGINE_ELEMENTS]; // Hash algorithm list that is used in the IKE
+ IKE_DH *IkeDhs[MAX_IKE_ENGINE_ELEMENTS]; // DH algorithm list that is used in the IKE
+
+ IKE_CRYPTO *EspCryptos[MAX_IKE_ENGINE_ELEMENTS]; // Encryption algorithm list that is used by ESP
+ IKE_HASH *EspHashes[MAX_IKE_ENGINE_ELEMENTS]; // Hash algorithm list that is used by ESP
+ IKE_DH *EspDhs[MAX_IKE_ENGINE_ELEMENTS]; // DH algorithm list that is used by ESP
+
+ LIST *CryptosList;
+ LIST *HashesList;
+ LIST *DhsList;
+};
+
+// IKE encryption parameters
+struct IKE_CRYPTO_PARAM
+{
+ IKE_CRYPTO_KEY *Key; // Key
+ UCHAR Iv[IKE_MAX_BLOCK_SIZE]; // IV
+ UCHAR NextIv[IKE_MAX_BLOCK_SIZE]; // IV to be used next
+};
+
+
+// Function prototype
+IKE_PACKET *IkeParseHeader(void *data, UINT size, IKE_CRYPTO_PARAM *cparam);
+IKE_PACKET *IkeParse(void *data, UINT size, IKE_CRYPTO_PARAM *cparam);
+IKE_PACKET *IkeParseEx(void *data, UINT size, IKE_CRYPTO_PARAM *cparam, bool header_only);
+void IkeFree(IKE_PACKET *p);
+IKE_PACKET *IkeNew(UINT64 init_cookie, UINT64 resp_cookie, UCHAR exchange_type,
+ bool encrypted, bool commit, bool auth_only, UINT msg_id,
+ LIST *payload_list);
+
+void IkeDebugPrintPayloads(LIST *o, UINT depth);
+void IkeDebugUdpSendRawPacket(IKE_PACKET *p);
+
+BUF *IkeEncrypt(void *data, UINT size, IKE_CRYPTO_PARAM *cparam);
+BUF *IkeEncryptWithPadding(void *data, UINT size, IKE_CRYPTO_PARAM *cparam);
+BUF *IkeDecrypt(void *data, UINT size, IKE_CRYPTO_PARAM *cparam);
+
+LIST *IkeParsePayloadList(void *data, UINT size, UCHAR first_payload);
+LIST *IkeParsePayloadListEx(void *data, UINT size, UCHAR first_payload, UINT *total_read_size);
+void IkeFreePayloadList(LIST *o);
+UINT IkeGetPayloadNum(LIST *o, UINT payload_type);
+IKE_PACKET_PAYLOAD *IkeGetPayload(LIST *o, UINT payload_type, UINT index);
+
+IKE_PACKET_PAYLOAD *IkeParsePayload(UINT payload_type, BUF *b);
+void IkeFreePayload(IKE_PACKET_PAYLOAD *p);
+bool IkeParseDataPayload(IKE_PACKET_DATA_PAYLOAD *t, BUF *b);
+void IkeFreeDataPayload(IKE_PACKET_DATA_PAYLOAD *t);
+bool IkeParseSaPayload(IKE_PACKET_SA_PAYLOAD *t, BUF *b);
+void IkeFreeSaPayload(IKE_PACKET_SA_PAYLOAD *t);
+bool IkeParseProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t, BUF *b);
+void IkeFreeProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t);
+bool IkeParseTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t, BUF *b);
+void IkeFreeTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t);
+LIST *IkeParseTransformValueList(BUF *b);
+void IkeFreeTransformValueList(LIST *o);
+bool IkeParseIdPayload(IKE_PACKET_ID_PAYLOAD *t, BUF *b);
+void IkeFreeIdPayload(IKE_PACKET_ID_PAYLOAD *t);
+bool IkeParseCertPayload(IKE_PACKET_CERT_PAYLOAD *t, BUF *b);
+void IkeFreeCertPayload(IKE_PACKET_CERT_PAYLOAD *t);
+bool IkeParseCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t, BUF *b);
+void IkeFreeCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t);
+bool IkeParseNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t, BUF *b);
+void IkeFreeNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t);
+bool IkeParseDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t, BUF *b);
+void IkeFreeDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t);
+bool IkeParseNatOaPayload(IKE_PACKET_NAT_OA_PAYLOAD *t, BUF *b);
+
+
+bool IkeCompareHash(IKE_PACKET_PAYLOAD *hash_payload, void *hash_data, UINT hash_size);
+
+IKE_PACKET_PAYLOAD *IkeNewPayload(UINT payload_type);
+IKE_PACKET_PAYLOAD *IkeNewDataPayload(UCHAR payload_type, void *data, UINT size);
+IKE_PACKET_PAYLOAD *IkeNewNatOaPayload(UCHAR payload_type, IP *ip);
+IKE_PACKET_PAYLOAD *IkeNewSaPayload(LIST *payload_list);
+IKE_PACKET_PAYLOAD *IkeNewProposalPayload(UCHAR number, UCHAR protocol_id, void *spi, UINT spi_size, LIST *payload_list);
+IKE_PACKET_PAYLOAD *IkeNewTransformPayload(UCHAR number, UCHAR transform_id, LIST *value_list);
+IKE_PACKET_TRANSFORM_VALUE *IkeNewTransformValue(UCHAR type, UINT value);
+IKE_PACKET_PAYLOAD *IkeNewIdPayload(UCHAR id_type, UCHAR protocol_id, USHORT port, void *id_data, UINT id_size);
+IKE_PACKET_PAYLOAD *IkeNewCertPayload(UCHAR cert_type, void *cert_data, UINT cert_size);
+IKE_PACKET_PAYLOAD *IkeNewCertRequestPayload(UCHAR cert_type, void *data, UINT size);
+IKE_PACKET_PAYLOAD *IkeNewNoticePayload(UCHAR protocol_id, USHORT message_type,
+ void *spi, UINT spi_size,
+ void *message, UINT message_size);
+IKE_PACKET_PAYLOAD *IkeNewDeletePayload(UCHAR protocol_id, LIST *spi_list);
+
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidCookiePayload(UINT64 init_cookie, UINT64 resp_cookie);
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidExchangeTypePayload(UINT64 init_cookie, UINT64 resp_cookie, UCHAR exchange_type);
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorInvalidSpiPayload(UINT spi);
+IKE_PACKET_PAYLOAD *IkeNewNoticeErrorNoProposalChosenPayload(bool quick_mode, UINT64 init_cookie, UINT64 resp_cookie);
+IKE_PACKET_PAYLOAD *IkeNewNoticeDpdPayload(bool ack, UINT64 init_cookie, UINT64 resp_cookie, UINT seq_no);
+
+UCHAR IkeGetFirstPayloadType(LIST *o);
+BUF *IkeBuild(IKE_PACKET *p, IKE_CRYPTO_PARAM *cparam);
+BUF *IkeBuildEx(IKE_PACKET *p, IKE_CRYPTO_PARAM *cparam, bool use_original_decrypted);
+BUF *IkeBuildPayloadList(LIST *o);
+BUF *IkeBuildPayload(IKE_PACKET_PAYLOAD *p);
+BUF *IkeBuildDataPayload(IKE_PACKET_DATA_PAYLOAD *t);
+BUF *IkeBuildSaPayload(IKE_PACKET_SA_PAYLOAD *t);
+BUF *IkeBuildProposalPayload(IKE_PACKET_PROPOSAL_PAYLOAD *t);
+BUF *IkeBuildTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t);
+BUF *IkeBuildTransformValue(IKE_PACKET_TRANSFORM_VALUE *v);
+BUF *IkeBuildTransformValueList(LIST *o);
+BUF *IkeBuildIdPayload(IKE_PACKET_ID_PAYLOAD *t);
+BUF *IkeBuildCertPayload(IKE_PACKET_CERT_PAYLOAD *t);
+BUF *IkeBuildCertRequestPayload(IKE_PACKET_CERT_REQUEST_PAYLOAD *t);
+BUF *IkeBuildNoticePayload(IKE_PACKET_NOTICE_PAYLOAD *t);
+BUF *IkeBuildDeletePayload(IKE_PACKET_DELETE_PAYLOAD *t);
+
+BUF *IkeBuildTransformPayload(IKE_PACKET_TRANSFORM_PAYLOAD *t);
+UINT IkeGetTransformValue(IKE_PACKET_TRANSFORM_PAYLOAD *t, UINT type, UINT index);
+UINT IkeGetTransformValueNum(IKE_PACKET_TRANSFORM_PAYLOAD *t, UINT type);
+
+UCHAR IkeStrToPhase1CryptId(char *name);
+UCHAR IkeStrToPhase1HashId(char *name);
+UCHAR IkeStrToPhase2CryptId(char *name);
+UCHAR IkeStrToPhase2HashId(char *name);
+BUF *IkeStrToPassword(char *str);
+UINT IkePhase1CryptIdToKeySize(UCHAR id);
+UINT IkePhase2CryptIdToKeySize(UCHAR id);
+
+UINT IkeNewSpi();
+
+IKE_ENGINE *NewIkeEngine();
+IKE_CRYPTO *NewIkeCrypto(IKE_ENGINE *e, UINT crypto_id, char *name, UINT *key_sizes, UINT num_key_sizes, UINT block_size);
+IKE_HASH *NewIkeHash(IKE_ENGINE *e, UINT hash_id, char *name, UINT size);
+IKE_DH *NewIkeDh(IKE_ENGINE *e, UINT dh_id, char *name, UINT key_size);
+void FreeIkeEngine(IKE_ENGINE *e);
+void FreeIkeCrypto(IKE_CRYPTO *c);
+void FreeIkeHash(IKE_HASH *h);
+void FreeIkeDh(IKE_DH *d);
+IKE_CRYPTO *GetIkeCrypto(IKE_ENGINE *e, bool for_esp, UINT i);
+IKE_HASH *GetIkeHash(IKE_ENGINE *e, bool for_esp, UINT i);
+IKE_DH *GetIkeDh(IKE_ENGINE *e, bool for_esp, UINT i);
+
+void IkeHash(IKE_HASH *h, void *dst, void *src, UINT size);
+void IkeHMac(IKE_HASH *h, void *dst, void *key, UINT key_size, void *data, UINT data_size);
+void IkeHMacBuf(IKE_HASH *h, void *dst, BUF *key, BUF *data);
+
+IKE_CRYPTO_KEY *IkeNewKey(IKE_CRYPTO *c, void *data, UINT size);
+bool IkeCheckKeySize(IKE_CRYPTO *c, UINT size);
+void IkeFreeKey(IKE_CRYPTO_KEY *k);
+void IkeCryptoEncrypt(IKE_CRYPTO_KEY *k, void *dst, void *src, UINT size, void *ivec);
+void IkeCryptoDecrypt(IKE_CRYPTO_KEY *k, void *dst, void *src, UINT size, void *ivec);
+
+DH_CTX *IkeDhNewCtx(IKE_DH *d);
+void IkeDhFreeCtx(DH_CTX *dh);
+
+
+#endif // IPSEC_PACKET_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_L2TP.c b/src/Cedar/IPsec_L2TP.c
new file mode 100644
index 00000000..6a4ecf6a
--- /dev/null
+++ b/src/Cedar/IPsec_L2TP.c
@@ -0,0 +1,2498 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_L2TP.c
+// L2TP protocol stack
+
+#include "CedarPch.h"
+
+// Release the L2TP AVP value
+void FreeL2TPAVP(L2TP_AVP *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (a->Data != NULL)
+ {
+ Free(a->Data);
+ }
+
+ Free(a);
+}
+
+// Release the L2TP packet
+void FreeL2TPPacket(L2TP_PACKET *p)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->AvpList != NULL)
+ {
+ for (i = 0;i < LIST_NUM(p->AvpList);i++)
+ {
+ L2TP_AVP *a = LIST_DATA(p->AvpList, i);
+
+ FreeL2TPAVP(a);
+ }
+
+ ReleaseList(p->AvpList);
+ }
+
+ if (p->Data != NULL)
+ {
+ Free(p->Data);
+ }
+
+ Free(p);
+}
+
+// Send an L2TP control packet
+void SendL2TPControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id, L2TP_PACKET *p)
+{
+ BUF *buf;
+ L2TP_QUEUE *q;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ p->IsControl = true;
+ p->TunnelId = t->TunnelId1;
+ p->SessionId = session_id;
+
+ p->Ns = t->NextNs;
+ t->NextNs++;
+
+ p->Nr = t->LastNr + 1;
+
+ buf = BuildL2TPPacketData(p);
+
+ q = ZeroMalloc(sizeof(L2TP_QUEUE));
+ q->Buf = buf;
+ q->Ns = p->Ns;
+ q->NextSendTick = l2tp->Now + (UINT64)L2TP_PACKET_RESEND_INTERVAL;
+ SendL2TPControlPacketMain(l2tp, t, q);
+
+ L2TPAddInterrupt(l2tp, q->NextSendTick);
+
+ Add(t->SendQueue, q);
+
+}
+
+// Specify the interrupt occurrence time of the next
+void L2TPAddInterrupt(L2TP_SERVER *l2tp, UINT64 next_tick)
+{
+ // Validate arguments
+ if (l2tp == NULL || next_tick == 0)
+ {
+ return;
+ }
+
+ AddInterrupt(l2tp->Interrupts, next_tick);
+}
+
+// Send a L2TP data packet
+void SendL2TPDataPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s, void *data, UINT size)
+{
+ UDPPACKET *p;
+ UCHAR *buf;
+ UINT buf_size;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || s == NULL || (size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ // Build a L2TP data packet
+ if (s->IsV3 == false)
+ {
+ // L2TP Ver 2
+ buf_size = 8 + size;
+ buf = Malloc(buf_size);
+ buf[0] = 0x40;
+ buf[1] = 0x02;
+
+ WRITE_USHORT(buf + 2, buf_size);
+ WRITE_USHORT(buf + 4, t->TunnelId1);
+ WRITE_USHORT(buf + 6, s->SessionId1);
+
+ Copy(buf + 8, data, size);
+
+ // Transmission
+ p = NewUdpPacket(&t->ServerIp, t->ServerPort, &t->ClientIp, t->ClientPort, buf, buf_size);
+ }
+ else
+ {
+ // L2TPv3
+ buf_size = 4 + size;
+ buf = Malloc(buf_size);
+
+ WRITE_UINT(buf, s->SessionId1);
+
+ Copy(buf + 4, data, size);
+
+ // Transmission
+ p = NewUdpPacket(&t->ServerIp, IPSEC_PORT_L2TPV3_VIRTUAL, &t->ClientIp, IPSEC_PORT_L2TPV3_VIRTUAL, buf, buf_size);
+ }
+
+ L2TPSendUDP(l2tp, p);
+}
+
+// L2TP packet transmission main
+void SendL2TPControlPacketMain(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_QUEUE *q)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || q == NULL)
+ {
+ return;
+ }
+
+ p = NewUdpPacket(&t->ServerIp, t->ServerPort, &t->ClientIp, t->ClientPort,
+ Clone(q->Buf->Buf, q->Buf->Size), q->Buf->Size);
+
+ // Update the received sequence number
+ WRITE_USHORT(((UCHAR *)p->Data) + (p->SrcPort == IPSEC_PORT_L2TPV3_VIRTUAL ? 14 : 10), t->LastNr + 1);
+
+ L2TPSendUDP(l2tp, p);
+}
+
+// Send a UDP packet
+void L2TPSendUDP(L2TP_SERVER *l2tp, UDPPACKET *p)
+{
+ // Validate arguments
+ if (l2tp == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Add(l2tp->SendPacketList, p);
+}
+
+// Build a L2TP packet
+BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
+{
+ BUF *ret;
+ UCHAR c;
+ USHORT us;
+ UINT ui;
+ // Validate arguments
+ if (pp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewBuf();
+
+ c = 0;
+
+ if (pp->Ver == 3)
+ {
+ if (pp->SessionId != 0)
+ {
+ // Add the Remote Session ID AVP
+ L2TP_AVP *a = GetAVPValue(pp, L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE);
+ if (a == NULL || a->DataSize != sizeof(UINT))
+ {
+ UINT ui = Endian32(pp->SessionId);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE, true, 0, &ui, sizeof(UINT)));
+
+ if (GetAVPValueEx(pp, L2TPV3_CISCO_AVP_SESSION_ID_LOCAL, L2TP_AVP_VENDOR_ID_CISCO) != NULL)
+ {
+ Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_SESSION_ID_REMOTE, true, L2TP_AVP_VENDOR_ID_CISCO, &ui, sizeof(UINT)));
+ }
+ }
+ }
+ }
+
+ if (pp->Ver == 3)
+ {
+ // Zero as Session ID
+ ui = 0;
+ WriteBuf(ret, &ui, sizeof(UINT));
+ }
+
+ // Flags
+ if (pp->IsControl)
+ {
+ c |= L2TP_HEADER_BIT_TYPE;
+ c |= L2TP_HEADER_BIT_LENGTH;
+ c |= L2TP_HEADER_BIT_SEQUENCE;
+ }
+ else
+ {
+ c |= L2TP_HEADER_BIT_OFFSET;
+ }
+
+ WriteBuf(ret, &c, 1);
+
+ // Ver
+ c = 2;
+ if (pp->Ver == 3)
+ {
+ c = 3;
+ }
+ WriteBuf(ret, &c, 1);
+
+ // Length
+ if (pp->IsControl)
+ {
+ us = 0;
+ WriteBuf(ret, &us, sizeof(USHORT));
+ }
+
+ // Tunnel ID
+ if (pp->Ver != 3)
+ {
+ us = Endian16((USHORT)pp->TunnelId);
+ WriteBuf(ret, &us, sizeof(USHORT));
+ }
+ else
+ {
+ ui = Endian32(pp->TunnelId);
+ WriteBuf(ret, &ui, sizeof(UINT));
+ }
+
+ // Session ID
+ if (pp->Ver != 3)
+ {
+ us = Endian16((USHORT)pp->SessionId);
+ WriteBuf(ret, &us, sizeof(USHORT));
+ }
+
+ if (pp->IsControl)
+ {
+ // Ns
+ us = Endian16(pp->Ns);
+ WriteBuf(ret, &us, sizeof(USHORT));
+
+ // Nr
+ us = Endian16(pp->Nr);
+ WriteBuf(ret, &us, sizeof(USHORT));
+ }
+ else
+ {
+ // Offset Size = 0
+ us = 0;
+ WriteBuf(ret, &us, sizeof(USHORT));
+ }
+
+ if (pp->IsControl)
+ {
+ // AVP
+ UINT i;
+ for (i = 0;i < LIST_NUM(pp->AvpList);i++)
+ {
+ L2TP_AVP *a = LIST_DATA(pp->AvpList, i);
+
+ // Length and Flags
+ us = Endian16(a->DataSize + 6);
+
+ if (a->Mandatory)
+ {
+ *((UCHAR *)&us) |= L2TP_AVP_BIT_MANDATORY;
+ }
+
+ WriteBuf(ret, &us, sizeof(USHORT));
+
+ // Vendor ID
+ us = Endian16(a->VendorID);
+ WriteBuf(ret, &us, sizeof(USHORT));
+
+ // Type
+ us = Endian16(a->Type);
+ WriteBuf(ret, &us, sizeof(USHORT));
+
+ // Data
+ WriteBuf(ret, a->Data, a->DataSize);
+ }
+ }
+ else
+ {
+ // Payload
+ WriteBuf(ret, pp->Data, pp->DataSize);
+ }
+
+ if (pp->IsControl)
+ {
+ // Update Length
+ WRITE_USHORT(((UCHAR *)ret->Buf) + 2 + (pp->Ver == 3 ? sizeof(UINT) : 0), (USHORT)(ret->Size - (pp->Ver == 3 ? sizeof(UINT) : 0)));
+ }
+
+ SeekBuf(ret, 0, 0);
+
+ return ret;
+}
+
+// Parse the L2TP packet
+L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
+{
+ L2TP_PACKET *ret;
+ UCHAR *buf;
+ UINT size;
+ bool is_l2tpv3 = false;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(L2TP_PACKET));
+
+ if (p->SrcPort == IPSEC_PORT_L2TPV3_VIRTUAL)
+ {
+ // It is L2TPv3
+ is_l2tpv3 = true;
+ }
+
+ buf = p->Data;
+ size = p->Size;
+
+ if (is_l2tpv3)
+ {
+ UINT session_id;
+ // In the case of L2TPv3
+ if (size < 4)
+ {
+ goto LABEL_ERROR;
+ }
+
+ session_id = READ_UINT(buf);
+
+ if (session_id != 0)
+ {
+ // L2TPv3 data packet reception
+ ret->SessionId = session_id;
+
+ buf += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ ret->Data = Clone(buf, size);
+ ret->DataSize = size;
+
+ ret->Ver = 3;
+
+ return ret;
+ }
+ else
+ {
+ // L2TPv3 control packet reception
+ buf += sizeof(UINT);
+ size -= sizeof(UINT);
+ }
+ }
+
+ // L2TP
+ if (size < 6)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (*buf & L2TP_HEADER_BIT_TYPE)
+ {
+ ret->IsControl = true;
+ }
+
+ if (*buf & L2TP_HEADER_BIT_LENGTH)
+ {
+ ret->HasLength = true;
+ }
+
+ if (*buf & L2TP_HEADER_BIT_SEQUENCE)
+ {
+ ret->HasSequence = true;
+ }
+
+ if (is_l2tpv3 == false)
+ {
+ if (*buf & L2TP_HEADER_BIT_OFFSET)
+ {
+ ret->HasOffset = true;
+ }
+
+ if (*buf & L2TP_HEADER_BIT_PRIORITY)
+ {
+ ret->IsPriority = true;
+ }
+ }
+
+ buf++;
+ size--;
+
+ ret->Ver = *buf & L2TP_HEADER_BIT_VER;
+
+ buf++;
+ size--;
+
+ if (is_l2tpv3 == false)
+ {
+ // L2TP
+ if (ret->Ver != 2)
+ {
+ goto LABEL_ERROR;
+ }
+ }
+ else
+ {
+ // L2TPv3
+ if (ret->Ver != 3)
+ {
+ goto LABEL_ERROR;
+ }
+ }
+
+ if (ret->IsControl)
+ {
+ if (ret->HasLength == false || ret->HasSequence == false)
+ {
+ goto LABEL_ERROR;
+ }
+ }
+ else
+ {
+ /*if (ret->HasSequence)
+ {
+ goto LABEL_ERROR;
+ }*/
+ }
+
+ if (ret->HasLength)
+ {
+ // Length
+ if (size < 2)
+ {
+ goto LABEL_ERROR;
+ }
+ ret->Length = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ if (size < (ret->Length - 4))
+ {
+ goto LABEL_ERROR;
+ }
+
+ size = ret->Length - 4;
+ }
+
+ // Tunnel ID, Session ID
+ if (size < 4)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (is_l2tpv3 == false)
+ {
+ // L2TP
+ ret->TunnelId = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ ret->SessionId = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+ }
+ else
+ {
+ // L2TPv3: Only tunnel ID is written in the header
+ ret->TunnelId = READ_UINT(buf);
+ buf += 4;
+ size -= 4;
+
+ // The session ID is not written in the header
+ ret->SessionId = 0;
+ }
+
+ if (ret->HasSequence)
+ {
+ // Ns, Nr
+ if (size < 4)
+ {
+ goto LABEL_ERROR;
+ }
+
+ ret->Ns = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ ret->Nr = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+ }
+
+ if (ret->HasOffset)
+ {
+ // Offset
+ if (size < 2)
+ {
+ goto LABEL_ERROR;
+ }
+
+ ret->OffsetSize = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ if (size < ret->OffsetSize)
+ {
+ goto LABEL_ERROR;
+ }
+
+ buf += ret->OffsetSize;
+ size -= ret->OffsetSize;
+ }
+
+ ret->DataSize = size;
+ ret->Data = Clone(buf, ret->DataSize);
+
+ if (ret->IsControl == false)
+ {
+ if (ret->DataSize == 0)
+ {
+ goto LABEL_ERROR;
+ }
+ }
+
+ if (ret->IsControl)
+ {
+ if (ret->DataSize == 0)
+ {
+ ret->IsZLB = true;
+ }
+ }
+
+ if (ret->IsControl)
+ {
+ ret->AvpList = NewListFast(NULL);
+
+ // Parse the AVP field
+ while (size != 0)
+ {
+ L2TP_AVP a;
+
+ Zero(&a, sizeof(a));
+
+ // Header
+ if (size < 6)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (*buf & L2TP_AVP_BIT_MANDATORY)
+ {
+ a.Mandatory = true;
+ }
+
+ if (*buf & L2TP_AVP_BIT_HIDDEN)
+ {
+ goto LABEL_ERROR;
+ }
+
+ a.Length = READ_USHORT(buf) & L2TP_AVP_LENGTH;
+
+ if (a.Length < 6)
+ {
+ goto LABEL_ERROR;
+ }
+
+ buf += 2;
+ size -= 2;
+
+ a.VendorID = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ a.Type = READ_USHORT(buf);
+ buf += 2;
+ size -= 2;
+
+ a.DataSize = a.Length - 6;
+ a.Data = Clone(buf, a.DataSize);
+
+ buf += a.DataSize;
+ size -= a.DataSize;
+
+ Add(ret->AvpList, Clone(&a, sizeof(a)));
+ }
+ }
+
+ if (ret->IsControl && ret->IsZLB == false)
+ {
+ // Get the MessageType in the case of Control packet
+ L2TP_AVP *a = GetAVPValue(ret, L2TP_AVP_TYPE_MESSAGE_TYPE);
+ if (a == NULL || a->DataSize != 2)
+ {
+ goto LABEL_ERROR;
+ }
+
+ ret->MessageType = READ_USHORT(a->Data);
+ }
+
+ if (ret->Ver == 3)
+ {
+ // Get the Remote Session ID in the case of L2TPv3
+ L2TP_AVP *a = GetAVPValue(ret, L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE);
+ if (a != NULL && a->DataSize == sizeof(UINT))
+ {
+ ret->SessionId = READ_UINT(a->Data);
+ }
+ }
+
+ return ret;
+
+LABEL_ERROR:
+ FreeL2TPPacket(ret);
+ return NULL;
+}
+
+// Get the AVP value
+L2TP_AVP *GetAVPValue(L2TP_PACKET *p, UINT type)
+{
+ return GetAVPValueEx(p, type, 0);
+}
+L2TP_AVP *GetAVPValueEx(L2TP_PACKET *p, UINT type, UINT vendor_id)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(p->AvpList);i++)
+ {
+ L2TP_AVP *a = LIST_DATA(p->AvpList, i);
+
+ if (a->Type == type && a->VendorID == vendor_id)
+ {
+ return a;
+ }
+ }
+
+ return NULL;
+}
+
+// Release the L2TP transmission queue
+void FreeL2TPQueue(L2TP_QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ FreeBuf(q->Buf);
+
+ FreeL2TPPacket(q->L2TPPacket);
+
+ Free(q);
+}
+
+// Sort function of L2TP reception queue
+int CmpL2TPQueueForRecv(void *p1, void *p2)
+{
+ L2TP_QUEUE *q1, *q2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ q1 = *(L2TP_QUEUE **)p1;
+ q2 = *(L2TP_QUEUE **)p2;
+ if (q1 == NULL || q2 == NULL)
+ {
+ return 0;
+ }
+
+ if (L2TP_SEQ_LT(q1->Ns, q2->Ns))
+ {
+ return -1;
+ }
+ else if (q1->Ns == q2->Ns)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+// Create a L2TP tunnel
+L2TP_TUNNEL *NewL2TPTunnel(L2TP_SERVER *l2tp, L2TP_PACKET *p, UDPPACKET *udp)
+{
+ L2TP_TUNNEL *t;
+ L2TP_AVP *a;
+ // Validate arguments
+ if (l2tp == NULL || p == NULL || udp == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(L2TP_TUNNEL));
+
+ if (p->Ver == 3)
+ {
+ t->IsV3 = true;
+ }
+
+ t->SessionList = NewList(NULL);
+
+ Copy(&t->ClientIp, &udp->SrcIP, sizeof(IP));
+ t->ClientPort = udp->SrcPort;
+
+ Copy(&t->ServerIp, &udp->DstIP, sizeof(IP));
+ t->ServerPort = udp->DestPort;
+
+ // Hostname
+ a = GetAVPValue(p, L2TP_AVP_TYPE_HOST_NAME);
+ if (a != NULL && a->DataSize >= 1 && a->DataSize < sizeof(t->HostName))
+ {
+ Copy(t->HostName, a->Data, a->DataSize);
+ }
+ else
+ {
+ IPToStr(t->HostName, sizeof(t->HostName), &t->ClientIp);
+ }
+
+ // Vendor Name
+ a = GetAVPValue(p, L2TP_AVP_TYPE_VENDOR_NAME);
+ if (a != NULL && a->DataSize >= 1 && a->DataSize < sizeof(t->VendorName))
+ {
+ Copy(t->VendorName, a->Data, a->DataSize);
+ }
+
+ // Assigned Tunnel ID
+ a = GetAVPValue(p, (p->Ver == 3 ? L2TP_AVP_TYPE_V3_TUNNEL_ID : L2TP_AVP_TYPE_ASSIGNED_TUNNEL));
+ if (a == NULL || a->DataSize != (t->IsV3 ? sizeof(UINT) : sizeof(USHORT)))
+ {
+ goto LABEL_ERROR;
+ }
+
+ t->TunnelId1 = (t->IsV3 ? READ_UINT(a->Data) : READ_USHORT(a->Data));
+ t->TunnelId2 = GenerateNewTunnelIdEx(l2tp, &t->ClientIp, t->IsV3);
+
+ if (t->TunnelId2 == 0)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (p->Ver == 3)
+ {
+ // Identify whether it's Cisco
+ a = GetAVPValueEx(p, L2TPV3_CISCO_AVP_TUNNEL_ID, L2TP_AVP_VENDOR_ID_CISCO);
+ if (a != NULL)
+ {
+ t->IsCiscoV3 = true;
+ }
+ }
+
+ // Transmission queue
+ t->SendQueue = NewList(NULL);
+
+ // Reception queue
+ t->RecvQueue = NewList(CmpL2TPQueueForRecv);
+
+ t->LastRecvTick = l2tp->Now;
+ t->LastHelloSent = l2tp->Now;
+
+ return t;
+
+LABEL_ERROR:
+ FreeL2TPTunnel(t);
+ return NULL;
+}
+
+// Search a tunnel
+L2TP_TUNNEL *GetTunnelFromId(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id, bool is_v3)
+{
+ UINT i;
+ // Validate arguments
+ if (l2tp == NULL || client_ip == 0 || tunnel_id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ if (t->TunnelId2 == tunnel_id && CmpIpAddr(&t->ClientIp, client_ip) == 0)
+ {
+ if (EQUAL_BOOL(t->IsV3, is_v3))
+ {
+ return t;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Search the tunnel by the tunnel ID that is assigned by the client
+L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClient(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id)
+{
+ UINT i;
+ // Validate arguments
+ if (l2tp == NULL || client_ip == 0 || tunnel_id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ if (t->TunnelId1 == tunnel_id && CmpIpAddr(&t->ClientIp, client_ip) == 0)
+ {
+ return t;
+ }
+ }
+
+ return NULL;
+}
+
+// Create a new tunnel ID
+UINT GenerateNewTunnelId(L2TP_SERVER *l2tp, IP *client_ip)
+{
+ return GenerateNewTunnelIdEx(l2tp, client_ip, false);
+}
+UINT GenerateNewTunnelIdEx(L2TP_SERVER *l2tp, IP *client_ip, bool is_32bit)
+{
+ UINT id;
+ UINT max_number = 0xffff;
+ // Validate arguments
+ if (l2tp == NULL || client_ip == NULL)
+ {
+ return 0;
+ }
+
+ if (is_32bit)
+ {
+ max_number = 0xfffffffe;
+ }
+
+ for (id = 1;id <= max_number;id++)
+ {
+ if (GetTunnelFromId(l2tp, client_ip, id, is_32bit) == NULL)
+ {
+ return id;
+ }
+ }
+
+ return 0;
+}
+
+// Release the L2TP tunnel
+void FreeL2TPTunnel(L2TP_TUNNEL *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->SessionList);i++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, i);
+
+ FreeL2TPSession(s);
+ }
+
+ ReleaseList(t->SessionList);
+
+ for (i = 0;i < LIST_NUM(t->SendQueue);i++)
+ {
+ L2TP_QUEUE *q = LIST_DATA(t->SendQueue, i);
+
+ FreeL2TPQueue(q);
+ }
+
+ ReleaseList(t->SendQueue);
+
+ for (i = 0;i < LIST_NUM(t->RecvQueue);i++)
+ {
+ L2TP_QUEUE *q = LIST_DATA(t->RecvQueue, i);
+
+ FreeL2TPQueue(q);
+ }
+
+ ReleaseList(t->RecvQueue);
+
+ Free(t);
+}
+
+// Generate a new L2TP control packet
+L2TP_PACKET *NewL2TPControlPacket(UINT message_type, bool is_v3)
+{
+ L2TP_PACKET *p = ZeroMalloc(sizeof(L2TP_PACKET));
+
+ p->IsControl = true;
+ p->HasLength = true;
+ p->HasSequence = true;
+ p->Ver = (is_v3 ? 3 : 2);
+ p->MessageType = message_type;
+
+ p->AvpList = NewListFast(NULL);
+
+ if (message_type != 0)
+ {
+ L2TP_AVP *a;
+ USHORT us;
+
+ a = ZeroMalloc(sizeof(L2TP_AVP));
+
+ a->Type = L2TP_AVP_TYPE_MESSAGE_TYPE;
+ a->Mandatory = true;
+
+ us = Endian16(message_type);
+ a->Data = Clone(&us, sizeof(USHORT));
+ a->DataSize = sizeof(USHORT);
+
+ Add(p->AvpList, a);
+ }
+
+ return p;
+}
+
+// Create a new AVP value
+L2TP_AVP *NewAVP(USHORT type, bool mandatory, USHORT vendor_id, void *data, UINT data_size)
+{
+ L2TP_AVP *a;
+ // Validate arguments
+ if (data_size != 0 && data == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(L2TP_AVP));
+
+ a->Type = type;
+ a->Mandatory = mandatory;
+ a->VendorID = vendor_id;
+ a->Data = Clone(data, data_size);
+ a->DataSize = data_size;
+
+ return a;
+}
+
+// Process a received L2TP packet
+void L2TPProcessRecvControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_PACKET *p)
+{
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (p->SessionId == 0)
+ {
+ if (p->MessageType == L2TP_MESSAGE_TYPE_SCCCN && l2tp->Halt == false)
+ {
+ // Tunnel establishment completed
+ if (t->Established == false)
+ {
+ if (t->Disconnecting == false)
+ {
+ t->Established = true;
+ t->LastHelloSent = l2tp->Now;
+ }
+ }
+ }
+
+ if (t->Established)
+ {
+ if (p->MessageType == L2TP_MESSAGE_TYPE_ICRQ && t->WantToDisconnect == false && l2tp->Halt == false)
+ {
+ // Request to establish a new session arrives
+ L2TP_AVP *a = GetAVPValue(p,
+ (t->IsV3 ? L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL : L2TP_AVP_TYPE_ASSIGNED_SESSION));
+ if (a != NULL && a->DataSize == (t->IsV3 ? sizeof(UINT) : sizeof(USHORT)) && IsZero(a->Data, (t->IsV3 ? sizeof(UINT) : sizeof(USHORT))) == false)
+ {
+ UINT session_id = (t->IsV3 ? READ_UINT(a->Data) : READ_USHORT(a->Data));
+
+ // Check whether there is other same session ID
+ if (GetSessionFromIdAssignedByClient(t, session_id) == NULL)
+ {
+ // Create a session
+ L2TP_SESSION *s = NewL2TPSession(l2tp, t, session_id);
+
+ if (s != NULL)
+ {
+ L2TP_PACKET *pp;
+ USHORT us;
+ UINT ui;
+
+ // Get the PseudowireType
+ if (t->IsV3)
+ {
+ s->PseudowireType = L2TPV3_PW_TYPE_ETHERNET;
+
+ a = GetAVPValue(p, L2TP_AVP_TYPE_V3_PW_TYPE);
+
+ if (a != NULL && a->DataSize == sizeof(USHORT))
+ {
+ ui = READ_USHORT(a->Data);
+
+ s->PseudowireType = ui;
+ }
+ }
+
+ Add(t->SessionList, s);
+ Debug("L2TP New Session: ID = %u/%u on Tunnel %u/%u\n", s->SessionId1, s->SessionId2,
+ t->TunnelId1, t->TunnelId2);
+
+ // Respond the session creation completion notice
+ pp = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_ICRP, s->IsV3);
+
+ // Assigned Session AVP
+ if (s->IsV3 == false)
+ {
+ us = Endian16(s->SessionId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_ASSIGNED_SESSION, true, 0, &us, sizeof(USHORT)));
+ }
+ else
+ {
+ ui = Endian32(s->SessionId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL, true, 0, &ui, sizeof(UINT)));
+
+ if (s->IsCiscoV3)
+ {
+ Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_SESSION_ID_LOCAL, true, L2TP_AVP_VENDOR_ID_CISCO, &ui, sizeof(UINT)));
+ }
+ }
+
+ if (s->IsV3)
+ {
+ // Pseudowire AVP
+ us = Endian16(s->PseudowireType);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_PW_TYPE, true, 0, &us, sizeof(USHORT)));
+
+ if (s->IsCiscoV3)
+ {
+ Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_PW_TYPE, true, L2TP_AVP_VENDOR_ID_CISCO, &us, sizeof(USHORT)));
+ }
+ }
+
+ SendL2TPControlPacket(l2tp, t, session_id, pp);
+
+ FreeL2TPPacket(pp);
+ }
+ }
+ }
+ }
+ else if (p->MessageType == L2TP_MESSAGE_TYPE_STOPCCN)
+ {
+ // Tunnel disconnect request arrives
+ L2TP_AVP *a = GetAVPValue(p, (t->IsV3 ? L2TP_AVP_TYPE_V3_TUNNEL_ID : L2TP_AVP_TYPE_ASSIGNED_TUNNEL));
+ if (a != NULL && a->DataSize == (t->IsV3 ? sizeof(UINT) : sizeof(USHORT)))
+ {
+ UINT ui = (t->IsV3 ? READ_UINT(a->Data) : READ_USHORT(a->Data));
+
+ if (ui == t->TunnelId1)
+ {
+ // Disconnect the tunnel
+ DisconnectL2TPTunnel(t);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Search a session
+ L2TP_SESSION *s = GetSessionFromId(t, p->SessionId);
+
+ if (s != NULL)
+ {
+ if (s->Established == false)
+ {
+ if (p->MessageType == L2TP_MESSAGE_TYPE_ICCN)
+ {
+ // Session establishment completed
+ if (s->Disconnecting == false)
+ {
+ s->Established = true;
+ }
+ }
+ }
+ else
+ {
+ if (p->MessageType == L2TP_MESSAGE_TYPE_CDN)
+ {
+ // Received a session disconnection request
+ L2TP_AVP *a = GetAVPValue(p,
+ (t->IsV3 ? L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL : L2TP_AVP_TYPE_ASSIGNED_SESSION));
+ if (a != NULL && a->DataSize == (t->IsV3 ? sizeof(UINT) : sizeof(USHORT)))
+ {
+ UINT ui = (t->IsV3 ? READ_UINT(a->Data) : READ_USHORT(a->Data));
+
+ if (ui == s->SessionId1)
+ {
+ // Disconnect the session
+ DisconnectL2TPSession(t, s);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Debug("Session ID %u not found in Tunnel ID %u/%u\n", p->SessionId, t->TunnelId1, t->TunnelId2);
+ }
+ }
+}
+
+// Disconnect the L2TP tunnel
+void DisconnectL2TPTunnel(L2TP_TUNNEL *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (/*t->Established && */t->Disconnecting == false && t->WantToDisconnect == false)
+ {
+ UINT i;
+
+ Debug("Trying to Disconnect Tunnel ID %u/%u\n", t->TunnelId1, t->TunnelId2);
+ t->WantToDisconnect = true;
+
+ // Disconnect all sessions within the tunnel
+ for (i = 0;i < LIST_NUM(t->SessionList);i++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, i);
+
+ DisconnectL2TPSession(t, s);
+ }
+ }
+}
+
+// Disconnect the L2TP session
+void DisconnectL2TPSession(L2TP_TUNNEL *t, L2TP_SESSION *s)
+{
+ // Validate arguments
+ if (t == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->Established && s->Disconnecting == false && s->WantToDisconnect == false)
+ {
+ Debug("Trying to Disconnect Session ID %u/%u on Tunnel %u/%u\n", s->SessionId1, s->SessionId2,
+ t->TunnelId1, t->TunnelId2);
+ s->WantToDisconnect = true;
+ }
+}
+
+// Create a new session
+L2TP_SESSION *NewL2TPSession(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id_by_client)
+{
+ L2TP_SESSION *s;
+ UINT session_id_by_server;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || session_id_by_client == 0)
+ {
+ return NULL;
+ }
+
+ if (t->IsV3 == false)
+ {
+ session_id_by_server = GenerateNewSessionIdEx(t, t->IsV3);
+ }
+ else
+ {
+ session_id_by_server = GenerateNewSessionIdForL2TPv3(l2tp);
+ }
+ if (session_id_by_server == 0)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(L2TP_SESSION));
+
+ s->SessionId1 = session_id_by_client;
+ s->SessionId2 = session_id_by_server;
+
+ s->IsV3 = t->IsV3;
+ s->IsCiscoV3 = t->IsCiscoV3;
+
+ s->Tunnel = t;
+
+ return s;
+}
+
+// Retrieve a session from L2TP session ID
+L2TP_SESSION *SearchL2TPSessionById(L2TP_SERVER *l2tp, bool is_v3, UINT id)
+{
+ UINT i, j;
+ // Validate arguments
+ if (l2tp == NULL || id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ for (j = 0;j < LIST_NUM(t->SessionList);j++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, j);
+
+ if (s->SessionId2 == id)
+ {
+ if (EQUAL_BOOL(s->IsV3, is_v3))
+ {
+ return s;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Create a new session ID
+UINT GenerateNewSessionId(L2TP_TUNNEL *t)
+{
+ return GenerateNewSessionIdEx(t, false);
+}
+UINT GenerateNewSessionIdEx(L2TP_TUNNEL *t, bool is_32bit)
+{
+ UINT i;
+ UINT max_number = 0xffff;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ if (is_32bit)
+ {
+ max_number = 0xfffffffe;
+ }
+
+ for (i = 1;i <= max_number;i++)
+ {
+ if (GetSessionFromId(t, i) == NULL)
+ {
+ return i;
+ }
+ }
+
+ return 0;
+}
+UINT GenerateNewSessionIdForL2TPv3(L2TP_SERVER *l2tp)
+{
+ // Validate arguments
+ if (l2tp == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ UINT id = Rand32();
+
+ if (id == 0 || id == 0xffffffff)
+ {
+ continue;
+ }
+
+ if (SearchL2TPSessionById(l2tp, true, id) == false)
+ {
+ return id;
+ }
+ }
+}
+
+// Release the session
+void FreeL2TPSession(L2TP_SESSION *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Free(s);
+}
+
+// Search a session from the session ID
+L2TP_SESSION *GetSessionFromId(L2TP_TUNNEL *t, UINT session_id)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || session_id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(t->SessionList);i++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, i);
+
+ if (s->SessionId2 == session_id)
+ {
+ return s;
+ }
+ }
+
+ return NULL;
+}
+
+// Search a session from the session ID (Search by ID assigned from the client side)
+L2TP_SESSION *GetSessionFromIdAssignedByClient(L2TP_TUNNEL *t, UINT session_id)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || session_id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(t->SessionList);i++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, i);
+
+ if (s->SessionId1 == session_id)
+ {
+ return s;
+ }
+ }
+
+ return NULL;
+}
+
+// Performs processing L2TP received packets.
+void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
+{
+ L2TP_PACKET *pp;
+ bool no_free = false;
+ // Validate arguments
+ if (l2tp == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Parse a packet.
+ pp = ParseL2TPPacket(p);
+ if (pp == NULL)
+ {
+ return;
+ }
+
+ if (pp->MessageType == L2TP_MESSAGE_TYPE_SCCRQ && pp->SessionId == 0 && pp->TunnelId == 0 &&
+ pp->Nr == 0 && pp->Ns == 0 && l2tp->Halt == false)
+ {
+ {
+ L2TP_AVP *a = GetAVPValue(pp, (pp->Ver == 3 ? L2TP_AVP_TYPE_V3_TUNNEL_ID : L2TP_AVP_TYPE_ASSIGNED_TUNNEL));
+ if (a != NULL && a->DataSize == (pp->Ver == 3 ? sizeof(UINT) : sizeof(USHORT)))
+ {
+ UINT client_assigned_id = (pp->Ver == 3 ? READ_UINT(a->Data) : READ_USHORT(a->Data));
+ if (GetTunnelFromIdOfAssignedByClient(l2tp, &p->SrcIP, client_assigned_id) == NULL)
+ {
+ char ipstr[MAX_SIZE];
+ L2TP_PACKET *pp2;
+ UCHAR protocol_version[2];
+ UCHAR caps_data[4];
+ USHORT us;
+ char hostname[MAX_SIZE];
+
+ // Begin Tunneling
+ L2TP_TUNNEL *t = NewL2TPTunnel(l2tp, pp, p);
+
+ if (t != NULL)
+ {
+ IPToStr(ipstr, sizeof(ipstr), &t->ClientIp);
+ Debug("L2TP New Tunnel From %s (%s, %s): New Tunnel ID = %u/%u\n", ipstr, t->HostName, t->VendorName,
+ t->TunnelId1, t->TunnelId2);
+
+ // Add the tunnel to the list
+ Add(l2tp->TunnelList, t);
+
+ // Respond with SCCEP to SCCRQ
+ pp2 = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_SCCRP, t->IsV3);
+
+ // Protocol Version
+ protocol_version[0] = 1;
+ protocol_version[1] = 0;
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_PROTOCOL_VERSION, true, 0, protocol_version, sizeof(protocol_version)));
+
+ // Framing Capabilities
+ Zero(caps_data, sizeof(caps_data));
+ if (t->IsV3 == false)
+ {
+ caps_data[3] = 3;
+ }
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_FRAME_CAP, false, 0, caps_data, sizeof(caps_data)));
+
+ if (t->IsV3 == false)
+ {
+ // Bearer Capabilities
+ Zero(caps_data, sizeof(caps_data));
+ caps_data[3] = 3;
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_BEARER_CAP, false, 0, caps_data, sizeof(caps_data)));
+ }
+
+ // Host Name
+ GetMachineHostName(hostname, sizeof(hostname));
+ if (IsEmptyStr(hostname))
+ {
+ StrCpy(hostname, sizeof(hostname), "vpn");
+ }
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_HOST_NAME, true, 0, hostname, StrLen(hostname)));
+
+ // Vendor Name
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_VENDOR_NAME, false, 0, L2TP_VENDOR_NAME, StrLen(L2TP_VENDOR_NAME)));
+
+ // Assigned Tunnel ID
+ if (t->IsV3 == false)
+ {
+ us = Endian16(t->TunnelId2);
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_ASSIGNED_TUNNEL, true, 0, &us, sizeof(USHORT)));
+ }
+ else
+ {
+ UINT ui = Endian32(t->TunnelId2);
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_V3_TUNNEL_ID, true, 0, &ui, sizeof(UINT)));
+
+ if (t->IsCiscoV3)
+ {
+ Add(pp2->AvpList, NewAVP(L2TPV3_CISCO_AVP_TUNNEL_ID, true, L2TP_AVP_VENDOR_ID_CISCO, &ui, sizeof(UINT)));
+ }
+ }
+
+ // Pseudowire Capabilities List
+ if (t->IsV3)
+ {
+ // Only Ethernet
+ USHORT cap_list[2];
+ cap_list[0] = Endian16(L2TPV3_PW_TYPE_ETHERNET);
+ cap_list[1] = Endian16(L2TPV3_PW_TYPE_ETHERNET_VLAN);
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_V3_PW_CAP_LIST, true, 0, cap_list, sizeof(cap_list)));
+
+ if (t->IsCiscoV3)
+ {
+ Add(pp2->AvpList, NewAVP(L2TPV3_CISCO_AVP_PW_CAP_LIST, true, L2TP_AVP_VENDOR_ID_CISCO, cap_list, sizeof(cap_list)));
+ }
+ }
+
+ // Cisco AVP
+ if (t->IsCiscoV3)
+ {
+ USHORT us = Endian16(1);
+ Add(pp2->AvpList, NewAVP(L2TPV3_CISCO_AVP_DRAFT_AVP_VERSION, true, L2TP_AVP_VENDOR_ID_CISCO, &us, sizeof(USHORT)));
+ }
+
+ // Recv Window Size
+ us = Endian16(L2TP_WINDOW_SIZE);
+ Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_RECV_WINDOW_SIZE, false, 0, &us, sizeof(USHORT)));
+
+ SendL2TPControlPacket(l2tp, t, 0, pp2);
+
+ FreeL2TPPacket(pp2);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Process related to the existing tunnel
+ // Find the tunnel
+ L2TP_TUNNEL *t = NULL;
+ L2TP_SESSION *l2tpv3_session = NULL;
+
+ if (pp->Ver != 3 || pp->IsControl)
+ {
+ t = GetTunnelFromId(l2tp, &p->SrcIP, pp->TunnelId, pp->Ver == 3);
+ }
+ else
+ {
+ l2tpv3_session = SearchL2TPSessionById(l2tp, true, pp->SessionId);
+ if (l2tpv3_session != NULL)
+ {
+ t = l2tpv3_session->Tunnel;
+
+ pp->TunnelId = t->TunnelId2;
+ }
+ }
+
+ if (t == NULL)
+ {
+ char ipstr[MAX_SIZE];
+
+ IPToStr(ipstr, sizeof(ipstr), &p->SrcIP);
+ Debug("L2TP Tunnel From %s ID=%u Not Found on the Table.\n", ipstr, pp->TunnelId);
+ }
+ else
+ {
+ // Update last reception time
+ t->LastRecvTick = l2tp->Now;
+
+ if (pp->IsControl)
+ {
+ // Control packet
+ UINT i;
+ LIST *o = NULL;
+ L2TP_QUEUE *q;
+ L2TP_QUEUE tt;
+
+ // Delete the queue that the other party has already received from the retransmission queue
+ for (i = 0;i < LIST_NUM(t->SendQueue);i++)
+ {
+ L2TP_QUEUE *q = LIST_DATA(t->SendQueue, i);
+ if (L2TP_SEQ_LT(q->Ns, pp->Nr))
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, q);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ L2TP_QUEUE *q = LIST_DATA(o, i);
+
+ Delete(t->SendQueue, q);
+
+ FreeL2TPQueue(q);
+ }
+
+ ReleaseList(o);
+ }
+
+ if ((!L2TP_SEQ_LT(pp->Ns, t->LastNr)) && (pp->Ns != t->LastNr))
+ {
+ // Add the packet received from the opposite to the queue
+ if (LIST_NUM(t->RecvQueue) < L2TP_WINDOW_SIZE)
+ {
+ Zero(&tt, sizeof(tt));
+ tt.Ns = pp->Ns;
+
+ if (Search(t->RecvQueue, &tt) == NULL)
+ {
+ q = ZeroMalloc(sizeof(L2TP_QUEUE));
+ q->Ns = pp->Ns;
+ q->L2TPPacket = pp;
+ no_free = true;
+ Insert(t->RecvQueue, q);
+
+ // Read to the end of completed part from the head of the queue
+ while (TRUE)
+ {
+ L2TP_QUEUE *q;
+ if (LIST_NUM(t->RecvQueue) == 0)
+ {
+ break;
+ }
+
+ q = LIST_DATA(t->RecvQueue, 0);
+ if (!L2TP_SEQ_EQ(q->Ns, t->LastNr + 1))
+ {
+ break;
+ }
+
+ if (q->L2TPPacket->IsZLB == false)
+ {
+ t->LastNr = q->Ns;
+
+ // The packet other than ZLB is treated
+ t->StateChanged = true;
+ }
+
+ Delete(t->RecvQueue, q);
+
+ // Process the received packet
+ L2TPProcessRecvControlPacket(l2tp, t, q->L2TPPacket);
+
+ FreeL2TPQueue(q);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Data packet
+ L2TP_SESSION *s = GetSessionFromId(t, pp->SessionId);
+
+ if (s != NULL && s->Established)
+ {
+ if (s->IsV3 == false)
+ {
+ // Start the L2TP thread (If not already started)
+ StartL2TPThread(l2tp, t, s);
+
+ // Pass the data
+ TubeSendEx(s->TubeRecv, pp->Data, pp->DataSize, NULL, true);
+ AddTubeToFlushList(l2tp->FlushList, s->TubeRecv);
+ }
+ else
+ {
+ BLOCK *b;
+
+ // Start the EtherIP session (If it's not have yet started)
+ L2TPSessionManageEtherIPServer(l2tp, s);
+
+ // Pass the data
+ b = NewBlock(pp->Data, pp->DataSize, 0);
+
+ EtherIPProcRecvPackets(s->EtherIP, b);
+
+ Free(b);
+ }
+ }
+ }
+ }
+ }
+
+ if (no_free == false)
+ {
+ FreeL2TPPacket(pp);
+ }
+}
+
+// Manage the EtherIP server that is associated with the L2TP session
+void L2TPSessionManageEtherIPServer(L2TP_SERVER *l2tp, L2TP_SESSION *s)
+{
+ IKE_SERVER *ike;
+ IKE_CLIENT *c;
+ // Validate arguments
+ if (l2tp == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (l2tp->IkeClient == NULL || l2tp->IkeServer == NULL)
+ {
+ return;
+ }
+
+ ike = l2tp->IkeServer;
+ c = l2tp->IkeClient;
+
+ if (s->EtherIP == NULL)
+ {
+ char crypt_name[MAX_SIZE];
+ UINT crypt_block_size = IKE_MAX_BLOCK_SIZE;
+
+ Zero(crypt_name, sizeof(crypt_name));
+
+ if (c->CurrentIpSecSaRecv != NULL)
+ {
+ Format(crypt_name, sizeof(crypt_name),
+ "IPsec - %s (%u bits)",
+ c->CurrentIpSecSaRecv->TransformSetting.Crypto->Name,
+ c->CurrentIpSecSaRecv->TransformSetting.CryptoKeySize * 8);
+
+ crypt_block_size = c->CurrentIpSecSaRecv->TransformSetting.Crypto->BlockSize;
+ }
+
+ s->EtherIP = NewEtherIPServer(ike->Cedar, ike->IPsec, ike,
+ &c->ClientIP, c->ClientPort,
+ &c->ServerIP, c->ServerPort, crypt_name,
+ c->IsL2TPOnIPsecTunnelMode, crypt_block_size, c->ClientId,
+ ++ike->CurrentEtherId);
+
+ StrCpy(s->EtherIP->VendorName, sizeof(s->EtherIP->VendorName), s->Tunnel->VendorName);
+
+ s->EtherIP->L2TPv3 = true;
+
+ Debug("IKE_CLIENT 0x%X: EtherIP Server Started.\n", c);
+
+ IPsecLog(ike, c, NULL, NULL, NULL, "LI_ETHERIP_SERVER_STARTED", ike->CurrentEtherId);
+ }
+ else
+ {
+ StrCpy(s->EtherIP->ClientId, sizeof(s->EtherIP->ClientId), c->ClientId);
+ }
+
+ if (s->EtherIP->Interrupts == NULL)
+ {
+ s->EtherIP->Interrupts = l2tp->Interrupts;
+ }
+
+ if (s->EtherIP->SockEvent == NULL)
+ {
+ SetEtherIPServerSockEvent(s->EtherIP, l2tp->SockEvent);
+ }
+
+ s->EtherIP->Now = l2tp->Now;
+}
+
+// Calculate the appropriate MSS of the L2TP
+UINT CalcL2TPMss(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s)
+{
+ UINT ret;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || s == NULL)
+ {
+ return 0;
+ }
+
+ ret = MTU_FOR_PPPOE;
+
+ if (l2tp->IkeServer != NULL)
+ {
+ // On IPsec
+ if (l2tp->IsIPsecIPv6)
+ {
+ ret -= 40;
+ }
+ else
+ {
+ ret -= 20;
+ }
+
+ // UDP
+ ret -= 8;
+
+ // ESP
+ ret -= 20 + l2tp->CryptBlockSize * 2;
+ }
+ else
+ {
+ // Raw L2TP
+ if (IsIP6(&t->ClientIp))
+ {
+ ret -= 40;
+ }
+ else
+ {
+ ret -= 20;
+ }
+ }
+
+ // L2TP UDP
+ ret -= 8;
+
+ // L2TP
+ ret -= 8;
+
+ // PPP
+ ret -= 4;
+
+ // Target communication
+ ret -= 20;
+
+ // TCP header
+ ret -= 20;
+
+ return ret;
+}
+
+// Start the L2TP thread
+void StartL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s)
+{
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->HasThread == false)
+ {
+ char tmp[MAX_SIZE];
+
+ Debug("Thread Created for Session %u/%u on Tunnel %u/%u\n",
+ s->SessionId1, s->SessionId2, t->TunnelId1, t->TunnelId2);
+
+ s->HasThread = true;
+
+ NewTubePair(&s->TubeSend, &s->TubeRecv, 0);
+ SetTubeSockEvent(s->TubeSend, l2tp->SockEvent);
+
+ if (IsEmptyStr(t->VendorName) == false)
+ {
+ Format(tmp, sizeof(tmp), L2TP_IPC_CLIENT_NAME_TAG, t->VendorName);
+ }
+ else
+ {
+ StrCpy(tmp, sizeof(tmp), L2TP_IPC_CLIENT_NAME_NO_TAG);
+ }
+
+ // Create a PPP thread
+ s->Thread = NewPPPSession(l2tp->Cedar, &t->ClientIp, t->ClientPort, &t->ServerIp, t->ServerPort,
+ s->TubeSend, s->TubeRecv, L2TP_IPC_POSTFIX, tmp, t->HostName, l2tp->CryptName,
+ CalcL2TPMss(l2tp, t, s));
+ }
+}
+
+// Stop the L2TP thread
+void StopL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s)
+{
+ THREAD *thread;
+ // Validate arguments
+ if (l2tp == NULL || t == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->IsV3)
+ {
+ // Process the L2TPv3
+ if (s->EtherIP != NULL)
+ {
+ // Release the EtherIP server
+ ReleaseEtherIPServer(s->EtherIP);
+ s->EtherIP = NULL;
+ }
+ return;
+ }
+
+ if (s->HasThread == false)
+ {
+ return;
+ }
+ thread = s->Thread;
+ s->Thread = NULL;
+ s->HasThread = false;
+
+ // Disconnect the tube
+ TubeDisconnect(s->TubeRecv);
+ TubeDisconnect(s->TubeSend);
+
+ // Release the tube
+ ReleaseTube(s->TubeRecv);
+ ReleaseTube(s->TubeSend);
+
+ s->TubeRecv = NULL;
+ s->TubeSend = NULL;
+
+ // Pass the thread to termination list
+ if (l2tp->IkeServer == NULL)
+ {
+ AddThreadToThreadList(l2tp->ThreadList, thread);
+ }
+ else
+ {
+ AddThreadToThreadList(l2tp->IkeServer->ThreadList, thread);
+ }
+
+ Debug("Thread Stopped for Session %u/%u on Tunnel %u/%u\n",
+ s->SessionId1, s->SessionId2, t->TunnelId1, t->TunnelId2);
+
+ // Release the thread
+ ReleaseThread(thread);
+}
+
+// Interrupt processing of L2TP server
+void L2TPProcessInterrupts(L2TP_SERVER *l2tp)
+{
+ UINT i, j;
+ LIST *delete_tunnel_list = NULL;
+ // Validate arguments
+ if (l2tp == NULL)
+ {
+ return;
+ }
+
+ if (l2tp->Halt)
+ {
+ if (l2tp->Halting == false)
+ {
+ l2tp->Halting = true;
+
+ // Disconnect all tunnels
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ DisconnectL2TPTunnel(t);
+ }
+ }
+ }
+
+ // Flush
+ FlushTubeFlushList(l2tp->FlushList);
+
+ // Enumerate all tunnels
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+ LIST *delete_session_list = NULL;
+
+ if ((l2tp->Now >= (t->LastRecvTick + (UINT64)L2TP_TUNNEL_TIMEOUT)) && t->Timedout == false)
+ {
+ // Disconnect the tunnel forcibly if data can not be received for a certain period of time
+ t->Timedout = true;
+
+ Debug("L2TP Tunnel %u/%u Timed out.\n", t->TunnelId1, t->TunnelId2);
+ DisconnectL2TPTunnel(t);
+ }
+
+ if (t->Established && (l2tp->Now >= (t->LastHelloSent + (UINT64)L2TP_HELLO_INTERVAL)))
+ {
+ if (LIST_NUM(t->SendQueue) <= L2TP_HELLO_SUPRESS_MAX_THRETHORD_NUM_SEND_QUEUE)
+ {
+ L2TP_PACKET *pp = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_HELLO, t->IsV3);
+
+ // Send a Hello message
+ t->LastHelloSent = l2tp->Now;
+ //Debug("L2TP Sending Hello %u/%u: tick=%I64u\n", t->TunnelId1, t->TunnelId2, l2tp->Now);
+
+ SendL2TPControlPacket(l2tp, t, 0, pp);
+
+ FreeL2TPPacket(pp);
+
+ L2TPAddInterrupt(l2tp, t->LastHelloSent + (UINT64)L2TP_HELLO_INTERVAL);
+ }
+ }
+
+ // Enumerate all sessions
+ for (j = 0;j < LIST_NUM(t->SessionList);j++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, j);
+
+ if (s->HasThread)
+ {
+ // Send packet data
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(s->TubeSend);
+
+ if (d == NULL)
+ {
+ break;
+ }
+
+ SendL2TPDataPacket(l2tp, t, s, d->Data, d->DataSize);
+
+ FreeTubeData(d);
+ }
+
+ if (IsTubeConnected(s->TubeSend) == false)
+ {
+ // Disconnect the this session because the PPP thread ends
+ DisconnectL2TPSession(t, s);
+ }
+ }
+
+ if (s->IsV3)
+ {
+ if (s->EtherIP != NULL)
+ {
+ UINT k;
+
+ L2TPSessionManageEtherIPServer(l2tp, s);
+
+ // Notify an interrupt to the EtherIP module
+ EtherIPProcInterrupts(s->EtherIP);
+
+ // Send an EtherIP packet data
+ for (k = 0;k < LIST_NUM(s->EtherIP->SendPacketList);k++)
+ {
+ BLOCK *b = LIST_DATA(s->EtherIP->SendPacketList, k);
+
+ SendL2TPDataPacket(l2tp, t, s, b->Buf, b->Size);
+
+ FreeBlock(b);
+ }
+
+ DeleteAll(s->EtherIP->SendPacketList);
+ }
+ }
+
+ if (s->WantToDisconnect && s->Disconnecting == false)
+ {
+ // Disconnect the session
+ UCHAR error_data[4];
+ USHORT us;
+ UINT ui;
+ UINT ppp_error_1 = 0, ppp_error_2 = 0;
+
+ // Send the session disconnection response
+ L2TP_PACKET *pp = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_CDN, s->IsV3);
+
+ if (s->TubeRecv != NULL)
+ {
+ ppp_error_1 = s->TubeRecv->IntParam1;
+ ppp_error_2 = s->TubeRecv->IntParam2;
+ }
+
+ // Assigned Session ID
+ if (s->IsV3 == false)
+ {
+ us = Endian16(s->SessionId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_ASSIGNED_SESSION, true, 0,
+ &us, sizeof(USHORT)));
+ }
+ else
+ {
+ ui = Endian16(s->SessionId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL, true, 0,
+ &ui, sizeof(UINT)));
+
+ if (t->IsCiscoV3)
+ {
+ Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_SESSION_ID_LOCAL, true, L2TP_AVP_VENDOR_ID_CISCO,
+ &ui, sizeof(UINT)));
+ }
+ }
+
+ // Result-Error Code
+ Zero(error_data, sizeof(error_data));
+ error_data[1] = 0x03;
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_RESULT_CODE, true, 0,
+ error_data, sizeof(error_data)));
+
+ if (ppp_error_1 != 0)
+ {
+ // PPP Disconnect Cause Code AVP
+ BUF *b = NewBuf();
+ UCHAR uc;
+ USHORT us;
+
+ // Disconnect Code
+ us = Endian16(ppp_error_1);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ // Control Protocol Number
+ us = Endian16(0xc021);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ // Direction
+ uc = (UCHAR)ppp_error_2;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_PPP_DISCONNECT_CAUSE, false, 0,
+ b->Buf, b->Size));
+
+ FreeBuf(b);
+ }
+
+ SendL2TPControlPacket(l2tp, t, s->SessionId1, pp);
+
+ FreeL2TPPacket(pp);
+
+ // Disconnect the session
+ Debug("L2TP Session %u/%u on Tunnel %u/%u Disconnected.\n", s->SessionId1, s->SessionId2,
+ t->TunnelId1, t->TunnelId2);
+ s->Disconnecting = true;
+ s->Established = false;
+ s->DisconnectTimeout = l2tp->Now + (UINT64)L2TP_TUNNEL_DISCONNECT_TIMEOUT;
+
+ // Stop the thread
+ StopL2TPThread(l2tp, t, s);
+
+ L2TPAddInterrupt(l2tp, s->DisconnectTimeout);
+ }
+
+ if (s->Disconnecting && ((l2tp->Now >= s->DisconnectTimeout) || LIST_NUM(t->SendQueue) == 0))
+ {
+ // Delete the session if synchronization between the client
+ // and the server is complete or a time-out occurs
+ if (delete_session_list == NULL)
+ {
+ delete_session_list = NewListFast(NULL);
+ }
+
+ Add(delete_session_list, s);
+ }
+ }
+
+ if (delete_session_list != NULL)
+ {
+ // Session deletion process
+ for (j = 0;j < LIST_NUM(delete_session_list);j++)
+ {
+ L2TP_SESSION *s = LIST_DATA(delete_session_list, j);
+
+ Debug("L2TP Session %u/%u on Tunnel %u/%u Cleaned up.\n", s->SessionId1, s->SessionId2,
+ t->TunnelId1, t->TunnelId2);
+
+ FreeL2TPSession(s);
+ Delete(t->SessionList, s);
+ }
+
+ ReleaseList(delete_session_list);
+ }
+
+ if (t->WantToDisconnect && t->Disconnecting == false)
+ {
+ // Disconnect the tunnel
+ USHORT error_data[4];
+ USHORT us;
+ UINT ui;
+ // Reply the tunnel disconnection response
+ L2TP_PACKET *pp = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_STOPCCN, t->IsV3);
+
+ // Assigned Tunnel ID
+ if (t->IsV3 == false)
+ {
+ us = Endian16(t->TunnelId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_ASSIGNED_TUNNEL, true, 0,
+ &us, sizeof(USHORT)));
+ }
+ else
+ {
+ ui = Endian32(t->TunnelId2);
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_TUNNEL_ID, true, 0,
+ &ui, sizeof(UINT)));
+
+ if (t->IsCiscoV3)
+ {
+ Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_TUNNEL_ID, true, L2TP_AVP_VENDOR_ID_CISCO,
+ &ui, sizeof(UINT)));
+ }
+ }
+
+ // Result-Error Code
+ Zero(error_data, sizeof(error_data));
+ error_data[1] = 0x06;
+ Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_RESULT_CODE, true, 0,
+ error_data, sizeof(error_data)));
+
+ SendL2TPControlPacket(l2tp, t, 0, pp);
+
+ FreeL2TPPacket(pp);
+
+ Debug("L2TP Tunnel %u/%u is Disconnected.\n", t->TunnelId1, t->TunnelId2);
+ t->Disconnecting = true;
+ t->Established = false;
+ t->DisconnectTimeout = l2tp->Now + (UINT64)L2TP_TUNNEL_DISCONNECT_TIMEOUT;
+ L2TPAddInterrupt(l2tp, t->DisconnectTimeout);
+ }
+
+ if (t->Disconnecting && (((LIST_NUM(t->SendQueue) == 0) && LIST_NUM(t->SessionList) == 0) || (l2tp->Now >= t->DisconnectTimeout)))
+ {
+ // Delete the tunnel if there is no session in the tunnel when synchronization
+ // between the client and the server has been completed or a time-out occurs
+ if (delete_tunnel_list == NULL)
+ {
+ delete_tunnel_list = NewListFast(NULL);
+ }
+
+ Add(delete_tunnel_list, t);
+ }
+ }
+
+ if (delete_tunnel_list != NULL)
+ {
+ for (i = 0;i < LIST_NUM(delete_tunnel_list);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(delete_tunnel_list, i);
+
+ Debug("L2TP Tunnel %u/%u Cleaned up.\n", t->TunnelId1, t->TunnelId2);
+
+ FreeL2TPTunnel(t);
+ Delete(l2tp->TunnelList, t);
+ }
+
+ ReleaseList(delete_tunnel_list);
+ }
+
+ // Re-transmit packets
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+ UINT j;
+
+ if (LIST_NUM(t->SendQueue) >= 1)
+ {
+ // Packet to be transmitted exists one or more
+ for (j = 0;j < LIST_NUM(t->SendQueue);j++)
+ {
+ L2TP_QUEUE *q = LIST_DATA(t->SendQueue, j);
+
+ if (l2tp->Now >= q->NextSendTick)
+ {
+ q->NextSendTick = l2tp->Now + (UINT64)L2TP_PACKET_RESEND_INTERVAL;
+
+ L2TPAddInterrupt(l2tp, q->NextSendTick);
+
+ SendL2TPControlPacketMain(l2tp, t, q);
+ }
+ }
+ }
+ else
+ {
+ // There is no packet to be transmitted, but the state of the tunnel is changed
+ if (t->StateChanged)
+ {
+ // Send a ZLB
+ L2TP_QUEUE *q = ZeroMalloc(sizeof(L2TP_QUEUE));
+ L2TP_PACKET *pp = NewL2TPControlPacket(0, t->IsV3);
+
+ pp->TunnelId = t->TunnelId1;
+ pp->Ns = t->NextNs;
+ q->Buf = BuildL2TPPacketData(pp);
+
+ SendL2TPControlPacketMain(l2tp, t, q);
+
+ FreeL2TPQueue(q);
+ FreeL2TPPacket(pp);
+ }
+ }
+
+ t->StateChanged = false;
+ }
+
+ if (l2tp->Halting)
+ {
+ if (LIST_NUM(l2tp->TunnelList) == 0)
+ {
+ // Stop all the L2TP tunnel completed
+ if (l2tp->HaltCompleted == false)
+ {
+ l2tp->HaltCompleted = true;
+
+ Set(l2tp->HaltCompletedEvent);
+ }
+ }
+ }
+
+ // Maintenance the thread list
+ if (l2tp->IkeServer == NULL)
+ {
+ MainteThreadList(l2tp->ThreadList);
+ //Debug("l2tp->ThreadList: %u\n", LIST_NUM(l2tp->ThreadList));
+ }
+}
+
+// Create a new L2TP server
+L2TP_SERVER *NewL2TPServer(CEDAR *cedar)
+{
+ return NewL2TPServerEx(cedar, NULL, false, 0);
+}
+L2TP_SERVER *NewL2TPServerEx(CEDAR *cedar, IKE_SERVER *ike, bool is_ipv6, UINT crypt_block_size)
+{
+ L2TP_SERVER *l2tp;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ l2tp = ZeroMalloc(sizeof(L2TP_SERVER));
+
+ l2tp->FlushList = NewTubeFlushList();
+
+ l2tp->Cedar = cedar;
+ AddRef(l2tp->Cedar->ref);
+
+ l2tp->SendPacketList = NewList(NULL);
+ l2tp->TunnelList = NewList(NULL);
+
+ l2tp->HaltCompletedEvent = NewEvent();
+
+ l2tp->ThreadList = NewThreadList();
+
+ l2tp->IkeServer = ike;
+
+ l2tp->IsIPsecIPv6 = is_ipv6;
+ l2tp->CryptBlockSize = crypt_block_size;
+
+ return l2tp;
+}
+
+// Stop the L2TP server
+void StopL2TPServer(L2TP_SERVER *l2tp, bool no_wait)
+{
+ // Validate arguments
+ if (l2tp == NULL)
+ {
+ return;
+ }
+ if (l2tp->Halt)
+ {
+ return;
+ }
+
+ // Begin to shut down
+ l2tp->Halt = true;
+ Debug("Shutting down L2TP Server...\n");
+
+ // Hit the event
+ SetSockEvent(l2tp->SockEvent);
+
+ if (no_wait == false)
+ {
+ // Wait until complete stopping all tunnels
+ Wait(l2tp->HaltCompletedEvent, INFINITE);
+ }
+ else
+ {
+ UINT i, j;
+ // Kill the thread of all sessions
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ for (j = 0;j < LIST_NUM(t->SessionList);j++)
+ {
+ L2TP_SESSION *s = LIST_DATA(t->SessionList, j);
+
+ StopL2TPThread(l2tp, t, s);
+ }
+ }
+ }
+
+ // Thread stop
+ Debug("Stopping all L2TP PPP Threads...\n");
+ StopThreadList(l2tp->ThreadList);
+ Debug("L2TP Server Shutdown Completed.\n");
+}
+
+// Release the L2TP server
+void FreeL2TPServer(L2TP_SERVER *l2tp)
+{
+ UINT i;
+ // Validate arguments
+ if (l2tp == NULL)
+ {
+ return;
+ }
+
+ FreeThreadList(l2tp->ThreadList);
+
+ for (i = 0;i < LIST_NUM(l2tp->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(l2tp->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(l2tp->SendPacketList);
+
+ for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
+ {
+ L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
+
+ FreeL2TPTunnel(t);
+ }
+
+ ReleaseList(l2tp->TunnelList);
+
+ ReleaseSockEvent(l2tp->SockEvent);
+
+ ReleaseEvent(l2tp->HaltCompletedEvent);
+
+ ReleaseCedar(l2tp->Cedar);
+
+ FreeTubeFlushList(l2tp->FlushList);
+
+ Free(l2tp);
+}
+
+// Set a SockEvent to the L2TP server
+void SetL2TPServerSockEvent(L2TP_SERVER *l2tp, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (l2tp == NULL)
+ {
+ return;
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ if (l2tp->SockEvent != NULL)
+ {
+ ReleaseSockEvent(l2tp->SockEvent);
+ l2tp->SockEvent = NULL;
+ }
+
+ l2tp->SockEvent = e;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_L2TP.h b/src/Cedar/IPsec_L2TP.h
new file mode 100644
index 00000000..1de1fe1d
--- /dev/null
+++ b/src/Cedar/IPsec_L2TP.h
@@ -0,0 +1,347 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_L2TP.h
+// Header of IPsec_L2TP.c
+
+#ifndef IPSEC_L2TP_H
+#define IPSEC_L2TP_H
+
+//// Macro
+
+// Check the sequence number
+#define L2TP_SEQ_LT(a, b) (((USHORT)(((USHORT)(a)) - ((USHORT)(b)))) & 0x8000)
+#define L2TP_SEQ_EQ(a, b) ((USHORT)(a) == (USHORT)(b))
+
+//// Constants
+
+// Client string
+#define L2TP_IPC_CLIENT_NAME_TAG "L2TP VPN Client - %s"
+#define L2TP_IPC_CLIENT_NAME_NO_TAG "L2TP VPN Client"
+#define L2TP_IPC_POSTFIX "L2TP"
+
+// L2TP vendor name
+#define L2TP_VENDOR_NAME "L2TP"
+
+// L2TP packet retransmission interval
+#define L2TP_PACKET_RESEND_INTERVAL 500
+
+// Timeout for L2TP tunnel disconnecting completion
+#define L2TP_TUNNEL_DISCONNECT_TIMEOUT 3000
+
+// Timeout for L2TP session disconnection completion
+#define L2TP_SESSION_DISCONNECT_TIMEOUT 3000
+
+// Time-out interval of L2TP tunnel
+#define L2TP_TUNNEL_TIMEOUT (60 * 1000)
+
+// Transmission interval of L2TP Hello
+#define L2TP_HELLO_INTERVAL (8801)
+
+// Threshold number of registered items in the transmission queue for suppressing the L2TP Hello transmission
+#define L2TP_HELLO_SUPRESS_MAX_THRETHORD_NUM_SEND_QUEUE 32
+
+// L2TP window size
+#define L2TP_WINDOW_SIZE 16
+
+// L2TP packet header bit mask
+#define L2TP_HEADER_BIT_TYPE 0x80 // Type
+#define L2TP_HEADER_BIT_LENGTH 0x40 // Length
+#define L2TP_HEADER_BIT_SEQUENCE 0x08 // Sequence
+#define L2TP_HEADER_BIT_OFFSET 0x02 // Offset
+#define L2TP_HEADER_BIT_PRIORITY 0x01 // Priority
+#define L2TP_HEADER_BIT_VER 0x0F // Version
+
+// L2TP AVP header bit mask
+#define L2TP_AVP_BIT_MANDATORY 0x80 // Mandatory
+#define L2TP_AVP_BIT_HIDDEN 0x40 // Hidden
+#define L2TP_AVP_LENGTH 0x3FF // Length
+
+// AVP value
+#define L2TP_AVP_TYPE_MESSAGE_TYPE 0 // Message Type
+#define L2TP_AVP_TYPE_RESULT_CODE 1 // Result Code
+#define L2TP_AVP_TYPE_PROTOCOL_VERSION 2 // Protocol Version
+#define L2TP_AVP_TYPE_FRAME_CAP 3 // Framing Capabilities
+#define L2TP_AVP_TYPE_BEARER_CAP 4 // Bearer Capabilities
+#define L2TP_AVP_TYPE_TIE_BREAKER 5 // Tie Breaker
+#define L2TP_AVP_TYPE_HOST_NAME 7 // Host Name
+#define L2TP_AVP_TYPE_VENDOR_NAME 8 // Vendor Name
+#define L2TP_AVP_TYPE_ASSIGNED_TUNNEL 9 // Assigned Tunnel
+#define L2TP_AVP_TYPE_RECV_WINDOW_SIZE 10 // Receive Window Size
+#define L2TP_AVP_TYPE_ASSIGNED_SESSION 14 // Assigned Session ID
+#define L2TP_AVP_TYPE_CALL_SERIAL 15 // Call Serial Number
+#define L2TP_AVP_TYPE_PPP_DISCONNECT_CAUSE 46 // PPP Disconnect Cause Code
+#define L2TP_AVP_TYPE_V3_ROUTER_ID 60 // Router ID
+#define L2TP_AVP_TYPE_V3_TUNNEL_ID 61 // Assigned Control Connection ID
+#define L2TP_AVP_TYPE_V3_PW_CAP_LIST 62 // Pseudowire Capabilities List
+#define L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL 63 // Local Session ID
+#define L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE 64 // Remote Session ID
+#define L2TP_AVP_TYPE_V3_PW_TYPE 68 // Pseudowire Type
+
+// Message Type value
+#define L2TP_MESSAGE_TYPE_SCCRQ 1 // Start-Control-Connection-Request
+#define L2TP_MESSAGE_TYPE_SCCRP 2 // Start-Control-Connection-Reply
+#define L2TP_MESSAGE_TYPE_SCCCN 3 // Start-Control-Connection-Connected
+#define L2TP_MESSAGE_TYPE_STOPCCN 4 // Stop-Control-Connection-Notification
+#define L2TP_MESSAGE_TYPE_HELLO 6 // Hello
+#define L2TP_MESSAGE_TYPE_ICRQ 10 // Incoming-Call-Request
+#define L2TP_MESSAGE_TYPE_ICRP 11 // Incoming-Call-Reply
+#define L2TP_MESSAGE_TYPE_ICCN 12 // Incoming-Call-Connected
+#define L2TP_MESSAGE_TYPE_CDN 14 // Call-Disconnect-Notify
+
+// Type of L2TPv3 virtual network
+#define L2TPV3_PW_TYPE_ETHERNET 5 // Ethernet
+#define L2TPV3_PW_TYPE_ETHERNET_VLAN 4 // Ethernet VLAN
+
+// L2TPv3 vendor unique value
+#define L2TP_AVP_VENDOR_ID_CISCO 9 // Cisco Systems
+#define L2TPV3_CISCO_AVP_TUNNEL_ID 1 // Assigned Connection ID
+#define L2TPV3_CISCO_AVP_PW_CAP_LIST 2 // Pseudowire Capabilities List
+#define L2TPV3_CISCO_AVP_SESSION_ID_LOCAL 3 // Local Session ID
+#define L2TPV3_CISCO_AVP_SESSION_ID_REMOTE 4 // Remote Session ID
+#define L2TPV3_CISCO_AVP_PW_TYPE 7 // Pseudowire Type
+#define L2TPV3_CISCO_AVP_DRAFT_AVP_VERSION 10 // Draft AVP Version
+
+
+
+//// Types
+
+// L2TP queue
+struct L2TP_QUEUE
+{
+ BUF *Buf; // Data
+ USHORT Ns; // Sequence number
+ UINT64 NextSendTick; // Scheduled time to be sent next
+ L2TP_PACKET *L2TPPacket; // L2TP packet data
+};
+
+// L2TP AVP value
+struct L2TP_AVP
+{
+ bool Mandatory; // Force bit
+ UINT Length; // Overall length
+ USHORT VendorID; // Vendor ID
+ USHORT Type; // Type
+ UINT DataSize; // Data size
+ void *Data; // Data body
+};
+
+// L2TP packet
+struct L2TP_PACKET
+{
+ bool IsControl; // Whether it's a control message
+ bool HasLength; // Whether there is length bit
+ bool HasSequence; // Whether there is sequence bit
+ bool HasOffset; // Whether there is offset bit
+ bool IsPriority; // Whether priority packet
+ bool IsZLB; // Zero Length Bit
+ UINT Ver; // Version
+ UINT Length; // Length
+ UINT TunnelId; // Tunnel ID
+ UINT SessionId; // Session ID
+ USHORT Ns, Nr; // Sequence number
+ UINT OffsetSize; // Offset size
+ UINT DataSize; // Data size
+ void *Data; // Data body
+ LIST *AvpList; // AVP list
+ UINT MessageType; // Message type
+};
+
+// L2TP session
+struct L2TP_SESSION
+{
+ L2TP_TUNNEL *Tunnel; // Parent L2TP tunnel
+ bool IsV3; // L2TPv3
+ bool IsCiscoV3; // L2TPv3 for Cisco
+ UINT SessionId1; // Session ID (server -> client direction)
+ UINT SessionId2; // Session ID (client -> server direction)
+ bool Established; // Established
+ bool WantToDisconnect; // Whether to want to disconnect
+ bool Disconnecting; // Whether disconnected
+ UINT64 DisconnectTimeout; // Disconnection completion time-out
+ bool HasThread; // Whether have a thread
+ THREAD *Thread; // Thread
+ TUBE *TubeSend; // Tube of PPP to L2TP direction
+ TUBE *TubeRecv; // Tube of L2TP to PPP direction
+ UINT PseudowireType; // Type of L2TPv3 virtual line
+ ETHERIP_SERVER *EtherIP; // EtherIP server
+};
+
+// L2TP tunnel
+struct L2TP_TUNNEL
+{
+ bool IsV3; // L2TPv3
+ bool IsCiscoV3; // L2TPv3 for Cisco
+ IP ClientIp; // Client IP address
+ UINT ClientPort; // Client port number
+ IP ServerIp; // Server IP address
+ UINT ServerPort; // Server port number
+ UINT TunnelId1; // Tunnel ID (server -> client direction)
+ UINT TunnelId2; // Tunnel ID (client -> server direction)
+ char HostName[MAX_SIZE]; // Destination host name
+ char VendorName[MAX_SIZE]; // Destination vendor name
+ LIST *SessionList; // L2TP session list
+ LIST *SendQueue; // Transmission queue
+ LIST *RecvQueue; // Reception queue
+ USHORT NextNs; // Value of Ns of the packet to be sent next
+ USHORT LastNr; // Value of NR received in the last
+ bool Established; // Whether the tunnel is established
+ bool StateChanged; // Whether the state have changed
+ bool WantToDisconnect; // Whether to want to disconnect
+ bool Disconnecting; // Whether disconnected
+ UINT64 DisconnectTimeout; // Disconnection completion time-out
+ UINT64 LastRecvTick; // Time which the data has been received at last
+ bool Timedout; // Whether the time-out
+ UINT64 LastHelloSent; // Time which the data has been sent at last
+};
+
+// L2TP server
+struct L2TP_SERVER
+{
+ CEDAR *Cedar;
+ UINT64 Now; // Current time
+ LIST *SendPacketList; // Transmission packet
+ LIST *TunnelList; // Tunnel list
+ INTERRUPT_MANAGER *Interrupts; // Interrupt manager
+ SOCK_EVENT *SockEvent; // SockEvent
+ bool Halt; // Start the shutdown
+ bool Halting; // During shutdown
+ bool HaltCompleted; // Shutdown is complete
+ EVENT *HaltCompletedEvent; // Stopping completion event
+ LIST *ThreadList; // Thread list
+ char CryptName[MAX_SIZE]; // Cipher algorithm name
+ IKE_SERVER *IkeServer; // IKE server (Only if associated)
+ IKE_CLIENT *IkeClient; // IKE client (Only if associated)
+ bool IsIPsecIPv6; // Whether it's IPv6
+ UINT CryptBlockSize; // Cipher block size of the upper layer
+ TUBE_FLUSH_LIST *FlushList; // Tube Flush List
+};
+
+
+//// Function prototype
+L2TP_SERVER *NewL2TPServer(CEDAR *cedar);
+L2TP_SERVER *NewL2TPServerEx(CEDAR *cedar, IKE_SERVER *ike, bool is_ipv6, UINT crypt_block_size);
+void SetL2TPServerSockEvent(L2TP_SERVER *l2tp, SOCK_EVENT *e);
+void FreeL2TPServer(L2TP_SERVER *l2tp);
+void StopL2TPServer(L2TP_SERVER *l2tp, bool no_wait);
+void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p);
+L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p);
+BUF *BuildL2TPPacketData(L2TP_PACKET *pp);
+L2TP_AVP *GetAVPValue(L2TP_PACKET *p, UINT type);
+L2TP_AVP *GetAVPValueEx(L2TP_PACKET *p, UINT type, UINT vendor_id);
+L2TP_TUNNEL *NewL2TPTunnel(L2TP_SERVER *l2tp, L2TP_PACKET *p, UDPPACKET *udp);
+UINT GenerateNewTunnelId(L2TP_SERVER *l2tp, IP *client_ip);
+UINT GenerateNewTunnelIdEx(L2TP_SERVER *l2tp, IP *client_ip, bool is_32bit);
+void FreeL2TPTunnel(L2TP_TUNNEL *t);
+L2TP_TUNNEL *GetTunnelFromId(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id, bool is_v3);
+L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClient(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id);
+void SendL2TPControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id, L2TP_PACKET *p);
+void SendL2TPControlPacketMain(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_QUEUE *q);
+void SendL2TPDataPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s, void *data, UINT size);
+void FreeL2TPQueue(L2TP_QUEUE *q);
+void L2TPAddInterrupt(L2TP_SERVER *l2tp, UINT64 next_tick);
+void L2TPSendUDP(L2TP_SERVER *l2tp, UDPPACKET *p);
+void L2TPProcessInterrupts(L2TP_SERVER *l2tp);
+L2TP_PACKET *NewL2TPControlPacket(UINT message_type, bool is_v3);
+L2TP_AVP *NewAVP(USHORT type, bool mandatory, USHORT vendor_id, void *data, UINT data_size);
+int CmpL2TPQueueForRecv(void *p1, void *p2);
+void L2TPProcessRecvControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_PACKET *p);
+L2TP_SESSION *GetSessionFromId(L2TP_TUNNEL *t, UINT session_id);
+L2TP_SESSION *GetSessionFromIdAssignedByClient(L2TP_TUNNEL *t, UINT session_id);
+L2TP_SESSION *NewL2TPSession(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id_by_client);
+UINT GenerateNewSessionId(L2TP_TUNNEL *t);
+UINT GenerateNewSessionIdEx(L2TP_TUNNEL *t, bool is_32bit);
+void FreeL2TPSession(L2TP_SESSION *s);
+void DisconnectL2TPSession(L2TP_TUNNEL *t, L2TP_SESSION *s);
+void DisconnectL2TPTunnel(L2TP_TUNNEL *t);
+void StartL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s);
+void StopL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s);
+UINT CalcL2TPMss(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s);
+UINT GenerateNewSessionIdForL2TPv3(L2TP_SERVER *l2tp);
+L2TP_SESSION *SearchL2TPSessionById(L2TP_SERVER *l2tp, bool is_v3, UINT id);
+void L2TPSessionManageEtherIPServer(L2TP_SERVER *l2tp, L2TP_SESSION *s);
+
+#endif // IPSEC_L2TP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_PPP.c b/src/Cedar/IPsec_PPP.c
new file mode 100644
index 00000000..26fa0d1d
--- /dev/null
+++ b/src/Cedar/IPsec_PPP.c
@@ -0,0 +1,2689 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_PPP.c
+// PPP protocol stack
+
+#include "CedarPch.h"
+
+// PPP thread
+void PPPThread(THREAD *thread, void *param)
+{
+ PPP_SESSION *p = (PPP_SESSION *)param;
+ UINT i;
+ PPP_LCP *c;
+ USHORT us;
+ UINT ui;
+ USHORT next_protocol = 0;
+ bool ret = false;
+ char ipstr1[128], ipstr2[128];
+ bool established = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Initialize
+ p->Mru1 = p->Mru2 = PPP_MRU_DEFAULT;
+ p->RecvPacketList = NewList(NULL);
+
+ //// Link establishment phase
+ IPToStr(ipstr1, sizeof(ipstr1), &p->ClientIP);
+ IPToStr(ipstr2, sizeof(ipstr2), &p->ServerIP);
+ PPPLog(p, "LP_CONNECTED", p->Postfix, ipstr1, p->ClientHostname, p->ClientPort, ipstr2, p->ServerPort,
+ p->ClientSoftwareName, p->AdjustMss);
+
+ // Request the use of PAP
+ c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
+ us = Endian16(PPP_LCP_AUTH_PAP);
+ Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &us, sizeof(USHORT)));
+ ret = PPPSendRequest(p, PPP_PROTOCOL_LCP, c);
+ FreePPPLCP(c);
+ if (ret == false)
+ {
+ if (IsTubeConnected(p->TubeRecv))
+ {
+ // PAP protocol is denied
+ p->DisconnectCauseCode = 15;
+ p->DisconnectCauseDirection = 1;
+ Debug("PPP: PAP Rejected.\n");
+
+ if (p->EnableMSCHAPv2)
+ {
+ // Try to request the use of MS-CHAPv2
+ UCHAR ms_chap_v2_code[3];
+ WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP);
+ ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2;
+
+ c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
+ Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, ms_chap_v2_code, sizeof(ms_chap_v2_code)));
+ ret = PPPSendRequest(p, PPP_PROTOCOL_LCP, c);
+ FreePPPLCP(c);
+
+ if (ret == false)
+ {
+ if (IsTubeConnected(p->TubeRecv))
+ {
+ // MS-CHAPv2 protocol was also rejected
+ p->DisconnectCauseCode = 15;
+ p->DisconnectCauseDirection = 1;
+ Debug("PPP: MS-CHAPv2 Rejected.\n");
+ PPPLog(p, "LP_PAP_MSCHAPV2_REJECTED");
+ }
+ }
+ else
+ {
+ // It is to be used for the MS-CHAPv2
+ p->AuthProtocol = PPP_PROTOCOL_CHAP;
+ }
+ }
+ else
+ {
+ PPPLog(p, "LP_PAP_REJECTED");
+ }
+ }
+
+ if (ret == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+ }
+
+ //// Authentication phase
+
+ if (p->AuthProtocol == PPP_PROTOCOL_PAP)
+ {
+ // PAP
+ next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_LCP);
+ if (next_protocol == 0)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ Debug("next_protocol = 0x%x\n", next_protocol);
+
+ if (next_protocol != PPP_PROTOCOL_PAP)
+ {
+ Debug("next_protocol is not PAP !!\n");
+ PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_PAP", next_protocol);
+ goto LABEL_CLEANUP;
+ }
+
+ next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_PAP);
+ if (next_protocol == 0 || p->AuthOk == false)
+ {
+ if (IsTubeConnected(p->TubeRecv))
+ {
+ // PAP authentication failed
+ p->DisconnectCauseCode = 15;
+ p->DisconnectCauseDirection = 1;
+ Debug("PPP: PAP Failed.\n");
+ PPPLog(p, "LP_PAP_FAILED");
+ }
+ goto LABEL_CLEANUP;
+ }
+ }
+ else
+ {
+ // MS-CHAP v2
+ PPP_PACKET *pp, *pp_ret;
+ BUF *b;
+ char machine_name[MAX_SIZE];
+ UINT64 start_tick = Tick64();
+ UINT64 timeout_tick = start_tick + (UINT64)PPP_PACKET_RECV_TIMEOUT;
+ UINT64 next_send_tick = 0;
+ USHORT pp_ret_protocol;
+
+ PPPContinueUntilFinishAllLCPOptionRequestsDetermined(p);
+
+ // Generate a Server Challenge packet of MS-CHAP v2
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
+
+ pp = ZeroMalloc(sizeof(PPP_PACKET));
+ pp->Protocol = PPP_PROTOCOL_CHAP;
+ pp->IsControl = true;
+ pp->Lcp = NewPPPLCP(PPP_CHAP_CODE_CHALLENGE, 0);
+
+ b = NewBuf();
+ WriteBufChar(b, 16);
+ WriteBuf(b, p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
+ WriteBuf(b, machine_name, StrLen(machine_name));
+ pp->Lcp->Data = Clone(b->Buf, b->Size);
+ pp->Lcp->DataSize = b->Size;
+ FreeBuf(b);
+
+ PPPSendPacket(p, pp);
+
+ pp_ret_protocol = 0;
+ pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false);
+
+ if (pp_ret != NULL)
+ {
+ FreePPPPacket(pp_ret);
+ }
+
+ FreePPPPacket(pp);
+
+ if (pp_ret_protocol == 0 || p->AuthOk == false)
+ {
+ if (IsTubeConnected(p->TubeRecv))
+ {
+ // MS-CHAPv2 authentication failed
+ p->DisconnectCauseCode = 15;
+ p->DisconnectCauseDirection = 1;
+ Debug("PPP: MS-CHAPv2 Failed.\n");
+ PPPLog(p, "LP_MSCHAPV2_FAILED");
+ }
+ goto LABEL_CLEANUP;
+ }
+
+ next_protocol = pp_ret_protocol;
+ }
+
+ Debug("next_protocol = 0x%x\n", next_protocol);
+
+ if (next_protocol != PPP_PROTOCOL_IPCP)
+ {
+ // Receive the protocol of non-IPCP
+ Debug("Not IPCP Protocol.\n");
+ PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_IPCP", next_protocol);
+ goto LABEL_CLEANUP;
+ }
+
+ // Notify the IP address of the PPP server
+ c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
+ ui = Endian32(0x01000001); // 1.0.0.1
+ Add(c->OptionList, NewPPPOption(PPP_IPCP_OPTION_IP, &ui, sizeof(UINT)));
+ ret = PPPSendRequest(p, PPP_PROTOCOL_IPCP, c);
+ FreePPPLCP(c);
+ if (ret == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_IPCP);
+ Debug("next_protocol = 0x%x\n", next_protocol);
+
+ if (p->Ipc == NULL || IsZeroIP(&p->Ipc->ClientIPAddress))
+ {
+ // IP address is undetermined
+ PPPLog(p, "LP_IP_ADDRESS_NOT_DETERMIND");
+ goto LABEL_CLEANUP;
+ }
+
+ if (next_protocol == PPP_PROTOCOL_IP)
+ {
+ established = true;
+
+ // Do the IP communication
+ while (true)
+ {
+ TUBE *tubes[2];
+ UINT64 now = Tick64();
+ UINT r;
+
+ // Flush the ARP table of the IPC
+ IPCFlushArpTable(p->Ipc);
+
+ // Packet of client to server direction
+ while (true)
+ {
+ PPP_PACKET *pp = PPPRecvPacketForCommunication(p);
+ if (pp == NULL)
+ {
+ break;
+ }
+
+ if (pp->Protocol == PPP_PROTOCOL_IP)
+ {
+ // Since I want to send the IP packet, pass it to the IPC
+ IPCSendIPv4(p->Ipc, pp->Data, pp->DataSize);
+ }
+
+ FreePPPPacket(pp);
+ }
+
+ if (p->DhcpAllocated)
+ {
+ if (now >= p->DhcpNextRenewTime)
+ {
+ IP ip;
+
+ // DHCP renewal procedure
+ p->DhcpNextRenewTime = now + p->DhcpRenewInterval;
+
+ UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
+
+ IPCDhcpRenewIP(p->Ipc, &ip);
+ }
+ }
+
+ // Happy procedure
+ IPCProcessL3Events(p->Ipc);
+
+ // Packet of server to client direction
+ while (true)
+ {
+ BLOCK *b = IPCRecvIPv4(p->Ipc);
+ PPP_PACKET *pp;
+ PPP_PACKET tmp;
+ if (b == NULL)
+ {
+ break;
+ }
+
+ // Since receiving the IP packet, send it to the client by PPP
+ pp = &tmp;
+ pp->IsControl = false;
+ pp->Protocol = PPP_PROTOCOL_IP;
+ pp->Lcp = NULL;
+ pp->Data = b->Buf;
+ pp->DataSize = b->Size;
+
+ PPPSendPacketEx(p, pp, true);
+
+ FreePPPPacketEx(pp, true);
+ Free(b);
+ }
+
+ FlushTubeFlushList(p->FlushList);
+
+ // PPP Echo Request
+ if (p->NextEchoSendTime == 0 || now >= p->NextEchoSendTime)
+ {
+ p->NextEchoSendTime = now + (UINT64)PPP_ECHO_SEND_INTERVAL;
+ AddInterrupt(p->Ipc->Interrupt, p->NextEchoSendTime);
+
+ PPPSendEchoRequest(p);
+ }
+
+ // Terminate if any tube is disconnected
+ if (IsTubeConnected(p->TubeRecv) == false || IsTubeConnected(p->TubeSend) == false)
+ {
+ // Higher-level protocol is disconnected
+ PPPLog(p, "LP_UPPER_PROTOCOL_DISCONNECTED", p->Postfix);
+ break;
+ }
+ if (IsIPCConnected(p->Ipc) == false)
+ {
+ // IPC VPN session is disconnected
+ PPPLog(p, "LP_VPN_SESSION_TERMINATED");
+ break;
+ }
+
+ // Time-out inspection
+ if ((p->LastRecvTime + (UINT64)PPP_DATA_TIMEOUT) <= now)
+ {
+ // Communication time-out occurs
+ PPPLog(p, "LP_DATA_TIMEOUT");
+ break;
+ }
+
+ // Terminate if the PPP disconnected
+ if (p->IsTerminateReceived)
+ {
+ PPPLog(p, "LP_NORMAL_TERMINATE");
+ break;
+ }
+
+ // Wait until the next packet arrives
+ tubes[0] = p->TubeRecv;
+ tubes[1] = p->Ipc->Sock->RecvTube;
+
+ r = GetNextIntervalForInterrupt(p->Ipc->Interrupt);
+ WaitForTubes(tubes, 2, MIN(r, 1234));
+ }
+
+ // Disconnected normally
+ PPPLog(p, "LP_DISCONNECTED");
+ }
+
+ if (p->DhcpAllocated)
+ {
+ // If any address is assigned from the DHCP, release it
+ IP ip;
+ char tmp[MAX_SIZE];
+
+ UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
+
+ IPToStr(tmp, sizeof(tmp), &ip);
+ Debug("Releasing IP Address from DHCP Server %s...\n", tmp);
+
+ IPCDhcpFreeIP(p->Ipc, &ip);
+ IPCProcessL3Events(p->Ipc);
+
+ SleepThread(300);
+ }
+
+LABEL_CLEANUP:
+
+ if (established == false)
+ {
+ // Disconnected Abnormally
+ PPPLog(p, "LP_DISCONNECTED_ABNORMAL");
+ }
+
+ // Disconnection process
+ PPPCleanTerminate(p);
+
+ // Release the memory
+ for (i = 0;i < LIST_NUM(p->RecvPacketList);i++)
+ {
+ PPP_PACKET *pp = LIST_DATA(p->RecvPacketList, i);
+
+ FreePPPPacket(pp);
+ }
+ ReleaseList(p->RecvPacketList);
+
+ // Release the PPP session
+ FreePPPSession(p);
+}
+
+// Disconnect the PPP cleanly
+void PPPCleanTerminate(PPP_SESSION *p)
+{
+ PPP_PACKET *pp;
+ PPP_PACKET *res;
+ UINT64 giveup_tick = Tick64() + (UINT64)PPP_TERMINATE_TIMEOUT;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Send a Terminate Request
+ pp = ZeroMalloc(sizeof(PPP_PACKET));
+ pp->IsControl = true;
+ pp->Protocol = PPP_PROTOCOL_LCP;
+ pp->Lcp = NewPPPLCP(PPP_LCP_CODE_TERMINATE_REQ, p->NextId++);
+ Debug("PPP: Terminate Request is Sent.\n");
+ if (PPPSendPacket(p, pp) == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Wait for Terminate ACK
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval;
+
+ if (now >= giveup_tick)
+ {
+ break;
+ }
+
+ while (true)
+ {
+ if (IsTubeConnected(p->TubeRecv) == false)
+ {
+ break;
+ }
+
+ res = PPPRecvPacket(p, true);
+
+ if (res == NULL)
+ {
+ break;
+ }
+
+ if (res->IsControl && res->Protocol == PPP_PROTOCOL_LCP && res->Lcp->Code == PPP_LCP_CODE_TERMINATE_ACK)
+ {
+ Debug("PPP: Terminate ACK is Received.\n");
+ FreePPPPacket(res);
+ goto LABEL_CLEANUP;
+ }
+
+ FreePPPPacket(res);
+ }
+
+ interval = (UINT)(giveup_tick - now);
+
+ Wait(p->TubeRecv->Event, interval);
+ }
+
+LABEL_CLEANUP:
+ FreePPPPacket(pp);
+}
+
+// Wait until all pending LCP option are determined
+bool PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION *p)
+{
+ USHORT received_protocol = 0;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ PPPRecvResponsePacket(p, NULL, PPP_PROTOCOL_LCP, &received_protocol, true);
+
+ return p->ClientLCPOptionDetermined;
+}
+
+// Continue the processing of the request packet protocol on the current PPP
+USHORT PPPContinueCurrentProtocolRequestListening(PPP_SESSION *p, USHORT protocol)
+{
+ USHORT received_protocol = 0;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ PPPRecvResponsePacket(p, NULL, protocol, &received_protocol, false);
+
+ return received_protocol;
+}
+
+// Send the PPP Echo Request
+void PPPSendEchoRequest(PPP_SESSION *p)
+{
+ PPP_PACKET *pp;
+ char echo_data[]= "\0\0\0\0Aho Baka Manuke";
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ pp = ZeroMalloc(sizeof(PPP_PACKET));
+ pp->Protocol = PPP_PROTOCOL_LCP;
+ pp->IsControl = true;
+ pp->Lcp = NewPPPLCP(PPP_LCP_CODE_ECHO_REQUEST, p->NextId++);
+
+ pp->Lcp->Data = Clone(echo_data, sizeof(echo_data));
+ pp->Lcp->DataSize = sizeof(echo_data);
+
+ PPPSendPacket(p, pp);
+
+ FreePPPPacket(pp);
+}
+
+// Send a request packet in the PPP
+bool PPPSendRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c)
+{
+ PPP_PACKET *pp;
+ PPP_PACKET *pp2;
+ bool ret = false;
+ // Validate arguments
+ if (p == NULL || c == NULL)
+ {
+ return false;
+ }
+
+ pp = ZeroMalloc(sizeof(PPP_PACKET));
+ pp->Protocol = protocol;
+ pp->IsControl = true;
+ pp->Lcp = c;
+ pp->Lcp->Id = p->NextId++;
+
+ // Send the PPP packet
+ if (PPPSendPacket(p, pp) == false)
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Receive a corresponding PPP packet
+ pp2 = PPPRecvResponsePacket(p, pp, 0, NULL, false);
+
+ if (pp2 != NULL)
+ {
+ if (protocol == PPP_PROTOCOL_LCP || protocol == PPP_PROTOCOL_IPCP)
+ {
+ if (!PPP_LCP_CODE_IS_NEGATIVE(pp2->Lcp->Code))
+ {
+ // A positive response is received
+ ret = true;
+ }
+ }
+ }
+
+ FreePPPPacket(pp2);
+ Free(pp);
+
+ return ret;
+
+LABEL_ERROR:
+ Free(pp);
+ return false;
+}
+
+// Check whether the Virtual HUB with the specified name exist?
+bool IsHubExistsWithLock(CEDAR *cedar, char *hubname)
+{
+ bool ret = false;
+ // Validate arguments
+ if (cedar == NULL || hubname == NULL)
+ {
+ return false;
+ }
+
+ LockList(cedar->HubList);
+ {
+ ret = IsHub(cedar, hubname);
+ }
+ UnlockList(cedar->HubList);
+
+ return ret;
+}
+
+// Separate into the user name and the Virtual HUB name by analyzing the string
+bool PPPParseUsername(CEDAR *cedar, char *src_username, ETHERIP_ID *dst)
+{
+ UINT i, len, last_at, first_en;
+ char token1[MAX_SIZE]; // username
+ char token2[MAX_SIZE]; // hub_name
+ char src[MAX_SIZE];
+ // Validate arguments
+ Zero(dst, sizeof(ETHERIP_ID));
+ if (cedar == NULL || src == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(src, sizeof(src), src_username);
+ Trim(src);
+
+ // Search for the first "\\" in the string
+ len = StrLen(src);
+
+ first_en = SearchStrEx(src, "\\", 0, true);
+
+ if (first_en != INFINITE && first_en >= 1 && (first_en < (len - 1)))
+ {
+ StrCpy(token1, sizeof(token1), src + first_en + 1);
+ StrCpy(token2, sizeof(token2), src);
+ token2[first_en] = 0;
+
+ // Confirm whether the hubname exists if the virtual HUB name is
+ // specified like as hubname\username
+ if (IsHubExistsWithLock(cedar, token2) == false)
+ {
+ // If the hubname does not exist, restore to the original name
+ StrCpy(token1, sizeof(token1), src);
+ ClearStr(token2, sizeof(token2));
+ }
+ }
+ else
+ {
+ // Search for the last "@" in the string
+ len = StrLen(src);
+ last_at = INFINITE;
+ for (i = 0;i < len;i++)
+ {
+ char c = src[i];
+
+ if (c == '@')
+ {
+ last_at = i;
+ }
+ }
+
+ Zero(token1, sizeof(token1));
+ Zero(token2, sizeof(token2));
+
+ if (last_at == INFINITE)
+ {
+ // "@" is not specified
+ StrCpy(token1, sizeof(token1), src);
+ }
+ else
+ {
+ // Split with last "@"
+ StrCpy(token1, sizeof(token1), src);
+ token1[last_at] = 0;
+
+ StrCpy(token2, sizeof(token2), src + last_at + 1);
+ }
+
+ // Check whether such Virtual HUB exists If the virtual HUB name is specified
+ if (IsEmptyStr(token2) == false)
+ {
+ if (IsHubExistsWithLock(cedar, token2) == false)
+ {
+ // Because the specified virtual HUB name doesn't exist, it's considered to be a part of the user name
+ StrCpy(token1, sizeof(token1), src);
+
+ ClearStr(token2, sizeof(token2));
+ }
+ }
+ }
+
+ if (IsEmptyStr(token2))
+ {
+ // Select the default Virtual HUB if the Virtual HUB name is not specified
+ StrCpy(token2, sizeof(token2), SERVER_DEFAULT_HUB_NAME);
+ if (cedar->Server != NULL && cedar->Server->IPsecServer != NULL)
+ {
+ Lock(cedar->Server->IPsecServer->LockSettings);
+ {
+ IPsecNormalizeServiceSetting(cedar->Server->IPsecServer);
+
+ StrCpy(token2, sizeof(token2), cedar->Server->IPsecServer->Services.L2TP_DefaultHub);
+ }
+ Unlock(cedar->Server->IPsecServer->LockSettings);
+ }
+
+ }
+
+ // Return the results
+ StrCpy(dst->HubName, sizeof(dst->HubName), token2);
+ StrCpy(dst->UserName, sizeof(dst->UserName), token1);
+
+ return true;
+}
+
+// Process the PPP request packet
+PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
+{
+ UINT i;
+ PPP_PACKET *ret = NULL;
+ UINT num_not_supported = 0;
+ UINT num_not_accepted = 0;
+ bool no_return_option_list = false;
+ UINT return_code = 0;
+ BUF *lcp_ret_data = NULL;
+ // Validate arguments
+ if (p == NULL || req == NULL || req->Lcp == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ t->IsAccepted = false;
+ t->IsSupported = false;
+ t->AltDataSize = 0;
+ Zero(t->AltData, sizeof(t->AltData));
+ }
+
+ // Process by scanning the specified option value
+ if (req->Protocol == PPP_PROTOCOL_LCP)
+ {
+ // LCP
+ if (req->Lcp == NULL)
+ {
+ return NULL;
+ }
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ switch (t->Type)
+ {
+ case PPP_LCP_OPTION_MRU:
+ // MRU
+ t->IsSupported = true;
+ if (t->DataSize == sizeof(USHORT))
+ {
+ UINT value = READ_USHORT(t->Data);
+ if (value < PPP_MRU_MIN || value > PPP_MRU_MAX)
+ {
+ t->IsAccepted = false;
+ value = MAKESURE(value, PPP_MRU_MIN, PPP_MRU_MAX);
+ WRITE_USHORT(t->AltData, value);
+ t->AltDataSize = sizeof(USHORT);
+ }
+ else
+ {
+ p->Mru1 = value;
+ Debug("PPP: Client set %u as MRU\n", p->Mru1);
+ t->IsAccepted = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if (req->Protocol == PPP_PROTOCOL_CHAP)
+ {
+ bool ok = false;
+ char ret_str[MAX_SIZE];
+
+ no_return_option_list = true;
+
+ if (p->Ipc == NULL)
+ {
+ // MS-CHAPv2
+ if (req->Lcp->DataSize >= 51)
+ {
+ BUF *b;
+
+ b = NewBuf();
+
+ WriteBuf(b, req->Lcp->Data, req->Lcp->DataSize);
+ SeekBuf(b, 0, 0);
+
+ if (ReadBufChar(b) == 49)
+ {
+ UCHAR client_response_buffer[49];
+ UCHAR *client_challenge_16;
+ UCHAR *client_response_24;
+ char username_tmp[MAX_SIZE];
+ IPC *ipc = NULL;
+ char id[MAX_SIZE];
+ char hub[MAX_SIZE];
+ char password[MAX_SIZE];
+ char server_challenge_hex[MAX_SIZE];
+ char client_challenge_hex[MAX_SIZE];
+ char client_response_hex[MAX_SIZE];
+ ETHERIP_ID d;
+ UINT error_code;
+
+ ReadBuf(b, client_response_buffer, 49);
+
+ Zero(username_tmp, sizeof(username_tmp));
+ ReadBuf(b, username_tmp, sizeof(username_tmp));
+
+ client_challenge_16 = client_response_buffer + 0;
+ client_response_24 = client_response_buffer + 16 + 8;
+
+ Copy(p->MsChapV2_ClientChallenge, client_challenge_16, 16);
+ Copy(p->MsChapV2_ClientResponse, client_response_24, 24);
+
+ Debug("MS-CHAPv2: id=%s\n", username_tmp);
+
+ Zero(id, sizeof(id));
+ Zero(hub, sizeof(hub));
+
+ // The user name is divided into the ID and the virtual HUB name
+ Zero(&d, sizeof(d));
+ PPPParseUsername(p->Cedar, username_tmp, &d);
+
+ StrCpy(id, sizeof(id), d.UserName);
+ StrCpy(hub, sizeof(hub), d.HubName);
+
+ // Convert the MS-CHAPv2 data to a password string
+ BinToStr(server_challenge_hex, sizeof(server_challenge_hex),
+ p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
+ BinToStr(client_challenge_hex, sizeof(client_challenge_hex),
+ p->MsChapV2_ClientChallenge, sizeof(p->MsChapV2_ClientChallenge));
+ BinToStr(client_response_hex, sizeof(client_response_hex),
+ p->MsChapV2_ClientResponse, sizeof(p->MsChapV2_ClientResponse));
+
+ Format(password, sizeof(password), "%s%s:%s:%s:%s",
+ IPC_PASSWORD_MSCHAPV2_TAG,
+ username_tmp,
+ server_challenge_hex,
+ client_challenge_hex,
+ client_response_hex);
+
+ // Attempt to connect with IPC
+ ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
+ &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
+ p->ClientHostname, p->CryptName, false, p->AdjustMss);
+
+ if (ipc != NULL)
+ {
+ p->Ipc = ipc;
+
+ Copy(p->MsChapV2_ServerResponse, ipc->MsChapV2_ServerResponse, 20);
+
+ ok = true;
+ }
+ else
+ {
+ switch (error_code)
+ {
+ default:
+ // Normal authentication error
+ p->MsChapV2_ErrorCode = 691;
+ break;
+
+ case ERR_MSCHAP2_PASSWORD_NEED_RESET:
+ // Authentication errors due to compatibility issues of the password
+ p->MsChapV2_ErrorCode = 942;
+ break;
+ }
+ }
+ }
+
+ FreeBuf(b);
+ }
+ }
+ else
+ {
+ // Return success for a request from the second time when it is successfully authenticated once
+ ok = true;
+ }
+
+ // Generate a response options string
+ if (ok == false)
+ {
+ // In the case of failure
+ char hex[MAX_SIZE];
+ BinToStr(hex, sizeof(hex), p->MsChapV2_ServerChallenge, 16);
+
+ Format(ret_str, sizeof(ret_str),
+ "E=%u R=0 C=%s V=3", p->MsChapV2_ErrorCode, hex);
+
+ return_code = PPP_CHAP_CODE_FAILURE;
+ }
+ else
+ {
+ // In the case of success
+ char hex[MAX_SIZE];
+ BinToStr(hex, sizeof(hex), p->MsChapV2_ServerResponse, 20);
+
+ Format(ret_str, sizeof(ret_str),
+ "S=%s", hex);
+
+ return_code = PPP_CHAP_CODE_SUCCESS;
+
+ p->AuthOk = true;
+ }
+
+ lcp_ret_data = NewBuf();
+ WriteBuf(lcp_ret_data, ret_str, StrLen(ret_str));
+ }
+ else if (req->Protocol == PPP_PROTOCOL_PAP)
+ {
+ UCHAR *data;
+ UINT size;
+ bool ok = false;
+
+ no_return_option_list = true;
+
+ if (p->Ipc == NULL)
+ {
+ // PAP
+
+ // Extract the ID and the password
+ data = req->Lcp->Data;
+ size = req->Lcp->DataSize;
+
+ if (size >= 1)
+ {
+ UCHAR len_id = data[0];
+ data++;
+ size--;
+
+ if (size >= len_id)
+ {
+ char username[256];
+ char password[256];
+
+ Zero(username, sizeof(username));
+ Zero(password, sizeof(password));
+
+ Copy(username, data, len_id);
+ data += len_id;
+ size -= len_id;
+
+ if (size >= 1)
+ {
+ UCHAR len_pass = data[0];
+ data++;
+ size--;
+
+ if (size >= len_pass)
+ {
+ IPC *ipc;
+ char id[MAX_SIZE];
+ char hub[MAX_SIZE];
+ ETHERIP_ID d;
+
+ Zero(id, sizeof(id));
+ Zero(hub, sizeof(hub));
+
+ Copy(password, data, len_pass);
+
+ Debug("PPP: id=%s, pw=%s\n", username, password);
+
+ // The user name is divided into the ID and the virtual HUB name
+ Zero(&d, sizeof(d));
+ PPPParseUsername(p->Cedar, username, &d);
+
+ StrCpy(id, sizeof(id), d.UserName);
+ StrCpy(hub, sizeof(hub), d.HubName);
+
+ if (IsEmptyStr(id) == false)
+ {
+ // Attempt to connect with IPC
+ UINT error_code;
+
+ ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
+ &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
+ p->ClientHostname, p->CryptName, false, p->AdjustMss);
+
+ if (ipc != NULL)
+ {
+ p->Ipc = ipc;
+ ok = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Return success for a request from the second time when it is successfully authenticated once
+ ok = true;
+ }
+
+ if (ok == false)
+ {
+ // Authentication failure
+ return_code = PPP_PAP_CODE_NAK;
+ }
+ else
+ {
+ // Authentication success
+ return_code = PPP_PAP_CODE_ACK;
+
+ p->AuthOk = true;
+ }
+ }
+ else if (req->Protocol == PPP_PROTOCOL_IPCP)
+ {
+ PPP_IPOPTION o;
+ // Get the IP options data from the request data
+ if (PPPGetIPOptionFromLCP(&o, req->Lcp))
+ {
+ PPP_IPOPTION res;
+ IP subnet;
+ IP gw;
+
+ if (IsZeroIP(&o.IpAddress) == false)
+ {
+ if (p->Ipc->Policy->DHCPForce == false)
+ {
+ if (p->DhcpAllocated == false)
+ {
+ if (p->UseStaticIPAddress == false)
+ {
+ DHCP_OPTION_LIST cao;
+
+ // The client specify an IP address
+ Zero(&cao, sizeof(cao));
+
+ cao.ClientAddress = IPToUINT(&o.IpAddress);
+
+ Copy(&p->ClientAddressOption, &cao, sizeof(cao));
+
+ p->UseStaticIPAddress = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ p->UseStaticIPAddress = false;
+ }
+
+ if (p->UseStaticIPAddress)
+ {
+ if (p->DhcpIpInformTried == false)
+ {
+ // Get additional information such as the subnet mask from the DHCP server
+ DHCP_OPTION_LIST cao;
+ IP client_ip;
+
+ IP subnet;
+ IP zero;
+
+ SetIP(&subnet, 255, 0, 0, 0);
+ Zero(&zero, sizeof(zero));
+
+ UINTToIP(&client_ip, p->ClientAddressOption.ClientAddress);
+
+ Zero(&cao, sizeof(cao));
+
+ IPCSetIPv4Parameters(p->Ipc, &client_ip, &subnet, &zero);
+
+ p->DhcpIpInformTried = true;
+
+ PPPLog(p, "LP_DHCP_INFORM_TRYING");
+
+ if (IPCDhcpRequestInformIP(p->Ipc, &cao, p->TubeRecv, &client_ip))
+ {
+ Debug("IPCDhcpRequestInformIP ok.\n");
+ Copy(&p->ClientAddressOption, &cao, sizeof(cao));
+ p->ClientAddressOption.ClientAddress = IPToUINT(&client_ip);
+
+ if (true)
+ {
+ char server_ip_str[64];
+ char subnet_str[64], defgw_str[64];
+ char dns1_str[64], dns2_str[64];
+ char wins1_str[64], wins2_str[64];
+
+ IPToStr32(server_ip_str, sizeof(server_ip_str), cao.ServerAddress);
+ IPToStr32(subnet_str, sizeof(subnet_str), cao.SubnetMask);
+ IPToStr32(defgw_str, sizeof(defgw_str), cao.Gateway);
+ IPToStr32(dns1_str, sizeof(dns1_str), cao.DnsServer);
+ IPToStr32(dns2_str, sizeof(dns2_str), cao.DnsServer2);
+ IPToStr32(wins1_str, sizeof(wins1_str), cao.WinsServer);
+ IPToStr32(wins2_str, sizeof(wins2_str), cao.WinsServer2);
+
+ PPPLog(p, "LP_DHCP_INFORM_OK",
+ subnet_str, defgw_str, cao.DomainName,
+ dns1_str, dns2_str, wins1_str, wins2_str,
+ server_ip_str);
+ }
+ }
+ else
+ {
+ Debug("IPCDhcpRequestInformIP failed.\n");
+
+ PPPLog(p, "LP_DHCP_INFORM_NG");
+ }
+
+ IPCSetIPv4Parameters(p->Ipc, &zero, &zero, &zero);
+ }
+ }
+ else
+ {
+ // Get an IP address from a DHCP server
+ if (p->DhcpIpAllocTried == false)
+ {
+ DHCP_OPTION_LIST cao;
+
+ Zero(&cao, sizeof(cao));
+ p->DhcpIpAllocTried = true;
+
+ PPPLog(p, "LP_DHCP_REQUEST_TRYING");
+
+ if (IPCDhcpAllocateIP(p->Ipc, &cao, p->TubeRecv))
+ {
+ UINT t;
+
+ Debug("IPCDhcpAllocateIP ok.\n");
+
+ // IP address has been determined
+ Copy(&p->ClientAddressOption, &cao, sizeof(cao));
+
+ p->DhcpAllocated = true;
+
+ // Determine the DHCP update interval
+ t = cao.LeaseTime;
+ if (t == 0)
+ {
+ t = 600;
+ }
+
+ t = t / 3;
+
+ if (t == 0)
+ {
+ t = 1;
+ }
+
+ p->DhcpRenewInterval = (UINT64)(t * 1000);
+ p->DhcpNextRenewTime = Tick64() + p->DhcpRenewInterval;
+
+ if (true)
+ {
+ char client_ip_str[64], server_ip_str[64];
+ char subnet_str[64], defgw_str[64];
+ char dns1_str[64], dns2_str[64];
+ char wins1_str[64], wins2_str[64];
+
+ IPToStr32(client_ip_str, sizeof(client_ip_str), cao.ClientAddress);
+ IPToStr32(server_ip_str, sizeof(server_ip_str), cao.ServerAddress);
+ IPToStr32(subnet_str, sizeof(subnet_str), cao.SubnetMask);
+ IPToStr32(defgw_str, sizeof(defgw_str), cao.Gateway);
+ IPToStr32(dns1_str, sizeof(dns1_str), cao.DnsServer);
+ IPToStr32(dns2_str, sizeof(dns2_str), cao.DnsServer2);
+ IPToStr32(wins1_str, sizeof(wins1_str), cao.WinsServer);
+ IPToStr32(wins2_str, sizeof(wins2_str), cao.WinsServer2);
+
+ PPPLog(p, "LP_DHCP_REQUEST_OK",
+ client_ip_str, subnet_str, defgw_str, cao.DomainName,
+ dns1_str, dns2_str, wins1_str, wins2_str,
+ server_ip_str, cao.LeaseTime);
+ }
+ }
+ else
+ {
+ Debug("IPCDhcpAllocateIP failed.\n");
+
+ PPPLog(p, "LP_DHCP_REQUEST_NG");
+ }
+ }
+ }
+
+ if (IsValidUnicastIPAddressUINT4(p->ClientAddressOption.ClientAddress) &&
+ p->ClientAddressOption.SubnetMask != 0)
+ {
+ // Success to determine the address
+ UINTToIP(&subnet, p->ClientAddressOption.SubnetMask);
+ UINTToIP(&gw, p->ClientAddressOption.Gateway);
+
+ Zero(&res, sizeof(res));
+ UINTToIP(&res.IpAddress, p->ClientAddressOption.ClientAddress);
+ UINTToIP(&res.DnsServer1, p->ClientAddressOption.DnsServer);
+ UINTToIP(&res.DnsServer2, p->ClientAddressOption.DnsServer2);
+ UINTToIP(&res.WinsServer1, p->ClientAddressOption.WinsServer);
+ UINTToIP(&res.WinsServer2, p->ClientAddressOption.WinsServer2);
+
+ if (IPCSetIPv4Parameters(p->Ipc, &res.IpAddress, &subnet, &gw))
+ {
+ char client_ip_str[64];
+ char subnet_str[64], defgw_str[64];
+ char dns1_str[64], dns2_str[64];
+ char wins1_str[64], wins2_str[64];
+
+ // IPv4 parameters have been set for the first time
+ Debug("Param First Set.\n");
+
+ IPToStr(client_ip_str, sizeof(client_ip_str), &res.IpAddress);
+ IPToStr(subnet_str, sizeof(subnet_str), &subnet);
+ IPToStr(defgw_str, sizeof(defgw_str), &gw);
+ IPToStr(dns1_str, sizeof(dns1_str), &res.DnsServer1);
+ IPToStr(dns2_str, sizeof(dns2_str), &res.DnsServer2);
+ IPToStr(wins1_str, sizeof(wins1_str), &res.WinsServer1);
+ IPToStr(wins2_str, sizeof(wins2_str), &res.WinsServer2);
+
+ PPPLog(p, "LP_SET_IPV4_PARAM", client_ip_str, subnet_str,
+ defgw_str, dns1_str, dns2_str, wins1_str, wins2_str);
+ }
+
+ PPPSetIPOptionToLCP(&res, req->Lcp, true);
+ }
+ else
+ {
+ // Failed to determine the address
+ Debug("IP Address Determination Failed.\n");
+
+ Zero(&res, sizeof(res));
+
+ PPPSetIPOptionToLCP(&res, req->Lcp, true);
+ }
+ }
+ }
+
+ // Assemble the LCP response packet based on the results
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ if (t->IsSupported == false)
+ {
+ num_not_supported++;
+ }
+
+ if (t->IsAccepted == false)
+ {
+ num_not_accepted++;
+ }
+ }
+
+ // Create a PPP response packet
+ ret = ZeroMalloc(sizeof(PPP_PACKET));
+ ret->IsControl = true;
+ ret->Protocol = req->Protocol;
+
+ if (no_return_option_list == false)
+ {
+ // Response by attaching an optional list
+ if (num_not_supported >= 1)
+ {
+ // Return a Reject if there are unsupported parameters
+ ret->Lcp = NewPPPLCP(PPP_LCP_CODE_REJECT, req->Lcp->Id);
+
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ if (t->IsSupported == false)
+ {
+ // Attach the original option value as is
+ Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->Data, t->DataSize));
+ }
+ }
+ }
+ else if (num_not_accepted >= 1)
+ {
+ // Return a NAK if there are any unacceptable parameter
+ // even that all parameters are supported
+ ret->Lcp = NewPPPLCP(PPP_LCP_CODE_NAK, req->Lcp->Id);
+
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ if (t->IsAccepted == false)
+ {
+ // Replace the original option value with an acceptable value
+ Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->AltData, t->AltDataSize));
+ }
+ }
+ }
+ else
+ {
+ // Return an ACK if all parameters are accepted
+ ret->Lcp = NewPPPLCP(PPP_LCP_CODE_ACK, req->Lcp->Id);
+
+ for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
+
+ // Attach the original option value as is
+ Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->Data, t->DataSize));
+ }
+
+ if (req->Protocol == PPP_PROTOCOL_LCP)
+ {
+ p->ClientLCPOptionDetermined = true;
+ }
+ }
+ }
+ else
+ {
+ // Response without attaching a list of options
+ ret->Lcp = NewPPPLCP(return_code, req->Lcp->Id);
+
+ if (lcp_ret_data != NULL && lcp_ret_data->Size >= 1)
+ {
+ ret->Lcp->Data = Clone(lcp_ret_data->Buf, lcp_ret_data->Size);
+ ret->Lcp->DataSize = lcp_ret_data->Size;
+ }
+ }
+
+ if (lcp_ret_data != NULL)
+ {
+ FreeBuf(lcp_ret_data);
+ }
+
+ return ret;
+}
+
+// Set the IP options of PPP to LCP
+bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify)
+{
+ bool ret = false;
+ // Validate arguments
+ if (c == NULL || o == NULL)
+ {
+ return false;
+ }
+
+ ret = PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_IP, &o->IpAddress, only_modify);
+
+ PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_DNS1, &o->DnsServer1, only_modify);
+ PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_DNS2, &o->DnsServer2, only_modify);
+ PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_WINS1, &o->WinsServer1, only_modify);
+ PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_WINS2, &o->WinsServer2, only_modify);
+
+ return ret;
+}
+
+// Get the IP options of PPP from LCP
+bool PPPGetIPOptionFromLCP(PPP_IPOPTION *o, PPP_LCP *c)
+{
+ bool ret;
+ // Validate arguments
+ if (c == NULL || o == NULL)
+ {
+ return false;
+ }
+
+ Zero(o, sizeof(PPP_IPOPTION));
+
+ ret = PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_IP, &o->IpAddress);
+
+ PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_DNS1, &o->DnsServer1);
+ PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_DNS2, &o->DnsServer2);
+ PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_WINS1, &o->WinsServer1);
+ PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_WINS2, &o->WinsServer2);
+
+ return ret;
+}
+
+// Set the IP address data to the option list of the LCP
+bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify)
+{
+ IP ip2;
+ UINT ui;
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ ui = IPToUINT(ip);
+
+ if (PPPGetIPAddressValueFromLCP(c, type, &ip2))
+ {
+ PPP_OPTION *opt;
+ opt = GetOptionValue(c, type);
+
+ if (opt != NULL)
+ {
+ if (IsZeroIP(ip) == false)
+ {
+ if (CmpIpAddr(&ip2, ip) == 0)
+ {
+ // No change
+ opt->IsAccepted = true;
+ opt->IsSupported = true;
+ }
+ else
+ {
+ // Changed
+ opt->IsAccepted = false;
+ opt->IsSupported = true;
+ opt->AltDataSize = 4;
+ Copy(opt->AltData, &ui, 4);
+ }
+ }
+ else
+ {
+ // The parameter itself is not supported
+ // (if the IP address is 0.0.0.0)
+ opt->IsSupported = false;
+ opt->IsAccepted = false;
+ }
+ }
+
+ return true;
+ }
+ else
+ {
+ if (IsZeroIP(ip) == false)
+ {
+ // Add as a new item
+ if (only_modify != false)
+ {
+ return false;
+ }
+ else
+ {
+ PPP_OPTION *opt2 = NewPPPOption(type, &ui, 4);
+ opt2->IsAccepted = opt2->IsSupported = true;
+
+ Add(c->OptionList, opt2);
+
+ return true;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
+
+// Get the IP address data from the option list of the LCP
+bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip)
+{
+ PPP_OPTION *opt;
+ UINT ui;
+ // Validate arguments
+ if (c == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ opt = GetOptionValue(c, type);
+ if (opt == NULL)
+ {
+ return false;
+ }
+
+ if (opt->DataSize != 4)
+ {
+ return false;
+ }
+
+ opt->IsSupported = true;
+
+ ui = *((UINT *)opt->Data);
+
+ UINTToIP(ip, ui);
+
+ return true;
+}
+
+// Process corresponding to the incoming request while receiving a PPP packet corresponding to the transmitted request.
+// (If req == NULL, process on that protocol while the protocol specified in expected_protocol have received.
+//If other protocols has arrived, without further processing, and then store that packet in the session context once,
+// return NULL by setting the received_protocol.)
+PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked)
+{
+ UINT64 giveup_tick = Tick64() + (UINT64)PPP_PACKET_RECV_TIMEOUT;
+ UINT64 next_resend = Tick64() + (UINT64)PPP_PACKET_RESEND_INTERVAL;
+ PPP_PACKET *ret = NULL;
+ USHORT tmp_us = 0;
+ // Validate arguments
+ if (p == NULL || req != NULL && req->Lcp == NULL)
+ {
+ return NULL;
+ }
+
+ if (received_protocol == NULL)
+ {
+ received_protocol = &tmp_us;
+ }
+
+ if (req != NULL)
+ {
+ expected_protocol = req->Protocol;
+ }
+
+ *received_protocol = 0;
+
+ // Receive the next packet (Retransmission repeatedly the last packet until the reception is completed)
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval;
+
+ if (IsTubeConnected(p->TubeRecv) == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ PPP_PACKET *pp;
+ PPP_PACKET *response;
+
+ if (p->LastStoredPacket != NULL)
+ {
+ pp = p->LastStoredPacket;
+ p->LastStoredPacket = NULL;
+ }
+ else
+ {
+ pp = PPPRecvPacketWithLowLayerProcessing(p, true);
+ }
+
+ if (pp == NULL)
+ {
+ break;
+ }
+
+ if (req != NULL)
+ {
+ // Determine whether the packet is corresponding to the request that was sent at the last
+ if (pp->IsControl && pp->Protocol == req->Protocol && pp->Lcp->Id == req->Lcp->Id &&
+ PPP_CODE_IS_RESPONSE(pp->Protocol, pp->Lcp->Code))
+ {
+ return pp;
+ }
+ }
+
+ // Return a response immediately without processing if a protocol other than the expected received
+ if ((pp->IsControl && pp->Protocol != expected_protocol) || pp->IsControl == false)
+ {
+ if (PPP_IS_SUPPORTED_PROTOCOL(pp->Protocol))
+ {
+ // This is another supported protocol
+ // Store this packet
+ PPPStoreLastPacket(p, pp);
+
+ *received_protocol = pp->Protocol;
+ return NULL;
+ }
+ else
+ {
+ // Unsupported protocol
+ Debug("Unsupported Protocol: 0x%x\n", pp->Protocol);
+ FreePPPPacket(pp);
+
+ return NULL;
+ }
+ }
+
+ if (pp->IsControl && PPP_CODE_IS_REQUEST(pp->Protocol, pp->Lcp->Code))
+ {
+ // Process when the received packet is a request packet
+ response = PPPProcessRequestPacket(p, pp);
+ FreePPPPacket(pp);
+
+ if (response == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ bool is_pap_and_disconnect_now = false;
+ bool is_chap_and_disconnect_now = false;
+
+ if (PPPSendPacket(p, response) == false)
+ {
+ FreePPPPacket(response);
+ return NULL;
+ }
+
+ if (response->Protocol == PPP_PROTOCOL_PAP && response->IsControl &&
+ response->Lcp->Code != PPP_PAP_CODE_ACK)
+ {
+ is_pap_and_disconnect_now = true;
+ }
+
+ if (response->Protocol == PPP_PROTOCOL_CHAP && response->IsControl &&
+ response->Lcp->Code == PPP_CHAP_CODE_FAILURE)
+ {
+ is_chap_and_disconnect_now = true;
+ }
+
+ FreePPPPacket(response);
+
+ if (is_pap_and_disconnect_now)
+ {
+ // Disconnect immediately if user authentication fails at least once in the PAP authentication protocol
+ Debug("Disconnecting because PAP failed.\n");
+ SleepThread(300);
+ return NULL;
+ }
+
+ if (is_chap_and_disconnect_now)
+ {
+ // Disconnect immediately if it fails to user authentication at least once in the CHAP authentication protocol
+ Debug("Disconnecting because CHAP failed.\n");
+ SleepThread(300);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ // Ignore in the case of the other packets
+ FreePPPPacket(pp);
+ }
+ }
+
+ // Packet retransmission
+ if (req != NULL)
+ {
+ if (now >= next_resend)
+ {
+ next_resend = now + PPP_PACKET_RESEND_INTERVAL;
+
+ if (PPPSendPacket(p, req) == false)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if (req == NULL)
+ {
+ giveup_tick = now + (UINT64)PPP_PACKET_RECV_TIMEOUT;
+ }
+
+ // Time-out decision
+ if (now >= giveup_tick)
+ {
+ PPPLog(p, "LP_CONTROL_TIMEOUT");
+ return NULL;
+ }
+
+ // Wait
+ if (req != NULL)
+ {
+ interval = MIN((UINT)(giveup_tick - now), (UINT)(next_resend - now));
+ }
+ else
+ {
+ interval = (UINT)(giveup_tick - now);
+ }
+
+ if (finish_when_all_lcp_acked && p->ClientLCPOptionDetermined)
+ {
+ return NULL;
+ }
+
+ Wait(p->TubeRecv->Event, interval);
+ }
+}
+
+// Store the last packet in the session (to be read the next time)
+void PPPStoreLastPacket(PPP_SESSION *p, PPP_PACKET *pp)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->LastStoredPacket != NULL)
+ {
+ FreePPPPacket(p->LastStoredPacket);
+ }
+
+ p->LastStoredPacket = pp;
+}
+
+// Receive a PPP communication packet
+PPP_PACKET *PPPRecvPacketForCommunication(PPP_SESSION *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ if (p->LastStoredPacket != NULL)
+ {
+ PPP_PACKET *pp = p->LastStoredPacket;
+ p->LastStoredPacket = NULL;
+ return pp;
+ }
+
+ return PPPRecvPacketWithLowLayerProcessing(p, true);
+}
+
+// Receive a PPP packet (Also performs low layer processing)
+PPP_PACKET *PPPRecvPacketWithLowLayerProcessing(PPP_SESSION *p, bool async)
+{
+ PPP_PACKET *pp = NULL;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+LABEL_LOOP:
+ pp = PPPRecvPacket(p, async);
+ if (pp == NULL)
+ {
+ return NULL;
+ }
+
+ if (PPP_IS_SUPPORTED_PROTOCOL(pp->Protocol) == false)
+ {
+ // Unsupported algorithm
+ PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
+ BUF *buf;
+ UCHAR c;
+ USHORT us;
+
+ pp2->Protocol = PPP_PROTOCOL_LCP;
+ pp2->IsControl = false;
+
+ buf = NewBuf();
+
+ // Code
+ c = PPP_LCP_CODE_PROTOCOL_REJECT;
+ WriteBuf(buf, &c, 1);
+
+ // ID
+ c = p->NextId++;
+ WriteBuf(buf, &c, 1);
+
+ // Length
+ us = Endian16(pp->DataSize + 6);
+ WriteBuf(buf, &us, 2);
+
+ // Rejected Protocol
+ us = Endian16(pp->Protocol);
+ WriteBuf(buf, &us, 2);
+
+ // Packet Data
+ WriteBuf(buf, pp->Data, pp->DataSize);
+
+ pp2->Data = Clone(buf->Buf, buf->Size);
+ pp2->DataSize = buf->Size;
+
+ FreePPPPacket(pp);
+
+ FreeBuf(buf);
+
+ if (PPPSendPacket(p, pp2) == false)
+ {
+ FreePPPPacket(pp2);
+ return NULL;
+ }
+
+ FreePPPPacket(pp2);
+ goto LABEL_LOOP;
+ }
+
+ if (pp->IsControl && pp->Protocol == PPP_PROTOCOL_LCP)
+ {
+ if (pp->Lcp->Code == PPP_LCP_CODE_ECHO_REQUEST)
+ {
+ // Immediately return the echo response to the echo request
+ PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
+
+ pp2->IsControl = true;
+ pp2->Protocol = PPP_PROTOCOL_LCP;
+ pp2->Lcp = NewPPPLCP(PPP_LCP_CODE_ECHO_RESPONSE, pp->Lcp->Id);
+ pp2->Lcp->Data = Clone(pp->Lcp->Data, pp->Lcp->DataSize);
+ pp2->Lcp->DataSize = pp->Lcp->DataSize;
+
+ FreePPPPacket(pp);
+
+ if (PPPSendPacket(p, pp2) == false)
+ {
+ FreePPPPacket(pp2);
+ return NULL;
+ }
+
+ FreePPPPacket(pp2);
+ goto LABEL_LOOP;
+ }
+ else if (pp->Lcp->Code == PPP_LCP_CODE_ECHO_RESPONSE)
+ {
+ // Ignore the Echo response packet
+ FreePPPPacket(pp);
+ goto LABEL_LOOP;
+ }
+ else if (pp->Lcp->Code == PPP_LCP_CODE_DROP)
+ {
+ // Ignore the Drop packet
+ FreePPPPacket(pp);
+ goto LABEL_LOOP;
+ }
+ else if (pp->Lcp->Code == PPP_LCP_CODE_IDENTIFICATION)
+ {
+ // Ignore the Identification packet
+ FreePPPPacket(pp);
+ WHERE;
+ goto LABEL_LOOP;
+ }
+ else if (pp->Lcp->Code == PPP_LCP_CODE_TERMINATE_REQ)
+ {
+ // Return the Terminate ACK If a Terminate Request has been received
+ PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
+
+ pp2->IsControl = true;
+ pp2->Protocol = PPP_PROTOCOL_LCP;
+ pp2->Lcp = NewPPPLCP(PPP_LCP_CODE_TERMINATE_ACK, pp->Lcp->Id);
+ pp2->Lcp->Data = Clone(pp->Lcp->Data, pp->Lcp->DataSize);
+ pp2->Lcp->DataSize = pp->Lcp->DataSize;
+
+ p->IsTerminateReceived = true;
+
+ FreePPPPacket(pp);
+
+ if (PPPSendPacket(p, pp2) == false)
+ {
+ FreePPPPacket(pp2);
+ return NULL;
+ }
+
+ SleepThread(100);
+
+ FreePPPPacket(pp2);
+ goto LABEL_LOOP;
+ }
+ }
+
+ return pp;
+}
+
+// Receive a PPP packet
+PPP_PACKET *PPPRecvPacket(PPP_SESSION *p, bool async)
+{
+ TUBEDATA *d;
+ PPP_PACKET *pp;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+LABEL_LOOP:
+
+ if (async == false)
+ {
+ d = TubeRecvSync(p->TubeRecv, PPP_PACKET_RECV_TIMEOUT);
+ }
+ else
+ {
+ d = TubeRecvAsync(p->TubeRecv);
+ }
+
+ if (d == NULL)
+ {
+ return NULL;
+ }
+
+ pp = ParsePPPPacket(d->Data, d->DataSize);
+ FreeTubeData(d);
+
+ if (pp == NULL)
+ {
+ // A broken packet is received
+ goto LABEL_LOOP;
+ }
+
+ p->LastRecvTime = Tick64();
+
+ return pp;
+}
+
+// Send the PPP packet
+bool PPPSendPacket(PPP_SESSION *p, PPP_PACKET *pp)
+{
+ return PPPSendPacketEx(p, pp, false);
+}
+bool PPPSendPacketEx(PPP_SESSION *p, PPP_PACKET *pp, bool no_flush)
+{
+ bool ret = false;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || pp == NULL)
+ {
+ return false;
+ }
+
+ b = BuildPPPPacketData(pp);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = TubeSendEx(p->TubeSend, b->Buf, b->Size, NULL, no_flush);
+
+ if (no_flush)
+ {
+ AddTubeToFlushList(p->FlushList, p->TubeSend);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Create a new PPP options
+PPP_OPTION *NewPPPOption(UCHAR type, void *data, UINT size)
+{
+ PPP_OPTION *o;
+ // Validate arguments
+ if (size != 0 && data == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(PPP_OPTION));
+
+ o->Type = type;
+ Copy(o->Data, data, size);
+ o->DataSize = size;
+
+ return o;
+}
+
+// Analyse the PPP packet
+PPP_PACKET *ParsePPPPacket(void *data, UINT size)
+{
+ PPP_PACKET *pp;
+ UCHAR *buf;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ pp = ZeroMalloc(sizeof(PPP_PACKET));
+
+ buf = (UCHAR *)data;
+
+ // Address
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ if (buf[0] != 0xff)
+ {
+ goto LABEL_ERROR;
+ }
+ size--;
+ buf++;
+
+ // Control
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ if (buf[0] != 0x03)
+ {
+ goto LABEL_ERROR;
+ }
+ size--;
+ buf++;
+
+ // Protocol
+ if (size < 2)
+ {
+ goto LABEL_ERROR;
+ }
+ pp->Protocol = READ_USHORT(buf);
+ size -= 2;
+ buf += 2;
+
+ if (pp->Protocol == PPP_PROTOCOL_LCP || pp->Protocol == PPP_PROTOCOL_PAP || pp->Protocol == PPP_PROTOCOL_CHAP || pp->Protocol == PPP_PROTOCOL_IPCP)
+ {
+ pp->IsControl = true;
+ }
+
+ pp->Data = Clone(buf, size);
+ pp->DataSize = size;
+
+ if (pp->IsControl)
+ {
+ pp->Lcp = ParseLCP(pp->Protocol, pp->Data, pp->DataSize);
+ if (pp->Lcp == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+ }
+
+ return pp;
+
+LABEL_ERROR:
+ FreePPPPacket(pp);
+ return NULL;
+}
+
+// Build a PPP packet data
+BUF *BuildPPPPacketData(PPP_PACKET *pp)
+{
+ BUF *ret;
+ UCHAR c;
+ USHORT us;
+ // Validate arguments
+ if (pp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewBuf();
+
+ // Address
+ c = 0xff;
+ WriteBuf(ret, &c, 1);
+
+ // Control
+ c = 0x03;
+ WriteBuf(ret, &c, 1);
+
+ // Protocol
+ us = Endian16(pp->Protocol);
+ WriteBuf(ret, &us, 2);
+
+ if (pp->IsControl)
+ {
+ // LCP
+ BUF *b = BuildLCPData(pp->Lcp);
+
+ WriteBufBuf(ret, b);
+
+ FreeBuf(b);
+ }
+ else
+ {
+ // Data
+ WriteBuf(ret, pp->Data, pp->DataSize);
+ }
+
+ SeekBuf(ret, 0, 0);
+
+ return ret;
+}
+
+// Build the LCP packet data
+BUF *BuildLCPData(PPP_LCP *c)
+{
+ BUF *b;
+ UCHAR zero = 0;
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Code
+ WriteBuf(b, &c->Code, 1);
+
+ // ID
+ WriteBuf(b, &c->Id, 1);
+
+ // Length (to be updated later)
+ zero = 0;
+ WriteBuf(b, &zero, 1);
+ WriteBuf(b, &zero, 1);
+
+ if (c->Data == NULL)
+ {
+ // Option List
+ for (i = 0;i < LIST_NUM(c->OptionList);i++)
+ {
+ PPP_OPTION *o = LIST_DATA(c->OptionList, i);
+ UCHAR sz = o->DataSize + 2;
+
+ WriteBuf(b, &o->Type, 1);
+ WriteBuf(b, &sz, 1);
+
+ WriteBuf(b, o->Data, o->DataSize);
+ }
+ }
+ else
+ {
+ // Data
+ WriteBuf(b, c->Data, c->DataSize);
+ }
+
+ SeekBuf(b, 0, 0);
+
+ // Update Length
+ WRITE_USHORT(((UCHAR *)b->Buf) + 2, b->Size);
+
+ return b;
+}
+
+// Analyse the LCP data
+PPP_LCP *ParseLCP(USHORT protocol, void *data, UINT size)
+{
+ UCHAR *buf;
+ PPP_LCP *c;
+ USHORT len;
+ bool has_option_list = false;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ buf = (UCHAR *)data;
+ c = ZeroMalloc(sizeof(PPP_LCP));
+
+ c->OptionList = NewListFast(NULL);
+
+ // Code
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ c->Code = buf[0];
+ buf++;
+ size--;
+
+ // ID
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ c->Id = buf[0];
+ buf++;
+ size--;
+
+ // Length
+ if (size < 2)
+ {
+ goto LABEL_ERROR;
+ }
+ len = READ_USHORT(buf);
+ if (len < 4)
+ {
+ goto LABEL_ERROR;
+ }
+ len -= 4;
+ buf += 2;
+ size -= 2;
+
+ // Options or Data
+ if (size < len)
+ {
+ goto LABEL_ERROR;
+ }
+
+ has_option_list = PPP_CODE_IS_WITH_OPTION_LIST(protocol, c->Code);
+
+ if (has_option_list == false)
+ {
+ c->Data = Clone(buf, size);
+ c->DataSize = size;
+ }
+ else
+ {
+ // Option List
+ while (len >= 1)
+ {
+ PPP_OPTION o;
+
+ Zero(&o, sizeof(o));
+
+ // Type
+ if (len < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ o.Type = buf[0];
+ buf++;
+ len--;
+
+ // Length
+ if (len < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ o.DataSize = buf[0];
+ if (o.DataSize < 2)
+ {
+ goto LABEL_ERROR;
+ }
+ o.DataSize -= 2;
+ buf++;
+ len--;
+
+ // Data
+ if (len < o.DataSize)
+ {
+ goto LABEL_ERROR;
+ }
+ Copy(o.Data, buf, o.DataSize);
+ buf += o.DataSize;
+ len -= o.DataSize;
+
+ Add(c->OptionList, Clone(&o, sizeof(o)));
+ }
+ }
+
+ return c;
+
+LABEL_ERROR:
+ FreePPPLCP(c);
+ return NULL;
+}
+
+// Release the PPP packet
+void FreePPPPacket(PPP_PACKET *pp)
+{
+ FreePPPPacketEx(pp, false);
+}
+void FreePPPPacketEx(PPP_PACKET *pp, bool no_free_struct)
+{
+ // Validate arguments
+ if (pp == NULL)
+ {
+ return;
+ }
+
+ FreePPPLCP(pp->Lcp);
+
+ Free(pp->Data);
+
+ if (no_free_struct == false)
+ {
+ Free(pp);
+ }
+}
+
+// Release the PPP session
+void FreePPPSession(PPP_SESSION *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->TubeRecv != NULL)
+ {
+ // Record the PPP disconnect reason code for L2TP
+ p->TubeRecv->IntParam1 = p->DisconnectCauseCode;
+ p->TubeRecv->IntParam2 = p->DisconnectCauseDirection;
+ }
+
+ FreeTubeFlushList(p->FlushList);
+
+ TubeDisconnect(p->TubeRecv);
+ TubeDisconnect(p->TubeSend);
+
+ ReleaseCedar(p->Cedar);
+
+ ReleaseTube(p->TubeRecv);
+ ReleaseTube(p->TubeSend);
+
+ PPPStoreLastPacket(p, NULL);
+
+ if (p->Ipc != NULL)
+ {
+ FreeIPC(p->Ipc);
+ }
+
+ Free(p);
+}
+
+// Get the option value
+PPP_OPTION *GetOptionValue(PPP_LCP *c, UCHAR type)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(c->OptionList);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(c->OptionList, i);
+
+ if (t->Type == type)
+ {
+ return t;
+ }
+ }
+
+ return NULL;
+}
+
+// Create the LCP
+PPP_LCP *NewPPPLCP(UCHAR code, UCHAR id)
+{
+ PPP_LCP *c = ZeroMalloc(sizeof(PPP_LCP));
+
+ c->Code = code;
+ c->Id = id;
+ c->OptionList = NewListFast(NULL);
+
+ return c;
+}
+
+// Release the LCP
+void FreePPPLCP(PPP_LCP *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ FreePPPOptionList(c->OptionList);
+
+ Free(c->Data);
+
+ Free(c);
+}
+
+// Release the PPP options list
+void FreePPPOptionList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PPP_OPTION *t = LIST_DATA(o, i);
+
+ Free(t);
+ }
+
+ ReleaseList(o);
+}
+
+// Create a new PPP session
+THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss)
+{
+ PPP_SESSION *p;
+ THREAD *t;
+ // Validate arguments
+ if (cedar == NULL || client_ip == NULL || server_ip == NULL || send_tube == NULL || recv_tube == NULL)
+ {
+ return NULL;
+ }
+ if (IsEmptyStr(postfix))
+ {
+ postfix = "PPP";
+ }
+ if (IsEmptyStr(crypt_name))
+ {
+ crypt_name = "";
+ }
+ if (IsEmptyStr(client_software_name))
+ {
+ client_software_name = "PPP VPN Client";
+ }
+
+ // Data structure initialization
+ p = ZeroMalloc(sizeof(PPP_SESSION));
+
+ p->EnableMSCHAPv2 = true;
+ p->AuthProtocol = PPP_PROTOCOL_PAP;
+ p->MsChapV2_ErrorCode = 691;
+
+ p->Cedar = cedar;
+ AddRef(cedar->ref);
+
+ p->AdjustMss = adjust_mss;
+
+ StrCpy(p->CryptName, sizeof(p->CryptName), crypt_name);
+
+ Copy(&p->ClientIP, client_ip, sizeof(IP));
+ p->ClientPort = client_port;
+
+ Copy(&p->ServerIP, server_ip, sizeof(IP));
+ p->ServerPort = server_port;
+
+ p->TubeRecv = recv_tube;
+ p->TubeSend = send_tube;
+
+ AddRef(p->TubeRecv->Ref);
+ AddRef(p->TubeSend->Ref);
+
+ StrCpy(p->Postfix, sizeof(p->Postfix), postfix);
+ StrCpy(p->ClientSoftwareName, sizeof(p->ClientSoftwareName), client_software_name);
+
+ if (IsEmptyStr(client_hostname))
+ {
+ IPToStr(p->ClientHostname, sizeof(p->ClientHostname), client_ip);
+ }
+ else
+ {
+ StrCpy(p->ClientHostname, sizeof(p->ClientHostname), client_hostname);
+ }
+
+ p->FlushList = NewTubeFlushList();
+
+ // Thread creation
+ t = NewThread(PPPThread, p);
+
+ return t;
+}
+
+// Generate the NT hash of the password
+void GenerateNtPasswordHash(UCHAR *dst, char *password)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ UINT i, len;
+ // Validate arguments
+ if (dst == NULL || password == NULL)
+ {
+ return;
+ }
+
+ // Generate a Unicode password
+ len = StrLen(password);
+ tmp_size = len * 2;
+
+ tmp = ZeroMalloc(tmp_size);
+
+ for (i = 0;i < len;i++)
+ {
+ tmp[i * 2] = password[i];
+ }
+
+ // Hashing
+ HashMd4(dst, tmp, tmp_size);
+
+ Free(tmp);
+}
+
+// Generate the MS-CHAPv2 server-side challenge
+void MsChapV2Server_GenerateChallenge(UCHAR *dst)
+{
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ Rand(dst, 16);
+}
+
+// Generate the MS-CHAPv2 client-side challenge
+void MsChapV2Client_GenerateChallenge(UCHAR *dst)
+{
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ Rand(dst, 16);
+}
+
+// Generate a 8 bytes challenge
+void MsChapV2_GenerateChallenge8(UCHAR *dst, UCHAR *client_challenge, UCHAR *server_challenge, char *username)
+{
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ char username2[MAX_SIZE];
+ char domainname2[MAX_SIZE];
+ // Validate arguments
+ if (dst == NULL || client_challenge == NULL || server_challenge == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+
+ WriteBuf(b, client_challenge, 16);
+ WriteBuf(b, server_challenge, 16);
+
+ ParseNtUsername(username, username2, sizeof(username2), domainname2, sizeof(domainname2), true);
+
+ if (IsEmptyStr(username2) == false)
+ {
+ WriteBuf(b, username2, StrLen(username2));
+ }
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Copy(dst, hash, 8);
+}
+
+// Generate the MS-CHAPv2 client response
+void MsChapV2Client_GenerateResponse(UCHAR *dst, UCHAR *challenge8, UCHAR *nt_password_hash)
+{
+ UCHAR password_hash_2[21];
+ UCHAR key1[8], key2[8], key3[8];
+ // Validate arguments
+ if (dst == NULL || challenge8 == NULL || nt_password_hash == NULL)
+ {
+ return;
+ }
+
+ Zero(password_hash_2, sizeof(password_hash_2));
+ Copy(password_hash_2, nt_password_hash, 16);
+
+ Zero(key1, sizeof(key1));
+ Zero(key2, sizeof(key2));
+ Zero(key3, sizeof(key3));
+
+ Copy(key1, password_hash_2 + 0, 7);
+ Copy(key2, password_hash_2 + 7, 7);
+ Copy(key3, password_hash_2 + 14, 7);
+
+ DesEcbEncrypt(dst + 0, challenge8, key1);
+ DesEcbEncrypt(dst + 8, challenge8, key2);
+ DesEcbEncrypt(dst + 16, challenge8, key3);
+}
+
+// Generate a hash of the hash of the NT password
+void GenerateNtPasswordHashHash(UCHAR *dst_hash, UCHAR *src_hash)
+{
+ // Validate arguments
+ if (dst_hash == NULL || src_hash == NULL)
+ {
+ return;
+ }
+
+ HashMd4(dst_hash, src_hash, 16);
+}
+
+// Generate the MS-CHAPv2 server response
+void MsChapV2Server_GenerateResponse(UCHAR *dst, UCHAR *nt_password_hash_hash, UCHAR *client_response, UCHAR *challenge8)
+{
+ UCHAR digest[SHA1_SIZE];
+ BUF *b;
+ char *magic1 = "Magic server to client signing constant";
+ char *magic2 = "Pad to make it do more than one iteration";
+ // Validate arguments
+ if (dst == NULL || nt_password_hash_hash == NULL || client_response == NULL || challenge8 == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, nt_password_hash_hash, 16);
+ WriteBuf(b, client_response, 24);
+ WriteBuf(b, magic1, StrLen(magic1));
+ HashSha1(digest, b->Buf, b->Size);
+ FreeBuf(b);
+
+ b = NewBuf();
+ WriteBuf(b, digest, sizeof(digest));
+ WriteBuf(b, challenge8, 8);
+ WriteBuf(b, magic2, StrLen(magic2));
+ HashSha1(dst, b->Buf, b->Size);
+ FreeBuf(b);
+}
+
+// Verify whether the password matches one that is specified by the user in the MS-CHAPv2
+bool MsChapV2VerityPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password)
+{
+ UCHAR ntlm_hash[MD5_SIZE];
+ UCHAR challenge8[8];
+ UCHAR client_response[24];
+ // Validate arguments
+ if (d == NULL || password == NULL)
+ {
+ return false;
+ }
+
+ GenerateNtPasswordHash(ntlm_hash, password);
+ MsChapV2_GenerateChallenge8(challenge8, d->MsChapV2_ClientChallenge, d->MsChapV2_ServerChallenge, d->MsChapV2_PPPUsername);
+ MsChapV2Client_GenerateResponse(client_response, challenge8, ntlm_hash);
+
+ if (Cmp(client_response, d->MsChapV2_ClientResponse, 24) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Estimate the password in the brute force for the request packet of MS-CHAPv2
+char *MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO *d, LIST *password_list)
+{
+ UINT i;
+ // Validate arguments
+ if (d == NULL || password_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(password_list);i++)
+ {
+ char *s = LIST_DATA(password_list, i);
+ char tmp[MAX_SIZE];
+ UINT j, max;
+ UINT len;
+
+ StrCpy(tmp, sizeof(tmp), s);
+
+ len = StrLen(tmp);
+ max = Power(2, MIN(len, 9));
+
+ for (j = 0;j < max;j++)
+ {
+ SetStrCaseAccordingToBits(tmp, j);
+ if (MsChapV2VerityPassword(d, tmp))
+ {
+ return CopyStr(tmp);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_PPP.h b/src/Cedar/IPsec_PPP.h
new file mode 100644
index 00000000..1534f1de
--- /dev/null
+++ b/src/Cedar/IPsec_PPP.h
@@ -0,0 +1,311 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_PPP.h
+// Header of IPsec_PPP.c
+
+#ifndef IPSEC_PPP_H
+#define IPSEC_PPP_H
+
+
+//// Macro
+#define PPP_LCP_CODE_IS_NEGATIVE(c) ((c) == PPP_LCP_CODE_NAK || (c) == PPP_LCP_CODE_REJECT || (c) == PPP_LCP_CODE_CODE_REJECT || (c) == PPP_LCP_CODE_PROTOCOL_REJECT)
+#define PPP_LCP_CODE_IS_REQUEST(c) ((c) == PPP_LCP_CODE_REQ)
+#define PPP_LCP_CODE_IS_RESPONSE(c) ((c) == PPP_LCP_CODE_ACK || (c) == PPP_LCP_CODE_NAK || (c) == PPP_LCP_CODE_REJECT || (c) == PPP_LCP_CODE_PROTOCOL_REJECT)
+#define PPP_LCP_CODE_IS_WITH_OPTION_LIST(c) ((c) == PPP_LCP_CODE_REQ || (c) == PPP_LCP_CODE_ACK || (c) == PPP_LCP_CODE_NAK)
+
+#define PPP_PAP_CODE_IS_REQUEST(c) ((c) == PPP_PAP_CODE_REQ)
+#define PPP_PAP_CODE_IS_RESPONSE(c) ((c) == PPP_PAP_CODE_ACK || (c) == PPP_PAP_CODE_NAK)
+
+#define PPP_CODE_IS_RESPONSE(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP) && PPP_LCP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_RESPONSE(c)))
+#define PPP_CODE_IS_REQUEST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP) && PPP_LCP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_REQUEST(c)) || ((protocol) == PPP_PROTOCOL_CHAP))
+#define PPP_CODE_IS_WITH_OPTION_LIST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP) && PPP_LCP_CODE_IS_WITH_OPTION_LIST(c)) || false)
+
+#define PPP_IS_SUPPORTED_PROTOCOL(p) ((p) == PPP_PROTOCOL_LCP || (p) == PPP_PROTOCOL_PAP || (p) == PPP_PROTOCOL_CHAP || (p) == PPP_PROTOCOL_IPCP || (p) == PPP_PROTOCOL_IP)
+
+
+//// Constants
+
+// Time-out value
+#define PPP_PACKET_RECV_TIMEOUT 10000 // Timeout until the next packet is received
+#define PPP_PACKET_RESEND_INTERVAL 1000 // Retransmission interval of the last packet
+#define PPP_TERMINATE_TIMEOUT 2000 // Timeout value to complete disconnection after requesting to disconnect in the PPP
+#define PPP_ECHO_SEND_INTERVAL 4792 // Transmission interval of PPP Echo Request
+#define PPP_DATA_TIMEOUT (20 * 1000) // Communication time-out
+
+// MRU
+#define PPP_MRU_DEFAULT 1500 // Default value
+#define PPP_MRU_MIN 100 // Minimum value
+#define PPP_MRU_MAX 1500 // Maximum value
+
+// PPP protocol (for control)
+#define PPP_PROTOCOL_LCP 0xc021
+#define PPP_PROTOCOL_PAP 0xc023
+#define PPP_PROTOCOL_IPCP 0x8021
+#define PPP_PROTOCOL_CHAP 0xc223
+
+// PPP protocol (for transfer)
+#define PPP_PROTOCOL_IP 0x0021
+
+// LCP code
+#define PPP_LCP_CODE_REQ 1
+#define PPP_LCP_CODE_ACK 2
+#define PPP_LCP_CODE_NAK 3
+#define PPP_LCP_CODE_REJECT 4
+#define PPP_LCP_CODE_TERMINATE_REQ 5
+#define PPP_LCP_CODE_TERMINATE_ACK 6
+#define PPP_LCP_CODE_CODE_REJECT 7
+#define PPP_LCP_CODE_PROTOCOL_REJECT 8
+#define PPP_LCP_CODE_ECHO_REQUEST 9
+#define PPP_LCP_CODE_ECHO_RESPONSE 10
+#define PPP_LCP_CODE_DROP 11
+#define PPP_LCP_CODE_IDENTIFICATION 12
+
+// PAP Code
+#define PPP_PAP_CODE_REQ 1
+#define PPP_PAP_CODE_ACK 2
+#define PPP_PAP_CODE_NAK 3
+
+// CHAP code
+#define PPP_CHAP_CODE_CHALLENGE 1
+#define PPP_CHAP_CODE_RESPONSE 2
+#define PPP_CHAP_CODE_SUCCESS 3
+#define PPP_CHAP_CODE_FAILURE 4
+
+// LCP Option Type
+#define PPP_LCP_OPTION_MRU 1
+#define PPP_LCP_OPTION_AUTH 3
+
+// IPCP option type
+#define PPP_IPCP_OPTION_IP 3
+#define PPP_IPCP_OPTION_DNS1 129
+#define PPP_IPCP_OPTION_DNS2 131
+#define PPP_IPCP_OPTION_WINS1 130
+#define PPP_IPCP_OPTION_WINS2 132
+
+// Authentication protocol
+#define PPP_LCP_AUTH_PAP PPP_PROTOCOL_PAP
+#define PPP_LCP_AUTH_CHAP PPP_PROTOCOL_CHAP
+
+// Algorithm of CHAP
+#define PPP_CHAP_ALG_MS_CHAP_V2 0x81
+
+
+//// Type
+
+// IP options used in the PPP
+struct PPP_IPOPTION
+{
+ IP IpAddress; // IP address
+ IP DnsServer1, DnsServer2; // DNS server address
+ IP WinsServer1, WinsServer2; // WINS server address
+};
+
+// PPP packet
+struct PPP_PACKET
+{
+ USHORT Protocol; // Protocol
+ bool IsControl; // Whether or not the control packet
+ PPP_LCP *Lcp; // LCP packet data
+ UINT DataSize; // Data size
+ void *Data; // Data body
+};
+
+// PPP LCP packet
+struct PPP_LCP
+{
+ UCHAR Code; // Code
+ UCHAR Id; // ID
+ UCHAR MagicNumber[4]; // Magic number
+ LIST *OptionList; // PPP options list
+ void *Data; // Data
+ UINT DataSize; // Data size
+};
+
+// PPP Options
+struct PPP_OPTION
+{
+ UCHAR Type; // Type of option
+ UINT DataSize; // Data size
+ UCHAR Data[254]; // Data
+ bool IsSupported; // Flag of whether it is supported
+ bool IsAccepted; // Flag for whether accepted
+ UCHAR AltData[254]; // Alternate data when it isn't accepted
+ UINT AltDataSize; // Alternate data size
+};
+
+// PPP session
+struct PPP_SESSION
+{
+ CEDAR *Cedar; // Cedar
+ IP ClientIP; // Client IP address
+ UINT ClientPort; // Client port
+ IP ServerIP; // Server IP address
+ UINT ServerPort; // Server port
+ TUBE *TubeSend; // Sending tube
+ TUBE *TubeRecv; // Receiving tube
+ UCHAR NextId; // ID to be used next
+ UINT Mru1; // MRU (server -> client)
+ UINT Mru2; // MRU (client -> server)
+ LIST *RecvPacketList; // Received packet list
+ PPP_PACKET *LastStoredPacket; // Packet that is stored at the last
+ bool IsTerminateReceived; // Whether a Terminate has been received
+ UINT DisconnectCauseCode; // L2TP disconnect cause code
+ UINT DisconnectCauseDirection; // L2TP disconnect cause direction code
+ IPC *Ipc; // IPC
+ bool ClientLCPOptionDetermined; // LCP option from the client has been determined
+ char Postfix[MAX_SIZE]; // Postfix of the session name
+ char ClientHostname[MAX_SIZE]; // Client host name
+ char ClientSoftwareName[MAX_SIZE]; // Client software name
+ UINT64 NextEchoSendTime; // Time to send Echo Request next
+ UINT64 LastRecvTime; // Time which the data has been received last
+ DHCP_OPTION_LIST ClientAddressOption; // Client address option
+ bool DhcpIpAllocTried; // Whether the request for an IP address is already attempted by DHCP
+ bool DhcpIpInformTried; // Whether the acquirement for an IP information is already attempted by DHCP
+ bool DhcpAllocated; // IP address is assigned by DHCP
+ bool UseStaticIPAddress; // Use a static IP address that is specified by the client
+ UINT64 DhcpRenewInterval; // DHCP update interval
+ UINT64 DhcpNextRenewTime; // DHCP renewal time of the next
+ char CryptName[MAX_SIZE]; // Cipher algorithm name
+ UINT AdjustMss; // MSS value
+ TUBE_FLUSH_LIST *FlushList; // Tube Flush List
+ bool EnableMSCHAPv2; // Enable the MS-CHAP v2
+ USHORT AuthProtocol; // Authentication protocol
+ bool AuthOk; // Flag for whether the authentication was successful
+ UCHAR MsChapV2_ServerChallenge[16]; // MS-CHAPv2 Server Challenge
+ UCHAR MsChapV2_ClientChallenge[16]; // MS-CHAPv2 Client Challenge
+ UCHAR MsChapV2_ClientResponse[24]; // MS-CHAPv2 Client Response
+ UCHAR MsChapV2_ServerResponse[20]; // MS-CHAPv2 Server Response
+ UINT MsChapV2_ErrorCode; // Authentication failure error code of MS-CHAPv2
+};
+
+// Function prototype
+THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss);
+void PPPThread(THREAD *thread, void *param);
+void FreePPPSession(PPP_SESSION *p);
+void FreePPPOptionList(LIST *o);
+void FreePPPLCP(PPP_LCP *c);
+PPP_LCP *NewPPPLCP(UCHAR code, UCHAR id);
+PPP_LCP *ParseLCP(USHORT protocol, void *data, UINT size);
+BUF *BuildLCPData(PPP_LCP *c);
+PPP_OPTION *GetOptionValue(PPP_LCP *c, UCHAR type);
+PPP_PACKET *ParsePPPPacket(void *data, UINT size);
+void FreePPPPacket(PPP_PACKET *pp);
+void FreePPPPacketEx(PPP_PACKET *pp, bool no_free_struct);
+BUF *BuildPPPPacketData(PPP_PACKET *pp);
+PPP_OPTION *NewPPPOption(UCHAR type, void *data, UINT size);
+bool PPPSendPacket(PPP_SESSION *p, PPP_PACKET *pp);
+bool PPPSendPacketEx(PPP_SESSION *p, PPP_PACKET *pp, bool no_flush);
+PPP_PACKET *PPPRecvPacket(PPP_SESSION *p, bool async);
+PPP_PACKET *PPPRecvPacketWithLowLayerProcessing(PPP_SESSION *p, bool async);
+PPP_PACKET *PPPRecvPacketForCommunication(PPP_SESSION *p);
+void PPPStoreLastPacket(PPP_SESSION *p, PPP_PACKET *pp);
+void PPPCleanTerminate(PPP_SESSION *p);
+bool PPPGetIPOptionFromLCP(PPP_IPOPTION *o, PPP_LCP *c);
+bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify);
+bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip);
+bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify);
+
+bool PPPSendRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c);
+USHORT PPPContinueCurrentProtocolRequestListening(PPP_SESSION *p, USHORT protocol);
+bool PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION *p);
+PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked);
+PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req);
+void PPPSendEchoRequest(PPP_SESSION *p);
+bool PPPParseUsername(CEDAR *cedar, char *src, ETHERIP_ID *dst);
+bool IsHubExistsWithLock(CEDAR *cedar, char *hubname);
+
+void GenerateNtPasswordHash(UCHAR *dst, char *password);
+void GenerateNtPasswordHashHash(UCHAR *dst_hash, UCHAR *src_hash);
+void MsChapV2Server_GenerateChallenge(UCHAR *dst);
+void MsChapV2Client_GenerateChallenge(UCHAR *dst);
+void MsChapV2_GenerateChallenge8(UCHAR *dst, UCHAR *client_challenge, UCHAR *server_challenge, char *username);
+void MsChapV2Client_GenerateResponse(UCHAR *dst, UCHAR *challenge8, UCHAR *nt_password_hash);
+void MsChapV2Server_GenerateResponse(UCHAR *dst, UCHAR *nt_password_hash_hash, UCHAR *client_response, UCHAR *challenge8);
+bool MsChapV2VerityPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password);
+char *MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO *d, LIST *password_list);
+
+#endif // IPSEC_PPP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_Win7.c b/src/Cedar/IPsec_Win7.c
new file mode 100644
index 00000000..e04a81e2
--- /dev/null
+++ b/src/Cedar/IPsec_Win7.c
@@ -0,0 +1,530 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_Win7.c
+// Initialize the helper module for Windows 7 / Windows 8 / Windows Vista / Windows Server 2008 / Windows Server 2008 R2 / Windows Server 2012
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define _WIN32_WINNT 0x0600
+#define WINVER 0x0600
+#define INITGUID
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <Fwpmu.h>
+#include <Fwpmtypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "IPsec_Win7Inner.h"
+#include <Wfp/Wfp.h>
+
+static IPSEC_WIN7_FUNCTIONS *api = NULL;
+static HINSTANCE hDll = NULL;
+
+
+// Initialize the IPsec helper module for Windows 7
+IPSEC_WIN7 *IPsecWin7Init()
+{
+ IPSEC_WIN7 *w;
+ FWPM_SESSION0 session;
+ UINT ret;
+ FWPM_FILTER0 filter;
+ UINT64 weight = MAXUINT64;
+
+ Debug("IPsecWin7Init()\n");
+
+ if (MsIsVista() == false)
+ {
+ return NULL;
+ }
+
+ if (MsIsAdmin() == false)
+ {
+ return NULL;
+ }
+
+ if (IPsecWin7InitApi() == false)
+ {
+ return NULL;
+ }
+
+ // Driver Initialization
+ if (IPsecWin7InitDriver() == false)
+ {
+ return NULL;
+ }
+
+ // Open the WFP (Dynamic Session)
+ Zero(&session, sizeof(session));
+ session.flags = FWPM_SESSION_FLAG_DYNAMIC;
+
+ w = ZeroMalloc(sizeof(IPSEC_WIN7));
+ ret = api->FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &w->hEngine);
+ if (ret)
+ {
+ Debug("FwpmEngineOpen0 Failed.\n");
+ IPsecWin7Free(w);
+ return NULL;
+ }
+
+ // Create the Filter (IPv4)
+ Zero(&filter, sizeof(filter));
+ filter.flags = FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED;
+ filter.layerKey = FWPM_LAYER_INBOUND_IPPACKET_V4;
+ filter.weight.type = FWP_UINT64;
+ filter.weight.uint64 = &weight;
+ filter.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
+ filter.action.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
+ filter.displayData.name = IPSEC_WIN7_FILTER_TITLE_V4;
+ ret = api->FwpmFilterAdd0(w->hEngine, &filter, NULL, &w->FilterIPv4Id);
+ if (ret)
+ {
+ Debug("FwpmFilterAdd0 for IPv4 Failed: 0x%X\n", ret);
+ }
+ else
+ {
+ Debug("FwpmFilterAdd0 for IPv4 Ok.\n");
+ }
+
+ // Create the Filter (IPv6)
+ Zero(&filter, sizeof(filter));
+ filter.flags = FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED;
+ filter.layerKey = FWPM_LAYER_INBOUND_IPPACKET_V6;
+ filter.weight.type = FWP_UINT64;
+ filter.weight.uint64 = &weight;
+ filter.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
+ filter.action.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
+ filter.displayData.name = IPSEC_WIN7_FILTER_TITLE_V6;
+ ret = api->FwpmFilterAdd0(w->hEngine, &filter, NULL, &w->FilterIPv6Id);
+ if (ret)
+ {
+ Debug("FwpmFilterAdd0 for IPv6 Failed: 0x%X\n", ret);
+ }
+ else
+ {
+ Debug("FwpmFilterAdd0 for IPv6 Ok.\n");
+ }
+
+ // Open the device of the driver as a file
+ w->hDriverFile = CreateFileA(WFP_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (w->hDriverFile == NULL || w->hDriverFile == INVALID_HANDLE_VALUE)
+ {
+ Debug("CreateFileA(\"%s\") Failed.\n", WFP_DEVICE_FILE_NAME);
+ IPsecWin7Free(w);
+ return NULL;
+ }
+
+ IPsecWin7UpdateHostIPAddressList(w);
+
+ Debug("IPsecWin7Init() Ok.\n");
+
+ return w;
+}
+
+// Update the IP address list of the host
+void IPsecWin7UpdateHostIPAddressList(IPSEC_WIN7 *w)
+{
+ LIST *o;
+ UINT i;
+ BUF *buf;
+ UINT retsize;
+ // Validate arguments
+ if (w == NULL)
+ {
+ return;
+ }
+
+ o = GetHostIPAddressList();
+ if (o == NULL)
+ {
+ return;
+ }
+
+ buf = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+ WFP_LOCAL_IP a;
+
+ Zero(&a, sizeof(a));
+
+ // Exclude any IPs or localhost IP
+ if (IsZeroIP(ip) == false && IsLocalHostIP(ip) == false)
+ {
+ if (IsIP4(ip))
+ {
+ a.IpVersion = 4;
+ Copy(a.IpAddress.IPv4Address, ip->addr, 4);
+ }
+ else
+ {
+ a.IpVersion = 6;
+ Copy(a.IpAddress.IPv6Address, ip->ipv6_addr, 16);
+ }
+
+ WriteBuf(buf, &a, sizeof(WFP_LOCAL_IP));
+ }
+ }
+
+ if (WriteFile(w->hDriverFile, buf->Buf, buf->Size, &retsize, NULL) == false)
+ {
+ Debug("WriteFile to the driver failed. %u\n", GetLastError());
+ }
+
+ FreeHostIPAddressList(o);
+
+ FreeBuf(buf);
+}
+
+// Release the module
+void IPsecWin7Free(IPSEC_WIN7 *w)
+{
+ // Validate arguments
+ if (w == NULL)
+ {
+ return;
+ }
+
+ if (w->hEngine != NULL)
+ {
+ api->FwpmEngineClose0(w->hEngine);
+ }
+
+ if (w->hDriverFile != NULL && w->hDriverFile != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(w->hDriverFile);
+ }
+
+ Free(w);
+}
+
+// Initialize and start the driver
+bool IPsecWin7InitDriver()
+{
+ bool ret;
+ void *lock = MsInitGlobalLock("IPsecWin7InitDriver", false);
+ void *p = MsDisableWow64FileSystemRedirection();
+
+ MsGlobalLock(lock);
+ {
+ ret = IPsecWin7InitDriverInner();
+ }
+ MsGlobalUnlock(lock);
+
+ MsFreeGlobalLock(lock);
+
+ MsRestoreWow64FileSystemRedirection(p);
+
+ Debug("IPsecWin7InitDriver: %u\n", ret);
+
+ return ret;
+}
+bool IPsecWin7InitDriverInner()
+{
+ char sys_filename[MAX_PATH];
+ bool install_driver = true;
+ HANDLE hEngine;
+ UINT ret;
+ FWPM_SESSION0 session;
+ UINT id;
+ FWPM_CALLOUT0 callout;
+
+ Format(sys_filename, sizeof(sys_filename), IPSEC_WIN7_DST_SYS, MsGetSystem32Dir());
+
+ if (IsFileExists(sys_filename) && MsIsServiceInstalled(IPSEC_WIN7_DRIVER_NAME))
+ {
+ if (GetCurrentIPsecWin7DriverBuild() >= CEDAR_BUILD)
+ {
+ // Not to install since the latest version has been already installed
+ install_driver = false;
+ }
+ }
+
+ if (install_driver)
+ {
+ char *src_filename = IPSEC_WIN7_SRC_SYS_X86;
+ if (MsIsX64())
+ {
+ src_filename = IPSEC_WIN7_SRC_SYS_X64;
+ }
+
+ // Copy the driver
+ if (FileCopy(src_filename, sys_filename) == false)
+ {
+ Debug("%s copy failed.\n", sys_filename);
+ return false;
+ }
+ Debug("%s copied.\n", sys_filename);
+
+ // Set the build number
+ SetCurrentIPsecWin7DriverBuild();
+ }
+
+ // Get whether the device drivers is already installed
+ if (MsIsServiceInstalled(IPSEC_WIN7_DRIVER_NAME) == false)
+ {
+ wchar_t sys_filename_w[MAX_PATH];
+
+ StrToUni(sys_filename_w, sizeof(sys_filename_w), sys_filename);
+
+ // Run a new installation
+ if (MsInstallDeviceDriverW(IPSEC_WIN7_DRIVER_NAME, IPSEC_WIN7_DRIVER_TITLE,
+ sys_filename_w, NULL) == false)
+ {
+ // Installation failed
+ Debug("MsInstallDeviceDriverW failed.\n");
+ return false;
+ }
+ }
+
+ // Start if the device driver is stopped
+ if (MsIsServiceRunning(IPSEC_WIN7_DRIVER_NAME) == false)
+ {
+ if (MsStartService(IPSEC_WIN7_DRIVER_NAME) == false)
+ {
+ // Start failure
+ Debug("MsStartService failed.\n");
+ return false;
+ }
+
+ Debug("%s service started.\n", IPSEC_WIN7_DRIVER_NAME);
+ }
+ else
+ {
+ Debug("%s service was already started.\n", IPSEC_WIN7_DRIVER_NAME);
+ }
+
+ // Open the WFP
+ Zero(&session, sizeof(session));
+
+ ret = api->FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &hEngine);
+ if (ret)
+ {
+ Debug("FwpmEngineOpen0 failed.\n");
+ return false;
+ }
+
+ // Create the Callout Driver (IPv4)
+ Zero(&callout, sizeof(callout));
+ callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
+ callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V4;
+ callout.displayData.name = IPSEC_WIN7_DRIVER_TITLE_V4;
+ ret = api->FwpmCalloutAdd0(hEngine, &callout, NULL, &id);
+ if (ret)
+ {
+ Debug("FwpmCalloutAdd0 for IPv4 Failed: 0x%X\n", ret);
+ }
+ else
+ {
+ Debug("FwpmCalloutAdd0 for IPv4 Ok.\n");
+ }
+
+ // Create the Callout Driver (IPv6)
+ Zero(&callout, sizeof(callout));
+ callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
+ callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V6;
+ callout.displayData.name = IPSEC_WIN7_DRIVER_TITLE_V6;
+ ret = api->FwpmCalloutAdd0(hEngine, &callout, NULL, &id);
+ if (ret)
+ {
+ Debug("FwpmCalloutAdd0 for IPv6 Failed: 0x%X\n", ret);
+ }
+ else
+ {
+ Debug("FwpmCalloutAdd0 for IPv6 Ok.\n");
+ }
+
+ api->FwpmEngineClose0(hEngine);
+
+ return true;
+}
+
+// Write the build number of the current driver
+void SetCurrentIPsecWin7DriverBuild()
+{
+ MsRegWriteInt(REG_LOCAL_MACHINE, IPSEC_WIN7_DRIVER_REGKEY, IPSEC_WIN7_DRIVER_BUILDNUMBER, CEDAR_BUILD);
+}
+
+// Get the build number of the current driver
+UINT GetCurrentIPsecWin7DriverBuild()
+{
+ return MsRegReadInt(REG_LOCAL_MACHINE, IPSEC_WIN7_DRIVER_REGKEY, IPSEC_WIN7_DRIVER_BUILDNUMBER);
+}
+
+// Initialization of the API
+bool IPsecWin7InitApi()
+{
+ if (api != NULL)
+ {
+ return true;
+ }
+
+ if (hDll == NULL)
+ {
+ hDll = LoadLibraryA("FWPUCLNT.DLL");
+ }
+
+ if (hDll == NULL)
+ {
+ return false;
+ }
+
+ api = malloc(sizeof(IPSEC_WIN7_FUNCTIONS));
+ Zero(api, sizeof(IPSEC_WIN7_FUNCTIONS));
+
+ api->FwpmEngineOpen0 =
+ (DWORD (__stdcall *)(const wchar_t *,UINT32,SEC_WINNT_AUTH_IDENTITY_W *,const FWPM_SESSION0 *,HANDLE *))
+ GetProcAddress(hDll, "FwpmEngineOpen0");
+
+ api->FwpmEngineClose0 =
+ (DWORD (__stdcall *)(HANDLE))
+ GetProcAddress(hDll, "FwpmEngineClose0");
+
+ api->FwpmFreeMemory0 =
+ (void (__stdcall *)(void **))
+ GetProcAddress(hDll, "FwpmFreeMemory0");
+
+ api->FwpmFilterAdd0 =
+ (DWORD (__stdcall *)(HANDLE,const FWPM_FILTER0 *,PSECURITY_DESCRIPTOR,UINT64 *))
+ GetProcAddress(hDll, "FwpmFilterAdd0");
+
+ api->IPsecSaContextCreate0 =
+ (DWORD (__stdcall *)(HANDLE,const IPSEC_TRAFFIC0 *,UINT64 *,UINT64 *))
+ GetProcAddress(hDll, "IPsecSaContextCreate0");
+
+ api->IPsecSaContextGetSpi0 =
+ (DWORD (__stdcall *)(HANDLE,UINT64,const IPSEC_GETSPI0 *,IPSEC_SA_SPI *))
+ GetProcAddress(hDll, "IPsecSaContextGetSpi0");
+
+ api->IPsecSaContextAddInbound0 =
+ (DWORD (__stdcall *)(HANDLE,UINT64,const IPSEC_SA_BUNDLE0 *))
+ GetProcAddress(hDll, "IPsecSaContextAddInbound0");
+
+ api->IPsecSaContextAddOutbound0 =
+ (DWORD (__stdcall *)(HANDLE,UINT64,const IPSEC_SA_BUNDLE0 *))
+ GetProcAddress(hDll, "IPsecSaContextAddOutbound0");
+
+ api->FwpmCalloutAdd0 =
+ (DWORD (__stdcall *)(HANDLE,const FWPM_CALLOUT0 *,PSECURITY_DESCRIPTOR,UINT32 *))
+ GetProcAddress(hDll, "FwpmCalloutAdd0");
+
+ if (api->FwpmEngineOpen0 == NULL ||
+ api->FwpmEngineClose0 == NULL ||
+ api->FwpmFreeMemory0 == NULL ||
+ api->FwpmFilterAdd0 == NULL ||
+ api->IPsecSaContextCreate0 == NULL ||
+ api->IPsecSaContextGetSpi0 == NULL ||
+ api->IPsecSaContextAddInbound0 == NULL ||
+ api->IPsecSaContextAddOutbound0 == NULL ||
+ api->FwpmCalloutAdd0 == NULL)
+ {
+ free(api);
+ api = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+#endif // WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_Win7.h b/src/Cedar/IPsec_Win7.h
new file mode 100644
index 00000000..35a8b664
--- /dev/null
+++ b/src/Cedar/IPsec_Win7.h
@@ -0,0 +1,121 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_Win7.h
+// Header of IPsec_Win7.c
+
+#ifndef IPSEC_WIN7_H
+#define IPSEC_WIN7_H
+
+// Constants
+#define IPSEC_WIN7_SRC_SYS_X86 "|pxwfp_x86.sys"
+#define IPSEC_WIN7_SRC_SYS_X64 "|pxwfp_x64.sys"
+#define IPSEC_WIN7_DST_SYS "%s\\drivers\\pxwfp.sys"
+
+#define IPSEC_WIN7_DRIVER_NAME "pxwfp"
+#define IPSEC_WIN7_DRIVER_TITLE L"SoftEther PacketiX VPN IPsec WFP Callout Driver"
+#define IPSEC_WIN7_DRIVER_TITLE_V4 L"SoftEther PacketiX VPN IPsec WFP Callout for IPv4"
+#define IPSEC_WIN7_DRIVER_TITLE_V6 L"SoftEther PacketiX VPN IPsec WFP Callout for IPv6"
+#define IPSEC_WIN7_FILTER_TITLE_V4 CEDAR_PRODUCT_STR_W L" VPN IPsec Filter for IPv4"
+#define IPSEC_WIN7_FILTER_TITLE_V6 CEDAR_PRODUCT_STR_W L" VPN IPsec Filter for IPv6"
+#define IPSEC_WIN7_DRIVER_REGKEY "SYSTEM\\CurrentControlSet\\services\\pxwfp"
+#define IPSEC_WIN7_DRIVER_BUILDNUMBER "CurrentInstalledBuild"
+
+
+// Function prototype
+IPSEC_WIN7 *IPsecWin7Init();
+void IPsecWin7Free(IPSEC_WIN7 *w);
+void IPsecWin7UpdateHostIPAddressList(IPSEC_WIN7 *w);
+
+bool IPsecWin7InitDriver();
+bool IPsecWin7InitDriverInner();
+UINT GetCurrentIPsecWin7DriverBuild();
+void SetCurrentIPsecWin7DriverBuild();
+bool IPsecWin7InitApi();
+
+
+#endif // IPSEC_WIN7_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/IPsec_Win7Inner.h b/src/Cedar/IPsec_Win7Inner.h
new file mode 100644
index 00000000..b57054b1
--- /dev/null
+++ b/src/Cedar/IPsec_Win7Inner.h
@@ -0,0 +1,160 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// IPsec_Win7.h
+// Internal header of IPsec_Win7.c
+
+#ifndef IPSEC_WIN7_INNER_H
+#define IPSEC_WIN7_INNER_H
+
+// API function
+typedef struct IPSEC_WIN7_FUNCTIONS
+{
+ DWORD (WINAPI *FwpmEngineOpen0)(
+ IN OPTIONAL const wchar_t* serverName,
+ IN UINT32 authnService,
+ IN OPTIONAL SEC_WINNT_AUTH_IDENTITY_W* authIdentity,
+ IN OPTIONAL const FWPM_SESSION0* session,
+ OUT HANDLE* engineHandle
+ );
+
+ DWORD (WINAPI *FwpmEngineClose0)(IN HANDLE engineHandle);
+
+ void (WINAPI *FwpmFreeMemory0)(IN OUT void** p);
+
+ DWORD (WINAPI *FwpmFilterAdd0)(
+ IN HANDLE engineHandle,
+ IN const FWPM_FILTER0* filter,
+ IN OPTIONAL PSECURITY_DESCRIPTOR sd,
+ OUT OPTIONAL UINT64* id
+ );
+
+ DWORD (WINAPI *IPsecSaContextCreate0)(
+ IN HANDLE engineHandle,
+ IN const IPSEC_TRAFFIC0* outboundTraffic,
+ OUT OPTIONAL UINT64* inboundFilterId,
+ OUT UINT64* id
+ );
+
+ DWORD (WINAPI *IPsecSaContextGetSpi0)(
+ IN HANDLE engineHandle,
+ IN UINT64 id,
+ IN const IPSEC_GETSPI0* getSpi,
+ OUT IPSEC_SA_SPI* inboundSpi
+ );
+
+ DWORD (WINAPI *IPsecSaContextAddInbound0)(
+ IN HANDLE engineHandle,
+ IN UINT64 id,
+ IN const IPSEC_SA_BUNDLE0* inboundBundle
+ );
+
+ DWORD (WINAPI *IPsecSaContextAddOutbound0)(
+ IN HANDLE engineHandle,
+ IN UINT64 id,
+ IN const IPSEC_SA_BUNDLE0* outboundBundle
+ );
+
+ DWORD (WINAPI *FwpmCalloutAdd0)(
+ IN HANDLE engineHandle,
+ IN const FWPM_CALLOUT0* callout,
+ IN OPTIONAL PSECURITY_DESCRIPTOR sd,
+ OUT OPTIONAL UINT32* id
+ );
+
+} IPSEC_WIN7_FUNCTIONS;
+
+// Instance
+struct IPSEC_WIN7
+{
+ HANDLE hEngine;
+ HANDLE hDriverFile;
+ UINT64 FilterIPv4Id, FilterIPv6Id;
+};
+
+
+#endif // IPSEC_WIN7_INNER_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Interop_OpenVPN.c b/src/Cedar/Interop_OpenVPN.c
new file mode 100644
index 00000000..48045333
--- /dev/null
+++ b/src/Cedar/Interop_OpenVPN.c
@@ -0,0 +1,2942 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Interop_OpenVPN.c
+// OpenVPN protocol stack
+
+#include "CedarPch.h"
+
+
+static bool g_no_openvpn_tcp = false;
+static bool g_no_openvpn_udp = false;
+
+// Ping signature of the OpenVPN protocol
+static UCHAR ping_signature[] =
+{
+ 0x2a, 0x18, 0x7b, 0xf3, 0x64, 0x1e, 0xb4, 0xcb,
+ 0x07, 0xed, 0x2d, 0x0a, 0x98, 0x1f, 0xc7, 0x48
+};
+
+// Set the OpenVPN over TCP disabling flag
+void OvsSetNoOpenVpnTcp(bool b)
+{
+ g_no_openvpn_tcp = b;
+}
+
+// Get the OpenVPN over TCP disabling flag
+bool OvsGetNoOpenVpnTcp()
+{
+ return g_no_openvpn_tcp;
+}
+
+// Set the OpenVPN over UDP disabling flag
+void OvsSetNoOpenVpnUdp(bool b)
+{
+ g_no_openvpn_udp = b;
+}
+
+// Get the OpenVPN over UDP disabling flag
+bool OvsGetNoOpenVpnUdp()
+{
+ return g_no_openvpn_udp;
+}
+
+
+// Write the OpenVPN log
+void OvsLog(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, char *name, ...)
+{
+ wchar_t prefix[MAX_SIZE * 2];
+ wchar_t buf2[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+ if (se == NULL)
+ {
+ UniStrCpy(prefix, sizeof(prefix), _UU("LO_PREFIX_RAW"));
+ }
+ else
+ {
+ if (c == NULL)
+ {
+ UniFormat(prefix, sizeof(prefix), _UU("LO_PREFIX_SESSION"),
+ se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort);
+ }
+ else
+ {
+ UniFormat(prefix, sizeof(prefix), _UU("LO_PREFIX_CHANNEL"),
+ se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort,
+ c->KeyId);
+ }
+ }
+ va_start(args, name);
+ UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
+ va_end(args);
+
+ UniStrCat(prefix, sizeof(prefix), buf2);
+
+ WriteServerLog(s->Cedar, prefix);
+}
+
+// Process the received packet
+void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
+{
+ OPENVPN_SESSION *se;
+ OPENVPN_PACKET *recv_packet;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+
+ // Search for the session
+ se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, protocol);
+ if (se == NULL)
+ {
+ return;
+ }
+
+ // Parse the packet
+ recv_packet = OvsParsePacket(p->Data, p->Size);
+
+ if (recv_packet != NULL)
+ {
+ OPENVPN_CHANNEL *c = NULL;
+ if (recv_packet->OpCode != OPENVPN_P_DATA_V1 && recv_packet->MySessionId != 0)
+ {
+ Debug("RECV PACKET: %u %I64u\n", recv_packet->KeyId, recv_packet->MySessionId);
+ }
+ if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
+ {
+ Debug(" PKT %u %u\n", recv_packet->OpCode, recv_packet->KeyId);
+ }
+
+ if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
+ {
+ // Control packet
+ if (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 ||
+ recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
+ {
+ // Connection request packet
+ if (se->Channels[recv_packet->KeyId] != NULL)
+ {
+ // Release when there is a channel data already
+ OvsFreeChannel(se->Channels[recv_packet->KeyId]);
+ se->Channels[recv_packet->KeyId] = NULL;
+ }
+
+ // Create a new channel
+ c = OvsNewChannel(se, recv_packet->KeyId);
+ if (se->ClientSessionId == 0)
+ {
+ se->ClientSessionId = recv_packet->MySessionId;
+ }
+ se->Channels[recv_packet->KeyId] = c;
+ Debug("OpenVPN New Channel :%u\n", recv_packet->KeyId);
+ OvsLog(s, se, c, "LO_NEW_CHANNEL");
+ }
+/* else if (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
+ {
+ // Response to soft reset request packet
+ OPENVPN_PACKET *p;
+
+ p = OvsNewControlPacket(OPENVPN_P_CONTROL_SOFT_RESET_V1, recv_packet->KeyId, se->ServerSessionId,
+ 0, NULL, 0, 0, 0, NULL);
+
+ OvsSendPacketNow(s, se, p);
+
+ OvsFreePacket(p);
+ }*/
+ else
+ {
+ // Packet other than the connection request
+ if (se->Channels[recv_packet->KeyId] != NULL)
+ {
+ c = se->Channels[recv_packet->KeyId];
+ }
+ }
+
+ if (c != NULL)
+ {
+ // Delete the send packet list by looking the packet ID in the ACK list of arrived packet
+ OvsDeleteFromSendingControlPacketList(c, recv_packet->NumAck, recv_packet->AckPacketId);
+
+ if (recv_packet->OpCode != OPENVPN_P_ACK_V1)
+ {
+ // Add the Packet ID of arrived packet to the list
+ InsertIntDistinct(c->AckReplyList, recv_packet->PacketId);
+ Debug("Recv Packet ID (c=%u): %u\n", c->KeyId, recv_packet->PacketId);
+
+ if ((recv_packet->PacketId > c->MaxRecvPacketId)
+ || (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2)
+ || (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1))
+ {
+ c->MaxRecvPacketId = recv_packet->PacketId;
+
+ // Process the received control packet
+ OvsProcessRecvControlPacket(s, se, c, recv_packet);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Data packet
+ if (se->Channels[recv_packet->KeyId] != NULL)
+ {
+ OPENVPN_CHANNEL *c = se->Channels[recv_packet->KeyId];
+ if (c->Status == OPENVPN_CHANNEL_STATUS_ESTABLISHED)
+ {
+ UCHAR *data;
+ UINT size;
+
+ data = recv_packet->Data;
+ size = recv_packet->DataSize;
+
+ if (size >= (c->MdRecv->Size + c->CipherDecrypt->IvSize + sizeof(UINT)))
+ {
+ UCHAR *hmac;
+ UCHAR *iv;
+ UCHAR hmac_test[128];
+
+ // HMAC
+ hmac = data;
+ data += c->MdRecv->Size;
+ size -= c->MdRecv->Size;
+
+ // Confirmation of HMAC
+ MdProcess(c->MdRecv, hmac_test, data, size);
+ if (Cmp(hmac_test, hmac, c->MdRecv->Size) == 0)
+ {
+ // Update of last communication time
+ se->LastCommTick = s->Now;
+
+ // IV
+ iv = data;
+ data += c->CipherDecrypt->IvSize;
+ size -= c->CipherDecrypt->IvSize;
+
+ // Payload
+ if (size >= 1 && (c->CipherDecrypt->BlockSize == 0 || (size % c->CipherDecrypt->BlockSize) == 0))
+ {
+ UINT data_packet_id;
+
+ // Decryption
+ size = CipherProcess(c->CipherDecrypt, iv, s->TmpBuf, data, size);
+
+ data = s->TmpBuf;
+
+ if (size >= sizeof(UINT))
+ {
+ data_packet_id = READ_UINT(data);
+
+ data += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ if (size >= sizeof(ping_signature) &&
+ Cmp(data, ping_signature, sizeof(ping_signature)) == 0)
+ {
+ // Ignore since a ping packet has been received
+ DoNothing();
+ }
+ else
+ {
+ // Receive a packet!!
+ if (se->Ipc != NULL)
+ {
+ switch (se->Mode)
+ {
+ case OPENVPN_MODE_L2: // Send an Ethernet packet to a session
+ IPCSendL2(se->Ipc, data, size);
+ break;
+
+ case OPENVPN_MODE_L3: // Send an IPv4 packet to a session
+ IPCSendIPv4(se->Ipc, data, size);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+// Debug("HMAC Failed (c=%u)\n", c->KeyId);
+ }
+ }
+ }
+ }
+ }
+
+ OvsFreePacket(recv_packet);
+ }
+}
+
+// Remove a packet which the opponent has received from the transmission list
+void OvsDeleteFromSendingControlPacketList(OPENVPN_CHANNEL *c, UINT num_acks, UINT *acks)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (c == NULL || num_acks == 0)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < num_acks;i++)
+ {
+ UINT ack = acks[i];
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(c->SendControlPacketList);j++)
+ {
+ OPENVPN_CONTROL_PACKET *p = LIST_DATA(c->SendControlPacketList, j);
+
+ if (p->PacketId == ack)
+ {
+ AddDistinct(o, p);
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ OPENVPN_CONTROL_PACKET *p = LIST_DATA(o, i);
+
+ Delete(c->SendControlPacketList, p);
+
+ OvsFreeControlPacket(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Process the received control packet
+void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, OPENVPN_PACKET *p)
+{
+ FIFO *recv_fifo = NULL;
+ FIFO *send_fifo = NULL;
+ // Validate arguments
+ if (s == NULL || se == NULL || c == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (p->OpCode == OPENVPN_P_CONTROL_V1)
+ {
+ Debug("SSL (c=%u): %u\n", c->KeyId, p->DataSize);
+
+ if (c->SslPipe == NULL)
+ {
+ // Create an SSL pipe
+ Lock(s->Cedar->lock);
+ {
+ c->SslPipe = NewSslPipe(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh);
+ }
+ Unlock(s->Cedar->lock);
+
+ Debug("SSL Pipe Created (c=%u).\n", c->KeyId);
+ }
+
+ if (c->SslPipe->IsDisconnected == false)
+ {
+ // Pour the physically received data into SSL pipe
+ if (FifoSize(c->SslPipe->RawIn->SendFifo) < OPENVPN_MAX_SSL_RECV_BUF_SIZE)
+ {
+ Debug("SSL_Write: %u\n", p->DataSize);
+ WriteFifo(c->SslPipe->RawIn->SendFifo, p->Data, p->DataSize);
+ }
+ SyncSslPipe(c->SslPipe);
+ }
+ }
+
+ if (c->SslPipe != NULL && c->SslPipe->IsDisconnected == false)
+ {
+ recv_fifo = c->SslPipe->SslInOut->RecvFifo;
+ send_fifo = c->SslPipe->SslInOut->SendFifo;
+ }
+
+ Debug("SIZE: recv_fifo = %u, send_fifo = %u\n", FifoSize(recv_fifo), FifoSize(send_fifo));
+
+ switch (c->Status)
+ {
+ case OPENVPN_CHANNEL_STATUS_INIT:
+ switch (p->OpCode)
+ {
+ case OPENVPN_P_CONTROL_SOFT_RESET_V1:
+ // Key update (soft reset)
+ if (se->Established)
+ {
+ if (c->IsInitiatorServer == false)
+ {
+ OvsSendControlPacket(c, OPENVPN_P_CONTROL_SOFT_RESET_V1, NULL, 0);
+ }
+
+ c->Status = OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_KEY;
+ c->IsRekeyChannel = true;
+ }
+ break;
+
+ case OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2:
+ // New connection (hard reset)
+ OvsSendControlPacket(c, OPENVPN_P_CONTROL_HARD_RESET_SERVER_V2, NULL, 0);
+
+ c->Status = OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_KEY;
+ break;
+ }
+ break;
+
+ case OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_KEY:
+ if (FifoSize(recv_fifo) >= 1)
+ {
+ OPENVPN_KEY_METHOD_2 data;
+ UCHAR *ptr = FifoPtr(recv_fifo);
+
+ // Parse OPENVPN_KEY_METHOD_2
+ UINT read_size = OvsParseKeyMethod2(&data, ptr, FifoSize(recv_fifo), true);
+ if (read_size != 0)
+ {
+ BUF *b;
+
+ // Success in parsing key information
+ ReadFifo(recv_fifo, NULL, read_size);
+
+ // Set session parameters
+ OvsSetupSessionParameters(s, se, c, &data);
+
+ // Build OPENVPN_KEY_METHOD_2 to respond
+ b = OvsBuildKeyMethod2(&c->ServerKey);
+
+ // Transmission of the response data
+ if (b != NULL)
+ {
+ WriteFifo(send_fifo, b->Buf, b->Size);
+
+ FreeBuf(b);
+ }
+
+ // State transition
+ c->Status = OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_PUSH_REQUEST;
+ if (c->IsRekeyChannel)
+ {
+ c->Status = OPENVPN_CHANNEL_STATUS_ESTABLISHED;
+ c->EstablishedTick = s->Now;
+ Debug("OpenVPN Channel %u Established (re-key).\n", c->KeyId);
+ OvsLog(s, se, c, "LO_CHANNEL_ESTABLISHED_NEWKEY");
+ }
+ }
+ }
+ break;
+
+ case OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_PUSH_REQUEST:
+ if (FifoSize(recv_fifo) >= 1)
+ {
+ char tmp[MAX_SIZE];
+ UINT read_size = OvsPeekStringFromFifo(recv_fifo, tmp, sizeof(tmp));
+
+ if (read_size >= 1)
+ {
+ Debug("Client->Server (c=%u): %s\n", c->KeyId, tmp);
+
+ ReadFifo(recv_fifo, NULL, read_size);
+
+ if (StartWith(tmp, "PUSH_REQUEST"))
+ {
+ // Since connection requested, start VPN connection
+ // When the IPC VPN connection has not been started yet, start it
+ OvsBeginIPCAsyncConnectionIfEmpty(s, se, c);
+
+ // State transition
+ c->Status = OPENVPN_CHANNEL_STATUS_TLS_VPN_CONNECTING;
+ }
+ }
+ }
+ break;
+
+ case OPENVPN_CHANNEL_STATUS_TLS_VPN_CONNECTING:
+ case OPENVPN_CHANNEL_STATUS_ESTABLISHED:
+ if (FifoSize(recv_fifo) >= 1)
+ {
+ char tmp[MAX_SIZE];
+ UINT read_size = OvsPeekStringFromFifo(recv_fifo, tmp, sizeof(tmp));
+
+ if (read_size >= 1)
+ {
+ Debug("Client->Server (c=%u): %s\n", c->KeyId, tmp);
+
+ ReadFifo(recv_fifo, NULL, read_size);
+
+ if (StartWith(tmp, "PUSH_REQUEST"))
+ {
+ WriteFifo(send_fifo, se->PushReplyStr, StrLen(se->PushReplyStr));
+ }
+ }
+ }
+ break;
+ }
+}
+
+// Calculate the proper MSS
+UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c)
+{
+ UINT ret = MTU_FOR_PPPOE;
+ // Validate arguments
+ if (s == NULL || se == NULL || c == NULL)
+ {
+ return 0;
+ }
+
+ if (c->MdSend == NULL || c->CipherEncrypt == NULL)
+ {
+ return 0;
+ }
+
+ if (se->Protocol == OPENVPN_PROTOCOL_TCP)
+ {
+ // Calculation is not required for TCP mode
+ return 0;
+ }
+
+ // IPv4 / IPv6
+ if (IsIP4(&se->ClientIp))
+ {
+ ret -= 20;
+ }
+ else
+ {
+ ret -= 40;
+ }
+
+ // UDP
+ ret -= 8;
+
+ // opcode
+ ret -= 1;
+
+ // HMAC
+ ret -= c->MdSend->Size;
+
+ // IV
+ ret -= c->CipherEncrypt->IvSize;
+
+ // Packet ID
+ ret -= 4;
+
+ if (c->CipherEncrypt->IsNullCipher == false)
+ {
+ // block
+ ret -= c->CipherEncrypt->BlockSize;
+ }
+
+ if (se->Mode == OPENVPN_MODE_L2)
+ {
+ // Inner Ethernet Header
+ ret -= 14;
+ }
+
+ // Inner IPv4
+ ret -= 20;
+
+ // Inner TCP
+ ret -= 20;
+
+ return ret;
+}
+
+// When the IPC VPN connection has not been started yet, start it
+void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c)
+{
+ // Validate arguments
+ if (s == NULL || se == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (IsIPCConnected(se->Ipc) == false)
+ {
+ FreeIPC(se->Ipc);
+
+ se->Ipc = NULL;
+ }
+
+ if (se->IpcAsync == NULL)
+ {
+ IPC_PARAM p;
+ ETHERIP_ID id;
+
+ Zero(&p, sizeof(p));
+ Zero(&id, sizeof(id));
+
+ // Parse the user name
+ PPPParseUsername(s->Cedar, c->ClientKey.Username, &id);
+
+
+ // Build IPC connection parameters
+ StrCpy(p.ClientName, sizeof(p.ClientName), OPENVPN_IPC_CLIENT_NAME);
+ StrCpy(p.Postfix, sizeof(p.Postfix), (se->Mode == OPENVPN_MODE_L3 ? OPENVPN_IPC_POSTFIX_L3 : OPENVPN_IPC_POSTFIX_L2));
+
+ StrCpy(p.UserName, sizeof(p.UserName), id.UserName);
+ StrCpy(p.HubName, sizeof(p.HubName), id.HubName);
+ StrCpy(p.Password, sizeof(p.Password), c->ClientKey.Password);
+
+ Copy(&p.ClientIp, &se->ClientIp, sizeof(IP));
+ p.ClientPort = se->ClientPort;
+
+ Copy(&p.ServerIp, &se->ServerIp, sizeof(IP));
+ p.ServerPort = se->ServerPort;
+
+ if (c->CipherEncrypt->IsNullCipher == false)
+ {
+ StrCpy(p.CryptName, sizeof(p.CryptName), c->CipherEncrypt->Name);
+ }
+
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ // L3 Mode
+ p.IsL3Mode = true;
+ }
+ else
+ {
+ // L2 Mode
+ p.BridgeMode = true;
+ }
+
+ p.IsOpenVPN = true;
+
+ // Calculate the MSS
+ p.Mss = OvsCalcTcpMss(s, se, c);
+ Debug("MSS=%u\n", p.Mss);
+
+ // Start an IPC connection
+ se->IpcAsync = NewIPCAsync(s->Cedar, &p, s->SockEvent);
+ }
+}
+
+// Peek a NULL-terminated string from the FIFO
+UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size)
+{
+ UINT i;
+ bool ok = false;
+ // Validate arguments
+ if (f == NULL || str == NULL || str_size == 0)
+ {
+ return 0;
+ }
+
+ StrCpy(str, str_size, "");
+
+ for (i = 0;i < MIN(str_size, FifoSize(f));i++)
+ {
+ char c = *(((char *)FifoPtr(f)) + i);
+
+ if (c != 0)
+ {
+ str[i] = c;
+ }
+ else
+ {
+ str[i] = 0;
+ i++;
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok == false)
+ {
+ return 0;
+ }
+
+ return i;
+}
+
+// Set session parameters
+void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, OPENVPN_KEY_METHOD_2 *data)
+{
+ LIST *o;
+ BUF *b;
+ // Validate arguments
+ if (s == NULL || se == NULL || c == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Copy(&c->ClientKey, data, sizeof(OPENVPN_KEY_METHOD_2));
+
+ // Parse the parameter string
+ Debug("Parsing Option Str: %s\n", data->OptionString);
+
+ OvsLog(s, se, c, "LO_OPTION_STR_RECV", data->OptionString);
+
+ o = OvsParseOptions(data->OptionString);
+
+ if (se->Mode == OPENVPN_MODE_UNKNOWN)
+ {
+ UINT mtu;
+ // Layer
+ if (StrCmpi(IniStrValue(o, "dev-type"), "tun") == 0)
+ {
+ // L3
+ se->Mode = OPENVPN_MODE_L3;
+ }
+ else
+ {
+ // L2
+ se->Mode = OPENVPN_MODE_L2;
+ }
+
+ // Link MTU
+ mtu = IniIntValue(o, "link-mtu");
+ if (mtu == 0)
+ {
+ mtu = OPENVPN_MTU_LINK;
+ }
+ se->LinkMtu = mtu;
+
+ // Tun MTU
+ mtu = IniIntValue(o, "tun-mtu");
+ if (mtu == 0)
+ {
+ mtu = OPENVPN_MTU_TUN;
+ }
+ se->TunMtu = mtu;
+ }
+
+ // Protocol
+ if (se->Protocol == OPENVPN_PROTOCOL_TCP)
+ {
+ // TCP
+ // UDP
+ if (IsIP6(&se->ClientIp) == false)
+ {
+ StrCpy(c->Proto, sizeof(c->Proto), "TCPv4_SERVER");
+ }
+ else
+ {
+ StrCpy(c->Proto, sizeof(c->Proto), "TCPv6_SERVER");
+ }
+ }
+ else
+ {
+ // UDP
+ if (IsIP6(&se->ClientIp) == false)
+ {
+ StrCpy(c->Proto, sizeof(c->Proto), "UDPv4");
+ }
+ else
+ {
+ StrCpy(c->Proto, sizeof(c->Proto), "UDPv6");
+ }
+ }
+
+ // Encryption algorithm
+ c->CipherEncrypt = OvsGetCipher(IniStrValue(o, "cipher"));
+ c->CipherDecrypt = NewCipher(c->CipherEncrypt->Name);
+
+ // Hash algorithm
+ c->MdSend = OvsGetMd(IniStrValue(o, "auth"));
+ c->MdRecv = NewMd(c->MdSend->Name);
+
+ // Random number generation
+ Rand(c->ServerKey.Random1, sizeof(c->ServerKey.Random1));
+ Rand(c->ServerKey.Random2, sizeof(c->ServerKey.Random2));
+
+ // Generate the Master Secret
+ b = NewBuf();
+ WriteBuf(b, OPENVPN_PREMASTER_LABEL, StrLen(OPENVPN_PREMASTER_LABEL));
+ WriteBuf(b, c->ClientKey.Random1, sizeof(c->ClientKey.Random1));
+ WriteBuf(b, c->ServerKey.Random1, sizeof(c->ServerKey.Random1));
+ Enc_tls1_PRF(b->Buf, b->Size,
+ c->ClientKey.PreMasterSecret, sizeof(c->ClientKey.PreMasterSecret),
+ c->MasterSecret, sizeof(c->MasterSecret));
+ FreeBuf(b);
+
+ // Generate an Expansion Key
+ b = NewBuf();
+ WriteBuf(b, OPENVPN_EXPANSION_LABEL, StrLen(OPENVPN_EXPANSION_LABEL));
+ WriteBuf(b, c->ClientKey.Random2, sizeof(c->ClientKey.Random2));
+ WriteBuf(b, c->ServerKey.Random2, sizeof(c->ServerKey.Random2));
+ WriteBufInt64(b, se->ClientSessionId);
+ WriteBufInt64(b, se->ServerSessionId);
+ Enc_tls1_PRF(b->Buf, b->Size, c->MasterSecret, sizeof(c->MasterSecret),
+ c->ExpansionKey, sizeof(c->ExpansionKey));
+ FreeBuf(b);
+
+ // Set the key
+ SetCipherKey(c->CipherDecrypt, c->ExpansionKey + 0, false);
+ SetCipherKey(c->CipherEncrypt, c->ExpansionKey + 128, true);
+ SetMdKey(c->MdRecv, c->ExpansionKey + 64, c->MdRecv->Size);
+ SetMdKey(c->MdSend, c->ExpansionKey + 192, c->MdSend->Size);
+
+ OvsFreeOptions(o);
+
+ // Generate the response option string
+ Format(c->ServerKey.OptionString, sizeof(c->ServerKey.OptionString),
+ "V4,dev-type %s,link-mtu %u,tun-mtu %u,proto %s,"
+ "cipher %s,auth %s,keysize %u,key-method 2,tls-server",
+ (se->Mode == OPENVPN_MODE_L2 ? "tap" : "tun"),
+ se->LinkMtu,
+ se->TunMtu,
+ c->Proto,
+ c->CipherEncrypt->Name, c->MdSend->Name, c->CipherEncrypt->KeySize * 8);
+ Debug("Building OptionStr: %s\n", c->ServerKey.OptionString);
+
+ OvsLog(s, se, c, "LO_OPTION_STR_SEND", c->ServerKey.OptionString);
+}
+
+// Get the encryption algorithm
+CIPHER *OvsGetCipher(char *name)
+{
+ CIPHER *c = NULL;
+
+ if (IsEmptyStr(name) == false && IsStrInStrTokenList(OPENVPN_CIPHER_LIST, name, NULL, false))
+ {
+ c = NewCipher(name);
+ }
+
+ if (c == NULL)
+ {
+ c = NewCipher(OPENVPN_DEFAULT_CIPHER);
+ }
+
+ return c;
+}
+
+// Get the hash algorithm
+MD *OvsGetMd(char *name)
+{
+ MD *m = NULL;
+
+ if (IsEmptyStr(name) == false && IsStrInStrTokenList(OPENVPN_MD_LIST, name, NULL, false))
+ {
+ m = NewMd(name);
+ }
+
+ if (m == NULL)
+ {
+ m = NewMd(OPENVPN_DEFAULT_MD);
+ }
+
+ return m;
+}
+
+// Parse the option string
+LIST *OvsParseOptions(char *str)
+{
+ LIST *o = NewListFast(NULL);
+ TOKEN_LIST *t;
+
+ t = ParseTokenWithoutNullStr(str, ",");
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char key[MAX_SIZE];
+ char value[MAX_SIZE];
+ char *line = t->Token[i];
+ Trim(line);
+
+ if (GetKeyAndValue(line, key, sizeof(key), value, sizeof(value), " \t"))
+ {
+ INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));
+
+ e->Key = CopyStr(key);
+ e->Value = CopyStr(value);
+
+ Add(o, e);
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return o;
+}
+
+// Release the option list
+void OvsFreeOptions(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ FreeIni(o);
+}
+
+// Create an Option List
+LIST *OvsNewOptions()
+{
+ return NewListFast(NULL);
+}
+
+// Add a value to the option list
+void OvsAddOption(LIST *o, char *key, char *value)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e != NULL)
+ {
+ // Overwrite existing keys
+ Free(e->Key);
+ e->Key = CopyStr(key);
+
+ Free(e->Value);
+ e->Value = CopyStr(value);
+ }
+ else
+ {
+ // Create a new key
+ e = ZeroMalloc(sizeof(INI_ENTRY));
+
+ e->Key = CopyStr(key);
+ e->Value = CopyStr(value);
+
+ Add(o, e);
+ }
+}
+
+// Confirm whether there is specified option key string
+bool OvsHasOption(LIST *o, char *key)
+{
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ if (GetIniEntry(o, key) != NULL)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Build the data from KEY_METHOD2
+BUF *OvsBuildKeyMethod2(OPENVPN_KEY_METHOD_2 *d)
+{
+ BUF *b;
+ UCHAR uc;
+ // Validate arguments
+ if (d == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Reserved
+ WriteBufInt(b, 0);
+
+ // Method
+ uc = 2;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ // Random1
+ WriteBuf(b, d->Random1, sizeof(d->Random1));
+
+ // Random2
+ WriteBuf(b, d->Random2, sizeof(d->Random2));
+
+ // Option String
+ OvsWriteStringToBuf(b, d->OptionString, sizeof(d->OptionString));
+
+ // Username
+ OvsWriteStringToBuf(b, d->Username, sizeof(d->Username));
+
+ // Password
+ OvsWriteStringToBuf(b, d->Password, sizeof(d->Password));
+
+ // PeerInfo
+ OvsWriteStringToBuf(b, d->PeerInfo, sizeof(d->PeerInfo));
+
+ return b;
+}
+
+// Append a string to buf
+void OvsWriteStringToBuf(BUF *b, char *str, UINT max_size)
+{
+ USHORT us;
+ UINT i;
+ char *tmp;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+ if (str == NULL)
+ {
+ str = "";
+ }
+
+ if (StrLen(str) == 0)
+ {
+ us = 0;
+ WriteBuf(b, &us, sizeof(USHORT));
+ return;
+ }
+
+ i = StrSize(str);
+ i = MIN(i, max_size);
+ us = Endian16((USHORT)i);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ tmp = Malloc(i);
+ Copy(tmp, str, i);
+ tmp[i - 1] = 0;
+ WriteBuf(b, tmp, i);
+
+ Free(tmp);
+}
+
+// Parse the KEY_METHOD2
+UINT OvsParseKeyMethod2(OPENVPN_KEY_METHOD_2 *ret, UCHAR *data, UINT size, bool client_mode)
+{
+ BUF *b;
+ UINT read_size = 0;
+ UINT ui;
+ UCHAR uc;
+ // Validate arguments
+ Zero(ret, sizeof(OPENVPN_KEY_METHOD_2));
+ if (ret == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ // Reserved
+ if (ReadBuf(b, &ui, sizeof(UINT)) == sizeof(UINT))
+ {
+ // Method
+ if (ReadBuf(b, &uc, sizeof(UCHAR)) == sizeof(UCHAR) && uc == 2)
+ {
+ // Pre Master Secret
+ if (client_mode == false || ReadBuf(b, ret->PreMasterSecret, sizeof(ret->PreMasterSecret)) == sizeof(ret->PreMasterSecret))
+ {
+ // Random1
+ if (ReadBuf(b, ret->Random1, sizeof(ret->Random1)) == sizeof(ret->Random1))
+ {
+ // Random2
+ if (ReadBuf(b, ret->Random2, sizeof(ret->Random2)) == sizeof(ret->Random2))
+ {
+ // String
+ if (OvsReadStringFromBuf(b, ret->OptionString, sizeof(ret->OptionString)) &&
+ OvsReadStringFromBuf(b, ret->Username, sizeof(ret->Username)) &&
+ OvsReadStringFromBuf(b, ret->Password, sizeof(ret->Password)) &&
+ OvsReadStringFromBuf(b, ret->PeerInfo, sizeof(ret->PeerInfo)))
+ {
+ read_size = b->Current;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeBuf(b);
+
+ return read_size;
+}
+
+// Read a string from BUF
+bool OvsReadStringFromBuf(BUF *b, char *str, UINT str_size)
+{
+ USHORT us;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, &us, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ return false;
+ }
+
+ us = Endian16(us);
+
+ if (us == 0)
+ {
+ StrCpy(str, str_size, "");
+ return true;
+ }
+
+ if (us > str_size)
+ {
+ return false;
+ }
+
+ if (ReadBuf(b, str, us) != us)
+ {
+ return false;
+ }
+
+ if (str[us - 1] != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Transmission of control packet (Automatic segmentation with the maximum size)
+void OvsSendControlPacketWithAutoSplit(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size)
+{
+ BUF *b;
+ // Validate arguments
+ if (c == NULL || (data_size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, data_size);
+ SeekBuf(b, 0, 0);
+
+ while (true)
+ {
+ UCHAR tmp[OPENVPN_CONTROL_PACKET_MAX_DATASIZE];
+ UINT size = ReadBuf(b, tmp, sizeof(tmp));
+
+ if (size == 0)
+ {
+ break;
+ }
+
+ OvsSendControlPacket(c, opcode, tmp, size);
+ //Debug(" *** CNT SEND %u\n", size);
+ }
+
+ FreeBuf(b);
+}
+
+// Send the control packet
+void OvsSendControlPacket(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size)
+{
+ OPENVPN_CONTROL_PACKET *p;
+ // Validate arguments
+ if (c == NULL || (data_size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ p = ZeroMalloc(sizeof(OPENVPN_CONTROL_PACKET));
+
+ p->OpCode = opcode;
+ p->PacketId = c->NextSendPacketId++;
+
+ if (data != NULL)
+ {
+ p->Data = Clone(data, data_size);
+ p->DataSize = data_size;
+ }
+
+ p->NextSendTime = 0;
+
+ Add(c->SendControlPacketList, p);
+}
+
+// Release the control packet being transmitted
+void OvsFreeControlPacket(OPENVPN_CONTROL_PACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->Data != NULL)
+ {
+ Free(p->Data);
+ }
+
+ Free(p);
+}
+
+// Get a list of packet ID to be responded
+UINT OvsGetAckReplyList(OPENVPN_CHANNEL *c, UINT *ret)
+{
+ UINT i;
+ LIST *o = NULL;
+ UINT num;
+ // Validate arguments
+ if (c == NULL || ret == NULL)
+ {
+ return 0;
+ }
+
+ num = MIN(LIST_NUM(c->AckReplyList), OPENVPN_MAX_NUMACK);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT *v = LIST_DATA(c->AckReplyList, i);
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, v);
+
+ ret[i] = *v;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT *v = LIST_DATA(o, i);
+
+ Delete(c->AckReplyList, v);
+
+ Free(v);
+ }
+
+ ReleaseList(o);
+
+ return num;
+}
+
+// Release the channel
+void OvsFreeChannel(OPENVPN_CHANNEL *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->SslPipe != NULL)
+ {
+ FreeSslPipe(c->SslPipe);
+ }
+
+ ReleaseIntList(c->AckReplyList);
+
+ for (i = 0;i < LIST_NUM(c->SendControlPacketList);i++)
+ {
+ OPENVPN_CONTROL_PACKET *p = LIST_DATA(c->SendControlPacketList, i);
+
+ OvsFreeControlPacket(p);
+ }
+
+ ReleaseList(c->SendControlPacketList);
+
+ FreeCipher(c->CipherDecrypt);
+ FreeCipher(c->CipherEncrypt);
+
+ FreeMd(c->MdRecv);
+ FreeMd(c->MdSend);
+
+ Free(c);
+}
+
+// Create a new channel
+OPENVPN_CHANNEL *OvsNewChannel(OPENVPN_SESSION *se, UCHAR key_id)
+{
+ OPENVPN_CHANNEL *c;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(OPENVPN_CHANNEL));
+
+ c->Session = se;
+ c->Server = se->Server;
+
+ c->Status = OPENVPN_CHANNEL_STATUS_INIT;
+
+ c->AckReplyList = NewIntList(true);
+
+ c->SendControlPacketList = NewListFast(NULL);
+
+ c->KeyId = key_id;
+
+ Rand(c->NextIv, sizeof(c->NextIv));
+
+ //c->NextRekey = se->Server->Now + (UINT64)5000;
+
+ se->LastCreatedChannelIndex = key_id;
+
+ return c;
+}
+
+// Create a new server-side channel ID
+UINT64 OvsNewServerSessionId(OPENVPN_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ UINT64 id = Rand64();
+ UINT i;
+ bool exists = false;
+
+ if (id == 0 || id == (UINT64)(0xFFFFFFFFFFFFFFFFULL))
+ {
+ continue;
+ }
+
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+ if (se->ServerSessionId == id)
+ {
+ exists = true;
+ }
+ }
+
+ if (exists == false)
+ {
+ return id;
+ }
+ }
+}
+
+// Build and submit the OpenVPN data packet
+void OvsSendDataPacket(OPENVPN_CHANNEL *c, UCHAR key_id, UINT data_packet_id, void *data, UINT data_size)
+{
+ UCHAR uc;
+ UCHAR *encrypted_data;
+ UINT encrypted_size;
+ UCHAR *dest_data;
+ UINT dest_size;
+ UINT r;
+
+ // Validate arguments
+ if (c == NULL || data == NULL || data_size == 0)
+ {
+ return;
+ }
+
+ uc = ((OPENVPN_P_DATA_V1 << 3) & 0xF8) | (key_id & 0x07);
+
+ // Generate the data to be encrypted
+
+ encrypted_size = sizeof(UINT) + data_size;
+ encrypted_data = ZeroMalloc(encrypted_size);
+
+ WRITE_UINT(encrypted_data, data_packet_id);
+ Copy(encrypted_data + sizeof(UINT), data, data_size);
+
+ // Prepare a buffer to store the results
+ dest_data = Malloc(sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize + encrypted_size + 256);
+
+ // Encrypt
+ r = CipherProcess(c->CipherEncrypt, c->NextIv, dest_data + sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize,
+ encrypted_data, encrypted_size);
+ dest_size = sizeof(UCHAR) + c->MdSend->Size + c->CipherEncrypt->IvSize + r;
+
+ // Copy the IV
+ Copy(dest_data + sizeof(UCHAR) + c->MdSend->Size, c->NextIv, c->CipherEncrypt->IvSize);
+
+ // Calculate the HMAC
+ MdProcess(c->MdSend, dest_data + sizeof(UCHAR), dest_data + sizeof(UCHAR) + c->MdSend->Size,
+ dest_size - sizeof(UCHAR) - c->MdSend->Size);
+
+ // Update the NextIV
+ Copy(c->NextIv, dest_data + dest_size - c->CipherEncrypt->IvSize, c->CipherEncrypt->IvSize);
+
+ // Op-code
+ dest_data[0] = uc;
+
+ OvsSendPacketRawNow(c->Server, c->Session, dest_data, dest_size);
+
+ Free(encrypted_data);
+}
+
+// Build an OpenVPN control packet
+BUF *OvsBuildPacket(OPENVPN_PACKET *p)
+{
+ BUF *b;
+ UCHAR uc;
+ UINT num_ack;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // OpCode + KeyID
+ uc = ((p->OpCode << 3) & 0xF8) | (p->KeyId & 0x07);
+ WriteBufChar(b, uc);
+
+ if (p->OpCode == OPENVPN_P_DATA_V1)
+ {
+ // Data Packet
+ WriteBuf(b, p->Data, p->DataSize);
+ SeekBuf(b, 0, 0);
+ return b;
+ }
+
+ // Sender Channel ID
+ WriteBufInt64(b, p->MySessionId);
+
+ // NumAck
+ num_ack = MIN(p->NumAck, OPENVPN_MAX_NUMACK);
+ WriteBufChar(b, (UCHAR)num_ack);
+
+ if (p->NumAck >= 1)
+ {
+ UINT i;
+
+ for (i = 0;i < num_ack;i++)
+ {
+ WriteBufInt(b, (UCHAR)p->AckPacketId[i]);
+ }
+
+ // Received Channel ID
+ WriteBufInt64(b, p->YourSessionId);
+ }
+
+ if (p->OpCode != OPENVPN_P_ACK_V1)
+ {
+ // Packet ID
+ WriteBufInt(b, p->PacketId);
+
+ // Payload
+ if (p->DataSize >= 1 && p->Data != NULL)
+ {
+ WriteBuf(b, p->Data, p->DataSize);
+ }
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Parse the OpenVPN packet
+OPENVPN_PACKET *OvsParsePacket(UCHAR *data, UINT size)
+{
+ UCHAR uc;
+ OPENVPN_PACKET *ret = NULL;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(OPENVPN_PACKET));
+
+ // OpCode + KeyID
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ uc = *((UCHAR *)data);
+ data++;
+ size--;
+
+ ret->OpCode = ((uc & 0xF8) >> 3) & 0x1F;
+ ret->KeyId = uc & 0x07;
+
+ if (ret->OpCode == OPENVPN_P_DATA_V1)
+ {
+ // Data packet
+ ret->DataSize = size;
+ ret->Data = Clone(data, size);
+ return ret;
+ }
+
+ // Sender Channel ID
+ if (size < sizeof(UINT64))
+ {
+ goto LABEL_ERROR;
+ }
+ ret->MySessionId = READ_UINT64(data);
+ data += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // ACK
+ if (size < 1)
+ {
+ goto LABEL_ERROR;
+ }
+ uc = *((UCHAR *)data);
+ data++;
+ size--;
+
+ ret->NumAck = uc;
+
+ if (ret->NumAck > 4)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (ret->NumAck >= 1)
+ {
+ UINT i;
+
+ if (size < (sizeof(UINT) * (UINT)ret->NumAck + sizeof(UINT64)))
+ {
+ goto LABEL_ERROR;
+ }
+
+ for (i = 0;i < ret->NumAck;i++)
+ {
+ UINT ui;
+
+ ui = READ_UINT(data);
+
+ ret->AckPacketId[i] = ui;
+
+ data += sizeof(UINT);
+ size -= sizeof(UINT);
+ }
+
+ ret->YourSessionId = READ_UINT64(data);
+ data += sizeof(UINT64);
+ size -= sizeof(UINT64);
+ }
+
+ if (ret->OpCode != OPENVPN_P_ACK_V1)
+ {
+ // Read the Packet ID Because in the case of other than ACK
+ if (size < sizeof(UINT))
+ {
+ goto LABEL_ERROR;
+ }
+
+ ret->PacketId = READ_UINT(data);
+ data += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ // Payload
+ ret->DataSize = size;
+ if (size >= 1)
+ {
+ ret->Data = Clone(data, size);
+ }
+ }
+
+ return ret;
+
+LABEL_ERROR:
+ Debug("OvsParsePacket Error.\n");
+ if (ret != NULL)
+ {
+ OvsFreePacket(ret);
+ }
+ return NULL;
+}
+
+// Release the OpenVPN packet
+void OvsFreePacket(OPENVPN_PACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->Data != NULL)
+ {
+ Free(p->Data);
+ }
+
+ Free(p);
+}
+
+// If the session does not exist, create a session
+OPENVPN_SESSION *OvsFindOrCreateSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol)
+{
+ OPENVPN_SESSION *se;
+ // Validate arguments
+ if (s == NULL || server_ip == NULL || server_port == 0 || client_ip == NULL || client_port == 0)
+ {
+ return NULL;
+ }
+
+ se = OvsSearchSession(s, server_ip, server_port, client_ip, client_port, protocol);
+ if (se == NULL)
+ {
+ se = OvsNewSession(s, server_ip, server_port, client_ip, client_port, protocol);
+
+ if (se != NULL)
+ {
+ Insert(s->SessionList, se);
+ }
+ }
+
+ return se;
+}
+
+// Get the number of sessions currently connected from the IP address of the client
+UINT OvsGetNumSessionByClientIp(OPENVPN_SERVER *s, IP *ip)
+{
+ UINT i;
+ UINT ret = 0;
+ // Validate arguments
+ if (s == NULL || ip == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+
+ if (CmpIpAddr(&se->ClientIp, ip) == 0)
+ {
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+// Create a new session
+OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol)
+{
+ OPENVPN_SESSION *se;
+ char server_ip_str[MAX_SIZE];
+ char client_ip_str[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || server_ip == NULL || server_port == 0 || client_ip == NULL || client_port == 0)
+ {
+ return NULL;
+ }
+
+
+ if (OvsGetNumSessionByClientIp(s, client_ip) > OPENVPN_QUOTA_MAX_NUM_SESSIONS_PER_IP)
+ {
+ // Number of sessions from the same IP address too many
+ return NULL;
+ }
+
+ if (LIST_NUM(s->SessionList) > OPENVPN_QUOTA_MAX_NUM_SESSIONS)
+ {
+ // Too many OpenVPN sessions
+ return NULL;
+ }
+
+ se = ZeroMalloc(sizeof(OPENVPN_SESSION));
+
+ se->Server = s;
+
+ Copy(&se->ClientIp, client_ip, sizeof(IP));
+ se->ClientPort = client_port;
+
+ Copy(&se->ServerIp, server_ip, sizeof(IP));
+ se->ServerPort = server_port;
+
+ se->LastCommTick = s->Now;
+
+ se->Protocol = protocol;
+
+ se->ServerSessionId = OvsNewServerSessionId(se->Server);
+
+ se->CreatedTick = s->Now;
+
+ se->Id = s->NextSessionId;
+ s->NextSessionId++;
+
+ IPToStr(server_ip_str, sizeof(server_ip_str), server_ip);
+ IPToStr(client_ip_str, sizeof(client_ip_str), client_ip);
+ Debug("OpenVPN New Session: %s:%u -> %s:%u Proto=%u\n", server_ip_str, server_port,
+ client_ip_str, client_port, protocol);
+
+ OvsLog(s, se, NULL, "LO_NEW_SESSION", (protocol == OPENVPN_PROTOCOL_UDP ? "UDP" : "TCP"));
+
+ return se;
+}
+
+// Release the session
+void OvsFreeSession(OPENVPN_SESSION *se)
+{
+ UINT i;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return;
+ }
+
+ // If there is IP addresses which is got from a DHCP server in the session, release it
+ if (se->Ipc != NULL)
+ {
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ if (se->IpcAsync != NULL)
+ {
+ IP dhcp_ip;
+
+ UINTToIP(&dhcp_ip, se->IpcAsync->L3ClientAddressOption.ServerAddress);
+
+ IPCDhcpFreeIP(se->Ipc, &dhcp_ip);
+ IPCProcessL3Events(se->Ipc);
+ }
+ }
+ }
+
+ // Release the channel
+ for (i = 0;i < OPENVPN_NUM_CHANNELS;i++)
+ {
+ OPENVPN_CHANNEL *c = se->Channels[i];
+
+ if (c != NULL)
+ {
+ OvsFreeChannel(c);
+ }
+ }
+
+ // Release the IPC
+ if (se->Ipc != NULL)
+ {
+ FreeIPC(se->Ipc);
+ }
+
+ if (se->IpcAsync != NULL)
+ {
+ FreeIPCAsync(se->IpcAsync);
+ }
+
+ Free(se);
+}
+
+// Search the session from the endpoint information
+OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol)
+{
+ OPENVPN_SESSION *se;
+ OPENVPN_SESSION t;
+ // Validate arguments
+ if (s == NULL || server_ip == NULL || server_port == 0 || client_ip == NULL || client_port == 0)
+ {
+ return NULL;
+ }
+
+ Copy(&t.ClientIp, client_ip, sizeof(IP));
+ t.ClientPort = client_port;
+ Copy(&t.ServerIp, server_ip, sizeof(IP));
+ t.ServerPort = server_port;
+ t.Protocol = protocol;
+
+ se = Search(s->SessionList, &t);
+
+ return se;
+}
+
+// Receive packets in the OpenVPN server
+void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
+{
+ UINT i, j;
+ LIST *delete_session_list = NULL;
+ // Validate arguments
+ if (s == NULL || recv_packet_list == NULL)
+ {
+ return;
+ }
+
+ s->Now = Tick64();
+
+ // Process for all sessions
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+
+ if (se->Ipc != NULL)
+ {
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ // Flush the ARP table of the IPC
+ IPCFlushArpTableEx(se->Ipc, s->Now);
+ }
+ }
+ }
+
+ // Process received packets
+ for (i = 0;i < LIST_NUM(recv_packet_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(recv_packet_list, i);
+
+ OvsProceccRecvPacket(s, p, protocol);
+ }
+
+ // Treat for all sessions and all channels
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_CHANNEL *latest_channel = NULL;
+ UINT64 max_tick = 0;
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+ bool is_disconnected = false;
+
+ if (se->Ipc != NULL)
+ {
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ IPCProcessL3Events(se->Ipc);
+ }
+ }
+
+ for (j = 0;j < OPENVPN_NUM_CHANNELS;j++)
+ {
+ OPENVPN_CHANNEL *c = se->Channels[j];
+
+ if (c != NULL)
+ {
+ if (c->RekeyInitiated == false && ((c->NextRekey <= s->Now && c->NextRekey != 0) || (c->LastDataPacketId >= OPENVPN_MAX_PACKET_ID_FOR_TRIGGER_REKEY)))
+ {
+ OPENVPN_CHANNEL *c2;
+ // Send a soft reset by creating a new channel
+ UINT next_channel_id = se->LastCreatedChannelIndex + 1;
+ if (next_channel_id >= OPENVPN_NUM_CHANNELS)
+ {
+ next_channel_id = 1;
+ }
+ if (se->Channels[next_channel_id] != NULL)
+ {
+ // Release when there is a channel data already
+ OvsFreeChannel(se->Channels[next_channel_id]);
+ se->Channels[next_channel_id] = NULL;
+ }
+
+ // Create a new channel
+ c2 = OvsNewChannel(se, (UCHAR)next_channel_id);
+ c2->IsInitiatorServer = true;
+ se->Channels[next_channel_id] = c2;
+ Debug("OpenVPN New Channel for Re-Keying :%u\n", next_channel_id);
+ OvsLog(s, se, c, "LO_INITIATE_REKEY");
+
+ // Send a soft reset
+ OvsSendControlPacket(c2, OPENVPN_P_CONTROL_SOFT_RESET_V1, NULL, 0);
+
+ c->RekeyInitiated = true;
+ }
+ }
+
+ if (c != NULL)
+ {
+ switch (c->Status)
+ {
+ case OPENVPN_CHANNEL_STATUS_TLS_VPN_CONNECTING:
+ // Check whether the connection process completed if there is a channel running a VPN connection process
+ if (se->IpcAsync != NULL)
+ {
+ if (se->IpcAsync->Done)
+ {
+ if (se->IpcAsync->Ipc != NULL)
+ {
+ char option_str[MAX_SIZE];
+ char l3_options[MAX_SIZE];
+
+ // Successful in VPN connection
+ Debug("OpenVPN Channel %u Established (new key).\n", j);
+ OvsLog(s, se, c, "LO_CHANNEL_ESTABLISHED");
+
+ // Return the PUSH_REPLY
+ Format(option_str, sizeof(option_str),
+ "PUSH_REPLY,ping %u,ping-restart %u",
+ (OPENVPN_PING_SEND_INTERVAL / 1000),
+ (OPENVPN_RECV_TIMEOUT / 1000));
+
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ // Add such as the IP address that was acquired from the DHCP server
+ // if the L3 mode to the option character string
+ DHCP_OPTION_LIST *cao = &se->IpcAsync->L3ClientAddressOption;
+ char ip_client[64];
+ char ip_tunnel_endpoint[64];
+ UINT ip_tunnel_endpoint_32;
+ char ip_network[64];
+ char ip_subnet_mask[64];
+ char ip_dns1[64];
+ char ip_dns2[64];
+ char ip_wins1[64];
+ char ip_wins2[64];
+ char ip_defgw[64];
+
+ ClearStr(ip_dns1, sizeof(ip_dns1));
+ ClearStr(ip_dns2, sizeof(ip_dns2));
+ ClearStr(ip_wins1, sizeof(ip_wins1));
+ ClearStr(ip_wins2, sizeof(ip_wins2));
+ ClearStr(ip_defgw, sizeof(ip_defgw));
+
+ IPToStr32(ip_client, sizeof(ip_client),
+ cao->ClientAddress);
+
+ // Generate a virtual gateway address to be passed to the OpenVPN
+ ip_tunnel_endpoint_32 = Endian32(cao->ClientAddress);
+ ip_tunnel_endpoint_32++;
+ ip_tunnel_endpoint_32 = Endian32(ip_tunnel_endpoint_32);
+ IPToStr32(ip_tunnel_endpoint, sizeof(ip_tunnel_endpoint), ip_tunnel_endpoint_32);
+
+ // Create a subnet information for the LAN
+ IPToStr32(ip_network, sizeof(ip_network),
+ GetNetworkAddress(cao->ClientAddress,
+ cao->SubnetMask));
+
+ IPToStr32(ip_subnet_mask, sizeof(ip_subnet_mask),
+ cao->SubnetMask);
+
+ Format(l3_options, sizeof(l3_options),
+ ",ifconfig %s %s",
+// ",ifconfig %s %s,route %s %s %s 1",
+ ip_client, ip_tunnel_endpoint, ip_network, ip_subnet_mask,
+ ip_tunnel_endpoint);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ // Domain name
+ if (IsEmptyStr(cao->DomainName) == false)
+ {
+ Format(l3_options, sizeof(l3_options),
+ ",dhcp-option DOMAIN %s", cao->DomainName);
+ StrCat(option_str, sizeof(option_str), l3_options);
+ }
+
+ // DNS server address 1
+ if (cao->DnsServer != 0)
+ {
+ char ip_str[64];
+ IPToStr32(ip_str, sizeof(ip_str), cao->DnsServer);
+ Format(l3_options, sizeof(l3_options),
+ ",dhcp-option DNS %s", ip_str);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ StrCpy(ip_dns1, sizeof(ip_dns1), ip_str);
+ }
+
+ // DNS server address 2
+ if (cao->DnsServer2 != 0)
+ {
+ char ip_str[64];
+ IPToStr32(ip_str, sizeof(ip_str), cao->DnsServer2);
+ Format(l3_options, sizeof(l3_options),
+ ",dhcp-option DNS %s", ip_str);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ StrCpy(ip_dns2, sizeof(ip_dns2), ip_str);
+ }
+
+ // WINS address 1
+ if (cao->WinsServer != 0)
+ {
+ char ip_str[64];
+ IPToStr32(ip_str, sizeof(ip_str), cao->WinsServer);
+ Format(l3_options, sizeof(l3_options),
+ ",dhcp-option WINS %s", ip_str);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ StrCpy(ip_wins1, sizeof(ip_wins1), ip_str);
+ }
+
+ // WINS address 2
+ if (cao->WinsServer2 != 0)
+ {
+ char ip_str[64];
+ IPToStr32(ip_str, sizeof(ip_str), cao->WinsServer2);
+ Format(l3_options, sizeof(l3_options),
+ ",dhcp-option WINS %s", ip_str);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ StrCpy(ip_wins2, sizeof(ip_wins2), ip_str);
+ }
+
+ // Default gateway
+ if (cao->Gateway != 0)
+ {
+ Format(l3_options, sizeof(l3_options),
+ ",route-gateway %s,redirect-gateway def1", ip_tunnel_endpoint);
+ StrCat(option_str, sizeof(option_str), l3_options);
+
+ IPToStr32(ip_defgw, sizeof(ip_defgw), cao->Gateway);
+ }
+
+ OvsLog(s, se, c, "LP_SET_IPV4_PARAM",
+ ip_client, ip_subnet_mask, ip_defgw, ip_dns1, ip_dns2, ip_wins1, ip_wins2);
+ }
+
+ WriteFifo(c->SslPipe->SslInOut->SendFifo, option_str, StrSize(option_str));
+
+ Debug("Push Str: %s\n", option_str);
+ OvsLog(s, se, c, "LO_PUSH_REPLY", option_str);
+
+ StrCpy(se->PushReplyStr, sizeof(se->PushReplyStr), option_str);
+
+ se->Ipc = se->IpcAsync->Ipc;
+ se->IpcAsync->Ipc = NULL;
+
+ s->SessionEstablishedCount++;
+
+ // Set a Sock Event of IPC to Sock Event of the UDP Listener
+ IPCSetSockEventWhenRecvL2Packet(se->Ipc, s->SockEvent);
+
+ // State transition
+ c->Status = OPENVPN_CHANNEL_STATUS_ESTABLISHED;
+ c->EstablishedTick = s->Now;
+ se->Established = true;
+ se->LastCommTick = Tick64();
+ }
+ else
+ {
+ char *str;
+
+ if (se->IpcAsync->DhcpAllocFailed)
+ {
+ OvsLog(s, se, c, "LP_DHCP_REQUEST_NG");
+ }
+
+ // Failed to connect VPN
+ Debug("OpenVPN Channel %u Failed.\n", j);
+ OvsLog(s, se, c, "LO_CHANNEL_FAILED");
+
+ // Return the AUTH_FAILED
+ str = "AUTH_FAILED";
+ WriteFifo(c->SslPipe->SslInOut->SendFifo, str, StrSize(str));
+
+ s->SessionEstablishedCount++;
+
+ // State transition
+ c->Status = OPENVPN_CHANNEL_STATUS_DISCONNECTED;
+
+ FreeIPCAsync(se->IpcAsync);
+ se->IpcAsync = NULL;
+ }
+ }
+ }
+ break;
+
+ case OPENVPN_CHANNEL_STATUS_ESTABLISHED:
+ // Monitor the IPC whether not disconnected when there is a VPN connection completed channel
+ if (IsIPCConnected(se->Ipc) == false)
+ {
+ // Send the RESTART since IPC is disconnected
+ char *str = "RESTART";
+ Debug("OpenVPN Channel %u Disconnected by HUB.\n", j);
+
+ OvsLog(s, se, c, "LO_CHANNEL_DISCONNECTED_BY_HUB");
+
+ WriteFifo(c->SslPipe->SslInOut->SendFifo, str, StrSize(str));
+
+ // State transition
+ c->Status = OPENVPN_CHANNEL_STATUS_DISCONNECTED;
+
+ // Set the session to disconnected state
+ se->Established = false;
+ se->LastCommTick = s->Now;
+ }
+ break;
+ }
+ }
+
+ if (c != NULL)
+ {
+ // If there is a packet to be transmitted physically in SSL, send it
+ if (c->SslPipe != NULL && SyncSslPipe(c->SslPipe))
+ {
+ if (FifoSize(c->SslPipe->RawOut->RecvFifo) >= 1)
+ {
+ Debug("RawOut Fifo Size (c=%u): %u\n", c->KeyId, FifoSize(c->SslPipe->RawOut->RecvFifo));
+
+ OvsSendControlPacketWithAutoSplit(c, OPENVPN_P_CONTROL_V1,
+ FifoPtr(c->SslPipe->RawOut->RecvFifo),
+ FifoSize(c->SslPipe->RawOut->RecvFifo));
+
+ ReadFifo(c->SslPipe->RawOut->RecvFifo, NULL, FifoSize(c->SslPipe->RawOut->RecvFifo));
+ }
+ }
+ }
+
+ if (c != NULL)
+ {
+ UINT num;
+ UINT acks[OPENVPN_MAX_NUMACK];
+ UINT k;
+
+ // Packet transmission
+ for (k = 0;k < LIST_NUM(c->SendControlPacketList);k++)
+ {
+ OPENVPN_CONTROL_PACKET *cp = LIST_DATA(c->SendControlPacketList, k);
+
+ if (cp->NextSendTime <= s->Now)
+ {
+ OPENVPN_PACKET *p;
+
+ num = OvsGetAckReplyList(c, acks);
+
+ p = OvsNewControlPacket(cp->OpCode, j, se->ServerSessionId, num, acks,
+ se->ClientSessionId, cp->PacketId, cp->DataSize, cp->Data);
+
+ OvsSendPacketNow(s, se, p);
+
+ OvsFreePacket(p);
+
+ cp->NextSendTime = s->Now + (UINT64)OPENVPN_CONTROL_PACKET_RESEND_INTERVAL;
+
+ AddInterrupt(s->Interrupt, cp->NextSendTime);
+ }
+ }
+
+ // If the response with an ACK-only packet is required, respond such that
+ num = OvsGetAckReplyList(c, acks);
+
+ if (num >= 1)
+ {
+ OPENVPN_PACKET *p = OvsNewControlPacket(OPENVPN_P_ACK_V1, j, se->ServerSessionId,
+ num, acks, se->ClientSessionId, 0, 0, NULL);
+
+ OvsSendPacketNow(s, se, p);
+
+ OvsFreePacket(p);
+ }
+ }
+ }
+
+ if (se->Ipc != NULL)
+ {
+ if (se->Mode == OPENVPN_MODE_L3)
+ {
+ if (se->IpcAsync != NULL)
+ {
+ // Update DHCP address
+ if (se->IpcAsync->L3NextDhcpRenewTick <= s->Now)
+ {
+ IP ip;
+
+ se->IpcAsync->L3NextDhcpRenewTick = s->Now + se->IpcAsync->L3DhcpRenewInterval;
+
+ UINTToIP(&ip, se->IpcAsync->L3ClientAddressOption.ServerAddress);
+
+ IPCDhcpRenewIP(se->Ipc, &ip);
+ }
+ }
+
+ IPCProcessL3Events(se->Ipc);
+ }
+
+ IPCProcessInterrupts(se->Ipc);
+ }
+
+ // Choose the latest channel in all established channels
+ for (j = 0;j < OPENVPN_NUM_CHANNELS;j++)
+ {
+ OPENVPN_CHANNEL *c = se->Channels[j];
+
+ if (c != NULL)
+ {
+ if (c->Status == OPENVPN_CHANNEL_STATUS_ESTABLISHED)
+ {
+ if (max_tick <= c->EstablishedTick)
+ {
+ max_tick = c->EstablishedTick;
+ latest_channel = c;
+ }
+ }
+ }
+ }
+
+ if (se->Established == false)
+ {
+ latest_channel = NULL;
+ }
+
+ // Send the data using the latest channel (when there is no transmission channel, suck out the queue simply)
+ if (se->Mode == OPENVPN_MODE_L2)
+ {
+ // Get an Ethernet frame from IPC
+ while (true)
+ {
+ BLOCK *b = IPCRecvL2(se->Ipc);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ if (latest_channel != NULL && s->SupressSendPacket == false)
+ {
+ OvsSendDataPacket(latest_channel, latest_channel->KeyId, ++latest_channel->LastDataPacketId, b->Buf, b->Size);
+ }
+
+ FreeBlock(b);
+ }
+ }
+ else
+ {
+ // Get an IPv4 packet from IPC
+ while (true)
+ {
+ BLOCK *b = IPCRecvIPv4(se->Ipc);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ if (latest_channel != NULL && s->SupressSendPacket == false)
+ {
+ OvsSendDataPacket(latest_channel, latest_channel->KeyId, ++latest_channel->LastDataPacketId, b->Buf, b->Size);
+ }
+
+ FreeBlock(b);
+ }
+ }
+
+ // Send a Ping
+ if (latest_channel != NULL)
+ {
+ if ((se->NextPingSendTick == 0) || (se->NextPingSendTick <= s->Now))
+ {
+ se->NextPingSendTick = s->Now + (UINT64)(OPENVPN_PING_SEND_INTERVAL);
+
+ OvsSendDataPacket(latest_channel, latest_channel->KeyId, ++latest_channel->LastDataPacketId,
+ ping_signature, sizeof(ping_signature));
+ //Debug(".");
+
+ AddInterrupt(s->Interrupt, se->NextPingSendTick);
+ }
+ }
+
+ if ((se->Established == false) && (s->Now >= (se->CreatedTick + (UINT64)OPENVPN_NEW_SESSION_DEADLINE_TIMEOUT)))
+ {
+ is_disconnected = true;
+ }
+
+ if (se->Established && (s->Now >= (se->LastCommTick + (UINT64)OPENVPN_RECV_TIMEOUT)))
+ {
+ is_disconnected = true;
+ }
+
+ if (is_disconnected)
+ {
+ if (delete_session_list == NULL)
+ {
+ delete_session_list = NewListFast(NULL);
+ }
+
+ Add(delete_session_list, se);
+ }
+ }
+
+ if (delete_session_list != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(delete_session_list);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(delete_session_list, i);
+
+ Debug("Deleting Session %p\n", se);
+ OvsLog(s, se, NULL, "LO_DELETE_SESSION");
+
+ OvsFreeSession(se);
+
+ s->DisconnectCount++;
+
+ Delete(s->SessionList, se);
+ }
+
+ ReleaseList(delete_session_list);
+ }
+}
+
+// Send the packet now
+void OvsSendPacketNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_PACKET *p)
+{
+ BUF *b;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || se == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Debug("Sending Opcode=%u ", p->OpCode);
+ if (p->NumAck >= 1)
+ {
+ Debug("Sending ACK Packet IDs (c=%u): ", p->KeyId);
+ for (i = 0;i < p->NumAck;i++)
+ {
+ Debug("%u ", p->AckPacketId[i]);
+ }
+ }
+ Debug("\n");
+
+ b = OvsBuildPacket(p);
+
+ OvsSendPacketRawNow(s, se, b->Buf, b->Size);
+
+ Free(b);
+}
+void OvsSendPacketRawNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, void *data, UINT size)
+{
+ UDPPACKET *u;
+
+ // Validate arguments
+ if (s == NULL || se == NULL || data == NULL || size == 0)
+ {
+ Free(data);
+ return;
+ }
+
+ u = NewUdpPacket(&se->ServerIp, se->ServerPort, &se->ClientIp, se->ClientPort,
+ data, size);
+
+ Add(s->SendPacketList, u);
+}
+// Create a new OpenVPN control packet
+OPENVPN_PACKET *OvsNewControlPacket(UCHAR opcode, UCHAR key_id, UINT64 my_channel_id, UINT num_ack,
+ UINT *ack_packet_ids, UINT64 your_channel_id, UINT packet_id,
+ UINT data_size, UCHAR *data)
+{
+ OPENVPN_PACKET *p = ZeroMalloc(sizeof(OPENVPN_PACKET));
+ UINT i;
+
+ p->OpCode = opcode;
+ p->KeyId = key_id;
+ p->MySessionId = my_channel_id;
+ p->NumAck = num_ack;
+
+ for (i = 0;i < MIN(num_ack, OPENVPN_MAX_NUMACK);i++)
+ {
+ p->AckPacketId[i] = ack_packet_ids[i];
+ }
+
+ p->YourSessionId = your_channel_id;
+ p->PacketId = packet_id;
+
+ if (data_size != 0 && data != NULL)
+ {
+ p->Data = Clone(data, data_size);
+ p->DataSize = data_size;
+ }
+
+ return p;
+}
+
+// Comparison function of the entries in the session list
+int OvsCompareSessionList(void *p1, void *p2)
+{
+ OPENVPN_SESSION *s1, *s2;
+ int i;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(OPENVPN_SESSION **)p1;
+ s2 = *(OPENVPN_SESSION **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ i = CmpIpAddr(&s1->Protocol, &s2->Protocol);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ i = CmpIpAddr(&s1->ClientIp, &s2->ClientIp);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ i = COMPARE_RET(s1->ClientPort, s2->ClientPort);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ i = CmpIpAddr(&s1->ServerIp, &s2->ServerIp);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ i = COMPARE_RET(s1->ServerPort, s2->ServerPort);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ return 0;
+}
+
+// Identify whether the IP address is compatible to the tun device of OpenVPN
+bool OvsIsCompatibleL3IP(UINT ip)
+{
+ IP p;
+
+ UINTToIP(&p, ip);
+ if ((p.addr[3] % 4) == 1)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get an IP address that is compatible to tun device of the OpenVPN after the specified IP address
+UINT OvsGetCompatibleL3IPNext(UINT ip)
+{
+ ip = Endian32(ip);
+
+ while (true)
+ {
+ if (OvsIsCompatibleL3IP(Endian32(ip)))
+ {
+ return Endian32(ip);
+ }
+
+ ip++;
+ }
+}
+
+// Create a new OpenVPN server
+OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event)
+{
+ OPENVPN_SERVER *s;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(OPENVPN_SERVER));
+
+ s->Cedar = cedar;
+
+ AddRef(s->Cedar->ref);
+
+ s->Interrupt = interrupt;
+
+ s->SessionList = NewList(OvsCompareSessionList);
+ s->SendPacketList = NewListFast(NULL);
+
+ s->Now = Tick64();
+
+ s->NextSessionId = 1;
+
+ if (sock_event != NULL)
+ {
+ s->SockEvent = sock_event;
+ AddRef(s->SockEvent->ref);
+ }
+
+ OvsLog(s, NULL, NULL, "LO_START");
+
+ s->Dh = DhNewGroup2();
+
+ return s;
+}
+
+// Release the OpenVPN server
+void FreeOpenVpnServer(OPENVPN_SERVER *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ OvsLog(s, NULL, NULL, "LO_STOP");
+
+ // Release the session list
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+
+ OvsFreeSession(se);
+ }
+
+ ReleaseList(s->SessionList);
+
+ // Release the packet which is attempting to send
+ for (i = 0;i < LIST_NUM(s->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(s->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(s->SendPacketList);
+
+ ReleaseCedar(s->Cedar);
+
+ if (s->SockEvent != NULL)
+ {
+ ReleaseSockEvent(s->SockEvent);
+ }
+
+ DhFree(s->Dh);
+
+ Free(s);
+}
+
+// UDP reception procedure
+void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list)
+{
+ OPENVPN_SERVER_UDP *us;
+ UINT64 now = Tick64();
+ // Validate arguments
+ if (u == NULL || packet_list == NULL)
+ {
+ return;
+ }
+
+ us = (OPENVPN_SERVER_UDP *)u->Param;
+
+ if (OvsGetNoOpenVpnUdp())
+ {
+ // OpenVPN over UDP is disabled
+ return;
+ }
+
+ if (us->OpenVpnServer != NULL)
+ {
+ {
+ u->PollMyIpAndPort = false;
+
+ ClearStr(us->Cedar->OpenVPNPublicPorts, sizeof(us->Cedar->OpenVPNPublicPorts));
+ }
+
+ OvsRecvPacket(us->OpenVpnServer, packet_list, OPENVPN_PROTOCOL_UDP);
+
+ UdpListenerSendPackets(u, us->OpenVpnServer->SendPacketList);
+ DeleteAll(us->OpenVpnServer->SendPacketList);
+ }
+}
+
+// Create an OpenVPN server (UDP mode)
+OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar)
+{
+ OPENVPN_SERVER_UDP *u;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ u = ZeroMalloc(sizeof(OPENVPN_SERVER_UDP));
+
+ u->Cedar = cedar;
+
+ AddRef(u->Cedar->ref);
+
+ // Create a UDP listener
+ u->UdpListener = NewUdpListener(OpenVpnServerUdpListenerProc, u);
+
+ // Create an OpenVPN server
+ u->OpenVpnServer = NewOpenVpnServer(cedar, u->UdpListener->Interrupts, u->UdpListener->Event);
+
+ return u;
+}
+
+// Apply the port list to the OpenVPN server
+void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ DeleteAllPortFromUdpListener(u->UdpListener);
+
+ o = StrToIntList(port_list, true);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT port = *((UINT *)LIST_DATA(o, i));
+
+ if (port >= 1 && port <= 65535)
+ {
+ AddPortToUdpListener(u->UdpListener, port);
+ }
+ }
+
+ ReleaseIntList(o);
+}
+
+// Release the OpenVPN server (UDP mode)
+void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ // Stop the UDP listener
+ FreeUdpListener(u->UdpListener);
+
+ // Release the OpenVPN server
+ FreeOpenVpnServer(u->OpenVpnServer);
+
+ ReleaseCedar(u->Cedar);
+
+ Free(u);
+}
+
+// Check whether it's OpenSSL protocol by looking the first receive buffer of the TCP
+bool OvsCheckTcpRecvBufIfOpenVPNProtocol(UCHAR *buf, UINT size)
+{
+ if (buf == NULL || size != 2)
+ {
+ return false;
+ }
+
+ if (buf[0] == 0x00 && buf[1] == 0x0E)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Run the OpenVPN server in TCP mode
+bool OvsPerformTcpServer(CEDAR *cedar, SOCK *sock)
+{
+ OPENVPN_SERVER *s;
+ INTERRUPT_MANAGER *im;
+ SOCK_EVENT *se;
+ FIFO *tcp_recv_fifo;
+ FIFO *tcp_send_fifo;
+ UINT buf_size = (128 * 1024);
+ UCHAR *buf;
+ UINT64 giveup_time = Tick64() + (UINT64)OPENVPN_NEW_SESSION_DEADLINE_TIMEOUT;
+ LIST *ovs_recv_packet;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (cedar == NULL || sock == NULL)
+ {
+ return false;
+ }
+
+ // Initialize
+ buf = Malloc(buf_size);
+ im = NewInterruptManager();
+ se = NewSockEvent();
+ SetTimeout(sock, TIMEOUT_INFINITE);
+ JoinSockToSockEvent(sock, se);
+
+ tcp_recv_fifo = NewFifoFast();
+ tcp_send_fifo = NewFifoFast();
+
+ ovs_recv_packet = NewListFast(NULL);
+
+ // Create an OpenVPN server
+ s = NewOpenVpnServer(cedar, im, se);
+
+ // Main loop
+ Debug("Entering OpenVPN TCP Server Main Loop.\n");
+ while (true)
+ {
+ UINT next_interval;
+ bool disconnected = false;
+ UINT64 now = Tick64();
+
+ // Receive data from a TCP socket
+ while (true)
+ {
+ UINT r = Recv(sock, buf, buf_size, false);
+ if (r == SOCK_LATER)
+ {
+ // Can not read any more
+ break;
+ }
+ else if (r == 0)
+ {
+ // Disconnected
+ disconnected = true;
+ break;
+ }
+ else
+ {
+ // Read
+ WriteFifo(tcp_recv_fifo, buf, r);
+ }
+ }
+
+ // Separate to a list of datagrams by interpreting the data received from the TCP socket
+ while (true)
+ {
+ UINT r = FifoSize(tcp_recv_fifo);
+ if (r >= sizeof(USHORT))
+ {
+ void *ptr = FifoPtr(tcp_recv_fifo);
+ USHORT packet_size = READ_USHORT(ptr);
+ if (packet_size <= OPENVPN_TCP_MAX_PACKET_SIZE)
+ {
+ UINT total_len = (UINT)packet_size + sizeof(USHORT);
+ if (r >= total_len)
+ {
+ if (ReadFifo(tcp_recv_fifo, buf, total_len) != total_len)
+ {
+ // Mismatch
+ disconnected = true;
+ break;
+ }
+ else
+ {
+ // Read one packet
+ UINT payload_len = packet_size;
+ UCHAR *payload_ptr = buf + sizeof(USHORT);
+
+ // Pass the packet to the OpenVPN server
+ Add(ovs_recv_packet, NewUdpPacket(&sock->RemoteIP, sock->RemotePort,
+ &sock->LocalIP, sock->LocalPort,
+ Clone(payload_ptr, payload_len), payload_len));
+ }
+ }
+ else
+ {
+ // Non-arrival
+ break;
+ }
+ }
+ else
+ {
+ // Invalid packet size
+ disconnected = true;
+ break;
+ }
+ }
+ else
+ {
+ // Non-arrival
+ break;
+ }
+ }
+
+ // Pass a list of received datagrams to the OpenVPN server
+ OvsRecvPacket(s, ovs_recv_packet, OPENVPN_PROTOCOL_TCP);
+
+ // Release the received packet list
+ for (i = 0;i < LIST_NUM(ovs_recv_packet);i++)
+ {
+ UDPPACKET *p = LIST_DATA(ovs_recv_packet, i);
+
+ FreeUdpPacket(p);
+ }
+
+ DeleteAll(ovs_recv_packet);
+
+ // Store in the queue by getting a list of the datagrams to be transmitted from the OpenVPN server
+ for (i = 0;i < LIST_NUM(s->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(s->SendPacketList, i);
+ // Store the size to the TCP send queue first
+ USHORT us = (USHORT)p->Size;
+ //Debug(" *** TCP SEND %u\n", us);
+ us = Endian16(us);
+ WriteFifo(tcp_send_fifo, &us, sizeof(USHORT));
+
+ // Write the data body
+ WriteFifo(tcp_send_fifo, p->Data, p->Size);
+
+ // Packet release
+ FreeUdpPacket(p);
+ }
+ DeleteAll(s->SendPacketList);
+
+ // Send data to the TCP socket
+ while (FifoSize(tcp_send_fifo) >= 1)
+ {
+ UINT r = Send(sock, FifoPtr(tcp_send_fifo), FifoSize(tcp_send_fifo), false);
+
+ if (r == SOCK_LATER)
+ {
+ // Can not write any more
+ break;
+ }
+ else if (r == 0)
+ {
+ // Disconnected
+ disconnected = true;
+ break;
+ }
+ else
+ {
+ // Wrote out
+ ReadFifo(tcp_send_fifo, NULL, r);
+ }
+ }
+
+ if (FifoSize(tcp_send_fifo) > MAX_BUFFERING_PACKET_SIZE)
+ {
+ s->SupressSendPacket = true;
+ }
+ else
+ {
+ s->SupressSendPacket = false;
+ }
+
+ if (s->DisconnectCount >= 1)
+ {
+ // Session disconnection has occurred on OpenVPN server-side
+ disconnected = true;
+ }
+
+ if (giveup_time <= now)
+ {
+ UINT i;
+ UINT num_established_sessions = 0;
+ for (i = 0;i < LIST_NUM(s->SessionList);i++)
+ {
+ OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
+
+ if (se->Established)
+ {
+ num_established_sessions++;
+ }
+ }
+
+ if (num_established_sessions == 0)
+ {
+ // If the number of sessions is 0 even if wait a certain period of time after the start of server, abort
+ disconnected = true;
+ }
+ }
+
+ if (disconnected)
+ {
+ // Error or disconnect occurs
+ Debug("Breaking OpenVPN TCP Server Main Loop.\n");
+ break;
+ }
+
+ // Wait until the next event occurs
+ next_interval = GetNextIntervalForInterrupt(im);
+ next_interval = MIN(next_interval, UDPLISTENER_WAIT_INTERVAL);
+ WaitSockEvent(se, next_interval);
+ }
+
+ if (s != NULL && s->SessionEstablishedCount != 0)
+ {
+ ret = true;
+ }
+
+ // Release the OpenVPN server
+ FreeOpenVpnServer(s);
+
+ // Release object
+ FreeInterruptManager(im);
+ ReleaseSockEvent(se);
+ ReleaseFifo(tcp_recv_fifo);
+ ReleaseFifo(tcp_send_fifo);
+ Free(buf);
+
+ // Release the received packet list
+ for (i = 0;i < LIST_NUM(ovs_recv_packet);i++)
+ {
+ UDPPACKET *p = LIST_DATA(ovs_recv_packet, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(ovs_recv_packet);
+
+ return ret;
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Interop_OpenVPN.h b/src/Cedar/Interop_OpenVPN.h
new file mode 100644
index 00000000..c60b6a60
--- /dev/null
+++ b/src/Cedar/Interop_OpenVPN.h
@@ -0,0 +1,362 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Interop_OpenVPN.h
+// Header of Interop_OpenVPN.c
+
+#ifndef INTEROP_OPENVPN_H
+#define INTEROP_OPENVPN_H
+
+
+//// Constants
+#define OPENVPN_UDP_PORT 1194 // OpenVPN default UDP port number
+#define OPENVPN_UDP_PORT_INCLUDE 1195 // OpenVPN default UDP port number (Operating within the client)
+
+#define OPENVPN_MAX_NUMACK 4 // The maximum number of ACKs
+#define OPENVPN_NUM_CHANNELS 8 // Maximum number of channels during a session
+#define OPENVPN_CONTROL_PACKET_RESEND_INTERVAL 500 // Control packet retransmission interval
+#define OPENVPN_CONTROL_PACKET_MAX_DATASIZE 1200 // Maximum data size that can be stored in one control packet
+
+#define OPENVPN_MAX_SSL_RECV_BUF_SIZE (256 * 1024) // SSL receive buffer maximum length
+
+#define OPENVPN_MAX_KEY_SIZE 64 // Maximum key size
+
+#define OPENVPN_TMP_BUFFER_SIZE (65536 + 256) // Temporary buffer size
+
+#define OPENVPN_PING_SEND_INTERVAL 3000 // Transmission interval of Ping
+#define OPENVPN_RECV_TIMEOUT 10000 // Communication time-out
+#define OPENVPN_NEW_SESSION_DEADLINE_TIMEOUT 30000 // Grace time to complete new VPN session connection since it was created
+
+#define OPENVPN_MAX_PACKET_ID_FOR_TRIGGER_REKEY 0xFF000000 // Packet ID that is a trigger to start the re-key
+#define OPENVPN_TCP_MAX_PACKET_SIZE 2000 // The maximum packet size allowed in TCP mode
+
+
+// The default algorithm
+#define OPENVPN_DEFAULT_CIPHER "AES-128-CBC"
+#define OPENVPN_DEFAULT_MD "SHA1"
+
+// Encryption related
+#define OPENVPN_PREMASTER_LABEL "OpenVPN master secret"
+#define OPENVPN_EXPANSION_LABEL "OpenVPN key expansion"
+
+// IPC related
+#define OPENVPN_IPC_CLIENT_NAME "OpenVPN Client"
+#define OPENVPN_IPC_POSTFIX_L2 "OPENVPN_L2"
+#define OPENVPN_IPC_POSTFIX_L3 "OPENVPN_L3"
+
+// List of supported encryption algorithms
+#define OPENVPN_CIPHER_LIST "[NULL-CIPHER] NULL AES-128-CBC AES-192-CBC AES-256-CBC BF-CBC CAST-CBC CAST5-CBC DES-CBC DES-EDE-CBC DES-EDE3-CBC DESX-CBC RC2-40-CBC RC2-64-CBC RC2-CBC"
+
+// List of the supported hash algorithm
+#define OPENVPN_MD_LIST "SHA SHA1 MD5 MD4 RMD160"
+
+// MTU
+#define OPENVPN_MTU_LINK 1514 // Ethernet MTU
+#define OPENVPN_MTU_TUN 1500 // Tun MTU
+
+// Protocol
+#define OPENVPN_PROTOCOL_UDP 0 // UDP
+#define OPENVPN_PROTOCOL_TCP 1 // TCP
+
+// Op-code
+#define OPENVPN_P_CONTROL_SOFT_RESET_V1 3 // Soft reset request
+#define OPENVPN_P_CONTROL_V1 4 // SSL negotiation packet
+#define OPENVPN_P_ACK_V1 5 // Acknowledgment
+#define OPENVPN_P_DATA_V1 6 // Data packet
+#define OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 7 // Connection request from client
+#define OPENVPN_P_CONTROL_HARD_RESET_SERVER_V2 8 // Connection response from server
+
+// State of OpenVPN channel
+#define OPENVPN_CHANNEL_STATUS_INIT 0 // Initialization phase
+#define OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_KEY 1 // Waiting for the key information from the client
+#define OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_PUSH_REQUEST 2 // Waiting for PUSH_REQUEST from the client
+#define OPENVPN_CHANNEL_STATUS_TLS_VPN_CONNECTING 3 // VPN connecting process is running
+#define OPENVPN_CHANNEL_STATUS_ESTABLISHED 4 // VPN connection established
+#define OPENVPN_CHANNEL_STATUS_DISCONNECTED 5 // Disconnected
+
+// Quota
+#define OPENVPN_QUOTA_MAX_NUM_SESSIONS_PER_IP 1000 // Number of OpenVPN sessions per IP address
+#define OPENVPN_QUOTA_MAX_NUM_SESSIONS 30000 // Limit of the number of sessions
+
+// Mode
+#define OPENVPN_MODE_UNKNOWN 0 // Unknown
+#define OPENVPN_MODE_L2 1 // TAP (Ethernet)
+#define OPENVPN_MODE_L3 2 // TUN (IP)
+
+
+//// Type
+
+// Data of OpenVPN Key Method 2
+struct OPENVPN_KEY_METHOD_2
+{
+ UCHAR PreMasterSecret[48]; // Pre Master Secret (client only)
+ UCHAR Random1[32]; // Random 1
+ UCHAR Random2[32]; // Random 2
+ char OptionString[512]; // Option string
+ char Username[512]; // User name
+ char Password[512]; // Password
+ char PeerInfo[1536]; // PeerInfo
+};
+
+// OpenVPN sending control packet
+struct OPENVPN_CONTROL_PACKET
+{
+ UCHAR OpCode; // Op-code
+ UINT PacketId; // Packet ID
+ UINT DataSize; // Data size
+ UCHAR *Data; // Data body
+ UINT64 NextSendTime; // Scheduled next transmission time
+};
+
+// OpenVPN packet
+struct OPENVPN_PACKET
+{
+ UCHAR OpCode; // Op-code
+ UCHAR KeyId; // Key ID
+ UINT64 MySessionId; // Channel ID of the sender
+ UCHAR NumAck; // Number of ACK
+ UINT AckPacketId[OPENVPN_MAX_NUMACK]; // ACK packet ID list
+ UINT64 YourSessionId; // Destination Channel ID (If there are one or more ACK)
+ UINT PacketId; // Packet ID
+ UINT DataSize; // Data size
+ UCHAR *Data; // Data body
+};
+
+// OpenVPN channel
+struct OPENVPN_CHANNEL
+{
+ OPENVPN_SERVER *Server;
+ OPENVPN_SESSION *Session;
+ UINT Status; // State
+ LIST *AckReplyList; // Response ACK list
+ UINT MaxRecvPacketId; // The maximum value of the arrived packet ID
+ UINT NextSendPacketId; // The value of a packet ID to be transmitted next
+ LIST *SendControlPacketList; // Sending control packet list
+ SSL_PIPE *SslPipe; // SSL pipe
+ OPENVPN_KEY_METHOD_2 ClientKey; // Key sent from the client
+ OPENVPN_KEY_METHOD_2 ServerKey; // Key sent from the server
+ char Proto[64]; // Protocol
+ CIPHER *CipherEncrypt; // Encryption algorithm
+ CIPHER *CipherDecrypt; // Decryption algorithm
+ MD *MdSend; // Transmission MD algorithm
+ MD *MdRecv; // Reception MD algorithm
+ UCHAR MasterSecret[48]; // Master Secret
+ UCHAR ExpansionKey[256]; // Expansion Key
+ UCHAR NextIv[64]; // Next IV
+ UINT LastDataPacketId; // Previous Data Packet ID
+ UINT64 EstablishedTick; // Established time
+ UCHAR KeyId; // KEY ID
+ bool IsRekeyChannel; // Whether it is a channel for key update
+ bool IsInitiatorServer; // Whether the channel was started from the server side
+ bool RekeyInitiated; // Whether re-keying has already started
+ UINT64 NextRekey;
+};
+
+// OpenVPN session
+struct OPENVPN_SESSION
+{
+ UINT Id; // ID
+ OPENVPN_SERVER *Server;
+ UINT64 ServerSessionId; // The session ID of the server-side
+ UINT64 ClientSessionId; // Session ID of the client side
+ UINT Protocol; // Protocol
+ IP ClientIp; // Client IP address
+ UINT ClientPort; // Client port number
+ IP ServerIp; // Server IP address
+ UINT ServerPort; // Server port number
+ OPENVPN_CHANNEL *Channels[OPENVPN_NUM_CHANNELS]; // Channels (up to 8)
+ UINT LastCreatedChannelIndex; // Channel number that is created in the last
+ UINT Mode; // Mode (L3 or L2)
+ UINT LinkMtu; // link-mtu
+ UINT TunMtu; // tun-mtu
+ IPC_ASYNC *IpcAsync; // Asynchronous IPC connection
+ IPC *Ipc; // Connected IPC connection
+ char PushReplyStr[MAX_SIZE]; // PUSH_REPLY string
+ UINT64 NextPingSendTick; // Next time to send a Ping
+ bool Established; // VPN communication established flag
+ UINT64 CreatedTick; // Creation date and time
+ UINT64 LastCommTick; // Last communication date and time
+};
+
+// OpenVPN server
+struct OPENVPN_SERVER
+{
+ CEDAR *Cedar;
+ INTERRUPT_MANAGER *Interrupt; // Interrupt manager
+ LIST *SendPacketList; // Transmission packet list
+ LIST *SessionList; // Session list
+ UINT64 Now; // Current time
+ SOCK_EVENT *SockEvent; // Socket event
+ UCHAR TmpBuf[OPENVPN_TMP_BUFFER_SIZE]; // Temporary buffer
+ UINT DisconnectCount; // The number of session lost that have occurred so far
+ bool SupressSendPacket; // Packet transmission suppression flag
+ UINT NextSessionId; // Next session ID
+ DH_CTX *Dh; // DH key
+ UINT SessionEstablishedCount; // Number of session establishment
+};
+
+// OpenVPN server (UDP mode)
+struct OPENVPN_SERVER_UDP
+{
+ CEDAR *Cedar;
+ UDPLISTENER *UdpListener; // UDP listener
+ OPENVPN_SERVER *OpenVpnServer; // OpenVPN server
+ UINT64 VgsNextGetPublicPortsTick;
+};
+
+
+//// Function prototype
+OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar);
+void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u);
+void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list);
+void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list);
+
+OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event);
+void FreeOpenVpnServer(OPENVPN_SERVER *s);
+void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol);
+void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol);
+int OvsCompareSessionList(void *p1, void *p2);
+OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
+OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
+OPENVPN_SESSION *OvsFindOrCreateSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
+void OvsFreeSession(OPENVPN_SESSION *se);
+UINT OvsGetNumSessionByClientIp(OPENVPN_SERVER *s, IP *ip);
+
+OPENVPN_PACKET *OvsParsePacket(UCHAR *data, UINT size);
+void OvsFreePacket(OPENVPN_PACKET *p);
+BUF *OvsBuildPacket(OPENVPN_PACKET *p);
+OPENVPN_PACKET *OvsNewControlPacket(UCHAR opcode, UCHAR key_id, UINT64 my_channel_id, UINT num_ack,
+ UINT *ack_packet_ids, UINT64 your_channel_id, UINT packet_id,
+ UINT data_size, UCHAR *data);
+void OvsSendDataPacket(OPENVPN_CHANNEL *c, UCHAR key_id, UINT data_packet_id, void *data, UINT data_size);
+
+
+OPENVPN_CHANNEL *OvsNewChannel(OPENVPN_SESSION *se, UCHAR key_id);
+void OvsFreeChannel(OPENVPN_CHANNEL *c);
+UINT64 OvsNewServerSessionId(OPENVPN_SERVER *s);
+UINT OvsGetAckReplyList(OPENVPN_CHANNEL *c, UINT *ret);
+
+void OvsSendPacketNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_PACKET *p);
+void OvsSendPacketRawNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, void *data, UINT size);
+
+void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, OPENVPN_PACKET *p);
+void OvsSendControlPacket(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size);
+void OvsSendControlPacketWithAutoSplit(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size);
+void OvsFreeControlPacket(OPENVPN_CONTROL_PACKET *p);
+void OvsDeleteFromSendingControlPacketList(OPENVPN_CHANNEL *c, UINT num_acks, UINT *acks);
+UINT OvsParseKeyMethod2(OPENVPN_KEY_METHOD_2 *ret, UCHAR *data, UINT size, bool client_mode);
+bool OvsReadStringFromBuf(BUF *b, char *str, UINT str_size);
+void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, OPENVPN_KEY_METHOD_2 *data);
+BUF *OvsBuildKeyMethod2(OPENVPN_KEY_METHOD_2 *d);
+void OvsWriteStringToBuf(BUF *b, char *str, UINT max_size);
+
+LIST *OvsParseOptions(char *str);
+void OvsFreeOptions(LIST *o);
+LIST *OvsNewOptions();
+void OvsAddOption(LIST *o, char *key, char *value);
+bool OvsHasOption(LIST *o, char *key);
+UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size);
+void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c);
+bool OvsIsCompatibleL3IP(UINT ip);
+UINT OvsGetCompatibleL3IPNext(UINT ip);
+UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c);
+
+CIPHER *OvsGetCipher(char *name);
+MD *OvsGetMd(char *name);
+bool OvsCheckTcpRecvBufIfOpenVPNProtocol(UCHAR *buf, UINT size);
+
+bool OvsPerformTcpServer(CEDAR *cedar, SOCK *sock);
+
+void OvsSetReplyForVgsPollEnable(bool b);
+
+void OvsSetNoOpenVpnTcp(bool b);
+bool OvsGetNoOpenVpnTcp();
+
+void OvsSetNoOpenVpnUdp(bool b);
+
+
+
+#endif // INTEROP_OPENVPN_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Interop_SSTP.c b/src/Cedar/Interop_SSTP.c
new file mode 100644
index 00000000..18065fae
--- /dev/null
+++ b/src/Cedar/Interop_SSTP.c
@@ -0,0 +1,1222 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Interop_SSTP.c
+// SSTP (Microsoft Secure Socket Tunneling Protocol) protocol stack
+
+#include "CedarPch.h"
+
+static bool g_no_sstp = false;
+
+// Get the SSTP disabling flag
+bool GetNoSstp()
+{
+ return g_no_sstp;
+}
+
+// Set the SSTP disabling flag
+void SetNoSstp(bool b)
+{
+ g_no_sstp = b;
+}
+
+// Process the SSTP control packet reception
+void SstpProcessControlPacket(SSTP_SERVER *s, SSTP_PACKET *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL || p->IsControl == false)
+ {
+ return;
+ }
+
+ Debug("SSTP Control Packet Recv: Msg = %u, Num = %u\n", p->MessageType, LIST_NUM(p->AttibuteList));
+
+ switch (p->MessageType)
+ {
+ case SSTP_MSG_CALL_CONNECT_REQUEST: // Receive a connection request from a client
+ if (s->Aborting == false && s->Disconnecting == false)
+ {
+ if (s->Status == SSTP_SERVER_STATUS_REQUEST_PENGING)
+ {
+ SSTP_ATTRIBUTE *protocol_id = SstpFindAttribute(p, SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID);
+ if (protocol_id != NULL && protocol_id->DataSize == 2 &&
+ READ_USHORT(protocol_id->Data) == SSTP_ENCAPSULATED_PROTOCOL_PPP)
+ {
+ // Accept the connection request by the PPP protocol
+ SSTP_PACKET *ret;
+
+ // Generation of random numbers
+ Rand(s->SentNonce, SSTP_NONCE_SIZE);
+
+ ret = SstpNewControlPacketWithAnAttribute(SSTP_MSG_CALL_CONNECT_ACK,
+ SstpNewCryptoBindingRequestAttribute(CERT_HASH_PROTOCOL_SHA256, s->SentNonce));
+
+ SstpSendPacket(s, ret);
+
+ SstpFreePacket(ret);
+
+ s->Status = SSTP_SERVER_STATUS_CONNECTED_PENDING;
+
+ s->EstablishedCount++;
+ }
+ else
+ {
+ // Refuse to accept for a connection request other than the PPP protocol
+ SSTP_PACKET *ret = SstpNewControlPacketWithAnAttribute(SSTP_MSG_CALL_CONNECT_NAK,
+ SstpNewStatusInfoAttribute(SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID, ATTRIB_STATUS_VALUE_NOT_SUPPORTED));
+
+ SstpSendPacket(s, ret);
+
+ SstpFreePacket(ret);
+ }
+ }
+ }
+ break;
+
+ case SSTP_MSG_CALL_CONNECTED: // Connection from the client complete
+ if (s->Aborting == false && s->Disconnecting == false)
+ {
+ if (s->Status == SSTP_SERVER_STATUS_CONNECTED_PENDING)
+ {
+ s->Status = SSTP_SERVER_STATUS_ESTABLISHED;
+
+ Debug("SSTP Connected.\n");
+ }
+ }
+ break;
+
+ case SSTP_MSG_CALL_DISCONNECT: // Receive a disconnect request from the client
+ case SSTP_MSG_CALL_DISCONNECT_ACK:
+ s->DisconnectRecved = true;
+ SstpDisconnect(s);
+ break;
+
+ case SSTP_MSG_CALL_ABORT: // Receive a disconnect request from the client
+ s->AbortReceived = true;
+ SstpAbort(s);
+ break;
+ }
+}
+
+// Process the SSTP received data packet
+void SstpProcessDataPacket(SSTP_SERVER *s, SSTP_PACKET *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL || p->IsControl)
+ {
+ return;
+ }
+
+ //Debug("SSTP Data Packet Recv: Size = %u\n", p->DataSize);
+
+ if (s->PPPThread == NULL)
+ {
+ // Create a thread to initialize the new PPP module
+ s->PPPThread = NewPPPSession(s->Cedar, &s->ClientIp, s->ClientPort, &s->ServerIp, s->ServerPort,
+ s->TubeSend, s->TubeRecv, SSTP_IPC_POSTFIX, SSTP_IPC_CLIENT_NAME,
+ s->ClientHostName, s->ClientCipherName, 0);
+ }
+
+ // Pass the received data to the PPP module
+ TubeSendEx(s->TubeRecv, p->Data, p->DataSize, NULL, true);
+ s->FlushRecvTube = true;
+}
+
+// Process the SSTP received packet
+void SstpProcessPacket(SSTP_SERVER *s, SSTP_PACKET *p)
+{
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ s->LastRecvTick = s->Now;
+
+ if (p->IsControl)
+ {
+ // Control packet
+ SstpProcessControlPacket(s, p);
+ }
+ else
+ {
+ // Data packet
+ SstpProcessDataPacket(s, p);
+ }
+}
+
+// Send a SSTP packet
+void SstpSendPacket(SSTP_SERVER *s, SSTP_PACKET *p)
+{
+ BUF *b;
+ BLOCK *block;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (p->IsControl)
+ {
+ Debug("SSTP Control Packet Send: Msg = %u, Num = %u\n", p->MessageType, LIST_NUM(p->AttibuteList));
+ }
+ else
+ {
+ //Debug("SSTP Data Packet Send: Size=%u\n", p->DataSize);
+ }
+
+ b = SstpBuildPacket(p);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ block = NewBlock(b->Buf, b->Size, 0);
+ block->PriorityQoS = p->IsControl;
+ Free(b);
+
+ InsertQueue(s->SendQueue, block);
+}
+
+// Process the timer interrupt
+void SstpProcessInterrupt(SSTP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->Now = Tick64();
+
+ s->FlushRecvTube = false;
+
+ // Process the received packet
+ while (true)
+ {
+ BLOCK *b = GetNext(s->RecvQueue);
+ SSTP_PACKET *p;
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ p = SstpParsePacket(b->Buf, b->Size);
+ if (p == NULL)
+ {
+ // Disconnect the SSTP since a bad packet received
+ SstpAbort(s);
+ }
+ else
+ {
+ // Process the received packet
+ SstpProcessPacket(s, p);
+
+ SstpFreePacket(p);
+ }
+
+ FreeBlock(b);
+ }
+
+ if (s->FlushRecvTube)
+ {
+ TubeFlush(s->TubeRecv);
+ }
+
+ // Transmit a packet that the PPP module is trying to send via the SSTP
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(s->TubeSend);
+ SSTP_PACKET *p;
+ if (d == NULL)
+ {
+ break;
+ }
+
+ p = SstpNewDataPacket(d->Data, d->DataSize);
+
+ SstpSendPacket(s, p);
+
+ SstpFreePacket(p);
+
+ FreeTubeData(d);
+ }
+
+ if (s->Status == SSTP_SERVER_STATUS_ESTABLISHED)
+ {
+ if (s->Disconnecting == false && s->Aborting == false)
+ {
+ // Periodic transmission of Echo Request
+ if (s->NextSendEchoRequestTick == 0 || s->NextSendEchoRequestTick <= s->Now)
+ {
+ UINT64 next_interval = (UINT64)(SSTP_ECHO_SEND_INTERVAL_MIN + Rand32() % (SSTP_ECHO_SEND_INTERVAL_MAX - SSTP_ECHO_SEND_INTERVAL_MIN));
+ SSTP_PACKET *p;
+
+ s->NextSendEchoRequestTick = s->Now + next_interval;
+ AddInterrupt(s->Interrupt, s->NextSendEchoRequestTick);
+
+ p = SstpNewControlPacket(SSTP_MSG_ECHO_REQUEST);
+
+ SstpSendPacket(s, p);
+
+ SstpFreePacket(p);
+ }
+ }
+ }
+
+ if ((s->LastRecvTick + (UINT64)SSTP_TIMEOUT) <= s->Now)
+ {
+ // Disconnect the SSTP because a timeout occurred
+ SstpAbort(s);
+ s->Disconnected = true;
+ }
+
+ if (IsTubeConnected(s->TubeRecv) == false || IsTubeConnected(s->TubeSend) == false)
+ {
+ // Disconnect the SSTP since the PPP module is disconnected
+ SstpDisconnect(s);
+ }
+
+ if (s->Disconnecting)
+ {
+ // Normal disconnection process
+ if (s->DisconnectSent == false)
+ {
+ // Send a Disconnect
+ SSTP_PACKET *ret = SstpNewControlPacket(s->DisconnectRecved ? SSTP_MSG_CALL_DISCONNECT_ACK : SSTP_MSG_CALL_DISCONNECT);
+
+ SstpSendPacket(s, ret);
+
+ SstpFreePacket(ret);
+
+ s->DisconnectSent = true;
+ }
+ }
+
+ if (s->Aborting)
+ {
+ // Abnormal disconnection processing
+ if (s->AbortSent == false)
+ {
+ // Send the Abort
+ SSTP_PACKET *ret = SstpNewControlPacket(SSTP_MSG_CALL_ABORT);
+
+ SstpSendPacket(s, ret);
+
+ SstpFreePacket(ret);
+
+ s->AbortSent = true;
+ }
+ }
+
+ if (s->DisconnectSent && s->DisconnectRecved)
+ {
+ // Disconnect after exchanging the Disconnect each other
+ s->Disconnected = true;
+ }
+
+ if (s->AbortSent && s->AbortReceived)
+ {
+ // Disconnect after exchanging the Abort each other
+ s->Disconnected = true;
+ }
+}
+
+// Create a new SSTP control packet with an Attribute
+SSTP_PACKET *SstpNewControlPacketWithAnAttribute(USHORT message_type, SSTP_ATTRIBUTE *a)
+{
+ SSTP_PACKET *p = SstpNewControlPacket(message_type);
+
+ if (a != NULL)
+ {
+ Add(p->AttibuteList, a);
+ }
+
+ return p;
+}
+
+// Create a new SSTP control packet
+SSTP_PACKET *SstpNewControlPacket(USHORT message_type)
+{
+ SSTP_PACKET *p = ZeroMalloc(sizeof(SSTP_PACKET));
+
+ p->IsControl = true;
+ p->MessageType = message_type;
+ p->Version = SSTP_VERSION_1;
+ p->AttibuteList = NewListFast(NULL);
+
+ return p;
+}
+
+// Create a new SSTP data packet
+SSTP_PACKET *SstpNewDataPacket(UCHAR *data, UINT size)
+{
+ SSTP_PACKET *p = ZeroMalloc(sizeof(SSTP_PACKET));
+
+ p->IsControl = false;
+ p->Data = Clone(data, size);
+ p->DataSize = size;
+
+ return p;
+}
+
+// Get the Attibute with the specified ID from SSTP packet
+SSTP_ATTRIBUTE *SstpFindAttribute(SSTP_PACKET *p, UCHAR attribute_id)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(p->AttibuteList);i++)
+ {
+ SSTP_ATTRIBUTE *a = LIST_DATA(p->AttibuteList, i);
+
+ if (a->AttributeId == attribute_id)
+ {
+ return a;
+ }
+ }
+
+ return NULL;
+}
+
+// Disconnect the SSTP normally
+void SstpDisconnect(SSTP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->Disconnecting = true;
+}
+
+// Disconnect the SSTP abnormally
+void SstpAbort(SSTP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->Aborting = true;
+}
+
+// Create a Crypto Binding Request Attribute
+SSTP_ATTRIBUTE *SstpNewCryptoBindingRequestAttribute(UCHAR hash_protocol_bitmask, UCHAR *nonce_32bytes)
+{
+ SSTP_ATTRIBUTE *a;
+ UCHAR uc;
+ BUF *b = NewBuf();
+
+ uc = 0;
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &hash_protocol_bitmask, 1);
+
+ WriteBuf(b, nonce_32bytes, SSTP_NONCE_SIZE);
+
+ a = SstpNewAttribute(SSTP_ATTRIB_CRYPTO_BINDING_REQ, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return a;
+}
+
+// Create a Status Info Attribute
+SSTP_ATTRIBUTE *SstpNewStatusInfoAttribute(UCHAR attrib_id, UINT status)
+{
+ SSTP_ATTRIBUTE *a;
+ UCHAR uc;
+ BUF *b = NewBuf();
+
+ uc = 0;
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &uc, 1);
+ WriteBuf(b, &attrib_id, 1);
+
+ WriteBufInt(b, status);
+
+ a = SstpNewAttribute(SSTP_ATTRIB_STATUS_INFO, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return a;
+}
+
+// Create a New Attribute
+SSTP_ATTRIBUTE *SstpNewAttribute(UCHAR attribute_id, UCHAR *data, UINT data_size)
+{
+ SSTP_ATTRIBUTE *a = ZeroMalloc(sizeof(SSTP_ATTRIBUTE));
+
+ a->AttributeId = attribute_id;
+ a->Data = Clone(data, data_size);
+ a->DataSize = data_size;
+
+ return a;
+}
+
+// Build the Attribute
+BUF *SstpBuildAttribute(SSTP_ATTRIBUTE *a)
+{
+ UCHAR uc;
+ USHORT us;
+ BUF *b;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Reserved
+ uc = 0;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ // Attribute ID
+ uc = a->AttributeId;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ // LengthPacket
+ a->TotalLength = a->DataSize + 4;
+ us = (USHORT)a->TotalLength;
+ us = Endian16(us);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ // Data
+ WriteBuf(b, a->Data, a->DataSize);
+
+ return b;
+}
+
+// Build the Attribute list
+BUF *SstpBuildAttributeList(LIST *o, USHORT message_type)
+{
+ UINT i;
+ BUF *b;
+ USHORT us;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ us = Endian16(message_type);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ us = Endian16((USHORT)LIST_NUM(o));
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SSTP_ATTRIBUTE *a = LIST_DATA(o, i);
+ BUF *ab = SstpBuildAttribute(a);
+
+ if (ab != NULL)
+ {
+ WriteBufBuf(b, ab);
+
+ FreeBuf(ab);
+ }
+ }
+
+ return b;
+}
+
+// Building the SSTP packet
+BUF *SstpBuildPacket(SSTP_PACKET *p)
+{
+ BUF *b;
+ UCHAR uc;
+ USHORT us;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ if (p->IsControl)
+ {
+ BUF *ab;
+
+ if (p->Data != NULL)
+ {
+ Free(p->Data);
+ }
+
+ ab = SstpBuildAttributeList(p->AttibuteList, p->MessageType);
+ p->Data = ab->Buf;
+ p->DataSize = ab->Size;
+ Free(ab);
+ }
+
+ // Version
+ uc = SSTP_VERSION_1;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ // Flag
+ uc = p->IsControl ? 1 : 0;
+ WriteBuf(b, &uc, sizeof(UCHAR));
+
+ // Length Packet
+ us = Endian16(p->DataSize + 4);
+ WriteBuf(b, &us, sizeof(USHORT));
+
+ // Data
+ WriteBuf(b, p->Data, p->DataSize);
+
+ return b;
+}
+
+// Parse the SSTP packet
+SSTP_PACKET *SstpParsePacket(UCHAR *data, UINT size)
+{
+ SSTP_PACKET *p;
+ USHORT len;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ if (size < 4)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(SSTP_PACKET));
+
+ // Version
+ p->Version = *((UCHAR *)data);
+ data++;
+ size--;
+
+ if (p->Version != SSTP_VERSION_1)
+ {
+ // Invalid version
+ SstpFreePacket(p);
+ return NULL;
+ }
+
+ // Flag
+ if ((*((UCHAR *)data)) & 0x01)
+ {
+ p->IsControl = true;
+ }
+ data++;
+ size--;
+
+ // Length
+ len = READ_USHORT(data) & 0xFFF;
+ data += sizeof(USHORT);
+ size -= sizeof(USHORT);
+
+ if (len < 4)
+ {
+ // Invalid size
+ SstpFreePacket(p);
+ return NULL;
+ }
+
+ if (((UINT)(len - 4)) > size)
+ {
+ // Oversized
+ SstpFreePacket(p);
+ return NULL;
+ }
+
+ // Data
+ p->DataSize = len - 4;
+ p->Data = Clone(data, p->DataSize);
+
+ if (p->IsControl)
+ {
+ // Parse the Attribute list
+ p->AttibuteList = SstpParseAttributeList(p->Data, p->DataSize, p);
+
+ if (p->AttibuteList == NULL)
+ {
+ // Failure of parsing list
+ SstpFreePacket(p);
+ return NULL;
+ }
+ }
+
+ return p;
+}
+
+// Parse the Attribute list
+LIST *SstpParseAttributeList(UCHAR *data, UINT size, SSTP_PACKET *p)
+{
+ LIST *o;
+ USHORT us;
+ UINT num;
+ // Validate arguments
+ if (size == 0 || data == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ if (size < 4)
+ {
+ return NULL;
+ }
+
+ // Message Type
+ us = READ_USHORT(data);
+ p->MessageType = us;
+ data += sizeof(USHORT);
+ size -= sizeof(USHORT);
+
+ // Num Attributes
+ num = READ_USHORT(data);
+ data += sizeof(USHORT);
+ size -= sizeof(USHORT);
+
+ // Attibutes List
+ o = NewListFast(NULL);
+
+ while (LIST_NUM(o) < num)
+ {
+ SSTP_ATTRIBUTE *a = SstpParseAttribute(data, size);
+
+ if (a == NULL)
+ {
+ SstpFreeAttributeList(o);
+ return NULL;
+ }
+
+ if (a->TotalLength > size)
+ {
+ SstpFreeAttribute(a);
+ SstpFreeAttributeList(o);
+ return NULL;
+ }
+
+ Add(o, a);
+
+ data += a->TotalLength;
+ size -= a->TotalLength;
+ }
+
+ return o;
+}
+
+// Parse the Attribute
+SSTP_ATTRIBUTE *SstpParseAttribute(UCHAR *data, UINT size)
+{
+ SSTP_ATTRIBUTE *a;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(SSTP_ATTRIBUTE));
+
+ if (size < 4)
+ {
+ SstpFreeAttribute(a);
+ return NULL;
+ }
+
+ data++;
+ size--;
+
+ // Attribute ID
+ a->AttributeId = *((UCHAR *)data);
+ data++;
+ size--;
+
+ // Length
+ a->TotalLength = READ_USHORT(data) & 0xFFF;
+ data += sizeof(USHORT);
+ size -= sizeof(USHORT);
+
+ if (a->TotalLength < 4)
+ {
+ // Length fraud
+ SstpFreeAttribute(a);
+ return NULL;
+ }
+
+ a->DataSize = a->TotalLength - 4;
+ if (a->DataSize > size)
+ {
+ // Length excess
+ SstpFreeAttribute(a);
+ return NULL;
+ }
+
+ a->Data = Clone(data, a->DataSize);
+
+ return a;
+}
+
+// Release the Attibute
+void SstpFreeAttribute(SSTP_ATTRIBUTE *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Free(a->Data);
+
+ Free(a);
+}
+
+// Release the Attribute list
+void SstpFreeAttributeList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SSTP_ATTRIBUTE *a = LIST_DATA(o, i);
+
+ SstpFreeAttribute(a);
+ }
+
+ ReleaseList(o);
+}
+
+// Release the SSTP packet
+void SstpFreePacket(SSTP_PACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->AttibuteList != NULL)
+ {
+ SstpFreeAttributeList(p->AttibuteList);
+ }
+
+ if (p->Data != NULL)
+ {
+ Free(p->Data);
+ }
+
+ Free(p);
+}
+
+// Create a SSTP server
+SSTP_SERVER *NewSstpServer(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip,
+ UINT server_port, SOCK_EVENT *se,
+ char *client_host_name, char *crypt_name)
+{
+ SSTP_SERVER *s = ZeroMalloc(sizeof(SSTP_SERVER));
+
+ s->LastRecvTick = Tick64();
+
+ StrCpy(s->ClientHostName, sizeof(s->ClientHostName), client_host_name);
+ StrCpy(s->ClientCipherName, sizeof(s->ClientCipherName), crypt_name);
+
+ s->Cedar = cedar;
+ AddRef(s->Cedar->ref);
+
+ NewTubePair(&s->TubeSend, &s->TubeRecv, 0);
+ SetTubeSockEvent(s->TubeSend, se);
+
+ s->Now = Tick64();
+
+ Copy(&s->ClientIp, client_ip, sizeof(IP));
+ s->ClientPort = client_port;
+ Copy(&s->ServerIp, server_ip, sizeof(IP));
+ s->ServerPort = server_port;
+
+ s->SockEvent = se;
+
+ AddRef(s->SockEvent->ref);
+
+ s->RecvQueue = NewQueueFast();
+ s->SendQueue = NewQueueFast();
+
+ s->Interrupt = NewInterruptManager();
+
+ return s;
+}
+
+// Release the SSTP server
+void FreeSstpServer(SSTP_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ TubeDisconnect(s->TubeRecv);
+ TubeDisconnect(s->TubeSend);
+
+ WaitThread(s->PPPThread, INFINITE);
+ ReleaseThread(s->PPPThread);
+
+ while (true)
+ {
+ BLOCK *b = GetNext(s->RecvQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+
+ while (true)
+ {
+ BLOCK *b = GetNext(s->SendQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+
+ ReleaseQueue(s->RecvQueue);
+ ReleaseQueue(s->SendQueue);
+
+ ReleaseSockEvent(s->SockEvent);
+
+ FreeInterruptManager(s->Interrupt);
+
+ ReleaseCedar(s->Cedar);
+
+ ReleaseTube(s->TubeSend);
+ ReleaseTube(s->TubeRecv);
+
+ Free(s);
+}
+
+// Handle the communication of SSTP protocol
+bool ProcessSstpHttps(CEDAR *cedar, SOCK *s, SOCK_EVENT *se)
+{
+ UINT tmp_size = 65536;
+ UCHAR *tmp_buf;
+ FIFO *recv_fifo;
+ FIFO *send_fifo;
+ SSTP_SERVER *sstp;
+ bool ret = false;
+ // Validate arguments
+ if (cedar == NULL || s == NULL || se == NULL)
+ {
+ return false;
+ }
+
+ tmp_buf = Malloc(tmp_size);
+ recv_fifo = NewFifo();
+ send_fifo = NewFifo();
+
+ sstp = NewSstpServer(cedar, &s->RemoteIP, s->RemotePort, &s->LocalIP, s->LocalPort, se,
+ s->RemoteHostname, s->CipherName);
+
+ while (true)
+ {
+ UINT r;
+ bool is_disconnected = false;
+ bool state_changed = false;
+
+ // Receive data over SSL
+ while (true)
+ {
+ r = Recv(s, tmp_buf, tmp_size, true);
+ if (r == 0)
+ {
+ // SSL is disconnected
+ is_disconnected = true;
+ break;
+ }
+ else if (r == SOCK_LATER)
+ {
+ // Data is not received any more
+ break;
+ }
+ else
+ {
+ // Queue the received data
+ WriteFifo(recv_fifo, tmp_buf, r);
+ state_changed = true;
+ }
+ }
+
+ while (recv_fifo->size >= 4)
+ {
+ UCHAR *first4;
+ UINT read_size = 0;
+ bool ok = false;
+ // Read 4 bytes from the beginning of the receive queue
+ first4 = ((UCHAR *)recv_fifo->p) + recv_fifo->pos;
+ if (first4[0] == SSTP_VERSION_1)
+ {
+ USHORT len = READ_USHORT(first4 + 2) & 0xFFF;
+ if (len >= 4)
+ {
+ ok = true;
+
+ if (recv_fifo->size >= len)
+ {
+ UCHAR *data;
+ BLOCK *b;
+
+ read_size = len;
+ data = Malloc(read_size);
+
+ ReadFifo(recv_fifo, data, read_size);
+
+ b = NewBlock(data, read_size, 0);
+
+ InsertQueue(sstp->RecvQueue, b);
+ }
+ }
+ }
+
+ if (read_size == 0)
+ {
+ break;
+ }
+
+ if (ok == false)
+ {
+ // Disconnect the connection since a bad packet received
+ is_disconnected = true;
+ break;
+ }
+ }
+
+ // Process the timer interrupt
+ SstpProcessInterrupt(sstp);
+
+ if (sstp->Disconnected)
+ {
+ is_disconnected = true;
+ }
+
+ // Put the transmission data that SSTP module has generated into the transmission queue
+ while (true)
+ {
+ BLOCK *b = GetNext(sstp->SendQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ // When transmit a data packet, If there are packets of more than about
+ // 2.5 MB in the transmission queue of the TCP, discard without transmission
+ if (b->PriorityQoS || (send_fifo->size <= MAX_BUFFERING_PACKET_SIZE))
+ {
+ WriteFifo(send_fifo, b->Buf, b->Size);
+ }
+
+ FreeBlock(b);
+ }
+
+ // Data is transmitted over SSL
+ while (send_fifo->size != 0)
+ {
+ r = Send(s, ((UCHAR *)send_fifo->p) + send_fifo->pos, send_fifo->size, true);
+ if (r == 0)
+ {
+ // SSL is disconnected
+ is_disconnected = true;
+ break;
+ }
+ else if (r == SOCK_LATER)
+ {
+ // Can not send any more
+ break;
+ }
+ else
+ {
+ // Advance the transmission queue by the amount of the transmitted
+ ReadFifo(send_fifo, NULL, r);
+ state_changed = true;
+ }
+ }
+
+ if (is_disconnected)
+ {
+ // Disconnected
+ break;
+ }
+
+ // Wait for the next state change
+ if (state_changed == false)
+ {
+ UINT r = GetNextIntervalForInterrupt(sstp->Interrupt);
+ WaitSockEvent(se, MIN(r, SELECT_TIME));
+ }
+ }
+
+ if (sstp != NULL && sstp->EstablishedCount >= 1)
+ {
+ ret = true;
+ }
+
+ FreeSstpServer(sstp);
+
+ ReleaseFifo(recv_fifo);
+ ReleaseFifo(send_fifo);
+ Free(tmp_buf);
+
+ YieldCpu();
+ Disconnect(s);
+
+ return ret;
+}
+
+// Accept the SSTP connection
+bool AcceptSstp(CONNECTION *c)
+{
+ SOCK *s;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ bool ret;
+ bool ret2 = false;
+ SOCK_EVENT *se;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ s = c->FirstSock;
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ // Return a response
+ h = NewHttpHeader("HTTP/1.1", "200", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Length", "18446744073709551615"));
+ AddHttpValue(h, NewHttpValue("Server", "Microsoft-HTTPAPI/2.0"));
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+
+ ret = PostHttp(s, h, NULL, 0);
+
+ FreeHttpHeader(h);
+
+ if (ret)
+ {
+ SetTimeout(s, INFINITE);
+
+ se = NewSockEvent();
+
+ JoinSockToSockEvent(s, se);
+
+ Debug("ProcessSstpHttps Start.\n");
+ ret2 = ProcessSstpHttps(c->Cedar, s, se);
+ Debug("ProcessSstpHttps End.\n");
+
+ ReleaseSockEvent(se);
+ }
+
+ Disconnect(s);
+
+ return ret2;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Interop_SSTP.h b/src/Cedar/Interop_SSTP.h
new file mode 100644
index 00000000..dbf2d50c
--- /dev/null
+++ b/src/Cedar/Interop_SSTP.h
@@ -0,0 +1,238 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Interop_SSTP.h
+// Header of Interop_SSTP.c
+
+#ifndef INTEROP_SSTP_H
+#define INTEROP_SSTP_H
+
+//// Constants
+#define SSTP_URI "/sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/" // SSTP HTTPS URI
+#define SSTP_VERSION_1 0x10 // SSTP Version 1.0
+#define MAX_SSTP_PACKET_SIZE 4096 // Maximum packet size
+#define SSTP_IPC_CLIENT_NAME "Microsoft SSTP VPN Client"
+#define SSTP_IPC_POSTFIX "SSTP"
+#define SSTP_ECHO_SEND_INTERVAL_MIN 2500 // Transmission interval of Echo Request (minimum)
+#define SSTP_ECHO_SEND_INTERVAL_MAX 4792 // Transmission interval of Echo Request (maximum)
+#define SSTP_TIMEOUT 10000 // Communication time-out of SSTP
+
+// SSTP Message Type
+#define SSTP_MSG_CALL_CONNECT_REQUEST 0x0001
+#define SSTP_MSG_CALL_CONNECT_ACK 0x0002
+#define SSTP_MSG_CALL_CONNECT_NAK 0x0003
+#define SSTP_MSG_CALL_CONNECTED 0x0004
+#define SSTP_MSG_CALL_ABORT 0x0005
+#define SSTP_MSG_CALL_DISCONNECT 0x0006
+#define SSTP_MSG_CALL_DISCONNECT_ACK 0x0007
+#define SSTP_MSG_ECHO_REQUEST 0x0008
+#define SSTP_MSG_ECHO_RESPONSE 0x0009
+
+// SSTP Attribute ID
+#define SSTP_ATTRIB_NO_ERROR 0x00
+#define SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID 0x01
+#define SSTP_ATTRIB_STATUS_INFO 0x02
+#define SSTP_ATTRIB_CRYPTO_BINDING 0x03
+#define SSTP_ATTRIB_CRYPTO_BINDING_REQ 0x04
+
+// Protocol ID
+#define SSTP_ENCAPSULATED_PROTOCOL_PPP 0x0001
+
+// Hash Protocol Bitmask
+#define CERT_HASH_PROTOCOL_SHA1 0x01
+#define CERT_HASH_PROTOCOL_SHA256 0x02
+
+// Status
+#define ATTRIB_STATUS_NO_ERROR 0x00000000
+#define ATTRIB_STATUS_DUPLICATE_ATTRIBUTE 0x00000001
+#define ATTRIB_STATUS_UNRECOGNIZED_ATTRIBUTE 0x00000002
+#define ATTRIB_STATUS_INVALID_ATTRIB_VALUE_LENGTH 0x00000003
+#define ATTRIB_STATUS_VALUE_NOT_SUPPORTED 0x00000004
+#define ATTRIB_STATUS_UNACCEPTED_FRAME_RECEIVED 0x00000005
+#define ATTRIB_STATUS_RETRY_COUNT_EXCEEDED 0x00000006
+#define ATTRIB_STATUS_INVALID_FRAME_RECEIVED 0x00000007
+#define ATTRIB_STATUS_NEGOTIATION_TIMEOUT 0x00000008
+#define ATTRIB_STATUS_ATTRIB_NOT_SUPPORTED_IN_MSG 0x00000009
+#define ATTRIB_STATUS_REQUIRED_ATTRIBUTE_MISSING 0x0000000A
+#define ATTRIB_STATUS_STATUS_INFO_NOT_SUPPORTED_IN_MSG 0x0000000B
+
+// State of SSTP Server
+#define SSTP_SERVER_STATUS_REQUEST_PENGING 0 // Connection incomplete
+#define SSTP_SERVER_STATUS_CONNECTED_PENDING 1 // Connection completed. Authentication incomplete
+#define SSTP_SERVER_STATUS_ESTABLISHED 2 // Connection completed. Communication available
+
+// Length of Nonce
+#define SSTP_NONCE_SIZE 32 // 256 bits
+
+
+//// Type
+
+// SSTP Attibute
+struct SSTP_ATTRIBUTE
+{
+ UCHAR AttributeId;
+ UCHAR *Data;
+ UINT DataSize;
+ UINT TotalLength;
+};
+
+// SSTP Packet
+struct SSTP_PACKET
+{
+ UCHAR Version;
+ bool IsControl;
+ UCHAR *Data;
+ UINT DataSize;
+ USHORT MessageType;
+ LIST *AttibuteList;
+};
+
+// SSTP Server
+struct SSTP_SERVER
+{
+ CEDAR *Cedar;
+ UINT64 Now;
+ IP ClientIp, ServerIp;
+ UINT ClientPort, ServerPort;
+ char ClientHostName[MAX_HOST_NAME_LEN + 1];
+ char ClientCipherName[MAX_SIZE];
+ SOCK_EVENT *SockEvent;
+ QUEUE *RecvQueue; // Receive queue
+ QUEUE *SendQueue; // Transmission queue
+ INTERRUPT_MANAGER *Interrupt; // Interrupt manager
+ bool Aborting; // Forced disconnection flag
+ bool AbortSent; // Flag of whether to send the Abort
+ bool AbortReceived; // Flag of whether the Abort has been received
+ bool Disconnecting; // Disconnecting flag
+ bool DisconnectSent; // Flag of whether to send a Disconnect
+ bool DisconnectRecved; // Flag of whether a Disconnect has been received
+ bool Disconnected; // Flag as to disconnect
+ UINT Status; // State
+ UCHAR SentNonce[SSTP_NONCE_SIZE]; // Random data sent
+ TUBE *TubeRecv, *TubeSend; // Delivery tube of packets to PPP module
+ THREAD *PPPThread; // PPP module thread
+ UINT64 NextSendEchoRequestTick; // Time to send the next Echo Request
+ UINT64 LastRecvTick; // Tick when some data has received at the end
+ bool FlushRecvTube; // Flag whether to flush the reception tube
+ UINT EstablishedCount; // Number of session establishment
+};
+
+
+//// Function prototype
+bool AcceptSstp(CONNECTION *c);
+bool ProcessSstpHttps(CEDAR *cedar, SOCK *s, SOCK_EVENT *se);
+
+SSTP_SERVER *NewSstpServer(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip,
+ UINT server_port, SOCK_EVENT *se,
+ char *client_host_name, char *crypt_name);
+void FreeSstpServer(SSTP_SERVER *s);
+void SstpProcessInterrupt(SSTP_SERVER *s);
+SSTP_PACKET *SstpParsePacket(UCHAR *data, UINT size);
+LIST *SstpParseAttributeList(UCHAR *data, UINT size, SSTP_PACKET *p);
+SSTP_ATTRIBUTE *SstpParseAttribute(UCHAR *data, UINT size);
+void SstpFreeAttribute(SSTP_ATTRIBUTE *a);
+void SstpFreeAttributeList(LIST *o);
+void SstpFreePacket(SSTP_PACKET *p);
+BUF *SstpBuildPacket(SSTP_PACKET *p);
+BUF *SstpBuildAttributeList(LIST *o, USHORT message_type);
+BUF *SstpBuildAttribute(SSTP_ATTRIBUTE *a);
+void SstpAbort(SSTP_SERVER *s);
+void SstpDisconnect(SSTP_SERVER *s);
+void SstpProcessPacket(SSTP_SERVER *s, SSTP_PACKET *p);
+void SstpProcessControlPacket(SSTP_SERVER *s, SSTP_PACKET *p);
+void SstpProcessDataPacket(SSTP_SERVER *s, SSTP_PACKET *p);
+SSTP_ATTRIBUTE *SstpFindAttribute(SSTP_PACKET *p, UCHAR attribute_id);
+SSTP_ATTRIBUTE *SstpNewAttribute(UCHAR attribute_id, UCHAR *data, UINT data_size);
+SSTP_ATTRIBUTE *SstpNewStatusInfoAttribute(UCHAR attrib_id, UINT status);
+SSTP_ATTRIBUTE *SstpNewCryptoBindingRequestAttribute(UCHAR hash_protocol_bitmask, UCHAR *nonce_32bytes);
+SSTP_PACKET *SstpNewDataPacket(UCHAR *data, UINT size);
+SSTP_PACKET *SstpNewControlPacket(USHORT message_type);
+SSTP_PACKET *SstpNewControlPacketWithAnAttribute(USHORT message_type, SSTP_ATTRIBUTE *a);
+void SstpSendPacket(SSTP_SERVER *s, SSTP_PACKET *p);
+bool GetNoSstp();
+void SetNoSstp(bool b);
+
+#endif // INTEROP_SSTP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Layer3.c b/src/Cedar/Layer3.c
new file mode 100644
index 00000000..3bb8ecbe
--- /dev/null
+++ b/src/Cedar/Layer3.c
@@ -0,0 +1,2173 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Layer3.c
+// Layer-3 switch module
+
+#include "CedarPch.h"
+
+static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+// Process the IP queue
+void L3PollingIpQueue(L3IF *f)
+{
+ L3PACKET *p;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ // Process the packet came from another session
+ while (p = GetNext(f->IpPacketQueue))
+ {
+ PKT *pkt = p->Packet;
+
+ // Send as an IP packet
+ L3SendIp(f, p);
+ }
+}
+
+// Process IP packets
+void L3RecvIp(L3IF *f, PKT *p, bool self)
+{
+ IPV4_HEADER *ip;
+ UINT header_size;
+ UINT next_hop = 0;
+ L3IF *dst;
+ L3PACKET *packet;
+ UINT new_ttl = 0;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ ip = p->L3.IPv4Header;
+ header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
+
+ // Calculate the checksum
+ if (IpCheckChecksum(ip) == false)
+ {
+ // The checksum does not match
+ goto FREE_PACKET;
+ }
+
+ // Register in the ARP table
+ L3KnownArp(f, ip->SrcIP, p->MacAddressSrc);
+
+ if (p->BroadcastPacket)
+ {
+ // Not to route in the case of broadcast packet
+ goto FREE_PACKET;
+ }
+
+ // Calculate the TTL
+ if (ip->TimeToLive >= 1)
+ {
+ new_ttl = ip->TimeToLive - 1;
+ }
+ else
+ {
+ new_ttl = 0;
+ }
+
+ if (new_ttl == 0)
+ {
+ if (ip->DstIP != f->IpAddress)
+ {
+ UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
+ UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
+ UCHAR *buf;
+ IPV4_HEADER *ipv4;
+ ICMP_HEADER *icmpv4;
+ UCHAR *data;
+ PKT *pkt;
+ UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
+
+ // Generate an ICMP message that means that the TTL has expired
+ buf = ZeroMalloc(icmp_packet_total_size);
+ ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
+ icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
+ data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
+
+ IPV4_SET_VERSION(ipv4, 4);
+ IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
+ ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
+ ipv4->TimeToLive = 0xff;
+ ipv4->Protocol = IP_PROTO_ICMPV4;
+ ipv4->SrcIP = f->IpAddress;
+ ipv4->DstIP = ip->SrcIP;
+ ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
+
+ icmpv4->Type = 11;
+ Copy(data, ip, data_size);
+ icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
+
+ buf[12] = 0x08;
+ buf[13] = 0x00;
+
+ pkt = ParsePacket(buf, icmp_packet_total_size);
+ if (pkt == NULL)
+ {
+ Free(buf);
+ }
+ else
+ {
+ L3RecvIp(f, pkt, true);
+ }
+
+ // Discard the packet body whose the TTL has expired
+ goto FREE_PACKET;
+ }
+ }
+
+ // Rewrite the TTL
+ p->L3.IPv4Header->TimeToLive = (UCHAR)new_ttl;
+
+ // Get the interface corresponding to the destination IP address
+ dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
+
+ if (dst == NULL && self == false)
+ {
+ UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
+ UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
+ UCHAR *buf;
+ IPV4_HEADER *ipv4;
+ ICMP_HEADER *icmpv4;
+ UCHAR *data;
+ PKT *pkt;
+ UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
+
+ // Respond with ICMP that indicates that no route can be found
+ buf = ZeroMalloc(icmp_packet_total_size);
+ ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
+ icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
+ data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
+
+ IPV4_SET_VERSION(ipv4, 4);
+ IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
+ ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
+ ipv4->TimeToLive = 0xff;
+ ipv4->Protocol = IP_PROTO_ICMPV4;
+ ipv4->SrcIP = f->IpAddress;
+ ipv4->DstIP = ip->SrcIP;
+ ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
+
+ icmpv4->Type = 3;
+ Copy(data, ip, data_size);
+ icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
+
+ buf[12] = 0x08;
+ buf[13] = 0x00;
+
+ pkt = ParsePacket(buf, icmp_packet_total_size);
+ if (pkt == NULL)
+ {
+ Free(buf);
+ }
+ else
+ {
+ L3RecvIp(f, pkt, true);
+ }
+
+ // Discard the packet body whose route can not be found
+ goto FREE_PACKET;
+ }
+
+ if (dst != NULL && ip->DstIP == dst->IpAddress)
+ {
+ bool free_packet = true;
+ // IP packet addressed to myself has arrived
+ if (p->TypeL4 == L4_ICMPV4)
+ {
+ ICMP_HEADER *icmp = p->L4.ICMPHeader;
+ if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
+ {
+ // Reply by rewriting the source and destination of the IP packet
+ UINT src_ip, dst_ip;
+ src_ip = p->L3.IPv4Header->DstIP;
+ dst_ip = p->L3.IPv4Header->SrcIP;
+
+ p->L3.IPv4Header->DstIP = dst_ip;
+ p->L3.IPv4Header->SrcIP = src_ip;
+
+ ip->TimeToLive = 0xff;
+
+ // Recalculates the checksum
+ ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
+ icmp->Checksum = 0;
+ icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
+ icmp->Checksum = IpChecksum(icmp, p->PacketSize - sizeof(MAC_HEADER) - header_size);
+
+ dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
+
+ free_packet = false;
+ }
+ }
+
+ if (free_packet)
+ {
+ goto FREE_PACKET;
+ }
+ }
+
+ if (dst == NULL)
+ {
+ // The destination does not exist
+ goto FREE_PACKET;
+ }
+
+ // Recalculate the IP checksum
+ ip->Checksum = 0;
+ ip->Checksum = IpChecksum(ip, header_size);
+
+ // Treat as a Layer-3 packet
+ packet = ZeroMalloc(sizeof(L3PACKET));
+ packet->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
+ packet->NextHopIp = next_hop;
+ packet->Packet = p;
+
+ // Store to the destination session
+ L3StoreIpPacketToIf(f, dst, packet);
+
+ return;
+
+FREE_PACKET:
+ // Release the packet
+ Free(p->PacketData);
+ FreePacket(p);
+ return;
+}
+
+// Process the Layer 2 packet
+void L3RecvL2(L3IF *f, PKT *p)
+{
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Ignore any packets except a unicast packet which is destinated other
+ // or a packet which I sent
+ if (Cmp(p->MacAddressSrc, f->MacAddress, 6) == 0 ||
+ (p->BroadcastPacket == false && Cmp(p->MacAddressDest, f->MacAddress, 6) != 0))
+ {
+ // Release the packet
+ Free(p->PacketData);
+ FreePacket(p);
+ return;
+ }
+
+ if (p->TypeL3 == L3_ARPV4)
+ {
+ // Received an ARP packet
+ L3RecvArp(f, p);
+
+ // Release the packet
+ Free(p->PacketData);
+ FreePacket(p);
+ }
+ else if (p->TypeL3 == L3_IPV4)
+ {
+ // Received an IP packet
+ L3RecvIp(f, p, false);
+ }
+ else
+ {
+ // Release the packet
+ Free(p->PacketData);
+ FreePacket(p);
+ }
+}
+
+// Store the IP packet to a different interface
+void L3StoreIpPacketToIf(L3IF *src_if, L3IF *dst_if, L3PACKET *p)
+{
+ // Validate arguments
+ if (src_if == NULL || p == NULL || dst_if == NULL)
+ {
+ return;
+ }
+
+ // Add to the queue of store-destination session
+ InsertQueue(dst_if->IpPacketQueue, p);
+
+ // Hit the Cancel object of the store-destination session
+ AddCancelList(src_if->CancelList, dst_if->Session->Cancel1);
+}
+
+// Write the packet (Process because the packet was received)
+void L3PutPacket(L3IF *f, void *data, UINT size)
+{
+ PKT *p;
+ L3SW *s;
+ if (f == NULL)
+ {
+ return;
+ }
+
+ s = f->Switch;
+
+ if (data != NULL)
+ {
+ // Handle the next packet
+ if (f->CancelList == NULL)
+ {
+ f->CancelList = NewCancelList();
+ }
+
+ // Packet analysis
+ p = ParsePacket(data, size);
+
+ if (p == NULL)
+ {
+ // Packet analysis failure
+ Free(data);
+ }
+ else
+ {
+ // Packet analysis success
+ Lock(s->lock);
+ {
+ L3RecvL2(f, p);
+ }
+ Unlock(s->lock);
+ }
+ }
+ else
+ {
+ // Cancel for the cancellation list after all packet processing has been finished
+ if (f->CancelList != NULL)
+ {
+ CancelList(f->CancelList);
+ ReleaseCancelList(f->CancelList);
+ f->CancelList = NULL;
+ }
+ }
+}
+
+// Send the waiting IP packets whose destination MAC address has been resolved
+void L3SendWaitingIp(L3IF *f, UCHAR *mac, UINT ip, L3ARPENTRY *a)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (f == NULL || mac == NULL || a == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
+ {
+ L3PACKET *p = LIST_DATA(f->IpWaitList, i);
+
+ if (p->NextHopIp == ip)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, p);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ L3PACKET *p = LIST_DATA(o, i);
+
+ // Transmission
+ L3SendIpNow(f, a, p);
+
+ Delete(f->IpWaitList, p);
+ Free(p->Packet->PacketData);
+ FreePacket(p->Packet);
+ Free(p);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Register in the ARP table
+void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac)
+{
+ L3ARPENTRY *a, t;
+ // Validate arguments
+ if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.IpAddress = ip;
+
+ a = Search(f->ArpTable, &t);
+
+ if (a == NULL)
+ {
+ // Since this is not registered, register this
+ a = ZeroMalloc(sizeof(L3ARPENTRY));
+ a->IpAddress = ip;
+ Copy(a->MacAddress, mac, 6);
+ Insert(f->ArpTable, a);
+ }
+
+ // Extend the expiration date
+ a->Expire = Tick64() + ARP_ENTRY_EXPIRES;
+
+ // Send waiting IP packets
+ L3SendWaitingIp(f, mac, ip, a);
+}
+
+// Function to be called when the ARP resolved
+void L3KnownArp(L3IF *f, UINT ip, UCHAR *mac)
+{
+ L3ARPWAIT t, *w;
+ // Validate arguments
+ if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
+ {
+ return;
+ }
+
+ // Delete an ARP query entry to this IP address
+ Zero(&t, sizeof(t));
+ t.IpAddress = ip;
+ w = Search(f->IpWaitList, &t);
+ if (w != NULL)
+ {
+ Delete(f->IpWaitList, w);
+ Free(w);
+ }
+
+ // Register in the ARP table
+ L3InsertArpTable(f, ip, mac);
+}
+
+// Issue an ARP query
+void L3SendArp(L3IF *f, UINT ip)
+{
+ L3ARPWAIT t, *w;
+ // Validate arguments
+ if (f == NULL || ip == 0 || ip == 0xffffffff)
+ {
+ return;
+ }
+
+ // Examine whether it has not already registered
+ Zero(&t, sizeof(t));
+ t.IpAddress = ip;
+ w = Search(f->ArpWaitTable, &t);
+
+ if (w != NULL)
+ {
+ // Do not do anything because it is already registered in the waiting list
+ return;
+ }
+ else
+ {
+ // Register in the waiting list newly
+ w = ZeroMalloc(sizeof(L3ARPWAIT));
+ w->Expire = Tick64() + ARP_REQUEST_GIVEUP;
+ w->IpAddress = ip;
+ Insert(f->ArpWaitTable, w);
+ }
+}
+
+// Received an ARP request
+void L3RecvArpRequest(L3IF *f, PKT *p)
+{
+ ARPV4_HEADER *a;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ a = p->L3.ARPv4Header;
+
+ L3KnownArp(f, a->SrcIP, a->SrcAddress);
+
+ if (a->TargetIP == f->IpAddress)
+ {
+ // Respond only if the ARP packet addressed to myself
+ L3SendArpResponseNow(f, a->SrcAddress, a->SrcIP, f->IpAddress);
+ }
+}
+
+// Received an ARP response
+void L3RecvArpResponse(L3IF *f, PKT *p)
+{
+ ARPV4_HEADER *a;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ a = p->L3.ARPv4Header;
+
+ L3KnownArp(f, a->SrcIP, a->SrcAddress);
+}
+
+// Received an ARP packet
+void L3RecvArp(L3IF *f, PKT *p)
+{
+ ARPV4_HEADER *a;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ a = p->L3.ARPv4Header;
+
+ if (Endian16(a->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET ||
+ Endian16(a->ProtocolType) != MAC_PROTO_IPV4 ||
+ a->HardwareSize != 6 || a->ProtocolSize != 4)
+ {
+ return;
+ }
+ if (Cmp(a->SrcAddress, p->MacAddressSrc, 6) != 0)
+ {
+ return;
+ }
+
+ switch (Endian16(a->Operation))
+ {
+ case ARP_OPERATION_REQUEST:
+ // ARP request arrives
+ L3RecvArpRequest(f, p);
+ break;
+
+ case ARP_OPERATION_RESPONSE:
+ // ARP response arrives
+ L3RecvArpResponse(f, p);
+ break;
+ }
+}
+
+// Send an IP packet
+void L3SendIp(L3IF *f, L3PACKET *p)
+{
+ L3ARPENTRY *a = NULL;
+ bool broadcast = false;
+ IPV4_HEADER *ip;
+ bool for_me = false;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+ if (p->Packet->TypeL3 != L3_IPV4)
+ {
+ return;
+ }
+
+ ip = p->Packet->L3.IPv4Header;
+
+ // Determining whether it's a broadcast
+ if (p->NextHopIp == 0xffffffff ||
+ ((p->NextHopIp & f->SubnetMask) == (f->IpAddress & f->SubnetMask)) &&
+ ((p->NextHopIp & (~f->SubnetMask)) == (~f->SubnetMask)))
+ {
+ broadcast = true;
+ }
+
+ if (broadcast == false && ip->DstIP == f->IpAddress)
+ {
+ // me?
+ }
+ else if (broadcast == false)
+ {
+ // Examine whether the ARP entry contains this in the case of unicast
+ a = L3SearchArpTable(f, p->NextHopIp);
+
+ if (a == NULL)
+ {
+ // Since It is not in the ARP table,
+ // insert it into the IP waiting list without sending immediately
+ p->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
+
+ Insert(f->IpWaitList, p);
+
+ // Issue an ARP query
+ L3SendArp(f, p->NextHopIp);
+ return;
+ }
+ }
+
+ if (for_me == false)
+ {
+ // Send the IP packet
+ L3SendIpNow(f, a, p);
+ }
+
+ // Release the packet
+ Free(p->Packet->PacketData);
+ FreePacket(p->Packet);
+ Free(p);
+}
+
+// Send the IP packet immediately
+void L3SendIpNow(L3IF *f, L3ARPENTRY *a, L3PACKET *p)
+{
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ L3SendL2Now(f, a != NULL ? a->MacAddress : broadcast, f->MacAddress, Endian16(p->Packet->MacHeader->Protocol),
+ p->Packet->L3.PointerL3, p->Packet->PacketSize - sizeof(MAC_HEADER));
+}
+
+// Search in the ARP table
+L3ARPENTRY *L3SearchArpTable(L3IF *f, UINT ip)
+{
+ L3ARPENTRY *e, t;
+ // Validate arguments
+ if (f == NULL || ip == 0 || ip == 0xffffffff)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.IpAddress = ip;
+
+ e = Search(f->ArpTable, &t);
+
+ return e;
+}
+
+// Send an ARP request packet
+void L3SendArpRequestNow(L3IF *f, UINT dest_ip)
+{
+ ARPV4_HEADER arp;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ // Build an ARP header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_REQUEST);
+ Copy(arp.SrcAddress, f->MacAddress, 6);
+ arp.SrcIP = f->IpAddress;
+ Zero(&arp.TargetAddress, 6);
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
+}
+
+// Send an ARP response packet
+void L3SendArpResponseNow(L3IF *f, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
+{
+ ARPV4_HEADER arp;
+ // Validate arguments
+ if (f == NULL || dest_mac == NULL)
+ {
+ return;
+ }
+
+ // Build a header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
+ Copy(arp.SrcAddress, f->MacAddress, 6);
+ Copy(arp.TargetAddress, dest_mac, 6);
+ arp.SrcIP = src_ip;
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ L3SendL2Now(f, dest_mac, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
+}
+
+// Generate a MAC address of the interface
+void L3GenerateMacAddress(L3IF *f)
+{
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, f->Switch->Name, StrLen(f->Switch->Name));
+ WriteBuf(b, f->HubName, StrLen(f->HubName));
+ WriteBuf(b, &f->IpAddress, sizeof(f->IpAddress));
+
+ GenMacAddress(f->MacAddress);
+ Hash(hash, b->Buf, b->Size, true);
+ Copy(f->MacAddress + 2, hash, 4);
+ f->MacAddress[1] = 0xA3;
+ FreeBuf(b);
+}
+
+// Send an L2 packet immediately
+void L3SendL2Now(L3IF *f, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
+{
+ UCHAR *buf;
+ MAC_HEADER *mac_header;
+ PKT *p;
+ // Validate arguments
+ if (f == NULL || dest_mac == NULL || src_mac == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Buffer creation
+ buf = Malloc(MAC_HEADER_SIZE + size);
+
+ // MAC header
+ mac_header = (MAC_HEADER *)&buf[0];
+ Copy(mac_header->DestAddress, dest_mac, 6);
+ Copy(mac_header->SrcAddress, src_mac, 6);
+ mac_header->Protocol = Endian16(protocol);
+
+ // Copy data
+ Copy(&buf[sizeof(MAC_HEADER)], data, size);
+
+ // Size
+ size += sizeof(MAC_HEADER);
+
+ // Packet generation
+ p = ZeroMalloc(sizeof(PKT));
+ p->PacketData = buf;
+ p->PacketSize = size;
+
+ // Add to the queue
+ InsertQueue(f->SendQueue, p);
+}
+
+// Polling for the ARP resolution waiting list
+void L3PollingArpWaitTable(L3IF *f)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
+ {
+ L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
+
+ if (w->Expire <= Tick64())
+ {
+ // The ARP request entry is expired
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Insert(o, w);
+ }
+ else if ((w->LastSentTime + ARP_REQUEST_TIMEOUT) <= Tick64())
+ {
+ // Send a next ARP request packet
+ w->LastSentTime = Tick64();
+
+ L3SendArpRequestNow(f, w->IpAddress);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ L3ARPWAIT *w = LIST_DATA(o, i);
+
+ Delete(f->ArpWaitTable, w);
+ Free(w);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Clear old ARP table entries
+void L3DeleteOldArpTable(L3IF *f)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ if ((f->LastDeleteOldArpTable + ARP_ENTRY_POLLING_TIME) > Tick64())
+ {
+ return;
+ }
+ f->LastDeleteOldArpTable = Tick64();
+
+ for (i = 0;i < LIST_NUM(f->ArpTable);i++)
+ {
+ L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
+
+ if (a->Expire <= Tick64())
+ {
+ // Expired
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Insert(o, a);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ L3ARPENTRY *a = LIST_DATA(o, i);
+
+ Delete(f->ArpTable, a);
+ Free(a);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Clear the IP waiting list
+void L3DeleteOldIpWaitList(L3IF *f)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
+ {
+ L3PACKET *p = LIST_DATA(f->IpWaitList, i);
+
+ if (p->Expire <= Tick64())
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Insert(o, p);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ L3PACKET *p = LIST_DATA(o, i);
+
+ Delete(f->IpWaitList, p);
+
+ Free(p->Packet->PacketData);
+ FreePacket(p->Packet);
+ Free(p);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Beacon transmission
+void L3PollingBeacon(L3IF *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ if (f->LastBeaconSent == 0 ||
+ (f->LastBeaconSent + BEACON_SEND_INTERVAL) <= Tick64())
+ {
+ UINT dest_ip;
+ UCHAR *udp_buf;
+ UINT udp_buf_size;
+ ARPV4_HEADER arp;
+ IPV4_HEADER *ip;
+ UDP_HEADER *udp;
+ static char beacon_str[] =
+ "PacketiX VPN Virtual Layer-3 Switch Beacon";
+
+ // Send an UDP
+ dest_ip = (f->IpAddress & f->SubnetMask) | (~f->SubnetMask);
+ udp_buf_size = sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + sizeof(beacon_str);
+ udp_buf = ZeroMalloc(udp_buf_size);
+
+ ip = (IPV4_HEADER *)udp_buf;
+ udp = (UDP_HEADER *)(udp_buf + sizeof(IPV4_HEADER));
+ udp->DstPort = Endian16(7);
+ udp->SrcPort = Endian16(7);
+ udp->PacketLength = Endian16(sizeof(UDP_HEADER) + sizeof(beacon_str));
+
+ Copy(udp_buf + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), beacon_str, sizeof(beacon_str));
+
+ udp->Checksum = IpChecksum(udp, sizeof(UDP_HEADER) + sizeof(beacon_str));
+
+ ip->DstIP = dest_ip;
+ IPV4_SET_VERSION(ip, 4);
+ IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
+ ip->TypeOfService = DEFAULT_IP_TOS;
+ ip->TotalLength = Endian16((USHORT)(udp_buf_size));
+ ip->TimeToLive = DEFAULT_IP_TTL;
+ ip->Protocol = IP_PROTO_UDP;
+ ip->SrcIP = f->IpAddress;
+ ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
+
+ L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_IPV4, udp_buf, udp_buf_size);
+
+ Free(udp_buf);
+
+ // Build the ARP header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
+ Copy(arp.SrcAddress, f->MacAddress, 6);
+ arp.SrcIP = f->IpAddress;
+ arp.TargetAddress[0] =
+ arp.TargetAddress[1] =
+ arp.TargetAddress[2] =
+ arp.TargetAddress[3] =
+ arp.TargetAddress[4] =
+ arp.TargetAddress[5] = 0xff;
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
+
+ f->LastBeaconSent = Tick64();
+ }
+}
+
+// Polling process
+void L3Polling(L3IF *f)
+{
+ L3SW *s;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ s = f->Switch;
+
+ // Lock the entire switch in the middle of the polling process
+ Lock(s->lock);
+ {
+ // Beacon transmission
+ L3PollingBeacon(f);
+
+ // Process the IP queue
+ L3PollingIpQueue(f);
+
+ // Clear old ARP table entries
+ L3DeleteOldArpTable(f);
+
+ // Polling ARP resolution waiting list
+ L3PollingArpWaitTable(f);
+
+ // Clear the IP waiting list
+ L3DeleteOldIpWaitList(f);
+ }
+ Unlock(s->lock);
+}
+
+// Get the next packet
+UINT L3GetNextPacket(L3IF *f, void **data)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (f == NULL || data == NULL)
+ {
+ return 0;
+ }
+
+START:
+ // Examine the send queue
+ LockQueue(f->SendQueue);
+ {
+ PKT *p = GetNext(f->SendQueue);
+
+ if (p != NULL)
+ {
+ // There is a packet
+ ret = p->PacketSize;
+ *data = p->PacketData;
+ // Packet structure may be discarded
+ Free(p);
+ }
+ }
+ UnlockQueue(f->SendQueue);
+
+ if (ret == 0)
+ {
+ // Polling process
+ L3Polling(f);
+
+ // Examine whether a new packet is queued for results of the polling process
+ if (f->SendQueue->num_item != 0)
+ {
+ // Get the packet immediately if it's in the queue
+ goto START;
+ }
+ }
+
+ return ret;
+}
+
+// Determine the packet destined for the specified IP address should be sent to which interface
+L3IF *L3GetNextIf(L3SW *s, UINT ip, UINT *next_hop)
+{
+ UINT i;
+ L3IF *f;
+ UINT next_hop_ip = 0;
+ // Validate arguments
+ if (s == NULL || ip == 0 || ip == 0xffffffff)
+ {
+ return NULL;
+ }
+
+ f = NULL;
+
+ // Examine whether the specified IP address is contained
+ // in the networks which each interfaces belong to
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *ff = LIST_DATA(s->IfList, i);
+
+ if ((ff->IpAddress & ff->SubnetMask) == (ip & ff->SubnetMask))
+ {
+ f = ff;
+ next_hop_ip = ip;
+ break;
+ }
+ }
+
+ if (f == NULL)
+ {
+ // Find the routing table if it's not found
+ L3TABLE *t = L3GetBestRoute(s, ip);
+
+ if (t == NULL)
+ {
+ // Still not found
+ return NULL;
+ }
+ else
+ {
+ // Find the interface with the IP address of the router of
+ // NextHop of the found route
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *ff = LIST_DATA(s->IfList, i);
+
+ if ((ff->IpAddress & ff->SubnetMask) == (t->GatewayAddress & ff->SubnetMask))
+ {
+ f = ff;
+ next_hop_ip = t->GatewayAddress;
+ break;
+ }
+ }
+ }
+ }
+
+ if (f == NULL)
+ {
+ // Destination interface was unknown after all
+ return NULL;
+ }
+
+ if (next_hop != NULL)
+ {
+ *next_hop = next_hop_ip;
+ }
+
+ return f;
+}
+
+// Get the best routing table entry for the specified IP address
+L3TABLE *L3GetBestRoute(L3SW *s, UINT ip)
+{
+ UINT i;
+ UINT max_mask = 0;
+ UINT min_metric = INFINITE;
+ L3TABLE *ret = NULL;
+ // Validate arguments
+ if (s == NULL || ip == 0)
+ {
+ return NULL;
+ }
+
+ // 1st condition: Choose the one which have the largest subnet mask
+ // 2nd condition: Choose the one which have the smallest metric
+ for (i = 0;i < LIST_NUM(s->TableList);i++)
+ {
+ L3TABLE *t = LIST_DATA(s->TableList, i);
+
+ if ((t->NetworkAddress & t->SubnetMask) == (ip & t->SubnetMask))
+ {
+ if (t->SubnetMask >= max_mask)
+ {
+ max_mask = t->SubnetMask;
+ if (min_metric >= t->Metric)
+ {
+ min_metric = t->Metric;
+ ret = t;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Initialize the Layer-3 interface
+void L3InitInterface(L3IF *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ // MAC address generation
+ L3GenerateMacAddress(f);
+
+ // List generation
+ f->ArpTable = NewList(CmpL3ArpEntry);
+ f->ArpWaitTable = NewList(CmpL3ArpWaitTable);
+ f->IpPacketQueue = NewQueue();
+ f->IpWaitList = NewList(NULL);
+ f->SendQueue = NewQueue();
+}
+
+// Release the Layer-3 interface
+void L3FreeInterface(L3IF *f)
+{
+ UINT i;
+ L3PACKET *p;
+ PKT *pkt;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->ArpTable);i++)
+ {
+ L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
+ Free(a);
+ }
+ ReleaseList(f->ArpTable);
+ f->ArpTable = NULL;
+
+ for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
+ {
+ L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
+ Free(w);
+ }
+ ReleaseList(f->ArpWaitTable);
+ f->ArpWaitTable = NULL;
+
+ while (p = GetNext(f->IpPacketQueue))
+ {
+ Free(p->Packet->PacketData);
+ FreePacket(p->Packet);
+ Free(p);
+ }
+ ReleaseQueue(f->IpPacketQueue);
+ f->IpPacketQueue = NULL;
+
+ for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
+ {
+ L3PACKET *p = LIST_DATA(f->IpWaitList, i);
+ Free(p->Packet->PacketData);
+ FreePacket(p->Packet);
+ Free(p);
+ }
+ ReleaseList(f->IpWaitList);
+ f->IpWaitList = NULL;
+
+ while (pkt = GetNext(f->SendQueue))
+ {
+ Free(pkt->PacketData);
+ FreePacket(pkt);
+ }
+ ReleaseQueue(f->SendQueue);
+ f->SendQueue = NULL;
+}
+
+// Layer-3 interface thread
+void L3IfThread(THREAD *t, void *param)
+{
+ L3IF *f;
+ CONNECTION *c;
+ SESSION *s;
+ POLICY *policy;
+ char tmp[MAX_SIZE];
+ char name[MAX_SIZE];
+ char username[MAX_SIZE];
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ f = (L3IF *)param;
+
+ StrCpy(username, sizeof(username), L3_USERNAME);
+ if (f->Switch != NULL)
+ {
+ StrCat(username, sizeof(username), f->Switch->Name);
+ }
+
+ // Create a connection
+ c = NewServerConnection(f->Switch->Cedar, NULL, t);
+ c->Protocol = CONNECTION_HUB_LAYER3;
+
+ // Create a Session
+ policy = ClonePolicy(GetDefaultPolicy());
+ // Not to limit the number of broadcast by policy
+ policy->NoBroadcastLimiter = true;
+ s = NewServerSession(f->Switch->Cedar, c, f->Hub, username, policy);
+ c->Session = s;
+
+ ReleaseConnection(c);
+
+ // Determine the name of the session
+ GetMachineHostName(tmp, sizeof(tmp));
+ if (f->Switch->Cedar->Server->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ Format(name, sizeof(name), "SID-L3-%s-%u", f->Switch->Name, Inc(f->Hub->SessionCounter));
+ }
+ else
+ {
+ Format(name, sizeof(name), "SID-L3-%s-%s-%u", tmp, f->Switch->Name, Inc(f->Hub->SessionCounter));
+ }
+ ConvertSafeFileName(name, sizeof(name), name);
+ StrUpper(name);
+
+ Free(s->Name);
+ s->Name = CopyStr(name);
+
+ s->L3SwitchMode = true;
+ s->L3If = f;
+
+ if (s->Username != NULL)
+ {
+ Free(s->Username);
+ }
+ s->Username = CopyStr(username);
+
+ StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username);
+
+ f->Session = s;
+ AddRef(s->ref);
+
+ // Notify the initialization completion
+ NoticeThreadInit(t);
+
+ // Session main process
+ SessionMain(s);
+
+ // Release the session
+ ReleaseSession(s);
+}
+
+// Initialize all Layer-3 interfaces
+void L3InitAllInterfaces(L3SW *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+ THREAD *t;
+
+ L3InitInterface(f);
+
+ f->Hub = GetHub(s->Cedar, f->HubName);
+ t = NewThread(L3IfThread, f);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+ }
+}
+
+// Release all Layer-3 interfaces
+void L3FreeAllInterfaces(L3SW *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+
+ ReleaseHub(f->Hub);
+ f->Hub = NULL;
+ ReleaseSession(f->Session);
+ f->Session = NULL;
+
+ L3FreeInterface(f);
+ }
+}
+
+// Layer-3 test
+void L3Test(SERVER *s)
+{
+ L3SW *ss = L3AddSw(s->Cedar, "TEST");
+ L3AddIf(ss, "DEFAULT", 0x0101a8c0, 0x00ffffff);
+ L3AddIf(ss, "DEFAULT2", 0x0102a8c0, 0x00ffffff);
+ L3SwStart(ss);
+ ReleaseL3Sw(ss);
+}
+
+// Layer-3 switch thread
+void L3SwThread(THREAD *t, void *param)
+{
+ L3SW *s;
+ bool shutdown_now = false;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ s = (L3SW *)param;
+
+ s->Active = true;
+
+ NoticeThreadInit(t);
+
+ // Operation start
+ SLog(s->Cedar, "L3_SWITCH_START", s->Name);
+
+ while (s->Halt == false)
+ {
+ if (s->Online == false)
+ {
+ // Because the L3 switch is off-line now,
+ // attempt to make it on-line periodically
+ LockList(s->Cedar->HubList);
+ {
+ Lock(s->lock);
+ {
+ UINT i;
+ UINT n = 0;
+ bool all_exists = true;
+ if (LIST_NUM(s->IfList) == 0)
+ {
+ // Don't operate if there is no interface
+ all_exists = false;
+ }
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+ HUB *h = GetHub(s->Cedar, f->HubName);
+
+ if (h != NULL)
+ {
+ if (h->Offline || h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ all_exists = false;
+ }
+ else
+ {
+ n++;
+ }
+ ReleaseHub(h);
+ }
+ else
+ {
+ all_exists = false;
+ }
+ }
+
+ if (all_exists && n >= 1)
+ {
+ // Start the operation because all Virtual HUBs for
+ // interfaces are enabled
+ SLog(s->Cedar, "L3_SWITCH_ONLINE", s->Name);
+ L3InitAllInterfaces(s);
+ s->Online = true;
+ }
+ }
+ Unlock(s->lock);
+ }
+ UnlockList(s->Cedar->HubList);
+ }
+ else
+ {
+ // Examine periodically whether all sessions terminated
+ UINT i;
+ bool any_halted = false;
+ LIST *o = NULL;
+
+SHUTDOWN:
+
+ Lock(s->lock);
+ {
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+ if (f->Session->Halt || f->Hub->Offline != false)
+ {
+ any_halted = true;
+ break;
+ }
+ }
+
+ if (shutdown_now)
+ {
+ any_halted = true;
+ }
+
+ if (any_halted)
+ {
+ SLog(s->Cedar, "L3_SWITCH_OFFLINE", s->Name);
+ o = NewListFast(NULL);
+ // If there is any terminated session, terminate all sessions
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+ Insert(o, f->Session);
+ }
+
+ // Restore to the offline
+ s->Online = false;
+ }
+ }
+ Unlock(s->lock);
+
+ if (o != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SESSION *s = LIST_DATA(o, i);
+ StopSession(s);
+ }
+ L3FreeAllInterfaces(s);
+ ReleaseList(o);
+ o = NULL;
+ }
+ }
+
+ SleepThread(50);
+ }
+
+ if (s->Online != false)
+ {
+ shutdown_now = true;
+ goto SHUTDOWN;
+ }
+
+ // Stop the operation
+ SLog(s->Cedar, "L3_SWITCH_STOP", s->Name);
+}
+
+// Start a Layer-3 switch
+void L3SwStart(L3SW *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->lock);
+ {
+ if (s->Active == false)
+ {
+ // Start if there is registered interface
+ if (LIST_NUM(s->IfList) >= 1)
+ {
+ s->Halt = false;
+
+ // Create a thread
+ s->Thread = NewThread(L3SwThread, s);
+ WaitThreadInit(s->Thread);
+ }
+ }
+ }
+ Unlock(s->lock);
+}
+
+// Stop the Layer-3 switch
+void L3SwStop(L3SW *s)
+{
+ THREAD *t = NULL;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->lock);
+ {
+ if (s->Active == false)
+ {
+ Unlock(s->lock);
+ return;
+ }
+
+ s->Halt = true;
+
+ t = s->Thread;
+
+ s->Active = false;
+ }
+ Unlock(s->lock);
+
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+}
+
+// Add a Layer-3 switch
+L3SW *L3AddSw(CEDAR *c, char *name)
+{
+ L3SW *s = NULL;
+ // Validate arguments
+ if (c == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(c->L3SwList);
+ {
+ s = L3GetSw(c, name);
+
+ if (s == NULL)
+ {
+ s = NewL3Sw(c, name);
+
+ Insert(c->L3SwList, s);
+
+ AddRef(s->ref);
+ }
+ else
+ {
+ ReleaseL3Sw(s);
+ s = NULL;
+ }
+ }
+ UnlockList(c->L3SwList);
+
+ return s;
+}
+
+// Delete the Layer-3 switch
+bool L3DelSw(CEDAR *c, char *name)
+{
+ L3SW *s;
+ bool ret = false;
+ // Validate arguments
+ if (c == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ LockList(c->L3SwList);
+ {
+ s = L3GetSw(c, name);
+
+ if (s != NULL)
+ {
+ // Stop and delete
+ L3SwStop(s);
+ Delete(c->L3SwList, s);
+ ReleaseL3Sw(s);
+ ReleaseL3Sw(s);
+
+ ret = true;
+ }
+ }
+ UnlockList(c->L3SwList);
+
+ return ret;
+}
+
+
+// Delete the routing table
+bool L3DelTable(L3SW *s, L3TABLE *tbl)
+{
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || tbl == NULL)
+ {
+ return false;
+ }
+
+ Lock(s->lock);
+ {
+ if (s->Active == false)
+ {
+ L3TABLE *t = Search(s->TableList, tbl);
+
+ if (t != NULL)
+ {
+ Delete(s->TableList, t);
+ Free(t);
+
+ ret = true;
+ }
+ }
+ }
+ Unlock(s->lock);
+
+ return ret;
+}
+
+// Add to the routing table
+bool L3AddTable(L3SW *s, L3TABLE *tbl)
+{
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || tbl == NULL)
+ {
+ return false;
+ }
+
+ if (tbl->Metric == 0 || tbl->GatewayAddress == 0 || tbl->GatewayAddress == 0xffffffff)
+ {
+ return false;
+ }
+
+ Lock(s->lock);
+ {
+ if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_table"))
+ {
+ // Too many
+ }
+ else
+ {
+ // Create
+ if (s->Active == false)
+ {
+ if (Search(s->TableList, tbl) == NULL)
+ {
+ L3TABLE *t = ZeroMalloc(sizeof(L3TABLE));
+
+ Copy(t, tbl, sizeof(L3TABLE));
+
+ Insert(s->TableList, t);
+
+ ret = true;
+ }
+ }
+ }
+ }
+ Unlock(s->lock);
+
+ return ret;
+}
+
+// Get the L3 switch
+L3SW *L3GetSw(CEDAR *c, char *name)
+{
+ L3SW t, *s;
+ // Validate arguments
+ if (c == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ LockList(c->L3SwList);
+ {
+ s = Search(c->L3SwList, &t);
+ }
+ UnlockList(c->L3SwList);
+
+ if (s != NULL)
+ {
+ AddRef(s->ref);
+ }
+
+ return s;
+}
+
+// Get the interface that is connected to the specified Virtual HUB from the L3 switch
+L3IF *L3SearchIf(L3SW *s, char *hubname)
+{
+ L3IF t, *f;
+ // Validate arguments
+ if (s == NULL || hubname == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ f = Search(s->IfList, &t);
+
+ return f;
+}
+
+// Delete the interface
+bool L3DelIf(L3SW *s, char *hubname)
+{
+ L3IF *f;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || hubname == NULL)
+ {
+ return false;
+ }
+
+ Lock(s->lock);
+ {
+ if (s->Active == false)
+ {
+ f = L3SearchIf(s, hubname);
+
+ if (f != NULL)
+ {
+ // Remove
+ Delete(s->IfList, f);
+ Free(f);
+
+ ret = true;
+ }
+ }
+ }
+ Unlock(s->lock);
+
+ return ret;
+}
+
+// Add an interface
+bool L3AddIf(L3SW *s, char *hubname, UINT ip, UINT subnet)
+{
+ L3IF *f;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || hubname == NULL || IsSafeStr(hubname) == false ||
+ ip == 0 || ip == 0xffffffff)
+ {
+ return false;
+ }
+
+ Lock(s->lock);
+ {
+ if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_if"))
+ {
+ // Too many
+ }
+ else
+ {
+ if (s->Active == false)
+ {
+ // Examine whether the interface is already in the same Virtual HUB
+ if (L3SearchIf(s, hubname) == NULL)
+ {
+ // Add
+ f = ZeroMalloc(sizeof(L3IF));
+
+ f->Switch = s;
+ StrCpy(f->HubName, sizeof(f->HubName), hubname);
+ f->IpAddress = ip;
+ f->SubnetMask = subnet;
+
+ Insert(s->IfList, f);
+
+ ret = true;
+ }
+ }
+ }
+ }
+ Unlock(s->lock);
+
+ return ret;
+}
+
+// Clean-up the L3 switch
+void CleanupL3Sw(L3SW *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(s->IfList);i++)
+ {
+ L3IF *f = LIST_DATA(s->IfList, i);
+ Free(f);
+ }
+ ReleaseList(s->IfList);
+
+ for (i = 0;i < LIST_NUM(s->TableList);i++)
+ {
+ L3TABLE *t = LIST_DATA(s->TableList, i);
+ Free(t);
+ }
+ ReleaseList(s->TableList);
+
+ DeleteLock(s->lock);
+ Free(s);
+}
+
+// Release the L3 switch
+void ReleaseL3Sw(L3SW *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ CleanupL3Sw(s);
+ }
+}
+
+// Create a new L3 switch
+L3SW *NewL3Sw(CEDAR *c, char *name)
+{
+ L3SW *o;
+ // Validate arguments
+ if (c == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(L3SW));
+
+ StrCpy(o->Name, sizeof(o->Name), name);
+
+ o->lock = NewLock();
+ o->ref = NewRef();
+ o->Cedar = c;
+ o->Active = false;
+
+ o->IfList = NewList(CmpL3If);
+ o->TableList = NewList(CmpL3Table);
+
+ return o;
+}
+
+// Stop all L3 switches in the Cedar
+void L3FreeAllSw(CEDAR *c)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+
+ LockList(c->L3SwList);
+ {
+ for (i = 0;i < LIST_NUM(c->L3SwList);i++)
+ {
+ L3SW *s = LIST_DATA(c->L3SwList, i);
+ Insert(o, CopyStr(s->Name));
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *name = LIST_DATA(o, i);
+
+ L3DelSw(c, name);
+
+ Free(name);
+ }
+
+ ReleaseList(o);
+ }
+ UnlockList(c->L3SwList);
+}
+
+// Stop the L3 switch function of the Cedar
+void FreeCedarLayer3(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ ReleaseList(c->L3SwList);
+ c->L3SwList = NULL;
+}
+
+// Start the L3 switch function of the Cedar
+void InitCedarLayer3(CEDAR *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ c->L3SwList = NewList(CmpL3Sw);
+}
+
+// Interface comparison function
+int CmpL3If(void *p1, void *p2)
+{
+ L3IF *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(L3IF **)p1;
+ f2 = *(L3IF **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(f1->HubName, f2->HubName);
+}
+
+// Routing table entry comparison function
+int CmpL3Table(void *p1, void *p2)
+{
+ L3TABLE *t1, *t2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ t1 = *(L3TABLE **)p1;
+ t2 = *(L3TABLE **)p2;
+ if (t1 == NULL || t2 == NULL)
+ {
+ return 0;
+ }
+
+ if (t1->NetworkAddress > t2->NetworkAddress)
+ {
+ return 1;
+ }
+ else if (t1->NetworkAddress < t2->NetworkAddress)
+ {
+ return -1;
+ }
+ else if (t1->SubnetMask > t2->SubnetMask)
+ {
+ return 1;
+ }
+ else if (t1->SubnetMask < t2->SubnetMask)
+ {
+ return -1;
+ }
+ else if (t1->GatewayAddress > t2->GatewayAddress)
+ {
+ return 1;
+ }
+ else if (t1->GatewayAddress < t2->GatewayAddress)
+ {
+ return -1;
+ }
+ else if (t1->Metric > t2->Metric)
+ {
+ return 1;
+ }
+ else if (t1->Metric < t2->Metric)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// L3SW comparison function
+int CmpL3Sw(void *p1, void *p2)
+{
+ L3SW *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(L3SW **)p1;
+ s2 = *(L3SW **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(s1->Name, s2->Name);
+}
+
+// ARP waiting entry comparison function
+int CmpL3ArpWaitTable(void *p1, void *p2)
+{
+ L3ARPWAIT *w1, *w2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ w1 = *(L3ARPWAIT **)p1;
+ w2 = *(L3ARPWAIT **)p2;
+ if (w1 == NULL || w2 == NULL)
+ {
+ return 0;
+ }
+ if (w1->IpAddress > w2->IpAddress)
+ {
+ return 1;
+ }
+ else if (w1->IpAddress < w2->IpAddress)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// ARP entries comparison function
+int CmpL3ArpEntry(void *p1, void *p2)
+{
+ L3ARPENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(L3ARPENTRY **)p1;
+ e2 = *(L3ARPENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+ if (e1->IpAddress > e2->IpAddress)
+ {
+ return 1;
+ }
+ else if (e1->IpAddress < e2->IpAddress)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Layer3.h b/src/Cedar/Layer3.h
new file mode 100644
index 00000000..eca95c5e
--- /dev/null
+++ b/src/Cedar/Layer3.h
@@ -0,0 +1,229 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Layer3.h
+// Header of Layer3.c
+
+#ifndef LAYER3_H
+#define LAYER3_H
+
+// Constants
+#define L3_USERNAME "L3SW_"
+
+
+// L3 ARP table entry
+struct L3ARPENTRY
+{
+ UINT IpAddress; // IP address
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT64 Expire; // Expiration date
+};
+
+// L3 ARP resolution waiting list entry
+struct L3ARPWAIT
+{
+ UINT IpAddress; // IP address
+ UINT64 LastSentTime; // Time which the data has been sent last
+ UINT64 Expire; // Expiration date
+};
+
+// L3 IP packet table
+struct L3PACKET
+{
+ PKT *Packet; // Packet data body
+ UINT64 Expire; // Expiration date
+ UINT NextHopIp; // Local delivery destination IP address
+};
+
+// L3 routing table definition
+struct L3TABLE
+{
+ UINT NetworkAddress; // Network address
+ UINT SubnetMask; // Subnet mask
+ UINT GatewayAddress; // Gateway address
+ UINT Metric; // Metric
+};
+
+// L3 interface definition
+struct L3IF
+{
+ L3SW *Switch; // Layer-3 switch
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ UINT IpAddress; // IP address
+ UINT SubnetMask; // Subnet mask
+
+ HUB *Hub; // Virtual HUB
+ SESSION *Session; // Session
+ LIST *ArpTable; // ARP table
+ LIST *ArpWaitTable; // ARP waiting table
+ QUEUE *IpPacketQueue; // IP packet queue (for reception from other interfaces)
+ LIST *IpWaitList; // IP waiting list
+ QUEUE *SendQueue; // Transmission queue
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT64 LastDeleteOldArpTable; // Time that old ARP table entries are cleared
+ LIST *CancelList; // Cancellation list
+ UINT64 LastBeaconSent; // Time which the beacon has been sent last
+};
+
+// L3 switch definition
+struct L3SW
+{
+ char Name[MAX_HUBNAME_LEN + 1]; // Name
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ bool Active; // During operation flag
+ bool Online; // Online flag
+ volatile bool Halt; // Halting flag
+ LIST *IfList; // Interface list
+ LIST *TableList; // Routing table list
+ THREAD *Thread; // Thread
+};
+
+
+
+// Function prototype
+int CmpL3Sw(void *p1, void *p2);
+int CmpL3ArpEntry(void *p1, void *p2);
+int CmpL3ArpWaitTable(void *p1, void *p2);
+int CmpL3Table(void *p1, void *p2);
+int CmpL3If(void *p1, void *p2);
+void InitCedarLayer3(CEDAR *c);
+void FreeCedarLayer3(CEDAR *c);
+L3SW *NewL3Sw(CEDAR *c, char *name);
+void ReleaseL3Sw(L3SW *s);
+void CleanupL3Sw(L3SW *s);
+bool L3AddIf(L3SW *s, char *hubname, UINT ip, UINT subnet);
+bool L3DelIf(L3SW *s, char *hubname);
+bool L3AddTable(L3SW *s, L3TABLE *tbl);
+bool L3DelTable(L3SW *s, L3TABLE *tbl);
+L3IF *L3SearchIf(L3SW *s, char *hubname);
+L3SW *L3GetSw(CEDAR *c, char *name);
+L3SW *L3AddSw(CEDAR *c, char *name);
+bool L3DelSw(CEDAR *c, char *name);
+void L3FreeAllSw(CEDAR *c);
+void L3SwStart(L3SW *s);
+void L3SwStop(L3SW *s);
+void L3SwThread(THREAD *t, void *param);
+void L3Test(SERVER *s);
+void L3InitAllInterfaces(L3SW *s);
+void L3FreeAllInterfaces(L3SW *s);
+void L3IfThread(THREAD *t, void *param);
+void L3InitInterface(L3IF *f);
+void L3FreeInterface(L3IF *f);
+L3IF *L3GetNextIf(L3SW *s, UINT ip, UINT *next_hop);
+L3TABLE *L3GetBestRoute(L3SW *s, UINT ip);
+UINT L3GetNextPacket(L3IF *f, void **data);
+void L3Polling(L3IF *f);
+void L3PollingBeacon(L3IF *f);
+void L3DeleteOldArpTable(L3IF *f);
+void L3DeleteOldIpWaitList(L3IF *f);
+void L3PollingArpWaitTable(L3IF *f);
+void L3SendL2Now(L3IF *f, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size);
+void L3SendArpRequestNow(L3IF *f, UINT dest_ip);
+void L3SendArpResponseNow(L3IF *f, UCHAR *dest_mac, UINT dest_ip, UINT src_ip);
+void L3GenerateMacAddress(L3IF *f);
+L3ARPENTRY *L3SearchArpTable(L3IF *f, UINT ip);
+void L3SendIpNow(L3IF *f, L3ARPENTRY *a, L3PACKET *p);
+void L3SendIp(L3IF *f, L3PACKET *p);
+void L3RecvArp(L3IF *f, PKT *p);
+void L3RecvArpRequest(L3IF *f, PKT *p);
+void L3RecvArpResponse(L3IF *f, PKT *p);
+void L3KnownArp(L3IF *f, UINT ip, UCHAR *mac);
+void L3SendArp(L3IF *f, UINT ip);
+void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac);
+void L3SendWaitingIp(L3IF *f, UCHAR *mac, UINT ip, L3ARPENTRY *a);
+void L3PutPacket(L3IF *f, void *data, UINT size);
+void L3RecvL2(L3IF *f, PKT *p);
+void L3StoreIpPacketToIf(L3IF *src_if, L3IF *dst_if, L3PACKET *p);
+void L3RecvIp(L3IF *f, PKT *p, bool self);
+void L3PollingIpQueue(L3IF *f);
+
+
+#endif // LAYER3_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Link.c b/src/Cedar/Link.c
new file mode 100644
index 00000000..13f001d2
--- /dev/null
+++ b/src/Cedar/Link.c
@@ -0,0 +1,655 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Link.c
+// Inter-HUB Link
+
+#include "CedarPch.h"
+
+// Link server thread
+void LinkServerSessionThread(THREAD *t, void *param)
+{
+ LINK *k = (LINK *)param;
+ CONNECTION *c;
+ SESSION *s;
+ POLICY *policy;
+ wchar_t name[MAX_SIZE];
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Create a server connection
+ c = NewServerConnection(k->Cedar, NULL, t);
+ c->Protocol = CONNECTION_HUB_LINK_SERVER;
+
+ // Create a policy
+ policy = ZeroMalloc(sizeof(POLICY));
+ Copy(policy, k->Policy, sizeof(POLICY));
+
+ // Create a server session
+ s = NewServerSession(k->Cedar, c, k->Hub, LINK_USER_NAME, policy);
+ s->LinkModeServer = true;
+ s->Link = k;
+ c->Session = s;
+ ReleaseConnection(c);
+
+ // User name
+ s->Username = CopyStr(LINK_USER_NAME_PRINT);
+
+ k->ServerSession = s;
+ AddRef(k->ServerSession->ref);
+
+ // Notify the initialization completion
+ NoticeThreadInit(t);
+
+ UniStrCpy(name, sizeof(name), k->Option->AccountName);
+ HLog(s->Hub, "LH_LINK_START", name, s->Name);
+
+ // Main function of session
+ SessionMain(s);
+
+ HLog(s->Hub, "LH_LINK_STOP", name);
+
+ ReleaseSession(s);
+}
+
+// Initialize the packet adapter
+bool LinkPaInit(SESSION *s)
+{
+ LINK *k;
+ THREAD *t;
+ // Validate arguments
+ if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
+ {
+ return false;
+ }
+
+ // Create a transmission packet queue
+ k->SendPacketQueue = NewQueue();
+
+ // Creat a link server thread
+ t = NewThread(LinkServerSessionThread, (void *)k);
+ WaitThreadInit(t);
+
+ ReleaseThread(t);
+
+ return true;
+}
+
+// Get the cancel object
+CANCEL *LinkPaGetCancel(SESSION *s)
+{
+ LINK *k;
+ // Validate arguments
+ if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
+ {
+ return NULL;
+ }
+
+ return NULL;
+}
+
+// Get the next packet
+UINT LinkPaGetNextPacket(SESSION *s, void **data)
+{
+ LINK *k;
+ UINT ret = 0;
+ // Validate arguments
+ if (s == NULL || data == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
+ {
+ return INFINITE;
+ }
+
+ // Examine whether there are packets in the queue
+ LockQueue(k->SendPacketQueue);
+ {
+ BLOCK *block = GetNext(k->SendPacketQueue);
+
+ if (block != NULL)
+ {
+ // There was a packet
+ *data = block->Buf;
+ ret = block->Size;
+ // Discard the memory for the structure
+ Free(block);
+ }
+ }
+ UnlockQueue(k->SendPacketQueue);
+
+ return ret;
+}
+
+// Write the received packet
+bool LinkPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ LINK *k;
+ BLOCK *block;
+ SESSION *server_session;
+ CONNECTION *server_connection;
+ // Validate arguments
+ if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
+ {
+ return false;
+ }
+
+ server_session = k->ServerSession;
+ server_connection = server_session->Connection;
+
+ // Since the packet arrives from the HUB of the link destination,
+ // deliver it to the ReceivedBlocks of the server session
+ if (data != NULL)
+ {
+ block = NewBlock(data, size, 0);
+
+ LockQueue(server_connection->ReceivedBlocks);
+ {
+ InsertQueue(server_connection->ReceivedBlocks, block);
+ }
+ UnlockQueue(server_connection->ReceivedBlocks);
+ }
+ else
+ {
+ // Issue the Cancel, since finished store all packets when the data == NULL
+ Cancel(server_session->Cancel1);
+
+ if (k->Hub != NULL && k->Hub->Option != NULL && k->Hub->Option->YieldAfterStorePacket)
+ {
+ YieldCpu();
+ }
+ }
+
+ return true;
+}
+
+// Release the packet adapter
+void LinkPaFree(SESSION *s)
+{
+ LINK *k;
+ // Validate arguments
+ if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
+ {
+ return;
+ }
+
+ // Stop the server session
+ StopSession(k->ServerSession);
+ ReleaseSession(k->ServerSession);
+
+ // Release the transmission packet queue
+ LockQueue(k->SendPacketQueue);
+ {
+ BLOCK *block;
+ while (block = GetNext(k->SendPacketQueue))
+ {
+ FreeBlock(block);
+ }
+ }
+ UnlockQueue(k->SendPacketQueue);
+
+ ReleaseQueue(k->SendPacketQueue);
+}
+
+// Packet adapter
+PACKET_ADAPTER *LinkGetPacketAdapter()
+{
+ return NewPacketAdapter(LinkPaInit, LinkPaGetCancel, LinkPaGetNextPacket,
+ LinkPaPutPacket, LinkPaFree);
+}
+
+// Release all links
+void ReleaseAllLink(HUB *h)
+{
+ LINK **kk;
+ UINT num, i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->LinkList);
+ {
+ num = LIST_NUM(h->LinkList);
+ kk = ToArray(h->LinkList);
+ DeleteAll(h->LinkList);
+ }
+ UnlockList(h->LinkList);
+
+ for (i = 0;i < num;i++)
+ {
+ LINK *k = kk[i];
+
+ ReleaseLink(k);
+ }
+
+ Free(kk);
+}
+
+// Release the link
+void ReleaseLink(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ if (Release(k->ref) == 0)
+ {
+ CleanupLink(k);
+ }
+}
+
+// Clean-up the link
+void CleanupLink(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(k->lock);
+ if (k->ClientSession)
+ {
+ ReleaseSession(k->ClientSession);
+ }
+ Free(k->Option);
+ CiFreeClientAuth(k->Auth);
+ Free(k->Policy);
+
+ if (k->ServerCert != NULL)
+ {
+ FreeX(k->ServerCert);
+ }
+
+ Free(k);
+}
+
+// Make the link on-line
+void SetLinkOnline(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ if (k->Offline == false)
+ {
+ return;
+ }
+
+ k->Offline = false;
+ StartLink(k);
+}
+
+// Make the link off-line
+void SetLinkOffline(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ if (k->Offline)
+ {
+ return;
+ }
+
+ StopLink(k);
+ k->Offline = true;
+}
+
+// Delete the link
+void DelLink(HUB *hub, LINK *k)
+{
+ // Validate arguments
+ if (hub == NULL || k == NULL)
+ {
+ return;
+ }
+
+ LockList(hub->LinkList);
+ {
+ if (Delete(hub->LinkList, k))
+ {
+ ReleaseLink(k);
+ }
+ }
+ UnlockList(hub->LinkList);
+}
+
+// Start all links
+void StartAllLink(HUB *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->LinkList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *k = (LINK *)LIST_DATA(h->LinkList, i);
+
+ if (k->Offline == false)
+ {
+ StartLink(k);
+ }
+ }
+ }
+ UnlockList(h->LinkList);
+}
+
+// Stop all links
+void StopAllLink(HUB *h)
+{
+ LINK **link_list;
+ UINT num_link;
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->LinkList);
+ {
+ link_list = ToArray(h->LinkList);
+ num_link = LIST_NUM(h->LinkList);
+ for (i = 0;i < num_link;i++)
+ {
+ AddRef(link_list[i]->ref);
+ }
+ }
+ UnlockList(h->LinkList);
+
+ for (i = 0;i < num_link;i++)
+ {
+ StopLink(link_list[i]);
+ ReleaseLink(link_list[i]);
+ }
+
+ Free(link_list);
+}
+
+// Start the link
+void StartLink(LINK *k)
+{
+ PACKET_ADAPTER *pa;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ LockLink(k);
+ {
+ if (k->Started || k->Halting)
+ {
+ UnlockLink(k);
+ return;
+ }
+ k->Started = true;
+ }
+ UnlockLink(k);
+
+ // Connect the client session
+ pa = LinkGetPacketAdapter();
+ pa->Param = (void *)k;
+ LockLink(k);
+ {
+ k->ClientSession = NewClientSession(k->Cedar, k->Option, k->Auth, pa);
+ }
+ UnlockLink(k);
+}
+
+// Stop the link
+void StopLink(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ LockLink(k);
+ {
+ if (k->Started == false)
+ {
+ UnlockLink(k);
+ return;
+ }
+ k->Started = false;
+ k->Halting = true;
+ }
+ UnlockLink(k);
+
+ if (k->ClientSession != NULL)
+ {
+ // Disconnect the client session
+ StopSession(k->ClientSession);
+
+ LockLink(k);
+ {
+ ReleaseSession(k->ClientSession);
+ k->ClientSession = NULL;
+ }
+ UnlockLink(k);
+ }
+
+ LockLink(k);
+ {
+ k->Halting = false;
+ }
+ UnlockLink(k);
+}
+
+// Lock the link
+void LockLink(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Lock(k->lock);
+}
+
+// Unlock the link
+void UnlockLink(LINK *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Unlock(k->lock);
+}
+
+// Normalize the policy for the link
+void NormalizeLinkPolicy(POLICY *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->Access = true;
+ p->NoBridge = p->NoRouting = p->PrivacyFilter =
+ p->MonitorPort = false;
+ p->MaxConnection = 32;
+ p->TimeOut = 20;
+ p->FixPassword = false;
+}
+
+// Create a Link
+LINK *NewLink(CEDAR *cedar, HUB *hub, CLIENT_OPTION *option, CLIENT_AUTH *auth, POLICY *policy)
+{
+ CLIENT_OPTION *o;
+ LINK *k;
+ CLIENT_AUTH *a;
+ // Validate arguments
+ if (cedar == NULL || hub == NULL || option == NULL || auth == NULL || policy == NULL)
+ {
+ return NULL;
+ }
+ if (hub->Halt)
+ {
+ return NULL;
+ }
+
+ if (LIST_NUM(hub->LinkList) >= MAX_HUB_LINKS)
+ {
+ return NULL;
+ }
+
+ if (UniIsEmptyStr(option->AccountName))
+ {
+ return NULL;
+ }
+
+ // Limitation of authentication method
+ if (auth->AuthType != CLIENT_AUTHTYPE_ANONYMOUS && auth->AuthType != CLIENT_AUTHTYPE_PASSWORD &&
+ auth->AuthType != CLIENT_AUTHTYPE_PLAIN_PASSWORD && auth->AuthType != CLIENT_AUTHTYPE_CERT)
+ {
+ // Authentication method other than anonymous authentication, password authentication, plain password, certificate authentication cannot be used
+ return NULL;
+ }
+
+ // Copy of the client options (for modification)
+ o = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(o, option, sizeof(CLIENT_OPTION));
+ StrCpy(o->DeviceName, sizeof(o->DeviceName), LINK_DEVICE_NAME);
+
+ o->RequireBridgeRoutingMode = true; // Request the bridge mode
+ o->RequireMonitorMode = false; // Not to require the monitor mode
+
+ o->NumRetry = INFINITE; // Retry the connection infinitely
+ o->RetryInterval = 10; // Retry interval is 10 seconds
+ o->NoRoutingTracking = true; // Stop the routing tracking
+
+ // Copy the authentication data
+ a = CopyClientAuth(auth);
+ a->SecureSignProc = NULL;
+ a->CheckCertProc = NULL;
+
+ // Link object
+ k = ZeroMalloc(sizeof(LINK));
+ k->lock = NewLock();
+ k->ref = NewRef();
+
+ k->Cedar = cedar;
+ k->Option = o;
+ k->Auth = a;
+ k->Hub = hub;
+
+ // Copy the policy
+ k->Policy = ZeroMalloc(sizeof(POLICY));
+ Copy(k->Policy, policy, sizeof(POLICY));
+
+ // Normalize the policy
+ NormalizeLinkPolicy(k->Policy);
+
+ // Register in the link list of the HUB
+ LockList(hub->LinkList);
+ {
+ Add(hub->LinkList, k);
+ AddRef(k->ref);
+ }
+ UnlockList(hub->LinkList);
+
+ return k;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Link.h b/src/Cedar/Link.h
new file mode 100644
index 00000000..c2e4bf95
--- /dev/null
+++ b/src/Cedar/Link.h
@@ -0,0 +1,139 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Link.h
+// Header of Link.c
+
+#ifndef LINK_H
+#define LINK_H
+
+struct LINK
+{
+ bool Started; // Running flag
+ volatile bool Halting; // Halting flag
+ bool Offline; // Offline
+ REF *ref; // Reference counter
+ LOCK *lock; // Lock
+ CEDAR *Cedar; // Cedar
+ HUB *Hub; // HUB
+ SESSION *ClientSession; // Client session
+ SESSION *ServerSession; // Server session
+ CLIENT_OPTION *Option; // Client Option
+ CLIENT_AUTH *Auth; // Authentication data
+ POLICY *Policy; // Policy
+ QUEUE *SendPacketQueue; // Transmission packet queue
+ UINT LastError; // Last error
+ bool CheckServerCert; // To check the server certificate
+ X *ServerCert; // Server certificate
+};
+
+
+PACKET_ADAPTER *LinkGetPacketAdapter();
+bool LinkPaInit(SESSION *s);
+CANCEL *LinkPaGetCancel(SESSION *s);
+UINT LinkPaGetNextPacket(SESSION *s, void **data);
+bool LinkPaPutPacket(SESSION *s, void *data, UINT size);
+void LinkPaFree(SESSION *s);
+
+void LinkServerSessionThread(THREAD *t, void *param);
+LINK *NewLink(CEDAR *cedar, HUB *hub, CLIENT_OPTION *option, CLIENT_AUTH *auth, POLICY *policy);
+void StartLink(LINK *k);
+void StopLink(LINK *k);
+void DelLink(HUB *hub, LINK *k);
+void LockLink(LINK *k);
+void UnlockLink(LINK *k);
+void StopAllLink(HUB *h);
+void StartAllLink(HUB *h);
+void SetLinkOnline(LINK *k);
+void SetLinkOffline(LINK *k);
+void ReleaseLink(LINK *k);
+void CleanupLink(LINK *k);
+void ReleaseAllLink(HUB *h);
+void NormalizeLinkPolicy(POLICY *p);
+
+#endif // LINK_H
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Listener.c b/src/Cedar/Listener.c
new file mode 100644
index 00000000..0babfac2
--- /dev/null
+++ b/src/Cedar/Listener.c
@@ -0,0 +1,1079 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Listener.c
+// Listener module
+
+#include "CedarPch.h"
+
+static bool disable_dos = false;
+static UINT max_connections_per_ip = DEFAULT_MAX_CONNECTIONS_PER_IP;
+static UINT max_unestablished_connections = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
+static bool listener_proc_recv_rpc = false;
+
+// Set the flag of whether to response to the RPC of RUDP
+void ListenerSetProcRecvRpcEnable(bool b)
+{
+ listener_proc_recv_rpc = b;
+}
+
+// Get the number of allowed outstanding connections
+UINT GetMaxUnestablishedConnections()
+{
+ return max_unestablished_connections;
+}
+
+// Set the number of allowed outstanding connections
+void SetMaxUnestablishedConnections(UINT num)
+{
+ if (num == 0)
+ {
+ num = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
+ }
+
+ max_unestablished_connections = MAX(num, max_connections_per_ip);
+}
+
+// Get the maximum number of connections per IP address
+UINT GetMaxConnectionsPerIp()
+{
+ return max_connections_per_ip;
+}
+
+// Set the maximum number of connections per IP address
+void SetMaxConnectionsPerIp(UINT num)
+{
+ if (num == 0)
+ {
+ num = DEFAULT_MAX_CONNECTIONS_PER_IP;
+ }
+ max_connections_per_ip = MAX(num, MIN_MAX_CONNECTIONS_PER_IP);
+}
+
+// Enable the DoS defense
+void EnableDosProtect()
+{
+ disable_dos = false;
+}
+
+// Disable the DoS defense
+void DisableDosProtect()
+{
+ disable_dos = true;
+}
+
+// An UDP packet has been received
+void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)
+{
+ SESSION *session;
+ UINT *key32;
+ UCHAR *buf;
+ CONNECTION *c;
+ // Validate arguments
+ if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)
+ {
+ return;
+ }
+
+ if (size < 16)
+ {
+ // Ignore since the packet size is not enough
+ return;
+ }
+ buf = (UCHAR *)data;
+ key32 = (UINT *)(buf + 4);
+
+
+ // Get the session from the Key32 value
+ session = GetSessionFromUDPEntry(cedar, Endian32(*key32));
+ if (session == NULL)
+ {
+ Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);
+ return;
+ }
+
+ c = session->Connection;
+
+ // Write the data
+ PutUDPPacketData(c, buf, size);
+
+ // Rewrite the UDP socket associated with the connection
+ Lock(c->lock);
+ {
+ if (c->Protocol == CONNECTION_UDP)
+ {
+ if (c->Udp->s != s)
+ {
+ if (c->Udp->s != NULL)
+ {
+ ReleaseSock(c->Udp->s);
+ }
+ AddRef(s->ref);
+ c->Udp->s = s;
+ }
+ Copy(&c->Udp->ip, ip, sizeof(UINT));
+ c->Udp->port = port;
+ }
+ }
+ Unlock(c->lock);
+
+ // Invoke the Cancel
+ Cancel(session->Cancel1);
+
+ // Release the session
+ ReleaseSession(session);
+}
+
+// Thread that processes the accepted TCP connection
+void TCPAcceptedThread(THREAD *t, void *param)
+{
+ TCP_ACCEPTED_PARAM *data;
+ LISTENER *r;
+ SOCK *s;
+ CONNECTION *c;
+ bool flag1;
+ char tmp[128];
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Initialize
+ data = (TCP_ACCEPTED_PARAM *)param;
+ r = data->r;
+ s = data->s;
+ AddRef(r->ref);
+ AddRef(s->ref);
+
+ // Create a connection
+ c = NewServerConnection(r->Cedar, s, t);
+
+ // Register to Cedar as a transient connection
+ AddConnection(c->Cedar, c);
+
+ NoticeThreadInit(t);
+
+ AcceptInit(s);
+ StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+ if (IS_SPECIAL_PORT(s->RemotePort) == false)
+ {
+ SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);
+ }
+
+ // Reception
+ ConnectionAccept(c);
+ flag1 = c->flag1;
+
+ // Release
+ SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
+ ReleaseConnection(c);
+
+ // Release
+ if (flag1 == false)
+ {
+ Debug("%s %u flag1 == false\n", __FILE__, __LINE__);
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+
+ if (IS_SPECIAL_PORT(s->RemotePort) == false)
+ {
+ SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);
+ }
+ Disconnect(s);
+ }
+ ReleaseSock(s);
+ ReleaseListener(r);
+}
+
+// Jump here if there is accepted connection in the TCP
+void TCPAccepted(LISTENER *r, SOCK *s)
+{
+ TCP_ACCEPTED_PARAM *data;
+ THREAD *t;
+ char tmp[MAX_SIZE];
+ UINT num_clients_from_this_ip = 0;
+ CEDAR *cedar;
+ // Validate arguments
+ if (r == NULL || s == NULL)
+ {
+ return;
+ }
+
+ cedar = r->Cedar;
+
+ num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);
+
+
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+
+ data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));
+ data->r = r;
+ data->s = s;
+
+ if (r->ThreadProc == TCPAcceptedThread)
+ {
+ Inc(cedar->AcceptingSockets);
+ }
+
+ t = NewThread(r->ThreadProc, data);
+ WaitThreadInit(t);
+ Free(data);
+ ReleaseThread(t);
+}
+
+
+// UDP listener main loop
+void ListenerUDPMainLoop(LISTENER *r)
+{
+ UCHAR *data;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ Debug("ListenerUDPMainLoop Starts.\n");
+ r->Status = LISTENER_STATUS_TRYING;
+
+ while (true)
+ {
+ // Try to listen on the UDP port
+ while (true)
+ {
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ return;
+ }
+
+ Debug("NewUDP()\n");
+ r->Sock = NewUDP(r->Port);
+ if (r->Sock != NULL)
+ {
+ // Wait success
+ break;
+ }
+
+ // Wait failure
+ Debug("Failed to NewUDP.\n");
+ Wait(r->Event, LISTEN_RETRY_TIME);
+
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ Debug("UDP Halt.\n");
+ return;
+ }
+ }
+
+ r->Status = LISTENER_STATUS_LISTENING;
+ Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);
+
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ goto STOP;
+ }
+
+ // Allocate the buffer area
+ data = Malloc(UDP_PACKET_SIZE);
+
+ // Read the next packet
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ UINT size;
+ SOCKSET set;
+
+ InitSockSet(&set);
+ AddSockSet(&set, r->Sock);
+ Select(&set, SELECT_TIME, NULL, NULL);
+
+ size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
+ if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
+ {
+ // Error has occurred
+STOP:
+ Disconnect(r->Sock);
+ ReleaseSock(r->Sock);
+ r->Sock = NULL;
+ Debug("UDP Listen Stopped.\n");
+ Free(data);
+ break;
+ }
+
+ // Received an UDP packet
+ if (size != SOCK_LATER)
+ {
+ UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
+ }
+ }
+ }
+}
+
+// RPC reception procedure
+bool ListenerRUDPRpcRecvProc(RUDP_STACK *r, UDPPACKET *p)
+{
+ return false;
+}
+
+// TCP listener main loop
+void ListenerTCPMainLoop(LISTENER *r)
+{
+ SOCK *new_sock;
+ SOCK *s;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ Debug("ListenerTCPMainLoop Starts.\n");
+ r->Status = LISTENER_STATUS_TRYING;
+
+ while (true)
+ {
+ bool first_failed = true;
+ Debug("Status = LISTENER_STATUS_TRYING\n");
+ r->Status = LISTENER_STATUS_TRYING;
+
+ // Try to Listen
+ while (true)
+ {
+ UINT interval;
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ return;
+ }
+
+ s = NULL;
+
+ if (r->Protocol == LISTENER_TCP)
+ {
+ if (r->ShadowIPv6 == false)
+ {
+ s = ListenEx2(r->Port, r->LocalOnly, r->EnableConditionalAccept);
+ }
+ else
+ {
+ s = ListenEx6(r->Port, r->LocalOnly);
+ }
+ }
+ else if (r->Protocol == LISTENER_INPROC)
+ {
+ s = ListenInProc();
+ }
+ else if (r->Protocol == LISTENER_RUDP)
+ {
+ s = ListenRUDPEx(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 0, false, false, r->NatTGlobalUdpPort, r->RandPortId);
+ }
+ else if (r->Protocol == LISTENER_ICMP)
+ {
+ s = ListenRUDP(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4),
+ true, false);
+ }
+ else if (r->Protocol == LISTENER_DNS)
+ {
+ s = ListenRUDP(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 53, true, true);
+ }
+ else if (r->Protocol == LISTENER_REVERSE)
+ {
+ s = ListenReverse();
+ }
+
+ if (s != NULL)
+ {
+ // Listen success
+ AddRef(s->ref);
+
+ Lock(r->lock);
+ {
+ r->Sock = s;
+ }
+ Unlock(r->lock);
+
+ if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
+ {
+ SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);
+ }
+ break;
+ }
+
+ // Listen failure
+ if (first_failed)
+ {
+ first_failed = false;
+ if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
+ {
+ SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);
+ }
+ }
+
+ interval = LISTEN_RETRY_TIME;
+
+ if (r->ShadowIPv6)
+ {
+ if (IsIPv6Supported() == false)
+ {
+ interval = LISTEN_RETRY_TIME_NOIPV6;
+
+ Debug("IPv6 is not supported.\n");
+ }
+ }
+
+ Wait(r->Event, interval);
+
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ Debug("Listener Halt.\n");
+ return;
+ }
+ }
+
+ r->Status = LISTENER_STATUS_LISTENING;
+ Debug("Status = LISTENER_STATUS_LISTENING\n");
+
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ goto STOP;
+ }
+
+ // Accpet loop
+ while (true)
+ {
+ // Accept
+ Debug("Accept()\n");
+ new_sock = Accept(s);
+ if (new_sock != NULL)
+ {
+ // Accept success
+ Debug("Accepted.\n");
+ TCPAccepted(r, new_sock);
+ ReleaseSock(new_sock);
+ }
+ else
+ {
+STOP:
+ Debug("Accept Canceled.\n");
+ // Failed to accept (socket is destroyed)
+ // Close the listening socket
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+
+ Lock(r->lock);
+ {
+ if (r->Sock != NULL)
+ {
+ s = r->Sock;
+ r->Sock = NULL;
+ }
+ }
+ Unlock(r->lock);
+
+ if (s != NULL)
+ {
+ ReleaseSock(s);
+ }
+
+ s = NULL;
+
+ break;
+ }
+ }
+
+ // Stop flag inspection
+ if (r->Halt)
+ {
+ // Stop
+ Debug("Listener Halt.\n");
+ return;
+ }
+ }
+}
+
+// Listener Thread
+void ListenerThread(THREAD *thread, void *param)
+{
+ LISTENER *r;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Initialize
+ r = (LISTENER *)param;
+ AddRef(r->ref);
+ r->Thread = thread;
+ AddRef(thread->ref);
+ NoticeThreadInit(thread);
+
+ // Main loop
+ switch (r->Protocol)
+ {
+ case LISTENER_TCP:
+ case LISTENER_INPROC:
+ case LISTENER_RUDP:
+ case LISTENER_DNS:
+ case LISTENER_ICMP:
+ case LISTENER_REVERSE:
+ // TCP or other stream-based protocol
+ ListenerTCPMainLoop(r);
+ break;
+
+ case LISTENER_UDP:
+ // UDP protocol
+ ListenerUDPMainLoop(r);
+ break;
+ }
+
+ // Release
+ ReleaseListener(r);
+}
+
+// Shutdown the Listener
+void StopListener(LISTENER *r)
+{
+ UINT port;
+ SOCK *s = NULL;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ Lock(r->lock);
+ if (r->Halt)
+ {
+ Unlock(r->lock);
+ return;
+ }
+
+ // Stop flag set
+ r->Halt = true;
+
+ if (r->Sock != NULL)
+ {
+ s = r->Sock;
+
+ AddRef(s->ref);
+ }
+
+ Unlock(r->lock);
+
+ port = r->Port;
+
+ if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
+ {
+ SLog(r->Cedar, "LS_LISTENER_STOP_1", port);
+ }
+
+ // Close the socket
+ if (s != NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+ }
+
+ // Set the event
+ Set(r->Event);
+
+ // Wait for stopping the thread
+ WaitThread(r->Thread, INFINITE);
+
+ // Stop the shadow listener
+ if (r->ShadowIPv6 == false)
+ {
+ if (r->ShadowListener != NULL)
+ {
+ StopListener(r->ShadowListener);
+
+ ReleaseListener(r->ShadowListener);
+
+ r->ShadowListener = NULL;
+ }
+ }
+
+ if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
+ {
+ SLog(r->Cedar, "LS_LISTENER_STOP_2", port);
+ }
+}
+
+// Cleanup the listener
+void CleanupListener(LISTENER *r)
+{
+ UINT i = 0;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+
+ if (r->Sock != NULL)
+ {
+ ReleaseSock(r->Sock);
+ }
+
+ DeleteLock(r->lock);
+ ReleaseThread(r->Thread);
+ ReleaseEvent(r->Event);
+
+ ReleaseCedar(r->Cedar);
+
+ Free(r);
+}
+
+// Release the listener
+void ReleaseListener(LISTENER *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ if (Release(r->ref) == 0)
+ {
+ CleanupListener(r);
+ }
+}
+
+// Comparison function of UDP entry list
+int CompareUDPEntry(void *p1, void *p2)
+{
+ UDP_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(UDP_ENTRY **)p1;
+ e2 = *(UDP_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->SessionKey32 > e2->SessionKey32)
+ {
+ return 1;
+ }
+ else if (e1->SessionKey32 == e2->SessionKey32)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+// Comparison function of the listener
+int CompareListener(void *p1, void *p2)
+{
+ LISTENER *r1, *r2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ r1 = *(LISTENER **)p1;
+ r2 = *(LISTENER **)p2;
+ if (r1 == NULL || r2 == NULL)
+ {
+ return 0;
+ }
+
+ if (r1->Protocol > r2->Protocol)
+ {
+ return 1;
+ }
+ else if (r1->Protocol < r2->Protocol)
+ {
+ return -1;
+ }
+ else if (r1->Port > r2->Port)
+ {
+ return 1;
+ }
+ else if (r1->Port < r2->Port)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Create a New Listener
+LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)
+{
+ return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);
+}
+LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)
+{
+ return NewListenerEx2(cedar, proto, port, proc, thread_param, false);
+}
+LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)
+{
+ return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);
+}
+LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)
+{
+ return NewListenerEx4(cedar, proto, port, proc, thread_param, local_only, shadow_ipv6, NULL, 0);
+}
+LISTENER *NewListenerEx4(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ return NewListenerEx5(cedar, proto, port, proc, thread_param,
+ local_only, shadow_ipv6, natt_global_udp_port, rand_port_id, false);
+}
+LISTENER *NewListenerEx5(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id, bool enable_ca)
+{
+ LISTENER *r;
+ THREAD *t;
+ // Validate arguments
+ if ((proto == LISTENER_TCP && port == 0) || cedar == NULL)
+ {
+ return NULL;
+ }
+ // Check the protocol number
+ if (proto != LISTENER_TCP && proto != LISTENER_INPROC &&
+ proto != LISTENER_RUDP && proto != LISTENER_ICMP && proto != LISTENER_DNS &&
+ proto != LISTENER_REVERSE)
+ {
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(LISTENER));
+
+ r->ThreadProc = proc;
+ r->ThreadParam = thread_param;
+ r->Cedar = cedar;
+ AddRef(r->Cedar->ref);
+ r->lock = NewLock();
+ r->ref = NewRef();
+ r->Protocol = proto;
+ r->Port = port;
+ r->Event = NewEvent();
+
+
+ r->LocalOnly = local_only;
+ r->ShadowIPv6 = shadow_ipv6;
+ r->NatTGlobalUdpPort = natt_global_udp_port;
+ r->RandPortId = rand_port_id;
+ r->EnableConditionalAccept = enable_ca;
+
+ if (r->ShadowIPv6 == false)
+ {
+ if (proto == LISTENER_TCP)
+ {
+ SLog(cedar, "LS_LISTENER_START_1", port);
+ }
+ }
+
+ // Creating a thread
+ t = NewThread(ListenerThread, r);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ if (r->ShadowIPv6 == false && proto == LISTENER_TCP)
+ {
+ if (r->Cedar->DisableIPv6Listener == false)
+ {
+ // Add a shadow listener
+ r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,
+ local_only, true);
+ }
+ }
+
+ if (r->ShadowIPv6 == false)
+ {
+ // Add to the Cedar
+ AddListener(cedar, r);
+ }
+
+ return r;
+}
+
+// Get the session from the session key
+SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)
+{
+ UDP_ENTRY *e, t;
+ SESSION *s;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ t.SessionKey32 = key32;
+
+ LockList(cedar->UDPEntryList);
+ {
+ e = Search(cedar->UDPEntryList, &t);
+ if (e == NULL)
+ {
+ UnlockList(cedar->UDPEntryList);
+ return NULL;
+ }
+ s = e->Session;
+ AddRef(s->ref);
+ }
+ UnlockList(cedar->UDPEntryList);
+
+ return s;
+}
+
+// Delete the UDP session from the UDP entry
+void DelUDPEntry(CEDAR *cedar, SESSION *session)
+{
+ UINT num, i;
+ // Validate arguments
+ if (cedar == NULL || session == NULL)
+ {
+ return;
+ }
+
+ LockList(cedar->UDPEntryList);
+ {
+ num = LIST_NUM(cedar->UDPEntryList);
+ for (i = 0;i < num;i++)
+ {
+ UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);
+ if (e->Session == session)
+ {
+ ReleaseSession(e->Session);
+ Delete(cedar->UDPEntryList, e);
+ Free(e);
+ UnlockList(cedar->UDPEntryList);
+ Debug("UDP_Entry Deleted.\n");
+ return;
+ }
+ }
+ }
+ UnlockList(cedar->UDPEntryList);
+}
+
+// Add an UDP session to the UDP entry
+void AddUDPEntry(CEDAR *cedar, SESSION *session)
+{
+ UDP_ENTRY *e;
+ // Validate arguments
+ if (cedar == NULL || session == NULL)
+ {
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(UDP_ENTRY));
+ e->Session = session;
+ e->SessionKey32 = session->SessionKey32;
+ AddRef(session->ref);
+
+ LockList(cedar->UDPEntryList);
+ {
+ Add(cedar->UDPEntryList, e);
+ }
+ UnlockList(cedar->UDPEntryList);
+
+ Debug("UDP_Entry Added.\n");
+}
+
+// Clear the UDP entry
+void CleanupUDPEntry(CEDAR *cedar)
+{
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return;
+ }
+}
+
+// Create a new dynamic listener
+DYNAMIC_LISTENER *NewDynamicListener(CEDAR *c, bool *enable_ptr, UINT protocol, UINT port)
+{
+ DYNAMIC_LISTENER *d;
+ // Validate arguments
+ if (c == NULL || enable_ptr == NULL)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(DYNAMIC_LISTENER));
+
+ d->Cedar = c;
+ AddRef(d->Cedar->ref);
+
+ d->Lock = NewLock();
+
+ d->EnablePtr = enable_ptr;
+
+ d->Listener = NULL;
+
+ d->Protocol = protocol;
+ d->Port = port;
+
+ ApplyDynamicListener(d);
+
+ return d;
+}
+
+// Release the dynamic listener
+void FreeDynamicListener(DYNAMIC_LISTENER *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Lock(d->Lock);
+ {
+ if (d->Listener != NULL)
+ {
+ StopListener(d->Listener);
+ ReleaseListener(d->Listener);
+ d->Listener = NULL;
+ }
+ }
+ Unlock(d->Lock);
+
+ ReleaseCedar(d->Cedar);
+
+ DeleteLock(d->Lock);
+
+ Free(d);
+}
+
+// Set the state to dynamic listener
+void ApplyDynamicListener(DYNAMIC_LISTENER *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Lock(d->Lock);
+ {
+ // Change the state
+ if (*d->EnablePtr)
+ {
+ if (d->Listener == NULL)
+ {
+ // Create a listener
+ WHERE;
+ d->Listener = NewListener(d->Cedar, d->Protocol, d->Port);
+ }
+ }
+ else
+ {
+ // Stop the listener
+ if (d->Listener != NULL)
+ {
+ WHERE;
+ StopListener(d->Listener);
+ ReleaseListener(d->Listener);
+ d->Listener = NULL;
+ }
+ }
+ }
+ Unlock(d->Lock);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Listener.h b/src/Cedar/Listener.h
new file mode 100644
index 00000000..454b5f87
--- /dev/null
+++ b/src/Cedar/Listener.h
@@ -0,0 +1,188 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Listener.h
+// Header of Listener.c
+
+#ifndef LISTENER_H
+#define LISTENER_H
+
+
+// Function to call when receiving a new connection
+typedef void (NEW_CONNECTION_PROC)(CONNECTION *c);
+
+
+
+// Listener structure
+struct LISTENER
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ UINT Protocol; // Protocol
+ UINT Port; // Port number
+ THREAD *Thread; // Operating thread
+ SOCK *Sock; // Socket
+ EVENT *Event; // Event
+ volatile bool Halt; // Halting flag
+ UINT Status; // State
+
+
+ THREAD_PROC *ThreadProc; // Thread procedure
+ void *ThreadParam; // Thread parameters
+ bool LocalOnly; // Can be connected only from localhost
+ bool ShadowIPv6; // Flag indicating that the shadow IPv6 listener
+ LISTENER *ShadowListener; // Reference to managing shadow IPv6 listener
+ bool DisableDos; // Disable the DoS attack detection
+ volatile UINT *NatTGlobalUdpPort; // NAT-T global UDP port number
+ UCHAR RandPortId; // NAT-T UDP random port ID
+ bool EnableConditionalAccept; // The flag of whether to enable the Conditional Accept
+};
+
+// Parameters of TCPAcceptedThread
+struct TCP_ACCEPTED_PARAM
+{
+ LISTENER *r;
+ SOCK *s;
+};
+
+// UDP entry
+struct UDP_ENTRY
+{
+ UINT SessionKey32; // 32bit session key
+ SESSION *Session; // Reference to the session
+};
+
+// Dynamic listener
+struct DYNAMIC_LISTENER
+{
+ UINT Protocol; // Protocol
+ UINT Port; // Port
+ LOCK *Lock; // Lock
+ CEDAR *Cedar; // Cedar
+ bool *EnablePtr; // A pointer to the flag of the valid / invalid state
+ LISTENER *Listener; // Listener
+};
+
+
+// Function prototype
+LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port);
+LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param);
+LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only);
+LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6);
+LISTENER *NewListenerEx4(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+LISTENER *NewListenerEx5(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id, bool enable_ca);
+void ReleaseListener(LISTENER *r);
+void CleanupListener(LISTENER *r);
+void ListenerThread(THREAD *thread, void *param);
+void ListenerTCPMainLoop(LISTENER *r);
+void StopListener(LISTENER *r);
+int CompareListener(void *p1, void *p2);
+void TCPAccepted(LISTENER *r, SOCK *s);
+void EnableDosProtect();
+void DisableDosProtect();
+void TCPAcceptedThread(THREAD *t, void *param);
+void ListenerUDPMainLoop(LISTENER *r);
+void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size);
+int CompareUDPEntry(void *p1, void *p2);
+void CleanupUDPEntry(CEDAR *cedar);
+void AddUDPEntry(CEDAR *cedar, SESSION *session);
+void DelUDPEntry(CEDAR *cedar, SESSION *session);
+SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32);
+UINT GetMaxConnectionsPerIp();
+void SetMaxConnectionsPerIp(UINT num);
+UINT GetMaxUnestablishedConnections();
+void SetMaxUnestablishedConnections(UINT num);
+DYNAMIC_LISTENER *NewDynamicListener(CEDAR *c, bool *enable_ptr, UINT protocol, UINT port);
+void ApplyDynamicListener(DYNAMIC_LISTENER *d);
+void FreeDynamicListener(DYNAMIC_LISTENER *d);
+bool ListenerRUDPRpcRecvProc(RUDP_STACK *r, UDPPACKET *p);
+void ListenerSetProcRecvRpcEnable(bool b);
+
+
+#endif // LISTENER_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Logging.c b/src/Cedar/Logging.c
new file mode 100644
index 00000000..a5bcf2d8
--- /dev/null
+++ b/src/Cedar/Logging.c
@@ -0,0 +1,2054 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Logging.c
+// Log storaging module
+
+#include "CedarPch.h"
+
+static char *delete_targets[] =
+{
+ "backup.vpn_bridge.config",
+ "backup.vpn_client.config",
+ "backup.vpn_server.config",
+ "backup.vpn_gate_svc.config",
+ "backup.etherlogger.config",
+ "packet_log",
+ "etherlogger_log",
+ "secure_nat_log",
+ "security_log",
+ "server_log",
+ "bridge_log",
+ "packet_log_archive",
+};
+
+// Send with syslog
+void SendSysLog(SLOG *g, wchar_t *str)
+{
+}
+
+// Release the syslog client
+void FreeSysLog(SLOG *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(g->lock);
+ ReleaseSock(g->Udp);
+ Free(g);
+}
+
+// Configure the syslog client
+void SetSysLog(SLOG *g, char *hostname, UINT port)
+{
+ IP ip;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+ if (port == 0)
+ {
+ port = SYSLOG_PORT;
+ }
+
+ if (hostname == NULL)
+ {
+ hostname = "";
+ }
+
+ Zero(&ip, sizeof(IP));
+ GetIP(&ip, hostname);
+
+ Lock(g->lock);
+ {
+ Copy(&g->DestIp, &ip, sizeof(IP));
+ g->DestPort = port;
+ StrCpy(g->HostName, sizeof(g->HostName), hostname);
+ g->NextPollIp = Tick64() + IsZeroIp(&ip) ? SYSLOG_POLL_IP_INTERVAL_NG : SYSLOG_POLL_IP_INTERVAL;
+ }
+ Unlock(g->lock);
+}
+
+// Create a syslog client
+SLOG *NewSysLog(char *hostname, UINT port)
+{
+ // Validate arguments
+ SLOG *g = ZeroMalloc(sizeof(SLOG));
+
+ g->lock = NewLock();
+ g->Udp = NewUDP(0);
+
+ SetSysLog(g, hostname, port);
+
+ return g;
+}
+
+// Check if there is enough free space on the disk
+bool CheckEraserDiskFreeSpace(ERASER *e)
+{
+ UINT64 s;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return true;
+ }
+
+ // Get the free disk space
+ if (GetDiskFree(e->DirName, &s, NULL, NULL) == false)
+ {
+ // Acquisition failure
+ return true;
+ }
+
+ if (e->MinFreeSpace > s)
+ {
+ // The free space is smaller than specified bytes
+ return false;
+ }
+
+ // Vacant enough
+ return true;
+}
+
+// Release the deleting file list
+void FreeEraseFileList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ERASE_FILE *f = LIST_DATA(o, i);
+ Free(f->FullPath);
+ Free(f);
+ }
+
+ ReleaseList(o);
+}
+
+// Show the deleting file list
+void PrintEraseFileList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ERASE_FILE *f = LIST_DATA(o, i);
+ Print("%I64u - %s\n", f->UpdateTime, f->FullPath);
+ }
+}
+
+// Generate a deleting file list of the specified directory
+void EnumEraseFile(LIST *o, char *dirname)
+{
+ DIRLIST *dir;
+ UINT i;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (o == NULL || dirname == NULL)
+ {
+ return;
+ }
+
+ // Enumeration
+ dir = EnumDir(dirname);
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+ Format(tmp, sizeof(tmp), "%s/%s", dirname, e->FileName);
+ NormalizePath(tmp, sizeof(tmp), tmp);
+
+ if (e->Folder == false)
+ {
+ // File
+ ERASE_FILE *f;
+
+ if (EndWith(tmp, ".log") || EndWith(tmp, ".config") || EndWith(tmp, ".old"))
+ {
+ // Target only .config files and .log files
+ f = ZeroMalloc(sizeof(ERASE_FILE));
+ f->FullPath = CopyStr(tmp);
+ f->UpdateTime = e->UpdateDate;
+
+ Add(o, f);
+ }
+ }
+ else
+ {
+ // Folder
+ EnumEraseFile(o, tmp);
+ }
+ }
+
+ FreeDir(dir);
+}
+
+// Generate a deleting file list
+LIST *GenerateEraseFileList(ERASER *e)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(CompareEraseFile);
+
+ // Scan for each directory
+ for (i = 0;i < sizeof(delete_targets) / sizeof(delete_targets[0]);i++)
+ {
+ char dirname[MAX_PATH];
+ Format(dirname, sizeof(dirname), "%s/%s", e->DirName, delete_targets[i]);
+
+ EnumEraseFile(o, dirname);
+ }
+
+ // Sort
+ Sort(o);
+
+ return o;
+}
+
+// Process of erasing unnecessary files
+void EraserMain(ERASER *e)
+{
+ LIST *o;
+ UINT i;
+ bool ok = false;
+ char bs[64];
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Check the free space first
+ if (CheckEraserDiskFreeSpace(e))
+ {
+ // Vacant enough
+ return;
+ }
+
+ ToStrByte(bs, sizeof(bs), e->MinFreeSpace);
+
+ // Generate the file list
+ o = GenerateEraseFileList(e);
+
+ // Try to delete one by one in order from oldest file
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ERASE_FILE *f = LIST_DATA(o, i);
+
+ // Delete the file
+ if (FileDelete(f->FullPath))
+ {
+ ELog(e, "LE_DELETE", bs, f->FullPath);
+ }
+
+ // Check the free space after the deleted
+ if (CheckEraserDiskFreeSpace(e))
+ {
+ // Free space has been restored
+ ok = true;
+ break;
+ }
+ }
+
+ // Release the file list
+ FreeEraseFileList(o);
+
+ if (e->LastFailed == false && ok == false)
+ {
+ // Free space is not enough, but can not delete the file any more
+ ELog(e, "LE_NOT_ENOUGH_FREE", bs);
+ }
+
+ e->LastFailed = ok ? false : true;
+}
+
+// Comparison of the deleting file entries
+int CompareEraseFile(void *p1, void *p2)
+{
+ ERASE_FILE *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(ERASE_FILE **)p1;
+ f2 = *(ERASE_FILE **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ if (f1->UpdateTime > f2->UpdateTime)
+ {
+ return 1;
+ }
+ else if (f1->UpdateTime == f2->UpdateTime)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+// Eraser thread
+void EraserThread(THREAD *t, void *p)
+{
+ ERASER *e = (ERASER *)p;
+ char bs[64];
+ // Validate arguments
+ if (t == NULL || e == NULL)
+ {
+ return;
+ }
+
+ // Start monitoring
+ ToStrByte(bs, sizeof(bs), e->MinFreeSpace);
+ ELog(e, "LE_START", e->DirName, bs);
+
+ while (e->Halt == false)
+ {
+ // Check the amount of free space on the disk periodically
+ EraserMain(e);
+
+ Wait(e->HaltEvent, DISK_FREE_CHECK_INTERVAL);
+ }
+}
+
+// Create a new eraser
+ERASER *NewEraser(LOG *log, UINT64 min_size)
+{
+ ERASER *e;
+ char dir[MAX_PATH];
+
+ if (min_size == 0)
+ {
+ if (OS_IS_WINDOWS(GetOsInfo()->OsType))
+ {
+ min_size = DISK_FREE_SPACE_DEFAULT_WINDOWS;
+ }
+ else
+ {
+ min_size = DISK_FREE_SPACE_DEFAULT;
+ }
+ }
+
+ if (min_size < DISK_FREE_SPACE_MIN)
+ {
+ min_size = DISK_FREE_SPACE_MIN;
+ }
+
+ e = ZeroMalloc(sizeof(ERASER));
+
+ GetExeDir(dir, sizeof(dir));
+
+ e->Log = log;
+ e->MinFreeSpace = min_size;
+ e->DirName = CopyStr(dir);
+ e->HaltEvent = NewEvent();
+
+ e->Thread = NewThread(EraserThread, e);
+
+ return e;
+}
+
+// Release the eraser
+void FreeEraser(ERASER *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ e->Halt = true;
+ Set(e->HaltEvent);
+ WaitThread(e->Thread, INFINITE);
+ ReleaseThread(e->Thread);
+ ReleaseEvent(e->HaltEvent);
+
+ Free(e->DirName);
+ Free(e);
+}
+
+// Take the debug log (variable-length argument)
+void DebugLog(CEDAR *c, char *fmt, ...)
+{
+ char buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+ if (c->DebugLog == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ FormatArgs(buf, sizeof(buf), fmt, args);
+
+ InsertStringRecord(c->DebugLog, buf);
+ va_end(args);
+}
+
+// Take the log of eraser
+void ELog(ERASER *e, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ InsertUnicodeRecord(e->Log, buf);
+
+ if (IsDebug())
+ {
+ UniPrint(L"LOG: %s\n", buf);
+ }
+ va_end(args);
+}
+
+// Take the log of the server
+void ServerLog(CEDAR *c, wchar_t *fmt, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniFormatArgs(buf, sizeof(buf), fmt, args);
+
+ WriteServerLog(c, buf);
+ va_end(args);
+}
+void SLog(CEDAR *c, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ WriteServerLog(c, buf);
+ va_end(args);
+}
+
+// Client log
+void CLog(CLIENT *c, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (c == NULL || c->NoSaveLog)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ WriteClientLog(c, buf);
+ va_end(args);
+}
+
+// Take the security log of the HUB
+void HubLog(HUB *h, wchar_t *fmt, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniFormatArgs(buf, sizeof(buf), fmt, args);
+
+ WriteHubLog(h, buf);
+ va_end(args);
+}
+void ALog(ADMIN *a, HUB *h, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ wchar_t tmp[MAX_SIZE * 2];
+ va_list args;
+ RPC *r;
+ // Validate arguments
+ if (a == NULL || name == NULL)
+ {
+ return;
+ }
+
+ r = a->Rpc;
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ if (h == NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("LA_TAG_1"), r->Name);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("LA_TAG_2"), r->Name, h->Name);
+ }
+
+ UniStrCat(tmp, sizeof(tmp), buf);
+
+ if (h == NULL)
+ {
+ WriteServerLog(((ADMIN *)r->Param)->Server->Cedar, tmp);
+ }
+ else
+ {
+ WriteHubLog(h, tmp);
+ }
+ va_end(args);
+}
+void HLog(HUB *h, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ WriteHubLog(h, buf);
+ va_end(args);
+}
+void NLog(VH *v, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ static wchar_t snat_prefix[] = L"SecureNAT: ";
+ va_list args;
+ // Validate arguments
+ if (name == NULL || v == NULL || v->nat == NULL || v->nat->SecureNAT == NULL || v->SaveLog == false)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ Copy(buf, snat_prefix, sizeof(snat_prefix));
+ UniFormatArgs(&buf[11], sizeof(buf) - 12 * sizeof(wchar_t), _UU(name), args);
+
+ WriteHubLog(v->nat->SecureNAT->Hub, buf);
+ va_end(args);
+}
+
+// Writing EtherIP log
+void EtherIPLog(ETHERIP_SERVER *s, char *name, ...)
+{
+ wchar_t prefix[MAX_SIZE * 2];
+ wchar_t buf2[MAX_SIZE * 2];
+ char server_ip[64];
+ char client_ip[64];
+ va_list args;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ IPToStr(server_ip, sizeof(server_ip), &s->ServerIP);
+ IPToStr(client_ip, sizeof(client_ip), &s->ClientIP);
+
+ UniFormat(prefix, sizeof(prefix), _UU("LE_PREFIX"), s->Id,
+ server_ip, s->ServerPort, client_ip, s->ClientPort);
+
+ va_start(args, name);
+ UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
+ va_end(args);
+
+ UniStrCat(prefix, sizeof(prefix), buf2);
+
+ WriteServerLog(s->Cedar, prefix);
+}
+
+// Write an IPsec log
+void IPsecLog(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, IPSECSA *ipsec_sa, char *name, ...)
+{
+ wchar_t prefix[MAX_SIZE * 2];
+ wchar_t buf2[MAX_SIZE * 2];
+ char server_ip[64];
+ char client_ip[64];
+ va_list args;
+ // Validate arguments
+ if (ike == NULL)
+ {
+ return;
+ }
+ if (ipsec_sa != NULL)
+ {
+ c = ipsec_sa->IkeClient;
+ }
+ else if (ike_sa != NULL)
+ {
+ c = ike_sa->IkeClient;
+ }
+
+ if (c == NULL)
+ {
+ UniStrCpy(prefix, sizeof(prefix), _UU("LI_PREFIX_RAW"));
+ }
+ else
+ {
+ IPToStr(server_ip, sizeof(server_ip), &c->ServerIP);
+ IPToStr(client_ip, sizeof(client_ip), &c->ClientIP);
+
+ if (ipsec_sa != NULL)
+ {
+ UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_IPSEC"),
+ ipsec_sa->Id, c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
+ }
+ else if (ike_sa != NULL)
+ {
+ UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_IKE"),
+ ike_sa->Id, c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
+ }
+ else
+ {
+ UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_CLIENT"),
+ c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
+ }
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
+ va_end(args);
+
+ UniStrCat(prefix, sizeof(prefix), buf2);
+
+ WriteServerLog(ike->Cedar, prefix);
+}
+
+// Write a PPP log
+void PPPLog(PPP_SESSION *p, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ wchar_t buf2[MAX_SIZE * 2];
+ char ipstr[128];
+ char *s1 = "", *s2 = "";
+ va_list args;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (StrCmpi(p->Postfix, "PPP") != 0)
+ {
+ s1 = p->Postfix;
+ s2 = " ";
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
+ va_end(args);
+
+ IPToStr(ipstr, sizeof(ipstr), &p->ClientIP);
+
+ UniFormat(buf, sizeof(buf), _UU("LP_PREFIX"), s1, s2, ipstr, p->ClientPort);
+
+ UniStrCat(buf, sizeof(buf), buf2);
+
+ WriteServerLog(p->Cedar, buf);
+}
+
+// Write an IPC log
+void IPCLog(IPC *ipc, char *name, ...)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ va_list args;
+ HUB *h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ h = GetHub(ipc->Cedar, ipc->HubName);
+
+ if (h == NULL)
+ {
+ return;
+ }
+
+ va_start(args, name);
+ UniFormatArgs(buf, sizeof(buf), _UU(name), args);
+
+ WriteHubLog(h, buf);
+ va_end(args);
+
+ ReleaseHub(h);
+}
+
+// Save the security log of the HUB
+void WriteHubLog(HUB *h, wchar_t *str)
+{
+ wchar_t buf[MAX_SIZE * 2];
+ UINT syslog_status;
+ SERVER *s;
+ // Validate arguments
+ if (h == NULL || str == NULL)
+ {
+ return;
+ }
+
+ s = h->Cedar->Server;
+ syslog_status = SiGetSysLogSaveStatus(s);
+
+ UniFormat(buf, sizeof(buf), L"[HUB \"%S\"] %s", h->Name, str);
+
+ if (syslog_status == SYSLOG_NONE)
+ {
+ WriteServerLog(h->Cedar, buf);
+ }
+
+ if (h->LogSetting.SaveSecurityLog == false)
+ {
+ return;
+ }
+
+ if (syslog_status == SYSLOG_SERVER_AND_HUB_SECURITY_LOG
+ || syslog_status == SYSLOG_SERVER_AND_HUB_ALL_LOG)
+ {
+ SiWriteSysLog(s, "SECURITY_LOG", h->Name, str);
+ }
+ else
+ {
+ InsertUnicodeRecord(h->SecurityLogger, str);
+ }
+}
+
+// Save the client log
+void WriteClientLog(CLIENT *c, wchar_t *str)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ InsertUnicodeRecord(c->Logger, str);
+}
+
+// Save the security log of the server
+void WriteServerLog(CEDAR *c, wchar_t *str)
+{
+ SERVER *s;
+ // Validate arguments
+ if (c == NULL || str == NULL)
+ {
+ return;
+ }
+
+ s = c->Server;
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (IsDebug())
+ {
+ UniPrint(L"LOG: %s\n", str);
+ }
+
+ if (SiGetSysLogSaveStatus(s) != SYSLOG_NONE)
+ {
+ SiWriteSysLog(s, "SERVER_LOG", NULL, str);
+ }
+ else
+ {
+ InsertUnicodeRecord(s->Logger, str);
+ }
+}
+
+// Write a multi-line log
+void WriteMultiLineLog(LOG *g, BUF *b)
+{
+ // Validate arguments
+ if (g == NULL || b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ while (true)
+ {
+ char *s = CfgReadNextLine(b);
+ if (s == NULL)
+ {
+ break;
+ }
+
+ if (IsEmptyStr(s) == false)
+ {
+ InsertStringRecord(g, s);
+ }
+
+ Free(s);
+ }
+}
+
+// Take the security log (variable-length argument) *abolished
+void SecLog(HUB *h, char *fmt, ...)
+{
+ char buf[MAX_SIZE * 2];
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ if (h->LogSetting.SaveSecurityLog == false)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ FormatArgs(buf, sizeof(buf), fmt, args);
+
+ WriteSecurityLog(h, buf);
+ va_end(args);
+}
+
+// Take a security log
+void WriteSecurityLog(HUB *h, char *str)
+{
+ // Validate arguments
+ if (h == NULL || str == NULL)
+ {
+ return;
+ }
+
+ InsertStringRecord(h->SecurityLogger, str);
+}
+
+// Take a packet log
+bool PacketLog(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *packet, UINT64 now)
+{
+ return true;
+}
+
+// Calculate the logging level of the specified packet
+UINT CalcPacketLoggingLevelEx(HUB_LOG *g, PKT *packet)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (g == NULL || packet == NULL)
+ {
+ return PACKET_LOG_NONE;
+ }
+
+ // Ethernet log
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ETHERNET]);
+
+ switch (packet->TypeL3)
+ {
+ case L3_ARPV4:
+ // ARP
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ARP]);
+ break;
+
+ case L3_IPV4:
+ // IPv4
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_IP]);
+
+ switch (packet->TypeL4)
+ {
+ case L4_ICMPV4:
+ // ICMPv4
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ICMP]);
+ break;
+
+ case L4_TCP:
+ // TCPv4
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP]);
+
+ if (packet->L4.TCPHeader->Flag & TCP_SYN ||
+ packet->L4.TCPHeader->Flag & TCP_RST ||
+ packet->L4.TCPHeader->Flag & TCP_FIN)
+ {
+ // TCP SYN LOG
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ }
+
+ break;
+
+ case L4_UDP:
+ // UDPv4
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_UDP]);
+
+ switch (packet->TypeL7)
+ {
+ case L7_DHCPV4:
+ // DHCPv4
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_DHCP]);
+ break;
+
+ case L7_IKECONN:
+ // IKE connection request
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ break;
+
+ case L7_OPENVPNCONN:
+ // OpenVPN connection request
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ break;
+ }
+
+ break;
+ }
+
+ break;
+
+ case L3_IPV6:
+ // IPv6
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_IP]);
+
+ switch (packet->TypeL4)
+ {
+ case L4_ICMPV6:
+ // ICMPv6
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ICMP]);
+ break;
+
+ case L4_TCP:
+ // TCPv6
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP]);
+
+ if (packet->L4.TCPHeader->Flag & TCP_SYN ||
+ packet->L4.TCPHeader->Flag & TCP_RST ||
+ packet->L4.TCPHeader->Flag & TCP_FIN)
+ {
+ // TCP SYN LOG
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ }
+
+ break;
+
+ case L4_UDP:
+ // UDPv6
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_UDP]);
+
+ switch (packet->TypeL7)
+ {
+ case L7_IKECONN:
+ // IKE connection request
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ break;
+
+ case L7_OPENVPNCONN:
+ // OpenVPN connection request
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ break;
+ }
+
+ break;
+ }
+
+ break;
+ }
+
+ if (packet->HttpLog != NULL)
+ {
+ // HTTP Connect Log
+ ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ }
+
+ return ret;
+}
+UINT CalcPacketLoggingLevel(HUB *hub, PKT *packet)
+{
+ // Validate arguments
+ if (hub == NULL || packet == NULL)
+ {
+ return PACKET_LOG_NONE;
+ }
+
+ return CalcPacketLoggingLevelEx(&hub->LogSetting, packet);
+}
+
+// Generate a string to be stored as an HTTP log
+char *BuildHttpLogStr(HTTPLOG *h)
+{
+ BUF *b;
+ char url[MAX_SIZE];
+ char nullchar = 0;
+ char *ret;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return CopyStr("");
+ }
+
+ b = NewBuf();
+
+ // URL generation
+ if (h->Port == 80)
+ {
+ Format(url, sizeof(url), "http://%s%s",
+ h->Hostname, h->Path);
+ }
+ else
+ {
+ Format(url, sizeof(url), "http://%s:%u%s",
+ h->Hostname, h->Port, h->Path);
+ }
+
+ AddLogBufToStr(b, "HttpMethod", h->Method);
+ AddLogBufToStr(b, "HttpUrl", url);
+ AddLogBufToStr(b, "HttpProtocol", h->Protocol);
+ AddLogBufToStr(b, "HttpReferer", h->Referer);
+ AddLogBufToStr(b, "HttpUserAgent", h->UserAgent);
+
+ WriteBuf(b, &nullchar, 1);
+
+ ret = CopyStr(b->Buf);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Append an item to the log buffer
+void AddLogBufToStr(BUF *b, char *name, char *value)
+{
+ char tmp[MAX_SIZE * 2];
+ char *p = NULL;
+ // Validate arguments
+ if (b == NULL || value == NULL)
+ {
+ return;
+ }
+
+ if (IsEmptyStr(value))
+ {
+ return;
+ }
+
+ tmp[0] = 0;
+
+ if (IsEmptyStr(name) == false)
+ {
+ p = &tmp[StrLen(tmp)];
+ StrCat(tmp, sizeof(tmp), name);
+ MakeSafeLogStr(p);
+ StrCat(tmp, sizeof(tmp), "=");
+ }
+
+ p = &tmp[StrLen(tmp)];
+ StrCat(tmp, sizeof(tmp), value);
+ MakeSafeLogStr(p);
+ StrCat(tmp, sizeof(tmp), " ");
+
+ WriteBuf(b, tmp, StrLen(tmp));
+}
+
+// Secure the log string
+void MakeSafeLogStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ EnPrintableAsciiStr(str, '?');
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] == ',')
+ {
+ str[i] = '.';
+ }
+ else if (str[i] == ' ')
+ {
+ str[i] = '_';
+ }
+ }
+}
+
+// Procedure for converting a packet log entry to a string
+char *PacketLogParseProc(RECORD *rec)
+{
+ return NULL;
+}
+
+// Convert TCP flags to a string
+char *TcpFlagStr(UCHAR flag)
+{
+ char tmp[MAX_SIZE];
+ StrCpy(tmp, sizeof(tmp), "");
+
+ if (flag & TCP_FIN)
+ {
+ StrCat(tmp, sizeof(tmp), "FIN+");
+ }
+
+ if (flag & TCP_SYN)
+ {
+ StrCat(tmp, sizeof(tmp), "SYN+");
+ }
+
+ if (flag & TCP_RST)
+ {
+ StrCat(tmp, sizeof(tmp), "RST+");
+ }
+
+ if (flag & TCP_PSH)
+ {
+ StrCat(tmp, sizeof(tmp), "PSH+");
+ }
+
+ if (flag & TCP_ACK)
+ {
+ StrCat(tmp, sizeof(tmp), "ACK+");
+ }
+
+ if (flag & TCP_URG)
+ {
+ StrCat(tmp, sizeof(tmp), "URG+");
+ }
+
+ if (StrLen(tmp) >= 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == '+')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+
+ return CopyStr(tmp);
+}
+
+// Generate a port string
+char *PortStr(CEDAR *cedar, UINT port, bool udp)
+{
+ char tmp[MAX_SIZE];
+ char *name;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ name = GetSvcName(cedar, udp, port);
+
+ if (name == NULL)
+ {
+ snprintf(tmp, sizeof(tmp), "%u", port);
+ }
+ else
+ {
+ snprintf(tmp, sizeof(tmp), "%s(%u)", name, port);
+ }
+
+ return CopyStr(tmp);
+}
+
+// Generate a comma-separated string
+char *GenCsvLine(TOKEN_LIST *t)
+{
+ UINT i;
+ BUF *b;
+ char *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (t->Token[i] != NULL)
+ {
+ ReplaceForCsv(t->Token[i]);
+ if (StrLen(t->Token[i]) == 0)
+ {
+ WriteBuf(b, "-", 1);
+ }
+ else
+ {
+ WriteBuf(b, t->Token[i], StrLen(t->Token[i]));
+ }
+ }
+ else
+ {
+ WriteBuf(b, "-", 1);
+ }
+ if (i != (t->NumTokens - 1))
+ {
+ WriteBuf(b, ",", 1);
+ }
+ }
+ WriteBuf(b, "\0", 1);
+
+ ret = (char *)b->Buf;
+
+ Free(b);
+
+ return ret;
+}
+
+// Replace the strings in the CSV correctly
+void ReplaceForCsv(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // If there are blanks, trim it
+ Trim(str);
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ // Convert the comma to underscore
+ if (str[i] == ',')
+ {
+ str[i] = '_';
+ }
+ }
+}
+
+// Set the directory name of the log
+void SetLogDirName(LOG *g, char *dir)
+{
+ // Validate arguments
+ if (g == NULL || dir == NULL)
+ {
+ return;
+ }
+
+ LockLog(g);
+ {
+ if (g->DirName != NULL)
+ {
+ Free(g->DirName);
+ }
+ g->DirName = CopyStr(dir);
+ }
+ UnlockLog(g);
+}
+
+// Set the name of the log
+void SetLogPrefix(LOG *g, char *prefix)
+{
+ // Validate arguments
+ if (g == NULL || prefix == NULL)
+ {
+ return;
+ }
+
+ LockLog(g);
+ {
+ if (g->DirName != NULL)
+ {
+ Free(g->Prefix);
+ }
+ g->DirName = CopyStr(prefix);
+ }
+ UnlockLog(g);
+}
+
+// Set the switch type of log
+void SetLogSwitchType(LOG *g, UINT switch_type)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ LockLog(g);
+ {
+ g->SwitchType = switch_type;
+ }
+ UnlockLog(g);
+}
+
+// Parse the string record
+char *StringRecordParseProc(RECORD *rec)
+{
+ // Validate arguments
+ if (rec == NULL)
+ {
+ return NULL;
+ }
+
+ return (char *)rec->Data;
+}
+
+// Add an Unicode string record in the log
+void InsertUnicodeRecord(LOG *g, wchar_t *unistr)
+{
+ char *str;
+ UINT size;
+ // Validate arguments
+ if (g == NULL || unistr == NULL)
+ {
+ return;
+ }
+
+ size = CalcUniToUtf8(unistr) + 32;
+ str = ZeroMalloc(size);
+
+ UniToUtf8((BYTE *)str, size, unistr);
+ InsertStringRecord(g, str);
+ Free(str);
+}
+
+// Add a string record to the log
+void InsertStringRecord(LOG *g, char *str)
+{
+ char *str_copy;
+ // Validate arguments
+ if (g == NULL || str == NULL)
+ {
+ return;
+ }
+
+ str_copy = CopyStr(str);
+
+ InsertRecord(g, str_copy, StringRecordParseProc);
+}
+
+// Add a record to the log
+void InsertRecord(LOG *g, void *data, RECORD_PARSE_PROC *proc)
+{
+ RECORD *rec;
+ // Validate arguments
+ if (g == NULL || data == NULL || proc == NULL)
+ {
+ return;
+ }
+
+ rec = ZeroMalloc(sizeof(RECORD));
+ rec->Tick = Tick64();
+ rec->ParseProc = proc;
+ rec->Data = data;
+
+ LockQueue(g->RecordQueue);
+ {
+ InsertQueue(g->RecordQueue, rec);
+ }
+ UnlockQueue(g->RecordQueue);
+
+ Set(g->Event);
+}
+
+// Lock the log
+void LockLog(LOG *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Lock(g->lock);
+}
+
+// Unlock the log
+void UnlockLog(LOG *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Unlock(g->lock);
+}
+
+// Generate the string portion of the log file name from the time and the switching rule
+void MakeLogFileNameStringFromTick(LOG *g, char *str, UINT size, UINT64 tick, UINT switch_type)
+{
+ UINT64 time;
+ SYSTEMTIME st;
+
+ // Validate arguments
+ if (str == NULL || g == NULL)
+ {
+ return;
+ }
+
+ if (g->CacheFlag)
+ {
+ if (g->LastTick == tick &&
+ g->LastSwitchType == switch_type)
+ {
+ StrCpy(str, size, g->LastStr);
+ return;
+ }
+ }
+
+ time = TickToTime(tick);
+ UINT64ToSystem(&st, SystemToLocal64(time));
+
+ switch (switch_type)
+ {
+ case LOG_SWITCH_SECOND: // Secondly basis
+ snprintf(str, size, "_%04u%02u%02u_%02u%02u%02u",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+ break;
+
+ case LOG_SWITCH_MINUTE: // Minutely basis
+ snprintf(str, size, "_%04u%02u%02u_%02u%02u",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute);
+ break;
+
+ case LOG_SWITCH_HOUR: // Hourly basis
+ snprintf(str, size, "_%04u%02u%02u_%02u", st.wYear, st.wMonth, st.wDay, st.wHour);
+ break;
+
+ case LOG_SWITCH_DAY: // Daily basis
+ snprintf(str, size, "_%04u%02u%02u", st.wYear, st.wMonth, st.wDay);
+ break;
+
+ case LOG_SWITCH_MONTH: // Monthly basis
+ snprintf(str, size, "_%04u%02u", st.wYear, st.wMonth);
+ break;
+
+ default: // Without switching
+ snprintf(str, size, "");
+ break;
+ }
+
+ g->CacheFlag = true;
+ g->LastTick = tick;
+ g->LastSwitchType = switch_type;
+ StrCpy(g->LastStr, sizeof(g->LastStr), str);
+}
+
+// Create a log file name
+bool MakeLogFileName(LOG *g, char *name, UINT size, char *dir, char *prefix, UINT64 tick, UINT switch_type, UINT num, char *old_datestr)
+{
+ char tmp[MAX_SIZE];
+ char tmp2[64];
+ bool ret = false;
+ // Validate arguments
+ if (g == NULL || name == NULL || prefix == NULL || old_datestr == NULL)
+ {
+ return false;
+ }
+
+ MakeLogFileNameStringFromTick(g, tmp, sizeof(tmp), tick, switch_type);
+
+ if (num == 0)
+ {
+ tmp2[0] = 0;
+ }
+ else
+ {
+ snprintf(tmp2, sizeof(tmp2), "~%02u", num);
+ }
+
+ if (strcmp(old_datestr, tmp) != 0)
+ {
+ ret = true;
+ strcpy(old_datestr, tmp);
+ }
+
+ snprintf(name, size, "%s%s%s%s%s.log", dir,
+ StrLen(dir) == 0 ? "" : "/",
+ prefix, tmp, tmp2
+ );
+
+ return ret;
+}
+
+// Wait until the log have been flushed
+void WaitLogFlush(LOG *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ UINT num;
+ LockQueue(g->RecordQueue);
+ {
+ num = g->RecordQueue->num_item;
+ }
+ UnlockQueue(g->RecordQueue);
+
+ if (num == 0)
+ {
+ break;
+ }
+
+ Wait(g->FlushEvent, 100);
+ }
+}
+
+// Logging thread
+void LogThread(THREAD *thread, void *param)
+{
+ LOG *g;
+ IO *io;
+ BUF *b;
+ bool flag = false;
+ char current_file_name[MAX_SIZE];
+ char current_logfile_datename[MAX_SIZE];
+ bool last_priority_flag = false;
+ bool log_date_changed = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ Zero(current_file_name, sizeof(current_file_name));
+ Zero(current_logfile_datename, sizeof(current_logfile_datename));
+
+ g = (LOG *)param;
+
+ io = NULL;
+ b = NewBuf();
+
+#ifdef OS_WIN32
+
+ // Lower priority to bottom
+ MsSetThreadPriorityIdle();
+
+#endif // OS_WIN32
+
+ NoticeThreadInit(thread);
+
+ while (true)
+ {
+ RECORD *rec;
+ UINT64 s = Tick64();
+
+ while (true)
+ {
+ char file_name[MAX_SIZE];
+ UINT num;
+
+ // Retrieve a record from the head of the queue
+ LockQueue(g->RecordQueue);
+ {
+ rec = GetNext(g->RecordQueue);
+ num = g->RecordQueue->num_item;
+ }
+ UnlockQueue(g->RecordQueue);
+
+#ifdef OS_WIN32
+ if (num >= LOG_ENGINE_SAVE_START_CACHE_COUNT)
+ {
+ // Raise the priority
+ if (last_priority_flag == false)
+ {
+ Debug("LOG_THREAD: MsSetThreadPriorityRealtime\n");
+ MsSetThreadPriorityRealtime();
+ last_priority_flag = true;
+ }
+ }
+
+ if (num < (LOG_ENGINE_SAVE_START_CACHE_COUNT / 2))
+ {
+ // Restore the priority
+ if (last_priority_flag)
+ {
+ Debug("LOG_THREAD: MsSetThreadPriorityIdle\n");
+ MsSetThreadPriorityIdle();
+ last_priority_flag = false;
+ }
+ }
+#endif // OS_WIN32
+
+ if (b->Size > g->MaxLogFileSize)
+ {
+ // Erase if the size of the buffer is larger than the maximum log file size
+ ClearBuf(b);
+ }
+
+ if (b->Size >= LOG_ENGINE_BUFFER_CACHE_SIZE_MAX)
+ {
+ // Write the contents of the buffer to the file
+ if (io != NULL)
+ {
+ if ((g->CurrentFilePointer + (UINT64)b->Size) > g->MaxLogFileSize)
+ {
+ if (g->log_number_incremented == false)
+ {
+ g->CurrentLogNumber++;
+ g->log_number_incremented = true;
+ }
+ }
+ else
+ {
+ if (FileWrite(io, b->Buf, b->Size) == false)
+ {
+ FileCloseEx(io, true);
+ // If it fails to write to the file,
+ // erase the buffer and give up
+ ClearBuf(b);
+ io = NULL;
+ }
+ else
+ {
+ g->CurrentFilePointer += (UINT64)b->Size;
+ ClearBuf(b);
+ }
+ }
+ }
+ }
+
+ if (rec == NULL)
+ {
+ if (b->Size != 0)
+ {
+ // Write the contents of the buffer to the file
+ if (io != NULL)
+ {
+ if ((g->CurrentFilePointer + (UINT64)b->Size) > g->MaxLogFileSize)
+ {
+ if (g->log_number_incremented == false)
+ {
+ g->CurrentLogNumber++;
+ g->log_number_incremented = true;
+ }
+ }
+ else
+ {
+ if (FileWrite(io, b->Buf, b->Size) == false)
+ {
+ FileCloseEx(io, true);
+ // If it fails to write to the file,
+ // erase the buffer and give up
+ ClearBuf(b);
+ io = NULL;
+ }
+ else
+ {
+ g->CurrentFilePointer += (UINT64)b->Size;
+ ClearBuf(b);
+ }
+ }
+ }
+ }
+
+ Set(g->FlushEvent);
+ break;
+ }
+
+ // Generate a log file name
+ LockLog(g);
+ {
+ log_date_changed = MakeLogFileName(g, file_name, sizeof(file_name),
+ g->DirName, g->Prefix, rec->Tick, g->SwitchType, g->CurrentLogNumber, current_logfile_datename);
+
+ if (log_date_changed)
+ {
+ UINT i;
+
+ g->CurrentLogNumber = 0;
+ MakeLogFileName(g, file_name, sizeof(file_name),
+ g->DirName, g->Prefix, rec->Tick, g->SwitchType, 0, current_logfile_datename);
+ for (i = 0;;i++)
+ {
+ char tmp[MAX_SIZE];
+ MakeLogFileName(g, tmp, sizeof(tmp),
+ g->DirName, g->Prefix, rec->Tick, g->SwitchType, i, current_logfile_datename);
+
+ if (IsFileExists(tmp) == false)
+ {
+ break;
+ }
+ StrCpy(file_name, sizeof(file_name), tmp);
+ g->CurrentLogNumber = i;
+ }
+ }
+ }
+ UnlockLog(g);
+
+ if (io != NULL)
+ {
+ if (StrCmp(current_file_name, file_name) != 0)
+ {
+ // If a log file is currently opened and writing to another log
+ // file is needed for this time, write the contents of the
+ //buffer and close the log file. Write the contents of the buffer
+ if (io != NULL)
+ {
+ if (log_date_changed)
+ {
+ if ((g->CurrentFilePointer + (UINT64)b->Size) <= g->MaxLogFileSize)
+ {
+ if (FileWrite(io, b->Buf, b->Size) == false)
+ {
+ FileCloseEx(io, true);
+ ClearBuf(b);
+ io = NULL;
+ }
+ else
+ {
+ g->CurrentFilePointer += (UINT64)b->Size;
+ ClearBuf(b);
+ }
+ }
+ }
+ // Close the file
+ FileCloseEx(io, true);
+ }
+
+ g->log_number_incremented = false;
+
+ // Open or create a new log file
+ StrCpy(current_file_name, sizeof(current_file_name), file_name);
+ io = FileOpen(file_name, true);
+ if (io == NULL)
+ {
+ // Create a log file
+ LockLog(g);
+ {
+ MakeDir(g->DirName);
+
+#ifdef OS_WIN32
+ Win32SetFolderCompress(g->DirName, true);
+#endif // OS_WIN32
+ }
+ UnlockLog(g);
+ io = FileCreate(file_name);
+ g->CurrentFilePointer = 0;
+ }
+ else
+ {
+ // Seek to the end of the log file
+ g->CurrentFilePointer = FileSize64(io);
+ FileSeek(io, SEEK_END, 0);
+ }
+ }
+ }
+ else
+ {
+ // Open or create a new log file
+ StrCpy(current_file_name, sizeof(current_file_name), file_name);
+ io = FileOpen(file_name, true);
+ if (io == NULL)
+ {
+ // Create a log file
+ LockLog(g);
+ {
+ MakeDir(g->DirName);
+#ifdef OS_WIN32
+ Win32SetFolderCompress(g->DirName, true);
+#endif // OS_WIN32
+ }
+ UnlockLog(g);
+ io = FileCreate(file_name);
+ g->CurrentFilePointer = 0;
+ if (io == NULL)
+ {
+ //Debug("Logging.c: SleepThread(30);\n");
+ SleepThread(30);
+ }
+ }
+ else
+ {
+ // Seek to the end of the log file
+ g->CurrentFilePointer = FileSize64(io);
+ FileSeek(io, SEEK_END, 0);
+ }
+
+ g->log_number_incremented = false;
+ }
+
+ // Write the contents of the log to the buffer
+ WriteRecordToBuffer(b, rec);
+
+ // Release the memory of record
+ Free(rec);
+
+ if (io == NULL)
+ {
+ break;
+ }
+ }
+
+ if (g->Halt)
+ {
+ // Break after finishing to save all records
+ // when the stop flag stood
+ UINT num;
+
+ if (flag == false)
+ {
+#ifdef OS_WIN32
+ MsSetThreadPriorityRealtime();
+#endif // OS_WIN32
+ flag = true;
+ }
+
+ LockQueue(g->RecordQueue);
+ {
+ num = g->RecordQueue->num_item;
+ }
+ UnlockQueue(g->RecordQueue);
+
+ if (num == 0 || io == NULL)
+ {
+ break;
+ }
+ }
+ else
+ {
+ Wait(g->Event, 9821);
+ }
+ }
+
+ if (io != NULL)
+ {
+ FileCloseEx(io, true);
+ }
+
+ FreeBuf(b);
+}
+
+// Write the contents of the log to the buffer
+void WriteRecordToBuffer(BUF *b, RECORD *r)
+{
+ UINT64 time;
+ char time_str[MAX_SIZE];
+ char date_str[MAX_SIZE];
+ char *s;
+ // Validate arguments
+ if (b == NULL || r == NULL)
+ {
+ return;
+ }
+
+ // Get the time
+ time = SystemToLocal64(TickToTime(r->Tick));
+
+ // Convert a time to a string
+ GetDateStr64(date_str, sizeof(date_str), time);
+ GetTimeStrMilli64(time_str, sizeof(time_str), time);
+
+ if (r->ParseProc != PacketLogParseProc)
+ {
+ // Other than packet log
+ WriteBuf(b, date_str, StrLen(date_str));
+ WriteBuf(b, " ", 1);
+ WriteBuf(b, time_str, StrLen(time_str));
+ WriteBuf(b, " ", 1);
+ }
+ else
+ {
+ // Packet log
+ WriteBuf(b, date_str, StrLen(date_str));
+ WriteBuf(b, ",", 1);
+ WriteBuf(b, time_str, StrLen(time_str));
+ WriteBuf(b, ",", 1);
+ }
+
+ // Output text
+ s = r->ParseProc(r);
+ WriteBuf(b, s, StrLen(s));
+ Free(s);
+
+ WriteBuf(b, "\r\n", 2);
+}
+
+// End of logging
+void FreeLog(LOG *g)
+{
+ RECORD *rec;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ // Halting flag
+ g->Halt = true;
+ Set(g->Event);
+
+ WaitThread(g->Thread, INFINITE);
+ ReleaseThread(g->Thread);
+
+ DeleteLock(g->lock);
+ Free(g->DirName);
+ Free(g->Prefix);
+
+ // Release the unprocessed record if it remains
+ // (It should not remain here)
+ while (rec = GetNext(g->RecordQueue))
+ {
+ char *s = rec->ParseProc(rec);
+ Free(s);
+ Free(rec);
+ }
+ ReleaseQueue(g->RecordQueue);
+
+ ReleaseEvent(g->Event);
+ ReleaseEvent(g->FlushEvent);
+
+ Free(g);
+}
+
+// Start a new logging
+LOG *NewLog(char *dir, char *prefix, UINT switch_type)
+{
+ LOG *g;
+
+ g = ZeroMalloc(sizeof(LOG));
+ g->lock = NewLock();
+ g->DirName = CopyStr(dir == NULL ? "" : dir);
+ g->Prefix = CopyStr(prefix == NULL ? "log" : prefix);
+ g->SwitchType = switch_type;
+ g->RecordQueue = NewQueue();
+ g->Event = NewEvent();
+ g->MaxLogFileSize = MAX_LOG_SIZE;
+ g->FlushEvent = NewEvent();
+
+ g->Thread = NewThread(LogThread, g);
+
+ WaitThreadInit(g->Thread);
+
+ return g;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Logging.h b/src/Cedar/Logging.h
new file mode 100644
index 00000000..cffec6fe
--- /dev/null
+++ b/src/Cedar/Logging.h
@@ -0,0 +1,248 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Logging.h
+// Header of Logging.c
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+
+// Port number for HTTP monitoring
+#define LOG_HTTP_PORT 80
+
+
+#define MAX_LOG_SIZE 1073741823ULL
+
+typedef char *(RECORD_PARSE_PROC)(RECORD *rec);
+
+// Packet log structure
+struct PACKET_LOG
+{
+ CEDAR *Cedar;
+ struct PKT *Packet;
+ char *SrcSessionName;
+ char *DestSessionName;
+ bool PurePacket; // Packet not cloned
+ bool PurePacketNoPayload; // Packet not cloned (without payload)
+ SESSION *SrcSession;
+ bool NoLog; // Not to write a log
+};
+
+// Log save options of the HUB
+struct HUB_LOG
+{
+ bool SaveSecurityLog; // To save the security log
+ UINT SecurityLogSwitchType; // Switching type of security log
+ bool SavePacketLog; // To save the packet log
+ UINT PacketLogSwitchType; // Switching type of packet log
+ UINT PacketLogConfig[NUM_PACKET_LOG]; // Packet log settings
+};
+
+// Record
+struct RECORD
+{
+ UINT64 Tick; // Time
+ RECORD_PARSE_PROC *ParseProc; // Parsing procedure
+ void *Data; // Data
+};
+
+// LOG object
+struct LOG
+{
+ LOCK *lock; // Lock
+ THREAD *Thread; // Thread
+ char *DirName; // Destination directory name
+ char *Prefix; // File name
+ UINT SwitchType; // Switching type of log file
+ QUEUE *RecordQueue; // Record queue
+ volatile bool Halt; // Halting flag
+ EVENT *Event; // Event for Log
+ EVENT *FlushEvent; // Flash completion event
+ bool CacheFlag;
+ UINT64 LastTick;
+ UINT LastSwitchType;
+ char LastStr[MAX_SIZE];
+ UINT64 CurrentFilePointer; // The current file pointer
+ UINT64 MaxLogFileSize; // Maximum log file size
+ UINT CurrentLogNumber; // Log file number of the current
+ bool log_number_incremented;
+};
+
+
+// ERASER object
+struct ERASER
+{
+ LOG *Log; // Logger
+ UINT64 MinFreeSpace; // Disk space to start deleting files
+ char *DirName; // Directory name
+ volatile bool Halt; // Halting flag
+ THREAD *Thread; // Thread
+ bool LastFailed; // Whether deletion of the file failed at the end
+ EVENT *HaltEvent; // Halting event
+};
+
+// List of files that can be deleted
+typedef struct ERASE_FILE
+{
+ char *FullPath; // Full path
+ UINT64 UpdateTime; // Updating date
+} ERASE_FILE;
+
+// SYSLOG object
+struct SLOG
+{
+ LOCK *lock; // Lock
+ SOCK *Udp; // UDP socket
+ IP DestIp; // Destination IP address
+ UINT DestPort; // Destination port number
+ char HostName[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT64 NextPollIp; // Time of examination of the IP address at the end
+};
+
+// Function prototype
+LOG *NewLog(char *dir, char *prefix, UINT switch_type);
+void FreeLog(LOG *g);
+void LogThread(THREAD *thread, void *param);
+void WaitLogFlush(LOG *g);
+void LockLog(LOG *g);
+void UnlockLog(LOG *g);
+void InsertRecord(LOG *g, void *data, RECORD_PARSE_PROC *proc);
+void InsertStringRecord(LOG *g, char *str);
+void InsertUnicodeRecord(LOG *g, wchar_t *unistr);
+char *StringRecordParseProc(RECORD *rec);
+bool MakeLogFileName(LOG *g, char *name, UINT size, char *dir, char *prefix, UINT64 tick, UINT switch_type, UINT num, char *old_datestr);
+void MakeLogFileNameStringFromTick(LOG *g, char *str, UINT size, UINT64 tick, UINT switch_type);
+void WriteRecordToBuffer(BUF *b, RECORD *r);
+void SetLogDirName(LOG *g, char *dir);
+void SetLogPrefix(LOG *g, char *prefix);
+void SetLogSwitchType(LOG *g, UINT switch_type);
+bool PacketLog(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *packet, UINT64 now);
+char *PacketLogParseProc(RECORD *rec);
+UINT CalcPacketLoggingLevel(HUB *hub, PKT *packet);
+UINT CalcPacketLoggingLevelEx(HUB_LOG *g, PKT *packet);
+char *GenCsvLine(TOKEN_LIST *t);
+void ReplaceForCsv(char *str);
+char *PortStr(CEDAR *cedar, UINT port, bool udp);
+char *TcpFlagStr(UCHAR flag);
+void WriteSecurityLog(HUB *h, char *str);
+void SecLog(HUB *h, char *fmt, ...);
+void SiSetDefaultLogSetting(HUB_LOG *g);
+void DebugLog(CEDAR *c, char *fmt, ...);
+void HubLog(HUB *h, wchar_t *fmt, ...);
+void ServerLog(CEDAR *c, wchar_t *fmt, ...);
+void SLog(CEDAR *c, char *name, ...);
+void WriteHubLog(HUB *h, wchar_t *str);
+void HLog(HUB *h, char *name, ...);
+void NLog(VH *v, char *name, ...);
+void IPCLog(IPC *ipc, char *name, ...);
+void PPPLog(PPP_SESSION *p, char *name, ...);
+void IPsecLog(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, IPSECSA *ipsec_sa, char *name, ...);
+void EtherIPLog(ETHERIP_SERVER *s, char *name, ...);
+void WriteServerLog(CEDAR *c, wchar_t *str);
+void ALog(ADMIN *a, HUB *h, char *name, ...);
+void CLog(CLIENT *c, char *name, ...);
+void WriteClientLog(CLIENT *c, wchar_t *str);
+ERASER *NewEraser(LOG *log, UINT64 min_size);
+void FreeEraser(ERASER *e);
+void ELog(ERASER *e, char *name, ...);
+void EraserThread(THREAD *t, void *p);
+void EraserMain(ERASER *e);
+bool CheckEraserDiskFreeSpace(ERASER *e);
+int CompareEraseFile(void *p1, void *p2);
+LIST *GenerateEraseFileList(ERASER *e);
+void FreeEraseFileList(LIST *o);
+void PrintEraseFileList(LIST *o);
+void EnumEraseFile(LIST *o, char *dirname);
+SLOG *NewSysLog(char *hostname, UINT port);
+void SetSysLog(SLOG *g, char *hostname, UINT port);
+void FreeSysLog(SLOG *g);
+void SendSysLog(SLOG *g, wchar_t *str);
+void WriteMultiLineLog(LOG *g, BUF *b);
+char *BuildHttpLogStr(HTTPLOG *h);
+void MakeSafeLogStr(char *str);
+void AddLogBufToStr(BUF *b, char *name, char *value);
+
+#endif // LOGGING_G
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NM.c b/src/Cedar/NM.c
new file mode 100644
index 00000000..74bb88fd
--- /dev/null
+++ b/src/Cedar/NM.c
@@ -0,0 +1,1516 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NM.c
+// VPN User-mode Router Manager for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define SM_C
+#define CM_C
+#define NM_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "CMInner.h"
+#include "SMInner.h"
+#include "NMInner.h"
+#include "EMInner.h"
+#include "../PenCore/resource.h"
+
+// Global variable
+static NM *nm = NULL;
+
+
+// Change Password dialog
+UINT NmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ RPC *r = (RPC *)param;
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ RPC_SET_PASSWORD t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, 0, r->Sock->RemoteHostname);
+ FormatText(hWnd, S_TITLE, r->Sock->RemoteHostname);
+ break;
+
+ case WM_COMMAND:
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+ switch (LOWORD(wParam))
+ {
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ SetEnable(hWnd, IDOK, StrCmp(tmp1, tmp2) == 0);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ Zero(&t, sizeof(t));
+ Hash(t.HashedPassword, tmp1, StrLen(tmp1), true);
+
+ if (CALL(hWnd, NcSetPassword(r, &t)))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("NM_PASSWORD_MSG"));
+ EndDialog(hWnd, true);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Change the password
+void NmChangePassword(HWND hWnd, RPC *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_NM_CHANGE_PASSWORD, NmChangePasswordProc, r);
+}
+
+// DHCP enumeration initialization
+void NmDhcpInit(HWND hWnd, SM_HUB *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_INTERNET);
+
+ LvInit(hWnd, L_TABLE);
+ LvInsertColumn(hWnd, L_TABLE, 0, _UU("DHCP_DHCP_ID"), 50);
+ LvInsertColumn(hWnd, L_TABLE, 1, _UU("DHCP_LEASED_TIME"), 200);
+ LvInsertColumn(hWnd, L_TABLE, 2, _UU("DHCP_EXPIRE_TIME"), 200);
+ LvInsertColumn(hWnd, L_TABLE, 3, _UU("DHCP_MAC_ADDRESS"), 130);
+ LvInsertColumn(hWnd, L_TABLE, 4, _UU("DHCP_IP_ADDRESS"), 100);
+ LvInsertColumn(hWnd, L_TABLE, 5, _UU("DHCP_HOSTNAME"), 150);
+
+ NmDhcpRefresh(hWnd, r);
+}
+
+// DHCP enumeration
+void NmDhcpRefresh(HWND hWnd, SM_HUB *r)
+{
+ LVB *b;
+ RPC_ENUM_DHCP t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), r->HubName);
+
+ if (CALL(hWnd, ScEnumDHCP(r->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_DHCP_ITEM *e = &t.Items[i];
+ wchar_t tmp0[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ char str[MAX_SIZE];
+
+ // ID
+ UniToStru(tmp0, e->Id);
+
+ // Time
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->LeasedTime), NULL);
+ GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(e->ExpireTime), NULL);
+
+ MacToStr(str, sizeof(str), e->MacAddress);
+ StrToUni(tmp3, sizeof(tmp3), str);
+
+ IPToStr32(str, sizeof(str), e->IpAddress);
+ StrToUni(tmp4, sizeof(tmp4), str);
+
+ StrToUni(tmp5, sizeof(tmp5), e->Hostname);
+
+ LvInsertAdd(b, ICO_INTERNET, NULL, 6,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+
+ LvInsertEnd(b, hWnd, L_TABLE);
+
+ FreeRpcEnumDhcp(&t);
+}
+
+// DHCP enumeration procedure
+UINT NmDhcpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *r = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ NmDhcpInit(hWnd, r);
+ SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_REFRESH:
+ NmDhcpRefresh(hWnd, r);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ NmDhcpRefresh(hWnd, r);
+ SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);
+
+ return 0;
+}
+
+// DHCP enumeration
+void NmDhcp(HWND hWnd, SM_HUB *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_NM_DHCP, NmDhcpProc, r);
+}
+
+
+// NAT enumeration initialization
+void NmNatInit(HWND hWnd, SM_HUB *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_PROTOCOL);
+
+ LvInit(hWnd, L_TABLE);
+ LvInsertColumn(hWnd, L_TABLE, 0, _UU("NM_NAT_ID"), 50);
+ LvInsertColumn(hWnd, L_TABLE, 1, _UU("NM_NAT_PROTOCOL"), 80);
+ LvInsertColumn(hWnd, L_TABLE, 2, _UU("NM_NAT_SRC_HOST"), 100);
+ LvInsertColumn(hWnd, L_TABLE, 3, _UU("NM_NAT_SRC_PORT"), 80);
+ LvInsertColumn(hWnd, L_TABLE, 4, _UU("NM_NAT_DST_HOST"), 150);
+ LvInsertColumn(hWnd, L_TABLE, 5, _UU("NM_NAT_DST_PORT"), 80);
+ LvInsertColumn(hWnd, L_TABLE, 6, _UU("NM_NAT_CREATED"), 200);
+ LvInsertColumn(hWnd, L_TABLE, 7, _UU("NM_NAT_LAST_COMM"), 200);
+ LvInsertColumn(hWnd, L_TABLE, 8, _UU("NM_NAT_SIZE"), 120);
+ LvInsertColumn(hWnd, L_TABLE, 9, _UU("NM_NAT_TCP_STATUS"), 120);
+
+ NmNatRefresh(hWnd, r);
+}
+
+// NAT enumeration
+void NmNatRefresh(HWND hWnd, SM_HUB *r)
+{
+ LVB *b;
+ RPC_ENUM_NAT t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), r->HubName);
+
+ if (CALL(hWnd, ScEnumNAT(r->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_NAT_ITEM *e = &t.Items[i];
+ wchar_t tmp0[MAX_SIZE];
+ wchar_t *tmp1 = L"";
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+ wchar_t tmp7[MAX_SIZE];
+ wchar_t tmp8[MAX_SIZE];
+ wchar_t *tmp9 = L"";
+ char v1[128], v2[128];
+
+ // ID
+ UniToStru(tmp0, e->Id);
+
+ // Protocol
+ switch (e->Protocol)
+ {
+ case NAT_TCP:
+ tmp1 = _UU("NM_NAT_PROTO_TCP");
+ break;
+ case NAT_UDP:
+ tmp1 = _UU("NM_NAT_PROTO_UDP");
+ break;
+ case NAT_DNS:
+ tmp1 = _UU("NM_NAT_PROTO_DNS");
+ break;
+ case NAT_ICMP:
+ tmp1 = _UU("NM_NAT_PROTO_ICMP");
+ break;
+ }
+
+ // Source host
+ StrToUni(tmp2, sizeof(tmp2), e->SrcHost);
+
+ // Source port
+ UniToStru(tmp3, e->SrcPort);
+
+ // Destination host
+ StrToUni(tmp4, sizeof(tmp4), e->DestHost);
+
+ // Destination port
+ UniToStru(tmp5, e->DestPort);
+
+ // Creation date and time of the session
+ GetDateTimeStrEx64(tmp6, sizeof(tmp6), SystemToLocal64(e->CreatedTime), NULL);
+
+ // Last communication date and time
+ GetDateTimeStrEx64(tmp7, sizeof(tmp7), SystemToLocal64(e->LastCommTime), NULL);
+
+ // Communication amount
+ ToStr3(v1, sizeof(v1), e->RecvSize);
+ ToStr3(v2, sizeof(v2), e->SendSize);
+ UniFormat(tmp8, sizeof(tmp8), L"%S / %S", v1, v2);
+
+ // TCP state
+ if (e->Protocol == NAT_TCP)
+ {
+ switch (e->TcpStatus)
+ {
+ case NAT_TCP_CONNECTING:
+ tmp9 = _UU("NAT_TCP_CONNECTING");
+ break;
+ case NAT_TCP_SEND_RESET:
+ tmp9 = _UU("NAT_TCP_SEND_RESET");
+ break;
+ case NAT_TCP_CONNECTED:
+ tmp9 = _UU("NAT_TCP_CONNECTED");
+ break;
+ case NAT_TCP_ESTABLISHED:
+ tmp9 = _UU("NAT_TCP_ESTABLISHED");
+ break;
+ case NAT_TCP_WAIT_DISCONNECT:
+ tmp9 = _UU("NAT_TCP_WAIT_DISCONNECT");
+ break;
+ }
+ }
+
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 10,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);
+ }
+
+ LvInsertEnd(b, hWnd, L_TABLE);
+
+ FreeRpcEnumNat(&t);
+}
+
+// NAT enumeration procedure
+UINT NmNatProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *r = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ NmNatInit(hWnd, r);
+ SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_REFRESH:
+ NmNatRefresh(hWnd, r);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ NmNatRefresh(hWnd, r);
+ SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);
+
+ return 0;
+}
+
+// NAT enumeration
+void NmNat(HWND hWnd, SM_HUB *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_NM_NAT, NmNatProc, r);
+}
+
+// Show the information of the router
+bool NmInfo(HWND hWnd, SM_SERVER *s, void *param)
+{
+ LVB *b;
+ RPC_NAT_INFO t;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, NcGetInfo(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ StrToUni(tmp, sizeof(tmp), t.NatProductName);
+ LvInsertAdd(b, ICO_ROUTER, NULL, 2, _UU("NM_INFO_PRODUCT_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.NatVersionString);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_VERSION_STR"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.NatBuildInfoString);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_BUILD_INFO"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.NatHostName);
+ LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("NM_INFO_HOSTNAME"), tmp);
+
+ // OS
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SYSTEM_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_PRODUCT_NAME"), tmp);
+
+ if (t.OsInfo.OsServicePack != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SERVICE_PACK"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VENDER_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VERSION"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_VERSION"), tmp);
+
+ // Memory information
+ if (t.MemInfo.TotalMemory != 0)
+ {
+ char vv[128];
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_PHYS"), tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcNatInfo(&t);
+
+ return true;
+}
+
+// Show the status of the router
+bool NmStatus(HWND hWnd, SM_SERVER *s, void *param)
+{
+ LVB *b;
+ RPC_NAT_STATUS t;
+ wchar_t tmp[MAX_SIZE];
+ SM_HUB *h = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), h->HubName);
+
+ if (CALL(hWnd, ScGetSecureNATStatus(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ StrToUni(tmp, sizeof(tmp), h->HubName);
+ LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_HUB_COLUMN_1"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumTcpSessions);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_TCP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumUdpSessions);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_UDP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumIcmpSessions);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_ICMP"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumDnsSessions);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_DNS"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_CLIENT"), t.NumDhcpClients);
+ LvInsertAdd(b, ICO_PROTOCOL_DHCP, NULL, 2, _UU("NM_STATUS_DHCP"), tmp);
+
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_SNAT_IS_KERNEL"), t.IsKernelMode ? _UU("SEC_YES") : _UU("SEC_NO"));
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcNatStatus(&t);
+
+ return true;
+}
+
+// Convert the contents of the form to the VH_OPTION
+void NmEditVhOptionFormToVH(HWND hWnd, VH_OPTION *t)
+{
+ char tmp[MAX_SIZE];
+ BUF *b;
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(VH_OPTION));
+
+ GetTxtA(hWnd, E_MAC, tmp, sizeof(tmp));
+ b = StrToBin(tmp);
+ if (b != NULL)
+ {
+ if (b->Size == 6)
+ {
+ Copy(t->MacAddress, b->Buf, 6);
+ }
+ FreeBuf(b);
+ }
+
+ UINTToIP(&t->Ip, IpGet(hWnd, E_IP));
+ UINTToIP(&t->Mask, IpGet(hWnd, E_MASK));
+
+ t->UseNat = IsChecked(hWnd, R_USE_NAT);
+ t->Mtu = GetInt(hWnd, E_MTU);
+ t->NatTcpTimeout = GetInt(hWnd, E_TCP);
+ t->NatUdpTimeout = GetInt(hWnd, E_UDP);
+
+ t->UseDhcp = IsChecked(hWnd, R_USE_DHCP);
+ UINTToIP(&t->DhcpLeaseIPStart, IpGet(hWnd, E_DHCP_START));
+ UINTToIP(&t->DhcpLeaseIPEnd, IpGet(hWnd, E_DHCP_END));
+ UINTToIP(&t->DhcpSubnetMask, IpGet(hWnd, E_DHCP_MASK));
+ t->DhcpExpireTimeSpan = GetInt(hWnd, E_EXPIRES);
+ UINTToIP(&t->DhcpGatewayAddress, IpGet(hWnd, E_GATEWAY));
+ UINTToIP(&t->DhcpDnsServerAddress, IpGet(hWnd, E_DNS));
+ UINTToIP(&t->DhcpDnsServerAddress2, IpGet(hWnd, E_DNS2));
+ GetTxtA(hWnd, E_DOMAIN, t->DhcpDomainName, sizeof(t->DhcpDomainName));
+ t->SaveLog = IsChecked(hWnd, R_SAVE_LOG);
+}
+
+// Initialize
+void NmEditVhOptionInit(HWND hWnd, SM_HUB *r)
+{
+ char tmp[MAX_SIZE];
+ VH_OPTION t;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ FormatText(hWnd, S_TITLE, r->HubName);
+
+ Zero(&t, sizeof(VH_OPTION));
+ StrCpy(t.HubName, sizeof(t.HubName), r->HubName);
+ if (CALL(hWnd, ScGetSecureNATOption(r->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ if (GetCapsBool(r->p->CapsList, "b_virtual_nat_disabled"))
+ {
+ SetEnable(hWnd, R_USE_NAT, false);
+ Check(hWnd, R_USE_NAT, false);
+ }
+
+ MacToStr(tmp, sizeof(tmp), t.MacAddress);
+ SetTextA(hWnd, E_MAC, tmp);
+ IpSet(hWnd, E_IP, IPToUINT(&t.Ip));
+ IpSet(hWnd, E_MASK, IPToUINT(&t.Mask));
+
+ Check(hWnd, R_USE_NAT, t.UseNat);
+ SetIntEx(hWnd, E_MTU, t.Mtu);
+ SetIntEx(hWnd, E_TCP, t.NatTcpTimeout);
+ SetIntEx(hWnd, E_UDP, t.NatUdpTimeout);
+
+ Check(hWnd, R_USE_DHCP, t.UseDhcp);
+ IpSet(hWnd, E_DHCP_START, IPToUINT(&t.DhcpLeaseIPStart));
+ IpSet(hWnd, E_DHCP_END, IPToUINT(&t.DhcpLeaseIPEnd));
+ IpSet(hWnd, E_DHCP_MASK, IPToUINT(&t.DhcpSubnetMask));
+ SetIntEx(hWnd, E_EXPIRES, t.DhcpExpireTimeSpan);
+
+ if (IPToUINT(&t.DhcpGatewayAddress) != 0)
+ {
+ IpSet(hWnd, E_GATEWAY, IPToUINT(&t.DhcpGatewayAddress));
+ }
+
+ if (IPToUINT(&t.DhcpDnsServerAddress) != 0)
+ {
+ IpSet(hWnd, E_DNS, IPToUINT(&t.DhcpDnsServerAddress));
+ }
+
+ if (IPToUINT(&t.DhcpDnsServerAddress2) != 0)
+ {
+ IpSet(hWnd, E_DNS2, IPToUINT(&t.DhcpDnsServerAddress2));
+ }
+
+ SetTextA(hWnd, E_DOMAIN, t.DhcpDomainName);
+ Check(hWnd, R_SAVE_LOG, t.SaveLog);
+
+ NmEditVhOptionUpdate(hWnd, r);
+
+}
+
+void NmEditVhOptionUpdate(HWND hWnd, SM_HUB *r)
+{
+ VH_OPTION t;
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ NmEditVhOptionFormToVH(hWnd, &t);
+
+ if (IsZero(t.MacAddress, 6))
+ {
+ ok = false;
+ }
+
+ if (IPToUINT(&t.Ip) == 0 || IPToUINT(&t.Mask) == 0)
+ {
+ ok = false;
+ }
+
+ if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)
+ {
+ ok = false;
+ }
+
+ if (IsHostIPAddress4(&t.Ip) == false || IsSubnetMask4(&t.Mask) == false)
+ {
+ ok = false;
+ }
+
+ if (t.UseNat)
+ {
+ if (t.Mtu < 64 || t.Mtu > 1500)
+ {
+ ok = false;
+ }
+
+ if (t.NatTcpTimeout < (NAT_TCP_MIN_TIMEOUT / 1000) || t.NatTcpTimeout > (NAT_TCP_MAX_TIMEOUT / 1000))
+ {
+ ok = false;
+ }
+
+ if (t.NatUdpTimeout < (NAT_UDP_MIN_TIMEOUT / 1000) || t.NatUdpTimeout > (NAT_UDP_MAX_TIMEOUT / 1000))
+ {
+ ok = false;
+ }
+ }
+
+ if (t.UseDhcp)
+ {
+ if (IpIsFilled(hWnd, E_DHCP_START) == false || IpIsFilled(hWnd, E_DHCP_END) == false ||
+ IpIsFilled(hWnd, E_DHCP_MASK) == false)
+ {
+ ok = false;
+ }
+
+ if (IpGetFilledNum(hWnd, E_GATEWAY) != 0 && IpGetFilledNum(hWnd, E_GATEWAY) != 4)
+ {
+ ok = false;
+ }
+
+ if (IpGetFilledNum(hWnd, E_DNS) != 0 && IpGetFilledNum(hWnd, E_DNS) != 4)
+ {
+ ok = false;
+ }
+
+ if (IpGetFilledNum(hWnd, E_DNS2) != 0 && IpGetFilledNum(hWnd, E_DNS2) != 4)
+ {
+ ok = false;
+ }
+
+ if (IPToUINT(&t.DhcpLeaseIPStart) == 0 || IPToUINT(&t.DhcpLeaseIPEnd) == 0 ||
+ IPToUINT(&t.DhcpSubnetMask) == 0)
+ {
+ ok = false;
+ }
+
+ if (t.DhcpExpireTimeSpan < 15)
+ {
+ ok = false;
+ }
+
+ if (Endian32(IPToUINT(&t.DhcpLeaseIPStart)) > Endian32(IPToUINT(&t.DhcpLeaseIPEnd)))
+ {
+ ok = false;
+ }
+
+ if (IsHostIPAddress4(&t.DhcpLeaseIPStart) == false ||
+ IsHostIPAddress4(&t.DhcpLeaseIPEnd) == false)
+ {
+ ok = false;
+ }
+
+ if (IsSubnetMask4(&t.DhcpSubnetMask) == false)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, E_MTU, t.UseNat);
+ SetEnable(hWnd, E_TCP, t.UseNat);
+ SetEnable(hWnd, E_UDP, t.UseNat);
+
+ SetEnable(hWnd, E_DHCP_START, t.UseDhcp);
+ SetEnable(hWnd, E_DHCP_END, t.UseDhcp);
+ SetEnable(hWnd, E_DHCP_MASK, t.UseDhcp);
+ SetEnable(hWnd, E_EXPIRES, t.UseDhcp);
+ SetEnable(hWnd, E_GATEWAY, t.UseDhcp);
+ SetEnable(hWnd, E_DNS, t.UseDhcp);
+ SetEnable(hWnd, E_DNS2, t.UseDhcp);
+ SetEnable(hWnd, E_DOMAIN, t.UseDhcp);
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// [OK] button
+void NmEditVhOptionOnOk(HWND hWnd, SM_HUB *r)
+{
+ VH_OPTION t;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ NmEditVhOptionFormToVH(hWnd, &t);
+ StrCpy(t.HubName, sizeof(t.HubName), r->HubName);
+
+ if (CALL(hWnd, ScSetSecureNATOption(r->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+}
+
+// Virtual host options editing dialog
+UINT NmEditVhOptionProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *r = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ NmEditVhOptionInit(hWnd, r);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_MAC:
+ case E_IP:
+ case E_MASK:
+ case R_USE_NAT:
+ case E_MTU:
+ case E_TCP:
+ case E_UDP:
+ case R_SAVE_LOG:
+ case R_USE_DHCP:
+ case E_DHCP_START:
+ case E_DHCP_END:
+ case E_DHCP_MASK:
+ case E_EXPIRES:
+ case E_GATEWAY:
+ case E_DNS:
+ case E_DNS2:
+ case E_DOMAIN:
+ NmEditVhOptionUpdate(hWnd, r);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ NmEditVhOptionOnOk(hWnd, r);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hWnd, false);
+ break;
+
+ case R_USE_NAT:
+ if (IsChecked(hWnd, R_USE_NAT))
+ {
+ FocusEx(hWnd, E_MTU);
+ }
+
+ if (IsChecked(hWnd, R_USE_DHCP))
+ {
+ Focus(hWnd, E_DHCP_START);
+ }
+ break;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+// Edit the virtual host option
+void NmEditVhOption(HWND hWnd, SM_HUB *r)
+{
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_NM_OPTION, NmEditVhOptionProc, r);
+}
+
+// Edit the client configuration
+void NmEditClientConfig(HWND hWnd, RPC *r)
+{
+ CM_ACCOUNT a;
+ RPC_CREATE_LINK t;
+ bool ret = false;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+ Zero(&t, sizeof(t));
+
+ a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ a.NatMode = true;
+ a.Rpc = r;
+
+ if (CALLEX(hWnd, NcGetClientConfig(r, &t)) != ERR_NO_ERROR)
+ {
+ // Create New
+ a.ClientOption->Port = 443;
+ a.ClientOption->RetryInterval = 15;
+ a.ClientOption->NumRetry = INFINITE;
+ a.ClientOption->AdditionalConnectionInterval = 1;
+ a.ClientOption->UseEncrypt = true;
+ a.ClientOption->NoRoutingTracking = true;
+ a.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+ a.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
+ }
+ else
+ {
+ // Edit
+ a.EditMode = true;
+ Copy(a.ClientOption, t.ClientOption, sizeof(CLIENT_OPTION));
+ a.ClientAuth = CopyClientAuth(t.ClientAuth);
+
+ FreeRpcCreateLink(&t);
+ }
+
+ ret = CmEditAccountDlg(hWnd, &a);
+
+ Free(a.ServerCert);
+ Free(a.ClientOption);
+ CiFreeClientAuth(a.ClientAuth);
+}
+
+// Initialize
+void NmMainDlgInit(HWND hWnd, RPC *r)
+{
+ // Validate arguments
+ if (r == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_ROUTER);
+ FormatText(hWnd, 0, r->Sock->RemoteHostname);
+ DlgFont(hWnd, S_STATUS, 11, true);
+
+ NmMainDlgRefresh(hWnd, r);
+}
+
+// Update
+void NmMainDlgRefresh(HWND hWnd, RPC *r)
+{
+#if 0
+ RPC_NAT_STATUS t;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (r == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(RPC_NAT_STATUS));
+
+ CALL(hWnd, NcGetStatus(r, &t));
+
+ if (t.Online == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("NM_OFFLINE"));
+
+ Enable(hWnd, B_CONNECT);
+ Disable(hWnd, B_DISCONNECT);
+ }
+ else
+ {
+ if (t.Connected)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECTED"), t.Status.ServerName);
+ }
+ else
+ {
+ if (t.LastError == ERR_NO_ERROR)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("NM_CONNECTING"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECT_ERROR"), t.LastError, _E(t.LastError));
+ }
+ }
+ Disable(hWnd, B_CONNECT);
+ Enable(hWnd, B_DISCONNECT);
+ }
+
+ UniFormat(tmp2, sizeof(tmp2), _UU("NM_STATUS_TAG"), tmp);
+
+ SetText(hWnd, S_STATUS, tmp2);
+
+ FreeRpcNatStatus(&t);
+#endif
+}
+
+// Main dialog procedure
+UINT NmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+#if 0
+ SM_HUB *r = (SM_HUB *)param;
+ RPC_DUMMY dummy;
+ SM_SERVER sm;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ NmMainDlgInit(hWnd, r);
+
+ SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL);
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_SETTING:
+ // Connection setting
+ NmEditClientConfig(hWnd, r);
+ break;
+
+ case B_CONNECT:
+ // Connection
+ Zero(&dummy, sizeof(dummy));
+ CALL(hWnd, NcOnline(r, &dummy));
+ NmMainDlgRefresh(hWnd, r);
+ break;
+
+ case B_DISCONNECT:
+ // Disconnect
+ Zero(&dummy, sizeof(dummy));
+ CALL(hWnd, NcOffline(r, &dummy));
+ NmMainDlgRefresh(hWnd, r);
+ break;
+
+ case B_OPTION:
+ // Operation setting
+ NmEditVhOption(hWnd, r->Rpc);
+ break;
+
+ case B_NAT:
+ // NAT
+ NmNat(hWnd, r);
+ break;
+
+ case B_DHCP:
+ // DHCP
+ NmDhcp(hWnd, r);
+ break;
+
+ case B_STATUS:
+ // Status
+ Zero(&sm, sizeof(sm));
+ sm.Rpc = r;
+ SmStatusDlg(hWnd, &sm, NULL, true, true, _UU("NM_STATUS"), ICO_ROUTER,
+ NULL, NmStatus);
+ break;
+
+ case B_INFO:
+ // Information
+ Zero(&sm, sizeof(sm));
+ sm.Rpc = r;
+ SmStatusDlg(hWnd, &sm, NULL, false, true, _UU("NM_INFO"), ICO_ROUTER,
+ NULL, NmInfo);
+ break;
+
+ case B_REFRESH:
+ // Refresh
+ NmMainDlgRefresh(hWnd, r);
+ break;
+
+ case B_PASSWORD:
+ // Change the password
+ NmChangePassword(hWnd, r);
+ break;
+
+ case B_ABOUT:
+ // Version information
+ About(hWnd, nm->Cedar, CEDAR_ROUTER_STR);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ if (IsEnable(hWnd, 0))
+ {
+ NmMainDlgRefresh(hWnd, r);
+ }
+
+ SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+#endif
+
+ return 0;
+}
+
+// Main dialog
+void NmMainDlg(RPC *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ Dialog(NULL, D_NM_MAIN, NmMainDlgProc, r);
+}
+
+// Login dialog
+UINT NmLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NM_LOGIN *login = (NM_LOGIN *)param;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, S_TITLE, login->Hostname);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));
+ Hash(login->hashed_password, tmp, StrLen(tmp), true);
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Connecting dialog
+UINT NmConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NM_CONNECT *t = (NM_CONNECT *)param;
+ RPC *rpc;
+ NM_LOGIN login;
+ UINT err;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, S_TITLE, t->Hostname);
+ SetTimer(hWnd, 1, 50, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ while (true)
+ {
+ bool flag = false;
+RETRY_PASSWORD:
+ // Password input dialog
+ Zero(&login, sizeof(login));
+ login.Hostname = t->Hostname;
+ login.Port = t->Port;
+ Hash(login.hashed_password, "", 0, true);
+
+ if (flag)
+ {
+ if (Dialog(hWnd, D_NM_LOGIN, NmLogin, &login) == false)
+ {
+ EndDialog(hWnd, false);
+ break;
+ }
+ }
+
+RETRY_CONNECT:
+ Refresh(DlgItem(hWnd, S_TITLE));
+ Refresh(hWnd);
+ // Connection
+ rpc = NatAdminConnect(nm->Cedar, t->Hostname, t->Port, login.hashed_password, &err);
+ if (rpc != NULL)
+ {
+ t->Rpc = rpc;
+ EndDialog(hWnd, true);
+ break;
+ }
+
+ // Error
+ if (err == ERR_ACCESS_DENIED || err == ERR_AUTH_FAILED)
+ {
+ if (flag)
+ {
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL,
+ _E(err)) == IDCANCEL)
+ {
+ EndDialog(hWnd, false);
+ break;
+ }
+ }
+ flag = true;
+ goto RETRY_PASSWORD;
+ }
+ else
+ {
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL,
+ _E(err)) == IDCANCEL)
+ {
+ EndDialog(hWnd, false);
+ break;
+ }
+ goto RETRY_CONNECT;
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Connect to the User-mode NAT program
+RPC *NmConnect(char *hostname, UINT port)
+{
+ NM_CONNECT t;
+ // Validate arguments
+ if (hostname == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Hostname = hostname;
+ t.Port = port;
+
+ Dialog(NULL, D_NM_CONNECT, NmConnectDlgProc, &t);
+
+ return t.Rpc;
+}
+
+// Main process
+void MainNM()
+{
+ UINT port;
+ char hostname[MAX_HOST_NAME_LEN + 1];
+ char *tmp =
+ RemoteDlg(NULL, NM_SETTING_REG_KEY, ICO_ROUTER,
+ _UU("NM_TITLE"), _UU("NM_CONNECT_TITLE"), NULL);
+ TOKEN_LIST *t;
+
+ Zero(hostname, sizeof(hostname));
+
+ if (tmp == NULL)
+ {
+ return;
+ }
+
+ t = ParseToken(tmp, ":");
+ port = DEFAULT_NAT_ADMIN_PORT;
+
+ if (t->NumTokens >= 2)
+ {
+ UINT i = ToInt(t->Token[1]);
+ if (i != 0)
+ {
+ port = i;
+ }
+ }
+ if (t->NumTokens >= 1)
+ {
+ RPC *rpc;
+ StrCpy(hostname, sizeof(hostname), t->Token[0]);
+
+ // Connection
+ Trim(hostname);
+
+ if (StrLen(hostname) != 0)
+ {
+ rpc = NmConnect(hostname, port);
+ if (rpc != NULL)
+ {
+ // Connected
+ NmMainDlg(rpc);
+ NatAdminDisconnect(rpc);
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ Free(tmp);
+}
+
+// Initialize
+void InitNM()
+{
+ if (nm != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ nm = ZeroMalloc(sizeof(NM));
+
+ InitWinUi(_UU("NM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ nm->Cedar = NewCedar(NULL, NULL);
+
+ InitCM(false);
+ InitSM();
+}
+
+// Release
+void FreeNM()
+{
+ if (nm == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ FreeSM();
+ FreeCM();
+
+ ReleaseCedar(nm->Cedar);
+
+ FreeWinUi();
+
+ Free(nm);
+ nm = NULL;
+}
+
+// Execution of NM
+void NMExec()
+{
+ InitNM();
+ MainNM();
+ FreeNM();
+}
+
+#endif
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NM.h b/src/Cedar/NM.h
new file mode 100644
index 00000000..27039ea6
--- /dev/null
+++ b/src/Cedar/NM.h
@@ -0,0 +1,96 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NM.h
+// Header of NM.c
+
+#ifndef NM_H
+#define NM_H
+
+// External function
+void NMExec();
+
+#endif // NM_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NMInner.h b/src/Cedar/NMInner.h
new file mode 100644
index 00000000..802172dc
--- /dev/null
+++ b/src/Cedar/NMInner.h
@@ -0,0 +1,148 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NMInner.h
+// The internal header of NM.c
+
+
+// Constants
+#define NM_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\User-mode Router Manager"
+#define NM_SETTING_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\User-mode Router Manager\\Settings"
+
+#define NM_REFRESH_TIME 1000
+#define NM_NAT_REFRESH_TIME 1000
+#define NM_DHCP_REFRESH_TIME 1000
+
+// Nat Admin structure
+typedef struct NM
+{
+ CEDAR *Cedar; // Cedar
+} NM;
+
+// Connection structure
+typedef struct NM_CONNECT
+{
+ RPC *Rpc; // RPC
+ char *Hostname;
+ UINT Port;
+} NM_CONNECT;
+
+// Login
+typedef struct NM_LOGIN
+{
+ char *Hostname;
+ UINT Port;
+ UCHAR hashed_password[SHA1_SIZE];
+} NM_LOGIN;
+
+// Internal function
+void InitNM();
+void FreeNM();
+void MainNM();
+RPC *NmConnect(char *hostname, UINT port);
+UINT NmConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+UINT NmLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NmMainDlg(RPC *r);
+UINT NmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NmMainDlgInit(HWND hWnd, RPC *r);
+void NmMainDlgRefresh(HWND hWnd, RPC *r);
+void NmEditClientConfig(HWND hWnd, RPC *r);
+void NmEditVhOption(HWND hWnd, SM_HUB *r);
+UINT NmEditVhOptionProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NmEditVhOptionInit(HWND hWnd, SM_HUB *r);
+void NmEditVhOptionUpdate(HWND hWnd, SM_HUB *r);
+void NmEditVhOptionOnOk(HWND hWnd, SM_HUB *r);
+void NmEditVhOptionFormToVH(HWND hWnd, VH_OPTION *t);
+bool NmStatus(HWND hWnd, SM_SERVER *s, void *param);
+bool NmInfo(HWND hWnd, SM_SERVER *s, void *param);
+void NmNat(HWND hWnd, SM_HUB *r);
+UINT NmNatProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NmNatInit(HWND hWnd, SM_HUB *r);
+void NmNatRefresh(HWND hWnd, SM_HUB *r);
+void NmDhcp(HWND hWnd, SM_HUB *r);
+UINT NmDhcpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NmDhcpRefresh(HWND hWnd, SM_HUB *r);
+void NmDhcpInit(HWND hWnd, SM_HUB *r);
+void NmChangePassword(HWND hWnd, RPC *r);
+UINT NmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Nat.c b/src/Cedar/Nat.c
new file mode 100644
index 00000000..33e6243e
--- /dev/null
+++ b/src/Cedar/Nat.c
@@ -0,0 +1,1876 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Nat.c
+// User-mode Router
+
+#include "CedarPch.h"
+
+static LOCK *nat_lock = NULL;
+static NAT *nat = NULL;
+
+
+// Disconnect the connection for the NAT administrator
+void NatAdminDisconnect(RPC *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ EndRpc(r);
+}
+
+// Connection for NAT administrator
+RPC *NatAdminConnect(CEDAR *cedar, char *hostname, UINT port, void *hashed_password, UINT *err)
+{
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR random[SHA1_SIZE];
+ SOCK *sock;
+ RPC *rpc;
+ PACK *p;
+ UINT error;
+ // Validate arguments
+ if (cedar == NULL || hostname == NULL || port == 0 || hashed_password == NULL || err == NULL)
+ {
+ if (err != NULL)
+ {
+ *err = ERR_INTERNAL_ERROR;
+ }
+ return NULL;
+ }
+
+ // Connection
+ sock = Connect(hostname, port);
+ if (sock == NULL)
+ {
+ *err = ERR_CONNECT_FAILED;
+ return NULL;
+ }
+
+ if (StartSSL(sock, NULL, NULL) == false)
+ {
+ *err = ERR_PROTOCOL_ERROR;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ SetTimeout(sock, 5000);
+
+ p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ *err = ERR_DISCONNECTED;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ if (PackGetData2(p, "auth_random", random, SHA1_SIZE) == false)
+ {
+ FreePack(p);
+ *err = ERR_PROTOCOL_ERROR;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ FreePack(p);
+
+ SecurePassword(secure_password, hashed_password, random);
+
+ p = NewPack();
+ PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
+
+ if (HttpClientSend(sock, p) == false)
+ {
+ FreePack(p);
+ *err = ERR_DISCONNECTED;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ FreePack(p);
+
+ p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ *err = ERR_DISCONNECTED;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ error = GetErrorFromPack(p);
+
+ FreePack(p);
+
+ if (error != ERR_NO_ERROR)
+ {
+ *err = error;
+ ReleaseSock(sock);
+ return NULL;
+ }
+
+ SetTimeout(sock, TIMEOUT_INFINITE);
+
+ rpc = StartRpcClient(sock, NULL);
+ ReleaseSock(sock);
+
+ return rpc;
+}
+
+// RPC functional related macro
+#define DECLARE_RPC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type t; \
+ Zero(&t, sizeof(t)); \
+ in_rpc(&t, p); \
+ err = function(n, &t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, &t); \
+ } \
+ free_rpc(&t); \
+ ok = true; \
+ }
+#define DECLARE_RPC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ else if (StrCmpi(name, rpc_name) == 0) \
+ { \
+ data_type t; \
+ Zero(&t, sizeof(t)); \
+ in_rpc(&t, p); \
+ err = function(n, &t); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ out_rpc(ret, &t); \
+ } \
+ ok = true; \
+ }
+#define DECLARE_SC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ free_rpc(t); \
+ Zero(t, sizeof(data_type)); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+#define DECLARE_SC(rpc_name, data_type, function, in_rpc, out_rpc) \
+ UINT function(RPC *r, data_type *t) \
+ { \
+ PACK *p, *ret; \
+ UINT err; \
+ if (r == NULL || t == NULL) \
+ { \
+ return ERR_INTERNAL_ERROR; \
+ } \
+ p = NewPack(); \
+ out_rpc(p, t); \
+ ret = AdminCall(r, rpc_name, p); \
+ err = GetErrorFromPack(ret); \
+ if (err == ERR_NO_ERROR) \
+ { \
+ in_rpc(t, ret); \
+ } \
+ FreePack(ret); \
+ return err; \
+ }
+
+// RPC server function
+PACK *NiRpcServer(RPC *r, char *name, PACK *p)
+{
+ NAT *n = (NAT *)r->Param;
+ PACK *ret;
+ UINT err;
+ bool ok;
+ // Validate arguments
+ if (r == NULL || name == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewPack();
+ err = ERR_NO_ERROR;
+ ok = false;
+
+ if (0) {}
+
+ // RPC function definition: From here
+
+// DECLARE_RPC("Online", RPC_DUMMY, NtOnline, InRpcDummy, OutRpcDummy)
+// DECLARE_RPC("Offline", RPC_DUMMY, NtOffline, InRpcDummy, OutRpcDummy)
+ DECLARE_RPC("SetHostOption", VH_OPTION, NtSetHostOption, InVhOption, OutVhOption)
+ DECLARE_RPC("GetHostOption", VH_OPTION, NtGetHostOption, InVhOption, OutVhOption)
+// DECLARE_RPC_EX("SetClientConfig", RPC_CREATE_LINK, NtSetClientConfig, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+// DECLARE_RPC_EX("GetClientConfig", RPC_CREATE_LINK, NtGetClientConfig, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+ DECLARE_RPC_EX("GetStatus", RPC_NAT_STATUS, NtGetStatus, InRpcNatStatus, OutRpcNatStatus, FreeRpcNatStatus)
+// DECLARE_RPC_EX("GetInfo", RPC_NAT_INFO, NtGetInfo, InRpcNatInfo, OutRpcNatInfo, FreeRpcNatInfo)
+ DECLARE_RPC_EX("EnumNatList", RPC_ENUM_NAT, NtEnumNatList, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)
+ DECLARE_RPC_EX("EnumDhcpList", RPC_ENUM_DHCP, NtEnumDhcpList, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)
+// DECLARE_RPC("SetPassword", RPC_SET_PASSWORD, NtSetPassword, InRpcSetPassword, OutRpcSetPassword)
+
+ // RPC function definition: To here
+
+ if (ok == false)
+ {
+ err = ERR_NOT_SUPPORTED;
+ }
+
+ PackAddInt(ret, "error", err);
+
+ return ret;
+}
+
+
+
+
+// RPC call definition: From here
+
+DECLARE_SC("Online", RPC_DUMMY, NcOnline, InRpcDummy, OutRpcDummy)
+DECLARE_SC("Offline", RPC_DUMMY, NcOffline, InRpcDummy, OutRpcDummy)
+DECLARE_SC("SetHostOption", VH_OPTION, NcSetHostOption, InVhOption, OutVhOption)
+DECLARE_SC("GetHostOption", VH_OPTION, NcGetHostOption, InVhOption, OutVhOption)
+DECLARE_SC_EX("SetClientConfig", RPC_CREATE_LINK, NcSetClientConfig, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+DECLARE_SC_EX("GetClientConfig", RPC_CREATE_LINK, NcGetClientConfig, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)
+DECLARE_SC_EX("GetStatus", RPC_NAT_STATUS, NcGetStatus, InRpcNatStatus, OutRpcNatStatus, FreeRpcNatStatus)
+DECLARE_SC_EX("GetInfo", RPC_NAT_INFO, NcGetInfo, InRpcNatInfo, OutRpcNatInfo, FreeRpcNatInfo)
+DECLARE_SC_EX("EnumNatList", RPC_ENUM_NAT, NcEnumNatList, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)
+DECLARE_SC_EX("EnumDhcpList", RPC_ENUM_DHCP, NcEnumDhcpList, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)
+DECLARE_SC("SetPassword", RPC_SET_PASSWORD, NcSetPassword, InRpcSetPassword, OutRpcSetPassword)
+
+// RPC call definition: To here
+
+
+
+// Set a password
+UINT NtSetPassword(NAT *n, RPC_SET_PASSWORD *t)
+{
+ Copy(n->HashedPassword, t->HashedPassword, SHA1_SIZE);
+
+ NiWriteConfig(n);
+
+ return ERR_NO_ERROR;
+}
+
+// Online
+UINT NtOnline(NAT *n, RPC_DUMMY *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ Lock(n->lock);
+ {
+ if (n->Online)
+ {
+ // It is already online
+ ret = ERR_ALREADY_ONLINE;
+ }
+ else
+ {
+ if (n->ClientOption == NULL || n->ClientAuth == NULL)
+ {
+ // Setting is not yet done
+ ret = ERR_ACCOUNT_NOT_PRESENT;
+ }
+ else
+ {
+ // OK
+ n->Online = true;
+
+ // Start connection
+ n->Virtual = NewVirtualHostEx(n->Cedar, n->ClientOption, n->ClientAuth,
+ &n->Option, n);
+ }
+ }
+ }
+ Unlock(n->lock);
+
+ NiWriteConfig(n);
+
+ return ret;
+}
+
+// Offline
+UINT NtOffline(NAT *n, RPC_DUMMY *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ Lock(n->lock);
+ {
+ if (n->Online == false)
+ {
+ // It is offline
+ ret = ERR_OFFLINE;
+ }
+ else
+ {
+ // Offline
+ StopVirtualHost(n->Virtual);
+ ReleaseVirtual(n->Virtual);
+ n->Virtual = NULL;
+
+ n->Online = false;
+ }
+ }
+ Unlock(n->lock);
+
+ NiWriteConfig(n);
+
+ return ret;
+}
+
+// Set host options
+UINT NtSetHostOption(NAT *n, VH_OPTION *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ Lock(n->lock);
+ {
+ Copy(&n->Option, t, sizeof(VH_OPTION));
+ }
+ Unlock(n->lock);
+
+ SetVirtualHostOption(n->Virtual, t);
+
+ NiWriteConfig(n);
+
+ return ret;
+}
+
+// Get host options
+UINT NtGetHostOption(NAT *n, VH_OPTION *t)
+{
+ UINT ret = ERR_NO_ERROR;
+
+ Lock(n->lock);
+ {
+ Copy(t, &n->Option, sizeof(VH_OPTION));
+ }
+ Unlock(n->lock);
+
+ return ret;
+}
+
+// Set the connection settings
+UINT NtSetClientConfig(NAT *n, RPC_CREATE_LINK *t)
+{
+ Lock(n->lock);
+ {
+ if (n->ClientOption != NULL || n->ClientAuth != NULL)
+ {
+ Free(n->ClientOption);
+ CiFreeClientAuth(n->ClientAuth);
+ }
+
+ n->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(n->ClientOption, t->ClientOption, sizeof(CLIENT_OPTION));
+ n->ClientAuth = CopyClientAuth(t->ClientAuth);
+ }
+ Unlock(n->lock);
+
+ NiWriteConfig(n);
+
+ if (n->Online)
+ {
+ NtOffline(n, NULL);
+ NtOnline(n, NULL);
+ }
+
+ return ERR_NO_ERROR;
+}
+
+// Get the connection settings
+UINT NtGetClientConfig(NAT *n, RPC_CREATE_LINK *t)
+{
+ UINT err = ERR_NO_ERROR;
+
+ Lock(n->lock);
+ {
+ if (n->ClientOption == NULL || n->ClientAuth == NULL)
+ {
+ err = ERR_ACCOUNT_NOT_PRESENT;
+ }
+ else
+ {
+ FreeRpcCreateLink(t);
+
+ Zero(t, sizeof(RPC_CREATE_LINK));
+ t->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ Copy(t->ClientOption, n->ClientOption, sizeof(CLIENT_OPTION));
+ t->ClientAuth = CopyClientAuth(n->ClientAuth);
+ }
+ }
+ Unlock(n->lock);
+
+ return err;
+}
+
+// Get the state
+UINT NtGetStatus(NAT *n, RPC_NAT_STATUS *t)
+{
+ Lock(n->lock);
+ {
+ VH *v = n->Virtual;
+ FreeRpcNatStatus(t);
+ Zero(t, sizeof(RPC_NAT_STATUS));
+
+ LockVirtual(v);
+ {
+ UINT i;
+
+ LockList(v->NatTable);
+ {
+ for (i = 0;i < LIST_NUM(v->NatTable);i++)
+ {
+ NAT_ENTRY *e = LIST_DATA(v->NatTable, i);
+
+ switch (e->Protocol)
+ {
+ case NAT_TCP:
+ t->NumTcpSessions++;
+ break;
+
+ case NAT_UDP:
+ t->NumUdpSessions++;
+ break;
+
+ case NAT_ICMP:
+ t->NumIcmpSessions++;
+ break;
+
+ case NAT_DNS:
+ t->NumDnsSessions++;
+ break;
+ }
+ }
+
+ if (NnIsActive(v) && v->NativeNat != NULL)
+ {
+ NATIVE_NAT *nn = v->NativeNat;
+
+ for (i = 0;i < LIST_NUM(nn->NatTableForSend->AllList);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(nn->NatTableForSend->AllList, i);
+
+ switch (e->Protocol)
+ {
+ case NAT_TCP:
+ t->NumTcpSessions++;
+ break;
+
+ case NAT_UDP:
+ t->NumUdpSessions++;
+ break;
+
+ case NAT_ICMP:
+ t->NumIcmpSessions++;
+ break;
+
+ case NAT_DNS:
+ t->NumDnsSessions++;
+ break;
+ }
+ }
+ }
+ }
+ UnlockList(v->NatTable);
+
+ t->NumDhcpClients = LIST_NUM(v->DhcpLeaseList);
+
+ t->IsKernelMode = NnIsActive(v);
+ }
+ UnlockVirtual(v);
+ }
+ Unlock(n->lock);
+
+ return ERR_NO_ERROR;
+}
+
+// Get the information
+UINT NtGetInfo(NAT *n, RPC_NAT_INFO *t)
+{
+ OS_INFO *info;
+ FreeRpcNatInfo(t);
+ Zero(t, sizeof(RPC_NAT_INFO));
+
+ StrCpy(t->NatProductName, sizeof(t->NatProductName), CEDAR_ROUTER_STR);
+ StrCpy(t->NatVersionString, sizeof(t->NatVersionString), n->Cedar->VerString);
+ StrCpy(t->NatBuildInfoString, sizeof(t->NatBuildInfoString), n->Cedar->BuildInfo);
+ t->NatVerInt = n->Cedar->Build;
+ t->NatBuildInt = n->Cedar->Build;
+
+ GetMachineName(t->NatHostName, sizeof(t->NatHostName));
+
+ info = GetOsInfo();
+
+ CopyOsInfo(&t->OsInfo, info);
+
+ GetMemInfo(&t->MemInfo);
+
+ return ERR_NO_ERROR;
+}
+
+// Get the NAT list
+UINT NtEnumNatList(NAT *n, RPC_ENUM_NAT *t)
+{
+ UINT ret = ERR_NO_ERROR;
+ VH *v = NULL;
+
+ Lock(n->lock);
+ {
+ v = n->Virtual;
+
+ if (n->Online == false || v == NULL)
+ {
+ ret = ERR_OFFLINE;
+ }
+ else
+ {
+ LockVirtual(v);
+ {
+ if (v->Active == false)
+ {
+ ret = ERR_OFFLINE;
+ }
+ else
+ {
+ FreeRpcEnumNat(t);
+ Zero(t, sizeof(RPC_ENUM_NAT));
+
+ LockList(v->NatTable);
+ {
+ UINT i;
+ UINT num_usermode_nat = LIST_NUM(v->NatTable);
+ UINT num_kernel_mode_nat = 0;
+ NATIVE_NAT *native = NULL;
+
+ if (NnIsActive(v) && (v->NativeNat != NULL))
+ {
+ native = v->NativeNat;
+
+ num_kernel_mode_nat = LIST_NUM(native->NatTableForSend->AllList);
+ }
+
+ t->NumItem = num_usermode_nat + num_kernel_mode_nat;
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_NAT_ITEM) * t->NumItem);
+
+ // Enumerate entries of the user mode NAT
+ for (i = 0;i < num_usermode_nat;i++)
+ {
+ NAT_ENTRY *nat = LIST_DATA(v->NatTable, i);
+ RPC_ENUM_NAT_ITEM *e = &t->Items[i];
+
+ e->Id = nat->Id;
+ e->Protocol = nat->Protocol;
+ e->SrcIp = nat->SrcIp;
+ e->DestIp = nat->DestIp;
+ e->SrcPort = nat->SrcPort;
+ e->DestPort = nat->DestPort;
+
+ e->CreatedTime = TickToTime(nat->CreatedTime);
+ e->LastCommTime = TickToTime(nat->LastCommTime);
+
+ IPToStr32(e->SrcHost, sizeof(e->SrcHost), e->SrcIp);
+ IPToStr32(e->DestHost, sizeof(e->DestHost), e->DestIp);
+
+ if (nat->Sock != NULL)
+ {
+ e->SendSize = nat->Sock->SendSize;
+ e->RecvSize = nat->Sock->RecvSize;
+
+ if (nat->Sock->Type == SOCK_TCP)
+ {
+ StrCpy(e->DestHost, sizeof(e->DestHost), nat->Sock->RemoteHostname);
+ }
+ }
+
+ e->TcpStatus = nat->TcpStatus;
+ }
+
+ // Enumerate the entries in the kernel-mode NAT
+ if (native != NULL)
+ {
+ for (i = 0;i < num_kernel_mode_nat;i++)
+ {
+ NATIVE_NAT_ENTRY *nat = LIST_DATA(native->NatTableForSend->AllList, i);
+ RPC_ENUM_NAT_ITEM *e = &t->Items[num_usermode_nat + i];
+
+ e->Id = nat->Id;
+ e->Protocol = nat->Protocol;
+ e->SrcIp = nat->SrcIp;
+ e->DestIp = nat->DestIp;
+ e->SrcPort = nat->SrcPort;
+ e->DestPort = nat->DestPort;
+ e->CreatedTime = TickToTime(nat->CreatedTime);
+ e->LastCommTime = TickToTime(nat->LastCommTime);
+
+ IPToStr32(e->SrcHost, sizeof(e->SrcHost), e->SrcIp);
+ IPToStr32(e->DestHost, sizeof(e->DestHost), e->DestIp);
+
+ e->SendSize = nat->TotalSent;
+ e->RecvSize = nat->TotalRecv;
+
+ e->TcpStatus = nat->Status;
+ }
+ }
+ }
+ UnlockList(v->NatTable);
+ }
+ }
+ UnlockVirtual(v);
+ }
+ }
+ Unlock(n->lock);
+
+ return ret;
+}
+
+UINT NtEnumDhcpList(NAT *n, RPC_ENUM_DHCP *t)
+{
+ UINT ret = ERR_NO_ERROR;
+ VH *v = NULL;
+
+ Lock(n->lock);
+ {
+ v = n->Virtual;
+
+ if (n->Online == false || v == NULL)
+ {
+ ret = ERR_OFFLINE;
+ }
+ else
+ {
+ LockVirtual(v);
+ {
+ if (v->Active == false)
+ {
+ ret = ERR_OFFLINE;
+ }
+ else
+ {
+ FreeRpcEnumDhcp(t);
+ Zero(t, sizeof(RPC_ENUM_DHCP));
+
+ LockList(v->DhcpLeaseList);
+ {
+ UINT i;
+ t->NumItem = LIST_NUM(v->DhcpLeaseList);
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_DHCP_ITEM) * t->NumItem);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ DHCP_LEASE *dhcp = LIST_DATA(v->DhcpLeaseList, i);
+ RPC_ENUM_DHCP_ITEM *e = &t->Items[i];
+
+ e->Id = dhcp->Id;
+ e->LeasedTime = TickToTime(dhcp->LeasedTime);
+ e->ExpireTime = TickToTime(dhcp->ExpireTime);
+ Copy(e->MacAddress, dhcp->MacAddress, 6);
+ e->IpAddress = dhcp->IpAddress;
+ e->Mask = dhcp->Mask;
+ StrCpy(e->Hostname, sizeof(e->Hostname), dhcp->Hostname);
+ }
+ }
+ UnlockList(v->DhcpLeaseList);
+ }
+ }
+ UnlockVirtual(v);
+ }
+ }
+ Unlock(n->lock);
+
+ return ret;
+}
+
+// VH_OPTION
+void InVhOption(VH_OPTION *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(VH_OPTION));
+ PackGetData2(p, "MacAddress", t->MacAddress, 6);
+ PackGetIp(p, "Ip", &t->Ip);
+ PackGetIp(p, "Mask", &t->Mask);
+ t->UseNat = PackGetBool(p, "UseNat");
+ t->Mtu = PackGetInt(p, "Mtu");
+ t->NatTcpTimeout = PackGetInt(p, "NatTcpTimeout");
+ t->NatUdpTimeout = PackGetInt(p, "NatUdpTimeout");
+ t->UseDhcp = PackGetBool(p, "UseDhcp");
+ PackGetIp(p, "DhcpLeaseIPStart", &t->DhcpLeaseIPStart);
+ PackGetIp(p, "DhcpLeaseIPEnd", &t->DhcpLeaseIPEnd);
+ PackGetIp(p, "DhcpSubnetMask", &t->DhcpSubnetMask);
+ t->DhcpExpireTimeSpan = PackGetInt(p, "DhcpExpireTimeSpan");
+ PackGetIp(p, "DhcpGatewayAddress", &t->DhcpGatewayAddress);
+ PackGetIp(p, "DhcpDnsServerAddress", &t->DhcpDnsServerAddress);
+ PackGetIp(p, "DhcpDnsServerAddress2", &t->DhcpDnsServerAddress2);
+ PackGetStr(p, "DhcpDomainName", t->DhcpDomainName, sizeof(t->DhcpDomainName));
+ t->SaveLog = PackGetBool(p, "SaveLog");
+ PackGetStr(p, "RpcHubName", t->HubName, sizeof(t->HubName));
+}
+void OutVhOption(PACK *p, VH_OPTION *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddData(p, "MacAddress", t->MacAddress, 6);
+ PackAddIp(p, "Ip", &t->Ip);
+ PackAddIp(p, "Mask", &t->Mask);
+ PackAddBool(p, "UseNat", t->UseNat);
+ PackAddInt(p, "Mtu", t->Mtu);
+ PackAddInt(p, "NatTcpTimeout", t->NatTcpTimeout);
+ PackAddInt(p, "NatUdpTimeout", t->NatUdpTimeout);
+ PackAddBool(p, "UseDhcp", t->UseDhcp);
+ PackAddIp(p, "DhcpLeaseIPStart", &t->DhcpLeaseIPStart);
+ PackAddIp(p, "DhcpLeaseIPEnd", &t->DhcpLeaseIPEnd);
+ PackAddIp(p, "DhcpSubnetMask", &t->DhcpSubnetMask);
+ PackAddInt(p, "DhcpExpireTimeSpan", t->DhcpExpireTimeSpan);
+ PackAddIp(p, "DhcpGatewayAddress", &t->DhcpGatewayAddress);
+ PackAddIp(p, "DhcpDnsServerAddress", &t->DhcpDnsServerAddress);
+ PackAddIp(p, "DhcpDnsServerAddress2", &t->DhcpDnsServerAddress2);
+ PackAddStr(p, "DhcpDomainName", t->DhcpDomainName);
+ PackAddBool(p, "SaveLog", t->SaveLog);
+ PackAddStr(p, "RpcHubName", t->HubName);
+}
+
+// RPC_ENUM_DHCP
+void InRpcEnumDhcp(RPC_ENUM_DHCP *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_DHCP));
+ t->NumItem = PackGetInt(p, "NumItem");
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_DHCP_ITEM) * t->NumItem);
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_DHCP_ITEM *e = &t->Items[i];
+
+ e->Id = PackGetIntEx(p, "Id", i);
+ e->LeasedTime = PackGetInt64Ex(p, "LeasedTime", i);
+ e->ExpireTime = PackGetInt64Ex(p, "ExpireTime", i);
+ PackGetDataEx2(p, "MacAddress", e->MacAddress, 6, i);
+ e->IpAddress = PackGetIp32Ex(p, "IpAddress", i);
+ e->Mask = PackGetIntEx(p, "Mask", i);
+ PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
+ }
+}
+void OutRpcEnumDhcp(PACK *p, RPC_ENUM_DHCP *t)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+ PackAddStr(p, "HubName", t->HubName);
+
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_DHCP_ITEM *e = &t->Items[i];
+
+ PackAddIntEx(p, "Id", e->Id, i, t->NumItem);
+ PackAddInt64Ex(p, "LeasedTime", e->LeasedTime, i, t->NumItem);
+ PackAddInt64Ex(p, "ExpireTime", e->ExpireTime, i, t->NumItem);
+ PackAddDataEx(p, "MacAddress", e->MacAddress, 6, i, t->NumItem);
+ PackAddIp32Ex(p, "IpAddress", e->IpAddress, i, t->NumItem);
+ PackAddIntEx(p, "Mask", e->Mask, i, t->NumItem);
+ PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumItem);
+ }
+}
+void FreeRpcEnumDhcp(RPC_ENUM_DHCP *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_ENUM_NAT
+void InRpcEnumNat(RPC_ENUM_NAT *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_ENUM_NAT));
+ t->NumItem = PackGetInt(p, "NumItem");
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+ t->Items = ZeroMalloc(sizeof(RPC_ENUM_NAT_ITEM) * t->NumItem);
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_NAT_ITEM *e = &t->Items[i];
+
+ e->Id = PackGetIntEx(p, "Id", i);
+ e->Protocol = PackGetIntEx(p, "Protocol", i);
+ e->SrcIp = PackGetIntEx(p, "SrcIp", i);
+ PackGetStrEx(p, "SrcHost", e->SrcHost, sizeof(e->SrcHost), i);
+ e->SrcPort = PackGetIntEx(p, "SrcPort", i);
+ e->DestIp = PackGetIntEx(p, "DestIp", i);
+ PackGetStrEx(p, "DestHost", e->DestHost, sizeof(e->DestHost), i);
+ e->DestPort = PackGetIntEx(p, "DestPort", i);
+ e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
+ e->LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);
+ e->SendSize = PackGetInt64Ex(p, "SendSize", i);
+ e->RecvSize = PackGetInt64Ex(p, "RecvSize", i);
+ e->TcpStatus = PackGetIntEx(p, "TcpStatus", i);
+ }
+}
+void OutRpcEnumNat(PACK *p, RPC_ENUM_NAT *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "NumItem", t->NumItem);
+ PackAddStr(p, "HubName", t->HubName);
+ for (i = 0;i < t->NumItem;i++)
+ {
+ RPC_ENUM_NAT_ITEM *e = &t->Items[i];
+
+ PackAddIntEx(p, "Id", e->Id, i, t->NumItem);
+ PackAddIntEx(p, "Protocol", e->Protocol, i, t->NumItem);
+ PackAddIp32Ex(p, "SrcIp", e->SrcIp, i, t->NumItem);
+ PackAddStrEx(p, "SrcHost", e->SrcHost, i, t->NumItem);
+ PackAddIntEx(p, "SrcPort", e->SrcPort, i, t->NumItem);
+ PackAddIp32Ex(p, "DestIp", e->DestIp, i, t->NumItem);
+ PackAddStrEx(p, "DestHost", e->DestHost, i, t->NumItem);
+ PackAddIntEx(p, "DestPort", e->DestPort, i, t->NumItem);
+ PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumItem);
+ PackAddInt64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumItem);
+ PackAddInt64Ex(p, "SendSize", e->SendSize, i, t->NumItem);
+ PackAddInt64Ex(p, "RecvSize", e->RecvSize, i, t->NumItem);
+ PackAddIntEx(p, "TcpStatus", e->TcpStatus, i, t->NumItem);
+ }
+}
+void FreeRpcEnumNat(RPC_ENUM_NAT *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Free(t->Items);
+}
+
+// RPC_NAT_INFO
+void InRpcNatInfo(RPC_NAT_INFO *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_NAT_INFO));
+ PackGetStr(p, "NatProductName", t->NatProductName, sizeof(t->NatProductName));
+ PackGetStr(p, "NatVersionString", t->NatVersionString, sizeof(t->NatVersionString));
+ PackGetStr(p, "NatBuildInfoString", t->NatBuildInfoString, sizeof(t->NatBuildInfoString));
+ t->NatVerInt = PackGetInt(p, "NatVerInt");
+ t->NatBuildInt = PackGetInt(p, "NatBuildInt");
+ PackGetStr(p, "NatHostName", t->NatHostName, sizeof(t->NatHostName));
+ InRpcOsInfo(&t->OsInfo, p);
+ InRpcMemInfo(&t->MemInfo, p);
+}
+void OutRpcNatInfo(PACK *p, RPC_NAT_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "NatProductName", t->NatProductName);
+ PackAddStr(p, "NatVersionString", t->NatVersionString);
+ PackAddStr(p, "NatBuildInfoString", t->NatBuildInfoString);
+ PackAddInt(p, "NatVerInt", t->NatVerInt);
+ PackAddInt(p, "NatBuildInt", t->NatBuildInt);
+ PackAddStr(p, "NatHostName", t->NatHostName);
+ OutRpcOsInfo(p, &t->OsInfo);
+ OutRpcMemInfo(p, &t->MemInfo);
+}
+void FreeRpcNatInfo(RPC_NAT_INFO *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ FreeRpcOsInfo(&t->OsInfo);
+}
+
+// RPC_NAT_STATUS
+void InRpcNatStatus(RPC_NAT_STATUS *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_NAT_STATUS));
+ t->NumTcpSessions = PackGetInt(p, "NumTcpSessions");
+ t->NumUdpSessions = PackGetInt(p, "NumUdpSessions");
+ t->NumIcmpSessions = PackGetInt(p, "NumIcmpSessions");
+ t->NumDnsSessions = PackGetInt(p, "NumDnsSessions");
+ t->NumDhcpClients = PackGetInt(p, "NumDhcpClients");
+ t->IsKernelMode = PackGetBool(p, "IsKernelMode");
+ PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
+}
+void OutRpcNatStatus(PACK *p, RPC_NAT_STATUS *t)
+{
+ // Validate arguments
+ if (p == NULL || t == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "HubName", t->HubName);
+ PackAddInt(p, "NumTcpSessions", t->NumTcpSessions);
+ PackAddInt(p, "NumUdpSessions", t->NumUdpSessions);
+ PackAddInt(p, "NumIcmpSessions", t->NumIcmpSessions);
+ PackAddInt(p, "NumDnsSessions", t->NumDnsSessions);
+ PackAddInt(p, "NumDhcpClients", t->NumDhcpClients);
+ PackAddBool(p, "IsKernelMode", t->IsKernelMode);
+}
+void FreeRpcNatStatus(RPC_NAT_STATUS *t)
+{
+}
+
+// RPC_DUMMY
+void InRpcDummy(RPC_DUMMY *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(RPC_DUMMY));
+ t->DummyValue = PackGetInt(p, "DummyValue");
+}
+void OutRpcDummy(PACK *p, RPC_DUMMY *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "DummyValue", t->DummyValue);
+}
+
+// Main procedure for management
+void NiAdminMain(NAT *n, SOCK *s)
+{
+ RPC *r;
+ PACK *p;
+ // Validate arguments
+ if (n == NULL || s == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ HttpServerSend(s, p);
+ FreePack(p);
+
+ r = StartRpcServer(s, NiRpcServer, n);
+
+ RpcServer(r);
+
+ RpcFree(r);
+}
+
+// Management thread
+void NiAdminThread(THREAD *thread, void *param)
+{
+ NAT_ADMIN *a = (NAT_ADMIN *)param;
+ NAT *n;
+ SOCK *s;
+ UCHAR random[SHA1_SIZE];
+ UINT err;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Random number generation
+ Rand(random, sizeof(random));
+
+ a->Thread = thread;
+ AddRef(a->Thread->ref);
+ s = a->Sock;
+ AddRef(s->ref);
+
+ n = a->Nat;
+
+ LockList(n->AdminList);
+ {
+ Add(n->AdminList, a);
+ }
+ UnlockList(n->AdminList);
+
+ NoticeThreadInit(thread);
+
+ err = ERR_AUTH_FAILED;
+
+ if (StartSSL(s, n->AdminX, n->AdminK))
+ {
+ PACK *p;
+
+ // Send the random number
+ p = NewPack();
+ PackAddData(p, "auth_random", random, sizeof(random));
+
+ if (HttpServerSend(s, p))
+ {
+ PACK *p;
+ // Receive a password
+ p = HttpServerRecv(s);
+ if (p != NULL)
+ {
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR secure_check[SHA1_SIZE];
+
+ if (PackGetData2(p, "secure_password", secure_password, sizeof(secure_password)))
+ {
+ SecurePassword(secure_check, n->HashedPassword, random);
+
+ if (Cmp(secure_check, secure_password, SHA1_SIZE) == 0)
+ {
+ UCHAR test[SHA1_SIZE];
+ // Password match
+ Hash(test, "", 0, true);
+ SecurePassword(test, test, random);
+
+#if 0
+ if (Cmp(test, secure_check, SHA1_SIZE) == 0 && s->RemoteIP.addr[0] != 127)
+ {
+ // A client can not connect from the outside with blank password
+ err = ERR_NULL_PASSWORD_LOCAL_ONLY;
+ }
+ else
+#endif
+
+ {
+ // Successful connection
+ err = ERR_NO_ERROR;
+ NiAdminMain(n, s);
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+ }
+
+ FreePack(p);
+
+ if (err != ERR_NO_ERROR)
+ {
+ p = PackError(err);
+ HttpServerSend(s, p);
+ FreePack(p);
+ }
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+}
+
+// Management port Listen thread
+void NiListenThread(THREAD *thread, void *param)
+{
+ NAT *n = (NAT *)param;
+ SOCK *a;
+ UINT i;
+ bool b = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Initialize the management list
+ n->AdminList = NewList(NULL);
+
+ while (true)
+ {
+ a = Listen(DEFAULT_NAT_ADMIN_PORT);
+ if (b == false)
+ {
+ b = true;
+ NoticeThreadInit(thread);
+ }
+ if (a != NULL)
+ {
+ break;
+ }
+
+ Wait(n->HaltEvent, NAT_ADMIN_PORT_LISTEN_INTERVAL);
+ if (n->Halt)
+ {
+ return;
+ }
+ }
+
+ n->AdminListenSock = a;
+ AddRef(a->ref);
+
+ // Waiting
+ while (true)
+ {
+ SOCK *s = Accept(a);
+ THREAD *t;
+ NAT_ADMIN *admin;
+ if (s == NULL)
+ {
+ break;
+ }
+ if (n->Halt)
+ {
+ ReleaseSock(s);
+ break;
+ }
+
+ admin = ZeroMalloc(sizeof(NAT_ADMIN));
+ admin->Nat = n;
+ admin->Sock = s;
+ t = NewThread(NiAdminThread, admin);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+ }
+
+ // Disconnect all management connections
+ LockList(n->AdminList);
+ {
+ for (i = 0;i < LIST_NUM(n->AdminList);i++)
+ {
+ NAT_ADMIN *a = LIST_DATA(n->AdminList, i);
+ Disconnect(a->Sock);
+ WaitThread(a->Thread, INFINITE);
+ ReleaseThread(a->Thread);
+ ReleaseSock(a->Sock);
+ Free(a);
+ }
+ }
+ UnlockList(n->AdminList);
+
+ ReleaseList(n->AdminList);
+
+ ReleaseSock(a);
+}
+
+// Initialize receiving management command
+void NiInitAdminAccept(NAT *n)
+{
+ THREAD *t;
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ t = NewThread(NiListenThread, n);
+ WaitThreadInit(t);
+ n->AdminAcceptThread = t;
+}
+
+// Complete receiving management command
+void NiFreeAdminAccept(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ n->Halt = true;
+ Disconnect(n->AdminListenSock);
+ Set(n->HaltEvent);
+
+ while (true)
+ {
+ if (WaitThread(n->AdminAcceptThread, 1000) == false)
+ {
+ Disconnect(n->AdminListenSock);
+ }
+ else
+ {
+ break;
+ }
+ }
+ ReleaseThread(n->AdminAcceptThread);
+
+ ReleaseSock(n->AdminListenSock);
+}
+
+// Clear the DHCP options that are not supported by the dynamic Virtual HUB
+void NiClearUnsupportedVhOptionForDynamicHub(VH_OPTION *o, bool initial)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->UseNat = false;
+
+ if (initial)
+ {
+ Zero(&o->DhcpGatewayAddress, sizeof(IP));
+ Zero(&o->DhcpDnsServerAddress, sizeof(IP));
+ Zero(&o->DhcpDnsServerAddress2, sizeof(IP));
+ StrCpy(o->DhcpDomainName, sizeof(o->DhcpDomainName), "");
+ }
+}
+
+// Initialize the options for the virtual host
+void NiSetDefaultVhOption(NAT *n, VH_OPTION *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Zero(o, sizeof(VH_OPTION));
+ GenMacAddress(o->MacAddress);
+
+ // Set the virtual IP to 192.168.30.1/24
+ SetIP(&o->Ip, 192, 168, 30, 1);
+ SetIP(&o->Mask, 255, 255, 255, 0);
+ o->UseNat = true;
+ o->Mtu = 1500;
+ o->NatTcpTimeout = 1800;
+ o->NatUdpTimeout = 60;
+ o->UseDhcp = true;
+ SetIP(&o->DhcpLeaseIPStart, 192, 168, 30, 10);
+ SetIP(&o->DhcpLeaseIPEnd, 192, 168, 30, 200);
+ SetIP(&o->DhcpSubnetMask, 255, 255, 255, 0);
+ o->DhcpExpireTimeSpan = 7200;
+ o->SaveLog = true;
+
+ SetIP(&o->DhcpGatewayAddress, 192, 168, 30, 1);
+ SetIP(&o->DhcpDnsServerAddress, 192, 168, 30, 1);
+
+ GetDomainName(o->DhcpDomainName, sizeof(o->DhcpDomainName));
+}
+
+// Reset the setting of NAT to the default
+void NiInitDefaultConfig(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Initialize the virtual host option
+ NiSetDefaultVhOption(n, &n->Option);
+
+ // Initialize management port
+ n->AdminPort = DEFAULT_NAT_ADMIN_PORT;
+
+ // Offline
+ n->Online = false;
+
+ // Save the log
+ n->Option.SaveLog = true;
+}
+
+// Initialize the NAT configuration
+void NiInitConfig(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Initial state
+ NiInitDefaultConfig(n);
+}
+
+// Read the virtual host option (extended)
+void NiLoadVhOptionEx(VH_OPTION *o, FOLDER *root)
+{
+ FOLDER *host, *nat, *dhcp;
+ char mac_address[MAX_SIZE];
+ // Validate arguments
+ if (o == NULL || root == NULL)
+ {
+ return;
+ }
+
+ host = CfgGetFolder(root, "VirtualHost");
+ nat = CfgGetFolder(root, "VirtualRouter");
+ dhcp = CfgGetFolder(root, "VirtualDhcpServer");
+
+ Zero(o, sizeof(VH_OPTION));
+
+ GenMacAddress(o->MacAddress);
+ if (CfgGetStr(host, "VirtualHostMacAddress", mac_address, sizeof(mac_address)))
+ {
+ BUF *b = StrToBin(mac_address);
+ if (b != NULL)
+ {
+ if (b->Size == 6)
+ {
+ Copy(o->MacAddress, b->Buf, 6);
+ }
+ }
+ FreeBuf(b);
+ }
+ CfgGetIp(host, "VirtualHostIp", &o->Ip);
+ CfgGetIp(host, "VirtualHostIpSubnetMask", &o->Mask);
+
+ o->UseNat = CfgGetBool(nat, "NatEnabled");
+ o->Mtu = CfgGetInt(nat, "NatMtu");
+ o->NatTcpTimeout = CfgGetInt(nat, "NatTcpTimeout");
+ o->NatUdpTimeout = CfgGetInt(nat, "NatUdpTimeout");
+
+ o->UseDhcp = CfgGetBool(dhcp, "DhcpEnabled");
+ CfgGetIp(dhcp, "DhcpLeaseIPStart", &o->DhcpLeaseIPStart);
+ CfgGetIp(dhcp, "DhcpLeaseIPEnd", &o->DhcpLeaseIPEnd);
+ CfgGetIp(dhcp, "DhcpSubnetMask", &o->DhcpSubnetMask);
+ o->DhcpExpireTimeSpan = CfgGetInt(dhcp, "DhcpExpireTimeSpan");
+ CfgGetIp(dhcp, "DhcpGatewayAddress", &o->DhcpGatewayAddress);
+ CfgGetIp(dhcp, "DhcpDnsServerAddress", &o->DhcpDnsServerAddress);
+ CfgGetIp(dhcp, "DhcpDnsServerAddress2", &o->DhcpDnsServerAddress2);
+ CfgGetStr(dhcp, "DhcpDomainName", o->DhcpDomainName, sizeof(o->DhcpDomainName));
+
+ Trim(o->DhcpDomainName);
+ if (StrLen(o->DhcpDomainName) == 0)
+ {
+ //GetDomainName(o->DhcpDomainName, sizeof(o->DhcpDomainName));
+ }
+
+ o->SaveLog = CfgGetBool(root, "SaveLog");
+}
+
+// Read the virtual host option
+void NiLoadVhOption(NAT *n, FOLDER *root)
+{
+ VH_OPTION *o;
+ FOLDER *host, *nat, *dhcp;
+ char mac_address[MAX_SIZE];
+ // Validate arguments
+ if (n == NULL || root == NULL)
+ {
+ return;
+ }
+
+ host = CfgGetFolder(root, "VirtualHost");
+ nat = CfgGetFolder(root, "VirtualRouter");
+ dhcp = CfgGetFolder(root, "VirtualDhcpServer");
+
+ o = &n->Option;
+ Zero(o, sizeof(VH_OPTION));
+
+ GenMacAddress(o->MacAddress);
+ if (CfgGetStr(host, "VirtualHostMacAddress", mac_address, sizeof(mac_address)))
+ {
+ BUF *b = StrToBin(mac_address);
+ if (b != NULL)
+ {
+ if (b->Size == 6)
+ {
+ Copy(o->MacAddress, b->Buf, 6);
+ }
+ }
+ FreeBuf(b);
+ }
+ CfgGetIp(host, "VirtualHostIp", &o->Ip);
+ CfgGetIp(host, "VirtualHostIpSubnetMask", &o->Mask);
+
+ o->UseNat = CfgGetBool(nat, "NatEnabled");
+ o->Mtu = CfgGetInt(nat, "NatMtu");
+ o->NatTcpTimeout = CfgGetInt(nat, "NatTcpTimeout");
+ o->NatUdpTimeout = CfgGetInt(nat, "NatUdpTimeout");
+
+ o->UseDhcp = CfgGetBool(dhcp, "DhcpEnabled");
+ CfgGetIp(dhcp, "DhcpLeaseIPStart", &o->DhcpLeaseIPStart);
+ CfgGetIp(dhcp, "DhcpLeaseIPEnd", &o->DhcpLeaseIPEnd);
+ CfgGetIp(dhcp, "DhcpSubnetMask", &o->DhcpSubnetMask);
+ o->DhcpExpireTimeSpan = CfgGetInt(dhcp, "DhcpExpireTimeSpan");
+ CfgGetIp(dhcp, "DhcpGatewayAddress", &o->DhcpGatewayAddress);
+ CfgGetIp(dhcp, "DhcpDnsServerAddress", &o->DhcpDnsServerAddress);
+ CfgGetIp(dhcp, "DhcpDnsServerAddress2", &o->DhcpDnsServerAddress2);
+ CfgGetStr(dhcp, "DhcpDomainName", o->DhcpDomainName, sizeof(o->DhcpDomainName));
+
+ o->SaveLog = CfgGetBool(root, "SaveLog");
+}
+
+// Read connection options from the VPN server
+void NiLoadClientData(NAT *n, FOLDER *root)
+{
+ FOLDER *co, *ca;
+ // Validate arguments
+ if (n == NULL || root == NULL)
+ {
+ return;
+ }
+
+ co = CfgGetFolder(root, "VpnClientOption");
+ ca = CfgGetFolder(root, "VpnClientAuth");
+ if (co == NULL || ca == NULL)
+ {
+ return;
+ }
+
+ n->ClientOption = CiLoadClientOption(co);
+ n->ClientAuth = CiLoadClientAuth(ca);
+}
+
+// Write connection options to the VPN server
+void NiWriteClientData(NAT *n, FOLDER *root)
+{
+ // Validate arguments
+ if (n == NULL || root == NULL || n->ClientOption == NULL || n->ClientAuth == NULL)
+ {
+ return;
+ }
+
+ CiWriteClientOption(CfgCreateFolder(root, "VpnClientOption"), n->ClientOption);
+ CiWriteClientAuth(CfgCreateFolder(root, "VpnClientAuth"), n->ClientAuth);
+}
+
+// Write the virtual host option (extended)
+void NiWriteVhOptionEx(VH_OPTION *o, FOLDER *root)
+{
+ FOLDER *host, *nat, *dhcp;
+ char mac_address[MAX_SIZE];
+ // Validate arguments
+ if (o == NULL || root == NULL)
+ {
+ return;
+ }
+
+ host = CfgCreateFolder(root, "VirtualHost");
+ nat = CfgCreateFolder(root, "VirtualRouter");
+ dhcp = CfgCreateFolder(root, "VirtualDhcpServer");
+
+ MacToStr(mac_address, sizeof(mac_address), o->MacAddress);
+ CfgAddStr(host, "VirtualHostMacAddress", mac_address);
+ CfgAddIp(host, "VirtualHostIp", &o->Ip);
+ CfgAddIp(host, "VirtualHostIpSubnetMask", &o->Mask);
+
+ CfgAddBool(nat, "NatEnabled", o->UseNat);
+ CfgAddInt(nat, "NatMtu", o->Mtu);
+ CfgAddInt(nat, "NatTcpTimeout", o->NatTcpTimeout);
+ CfgAddInt(nat, "NatUdpTimeout", o->NatUdpTimeout);
+
+ CfgAddBool(dhcp, "DhcpEnabled", o->UseDhcp);
+ CfgAddIp(dhcp, "DhcpLeaseIPStart", &o->DhcpLeaseIPStart);
+ CfgAddIp(dhcp, "DhcpLeaseIPEnd", &o->DhcpLeaseIPEnd);
+ CfgAddIp(dhcp, "DhcpSubnetMask", &o->DhcpSubnetMask);
+ CfgAddInt(dhcp, "DhcpExpireTimeSpan", o->DhcpExpireTimeSpan);
+ CfgAddIp(dhcp, "DhcpGatewayAddress", &o->DhcpGatewayAddress);
+ CfgAddIp(dhcp, "DhcpDnsServerAddress", &o->DhcpDnsServerAddress);
+ CfgAddIp(dhcp, "DhcpDnsServerAddress2", &o->DhcpDnsServerAddress2);
+ CfgAddStr(dhcp, "DhcpDomainName", o->DhcpDomainName);
+
+ CfgAddBool(root, "SaveLog", o->SaveLog);
+}
+
+// Write the virtual host option
+void NiWriteVhOption(NAT *n, FOLDER *root)
+{
+ VH_OPTION *o;
+ FOLDER *host, *nat, *dhcp;
+ char mac_address[MAX_SIZE];
+ // Validate arguments
+ if (n == NULL || root == NULL)
+ {
+ return;
+ }
+
+ host = CfgCreateFolder(root, "VirtualHost");
+ nat = CfgCreateFolder(root, "VirtualRouter");
+ dhcp = CfgCreateFolder(root, "VirtualDhcpServer");
+
+ o = &n->Option;
+
+ MacToStr(mac_address, sizeof(mac_address), o->MacAddress);
+ CfgAddStr(host, "VirtualHostMacAddress", mac_address);
+ CfgAddIp(host, "VirtualHostIp", &o->Ip);
+ CfgAddIp(host, "VirtualHostIpSubnetMask", &o->Mask);
+
+ CfgAddBool(nat, "NatEnabled", o->UseNat);
+ CfgAddInt(nat, "NatMtu", o->Mtu);
+ CfgAddInt(nat, "NatTcpTimeout", o->NatTcpTimeout);
+ CfgAddInt(nat, "NatUdpTimeout", o->NatUdpTimeout);
+
+ CfgAddBool(dhcp, "DhcpEnabled", o->UseDhcp);
+ CfgAddIp(dhcp, "DhcpLeaseIPStart", &o->DhcpLeaseIPStart);
+ CfgAddIp(dhcp, "DhcpLeaseIPEnd", &o->DhcpLeaseIPEnd);
+ CfgAddIp(dhcp, "DhcpSubnetMask", &o->DhcpSubnetMask);
+ CfgAddInt(dhcp, "DhcpExpireTimeSpan", o->DhcpExpireTimeSpan);
+ CfgAddIp(dhcp, "DhcpGatewayAddress", &o->DhcpGatewayAddress);
+ CfgAddIp(dhcp, "DhcpDnsServerAddress", &o->DhcpDnsServerAddress);
+ CfgAddIp(dhcp, "DhcpDnsServerAddress2", &o->DhcpDnsServerAddress2);
+ CfgAddStr(dhcp, "DhcpDomainName", o->DhcpDomainName);
+
+ CfgAddBool(root, "SaveLog", o->SaveLog);
+}
+
+// Read the configuration file
+bool NiLoadConfig(NAT *n, FOLDER *root)
+{
+ FOLDER *host;
+ BUF *b;
+ // Validate arguments
+ if (n == NULL || root == NULL)
+ {
+ return false;
+ }
+
+ host = CfgGetFolder(root, "VirtualHost");
+ if (host == NULL)
+ {
+ return false;
+ }
+
+ CfgGetByte(root, "HashedPassword", n->HashedPassword, sizeof(n->HashedPassword));
+ n->AdminPort = CfgGetInt(root, "AdminPort");
+ n->Online = CfgGetBool(root, "Online");
+
+ b = CfgGetBuf(root, "AdminCert");
+ if (b != NULL)
+ {
+ n->AdminX = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ b = CfgGetBuf(root, "AdminKey");
+ if (b != NULL)
+ {
+ n->AdminK = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+ }
+
+ NiLoadVhOption(n, root);
+
+ NiLoadClientData(n, root);
+
+ return true;
+}
+
+// Write the configuration to a file
+void NiWriteConfig(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ Lock(n->lock);
+ {
+ FOLDER *root = CfgCreateFolder(NULL, TAG_ROOT);
+ BUF *b;
+
+ // Certificate
+ b = XToBuf(n->AdminX, false);
+ CfgAddBuf(root, "AdminCert", b);
+ FreeBuf(b);
+
+ // Secret key
+ b = KToBuf(n->AdminK, false, NULL);
+ CfgAddBuf(root, "AdminKey", b);
+ FreeBuf(b);
+
+ // Password
+ CfgAddByte(root, "HashedPassword", n->HashedPassword, sizeof(n->HashedPassword));
+ CfgAddInt(root, "AdminPort", n->AdminPort);
+ CfgAddBool(root, "Online", n->Online);
+
+ // Virtual host option
+ NiWriteVhOption(n, root);
+
+ // Connection options
+ if (n->ClientOption != NULL && n->ClientAuth != NULL)
+ {
+ NiWriteClientData(n, root);
+ }
+
+ SaveCfgRw(n->CfgRw, root);
+ CfgDeleteFolder(root);
+ }
+ Unlock(n->lock);
+}
+
+// Release the NAT configuration
+void NiFreeConfig(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Write the latest configuration
+ NiWriteConfig(n);
+
+ // Release the configuration R/W
+ FreeCfgRw(n->CfgRw);
+ n->CfgRw = NULL;
+
+ Free(n->ClientOption);
+ CiFreeClientAuth(n->ClientAuth);
+
+ FreeX(n->AdminX);
+ FreeK(n->AdminK);
+}
+
+// Create a NAT
+NAT *NiNewNatEx(SNAT *snat, VH_OPTION *o)
+{
+ NAT *n = ZeroMalloc(sizeof(NAT));
+
+ n->lock = NewLock();
+ Hash(n->HashedPassword, "", 0, true);
+ n->HaltEvent = NewEvent();
+
+ //n->Cedar = NewCedar(NULL, NULL);
+
+ n->SecureNAT = snat;
+
+ // Raise the priority
+ //OSSetHighPriority();
+
+ // Initialize the settings
+ NiInitConfig(n);
+
+#if 0
+ // Start the operation of the virtual host
+ if (n->Online && n->ClientOption != NULL)
+ {
+ n->Virtual = NewVirtualHostEx(n->Cedar, n->ClientOption, n->ClientAuth, &n->Option, n);
+ }
+ else
+ {
+ n->Online = false;
+ n->Virtual = NULL;
+ }
+#else
+ n->Virtual = NewVirtualHostEx(n->Cedar, NULL, NULL, o, n);
+ n->Online = true;
+#endif
+
+ // Start management command
+ //NiInitAdminAccept(n);
+
+ return n;
+}
+NAT *NiNewNat()
+{
+ return NiNewNatEx(NULL, NULL);
+}
+
+// Release the NAT
+void NiFreeNat(NAT *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Complete management command
+ //NiFreeAdminAccept(n);
+
+ // Stop if the virtual host is running
+ Lock(n->lock);
+ {
+ if (n->Virtual != NULL)
+ {
+ StopVirtualHost(n->Virtual);
+ ReleaseVirtual(n->Virtual);
+ n->Virtual = NULL;
+ }
+ }
+ Unlock(n->lock);
+
+ // Release the settings
+ NiFreeConfig(n);
+
+ // Delete the object
+ ReleaseCedar(n->Cedar);
+ ReleaseEvent(n->HaltEvent);
+ DeleteLock(n->lock);
+
+ Free(n);
+}
+
+// Stop the NAT
+void NtStopNat()
+{
+ Lock(nat_lock);
+ {
+ if (nat != NULL)
+ {
+ NiFreeNat(nat);
+ nat = NULL;
+ }
+ }
+ Unlock(nat_lock);
+}
+
+// Start the NAT
+void NtStartNat()
+{
+ Lock(nat_lock);
+ {
+ if (nat == NULL)
+ {
+ nat = NiNewNat();
+ }
+ }
+ Unlock(nat_lock);
+}
+
+// Initialize the NtXxx function
+void NtInit()
+{
+ if (nat_lock != NULL)
+ {
+ return;
+ }
+
+ nat_lock = NewLock();
+}
+
+// Release the NtXxx function
+void NtFree()
+{
+ if (nat_lock == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(nat_lock);
+ nat_lock = NULL;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Nat.h b/src/Cedar/Nat.h
new file mode 100644
index 00000000..60a865ea
--- /dev/null
+++ b/src/Cedar/Nat.h
@@ -0,0 +1,291 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Nat.h
+// Header of Nat.c
+
+#ifndef NAT_H
+#define NAT_H
+
+// Constants
+#define NAT_CONFIG_FILE_NAME "@vpn_router.config" // NAT configuration file
+#define DEFAULT_NAT_ADMIN_PORT 2828 // Default port number for management
+#define NAT_ADMIN_PORT_LISTEN_INTERVAL 1000 // Interval for trying to open a port for management
+#define NAT_FILE_SAVE_INTERVAL (30 * 1000) // Interval to save
+
+
+// NAT object
+struct NAT
+{
+ LOCK *lock; // Lock
+ UCHAR HashedPassword[SHA1_SIZE]; // Administrative password
+ VH_OPTION Option; // Option
+ CEDAR *Cedar; // Cedar
+ UINT AdminPort; // Management port number
+ bool Online; // Online flag
+ VH *Virtual; // Virtual host object
+ CLIENT_OPTION *ClientOption; // Client Option
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ CFG_RW *CfgRw; // Config file R/W
+ THREAD *AdminAcceptThread; // Management connection reception thread
+ SOCK *AdminListenSock; // Management port socket
+ EVENT *HaltEvent; // Halting event
+ volatile bool Halt; // Halting flag
+ LIST *AdminList; // Management thread list
+ X *AdminX; // Server certificate for management
+ K *AdminK; // Server private key for management
+ SNAT *SecureNAT; // SecureNAT object
+};
+
+// NAT management connection
+struct NAT_ADMIN
+{
+ NAT *Nat; // NAT
+ SOCK *Sock; // Socket
+ THREAD *Thread; // Thread
+};
+
+// RPC_DUMMY
+struct RPC_DUMMY
+{
+ UINT DummyValue;
+};
+
+// RPC_NAT_STATUS
+struct RPC_NAT_STATUS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UINT NumTcpSessions; // Number of TCP sessions
+ UINT NumUdpSessions; // Ntmber of UDP sessions
+ UINT NumIcmpSessions; // Nymber of ICMP sessions
+ UINT NumDnsSessions; // Number of DNS sessions
+ UINT NumDhcpClients; // Number of DHCP clients
+ bool IsKernelMode; // Whether kernel mode
+};
+
+// RPC_NAT_INFO *
+struct RPC_NAT_INFO
+{
+ char NatProductName[128]; // Server product name
+ char NatVersionString[128]; // Server version string
+ char NatBuildInfoString[128]; // Server build information string
+ UINT NatVerInt; // Server version integer value
+ UINT NatBuildInt; // Server build number integer value
+ char NatHostName[MAX_HOST_NAME_LEN + 1]; // Server host name
+ OS_INFO OsInfo; // OS information
+ MEMINFO MemInfo; // Memory information
+};
+
+// RPC_ENUM_NAT_ITEM
+struct RPC_ENUM_NAT_ITEM
+{
+ UINT Id; // ID
+ UINT Protocol; // Protocol
+ UINT SrcIp; // Source IP address
+ char SrcHost[MAX_HOST_NAME_LEN + 1]; // Source host name
+ UINT SrcPort; // Source port number
+ UINT DestIp; // Destination IP address
+ char DestHost[MAX_HOST_NAME_LEN + 1]; // Destination host name
+ UINT DestPort; // Destination port number
+ UINT64 CreatedTime; // Connection time
+ UINT64 LastCommTime; // Last communication time
+ UINT64 SendSize; // Transmission size
+ UINT64 RecvSize; // Receive size
+ UINT TcpStatus; // TCP state
+};
+
+// RPC_ENUM_NAT *
+struct RPC_ENUM_NAT
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UINT NumItem; // Number of items
+ RPC_ENUM_NAT_ITEM *Items; // Item
+};
+
+// RPC_ENUM_DHCP_ITEM
+struct RPC_ENUM_DHCP_ITEM
+{
+ UINT Id; // ID
+ UINT64 LeasedTime; // Lease time
+ UINT64 ExpireTime; // Expiration date
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2]; // Padding
+ UINT IpAddress; // IP address
+ UINT Mask; // Subnet mask
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+};
+
+// RPC_ENUM_DHCP *
+struct RPC_ENUM_DHCP
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UINT NumItem; // Number of items
+ RPC_ENUM_DHCP_ITEM *Items; // Item
+};
+
+
+// Function prototype
+NAT *NiNewNat();
+NAT *NiNewNatEx(SNAT *snat, VH_OPTION *o);
+void NiFreeNat(NAT *n);
+void NiInitConfig(NAT *n);
+void NiFreeConfig(NAT *n);
+void NiInitDefaultConfig(NAT *n);
+void NiSetDefaultVhOption(NAT *n, VH_OPTION *o);
+void NiClearUnsupportedVhOptionForDynamicHub(VH_OPTION *o, bool initial);
+void NiWriteConfig(NAT *n);
+void NiWriteVhOption(NAT *n, FOLDER *root);
+void NiWriteVhOptionEx(VH_OPTION *o, FOLDER *root);
+void NiWriteClientData(NAT *n, FOLDER *root);
+void NiLoadVhOption(NAT *n, FOLDER *root);
+void NiLoadVhOptionEx(VH_OPTION *o, FOLDER *root);
+bool NiLoadConfig(NAT *n, FOLDER *root);
+void NiLoadClientData(NAT *n, FOLDER *root);
+void NiInitAdminAccept(NAT *n);
+void NiFreeAdminAccept(NAT *n);
+void NiListenThread(THREAD *thread, void *param);
+void NiAdminThread(THREAD *thread, void *param);
+void NiAdminMain(NAT *n, SOCK *s);
+PACK *NiRpcServer(RPC *r, char *name, PACK *p);
+
+RPC *NatAdminConnect(CEDAR *cedar, char *hostname, UINT port, void *hashed_password, UINT *err);
+void NatAdminDisconnect(RPC *r);
+
+void NtStartNat();
+void NtStopNat();
+void NtInit();
+void NtFree();
+
+
+UINT NtOnline(NAT *n, RPC_DUMMY *t);
+UINT NtOffline(NAT *n, RPC_DUMMY *t);
+UINT NtSetHostOption(NAT *n, VH_OPTION *t);
+UINT NtGetHostOption(NAT *n, VH_OPTION *t);
+UINT NtSetClientConfig(NAT *n, RPC_CREATE_LINK *t);
+UINT NtGetClientConfig(NAT *n, RPC_CREATE_LINK *t);
+UINT NtGetStatus(NAT *n, RPC_NAT_STATUS *t);
+UINT NtGetInfo(NAT *n, RPC_NAT_INFO *t);
+UINT NtEnumNatList(NAT *n, RPC_ENUM_NAT *t);
+UINT NtEnumDhcpList(NAT *n, RPC_ENUM_DHCP *t);
+UINT NtSetPassword(NAT *n, RPC_SET_PASSWORD *t);
+
+
+UINT NcOnline(RPC *r, RPC_DUMMY *t);
+UINT NcOffline(RPC *r, RPC_DUMMY *t);
+UINT NcSetHostOption(RPC *r, VH_OPTION *t);
+UINT NcGetHostOption(RPC *r, VH_OPTION *t);
+UINT NcSetClientConfig(RPC *r, RPC_CREATE_LINK *t);
+UINT NcGetClientConfig(RPC *r, RPC_CREATE_LINK *t);
+UINT NcGetStatus(RPC *r, RPC_NAT_STATUS *t);
+UINT NcGetInfo(RPC *r, RPC_NAT_INFO *t);
+UINT NcEnumNatList(RPC *r, RPC_ENUM_NAT *t);
+UINT NcEnumDhcpList(RPC *r, RPC_ENUM_DHCP *t);
+UINT NcSetPassword(RPC *r, RPC_SET_PASSWORD *t);
+
+
+
+
+void InRpcEnumDhcp(RPC_ENUM_DHCP *t, PACK *p);
+void OutRpcEnumDhcp(PACK *p, RPC_ENUM_DHCP *t);
+void FreeRpcEnumDhcp(RPC_ENUM_DHCP *t);
+void InRpcEnumNat(RPC_ENUM_NAT *t, PACK *p);
+void OutRpcEnumNat(PACK *p, RPC_ENUM_NAT *t);
+void FreeRpcEnumNat(RPC_ENUM_NAT *t);
+void InRpcNatInfo(RPC_NAT_INFO *t, PACK *p);
+void OutRpcNatInfo(PACK *p, RPC_NAT_INFO *t);
+void FreeRpcNatInfo(RPC_NAT_INFO *t);
+void InRpcNatStatus(RPC_NAT_STATUS *t, PACK *p);
+void OutRpcNatStatus(PACK *p, RPC_NAT_STATUS *t);
+void FreeRpcNatStatus(RPC_NAT_STATUS *t);
+void InVhOption(VH_OPTION *t, PACK *p);
+void OutVhOption(PACK *p, VH_OPTION *t);
+void InRpcDummy(RPC_DUMMY *t, PACK *p);
+void OutRpcDummy(PACK *p, RPC_DUMMY *t);
+
+
+
+
+#endif // NAT_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NativeStack.c b/src/Cedar/NativeStack.c
new file mode 100644
index 00000000..9689964e
--- /dev/null
+++ b/src/Cedar/NativeStack.c
@@ -0,0 +1,417 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NativeStack.c
+// Native IP stack
+
+#include "CedarPch.h"
+
+// Stack main thread
+void NsMainThread(THREAD *thread, void *param)
+{
+ NATIVE_STACK *a = (NATIVE_STACK *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ SOCKSET set;
+ bool err = false;
+ bool flush_tube;
+ LIST *recv_packets;
+ bool state_changed = false;
+
+ InitSockSet(&set);
+ AddSockSet(&set, a->Sock1);
+
+ if (a->Halt)
+ {
+ break;
+ }
+
+ // Pass to the IPC by receiving from the bridge
+LABEL_RESTART:
+ state_changed = false;
+ flush_tube = false;
+ while (true)
+ {
+ void *data;
+ UINT size;
+
+ size = EthGetPacket(a->Eth, &data);
+
+ if (size == INFINITE)
+ {
+ // Device error
+ err = true;
+ break;
+ }
+ else if (size == 0)
+ {
+ // Can not get any more
+ break;
+ }
+ else
+ {
+ // Pass the IPC socket
+ TubeSendEx(a->Sock1->SendTube, data, size, NULL, true);
+ Free(data);
+ flush_tube = true;
+ state_changed = true;
+ }
+ }
+
+ if (flush_tube)
+ {
+ TubeFlush(a->Sock1->SendTube);
+ }
+
+ // Pass to the bridge by receiving from IPC
+ recv_packets = NULL;
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(a->Sock1->RecvTube);
+
+ if (d == NULL)
+ {
+ break;
+ }
+
+ if (recv_packets == NULL)
+ {
+ recv_packets = NewListFast(NULL);
+ }
+
+ Add(recv_packets, d);
+
+ state_changed = true;
+ }
+ if (recv_packets != NULL)
+ {
+ UINT i;
+ UINT num = LIST_NUM(recv_packets);
+ void **data_array;
+ UINT *size_array;
+
+ data_array = Malloc(sizeof(void *) * num);
+ size_array = Malloc(sizeof(UINT) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ TUBEDATA *d = LIST_DATA(recv_packets, i);
+
+ data_array[i] = d->Data;
+ size_array[i] = d->DataSize;
+ }
+
+ EthPutPackets(a->Eth, num, data_array, size_array);
+
+ for (i = 0;i < num;i++)
+ {
+ TUBEDATA *d = LIST_DATA(recv_packets, i);
+
+ // Because the data buffer has been already released, not to release twice
+ d->Data = NULL;
+
+ FreeTubeData(d);
+ }
+
+ Free(data_array);
+ Free(size_array);
+
+ ReleaseList(recv_packets);
+ }
+
+ if (IsTubeConnected(a->Sock1->SendTube) == false || IsTubeConnected(a->Sock1->RecvTube) == false)
+ {
+ err = true;
+ }
+
+ if (err)
+ {
+ // An error has occured
+ Debug("Native Stack: Error !\n");
+ a->Halt = true;
+ continue;
+ }
+
+ if (state_changed)
+ {
+ goto LABEL_RESTART;
+ }
+
+ Select(&set, 1234, a->Cancel, NULL);
+ }
+
+ Disconnect(a->Sock1);
+ Disconnect(a->Sock2);
+}
+
+// Release the stack
+void FreeNativeStack(NATIVE_STACK *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (a->Ipc != NULL && IsZero(&a->CurrentDhcpOptionList, sizeof(a->CurrentDhcpOptionList)) == false)
+ {
+ IP dhcp_server;
+
+ UINTToIP(&dhcp_server, a->CurrentDhcpOptionList.ServerAddress);
+
+ IPCDhcpFreeIP(a->Ipc, &dhcp_server);
+ SleepThread(200);
+ }
+
+ a->Halt = true;
+ Cancel(a->Cancel);
+ Disconnect(a->Sock1);
+ Disconnect(a->Sock2);
+
+ WaitThread(a->MainThread, INFINITE);
+
+ ReleaseThread(a->MainThread);
+
+ CloseEth(a->Eth);
+ FreeIPC(a->Ipc);
+
+ ReleaseCancel(a->Cancel);
+
+ ReleaseSock(a->Sock1);
+ ReleaseSock(a->Sock2);
+
+ ReleaseCedar(a->Cedar);
+
+ Free(a);
+}
+
+// Create a new stack
+NATIVE_STACK *NewNativeStack(CEDAR *cedar, char *device_name, char *mac_address_seed)
+{
+ ETH *eth;
+ NATIVE_STACK *a;
+ IP localhost;
+ char tmp[64];
+ bool release_cedar = false;
+ // Validate arguments
+ if (device_name == NULL || mac_address_seed == NULL)
+ {
+ return NULL;
+ }
+
+ if (cedar == NULL)
+ {
+ cedar = NewCedar(NULL, NULL);
+ release_cedar = true;
+ }
+
+ GetLocalHostIP4(&localhost);
+
+ // Open the Eth device
+ eth = OpenEth(device_name, false, false, NULL);
+ if (eth == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(NATIVE_STACK));
+
+ NewSocketPair(&a->Sock1, &a->Sock2, &localhost, 1, &localhost, 1);
+
+ a->Cedar = cedar;
+ AddRef(a->Cedar->ref);
+
+ NsGenMacAddress(a->MacAddress, mac_address_seed, device_name);
+
+ BinToStr(tmp, sizeof(tmp), a->MacAddress, sizeof(a->MacAddress));
+ Debug("NewNativeStack: MAC Address = %s\n", tmp);
+
+ a->Ipc = NewIPCBySock(cedar, a->Sock2, a->MacAddress);
+
+ StrCpy(a->DeviceName, sizeof(a->DeviceName), device_name);
+
+ a->Eth = eth;
+ a->Cancel = EthGetCancel(eth);
+
+ a->MainThread = NewThread(NsMainThread, a);
+
+ if (release_cedar)
+ {
+ ReleaseCedar(cedar);
+ }
+
+ return a;
+}
+
+// Identify whether the specified MAC address is for the Native Stack which operate on the same host
+bool NsIsMacAddressOnLocalhost(UCHAR *mac)
+{
+ UCHAR tmp[2];
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ if (mac[0] != NS_MAC_ADDRESS_BYTE_1)
+ {
+ return false;
+ }
+
+ NsGenMacAddressSignatureForMachine(tmp, mac);
+
+ if (Cmp(mac + 4, tmp, 2) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Determine the last two bytes of the MAC address
+void NsGenMacAddressSignatureForMachine(UCHAR *dst_last_2, UCHAR *src_mac_addr_4)
+{
+ char machine_name[MAX_SIZE];
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (dst_last_2 == NULL || src_mac_addr_4 == NULL)
+ {
+ return;
+ }
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ b = NewBuf();
+ WriteBuf(b, src_mac_addr_4, 4);
+ WriteBufStr(b, machine_name);
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Copy(dst_last_2, hash, 2);
+}
+
+// Generate the MAC address
+void NsGenMacAddress(void *dest, char *mac_address_seed, char *device_name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR mac[6];
+ UCHAR hash[SHA1_SIZE];
+
+ Zero(tmp, sizeof(tmp));
+
+ StrCat(tmp, sizeof(tmp), mac_address_seed);
+ StrCat(tmp, sizeof(tmp), "@");
+ StrCat(tmp, sizeof(tmp), device_name);
+
+ Trim(tmp);
+
+ StrLower(tmp);
+
+ HashSha1(hash, tmp, StrLen(tmp));
+
+ mac[0] = NS_MAC_ADDRESS_BYTE_1;
+ mac[1] = hash[1];
+ mac[2] = hash[2];
+ mac[3] = hash[3];
+ mac[4] = hash[4];
+ mac[5] = hash[5];
+
+ NsGenMacAddressSignatureForMachine(mac + 4, mac);
+
+ Copy(dest, mac, 6);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NativeStack.h b/src/Cedar/NativeStack.h
new file mode 100644
index 00000000..f115e671
--- /dev/null
+++ b/src/Cedar/NativeStack.h
@@ -0,0 +1,123 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NativeStack.h
+// Header of NativeStack.c
+
+#ifndef NATIVESTACK_H
+#define NATIVESTACK_H
+
+//// Constants
+#define NS_MAC_ADDRESS_BYTE_1 0xDA // First byte of the MAC address
+
+//// Type
+struct NATIVE_STACK
+{
+ CEDAR *Cedar;
+ IPC *Ipc; // IPC object
+ char DeviceName[MAX_SIZE]; // Ethernet device name
+ THREAD *MainThread; // Main thread
+ bool Halt; // Halting flag
+ CANCEL *Cancel; // Cancel
+ UCHAR MacAddress[6]; // MAC address of the virtual host
+ ETH *Eth; // Eth device
+ SOCK *Sock1; // Sock1 (To be used in the bridge side)
+ SOCK *Sock2; // Sock2 (Used in the IPC side)
+ DHCP_OPTION_LIST CurrentDhcpOptionList; // Current DHCP options list
+ IP DnsServerIP; // IP address of the DNS server
+};
+
+
+//// Function prototype
+NATIVE_STACK *NewNativeStack(CEDAR *cedar, char *device_name, char *mac_address_seed);
+void FreeNativeStack(NATIVE_STACK *a);
+
+void NsGenMacAddress(void *dest, char *mac_address_seed, char *device_name);
+void NsMainThread(THREAD *thread, void *param);
+void NsGenMacAddressSignatureForMachine(UCHAR *dst_last_2, UCHAR *src_mac_addr_4);
+bool NsIsMacAddressOnLocalhost(UCHAR *mac);
+
+#endif // NATIVESTACK_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NullLan.c b/src/Cedar/NullLan.c
new file mode 100644
index 00000000..8f3fad40
--- /dev/null
+++ b/src/Cedar/NullLan.c
@@ -0,0 +1,256 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NullLan.c
+// Virtual LAN card device driver for testing
+
+#include "CedarPch.h"
+
+static UCHAR null_lan_broadcast_address[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+// Get the packet adapter
+PACKET_ADAPTER *NullGetPacketAdapter()
+{
+ PACKET_ADAPTER *pa = NewPacketAdapter(NullPaInit, NullPaGetCancel, NullPaGetNextPacket,
+ NullPaPutPacket, NullPaFree);
+
+ return pa;
+}
+
+// Packet generation thread
+void NullPacketGenerateThread(THREAD *t, void *param)
+{
+ NULL_LAN *n = (NULL_LAN *)param;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ Wait(n->Event, Rand32() % NULL_PACKET_GENERATE_INTERVAL);
+ if (n->Halt)
+ {
+ break;
+ }
+
+ LockQueue(n->PacketQueue);
+ {
+ UCHAR *data;
+ BLOCK *b;
+ UINT size = Rand32() % 1500 + 14;
+ data = Malloc(size);
+ Copy(data, null_lan_broadcast_address, 6);
+ Copy(data + 6, n->MacAddr, 6);
+ b = NewBlock(data, size, 0);
+ InsertQueue(n->PacketQueue, b);
+ }
+ UnlockQueue(n->PacketQueue);
+ Cancel(n->Cancel);
+ }
+}
+
+// Initialize the packet adapter
+bool NullPaInit(SESSION *s)
+{
+ NULL_LAN *n;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ n = ZeroMalloc(sizeof(NULL_LAN));
+ s->PacketAdapter->Param = (void *)n;
+
+ n->Cancel = NewCancel();
+ n->PacketQueue = NewQueue();
+ n->Event = NewEvent();
+
+ GenMacAddress(n->MacAddr);
+
+ n->PacketGeneratorThread = NewThread(NullPacketGenerateThread, n);
+
+ return true;
+}
+
+// Get the cancel object
+CANCEL *NullPaGetCancel(SESSION *s)
+{
+ // Validate arguments
+ NULL_LAN *n;
+ if (s == NULL || (n = s->PacketAdapter->Param) == NULL)
+ {
+ return NULL;
+ }
+
+ AddRef(n->Cancel->ref);
+
+ return n->Cancel;
+}
+
+// Get the next packet
+UINT NullPaGetNextPacket(SESSION *s, void **data)
+{
+ UINT size = 0;
+ // Validate arguments
+ NULL_LAN *n;
+ if (s == NULL || (n = s->PacketAdapter->Param) == NULL)
+ {
+ return INFINITE;
+ }
+
+ LockQueue(n->PacketQueue);
+ {
+ BLOCK *b = GetNext(n->PacketQueue);
+
+ if (b != NULL)
+ {
+ *data = b->Buf;
+ size = b->Size;
+ Free(b);
+ }
+ }
+ UnlockQueue(n->PacketQueue);
+
+ return size;
+}
+
+// Write the packet
+bool NullPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+ if (data == NULL)
+ {
+ return true;
+ }
+
+ // Packet ignored
+ Free(data);
+
+ return true;
+}
+
+// Release
+void NullPaFree(SESSION *s)
+{
+ // Validate arguments
+ NULL_LAN *n;
+ BLOCK *b;
+ if (s == NULL || (n = s->PacketAdapter->Param) == NULL)
+ {
+ return;
+ }
+
+ n->Halt = true;
+ Set(n->Event);
+
+ WaitThread(n->PacketGeneratorThread, INFINITE);
+ ReleaseThread(n->PacketGeneratorThread);
+
+ LockQueue(n->PacketQueue);
+ {
+ while (b = GetNext(n->PacketQueue))
+ {
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(n->PacketQueue);
+
+ ReleaseQueue(n->PacketQueue);
+
+ ReleaseCancel(n->Cancel);
+
+ ReleaseEvent(n->Event);
+
+ s->PacketAdapter->Param = NULL;
+ Free(n);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/NullLan.h b/src/Cedar/NullLan.h
new file mode 100644
index 00000000..3ccc068e
--- /dev/null
+++ b/src/Cedar/NullLan.h
@@ -0,0 +1,117 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NullLan.h
+// Header of NullLan.c
+
+#ifndef NULLLAN_H
+#define NULLLAN_H
+
+
+#define NULL_PACKET_GENERATE_INTERVAL 100000000 // Packet generation interval
+
+// NULL device structure
+struct NULL_LAN
+{
+ THREAD *PacketGeneratorThread;
+ CANCEL *Cancel;
+ QUEUE *PacketQueue;
+ volatile bool Halt;
+ EVENT *Event;
+ UCHAR MacAddr[6];
+ UCHAR Padding[2];
+};
+
+PACKET_ADAPTER *NullGetPacketAdapter();
+bool NullPaInit(SESSION *s);
+CANCEL *NullPaGetCancel(SESSION *s);
+UINT NullPaGetNextPacket(SESSION *s, void **data);
+bool NullPaPutPacket(SESSION *s, void *data, UINT size);
+void NullPaFree(SESSION *s);
+void NullPacketGenerateThread(THREAD *t, void *param);
+
+#endif // NULLAN_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c
new file mode 100644
index 00000000..beb2f3b4
--- /dev/null
+++ b/src/Cedar/Protocol.c
@@ -0,0 +1,6535 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Protocol.c
+// SoftEther protocol related routines
+
+#include "CedarPch.h"
+
+static UCHAR ssl_packet_start[3] = {0x17, 0x03, 0x00};
+
+
+// Convert the date of YYYYMMDD format to a number
+UINT64 ShortStrToDate64(char *str)
+{
+ UINT v;
+ SYSTEMTIME st;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ v = ToInt(str);
+
+ Zero(&st, sizeof(st));
+
+ st.wYear = (v % 100000000) / 10000;
+ st.wMonth = (v % 10000) / 100;
+ st.wDay = v % 100;
+
+ return SystemToUINT64(&st);
+}
+
+// Handle the response that is returned from the server in the update client
+void UpdateClientThreadProcessResults(UPDATE_CLIENT *c, BUF *b)
+{
+ bool exit = false;
+ // Validate arguments
+ if (c == NULL || b == NULL)
+ {
+ return;
+ }
+
+ SeekBufToBegin(b);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (StartWith(line, "#") == false && IsEmptyStr(line) == false)
+ {
+ TOKEN_LIST *t = ParseTokenWithNullStr(line, " \t");
+
+ if (t != NULL)
+ {
+ if (t->NumTokens >= 5)
+ {
+ if (StrCmpi(t->Token[0], c->FamilyName) == 0)
+ {
+ // Match
+ UINT64 date = ShortStrToDate64(t->Token[1]);
+ if (date != 0)
+ {
+ UINT build = ToInt(t->Token[2]);
+ if (build != 0)
+ {
+ if (build > c->MyBuild && build > c->LatestBuild && build > c->Setting.LatestIgnoreBuild)
+ {
+ c->Callback(c, build, date, t->Token[3], t->Token[4], &c->HaltFlag, c->Param);
+
+ c->LatestBuild = build;
+
+ exit = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+ }
+
+ Free(line);
+
+ if (exit)
+ {
+ break;
+ }
+ }
+}
+
+// Update client main process
+void UpdateClientThreadMain(UPDATE_CLIENT *c)
+{
+ char url[MAX_SIZE];
+ char id[MAX_SIZE];
+ URL_DATA data;
+ BUF *cert_hash;
+ UINT ret = 0;
+ BUF *recv;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Generate the URL
+ Format(url, sizeof(url), IsUseAlternativeHostname() ? UPDATE_SERVER_URL_CHINA : UPDATE_SERVER_URL_GLOBAL, c->FamilyName, c->SoftwareName, c->MyBuild, c->MyLanguage);
+
+ if (IsEmptyStr(c->ClientId) == false)
+ {
+ Format(id, sizeof(id), "&id=%s", c->ClientId);
+ StrCat(url, sizeof(url), id);
+ }
+
+ // Get a text file at this URL
+ if (ParseUrl(&data, url, false, NULL) == false)
+ {
+ return;
+ }
+
+ cert_hash = StrToBin(UPDATE_SERVER_CERT_HASH);
+
+ recv = HttpRequest(&data, NULL, UPDATE_CONNECT_TIMEOUT, UPDATE_COMM_TIMEOUT, &ret, false, NULL, NULL,
+ NULL, ((cert_hash != NULL && cert_hash->Size == SHA1_SIZE) ? cert_hash->Buf : NULL));
+
+ FreeBuf(cert_hash);
+
+ if (recv != NULL)
+ {
+ UpdateClientThreadProcessResults(c, recv);
+
+ FreeBuf(recv);
+ }
+}
+
+// Update client main thread
+void UpdateClientThreadProc(THREAD *thread, void *param)
+{
+ UPDATE_CLIENT *c = (UPDATE_CLIENT *)param;
+ bool first_loop = true;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ // Termination check
+ if (c->HaltFlag)
+ {
+ break;
+ }
+
+ if (first_loop == false)
+ {
+ // Wait for the foreground
+ if (c->IsForegroundCb != NULL)
+ {
+ while (true)
+ {
+ if (c->HaltFlag)
+ {
+ break;
+ }
+
+ if (c->IsForegroundCb(c, c->Param))
+ {
+ break;
+ }
+
+ Wait(c->HaltEvent, 1000);
+ }
+ }
+ }
+
+ first_loop = false;
+
+ if (c->HaltFlag)
+ {
+ break;
+ }
+
+ if (c->Setting.DisableCheck == false)
+ {
+ UpdateClientThreadMain(c);
+ }
+
+ // Wait until the next attempt
+ Wait(c->HaltEvent, GenRandInterval(UPDATE_CHECK_INTERVAL_MIN, UPDATE_CHECK_INTERVAL_MAX));
+ }
+}
+
+// Update the configuration of the update client
+void SetUpdateClientSetting(UPDATE_CLIENT *c, UPDATE_CLIENT_SETTING *s)
+{
+ bool old_disable;
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ old_disable = c->Setting.DisableCheck;
+
+ Copy(&c->Setting, s, sizeof(UPDATE_CLIENT_SETTING));
+
+ Set(c->HaltEvent);
+}
+
+// Start the update client
+UPDATE_CLIENT *NewUpdateClient(UPDATE_NOTIFY_PROC *cb, UPDATE_ISFOREGROUND_PROC *isforeground_cb, void *param, char *family_name, char *software_name, wchar_t *software_title, UINT my_build, UINT64 my_date, char *my_lang, UPDATE_CLIENT_SETTING *current_setting, char *client_id)
+{
+ UPDATE_CLIENT *c;
+ // Validate arguments
+ if (family_name == NULL || software_title == NULL || software_name == NULL || my_build == 0 ||
+ my_lang == NULL || current_setting == NULL || cb == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(UPDATE_CLIENT));
+
+ c->Callback = cb;
+ c->IsForegroundCb = isforeground_cb;
+
+ StrCpy(c->ClientId, sizeof(c->ClientId), client_id);
+ StrCpy(c->FamilyName, sizeof(c->FamilyName), family_name);
+ StrCpy(c->SoftwareName, sizeof(c->SoftwareName), software_name);
+ UniStrCpy(c->SoftwareTitle, sizeof(c->SoftwareTitle), software_title);
+ c->MyBuild = my_build;
+ c->MyDate = my_date;
+ StrCpy(c->MyLanguage, sizeof(c->MyLanguage), my_lang);
+
+ Copy(&c->Setting, current_setting, sizeof(c->Setting));
+
+ c->Param = param;
+
+ c->HaltEvent = NewEvent();
+
+ // Create a thread
+ c->Thread = NewThread(UpdateClientThreadProc, c);
+
+ return c;
+}
+
+// Terminate the update client
+void FreeUpdateClient(UPDATE_CLIENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Thread stop
+ c->HaltFlag = true;
+ Set(c->HaltEvent);
+
+ // Wait for thread termination
+ WaitThread(c->Thread, INFINITE);
+
+ ReleaseThread(c->Thread);
+ ReleaseEvent(c->HaltEvent);
+
+ Free(c);
+}
+
+// Generate unique IDs for each machine
+void GenerateMachineUniqueHash(void *data)
+{
+ BUF *b;
+ char name[64];
+ char ip_str[64];
+ IP ip;
+ OS_INFO *osinfo;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ GetMachineName(name, sizeof(name));
+ GetMachineIp(&ip);
+ IPToStr(ip_str, sizeof(ip_str), &ip);
+
+ osinfo = GetOsInfo();
+
+ WriteBuf(b, name, StrLen(name));
+ WriteBuf(b, ip_str, StrLen(ip_str));
+
+ WriteBuf(b, &osinfo->OsType, sizeof(osinfo->OsType));
+ WriteBuf(b, osinfo->KernelName, StrLen(osinfo->KernelName));
+ WriteBuf(b, osinfo->KernelVersion, StrLen(osinfo->KernelVersion));
+ WriteBuf(b, osinfo->OsProductName, StrLen(osinfo->OsProductName));
+ WriteBuf(b, &osinfo->OsServicePack, sizeof(osinfo->OsServicePack));
+ WriteBuf(b, osinfo->OsSystemName, StrLen(osinfo->OsSystemName));
+ WriteBuf(b, osinfo->OsVendorName, StrLen(osinfo->OsVendorName));
+ WriteBuf(b, osinfo->OsVersion, StrLen(osinfo->OsVersion));
+
+ Hash(data, b->Buf, b->Size, true);
+
+ FreeBuf(b);
+}
+
+// Convert a node information to a string
+void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info)
+{
+ char client_ip[128], server_ip[128], proxy_ip[128], unique_id[128];
+ // Validate arguments
+ if (str == NULL || info == NULL)
+ {
+ return;
+ }
+
+ IPToStr4or6(client_ip, sizeof(client_ip), info->ClientIpAddress, info->ClientIpAddress6);
+ IPToStr4or6(server_ip, sizeof(server_ip), info->ServerIpAddress, info->ServerIpAddress6);
+ IPToStr4or6(proxy_ip, sizeof(proxy_ip), info->ProxyIpAddress, info->ProxyIpAddress6);
+ BinToStr(unique_id, sizeof(unique_id), info->UniqueId, sizeof(info->UniqueId));
+
+ UniFormat(str, size, _UU("LS_NODE_INFO_TAG"), info->ClientProductName,
+ Endian32(info->ClientProductVer), Endian32(info->ClientProductBuild),
+ info->ServerProductName, Endian32(info->ServerProductVer), Endian32(info->ServerProductBuild),
+ info->ClientOsName, info->ClientOsVer, info->ClientOsProductId,
+ info->ClientHostname, client_ip, Endian32(info->ClientPort),
+ info->ServerHostname, server_ip, Endian32(info->ServerPort),
+ info->ProxyHostname, proxy_ip, Endian32(info->ProxyPort),
+ info->HubName, unique_id);
+}
+
+// Comparison of node information
+bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b)
+{
+ // Validate arguments
+ if (a == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ if (StrCmp(a->ClientProductName, b->ClientProductName) != 0)
+ {
+ return false;
+ }
+ if (a->ClientProductVer != b->ClientProductVer)
+ {
+ return false;
+ }
+ if (a->ClientProductBuild != b->ClientProductBuild)
+ {
+ return false;
+ }
+ if (StrCmp(a->ServerProductName, b->ServerProductName) != 0)
+ {
+ return false;
+ }
+ if (a->ServerProductVer != b->ServerProductVer)
+ {
+ return false;
+ }
+ if (a->ServerProductBuild != b->ServerProductBuild)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsName, b->ClientOsName) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsVer, b->ClientOsVer) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsProductId, b->ClientOsProductId) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientHostname, b->ClientHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ClientIpAddress != b->ClientIpAddress)
+ {
+ return false;
+ }
+ if (StrCmp(a->ServerHostname, b->ServerHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ServerIpAddress != b->ServerIpAddress)
+ {
+ return false;
+ }
+ if (a->ServerPort != b->ServerPort)
+ {
+ return false;
+ }
+ if (StrCmp(a->ProxyHostname, b->ProxyHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ProxyIpAddress != b->ProxyIpAddress)
+ {
+ return false;
+ }
+ if (a->ProxyPort != b->ProxyPort)
+ {
+ return false;
+ }
+ if (StrCmp(a->HubName, b->HubName) != 0)
+ {
+ return false;
+ }
+ if (Cmp(a->UniqueId, b->UniqueId, 16) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Accept the password change
+UINT ChangePasswordAccept(CONNECTION *c, PACK *p)
+{
+ CEDAR *cedar;
+ UCHAR random[SHA1_SIZE];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ char username[MAX_USERNAME_LEN + 1];
+ UCHAR secure_old_password[SHA1_SIZE];
+ UCHAR new_password[SHA1_SIZE];
+ UCHAR new_password_ntlm[SHA1_SIZE];
+ UCHAR check_secure_old_password[SHA1_SIZE];
+ UINT ret = ERR_NO_ERROR;
+ HUB *hub;
+ bool save = false;
+ // Validate arguments
+ if (c == NULL || p == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Copy(random, c->Random, SHA1_SIZE);
+ if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false ||
+ PackGetStr(p, "username", username, sizeof(username)) == false ||
+ PackGetData2(p, "secure_old_password", secure_old_password, sizeof(secure_old_password)) == false ||
+ PackGetData2(p, "new_password", new_password, sizeof(new_password)) == false)
+ {
+ return ERR_PROTOCOL_ERROR;
+ }
+
+ if (PackGetData2(p, "new_password_ntlm", new_password_ntlm, MD5_SIZE) == false)
+ {
+ Zero(new_password_ntlm, sizeof(new_password_ntlm));
+ }
+
+ cedar = c->Cedar;
+
+ LockHubList(cedar);
+ {
+ hub = GetHub(cedar, hubname);
+ }
+ UnlockHubList(cedar);
+
+ if (hub == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ if (GetHubAdminOption(hub, "deny_change_user_password") != 0)
+ {
+ ReleaseHub(hub);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ IPToStr(tmp, sizeof(tmp), &c->FirstSock->RemoteIP);
+ HLog(hub, "LH_CHANGE_PASSWORD_1", c->Name, tmp);
+
+ AcLock(hub);
+ {
+ USER *u = AcGetUser(hub, username);
+ if (u == NULL)
+ {
+ HLog(hub, "LH_CHANGE_PASSWORD_2", c->Name, username);
+ ret = ERR_OLD_PASSWORD_WRONG;
+ }
+ else
+ {
+ Lock(u->lock);
+ {
+ if (u->AuthType != AUTHTYPE_PASSWORD)
+ {
+ // Not a password authentication
+ HLog(hub, "LH_CHANGE_PASSWORD_3", c->Name, username);
+ ret = ERR_USER_AUTHTYPE_NOT_PASSWORD;
+ }
+ else
+ {
+ bool fix_password = false;
+ if (u->Policy != NULL)
+ {
+ fix_password = u->Policy->FixPassword;
+ }
+ else
+ {
+ if (u->Group != NULL)
+ {
+ if (u->Group->Policy != NULL)
+ {
+ fix_password = u->Group->Policy->FixPassword;
+ }
+ }
+ }
+ if (fix_password == false)
+ {
+ // Confirmation of the old password
+ AUTHPASSWORD *pw = (AUTHPASSWORD *)u->AuthData;
+
+ SecurePassword(check_secure_old_password, pw->HashedKey, random);
+ if (Cmp(check_secure_old_password, secure_old_password, SHA1_SIZE) != 0)
+ {
+ // Old password is incorrect
+ ret = ERR_OLD_PASSWORD_WRONG;
+ HLog(hub, "LH_CHANGE_PASSWORD_4", c->Name, username);
+ }
+ else
+ {
+ // Write a new password
+ if (Cmp(pw->HashedKey, new_password, SHA1_SIZE) != 0 || IsZero(pw->NtLmSecureHash, MD5_SIZE))
+ {
+ Copy(pw->HashedKey, new_password, SHA1_SIZE);
+ Copy(pw->NtLmSecureHash, new_password_ntlm, MD5_SIZE);
+ }
+ HLog(hub, "LH_CHANGE_PASSWORD_5", c->Name, username);
+ save = true;
+ }
+ }
+ else
+ {
+ // Password change is prohibited
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ }
+ }
+ Unlock(u->lock);
+
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(hub);
+ ReleaseHub(hub);
+ }
+
+ return ret;
+}
+
+// Change the password
+UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass)
+{
+ UINT ret = ERR_NO_ERROR;
+ UCHAR old_password[SHA1_SIZE];
+ UCHAR secure_old_password[SHA1_SIZE];
+ UCHAR new_password[SHA1_SIZE];
+ UCHAR new_password_ntlm[MD5_SIZE];
+ SOCK *sock;
+ SESSION *s;
+ // Validate arguments
+ if (cedar == NULL || o == NULL || hubname == NULL || username == NULL || old_pass == NULL || new_pass == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+
+ // Create a session
+ s = NewRpcSessionEx(cedar, o, &ret, NULL);
+
+ if (s != NULL)
+ {
+ PACK *p = NewPack();
+
+ sock = s->Connection->FirstSock;
+
+ HashPassword(old_password, username, old_pass);
+ SecurePassword(secure_old_password, old_password, s->Connection->Random);
+ HashPassword(new_password, username, new_pass);
+ GenerateNtPasswordHash(new_password_ntlm, new_pass);
+
+ PackAddClientVersion(p, s->Connection);
+
+ PackAddStr(p, "method", "password");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddData(p, "secure_old_password", secure_old_password, SHA1_SIZE);
+ PackAddData(p, "new_password", new_password, SHA1_SIZE);
+ PackAddData(p, "new_password_ntlm", new_password_ntlm, MD5_SIZE);
+
+ if (HttpClientSend(sock, p))
+ {
+ PACK *p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ ret = ERR_DISCONNECTED;
+ }
+ else
+ {
+ ret = GetErrorFromPack(p);
+ }
+ FreePack(p);
+ }
+ else
+ {
+ ret = ERR_DISCONNECTED;
+ }
+ FreePack(p);
+
+ ReleaseSession(s);
+ }
+
+ return ret;
+}
+
+// Enumerate HUBs
+TOKEN_LIST *EnumHub(SESSION *s)
+{
+ SOCK *sock;
+ TOKEN_LIST *ret;
+ PACK *p;
+ UINT num;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || s->Connection == NULL)
+ {
+ return NULL;
+ }
+
+ sock = s->Connection->FirstSock;
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+
+ // Set the Timeout
+ SetTimeout(sock, 10000);
+
+ p = NewPack();
+ PackAddStr(p, "method", "enum_hub");
+
+ PackAddClientVersion(p, s->Connection);
+
+ if (HttpClientSend(sock, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+ FreePack(p);
+
+ p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ num = PackGetInt(p, "NumHub");
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = ZeroMalloc(sizeof(char *) * num);
+ for (i = 0;i < num;i++)
+ {
+ char tmp[MAX_SIZE];
+ if (PackGetStrEx(p, "HubName", tmp, sizeof(tmp), i))
+ {
+ ret->Token[i] = CopyStr(tmp);
+ }
+ }
+ FreePack(p);
+
+ return ret;
+}
+
+// Server accepts a connection from client
+bool ServerAccept(CONNECTION *c)
+{
+ bool ret = false;
+ UINT err;
+ PACK *p;
+ char username_real[MAX_SIZE];
+ char method[MAX_SIZE];
+ char hubname[MAX_SIZE];
+ char username[MAX_SIZE];
+ char groupname[MAX_SIZE];
+ UCHAR session_key[SHA1_SIZE];
+ UCHAR ticket[SHA1_SIZE];
+ RC4_KEY_PAIR key_pair;
+ UINT authtype;
+ POLICY *policy;
+ HUB *hub;
+ SESSION *s = NULL;
+ UINT64 user_expires = 0;
+ bool use_encrypt;
+ bool use_compress;
+ bool half_connection;
+ UINT adjust_mss;
+ bool use_udp_acceleration_client;
+ bool support_hmac_on_udp_acceleration_client = false;
+ bool support_udp_accel_fast_disconnect_detect;
+ bool use_hmac_on_udp_acceleration = false;
+ IP udp_acceleration_client_ip;
+ UCHAR udp_acceleration_client_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
+ UINT udp_acceleration_client_port;
+ bool use_fast_rc4;
+ bool admin_mode = false;
+ UINT direction;
+ UINT max_connection;
+ UINT timeout;
+ bool no_reconnect_to_session = false;
+ bool farm_controller = false;
+ bool farm_member = false;
+ bool farm_mode = false;
+ bool require_bridge_routing_mode;
+ bool require_monitor_mode;
+ bool support_bulk_on_rudp = false;
+ bool support_hmac_on_bulk_of_rudp = false;
+ bool support_udp_recovery = false;
+ bool enable_bulk_on_rudp = false;
+ bool enable_udp_recovery = false;
+ bool enable_hmac_on_bulk_of_rudp = false;
+ bool use_client_license = false, use_bridge_license = false;
+ bool local_host_session = false;
+ char sessionname[MAX_SESSION_NAME_LEN + 1];
+ bool is_server_or_bridge = false;
+ bool qos = false;
+ bool cluster_dynamic_secure_nat = false;
+ bool no_save_password = false;
+ NODE_INFO node;
+ wchar_t *msg = NULL;
+ USER *loggedin_user_object = NULL;
+ FARM_MEMBER *f = NULL;
+ SERVER *server = NULL;
+ POLICY ticketed_policy;
+ UINT64 timestamp;
+ UCHAR unique[SHA1_SIZE], unique2[SHA1_SIZE];
+ CEDAR *cedar;
+ RPC_WINVER winver;
+ UINT client_id;
+ bool no_more_users_in_server = false;
+ UCHAR mschap_v2_server_response_20[20];
+ UINT ms_chap_error = 0;
+ bool is_empty_password = false;
+ char *error_detail = NULL;
+ char *error_detail_2 = NULL;
+ char ctoken_hash_str[64];
+
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Zero(ctoken_hash_str, sizeof(ctoken_hash_str));
+
+ Zero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
+
+ Zero(&udp_acceleration_client_ip, sizeof(udp_acceleration_client_ip));
+ udp_acceleration_client_port = 0;
+ Zero(udp_acceleration_client_key, sizeof(udp_acceleration_client_key));
+
+ Zero(&winver, sizeof(winver));
+
+ StrCpy(groupname, sizeof(groupname), "");
+ StrCpy(sessionname, sizeof(sessionname), "");
+
+ if (IsZero(c->CToken_Hash, SHA1_SIZE) == false)
+ {
+ BinToStr(ctoken_hash_str, sizeof(ctoken_hash_str), c->CToken_Hash, SHA1_SIZE);
+ }
+
+ cedar = c->Cedar;
+
+ // Get the license status
+
+ no_more_users_in_server = SiTooManyUserObjectsInServer(cedar->Server, true);
+
+ c->Status = CONNECTION_STATUS_NEGOTIATION;
+
+ if (c->Cedar->Server != NULL)
+ {
+ SERVER *s = c->Cedar->Server;
+ server = s;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ farm_member = true;
+ farm_mode = true;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ farm_controller = true;
+ farm_mode = true;
+ }
+ }
+
+ // Receive the signature
+ Debug("Downloading Signature...\n");
+ error_detail_2 = NULL;
+ if (ServerDownloadSignature(c, &error_detail_2) == false)
+ {
+ if (error_detail_2 == NULL)
+ {
+ error_detail = "ServerDownloadSignature";
+ }
+ else
+ {
+ error_detail = error_detail_2;
+ }
+ goto CLEANUP;
+ }
+
+ // Send a Hello packet
+ Debug("Uploading Hello...\n");
+ if (ServerUploadHello(c) == false)
+ {
+ error_detail = "ServerUploadHello";
+ goto CLEANUP;
+ }
+
+ // Receive the authentication data
+ Debug("Auth...\n");
+
+ p = HttpServerRecv(c->FirstSock);
+ if (p == NULL)
+ {
+ // The connection disconnected
+ c->Err = ERR_DISCONNECTED;
+ error_detail = "RecvAuth1";
+ goto CLEANUP;
+ }
+
+ if (err = GetErrorFromPack(p))
+ {
+ // An error has occured
+ FreePack(p);
+ c->Err = err;
+ error_detail = "RecvAuth2";
+ goto CLEANUP;
+ }
+
+ // Get the method
+ if (GetMethodFromPack(p, method, sizeof(method)) == false)
+ {
+ // Protocol error
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ error_detail = "GetMethodFromPack";
+ goto CLEANUP;
+ }
+
+ // Brand string for the connection limit
+ {
+ char tmp[20];
+ char *branded_ctos = _SS("BRANDED_C_TO_S");
+ PackGetStr(p, "branded_ctos", tmp, sizeof(tmp));
+
+ if(StrCmpi(method, "login") == 0 && StrLen(branded_ctos) > 0 && StrCmpi(branded_ctos, tmp) != 0)
+ {
+ FreePack(p);
+ c->Err = ERR_BRANDED_C_TO_S;
+ goto CLEANUP;
+ }
+ }
+
+ // Time inspection
+ timestamp = PackGetInt64(p, "timestamp");
+ if (timestamp != 0)
+ {
+ UINT64 now = SystemTime64();
+ UINT64 abs;
+ if (now >= timestamp)
+ {
+ abs = now - timestamp;
+ }
+ else
+ {
+ abs = timestamp - now;
+ }
+
+ if (abs > ALLOW_TIMESTAMP_DIFF)
+ {
+ // Time difference is too large
+ FreePack(p);
+ c->Err = ERR_BAD_CLOCK;
+ error_detail = "ERR_BAD_CLOCK";
+ goto CLEANUP;
+ }
+ }
+
+ // Get the client version
+ PackGetStr(p, "client_str", c->ClientStr, sizeof(c->ClientStr));
+ c->ClientVer = PackGetInt(p, "client_ver");
+ c->ClientBuild = PackGetInt(p, "client_build");
+
+ if (SearchStrEx(c->ClientStr, "server", 0, false) != INFINITE ||
+ SearchStrEx(c->ClientStr, "bridge", 0, false) != INFINITE)
+ {
+ is_server_or_bridge = true;
+ }
+
+ // Get the client Windows version
+ InRpcWinVer(&winver, p);
+
+ DecrementNoSsl(c->Cedar, &c->FirstSock->RemoteIP, 2);
+
+ if (StrCmpi(method, "login") == 0)
+ {
+ bool auth_ret = false;
+
+ Debug("Login...\n");
+ c->Status = CONNECTION_STATUS_USERAUTH;
+
+ c->Type = CONNECTION_TYPE_LOGIN;
+
+ if (no_more_users_in_server)
+ {
+ // There are many users than are allowed in the VPN Server
+ FreePack(p);
+ c->Err = ERR_TOO_MANY_USER;
+ error_detail = "ERR_TOO_MANY_USER";
+ goto CLEANUP;
+ }
+
+ // Such as the client name
+ if (PackGetStr(p, "hello", c->ClientStr, sizeof(c->ClientStr)) == false)
+ {
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), "Unknown");
+ }
+ c->ServerVer = CEDAR_VER;
+ c->ServerBuild = CEDAR_BUILD;
+
+ // Get the NODE_INFO
+ Zero(&node, sizeof(node));
+ InRpcNodeInfo(&node, p);
+
+ // Protocol
+ c->Protocol = GetProtocolFromPack(p);
+ if (c->Protocol == CONNECTION_UDP)
+ {
+ // Release the structure of the TCP connection
+ if (c->Tcp)
+ {
+ ReleaseList(c->Tcp->TcpSockList);
+ Free(c->Tcp);
+ }
+ }
+
+ if (GetServerCapsBool(c->Cedar->Server, "b_vpn_client_connect") == false)
+ {
+ // VPN client is unable to connect
+ FreePack(p);
+ c->Err = ERR_NOT_SUPPORTED;
+ goto CLEANUP;
+ }
+
+
+
+ // Login
+ if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
+ {
+ // Protocol error
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ error_detail = "GetHubnameAndUsernameFromPack";
+ goto CLEANUP;
+ }
+
+ if (farm_member)
+ {
+ bool ok = false;
+ UINT authtype;
+
+ authtype = GetAuthTypeFromPack(p);
+ if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
+ authtype == AUTHTYPE_PASSWORD)
+ {
+ ok = true;
+ }
+
+ if (authtype == AUTHTYPE_TICKET)
+ {
+ ok = true;
+ }
+
+ if (ok == false)
+ {
+ // Logging on directly to server farm members by
+ // non-Administrators are prohibited
+ FreePack(p);
+ SLog(c->Cedar, "LS_FARMMEMBER_NOT_ADMIN", c->Name, hubname, ADMINISTRATOR_USERNAME, username);
+ c->Err = ERR_ACCESS_DENIED;
+ goto CLEANUP;
+ }
+ }
+
+ Debug("Username = %s, HubName = %s\n", username, hubname);
+ LockHubList(c->Cedar);
+ {
+ hub = GetHub(c->Cedar, hubname);
+ }
+ UnlockHubList(c->Cedar);
+ if (hub == NULL)
+ {
+ // The HUB does not exist
+ FreePack(p);
+ c->Err = ERR_HUB_NOT_FOUND;
+ SLog(c->Cedar, "LS_HUB_NOT_FOUND", c->Name, hubname);
+ error_detail = "ERR_HUB_NOT_FOUND";
+ goto CLEANUP;
+ }
+
+
+ Lock(hub->lock);
+ {
+ UINT cert_size = 0;
+ void *cert_buf = NULL;
+ USER *user;
+ USERGROUP *group;
+ char plain_password[MAX_PASSWORD_LEN + 1];
+ if (hub->Halt || hub->Offline)
+ {
+ // HUB is off-line
+ FreePack(p);
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_STOPPING;
+ goto CLEANUP;
+ }
+
+ // Get the various flags
+ use_encrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
+ use_compress = PackGetInt(p, "use_compress") == 0 ? false : true;
+ max_connection = PackGetInt(p, "max_connection");
+ half_connection = PackGetInt(p, "half_connection") == 0 ? false : true;
+ use_fast_rc4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
+ qos = PackGetInt(p, "qos") ? true : false;
+ client_id = PackGetInt(p, "client_id");
+ adjust_mss = PackGetInt(p, "adjust_mss");
+ use_udp_acceleration_client = PackGetBool(p, "use_udp_acceleration");
+ support_hmac_on_udp_acceleration_client = PackGetBool(p, "support_hmac_on_udp_acceleration");
+ support_udp_accel_fast_disconnect_detect = PackGetBool(p, "support_udp_accel_fast_disconnect_detect");
+ support_bulk_on_rudp = PackGetBool(p, "support_bulk_on_rudp");
+ support_hmac_on_bulk_of_rudp = PackGetBool(p, "support_hmac_on_bulk_of_rudp");
+ support_udp_recovery = PackGetBool(p, "support_udp_recovery");
+
+ if (c->IsInProc)
+ {
+ char tmp[MAX_SIZE];
+ PackGetStr(p, "inproc_postfix", c->InProcPrefix, sizeof(c->InProcPrefix));
+ Zero(tmp, sizeof(tmp));
+ PackGetStr(p, "inproc_cryptname", tmp, sizeof(tmp));
+
+ if (c->FirstSock != NULL)
+ {
+ if (IsEmptyStr(c->InProcPrefix) == false)
+ {
+ Format(c->FirstSock->UnderlayProtocol, sizeof(c->FirstSock->UnderlayProtocol),
+ SOCK_UNDERLAY_INPROC_EX, c->InProcPrefix);
+ }
+ }
+
+ if (c->CipherName != NULL)
+ {
+ Free(c->CipherName);
+ }
+
+ c->CipherName = NULL;
+
+ if (IsEmptyStr(tmp) == false)
+ {
+ c->CipherName = CopyStr(tmp);
+ use_encrypt = true;
+ }
+
+ use_udp_acceleration_client = false;
+ }
+ else
+ {
+ if (c->CipherName != NULL)
+ {
+ Free(c->CipherName);
+ }
+ c->CipherName = NULL;
+
+ if (c->FirstSock != NULL && IsEmptyStr(c->FirstSock->CipherName) == false)
+ {
+ c->CipherName = CopyStr(c->FirstSock->CipherName);
+ }
+ }
+
+ if (support_bulk_on_rudp && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket &&
+ c->FirstSock->BulkRecvKey != NULL && c->FirstSock->BulkSendKey != NULL)
+ {
+ // RAllow UDP bulk transfer if the client side supports
+ // in the case of using R-UDP Socket
+ enable_bulk_on_rudp = true;
+
+ enable_hmac_on_bulk_of_rudp = support_hmac_on_bulk_of_rudp;
+ }
+
+ if (support_udp_recovery && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket)
+ {
+ // Allow UDP recovery
+ enable_udp_recovery = true;
+ }
+
+ if (use_udp_acceleration_client)
+ {
+ // Get the parameters for the UDP acceleration function
+ if (PackGetIp(p, "udp_acceleration_client_ip", &udp_acceleration_client_ip) == false ||
+ PackGetData2(p, "udp_acceleration_client_key", udp_acceleration_client_key, UDP_ACCELERATION_COMMON_KEY_SIZE) == false)
+ {
+ use_udp_acceleration_client = false;
+ }
+ else
+ {
+ if (IsZeroIp(&udp_acceleration_client_ip))
+ {
+ Copy(&udp_acceleration_client_ip, &c->FirstSock->RemoteIP, sizeof(IP));
+ }
+ udp_acceleration_client_port = PackGetInt(p, "udp_acceleration_client_port");
+ if (udp_acceleration_client_port == 0)
+ {
+ use_udp_acceleration_client = false;
+ }
+ }
+
+ use_hmac_on_udp_acceleration = support_hmac_on_udp_acceleration_client;
+ }
+
+ Debug("use_udp_acceleration_client = %u\n", use_udp_acceleration_client);
+ Debug("use_hmac_on_udp_acceleration = %u\n", use_hmac_on_udp_acceleration);
+
+ // Request mode
+ require_bridge_routing_mode = PackGetBool(p, "require_bridge_routing_mode");
+ require_monitor_mode = PackGetBool(p, "require_monitor_mode");
+ if (require_monitor_mode)
+ {
+ qos = false;
+ }
+
+ if (is_server_or_bridge)
+ {
+ require_bridge_routing_mode = true;
+ }
+
+ // Client unique ID
+ Zero(unique, sizeof(unique));
+ if (PackGetDataSize(p, "unique_id") == SHA1_SIZE)
+ {
+ PackGetData(p, "unique_id", unique);
+ }
+
+ // Get the authentication method
+ authtype = GetAuthTypeFromPack(p);
+
+ if (1)
+ {
+ // Log
+ char ip1[64], ip2[64], verstr[64];
+ wchar_t *authtype_str = _UU("LH_AUTH_UNKNOWN");
+ switch (authtype)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ authtype_str = _UU("LH_AUTH_ANONYMOUS");
+ break;
+ case CLIENT_AUTHTYPE_PASSWORD:
+ authtype_str = _UU("LH_AUTH_PASSWORD");
+ break;
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ authtype_str = _UU("LH_AUTH_PLAIN_PASSWORD");
+ break;
+ case CLIENT_AUTHTYPE_CERT:
+ authtype_str = _UU("LH_AUTH_CERT");
+ break;
+ case AUTHTYPE_TICKET:
+ authtype_str = _UU("LH_AUTH_TICKET");
+ break;
+ }
+ IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
+ IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
+
+ Format(verstr, sizeof(verstr), "%u.%02u", c->ClientVer / 100, c->ClientVer % 100);
+
+ HLog(hub, "LH_CONNECT_CLIENT", c->Name, ip1, c->FirstSock->RemoteHostname, c->FirstSock->RemotePort,
+ c->ClientStr, verstr, c->ClientBuild, authtype_str, username);
+ }
+
+ // Attempt an anonymous authentication first
+ auth_ret = SamAuthUserByAnonymous(hub, username);
+
+ if (auth_ret)
+ {
+ if (c->IsInProc)
+ {
+ IPC_MSCHAP_V2_AUTHINFO mschap;
+ char password_tmp[MAX_SIZE];
+
+ Zero(&mschap, sizeof(mschap));
+
+ Zero(password_tmp, sizeof(password_tmp));
+ PackGetStr(p, "plain_password", password_tmp, sizeof(password_tmp));
+
+ if (ParseAndExtractMsChapV2InfoFromPassword(&mschap, password_tmp))
+ {
+ // Because the server don't know the NTLM hashed password, the bet to the possibility of
+ // the same character to the user name and empty, search a password of different
+ // versions of the upper and lower case characters in the case of anonymous authentication.
+ // Returns the MS-CHAPv2 response by using the password if there is a match.
+ // Fail the authentication if no match is found.
+ // (Because, if return a false MS-CHAPv2 Response, PPP client cause an error)
+ LIST *o = NewListFast(NULL);
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ char tmp3[MAX_SIZE];
+ char tmp4[MAX_SIZE];
+ char *response_pw;
+ char psk[MAX_SIZE];
+
+ ParseNtUsername(mschap.MsChapV2_PPPUsername, tmp1, sizeof(tmp1), tmp2, sizeof(tmp2), false);
+ ParseNtUsername(mschap.MsChapV2_PPPUsername, tmp3, sizeof(tmp3), tmp4, sizeof(tmp4), true);
+
+ Add(o, "");
+ Add(o, "-");
+ Add(o, ".");
+ Add(o, "*");
+ Add(o, "?");
+ Add(o, " ");
+ Add(o, "p");
+ Add(o, "guest");
+ Add(o, "anony");
+ Add(o, "anonymouse");
+ Add(o, "password");
+ Add(o, "passwd");
+ Add(o, "pass");
+ Add(o, "pw");
+ Add(o, mschap.MsChapV2_PPPUsername);
+ Add(o, tmp1);
+ Add(o, tmp2);
+ Add(o, tmp3);
+ Add(o, tmp4);
+
+ Zero(psk, sizeof(psk));
+
+ if (c->Cedar->Server != NULL)
+ {
+ SERVER *s = c->Cedar->Server;
+
+ if (s->IPsecServer != NULL)
+ {
+ StrCpy(psk, sizeof(psk), s->IPsecServer->Services.IPsec_Secret);
+
+ Add(o, psk);
+ }
+ }
+
+ response_pw = MsChapV2DoBruteForce(&mschap, o);
+
+ ReleaseList(o);
+
+ if (response_pw != NULL)
+ {
+ UCHAR challenge8[8];
+ UCHAR nt_hash[16];
+ UCHAR nt_hash_hash[16];
+
+ GenerateNtPasswordHash(nt_hash, response_pw);
+ GenerateNtPasswordHashHash(nt_hash_hash, nt_hash);
+ MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_ServerChallenge,
+ mschap.MsChapV2_PPPUsername);
+ MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_hash_hash,
+ mschap.MsChapV2_ClientResponse, challenge8);
+
+ Free(response_pw);
+ }
+ else
+ {
+ auth_ret = false;
+ }
+ }
+ }
+
+ if (auth_ret)
+ {
+ // User authentication success by anonymous authentication
+ HLog(hub, "LH_AUTH_OK", c->Name, username);
+ is_empty_password = true;
+ }
+ }
+
+ if (auth_ret == false)
+ {
+ // Attempt other authentication methods if anonymous authentication fails
+ switch (authtype)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ // Anonymous authentication (this have been already attempted)
+ break;
+
+ case AUTHTYPE_TICKET:
+ // Ticket authentication
+ if (PackGetDataSize(p, "ticket") == SHA1_SIZE)
+ {
+ PackGetData(p, "ticket", ticket);
+
+ auth_ret = SiCheckTicket(hub, ticket, username, sizeof(username), username_real, sizeof(username_real),
+ &ticketed_policy, sessionname, sizeof(sessionname), groupname, sizeof(groupname));
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // Password authentication
+ if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
+ {
+ POLICY *pol = NULL;
+ UCHAR secure_password[SHA1_SIZE];
+ Zero(secure_password, sizeof(secure_password));
+ if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
+ {
+ PackGetData(p, "secure_password", secure_password);
+ }
+ auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password, NULL, NULL, NULL);
+
+ pol = SamGetUserPolicy(hub, username);
+ if (pol != NULL)
+ {
+ no_save_password = pol->NoSavePassword;
+ Free(pol);
+ }
+
+ if(auth_ret){
+ // Check whether the password was empty
+ UCHAR hashed_empty_password[SHA1_SIZE];
+ UCHAR secure_empty_password[SHA1_SIZE];
+ HashPassword(hashed_empty_password, username, "");
+ SecurePassword(secure_empty_password, hashed_empty_password, c->Random);
+ if(Cmp(secure_password, secure_empty_password, SHA1_SIZE)==0){
+ is_empty_password = true;
+ }
+ }
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ {
+ POLICY *pol = NULL;
+
+ // Plaintext password authentication
+ Zero(plain_password, sizeof(plain_password));
+ PackGetStr(p, "plain_password", plain_password, sizeof(plain_password));
+ if (c->IsInProc == false && StartWith(plain_password, IPC_PASSWORD_MSCHAPV2_TAG))
+ {
+ // Do not allow the MS-CHAPv2 authentication other than IPC sessions
+ Zero(plain_password, sizeof(plain_password));
+ }
+
+ if (auth_ret == false)
+ {
+ // Attempt a password authentication of normal user
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR hash_password[SHA1_SIZE];
+ bool is_mschap = StartWith(plain_password, IPC_PASSWORD_MSCHAPV2_TAG);
+
+ HashPassword(hash_password, username, plain_password);
+ SecurePassword(secure_password, hash_password, c->Random);
+
+ if (is_mschap == false)
+ {
+ auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password, NULL, NULL, NULL);
+ }
+ else
+ {
+ auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password,
+ plain_password, mschap_v2_server_response_20, &ms_chap_error);
+ }
+
+ if (auth_ret && pol == NULL)
+ {
+ pol = SamGetUserPolicy(hub, username);
+ }
+ }
+
+ if (auth_ret == false)
+ {
+ // Attempt external authentication registered users
+ bool fail_ext_user_auth = false;
+ if (true)
+ {
+ fail_ext_user_auth = true;
+ }
+
+ if (fail_ext_user_auth == false)
+ {
+ auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, false, mschap_v2_server_response_20);
+ }
+
+ if (auth_ret && pol == NULL)
+ {
+ pol = SamGetUserPolicy(hub, username);
+ }
+ }
+
+
+ if (pol != NULL)
+ {
+ no_save_password = pol->NoSavePassword;
+ Free(pol);
+ }
+
+ if(auth_ret){
+ // Check whether the password was empty
+ if(IsEmptyStr(plain_password)){
+ is_empty_password = true;
+ }
+ }
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ // Certificate authentication is not supported in the open source version
+ HLog(hub, "LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE", c->Name, username);
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
+ goto CLEANUP;
+ break;
+
+ default:
+ // Unknown authentication method
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
+ error_detail = "ERR_AUTHTYPE_NOT_SUPPORTED";
+ goto CLEANUP;
+ }
+
+ if (auth_ret == false)
+ {
+ // Authentication failure
+ HLog(hub, "LH_AUTH_NG", c->Name, username);
+ }
+ else
+ {
+ // Authentication success
+ HLog(hub, "LH_AUTH_OK", c->Name, username);
+ }
+ }
+
+ if (auth_ret == false)
+ {
+ // Authentication failure
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTH_FAILED;
+ if (ms_chap_error != 0)
+ {
+ c->Err = ms_chap_error;
+ }
+ error_detail = "ERR_AUTH_FAILED";
+ goto CLEANUP;
+ }
+ else
+ {
+ if(is_empty_password)
+ {
+ SOCK *s = c->FirstSock;
+ if (s != NULL && s->RemoteIP.addr[0] != 127)
+ {
+ if(StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 ||
+ GetHubAdminOption(hub, "deny_empty_password") != 0)
+ {
+ // When the password is empty, remote connection is not acceptable
+ HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_NULL_PASSWORD_LOCAL_ONLY;
+ error_detail = "ERR_NULL_PASSWORD_LOCAL_ONLY";
+ goto CLEANUP;
+ }
+ }
+ }
+ }
+
+ policy = NULL;
+
+ // Authentication success
+ FreePack(p);
+
+ if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
+ {
+ // Get the policy
+ if (farm_member == false)
+ {
+ // In the case of not a farm member
+ user = AcGetUser(hub, username);
+ if (user == NULL)
+ {
+ user = AcGetUser(hub, "*");
+ if (user == NULL)
+ {
+ // User acquisition failure
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_ACCESS_DENIED;
+ error_detail = "AcGetUser";
+ goto CLEANUP;
+ }
+ }
+
+ policy = NULL;
+
+ Lock(user->lock);
+ {
+ // Get the expiration date
+ user_expires = user->ExpireTime;
+
+ StrCpy(username_real, sizeof(username_real), user->Name);
+ group = user->Group;
+ if (group != NULL)
+ {
+ AddRef(group->ref);
+
+ Lock(group->lock);
+ {
+ // Get the group name
+ StrCpy(groupname, sizeof(groupname), group->Name);
+ }
+ Unlock(group->lock);
+ }
+
+ if (user->Policy != NULL)
+ {
+ policy = ClonePolicy(user->Policy);
+ }
+ else
+ {
+ if (group)
+ {
+ Lock(group->lock);
+ {
+ if (group->Policy != NULL)
+ {
+ policy = ClonePolicy(group->Policy);
+ }
+ }
+ Unlock(group->lock);
+ }
+ }
+
+ if (group != NULL)
+ {
+ ReleaseGroup(group);
+ }
+ }
+ Unlock(user->lock);
+ loggedin_user_object = user;
+ }
+ else
+ {
+ // In the case of farm member
+ policy = ClonePolicy(&ticketed_policy);
+ }
+ }
+ else
+ {
+ // Administrator mode
+ admin_mode = true;
+ StrCpy(username_real, sizeof(username_real), ADMINISTRATOR_USERNAME);
+
+ policy = ClonePolicy(GetDefaultPolicy());
+ policy->NoBroadcastLimiter = true;
+ policy->MonitorPort = true;
+ }
+
+ if (policy == NULL)
+ {
+ // Use the default policy
+ policy = ClonePolicy(GetDefaultPolicy());
+ }
+
+ if (policy->MaxConnection == 0)
+ {
+ policy->MaxConnection = MAX_TCP_CONNECTION;
+ }
+
+ if (policy->TimeOut == 0)
+ {
+ policy->TimeOut = 20;
+ }
+
+ if (qos)
+ {
+ // VoIP / QoS
+ if (policy->NoQoS)
+ {
+ // Policy does not allow QoS
+ qos = false;
+ }
+ if (GetServerCapsBool(c->Cedar->Server, "b_support_qos") == false)
+ {
+ // Server does not support QoS
+ qos = false;
+ policy->NoQoS = true;
+ }
+ if (GetHubAdminOption(hub, "deny_qos") != 0)
+ {
+ // It is prohibited in the management options
+ qos = false;
+ policy->NoQoS = true;
+ }
+ }
+
+ if (GetHubAdminOption(hub, "max_bitrates_download") != 0)
+ {
+ if (policy->MaxDownload == 0)
+ {
+ policy->MaxDownload = GetHubAdminOption(hub, "max_bitrates_download");
+ }
+ else
+ {
+ UINT r = GetHubAdminOption(hub, "max_bitrates_download");
+ policy->MaxDownload = MIN(policy->MaxDownload, r);
+ }
+ }
+
+ if (GetHubAdminOption(hub, "max_bitrates_upload") != 0)
+ {
+ if (policy->MaxUpload == 0)
+ {
+ policy->MaxUpload = GetHubAdminOption(hub, "max_bitrates_upload");
+ }
+ else
+ {
+ UINT r = GetHubAdminOption(hub, "max_bitrates_upload");
+ policy->MaxUpload = MIN(policy->MaxUpload, r);
+ }
+ }
+
+ if (GetHubAdminOption(hub, "deny_bridge") != 0)
+ {
+ policy->NoBridge = true;
+ }
+
+ if (GetHubAdminOption(hub, "deny_routing") != 0)
+ {
+ policy->NoRouting = true;
+ }
+
+ if (c->IsInProc)
+ {
+ policy->NoBridge = false;
+ policy->NoRouting = false;
+ }
+
+ if (hub->Option->ClientMinimumRequiredBuild > c->ClientBuild &&
+ InStrEx(c->ClientStr, "client", false))
+ {
+ // Build number of the client is too small
+ HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, hub->Option->ClientMinimumRequiredBuild);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_VERSION_INVALID;
+ Free(policy);
+ error_detail = "ERR_VERSION_INVALID";
+ goto CLEANUP;
+ }
+
+ if (hub->Option->RequiredClientId != 0 &&
+ hub->Option->RequiredClientId != client_id &&
+ InStrEx(c->ClientStr, "client", false))
+ {
+ // Build number of the client is too small
+ HLog(hub, "LH_CLIENT_ID_REQUIRED", c->Name, client_id, hub->Option->RequiredClientId);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_CLIENT_ID_REQUIRED;
+ error_detail = "ERR_CLIENT_ID_REQUIRED";
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if ((policy->NoSavePassword) || (policy->AutoDisconnect != 0))
+ {
+ if (c->ClientBuild < 6560 && InStrEx(c->ClientStr, "client", false))
+ {
+ // If NoSavePassword policy is specified,
+ // only supported client can connect
+ HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, 6560);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_VERSION_INVALID;
+ error_detail = "ERR_VERSION_INVALID";
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (user_expires != 0 && user_expires <= SystemTime64())
+ {
+ // User expired
+ HLog(hub, "LH_USER_EXPIRES", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_ACCESS_DENIED;
+ error_detail = "LH_USER_EXPIRES";
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (policy->Access == false)
+ {
+ // Access is denied
+ HLog(hub, "LH_POLICY_ACCESS_NG", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ error_detail = "LH_POLICY_ACCESS_NG";
+ c->Err = ERR_ACCESS_DENIED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ // Determine the contents of the policy by comparing to
+ // option presented by client or deny the connection.
+ // Confirm the connectivity in the monitor-mode first
+ if (require_monitor_mode && policy->MonitorPort == false)
+ {
+ // Can not connect in the monitor port mode
+ HLog(hub, "LH_POLICY_MONITOR_MODE", c->Name);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_MONITOR_MODE_DENIED;
+ Free(policy);
+ error_detail = "ERR_MONITOR_MODE_DENIED";
+ goto CLEANUP;
+ }
+
+ if (policy->MonitorPort)
+ {
+ if (require_monitor_mode == false)
+ {
+ policy->MonitorPort = false;
+ }
+ }
+
+ if (policy->MonitorPort)
+ {
+ qos = false;
+ }
+
+ // Determine whether it can be connected by a bridge / routing mode next
+ if (require_bridge_routing_mode &&
+ (policy->NoBridge && policy->NoRouting))
+ {
+ // Can not be connected by a bridge / routing mode
+ HLog(hub, "LH_POLICY_BRIDGE_MODE", c->Name);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_BRIDGE_MODE_DENIED;
+ error_detail = "ERR_BRIDGE_MODE_DENIED";
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (require_bridge_routing_mode == false)
+ {
+ policy->NoBridge = true;
+ policy->NoRouting = true;
+ }
+
+ GenerateMachineUniqueHash(unique2);
+
+ if (Cmp(unique, unique2, SHA1_SIZE) == 0)
+ {
+ // It's a localhost session
+ local_host_session = true;
+ }
+
+ if (local_host_session == false)
+ {
+ // Make further judgment whether localhost session
+ SOCK *s = c->FirstSock;
+
+ if (s != NULL)
+ {
+ if (IsIPMyHost(&s->RemoteIP))
+ {
+ // It's a localhost session
+ local_host_session = true;
+ }
+ }
+ }
+
+ if (local_host_session)
+ {
+ // Permit routing or bridging in the case of localhost session
+ policy->NoBridge = false;
+ policy->NoRouting = false;
+ }
+
+ if (local_host_session == false)
+ {
+
+ if (policy->NoBridge == false || policy->NoRouting == false)
+ {
+ use_bridge_license = true;
+ }
+ else
+ {
+ use_client_license = true;
+ }
+ }
+
+
+ if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
+ policy != NULL)
+ {
+ if (GetServerCapsBool(hub->Cedar->Server, "b_support_limit_multilogin"))
+ {
+ // Check if the number of concurrent multiple logins limit is specified in the policy
+ RPC_ENUM_SESSION t;
+ UINT i, num;
+ UINT max_logins = policy->MultiLogins;
+ UINT ao = GetHubAdminOption(hub, "max_multilogins_per_user");
+
+ if (ao != 0)
+ {
+ if (max_logins != 0)
+ {
+ max_logins = MIN(max_logins, ao);
+ }
+ else
+ {
+ max_logins = ao;
+ }
+ }
+
+ if (max_logins != 0)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hub->Name);
+
+ Unlock(hub->lock);
+
+ SiEnumSessionMain(server, &t);
+
+ Lock(hub->lock);
+
+ num = 0;
+
+ for (i = 0;i < t.NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
+
+ if (e->BridgeMode == false && e->Layer3Mode == false && e->LinkMode == false && e->CurrentNumTcp != 0)
+ {
+ if (StrCmpi(e->Username, username) == 0 &&
+ (IsZero(e->UniqueId, 16) || Cmp(e->UniqueId, node.UniqueId, 16) != 0))
+ {
+ num++;
+ }
+ }
+ }
+
+ FreeRpcEnumSession(&t);
+
+ if (num >= max_logins)
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ // Dump a detailed error log
+ HLog(hub, "LH_TOO_MANY_MULTILOGINS",
+ c->Name,
+ username, max_logins, num);
+
+ ReleaseHub(hub);
+ c->Err = ERR_TOO_MANY_USER_SESSION;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+ }
+ }
+
+ if (loggedin_user_object != NULL)
+ {
+ // Update the user information
+ Lock(loggedin_user_object->lock);
+ {
+ loggedin_user_object->LastLoginTime = SystemTime64();
+ }
+ Unlock(loggedin_user_object->lock);
+ }
+
+ // Update the number of log-ins
+ hub->LastCommTime = hub->LastLoginTime = SystemTime64();
+
+ if (farm_controller)
+ {
+ wchar_t *msg = GetHubMsg(hub);
+
+ Unlock(hub->lock);
+
+ Lock(cedar->CedarSuperLock);
+
+ // In the case of farm controller, choose a farm members to host this HUB
+ LockList(server->FarmMemberList);
+ {
+ HLog(hub, "LH_FARM_SELECT_1", c->Name);
+ f = SiGetHubHostingMember(server, hub, admin_mode, c);
+
+ if (f == NULL)
+ {
+ // Failed in the selection
+ HLog(hub, "LH_FARM_SELECT_2", c->Name);
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ ReleaseHub(hub);
+ c->Err = ERR_COULD_NOT_HOST_HUB_ON_FARM;
+ Free(policy);
+ Free(msg);
+ goto CLEANUP;
+ }
+ else
+ {
+ if (f->Me == false)
+ {
+ UCHAR ticket[SHA1_SIZE];
+ PACK *p;
+ BUF *b;
+ UINT i;
+
+ SLog(c->Cedar, "LH_FARM_SELECT_4", c->Name, f->hostname);
+
+ // Create a session on the selected server farm member
+ Rand(ticket, sizeof(ticket));
+ SiCallCreateTicket(server, f, hub->Name,
+ username, username_real, policy, ticket, Inc(hub->SessionCounter), groupname);
+
+ p = NewPack();
+ PackAddInt(p, "Redirect", 1);
+ PackAddIp32(p, "Ip", f->Ip);
+ for (i = 0;i < f->NumPort;i++)
+ {
+ PackAddIntEx(p, "Port", f->Ports[i], i, f->NumPort);
+ }
+ PackAddData(p, "Ticket", ticket, sizeof(ticket));
+
+ if (true)
+ {
+ char *utf = CopyUniToUtf(msg);
+
+ PackAddData(p, "Msg", utf, StrLen(utf));
+
+ Free(utf);
+ }
+
+ b = XToBuf(f->ServerCert, false);
+ PackAddBuf(p, "Cert", b);
+ FreeBuf(b);
+
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ ReleaseHub(hub);
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ c->Err = 0;
+ Free(policy);
+
+ FreePack(HttpServerRecv(c->FirstSock));
+ Free(msg);
+ goto CLEANUP;
+ }
+ else
+ {
+ HLog(hub, "LH_FARM_SELECT_3", c->Name);
+ // Continue the process because myself was selected
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ f->Point = SiGetPoint(server);
+ Lock(hub->lock);
+ Free(msg);
+ }
+ }
+ }
+ }
+
+ if (admin_mode == false)
+ {
+ // Check the maximum number of connections of the HUB
+ if (hub->Option->MaxSession != 0 &&
+ hub->Option->MaxSession <= Count(hub->NumSessions))
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION", c->Name, hub->Option->MaxSession);
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ error_detail = "ERR_HUB_IS_BUSY";
+ goto CLEANUP;
+ }
+ }
+
+ if (use_client_license || use_bridge_license)
+ {
+ // Examine whether not to conflict with the limit of simultaneous connections
+ // number of sessions defined by the Virtual HUB management options
+ if (
+ (GetHubAdminOption(hub, "max_sessions") != 0 &&
+ (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= GetHubAdminOption(hub, "max_sessions"))
+ ||
+ (hub->Option->MaxSession != 0 &&
+ (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= hub->Option->MaxSession))
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION", c->Name, GetHubAdminOption(hub, "max_sessions"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (use_client_license)
+ {
+ // Examine whether not to conflict with the limit of simultaneous connections
+ // number of sessions(client) defined by the Virtual HUB management options
+ if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0
+ ) &&
+ Count(hub->NumSessionsClient) >= GetHubAdminOption(hub, "max_sessions_client") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
+ ||
+ (hub->FarmMember_MaxSessionClientBridgeApply &&
+ Count(hub->NumSessionsClient) >= hub->FarmMember_MaxSessionClient))
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_CLIENT", c->Name, GetHubAdminOption(hub, "max_sessions_client"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (use_bridge_license)
+ {
+ // Examine whether not to conflict with the limit of simultaneous connections
+ // number of sessions(bridge) defined by the Virtual HUB management options
+ if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0
+ ) &&
+ Count(hub->NumSessionsBridge) >= GetHubAdminOption(hub, "max_sessions_bridge") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
+ ||
+ (hub->FarmMember_MaxSessionClientBridgeApply &&
+ Count(hub->NumSessionsBridge) >= hub->FarmMember_MaxSessionBridge))
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_BRIDGE", c->Name, GetHubAdminOption(hub, "max_sessions_bridge"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (Count(hub->Cedar->CurrentSessions) >= GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"))
+ {
+ // Can not connect any more
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_2", c->Name, GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ // Increment the current number of connections
+ Inc(hub->NumSessions);
+ if (use_bridge_license)
+ {
+ Inc(hub->NumSessionsBridge);
+ }
+
+ if (use_client_license)
+ {
+ Inc(hub->NumSessionsClient);
+ }
+ Inc(hub->Cedar->CurrentSessions);
+
+ // Calculate the time-out period
+ timeout = policy->TimeOut * 1000; // Convert milliseconds to seconds
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_DEFAULT;
+ }
+ timeout = MIN(timeout, TIMEOUT_MAX);
+ timeout = MAX(timeout, TIMEOUT_MIN);
+
+ // Update the max_connection according to the policy
+ max_connection = MIN(max_connection, policy->MaxConnection);
+ max_connection = MIN(max_connection, MAX_TCP_CONNECTION);
+ max_connection = MAX(max_connection, 1);
+
+ if (c->FirstSock->IsRUDPSocket)
+ {
+ // In the case of TCP-over-UDP
+ half_connection = false;
+
+ // Disable the QoS
+ qos = false;
+
+ if (enable_udp_recovery == false)
+ {
+ // Disable the session reconnection feature
+ no_reconnect_to_session = true;
+ max_connection = 1;
+ }
+ else
+ {
+ // If the UDP recovery is enabled, permit the session re-connection feature (for 2)
+ no_reconnect_to_session = false;
+ max_connection = NUM_TCP_CONNECTION_FOR_UDP_RECOVERY;
+ }
+ }
+
+ if (half_connection)
+ {
+ // Number of connections should be more than 2 in the case of Half Connection
+ max_connection = MAX(max_connection, 2);
+ }
+
+ if (qos)
+ {
+ // Number of connections is set to 2 or more when using the VoIP / QoS
+ max_connection = MAX(max_connection, 2);
+ if (half_connection)
+ {
+ max_connection = MAX(max_connection, 4);
+ }
+ }
+
+ c->Status = CONNECTION_STATUS_ESTABLISHED;
+
+ // Remove the connection from Cedar
+ DelConnection(c->Cedar, c);
+
+ // Create a Session
+ StrLower(username);
+ s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc);
+
+ s->EnableUdpRecovery = enable_udp_recovery;
+ s->LocalHostSession = local_host_session;
+ s->NormalClient = true;
+
+ if (c->FirstSock->IsRUDPSocket)
+ {
+ // R-UDP session
+ s->IsRUDPSession = true;
+ s->RUdpMss = c->FirstSock->RUDP_OptimizedMss;
+ Debug("Optimized MSS Value for R-UDP: %u\n", s->RUdpMss);
+ }
+
+ if (enable_bulk_on_rudp)
+ {
+ // Allow bulk transfer on R-UDP
+ s->EnableBulkOnRUDP = true;
+ s->EnableHMacOnBulkOfRUDP = enable_hmac_on_bulk_of_rudp;
+ }
+
+ s->IsAzureSession = c->FirstSock->IsReverseAcceptedSocket;
+
+ StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), c->FirstSock->UnderlayProtocol);
+
+ if (server != NULL)
+ {
+ s->NoSendSignature = server->NoSendSignature;
+ }
+
+ if (c->IsInProc)
+ {
+ s->NoSendSignature = true;
+ }
+
+ if (c->IsInProc && StrCmpi(c->InProcPrefix, OPENVPN_IPC_POSTFIX_L3) == 0)
+ {
+ // OpenVPN L3 session
+ s->IsOpenVPNL3Session = true;
+ }
+
+ if (c->IsInProc && StrCmpi(c->InProcPrefix, OPENVPN_IPC_POSTFIX_L2) == 0)
+ {
+ // OpenVPN L2 session
+ s->IsOpenVPNL2Session = true;
+ }
+
+ // Determine whether the use of UDP acceleration mode
+ if (use_udp_acceleration_client)
+ {
+ s->UseUdpAcceleration = true;
+
+ s->UdpAccelFastDisconnectDetect = support_udp_accel_fast_disconnect_detect;
+ }
+
+ if (hub->Option != NULL && hub->Option->DisableUdpAcceleration)
+ {
+ s->UseUdpAcceleration = false;
+ }
+
+ if (IsZeroIP(&c->FirstSock->Reverse_MyServerGlobalIp) == false &&
+ CmpIpAddr(&c->FirstSock->Reverse_MyServerGlobalIp, &c->FirstSock->RemoteIP) == 0)
+ {
+ // Disable forcibly the UDP acceleration mode if VPN Server and VPN Client
+ // are in same LAN in the case of using VPN Azure.
+ // (Or this may cause infinite loop of packet)
+ s->UseUdpAcceleration = false;
+ }
+
+ if (s->UseUdpAcceleration)
+ {
+ s->UseHMacOnUdpAcceleration = use_hmac_on_udp_acceleration;
+ }
+
+ Debug("UseUdpAcceleration = %u\n", s->UseUdpAcceleration);
+ Debug("UseHMacOnUdpAcceleration = %u\n", s->UseHMacOnUdpAcceleration);
+
+ if (s->UseUdpAcceleration)
+ {
+ // Initialize the UDP acceleration function
+ s->UdpAccel = NewUdpAccel(c->Cedar, (c->FirstSock->IsRUDPSocket ? NULL : &c->FirstSock->LocalIP), false, c->FirstSock->IsRUDPSocket, false);
+ if (s->UdpAccel == NULL)
+ {
+ s->UseUdpAcceleration = false;
+ Debug("NewUdpAccel Failed.\n");
+ }
+ else
+ {
+ if (UdpAccelInitServer(s->UdpAccel, udp_acceleration_client_key, &udp_acceleration_client_ip, udp_acceleration_client_port,
+ &c->FirstSock->RemoteIP) == false)
+ {
+ Debug("UdpAccelInitServer Failed.\n");
+ s->UseUdpAcceleration = false;
+ }
+
+ s->UdpAccel->FastDetect = s->UdpAccelFastDisconnectDetect;
+
+ if (use_encrypt == false)
+ {
+ s->UdpAccel->PlainTextMode = true;
+ }
+
+ s->UdpAccel->UseHMac = s->UseHMacOnUdpAcceleration;
+ }
+ }
+
+ s->UseClientLicense = use_client_license;
+ s->UseBridgeLicense = use_bridge_license;
+
+ s->AdjustMss = adjust_mss;
+ if (s->AdjustMss != 0)
+ {
+ Debug("AdjustMSS: %u\n", s->AdjustMss);
+ }
+
+ s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
+ s->IsMonitorMode = policy->MonitorPort;
+
+ // Decide whether IPv6 session
+ s->IPv6Session = false;
+
+ if (node.ClientIpAddress == 0)
+ {
+ s->IPv6Session = true;
+ }
+
+ if (use_bridge_license)
+ {
+ Inc(s->Cedar->AssignedBridgeLicense);
+ }
+
+ if (use_client_license)
+ {
+ Inc(s->Cedar->AssignedClientLicense);
+ }
+
+ if (server != NULL)
+ {
+ // Update the total allocation of the number of licenses for Server structure
+ if (server->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // Update only stand-alone mode
+ // (Periodically poll in the cluster controller mode)
+ server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
+ server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
+ }
+ }
+
+ if (StrLen(sessionname) != 0)
+ {
+ // Specify the session name
+ Free(s->Name);
+ s->Name = CopyStr(sessionname);
+ }
+
+ {
+ char ip[128];
+ IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
+ HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort,
+ c->FirstSock->UnderlayProtocol);
+ }
+
+ c->Session = s;
+ s->AdministratorMode = admin_mode;
+ StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username_real);
+ StrCpy(s->GroupName, sizeof(s->GroupName), groupname);
+
+ // Get the session key
+ Copy(session_key, s->SessionKey, SHA1_SIZE);
+
+ // Set the parameters
+ s->MaxConnection = max_connection;
+ s->UseEncrypt = use_encrypt;
+ if (s->UseEncrypt && use_fast_rc4)
+ {
+ s->UseFastRC4 = use_fast_rc4;
+ }
+ s->UseCompress = use_compress;
+ s->HalfConnection = half_connection;
+ s->Timeout = timeout;
+ s->QoS = qos;
+ s->NoReconnectToSession = no_reconnect_to_session;
+
+ if (policy != NULL)
+ {
+ s->VLanId = policy->VLanId;
+ }
+
+ // User name
+ s->Username = CopyStr(username);
+
+ HLog(hub, "LH_SET_SESSION", s->Name, s->MaxConnection,
+ s->UseEncrypt ? _UU("L_YES") : _UU("L_NO"),
+ s->UseCompress ? _UU("L_YES") : _UU("L_NO"),
+ s->HalfConnection ? _UU("L_YES") : _UU("L_NO"),
+ s->Timeout / 1000);
+
+ msg = GetHubMsg(hub);
+ }
+ Unlock(hub->lock);
+
+ // Send a Welcome packet to the client
+ p = PackWelcome(s);
+
+ if (s->InProcMode)
+ {
+ if (IsZero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20)) == false)
+ {
+ // MS-CHAPv2 Response
+ PackAddData(p, "IpcMsChapV2ServerResponse", mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
+ }
+ }
+
+ if (true)
+ {
+ // A message to be displayed in the VPN Client (Will not be displayed if the VPN Gate Virtual HUB)
+ char *utf;
+ wchar_t winver_msg_client[3800];
+ wchar_t winver_msg_server[3800];
+ UINT tmpsize;
+ wchar_t *tmp;
+ RPC_WINVER server_winver;
+
+ GetWinVer(&server_winver);
+
+ Zero(winver_msg_client, sizeof(winver_msg_client));
+ Zero(winver_msg_server, sizeof(winver_msg_server));
+
+ if (IsSupportedWinVer(&winver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ winver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ if (IsSupportedWinVer(&server_winver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ server_winver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(msg) + 16000;
+
+ tmp = ZeroMalloc(tmpsize);
+
+ if (IsURLMsg(msg, NULL, 0) == false)
+ {
+
+ {
+ if (GetCurrentLangId() != SE_LANG_ENGLISH)
+ {
+ UniStrCat(tmp, tmpsize, _UU("OSS_MSG"));
+ }
+ }
+
+ {
+ UniStrCat(tmp, tmpsize, winver_msg_client);
+ UniStrCat(tmp, tmpsize, winver_msg_server);
+ }
+ }
+ UniStrCat(tmp, tmpsize, msg);
+
+ utf = CopyUniToUtf(tmp);
+
+ PackAddData(p, "Msg", utf, StrLen(utf));
+
+ Free(tmp);
+ Free(utf);
+ }
+
+ Free(msg);
+
+
+ if (s->UseFastRC4)
+ {
+ // Generate a RC4 key pair
+ GenerateRC4KeyPair(&key_pair);
+
+ // Add to Welcome packet
+ PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
+ PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ // Brand string for the connection limit
+ {
+ char *branded_cfroms = _SS("BRANDED_C_FROM_S");
+ if(StrLen(branded_cfroms) > 0)
+ {
+ PackAddStr(p, "branded_cfroms", branded_cfroms);
+ }
+ }
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ // Receive a signature
+ Copy(&c->Session->NodeInfo, &node, sizeof(NODE_INFO));
+
+
+ {
+ wchar_t tmp[MAX_SIZE * 2];
+ NodeInfoToStr(tmp, sizeof(tmp), &s->NodeInfo);
+
+ HLog(hub, "LH_NODE_INFO", s->Name, tmp);
+ }
+
+ // Shift the connection to the tunneling mode
+ StartTunnelingMode(c);
+
+ // Processing of half-connection mode
+ if (s->HalfConnection)
+ {
+ // The direction of the first socket is client to server
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ ts->Direction = TCP_CLIENT_TO_SERVER;
+ }
+
+ if (s->UseFastRC4)
+ {
+ // Set the RC4 key information to the first TCP connection
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, true);
+ }
+
+ if (s->UseEncrypt && s->UseFastRC4 == false)
+ {
+ s->UseSSLDataEncryption = true;
+ }
+ else
+ {
+ s->UseSSLDataEncryption = false;
+ }
+
+ if (s->Hub->Type == HUB_TYPE_FARM_DYNAMIC && s->Cedar->Server != NULL && s->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (s->Hub->BeingOffline == false)
+ {
+ // Start the SecureNAT on the dynamic Virtual HUB
+ EnableSecureNATEx(s->Hub, false, true);
+
+ cluster_dynamic_secure_nat = true;
+ }
+ }
+
+ if (s->LocalHostSession)
+ {
+ // Update the local MAC address list
+ RefreshLocalMacAddressList();
+ }
+
+ // Discard the user list cache
+ DeleteAllUserListCache(hub->UserList);
+
+
+ // Main routine of the session
+ Debug("SessionMain()\n");
+ s->NumLoginIncrementUserObject = loggedin_user_object;
+ s->NumLoginIncrementHubObject = s->Hub;
+ s->NumLoginIncrementTick = Tick64() + (UINT64)NUM_LOGIN_INCREMENT_INTERVAL;
+ SessionMain(s);
+
+
+ // Discard the user list cache
+ DeleteAllUserListCache(hub->UserList);
+
+ // Decrement the current number of connections
+ Lock(s->Hub->lock);
+ {
+ if (use_bridge_license)
+ {
+ Dec(hub->NumSessionsBridge);
+ }
+
+ if (use_client_license)
+ {
+ Dec(hub->NumSessionsClient);
+ }
+
+ Dec(s->Hub->NumSessions);
+ Dec(s->Hub->Cedar->CurrentSessions);
+
+ // Decrement the number of licenses
+ if (use_bridge_license)
+ {
+ Dec(s->Cedar->AssignedBridgeLicense);
+ }
+
+ if (use_client_license)
+ {
+ Dec(s->Cedar->AssignedClientLicense);
+ }
+
+ if (server != NULL)
+ {
+ // Update the total allocation of the number of licenses for Server structure
+ if (server->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // Update only stand-alone mode
+ // (Periodically polled in the cluster controller mode)
+ server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
+ server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
+ }
+ }
+ }
+ Unlock(s->Hub->lock);
+
+ PrintSessionTotalDataSize(s);
+
+ HLog(s->Hub, "LH_END_SESSION", s->Name, s->TotalSendSizeReal, s->TotalRecvSizeReal);
+
+ if (cluster_dynamic_secure_nat && s->Hub->BeingOffline == false)
+ {
+ // Stop the SecureNAT on the dynamic Virtual HUB
+ EnableSecureNATEx(s->Hub, false, true);
+ }
+
+ if (s->UdpAccel != NULL)
+ {
+ // Release the UDP acceleration
+ FreeUdpAccel(s->UdpAccel);
+ s->UdpAccel = NULL;
+ }
+
+ ReleaseSession(s);
+
+ ret = true;
+ c->Err = ERR_SESSION_REMOVED;
+
+ ReleaseHub(hub);
+
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "additional_connect") == 0)
+ {
+ SOCK *sock;
+ TCPSOCK *ts;
+ UINT dummy;
+
+ c->Type = CONNECTION_TYPE_ADDITIONAL;
+
+ // Additional connection
+ // Read the session key
+ if (GetSessionKeyFromPack(p, session_key, &dummy) == false)
+ {
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ FreePack(p);
+
+ // Get the session from the session key
+ s = GetSessionFromKey(c->Cedar, session_key);
+ if (s == NULL || s->Halt || s->NoReconnectToSession)
+ {
+ // Session can not be found, or re-connection is prohibited
+ Debug("Session Not Found.\n");
+ c->Err = ERR_SESSION_TIMEOUT;
+ goto CLEANUP;
+ }
+
+ // Session is found
+ Debug("Session Found: %s\n", s->Name);
+ // Check the protocol of session
+ c->Err = 0;
+ Lock(s->lock);
+ {
+ if (s->Connection->Protocol != CONNECTION_TCP)
+ {
+ c->Err = ERR_INVALID_PROTOCOL;
+ }
+ }
+ Unlock(s->lock);
+ // Check the current number of connections of the session
+ Lock(s->Connection->lock);
+ if (c->Err == 0)
+ {
+ if (Count(s->Connection->CurrentNumConnection) > s->MaxConnection)
+ {
+ c->Err = ERR_TOO_MANY_CONNECTION;
+ }
+ }
+ if (c->Err != 0)
+ {
+ Unlock(s->Connection->lock);
+ if (c->Err == ERR_TOO_MANY_CONNECTION)
+ {
+ Debug("Session TOO MANY CONNECTIONS !!: %u\n",
+ Count(s->Connection->CurrentNumConnection));
+ }
+ else
+ {
+ Debug("Session Invalid Protocol.\n");
+ }
+ ReleaseSession(s);
+ goto CLEANUP;
+ }
+
+ // Generate a high-speed RC4 encryption key
+ if (s->UseFastRC4)
+ {
+ GenerateRC4KeyPair(&key_pair);
+ }
+
+ // Add the socket of this connection to the connection list of the session (TCP)
+ sock = c->FirstSock;
+ ts = NewTcpSock(sock);
+ SetTimeout(sock, CONNECTING_TIMEOUT);
+ direction = TCP_BOTH;
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ if (s->HalfConnection)
+ {
+ // In half-connection, directions of the TCP connections are automatically
+ // adjusted by examining all current direction of the TCP connections
+ UINT i, c2s, s2c;
+ c2s = s2c = 0;
+ for (i = 0;i < LIST_NUM(s->Connection->Tcp->TcpSockList);i++)
+ {
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(s->Connection->Tcp->TcpSockList, i);
+ if (ts->Direction == TCP_SERVER_TO_CLIENT)
+ {
+ s2c++;
+ }
+ else
+ {
+ c2s++;
+ }
+ }
+ if (s2c > c2s)
+ {
+ direction = TCP_CLIENT_TO_SERVER;
+ }
+ else
+ {
+ direction = TCP_SERVER_TO_CLIENT;
+ }
+ Debug("%u/%u\n", s2c, c2s);
+ ts->Direction = direction;
+ }
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+
+ if (s->UseFastRC4)
+ {
+ // Set the RC4 key information
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, true);
+ }
+
+ // Return a success result
+ p = PackError(ERR_NO_ERROR);
+ PackAddInt(p, "direction", direction);
+
+ if (s->UseFastRC4)
+ {
+ // Add a RC4 key information
+ PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
+ PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ SetTimeout(sock, INFINITE);
+
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ Add(s->Connection->Tcp->TcpSockList, ts);
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+
+ // Increment the number of connections
+ Inc(s->Connection->CurrentNumConnection);
+ Debug("TCP Connection Incremented: %u\n", Count(s->Connection->CurrentNumConnection));
+
+ // Issue the Cancel of session
+ Cancel(s->Cancel1);
+
+ Unlock(s->Connection->lock);
+
+ c->flag1 = true;
+
+ ReleaseSession(s);
+
+ return true;
+ }
+ else if (StrCmpi(method, "enum_hub") == 0)
+ {
+ // Enumerate the Virtual HUB
+ UINT i, num;
+ LIST *o;
+ o = NewListFast(NULL);
+
+ c->Type = CONNECTION_TYPE_ENUM_HUB;
+
+ FreePack(p);
+ p = NewPack();
+ LockList(c->Cedar->HubList);
+ {
+ num = LIST_NUM(c->Cedar->HubList);
+ for (i = 0;i < num;i++)
+ {
+ HUB *h = LIST_DATA(c->Cedar->HubList, i);
+ if (h->Option != NULL && h->Option->NoEnum == false)
+ {
+ Insert(o, CopyStr(h->Name));
+ }
+ }
+ }
+ UnlockList(c->Cedar->HubList);
+
+ num = LIST_NUM(o);
+ for (i = 0;i < num;i++)
+ {
+ char *name = LIST_DATA(o, i);
+ PackAddStrEx(p, "HubName", name, i, num);
+ Free(name);
+ }
+ ReleaseList(o);
+ PackAddInt(p, "NumHub", num);
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ FreePack(HttpServerRecv(c->FirstSock));
+ c->Err = 0;
+
+ SLog(c->Cedar, "LS_ENUM_HUB", c->Name, num);
+
+ error_detail = "enum_hub";
+
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "farm_connect") == 0)
+ {
+ // Server farm connection request
+ CEDAR *cedar = c->Cedar;
+ c->Type = CONNECTION_TYPE_FARM_RPC;
+ c->Err = 0;
+ if (c->Cedar->Server == NULL)
+ {
+ // Unsupported
+ c->Err = ERR_NOT_FARM_CONTROLLER;
+ }
+ else
+ {
+ SERVER *s = c->Cedar->Server;
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER || s->FarmControllerInited == false)
+ {
+ // Not a farm controller
+ SLog(c->Cedar, "LS_FARM_ACCEPT_1", c->Name);
+ c->Err = ERR_NOT_FARM_CONTROLLER;
+ }
+ else
+ {
+ UCHAR check_secure_password[SHA1_SIZE];
+ UCHAR secure_password[SHA1_SIZE];
+ // User authentication
+ SecurePassword(check_secure_password, s->HashedPassword, c->Random);
+ if (PackGetDataSize(p, "SecurePassword") == sizeof(secure_password))
+ {
+ PackGetData(p, "SecurePassword", secure_password);
+ }
+ else
+ {
+ Zero(secure_password, sizeof(secure_password));
+ }
+
+ if (Cmp(secure_password, check_secure_password, SHA1_SIZE) != 0)
+ {
+ // Password is different
+ SLog(c->Cedar, "LS_FARM_ACCEPT_2", c->Name);
+ c->Err = ERR_ACCESS_DENIED;
+ }
+ else
+ {
+ // Get the certificate
+ BUF *b;
+ X *server_x;
+
+ SLog(c->Cedar, "LS_FARM_ACCEPT_3", c->Name);
+ b = PackGetBuf(p, "ServerCert");
+ if (b == NULL)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ else
+ {
+ server_x = BufToX(b, false);
+ FreeBuf(b);
+ if (server_x == NULL)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ else
+ {
+ UINT ip;
+ UINT point;
+ char hostname[MAX_SIZE];
+
+#ifdef OS_WIN32
+ MsSetThreadPriorityRealtime();
+#endif // OS_WIN32
+
+ SetTimeout(c->FirstSock, SERVER_CONTROL_TCP_TIMEOUT);
+
+ ip = PackGetIp32(p, "PublicIp");
+ point = PackGetInt(p, "Point");
+ if (PackGetStr(p, "HostName", hostname, sizeof(hostname)))
+ {
+ UINT num_port = PackGetIndexCount(p, "PublicPort");
+ if (num_port >= 1 && num_port <= MAX_PUBLIC_PORT_NUM)
+ {
+ UINT *ports = ZeroMalloc(sizeof(UINT) * num_port);
+ UINT i;
+
+ for (i = 0;i < num_port;i++)
+ {
+ ports[i] = PackGetIntEx(p, "PublicPort", i);
+ }
+
+ SiFarmServ(s, c->FirstSock, server_x, ip, num_port, ports, hostname, point,
+ PackGetInt(p, "Weight"), PackGetInt(p, "MaxSessions"));
+
+ Free(ports);
+ }
+ }
+
+ FreeX(server_x);
+ }
+ }
+ }
+ }
+ }
+ FreePack(p);
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "admin") == 0 && c->Cedar->Server != NULL)
+ {
+ UINT err;
+ // Administrative RPC connection request
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+ err = AdminAccept(c, p);
+ FreePack(p);
+ if (err != ERR_NO_ERROR)
+ {
+ PACK *p = PackError(err);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ }
+
+ error_detail = "admin_rpc";
+
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "password") == 0)
+ {
+ UINT err;
+ // Password change request
+ c->Type = CONNECTION_TYPE_PASSWORD;
+ err = ChangePasswordAccept(c, p);
+ FreePack(p);
+
+ p = PackError(err);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ error_detail = "change_password";
+
+ goto CLEANUP;
+ }
+ else
+ {
+ // Unknown method
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+
+ error_detail = "unknown_method";
+
+ goto CLEANUP;
+ }
+
+CLEANUP:
+ // Release the user object
+ if (loggedin_user_object != NULL)
+ {
+ ReleaseUser(loggedin_user_object);
+ }
+
+
+ // Error packet transmission
+ p = PackError(c->Err);
+ PackAddBool(p, "no_save_password", no_save_password);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ FreePack(HttpServerRecv(c->FirstSock));
+ SleepThread(25);
+
+ SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
+
+ return ret;
+}
+
+
+// Create a Node information
+void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
+{
+ SESSION *s;
+ OS_INFO *os;
+ char *product_id;
+ IP ip;
+ bool is_vgc = false;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ s = c->Session;
+ os = GetOsInfo();
+
+
+
+ Zero(info, sizeof(NODE_INFO));
+
+ // Client product name
+ StrCpy(info->ClientProductName, sizeof(info->ClientProductName), c->ClientStr);
+ // Client version
+ info->ClientProductVer = Endian32(c->ClientVer);
+ // Client build number
+ info->ClientProductBuild = Endian32(c->ClientBuild);
+
+ // Server product name
+ StrCpy(info->ServerProductName, sizeof(info->ServerProductName), c->ServerStr);
+ // Server version
+ info->ServerProductVer = Endian32(c->ServerVer);
+ // Server build number
+ info->ServerProductBuild = Endian32(c->ServerBuild);
+
+ // Client OS name
+ StrCpy(info->ClientOsName, sizeof(info->ClientOsName), os->OsProductName);
+ // Client OS version
+ StrCpy(info->ClientOsVer, sizeof(info->ClientOsVer), os->OsVersion);
+ // Client OS Product ID
+ product_id = OSGetProductId();
+ StrCpy(info->ClientOsProductId, sizeof(info->ClientOsProductId), product_id);
+ Free(product_id);
+
+ // Client host name
+#ifndef OS_WIN32
+ GetMachineName(info->ClientHostname, sizeof(info->ClientHostname));
+#else // OS_WIN32
+ if (true)
+ {
+ wchar_t namew[256];
+ char namea[256];
+
+ Zero(namew, sizeof(namew));
+ MsGetComputerNameFullEx(namew, sizeof(namew), true);
+
+ Zero(namea, sizeof(namea));
+ UniToStr(namea, sizeof(namea), namew);
+
+ if (IsEmptyStr(namea))
+ {
+ GetMachineName(namea, sizeof(namea));
+ }
+
+ StrCpy(info->ClientHostname, sizeof(info->ClientHostname), namea);
+
+ }
+#endif // OS_WIN32
+ // Client IP address
+ if (IsIP6(&c->FirstSock->LocalIP) == false)
+ {
+ info->ClientIpAddress = IPToUINT(&c->FirstSock->LocalIP);
+ }
+ else
+ {
+ Copy(info->ClientIpAddress6, c->FirstSock->LocalIP.ipv6_addr, sizeof(info->ClientIpAddress6));
+ }
+ // Client port number
+ info->ClientPort = Endian32(c->FirstSock->LocalPort);
+
+ // Server host name
+ StrCpy(info->ServerHostname, sizeof(info->ServerHostname), c->ServerName);
+ // Server IP address
+ if (GetIP(&ip, info->ServerHostname))
+ {
+ if (IsIP6(&ip) == false)
+ {
+ info->ServerIpAddress = IPToUINT(&ip);
+ }
+ else
+ {
+ Copy(info->ServerIpAddress6, ip.ipv6_addr, sizeof(info->ServerIpAddress6));
+ }
+ }
+ // Server port number
+ info->ServerPort = Endian32(c->ServerPort);
+
+ if (s->ClientOption->ProxyType == PROXY_SOCKS || s->ClientOption->ProxyType == PROXY_HTTP)
+ {
+ // Proxy host name
+ StrCpy(info->ProxyHostname, sizeof(info->ProxyHostname), s->ClientOption->ProxyName);
+
+ // Proxy Server IP Address
+ if (IsIP6(&c->FirstSock->RemoteIP) == false)
+ {
+ info->ProxyIpAddress = IPToUINT(&c->FirstSock->RemoteIP);
+ }
+ else
+ {
+ Copy(&info->ProxyIpAddress6, c->FirstSock->RemoteIP.ipv6_addr, sizeof(info->ProxyIpAddress6));
+ }
+
+ info->ProxyPort = Endian32(c->FirstSock->RemotePort);
+ }
+
+ // HUB name
+ StrCpy(info->HubName, sizeof(info->HubName), s->ClientOption->HubName);
+
+ // Unique ID
+ Copy(info->UniqueId, c->Cedar->UniqueId, sizeof(info->UniqueId));
+}
+
+// Connect a socket additionally
+SOCK *ClientAdditionalConnectToServer(CONNECTION *c)
+{
+ SOCK *s;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ // Socket connection
+ s = ClientConnectGetSocket(c, true, (c->DontUseTls1 ? false : true));
+ if (s == NULL)
+ {
+ // Connection failure
+ return NULL;
+ }
+
+ // Add the socket to the list
+ LockList(c->ConnectingSocks);
+ {
+ Add(c->ConnectingSocks, s);
+ AddRef(s->ref);
+ }
+ UnlockList(c->ConnectingSocks);
+
+ if (c->Session->Halt)
+ {
+ // Stop
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // Time-out
+ SetTimeout(s, CONNECTING_TIMEOUT);
+
+ // Start the SSL communication
+ if (StartSSLEx(s, NULL, NULL, (c->DontUseTls1 ? false : true), 0, c->ServerName) == false)
+ {
+ // SSL communication failure
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // Check the certificate
+ if (CompareX(s->RemoteX, c->ServerX) == false)
+ {
+ // The certificate is invalid
+ Disconnect(s);
+ c->Session->SessionTimeOuted = true;
+ }
+
+ return s;
+}
+
+// Remove the key and certificate in the secure device
+UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name)
+{
+ SECURE *sec;
+ // Validate arguments
+ if (pin == NULL || device_id == 0)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Open the device
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Open the session
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Login
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // Delete the certificate
+ if (cert_name != NULL)
+ {
+ DeleteSecCert(sec, cert_name);
+ }
+
+ // Delete the Private key
+ if (key_name != NULL)
+ {
+ DeleteSecKey(sec, key_name);
+ }
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Close the device
+ CloseSec(sec);
+
+ return ERR_NO_ERROR;
+}
+
+// Enumerate certificates and keys in the secure device
+UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list)
+{
+ SECURE *sec;
+ LIST *o;
+ LIST *cert_name_list, *key_name_list;
+ // Validate arguments
+ if (pin == NULL || device_id == 0 || cert_list == NULL || key_list == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Open the device
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Open the session
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Login
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // Enumerate objects
+ if ((o = EnumSecObject(sec)) != NULL)
+ {
+ UINT i;
+
+ cert_name_list = NewList(CompareStr);
+ key_name_list = NewList(CompareStr);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ if (obj->Type == SEC_X)
+ {
+ Add(cert_name_list, CopyStr(obj->Name));
+ }
+ else if (obj->Type == SEC_K)
+ {
+ Add(key_name_list, CopyStr(obj->Name));
+ }
+ }
+
+ Sort(cert_name_list);
+ Sort(key_name_list);
+
+ *cert_list = ListToTokenList(cert_name_list);
+ *key_list = ListToTokenList(key_name_list);
+
+ // Release the memory
+ FreeStrList(cert_name_list);
+ FreeStrList(key_name_list);
+ FreeEnumSecObject(o);
+ }
+ else
+ {
+ *cert_list = NullToken();
+ *key_list = NullToken();
+ }
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Close the device
+ CloseSec(sec);
+
+ return ERR_NO_ERROR;
+}
+
+// Record the certificate and key to secure device
+UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin)
+{
+ SECURE *sec;
+ bool failed;
+ // Validate arguments
+ if (pin == NULL || device_id == 0 || cert_name == NULL || x == NULL || key_name == NULL || k == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Open the device
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Open the session
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Login
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // Registration
+ failed = false;
+
+ // Register the certificate
+ if (WriteSecCert(sec, true, cert_name, x) == false)
+ {
+ failed = true;
+ }
+
+ // Register the private key
+ if (WriteSecKey(sec, true, key_name, k) == false)
+ {
+ failed = true;
+ }
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Close the device
+ CloseSec(sec);
+
+ if (failed == false)
+ {
+ // Success
+ return ERR_NO_ERROR;
+ }
+ else
+ {
+ // Failure
+ return ERR_SECURE_CANT_WRITE;
+ }
+}
+
+// Attempt to sign by the secure device
+UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin)
+{
+ SECURE *sec;
+ X *x;
+ // Validate arguments
+ if (sign == false || pin == NULL || device_id == 0)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // Open the device
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Open the session
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // Login
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // Read the certificate
+ x = ReadSecCert(sec, sign->SecurePublicCertName);
+ if (x == NULL)
+ {
+ LogoutSec(sec);
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_NO_CERT;
+ }
+
+ // Sign by the private key
+ if (SignSec(sec, sign->SecurePrivateKeyName, sign->Signature, sign->Random, SHA1_SIZE) == false)
+ {
+ // Signing failure
+ FreeX(x);
+ LogoutSec(sec);
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_NO_PRIVATE_KEY;
+ }
+
+ // Convert the certificate to buffer
+ sign->ClientCert = x;
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Close the device
+ CloseSec(sec);
+
+ // Success
+ return ERR_NO_ERROR;
+}
+
+// Client connects to the server additionally
+bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
+{
+ SOCK *s;
+ PACK *p;
+ TCPSOCK *ts;
+ UINT err;
+ UINT direction;
+ RC4_KEY_PAIR key_pair;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // Socket connection to the server
+ s = ClientAdditionalConnectToServer(c);
+ if (s == NULL)
+ {
+ // Failed to connect socket
+ return false;
+ }
+
+ if (c->Halt)
+ {
+ goto CLEANUP;
+ }
+
+ // Send a signature
+ Debug("Uploading Signature...\n");
+ if (ClientUploadSignature(s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ goto CLEANUP;
+ }
+
+ // Receive a Hello packet
+ Debug("Downloading Hello...\n");
+ if (ClientDownloadHello(c, s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ goto CLEANUP;
+ }
+
+ // Send a authentication data for the additional connection
+ if (ClientUploadAuth2(c, s) == false)
+ {
+ // Disconnected
+ goto CLEANUP;
+ }
+
+ // Receive a response
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ // Disconnected
+ goto CLEANUP;
+ }
+
+ err = GetErrorFromPack(p);
+ direction = PackGetInt(p, "direction");
+
+ if (c->Session->UseFastRC4)
+ {
+ // Get the RC4 key information
+ if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
+ {
+ PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
+ }
+ if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
+ {
+ PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
+ }
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ FreePack(p);
+ p = NULL;
+
+ if (err != 0)
+ {
+ // Error has occurred
+ Debug("Additional Connect Error: %u\n", err);
+ if (err == ERR_SESSION_TIMEOUT || err == ERR_INVALID_PROTOCOL)
+ {
+ // We shall re-connection because it is a fatal error
+ c->Session->SessionTimeOuted = true;
+ }
+ goto CLEANUP;
+ }
+
+ Debug("Additional Connect Succeed!\n");
+
+ // Success the additional connection
+ // Add to the TcpSockList of the connection
+ ts = NewTcpSock(s);
+
+ if (c->ServerMode == false)
+ {
+ if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
+ }
+ }
+
+ LockList(c->Tcp->TcpSockList);
+ {
+ ts->Direction = direction;
+ Add(c->Tcp->TcpSockList, ts);
+ }
+ UnlockList(c->Tcp->TcpSockList);
+ Debug("TCP Connection Incremented: %u\n", Count(c->CurrentNumConnection));
+
+ if (c->Session->HalfConnection)
+ {
+ Debug("New Half Connection: %s\n",
+ direction == TCP_SERVER_TO_CLIENT ? "TCP_SERVER_TO_CLIENT" : "TCP_CLIENT_TO_SERVER"
+ );
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // Set the RC4 encryption key
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, false);
+ }
+
+ // Issue the Cancel to the session
+ Cancel(c->Session->Cancel1);
+
+ // Remove the socket from the socket list of connected
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return true;
+
+CLEANUP:
+ // Disconnection process
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return false;
+}
+
+// Secure device signing thread
+void ClientSecureSignThread(THREAD *thread, void *param)
+{
+ SECURE_SIGN_THREAD_PROC *p = (SECURE_SIGN_THREAD_PROC *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ NoticeThreadInit(thread);
+
+ p->Ok = p->SecureSignProc(p->Connection->Session, p->Connection, p->SecureSign);
+ p->UserFinished = true;
+}
+
+// Signing with the secure device
+bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x)
+{
+ SECURE_SIGN_THREAD_PROC *p;
+ SECURE_SIGN *ss;
+ SESSION *s;
+ CLIENT_OPTION *o;
+ CLIENT_AUTH *a;
+ THREAD *thread;
+ UINT64 start;
+ bool ret;
+ // Validate arguments
+ if (c == NULL || sign == NULL || random == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ s = c->Session;
+ o = s->ClientOption;
+ a = s->ClientAuth;
+
+ p = ZeroMalloc(sizeof(SECURE_SIGN_THREAD_PROC));
+ p->Connection = c;
+ ss = p->SecureSign = ZeroMallocEx(sizeof(SECURE_SIGN), true);
+ StrCpy(ss->SecurePrivateKeyName, sizeof(ss->SecurePrivateKeyName),
+ a->SecurePrivateKeyName);
+ StrCpy(ss->SecurePublicCertName, sizeof(ss->SecurePublicCertName),
+ a->SecurePublicCertName);
+ ss->UseSecureDeviceId = c->Cedar->Client->UseSecureDeviceId;
+ Copy(ss->Random, random, SHA1_SIZE);
+
+#ifdef OS_WIN32
+ ss->BitmapId = CmGetSecureBitmapId(c->ServerName);
+#endif // OS_WIN32
+
+ p->SecureSignProc = a->SecureSignProc;
+
+ // Create a thread
+ thread = NewThread(ClientSecureSignThread, p);
+ WaitThreadInit(thread);
+
+ // Poll every 0.5 seconds until signing is completed or canceled
+ start = Tick64();
+ while (true)
+ {
+ if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
+ {
+ // Send a NOOP periodically for disconnection prevention
+ start = Tick64();
+ ClientUploadNoop(c);
+ }
+ if (p->UserFinished)
+ {
+ // User selected
+ break;
+ }
+ WaitThread(thread, 500);
+ }
+ ReleaseThread(thread);
+
+ ret = p->Ok;
+
+ if (ret)
+ {
+ Copy(sign, ss->Signature, 128);
+ *x = ss->ClientCert;
+ }
+
+ Free(p->SecureSign);
+ Free(p);
+
+ return ret;
+}
+
+// Server certificate confirmation thread
+void ClientCheckServerCertThread(THREAD *thread, void *param)
+{
+ CHECK_CERT_THREAD_PROC *p = (CHECK_CERT_THREAD_PROC *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Notify the completion of initialization
+ NoticeThreadInit(thread);
+
+ // Query for the selection to the user
+ p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Exipred);
+ p->UserSelected = true;
+}
+
+// Client verify the certificate of the server
+bool ClientCheckServerCert(CONNECTION *c, bool *expired)
+{
+ CLIENT_AUTH *auth;
+ X *x;
+ CHECK_CERT_THREAD_PROC *p;
+ THREAD *thread;
+ CEDAR *cedar;
+ bool ret;
+ UINT64 start;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ if (expired != NULL)
+ {
+ *expired = false;
+ }
+
+ auth = c->Session->ClientAuth;
+ cedar = c->Cedar;
+
+ if (auth->CheckCertProc == NULL && c->Session->LinkModeClient == false)
+ {
+ // No checking function
+ return true;
+ }
+
+ if (c->Session->LinkModeClient && c->Session->Link->CheckServerCert == false)
+ {
+ // It's in cascade connection mode, but do not check the server certificate
+ return true;
+ }
+
+ if (c->UseTicket)
+ {
+ // Check the certificate of the redirected VPN server
+ if (CompareX(c->FirstSock->RemoteX, c->ServerX) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ x = CloneX(c->FirstSock->RemoteX);
+ if (x == NULL)
+ {
+ // Strange error occurs
+ return false;
+ }
+
+ if (CheckXDateNow(x))
+ {
+ // Check whether it is signed by the root certificate to trust
+ if (c->Session->LinkModeClient == false)
+ {
+ // Normal VPN Client mode
+ if (CheckSignatureByCa(cedar, x))
+ {
+ // This certificate can be trusted because it is signed
+ FreeX(x);
+ return true;
+ }
+ }
+ else
+ {
+ // Cascade connection mode
+ if (CheckSignatureByCaLinkMode(c->Session, x))
+ {
+ // This certificate can be trusted because it is signed
+ FreeX(x);
+ return true;
+ }
+ }
+ }
+
+ if (c->Session->LinkModeClient)
+ {
+ if (CheckXDateNow(x))
+ {
+ Lock(c->Session->Link->lock);
+ {
+ if (c->Session->Link->ServerCert != NULL)
+ {
+ if (CompareX(c->Session->Link->ServerCert, x))
+ {
+ Unlock(c->Session->Link->lock);
+ // Exactly match the certificate that is registered in the cascade configuration
+ FreeX(x);
+ return true;
+ }
+ }
+ }
+ Unlock(c->Session->Link->lock);
+ }
+ else
+ {
+ if (expired != NULL)
+ {
+ *expired = true;
+ }
+ }
+
+ // Verification failure at this point in the case of cascade connection mode
+ FreeX(x);
+ return false;
+ }
+
+ p = ZeroMalloc(sizeof(CHECK_CERT_THREAD_PROC));
+ p->ServerX = x;
+ p->CheckCertProc = auth->CheckCertProc;
+ p->Connection = c;
+
+ // Create a thread
+ thread = NewThread(ClientCheckServerCertThread, p);
+ WaitThreadInit(thread);
+
+ // Poll at 0.5-second intervals until the user selects whether the connection
+ start = Tick64();
+ while (true)
+ {
+ if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
+ {
+ // Send a NOOP periodically for disconnection prevention
+ start = Tick64();
+ ClientUploadNoop(c);
+ }
+ if (p->UserSelected)
+ {
+ // User-selected
+ break;
+ }
+ WaitThread(thread, 500);
+ }
+
+ if (expired != NULL)
+ {
+ *expired = p->Exipred;
+ }
+
+ ret = p->Ok;
+ FreeX(p->ServerX);
+ Free(p);
+ ReleaseThread(thread);
+
+ return ret;
+}
+
+// Client connects to the server
+bool ClientConnect(CONNECTION *c)
+{
+ bool ret = false;
+ bool ok = false;
+ UINT err;
+ SOCK *s;
+ PACK *p = NULL;
+ UINT session_key_32;
+ SESSION *sess;
+ char session_name[MAX_SESSION_NAME_LEN + 1];
+ char connection_name[MAX_CONNECTION_NAME_LEN + 1];
+ UCHAR session_key[SHA1_SIZE];
+ RC4_KEY_PAIR key_pair;
+ POLICY *policy;
+ bool expired = false;
+ IP server_ip;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ sess = c->Session;
+
+ PrintStatus(sess, L"init");
+ PrintStatus(sess, _UU("STATUS_1"));
+
+REDIRECTED:
+
+ // [Connecting]
+ c->Status = CONNECTION_STATUS_CONNECTING;
+ c->Session->ClientStatus = CLIENT_STATUS_CONNECTING;
+
+ s = ClientConnectToServer(c);
+ if (s == NULL)
+ {
+ PrintStatus(sess, L"free");
+ return false;
+ }
+
+ Copy(&server_ip, &s->RemoteIP, sizeof(IP));
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ // [Negotiating]
+ c->Session->ClientStatus = CLIENT_STATUS_NEGOTIATION;
+
+ // Initialize the UDP acceleration function
+ if (sess->ClientOption != NULL && sess->ClientOption->NoUdpAcceleration == false)
+ {
+ if (sess->ClientOption->ProxyType == PROXY_DIRECT)
+ {
+ if (s->Type == SOCK_TCP)
+ {
+ if (sess->UdpAccel == NULL)
+ {
+ bool no_nat_t = false;
+
+ if (sess->ClientOption->PortUDP != 0)
+ {
+ // There is no need for NAT-T treatment on my part if the UDP port on the other end is known beforehand
+ no_nat_t = true;
+ }
+
+
+ sess->UdpAccel = NewUdpAccel(c->Cedar, &s->LocalIP, true, true, no_nat_t);
+ }
+ }
+ }
+ }
+
+ // Send a signature
+ Debug("Uploading Signature...\n");
+ if (ClientUploadSignature(s) == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ PrintStatus(sess, _UU("STATUS_5"));
+
+ // Receive a Hello packet
+ Debug("Downloading Hello...\n");
+ if (ClientDownloadHello(c, s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Session->ClientOption != NULL && c->Session->ClientOption->FromAdminPack)
+ {
+ if (IsAdminPackSupportedServerProduct(c->ServerStr) == false)
+ {
+ c->Err = ERR_NOT_ADMINPACK_SERVER;
+ goto CLEANUP;
+ }
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ Debug("Server Version : %u\n"
+ "Server String : %s\n"
+ "Server Build : %u\n"
+ "Client Version : %u\n"
+ "Client String : %s\n"
+ "Client Build : %u\n",
+ c->ServerVer, c->ServerStr, c->ServerBuild,
+ c->ClientVer, c->ClientStr, c->ClientBuild);
+
+ // During user authentication
+ c->Session->ClientStatus = CLIENT_STATUS_AUTH;
+
+ // Verify the server certificate by the client
+ if (ClientCheckServerCert(c, &expired) == false)
+ {
+ if (expired == false)
+ {
+ c->Err = ERR_CERT_NOT_TRUSTED;
+ }
+ else
+ {
+ c->Err = ERR_SERVER_CERT_EXPIRES;
+ }
+
+ if (c->Session->LinkModeClient == false && c->Err == ERR_CERT_NOT_TRUSTED)
+ {
+ c->Session->ForceStopFlag = true;
+ }
+
+ goto CLEANUP;
+ }
+
+ PrintStatus(sess, _UU("STATUS_6"));
+
+ // Send the authentication data
+ if (ClientUploadAuth(c) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ // Receive a Welcome packet
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ c->Err = ERR_DISCONNECTED;
+ goto CLEANUP;
+ }
+
+ // Error checking
+ err = GetErrorFromPack(p);
+ if (err != 0)
+ {
+ // An error has occured
+ c->Err = err;
+ c->ClientConnectError_NoSavePassword = PackGetBool(p, "no_save_password");
+ goto CLEANUP;
+ }
+
+ // Branding string check for the connection limit
+ {
+ char tmp[20];
+ char *branded_cfroms = _SS("BRANDED_C_FROM_S");
+ PackGetStr(p, "branded_cfroms", tmp, sizeof(tmp));
+
+ if(StrLen(branded_cfroms) > 0 && StrCmpi(branded_cfroms, tmp) != 0)
+ {
+ c->Err = ERR_BRANDED_C_FROM_S;
+ goto CLEANUP;
+ }
+ }
+
+ if (true)
+ {
+ // Message retrieval
+ UINT utf_size;
+ char *utf;
+ wchar_t *msg;
+
+ utf_size = PackGetDataSize(p, "Msg");
+ utf = ZeroMalloc(utf_size + 8);
+ PackGetData(p, "Msg", utf);
+
+ msg = CopyUtfToUni(utf);
+
+ if (IsEmptyUniStr(msg) == false)
+ {
+ if (c->Session->Client_Message != NULL)
+ {
+ Free(c->Session->Client_Message);
+ }
+
+ c->Session->Client_Message = msg;
+ }
+ else
+ {
+ Free(msg);
+ }
+
+ Free(utf);
+ }
+
+ if (PackGetInt(p, "Redirect") != 0)
+ {
+ UINT i;
+ UINT ip;
+ UINT num_port;
+ UINT *ports;
+ UINT use_port = 0;
+ UINT current_port = c->ServerPort;
+ UCHAR ticket[SHA1_SIZE];
+ X *server_cert;
+ BUF *b;
+
+ // Redirect mode
+ PrintStatus(sess, _UU("STATUS_8"));
+
+ ip = PackGetIp32(p, "Ip");
+ num_port = MAX(MIN(PackGetIndexCount(p, "Port"), MAX_PUBLIC_PORT_NUM), 1);
+ ports = ZeroMalloc(sizeof(UINT) * num_port);
+ for (i = 0;i < num_port;i++)
+ {
+ ports[i] = PackGetIntEx(p, "Port", i);
+ }
+
+ // Select a port number
+ for (i = 0;i < num_port;i++)
+ {
+ if (ports[i] == current_port)
+ {
+ use_port = current_port;
+ }
+ }
+ if (use_port == 0)
+ {
+ use_port = ports[0];
+ }
+
+ Free(ports);
+
+ if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
+ {
+ PackGetData(p, "Ticket", ticket);
+ }
+
+ b = PackGetBuf(p, "Cert");
+ if (b != NULL)
+ {
+ server_cert = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ if (c->ServerX != NULL)
+ {
+ FreeX(c->ServerX);
+ }
+ c->ServerX = server_cert;
+
+ IPToStr32(c->ServerName, sizeof(c->ServerName), ip);
+ c->ServerPort = use_port;
+
+ c->UseTicket = true;
+ Copy(c->Ticket, ticket, SHA1_SIZE);
+
+ FreePack(p);
+
+ p = NewPack();
+ HttpClientSend(s, p);
+ FreePack(p);
+
+ p = NULL;
+
+ c->FirstSock = NULL;
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+
+ goto REDIRECTED;
+ }
+
+ PrintStatus(sess, _UU("STATUS_7"));
+
+ // Parse the Welcome packet
+ if (ParseWelcomeFromPack(p, session_name, sizeof(session_name),
+ connection_name, sizeof(connection_name), &policy) == false)
+ {
+ // Parsing failure
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ // Get the session key
+ if (GetSessionKeyFromPack(p, session_key, &session_key_32) == false)
+ {
+ // Acquisition failure
+ Free(policy);
+ policy = NULL;
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ Copy(c->Session->SessionKey, session_key, SHA1_SIZE);
+ c->Session->SessionKey32 = session_key_32;
+
+ // Save the contents of the Welcome packet
+ Debug("session_name: %s, connection_name: %s\n",
+ session_name, connection_name);
+
+ Lock(c->Session->lock);
+ {
+ // Deploy and update connection parameters
+ sess->EnableUdpRecovery = PackGetBool(p, "enable_udp_recovery");
+ c->Session->MaxConnection = PackGetInt(p, "max_connection");
+
+ if (sess->EnableUdpRecovery == false)
+ {
+ c->Session->MaxConnection = MIN(c->Session->MaxConnection, c->Session->ClientOption->MaxConnection);
+ }
+
+ c->Session->MaxConnection = MIN(c->Session->MaxConnection, MAX_TCP_CONNECTION);
+ c->Session->MaxConnection = MAX(c->Session->MaxConnection, 1);
+ c->Session->UseCompress = PackGetInt(p, "use_compress") == 0 ? false : true;
+ c->Session->UseEncrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
+ c->Session->NoSendSignature = PackGetBool(p, "no_send_signature");
+ if (c->Session->UseEncrypt)
+ {
+ c->Session->UseFastRC4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
+ }
+ c->Session->HalfConnection = PackGetInt(p, "half_connection") == 0 ? false : true;
+ c->Session->IsAzureSession = PackGetInt(p, "is_azure_session") == 0 ? false : true;
+ c->Session->Timeout = PackGetInt(p, "timeout");
+ c->Session->QoS = PackGetInt(p, "qos") == 0 ? false : true;
+ if (c->Session->QoS)
+ {
+ c->Session->MaxConnection = MAX(c->Session->MaxConnection, (UINT)(c->Session->HalfConnection ? 4 : 2));
+ }
+ c->Session->VLanId = PackGetInt(p, "vlan_id");
+
+ // R-UDP Session ?
+ c->Session->IsRUDPSession = s->IsRUDPSocket;
+
+ ZeroIP4(&c->Session->AzureRealServerGlobalIp);
+
+ if (c->Session->IsAzureSession)
+ {
+ // Disable the life parameter of the connection in the case of VPN Azure relayed session
+ c->Session->ClientOption->ConnectionDisconnectSpan = 0;
+
+ // Get the AzureRealServerGlobalIp the case of VPN Azure relayed
+ PackGetIp(p, "azure_real_server_global_ip", &c->Session->AzureRealServerGlobalIp);
+ }
+
+ if (c->Session->IsRUDPSession)
+ {
+ // Disable the life parameter of the connection in the case of R-UDP session
+ c->Session->ClientOption->ConnectionDisconnectSpan = 0;
+
+ // Disable QoS, etc. in the case of R-UDP session
+ c->Session->QoS = false;
+ c->Session->HalfConnection = false;
+
+ if (c->Session->EnableUdpRecovery == false)
+ {
+ // Set the number of connection to 1 if UDP recovery is not supported
+ c->Session->MaxConnection = 1;
+ }
+ }
+
+ // Physical communication protocol
+ StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), s->UnderlayProtocol);
+
+ if (c->Session->IsAzureSession)
+ {
+ StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), SOCK_UNDERLAY_AZURE);
+ }
+
+ if (c->Protocol == CONNECTION_UDP)
+ {
+ // In the case of UDP protocol, receive the key from the server
+ if (PackGetDataSize(p, "udp_send_key") == sizeof(c->Session->UdpSendKey))
+ {
+ PackGetData(p, "udp_send_key", c->Session->UdpSendKey);
+ }
+
+ if (PackGetDataSize(p, "udp_recv_key") == sizeof(c->Session->UdpRecvKey))
+ {
+ PackGetData(p, "udp_recv_key", c->Session->UdpRecvKey);
+ }
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // Get the RC4 key information
+ if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
+ {
+ PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
+ }
+ if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
+ {
+ PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
+ }
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ sess->EnableBulkOnRUDP = false;
+ sess->EnableHMacOnBulkOfRUDP = false;
+ if (s != NULL && s->IsRUDPSocket && s->BulkRecvKey != NULL && s->BulkSendKey != NULL)
+ {
+ // Bulk transfer on R-UDP
+ if (PackGetBool(p, "enable_bulk_on_rudp"))
+ {
+ // Receive the key
+ UCHAR key_send[SHA1_SIZE];
+ UCHAR key_recv[SHA1_SIZE];
+
+ if (PackGetData2(p, "bulk_on_rudp_send_key", key_send, SHA1_SIZE) &&
+ PackGetData2(p, "bulk_on_rudp_recv_key", key_recv, SHA1_SIZE))
+ {
+ sess->EnableBulkOnRUDP = true;
+
+ Copy(s->BulkSendKey->Data, key_send, SHA1_SIZE);
+ Copy(s->BulkRecvKey->Data, key_recv, SHA1_SIZE);
+ }
+ }
+
+ sess->EnableHMacOnBulkOfRUDP = PackGetBool(p, "enable_hmac_on_bulk_of_rudp");
+ }
+
+ Debug("EnableBulkOnRUDP = %u\n", sess->EnableBulkOnRUDP);
+ Debug("EnableHMacOnBulkOfRUDP = %u\n", sess->EnableHMacOnBulkOfRUDP);
+ Debug("EnableUdpRecovery = %u\n", sess->EnableUdpRecovery);
+
+ sess->UseUdpAcceleration = false;
+ sess->IsUsingUdpAcceleration = false;
+ sess->UseHMacOnUdpAcceleration = false;
+
+ if (sess->UdpAccel != NULL)
+ {
+ sess->UdpAccel->UseHMac = false;
+
+ sess->UdpAccelFastDisconnectDetect = false;
+
+ if (PackGetBool(p, "use_udp_acceleration"))
+ {
+ IP udp_acceleration_server_ip;
+
+ sess->UdpAccelFastDisconnectDetect = PackGetBool(p, "udp_accel_fast_disconnect_detect");
+
+ if (PackGetIp(p, "udp_acceleration_server_ip", &udp_acceleration_server_ip))
+ {
+ UINT udp_acceleration_server_port = PackGetInt(p, "udp_acceleration_server_port");
+
+ if (IsZeroIp(&udp_acceleration_server_ip))
+ {
+ Copy(&udp_acceleration_server_ip, &s->RemoteIP, sizeof(IP));
+ }
+
+ if (udp_acceleration_server_port != 0)
+ {
+ UCHAR udp_acceleration_server_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
+
+ if (PackGetData2(p, "udp_acceleration_server_key", udp_acceleration_server_key, UDP_ACCELERATION_COMMON_KEY_SIZE))
+ {
+ UINT server_cookie = PackGetInt(p, "udp_acceleration_server_cookie");
+ UINT client_cookie = PackGetInt(p, "udp_acceleration_client_cookie");
+ bool encryption = PackGetBool(p, "udp_acceleration_use_encryption");
+
+ if (server_cookie != 0 && client_cookie != 0)
+ {
+ IP remote_ip;
+
+ Copy(&remote_ip, &s->RemoteIP, sizeof(IP));
+
+ if (IsZeroIp(&c->Session->AzureRealServerGlobalIp) == false)
+ {
+ Copy(&remote_ip, &c->Session->AzureRealServerGlobalIp, sizeof(IP));
+ }
+
+ if (UdpAccelInitClient(sess->UdpAccel, udp_acceleration_server_key,
+ &udp_acceleration_server_ip, udp_acceleration_server_port,
+ server_cookie, client_cookie, &remote_ip) == false)
+ {
+ Debug("UdpAccelInitClient failed.\n");
+ }
+ else
+ {
+ sess->UseUdpAcceleration = true;
+
+ sess->UdpAccel->FastDetect = sess->UdpAccelFastDisconnectDetect;
+
+ sess->UdpAccel->PlainTextMode = !encryption;
+
+ sess->UseHMacOnUdpAcceleration = PackGetBool(p, "use_hmac_on_udp_acceleration");
+
+ if (sess->UseHMacOnUdpAcceleration)
+ {
+ sess->UdpAccel->UseHMac = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Unlock(c->Session->lock);
+
+ Debug("UseUdpAcceleration = %u\n", sess->UseUdpAcceleration);
+
+ if (sess->UseUdpAcceleration == false)
+ {
+ if (sess->UdpAccel != NULL)
+ {
+ FreeUdpAccel(sess->UdpAccel);
+ sess->UdpAccel = NULL;
+ }
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Name != NULL)
+ {
+ Free(c->Name);
+ }
+ c->Name = CopyStr(connection_name);
+
+ // Save the name of a cryptographic algorithm
+ if (c->CipherName != NULL)
+ {
+ Free(c->CipherName);
+ }
+
+ c->CipherName = CopyStr(c->FirstSock->CipherName);
+ }
+ Unlock(c->lock);
+
+ Lock(c->Session->lock);
+ {
+ if (c->Session->Name != NULL)
+ {
+ Free(c->Session->Name);
+ }
+ c->Session->Name = CopyStr(session_name);
+
+ c->Session->Policy = policy;
+ }
+ Unlock(c->Session->lock);
+
+ // Discard the Welcome packet
+ FreePack(p);
+ p = NULL;
+
+
+ // Connection establishment
+ c->Session->ClientStatus = CLIENT_STATUS_ESTABLISHED;
+
+ // Save the server certificate
+ if (c->ServerX == NULL)
+ {
+ c->ServerX = CloneX(c->FirstSock->RemoteX);
+ }
+
+ PrintStatus(sess, _UU("STATUS_9"));
+
+ // Shift the connection to the tunneling mode
+ StartTunnelingMode(c);
+ s = NULL;
+
+ if (c->Session->HalfConnection)
+ {
+ // Processing in the case of half-connection
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ ts->Direction = TCP_CLIENT_TO_SERVER;
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // Set the high-speed RC4 encryption key
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(key_pair));
+
+ InitTcpSockRc4Key(ts, false);
+ }
+
+ // SSL encryption flag
+ if (c->Session->UseEncrypt && c->Session->UseFastRC4 == false)
+ {
+ c->Session->UseSSLDataEncryption = true;
+ }
+ else
+ {
+ c->Session->UseSSLDataEncryption = false;
+ }
+
+ PrintStatus(sess, L"free");
+
+ CLog(c->Cedar->Client, "LC_CONNECT_2", c->Session->ClientOption->AccountName,
+ session_name);
+
+ if (c->Session->LinkModeClient && c->Session->Link != NULL)
+ {
+ HLog(c->Session->Link->Hub, "LH_CONNECT_2", c->Session->ClientOption->AccountName, session_name);
+ }
+
+ // Main routine of the session
+ SessionMain(c->Session);
+
+ ok = true;
+
+ if (c->Err == ERR_USER_CANCEL)
+ {
+ ret = true;
+ }
+
+CLEANUP:
+ c->FirstSock = NULL;
+
+ if (sess->UdpAccel != NULL)
+ {
+ FreeUdpAccel(sess->UdpAccel);
+ sess->UdpAccel = NULL;
+ }
+
+ if (p != NULL)
+ {
+ FreePack(p);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ Debug("Error: %u\n", c->Err);
+
+ if (ok == false)
+ {
+ PrintStatus(sess, L"free");
+ }
+
+ return ret;
+}
+
+// Parse the Welcome packet
+bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
+ char *connection_name, UINT connection_name_size,
+ POLICY **policy)
+{
+ // Validate arguments
+ if (p == NULL || session_name == NULL || connection_name == NULL || policy == NULL)
+ {
+ return false;
+ }
+
+ // Session name
+ if (PackGetStr(p, "session_name", session_name, session_name_size) == false)
+ {
+ return false;
+ }
+
+ // Connection name
+ if (PackGetStr(p, "connection_name", connection_name, connection_name_size) == false)
+ {
+ return false;
+ }
+
+ // Policy
+ *policy = PackGetPolicy(p);
+ if (*policy == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Generate the Welcome packet
+PACK *PackWelcome(SESSION *s)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+
+ // Session name
+ PackAddStr(p, "session_name", s->Name);
+
+ // Connection name
+ PackAddStr(p, "connection_name", s->Connection->Name);
+
+ // Parameters
+ PackAddInt(p, "max_connection", s->MaxConnection);
+ PackAddInt(p, "use_encrypt", s->UseEncrypt == false ? 0 : 1);
+ PackAddInt(p, "use_fast_rc4", s->UseFastRC4 == false ? 0 : 1);
+ PackAddInt(p, "use_compress", s->UseCompress == false ? 0 : 1);
+ PackAddInt(p, "half_connection", s->HalfConnection == false ? 0 : 1);
+ PackAddInt(p, "timeout", s->Timeout);
+ PackAddInt(p, "qos", s->QoS ? 1 : 0);
+ PackAddInt(p, "is_azure_session", s->IsAzureSession);
+
+ // Session key
+ PackAddData(p, "session_key", s->SessionKey, SHA1_SIZE);
+ PackAddInt(p, "session_key_32", s->SessionKey32);
+
+ // Policy
+ PackAddPolicy(p, s->Policy);
+
+ // VLAN ID
+ PackAddInt(p, "vlan_id", s->VLanId);
+
+ if (s->Connection->Protocol == CONNECTION_UDP)
+ {
+ // In the case of UDP protocol, generate 2 pairs of key
+ Rand(s->UdpSendKey, sizeof(s->UdpSendKey));
+ Rand(s->UdpRecvKey, sizeof(s->UdpRecvKey));
+
+ // Send to client by exchanging 2 keys
+ PackAddData(p, "udp_send_key", s->UdpRecvKey, sizeof(s->UdpRecvKey));
+ PackAddData(p, "udp_recv_key", s->UdpSendKey, sizeof(s->UdpSendKey));
+ }
+
+ // no_send_signature
+ if (s->NoSendSignature)
+ {
+ PackAddBool(p, "no_send_signature", true);
+ }
+
+ if (s->InProcMode)
+ {
+ // MAC address for IPC
+ PackAddData(p, "IpcMacAddress", s->IpcMacAddress, 6);
+
+ // Virtual HUB name
+ PackAddStr(p, "IpcHubName", s->Hub->Name);
+ }
+
+ if (s->UdpAccel != NULL)
+ {
+ // UDP acceleration function
+ PackAddBool(p, "use_udp_acceleration", true);
+ PackAddIp(p, "udp_acceleration_server_ip", &s->UdpAccel->MyIp);
+ PackAddInt(p, "udp_acceleration_server_port", s->UdpAccel->MyPort);
+ PackAddData(p, "udp_acceleration_server_key", s->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ PackAddInt(p, "udp_acceleration_server_cookie", s->UdpAccel->MyCookie);
+ PackAddInt(p, "udp_acceleration_client_cookie", s->UdpAccel->YourCookie);
+ PackAddBool(p, "udp_acceleration_use_encryption", !s->UdpAccel->PlainTextMode);
+ PackAddBool(p, "use_hmac_on_udp_acceleration", s->UdpAccel->UseHMac);
+ PackAddBool(p, "udp_accel_fast_disconnect_detect", s->UdpAccelFastDisconnectDetect);
+ }
+
+ if (s->EnableBulkOnRUDP)
+ {
+ // Allow bulk transfer on R-UDP
+ PackAddBool(p, "enable_bulk_on_rudp", true);
+ PackAddBool(p, "enable_hmac_on_bulk_of_rudp", s->EnableHMacOnBulkOfRUDP);
+
+ PackAddData(p, "bulk_on_rudp_send_key", s->Connection->FirstSock->BulkRecvKey->Data, SHA1_SIZE);
+ PackAddData(p, "bulk_on_rudp_recv_key", s->Connection->FirstSock->BulkSendKey->Data, SHA1_SIZE);
+ }
+
+ if (s->IsAzureSession)
+ {
+ if (s->Connection != NULL && s->Connection->FirstSock != NULL)
+ {
+ SOCK *sock = s->Connection->FirstSock;
+
+ PackAddIp(p, "azure_real_server_global_ip", &sock->Reverse_MyServerGlobalIp);
+ }
+ }
+
+ PackAddBool(p, "enable_udp_recovery", s->EnableUdpRecovery);
+
+ return p;
+}
+
+#define PACK_ADD_POLICY_BOOL(name, value) \
+ PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
+#define PACK_ADD_POLICY_UINT(name, value) \
+ PackAddInt(p, "policy:" name, y->value)
+#define PACK_GET_POLICY_BOOL(name, value) \
+ y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
+#define PACK_GET_POLICY_UINT(name, value) \
+ y->value = PackGetInt(p, "policy:" name)
+
+// Get a PACK from the session key
+bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32)
+{
+ // Validate arguments
+ if (p == NULL || session_key == NULL || session_key_32 == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetDataSize(p, "session_key") != SHA1_SIZE)
+ {
+ return false;
+ }
+ if (PackGetData(p, "session_key", session_key) == false)
+ {
+ return false;
+ }
+ *session_key_32 = PackGetInt(p, "session_key_32");
+
+ return true;
+}
+
+// Get the policy from the PACK
+POLICY *PackGetPolicy(PACK *p)
+{
+ POLICY *y;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ y = ZeroMalloc(sizeof(POLICY));
+
+ // Bool value
+ // Ver 2
+ PACK_GET_POLICY_BOOL("Access", Access);
+ PACK_GET_POLICY_BOOL("DHCPFilter", DHCPFilter);
+ PACK_GET_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
+ PACK_GET_POLICY_BOOL("DHCPForce", DHCPForce);
+ PACK_GET_POLICY_BOOL("NoBridge", NoBridge);
+ PACK_GET_POLICY_BOOL("NoRouting", NoRouting);
+ PACK_GET_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
+ PACK_GET_POLICY_BOOL("NoServer", NoServer);
+ PACK_GET_POLICY_BOOL("CheckMac", CheckMac);
+ PACK_GET_POLICY_BOOL("CheckIP", CheckIP);
+ PACK_GET_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
+ PACK_GET_POLICY_BOOL("MonitorPort", MonitorPort);
+ PACK_GET_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
+ PACK_GET_POLICY_BOOL("FixPassword", FixPassword);
+ PACK_GET_POLICY_BOOL("NoQoS", NoQoS);
+ // Ver 3
+ PACK_GET_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
+ PACK_GET_POLICY_BOOL("RAFilter", RAFilter);
+ PACK_GET_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
+ PACK_GET_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
+ PACK_GET_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
+ PACK_GET_POLICY_BOOL("CheckIPv6", CheckIPv6);
+ PACK_GET_POLICY_BOOL("NoServerV6", NoServerV6);
+ PACK_GET_POLICY_BOOL("NoSavePassword", NoSavePassword);
+ PACK_GET_POLICY_BOOL("FilterIPv4", FilterIPv4);
+ PACK_GET_POLICY_BOOL("FilterIPv6", FilterIPv6);
+ PACK_GET_POLICY_BOOL("FilterNonIP", FilterNonIP);
+ PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
+ PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
+
+ // UINT value
+ // Ver 2
+ PACK_GET_POLICY_UINT("MaxConnection", MaxConnection);
+ PACK_GET_POLICY_UINT("TimeOut", TimeOut);
+ PACK_GET_POLICY_UINT("MaxMac", MaxMac);
+ PACK_GET_POLICY_UINT("MaxIP", MaxIP);
+ PACK_GET_POLICY_UINT("MaxUpload", MaxUpload);
+ PACK_GET_POLICY_UINT("MaxDownload", MaxDownload);
+ PACK_GET_POLICY_UINT("MultiLogins", MultiLogins);
+ // Ver 3
+ PACK_GET_POLICY_UINT("MaxIPv6", MaxIPv6);
+ PACK_GET_POLICY_UINT("AutoDisconnect", AutoDisconnect);
+ PACK_GET_POLICY_UINT("VLanId", VLanId);
+
+ // Ver 3 flag
+ PACK_GET_POLICY_BOOL("Ver3", Ver3);
+
+ return y;
+}
+
+// Insert the policy into the PACK
+void PackAddPolicy(PACK *p, POLICY *y)
+{
+ // Validate arguments
+ if (p == NULL || y == NULL)
+ {
+ return;
+ }
+
+ // Bool value
+ // Ver 2
+ PACK_ADD_POLICY_BOOL("Access", Access);
+ PACK_ADD_POLICY_BOOL("DHCPFilter", DHCPFilter);
+ PACK_ADD_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
+ PACK_ADD_POLICY_BOOL("DHCPForce", DHCPForce);
+ PACK_ADD_POLICY_BOOL("NoBridge", NoBridge);
+ PACK_ADD_POLICY_BOOL("NoRouting", NoRouting);
+ PACK_ADD_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
+ PACK_ADD_POLICY_BOOL("NoServer", NoServer);
+ PACK_ADD_POLICY_BOOL("CheckMac", CheckMac);
+ PACK_ADD_POLICY_BOOL("CheckIP", CheckIP);
+ PACK_ADD_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
+ PACK_ADD_POLICY_BOOL("MonitorPort", MonitorPort);
+ PACK_ADD_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
+ PACK_ADD_POLICY_BOOL("FixPassword", FixPassword);
+ PACK_ADD_POLICY_BOOL("NoQoS", NoQoS);
+ // Ver 3
+ PACK_ADD_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
+ PACK_ADD_POLICY_BOOL("RAFilter", RAFilter);
+ PACK_ADD_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
+ PACK_ADD_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
+ PACK_ADD_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
+ PACK_ADD_POLICY_BOOL("CheckIPv6", CheckIPv6);
+ PACK_ADD_POLICY_BOOL("NoServerV6", NoServerV6);
+ PACK_ADD_POLICY_BOOL("NoSavePassword", NoSavePassword);
+ PACK_ADD_POLICY_BOOL("FilterIPv4", FilterIPv4);
+ PACK_ADD_POLICY_BOOL("FilterIPv6", FilterIPv6);
+ PACK_ADD_POLICY_BOOL("FilterNonIP", FilterNonIP);
+ PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
+ PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
+
+ // UINT value
+ // Ver 2
+ PACK_ADD_POLICY_UINT("MaxConnection", MaxConnection);
+ PACK_ADD_POLICY_UINT("TimeOut", TimeOut);
+ PACK_ADD_POLICY_UINT("MaxMac", MaxMac);
+ PACK_ADD_POLICY_UINT("MaxIP", MaxIP);
+ PACK_ADD_POLICY_UINT("MaxUpload", MaxUpload);
+ PACK_ADD_POLICY_UINT("MaxDownload", MaxDownload);
+ PACK_ADD_POLICY_UINT("MultiLogins", MultiLogins);
+ // Ver 3
+ PACK_ADD_POLICY_UINT("MaxIPv6", MaxIPv6);
+ PACK_ADD_POLICY_UINT("AutoDisconnect", AutoDisconnect);
+ PACK_ADD_POLICY_UINT("VLanId", VLanId);
+
+ // Ver 3 flag
+ PackAddBool(p, "policy:Ver3", true);
+}
+
+// Upload the authentication data for the additional connection
+bool ClientUploadAuth2(CONNECTION *c, SOCK *s)
+{
+ PACK *p = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ p = PackAdditionalConnect(c->Session->SessionKey);
+
+ PackAddClientVersion(p, c);
+
+ if (HttpClientSend(s, p) == false)
+ {
+ FreePack(p);
+ return false;
+ }
+ FreePack(p);
+
+ return true;
+}
+
+// Send a NOOP
+void ClientUploadNoop(CONNECTION *c)
+{
+ PACK *p;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ p = PackError(0);
+ PackAddInt(p, "noop", 1);
+ HttpClientSend(c->FirstSock, p);
+ FreePack(p);
+
+ p = HttpClientRecv(c->FirstSock);
+ if (p != NULL)
+ {
+ FreePack(p);
+ }
+}
+
+// Add client version information to the PACK
+void PackAddClientVersion(PACK *p, CONNECTION *c)
+{
+ // Validate arguments
+ if (p == NULL || c == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "client_str", c->ClientStr);
+ PackAddInt(p, "client_ver", c->ClientVer);
+ PackAddInt(p, "client_build", c->ClientBuild);
+}
+
+// Upload the certificate data for the new connection
+bool ClientUploadAuth(CONNECTION *c)
+{
+ PACK *p = NULL;
+ CLIENT_AUTH *a;
+ CLIENT_OPTION *o;
+ X *x;
+ bool ret;
+ NODE_INFO info;
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR sign[4096 / 8];
+ UCHAR unique[SHA1_SIZE];
+ RPC_WINVER v;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Zero(sign, sizeof(sign));
+
+ a = c->Session->ClientAuth;
+ o = c->Session->ClientOption;
+
+ if (c->UseTicket == false)
+ {
+ switch (a->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ // Anonymous authentication
+ p = PackLoginWithAnonymous(o->HubName, a->Username);
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // Password authentication
+ SecurePassword(secure_password, a->HashedPassword, c->Random);
+ p = PackLoginWithPassword(o->HubName, a->Username, secure_password);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ // Plaintext password authentication
+ p = PackLoginWithPlainPassword(o->HubName, a->Username, a->PlainPassword);
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ // Certificate authentication
+ if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
+ a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
+ {
+ if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
+ {
+ p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
+ c->ClientX = CloneX(a->ClientX);
+ }
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ // Authentication by secure device
+ if (ClientSecureSign(c, sign, c->Random, &x))
+ {
+ p = PackLoginWithCert(o->HubName, a->Username, x, sign, 128);
+ c->ClientX = CloneX(x);
+ FreeX(x);
+ }
+ else
+ {
+ c->Err = ERR_SECURE_DEVICE_OPEN_FAILED;
+ c->Session->ForceStopFlag = true;
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Ticket
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", o->HubName);
+ PackAddStr(p, "username", a->Username);
+ PackAddInt(p, "authtype", AUTHTYPE_TICKET);
+ PackAddData(p, "ticket", c->Ticket, SHA1_SIZE);
+ }
+
+ // Current time
+ PackAddInt64(p, "timestamp", SystemTime64());
+
+ if (p == NULL)
+ {
+ // Error
+ if (c->Err != ERR_SECURE_DEVICE_OPEN_FAILED)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ return false;
+ }
+
+ PackAddClientVersion(p, c);
+
+ // Protocol
+ PackAddInt(p, "protocol", c->Protocol);
+
+ // Version, etc.
+ PackAddStr(p, "hello", c->ClientStr);
+ PackAddInt(p, "version", c->ClientVer);
+ PackAddInt(p, "build", c->ClientBuild);
+ PackAddInt(p, "client_id", c->Cedar->ClientId);
+
+ // The maximum number of connections
+ PackAddInt(p, "max_connection", o->MaxConnection);
+ // Flag to use of cryptography
+ PackAddInt(p, "use_encrypt", o->UseEncrypt == false ? 0 : 1);
+ // Fast encryption using flag
+ // PackAddInt(p, "use_fast_rc4", o->UseFastRC4 == false ? 0 : 1);
+ // Data compression flag
+ PackAddInt(p, "use_compress", o->UseCompress == false ? 0 : 1);
+ // Half connection flag
+ PackAddInt(p, "half_connection", o->HalfConnection == false ? 0 : 1);
+
+ // Bridge / routing mode flag
+ PackAddBool(p, "require_bridge_routing_mode", o->RequireBridgeRoutingMode);
+
+ // Monitor mode flag
+ PackAddBool(p, "require_monitor_mode", o->RequireMonitorMode);
+
+ // VoIP / QoS flag
+ PackAddBool(p, "qos", o->DisableQoS ? false : true);
+
+ // Bulk transfer support
+ PackAddBool(p, "support_bulk_on_rudp", true);
+ PackAddBool(p, "support_hmac_on_bulk_of_rudp", true);
+
+ // UDP recovery support
+ PackAddBool(p, "support_udp_recovery", true);
+
+ // Unique ID
+ GenerateMachineUniqueHash(unique);
+ PackAddData(p, "unique_id", unique, SHA1_SIZE);
+
+ // UDP acceleration function using flag
+ if (o->NoUdpAcceleration == false && c->Session->UdpAccel != NULL)
+ {
+ PackAddBool(p, "use_udp_acceleration", true);
+ PackAddIp(p, "udp_acceleration_client_ip", &c->Session->UdpAccel->MyIp);
+ PackAddInt(p, "udp_acceleration_client_port", c->Session->UdpAccel->MyPort);
+ PackAddData(p, "udp_acceleration_client_key", c->Session->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ PackAddBool(p, "support_hmac_on_udp_acceleration", true);
+ PackAddBool(p, "support_udp_accel_fast_disconnect_detect", true);
+ }
+
+ // Brand string for the connection limit
+ {
+ char *branded_ctos = _SS("BRANDED_C_TO_S");
+ if(StrLen(branded_ctos) > 0)
+ {
+ PackAddStr(p, "branded_ctos", branded_ctos);
+ }
+ }
+
+ // Node information
+ CreateNodeInfo(&info, c);
+ OutRpcNodeInfo(p, &info);
+
+ // OS information
+ GetWinVer(&v);
+ OutRpcWinVer(p, &v);
+
+ ret = HttpClientSend(c->FirstSock, p);
+ if (ret == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ }
+
+ FreePack(p);
+
+ return ret;
+}
+
+// Upload the Hello packet
+bool ServerUploadHello(CONNECTION *c)
+{
+ PACK *p;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // Random number generation
+ Rand(c->Random, SHA1_SIZE);
+
+ p = PackHello(c->Random, c->ServerVer, c->ServerBuild, c->ServerStr);
+ if (HttpServerSend(c->FirstSock, p) == false)
+ {
+ FreePack(p);
+ c->Err = ERR_DISCONNECTED;
+ return false;
+ }
+
+ FreePack(p);
+
+ return true;
+}
+
+// Download the Hello packet
+bool ClientDownloadHello(CONNECTION *c, SOCK *s)
+{
+ PACK *p;
+ UINT err;
+ UCHAR random[SHA1_SIZE];
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // Data reception
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return false;
+ }
+
+ if (err = GetErrorFromPack(p))
+ {
+ // An error has occured
+ c->Err = err;
+ FreePack(p);
+ return false;
+ }
+
+ // Packet interpretation
+ if (GetHello(p, random, &c->ServerVer, &c->ServerBuild, c->ServerStr, sizeof(c->ServerStr)) == false)
+ {
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ FreePack(p);
+ return false;
+ }
+
+ if (c->FirstSock == s)
+ {
+ Copy(c->Random, random, SHA1_SIZE);
+ }
+
+ FreePack(p);
+
+ return true;
+}
+
+// Download the signature
+bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
+{
+ HTTP_HEADER *h;
+ UCHAR *data;
+ UINT data_size;
+ SOCK *s;
+ UINT num = 0, max = 19;
+ SERVER *server;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ server = c->Cedar->Server;
+
+ s = c->FirstSock;
+
+ while (true)
+ {
+ num++;
+ if (num > max)
+ {
+ // Disconnect
+ Disconnect(s);
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+
+ *error_detail_str = "HTTP_TOO_MANY_REQUEST";
+ return false;
+ }
+ // Receive a header
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+ return false;
+ }
+
+ // Interpret
+ if (StrCmpi(h->Method, "POST") == 0)
+ {
+ // Receive the data since it's POST
+ data_size = GetContentLength(h);
+ if ((data_size > MAX_WATERMARK_SIZE || data_size < SizeOfWaterMark()) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
+ {
+ // Data is too large
+ HttpSendForbidden(s, h->Target, NULL);
+ FreeHttpHeader(h);
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+ *error_detail_str = "POST_Recv_TooLong";
+ return false;
+ }
+ data = Malloc(data_size);
+ if (RecvAll(s, data, data_size, s->SecureMode) == false)
+ {
+ // Data reception failure
+ Free(data);
+ FreeHttpHeader(h);
+ c->Err = ERR_DISCONNECTED;
+ *error_detail_str = "POST_Recv_Failed";
+ return false;
+ }
+ // Check the Target
+ if (StrCmpi(h->Target, HTTP_VPN_TARGET2) != 0)
+ {
+ // Target is invalid
+ HttpSendNotFound(s, h->Target);
+ Free(data);
+ FreeHttpHeader(h);
+ *error_detail_str = "POST_Target_Wrong";
+ }
+ else
+ {
+ // Compare posted data with the WaterMark
+ if ((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0))
+ || (Cmp(data, WaterMark, SizeOfWaterMark()) == 0))
+ {
+ // Check the WaterMark
+ Free(data);
+ FreeHttpHeader(h);
+ return true;
+ }
+ else
+ {
+ // WaterMark is incorrect
+ HttpSendForbidden(s, h->Target, NULL);
+ FreeHttpHeader(h);
+ *error_detail_str = "POST_WaterMark_Error";
+ }
+ }
+ }
+ else if (StrCmpi(h->Method, "SSTP_DUPLEX_POST") == 0 && (server->DisableSSTPServer == false || s->IsReverseAcceptedSocket
+ ) &&
+ GetServerCapsBool(server, "b_support_sstp") && GetNoSstp() == false)
+ {
+ // SSTP client is connected
+ c->WasSstp = true;
+
+ if (StrCmpi(h->Target, SSTP_URI) == 0)
+ {
+ bool sstp_ret;
+ // Accept the SSTP connection
+ c->Type = CONNECTION_TYPE_SSTP;
+
+ sstp_ret = AcceptSstp(c);
+
+ c->Err = ERR_DISCONNECTED;
+ FreeHttpHeader(h);
+
+ if (sstp_ret)
+ {
+ *error_detail_str = "";
+ }
+ else
+ {
+ *error_detail_str = "SSTP_ABORT";
+ }
+
+ return false;
+ }
+ else
+ {
+ // URI is invalid
+ HttpSendNotFound(s, h->Target);
+ *error_detail_str = "SSTP_URL_WRONG";
+ }
+
+ FreeHttpHeader(h);
+ }
+ else
+ {
+ // This should not be a VPN client, but interpret a bit more
+ if (StrCmpi(h->Method, "GET") != 0)
+ {
+ // Unsupported method calls
+ HttpSendNotImplemented(s, h->Method, h->Target, h->Version);
+ *error_detail_str = "HTTP_BAD_METHOD";
+ }
+ else
+ {
+
+ if (StrCmpi(h->Target, "/") == 0)
+ {
+ // Root directory
+ SERVER *s = c->Cedar->Server;
+ bool is_free = false;
+
+ *error_detail_str = "HTTP_ROOT";
+
+ if (s != NULL && s->UseWebTimePage)
+ {
+ // Generate a page that shows the current time as the top page automatically
+ BUF *b = ReadDump("|time.htm");
+
+ if (b != NULL)
+ {
+ char *src = ZeroMalloc(b->Size + 1);
+ UINT dst_size = b->Size * 2 + 64;
+ char *dst = ZeroMalloc(dst_size);
+ char host[MAX_PATH];
+ char portstr[64];
+ char now_str[MAX_PATH];
+
+ GetDateTimeStr64(now_str, sizeof(now_str), LocalTime64());
+
+ GetMachineName(host, sizeof(host));
+ ToStr(portstr, c->FirstSock->LocalPort);
+
+ Copy(src, b->Buf, b->Size);
+ ReplaceStrEx(dst, dst_size, src,
+ "$HOST$", host, false);
+ ReplaceStrEx(dst, dst_size, dst,
+ "$PORT$", portstr, false);
+ ReplaceStrEx(dst, dst_size, dst,
+ "$NOW$", now_str, false);
+
+ FreeHttpHeader(h);
+ h = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ PostHttp(c->FirstSock, h, dst, StrLen(dst));
+
+ Free(src);
+ Free(dst);
+
+ FreeBuf(b);
+ }
+ }
+ else
+ {
+ if (is_free == false)
+ {
+ // Other than free version
+ HttpSendForbidden(c->FirstSock, h->Target, "");
+ }
+ else
+ {
+ // Free version
+ BUF *b = ReadDump("|free.htm");
+
+ if (b != NULL)
+ {
+ char *src = ZeroMalloc(b->Size + 1);
+ UINT dst_size = b->Size * 2 + 64;
+ char *dst = ZeroMalloc(dst_size);
+ char host[MAX_PATH];
+ char portstr[64];
+
+ GetMachineName(host, sizeof(host));
+ ToStr(portstr, c->FirstSock->LocalPort);
+
+ Copy(src, b->Buf, b->Size);
+ ReplaceStrEx(dst, dst_size, src,
+ "$HOST$", host, false);
+ ReplaceStrEx(dst, dst_size, dst,
+ "$PORT$", portstr, false);
+
+ FreeHttpHeader(h);
+ h = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ PostHttp(c->FirstSock, h, dst, StrLen(dst));
+
+ Free(src);
+ Free(dst);
+
+ FreeBuf(b);
+ }
+ }
+ }
+ }
+ else
+ {
+ bool b = false;
+
+ // Show the WebUI if the configuration allow to use the WebUI
+ if (c->Cedar->Server != NULL && c->Cedar->Server->UseWebUI)
+ {
+ WU_WEBPAGE *page;
+
+ // Show the WebUI
+ page = WuGetPage(h->Target, c->Cedar->WebUI);
+
+ if (page != NULL)
+ {
+ PostHttp(s, page->header, page->data, page->size);
+ b = true;
+ WuFreeWebPage(page);
+ }
+
+ }
+
+ if (c->FirstSock->RemoteIP.addr[0] == 127)
+ {
+ if (StrCmpi(h->Target, HTTP_SAITAMA) == 0)
+ {
+ // Saitama (joke)
+ FreeHttpHeader(h);
+ h = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ PostHttp(s, h, Saitama, SizeOfSaitama());
+ b = true;
+ }
+ else if (StartWith(h->Target, HTTP_PICTURES))
+ {
+ BUF *buf;
+
+ // Lots of photos
+ buf = ReadDump("|Pictures.mht");
+
+ if (buf != NULL)
+ {
+ FreeHttpHeader(h);
+ h = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE5));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ PostHttp(s, h, buf->Buf, buf->Size);
+ b = true;
+
+ FreeBuf(buf);
+ }
+ }
+ }
+
+ if (b == false)
+ {
+ // Not Found
+ HttpSendNotFound(s, h->Target);
+
+ *error_detail_str = "HTTP_NOT_FOUND";
+ }
+ }
+ }
+ FreeHttpHeader(h);
+ }
+ }
+}
+
+// Upload a signature
+bool ClientUploadSignature(SOCK *s)
+{
+ HTTP_HEADER *h;
+ UINT water_size, rand_size;
+ UCHAR *water;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+
+ // Generate a watermark
+ rand_size = Rand32() % (HTTP_PACK_RAND_SIZE_MAX * 2);
+ water_size = SizeOfWaterMark() + rand_size;
+ water = Malloc(water_size);
+ Copy(water, WaterMark, SizeOfWaterMark());
+ Rand(&water[SizeOfWaterMark()], rand_size);
+
+ // Upload the watermark data
+ if (PostHttp(s, h, water, water_size) == false)
+ {
+ Free(water);
+ FreeHttpHeader(h);
+ return false;
+ }
+
+ Free(water);
+ FreeHttpHeader(h);
+
+ return true;
+}
+
+// Establish a connection to the server
+SOCK *ClientConnectToServer(CONNECTION *c)
+{
+ SOCK *s = NULL;
+ X *x = NULL;
+ K *k = NULL;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ if (c->Halt)
+ {
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // Get the socket by connecting
+ s = ClientConnectGetSocket(c, false, (c->DontUseTls1 ? false : true));
+ if (s == NULL)
+ {
+ // Connection failure
+ return NULL;
+ }
+
+ c->FirstSock = s;
+
+ if (c->Halt)
+ {
+ c->Err = ERR_USER_CANCEL;
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ return NULL;
+ }
+
+ // Time-out
+ SetTimeout(s, CONNECTING_TIMEOUT);
+
+ // Start the SSL communication
+ if (StartSSLEx(s, x, k, (c->DontUseTls1 ? false : true), 0, c->ServerName) == false)
+ {
+ // SSL communication start failure
+ Disconnect(s);
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return NULL;
+ }
+
+ if (s->RemoteX == NULL)
+ {
+ // SSL communication start failure
+ Disconnect(s);
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return NULL;
+ }
+
+ return s;
+}
+
+// Return a socket by connecting to the server
+SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect, bool no_tls)
+{
+ SOCK *s = NULL;
+ CLIENT_OPTION *o;
+ char *host_for_direct_connection;
+ UINT port_for_direct_connection;
+ wchar_t tmp[MAX_SIZE];
+ SESSION *sess;
+ volatile bool *cancel_flag = NULL;
+ void *hWnd;
+ UINT nat_t_err = 0;
+ bool is_additonal_rudp_session = false;
+ UCHAR uc = 0;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ sess = c->Session;
+
+ if (sess != NULL)
+ {
+ cancel_flag = &sess->CancelConnect;
+ is_additonal_rudp_session = sess->IsRUDPSession;
+ }
+
+ hWnd = c->hWndForUI;
+
+ o = c->Session->ClientOption;
+
+ if (c->RestoreServerNameAndPort && additional_connect)
+ {
+ // Restore to the original server name and port number
+ c->RestoreServerNameAndPort = false;
+
+ StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
+ c->ServerPort = o->Port;
+ }
+
+ host_for_direct_connection = c->ServerName;
+ port_for_direct_connection = c->ServerPort;
+
+ switch (o->ProxyType)
+ {
+ case PROXY_DIRECT: // TCP/IP
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), c->ServerName);
+ PrintStatus(sess, tmp);
+ // Production job
+ if (o->PortUDP == 0)
+ {
+ {
+ // If additional_connect == false, enable trying to NAT-T connection
+ // If additional_connect == true, follow the IsRUDPSession setting in this session
+ s = TcpIpConnectEx(host_for_direct_connection, port_for_direct_connection,
+ (bool *)cancel_flag, hWnd, &nat_t_err, (additional_connect ? (!is_additonal_rudp_session) : false),
+ true, no_tls);
+ }
+ }
+ else
+ {
+ // Mode to connect with R-UDP directly without using NAT-T server when using UDP
+ IP ip;
+
+ Zero(&ip, sizeof(ip));
+
+ StrToIP(&ip, o->Hostname);
+
+
+ s = NewRUDPClientDirect(VPN_RUDP_SVC_NAME, &ip, o->PortUDP, &nat_t_err,
+ TIMEOUT_TCP_PORT_CHECK, (bool *)cancel_flag, NULL, NULL, 0, false);
+
+ if (s != NULL)
+ {
+ StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ }
+ }
+ if (s == NULL)
+ {
+ // Connection failure
+ if (nat_t_err != RUDP_ERROR_NAT_T_TWO_OR_MORE)
+ {
+ c->Err = ERR_CONNECT_FAILED;
+ }
+ else
+ {
+ c->Err = ERR_NAT_T_TWO_OR_MORE;
+ }
+ return NULL;
+ }
+ break;
+
+ case PROXY_HTTP: // HTTP Proxy
+ host_for_direct_connection = o->ProxyName;
+ port_for_direct_connection = o->ProxyPort;
+
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
+ PrintStatus(sess, tmp);
+
+
+ // Proxy connection
+ s = ProxyConnectEx(c, host_for_direct_connection, port_for_direct_connection,
+ c->ServerName, c->ServerPort, o->ProxyUsername, o->ProxyPassword,
+ additional_connect, (bool *)cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // Connection failure
+ return NULL;
+ }
+ break;
+
+ case PROXY_SOCKS: // SOCKS Proxy
+ host_for_direct_connection = o->ProxyName;
+
+ port_for_direct_connection = o->ProxyPort;
+
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
+ PrintStatus(sess, tmp);
+
+
+ // SOCKS connection
+ s = SocksConnectEx(c, host_for_direct_connection, port_for_direct_connection,
+ c->ServerName, c->ServerPort, o->ProxyUsername,
+ additional_connect, (bool *)cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // Connection failure
+ return NULL;
+ }
+ break;
+ }
+
+ if (s == NULL)
+ {
+ // Connection failure
+ c->Err = ERR_CONNECT_FAILED;
+ }
+ else
+ {
+ // Success to connect
+ // Keep a note of the IP address
+ if (additional_connect == false || IsZeroIP(&s->RemoteIP))
+ {
+ if (((s->IsRUDPSocket || s->IPv6) && IsZeroIP(&s->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, host_for_direct_connection) == false)
+ {
+ Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
+ }
+ }
+ }
+
+ return s;
+}
+
+// Connect via SOCKS
+SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect)
+{
+ return SocksConnectEx(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, additional_connect, NULL, NULL);
+}
+SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect,
+ bool *cancel_flag, void *hWnd)
+{
+ return SocksConnectEx2(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, additional_connect, cancel_flag,
+ hWnd, 0);
+}
+SOCK *SocksConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect,
+ bool *cancel_flag, void *hWnd, UINT timeout)
+{
+ SOCK *s = NULL;
+ IP ip;
+ // Validate arguments
+ if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
+ || server_port == 0)
+ {
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // Get the IP address of the destination server
+ if (GetIP(&ip, server_host_name) == false)
+ {
+ // Failure
+ c->Err = ERR_CONNECT_FAILED;
+ return NULL;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // Connection
+ s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, false);
+ if (s == NULL)
+ {
+ // Failure
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // Timeout setting
+ SetTimeout(s, MIN(CONNECTING_TIMEOUT_PROXY, (timeout == 0 ? INFINITE : timeout)));
+
+ if (additional_connect == false)
+ {
+ c->FirstSock = s;
+ }
+
+ // Request packet transmission
+ if (SocksSendRequestPacket(c, s, server_port, &ip, username) == false)
+ {
+ // Failure
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // Receive a response packet
+ if (SocksRecvResponsePacket(c, s) == false)
+ {
+ // Failure
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ SetTimeout(s, INFINITE);
+
+ return s;
+}
+
+// Receive a SOCKS response packet
+bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
+{
+ BUF *b;
+ UINT size = 8;
+ UCHAR tmp[8];
+ UCHAR vn, cd;
+ // Validate arguments
+ if (c == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, tmp, sizeof(tmp), false) == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, sizeof(tmp));
+ SeekBuf(b, 0, 0);
+
+ ReadBuf(b, &vn, 1);
+ ReadBuf(b, &cd, 1);
+
+ FreeBuf(b);
+
+ if (vn != 0)
+ {
+ c->Err = ERR_PROXY_ERROR;
+ return false;
+ }
+
+ switch (cd)
+ {
+ case 90:
+ // Success
+ return true;
+
+ case 93:
+ // Authentication failure
+ c->Err = ERR_PROXY_AUTH_FAILED;
+ return false;
+
+ default:
+ // Connection to the server failure
+ c->Err = ERR_CONNECT_FAILED;
+ return false;
+ }
+}
+
+// Send a SOCKS request packet
+bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid)
+{
+ BUF *b;
+ UCHAR vn, cd;
+ USHORT port;
+ UINT ip;
+ bool ret;
+ // Validate arguments
+ if (s == NULL || dest_port == 0 || dest_ip == NULL || c == NULL)
+ {
+ return false;
+ }
+ if (userid == NULL)
+ {
+ userid = "";
+ }
+
+ b = NewBuf();
+ vn = 4;
+ cd = 1;
+ WriteBuf(b, &vn, 1);
+ WriteBuf(b, &cd, 1);
+ port = Endian16((USHORT)dest_port);
+ ip = IPToUINT(dest_ip);
+ WriteBuf(b, &port, 2);
+ WriteBuf(b, &ip, 4);
+ WriteBuf(b, userid, StrLen(userid) + 1);
+
+ ret = SendAll(s, b->Buf, b->Size, false);
+ if (ret == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Connect through a proxy
+SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect)
+{
+ return ProxyConnectEx(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, password, additional_connect, NULL, NULL);
+}
+SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect,
+ bool *cancel_flag, void *hWnd)
+{
+ return ProxyConnectEx2(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, password, additional_connect,
+ cancel_flag, hWnd, 0);
+}
+SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect,
+ bool *cancel_flag, void *hWnd, UINT timeout)
+{
+ SOCK *s = NULL;
+ bool use_auth = false;
+ char tmp[MAX_SIZE];
+ char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
+ char basic_str[MAX_SIZE * 2];
+ UINT http_error_code;
+ HTTP_HEADER *h;
+ // Validate arguments
+ if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
+ server_port == 0)
+ {
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+ if (username != NULL && password != NULL &&
+ (StrLen(username) != 0 || StrLen(password) != 0))
+ {
+ use_auth = true;
+ }
+
+ if (c->Halt)
+ {
+ // Stop
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // Connection
+ s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, false);
+ if (s == NULL)
+ {
+ // Failure
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // Timeout setting
+ SetTimeout(s, MIN(CONNECTING_TIMEOUT_PROXY, (timeout == 0 ? INFINITE : timeout)));
+
+ if (additional_connect == false)
+ {
+ c->FirstSock = s;
+ }
+
+ // HTTP header generation
+ if (IsStrIPv6Address(server_host_name))
+ {
+ IP ip;
+ char iptmp[MAX_PATH];
+
+ StrToIP(&ip, server_host_name);
+ IPToStr(iptmp, sizeof(iptmp), &ip);
+
+ Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "%s:%u", server_host_name, server_port);
+ }
+
+ h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
+ AddHttpValue(h, NewHttpValue("User-Agent", (c->Cedar == NULL ? DEFAULT_USER_AGENT : c->Cedar->HttpUserAgent)));
+ AddHttpValue(h, NewHttpValue("Host", server_host_name));
+ AddHttpValue(h, NewHttpValue("Content-Length", "0"));
+ AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
+
+ if (use_auth)
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name);
+ // Generate the authentication string
+ Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
+ username, password);
+
+ // Base64 encode
+ Zero(auth_b64_str, sizeof(auth_b64_str));
+ Encode64(auth_b64_str, auth_tmp_str);
+ Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
+
+ AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
+ }
+
+ // Transmission
+ if (SendHttpHeader(s, h) == false)
+ {
+ // Failure
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ FreeHttpHeader(h);
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+
+ FreeHttpHeader(h);
+
+ if (c->Halt)
+ {
+ // Stop
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // Receive the results
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ // Failure
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ FreeHttpHeader(h);
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+
+ http_error_code = 0;
+ if (StrLen(h->Method) == 8)
+ {
+ if (Cmp(h->Method, "HTTP/1.", 7) == 0)
+ {
+ http_error_code = ToInt(h->Target);
+ }
+ }
+ FreeHttpHeader(h);
+
+ // Check the code
+ switch (http_error_code)
+ {
+ case 401:
+ case 403:
+ case 407:
+ // Authentication failure
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_AUTH_FAILED;
+ return NULL;
+
+ default:
+ if ((http_error_code / 100) == 2)
+ {
+ // Success
+ SetTimeout(s, INFINITE);
+ return s;
+ }
+ else
+ {
+ // Receive an unknown result
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+ }
+}
+
+// TCP connection function
+SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool try_start_ssl, bool ssl_no_tls)
+{
+ return TcpConnectEx3(hostname, port, timeout, cancel_flag, hWnd, false, NULL, try_start_ssl, ssl_no_tls);
+}
+SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls)
+{
+#ifdef OS_WIN32
+ if (hWnd == NULL)
+ {
+#endif // OS_WIN32
+ return ConnectEx3(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, ssl_no_tls, false);
+#ifdef OS_WIN32
+ }
+ else
+ {
+ return WinConnectEx3((HWND)hWnd, hostname, port, timeout, 0, NULL, NULL, nat_t_error_code, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), try_start_ssl, ssl_no_tls);
+ }
+#endif // OS_WIN32
+}
+
+// Connect with TCP/IP
+SOCK *TcpIpConnect(char *hostname, UINT port, bool try_start_ssl, bool ssl_no_tls)
+{
+ return TcpIpConnectEx(hostname, port, NULL, NULL, NULL, false, try_start_ssl, ssl_no_tls);
+}
+SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, bool ssl_no_tls)
+{
+ SOCK *s = NULL;
+ UINT dummy_int = 0;
+ // Validate arguments
+ if (nat_t_error_code == NULL)
+ {
+ nat_t_error_code = &dummy_int;
+ }
+ *nat_t_error_code = 0;
+ if (hostname == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ s = TcpConnectEx3(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_no_tls);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ return s;
+}
+
+// Protocol routine initialization
+void InitProtocol()
+{
+}
+
+// Release the protocol routine
+void FreeProtocol()
+{
+}
+
+// Create a Hello packet
+PACK *PackHello(void *random, UINT ver, UINT build, char *server_str)
+{
+ PACK *p;
+ // Validate arguments
+ if (random == NULL || server_str == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "hello", server_str);
+ PackAddInt(p, "version", ver);
+ PackAddInt(p, "build", build);
+ PackAddData(p, "random", random, SHA1_SIZE);
+
+ return p;
+}
+
+// Interpret the Hello packet
+bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size)
+{
+ // Validate arguments
+ if (p == NULL || random == NULL || ver == NULL || server_str == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetStr(p, "hello", server_str, server_str_size) == false)
+ {
+ return false;
+ }
+ *ver = PackGetInt(p, "version");
+ *build = PackGetInt(p, "build");
+ if (PackGetDataSize(p, "random") != SHA1_SIZE)
+ {
+ return false;
+ }
+ if (PackGetData(p, "random", random) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the authentication method from PACK
+UINT GetAuthTypeFromPack(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetInt(p, "authtype");
+}
+
+// Get the HUB name and the user name from the PACK
+bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
+ char *hubname, UINT hubname_size)
+{
+ // Validate arguments
+ if (p == NULL || username == NULL || hubname == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetStr(p, "username", username, username_size) == false)
+ {
+ return false;
+ }
+ if (PackGetStr(p, "hubname", hubname, hubname_size) == false)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Get the protocol from PACK
+UINT GetProtocolFromPack(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+#if 0
+ return PackGetInt(p, "protocol");
+#else
+ // Limit to the TCP protocol in the current version
+ return CONNECTION_TCP;
+#endif
+}
+
+// Get the method from the PACK
+bool GetMethodFromPack(PACK *p, char *method, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || method == NULL || size == 0)
+ {
+ return false;
+ }
+
+ return PackGetStr(p, "method", method, size);
+}
+
+// Generate a packet of certificate authentication login
+PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size)
+{
+ PACK *p;
+ BUF *b;
+ // Validate arguments
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_CERT);
+
+ // Certificate
+ b = XToBuf(x, false);
+ PackAddData(p, "cert", b->Buf, b->Size);
+ FreeBuf(b);
+
+ // Signature data
+ PackAddData(p, "sign", sign, sign_size);
+
+ return p;
+}
+
+// Generate a packet of plain text password authentication login
+PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password)
+{
+ PACK *p;
+ // Validate arguments
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PLAIN_PASSWORD);
+ PackAddStr(p, "plain_password", plain_password);
+
+ return p;
+}
+
+// Create a packet of password authentication login
+PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
+{
+ PACK *p;
+ // Validate arguments
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PASSWORD);
+ PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
+
+ return p;
+}
+
+// Create a packet for anonymous login
+PACK *PackLoginWithAnonymous(char *hubname, char *username)
+{
+ PACK *p;
+ // Validate arguments
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_ANONYMOUS);
+
+ return p;
+}
+
+// Create a packet for the additional connection
+PACK *PackAdditionalConnect(UCHAR *session_key)
+{
+ PACK *p;
+ // Validate arguments
+ if (session_key == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "additional_connect");
+ PackAddData(p, "session_key", session_key, SHA1_SIZE);
+
+ return p;
+}
+
+
+// Generate a RC4 key pair
+void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Rand(k->ClientToServerKey, sizeof(k->ClientToServerKey));
+ Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Protocol.h b/src/Cedar/Protocol.h
new file mode 100644
index 00000000..45827d82
--- /dev/null
+++ b/src/Cedar/Protocol.h
@@ -0,0 +1,270 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Protocol.h
+// Header of Protocol.c
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+// The parameters that will be passed to the certificate confirmation thread
+struct CHECK_CERT_THREAD_PROC
+{
+ CONNECTION *Connection;
+ X *ServerX;
+ CHECK_CERT_PROC *CheckCertProc;
+ bool UserSelected;
+ bool Exipred;
+ bool Ok;
+};
+
+// The parameters that will be passed to the secure device signature thread
+struct SECURE_SIGN_THREAD_PROC
+{
+ SECURE_SIGN_PROC *SecureSignProc;
+ CONNECTION *Connection;
+ SECURE_SIGN *SecureSign;
+ bool UserFinished;
+ bool Ok;
+};
+
+// Signature sending thread parameters
+struct SEND_SIGNATURE_PARAM
+{
+ char Hostname[MAX_PATH]; // Host name
+ UINT Port; // Port number
+ BUF *Buffer; // Packet contents
+};
+
+// Software update client callback
+typedef void (UPDATE_NOTIFY_PROC)(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param);
+typedef bool (UPDATE_ISFOREGROUND_PROC)(UPDATE_CLIENT *c, void *param);
+
+// Configure the software update client
+struct UPDATE_CLIENT_SETTING
+{
+ bool DisableCheck; // Disable the update check
+ UINT LatestIgnoreBuild; // Ignore for earlier or identical to this build number
+};
+
+// Software update client
+struct UPDATE_CLIENT
+{
+ char FamilyName[MAX_SIZE]; // Product family name
+ char SoftwareName[MAX_SIZE]; // Software Name
+ wchar_t SoftwareTitle[MAX_SIZE]; // Software display name
+ char ClientId[128]; // Client ID
+ UINT MyBuild; // Build number of myself
+ UINT64 MyDate; // Build date of myself
+ char MyLanguage[MAX_SIZE]; // My language
+ UPDATE_CLIENT_SETTING Setting; // Setting
+ UINT LatestBuild; // Latest build number that was successfully acquired
+ volatile bool HaltFlag; // Halting flag
+ EVENT *HaltEvent; // Halting event
+ void *Param; // Any parameters
+ THREAD *Thread; // Thread
+ UPDATE_NOTIFY_PROC *Callback; // Callback function
+ UPDATE_ISFOREGROUND_PROC *IsForegroundCb; // Callback function for retrieving whether foreground
+};
+
+//// Constant related to updating of the software
+
+// Family
+#define UPDATE_FAMILY_NAME _SS("PRODUCT_FAMILY_NAME")
+
+// Software update server certificate hash
+#define UPDATE_SERVER_CERT_HASH "EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3"
+
+// URL
+#define UPDATE_SERVER_URL_GLOBAL "https://update-check.softether-network.net/update/update.aspx?family=%s&software=%s&mybuild=%u&lang=%s"
+#define UPDATE_SERVER_URL_CHINA "https://update-check.uxcom.jp/update/update.aspx?family=%s&software=%s&mybuild=%u&lang=%s"
+
+// Update check interval
+#define UPDATE_CHECK_INTERVAL_MIN (12 * 3600 * 1000)
+#define UPDATE_CHECK_INTERVAL_MAX (24 * 7200 * 1000)
+
+// Connection parameters
+#define UPDATE_CONNECT_TIMEOUT 5000
+#define UPDATE_COMM_TIMEOUT 5000
+
+
+
+// Function prototype
+UPDATE_CLIENT *NewUpdateClient(UPDATE_NOTIFY_PROC *cb, UPDATE_ISFOREGROUND_PROC *isforeground_cb, void *param, char *family_name, char *software_name, wchar_t *software_title, UINT my_build, UINT64 my_date, char *my_lang, UPDATE_CLIENT_SETTING *current_setting, char *client_id);
+void FreeUpdateClient(UPDATE_CLIENT *c);
+void UpdateClientThreadProc(THREAD *thread, void *param);
+void UpdateClientThreadMain(UPDATE_CLIENT *c);
+void UpdateClientThreadProcessResults(UPDATE_CLIENT *c, BUF *b);
+void SetUpdateClientSetting(UPDATE_CLIENT *c, UPDATE_CLIENT_SETTING *s);
+UINT64 ShortStrToDate64(char *str);
+
+
+bool ServerAccept(CONNECTION *c);
+bool ClientConnect(CONNECTION *c);
+SOCK *ClientConnectToServer(CONNECTION *c);
+SOCK *TcpIpConnect(char *hostname, UINT port, bool try_start_ssl, bool ssl_no_tls);
+SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, bool ssl_no_tls);
+bool ClientUploadSignature(SOCK *s);
+bool ClientDownloadHello(CONNECTION *c, SOCK *s);
+bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str);
+bool ServerUploadHello(CONNECTION *c);
+bool ClientUploadAuth(CONNECTION *c);
+SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect, bool no_tls);
+SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool try_start_ssl, bool ssl_no_tls);
+SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls);
+
+void InitProtocol();
+void FreeProtocol();
+
+
+
+POLICY *PackGetPolicy(PACK *p);
+void PackAddPolicy(PACK *p, POLICY *y);
+PACK *PackWelcome(SESSION *s);
+PACK *PackHello(void *random, UINT ver, UINT build, char *server_str);
+bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size);
+PACK *PackLoginWithAnonymous(char *hubname, char *username);
+PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
+PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
+PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size);
+bool GetMethodFromPack(PACK *p, char *method, UINT size);
+bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
+ char *hubname, UINT hubname_size);
+PACK *PackAdditionalConnect(UCHAR *session_key);
+UINT GetAuthTypeFromPack(PACK *p);
+UINT GetProtocolFromPack(PACK *p);
+bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
+ char *connection_name, UINT connection_name_size,
+ POLICY **policy);
+
+
+bool ClientAdditionalConnect(CONNECTION *c, THREAD *t);
+SOCK *ClientAdditionalConnectToServer(CONNECTION *c);
+bool ClientUploadAuth2(CONNECTION *c, SOCK *s);
+bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32);
+void GenerateRC4KeyPair(RC4_KEY_PAIR *k);
+
+SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect);
+SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect,
+ bool *cancel_flag, void *hWnd);
+SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect,
+ bool *cancel_flag, void *hWnd, UINT timeout);
+SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect);
+SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect,
+ bool *cancel_flag, void *hWnd);
+SOCK *SocksConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect,
+ bool *cancel_flag, void *hWnd, UINT timeout);
+bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid);
+bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s);
+void CreateNodeInfo(NODE_INFO *info, CONNECTION *c);
+UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin);
+void ClientUploadNoop(CONNECTION *c);
+bool ClientCheckServerCert(CONNECTION *c, bool *expired);
+void ClientCheckServerCertThread(THREAD *thread, void *param);
+bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x);
+void ClientSecureSignThread(THREAD *thread, void *param);
+UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin);
+UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list);
+UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name);
+TOKEN_LIST *EnumHub(SESSION *s);
+UINT ChangePasswordAccept(CONNECTION *c, PACK *p);
+UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass);
+void PackAddClientVersion(PACK *p, CONNECTION *c);
+void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info);
+void GenerateMachineUniqueHash(void *data);
+
+
+#endif // PROTOCOL_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Radius.c b/src/Cedar/Radius.c
new file mode 100644
index 00000000..24ac5751
--- /dev/null
+++ b/src/Cedar/Radius.c
@@ -0,0 +1,90 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Radius.c
+// Radius authentication module
+
+#include "CedarPch.h"
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Radius.h b/src/Cedar/Radius.h
new file mode 100644
index 00000000..681e2a56
--- /dev/null
+++ b/src/Cedar/Radius.h
@@ -0,0 +1,99 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Radius.h
+// Header of Radius.c
+
+#ifndef RADIUS_H
+#define RADIUS_H
+
+#define RADIUS_DEFAULT_PORT 1812 // The default port number
+#define RADIUS_RETRY_INTERVAL 500 // Retransmission interval
+#define RADIUS_RETRY_TIMEOUT (10 * 1000) // Time-out period
+
+
+#endif // RADIUS_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Remote.c b/src/Cedar/Remote.c
new file mode 100644
index 00000000..b8ab70b8
--- /dev/null
+++ b/src/Cedar/Remote.c
@@ -0,0 +1,448 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Remote.c
+// Remote Procedure Call
+
+#include "CedarPch.h"
+
+// End of RPC
+void EndRpc(RPC *rpc)
+{
+ RpcFree(rpc);
+}
+
+// Release the RPC
+void RpcFree(RPC *rpc)
+{
+ // Validate arguments
+ if (rpc == NULL)
+ {
+ return;
+ }
+
+ Disconnect(rpc->Sock);
+ ReleaseSock(rpc->Sock);
+
+ DeleteLock(rpc->Lock);
+
+ Free(rpc);
+}
+
+// Get error
+UINT RpcGetError(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return ERR_DISCONNECTED;
+ }
+
+ return PackGetInt(p, "error_code");
+}
+
+// Error checking
+bool RpcIsOk(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetInt(p, "error") == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Error code setting
+void RpcError(PACK *p, UINT err)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "error", 1);
+ PackAddInt(p, "error_code", err);
+}
+
+// Start the RPC dispatcher
+PACK *CallRpcDispatcher(RPC *r, PACK *p)
+{
+ char func_name[MAX_SIZE];
+ // Validate arguments
+ if (r == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ if (PackGetStr(p, "function_name", func_name, sizeof(func_name)) == false)
+ {
+ return NULL;
+ }
+
+ return r->Dispatch(r, func_name, p);
+}
+
+// Wait for the next RPC call
+bool RpcRecvNextCall(RPC *r)
+{
+ UINT size;
+ void *tmp;
+ SOCK *s;
+ BUF *b;
+ PACK *p;
+ PACK *ret;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return false;
+ }
+
+ s = r->Sock;
+
+ if (RecvAll(s, &size, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+
+ size = Endian32(size);
+
+ if (size > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+
+ tmp = MallocEx(size, true);
+
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ SeekBuf(b, 0, 0);
+ Free(tmp);
+
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ ret = CallRpcDispatcher(r, p);
+ FreePack(p);
+
+ if (ret == NULL)
+ {
+ ret = PackError(ERR_NOT_SUPPORTED);
+ }
+
+ b = PackToBuf(ret);
+ FreePack(ret);
+
+ size = Endian32(b->Size);
+ SendAdd(s, &size, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+
+ if (SendNow(s, s->SecureMode) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// RPC server operation
+void RpcServer(RPC *r)
+{
+ SOCK *s;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ s = r->Sock;
+
+ while (true)
+ {
+ // Wait for the next RPC call
+ if (RpcRecvNextCall(r) == false)
+ {
+ // Communication error
+ break;
+ }
+ }
+}
+
+// RPC call
+PACK *RpcCall(RPC *r, char *function_name, PACK *p)
+{
+ PACK *ret;
+ UINT num_retry = 0;
+ UINT err = 0;
+ // Validate arguments
+ if (r == NULL || function_name == NULL)
+ {
+ return NULL;
+ }
+
+// Debug("RpcCall: %s\n", function_name);
+
+ Lock(r->Lock);
+ {
+ if (p == NULL)
+ {
+ p = NewPack();
+ }
+
+ PackAddStr(p, "function_name", function_name);
+
+RETRY:
+ err = 0;
+ ret = RpcCallInternal(r, p);
+
+ if (ret == NULL)
+ {
+ if (r->IsVpnServer && r->Sock != NULL)
+ {
+ if (num_retry < 1)
+ {
+ num_retry++;
+
+ // Attempt to reconnect the RPC to the VPN Server
+ err = AdminReconnect(r);
+
+ if (err == ERR_NO_ERROR)
+ {
+ goto RETRY;
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+
+ if (ret == NULL)
+ {
+ if (err == 0)
+ {
+ err = ERR_DISCONNECTED;
+ }
+
+ ret = PackError(err);
+ PackAddInt(ret, "error_code", err);
+ }
+ }
+ Unlock(r->Lock);
+
+ return ret;
+}
+
+// RPC internal call
+PACK *RpcCallInternal(RPC *r, PACK *p)
+{
+ BUF *b;
+ UINT size;
+ PACK *ret;
+ void *tmp;
+ // Validate arguments
+ if (r == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ if (r->Sock == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackToBuf(p);
+
+ size = Endian32(b->Size);
+ SendAdd(r->Sock, &size, sizeof(UINT));
+ SendAdd(r->Sock, b->Buf, b->Size);
+ FreeBuf(b);
+
+ if (SendNow(r->Sock, r->Sock->SecureMode) == false)
+ {
+ return NULL;
+ }
+
+ if (RecvAll(r->Sock, &size, sizeof(UINT), r->Sock->SecureMode) == false)
+ {
+ return NULL;
+ }
+
+ size = Endian32(size);
+ if (size > MAX_PACK_SIZE)
+ {
+ return NULL;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(r->Sock, tmp, size, r->Sock->SecureMode) == false)
+ {
+ Free(tmp);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ SeekBuf(b, 0, 0);
+ Free(tmp);
+
+ ret = BufToPack(b);
+ if (ret == NULL)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Start the RPC server
+RPC *StartRpcServer(SOCK *s, RPC_DISPATCHER *dispatch, void *param)
+{
+ RPC *r;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ r = ZeroMallocEx(sizeof(RPC), true);
+ r->Sock = s;
+ r->Param = param;
+ r->Lock = NewLock();
+ AddRef(s->ref);
+
+ r->ServerMode = true;
+ r->Dispatch = dispatch;
+
+ // Name generation
+ Format(r->Name, sizeof(r->Name), "RPC-%u", s->socket);
+
+ return r;
+}
+
+// Start the RPC client
+RPC *StartRpcClient(SOCK *s, void *param)
+{
+ RPC *r;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(RPC));
+ r->Sock = s;
+ r->Param = param;
+ r->Lock = NewLock();
+ AddRef(s->ref);
+
+ r->ServerMode = false;
+
+ return r;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Remote.h b/src/Cedar/Remote.h
new file mode 100644
index 00000000..2081e70b
--- /dev/null
+++ b/src/Cedar/Remote.h
@@ -0,0 +1,127 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Remote.h
+// Header of Remote.c
+
+#ifndef REMOTE_H
+#define REMOTE_H
+
+// RPC execution function
+typedef PACK *(RPC_DISPATCHER)(RPC *r, char *function_name, PACK *p);
+
+// RPC object
+struct RPC
+{
+ SOCK *Sock; // Socket
+ bool ServerMode; // Server mode
+ RPC_DISPATCHER *Dispatch; // Execution routine
+ void *Param; // Parameters
+ bool ServerAdminMode; // Server management mode
+ char HubName[MAX_HUBNAME_LEN + 1]; // Managing HUB name
+ char Name[MAX_SIZE]; // RPC session name
+ LOCK *Lock; // Lock
+ bool IsVpnServer; // Whether VPN Server management RPC
+ CLIENT_OPTION VpnServerClientOption;
+ char VpnServerHubName[MAX_HUBNAME_LEN + 1];
+ UCHAR VpnServerHashedPassword[SHA1_SIZE];
+ char VpnServerClientName[MAX_PATH];
+};
+
+// Function prototype
+RPC *StartRpcClient(SOCK *s, void *param);
+RPC *StartRpcServer(SOCK *s, RPC_DISPATCHER *dispatch, void *param);
+PACK *RpcCallInternal(RPC *r, PACK *p);
+PACK *RpcCall(RPC *r, char *function_name, PACK *p);
+void RpcServer(RPC *r);
+bool RpcRecvNextCall(RPC *r);
+PACK *CallRpcDispatcher(RPC *r, PACK *p);
+void RpcError(PACK *p, UINT err);
+bool RpcIsOk(PACK *p);
+UINT RpcGetError(PACK *p);
+void EndRpc(RPC *rpc);
+void RpcFree(RPC *rpc);
+
+#endif // REMOTE_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SM.c b/src/Cedar/SM.c
new file mode 100644
index 00000000..1aba59e2
--- /dev/null
+++ b/src/Cedar/SM.c
@@ -0,0 +1,20505 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SM.c
+// VPN Server Manager for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define SM_C
+#define CM_C
+#define NM_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "CMInner.h"
+#include "SMInner.h"
+#include "NMInner.h"
+#include "EMInner.h"
+#include "../PenCore/resource.h"
+
+// Global variable
+static SM *sm = NULL;
+static bool link_create_now = false;
+
+
+// Proxy Settings dialog initialization
+void SmProxyDlgInit(HWND hWnd, INTERNET_SETTING *t)
+{
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Check(hWnd, R_DIRECT_TCP, t->ProxyType == PROXY_DIRECT);
+ Check(hWnd, R_HTTPS, t->ProxyType == PROXY_HTTP);
+ Check(hWnd, R_SOCKS, t->ProxyType == PROXY_SOCKS);
+
+ SmProxyDlgUpdate(hWnd, t);
+}
+
+// Proxy Settings dialog update
+void SmProxyDlgUpdate(HWND hWnd, INTERNET_SETTING *t)
+{
+ bool ok = false;
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ if (t->ProxyType == PROXY_DIRECT)
+ {
+ ok = true;
+ }
+ else
+ {
+ if (IsEmptyStr(t->ProxyHostName) == false &&
+ t->ProxyPort != 0)
+ {
+ ok = true;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+
+ SetEnable(hWnd, B_PROXY_CONFIG, !IsChecked(hWnd, R_DIRECT_TCP));
+}
+
+// Proxy settings generic dialog procedure
+UINT SmProxyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ INTERNET_SETTING *t = (INTERNET_SETTING *)param;
+ CLIENT_OPTION a;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmProxyDlgInit(hWnd, t);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_DIRECT_TCP:
+ case R_HTTPS:
+ case R_SOCKS:
+ if (IsChecked(hWnd, R_HTTPS))
+ {
+ t->ProxyType = PROXY_HTTP;
+ }
+ else if (IsChecked(hWnd, R_SOCKS))
+ {
+ t->ProxyType = PROXY_SOCKS;
+ }
+ else
+ {
+ t->ProxyType = PROXY_DIRECT;
+ }
+
+ SmProxyDlgUpdate(hWnd, t);
+ break;
+
+ case B_PROXY_CONFIG:
+ Zero(&a, sizeof(a));
+
+ a.ProxyType = t->ProxyType;
+ StrCpy(a.ProxyName, sizeof(a.ProxyName), t->ProxyHostName);
+ a.ProxyPort = t->ProxyPort;
+ StrCpy(a.ProxyUsername, sizeof(a.ProxyUsername), t->ProxyUsername);
+ StrCpy(a.ProxyPassword, sizeof(a.ProxyPassword), t->ProxyPassword);
+
+ if (CmProxyDlg(hWnd, &a))
+ {
+ t->ProxyType = a.ProxyType;
+ StrCpy(t->ProxyHostName, sizeof(t->ProxyHostName), a.ProxyName);
+ t->ProxyPort = a.ProxyPort;
+ StrCpy(t->ProxyUsername, sizeof(t->ProxyUsername), a.ProxyUsername);
+ StrCpy(t->ProxyPassword, sizeof(t->ProxyPassword), a.ProxyPassword);
+ }
+
+ SmProxyDlgUpdate(hWnd, t);
+
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Proxy Settings generic dialog
+bool SmProxy(HWND hWnd, INTERNET_SETTING *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_SM_PROXY, SmProxyDlg, t);
+}
+
+// VPN Azure dialog procedure
+UINT SmAzureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_AZURE *a = (SM_AZURE *)param;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmAzureDlgOnInit(hWnd, a);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_CHANGE:
+ if (SmDDns(hWnd, a->s, false, true))
+ {
+ SmAzureDlgRefresh(hWnd, a);
+ }
+ break;
+
+ case B_WEB:
+ MsExecute(_SS("SE_VPNAZURE_URL"), NULL);
+ break;
+
+ case R_ENABLE:
+ case R_DISABLE:
+ if (IsChecked(hWnd, R_ENABLE) || IsChecked(hWnd, R_DISABLE))
+ {
+ Enable(hWnd, IDCANCEL);
+ EnableClose(hWnd);
+ }
+
+ SmAzureSetStatus(hWnd, a);
+ break;
+
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+
+ SmAzureDlgRefresh(hWnd, a);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Set the status
+void SmAzureSetStatus(HWND hWnd, SM_AZURE *a)
+{
+ RPC_AZURE_STATUS st;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ Zero(&st, sizeof(st));
+
+ st.IsEnabled = IsChecked(hWnd, R_ENABLE);
+
+ if (CALL(hWnd, ScSetAzureStatus(a->s->Rpc, &st)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ SmAzureDlgRefresh(hWnd, a);
+}
+
+// Initialize the dialog
+void SmAzureDlgOnInit(HWND hWnd, SM_AZURE *a)
+{
+ RPC_AZURE_STATUS st;
+ UINT current_lang_id;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_AZURE);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+ DlgFont(hWnd, R_ENABLE, 0, true);
+
+ SetFont(hWnd, E_HOST, GetFont("Verdana", 10, false, false, false, false));
+
+ current_lang_id = GetCurrentLangId();
+
+ // Japanese
+ SetShow(hWnd, S_BMP_JA, current_lang_id == SE_LANG_JAPANESE);
+
+ // Chinese
+ SetShow(hWnd, S_BMP_CN, current_lang_id == SE_LANG_CHINESE_ZH);
+
+ // Other languages
+ SetShow(hWnd, S_BMP_EN, (current_lang_id != SE_LANG_JAPANESE) && (current_lang_id != SE_LANG_CHINESE_ZH));
+
+ // Apply the current settings
+ Zero(&st, sizeof(st));
+
+ if (CALL(hWnd, ScGetAzureStatus(a->s->Rpc, &st)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ if (a->OnSetup == false || st.IsEnabled)
+ {
+ Check(hWnd, R_ENABLE, st.IsEnabled);
+ Check(hWnd, R_DISABLE, !st.IsEnabled);
+ }
+ else
+ {
+ Disable(hWnd, IDCANCEL);
+ DisableClose(hWnd);
+ }
+
+ SmAzureDlgRefresh(hWnd, a);
+}
+
+// Update the dialog
+void SmAzureDlgRefresh(HWND hWnd, SM_AZURE *a)
+{
+ RPC_AZURE_STATUS st;
+ DDNS_CLIENT_STATUS ddns;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ Zero(&st, sizeof(st));
+ Zero(&ddns, sizeof(ddns));
+
+ if (CALL(hWnd, ScGetAzureStatus(a->s->Rpc, &st)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ if (CALL(hWnd, ScGetDDnsClientStatus(a->s->Rpc, &ddns)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ if (st.IsEnabled == false)
+ {
+ SetText(hWnd, S_STATUS, _UU("SM_AZURE_STATUS_NOT_CONNECTED"));
+ Disable(hWnd, S_STATUS);
+ }
+ else
+ {
+ SetText(hWnd, S_STATUS, (st.IsConnected ? _UU("SM_AZURE_STATUS_CONNECTED") : _UU("SM_AZURE_STATUS_NOT_CONNECTED")));
+ Enable(hWnd, S_STATUS);
+ }
+
+ SetShow(hWnd, S_HOSTNAME_BORDER, st.IsEnabled);
+ SetShow(hWnd, S_HOSTNAME_INFO, st.IsEnabled);
+ SetShow(hWnd, B_CHANGE, st.IsEnabled);
+
+ if (st.IsEnabled == false || IsEmptyStr(ddns.CurrentHostName))
+ {
+ Hide(hWnd, E_HOST);
+ }
+ else
+ {
+ StrCpy(tmp, sizeof(tmp), ddns.CurrentHostName);
+ StrCat(tmp, sizeof(tmp), AZURE_DOMAIN_SUFFIX);
+
+ SetTextA(hWnd, E_HOST, tmp);
+
+ Show(hWnd, E_HOST);
+ }
+}
+
+// VPN Azure Setup screen
+void SmAzure(HWND hWnd, SM_SERVER *s, bool on_setup)
+{
+ SM_AZURE a;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+
+ a.s = s;
+ a.OnSetup = on_setup;
+
+ Dialog(hWnd, D_SM_AZURE, SmAzureDlg, &a);
+}
+
+// Notification screen about the bridge in VM
+UINT SmVmBridgeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ DlgFont(hWnd, S_TITLE, 14, true);
+ SetIcon(hWnd, 0, ICO_NIC_ONLINE);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Setting screen of VPN over ICMP, etc.
+void SmSpecialListener(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_SPECIALLISTENER, SmSpecialListenerDlg, s);
+}
+UINT SmSpecialListenerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmSpecialListenerDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ SmSpecialListenerDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+void SmSpecialListenerDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ RPC_SPECIAL_LISTENER t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SPECIALLISTENER);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+ DlgFont(hWnd, S_1, 0, true);
+ DlgFont(hWnd, R_OVER_ICMP, 0, true);
+ DlgFont(hWnd, R_OVER_DNS, 0, true);
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, ScGetSpecialListener(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ Check(hWnd, R_OVER_ICMP, t.VpnOverIcmpListener);
+ Check(hWnd, R_OVER_DNS, t.VpnOverDnsListener);
+}
+void SmSpecialListenerDlgOnOk(HWND hWnd, SM_SERVER *s)
+{
+ RPC_SPECIAL_LISTENER t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ t.VpnOverIcmpListener = IsChecked(hWnd, R_OVER_ICMP);
+ t.VpnOverDnsListener = IsChecked(hWnd, R_OVER_DNS);
+
+ if (CALL(hWnd, ScSetSpecialListener(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ EndDialog(hWnd, 1);
+}
+
+
+// DDNS dialog
+bool SmDDns(HWND hWnd, SM_SERVER *s, bool silent, bool no_change_cert)
+{
+ SM_DDNS d;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&d, sizeof(d));
+ d.s = s;
+ d.Silent = silent;
+ d.NoChangeCert = no_change_cert;
+
+ Dialog(hWnd, D_SM_DDNS, SmDDnsDlg, &d);
+
+ return d.Changed;
+}
+UINT SmDDnsDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_DDNS *d = (SM_DDNS *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmDDnsDlgInit(hWnd, d);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_NEWHOST:
+ SmDDnsDlgUpdate(hWnd, d);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmDDnsDlgOnOk(hWnd, d);
+ break;
+
+ case B_RESTORE:
+ // Restore to original
+ if (d->Status.Err_IPv4 == ERR_NO_ERROR || d->Status.Err_IPv6 == ERR_NO_ERROR)
+ {
+ SetTextA(hWnd, E_NEWHOST, d->Status.CurrentHostName);
+ SmDDnsDlgUpdate(hWnd, d);
+ FocusEx(hWnd, E_NEWHOST);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_DISABLE:
+ d->DoNotPoll = true;
+
+ OnceMsg(hWnd, _UU("SM_DISABLE_DDNS_HINT_CAPTION"), _UU("SM_DISABLE_DDNS_HINT"), false, ICO_INFORMATION);
+
+ d->DoNotPoll = false;
+ break;
+
+ case B_HINT:
+ // Hint
+ if (d->Status.Err_IPv4 == ERR_NO_ERROR || d->Status.Err_IPv6 == ERR_NO_ERROR)
+ {
+ wchar_t tmp[MAX_SIZE * 4];
+ wchar_t ipv4[MAX_SIZE], ipv6[MAX_SIZE];
+
+ StrToUni(ipv4, sizeof(ipv4), d->Status.CurrentIPv4);
+ StrToUni(ipv6, sizeof(ipv6), d->Status.CurrentIPv6);
+
+ if (UniIsEmptyStr(ipv4))
+ {
+ UniStrCpy(ipv4, sizeof(ipv4), _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+
+ if (UniIsEmptyStr(ipv6))
+ {
+ UniStrCpy(ipv6, sizeof(ipv6), _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+
+ UniFormat(tmp, sizeof(tmp),
+ _UU("SM_DDNS_OK_MSG"),
+ d->Status.CurrentHostName, d->Status.DnsSuffix,
+ ipv4, ipv6,
+ d->Status.CurrentHostName, d->Status.DnsSuffix,
+ d->Status.CurrentHostName, d->Status.DnsSuffix);
+
+ d->DoNotPoll = true;
+
+ OnceMsg(hWnd, _UU("SM_DDNS_OK_TITLE"), tmp, false, ICO_DISPLAY);
+
+ d->DoNotPoll = false;
+ }
+ break;
+
+ case B_PROXY:
+ // Proxy settings
+ if (true)
+ {
+ INTERNET_SETTING t;
+
+ if (CALL(hWnd, ScGetDDnsInternetSetting(d->s->Rpc, &t)))
+ {
+ if (SmProxy(hWnd, &t))
+ {
+ if (CALL(hWnd, ScSetDDnsInternetSetting(d->s->Rpc, &t)))
+ {
+ SmDDnsRefresh(hWnd, d);
+ }
+ }
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+
+ SmDDnsRefresh(hWnd, d);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ if (d->Changed || d->Silent)
+ {
+ // Check the server certificate if the host name has been changed
+ RPC_KEY_PAIR t;
+ char fqdn[MAX_SIZE];
+ bool is_vgs_enabled = false;
+
+
+ StrCpy(fqdn, sizeof(fqdn), d->Status.CurrentFqdn);
+
+ if (IsEmptyStr(fqdn) == false)
+ {
+ Zero(&t, sizeof(t));
+ if (ScGetServerCert(d->s->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.Cert != NULL && t.Cert->root_cert && t.Cert->subject_name != NULL && is_vgs_enabled == false)
+ {
+ char cn[MAX_SIZE];
+
+ UniToStr(cn, sizeof(cn), t.Cert->subject_name->CommonName);
+
+ if ((StrCmpi(cn, fqdn) != 0) && (d->NoChangeCert == false))
+ {
+ // Confirm whether the user want to replace the server certificate
+ if (d->Silent || (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO,
+ _UU("SM_DDNS_SERVER_CERT_MSG"),
+ fqdn, fqdn) == IDYES))
+ {
+ // Re-generate the server certificate
+ RPC_TEST tt;
+
+ Zero(&tt, sizeof(tt));
+
+ StrCpy(tt.StrValue, sizeof(tt.StrValue), fqdn);
+
+ SetText(hWnd, IDCANCEL, _UU("CM_VLAN_INSTALLING"));
+ Refresh(DlgItem(hWnd, IDCANCEL));
+ Refresh(hWnd);
+ DoEvents(NULL);
+
+ if (CALL(hWnd, ScRegenerateServerCert(d->s->Rpc, &tt)))
+ {
+ // Confirm whether the user want to save the server certificate
+ if ((d->Silent == false) && (
+ MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_YESNO,
+ _UU("SM_DDNS_SERVER_CERT_OK"),
+ fqdn) == IDYES))
+ {
+ // Get the server certificate
+ RPC_KEY_PAIR t2;
+
+ Zero(&t2, sizeof(t2));
+ if (CALL(hWnd, ScGetServerCert(d->s->Rpc, &t2)))
+ {
+ wchar_t *name;
+ wchar_t defname[MAX_PATH];
+
+ StrToUni(defname, sizeof(defname), fqdn);
+ UniStrCat(defname, sizeof(defname), L".cer");
+
+ name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), defname, L".cer");
+
+ if (name != NULL)
+ {
+ if (XToFileW(t2.Cert, name, true))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
+ }
+
+ Free(name);
+ }
+
+ FreeRpcKeyPair(&t2);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ }
+ }
+
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+void SmDDnsDlgInit(HWND hWnd, SM_DDNS *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ d->DoNotPoll = false;
+
+ SetIcon(hWnd, 0, ICO_DISPLAY);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+ DlgFont(hWnd, S_STATUS3, 0, true);
+ DlgFont(hWnd, S_STATUS4, 0, true);
+ DlgFont(hWnd, S_STATUS5, 0, true);
+ DlgFont(hWnd, S_STATUS6, 0, true);
+
+ SetFont(hWnd, S_SUFFIX, GetFont("Verdana", 10, false, false, false, false));
+ SetFont(hWnd, E_NEWHOST, GetFont("Verdana", 10, false, false, false, false));
+
+ SetFont(hWnd, E_HOST, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 10, false, false, false, false));
+ SetFont(hWnd, E_IPV4, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 10, false, false, false, false));
+ SetFont(hWnd, E_IPV6, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 10, false, false, false, false));
+
+ DlgFont(hWnd, IDOK, 0, true);
+
+ if (d->Silent)
+ {
+ Hide(hWnd, B_DISABLE);
+ }
+
+ Hide(hWnd, B_PROXY);
+
+ SmDDnsRefresh(hWnd, d);
+}
+
+void SmDDnsRefresh(HWND hWnd, SM_DDNS *d)
+{
+ DDNS_CLIENT_STATUS st;
+ INTERNET_SETTING t;
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (d->DoNotPoll)
+ {
+ return;
+ }
+
+ Zero(&st, sizeof(st));
+ Zero(&t, sizeof(t));
+
+ // Get the status
+ if (CALL(hWnd, ScGetDDnsClientStatus(d->s->Rpc, &st)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ ScGetDDnsInternetSetting(d->s->Rpc, &t);
+
+ Copy(&d->Status, &st, sizeof(st));
+
+ if (IsEmptyStr(st.CurrentFqdn) == false)
+ {
+ SetTextA(hWnd, E_HOST, st.CurrentFqdn);
+ }
+ else
+ {
+ SetText(hWnd, E_HOST, _UU("SM_DDNS_FQDN_EMPTY"));
+ }
+
+ if (st.Err_IPv4 == ERR_NO_ERROR)
+ {
+ SetTextA(hWnd, E_IPV4, st.CurrentIPv4);
+ }
+ else
+ {
+ if (st.Err_IPv4 == ERR_CONNECT_FAILED)
+ {
+ SetText(hWnd, E_IPV4, _UU("SM_DDNS_IPV4_ERROR"));
+ }
+ else
+ {
+ SetText(hWnd, E_IPV4, _E(st.Err_IPv4));
+ }
+ }
+
+ if (st.Err_IPv6 == ERR_NO_ERROR)
+ {
+ SetTextA(hWnd, E_IPV6, st.CurrentIPv6);
+ }
+ else
+ {
+ if (st.Err_IPv6 == ERR_CONNECT_FAILED)
+ {
+ SetText(hWnd, E_IPV6, _UU("SM_DDNS_IPV6_ERROR"));
+ }
+ else
+ {
+ SetText(hWnd, E_IPV6, _E(st.Err_IPv6));
+ }
+ }
+
+ if (st.Err_IPv4 == ERR_NO_ERROR || st.Err_IPv6 == ERR_NO_ERROR)
+ {
+ if (IsEmptyStr(st.DnsSuffix) == false)
+ {
+ SetTextA(hWnd, S_SUFFIX, st.DnsSuffix);
+ }
+
+ Enable(hWnd, S_STATUS6);
+ Enable(hWnd, E_NEWHOST);
+ Enable(hWnd, S_SUFFIX);
+ Enable(hWnd, S_STATUS7);
+ Enable(hWnd, B_HINT);
+ }
+ else
+ {
+ SetTextA(hWnd, S_SUFFIX, "");
+
+ Disable(hWnd, S_STATUS6);
+ Disable(hWnd, E_NEWHOST);
+ Disable(hWnd, S_SUFFIX);
+ Disable(hWnd, S_STATUS7);
+ Disable(hWnd, B_HINT);
+ }
+
+ if (GetCapsBool(d->s->CapsList, "b_support_ddns_proxy"))
+ {
+ // Show the proxy button
+ Show(hWnd, B_PROXY);
+ }
+ else
+ {
+ // Hide the proxy button
+ Hide(hWnd, B_PROXY);
+ }
+
+ SmDDnsDlgUpdate(hWnd, d);
+
+ if (d->Flag == false)
+ {
+ d->Flag = true;
+ }
+
+ if (IsEmptyStr(st.CurrentHostName) == false)
+ {
+ if (d->HostnameSetFlag == false)
+ {
+ d->HostnameSetFlag = true;
+
+ SetTextA(hWnd, E_NEWHOST, st.CurrentHostName);
+
+ FocusEx(hWnd, E_NEWHOST);
+ }
+ }
+}
+void SmDDnsDlgUpdate(HWND hWnd, SM_DDNS *d)
+{
+ char tmp[MAX_SIZE];
+ bool b = false;
+
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (GetTxtA(hWnd, E_NEWHOST, tmp, sizeof(tmp)))
+ {
+ Trim(tmp);
+
+ // Get whether the host name have changed
+ if (IsEmptyStr(tmp) == false)
+ {
+ if (StrCmpi(d->Status.CurrentHostName, tmp) != 0)
+ {
+ if (d->Status.Err_IPv4 == ERR_NO_ERROR || d->Status.Err_IPv6 == ERR_NO_ERROR)
+ {
+ b = true;
+ }
+ }
+ }
+ }
+
+ SetEnable(hWnd, IDOK, b);
+ SetEnable(hWnd, B_RESTORE, b);
+}
+void SmDDnsDlgOnOk(HWND hWnd, SM_DDNS *d)
+{
+ RPC_TEST t;
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ GetTxtA(hWnd, E_NEWHOST, t.StrValue, sizeof(t.StrValue));
+
+ if (CALL(hWnd, ScChangeDDnsClientHostname(d->s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ d->Changed = true;
+
+ SmDDnsRefresh(hWnd, d);
+ FocusEx(hWnd, E_NEWHOST);
+
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_DDNS_OK_MSG2"), t.StrValue);
+ FocusEx(hWnd, E_NEWHOST);
+}
+
+// Open the OpenVPN dialog
+void SmOpenVpn(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_OPENVPN, SmOpenVpnDlg, s);
+}
+
+// OpenVPN dialog
+UINT SmOpenVpnDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmOpenVpnDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_OPENVPN:
+ case E_UDP:
+ case R_SSTP:
+ SmOpenVpnDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmOpenVpnDlgOnOk(hWnd, s, false);
+ break;
+
+ case B_DEFAULT:
+ ToStr(tmp, OPENVPN_UDP_PORT);
+ SetTextA(hWnd, E_UDP, tmp);
+ FocusEx(hWnd, E_UDP);
+ break;
+
+ case B_CONFIG:
+ // Create an OpenVPN configuration
+ {
+ OPENVPN_SSTP_CONFIG t2;
+ RPC_READ_LOG_FILE t;
+
+ Zero(&t2, sizeof(t2));
+
+ if (CALL(hWnd, ScGetOpenVpnSstpConfig(s->Rpc, &t2)))
+ {
+ if (t2.EnableOpenVPN == false)
+ {
+ // Enable the OpenVPN first
+ SmOpenVpnDlgOnOk(hWnd, s, true);
+
+ Disable(hWnd, IDCANCEL);
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, ScMakeOpenVpnConfigFile(s->Rpc, &t)))
+ {
+ // Generate a file name
+ wchar_t filename[MAX_SIZE];
+ char safe_hostname[MAX_SIZE];
+ SYSTEMTIME st;
+ wchar_t *dst;
+
+ MakeSafeFileName(safe_hostname, sizeof(safe_hostname), s->ServerName);
+
+ LocalTime(&st);
+
+ UniFormat(filename, sizeof(filename),
+ L"OpenVPN_Sample_Config_%S_%04u%02u%02u_%02u%02u%02u.zip",
+ safe_hostname,
+ st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond);
+
+ dst = SaveDlg(hWnd, _UU("DLG_ZIP_FILER"), _UU("DLG_SAVE_OPENVPN_CONFIG"),
+ filename, L".zip");
+
+ if (dst != NULL)
+ {
+ // Save
+ if (DumpBufW(t.Buffer, dst) == false)
+ {
+ // Failure
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("SM_OPENVPN_CONFIG_SAVE_NG"), dst);
+ }
+ else
+ {
+ // Success
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_OPENVPN_CONFIG_SAVE_OK"), dst) == IDYES)
+ {
+ if (MsExecuteW(dst, L"") == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_OPENVPN_CONFIG_OPEN_NG"), dst);
+ }
+ }
+ }
+
+ Free(dst);
+ }
+
+ FreeRpcReadLogFile(&t);
+ }
+ }
+ break;
+
+ case B_IPSEC:
+ SmIPsec(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+void SmOpenVpnDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ OPENVPN_SSTP_CONFIG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetOpenVpnSstpConfig(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ Check(hWnd, R_OPENVPN, t.EnableOpenVPN);
+ SetTextA(hWnd, E_UDP, t.OpenVPNPortList);
+ Check(hWnd, R_SSTP, t.EnableSSTP);
+
+ SetIcon(hWnd, 0, ICO_OPENVPN);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+ SetFont(hWnd, E_UDP, GetFont("Verdana", 10, false, false, false, false));
+
+ DlgFont(hWnd, R_OPENVPN, 0, true);
+ DlgFont(hWnd, S_TOOL, 11, true);
+ DlgFont(hWnd, R_SSTP, 0, true);
+
+ SmOpenVpnDlgUpdate(hWnd, s);
+}
+void SmOpenVpnDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ bool b1, b2;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b1 = IsChecked(hWnd, R_OPENVPN);
+ b2 = IsChecked(hWnd, R_SSTP);
+
+ SetEnable(hWnd, S_UDP, b1);
+ SetEnable(hWnd, E_UDP, b1);
+ SetEnable(hWnd, B_DEFAULT, b1);
+ SetEnable(hWnd, S_UDP2, b1);
+ SetEnable(hWnd, S_TOOL, b1);
+ SetEnable(hWnd, S_TOOL2, b1);
+ SetEnable(hWnd, B_CONFIG, b1);
+
+ SetEnable(hWnd, S_SSTP, b2);
+}
+void SmOpenVpnDlgOnOk(HWND hWnd, SM_SERVER *s, bool no_close)
+{
+ OPENVPN_SSTP_CONFIG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ t.EnableOpenVPN = IsChecked(hWnd, R_OPENVPN);
+ GetTxtA(hWnd, E_UDP, t.OpenVPNPortList, sizeof(t.OpenVPNPortList));
+ t.EnableSSTP = IsChecked(hWnd, R_SSTP);
+
+ if (CALL(hWnd, ScSetOpenVpnSstpConfig(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ if (no_close == false)
+ {
+ EndDialog(hWnd, 1);
+ }
+}
+
+// Open the EtherIP ID edit dialog
+bool SmEtherIpId(HWND hWnd, SM_ETHERIP_ID *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (Dialog(hWnd, D_SM_ETHERIP_ID, SmEtherIpIdDlg, t) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// EtherIP ID edit dialog procedure
+UINT SmEtherIpIdDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_ETHERIP_ID *t = (SM_ETHERIP_ID *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmEtherIpIdDlgInit(hWnd, t);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_ID:
+ case L_HUBNAME:
+ case E_USERNAME:
+ SmEtherIpIdDlgUpdate(hWnd, t);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmEtherIpIdDlgOnOk(hWnd, t);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize the EtherIP ID edit dialog
+void SmEtherIpIdDlgInit(HWND hWnd, SM_ETHERIP_ID *t)
+{
+ RPC_ENUM_HUB tt;
+ UINT sel_index;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_KEY);
+
+ // Get the current data in the case of edit mode
+ if (t->EditMode)
+ {
+ Zero(&t->Data, sizeof(t->Data));
+ StrCpy(t->Data.Id, sizeof(t->Data.Id), t->EditId);
+
+ if (CALL(hWnd, ScGetEtherIpId(t->s->Rpc, &t->Data)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+ }
+
+ // Enumerate the Virtual HUBs
+ Zero(&tt, sizeof(tt));
+ if (CALL(hWnd, ScEnumHub(t->s->Rpc, &tt)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ CbReset(hWnd, L_HUBNAME);
+ CbSetHeight(hWnd, L_HUBNAME, 18);
+ sel_index = INFINITE;
+
+ for (i = 0;i < tt.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &tt.Hubs[i];
+ UINT index;
+
+ index = CbAddStrA(hWnd, L_HUBNAME, e->HubName, 0);
+ if (sel_index == INFINITE)
+ {
+ sel_index = index;
+ }
+
+ if (t->EditMode)
+ {
+ if (StrCmpi(e->HubName, t->Data.HubName) == 0)
+ {
+ sel_index = index;
+ }
+ }
+ }
+
+ if (sel_index != INFINITE)
+ {
+ CbSelectIndex(hWnd, L_HUBNAME, sel_index);
+ }
+
+ if (t->EditMode)
+ {
+ SetTextA(hWnd, E_ID, t->Data.Id);
+ SetTextA(hWnd, E_USERNAME, t->Data.UserName);
+ SetTextA(hWnd, E_PASSWORD, t->Data.Password);
+
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ else
+ {
+ Focus(hWnd, E_ID);
+ }
+
+ FreeRpcEnumHub(&tt);
+
+ t->InitCompleted = true;
+ SmEtherIpIdDlgUpdate(hWnd, t);
+}
+
+// EtherIP ID edit dialog: Click the OK button
+void SmEtherIpIdDlgOnOk(HWND hWnd, SM_ETHERIP_ID *t)
+{
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ SmEtherIpIdDlgGetSetting(hWnd, t);
+
+ if (t->EditMode)
+ {
+ ETHERIP_ID d;
+ // Delete old items
+ Zero(&d, sizeof(d));
+
+ StrCpy(d.Id, sizeof(d.Id), t->EditId);
+
+ ScDeleteEtherIpId(t->s->Rpc, &d);
+ }
+
+ if (CALL(hWnd, ScAddEtherIpId(t->s->Rpc, &t->Data)) == false)
+ {
+ return;
+ }
+
+ if (t->EditMode == false)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_ETHERIP_ADD_OK"));
+ }
+
+ EndDialog(hWnd, 1);
+}
+
+// EtherIP ID edit dialog: Update the controls
+void SmEtherIpIdDlgUpdate(HWND hWnd, SM_ETHERIP_ID *t)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ if (t->InitCompleted == false)
+ {
+ return;
+ }
+
+ SmEtherIpIdDlgGetSetting(hWnd, t);
+
+ if (IsEmptyStr(t->Data.Id) ||
+ IsEmptyStr(t->Data.HubName) ||
+ IsEmptyStr(t->Data.UserName))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// EtherIP ID edit dialog: Get the current settings
+void SmEtherIpIdDlgGetSetting(HWND hWnd, SM_ETHERIP_ID *t)
+{
+ wchar_t *ws;
+ // Validate arguments
+ if (hWnd == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(&t->Data, sizeof(t->Data));
+
+ GetTxtA(hWnd, E_ID, t->Data.Id, sizeof(t->Data.Id));
+ GetTxtA(hWnd, E_USERNAME, t->Data.UserName, sizeof(t->Data.UserName));
+ GetTxtA(hWnd, E_PASSWORD, t->Data.Password, sizeof(t->Data.Password));
+
+ ws = CbGetStr(hWnd, L_HUBNAME);
+
+ if (ws != NULL && IsEmptyUniStr(ws) == false)
+ {
+ UniToStr(t->Data.HubName, sizeof(t->Data.HubName), ws);
+ }
+
+ Free(ws);
+}
+
+
+// Open the EtherIP settings dialog
+void SmEtherIp(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_ETHERIP, SmEtherIpDlg, s);
+}
+
+// EtherIP Setup dialog procedure
+UINT SmEtherIpDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ NMHDR *n;
+ char *id;
+ SM_ETHERIP_ID t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmEtherIpDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Edit
+ id = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (id != NULL)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.EditId, sizeof(t.EditId), id);
+ t.EditMode = true;
+ t.s = s;
+
+ if (SmEtherIpId(hWnd, &t))
+ {
+ SmEtherIpDlgRefresh(hWnd, s);
+ }
+
+ Free(id);
+ }
+ break;
+
+ case B_ADD:
+ // Add
+ Zero(&t, sizeof(t));
+ t.s = s;
+ if (SmEtherIpId(hWnd, &t))
+ {
+ SmEtherIpDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CRL_DELETE_MSG")) == IDYES)
+ {
+ id = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (id != NULL)
+ {
+ ETHERIP_ID d;
+
+ Zero(&d, sizeof(d));
+
+ StrCpy(d.Id, sizeof(d.Id), id);
+
+ if (CALL(hWnd, ScDeleteEtherIpId(s->Rpc, &d)))
+ {
+ SmEtherIpDlgRefresh(hWnd, s);
+ }
+
+ Free(id);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ // Close
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmEtherIpDlgUpdate(hWnd, s);
+ break;
+
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// EtherIP Setup dialog data update
+void SmEtherIpDlgRefresh(HWND hWnd, SM_SERVER *s)
+{
+ RPC_ENUM_ETHERIP_ID t;
+ UINT i;
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ // Data update
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, ScEnumEtherIpId(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ ETHERIP_ID *d = &t.IdList[i];
+ wchar_t id[MAX_SIZE], hubname[MAX_SIZE], username[MAX_SIZE];
+
+ StrToUni(id, sizeof(id), d->Id);
+ StrToUni(hubname, sizeof(hubname), d->HubName);
+ StrToUni(username, sizeof(username), d->UserName);
+
+ LvInsertAdd(b, ICO_CASCADE, NULL, 3, id, hubname, username);
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumEtherIpId(&t);
+
+ SmEtherIpDlgUpdate(hWnd, s);
+}
+
+// Initialize the EtherIP settings dialog
+void SmEtherIpDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_MACHINE);
+ DlgFont(hWnd, S_TITLE, 14, true);
+ DlgFont(hWnd, S_BOLD, 0, true);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_ETHERIP_COLUMN_0"), 205);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_ETHERIP_COLUMN_1"), 179);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_ETHERIP_COLUMN_2"), 154);
+
+ SmEtherIpDlgRefresh(hWnd, s);
+}
+
+// EtherIP Settings dialog controls update
+void SmEtherIpDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));
+ SetEnable(hWnd, B_DELETE, LvIsSingleSelected(hWnd, L_LIST));
+}
+
+// IPsec Settings dialog procedure
+UINT SmIPsecDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmIPsecDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_L2TP_OVER_IPSEC:
+ case R_L2TP_RAW:
+ case R_ETHERIP:
+ case E_SECRET:
+ case L_HUBNAME:
+ SmIPsecDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmIPsecDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_DETAIL:
+ // Advanced Settings dialog for EtherIP function
+ SmEtherIp(hWnd, s);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// IPsec Settings dialog: controls update
+void SmIPsecDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ IPSEC_SERVICES sl;
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SmIPsecDlgGetSetting(hWnd, &sl);
+
+ //SetEnable(hWnd, S_1, sl.L2TP_IPsec || sl.L2TP_Raw);
+ //SetEnable(hWnd, S_2, sl.L2TP_IPsec || sl.L2TP_Raw);
+ //SetEnable(hWnd, L_HUBNAME, sl.L2TP_IPsec || sl.L2TP_Raw);
+
+ SetEnable(hWnd, S_PSK, sl.L2TP_IPsec || sl.EtherIP_IPsec);
+ SetEnable(hWnd, S_PSK2, sl.L2TP_IPsec || sl.EtherIP_IPsec);
+ SetEnable(hWnd, E_SECRET, sl.L2TP_IPsec || sl.EtherIP_IPsec);
+
+ SetEnable(hWnd, B_DETAIL, sl.EtherIP_IPsec);
+
+ if ((sl.L2TP_IPsec || sl.EtherIP_IPsec) && IsEmptyStr(sl.IPsec_Secret))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Get the IPsec configuration into the structure
+void SmIPsecDlgGetSetting(HWND hWnd, IPSEC_SERVICES *sl)
+{
+ wchar_t *ws;
+ // Validate arguments
+ if (hWnd == NULL || sl == NULL)
+ {
+ return;
+ }
+
+ Zero(sl, sizeof(IPSEC_SERVICES));
+
+ sl->L2TP_IPsec = IsChecked(hWnd, R_L2TP_OVER_IPSEC);
+ sl->L2TP_Raw = IsChecked(hWnd, R_L2TP_RAW);
+ sl->EtherIP_IPsec = IsChecked(hWnd, R_ETHERIP);
+
+ ws = CbGetStr(hWnd, L_HUBNAME);
+ if (ws != NULL && IsEmptyUniStr(ws) == false)
+ {
+ UniToStr(sl->L2TP_DefaultHub, sizeof(sl->L2TP_DefaultHub), ws);
+ }
+
+ Free(ws);
+
+ GetTxtA(hWnd, E_SECRET, sl->IPsec_Secret, sizeof(sl->IPsec_Secret));
+}
+
+// IPsec Settings dialog initialization
+void SmIPsecDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ IPSEC_SERVICES sl;
+ RPC_ENUM_HUB t;
+ UINT i;
+ UINT sel_index;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_IPSEC);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+ SetFont(hWnd, E_SECRET, GetFont("Verdana", 10, false, false, false, false));
+
+ DlgFont(hWnd, R_L2TP_OVER_IPSEC, 0, true);
+ DlgFont(hWnd, R_L2TP_RAW, 0, true);
+ DlgFont(hWnd, R_ETHERIP, 0, true);
+
+ // Get the configuration
+ Zero(&sl, sizeof(sl));
+ if (CALL(hWnd, ScGetIPsecServices(s->Rpc, &sl)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ SetTextA(hWnd, E_SECRET, sl.IPsec_Secret);
+
+ Check(hWnd, R_L2TP_OVER_IPSEC, sl.L2TP_IPsec);
+ Check(hWnd, R_L2TP_RAW, sl.L2TP_Raw);
+ Check(hWnd, R_ETHERIP, sl.EtherIP_IPsec);
+
+ // Enumerate the Virtual HUBs
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumHub(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ CbReset(hWnd, L_HUBNAME);
+ CbSetHeight(hWnd, L_HUBNAME, 18);
+
+ sel_index = INFINITE;
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+ UINT index;
+
+ index = CbAddStrA(hWnd, L_HUBNAME, e->HubName, 0);
+ if (sel_index == INFINITE)
+ {
+ sel_index = index;
+ }
+
+ if (StrCmpi(e->HubName, sl.L2TP_DefaultHub) == 0)
+ {
+ sel_index = index;
+ }
+ }
+
+ if (sel_index != INFINITE)
+ {
+ CbSelectIndex(hWnd, L_HUBNAME, sel_index);
+ }
+
+ FreeRpcEnumHub(&t);
+
+ SmIPsecDlgUpdate(hWnd, s);
+}
+
+// IPsec Settings dialog: on click the OK button
+void SmIPsecDlgOnOk(HWND hWnd, SM_SERVER *s)
+{
+ IPSEC_SERVICES sl;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SmIPsecDlgGetSetting(hWnd, &sl);
+
+ // Confirm the length of the PSK
+ if (StrLen(sl.IPsec_Secret) >= 10)
+ {
+ IPSEC_SERVICES sl_old;
+ if (ScGetIPsecServices(s->Rpc, &sl_old) == ERR_NO_ERROR)
+ {
+ if (StrCmp(sl_old.IPsec_Secret, sl.IPsec_Secret) != 0 || ((sl_old.EtherIP_IPsec == false && sl_old.L2TP_IPsec == false)))
+ {
+ if (sl.EtherIP_IPsec || sl.L2TP_IPsec)
+ {
+ // Show a warning message if it exceeds 10 characters (Only if there is a change)
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO, _UU("SM_IPSEC_PSK_TOO_LONG")) == IDYES)
+ {
+ FocusEx(hWnd, E_SECRET);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ if (CALL(hWnd, ScSetIPsecServices(s->Rpc, &sl)) == false)
+ {
+ return;
+ }
+
+ EndDialog(hWnd, 1);
+}
+
+// Start the IPsec Settings dialog
+void SmIPsec(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_IPSEC, SmIPsecDlg, s);
+}
+
+// Message Settings
+void SmHubMsg(HWND hWnd, SM_EDIT_HUB *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_MSG, SmHubMsgDlg, s);
+}
+
+// Message dialog procedure
+UINT SmHubMsgDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_HUB *s = (SM_EDIT_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmHubMsgDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_TEXT:
+ SmHubMsgDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmHubMsgDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case C_USEMSG:
+ SmHubMsgDlgUpdate(hWnd, s);
+
+ if (IsChecked(hWnd, C_USEMSG))
+ {
+ FocusEx(hWnd, E_TEXT);
+ }
+ break;
+ }
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Message dialog initialization
+void SmHubMsgDlgInit(HWND hWnd, SM_EDIT_HUB *s)
+{
+ RPC_MSG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (MsIsVista())
+ {
+ SetFont(hWnd, E_TEXT, GetMeiryoFont());
+ }
+ else
+ {
+ DlgFont(hWnd, E_TEXT, 11, false);
+ }
+
+ FormatText(hWnd, S_MSG_2, s->HubName);
+
+ LimitText(hWnd, E_TEXT, HUB_MAXMSG_LEN);
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScGetHubMsg(s->p->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ if (UniIsEmptyStr(t.Msg) == false)
+ {
+ SetText(hWnd, E_TEXT, t.Msg);
+
+ Check(hWnd, C_USEMSG, true);
+ }
+ else
+ {
+ Check(hWnd, C_USEMSG, false);
+ }
+
+ FreeRpcMsg(&t);
+
+ SmHubMsgDlgUpdate(hWnd, s);
+}
+
+// [OK] button
+void SmHubMsgDlgOnOk(HWND hWnd, SM_EDIT_HUB *s)
+{
+ RPC_MSG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (IsChecked(hWnd, C_USEMSG) == false)
+ {
+ t.Msg = CopyUniStr(L"");
+ }
+ else
+ {
+ t.Msg = GetText(hWnd, E_TEXT);
+ }
+
+ if (CALL(hWnd, ScSetHubMsg(s->p->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ FreeRpcMsg(&t);
+
+ EndDialog(hWnd, 1);
+}
+
+// Message dialog update
+void SmHubMsgDlgUpdate(HWND hWnd, SM_EDIT_HUB *s)
+{
+ bool b = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, E_TEXT, IsChecked(hWnd, C_USEMSG));
+
+ if (IsChecked(hWnd, C_USEMSG))
+ {
+ wchar_t *s = GetText(hWnd, E_TEXT);
+
+ b = !IsEmptyUniStr(s);
+
+ Free(s);
+ }
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+// VLAN utility
+void SmVLan(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_VLAN, SmVLanDlg, s);
+}
+
+// VLAN dialog
+UINT SmVLanDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ NMHDR *n;
+
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmVLanDlgInit(hWnd, s);
+
+ if (LvNum(hWnd, L_LIST) == 0)
+ {
+ Disable(hWnd, L_LIST);
+ SetTimer(hWnd, 1, 100, NULL);
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_VLAN_NOTHING"),
+ s->CurrentSetting->ClientOption.Hostname);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_ENABLE:
+ case B_DISABLE:
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ char *name = LvGetStrA(hWnd, L_LIST, i, 0);
+
+ if (IsEmptyStr(name) == false)
+ {
+ RPC_TEST t;
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.StrValue, sizeof(t.StrValue), name);
+ t.IntValue = BOOL_TO_INT(wParam == B_ENABLE);
+
+ if (CALL(hWnd, ScSetEnableEthVLan(s->Rpc, &t)))
+ {
+ SmVLanDlgRefresh(hWnd, s);
+
+ if (wParam == B_ENABLE)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION,
+ _UU("SM_VLAN_MSG_1"),
+ name, name, name);
+ }
+ else
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION,
+ _UU("SM_VLAN_MSG_2"),
+ name);
+ }
+ }
+ }
+
+ Free(name);
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmVLanDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// VLAN dialog initialization
+void SmVLanDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_VLAN_COLUMN_0"), 245);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_VLAN_COLUMN_1"), 75);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_VLAN_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_VLAN_COLUMN_3"), 100);
+ LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_VLAN_COLUMN_4"), 290);
+ LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_VLAN_COLUMN_5"), 430);
+
+ SmVLanDlgRefresh(hWnd, s);
+}
+
+// VLAN dialog content update
+void SmVLanDlgRefresh(HWND hWnd, SM_SERVER *s)
+{
+ LVB *b;
+ RPC_ENUM_ETH_VLAN t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumEthVLan(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_ETH_VLAN_ITEM *e = &t.Items[i];
+
+ if (e->Support)
+ {
+ wchar_t tmp0[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t *tmp3;
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+
+ StrToUni(tmp0, sizeof(tmp0), e->DeviceName);
+ StrToUni(tmp1, sizeof(tmp1), e->DriverType);
+ StrToUni(tmp2, sizeof(tmp2), e->DriverName);
+ tmp3 = (e->Enabled ? _UU("SM_VLAN_YES") : _UU("SM_VLAN_NO"));
+ StrToUni(tmp4, sizeof(tmp4), e->Guid);
+ StrToUni(tmp5, sizeof(tmp5), e->DeviceInstanceId);
+
+ LvInsertAdd(b,
+ e->Enabled ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE, 0, 6,
+ tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumEthVLan(&t);
+
+ SmVLanDlgUpdate(hWnd, s);
+}
+
+// VLAN dialog control update
+void SmVLanDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSingleSelected(hWnd, L_LIST) == false)
+ {
+ Disable(hWnd, B_ENABLE);
+ Disable(hWnd, B_DISABLE);
+ }
+ else
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_LIST, i, 3);
+
+ if (UniStrCmpi(s, _UU("SM_VLAN_YES")) != 0)
+ {
+ Enable(hWnd, B_ENABLE);
+ Disable(hWnd, B_DISABLE);
+ }
+ else
+ {
+ Enable(hWnd, B_DISABLE);
+ Disable(hWnd, B_ENABLE);
+ }
+
+ Free(s);
+ }
+ }
+}
+
+// Examine whether the current state of VPN Server / VPN Bridge is the initial state
+bool SmSetupIsNew(SM_SERVER *s)
+{
+ RPC *rpc;
+ bool is_bridge;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ bool check_hub = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->ServerAdminMode == false)
+ {
+ return false;
+ }
+
+ rpc = s->Rpc;
+ is_bridge =s->Bridge;
+
+ // Server type
+ if (is_bridge == false)
+ {
+ bool b = false;
+ RPC_SERVER_INFO t;
+
+ Zero(&t, sizeof(t));
+ if (ScGetServerInfo(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.ServerType != SERVER_TYPE_STANDALONE)
+ {
+ b = true;
+ }
+
+ FreeRpcServerInfo(&t);
+ }
+ else
+ {
+ return false;
+ }
+
+ if (b)
+ {
+ return false;
+ }
+ }
+
+ // Local bridge
+ if (true)
+ {
+ RPC_ENUM_LOCALBRIDGE t;
+ bool b = false;
+
+ Zero(&t, sizeof(t));
+ if (ScEnumLocalBridge(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.NumItem != 0)
+ {
+ b = true;
+ }
+ FreeRpcEnumLocalBridge(&t);
+ }
+
+ if (b)
+ {
+ return false;
+ }
+ }
+
+ // Virtual HUB
+
+ check_hub = false;
+
+ if (is_bridge == false)
+ {
+ RPC_ENUM_HUB t;
+ bool b = false;
+
+ Zero(&t, sizeof(t));
+ if (ScEnumHub(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.NumHub >= 2)
+ {
+ b = true;
+ }
+ else if (t.NumHub == 1)
+ {
+ if (StrCmpi(t.Hubs[0].HubName, SERVER_DEFAULT_HUB_NAME) != 0)
+ {
+ b = true;
+ }
+ else
+ {
+ check_hub = true;
+ }
+ }
+
+ FreeRpcEnumHub(&t);
+ }
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ check_hub = true;
+ }
+
+ // Status of the virtual HUB
+ if (is_bridge == false)
+ {
+ StrCpy(hubname, sizeof(hubname), SERVER_DEFAULT_HUB_NAME);
+ }
+ else
+ {
+ StrCpy(hubname, sizeof(hubname), SERVER_DEFAULT_BRIDGE_NAME);
+ }
+
+ if (check_hub)
+ {
+ if (true)
+ {
+ // Number of objects in the Virtual HUB
+ RPC_HUB_STATUS t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScGetHubStatus(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.NumSessions != 0 || t.NumAccessLists != 0 ||
+ t.NumUsers != 0 || t.NumGroups != 0 ||
+ t.NumMacTables != 0 || t.NumIpTables != 0 ||
+ t.SecureNATEnabled)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (true)
+ {
+ // Cascade connection
+ RPC_ENUM_LINK t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScEnumLink(rpc, &t) == ERR_NO_ERROR)
+ {
+ bool b = false;
+
+ if (t.NumLink != 0)
+ {
+ b = true;
+ }
+
+ FreeRpcEnumLink(&t);
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // Certificate list to trust
+ RPC_HUB_ENUM_CA t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScEnumCa(rpc, &t) == ERR_NO_ERROR)
+ {
+ bool b = false;
+
+ if (t.NumCa != 0)
+ {
+ b = true;
+ }
+
+ FreeRpcHubEnumCa(&t);
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // Certificate revocation list
+ RPC_ENUM_CRL t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScEnumCrl(rpc, &t) == ERR_NO_ERROR)
+ {
+ bool b = false;
+
+ if (t.NumItem != 0)
+ {
+ b = true;
+ }
+
+ FreeRpcEnumCrl(&t);
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // Authentication server configuration
+ RPC_RADIUS t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScGetHubRadius(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (IsEmptyStr(t.RadiusServerName) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // Virtual HUB configuration
+ RPC_CREATE_HUB t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScGetHub(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.HubOption.NoEnum || t.HubOption.MaxSession != 0 ||
+ t.Online == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // IP access control list
+ RPC_AC_LIST t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScGetAcList(rpc, &t) == ERR_NO_ERROR)
+ {
+ bool b = false;
+ if (LIST_NUM(t.o) != 0)
+ {
+ b = true;
+ }
+ FreeRpcAcList(&t);
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (is_bridge == false)
+ {
+ // AO
+ RPC_ADMIN_OPTION t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (ScGetHubAdminOptions(rpc, &t) == ERR_NO_ERROR)
+ {
+ bool b = false;
+ UINT i;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ if (t.Items[i].Value != 0)
+ {
+ b = true;
+ }
+ }
+
+ FreeRpcAdminOption(&t);
+
+ if (b)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // Virtual layer 3 switch
+ if (is_bridge == false)
+ {
+ RPC_ENUM_L3SW t;
+ bool b = false;
+
+ Zero(&t, sizeof(t));
+ if (ScEnumL3Switch(rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.NumItem != 0)
+ {
+ b = true;
+ }
+
+ FreeRpcEnumL3Sw(&t);
+ }
+ else
+ {
+ return false;
+ }
+
+ if (b)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Setup procedure dialog initialization
+void SmSetupStepDlgInit(HWND hWnd, SM_SETUP *s)
+{
+ bool b;
+ RPC_ENUM_ETH t;
+ UINT i;
+ RPC_BRIDGE_SUPPORT bs;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SETUP);
+
+ DlgFont(hWnd, S_1_1, 0, true);
+ DlgFont(hWnd, S_2_1, 0, true);
+ DlgFont(hWnd, S_3_1, 0, true);
+
+ b = false;
+ if (s->UseRemote)
+ {
+ b = true;
+ }
+ if (s->UseSite && s->UseSiteEdge == false)
+ {
+ b = true;
+ }
+
+ SetEnable(hWnd, S_1_1, b);
+ SetEnable(hWnd, S_1_2, b);
+ SetEnable(hWnd, B_USER, b);
+
+ b = false;
+ if (s->UseSiteEdge)
+ {
+ b = true;
+ }
+
+ SetEnable(hWnd, S_2_1, b);
+ SetEnable(hWnd, S_2_2, b);
+ SetEnable(hWnd, B_CASCADE, b);
+
+ CbReset(hWnd, C_DEVICE);
+ CbSetHeight(hWnd, C_DEVICE, 18);
+
+ Zero(&t, sizeof(t));
+
+ CbAddStr(hWnd, C_DEVICE, _UU("SM_SETUP_SELECT"), 0);
+
+ Zero(&bs, sizeof(bs));
+ if (CALL(hWnd, ScGetBridgeSupport(s->Rpc, &bs)) == false)
+ {
+ return;
+ }
+
+ if (bs.IsBridgeSupportedOs)
+ {
+ // Enumerate the local bridges
+ if (ScEnumEthernet(s->Rpc, &t) == ERR_NO_ERROR)
+ {
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp[MAX_PATH];
+ RPC_ENUM_ETH_ITEM *e = &t.Items[i];
+
+ if (GetCapsBool(s->s->CapsList, "b_support_network_connection_name"))
+ {
+ UniFormat(tmp, sizeof(tmp), BRIDGE_NETWORK_CONNECTION_STR, e->NetworkConnectionName, e->DeviceName);
+ }
+ else
+ {
+ StrToUni(tmp, sizeof(tmp), e->DeviceName);
+ }
+
+ CbAddStr(hWnd, C_DEVICE, tmp, 1);
+ }
+
+ FreeRpcEnumEth(&t);
+ }
+ Show(hWnd, C_DEVICE);
+ Hide(hWnd, B_SECURENAT);
+ }
+ else
+ {
+ RPC_HUB t;
+
+ // Enable the SecureNAT automatically if the local bridge does not work in this environment
+ SetText(hWnd, S_3_2, _UU("SM_SETUP_STEP_SECURENAT"));
+ SetText(hWnd, S_3_1, _UU("SM_SETUP_STEP_SECURENAT_TITLE"));
+ Hide(hWnd, C_DEVICE);
+ Show(hWnd, B_SECURENAT);
+ SetIcon(hWnd, S_ICON, ICO_ROUTER);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ ScEnableSecureNAT(s->Rpc, &t);
+ }
+
+ s->Flag1 = false;
+ s->Flag2 = false;
+}
+
+// Close
+void SmSetupOnClose(HWND hWnd, SM_SETUP *s)
+{
+ wchar_t *tmp;
+ char name[MAX_PATH];
+ RPC_BRIDGE_SUPPORT bs;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&bs, sizeof(bs));
+ if (CALL(hWnd, ScGetBridgeSupport(s->Rpc, &bs)) == false)
+ {
+ return;
+ }
+
+ if (bs.IsBridgeSupportedOs)
+ {
+ // Add a Local Bridge
+ tmp = CbGetStr(hWnd, C_DEVICE);
+
+ if (tmp != NULL)
+ {
+ UniToStr(name, sizeof(name), tmp);
+
+ if (CbGetSelect(hWnd, C_DEVICE) != 0)
+ {
+ // Show a warning message if the VPN Server is running in a VM
+ if (GetCapsBool(s->s->CapsList, "b_is_in_vm"))
+ {
+ Dialog(hWnd, D_SM_VMBRIDGE, SmVmBridgeDlg, NULL);
+ }
+
+ if (GetCapsBool(s->s->CapsList, "b_support_network_connection_name") == false)
+ {
+ RPC_LOCALBRIDGE t;
+
+ Zero(&t, sizeof(t));
+ t.Active = true;
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), name);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Online = true;
+ t.TapMode = false;
+
+ if (CALL(hWnd, ScAddLocalBridge(s->Rpc, &t)) == false)
+ {
+ Free(tmp);
+ return;
+ }
+ }
+ else
+ {
+ RPC_ENUM_ETH tt;
+ UINT i;
+
+ Zero(&tt, sizeof(tt));
+ if (CALL(hWnd, ScEnumEthernet(s->Rpc, &tt)) == false)
+ {
+ Free(tmp);
+ return;
+ }
+
+ for (i = 0;i < tt.NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *ti = &tt.Items[i];
+ wchar_t fullname[MAX_SIZE];
+
+ UniFormat(fullname, sizeof(fullname), BRIDGE_NETWORK_CONNECTION_STR, ti->NetworkConnectionName, ti->DeviceName);
+
+ if (UniStrCmpi(fullname, tmp) == 0)
+ {
+ RPC_LOCALBRIDGE t;
+
+ Zero(&t, sizeof(t));
+ t.Active = true;
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), ti->DeviceName);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Online = true;
+ t.TapMode = false;
+
+ if (CALL(hWnd, ScAddLocalBridge(s->Rpc, &t)) == false)
+ {
+ FreeRpcEnumEth(&tt);
+ Free(tmp);
+ return;
+ }
+ break;
+ }
+ }
+
+ FreeRpcEnumEth(&tt);
+ }
+
+ }
+ Free(tmp);
+ }
+ }
+ else
+ {
+ // Enable the SecureNAT
+ }
+
+ EndDialog(hWnd, 0);
+}
+
+// Setup Procedure dialog procedure
+UINT SmSetupStepDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SETUP *s = (SM_SETUP *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmSetupStepDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_USER:
+ // User creation
+ if (true)
+ {
+ SM_HUB h;
+
+ Zero(&h, sizeof(h));
+ h.HubName = s->HubName;
+ h.p = s->s;
+ h.Rpc = s->Rpc;
+
+ SmUserListDlgEx(hWnd, &h, NULL, s->Flag1 ? false : true);
+
+ s->Flag1 = true;
+ }
+ break;
+
+ case B_CASCADE:
+ // Create a cascade connection
+ if (true)
+ {
+ SM_HUB h;
+
+ Zero(&h, sizeof(h));
+ h.HubName = s->HubName;
+ h.p = s->s;
+ h.Rpc = s->Rpc;
+
+ SmLinkDlgEx(hWnd, &h, s->Flag2 ? false : true);
+ s->Flag2 = true;
+ }
+ break;
+
+ case B_SECURENAT:
+ // Setting the SecureNAT
+ if (true)
+ {
+ SM_HUB h;
+
+ Zero(&h, sizeof(h));
+ h.p = s->s;
+ h.Rpc = s->Rpc;
+ h.HubName = s->HubName;
+
+ Dialog(hWnd, D_SM_SNAT, SmSNATDlgProc, &h);
+ }
+ break;
+
+ case IDCANCEL:
+ // Close button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ // Exit
+ SmSetupOnClose(hWnd, s);
+ break;
+ }
+
+ return 0;
+}
+
+// Setup procedure dialog
+void SmSetupStep(HWND hWnd, SM_SETUP *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_SETUP_STEP, SmSetupStepDlg, s);
+}
+
+// Initialize by setup
+bool SmSetupInit(HWND hWnd, SM_SETUP *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->IsBridge == false)
+ {
+ if (SmSetupDeleteAllLayer3(hWnd, s) == false)
+ {
+ return false;
+ }
+
+ if (SmSetupDeleteAllHub(hWnd, s) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (SmSetupDeleteAllObjectInBridgeHub(hWnd, s) == false)
+ {
+ return false;
+ }
+ }
+
+ SmSetupDeleteAllLocalBridge(hWnd, s);
+
+ if (s->IsBridge == false)
+ {
+ // Create a Virtual HUB
+ RPC_CREATE_HUB t;
+ char *password = "";
+
+ Zero(&t, sizeof(t));
+ Hash(t.HashedPassword, password, StrLen(password), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, password);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.HubType = HUB_TYPE_STANDALONE;
+ t.Online = true;
+
+ if (CALL(hWnd, ScCreateHub(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Remove all objects in the Virtual HUB of the VPN Bridge
+bool SmSetupDeleteAllObjectInBridgeHub(HWND hWnd, SM_SETUP *s)
+{
+ char *hubname = SERVER_DEFAULT_BRIDGE_NAME;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (true)
+ {
+ RPC_ENUM_LINK t;
+ UINT i;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (CALL(hWnd, ScEnumLink(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t.NumLink;i++)
+ {
+ RPC_ENUM_LINK_ITEM *e = &t.Links[i];
+ RPC_LINK a;
+
+ Zero(&a, sizeof(a));
+ StrCpy(a.HubName, sizeof(a.HubName), hubname);
+ UniStrCpy(a.AccountName, sizeof(a.AccountName), e->AccountName);
+
+ if (CALL(hWnd, ScDeleteLink(s->Rpc, &a)) == false)
+ {
+ FreeRpcEnumLink(&t);
+ return false;
+ }
+ }
+
+ FreeRpcEnumLink(&t);
+ }
+
+ if (true)
+ {
+ RPC_HUB t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if (CALL(hWnd, ScDisableSecureNAT(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Delete all Virtual Layer 3 Switches
+bool SmSetupDeleteAllLayer3(HWND hWnd, SM_SETUP *s)
+{
+ RPC_ENUM_L3SW t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if(CALL(hWnd, ScEnumL3Switch(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *e = &t.Items[i];
+ RPC_L3SW tt;
+
+ Zero(&tt, sizeof(tt));
+ StrCpy(tt.Name, sizeof(tt.Name), e->Name);
+
+ if (CALL(hWnd, ScDelL3Switch(s->Rpc, &tt)) == false)
+ {
+ FreeRpcEnumL3Sw(&t);
+ return false;
+ }
+ }
+
+ FreeRpcEnumL3Sw(&t);
+
+ return true;
+}
+
+// Delete all local bridges
+bool SmSetupDeleteAllLocalBridge(HWND hWnd, SM_SETUP *s)
+{
+ RPC_ENUM_LOCALBRIDGE t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (ScEnumLocalBridge(s->Rpc, &t) != ERR_NO_ERROR)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t.Items[i];
+
+ if (CALL(hWnd, ScDeleteLocalBridge(s->Rpc, e)) == false)
+ {
+ FreeRpcEnumLocalBridge(&t);
+ return false;
+ }
+ }
+
+ FreeRpcEnumLocalBridge(&t);
+
+ return true;
+}
+
+// Delete all Virtual HUBs
+bool SmSetupDeleteAllHub(HWND hWnd, SM_SETUP *s)
+{
+ RPC_ENUM_HUB t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumHub(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+ RPC_DELETE_HUB tt;
+
+ Zero(&tt, sizeof(tt));
+ StrCpy(tt.HubName, sizeof(tt.HubName), e->HubName);
+
+ if (CALL(hWnd, ScDeleteHub(s->Rpc, &tt)) == false)
+ {
+ FreeRpcEnumHub(&t);
+ return false;
+ }
+ }
+
+ FreeRpcEnumHub(&t);
+
+ return true;
+}
+
+// Update the control of the Virtual HUB
+void SmSetupHubDlgUpdate(HWND hWnd, SM_SETUP *s)
+{
+ bool ok = true;
+ char tmp[MAX_HUBNAME_LEN + 1];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_HUBNAME, tmp, sizeof(tmp));
+
+ if (IsEmptyStr(tmp) || IsSafeStr(tmp) == false)
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Virtual HUB creation dialog
+UINT SmSetupHubDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SETUP *s = (SM_SETUP *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetTextA(hWnd, E_HUBNAME, "VPN");
+ FocusEx(hWnd, E_HUBNAME);
+ SmSetupHubDlgUpdate(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ SmSetupHubDlgUpdate(hWnd, s);
+
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_HUBNAME, s->HubName, sizeof(s->HubName));
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Setup dialog: [Next] button
+void SmSetupDlgOnOk(HWND hWnd, SM_SETUP *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, _UU("SM_SETUP_WARNING")) == IDNO)
+ {
+ return;
+ }
+
+ s->UseRemote = IsChecked(hWnd, C_REMOTE);
+ s->UseSite = IsChecked(hWnd, C_SITE);
+ s->UseSiteEdge = IsChecked(hWnd, C_EDGE);
+
+ if (s->IsBridge)
+ {
+ StrCpy(s->HubName, sizeof(s->HubName), SERVER_DEFAULT_BRIDGE_NAME);
+ }
+ else
+ {
+ if (Dialog(hWnd, D_SM_SETUP_HUB, SmSetupHubDlg, s) == false)
+ {
+ return;
+ }
+ }
+
+ // Initialize (Wipe existing objects)
+ if (SmSetupInit(hWnd, s) == false)
+ {
+ return;
+ }
+
+ if (s->IsBridge == false)
+ {
+ if (GetCapsBool(s->s->CapsList, "b_support_ddns"))
+ {
+ if (s->UseRemote || (s->UseSite && s->UseSiteEdge == false))
+ {
+ DDNS_CLIENT_STATUS st;
+
+ Zero(&st, sizeof(st));
+
+ if (ScGetDDnsClientStatus(s->s->Rpc, &st) == ERR_NO_ERROR &&
+ IsEmptyStr(st.CurrentHostName) == false)
+ {
+ // Display the Dynamic DNS setting screen
+ SmDDns(hWnd, s->s, true, false);
+ }
+ }
+ }
+
+ // Configure the IPsec if the IPsec feature is available
+ if (GetCapsBool(s->s->CapsList, "b_support_ipsec") && s->s->IPsecMessageDisplayed == false)
+ {
+ // Display a message about IPsec
+ RPC_TEST flag;
+
+ if (s->UseRemote || (s->UseSite && s->UseSiteEdge == false))
+ {
+ SmIPsec(hWnd, s->s);
+ }
+
+ Zero(&flag, sizeof(flag));
+ flag.IntValue = 9;
+ ToStr(flag.StrValue, 1);
+
+ ScDebug(s->s->Rpc, &flag);
+
+ s->s->IPsecMessageDisplayed = true;
+ }
+
+ // Confgure the VPN Azure if VPN Azure feature is available
+ if (GetCapsBool(s->s->CapsList, "b_support_azure"))
+ {
+ SmAzure(hWnd, s->s, true);
+ }
+
+ }
+
+ // Execute the procedure
+ SmSetupStep(hWnd, s);
+
+ // Close the dialog
+ EndDialog(hWnd, true);
+}
+
+// Setup dialog: initialization
+void SmSetupDlgInit(HWND hWnd, SM_SETUP *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SETUP);
+ DlgFont(hWnd, S_TITLE, 14, true);
+ DlgFont(hWnd, C_REMOTE, 0, true);
+ DlgFont(hWnd, C_SITE, 0, true);
+ DlgFont(hWnd, C_OTHER, 0, true);
+
+ if (s->IsBridge)
+ {
+ SetText(hWnd, B_BOLD, _UU("SM_SETUP_BRIDGE_ONLY"));
+ SetText(hWnd, C_EDGE, _UU("SM_SETUP_BRIDGE_EDGE"));
+
+ Check(hWnd, C_SITE, true);
+ Check(hWnd, C_EDGE, true);
+ Focus(hWnd, C_SITE);
+ }
+
+ SmSetupDlgUpdate(hWnd, s);
+}
+
+// Setup dialog: update
+void SmSetupDlgUpdate(HWND hWnd, SM_SETUP *s)
+{
+ bool enable_remote = true;
+ bool enable_site = true;
+ bool enable_site_center = true;
+ bool enable_detail = true;
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->IsBridge)
+ {
+ enable_remote = false;
+ enable_site_center = false;
+ enable_detail = false;
+ }
+
+ if (IsChecked(hWnd, C_OTHER))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, C_REMOTE, enable_remote && IsChecked(hWnd, C_OTHER) == false);
+ SetEnable(hWnd, S_REMOTE_1, enable_remote && IsChecked(hWnd, C_OTHER) == false);
+
+ SetEnable(hWnd, C_SITE, enable_site && IsChecked(hWnd, C_OTHER) == false);
+ SetEnable(hWnd, S_SITE_1, enable_site && IsChecked(hWnd, C_OTHER) == false);
+ SetEnable(hWnd, S_SITE_2, enable_site && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);
+ SetEnable(hWnd, C_CENTER, enable_site && enable_site_center && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);
+ SetEnable(hWnd, C_EDGE, enable_site && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);
+
+ SetEnable(hWnd, C_OTHER, enable_detail);
+ SetEnable(hWnd, S_OTHER, enable_detail);
+
+ if (IsChecked(hWnd, C_REMOTE) == false && IsChecked(hWnd, C_SITE) == false)
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, C_SITE))
+ {
+ if (IsChecked(hWnd, C_CENTER) == false && IsChecked(hWnd, C_EDGE) == false)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+
+ SetText(hWnd, S_INFO,
+ IsChecked(hWnd, C_OTHER) ? _UU("SM_SETUP_INFO_2") : _UU("SM_SETUP_INFO_1"));
+}
+
+// Setup dialog
+UINT SmSetupDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SETUP *s = (SM_SETUP *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmSetupDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ SmSetupDlgUpdate(hWnd, s);
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmSetupDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Setup
+bool SmSetup(HWND hWnd, SM_SERVER *s)
+{
+ SM_SETUP ss;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ss, sizeof(ss));
+ ss.s = s;
+ ss.IsBridge = ss.s->Bridge;
+ ss.Rpc = s->Rpc;
+
+ if (Dialog(hWnd, D_SM_SETUP, SmSetupDlg, &ss) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// License registration process
+void SmLicenseAddDlgOnOk(HWND hWnd, SM_SERVER *s)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SmLicenseAddDlgGetText(hWnd, tmp, sizeof(tmp));
+
+ if (LiIsLicenseKey(tmp))
+ {
+ RPC_TEST t;
+
+ Disable(hWnd, IDOK);
+ Disable(hWnd, IDCANCEL);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.StrValue, sizeof(t.StrValue), tmp);
+
+ if (CALL(hWnd, ScAddLicenseKey(s->Rpc, &t)) == false)
+ {
+ FocusEx(hWnd, B_KEY6);
+ }
+ else
+ {
+ EndDialog(hWnd, true);
+ }
+
+ Enable(hWnd, IDOK);
+ Enable(hWnd, IDCANCEL);
+ }
+}
+
+// Shift treatment of text input
+void SmLicenseAddDlgShiftTextItem(HWND hWnd, UINT id1, UINT id2, UINT *next_focus)
+{
+ char *s;
+ // Validate arguments
+ if (hWnd == NULL || next_focus == NULL)
+ {
+ return;
+ }
+
+ s = GetTextA(hWnd, id1);
+ if (StrLen(s) >= 6)
+ {
+ char *s2 = CopyStr(s);
+ char tmp[MAX_SIZE];
+ s2[6] = 0;
+ SetTextA(hWnd, id1, s2);
+ Free(s2);
+
+ if (id2 != 0)
+ {
+ GetTxtA(hWnd, id2, tmp, sizeof(tmp));
+
+ StrCat(tmp, sizeof(tmp), s + 6);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "-", "", false);
+
+ SetTextA(hWnd, id2, tmp);
+
+ *next_focus = id2;
+ }
+ else
+ {
+ *next_focus = IDOK;
+ }
+ }
+
+ Free(s);
+}
+
+// Make a text from the input data
+void SmLicenseAddDlgGetText(HWND hWnd, char *str, UINT size)
+{
+ char *k1, *k2, *k3, *k4, *k5, *k6;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ k1 = GetTextA(hWnd, B_KEY1);
+ k2 = GetTextA(hWnd, B_KEY2);
+ k3 = GetTextA(hWnd, B_KEY3);
+ k4 = GetTextA(hWnd, B_KEY4);
+ k5 = GetTextA(hWnd, B_KEY5);
+ k6 = GetTextA(hWnd, B_KEY6);
+
+ Format(str, size, "%s-%s-%s-%s-%s-%s", k1, k2, k3, k4, k5, k6);
+
+ Free(k1);
+ Free(k2);
+ Free(k3);
+ Free(k4);
+ Free(k5);
+ Free(k6);
+}
+
+// License addition dialog update
+void SmLicenseAddDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ UINT next_focus = 0;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY1, B_KEY2, &next_focus);
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY2, B_KEY3, &next_focus);
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY3, B_KEY4, &next_focus);
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY4, B_KEY5, &next_focus);
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY5, B_KEY6, &next_focus);
+ SmLicenseAddDlgShiftTextItem(hWnd, B_KEY6, 0, &next_focus);
+
+ if ((IsFocus(hWnd, B_KEY1) && GetTextLen(hWnd, B_KEY1, true) <= 5) ||
+ (IsFocus(hWnd, B_KEY2) && GetTextLen(hWnd, B_KEY2, true) <= 5) ||
+ (IsFocus(hWnd, B_KEY3) && GetTextLen(hWnd, B_KEY3, true) <= 5) ||
+ (IsFocus(hWnd, B_KEY4) && GetTextLen(hWnd, B_KEY4, true) <= 5) ||
+ (IsFocus(hWnd, B_KEY5) && GetTextLen(hWnd, B_KEY5, true) <= 5) ||
+ (IsFocus(hWnd, B_KEY6) && GetTextLen(hWnd, B_KEY6, true) <= 5))
+ {
+ next_focus = 0;
+ }
+
+ if (next_focus != 0)
+ {
+ Focus(hWnd, next_focus);
+ }
+
+ SmLicenseAddDlgGetText(hWnd, tmp, sizeof(tmp));
+
+ SetEnable(hWnd, IDOK, LiIsLicenseKey(tmp));
+}
+
+// License addition dialog initialization
+void SmLicenseAddDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ HFONT h;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ h = GetFont("Arial", 10, true, false, false, false);
+ SetFont(hWnd, B_KEY1, h);
+ SetFont(hWnd, B_KEY2, h);
+ SetFont(hWnd, B_KEY3, h);
+ SetFont(hWnd, B_KEY4, h);
+ SetFont(hWnd, B_KEY5, h);
+ SetFont(hWnd, B_KEY6, h);
+
+ DlgFont(hWnd, S_INFO, 10, true);
+
+ SmLicenseAddDlgUpdate(hWnd, s);
+}
+
+// License addition dialog
+UINT SmLicenseAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmLicenseAddDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case B_KEY1:
+ case B_KEY2:
+ case B_KEY3:
+ case B_KEY4:
+ case B_KEY5:
+ case B_KEY6:
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ SmLicenseAddDlgUpdate(hWnd, s);
+
+ switch (LOWORD(wParam))
+ {
+ case B_KEY2:
+ if (GetTextLen(hWnd, B_KEY2, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY1);
+ }
+ break;
+ case B_KEY3:
+ if (GetTextLen(hWnd, B_KEY3, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY2);
+ }
+ break;
+ case B_KEY4:
+ if (GetTextLen(hWnd, B_KEY4, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY3);
+ }
+ break;
+ case B_KEY5:
+ if (GetTextLen(hWnd, B_KEY5, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY4);
+ }
+ break;
+ case B_KEY6:
+ if (GetTextLen(hWnd, B_KEY6, true) == 0)
+ {
+ FocusEx(hWnd, B_KEY5);
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmLicenseAddDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Add a license
+bool SmLicenseAdd(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_SM_LICENSE_ADD, SmLicenseAddDlg, s);
+}
+
+// License dialog initialization
+void SmLicenseDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_CERT);
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+ DlgFont(hWnd, S_BOLD2, 0, true);
+
+ LvInit(hWnd, L_LIST);
+ LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_LICENSE_COLUMN_1"), 50);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_LICENSE_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_LICENSE_COLUMN_3"), 290);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_LICENSE_COLUMN_4"), 150);
+ LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_LICENSE_COLUMN_5"), 120);
+ LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_LICENSE_COLUMN_6"), 250);
+ LvInsertColumn(hWnd, L_LIST, 6, _UU("SM_LICENSE_COLUMN_7"), 100);
+ LvInsertColumn(hWnd, L_LIST, 7, _UU("SM_LICENSE_COLUMN_8"), 100);
+ LvInsertColumn(hWnd, L_LIST, 8, _UU("SM_LICENSE_COLUMN_9"), 100);
+
+ LvInitEx(hWnd, L_STATUS, true);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 100);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 100);
+
+ SmLicenseDlgRefresh(hWnd, s);
+}
+
+// License dialog update
+void SmLicenseDlgRefresh(HWND hWnd, SM_SERVER *s)
+{
+ RPC_ENUM_LICENSE_KEY t;
+ RPC_LICENSE_STATUS st;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, ScEnumLicenseKey(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ wchar_t tmp1[32], tmp2[LICENSE_KEYSTR_LEN + 1], tmp3[LICENSE_MAX_PRODUCT_NAME_LEN + 1],
+ *tmp4, tmp5[128], tmp6[LICENSE_LICENSEID_STR_LEN + 1], tmp7[64],
+ tmp8[64], tmp9[64];
+ RPC_ENUM_LICENSE_KEY_ITEM *e = &t.Items[i];
+
+ UniToStru(tmp1, e->Id);
+ StrToUni(tmp2, sizeof(tmp2), e->LicenseKey);
+ StrToUni(tmp3, sizeof(tmp3), e->LicenseName);
+ tmp4 = LiGetLicenseStatusStr(e->Status);
+ if (e->Expires == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp5, sizeof(tmp5), e->Expires, NULL);
+ }
+ StrToUni(tmp6, sizeof(tmp6), e->LicenseId);
+ UniToStru(tmp7, e->ProductId);
+ UniFormat(tmp8, sizeof(tmp8), L"%I64u", e->SystemId);
+ UniToStru(tmp9, e->SerialId);
+
+ LvInsertAdd(b,
+ e->Status == LICENSE_STATUS_OK ? ICO_PASS : ICO_DISCARD,
+ (void *)e->Id, 9,
+ tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumLicenseKey(&t);
+
+ Zero(&st, sizeof(st));
+
+ if (CALL(hWnd, ScGetLicenseStatus(s->Rpc, &st)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ if (st.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE)
+ {
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NO_LICENSE_COLUMN"), _UU("SM_NO_LICENSE"));
+ }
+ else
+ {
+ // Product edition name
+ StrToUni(tmp, sizeof(tmp), st.EditionStr);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_EDITION"), tmp);
+
+ // Release date
+ if (st.ReleaseDate != 0)
+ {
+ GetDateStrEx64(tmp, sizeof(tmp), st.ReleaseDate, NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_RELEASE"), tmp);
+ }
+
+ // Current system ID
+ UniFormat(tmp, sizeof(tmp), L"%I64u", st.SystemId);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SYSTEM_ID"), tmp);
+
+ // Expiration date of the current product license
+ if (st.SystemExpires == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateStrEx64(tmp, sizeof(tmp), st.SystemExpires, NULL);
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_EXPIRES"), tmp);
+
+ // Subscription (support) contract
+ if (st.NeedSubscription == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONEED"));
+ }
+ else
+ {
+ if (st.SubscriptionExpires == 0)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONE"));
+ }
+ else
+ {
+ wchar_t dtstr[MAX_PATH];
+
+ GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);
+
+ UniFormat(tmp, sizeof(tmp),
+ st.IsSubscriptionExpired ? _UU("SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED") : _UU("SM_LICENSE_STATUS_SUBSCRIPTION_VALID"),
+ dtstr);
+ }
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION"), tmp);
+
+ if (st.NeedSubscription == false && st.SubscriptionExpires != 0)
+ {
+ wchar_t dtstr[MAX_PATH];
+
+ GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), tmp);
+ }
+
+ if (st.NeedSubscription && st.SubscriptionExpires != 0)
+ {
+ wchar_t dtstr[MAX_PATH];
+
+ GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), dtstr);
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD"), tmp);
+ }
+
+ if (GetCapsBool(s->CapsList, "b_vpn3"))
+ {
+ // Maximum number of users
+ if (st.NumUserCreationLicense == INFINITE)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, st.NumUserCreationLicense);
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_USER"), tmp);
+ }
+
+ // Available number of concurrent client connections
+ if (st.NumClientConnectLicense == INFINITE)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, st.NumClientConnectLicense);
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_CLIENT"), tmp);
+
+ // Available number of concurrent Bridge connections
+ if (st.NumBridgeConnectLicense == INFINITE)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));
+ }
+ else
+ {
+ UniToStru(tmp, st.NumBridgeConnectLicense);
+ }
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_BRIDGE"), tmp);
+
+ // Availability of enterprise features
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_ENTERPRISE"),
+ st.AllowEnterpriseFunction ? _UU("SM_LICENSE_STATUS_ENTERPRISE_YES") : _UU("SM_LICENSE_STATUS_ENTERPRISE_NO"));
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ if (LvNum(hWnd, L_STATUS) >= 1)
+ {
+ LvAutoSize(hWnd, L_STATUS);
+ }
+
+ SmLicenseDlgUpdate(hWnd, s);
+}
+
+// License dialog control update
+void SmLicenseDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ bool b = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b = LvIsSingleSelected(hWnd, L_LIST);
+
+ SetEnable(hWnd, B_DEL, b);
+ SetEnable(hWnd, IDOK, b);
+}
+
+// License dialog
+UINT SmLicenseDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmLicenseDlgInit(hWnd, s);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ case L_STATUS:
+ SmLicenseDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+
+ if (i != INFINITE)
+ {
+ char *s = LvGetStrA(hWnd, L_LIST, i, 1);
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), _SS("LICENSE_SUPPORT_URL"), s);
+ ShellExecute(hWnd, "open", tmp, NULL, NULL, SW_SHOW);
+
+ Free(s);
+ }
+ }
+ break;
+
+ case B_OBTAIN:
+ ShellExecute(hWnd, "open", _SS("LICENSE_INFO_URL"), NULL, NULL, SW_SHOW);
+ break;
+
+ case B_ADD:
+ if (SmLicenseAdd(hWnd, s))
+ {
+ SmLicenseDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DEL:
+ if (IsEnable(hWnd, B_DEL))
+ {
+ UINT id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (id != 0)
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_LICENSE_DELETE_MSG")) == IDYES)
+ {
+ RPC_TEST t;
+
+ Zero(&t, sizeof(t));
+ t.IntValue = id;
+
+ if (CALL(hWnd, ScDelLicenseKey(s->Rpc, &t)))
+ {
+ SmLicenseDlgRefresh(hWnd, s);
+ }
+ }
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Add or Remove license
+void SmLicense(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_LICENSE, SmLicenseDlg, s);
+
+ FreeCapsList(s->CapsList);
+ s->CapsList = ScGetCapsEx(s->Rpc);
+}
+
+// Log storing procedure
+UINT SmSaveLogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_READ_LOG_FILE *p = (SM_READ_LOG_FILE *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, S_INFO, p->filepath);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case B_SAVE:
+ if (p->Buffer != NULL)
+ {
+ char filename[MAX_PATH];
+
+ Format(filename, sizeof(filename), "%s_%s", p->server_name, p->filepath);
+ ConvertSafeFileName(filename, sizeof(filename), filename);
+
+ if (wParam == IDOK)
+ {
+ // Open with an editor
+ char fullpath[MAX_PATH];
+
+ Format(fullpath, sizeof(fullpath), "%s\\%s",
+ MsGetMyTempDir(), filename);
+
+ if (DumpBuf(p->Buffer, fullpath) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("SM_READ_SAVE_TMP_FAILED"),
+ fullpath);
+ }
+ else
+ {
+ if (((UINT)ShellExecute(hWnd, "open", fullpath, NULL, NULL, SW_SHOWNORMAL)) > 32)
+ {
+ EndDialog(hWnd, true);
+ }
+ else
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_READ_SAVE_OPEN_ERROR"), fullpath);
+ }
+ }
+ }
+ else
+ {
+ // Save to a file
+ wchar_t def[MAX_PATH];
+ wchar_t *uni_path;
+
+ StrToUni(def, sizeof(def), filename);
+
+ uni_path = SaveDlg(hWnd, _UU("SM_READ_SAVE_DLG_FILTER"), _UU("SM_READ_SAVE_DLG_TITLE"),
+ def, L".log");
+
+ if (uni_path != NULL)
+ {
+ char path[MAX_PATH];
+
+ UniToStr(path, sizeof(path), uni_path);
+ Free(uni_path);
+
+ if (DumpBuf(p->Buffer, path) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_READ_SAVE_FAILED"));
+ }
+ else
+ {
+ EndDialog(hWnd, true);
+ }
+ }
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Download callback procedure
+bool SmReadLogFileProc(DOWNLOAD_PROGRESS *g)
+{
+ wchar_t tmp[MAX_SIZE];
+ char size1[64], size2[64];
+ SM_READ_LOG_FILE *p;
+ HWND hWnd;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return false;
+ }
+
+ p = (SM_READ_LOG_FILE *)g->Param;
+ hWnd = p->hWnd;
+
+ SetPos(hWnd, P_PROGRESS, g->ProgressPercent);
+
+ ToStrByte(size1, sizeof(size1), g->CurrentSize);
+ ToStrByte(size2, sizeof(size2), g->TotalSize);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_READ_LOG_FILE_INFO_2"), size2, size1);
+
+ SetText(hWnd, S_INFO, tmp);
+
+ DoEvents(hWnd);
+
+ return p->cancel_flag ? false : true;
+}
+
+// Log file download dialog procedure
+UINT SmReadLogFile(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_READ_LOG_FILE *p = (SM_READ_LOG_FILE *)param;
+ BUF *buf;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ p->hWnd = hWnd;
+ SetFont(hWnd, S_INFO, Font(11, true));
+ SetText(hWnd, S_INFO, _UU("SM_READ_LOG_FILE_INFO_1"));
+ DisableClose(hWnd);
+ FormatText(hWnd, S_INFO2, p->filepath);
+ SetRange(hWnd, P_PROGRESS, 0, 100);
+
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ buf = DownloadFileFromServer(p->s->Rpc, p->server_name, p->filepath, p->totalsize, SmReadLogFileProc, p);
+ if (buf == NULL)
+ {
+ if (p->cancel_flag == false)
+ {
+ // Download failure
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_READ_LOG_FILE_ERROR"));
+ }
+ EndDialog(hWnd, false);
+ }
+ else
+ {
+ // Download success
+ p->Buffer = buf;
+ Dialog(hWnd, D_SM_SAVE_LOG, SmSaveLogProc, p);
+ FreeBuf(buf);
+ EndDialog(hWnd, true);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ p->cancel_flag = true;
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Start the download of the log file
+void SmLogFileStartDownload(HWND hWnd, SM_SERVER *s, char *server_name, char *filepath, UINT totalsize)
+{
+ SM_READ_LOG_FILE p;
+ // Validate arguments
+ if (hWnd == NULL || server_name == NULL || filepath == NULL || totalsize == 0)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ p.filepath = filepath;
+ p.s = s;
+ p.server_name = server_name;
+ p.totalsize = totalsize;
+
+ Dialog(hWnd, D_SM_READ_LOG_FILE, SmReadLogFile, &p);
+}
+
+// Initialize the dialog
+void SmLogFileDlgInit(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_LOG2);
+
+ LvInit(hWnd, L_LIST);
+
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_LOG_FILE_COLUMN_1"), 250);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_LOG_FILE_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_LOG_FILE_COLUMN_3"), 130);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_LOG_FILE_COLUMN_4"), 110);
+
+ SmLogFileDlgRefresh(hWnd, p);
+}
+
+// Dialog content update
+void SmLogFileDlgRefresh(HWND hWnd, SM_SERVER *p)
+{
+ UINT i;
+ LVB *v;
+ RPC_ENUM_LOG_FILE t;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumLogFile(p->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_LOG_FILE_ITEM *e = &t.Items[i];
+ wchar_t tmp1[MAX_PATH], tmp2[128], tmp3[128], tmp4[MAX_HOST_NAME_LEN + 1];
+ char tmp[MAX_SIZE];
+
+ StrToUni(tmp1, sizeof(tmp1), e->FilePath);
+
+ ToStrByte(tmp, sizeof(tmp), e->FileSize);
+ StrToUni(tmp2, sizeof(tmp2), tmp);
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->UpdatedTime));
+
+ StrToUni(tmp4, sizeof(tmp4), e->ServerName);
+
+ LvInsertAdd(v, ICO_LOG2, (void *)e->FileSize, 4, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ LvInsertEndEx(v, hWnd, L_LIST, true);
+
+ if (t.NumItem != 0)
+ {
+ LvAutoSize(hWnd, L_LIST);
+ }
+
+ FreeRpcEnumLogFile(&t);
+
+ SmLogFileDlgUpdate(hWnd, p);
+}
+
+// Update the dialog control
+void SmLogFileDlgUpdate(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));
+}
+
+// Log file dialog procedure
+UINT SmLogFileDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_SERVER *p = (SM_SERVER *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmLogFileDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ UINT size = (UINT)LvGetParam(hWnd, L_LIST, i);
+ char *server_name;
+ char *filepath;
+
+ server_name = LvGetStrA(hWnd, L_LIST, i, 3);
+ filepath = LvGetStrA(hWnd, L_LIST, i, 0);
+ SmLogFileStartDownload(hWnd, p, server_name, filepath, size);
+ Free(filepath);
+ Free(server_name);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_REFRESH:
+ SmLogFileDlgRefresh(hWnd, p);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ SmLogFileDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Initialize the dialog
+void SmHubEditAcDlgInit(HWND hWnd, SM_EDIT_AC *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, R_IPV6, GetCapsBool(p->e->s->p->CapsList, "b_support_ipv6_ac"));
+
+ if (p->id == 0)
+ {
+ UINT i, v;
+
+ Check(hWnd, R_SINGLE, true);
+ Check(hWnd, R_PASS, true);
+ Check(hWnd, R_IPV4, true);
+
+ v = 0;
+
+ for (i = 0;i < LIST_NUM(p->e->AcList);i++)
+ {
+ AC *ac = LIST_DATA(p->e->AcList, i);
+
+ v = MAX(v, ac->Priority);
+ }
+
+ v += 100;
+
+ SetInt(hWnd, E_PRIORITY, v);
+ }
+ else
+ {
+ AC *ac = GetAc(p->e->AcList, p->id);
+
+ if (ac == NULL)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ Check(hWnd, R_SINGLE, ac->Masked == false);
+ Check(hWnd, R_MASKED, ac->Masked);
+ Check(hWnd, R_IPV4, IsIP4(&ac->IpAddress));
+ Check(hWnd, R_IPV6, IsIP6(&ac->IpAddress));
+
+ if (IsIP4(&ac->IpAddress))
+ {
+ IpSet(hWnd, E_IP, IPToUINT(&ac->IpAddress));
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ IPToStr(tmp, sizeof(tmp), &ac->IpAddress);
+ SetTextA(hWnd, E_IPV6, tmp);
+ }
+
+ if (ac->Masked)
+ {
+ if (IsIP4(&ac->IpAddress))
+ {
+ IpSet(hWnd, E_MASK, IPToUINT(&ac->SubnetMask));
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ MaskToStrEx(tmp, sizeof(tmp), &ac->SubnetMask, false);
+
+ if (IsNum(tmp))
+ {
+ StrCatLeft(tmp, sizeof(tmp), "/");
+ }
+
+ SetTextA(hWnd, E_MASKV6, tmp);
+ }
+ }
+
+ Check(hWnd, R_PASS, ac->Deny == false);
+ Check(hWnd, R_DENY, ac->Deny);
+ SetInt(hWnd, E_PRIORITY, ac->Priority);
+
+ Free(ac);
+ }
+
+ Focus(hWnd, E_IP);
+
+ SmHubEditAcDlgUpdate(hWnd, p);
+}
+
+// Dialog update
+void SmHubEditAcDlgUpdate(HWND hWnd, SM_EDIT_AC *p)
+{
+ bool b = true;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsChecked(hWnd, R_SINGLE))
+ {
+ if (IsChecked(hWnd, R_IPV6) == false)
+ {
+ Show(hWnd, E_IP);
+ Hide(hWnd, E_IPV6);
+
+ if (IpIsFilled(hWnd, E_IP) == false)
+ {
+ b = false;
+ }
+
+ if (IpGet(hWnd, E_IP) == 0 || IpGet(hWnd, E_IP) == 0xffffffff)
+ {
+ b = false;
+ }
+ }
+ else
+ {
+ Show(hWnd, E_IPV6);
+ Hide(hWnd, E_IP);
+
+ GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));
+
+ if (IsStrIPv6Address(tmp) == false)
+ {
+ b = false;
+ }
+ }
+
+ Hide(hWnd, S_MASK);
+ Hide(hWnd, E_MASK);
+ Hide(hWnd, E_MASKV6);
+ }
+ else
+ {
+ if (IsChecked(hWnd, R_IPV6) == false)
+ {
+ Show(hWnd, E_IP);
+ Hide(hWnd, E_IPV6);
+
+ if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)
+ {
+ b = false;
+ }
+
+ if (IpGet(hWnd, E_IP) == 0xffffffff)
+ {
+ b = false;
+ }
+ }
+ else
+ {
+ char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+
+ Show(hWnd, E_IPV6);
+ Hide(hWnd, E_IP);
+
+ GetTxtA(hWnd, E_IPV6, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_MASKV6, tmp2, sizeof(tmp2));
+
+ if (!(IsIpStr6(tmp1) && IsIpMask6(tmp2)))
+ {
+ b = false;
+ }
+ }
+
+ Show(hWnd, S_MASK);
+ SetShow(hWnd, E_MASK, !IsChecked(hWnd, R_IPV6));
+ SetShow(hWnd, E_MASKV6, IsChecked(hWnd, R_IPV6));
+ }
+
+ if (GetInt(hWnd, E_PRIORITY) == 0)
+ {
+ b = false;
+ }
+
+ SetIcon(hWnd, S_ICON, IsChecked(hWnd, R_PASS) ? ICO_INTERNET : ICO_INTERNET_X);
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+// OK button is clicked in the dialog
+void SmHubEditAcDlgOnOk(HWND hWnd, SM_EDIT_AC *p)
+{
+ AC ac;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&ac, sizeof(ac));
+ ac.Deny = IsChecked(hWnd, R_DENY);
+ ac.Priority = GetInt(hWnd, E_PRIORITY);
+
+ if (IsChecked(hWnd, R_IPV6) == false)
+ {
+ UINTToIP(&ac.IpAddress, IpGet(hWnd, E_IP));
+ }
+ else
+ {
+ GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));
+
+ StrToIP6(&ac.IpAddress, tmp);
+ }
+
+ ac.Masked = IsChecked(hWnd, R_MASKED);
+
+ if (ac.Masked)
+ {
+ if (IsChecked(hWnd, R_IPV6) == false)
+ {
+ UINTToIP(&ac.SubnetMask, IpGet(hWnd, E_MASK));
+ }
+ else
+ {
+ GetTxtA(hWnd, E_MASKV6, tmp, sizeof(tmp));
+
+ StrToMask6(&ac.SubnetMask, tmp);
+ }
+ }
+
+ if (p->id != 0)
+ {
+ SetAc(p->e->AcList, p->id, &ac);
+ }
+ else
+ {
+ AddAc(p->e->AcList, &ac);
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// AC edit dialog
+UINT SmHubEditAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_AC *p = (SM_EDIT_AC *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmHubEditAcDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_SINGLE:
+ case R_MASKED:
+ case E_IP:
+ case E_MASK:
+ case R_PASS:
+ case R_DENY:
+ case E_PRIORITY:
+ case R_IPV4:
+ case R_IPV6:
+ case E_IPV6:
+ case E_MASKV6:
+ SmHubEditAcDlgUpdate(hWnd, p);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case R_IPV4:
+ case R_IPV6:
+ case R_SINGLE:
+ case R_MASKED:
+ if (IsChecked(hWnd, R_IPV6) == false)
+ {
+ if (IpIsFilled(hWnd, E_IP))
+ {
+ Focus(hWnd, E_MASK);
+ }
+ else
+ {
+ Focus(hWnd, E_IP);
+ }
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));
+
+ if (IsStrIPv6Address(tmp))
+ {
+ FocusEx(hWnd, E_MASKV6);
+ }
+ else
+ {
+ FocusEx(hWnd, E_IPV6);
+ }
+ }
+ break;
+
+ case IDOK:
+ SmHubEditAcDlgOnOk(hWnd, p);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize the dialog
+void SmHubAcDlgInit(HWND hWnd, SM_EDIT_AC_LIST *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_INTERNET);
+
+ FormatText(hWnd, S_TITLE, p->s->HubName);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_AC_COLUMN_1"), 40);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_AC_COLUMN_2"), 80);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_AC_COLUMN_3"), 90);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_AC_COLUMN_4"), 170);
+
+ SmHubAcDlgRefresh(hWnd, p);
+}
+
+// Update the dialog control
+void SmHubAcDlgUpdate(HWND hWnd, SM_EDIT_AC_LIST *p)
+{
+ bool b;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ b = LvIsSingleSelected(hWnd, L_LIST);
+
+ SetEnable(hWnd, IDOK, b);
+ SetEnable(hWnd, B_DELETE, b);
+}
+
+// Dialog content update
+void SmHubAcDlgRefresh(HWND hWnd, SM_EDIT_AC_LIST *p)
+{
+ UINT i;
+ LVB *v;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(p->AcList);i++)
+ {
+ wchar_t tmp1[32], *tmp2, tmp3[MAX_SIZE], tmp4[32];
+ char *tmp_str;
+ AC *ac = LIST_DATA(p->AcList, i);
+
+ UniToStru(tmp1, ac->Id);
+ tmp2 = ac->Deny ? _UU("SM_AC_DENY") : _UU("SM_AC_PASS");
+ tmp_str = GenerateAcStr(ac);
+ StrToUni(tmp3, sizeof(tmp3), tmp_str);
+
+ Free(tmp_str);
+
+ UniToStru(tmp4, ac->Priority);
+
+ LvInsertAdd(v, ac->Deny ? ICO_INTERNET_X : ICO_INTERNET,
+ (void *)ac->Id, 4, tmp1, tmp4, tmp2, tmp3);
+ }
+
+ LvInsertEnd(v, hWnd, L_LIST);
+ LvSortEx(hWnd, L_LIST, 0, false, true);
+
+
+ SmHubAcDlgUpdate(hWnd, p);
+}
+
+// Access control list editing dialog
+UINT SmHubAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_EDIT_AC_LIST *p = (SM_EDIT_AC_LIST *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmHubAcDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ SM_EDIT_AC s;
+ Zero(&s, sizeof(s));
+
+ s.e = p;
+ s.id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (Dialog(hWnd, D_SM_AC, SmHubEditAcDlgProc, &s))
+ {
+ SmHubAcDlgRefresh(hWnd, p);
+ }
+ }
+ break;
+
+ case B_ADD:
+ if (IsEnable(hWnd, B_ADD))
+ {
+ SM_EDIT_AC s;
+ Zero(&s, sizeof(s));
+
+ s.e = p;
+
+ if (Dialog(hWnd, D_SM_AC, SmHubEditAcDlgProc, &s))
+ {
+ SmHubAcDlgRefresh(hWnd, p);
+ }
+ }
+ break;
+
+ case B_DELETE:
+ if (IsEnable(hWnd, B_DELETE))
+ {
+ UINT id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (DelAc(p->AcList, id))
+ {
+ SmHubAcDlgRefresh(hWnd, p);
+ }
+ }
+ break;
+
+ case B_SAVE:
+ if (IsEnable(hWnd, B_SAVE))
+ {
+ RPC_AC_LIST t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), p->s->HubName);
+ t.o = CloneAcList(p->AcList);
+
+ if (CALL(hWnd, ScSetAcList(p->s->p->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+
+ FreeRpcAcList(&t);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ SmHubAcDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Access control list editing
+void SmHubAc(HWND hWnd, SM_EDIT_HUB *s)
+{
+ SM_EDIT_AC_LIST p;
+ RPC_AC_LIST t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScGetAcList(s->p->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ p.s = s;
+ p.AcList = CloneAcList(t.o);
+
+ FreeRpcAcList(&t);
+
+ Dialog(hWnd, D_SM_AC_LIST, SmHubAcDlgProc, &p);
+
+ FreeAcList(p.AcList);
+}
+
+// Initialize the dialog
+void SmEditCrlDlgInit(HWND hWnd, SM_EDIT_CRL *c)
+{
+ // Validate arguments
+ if (hWnd == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (c->NewCrl == false)
+ {
+ RPC_CRL t;
+ CRL *crl;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);
+ t.Key = c->Key;
+
+ if (CALL(hWnd, ScGetCrl(c->s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ crl = t.Crl;
+
+ SmEditCrlDlgSetName(hWnd, crl->Name);
+ SmEditCrlDlgSetSerial(hWnd, crl->Serial);
+ SmEditCrlDlgSetHash(hWnd, crl->DigestMD5, crl->DigestSHA1);
+
+ FreeRpcCrl(&t);
+ }
+
+ SmEditCrlDlgUpdate(hWnd, c);
+}
+
+// Update the controls
+void SmEditCrlDlgUpdate(HWND hWnd, SM_EDIT_CRL *c)
+{
+ bool b = true;
+ // Validate arguments
+ if (hWnd == NULL || c == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, E_CN, IsChecked(hWnd, R_CN));
+ SetEnable(hWnd, E_O, IsChecked(hWnd, R_O));
+ SetEnable(hWnd, E_OU, IsChecked(hWnd, R_OU));
+ SetEnable(hWnd, E_C, IsChecked(hWnd, R_C));
+ SetEnable(hWnd, E_ST, IsChecked(hWnd, R_ST));
+ SetEnable(hWnd, E_L, IsChecked(hWnd, R_L));
+ SetEnable(hWnd, E_SERI, IsChecked(hWnd, R_SERI));
+ SetEnable(hWnd, E_MD5_HASH, IsChecked(hWnd, R_MD5_HASH));
+ SetEnable(hWnd, E_SHA1_HASH, IsChecked(hWnd, R_SHA1_HASH));
+
+ if (IsChecked(hWnd, R_CN))
+ {
+ if (IsEmpty(hWnd, E_CN))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_O))
+ {
+ if (IsEmpty(hWnd, E_O))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_OU))
+ {
+ if (IsEmpty(hWnd, E_OU))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_C))
+ {
+ if (IsEmpty(hWnd, E_C))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_ST))
+ {
+ if (IsEmpty(hWnd, E_ST))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_L))
+ {
+ if (IsEmpty(hWnd, E_L))
+ {
+ b = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_SERI))
+ {
+ char tmp[MAX_SIZE];
+ BUF *buf;
+
+ GetTxtA(hWnd, E_SERI, tmp, sizeof(tmp));
+ buf = StrToBin(tmp);
+
+ if (buf->Size == 0)
+ {
+ b = false;
+ }
+
+ FreeBuf(buf);
+ }
+
+ if (IsChecked(hWnd, R_MD5_HASH))
+ {
+ char tmp[MAX_SIZE];
+ BUF *buf;
+
+ GetTxtA(hWnd, E_MD5_HASH, tmp, sizeof(tmp));
+ buf = StrToBin(tmp);
+
+ if (buf->Size != MD5_SIZE)
+ {
+ b = false;
+ }
+
+ FreeBuf(buf);
+ }
+
+ if (IsChecked(hWnd, R_SHA1_HASH))
+ {
+ char tmp[MAX_SIZE];
+ BUF *buf;
+
+ GetTxtA(hWnd, E_SHA1_HASH, tmp, sizeof(tmp));
+ buf = StrToBin(tmp);
+
+ if (buf->Size != SHA1_SIZE)
+ {
+ b = false;
+ }
+
+ FreeBuf(buf);
+ }
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+// On click the OK button
+void SmEditCrlDlgOnOk(HWND hWnd, SM_EDIT_CRL *c)
+{
+ CRL *crl;
+ NAME *n;
+ RPC_CRL t;
+ bool empty = true;
+ // Validate arguments
+ if (hWnd == NULL || c == NULL)
+ {
+ return;
+ }
+
+ crl = ZeroMalloc(sizeof(CRL));
+ crl->Name = ZeroMalloc(sizeof(NAME));
+ n = crl->Name;
+
+ if (IsChecked(hWnd, R_CN))
+ {
+ n->CommonName = GetText(hWnd, E_CN);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_O))
+ {
+ n->Organization = GetText(hWnd, E_O);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_OU))
+ {
+ n->Unit = GetText(hWnd, E_OU);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_C))
+ {
+ n->Country = GetText(hWnd, E_C);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_ST))
+ {
+ n->State = GetText(hWnd, E_ST);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_L))
+ {
+ n->Local = GetText(hWnd, E_L);
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_SERI))
+ {
+ char tmp[MAX_SIZE];
+ BUF *b;
+
+ GetTxtA(hWnd, E_SERI, tmp, sizeof(tmp));
+ b = StrToBin(tmp);
+
+ if (b != NULL && b->Size >= 1)
+ {
+ crl->Serial = NewXSerial(b->Buf, b->Size);
+ }
+
+ FreeBuf(b);
+
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_MD5_HASH))
+ {
+ char tmp[MAX_SIZE];
+ BUF *b;
+
+ GetTxtA(hWnd, E_MD5_HASH, tmp, sizeof(tmp));
+ b = StrToBin(tmp);
+
+ if (b != NULL && b->Size == MD5_SIZE)
+ {
+ Copy(crl->DigestMD5, b->Buf, MD5_SIZE);
+ }
+
+ FreeBuf(b);
+
+ empty = false;
+ }
+
+ if (IsChecked(hWnd, R_SHA1_HASH))
+ {
+ char tmp[MAX_SIZE];
+ BUF *b;
+
+ GetTxtA(hWnd, E_SHA1_HASH, tmp, sizeof(tmp));
+ b = StrToBin(tmp);
+
+ if (b != NULL && b->Size == SHA1_SIZE)
+ {
+ Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);
+ }
+
+ FreeBuf(b);
+
+ empty = false;
+ }
+
+ if (empty)
+ {
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CRL_EMPTY_MSG")) == IDNO)
+ {
+ return;
+ }
+ }
+
+ if (c->NewCrl)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);
+ t.Crl = crl;
+
+ if (CALL(hWnd, ScAddCrl(c->s->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+
+ FreeRpcCrl(&t);
+ }
+ else
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);
+ t.Crl = crl;
+ t.Key = c->Key;
+
+ if (CALL(hWnd, ScSetCrl(c->s->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+
+ FreeRpcCrl(&t);
+ }
+}
+
+// Read the certificate
+void SmEditCrlDlgOnLoad(HWND hWnd, SM_EDIT_CRL *c)
+{
+ X *x;
+ // Validate arguments
+ if (hWnd == NULL || c == NULL)
+ {
+ return;
+ }
+
+ if (CmLoadXFromFileOrSecureCard(hWnd, &x))
+ {
+ UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];
+
+ SmEditCrlDlgSetName(hWnd, x->subject_name);
+ SmEditCrlDlgSetSerial(hWnd, x->serial);
+ GetXDigest(x, md5, false);
+ GetXDigest(x, sha1, true);
+ SmEditCrlDlgSetHash(hWnd, md5, sha1);
+
+ FreeX(x);
+
+ SmEditCrlDlgUpdate(hWnd, c);
+ }
+}
+
+// Set the hash information to the dialog
+void SmEditCrlDlgSetHash(HWND hWnd, UCHAR *hash_md5, UCHAR *hash_sha1)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (hash_md5 != NULL && IsZero(hash_md5, MD5_SIZE) == false)
+ {
+ Check(hWnd, R_MD5_HASH, true);
+ BinToStrEx(tmp, sizeof(tmp), hash_md5, MD5_SIZE);
+ SetTextA(hWnd, E_MD5_HASH, tmp);
+ }
+ else
+ {
+ Check(hWnd, R_MD5_HASH, false);
+ }
+
+ if (hash_sha1 != NULL && IsZero(hash_sha1, SHA1_SIZE) == false)
+ {
+ Check(hWnd, R_SHA1_HASH, true);
+ BinToStrEx(tmp, sizeof(tmp), hash_sha1, SHA1_SIZE);
+ SetTextA(hWnd, E_SHA1_HASH, tmp);
+ }
+ else
+ {
+ Check(hWnd, R_SHA1_HASH, false);
+ }
+}
+
+// Set the serial number to the dialog
+void SmEditCrlDlgSetSerial(HWND hWnd, X_SERIAL *serial)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || serial == NULL)
+ {
+ return;
+ }
+
+ BinToStrEx(tmp, sizeof(tmp), serial->data, serial->size);
+
+ Check(hWnd, R_SERI, true);
+
+ SetTextA(hWnd, E_SERI, tmp);
+}
+
+// Set the name situation to the dialog
+void SmEditCrlDlgSetName(HWND hWnd, NAME *name)
+{
+ // Validate arguments
+ if (hWnd == NULL || name == NULL)
+ {
+ return;
+ }
+
+ // CN
+ if (UniIsEmptyStr(name->CommonName))
+ {
+ Check(hWnd, R_CN, false);
+ }
+ else
+ {
+ Check(hWnd, R_CN, true);
+ SetText(hWnd, E_CN, name->CommonName);
+ }
+
+ // O
+ if (UniIsEmptyStr(name->Organization))
+ {
+ Check(hWnd, R_O, false);
+ }
+ else
+ {
+ Check(hWnd, R_O, true);
+ SetText(hWnd, E_O, name->Organization);
+ }
+
+ // OU
+ if (UniIsEmptyStr(name->Unit))
+ {
+ Check(hWnd, R_OU, false);
+ }
+ else
+ {
+ Check(hWnd, R_OU, true);
+ SetText(hWnd, E_OU, name->Unit);
+ }
+
+ // C
+ if (UniIsEmptyStr(name->Country))
+ {
+ Check(hWnd, R_C, false);
+ }
+ else
+ {
+ Check(hWnd, R_C, true);
+ SetText(hWnd, E_C, name->Country);
+ }
+
+ // ST
+ if (UniIsEmptyStr(name->State))
+ {
+ Check(hWnd, R_ST, false);
+ }
+ else
+ {
+ Check(hWnd, R_ST, true);
+ SetText(hWnd, E_ST, name->State);
+ }
+
+ // L
+ if (UniIsEmptyStr(name->Local))
+ {
+ Check(hWnd, R_L, false);
+ }
+ else
+ {
+ Check(hWnd, R_L, true);
+ SetText(hWnd, E_L, name->Local);
+ }
+}
+
+// CRL edit dialog procedure
+UINT SmEditCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_CRL *c = (SM_EDIT_CRL *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmEditCrlDlgInit(hWnd, c);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_CN:
+ case E_CN:
+ case R_O:
+ case E_O:
+ case R_OU:
+ case E_OU:
+ case R_C:
+ case E_C:
+ case R_ST:
+ case E_ST:
+ case R_L:
+ case E_L:
+ case R_SERI:
+ case E_SERI:
+ case R_MD5_HASH:
+ case E_MD5_HASH:
+ case R_SHA1_HASH:
+ case E_SHA1_HASH:
+ SmEditCrlDlgUpdate(hWnd, c);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case B_LOAD:
+ SmEditCrlDlgOnLoad(hWnd, c);
+ break;
+
+ case IDOK:
+ SmEditCrlDlgOnOk(hWnd, c);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_CN:
+ FocusEx(hWnd, E_CN);
+ break;
+
+ case R_O:
+ FocusEx(hWnd, E_O);
+ break;
+
+ case R_OU:
+ FocusEx(hWnd, E_OU);
+ break;
+
+ case R_C:
+ FocusEx(hWnd, E_C);
+ break;
+
+ case R_ST:
+ FocusEx(hWnd, E_ST);
+ break;
+
+ case R_L:
+ FocusEx(hWnd, E_L);
+ break;
+
+ case R_SERI:
+ FocusEx(hWnd, E_SERI);
+ break;
+
+ case R_MD5_HASH:
+ FocusEx(hWnd, E_MD5_HASH);
+ break;
+
+ case R_SHA1_HASH:
+ FocusEx(hWnd, E_SHA1_HASH);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize the dialog
+void SmCrlDlgInit(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_CERT_X);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_CRL_COLUMN_1"), 555);
+
+ SmCrlDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmCrlDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));
+ SetEnable(hWnd, B_DELETE, LvIsSingleSelected(hWnd, L_LIST));
+}
+
+// Content update
+void SmCrlDlgRefresh(HWND hWnd, SM_HUB *s)
+{
+ UINT i;
+ RPC_ENUM_CRL t;
+ LVB *v;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScEnumCrl(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_CRL_ITEM *e = &t.Items[i];
+ LvInsertAdd(v, ICO_CERT_X, (void *)e->Key, 1, e->CrlInfo);
+ }
+
+ LvInsertEndEx(v, hWnd, L_LIST, true);
+
+ if (t.NumItem >= 1)
+ {
+ LvAutoSize(hWnd, L_LIST);
+ }
+
+ FreeRpcEnumCrl(&t);
+
+ SmCrlDlgUpdate(hWnd, s);
+}
+
+// Certificate revocation list dialog procedure
+UINT SmCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_CRL c;
+ SM_HUB *s = (SM_HUB *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmCrlDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_ADD:
+ Zero(&c, sizeof(c));
+ c.NewCrl = true;
+ c.s = s;
+
+ if (Dialog(hWnd, D_SM_EDIT_CRL, SmEditCrlDlgProc, &c))
+ {
+ SmCrlDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DELETE:
+ if (IsEnable(hWnd, B_DELETE))
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CRL_DELETE_MSG")) == IDYES)
+ {
+ RPC_CRL t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Key = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (CALL(hWnd, ScDelCrl(s->Rpc, &t)))
+ {
+ SmCrlDlgRefresh(hWnd, s);
+ }
+
+ FreeRpcCrl(&t);
+ }
+ }
+ break;
+
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ SM_EDIT_CRL c;
+
+ Zero(&c, sizeof(c));
+ c.NewCrl = false;
+ c.s = s;
+ c.Key = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));
+
+ if (Dialog(hWnd, D_SM_EDIT_CRL, SmEditCrlDlgProc, &c))
+ {
+ SmCrlDlgRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ SmCrlDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Smart Card Manager
+void SmSecureManager(HWND hWnd)
+{
+ UINT id = SmGetCurrentSecureIdFromReg();
+
+ if (id == 0)
+ {
+ id = SmSelectSecureId(hWnd);
+ }
+
+ if (id == 0)
+ {
+ return;
+ }
+
+ CmSecureManager(hWnd, id);
+}
+
+// Initialize the dialog
+void SmSelectKeyPairDlgInit(HWND hWnd, SM_SECURE_KEYPAIR *k)
+{
+ SECURE_DEVICE *dev;
+ // Validate arguments
+ if (hWnd == NULL || k == NULL)
+ {
+ return;
+ }
+
+ dev = GetSecureDevice(k->Id);
+ if (dev != NULL)
+ {
+ FormatText(hWnd, S_INFO, dev->DeviceName);
+ }
+
+ LvInit(hWnd, L_CERT);
+ LvInsertColumn(hWnd, L_CERT, 0, _UU("SEC_MGR_COLUMN1"), 200);
+ LvInsertColumn(hWnd, L_CERT, 1, _UU("SEC_MGR_COLUMN2"), 110);
+
+ LvInit(hWnd, L_KEY);
+ LvInsertColumn(hWnd, L_KEY, 0, _UU("SEC_MGR_COLUMN1"), 200);
+ LvInsertColumn(hWnd, L_KEY, 1, _UU("SEC_MGR_COLUMN2"), 110);
+
+ SetEnable(hWnd, L_CERT, k->UseCert);
+ SetEnable(hWnd, B_BOLD1, k->UseCert);
+ SetEnable(hWnd, L_KEY, k->UseKey);
+ SetEnable(hWnd, B_BOLD2, k->UseKey);
+
+ SetFont(hWnd, B_BOLD1, Font(0, true));
+ SetFont(hWnd, B_BOLD2, Font(0, true));
+
+ SmSelectKeyPairDlgUpdate(hWnd, k);
+}
+
+// Update the dialog control
+void SmSelectKeyPairDlgUpdate(HWND hWnd, SM_SECURE_KEYPAIR *k)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || k == NULL)
+ {
+ return;
+ }
+
+ if (k->UseCert)
+ {
+ if (LvIsSingleSelected(hWnd, L_CERT) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ char *name = LvGetSelectedStrA(hWnd, L_CERT, 0);
+ if (name != NULL)
+ {
+ if (LvIsSingleSelected(hWnd, L_KEY) == false)
+ {
+ if ((k->Flag++) == 0)
+ {
+ LvSelect(hWnd, L_KEY, LvSearchStrA(hWnd, L_KEY, 0, name));
+ }
+ }
+ Free(name);
+ }
+ }
+ }
+
+ if (k->UseKey)
+ {
+ if (LvIsSingleSelected(hWnd, L_KEY) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ char *name = LvGetSelectedStrA(hWnd, L_KEY, 0);
+ if (name != NULL)
+ {
+ if (LvIsSingleSelected(hWnd, L_CERT) == false)
+ {
+ if ((k->Flag++) == 0)
+ {
+ LvSelect(hWnd, L_CERT, LvSearchStrA(hWnd, L_CERT, 0, name));
+ }
+ }
+ Free(name);
+ }
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Update the contents
+void SmSelectKeyPairDlgRefresh(HWND hWnd, SM_SECURE_KEYPAIR *k)
+{
+ bool ret;
+ LIST *o;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+ // Validate arguments
+ if (hWnd == NULL || k == NULL)
+ {
+ return;
+ }
+
+ ret = SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), k->Id, k->BitmapId);
+
+ if (ret == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ o = batch[0].EnumList;
+ if (o != NULL)
+ {
+ if (k->UseCert)
+ {
+ CmSecureManagerDlgPrintListEx(hWnd, L_CERT, o, SEC_X);
+ }
+
+ if (k->UseKey)
+ {
+ CmSecureManagerDlgPrintListEx(hWnd, L_KEY, o, SEC_K);
+ }
+
+ FreeEnumSecObject(o);
+ }
+
+ // Update the control
+ SmSelectKeyPairDlgUpdate(hWnd, k);
+}
+
+// Key pair import dialog procedure
+UINT SmSelectKeyPairDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_SECURE_KEYPAIR *k = (SM_SECURE_KEYPAIR *)param;
+ char *s1, *s2;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmSelectKeyPairDlgInit(hWnd, k);
+
+ SetTimer(hWnd, 1, 1, NULL);
+ SetTimer(hWnd, 2, 100, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ SmSelectKeyPairDlgRefresh(hWnd, k);
+ break;
+
+ case 2:
+ SmSelectKeyPairDlgUpdate(hWnd, k);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ s1 = LvGetSelectedStrA(hWnd, L_CERT, 0);
+ s2 = LvGetSelectedStrA(hWnd, L_KEY, 0);
+ if (k->UseCert)
+ {
+ StrCpy(k->CertName, sizeof(k->CertName), s1);
+ }
+ if (k->UseKey)
+ {
+ StrCpy(k->KeyName, sizeof(k->KeyName), s2);
+ }
+ Free(s1);
+ Free(s2);
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_CERT:
+ case L_KEY:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmSelectKeyPairDlgUpdate(hWnd, k);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Read a key pair from the smart card
+bool SmSelectKeyPair(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size)
+{
+ return SmSelectKeyPairEx(hWnd, cert_name, cert_name_size, key_name, key_name_size, 0);
+}
+bool SmSelectKeyPairEx(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size, UINT bitmap_id)
+{
+ SM_SECURE_KEYPAIR p;
+ // Validate arguments
+ if (hWnd == NULL || (cert_name == NULL && key_name == NULL))
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.Id = SmGetCurrentSecureId(hWnd);
+ if (p.Id == 0)
+ {
+ return false;
+ }
+
+ p.UseCert = (cert_name == NULL) ? false : true;
+ p.UseKey = (key_name == NULL) ? false : true;
+ p.BitmapId = bitmap_id;
+
+ if (Dialog(hWnd, D_SM_SELECT_KEYPAIR, SmSelectKeyPairDlg, &p) == false)
+ {
+ return false;
+ }
+
+ if (p.UseCert)
+ {
+ StrCpy(cert_name, cert_name_size, p.CertName);
+ }
+ if (p.UseKey)
+ {
+ StrCpy(key_name, key_name_size, p.KeyName);
+ }
+
+ return true;
+}
+
+// Make the user select the smart card number
+UINT SmSelectSecureId(HWND hWnd)
+{
+ UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");
+ UINT ret;
+
+ if (id != 0 && CheckSecureDeviceId(id) == false)
+ {
+ id = 0;
+ }
+
+ ret = CmSelectSecure(hWnd, id);
+ if (ret == 0)
+ {
+ return 0;
+ }
+
+ SmWriteSelectSecureIdReg(ret);
+
+ return ret;
+}
+
+// Write the current smart card number to the registry
+void SmWriteSelectSecureIdReg(UINT id)
+{
+ MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId", id);
+}
+
+// Get the current smart card number
+UINT SmGetCurrentSecureId(HWND hWnd)
+{
+ // Load the current settings
+ UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");
+
+ // Check whether it's valid
+ if (id == 0 || CheckSecureDeviceId(id) == false)
+ {
+ // Select a smart card device number if it's invalid
+ id = SmSelectSecureId(hWnd);
+ }
+
+ return id;
+}
+
+// Get the current smart card number from the registry
+UINT SmGetCurrentSecureIdFromReg()
+{
+ // Load the current settings
+ UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");
+
+ // Check whether normal
+ if (id == 0 || CheckSecureDeviceId(id) == false)
+ {
+ id = 0;
+ }
+
+ return id;
+}
+
+// Get whether the specified L3 switch started
+bool SmL3IsSwActive(SM_SERVER *s, char *name)
+{
+ bool ret = false;
+ UINT i;
+ RPC_ENUM_L3SW t;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (ScEnumL3Switch(s->Rpc, &t) == ERR_NO_ERROR)
+ {
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *e = &t.Items[i];
+ if (StrCmpi(e->Name, name) == 0)
+ {
+ if (e->Active)
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ FreeRpcEnumL3Sw(&t);
+ }
+
+ return ret;
+}
+
+// Initialize the dialog
+void SmL3SwTableDlgInit(HWND hWnd, SM_L3SW *w)
+{
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ SmL3SwTableDlgUpdate(hWnd, w);
+}
+
+// Update the control
+void SmL3SwTableDlgUpdate(HWND hWnd, SM_L3SW *w)
+{
+ bool b = true;
+ UINT ip;
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ if (IpIsFilled(hWnd, E_NETWORK) == false ||
+ IpIsFilled(hWnd, E_MASK) == false ||
+ IpIsFilled(hWnd, E_GATEWAY) == false)
+ {
+ b = false;
+ }
+
+ ip = IpGet(hWnd, E_GATEWAY);
+ if (ip == 0 || ip == 0xffffffff)
+ {
+ b = false;
+ }
+
+ if (GetInt(hWnd, E_METRIC) == 0)
+ {
+ b = false;
+ }
+
+ if (IsNetworkAddress32(IpGet(hWnd, E_NETWORK), IpGet(hWnd, E_MASK)) == false)
+ {
+ b = false;
+ }
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+UINT SmL3SwTableDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_L3SW *w = (SM_L3SW *)param;
+ RPC_L3TABLE t;
+
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmL3SwTableDlgInit(hWnd, w);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_NETWORK:
+ case E_MASK:
+ case E_GATEWAY:
+ case E_METRIC:
+ SmL3SwTableDlgUpdate(hWnd, w);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+ t.NetworkAddress = IpGet(hWnd, E_NETWORK);
+ t.SubnetMask = IpGet(hWnd, E_MASK);
+ t.GatewayAddress = IpGet(hWnd, E_GATEWAY);
+ t.Metric = GetInt(hWnd, E_METRIC);
+
+ if (CALL(hWnd, ScAddL3Table(w->s->Rpc, &t)))
+ {
+ EndDialog(hWnd, 1);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize the dialog
+void SmL3SwIfDlgInit(HWND hWnd, SM_L3SW *w)
+{
+ RPC_ENUM_HUB t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ if (CALL(hWnd, ScEnumHub(w->s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ CbReset(hWnd, E_HUBNAME);
+ CbSetHeight(hWnd, E_HUBNAME, 18);
+
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+
+ if (e->HubType != HUB_TYPE_FARM_DYNAMIC)
+ {
+ CbAddStrA(hWnd, E_HUBNAME, e->HubName, 0);
+ }
+ }
+
+ FreeRpcEnumHub(&t);
+
+ SetTextA(hWnd, E_HUBNAME, "");
+
+ SmL3SwIfDlgUpdate(hWnd, w);
+}
+
+// Update the control
+void SmL3SwIfDlgUpdate(HWND hWnd, SM_L3SW *w)
+{
+ bool b = true;
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ if (IsEmpty(hWnd, E_HUBNAME))
+ {
+ b = false;
+ }
+
+ if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)
+ {
+ b = false;
+ }
+
+ if (IpGet(hWnd, E_IP) == 0 || IpGet(hWnd, E_IP) == 0xffffffff)
+ {
+ b = false;
+ }
+
+ if (IsSubnetMask32(IpGet(hWnd, E_MASK)) == false)
+ {
+ b = false;
+ }
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+// Dialog for adding a virtual interface
+UINT SmL3SwIfDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_L3SW *w = (SM_L3SW *)param;
+ char *hubname;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmL3SwIfDlgInit(hWnd, w);
+
+ SetTimer(hWnd, 1, 250, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ SmL3SwIfDlgUpdate(hWnd, w);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_HUBNAME:
+ case E_IP:
+ case E_MASK:
+ SmL3SwIfDlgUpdate(hWnd, w);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ hubname = GetTextA(hWnd, E_HUBNAME);
+ if (hubname != NULL)
+ {
+ RPC_L3IF t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ t.IpAddress = IpGet(hWnd, E_IP);
+ t.SubnetMask = IpGet(hWnd, E_MASK);
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+
+ if (CALL(hWnd, ScAddL3If(w->s->Rpc, &t)))
+ {
+ EndDialog(hWnd, 1);
+ }
+
+ Free(hubname);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize
+void SmL3SwDlgInit(HWND hWnd, SM_L3SW *w)
+{
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SWITCH_OFFLINE);
+
+ FormatText(hWnd, 0, w->SwitchName);
+
+ SetFont(hWnd, S_BOLD1, Font(0, true));
+ SetFont(hWnd, S_BOLD2, Font(0, true));
+
+ LvInit(hWnd, L_IF);
+ LvInsertColumn(hWnd, L_IF, 0, _UU("SM_L3_SW_IF_COLUMN1"), 150);
+ LvInsertColumn(hWnd, L_IF, 1, _UU("SM_L3_SW_IF_COLUMN2"), 150);
+ LvInsertColumn(hWnd, L_IF, 2, _UU("SM_L3_SW_IF_COLUMN3"), 180);
+
+ LvInit(hWnd, L_TABLE);
+ LvInsertColumn(hWnd, L_TABLE, 0, _UU("SM_L3_SW_TABLE_COLUMN1"), 130);
+ LvInsertColumn(hWnd, L_TABLE, 1, _UU("SM_L3_SW_TABLE_COLUMN2"), 130);
+ LvInsertColumn(hWnd, L_TABLE, 2, _UU("SM_L3_SW_TABLE_COLUMN3"), 130);
+ LvInsertColumn(hWnd, L_TABLE, 3, _UU("SM_L3_SW_TABLE_COLUMN4"), 100);
+
+ w->Enable = SmL3IsSwActive(w->s, w->SwitchName) ? false : true;
+
+ SmL3SwDlgRefresh(hWnd, w);
+}
+
+// Update the control
+void SmL3SwDlgUpdate(HWND hWnd, SM_L3SW *w)
+{
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, B_ADD_IF, w->s->ServerAdminMode && w->Enable);
+ SetEnable(hWnd, B_ADD_TABLE, w->s->ServerAdminMode && w->Enable);
+ SetEnable(hWnd, B_DEL_IF, LvIsSingleSelected(hWnd, L_IF) && w->s->ServerAdminMode && w->Enable);
+ SetEnable(hWnd, B_DEL_TABLE, LvIsSingleSelected(hWnd, L_TABLE) && w->s->ServerAdminMode && w->Enable);
+ SetEnable(hWnd, B_START, w->s->ServerAdminMode && w->Enable);
+ SetEnable(hWnd, B_STOP, w->s->ServerAdminMode && (w->Enable == false));
+}
+
+// Content update
+void SmL3SwDlgRefresh(HWND hWnd, SM_L3SW *w)
+{
+ UINT i;
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ // Virtual interface list
+ {
+ RPC_ENUM_L3IF t;
+ LVB *v;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+
+ if (CALL(hWnd, ScEnumL3If(w->s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_L3IF *e = &t.Items[i];
+
+ IPToUniStr32(tmp1, sizeof(tmp1), e->IpAddress);
+ IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);
+ StrToUni(tmp3, sizeof(tmp3), e->HubName);
+
+ LvInsertAdd(v, ICO_NIC_ONLINE, NULL, 3, tmp1, tmp2, tmp3);
+ }
+
+ LvReset(hWnd, L_IF);
+
+ LvInsertEnd(v, hWnd, L_IF);
+
+ FreeRpcEnumL3If(&t);
+ }
+
+ // Routing Table Entry List
+ {
+ RPC_ENUM_L3TABLE t;
+ LVB *v;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+
+ if (CALL(hWnd, ScEnumL3Table(w->s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_L3TABLE *e = &t.Items[i];
+
+ IPToUniStr32(tmp1, sizeof(tmp1), e->NetworkAddress);
+ IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);
+ IPToUniStr32(tmp3, sizeof(tmp3), e->GatewayAddress);
+ UniToStru(tmp4, e->Metric);
+
+ LvInsertAdd(v, ICO_PROTOCOL, NULL, 4, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ LvReset(hWnd, L_TABLE);
+
+ LvInsertEnd(v, hWnd, L_TABLE);
+
+ FreeRpcEnumL3Table(&t);
+ }
+
+ SmL3SwDlgUpdate(hWnd, w);
+}
+
+// Edit dialog of L3 switch
+UINT SmL3SwDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_L3SW *w = (SM_L3SW *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmL3SwDlgInit(hWnd, w);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+ w->Enable = SmL3IsSwActive(w->s, w->SwitchName) ? false : true;
+ SmL3SwDlgUpdate(hWnd, w);
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_START:
+ if (IsEnable(hWnd, B_START))
+ {
+ RPC_L3SW t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+
+ if (CALL(hWnd, ScStartL3Switch(w->s->Rpc, &t)))
+ {
+ SmL3SwDlgUpdate(hWnd, w);
+ }
+ }
+ break;
+
+ case B_STOP:
+ if (IsEnable(hWnd, B_STOP))
+ {
+ RPC_L3SW t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+
+ if (CALL(hWnd, ScStopL3Switch(w->s->Rpc, &t)))
+ {
+ SmL3SwDlgUpdate(hWnd, w);
+ }
+ }
+ break;
+
+ case B_ADD_IF:
+ if (Dialog(hWnd, D_SM_L3_SW_IF, SmL3SwIfDlg, w))
+ {
+ SmL3SwDlgRefresh(hWnd, w);
+ }
+ break;
+
+ case B_DEL_IF:
+ if (LvIsSingleSelected(hWnd, L_IF))
+ {
+ RPC_L3IF t;
+ char *tmp1, *tmp2, *tmp3;
+
+ tmp1 = LvGetSelectedStrA(hWnd, L_IF, 0);
+ tmp2 = LvGetSelectedStrA(hWnd, L_IF, 1);
+ tmp3 = LvGetSelectedStrA(hWnd, L_IF, 2);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+ t.IpAddress = StrToIP32(tmp1);
+ t.SubnetMask = StrToIP32(tmp2);
+ StrCpy(t.HubName, sizeof(t.HubName), tmp3);
+
+ if (CALL(hWnd, ScDelL3If(w->s->Rpc, &t)))
+ {
+ SmL3SwDlgRefresh(hWnd, w);
+ }
+
+ Free(tmp1);
+ Free(tmp2);
+ Free(tmp3);
+ }
+ break;
+
+ case B_ADD_TABLE:
+ if (Dialog(hWnd, D_SM_L3_SW_TABLE, SmL3SwTableDlg, w))
+ {
+ SmL3SwDlgRefresh(hWnd, w);
+ }
+ break;
+
+ case B_DEL_TABLE:
+ if (LvIsSingleSelected(hWnd, L_TABLE))
+ {
+ RPC_L3TABLE t;
+ char *tmp1, *tmp2, *tmp3, *tmp4;
+
+ tmp1 = LvGetSelectedStrA(hWnd, L_TABLE, 0);
+ tmp2 = LvGetSelectedStrA(hWnd, L_TABLE, 1);
+ tmp3 = LvGetSelectedStrA(hWnd, L_TABLE, 2);
+ tmp4 = LvGetSelectedStrA(hWnd, L_TABLE, 3);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), w->SwitchName);
+ t.NetworkAddress = StrToIP32(tmp1);
+ t.SubnetMask = StrToIP32(tmp2);
+ t.GatewayAddress = StrToIP32(tmp3);
+ t.Metric = ToInt(tmp4);
+
+ if (CALL(hWnd, ScDelL3Table(w->s->Rpc, &t)))
+ {
+ SmL3SwDlgRefresh(hWnd, w);
+ }
+
+ Free(tmp1);
+ Free(tmp2);
+ Free(tmp3);
+ Free(tmp4);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_IF:
+ case L_TABLE:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmL3SwDlgUpdate(hWnd, w);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Update the control
+void SmL3AddDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ char *tmp;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ tmp = GetTextA(hWnd, E_NAME);
+
+ SetEnable(hWnd, IDOK, IsEmptyStr(tmp) == false && IsSafeStr(tmp));
+
+ Free(tmp);
+}
+
+// The dialog box to create a new L3 switch
+UINT SmL3AddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *s = (SM_SERVER *)param;
+ RPC_L3SW t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ LimitText(hWnd, E_NAME, MAX_HUBNAME_LEN);
+ SmL3AddDlgUpdate(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_NAME:
+ SmL3AddDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ Zero(&t, sizeof(t));
+ GetTxtA(hWnd, E_NAME, t.Name, sizeof(t.Name));
+ if (CALL(hWnd, ScAddL3Switch(s->Rpc, &t)))
+ {
+ EndDialog(hWnd, 1);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize the dialog
+void SmL3DlgInit(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetFont(hWnd, S_BOLD, Font(0, true));
+
+ SetIcon(hWnd, 0, ICO_SWITCH);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_L3_SW_COLUMN1"), 150);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_L3_SW_COLUMN2"), 120);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_L3_SW_COLUMN3"), 100);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_L3_SW_COLUMN4"), 100);
+
+ SmL3DlgRefresh(hWnd, s);
+}
+
+// Update the dialog control
+void SmL3DlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ bool b = false;
+ bool active = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSingleSelected(hWnd, L_LIST))
+ {
+ wchar_t *tmp;
+ UINT i;
+ b = true;
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ tmp = LvGetStr(hWnd, L_LIST, i, 1);
+ if (UniStrCmpi(tmp, _UU("SM_L3_SW_ST_F_F")) != 0)
+ {
+ active = true;
+ }
+ Free(tmp);
+ }
+ }
+
+ SetEnable(hWnd, B_START, b && (active == false));
+ SetEnable(hWnd, B_STOP, b && (active != false));
+ SetEnable(hWnd, IDOK, b);
+ SetEnable(hWnd, B_DELETE, b);
+}
+
+// Dialog content update
+void SmL3DlgRefresh(HWND hWnd, SM_SERVER *s)
+{
+ RPC_ENUM_L3SW t;
+ UINT i;
+ LVB *v;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumL3Switch(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ v = LvInsertStart();
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_L3SW_ITEM *e = &t.Items[i];
+ wchar_t tmp1[MAX_SIZE], *tmp2, tmp3[64], tmp4[64];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ if (e->Active == false)
+ {
+ tmp2 = _UU("SM_L3_SW_ST_F_F");
+ }
+ else if (e->Online == false)
+ {
+ tmp2 = _UU("SM_L3_SW_ST_T_F");
+ }
+ else
+ {
+ tmp2 = _UU("SM_L3_SW_ST_T_T");
+ }
+ UniToStru(tmp3, e->NumInterfaces);
+ UniToStru(tmp4, e->NumTables);
+
+ LvInsertAdd(v, e->Active ? ICO_SWITCH : ICO_SWITCH_OFFLINE, NULL,
+ 4, tmp1, tmp2, tmp3, tmp4);
+ }
+
+ LvInsertEnd(v, hWnd, L_LIST);
+
+ FreeRpcEnumL3Sw(&t);
+
+ SmL3DlgUpdate(hWnd, s);
+}
+
+// L3 dialog procedure
+UINT SmL3Dlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_SERVER *s = (SM_SERVER *)param;
+ RPC_L3SW t;
+ char *name;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmL3DlgInit(hWnd, s);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+ SmL3DlgRefresh(hWnd, s);
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_ADD:
+ // Add
+ if (Dialog(hWnd, D_SM_L3_ADD, SmL3AddDlg, s))
+ {
+ SmL3DlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_START:
+ // Operation start
+ name = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (name != NULL)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (CALL(hWnd, ScStartL3Switch(s->Rpc, &t)))
+ {
+ SmL3DlgRefresh(hWnd, s);
+ }
+
+ Free(name);
+ }
+ break;
+
+ case B_STOP:
+ // Operation stop
+ name = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (name != NULL)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (CALL(hWnd, ScStopL3Switch(s->Rpc, &t)))
+ {
+ SmL3DlgRefresh(hWnd, s);
+ }
+
+ Free(name);
+ }
+ break;
+
+ case IDOK:
+ // Edit
+ if (IsEnable(hWnd, IDOK))
+ {
+ name = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (name != NULL)
+ {
+ SM_L3SW w;
+ Zero(&w, sizeof(w));
+ w.s = s;
+ w.SwitchName = name;
+
+ Dialog(hWnd, D_SM_L3_SW, SmL3SwDlg, &w);
+
+ Free(name);
+ }
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ name = LvGetSelectedStrA(hWnd, L_LIST, 0);
+ if (name != NULL)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_L3_SW_DEL_MSG"), name) == IDYES)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (CALL(hWnd, ScDelL3Switch(s->Rpc, &t)))
+ {
+ SmL3DlgRefresh(hWnd, s);
+ }
+ }
+
+ Free(name);
+ }
+ break;
+
+ case IDCANCEL:
+ // Close
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmL3DlgUpdate(hWnd, s);
+ break;
+
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// L3 dialog
+void SmL3(HWND hWnd, SM_SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_L3, SmL3Dlg, s);
+}
+
+// Dialog for management option value
+UINT SmHubAdminOptionValueDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_AO *a = (SM_EDIT_AO *)param;
+ UINT i;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ CbReset(hWnd, C_NAME);
+ for (i = 0;i < a->DefaultOptions.NumItem;i++)
+ {
+ wchar_t tmp[MAX_PATH];
+ StrToUni(tmp, sizeof(tmp), a->DefaultOptions.Items[i].Name);
+ CbAddStr(hWnd, C_NAME, tmp, 0);
+ }
+ if (a->NewMode == false)
+ {
+ char tmp[MAX_SIZE];
+
+ SetTextA(hWnd, C_NAME, a->Name);
+ ToStr(tmp, a->Value);
+
+ SetTextA(hWnd, E_VALUE, tmp);
+ }
+ else
+ {
+ SetTextA(hWnd, C_NAME, "");
+ }
+ SmHubAdminOptionValueDlgUpdate(hWnd, a);
+ if (a->NewMode == false)
+ {
+ FocusEx(hWnd, E_VALUE);
+ Disable(hWnd, C_NAME);
+ }
+ else
+ {
+ FocusEx(hWnd, C_NAME);
+ }
+
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+
+ case WM_TIMER:
+ if (IsEnable(hWnd, 0))
+ {
+ SmHubAdminOptionValueDlgUpdate(hWnd, a);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (a->NewMode)
+ {
+ GetTxtA(hWnd, C_NAME, a->Name, sizeof(a->Name));
+ }
+
+ GetTxtA(hWnd, E_VALUE, tmp, sizeof(tmp));
+ a->Value = ToInt(tmp);
+
+ Trim(a->Name);
+
+ if (StartWith(a->Name, "no") || StartWith(a->Name, "allow") || StartWith(a->Name, "deny")
+ || StartWith(a->Name, "filter") || StartWith(a->Name, "fix") || StartWith(a->Name, "force")
+ || StartWith(a->Name, "use") || StartWith(a->Name, "b_") || StartWith(a->Name, "is")
+ || StartWith(a->Name, "manage") || StartWith(a->Name, "yield")
+ || StartWith(a->Name, "permit") || StartWith(a->Name, "yes") || StartWith(a->Name, "ok")
+ || StartWith(a->Name, "do") || StartWith(a->Name, "only") || StartWith(a->Name, "disable"))
+ {
+ if (StrCmpi(tmp, "0") != 0 && StrCmpi(tmp, "1") != 0)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_TRUE_OR_FALSE"));
+ FocusEx(hWnd, E_VALUE);
+ break;
+ }
+ }
+
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+
+ SmHubAdminOptionValueDlgUpdate(hWnd, a);
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Update the dialog controls for management option value
+void SmHubAdminOptionValueDlgUpdate(HWND hWnd, SM_EDIT_AO *a)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, C_NAME, tmp, sizeof(tmp));
+
+ SetEnable(hWnd, IDOK, IsEmpty(hWnd, C_NAME) == false && IsEmpty(hWnd, E_VALUE) == false &&
+ IsSafeStr(tmp));
+}
+
+// Initialize
+void SmHubAdminOptionDlgInit(HWND hWnd, SM_EDIT_AO *a)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_USER_ADMIN);
+
+ if (a->e->p->ServerAdminMode)
+ {
+ a->CanChange = true;
+ }
+ else
+ {
+ if (a->ExtOption == false)
+ {
+ for (i = 0;i < a->CurrentOptions.NumItem;i++)
+ {
+ if (StrCmpi(a->CurrentOptions.Items[i].Name, "allow_hub_admin_change_option") == 0)
+ {
+ if (a->CurrentOptions.Items[i].Value != 0)
+ {
+ a->CanChange = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ a->CanChange = true;
+ }
+ }
+
+ FormatText(hWnd, S_INFO, a->e->HubName);
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_AO_COLUMN_1"), 260);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_AO_COLUMN_2"), 100);
+
+ for (i = 0;i < a->CurrentOptions.NumItem;i++)
+ {
+ ADMIN_OPTION *e = &a->CurrentOptions.Items[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ UniToStru(tmp2, e->Value);
+
+ LvInsert(hWnd, L_LIST, ICO_LOG, NULL, 2, tmp1, tmp2);
+
+ }
+
+ if (a->ExtOption)
+ {
+ SetIcon(hWnd, S_ICON, ICO_LINK2);
+ SetIcon(hWnd, 0, ICO_LINK2);
+
+ SetText(hWnd, 0, _UU("SM_HUBEXT_OPTION_TITLE"));
+ SetText(hWnd, S_STATIC1, _UU("SM_HUBEXT_OPTION_STATIC1"));
+ SetText(hWnd, S_STATIC2, _UU("SM_HUBEXT_OPTION_STATIC2"));
+ }
+
+ // Update the control
+ SmHubAdminOptionDlgUpdate(hWnd, a);
+}
+
+// Update the control
+void SmHubAdminOptionDlgUpdate(HWND hWnd, SM_EDIT_AO *a)
+{
+ bool b = false;
+ wchar_t *helpstr;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ helpstr = _UU("HUB_AO_CLICK");
+
+ SetEnable(hWnd, IDOK, a->CanChange);
+ SetEnable(hWnd, B_ADD, a->CanChange);
+ SetEnable(hWnd, B_EDIT, a->CanChange && (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false));
+
+ if (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false)
+ {
+ UINT i;
+ i = LvGetSelected(hWnd, L_LIST);
+
+ if (a->CanChange)
+ {
+
+ b = true;
+
+ if (i != INFINITE)
+ {
+ char *name = LvGetStrA(hWnd, L_LIST, i, 0);
+ if (name != NULL)
+ {
+ UINT j;
+
+ for (j = 0;j < a->DefaultOptions.NumItem;j++)
+ {
+ if (StrCmpi(a->DefaultOptions.Items[j].Name, name) == 0)
+ {
+ b = false;
+ }
+ }
+ Free(name);
+ }
+ }
+ }
+
+ if (i != INFINITE)
+ {
+ char *name = LvGetStrA(hWnd, L_LIST, i, 0);
+ if (name != NULL)
+ {
+ helpstr = GetHubAdminOptionHelpString(name);
+ }
+ Free(name);
+ }
+ }
+ SetEnable(hWnd, B_DELETE, b);
+
+ SetText(hWnd, E_HELP, helpstr);
+}
+
+// Save
+void SmHubAdminOptionDlgOk(HWND hWnd, SM_EDIT_AO *a)
+{
+ UINT i, num;
+ RPC_ADMIN_OPTION t;
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ num = LvNum(hWnd, L_LIST);
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), a->e->HubName);
+ t.NumItem = num;
+ t.Items = ZeroMalloc(sizeof(ADMIN_OPTION) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ char *name = LvGetStrA(hWnd, L_LIST, i, 0);
+ char *s_value = LvGetStrA(hWnd, L_LIST, i, 1);
+ ADMIN_OPTION *a = &t.Items[i];
+
+ StrCpy(a->Name, sizeof(a->Name), name);
+ a->Value = ToInt(s_value);
+
+ Free(name);
+ Free(s_value);
+ }
+
+ if (a->ExtOption == false)
+ {
+ if (CALL(hWnd, ScSetHubAdminOptions(a->e->p->Rpc, &t)))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_AO_SET_OK"));
+ EndDialog(hWnd, true);
+ }
+ }
+ else
+ {
+ if (CALL(hWnd, ScSetHubExtOptions(a->e->p->Rpc, &t)))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_EXT_OPTION_SET_OK"));
+ EndDialog(hWnd, true);
+ }
+ }
+
+ FreeRpcAdminOption(&t);
+}
+
+// Virtual HUB Management Options dialog
+UINT SmHubAdminOptionDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_AO *a = (SM_EDIT_AO *)param;
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmHubAdminOptionDlgInit(hWnd, a);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_ADD:
+ a->NewMode = true;
+ StrCpy(a->Name, sizeof(a->Name), "");
+ a->Value = 0;
+ if (Dialog(hWnd, D_SM_AO_VALUE, SmHubAdminOptionValueDlg,
+ a))
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ StrToUni(tmp1, sizeof(tmp1), a->Name);
+ UniToStru(tmp2, a->Value);
+
+ LvInsert(hWnd, L_LIST, ICO_LOG, NULL, 2, tmp1, tmp2);
+ }
+ break;
+
+ case B_EDIT:
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE && a->CanChange)
+ {
+ char *name, *value;
+ name = LvGetStrA(hWnd, L_LIST, i, 0);
+ value = LvGetStrA(hWnd, L_LIST, i, 1);
+ a->NewMode = false;
+ StrCpy(a->Name, sizeof(a->Name), name);
+ a->Value = ToInt(value);
+
+ if (Dialog(hWnd, D_SM_AO_VALUE, SmHubAdminOptionValueDlg,
+ a))
+ {
+ char tmp[MAX_PATH];
+ ToStr(tmp, a->Value);
+ LvSetItemA(hWnd, L_LIST, i, 1, tmp);
+ }
+
+ Free(name);
+ Free(value);
+ }
+ break;
+
+ case B_DELETE:
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ LvDeleteItem(hWnd, L_LIST, i);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case IDOK:
+ SmHubAdminOptionDlgOk(hWnd, a);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmHubAdminOptionDlgUpdate(hWnd, a);
+ break;
+
+ case NM_DBLCLK:
+ Command(hWnd, B_EDIT);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Virtual HUB extended options
+void SmHubExtOption(HWND hWnd, SM_EDIT_HUB *e)
+{
+ SM_EDIT_AO a;
+ // Validate arguments
+ if (hWnd == NULL || e == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+ a.e = e;
+ a.ExtOption = true;
+
+ StrCpy(a.CurrentOptions.HubName, sizeof(a.CurrentOptions.HubName), e->HubName);
+
+ // Get the current options on the server
+ if (CALL(hWnd, ScGetHubExtOptions(e->p->Rpc, &a.CurrentOptions)) == false)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_ADMIN_OPTION, SmHubAdminOptionDlg, &a);
+
+ FreeRpcAdminOption(&a.CurrentOptions);
+ FreeRpcAdminOption(&a.DefaultOptions);
+}
+
+// Virtual HUB management options
+void SmHubAdminOption(HWND hWnd, SM_EDIT_HUB *e)
+{
+ SM_EDIT_AO a;
+ // Validate arguments
+ if (hWnd == NULL || e == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+ a.e = e;
+
+ StrCpy(a.CurrentOptions.HubName, sizeof(a.CurrentOptions.HubName), e->HubName);
+
+ // Get the current options on the server
+ if (CALL(hWnd, ScGetHubAdminOptions(e->p->Rpc, &a.CurrentOptions)) == false)
+ {
+ return;
+ }
+
+ ScGetDefaultHubAdminOptions(e->p->Rpc, &a.DefaultOptions);
+
+ Dialog(hWnd, D_SM_ADMIN_OPTION, SmHubAdminOptionDlg, &a);
+
+ FreeRpcAdminOption(&a.CurrentOptions);
+ FreeRpcAdminOption(&a.DefaultOptions);
+}
+
+// Initialize
+void SmConfigDlgInit(HWND hWnd, SM_CONFIG *c)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (hWnd == NULL || c == NULL)
+ {
+ return;
+ }
+
+ Focus(hWnd, IDCANCEL);
+
+ SetIcon(hWnd, 0, ICO_MACHINE);
+
+ SetFont(hWnd, E_CONFIG, GetFont(_SS("DEFAULT_FONT_2"), 0, false, false,
+ false, false));
+
+ FormatText(hWnd, IDC_INFO, c->s->ServerName);
+
+ // Convert from UTF-8 to Unicode
+ tmp_size = CalcUtf8ToUni(c->Config.FileData, StrLen(c->Config.FileData)) + 1;
+ tmp = ZeroMalloc(tmp_size);
+ Utf8ToUni(tmp, tmp_size, c->Config.FileData, StrLen(c->Config.FileData));
+
+ SetText(hWnd, E_CONFIG, tmp);
+
+ Free(tmp);
+}
+
+// Config edit dialog
+UINT SmConfigDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_CONFIG *c = (SM_CONFIG *)param;
+ char *filename;
+ wchar_t *filename_unicode;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmConfigDlgInit(hWnd, c);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_EXPORT:
+ StrToUni(tmp, sizeof(tmp), c->Config.FileName);
+ filename_unicode = SaveDlg(hWnd, _UU("DLG_CONFIG_FILES"), _UU("DLG_SAVE_CONFIG"), tmp, L".config");
+ if (filename_unicode != NULL)
+ {
+ BUF *b = NewBuf();
+ filename = CopyUniToStr(filename_unicode);
+ WriteBuf(b, c->Config.FileData, StrLen(c->Config.FileData));
+ if (DumpBuf(b, filename))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CONFIG_SAVED"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CONFIG_SAVE_FAILED"));
+ }
+ FreeBuf(b);
+ Free(filename);
+ Free(filename_unicode);
+ }
+ break;
+
+ case B_IMPORT:
+ filename_unicode = OpenDlg(hWnd, _UU("DLG_CONFIG_FILES"), _UU("DLG_OPEN_CONFIG"));
+ if (filename_unicode != NULL)
+ {
+ BUF *b;
+ filename = CopyUniToStr(filename_unicode);
+ b = ReadDump(filename);
+ if (b != NULL)
+ {
+ RPC_CONFIG t;
+
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_CONFIG_CONFIRM")) == IDYES)
+ {
+ Zero(&t, sizeof(t));
+ t.FileData = ZeroMalloc(b->Size + 1);
+ Copy(t.FileData, b->Buf, b->Size);
+
+ if (CALL(hWnd, ScSetConfig(c->s->Rpc, &t)))
+ {
+ // Success
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CONFIG_WRITE_OK"));
+ _exit(0);
+ }
+
+ FreeRpcConfig(&t);
+
+ FreeRpcConfig(&t);
+ FreeBuf(b);
+ }
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CONFIG_OPEN_FAILED"));
+ }
+ Free(filename);
+ Free(filename_unicode);
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_FACTORY:
+ if (MsgBox(hWnd, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2, _UU("SM_FACTORY_DEFAULT_WARNING")) == IDYES)
+ {
+ RPC_TEST t;
+ UINT ret;
+
+ Zero(&t, sizeof(t));
+
+ t.IntValue = 1;
+ ret = ScRebootServer(c->s->Rpc, &t);
+
+ if (ret == ERR_DISCONNECTED || ret == ERR_NO_ERROR)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_FACTORY_DEFAULT_PERFORMED"));
+
+ exit(0);
+ }
+ else
+ {
+ CALL(hWnd, ret);
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the config edit dialog
+void SmConfig(HWND hWnd, SM_SERVER *s)
+{
+ SM_CONFIG c;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+
+ c.s = s;
+
+ // Get current config from the server
+ if (CALL(hWnd, ScGetConfig(s->Rpc, &c.Config)) == false)
+ {
+ return;
+ }
+
+ // Show the dialog
+ Dialog(hWnd, D_SM_CONFIG, SmConfigDlg, &c);
+
+ // Release
+ FreeRpcConfig(&c.Config);
+}
+
+// Bridge dialog initialization
+UINT SmBridgeDlgInit(HWND hWnd, SM_SERVER *s)
+{
+ UINT i;
+ RPC_ENUM_ETH t;
+ RPC_SERVER_INFO si;
+ UINT num = 0;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return 0;
+ }
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_BRIDGE_COLUMN_1"), 50);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_BRIDGE_COLUMN_2"), 145);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_BRIDGE_COLUMN_3"), 300);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_BRIDGE_COLUMN_4"), 100);
+
+ SmBridgeDlgRefresh(hWnd, s);
+
+ SetShow(hWnd, B_VLAN, GetCapsBool(s->CapsList, "b_support_eth_vlan"));
+
+ SetIcon(hWnd, 0, ICO_BRIDGE);
+
+ // Get the server information
+ Zero(&si, sizeof(si));
+ ScGetServerInfo(s->Rpc, &si);
+ if (GetCapsBool(s->CapsList, "b_tap_supported") == false)
+ {
+ // Tap does not supported
+ Hide(hWnd, R_TAP);
+ Hide(hWnd, S_TAP_1);
+ Hide(hWnd, E_TAPNAME);
+ Hide(hWnd, S_TAP_2);
+ Hide(hWnd, R_BRIDGE);
+ Hide(hWnd, S_STATIC5);
+ }
+ Check(hWnd, R_BRIDGE, true);
+ FreeRpcServerInfo(&si);
+
+ // Enumerate the Ethernet devices
+ Zero(&t, sizeof(t));
+ ScEnumEthernet(s->Rpc, &t);
+
+ CbReset(hWnd, E_NICNAME);
+ CbSetHeight(hWnd, E_NICNAME, 18);
+
+ num = t.NumItem;
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_ENUM_ETH_ITEM *e = &t.Items[i];
+ if (GetCapsBool(s->CapsList, "b_support_network_connection_name"))
+ {
+ wchar_t ncname[MAX_SIZE * 2];
+ UniFormat(ncname, sizeof(ncname), BRIDGE_NETWORK_CONNECTION_STR, e->NetworkConnectionName, e->DeviceName);
+ CbAddStr(hWnd, E_NICNAME, ncname, 0);
+ }
+ else
+ {
+ wchar_t *s = CopyStrToUni(e->DeviceName);
+ CbAddStr(hWnd, E_NICNAME, s, 0);
+ Free(s);
+ }
+ }
+
+ FreeRpcEnumEth(&t);
+
+ // Enumerate the Virtual HUBs
+ {
+ RPC_ENUM_HUB t;
+ Zero(&t, sizeof(t));
+
+ ScEnumHub(s->Rpc, &t);
+
+ CbReset(hWnd, E_HUBNAME);
+ CbSetHeight(hWnd, E_HUBNAME, 18);
+
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+ wchar_t *s = CopyStrToUni(e->HubName);
+
+ if (e->HubType != HUB_TYPE_FARM_DYNAMIC)
+ {
+ CbAddStr(hWnd, E_HUBNAME, s, 0);
+ }
+ Free(s);
+ }
+
+ SetText(hWnd, E_HUBNAME, L"");
+
+ FreeRpcEnumHub(&t);
+ }
+
+ if (s->Bridge)
+ {
+ SetTextA(hWnd, E_HUBNAME, "BRIDGE");
+ }
+
+ Focus(hWnd, E_HUBNAME);
+
+ SmBridgeDlgUpdate(hWnd, s);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+
+ return num;
+}
+
+// Bridge dialog control update
+void SmBridgeDlgUpdate(HWND hWnd, SM_SERVER *s)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false)
+ {
+ Enable(hWnd, B_DELETE);
+ }
+ else
+ {
+ Disable(hWnd, B_DELETE);
+ }
+
+ if (IsEmpty(hWnd, E_HUBNAME))
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, R_TAP) == false)
+ {
+ // Bridge mode
+ Enable(hWnd, S_ETH_1);
+ Enable(hWnd, E_NICNAME);
+ Disable(hWnd, S_TAP_1);
+ Disable(hWnd, S_TAP_2);
+ Disable(hWnd, E_TAPNAME);
+ SetText(hWnd, S_INFO, _UU("SM_BRIDGE_INFO_1"));
+ SetIcon(hWnd, S_ICON, ICO_NIC_ONLINE);
+ if (IsEmpty(hWnd, E_NICNAME))
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ // Tap mode
+ Disable(hWnd, S_ETH_1);
+ Disable(hWnd, E_NICNAME);
+ Enable(hWnd, S_TAP_1);
+ Enable(hWnd, S_TAP_2);
+ Enable(hWnd, E_TAPNAME);
+ SetText(hWnd, S_INFO, _UU("SM_BRIDGE_INFO_2"));
+ SetIcon(hWnd, S_ICON, ICO_PROTOCOL);
+ GetTxtA(hWnd, E_TAPNAME, tmp, sizeof(tmp));
+ if (IsEmptyStr(tmp))
+ {
+ ok = false;
+ }
+ else
+ {
+ if (IsSafeStr(tmp) == false)
+ {
+ ok = false;
+ }
+ if (StrLen(tmp) >= 12)
+ {
+ ok = false;
+ }
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Bridge dialog update
+void SmBridgeDlgRefresh(HWND hWnd, SM_SERVER *s)
+{
+ LVB *lvb;
+ RPC_ENUM_LOCALBRIDGE t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ lvb = LvInsertStart();
+
+ Zero(&t, sizeof(t));
+
+ ScEnumLocalBridge(s->Rpc, &t);
+
+ for (i = 0;i < t.NumItem;i++)
+ {
+ RPC_LOCALBRIDGE *e = &t.Items[i];
+ wchar_t name[MAX_SIZE];
+ wchar_t nic[MAX_SIZE];
+ wchar_t hub[MAX_SIZE];
+ wchar_t *status = _UU("SM_BRIDGE_OFFLINE");
+
+ UniToStru(name, i + 1);
+ StrToUni(nic, sizeof(nic), e->DeviceName);
+ StrToUni(hub, sizeof(hub), e->HubName);
+
+ if (e->Online)
+ {
+ status = e->Active ? _UU("SM_BRIDGE_ONLINE") : _UU("SM_BRIDGE_ERROR");
+ }
+
+ LvInsertAdd(lvb, e->TapMode == false ? (e->Active ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE) : ICO_PROTOCOL,
+ NULL, 4, name, hub, nic, status);
+ }
+
+ FreeRpcEnumLocalBridge(&t);
+
+ LvInsertEnd(lvb, hWnd, L_LIST);
+
+ SmBridgeDlgUpdate(hWnd, s);
+}
+
+// Add a Local Bridge
+void SmBridgeDlgOnOk(HWND hWnd, SM_SERVER *s)
+{
+ char nic[MAX_SIZE];
+ char hub[MAX_SIZE];
+ RPC_LOCALBRIDGE t;
+ bool tapmode = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_HUBNAME, hub, sizeof(hub));
+
+ Zero(nic, sizeof(nic));
+
+ if (IsChecked(hWnd, R_TAP) == false)
+ {
+ wchar_t nctmp[MAX_SIZE * 2];
+ if(GetCapsBool(s->CapsList, "b_support_network_connection_name") && GetTxt(hWnd, E_NICNAME, nctmp, sizeof(nctmp)))
+ {
+ RPC_ENUM_ETH et;
+ UINT i;
+ Zero(&et, sizeof(et));
+ ScEnumEthernet(s->Rpc, &et);
+ for(i = 0; i < et.NumItem; i++)
+ {
+ RPC_ENUM_ETH_ITEM *e = &et.Items[i];
+ if(UniIsEmptyStr(e->NetworkConnectionName) == false)
+ {
+ wchar_t ncname[MAX_SIZE * 2];
+ UniFormat(ncname, sizeof(ncname), BRIDGE_NETWORK_CONNECTION_STR, e->NetworkConnectionName, e->DeviceName);
+ if(UniStrCmp(ncname, nctmp) == 0)
+ {
+ StrCpy(nic, sizeof(nic), e->DeviceName);
+ break;
+ }
+ }
+ }
+ FreeRpcEnumEth(&et);
+
+ if (IsEmptyStr(nic))
+ {
+ GetTxtA(hWnd, E_NICNAME, nic, sizeof(nic));
+ }
+ }
+ else
+ {
+ GetTxtA(hWnd, E_NICNAME, nic, sizeof(nic));
+ }
+ }
+ else
+ {
+ tapmode = true;
+ GetTxtA(hWnd, E_TAPNAME, nic, sizeof(nic));
+ }
+
+ Trim(hub);
+ Trim(nic);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), nic);
+ StrCpy(t.HubName, sizeof(t.HubName), hub);
+ t.TapMode = tapmode;
+
+ if (InStrEx(t.DeviceName, "vpn", false) || InStrEx(t.DeviceName, "tun", false)
+ || InStrEx(t.DeviceName, "tap", false))
+ {
+ // Trying to make a local bridge to the VPN device
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_BRIDGE_VPN"),
+ t.DeviceName) == IDNO)
+ {
+ return;
+ }
+ }
+
+ // Show a warning message if the VPN Server is running in a VM
+ if (GetCapsBool(s->CapsList, "b_is_in_vm"))
+ {
+ Dialog(hWnd, D_SM_VMBRIDGE, SmVmBridgeDlg, NULL);
+ }
+
+ // Warning for such as Intel LAN cards
+ if (tapmode == false)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_INTEL"));
+ }
+
+ if (CALL(hWnd, ScAddLocalBridge(s->Rpc, &t)) == false)
+ {
+ Focus(hWnd, E_HUBNAME);
+ return;
+ }
+
+ SetText(hWnd, E_HUBNAME, L"");
+ Focus(hWnd, E_HUBNAME);
+
+ if (tapmode)
+ {
+ SetTextA(hWnd, E_TAPNAME, "");
+ }
+
+ SmBridgeDlgRefresh(hWnd, s);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_OK"));
+}
+
+// Bridge dialog procedure
+UINT SmBridgeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_SERVER *s = (SM_SERVER *)param;
+ UINT i;
+ UINT num;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ num = SmBridgeDlgInit(hWnd, s);
+
+ if (num == 0)
+ {
+ SetTimer(hWnd, 2, 500, NULL);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_HUBNAME:
+ case E_NICNAME:
+ case R_BRIDGE:
+ case R_TAP:
+ case E_TAPNAME:
+ SmBridgeDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case R_BRIDGE:
+ Focus(hWnd, E_NICNAME);
+ break;
+
+ case R_TAP:
+ FocusEx(hWnd, E_TAPNAME);
+ break;
+
+ case IDOK:
+ // Add
+ SmBridgeDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Close
+ Close(hWnd);
+ break;
+
+ case B_VLAN:
+ // VLAN utility
+ SmVLan(hWnd, s);
+ break;
+
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ wchar_t *nic, *hub;
+ wchar_t tmp[MAX_SIZE];
+ RPC_LOCALBRIDGE t;
+
+ hub = LvGetStr(hWnd, L_LIST, i, 1);
+ nic = LvGetStr(hWnd, L_LIST, i, 2);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_BRIDGE_DELETE"),
+ hub, nic);
+
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, tmp) == IDYES)
+ {
+ Zero(&t, sizeof(t));
+ UniToStr(t.DeviceName, sizeof(t.DeviceName), nic);
+ UniToStr(t.HubName, sizeof(t.HubName), hub);
+
+ if (CALL(hWnd, ScDeleteLocalBridge(s->Rpc, &t)))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_DELETE_OK"));
+ SmBridgeDlgRefresh(hWnd, s);
+ }
+ }
+
+ Free(hub);
+ Free(nic);
+ }
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+ SmBridgeDlgRefresh(hWnd, s);
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+
+ case 2:
+ KillTimer(hWnd, 2);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_NO_BRIDGE_NICS"));
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ SmBridgeDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Installation of WinPcap
+void SmInstallWinPcap(HWND hWnd, SM_SERVER *s)
+{
+ wchar_t temp_name[MAX_SIZE];
+ IO *io;
+ BUF *buf;
+
+ // Ask whether the user want to start the installation
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_BRIDGE_WPCAP_INSTALL")) == IDNO)
+ {
+ return;
+ }
+
+ // Generate a temporary file name
+ UniFormat(temp_name, sizeof(temp_name), L"%s\\winpcap_installer.exe", MsGetTempDirW());
+
+ // Read from hamcore
+ buf = ReadDump(MsIsNt() ? "|winpcap_installer.exe" : "|winpcap_installer_win9x.exe");
+ if (buf == NULL)
+ {
+RES_ERROR:
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_BRIDGE_RESOURCE"));
+ return;
+ }
+
+ // Write to a temporary file
+ io = FileCreateW(temp_name);
+ if (io == NULL)
+ {
+ FreeBuf(buf);
+ goto RES_ERROR;
+ }
+
+ FileWrite(io, buf->Buf, buf->Size);
+ FileClose(io);
+
+ FreeBuf(buf);
+
+ // Run
+ if (RunW(temp_name, NULL, false, true) == false)
+ {
+ // Failure
+ FileDeleteW(temp_name);
+ goto RES_ERROR;
+ }
+
+ FileDeleteW(temp_name);
+
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Message after completed
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) == false)
+ {
+ // Need to restart the computer
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_REBOOT1"));
+ }
+ else
+ {
+ // Need to restart the service
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_BRIDGE_WPCAP_REBOOT2")) == IDNO)
+ {
+ // Not restart
+ }
+ else
+ {
+ // Restart
+ RPC_TEST t;
+ Zero(&t, sizeof(t));
+ ScRebootServer(s->Rpc, &t);
+
+ SleepThread(500);
+
+ Zero(&t, sizeof(t));
+ CALL(hWnd, ScTest(s->Rpc, &t));
+ }
+ }
+}
+
+// Bridge dialog
+void SmBridgeDlg(HWND hWnd, SM_SERVER *s)
+{
+ RPC_BRIDGE_SUPPORT t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ // Examine the bridge support status of the server side first
+ Zero(&t, sizeof(t));
+ if (CALLEX(hWnd, ScGetBridgeSupport(s->Rpc, &t)) != ERR_NO_ERROR)
+ {
+ // Not supported because it is old version
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_BRIDGE_TOO_OLD_VER"));
+ return;
+ }
+
+ if (t.IsBridgeSupportedOs == false)
+ {
+ // OS does not support the bridge
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_BRIDGE_UNSUPPORTED"));
+ return;
+ }
+
+ if (t.IsWinPcapNeeded)
+ {
+ if (s->Rpc->Sock->RemoteIP.addr[0] != 127)
+ {
+ // WinPcap is required, but can not do anything because it is in remote control mode
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_REMOTE"));
+ return;
+ }
+ else
+ {
+ // WinPcap is required, and it's in local management mode
+ if (MsIsAdmin())
+ {
+ // The user is an Administrators
+ SmInstallWinPcap(hWnd, s);
+ return;
+ }
+ else
+ {
+ // The user is a non-Administrators
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_ROOT"));
+ return;
+ }
+ }
+ }
+
+ Dialog(hWnd, D_SM_BRIDGE, SmBridgeDlgProc, s);
+}
+
+// SecureNAT screen update
+void SmSNATDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ bool b;
+ RPC_HUB_STATUS t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScGetHubStatus(s->Rpc, &t)) == false)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ b = t.SecureNATEnabled;
+
+ if (b)
+ {
+ Disable(hWnd, B_ENABLE);
+ Enable(hWnd, B_DISABLE);
+ Enable(hWnd, B_NAT);
+ Enable(hWnd, B_DHCP);
+ Enable(hWnd, B_STATUS);
+ }
+ else
+ {
+ Enable(hWnd, B_ENABLE);
+ Disable(hWnd, B_DISABLE);
+ Disable(hWnd, B_NAT);
+ Disable(hWnd, B_DHCP);
+ Disable(hWnd, B_STATUS);
+ }
+}
+
+// SecureNAT configuration screen
+UINT SmSNATDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ RPC_HUB t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_ROUTER);
+ DlgFont(hWnd, S_WARNING, (_GETLANG() == 0 || _GETLANG() == 2) ? 13 : 10, true);
+ FormatText(hWnd, S_TITLE, s->HubName);
+ SmSNATDlgUpdate(hWnd, s);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_TIMER:
+ if (wParam == 1)
+ {
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+
+ SmSNATDlgUpdate(hWnd, s);
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_ENABLE:
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_OKCANCEL | MB_DEFBUTTON2,
+ _UU("SM_SECURE_NAT_MSG")) == IDOK)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ CALL(hWnd, ScEnableSecureNAT(s->Rpc, &t));
+ SmSNATDlgUpdate(hWnd, s);
+ }
+ break;
+
+ case B_DISABLE:
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ CALL(hWnd, ScDisableSecureNAT(s->Rpc, &t));
+ SmSNATDlgUpdate(hWnd, s);
+ break;
+
+ case B_CONFIG:
+ NmEditVhOption(hWnd, s);
+ break;
+
+ case B_NAT:
+ NmNat(hWnd, s);
+ break;
+
+ case B_DHCP:
+ NmDhcp(hWnd, s);
+ break;
+
+ case B_STATUS:
+ SmStatusDlg(hWnd, s->p, s, false, true, _UU("SM_SNAT_STATUS"), ICO_ROUTER,
+ NULL, NmStatus);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize
+void SmCreateCertDlgInit(HWND hWnd, SM_CERT *s)
+{
+ UINT cert_sign;
+ UINT cert_days;
+ char *reg_o, *reg_ou, *reg_c, *reg_st, *reg_l;
+ UINT bits[] = {1024, 1536, 2048, 3072, 4096 };
+ UINT i;
+ UINT last_bit;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetTextA(hWnd, E_CN, s->default_cn);
+
+ last_bit = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Bits");
+ if (last_bit == 0)
+ {
+ last_bit = 2048;
+ }
+
+ CbReset(hWnd, C_BITS);
+ for (i = 0;i < sizeof(bits) / sizeof(bits[0]);i++)
+ {
+ char tmp[MAX_PATH];
+ UINT index;
+
+ ToStr(tmp, bits[i]);
+
+ index = CbAddStrA(hWnd, C_BITS, tmp, bits[i]);
+ }
+
+ CbSelect(hWnd, C_BITS, 1024);
+ CbSelect(hWnd, C_BITS, last_bit);
+
+ reg_o = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "O");
+ reg_ou = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "OU");
+ reg_c = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "C");
+ reg_st = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "ST");
+ reg_l = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "L");
+ SetTextA(hWnd, E_O, reg_o);
+ SetTextA(hWnd, E_OU, reg_ou);
+ SetTextA(hWnd, E_C, reg_c);
+ SetTextA(hWnd, E_ST, reg_st);
+ SetTextA(hWnd, E_L, reg_l);
+ Free(reg_o);
+ Free(reg_ou);
+ Free(reg_c);
+ Free(reg_st);
+ Free(reg_l);
+
+ LimitText(hWnd, E_C, 2);
+
+ cert_sign = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Sign");
+ cert_days = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Days");
+
+ Check(hWnd, R_ROOT_CERT, cert_sign ? false : true);
+ Check(hWnd, R_SIGNED_CERT, cert_sign ? true : false);
+
+ if (cert_days == 0)
+ {
+ cert_days = 3650;
+ }
+
+ SetIntEx(hWnd, E_EXPIRE, cert_days);
+
+ SmCreateCertDlgUpdate(hWnd, s);
+
+ if (s->root_only)
+ {
+ Disable(hWnd, R_SIGNED_CERT);
+ }
+
+ // Font
+ SetFont(hWnd, E_CN, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_O, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_OU, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_C, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_ST, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_L, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_SERIAL, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, E_EXPIRE, GetFont((MsIsWinXPOrGreater() ? "Verdana" : NULL), 0, false, false, false, false));
+ SetFont(hWnd, C_BITS, GetFont("Verdana", 0, false, false, false, false));
+
+ FocusEx(hWnd, E_CN);
+}
+
+// Update
+void SmCreateCertDlgUpdate(HWND hWnd, SM_CERT *s)
+{
+ bool ok = true;
+ bool b;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (IsEmpty(hWnd, E_CN) && IsEmpty(hWnd, E_O) && IsEmpty(hWnd, E_OU) &&
+ IsEmpty(hWnd, E_ST) && IsEmpty(hWnd, E_L))
+ {
+ ok = false;
+ }
+
+ i = GetInt(hWnd, E_EXPIRE);
+ if (i == 0 || i >= (365 * 30))
+ {
+ ok = false;
+ }
+
+ b = IsChecked(hWnd, R_SIGNED_CERT);
+
+ SetEnable(hWnd, S_LOAD_1, b);
+ SetEnable(hWnd, B_LOAD, b);
+ SetEnable(hWnd, S_LOAD_2, b);
+
+ if (b && (s->root_k == NULL || s->root_x == NULL))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// [OK] button
+void SmCreateCertDlgOnOk(HWND hWnd, SM_CERT *s)
+{
+ wchar_t cn[MAX_SIZE], o[MAX_SIZE], ou[MAX_SIZE], c[MAX_SIZE], st[MAX_SIZE], l[MAX_SIZE];
+ char *reg_o, *reg_ou, *reg_c, *reg_st, *reg_l;
+ UINT days;
+ bool sign;
+ char serial[MAX_SIZE * 2];
+ X *x;
+ K *pub;
+ K *pri;
+ NAME *n;
+ X_SERIAL *x_serial;
+ BUF *buf;
+ UINT bits;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ GetTxt(hWnd, E_CN, cn, sizeof(cn));
+ GetTxt(hWnd, E_O, o, sizeof(o));
+ GetTxt(hWnd, E_OU, ou, sizeof(ou));
+ GetTxt(hWnd, E_C, c, sizeof(c));
+ GetTxt(hWnd, E_ST, st, sizeof(st));
+ GetTxt(hWnd, E_L, l, sizeof(l));
+ GetTxtA(hWnd, E_SERIAL, serial, sizeof(serial));
+
+ bits = CbGetSelect(hWnd, C_BITS);
+ if (bits == INFINITE)
+ {
+ bits = 1024;
+ }
+
+ buf = StrToBin(serial);
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ if (buf->Size > 1)
+ {
+ x_serial = NewXSerial(buf->Buf, buf->Size);
+ }
+ else
+ {
+ x_serial = NULL;
+ }
+
+ FreeBuf(buf);
+
+ n = NewName(UniStrLen(cn) ? cn : NULL,
+ UniStrLen(o) ? o : NULL,
+ UniStrLen(ou) ? ou : NULL,
+ UniStrLen(c) ? c : NULL,
+ UniStrLen(st) ? st : NULL,
+ UniStrLen(l) ? l : NULL);
+
+ days = GetInt(hWnd, E_EXPIRE);
+
+ sign = IsChecked(hWnd, R_SIGNED_CERT);
+
+ MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Sign", sign);
+ MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Days", days);
+ MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Bits", bits);
+
+ RsaGen(&pri, &pub, bits);
+
+ if (sign == false)
+ {
+ x = NewRootX(pub, pri, n, days, x_serial);
+ }
+ else
+ {
+ x = NewX(pub, s->root_k, s->root_x, n, days, x_serial);
+ }
+
+ FreeName(n);
+
+ FreeXSerial(x_serial);
+
+ if (x == NULL)
+ {
+ FreeX(x);
+ FreeK(pub);
+ FreeK(pri);
+ return;
+ }
+
+ if (s->do_not_save == false)
+ {
+ if (SmSaveKeyPairDlg(hWnd, x, pri) == false)
+ {
+ FreeX(x);
+ FreeK(pub);
+ FreeK(pri);
+ return;
+ }
+ }
+
+ s->x = x;
+ s->k = pri;
+ FreeK(pub);
+
+ reg_o = GetTextA(hWnd, E_O);
+ reg_ou = GetTextA(hWnd, E_OU);
+ reg_c = GetTextA(hWnd, E_C);
+ reg_st = GetTextA(hWnd, E_ST);
+ reg_l = GetTextA(hWnd, E_L);
+ MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "O", reg_o);
+ MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "OU", reg_ou);
+ MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "C", reg_c);
+ MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "ST", reg_st);
+ MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "L", reg_l);
+ Free(reg_o);
+ Free(reg_ou);
+ Free(reg_c);
+ Free(reg_st);
+ Free(reg_l);
+
+ EndDialog(hWnd, true);
+}
+
+// Certificate creation screen
+UINT SmCreateCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_CERT *s = (SM_CERT *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmCreateCertDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_ROOT_CERT:
+ case R_SIGNED_CERT:
+ case B_LOAD:
+ case E_CN:
+ case E_O:
+ case E_OU:
+ case E_C:
+ case E_ST:
+ case E_L:
+ case E_EXPIRE:
+ SmCreateCertDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmCreateCertDlgOnOk(hWnd, s);
+ break;
+
+ case R_ROOT_CERT:
+ if (IsChecked(hWnd, R_ROOT_CERT))
+ {
+ FocusEx(hWnd, E_CN);
+ }
+ break;
+
+ case B_LOAD:
+ // Read a certificate
+ if (1)
+ {
+ X *x;
+ K *k;
+ if (CmLoadXAndK(hWnd, &x, &k))
+ {
+ wchar_t tmp[MAX_SIZE];
+ FreeX(s->root_x);
+ FreeK(s->root_k);
+ s->root_x = x;
+ s->root_k = k;
+
+ SmGetCertInfoStr(tmp, sizeof(tmp), x);
+ SetText(hWnd, S_LOAD_2, tmp);
+ SmCreateCertDlgUpdate(hWnd, s);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Certificate tool
+bool SmCreateCert(HWND hWnd, X **x, K **k, bool do_not_save, char *default_cn, bool root_only)
+{
+ bool ret;
+ SM_CERT s;
+ Zero(&s, sizeof(s));
+
+ if (default_cn == NULL)
+ {
+ default_cn = "";
+ }
+
+ s.default_cn = default_cn;
+
+ s.do_not_save = do_not_save;
+
+ s.root_only = root_only;
+
+ ret = Dialog(hWnd, D_SM_CREATE_CERT, SmCreateCertDlgProc, &s);
+
+ if (ret)
+ {
+ if (x != NULL)
+ {
+ *x = CloneX(s.x);
+ }
+
+ if (k != NULL)
+ {
+ *k = CloneK(s.k);
+ }
+ }
+
+ FreeX(s.x);
+ FreeK(s.k);
+ FreeX(s.root_x);
+ FreeK(s.root_k);
+
+ return ret;
+}
+
+// Initialize
+void SmIpTableDlgInit(HWND hWnd, SM_TABLE *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_PROTOCOL);
+ FormatText(hWnd, S_TITLE, s->Hub->HubName);
+
+ if (s->SessionName != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ GetTxt(hWnd, S_TITLE, tmp, sizeof(tmp));
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESSION_FILTER"), s->SessionName);
+ UniStrCat(tmp, sizeof(tmp), tmp2);
+ SetText(hWnd, S_TITLE, tmp);
+ }
+
+ LvInit(hWnd, L_TABLE);
+ LvInsertColumn(hWnd, L_TABLE, 0, _UU("SM_IP_COLUMN_1"), 190);
+ LvInsertColumn(hWnd, L_TABLE, 1, _UU("SM_IP_COLUMN_2"), 140);
+ LvInsertColumn(hWnd, L_TABLE, 2, _UU("SM_IP_COLUMN_3"), 133);
+ LvInsertColumn(hWnd, L_TABLE, 3, _UU("SM_IP_COLUMN_4"), 133);
+ LvInsertColumn(hWnd, L_TABLE, 4, _UU("SM_IP_COLUMN_5"), 133);
+ LvSetStyle(hWnd, L_TABLE, LVS_EX_GRIDLINES);
+
+ SmIpTableDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmIpTableDlgUpdate(HWND hWnd, SM_TABLE *s)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_TABLE) == false || LvIsMultiMasked(hWnd, L_TABLE))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, B_DELETE, ok);
+}
+
+// Content update
+void SmIpTableDlgRefresh(HWND hWnd, SM_TABLE *s)
+{
+ UINT i;
+ RPC_ENUM_IP_TABLE t;
+ UINT old_selected = 0;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+
+ if (CALL(hWnd, ScEnumIpTable(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ i = LvGetSelected(hWnd, L_TABLE);
+ if (i != INFINITE)
+ {
+ old_selected = (UINT)LvGetParam(hWnd, L_TABLE, i);
+ }
+
+ LvReset(hWnd, L_TABLE);
+
+ for (i = 0;i < t.NumIpTable;i++)
+ {
+ char str[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ RPC_ENUM_IP_TABLE_ITEM *e = &t.IpTables[i];
+
+ if (s->SessionName == NULL || StrCmpi(e->SessionName, s->SessionName) == 0)
+ {
+ StrToUni(tmp1, sizeof(tmp1), e->SessionName);
+
+ if (e->DhcpAllocated == false)
+ {
+ IPToStr(str, sizeof(str), &e->IpV6);
+ StrToUni(tmp2, sizeof(tmp2), str);
+ }
+ else
+ {
+ IPToStr(str, sizeof(str), &e->IpV6);
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_MAC_IP_DHCP"), str);
+ }
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));
+
+ GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));
+
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));
+ }
+ else
+ {
+ UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);
+ }
+
+ LvInsert(hWnd, L_TABLE, e->DhcpAllocated ? ICO_PROTOCOL_DHCP : ICO_PROTOCOL, (void *)e->Key, 5,
+ tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+ }
+
+ FreeRpcEnumIpTable(&t);
+
+ if (old_selected != 0)
+ {
+ LvSelect(hWnd, L_TABLE, LvSearchParam(hWnd, L_TABLE, (void *)old_selected));
+ }
+
+ SmIpTableDlgUpdate(hWnd, s);
+}
+
+// IP address table dialog procedure
+UINT SmIpTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_TABLE *s = (SM_TABLE *)param;
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmIpTableDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_TABLE);
+ if (i != INFINITE)
+ {
+ RPC_DELETE_TABLE t;
+ UINT key = (UINT)LvGetParam(hWnd, L_TABLE, i);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ t.Key = key;
+ if (CALL(hWnd, ScDeleteIpTable(s->Rpc, &t)))
+ {
+ LvDeleteItem(hWnd, L_TABLE, i);
+ }
+ }
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmIpTableDlgRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_TABLE:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmIpTableDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);
+
+ return 0;
+}
+
+// IP address table dialog
+void SmIpTableDlg(HWND hWnd, SM_HUB *s, char *session_name)
+{
+ SM_TABLE t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Hub = s;
+ t.Rpc = s->Rpc;
+ t.SessionName = session_name;
+
+ Dialog(hWnd, D_SM_IP, SmIpTableDlgProc, &t);
+}
+
+
+// Initialize
+void SmMacTableDlgInit(HWND hWnd, SM_TABLE *s)
+{
+ UINT i = 0;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_NIC_ONLINE);
+ FormatText(hWnd, S_TITLE, s->Hub->HubName);
+
+ if (s->SessionName != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ GetTxt(hWnd, S_TITLE, tmp, sizeof(tmp));
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESSION_FILTER"), s->SessionName);
+ UniStrCat(tmp, sizeof(tmp), tmp2);
+ SetText(hWnd, S_TITLE, tmp);
+ }
+
+ LvInit(hWnd, L_TABLE);
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_1"), 190);
+ if (GetCapsBool(s->Hub->p->CapsList, "b_support_vlan"))
+ {
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_1A"), 65);
+ }
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_2"), 140);
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_3"), 133);
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_4"), 133);
+ LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_5"), 133);
+ LvSetStyle(hWnd, L_TABLE, LVS_EX_GRIDLINES);
+
+ SmMacTableDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmMacTableDlgUpdate(HWND hWnd, SM_TABLE *s)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_TABLE) == false || LvIsMultiMasked(hWnd, L_TABLE))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, B_DELETE, ok);
+}
+
+// Content update
+void SmMacTableDlgRefresh(HWND hWnd, SM_TABLE *s)
+{
+ UINT i;
+ RPC_ENUM_MAC_TABLE t;
+ UINT old_selected = 0;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+
+ if (CALL(hWnd, ScEnumMacTable(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ i = LvGetSelected(hWnd, L_TABLE);
+ if (i != INFINITE)
+ {
+ old_selected = (UINT)LvGetParam(hWnd, L_TABLE, i);
+ }
+
+ LvReset(hWnd, L_TABLE);
+
+ for (i = 0;i < t.NumMacTable;i++)
+ {
+ char str[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+ RPC_ENUM_MAC_TABLE_ITEM *e = &t.MacTables[i];
+
+ if (s->SessionName == NULL || StrCmpi(e->SessionName, s->SessionName) == 0)
+ {
+ StrToUni(tmp1, sizeof(tmp1), e->SessionName);
+
+ MacToStr(str, sizeof(str), e->MacAddress);
+ StrToUni(tmp2, sizeof(tmp2), str);
+
+ GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));
+
+ GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));
+
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));
+ }
+ else
+ {
+ UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);
+ }
+
+ UniToStru(tmp6, e->VlanId);
+ if (e->VlanId == 0)
+ {
+ UniStrCpy(tmp6, sizeof(tmp6), _UU("CM_ST_NONE"));
+ }
+
+ if (GetCapsBool(s->Hub->p->CapsList, "b_support_vlan"))
+ {
+ LvInsert(hWnd, L_TABLE, ICO_NIC_ONLINE, (void *)e->Key, 6,
+ tmp1, tmp6, tmp2, tmp3, tmp4, tmp5);
+ }
+ else
+ {
+ LvInsert(hWnd, L_TABLE, ICO_NIC_ONLINE, (void *)e->Key, 5,
+ tmp1, tmp2, tmp3, tmp4, tmp5);
+ }
+ }
+ }
+
+ FreeRpcEnumMacTable(&t);
+
+ if (old_selected != 0)
+ {
+ LvSelect(hWnd, L_TABLE, LvSearchParam(hWnd, L_TABLE, (void *)old_selected));
+ }
+
+ SmMacTableDlgUpdate(hWnd, s);
+}
+
+// MAC address table dialog procedure
+UINT SmMacTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_TABLE *s = (SM_TABLE *)param;
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmMacTableDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_TABLE);
+ if (i != INFINITE)
+ {
+ RPC_DELETE_TABLE t;
+ UINT key = (UINT)LvGetParam(hWnd, L_TABLE, i);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ t.Key = key;
+ if (CALL(hWnd, ScDeleteMacTable(s->Rpc, &t)))
+ {
+ LvDeleteItem(hWnd, L_TABLE, i);
+ }
+ }
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmMacTableDlgRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_TABLE:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmMacTableDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);
+
+ return 0;
+}
+
+// MAC address table dialog
+void SmMacTableDlg(HWND hWnd, SM_HUB *s, char *session_name)
+{
+ SM_TABLE t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Hub = s;
+ t.Rpc = s->Rpc;
+ t.SessionName = session_name;
+
+ Dialog(hWnd, D_SM_MAC, SmMacTableDlgProc, &t);
+}
+
+// Initialize
+void SmSessionDlgInit(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_VPN);
+ FormatText(hWnd, 0, s->HubName);
+ FormatText(hWnd, S_TITLE, s->HubName);
+
+ LvInit(hWnd, L_LIST);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_SESS_COLUMN_1"), 176);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_SESS_COLUMN_8"), 58);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_SESS_COLUMN_2"), 62);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_SESS_COLUMN_3"), 78);
+ LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_SESS_COLUMN_4"), 122);
+ LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_SESS_COLUMN_5"), 68);
+ LvInsertColumn(hWnd, L_LIST, 6, _UU("SM_SESS_COLUMN_6"), 100);
+ LvInsertColumn(hWnd, L_LIST, 7, _UU("SM_SESS_COLUMN_7"), 100);
+ LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);
+
+ if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER && GetCapsBool(s->p->CapsList, "b_support_cluster_admin") == false)
+ {
+ Show(hWnd, S_FARM_INFO_1);
+ Show(hWnd, S_FARM_INFO_2);
+ }
+
+ SmSessionDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmSessionDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ bool ok = true;
+ bool ok2 = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_LIST) == false || LvIsMultiMasked(hWnd, L_LIST))
+ {
+ ok = false;
+ ok2 = false;
+ }
+ else
+ {
+ UINT i = LvGetSelected(hWnd, L_LIST);
+ if (i != INFINITE)
+ {
+ void *p = LvGetParam(hWnd, L_LIST, i);
+ if (((bool)p) != false)
+ {
+ if (GetCapsBool(s->p->CapsList, "b_support_cluster_admin") == false)
+ {
+ ok = false;
+ }
+ }
+ }
+ }
+
+ if (s->p->ServerInfo.ServerBuildInt < 2844)
+ {
+ // Old version doen't support for remote management of the sessions
+ ok2 = ok;
+ }
+
+ SetEnable(hWnd, IDOK, ok2);
+ SetEnable(hWnd, B_DISCONNECT, ok2);
+ SetEnable(hWnd, B_SESSION_IP_TABLE, ok);
+ SetEnable(hWnd, B_SESSION_MAC_TABLE, ok);
+}
+
+// Update the list
+void SmSessionDlgRefresh(HWND hWnd, SM_HUB *s)
+{
+ LVB *b;
+ UINT i;
+ wchar_t *old_select;
+ RPC_ENUM_SESSION t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScEnumSession(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ old_select = LvGetSelectedStr(hWnd, L_LIST, 0);
+
+ LvReset(hWnd, L_LIST);
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t *tmp2;
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ wchar_t tmp5[MAX_SIZE];
+ wchar_t tmp6[MAX_SIZE];
+ wchar_t tmp7[MAX_SIZE];
+ wchar_t tmp8[MAX_SIZE];
+ bool free_tmp2 = false;
+ UINT icon;
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+
+ tmp2 = _UU("SM_SESS_NORMAL");
+ icon = ICO_VPN;
+ if (s->p->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ if (e->RemoteSession)
+ {
+ tmp2 = ZeroMalloc(MAX_SIZE);
+ UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_REMOTE"), e->RemoteHostname);
+ icon = ICO_VPN;
+ free_tmp2 = true;
+ }
+ else
+ {
+ if (StrLen(e->RemoteHostname) == 0)
+ {
+ tmp2 = _UU("SM_SESS_LOCAL");
+ }
+ else
+ {
+ tmp2 = ZeroMalloc(MAX_SIZE);
+ UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_LOCAL_2"), e->RemoteHostname);
+ free_tmp2 = true;
+ }
+ }
+ }
+ if (e->LinkMode)
+ {
+ if (free_tmp2)
+ {
+ Free(tmp2);
+ free_tmp2 = false;
+ }
+ tmp2 = _UU("SM_SESS_LINK");
+ icon = ICO_CASCADE;
+ }
+ else if (e->SecureNATMode)
+ {
+ /*if (free_tmp2)
+ {
+ Free(tmp2);
+ free_tmp2 = false;
+ }
+ tmp2 = _UU("SM_SESS_SNAT");*/
+ icon = ICO_ROUTER;
+ }
+ else if (e->BridgeMode)
+ {
+ icon = ICO_BRIDGE;
+ }
+ else if (e->Layer3Mode)
+ {
+ icon = ICO_SWITCH;
+ }
+
+ StrToUni(tmp3, sizeof(tmp3), e->Username);
+
+ StrToUni(tmp4, sizeof(tmp4), e->Hostname);
+ if (e->LinkMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LINK_HOSTNAME"));
+ }
+ else if (e->SecureNATMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_SNAT_HOSTNAME"));
+ }
+ else if (e->BridgeMode)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_BRIDGE_HOSTNAME"));
+ }
+ else if (StartWith(e->Username, L3_USERNAME))
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LAYER3_HOSTNAME"));
+ }
+
+ UniFormat(tmp5, sizeof(tmp5), L"%u / %u", e->CurrentNumTcp, e->MaxNumTcp);
+ if (e->LinkMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_LINK_TCP"));
+ }
+ else if (e->SecureNATMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_SNAT_TCP"));
+ }
+ else if (e->BridgeMode)
+ {
+ UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_BRIDGE_TCP"));
+ }
+
+ if (e->VLanId == 0)
+ {
+ UniStrCpy(tmp8, sizeof(tmp8), _UU("CM_ST_NO_VLAN"));
+ }
+ else
+ {
+ UniToStru(tmp8, e->VLanId);
+ }
+
+ UniToStr3(tmp6, sizeof(tmp6), e->PacketSize);
+ UniToStr3(tmp7, sizeof(tmp7), e->PacketNum);
+
+ if (icon == ICO_VPN)
+ {
+ if (e->Client_BridgeMode)
+ {
+ icon = ICO_SESSION_BRIDGE;
+ }
+ else if (e->Client_MonitorMode)
+ {
+ icon = ICO_SESSION_MONITOR;
+ }
+ }
+
+ LvInsertAdd(b, icon, (void *)(e->RemoteSession), 8, tmp1, tmp8, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
+
+ if (free_tmp2)
+ {
+ Free(tmp2);
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ if (old_select != NULL && UniStrLen(old_select) != 0)
+ {
+ UINT i = LvSearchStr(hWnd, L_LIST, 0, old_select);
+ if (i != INFINITE)
+ {
+ LvSelect(hWnd, L_LIST, i);
+ }
+ }
+
+ Free(old_select);
+
+ FreeRpcEnumSession(&t);
+
+ SmSessionDlgUpdate(hWnd, s);
+}
+
+// Display the NODE_INFO
+void SmPrintNodeInfo(LVB *b, NODE_INFO *info)
+{
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (b == NULL || info == NULL)
+ {
+ return;
+ }
+
+ StrToUni(tmp, sizeof(tmp), info->ClientProductName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_NAME"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", Endian32(info->ClientProductVer) / 100, Endian32(info->ClientProductVer) % 100);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_VER"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"Build %u", Endian32(info->ClientProductBuild));
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_BUILD"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsVer);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_VER"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientOsProductId);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_PID"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ClientHostname);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_HOST"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ClientIpAddress, info->ClientIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ClientPort));
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_PORT"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), info->ServerHostname);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_HOST"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ServerIpAddress, info->ServerIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ServerPort));
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_PORT"), tmp);
+
+ if (StrLen(info->ProxyHostname) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), info->ProxyHostname);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_HOSTNAME"), tmp);
+
+ IPToStr4or6(str, sizeof(str), info->ProxyIpAddress, info->ProxyIpAddress6);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_IP"), tmp);
+
+ UniToStru(tmp, Endian32(info->ProxyPort));
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_PORT"), tmp);
+ }
+}
+
+// Update the session status
+bool SmRefreshSessionStatus(HWND hWnd, SM_SERVER *s, void *param)
+{
+ LVB *b;
+ SM_SESSION_STATUS *status = (SM_SESSION_STATUS *)param;
+ RPC_SESSION_STATUS t;
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), status->Hub->HubName);
+ StrCpy(t.Name, sizeof(t.Name), status->SessionName);
+
+ if (CALL(hWnd, ScGetSessionStatus(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ if (t.ClientIp != 0)
+ {
+ IPToStr4or6(str, sizeof(str), t.ClientIp, t.ClientIp6);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_CLIENT_IP"), tmp);
+ }
+
+ if (StrLen(t.ClientHostName) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.ClientHostName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_CLIENT_HOSTNAME"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), t.Username);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_USERNAME"), tmp);
+
+ if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.RealUsername);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_REALUSER"), tmp);
+ }
+
+ if (IsEmptyStr(t.GroupName) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), t.GroupName);
+ LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_GROUPNAME"), tmp);
+ }
+
+ CmPrintStatusToListViewEx(b, &t.Status, true);
+
+ if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0 &&
+ StartWith(t.Username, L3_USERNAME) == false)
+ {
+ SmPrintNodeInfo(b, &t.NodeInfo);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcSessionStatus(&t);
+
+ return true;
+}
+
+// Session Management dialog procedure
+UINT SmSessionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ wchar_t *tmp;
+ wchar_t tmp2[MAX_SIZE];
+ char name[MAX_SIZE];
+ NMHDR *n;
+ SM_SESSION_STATUS status;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ tmp = LvGetSelectedStr(hWnd, L_LIST, 0);
+ UniToStr(name, sizeof(name), tmp);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmSessionDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (IsEnable(hWnd, IDOK))
+ {
+ // Session status display
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESS_STATUS_CAPTION"), name);
+ Zero(&status, sizeof(status));
+ status.Hub = s;
+ status.SessionName = name;
+ SmStatusDlg(hWnd, s->p, &status, true, true, tmp2, ICO_VPN,
+ NULL, SmRefreshSessionStatus);
+ }
+ break;
+
+ case B_DISCONNECT:
+ // Disconnect
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_SESS_DISCONNECT_MSG"), name) == IDYES)
+ {
+ RPC_DELETE_SESSION t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (CALL(hWnd, ScDeleteSession(s->Rpc, &t)))
+ {
+ SmSessionDlgRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmSessionDlgRefresh(hWnd, s);
+ break;
+
+ case B_SESSION_IP_TABLE:
+ // IP table
+ SmIpTableDlg(hWnd, s, name);
+ break;
+
+ case B_SESSION_MAC_TABLE:
+ // MAC table
+ SmMacTableDlg(hWnd, s, name);
+ break;
+
+ case B_MAC_TABLE:
+ // MAC Table List
+ SmMacTableDlg(hWnd, s, NULL);
+ break;
+
+ case B_IP_TABLE:
+ // IP Table List
+ SmIpTableDlg(hWnd, s, NULL);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ SmSessionDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ Free(tmp);
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Session Management dialog
+void SmSessionDlg(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_SESSION, SmSessionDlgProc, s);
+}
+
+// Certificate List Update
+void SmCaDlgRefresh(HWND hWnd, SM_HUB *s)
+{
+ LVB *b;
+ UINT i;
+ RPC_HUB_ENUM_CA t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScEnumCa(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumCa;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ RPC_HUB_ENUM_CA_ITEM *e = &t.Ca[i];
+
+ GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);
+
+ LvInsertAdd(b, ICO_SERVER_CERT, (void *)e->Key, 3,
+ e->SubjectName, e->IssuerName, tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_CERT);
+
+ FreeRpcHubEnumCa(&t);
+
+ SmCaDlgUpdate(hWnd, s);
+}
+
+// Initialize
+void SmCaDlgInit(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_SERVER_CERT);
+
+ LvInit(hWnd, L_CERT);
+ LvInsertColumn(hWnd, L_CERT, 0, _UU("CM_CERT_COLUMN_1"), 190);
+ LvInsertColumn(hWnd, L_CERT, 1, _UU("CM_CERT_COLUMN_2"), 190);
+ LvInsertColumn(hWnd, L_CERT, 2, _UU("CM_CERT_COLUMN_3"), 160);
+
+ SmCaDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmCaDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, B_DELETE, LvIsSelected(hWnd, L_CERT));
+ SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_CERT));
+}
+
+// OK
+void SmCaDlgOnOk(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+}
+
+// CA Adding dialog
+bool SmCaDlgAdd(HWND hWnd, SM_HUB *s)
+{
+ X *x;
+ RPC_HUB_ADD_CA t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (CmLoadXFromFileOrSecureCard(hWnd, &x) == false)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Cert = x;
+
+ if (CALL(hWnd, ScAddCa(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ FreeRpcHubAddCa(&t);
+
+ return true;
+}
+
+// CA List dialog procedure
+UINT SmCaDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ SM_HUB *s = (SM_HUB *)param;
+ UINT i, key;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmCaDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_IMPORT:
+ // Add
+ if (SmCaDlgAdd(hWnd, s))
+ {
+ SmCaDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_CERT);
+ if (i != INFINITE)
+ {
+ key = (UINT)LvGetParam(hWnd, L_CERT, i);
+ if (key != 0)
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("CM_CERT_DELETE_MSG")) == IDYES)
+ {
+ RPC_HUB_DELETE_CA t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Key = key;
+
+ if (CALL(hWnd, ScDeleteCa(s->Rpc, &t)))
+ {
+ SmCaDlgRefresh(hWnd, s);
+ }
+ }
+ }
+ }
+ break;
+
+ case IDOK:
+ // Display
+ i = LvGetSelected(hWnd, L_CERT);
+ if (i != INFINITE)
+ {
+ key = (UINT)LvGetParam(hWnd, L_CERT, i);
+ if (key != 0)
+ {
+ RPC_HUB_GET_CA t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.Key = key;
+
+ if (CALL(hWnd, ScGetCa(s->Rpc, &t)))
+ {
+ CertDlg(hWnd, t.Cert, NULL, true);
+ FreeRpcHubGetCa(&t);
+ }
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_CERT:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmCaDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_CERT);
+
+ return 0;
+}
+
+// CA List dialog box
+void SmCaDlg(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_CA, SmCaDlgProc, s);
+}
+
+// Initialize
+void SmLogDlgInit(HWND hWnd, SM_HUB *s)
+{
+ RPC_HUB_LOG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_LOG2);
+
+ FormatText(hWnd, S_TITLE, s->HubName);
+
+ CbSetHeight(hWnd, C_SEC_SWITCH, 18);
+ CbSetHeight(hWnd, C_PACKET_SWITCH, 18);
+
+ // Initialize the control
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_0"), 0);
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_1"), 1);
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_2"), 2);
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_3"), 3);
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_4"), 4);
+ CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_5"), 5);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_0"), 0);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_1"), 1);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_2"), 2);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_3"), 3);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_4"), 4);
+ CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_5"), 5);
+
+ // Get the log settings
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScGetHubLog(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ Check(hWnd, B_SEC, t.LogSetting.SaveSecurityLog);
+ CbSelect(hWnd, C_SEC_SWITCH, t.LogSetting.SecurityLogSwitchType);
+
+ Check(hWnd, B_PACKET, t.LogSetting.SavePacketLog);
+ CbSelect(hWnd, C_PACKET_SWITCH, t.LogSetting.PacketLogSwitchType);
+
+ Check(hWnd, B_PACKET_0_0, t.LogSetting.PacketLogConfig[0] == 0);
+ Check(hWnd, B_PACKET_0_1, t.LogSetting.PacketLogConfig[0] == 1);
+ Check(hWnd, B_PACKET_0_2, t.LogSetting.PacketLogConfig[0] == 2);
+
+ Check(hWnd, B_PACKET_1_0, t.LogSetting.PacketLogConfig[1] == 0);
+ Check(hWnd, B_PACKET_1_1, t.LogSetting.PacketLogConfig[1] == 1);
+ Check(hWnd, B_PACKET_1_2, t.LogSetting.PacketLogConfig[1] == 2);
+
+ Check(hWnd, B_PACKET_2_0, t.LogSetting.PacketLogConfig[2] == 0);
+ Check(hWnd, B_PACKET_2_1, t.LogSetting.PacketLogConfig[2] == 1);
+ Check(hWnd, B_PACKET_2_2, t.LogSetting.PacketLogConfig[2] == 2);
+
+ Check(hWnd, B_PACKET_3_0, t.LogSetting.PacketLogConfig[3] == 0);
+ Check(hWnd, B_PACKET_3_1, t.LogSetting.PacketLogConfig[3] == 1);
+ Check(hWnd, B_PACKET_3_2, t.LogSetting.PacketLogConfig[3] == 2);
+
+ Check(hWnd, B_PACKET_4_0, t.LogSetting.PacketLogConfig[4] == 0);
+ Check(hWnd, B_PACKET_4_1, t.LogSetting.PacketLogConfig[4] == 1);
+ Check(hWnd, B_PACKET_4_2, t.LogSetting.PacketLogConfig[4] == 2);
+
+ Check(hWnd, B_PACKET_5_0, t.LogSetting.PacketLogConfig[5] == 0);
+ Check(hWnd, B_PACKET_5_1, t.LogSetting.PacketLogConfig[5] == 1);
+ Check(hWnd, B_PACKET_5_2, t.LogSetting.PacketLogConfig[5] == 2);
+
+ Check(hWnd, B_PACKET_6_0, t.LogSetting.PacketLogConfig[6] == 0);
+ Check(hWnd, B_PACKET_6_1, t.LogSetting.PacketLogConfig[6] == 1);
+ Check(hWnd, B_PACKET_6_2, t.LogSetting.PacketLogConfig[6] == 2);
+
+ Check(hWnd, B_PACKET_7_0, t.LogSetting.PacketLogConfig[7] == 0);
+ Check(hWnd, B_PACKET_7_1, t.LogSetting.PacketLogConfig[7] == 1);
+ Check(hWnd, B_PACKET_7_2, t.LogSetting.PacketLogConfig[7] == 2);
+
+ SmLogDlgUpdate(hWnd, s);
+}
+
+// Update the control
+void SmLogDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ bool b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b = IsChecked(hWnd, B_SEC);
+ SetEnable(hWnd, S_SEC, b);
+ SetEnable(hWnd, C_SEC_SWITCH, b);
+
+ b = IsChecked(hWnd, B_PACKET);
+ SetEnable(hWnd, S_PACKET, b);
+ SetEnable(hWnd, C_PACKET_SWITCH, b);
+ SetEnable(hWnd, S_PACKET_0, b);
+ SetEnable(hWnd, S_PACKET_1, b);
+ SetEnable(hWnd, S_PACKET_2, b);
+ SetEnable(hWnd, S_PACKET_3, b);
+ SetEnable(hWnd, S_PACKET_4, b);
+ SetEnable(hWnd, S_PACKET_5, b);
+ SetEnable(hWnd, S_PACKET_6, b);
+ SetEnable(hWnd, S_PACKET_7, b);
+ SetEnable(hWnd, B_PACKET_0_0, b); SetEnable(hWnd, B_PACKET_0_1, b); SetEnable(hWnd, B_PACKET_0_2, b);
+ SetEnable(hWnd, B_PACKET_1_0, b); SetEnable(hWnd, B_PACKET_1_1, b); SetEnable(hWnd, B_PACKET_1_2, b);
+ SetEnable(hWnd, B_PACKET_2_0, b); SetEnable(hWnd, B_PACKET_2_1, b); SetEnable(hWnd, B_PACKET_2_2, b);
+ SetEnable(hWnd, B_PACKET_3_0, b); SetEnable(hWnd, B_PACKET_3_1, b); SetEnable(hWnd, B_PACKET_3_2, b);
+ SetEnable(hWnd, B_PACKET_4_0, b); SetEnable(hWnd, B_PACKET_4_1, b); SetEnable(hWnd, B_PACKET_4_2, b);
+ SetEnable(hWnd, B_PACKET_5_0, b); SetEnable(hWnd, B_PACKET_5_1, b); SetEnable(hWnd, B_PACKET_5_2, b);
+ SetEnable(hWnd, B_PACKET_6_0, b); SetEnable(hWnd, B_PACKET_6_1, b); SetEnable(hWnd, B_PACKET_6_2, b);
+ SetEnable(hWnd, B_PACKET_7_0, b); SetEnable(hWnd, B_PACKET_7_1, b); SetEnable(hWnd, B_PACKET_7_2, b);
+}
+
+// OK
+void SmLogDlgOnOk(HWND hWnd, SM_HUB *s)
+{
+ HUB_LOG g;
+ RPC_HUB_LOG t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&g, sizeof(g));
+ g.SaveSecurityLog = IsChecked(hWnd, B_SEC);
+ g.SavePacketLog = IsChecked(hWnd, B_PACKET);
+ g.SecurityLogSwitchType = CbGetSelect(hWnd, C_SEC_SWITCH);
+ g.PacketLogSwitchType = CbGetSelect(hWnd, C_PACKET_SWITCH);
+
+ g.PacketLogConfig[0] = IsChecked(hWnd, B_PACKET_0_0) ? 0 : IsChecked(hWnd, B_PACKET_0_1) ? 1 : 2;
+ g.PacketLogConfig[1] = IsChecked(hWnd, B_PACKET_1_0) ? 0 : IsChecked(hWnd, B_PACKET_1_1) ? 1 : 2;
+ g.PacketLogConfig[2] = IsChecked(hWnd, B_PACKET_2_0) ? 0 : IsChecked(hWnd, B_PACKET_2_1) ? 1 : 2;
+ g.PacketLogConfig[3] = IsChecked(hWnd, B_PACKET_3_0) ? 0 : IsChecked(hWnd, B_PACKET_3_1) ? 1 : 2;
+ g.PacketLogConfig[4] = IsChecked(hWnd, B_PACKET_4_0) ? 0 : IsChecked(hWnd, B_PACKET_4_1) ? 1 : 2;
+ g.PacketLogConfig[5] = IsChecked(hWnd, B_PACKET_5_0) ? 0 : IsChecked(hWnd, B_PACKET_5_1) ? 1 : 2;
+ g.PacketLogConfig[6] = IsChecked(hWnd, B_PACKET_6_0) ? 0 : IsChecked(hWnd, B_PACKET_6_1) ? 1 : 2;
+ g.PacketLogConfig[7] = IsChecked(hWnd, B_PACKET_7_0) ? 0 : IsChecked(hWnd, B_PACKET_7_1) ? 1 : 2;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ Copy(&t.LogSetting, &g, sizeof(HUB_LOG));
+
+ if (CALL(hWnd, ScSetHubLog(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// Log storage settings dialog
+UINT SmLogDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmLogDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case B_SEC:
+ case B_PACKET:
+ SmLogDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmLogDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the status of the cascade connection
+bool SmRefreshLinkStatus(HWND hWnd, SM_SERVER *s, void *param)
+{
+ SM_LINK *k = (SM_LINK *)param;
+ RPC_LINK_STATUS t;
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), k->Hub->HubName);
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), k->AccountName);
+
+ if (CALL(hWnd, ScGetLinkStatus(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ CmPrintStatusToListView(b, &t.Status);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcLinkStatus(&t);
+
+ return true;
+}
+
+// Edit the link
+bool SmLinkEdit(HWND hWnd, SM_HUB *s, wchar_t *name)
+{
+ CM_ACCOUNT a;
+ RPC_CREATE_LINK t;
+ bool ret = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), name);
+
+ if (CALL(hWnd, ScGetLink(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ a.Hub = s;
+ a.EditMode = true;
+ a.LinkMode = true;
+ a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ a.OnlineFlag = t.Online;
+ Copy(a.ClientOption, t.ClientOption, sizeof(CLIENT_OPTION));
+ a.ClientAuth = CopyClientAuth(t.ClientAuth);
+ Copy(&a.Policy, &t.Policy, sizeof(POLICY));
+ a.CheckServerCert = t.CheckServerCert;
+ a.ServerCert = CloneX(t.ServerCert);
+ a.HideTrustCert = GetCapsBool(s->p->CapsList, "b_support_config_hub");
+ FreeRpcCreateLink(&t);
+
+ a.PolicyVer = s->p->PolicyVer;
+
+ if (GetCapsBool(s->p->CapsList, "b_support_cascade_client_cert") == false)
+ {
+ a.HideClientCertAuth = true;
+ }
+
+ a.HideSecureAuth = true;
+
+ ret = CmEditAccountDlg(hWnd, &a);
+
+ FreeX(a.ServerCert);
+ Free(a.ClientOption);
+ CiFreeClientAuth(a.ClientAuth);
+
+ return ret;
+}
+
+// Create a new link
+bool SmLinkCreate(HWND hWnd, SM_HUB *s)
+{
+ return SmLinkCreateEx(hWnd, s, false);
+}
+bool SmLinkCreateEx(HWND hWnd, SM_HUB *s, bool connectNow)
+{
+ CM_ACCOUNT a;
+ bool ret = false;;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+
+ a.Hub = s;
+ a.EditMode = false;
+ a.LinkMode = true;
+ a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
+ a.OnlineFlag = false;
+ a.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
+ a.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
+ Copy(&a.Policy, GetDefaultPolicy(), sizeof(POLICY));
+ a.ClientOption->Port = 443; // Default port number
+ a.ClientOption->NumRetry = INFINITE;
+ a.ClientOption->RetryInterval = 15;
+ a.ClientOption->MaxConnection = 8;
+ a.ClientOption->UseEncrypt = true;
+ a.ClientOption->HalfConnection = false;
+ a.ClientOption->AdditionalConnectionInterval = 1;
+ a.ClientOption->RequireBridgeRoutingMode = true;
+ a.Link_ConnectNow = connectNow;
+
+ a.PolicyVer = s->p->PolicyVer;
+
+ if (GetCapsBool(s->p->CapsList, "b_support_cascade_client_cert") == false)
+ {
+ a.HideClientCertAuth = true;
+ }
+
+ a.HideSecureAuth = true;
+
+ ret = CmEditAccountDlg(hWnd, &a);
+
+ FreeX(a.ServerCert);
+ Free(a.ClientOption);
+ CiFreeClientAuth(a.ClientAuth);
+
+ return ret;
+}
+
+// Initialize
+void SmLinkDlgInit(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_LINK);
+
+ FormatText(hWnd, 0, s->HubName);
+
+ LvInit(hWnd, L_LINK);
+
+ LvInsertColumn(hWnd, L_LINK, 0, _UU("SM_LINK_COLUMN_1"), 120);
+ LvInsertColumn(hWnd, L_LINK, 1, _UU("SM_LINK_COLUMN_2"), 150);
+ LvInsertColumn(hWnd, L_LINK, 2, _UU("SM_LINK_COLUMN_3"), 180);
+ LvInsertColumn(hWnd, L_LINK, 3, _UU("SM_LINK_COLUMN_4"), 130);
+ LvInsertColumn(hWnd, L_LINK, 4, _UU("SM_LINK_COLUMN_5"), 130);
+
+ LvSetStyle(hWnd, L_LINK, LVS_EX_GRIDLINES);
+
+ SmLinkDlgRefresh(hWnd, s);
+}
+
+// Update the controls
+void SmLinkDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ bool ok = true;
+ bool online = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_LINK) == false || LvIsMultiMasked(hWnd, L_LINK))
+ {
+ ok = false;
+ }
+ else
+ {
+ online = (bool)LvGetParam(hWnd, L_LINK, LvGetSelected(hWnd, L_LINK));
+ }
+
+ SetEnable(hWnd, B_EDIT, ok);
+ SetEnable(hWnd, B_ONLINE, ok && (online == false));
+ SetEnable(hWnd, B_OFFLINE, ok && online);
+ SetEnable(hWnd, IDOK, ok && online);
+ SetEnable(hWnd, B_DELETE, ok);
+ SetEnable(hWnd, B_RENAME, ok);
+}
+
+// Content update
+void SmLinkDlgRefresh(HWND hWnd, SM_HUB *s)
+{
+ LVB *b;
+ RPC_ENUM_LINK t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScEnumLink(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumLink;i++)
+ {
+ RPC_ENUM_LINK_ITEM *e = &t.Links[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp4[MAX_SIZE];
+ UINT icon = ICO_CASCADE;
+
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);
+ StrToUni(tmp2, sizeof(tmp2), e->Hostname);
+ StrToUni(tmp3, sizeof(tmp3), e->HubName);
+
+ if (e->Online == false)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_OFFLINE"));
+ }
+ else
+ {
+ if (e->Connected)
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ONLINE"));
+ }
+ else
+ {
+ if (e->LastError != 0)
+ {
+ UniFormat(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ERROR"), e->LastError, _E(e->LastError));
+ }
+ else
+ {
+ UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_CONNECTING"));
+ }
+ }
+ }
+
+ if (e->Online == false)
+ {
+ icon = ICO_CASCADE_OFFLINE;
+ }
+ else
+ {
+ if (e->Connected == false && e->LastError != 0)
+ {
+ icon = ICO_CASCADE_ERROR;
+ }
+ else
+ {
+ icon = ICO_CASCADE;
+ }
+ }
+
+ LvInsertAdd(b,
+ icon, (void *)e->Online, 5,
+ e->AccountName, tmp4, tmp1, tmp2, tmp3);
+ }
+
+ LvInsertEnd(b, hWnd, L_LINK);
+
+ FreeRpcEnumLink(&t);
+
+ SmLinkDlgUpdate(hWnd, s);
+}
+
+
+// Link List dialog procedure
+UINT SmLinkDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ wchar_t *str;
+ NMHDR *n;
+ NMLVDISPINFOW *disp_info;
+ NMLVKEYDOWN *key;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ str = LvGetSelectedStr(hWnd, L_LINK, 0);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmLinkDlgInit(hWnd, s);
+
+ if (link_create_now)
+ {
+ if (SmLinkCreateEx(hWnd, s, true))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+
+ SetTimer(hWnd, 1, 1000, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (IsEnable(hWnd, 0))
+ {
+ KillTimer(hWnd, 1);
+ SmLinkDlgRefresh(hWnd, s);
+ SetTimer(hWnd, 1, 1000, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_CREATE:
+ // Create new
+ if (SmLinkCreate(hWnd, s))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_EDIT:
+ // Edit
+ if (str != NULL)
+ {
+ if (SmLinkEdit(hWnd, s, str))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_ONLINE:
+ // Online
+ if (str != NULL)
+ {
+ RPC_LINK t;
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), str);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScSetLinkOnline(s->Rpc, &t)))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_OFFLINE:
+ // Offline
+ if (str != NULL)
+ {
+ RPC_LINK t;
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), str);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_LINK_OFFLINE_MSG"), t.AccountName) == IDYES)
+ {
+ if (CALL(hWnd, ScSetLinkOffline(s->Rpc, &t)))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+ }
+ break;
+
+ case IDOK:
+ // Status
+ if (str != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ SM_LINK t;
+ Zero(&t, sizeof(t));
+ t.Hub = s;
+ t.AccountName = str;
+ UniFormat(tmp, sizeof(tmp), _UU("SM_LINK_STATUS_CAPTION"), str);
+ SmStatusDlg(hWnd, s->p, &t, true, true, tmp,
+ ICO_CASCADE, NULL, SmRefreshLinkStatus);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ if (str != NULL)
+ {
+ RPC_LINK t;
+ Zero(&t, sizeof(t));
+ UniStrCpy(t.AccountName, sizeof(t.AccountName), str);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_LINK_DELETE_MSG"), t.AccountName) == IDYES)
+ {
+ if (CALL(hWnd, ScDeleteLink(s->Rpc, &t)))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+ }
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmLinkDlgRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case B_RENAME:
+ // Change the name
+ Focus(hWnd, L_LINK);
+ LvRename(hWnd, L_LINK, LvGetSelected(hWnd, L_LINK));
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LINK:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ // Change the selection state
+ SmLinkDlgUpdate(hWnd, s);
+ break;
+
+ case LVN_ENDLABELEDITW:
+ // Change the name
+ disp_info = (NMLVDISPINFOW *)n;
+ if (disp_info->item.pszText != NULL)
+ {
+ wchar_t *new_name = disp_info->item.pszText;
+ wchar_t *old_name = LvGetStr(hWnd, L_LINK, disp_info->item.iItem, 0);
+
+ if (old_name != NULL)
+ {
+ if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)
+ {
+ RPC_RENAME_LINK t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ UniStrCpy(t.OldAccountName, sizeof(t.OldAccountName), old_name);
+ UniStrCpy(t.NewAccountName, sizeof(t.NewAccountName), new_name);
+ if (CALL(hWnd, ScRenameLink(s->Rpc, &t)))
+ {
+ SmLinkDlgRefresh(hWnd, s);
+ }
+ }
+
+ Free(old_name);
+ }
+ }
+ break;
+
+ case LVN_KEYDOWN:
+ // Keypress
+ key = (NMLVKEYDOWN *)n;
+ if (key != NULL)
+ {
+ bool ctrl, alt;
+ UINT code = key->wVKey;
+ ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
+ alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
+
+ if (code == VK_F2)
+ {
+ Command(hWnd, B_RENAME);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ Free(str);
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LINK);
+
+ return 0;
+}
+
+// Link List dialog
+void SmLinkDlg(HWND hWnd, SM_HUB *s)
+{
+ SmLinkDlgEx(hWnd, s, false);
+}
+void SmLinkDlgEx(HWND hWnd, SM_HUB *s, bool createNow)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ link_create_now = createNow;
+
+ Dialog(hWnd, D_SM_LINK, SmLinkDlgProc, s);
+}
+
+// Initialize
+void SmRadiusDlgInit(HWND hWnd, SM_HUB *s)
+{
+ RPC_RADIUS t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_TOWER);
+
+ FormatText(hWnd, S_TITLE, s->HubName);
+ FormatText(hWnd, S_RADIUS_7, RADIUS_RETRY_INTERVAL, RADIUS_RETRY_TIMEOUT);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (CALL(hWnd, ScGetHubRadius(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ Check(hWnd, R_USE_RADIUS, StrLen(t.RadiusServerName) != 0);
+
+ if (StrLen(t.RadiusServerName) != 0)
+ {
+ SetTextA(hWnd, E_HOSTNAME, t.RadiusServerName);
+ SetIntEx(hWnd, E_PORT, t.RadiusPort);
+ SetTextA(hWnd, E_SECRET1, t.RadiusSecret);
+ SetTextA(hWnd, E_SECRET2, t.RadiusSecret);
+ SetIntEx(hWnd, E_RADIUS_RETRY_INTERVAL, t.RadiusRetryInterval);
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+ else
+ {
+ SetInt(hWnd, E_PORT, RADIUS_DEFAULT_PORT);
+ SetInt(hWnd, E_RADIUS_RETRY_INTERVAL, RADIUS_RETRY_INTERVAL);
+ }
+
+ SmRadiusDlgUpdate(hWnd, s);
+}
+
+// Update the control
+void SmRadiusDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ bool ok = true;
+ bool b, b1;
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b1 = GetCapsBool(s->p->CapsList, "b_support_radius_retry_interval_and_several_servers");
+ if(b1 == false)
+ {
+ Hide(hWnd, S_RADIUS_7);
+ Hide(hWnd, S_RADIUS_8);
+ Hide(hWnd, S_RADIUS_9);
+ Hide(hWnd, E_RADIUS_RETRY_INTERVAL);
+ }
+
+ b = IsChecked(hWnd, R_USE_RADIUS);
+
+ SetEnable(hWnd, S_RADIUS_1, b);
+ SetEnable(hWnd, S_RADIUS_2, b);
+ SetEnable(hWnd, S_RADIUS_3, b);
+ SetEnable(hWnd, S_RADIUS3, b);
+ SetEnable(hWnd, S_RADIUS_4, b);
+ SetEnable(hWnd, S_RADIUS_5, b);
+ SetEnable(hWnd, S_RADIUS_6, b);
+ SetEnable(hWnd, S_RADIUS_7, b);
+ SetEnable(hWnd, S_RADIUS_8, b);
+ SetEnable(hWnd, S_RADIUS_9, b);
+ SetEnable(hWnd, E_HOSTNAME, b);
+ SetEnable(hWnd, E_PORT, b);
+ SetEnable(hWnd, E_SECRET1, b);
+ SetEnable(hWnd, E_SECRET2, b);
+ SetEnable(hWnd, E_RADIUS_RETRY_INTERVAL, b);
+
+ if (b)
+ {
+ UINT p, m;
+ GetTxtA(hWnd, E_SECRET1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_SECRET2, tmp2, sizeof(tmp2));
+
+ if (StrCmp(tmp1, tmp2) != 0)
+ {
+ ok = false;
+ }
+
+ if (IsEmpty(hWnd, E_HOSTNAME))
+ {
+ ok = false;
+ }
+
+ p = GetInt(hWnd, E_PORT);
+
+ if (p == 0 || p >= 65536)
+ {
+ ok = false;
+ }
+
+ m = GetInt(hWnd, E_RADIUS_RETRY_INTERVAL);
+ if (m > RADIUS_RETRY_TIMEOUT || m < RADIUS_RETRY_INTERVAL)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// [OK] button
+void SmRadiusDlgOnOk(HWND hWnd, SM_HUB *s)
+{
+ RPC_RADIUS t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+
+ if (IsChecked(hWnd, R_USE_RADIUS))
+ {
+ GetTxtA(hWnd, E_HOSTNAME, t.RadiusServerName, sizeof(t.RadiusServerName));
+ t.RadiusPort = GetInt(hWnd, E_PORT);
+ GetTxtA(hWnd, E_SECRET1,t.RadiusSecret, sizeof(t.RadiusSecret));
+ t.RadiusRetryInterval = GetInt(hWnd, E_RADIUS_RETRY_INTERVAL);
+ }
+
+ if (CALL(hWnd, ScSetHubRadius(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ EndDialog(hWnd, true);
+}
+
+
+// Radius dialog procedure
+UINT SmRadiusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmRadiusDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_HOSTNAME:
+ case E_PORT:
+ case E_SECRET1:
+ case E_SECRET2:
+ case E_RADIUS_RETRY_INTERVAL:
+ case R_USE_RADIUS:
+ SmRadiusDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmRadiusDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_USE_RADIUS:
+ if (IsChecked(hWnd, R_USE_RADIUS))
+ {
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Radius Setup dialog
+void SmRadiusDlg(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_RADIUS, SmRadiusDlgProc, s);
+}
+
+
+// Initialize
+void SmEditAccessInit(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ ACCESS *a;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_PASS);
+
+ GetTxt(hWnd, 0, tmp, sizeof(tmp));
+
+ UniStrCat(tmp, sizeof(tmp), s->Access->IsIPv6 ? L" (IPv6)" : L" (IPv4)");
+
+ SetText(hWnd, 0, tmp);
+
+ s->Inited = false;
+ a = s->Access;
+
+ SetText(hWnd, E_NOTE, a->Note);
+
+ Check(hWnd, R_DISCARD, a->Discard);
+ Check(hWnd, R_PASS, a->Discard == false);
+ SetIntEx(hWnd, E_PRIORITY, a->Priority);
+
+ if (a->IsIPv6 == false)
+ {
+ // IPv4
+ if (a->SrcIpAddress == 0 && a->SrcSubnetMask == 0)
+ {
+ Check(hWnd, R_SRC_ALL, true);
+ }
+ else
+ {
+ IpSet(hWnd, E_SRC_IP, a->SrcIpAddress);
+ IpSet(hWnd, E_SRC_MASK, a->SrcSubnetMask);
+ }
+
+ if (a->DestIpAddress == 0 && a->DestSubnetMask == 0)
+ {
+ Check(hWnd, R_DST_ALL, true);
+ }
+ else
+ {
+ IpSet(hWnd, E_DST_IP, a->DestIpAddress);
+ IpSet(hWnd, E_DST_MASK, a->DestSubnetMask);
+ }
+ }
+ else
+ {
+ // IPv6
+ if (IsZeroIP6Addr(&a->SrcIpAddress6) && IsZeroIP6Addr(&a->SrcSubnetMask6))
+ {
+ Check(hWnd, R_SRC_ALL, true);
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ IP6AddrToStr(tmp, sizeof(tmp), &a->SrcIpAddress6);
+ SetTextA(hWnd, E_SRC_IP_V6, tmp);
+
+ Mask6AddrToStrEx(tmp, sizeof(tmp), &a->SrcSubnetMask6, false);
+
+ if (IsNum(tmp))
+ {
+ StrCatLeft(tmp, sizeof(tmp), "/");
+ }
+
+ SetTextA(hWnd, E_SRC_MASK_V6, tmp);
+ }
+
+ if (IsZeroIP6Addr(&a->DestIpAddress6) && IsZeroIP6Addr(&a->DestSubnetMask6))
+ {
+ Check(hWnd, R_DST_ALL, true);
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ IP6AddrToStr(tmp, sizeof(tmp), &a->DestIpAddress6);
+ SetTextA(hWnd, E_DST_IP_V6, tmp);
+
+ Mask6AddrToStrEx(tmp, sizeof(tmp), &a->DestSubnetMask6, false);
+
+ if (IsNum(tmp))
+ {
+ StrCatLeft(tmp, sizeof(tmp), "/");
+ }
+
+ SetTextA(hWnd, E_DST_MASK_V6, tmp);
+ }
+ }
+
+ CbSetHeight(hWnd, C_PROTOCOL, 18);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_1"), 0);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_2"), 0);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_3"), 0);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_4"), 0);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_5"), 0);
+ CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_6"), 0);
+
+ switch (a->Protocol)
+ {
+ case 0:
+ CbSelectIndex(hWnd, C_PROTOCOL, 0);
+ break;
+ case 6:
+ CbSelectIndex(hWnd, C_PROTOCOL, 1);
+ break;
+ case 17:
+ CbSelectIndex(hWnd, C_PROTOCOL, 2);
+ break;
+ case 1:
+ CbSelectIndex(hWnd, C_PROTOCOL, 3);
+ break;
+ case 58:
+ CbSelectIndex(hWnd, C_PROTOCOL, 4);
+ break;
+ default:
+ CbSelectIndex(hWnd, C_PROTOCOL, 5);
+ break;
+ }
+
+ SetIntEx(hWnd, E_IP_PROTO, a->Protocol);
+
+ SetIntEx(hWnd, E_SRC_PORT_1, a->SrcPortStart);
+ SetIntEx(hWnd, E_SRC_PORT_2, a->SrcPortEnd);
+ SetIntEx(hWnd, E_DST_PORT_1, a->DestPortStart);
+ SetIntEx(hWnd, E_DST_PORT_2, a->DestPortEnd);
+
+ SetTextA(hWnd, E_USERNAME1, a->SrcUsername);
+ SetTextA(hWnd, E_USERNAME2, a->DestUsername);
+
+ if(a->CheckSrcMac != false)
+ {
+ char mac[MAX_SIZE], mask[MAX_SIZE];
+ MacToStr(mac, sizeof(mac), a->SrcMacAddress);
+ MacToStr(mask, sizeof(mask), a->SrcMacMask);
+ SetTextA(hWnd, E_SRC_MAC, mac);
+ SetTextA(hWnd, E_SRC_MAC_MASK, mask);
+ }
+ if(a->CheckDstMac != false)
+ {
+ char mac[MAX_SIZE], mask[MAX_SIZE];
+ MacToStr(mac, sizeof(mac), a->DstMacAddress);
+ MacToStr(mask, sizeof(mask), a->DstMacMask);
+ SetTextA(hWnd, E_DST_MAC, mac);
+ SetTextA(hWnd, E_DST_MAC_MASK, mask);
+ }
+ Check(hWnd, R_CHECK_SRC_MAC, !a->CheckSrcMac);
+ Check(hWnd, R_CHECK_DST_MAC, !a->CheckDstMac);
+
+ Check(hWnd, R_CHECK_TCP_STATE, a->CheckTcpState);
+ if(a->CheckTcpState != false)
+ {
+ Check(hWnd, R_ESTABLISHED, a->Established);
+ Check(hWnd, R_UNESTABLISHED, !a->Established);
+ }
+
+ if (GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group") == false)
+ {
+ SetText(hWnd, S_STATIC11, _UU("D_SM_EDIT_ACCESS@STATIC11_OLD"));
+ SetText(hWnd, S_STATIC12, _UU("D_SM_EDIT_ACCESS@STATIC12_OLD"));
+ SetText(hWnd, S_STATIC15, _UU("D_SM_EDIT_ACCESS@STATIC15_OLD"));
+ }
+
+ SetEnable(hWnd, R_REDIRECT, GetCapsBool(s->Hub->p->CapsList, "b_support_redirect_url_acl"));
+ Check(hWnd, R_REDIRECT, (IsEmptyStr(a->RedirectUrl) ? false : true));
+
+ s->Inited = true;
+
+ SmEditAccessUpdate(hWnd, s);
+}
+
+// HTTP Redirection Settings dialog
+void SmRedirect(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_REDIRECT, SmRedirectDlg, s);
+}
+UINT SmRedirectDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_ACCESS *s = (SM_EDIT_ACCESS *)param;
+ char tmp[MAX_REDIRECT_URL_LEN + 1];
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmRedirectDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_URL:
+ SmRedirectDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_URL, tmp, sizeof(tmp));
+
+ if (StartWith(tmp, "http://") == false &&
+ StartWith(tmp, "https://") == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_ADVANCED_REDIRECT_URL_MSG"));
+
+ FocusEx(hWnd, E_URL);
+ break;
+ }
+
+ StrCpy(s->Access->RedirectUrl, sizeof(s->Access->RedirectUrl), tmp);
+
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_HINT:
+ OnceMsg(hWnd, _UU("SM_ADVANCED_REDIRECT_URL_HINT_TITLE"),
+ _UU("SM_ADVANCED_REDIRECT_URL_HINT"), false, ICO_INTERNET);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+void SmRedirectDlgInit(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ a = s->Access;
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+ DlgFont(hWnd, S_BOLD2, 0, true);
+
+ SetFont(hWnd, E_SAMPLE1, GetFont("Verdana", 0, false, false, false, false));
+ SetFont(hWnd, E_SAMPLE2, GetFont("Verdana", 0, false, false, false, false));
+ SetFont(hWnd, E_URL, GetFont("Verdana", 10, false, false, false, false));
+
+ SetTextA(hWnd, E_SAMPLE1, "http://www.google.com/about/");
+ SetTextA(hWnd, E_SAMPLE2, "http://www.google.com/search?q=<INFO>|secret");
+
+ SetTextA(hWnd, E_URL, s->Access->RedirectUrl);
+
+ if (IsEmpty(hWnd, E_URL))
+ {
+ SetTextA(hWnd, E_URL, "http://");
+
+ SetCursorOnRight(hWnd, E_URL);
+ Focus(hWnd, E_URL);
+ }
+ else
+ {
+ FocusEx(hWnd, E_URL);
+ }
+
+ SmRedirectDlgUpdate(hWnd, s);
+}
+void SmRedirectDlgUpdate(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ char tmp[MAX_REDIRECT_URL_LEN + 1];
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_URL, tmp, sizeof(tmp));
+
+ if (IsEmptyStr(tmp))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Update the control
+void SmEditAccessUpdate(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ bool ok = true;
+ bool tcp;
+ bool b;
+ bool check_srcmac, check_dstmac, support_mac;
+ bool check_state, support_check_state;
+ char srcmac[MAX_SIZE], srcmac_mask[MAX_SIZE], dstmac[MAX_SIZE], dstmac_mask[MAX_SIZE];
+ char tmp[MAX_SIZE];
+ wchar_t unitmp[MAX_SIZE];
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->Inited == false)
+ {
+ return;
+ }
+
+ a = s->Access;
+
+ GetTxt(hWnd, E_NOTE, a->Note, sizeof(a->Note));
+
+ a->Discard = IsChecked(hWnd, R_DISCARD);
+
+ a->Priority = GetInt(hWnd, E_PRIORITY);
+ if (a->Priority == 0)
+ {
+ ok = false;
+ }
+
+
+ b = IsChecked(hWnd, R_SRC_ALL) ? false : true;
+ if (b == false)
+ {
+ if (a->IsIPv6 == false)
+ {
+ a->SrcIpAddress = 0;
+ a->SrcSubnetMask = 0;
+ }
+ else
+ {
+ Zero(&a->SrcIpAddress6, sizeof(IPV6_ADDR));
+ Zero(&a->SrcSubnetMask6, sizeof(IPV6_ADDR));
+ }
+ }
+ else
+ {
+ if (a->IsIPv6 == false)
+ {
+ if (IpIsFilled(hWnd, E_SRC_IP) == false || IpIsFilled(hWnd, E_SRC_MASK) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ a->SrcIpAddress = IpGet(hWnd, E_SRC_IP);
+ a->SrcSubnetMask = IpGet(hWnd, E_SRC_MASK);
+ }
+ }
+ else
+ {
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+
+ GetTxtA(hWnd, E_SRC_IP_V6, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_SRC_MASK_V6, tmp2, sizeof(tmp2));
+
+ if (StrToIP6Addr(&a->SrcIpAddress6, tmp1) == false ||
+ StrToMask6Addr(&a->SrcSubnetMask6, tmp2) == false)
+ {
+ ok = false;
+ }
+ }
+ }
+ SetEnable(hWnd, S_SRC_IP_1, b);
+ SetEnable(hWnd, S_SRC_IP_2, b);
+ SetEnable(hWnd, S_SRC_IP_3, b);
+ SetEnable(hWnd, E_SRC_IP, b);
+ SetEnable(hWnd, E_SRC_MASK, b);
+ SetEnable(hWnd, E_SRC_IP_V6, b);
+ SetEnable(hWnd, E_SRC_MASK_V6, b);
+
+ b = IsChecked(hWnd, R_DST_ALL) ? false : true;
+ if (b == false)
+ {
+ if (a->IsIPv6 == false)
+ {
+ a->DestIpAddress = 0;
+ a->DestSubnetMask = 0;
+ }
+ else
+ {
+ Zero(&a->DestIpAddress6, sizeof(IPV6_ADDR));
+ Zero(&a->DestSubnetMask6, sizeof(IPV6_ADDR));
+ }
+ }
+ else
+ {
+ if (a->IsIPv6 == false)
+ {
+ if (IpIsFilled(hWnd, E_DST_IP) == false || IpIsFilled(hWnd, E_DST_MASK) == false)
+ {
+ ok = false;
+ }
+ else
+ {
+ a->DestIpAddress = IpGet(hWnd, E_DST_IP);
+ a->DestSubnetMask = IpGet(hWnd, E_DST_MASK);
+ }
+ }
+ else
+ {
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+
+ GetTxtA(hWnd, E_DST_IP_V6, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_DST_MASK_V6, tmp2, sizeof(tmp2));
+
+ if (StrToIP6Addr(&a->DestIpAddress6, tmp1) == false ||
+ StrToMask6Addr(&a->DestSubnetMask6, tmp2) == false)
+ {
+ ok = false;
+ }
+ }
+ }
+ SetEnable(hWnd, S_IP_DST_1, b);
+ SetEnable(hWnd, S_IP_DST_2, b);
+ SetEnable(hWnd, S_IP_DST_3, b);
+ SetEnable(hWnd, E_DST_IP, b);
+ SetEnable(hWnd, E_DST_MASK, b);
+ SetEnable(hWnd, E_DST_IP_V6, b);
+ SetEnable(hWnd, E_DST_MASK_V6, b);
+
+ a->Protocol = GetInt(hWnd, C_PROTOCOL);
+
+ GetTxtA(hWnd, C_PROTOCOL, tmp, sizeof(tmp));
+ GetTxt(hWnd, C_PROTOCOL, unitmp, sizeof(unitmp));
+
+ if (UniStrCmpi(unitmp, _UU("SM_ACCESS_PROTO_6")) == 0 || StrCmpi(tmp, _SS("SM_ACCESS_PROTO_6")) == 0)
+ {
+ a->Protocol = GetInt(hWnd, E_IP_PROTO);
+
+ if (IsEmpty(hWnd, E_IP_PROTO))
+ {
+ ok = false;
+ }
+
+ Enable(hWnd, S_PROTOID);
+ Enable(hWnd, E_IP_PROTO);
+ }
+ else
+ {
+ Disable(hWnd, E_IP_PROTO);
+ Disable(hWnd, S_PROTOID);
+ }
+
+ tcp = false;
+ if (a->Protocol == 17 || a->Protocol == 6)
+ {
+ tcp = true;
+ }
+
+ SetEnable(hWnd, S_TCP_1, tcp);
+ SetEnable(hWnd, S_TCP_2, tcp);
+ SetEnable(hWnd, S_TCP_3, tcp);
+ SetEnable(hWnd, S_TCP_4, tcp);
+ SetEnable(hWnd, S_TCP_5, tcp);
+ SetEnable(hWnd, S_TCP_6, tcp);
+ SetEnable(hWnd, S_TCP_7, tcp);
+ SetEnable(hWnd, E_SRC_PORT_1, tcp);
+ SetEnable(hWnd, E_SRC_PORT_2, tcp);
+ SetEnable(hWnd, E_DST_PORT_1, tcp);
+ SetEnable(hWnd, E_DST_PORT_2, tcp);
+
+ if (tcp == false)
+ {
+ a->SrcPortEnd = a->SrcPortStart = a->DestPortEnd = a->DestPortStart = 0;
+ }
+ else
+ {
+ a->SrcPortStart = GetInt(hWnd, E_SRC_PORT_1);
+ a->SrcPortEnd = GetInt(hWnd, E_SRC_PORT_2);
+ a->DestPortStart = GetInt(hWnd, E_DST_PORT_1);
+ a->DestPortEnd = GetInt(hWnd, E_DST_PORT_2);
+
+ if (a->SrcPortStart != 0)
+ {
+ if (a->SrcPortEnd != 0)
+ {
+ if (a->SrcPortStart > a->SrcPortEnd)
+ {
+ ok = false;
+ }
+ }
+ }
+ else
+ {
+ if (a->SrcPortEnd != 0)
+ {
+ ok = false;
+ }
+ }
+
+ if (a->DestPortStart != 0)
+ {
+ if (a->DestPortEnd != 0)
+ {
+ if (a->DestPortStart > a->DestPortEnd)
+ {
+ ok = false;
+ }
+ }
+ }
+ else
+ {
+ if (a->DestPortEnd != 0)
+ {
+ ok = false;
+ }
+ }
+
+ if (a->DestPortEnd < a->DestPortStart)
+ {
+ a->DestPortEnd = a->DestPortStart;
+ }
+
+ if (a->SrcPortEnd < a->SrcPortStart)
+ {
+ a->SrcPortEnd = a->SrcPortStart;
+ }
+ }
+
+ a->SrcUsernameHash = a->DestUsernameHash = 0;
+ GetTxtA(hWnd, E_USERNAME1, a->SrcUsername, sizeof(a->SrcUsername));
+ GetTxtA(hWnd, E_USERNAME2, a->DestUsername, sizeof(a->DestUsername));
+
+ if (StartWith(a->SrcUsername, ACCESS_LIST_INCLUDED_PREFIX) == false &&
+ StartWith(a->SrcUsername, ACCESS_LIST_EXCLUDED_PREFIX) == false)
+ {
+ MakeSimpleUsernameRemoveNtDomain(a->SrcUsername, sizeof(a->SrcUsername), a->SrcUsername);
+ }
+
+ if (StartWith(a->DestUsername, ACCESS_LIST_INCLUDED_PREFIX) == false &&
+ StartWith(a->DestUsername, ACCESS_LIST_EXCLUDED_PREFIX) == false)
+ {
+ MakeSimpleUsernameRemoveNtDomain(a->DestUsername, sizeof(a->DestUsername), a->DestUsername);
+ }
+
+ Trim(a->SrcUsername);
+ /*
+ if (StrLen(a->SrcUsername) != 0)
+ {
+ if (IsUserName(a->SrcUsername) == false)
+ {
+ ok = false;
+ }
+ }*/
+
+ Trim(a->DestUsername);
+ /*
+ if (StrLen(a->DestUsername) != 0)
+ {
+ if (IsUserName(a->DestUsername) == false)
+ {
+ ok = false;
+ }
+ }*/
+
+ support_mac = GetCapsBool(s->Hub->p->CapsList, "b_support_check_mac");
+
+ // Set the source MAC address
+ check_srcmac = a->CheckSrcMac = support_mac && (IsChecked(hWnd, R_CHECK_SRC_MAC) ? false : true);
+ if(check_srcmac == false)
+ {
+ Zero(a->SrcMacAddress, sizeof(a->SrcMacAddress));
+ Zero(a->SrcMacMask, sizeof(a->SrcMacMask));
+ }
+ else
+ {
+ GetTxtA(hWnd, E_SRC_MAC, srcmac, sizeof(srcmac));
+ GetTxtA(hWnd, E_SRC_MAC_MASK, srcmac_mask, sizeof(srcmac_mask));
+ Trim(srcmac);
+ Trim(srcmac_mask);
+ if(StrLen(srcmac) != 0 && StrLen(srcmac_mask) != 0)
+ {
+ UCHAR mac[6], mask[6];
+ if(StrToMac(mac, srcmac) && StrToMac(mask, srcmac_mask))
+ {
+ Copy(a->SrcMacAddress, mac, 6);
+ Copy(a->SrcMacMask, mask, 6);
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+ SetEnable(hWnd, S_CHECK_SRC_MAC, support_mac);
+ SetEnable(hWnd, R_CHECK_SRC_MAC, support_mac);
+ SetEnable(hWnd, S_SRC_MAC, check_srcmac);
+ SetEnable(hWnd, S_SRC_MAC_MASK, check_srcmac);
+ SetEnable(hWnd, E_SRC_MAC, check_srcmac);
+ SetEnable(hWnd, E_SRC_MAC_MASK, check_srcmac);
+
+ // Set the destination MAC address
+ check_dstmac = a->CheckDstMac = support_mac && (IsChecked(hWnd, R_CHECK_DST_MAC) ? false : true);
+ if(check_dstmac == false)
+ {
+ Zero(a->DstMacAddress, sizeof(a->DstMacAddress));
+ Zero(a->DstMacMask, sizeof(a->DstMacMask));
+ }
+ else
+ {
+ GetTxtA(hWnd, E_DST_MAC, dstmac, sizeof(dstmac));
+ GetTxtA(hWnd, E_DST_MAC_MASK, dstmac_mask, sizeof(dstmac_mask));
+ Trim(dstmac);
+ Trim(dstmac_mask);
+ if(StrLen(dstmac) != 0 && StrLen(dstmac_mask) != 0)
+ {
+ UCHAR mac[6], mask[6];
+ if(StrToMac(mac, dstmac) && StrToMac(mask, dstmac_mask))
+ {
+ Copy(a->DstMacAddress, mac, 6);
+ Copy(a->DstMacMask, mask, 6);
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+ SetEnable(hWnd, S_CHECK_DST_MAC, support_mac);
+ SetEnable(hWnd, R_CHECK_DST_MAC, support_mac);
+ SetEnable(hWnd, S_DST_MAC, check_dstmac);
+ SetEnable(hWnd, S_DST_MAC_MASK, check_dstmac);
+ SetEnable(hWnd, E_DST_MAC, check_dstmac);
+ SetEnable(hWnd, E_DST_MAC_MASK, check_dstmac);
+
+ SetEnable(hWnd, S_MAC_NOTE, check_srcmac || check_dstmac);
+
+ // Status of the TCP connection
+ support_check_state = GetCapsBool(s->Hub->p->CapsList, "b_support_check_tcp_state") && a->Protocol == 6;
+ SetEnable(hWnd, R_CHECK_TCP_STATE, support_check_state);
+ check_state = a->CheckTcpState = support_check_state && IsChecked(hWnd, R_CHECK_TCP_STATE);
+
+ a->Established = IsChecked(hWnd, R_ESTABLISHED) && check_state;
+ SetEnable(hWnd, R_ESTABLISHED, check_state);
+ SetEnable(hWnd, R_UNESTABLISHED, check_state);
+ if(check_state != false && IsChecked(hWnd, R_ESTABLISHED) == false && IsChecked(hWnd, R_UNESTABLISHED) == false)
+ {
+ ok = false;
+ }
+
+ // Settings button such as delay
+ SetEnable(hWnd, B_SIMULATION, a->Discard == false && GetCapsBool(s->Hub->p->CapsList, "b_support_ex_acl"));
+
+ // HTTP redirection settings button
+ SetEnable(hWnd, B_REDIRECT, IsChecked(hWnd, R_REDIRECT) && (a->Discard == false) && GetCapsBool(s->Hub->p->CapsList, "b_support_redirect_url_acl"));
+ SetEnable(hWnd, R_REDIRECT, (a->Discard == false) && GetCapsBool(s->Hub->p->CapsList, "b_support_redirect_url_acl"));
+
+ if (IsChecked(hWnd, R_REDIRECT) && (a->Discard == false) && GetCapsBool(s->Hub->p->CapsList, "b_support_redirect_url_acl"))
+ {
+ if (IsEmptyStr(a->RedirectUrl))
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// OK Click
+void SmEditAccessOnOk(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ a = s->Access;
+
+ SmEditAccessUpdate(hWnd, s);
+
+ if (IsChecked(hWnd, R_REDIRECT) == false || (a->Discard) || GetCapsBool(s->Hub->p->CapsList, "b_support_redirect_url_acl") == false)
+ {
+ // Disable the HTTP redirection
+ ClearStr(a->RedirectUrl, sizeof(a->RedirectUrl));
+ }
+
+ EndDialog(hWnd, true);
+}
+
+
+// Access list editing dialog
+UINT SmEditAccessDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_ACCESS *s = (SM_EDIT_ACCESS *)param;
+ UINT ico;
+ ACCESS *a;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmEditAccessInit(hWnd, s);
+
+ goto REFRESH_ICON;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_PASS:
+ case R_DISCARD:
+ case E_PRIORITY:
+ case R_SRC_ALL:
+ case E_SRC_IP:
+ case E_SRC_MASK:
+ case R_DST_ALL:
+ case E_DST_MASK:
+ case E_SRC_IP_V6:
+ case E_SRC_MASK_V6:
+ case E_DST_MASK_V6:
+ case E_DST_IP_V6:
+ case C_PROTOCOL:
+ case E_SRC_PORT_1:
+ case E_SRC_PORT_2:
+ case E_DST_PORT_1:
+ case E_DST_PORT_2:
+ case E_USERNAME1:
+ case E_USERNAME2:
+ case E_IP_PROTO:
+ case R_CHECK_SRC_MAC:
+ case E_SRC_MAC:
+ case E_SRC_MAC_MASK:
+ case R_CHECK_DST_MAC:
+ case E_DST_MAC:
+ case E_DST_MAC_MASK:
+ case R_CHECK_TCP_STATE:
+ case R_ESTABLISHED:
+ case R_UNESTABLISHED:
+ case R_REDIRECT:
+ SmEditAccessUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case B_USER1:
+ if (GetTxtA(hWnd, E_USERNAME1, tmp, sizeof(tmp)))
+ {
+ char *ret = SmSelectUserDlgEx(hWnd, s->Hub, tmp, GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group"));
+ if (ret == NULL)
+ {
+ SetTextA(hWnd, E_USERNAME1, "");
+ }
+ else
+ {
+ SetTextA(hWnd, E_USERNAME1, ret);
+ Free(ret);
+ }
+ FocusEx(hWnd, E_USERNAME1);
+ }
+ break;
+
+ case B_USER2:
+ if (GetTxtA(hWnd, E_USERNAME2, tmp, sizeof(tmp)))
+ {
+ char *ret = SmSelectUserDlgEx(hWnd, s->Hub, tmp, GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group"));
+ if (ret == NULL)
+ {
+ SetTextA(hWnd, E_USERNAME2, "");
+ }
+ else
+ {
+ SetTextA(hWnd, E_USERNAME2, ret);
+ Free(ret);
+ }
+ FocusEx(hWnd, E_USERNAME2);
+ }
+ break;
+
+ case IDOK:
+ // [OK] button
+ SmEditAccessOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_SRC_ALL:
+ if (IsChecked(hWnd, R_SRC_ALL) == false)
+ {
+ if (s->Access->IsIPv6)
+ {
+ FocusEx(hWnd, E_SRC_IP_V6);
+ }
+ else
+ {
+ Focus(hWnd, E_SRC_IP);
+ }
+ }
+ break;
+
+ case R_DST_ALL:
+ if (IsChecked(hWnd, R_DST_ALL) == false)
+ {
+ if (s->Access->IsIPv6)
+ {
+ FocusEx(hWnd, E_DST_IP_V6);
+ }
+ else
+ {
+ Focus(hWnd, E_DST_IP);
+ }
+ }
+ break;
+ case R_CHECK_SRC_MAC:
+ if(IsChecked(hWnd, R_CHECK_SRC_MAC) == false)
+ {
+ Focus(hWnd, E_SRC_MAC);
+ }
+ break;
+ case R_CHECK_DST_MAC:
+ if(IsChecked(hWnd, R_CHECK_DST_MAC) == false)
+ {
+ Focus(hWnd, E_DST_MAC);
+ }
+ break;
+
+ case R_PASS:
+ case R_DISCARD:
+REFRESH_ICON:
+ a = s->Access;
+ if (a->Discard == false && a->Active == false)
+ {
+ ico = ICO_PASS_DISABLE;
+ }
+ else if (a->Discard == false && a->Active)
+ {
+ ico = ICO_PASS;
+ }
+ else if (a->Discard && a->Active == false)
+ {
+ ico = ICO_DISCARD_DISABLE;
+ }
+ else
+ {
+ ico = ICO_DISCARD;
+ }
+
+ SetIcon(hWnd, S_ICON, ico);
+ break;
+
+ case B_SIMULATION:
+ // Simulation
+ Dialog(hWnd, D_SM_SIMULATION, SmSimulationDlg, s);
+ break;
+
+ case B_REDIRECT:
+ // Set the URL to redirect to
+ SmRedirect(hWnd, s);
+ SmEditAccessUpdate(hWnd, s);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Delay, jitter, packet-loss dialog
+UINT SmSimulationDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_ACCESS *s = (SM_EDIT_ACCESS *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmSimulationInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_DELAY:
+ case E_JITTER:
+ case E_LOSS:
+ SmSimulationUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmSimulationOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case C_DELAY:
+ SmSimulationUpdate(hWnd, s);
+ if (IsChecked(hWnd, C_DELAY))
+ {
+ FocusEx(hWnd, E_DELAY);
+ }
+ break;
+
+ case C_JITTER:
+ SmSimulationUpdate(hWnd, s);
+ if (IsChecked(hWnd, C_JITTER))
+ {
+ FocusEx(hWnd, E_JITTER);
+ }
+ break;
+
+ case C_LOSS:
+ SmSimulationUpdate(hWnd, s);
+ if (IsChecked(hWnd, C_LOSS))
+ {
+ FocusEx(hWnd, E_LOSS);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Update of delay, jitter, packet-loss dialog
+void SmSimulationUpdate(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ bool b1, b2, b3;
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b1 = IsChecked(hWnd, C_DELAY);
+ b2 = IsChecked(hWnd, C_JITTER);
+ b3 = IsChecked(hWnd, C_LOSS);
+
+ SetEnable(hWnd, S_DELAY, b1);
+ SetEnable(hWnd, S_DELAY2, b1);
+ SetEnable(hWnd, E_DELAY, b1);
+
+ SetEnable(hWnd, C_JITTER, b1);
+
+ if (b1 == false)
+ {
+ b2 = false;
+ }
+
+ SetEnable(hWnd, S_JITTER, b2);
+ SetEnable(hWnd, S_JITTER2, b2);
+ SetEnable(hWnd, E_JITTER, b2);
+
+ SetEnable(hWnd, S_LOSS, b3);
+ SetEnable(hWnd, S_LOSS2, b3);
+ SetEnable(hWnd, E_LOSS, b3);
+
+ if (b1)
+ {
+ UINT i = GetInt(hWnd, E_DELAY);
+ if (i == 0 || i > HUB_ACCESSLIST_DELAY_MAX)
+ {
+ ok = false;
+ }
+ }
+
+ if (b2)
+ {
+ UINT i = GetInt(hWnd, E_JITTER);
+ if (i == 0 || i > HUB_ACCESSLIST_JITTER_MAX)
+ {
+ ok = false;
+ }
+ }
+
+ if (b3)
+ {
+ UINT i = GetInt(hWnd, E_LOSS);
+ if (i == 0 || i > HUB_ACCESSLIST_LOSS_MAX)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Initialization of delay, jitter, packet-loss dialog
+void SmSimulationInit(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ a = s->Access;
+
+ Check(hWnd, C_DELAY, a->Delay != 0);
+ Check(hWnd, C_JITTER, a->Jitter != 0);
+ Check(hWnd, C_LOSS, a->Loss != 0);
+
+ SetIntEx(hWnd, E_DELAY, a->Delay);
+ if (a->Delay != 0)
+ {
+ SetIntEx(hWnd, E_JITTER, a->Jitter);
+ }
+ SetIntEx(hWnd, E_LOSS, a->Loss);
+
+ SmSimulationUpdate(hWnd, s);
+
+ if (a->Delay != 0)
+ {
+ FocusEx(hWnd, E_DELAY);
+ }
+ else
+ {
+ Focus(hWnd, C_DELAY);
+ }
+}
+
+// Saving of delay, jitter, packet-loss dialog
+void SmSimulationOnOk(HWND hWnd, SM_EDIT_ACCESS *s)
+{
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ a = s->Access;
+
+ a->Jitter = a->Loss = a->Delay = 0;
+
+ if (IsChecked(hWnd, C_DELAY))
+ {
+ a->Delay = GetInt(hWnd, E_DELAY);
+ }
+
+ if (IsChecked(hWnd, C_JITTER))
+ {
+ a->Jitter = GetInt(hWnd, E_JITTER);
+ }
+
+ if (IsChecked(hWnd, C_LOSS))
+ {
+ a->Loss = GetInt(hWnd, E_LOSS);
+ }
+
+ EndDialog(hWnd, 1);
+}
+
+// Edit the access list
+bool SmEditAccess(HWND hWnd, SM_ACCESS_LIST *s, ACCESS *a)
+{
+ SM_EDIT_ACCESS edit;
+ bool ret;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&edit, sizeof(edit));
+ edit.AccessList = s;
+ edit.EditMode = true;
+ edit.Access = ZeroMalloc(sizeof(ACCESS));
+ edit.Hub = s->Hub;
+ Copy(edit.Access, a, sizeof(ACCESS));
+
+ if (edit.Access->IsIPv6 == false)
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS, SmEditAccessDlg, &edit);
+ }
+ else
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS_V6, SmEditAccessDlg, &edit);
+ }
+
+ if (ret)
+ {
+ Copy(a, edit.Access, sizeof(ACCESS));
+ Free(edit.Access);
+ Sort(s->AccessList);
+
+ // Reassign the ID
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ a->Id = (i + 1);
+ }
+ }
+ else
+ {
+ Free(edit.Access);
+ }
+
+ return ret;
+}
+
+// Clone of the access list
+bool SmCloneAccess(HWND hWnd, SM_ACCESS_LIST *s, ACCESS *t)
+{
+ SM_EDIT_ACCESS edit;
+ bool ret;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || t == NULL)
+ {
+ return false;
+ }
+
+ Zero(&edit, sizeof(edit));
+ edit.AccessList = s;
+ edit.Access = Clone(t, sizeof(ACCESS));
+ edit.Access->Priority = 0;
+ edit.Hub = s->Hub;
+
+ // Generate a number that does not duplicate with other and is larger than the priority of the cloning original
+ for (edit.Access->Priority = t->Priority;edit.Access->Priority != INFINITE;edit.Access->Priority++)
+ {
+ bool exists = false;
+
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+
+ if (a->Priority == edit.Access->Priority)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ break;
+ }
+ }
+
+ if (edit.Access->IsIPv6 == false)
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS, SmEditAccessDlg, &edit);
+ }
+ else
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS_V6, SmEditAccessDlg, &edit);
+ }
+
+ if (ret)
+ {
+ Insert(s->AccessList, edit.Access);
+
+ // Reassign the ID
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ a->Id = (i + 1);
+ }
+ }
+ else
+ {
+ Free(edit.Access);
+ }
+
+ return ret;
+}
+
+// Add to Access List
+bool SmAddAccess(HWND hWnd, SM_ACCESS_LIST *s, bool ipv6)
+{
+ SM_EDIT_ACCESS edit;
+ bool ret;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&edit, sizeof(edit));
+ edit.AccessList = s;
+ edit.Access = ZeroMalloc(sizeof(ACCESS));
+ edit.Access->Active = true;
+ edit.Access->Priority = 0;
+ edit.Access->IsIPv6 = ipv6;
+ edit.Hub = s->Hub;
+
+ // Get the new priority
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ edit.Access->Priority = MAX(edit.Access->Priority, a->Priority);
+ }
+
+ if (edit.Access->Priority == 0)
+ {
+ edit.Access->Priority = 900;
+ }
+
+ edit.Access->Priority += 100;
+
+ if (edit.Access->IsIPv6 == false)
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS, SmEditAccessDlg, &edit);
+ }
+ else
+ {
+ ret = Dialog(hWnd, D_SM_EDIT_ACCESS_V6, SmEditAccessDlg, &edit);
+ }
+
+ if (ret)
+ {
+ Insert(s->AccessList, edit.Access);
+
+ // Reassign the ID
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ a->Id = (i + 1);
+ }
+ }
+ else
+ {
+ Free(edit.Access);
+ }
+
+ return ret;
+}
+
+// Initialize
+void SmAccessListInit(HWND hWnd, SM_ACCESS_LIST *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_PASS);
+ FormatText(hWnd, S_TITLE, s->Hub->HubName);
+
+ LvInit(hWnd, L_ACCESS_LIST);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 0, _UU("SM_ACCESS_COLUMN_0"), 60);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 1, _UU("SM_ACCESS_COLUMN_1"), 60);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 2, _UU("SM_ACCESS_COLUMN_2"), 60);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 3, _UU("SM_ACCESS_COLUMN_3"), 70);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 4, _UU("SM_ACCESS_COLUMN_4"), 150);
+ LvInsertColumn(hWnd, L_ACCESS_LIST, 5, _UU("SM_ACCESS_COLUMN_5"), 600);
+
+ LvSetStyle(hWnd, L_ACCESS_LIST, LVS_EX_GRIDLINES);
+
+ SetEnable(hWnd, B_ADD_V6, GetCapsBool(s->Hub->p->CapsList, "b_support_ipv6_acl"));
+
+ SmAccessListRefresh(hWnd, s);
+}
+
+// Update the control
+void SmAccessListUpdate(HWND hWnd, SM_ACCESS_LIST *s)
+{
+ bool ok = true;
+ UINT max_access_lists = 0;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_ACCESS_LIST) == false || LvIsMultiMasked(hWnd, L_ACCESS_LIST))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+ SetEnable(hWnd, B_DELETE, ok);
+ SetEnable(hWnd, B_CLONE, ok);
+
+ if (ok == false)
+ {
+ SetEnable(hWnd, B_ENABLE, false);
+ SetEnable(hWnd, B_DISABLE, false);
+ }
+ else
+ {
+ ACCESS *a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+
+ if (a != NULL)
+ {
+ SetEnable(hWnd, B_ENABLE, (a->Active == false));
+ SetEnable(hWnd, B_DISABLE, (a->Active == true));
+ }
+ else
+ {
+ SetEnable(hWnd, B_ENABLE, false);
+ SetEnable(hWnd, B_DISABLE, false);
+ }
+ }
+
+ max_access_lists = GetCapsInt(s->Hub->p->CapsList, "i_max_access_lists");
+
+ SetEnable(hWnd, B_CREATE, LIST_NUM(s->AccessList) < max_access_lists);
+}
+
+// Content update
+void SmAccessListRefresh(HWND hWnd, SM_ACCESS_LIST *s)
+{
+ LVB *b;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ b = LvInsertStart();
+
+ Sort(s->AccessList);
+
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ char tmp[MAX_SIZE];
+ UINT ico = ICO_PASS;
+ wchar_t tmp3[MAX_SIZE];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ GetAccessListStr(tmp, sizeof(tmp), a);
+ UniToStru(tmp1, a->Priority);
+ StrToUni(tmp2, sizeof(tmp2), tmp);
+
+ if (a->Discard == false && a->Active == false)
+ {
+ ico = ICO_PASS_DISABLE;
+ }
+ else if (a->Discard == false && a->Active)
+ {
+ ico = ICO_PASS;
+ }
+ else if (a->Discard && a->Active == false)
+ {
+ ico = ICO_DISCARD_DISABLE;
+ }
+ else
+ {
+ ico = ICO_DISCARD;
+ }
+
+ UniToStru(tmp3, a->Id);
+
+ LvInsertAdd(b, ico, (void *)a, 6,
+ tmp3,
+ a->Discard ? _UU("SM_ACCESS_DISCARD") : _UU("SM_ACCESS_PASS"),
+ a->Active ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"),
+ tmp1,
+ a->Note,
+ tmp2);
+ }
+
+ LvInsertEnd(b, hWnd, L_ACCESS_LIST);
+ LvSortEx(hWnd, L_ACCESS_LIST, 0, false, true);
+
+ SmAccessListUpdate(hWnd, s);
+}
+
+// Access List dialog procedure
+UINT SmAccessListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_ACCESS_LIST *s = (SM_ACCESS_LIST *)param;
+ NMHDR *n;
+ ACCESS *a;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmAccessListInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_ADD:
+ // Add (IPv4)
+ if (SmAddAccess(hWnd, s, false))
+ {
+ SmAccessListRefresh(hWnd, s);
+ }
+ break;
+
+ case B_ADD_V6:
+ // Add (IPv6)
+ if (SmAddAccess(hWnd, s, true))
+ {
+ SmAccessListRefresh(hWnd, s);
+ }
+ break;
+
+ case IDOK:
+ // Edit
+ a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+ if (a != NULL)
+ {
+ if (SmEditAccess(hWnd, s, a))
+ {
+ SmAccessListRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_CLONE:
+ // Create by cloning
+ a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+ if (a != NULL)
+ {
+ if (SmCloneAccess(hWnd, s, a))
+ {
+ SmAccessListRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_ENABLE:
+ a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+ if (a != NULL)
+ {
+ a->Active = true;
+ SmAccessListRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DISABLE:
+ a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+ if (a != NULL)
+ {
+ a->Active = false;
+ SmAccessListRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));
+ if (a != NULL)
+ {
+ UINT i;
+ if (IsInList(s->AccessList, a))
+ {
+ Delete(s->AccessList, a);
+ Free(a);
+ // Reassign the ID
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(s->AccessList, i);
+ a->Id = (i + 1);
+ }
+ SmAccessListRefresh(hWnd, s);
+ }
+ }
+ break;
+
+ case B_SAVE:
+ // Save
+ {
+ UINT i;
+ bool ok;
+ // Save the access list
+ RPC_ENUM_ACCESS_LIST t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ t.NumAccess = LIST_NUM(s->AccessList);
+ t.Accesses = ZeroMalloc(sizeof(ACCESS) * t.NumAccess);
+ for (i = 0;i < LIST_NUM(s->AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(s->AccessList, i);
+ Copy(&t.Accesses[i], access, sizeof(ACCESS));
+ }
+
+ ok = CALL(hWnd, ScSetAccessList(s->Rpc, &t));
+ FreeRpcEnumAccessList(&t);
+ if (ok)
+ {
+ EndDialog(hWnd, true);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_ACCESS_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmAccessListUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_ACCESS_LIST);
+
+ return 0;
+}
+
+
+// Access List dialog
+void SmAccessListDlg(HWND hWnd, SM_HUB *s)
+{
+ SM_ACCESS_LIST a;
+ UINT i;
+ RPC_ENUM_ACCESS_LIST t;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+ a.Hub = s;
+ a.Rpc = s->Rpc;
+
+ // Get the access list
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScEnumAccess(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ a.AccessList = NewListFast(CmpAccessList);
+ // Add to the list
+ for (i = 0;i < t.NumAccess;i++)
+ {
+ ACCESS *access = ZeroMalloc(sizeof(ACCESS));
+ Copy(access, &t.Accesses[i], sizeof(ACCESS));
+
+ Add(a.AccessList, access);
+ }
+
+ // Sort
+ Sort(a.AccessList);
+ FreeRpcEnumAccessList(&t);
+
+ // Show the dialog
+ ret = Dialog(hWnd, D_SM_ACCESS_LIST, SmAccessListProc, &a);
+
+ for (i = 0;i < LIST_NUM(a.AccessList);i++)
+ {
+ ACCESS *access = LIST_DATA(a.AccessList, i);
+ Free(access);
+ }
+ ReleaseList(a.AccessList);
+}
+
+// Initialize
+void SmEditGroupDlgInit(HWND hWnd, SM_EDIT_GROUP *g)
+{
+ RPC_SET_GROUP *group;
+ LVB *b;
+ // Validate arguments
+ if (hWnd == NULL || g == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_GROUP);
+
+ group = &g->SetGroup;
+
+ if (g->EditMode == false)
+ {
+ SetText(hWnd, 0, _UU("SM_EDIT_GROUP_CAPTION_1"));
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_GROUP_CAPTION_2"), group->Name);
+ SetText(hWnd, 0, tmp);
+ }
+
+ SetTextA(hWnd, E_GROUPNAME, group->Name);
+ SetText(hWnd, E_REALNAME, group->Realname);
+ SetText(hWnd, E_NOTE, group->Note);
+
+ g->Inited = true;
+
+ if (g->EditMode == false)
+ {
+ Disable(hWnd, L_STATUS);
+ }
+ else
+ {
+ LvInit(hWnd, L_STATUS);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);
+ LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);
+
+ b = LvInsertStart();
+
+ SmInsertTrafficInfo(b, &group->Traffic);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ LvAutoSize(hWnd, L_STATUS);
+ }
+
+ Check(hWnd, R_POLICY, group->Policy != NULL);
+
+ if (g->EditMode)
+ {
+ Disable(hWnd, E_GROUPNAME);
+ FocusEx(hWnd, E_REALNAME);
+ }
+
+ SmEditGroupDlgUpdate(hWnd, g);
+}
+
+// Update
+void SmEditGroupDlgUpdate(HWND hWnd, SM_EDIT_GROUP *g)
+{
+ bool ok = true;
+ RPC_SET_GROUP *group;
+ // Validate arguments
+ if (hWnd == NULL || g == NULL)
+ {
+ return;
+ }
+
+ if (g->Inited == false)
+ {
+ return;
+ }
+
+ group = &g->SetGroup;
+
+ GetTxtA(hWnd, E_GROUPNAME, group->Name, sizeof(group->Name));
+ Trim(group->Name);
+
+ if (IsUserName(group->Name) == false)
+ {
+ ok = false;
+ }
+
+ GetTxt(hWnd, E_REALNAME, group->Realname, sizeof(group->Realname));
+ UniTrim(group->Realname);
+
+ GetTxt(hWnd, E_NOTE, group->Note, sizeof(group->Note));
+ UniTrim(group->Note);
+
+ SetEnable(hWnd, B_POLICY, IsChecked(hWnd, R_POLICY));
+
+ if (IsChecked(hWnd, R_POLICY))
+ {
+ if (group->Policy == NULL)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// OK
+void SmEditGroupDlgOnOk(HWND hWnd, SM_EDIT_GROUP *g)
+{
+ RPC_SET_GROUP *group;
+ RPC_SET_GROUP t;
+ // Validate arguments
+ if (hWnd == NULL || g == NULL)
+ {
+ return;
+ }
+
+ SmEditGroupDlgUpdate(hWnd, g);
+
+ group = &g->SetGroup;
+
+ if (IsChecked(hWnd, R_POLICY) == false)
+ {
+ if (group->Policy != NULL)
+ {
+ Free(group->Policy);
+ group->Policy = NULL;
+ }
+ }
+
+ Zero(&t, sizeof(t));
+ Copy(&t, group, sizeof(RPC_SET_GROUP));
+
+ t.Policy = ClonePolicy(group->Policy);
+
+ if (g->EditMode == false)
+ {
+ if (CALL(hWnd, ScCreateGroup(g->Rpc, &t)) == false)
+ {
+ FocusEx(hWnd, E_GROUPNAME);
+ return;
+ }
+ }
+ else
+ {
+ if (CALL(hWnd, ScSetGroup(g->Rpc, &t)) == false)
+ {
+ return;
+ }
+ }
+
+ FreeRpcSetGroup(&t);
+
+ if (g->EditMode == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_GROUP_CREATED"), group->Name);
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// Group editing dialog procedure
+UINT SmEditGroupDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_GROUP *g = (SM_EDIT_GROUP *)param;
+ wchar_t tmp[MAX_SIZE];
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmEditGroupDlgInit(hWnd, g);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_GROUPNAME:
+ case E_REALNAME:
+ case E_NOTE:
+ case R_POLICY:
+ SmEditGroupDlgUpdate(hWnd, g);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmEditGroupDlgOnOk(hWnd, g);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_POLICY:
+ if (IsChecked(hWnd, R_POLICY))
+ {
+ Focus(hWnd, B_POLICY);
+ }
+ break;
+
+ case B_POLICY:
+ // Security policy
+ UniFormat(tmp, sizeof(tmp), _UU("SM_GROUP_POLICY_CAPTION"), g->SetGroup.Name);
+ if (g->SetGroup.Policy == NULL)
+ {
+ POLICY *p = ClonePolicy(GetDefaultPolicy());
+ if (SmPolicyDlgEx2(hWnd, p, tmp, false, g->p->PolicyVer))
+ {
+ g->SetGroup.Policy = p;
+ SmEditGroupDlgUpdate(hWnd, g);
+ }
+ else
+ {
+ Free(p);
+ }
+ }
+ else
+ {
+ SmPolicyDlgEx2(hWnd, g->SetGroup.Policy, tmp, false, g->p->PolicyVer);
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_STATUS:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmEditGroupDlgUpdate(hWnd, g);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Group editing dialog
+bool SmEditGroupDlg(HWND hWnd, SM_GROUP *s, char *name)
+{
+ SM_EDIT_GROUP g;
+ RPC_SET_GROUP *group;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&g, sizeof(g));
+ g.EditMode = true;
+ g.Hub = s->Hub;
+ g.p = s->p;
+ g.Rpc = s->Rpc;
+
+ group = &g.SetGroup;
+
+ StrCpy(group->Name, sizeof(group->Name), name);
+ StrCpy(group->HubName, sizeof(group->HubName), s->Hub->HubName);
+
+ if (CALL(hWnd, ScGetGroup(s->Rpc, group)) == false)
+ {
+ return false;
+ }
+
+ ret = Dialog(hWnd, D_SM_EDIT_GROUP, SmEditGroupDlgProc, &g);
+
+ FreeRpcSetGroup(group);
+
+ return ret;
+}
+
+// Group creation dialog
+bool SmCreateGroupDlg(HWND hWnd, SM_GROUP *s)
+{
+ SM_EDIT_GROUP g;
+ RPC_SET_GROUP *group;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&g, sizeof(g));
+ g.EditMode = false;
+ g.Hub = s->Hub;
+ g.p = s->p;
+ g.Rpc = s->Rpc;
+
+ group = &g.SetGroup;
+
+ StrCpy(group->HubName, sizeof(group->HubName), s->Hub->HubName);
+
+ ret = Dialog(hWnd, D_SM_EDIT_GROUP, SmEditGroupDlgProc, &g);
+
+ FreeRpcSetGroup(group);
+
+ return ret;
+}
+
+// Initialize
+void SmGroupListDlgInit(HWND hWnd, SM_GROUP *s)
+{
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_GROUP);
+
+ // Initialize the column
+ LvInit(hWnd, L_GROUP);
+ LvInsertColumn(hWnd, L_GROUP, 0, _UU("SM_GROUPLIST_NAME"), 130);
+ LvInsertColumn(hWnd, L_GROUP, 1, _UU("SM_GROUPLIST_REALNAME"), 130);
+ LvInsertColumn(hWnd, L_GROUP, 2, _UU("SM_GROUPLIST_NOTE"), 170);
+ LvInsertColumn(hWnd, L_GROUP, 3, _UU("SM_GROUPLIST_NUMUSERS"), 80);
+ LvSetStyle(hWnd, L_GROUP, LVS_EX_GRIDLINES);
+
+ FormatText(hWnd, S_TITLE, s->Hub->HubName);
+
+ SmGroupListDlgRefresh(hWnd, s);
+
+ if (s->SelectMode)
+ {
+ SetStyle(hWnd, L_GROUP, LVS_SINGLESEL);
+ }
+
+ if (s->SelectMode)
+ {
+ wchar_t tmp[MAX_SIZE];
+ SetText(hWnd, IDOK, _UU("SM_SELECT_GROUP"));
+
+ if (s->SelectedGroupName != NULL)
+ {
+ UINT i;
+ StrToUni(tmp, sizeof(tmp), s->SelectedGroupName);
+ i = LvSearchStr(hWnd, L_GROUP, 0, tmp);
+ if (i != INFINITE)
+ {
+ LvSelect(hWnd, L_GROUP, i);
+ }
+ }
+ }
+}
+
+// Update the controls
+void SmGroupListDlgUpdate(HWND hWnd, SM_GROUP *s)
+{
+ bool ok = true;
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_GROUP) == false || LvIsMultiMasked(hWnd, L_GROUP))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+ SetEnable(hWnd, B_USER, ok);
+ SetEnable(hWnd, B_STATUS, ok);
+
+ if (s->SelectMode == false)
+ {
+ SetEnable(hWnd, B_DELETE, ok);
+ }
+ else
+ {
+ SetEnable(hWnd, B_DELETE, false);
+ SetEnable(hWnd, B_USER, false);
+ SetText(hWnd, IDCANCEL, _UU("SM_SELECT_NO_GROUP"));
+ }
+}
+
+// Content update
+void SmGroupListDlgRefresh(HWND hWnd, SM_GROUP *s)
+{
+ RPC_ENUM_GROUP t;
+ UINT i;
+ LVB *b;
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+
+ if (CALL(hWnd, ScEnumGroup(s->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumGroup;i++)
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ RPC_ENUM_GROUP_ITEM *e = &t.Groups[i];
+
+ StrToUni(tmp1, sizeof(tmp1), e->Name);
+ UniToStru(tmp2, e->NumUsers);
+
+ LvInsertAdd(b, e->DenyAccess == false ? ICO_GROUP : ICO_GROUP_DENY,
+ NULL, 4, tmp1, e->Realname, e->Note, tmp2);
+ }
+
+ LvInsertEnd(b, hWnd, L_GROUP);
+
+ SmGroupListDlgUpdate(hWnd, s);
+
+ FreeRpcEnumGroup(&t);
+}
+
+// Group List dialog procedure
+UINT SmGroupListDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_GROUP *s = (SM_GROUP *)param;
+ NMHDR *n;
+ wchar_t *tmp;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmGroupListDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_CREATE:
+ // Create new
+ if (SmCreateGroupDlg(hWnd, s))
+ {
+ SmGroupListDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case IDOK:
+ // Edit
+ tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);
+ if (tmp != NULL)
+ {
+ char name[MAX_SIZE];
+ UniToStr(name, sizeof(name), tmp);
+
+ if (s->SelectMode == false)
+ {
+ if (SmEditGroupDlg(hWnd, s, name))
+ {
+ SmGroupListDlgRefresh(hWnd, s);
+ }
+ }
+ else
+ {
+ s->SelectedGroupName = CopyStr(name);
+ EndDialog(hWnd, true);
+ }
+ Free(tmp);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete
+ tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);
+ if (tmp != NULL)
+ {
+ char name[MAX_SIZE];
+ RPC_DELETE_USER t;
+ UniToStr(name, sizeof(name), tmp);
+
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_GROUP_DELETE_MSG"), name) == IDYES)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (CALL(hWnd, ScDeleteGroup(s->Rpc, &t)))
+ {
+ SmGroupListDlgRefresh(hWnd, s);
+ }
+ }
+
+ Free(tmp);
+ }
+ break;
+
+ case B_USER:
+ // Member List
+ tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);
+ if (tmp != NULL)
+ {
+ char name[MAX_SIZE];
+ UniToStr(name, sizeof(name), tmp);
+ SmUserListDlgEx(hWnd, s->Hub, name, false);
+ Free(tmp);
+ }
+ break;
+
+ case B_REFRESH:
+ // Update to the latest information
+ SmGroupListDlgRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_GROUP:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmGroupListDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_GROUP);
+
+ return 0;
+}
+
+// Group List dialog (selection mode)
+char *SmSelectGroupDlg(HWND hWnd, SM_HUB *s, char *default_name)
+{
+ SM_GROUP g;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&g, sizeof(g));
+ g.Hub = s;
+ g.p = s->p;
+ g.Rpc = s->Rpc;
+ g.SelectMode = true;
+ g.SelectedGroupName = default_name;
+
+ if (Dialog(hWnd, D_SM_GROUP, SmGroupListDlgProc, &g) == false)
+ {
+ return NULL;
+ }
+
+ return g.SelectedGroupName;
+}
+
+// Group List dialog
+void SmGroupListDlg(HWND hWnd, SM_HUB *s)
+{
+ SM_GROUP g;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&g, sizeof(g));
+ g.Hub = s;
+ g.p = s->p;
+ g.Rpc = s->Rpc;
+ g.SelectMode = false;
+
+ Dialog(hWnd, D_SM_GROUP, SmGroupListDlgProc, &g);
+}
+
+// Update the user information
+bool SmRefreshUserInfo(HWND hWnd, SM_SERVER *s, void *param)
+{
+ RPC_SET_USER t;
+ SM_USER_INFO *p = (SM_USER_INFO *)param;
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ char *username;
+
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ username = p->Username;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), p->Hub->HubName);
+ StrCpy(t.Name, sizeof(t.Name), username);
+
+ if (CALL(hWnd, ScGetUser(s->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ StrToUni(tmp, sizeof(tmp), t.Name);
+ LvInsertAdd(b, ICO_USER, NULL, 2, _UU("SM_USERINFO_NAME"), tmp);
+
+ if (StrLen(t.GroupName) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.GroupName);
+ LvInsertAdd(b, ICO_GROUP, NULL, 2, _UU("SM_USERINFO_GROUP"), tmp);
+ }
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime), NULL);
+ LvInsertAdd(b, ICO_USER_ADMIN, NULL, 2, _UU("SM_USERINFO_CREATE"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.UpdatedTime), NULL);
+ LvInsertAdd(b, ICO_USER_ADMIN, NULL, 2, _UU("SM_USERINFO_UPDATE"), tmp);
+
+ if (t.ExpireTime != 0)
+ {
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ExpireTime), NULL);
+ LvInsertAdd(b, ICO_WARNING, NULL, 2, _UU("SM_USERINFO_EXPIRE"), tmp);
+ }
+
+ SmInsertTrafficInfo(b, &t.Traffic);
+
+ UniToStru(tmp, t.NumLogin);
+ LvInsertAdd(b, ICO_LINK, NULL, 2, _UU("SM_USERINFO_NUMLOGIN"), tmp);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcSetUser(&t);
+
+ return true;
+}
+
+// Initialize
+void SmPolicyDlgInit(HWND hWnd, SM_POLICY *s)
+{
+ CM_POLICY cp;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_MACHINE);
+ SetText(hWnd, 0, s->Caption);
+ SetText(hWnd, S_TITLE, s->Caption);
+ DlgFont(hWnd, S_BOLD, 10, true);
+ DlgFont(hWnd, S_BOLD2, 10, true);
+
+ DlgFont(hWnd, S_POLICY_TITLE, 11, false);
+ DlgFont(hWnd, E_POLICY_DESCRIPTION, 10, false);
+
+ Zero(&cp, sizeof(cp));
+ cp.Policy = s->Policy;
+ cp.Extension = true;
+
+ LvInit(hWnd, L_POLICY);
+ LvInsertColumn(hWnd, L_POLICY, 0, _UU("POL_TITLE_STR"), 250);
+ LvInsertColumn(hWnd, L_POLICY, 1, _UU("POL_VALUE_STR"), 150);
+ LvSetStyle(hWnd, L_POLICY, LVS_EX_GRIDLINES);
+
+ CmPolicyDlgPrintEx2(hWnd, &cp, s->CascadeMode, s->Ver);
+
+ LvSelect(hWnd, L_POLICY, 0);
+
+ s->Inited = true;
+ SmPolicyDlgUpdate(hWnd, s);
+}
+
+// Update
+void SmPolicyDlgUpdate(HWND hWnd, SM_POLICY *s)
+{
+ bool ok = true;
+ bool value_changed = false;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->Inited == false)
+ {
+ return;
+ }
+
+ i = LvGetSelected(hWnd, L_POLICY);
+ if (i != INFINITE)
+ {
+ i = (UINT)LvGetParam(hWnd, L_POLICY, i);
+ }
+ if (i == INFINITE || i >= NUM_POLICY_ITEM)
+ {
+ SetText(hWnd, S_POLICY_TITLE, _UU("SM_POLICY_INIT_TITLE"));
+ SetText(hWnd, E_POLICY_DESCRIPTION, L"");
+ Disable(hWnd, S_POLICY_TITLE);
+ Disable(hWnd, S_BOLD);
+ Hide(hWnd, S_BOLD2);
+ Hide(hWnd, R_ENABLE);
+ Hide(hWnd, R_DISABLE);
+ Hide(hWnd, R_DEFINE);
+ Hide(hWnd, E_VALUE);
+ Hide(hWnd, S_TANI);
+ Hide(hWnd, S_LIMIT);
+ }
+ else
+ {
+ POLICY_ITEM *item = &policy_item[i];
+ bool changed = false;
+ wchar_t *tmp = GetText(hWnd, S_POLICY_TITLE);
+ if (UniStrCmp(tmp, GetPolicyTitle(i)) != 0)
+ {
+ changed = true;
+ }
+ Free(tmp);
+ SetText(hWnd, S_POLICY_TITLE, GetPolicyTitle(i));
+ SetText(hWnd, E_POLICY_DESCRIPTION, GetPolicyDescription(i));
+ Enable(hWnd, S_POLICY_TITLE);
+ Enable(hWnd, S_BOLD);
+ Show(hWnd, S_BOLD2);
+
+ if (item->TypeInt == false)
+ {
+ Show(hWnd, R_ENABLE);
+ Show(hWnd, R_DISABLE);
+ Hide(hWnd, R_DEFINE);
+ Hide(hWnd, E_VALUE);
+ Hide(hWnd, S_TANI);
+ Hide(hWnd, S_LIMIT);
+
+ if (changed)
+ {
+ if (POLICY_BOOL(s->Policy, i))
+ {
+ Check(hWnd, R_ENABLE, true);
+ Check(hWnd, R_DISABLE, false);
+ }
+ else
+ {
+ Check(hWnd, R_ENABLE, false);
+ Check(hWnd, R_DISABLE, true);
+ }
+ }
+
+ if ((!(POLICY_BOOL(s->Policy, i))) != (!(IsChecked(hWnd, R_ENABLE))))
+ {
+ POLICY_BOOL(s->Policy, i) = IsChecked(hWnd, R_ENABLE);
+ value_changed = true;
+ }
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ UINT value;
+ if (item->AllowZero)
+ {
+ if (changed)
+ {
+ Check(hWnd, R_DEFINE, POLICY_INT(s->Policy, i) != 0);
+ Enable(hWnd, R_DEFINE);
+ SetIntEx(hWnd, E_VALUE, POLICY_INT(s->Policy, i));
+ }
+
+ SetEnable(hWnd, E_VALUE, IsChecked(hWnd, R_DEFINE));
+ SetEnable(hWnd, S_TANI, IsChecked(hWnd, R_DEFINE));
+ SetEnable(hWnd, S_LIMIT, IsChecked(hWnd, R_DEFINE));
+ }
+ else
+ {
+ if (changed)
+ {
+ Check(hWnd, R_DEFINE, true);
+ Disable(hWnd, R_DEFINE);
+ SetInt(hWnd, E_VALUE, POLICY_INT(s->Policy, i));
+ }
+
+ SetEnable(hWnd, E_VALUE, IsChecked(hWnd, R_DEFINE));
+ SetEnable(hWnd, S_TANI, IsChecked(hWnd, R_DEFINE));
+ SetEnable(hWnd, S_LIMIT, IsChecked(hWnd, R_DEFINE));
+ }
+
+ UniReplaceStrEx(tmp, sizeof(tmp), _UU(policy_item[i].FormatStr),
+ L"%u ", L"", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp,
+ L"%u", L"", false);
+
+ SetText(hWnd, S_TANI, tmp);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_LIMIT_STR"), policy_item[i].MinValue, policy_item[i].MaxValue);
+ SetText(hWnd, S_LIMIT, tmp);
+
+ Hide(hWnd, R_ENABLE);
+ Hide(hWnd, R_DISABLE);
+ Show(hWnd, E_VALUE);
+ Show(hWnd, R_DEFINE);
+ Show(hWnd, S_TANI);
+ Show(hWnd, S_LIMIT);
+
+ value = GetInt(hWnd, E_VALUE);
+
+ if (item->AllowZero && (IsChecked(hWnd, R_DEFINE) == false))
+ {
+ value = 0;
+ }
+ else
+ {
+ if (value < policy_item[i].MinValue || value > policy_item[i].MaxValue)
+ {
+ ok = false;
+ }
+ }
+
+ if (ok)
+ {
+ if (POLICY_INT(s->Policy, i) != value)
+ {
+ POLICY_INT(s->Policy, i) = value;
+ value_changed = true;
+ }
+ }
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+ SetEnable(hWnd, L_POLICY, ok);
+
+ if (value_changed)
+ {
+ CM_POLICY cp;
+ Zero(&cp, sizeof(cp));
+ cp.Policy = s->Policy;
+ cp.Extension = true;
+
+ CmPolicyDlgPrintEx(hWnd, &cp, s->CascadeMode);
+ }
+}
+
+// Confirmation
+void SmPolicyDlgOk(HWND hWnd, SM_POLICY *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// Policy dialog box procedure
+UINT SmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_POLICY *s = (SM_POLICY *)param;
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmPolicyDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_DEFINE:
+ case R_ENABLE:
+ case R_DISABLE:
+ case E_VALUE:
+ SmPolicyDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmPolicyDlgOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_DEFINE:
+ if (IsChecked(hWnd, R_DEFINE))
+ {
+ FocusEx(hWnd, E_VALUE);
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_POLICY:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmPolicyDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show Policies dialog box
+bool SmPolicyDlg(HWND hWnd, POLICY *p, wchar_t *caption)
+{
+ return SmPolicyDlgEx(hWnd, p, caption, false);
+}
+bool SmPolicyDlgEx(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode)
+{
+ return SmPolicyDlgEx2(hWnd, p, caption, cascade_mode, POLICY_CURRENT_VERSION);
+}
+bool SmPolicyDlgEx2(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode, UINT ver)
+{
+ SM_POLICY s;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ if (caption == NULL)
+ {
+ caption = _UU("SM_POLICY_DEF_CAPTION");
+ }
+
+ Zero(&s, sizeof(s));
+ s.Caption = caption;
+ s.Policy = ClonePolicy(p);
+ s.CascadeMode = cascade_mode;
+ s.Ver = ver;
+
+ ret = Dialog(hWnd, D_SM_POLICY, SmPolicyDlgProc, &s);
+
+ if (ret)
+ {
+ Copy(p, s.Policy, sizeof(POLICY));
+ }
+
+ Free(s.Policy);
+
+ return ret;
+}
+
+// Edit user confirmed
+void SmEditUserDlgOk(HWND hWnd, SM_EDIT_USER *s)
+{
+ RPC_SET_USER t;
+ RPC_SET_USER *u;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SmEditUserDlgUpdate(hWnd, s);
+
+ Zero(&t, sizeof(t));
+ u = &s->SetUser;
+
+ StrCpy(t.HubName, sizeof(t.HubName), u->HubName);
+ StrCpy(t.Name, sizeof(t.Name), u->Name);
+ StrCpy(t.GroupName, sizeof(t.GroupName), u->GroupName);
+ UniStrCpy(t.Realname, sizeof(t.Realname), u->Realname);
+ UniStrCpy(t.Note, sizeof(t.Note), u->Note);
+ t.ExpireTime = u->ExpireTime;
+ t.AuthType = u->AuthType;
+ t.AuthData = CopyAuthData(u->AuthData, t.AuthType);
+
+ if (IsChecked(hWnd, R_POLICY))
+ {
+ t.Policy = ClonePolicy(u->Policy);
+ }
+ else
+ {
+ t.Policy = NULL;
+ }
+
+ if (s->EditMode == false)
+ {
+ if (CALL(hWnd, ScCreateUser(s->Rpc, &t)) == false)
+ {
+ FocusEx(hWnd, E_USERNAME);
+ return;
+ }
+ FreeRpcSetUser(&t);
+
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_USER_CREEATE_OK"), u->Name);
+ }
+ else
+ {
+ if (CALL(hWnd, ScSetUser(s->Rpc, &t)) == false)
+ {
+ FocusEx(hWnd, E_REALNAME);
+ return;
+ }
+ FreeRpcSetUser(&t);
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// Edit user initialization
+void SmEditUserDlgInit(HWND hWnd, SM_EDIT_USER *s)
+{
+ RPC_SET_USER *u;
+ wchar_t tmp[MAX_SIZE];
+ UINT i;
+ UINT icons[6] = {ICO_PASS, ICO_KEY, ICO_CERT, ICO_SERVER_CERT,
+ ICO_TOWER, ICO_LINK};
+ RECT rect;
+
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_USER);
+
+ u = &s->SetUser;
+
+ // Initialize the column
+ LvInit(hWnd, L_AUTH);
+ LvSetStyle(hWnd, L_AUTH, LVS_EX_GRIDLINES);
+
+ GetClientRect(DlgItem(hWnd, L_AUTH), &rect);
+ LvInsertColumn(hWnd, L_AUTH, 0, L"Name", rect.right - rect.left);
+
+ for (i = 0;i < 6;i++)
+ {
+ LvInsert(hWnd, L_AUTH, icons[i], (void *)i, 1, SmGetAuthTypeStr(i));
+ }
+
+ // User name, etc.
+ SetTextA(hWnd, E_USERNAME, u->Name);
+ SetText(hWnd, E_REALNAME, u->Realname);
+ SetText(hWnd, E_NOTE, u->Note);
+
+
+ // Expiration date
+ if (u->ExpireTime == 0)
+ {
+ SYSTEMTIME st;
+ Check(hWnd, R_EXPIRES, false);
+ GetLocalTime(&st);
+ UINT64ToSystem(&st, SystemToUINT64(&st) + (60 * 60 * 24 * 1000));
+ st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
+ DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), GDT_VALID, &st);
+ DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), GDT_VALID, &st);
+ }
+ else
+ {
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, SystemToLocal64(u->ExpireTime));
+ Check(hWnd, R_EXPIRES, true);
+ DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), GDT_VALID, &st);
+ DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), GDT_VALID, &st);
+ }
+
+ if (GetCurrentOsLangId() == SE_LANG_JAPANESE || GetCurrentOsLangId() == SE_LANG_CHINESE_ZH)
+ {
+ SetStyle(hWnd, E_EXPIRES_DATE, DTS_LONGDATEFORMAT);
+ }
+ else
+ {
+ SetStyle(hWnd, E_EXPIRES_DATE, DTS_SHORTDATEFORMAT);
+ }
+
+ SetWindowLong(DlgItem(hWnd, E_EXPIRES_TIME), GWL_STYLE, WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | DTS_RIGHTALIGN | DTS_TIMEFORMAT | DTS_UPDOWN);
+
+ // Group name
+ SetTextA(hWnd, E_GROUP, u->GroupName);
+
+ // Authentication method
+ LvSelect(hWnd, L_AUTH, u->AuthType);
+
+ SetText(hWnd, S_CERT_INFO, _UU("SM_EDIT_USER_CERT_INFO"));
+
+ switch (u->AuthType)
+ {
+ case AUTHTYPE_PASSWORD:
+ if (s->EditMode)
+ {
+ SetTextA(hWnd, E_PASSWORD1, HIDDEN_PASSWORD);
+ SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);
+ }
+ break;
+
+ case AUTHTYPE_USERCERT:
+ SmGetCertInfoStr(tmp, sizeof(tmp), ((AUTHUSERCERT *)u->AuthData)->UserX);
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ if (u->AuthData != NULL)
+ {
+ AUTHROOTCERT *c = (AUTHROOTCERT *)u->AuthData;
+ if (c->CommonName != NULL && UniStrLen(c->CommonName) != 0)
+ {
+ Check(hWnd, R_CN, true);
+ SetText(hWnd, E_CN, c->CommonName);
+ }
+ else
+ {
+ Check(hWnd, R_CN, false);
+ }
+ if (c->Serial != NULL && c->Serial->size != 0)
+ {
+ X_SERIAL *s = c->Serial;
+ char *tmp;
+ UINT tmp_size = s->size * 3 + 1;
+ tmp = ZeroMalloc(tmp_size);
+ BinToStrEx(tmp, tmp_size, s->data, s->size);
+ SetTextA(hWnd, E_SERIAL, tmp);
+ Free(tmp);
+ Check(hWnd, R_SERIAL, true);
+ }
+ else
+ {
+ Check(hWnd, R_SERIAL, false);
+ }
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ if (u->AuthData != NULL)
+ {
+ AUTHRADIUS *r = (AUTHRADIUS *)u->AuthData;
+ if (UniStrLen(r->RadiusUsername) != 0)
+ {
+ Check(hWnd, R_SET_RADIUS_USERNAME, true);
+ SetText(hWnd, E_RADIUS_USERNAME, r->RadiusUsername);
+ }
+ else
+ {
+ Check(hWnd, R_SET_RADIUS_USERNAME, false);
+ }
+ }
+ break;
+
+ case AUTHTYPE_NT:
+ if (u->AuthData != NULL)
+ {
+ AUTHNT *n = (AUTHNT *)u->AuthData;
+ if (UniStrLen(n->NtUsername) != 0)
+ {
+ Check(hWnd, R_SET_RADIUS_USERNAME, true);
+ SetText(hWnd, E_RADIUS_USERNAME, n->NtUsername);
+ }
+ else
+ {
+ Check(hWnd, R_SET_RADIUS_USERNAME, false);
+ }
+ }
+ break;
+ }
+
+ if (u->Policy != NULL)
+ {
+ Check(hWnd, R_POLICY, true);
+ }
+
+ s->Inited = true;
+
+ SmEditUserDlgUpdate(hWnd, s);
+
+ if (s->EditMode == false)
+ {
+ Focus(hWnd, E_USERNAME);
+ SetText(hWnd, 0, _UU("SM_EDIT_USER_CAPTION_1"));
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_USER_CAPTION_2"), s->SetUser.Name);
+ SetText(hWnd, 0, tmp);
+
+ Disable(hWnd, E_USERNAME);
+ FocusEx(hWnd, E_REALNAME);
+ }
+
+ SetShow(hWnd, S_HINT, (s->EditMode ? false : true));
+}
+
+// User edit control update
+void SmEditUserDlgUpdate(HWND hWnd, SM_EDIT_USER *s)
+{
+ RPC_SET_USER *u;
+ bool ok = true;
+ UINT old_authtype;
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ bool authtype_changed = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->Inited == false)
+ {
+ return;
+ }
+
+ u = &s->SetUser;
+
+ // User name
+ GetTxtA(hWnd, E_USERNAME, u->Name, sizeof(u->Name));
+ Trim(u->Name);
+ if (StrLen(u->Name) == 0 || IsUserName(u->Name) == false)
+ {
+ ok = false;
+ }
+
+ // Real name
+ GetTxt(hWnd, E_REALNAME, u->Realname, sizeof(u->Realname));
+ UniTrim(u->Realname);
+
+ // Note
+ GetTxt(hWnd, E_NOTE, u->Note, sizeof(u->Note));
+ UniTrim(u->Realname);
+
+ // Group
+ GetTxtA(hWnd, E_GROUP, u->GroupName, sizeof(u->GroupName));
+ Trim(u->GroupName);
+
+ // Expiration date
+ if (IsChecked(hWnd, R_EXPIRES) == false)
+ {
+ u->ExpireTime = 0;
+ Disable(hWnd, E_EXPIRES_DATE);
+ Disable(hWnd, E_EXPIRES_TIME);
+ }
+ else
+ {
+ SYSTEMTIME st1, st2;
+ Enable(hWnd, E_EXPIRES_DATE);
+ Enable(hWnd, E_EXPIRES_TIME);
+ DateTime_GetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), &st1);
+ DateTime_GetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), &st2);
+ st1.wHour = st2.wHour;
+ st1.wMinute = st2.wMinute;
+ st1.wSecond = st2.wSecond;
+ st1.wMilliseconds = st2.wMilliseconds;
+ u->ExpireTime = LocalToSystem64(SystemToUINT64(&st1));
+ }
+
+ // Authentication method
+ old_authtype = u->AuthType;
+ u->AuthType = LvGetSelected(hWnd, L_AUTH);
+
+ if (StrCmpi(u->Name, "*") == 0)
+ {
+ if (u->AuthType != AUTHTYPE_RADIUS && u->AuthType != AUTHTYPE_NT)
+ {
+ ok = false;
+ }
+ }
+
+ if (u->AuthType == INFINITE)
+ {
+ ok = false;
+ u->AuthType = 0;
+ }
+ if (old_authtype != u->AuthType)
+ {
+ authtype_changed = true;
+ }
+
+ if (authtype_changed)
+ {
+ FreeAuthData(old_authtype, u->AuthData);
+ u->AuthData = NULL;
+ switch (u->AuthType)
+ {
+ case AUTHTYPE_ANONYMOUS:
+ u->AuthData = NULL;
+ break;
+
+ case AUTHTYPE_PASSWORD:
+ u->AuthData = NewPasswordAuthData("", "");
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ if (StrCmp(tmp1, HIDDEN_PASSWORD) == 0)
+ {
+ SetTextA(hWnd, E_PASSWORD1, "");
+ }
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+ if (StrCmp(tmp2, HIDDEN_PASSWORD) == 0)
+ {
+ SetTextA(hWnd, E_PASSWORD2, "");
+ }
+ break;
+
+ case AUTHTYPE_USERCERT:
+ u->AuthData = NewUserCertAuthData(NULL);
+ SetText(hWnd, S_CERT_INFO, _UU("SM_EDIT_USER_CERT_INFO"));
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ u->AuthData = NewRootCertAuthData(NULL, NULL);
+ break;
+
+ case AUTHTYPE_NT:
+ u->AuthData = NewNTAuthData(L"");
+ break;
+
+ case AUTHTYPE_RADIUS:
+ u->AuthData = NewRadiusAuthData(L"");
+ break;
+ }
+ }
+
+ SetEnable(hWnd, S_RADIUS_3, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));
+ SetEnable(hWnd, R_SET_RADIUS_USERNAME, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));
+ SetEnable(hWnd, S_RADIUS_1, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));
+
+ if (StrCmp(u->Name, "*") == 0)
+ {
+ Check(hWnd, R_SET_RADIUS_USERNAME, false);
+ Disable(hWnd, R_SET_RADIUS_USERNAME);
+ }
+
+ if ((u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT))
+ {
+ SetEnable(hWnd, E_RADIUS_USERNAME, IsChecked(hWnd, R_SET_RADIUS_USERNAME));
+ SetEnable(hWnd, S_RADIUS_2, IsChecked(hWnd, R_SET_RADIUS_USERNAME));
+ }
+ else
+ {
+ SetEnable(hWnd, E_RADIUS_USERNAME, false);
+ SetEnable(hWnd, S_RADIUS_2, false);
+ }
+
+ SetEnable(hWnd, S_PASSWORD_1, u->AuthType == AUTHTYPE_PASSWORD);
+ SetEnable(hWnd, S_PASSWORD_2, u->AuthType == AUTHTYPE_PASSWORD);
+ SetEnable(hWnd, S_PASSWORD_3, u->AuthType == AUTHTYPE_PASSWORD);
+ SetEnable(hWnd, E_PASSWORD1, u->AuthType == AUTHTYPE_PASSWORD);
+ SetEnable(hWnd, E_PASSWORD2, u->AuthType == AUTHTYPE_PASSWORD);
+
+ SetEnable(hWnd, S_USER_CERT_1, u->AuthType == AUTHTYPE_USERCERT);
+ SetEnable(hWnd, S_CERT_INFO, u->AuthType == AUTHTYPE_USERCERT);
+ SetEnable(hWnd, B_LOAD_CERT, u->AuthType == AUTHTYPE_USERCERT);
+
+ if (u->AuthType == AUTHTYPE_USERCERT)
+ {
+ SetEnable(hWnd, B_VIEW_CERT, ((AUTHUSERCERT *)u->AuthData)->UserX != NULL);
+ }
+ else
+ {
+ SetEnable(hWnd, B_VIEW_CERT, false);
+ }
+
+ SetEnable(hWnd, S_ROOT_CERT_1, u->AuthType == AUTHTYPE_ROOTCERT);
+ SetEnable(hWnd, S_ROOT_CERT_2, u->AuthType == AUTHTYPE_ROOTCERT);
+ SetEnable(hWnd, S_ROOT_CERT_3, u->AuthType == AUTHTYPE_ROOTCERT);
+ SetEnable(hWnd, R_CN, u->AuthType == AUTHTYPE_ROOTCERT);
+ SetEnable(hWnd, R_SERIAL, u->AuthType == AUTHTYPE_ROOTCERT);
+
+ if (u->AuthType == AUTHTYPE_ROOTCERT)
+ {
+ SetEnable(hWnd, E_CN, IsChecked(hWnd, R_CN));
+ SetEnable(hWnd, E_SERIAL, IsChecked(hWnd, R_SERIAL));
+ }
+ else
+ {
+ Disable(hWnd, E_CN);
+ Disable(hWnd, E_SERIAL);
+ }
+
+ switch (u->AuthType)
+ {
+ case AUTHTYPE_PASSWORD:
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+ if (StrCmp(tmp1, tmp2) != 0)
+ {
+ ok = false;
+ }
+ else
+ {
+ if (StrCmp(tmp1, HIDDEN_PASSWORD) != 0)
+ {
+ HashPassword(((AUTHPASSWORD *)u->AuthData)->HashedKey, u->Name, tmp1);
+ GenerateNtPasswordHash(((AUTHPASSWORD *)u->AuthData)->NtLmSecureHash, tmp1);
+ }
+ }
+ break;
+
+ case AUTHTYPE_USERCERT:
+ if (((AUTHUSERCERT *)u->AuthData)->UserX == NULL)
+ {
+ ok = false;
+ }
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ Free(((AUTHROOTCERT *)u->AuthData)->CommonName);
+ ((AUTHROOTCERT *)u->AuthData)->CommonName = NULL;
+ if (IsChecked(hWnd, R_CN) && (IsEmpty(hWnd, E_CN) == false))
+ {
+ ((AUTHROOTCERT *)u->AuthData)->CommonName = GetText(hWnd, E_CN);
+ UniTrim(((AUTHROOTCERT *)u->AuthData)->CommonName);
+ }
+ if (IsChecked(hWnd, R_CN) && ((AUTHROOTCERT *)u->AuthData)->CommonName == NULL)
+ {
+ ok = false;
+ }
+ FreeXSerial(((AUTHROOTCERT *)u->AuthData)->Serial);
+ ((AUTHROOTCERT *)u->AuthData)->Serial = NULL;
+ if (IsChecked(hWnd, R_SERIAL))
+ {
+ char *serial_str = GetTextA(hWnd, E_SERIAL);
+ if (serial_str != NULL)
+ {
+ BUF *b = StrToBin(serial_str);
+ if (b->Size >= 1)
+ {
+ ((AUTHROOTCERT *)u->AuthData)->Serial = NewXSerial(b->Buf, b->Size);
+ }
+ FreeBuf(b);
+ Free(serial_str);
+ }
+ }
+ if (IsChecked(hWnd, R_SERIAL) && ((AUTHROOTCERT *)u->AuthData)->Serial == NULL)
+ {
+ ok = false;
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ Free(((AUTHRADIUS *)u->AuthData)->RadiusUsername);
+ ((AUTHRADIUS *)u->AuthData)->RadiusUsername = NULL;
+ if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && (IsEmpty(hWnd, E_RADIUS_USERNAME) == false))
+ {
+ ((AUTHRADIUS *)u->AuthData)->RadiusUsername = GetText(hWnd, E_RADIUS_USERNAME);
+ }
+ if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && ((AUTHRADIUS *)u->AuthData)->RadiusUsername == NULL)
+ {
+ ok = false;
+ }
+ break;
+
+ case AUTHTYPE_NT:
+ Free(((AUTHNT *)u->AuthData)->NtUsername);
+ ((AUTHNT *)u->AuthData)->NtUsername = NULL;
+ if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && (IsEmpty(hWnd, E_RADIUS_USERNAME) == false))
+ {
+ ((AUTHNT *)u->AuthData)->NtUsername = GetText(hWnd, E_RADIUS_USERNAME);
+ }
+ if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && ((AUTHNT *)u->AuthData)->NtUsername == NULL)
+ {
+ ok = false;
+ }
+ break;
+ }
+
+ SetEnable(hWnd, B_POLICY, IsChecked(hWnd, R_POLICY));
+ if (IsChecked(hWnd, R_POLICY))
+ {
+ if (u->Policy == NULL)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Edit User dialog procedure
+UINT SmEditUserDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_USER *s = (SM_EDIT_USER *)param;
+ NMHDR *n;
+ POLICY *policy;
+ X *x = NULL;
+ wchar_t tmp[MAX_SIZE];
+ char name[MAX_SIZE];
+ char *ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmEditUserDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_USERNAME:
+ case E_REALNAME:
+ case E_NOTE:
+ case R_EXPIRES:
+ case E_EXPIRES_DATE:
+ case E_EXPIRES_TIME:
+ case E_GROUP:
+ case L_AUTH:
+ case R_SET_RADIUS_USERNAME:
+ case E_RADIUS_USERNAME:
+ case R_POLICY:
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ case R_CN:
+ case E_CN:
+ case R_SERIAL:
+ case E_SERIAL:
+ SmEditUserDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmEditUserDlgOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case B_POLICY:
+ UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_USER_POL_DLG"), s->SetUser.Name);
+ // Policy
+ if (s->SetUser.Policy == NULL)
+ {
+ policy = ClonePolicy(GetDefaultPolicy());
+ if (SmPolicyDlgEx2(hWnd, policy, tmp, false, s->p->PolicyVer))
+ {
+ s->SetUser.Policy = policy;
+ SmEditUserDlgUpdate(hWnd, s);
+ }
+ else
+ {
+ Free(policy);
+ }
+ }
+ else
+ {
+ SmPolicyDlgEx2(hWnd, s->SetUser.Policy, tmp, false, s->p->PolicyVer);
+ }
+ break;
+
+ case B_GROUP:
+ // Browse for a Group
+ GetTxtA(hWnd, E_GROUP, name, sizeof(name));
+ Trim(name);
+ ret = SmSelectGroupDlg(hWnd, s->Hub, StrLen(name) == 0 ? NULL : name);
+ if (ret != NULL)
+ {
+ SetTextA(hWnd, E_GROUP, ret);
+ Free(ret);
+ }
+ else
+ {
+ SetTextA(hWnd, E_GROUP, "");
+ }
+ FocusEx(hWnd, E_GROUP);
+ break;
+
+ case B_LOAD_CERT:
+ // Specify the certificate
+ if (CmLoadXFromFileOrSecureCard(hWnd, &x))
+ {
+UPDATE_CERT:
+ if (s->SetUser.AuthType == AUTHTYPE_USERCERT)
+ {
+ wchar_t tmp[MAX_SIZE];
+ FreeX(((AUTHUSERCERT *)s->SetUser.AuthData)->UserX);
+ ((AUTHUSERCERT *)s->SetUser.AuthData)->UserX = x;
+ SmGetCertInfoStr(tmp, sizeof(tmp), x);
+ SetText(hWnd, S_CERT_INFO, tmp);
+ SmEditUserDlgUpdate(hWnd, s);
+ }
+ else
+ {
+ if (x != NULL)
+ {
+ FreeX(x);
+ x = NULL;
+ }
+ }
+ }
+ break;
+
+ case B_VIEW_CERT:
+ // Show the certificate
+ if (s->SetUser.AuthType == AUTHTYPE_USERCERT)
+ {
+ CertDlg(hWnd, ((AUTHUSERCERT *)s->SetUser.AuthData)->UserX, NULL, true);
+ }
+ break;
+
+ case B_CREATE:
+ // Create
+ GetTxtA(hWnd, E_USERNAME, name, sizeof(name));
+ Trim(name);
+ if (SmCreateCert(hWnd, &x, NULL, false, name, false))
+ {
+ if (s->SetUser.AuthType != AUTHTYPE_USERCERT)
+ {
+ LvSelect(hWnd, L_AUTH, 2);
+ }
+ goto UPDATE_CERT;
+ }
+ break;
+
+ case R_SET_RADIUS_USERNAME:
+ if (IsChecked(hWnd, R_SET_RADIUS_USERNAME))
+ {
+ FocusEx(hWnd, E_RADIUS_USERNAME);
+ }
+ break;
+
+ case R_EXPIRES:
+ if (IsChecked(hWnd, R_EXPIRES))
+ {
+ Focus(hWnd, E_EXPIRES_DATE);
+ }
+ break;
+
+ case R_POLICY:
+ if (IsChecked(hWnd, R_POLICY))
+ {
+ Focus(hWnd, B_POLICY);
+ }
+ break;
+
+ case R_CN:
+ if (IsChecked(hWnd, R_CN))
+ {
+ Focus(hWnd, E_CN);
+ }
+ break;
+
+ case R_SERIAL:
+ if (IsChecked(hWnd, R_SERIAL))
+ {
+ Focus(hWnd, E_SERIAL);
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_AUTH:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmEditUserDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// User editing dialog
+bool SmEditUserDlg(HWND hWnd, SM_HUB *s, char *username)
+{
+ SM_EDIT_USER e;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL || username == NULL)
+ {
+ return false;
+ }
+
+ Zero(&e, sizeof(e));
+ e.p = s->p;
+ e.Rpc = s->Rpc;
+ e.Hub = s;
+
+ // Get the User
+ StrCpy(e.SetUser.HubName, sizeof(e.SetUser.HubName), e.Hub->HubName);
+ StrCpy(e.SetUser.Name, sizeof(e.SetUser.Name), username);
+
+ if (CALL(hWnd, ScGetUser(s->Rpc, &e.SetUser)) == false)
+ {
+ return false;
+ }
+
+ e.EditMode = true;
+
+ ret = Dialog(hWnd, D_SM_EDIT_USER, SmEditUserDlgProc, &e);
+
+ FreeRpcSetUser(&e.SetUser);
+
+ return ret;
+}
+
+// New user creation dialog
+bool SmCreateUserDlg(HWND hWnd, SM_HUB *s)
+{
+ SM_EDIT_USER e;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Zero(&e, sizeof(e));
+ e.EditMode = false;
+ e.p = s->p;
+ e.Rpc = s->Rpc;
+ e.Hub = s;
+
+ // Set up a new user
+ StrCpy(e.SetUser.HubName, sizeof(e.SetUser.HubName), e.Hub->HubName);
+ e.SetUser.AuthType = CLIENT_AUTHTYPE_PASSWORD;
+ e.SetUser.AuthData = NewPasswordAuthData("", "");
+
+ ret = Dialog(hWnd, D_SM_EDIT_USER, SmEditUserDlgProc, &e);
+
+ FreeRpcSetUser(&e.SetUser);
+
+ return ret;
+}
+
+// Get a string of user authentication method
+wchar_t *SmGetAuthTypeStr(UINT id)
+{
+ return GetAuthTypeStr(id);
+}
+
+// User list initialization
+void SmUserListInit(HWND hWnd, SM_USER *s)
+{
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_USER);
+
+ // Initialize the column
+ LvInit(hWnd, L_USER);
+ LvSetStyle(hWnd, L_USER, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_USER, 0, _UU("SM_USER_COLUMN_1"), 120);
+ LvInsertColumn(hWnd, L_USER, 1, _UU("SM_USER_COLUMN_2"), 100);
+ LvInsertColumn(hWnd, L_USER, 2, _UU("SM_USER_COLUMN_3"), 100);
+ LvInsertColumn(hWnd, L_USER, 3, _UU("SM_USER_COLUMN_4"), 130);
+ LvInsertColumn(hWnd, L_USER, 4, _UU("SM_USER_COLUMN_5"), 100);
+ LvInsertColumn(hWnd, L_USER, 5, _UU("SM_USER_COLUMN_6"), 90);
+ LvInsertColumn(hWnd, L_USER, 6, _UU("SM_USER_COLUMN_7"), 120);
+ LvInsertColumn(hWnd, L_USER, 7, _UU("SM_LICENSE_COLUMN_5"), 120);
+ LvInsertColumn(hWnd, L_USER, 8, _UU("SM_SESS_COLUMN_6"), 100);
+ LvInsertColumn(hWnd, L_USER, 9, _UU("SM_SESS_COLUMN_7"), 100);
+
+ FormatText(hWnd, S_TITLE, s->Hub->HubName);
+
+ if (s->GroupName != NULL)
+ {
+ GetTxt(hWnd, 0, tmp1, sizeof(tmp1));
+ UniFormat(tmp2, sizeof(tmp2), _UU("SM_GROUP_MEMBER_STR"), s->GroupName);
+ UniStrCat(tmp1, sizeof(tmp1), tmp2);
+ SetText(hWnd, S_TITLE, tmp1);
+ Disable(hWnd, B_CREATE);
+ }
+
+ if (s->SelectMode)
+ {
+ SetStyle(hWnd, L_USER, LVS_SINGLESEL);
+ }
+
+ SmUserListRefresh(hWnd, s);
+
+ if (s->SelectMode)
+ {
+ wchar_t tmp[MAX_SIZE];
+ UINT i;
+ StrToUni(tmp, sizeof(tmp), s->SelectedName);
+ i = LvSearchStr(hWnd, L_USER, 0, tmp);
+ if (i != INFINITE)
+ {
+ LvSelect(hWnd, L_USER, i);
+ }
+
+ if (s->AllowGroup)
+ {
+ SetText(hWnd, B_DELETE, _UU("SM_SELECT_ALT_GROUP"));
+ }
+ }
+}
+
+// User list update
+void SmUserListRefresh(HWND hWnd, SM_USER *s)
+{
+ LVB *b;
+ RPC_ENUM_USER t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ if (CALL(hWnd, ScEnumUser(s->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumUser;i++)
+ {
+ RPC_ENUM_USER_ITEM *e = &t.Users[i];
+ wchar_t name[MAX_SIZE];
+ wchar_t group[MAX_SIZE];
+ wchar_t num[MAX_SIZE];
+ wchar_t time[MAX_SIZE];
+ wchar_t exp[MAX_SIZE];
+ wchar_t num1[64], num2[64];
+
+ if (s->GroupName != NULL)
+ {
+ if (StrCmpi(s->GroupName, e->GroupName) != 0)
+ {
+ continue;
+ }
+ }
+
+ StrToUni(name, sizeof(name), e->Name);
+
+ if (StrLen(e->GroupName) != 0)
+ {
+ StrToUni(group, sizeof(group), e->GroupName);
+ }
+ else
+ {
+ UniStrCpy(group, sizeof(group), _UU("SM_NO_GROUP"));
+ }
+
+ UniToStru(num, e->NumLogin);
+
+ GetDateTimeStrEx64(time, sizeof(time), SystemToLocal64(e->LastLoginTime), NULL);
+
+ if (e->IsExpiresFilled == false)
+ {
+ UniStrCpy(exp, sizeof(exp), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ if (e->Expires == 0)
+ {
+ UniStrCpy(exp, sizeof(exp), _UU("SM_LICENSE_NO_EXPIRES"));
+ }
+ else
+ {
+ GetDateTimeStrEx64(exp, sizeof(exp), SystemToLocal64(e->Expires), NULL);
+ }
+ }
+
+ if (e->IsTrafficFilled == false)
+ {
+ UniStrCpy(num1, sizeof(num1), _UU("CM_ST_NONE"));
+ UniStrCpy(num2, sizeof(num2), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ UniToStr3(num1, sizeof(num1),
+ e->Traffic.Recv.BroadcastBytes + e->Traffic.Recv.UnicastBytes +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastBytes);
+
+ UniToStr3(num2, sizeof(num2),
+ e->Traffic.Recv.BroadcastCount + e->Traffic.Recv.UnicastCount +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastCount);
+ }
+
+ LvInsertAdd(b, e->DenyAccess ? ICO_USER_DENY : ICO_USER, NULL, 10,
+ name, e->Realname, group, e->Note, SmGetAuthTypeStr(e->AuthType),
+ num, time, exp, num1, num2);
+ }
+
+ LvInsertEnd(b, hWnd, L_USER);
+
+ FreeRpcEnumUser(&t);
+
+ SmUserListUpdate(hWnd, s);
+}
+
+// User list control update
+void SmUserListUpdate(HWND hWnd, SM_USER *s)
+{
+ bool b = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_USER) == false || LvIsMultiMasked(hWnd, L_USER))
+ {
+ b = false;
+ }
+
+ if (s->SelectMode)
+ {
+ SetText(hWnd, IDOK, _UU("SM_SELECT_USER"));
+ SetText(hWnd, IDCANCEL, _UU("SM_SELECT_NO"));
+ SetText(hWnd, S_TITLE, _UU("SM_PLEASE_SELECT"));
+ }
+
+ SetEnable(hWnd, IDOK, b);
+
+ SetEnable(hWnd, B_STATUS, b);
+ SetEnable(hWnd, B_DELETE, (b && s->SelectedName == false) || s->AllowGroup);
+ SetEnable(hWnd, B_CREATE, s->SelectedName == false);
+}
+
+// User List dialog procedure
+UINT SmUserListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_USER *s = (SM_USER *)param;
+ NMHDR *n;
+ wchar_t *str;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmUserListInit(hWnd, s);
+
+ if (s->CreateNow)
+ {
+ // Create instantly
+ if (IsEnable(hWnd, B_CREATE))
+ {
+ Command(hWnd, B_CREATE);
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ if (s->SelectMode == false)
+ {
+ // Property
+ str = LvGetSelectedStr(hWnd, L_USER, 0);
+ if (str != NULL)
+ {
+ char name[MAX_SIZE];
+ UniToStr(name, sizeof(name), str);
+
+ if (SmEditUserDlg(hWnd, s->Hub, name))
+ {
+ SmUserListRefresh(hWnd, s);
+ }
+
+ Free(str);
+ }
+ }
+ else
+ {
+ // The user has been chosen
+ str = LvGetSelectedStr(hWnd, L_USER, 0);
+ if (str != NULL)
+ {
+ char name[MAX_SIZE];
+ UniToStr(name, sizeof(name), str);
+
+ s->SelectedName = CopyStr(name);
+
+ EndDialog(hWnd, true);
+
+ Free(str);
+ }
+ }
+ break;
+
+ case B_CREATE:
+ // Create new
+ if (SmCreateUserDlg(hWnd, s->Hub))
+ {
+ SmUserListRefresh(hWnd, s);
+ }
+ break;
+
+ case B_DELETE:
+ if (s->AllowGroup)
+ {
+ // Group selection
+ EndDialog(hWnd, INFINITE);
+ }
+ else
+ {
+ // Delete
+ str = LvGetSelectedStr(hWnd, L_USER, 0);
+ if (str != NULL)
+ {
+ RPC_DELETE_USER t;
+ char name[MAX_SIZE];
+ UniToStr(name, sizeof(name), str);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);
+ StrCpy(t.Name, sizeof(t.Name), name);
+
+ if (MsgBoxEx(hWnd, MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION,
+ _UU("SM_USER_DELETE_MSG"), str) == IDYES)
+ {
+ if (CALL(hWnd, ScDeleteUser(s->Rpc, &t)))
+ {
+ SmUserListRefresh(hWnd, s);
+ }
+ }
+
+ Free(str);
+ }
+ }
+ break;
+
+ case B_STATUS:
+ // Display the User Information
+ str = LvGetSelectedStr(hWnd, L_USER, 0);
+ if (str != NULL)
+ {
+ char name[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ SM_USER_INFO info;
+ UniToStr(name, sizeof(name), str);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_USERINFO_CAPTION"), name);
+
+ Zero(&info, sizeof(info));
+ info.p = s->p;
+ info.Rpc = s->Rpc;
+ info.Hub = s->Hub;
+ info.Username = name;
+
+ SmStatusDlg(hWnd, s->p, &info, false, true, tmp, ICO_USER, NULL, SmRefreshUserInfo);
+
+ Free(str);
+ }
+ break;
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmUserListRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_USER:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ // Update the control
+ SmUserListUpdate(hWnd, s);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_USER);
+
+ return 0;
+}
+
+// User List dialog (selection)
+char *SmSelectUserDlg(HWND hWnd, SM_HUB *s, char *default_name)
+{
+ return SmSelectUserDlgEx(hWnd, s, default_name, false);
+}
+char *SmSelectUserDlgEx(HWND hWnd, SM_HUB *s, char *default_name, bool allow_group)
+{
+ UINT ret;
+ SM_USER user;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&user, sizeof(user));
+ user.Hub = s;
+ user.p = s->p;
+ user.Rpc = s->Rpc;
+ user.GroupName = NULL;
+ user.SelectedName = default_name;
+ user.SelectMode = true;
+ user.AllowGroup = allow_group;
+
+ ret = Dialog(hWnd, D_SM_USER, SmUserListProc, &user);
+
+ if (ret == 0)
+ {
+ return NULL;
+ }
+ else if (ret == INFINITE)
+ {
+ // Select a Group
+ return SmSelectGroupDlg(hWnd, s, default_name);
+ }
+ else
+ {
+ return user.SelectedName;
+ }
+}
+
+// User List dialog (filtered by group name)
+void SmUserListDlgEx(HWND hWnd, SM_HUB *s, char *groupname, bool create)
+{
+ SM_USER user;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&user, sizeof(user));
+ user.Hub = s;
+ user.p = s->p;
+ user.Rpc = s->Rpc;
+ user.GroupName = groupname;
+ user.CreateNow = create;
+
+ Dialog(hWnd, D_SM_USER, SmUserListProc, &user);
+}
+
+// User List dialog
+void SmUserListDlg(HWND hWnd, SM_HUB *s)
+{
+ SmUserListDlgEx(hWnd, s, NULL, false);
+}
+
+// Initialize
+void SmHubDlgInit(HWND hWnd, SM_HUB *s)
+{
+ CAPSLIST *caps;
+ bool support_user, support_group, support_accesslist, support_cascade,
+ support_log, support_config_hub, support_secure_nat, support_config_radius;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ FormatText(hWnd, 0, s->HubName);
+ FormatText(hWnd, S_TITLE, s->HubName);
+ SetIcon(hWnd, 0, ICO_HUB);
+ DlgFont(hWnd, S_TITLE, 15, true);
+
+ LvInit(hWnd, L_STATUS);
+ LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);
+
+ caps = s->p->CapsList;
+
+ support_user = GetCapsInt(caps, "i_max_users_per_hub") == 0 ? false : true;
+ support_group = GetCapsInt(caps, "i_max_groups_per_hub") == 0 ? false : true;
+ support_accesslist = GetCapsInt(caps, "i_max_access_lists") == 0 ? false : true;
+ support_cascade = GetCapsBool(caps, "b_support_cascade");
+ support_log = GetCapsBool(caps, "b_support_config_log");
+ support_config_hub = GetCapsBool(caps, "b_support_config_hub");
+ support_secure_nat = GetCapsBool(caps, "b_support_securenat");
+ support_config_radius = GetCapsBool(caps, "b_support_radius");
+
+ SetEnable(hWnd, B_USER, support_user);
+ SetEnable(hWnd, S_USER, support_user);
+
+ SetEnable(hWnd, B_GROUP, support_group);
+ SetEnable(hWnd, S_GROUP, support_group);
+
+ SetEnable(hWnd, B_ACCESS, support_accesslist);
+ SetEnable(hWnd, S_ACCESS, support_accesslist);
+
+ SetEnable(hWnd, B_PROPERTY, s->p->ServerType != SERVER_TYPE_FARM_MEMBER);
+ SetEnable(hWnd, S_PROPERTY, s->p->ServerType != SERVER_TYPE_FARM_MEMBER);
+
+ SetEnable(hWnd, B_RADIUS, support_config_radius);
+ SetEnable(hWnd, S_RADIUS, support_config_radius);
+
+ SetEnable(hWnd, B_LINK, support_cascade);
+ SetEnable(hWnd, S_LINK, support_cascade);
+
+ SetEnable(hWnd, B_LOG, support_log);
+ SetEnable(hWnd, S_LOG, support_log);
+
+ SetEnable(hWnd, B_CA, support_config_hub);
+ SetEnable(hWnd, S_CA, support_config_hub);
+
+ SetEnable(hWnd, B_SNAT, support_secure_nat);
+ SetEnable(hWnd, S_SNAT, support_secure_nat);
+
+ SetEnable(hWnd, B_CRL, GetCapsBool(caps, "b_support_crl"));
+
+ SetEnable(hWnd, B_LOG_FILE, GetCapsBool(caps, "b_support_read_log"));
+
+ SmHubDlgRefresh(hWnd, s);
+}
+
+// Update the control
+void SmHubDlgUpdate(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+}
+
+// Content update
+void SmHubDlgRefresh(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SmRefreshHubStatus(hWnd, s->p, (void *)s->HubName);
+ LvAutoSize(hWnd, L_STATUS);
+
+ SmHubDlgUpdate(hWnd, s);
+}
+
+// HUB management dialog
+UINT SmHubDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_HUB *s = (SM_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmHubDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_USER:
+ // User
+ SmUserListDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_GROUP:
+ // Group
+ SmGroupListDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_ACCESS:
+ // Access list
+ SmAccessListDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_PROPERTY:
+ // Property
+ if (SmEditHubDlg(hWnd, s->p, s->HubName))
+ {
+ SmHubDlgRefresh(hWnd, s);
+ }
+ break;
+
+ case B_RADIUS:
+ // Radius
+ SmRadiusDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_LINK:
+ // Cascade
+ SmLinkDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_SESSION:
+ // Session
+ SmSessionDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_LOG:
+ // Log
+ Dialog(hWnd, D_SM_LOG, SmLogDlg, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_CA:
+ // CA
+ SmCaDlg(hWnd, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_SNAT:
+ // SecureNAT
+ Dialog(hWnd, D_SM_SNAT, SmSNATDlgProc, s);
+ SmHubDlgRefresh(hWnd, s);
+ break;
+
+ case B_CRL:
+ // Certificate revocation list
+ Dialog(hWnd, D_SM_CRL, SmCrlDlgProc, s);
+ break;
+
+ case B_LOG_FILE:
+ // Log file
+ Dialog(hWnd, D_SM_LOG_FILE, SmLogFileDlgProc, s->p);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Management of HUB
+void SmHubDlg(HWND hWnd, SM_HUB *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_HUB, SmHubDlgProc, s);
+}
+
+// Change the server password
+UINT SmChangeServerPasswordDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *p = (SM_SERVER *)param;
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ RPC_SET_PASSWORD t;
+ SETTING *setting;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SetIcon(hWnd, 0, ICO_USER_ADMIN);
+ FormatText(hWnd, 0, p->ServerName);
+ FormatText(hWnd, S_TITLE, p->ServerName);
+ Focus(hWnd, E_PASSWORD1);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+
+ if (StrLen(tmp1) == 0 || StrLen(tmp2) == 0)
+ {
+ Disable(hWnd, IDOK);
+ }
+ else
+ {
+ Enable(hWnd, IDOK);
+ }
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
+ GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
+ if (StrCmp(tmp1, tmp2) != 0)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CHANGE_PASSWORD_1"));
+ FocusEx(hWnd, E_PASSWORD2);
+ break;
+ }
+ if (StrLen(tmp1) == 0)
+ {
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CHANGE_PASSWORD_2")) == IDNO)
+ {
+ Focus(hWnd, E_PASSWORD1);
+ break;
+ }
+ }
+ Zero(&t, sizeof(t));
+ Hash(t.HashedPassword, tmp1, StrLen(tmp1), true);
+ Copy(hash, t.HashedPassword, sizeof(hash));
+ if (CALL(hWnd, ScSetServerPassword(p->Rpc, &t)) == false)
+ {
+ break;
+ }
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CHANGE_PASSWORD_3"));
+
+ // Change the password for the connection setting
+ setting = SmGetSetting(p->CurrentSetting->Title);
+ if (setting != NULL && sm->TempSetting == NULL)
+ {
+ if (IsZero(setting->HashedPassword, SHA1_SIZE) == false)
+ {
+ Copy(setting->HashedPassword, hash, SHA1_SIZE);
+ SmWriteSettingList();
+ }
+ }
+
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Update the status of the connection to the server farm controller
+bool SmRefreshFarmConnectionInfo(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_FARM_CONNECTION_STATUS t;
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetFarmConnectionStatus(p->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ if (t.Online == false)
+ {
+ LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FC_IP"), _UU("SM_FC_NOT_CONNECTED"));
+
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_PORT"), _UU("SM_FC_NOT_CONNECTED"));
+ }
+ else
+ {
+ IPToStr32(str, sizeof(str), t.Ip);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FC_IP"), tmp);
+
+ UniToStru(tmp, t.Port);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_PORT"), tmp);
+ }
+
+ LvInsertAdd(b,
+ t.Online ? ICO_SERVER_ONLINE_EX : ICO_PROTOCOL_X, NULL, 2,
+ _UU("SM_FC_STATUS"),
+ t.Online ? _UU("SM_FC_ONLINE") : _UU("SM_FC_OFFLINE"));
+
+ if (t.Online == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FC_ERROR_TAG"), _E(t.LastError), t.LastError);
+ LvInsertAdd(b, ICO_STOP, NULL, 2,
+ _UU("SM_FC_LAST_ERROR"), tmp);
+ }
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartedTime), NULL);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_START_TIME"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.FirstConnectedTime), NULL);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_FIRST_TIME"), tmp);
+
+ //if (t.Online == false)
+ {
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CurrentConnectedTime), NULL);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_CURRENT_TIME"), tmp);
+ }
+
+ UniToStru(tmp, t.NumTry);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_TRY"), tmp);
+
+ UniToStru(tmp, t.NumConnected);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_CONNECTED"), tmp);
+
+ UniToStru(tmp, t.NumFailed);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_FAILED"), tmp);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ return true;
+}
+
+// Initialize
+void SmFarmMemberDlgInit(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_FARM);
+
+ FormatText(hWnd, S_TITLE, p->ServerName);
+
+ // Initialize the column
+ LvInit(hWnd, L_FARM_MEMBER);
+ LvSetStyle(hWnd, L_FARM_MEMBER, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 0, _UU("SM_FM_COLUMN_1"), 90);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 1, _UU("SM_FM_COLUMN_2"), 150);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 2, _UU("SM_FM_COLUMN_3"), 140);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 3, _UU("SM_FM_COLUMN_4"), 60);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 4, _UU("SM_FM_COLUMN_5"), 80);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 5, _UU("SM_FM_COLUMN_6"), 80);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 6, _UU("SM_FM_COLUMN_7"), 80);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 7, _UU("SM_FM_COLUMN_8"), 160);
+ LvInsertColumn(hWnd, L_FARM_MEMBER, 8, _UU("SM_FM_COLUMN_9"), 160);
+
+ SmFarmMemberDlgRefresh(hWnd, p);
+}
+
+// Update
+void SmFarmMemberDlgUpdate(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_FARM_MEMBER) && (LvIsMultiMasked(hWnd, L_FARM_MEMBER) == false));
+ SetEnable(hWnd, B_CERT, LvIsSelected(hWnd, L_FARM_MEMBER) && (LvIsMultiMasked(hWnd, L_FARM_MEMBER) == false));
+}
+
+// Content update
+void SmFarmMemberDlgRefresh(HWND hWnd, SM_SERVER *p)
+{
+ RPC_ENUM_FARM t;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumFarmMember(p->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ LvReset(hWnd, L_FARM_MEMBER);
+
+ for (i = 0;i < t.NumFarm;i++)
+ {
+ RPC_ENUM_FARM_ITEM *e = &t.Farms[i];
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ wchar_t tmp3[64];
+ wchar_t tmp4[64];
+ wchar_t tmp5[64];
+ wchar_t tmp6[64];
+ wchar_t tmp7[64];
+ wchar_t tmp8[64];
+
+ GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);
+ StrToUni(tmp2, sizeof(tmp2), e->Hostname);
+ UniToStru(tmp3, e->Point);
+ UniToStru(tmp4, e->NumSessions);
+ UniToStru(tmp5, e->NumTcpConnections);
+ UniToStru(tmp6, e->NumHubs);
+ UniToStru(tmp7, e->AssignedClientLicense);
+ UniToStru(tmp8, e->AssignedBridgeLicense);
+
+ LvInsert(hWnd, L_FARM_MEMBER, e->Controller ? ICO_FARM : ICO_TOWER, (void *)e->Id, 9,
+ e->Controller ? _UU("SM_FM_CONTROLLER") : _UU("SM_FM_MEMBER"),
+ tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8);
+ }
+
+ FreeRpcEnumFarm(&t);
+
+ SmFarmMemberDlgUpdate(hWnd, p);
+}
+
+// [OK] button
+void SmFarmMemberDlgOnOk(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+}
+
+// Display the farm member certificate
+void SmFarmMemberCert(HWND hWnd, SM_SERVER *p, UINT id)
+{
+ RPC_FARM_INFO t;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || id == 0)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Id = id;
+
+ if (CALL(hWnd, ScGetFarmInfo(p->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ CertDlg(hWnd, t.ServerCert, NULL, true);
+
+ FreeRpcFarmInfo(&t);
+}
+
+// Update the farm member information
+bool SmRefreshFarmMemberInfo(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_FARM_INFO t;
+ UINT id = (UINT)param;
+ LVB *b;
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || id == 0)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ t.Id = id;
+
+ if (CALL(hWnd, ScGetFarmInfo(p->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FMINFO_TYPE"),
+ t.Controller ? _UU("SM_FARM_CONTROLLER") : _UU("SM_FARM_MEMBER"));
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FMINFO_CONNECT_TIME"), tmp);
+
+ IPToStr32(str, sizeof(str), t.Ip);
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_IP"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.Hostname);
+ LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("SM_FMINFO_HOSTNAME"), tmp);
+
+ UniToStru(tmp, t.Point);
+ LvInsertAdd(b, ICO_TEST, NULL, 2, _UU("SM_FMINFO_POINT"), tmp);
+
+ UniToStru(tmp, t.Weight);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_FMINFO_WEIGHT"), tmp);
+
+ UniToStru(tmp, t.NumPort);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_NUM_PORT"), tmp);
+
+ for (i = 0;i < t.NumPort;i++)
+ {
+ wchar_t tmp2[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_PORT"), i + 1);
+ UniToStru(tmp2, t.Ports[i]);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, tmp, tmp2);
+ }
+
+ UniToStru(tmp, t.NumFarmHub);
+ LvInsertAdd(b, ICO_HUB_OFFLINE, NULL, 2, _UU("SM_FMINFO_NUM_HUB"), tmp);
+
+ for (i = 0;i < t.NumFarmHub;i++)
+ {
+ wchar_t tmp2[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_HUB"), i + 1);
+ UniFormat(tmp2, sizeof(tmp2),
+ t.FarmHubs[i].DynamicHub ? _UU("SM_FMINFO_HUB_TAG_2") : _UU("SM_FMINFO_HUB_TAG_1"),
+ t.FarmHubs[i].HubName);
+ LvInsertAdd(b, ICO_HUB, NULL, 2, tmp, tmp2);
+ }
+
+ UniToStru(tmp, t.NumSessions);
+ LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_FMINFO_NUM_SESSION"), tmp);
+
+ UniToStru(tmp, t.NumTcpConnections);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_NUN_CONNECTION"), tmp);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcFarmInfo(&t);
+
+ return true;
+}
+
+// Farm Member List dialog
+UINT SmFarmMemberDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *p = (SM_SERVER *)param;
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmFarmMemberDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Display the information of farm members
+ i = LvGetSelected(hWnd, L_FARM_MEMBER);
+ if (i != INFINITE)
+ {
+ SmStatusDlg(hWnd, p, LvGetParam(hWnd, L_FARM_MEMBER, i), false, true,
+ _UU("SM_FMINFO_CAPTION"), ICO_FARM, NULL, SmRefreshFarmMemberInfo);
+ }
+ break;
+
+ case B_CERT:
+ // Show the Server Certificate
+ i = LvGetSelected(hWnd, L_FARM_MEMBER);
+ if (i != INFINITE)
+ {
+ SmFarmMemberCert(hWnd, p, (UINT)LvGetParam(hWnd, L_FARM_MEMBER, i));
+ }
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case B_REFRESH:
+ // Update
+ SmFarmMemberDlgRefresh(hWnd, p);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ switch (n->idFrom)
+ {
+ case L_FARM_MEMBER:
+ SmFarmMemberDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_FARM_MEMBER);
+
+ return 0;
+}
+
+// Convert the string to port list
+LIST *SmStrToPortList(char *str)
+{
+ return StrToPortList(str);
+}
+
+// Initialize the dialog
+void SmFarmDlgInit(HWND hWnd, SM_SERVER *p)
+{
+ RPC_FARM t;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_FARM);
+
+ // Get the current settings
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetFarmSetting(p->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ if (t.Weight == 0)
+ {
+ t.Weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ FormatText(hWnd, S_TITLE, p->ServerName);
+ DlgFont(hWnd, S_CURRENT, 11, true);
+
+ SetText(hWnd, S_CURRENT, GetServerTypeStr(t.ServerType));
+
+ switch (t.ServerType)
+ {
+ case SERVER_TYPE_FARM_CONTROLLER:
+ Check(hWnd, R_CONTROLLER, true);
+ break;
+
+ case SERVER_TYPE_FARM_MEMBER:
+ Check(hWnd, R_MEMBER, true);
+ break;
+
+ default:
+ Check(hWnd, R_STANDALONE, true);
+ break;
+ }
+
+ SetInt(hWnd, E_WEIGHT, t.Weight);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ Check(hWnd, R_CONTROLLER_ONLY, t.ControllerOnly);
+ }
+
+ if (t.ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ char tmp[MAX_PUBLIC_PORT_NUM * 8];
+ UINT i;
+ if (t.PublicIp != 0)
+ {
+ IpSet(hWnd, E_IP, t.PublicIp);
+ }
+ StrCpy(tmp, sizeof(tmp), "");
+ if (t.NumPort != 0)
+ {
+ for (i = 0;i < t.NumPort;i++)
+ {
+ Format(tmp, sizeof(tmp), "%s%u", tmp, t.Ports[i]);
+ if (i != (t.NumPort - 1))
+ {
+ StrCat(tmp, sizeof(tmp), ", ");
+ }
+ }
+ SetTextA(hWnd, E_PORT, tmp);
+ }
+ SetTextA(hWnd, E_CONTROLLER, t.ControllerName);
+ SetIntEx(hWnd, E_CONTROLLER_PORT, t.ControllerPort);
+ SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
+ }
+ else
+ {
+ // Write the port list
+ RPC_LISTENER_LIST t;
+ char tmp[MAX_PUBLIC_PORT_NUM * 8];
+ Zero(&t, sizeof(t));
+ StrCpy(tmp, sizeof(tmp), "");
+ if (CALL(hWnd, ScEnumListener(p->Rpc, &t)))
+ {
+ UINT i;
+ if (t.NumPort != 0)
+ {
+ for (i = 0;i < t.NumPort;i++)
+ {
+ Format(tmp, sizeof(tmp), "%s%u", tmp, t.Ports[i]);
+ if (i != (t.NumPort - 1))
+ {
+ StrCat(tmp, sizeof(tmp), ", ");
+ }
+ }
+ SetTextA(hWnd, E_PORT, tmp);
+ }
+ FreeRpcListenerList(&t);
+ }
+ }
+
+ SmFarmDlgUpdate(hWnd, p);
+
+ FreeRpcFarm(&t);
+
+ Focus(hWnd, IDOK);
+}
+
+// Dialog update
+void SmFarmDlgUpdate(HWND hWnd, SM_SERVER *p)
+{
+ bool ok = true;
+ bool farm_member_control = false;
+ char *s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsChecked(hWnd, R_MEMBER))
+ {
+ LIST *o;
+ UINT i = IpGetFilledNum(hWnd, E_IP);
+ if (i != 0 && i != 4)
+ {
+ ok = false;
+ }
+
+ s = GetTextA(hWnd, E_PORT);
+ o = SmStrToPortList(s);
+ if (o == NULL)
+ {
+ ok = false;
+ }
+ else
+ {
+ ReleaseList(o);
+ }
+ Free(s);
+
+ if (IsEmpty(hWnd, E_CONTROLLER))
+ {
+ ok = false;
+ }
+
+ i = GetInt(hWnd, E_CONTROLLER_PORT);
+ if (i == 0 || i >= 65536)
+ {
+ ok = false;
+ }
+
+ farm_member_control = true;
+ }
+
+ if (IsChecked(hWnd, R_STANDALONE))
+ {
+ Disable(hWnd, S_1);
+ Disable(hWnd, S_2);
+ Disable(hWnd, E_WEIGHT);
+ }
+ else
+ {
+ Enable(hWnd, S_1);
+ Enable(hWnd, S_2);
+ Enable(hWnd, E_WEIGHT);
+ }
+
+ if (IsChecked(hWnd, R_CONTROLLER))
+ {
+ Enable(hWnd, R_CONTROLLER_ONLY);
+ }
+ else
+ {
+ Disable(hWnd, R_CONTROLLER_ONLY);
+ }
+
+ if (IsChecked(hWnd, R_CONTROLLER) || IsChecked(hWnd, R_MEMBER))
+ {
+ if (GetInt(hWnd, E_WEIGHT) == 0)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, S_IP_1, farm_member_control);
+ SetEnable(hWnd, E_IP, farm_member_control);
+ SetEnable(hWnd, S_IP_2, farm_member_control);
+ SetEnable(hWnd, S_PORT_1, farm_member_control);
+ SetEnable(hWnd, E_PORT, farm_member_control);
+ SetEnable(hWnd, S_PORT_2, farm_member_control);
+ SetEnable(hWnd, S_PORT_3, farm_member_control);
+ SetEnable(hWnd, E_CONTROLLER, farm_member_control);
+ SetEnable(hWnd, S_CONTROLLER, farm_member_control);
+ SetEnable(hWnd, E_CONTROLLER_PORT, farm_member_control);
+ SetEnable(hWnd, S_CONTROLLER_PORT, farm_member_control);
+ SetEnable(hWnd, S_PASSWORD, farm_member_control);
+ SetEnable(hWnd, E_PASSWORD, farm_member_control);
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// [OK] button
+void SmFarmDlgOnOk(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Display the message
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_OKCANCEL | MB_DEFBUTTON2,
+ _UU("SM_FARM_REBOOT_MSG")) == IDOK)
+ {
+ RPC_FARM t;
+ Zero(&t, sizeof(t));
+ t.ServerType = SERVER_TYPE_STANDALONE;
+ if (IsChecked(hWnd, R_CONTROLLER))
+ {
+ t.ServerType = SERVER_TYPE_FARM_CONTROLLER;
+ }
+ if (IsChecked(hWnd, R_MEMBER))
+ {
+ t.ServerType = SERVER_TYPE_FARM_MEMBER;
+ }
+
+ t.ControllerOnly = IsChecked(hWnd, R_CONTROLLER_ONLY);
+ t.Weight = GetInt(hWnd, E_WEIGHT);
+
+ if (t.ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ char *s;
+ char pass[MAX_SIZE];
+ t.PublicIp = IpGet(hWnd, E_IP);
+ s = GetTextA(hWnd, E_PORT);
+ if (s != NULL)
+ {
+ LIST *o = SmStrToPortList(s);
+ if (o != NULL)
+ {
+ UINT i;
+ t.NumPort = LIST_NUM(o);
+ t.Ports = ZeroMalloc(sizeof(UINT) * t.NumPort);
+ for (i = 0;i < t.NumPort;i++)
+ {
+ t.Ports[i] = (UINT)LIST_DATA(o, i);
+ }
+ ReleaseList(o);
+ }
+ Free(s);
+ }
+ GetTxtA(hWnd, E_CONTROLLER, t.ControllerName, sizeof(t.ControllerName));
+ t.ControllerPort = GetInt(hWnd, E_CONTROLLER_PORT);
+ GetTxtA(hWnd, E_PASSWORD, pass, sizeof(pass));
+ if (StrCmp(pass, HIDDEN_PASSWORD) != 0)
+ {
+ Hash(t.MemberPassword, pass, StrLen(pass), true);
+ }
+ }
+
+ // Configuration update
+ if (CALL(hWnd, ScSetFarmSetting(p->Rpc, &t)) == false)
+ {
+ return;
+ }
+
+ FreeRpcFarm(&t);
+
+ EndDialog(hWnd, true);
+ }
+}
+
+// Server farm dialog procedure
+UINT SmFarmDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *p = (SM_SERVER *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmFarmDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_STANDALONE:
+ case R_CONTROLLER:
+ case R_MEMBER:
+ case E_IP:
+ case E_PORT:
+ case E_CONTROLLER:
+ case E_CONTROLLER_PORT:
+ case E_PASSWORD:
+ case R_CONTROLLER_ONLY:
+ case E_WEIGHT:
+ SmFarmDlgUpdate(hWnd, p);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmFarmDlgOnOk(hWnd, p);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_MEMBER:
+ if (IsChecked(hWnd, R_MEMBER))
+ {
+ Focus(hWnd, E_IP);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Server farm configuration
+bool SmFarmDlg(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_SM_FARM, SmFarmDlgProc, p);
+}
+
+// Update the connection information
+bool SmRefreshConnectionStatus(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_CONNECTION_INFO t;
+ SM_CONNECTION_INFO *info = (SM_CONNECTION_INFO *)param;
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), info->ConnectionName);
+ if (CALL(hWnd, ScGetConnectionInfo(p->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ StrToUni(tmp, sizeof(tmp), t.Name);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_CONNINFO_NAME"), tmp);
+
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_TYPE"), SmGetConnectionTypeStr(t.Type));
+
+ StrToUni(tmp, sizeof(tmp), t.Hostname);
+ LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_CONNINFO_HOSTNAME"), tmp);
+
+ UniToStru(tmp, t.Port);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_CONNINFO_PORT"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_CONNINFO_TIME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.ServerStr);
+ LvInsertAdd(b, ICO_VPNSERVER, NULL, 2, _UU("SM_CONNINFO_SERVER_STR"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ServerVer / 100, t.ServerVer % 100);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_SERVER_VER"), tmp);
+
+ UniToStru(tmp, t.ServerBuild);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_SERVER_BUILD"), tmp);
+
+ if (StrLen(t.ClientStr) != 0)
+ {
+ StrToUni(tmp, sizeof(tmp), t.ClientStr);
+ LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_CONNINFO_CLIENT_STR"), tmp);
+
+ UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ClientVer / 100, t.ClientVer % 100);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_CLIENT_VER"), tmp);
+
+ UniToStru(tmp, t.ClientBuild);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_CLIENT_BUILD"), tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ return true;
+}
+
+// Initialize
+void SmConnectionDlgInit(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_PROTOCOL);
+ FormatText(hWnd, S_TITLE, p->ServerName);
+
+ // Initialize the column
+ LvInit(hWnd, L_LIST);
+ LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_CONN_COLUMN_1"), 90);
+ LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_CONN_COLUMN_2"), 150);
+ LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_CONN_COLUMN_3"), 200);
+ LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_CONN_COLUMN_4"), 80);
+
+ SmConnectionDlgRefresh(hWnd, p);
+ SmConnectionDlgUpdate(hWnd, p);
+}
+
+// Update
+void SmConnectionDlgRefresh(HWND hWnd, SM_SERVER *p)
+{
+ LVB *b;
+ UINT i;
+ RPC_ENUM_CONNECTION t;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumConnection(p->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < t.NumConnection;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t name[MAX_SIZE];
+ wchar_t datetime[MAX_SIZE];
+ RPC_ENUM_CONNECTION_ITEM *e = &t.Connections[i];
+
+ StrToUni(name, sizeof(name), e->Name);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_HOSTNAME_AND_PORT"), e->Hostname, e->Port);
+ GetDateTimeStrEx64(datetime, sizeof(datetime), SystemToLocal64(e->ConnectedTime), NULL);
+
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 4, name, tmp, datetime,
+ SmGetConnectionTypeStr(e->Type));
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ FreeRpcEnumConnetion(&t);
+}
+
+// Update the control
+void SmConnectionDlgUpdate(HWND hWnd, SM_SERVER *p)
+{
+ bool b = false;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_LIST) && (LvIsMultiMasked(hWnd, L_LIST) == false))
+ {
+ b = true;
+ }
+
+ SetEnable(hWnd, IDOK, b);
+ SetEnable(hWnd, B_DISCONNECT, b && p->ServerAdminMode);
+}
+
+// Connection List procedure
+UINT SmConnectionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *p = (SM_SERVER *)param;
+ NMHDR *n;
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmConnectionDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Show the connection information
+ s = LvGetSelectedStr(hWnd, L_LIST, 0);
+ if (s != NULL)
+ {
+ wchar_t caption[MAX_SIZE];
+ SM_CONNECTION_INFO info;
+ UniFormat(caption, sizeof(caption), _UU("SM_CONNINFO_CAPTION"),
+ s);
+ Zero(&info, sizeof(info));
+ info.ConnectionName = CopyUniToStr(s);
+ info.p = p;
+ SmStatusDlg(hWnd, p, &info, false, false, caption, ICO_PROTOCOL,
+ NULL, SmRefreshConnectionStatus);
+ Free(info.ConnectionName);
+ Free(s);
+ }
+ break;
+
+ case B_DISCONNECT:
+ // Disconnect
+ s = LvGetSelectedStr(hWnd, L_LIST, 0);
+ if (s != NULL)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_CONN_DISCONNECT_MSG"), s) == IDYES)
+ {
+ char tmp[MAX_SIZE];
+ RPC_DISCONNECT_CONNECTION t;
+
+ UniToStr(tmp, sizeof(tmp), s);
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), tmp);
+
+ if (CALL(hWnd, ScDisconnectConnection(p->Rpc, &t)))
+ {
+ SmConnectionDlgRefresh(hWnd, p);
+ }
+ }
+ Free(s);
+ }
+ break;
+
+ case B_REFRESH:
+ // Update to the latest state
+ SmConnectionDlgRefresh(hWnd, p);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmConnectionDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);
+
+ return 0;
+}
+
+// Display the connection list
+void SmConnectionDlg(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_SM_CONNECTION, SmConnectionDlgProc, p);
+}
+
+// Get the connection type string
+wchar_t *SmGetConnectionTypeStr(UINT type)
+{
+ return GetConnectionTypeStr(type);
+}
+
+// Update the server information
+bool SmRefreshServerInfo(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_SERVER_INFO t;
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetServerInfo(p->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ // Product name
+ StrToUni(tmp, sizeof(tmp), t.ServerProductName);
+ LvInsertAdd(b, ICO_VPNSERVER, NULL, 2, _UU("SM_INFO_PRODUCT_NAME"), tmp);
+
+ // Version
+ StrToUni(tmp, sizeof(tmp), t.ServerVersionString);
+ LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_INFO_VERSION"), tmp);
+
+ // Build
+ StrToUni(tmp, sizeof(tmp), t.ServerBuildInfoString);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_INFO_BUILD"), tmp);
+
+ // Host name
+ StrToUni(tmp, sizeof(tmp), t.ServerHostName);
+ LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("SM_INFO_HOSTNAME"), tmp);
+
+ // Type
+ LvInsertAdd(b, t.ServerType == SERVER_TYPE_STANDALONE ? ICO_SERVER_ONLINE : ICO_FARM, 0,
+ 2, _UU("SM_ST_SERVER_TYPE"),
+ GetServerTypeStr(t.ServerType));
+
+ // OS
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SYSTEM_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_PRODUCT_NAME"), tmp);
+
+ if (t.OsInfo.OsServicePack != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SERVICE_PACK"), tmp);
+ }
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VENDER_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VERSION"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_NAME"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_VERSION"), tmp);
+
+ SmAddServerCaps(b, p->CapsList);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ FreeRpcServerInfo(&t);
+
+ return true;
+}
+
+// Display the Caps of the server on the screen
+void SmAddServerCaps(LVB *b, CAPSLIST *t)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->CapsList);i++)
+ {
+ CAPS *c = LIST_DATA(t->CapsList, i);
+ wchar_t title[MAX_SIZE];
+ char name[256];
+
+ Format(name, sizeof(name), "CT_%s", c->Name);
+
+ UniStrCpy(title, sizeof(title), _UU(name));
+
+ if (UniIsEmptyStr(title))
+ {
+ UniFormat(title, sizeof(title), L"%S", (StrLen(c->Name) >= 2) ? c->Name + 2 : c->Name);
+ }
+
+ if (StartWith(c->Name, "b_"))
+ {
+ bool icon_pass = c->Value == 0 ? false : true;
+ if (StrCmpi(c->Name, "b_must_install_pcap") == 0)
+ {
+ // Invert only the item of WinPcap
+ icon_pass = !icon_pass;
+ }
+ LvInsertAdd(b, icon_pass == false ? ICO_DISCARD : ICO_PASS,
+ NULL, 2, title, c->Value == 0 ? _UU("CAPS_NO") : _UU("CAPS_YES"));
+ }
+ else
+ {
+ wchar_t str[64];
+ UniToStru(str, c->Value);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, title, str);
+ }
+ }
+}
+
+// Update the server state
+bool SmRefreshServerStatus(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_SERVER_STATUS t;
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetServerStatus(p->Rpc, &t)) == false)
+ {
+ return false;
+ }
+
+ b = LvInsertStart();
+
+ // Type of server
+ LvInsertAdd(b, t.ServerType == SERVER_TYPE_STANDALONE ? ICO_SERVER_ONLINE : ICO_FARM, 0,
+ 2, _UU("SM_ST_SERVER_TYPE"),
+ GetServerTypeStr(t.ServerType));
+
+ // Number of TCP connections
+ UniToStru(tmp, t.NumTcpConnections);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Number of Local TCP connections
+ UniToStru(tmp, t.NumTcpConnectionsLocal);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP_LOCAL"), tmp);
+
+ // Number of remote TCP connections
+ UniToStru(tmp, t.NumTcpConnectionsRemote);
+ LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP_REMOTE"), tmp);
+ }
+
+ // Number of Virtual HUBs
+ UniToStru(tmp, t.NumHubTotal);
+ LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_TOTAL"), tmp);
+
+ if (t.ServerType != SERVER_TYPE_STANDALONE)
+ {
+ // Number of static HUBs
+ UniToStru(tmp, t.NumHubStatic);
+ LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_STATIC"), tmp);
+
+ // Number of Dynamic HUBs
+ UniToStru(tmp, t.NumHubDynamic);
+ LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_DYNAMIC"), tmp);
+ }
+
+ // Number of sessions
+ UniToStru(tmp, t.NumSessionsTotal);
+ LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_TOTAL"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Number of local sessions
+ UniToStru(tmp, t.NumSessionsLocal);
+ LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_LOCAL"), tmp);
+
+ // Number of local sessions
+ UniToStru(tmp, t.NumSessionsRemote);
+ LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_REMOTE"), tmp);
+ }
+
+ // Number of MAC table entries
+ UniToStru(tmp, t.NumMacTables);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_ST_NUM_MAC_TABLE"), tmp);
+
+ // Number of IP table entries
+ UniToStru(tmp, t.NumIpTables);
+ LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_ST_NUM_IP_TABLE"), tmp);
+
+ // Number of users
+ UniToStru(tmp, t.NumUsers);
+ LvInsertAdd(b, ICO_USER, NULL, 2, _UU("SM_ST_NUM_USERS"), tmp);
+
+ // Number of groups
+ UniToStru(tmp, t.NumGroups);
+ LvInsertAdd(b, ICO_GROUP, NULL, 2, _UU("SM_ST_NUM_GROUPS"), tmp);
+
+ // Number of assigned licenses
+ UniToStru(tmp, t.AssignedClientLicenses);
+ LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_CLIENT_LICENSE"), tmp);
+ UniToStru(tmp, t.AssignedBridgeLicenses);
+ LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_BRIDGE_LICENSE"), tmp);
+
+ if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ UniToStru(tmp, t.AssignedClientLicensesTotal);
+ LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_CLIENT_LICENSE_EX"), tmp);
+ UniToStru(tmp, t.AssignedBridgeLicensesTotal);
+ LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_BRIDGE_LICENSE_EX"), tmp);
+ }
+
+ // Traffic
+ SmInsertTrafficInfo(b, &t.Traffic);
+
+ // Server start-up time
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartTime), NULL);
+ LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_START_TIME"), tmp);
+
+ // Current time
+ GetDateTimeStrMilli64(str, sizeof(str), SystemToLocal64(t.CurrentTime));
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_CURRENT_TIME"), tmp);
+
+ // Tick value
+ UniFormat(tmp, sizeof(tmp), L"%I64u", t.CurrentTick);
+ LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_CURRENT_TICK"), tmp);
+
+ // Memory information
+ if (t.MemInfo.TotalMemory != 0)
+ {
+ char vv[128];
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_MEMORY"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_PHYS"), tmp);
+
+ ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);
+ LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_PHYS"), tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+
+ return true;
+}
+
+// Initialize
+void SmSaveKeyPairDlgInit(HWND hWnd, SM_SAVE_KEY_PAIR *s)
+{
+ UINT current;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ current = MsRegReadInt(REG_CURRENT_USER, SM_REG_KEY, "SavePkcs12");
+
+ if (current == 1)
+ {
+ Check(hWnd, R_PKCS12, true);
+ }
+ else if (current == 2)
+ {
+ Check(hWnd, R_SECURE, true);
+ }
+ else
+ {
+ Check(hWnd, R_X509_AND_KEY, true);
+ }
+
+ SmSaveKeyPairDlgUpdate(hWnd, s);
+}
+
+// Update
+void SmSaveKeyPairDlgUpdate(HWND hWnd, SM_SAVE_KEY_PAIR *s)
+{
+ SECURE_DEVICE *dev;
+ bool ok = true;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ dev = GetSecureDevice(SmGetCurrentSecureIdFromReg());
+ if (dev == NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SEC_CURRENT_NO_DEVICE"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SEC_CURRENT_DEVICE"), dev->DeviceName);
+ }
+
+ SetText(hWnd, S_INFO, tmp);
+
+ if (IsChecked(hWnd, R_USE_PASS))
+ {
+ char *s1, *s2;
+ s1 = GetTextA(hWnd, E_PASS1);
+ s2 = GetTextA(hWnd, E_PASS2);
+ if (StrCmp(s1, s2) != 0)
+ {
+ ok = false;
+ }
+ Free(s1);
+ Free(s2);
+ }
+
+ if (IsChecked(hWnd, R_SECURE))
+ {
+ if (dev == NULL)
+ {
+ ok = false;
+ }
+ }
+
+ SetEnable(hWnd, B_SELECT, IsChecked(hWnd, R_SECURE));
+ SetEnable(hWnd, B_SECURE_MANAGER, IsChecked(hWnd, R_SECURE));
+ SetEnable(hWnd, S_INFO, IsChecked(hWnd, R_SECURE));
+
+ SetEnable(hWnd, E_PASS1, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, E_PASS2, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, S_PASS1, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, S_PASS2, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, R_USE_PASS, (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, S_PASS3, (IsChecked(hWnd, R_SECURE) == false));
+ SetEnable(hWnd, S_PASS4, (IsChecked(hWnd, R_SECURE) == false));
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// [OK] button
+void SmSaveKeyPairDlgOnOk(HWND hWnd, SM_SAVE_KEY_PAIR *s)
+{
+ UINT pkcs12;
+ char pass[MAX_SIZE];
+ char *password;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ pkcs12 = 0;
+
+ if (IsChecked(hWnd, R_PKCS12))
+ {
+ pkcs12 = 1;
+ }
+ else if (IsChecked(hWnd, R_SECURE))
+ {
+ pkcs12 = 2;
+ }
+ MsRegWriteInt(REG_CURRENT_USER, SM_REG_KEY, "SavePkcs12", pkcs12);
+
+ if (pkcs12 != 2)
+ {
+ GetTxtA(hWnd, E_PASS1, pass, sizeof(pass));
+
+ if (StrLen(pass) != 0)
+ {
+ password = pass;
+ }
+ else
+ {
+ password = NULL;
+ }
+
+ if (pkcs12 == false)
+ {
+ // Write to the X509 and KEY
+ wchar_t *x509_name, *key_name;
+ x509_name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
+ if (x509_name == NULL)
+ {
+ // Cancel
+ return;
+ }
+ else
+ {
+ wchar_t default_key_name[MAX_SIZE];
+ UniReplaceStrEx(default_key_name, sizeof(default_key_name), x509_name,
+ L".cer", L"", false);
+ UniReplaceStrEx(default_key_name, sizeof(default_key_name), default_key_name,
+ L".crt", L"", false);
+ UniStrCat(default_key_name, sizeof(default_key_name), L".key");
+ key_name = SaveDlg(hWnd, _UU("DLG_KEY_FILTER"), _UU("DLG_SAVE_KEY"),
+ default_key_name, L".key");
+ if (key_name == NULL)
+ {
+ // Cancel
+ Free(x509_name);
+ return;
+ }
+ else
+ {
+ bool ok = true;
+ wchar_t filename1[MAX_SIZE];
+ wchar_t filename2[MAX_SIZE];
+
+ UniStrCpy(filename1, sizeof(filename1), x509_name);
+ UniStrCpy(filename2, sizeof(filename2), key_name);
+
+ // Save the certificate
+ if (XToFileW(s->Cert, filename1, true) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
+ ok = false;
+ }
+ else
+ {
+ if (KToFileW(s->Key, filename2, true, password) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_SAVE_ERROR"));
+ ok = false;
+ }
+ }
+
+ if (ok)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_KEY_PAIR_SAVE_OK"));
+ EndDialog(hWnd, true);
+ }
+
+ Free(key_name);
+ }
+ Free(x509_name);
+ }
+ }
+ else
+ {
+ // Write to the PKCS#12
+ wchar_t *name = SaveDlg(hWnd, _UU("DLG_PKCS12_FILTER"), _UU("DLG_SAVE_P12"), NULL, L".p12");
+ if (name == NULL)
+ {
+ // Cancel
+ return;
+ }
+ else
+ {
+ P12 *p12;
+ wchar_t filename[MAX_SIZE];
+ UniStrCpy(filename, sizeof(filename), name);
+
+ // Convert to PKCS#12
+ p12 = NewP12(s->Cert, s->Key, pass);
+ if (p12 == NULL)
+ {
+ // Failure
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_PAIR_SAVE_ERROR"));
+ }
+ else
+ {
+ // Save
+ if (P12ToFileW(p12, filename) == false)
+ {
+ // Failure
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_PAIR_SAVE_ERROR"));
+ }
+ else
+ {
+ // Success
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_KEY_PAIR_SAVE_OK"));
+ EndDialog(hWnd, true);
+ }
+ FreeP12(p12);
+ }
+
+ Free(name);
+ }
+ }
+ }
+ else
+ {
+ char default_name[MAX_SIZE];
+ char *object_name;
+ bool ok = false;
+ X *x;
+ K *k;
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_WRITE_CERT, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ {WINUI_SECURE_WRITE_KEY, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+
+ x = s->Cert;
+ k = s->Key;
+
+ // Generate the default name
+ GetPrintNameFromXA(default_name, sizeof(default_name), x);
+ ConvertSafeFileName(default_name, sizeof(default_name), default_name);
+
+ object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
+ _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);
+
+ if (object_name != NULL)
+ {
+ // Write and enumerate
+ batch[0].InputX = x;
+ batch[0].Name = object_name;
+ batch[1].InputK = k;
+ batch[1].Name = object_name;
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), SmGetCurrentSecureIdFromReg(), 0) == false)
+ {
+ // Failure
+ }
+ else
+ {
+ ok = true;
+ }
+
+ Free(object_name);
+ }
+
+ if (ok)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NEW_CERT_IMPORT_OK"));
+
+ EndDialog(hWnd, true);
+ }
+ }
+}
+
+// Saving dialog box of the certificate and private key
+UINT SmSaveKeyPairDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SAVE_KEY_PAIR *s = (SM_SAVE_KEY_PAIR *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmSaveKeyPairDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_PASS1:
+ case E_PASS2:
+ case R_USE_PASS:
+ case R_SECURE:
+ case R_X509_AND_KEY:
+ case R_PKCS12:
+ SmSaveKeyPairDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmSaveKeyPairDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case R_USE_PASS:
+ if (IsChecked(hWnd, R_USE_PASS))
+ {
+ FocusEx(hWnd, E_PASS1);
+ }
+ break;
+
+ case B_SELECT:
+ SmSelectSecureId(hWnd);
+ SmSaveKeyPairDlgUpdate(hWnd, s);
+ break;
+
+ case B_SECURE_MANAGER:
+ CmSecureManagerEx(hWnd, SmGetCurrentSecureId(hWnd), true);
+ SmSaveKeyPairDlgUpdate(hWnd, s);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Save the certificate and private key
+bool SmSaveKeyPairDlg(HWND hWnd, X *x, K *k)
+{
+ SM_SAVE_KEY_PAIR s;
+ // Validate arguments
+ if (hWnd == NULL || x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Zero(&s, sizeof(s));
+ s.Cert = x;
+ s.Key = k;
+
+ return Dialog(hWnd, D_SM_SAVE_KEY_PAIR, SmSaveKeyPairDlgProc, &s);
+}
+
+// OK is clicked on the SSL related dialog
+void SmSslDlgOnOk(HWND hWnd, SM_SSL *s)
+{
+ char *name;
+ RPC_KEEP t;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (s->p->ServerAdminMode == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ name = GetTextA(hWnd, C_CIPHER);
+ if (name == NULL)
+ {
+ return;
+ }
+ else
+ {
+ RPC_STR t;
+ Zero(&t, sizeof(t));
+ t.String = name;
+
+ // Set the encryption algorithm
+ if (CALL(hWnd, ScSetServerCipher(s->p->Rpc, &t)) == false)
+ {
+ Focus(hWnd, C_CIPHER);
+ return;
+ }
+ FreeRpcStr(&t);
+ }
+
+ if (s->SetCertAndKey)
+ {
+ // Set the certificate
+ RPC_KEY_PAIR t;
+ Zero(&t, sizeof(t));
+
+ t.Cert = CloneX(s->Cert);
+ t.Key = CloneK(s->Key);
+
+ if (CALL(hWnd, ScSetServerCert(s->p->Rpc, &t)) == false)
+ {
+ return;
+ }
+ FreeRpcKeyPair(&t);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_CERT_SET_MSG"));
+ }
+
+ Zero(&t, sizeof(t));
+ t.UseKeepConnect = IsChecked(hWnd, R_USE_KEEP_CONNECT);
+ GetTxtA(hWnd, E_HOSTNAME, t.KeepConnectHost, sizeof(t.KeepConnectHost));
+ t.KeepConnectPort = GetInt(hWnd, E_PORT);
+ t.KeepConnectInterval = GetInt(hWnd, E_INTERVAL);
+ t.KeepConnectProtocol = IsChecked(hWnd, R_UDP) ? 1 : 0;
+
+ CALL(hWnd, ScSetKeep(s->p->Rpc, &t));
+
+ if (GetCapsBool(s->p->CapsList, "b_support_syslog"))
+ {
+ if (s->p->ServerAdminMode)
+ {
+ SYSLOG_SETTING set;
+
+ Zero(&set, sizeof(set));
+ GetTxtA(hWnd, E_SYSLOG_HOSTNAME, set.Hostname, sizeof(set.Hostname));
+ set.Port = GetInt(hWnd, E_SYSLOG_PORT);
+ set.SaveType = CbGetSelect(hWnd, C_SYSLOG);
+
+ if (CALL(hWnd, ScSetSysLog(s->p->Rpc, &set)) == false)
+ {
+ return;
+ }
+ }
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// SSL related dialog initialization
+void SmSslDlgInit(HWND hWnd, SM_SSL *s)
+{
+ UINT i;
+ TOKEN_LIST *cipher_list;
+ RPC_KEEP t;
+ bool private_key_exportable = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ // Set the encryption algorithm list
+ cipher_list = GetCipherList();
+ CbSetHeight(hWnd, C_CIPHER, 18);
+ for (i = 0;i < cipher_list->NumTokens;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char *name = cipher_list->Token[i];
+ StrToUni(tmp, sizeof(tmp), name);
+ CbAddStr(hWnd, C_CIPHER, tmp, 0);
+ }
+
+ if (s->p != NULL)
+ {
+ // Get the encryption algorithm name from the server
+ RPC_STR t;
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetServerCipher(s->p->Rpc, &t)))
+ {
+ wchar_t tmp[MAX_SIZE];
+ StrToUni(tmp, sizeof(tmp), t.String);
+ SetText(hWnd, C_CIPHER, tmp);
+ FreeRpcStr(&t);
+ }
+ else
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+ }
+
+ if (s->p != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ // Get the SSL certificate and private key from the server
+ RPC_KEY_PAIR t;
+ s->SetCertAndKey = false;
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScGetServerCert(s->p->Rpc, &t)))
+ {
+ // Copy the certificate and key
+ s->Cert = CloneX(t.Cert);
+ s->Key = CloneK(t.Key);
+
+ if (t.Key != NULL)
+ {
+ private_key_exportable = true;
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ else
+ {
+ EndDialog(hWnd, 0);
+ return;
+ }
+
+ // Show the Certificate Information
+ SmGetCertInfoStr(tmp, sizeof(tmp), s->Cert);
+ SetText(hWnd, S_CERT_INFO, tmp);
+ }
+
+ // Password change
+ SetEnable(hWnd, B_PASSWORD, s->p->ServerAdminMode);
+ SetEnable(hWnd, S_INFO4, s->p->ServerAdminMode);
+
+ // Enable / disable the button
+ SetEnable(hWnd, B_IMPORT, s->p->ServerAdminMode);
+ SetEnable(hWnd, B_EXPORT, s->p->ServerAdminMode && private_key_exportable);
+ SetEnable(hWnd, B_REGENERATE, s->p->ServerAdminMode);
+ SetEnable(hWnd, R_USE_KEEP_CONNECT, s->p->ServerAdminMode);
+ SetEnable(hWnd, B_UPDATE_CONFIG, s->p->Update != NULL);
+
+ if (s->p->ServerAdminMode && GetCapsBool(s->p->CapsList, "b_support_special_listener"))
+ {
+ SetEnable(hWnd, B_SPECIALLISTENER, true);
+ SetEnable(hWnd, S_INFO5, true);
+ }
+ else
+ {
+ SetEnable(hWnd, B_SPECIALLISTENER, false);
+ SetEnable(hWnd, S_INFO5, false);
+ }
+
+ if (s->p->ServerAdminMode == false)
+ {
+ Disable(hWnd, C_CIPHER);
+ }
+
+ if (CALL(hWnd, ScGetKeep(s->p->Rpc, &t)))
+ {
+ Check(hWnd, R_USE_KEEP_CONNECT, t.UseKeepConnect);
+ SetTextA(hWnd, E_HOSTNAME, t.KeepConnectHost);
+ SetIntEx(hWnd, E_PORT, t.KeepConnectPort);
+ SetInt(hWnd, E_INTERVAL, t.KeepConnectInterval);
+ Check(hWnd, R_TCP, t.KeepConnectProtocol == 0);
+ Check(hWnd, R_UDP, t.KeepConnectProtocol != 0);
+ }
+
+ CbSetHeight(hWnd, C_SYSLOG, 18);
+ CbReset(hWnd, C_SYSLOG);
+ CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_0"), SYSLOG_NONE);
+ CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_1"), SYSLOG_SERVER_LOG);
+ CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_2"), SYSLOG_SERVER_AND_HUB_SECURITY_LOG);
+ CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_3"), SYSLOG_SERVER_AND_HUB_ALL_LOG);
+
+ if (GetCapsBool(s->p->CapsList, "b_support_syslog"))
+ {
+ SYSLOG_SETTING set;
+
+ SetEnable(hWnd, C_SYSLOG, s->p->ServerAdminMode);
+ SetEnable(hWnd, E_SYSLOG_HOSTNAME, s->p->ServerAdminMode);
+ SetEnable(hWnd, E_SYSLOG_PORT, s->p->ServerAdminMode);
+ SetEnable(hWnd, S_01, s->p->ServerAdminMode);
+ SetEnable(hWnd, S_02, s->p->ServerAdminMode);
+
+ Zero(&set, sizeof(set));
+
+ if (CALL(hWnd, ScGetSysLog(s->p->Rpc, &set)))
+ {
+ SetTextA(hWnd, E_SYSLOG_HOSTNAME, set.Hostname);
+ SetInt(hWnd, E_SYSLOG_PORT, set.Port == 0 ? SYSLOG_PORT : set.Port);
+ CbSelect(hWnd, C_SYSLOG, set.SaveType);
+ }
+ }
+ else
+ {
+ Disable(hWnd, C_SYSLOG);
+ Disable(hWnd, E_SYSLOG_HOSTNAME);
+ Disable(hWnd, E_SYSLOG_PORT);
+ Disable(hWnd, S_01);
+ Disable(hWnd, S_02);
+ }
+
+ SmSslDlgUpdate(hWnd, s);
+}
+
+// SSL related dialog control update
+void SmSslDlgUpdate(HWND hWnd, SM_SSL *s)
+{
+ bool ok = true;
+ bool b;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
+ {
+ UINT i;
+ b = true;
+ if (IsEmpty(hWnd, E_HOSTNAME))
+ {
+ ok = false;
+ }
+ i = GetInt(hWnd, E_PORT);
+ if (i == 0 || i >= 65536)
+ {
+ ok = false;
+ }
+ i = GetInt(hWnd, E_INTERVAL);
+ if (i < 5 || i > 600)
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ b = false;
+ }
+
+ if (IsEnable(hWnd, C_SYSLOG))
+ {
+ UINT i = CbGetSelect(hWnd, C_SYSLOG);
+
+ SetEnable(hWnd, E_SYSLOG_HOSTNAME, i != SYSLOG_NONE);
+ SetEnable(hWnd, E_SYSLOG_PORT, i != SYSLOG_NONE);
+ SetEnable(hWnd, S_01, i != SYSLOG_NONE);
+ SetEnable(hWnd, S_02, i != SYSLOG_NONE);
+ }
+
+ SetEnable(hWnd, S_HOSTNAME, b);
+ SetEnable(hWnd, E_HOSTNAME, b);
+ SetEnable(hWnd, S_PORT, b);
+ SetEnable(hWnd, E_PORT, b);
+ SetEnable(hWnd, S_INTERVAL, b);
+ SetEnable(hWnd, E_INTERVAL, b);
+ SetEnable(hWnd, S_INTERVAL2, b);
+ SetEnable(hWnd, S_PROTOCOL, b);
+ SetEnable(hWnd, R_TCP, b);
+ SetEnable(hWnd, R_UDP, b);
+ SetEnable(hWnd, S_INFO, b);
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Get the certificate information string
+void SmGetCertInfoStr(wchar_t *str, UINT size, X *x)
+{
+ wchar_t subject[MAX_SIZE];
+ wchar_t issuer[MAX_SIZE];
+ wchar_t date[MAX_SIZE];
+ // Validate arguments
+ if (x == NULL || str == NULL)
+ {
+ if (str != NULL)
+ {
+ str[0] = 0;
+ }
+ return;
+ }
+
+ GetPrintNameFromName(subject, sizeof(subject), x->subject_name);
+ GetPrintNameFromName(issuer, sizeof(issuer), x->issuer_name);
+ GetDateStrEx64(date, sizeof(date), x->notAfter, NULL);
+
+ UniFormat(str, size, _UU("CM_CERT_INFO"), subject, issuer, date);
+}
+
+// Regenerate the server certificate
+bool SmRegenerateServerCert(HWND hWnd, SM_SERVER *server, char *default_cn, X **x, K **k, bool root_only)
+{
+ char defcn[MAX_SIZE];
+ // Validate arguments
+ if (server == NULL || x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Zero(defcn, sizeof(defcn));
+ if (IsEmptyStr(default_cn) == false)
+ {
+ StrCpy(defcn, sizeof(defcn), default_cn);
+ }
+
+ if (IsEmptyStr(defcn))
+ {
+ // If default CN is not specified, copy from the setting of the DDNS server
+ DDNS_CLIENT_STATUS t;
+
+ Zero(&t, sizeof(t));
+
+ if (ScGetDDnsClientStatus(server->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (IsEmptyStr(t.CurrentFqdn) == false)
+ {
+ StrCpy(defcn, sizeof(defcn), t.CurrentFqdn);
+ }
+ }
+ }
+
+ if (IsEmptyStr(defcn))
+ {
+ // Copy from the certificate information of the current server
+ RPC_KEY_PAIR t;
+
+ Zero(&t, sizeof(t));
+
+ if (ScGetServerCert(server->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.Cert != NULL)
+ {
+ if (t.Cert->subject_name != NULL)
+ {
+ UniToStr(defcn, sizeof(defcn), t.Cert->subject_name->CommonName);
+ }
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ }
+
+ if (IsEmptyStr(defcn))
+ {
+ // Copy from the destination server name of the current connection settings
+ StrCpy(defcn, sizeof(defcn), server->ServerName);
+ }
+
+ // Create a new certificate in the Certificate Creation Tool
+ if (SmCreateCert(hWnd, x, k, true, defcn, root_only) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// SSL related dialog procedure
+UINT SmSslDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SSL *s = (SM_SSL *)param;
+ X *x;
+ K *k;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SmSslDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_USE_KEEP_CONNECT:
+ case E_HOSTNAME:
+ case E_PORT:
+ case E_INTERVAL:
+ case R_TCP:
+ case R_UDP:
+ case C_SYSLOG:
+ case E_SYSLOG_HOSTNAME:
+ case E_SYSLOG_PORT:
+ SmSslDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ // [OK] button
+ SmSslDlgOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+
+ case B_UPDATE_CONFIG:
+ // Update notification setting
+ ConfigUpdateUi(s->p->Update, hWnd);
+ break;
+
+ case B_IMPORT:
+ // Import
+ if (CmLoadXAndK(hWnd, &x, &k))
+ {
+ wchar_t tmp[MAX_SIZE];
+
+LABEL_APPLY_NEW_CERT:
+ FreeX(s->Cert);
+ FreeK(s->Key);
+ s->Cert = x;
+ s->Key = k;
+ s->SetCertAndKey = true;
+ // Show the Certificate Information
+ SmGetCertInfoStr(tmp, sizeof(tmp), s->Cert);
+ SetText(hWnd, S_CERT_INFO, tmp);
+ }
+ break;
+
+ case B_EXPORT:
+ // Export
+ SmSaveKeyPairDlg(hWnd, s->Cert, s->Key);
+ break;
+
+ case B_VIEW:
+ // Show the certificate
+ CertDlg(hWnd, s->Cert, NULL, true);
+ break;
+
+ case B_SPECIALLISTENER:
+ // Special listener configuration
+ SmSpecialListener(hWnd, s->p);
+ break;
+
+ case B_REGENERATE:
+ // Regenerating the certificate
+ if (SmRegenerateServerCert(hWnd, s->p, NULL, &x, &k, false))
+ {
+ // Confirmation message
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO, _UU("SM_REGENERATE_CERT_MSG")) == IDYES)
+ {
+ goto LABEL_APPLY_NEW_CERT;
+ }
+ else
+ {
+ FreeX(x);
+ FreeK(k);
+ }
+ }
+ break;
+
+ case B_PASSWORD:
+ // Password change
+ Dialog(hWnd, D_SM_CHANGE_PASSWORD, SmChangeServerPasswordDlg, s->p);
+ break;
+
+ case R_USE_KEEP_CONNECT:
+ if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
+ {
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Display the SSL related dialog
+void SmSslDlg(HWND hWnd, SM_SERVER *p)
+{
+ SM_SSL s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(&s, sizeof(s));
+ s.p = p;
+
+ Dialog(hWnd, D_SM_SSL, SmSslDlgProc, &s);
+
+ // Cleanup
+ FreeX(s.Cert);
+ FreeK(s.Key);
+}
+
+// Listener creation dialog procedure
+UINT SmCreateListenerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT port;
+ RPC_LISTENER t;
+ SM_SERVER *p = (SM_SERVER *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ Focus(hWnd, E_PORT);
+ Disable(hWnd, IDOK);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_PORT:
+ port = GetInt(hWnd, E_PORT);
+ if (port == 0 || port >= 65536)
+ {
+ Disable(hWnd, IDOK);
+ }
+ else
+ {
+ Enable(hWnd, IDOK);
+ }
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ port = GetInt(hWnd, E_PORT);
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = port;
+ if (CALL(hWnd, ScCreateListener(p->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Listener creation dialog
+bool SmCreateListenerDlg(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_SM_CREATE_LISTENER, SmCreateListenerDlgProc, p);
+}
+
+// HUB edit OK button
+void SmEditHubOnOk(HWND hWnd, SM_EDIT_HUB *s)
+{
+ RPC_CREATE_HUB t;
+ char pass1[MAX_SIZE];
+ char pass2[MAX_SIZE];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ if (s->EditMode)
+ {
+ StrCpy(hubname, sizeof(hubname), s->HubName);
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ }
+ else
+ {
+ GetTxtA(hWnd, E_HUBNAME, t.HubName, sizeof(t.HubName));
+ StrCpy(hubname, sizeof(hubname), t.HubName);
+ }
+
+ GetTxtA(hWnd, E_PASSWORD1, pass1, sizeof(pass1));
+ GetTxtA(hWnd, E_PASSWORD2, pass2, sizeof(pass2));
+
+ if (s->EditMode == false || StrCmp(pass1, HIDDEN_PASSWORD) != 0)
+ {
+ Hash(t.HashedPassword, pass1, StrLen(pass1), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass1);
+ }
+
+ if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))
+ {
+ t.HubOption.MaxSession = GetInt(hWnd, E_MAX_SESSION);
+ }
+
+ t.Online = IsChecked(hWnd, R_ONLINE);
+
+ if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ t.HubType = HUB_TYPE_FARM_STATIC;
+ if (IsChecked(hWnd, R_DYNAMIC))
+ {
+ t.HubType = HUB_TYPE_FARM_DYNAMIC;
+ }
+ }
+
+ t.HubOption.NoEnum = IsChecked(hWnd, R_NO_ENUM);
+
+ if (s->EditMode == false)
+ {
+ if (CALL(hWnd, ScCreateHub(s->p->Rpc, &t)))
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_EDIT_HUB_CREATER"), hubname);
+ EndDialog(hWnd, true);
+ }
+ }
+ else
+ {
+ if (CALL(hWnd, ScSetHub(s->p->Rpc, &t)))
+ {
+ EndDialog(hWnd, true);
+ }
+ }
+}
+
+// HUB editing update
+void SmEditHubUpdate(HWND hWnd, SM_EDIT_HUB *s)
+{
+ bool ok = true;
+ char *s1, *s2;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ s1 = GetTextA(hWnd, E_PASSWORD1);
+ s2 = GetTextA(hWnd, E_PASSWORD2);
+ if (StrCmp(s1, s2) != 0)
+ {
+ ok = false;
+ }
+ Free(s1);
+ Free(s2);
+
+ GetTxtA(hWnd, E_HUBNAME, hubname, sizeof(hubname));
+ Trim(hubname);
+ if (StrLen(hubname) == 0 ||
+ IsSafeStr(hubname) == false)
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))
+ {
+ Enable(hWnd, E_MAX_SESSION);
+ Enable(hWnd, S_MAX_SESSION_1);
+ Enable(hWnd, S_MAX_SESSION_2);
+ if (GetInt(hWnd, E_MAX_SESSION) == 0)
+ {
+ ok = false;
+ }
+ }
+ else
+ {
+ Disable(hWnd, E_MAX_SESSION);
+ Disable(hWnd, S_MAX_SESSION_1);
+ Disable(hWnd, S_MAX_SESSION_2);
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// HUB editing initialization
+void SmEditHubInit(HWND hWnd, SM_EDIT_HUB *s)
+{
+ RPC_CREATE_HUB t;
+ bool b = false;
+ bool support_extoption = false;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_HUB);
+
+ Zero(&t, sizeof(t));
+
+ if (s->EditMode == false)
+ {
+ // Create new
+ SetText(hWnd, 0, _UU("CM_EDIT_HUB_1"));
+ FocusEx(hWnd, E_HUBNAME);
+
+ if (s->p->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // Stand-alone mode
+ Disable(hWnd, R_STATIC);
+ Disable(hWnd, R_DYNAMIC);
+ SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_STANDALONE"));
+ }
+ else
+ {
+ Check(hWnd, R_STATIC, true);
+ }
+
+ Check(hWnd, R_ONLINE, true);
+
+ Hide(hWnd, B_ACL);
+ Hide(hWnd, S_ACL);
+ Hide(hWnd, S_ACL_2);
+ Hide(hWnd, S_ACL_3);
+ Hide(hWnd, S_MSG_1);
+ Hide(hWnd, S_MSG_4);
+ Hide(hWnd, S_MSG_2);
+ Hide(hWnd, B_MSG);
+ }
+ else
+ {
+ // Edit
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("CM_EDIT_HUB_2"), s->HubName);
+ SetText(hWnd, 0, tmp);
+ SetTextA(hWnd, E_HUBNAME, s->HubName);
+ Disable(hWnd, E_HUBNAME);
+
+ if (s->p->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // Stand-alone mode
+ Disable(hWnd, R_STATIC);
+ Disable(hWnd, R_DYNAMIC);
+ SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_STANDALONE"));
+ }
+
+ if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Controller
+ if (GetCapsBool(s->p->CapsList, "b_cluster_hub_type_fixed"))
+ {
+ Disable(hWnd, R_STATIC);
+ Disable(hWnd, R_DYNAMIC);
+ SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_TYPE_FIXED"));
+ }
+ }
+
+ // Get the HUB information
+ StrCpy(t.HubName, sizeof(t.HubName), s->HubName);
+ if (CALL(hWnd, ScGetHub(s->p->Rpc, &t)) == false)
+ {
+ EndDialog(hWnd, false);
+ return;
+ }
+
+ SetTextA(hWnd, E_PASSWORD1, HIDDEN_PASSWORD);
+ SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);
+
+ if (t.HubOption.MaxSession == 0)
+ {
+ Check(hWnd, R_LIMIT_MAX_SESSION, false);
+ }
+ else
+ {
+ Check(hWnd, R_LIMIT_MAX_SESSION, true);
+ }
+
+ Check(hWnd, R_NO_ENUM, t.HubOption.NoEnum);
+
+ SetIntEx(hWnd, E_MAX_SESSION, t.HubOption.MaxSession);
+
+ Check(hWnd, R_ONLINE, t.Online);
+ Check(hWnd, R_OFFLINE, t.Online ? false : true);
+
+ Check(hWnd, R_STATIC, t.HubType == HUB_TYPE_FARM_STATIC);
+ Check(hWnd, R_DYNAMIC, t.HubType == HUB_TYPE_FARM_DYNAMIC);
+
+ SetShow(hWnd, B_ACL, GetCapsBool(s->p->CapsList, "b_support_ac"));
+ SetShow(hWnd, S_ACL, GetCapsBool(s->p->CapsList, "b_support_ac"));
+ SetShow(hWnd, S_ACL_2, GetCapsBool(s->p->CapsList, "b_support_ac"));
+ SetShow(hWnd, S_ACL_3, GetCapsBool(s->p->CapsList, "b_support_ac"));
+
+ SetShow(hWnd, S_MSG_1, GetCapsBool(s->p->CapsList, "b_support_msg"));
+ SetShow(hWnd, S_MSG_4, GetCapsBool(s->p->CapsList, "b_support_msg"));
+ SetShow(hWnd, S_MSG_2, GetCapsBool(s->p->CapsList, "b_support_msg"));
+ SetShow(hWnd, B_MSG, GetCapsBool(s->p->CapsList, "b_support_msg"));
+ }
+
+ // Advanced options
+ if (s->EditMode)
+ {
+ support_extoption = GetCapsBool(s->p->CapsList, "b_support_hub_ext_options");
+ }
+
+ SetEnable(hWnd, S_STATIC, support_extoption);
+ SetEnable(hWnd, B_EXTOPTION, support_extoption);
+
+ SetEnable(hWnd, R_NO_ENUM, GetCapsBool(s->p->CapsList, "b_support_hide_hub"));
+
+ SmEditHubUpdate(hWnd, s);
+
+ if (s->EditMode)
+ {
+ Focus(hWnd, IDOK);
+ }
+
+ if (s->EditMode)
+ {
+ if (GetCapsBool(s->p->CapsList, "b_support_hub_admin_option"))
+ {
+ b = true;
+ }
+ }
+
+ SetShow(hWnd, S_AO_1, b);
+ SetShow(hWnd, S_AO_2, b);
+ SetShow(hWnd, S_AO_3, b);
+ SetShow(hWnd, B_ADMINOPTION, b);
+}
+
+// HUB edit procedure
+UINT SmEditHubProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_HUB *s = (SM_EDIT_HUB *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmEditHubInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_PASSWORD1:
+ case E_PASSWORD2:
+ case E_HUBNAME:
+ case R_LIMIT_MAX_SESSION:
+ case E_MAX_SESSION:
+ SmEditHubUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmEditHubOnOk(hWnd, s);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_LIMIT_MAX_SESSION:
+ if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))
+ {
+ FocusEx(hWnd, E_MAX_SESSION);
+ }
+ break;
+
+ case B_ADMINOPTION:
+ SmHubAdminOption(hWnd, s);
+ break;
+
+ case B_EXTOPTION:
+ SmHubExtOption(hWnd, s);
+ break;
+
+ case B_ACL:
+ SmHubAc(hWnd, s);
+ break;
+
+ case B_MSG:
+ SmHubMsg(hWnd, s);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// HUB edit dialog
+bool SmEditHubDlg(HWND hWnd, SM_SERVER *p, char *hubname)
+{
+ SM_EDIT_HUB s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ Zero(&s, sizeof(s));
+ s.p = p;
+ s.EditMode = true;
+ StrCpy(s.HubName, sizeof(s.HubName), hubname);
+
+ if (p->Bridge == false)
+ {
+ return Dialog(hWnd, D_SM_EDIT_HUB, SmEditHubProc, &s);
+ }
+ else
+ {
+ SmHubExtOption(hWnd, &s);
+ return false;
+ }
+}
+
+// HUB creation dialog
+bool SmCreateHubDlg(HWND hWnd, SM_SERVER *p)
+{
+ SM_EDIT_HUB s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ Zero(&s, sizeof(s));
+ s.p = p;
+ s.EditMode = false;
+
+ return Dialog(hWnd, D_SM_EDIT_HUB, SmEditHubProc, &s);
+}
+
+// Display the status of the virtual HUB
+bool SmRefreshHubStatus(HWND hWnd, SM_SERVER *p, void *param)
+{
+ RPC_HUB_STATUS t;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(RPC_HUB_STATUS));
+ StrCpy(t.HubName, sizeof(t.HubName), (char *)param);
+ if (CALL(hWnd, ScGetHubStatus(p->Rpc, &t)))
+ {
+ wchar_t *s;
+ wchar_t tmp[MAX_SIZE];
+ LVB *b = LvInsertStart();
+
+ // HUB name
+ s = CopyStrToUni((char *)param);
+ LvInsertAdd(b, ICO_HUB, 0, 2, _UU("SM_HUB_STATUS_HUBNAME"), s);
+ Free(s);
+
+ // Online
+ LvInsertAdd(b, t.Online ? ICO_PROTOCOL : ICO_PROTOCOL_X, 0, 2, _UU("SM_HUB_STATUS_ONLINE"),
+ t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));
+
+ // Type of HUB
+ LvInsertAdd(b, t.HubType == HUB_TYPE_STANDALONE ? ICO_TOWER : ICO_FARM, 0, 2, _UU("SM_HUB_TYPE"),
+ GetHubTypeStr(t.HubType));
+
+ if (t.HubType == HUB_TYPE_STANDALONE)
+ {
+ // Enable / Disable the SecureNAT
+ LvInsertAdd(b, ICO_ROUTER, NULL, 2, _UU("SM_HUB_SECURE_NAT"),
+ t.SecureNATEnabled ? _UU("SM_HUB_SECURE_NAT_YES") : _UU("SM_HUB_SECURE_NAT_NO"));
+ }
+
+ // Other values
+ UniToStru(tmp, t.NumSessions);
+ LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS"), tmp);
+ if (t.NumSessionsClient != 0 || t.NumSessionsBridge != 0)
+ {
+ UniToStru(tmp, t.NumSessionsClient);
+ LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS_CLIENT"), tmp);
+ UniToStru(tmp, t.NumSessionsBridge);
+ LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS_BRIDGE"), tmp);
+ }
+
+ UniToStru(tmp, t.NumAccessLists);
+ LvInsertAdd(b, ICO_DISCARD, 0, 2, _UU("SM_HUB_NUM_ACCESSES"), tmp);
+
+ if (p->ServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ UniToStru(tmp, t.NumUsers);
+ LvInsertAdd(b, ICO_USER, 0, 2, _UU("SM_HUB_NUM_USERS"), tmp);
+ UniToStru(tmp, t.NumGroups);
+ LvInsertAdd(b, ICO_GROUP, 0, 2, _UU("SM_HUB_NUM_GROUPS"), tmp);
+ }
+
+ UniToStru(tmp, t.NumMacTables);
+ LvInsertAdd(b, ICO_MACHINE, 0, 2, _UU("SM_HUB_NUM_MAC_TABLES"), tmp);
+ UniToStru(tmp, t.NumIpTables);
+ LvInsertAdd(b, ICO_MACHINE, 0, 2, _UU("SM_HUB_NUM_IP_TABLES"), tmp);
+
+ // Usage status
+ UniToStru(tmp, t.NumLogin);
+ LvInsertAdd(b, ICO_KEY, NULL, 2, _UU("SM_HUB_NUM_LOGIN"), tmp);
+
+ if (t.LastLoginTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastLoginTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_LAST_LOGIN_TIME"), tmp);
+
+ if (t.LastCommTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastCommTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_LAST_COMM_TIME"), tmp);
+
+ if (t.CreatedTime != 0)
+ {
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime));
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));
+ }
+ LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_CREATED_TIME"), tmp);
+
+ // Traffic information
+ SmInsertTrafficInfo(b, &t.Traffic);
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Add a traffic information to LVB
+void SmInsertTrafficInfo(LVB *b, TRAFFIC *t)
+{
+ wchar_t tmp[MAX_SIZE];
+ char vv[128];
+ // Validate arguments
+ if (b == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // Transmission information
+ ToStr3(vv, sizeof(vv), t->Send.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Send.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_BCAST_SIZE"), tmp);
+
+ // Reception information
+ ToStr3(vv, sizeof(vv), t->Recv.UnicastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_UCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.UnicastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_UCAST_SIZE"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.BroadcastCount);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_BCAST_NUM"), tmp);
+
+ ToStr3(vv, sizeof(vv), t->Recv.BroadcastBytes);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);
+ LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_BCAST_SIZE"), tmp);
+}
+
+// Status display dialog procedure
+UINT SmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_STATUS *s = (SM_STATUS *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ LvInitEx(hWnd, L_STATUS, s->NoImage);
+ LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);
+ SetIcon(hWnd, 0, s->Icon);
+ SetIcon(hWnd, S_ICON, s->Icon);
+ SetText(hWnd, 0, s->Caption);
+ SetText(hWnd, S_TITLE, s->Caption);
+ DlgFont(hWnd, S_TITLE, 15, true);
+ if (s->InitProc != NULL)
+ {
+ s->InitProc(hWnd, s->p, s->Param);
+ }
+ else
+ {
+ // Initialize the column
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);
+ }
+ if (s->RefreshProc(hWnd, s->p, s->Param) == false)
+ {
+ Close(hWnd);
+ }
+ LvAutoSize(hWnd, L_STATUS);
+ Focus(hWnd, L_STATUS);
+
+ if (s->show_refresh_button == false)
+ {
+ Hide(hWnd, IDOK);
+ }
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Update
+ if (s->RefreshProc(hWnd, s->p, s->Param) == false)
+ {
+ Close(hWnd);
+ }
+ LvAutoSize(hWnd, L_STATUS);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_STATUS);
+
+ return 0;
+}
+
+// Status display dialog
+void SmStatusDlg(HWND hWnd, SM_SERVER *p, void *param, bool no_image, bool show_refresh_button, wchar_t *caption, UINT icon,
+ SM_STATUS_INIT_PROC *init, SM_STATUS_REFRESH_PROC *refresh)
+{
+ SM_STATUS s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || refresh == NULL)
+ {
+ return;
+ }
+
+ if (icon == 0)
+ {
+ icon = ICO_INFORMATION;
+ }
+ if (caption == NULL)
+ {
+ caption = _UU("SM_INFORMATION");
+ }
+
+ Zero(&s, sizeof(s));
+ s.show_refresh_button = show_refresh_button;
+ s.p = p;
+ s.NoImage = no_image;
+ s.Param = param;
+ s.Icon = icon;
+ s.Caption = caption;
+ s.InitProc = init;
+ s.RefreshProc = refresh;
+
+ Dialog(hWnd, D_SM_STATUS, SmStatusDlgProc, &s);
+}
+
+// Server management dialog update
+void SmServerDlgUpdate(HWND hWnd, SM_SERVER *p)
+{
+ bool hub_selected = false;
+ bool hub_selected_online = false;
+ bool hub_selected_offline = false;
+ bool hub_have_admin_right = false;
+ bool listener_selected = false;
+ bool listener_selected_enabled = false;
+ bool listener_selected_disabled = false;
+ bool two_or_more_listener = false;
+ bool bridge;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ bridge = GetCapsBool(p->CapsList, "b_bridge");
+
+ hub_selected = LvIsSelected(hWnd, L_HUB);
+
+ if (hub_selected)
+ {
+ if (p->ServerAdminMode)
+ {
+ hub_have_admin_right = true;
+ }
+ i = LvGetSelected(hWnd, L_HUB);
+ if (i != INFINITE)
+ {
+ wchar_t *s = LvGetStr(hWnd, L_HUB, i, 1);
+ if (p->ServerAdminMode == false)
+ {
+ char *hubname = LvGetStrA(hWnd, L_HUB, i, 0);
+ if (hubname != NULL)
+ {
+ if (StrCmpi(hubname, p->HubName) == 0)
+ {
+ hub_have_admin_right = true;
+ }
+ Free(hubname);
+ }
+ }
+ hub_selected_online = (UniStrCmpi(s, _UU("SM_HUB_ONLINE")) == 0);
+ hub_selected_offline = hub_selected_online ? false : true;
+ Free(s);
+ }
+ }
+
+ listener_selected = LvIsSelected(hWnd, L_LISTENER);
+ if (listener_selected)
+ {
+ wchar_t *s = LvGetSelectedStr(hWnd, L_LISTENER, 1);
+ if (UniStrCmpi(s, _UU("CM_LISTENER_OFFLINE")) == 0)
+ {
+ listener_selected_disabled = true;
+ }
+ else
+ {
+ listener_selected_enabled = true;
+ }
+ Free(s);
+ }
+
+ if (LvNum(hWnd, L_LISTENER) >= 2)
+ {
+ two_or_more_listener = true;
+ }
+
+ SetEnable(hWnd, IDOK, bridge || (hub_selected && hub_have_admin_right));
+ SetEnable(hWnd, B_ONLINE, bridge == false && hub_selected_offline && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);
+ SetEnable(hWnd, B_OFFLINE, bridge == false && hub_selected_online && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);
+ SetEnable(hWnd, B_HUB_STATUS, hub_selected && hub_have_admin_right);
+ SetEnable(hWnd, B_DELETE, bridge == false && hub_selected && p->ServerAdminMode && p->ServerType != SERVER_TYPE_FARM_MEMBER);
+ SetEnable(hWnd, B_EDIT, hub_selected && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);
+ SetEnable(hWnd, B_CREATE, bridge == false && p->ServerAdminMode && p->ServerType != SERVER_TYPE_FARM_MEMBER);
+
+ SetEnable(hWnd, B_CREATE_LISTENER, p->ServerAdminMode);
+ SetEnable(hWnd, B_DELETE_LISTENER, p->ServerAdminMode && listener_selected && two_or_more_listener);
+ SetEnable(hWnd, B_START, p->ServerAdminMode && listener_selected_disabled);
+ SetEnable(hWnd, B_STOP, p->ServerAdminMode && listener_selected_enabled);
+ SetEnable(hWnd, B_FARM, GetCapsBool(p->CapsList, "b_support_cluster") && p->ServerAdminMode && GetCapsBool(p->CapsList, "b_support_vgs_in_client") == false);
+ SetEnable(hWnd, B_FARM_STATUS, GetCapsBool(p->CapsList, "b_support_cluster") && p->ServerType != SERVER_TYPE_STANDALONE);
+}
+
+// Server management dialog initialization
+void SmServerDlgInit(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Initialize the column
+ LvInit(hWnd, L_HUB);
+ LvSetStyle(hWnd, L_HUB, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_HUB, 0, _UU("SM_HUB_COLUMN_1"), 150);
+ LvInsertColumn(hWnd, L_HUB, 1, _UU("SM_HUB_COLUMN_2"), 80);
+ LvInsertColumn(hWnd, L_HUB, 2, _UU("SM_HUB_COLUMN_3"), 80);
+ LvInsertColumn(hWnd, L_HUB, 3, _UU("SM_HUB_COLUMN_4"), 80);
+ LvInsertColumn(hWnd, L_HUB, 4, _UU("SM_HUB_COLUMN_5"), 80);
+ LvInsertColumn(hWnd, L_HUB, 5, _UU("SM_HUB_COLUMN_6"), 80);
+ LvInsertColumn(hWnd, L_HUB, 6, _UU("SM_HUB_COLUMN_7"), 80);
+ LvInsertColumn(hWnd, L_HUB, 7, _UU("SM_HUB_COLUMN_8"), 80);
+ LvInsertColumn(hWnd, L_HUB, 8, _UU("SM_HUB_COLUMN_9"), 80);
+ LvInsertColumn(hWnd, L_HUB, 9, _UU("SM_HUB_COLUMN_10"), 120);
+ LvInsertColumn(hWnd, L_HUB, 10, _UU("SM_HUB_COLUMN_11"), 120);
+ LvInsertColumn(hWnd, L_HUB, 11, _UU("SM_SESS_COLUMN_6"), 100);
+ LvInsertColumn(hWnd, L_HUB, 12, _UU("SM_SESS_COLUMN_7"), 100);
+
+ LvInit(hWnd, L_LISTENER);
+ LvSetStyle(hWnd, L_LISTENER, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_LISTENER, 0, _UU("CM_LISTENER_COLUMN_1"), 90);
+ LvInsertColumn(hWnd, L_LISTENER, 1, _UU("CM_LISTENER_COLUMN_2"), 80);
+
+ SmServerDlgRefresh(hWnd, p);
+
+ if (p->ServerAdminMode == false)
+ {
+ // Select the target HUB in the case of the Virtual HUB management mode
+ wchar_t *s = CopyStrToUni(p->HubName);
+ LvSelect(hWnd, L_HUB, LvSearchStr(hWnd, L_HUB, 0, s));
+ Free(s);
+ }
+ else
+ {
+ // In the case of whole server management mode
+ UINT num_hubs = LvNum(hWnd, L_HUB);
+
+ if (num_hubs == 1)
+ {
+ // Select the Virtual HUB if Virtual HUB exists only one
+ LvSelect(hWnd, L_HUB, 0);
+ }
+ else
+ {
+ // Select the Virtual HUB the last selected if there are some virtual HUBs
+ char tmp[MAX_SIZE];
+ char *hubname;
+
+ Format(tmp, sizeof(tmp), "%s:%u:%s", p->CurrentSetting->ClientOption.Hostname,
+ p->CurrentSetting->ClientOption.Port,
+ p->CurrentSetting->ServerAdminMode ? "" : p->CurrentSetting->HubName);
+
+ hubname = MsRegReadStr(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp);
+
+ if (IsEmptyStr(hubname) == false)
+ {
+ LvSelect(hWnd, L_HUB, LvSearchStrA(hWnd, L_HUB, 0, hubname));
+ }
+
+ Free(hubname);
+ }
+ }
+
+ Focus(hWnd, L_HUB);
+
+ SmServerDlgUpdate(hWnd, p);
+
+ if (GetCapsBool(p->CapsList, "b_bridge"))
+ {
+ Disable(hWnd, L_HUB);
+ }
+
+ // Enable Local bridge button, etc. in the case of the Admin of the Server
+ SetEnable(hWnd, B_BRIDGE, GetCapsBool(p->CapsList, "b_local_bridge") && p->ServerAdminMode && GetCapsBool(p->CapsList, "b_support_vgs_in_client") == false);
+ SetEnable(hWnd, B_CONNECTION, p->ServerAdminMode);
+
+ // Config R/W button
+ SetEnable(hWnd, B_CONFIG, GetCapsBool(p->CapsList, "b_support_config_rw") && p->ServerAdminMode && GetCapsBool(p->CapsList, "b_support_vgs_in_client") == false);
+
+ // Layer 3 button
+ SetEnable(hWnd, B_L3, GetCapsBool(p->CapsList, "b_support_layer3") && p->ServerAdminMode && GetCapsBool(p->CapsList, "b_support_vgs_in_client") == false);
+
+ // License button
+ SetShow(hWnd, B_LICENSE, GetCapsBool(p->CapsList, "b_support_license") && p->ServerAdminMode);
+ SetShow(hWnd, S_LICENSE, GetCapsBool(p->CapsList, "b_support_license") && p->ServerAdminMode);
+ SetShow(hWnd, S_BETA, GetCapsBool(p->CapsList, "b_beta_version") && (IsShow(hWnd, B_LICENSE) == false));
+
+ // IPsec button
+ SetEnable(hWnd, B_IPSEC, GetCapsBool(p->CapsList, "b_support_ipsec") && p->ServerAdminMode);
+
+ // OpenVPN, SSTP button
+ SetEnable(hWnd, B_OPENVPN, GetCapsBool(p->CapsList, "b_support_openvpn") && p->ServerAdminMode);
+
+ // DDNS button
+ SetEnable(hWnd, B_DDNS, GetCapsBool(p->CapsList, "b_support_ddns") && p->ServerAdminMode);
+
+ // VPN Azure button
+ SetEnable(hWnd, B_AZURE, GetCapsBool(p->CapsList, "b_support_azure") && p->ServerAdminMode);
+
+ DlgFont(hWnd, S_BETA, 12, false);
+ SetFont(hWnd, E_DDNS_HOST, GetFont("Verdana", 10, false, false, false, false));
+ SetFont(hWnd, E_AZURE_HOST, GetFont("Verdana", 10, false, false, false, false));
+
+ SetShow(hWnd, B_VPNGATE, false);
+ SetShow(hWnd, S_ICO_VPNGATE, false);
+
+ DlgFont(hWnd, IDOK, 0, true);
+}
+
+// Server management dialog update
+void SmServerDlgRefresh(HWND hWnd, SM_SERVER *p)
+{
+ RPC_ENUM_HUB t;
+ DDNS_CLIENT_STATUS st;
+ RPC_AZURE_STATUS sta;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Virtual HUB list update
+ Zero(&t, sizeof(t));
+ if (CALL(hWnd, ScEnumHub(p->Rpc, &t)))
+ {
+ LVB *b = LvInsertStart();
+ for (i = 0;i < t.NumHub;i++)
+ {
+ RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];
+ wchar_t name[MAX_HUBNAME_LEN + 1];
+ wchar_t s1[64], s2[64], s3[64], s4[64], s5[64];
+ wchar_t s6[64], s7[128], s8[128];
+ wchar_t s9[64], s10[64];
+ UINT icon;
+
+ UniToStru(s1, e->NumUsers);
+ UniToStru(s2, e->NumGroups);
+ UniToStru(s3, e->NumSessions);
+ UniToStru(s4, e->NumMacTables);
+ UniToStru(s5, e->NumIpTables);
+
+ UniToStru(s6, e->NumLogin);
+
+ if (e->LastLoginTime != 0)
+ {
+ GetDateTimeStr64Uni(s7, sizeof(s7), SystemToLocal64(e->LastLoginTime));
+ }
+ else
+ {
+ UniStrCpy(s7, sizeof(s7), _UU("COMMON_UNKNOWN"));
+ }
+
+ if (e->LastCommTime != 0)
+ {
+ GetDateTimeStr64Uni(s8, sizeof(s8), SystemToLocal64(e->LastCommTime));
+ }
+ else
+ {
+ UniStrCpy(s8, sizeof(s8), _UU("COMMON_UNKNOWN"));
+ }
+
+ StrToUni(name, sizeof(name), e->HubName);
+
+ icon = ICO_HUB;
+ if (e->Online == false)
+ {
+ icon = ICO_HUB_OFFLINE;
+ }
+
+ if (e->IsTrafficFilled == false)
+ {
+ UniStrCpy(s9, sizeof(s9), _UU("CM_ST_NONE"));
+ UniStrCpy(s10, sizeof(s10), _UU("CM_ST_NONE"));
+ }
+ else
+ {
+ UniToStr3(s9, sizeof(s9),
+ e->Traffic.Recv.BroadcastBytes + e->Traffic.Recv.UnicastBytes +
+ e->Traffic.Send.BroadcastBytes + e->Traffic.Send.UnicastBytes);
+
+ UniToStr3(s10, sizeof(s10),
+ e->Traffic.Recv.BroadcastCount + e->Traffic.Recv.UnicastCount +
+ e->Traffic.Send.BroadcastCount + e->Traffic.Send.UnicastCount);
+ }
+
+ LvInsertAdd(b,
+ icon,
+ NULL,
+ 13,
+ name,
+ e->Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"),
+ GetHubTypeStr(e->HubType),
+ s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
+ }
+ LvInsertEnd(b, hWnd, L_HUB);
+ FreeRpcEnumHub(&t);
+ }
+
+ // Listener list update
+ if (p != NULL)
+ {
+ RPC_LISTENER_LIST t;
+ Zero(&t, sizeof(RPC_LISTENER_LIST));
+ if (CALL(hWnd, ScEnumListener(p->Rpc, &t)))
+ {
+ LVB *b = LvInsertStart();
+ for (i = 0;i < t.NumPort;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t *status;
+ UINT icon;
+ UniFormat(tmp, sizeof(tmp), _UU("CM_LISTENER_TCP_PORT"), t.Ports[i]);
+
+ status = _UU("CM_LISTENER_ONLINE");
+ icon = ICO_PROTOCOL;
+ if (t.Errors[i])
+ {
+ status = _UU("CM_LISTENER_ERROR");
+ icon = ICO_PROTOCOL_X;
+ }
+ else if (t.Enables[i] == false)
+ {
+ status = _UU("CM_LISTENER_OFFLINE");
+ icon = ICO_PROTOCOL_OFFLINE;
+ }
+
+ LvInsertAdd(b, icon, (void *)t.Ports[i], 2, tmp, status);
+ }
+ LvInsertEnd(b, hWnd, L_LISTENER);
+ FreeRpcListenerList(&t);
+ }
+ }
+
+ // Get the DDNS client state
+ Zero(&st, sizeof(st));
+ if (ScGetDDnsClientStatus(p->Rpc, &st) == ERR_NO_ERROR && IsEmptyStr(st.CurrentFqdn) == false)
+ {
+ SetTextA(hWnd, E_DDNS_HOST, st.CurrentFqdn);
+
+ Show(hWnd, S_DDNS);
+ Show(hWnd, E_DDNS_HOST);
+ }
+ else
+ {
+ Hide(hWnd, S_DDNS);
+ Hide(hWnd, E_DDNS_HOST);
+ }
+
+ // VPN Azure client state acquisition
+ Zero(&sta, sizeof(sta));
+ if (ScGetAzureStatus(p->Rpc, &sta) == ERR_NO_ERROR && sta.IsEnabled && IsEmptyStr(st.CurrentFqdn) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ StrCpy(tmp, sizeof(tmp), st.CurrentHostName);
+ StrCat(tmp, sizeof(tmp), AZURE_DOMAIN_SUFFIX);
+
+ SetTextA(hWnd, E_AZURE_HOST, tmp);
+
+ Show(hWnd, S_AZURE);
+ Show(hWnd, E_AZURE_HOST);
+ }
+ else
+ {
+ Hide(hWnd, S_AZURE);
+ Hide(hWnd, E_AZURE_HOST);
+ }
+
+ SmServerDlgUpdate(hWnd, p);
+}
+
+// Server management dialog procedure
+UINT SmServerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_SERVER *p = (SM_SERVER *)param;
+ wchar_t *s;
+ wchar_t tmp[MAX_SIZE];
+ NMHDR *n;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, 0, p->Title);
+
+ if (p->Bridge == false)
+ {
+ FormatText(hWnd, S_TITLE, p->ServerName);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SERVER_BRIDGE_TITLE"), p->ServerName);
+ SetText(hWnd, S_TITLE, tmp);
+ }
+
+ DlgFont(hWnd, S_TITLE, 16, 1);
+
+ SetIcon(hWnd, 0, p->Bridge == false ? ICO_VPNSERVER : ICO_BRIDGE);
+
+ SmServerDlgInit(hWnd, p);
+
+ SetTimer(hWnd, 1, 50, NULL);
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Management
+ if (IsEnable(hWnd, IDOK))
+ {
+ if (p->Bridge == false)
+ {
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ }
+ else
+ {
+ s = CopyUniStr(L"BRIDGE");
+ }
+ if (s != NULL)
+ {
+ char hubname[MAX_HUBNAME_LEN + 1];
+ SM_HUB hub;
+ Zero(&hub, sizeof(hub));
+ UniToStr(hubname, sizeof(hubname), s);
+ hub.p = p;
+ hub.Rpc = p->Rpc;
+ hub.HubName = hubname;
+ SmHubDlg(hWnd, &hub);
+ //SmServerDlgRefresh(hWnd, p);
+ Free(s);
+ }
+ }
+ break;
+
+ case B_ONLINE:
+ // Online
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ if (s != NULL)
+ {
+ RPC_SET_HUB_ONLINE t;
+ Zero(&t, sizeof(t));
+ UniToStr(t.HubName, sizeof(t.HubName), s);
+ t.Online = true;
+ if (CALL(hWnd, ScSetHubOnline(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ Free(s);
+ }
+ break;
+
+ case B_OFFLINE:
+ // Offline
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ if (s != NULL)
+ {
+ RPC_SET_HUB_ONLINE t;
+ Zero(&t, sizeof(t));
+ // Confirmation message
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("CM_OFFLINE_MSG"), s) == IDYES)
+ {
+ UniToStr(t.HubName, sizeof(t.HubName), s);
+ t.Online = false;
+ if (CALL(hWnd, ScSetHubOnline(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ }
+ Free(s);
+ }
+ break;
+
+ case B_HUB_STATUS:
+ // Status of HUB
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ if (s != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ char *hubname = CopyUniToStr(s);
+ UniFormat(tmp, sizeof(tmp), _UU("SM_HUB_STATUS_CAPTION"), s);
+ SmStatusDlg(hWnd, p, hubname, false, true, tmp, ICO_HUB,
+ NULL, SmRefreshHubStatus);
+ Free(hubname);
+ Free(s);
+ }
+ break;
+
+ case B_CREATE:
+ // Create a HUB
+ if (SmCreateHubDlg(hWnd, p))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ break;
+
+ case B_EDIT:
+ // Edit the HUB
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ if (s != NULL)
+ {
+ char *name = CopyUniToStr(s);
+ if (SmEditHubDlg(hWnd, p, name))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ Free(name);
+ Free(s);
+ }
+ break;
+
+ case B_DELETE:
+ // Delete the HUB
+ s = LvGetSelectedStr(hWnd, L_HUB, 0);
+ if (s != NULL)
+ {
+ char *name = CopyUniToStr(s);
+ RPC_DELETE_HUB t;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), name);
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_HUB_MSG"), name) == IDYES)
+ {
+ if (CALL(hWnd, ScDeleteHub(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_HUB_DELETED_MSG"), name);
+ }
+ }
+ Free(name);
+ Free(s);
+ }
+ break;
+
+ case B_CREATE_LISTENER:
+ // Create a listener
+ if (SmCreateListenerDlg(hWnd, p))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ break;
+
+ case B_DELETE_LISTENER:
+ // Remove the listener
+ i = LvGetSelected(hWnd, L_LISTENER);
+ if (i != INFINITE)
+ {
+ UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_LISTENER_MSG"), port) == IDYES)
+ {
+ RPC_LISTENER t;
+ Zero(&t, sizeof(t));
+ t.Enable = false;
+ t.Port = port;
+
+ if (CALL(hWnd, ScDeleteListener(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ }
+ }
+ break;
+
+ case B_START:
+ // Start
+ i = LvGetSelected(hWnd, L_LISTENER);
+ if (i != INFINITE)
+ {
+ UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);
+ RPC_LISTENER t;
+ Zero(&t, sizeof(t));
+ t.Enable = true;
+ t.Port = port;
+
+ if (CALL(hWnd, ScEnableListener(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ }
+ break;
+
+ case B_STOP:
+ // Stop
+ i = LvGetSelected(hWnd, L_LISTENER);
+ if (i != INFINITE)
+ {
+ UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_STOP_LISTENER_MSG"), port) == IDYES)
+ {
+ RPC_LISTENER t;
+ Zero(&t, sizeof(t));
+ t.Enable = false;
+ t.Port = port;
+
+ if (CALL(hWnd, ScEnableListener(p->Rpc, &t)))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ }
+ }
+ break;
+
+ case B_SSL:
+ // SSL related
+ SmSslDlg(hWnd, p);
+ break;
+
+ case B_STATUS:
+ // Server status
+ SmStatusDlg(hWnd, p, p, false, true, _UU("SM_SERVER_STATUS"), ICO_VPNSERVER,
+ NULL, SmRefreshServerStatus);
+ break;
+
+ case B_INFO:
+ // Server Information
+ SmStatusDlg(hWnd, p, p, false, false, _UU("SM_INFO_TITLE"), ICO_VPNSERVER,
+ NULL, SmRefreshServerInfo);
+ break;
+
+ case B_BRIDGE:
+ // Local bridge configuration
+ SmBridgeDlg(hWnd, p);
+ SmServerDlgRefresh(hWnd, p);
+ break;
+
+ case B_FARM:
+ // Server farm
+ if (SmFarmDlg(hWnd, p))
+ {
+ // Close the dialog if the server farm configuration has changed
+ Close(hWnd);
+ }
+ break;
+
+ case B_FARM_STATUS:
+ // Server farm status
+ if (p->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ Dialog(hWnd, D_SM_FARM_MEMBER, SmFarmMemberDlgProc, p);
+ }
+ else if (p->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ SmStatusDlg(hWnd, p, NULL, false, true, _UU("SM_FC_STATUS_CAPTION"),
+ ICO_FARM, NULL, SmRefreshFarmConnectionInfo);
+ }
+ break;
+
+ case B_CONNECTION:
+ // TCP connection list
+ SmConnectionDlg(hWnd, p);
+ break;
+
+ case B_REFRESH:
+ // Update to the latest state
+ SmServerDlgRefresh(hWnd, p);
+ break;
+
+ case B_CONFIG:
+ // Config edit
+ SmConfig(hWnd, p);
+ break;
+
+ case B_L3:
+ // L3 switch
+ SmL3(hWnd, p);
+ break;
+
+ case B_LICENSE:
+ // Add or Remove license
+ SmLicense(hWnd, p);
+ SmServerDlgUpdate(hWnd, p);
+ break;
+
+ case B_IPSEC:
+ // IPsec Settings
+ SmIPsec(hWnd, p);
+ break;
+
+ case B_OPENVPN:
+ // OpenVPN, SSTP setting
+ SmOpenVpn(hWnd, p);
+ break;
+
+ case B_DDNS:
+ // DDNS setting
+ if (SmDDns(hWnd, p, false, false))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ break;
+
+ case B_AZURE:
+ // VPN Azure setting
+ SmAzure(hWnd, p, false);
+
+ SmServerDlgRefresh(hWnd, p);
+ break;
+
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ {
+ // Save the HUB that was selected last
+ char *hubname = NULL;
+ char tmp[MAX_SIZE];
+
+
+ Format(tmp, sizeof(tmp), "%s:%u:%s", p->CurrentSetting->ClientOption.Hostname,
+ p->CurrentSetting->ClientOption.Port,
+ p->CurrentSetting->ServerAdminMode ? "" : p->CurrentSetting->HubName);
+
+ if (LvIsSingleSelected(hWnd, L_HUB))
+ {
+ hubname = LvGetSelectedStrA(hWnd, L_HUB, 0);
+ }
+
+ if (IsEmptyStr(hubname) == false)
+ {
+ MsRegWriteStr(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp, hubname);
+ }
+ else
+ {
+ MsRegDeleteValue(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp);
+ }
+
+ Free(hubname);
+
+ EndDialog(hWnd, false);
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_HUB:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmServerDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ case L_LISTENER:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SmServerDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ if (p->ServerAdminMode)
+ {
+ // Prompt the registration if the license key is not registered
+ RPC_LICENSE_STATUS t;
+
+ Zero(&t, sizeof(t));
+ if (p->Bridge == false && GetCapsBool(p->CapsList, "b_support_license"))
+ {
+ if (ScGetLicenseStatus(p->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE || (t.NeedSubscription && t.SubscriptionExpires == 0))
+ {
+ // Valid license key is not registered
+
+ if (MsgBox(hWnd, MB_YESNO | MB_ICONINFORMATION,
+ _UU("SM_SETUP_NO_LICENSE_KEY")) == IDYES)
+ {
+ SmLicense(hWnd, p);
+ }
+ }
+ }
+ }
+ }
+
+ SetTimer(hWnd, 2, 150, NULL);
+ break;
+
+ case 2:
+ // Setup
+ KillTimer(hWnd, 2);
+
+ if (SmSetupIsNew(p))
+ {
+ if (SmSetup(hWnd, p))
+ {
+ SmServerDlgRefresh(hWnd, p);
+ }
+ }
+
+ SmShowIPSecMessageIfNecessary(hWnd, p);
+
+ SetTimer(hWnd, 3, 150, NULL);
+ break;
+
+ case 3:
+ // Message for Administrators
+ KillTimer(hWnd, 3);
+
+ if (UniIsEmptyStr(p->AdminMsg) == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("SM_SERVER_ADMIN_MSG"), p->ServerName);
+ OnceMsg(hWnd, tmp, p->AdminMsg, true, ICO_VPNSERVER);
+ }
+ break;
+ }
+ break;
+ }
+
+ LvStandardHandler(hWnd, msg, wParam, lParam, L_HUB);
+
+ return 0;
+}
+
+// Display messages about IPsec, and prompt for the setting
+void SmShowIPSecMessageIfNecessary(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (GetCapsBool(p->CapsList, "b_support_vgs_in_client") == false)
+ {
+ if (GetCapsBool(p->CapsList, "b_support_ipsec") && p->IPsecMessageDisplayed == false)
+ {
+ // Display a message about IPsec
+ RPC_TEST flag;
+
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_IPSEC_SETUP_QUESTION")) == IDYES)
+ {
+ // Display the IPsec dialog
+ SmIPsec(hWnd, p);
+ }
+
+ Zero(&flag, sizeof(flag));
+ flag.IntValue = 9;
+ ToStr(flag.StrValue, 1);
+
+ ScDebug(p->Rpc, &flag);
+
+ p->IPsecMessageDisplayed = true;
+ }
+
+ }
+}
+
+// Connection
+void SmConnect(HWND hWnd, SETTING *s)
+{
+ SmConnectEx(hWnd, s, false);
+}
+void SmConnectEx(HWND hWnd, SETTING *s, bool is_in_client)
+{
+ bool ok;
+ RPC *rpc;
+ char *pass;
+ bool empty_password = false;
+ bool first_bad_password = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Updater terminate
+ if (sm->Update != NULL)
+ {
+ FreeUpdateUi(sm->Update);
+ sm->Update = NULL;
+ }
+
+ // Disable the control
+ Disable(hWnd, L_SETTING);
+ Disable(hWnd, B_NEW_SETTING);
+ Disable(hWnd, B_EDIT_SETTING);
+ Disable(hWnd, B_DELETE);
+ Disable(hWnd, IDOK);
+ Disable(hWnd, B_ABOUT);
+ Disable(hWnd, IDCANCEL);
+ Disable(hWnd, B_SECURE_MANAGER);
+ Disable(hWnd, B_SELECT_SECURE);
+ Disable(hWnd, B_CERT_TOOL);
+
+ ok = true;
+
+ if (IsZero(s->HashedPassword, SHA1_SIZE))
+ {
+ // Password input screen
+ENTER_PASSWORD:
+ pass = SmPassword(hWnd, s->ClientOption.Hostname);
+ if (pass != NULL)
+ {
+ Hash(s->HashedPassword, pass, StrLen(pass), true);
+ Free(pass);
+ ok = true;
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+
+ if (ok)
+ {
+ UINT err = ERR_INTERNAL_ERROR;
+ // Connection
+ rpc = AdminConnectEx2(sm->Cedar, &s->ClientOption, s->ServerAdminMode ? "" : s->HubName, s->HashedPassword, &err, NULL,
+ hWnd);
+ if (rpc == NULL)
+ {
+ // An error has occured
+ if (err != ERR_ACCESS_DENIED || first_bad_password)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _E(err));
+ }
+ if (err == ERR_ACCESS_DENIED)
+ {
+ // Password incorrect
+ first_bad_password = true;
+ goto ENTER_PASSWORD;
+ }
+ else
+ {
+ // Other errors
+ }
+ }
+ else
+ {
+ UCHAR test[SHA1_SIZE];
+ SM_SERVER p;
+ RPC_SERVER_STATUS status;
+ RPC_SERVER_INFO info;
+ SETTING *setting;
+ RPC_MSG msg;
+ RPC_TEST flag;
+ bool cancel = false;
+
+ Hash(test, "", 0, true);
+
+ if (Cmp(test, s->HashedPassword, SHA1_SIZE) == 0 || Cmp(test, rpc->VpnServerHashedPassword, SHA1_SIZE) == 0)
+ {
+ empty_password = true;
+ }
+
+ if (sm->TempSetting == NULL)
+ {
+ setting = SmGetSetting(s->Title);
+ if (setting != NULL)
+ {
+ if (IsZero(setting->HashedPassword, SHA1_SIZE) == false)
+ {
+ Copy(setting->HashedPassword, s->HashedPassword, SHA1_SIZE);
+ SmWriteSettingList();
+ }
+ }
+ }
+
+ rpc->ServerAdminMode = s->ServerAdminMode;
+ if (s->ServerAdminMode == false)
+ {
+ StrCpy(rpc->HubName, sizeof(rpc->HubName), s->HubName);
+ }
+
+ Zero(&p, sizeof(p));
+ p.IsInClient = is_in_client;
+ p.CurrentSetting = s;
+ p.Rpc = rpc;
+ p.ServerAdminMode = rpc->ServerAdminMode;
+ StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption.Hostname);
+ if (p.ServerAdminMode == false)
+ {
+ StrCpy(p.HubName, sizeof(p.HubName), rpc->HubName);
+ }
+ UniStrCpy(p.Title, sizeof(p.Title), s->Title);
+
+ // Get the type of server
+ Zero(&status, sizeof(status));
+ ScGetServerStatus(rpc, &status);
+
+ p.ServerType = status.ServerType;
+
+ Zero(&info, sizeof(info));
+ ScGetServerInfo(rpc, &info);
+
+ Copy(&p.ServerInfo, &info, sizeof(RPC_SERVER_INFO));
+ Copy(&p.ServerStatus, &status, sizeof(RPC_SERVER_STATUS));
+
+ // Get the Admin Msg
+ Zero(&msg, sizeof(msg));
+ if (ScGetAdminMsg(rpc, &msg) == ERR_NO_ERROR)
+ {
+ p.AdminMsg = UniCopyStr(msg.Msg);
+ FreeRpcMsg(&msg);
+ }
+
+ // IPsec related
+ Zero(&flag, sizeof(flag));
+ flag.IntValue = 8;
+ if (ScDebug(rpc, &flag) == ERR_NO_ERROR)
+ {
+ p.IPsecMessageDisplayed = ToInt(flag.StrValue);
+ }
+ else
+ {
+ p.IPsecMessageDisplayed = true;
+ }
+
+ // VGS related
+ Zero(&flag, sizeof(flag));
+ flag.IntValue = 10;
+ if (ScDebug(rpc, &flag) == ERR_NO_ERROR)
+ {
+ p.VgsMessageDisplayed = ToInt(flag.StrValue);
+ }
+ else
+ {
+ p.VgsMessageDisplayed = true;
+ }
+
+ // Get the Caps
+ p.CapsList = ScGetCapsEx(p.Rpc);
+
+ p.Bridge = GetCapsBool(p.CapsList, "b_bridge");
+
+ if (GetCapsBool(p.CapsList, "b_support_policy_ver_3"))
+ {
+ p.PolicyVer = 3;
+ }
+ else
+ {
+ p.PolicyVer = 2;
+ }
+
+ if (empty_password && s->ServerAdminMode)
+ {
+ // Make the user set a password when a password empty (In the case of server management mode)
+ if (Dialog(hWnd, D_SM_CHANGE_PASSWORD, SmChangeServerPasswordDlg, &p) == 0)
+ {
+ cancel = true;
+ }
+ }
+
+ // Server management screen
+ if (cancel == false)
+ {
+ // Update notification initialization
+ WINUI_UPDATE *update = NULL;
+
+ if (p.ServerAdminMode && is_in_client == false)
+ {
+ wchar_t update_software_title[MAX_SIZE];
+ char update_software_name[MAX_SIZE];
+ char server_name_safe[MAX_HOST_NAME_LEN + 1];
+ char family_name[128];
+
+ MakeSafeFileName(server_name_safe, sizeof(server_name_safe), p.ServerName);
+ Format(update_software_name, sizeof(update_software_name), (p.Bridge ? NAME_OF_VPN_BRIDGE_TARGET : NAME_OF_VPN_SERVER_TARGET), server_name_safe);
+ StrLower(update_software_name);
+ Trim(update_software_name);
+
+ Zero(family_name, sizeof(family_name));
+ StrCpy(family_name, sizeof(family_name), p.ServerInfo.ServerFamilyName);
+
+ if (IsEmptyStr(family_name))
+ {
+ if (InStr(p.ServerInfo.ServerProductName, "PacketiX"))
+ {
+ StrCpy(family_name, sizeof(family_name), "PacketiX");
+ }
+ else if (InStr(p.ServerInfo.ServerProductName, "UT-VPN") ||
+ InStr(p.ServerInfo.ServerProductName, "SoftEther"))
+ {
+ StrCpy(family_name, sizeof(family_name), "softether");
+ }
+ }
+
+ if (IsEmptyStr(family_name) == false)
+ {
+ UniFormat(update_software_title, sizeof(update_software_title), _UU(p.Bridge ? "SM_UPDATE_CHECK_TITLE_VPNBRIDGE" : "SM_UPDATE_CHECK_TITLE_VPNSERVER"),
+ family_name, p.ServerName);
+
+ update = InitUpdateUi(update_software_title, update_software_name, family_name, p.ServerInfo.ServerBuildDate,
+ p.ServerInfo.ServerBuildInt, p.ServerInfo.ServerVerInt, NULL);
+ }
+ }
+
+ p.Update = update;
+
+ // Main screen
+ Dialog(hWnd, D_SM_SERVER, SmServerDlgProc, &p);
+
+ if (p.Update != NULL)
+ {
+ FreeUpdateUi(p.Update);
+ p.Update = NULL;
+ }
+ }
+
+ // Disconnect
+ AdminDisconnect(rpc);
+
+ // Release the Caps
+ FreeCapsList(p.CapsList);
+
+ Free(p.AdminMsg);
+ p.AdminMsg = NULL;
+
+ FreeRpcServerInfo(&info);
+ }
+ }
+
+ // Enable the control
+ Enable(hWnd, L_SETTING);
+ Enable(hWnd, B_NEW_SETTING);
+ Enable(hWnd, B_EDIT_SETTING);
+ Enable(hWnd, B_DELETE);
+ Enable(hWnd, IDOK);
+ Enable(hWnd, B_ABOUT);
+ Enable(hWnd, IDCANCEL);
+ Enable(hWnd, B_SECURE_MANAGER);
+ Enable(hWnd, B_SELECT_SECURE);
+ Enable(hWnd, B_CERT_TOOL);
+}
+
+// Password input dialog
+char *SmPassword(HWND hWnd, char *server_name)
+{
+ char *ret;
+ UI_PASSWORD_DLG p;
+ // Validate arguments
+ if (server_name == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&p, sizeof(p));
+ p.AdminMode = true;
+ StrCpy(p.ServerName, sizeof(p.ServerName), server_name);
+
+ if (PasswordDlg(hWnd, &p) == false)
+ {
+ return NULL;
+ }
+
+ ret = CopyStr(p.Password);
+
+ return ret;
+}
+
+// Configuration editing dialog initialization
+void SmEditSettingDlgInit(HWND hWnd, SM_EDIT_SETTING *p)
+{
+ SETTING *s;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ p->Inited = false;
+
+ s = p->Setting;
+
+ // Title
+ if (p->EditMode == false)
+ {
+ SetText(hWnd, 0, _UU("SM_EDIT_CAPTION_1"));
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_CAPTION_2"), s->Title);
+ SetText(hWnd, 0, tmp);
+ }
+
+ // Connection setting name
+ SetText(hWnd, E_ACCOUNT_NAME, s->Title);
+
+ // Host name
+ SetTextA(hWnd, E_HOSTNAME, s->ClientOption.Hostname);
+
+ // Port number
+ CbSetHeight(hWnd, C_PORT, 18);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_1"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_2"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_3"), 0);
+ CbAddStr(hWnd, C_PORT, _UU("CM_PORT_4"), 0);
+ SetIntEx(hWnd, C_PORT, s->ClientOption.Port);
+
+ // Proxy Settings
+ Check(hWnd, R_DIRECT_TCP, s->ClientOption.ProxyType == PROXY_DIRECT);
+ Check(hWnd, R_HTTPS, s->ClientOption.ProxyType == PROXY_HTTP);
+ Check(hWnd, R_SOCKS, s->ClientOption.ProxyType == PROXY_SOCKS);
+
+ // Management mode setting
+ Check(hWnd, R_SERVER_ADMIN, s->ServerAdminMode);
+ Check(hWnd, R_HUB_ADMIN, s->ServerAdminMode == false ? true : false);
+ CbSetHeight(hWnd, C_HUBNAME, 18);
+ SetTextA(hWnd, C_HUBNAME, s->HubName);
+
+ // Password
+ if (IsZero(s->HashedPassword, SHA1_SIZE))
+ {
+ Check(hWnd, R_NO_SAVE, true);
+ }
+ else
+ {
+ UCHAR test[SHA1_SIZE];
+
+ Hash(test, "", 0, true);
+ if (Cmp(test, s->HashedPassword, SHA1_SIZE) != 0)
+ {
+ SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
+ }
+ }
+
+ if (p->EditMode == false)
+ {
+ FocusEx(hWnd, E_ACCOUNT_NAME);
+ }
+ else
+ {
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+
+ p->Inited = true;
+
+ // Start enumerating the Virtual HUBs
+ CmEnumHubStart(hWnd, &s->ClientOption);
+
+ SmEditSettingDlgUpdate(hWnd, p);
+}
+
+// Configuration editing dialog update
+void SmEditSettingDlgUpdate(HWND hWnd, SM_EDIT_SETTING *p)
+{
+ bool ok = true;
+ UINT delete_hub_list = 0;
+ SETTING *s;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || p->Inited == false)
+ {
+ return;
+ }
+
+ s = p->Setting;
+
+ GetTxt(hWnd, E_ACCOUNT_NAME, s->Title, sizeof(s->Title));
+ UniTrim(s->Title);
+
+ if (UniStrLen(s->Title) == 0)
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, R_LOCALHOST))
+ {
+ SetTextA(hWnd, E_HOSTNAME, "localhost");
+ Disable(hWnd, E_HOSTNAME);
+ }
+ else
+ {
+ Enable(hWnd, E_HOSTNAME);
+ }
+
+ GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));
+ Trim(tmp);
+
+ if (StrCmpi(tmp, s->ClientOption.Hostname) != 0)
+ {
+ delete_hub_list++;
+ }
+
+ StrCpy(s->ClientOption.Hostname, sizeof(s->ClientOption.Hostname), tmp);
+
+ if (StrLen(s->ClientOption.Hostname) == 0)
+ {
+ ok = false;
+ }
+
+ s->ClientOption.Port = GetInt(hWnd, C_PORT);
+ if (s->ClientOption.Port == 0)
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, R_DIRECT_TCP))
+ {
+ s->ClientOption.ProxyType = PROXY_DIRECT;
+ }
+ else if (IsChecked(hWnd, R_HTTPS))
+ {
+ s->ClientOption.ProxyType = PROXY_HTTP;
+ }
+ else
+ {
+ s->ClientOption.ProxyType = PROXY_SOCKS;
+ }
+
+ SetEnable(hWnd, B_PROXY_CONFIG, s->ClientOption.ProxyType != PROXY_DIRECT);
+
+ if (s->ClientOption.ProxyType != PROXY_DIRECT)
+ {
+ if (StrLen(s->ClientOption.ProxyName) == 0)
+ {
+ ok = false;
+ }
+ if (s->ClientOption.ProxyPort == 0)
+ {
+ ok = false;
+ }
+ }
+
+ s->ServerAdminMode = IsChecked(hWnd, R_SERVER_ADMIN);
+
+ SetEnable(hWnd, C_HUBNAME, s->ServerAdminMode == false ? true : false);
+ SetEnable(hWnd, S_HUBNAME, s->ServerAdminMode == false ? true : false);
+
+ GetTxtA(hWnd, C_HUBNAME, s->HubName, sizeof(s->HubName));
+ Trim(s->HubName);
+ if (StrLen(s->HubName) == 0)
+ {
+ if (s->ServerAdminMode == false)
+ {
+ ok = false;
+ }
+ }
+
+ if (IsChecked(hWnd, R_NO_SAVE))
+ {
+ Zero(s->HashedPassword, SHA1_SIZE);
+ SetTextA(hWnd, E_PASSWORD, "");
+ Disable(hWnd, E_PASSWORD);
+ Disable(hWnd, S_PASSWORD);
+ }
+ else
+ {
+ char tmp[MAX_PASSWORD_LEN + 1];
+ Enable(hWnd, E_PASSWORD);
+ Enable(hWnd, S_PASSWORD);
+ GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));
+ if (StrCmp(tmp, HIDDEN_PASSWORD) != 0)
+ {
+ Hash(s->HashedPassword, tmp, StrLen(tmp), true);
+ }
+ }
+
+ if (delete_hub_list)
+ {
+ CbReset(hWnd, C_HUBNAME);
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Configuration Edit dialog OK button
+void SmEditSettingDlgOnOk(HWND hWnd, SM_EDIT_SETTING *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (p->EditMode == false)
+ {
+ // Register new
+ SETTING *s = ZeroMalloc(sizeof(SETTING));
+ Copy(s, p->Setting, sizeof(SETTING));
+ if (SmAddSetting(s) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"), s->Title);
+ Free(s);
+ FocusEx(hWnd, E_ACCOUNT_NAME);
+ return;
+ }
+ EndDialog(hWnd, true);
+ }
+ else
+ {
+ // Update registration
+ SETTING *t = SmGetSetting(p->Setting->Title);
+ if (t != NULL && t != p->OldSetting)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"), p->Setting->Title);
+ FocusEx(hWnd, E_ACCOUNT_NAME);
+ return;
+ }
+
+ Copy(p->OldSetting, p->Setting, sizeof(SETTING));
+ Sort(sm->SettingList);
+ SmWriteSettingList();
+
+ EndDialog(hWnd, true);
+ }
+}
+
+// Settings add / edit dialog
+UINT SmEditSettingDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SM_EDIT_SETTING *p = (SM_EDIT_SETTING *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmEditSettingDlgInit(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_LOCALHOST:
+ case E_ACCOUNT_NAME:
+ case E_HOSTNAME:
+ case C_PORT:
+ case R_DIRECT_TCP:
+ case R_HTTPS:
+ case R_SOCKS:
+ case R_SERVER_ADMIN:
+ case R_HUB_ADMIN:
+ case C_HUBNAME:
+ case E_PASSWORD:
+ case R_NO_SAVE:
+ SmEditSettingDlgUpdate(hWnd, p);
+ break;
+ }
+
+ if (LOWORD(wParam) == R_LOCALHOST)
+ {
+ FocusEx(hWnd, E_HOSTNAME);
+ }
+
+ switch (LOWORD(wParam))
+ {
+ case E_HOSTNAME:
+ if (HIWORD(wParam) == EN_KILLFOCUS)
+ {
+ CmEnumHubStart(hWnd, &p->Setting->ClientOption);
+ }
+ break;
+ case C_PORT:
+ if (HIWORD(wParam) == CBN_KILLFOCUS)
+ {
+ CmEnumHubStart(hWnd, &p->Setting->ClientOption);
+ }
+ break;
+ case R_DIRECT_TCP:
+ case R_HTTPS:
+ case R_SOCKS:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ CmEnumHubStart(hWnd, &p->Setting->ClientOption);
+ }
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ SmEditSettingDlgOnOk(hWnd, p);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_PROXY_CONFIG:
+ // Proxy Settings
+ if (CmProxyDlg(hWnd, &p->Setting->ClientOption))
+ {
+ UINT n = GetInt(hWnd, C_PORT);
+ if (p->Setting->ClientOption.ProxyType == PROXY_HTTP &&
+ n != 443)
+ {
+ // Show a warning message if the destination port is
+ // other than 443 in when HTTP proxy is used
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_HTTP_PROXY_WARNING"), n) == IDYES)
+ {
+ // Change the port number to 443
+ SetText(hWnd, C_PORT, _UU("CM_PORT_2"));
+ }
+ }
+ SmEditSettingDlgUpdate(hWnd, p);
+ CmEnumHubStart(hWnd, &p->Setting->ClientOption);
+ }
+ break;
+
+ case R_NO_SAVE:
+ if (IsChecked(hWnd, R_NO_SAVE) == false)
+ {
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the Settings Adding dialog
+bool SmAddSettingDlg(HWND hWnd, wchar_t *new_name, UINT new_name_size)
+{
+ SM_EDIT_SETTING p;
+ SETTING s;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (hWnd == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ Zero(&s, sizeof(s));
+
+ s.ClientOption.Port = 443;
+
+ p.EditMode = false;
+ p.Setting = &s;
+
+ for (i = 1;;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ if (i == 1)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_1"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_2"), i);
+ }
+
+ if (SmGetSetting(tmp) == NULL)
+ {
+ UniStrCpy(s.Title, sizeof(s.Title), tmp);
+ Hash(s.HashedPassword, "", 0, true);
+ s.ServerAdminMode = true;
+ break;
+ }
+ }
+
+ ret = Dialog(hWnd, D_SM_EDIT_SETTING, SmEditSettingDlgProc, &p);
+
+ if (ret)
+ {
+ UniStrCpy(new_name, new_name_size, s.Title);
+ }
+
+ return ret;
+}
+
+// Show the settings edit dialog
+bool SmEditSettingDlg(HWND hWnd)
+{
+ SM_EDIT_SETTING p;
+ SETTING s, *setting;
+ UINT i;
+ wchar_t *name;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ i = LvGetSelected(hWnd, L_SETTING);
+ if (i == INFINITE)
+ {
+ return false;
+ }
+
+ name = LvGetStr(hWnd, L_SETTING, i, 0);
+
+ setting = SmGetSetting(name);
+ if (setting == NULL)
+ {
+ Free(name);
+ return false;
+ }
+
+ Free(name);
+
+ Copy(&s, setting, sizeof(SETTING));
+
+ Zero(&p, sizeof(p));
+
+ p.EditMode = true;
+ p.OldSetting = setting;
+ p.Setting = &s;
+
+ return Dialog(hWnd, D_SM_EDIT_SETTING, SmEditSettingDlgProc, &p);
+}
+
+// Update the configuration
+bool SmCheckNewName(SETTING *s, wchar_t *new_title)
+{
+ UINT i;
+ // Validate arguments
+ if (new_title == NULL)
+ {
+ return false;
+ }
+ if (s != NULL)
+ {
+ if (IsInList(sm->SettingList, s) == false)
+ {
+ return false;
+ }
+ }
+
+ // Check whether there is the same name in other
+ for (i = 0;i < LIST_NUM(sm->SettingList);i++)
+ {
+ SETTING *t = LIST_DATA(sm->SettingList, i);
+
+ if (s != t)
+ {
+ if (UniStrCmpi(t->Title, new_title) == 0)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Delete the configuration
+void SmDeleteSetting(wchar_t *title)
+{
+ SETTING *s;
+ // Validate arguments
+ if (title == NULL)
+ {
+ return;
+ }
+
+ s = SmGetSetting(title);
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Delete(sm->SettingList, s);
+ Free(s);
+ Sort(sm->SettingList);
+
+ SmWriteSettingList();
+}
+
+// Add the settings
+bool SmAddSetting(SETTING *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (SmGetSetting(s->Title) != NULL)
+ {
+ return false;
+ }
+
+ Insert(sm->SettingList, s);
+
+ SmWriteSettingList();
+
+ return true;
+}
+
+// Get the configuration
+SETTING *SmGetSetting(wchar_t *title)
+{
+ SETTING s;
+ // Validate arguments
+ if (title == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&s, sizeof(SETTING));
+ UniStrCpy(s.Title, sizeof(s.Title), title);
+
+ return (SETTING *)Search(sm->SettingList, &s);
+}
+
+// Comparison of connection settings
+int SmCompareSetting(void *p1, void *p2)
+{
+ SETTING *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(SETTING **)p1;
+ s2 = *(SETTING **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ return UniStrCmpi(s1->Title, s2->Title);
+}
+
+// Initialize the configuration list
+void SmInitSettingList()
+{
+ sm->SettingList = NewList(SmCompareSetting);
+
+ SmLoadSettingList();
+
+ SmInitDefaultSettingList();
+}
+
+// Release the configuration list
+void SmFreeSettingList()
+{
+ UINT i;
+
+ // Write
+ SmWriteSettingList();
+
+ for (i = 0;i < LIST_NUM(sm->SettingList);i++)
+ {
+ SETTING *s = LIST_DATA(sm->SettingList, i);
+ Free(s);
+ }
+ ReleaseList(sm->SettingList);
+
+ sm->SettingList = NULL;
+}
+
+// Write the configuration list
+void SmWriteSettingList()
+{
+ TOKEN_LIST *t;
+ UINT i;
+
+ t = MsRegEnumValue(REG_CURRENT_USER, SM_SETTING_REG_KEY);
+ if (t != NULL)
+ {
+ // Remove all existing values
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ MsRegDeleteValue(REG_CURRENT_USER, SM_SETTING_REG_KEY, name);
+ }
+
+ FreeToken(t);
+ }
+
+ for (i = 0;i < LIST_NUM(sm->SettingList);i++)
+ {
+ char name[MAX_SIZE];
+ SETTING *s = LIST_DATA(sm->SettingList, i);
+
+ // Write
+ Format(name, sizeof(name), "Setting%u", i + 1);
+ MsRegWriteBin(REG_CURRENT_USER, SM_SETTING_REG_KEY, name, s, sizeof(SETTING));
+ }
+}
+
+// Load the connection list
+void SmLoadSettingList()
+{
+ TOKEN_LIST *t;
+ UINT i;
+ char *key_name = SM_SETTING_REG_KEY;
+
+ t = MsRegEnumValue(REG_CURRENT_USER, key_name);
+ if (t == NULL)
+ {
+ key_name = SM_SETTING_REG_KEY_OLD;
+ t = MsRegEnumValue(REG_CURRENT_USER, key_name);
+ if (t == NULL)
+ {
+ return;
+ }
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ BUF *b = MsRegReadBin(REG_CURRENT_USER, key_name, name);
+ if (b != NULL)
+ {
+ if (b->Size == sizeof(SETTING))
+ {
+ SETTING *s = ZeroMalloc(sizeof(SETTING));
+ Copy(s, b->Buf, sizeof(SETTING));
+
+ Add(sm->SettingList, s);
+ }
+ FreeBuf(b);
+ }
+ }
+
+ FreeToken(t);
+
+ Sort(sm->SettingList);
+}
+
+// Initialize the default setting list
+void SmInitDefaultSettingList()
+{
+ if (LIST_NUM(sm->SettingList) == 0)
+ {
+ bool b = false;
+ LIST *pl = MsGetProcessList();
+
+ if (pl != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(pl);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(pl, i);
+
+ if (UniInStr(p->ExeFilenameW, L"vpnserver.exe") || UniInStr(p->ExeFilenameW, L"vpnserver_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"vpnserver_ia64.exe") ||
+ UniInStr(p->ExeFilenameW, L"vpnbridge.exe") || UniInStr(p->ExeFilenameW, L"vpnbridge_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"vpnbridge_ia64.exe"))
+ {
+ b = true;
+ }
+
+ if (UniInStr(p->ExeFilenameW, L"sevpnserver.exe") || UniInStr(p->ExeFilenameW, L"sevpnserver_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"sevpnserver_ia64.exe") ||
+ UniInStr(p->ExeFilenameW, L"sevpnbridge.exe") || UniInStr(p->ExeFilenameW, L"sevpnbridge_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"sevpnbridge_ia64.exe"))
+ {
+ b = true;
+ }
+
+ if (UniInStr(p->ExeFilenameW, L"utvpnserver.exe") || UniInStr(p->ExeFilenameW, L"utvpnserver_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"utvpnserver_ia64.exe") ||
+ UniInStr(p->ExeFilenameW, L"utvpnbridge.exe") || UniInStr(p->ExeFilenameW, L"utvpnbridge_x64.exe") ||
+ UniInStr(p->ExeFilenameW, L"utvpnbridge_ia64.exe"))
+ {
+ b = true;
+ }
+ }
+ }
+
+ MsFreeProcessList(pl);
+
+ if (b == false)
+ {
+ if (MsIsServiceRunning(GC_SVC_NAME_VPNSERVER) || MsIsServiceRunning(GC_SVC_NAME_VPNBRIDGE))
+ {
+ b = true;
+ }
+ }
+
+ if (b)
+ {
+ SETTING *s = ZeroMalloc(sizeof(SETTING));
+
+ UniStrCpy(s->Title, sizeof(s->Title), _UU("SM_LOCALHOST"));
+ s->ServerAdminMode = true;
+ Hash(s->HashedPassword, "", 0, true);
+ UniStrCpy(s->ClientOption.AccountName, sizeof(s->ClientOption.AccountName), s->Title);
+ StrCpy(s->ClientOption.Hostname, sizeof(s->ClientOption.Hostname), "localhost");
+ s->ClientOption.Port = GC_DEFAULT_PORT;
+
+ Add(sm->SettingList, s);
+ }
+ }
+}
+
+// Main dialog initialization
+void SmMainDlgInit(HWND hWnd)
+{
+ wchar_t *last_select;
+ UINT i = INFINITE;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_VPNSERVER);
+
+ LvInit(hWnd, L_SETTING);
+ LvSetStyle(hWnd, L_SETTING, LVS_EX_GRIDLINES);
+ LvInsertColumn(hWnd, L_SETTING, 0, _UU("SM_MAIN_COLUMN_1"), 145);
+ LvInsertColumn(hWnd, L_SETTING, 1, _UU("SM_MAIN_COLUMN_2"), 129);
+ LvInsertColumn(hWnd, L_SETTING, 2, _UU("SM_MAIN_COLUMN_3"), 125);
+
+ SmRefreshSetting(hWnd);
+
+ last_select = MsRegReadStrW(REG_CURRENT_USER, SM_REG_KEY, "Last Select");
+ if (UniIsEmptyStr(last_select) == false)
+ {
+ i = LvSearchStr(hWnd, L_SETTING, 0, last_select);
+ }
+ Free(last_select);
+
+ if (i == INFINITE)
+ {
+ LvSelect(hWnd, L_SETTING, 0);
+ }
+ else
+ {
+ LvSelect(hWnd, L_SETTING, i);
+ }
+
+ DlgFont(hWnd, IDOK, 10, true);
+
+ Focus(hWnd, L_SETTING);
+
+ SmMainDlgUpdate(hWnd);
+}
+
+// Update the configuration list
+void SmRefreshSetting(HWND hWnd)
+{
+ SmRefreshSettingEx(hWnd, NULL);
+}
+void SmRefreshSettingEx(HWND hWnd, wchar_t *select_name)
+{
+ LVB *b;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ b = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(sm->SettingList);i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ SETTING *s = LIST_DATA(sm->SettingList, i);
+
+ if (s->ServerAdminMode)
+ {
+ UniStrCpy(tmp, sizeof(tmp), _UU("SM_MODE_SERVER"));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SM_MODE_HUB"), s->HubName);
+ }
+
+ StrToUni(tmp2, sizeof(tmp2), s->ClientOption.Hostname);
+
+ LvInsertAdd(b,
+ (s->ServerAdminMode ? ICO_SERVER_ONLINE : ICO_HUB),
+ NULL,
+ 3,
+ s->Title,
+ tmp2,
+ tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_SETTING);
+
+ if (UniIsEmptyStr(select_name) == false)
+ {
+ LvSelect(hWnd, L_SETTING, INFINITE);
+ LvSelect(hWnd, L_SETTING, LvSearchStr(hWnd, L_SETTING, 0, select_name));
+ }
+}
+
+// Main dialog update
+void SmMainDlgUpdate(HWND hWnd)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_SETTING) == false)
+ {
+ ok = false;
+ }
+ if (LvIsMultiMasked(hWnd, L_SETTING))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+ SetEnable(hWnd, B_EDIT_SETTING, ok);
+ SetEnable(hWnd, B_DELETE, ok);
+}
+
+// Main window procedure
+UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ NMHDR *n;
+ NMLVDISPINFOW *info;
+ NMLVKEYDOWN *key;
+ wchar_t *tmp;
+ UINT i;
+ wchar_t new_name[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SmMainDlgInit(hWnd);
+ SetTimer(hWnd, 4, 100, NULL);
+
+ // Updater start
+ sm->Update = InitUpdateUi(_UU("PRODUCT_NAME_VPN_SMGR"), NAME_OF_VPN_SERVER_MANAGER, NULL, GetCurrentBuildDate(),
+ CEDAR_BUILD, CEDAR_VER, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 4:
+ KillTimer(hWnd, 4);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ // Connection
+ i = LvGetSelected(hWnd, L_SETTING);
+ if (i != INFINITE)
+ {
+ tmp = LvGetStr(hWnd, L_SETTING, i, 0);
+ if (tmp != NULL)
+ {
+ SETTING *setting = SmGetSetting(tmp);
+ if (setting != NULL)
+ {
+ SETTING s;
+
+ // Record in the registry as the last choice
+ MsRegWriteStrW(REG_CURRENT_USER, SM_REG_KEY, "Last Select", tmp);
+
+ // Copy the configuration
+ Copy(&s, setting, sizeof(SETTING));
+ SmConnect(hWnd, &s);
+ }
+ Free(tmp);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case B_NEW_SETTING:
+ // Add
+ if (SmAddSettingDlg(hWnd, new_name, sizeof(new_name)))
+ {
+ SmRefreshSettingEx(hWnd, new_name);
+ }
+ break;
+
+ case B_EDIT_SETTING:
+ // Edit
+ if (SmEditSettingDlg(hWnd))
+ {
+ SmWriteSettingList();
+ SmRefreshSetting(hWnd);
+ }
+
+ break;
+
+ case B_DELETE:
+ // Delete
+ i = LvGetSelected(hWnd, L_SETTING);
+ if (i != INFINITE)
+ {
+ tmp = LvGetStr(hWnd, L_SETTING, i, 0);
+ if (tmp != NULL)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SM_SETTING_DELETE_MSG"), tmp) == IDYES)
+ {
+ SmDeleteSetting(tmp);
+ SmWriteSettingList();
+ SmRefreshSetting(hWnd);
+ }
+ Free(tmp);
+ }
+ }
+ break;
+
+ case B_ABOUT:
+ // Version information
+ AboutEx(hWnd, sm->Cedar, _UU("PRODUCT_NAME_VPN_SMGR"), sm->Update);
+ break;
+
+ case B_SECURE_MANAGER:
+ // Smart Card Manager
+ SmSecureManager(hWnd);
+ break;
+
+ case B_SELECT_SECURE:
+ // Smart card selection
+ SmSelectSecureId(hWnd);
+ break;
+
+ case B_CERT_TOOL:
+ // Certificate Creation Tool
+ SmCreateCert(hWnd, NULL, NULL, false, NULL, false);
+ break;
+ }
+
+ break;
+
+ case WM_CLOSE:
+ // Updater terminate
+ if (sm->Update != NULL)
+ {
+ FreeUpdateUi(sm->Update);
+ sm->Update = NULL;
+ }
+
+ EndDialog(hWnd, 0);
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_SETTING:
+ switch (n->code)
+ {
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+
+ case LVN_KEYDOWN:
+ key = (NMLVKEYDOWN *)n;
+ if (key != NULL)
+ {
+ UINT code = key->wVKey;
+ switch (code)
+ {
+ case VK_F2:
+ if (LvIsSelected(hWnd, L_SETTING))
+ {
+ LvRename(hWnd, L_SETTING, LvGetSelected(hWnd, L_SETTING));
+ }
+ break;
+
+ case VK_DELETE:
+ Command(hWnd, B_DELETE);
+ break;
+
+ case VK_RETURN:
+ Command(hWnd, IDOK);
+ break;
+ }
+ }
+ break;
+
+ case LVN_ENDLABELEDITW:
+ // Change the name
+ info = (NMLVDISPINFOW *)n;
+ if (info->item.pszText != NULL)
+ {
+ wchar_t *new_name = info->item.pszText;
+ wchar_t *old_name = LvGetStr(hWnd, L_SETTING, info->item.iItem, 0);
+
+ if (old_name != NULL)
+ {
+ if (UniStrCmp(new_name, old_name) != 0 && UniStrLen(new_name) != 0)
+ {
+ // Change the name
+ SETTING *s = SmGetSetting(old_name);
+ if (s != NULL)
+ {
+ if (SmGetSetting(new_name) != NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"),
+ new_name);
+ }
+ else
+ {
+ UniStrCpy(s->Title, sizeof(s->Title), new_name);
+ Sort(sm->SettingList);
+ SmWriteSettingList();
+ LvSetItem(hWnd, L_SETTING, info->item.iItem, 0, new_name);
+ }
+ }
+ }
+
+ Free(old_name);
+ }
+ }
+ break;
+
+ case LVN_ITEMCHANGED:
+ SmMainDlgUpdate(hWnd);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, L_SETTING);
+
+ return 0;
+}
+
+// Main window
+void SmMainDlg()
+{
+ Dialog(NULL, D_SM_MAIN, SmMainDlgProc, NULL);
+}
+
+// Server Manager main process
+void MainSM()
+{
+ if (sm->TempSetting == NULL)
+ {
+ // Open the main window
+ SmMainDlg();
+ }
+ else
+ {
+ SmConnect(sm->hParentWnd, sm->TempSetting);
+ }
+}
+
+// Initialize
+void InitSM()
+{
+ InitSMEx(false);
+}
+void InitSMEx(bool from_cm)
+{
+ if (sm != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ sm = ZeroMalloc(sizeof(SM));
+
+ if (from_cm == false)
+ {
+ InitWinUi(_UU("SM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+ }
+
+ sm->Cedar = NewCedar(NULL, NULL);
+
+ if (from_cm == false)
+ {
+ SmInitSettingList();
+ InitCM(false);
+
+ // Interpret the command line
+ SmParseCommandLine();
+ }
+}
+
+// Interpret the command line
+void SmParseCommandLine()
+{
+ LIST *o;
+ CONSOLE *c = NewLocalConsole(NULL, NULL);
+ wchar_t *cmdline;
+ PARAM args[] =
+ {
+ {"[vpnserver]", NULL, NULL, NULL, NULL,},
+ {"HUB", NULL, NULL, NULL, NULL,},
+ {"PASSWORD", NULL, NULL, NULL, NULL,},
+ {"TITLE", NULL, NULL, NULL, NULL,},
+ {"HWND", NULL, NULL, NULL, NULL,},
+ };
+ if (c == NULL)
+ {
+ return;
+ }
+
+ cmdline = GetCommandLineUniStr();
+
+ if (UniIsEmptyStr(cmdline) == false)
+ {
+ o = ParseCommandList(c, "vpnsmgr", cmdline, args, sizeof(args) / sizeof(args[0]));
+ if (o != NULL)
+ {
+ char *host;
+ UINT port;
+
+ if (ParseHostPort(GetParamStr(o, "[vpnserver]"), &host, &port, 443))
+ {
+ char *hub = GetParamStr(o, "HUB");
+ char *password = GetParamStr(o, "PASSWORD");
+ char *title = GetParamStr(o, "TITLE");
+ char *hwndstr = GetParamStr(o, "HWND");
+
+ if (hub == NULL || StrCmpi(hub, "\"") == 0)
+ {
+ hub = CopyStr("");
+ }
+ if (password == NULL)
+ {
+ password = CopyStr("");
+ }
+ if (title == NULL)
+ {
+ title = CopyStr(host);
+ }
+
+ if (IsEmptyStr(host) == false)
+ {
+ SETTING *s = ZeroMalloc(sizeof(SETTING));
+ BUF *b;
+ CLIENT_OPTION *o;
+
+ StrToUni(s->Title, sizeof(s->Title), title);
+
+ if (IsEmptyStr(hub))
+ {
+ s->ServerAdminMode = true;
+ }
+ else
+ {
+ s->ServerAdminMode = false;
+ StrCpy(s->HubName, sizeof(s->HubName), hub);
+ }
+
+ b = StrToBin(password);
+ if (b == NULL || b->Size != SHA1_SIZE)
+ {
+ Hash(s->HashedPassword, password, StrLen(password), true);
+ }
+ else
+ {
+ Copy(s->HashedPassword, b->Buf, SHA1_SIZE);
+ }
+ FreeBuf(b);
+
+ o = &s->ClientOption;
+
+ UniStrCpy(o->AccountName, sizeof(o->AccountName), s->Title);
+ StrCpy(o->Hostname, sizeof(o->Hostname), host);
+ o->Port = port;
+ o->ProxyType = PROXY_DIRECT;
+ StrCpy(o->DeviceName, sizeof(o->DeviceName), "DUMMY");
+
+ sm->TempSetting = s;
+
+ if (IsEmptyStr(hwndstr) == false)
+ {
+ sm->hParentWnd = (HWND)ToInt64(hwndstr);
+ }
+ }
+
+ Free(hwndstr);
+ Free(title);
+ Free(hub);
+ Free(password);
+ Free(host);
+ }
+ }
+ }
+
+ Free(cmdline);
+
+ c->Free(c);
+}
+
+// Release
+void FreeSM()
+{
+ FreeSMEx(false);
+}
+void FreeSMEx(bool from_cm)
+{
+ if (sm == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ if (from_cm == false)
+ {
+ FreeCM();
+
+ SmFreeSettingList();
+ }
+
+ ReleaseCedar(sm->Cedar);
+
+ if (from_cm == false)
+ {
+ FreeWinUi();
+ }
+
+ if (sm->TempSetting != NULL)
+ {
+ Free(sm->TempSetting);
+ }
+
+ Free(sm);
+ sm = NULL;
+}
+
+// Running the Server Manager
+void SMExec()
+{
+ InitSM();
+ MainSM();
+ FreeSM();
+}
+
+#endif // WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SM.h b/src/Cedar/SM.h
new file mode 100644
index 00000000..10d1dab8
--- /dev/null
+++ b/src/Cedar/SM.h
@@ -0,0 +1,95 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SM.h
+// Header of SM.c
+
+#ifndef SM_H
+#define SM_H
+
+void SMExec();
+
+#endif // SM_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SMInner.h b/src/Cedar/SMInner.h
new file mode 100644
index 00000000..2bf8cdc8
--- /dev/null
+++ b/src/Cedar/SMInner.h
@@ -0,0 +1,801 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SMInner.h
+// The internal header of SM.c
+
+// Constants
+#define SM_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager"
+#define SM_CERT_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Cert Tool"
+#define SM_SETTING_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Settings"
+#define SM_LASTHUB_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Last HUB Name"
+
+#define NAME_OF_VPN_SERVER_MANAGER "vpnsmgr"
+#define NAME_OF_VPN_SERVER_TARGET "vpnserver@%s"
+#define NAME_OF_VPN_BRIDGE_TARGET "vpnbridge@%s"
+
+// Constants (Old value)
+#define SM_SETTING_REG_KEY_OLD "Software\\SoftEther Corporation\\SoftEther VPN 2.0\\Server Manager\\Settings"
+
+// Connection setting
+typedef struct SETTING
+{
+ wchar_t Title[MAX_SIZE]; // Setting Name
+ bool ServerAdminMode; // Server management mode
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UCHAR HashedPassword[SHA1_SIZE]; // Password
+ CLIENT_OPTION ClientOption; // Client Option
+ UCHAR Reserved[10240 - sizeof(bool) * 8 - SHA1_SIZE]; // Reserved area
+} SETTING;
+
+// Structure declaration
+typedef struct SM
+{
+ CEDAR *Cedar; // Cedar
+ LIST *SettingList; // Setting List
+ SETTING *TempSetting; // Temporaly setting
+ HWND hParentWnd; // Parent window handle
+ WINUI_UPDATE *Update; // Updater
+} SM;
+
+// Edit connection settings
+typedef struct SM_EDIT_SETTING
+{
+ bool EditMode; // Edit mode
+ SETTING *OldSetting; // Pointer to the previous settings
+ SETTING *Setting; // Pointer to the configuration
+ bool Inited; // Initialized flag
+} SM_EDIT_SETTING;
+
+// Server management dialog
+typedef struct SM_SERVER
+{
+ RPC *Rpc; // RPC
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ wchar_t Title[MAX_SIZE]; // Title
+ bool ServerAdminMode; // Server management mode
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+ UINT ServerType; // Type of server
+ bool Bridge; // VPN Bridge product
+ UINT PolicyVer; // Policy version
+ RPC_SERVER_STATUS ServerStatus; // Server status
+ RPC_SERVER_INFO ServerInfo; // Server Information
+ CAPSLIST *CapsList; // Caps list
+ SETTING *CurrentSetting; // The current connection settings
+ wchar_t *AdminMsg; // Message for Administrators
+ bool IPsecMessageDisplayed; // Whether to have already displayed a message about IPsec
+ bool VgsMessageDisplayed; // Whether to have already displayed a message about VGS
+ WINUI_UPDATE *Update; // Update notification
+ bool IsInClient; // Within VPN Client mode
+} SM_SERVER;
+
+typedef void (SM_STATUS_INIT_PROC)(HWND hWnd, SM_SERVER *p, void *param);
+typedef bool (SM_STATUS_REFRESH_PROC)(HWND hWnd, SM_SERVER *p, void *param);
+
+// Information display dialog
+typedef struct SM_STATUS
+{
+ SM_SERVER *p; // Pointer to the P
+ void *Param; // Parameter
+ UINT Icon; // Icon
+ wchar_t *Caption; // Title
+ bool show_refresh_button; // Show Updates button
+ bool NoImage; // No image
+ SM_STATUS_INIT_PROC *InitProc;
+ SM_STATUS_REFRESH_PROC *RefreshProc;
+} SM_STATUS;
+
+// Virtual HUB edit dialog
+typedef struct SM_EDIT_HUB
+{
+ SM_SERVER *p; // P
+ bool EditMode; // Edit mode
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
+} SM_EDIT_HUB;
+
+// SSL related
+typedef struct SM_SSL
+{
+ SM_SERVER *p; // P
+ X *Cert; // Certificate
+ K *Key; // Secret key
+ bool SetCertAndKey; // Set the key
+} SM_SSL;
+
+// Save the certificate
+typedef struct SM_SAVE_KEY_PAIR
+{
+ X *Cert; // Certificate
+ K *Key; // Secret key
+ char *Pass; // Passphrase
+} SM_SAVE_KEY_PAIR;
+
+// Connection information
+typedef struct SM_CONNECTION_INFO
+{
+ SM_SERVER *p; // P
+ char *ConnectionName; // Connection name
+} SM_CONNECTION_INFO;
+
+// Management of HUB
+typedef struct SM_HUB
+{
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ char *HubName; // HUB name
+} SM_HUB;
+
+// Show the User list
+typedef struct SM_USER
+{
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ char *GroupName; // Filter by group name
+ bool SelectMode; // Selection mode
+ char *SelectedName; // User name of the selected
+ bool AllowGroup; // Allow selection of group
+ bool CreateNow; // Create a user immediately
+} SM_USER;
+
+// Edit the User
+typedef struct SM_EDIT_USER
+{
+ bool Inited; // Initialized flag
+ bool EditMode; // Edit mode
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ RPC_SET_USER SetUser; // Configure the User
+} SM_EDIT_USER;
+
+// User information
+typedef struct SM_USER_INFO
+{
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ char *Username; // Username
+} SM_USER_INFO;
+
+// Policy
+typedef struct SM_POLICY
+{
+ bool Inited; // Initialize
+ POLICY *Policy; // Policy
+ wchar_t *Caption; // Title
+ bool CascadeMode; // Cascade mode
+ UINT Ver; // Version
+} SM_POLICY;
+
+// Show the Group list
+typedef struct SM_GROUP
+{
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ bool SelectMode; // Selection mode
+ char *SelectedGroupName; // Group name of the selected
+} SM_GROUP;
+
+// Edit the Group
+typedef struct SM_EDIT_GROUP
+{
+ bool Inited; // Initialization flag
+ bool EditMode; // Edit mode
+ SM_SERVER *p; // P
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ RPC_SET_GROUP SetGroup; // Group Settings
+} SM_EDIT_GROUP;
+
+// Access list
+typedef struct SM_ACCESS_LIST
+{
+ RPC *Rpc; // RPC
+ SM_HUB *Hub; // HUB
+ LIST *AccessList; // Access list
+} SM_ACCESS_LIST;
+
+// Edit the access list
+typedef struct SM_EDIT_ACCESS
+{
+ SM_HUB *Hub; // HUB
+ bool Inited; // Initialization flag
+ bool EditMode; // Edit mode
+ SM_ACCESS_LIST *AccessList; // Access list
+ ACCESS *Access; // Access list item
+} SM_EDIT_ACCESS;
+
+// Display status of the access list
+typedef struct SM_LINK
+{
+ SM_HUB *Hub; // HUB
+ wchar_t *AccountName; // Account name
+} SM_LINK;
+
+// Session status
+typedef struct SM_SESSION_STATUS
+{
+ SM_HUB *Hub; // HUB
+ char *SessionName; // Session name
+} SM_SESSION_STATUS;
+
+// Address table
+typedef struct SM_TABLE
+{
+ SM_HUB *Hub; // HUB
+ RPC *Rpc; // RPC
+ char *SessionName; // Session name
+} SM_TABLE;
+
+// Certificate tool
+typedef struct SM_CERT
+{
+ X *x; // Generated certificate
+ K *k; // Generated secret key
+ X *root_x; // Root certificate
+ K *root_k; // Private key of the root certificate
+ bool do_not_save; // Do not save to the file
+ char *default_cn; // Default CN
+ bool root_only; // Only the root certificate
+} SM_CERT;
+
+// Config edit
+typedef struct SM_CONFIG
+{
+ SM_SERVER *s; // SM_SERVER
+ RPC_CONFIG Config; // Config body
+} SM_CONFIG;
+
+// Hub_admin_option edit
+typedef struct SM_EDIT_AO
+{
+ SM_EDIT_HUB *e;
+ bool CanChange;
+ RPC_ADMIN_OPTION CurrentOptions;
+ RPC_ADMIN_OPTION DefaultOptions;
+ bool NewMode;
+ char Name[MAX_ADMIN_OPTION_NAME_LEN + 1];
+ UINT Value;
+ bool ExtOption;
+} SM_EDIT_AO;
+
+// Editing the switch
+typedef struct SM_L3SW
+{
+ SM_SERVER *s;
+ char *SwitchName;
+ bool Enable;
+} SM_L3SW;
+
+// Specify the certificate and private key in the smart card
+typedef struct SM_SECURE_KEYPAIR
+{
+ UINT Id;
+ bool UseCert;
+ bool UseKey;
+ char CertName[MAX_SIZE];
+ char KeyName[MAX_SIZE];
+ bool Flag;
+ UINT BitmapId;
+} SM_SECURE_KEYPAIR;
+
+// CRL edit
+typedef struct SM_EDIT_CRL
+{
+ SM_HUB *s;
+ bool NewCrl;
+ UINT Key;
+} SM_EDIT_CRL;
+
+// AC list edit
+typedef struct SM_EDIT_AC_LIST
+{
+ SM_EDIT_HUB *s;
+ LIST *AcList;
+} SM_EDIT_AC_LIST;
+
+// AC edit
+typedef struct SM_EDIT_AC
+{
+ SM_EDIT_AC_LIST *e;
+ UINT id;
+} SM_EDIT_AC;
+
+// Download the log File
+typedef struct SM_READ_LOG_FILE
+{
+ HWND hWnd;
+ SM_SERVER *s;
+ char *server_name;
+ char *filepath;
+ UINT totalsize;
+ bool cancel_flag;
+ BUF *Buffer;
+} SM_READ_LOG_FILE;
+
+// Setup dialog
+typedef struct SM_SETUP
+{
+ SM_SERVER *s;
+ RPC *Rpc;
+ bool IsBridge;
+ bool UseRemote; // Remote Access VPN
+ bool UseSite; // LAN-to-LAN VPN
+ bool UseSiteEdge; // VPN Server / Bridge to be installed in each site
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ bool Flag1;
+ bool Flag2;
+} SM_SETUP;
+
+// EtherIP ID edit dialog
+typedef struct SM_ETHERIP_ID
+{
+ SM_SERVER *s;
+ bool EditMode;
+ char EditId[MAX_SIZE];
+ bool InitCompleted;
+ ETHERIP_ID Data;
+} SM_ETHERIP_ID;
+
+// DDNS dialog
+typedef struct SM_DDNS
+{
+ SM_SERVER *s;
+ DDNS_CLIENT_STATUS Status;
+ bool Flag;
+ bool HostnameSetFlag;
+ bool Changed;
+ bool Silent;
+ bool NoChangeCert;
+ bool DoNotPoll;
+} SM_DDNS;
+
+// VPN Azure dialog
+typedef struct SM_AZURE
+{
+ SM_SERVER *s;
+ bool OnSetup;
+} SM_AZURE;
+
+
+
+// Function prototype
+void InitSM();
+void InitSMEx(bool from_cm);
+void SmParseCommandLine();
+void MainSM();
+void FreeSM();
+void FreeSMEx(bool from_cm);
+void SmMainDlg();
+UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmMainDlgInit(HWND hWnd);
+void SmMainDlgUpdate(HWND hWnd);
+void SmInitSettingList();
+void SmFreeSettingList();
+void SmWriteSettingList();
+void SmLoadSettingList();
+void SmInitDefaultSettingList();
+int SmCompareSetting(void *p1, void *p2);
+SETTING *SmGetSetting(wchar_t *title);
+bool SmAddSetting(SETTING *s);
+void SmDeleteSetting(wchar_t *title);
+bool SmCheckNewName(SETTING *s, wchar_t *new_title);
+void SmRefreshSetting(HWND hWnd);
+void SmRefreshSettingEx(HWND hWnd, wchar_t *select_name);
+bool SmAddSettingDlg(HWND hWnd, wchar_t *new_name, UINT new_name_size);
+bool SmEditSettingDlg(HWND hWnd);
+UINT SmEditSettingDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditSettingDlgInit(HWND hWnd, SM_EDIT_SETTING *p);
+void SmEditSettingDlgUpdate(HWND hWnd, SM_EDIT_SETTING *p);
+void SmEditSettingDlgOnOk(HWND hWnd, SM_EDIT_SETTING *p);
+void SmConnect(HWND hWnd, SETTING *s);
+void SmConnectEx(HWND hWnd, SETTING *s, bool is_in_client);
+char *SmPassword(HWND hWnd, char *server_name);
+UINT SmServerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmServerDlgInit(HWND hWnd, SM_SERVER *p);
+void SmServerDlgUpdate(HWND hWnd, SM_SERVER *p);
+void SmServerDlgRefresh(HWND hWnd, SM_SERVER *p);
+void SmStatusDlg(HWND hWnd, SM_SERVER *p, void *param, bool no_image, bool show_refresh_button, wchar_t *caption, UINT icon,
+ SM_STATUS_INIT_PROC *init, SM_STATUS_REFRESH_PROC *refresh);
+UINT SmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool SmRefreshHubStatus(HWND hWnd, SM_SERVER *p, void *param);
+void SmInsertTrafficInfo(LVB *b, TRAFFIC *t);
+bool SmCreateHubDlg(HWND hWnd, SM_SERVER *p);
+bool SmEditHubDlg(HWND hWnd, SM_SERVER *p, char *hubname);
+UINT SmEditHubProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditHubInit(HWND hWnd, SM_EDIT_HUB *s);
+void SmEditHubUpdate(HWND hWnd, SM_EDIT_HUB *s);
+void SmEditHubOnOk(HWND hWnd, SM_EDIT_HUB *s);
+bool SmCreateListenerDlg(HWND hWnd, SM_SERVER *p);
+UINT SmCreateListenerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSslDlg(HWND hWnd, SM_SERVER *p);
+UINT SmSslDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSslDlgInit(HWND hWnd, SM_SSL *s);
+void SmSslDlgOnOk(HWND hWnd, SM_SSL *s);
+void SmSslDlgUpdate(HWND hWnd, SM_SSL *s);
+void SmGetCertInfoStr(wchar_t *str, UINT size, X *x);
+bool SmRegenerateServerCert(HWND hWnd, SM_SERVER *server, char *default_cn, X **x, K **k, bool root_only);
+bool SmSaveKeyPairDlg(HWND hWnd, X *x, K *k);
+UINT SmSaveKeyPairDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSaveKeyPairDlgInit(HWND hWnd, SM_SAVE_KEY_PAIR *s);
+void SmSaveKeyPairDlgUpdate(HWND hWnd, SM_SAVE_KEY_PAIR *s);
+void SmSaveKeyPairDlgOnOk(HWND hWnd, SM_SAVE_KEY_PAIR *s);
+bool SmRefreshServerStatus(HWND hWnd, SM_SERVER *p, void *param);
+bool SmRefreshServerInfo(HWND hWnd, SM_SERVER *p, void *param);
+void SmPrintNodeInfo(LVB *b, NODE_INFO *info);
+wchar_t *SmGetConnectionTypeStr(UINT type);
+void SmConnectionDlg(HWND hWnd, SM_SERVER *p);
+UINT SmConnectionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmConnectionDlgInit(HWND hWnd, SM_SERVER *p);
+void SmConnectionDlgRefresh(HWND hWnd, SM_SERVER *p);
+void SmConnectionDlgUpdate(HWND hWnd, SM_SERVER *p);
+bool SmRefreshConnectionStatus(HWND hWnd, SM_SERVER *p, void *param);
+bool SmFarmDlg(HWND hWnd, SM_SERVER *p);
+UINT SmFarmDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmFarmDlgInit(HWND hWnd, SM_SERVER *p);
+void SmFarmDlgUpdate(HWND hWnd, SM_SERVER *p);
+void SmFarmDlgOnOk(HWND hWnd, SM_SERVER *p);
+LIST *SmStrToPortList(char *str);
+UINT SmFarmMemberDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmFarmMemberDlgInit(HWND hWnd, SM_SERVER *p);
+void SmFarmMemberDlgUpdate(HWND hWnd, SM_SERVER *p);
+void SmFarmMemberDlgRefresh(HWND hWnd, SM_SERVER *p);
+void SmFarmMemberDlgOnOk(HWND hWnd, SM_SERVER *p);
+void SmFarmMemberCert(HWND hWnd, SM_SERVER *p, UINT id);
+bool SmRefreshFarmMemberInfo(HWND hWnd, SM_SERVER *p, void *param);
+bool SmRefreshFarmConnectionInfo(HWND hWnd, SM_SERVER *p, void *param);
+UINT SmChangeServerPasswordDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubDlg(HWND hWnd, SM_HUB *s);
+UINT SmHubDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubDlgInit(HWND hWnd, SM_HUB *s);
+void SmHubDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmHubDlgRefresh(HWND hWnd, SM_HUB *s);
+void SmUserListDlg(HWND hWnd, SM_HUB *s);
+UINT SmUserListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmUserListInit(HWND hWnd, SM_USER *s);
+void SmUserListRefresh(HWND hWnd, SM_USER *s);
+void SmUserListUpdate(HWND hWnd, SM_USER *s);
+wchar_t *SmGetAuthTypeStr(UINT id);
+bool SmCreateUserDlg(HWND hWnd, SM_HUB *s);
+UINT SmEditUserDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditUserDlgInit(HWND hWnd, SM_EDIT_USER *s);
+void SmEditUserDlgUpdate(HWND hWnd, SM_EDIT_USER *s);
+void SmEditUserDlgOk(HWND hWnd, SM_EDIT_USER *s);
+bool SmPolicyDlg(HWND hWnd, POLICY *p, wchar_t *caption);
+bool SmPolicyDlgEx(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode);
+bool SmPolicyDlgEx2(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode, UINT ver);
+UINT SmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmPolicyDlgInit(HWND hWnd, SM_POLICY *s);
+void SmPolicyDlgUpdate(HWND hWnd, SM_POLICY *s);
+void SmPolicyDlgOk(HWND hWnd, SM_POLICY *s);
+bool SmEditUserDlg(HWND hWnd, SM_HUB *s, char *username);
+bool SmRefreshUserInfo(HWND hWnd, SM_SERVER *s, void *param);
+void SmGroupListDlg(HWND hWnd, SM_HUB *s);
+char *SmSelectGroupDlg(HWND hWnd, SM_HUB *s, char *default_name);
+UINT SmGroupListDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmGroupListDlgInit(HWND hWnd, SM_GROUP *s);
+void SmGroupListDlgUpdate(HWND hWnd, SM_GROUP *s);
+void SmGroupListDlgRefresh(HWND hWnd, SM_GROUP *s);
+bool SmCreateGroupDlg(HWND hWnd, SM_GROUP *s);
+bool SmEditGroupDlg(HWND hWnd, SM_GROUP *s, char *name);
+UINT SmEditGroupDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditGroupDlgInit(HWND hWnd, SM_EDIT_GROUP *g);
+void SmEditGroupDlgUpdate(HWND hWnd, SM_EDIT_GROUP *g);
+void SmEditGroupDlgOnOk(HWND hWnd, SM_EDIT_GROUP *g);
+void SmUserListDlgEx(HWND hWnd, SM_HUB *s, char *groupname, bool create);
+void SmAccessListDlg(HWND hWnd, SM_HUB *s);
+UINT SmAccessListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmAccessListInit(HWND hWnd, SM_ACCESS_LIST *s);
+void SmAccessListUpdate(HWND hWnd, SM_ACCESS_LIST *s);
+void SmAccessListRefresh(HWND hWnd, SM_ACCESS_LIST *s);
+bool SmAddAccess(HWND hWnd, SM_ACCESS_LIST *s, bool ipv6);
+bool SmCloneAccess(HWND hWnd, SM_ACCESS_LIST *s, ACCESS *t);
+bool SmEditAccess(HWND hWnd, SM_ACCESS_LIST *s, ACCESS *a);
+UINT SmEditAccessDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditAccessInit(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmEditAccessUpdate(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmEditAccessOnOk(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmRedirect(HWND hWnd, SM_EDIT_ACCESS *s);
+UINT SmRedirectDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmRedirectDlgInit(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmRedirectDlgUpdate(HWND hWnd, SM_EDIT_ACCESS *s);
+UINT SmSimulationDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSimulationUpdate(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmSimulationInit(HWND hWnd, SM_EDIT_ACCESS *s);
+void SmSimulationOnOk(HWND hWnd, SM_EDIT_ACCESS *s);
+char *SmSelectUserDlg(HWND hWnd, SM_HUB *s, char *default_name);
+char *SmSelectUserDlgEx(HWND hWnd, SM_HUB *s, char *default_name, bool allow_group);
+void SmRadiusDlg(HWND hWnd, SM_HUB *s);
+UINT SmRadiusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmRadiusDlgInit(HWND hWnd, SM_HUB *s);
+void SmRadiusDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmRadiusDlgOnOk(HWND hWnd, SM_HUB *s);
+void SmLinkDlg(HWND hWnd, SM_HUB *s);
+void SmLinkDlgEx(HWND hWnd, SM_HUB *s, bool createNow);
+UINT SmLinkDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLinkDlgInit(HWND hWnd, SM_HUB *s);
+void SmLinkDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmLinkDlgRefresh(HWND hWnd, SM_HUB *s);
+bool SmLinkCreate(HWND hWnd, SM_HUB *s);
+bool SmLinkCreateEx(HWND hWnd, SM_HUB *s, bool connectNow);
+bool SmLinkEdit(HWND hWnd, SM_HUB *s, wchar_t *name);
+bool SmRefreshLinkStatus(HWND hWnd, SM_SERVER *s, void *param);
+UINT SmLogDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLogDlgInit(HWND hWnd, SM_HUB *s);
+void SmLogDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmLogDlgOnOk(HWND hWnd, SM_HUB *s);
+void SmCaDlg(HWND hWnd, SM_HUB *s);
+UINT SmCaDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmCaDlgInit(HWND hWnd, SM_HUB *s);
+void SmCaDlgRefresh(HWND hWnd, SM_HUB *s);
+void SmCaDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmCaDlgOnOk(HWND hWnd, SM_HUB *s);
+bool SmCaDlgAdd(HWND hWnd, SM_HUB *s);
+void SmSessionDlg(HWND hWnd, SM_HUB *s);
+UINT SmSessionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSessionDlgInit(HWND hWnd, SM_HUB *s);
+void SmSessionDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmSessionDlgRefresh(HWND hWnd, SM_HUB *s);
+bool SmRefreshSessionStatus(HWND hWnd, SM_SERVER *s, void *param);
+void SmMacTableDlg(HWND hWnd, SM_HUB *s, char *session_name);
+UINT SmMacTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmMacTableDlgInit(HWND hWnd, SM_TABLE *s);
+void SmMacTableDlgUpdate(HWND hWnd, SM_TABLE *s);
+void SmMacTableDlgRefresh(HWND hWnd, SM_TABLE *s);
+void SmIpTableDlg(HWND hWnd, SM_HUB *s, char *session_name);
+UINT SmIpTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmIpTableDlgInit(HWND hWnd, SM_TABLE *s);
+void SmIpTableDlgUpdate(HWND hWnd, SM_TABLE *s);
+void SmIpTableDlgRefresh(HWND hWnd, SM_TABLE *s);
+bool SmCreateCert(HWND hWnd, X **x, K **k, bool do_not_save, char *default_cn, bool root_only);
+UINT SmCreateCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmCreateCertDlgInit(HWND hWnd, SM_CERT *s);
+void SmCreateCertDlgUpdate(HWND hWnd, SM_CERT *s);
+void SmCreateCertDlgOnOk(HWND hWnd, SM_CERT *s);
+UINT SmSNATDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSNATDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmBridgeDlg(HWND hWnd, SM_SERVER *s);
+void SmInstallWinPcap(HWND hWnd, SM_SERVER *s);
+UINT SmBridgeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+UINT SmBridgeDlgInit(HWND hWnd, SM_SERVER *s);
+void SmBridgeDlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmBridgeDlgRefresh(HWND hWnd, SM_SERVER *s);
+void SmBridgeDlgOnOk(HWND hWnd, SM_SERVER *s);
+void SmAddServerCaps(LVB *b, CAPSLIST *t);
+void SmConfig(HWND hWnd, SM_SERVER *s);
+UINT SmConfigDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmConfigDlgInit(HWND hWnd, SM_CONFIG *c);
+void SmHubAdminOption(HWND hWnd, SM_EDIT_HUB *e);
+void SmHubExtOption(HWND hWnd, SM_EDIT_HUB *e);
+UINT SmHubAdminOptionDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubAdminOptionDlgUpdate(HWND hWnd, SM_EDIT_AO *a);
+void SmHubAdminOptionDlgInit(HWND hWnd, SM_EDIT_AO *a);
+void SmHubAdminOptionDlgOk(HWND hWnd, SM_EDIT_AO *a);
+UINT SmHubAdminOptionValueDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubAdminOptionValueDlgUpdate(HWND hWnd, SM_EDIT_AO *a);
+void SmL3(HWND hWnd, SM_SERVER *s);
+UINT SmL3Dlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmL3DlgInit(HWND hWnd, SM_SERVER *s);
+void SmL3DlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmL3DlgRefresh(HWND hWnd, SM_SERVER *s);
+UINT SmL3AddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmL3AddDlgUpdate(HWND hWnd, SM_SERVER *s);
+UINT SmL3SwDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmL3SwDlgInit(HWND hWnd, SM_L3SW *w);
+void SmL3SwDlgUpdate(HWND hWnd, SM_L3SW *w);
+void SmL3SwDlgRefresh(HWND hWnd, SM_L3SW *w);
+UINT SmL3SwIfDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmL3SwIfDlgInit(HWND hWnd, SM_L3SW *w);
+void SmL3SwIfDlgUpdate(HWND hWnd, SM_L3SW *w);
+UINT SmL3SwTableDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmL3SwTableDlgInit(HWND hWnd, SM_L3SW *w);
+void SmL3SwTableDlgUpdate(HWND hWnd, SM_L3SW *w);
+bool SmL3IsSwActive(SM_SERVER *s, char *name);
+UINT SmGetCurrentSecureId(HWND hWnd);
+UINT SmGetCurrentSecureIdFromReg();
+UINT SmSelectSecureId(HWND hWnd);
+void SmWriteSelectSecureIdReg(UINT id);
+bool SmSelectKeyPair(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size);
+bool SmSelectKeyPairEx(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size, UINT bitmap_id);
+UINT SmSelectKeyPairDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSelectKeyPairDlgInit(HWND hWnd, SM_SECURE_KEYPAIR *k);
+void SmSelectKeyPairDlgUpdate(HWND hWnd, SM_SECURE_KEYPAIR *k);
+void SmSelectKeyPairDlgRefresh(HWND hWnd, SM_SECURE_KEYPAIR *k);
+void SmSecureManager(HWND hWnd);
+UINT SmCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmCrlDlgInit(HWND hWnd, SM_HUB *s);
+void SmCrlDlgUpdate(HWND hWnd, SM_HUB *s);
+void SmCrlDlgRefresh(HWND hWnd, SM_HUB *s);
+UINT SmEditCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEditCrlDlgInit(HWND hWnd, SM_EDIT_CRL *c);
+void SmEditCrlDlgUpdate(HWND hWnd, SM_EDIT_CRL *c);
+void SmEditCrlDlgOnOk(HWND hWnd, SM_EDIT_CRL *c);
+void SmEditCrlDlgOnLoad(HWND hWnd, SM_EDIT_CRL *c);
+void SmEditCrlDlgSetName(HWND hWnd, NAME *name);
+void SmEditCrlDlgSetSerial(HWND hWnd, X_SERIAL *serial);
+void SmEditCrlDlgSetHash(HWND hWnd, UCHAR *hash_md5, UCHAR *hash_sha1);
+void SmHubAc(HWND hWnd, SM_EDIT_HUB *s);
+UINT SmHubAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubAcDlgInit(HWND hWnd, SM_EDIT_AC_LIST *p);
+void SmHubAcDlgUpdate(HWND hWnd, SM_EDIT_AC_LIST *p);
+void SmHubAcDlgRefresh(HWND hWnd, SM_EDIT_AC_LIST *p);
+UINT SmHubEditAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubEditAcDlgInit(HWND hWnd, SM_EDIT_AC *p);
+void SmHubEditAcDlgUpdate(HWND hWnd, SM_EDIT_AC *p);
+void SmHubEditAcDlgOnOk(HWND hWnd, SM_EDIT_AC *p);
+UINT SmLogFileDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLogFileDlgInit(HWND hWnd, SM_SERVER *p);
+void SmLogFileDlgRefresh(HWND hWnd, SM_SERVER *p);
+void SmLogFileDlgUpdate(HWND hWnd, SM_SERVER *p);
+void SmLogFileStartDownload(HWND hWnd, SM_SERVER *s, char *server_name, char *filepath, UINT totalsize);
+UINT SmReadLogFile(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool SmReadLogFileProc(DOWNLOAD_PROGRESS *g);
+UINT SmSaveLogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLicense(HWND hWnd, SM_SERVER *s);
+UINT SmLicenseDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLicenseDlgInit(HWND hWnd, SM_SERVER *s);
+void SmLicenseDlgRefresh(HWND hWnd, SM_SERVER *s);
+void SmLicenseDlgUpdate(HWND hWnd, SM_SERVER *s);
+bool SmLicenseAdd(HWND hWnd, SM_SERVER *s);
+UINT SmLicenseAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmLicenseAddDlgInit(HWND hWnd, SM_SERVER *s);
+void SmLicenseAddDlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmLicenseAddDlgShiftTextItem(HWND hWnd, UINT id1, UINT id2, UINT *next_focus);
+void SmLicenseAddDlgGetText(HWND hWnd, char *str, UINT size);
+void SmLicenseAddDlgOnOk(HWND hWnd, SM_SERVER *s);
+bool SmSetup(HWND hWnd, SM_SERVER *s);
+UINT SmSetupDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSetupDlgInit(HWND hWnd, SM_SETUP *s);
+void SmSetupDlgUpdate(HWND hWnd, SM_SETUP *s);
+void SmSetupDlgOnOk(HWND hWnd, SM_SETUP *s);
+UINT SmSetupHubDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSetupHubDlgUpdate(HWND hWnd, SM_SETUP *s);
+bool SmSetupInit(HWND hWnd, SM_SETUP *s);
+bool SmSetupDeleteAllHub(HWND hWnd, SM_SETUP *s);
+bool SmSetupDeleteAllLocalBridge(HWND hWnd, SM_SETUP *s);
+bool SmSetupDeleteAllLayer3(HWND hWnd, SM_SETUP *s);
+bool SmSetupDeleteAllObjectInBridgeHub(HWND hWnd, SM_SETUP *s);
+void SmSetupStep(HWND hWnd, SM_SETUP *s);
+UINT SmSetupStepDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSetupStepDlgInit(HWND hWnd, SM_SETUP *s);
+void SmSetupOnClose(HWND hWnd, SM_SETUP *s);
+bool SmSetupIsNew(SM_SERVER *s);
+void SmVLan(HWND hWnd, SM_SERVER *s);
+UINT SmVLanDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmVLanDlgInit(HWND hWnd, SM_SERVER *s);
+void SmVLanDlgRefresh(HWND hWnd, SM_SERVER *s);
+void SmVLanDlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmHubMsg(HWND hWnd, SM_EDIT_HUB *s);
+UINT SmHubMsgDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmHubMsgDlgInit(HWND hWnd, SM_EDIT_HUB *s);
+void SmHubMsgDlgUpdate(HWND hWnd, SM_EDIT_HUB *s);
+void SmHubMsgDlgOnOk(HWND hWnd, SM_EDIT_HUB *s);
+void SmIPsec(HWND hWnd, SM_SERVER *s);
+UINT SmIPsecDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmIPsecDlgInit(HWND hWnd, SM_SERVER *s);
+void SmIPsecDlgOnOk(HWND hWnd, SM_SERVER *s);
+void SmIPsecDlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmIPsecDlgGetSetting(HWND hWnd, IPSEC_SERVICES *sl);
+void SmEtherIp(HWND hWnd, SM_SERVER *s);
+UINT SmEtherIpDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEtherIpDlgInit(HWND hWnd, SM_SERVER *s);
+void SmEtherIpDlgRefresh(HWND hWnd, SM_SERVER *s);
+void SmEtherIpDlgUpdate(HWND hWnd, SM_SERVER *s);
+bool SmEtherIpId(HWND hWnd, SM_ETHERIP_ID *t);
+UINT SmEtherIpIdDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmEtherIpIdDlgInit(HWND hWnd, SM_ETHERIP_ID *t);
+void SmEtherIpIdDlgOnOk(HWND hWnd, SM_ETHERIP_ID *t);
+void SmEtherIpIdDlgUpdate(HWND hWnd, SM_ETHERIP_ID *t);
+void SmEtherIpIdDlgGetSetting(HWND hWnd, SM_ETHERIP_ID *t);
+bool SmDDns(HWND hWnd, SM_SERVER *s, bool silent, bool no_change_cert);
+UINT SmDDnsDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmDDnsDlgInit(HWND hWnd, SM_DDNS *d);
+void SmDDnsRefresh(HWND hWnd, SM_DDNS *d);
+void SmDDnsDlgOnOk(HWND hWnd, SM_DDNS *d);
+void SmDDnsDlgUpdate(HWND hWnd, SM_DDNS *d);
+void SmOpenVpn(HWND hWnd, SM_SERVER *s);
+UINT SmOpenVpnDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmOpenVpnDlgInit(HWND hWnd, SM_SERVER *s);
+void SmOpenVpnDlgOnOk(HWND hWnd, SM_SERVER *s, bool no_close);
+void SmOpenVpnDlgUpdate(HWND hWnd, SM_SERVER *s);
+void SmOpenVpn(HWND hWnd, SM_SERVER *s);
+void SmSpecialListener(HWND hWnd, SM_SERVER *s);
+UINT SmSpecialListenerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmSpecialListenerDlgInit(HWND hWnd, SM_SERVER *s);
+void SmSpecialListenerDlgOnOk(HWND hWnd, SM_SERVER *s);
+void SmShowIPSecMessageIfNecessary(HWND hWnd, SM_SERVER *p);
+UINT SmVmBridgeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmAzure(HWND hWnd, SM_SERVER *s, bool on_setup);
+UINT SmAzureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmAzureDlgOnInit(HWND hWnd, SM_AZURE *a);
+void SmAzureDlgRefresh(HWND hWnd, SM_AZURE *a);
+void SmAzureSetStatus(HWND hWnd, SM_AZURE *a);
+bool SmProxy(HWND hWnd, INTERNET_SETTING *t);
+UINT SmProxyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void SmProxyDlgInit(HWND hWnd, INTERNET_SETTING *t);
+void SmProxyDlgUpdate(HWND hWnd, INTERNET_SETTING *t);
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SW.c b/src/Cedar/SW.c
new file mode 100644
index 00000000..19ed156c
--- /dev/null
+++ b/src/Cedar/SW.c
@@ -0,0 +1,6569 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SW.c
+// Setup Wizard for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define SM_C
+#define CM_C
+#define NM_C
+#define SW_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "CMInner.h"
+#include "SMInner.h"
+#include "NMInner.h"
+#include "EMInner.h"
+#include "SWInner.h"
+#include "../PenCore/resource.h"
+
+//// Old MSI product information
+// VPN Server
+static SW_OLD_MSI old_msi_vpnserver[] =
+{
+ {"{B5B58F8A-D56C-4f3e-B400-235A6E007101}", "{1BDA6B01-2DB3-478c-AA5B-E973A7DC49A4}"},
+ {"{124DDAE2-B9AF-4541-B3EF-B169D9007101}", "{BCDE5CF2-7413-47d0-92E1-F6F2189D8E60}"},
+};
+static SW_OLD_MSI old_msi_vpnclient[] =
+{
+ {"{54864EDD-4FC6-4269-AA17-3E7C13607101}", "{13ED64E0-532D-4ff0-A3A0-5D700C73259E}"},
+ {"{8A215EB7-C5F2-4193-9D7D-1017F1007101}", "{AD593FE5-759E-46c6-9355-29031A8C7D44}"},
+};
+static SW_OLD_MSI old_msi_vpnbridge[] =
+{
+ {"{58CE8E96-1234-499D-CAFE-3E62261DF211}", "{211FA6A7-1234-4985-CAFE-3DD3E3151E7E}"},
+};
+
+// List of file names needed to SFX
+static char *sfx_vpn_server_bridge_files[] =
+{
+ "vpnsetup.exe",
+ "vpnserver.exe",
+ "vpnserver_x64.exe",
+ "vpnbridge.exe",
+ "vpnbridge_x64.exe",
+ "vpnsmgr.exe",
+ "vpnsmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+};
+static char *sfx_vpn_client_files[] =
+{
+ "vpnsetup.exe",
+ "vpnclient.exe",
+ "vpnclient_x64.exe",
+ "vpncmgr.exe",
+ "vpncmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "vpninstall.exe",
+ "vpnweb.cab",
+ "hamcore.se2",
+};
+
+// Global variables to be used out of necessity
+static bool g_stop_flag = false;
+static HANDLE g_wait_process_handle = NULL;
+
+
+// SFX generation main
+bool SwGenSfxModeMain(char *mode, wchar_t *dst)
+{
+ LIST *o;
+ bool ret = false;
+ // Validate arguments
+ if (mode == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ o = SwNewSfxFileList();
+
+ if (SwAddBasicFilesToList(o, mode))
+ {
+ if (SwCompileSfx(o, dst))
+ {
+ ret = true;
+ }
+ }
+
+ SwFreeSfxFileList(o);
+
+ return ret;
+}
+
+// Compile the SFX files
+bool SwCompileSfx(LIST *o, wchar_t *dst_filename)
+{
+ bool ret = false;
+ wchar_t exe_filename[MAX_PATH];
+ HINSTANCE hKernel32 = LoadLibraryA("kernel32.dll");
+ HANDLE (WINAPI *_BeginUpdateResourceW)(LPCWSTR, BOOL) = NULL;
+ BOOL (WINAPI *_UpdateResourceA)(HANDLE, LPCSTR, LPCSTR, WORD, LPVOID, DWORD) = NULL;
+ BOOL (WINAPI *_EndUpdateResourceW)(HANDLE, BOOL) = NULL;
+ // Validate arguments
+ if (o == NULL || dst_filename == NULL || hKernel32 == NULL)
+ {
+ return false;
+ }
+
+ // Get the API related to the resource editing
+ _BeginUpdateResourceW = (HANDLE (__stdcall *)(LPCWSTR,UINT))GetProcAddress(hKernel32, "BeginUpdateResourceW");
+ _UpdateResourceA = (UINT (__stdcall *)(HANDLE,LPCSTR,LPCSTR,WORD,LPVOID,DWORD))GetProcAddress(hKernel32, "UpdateResourceA");
+ _EndUpdateResourceW = (UINT (__stdcall *)(HANDLE,UINT))GetProcAddress(hKernel32, "EndUpdateResourceW");
+
+ if (_BeginUpdateResourceW != NULL && _UpdateResourceA != NULL && _EndUpdateResourceW != NULL)
+ {
+ // Generate the setup.exe file in the Temp directory
+ ConbinePathW(exe_filename, sizeof(exe_filename), MsGetMyTempDirW(), L"setup.exe");
+ if (FileCopyW(L"|vpnsetup_nosign.exe", exe_filename))
+ {
+ // Resource updating start
+ HANDLE h = _BeginUpdateResourceW(exe_filename, false);
+
+ if (h != NULL)
+ {
+ UINT i;
+ bool ok = true;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SW_SFX_FILE *f = LIST_DATA(o, i);
+ BUF *b;
+
+ // Read the original file
+ b = ReadDumpW(f->DiskFileName);
+ if (b != NULL)
+ {
+ // Add resources
+ char inner_name[MAX_PATH];
+ BUF *b2;
+ StrCpy(inner_name, sizeof(inner_name), f->InnerFileName);
+ StrUpper(inner_name);
+
+ if (StrCmpi(inner_name, "hamcore.se2") == 0)
+ {
+ // Not to re-compress the hamcore.se2 because they are already compressed
+ // Prepend "raw_" to file name
+ Format(inner_name, sizeof(inner_name), "raw_%s", f->InnerFileName);
+ StrUpper(inner_name);
+ }
+ else
+ {
+ // Compress
+ b2 = CompressBuf(b);
+ FreeBuf(b);
+ b = b2;
+ }
+
+
+ if (_UpdateResourceA(h, SW_SFX_RESOURCE_TYPE, inner_name, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+ b->Buf, b->Size) == false)
+ {
+ ok = false;
+ }
+
+ FreeBuf(b);
+ }
+
+ if (ok == false)
+ {
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ // Success to add all resources
+ if (_EndUpdateResourceW(h, false))
+ {
+ h = NULL;
+
+ // File Copy
+ if (FileCopyW(exe_filename, dst_filename))
+ {
+ // All succeed
+ ret = true;
+ }
+ }
+ }
+
+ if (ret == false)
+ {
+ // Failed to add resource
+ if (h != NULL)
+ {
+ _EndUpdateResourceW(h, true);
+ h = NULL;
+ }
+ }
+
+ FileDeleteW(exe_filename);
+ }
+ }
+ }
+
+ FreeLibrary(hKernel32);
+
+ return ret;
+}
+
+// Create new item in the SFX compression list
+SW_SFX_FILE *SwNewSfxFile(char *inner_file_name, wchar_t *disk_file_name)
+{
+ SW_SFX_FILE *f = ZeroMalloc(sizeof(SW_SFX_FILE));
+
+ StrCpy(f->InnerFileName, sizeof(f->InnerFileName), inner_file_name);
+ UniStrCpy(f->DiskFileName, sizeof(f->DiskFileName), disk_file_name);
+
+ return f;
+}
+
+// Add the basically required files for the components to SFX compressed files list
+bool SwAddBasicFilesToList(LIST *o, char *component_name)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || component_name == NULL)
+ {
+ return false;
+ }
+
+ if (StrCmpi(component_name, "vpnserver_vpnbridge") == 0)
+ {
+ // VPN Server & VPN Bridge
+ for (i = 0; i < (sizeof(sfx_vpn_server_bridge_files) / sizeof(char *)); i++)
+ {
+ char *name = sfx_vpn_server_bridge_files[i];
+ wchar_t name_w[MAX_PATH];
+ wchar_t src_file_name[MAX_PATH];
+
+ StrToUni(name_w, sizeof(name_w), name);
+ ConbinePathW(src_file_name, sizeof(src_file_name), MsGetExeFileDirW(), name_w);
+
+ Add(o, SwNewSfxFile(name, src_file_name));
+ }
+ }
+ else if (StrCmpi(component_name, "vpnclient") == 0)
+ {
+ // VPN Client
+ for (i = 0; i < (sizeof(sfx_vpn_client_files) / sizeof(char *)); i++)
+ {
+ char *name = sfx_vpn_client_files[i];
+ wchar_t name_w[MAX_PATH];
+ wchar_t src_file_name[MAX_PATH];
+
+ StrToUni(name_w, sizeof(name_w), name);
+ ConbinePathW(src_file_name, sizeof(src_file_name), MsGetExeFileDirW(), name_w);
+
+ Add(o, SwNewSfxFile(name, src_file_name));
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ Add(o, SwNewSfxFile("install_src.dat", L"|install_src.dat"));
+
+ return true;
+}
+
+// Release the SFX file list
+void SwFreeSfxFileList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SW_SFX_FILE *f = LIST_DATA(o, i);
+
+ Free(f);
+ }
+
+ ReleaseList(o);
+}
+
+// Generate the SFX file list
+LIST *SwNewSfxFileList()
+{
+ LIST *o = NewListFast(NULL);
+
+ return o;
+}
+
+// Extract from the SFX files
+bool SwSfxExtractFile(HWND hWnd, void *data, UINT size, wchar_t *dst, bool compressed)
+{
+ IO *io;
+ bool ret = false;
+ // Validate arguments
+ if (data == NULL || size == 0 || dst == NULL)
+ {
+ return false;
+ }
+
+ io = FileCreateW(dst);
+
+ if (compressed == false)
+ {
+ // Write uncompressed files as is
+ ret = FileWrite(io, data, size);
+ }
+ else
+ {
+ // Unzip when the files are compressed
+ BUF *src = NewBuf();
+ BUF *dst;
+
+ WriteBuf(src, data, size);
+
+ dst = UncompressBuf(src);
+
+ FreeBuf(src);
+
+ ret = FileWrite(io, dst->Buf, dst->Size);
+
+ FreeBuf(dst);
+ }
+
+ FileClose(io);
+
+ if (ret == false)
+ {
+ FileDeleteW(dst);
+ }
+
+ return ret;
+}
+
+// SFX extraction process
+bool SwSfxExtractProcess(HWND hWnd, bool *hide_error_msg)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ bool ret = true;
+ wchar_t exec_filename[MAX_SIZE];
+ bool is_easy_installer = false;
+ bool dummy_bool = false;
+
+ if (hide_error_msg == NULL)
+ {
+ hide_error_msg = &dummy_bool;
+ }
+
+ *hide_error_msg = false;
+
+ Zero(exec_filename, sizeof(exec_filename));
+
+ // Enumerate the DATAFILE resources
+ t = MsEnumResources(NULL, SW_SFX_RESOURCE_TYPE);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *resource_name = t->Token[i];
+ char filename[MAX_PATH];
+ wchar_t filename_w[MAX_PATH];
+ wchar_t tmp_filename[MAX_PATH];
+ HRSRC hr;
+ bool ok = false;
+ bool is_compressed = true;
+
+ DoEvents(hWnd);
+
+ if (g_stop_flag)
+ {
+ // User cancel
+ ret = false;
+ break;
+ }
+
+ StrCpy(filename, sizeof(filename), resource_name);
+
+ StrLower(filename);
+
+ if (EndWith(filename, ".vpn"))
+ {
+ is_easy_installer = true;
+ }
+
+ if (StartWith(filename, "raw_"))
+ {
+ StrToUni(filename_w, sizeof(filename_w), filename + 4);
+ is_compressed = false;
+ }
+ else
+ {
+ StrToUni(filename_w, sizeof(filename_w), filename);
+ }
+
+ ConbinePathW(tmp_filename, sizeof(tmp_filename), MsGetMyTempDirW(), filename_w);
+
+ if (EndWith(filename, "vpnsetup.exe"))
+ {
+ UniStrCpy(exec_filename, sizeof(exec_filename), tmp_filename);
+ }
+
+ // Find the resources
+ hr = FindResourceA(MsGetCurrentModuleHandle(), resource_name, SW_SFX_RESOURCE_TYPE);
+ if (hr != NULL)
+ {
+ HGLOBAL hg = LoadResource(MsGetCurrentModuleHandle(), hr);
+
+ if (hg != NULL)
+ {
+ UINT size = SizeofResource(MsGetCurrentModuleHandle(), hr);
+ void *ptr = LockResource(hg);
+
+ if (size != 0 && ptr != NULL)
+ {
+ if (SwSfxExtractFile(hWnd, ptr, size, tmp_filename, is_compressed))
+ {
+ ok = true;
+ }
+ }
+ }
+ }
+
+ DoEvents(hWnd);
+
+ if (ok == false)
+ {
+ // Failure
+ ret = false;
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ if (ret)
+ {
+ wchar_t exe_name[MAX_PATH];
+ wchar_t *exe_dir = MsGetExeFileDirW();
+
+ GetFileNameFromFilePathW(exe_name, sizeof(exe_name), MsGetExeFileNameW());
+
+ }
+
+ if (ret)
+ {
+ // Start the vpnsetup.exe
+ if (UniIsEmptyStr(exec_filename))
+ {
+ ret = false;
+ }
+ else
+ {
+ void *handle = NULL;
+ wchar_t params[MAX_SIZE];
+ wchar_t *current_params = GetCommandLineUniStr();
+ wchar_t tmp[MAX_SIZE];
+ char *last_lang;
+ wchar_t copy_of_me[MAX_PATH];
+
+ UniStrCpy(params, sizeof(params), current_params);
+
+ // Copy itself to the Temp directory
+ CombinePathW(copy_of_me, sizeof(copy_of_me), MsGetMyTempDirW(), L"installer.cache");
+ if (FileCopyW(MsGetExeFileNameW(), copy_of_me) == false)
+ {
+ Zero(copy_of_me, sizeof(copy_of_me));
+ }
+
+ // Add a path of this own
+ UniFormat(tmp, sizeof(tmp), L" /CALLERSFXPATH:\"%s\"", copy_of_me);
+ UniStrCat(params, sizeof(params), tmp);
+
+ // Add information of whether it's a simple installer
+ UniFormat(tmp, sizeof(tmp), L" /ISEASYINSTALLER:%u", is_easy_installer);
+ UniStrCat(params, sizeof(params), tmp);
+
+ UniTrim(params);
+
+ // Specify a language by the lang.config
+ last_lang = MsRegReadStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last User Language", false, true);
+ if (IsEmptyStr(last_lang) == false)
+ {
+ wchar_t lang_filename[MAX_PATH];
+ BUF *buf;
+
+ CombinePathW(lang_filename, sizeof(lang_filename), MsGetMyTempDirW(), L"lang.config");
+
+ buf = NewBuf();
+ WriteBufLine(buf, "");
+ WriteBufLine(buf, last_lang);
+ WriteBufLine(buf, "");
+ DumpBufW(buf, lang_filename);
+ FreeBuf(buf);
+ }
+ Free(last_lang);
+
+ if (MsExecuteEx2W(exec_filename, params, &handle, false) == false)
+ {
+ ret = false;
+ }
+ else
+ {
+ g_wait_process_handle = handle;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Copy the files of VPN Gate
+bool SwSfxCopyVgFiles(HWND hWnd, wchar_t *src, wchar_t *dst)
+{
+ wchar_t *msg;
+ wchar_t srcfilename[MAX_PATH];
+ wchar_t exefilename[MAX_PATH];
+
+ GetFileNameFromFilePathW(srcfilename, sizeof(srcfilename), src);
+ GetFileNameFromFilePathW(exefilename, sizeof(exefilename), MsGetExeFileNameW());
+
+ if (FileCopyW(src, dst))
+ {
+ return true;
+ }
+
+ msg = L"The file \"%s\" was not found on the directory which the installer \"%s\" is located on.\r\n\r\n"
+ L"To continue the installation, the file \"%s\" is required on the same direcotry.\r\n"
+ L"If you have extracted the installer from a ZIP archive, you have to also extract the file \"%s\" from the ZIP archive together.";
+
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, msg, srcfilename, exefilename, srcfilename, srcfilename);
+
+ return false;
+}
+
+// SFX extraction dialog procedure
+bool CALLBACK SfxModeMainDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ UINT ret;
+ bool hide_msg = false;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetTimer(hWnd, 1, 500, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ ret = SW_EXIT_CODE_USER_CANCEL;
+ if (SwSfxExtractProcess(hWnd, &hide_msg))
+ {
+ ret = 0;
+ }
+ else
+ {
+ if (g_stop_flag == false)
+ {
+ if (hide_msg == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, L"Fatal Error: Self extracting files to the temporary directory was failed.\r\n\r\n"
+ L"Please try again after reboot Windows.");
+ }
+ }
+ }
+
+ EndDialog(hWnd, ret);
+
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ g_stop_flag = true;
+ Disable(hWnd, IDCANCEL);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ break;
+ }
+
+ return false;
+}
+
+// Main process as SFX mode
+UINT SwSfxModeMain()
+{
+ UINT ret;
+ // Select either English or Japanese
+ UINT dialog_id = (MsIsCurrentUserLocaleIdJapanese() ? 10001 : 10002);
+
+ g_wait_process_handle = NULL;
+ g_stop_flag = false;
+
+ // Show the screen
+ ret = (UINT)DialogBoxParamA(MsGetCurrentModuleHandle(), MAKEINTRESOURCEA(dialog_id), NULL, (DLGPROC)SfxModeMainDialogProc, 0);
+
+ if (g_wait_process_handle != NULL)
+ {
+ // If this have started the vpnsetup.exe, wait for termination of the child process
+ ret = MsWaitProcessExit(g_wait_process_handle);
+ }
+
+ return ret;
+}
+
+// Resource name enumeration procedure
+bool CALLBACK SwEnumResourceNamesProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam)
+{
+ bool *b = (bool *)lParam;
+ // Validate arguments
+ if (type == NULL || name == NULL || lParam == 0)
+ {
+ return false;
+ }
+
+ *b = true;
+
+ return true;
+}
+
+// Main process of vpnsetup.exe
+UINT SWExec()
+{
+ UINT ret = 0;
+ bool is_datafile_exists = false;
+
+ // Examine whether DATAFILE resources are stored in setup.exe that is currently running
+ EnumResourceNamesA(NULL, SW_SFX_RESOURCE_TYPE, SwEnumResourceNamesProc, (LONG_PTR)(&is_datafile_exists));
+
+ if (is_datafile_exists)
+ {
+ // If DATAFILE resources are stored, extract it as SFX
+ MayaquaMinimalMode();
+ }
+
+ InitMayaqua(false, false, 0, NULL);
+ InitCedar();
+
+ if (is_datafile_exists == false)
+ {
+ // Start the Setup Wizard
+ ret = SWExecMain();
+ }
+ else
+ {
+ // SFX mode
+ ret = SwSfxModeMain();
+ }
+
+ FreeCedar();
+ FreeMayaqua();
+
+ return ret;
+}
+
+// Dialog procedure (for copy and paste)
+UINT SwDefaultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, true, true, false);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Update the file specification dialog
+void SwWeb2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard_page == NULL || wizard == NULL)
+ {
+ return;
+ }
+
+ if (IsEmptyUniStr(sw->Web_OutFile) || IsEmptyUniStr(sw->Web_SettingFile))
+ {
+ ok = false;
+ }
+
+ SetText(hWnd, E_SETTING, sw->Web_SettingFile);
+ SetText(hWnd, E_OUT, sw->Web_OutFile);
+
+ SetWizardButton(wizard_page, ok, true, true, false);
+}
+
+// Update the file specification dialog
+void SwEasy2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page)
+{
+ bool ok = true;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard_page == NULL || wizard == NULL)
+ {
+ return;
+ }
+
+ if (IsEmptyUniStr(sw->Easy_OutFile) || IsEmptyUniStr(sw->Easy_SettingFile))
+ {
+ ok = false;
+ }
+
+ SetText(hWnd, E_SETTING, sw->Easy_SettingFile);
+ SetText(hWnd, E_OUT, sw->Easy_OutFile);
+
+ SetWizardButton(wizard_page, ok, true, true, false);
+}
+
+// Generate a SFX file name of the default
+void SwGenerateDefaultSfxFileName(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ UniFormat(name, size, L"easy-" GC_SW_SOFTETHER_PREFIX_W L"vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.exe",
+ CEDAR_VER / 100,
+ CEDAR_VER % 100,
+ CEDAR_BUILD,
+ BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D);
+}
+
+// Generate a ZIP file name of the default
+void SwGenerateDefaultZipFileName(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ UniFormat(name, size, L"web-" GC_SW_SOFTETHER_PREFIX_W L"vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.zip",
+ CEDAR_VER / 100,
+ CEDAR_VER % 100,
+ CEDAR_BUILD,
+ BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D);
+}
+
+// Specify a file
+UINT SwEasy2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ wchar_t *fn;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ DlgFont(hWnd, S_BOLD1, 10, true);
+ DlgFont(hWnd, S_BOLD2, 10, true);
+
+ Check(hWnd, B_DELETE_SENSITIVE, sw->Easy_EraseSensitive);
+ Check(hWnd, B_EASYMODE, sw->Easy_EasyMode);
+
+ break;
+
+ case WM_WIZ_SHOW:
+ SwEasy2Update(hWnd, sw, wizard, wizard_page);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ // Save the Settings
+ MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EraseSensitive", sw->Easy_EraseSensitive);
+ MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EasyMode", sw->Easy_EasyMode);
+ return D_SW_PERFORM;
+
+ case WM_WIZ_BACK:
+ return D_SW_EASY1;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_DELETE_SENSITIVE:
+ sw->Easy_EraseSensitive = IsChecked(hWnd, B_DELETE_SENSITIVE);
+ sw->Easy_EasyMode = IsChecked(hWnd, B_EASYMODE);
+ break;
+
+ case B_BROWSE_SETTING:
+ fn = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE"));
+
+ if (fn != NULL)
+ {
+ // Parse
+ if (CiTryToParseAccountFile(fn) == false)
+ {
+ // Failure
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED"));
+ }
+ else
+ {
+ // Success
+ UniStrCpy(sw->Easy_SettingFile, sizeof(sw->Easy_SettingFile), fn);
+
+ SwEasy2Update(hWnd, sw, wizard, wizard_page);
+
+ FocusEx(hWnd, E_SETTING);
+ }
+
+ Free(fn);
+ }
+ break;
+
+ case B_BROWSE_OUT:
+ SwGenerateDefaultSfxFileName(tmp, sizeof(tmp));
+
+ fn = SaveDlg(hWnd, _UU("SW_EXE_FILTER"), _UU("DLG_SAVE_FILE"), tmp, L".exe");
+
+ if (fn != NULL)
+ {
+ UniStrCpy(sw->Easy_OutFile, sizeof(sw->Easy_OutFile), fn);
+
+ SwEasy2Update(hWnd, sw, wizard, wizard_page);
+ }
+ break;
+
+ case B_HINT:
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Specify a file
+UINT SwWeb2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ wchar_t *fn;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ DlgFont(hWnd, S_BOLD1, 10, true);
+ DlgFont(hWnd, S_BOLD2, 10, true);
+
+ Check(hWnd, B_DELETE_SENSITIVE, sw->Web_EraseSensitive);
+ Check(hWnd, B_EASYMODE, sw->Web_EasyMode);
+
+ break;
+
+ case WM_WIZ_SHOW:
+ SwWeb2Update(hWnd, sw, wizard, wizard_page);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ // Save the settings
+ MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EraseSensitive", sw->Web_EraseSensitive);
+ MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EasyMode", sw->Web_EasyMode);
+ return D_SW_PERFORM;
+
+ case WM_WIZ_BACK:
+ return D_SW_WEB1;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_DELETE_SENSITIVE:
+ sw->Web_EraseSensitive = IsChecked(hWnd, B_DELETE_SENSITIVE);
+ sw->Web_EasyMode = IsChecked(hWnd, B_EASYMODE);
+ break;
+
+ case B_BROWSE_SETTING:
+ fn = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE"));
+
+ if (fn != NULL)
+ {
+ // Parse
+ if (CiTryToParseAccountFile(fn) == false)
+ {
+ // Failure
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED"));
+ }
+ else
+ {
+ // Success
+ UniStrCpy(sw->Web_SettingFile, sizeof(sw->Web_SettingFile), fn);
+
+ SwWeb2Update(hWnd, sw, wizard, wizard_page);
+
+ FocusEx(hWnd, E_SETTING);
+ }
+
+ Free(fn);
+ }
+ break;
+
+ case B_BROWSE_OUT:
+ SwGenerateDefaultZipFileName(tmp, sizeof(tmp));
+
+ fn = SaveDlg(hWnd, _UU("DLG_ZIP_FILER"), _UU("DLG_SAVE_FILE"), tmp, L".zip");
+
+ if (fn != NULL)
+ {
+ UniStrCpy(sw->Web_OutFile, sizeof(sw->Web_OutFile), fn);
+
+ SwWeb2Update(hWnd, sw, wizard, wizard_page);
+ }
+ break;
+
+ case B_HINT:
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Start screen of the Web Installer Creation Wizard
+UINT SwWeb1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ wizard->CloseConfirmMsg = NULL;
+ DlgFont(hWnd, S_TITLE, 11, true);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, false, true, false);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ return D_SW_WEB2;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Start screen of the Simple installer creation wizard
+UINT SwEasy1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ wizard->CloseConfirmMsg = NULL;
+ DlgFont(hWnd, S_TITLE, 11, true);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, false, true, false);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ return D_SW_EASY2;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Get the icon for the language
+UINT SwGetLangIcon(char *name)
+{
+ UINT ret = ICO_NULL;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return ICO_NULL;
+ }
+
+ if (StrCmpi(name, "ja") == 0)
+ {
+ ret = ICO_LANG_JAPANESE;
+ }
+ else if (StrCmpi(name, "en") == 0)
+ {
+ ret = ICO_LANG_ENGLISH;
+ }
+ else if (StrCmpi(name, "cn") == 0)
+ {
+ ret = ICO_LANG_CHINESE;
+ }
+
+ return ret;
+}
+
+// Initialize the language list
+void SwLang1Init(HWND hWnd, SW *sw)
+{
+ LVB *b;
+ UINT i;
+ SW_COMPONENT *default_select = NULL;
+ LIST *o;
+ UINT current_lang = GetCurrentLangId();
+ UINT select_index = INFINITE;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return;
+ }
+
+ o = LoadLangList();
+
+ LvReset(hWnd, L_LIST);
+
+ b = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *t = LIST_DATA(o, i);
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), L"(%s)", t->TitleLocal);
+ UniFormat(tmp2, sizeof(tmp2), L" %s", t->TitleEnglish);
+
+ LvInsertAdd(b, SwGetLangIcon(t->Name), (void *)(t->Id + 1), 2, tmp2, tmp);
+
+ if (t->Id == current_lang)
+ {
+ select_index = i;
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ if (sw->CurrentComponent == NULL)
+ {
+ LvSelectByParam(hWnd, L_LIST, default_select);
+ }
+ else
+ {
+ LvSelectByParam(hWnd, L_LIST, sw->CurrentComponent);
+ }
+
+ LvAutoSize(hWnd, L_LIST);
+
+ FreeLangList(o);
+
+ if (select_index != INFINITE)
+ {
+ LvSelect(hWnd, L_LIST, select_index);
+ }
+
+ LvSort(hWnd, L_LIST, 0, false);
+
+ Focus(hWnd, L_LIST);
+
+ // Show the current language
+ if (true)
+ {
+ LANGLIST t;
+ wchar_t tmp[MAX_SIZE];
+
+ Zero(&t, sizeof(t));
+ GetCurrentLang(&t);
+
+ UniFormat(tmp, sizeof(tmp), L"%s (%s)", t.TitleEnglish, t.TitleLocal);
+
+ SetText(hWnd, E_CURRENT, tmp);
+
+ if (MsIsVista())
+ {
+ SetFont(hWnd, E_CURRENT, GetMeiryoFontEx(11));
+ }
+ else
+ {
+ DlgFont(hWnd, E_CURRENT, 11, false);
+ }
+ }
+}
+
+// Update of control
+void SwLang1Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page)
+{
+ UINT id;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL)
+ {
+ return;
+ }
+
+ id = (UINT)LvGetSelectedParam(hWnd, L_LIST);
+
+ if (id == 0)
+ {
+ SetWizardButtonEx(wizard_page, false, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode));
+ }
+ else
+ {
+ SetWizardButtonEx(wizard_page, true, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode));
+ }
+}
+
+// Language setting screen
+UINT SwLang1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ NMHDR *n;
+ UINT id;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ LvInitEx2(hWnd, L_LIST, false, true);
+
+ if (MsIsVista())
+ {
+ SetFont(hWnd, L_LIST, GetMeiryoFontEx(12));
+ }
+ else
+ {
+ DlgFont(hWnd, L_LIST, 12, false);
+ }
+
+ LvInsertColumn(hWnd, L_LIST, 0, L"English Name", 250);
+ LvInsertColumn(hWnd, L_LIST, 1, L"Local Name", 250);
+
+ SwLang1Update(hWnd, sw, wizard, wizard_page);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButtonEx(wizard_page, true, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode));
+
+ SwLang1Init(hWnd, sw);
+
+ SwLang1Update(hWnd, sw, wizard, wizard_page);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ if (SwEnterSingle(sw) == false)
+ {
+ // Multiple-starts prevention
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS"));
+ break;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Win9x
+ MsgBox(hWnd, MB_ICONSTOP,
+ L"Windows 9x / Me doesn't support multi-language switcing.\r\n\r\nIf you want to switch to another language, please use Windows NT 4.0, 2000 or greater.");
+ break;
+ }
+
+ // Get the current selection
+ id = (UINT)LvGetSelectedParam(hWnd, L_LIST);
+ if (id != 0)
+ {
+ id--;
+
+ if (id == GetCurrentLangId())
+ {
+ // No change
+ sw->LangNotChanged = true;
+
+ sw->ExitCode = 0;
+
+ return D_SW_ERROR;
+ }
+ else
+ {
+ wchar_t add_param[MAX_SIZE];
+ LIST *o;
+ LANGLIST *new_lang;
+ LANGLIST old_lang;
+ char new_lang_name[MAX_SIZE];
+ char old_lang_name[MAX_SIZE];
+
+ GetCurrentLang(&old_lang);
+
+ o = LoadLangList();
+
+ if (o == NULL)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED"));
+ break;
+ }
+
+ new_lang = GetLangById(o, id);
+
+ if (new_lang == NULL)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED"));
+ FreeLangList(o);
+ break;
+ }
+
+ StrCpy(new_lang_name, sizeof(new_lang_name), new_lang->Name);
+ StrCpy(old_lang_name, sizeof(old_lang_name), old_lang.Name);
+
+ FreeLangList(o);
+
+ UniFormat(add_param, sizeof(add_param), L"/LANGID:%u", id);
+
+ if (sw->DoubleClickBlocker)
+ {
+ break;
+ }
+
+ sw->DoubleClickBlocker = true;
+
+ sw->LangId = id;
+
+ if (sw->IsSystemMode == false)
+ {
+LABEL_RUN_CHILD_PROCESS:
+ // Start the process immediately in the case of user mode
+ if (SaveLangConfigCurrentDir(new_lang_name) == false)
+ {
+ sw->DoubleClickBlocker = false;
+ MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_SET_FAILED"));
+ break;
+ }
+
+ UniStrCat(add_param, sizeof(add_param), L" /LANGNOW:yes");
+ if (SwReExecMyself(sw, add_param, false))
+ {
+ // Terminate itself if it succeeds to start the child process
+ CloseWizard(wizard_page);
+ break;
+ }
+ else
+ {
+ // Child process startup failure
+ sw->DoubleClickBlocker = false;
+
+ // Undo the language setting
+ SaveLangConfigCurrentDir(old_lang_name);
+ break;
+ }
+ }
+
+ // In the case of system mode
+ if (MsIsAdmin() == false)
+ {
+ if (MsIsVista())
+ {
+ if (sw->IsReExecForUac == false)
+ {
+ // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run
+ UniStrCat(add_param, sizeof(add_param), L" /SETLANGANDREBOOT:true");
+
+ if (SwReExecMyself(sw, add_param, true))
+ {
+ // Terminate itself if it succeeds to start the child process
+ CloseWizard(wizard_page);
+ break;
+ }
+ else
+ {
+ // Do nothing if it fails to start in the UAC
+ sw->DoubleClickBlocker = false;
+ break;
+ }
+ }
+ else
+ {
+ // If no Admin privileges after being started by the UAC, jump to the guidance screen indicating it is not Admin
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ // Jump to guide screen indicating that it is not the Admin in the case of XP or earlier
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ // Start the process if there is a Admin privileges
+ goto LABEL_RUN_CHILD_PROCESS;
+ }
+ }
+ }
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SwLang1Update(hWnd, sw, wizard, wizard_page);
+ break;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+// Start the uninstallation
+UINT SwUninst1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, S_TITLE, sw->CurrentComponent->Title);
+ FormatText(hWnd, S_WELCOME, sw->CurrentComponent->Title);
+ break;
+
+ case WM_WIZ_SHOW:
+ DlgFont(hWnd, S_TITLE, 11, true);
+ SetWizardButtonEx(wizard_page, true, false, true, false, sw->IsSystemMode);
+
+ sw->DoubleClickBlocker = false;
+
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_UNINSTALL_CONFIRM"),
+ sw->CurrentComponent->Title) == IDNO)
+ {
+ break;
+ }
+
+ if (SwEnterSingle(sw) == false)
+ {
+ // Multiple-starts prevention
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS"));
+ break;
+ }
+
+ if (sw->DoubleClickBlocker)
+ {
+ break;
+ }
+
+ sw->DoubleClickBlocker = true;
+
+ if (sw->IsSystemMode == false)
+ {
+ // Start uninstallation immediately in the case of user mode
+ return D_SW_PERFORM;
+ }
+
+ // In the case of system mode
+ if (MsIsAdmin() == false)
+ {
+ if (MsIsVista())
+ {
+ if (sw->IsReExecForUac == false)
+ {
+ // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run
+ if (SwReExecMyself(sw, NULL, true))
+ {
+ // Terminate itself if it succeeds to start the child process
+ CloseWizard(wizard_page);
+ break;
+ }
+ else
+ {
+ // If fail to run in UAC, jump to guide screen indicating that it is not Admin
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ // If no Admin privileges after being started by the UAC, jump to the guidance screen indicating it is not Admin
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ // Jump to guide screen indicating that it is not the Admin in the case of XP or earlier
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ // Start the uninstallation if it has Admin privileges
+ return D_SW_PERFORM;
+ }
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Completion screen
+UINT SwFinish(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (sw->EasyMode)
+ {
+ SetIcon(hWnd, S_ICON, ICO_SETUP);
+ }
+ else if (sw->WebMode)
+ {
+ SetIcon(hWnd, S_ICON, ICO_INTERNET);
+ }
+ else
+ {
+ FormatText(hWnd, S_INFO, sw->CurrentComponent->Title);
+ SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon);
+ }
+
+ wizard->CloseConfirmMsg = NULL;
+
+ sw->ExitCode = 0;
+ break;
+
+ case WM_WIZ_SHOW:
+ if (UniIsEmptyStr(sw->FinishMsg) == false)
+ {
+ SetText(hWnd, S_INFO, sw->FinishMsg);
+ }
+
+ SetWizardButton(wizard_page, true, false, false, true);
+
+ if (sw->HideStartCommand || sw->UninstallMode || sw->LanguageMode || sw->EasyMode || sw->WebMode || UniIsEmptyStr(sw->CurrentComponent->StartExeName))
+ {
+ Hide(hWnd, B_RUN);
+ sw->Run = false;
+ }
+ else
+ {
+ SetText(hWnd, B_RUN, sw->CurrentComponent->StartDescription);
+ Show(hWnd, B_RUN);
+ Format(tmp, sizeof(tmp), "UI_NoCheck_%s_%u", sw->CurrentComponent->Name, sw->IsSystemMode);
+ Check(hWnd, B_RUN, !MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, tmp));
+ sw->Run = IsChecked(hWnd, B_RUN);
+ }
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_RUN:
+ if (sw->HideStartCommand || sw->UninstallMode || sw->LanguageMode || sw->EasyMode || sw->WebMode || UniIsEmptyStr(sw->CurrentComponent->StartExeName))
+ {
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "UI_NoCheck_%s_%u", sw->CurrentComponent->Name, sw->IsSystemMode);
+ sw->Run = IsChecked(hWnd, B_RUN);
+ MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, tmp, !sw->Run);
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Error occuring screen
+UINT SwError(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ wizard->CloseConfirmMsg = NULL;
+
+ if (sw->EasyMode)
+ {
+ SetText(hWnd, S_INFO, _UU("SW_EASY_ERROR_MSG"));
+ }
+ else if (sw->WebMode)
+ {
+ SetText(hWnd, S_INFO, _UU("SW_WEB_ERROR_MSG"));
+ }
+ else
+ {
+ FormatText(hWnd, S_INFO, sw->CurrentComponent->Title);
+ }
+
+ if (sw->MsiRebootRequired)
+ {
+ // MSI requires a reboot
+ wchar_t tmp[MAX_SIZE];
+
+ SetIcon(hWnd, S_ICON, ICO_INFORMATION);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SW_MSI_UNINSTALL_REBOOT_REQUIRED"), sw->CurrentComponent->Title);
+
+ SetText(hWnd, S_INFO, tmp);
+ }
+
+ if (sw->LangNotChanged)
+ {
+ // Language has not changed
+ wchar_t tmp[MAX_SIZE];
+
+ SetIcon(hWnd, S_ICON, ICO_INFORMATION);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SW_LANG_NOT_CHANGED"), sw->CurrentComponent->Title);
+
+ SetText(hWnd, S_INFO, tmp);
+ }
+
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, false, false, true);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Execution thread of the setup process
+void SwPerformThread(THREAD *thread, void *param)
+{
+ WIZARD_PAGE *wp = (WIZARD_PAGE *)param;
+ SW *sw;
+ SW_COMPONENT *c;
+ bool ret;
+ SW_UI ui;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ sw = (SW *)wp->Wizard->Param;
+
+ sw->ExitCode = SW_EXIT_CODE_INTERNAL_ERROR;
+
+ // Components to be installed
+ c = sw->CurrentComponent;
+
+ if (sw->EasyMode)
+ {
+ // Create a simple installer
+ ret = SwEasyMain(sw, wp);
+ }
+ else if (sw->WebMode)
+ {
+ // Create a Web installer
+ ret = SwWebMain(sw, wp);
+ }
+ else if (sw->UninstallMode == false)
+ {
+ // Installation
+ ret = SwInstallMain(sw, wp, c);
+ }
+ else
+ {
+ // Uninstallation
+ ret = SwUninstallMain(sw, wp, c);
+ }
+
+ // Notify the results to the window
+ Zero(&ui, sizeof(ui));
+ ui.Type = (ret ? SW_UI_TYPE_FINISH : SW_UI_TYPE_ERROR);
+ SwInteractUi(wp, &ui);
+}
+
+// Create a file copy task
+SW_TASK_COPY *SwNewCopyTask(wchar_t *srcfilename, wchar_t *dstfilename, wchar_t *srcdir, wchar_t *dstdir, bool overwrite, bool setup_file)
+{
+ SW_TASK_COPY *ct;
+ // Validate arguments
+ if (srcfilename == NULL || srcdir == NULL || dstdir == NULL)
+ {
+ return NULL;
+ }
+
+ ct = ZeroMalloc(sizeof(SW_TASK_COPY));
+
+ UniStrCpy(ct->SrcFileName, sizeof(ct->SrcFileName), srcfilename);
+
+ if (UniIsEmptyStr(dstfilename))
+ {
+ UniStrCpy(ct->DstFileName, sizeof(ct->DstFileName), srcfilename);
+ }
+ else
+ {
+ UniStrCpy(ct->DstFileName, sizeof(ct->DstFileName), dstfilename);
+ }
+
+ UniStrCpy(ct->SrcDir, sizeof(ct->SrcDir), srcdir);
+ UniStrCpy(ct->DstDir, sizeof(ct->DstDir), dstdir);
+
+ ct->Overwrite = overwrite;
+ ct->SetupFile = setup_file;
+
+ return ct;
+}
+
+// Release the file copy task
+void SwFreeCopyTask(SW_TASK_COPY *ct)
+{
+ // Validate arguments
+ if (ct == NULL)
+ {
+ return;
+ }
+
+ Free(ct);
+}
+
+// Create a link creation task
+SW_TASK_LINK *SwNewLinkTask(wchar_t *target_dir, wchar_t *target_exe, wchar_t *target_arg,
+ wchar_t *icon_exe, UINT icon_index,
+ wchar_t *dest_dir, wchar_t *dest_name, wchar_t *dest_desc,
+ bool no_delete_dir)
+{
+ SW_TASK_LINK *lt;
+ // Validate arguments
+ if (target_dir == NULL || target_exe == NULL || dest_dir == NULL || dest_name == NULL)
+ {
+ return NULL;
+ }
+
+ lt = ZeroMalloc(sizeof(SW_TASK_LINK));
+
+ UniStrCpy(lt->TargetDir, sizeof(lt->TargetDir), target_dir);
+ UniStrCpy(lt->TargetExe, sizeof(lt->TargetExe), target_exe);
+ UniStrCpy(lt->TargetArg, sizeof(lt->TargetArg), target_arg);
+
+ if (UniIsEmptyStr(icon_exe) == false)
+ {
+ UniStrCpy(lt->IconExe, sizeof(lt->IconExe), icon_exe);
+ }
+ else
+ {
+ UniStrCpy(lt->IconExe, sizeof(lt->IconExe), target_exe);
+ }
+
+ lt->IconIndex = icon_index;
+
+ UniStrCpy(lt->DestDir, sizeof(lt->DestDir), dest_dir);
+ UniStrCpy(lt->DestName, sizeof(lt->DestName), dest_name);
+ UniStrCpy(lt->DestDescription, sizeof(lt->DestDescription), dest_desc);
+
+ lt->NoDeleteDir = no_delete_dir;
+
+ return lt;
+}
+
+// Release the link creation task
+void SwFreeLinkTask(SW_TASK_LINK *lt)
+{
+ // Validate arguments
+ if (lt == NULL)
+ {
+ return;
+ }
+
+ Free(lt);
+}
+
+// Create a Setup task
+SW_TASK *SwNewTask()
+{
+ SW_TASK *t = ZeroMalloc(sizeof(SW_TASK));
+
+ t->CopyTasks = NewListFast(NULL);
+
+ t->SetSecurityPaths = NewListFast(NULL);
+
+ t->LinkTasks = NewListFast(NULL);
+
+ return t;
+}
+
+// Release the Setup Tasks
+void SwFreeTask(SW_TASK *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->CopyTasks);i++)
+ {
+ SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i);
+
+ SwFreeCopyTask(ct);
+ }
+
+ ReleaseList(t->CopyTasks);
+
+ FreeStrList(t->SetSecurityPaths);
+
+ for (i = 0;i < LIST_NUM(t->LinkTasks);i++)
+ {
+ SW_TASK_LINK *lt = LIST_DATA(t->LinkTasks, i);
+
+ SwFreeLinkTask(lt);
+ }
+
+ ReleaseList(t->LinkTasks);
+
+ Free(t);
+}
+
+// Delete the shortcut file
+void SwDeleteShortcuts(SW_LOGFILE *logfile)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (logfile == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(logfile->LogList);i++)
+ {
+ SW_LOG *g = LIST_DATA(logfile->LogList, LIST_NUM(logfile->LogList) - i - 1);
+
+ switch (g->Type)
+ {
+ case SW_LOG_TYPE_LNK:
+ FileDeleteW(g->Path);
+ Add(o, g);
+ break;
+
+ case SW_LOG_TYPE_LNK_DIR:
+ SleepThread(100);
+ DeleteDirW(g->Path);
+ Add(o, g);
+ break;
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SW_LOG *g = LIST_DATA(o, i);
+
+ Delete(logfile->LogList, g);
+
+ Free(g);
+ }
+
+ ReleaseList(o);
+}
+
+// Uninstall main
+bool SwUninstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c)
+{
+ bool x64 = MsIs64BitWindows();
+ bool ok;
+ wchar_t tmp[MAX_SIZE];
+ UINT i;
+ // Validate arguments
+ if (sw == NULL || wp == NULL || c == NULL)
+ {
+ return false;
+ }
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INIT_UNINST"));
+
+ // Stop the Service
+ ok = true;
+
+ if (c->InstallService)
+ {
+ char svc_title_name[MAX_SIZE];
+ wchar_t *svc_title;
+
+ Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName);
+
+ svc_title = _UU(svc_title_name);
+
+ if (UniIsEmptyStr(svc_title) == false)
+ {
+ if (sw->IsSystemMode && MsIsNt())
+ {
+ // WinNT and system mode
+ if (MsIsServiceRunning(c->SvcName))
+ {
+ wchar_t svc_exe[MAX_SIZE];
+ UINT64 giveup_tick;
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC"), svc_title);
+ SwPerformPrint(wp, tmp);
+
+LABEL_RETRY_3:
+ if (MsStopService(c->SvcName) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC_ERROR"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ if (MsIsServiceRunning(c->SvcName))
+ {
+ goto LABEL_RETRY_3;
+ }
+ }
+ }
+
+ // Wait 5 seconds if stop the service
+ SleepThread(5000);
+
+ // Wait until the EXE file for the service become ready to write
+ ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName);
+
+ giveup_tick = Tick64() + (UINT64)10000;
+ while (IsFileWriteLockedW(svc_exe))
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe);
+ SwPerformPrint(wp, tmp);
+
+ SleepThread(100);
+
+ if (Tick64() >= giveup_tick)
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Win9x or user mode
+ wchar_t svc_exe[MAX_SIZE];
+ UINT64 giveup_tick;
+
+ // Stop the Service
+ MsStopUserModeSvc(c->SvcName);
+ SleepThread(3000);
+
+ // Wait until the EXE file for the service become ready to write
+ ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName);
+
+ giveup_tick = Tick64() + (UINT64)10000;
+ while (IsFileWriteLockedW(svc_exe))
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe);
+ SwPerformPrint(wp, tmp);
+
+ SleepThread(100);
+
+ if (Tick64() >= giveup_tick)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Examine preliminary whether the files to be deleted can be written successfully
+ ok = true;
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_PREPARE"));
+
+ for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++)
+ {
+ SW_LOG *g = LIST_DATA(sw->LogFile->LogList, i);
+
+ if (g->Type == SW_LOG_TYPE_FILE)
+ {
+ wchar_t fullpath[MAX_SIZE];
+ IO *io;
+ bool write_ok;
+ bool new_file;
+
+LABEL_RETRY_1:
+ write_ok = new_file = false;
+
+ UniStrCpy(fullpath, sizeof(fullpath), g->Path);
+
+ // If the process with the same name is running, kill it
+ if (MsKillProcessByExeName(fullpath) != 0)
+ {
+ // Wait for 1 second if kill the process
+ SleepThread(1000);
+ }
+
+ // Writing check
+ io = FileOpenExW(fullpath, true, true);
+ if (io == NULL)
+ {
+ io = FileCreateW(fullpath);
+ new_file = true;
+ }
+ if (io != NULL)
+ {
+ // Writing OK
+ write_ok = true;
+
+ FileCloseEx(io, true);
+
+ if (new_file)
+ {
+ FileDeleteW(fullpath);
+ }
+ }
+
+ if (write_ok == false)
+ {
+ // Show an error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_DELETE_ERROR"), fullpath, c->Title);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ break;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_1;
+ }
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Delete the service
+ if (c->InstallService)
+ {
+ char svc_title_name[MAX_SIZE];
+ char svc_description_name[MAX_SIZE];
+ wchar_t *svc_title;
+
+ Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName);
+ Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName);
+
+ svc_title = _UU(svc_title_name);
+
+ if (UniIsEmptyStr(svc_title) == false)
+ {
+ if (sw->IsSystemMode == false || MsIsNt() == false)
+ {
+ // Win9x or user mode
+ if (MsIsNt() == false)
+ {
+ // Remove the Run key from the registry for Win9x
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, c->SvcName);
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, c->SvcName);
+ }
+ }
+ else
+ {
+ // System mode
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_UNINSTALL_SVC"), svc_title);
+ SwPerformPrint(wp, tmp);
+
+LABEL_RETRY_4:
+
+ if (MsIsServiceInstalled(c->SvcName))
+ {
+ // Stop the service if it is running by any chance
+ MsStopService(c->SvcName);
+ }
+
+ if (MsIsServiceInstalled(c->SvcName))
+ {
+ // Uninstall the service
+ if (MsUninstallService(c->SvcName) == false)
+ {
+ // Show an error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_UNINSTALL_FAILED"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_4;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Delete the shortcut
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_LINKS"));
+ SwDeleteShortcuts(sw->LogFile);
+
+ // Delete the registry, files, and directories
+ for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++)
+ {
+ SW_LOG *g = LIST_DATA(sw->LogFile->LogList, LIST_NUM(sw->LogFile->LogList) - i - 1);
+ char tmpa[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_DELETE"), g->Path);
+
+ switch (g->Type)
+ {
+ case SW_LOG_TYPE_FILE: // File
+ SwPerformPrint(wp, tmp);
+ FileDeleteW(g->Path);
+ break;
+
+ case SW_LOG_TYPE_DIR: // Directory
+ SwPerformPrint(wp, tmp);
+ SleepThread(100);
+ DeleteDirW(g->Path);
+ break;
+
+ case SW_LOG_TYPE_REGISTRY: // Registry
+ SwPerformPrint(wp, tmp);
+ UniToStr(tmpa, sizeof(tmpa), g->Path);
+ MsRegDeleteKeyEx2(REG_LOCAL_MACHINE, tmpa, false, true);
+ break;
+ }
+ }
+
+ // Remove the installed build number from the registry
+ if (true)
+ {
+ char keyname[MAX_SIZE];
+ Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name);
+ MsRegDeleteValueEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER,
+ keyname, "InstalledBuild", false, true);
+ }
+
+ // Remove the EULA agreement record
+ MsRegDeleteValueEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true);
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_SETUP_INFO"));
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ // Remove the UI Helper
+ MsRegDeleteValueEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+ SW_VPN_CLIENT_UIHELPER_REGVALUE, false, true);
+ }
+
+ // Remove the installation directory from the registry
+ if (true)
+ {
+ // Remove the installed directory from the registry
+ char keyname[MAX_SIZE];
+ Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name);
+ MsRegDeleteKeyEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER, keyname, false, true);
+ }
+
+ // Delete the setuplog.dat
+ if (true)
+ {
+ wchar_t setuplog[MAX_PATH];
+
+ ConbinePathW(setuplog, sizeof(setuplog), MsGetExeDirNameW(), L"setuplog.dat");
+
+ FileDeleteW(setuplog);
+ }
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_UPDATING"));
+
+ // Notify the update to the system
+ MsUpdateSystem();
+
+ // Completion message
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_FINISHED"));
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+LABEL_CLEANUP:
+
+ return ok;
+}
+
+// Create a Task List
+void SwDefineTasks(SW *sw, SW_TASK *t, SW_COMPONENT *c)
+{
+ wchar_t tmp[MAX_SIZE];
+ bool x64 = MsIs64BitWindows();
+ wchar_t src_setup_exe_fullpath[MAX_PATH];
+ wchar_t src_setup_exe_dir[MAX_PATH];
+ wchar_t src_setup_exe_filename[MAX_PATH];
+ wchar_t dir_desktop[MAX_PATH];
+ wchar_t dir_startmenu[MAX_PATH];
+ wchar_t dir_program[MAX_PATH];
+ wchar_t dir_app_program[MAX_PATH];
+ wchar_t dir_config_program[MAX_PATH];
+ wchar_t dir_admin_tools[MAX_PATH];
+ wchar_t dir_config_language[MAX_PATH];
+ wchar_t dir_startup[MAX_PATH];
+ wchar_t tmp1[MAX_SIZE], tmp2[MAX_SIZE];
+ SW_TASK_COPY *setup_exe;
+ // Validate arguments
+ if (sw == NULL || t == NULL || c == NULL)
+ {
+ return;
+ }
+
+ //// Organize directory name for creating shortcut
+ // Desktop
+ UniStrCpy(dir_desktop, sizeof(dir_desktop), (sw->IsSystemMode ? MsGetCommonDesktopDirW() : MsGetPersonalDesktopDirW()));
+ // Start menu
+ UniStrCpy(dir_startmenu, sizeof(dir_startmenu), (sw->IsSystemMode ? MsGetCommonStartMenuDirW() : MsGetPersonalStartMenuDirW()));
+ // Program
+ UniStrCpy(dir_program, sizeof(dir_program), (sw->IsSystemMode ? MsGetCommonProgramsDirW() : MsGetPersonalProgramsDirW()));
+ // Program directory for this application
+ ConbinePathW(dir_app_program, sizeof(dir_app_program), dir_program, c->LongName);
+ if (sw->IsSystemMode == false)
+ {
+ // User mode
+ UniStrCat(dir_app_program, sizeof(dir_app_program), _UU("SW_TAG_USERNAME"));
+ }
+ // Configuration tool directory
+ ConbinePathW(dir_config_program, sizeof(dir_config_program), dir_app_program, _UU("SW_DIRNAME_CONFIG_TOOLS"));
+ // Language configuration directory
+ ConbinePathW(dir_config_language, sizeof(dir_config_language), dir_app_program, _UU("SW_DIRNAME_LANGUAGE_TOOLS"));
+ // Directory for System administrator tool
+ ConbinePathW(dir_admin_tools, sizeof(dir_admin_tools), dir_app_program, _UU("SW_DIRNAME_ADMIN_TOOLS"));
+ // Startup
+ UniStrCpy(dir_startup, sizeof(dir_startup), (sw->IsSystemMode ? MsGetCommonStartupDirW() : MsGetPersonalStartupDirW()));
+
+ // Get the path information related to vpnsetup.exe
+ UniStrCpy(src_setup_exe_fullpath, sizeof(src_setup_exe_fullpath), MsGetExeFileNameW());
+ GetDirNameFromFilePathW(src_setup_exe_dir, sizeof(src_setup_exe_dir), src_setup_exe_fullpath);
+ GetFileNameFromFilePathW(src_setup_exe_filename, sizeof(src_setup_exe_filename), src_setup_exe_fullpath);
+
+ // Add the Setup program (themselves) to the copy list
+ Add(t->CopyTasks, (setup_exe = SwNewCopyTask(src_setup_exe_filename,
+ L"vpnsetup.exe", src_setup_exe_dir, sw->InstallDir, true, true)));
+
+ // Generate the file processing list for each component
+ if (c->Id == SW_CMP_VPN_SERVER)
+ {
+ // VPN Server
+ SW_TASK_COPY *ct;
+ SW_TASK_COPY *vpnserver, *vpncmd, *vpnsmgr;
+
+ CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_server.config");
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ if (x64 == false)
+ {
+ vpnserver = SwNewCopyTask(L"vpnserver.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+ else
+ {
+ vpnserver = SwNewCopyTask(L"vpnserver_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+
+ Add(t->CopyTasks, vpnserver);
+ Add(t->CopyTasks, vpncmd);
+ Add(t->CopyTasks, vpnsmgr);
+
+ Add(t->CopyTasks, (ct = SwNewCopyTask(L"|empty.config", L"vpn_server.config", sw->InstallSrc, sw->InstallDir, false, false)));
+ Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false));
+
+ CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName);
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ //// Definition of the shortcuts
+ // Desktop and Start menu
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+
+ // Programs\PacketiX VPN Server
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNSMGR_FULL"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMD"),
+ _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools,
+ _UU("SW_LINK_NAME_TRAFFIC"),
+ _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false));
+
+ // Programs\PacketiX VPN Server\Configuration tool
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program,
+ _UU("SW_LINK_NAME_TCP"),
+ _UU("SW_LINK_NAME_TCP_COMMENT"), false));
+
+ if (MsIsWin2000OrGreater())
+ {
+ Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program,
+ _UU("SW_LINK_NAME_SERVICES"),
+ _UU("SW_LINK_NAME_SERVICES_COMMENT"), false));
+
+ if (sw->IsSystemMode)
+ {
+ // Debugging information collecting tool
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools,
+ _UU("SW_LINK_NAME_DEBUG"),
+ _UU("SW_LINK_NAME_DEBUG_COMMENT"), false));
+ }
+ }
+
+ if (sw->IsSystemMode == false)
+ {
+ // Register to the start-up in the case of user mode
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/usermode", NULL, 0, dir_startup,
+ _UU("SW_LINK_NAME_VPNSERVER_SVC"),
+ _UU("SW_LINK_NAME_VPNSERVER_SVC_COMMENT"), true));
+ }
+ }
+ else if (c->Id == SW_CMP_VPN_BRIDGE)
+ {
+ // VPN Bridge
+ SW_TASK_COPY *ct;
+ SW_TASK_COPY *vpnbridge, *vpncmd, *vpnsmgr;
+
+ CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_bridge.config");
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ if (x64 == false)
+ {
+ vpnbridge = SwNewCopyTask(L"vpnbridge.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+ else
+ {
+ vpnbridge = SwNewCopyTask(L"vpnbridge_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+
+ Add(t->CopyTasks, vpnbridge);
+ Add(t->CopyTasks, vpncmd);
+ Add(t->CopyTasks, vpnsmgr);
+
+ Add(t->CopyTasks, (ct = SwNewCopyTask(L"|empty.config", L"vpn_bridge.config", sw->InstallSrc, sw->InstallDir, false, false)));
+ Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false));
+
+ CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName);
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ //// Definition of the shortcuts
+ // Desktop and Start menu
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+
+ // Programs\PacketiX VPN Bridge
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNSMGR_FULL"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMD"),
+ _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools,
+ _UU("SW_LINK_NAME_TRAFFIC"),
+ _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false));
+
+ // Programs\PacketiX VPN Bridge\Configuration tool
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program,
+ _UU("SW_LINK_NAME_TCP"),
+ _UU("SW_LINK_NAME_TCP_COMMENT"), false));
+
+ if (MsIsWin2000OrGreater())
+ {
+ Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program,
+ _UU("SW_LINK_NAME_SERVICES"),
+ _UU("SW_LINK_NAME_SERVICES_COMMENT"), false));
+
+ if (sw->IsSystemMode)
+ {
+ // Debugging information collecting tool
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools,
+ _UU("SW_LINK_NAME_DEBUG"),
+ _UU("SW_LINK_NAME_DEBUG_COMMENT"), false));
+ }
+ }
+
+ if (sw->IsSystemMode == false)
+ {
+ // Register to the start-up in the case of user mode
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/usermode", NULL, 0, dir_startup,
+ _UU("SW_LINK_NAME_VPNBRIDGE_SVC"),
+ _UU("SW_LINK_NAME_VPNBRIDGE_SVC_COMMENT"), true));
+ }
+ }
+ else if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ // VPN Client
+ SW_TASK_COPY *ct;
+ SW_TASK_COPY *vpnclient, *vpncmd, *vpncmgr;
+ SW_TASK_COPY *vpnclient_gomi, *vpncmd_gomi, *vpncmgr_gomi;
+ SW_TASK_COPY *sfx_cache = NULL;
+ SW_TASK_COPY *vpnweb;
+ SW_TASK_COPY *vpninstall;
+ wchar_t *src_config_filename;
+
+ CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_vpnclient.config");
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ if (x64 == false)
+ {
+ vpnclient = SwNewCopyTask(L"vpnclient.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnclient_gomi = SwNewCopyTask(L"vpnclient_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd_gomi = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr_gomi = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+ else
+ {
+ vpnclient = SwNewCopyTask(L"vpnclient_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnclient_gomi = SwNewCopyTask(L"vpnclient.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmd_gomi = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr_gomi = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+
+ if (vpncmgr != NULL)
+ {
+ CombinePathW(sw->vpncmgr_path, sizeof(sw->vpncmgr_path),
+ vpncmgr->DstDir, vpncmgr->DstFileName);
+ }
+
+ if (UniIsEmptyStr(sw->CallerSfxPath) == false)
+ {
+ if (IsFileExistsW(sw->CallerSfxPath))
+ {
+ // Cache the calling SFX file body to the installation directory
+ wchar_t srcname[MAX_PATH];
+ wchar_t srcdir[MAX_PATH];
+
+ GetFileNameFromFilePathW(srcname, sizeof(srcname), sw->CallerSfxPath);
+ GetDirNameFromFilePathW(srcdir, sizeof(srcdir), sw->CallerSfxPath);
+
+ sfx_cache = SwNewCopyTask(srcname, SW_SFX_CACHE_FILENAME, srcdir, sw->InstallDir, true, false);
+ }
+ }
+
+ vpnweb = SwNewCopyTask(L"vpnweb.cab", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpninstall = SwNewCopyTask(L"vpninstall.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+
+ Add(t->CopyTasks, vpnclient);
+ Add(t->CopyTasks, vpncmd);
+ Add(t->CopyTasks, vpncmgr);
+ Add(t->CopyTasks, vpnclient_gomi);
+ Add(t->CopyTasks, vpncmd_gomi);
+ Add(t->CopyTasks, vpncmgr_gomi);
+ Add(t->CopyTasks, vpnweb);
+ Add(t->CopyTasks, vpninstall);
+
+
+ if (sfx_cache != NULL)
+ {
+ Add(t->CopyTasks, sfx_cache);
+ }
+
+ src_config_filename = L"|empty.config";
+
+ Add(t->CopyTasks, (ct = SwNewCopyTask(src_config_filename, L"vpn_client.config", sw->InstallSrc, sw->InstallDir, false, false)));
+
+ Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false));
+
+ CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName);
+ Add(t->SetSecurityPaths, CopyUniStr(tmp));
+
+ //// Definition of the shortcuts
+ // Desktop and Start menu
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_desktop,
+ _UU("SW_LINK_NAME_VPNCMGR_SHORT"),
+ _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), true));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_startmenu,
+ _UU("SW_LINK_NAME_VPNCMGR_SHORT"),
+ _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), true));
+
+ // Programs\PacketiX VPN Client
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMGR_FULL"),
+ _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMGR2_FULL"),
+ _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMD"),
+ _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnclient->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools,
+ _UU("SW_LINK_NAME_TRAFFIC"),
+ _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false));
+
+ // Programs\PacketiX VPN Client\Configuration Tools
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnclient->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program,
+ _UU("SW_LINK_NAME_TCP"),
+ _UU("SW_LINK_NAME_TCP_COMMENT"), false));
+
+ if (MsIsWin2000OrGreater())
+ {
+ Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program,
+ _UU("SW_LINK_NAME_SERVICES"),
+ _UU("SW_LINK_NAME_SERVICES_COMMENT"), false));
+
+ if (sw->IsSystemMode)
+ {
+ // Debugging information collecting tool
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools,
+ _UU("SW_LINK_NAME_DEBUG"),
+ _UU("SW_LINK_NAME_DEBUG_COMMENT"), false));
+ }
+ }
+
+ // Programs\PacketiX VPN Client\System administrators tool
+ if (MsIsNt())
+ {
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, L"vpnsetup.exe", L"/easy:true", L"vpnsetup.exe", 12, dir_admin_tools,
+ _UU("SW_LINK_NAME_EASYINSTALLER"),
+ _UU("SW_LINK_NAME_EASYINSTALLER_COMMENT"), false));
+
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, L"vpnsetup.exe", L"/web:true", L"vpnsetup.exe", 1, dir_admin_tools,
+ _UU("SW_LINK_NAME_WEBINSTALLER"),
+ _UU("SW_LINK_NAME_WEBINSTALLER_COMMENT"), false));
+ }
+
+ // Startup
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/startup", NULL, 0, dir_startup,
+ _UU("SW_LINK_NAME_VPNCMGRTRAY_FULL"),
+ _UU("SW_LINK_NAME_VPNCMGRTRAY_COMMENT"), true));
+ }
+ else if (c->Id == SW_CMP_VPN_SMGR)
+ {
+ // VPN Server Manager (Tools Only)
+ SW_TASK_COPY *vpncmd, *vpnsmgr;
+
+ if (x64 == false)
+ {
+ vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+ else
+ {
+ vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+
+ Add(t->CopyTasks, vpncmd);
+ Add(t->CopyTasks, vpnsmgr);
+
+ //// Definition of the shortcuts
+ // Desktop and Start menu
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY" : "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY" : "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true));
+
+ // Programs\PacketiX VPN Server Manager (Tools Only)
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNSMGR_FULL"),
+ _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMD"),
+ _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false));
+ }
+ else if (c->Id == SW_CMP_VPN_CMGR)
+ {
+ // VPN Client Manager (Tools Only)
+ SW_TASK_COPY *vpncmd, *vpncmgr;
+
+ if (x64 == false)
+ {
+ vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+ else
+ {
+ vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ vpncmgr = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false);
+ }
+
+ Add(t->CopyTasks, vpncmd);
+ Add(t->CopyTasks, vpncmgr);
+
+ //// Definition of the shortcuts
+ // Desktop and Start menu
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_desktop,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNCMGRTOOLS_SHORT" : "SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), true));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_startmenu,
+ _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNCMGRTOOLS_SHORT" : "SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM"),
+ _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), true));
+
+ // Programs\PacketiX VPN Client Manager (Tools Only)
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMGR2_FULL"),
+ _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), false));
+ Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program,
+ _UU("SW_LINK_NAME_VPNCMD"),
+ _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false));
+ }
+
+ // Uninstallation
+ UniFormat(tmp1, sizeof(tmp1), _UU("SW_LINK_NAME_UNINSTALL"), c->Title);
+ UniFormat(tmp2, sizeof(tmp2), _UU("SW_LINK_NAME_UNINSTALL_COMMENT"), c->Title);
+ Add(t->LinkTasks, SwNewLinkTask(setup_exe->DstDir, setup_exe->DstFileName, NULL, NULL, 0, dir_config_program,
+ tmp1,
+ tmp2, false));
+
+ // Language settings (except for Win9x)
+ if (MsIsNt())
+ {
+ UniFormat(tmp1, sizeof(tmp1), _UU("SW_LINK_NAME_LANGUAGE"), c->Title);
+ UniFormat(tmp2, sizeof(tmp2), _UU("SW_LINK_NAME_LANGUAGE_COMMENT"), c->Title);
+ Add(t->LinkTasks, SwNewLinkTask(setup_exe->DstDir, setup_exe->DstFileName, L"/language:yes",
+ L"vpnsetup.exe", 10, dir_config_language,
+ tmp1,
+ tmp2, false));
+ }
+
+ // Hamcore!
+ Add(t->CopyTasks, SwNewCopyTask(L"hamcore.se2", NULL, sw->InstallSrc, sw->InstallDir, true, true));
+}
+
+// Build the Web installer
+bool SwWebMain(SW *sw, WIZARD_PAGE *wp)
+{
+ bool ret = false;
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (sw == NULL || wp == NULL)
+ {
+ return false;
+ }
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_WEB_INIT"));
+
+ if (true)
+ {
+ wchar_t installer_src_exe[MAX_PATH];
+ wchar_t src_cab[MAX_PATH];
+ wchar_t vpninstall_exe[MAX_PATH];
+ char inf_path[MAX_PATH];
+ char htm_path[MAX_PATH];
+ LANGLIST current_lang;
+ BUF *inf_buf = NULL;
+ BUF *htm_buf = NULL;
+ BUF *setting_buf = NULL;
+ char *inf_data = NULL;
+ UINT inf_data_size;
+ char *htm_data = NULL;
+ UINT htm_data_size;
+ char ver_major[64];
+ char ver_minor[64];
+ char ver_build[64];
+ char *normal_mode = (sw->Web_EasyMode ? "false" : "true");
+ char package_name[MAX_SIZE];
+ ZIP_PACKER *z = NULL;
+
+ ToStr(ver_major, CEDAR_VER / 100);
+ ToStr(ver_minor, CEDAR_VER % 100);
+ ToStr(ver_build, CEDAR_BUILD);
+
+ Format(package_name, sizeof(package_name),
+ GC_SW_SOFTETHER_PREFIX "vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.exe",
+ CEDAR_VER / 100,
+ CEDAR_VER % 100,
+ CEDAR_BUILD,
+ BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D);
+
+ GetCurrentLang(&current_lang);
+
+ // Installer cache file
+ CombinePathW(installer_src_exe, sizeof(installer_src_exe), MsGetExeDirNameW(), SW_SFX_CACHE_FILENAME);
+
+ // Cab file
+ CombinePathW(src_cab, sizeof(src_cab), MsGetExeDirNameW(), L"vpnweb.cab");
+
+ // Vpninstall file
+ CombinePathW(vpninstall_exe, sizeof(vpninstall_exe), MsGetExeDirNameW(), L"vpninstall.exe");
+
+ // Confirm existence of the file
+ if (IsFileExistsW(installer_src_exe) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), installer_src_exe);
+ SwPerformMsgBox(wp, MB_ICONSTOP, tmp);
+ goto LABEL_CLEANUP;
+ }
+ if (IsFileExistsW(src_cab) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), src_cab);
+ SwPerformMsgBox(wp, MB_ICONSTOP, tmp);
+ goto LABEL_CLEANUP;
+ }
+ if (IsFileExistsW(vpninstall_exe) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), vpninstall_exe);
+ SwPerformMsgBox(wp, MB_ICONSTOP, tmp);
+ goto LABEL_CLEANUP;
+ }
+
+ // Read the configuration file
+ setting_buf = ReadDumpW(sw->Web_SettingFile);
+ if (setting_buf != NULL)
+ {
+ if (sw->Web_EraseSensitive)
+ {
+ // Remove the secret information
+ CiEraseSensitiveInAccount(setting_buf);
+ }
+ }
+
+ // Verify the signature of the installer cache file
+ if (MsCheckFileDigitalSignatureW(NULL, installer_src_exe, NULL) == false)
+ {
+ // Installer cache file is not signed
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("SW_INSTALLER_CACHE_IS_NOT_SIGNED")) == IDNO)
+ {
+ // Cancel
+ goto LABEL_CLEANUP;
+ }
+ }
+
+ // Read the .inf file
+ Format(inf_path, sizeof(inf_path), "|vpninstall_%s.inf", current_lang.Name);
+
+ inf_buf = ReadDump(inf_path);
+ if (inf_buf == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ inf_data_size = (inf_buf->Size + 1024) * 2;
+ inf_data = ZeroMalloc(inf_data_size);
+ Copy(inf_data, inf_buf->Buf, inf_buf->Size);
+
+ ReplaceStrEx(inf_data, inf_data_size, inf_data, "$VER_BUILD$", ver_build, false);
+ ReplaceStrEx(inf_data, inf_data_size, inf_data, "$PACKAGE_FILENAME$", package_name, false);
+ ReplaceStrEx(inf_data, inf_data_size, inf_data, "$NORMAL_MODE$", normal_mode, false);
+
+ // Read the .htm file
+ Format(htm_path, sizeof(htm_path), "|vpnweb_sample_%s.htm", current_lang.Name);
+
+ htm_buf = ReadDump(htm_path);
+ if (htm_buf == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ htm_data_size = (htm_buf->Size + 1024) * 2;
+ htm_data = ZeroMalloc(htm_data_size);
+ Copy(htm_data, htm_buf->Buf, htm_buf->Size);
+
+ ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_MAJOR$", ver_major, false);
+ ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_MINOR$", ver_minor, false);
+ ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_BUILD$", ver_build, false);
+
+ // Creating a ZIP
+ z = NewZipPacker();
+
+ if (ZipAddRealFileW(z, "vpnweb.cab", 0, 0, src_cab) == false ||
+ ZipAddRealFileW(z, "vpninstall.exe", 0, 0, vpninstall_exe) == false ||
+ ZipAddRealFileW(z, package_name, 0, 0, installer_src_exe) == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ ZipAddFileSimple(z, "vpninstall.inf", 0, 0, inf_data, StrLen(inf_data));
+ ZipAddFileSimple(z, "index.html", 0, 0, htm_data, StrLen(htm_data));
+ ZipAddFileSimple(z, "auto_setting.vpn", 0, 0, setting_buf->Buf, setting_buf->Size);
+
+ // Export
+ if (ZipWriteW(z, sw->Web_OutFile))
+ {
+ ret = true;
+
+ UniFormat(sw->FinishMsg, sizeof(sw->FinishMsg),
+ _UU("SW_WEB_FINISHED"),
+ sw->Web_OutFile);
+ }
+
+LABEL_CLEANUP:
+ FreeZipPacker(z);
+ FreeBuf(setting_buf);
+ FreeBuf(inf_buf);
+ FreeBuf(htm_buf);
+ Free(inf_data);
+ Free(htm_data);
+ }
+
+
+ return ret;
+}
+
+// Build a simple installer
+bool SwEasyMain(SW *sw, WIZARD_PAGE *wp)
+{
+ LIST *o;
+ BUF *b;
+ bool ret = false;
+ wchar_t account_tmp[MAX_PATH];
+ // Validate arguments
+ if (sw == NULL || wp == NULL)
+ {
+ return false;
+ }
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_EASY_INIT"));
+
+ o = SwNewSfxFileList();
+
+ SwAddBasicFilesToList(o, "vpnclient");
+
+ // Load a connection setting file
+ b = ReadDumpW(sw->Easy_SettingFile);
+ if (b != NULL)
+ {
+ if (sw->Easy_EraseSensitive)
+ {
+ // Remove secret information
+ CiEraseSensitiveInAccount(b);
+ }
+
+ // Save to a temporary folder
+ CombinePathW(account_tmp, sizeof(account_tmp), MsGetMyTempDirW(), L"vpn_setting.vpn");
+ if (DumpBufW(b, account_tmp))
+ {
+ // Add a connection settings to file list of SFX
+ Add(o, SwNewSfxFile(SW_AUTO_CONNECT_ACCOUNT_FILE_NAME, account_tmp));
+
+ if (sw->Easy_EasyMode)
+ {
+ // Set the connection manager to simple mode
+ Add(o, SwNewSfxFile(SW_FLAG_EASY_MODE, account_tmp));
+ }
+
+ if (SwCompileSfx(o, sw->Easy_OutFile))
+ {
+ ret = true;
+ }
+
+ FileDeleteW(account_tmp);
+ }
+
+ FreeBuf(b);
+ }
+
+ SwFreeSfxFileList(o);
+
+ if (ret)
+ {
+ // Completion message
+ UniFormat(sw->FinishMsg, sizeof(sw->FinishMsg), _UU("SW_EASY_FINISHED_MSG"), sw->Easy_OutFile);
+ }
+
+ return ret;
+}
+
+// Installation main
+bool SwInstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c)
+{
+ SW_TASK *t;
+ bool ret = false;
+ UINT i;
+ wchar_t tmp[MAX_SIZE * 2];
+ bool ok;
+ bool x64 = MsIs64BitWindows();
+ // Validate arguments
+ if (sw == NULL || wp == NULL || c == NULL)
+ {
+ return false;
+ }
+
+ ok = true;
+ t = NULL;
+
+ // Create a Setup task
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INIT_TASKS"));
+ t = SwNewTask();
+
+ // Create a list of files to be installed
+ SwDefineTasks(sw, t, c);
+
+ if (sw->LanguageMode)
+ {
+ goto LABEL_CREATE_SHORTCUT;
+ }
+
+ if (sw->OnlyAutoSettingMode)
+ {
+ goto LABEL_IMPORT_SETTING;
+ }
+
+ // Install the SeLow
+ if (SuIsSupportedOs())
+ {
+ // Only in the system mode
+ if (c->InstallService && sw->IsSystemMode)
+ {
+ // Not to install in the case of the VPN Client
+ //if (c->Id != SW_CMP_VPN_CLIENT)
+ {
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INSTALL_SELOW"));
+
+ SuInstallDriver(false);
+ }
+ }
+ }
+
+ // Uninstall the old MSI
+ ok = true;
+ if (sw->IsSystemMode && c->OldMsiList != NULL)
+ {
+ bool reboot_required = false;
+
+ if (SwUninstallOldMsiInstalled(wp->Wizard->hWndWizard, wp, c, &reboot_required) == false)
+ {
+ // MSI uninstall Failed
+ ok = false;
+ }
+ else if (reboot_required)
+ {
+ // Require to restart
+ ok = false;
+
+ sw->MsiRebootRequired = true;
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Stop the Service
+ ok = true;
+
+ if (c->InstallService)
+ {
+ char svc_title_name[MAX_SIZE];
+ wchar_t *svc_title;
+
+ Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName);
+
+ svc_title = _UU(svc_title_name);
+
+ if (UniIsEmptyStr(svc_title) == false)
+ {
+ if (sw->IsSystemMode && MsIsNt())
+ {
+ // WinNT and system mode
+ if (MsIsServiceRunning(c->SvcName))
+ {
+ wchar_t svc_exe[MAX_SIZE];
+ UINT64 giveup_tick;
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC"), svc_title);
+ SwPerformPrint(wp, tmp);
+
+LABEL_RETRY_3:
+ if (MsStopService(c->SvcName) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC_ERROR"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ if (MsIsServiceRunning(c->SvcName))
+ {
+ goto LABEL_RETRY_3;
+ }
+ }
+ }
+
+ // Wait for 5 seconds if stopped the service
+ SleepThread(5000);
+
+ // Wait until the EXE file for the service become ready to write
+ ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName);
+
+ giveup_tick = Tick64() + (UINT64)10000;
+ while (IsFileWriteLockedW(svc_exe))
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe);
+ SwPerformPrint(wp, tmp);
+
+ SleepThread(100);
+
+ if (Tick64() >= giveup_tick)
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // In the case of Win9x or user mode
+ wchar_t svc_exe[MAX_SIZE];
+ UINT64 giveup_tick;
+
+ // Stop the Service
+ MsStopUserModeSvc(c->SvcName);
+ SleepThread(3000);
+
+ // Wait until the EXE file for the service become ready to write
+ ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName);
+
+ giveup_tick = Tick64() + (UINT64)10000;
+ while (IsFileWriteLockedW(svc_exe))
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe);
+ SwPerformPrint(wp, tmp);
+
+ SleepThread(100);
+
+ if (Tick64() >= giveup_tick)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Examine preliminary whether files to be copied are writable successfully
+ ok = true;
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_COPY_PREPARE"));
+
+ for (i = 0;i < LIST_NUM(t->CopyTasks);i++)
+ {
+ SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i);
+
+ wchar_t fullpath[MAX_SIZE];
+ IO *io;
+ bool write_ok;
+ bool new_file;
+ bool new_dir;
+ UINT64 giveup_tick = Tick64() + 30000ULL;
+
+LABEL_RETRY_1:
+ new_dir = write_ok = new_file = false;
+
+ CombinePathW(fullpath, sizeof(fullpath), ct->DstDir, ct->DstFileName);
+
+ if (ct->Overwrite == false)
+ {
+ // Do not check if overwrite is Off
+ continue;
+ }
+
+ // If the process with the same name is running, kill it
+ if (MsKillProcessByExeName(fullpath) != 0)
+ {
+ // Wait for 1 second if killed the process
+ SleepThread(1000);
+ }
+
+ new_dir = MakeDirExW(ct->DstDir);
+
+ // Write check
+ io = FileOpenExW(fullpath, true, true);
+ if (io == NULL)
+ {
+ io = FileCreateW(fullpath);
+ new_file = true;
+ }
+ if (io != NULL)
+ {
+ // Writing OK
+ write_ok = true;
+
+ FileCloseEx(io, true);
+
+ if (new_file)
+ {
+ FileDeleteW(fullpath);
+ }
+ }
+
+ if (new_dir)
+ {
+ DeleteDirW(ct->DstDir);
+ }
+
+ if (write_ok == false)
+ {
+ UINT64 now = Tick64();
+
+ if (now <= giveup_tick)
+ {
+ // Do the auto-retry in 30 seconds
+ SleepThread(1000);
+ goto LABEL_RETRY_1;
+ }
+
+ // Show an error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WRITE_ERROR"), fullpath, c->Title);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ break;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_1;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // File Copy
+ ok = true;
+
+ for (i = 0;i < LIST_NUM(t->CopyTasks);i++)
+ {
+ SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i);
+ wchar_t fullpath_src[MAX_SIZE];
+ wchar_t fullpath_dst[MAX_SIZE];
+ bool skip;
+
+LABEL_RETRY_2:
+
+ if (UniStartWith(ct->SrcFileName, L"|") == false)
+ {
+ CombinePathW(fullpath_src, sizeof(fullpath_src), ct->SrcDir, ct->SrcFileName);
+ }
+ else
+ {
+ UniStrCpy(fullpath_src, sizeof(fullpath_src), ct->SrcFileName);
+ }
+
+ CombinePathW(fullpath_dst, sizeof(fullpath_dst), ct->DstDir, ct->DstFileName);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_COPY_FILE"), fullpath_dst);
+ SwPerformPrint(wp, tmp);
+
+ skip = false;
+
+ if (ct->Overwrite == false)
+ {
+ if (IsFileExistsW(fullpath_dst))
+ {
+ // Do nothing because the destination file already exists
+ skip = true;
+ }
+ }
+
+ if (skip == false)
+ {
+ // Create a directory
+ if (MakeDirExW(ct->DstDir))
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_DIR, ct->DstDir);
+ }
+
+ // Copy
+ if (FileCopyW(fullpath_src, fullpath_dst) == false && ct->Overwrite)
+ {
+ // Show an error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_COPY_ERROR"), fullpath_dst);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ break;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_2;
+ }
+ }
+ else
+ {
+ if (ct->Overwrite && ct->SetupFile == false)
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_FILE, fullpath_dst);
+ }
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+
+ if (sw->IsSystemMode && MsIsNt())
+ {
+ // ACL settings only in the system mode
+ for (i = 0;i < LIST_NUM(t->SetSecurityPaths);i++)
+ {
+ // Security Settings
+ wchar_t *path = LIST_DATA(t->SetSecurityPaths, i);
+
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SET_SECURITY"), path);
+ SwPerformPrint(wp, tmp);
+
+ MsSetFileSecureAcl(path);
+ }
+ }
+
+ // Set the language of the destination
+ if (true)
+ {
+ LANGLIST current_lang;
+ wchar_t langfilename[MAX_PATH];
+
+ Zero(&current_lang, sizeof(current_lang));
+ GetCurrentLang(&current_lang);
+
+ ConbinePathW(langfilename, sizeof(langfilename), sw->InstallDir, L"lang.config");
+
+ SaveLangConfig(langfilename, current_lang.Name);
+ }
+
+ // Firewall registration
+ if (true)
+ {
+ char dira[MAX_PATH];
+
+ UniToStr(dira, sizeof(dira), sw->InstallDir);
+
+ RegistWindowsFirewallAllEx(dira);
+ }
+
+ if (c->Id == SW_CMP_VPN_SERVER || c->Id == SW_CMP_VPN_BRIDGE)
+ {
+ // Disable the off-loading
+ MsDisableNetworkOffloadingEtc();
+ }
+
+ // Install the service
+ ok = true;
+
+ if (c->InstallService)
+ {
+ char svc_title_name[MAX_SIZE];
+ char svc_description_name[MAX_SIZE];
+ wchar_t *svc_title;
+
+ Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName);
+ Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName);
+
+ svc_title = _UU(svc_title_name);
+
+ if (UniIsEmptyStr(svc_title) == false)
+ {
+ if (sw->IsSystemMode == false || MsIsNt() == false)
+ {
+ // Just simply start in user mode or Win9x mode
+ wchar_t fullpath[MAX_SIZE];
+
+LABEL_RETRY_USERMODE_EXEC:
+
+ CombinePathW(fullpath, sizeof(fullpath), sw->InstallDir, c->SvcFileName);
+
+ if (MsExecuteW(fullpath, (MsIsNt() ? L"/usermode" : L"/win9x_service")) == false)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_USERMODE_EXEC_FAILED"), fullpath);
+
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_USERMODE_EXEC;
+ }
+ }
+ else
+ {
+ if (MsIsNt() == false)
+ {
+ // Register into the registry as a background service in the case of Win9x
+ wchar_t fullpath2[MAX_SIZE];
+
+ UniFormat(fullpath2, sizeof(fullpath2), L"\"%s\" /win9x_service", fullpath);
+
+ MsRegWriteStrW(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, c->SvcName, fullpath2);
+ MsRegWriteStrW(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, c->SvcName, fullpath2);
+ }
+ }
+ }
+ else
+ {
+ // System mode
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_INSTALL_SVC"), svc_title);
+ SwPerformPrint(wp, tmp);
+
+LABEL_RETRY_4:
+
+ if (MsIsServiceInstalled(c->SvcName))
+ {
+ // Stop the service if it is running by any chance
+ MsStopService(c->SvcName);
+ }
+
+ if (MsIsServiceInstalled(c->SvcName))
+ {
+ // Uninstall the old service
+ if (MsUninstallService(c->SvcName) == false)
+ {
+ // Show an error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_UNINSTALL_FAILED"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_4;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ wchar_t fullpath[MAX_SIZE];
+ wchar_t fullpath2[MAX_SIZE];
+
+ CombinePathW(fullpath2, sizeof(fullpath), sw->InstallDir, c->SvcFileName);
+ UniFormat(fullpath, sizeof(fullpath), L"\"%s\" /service", fullpath2);
+
+ // Install a new service
+ if (MsInstallServiceW(c->SvcName, svc_title, _UU(svc_description_name), fullpath) == false)
+ {
+ // Show the error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_INSTALL_FAILED"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ // Retry
+ goto LABEL_RETRY_4;
+ }
+ }
+ else
+ {
+ wchar_t wtmp[256];
+
+ StrToUni(wtmp, sizeof(wtmp), c->SvcName);
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_SVC, wtmp);
+ }
+ }
+
+ if (ok)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_START_SVC"), svc_title);
+ SwPerformPrint(wp, tmp);
+
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", c->SvcName, 0, false, true);
+
+LABEL_RETRY_5:
+ // Start the service
+ if (MsStartService(c->SvcName) == false)
+ {
+ // Show the error message if it fails
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_START_SVC_ERROR"), svc_title, c->SvcName);
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY)
+ {
+ // Cancel
+ ok = false;
+ }
+ else
+ {
+ // Retry
+ if (MsIsServiceRunning(c->SvcName) == false)
+ {
+ goto LABEL_RETRY_5;
+ }
+ }
+ }
+ }
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ // In the VPN Client service, wait until the service port can be connected
+ SwWaitForVpnClientPortReady(SW_VPNCLIENT_SERVICE_WAIT_READY_TIMEOUT);
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+LABEL_CREATE_SHORTCUT:
+
+ // Create a shortcut
+ SwInstallShortcuts(sw, wp, c, t);
+
+ if (sw->LanguageMode)
+ {
+ // Update the Description of the service if in the language setting mode
+ if (c->InstallService)
+ {
+ char svc_description_name[MAX_SIZE];
+ wchar_t *svc_description;
+
+ Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName);
+
+ svc_description = _UU(svc_description_name);
+
+ if (UniIsEmptyStr(svc_description) == false)
+ {
+ if (sw->IsSystemMode && MsIsNt())
+ {
+ MsSetServiceDescription(c->SvcName, svc_description);
+ }
+ }
+ }
+
+ goto LABEL_REGISTER_UNINSTALL;
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ // Register the UI Helper in the Run in the case of the VPN Client
+ wchar_t fullpath[MAX_PATH];
+ wchar_t fullcmd[MAX_SIZE];
+
+ ConbinePathW(fullpath, sizeof(fullpath), sw->InstallDir, c->SvcFileName);
+
+ UniFormat(fullcmd, sizeof(fullcmd), L"\"%s\" /uihelp", fullpath);
+
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+ SW_VPN_CLIENT_UIHELPER_REGVALUE, fullcmd, false, true);
+
+ // Start the UI Helper
+ MsExecuteW(fullpath, L"/uihelp");
+
+ SleepThread(3000);
+ }
+
+ if (true)
+ {
+ // Run the vpncmd and exit immediately
+ wchar_t fullpath[MAX_PATH];
+
+ ConbinePathW(fullpath, sizeof(fullpath), sw->InstallDir, (MsIsX64() ? L"vpncmd_x64.exe" : L"vpncmd.exe"));
+
+ RunW(fullpath, L"/?", true, false);
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ wchar_t dst_vpnclient_exe[MAX_PATH];
+ wchar_t vpnclient_arg[MAX_SIZE];
+
+ ConbinePathW(dst_vpnclient_exe, sizeof(dst_vpnclient_exe), sw->InstallDir, c->SvcFileName);
+ UniFormat(vpnclient_arg, sizeof(vpnclient_arg), L"\"%s\" \"%%1\"", dst_vpnclient_exe);
+
+ // Register the association to .vpn file in the case of VPN Client
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY, NULL, SW_VPN_CLIENT_EXT_REGVALUE, false, true);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY);
+
+ MsRegNewKeyEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY_SUB1, false, true);
+ MsRegNewKeyEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY_SUB2, false, true);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY_SUB1);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY_SUB2);
+
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_REGKEY, NULL, SW_VPN_CLIENT_VPNFILE_REGVALUE, false, true);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_REGKEY);
+
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_ICON_REGKEY, NULL, dst_vpnclient_exe, false, true);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_ICON_REGKEY);
+
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY, NULL, vpnclient_arg, false, true);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB2);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB1);
+ SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY);
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ // Disable the MMCSS
+ MsSetMMCSSNetworkThrottlingEnable(false);
+ }
+
+LABEL_IMPORT_SETTING:
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ if (UniIsEmptyStr(sw->auto_setting_path) == false)
+ {
+ if (UniIsEmptyStr(sw->vpncmgr_path) == false)
+ {
+ if (sw->DisableAutoImport == false)
+ {
+ wchar_t tmp_setting_path[MAX_PATH];
+ wchar_t arg[MAX_PATH];
+ void *handle;
+ bool easy_mode = IsFileExists(SW_FLAG_EASY_MODE_2);
+ // Run the vpncmgr, and start a connection by importing the connection configuration file
+ // Store a connection setting file to stable temporally directory
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_IMPORTING_ACCOUNT"));
+
+ ConbinePathW(tmp_setting_path, sizeof(tmp_setting_path), MsGetTempDirW(), L"vpn_auto_connect.vpn");
+ FileCopyW(sw->auto_setting_path, tmp_setting_path);
+
+ // Start the vpncmgr
+ UniFormat(arg, sizeof(arg), L"/%S \"%s\"", (easy_mode ? "easy" : "normal"), tmp_setting_path);
+ handle = MsRunAsUserExW(sw->vpncmgr_path, arg, false);
+
+ if (handle != NULL)
+ {
+ sw->HideStartCommand = true;
+
+ CloseHandle(handle);
+ }
+ }
+ }
+ }
+ }
+
+ if (sw->OnlyAutoSettingMode)
+ {
+ goto LABEL_FINISHED;
+ }
+
+LABEL_REGISTER_UNINSTALL:
+ // Register the uninstall information
+ if (sw->IsSystemMode)
+ {
+ char uninstall_keyname[MAX_SIZE];
+ wchar_t uninstall_keyname_w[MAX_SIZE];
+ char uninstall_version[MAX_SIZE];
+ wchar_t dst_setup_exe[MAX_PATH];
+ wchar_t setup_icon[MAX_SIZE];
+ wchar_t uninstaller_exe[MAX_PATH];
+ SYSTEMTIME st;
+ char install_date[MAX_PATH];
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_REGISTER_UNINSTALL"));
+
+ Zero(&st, sizeof(st));
+ LocalTime(&st);
+
+ Format(install_date, sizeof(install_date), "%04u/%02u/%02u", st.wYear, st.wMonth, st.wDay);
+
+ CombinePathW(dst_setup_exe, sizeof(dst_setup_exe), sw->InstallDir, L"vpnsetup.exe");
+
+ Format(uninstall_keyname, sizeof(uninstall_keyname),
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\softether_" GC_SW_SOFTETHER_PREFIX "%s", c->Name);
+ StrToUni(uninstall_keyname_w, sizeof(uninstall_keyname_w), uninstall_keyname);
+
+ GetCedarVersion(uninstall_version, sizeof(uninstall_version));
+
+ // Display name
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayName", c->LongName,
+ false, true);
+
+ // Version
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayVersion", uninstall_version,
+ false, true);
+
+ // Icon
+ UniFormat(setup_icon, sizeof(setup_icon), L"\"%s\",%u", dst_setup_exe, c->IconExeIndex);
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayIcon", setup_icon,
+ false, true);
+
+ // Information
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, uninstall_keyname, "NoModify", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, uninstall_keyname, "NoRepair", 1, false, true);
+
+ // Link
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "HelpLink", _SS("SW_UNINSTALLINFO_URL"),
+ false, true);
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "URLInfoAbout", _SS("SW_UNINSTALLINFO_URL"),
+ false, true);
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "URLUpdateInfo", _SS("SW_UNINSTALLINFO_URL"),
+ false, true);
+
+ // Publisher
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "Publisher", _UU("SW_UNINSTALLINFO_PUBLISHER"),
+ false, true);
+
+ // Date of installation
+ MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "InstallDate", install_date,
+ false, true);
+
+ // Uninstaller
+ UniFormat(uninstaller_exe, sizeof(uninstaller_exe), L"\"%s\"", dst_setup_exe);
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "UninstallString", uninstaller_exe,
+ false, true);
+
+ if (sw->LanguageMode == false)
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, uninstall_keyname_w);
+ }
+ }
+
+ // Write the log
+ if (true)
+ {
+ wchar_t log_filename[MAX_SIZE];
+
+L_RETRY_LOG:
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_WRITE_LOG"));
+
+ CombinePathW(log_filename, sizeof(log_filename), sw->InstallDir, L"setuplog.dat");
+
+ if (sw->LanguageMode == false)
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_FILE, log_filename);
+ }
+
+ sw->LogFile->IsSystemMode = sw->IsSystemMode;
+ sw->LogFile->Component = sw->CurrentComponent;
+ sw->LogFile->Build = CEDAR_BUILD;
+
+ if (SwSaveLogFile(sw, log_filename, sw->LogFile) == false)
+ {
+ // Show the error message if it fails
+ UINT msgret;
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WRITE_LOG_ERROR"), log_filename);
+ msgret = SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO, tmp);
+
+ if (msgret == IDYES)
+ {
+ // Retry
+ goto L_RETRY_LOG;
+ }
+ }
+ }
+
+ if (true)
+ {
+ // Record the installed build number and directory in the registry
+ char keyname[MAX_SIZE];
+ LANGLIST current_lang;
+ LANGLIST current_os_lang;
+
+ GetCurrentLang(&current_lang);
+ GetCurrentLang(&current_os_lang);
+
+ Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name);
+ MsRegWriteStrEx2W(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER,
+ keyname, "InstalledDir", sw->InstallDir, false, true);
+ MsRegWriteIntEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER,
+ keyname, "InstalledBuild", CEDAR_BUILD, false, true);
+
+ // Set the language to registry
+ MsRegWriteStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last User Language",
+ current_lang.Name, false, true);
+ MsRegWriteStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last Operating System Language",
+ current_os_lang.Name, false, true);
+
+ // Save the EULA agreement record
+ if (sw->EulaAgreed && sw->CurrentEulaHash != 0)
+ {
+ MsRegWriteIntEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name,
+ sw->CurrentEulaHash, false, true);
+ }
+ }
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_UPDATING"));
+
+ // Notify the update to the system
+ MsUpdateSystem();
+
+ if (sw->LanguageMode)
+ {
+ // Show a message that the language configuration is complete
+ wchar_t msg[MAX_SIZE];
+
+ UniFormat(msg, sizeof(msg), _UU("SW_LANG_OK"), c->Title, c->Title);
+
+ if (c->InstallService)
+ {
+ UniStrCat(msg, sizeof(msg), _UU("SW_LANG_OK_SERVICE"));
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ UniStrCat(msg, sizeof(msg), _UU("SW_LANG_OK_VPNCMGR"));
+ }
+
+ UniStrCpy(sw->FinishMsg, sizeof(sw->FinishMsg), msg);
+ }
+
+LABEL_FINISHED:
+
+ // Completion message
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_FINISHED"));
+
+ ret = true;
+
+LABEL_CLEANUP:
+ // Release the task
+ if (t != NULL)
+ {
+ SwFreeTask(t);
+ }
+
+ return ret;
+}
+
+// Wait for that the listening port of the VPN Client service becomes available
+bool SwWaitForVpnClientPortReady(UINT timeout)
+{
+ UINT64 start, giveup;
+ bool ret = false;
+ if (timeout == 0)
+ {
+ timeout = SW_VPNCLIENT_SERVICE_WAIT_READY_TIMEOUT;
+ }
+
+ start = Tick64();
+ giveup = start + (UINT64)timeout;
+
+ while (Tick64() < giveup)
+ {
+ if (CheckTCPPortEx("localhost", CLIENT_CONFIG_PORT, 1000))
+ {
+ ret = true;
+ break;
+ }
+
+ SleepThread(1000);
+ }
+
+ return ret;
+}
+
+// Create a Shortcut file (Delete the old one)
+void SwInstallShortcuts(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c, SW_TASK *t)
+{
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t setuplog[MAX_PATH];
+ LIST *o;
+ SW_LOGFILE *oldlog;
+ // Validate arguments
+ if (sw == NULL || wp == NULL || c == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // If there is an old setup log, read it
+ CombinePathW(setuplog, sizeof(setuplog), sw->InstallDir, L"setuplog.dat");
+ oldlog = SwLoadLogFile(sw, setuplog);
+ if (oldlog != NULL)
+ {
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_OLD_LINKS"));
+
+ SwDeleteShortcuts(oldlog);
+
+ SwFreeLogFile(oldlog);
+ }
+
+ // Remove only the shortcut setup log from the current log
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++)
+ {
+ SW_LOG *g = LIST_DATA(sw->LogFile->LogList, i);
+
+ if (g->Type == SW_LOG_TYPE_LNK || g->Type == SW_LOG_TYPE_LNK_DIR)
+ {
+ Add(o, g);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SW_LOG *g = LIST_DATA(o, i);
+
+ Delete(sw->LogFile->LogList, g);
+
+ Free(g);
+ }
+
+ ReleaseList(o);
+
+ for (i = 0;i < LIST_NUM(t->LinkTasks);i++)
+ {
+ SW_TASK_LINK *lt = LIST_DATA(t->LinkTasks, i);
+ wchar_t lnk_fullpath[MAX_SIZE];
+ wchar_t lnk_dirname[MAX_SIZE];
+ wchar_t target_fullpath[MAX_SIZE];
+ wchar_t target_dirname[MAX_SIZE];
+ wchar_t icon_fullpath[MAX_SIZE];
+
+L_RETRY_LINK:
+
+ SwPerformPrint(wp, _UU("SW_PERFORM_MSG_CREATE_LINKS"));
+
+ // Generate the full path of the LNK file
+ CombinePathW(lnk_fullpath, sizeof(lnk_fullpath), lt->DestDir, lt->DestName);
+ UniStrCat(lnk_fullpath, sizeof(lnk_fullpath), L".lnk");
+
+ // Get the directory name to be saved the LNK file
+ GetDirNameFromFilePathW(lnk_dirname, sizeof(lnk_dirname), lnk_fullpath);
+
+ // Generate the full path to the link destination
+ CombinePathW(target_fullpath, sizeof(target_fullpath), lt->TargetDir, lt->TargetExe);
+
+ // Create the full path of the icon
+ CombinePathW(icon_fullpath, sizeof(icon_fullpath), lt->TargetDir, lt->IconExe);
+
+ // Get the directory name of the full path to the link destination
+ GetDirNameFromFilePathW(target_dirname, sizeof(target_dirname), target_fullpath);
+
+ // Create a directory
+ MakeDirExW(lnk_dirname);
+ if (lt->NoDeleteDir == false)
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_LNK_DIR, lnk_dirname);
+ }
+
+ // Create the LNK file
+ if (CreateLink(lnk_fullpath, target_fullpath, target_dirname, lt->TargetArg,
+ lt->DestDescription, icon_fullpath, lt->IconIndex) == false)
+ {
+ // Show the error message if it fails
+ UINT msgret;
+ UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_CRAETE_LINK_ERROR"), lnk_fullpath);
+ msgret = SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO, tmp);
+
+ if (msgret == IDYES)
+ {
+ // Retry
+ goto L_RETRY_LINK;
+ }
+ }
+ else
+ {
+ SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_LNK, lnk_fullpath);
+ }
+ }
+}
+
+// Search component
+SW_COMPONENT *SwFindComponent(SW *sw, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (sw == NULL || IsEmptyStr(name))
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(sw->ComponentList);i++)
+ {
+ SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i);
+
+ if (StrCmpi(c->Name, name) == 0)
+ {
+ return c;
+ }
+ }
+
+ return NULL;
+}
+
+// Release the log file
+void SwFreeLogFile(SW_LOGFILE *logfile)
+{
+ UINT i;
+ // Validate arguments
+ if (logfile == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(logfile->LogList);i++)
+ {
+ SW_LOG *g = LIST_DATA(logfile->LogList, i);
+
+ Free(g);
+ }
+
+ ReleaseList(logfile->LogList);
+
+ Free(logfile);
+}
+
+// Create a new log file
+SW_LOGFILE *SwNewLogFile()
+{
+ SW_LOGFILE *logfile = ZeroMalloc(sizeof(SW_LOGFILE));
+
+ logfile->LogList = NewListFast(NULL);
+
+ return logfile;
+}
+
+// Read the log file
+SW_LOGFILE *SwLoadLogFile(SW *sw, wchar_t *filename)
+{
+ FOLDER *r = NULL;
+ FOLDER *items = NULL;
+ FOLDER *info = NULL;
+ UINT i;
+ TOKEN_LIST *t = NULL;
+ bool is_system_mode = false;
+ char component_name[MAX_SIZE] = { 0 };
+ UINT build;
+ SW_COMPONENT *c = NULL;
+ SW_LOGFILE *ret = NULL;
+ // Validate arguments
+ if (sw == NULL || filename == NULL)
+ {
+ return NULL;
+ }
+
+ r = CfgReadW(filename);
+ if (r == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ items = CfgGetFolder(r, "Items");
+ info = CfgGetFolder(r, "Info");
+ if (items == NULL || info == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ t = CfgEnumFolderToTokenList(items);
+ if (t == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ // Mode and components
+ is_system_mode = CfgGetBool(info, "IsSystemMode");
+ CfgGetStr(info, "ComponentName", component_name, sizeof(component_name));
+ build = CfgGetInt(info, "Build");
+
+ if (build == 0)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ c = SwFindComponent(sw, component_name);
+ if (c == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ ret = ZeroMalloc(sizeof(SW_LOGFILE));
+ ret->IsSystemMode = is_system_mode;
+ ret->Component = c;
+ ret->Build = build;
+ ret->LogList = NewListFast(NULL);
+
+ // Item List
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ FOLDER *f = CfgGetFolder(items, name);
+
+ if (f != NULL)
+ {
+ UINT type = CfgGetInt(f, "Type");
+ wchar_t value[MAX_SIZE];
+
+ if (CfgGetUniStr(f, "Path", value, sizeof(value)))
+ {
+ if (IsEmptyUniStr(value) == false && type != 0)
+ {
+ SW_LOG *g = ZeroMalloc(sizeof(SW_LOG));
+
+ g->Type = type;
+ UniStrCpy(g->Path, sizeof(g->Path), value);
+
+ Add(ret->LogList, g);
+ }
+ }
+ }
+ }
+
+LABEL_CLEANUP:
+ if (r != NULL)
+ {
+ CfgDeleteFolder(r);
+ }
+
+ if (t != NULL)
+ {
+ FreeToken(t);
+ }
+
+ return ret;
+}
+
+// Save the log file
+bool SwSaveLogFile(SW *sw, wchar_t *dst_name, SW_LOGFILE *logfile)
+{
+ FOLDER *r;
+ FOLDER *items;
+ FOLDER *info;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (sw == NULL || dst_name == NULL || logfile == NULL)
+ {
+ return false;
+ }
+
+ r = CfgCreateRoot();
+
+ items = CfgCreateFolder(r, "Items");
+
+ info = CfgCreateFolder(r, "Info");
+
+ CfgAddBool(info, "IsSystemMode", logfile->IsSystemMode);
+ CfgAddStr(info, "ComponentName", logfile->Component->Name);
+ CfgAddInt(info, "Build", logfile->Build);
+
+ for (i = 0;i < LIST_NUM(logfile->LogList);i++)
+ {
+ FOLDER *f;
+ SW_LOG *g = LIST_DATA(logfile->LogList, i);
+ char name[MAX_PATH];
+
+ Format(name, sizeof(name), "Item%04u", i);
+
+ f = CfgCreateFolder(items, name);
+
+ CfgAddInt(f, "Type", g->Type);
+ CfgAddUniStr(f, "Path", g->Path);
+ }
+
+ ret = CfgSaveExW3(NULL, r, dst_name, NULL, true);
+
+ CfgDeleteFolder(r);
+
+ return ret;
+}
+
+// Display the string to the status screen
+void SwPerformPrint(WIZARD_PAGE *wp, wchar_t *str)
+{
+ SW_UI ui;
+ // Validate arguments
+ if (wp == NULL || str == NULL)
+ {
+ return;
+ }
+
+ Zero(&ui, sizeof(ui));
+ ui.Type = SW_UI_TYPE_PRINT;
+ ui.Message = str;
+
+ SwInteractUi(wp, &ui);
+}
+
+// Show a message box on the screen
+UINT SwPerformMsgBox(WIZARD_PAGE *wp, UINT flags, wchar_t *msg)
+{
+ SW_UI ui;
+ // Validate arguments
+ if (wp == NULL || msg == NULL)
+ {
+ return 0;
+ }
+
+ Zero(&ui, sizeof(ui));
+ ui.Type = SW_UI_TYPE_MSGBOX;
+ ui.Message = msg;
+ ui.Param = flags;
+
+ return SwInteractUi(wp, &ui);
+}
+
+// Call the UI interaction
+UINT SwInteractUi(WIZARD_PAGE *wp, SW_UI *ui)
+{
+ // Validate arguments
+ if (wp == NULL || ui == NULL)
+ {
+ return 0;
+ }
+
+ SendMsg(wp->hWndPage, 0, WM_SW_INTERACT_UI, 0xCAFE, (LPARAM)ui);
+
+ SleepThread(50);
+
+ return ui->RetCode;
+}
+
+// UI interaction is called
+void SwInteractUiCalled(HWND hWnd, SW *sw, WIZARD_PAGE *wp, SW_UI *ui)
+{
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wp == NULL || ui == NULL)
+ {
+ return;
+ }
+
+ switch (ui->Type)
+ {
+ case SW_UI_TYPE_PRINT: // Display the message
+ SetText(hWnd, S_STATUS, ui->Message);
+ break;
+
+ case SW_UI_TYPE_MSGBOX: // Show a message box
+ ui->RetCode = MsgBox(hWnd, ui->Param, ui->Message);
+ break;
+
+ case SW_UI_TYPE_FINISH: // Complete
+ PostMessageA(hWnd, WM_SW_EXIT, 0xCAFE, 1);
+ break;
+
+ case SW_UI_TYPE_ERROR: // Error
+ PostMessageA(hWnd, WM_SW_EXIT, 0xCAFE, 0);
+ break;
+ }
+}
+
+// Initialize the setup process screen
+void SwPerformInit(HWND hWnd, SW *sw, WIZARD_PAGE *wp)
+{
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wp == NULL)
+ {
+ return;
+ }
+
+ DlgFont(hWnd, S_INFO, 10, true);
+
+ if (sw->EasyMode)
+ {
+ SetIcon(hWnd, S_ICON, ICO_SETUP);
+
+ SetText(hWnd, S_INFO, _UU("SW_PERFORM_MSG_EASY_INFO"));
+ }
+ else if (sw->WebMode)
+ {
+ SetIcon(hWnd, S_ICON, ICO_SETUP);
+
+ SetText(hWnd, S_INFO, _UU("SW_PERFORM_MSG_WEB_INFO"));
+ }
+ else
+ {
+ SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon);
+
+ FormatText(hWnd, S_INFO, sw->CurrentComponent->Title);
+ }
+
+ SetTextA(hWnd, S_STATUS, "");
+
+ if (MsIsWinXPOrWinVista())
+ {
+ // Display the progress bar for Windows XP or later
+ SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100);
+ SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE);
+ }
+ else
+ {
+ // Hide the progress bar in the case of Windows 2000 or earlier
+ Hide(hWnd, IDC_PROGRESS1);
+ }
+}
+
+// Do the set-up process
+UINT SwPerform(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SwPerformInit(hWnd, sw, wizard_page);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, false, false, false, false);
+
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+
+ case WM_TIMER:
+ KillTimer(hWnd, 1);
+
+ // Main thread execution
+ if (sw->PerformThread == NULL)
+ {
+ sw->PerformThread = NewThread(SwPerformThread, wizard_page);
+ }
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_SW_INTERACT_UI:
+ // UI interaction is called
+ if (wParam == 0xCAFE)
+ {
+ SwInteractUiCalled(hWnd, sw, wizard_page, (SW_UI *)lParam);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+
+ case WM_SW_EXIT:
+ // Close this screen since the process completed
+ if (wParam == 0xCAFE)
+ {
+ JumpWizard(wizard_page, (lParam == 0 ? D_SW_ERROR : D_SW_FINISH));
+
+ if (sw->PerformThread != NULL)
+ {
+ WaitThread(sw->PerformThread, INFINITE);
+ ReleaseThread(sw->PerformThread);
+ sw->PerformThread = NULL;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Final confirmation screen
+UINT SwReady(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, S_INFO, sw->CurrentComponent->Title);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, true, true, false);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ return D_SW_PERFORM;
+
+ case WM_WIZ_BACK:
+ return D_SW_DIR;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Uninstall all the old MSI products
+bool SwUninstallOldMsiInstalled(HWND hWnd, WIZARD_PAGE *wp, SW_COMPONENT *c, bool *reboot_required)
+{
+ UINT i;
+ bool dummy_bool = false;
+ // Validate arguments
+ if (c == NULL || wp == NULL)
+ {
+ return true;
+ }
+ if (reboot_required == NULL)
+ {
+ reboot_required = &dummy_bool;
+ }
+
+ *reboot_required = false;
+
+ if (c->OldMsiList == NULL)
+ {
+ return true;
+ }
+
+ for (i = 0;i < c->NumOldMsi;i++)
+ {
+ SW_OLD_MSI *m = &c->OldMsiList[i];
+ wchar_t tmp[MAX_SIZE];
+
+ if (MsGetMsiInstalledDir(m->ComponentCode, tmp, sizeof(tmp)))
+ {
+ bool rr = false;
+ wchar_t msg[MAX_SIZE];
+
+LABEL_RETRY:
+
+ UniFormat(msg, sizeof(msg), _UU("SW_PERFORM_MSG_UNINSTALL_MSI"), c->Title);
+ SwPerformPrint(wp, msg);
+
+ if (MsMsiUninstall(m->ProductCode, hWnd, &rr) == false)
+ {
+ UniFormat(msg, sizeof(msg), _UU("SW_MSI_UNINSTALL_FAILED"), c->Title, m->ProductCode);
+
+ if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, msg) == IDRETRY)
+ {
+ goto LABEL_RETRY;
+ }
+
+ return false;
+ }
+ else
+ {
+ if (rr)
+ {
+ *reboot_required = true;
+ return true;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Get the directory where the old MSI products are installed
+wchar_t *SwGetOldMsiInstalledDir(SW_COMPONENT *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ if (c->OldMsiList == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < c->NumOldMsi;i++)
+ {
+ SW_OLD_MSI *m = &c->OldMsiList[i];
+ wchar_t tmp[MAX_SIZE];
+
+ if (MsGetMsiInstalledDir(m->ComponentCode, tmp, sizeof(tmp)))
+ {
+ return UniCopyStr(tmp);
+ }
+ }
+
+ return NULL;
+}
+
+// Initialize the default installation directory
+void SwInitDefaultInstallDir(SW *sw)
+{
+ char keyname[MAX_SIZE];
+ wchar_t *reg_dir_system;
+ wchar_t *reg_dir_user;
+ wchar_t *msi_dir_system = NULL;
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ msi_dir_system = SwGetOldMsiInstalledDir(sw->CurrentComponent);
+
+ Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name);
+
+ if (UniIsEmptyStr(msi_dir_system) == false)
+ {
+ MsRegWriteStrEx2W(REG_LOCAL_MACHINE, keyname, "InstalledDir", msi_dir_system, false, true);
+ }
+
+ reg_dir_system = MsRegReadStrEx2W(REG_LOCAL_MACHINE, keyname, "InstalledDir", false, true);
+ reg_dir_user = MsRegReadStrEx2W(REG_CURRENT_USER, keyname, "InstalledDir", false, true);
+
+ // Generate a directory name in the case of system mode
+ CombinePathW(sw->DefaultInstallDir_System, sizeof(sw->DefaultInstallDir_System),
+ MsGetProgramFilesDirX64W(), sw->CurrentComponent->DefaultDirName);
+
+ // Generate a directory name in the case of user mode
+ CombinePathW(sw->DefaultInstallDir_User, sizeof(sw->DefaultInstallDir_User),
+ MsGetPersonalAppDataDirW(), sw->CurrentComponent->DefaultDirName);
+
+ if (UniIsEmptyStr(reg_dir_system) == false)
+ {
+ UniStrCpy(sw->DefaultInstallDir_System, sizeof(sw->DefaultInstallDir_System), reg_dir_system);
+ }
+
+ if (UniIsEmptyStr(reg_dir_user) == false)
+ {
+ UniStrCpy(sw->DefaultInstallDir_User, sizeof(sw->DefaultInstallDir_User), reg_dir_user);
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Set to system mode for Win9x
+ sw->IsSystemMode = true;
+ }
+
+ if (MsIsAdmin() == false)
+ {
+ sw->IsAvailableSystemMode = false;
+ sw->IsAvailableUserMode = true;
+ }
+ else if (MsIsNt() == false)
+ {
+ sw->IsAvailableSystemMode = true;
+ sw->IsAvailableUserMode = false;
+ }
+ else
+ {
+ sw->IsAvailableSystemMode = true;
+ sw->IsAvailableUserMode = !sw->CurrentComponent->SystemModeOnly;
+ }
+
+ sw->ShowWarningForUserMode = sw->CurrentComponent->InstallService;
+
+ Free(reg_dir_system);
+ Free(reg_dir_user);
+ Free(msi_dir_system);
+}
+
+// Update the installation directory setting screen
+void SwDirUpdate(HWND hWnd, SW *sw, WIZARD_PAGE *wizard_page)
+{
+ bool user_mode_selected;
+ bool show_custom;
+ bool change_dir;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard_page == NULL)
+ {
+ return;
+ }
+
+ change_dir = IsChecked(hWnd, R_CUSTOM);
+
+ SetShow(hWnd, S_DEST, change_dir);
+ SetShow(hWnd, E_DIR, change_dir);
+ SetShow(hWnd, B_BROWSE, change_dir);
+
+ show_custom = IsChecked(hWnd, R_SHOWCUSTOM);
+
+ SetShow(hWnd, R_FOR_SYSTEM, show_custom);
+ SetShow(hWnd, R_FOR_USER, show_custom);
+
+ user_mode_selected = IsChecked(hWnd, R_FOR_USER);
+
+ SetText(hWnd, R_DEFAULT, user_mode_selected ? sw->DefaultInstallDir_User : sw->DefaultInstallDir_System);
+
+ if (user_mode_selected == false)
+ {
+ Hide(hWnd, S_WARNING);
+ Hide(hWnd, S_WARNING2);
+ }
+ else
+ {
+ SetShow(hWnd, S_WARNING, sw->ShowWarningForUserMode);
+ SetShow(hWnd, S_WARNING2, sw->ShowWarningForUserMode);
+ }
+
+ SetEnable(hWnd, R_SHOWCUSTOM, !user_mode_selected);
+
+ DlgFont(hWnd, R_DEFAULT, 0, !change_dir);
+}
+
+// Check the directory name planned to be created newly
+bool SwCheckNewDirName(wchar_t *name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR rand[16];
+ wchar_t testname[MAX_SIZE];
+ IO *io;
+ bool new_dir;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ // Create a directory
+ new_dir = MakeDirExW(name);
+
+ // Writes the appropriate files
+ Rand(rand, sizeof(rand));
+ BinToStr(tmp, sizeof(tmp), rand, sizeof(rand));
+ UniFormat(testname, sizeof(testname), L"%s\\%S.dat", name, tmp);
+
+ io = FileCreateW(testname);
+
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileClose(io);
+
+ FileDeleteW(testname);
+
+ if (new_dir)
+ {
+ DeleteDirW(name);
+ }
+
+ return true;
+}
+
+// Set the installation directory
+UINT SwDir(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t setuplog[MAX_SIZE];
+ wchar_t *s;
+ SW_LOGFILE *logfile;
+ bool is_system_mode;
+ bool skip_ver_check = false;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon);
+
+ SwInitDefaultInstallDir(sw);
+
+ FormatText(hWnd, S_INFO, sw->CurrentComponent->Title);
+ FormatText(hWnd, R_FOR_USER, MsGetUserNameW());
+ FormatText(hWnd, S_WARNING, MsGetUserNameW(), sw->CurrentComponent->Title);
+
+ Check(hWnd, R_FOR_SYSTEM, sw->IsSystemMode);
+ Check(hWnd, R_FOR_USER, !sw->IsSystemMode);
+
+ if (sw->IsSystemMode == false)
+ {
+ Check(hWnd, R_SHOWCUSTOM, true);
+ }
+
+ SetText(hWnd, E_DIR, sw->IsSystemMode ? sw->DefaultInstallDir_System : sw->DefaultInstallDir_User);
+
+ Check(hWnd, R_DEFAULT, true);
+
+ SetEnable(hWnd, R_FOR_SYSTEM, sw->IsAvailableSystemMode);
+ SetEnable(hWnd, R_FOR_USER, sw->IsAvailableUserMode);
+
+ SwDirUpdate(hWnd, sw, wizard_page);
+
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, false, true, false);
+
+ SwDirUpdate(hWnd, sw, wizard_page);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ if (IsChecked(hWnd, R_CUSTOM))
+ {
+ GetTxt(hWnd, E_DIR, tmp, sizeof(tmp));
+ }
+ else
+ {
+ if (IsChecked(hWnd, R_FOR_SYSTEM))
+ {
+ UniStrCpy(tmp, sizeof(tmp), sw->DefaultInstallDir_System);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), sw->DefaultInstallDir_User);
+ }
+ }
+
+ is_system_mode = IsChecked(hWnd, R_FOR_SYSTEM);
+
+ if (is_system_mode == false)
+ {
+ if (sw->CurrentComponent->InstallService)
+ {
+ if (MsIsServiceInstalled(sw->CurrentComponent->SvcName))
+ {
+ // If the type of installation is user mode and the same software
+ // is running in system mode already, warn about it
+ if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_SYSTEM_MODE_ALREADY_INSTALLED"),
+ sw->CurrentComponent->Title) == IDNO)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ UniTrim(tmp);
+
+ Win32NukuEnW(tmp, sizeof(tmp), tmp);
+
+ // Check Length
+ if (UniStrLen(tmp) > 110)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_MORE_THAN_110"));
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ // Check whether it's a full path
+ if (UniStartWith(tmp, L"\\\\") == false &&
+ (tmp[1] != L':' || tmp[2] != L'\\'))
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_IS_NOT_FULLPATH"), tmp);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ NormalizePathW(tmp, sizeof(tmp), tmp);
+
+ // Check the type of the drive
+ if (IsChecked(hWnd, R_FOR_SYSTEM))
+ {
+ // System mode service is installed only on the hard disk
+ bool ok = true;
+
+ if (UniStartWith(tmp, L"\\\\"))
+ {
+ ok = false;
+ }
+ else
+ {
+ char tmpa[MAX_SIZE];
+ UINT ret;
+
+ UniToStr(tmpa, sizeof(tmpa), tmp);
+
+ tmpa[3] = 0;
+
+ ret = GetDriveTypeA(tmpa);
+
+ if (ret != DRIVE_FIXED && ret != DRIVE_RAMDISK)
+ {
+ ok = false;
+ }
+ }
+
+ if (ok == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_IS_NOT_HDD"), tmp, sw->CurrentComponent->Title);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+ }
+
+ // Write check
+ if (SwCheckNewDirName(tmp) == false)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_WRITE_ERROR"), tmp);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ // Analyze if there is a setuplog.dat on destination
+ CombinePathW(setuplog, sizeof(setuplog), tmp, L"setuplog.dat");
+ logfile = SwLoadLogFile(sw, setuplog);
+ if (logfile == NULL && IsFileExistsW(setuplog))
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_DST_IS_BROKEN"), setuplog);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ if (logfile != NULL && (logfile->Build > CEDAR_BUILD) && UniIsEmptyStr(sw->auto_setting_path) == false &&
+ sw->CurrentComponent->Id == SW_CMP_VPN_CLIENT && logfile->Component->Id == SW_CMP_VPN_CLIENT)
+ {
+ // In the case of the VPN Client, show a message if a newer version is installed and
+ // the automatic connection setting by simple installer should be applied
+ if (MsgBox(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("SW_DIR_DST_IS_NEWER_2")) == IDCANCEL)
+ {
+ // Cancel
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ skip_ver_check = true;
+ }
+
+ if (logfile != NULL)
+ {
+ wchar_t *errmsg = NULL;
+ if (logfile->Component != sw->CurrentComponent)
+ {
+ errmsg = _UU("SW_DIR_DST_IS_OTHER_PRODUCT");
+ }
+ else if ((skip_ver_check == false) && (logfile->Build > CEDAR_BUILD))
+ {
+ errmsg = _UU("SW_DIR_DST_IS_NEWER");
+ }
+ else if (logfile->IsSystemMode && is_system_mode == false)
+ {
+ errmsg = _UU("SW_DIR_DST_IS_SYSTEM_MODE");
+ }
+ else if (logfile->IsSystemMode == false && is_system_mode)
+ {
+ errmsg = _UU("SW_DIR_DST_IS_USER_MODE");
+ }
+
+ SwFreeLogFile(logfile);
+
+ if (errmsg != NULL)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, errmsg);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+ }
+
+ // Check whether installation destination and installation source are not same
+ if (UniStrCmpi(tmp, sw->InstallSrc) == 0)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_DST_IS_SAME_TO_SRC"), tmp);
+ FocusEx(hWnd, E_DIR);
+ break;
+ }
+
+ UniStrCpy(sw->InstallDir, sizeof(sw->InstallDir), tmp);
+ sw->IsSystemMode = IsChecked(hWnd, R_FOR_SYSTEM);
+
+ sw->OnlyAutoSettingMode = skip_ver_check;
+
+ return D_SW_READY;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case R_DEFAULT:
+ case R_CUSTOM:
+ case R_SHOWCUSTOM:
+ case R_FOR_SYSTEM:
+ case R_FOR_USER:
+ SwDirUpdate(hWnd, sw, wizard_page);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case R_FOR_SYSTEM:
+ SetText(hWnd, E_DIR, sw->DefaultInstallDir_System);
+ break;
+
+ case R_FOR_USER:
+ SetText(hWnd, E_DIR, sw->DefaultInstallDir_User);
+ break;
+
+ case B_BROWSE:
+ GetTxt(hWnd, E_DIR, tmp, sizeof(tmp));
+ s = FolderDlgW(hWnd, _UU("SW_DIR_SELECT"), tmp);
+
+ if (s != NULL)
+ {
+ if (UniEndWith(s, sw->CurrentComponent->DefaultDirName))
+ {
+ UniStrCpy(tmp, sizeof(tmp), s);
+ }
+ else
+ {
+ CombinePathW(tmp, sizeof(tmp), s, sw->CurrentComponent->DefaultDirName);
+ }
+
+ SetText(hWnd, E_DIR, tmp);
+ FocusEx(hWnd, E_DIR);
+
+ Free(s);
+ }
+ break;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+// Warning screen
+UINT SwWarning(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ BUF *b;
+ UCHAR c = 0;
+ wchar_t *str;
+ char warning_filename[MAX_PATH];
+ LANGLIST t;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ DlgFont(hWnd, B_AGREE, 0, true);
+
+ GetCurrentLang(&t);
+
+ SetFont(hWnd, E_TEXT, GetFont((t.Id == SE_LANG_JAPANESE && MsIsWindows7()) ? "Meiryo UI" : NULL, 10, false , false, false, false));
+
+ Format(warning_filename, sizeof(warning_filename), "|warning_%s.txt", t.Name);
+ b = ReadDump(warning_filename);
+
+ SeekBuf(b, b->Size, 0);
+ c = 0;
+ WriteBuf(b, &c, 1);
+
+ str = CopyUtfToUni(b->Buf);
+
+ UniIsEmptyStr(str);
+
+ SetText(hWnd, E_TEXT, str);
+
+ FreeBuf(b);
+
+ Free(str);
+
+ UnselectEdit(hWnd, E_TEXT);
+
+ Focus(hWnd, E_TEXT);
+
+ SetWizardButton(wizard_page, true, true, true, false);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ if (SwEnterSingle(sw) == false)
+ {
+ // Multiple-starts prevention
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS"));
+ break;
+ }
+ return D_SW_DIR;
+
+ case WM_WIZ_BACK:
+ return D_SW_EULA;
+
+ case WM_COMMAND:
+ break;
+ }
+
+ return 0;
+}
+
+// Update the license agreement screen
+void SwEulaUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page)
+{
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL)
+ {
+ return;
+ }
+
+ sw->EulaAgreed = IsChecked(hWnd, B_AGREE);
+
+ if (sw->EulaAgreed == false)
+ {
+ // Delete the agreement record in the case of non-agreement for the EULA
+ MsRegDeleteValueEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true);
+ }
+
+ SetWizardButton(wizard_page, sw->EulaAgreed, true, true, false);
+}
+
+// License Agreement
+UINT SwEula(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ BUF *b;
+ UCHAR c = 0;
+ wchar_t *str;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ SetFont(hWnd, E_TEXT, GetFont((MsIsWindows7() ? "Segoe UI" : "Verdana"), 10, false, false, false, false));
+ //DlgFont(hWnd, B_AGREE, 10, true);
+
+ b = ReadDump("|eula.txt");
+
+ SeekBuf(b, b->Size, 0);
+ c = 0;
+ WriteBuf(b, &c, 1);
+
+ str = CopyUtfToUni(b->Buf);
+
+ UniIsEmptyStr(str);
+
+ SetText(hWnd, E_TEXT, str);
+
+ sw->CurrentEulaHash = HashToUINT(b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(str);
+
+ if (sw->CurrentComponent != NULL && sw->CurrentEulaHash != 0 && sw->CurrentEulaHash == MsRegReadIntEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true))
+ {
+ // Check the consent check box in advance if the user accepts the same EULA during the last installation
+ sw->EulaAgreed = true;
+ }
+
+ Check(hWnd, B_AGREE, sw->EulaAgreed);
+
+ UnselectEdit(hWnd, E_TEXT);
+
+ Focus(hWnd, E_TEXT);
+
+ SwEulaUpdate(hWnd, sw, wizard, wizard_page);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ SwEulaUpdate(hWnd, sw, wizard, wizard_page);
+
+ if (sw->EulaAgreed)
+ {
+ return D_SW_WARNING;
+ }
+ break;
+
+ case WM_WIZ_BACK:
+ sw->EulaAgreed = false;
+ return D_SW_COMPONENTS;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_AGREE:
+ SwEulaUpdate(hWnd, sw, wizard, wizard_page);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Initialize a component list
+void SwComponentsInit(HWND hWnd, SW *sw)
+{
+ LVB *b;
+ UINT i;
+ SW_COMPONENT *default_select = NULL;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return;
+ }
+
+ LvReset(hWnd, L_LIST);
+
+ b = LvInsertStart();
+
+ for (i = 0;i < LIST_NUM(sw->ComponentList);i++)
+ {
+ SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i);
+
+ if (c->Detected)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniFormat(tmp, sizeof(tmp), L" %s", c->Title);
+
+ LvInsertAdd(b, c->Icon, c, 1, tmp);
+
+ if (c->SystemModeOnly == false || MsIsAdmin())
+ {
+ if (default_select == NULL)
+ {
+ default_select = c;
+ }
+ }
+ }
+ }
+
+ LvInsertEnd(b, hWnd, L_LIST);
+
+ if (sw->CurrentComponent == NULL)
+ {
+ LvSelectByParam(hWnd, L_LIST, default_select);
+ }
+ else
+ {
+ LvSelectByParam(hWnd, L_LIST, sw->CurrentComponent);
+ }
+
+ Focus(hWnd, L_LIST);
+}
+
+// Update the Component Selection screen
+void SwComponentsUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page)
+{
+ SW_COMPONENT *c;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL)
+ {
+ return;
+ }
+
+ c = (SW_COMPONENT *)LvGetSelectedParam(hWnd, L_LIST);
+
+ if (c == NULL)
+ {
+ Hide(hWnd, S_TITLE);
+ Hide(hWnd, S_DESCRIPTION);
+ Hide(hWnd, S_ICON);
+
+ SetWizardButton(wizard_page, false, true, true, false);
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ if (c->SystemModeOnly && MsIsAdmin() == false)
+ {
+ // Components to be installed only in system mode is set to unselectable
+ SetText(hWnd, S_TITLE, _UU("SW_COMPONENTS_REQUIRE_ADMIN"));
+ UniFormat(tmp, sizeof(tmp), _UU("SW_COMPONENTS_REQUIRE_ADMIN_TEXT"), c->Title);
+ SetText(hWnd, S_DESCRIPTION, tmp);
+ SetIcon(hWnd, S_ICON, ICO_WARNING);
+
+ SetWizardButton(wizard_page, false, true, true, false);
+ }
+ else
+ {
+ // Show the description of the component
+ UniFormat(tmp, sizeof(tmp), _UU("SW_COMPONENTS_ABOUT_TAG"), c->Title);
+ SetText(hWnd, S_TITLE, tmp);
+ SetText(hWnd, S_DESCRIPTION, c->Description);
+ SetIcon(hWnd, S_ICON, c->Icon);
+
+ SetWizardButton(wizard_page, true, true, true, false);
+ }
+
+ Show(hWnd, S_TITLE);
+ Show(hWnd, S_DESCRIPTION);
+ Show(hWnd, S_ICON);
+ }
+}
+
+// Component selection screen
+UINT SwComponents(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ NMHDR *n;
+ SW_COMPONENT *c;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ LvInitEx2(hWnd, L_LIST, false, true);
+
+ if (MsIsVista())
+ {
+ SetFont(hWnd, L_LIST, GetMeiryoFontEx(12));
+ SetFont(hWnd, S_TITLE, GetMeiryoFontEx(11));
+ }
+ else
+ {
+ DlgFont(hWnd, L_LIST, 12, false);
+ DlgFont(hWnd, S_TITLE, 11, false);
+ }
+
+ LvInsertColumn(hWnd, L_LIST, 0, L"Component", 515);
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, true, true, false);
+
+ SwComponentsInit(hWnd, sw);
+
+ SwComponentsUpdate(hWnd, sw, wizard, wizard_page);
+
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ c = (SW_COMPONENT *)LvGetSelectedParam(hWnd, L_LIST);
+
+ if (c != NULL)
+ {
+ if (SwCheckOs(sw, c) == false)
+ {
+ // OS Check Failed
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_OS_FAILED"), c->Title);
+ break;
+ }
+
+ sw->CurrentComponent = c;
+
+ if (sw->CurrentComponent->SystemModeOnly == false || MsIsAdmin())
+ {
+ if (sw->CurrentComponent->Id == SW_CMP_VPN_SERVER && MsIsServiceInstalled(GC_SVC_NAME_VPNBRIDGE))
+ {
+ // The user is trying to install the VPN Server but, VPN Bridge already exists
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_NOTICE_VPNBRIDGE_IS_INSTALLED")) == IDNO)
+ {
+ break;
+ }
+ }
+ else if (sw->CurrentComponent->Id == SW_CMP_VPN_BRIDGE && MsIsServiceInstalled(GC_SVC_NAME_VPNSERVER))
+ {
+ // The user is trying to install the VPN Bridge, but a VPN Server already exists
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_NOTICE_VPNSERVER_IS_INSTALLED")) == IDNO)
+ {
+ break;
+ }
+ }
+
+ // Continue
+ return D_SW_EULA;
+ }
+ }
+ break;
+
+ case WM_WIZ_BACK:
+ if (MsIsAdmin())
+ {
+ return D_SW_WELCOME;
+ }
+ else
+ {
+ return D_SW_MODE;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+
+ switch (n->idFrom)
+ {
+ case L_LIST:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ SwComponentsUpdate(hWnd, sw, wizard, wizard_page);
+ break;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+// Screen that is displayed when the user don't have administrative privileges
+UINT SwNotAdminDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ FormatText(hWnd, S_INFO, MsGetUserNameW());
+
+ SetShow(hWnd, S_INFO2, (sw->UninstallMode ? false : true));
+
+ SetWizardButton(wizard_page, true, ((sw->UninstallMode && sw->IsReExecForUac) ? false : true), true, true);
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ break;
+
+ case WM_WIZ_BACK:
+ if (sw->UninstallMode == false)
+ {
+ return D_SW_MODE;
+ }
+ else
+ {
+ return D_SW_UNINST1;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Choose the setup mode
+UINT SwModeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ SetWizardButton(wizard_page, true, true, true, false);
+ FormatText(hWnd, S_USER, MsGetUserNameW());
+
+ // Choose the initial state
+ Check(hWnd, R_SYSTEM, sw->IsSystemMode);
+ Check(hWnd, R_USER, !sw->IsSystemMode);
+
+ Focus(hWnd, (sw->IsSystemMode ? R_SYSTEM : R_USER));
+
+ sw->DoubleClickBlocker = false;
+ SetUacIcon(hWnd, S_UAC);
+
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ // Mode
+ sw->IsSystemMode = IsChecked(hWnd, R_SYSTEM);
+
+ if (sw->DoubleClickBlocker)
+ {
+ break;
+ }
+
+ sw->DoubleClickBlocker = true;
+
+ if (sw->IsSystemMode)
+ {
+ if (MsIsVista() && MsIsAdmin() == false && sw->IsReExecForUac == false)
+ {
+ // If UAC is available and this isn't invoked via UAC,
+ // give the user a chance to get administrator privileges on UAC start again
+ if (SwReExecMyself(sw, NULL, true))
+ {
+ // Terminate itself if it succeeds to start the child process
+ CloseWizard(wizard_page);
+ }
+ else
+ {
+ // Jump to screen prompts to re-start as a administrator if it fails to start the child process
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ if (MsIsAdmin())
+ {
+ // Jump to the component list screen if the user has administrator privileges
+ return D_SW_COMPONENTS;
+ }
+ else
+ {
+ // Jump to screen prompts to re-start as a administrator if the user doesn't have administrator privileges
+ return D_SW_NOT_ADMIN;
+ }
+ }
+ }
+ else
+ {
+ // Jump to the component list screen
+ return D_SW_COMPONENTS;
+ }
+
+ break;
+
+ case WM_WIZ_BACK:
+ return D_SW_WELCOME;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Welcome screen
+UINT SwWelcomeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param)
+{
+ SW *sw = (SW *)param;
+ // Validate arguments
+ if (hWnd == NULL || sw == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_WIZ_SHOW:
+ DlgFont(hWnd, S_WELCOME, 10, false);
+ DlgFont(hWnd, S_TITLE, 11, true);
+ SetWizardButtonEx(wizard_page, true, false, true, false, true);
+
+ sw->DoubleClickBlocker = false;
+
+ break;
+
+ case WM_WIZ_HIDE:
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_WIZ_NEXT:
+ if (IsFileExistsW(L"@install_src.dat") == false)
+ {
+ // Vpnsetup.exe is launched from other than the installation source
+ MsgBoxEx(hWnd, MB_ICONSTOP, _UU("SW_NOT_INSTALL_SRC"));
+ break;
+ }
+
+ if (sw->DoubleClickBlocker)
+ {
+ break;
+ }
+
+ sw->DoubleClickBlocker = true;
+
+ if (MsIsAdmin() == false)
+ {
+ if (MsIsVista())
+ {
+ if (sw->IsReExecForUac == false)
+ {
+ // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run
+ if (SwReExecMyself(sw, NULL, true))
+ {
+ // Terminate itself if it succeeds to start the child process
+ CloseWizard(wizard_page);
+ break;
+ }
+ else
+ {
+ // Jump to mode selection screen if it fails to start the
+ // child process (including user presses the cancel of UAC)
+ return D_SW_MODE;
+ }
+ }
+ else
+ {
+ // Jump to mode selection screen when the user don't have Admin rights after being activated by UAC
+ return D_SW_MODE;
+ }
+ }
+ else
+ {
+ // Jump to the mode selection screen in the case of older than Vista
+ return D_SW_MODE;
+ }
+ }
+ else
+ {
+ // Skip to the component list screen if the user has Admin privileges
+ return D_SW_COMPONENTS;
+ }
+ break;
+
+ case WM_WIZ_BACK:
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Restart itself
+bool SwReExecMyself(SW *sw, wchar_t *additional_params, bool as_admin)
+{
+ wchar_t *current_params;
+ wchar_t new_param[MAX_SIZE];
+ void *handle;
+ bool ret = false;
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return false;
+ }
+ if (sw->ReExecProcessHandle != NULL)
+ {
+ return false;
+ }
+
+ current_params = GetCommandLineUniStr();
+
+ if (IsEmptyUniStr(additional_params))
+ {
+ additional_params = L"";
+ }
+
+ UniFormat(new_param, sizeof(new_param), L"%s %s %s", current_params, (as_admin ? L"/UAC:true" : L""), additional_params);
+
+ UniTrim(new_param);
+
+ handle = NULL;
+ ret = MsExecuteEx2W(MsGetExeFileNameW(), new_param, &handle, as_admin);
+
+ Free(current_params);
+
+ if (ret == false)
+ {
+ return false;
+ }
+
+ sw->ReExecProcessHandle = handle;
+
+ return true;
+}
+
+// Show the UI
+void SwUiMain(SW *sw)
+{
+ WIZARD *w;
+ wchar_t verstr[MAX_SIZE];
+ char ver[MAX_SIZE];
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ // Define the wizard UI
+ GetCedarVersion(ver, sizeof(ver));
+ UniFormat(verstr, sizeof(verstr), _UU("SW_TITLE"), ver);
+
+ // DO NOT REMOVE THIS INDICATION !!!
+ UniStrCat(verstr, sizeof(verstr), L" - Customized Version");
+
+ w = NewWizard(ICO_SETUP, BMP_SELOGO49x49, verstr, sw);
+
+ w->CloseConfirmMsg = _UU("SW_EXIT_CONFIRM");
+
+ AddWizardPage(w, NewWizardPage(D_SW_WELCOME, SwWelcomeDlg, _UU("SW_WELCOME_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_MODE, SwModeDlg, _UU("SW_MODE_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_NOT_ADMIN, SwNotAdminDlg, _UU("SW_NOT_ADMIN_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_COMPONENTS, SwComponents, _UU("SW_COMPONENTS_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_EULA, SwEula, _UU("SW_EULA_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_WARNING, SwWarning, _UU("SW_WARNING_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_DIR, SwDir, _UU("SW_DIR_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_READY, SwReady, _UU("SW_READY_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_PERFORM, SwPerform, _UU("SW_PERFORM_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_ERROR, SwError, _UU("SW_ERROR_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_FINISH, SwFinish, _UU("SW_FINISH_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_UNINST1, SwUninst1, _UU("SW_UNINST1_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_LANG1, SwLang1, _UU("SW_LANG1_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_EASY1, SwEasy1, _UU("SW_EASY1_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_EASY2, SwEasy2, _UU("SW_EASY2_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_WEB1, SwWeb1, _UU("SW_WEB1_TITLE")));
+ AddWizardPage(w, NewWizardPage(D_SW_WEB2, SwWeb2, _UU("SW_WEB2_TITLE")));
+
+ if (MsIsVista())
+ {
+ w->IsAreoStyle = true;
+ }
+
+ if (sw->UninstallMode)
+ {
+ // Uninstall mode
+ UINT start_page = D_SW_UNINST1;
+
+ if (sw->IsReExecForUac)
+ {
+ // In the case of this have been executed for UAC
+ if (MsIsAdmin())
+ {
+ // Uninstall
+ start_page = D_SW_PERFORM;
+ }
+ else
+ {
+ // Error screen
+ start_page = D_SW_NOT_ADMIN;
+ }
+ }
+
+ ShowWizard(NULL, w, start_page);
+ }
+ else if (sw->WebMode)
+ {
+ // Web installer creation mode
+ UINT start_page = D_SW_WEB1;
+
+ ShowWizard(NULL, w, start_page);
+ }
+ else if (sw->EasyMode)
+ {
+ // Simple installer creation mode
+ UINT start_page = D_SW_EASY1;
+
+ ShowWizard(NULL, w, start_page);
+ }
+ else if (sw->LanguageMode)
+ {
+ // Language setting mode
+ UINT start_page = D_SW_LANG1;
+
+ w->CloseConfirmMsg = NULL;
+
+ if (sw->IsReExecForUac)
+ {
+ // In the case of this have been executed for UAC
+ if (MsIsAdmin())
+ {
+ // Do the language setting
+ start_page = D_SW_PERFORM;
+ }
+ else
+ {
+ // Error screen
+ start_page = D_SW_NOT_ADMIN;
+ }
+ }
+ else
+ {
+ if (sw->LangNow)
+ {
+ // If not via UAC but Lang Now is set
+ start_page = D_SW_PERFORM;
+ }
+ }
+
+ if (sw->SetLangAndReboot && sw->LangNow == false)
+ {
+ // Restart myself immediately by changing the lang.config
+ LIST *o = LoadLangList();
+
+ if (o == NULL)
+ {
+ MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED"));
+ }
+ else
+ {
+ LANGLIST *new_lang = GetLangById(o, sw->LangId);
+ LANGLIST old_lang;
+
+ Zero(&old_lang, sizeof(old_lang));
+ GetCurrentLang(&old_lang);
+
+ if (new_lang == NULL)
+ {
+ MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED"));
+ }
+ else
+ {
+ if (SaveLangConfigCurrentDir(new_lang->Name) == false)
+ {
+ MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_SET_FAILED"));
+ }
+ else
+ {
+ if (SwReExecMyself(sw, L"/LANGNOW:true ", false) == false)
+ {
+ SaveLangConfigCurrentDir(old_lang.Name);
+
+ MsgBox(NULL, MB_ICONSTOP, _UU("SW_CHILD_PROCESS_ERROR"));
+
+ sw->ExitCode = SW_EXIT_CODE_INTERNAL_ERROR;
+ }
+ }
+ }
+
+ FreeLangList(o);
+ }
+ }
+ else
+ {
+ // Show the wizard
+ ShowWizard(NULL, w, start_page);
+ }
+ }
+ else
+ {
+ // Installation mode
+ UINT start_page = D_SW_WELCOME;
+
+ if (sw->IsReExecForUac)
+ {
+ // In the case of this have been executed for UAC
+ if (MsIsAdmin())
+ {
+ // Jump to component list if the user have system administrator privileges
+ start_page = D_SW_COMPONENTS;
+ }
+ else
+ {
+ // Jump to the setup mode selection screen when fail
+ // to get admin privileges even executed by enabling UAC
+ start_page = D_SW_MODE;
+ }
+ }
+
+ ShowWizard(NULL, w, start_page);
+
+ if (sw->Run)
+ {
+ // Auto run the app
+ wchar_t tmp[MAX_PATH];
+ HANDLE h;
+ UNI_TOKEN_LIST *t;
+
+ t = UniParseToken(sw->CurrentComponent->StartExeName, L" ");
+
+ if (t != NULL)
+ {
+ wchar_t exe[MAX_PATH];
+ wchar_t arg[MAX_PATH];
+
+ Zero(exe, sizeof(exe));
+ Zero(arg, sizeof(arg));
+
+ if (t->NumTokens >= 1)
+ {
+ UniStrCpy(exe, sizeof(exe), t->Token[0]);
+ }
+ if (t->NumTokens >= 2)
+ {
+ UniStrCpy(arg, sizeof(arg), t->Token[1]);
+ }
+
+ if (UniIsEmptyStr(exe) == false)
+ {
+ CombinePathW(tmp, sizeof(tmp), sw->InstallDir, exe);
+
+ h = MsRunAsUserExW(tmp, arg, false);
+ if (h != NULL)
+ {
+ CloseHandle(h);
+ }
+ }
+
+ UniFreeToken(t);
+ }
+ }
+ }
+
+ FreeWizard(w);
+}
+
+// Release the component
+void SwFreeComponent(SW_COMPONENT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ FreeStrList(c->NeedFiles);
+ Free(c->Name);
+ Free(c->SvcName);
+ Free(c->LongName);
+ Free(c->Title);
+ Free(c->Description);
+ Free(c->DefaultDirName);
+ Free(c->SvcFileName);
+ Free(c->StartExeName);
+ Free(c->StartDescription);
+
+ Free(c);
+}
+
+// Create a component
+SW_COMPONENT *SwNewComponent(char *name, char *svc_name, UINT id, UINT icon, UINT icon_index, wchar_t *svc_filename,
+ wchar_t *long_name, bool system_mode_only, UINT num_files, char *files[],
+ wchar_t *start_exe_name, wchar_t *start_description,
+ SW_OLD_MSI *old_msis, UINT num_old_msis)
+{
+ SW_COMPONENT *c;
+ UINT i;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL || files == NULL || long_name == NULL)
+ {
+ return NULL;
+ }
+ if (svc_name == NULL)
+ {
+ svc_name = name;
+ }
+
+ c = ZeroMalloc(sizeof(SW_COMPONENT));
+
+ c->Id = id;
+
+ c->NeedFiles = NewListFast(NULL);
+
+ for (i = 0;i < num_files;i++)
+ {
+ Add(c->NeedFiles, CopyStr(files[i]));
+ }
+
+ c->SystemModeOnly = system_mode_only;
+ c->Name = CopyStr(name);
+ c->SvcName = CopyStr(svc_name);
+ c->DefaultDirName = CopyUniStr(long_name);
+ c->LongName = CopyUniStr(long_name);
+
+ Format(tmp, sizeof(tmp), "SW_COMPONENT_%s_TITLE", name);
+ c->Title = CopyUniStr(_UU(tmp));
+
+ Format(tmp, sizeof(tmp), "SW_COMPONENT_%s_DESCRIPTION", name);
+ c->Description = CopyUniStr(_UU(tmp));
+
+ c->Icon = icon;
+ c->IconExeIndex = icon_index;
+
+ if (UniIsEmptyStr(svc_filename) == false)
+ {
+ c->InstallService = true;
+ c->SvcFileName = UniCopyStr(svc_filename);
+ }
+
+ if (UniIsEmptyStr(start_exe_name) == false && UniIsEmptyStr(start_description) == false)
+ {
+ c->StartExeName = UniCopyStr(start_exe_name);
+ c->StartDescription = UniCopyStr(start_description);
+ }
+
+ c->OldMsiList = old_msis;
+ c->NumOldMsi = num_old_msis;
+
+ return c;
+}
+
+// Examine the OS requirements
+bool SwCheckOs(SW *sw, SW_COMPONENT *c)
+{
+ // Validate arguments
+ if (sw == NULL || c == NULL)
+ {
+ return false;
+ }
+
+ if (c->Id == SW_CMP_VPN_CLIENT)
+ {
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (MsIsWin2000OrGreater() == false)
+ {
+ // It doesn't work with WinNT 4.0
+ return false;
+ }
+ }
+ else
+ {
+ if (GET_KETA(info->OsType, 100) <= 1)
+ {
+ // It doesn't work with Win95
+ return false;
+ }
+ else if (info->OsType == OSTYPE_WINDOWS_98)
+ {
+ if (EndWith(info->OsVersion, "A") == false)
+ {
+ // It doesn't work in Win98 First Edition
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Define the component
+void SwDefineComponents(SW *sw)
+{
+ SW_COMPONENT *c;
+ char *vpn_server_files[] =
+ {
+ "vpnserver.exe",
+ "vpnserver_x64.exe",
+ "vpnsmgr.exe",
+ "vpnsmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+ };
+ char *vpn_client_files[] =
+ {
+ "vpnclient.exe",
+ "vpnclient_x64.exe",
+ "vpncmgr.exe",
+ "vpncmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+ "vpninstall.exe",
+ "vpnweb.cab",
+ };
+ char *vpn_bridge_files[] =
+ {
+ "vpnbridge.exe",
+ "vpnbridge_x64.exe",
+ "vpnsmgr.exe",
+ "vpnsmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+ };
+ char *vpn_smgr_files[] =
+ {
+ "vpnsmgr.exe",
+ "vpnsmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+ };
+ char *vpn_cmgr_files[] =
+ {
+ "vpncmgr.exe",
+ "vpncmgr_x64.exe",
+ "vpncmd.exe",
+ "vpncmd_x64.exe",
+ "hamcore.se2",
+ };
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ // VPN Server
+ c = SwNewComponent(SW_NAME_VPNSERVER, GC_SVC_NAME_VPNSERVER, SW_CMP_VPN_SERVER, ICO_VPNSERVER, 5, (MsIsX64() ? L"vpnserver_x64.exe" : L"vpnserver.exe"),
+ SW_LONG_VPNSERVER, false, sizeof(vpn_server_files) / sizeof(char *), vpn_server_files,
+ (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"),
+ old_msi_vpnserver, sizeof(old_msi_vpnserver) / sizeof(SW_OLD_MSI));
+ Add(sw->ComponentList, c);
+
+ // VPN Client
+ c = SwNewComponent(SW_NAME_VPNCLIENT, GC_SVC_NAME_VPNCLIENT, SW_CMP_VPN_CLIENT, ICO_VPN, 6, (MsIsX64() ? L"vpnclient_x64.exe" : L"vpnclient.exe"),
+ SW_LONG_VPNCLIENT, true, sizeof(vpn_client_files) / sizeof(char *), vpn_client_files,
+ (MsIsX64() ? L"vpncmgr_x64.exe" : L"vpncmgr.exe"), _UU("SW_RUN_TEXT_VPNCMGR"),
+ old_msi_vpnclient, sizeof(old_msi_vpnclient) / sizeof(SW_OLD_MSI));
+
+#ifdef GC_ENABLE_VPNGATE
+#endif // GC_ENABLE_VPNGATE
+
+ Add(sw->ComponentList, c);
+
+ // VPN Bridge
+ c = SwNewComponent(SW_NAME_VPNBRIDGE, GC_SVC_NAME_VPNBRIDGE, SW_CMP_VPN_BRIDGE, ICO_CASCADE, 7, (MsIsX64() ? L"vpnbridge_x64.exe" : L"vpnbridge.exe"),
+ SW_LONG_VPNBRIDGE, false, sizeof(vpn_bridge_files) / sizeof(char *), vpn_bridge_files,
+ (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"),
+ old_msi_vpnbridge, sizeof(old_msi_vpnbridge) / sizeof(SW_OLD_MSI));
+ Add(sw->ComponentList, c);
+
+ // VPN Server Manager (Tools Only)
+ c = SwNewComponent(SW_NAME_VPNSMGR, NULL, SW_CMP_VPN_SMGR, ICO_USER_ADMIN, 8, NULL,
+ SW_LONG_VPNSMGR, false, sizeof(vpn_smgr_files) / sizeof(char *), vpn_smgr_files,
+ (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"),
+ NULL, 0);
+ Add(sw->ComponentList, c);
+
+ // VPN Client Manager (Tools Only)
+ c = SwNewComponent(SW_NAME_VPNCMGR, NULL, SW_CMP_VPN_CMGR, ICO_INTERNET, 9, NULL,
+ SW_LONG_VPNCMGR, false, sizeof(vpn_cmgr_files) / sizeof(char *), vpn_cmgr_files,
+ (MsIsX64() ? L"vpncmgr_x64.exe /remote" : L"vpncmgr.exe /remote"), _UU("SW_RUN_TEXT_VPNCMGR"),
+ NULL, 0);
+ Add(sw->ComponentList, c);
+}
+
+// Detect the available components
+void SwDetectComponents(SW *sw)
+{
+ UINT i;
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(sw->ComponentList);i++)
+ {
+ SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i);
+
+ c->Detected = SwIsComponentDetected(sw, c);
+ }
+
+ // Determine whether the automatic connection configuration file exists in the same directory
+ if (true)
+ {
+ wchar_t tmp[MAX_PATH];
+
+ ConbinePathW(tmp, sizeof(tmp), MsGetExeDirNameW(), SW_AUTO_CONNECT_ACCOUNT_FILE_NAME_W);
+
+ if (IsFileExistsW(tmp))
+ {
+ // Exist
+ UniStrCpy(sw->auto_setting_path, sizeof(sw->auto_setting_path), tmp);
+ }
+ }
+}
+
+// Determine whether detection of the component is successful
+bool SwIsComponentDetected(SW *sw, SW_COMPONENT *c)
+{
+ UINT i;
+ bool ret = true;
+ // Validate arguments
+ if (sw == NULL || c == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(c->NeedFiles);i++)
+ {
+ char *name = LIST_DATA(c->NeedFiles, i);
+ wchar_t name_w[MAX_SIZE];
+ wchar_t fullpath[MAX_SIZE];
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ CombinePathW(fullpath, sizeof(fullpath), sw->InstallSrc, name_w);
+
+ if (IsFileExistsW(fullpath) == false)
+ {
+ ret = false;
+ break;
+ }
+ }
+
+ if (c->InstallService == false)
+ {
+ if (sw->IsEasyInstaller || sw->IsWebInstaller)
+ {
+ // Prevent installing only management tool
+ // for Web installer or a simple installer
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+// Add a new log
+void SwAddLog(SW *sw, SW_LOGFILE *logfile, UINT type, wchar_t *path)
+{
+ SW_LOG *g;
+ // Validate arguments
+ if (sw == NULL || path == NULL || logfile == NULL)
+ {
+ return;
+ }
+
+ g = ZeroMalloc(sizeof(SW_LOG));
+ g->Type = type;
+ UniStrCpy(g->Path, sizeof(g->Path), path);
+
+ Add(logfile->LogList, g);
+}
+void SwAddLogA(SW *sw, SW_LOGFILE *logfile, UINT type, char *path)
+{
+ wchar_t *w;
+ // Validate arguments
+ if (sw == NULL || path == NULL || logfile == NULL)
+ {
+ return;
+ }
+
+ w = CopyStrToUni(path);
+
+ SwAddLog(sw, logfile, type, w);
+
+ Free(w);
+}
+
+// Create a SW
+SW *NewSw()
+{
+ SW *sw = ZeroMalloc(sizeof(SW));
+
+ sw->IsSystemMode = true;
+
+ sw->ComponentList = NewListFast(NULL);
+
+ sw->ExitCode = SW_EXIT_CODE_USER_CANCEL;
+
+ UniStrCpy(sw->InstallSrc, sizeof(sw->InstallSrc), MsGetExeDirNameW());
+
+ SwDefineComponents(sw);
+
+ return sw;
+}
+
+// Release the SW
+UINT FreeSw(SW *sw)
+{
+ UINT i;
+ UINT ret;
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return SW_EXIT_CODE_INTERNAL_ERROR;
+ }
+
+ SwLeaveSingle(sw);
+
+ for (i = 0;i < LIST_NUM(sw->ComponentList);i++)
+ {
+ SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i);
+
+ SwFreeComponent(c);
+ }
+
+ ReleaseList(sw->ComponentList);
+
+ SwFreeLogFile(sw->LogFile);
+
+ if (sw->ReExecProcessHandle != NULL)
+ {
+ // If you have started the child process, wait for the termination of child process
+ sw->ExitCode = MsWaitProcessExit(sw->ReExecProcessHandle);
+ }
+
+ ret = sw->ExitCode;
+
+ Free(sw);
+
+ return ret;
+}
+
+// Exit the multi-starts prevention mode
+void SwLeaveSingle(SW *sw)
+{
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ if (sw->Single != NULL)
+ {
+ FreeSingleInstance(sw->Single);
+ sw->Single = NULL;
+ }
+}
+
+// Enter multiple-starts prevention mode
+bool SwEnterSingle(SW *sw)
+{
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return false;
+ }
+
+ if (sw->Single != NULL)
+ {
+ return true;
+ }
+
+ sw->Single = NewSingleInstance(SW_SINGLE_INSTANCE_NAME);
+
+ if (sw->Single == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Parse the command line
+void SwParseCommandLine(SW *sw)
+{
+ CONSOLE *c;
+ wchar_t *cmdline;
+ LIST *o;
+ PARAM args[] =
+ {
+ {"UAC", NULL, NULL, NULL, NULL, },
+ {"LANGUAGE", NULL, NULL, NULL, NULL, },
+ {"LANGID", NULL, NULL, NULL, NULL, },
+ {"LANGNOW", NULL, NULL, NULL, NULL, },
+ {"SETLANGANDREBOOT", NULL, NULL, NULL, NULL, },
+ {"EASY", NULL, NULL, NULL, NULL, },
+ {"WEB", NULL, NULL, NULL, NULL, },
+ {"SFXMODE", NULL, NULL, NULL, NULL, },
+ {"SFXOUT", NULL, NULL, NULL, NULL, },
+ {"HIDESTARTCOMMAND", NULL, NULL, NULL, NULL, },
+ {"CALLERSFXPATH", NULL, NULL, NULL, NULL, },
+ {"ISEASYINSTALLER", NULL, NULL, NULL, NULL, },
+ {"DISABLEAUTOIMPORT", NULL, NULL, NULL, NULL, },
+ {"ISWEBINSTALLER", NULL, NULL, NULL, NULL, },
+ };
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ c = NewLocalConsole(NULL, NULL);
+ if (c == NULL)
+ {
+ return;
+ }
+
+ cmdline = GetCommandLineUniStr();
+
+ if (UniIsEmptyStr(cmdline) == false)
+ {
+ o = ParseCommandList(c, "setup", cmdline, args, sizeof(args) / sizeof(args[0]));
+
+ if (o != NULL)
+ {
+ sw->IsReExecForUac = GetParamYes(o, "UAC");
+ sw->LanguageMode = GetParamYes(o, "LANGUAGE");
+ sw->LangId = GetParamInt(o, "LANGID");
+ sw->LangNow = GetParamYes(o, "LANGNOW");
+ sw->SetLangAndReboot = GetParamYes(o, "SETLANGANDREBOOT");
+ sw->HideStartCommand = GetParamYes(o, "HIDESTARTCOMMAND");
+
+ // Special mode
+ if (sw->LanguageMode == false)
+ {
+ sw->EasyMode = GetParamYes(o, "EASY");
+
+ if (sw->EasyMode == false)
+ {
+ sw->WebMode = GetParamYes(o, "WEB");
+ }
+ }
+
+ StrCpy(sw->SfxMode, sizeof(sw->SfxMode), GetParamStr(o, "SFXMODE"));
+ UniStrCpy(sw->SfxOut, sizeof(sw->SfxOut), GetParamUniStr(o, "SFXOUT"));
+ UniStrCpy(sw->CallerSfxPath, sizeof(sw->CallerSfxPath), GetParamUniStr(o, "CALLERSFXPATH"));
+ sw->IsEasyInstaller = GetParamYes(o, "ISEASYINSTALLER");
+ sw->IsWebInstaller = GetParamYes(o, "ISWEBINSTALLER");
+ sw->DisableAutoImport = GetParamYes(o, "DISABLEAUTOIMPORT");
+
+ FreeParamValueList(o);
+ }
+ }
+
+ Free(cmdline);
+
+ c->Free(c);
+}
+
+// Start the Setup Wizard
+UINT SWExecMain()
+{
+ SW *sw;
+ UINT ret;
+ SW_LOGFILE *logfile = NULL;
+ wchar_t verstr[MAX_SIZE];
+ char ver[MAX_SIZE];
+
+ // Define the wizard UI
+ GetCedarVersion(ver, sizeof(ver));
+ UniFormat(verstr, sizeof(verstr), _UU("SW_TITLE"), ver);
+
+ InitWinUi(verstr, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ // Create a SW
+ sw = NewSw();
+
+ // Read the setting
+ sw->Easy_EraseSensitive = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EraseSensitive");
+ sw->Easy_EasyMode = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EasyMode");
+ sw->Web_EraseSensitive = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EraseSensitive");
+ sw->Web_EasyMode = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EasyMode");
+
+ // Parse the command line
+ SwParseCommandLine(sw);
+
+ // Test!
+ //sw->WebMode = true;
+
+ // Detect the installable components
+ SwDetectComponents(sw);
+
+ if (IsEmptyStr(sw->SfxMode) == false && UniIsEmptyStr(sw->SfxOut) == false)
+ {
+ // SFX generation mode
+ if (SwGenSfxModeMain(sw->SfxMode, sw->SfxOut))
+ {
+ // Success
+ sw->ExitCode = 0;
+ }
+ }
+ else
+ {
+ // Normal mode
+ // Load setuplog.dat
+ if (IsFileExistsW(L"@" L"setuplog.dat") && (logfile = SwLoadLogFile(sw, L"@" L"setuplog.dat")) == NULL)
+ {
+ // Setuplog.dat is broken
+ MsgBox(NULL, MB_ICONSTOP, _UU("SW_SETUPLOG_CORRUPTED"));
+ }
+ else
+ {
+ sw->LogFile = logfile;
+ if (sw->LogFile == NULL)
+ {
+ // Setuplog.dat does not exist
+ sw->LogFile = SwNewLogFile();
+ }
+ else
+ {
+ // When setuplog.dat exists, it is in either of language-setting-change-mode, simple-installer-creation-mode, uninstall-mode
+ sw->CurrentComponent = sw->LogFile->Component;
+ sw->IsSystemMode = sw->LogFile->IsSystemMode;
+ UniStrCpy(sw->InstallDir, sizeof(sw->InstallDir), MsGetExeDirNameW());
+
+ if (sw->LanguageMode == false && sw->EasyMode == false && sw->WebMode == false)
+ {
+ // Uninstall mode
+ sw->UninstallMode = true;
+ }
+ }
+
+ // UI main
+ SwUiMain(sw);
+ }
+ }
+
+ // Release the SW
+ ret = FreeSw(sw);
+
+ FreeWinUi();
+
+ return ret;
+}
+
+
+#endif // WIN32
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SW.h b/src/Cedar/SW.h
new file mode 100644
index 00000000..45710f99
--- /dev/null
+++ b/src/Cedar/SW.h
@@ -0,0 +1,105 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SW.h
+// Header of SW.c
+
+#ifndef SW_H
+#define SW_H
+
+#define SW_REG_KEY "Software\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings"
+
+
+UINT SWExec();
+UINT SWExecMain();
+LIST *SwNewSfxFileList();
+void SwFreeSfxFileList(LIST *o);
+bool SwAddBasicFilesToList(LIST *o, char *component_name);
+bool SwCompileSfx(LIST *o, wchar_t *dst_filename);
+bool SwGenSfxModeMain(char *mode, wchar_t *dst);
+bool SwWaitForVpnClientPortReady(UINT timeout);
+
+#endif // SW_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SWInner.h b/src/Cedar/SWInner.h
new file mode 100644
index 00000000..a7f56c64
--- /dev/null
+++ b/src/Cedar/SWInner.h
@@ -0,0 +1,425 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SWInner.h
+// Header of SW.c (for internal use)
+
+#ifndef SW_INNER_H
+#define SW_INNER_H
+
+// Component string
+#define SW_NAME_VPNSERVER "vpnserver"
+#define SW_LONG_VPNSERVER _UU("SW_LONG_VPNSERVER")
+
+#define SW_NAME_VPNCLIENT "vpnclient"
+#define SW_LONG_VPNCLIENT _UU("SW_LONG_VPNCLIENT")
+
+#define SW_NAME_VPNBRIDGE "vpnbridge"
+#define SW_LONG_VPNBRIDGE _UU("SW_LONG_VPNBRIDGE")
+
+#define SW_NAME_VPNSMGR "vpnsmgr"
+#define SW_LONG_VPNSMGR _UU("SW_LONG_VPNSMGR")
+
+#define SW_NAME_VPNCMGR "vpncmgr"
+#define SW_LONG_VPNCMGR _UU("SW_LONG_VPNCMGR")
+
+#define SW_VPN_CLIENT_UIHELPER_REGVALUE GC_SW_UIHELPER_REGVALUE
+
+#define SW_VPN_CLIENT_EXT_REGKEY "SOFTWARE\\Classes\\.vpn"
+#define SW_VPN_CLIENT_EXT_REGVALUE "vpnfile"
+#define SW_VPN_CLIENT_EXT_REGKEY_SUB1 "SOFTWARE\\Classes\\.vpn\\vpnfile"
+#define SW_VPN_CLIENT_EXT_REGKEY_SUB2 "SOFTWARE\\Classes\\.vpn\\vpnfile\\ShellNew"
+
+#define SW_VPN_CLIENT_VPNFILE_REGKEY "SOFTWARE\\Classes\\vpnfile"
+#define SW_VPN_CLIENT_VPNFILE_REGVALUE "VPN Client Connection Setting File"
+#define SW_VPN_CLIENT_VPNFILE_ICON_REGKEY "SOFTWARE\\Classes\\vpnfile\\DefaultIcon"
+#define SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY "SOFTWARE\\Classes\\vpnfile\\shell\\open\\command"
+#define SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB1 "SOFTWARE\\Classes\\vpnfile\\shell\\open"
+#define SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB2 "SOFTWARE\\Classes\\vpnfile\\shell"
+
+#define SW_REG_KEY_EULA "Software\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings\\Eula"
+
+
+// Component ID
+#define SW_CMP_VPN_SERVER 1 // VPN Server
+#define SW_CMP_VPN_CLIENT 2 // VPN Client
+#define SW_CMP_VPN_BRIDGE 3 // VPN Bridge
+#define SW_CMP_VPN_SMGR 4 // VPN Server Manager (Tools Only)
+#define SW_CMP_VPN_CMGR 5 // VPN Client Manager (Tools Only)
+
+// Exit code
+#define SW_EXIT_CODE_USER_CANCEL 1000000001 // Cancel by the user
+#define SW_EXIT_CODE_INTERNAL_ERROR 1000000002 // Internal error
+
+// Special messages to be used in the setup wizard
+#define WM_SW_BASE (WM_APP + 251)
+#define WM_SW_INTERACT_UI (WM_SW_BASE + 0) // UI processing
+#define WM_SW_EXIT (WM_SW_BASE + 1) // Close
+
+// Automatic connection setting file
+#define SW_AUTO_CONNECT_ACCOUNT_FILE_NAME "auto_connect.vpn"
+#define SW_AUTO_CONNECT_ACCOUNT_FILE_NAME_W L"auto_connect.vpn"
+
+// Installer cache file to be stored in the VPN Client installation folder
+#define SW_SFX_CACHE_FILENAME L"installer.cache"
+
+// Flag file
+#define SW_FLAG_EASY_MODE "easy_mode.flag"
+#define SW_FLAG_EASY_MODE_2 "@easy_mode.flag"
+
+// Multiple-starts prevention name
+#define SW_SINGLE_INSTANCE_NAME "SoftEther_VPN_Setup_Wizard"
+
+// Time to wait for the VPN Client service startup
+#define SW_VPNCLIENT_SERVICE_WAIT_READY_TIMEOUT (30 * 1000)
+
+// UI interaction
+typedef struct SW_UI
+{
+ UINT Type; // Type
+ wchar_t *Message; // Message string
+ UINT Param; // Parameters
+ UINT RetCode; // Return value
+} SW_UI;
+
+// Type of UI interaction
+#define SW_UI_TYPE_PRINT 0 // Display the message
+#define SW_UI_TYPE_MSGBOX 1 // Show a message box
+#define SW_UI_TYPE_FINISH 2 // Completion
+#define SW_UI_TYPE_ERROR 3 // Error
+
+// Resource type of the file stored in the setup.exe
+#define SW_SFX_RESOURCE_TYPE "DATAFILE"
+
+// Code of old MSI
+typedef struct SW_OLD_MSI
+{
+ char *ProductCode; // Product code
+ char *ComponentCode; // Component code
+} SW_OLD_MSI;
+
+// Component
+typedef struct SW_COMPONENT
+{
+ UINT Id; // ID
+ bool Detected; // Whether it has been detected as an installation source
+ LIST *NeedFiles; // Necessary files
+ char *Name; // Internal name
+ char *SvcName; // Service name
+ wchar_t *Title; // Display name
+ wchar_t *Description; // Detail
+ wchar_t *DefaultDirName; // Installation directory name of the default
+ wchar_t *LongName; // Long name
+ UINT Icon; // Icon
+ UINT IconExeIndex; // The index number of the icon within the Setup.exe
+ bool SystemModeOnly; // Only system mode
+ bool InstallService; // Installation of service
+ wchar_t *SvcFileName; // Service file name
+ wchar_t *StartExeName; // Start EXE file name
+ wchar_t *StartDescription; // Description of the running software
+ SW_OLD_MSI *OldMsiList; // Old MSI Product List
+ UINT NumOldMsi; // The number of old MSI Product List
+ bool CopyVGDat; // Copy of the VPN Gate DAT file
+} SW_COMPONENT;
+
+// File copy task
+typedef struct SW_TASK_COPY
+{
+ wchar_t SrcFileName[MAX_SIZE]; // Original file name
+ wchar_t DstFileName[MAX_SIZE]; // Destination file name
+ wchar_t SrcDir[MAX_SIZE]; // Source directory
+ wchar_t DstDir[MAX_SIZE]; // Destination directory
+ bool Overwrite; // Override flag
+ bool SetupFile; // Setup file flag
+} SW_TASK_COPY;
+
+// Link creation task
+typedef struct SW_TASK_LINK
+{
+ wchar_t TargetDir[MAX_SIZE]; // Target directory
+ wchar_t TargetExe[MAX_SIZE]; // Target EXE file name
+ wchar_t TargetArg[MAX_SIZE]; // Arguments to pass to the target
+ wchar_t IconExe[MAX_SIZE]; // Icon EXE file name
+ UINT IconIndex; // Icon Index number
+ wchar_t DestDir[MAX_SIZE]; // Directory name to be created
+ wchar_t DestName[MAX_SIZE]; // File name to be created
+ wchar_t DestDescription[MAX_SIZE]; // Description string
+ bool NoDeleteDir; // Do not delete the directory on uninstall
+} SW_TASK_LINK;
+
+// Setup Tasks
+typedef struct SW_TASK
+{
+ LIST *CopyTasks; // File copy task
+ LIST *SetSecurityPaths; // List of paths to set the security
+ LIST *LinkTasks; // Link creation task
+} SW_TASK;
+
+// Setup log
+typedef struct SW_LOG
+{
+ UINT Type; // Type of log
+ wchar_t Path[MAX_PATH]; // Path
+} SW_LOG;
+
+// Type of setup log
+#define SW_LOG_TYPE_FILE 1 // File
+#define SW_LOG_TYPE_DIR 2 // Directory
+#define SW_LOG_TYPE_REGISTRY 3 // Registry
+#define SW_LOG_TYPE_LNK 4 // Shortcut file
+#define SW_LOG_TYPE_LNK_DIR 5 // Shortcut directory
+#define SW_LOG_TYPE_SVC 6 // Service
+
+// Setup log files
+typedef struct SW_LOGFILE
+{
+ LIST *LogList; // List of log
+ bool IsSystemMode; // Whether the system mode
+ UINT Build; // Build Number
+ SW_COMPONENT *Component; // Component
+} SW_LOGFILE;
+
+// SFX file
+typedef struct SW_SFX_FILE
+{
+ char InnerFileName[MAX_PATH]; // Internal file name
+ wchar_t DiskFileName[MAX_PATH]; // File name of the disk
+} SW_SFX_FILE;
+
+// SW instance
+typedef struct SW
+{
+ LIST *ComponentList; // List of components
+ wchar_t InstallSrc[MAX_SIZE]; // Source directory
+ bool IsSystemMode; // Whether the system mode
+ bool UninstallMode; // Uninstall mode
+ UINT ExitCode; // Exit code
+ void *ReExecProcessHandle; // Child process handle of a result of the re-run itself
+ bool IsReExecForUac; // Whether the process was re-run for UAC handling
+ SW_COMPONENT *CurrentComponent; // Component that is currently selected
+ bool EulaAgreed; // Whether the user accepted the license agreement
+ bool DoubleClickBlocker; // Double-click blocker
+ bool LanguageMode; // Language setting mode
+ UINT LangId; // Language ID in the language setting mode
+ bool SetLangAndReboot; // Prompt to restart after making the language setting
+ bool LangNow; // Start the language setting process right now
+ bool EasyMode; // Simple installer creation mode
+ bool WebMode; // Web installer creation mode
+ bool OnlyAutoSettingMode; // Apply only mode of connection settings of VPN Client
+
+ INSTANCE *Single; // Multiple-starts check
+ wchar_t DefaultInstallDir_System[MAX_PATH]; // Default system installation directory
+ wchar_t DefaultInstallDir_User[MAX_PATH]; // Default user installation directory
+ bool IsAvailableSystemMode; // Whether the system mode is selectable
+ bool IsAvailableUserMode; // Whether the user mode is selectable
+ bool ShowWarningForUserMode; // Whether to display a warning for the user-mode
+ wchar_t InstallDir[MAX_PATH]; // Destination directory
+ THREAD *PerformThread; // Set up processing thread
+ bool Run; // Whether to start the tool after Setup finishes
+ SW_LOGFILE *LogFile; // Log file
+ bool MsiRebootRequired; // Need to be re-started as a result of MSI
+ bool LangNotChanged; // Language has not changed
+ wchar_t FinishMsg[MAX_SIZE * 2]; // Completion message
+ wchar_t Easy_SettingFile[MAX_PATH]; // Connection settings file name of the Simple installer creation kit:
+ wchar_t Easy_OutFile[MAX_PATH]; // Destination file name of the simple installer creation kit
+ bool Easy_EraseSensitive; // Simple installer creation kit: Delete the confidential information
+ bool Easy_EasyMode; // Simple installer creation kit: simple mode
+ wchar_t Web_SettingFile[MAX_PATH]; // Connection setting file name for the Web installer creation Kit
+ wchar_t Web_OutFile[MAX_PATH]; // Destination file name of the Web installer creation Kit
+ bool Web_EraseSensitive; // Web installer creation Kit: removing confidential information
+ bool Web_EasyMode; // Web installer creation kit: simple mode
+ wchar_t vpncmgr_path[MAX_PATH]; // Path of vpncmgr.exe
+ wchar_t auto_setting_path[MAX_PATH]; // Path of automatic connection setting
+ bool HideStartCommand; // Not to show the option to start the program on installation complete screen
+ char SfxMode[MAX_SIZE]; // SFX generation mode
+ wchar_t SfxOut[MAX_PATH]; // SFX destination
+ wchar_t CallerSfxPath[MAX_PATH]; // Calling SFX path
+ bool IsEasyInstaller; // Whether the calling SFX was built by the simple installer creation kit
+ bool IsWebInstaller; // Whether Web installer
+ bool DisableAutoImport; // Not to use the automatic import process
+ UINT CurrentEulaHash; // Hash of the license agreement
+} SW;
+
+
+// Function prototype
+SW *NewSw();
+UINT FreeSw(SW *sw);
+
+void SwDefineComponents(SW *sw);
+SW_COMPONENT *SwNewComponent(char *name, char *svc_name, UINT id, UINT icon, UINT icon_index, wchar_t *svc_filename,
+ wchar_t *long_name, bool system_mode_only, UINT num_files, char *files[],
+ wchar_t *start_exe_name, wchar_t *start_description,
+ SW_OLD_MSI *old_msis, UINT num_old_msis);
+void SwFreeComponent(SW_COMPONENT *c);
+void SwDetectComponents(SW *sw);
+bool SwIsComponentDetected(SW *sw, SW_COMPONENT *c);
+void SwParseCommandLine(SW *sw);
+SW_COMPONENT *SwFindComponent(SW *sw, char *name);
+
+void SwInitDefaultInstallDir(SW *sw);
+void SwUiMain(SW *sw);
+bool SwCheckNewDirName(wchar_t *name);
+wchar_t *SwGetOldMsiInstalledDir(SW_COMPONENT *c);
+bool SwUninstallOldMsiInstalled(HWND hWnd, WIZARD_PAGE *wp, SW_COMPONENT *c, bool *reboot_required);
+
+bool SwReExecMyself(SW *sw, wchar_t *additional_params, bool as_admin);
+
+SW_TASK *SwNewTask();
+void SwFreeTask(SW_TASK *t);
+SW_TASK_COPY *SwNewCopyTask(wchar_t *srcfilename, wchar_t *dstfilename, wchar_t *srcdir, wchar_t *dstdir, bool overwrite, bool setup_file);
+void SwFreeCopyTask(SW_TASK_COPY *ct);
+void SwDefineTasks(SW *sw, SW_TASK *t, SW_COMPONENT *c);
+SW_TASK_LINK *SwNewLinkTask(wchar_t *target_dir, wchar_t *target_exe, wchar_t *target_arg,
+ wchar_t *icon_exe, UINT icon_index,
+ wchar_t *dest_dir, wchar_t *dest_name, wchar_t *dest_desc,
+ bool no_delete_dir);
+void SwFreeLinkTask(SW_TASK_LINK *lt);
+
+void SwAddLog(SW *sw, SW_LOGFILE *logfile, UINT type, wchar_t *path);
+void SwAddLogA(SW *sw, SW_LOGFILE *logfile, UINT type, char *path);
+bool SwSaveLogFile(SW *sw, wchar_t *dst_name, SW_LOGFILE *logfile);
+SW_LOGFILE *SwLoadLogFile(SW *sw, wchar_t *filename);
+SW_LOGFILE *SwNewLogFile();
+void SwFreeLogFile(SW_LOGFILE *logfile);
+
+void SwInstallShortcuts(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c, SW_TASK *t);
+void SwDeleteShortcuts(SW_LOGFILE *logfile);
+
+bool SwCheckOs(SW *sw, SW_COMPONENT *c);
+
+bool SwEnterSingle(SW *sw);
+void SwLeaveSingle(SW *sw);
+
+UINT SwWelcomeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwModeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwNotAdminDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwComponents(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwComponentsInit(HWND hWnd, SW *sw);
+void SwComponentsUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page);
+UINT SwEula(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwEulaUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page);
+UINT SwDir(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwDirUpdate(HWND hWnd, SW *sw, WIZARD_PAGE *wizard_page);
+UINT SwReady(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwPerform(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwPerformInit(HWND hWnd, SW *sw, WIZARD_PAGE *wp);
+void SwPerformThread(THREAD *thread, void *param);
+void SwPerformPrint(WIZARD_PAGE *wp, wchar_t *str);
+UINT SwPerformMsgBox(WIZARD_PAGE *wp, UINT flags, wchar_t *msg);
+UINT SwInteractUi(WIZARD_PAGE *wp, SW_UI *ui);
+void SwInteractUiCalled(HWND hWnd, SW *sw, WIZARD_PAGE *wp, SW_UI *ui);
+bool SwInstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c);
+UINT SwError(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwFinish(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwUninst1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+bool SwUninstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c);
+UINT SwLang1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwLang1Init(HWND hWnd, SW *sw);
+UINT SwGetLangIcon(char *name);
+void SwLang1Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page);
+UINT SwEasy1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwEasy2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwEasy2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page);
+bool SwEasyMain(SW *sw, WIZARD_PAGE *wp);
+UINT SwWeb1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+UINT SwWeb2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param);
+void SwWeb2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page);
+bool SwWebMain(SW *sw, WIZARD_PAGE *wp);
+
+
+void SwGenerateDefaultSfxFileName(wchar_t *name, UINT size);
+void SwGenerateDefaultZipFileName(wchar_t *name, UINT size);
+
+bool CALLBACK SwEnumResourceNamesProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam);
+
+UINT SwSfxModeMain();
+bool CALLBACK SfxModeMainDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+bool SwSfxExtractProcess(HWND hWnd, bool *hide_error_msg);
+bool SwSfxExtractFile(HWND hWnd, void *data, UINT size, wchar_t *dst, bool compressed);
+SW_SFX_FILE *SwNewSfxFile(char *inner_file_name, wchar_t *disk_file_name);
+bool SwSfxCopyVgFiles(HWND hWnd, wchar_t *src, wchar_t *dst);
+
+#endif // SW_INNER_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Sam.c b/src/Cedar/Sam.c
new file mode 100644
index 00000000..ac0a0ae2
--- /dev/null
+++ b/src/Cedar/Sam.c
@@ -0,0 +1,415 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Sam.c
+// Security Accounts Manager
+
+#include "CedarPch.h"
+
+// Password encryption
+void SecurePassword(void *secure_password, void *password, void *random)
+{
+ BUF *b;
+ // Validate arguments
+ if (secure_password == NULL || password == NULL || random == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, password, SHA1_SIZE);
+ WriteBuf(b, random, SHA1_SIZE);
+ Hash(secure_password, b->Buf, b->Size, true);
+
+ FreeBuf(b);
+}
+
+// Generate 160bit random number
+void GenRamdom(void *random)
+{
+ // Validate arguments
+ if (random == NULL)
+ {
+ return;
+ }
+
+ Rand(random, SHA1_SIZE);
+}
+
+// Anonymous authentication of user
+bool SamAuthUserByAnonymous(HUB *h, char *username)
+{
+ bool b = false;
+ // Validate arguments
+ if (h == NULL || username == NULL)
+ {
+ return false;
+ }
+
+ AcLock(h);
+ {
+ USER *u = AcGetUser(h, username);
+ if (u)
+ {
+ Lock(u->lock);
+ {
+ if (u->AuthType == AUTHTYPE_ANONYMOUS)
+ {
+ b = true;
+ }
+ }
+ Unlock(u->lock);
+ }
+ ReleaseUser(u);
+ }
+ AcUnlock(h);
+
+ return b;
+}
+
+// Plaintext password authentication of user
+bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *password, bool ast, UCHAR *mschap_v2_server_response_20)
+{
+ return false;
+}
+
+// Certificate authentication of user
+bool SamAuthUserByCert(HUB *h, char *username, X *x)
+{
+ return false;
+}
+
+// Get the root certificate that signed the specified certificate from the list
+X *GetIssuerFromList(LIST *cert_list, X *cert)
+{
+ UINT i;
+ X *ret = NULL;
+ // Validate arguments
+ if (cert_list == NULL || cert == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(cert_list);i++)
+ {
+ X *x = LIST_DATA(cert_list, i);
+ // Name comparison
+ if (CheckXDateNow(x))
+ {
+ if (CompareName(x->subject_name, cert->issuer_name))
+ {
+ // Get the public key of the root certificate
+ K *k = GetKFromX(x);
+
+ if (k != NULL)
+ {
+ // Check the signature
+ if (CheckSignature(cert, k))
+ {
+ ret = x;
+ }
+ FreeK(k);
+ }
+ }
+ }
+ if (CompareX(x, cert))
+ {
+ // Complete identical
+ ret = x;
+ }
+ }
+
+ return ret;
+}
+
+// Get the policy to be applied for the user
+POLICY *SamGetUserPolicy(HUB *h, char *username)
+{
+ POLICY *ret = NULL;
+ // Validate arguments
+ if (h == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ AcLock(h);
+ {
+ USER *u;
+ u = AcGetUser(h, username);
+ if (u)
+ {
+ USERGROUP *g = NULL;
+ Lock(u->lock);
+ {
+ if (u->Policy != NULL)
+ {
+ ret = ClonePolicy(u->Policy);
+ }
+
+ g = u->Group;
+
+ if (g != NULL)
+ {
+ AddRef(g->ref);
+ }
+ }
+ Unlock(u->lock);
+
+ ReleaseUser(u);
+ u = NULL;
+
+ if (ret == NULL)
+ {
+ if (g != NULL)
+ {
+ Lock(g->lock);
+ {
+ ret = ClonePolicy(g->Policy);
+ }
+ Unlock(g->lock);
+ }
+ }
+
+ if (g != NULL)
+ {
+ ReleaseGroup(g);
+ }
+ }
+ }
+ AcUnlock(h);
+
+ return ret;
+}
+
+// Password authentication of user
+bool SamAuthUserByPassword(HUB *h, char *username, void *random, void *secure_password, char *mschap_v2_password, UCHAR *mschap_v2_server_response_20, UINT *err)
+{
+ bool b = false;
+ UCHAR secure_password_check[SHA1_SIZE];
+ bool is_mschap = false;
+ IPC_MSCHAP_V2_AUTHINFO mschap;
+ UINT dummy = 0;
+ // Validate arguments
+ if (h == NULL || username == NULL || secure_password == NULL)
+ {
+ return false;
+ }
+ if (err == NULL)
+ {
+ err = &dummy;
+ }
+
+ *err = 0;
+
+ Zero(&mschap, sizeof(mschap));
+
+ is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, mschap_v2_password);
+
+ if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0)
+ {
+ // Administrator mode
+ SecurePassword(secure_password_check, h->SecurePassword, random);
+ if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ AcLock(h);
+ {
+ USER *u;
+ u = AcGetUser(h, username);
+ if (u)
+ {
+ Lock(u->lock);
+ {
+ if (u->AuthType == AUTHTYPE_PASSWORD)
+ {
+ AUTHPASSWORD *auth = (AUTHPASSWORD *)u->AuthData;
+
+ if (is_mschap == false)
+ {
+ // Normal password authentication
+ SecurePassword(secure_password_check, auth->HashedKey, random);
+ if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0)
+ {
+ b = true;
+ }
+ }
+ else
+ {
+ // MS-CHAP v2 authentication via PPP
+ UCHAR challenge8[8];
+ UCHAR client_response[24];
+
+ if (IsZero(auth->NtLmSecureHash, MD5_SIZE))
+ {
+ // NTLM hash is not registered in the user account
+ *err = ERR_MSCHAP2_PASSWORD_NEED_RESET;
+ }
+ else
+ {
+ UCHAR nt_pw_hash_hash[16];
+ Zero(challenge8, sizeof(challenge8));
+ Zero(client_response, sizeof(client_response));
+
+ MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_ServerChallenge,
+ mschap.MsChapV2_PPPUsername);
+
+ MsChapV2Client_GenerateResponse(client_response, challenge8, auth->NtLmSecureHash);
+
+ if (Cmp(client_response, mschap.MsChapV2_ClientResponse, 24) == 0)
+ {
+ // Hash matched
+ b = true;
+
+ // Calculate the response
+ GenerateNtPasswordHashHash(nt_pw_hash_hash, auth->NtLmSecureHash);
+ MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_pw_hash_hash,
+ client_response, challenge8);
+ }
+ }
+ }
+ }
+ }
+ Unlock(u->lock);
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(h);
+
+ return b;
+}
+
+// Make sure that the user exists
+bool SamIsUser(HUB *h, char *username)
+{
+ bool b;
+ // Validate arguments
+ if (h == NULL || username == NULL)
+ {
+ return false;
+ }
+
+ AcLock(h);
+ {
+ b = AcIsUser(h, username);
+ }
+ AcUnlock(h);
+
+ return b;
+}
+
+// Get the type of authentication used by the user
+UINT SamGetUserAuthType(HUB *h, char *username)
+{
+ UINT authtype;
+ // Validate arguments
+ if (h == NULL || username == NULL)
+ {
+ return INFINITE;
+ }
+
+ AcLock(h);
+ {
+ USER *u = AcGetUser(h, username);
+ if (u == NULL)
+ {
+ authtype = INFINITE;
+ }
+ else
+ {
+ authtype = u->AuthType;
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(h);
+
+ return authtype;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Sam.h b/src/Cedar/Sam.h
new file mode 100644
index 00000000..fca9ab84
--- /dev/null
+++ b/src/Cedar/Sam.h
@@ -0,0 +1,106 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Sam.h
+// Header of Sam.c
+
+#ifndef SAM_H
+#define SAM_H
+
+
+// Function prototype
+bool SamIsUser(HUB *h, char *username);
+UINT SamGetUserAuthType(HUB *h, char *username);
+bool SamAuthUserByPassword(HUB *h, char *username, void *random, void *secure_password, char *mschap_v2_password, UCHAR *mschap_v2_server_response_20, UINT *err);
+bool SamAuthUserByAnonymous(HUB *h, char *username);
+bool SamAuthUserByCert(HUB *h, char *username, X *x);
+bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *password, bool ast, UCHAR *mschap_v2_server_response_20);
+POLICY *SamGetUserPolicy(HUB *h, char *username);
+
+void GenRamdom(void *random);
+void SecurePassword(void *secure_password, void *password, void *random);
+X *GetIssuerFromList(LIST *cert_list, X *cert);
+
+#endif // SAM_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SeLowUser.c b/src/Cedar/SeLowUser.c
new file mode 100644
index 00000000..14eb422a
--- /dev/null
+++ b/src/Cedar/SeLowUser.c
@@ -0,0 +1,772 @@
+// SoftEther VPN Source Code
+// SeLow: SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLowUser.c
+// SoftEther Lightweight Network Protocol User-mode Library
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// Install the driver
+bool SuInstallDriver(bool force)
+{
+ bool ret;
+ void *wow;
+
+ wow = MsDisableWow64FileSystemRedirection();
+
+ ret = SuInstallDriverInner(force);
+
+ MsRestoreWow64FileSystemRedirection(wow);
+
+ return ret;
+}
+bool SuInstallDriverInner(bool force)
+{
+ wchar_t sys_fullpath[MAX_PATH];
+ UINT current_sl_ver = 0;
+ bool ret = false;
+ wchar_t src_cat[MAX_PATH];
+ wchar_t src_inf[MAX_PATH];
+ wchar_t src_sys[MAX_PATH];
+ wchar_t dst_cat[MAX_PATH];
+ wchar_t dst_inf[MAX_PATH];
+ wchar_t dst_sys[MAX_PATH];
+ wchar_t tmp_dir[MAX_PATH];
+ char *cpu_type = MsIsX64() ? "x64" : "x86";
+
+ if (SuIsSupportedOs() == false)
+ {
+ // Unsupported OS
+ return false;
+ }
+
+ CombinePathW(tmp_dir, sizeof(tmp_dir), MsGetWindowsDirW(), L"Temp");
+ MakeDirExW(tmp_dir);
+
+ UniStrCat(tmp_dir, sizeof(tmp_dir), L"\\selowtmp");
+ MakeDirExW(tmp_dir);
+
+ // Confirm whether the driver is currently installed
+ CombinePathW(sys_fullpath, sizeof(sys_fullpath), MsGetSystem32DirW(), L"drivers\\SeLow_%S.sys");
+ UniFormat(sys_fullpath, sizeof(sys_fullpath), sys_fullpath, cpu_type);
+
+ if (IsFileExistsW(sys_fullpath))
+ {
+ char *path;
+
+ // Read the current version from the registry
+ current_sl_ver = MsRegReadIntEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, SL_REG_VER_VALUE, false, true);
+
+ path = MsRegReadStrEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, "ImagePath", false, true);
+
+ if (IsEmptyStr(path))
+ {
+ current_sl_ver = 0;
+ }
+
+ Free(path);
+ }
+
+ if (force == false && current_sl_ver >= SL_VER)
+ {
+ // Newer version has already been installed
+ Debug("Newer SeLow is Installed. %u >= %u\n", current_sl_ver, SL_VER);
+ return true;
+ }
+
+ // Copy necessary files to a temporary directory
+ UniFormat(src_sys, sizeof(src_sys), L"|SeLow_%S.sys", cpu_type);
+ UniFormat(src_cat, sizeof(src_cat), L"|inf\\selow_%S\\inf.cat", cpu_type);
+ UniFormat(src_inf, sizeof(src_inf), L"|inf\\selow_%S\\SeLow_%S.inf", cpu_type, cpu_type);
+
+ UniFormat(dst_sys, sizeof(dst_cat), L"%s\\SeLow_%S.sys", tmp_dir, cpu_type);
+ UniFormat(dst_cat, sizeof(dst_cat), L"%s\\inf_selow.cat", tmp_dir);
+ UniFormat(dst_inf, sizeof(dst_inf), L"%s\\SeLow_%S.inf", tmp_dir, cpu_type);
+
+ if (FileCopyW(src_sys, dst_sys) &&
+ FileCopyW(src_cat, dst_cat) &&
+ FileCopyW(src_inf, dst_inf))
+ {
+ NO_WARNING *nw;
+
+ nw = MsInitNoWarningEx(SL_USER_AUTO_PUSH_TIMER);
+
+ // Call the installer
+ if (InstallNdisProtocolDriver(dst_inf, L"SeLow", SL_USER_INSTALL_LOCK_TIMEOUT) == false)
+ {
+ Debug("InstallNdisProtocolDriver Error.\n");
+ }
+ else
+ {
+ Debug("InstallNdisProtocolDriver Ok.\n");
+
+ // Copy manually because there are cases where .sys file is not copied successfully for some reason
+ FileCopyW(src_sys, sys_fullpath);
+
+ ret = true;
+
+ // Write the version number into the registry
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, SL_REG_VER_VALUE, SL_VER, false, true);
+
+ // Set to automatic startup
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, "Start", SERVICE_SYSTEM_START, false, true);
+ }
+
+ MsFreeNoWarning(nw);
+ }
+ else
+ {
+ Debug("Fail Copying Files.\n");
+ }
+
+ if (ret)
+ {
+ // If the service is installed this time, start and wait until the enumeration is completed
+ SuFree(SuInitEx(180 * 1000));
+ }
+
+ return ret;
+}
+
+// Get whether the current OS is supported by SeLow
+bool SuIsSupportedOs()
+{
+ // At present, this doesn't support any OS.
+ return false;
+ //return MsIsWindows7();
+}
+
+// Write the next packet to the driver
+bool SuPutPacket(SU_ADAPTER *a, void *buf, UINT size)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (a->Halt)
+ {
+ return false;
+ }
+ if (size > MAX_PACKET_SIZE)
+ {
+ return false;
+ }
+
+ // First, examine whether the current buffer is full
+ if ((SL_NUM_PACKET(a->PutBuffer) >= SL_MAX_PACKET_EXCHANGE) ||
+ (buf == NULL && SL_NUM_PACKET(a->PutBuffer) != 0))
+ {
+ // Write all current packets to the driver
+ if (SuPutPacketsToDriver(a) == false)
+ {
+ return false;
+ }
+
+ SL_NUM_PACKET(a->PutBuffer) = 0;
+ }
+
+ // Add the next packet to the buffer
+ if (buf != NULL)
+ {
+ UINT i = SL_NUM_PACKET(a->PutBuffer);
+ SL_NUM_PACKET(a->PutBuffer)++;
+
+ SL_SIZE_OF_PACKET(a->PutBuffer, i) = size;
+ Copy(SL_ADDR_OF_PACKET(a->PutBuffer, i), buf, size);
+
+ Free(buf);
+ }
+
+ return true;
+}
+
+// Write all current packets to the driver
+bool SuPutPacketsToDriver(SU_ADAPTER *a)
+{
+ DWORD write_size;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (a->Halt)
+ {
+ return false;
+ }
+
+ if (WriteFile(a->hFile, a->PutBuffer, SL_EXCHANGE_BUFFER_SIZE, &write_size, NULL) == false)
+ {
+ a->Halt = true;
+
+ SuCloseAdapterHandleInner(a);
+ return false;
+ }
+
+ if (write_size != SL_EXCHANGE_BUFFER_SIZE)
+ {
+ a->Halt = true;
+ return false;
+ }
+
+ return true;
+}
+
+// Read the next packet from the driver
+bool SuGetNextPacket(SU_ADAPTER *a, void **buf, UINT *size)
+{
+ // Validate arguments
+ if (a == NULL || buf == NULL || size == NULL)
+ {
+ return false;
+ }
+
+ if (a->Halt)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ if (a->CurrentPacketCount < SL_NUM_PACKET(a->GetBuffer))
+ {
+ // There are still packets that have been already read
+ *size = SL_SIZE_OF_PACKET(a->GetBuffer, a->CurrentPacketCount);
+ *buf = Malloc(*size);
+ Copy(*buf, SL_ADDR_OF_PACKET(a->GetBuffer, a->CurrentPacketCount), *size);
+
+ // Increment the packet number
+ a->CurrentPacketCount++;
+
+ return true;
+ }
+ else
+ {
+ // Read the next packet from the driver
+ if (SuGetPacketsFromDriver(a) == false)
+ {
+ return false;
+ }
+
+ if (SL_NUM_PACKET(a->GetBuffer) == 0)
+ {
+ // Packet is not received yet
+ *buf = NULL;
+ *size = 0;
+ return true;
+ }
+
+ a->CurrentPacketCount = 0;
+ }
+ }
+}
+
+// Read the next packet from the driver
+bool SuGetPacketsFromDriver(SU_ADAPTER *a)
+{
+ DWORD read_size;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ if (a->Halt)
+ {
+ return false;
+ }
+
+ if (ReadFile(a->hFile, a->GetBuffer, SL_EXCHANGE_BUFFER_SIZE, &read_size, NULL) == false)
+ {
+ a->Halt = true;
+
+ SuCloseAdapterHandleInner(a);
+ return false;
+ }
+
+ if (read_size != SL_EXCHANGE_BUFFER_SIZE)
+ {
+ a->Halt = true;
+ return false;
+ }
+
+ return true;
+}
+
+// Close the adapter
+void SuCloseAdapter(SU_ADAPTER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (a->hEvent != NULL)
+ {
+ CloseHandle(a->hEvent);
+ }
+
+ if (a->hFile != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(a->hFile);
+ a->hFile = INVALID_HANDLE_VALUE;
+ }
+
+ Free(a);
+}
+
+// Close the adapter handle
+void SuCloseAdapterHandleInner(SU_ADAPTER *a)
+{
+ return;//////////// ****************
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (a->hFile != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(a->hFile);
+ a->hFile = INVALID_HANDLE_VALUE;
+ }
+}
+
+// Open the adapter
+SU_ADAPTER *SuOpenAdapter(SU *u, char *adapter_id)
+{
+ char filename[MAX_PATH];
+ void *h;
+ SU_ADAPTER *a;
+ SL_IOCTL_EVENT_NAME t;
+ UINT read_size;
+ // Validate arguments
+ if (u == NULL || adapter_id == NULL)
+ {
+ return NULL;
+ }
+
+ Format(filename, sizeof(filename), SL_ADAPTER_DEVICE_FILENAME_WIN32, adapter_id);
+
+ h = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ Debug("Create File %s failed. %u\n", filename, GetLastError());
+ return NULL;
+ }
+ else
+ {
+ Debug("Create File %s ok.\n", filename);
+ }
+
+ a = ZeroMalloc(sizeof(SU_ADAPTER));
+
+ StrCpy(a->AdapterId, sizeof(a->AdapterId), adapter_id);
+ StrCpy(a->DeviceName, sizeof(a->DeviceName), filename);
+
+ a->hFile = h;
+
+ Zero(&t, sizeof(t));
+
+ // Get the event name
+ if (DeviceIoControl(h, SL_IOCTL_GET_EVENT_NAME, &t, sizeof(t), &t, sizeof(t), &read_size, NULL) == false)
+ {
+ // Acquisition failure
+ SuCloseAdapter(a);
+ return NULL;
+ }
+
+ Debug("Event Name: %s\n", t.EventNameWin32);
+
+ // Get the event
+ a->hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, t.EventNameWin32);
+
+ if (a->hEvent == NULL)
+ {
+ // Acquisition failure
+ SuCloseAdapter(a);
+ return NULL;
+ }
+
+ return a;
+}
+
+// Enumerate adapters
+TOKEN_LIST *SuEnumAdapters(SU *u)
+{
+ UINT i;
+ UINT ret_size;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NullToken();
+ }
+
+ Zero(&u->AdapterInfoList, sizeof(u->AdapterInfoList));
+ if (ReadFile(u->hFile, &u->AdapterInfoList, sizeof(u->AdapterInfoList),
+ &ret_size, NULL) == false ||
+ u->AdapterInfoList.Signature != SL_SIGNATURE)
+ {
+ Debug("SuEnumAdapters: ReadFile error.\n");
+ return NullToken();
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+
+ ret->NumTokens = u->AdapterInfoList.NumAdapters;
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ Debug("SuEnumAdapters: u->AdapterInfoList.NumAdapters = %u\n", u->AdapterInfoList.NumAdapters);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyUniToStr(u->AdapterInfoList.Adapters[i].AdapterId);
+
+ UniPrint(L"%s %u %S\n",
+ u->AdapterInfoList.Adapters[i].AdapterId,
+ u->AdapterInfoList.Adapters[i].MtuSize,
+ u->AdapterInfoList.Adapters[i].FriendlyName);
+ }
+
+ return ret;
+}
+
+// Create an adapters list
+LIST *SuGetAdapterList(SU *u)
+{
+ LIST *ret;
+ UINT read_size;
+ UINT i;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewList(SuCmpAdaterList);
+
+ // Enumerate adapters
+ Zero(&u->AdapterInfoList, sizeof(u->AdapterInfoList));
+ if (ReadFile(u->hFile, &u->AdapterInfoList, sizeof(u->AdapterInfoList),
+ &read_size, NULL) == false ||
+ u->AdapterInfoList.Signature != SL_SIGNATURE)
+ {
+ SuFreeAdapterList(ret);
+ return NULL;
+ }
+
+ for (i = 0;i < u->AdapterInfoList.NumAdapters;i++)
+ {
+ SL_ADAPTER_INFO *info = &u->AdapterInfoList.Adapters[i];
+ SU_ADAPTER_LIST *a = SuAdapterInfoToAdapterList(info);
+
+ if (a != NULL)
+ {
+ Add(ret, a);
+ }
+ }
+
+ // Sort
+ Sort(ret);
+
+ return ret;
+}
+
+// Comparison function of the adapter list
+int SuCmpAdaterList(void *p1, void *p2)
+{
+ int r;
+ SU_ADAPTER_LIST *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(SU_ADAPTER_LIST **)p1;
+ a2 = *(SU_ADAPTER_LIST **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+
+ r = StrCmpi(a1->SortKey, a2->SortKey);
+ if (r != 0)
+ {
+ return 0;
+ }
+
+ return StrCmpi(a1->Guid, a2->Guid);
+}
+
+// Release the adapter list
+void SuFreeAdapterList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SU_ADAPTER_LIST *a = LIST_DATA(o, i);
+
+ Free(a);
+ }
+
+ ReleaseList(o);
+}
+
+// Create an adapter list item
+SU_ADAPTER_LIST *SuAdapterInfoToAdapterList(SL_ADAPTER_INFO *info)
+{
+ SU_ADAPTER_LIST t;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (info == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ Copy(&t.Info, info, sizeof(SL_ADAPTER_INFO));
+
+ UniToStr(tmp, sizeof(tmp), info->AdapterId);
+ if (IsEmptyStr(tmp) || IsEmptyStr(info->FriendlyName) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false)
+ {
+ // Name is invalid
+ return NULL;
+ }
+
+ // GUID (Part after "SELOW_A_" prefix)
+ StrCpy(t.Guid, sizeof(t.Guid), tmp + StrLen(SL_ADAPTER_ID_PREFIX));
+
+ // Name
+ StrCpy(t.Name, sizeof(t.Name), tmp);
+
+ // Key for sort
+ if (GetClassRegKeyWin32(t.SortKey, sizeof(t.SortKey), tmp, sizeof(tmp), t.Guid) == false)
+ {
+ // Can not be found
+ return NULL;
+ }
+
+ return Clone(&t, sizeof(t));
+}
+
+// Initialize the driver
+SU *SuInit()
+{
+ return SuInitEx(0);
+}
+SU *SuInitEx(UINT wait_for_bind_complete_tick)
+{
+ void *h;
+ SU *u;
+ UINT read_size;
+ bool flag = false;
+ UINT64 giveup_tick = 0;
+
+ if (SuIsSupportedOs() == false)
+ {
+ // Unsupported OS
+ return NULL;
+ }
+
+LABEL_RETRY:
+
+ // Open the device driver
+ h = CreateFileA(SL_BASIC_DEVICE_FILENAME_WIN32, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ Debug("CreateFileA(%s) Failed.\n", SL_BASIC_DEVICE_FILENAME_WIN32);
+
+ // Start the service if it fails to start the device driver
+ if (flag == false)
+ {
+ if (MsStartService(SL_PROTOCOL_NAME) == false)
+ {
+ Debug("MsStartService(%s) Failed.\n", SL_PROTOCOL_NAME);
+ }
+ else
+ {
+ Debug("MsStartService(%s) Ok.\n", SL_PROTOCOL_NAME);
+ flag = true;
+
+ goto LABEL_RETRY;
+ }
+ }
+ return NULL;
+ }
+
+ //Debug("CreateFileA(%s) Ok.\n", SL_BASIC_DEVICE_FILENAME_WIN32);
+
+ u = ZeroMalloc(sizeof(SU));
+
+ giveup_tick = Tick64() + (UINT64)wait_for_bind_complete_tick;
+
+ if (wait_for_bind_complete_tick == 0)
+ {
+ if (ReadFile(h, &u->AdapterInfoList, sizeof(u->AdapterInfoList), &read_size, NULL) == false ||
+ u->AdapterInfoList.Signature != SL_SIGNATURE)
+ {
+ // Signature reception failure
+ Debug("Bad Signature.\n");
+
+ Free(u);
+ CloseHandle(h);
+
+ return NULL;
+ }
+ }
+ else
+ {
+ while (giveup_tick >= Tick64())
+ {
+ // Wait until the enumeration is completed
+ if (ReadFile(h, &u->AdapterInfoList, sizeof(u->AdapterInfoList), &read_size, NULL) == false ||
+ u->AdapterInfoList.Signature != SL_SIGNATURE)
+ {
+ // Signature reception failure
+ Debug("Bad Signature.\n");
+
+ Free(u);
+ CloseHandle(h);
+
+ return NULL;
+ }
+
+ if (u->AdapterInfoList.EnumCompleted)
+ {
+ // Complete enumeration
+ Debug("Bind Completed! %u\n", u->AdapterInfoList.EnumCompleted);
+ break;
+ }
+
+ // Incomplete enumeration
+ Debug("Waiting for Bind Complete.\n");
+
+ SleepThread(25);
+ }
+ }
+
+ u->hFile = h;
+
+ return u;
+}
+
+// Release the driver
+void SuFree(SU *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(u->hFile);
+
+ Free(u);
+}
+
+#endif // WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SeLowUser.h b/src/Cedar/SeLowUser.h
new file mode 100644
index 00000000..c71e947e
--- /dev/null
+++ b/src/Cedar/SeLowUser.h
@@ -0,0 +1,154 @@
+// SoftEther VPN Source Code
+// SeLow: SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLowUser.h
+// Header for SeLowUser.c
+
+#ifndef SELOWUSER_H
+#define SELOWUSER_H
+
+#include <SeLow/SeLowCommon.h>
+
+//// Macro
+#define SL_USER_INSTALL_LOCK_TIMEOUT 60000 // Lock acquisition timeout
+#define SL_USER_AUTO_PUSH_TIMER 60000 // Timer to start the installation automatically
+
+//// Type
+
+// SU
+struct SU
+{
+ void *hFile; // File handle
+ SL_ADAPTER_INFO_LIST AdapterInfoList; // Adapter list cache
+};
+
+// Adapter
+struct SU_ADAPTER
+{
+ char AdapterId[MAX_PATH]; // Adapter ID
+ char DeviceName[MAX_PATH]; // Device name
+ void *hFile; // File handle
+ void *hEvent; // Event handle
+ bool Halt;
+ UINT CurrentPacketCount;
+ UCHAR GetBuffer[SL_EXCHANGE_BUFFER_SIZE]; // Read buffer
+ UCHAR PutBuffer[SL_EXCHANGE_BUFFER_SIZE]; // Write buffer
+};
+
+// Adapter list items
+struct SU_ADAPTER_LIST
+{
+ SL_ADAPTER_INFO Info; // Adapter information
+ char Guid[128]; // GUID
+ char Name[MAX_SIZE]; // Name
+ char SortKey[MAX_SIZE]; // Sort key
+};
+
+
+//// Function prototype
+SU *SuInit();
+SU *SuInitEx(UINT wait_for_bind_complete_tick);
+void SuFree(SU *u);
+TOKEN_LIST *SuEnumAdapters(SU *u);
+SU_ADAPTER *SuOpenAdapter(SU *u, char *adapter_id);
+void SuCloseAdapter(SU_ADAPTER *a);
+void SuCloseAdapterHandleInner(SU_ADAPTER *a);
+bool SuGetPacketsFromDriver(SU_ADAPTER *a);
+bool SuGetNextPacket(SU_ADAPTER *a, void **buf, UINT *size);
+bool SuPutPacketsToDriver(SU_ADAPTER *a);
+bool SuPutPacket(SU_ADAPTER *a, void *buf, UINT size);
+
+SU_ADAPTER_LIST *SuAdapterInfoToAdapterList(SL_ADAPTER_INFO *info);
+LIST *SuGetAdapterList(SU *u);
+void SuFreeAdapterList(LIST *o);
+int SuCmpAdaterList(void *p1, void *p2);
+
+bool SuInstallDriver(bool force);
+bool SuInstallDriverInner(bool force);
+bool SuIsSupportedOs();
+
+#endif // SELOWUSER_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SecureInfo.c b/src/Cedar/SecureInfo.c
new file mode 100644
index 00000000..97e66758
--- /dev/null
+++ b/src/Cedar/SecureInfo.c
@@ -0,0 +1,90 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SecureInfo.c
+// Code related to a secure VPN tunnel data for system administrators
+
+#include "CedarPch.h"
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SecureInfo.h b/src/Cedar/SecureInfo.h
new file mode 100644
index 00000000..dedb2006
--- /dev/null
+++ b/src/Cedar/SecureInfo.h
@@ -0,0 +1,94 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SecureInfo.h
+// Header of SecureInfo.c
+
+#ifndef SECUREINFO_H
+#define SECUREINFO_H
+
+
+#endif // SECUREINFO_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SecureNAT.c b/src/Cedar/SecureNAT.c
new file mode 100644
index 00000000..bf2f81bc
--- /dev/null
+++ b/src/Cedar/SecureNAT.c
@@ -0,0 +1,228 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SecureNAT.c
+// SecureNAT code
+
+#include "CedarPch.h"
+
+// SecureNAT server-side thread
+void SnSecureNATThread(THREAD *t, void *param)
+{
+ SNAT *s;
+ CONNECTION *c;
+ SESSION *se;
+ POLICY *policy;
+ HUB *h;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ s = (SNAT *)param;
+ // Create a server connection
+ c = NewServerConnection(s->Cedar, NULL, t);
+ c->Protocol = CONNECTION_HUB_SECURE_NAT;
+
+ // Apply the default policy
+ policy = ClonePolicy(GetDefaultPolicy());
+
+ // Not to limit the number of broadcast
+ policy->NoBroadcastLimiter = true;
+
+ h = s->Hub;
+ AddRef(h->ref);
+
+ // create a server session
+ se = NewServerSession(s->Cedar, c, s->Hub, SNAT_USER_NAME, policy);
+ se->SecureNATMode = true;
+ se->SecureNAT = s;
+ c->Session = se;
+ ReleaseConnection(c);
+
+ HLog(se->Hub, "LH_NAT_START", se->Name);
+
+ // User name
+ se->Username = CopyStr(SNAT_USER_NAME_PRINT);
+
+ s->Session = se;
+ AddRef(se->ref);
+
+ // Notification initialization completion
+ NoticeThreadInit(t);
+
+ ReleaseCancel(s->Nat->Virtual->Cancel);
+ s->Nat->Virtual->Cancel = se->Cancel1;
+ AddRef(se->Cancel1->ref);
+
+ if (s->Nat->Virtual->NativeNat != NULL)
+ {
+ CANCEL *old_cancel = NULL;
+
+ Lock(s->Nat->Virtual->NativeNat->CancelLock);
+ {
+ if (s->Nat->Virtual->NativeNat->Cancel != NULL)
+ {
+ old_cancel = s->Nat->Virtual->NativeNat->Cancel;
+
+ s->Nat->Virtual->NativeNat->Cancel = se->Cancel1;
+
+ AddRef(se->Cancel1->ref);
+ }
+ }
+ Unlock(s->Nat->Virtual->NativeNat->CancelLock);
+
+ if (old_cancel != NULL)
+ {
+ ReleaseCancel(old_cancel);
+ }
+ }
+
+ // Main function of the session
+ Debug("SecureNAT Start.\n");
+ SessionMain(se);
+ Debug("SecureNAT Stop.\n");
+
+ HLog(se->Hub, "LH_NAT_STOP");
+
+ ReleaseHub(h);
+
+ ReleaseSession(se);
+}
+
+// Release the SecureNAT
+void SnFreeSecureNAT(SNAT *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Stop the session
+ StopSession(s->Session);
+ ReleaseSession(s->Session);
+
+ // Virtual machine release
+ Virtual_Free(s->Nat->Virtual);
+
+ // NAT release
+ NiFreeNat(s->Nat);
+
+ DeleteLock(s->lock);
+
+ Free(s);
+}
+
+// Create a new SecureNAT
+SNAT *SnNewSecureNAT(HUB *h, VH_OPTION *o)
+{
+ SNAT *s;
+ THREAD *t;
+ // Validate arguments
+ if (h == NULL || o == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(SNAT));
+ s->Cedar = h->Cedar;
+ s->Hub = h;
+ s->lock = NewLock();
+
+ // Create a NAT
+ s->Nat = NiNewNatEx(s, o);
+
+ // Initialize the virtual machine
+ VirtualInit(s->Nat->Virtual);
+
+ // Create a thread
+ t = NewThread(SnSecureNATThread, s);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ return s;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/SecureNAT.h b/src/Cedar/SecureNAT.h
new file mode 100644
index 00000000..ba387a88
--- /dev/null
+++ b/src/Cedar/SecureNAT.h
@@ -0,0 +1,108 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SecureNAT.h
+// Header of SecureNAT.c
+
+#ifndef SECURENAT_H
+#define SECURENAT_H
+
+struct SNAT
+{
+ LOCK *lock; // Lock
+ CEDAR *Cedar; // Cedar
+ HUB *Hub; // HUB
+ SESSION *Session; // Session
+ POLICY *Policy; // Policy
+ NAT *Nat; // NAT
+};
+
+
+SNAT *SnNewSecureNAT(HUB *h, VH_OPTION *o);
+void SnFreeSecureNAT(SNAT *s);
+void SnSecureNATThread(THREAD *t, void *param);
+
+
+#endif // SECURENAT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Server.c b/src/Cedar/Server.c
new file mode 100644
index 00000000..aa5ba62d
--- /dev/null
+++ b/src/Cedar/Server.c
@@ -0,0 +1,10466 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Server.c
+// VPN Server module
+
+#include "CedarPch.h"
+
+static SERVER *server = NULL;
+static LOCK *server_lock = NULL;
+char *SERVER_CONFIG_FILE_NAME = "@vpn_server.config";
+char *SERVER_CONFIG_FILE_NAME_IN_CLIENT = "@vpn_gate_svc.config";
+char *BRIDGE_CONFIG_FILE_NAME = "@vpn_bridge.config";
+
+static bool server_reset_setting = false;
+
+// Set the OpenVPN and SSTP setting
+void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
+{
+ // Validate arguments
+ if (s == NULL || c == NULL)
+ {
+ return;
+ }
+
+ Lock(s->OpenVpnSstpConfigLock);
+ {
+ // Save the settings
+ if (s->Cedar->Bridge || s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ s->DisableSSTPServer = true;
+ s->DisableOpenVPNServer = true;
+ }
+ else
+ {
+ s->DisableSSTPServer = !c->EnableSSTP;
+ s->DisableOpenVPNServer = !c->EnableOpenVPN;
+ }
+
+ NormalizeIntListStr(s->OpenVpnServerUdpPorts, sizeof(s->OpenVpnServerUdpPorts),
+ c->OpenVPNPortList, true, ", ");
+
+ // Apply the OpenVPN configuration
+ if (s->OpenVpnServerUdp != NULL)
+ {
+ if (s->DisableOpenVPNServer)
+ {
+ OvsApplyUdpPortList(s->OpenVpnServerUdp, "");
+ }
+ else
+ {
+ OvsApplyUdpPortList(s->OpenVpnServerUdp, s->OpenVpnServerUdpPorts);
+ }
+ }
+ }
+ Unlock(s->OpenVpnSstpConfigLock);
+}
+
+// Get the OpenVPN and SSTP setting
+void SiGetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
+{
+ // Validate arguments
+ if (s == NULL || c == NULL)
+ {
+ return;
+ }
+
+ Zero(c, sizeof(OPENVPN_SSTP_CONFIG));
+
+ Lock(s->OpenVpnSstpConfigLock);
+ {
+ if (s->DisableOpenVPNServer == false)
+ {
+ c->EnableOpenVPN = true;
+ }
+
+ if (s->DisableSSTPServer == false)
+ {
+ c->EnableSSTP = true;
+ }
+
+ StrCpy(c->OpenVPNPortList, sizeof(c->OpenVPNPortList), s->OpenVpnServerUdpPorts);
+ }
+ Unlock(s->OpenVpnSstpConfigLock);
+}
+
+// Get whether the number of user objects that are registered in the VPN Server is too many
+bool SiTooManyUserObjectsInServer(SERVER *s, bool oneMore)
+{
+ return false;
+}
+
+// Get the number of user objects that are registered in the VPN Server
+UINT SiGetServerNumUserObjects(SERVER *s)
+{
+ CEDAR *c;
+ UINT ret = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ c = s->Cedar;
+
+ LockList(c->HubList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+
+ if (h->HubDb != NULL)
+ {
+ ret += LIST_NUM(h->HubDb->UserList);
+ }
+ }
+ }
+ UnlockList(c->HubList);
+
+ return ret;
+}
+
+
+typedef struct SI_DEBUG_PROC_LIST
+{
+ UINT Id;
+ char *Description;
+ char *Args;
+ SI_DEBUG_PROC *Proc;
+} SI_DEBUG_PROC_LIST;
+
+// Debugging function
+UINT SiDebug(SERVER *s, RPC_TEST *ret, UINT i, char *str)
+{
+ SI_DEBUG_PROC_LIST proc_list[] =
+ {
+ {1, "Hello World", "<test string>", SiDebugProcHelloWorld},
+ {2, "Terminate process now", "", SiDebugProcExit},
+ {3, "Write memory dumpfile", "", SiDebugProcDump},
+ {4, "Restore process priority", "", SiDebugProcRestorePriority},
+ {5, "Set the process priority high", "", SiDebugProcSetHighPriority},
+ {6, "Get the .exe filename of the process", "", SiDebugProcGetExeFileName},
+ {7, "Crash the process", "", SiDebugProcCrash},
+ {8, "Get IPsecMessageDisplayed Flag", "", SiDebugProcGetIPsecMessageDisplayedValue},
+ {9, "Set IPsecMessageDisplayed Flag", "", SiDebugProcSetIPsecMessageDisplayedValue},
+ {10, "Get VgsMessageDisplayed Flag", "", SiDebugProcGetVgsMessageDisplayedValue},
+ {11, "Set VgsMessageDisplayed Flag", "", SiDebugProcSetVgsMessageDisplayedValue},
+ };
+ UINT num_proc_list = sizeof(proc_list) / sizeof(proc_list[0]);
+ UINT j;
+ UINT ret_value = ERR_NO_ERROR;
+ // Validate arguments
+ if (s == NULL || ret == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ if (i == 0)
+ {
+ char tmp[MAX_SIZE];
+ Zero(ret, sizeof(RPC_TEST));
+
+ StrCat(ret->StrValue, sizeof(ret->StrValue),
+ "\n--- Debug Functions List --\n");
+
+ for (j = 0;j < num_proc_list;j++)
+ {
+ SI_DEBUG_PROC_LIST *p = &proc_list[j];
+
+ if (IsEmptyStr(p->Args) == false)
+ {
+ Format(tmp, sizeof(tmp),
+ " %u: %s - Usage: %u /ARG:\"%s\"\n",
+ p->Id, p->Description, p->Id, p->Args);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp),
+ " %u: %s - Usage: %u\n",
+ p->Id, p->Description, p->Id);
+ }
+
+ StrCat(ret->StrValue, sizeof(ret->StrValue), tmp);
+ }
+ }
+ else
+ {
+ ret_value = ERR_NOT_SUPPORTED;
+
+ for (j = 0;j < num_proc_list;j++)
+ {
+ SI_DEBUG_PROC_LIST *p = &proc_list[j];
+
+ if (p->Id == i)
+ {
+ ret_value = p->Proc(s, str, ret->StrValue, sizeof(ret->StrValue));
+
+ if (ret_value == ERR_NO_ERROR && IsEmptyStr(ret->StrValue))
+ {
+ StrCpy(ret->StrValue, sizeof(ret->StrValue), "Ok.");
+ }
+ break;
+ }
+ }
+ }
+
+ return ret_value;
+}
+UINT SiDebugProcHelloWorld(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ Format(ret_str, ret_str_size, "Hello World %s\n", in_str);
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcExit(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ _exit(1);
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcDump(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+#ifdef OS_WIN32
+ MsWriteMinidump(NULL, NULL);
+#else // OS_WIN32
+ return ERR_NOT_SUPPORTED;
+#endif // OS_WIN32
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcRestorePriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ OSRestorePriority();
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcSetHighPriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ OSSetHighPriority();
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcGetExeFileName(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ GetExeName(ret_str, ret_str_size);
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcCrash(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ CrashNow();
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcGetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ ToStr(ret_str, s->IPsecMessageDisplayed);
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcSetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ s->IPsecMessageDisplayed = ToInt(in_str);
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcGetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+#if 0
+ if (VgDoNotPopupMessage() == false)
+ {
+ ToStr(ret_str, s->VgsMessageDisplayed);
+ }
+ else
+ {
+ ToStr(ret_str, 1);
+ }
+#else
+ // Do not show the VGS message in VPN Server of the current version
+ ToStr(ret_str, 1);
+#endif
+
+ return ERR_NO_ERROR;
+}
+UINT SiDebugProcSetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+ // Validate arguments
+ if (s == NULL || in_str == NULL || ret_str == NULL)
+ {
+ return ERR_INVALID_PARAMETER;
+ }
+
+
+ return ERR_NO_ERROR;
+}
+
+// Write the debug log
+void SiDebugLog(SERVER *s, char *msg)
+{
+ // Validate arguments
+ if (s == NULL || msg == NULL)
+ {
+ return;
+ }
+
+ if (s->DebugLog != NULL)
+ {
+ WriteTinyLog(s->DebugLog, msg);
+ }
+}
+
+// Deadlock inspection main
+void SiCheckDeadLockMain(SERVER *s, UINT timeout)
+{
+ CEDAR *cedar;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ //Debug("SiCheckDeadLockMain Start.\n");
+
+ cedar = s->Cedar;
+
+ if (s->ServerListenerList != NULL)
+ {
+ CheckDeadLock(s->ServerListenerList->lock, timeout, "s->ServerListenerList->lock");
+ }
+
+ CheckDeadLock(s->lock, timeout, "s->lock");
+
+ if (s->FarmMemberList != NULL)
+ {
+ CheckDeadLock(s->FarmMemberList->lock, timeout, "s->FarmMemberList->lock");
+ }
+
+ if (s->HubCreateHistoryList != NULL)
+ {
+ CheckDeadLock(s->HubCreateHistoryList->lock, timeout, "s->HubCreateHistoryList->lock");
+ }
+
+ CheckDeadLock(s->CapsCacheLock, timeout, "s->CapsCacheLock");
+
+ CheckDeadLock(s->TasksFromFarmControllerLock, timeout, "s->TasksFromFarmControllerLock");
+
+ if (cedar != NULL)
+ {
+ if (cedar->HubList != NULL)
+ {
+ CheckDeadLock(cedar->HubList->lock, timeout, "cedar->HubList->lock");
+ }
+
+ if (cedar->ListenerList != NULL)
+ {
+ UINT i;
+ LIST *o = NewListFast(NULL);
+
+ CheckDeadLock(cedar->ListenerList->lock, timeout, "cedar->ListenerList->lock");
+
+ LockList(cedar->ListenerList);
+ {
+ for (i = 0;i < LIST_NUM(cedar->ListenerList);i++)
+ {
+ LISTENER *r = LIST_DATA(cedar->ListenerList, i);
+
+ AddRef(r->ref);
+
+ Add(o, r);
+ }
+ }
+ UnlockList(cedar->ListenerList);
+
+
+ ReleaseList(o);
+ }
+
+ if (cedar->ConnectionList != NULL)
+ {
+ CheckDeadLock(cedar->ConnectionList->lock, timeout, "cedar->ConnectionList->lock");
+ }
+
+ if (cedar->CaList != NULL)
+ {
+ CheckDeadLock(cedar->CaList->lock, timeout, "cedar->CaList->lock");
+ }
+
+ if (cedar->TrafficLock != NULL)
+ {
+ CheckDeadLock(cedar->TrafficLock, timeout, "cedar->TrafficLock");
+ }
+
+ if (cedar->TrafficDiffList != NULL)
+ {
+ CheckDeadLock(cedar->TrafficDiffList->lock, timeout, "cedar->TrafficDiffList->lock");
+ }
+
+ if (cedar->LocalBridgeList != NULL)
+ {
+ CheckDeadLock(cedar->LocalBridgeList->lock, timeout, "cedar->LocalBridgeList->lock");
+ }
+
+ if (cedar->L3SwList != NULL)
+ {
+ CheckDeadLock(cedar->L3SwList->lock, timeout, "cedar->L3SwList->lock");
+ }
+ }
+
+ //Debug("SiCheckDeadLockMain Finish.\n");
+}
+
+// Deadlock check thread
+void SiDeadLockCheckThread(THREAD *t, void *param)
+{
+ SERVER *s = (SERVER *)param;
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ Wait(s->DeadLockWaitEvent, SERVER_DEADLOCK_CHECK_SPAN);
+
+ if (s->HaltDeadLockThread)
+ {
+ break;
+ }
+
+ SiCheckDeadLockMain(s, SERVER_DEADLOCK_CHECK_TIMEOUT);
+ }
+}
+
+// Initialize the deadlock check
+void SiInitDeadLockCheck(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+ if (s->DisableDeadLockCheck)
+ {
+ return;
+ }
+
+ s->HaltDeadLockThread = false;
+ s->DeadLockWaitEvent = NewEvent();
+ s->DeadLockCheckThread = NewThread(SiDeadLockCheckThread, s);
+}
+
+// Release the deadlock check
+void SiFreeDeadLockCheck(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->DeadLockCheckThread == NULL)
+ {
+ return;
+ }
+
+ s->HaltDeadLockThread = true;
+ Set(s->DeadLockWaitEvent);
+
+ WaitThread(s->DeadLockCheckThread, INFINITE);
+
+ ReleaseThread(s->DeadLockCheckThread);
+ s->DeadLockCheckThread = NULL;
+
+ ReleaseEvent(s->DeadLockWaitEvent);
+ s->DeadLockWaitEvent = NULL;
+
+ s->HaltDeadLockThread = false;
+}
+
+// Check whether the specified virtual HUB has been registered to creation history
+bool SiIsHubRegistedOnCreateHistory(SERVER *s, char *name)
+{
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ SiDeleteOldHubCreateHistory(s);
+
+ LockList(s->HubCreateHistoryList);
+ {
+ for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
+
+ if (StrCmpi(h->HubName, name) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ UnlockList(s->HubCreateHistoryList);
+
+ return ret;
+}
+
+// Delete the Virtual HUB creation history
+void SiDelHubCreateHistory(SERVER *s, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return;
+ }
+
+ LockList(s->HubCreateHistoryList);
+ {
+ SERVER_HUB_CREATE_HISTORY *hh = NULL;
+ for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
+
+ if (StrCmpi(h->HubName, name) == 0)
+ {
+ Delete(s->HubCreateHistoryList, h);
+ Free(h);
+ break;
+ }
+ }
+ }
+ UnlockList(s->HubCreateHistoryList);
+
+ SiDeleteOldHubCreateHistory(s);
+}
+
+// Register to the Virtual HUB creation history
+void SiAddHubCreateHistory(SERVER *s, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return;
+ }
+
+ LockList(s->HubCreateHistoryList);
+ {
+ SERVER_HUB_CREATE_HISTORY *hh = NULL;
+ for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
+
+ if (StrCmpi(h->HubName, name) == 0)
+ {
+ hh = h;
+ break;
+ }
+ }
+
+ if (hh == NULL)
+ {
+ hh = ZeroMalloc(sizeof(SERVER_HUB_CREATE_HISTORY));
+ StrCpy(hh->HubName, sizeof(hh->HubName), name);
+
+ Add(s->HubCreateHistoryList, hh);
+ }
+
+ hh->CreatedTime = Tick64();
+ }
+ UnlockList(s->HubCreateHistoryList);
+
+ SiDeleteOldHubCreateHistory(s);
+}
+
+// Delete outdated Virtual HUB creation histories
+void SiDeleteOldHubCreateHistory(SERVER *s)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ LockList(s->HubCreateHistoryList);
+ {
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
+
+ if ((h->CreatedTime + ((UINT64)TICKET_EXPIRES)) <= Tick64())
+ {
+ // Expired
+ Add(o, h);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(o, i);
+
+ Delete(s->HubCreateHistoryList, h);
+
+ Free(h);
+ }
+
+ ReleaseList(o);
+ }
+ UnlockList(s->HubCreateHistoryList);
+}
+
+// Initialize the Virtual HUB creation history
+void SiInitHubCreateHistory(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->HubCreateHistoryList = NewList(NULL);
+}
+
+// Release the Virtual HUB creation history
+void SiFreeHubCreateHistory(SERVER *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
+ {
+ SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
+
+ Free(h);
+ }
+
+ ReleaseList(s->HubCreateHistoryList);
+
+ s->HubCreateHistoryList = NULL;
+}
+
+// Identify whether the server can be connected from the VPN Client that is
+// created by the installer creating kit of Admin Pack
+bool IsAdminPackSupportedServerProduct(char *name)
+{
+ return true;
+}
+
+
+// Get the saving status of syslog
+UINT SiGetSysLogSaveStatus(SERVER *s)
+{
+ SYSLOG_SETTING set;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return SYSLOG_NONE;
+ }
+
+ SiGetSysLogSetting(s, &set);
+
+ return set.SaveType;
+}
+
+// Send a syslog
+void SiWriteSysLog(SERVER *s, char *typestr, char *hubname, wchar_t *message)
+{
+}
+
+// Write the syslog configuration
+void SiSetSysLogSetting(SERVER *s, SYSLOG_SETTING *setting)
+{
+ SYSLOG_SETTING set;
+ // Validate arguments
+ if (s == NULL || setting == NULL)
+ {
+ return;
+ }
+
+ Zero(&set, sizeof(set));
+ Copy(&set, setting, sizeof(SYSLOG_SETTING));
+
+ if (IsEmptyStr(set.Hostname) || set.Port == 0)
+ {
+ set.SaveType = SYSLOG_NONE;
+ }
+
+ Lock(s->SyslogLock);
+ {
+ Copy(&s->SyslogSetting, &set, sizeof(SYSLOG_SETTING));
+
+ SetSysLog(s->Syslog, set.Hostname, set.Port);
+ }
+ Unlock(s->SyslogLock);
+}
+
+// Read the syslog configuration
+void SiGetSysLogSetting(SERVER *s, SYSLOG_SETTING *setting)
+{
+ // Validate arguments
+ if (s == NULL || setting == NULL)
+ {
+ return;
+ }
+
+ //Lock(s->SyslogLock);
+ {
+ Copy(setting, &s->SyslogSetting, sizeof(SYSLOG_SETTING));
+ }
+ //Unlock(s->SyslogLock);
+}
+
+
+// Get the server product name
+void GetServerProductName(SERVER *s, char *name, UINT size)
+{
+ char *cpu;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return;
+ }
+
+ GetServerProductNameInternal(s, name, size);
+
+#ifdef CPU_64
+ cpu = " (64 bit)";
+#else // CPU_64
+ cpu = " (32 bit)";
+#endif // CPU_64
+
+ StrCat(name, size, cpu);
+
+ StrCat(name, size, " (Open Source)");
+}
+void GetServerProductNameInternal(SERVER *s, char *name, UINT size)
+{
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return;
+ }
+
+#ifdef BETA_NUMBER
+ if (s->Cedar->Bridge)
+ {
+ StrCpy(name, size, CEDAR_BRIDGE_STR);
+ }
+ else
+ {
+ StrCpy(name, size, CEDAR_BETA_SERVER);
+ }
+ return;
+#else // BETA_NUMBER
+ if (s->Cedar->Bridge)
+ {
+ StrCpy(name, size, CEDAR_BRIDGE_STR);
+ }
+ else
+ {
+ StrCpy(name, size, CEDAR_SERVER_STR);
+ }
+#endif // BETA_NUMBER
+}
+
+// Adjoin the enumerations of log files
+void AdjoinEnumLogFile(LIST *o, LIST *src)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || src == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(src);i++)
+ {
+ LOG_FILE *f = LIST_DATA(src, i);
+
+ Insert(o, Clone(f, sizeof(LOG_FILE)));
+ }
+}
+
+// Check whether the log file with the specified name is contained in the enumerated list
+bool CheckLogFileNameFromEnumList(LIST *o, char *name, char *server_name)
+{
+ LOG_FILE t;
+ // Validate arguments
+ if (o == NULL || name == NULL || server_name == NULL)
+ {
+ return false;
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Path, sizeof(t.Path), name);
+ StrCpy(t.ServerName, sizeof(t.ServerName), server_name);
+
+ if (Search(o, &t) == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Release the log file enumeration
+void FreeEnumLogFile(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LOG_FILE *f = LIST_DATA(o, i);
+
+ Free(f);
+ }
+
+ ReleaseList(o);
+}
+
+// Enumerate the log files associated with the virtual HUB (All logs are listed in the case of server administrator)
+LIST *EnumLogFile(char *hubname)
+{
+ char exe_dir[MAX_PATH];
+ char tmp[MAX_PATH];
+ LIST *o = NewListFast(CmpLogFile);
+ DIRLIST *dir;
+
+ if (StrLen(hubname) == 0)
+ {
+ hubname = NULL;
+ }
+
+ GetExeDir(exe_dir, sizeof(exe_dir));
+
+ // Enumerate in the server_log
+ if (hubname == NULL)
+ {
+ EnumLogFileDir(o, "server_log");
+ }
+
+ // Enumerate in the packet_log
+ Format(tmp, sizeof(tmp), "%s/packet_log", exe_dir);
+ dir = EnumDir(tmp);
+ if (dir != NULL)
+ {
+ UINT i;
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder)
+ {
+ char dir_name[MAX_PATH];
+
+ if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
+ {
+ Format(dir_name, sizeof(dir_name), "packet_log/%s", e->FileName);
+ EnumLogFileDir(o, dir_name);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+
+ // Enumerate in the security_log
+ Format(tmp, sizeof(tmp), "%s/security_log", exe_dir);
+ dir = EnumDir(tmp);
+ if (dir != NULL)
+ {
+ UINT i;
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder)
+ {
+ char dir_name[MAX_PATH];
+
+ if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
+ {
+ Format(dir_name, sizeof(dir_name), "security_log/%s", e->FileName);
+ EnumLogFileDir(o, dir_name);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+
+ return o;
+}
+
+// Enumerate log files in the specified directory
+void EnumLogFileDir(LIST *o, char *dirname)
+{
+ UINT i;
+ char exe_dir[MAX_PATH];
+ char dir_full_path[MAX_PATH];
+ DIRLIST *dir;
+ // Validate arguments
+ if (o == NULL || dirname == NULL)
+ {
+ return;
+ }
+
+ GetExeDir(exe_dir, sizeof(exe_dir));
+ Format(dir_full_path, sizeof(dir_full_path), "%s/%s", exe_dir, dirname);
+
+ dir = EnumDir(dir_full_path);
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder == false && e->FileSize > 0)
+ {
+ char full_path[MAX_PATH];
+ char file_path[MAX_PATH];
+
+ Format(file_path, sizeof(file_path), "%s/%s", dirname, e->FileName);
+ Format(full_path, sizeof(full_path), "%s/%s", exe_dir, file_path);
+
+ if (EndWith(file_path, ".log"))
+ {
+ LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));
+
+ StrCpy(f->Path, sizeof(f->Path), file_path);
+ f->FileSize = (UINT)(MIN(e->FileSize, 0xffffffffUL));
+ f->UpdatedTime = e->UpdateDate;
+
+ GetMachineName(f->ServerName, sizeof(f->ServerName));
+
+ Insert(o, f);
+ }
+ }
+ }
+
+ FreeDir(dir);
+}
+
+// Log file list entry comparison
+int CmpLogFile(void *p1, void *p2)
+{
+ LOG_FILE *f1, *f2;
+ UINT i;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(LOG_FILE **)p1;
+ f2 = *(LOG_FILE **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+
+ i = StrCmpi(f1->Path, f2->Path);
+ if (i != 0)
+ {
+ return i;
+ }
+
+ return StrCmpi(f1->ServerName, f2->ServerName);
+}
+
+// Get the Caps of the server
+UINT GetServerCapsInt(SERVER *s, char *name)
+{
+ CAPSLIST t;
+ UINT ret;
+ // Validate arguments
+ if (s == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ Zero(&t, sizeof(t));
+ GetServerCaps(s, &t);
+
+ ret = GetCapsInt(&t, name);
+
+ return ret;
+}
+bool GetServerCapsBool(SERVER *s, char *name)
+{
+ return (GetServerCapsInt(s, name) == 0) ? false : true;
+}
+
+// Initialize the Caps cache of the server
+void InitServerCapsCache(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->CapsCacheLock = NewLock();
+ s->CapsListCache = NULL;
+}
+
+// Release the Caps cache of the server
+void FreeServerCapsCache(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->CapsListCache != NULL)
+ {
+ FreeCapsList(s->CapsListCache);
+ s->CapsListCache = NULL;
+ }
+ DeleteLock(s->CapsCacheLock);
+}
+
+// Dispose the Caps cache of the server
+void DestroyServerCapsCache(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->CapsCacheLock);
+ {
+ if (s->CapsListCache != NULL)
+ {
+ FreeCapsList(s->CapsListCache);
+ s->CapsListCache = NULL;
+ }
+ }
+ Unlock(s->CapsCacheLock);
+}
+
+// Get the Caps list for this server
+void GetServerCaps(SERVER *s, CAPSLIST *t)
+{
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Lock(s->CapsCacheLock);
+ {
+
+ if (s->CapsListCache == NULL)
+ {
+ s->CapsListCache = ZeroMalloc(sizeof(CAPSLIST));
+ GetServerCapsMain(s, s->CapsListCache);
+ }
+
+ Copy(t, s->CapsListCache, sizeof(s->CapsListCache));
+ }
+ Unlock(s->CapsCacheLock);
+}
+
+// Main of the aquisition of Caps of the server
+void GetServerCapsMain(SERVER *s, CAPSLIST *t)
+{
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // Initialize
+ InitCapsList(t);
+
+ // Maximum Ethernet packet size
+ AddCapsInt(t, "i_max_packet_size", MAX_PACKET_SIZE);
+
+ if (s->Cedar->Bridge == false)
+ {
+ UINT max_sessions, max_clients, max_bridges, max_user_creations;
+
+ max_clients = INFINITE;
+ max_bridges = INFINITE;
+ max_sessions = SERVER_MAX_SESSIONS_FOR_CARRIER_EDITION;
+ max_user_creations = INFINITE;
+
+ // Maximum number of virtual HUBs
+ AddCapsInt(t, "i_max_hubs", SERVER_MAX_SESSIONS_FOR_CARRIER_EDITION);
+
+ // The maximum number of concurrent sessions
+ AddCapsInt(t, "i_max_sessions", max_sessions);
+
+ // Maximum number of creatable users
+ AddCapsInt(t, "i_max_user_creation", max_user_creations);
+
+ // Maximum number of clients
+ AddCapsInt(t, "i_max_clients", max_clients);
+
+ // Maximum number of bridges
+ AddCapsInt(t, "i_max_bridges", max_bridges);
+
+ if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ // Maximum number of registrable users / Virtual HUB
+ AddCapsInt(t, "i_max_users_per_hub", MAX_USERS);
+
+ // Maximum number of registrable groups / Virtual HUB
+ AddCapsInt(t, "i_max_groups_per_hub", MAX_GROUPS);
+
+ // Maximum number of registrable access list entries / Virtual HUB
+ AddCapsInt(t, "i_max_access_lists", MAX_ACCESSLISTS);
+ }
+ else
+ {
+ // Maximum number of registrable users / Virtual HUB
+ AddCapsInt(t, "i_max_users_per_hub", 0);
+
+ // Maximum number of registrable groups / Virtual HUB
+ AddCapsInt(t, "i_max_groups_per_hub", 0);
+
+ // Maximum number of registrable access list entries / Virtual HUB
+ AddCapsInt(t, "i_max_access_lists", 0);
+ }
+
+ // The policy related to multiple logins
+ AddCapsBool(t, "b_support_limit_multilogin", true);
+
+ // QoS / VoIP
+ AddCapsBool(t, "b_support_qos", true);
+
+ // syslog
+ AddCapsBool(t, "b_support_syslog", false);
+
+ // IPsec
+ // (Only works in stand-alone mode currently)
+ AddCapsBool(t, "b_support_ipsec", (s->ServerType == SERVER_TYPE_STANDALONE));
+
+ // SSTP
+ // (Only works in stand-alone mode currently)
+ AddCapsBool(t, "b_support_sstp", (s->ServerType == SERVER_TYPE_STANDALONE));
+
+ // OpenVPN
+ // (Only works in stand-alone mode currently)
+ AddCapsBool(t, "b_support_openvpn", (s->ServerType == SERVER_TYPE_STANDALONE));
+
+ // DDNS
+ AddCapsBool(t, "b_support_ddns", (s->DDnsClient != NULL));
+
+ if (s->DDnsClient != NULL)
+ {
+ // DDNS via Proxy
+ AddCapsBool(t, "b_support_ddns_proxy", true);
+ }
+
+ // VPN over ICMP, VPN over DNS
+ AddCapsBool(t, "b_support_special_listener", true);
+ }
+ else
+ {
+ // Maximum number of virtual HUBs
+ AddCapsInt(t, "i_max_hubs", 0);
+
+ // The maximum number of concurrent sessions
+ AddCapsInt(t, "i_max_sessions", 0);
+
+ // Maximum number of clients
+ AddCapsInt(t, "i_max_clients", 0);
+
+ // Maximum number of bridges
+ AddCapsInt(t, "i_max_bridges", 0);
+
+ // Maximum number of registrable users / Virtual HUB
+ AddCapsInt(t, "i_max_users_per_hub", 0);
+
+ // Maximum number of registrable groups / Virtual HUB
+ AddCapsInt(t, "i_max_groups_per_hub", 0);
+
+ // Maximum number of registrable access list entries / Virtual HUB
+ AddCapsInt(t, "i_max_access_lists", 0);
+
+ // QoS / VoIP
+ AddCapsBool(t, "b_support_qos", true);
+
+ // syslog
+ AddCapsBool(t, "b_support_syslog", true);
+
+ // IPsec
+ AddCapsBool(t, "b_support_ipsec", false);
+
+ // SSTP
+ AddCapsBool(t, "b_support_sstp", false);
+
+ // OpenVPN
+ AddCapsBool(t, "b_support_openvpn", false);
+
+ // DDNS
+ AddCapsBool(t, "b_support_ddns", false);
+
+ // VPN over ICMP, VPN over DNS
+ AddCapsBool(t, "b_support_special_listener", false);
+ }
+
+ // Changing the type of Virtual HUB in cluster is prohibited
+ AddCapsBool(t, "b_cluster_hub_type_fixed", true);
+
+ // Maximum MAC address table size / Virtual HUB
+ AddCapsInt(t, "i_max_mac_tables", MAX_MAC_TABLES);
+
+ // Maximum IP address table size / Virtual HUB
+ AddCapsInt(t, "i_max_ip_tables", MAX_IP_TABLES);
+
+ // SecureNAT function is available
+ AddCapsBool(t, "b_support_securenat", true);
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_virtual_nat_disabled", true);
+ }
+
+ // Maximum NAT table size / Virtual HUB
+ AddCapsInt(t, "i_max_secnat_tables", NAT_MAX_SESSIONS);
+
+ // Cascade connction
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_support_cascade", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_cascade", false);
+ }
+
+ if (s->Cedar->Bridge)
+ {
+ // Bridge mode
+ AddCapsBool(t, "b_bridge", true);
+ }
+ else if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // Stand-alone mode
+ AddCapsBool(t, "b_standalone", true);
+ }
+ else if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Cluster controller mode
+ AddCapsBool(t, "b_cluster_controller", true);
+ }
+ else
+ {
+ // Cluster member mode
+ AddCapsBool(t, "b_cluster_member", true);
+ }
+
+ // Virtual HUB is modifiable
+ AddCapsBool(t, "b_support_config_hub", s->ServerType != SERVER_TYPE_FARM_MEMBER &&
+ s->Cedar->Bridge == false);
+
+ // VPN client can be connected
+ AddCapsBool(t, "b_vpn_client_connect", s->Cedar->Bridge == false ? true : false);
+
+ AddCapsBool(t, "b_support_radius", false);
+
+ // Local-bridge function is available
+ AddCapsBool(t, "b_local_bridge", IsBridgeSupported());
+
+ if (OS_IS_WINDOWS(GetOsInfo()->OsType))
+ {
+ // Packet capture driver is not installed
+ AddCapsBool(t, "b_must_install_pcap", IsEthSupported() == false ? true : false);
+ }
+ else
+ {
+ // Regard that the driver is installed in the Linux version
+ AddCapsBool(t, "b_must_install_pcap", false);
+ }
+
+ if (IsBridgeSupported())
+ {
+ // Tun / tap device is available (only Linux)
+ AddCapsBool(t, "b_tap_supported", GetOsInfo()->OsType == OSTYPE_LINUX ? true : false);
+ }
+
+ // Cascade connction
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ AddCapsBool(t, "b_support_cascade", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_cascade", false);
+ }
+
+ // Server authentication can be used in cascade connection
+ AddCapsBool(t, "b_support_cascade_cert", true);
+
+ AddCapsBool(t, "b_support_config_log", false);
+
+ // Automatic deletion of log file is available
+ AddCapsBool(t, "b_support_autodelete", true);
+
+ // Config file operation is available
+ AddCapsBool(t, "b_support_config_rw", true);
+
+ // Attribute of each Virtual HUB can be set
+ AddCapsBool(t, "b_support_hub_admin_option", true);
+
+ // Client certificate can be set in a cascade connection
+ AddCapsBool(t, "b_support_cascade_client_cert", true);
+
+ // Virtual HUB can be hidden
+ AddCapsBool(t, "b_support_hide_hub", true);
+
+ // Integrated management
+ AddCapsBool(t, "b_support_cluster_admin", true);
+
+ // Flag of open-source version
+ AddCapsBool(t, "b_is_softether", true);
+
+ if (s->Cedar->Bridge == false)
+ {
+
+ // The virtual layer 3 switch function is available
+ AddCapsBool(t, "b_support_layer3", true);
+
+ AddCapsInt(t, "i_max_l3_sw", MAX_NUM_L3_SWITCH);
+ AddCapsInt(t, "i_max_l3_if", MAX_NUM_L3_IF);
+ AddCapsInt(t, "i_max_l3_table", MAX_NUM_L3_TABLE);
+
+ // Can act as a part of a cluster
+ AddCapsBool(t, "b_support_cluster", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_layer3", false);
+
+ AddCapsInt(t, "i_max_l3_sw", 0);
+ AddCapsInt(t, "i_max_l3_if", 0);
+ AddCapsInt(t, "i_max_l3_table", 0);
+
+ AddCapsBool(t, "b_support_cluster", false);
+ }
+
+ if (s->ServerType != SERVER_TYPE_FARM_MEMBER && s->Cedar->Bridge == false)
+ {
+ // Support for CRL
+ AddCapsBool(t, "b_support_crl", true);
+
+ }
+
+ // Supports downloading a log file
+ AddCapsBool(t, "b_support_read_log", true);
+
+ // Cascade connection can be renamed
+ AddCapsBool(t, "b_support_rename_cascade", true);
+
+
+ if (s->Cedar->Beta)
+ {
+ // Beta version
+ AddCapsBool(t, "b_beta_version", true);
+ }
+
+ // VM discrimination
+ AddCapsBool(t, "b_is_in_vm", s->IsInVm);
+
+ // Support for display name of the network connection for the local bridge
+#ifdef OS_WIN32
+ if (IsBridgeSupported() && IsNt() && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL)
+ {
+ AddCapsBool(t, "b_support_network_connection_name", true);
+ }
+#else // OS_WIN32
+ if (IsBridgeSupported() && EthIsInterfaceDescriptionSupportedUnix())
+ {
+ AddCapsBool(t, "b_support_network_connection_name", true);
+ }
+#endif // OS_WIN32
+
+ // Support for MAC address filtering
+ AddCapsBool(t, "b_support_check_mac", true);
+
+ // Support for status check of the TCP connection
+ AddCapsBool(t, "b_support_check_tcp_state", true);
+
+ // Can specify multiple server and retry intervals in Radius authentication
+ AddCapsBool(t, "b_support_radius_retry_interval_and_several_servers", s->ServerType != SERVER_TYPE_FARM_MEMBER &&
+ s->Cedar->Bridge == false);
+
+ // Can manage the ID of the tagged VLAN in the MAC address table
+ AddCapsBool(t, "b_support_vlan", true);
+
+ // Support for Virtual HUB extended options
+ if ((s->Cedar->Bridge == false) &&
+ (s->ServerType == SERVER_TYPE_STANDALONE || s->ServerType == SERVER_TYPE_FARM_CONTROLLER))
+ {
+ AddCapsBool(t, "b_support_hub_ext_options", true);
+ }
+ else
+ {
+ AddCapsBool(t, "b_support_hub_ext_options", false);
+ }
+
+ // Support for Security Policy version 3.0
+ AddCapsBool(t, "b_support_policy_ver_3", true);
+
+ // Support for IPv6 access list
+ AddCapsBool(t, "b_support_ipv6_acl", true);
+
+ // Support for setting of delay, jitter and packet loss in the access list
+ AddCapsBool(t, "b_support_ex_acl", true);
+
+ // Support for URL redirection in the access list
+ AddCapsBool(t, "b_support_redirect_url_acl", true);
+
+ // Supports the specification by the group name in the access list
+ AddCapsBool(t, "b_support_acl_group", true);
+
+ // Support for IPv6 in connection source IP restriction list
+ AddCapsBool(t, "b_support_ipv6_ac", true);
+
+ // Support for VLAN tagged packet transmission configuration tool
+ AddCapsBool(t, "b_support_eth_vlan", (OS_IS_WINDOWS_NT(GetOsType()) && GET_KETA(GetOsType(), 100) >= 2));
+
+ // Support for the message display function when the VPN connect to the Virtual HUB
+ AddCapsBool(t, "b_support_msg", true);
+
+ // UDP acceleration feature
+ AddCapsBool(t, "b_support_udp_acceleration", true);
+
+ // Intel AES Acceleration function
+ AddCapsBool(t, "b_support_intel_aes", IsIntelAesNiSupported());
+
+#ifdef OS_WIN32
+ // SeLow driver
+ AddCapsBool(t, "b_using_selow_driver", Win32IsUsingSeLow());
+#endif // OS_WIN32
+
+ // VPN Azure function
+ AddCapsBool(t, "b_support_azure", SiIsAzureSupported(s));
+
+ // VPN3
+ AddCapsBool(t, "b_vpn3", true);
+
+ // VPN4
+ AddCapsBool(t, "b_vpn4", true);
+
+}
+
+// SYSLOG_SETTING
+void InRpcSysLogSetting(SYSLOG_SETTING *t, PACK *p)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(SYSLOG_SETTING));
+ t->SaveType = PackGetInt(p, "SaveType");
+ t->Port = PackGetInt(p, "Port");
+ PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));
+}
+void OutRpcSysLogSetting(PACK *p, SYSLOG_SETTING *t)
+{
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackAddInt(p, "SaveType", t->SaveType);
+ PackAddInt(p, "Port", t->Port);
+ PackAddStr(p, "Hostname", t->Hostname);
+}
+
+// CAPSLIST
+void InitCapsList(CAPSLIST *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(CAPSLIST));
+ t->CapsList = NewListFast(NULL);
+}
+void InRpcCapsList(CAPSLIST *t, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(CAPSLIST));
+ t->CapsList = NewListFast(CompareCaps);
+
+ for (i = 0;i < LIST_NUM(p->elements);i++)
+ {
+ ELEMENT *e = LIST_DATA(p->elements, i);
+
+ if (StartWith(e->name, "caps_") && e->type == VALUE_INT && e->num_value == 1)
+ {
+ CAPS *c = NewCaps(e->name + 5, e->values[0]->IntValue);
+ Insert(t->CapsList, c);
+ }
+ }
+}
+void OutRpcCapsList(PACK *p, CAPSLIST *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->CapsList);i++)
+ {
+ char tmp[MAX_SIZE];
+ CAPS *c = LIST_DATA(t->CapsList, i);
+
+ Format(tmp, sizeof(tmp), "caps_%s", c->Name);
+ PackAddInt(p, tmp, c->Value);
+ }
+}
+void FreeRpcCapsList(CAPSLIST *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->CapsList);i++)
+ {
+ CAPS *c = LIST_DATA(t->CapsList, i);
+
+ FreeCaps(c);
+ }
+
+ ReleaseList(t->CapsList);
+}
+
+// Add a bool type to Caps list
+void AddCapsBool(CAPSLIST *caps, char *name, bool b)
+{
+ CAPS *c;
+ // Validate arguments
+ if (caps == NULL || name == NULL)
+ {
+ return;
+ }
+
+ c = NewCaps(name, b == false ? 0 : 1);
+ AddCaps(caps, c);
+}
+
+// Add the int type to Caps list
+void AddCapsInt(CAPSLIST *caps, char *name, UINT i)
+{
+ CAPS *c;
+ // Validate arguments
+ if (caps == NULL || name == NULL)
+ {
+ return;
+ }
+
+ c = NewCaps(name, i);
+ AddCaps(caps, c);
+}
+
+// Get the int type from the Caps list
+UINT GetCapsInt(CAPSLIST *caps, char *name)
+{
+ CAPS *c;
+ // Validate arguments
+ if (caps == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ c = GetCaps(caps, name);
+ if (c == NULL)
+ {
+ return 0;
+ }
+
+ return c->Value;
+}
+
+// Get bool type from the Caps list
+bool GetCapsBool(CAPSLIST *caps, char *name)
+{
+ CAPS *c;
+ // Validate arguments
+ if (caps == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ c = GetCaps(caps, name);
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ return c->Value == 0 ? false : true;
+}
+
+// Release the Caps list
+void FreeCapsList(CAPSLIST *caps)
+{
+ UINT i;
+ // Validate arguments
+ if (caps == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(caps->CapsList);i++)
+ {
+ CAPS *c = LIST_DATA(caps->CapsList, i);
+
+ FreeCaps(c);
+ }
+
+ ReleaseList(caps->CapsList);
+ Free(caps);
+}
+
+// Get the Caps
+CAPS *GetCaps(CAPSLIST *caps, char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (caps == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(caps->CapsList);i++)
+ {
+ CAPS *c = LIST_DATA(caps->CapsList, i);
+
+ if (StrCmpi(c->Name, name) == 0)
+ {
+ return c;
+ }
+ }
+
+ return NULL;
+}
+
+// Add to the Caps
+void AddCaps(CAPSLIST *caps, CAPS *c)
+{
+ // Validate arguments
+ if (caps == NULL || c == NULL)
+ {
+ return;
+ }
+
+ Insert(caps->CapsList, c);
+}
+
+// Comparison of Caps
+int CompareCaps(void *p1, void *p2)
+{
+ CAPS *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(CAPS **)p1;
+ c2 = *(CAPS **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(c1->Name, c2->Name);
+}
+
+// Create a Caps list
+CAPSLIST *NewCapsList()
+{
+ CAPSLIST *caps = ZeroMalloc(sizeof(CAPSLIST));
+
+ caps->CapsList = NewListFast(CompareCaps);
+
+ return caps;
+}
+
+// Release the Caps
+void FreeCaps(CAPS *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ Free(c->Name);
+ Free(c);
+}
+
+// Create a Caps
+CAPS *NewCaps(char *name, UINT value)
+{
+ CAPS *c;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CAPS));
+ c->Name = CopyStr(name);
+ c->Value = value;
+
+ return c;
+}
+
+// Calculate the score from the current number of connections and weight
+UINT SiCalcPoint(SERVER *s, UINT num, UINT weight)
+{
+ UINT server_max_sessions = SERVER_MAX_SESSIONS;
+ if (s == NULL)
+ {
+ return 0;
+ }
+ if (weight == 0)
+ {
+ weight = 100;
+ }
+
+ server_max_sessions = GetServerCapsInt(s, "i_max_sessions");
+
+ return (UINT)(((double)server_max_sessions -
+ MIN((double)num * 100.0 / (double)weight, (double)server_max_sessions))
+ * (double)FARM_BASE_POINT / (double)server_max_sessions);
+}
+
+// Get the server score
+UINT SiGetPoint(SERVER *s)
+{
+ UINT num_session;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ num_session = Count(s->Cedar->CurrentSessions);
+
+ return SiCalcPoint(s, num_session, s->Weight);
+}
+
+// Generate the default certificate
+void SiGenerateDefaultCert(X **server_x, K **server_k)
+{
+ SiGenerateDefaultCertEx(server_x, server_k, NULL);
+}
+void SiGenerateDefaultCertEx(X **server_x, K **server_k, char *common_name)
+{
+ X *x;
+ K *private_key, *public_key;
+ NAME *name;
+ char tmp[MAX_SIZE];
+ wchar_t cn[MAX_SIZE];
+ // Validate arguments
+ if (server_x == NULL || server_k == NULL)
+ {
+ return;
+ }
+
+ // Create a key pair
+ RsaGen(&private_key, &public_key, 2048);
+
+ if (IsEmptyStr(common_name))
+ {
+ // Get the host name
+ StrCpy(tmp, sizeof(tmp), "server.softether.vpn");
+ GetMachineName(tmp, sizeof(tmp));
+ StrToUni(cn, sizeof(cn), tmp);
+ }
+ else
+ {
+ StrToUni(cn, sizeof(cn), common_name);
+ }
+
+ name = NewName(cn, cn, cn,
+ L"US", NULL, NULL);
+ x = NewRootX(public_key, private_key, name, MAX(GetDaysUntil2038(), SERVER_DEFAULT_CERT_DAYS), NULL);
+
+ *server_x = x;
+ *server_k = private_key;
+
+ FreeName(name);
+
+ FreeK(public_key);
+}
+
+// Set the server certificate to default
+void SiInitDefaultServerCert(SERVER *s)
+{
+ X *x = NULL;
+ K *k = NULL;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Generate a server certificate and private key
+ SiGenerateDefaultCert(&x, &k);
+
+ // Configure
+ SetCedarCert(s->Cedar, x, k);
+
+ FreeX(x);
+ FreeK(k);
+}
+
+// Set the encryption algorithm name to default
+void SiInitCipherName(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SetCedarCipherList(s->Cedar, SERVER_DEFAULT_CIPHER_NAME);
+}
+
+// Initialize the listener list
+void SiInitListenerList(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SiLockListenerList(s);
+ {
+ {
+ // Register the 4 ports (443, 992, 1194, 8888) as the default port
+ SiAddListener(s, SERVER_DEF_PORTS_1, true);
+ SiAddListener(s, SERVER_DEF_PORTS_2, true);
+ SiAddListener(s, SERVER_DEF_PORTS_3, true);
+ SiAddListener(s, SERVER_DEF_PORTS_4, true);
+ }
+ }
+ SiUnlockListenerList(s);
+}
+
+// Remove the listener
+bool SiDeleteListener(SERVER *s, UINT port)
+{
+ SERVER_LISTENER *e;
+ // Validate arguments
+ if (s == NULL || port == 0)
+ {
+ return false;
+ }
+
+ e = SiGetListener(s, port);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ // Stop if still alive
+ SiDisableListener(s, port);
+
+ if (e->Listener != NULL)
+ {
+ ReleaseListener(e->Listener);
+ }
+
+ Delete(s->ServerListenerList, e);
+ Free(e);
+
+ return true;
+}
+
+// Compare the SERVER_LISTENER
+int CompareServerListener(void *p1, void *p2)
+{
+ SERVER_LISTENER *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(SERVER_LISTENER **)p1;
+ s2 = *(SERVER_LISTENER **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ if (s1->Port > s2->Port)
+ {
+ return 1;
+ }
+ else if (s1->Port < s2->Port)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Stop the listener
+bool SiDisableListener(SERVER *s, UINT port)
+{
+ SERVER_LISTENER *e;
+ // Validate arguments
+ if (s == NULL || port == 0)
+ {
+ return false;
+ }
+
+ // Get the listener
+ e = SiGetListener(s, port);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ if (e->Enabled == false || e->Listener == NULL)
+ {
+ // Already stopped
+ return true;
+ }
+
+ // Stop the listener
+ StopListener(e->Listener);
+
+ // Release the listener
+ ReleaseListener(e->Listener);
+ e->Listener = NULL;
+
+ e->Enabled = false;
+
+ return true;
+}
+
+// Start the listener
+bool SiEnableListener(SERVER *s, UINT port)
+{
+ SERVER_LISTENER *e;
+ // Validate arguments
+ if (s == NULL || port == 0)
+ {
+ return false;
+ }
+
+ // Get the listener
+ e = SiGetListener(s, port);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ if (e->Enabled)
+ {
+ // It has already started
+ return true;
+ }
+
+ // Create a listener
+ e->Listener = NewListener(s->Cedar, LISTENER_TCP, e->Port);
+ if (e->Listener == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ e->Listener->DisableDos = e->DisableDos;
+
+ e->Enabled = true;
+
+ return true;
+}
+
+// Get the listener
+SERVER_LISTENER *SiGetListener(SERVER *s, UINT port)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ SERVER_LISTENER *e = LIST_DATA(s->ServerListenerList, i);
+ if (e->Port == port)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Add a listener
+bool SiAddListener(SERVER *s, UINT port, bool enabled)
+{
+ return SiAddListenerEx(s, port, enabled, false);
+}
+bool SiAddListenerEx(SERVER *s, UINT port, bool enabled, bool disable_dos)
+{
+ SERVER_LISTENER *e;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || port == 0)
+ {
+ return false;
+ }
+
+ // Check whether the listener exists already
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ e = LIST_DATA(s->ServerListenerList, i);
+ if (e->Port == port)
+ {
+ // Already exist
+ return false;
+ }
+ }
+
+ // Register by initializing a new listener
+ e = ZeroMalloc(sizeof(SERVER_LISTENER));
+ e->Enabled = enabled;
+ e->Port = port;
+ e->DisableDos = disable_dos;
+
+ if (e->Enabled)
+ {
+ // Create a listener
+ e->Listener = NewListener(s->Cedar, LISTENER_TCP, e->Port);
+ if (e->Listener != NULL)
+ {
+ e->Listener->DisableDos = e->DisableDos;
+ }
+ }
+
+ Insert(s->ServerListenerList, e);
+
+ return true;
+}
+
+// Lock the listener list
+void SiLockListenerList(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ LockList(s->ServerListenerList);
+}
+
+// Unlock the listener list
+void SiUnlockListenerList(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ UnlockList(s->ServerListenerList);
+}
+
+// Initialize the Bridge
+void SiInitBridge(SERVER *s)
+{
+ HUB *h;
+ HUB_OPTION o;
+ HUB_LOG g;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Zero(&o, sizeof(o));
+ o.MaxSession = 0;
+
+ h = NewHub(s->Cedar, SERVER_DEFAULT_BRIDGE_NAME, &o);
+ AddHub(s->Cedar, h);
+
+ h->Offline = true;
+ SetHubOnline(h);
+
+ // Log settings
+ SiSetDefaultLogSetting(&g);
+ SetHubLogSetting(h, &g);
+
+ ReleaseHub(h);
+}
+
+// Set the default value of the Virtual HUB options
+void SiSetDefaultHubOption(HUB_OPTION *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->MaxSession = 0;
+ o->VlanTypeId = MAC_PROTO_TAGVLAN;
+ o->NoIPv6DefaultRouterInRAWhenIPv6 = true;
+ o->ManageOnlyPrivateIP = true;
+ o->ManageOnlyLocalUnicastIPv6 = true;
+ o->NoMacAddressLog = true;
+ o->NoDhcpPacketLogOutsideHub = true;
+ o->AccessListIncludeFileCacheLifetime = ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME;
+ o->RemoveDefGwOnDhcpForLocalhost = true;
+}
+
+// Create a default virtual HUB
+void SiInitDefaultHubList(SERVER *s)
+{
+ HUB *h;
+ HUB_OPTION o;
+ HUB_LOG g;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Zero(&o, sizeof(o));
+
+ // Configure a default Virtual HUB management options
+ SiSetDefaultHubOption(&o);
+
+ h = NewHub(s->Cedar, s->Cedar->Bridge == false ? SERVER_DEFAULT_HUB_NAME : SERVER_DEFAULT_BRIDGE_NAME, &o);
+ h->CreatedTime = SystemTime64();
+ AddHub(s->Cedar, h);
+
+ if (s->Cedar->Bridge)
+ {
+ // Randomize the password
+ Rand(h->HashedPassword, sizeof(h->HashedPassword));
+ Rand(h->SecurePassword, sizeof(h->SecurePassword));
+ }
+
+ h->Offline = true;
+ SetHubOnline(h);
+
+ // Log settings
+ SiSetDefaultLogSetting(&g);
+ SetHubLogSetting(h, &g);
+
+ {
+ UINT i;
+ for (i = 0;i < 0;i++)
+ {
+ char tmp[MAX_SIZE];
+ USER *u;
+ sprintf(tmp, "user%u", i);
+ AcLock(h);
+ u = NewUser(tmp, L"test", L"", AUTHTYPE_ANONYMOUS, NULL);
+ AcAddUser(h, u);
+ ReleaseUser(u);
+ AcUnlock(h);
+ }
+ }
+
+ ReleaseHub(h);
+}
+
+// Set the log settings to default
+void SiSetDefaultLogSetting(HUB_LOG *g)
+{
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ Zero(g, sizeof(HUB_LOG));
+ g->SaveSecurityLog = true;
+ g->SecurityLogSwitchType = LOG_SWITCH_DAY;
+ g->SavePacketLog = true;
+ g->PacketLogSwitchType = LOG_SWITCH_DAY;
+ g->PacketLogConfig[PACKET_LOG_TCP_CONN] =
+ g->PacketLogConfig[PACKET_LOG_DHCP] = PACKET_LOG_HEADER;
+}
+
+// Test
+void SiTest(SERVER *s)
+{
+}
+
+// Set the initial configuration
+void SiLoadInitialConfiguration(SERVER *s)
+{
+ RPC_KEEP k;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Auto saving interval related
+ s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
+ s->BackupConfigOnlyWhenModified = true;
+
+ s->Weight = FARM_DEFAULT_WEIGHT;
+
+ // KEEP related
+ Zero(&k, sizeof(k));
+
+ {
+ k.UseKeepConnect = true;
+ }
+ k.KeepConnectPort = 80;
+ StrCpy(k.KeepConnectHost, sizeof(k.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
+ k.KeepConnectInterval = KEEP_INTERVAL_DEFAULT * 1000;
+ k.KeepConnectProtocol = CONNECTION_UDP;
+
+ Lock(s->Keep->lock);
+ {
+ KEEP *keep = s->Keep;
+ keep->Enable = k.UseKeepConnect;
+ keep->Server = true;
+ StrCpy(keep->ServerName, sizeof(keep->ServerName), k.KeepConnectHost);
+ keep->ServerPort = k.KeepConnectPort;
+ keep->UdpMode = k.KeepConnectProtocol;
+ keep->Interval = k.KeepConnectInterval;
+ }
+ Unlock(s->Keep->lock);
+
+ // Initialize the password
+ {
+ Hash(s->HashedPassword, "", 0, true);
+ }
+
+ // Set the encryption algorithm name to default
+ SiInitCipherName(s);
+
+ // Set the server certificate to default
+ SiInitDefaultServerCert(s);
+
+ // Create a default HUB
+ {
+ SiInitDefaultHubList(s);
+ }
+
+ if (s->Cedar->Bridge == false)
+ {
+ // Create a DDNS client
+ s->DDnsClient = NewDDNSClient(s->Cedar, NULL, NULL);
+ }
+
+
+ // Set the listener list to default setting
+ SiInitListenerList(s);
+
+ if (s->Cedar->Bridge)
+ {
+ // SSTP, OpenVPN, and NAT traversal function can not be used in the bridge environment
+ s->DisableNatTraversal = true;
+ s->DisableSSTPServer = true;
+ s->DisableOpenVPNServer = true;
+ }
+ else
+ {
+ // Enable the SSTP and OpenVPN for default setting
+ OPENVPN_SSTP_CONFIG c;
+
+ Zero(&c, sizeof(c));
+ c.EnableOpenVPN = true;
+ c.EnableSSTP = true;
+
+ {
+ ToStr(c.OpenVPNPortList, OPENVPN_UDP_PORT);
+ }
+
+ SiSetOpenVPNAndSSTPConfig(s, &c);
+
+ {
+ // Enable VPN-over-ICMP" and VPN-over-DNS for default setting
+ s->EnableVpnOverIcmp = SiCanOpenVpnOverIcmpPort();
+ s->EnableVpnOverDns = SiCanOpenVpnOverDnsPort();
+
+#ifdef OS_WIN32
+ // Over-DNS is disabled on Windows by default
+ s->EnableVpnOverDns = false;
+#endif // OS_WIN32
+ }
+ }
+
+ s->Eraser = NewEraser(s->Logger, 0);
+}
+
+// Check whether the ports required for VPN-over-ICMP can be opened
+bool SiCanOpenVpnOverIcmpPort()
+{
+ // Whether the ICMP can be opened
+ SOCK *s = NewUDP(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4));
+
+ if (s == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return true;
+}
+
+// Check whether the ports required for VPN-over-DNS can be opened
+bool SiCanOpenVpnOverDnsPort()
+{
+ // Whether UDP Port 53 can be listen on
+ SOCK *s = NewUDP(53);
+
+ if (s == NULL)
+ {
+ // Listening failure
+ return false;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return true;
+}
+
+// Read the configuration file (main)
+bool SiLoadConfigurationFileMain(SERVER *s, FOLDER *root)
+{
+ // Validate arguments
+ if (s == NULL || root == NULL)
+ {
+ return false;
+ }
+
+ return SiLoadConfigurationCfg(s, root);
+}
+
+// Read the configuration file
+bool SiLoadConfigurationFile(SERVER *s)
+{
+ // Validate arguments
+ bool ret = false;
+ FOLDER *root;
+ char *server_config_filename = SERVER_CONFIG_FILE_NAME;
+ if (s == NULL)
+ {
+ return false;
+ }
+
+
+ s->CfgRw = NewCfgRw(&root,
+ s->Cedar->Bridge == false ? server_config_filename : BRIDGE_CONFIG_FILE_NAME);
+
+ if (server_reset_setting)
+ {
+ CfgDeleteFolder(root);
+ root = NULL;
+ server_reset_setting = false;
+ }
+
+ if (root == NULL)
+ {
+ return false;
+ }
+
+ ret = SiLoadConfigurationFileMain(s, root);
+
+ CfgDeleteFolder(root);
+
+ return ret;
+}
+
+// Initialize the configuration
+void SiInitConfiguration(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
+ s->BackupConfigOnlyWhenModified = true;
+
+ // IPsec server
+ if (s->Cedar->Bridge == false)
+ {
+ s->IPsecServer = NewIPsecServer(s->Cedar);
+ }
+
+ // OpenVPN server (UDP)
+ if (s->Cedar->Bridge == false)
+ {
+ s->OpenVpnServerUdp = NewOpenVpnServerUdp(s->Cedar);
+ }
+
+ SLog(s->Cedar, "LS_LOAD_CONFIG_1");
+ if (SiLoadConfigurationFile(s) == false)
+ {
+ // Ethernet initialization
+ InitEth();
+
+ SLog(s->Cedar, "LS_LOAD_CONFIG_3");
+ SiLoadInitialConfiguration(s);
+
+ server_reset_setting = false;
+ }
+ else
+ {
+ SLog(s->Cedar, "LS_LOAD_CONFIG_2");
+ }
+
+ s->CfgRw->DontBackup = s->DontBackupConfig;
+
+ // The arp_filter in Linux
+ if (GetOsInfo()->OsType == OSTYPE_LINUX)
+ {
+ if (s->NoLinuxArpFilter == false)
+ {
+ SetLinuxArpFilter();
+ }
+ }
+
+ if (s->DisableDosProction)
+ {
+ DisableDosProtect();
+ }
+ else
+ {
+ EnableDosProtect();
+ }
+
+ s->AutoSaveConfigSpanSaved = s->AutoSaveConfigSpan;
+
+ // Create a VPN Azure client
+ if (s->DDnsClient != NULL && s->Cedar->Bridge == false && s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ s->AzureClient = NewAzureClient(s->Cedar, s);
+
+ AcSetEnable(s->AzureClient, s->EnableVpnAzure);
+ }
+
+ // Reduce the storage interval in the case of user mode
+#ifdef OS_WIN32
+ if (MsIsUserMode())
+ {
+ s->AutoSaveConfigSpan = MIN(s->AutoSaveConfigSpan, SERVER_FILE_SAVE_INTERVAL_USERMODE);
+ }
+#endif //OS_WIN32
+
+ // Create a saving thread
+ SLog(s->Cedar, "LS_INIT_SAVE_THREAD", s->AutoSaveConfigSpan / 1000);
+ s->SaveHaltEvent = NewEvent();
+ s->SaveThread = NewThread(SiSaverThread, s);
+}
+
+// Set the state of Enabled / Disabled of Azure Client
+void SiSetAzureEnable(SERVER *s, bool enabled)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->AzureClient != NULL)
+ {
+ AcSetEnable(s->AzureClient, enabled);
+ }
+
+ s->EnableVpnAzure = enabled;
+}
+
+// Get the state of Enabled / Disabled of Azure Client
+bool SiGetAzureEnable(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->AzureClient != NULL)
+ {
+ return AcGetEnable(s->AzureClient);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Apply the Config to the Azure Client
+void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ AcApplyCurrentConfig(s->AzureClient, ddns_status);
+}
+
+// Get whether the Azure Client is enabled
+bool SiIsAzureEnabled(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->AzureClient == NULL)
+ {
+ return false;
+ }
+
+ return s->EnableVpnAzure;
+}
+
+// Get whether the Azure Client is supported
+bool SiIsAzureSupported(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->AzureClient == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read the server settings from the CFG
+bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
+{
+ FOLDER *f1, *f2, *f3, *f4, *f5, *f6, *f7, *f8, *f;
+ bool is_vgs_enabled = false;
+ // Validate arguments
+ if (s == NULL || root == NULL)
+ {
+ return false;
+ }
+
+ f = NULL;
+
+
+ f1 = CfgGetFolder(root, "ServerConfiguration");
+ f2 = CfgGetFolder(root, "VirtualHUB");
+ f3 = CfgGetFolder(root, "ListenerList");
+ f4 = CfgGetFolder(root, "LocalBridgeList");
+ f5 = CfgGetFolder(root, "VirtualLayer3SwitchList");
+ f6 = CfgGetFolder(root, "LicenseManager");
+ f7 = CfgGetFolder(root, "IPsec");
+ f8 = CfgGetFolder(root, "DDnsClient");
+
+ if (f1 == NULL)
+ {
+ SLog(s->Cedar, "LS_BAD_CONFIG");
+ return false;
+ }
+
+#ifdef OS_WIN32
+ if (f4 != NULL)
+ {
+ // Read the flag of using the SeLow driver
+ bool b = true;
+
+ if (CfgIsItem(f4, "EnableSoftEtherKernelModeDriver"))
+ {
+ b = CfgGetBool(f4, "EnableSoftEtherKernelModeDriver");
+ }
+
+ Win32SetEnableSeLow(b);
+ }
+#endif // OS_WIN32
+
+ // Ethernet initialization
+ InitEth();
+
+ s->ConfigRevision = CfgGetInt(root, "ConfigRevision");
+
+ if (s->Cedar->Bridge == false && f6 != NULL)
+ {
+ if (GetServerCapsBool(s, "b_support_license"))
+ {
+ SiLoadLicenseManager(s, f6);
+ }
+ }
+
+ DestroyServerCapsCache(s);
+
+ SiLoadServerCfg(s, f1);
+
+ if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ SiLoadHubs(s, f2);
+ }
+
+ SiLoadListeners(s, f3);
+
+ if (f4 != NULL)
+ {
+ SiLoadLocalBridges(s, f4);
+ }
+
+ if (s->Cedar->Bridge == false && f5 != NULL)
+ {
+ SiLoadL3Switchs(s, f5);
+ }
+
+ if (f7 != NULL && GetServerCapsBool(s, "b_support_ipsec"))
+ {
+ SiLoadIPsec(s, f7);
+ }
+
+ if (s->Cedar->Bridge == false)
+ {
+ if (f8 == NULL)
+ {
+ // Create a DDNS client with a new key
+ s->DDnsClient = NewDDNSClient(s->Cedar, NULL, NULL);
+ }
+ else
+ {
+ // Create by reading the setting of the DDNS client
+ UCHAR key[SHA1_SIZE];
+ if (CfgGetBool(f8, "Disabled"))
+ {
+ // Disabled
+ }
+ else
+ {
+ char machine_name[MAX_SIZE];
+ char machine_name2[MAX_SIZE];
+ INTERNET_SETTING t;
+ BUF *pw;
+
+ // Proxy Setting
+ Zero(&t, sizeof(t));
+ t.ProxyType = CfgGetInt(f8, "ProxyType");
+ CfgGetStr(f8, "ProxyHostName", t.ProxyHostName, sizeof(t.ProxyHostName));
+ t.ProxyPort = CfgGetInt(f8, "ProxyPort");
+ CfgGetStr(f8, "ProxyUsername", t.ProxyUsername, sizeof(t.ProxyUsername));
+ pw = CfgGetBuf(f8, "ProxyPassword");
+ if (pw != NULL)
+ {
+ char *pw_str = DecryptPassword(pw);
+ StrCpy(t.ProxyPassword, sizeof(t.ProxyPassword), pw_str);
+
+ Free(pw_str);
+ FreeBuf(pw);
+ }
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+
+ CfgGetStr(f8, "LocalHostname", machine_name2, sizeof(machine_name2));
+
+ if (CfgGetByte(f8, "Key", key, sizeof(key)) != sizeof(key) || StrCmpi(machine_name, machine_name2) != 0)
+ {
+ // Create a DDNS client with a new key
+ s->DDnsClient = NewDDNSClient(s->Cedar, NULL, &t);
+ }
+ else
+ {
+ // Create the DDNS client with stored key
+ s->DDnsClient = NewDDNSClient(s->Cedar, key, &t);
+ }
+ }
+ }
+ }
+
+
+ {
+ HUB *h = NULL;
+
+ // Remove the virtual HUB "VPNGATE" when VGS disabled
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, VG_HUBNAME);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h != NULL)
+ {
+ StopHub(h);
+ DelHub(s->Cedar, h);
+ ReleaseHub(h);
+ }
+ }
+
+ s->IPsecMessageDisplayed = CfgGetBool(root, "IPsecMessageDisplayed");
+
+
+ return true;
+}
+
+// Write the listener configuration
+void SiWriteListenerCfg(FOLDER *f, SERVER_LISTENER *r)
+{
+ // Validate arguments
+ if (f == NULL || r == NULL)
+ {
+ return;
+ }
+
+ CfgAddBool(f, "Enabled", r->Enabled);
+ CfgAddInt(f, "Port", r->Port);
+ CfgAddBool(f, "DisableDos", r->DisableDos);
+}
+
+// Read the listener configuration
+void SiLoadListenerCfg(SERVER *s, FOLDER *f)
+{
+ bool enable;
+ UINT port;
+ bool disable_dos;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ enable = CfgGetBool(f, "Enabled");
+ port = CfgGetInt(f, "Port");
+ disable_dos = CfgGetBool(f, "DisableDos");
+
+ if (port == 0)
+ {
+ return;
+ }
+
+ SiAddListenerEx(s, port, enable, disable_dos);
+}
+
+// Read the listener list
+void SiLoadListeners(SERVER *s, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(f, t->Token[i]);
+ if (ff != NULL)
+ {
+ SiLoadListenerCfg(s, ff);
+ }
+ }
+ FreeToken(t);
+}
+
+// Write the listener list
+void SiWriteListeners(FOLDER *f, SERVER *s)
+{
+ // Validate arguments
+ if (f == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(s->ServerListenerList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ SERVER_LISTENER *r = LIST_DATA(s->ServerListenerList, i);
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "Listener%u", i);
+ SiWriteListenerCfg(CfgCreateFolder(f, name), r);
+ }
+ }
+ UnlockList(s->ServerListenerList);
+}
+
+// Write the bridge
+void SiWriteLocalBridgeCfg(FOLDER *f, LOCALBRIDGE *br)
+{
+ // Validate arguments
+ if (f == NULL || br == NULL)
+ {
+ return;
+ }
+
+ CfgAddStr(f, "DeviceName", br->DeviceName);
+ CfgAddStr(f, "HubName", br->HubName);
+ CfgAddBool(f, "NoPromiscuousMode", br->Local);
+ CfgAddBool(f, "MonitorMode", br->Monitor);
+ CfgAddBool(f, "LimitBroadcast", br->LimitBroadcast);
+
+ if (OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ CfgAddBool(f, "TapMode", br->TapMode);
+
+ if (br->TapMode)
+ {
+ char tmp[MAX_SIZE];
+ MacToStr(tmp, sizeof(tmp), br->TapMacAddress);
+ CfgAddStr(f, "TapMacAddress", tmp);
+ }
+ }
+}
+
+// Write the bridge list
+void SiWriteLocalBridges(FOLDER *f, SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ CfgAddBool(f, "ShowAllInterfaces", Win32EthGetShowAllIf());
+
+ CfgAddBool(f, "EnableSoftEtherKernelModeDriver", Win32GetEnableSeLow());
+#endif // OS_WIN32
+
+ LockList(s->Cedar->LocalBridgeList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(s->Cedar->LocalBridgeList);i++)
+ {
+ LOCALBRIDGE *br = LIST_DATA(s->Cedar->LocalBridgeList, i);
+ char name[MAX_SIZE];
+
+ Format(name, sizeof(name), "LocalBridge%u", i);
+ SiWriteLocalBridgeCfg(CfgCreateFolder(f, name), br);
+ }
+ }
+ UnlockList(s->Cedar->LocalBridgeList);
+}
+
+// Read the bridge
+void SiLoadLocalBridgeCfg(SERVER *s, FOLDER *f)
+{
+ char hub[MAX_SIZE];
+ char nic[MAX_SIZE];
+ bool tapmode = false;
+ UCHAR tapaddr[6];
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ Zero(hub, sizeof(hub));
+ Zero(nic, sizeof(nic));
+
+ CfgGetStr(f, "HubName", hub, sizeof(hub));
+ CfgGetStr(f, "DeviceName", nic, sizeof(nic));
+
+ if (IsEmptyStr(hub) || IsEmptyStr(nic)
+ )
+ {
+ return;
+ }
+
+ if (OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ if (CfgGetBool(f, "TapMode"))
+ {
+ char tmp[MAX_SIZE];
+ tapmode = true;
+ Zero(tapaddr, sizeof(tapaddr));
+ if (CfgGetStr(f, "TapMacAddress", tmp, sizeof(tmp)))
+ {
+ BUF *b;
+ b = StrToBin(tmp);
+ if (b != NULL && b->Size == 6)
+ {
+ Copy(tapaddr, b->Buf, sizeof(tapaddr));
+ }
+ FreeBuf(b);
+ }
+ }
+ }
+
+ AddLocalBridge(s->Cedar, hub, nic, CfgGetBool(f, "NoPromiscuousMode"), CfgGetBool(f, "MonitorMode"),
+ tapmode, tapaddr, CfgGetBool(f, "LimitBroadcast"));
+}
+
+// Read the bridge list
+void SiLoadLocalBridges(SERVER *s, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32EthSetShowAllIf(CfgGetBool(f, "ShowAllInterfaces"));
+#endif // OS_WIN32
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+
+ SiLoadLocalBridgeCfg(s, CfgGetFolder(f, name));
+ }
+
+ FreeToken(t);
+}
+
+// Increment the configuration revision of the server
+void IncrementServerConfigRevision(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ s->ConfigRevision++;
+}
+
+// Write the server settings to CFG
+FOLDER *SiWriteConfigurationToCfg(SERVER *s)
+{
+ FOLDER *root;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+
+ CfgAddInt(root, "ConfigRevision", s->ConfigRevision);
+
+ SiWriteListeners(CfgCreateFolder(root, "ListenerList"), s);
+
+ SiWriteLocalBridges(CfgCreateFolder(root, "LocalBridgeList"), s);
+
+ SiWriteServerCfg(CfgCreateFolder(root, "ServerConfiguration"), s);
+
+
+ if (s->UpdatedServerType != SERVER_TYPE_FARM_MEMBER)
+ {
+ SiWriteHubs(CfgCreateFolder(root, "VirtualHUB"), s);
+ }
+
+ if (s->Cedar->Bridge == false)
+ {
+ SiWriteL3Switchs(CfgCreateFolder(root, "VirtualLayer3SwitchList"), s);
+
+ if (GetServerCapsBool(s, "b_support_license"))
+ {
+ SiWriteLicenseManager(CfgCreateFolder(root, "LicenseManager"), s);
+ }
+ }
+
+ if (s->Led)
+ {
+ CfgAddBool(root, "Led", true);
+ CfgAddBool(root, "LedSpecial", s->LedSpecial);
+ }
+
+ if (GetServerCapsBool(s, "b_support_ipsec"))
+ {
+ SiWriteIPsec(CfgCreateFolder(root, "IPsec"), s);
+ }
+
+ if (s->Cedar->Bridge == false)
+ {
+ FOLDER *ddns_folder = CfgCreateFolder(root, "DDnsClient");
+
+ if (s->DDnsClient == NULL)
+ {
+ // Disabled
+ CfgAddBool(ddns_folder, "Disabled", true);
+ }
+ else
+ {
+ char machine_name[MAX_SIZE];
+ BUF *pw;
+ INTERNET_SETTING *t;
+ // Enabled
+ CfgAddBool(ddns_folder, "Disabled", false);
+ CfgAddByte(ddns_folder, "Key", s->DDnsClient->Key, SHA1_SIZE);
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ CfgAddStr(ddns_folder, "LocalHostname", machine_name);
+
+ t = &s->DDnsClient->InternetSetting;
+
+ CfgAddInt(ddns_folder, "ProxyType", t->ProxyType);
+ CfgAddStr(ddns_folder, "ProxyHostName", t->ProxyHostName);
+ CfgAddInt(ddns_folder, "ProxyPort", t->ProxyPort);
+ CfgAddStr(ddns_folder, "ProxyUsername", t->ProxyUsername);
+
+ if (IsEmptyStr(t->ProxyPassword) == false)
+ {
+ pw = EncryptPassword(t->ProxyPassword);
+
+ CfgAddBuf(ddns_folder, "ProxyPassword", pw);
+
+ FreeBuf(pw);
+ }
+ }
+ }
+
+ CfgAddBool(root, "IPsecMessageDisplayed", s->IPsecMessageDisplayed);
+
+
+ return root;
+}
+
+// Read the policy
+void SiLoadPolicyCfg(POLICY *p, FOLDER *f)
+{
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Zero(p, sizeof(POLICY));
+
+ // Ver 2
+ p->Access = CfgGetBool(f, "Access");
+ p->DHCPFilter = CfgGetBool(f, "DHCPFilter");
+ p->DHCPNoServer = CfgGetBool(f, "DHCPNoServer");
+ p->DHCPForce = CfgGetBool(f, "DHCPForce");
+ p->NoBridge = CfgGetBool(f, "NoBridge");
+ p->NoRouting = CfgGetBool(f, "NoRouting");
+ p->CheckMac = CfgGetBool(f, "CheckMac");
+ p->CheckIP = CfgGetBool(f, "CheckIP");
+ p->ArpDhcpOnly = CfgGetBool(f, "ArpDhcpOnly");
+ p->PrivacyFilter = CfgGetBool(f, "PrivacyFilter");
+ p->NoServer = CfgGetBool(f, "NoServer");
+ p->NoBroadcastLimiter = CfgGetBool(f, "NoBroadcastLimiter");
+ p->MonitorPort = CfgGetBool(f, "MonitorPort");
+ p->MaxConnection = CfgGetInt(f, "MaxConnection");
+ p->TimeOut = CfgGetInt(f, "TimeOut");
+ p->MaxMac = CfgGetInt(f, "MaxMac");
+ p->MaxIP = CfgGetInt(f, "MaxIP");
+ p->MaxUpload = CfgGetInt(f, "MaxUpload");
+ p->MaxDownload = CfgGetInt(f, "MaxDownload");
+ p->FixPassword = CfgGetBool(f, "FixPassword");
+ p->MultiLogins = CfgGetInt(f, "MultiLogins");
+ p->NoQoS = CfgGetBool(f, "NoQoS");
+
+ // Ver 3
+ p->RSandRAFilter = CfgGetBool(f, "RSandRAFilter");
+ p->RAFilter = CfgGetBool(f, "RAFilter");
+ p->DHCPv6Filter = CfgGetBool(f, "DHCPv6Filter");
+ p->DHCPv6NoServer = CfgGetBool(f, "DHCPv6NoServer");
+ p->NoRoutingV6 = CfgGetBool(f, "NoRoutingV6");
+ p->CheckIPv6 = CfgGetBool(f, "CheckIPv6");
+ p->NoServerV6 = CfgGetBool(f, "NoServerV6");
+ p->MaxIPv6 = CfgGetInt(f, "MaxIPv6");
+ p->NoSavePassword = CfgGetBool(f, "NoSavePassword");
+ p->AutoDisconnect = CfgGetInt(f, "AutoDisconnect");
+ p->FilterIPv4 = CfgGetBool(f, "FilterIPv4");
+ p->FilterIPv6 = CfgGetBool(f, "FilterIPv6");
+ p->FilterNonIP = CfgGetBool(f, "FilterNonIP");
+ p->NoIPv6DefaultRouterInRA = CfgGetBool(f, "NoIPv6DefaultRouterInRA");
+ p->NoIPv6DefaultRouterInRAWhenIPv6 = CfgGetBool(f, "NoIPv6DefaultRouterInRAWhenIPv6");
+ p->VLanId = CfgGetInt(f, "VLanId");
+}
+
+// Write the policy
+void SiWritePolicyCfg(FOLDER *f, POLICY *p, bool cascade_mode)
+{
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Ver 2.0
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "Access", p->Access);
+ }
+
+ CfgAddBool(f, "DHCPFilter", p->DHCPFilter);
+ CfgAddBool(f, "DHCPNoServer", p->DHCPNoServer);
+ CfgAddBool(f, "DHCPForce", p->DHCPForce);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "NoBridge", p->NoBridge);
+ CfgAddBool(f, "NoRouting", p->NoRouting);
+ }
+
+ CfgAddBool(f, "CheckMac", p->CheckMac);
+ CfgAddBool(f, "CheckIP", p->CheckIP);
+ CfgAddBool(f, "ArpDhcpOnly", p->ArpDhcpOnly);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "PrivacyFilter", p->PrivacyFilter);
+ }
+
+ CfgAddBool(f, "NoServer", p->NoServer);
+ CfgAddBool(f, "NoBroadcastLimiter", p->NoBroadcastLimiter);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "MonitorPort", p->MonitorPort);
+ CfgAddInt(f, "MaxConnection", p->MaxConnection);
+ CfgAddInt(f, "TimeOut", p->TimeOut);
+ }
+
+ CfgAddInt(f, "MaxMac", p->MaxMac);
+ CfgAddInt(f, "MaxIP", p->MaxIP);
+ CfgAddInt(f, "MaxUpload", p->MaxUpload);
+ CfgAddInt(f, "MaxDownload", p->MaxDownload);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "FixPassword", p->FixPassword);
+ CfgAddInt(f, "MultiLogins", p->MultiLogins);
+ CfgAddBool(f, "NoQoS", p->NoQoS);
+ }
+
+ // Ver 3.0
+ CfgAddBool(f, "RSandRAFilter", p->RSandRAFilter);
+ CfgAddBool(f, "RAFilter", p->RAFilter);
+ CfgAddBool(f, "DHCPv6Filter", p->DHCPv6Filter);
+ CfgAddBool(f, "DHCPv6NoServer", p->DHCPv6NoServer);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "NoRoutingV6", p->NoRoutingV6);
+ }
+
+ CfgAddBool(f, "CheckIPv6", p->CheckIPv6);
+ CfgAddBool(f, "NoServerV6", p->NoServerV6);
+ CfgAddInt(f, "MaxIPv6", p->MaxIPv6);
+
+ if (cascade_mode == false)
+ {
+ CfgAddBool(f, "NoSavePassword", p->NoSavePassword);
+ CfgAddInt(f, "AutoDisconnect", p->AutoDisconnect);
+ }
+
+ CfgAddBool(f, "FilterIPv4", p->FilterIPv4);
+ CfgAddBool(f, "FilterIPv6", p->FilterIPv6);
+ CfgAddBool(f, "FilterNonIP", p->FilterNonIP);
+ CfgAddBool(f, "NoIPv6DefaultRouterInRA", p->NoIPv6DefaultRouterInRA);
+ CfgAddBool(f, "NoIPv6DefaultRouterInRAWhenIPv6", p->NoIPv6DefaultRouterInRAWhenIPv6);
+ CfgAddInt(f, "VLanId", p->VLanId);
+}
+
+// Write the link information of the Virtual HUB
+void SiWriteHubLinkCfg(FOLDER *f, LINK *k)
+{
+ // Validate arguments
+ if (f == NULL || k == NULL)
+ {
+ return;
+ }
+
+ Lock(k->lock);
+ {
+ // Online
+ CfgAddBool(f, "Online", k->Offline ? false : true);
+
+ // Client options
+ CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), k->Option);
+
+ // Client authentication data
+ CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), k->Auth);
+
+ // Policy
+ if (k->Policy != NULL)
+ {
+ SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), k->Policy, true);
+ }
+
+ CfgAddBool(f, "CheckServerCert", k->CheckServerCert);
+
+ if (k->ServerCert != NULL)
+ {
+ BUF *b = XToBuf(k->ServerCert, false);
+ CfgAddBuf(f, "ServerCert", b);
+ FreeBuf(b);
+ }
+ }
+ Unlock(k->lock);
+}
+
+// Read the link information
+void SiLoadHubLinkCfg(FOLDER *f, HUB *h)
+{
+ bool online;
+ CLIENT_OPTION *o;
+ CLIENT_AUTH *a;
+ FOLDER *pf;
+ POLICY p;
+ LINK *k;
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ pf = CfgGetFolder(f, "Policy");
+ if (pf == NULL)
+ {
+ return;
+ }
+
+ SiLoadPolicyCfg(&p, pf);
+
+ online = CfgGetBool(f, "Online");
+
+ o = CiLoadClientOption(CfgGetFolder(f, "ClientOption"));
+ a = CiLoadClientAuth(CfgGetFolder(f, "ClientAuth"));
+ if (o == NULL || a == NULL)
+ {
+ Free(o);
+ CiFreeClientAuth(a);
+ return;
+ }
+
+ k = NewLink(h->Cedar, h, o, a, &p);
+ if (k != NULL)
+ {
+ BUF *b;
+ k->CheckServerCert = CfgGetBool(f, "CheckServerCert");
+ b = CfgGetBuf(f, "ServerCert");
+ if (b != NULL)
+ {
+ k->ServerCert = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ if (online)
+ {
+ k->Offline = true;
+ SetLinkOnline(k);
+ }
+ else
+ {
+ k->Offline = false;
+ SetLinkOffline(k);
+ }
+ ReleaseLink(k);
+ }
+
+ Free(o);
+ CiFreeClientAuth(a);
+}
+
+// Write the SecureNAT of the Virtual HUB
+void SiWriteSecureNAT(HUB *h, FOLDER *f)
+{
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ CfgAddBool(f, "Disabled", h->EnableSecureNAT ? false : true);
+
+ NiWriteVhOptionEx(h->SecureNATOption, f);
+}
+
+// Read the administration options for the virtual HUB
+void SiLoadHubAdminOptions(HUB *h, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumItemToTokenList(f);
+ if (t != NULL)
+ {
+ UINT i;
+
+ LockList(h->AdminOptionList);
+ {
+ DeleteAllHubAdminOption(h, false);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ ADMIN_OPTION *a;
+ UINT value = CfgGetInt(f, name);;
+
+ Trim(name);
+
+ a = ZeroMalloc(sizeof(ADMIN_OPTION));
+ StrCpy(a->Name, sizeof(a->Name), name);
+ a->Value = value;
+
+ Insert(h->AdminOptionList, a);
+ }
+
+ AddHubAdminOptionsDefaults(h, false);
+ }
+ UnlockList(h->AdminOptionList);
+
+ FreeToken(t);
+ }
+}
+
+// Write the administration options for the virtual HUB
+void SiWriteHubAdminOptions(FOLDER *f, HUB *h)
+{
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->AdminOptionList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
+ {
+ ADMIN_OPTION *a = LIST_DATA(h->AdminOptionList, i);
+
+ CfgAddInt(f, a->Name, a->Value);
+ }
+ }
+ UnlockList(h->AdminOptionList);
+}
+
+// Write the link list of the Virtual HUB
+void SiWriteHubLinks(FOLDER *f, HUB *h)
+{
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->LinkList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->LinkList);i++)
+ {
+ LINK *k = LIST_DATA(h->LinkList, i);
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "Cascade%u", i);
+ SiWriteHubLinkCfg(CfgCreateFolder(f, name), k);
+ }
+ }
+ UnlockList(h->LinkList);
+}
+
+// Read the link list
+void SiLoadHubLinks(HUB *h, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ SiLoadHubLinkCfg(CfgGetFolder(f, name), h);
+ }
+
+ FreeToken(t);
+}
+
+// Write an item of the access list
+void SiWriteHubAccessCfg(FOLDER *f, ACCESS *a)
+{
+ // Validate arguments
+ if (f == NULL || a == NULL)
+ {
+ return;
+ }
+
+ CfgAddUniStr(f, "Note", a->Note);
+ CfgAddBool(f, "Active", a->Active);
+ CfgAddInt(f, "Priority", a->Priority);
+ CfgAddBool(f, "Discard", a->Discard);
+ CfgAddBool(f, "IsIPv6", a->IsIPv6);
+
+ if (a->IsIPv6 == false)
+ {
+ CfgAddIp32(f, "SrcIpAddress", a->SrcIpAddress);
+ CfgAddIp32(f, "SrcSubnetMask", a->SrcSubnetMask);
+ CfgAddIp32(f, "DestIpAddress", a->DestIpAddress);
+ CfgAddIp32(f, "DestSubnetMask", a->DestSubnetMask);
+ }
+ else
+ {
+ CfgAddIp6Addr(f, "SrcIpAddress6", &a->SrcIpAddress6);
+ CfgAddIp6Addr(f, "SrcSubnetMask6", &a->SrcSubnetMask6);
+ CfgAddIp6Addr(f, "DestIpAddress6", &a->DestIpAddress6);
+ CfgAddIp6Addr(f, "DestSubnetMask6", &a->DestSubnetMask6);
+ }
+
+ CfgAddInt(f, "Protocol", a->Protocol);
+ CfgAddInt(f, "SrcPortStart", a->SrcPortStart);
+ CfgAddInt(f, "SrcPortEnd", a->SrcPortEnd);
+ CfgAddInt(f, "DestPortStart", a->DestPortStart);
+ CfgAddInt(f, "DestPortEnd", a->DestPortEnd);
+ CfgAddStr(f, "SrcUsername", a->SrcUsername);
+ CfgAddStr(f, "DestUsername", a->DestUsername);
+ CfgAddBool(f, "CheckSrcMac", a->CheckSrcMac);
+
+ if (a->CheckSrcMac)
+ {
+ char tmp[MAX_PATH];
+
+ MacToStr(tmp, sizeof(tmp), a->SrcMacAddress);
+ CfgAddStr(f, "SrcMacAddress", tmp);
+
+ MacToStr(tmp, sizeof(tmp), a->SrcMacMask);
+ CfgAddStr(f, "SrcMacMask", tmp);
+ }
+
+ CfgAddBool(f, "CheckDstMac", a->CheckDstMac);
+
+ if (a->CheckDstMac)
+ {
+ char tmp[MAX_PATH];
+
+ MacToStr(tmp, sizeof(tmp), a->DstMacAddress);
+ CfgAddStr(f, "DstMacAddress", tmp);
+
+ MacToStr(tmp, sizeof(tmp), a->DstMacMask);
+ CfgAddStr(f, "DstMacMask", tmp);
+ }
+
+ CfgAddBool(f, "CheckTcpState", a->CheckTcpState);
+ CfgAddBool(f, "Established", a->Established);
+
+ CfgAddStr(f, "RedirectUrl", a->RedirectUrl);
+
+ CfgAddInt(f, "Delay", a->Delay);
+ CfgAddInt(f, "Jitter", a->Jitter);
+ CfgAddInt(f, "Loss", a->Loss);
+}
+
+// Read an item of the access list
+void SiLoadHubAccessCfg(HUB *h, FOLDER *f)
+{
+ ACCESS a;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+
+ CfgGetUniStr(f, "Note", a.Note, sizeof(a.Note));
+ a.Active = CfgGetBool(f, "Active");
+ a.Priority = CfgGetInt(f, "Priority");
+ a.Discard = CfgGetBool(f, "Discard");
+ a.IsIPv6 = CfgGetBool(f, "IsIPv6");
+
+ if (a.IsIPv6 == false)
+ {
+ a.SrcIpAddress = CfgGetIp32(f, "SrcIpAddress");
+ a.SrcSubnetMask = CfgGetIp32(f, "SrcSubnetMask");
+ a.DestIpAddress = CfgGetIp32(f, "DestIpAddress");
+ a.DestSubnetMask = CfgGetIp32(f, "DestSubnetMask");
+ }
+ else
+ {
+ CfgGetIp6Addr(f, "SrcIpAddress6", &a.SrcIpAddress6);
+ CfgGetIp6Addr(f, "SrcSubnetMask6", &a.SrcSubnetMask6);
+ CfgGetIp6Addr(f, "DestIpAddress6", &a.DestIpAddress6);
+ CfgGetIp6Addr(f, "DestSubnetMask6", &a.DestSubnetMask6);
+ }
+
+ a.Protocol = CfgGetInt(f, "Protocol");
+ a.SrcPortStart = CfgGetInt(f, "SrcPortStart");
+ a.SrcPortEnd = CfgGetInt(f, "SrcPortEnd");
+ a.DestPortStart = CfgGetInt(f, "DestPortStart");
+ a.DestPortEnd = CfgGetInt(f, "DestPortEnd");
+ CfgGetStr(f, "SrcUsername", a.SrcUsername, sizeof(a.SrcUsername));
+ CfgGetStr(f, "DestUsername", a.DestUsername, sizeof(a.DestUsername));
+ a.CheckSrcMac = CfgGetBool(f, "CheckSrcMac");
+
+ if (CfgGetByte(f, "SrcMacAddress", a.SrcMacAddress, sizeof(a.SrcMacAddress)) == 0)
+ {
+ CfgGetStr(f, "SrcMacAddress", tmp, sizeof(tmp));
+ if (StrToMac(a.SrcMacAddress, tmp) == false)
+ {
+ a.CheckSrcMac = false;
+ }
+ }
+
+ if (CfgGetByte(f, "SrcMacMask", a.SrcMacMask, sizeof(a.SrcMacMask)) == 0)
+ {
+ CfgGetStr(f, "SrcMacMask", tmp, sizeof(tmp));
+ if (StrToMac(a.SrcMacMask, tmp) == false)
+ {
+ a.CheckSrcMac = false;
+ }
+ }
+
+ a.CheckDstMac = CfgGetBool(f, "CheckDstMac");
+
+ if (CfgGetByte(f, "DstMacAddress", a.DstMacAddress, sizeof(a.DstMacAddress)) == 0)
+ {
+ CfgGetStr(f, "DstMacAddress", tmp, sizeof(tmp));
+ if (StrToMac(a.DstMacAddress, tmp) == false)
+ {
+ a.CheckDstMac = false;
+ }
+ }
+
+ if (CfgGetByte(f, "DstMacMask", a.DstMacMask, sizeof(a.DstMacMask)) == 0)
+ {
+ CfgGetStr(f, "DstMacMask", tmp, sizeof(tmp));
+ if (StrToMac(a.DstMacMask, tmp) == false)
+ {
+ a.CheckDstMac = false;
+ }
+ }
+
+ a.CheckTcpState = CfgGetBool(f, "CheckTcpState");
+ a.Established = CfgGetBool(f, "Established");
+ a.Delay = MAKESURE(CfgGetInt(f, "Delay"), 0, HUB_ACCESSLIST_DELAY_MAX);
+ a.Jitter = MAKESURE(CfgGetInt(f, "Jitter"), 0, HUB_ACCESSLIST_JITTER_MAX);
+ a.Loss = MAKESURE(CfgGetInt(f, "Loss"), 0, HUB_ACCESSLIST_LOSS_MAX);
+
+ CfgGetStr(f, "RedirectUrl", a.RedirectUrl, sizeof(a.RedirectUrl));
+
+ AddAccessList(h, &a);
+}
+
+// Write the access list
+void SiWriteHubAccessLists(FOLDER *f, HUB *h)
+{
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->AccessList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(h->AccessList, i);
+ char name[MAX_SIZE];
+ ToStr(name, a->Id);
+ SiWriteHubAccessCfg(CfgCreateFolder(f, name), a);
+ }
+ }
+ UnlockList(h->AccessList);
+}
+
+// Read the access list
+void SiLoadHubAccessLists(HUB *h, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ UINT id = ToInt(name);
+ SiLoadHubAccessCfg(h, CfgGetFolder(f, name));
+ }
+
+ FreeToken(t);
+}
+
+// Read the HUB_OPTION
+void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ o->MaxSession = CfgGetInt(f, "MaxSession");
+ o->NoArpPolling = CfgGetBool(f, "NoArpPolling");
+ o->NoIPv6AddrPolling = CfgGetBool(f, "NoIPv6AddrPolling");
+ o->NoIpTable = CfgGetBool(f, "NoIpTable");
+ o->NoEnum = CfgGetBool(f, "NoEnum");
+ o->FilterPPPoE = CfgGetBool(f, "FilterPPPoE");
+ o->FilterOSPF = CfgGetBool(f, "FilterOSPF");
+ o->FilterIPv4 = CfgGetBool(f, "FilterIPv4");
+ o->FilterIPv6 = CfgGetBool(f, "FilterIPv6");
+ o->FilterNonIP = CfgGetBool(f, "FilterNonIP");
+ o->FilterBPDU = CfgGetBool(f, "FilterBPDU");
+ o->NoIPv4PacketLog = CfgGetBool(f, "NoIPv4PacketLog");
+ o->NoIPv6PacketLog = CfgGetBool(f, "NoIPv6PacketLog");
+ o->NoIPv6DefaultRouterInRAWhenIPv6 = CfgGetBool(f, "NoIPv6DefaultRouterInRAWhenIPv6");
+ o->DisableIPParsing = CfgGetBool(f, "DisableIPParsing");
+ o->YieldAfterStorePacket = CfgGetBool(f, "YieldAfterStorePacket");
+ o->NoSpinLockForPacketDelay = CfgGetBool(f, "NoSpinLockForPacketDelay");
+ o->BroadcastStormDetectionThreshold = CfgGetInt(f, "BroadcastStormDetectionThreshold");
+ o->ClientMinimumRequiredBuild = CfgGetInt(f, "ClientMinimumRequiredBuild");
+ o->RequiredClientId = CfgGetInt(f, "RequiredClientId");
+ o->NoManageVlanId = CfgGetBool(f, "NoManageVlanId");
+ o->VlanTypeId = 0;
+ if (CfgGetStr(f, "VlanTypeId", tmp, sizeof(tmp)))
+ {
+ o->VlanTypeId = HexToInt(tmp);
+ }
+ if (o->VlanTypeId == 0)
+ {
+ o->VlanTypeId = MAC_PROTO_TAGVLAN;
+ }
+ o->FixForDLinkBPDU = CfgGetBool(f, "FixForDLinkBPDU");
+ o->BroadcastLimiterStrictMode = CfgGetBool(f, "BroadcastLimiterStrictMode");
+ o->MaxLoggedPacketsPerMinute = CfgGetInt(f, "MaxLoggedPacketsPerMinute");
+ o->DoNotSaveHeavySecurityLogs = CfgGetBool(f, "DoNotSaveHeavySecurityLogs");
+ o->NoLookBPDUBridgeId = CfgGetBool(f, "NoLookBPDUBridgeId");
+ o->AdjustTcpMssValue = CfgGetInt(f, "AdjustTcpMssValue");
+ o->DisableAdjustTcpMss = CfgGetBool(f, "DisableAdjustTcpMss");
+ if (CfgIsItem(f, "NoDhcpPacketLogOutsideHub"))
+ {
+ o->NoDhcpPacketLogOutsideHub = CfgGetBool(f, "NoDhcpPacketLogOutsideHub");
+ }
+ else
+ {
+ o->NoDhcpPacketLogOutsideHub = true;
+ }
+ o->DisableHttpParsing = CfgGetBool(f, "DisableHttpParsing");
+ o->DisableUdpAcceleration = CfgGetBool(f, "DisableUdpAcceleration");
+ o->DisableUdpFilterForLocalBridgeNic = CfgGetBool(f, "DisableUdpFilterForLocalBridgeNic");
+ o->ApplyIPv4AccessListOnArpPacket = CfgGetBool(f, "ApplyIPv4AccessListOnArpPacket");
+ if (CfgIsItem(f, "RemoveDefGwOnDhcpForLocalhost"))
+ {
+ o->RemoveDefGwOnDhcpForLocalhost = CfgGetBool(f, "RemoveDefGwOnDhcpForLocalhost");
+ }
+ else
+ {
+ o->RemoveDefGwOnDhcpForLocalhost = true;
+ }
+ o->SecureNAT_MaxTcpSessionsPerIp = CfgGetInt(f, "SecureNAT_MaxTcpSessionsPerIp");
+ o->SecureNAT_MaxTcpSynSentPerIp = CfgGetInt(f, "SecureNAT_MaxTcpSynSentPerIp");
+ o->SecureNAT_MaxUdpSessionsPerIp = CfgGetInt(f, "SecureNAT_MaxUdpSessionsPerIp");
+ o->SecureNAT_MaxDnsSessionsPerIp = CfgGetInt(f, "SecureNAT_MaxDnsSessionsPerIp");
+ o->SecureNAT_MaxIcmpSessionsPerIp = CfgGetInt(f, "SecureNAT_MaxIcmpSessionsPerIp");
+ o->AccessListIncludeFileCacheLifetime = CfgGetInt(f, "AccessListIncludeFileCacheLifetime");
+
+ if (o->AccessListIncludeFileCacheLifetime == 0)
+ {
+ o->AccessListIncludeFileCacheLifetime = ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME;
+ }
+
+ o->DisableKernelModeSecureNAT = CfgGetBool(f, "DisableKernelModeSecureNAT");
+ o->DisableUserModeSecureNAT = CfgGetBool(f, "DisableUserModeSecureNAT");
+ o->DisableCheckMacOnLocalBridge = CfgGetBool(f, "DisableCheckMacOnLocalBridge");
+ o->DisableCorrectIpOffloadChecksum = CfgGetBool(f, "DisableCorrectIpOffloadChecksum");
+
+ // Enabled by default
+ if (CfgIsItem(f, "ManageOnlyPrivateIP"))
+ {
+ o->ManageOnlyPrivateIP = CfgGetBool(f, "ManageOnlyPrivateIP");
+ }
+ else
+ {
+ o->ManageOnlyPrivateIP = true;
+ }
+ if (CfgIsItem(f, "ManageOnlyLocalUnicastIPv6"))
+ {
+ o->ManageOnlyLocalUnicastIPv6 = CfgGetBool(f, "ManageOnlyLocalUnicastIPv6");
+ }
+ else
+ {
+ o->ManageOnlyLocalUnicastIPv6 = true;
+ }
+ if (CfgIsItem(f, "NoMacAddressLog"))
+ {
+ o->NoMacAddressLog = CfgGetBool(f, "NoMacAddressLog");
+ }
+ else
+ {
+ o->NoMacAddressLog = true;
+ }
+}
+
+// Write the HUB_OPTION
+void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ CfgAddInt(f, "MaxSession", o->MaxSession);
+ CfgAddBool(f, "NoArpPolling", o->NoArpPolling);
+ CfgAddBool(f, "NoIPv6AddrPolling", o->NoIPv6AddrPolling);
+ CfgAddBool(f, "NoIpTable", o->NoIpTable);
+ CfgAddBool(f, "NoEnum", o->NoEnum);
+ CfgAddBool(f, "FilterPPPoE", o->FilterPPPoE);
+ CfgAddBool(f, "FilterOSPF", o->FilterOSPF);
+ CfgAddBool(f, "FilterIPv4", o->FilterIPv4);
+ CfgAddBool(f, "FilterIPv6", o->FilterIPv6);
+ CfgAddBool(f, "FilterNonIP", o->FilterNonIP);
+ CfgAddBool(f, "NoIPv4PacketLog", o->NoIPv4PacketLog);
+ CfgAddBool(f, "NoIPv6PacketLog", o->NoIPv6PacketLog);
+ CfgAddBool(f, "FilterBPDU", o->FilterBPDU);
+ CfgAddBool(f, "NoIPv6DefaultRouterInRAWhenIPv6", o->NoIPv6DefaultRouterInRAWhenIPv6);
+ CfgAddBool(f, "NoMacAddressLog", o->NoMacAddressLog);
+ CfgAddBool(f, "ManageOnlyPrivateIP", o->ManageOnlyPrivateIP);
+ CfgAddBool(f, "ManageOnlyLocalUnicastIPv6", o->ManageOnlyLocalUnicastIPv6);
+ CfgAddBool(f, "DisableIPParsing", o->DisableIPParsing);
+ CfgAddBool(f, "YieldAfterStorePacket", o->YieldAfterStorePacket);
+ CfgAddBool(f, "NoSpinLockForPacketDelay", o->NoSpinLockForPacketDelay);
+ CfgAddInt(f, "BroadcastStormDetectionThreshold", o->BroadcastStormDetectionThreshold);
+ CfgAddInt(f, "ClientMinimumRequiredBuild", o->ClientMinimumRequiredBuild);
+ CfgAddInt(f, "RequiredClientId", o->RequiredClientId);
+ CfgAddBool(f, "NoManageVlanId", o->NoManageVlanId);
+ Format(tmp, sizeof(tmp), "0x%x", o->VlanTypeId);
+ CfgAddStr(f, "VlanTypeId", tmp);
+ if (o->FixForDLinkBPDU)
+ {
+ CfgAddBool(f, "FixForDLinkBPDU", o->FixForDLinkBPDU);
+ }
+ CfgAddBool(f, "BroadcastLimiterStrictMode", o->BroadcastLimiterStrictMode);
+ CfgAddInt(f, "MaxLoggedPacketsPerMinute", o->MaxLoggedPacketsPerMinute);
+ CfgAddBool(f, "DoNotSaveHeavySecurityLogs", o->DoNotSaveHeavySecurityLogs);
+ CfgAddBool(f, "NoLookBPDUBridgeId", o->NoLookBPDUBridgeId);
+ CfgAddInt(f, "AdjustTcpMssValue", o->AdjustTcpMssValue);
+ CfgAddBool(f, "DisableAdjustTcpMss", o->DisableAdjustTcpMss);
+ CfgAddBool(f, "NoDhcpPacketLogOutsideHub", o->NoDhcpPacketLogOutsideHub);
+ CfgAddBool(f, "DisableHttpParsing", o->DisableHttpParsing);
+ CfgAddBool(f, "DisableUdpAcceleration", o->DisableUdpAcceleration);
+ CfgAddBool(f, "DisableUdpFilterForLocalBridgeNic", o->DisableUdpFilterForLocalBridgeNic);
+ CfgAddBool(f, "ApplyIPv4AccessListOnArpPacket", o->ApplyIPv4AccessListOnArpPacket);
+ CfgAddBool(f, "RemoveDefGwOnDhcpForLocalhost", o->RemoveDefGwOnDhcpForLocalhost);
+ CfgAddInt(f, "SecureNAT_MaxTcpSessionsPerIp", o->SecureNAT_MaxTcpSessionsPerIp);
+ CfgAddInt(f, "SecureNAT_MaxTcpSynSentPerIp", o->SecureNAT_MaxTcpSynSentPerIp);
+ CfgAddInt(f, "SecureNAT_MaxUdpSessionsPerIp", o->SecureNAT_MaxUdpSessionsPerIp);
+ CfgAddInt(f, "SecureNAT_MaxDnsSessionsPerIp", o->SecureNAT_MaxDnsSessionsPerIp);
+ CfgAddInt(f, "SecureNAT_MaxIcmpSessionsPerIp", o->SecureNAT_MaxIcmpSessionsPerIp);
+ CfgAddInt(f, "AccessListIncludeFileCacheLifetime", o->AccessListIncludeFileCacheLifetime);
+ CfgAddBool(f, "DisableKernelModeSecureNAT", o->DisableKernelModeSecureNAT);
+ CfgAddBool(f, "DisableUserModeSecureNAT", o->DisableUserModeSecureNAT);
+ CfgAddBool(f, "DisableCheckMacOnLocalBridge", o->DisableCheckMacOnLocalBridge);
+ CfgAddBool(f, "DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum);
+}
+
+// Write the user
+void SiWriteUserCfg(FOLDER *f, USER *u)
+{
+ BUF *b;
+ AUTHPASSWORD *password;
+ AUTHRADIUS *radius;
+ AUTHNT *nt;
+ AUTHUSERCERT *usercert;
+ AUTHROOTCERT *rootcert;
+ // Validate arguments
+ if (f == NULL || u == NULL)
+ {
+ return;
+ }
+
+ Lock(u->lock);
+ {
+ CfgAddUniStr(f, "RealName", u->RealName);
+ CfgAddUniStr(f, "Note", u->Note);
+ if (u->Group != NULL)
+ {
+ CfgAddStr(f, "GroupName", u->GroupName);
+ }
+ CfgAddInt64(f, "CreatedTime", u->CreatedTime);
+ CfgAddInt64(f, "UpdatedTime", u->UpdatedTime);
+ CfgAddInt64(f, "ExpireTime", u->ExpireTime);
+ CfgAddInt64(f, "LastLoginTime", u->LastLoginTime);
+ CfgAddInt(f, "NumLogin", u->NumLogin);
+ if (u->Policy != NULL)
+ {
+ SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), u->Policy, false);
+ }
+ SiWriteTraffic(f, "Traffic", u->Traffic);
+
+ CfgAddInt(f, "AuthType", u->AuthType);
+ if (u->AuthData != NULL)
+ {
+ switch (u->AuthType)
+ {
+ case AUTHTYPE_ANONYMOUS:
+ break;
+
+ case AUTHTYPE_PASSWORD:
+ password = (AUTHPASSWORD *)u->AuthData;
+ CfgAddByte(f, "AuthPassword", password->HashedKey, sizeof(password->HashedKey));
+
+ if (IsZero(password->NtLmSecureHash, sizeof(password->NtLmSecureHash)) == false)
+ {
+ CfgAddByte(f, "AuthNtLmSecureHash", password->NtLmSecureHash, sizeof(password->NtLmSecureHash));
+ }
+ break;
+
+ case AUTHTYPE_NT:
+ nt = (AUTHNT *)u->AuthData;
+ CfgAddUniStr(f, "AuthNtUserName", nt->NtUsername);
+ break;
+
+ case AUTHTYPE_RADIUS:
+ radius = (AUTHRADIUS *)u->AuthData;
+ CfgAddUniStr(f, "AuthRadiusUsername", radius->RadiusUsername);
+ break;
+
+ case AUTHTYPE_USERCERT:
+ usercert = (AUTHUSERCERT *)u->AuthData;
+ b = XToBuf(usercert->UserX, false);
+ if (b != NULL)
+ {
+ CfgAddBuf(f, "AuthUserCert", b);
+ FreeBuf(b);
+ }
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ rootcert = (AUTHROOTCERT *)u->AuthData;
+ if (rootcert->Serial != NULL && rootcert->Serial->size >= 1)
+ {
+ CfgAddByte(f, "AuthSerial", rootcert->Serial->data, rootcert->Serial->size);
+ }
+ if (rootcert->CommonName != NULL && UniIsEmptyStr(rootcert->CommonName) == false)
+ {
+ CfgAddUniStr(f, "AuthCommonName", rootcert->CommonName);
+ }
+ break;
+ }
+ }
+ }
+ Unlock(u->lock);
+}
+
+// Read an user
+void SiLoadUserCfg(HUB *h, FOLDER *f)
+{
+ char *username;
+ wchar_t realname[MAX_SIZE];
+ wchar_t note[MAX_SIZE];
+ char groupname[MAX_SIZE];
+ FOLDER *pf;
+ UINT64 created_time;
+ UINT64 updated_time;
+ UINT64 expire_time;
+ UINT64 last_login_time;
+ UINT num_login;
+ POLICY p;
+ TRAFFIC t;
+ BUF *b;
+ UINT authtype;
+ void *authdata;
+ X_SERIAL *serial = NULL;
+ wchar_t common_name[MAX_SIZE];
+ UCHAR hashed_password[SHA1_SIZE];
+ UCHAR md4_password[MD5_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ USER *u;
+ USERGROUP *g;
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ username = f->Name;
+ CfgGetUniStr(f, "RealName", realname, sizeof(realname));
+ CfgGetUniStr(f, "Note", note, sizeof(note));
+ CfgGetStr(f, "GroupName", groupname, sizeof(groupname));
+
+ created_time = CfgGetInt64(f, "CreatedTime");
+ updated_time = CfgGetInt64(f, "UpdatedTime");
+ expire_time = CfgGetInt64(f, "ExpireTime");
+ last_login_time = CfgGetInt64(f, "LastLoginTime");
+ num_login = CfgGetInt(f, "NumLogin");
+ pf = CfgGetFolder(f, "Policy");
+ if (pf != NULL)
+ {
+ SiLoadPolicyCfg(&p, pf);
+ }
+ SiLoadTraffic(f, "Traffic", &t);
+
+ authtype = CfgGetInt(f, "AuthType");
+ authdata = NULL;
+
+ switch (authtype)
+ {
+ case AUTHTYPE_PASSWORD:
+ Zero(hashed_password, sizeof(hashed_password));
+ Zero(md4_password, sizeof(md4_password));
+ CfgGetByte(f, "AuthPassword", hashed_password, sizeof(hashed_password));
+ CfgGetByte(f, "AuthNtLmSecureHash", md4_password, sizeof(md4_password));
+ authdata = NewPasswordAuthDataRaw(hashed_password, md4_password);
+ break;
+
+ case AUTHTYPE_NT:
+ if (CfgGetUniStr(f, "AuthNtUserName", tmp, sizeof(tmp)))
+ {
+ authdata = NewNTAuthData(tmp);
+ }
+ else
+ {
+ authdata = NewNTAuthData(NULL);
+ }
+ break;
+
+ case AUTHTYPE_RADIUS:
+ if (CfgGetUniStr(f, "AuthRadiusUsername", tmp, sizeof(tmp)))
+ {
+ authdata = NewRadiusAuthData(tmp);
+ }
+ else
+ {
+ authdata = NewRadiusAuthData(NULL);
+ }
+ break;
+
+ case AUTHTYPE_USERCERT:
+ b = CfgGetBuf(f, "AuthUserCert");
+ if (b != NULL)
+ {
+ X *x = BufToX(b, false);
+ if (x != NULL)
+ {
+ authdata = NewUserCertAuthData(x);
+ FreeX(x);
+ }
+ FreeBuf(b);
+ }
+ break;
+
+ case AUTHTYPE_ROOTCERT:
+ b = CfgGetBuf(f, "AuthSerial");
+ if (b != NULL)
+ {
+ serial = NewXSerial(b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ CfgGetUniStr(f, "AuthCommonName", common_name, sizeof(common_name));
+ authdata = NewRootCertAuthData(serial, common_name);
+ break;
+ }
+
+ // Add an user
+ AcLock(h);
+ {
+ if (StrLen(groupname) > 0)
+ {
+ g = AcGetGroup(h, groupname);
+ }
+ else
+ {
+ g = NULL;
+ }
+
+ u = NewUser(username, realname, note, authtype, authdata);
+ if (u != NULL)
+ {
+ if (g != NULL)
+ {
+ JoinUserToGroup(u, g);
+ }
+
+ SetUserTraffic(u, &t);
+
+ if (pf != NULL)
+ {
+ SetUserPolicy(u, &p);
+ }
+
+ Lock(u->lock);
+ {
+ u->CreatedTime = created_time;
+ u->UpdatedTime = updated_time;
+ u->ExpireTime = expire_time;
+ u->LastLoginTime = last_login_time;
+ u->NumLogin = num_login;
+ }
+ Unlock(u->lock);
+
+ AcAddUser(h, u);
+
+ ReleaseUser(u);
+ }
+
+ if (g != NULL)
+ {
+ ReleaseGroup(g);
+ }
+ }
+ AcUnlock(h);
+
+ if (serial != NULL)
+ {
+ FreeXSerial(serial);
+ }
+}
+
+// Write the user list
+void SiWriteUserList(FOLDER *f, LIST *o)
+{
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ USER *u = LIST_DATA(o, i);
+ SiWriteUserCfg(CfgCreateFolder(f, u->Name), u);
+ }
+ }
+ UnlockList(o);
+}
+
+// Read the user list
+void SiLoadUserList(HUB *h, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ char *name;
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff;
+ name = t->Token[i];
+ ff = CfgGetFolder(f, name);
+ SiLoadUserCfg(h, ff);
+ }
+
+ FreeToken(t);
+}
+
+// Write the group information
+void SiWriteGroupCfg(FOLDER *f, USERGROUP *g)
+{
+ // Validate arguments
+ if (f == NULL || g == NULL)
+ {
+ return;
+ }
+
+ Lock(g->lock);
+ {
+ CfgAddUniStr(f, "RealName", g->RealName);
+ CfgAddUniStr(f, "Note", g->Note);
+ if (g->Policy != NULL)
+ {
+ SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), g->Policy, false);
+ }
+ SiWriteTraffic(f, "Traffic", g->Traffic);
+ }
+ Unlock(g->lock);
+}
+
+// Read the group information
+void SiLoadGroupCfg(HUB *h, FOLDER *f)
+{
+ wchar_t realname[MAX_SIZE];
+ wchar_t note[MAX_SIZE];
+ char *name;
+ FOLDER *pf;
+ POLICY p;
+ TRAFFIC t;
+ USERGROUP *g;
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ name = f->Name;
+
+ CfgGetUniStr(f, "RealName", realname, sizeof(realname));
+ CfgGetUniStr(f, "Note", note, sizeof(note));
+
+ pf = CfgGetFolder(f, "Policy");
+ if (pf != NULL)
+ {
+ SiLoadPolicyCfg(&p, pf);
+ }
+
+ SiLoadTraffic(f, "Traffic", &t);
+
+ g = NewGroup(name, realname, note);
+ if (g == NULL)
+ {
+ return;
+ }
+
+ if (pf != NULL)
+ {
+ SetGroupPolicy(g, &p);
+ }
+
+ SetGroupTraffic(g, &t);
+
+ AcLock(h);
+ {
+ AcAddGroup(h, g);
+ }
+ AcUnlock(h);
+
+ ReleaseGroup(g);
+}
+
+// Write the group list
+void SiWriteGroupList(FOLDER *f, LIST *o)
+{
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ USERGROUP *g = LIST_DATA(o, i);
+ SiWriteGroupCfg(CfgCreateFolder(f, g->Name), g);
+ }
+ }
+ UnlockList(o);
+}
+
+// Read the group List
+void SiLoadGroupList(HUB *h, FOLDER *f)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ char *name;
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ name = t->Token[i];
+ SiLoadGroupCfg(h, CfgGetFolder(f, name));
+ }
+
+ FreeToken(t);
+}
+
+// Write the AC list
+void SiWriteAcList(FOLDER *f, LIST *o)
+{
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char name[MAX_SIZE];
+ AC *ac = LIST_DATA(o, i);
+ FOLDER *ff;
+
+ Format(name, sizeof(name), "Acl%u", i + 1);
+
+ ff = CfgCreateFolder(f, name);
+
+ CfgAddBool(ff, "Deny", ac->Deny);
+ CfgAddInt(ff, "Priority", ac->Priority);
+ CfgAddIp(ff, "IpAddress", &ac->IpAddress);
+
+ if (ac->Masked)
+ {
+ CfgAddIp(ff, "NetMask", &ac->SubnetMask);
+ }
+ }
+ }
+ UnlockList(o);
+}
+
+// Read the AC list
+void SiLoadAcList(LIST *o, FOLDER *f)
+{
+ // Validate arguments
+ if (o == NULL || f == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ TOKEN_LIST *t = CfgEnumFolderToTokenList(f);
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(f, t->Token[i]);
+
+ if (ff != NULL)
+ {
+ AC ac;
+
+ Zero(&ac, sizeof(ac));
+ ac.Deny = CfgGetBool(ff, "Deny");
+ ac.Priority = CfgGetInt(ff, "Priority");
+ CfgGetIp(ff, "IpAddress", &ac.IpAddress);
+
+ if (CfgGetIp(ff, "NetMask", &ac.SubnetMask))
+ {
+ ac.Masked = true;
+ }
+
+ AddAc(o, &ac);
+ }
+ }
+
+ FreeToken(t);
+ }
+ }
+ UnlockList(o);
+}
+
+// Write the certificate revocation list
+void SiWriteCrlList(FOLDER *f, LIST *o)
+{
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char name[MAX_SIZE];
+ CRL *crl = LIST_DATA(o, i);
+ FOLDER *ff;
+ NAME *n;
+
+ Format(name, sizeof(name), "Crl%u", i);
+
+ ff = CfgCreateFolder(f, name);
+ n = crl->Name;
+
+ if (UniIsEmptyStr(n->CommonName) == false)
+ {
+ CfgAddUniStr(ff, "CommonName", n->CommonName);
+ }
+
+ if (UniIsEmptyStr(n->Organization) == false)
+ {
+ CfgAddUniStr(ff, "Organization", n->Organization);
+ }
+
+ if (UniIsEmptyStr(n->Unit) == false)
+ {
+ CfgAddUniStr(ff, "Unit", n->Unit);
+ }
+
+ if (UniIsEmptyStr(n->Country) == false)
+ {
+ CfgAddUniStr(ff, "Country", n->Country);
+ }
+
+ if (UniIsEmptyStr(n->State) == false)
+ {
+ CfgAddUniStr(ff, "State", n->State);
+ }
+
+ if (UniIsEmptyStr(n->Local) == false)
+ {
+ CfgAddUniStr(ff, "Local", n->Local);
+ }
+
+ if (IsZero(crl->DigestMD5, MD5_SIZE) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ BinToStr(tmp, sizeof(tmp), crl->DigestMD5, MD5_SIZE);
+ CfgAddStr(ff, "DigestMD5", tmp);
+ }
+
+ if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ BinToStr(tmp, sizeof(tmp), crl->DigestSHA1, SHA1_SIZE);
+ CfgAddStr(ff, "DigestSHA1", tmp);
+ }
+
+ if (crl->Serial != NULL)
+ {
+ char tmp[MAX_SIZE];
+
+ BinToStr(tmp, sizeof(tmp), crl->Serial->data, crl->Serial->size);
+ CfgAddStr(ff, "Serial", tmp);
+ }
+ }
+ }
+ UnlockList(o);
+}
+
+// Read the certificate revocation list
+void SiLoadCrlList(LIST *o, FOLDER *f)
+{
+ // Validate arguments
+ if (o == NULL || f == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ TOKEN_LIST *t;
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ CRL *crl;
+ FOLDER *ff = CfgGetFolder(f, t->Token[i]);
+ wchar_t cn[MAX_SIZE], org[MAX_SIZE], u[MAX_SIZE], c[MAX_SIZE],
+ st[MAX_SIZE], l[MAX_SIZE];
+ char tmp[MAX_SIZE];
+
+ if (ff != NULL)
+ {
+ BUF *b;
+
+ crl = ZeroMalloc(sizeof(CRL));
+
+ CfgGetUniStr(ff, "CommonName", cn, sizeof(cn));
+ CfgGetUniStr(ff, "Organization", org, sizeof(org));
+ CfgGetUniStr(ff, "Unit", u, sizeof(u));
+ CfgGetUniStr(ff, "Country", c, sizeof(c));
+ CfgGetUniStr(ff, "State", st, sizeof(st));
+ CfgGetUniStr(ff, "Local", l, sizeof(l));
+
+ crl->Name = NewName(cn, org, u, c, st, l);
+
+ if (CfgGetStr(ff, "Serial", tmp, sizeof(tmp)))
+ {
+ b = StrToBin(tmp);
+
+ if (b != NULL)
+ {
+ if (b->Size >= 1)
+ {
+ crl->Serial = NewXSerial(b->Buf, b->Size);
+ }
+
+ FreeBuf(b);
+ }
+ }
+
+ if (CfgGetStr(ff, "DigestMD5", tmp, sizeof(tmp)))
+ {
+ b = StrToBin(tmp);
+
+ if (b != NULL)
+ {
+ if (b->Size == MD5_SIZE)
+ {
+ Copy(crl->DigestMD5, b->Buf, MD5_SIZE);
+ }
+
+ FreeBuf(b);
+ }
+ }
+
+ if (CfgGetStr(ff, "DigestSHA1", tmp, sizeof(tmp)))
+ {
+ b = StrToBin(tmp);
+
+ if (b != NULL)
+ {
+ if (b->Size == SHA1_SIZE)
+ {
+ Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);
+ }
+
+ FreeBuf(b);
+ }
+ }
+
+ Insert(o, crl);
+ }
+ }
+
+ FreeToken(t);
+ }
+ UnlockList(o);
+}
+
+// Write the certificates list
+void SiWriteCertList(FOLDER *f, LIST *o)
+{
+ // Validate arguments
+ if (f == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ X *x;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char name[MAX_SIZE];
+ BUF *b;
+ x = LIST_DATA(o, i);
+ Format(name, sizeof(name), "Cert%u", i);
+ b = XToBuf(x, false);
+ if (b != NULL)
+ {
+ CfgAddBuf(CfgCreateFolder(f, name), "X509", b);
+ FreeBuf(b);
+ }
+ }
+ }
+ UnlockList(o);
+}
+
+// Read the certificates list
+void SiLoadCertList(LIST *o, FOLDER *f)
+{
+ // Validate arguments
+ if (o == NULL || f == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ TOKEN_LIST *t;
+
+ t = CfgEnumFolderToTokenList(f);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(f, t->Token[i]);
+ BUF *b;
+
+ b = CfgGetBuf(ff, "X509");
+ if (b != NULL)
+ {
+ X *x = BufToX(b, false);
+ if (x != NULL)
+ {
+ Insert(o, x);
+ }
+ FreeBuf(b);
+ }
+ }
+
+ FreeToken(t);
+ }
+ UnlockList(o);
+}
+
+// Write the database
+void SiWriteHubDb(FOLDER *f, HUBDB *db, bool no_save_ac_list)
+{
+ // Validate arguments
+ if (f == NULL || db == NULL)
+ {
+ return;
+ }
+
+ SiWriteUserList(CfgCreateFolder(f, "UserList"), db->UserList);
+ SiWriteGroupList(CfgCreateFolder(f, "GroupList"), db->GroupList);
+ SiWriteCertList(CfgCreateFolder(f, "CertList"), db->RootCertList);
+ SiWriteCrlList(CfgCreateFolder(f, "CrlList"), db->CrlList);
+
+ if (no_save_ac_list == false)
+ {
+ SiWriteAcList(CfgCreateFolder(f, "IPAccessControlList"), db->AcList);
+ }
+}
+
+// Read the database
+void SiLoadHubDb(HUB *h, FOLDER *f)
+{
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ SiLoadGroupList(h, CfgGetFolder(f, "GroupList"));
+ SiLoadUserList(h, CfgGetFolder(f, "UserList"));
+
+ if (h->HubDb != NULL)
+ {
+ SiLoadCertList(h->HubDb->RootCertList, CfgGetFolder(f, "CertList"));
+ SiLoadCrlList(h->HubDb->CrlList, CfgGetFolder(f, "CrlList"));
+ SiLoadAcList(h->HubDb->AcList, CfgGetFolder(f, "IPAccessControlList"));
+ }
+}
+
+// Write the Virtual HUB setting
+void SiWriteHubCfg(FOLDER *f, HUB *h)
+{
+ // Validate arguments
+ if (f == NULL || h == NULL)
+ {
+ return;
+ }
+
+ // Radius server name
+ Lock(h->RadiusOptionLock);
+ {
+ if (h->RadiusServerName != NULL)
+ {
+ CfgAddStr(f, "RadiusServerName", h->RadiusServerName);
+ CfgAddBuf(f, "RadiusSecret", h->RadiusSecret);
+ }
+ CfgAddInt(f, "RadiusServerPort", h->RadiusServerPort);
+ CfgAddInt(f, "RadiusRetryInterval", h->RadiusRetryInterval);
+ CfgAddStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter);
+ }
+ Unlock(h->RadiusOptionLock);
+
+ // Password
+ CfgAddByte(f, "HashedPassword", h->HashedPassword, sizeof(h->HashedPassword));
+ CfgAddByte(f, "SecurePassword", h->SecurePassword, sizeof(h->SecurePassword));
+
+ // Online / Offline flag
+ if (h->Cedar->Bridge == false)
+ {
+ CfgAddBool(f, "Online", (h->Offline && (h->HubIsOnlineButHalting == false)) ? false : true);
+ }
+
+ // Traffic information
+ SiWriteTraffic(f, "Traffic", h->Traffic);
+
+ // HUB options
+ SiWriteHubOptionCfg(CfgCreateFolder(f, "Option"), h->Option);
+
+ // Message
+ {
+ FOLDER *folder = CfgCreateFolder(f, "Message");
+
+ if (IsEmptyUniStr(h->Msg) == false)
+ {
+ CfgAddUniStr(folder, "MessageText", h->Msg);
+ }
+ }
+
+ // HUB_LOG
+ SiWriteHubLogCfg(CfgCreateFolder(f, "LogSetting"), &h->LogSetting);
+
+ if (h->Type == HUB_TYPE_STANDALONE)
+ {
+ // Link list
+ SiWriteHubLinks(CfgCreateFolder(f, "CascadeList"), h);
+ }
+
+ if (h->Type != HUB_TYPE_FARM_STATIC)
+ {
+ if (GetServerCapsBool(h->Cedar->Server, "b_support_securenat"))
+ {
+ // SecureNAT
+ SiWriteSecureNAT(h, CfgCreateFolder(f, "SecureNAT"));
+ }
+ }
+
+ // Access list
+ SiWriteHubAccessLists(CfgCreateFolder(f, "AccessList"), h);
+
+ // Administration options
+ SiWriteHubAdminOptions(CfgCreateFolder(f, "AdminOption"), h);
+
+ // Type of HUB
+ CfgAddInt(f, "Type", h->Type);
+
+ // Database
+ if (h->Cedar->Bridge == false)
+ {
+ SiWriteHubDb(CfgCreateFolder(f, "SecurityAccountDatabase"), h->HubDb,
+ false
+ );
+ }
+
+ // Usage status
+ CfgAddInt64(f, "LastCommTime", h->LastCommTime);
+ CfgAddInt64(f, "LastLoginTime", h->LastLoginTime);
+ CfgAddInt64(f, "CreatedTime", h->CreatedTime);
+ CfgAddInt(f, "NumLogin", h->NumLogin);
+}
+
+// Read the logging options
+void SiLoadHubLogCfg(HUB_LOG *g, FOLDER *f)
+{
+ // Validate arguments
+ if (f == NULL || g == NULL)
+ {
+ return;
+ }
+
+ Zero(g, sizeof(HUB_LOG));
+ g->SaveSecurityLog = CfgGetBool(f, "SaveSecurityLog");
+ g->SecurityLogSwitchType = CfgGetInt(f, "SecurityLogSwitchType");
+ g->SavePacketLog = CfgGetBool(f, "SavePacketLog");
+ g->PacketLogSwitchType = CfgGetInt(f, "PacketLogSwitchType");
+
+ g->PacketLogConfig[PACKET_LOG_TCP_CONN] = CfgGetInt(f, "PACKET_LOG_TCP_CONN");
+ g->PacketLogConfig[PACKET_LOG_TCP] = CfgGetInt(f, "PACKET_LOG_TCP");
+ g->PacketLogConfig[PACKET_LOG_DHCP] = CfgGetInt(f, "PACKET_LOG_DHCP");
+ g->PacketLogConfig[PACKET_LOG_UDP] = CfgGetInt(f, "PACKET_LOG_UDP");
+ g->PacketLogConfig[PACKET_LOG_ICMP] = CfgGetInt(f, "PACKET_LOG_ICMP");
+ g->PacketLogConfig[PACKET_LOG_IP] = CfgGetInt(f, "PACKET_LOG_IP");
+ g->PacketLogConfig[PACKET_LOG_ARP] = CfgGetInt(f, "PACKET_LOG_ARP");
+ g->PacketLogConfig[PACKET_LOG_ETHERNET] = CfgGetInt(f, "PACKET_LOG_ETHERNET");
+}
+
+// Write the logging options
+void SiWriteHubLogCfg(FOLDER *f, HUB_LOG *g)
+{
+ SiWriteHubLogCfgEx(f, g, false);
+}
+void SiWriteHubLogCfgEx(FOLDER *f, HUB_LOG *g, bool el_mode)
+{
+ // Validate arguments
+ if (f == NULL || g == NULL)
+ {
+ return;
+ }
+
+ if (el_mode == false)
+ {
+ CfgAddBool(f, "SaveSecurityLog", g->SaveSecurityLog);
+ CfgAddInt(f, "SecurityLogSwitchType", g->SecurityLogSwitchType);
+ CfgAddBool(f, "SavePacketLog", g->SavePacketLog);
+ }
+
+ CfgAddInt(f, "PacketLogSwitchType", g->PacketLogSwitchType);
+
+ CfgAddInt(f, "PACKET_LOG_TCP_CONN", g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
+ CfgAddInt(f, "PACKET_LOG_TCP", g->PacketLogConfig[PACKET_LOG_TCP]);
+ CfgAddInt(f, "PACKET_LOG_DHCP", g->PacketLogConfig[PACKET_LOG_DHCP]);
+ CfgAddInt(f, "PACKET_LOG_UDP", g->PacketLogConfig[PACKET_LOG_UDP]);
+ CfgAddInt(f, "PACKET_LOG_ICMP", g->PacketLogConfig[PACKET_LOG_ICMP]);
+ CfgAddInt(f, "PACKET_LOG_IP", g->PacketLogConfig[PACKET_LOG_IP]);
+ CfgAddInt(f, "PACKET_LOG_ARP", g->PacketLogConfig[PACKET_LOG_ARP]);
+ CfgAddInt(f, "PACKET_LOG_ETHERNET", g->PacketLogConfig[PACKET_LOG_ETHERNET]);
+}
+
+// Read the Virtual HUB settings
+void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
+{
+ HUB *h;
+ CEDAR *c;
+ HUB_OPTION o;
+ bool online;
+ UINT hub_old_type = 0;
+ // Validate arguments
+ if (s == NULL || f == NULL || name == NULL)
+ {
+ return;
+ }
+
+ c = s->Cedar;
+
+ // Get the option
+ Zero(&o, sizeof(o));
+ SiLoadHubOptionCfg(CfgGetFolder(f, "Option"), &o);
+
+ // Create a HUB
+ h = NewHub(c, name, &o);
+ if (h != NULL)
+ {
+ HUB_LOG g;
+ // Radius server settings
+ Lock(h->RadiusOptionLock);
+ {
+ char name[MAX_SIZE];
+ BUF *secret;
+ UINT port;
+ UINT interval;
+
+ port = CfgGetInt(f, "RadiusServerPort");
+ interval = CfgGetInt(f, "RadiusRetryInterval");
+
+ CfgGetStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter, sizeof(h->RadiusSuffixFilter));
+
+ if (interval == 0)
+ {
+ interval = RADIUS_RETRY_INTERVAL;
+ }
+
+ if (port != 0 && CfgGetStr(f, "RadiusServerName", name, sizeof(name)))
+ {
+ secret = CfgGetBuf(f, "RadiusSecret");
+ if (secret != NULL)
+ {
+ char secret_str[MAX_SIZE];
+ Zero(secret_str, sizeof(secret_str));
+ if (secret->Size < sizeof(secret_str))
+ {
+ Copy(secret_str, secret->Buf, secret->Size);
+ }
+ secret_str[sizeof(secret_str) - 1] = 0;
+ //SetRadiusServer(h, name, port, secret_str);
+ SetRadiusServerEx(h, name, port, secret_str, interval);
+ FreeBuf(secret);
+ }
+ }
+ }
+ Unlock(h->RadiusOptionLock);
+
+ // Password
+ if (CfgGetByte(f, "HashedPassword", h->HashedPassword, sizeof(h->HashedPassword)) != sizeof(h->HashedPassword))
+ {
+ Hash(h->HashedPassword, "", 0, true);
+ }
+ if (CfgGetByte(f, "SecurePassword", h->SecurePassword, sizeof(h->SecurePassword)) != sizeof(h->SecurePassword))
+ {
+ HashPassword(h->SecurePassword, ADMINISTRATOR_USERNAME, "");
+ }
+
+ // Log Settings
+ Zero(&g, sizeof(g));
+ SiLoadHubLogCfg(&g, CfgGetFolder(f, "LogSetting"));
+ SetHubLogSetting(h, &g);
+
+ // Online / Offline flag
+ if (h->Cedar->Bridge == false)
+ {
+ online = CfgGetBool(f, "Online");
+ }
+ else
+ {
+ online = true;
+ }
+
+ // Traffic information
+ SiLoadTraffic(f, "Traffic", h->Traffic);
+
+ // Access list
+ SiLoadHubAccessLists(h, CfgGetFolder(f, "AccessList"));
+
+ // Type of HUB
+ hub_old_type = h->Type = CfgGetInt(f, "Type");
+
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ if (h->Type != HUB_TYPE_STANDALONE)
+ {
+ // Change the type of all HUB to a stand-alone if the server is a stand-alone
+ h->Type = HUB_TYPE_STANDALONE;
+ }
+ }
+ else
+ {
+ if (h->Type == HUB_TYPE_STANDALONE)
+ {
+ // If the server is a farm controller, change the type of HUB to the farm supported types
+ h->Type = HUB_TYPE_FARM_DYNAMIC;
+ }
+ }
+
+ if (h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ h->CurrentVersion = h->LastVersion = 1;
+ }
+
+ // Message
+ {
+ FOLDER *folder = CfgGetFolder(f, "Message");
+ if (folder != NULL)
+ {
+ wchar_t *tmp = Malloc(sizeof(wchar_t) * (HUB_MAXMSG_LEN + 1));
+ if (CfgGetUniStr(folder, "MessageText", tmp, sizeof(wchar_t) * (HUB_MAXMSG_LEN + 1)))
+ {
+ SetHubMsg(h, tmp);
+ }
+ Free(tmp);
+ }
+ }
+
+ // Link list
+ if (h->Type == HUB_TYPE_STANDALONE)
+ {
+ // The link list is used only on stand-alone HUB
+ // In VPN Gate hubs, don't load this
+ {
+ SiLoadHubLinks(h, CfgGetFolder(f, "CascadeList"));
+ }
+ }
+
+ // SecureNAT
+ if (GetServerCapsBool(h->Cedar->Server, "b_support_securenat"))
+ {
+ if (h->Type == HUB_TYPE_STANDALONE || h->Type == HUB_TYPE_FARM_DYNAMIC)
+ {
+ // SecureNAT is used only in the case of dynamic HUB or standalone HUB
+ SiLoadSecureNAT(h, CfgGetFolder(f, "SecureNAT"));
+
+ if (h->Type != HUB_TYPE_STANDALONE && h->Cedar != NULL && h->Cedar->Server != NULL &&
+ h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption,
+ hub_old_type == HUB_TYPE_STANDALONE);
+ }
+
+ }
+ }
+
+ // Administration options
+ SiLoadHubAdminOptions(h, CfgGetFolder(f, "AdminOption"));
+
+ // Database
+ if (h->Cedar->Bridge == false)
+ {
+ SiLoadHubDb(h, CfgGetFolder(f, "SecurityAccountDatabase"));
+ }
+
+ // Usage status
+ h->LastCommTime = CfgGetInt64(f, "LastCommTime");
+ if (h->LastCommTime == 0)
+ {
+ h->LastCommTime = SystemTime64();
+ }
+ h->LastLoginTime = CfgGetInt64(f, "LastLoginTime");
+ if (h->LastLoginTime == 0)
+ {
+ h->LastLoginTime = SystemTime64();
+ }
+ h->CreatedTime = CfgGetInt64(f, "CreatedTime");
+ h->NumLogin = CfgGetInt(f, "NumLogin");
+
+ // Start the operation of the HUB
+ AddHub(c, h);
+
+ if (online)
+ {
+ h->Offline = true;
+ SetHubOnline(h);
+ }
+ else
+ {
+ h->Offline = false;
+ SetHubOffline(h);
+ }
+
+ WaitLogFlush(h->SecurityLogger);
+ WaitLogFlush(h->PacketLogger);
+
+ ReleaseHub(h);
+ }
+}
+
+// Read the SecureNAT configuration
+void SiLoadSecureNAT(HUB *h, FOLDER *f)
+{
+ VH_OPTION o;
+ // Validate arguments
+ if (h == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Read the VH_OPTION
+ NiLoadVhOptionEx(&o, f);
+
+ // Set the VH_OPTION
+ Copy(h->SecureNATOption, &o, sizeof(VH_OPTION));
+
+ EnableSecureNAT(h, CfgGetBool(f, "Disabled") ? false : true);
+}
+
+// Read the virtual layer 3 switch settings
+void SiLoadL3SwitchCfg(L3SW *sw, FOLDER *f)
+{
+ UINT i;
+ FOLDER *if_folder, *table_folder;
+ TOKEN_LIST *t;
+ bool active = false;
+ // Validate arguments
+ if (sw == NULL || f == NULL)
+ {
+ return;
+ }
+
+ active = CfgGetBool(f, "Active");
+
+ // Interface list
+ if_folder = CfgGetFolder(f, "InterfaceList");
+ if (if_folder != NULL)
+ {
+ t = CfgEnumFolderToTokenList(if_folder);
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(if_folder, t->Token[i]);
+ char name[MAX_HUBNAME_LEN + 1];
+ UINT ip, subnet;
+
+ CfgGetStr(ff, "HubName", name, sizeof(name));
+ ip = CfgGetIp32(ff, "IpAddress");
+ subnet = CfgGetIp32(ff, "SubnetMask");
+
+ {
+ L3AddIf(sw, name, ip, subnet);
+ }
+ }
+ FreeToken(t);
+ }
+ }
+
+ // Routing table
+ table_folder = CfgGetFolder(f, "RoutingTable");
+ if (table_folder != NULL)
+ {
+ t = CfgEnumFolderToTokenList(table_folder);
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = CfgGetFolder(table_folder, t->Token[i]);
+ L3TABLE tbl;
+
+ Zero(&tbl, sizeof(tbl));
+ tbl.NetworkAddress = CfgGetIp32(ff, "NetworkAddress");
+ tbl.SubnetMask = CfgGetIp32(ff, "SubnetMask");
+ tbl.GatewayAddress = CfgGetIp32(ff, "GatewayAddress");
+ tbl.Metric = CfgGetInt(ff, "Metric");
+
+ L3AddTable(sw, &tbl);
+ }
+ FreeToken(t);
+ }
+ }
+
+ if (active)
+ {
+ L3SwStart(sw);
+ }
+}
+
+// Write the virtual layer 3 switch settings
+void SiWriteL3SwitchCfg(FOLDER *f, L3SW *sw)
+{
+ UINT i;
+ FOLDER *if_folder, *table_folder;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || sw == NULL)
+ {
+ return;
+ }
+
+ // Active flag
+ CfgAddBool(f, "Active", sw->Active);
+
+ // Interface list
+ if_folder = CfgCreateFolder(f, "InterfaceList");
+ for (i = 0;i < LIST_NUM(sw->IfList);i++)
+ {
+ L3IF *e = LIST_DATA(sw->IfList, i);
+ FOLDER *ff;
+
+ Format(tmp, sizeof(tmp), "Interface%u", i);
+ ff = CfgCreateFolder(if_folder, tmp);
+
+ CfgAddStr(ff, "HubName", e->HubName);
+ CfgAddIp32(ff, "IpAddress", e->IpAddress);
+ CfgAddIp32(ff, "SubnetMask", e->SubnetMask);
+ }
+
+ // Routing table
+ table_folder = CfgCreateFolder(f, "RoutingTable");
+ for (i = 0;i < LIST_NUM(sw->TableList);i++)
+ {
+ L3TABLE *e = LIST_DATA(sw->TableList, i);
+ FOLDER *ff;
+
+ Format(tmp, sizeof(tmp), "Entry%u", i);
+ ff = CfgCreateFolder(table_folder, tmp);
+
+ CfgAddIp32(ff, "NetworkAddress", e->NetworkAddress);
+ CfgAddIp32(ff, "SubnetMask", e->SubnetMask);
+ CfgAddIp32(ff, "GatewayAddress", e->GatewayAddress);
+ CfgAddInt(ff, "Metric", e->Metric);
+ }
+}
+
+// Read the Virtual Layer 3 switch list
+void SiLoadL3Switchs(SERVER *s, FOLDER *f)
+{
+ UINT i;
+ TOKEN_LIST *t;
+ CEDAR *c;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+ c = s->Cedar;
+
+ t = CfgEnumFolderToTokenList(f);
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ L3SW *sw = L3AddSw(c, name);
+
+ SiLoadL3SwitchCfg(sw, CfgGetFolder(f, name));
+
+ ReleaseL3Sw(sw);
+ }
+ }
+ FreeToken(t);
+}
+
+// Write the Virtual Layer 3 switch list
+void SiWriteL3Switchs(FOLDER *f, SERVER *s)
+{
+ UINT i;
+ FOLDER *folder;
+ CEDAR *c;
+ // Validate arguments
+ if (f == NULL || s == NULL)
+ {
+ return;
+ }
+ c = s->Cedar;
+
+ LockList(c->L3SwList);
+ {
+ for (i = 0;i < LIST_NUM(c->L3SwList);i++)
+ {
+ L3SW *sw = LIST_DATA(c->L3SwList, i);
+
+ Lock(sw->lock);
+ {
+ folder = CfgCreateFolder(f, sw->Name);
+
+ SiWriteL3SwitchCfg(folder, sw);
+ }
+ Unlock(sw->lock);
+ }
+ }
+ UnlockList(c->L3SwList);
+}
+
+// Read the IPsec server configuration
+void SiLoadIPsec(SERVER *s, FOLDER *f)
+{
+ IPSEC_SERVICES sl;
+ FOLDER *list_folder;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ Zero(&sl, sizeof(sl));
+
+ CfgGetStr(f, "IPsec_Secret", sl.IPsec_Secret, sizeof(sl.IPsec_Secret));
+ CfgGetStr(f, "L2TP_DefaultHub", sl.L2TP_DefaultHub, sizeof(sl.L2TP_DefaultHub));
+
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // IPsec feature only be enabled on a standalone server
+ sl.L2TP_Raw = CfgGetBool(f, "L2TP_Raw");
+ sl.L2TP_IPsec = CfgGetBool(f, "L2TP_IPsec");
+ sl.EtherIP_IPsec = CfgGetBool(f, "EtherIP_IPsec");
+ }
+
+ IPsecServerSetServices(s->IPsecServer, &sl);
+
+ list_folder = CfgGetFolder(f, "EtherIP_IDSettingsList");
+
+ if (list_folder != NULL)
+ {
+ TOKEN_LIST *t = CfgEnumFolderToTokenList(list_folder);
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ FOLDER *f = CfgGetFolder(list_folder, name);
+
+ if (f != NULL)
+ {
+ ETHERIP_ID d;
+ BUF *b;
+
+ Zero(&d, sizeof(d));
+
+ StrCpy(d.Id, sizeof(d.Id), name);
+ CfgGetStr(f, "HubName", d.HubName, sizeof(d.HubName));
+ CfgGetStr(f, "UserName", d.UserName, sizeof(d.UserName));
+
+ b = CfgGetBuf(f, "EncryptedPassword");
+ if (b != NULL)
+ {
+ char *pass = DecryptPassword2(b);
+
+ StrCpy(d.Password, sizeof(d.Password), pass);
+
+ Free(pass);
+
+ AddEtherIPId(s->IPsecServer, &d);
+
+ FreeBuf(b);
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+ }
+}
+
+// Write the IPsec server configuration
+void SiWriteIPsec(FOLDER *f, SERVER *s)
+{
+ IPSEC_SERVICES sl;
+ FOLDER *list_folder;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ if (s->IPsecServer == NULL)
+ {
+ return;
+ }
+
+ Zero(&sl, sizeof(sl));
+ IPsecServerGetServices(s->IPsecServer, &sl);
+
+ CfgAddStr(f, "IPsec_Secret", sl.IPsec_Secret);
+ CfgAddStr(f, "L2TP_DefaultHub", sl.L2TP_DefaultHub);
+
+ CfgAddBool(f, "L2TP_Raw", sl.L2TP_Raw);
+ CfgAddBool(f, "L2TP_IPsec", sl.L2TP_IPsec);
+ CfgAddBool(f, "EtherIP_IPsec", sl.EtherIP_IPsec);
+
+ list_folder = CfgCreateFolder(f, "EtherIP_IDSettingsList");
+
+ Lock(s->IPsecServer->LockSettings);
+ {
+ for (i = 0;i < LIST_NUM(s->IPsecServer->EtherIPIdList);i++)
+ {
+ ETHERIP_ID *d = LIST_DATA(s->IPsecServer->EtherIPIdList, i);
+ FOLDER *f;
+ BUF *b;
+
+ f = CfgCreateFolder(list_folder, d->Id);
+
+ CfgAddStr(f, "HubName", d->HubName);
+ CfgAddStr(f, "UserName", d->UserName);
+
+ b = EncryptPassword2(d->Password);
+
+ CfgAddBuf(f, "EncryptedPassword", b);
+
+ FreeBuf(b);
+ }
+ }
+ Unlock(s->IPsecServer->LockSettings);
+}
+
+// Write the license list
+void SiWriteLicenseManager(FOLDER *f, SERVER *s)
+{
+}
+
+// Read the license list
+void SiLoadLicenseManager(SERVER *s, FOLDER *f)
+{
+}
+
+// Write the Virtual HUB list
+void SiWriteHubs(FOLDER *f, SERVER *s)
+{
+ UINT i;
+ FOLDER *hub_folder;
+ CEDAR *c;
+ UINT num;
+ HUB **hubs;
+ // Validate arguments
+ if (f == NULL || s == NULL)
+ {
+ return;
+ }
+ c = s->Cedar;
+
+ LockList(c->HubList);
+ {
+ hubs = ToArray(c->HubList);
+ num = LIST_NUM(c->HubList);
+
+ for (i = 0;i < num;i++)
+ {
+ AddRef(hubs[i]->ref);
+ }
+ }
+ UnlockList(c->HubList);
+
+ for (i = 0;i < num;i++)
+ {
+ HUB *h = hubs[i];
+
+ Lock(h->lock);
+ {
+ hub_folder = CfgCreateFolder(f, h->Name);
+ SiWriteHubCfg(hub_folder, h);
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+
+ if ((i % 30) == 1)
+ {
+ YieldCpu();
+ }
+ }
+
+ Free(hubs);
+}
+
+// Read the Virtual HUB list
+void SiLoadHubs(SERVER *s, FOLDER *f)
+{
+ UINT i;
+ FOLDER *hub_folder;
+ CEDAR *c;
+ TOKEN_LIST *t;
+ bool b = false;
+ // Validate arguments
+ if (f == NULL || s == NULL)
+ {
+ return;
+ }
+ c = s->Cedar;
+
+ t = CfgEnumFolderToTokenList(f);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+
+
+ if (s->Cedar->Bridge)
+ {
+ if (StrCmpi(name, SERVER_DEFAULT_BRIDGE_NAME) == 0)
+ {
+ // Read only the setting of Virtual HUB named "BRIDGE"
+ // in the case of the Bridge
+ b = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ hub_folder = CfgGetFolder(f, name);
+ if (hub_folder != NULL)
+ {
+ SiLoadHubCfg(s, hub_folder, name);
+ }
+ }
+ FreeToken(t);
+
+ if (s->Cedar->Bridge && b == false)
+ {
+ // If there isn't "BRIDGE" virtual HUB setting, create it newly
+ SiInitDefaultHubList(s);
+ }
+}
+
+// Read the server-specific settings
+void SiLoadServerCfg(SERVER *s, FOLDER *f)
+{
+ BUF *b;
+ CEDAR *c;
+ char tmp[MAX_SIZE];
+ X *x = NULL;
+ K *k = NULL;
+ bool cluster_allowed = false;
+ UINT num_connections_per_ip = 0;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Save interval related
+ s->AutoSaveConfigSpan = CfgGetInt(f, "AutoSaveConfigSpan") * 1000;
+ if (s->AutoSaveConfigSpan == 0)
+ {
+ s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
+ }
+ else
+ {
+ s->AutoSaveConfigSpan = MAKESURE(s->AutoSaveConfigSpan, SERVER_FILE_SAVE_INTERVAL_MIN, SERVER_FILE_SAVE_INTERVAL_MAX);
+ }
+
+ s->DontBackupConfig = CfgGetBool(f, "DontBackupConfig");
+
+ if (CfgIsItem(f, "BackupConfigOnlyWhenModified"))
+ {
+ s->BackupConfigOnlyWhenModified = CfgGetBool(f, "BackupConfigOnlyWhenModified");
+ }
+ else
+ {
+ s->BackupConfigOnlyWhenModified = true;
+ }
+
+ c = s->Cedar;
+ Lock(c->lock);
+ {
+ OPENVPN_SSTP_CONFIG config;
+ FOLDER *syslog_f;
+ {
+ RPC_KEEP k;
+
+ // Keep-alive related
+ Zero(&k, sizeof(k));
+ k.UseKeepConnect = CfgGetBool(f, "UseKeepConnect");
+ CfgGetStr(f, "KeepConnectHost", k.KeepConnectHost, sizeof(k.KeepConnectHost));
+ k.KeepConnectPort = CfgGetInt(f, "KeepConnectPort");
+ k.KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");
+ k.KeepConnectInterval = CfgGetInt(f, "KeepConnectInterval") * 1000;
+ if (k.KeepConnectPort == 0)
+ {
+ k.KeepConnectPort = 80;
+ }
+ if (StrLen(k.KeepConnectHost) == 0)
+ {
+ StrCpy(k.KeepConnectHost, sizeof(k.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
+ }
+ if (k.KeepConnectInterval == 0)
+ {
+ k.KeepConnectInterval = KEEP_INTERVAL_DEFAULT * 1000;
+ }
+ if (k.KeepConnectInterval < 5000)
+ {
+ k.KeepConnectInterval = 5000;
+ }
+ if (k.KeepConnectInterval > 600000)
+ {
+ k.KeepConnectInterval = 600000;
+ }
+
+ Lock(s->Keep->lock);
+ {
+ KEEP *keep = s->Keep;
+ keep->Enable = k.UseKeepConnect;
+ keep->Server = true;
+ StrCpy(keep->ServerName, sizeof(keep->ServerName), k.KeepConnectHost);
+ keep->ServerPort = k.KeepConnectPort;
+ keep->UdpMode = k.KeepConnectProtocol;
+ keep->Interval = k.KeepConnectInterval;
+ }
+ Unlock(s->Keep->lock);
+ }
+
+ // syslog
+ syslog_f = CfgGetFolder(f, "SyslogSettings");
+ if (syslog_f != NULL && GetServerCapsBool(s, "b_support_syslog"))
+ {
+ SYSLOG_SETTING set;
+
+ Zero(&set, sizeof(set));
+
+ set.SaveType = CfgGetInt(syslog_f, "SaveType");
+ CfgGetStr(syslog_f, "HostName", set.Hostname, sizeof(set.Hostname));
+ set.Port = CfgGetInt(syslog_f, "Port");
+
+ SiSetSysLogSetting(s, &set);
+ }
+
+ // Whether to disable the IPv6 listener
+ s->Cedar->DisableIPv6Listener = CfgGetBool(f, "DisableIPv6Listener");
+
+ // DoS
+ s->DisableDosProction = CfgGetBool(f, "DisableDosProction");
+
+ // Num Connections Per IP
+ SetMaxConnectionsPerIp(CfgGetInt(f, "MaxConnectionsPerIP"));
+
+ // MaxUnestablishedConnections
+ SetMaxUnestablishedConnections(CfgGetInt(f, "MaxUnestablishedConnections"));
+
+ // DeadLock
+ s->DisableDeadLockCheck = CfgGetBool(f, "DisableDeadLockCheck");
+
+ // Eraser
+ s->Eraser = NewEraser(s->Logger, CfgGetInt64(f, "AutoDeleteCheckDiskFreeSpaceMin"));
+
+ // WebUI
+ s->UseWebUI = CfgGetBool(f, "UseWebUI");
+
+ // WebTimePage
+ s->UseWebTimePage = CfgGetBool(f, "UseWebTimePage");
+
+ // NoLinuxArpFilter
+ s->NoLinuxArpFilter = CfgGetBool(f, "NoLinuxArpFilter");
+
+ // NoHighPriorityProcess
+ s->NoHighPriorityProcess = CfgGetBool(f, "NoHighPriorityProcess");
+
+ // NoDebugDump
+ s->NoDebugDump = CfgGetBool(f, "NoDebugDump");
+ if (s->NoDebugDump)
+ {
+#ifdef OS_WIN32
+ MsSetEnableMinidump(false);
+#endif // OS_WIN32
+ }
+
+ // Disable the SSTP server function
+ s->DisableSSTPServer = CfgGetBool(f, "DisableSSTPServer");
+
+ // Disable the OpenVPN server function
+ s->DisableOpenVPNServer = CfgGetBool(f, "DisableOpenVPNServer");
+
+ // Disable the NAT-traversal feature
+ s->DisableNatTraversal = CfgGetBool(f, "DisableNatTraversal");
+
+ // Intel AES
+ s->DisableIntelAesAcceleration = CfgGetBool(f, "DisableIntelAesAcceleration");
+
+ if (s->Cedar->Bridge == false)
+ {
+ // Enable the VPN-over-ICMP
+ if (CfgIsItem(f, "EnableVpnOverIcmp"))
+ {
+ s->EnableVpnOverIcmp = CfgGetBool(f, "EnableVpnOverIcmp");
+ }
+ else
+ {
+ s->EnableVpnOverIcmp = SiCanOpenVpnOverIcmpPort();;
+ }
+
+ // Enable the VPN-over-DNS
+ if (CfgIsItem(f, "EnableVpnOverDns"))
+ {
+ s->EnableVpnOverDns = CfgGetBool(f, "EnableVpnOverDns");
+ }
+ else
+ {
+ s->EnableVpnOverDns = SiCanOpenVpnOverDnsPort();
+ }
+ }
+
+ // Debug log
+ s->SaveDebugLog = CfgGetBool(f, "SaveDebugLog");
+ if (s->SaveDebugLog)
+ {
+ s->DebugLog = NewTinyLog();
+ }
+
+ // Let the client not to send a signature
+ s->NoSendSignature = CfgGetBool(f, "NoSendSignature");
+
+ // Server certificate
+ b = CfgGetBuf(f, "ServerCert");
+ if (b != NULL)
+ {
+ x = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ // Server private key
+ b = CfgGetBuf(f, "ServerKey");
+ if (b != NULL)
+ {
+ k = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+ }
+
+ if (x == NULL || k == NULL || CheckXandK(x, k) == false)
+ {
+ FreeX(x);
+ FreeK(k);
+ SiGenerateDefaultCert(&x, &k);
+
+ SetCedarCert(c, x, k);
+
+ FreeX(x);
+ FreeK(k);
+ }
+ else
+ {
+ SetCedarCert(c, x, k);
+
+ FreeX(x);
+ FreeK(k);
+ }
+
+ // Cipher Name
+ if (CfgGetStr(f, "CipherName", tmp, sizeof(tmp)))
+ {
+ StrUpper(tmp);
+ if (CheckCipherListName(tmp))
+ {
+ SetCedarCipherList(c, tmp);
+ }
+ }
+
+ // Traffic information
+ Lock(c->TrafficLock);
+ {
+ SiLoadTraffic(f, "ServerTraffic", c->Traffic);
+ }
+ Unlock(c->TrafficLock);
+
+ // Get whether the current license allows cluster mode
+ cluster_allowed = true;
+
+
+ // Type of server
+ s->UpdatedServerType = s->ServerType =
+ cluster_allowed ? CfgGetInt(f, "ServerType") : SERVER_TYPE_STANDALONE;
+
+ // Password
+ if (CfgGetByte(f, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword)) != sizeof(s->HashedPassword))
+ {
+ Hash(s->HashedPassword, "", 0, true);
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ // Performance ratio of the server
+ s->Weight = CfgGetInt(f, "ClusterMemberWeight");
+ if (s->Weight == 0)
+ {
+ s->Weight = FARM_DEFAULT_WEIGHT;
+ }
+ }
+ else
+ {
+ s->Weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ s->ControllerOnly = CfgGetBool(f, "ControllerOnly");
+ }
+
+ if (s->ServerType != SERVER_TYPE_STANDALONE)
+ {
+ // SSTP, OpenVPN, and NAT traversal can not be used in a cluster environment
+ s->DisableNatTraversal = true;
+ s->DisableSSTPServer = true;
+ s->DisableOpenVPNServer = true;
+ }
+
+ if (s->Cedar->Bridge)
+ {
+ // SSTP, OpenVPN, and NAT traversal function can not be used in the bridge environment
+ s->DisableNatTraversal = true;
+ s->DisableSSTPServer = true;
+ s->DisableOpenVPNServer = true;
+ }
+
+ // Read the OpenVPN Port List
+ if (CfgGetStr(f, "OpenVPN_UdpPortList", tmp, sizeof(tmp)) == false)
+ {
+ {
+ ToStr(tmp, OPENVPN_UDP_PORT);
+ }
+ }
+
+ // Apply the configuration of SSTP and OpenVPN
+ Zero(&config, sizeof(config));
+ config.EnableOpenVPN = !s->DisableOpenVPNServer;
+ config.EnableSSTP = !s->DisableSSTPServer;
+ StrCpy(config.OpenVPNPortList, sizeof(config.OpenVPNPortList), tmp);
+
+ SiSetOpenVPNAndSSTPConfig(s, &config);
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ char tmp[6 * MAX_PUBLIC_PORT_NUM + 1];
+ // Load the settings item in the case of farm members
+ CfgGetStr(f, "ControllerName", s->ControllerName, sizeof(s->ControllerName));
+ s->ControllerPort = CfgGetInt(f, "ControllerPort");
+ CfgGetByte(f, "MemberPassword", s->MemberPassword, SHA1_SIZE);
+ s->PublicIp = CfgGetIp32(f, "PublicIp");
+ if (CfgGetStr(f, "PublicPorts", tmp, sizeof(tmp)))
+ {
+ TOKEN_LIST *t = ParseToken(tmp, ", ");
+ UINT i;
+ s->NumPublicPort = t->NumTokens;
+ s->PublicPorts = ZeroMalloc(s->NumPublicPort * sizeof(UINT));
+ for (i = 0;i < s->NumPublicPort;i++)
+ {
+ s->PublicPorts[i] = ToInt(t->Token[i]);
+ }
+ FreeToken(t);
+ }
+ }
+
+ // Configuration of VPN Azure Client
+ s->EnableVpnAzure = CfgGetBool(f, "EnableVpnAzure");
+ }
+ Unlock(c->lock);
+}
+
+// Write the server-specific settings
+void SiWriteServerCfg(FOLDER *f, SERVER *s)
+{
+ BUF *b;
+ CEDAR *c;
+ // Validate arguments
+ if (f == NULL || s == NULL)
+ {
+ return;
+ }
+
+ CfgAddInt(f, "CurrentBuild", s->Cedar->Build);
+
+ CfgAddInt(f, "AutoSaveConfigSpan", s->AutoSaveConfigSpanSaved / 1000);
+
+ CfgAddBool(f, "DontBackupConfig", s->DontBackupConfig);
+ CfgAddBool(f, "BackupConfigOnlyWhenModified", s->BackupConfigOnlyWhenModified);
+
+ c = s->Cedar;
+
+ Lock(c->lock);
+ {
+ bool is_vgs_cert = false;
+ FOLDER *syslog_f;
+ Lock(s->Keep->lock);
+ {
+ KEEP *k = s->Keep;
+ CfgAddBool(f, "UseKeepConnect", k->Enable);
+ CfgAddStr(f, "KeepConnectHost", k->ServerName);
+ CfgAddInt(f, "KeepConnectPort", k->ServerPort);
+ CfgAddInt(f, "KeepConnectProtocol", k->UdpMode);
+ CfgAddInt(f, "KeepConnectInterval", k->Interval / 1000);
+ }
+ Unlock(s->Keep->lock);
+
+ // syslog
+ syslog_f = CfgCreateFolder(f, "SyslogSettings");
+ if (syslog_f != NULL)
+ {
+ SYSLOG_SETTING set;
+
+ SiGetSysLogSetting(s, &set);
+
+ CfgAddInt(syslog_f, "SaveType", set.SaveType);
+ CfgAddStr(syslog_f, "HostName", set.Hostname);
+ CfgAddInt(syslog_f, "Port", set.Port);
+ }
+
+ // IPv6 listener disable setting
+ CfgAddBool(f, "DisableIPv6Listener", s->Cedar->DisableIPv6Listener);
+
+ // DoS
+ CfgAddBool(f, "DisableDosProction", s->DisableDosProction);
+
+ // MaxConnectionsPerIP
+ CfgAddInt(f, "MaxConnectionsPerIP", GetMaxConnectionsPerIp());
+
+ // MaxUnestablishedConnections
+ CfgAddInt(f, "MaxUnestablishedConnections", GetMaxUnestablishedConnections());
+
+ // DeadLock
+ CfgAddBool(f, "DisableDeadLockCheck", s->DisableDeadLockCheck);
+
+ // Eraser related
+ CfgAddInt64(f, "AutoDeleteCheckDiskFreeSpaceMin", s->Eraser->MinFreeSpace);
+
+ // WebUI
+ CfgAddBool(f, "UseWebUI", s->UseWebUI);
+
+ // NoLinuxArpFilter
+ if (GetOsInfo()->OsType == OSTYPE_LINUX)
+ {
+ CfgAddBool(f, "NoLinuxArpFilter", s->NoLinuxArpFilter);
+ }
+
+ // NoHighPriorityProcess
+ CfgAddBool(f, "NoHighPriorityProcess", s->NoHighPriorityProcess);
+
+#ifdef OS_WIN32
+ CfgAddBool(f, "NoDebugDump", s->NoDebugDump);
+#endif // OS_WIN32
+
+ if (s->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ if (c->Bridge == false)
+ {
+ // Disable the NAT-traversal feature
+ CfgAddBool(f, "DisableNatTraversal", s->DisableNatTraversal);
+
+ // Disable the SSTP server function
+ CfgAddBool(f, "DisableSSTPServer", s->DisableSSTPServer);
+
+ // Disable the OpenVPN server function
+ CfgAddBool(f, "DisableOpenVPNServer", s->DisableOpenVPNServer);
+ }
+ }
+
+ if (c->Bridge == false)
+ {
+ // VPN over ICMP
+ CfgAddBool(f, "EnableVpnOverIcmp", s->EnableVpnOverIcmp);
+
+ // VPN over DNS
+ CfgAddBool(f, "EnableVpnOverDns", s->EnableVpnOverDns);
+ }
+
+ // Intel AES
+ CfgAddBool(f, "DisableIntelAesAcceleration", s->DisableIntelAesAcceleration);
+
+ if (c->Bridge == false)
+ {
+ OPENVPN_SSTP_CONFIG config;
+
+ SiGetOpenVPNAndSSTPConfig(s, &config);
+
+ CfgAddStr(f, "OpenVPN_UdpPortList", config.OpenVPNPortList);
+ }
+
+ // WebTimePage
+ CfgAddBool(f, "UseWebTimePage", s->UseWebTimePage);
+
+ // Debug log
+ CfgAddBool(f, "SaveDebugLog", s->SaveDebugLog);
+
+ // Let the client not to send a signature
+ CfgAddBool(f, "NoSendSignature", s->NoSendSignature);
+
+
+ if (is_vgs_cert == false)
+ {
+ // Server certificate
+ b = XToBuf(c->ServerX, false);
+ CfgAddBuf(f, "ServerCert", b);
+ FreeBuf(b);
+
+ // Server private key
+ b = KToBuf(c->ServerK, false, NULL);
+ CfgAddBuf(f, "ServerKey", b);
+ FreeBuf(b);
+ }
+
+ // Traffic information
+ Lock(c->TrafficLock);
+ {
+ SiWriteTraffic(f, "ServerTraffic", c->Traffic);
+ }
+ Unlock(c->TrafficLock);
+
+ // Type of server
+ if (s->Cedar->Bridge == false)
+ {
+ CfgAddInt(f, "ServerType", s->UpdatedServerType);
+ }
+
+ // Cipher Name
+ CfgAddStr(f, "CipherName", s->Cedar->CipherList);
+
+ // Password
+ CfgAddByte(f, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
+
+ if (s->UpdatedServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ char tmp[6 * MAX_PUBLIC_PORT_NUM + 1];
+ UINT i;
+ // Setting items in the case of farm members
+ CfgAddStr(f, "ControllerName", s->ControllerName);
+ CfgAddInt(f, "ControllerPort", s->ControllerPort);
+ CfgAddByte(f, "MemberPassword", s->MemberPassword, SHA1_SIZE);
+ CfgAddIp32(f, "PublicIp", s->PublicIp);
+ tmp[0] = 0;
+ for (i = 0;i < s->NumPublicPort;i++)
+ {
+ char tmp2[MAX_SIZE];
+ ToStr(tmp2, s->PublicPorts[i]);
+ StrCat(tmp, sizeof(tmp), tmp2);
+ StrCat(tmp, sizeof(tmp), ",");
+ }
+ if (StrLen(tmp) >= 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == ',')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+ CfgAddStr(f, "PublicPorts", tmp);
+ }
+
+ if (s->UpdatedServerType != SERVER_TYPE_STANDALONE)
+ {
+ CfgAddInt(f, "ClusterMemberWeight", s->Weight);
+ }
+
+ if (s->UpdatedServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ CfgAddBool(f, "ControllerOnly", s->ControllerOnly);
+ }
+
+ // VPN Azure Client
+ if (s->AzureClient != NULL)
+ {
+ CfgAddBool(f, "EnableVpnAzure", s->EnableVpnAzure);
+ }
+ }
+ Unlock(c->lock);
+}
+
+// Read the traffic information
+void SiLoadTraffic(FOLDER *parent, char *name, TRAFFIC *t)
+{
+ FOLDER *f;
+ // Validate arguments
+ if (t != NULL)
+ {
+ Zero(t, sizeof(TRAFFIC));
+ }
+ if (parent == NULL || name == NULL || t == NULL)
+ {
+ return;
+ }
+
+ f = CfgGetFolder(parent, name);
+
+ if (f == NULL)
+ {
+ return;
+ }
+
+ SiLoadTrafficInner(f, "SendTraffic", &t->Send);
+ SiLoadTrafficInner(f, "RecvTraffic", &t->Recv);
+}
+void SiLoadTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e)
+{
+ FOLDER *f;
+ // Validate arguments
+ if (e != NULL)
+ {
+ Zero(e, sizeof(TRAFFIC_ENTRY));
+ }
+ if (parent == NULL || name == NULL || e == NULL)
+ {
+ return;
+ }
+
+ f = CfgGetFolder(parent, name);
+ if (f == NULL)
+ {
+ return;
+ }
+
+ e->BroadcastCount = CfgGetInt64(f, "BroadcastCount");
+ e->BroadcastBytes = CfgGetInt64(f, "BroadcastBytes");
+ e->UnicastCount = CfgGetInt64(f, "UnicastCount");
+ e->UnicastBytes = CfgGetInt64(f, "UnicastBytes");
+}
+
+// Write the traffic information
+void SiWriteTraffic(FOLDER *parent, char *name, TRAFFIC *t)
+{
+ FOLDER *f;
+ // Validate arguments
+ if (parent == NULL || name == NULL || t == NULL)
+ {
+ return;
+ }
+
+ f = CfgCreateFolder(parent, name);
+
+ SiWriteTrafficInner(f, "SendTraffic", &t->Send);
+ SiWriteTrafficInner(f, "RecvTraffic", &t->Recv);
+}
+void SiWriteTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e)
+{
+ FOLDER *f;
+ // Validate arguments
+ if (parent == NULL || name == NULL || e == NULL)
+ {
+ return;
+ }
+
+ f = CfgCreateFolder(parent, name);
+ CfgAddInt64(f, "BroadcastCount", e->BroadcastCount);
+ CfgAddInt64(f, "BroadcastBytes", e->BroadcastBytes);
+ CfgAddInt64(f, "UnicastCount", e->UnicastCount);
+ CfgAddInt64(f, "UnicastBytes", e->UnicastBytes);
+}
+
+// Thread for writing configuration file
+void SiSaverThread(THREAD *thread, void *param)
+{
+ SERVER *s = (SERVER *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (s->Halt == false)
+ {
+ // Save to the configuration file
+ if (s->NoMoreSave == false)
+ {
+ SiWriteConfigurationFile(s);
+ }
+
+ Wait(s->SaveHaltEvent, s->AutoSaveConfigSpan);
+ }
+}
+
+// Write to the configuration file
+UINT SiWriteConfigurationFile(SERVER *s)
+{
+ UINT ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ if (s->CfgRw == NULL)
+ {
+ return 0;
+ }
+
+ if (s->NoMoreSave)
+ {
+ return 0;
+ }
+
+ Lock(s->SaveCfgLock);
+ {
+ FOLDER *f;
+
+ Debug("save: SiWriteConfigurationToCfg() start.\n");
+ f = SiWriteConfigurationToCfg(s);
+ Debug("save: SiWriteConfigurationToCfg() finished.\n");
+
+ Debug("save: SaveCfgRw() start.\n");
+ ret = SaveCfgRwEx(s->CfgRw, f, s->BackupConfigOnlyWhenModified ? s->ConfigRevision : INFINITE);
+ Debug("save: SaveCfgRw() finished.\n");
+
+ Debug("save: CfgDeleteFolder() start.\n");
+ CfgDeleteFolder(f);
+ Debug("save: CfgDeleteFolder() finished.\n");
+ }
+ Unlock(s->SaveCfgLock);
+
+ return ret;
+}
+
+// Release the configuration
+void SiFreeConfiguration(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Write to the configuration file
+ SiWriteConfigurationFile(s);
+
+ // Terminate the configuration file saving thread
+ s->NoMoreSave = true;
+ s->Halt = true;
+ Set(s->SaveHaltEvent);
+ WaitThread(s->SaveThread, INFINITE);
+
+ ReleaseEvent(s->SaveHaltEvent);
+ ReleaseThread(s->SaveThread);
+
+ s->SaveHaltEvent = NULL;
+ s->SaveThread = NULL;
+
+
+ // Stop the IPsec server
+ if (s->IPsecServer != NULL)
+ {
+ FreeIPsecServer(s->IPsecServer);
+ s->IPsecServer = NULL;
+ }
+
+ // Terminate the OpenVPN server
+ if (s->OpenVpnServerUdp != NULL)
+ {
+ FreeOpenVpnServerUdp(s->OpenVpnServerUdp);
+ s->OpenVpnServerUdp = NULL;
+ }
+
+
+ // Terminate the DDNS client
+ if (s->DDnsClient != NULL)
+ {
+ FreeDDNSClient(s->DDnsClient);
+ s->DDnsClient = NULL;
+ }
+
+ // Terminate the VPN Azure client
+ if (s->AzureClient != NULL)
+ {
+ FreeAzureClient(s->AzureClient);
+ s->AzureClient = NULL;
+ }
+
+ FreeCfgRw(s->CfgRw);
+ s->CfgRw = NULL;
+
+ // Release the Ethernet
+ FreeEth();
+}
+
+// Initialize the StXxx related function
+void StInit()
+{
+ if (server_lock != NULL)
+ {
+ return;
+ }
+
+ server_lock = NewLock();
+}
+
+// Release the StXxx related function
+void StFree()
+{
+ DeleteLock(server_lock);
+ server_lock = NULL;
+}
+
+// Start the server
+void StStartServer(bool bridge)
+{
+ Lock(server_lock);
+ {
+ if (server != NULL)
+ {
+ // It has already started
+ Unlock(server_lock);
+ return;
+ }
+
+ // Create a server
+ server = SiNewServer(bridge);
+ }
+ Unlock(server_lock);
+
+// StartCedarLog();
+}
+
+// Get the server
+SERVER *StGetServer()
+{
+ if (server == NULL)
+ {
+ return NULL;
+ }
+ return server;
+}
+
+// Stop the server
+void StStopServer()
+{
+ Lock(server_lock);
+ {
+ if (server == NULL)
+ {
+ // Not started
+ Unlock(server_lock);
+ return;
+ }
+
+ // Release the server
+ SiReleaseServer(server);
+ server = NULL;
+ }
+ Unlock(server_lock);
+
+ StopCedarLog();
+}
+
+// Set the type of server
+void SiSetServerType(SERVER *s, UINT type,
+ UINT ip, UINT num_port, UINT *ports,
+ char *controller_name, UINT controller_port, UCHAR *password, UINT weight, bool controller_only)
+{
+ bool bridge;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+ if (type == SERVER_TYPE_FARM_MEMBER &&
+ (num_port == 0 || ports == NULL || controller_name == NULL ||
+ controller_port == 0 || password == NULL || num_port > MAX_PUBLIC_PORT_NUM))
+ {
+ return;
+ }
+ if (weight == 0)
+ {
+ weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ bridge = s->Cedar->Bridge;
+
+ Lock(s->lock);
+ {
+ // Update types
+ s->UpdatedServerType = type;
+
+ s->Weight = weight;
+
+ // Set the value
+ if (type == SERVER_TYPE_FARM_MEMBER)
+ {
+ StrCpy(s->ControllerName, sizeof(s->ControllerName), controller_name);
+ s->ControllerPort = controller_port;
+ if (IsZero(password, SHA1_SIZE) == false)
+ {
+ Copy(s->MemberPassword, password, SHA1_SIZE);
+ }
+ s->PublicIp = ip;
+ s->NumPublicPort = num_port;
+ if (s->PublicPorts != NULL)
+ {
+ Free(s->PublicPorts);
+ }
+ s->PublicPorts = ZeroMalloc(num_port * sizeof(UINT));
+ Copy(s->PublicPorts, ports, num_port * sizeof(UINT));
+ }
+
+ if (type == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ s->ControllerOnly = controller_only;
+ }
+ }
+ Unlock(s->lock);
+
+ // Restart the server
+ SiRebootServer(bridge);
+}
+
+// Thread to restart the server
+void SiRebootServerThread(THREAD *thread, void *param)
+{
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+ if (server == NULL)
+ {
+ return;
+ }
+
+ // Stop the server
+ StStopServer();
+
+ // Start the server
+ StStartServer((bool)param);
+}
+
+// Restart the server
+void SiRebootServer(bool bridge)
+{
+ SiRebootServerEx(bridge, false);
+}
+void SiRebootServerEx(bool bridge, bool reset_setting)
+{
+ THREAD *t;
+
+ server_reset_setting = reset_setting;
+
+ t = NewThread(SiRebootServerThread, (void *)bridge);
+ ReleaseThread(t);
+}
+
+// Set the state of the special listener
+void SiApplySpecialListenerStatus(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->DynListenerDns != NULL)
+ {
+ *s->DynListenerDns->EnablePtr = s->EnableVpnOverDns;
+ ApplyDynamicListener(s->DynListenerDns);
+ }
+
+ if (s->DynListenerIcmp != NULL)
+ {
+ *s->DynListenerIcmp->EnablePtr = s->EnableVpnOverIcmp;
+ ApplyDynamicListener(s->DynListenerIcmp);
+ }
+}
+
+// Stop all listeners
+void SiStopAllListener(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SiLockListenerList(s);
+ {
+ UINT i;
+ LIST *o = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
+ {
+ SERVER_LISTENER *e = LIST_DATA(s->ServerListenerList, i);
+ Add(o, e);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SERVER_LISTENER *e = LIST_DATA(o, i);
+ SiDeleteListener(s, e->Port);
+ }
+
+ ReleaseList(o);
+ }
+ SiUnlockListenerList(s);
+
+ ReleaseList(s->ServerListenerList);
+
+ // Stop the VPN over ICMP listener
+ FreeDynamicListener(s->DynListenerIcmp);
+ s->DynListenerIcmp = NULL;
+
+ // Stop the VPN over DNS listener
+ FreeDynamicListener(s->DynListenerDns);
+ s->DynListenerDns = NULL;
+}
+
+// Clean-up the server
+void SiCleanupServer(SERVER *s)
+{
+ UINT i;
+ CEDAR *c;
+ LISTENER **listener_list;
+ UINT num_listener;
+ HUB **hub_list;
+ UINT num_hub;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SiFreeDeadLockCheck(s);
+
+
+ c = s->Cedar;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ // In the case of farm members, stop the connection to the farm controller
+ SLog(c, "LS_STOP_FARM_MEMBER");
+ SiStopConnectToController(s->FarmController);
+ s->FarmController = NULL;
+ SLog(c, "LS_STOP_FARM_MEMBER_2");
+ }
+
+ IncrementServerConfigRevision(s);
+
+ SLog(c, "LS_END_2");
+
+ SLog(c, "LS_STOP_ALL_LISTENER");
+ // Stop all listeners
+ LockList(c->ListenerList);
+ {
+ listener_list = ToArray(c->ListenerList);
+ num_listener = LIST_NUM(c->ListenerList);
+ for (i = 0;i < num_listener;i++)
+ {
+ AddRef(listener_list[i]->ref);
+ }
+ }
+ UnlockList(c->ListenerList);
+
+ for (i = 0;i < num_listener;i++)
+ {
+ StopListener(listener_list[i]);
+ ReleaseListener(listener_list[i]);
+ }
+ Free(listener_list);
+ SLog(c, "LS_STOP_ALL_LISTENER_2");
+
+ SLog(c, "LS_STOP_ALL_HUB");
+ // Stop all HUBs
+ LockList(c->HubList);
+ {
+ hub_list = ToArray(c->HubList);
+ num_hub = LIST_NUM(c->HubList);
+ for (i = 0;i < num_hub;i++)
+ {
+ AddRef(hub_list[i]->ref);
+ }
+ }
+ UnlockList(c->HubList);
+
+ for (i = 0;i < num_hub;i++)
+ {
+ StopHub(hub_list[i]);
+ ReleaseHub(hub_list[i]);
+ }
+ Free(hub_list);
+ SLog(c, "LS_STOP_ALL_HUB_2");
+
+ // Release the configuration
+ SiFreeConfiguration(s);
+
+ // Stop the Cedar
+ SLog(c, "LS_STOP_CEDAR");
+ StopCedar(s->Cedar);
+ SLog(c, "LS_STOP_CEDAR_2");
+
+ // Stop all listeners
+ SiStopAllListener(s);
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // In the case of farm controller
+ UINT i;
+
+ SLog(c, "LS_STOP_FARM_CONTROL");
+
+ // Stop the farm controling
+ SiStopFarmControl(s);
+
+ // Release the farm member information
+ ReleaseList(s->FarmMemberList);
+ s->FarmMemberList = NULL;
+
+ for (i = 0;i < LIST_NUM(s->Me->HubList);i++)
+ {
+ Free(LIST_DATA(s->Me->HubList, i));
+ }
+ ReleaseList(s->Me->HubList);
+
+ Free(s->Me);
+
+ SLog(c, "LS_STOP_FARM_CONTROL_2");
+ }
+
+ if (s->PublicPorts != NULL)
+ {
+ Free(s->PublicPorts);
+ }
+
+ SLog(s->Cedar, "LS_END_1");
+ SLog(s->Cedar, "L_LINE");
+
+#ifdef ENABLE_AZURE_SERVER
+ if (s->AzureServer != NULL)
+ {
+ FreeAzureServer(s->AzureServer);
+ }
+#endif // ENABLE_AZURE_SERVER
+
+ ReleaseCedar(s->Cedar);
+ DeleteLock(s->lock);
+ DeleteLock(s->SaveCfgLock);
+
+ StopKeep(s->Keep);
+
+ FreeEraser(s->Eraser);
+
+
+ FreeLog(s->Logger);
+
+ FreeSysLog(s->Syslog);
+ DeleteLock(s->SyslogLock);
+
+ FreeServerCapsCache(s);
+
+ SiFreeHubCreateHistory(s);
+
+ // Stop the debug log
+ FreeTinyLog(s->DebugLog);
+
+ DeleteLock(s->TasksFromFarmControllerLock);
+ DeleteLock(s->OpenVpnSstpConfigLock);
+
+
+ Free(s);
+}
+
+// Release the server
+void SiReleaseServer(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ SiCleanupServer(s);
+ }
+}
+
+// Get the URL of the member selector
+bool SiGetMemberSelectorUrl(char *url, UINT url_size)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (url == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(MEMBER_SELECTOR_TXT_FILENAME);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false && ret == false)
+ {
+ StrCpy(url, url_size, line);
+ ret = true;
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Specify the farm member for the next processing
+FARM_MEMBER *SiGetNextFarmMember(SERVER *s, CONNECTION *c, HUB *h)
+{
+ UINT i, num;
+ UINT min_point = 0;
+ FARM_MEMBER *ret = NULL;
+ PACK *p;
+ char url[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER || c == NULL || h == NULL)
+ {
+ return NULL;
+ }
+
+ num = LIST_NUM(s->FarmMemberList);
+ if (num == 0)
+ {
+ return NULL;
+ }
+
+ if (SiGetMemberSelectorUrl(url, sizeof(url)))
+ {
+ UINT64 ret_key = 0;
+ // Generate the data for the member selector
+ p = NewPack();
+ for (i = 0;i < num;i++)
+ {
+ UINT num_sessions;
+ UINT max_sessions;
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ bool do_not_select = false;
+ if (s->ControllerOnly)
+ {
+ if (f->Me)
+ {
+ // No to select myself in the case of ControllerOnly
+ do_not_select = true;
+ }
+ }
+
+ if (f->Me == false)
+ {
+ num_sessions = f->NumSessions;
+ max_sessions = f->MaxSessions;
+ }
+ else
+ {
+ num_sessions = Count(s->Cedar->CurrentSessions);
+ max_sessions = GetServerCapsInt(s, "i_max_sessions");
+ }
+
+ if (max_sessions == 0)
+ {
+ max_sessions = GetServerCapsInt(s, "i_max_sessions");
+ }
+
+ if (num_sessions >= max_sessions)
+ {
+ do_not_select = true;
+ }
+
+ if (true)
+ {
+ UINT point = f->Point;
+ char public_ip_str[MAX_SIZE];
+
+ IPToStr32(public_ip_str, sizeof(public_ip_str), f->Ip);
+
+ PackAddIntEx(p, "Point", point, i, num);
+ PackAddInt64Ex(p, "Key", (UINT64)f, i, num);
+ PackAddStrEx(p, "Hostname", f->hostname, i, num);
+ PackAddStrEx(p, "PublicIp", public_ip_str, i, num);
+ PackAddIntEx(p, "NumSessions", num_sessions, i, num);
+ PackAddIntEx(p, "MaxSessions", max_sessions, i, num);
+ PackAddIntEx(p, "AssignedClientLicense", f->AssignedClientLicense, i, num);
+ PackAddIntEx(p, "AssignedBridgeLicense", f->AssignedBridgeLicense, i, num);
+ PackAddIntEx(p, "Weight", f->Weight, i, num);
+ PackAddDataEx(p, "RandomKey", f->RandomKey, SHA1_SIZE, i, num);
+ PackAddIntEx(p, "NumTcpConnections", f->NumTcpConnections, i, num);
+ PackAddIntEx(p, "NumHubs", LIST_NUM(f->HubList), i, num);
+ PackAddBoolEx(p, "Me", f->Me, i, num);
+ PackAddInt64Ex(p, "ConnectedTime", f->ConnectedTime, i, num);
+ PackAddInt64Ex(p, "SystemId", f->SystemId, i, num);
+ PackAddBoolEx(p, "DoNotSelect", do_not_select, i, num);
+ }
+ }
+
+ if (true)
+ {
+ char client_ip_str[MAX_SIZE];
+ UINT client_port = 0;
+ UINT server_port = 0;
+ SOCK *s = c->FirstSock;
+
+ Zero(client_ip_str, sizeof(client_ip_str));
+ if (s != NULL)
+ {
+ IPToStr(client_ip_str, sizeof(client_ip_str), &s->RemoteIP);
+ client_port = s->RemotePort;
+ server_port = s->LocalPort;
+ }
+
+ PackAddStr(p, "ClientIp", client_ip_str);
+ PackAddInt(p, "ClientPort", client_port);
+ PackAddInt(p, "ServerPort", server_port);
+
+ PackAddInt(p, "ClientBuild", c->ClientBuild);
+ PackAddStr(p, "CipherName", c->CipherName);
+ PackAddStr(p, "ClientStr", c->ClientStr);
+ PackAddInt(p, "ClientVer", c->ClientVer);
+ PackAddInt64(p, "ConnectedTime", Tick64ToTime64(c->ConnectedTick));
+
+ PackAddStr(p, "HubName", h->Name);
+ PackAddBool(p, "StaticHub", h->Type == HUB_TYPE_FARM_STATIC);
+ }
+
+ PackAddInt(p, "NumMembers", num);
+
+ // Make the member selector choose a member
+ UnlockList(s->FarmMemberList);
+ Unlock(s->Cedar->CedarSuperLock);
+ {
+ PACK *ret;
+
+ Debug("Calling %s ...\n", url);
+
+ ret = WpcCall(url, NULL, MEMBER_SELECTOR_CONNECT_TIMEOUT, MEMBER_SELECTOR_DATA_TIMEOUT,
+ "Select", p, NULL, NULL, NULL);
+
+ if (GetErrorFromPack(ret) == ERR_NO_ERROR)
+ {
+ ret_key = PackGetInt64(ret, "Key");
+ Debug("Ret Key = %I64u\n", ret_key);
+ }
+ else
+ {
+ Debug("Error: %u\n", GetErrorFromPack(ret));
+ }
+
+ FreePack(ret);
+ }
+ Lock(s->Cedar->CedarSuperLock);
+ LockList(s->FarmMemberList);
+
+ FreePack(p);
+
+ if (ret_key != 0)
+ {
+ FARM_MEMBER *f = (FARM_MEMBER *)ret_key;
+ if (IsInList(s->FarmMemberList, f))
+ {
+ Debug("Farm Member Selected by Selector: %s\n", f->hostname);
+
+ return f;
+ }
+ else
+ {
+ Debug("Farm Member Key = %I64u Not Found.\n", ret_key);
+ }
+ }
+ else
+ {
+ // The member selector failed to select a member
+ return NULL;
+ }
+ }
+
+ num = LIST_NUM(s->FarmMemberList);
+ if (num == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ UINT num_sessions;
+ UINT max_sessions;
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (s->ControllerOnly)
+ {
+ if (f->Me)
+ {
+ // No to select myself in the case of ControllerOnly
+ continue;
+ }
+ }
+
+ if (f->Me == false)
+ {
+ num_sessions = f->NumSessions;
+ max_sessions = f->MaxSessions;
+ }
+ else
+ {
+ num_sessions = Count(s->Cedar->CurrentSessions);
+ max_sessions = GetServerCapsInt(s, "i_max_sessions");
+ }
+
+ if (max_sessions == 0)
+ {
+ max_sessions = GetServerCapsInt(s, "i_max_sessions");
+ }
+
+ if (num_sessions < max_sessions)
+ {
+ if (f->Point >= min_point)
+ {
+ min_point = f->Point;
+ ret = f;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Receive a HUB enumeration directive
+void SiCalledEnumHub(SERVER *s, PACK *p, PACK *req)
+{
+ UINT i;
+ CEDAR *c;
+ UINT num = 0;
+ // Validate arguments
+ if (s == NULL || p == NULL || req == NULL)
+ {
+ return;
+ }
+
+
+ c = s->Cedar;
+
+ LockList(c->HubList);
+ {
+ UINT num = LIST_NUM(c->HubList);
+ for (i = 0;i < num;i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ Lock(h->lock);
+ {
+ PackAddStrEx(p, "HubName", h->Name, i, num);
+ PackAddIntEx(p, "HubType", h->Type, i, num);
+ PackAddIntEx(p, "NumSession", Count(h->NumSessions), i, num);
+
+ PackAddIntEx(p, "NumSessions", LIST_NUM(h->SessionList), i, num);
+ PackAddIntEx(p, "NumSessionsClient", Count(h->NumSessionsClient), i, num);
+ PackAddIntEx(p, "NumSessionsBridge", Count(h->NumSessionsBridge), i, num);
+
+ PackAddIntEx(p, "NumMacTables", LIST_NUM(h->MacTable), i, num);
+
+ PackAddIntEx(p, "NumIpTables", LIST_NUM(h->IpTable), i, num);
+
+ PackAddInt64Ex(p, "LastCommTime", h->LastCommTime, i, num);
+ PackAddInt64Ex(p, "CreatedTime", h->CreatedTime, i, num);
+ }
+ Unlock(h->lock);
+ }
+ }
+ UnlockList(c->HubList);
+
+ PackAddInt(p, "Point", SiGetPoint(s));
+ PackAddInt(p, "NumTcpConnections", Count(s->Cedar->CurrentTcpConnections));
+ PackAddInt(p, "NumTotalSessions", Count(s->Cedar->CurrentSessions));
+ PackAddInt(p, "MaxSessions", GetServerCapsInt(s, "i_max_sessions"));
+
+ PackAddInt(p, "AssignedClientLicense", Count(s->Cedar->AssignedClientLicense));
+ PackAddInt(p, "AssignedBridgeLicense", Count(s->Cedar->AssignedBridgeLicense));
+
+ PackAddData(p, "RandomKey", s->MyRandomKey, SHA1_SIZE);
+
+
+ Lock(c->TrafficLock);
+ {
+ OutRpcTraffic(p, c->Traffic);
+ }
+ Unlock(c->TrafficLock);
+
+ LockList(c->TrafficDiffList);
+ {
+ UINT num = LIST_NUM(c->TrafficDiffList);
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ TRAFFIC_DIFF *d = LIST_DATA(c->TrafficDiffList, i);
+
+ PackAddIntEx(p, "TdType", d->Type, i, num);
+ PackAddStrEx(p, "TdHubName", d->HubName, i, num);
+ PackAddStrEx(p, "TdName", d->Name, i, num);
+
+ OutRpcTrafficEx(&d->Traffic, p, i, num);
+
+ Free(d->HubName);
+ Free(d->Name);
+ Free(d);
+ }
+
+ DeleteAll(c->TrafficDiffList);
+ }
+ UnlockList(c->TrafficDiffList);
+}
+
+// Receive a HUB delete directive
+void SiCalledDeleteHub(SERVER *s, PACK *p)
+{
+ char name[MAX_SIZE];
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (PackGetStr(p, "HubName", name, sizeof(name)) == false)
+ {
+ return;
+ }
+
+ LockHubList(s->Cedar);
+
+ h = GetHub(s->Cedar, name);
+ if (h == NULL)
+ {
+ UnlockHubList(s->Cedar);
+ return;
+ }
+ UnlockHubList(s->Cedar);
+
+ SetHubOffline(h);
+
+ LockHubList(s->Cedar);
+
+ DelHubEx(s->Cedar, h, true);
+
+ UnlockHubList(s->Cedar);
+
+ ReleaseHub(h);
+}
+
+// Receive a HUB update directive
+void SiCalledUpdateHub(SERVER *s, PACK *p)
+{
+ char name[MAX_SIZE];
+ UINT type;
+ HUB_OPTION o;
+ HUB_LOG log;
+ bool save_packet_log;
+ UINT packet_log_switch_type;
+ UINT packet_log_config[NUM_PACKET_LOG];
+ bool save_security_log;
+ bool type_changed = false;
+ UINT security_log_switch_type;
+ UINT i;
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetStr(p, "HubName", name, sizeof(name));
+ type = PackGetInt(p, "HubType");
+ Zero(&o, sizeof(o));
+ o.MaxSession = PackGetInt(p, "MaxSession");
+ o.NoArpPolling = PackGetBool(p, "NoArpPolling");
+ o.NoIPv6AddrPolling = PackGetBool(p, "NoIPv6AddrPolling");
+ o.FilterPPPoE = PackGetBool(p, "FilterPPPoE");
+ o.YieldAfterStorePacket = PackGetBool(p, "YieldAfterStorePacket");
+ o.NoSpinLockForPacketDelay = PackGetBool(p, "NoSpinLockForPacketDelay");
+ o.BroadcastStormDetectionThreshold = PackGetInt(p, "BroadcastStormDetectionThreshold");
+ o.ClientMinimumRequiredBuild = PackGetInt(p, "ClientMinimumRequiredBuild");
+ o.FixForDLinkBPDU = PackGetBool(p, "FixForDLinkBPDU");
+ o.BroadcastLimiterStrictMode = PackGetBool(p, "BroadcastLimiterStrictMode");
+ o.NoLookBPDUBridgeId = PackGetBool(p, "NoLookBPDUBridgeId");
+ o.NoManageVlanId = PackGetBool(p, "NoManageVlanId");
+ o.MaxLoggedPacketsPerMinute = PackGetInt(p, "MaxLoggedPacketsPerMinute");
+ o.DoNotSaveHeavySecurityLogs = PackGetBool(p, "DoNotSaveHeavySecurityLogs");
+ o.VlanTypeId = PackGetInt(p, "VlanTypeId");
+ if (o.VlanTypeId == 0)
+ {
+ o.VlanTypeId = MAC_PROTO_TAGVLAN;
+ }
+ o.FilterOSPF = PackGetBool(p, "FilterOSPF");
+ o.FilterIPv4 = PackGetBool(p, "FilterIPv4");
+ o.FilterIPv6 = PackGetBool(p, "FilterIPv6");
+ o.FilterNonIP = PackGetBool(p, "FilterNonIP");
+ o.NoIPv4PacketLog = PackGetBool(p, "NoIPv4PacketLog");
+ o.NoIPv6PacketLog = PackGetBool(p, "NoIPv6PacketLog");
+ o.FilterBPDU = PackGetBool(p, "FilterBPDU");
+ o.NoIPv6DefaultRouterInRAWhenIPv6 = PackGetBool(p, "NoIPv6DefaultRouterInRAWhenIPv6");
+ o.NoMacAddressLog = PackGetBool(p, "NoMacAddressLog");
+ o.ManageOnlyPrivateIP = PackGetBool(p, "ManageOnlyPrivateIP");
+ o.ManageOnlyLocalUnicastIPv6 = PackGetBool(p, "ManageOnlyLocalUnicastIPv6");
+ o.DisableIPParsing = PackGetBool(p, "DisableIPParsing");
+ o.NoIpTable = PackGetBool(p, "NoIpTable");
+ o.NoEnum = PackGetBool(p, "NoEnum");
+ o.AdjustTcpMssValue = PackGetInt(p, "AdjustTcpMssValue");
+ o.DisableAdjustTcpMss = PackGetBool(p, "DisableAdjustTcpMss");
+ o.NoDhcpPacketLogOutsideHub = PackGetBool(p, "NoDhcpPacketLogOutsideHub");
+ o.DisableHttpParsing = PackGetBool(p, "DisableHttpParsing");
+ o.DisableUdpAcceleration = PackGetBool(p, "DisableUdpAcceleration");
+ o.DisableUdpFilterForLocalBridgeNic = PackGetBool(p, "DisableUdpFilterForLocalBridgeNic");
+ o.ApplyIPv4AccessListOnArpPacket = PackGetBool(p, "ApplyIPv4AccessListOnArpPacket");
+ o.RemoveDefGwOnDhcpForLocalhost = PackGetBool(p, "RemoveDefGwOnDhcpForLocalhost");
+ o.SecureNAT_MaxTcpSessionsPerIp = PackGetInt(p, "SecureNAT_MaxTcpSessionsPerIp");
+ o.SecureNAT_MaxTcpSynSentPerIp = PackGetInt(p, "SecureNAT_MaxTcpSynSentPerIp");
+ o.SecureNAT_MaxUdpSessionsPerIp = PackGetInt(p, "SecureNAT_MaxUdpSessionsPerIp");
+ o.SecureNAT_MaxDnsSessionsPerIp = PackGetInt(p, "SecureNAT_MaxDnsSessionsPerIp");
+ o.SecureNAT_MaxIcmpSessionsPerIp = PackGetInt(p, "SecureNAT_MaxIcmpSessionsPerIp");
+ o.AccessListIncludeFileCacheLifetime = PackGetInt(p, "AccessListIncludeFileCacheLifetime");
+ if (o.AccessListIncludeFileCacheLifetime == 0)
+ {
+ o.AccessListIncludeFileCacheLifetime = ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME;
+ }
+ o.DisableKernelModeSecureNAT = PackGetBool(p, "DisableKernelModeSecureNAT");
+ o.DisableUserModeSecureNAT = PackGetBool(p, "DisableUserModeSecureNAT");
+ o.DisableCheckMacOnLocalBridge = PackGetBool(p, "DisableCheckMacOnLocalBridge");
+ o.DisableCorrectIpOffloadChecksum = PackGetBool(p, "DisableCorrectIpOffloadChecksum");
+
+ save_packet_log = PackGetInt(p, "SavePacketLog");
+ packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ packet_log_config[i] = PackGetIntEx(p, "PacketLogConfig", i);
+ }
+ save_security_log = PackGetInt(p, "SaveSecurityLog");
+ security_log_switch_type = PackGetInt(p, "SecurityLogSwitchType");
+
+ Zero(&log, sizeof(log));
+ log.SavePacketLog = save_packet_log;
+ log.PacketLogSwitchType = packet_log_switch_type;
+ Copy(log.PacketLogConfig, packet_log_config, sizeof(log.PacketLogConfig));
+ log.SaveSecurityLog = save_security_log;
+ log.SecurityLogSwitchType = security_log_switch_type;
+
+ h = GetHub(s->Cedar, name);
+ if (h == NULL)
+ {
+ return;
+ }
+
+ h->FarmMember_MaxSessionClient = PackGetInt(p, "MaxSessionClient");
+ h->FarmMember_MaxSessionBridge = PackGetInt(p, "MaxSessionBridge");
+ h->FarmMember_MaxSessionClientBridgeApply = PackGetBool(p, "MaxSessionClientBridgeApply");
+
+ if (h->FarmMember_MaxSessionClientBridgeApply == false)
+ {
+ h->FarmMember_MaxSessionClient = INFINITE;
+ h->FarmMember_MaxSessionBridge = INFINITE;
+ }
+
+ Lock(h->lock);
+ {
+ Copy(h->Option, &o, sizeof(HUB_OPTION));
+ PackGetData2(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
+ PackGetData2(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
+ }
+ Unlock(h->lock);
+
+ SetHubLogSetting(h, &log);
+
+ if (h->Type != type)
+ {
+ h->Type = type;
+ type_changed = true;
+ }
+
+ LockList(h->AccessList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ {
+ ACCESS *a = LIST_DATA(h->AccessList, i);
+ Free(a);
+ }
+ DeleteAll(h->AccessList);
+ }
+ UnlockList(h->AccessList);
+
+ for (i = 0;i < SiNumAccessFromPack(p);i++)
+ {
+ ACCESS *a = SiPackToAccess(p, i);
+ AddAccessList(h, a);
+ Free(a);
+ }
+
+ if (PackGetBool(p, "EnableSecureNAT"))
+ {
+ VH_OPTION t;
+ bool changed;
+
+ InVhOption(&t, p);
+
+ changed = Cmp(h->SecureNATOption, &t, sizeof(VH_OPTION)) == 0 ? false : true;
+ Copy(h->SecureNATOption, &t, sizeof(VH_OPTION));
+
+ EnableSecureNAT(h, true);
+
+ if (changed)
+ {
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT != NULL)
+ {
+ SetVirtualHostOption(h->SecureNAT->Nat->Virtual, &t);
+ Debug("SiCalledUpdateHub: SecureNAT Updated.\n");
+ }
+ }
+ Unlock(h->lock_online);
+ }
+ }
+ else
+ {
+ EnableSecureNAT(h, false);
+ Debug("SiCalledUpdateHub: SecureNAT Disabled.\n");
+ }
+
+ if (type_changed)
+ {
+ // Remove all sessions since the type of HUB has been changed
+ if (h->Offline == false)
+ {
+ SetHubOffline(h);
+ SetHubOnline(h);
+ }
+ }
+
+ ReleaseHub(h);
+}
+
+// Inspect the ticket
+bool SiCheckTicket(HUB *h, UCHAR *ticket, char *username, UINT username_size, char *usernamereal, UINT usernamereal_size, POLICY *policy, char *sessionname, UINT sessionname_size, char *groupname, UINT groupname_size)
+{
+ bool ret = false;
+ // Validate arguments
+ if (h == NULL || ticket == NULL || username == NULL || usernamereal == NULL || policy == NULL || sessionname == NULL)
+ {
+ return false;
+ }
+
+ LockList(h->TicketList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(h->TicketList);i++)
+ {
+ TICKET *t = LIST_DATA(h->TicketList, i);
+ if (Cmp(t->Ticket, ticket, SHA1_SIZE) == 0)
+ {
+ ret = true;
+ StrCpy(username, username_size, t->Username);
+ StrCpy(usernamereal, usernamereal_size, t->UsernameReal);
+ StrCpy(sessionname, sessionname_size, t->SessionName);
+ StrCpy(groupname, groupname_size, t->GroupName);
+ Copy(policy, &t->Policy, sizeof(POLICY));
+ Delete(h->TicketList, t);
+ Free(t);
+ break;
+ }
+ }
+ }
+ UnlockList(h->TicketList);
+
+ return ret;
+}
+
+// Receive a MAC address deletion directive
+void SiCalledDeleteMacTable(SERVER *s, PACK *p)
+{
+ UINT key;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return;
+ }
+ key = PackGetInt(p, "Key");
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->MacTable);
+ {
+ if (IsInList(h->MacTable, (void *)key))
+ {
+ MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)key;
+ Delete(h->MacTable, e);
+ Free(e);
+ }
+ }
+ UnlockList(h->MacTable);
+
+ ReleaseHub(h);
+}
+
+// Receive an IP address delete directive
+void SiCalledDeleteIpTable(SERVER *s, PACK *p)
+{
+ UINT key;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return;
+ }
+ key = PackGetInt(p, "Key");
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h == NULL)
+ {
+ return;
+ }
+
+ LockList(h->IpTable);
+ {
+ if (IsInList(h->IpTable, (void *)key))
+ {
+ IP_TABLE_ENTRY *e = (IP_TABLE_ENTRY *)key;
+ Delete(h->IpTable, e);
+ Free(e);
+ }
+ }
+ UnlockList(h->IpTable);
+
+ ReleaseHub(h);
+}
+
+// Receive a session deletion directive
+void SiCalledDeleteSession(SERVER *s, PACK *p)
+{
+ char name[MAX_SESSION_NAME_LEN + 1];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ HUB *h;
+ SESSION *sess;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return;
+ }
+ if (PackGetStr(p, "SessionName", name, sizeof(name)) == false)
+ {
+ return;
+ }
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h == NULL)
+ {
+ return;
+ }
+
+ sess = GetSessionByName(h, name);
+
+ if (sess != NULL)
+ {
+ if (sess->BridgeMode == false && sess->LinkModeServer == false && sess->SecureNATMode == false)
+ {
+ StopSession(sess);
+ }
+ ReleaseSession(sess);
+ }
+
+ ReleaseHub(h);
+}
+
+// Receive a log file reading directive
+PACK *SiCalledReadLogFile(SERVER *s, PACK *p)
+{
+ RPC_READ_LOG_FILE t;
+ PACK *ret;
+ char filepath[MAX_PATH];
+ UINT offset;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ PackGetStr(p, "FilePath", filepath, sizeof(filepath));
+ offset = PackGetInt(p, "Offset");
+
+ Zero(&t, sizeof(t));
+
+ SiReadLocalLogFile(s, filepath, offset, &t);
+
+ ret = NewPack();
+
+ OutRpcReadLogFile(ret, &t);
+ FreeRpcReadLogFile(&t);
+
+ return ret;
+}
+
+// Receive a log file enumeration directive
+PACK *SiCalledEnumLogFileList(SERVER *s, PACK *p)
+{
+ RPC_ENUM_LOG_FILE t;
+ PACK *ret;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ PackGetStr(p, "HubName", hubname, sizeof(hubname));
+
+ Zero(&t, sizeof(t));
+
+ SiEnumLocalLogFileList(s, hubname, &t);
+
+ ret = NewPack();
+
+ OutRpcEnumLogFile(ret, &t);
+ FreeRpcEnumLogFile(&t);
+
+ return ret;
+}
+
+// Receive a session information directive
+PACK *SiCalledGetSessionStatus(SERVER *s, PACK *p)
+{
+ RPC_SESSION_STATUS t;
+ ADMIN a;
+ PACK *ret;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ InRpcSessionStatus(&t, p);
+
+ Zero(&a, sizeof(a));
+ a.Server = s;
+ a.ServerAdmin = true;
+
+ if (StGetSessionStatus(&a, &t) != ERR_NO_ERROR)
+ {
+ FreeRpcSessionStatus(&t);
+ return NULL;
+ }
+
+ ret = NewPack();
+
+ OutRpcSessionStatus(ret, &t);
+
+ FreeRpcSessionStatus(&t);
+
+ return ret;
+}
+
+// IP table enumeration directive
+PACK *SiCalledEnumIpTable(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_ENUM_IP_TABLE t;
+ PACK *ret;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ SiEnumIpTable(s, hubname, &t);
+
+ ret = NewPack();
+ OutRpcEnumIpTable(ret, &t);
+ FreeRpcEnumIpTable(&t);
+
+ return ret;
+}
+
+// MAC table enumeration directive
+PACK *SiCalledEnumMacTable(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_ENUM_MAC_TABLE t;
+ PACK *ret;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ SiEnumMacTable(s, hubname, &t);
+
+ ret = NewPack();
+ OutRpcEnumMacTable(ret, &t);
+ FreeRpcEnumMacTable(&t);
+
+ return ret;
+}
+
+// NAT status acquisition directive
+PACK *SiCalledGetNatStatus(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_NAT_STATUS t;
+ PACK *ret;
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h != NULL)
+ {
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT != NULL)
+ {
+ NtGetStatus(h->SecureNAT->Nat, &t);
+ }
+ }
+ Unlock(h->lock_online);
+ }
+
+ ReleaseHub(h);
+
+ ret = NewPack();
+ OutRpcNatStatus(ret, &t);
+ FreeRpcNatStatus(&t);
+
+ return ret;
+}
+
+// DHCP table enumeration directive
+PACK *SiCalledEnumDhcp(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_ENUM_DHCP t;
+ PACK *ret;
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h != NULL)
+ {
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT != NULL)
+ {
+ NtEnumDhcpList(h->SecureNAT->Nat, &t);
+ }
+ }
+ Unlock(h->lock_online);
+ }
+
+ ReleaseHub(h);
+
+ ret = NewPack();
+ OutRpcEnumDhcp(ret, &t);
+ FreeRpcEnumDhcp(&t);
+
+ return ret;
+}
+
+// NAT table enumeration directive
+PACK *SiCalledEnumNat(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_ENUM_NAT t;
+ PACK *ret;
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ LockHubList(s->Cedar);
+ {
+ h = GetHub(s->Cedar, hubname);
+ }
+ UnlockHubList(s->Cedar);
+
+ if (h != NULL)
+ {
+ Lock(h->lock_online);
+ {
+ if (h->SecureNAT != NULL)
+ {
+ NtEnumNatList(h->SecureNAT->Nat, &t);
+ }
+ }
+ Unlock(h->lock_online);
+ }
+
+ ReleaseHub(h);
+
+ ret = NewPack();
+ OutRpcEnumNat(ret, &t);
+ FreeRpcEnumNat(&t);
+
+ return ret;
+}
+
+// Receive a session enumeration directive
+PACK *SiCalledEnumSession(SERVER *s, PACK *p)
+{
+ char hubname[MAX_HUBNAME_LEN + 1];
+ RPC_ENUM_SESSION t;
+ PACK *ret;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+ if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
+ {
+ return NewPack();
+ }
+ Zero(&t, sizeof(t));
+
+ SiEnumLocalSession(s, hubname, &t);
+
+ ret = NewPack();
+ OutRpcEnumSession(ret, &t);
+ FreeRpcEnumSession(&t);
+
+ return ret;
+}
+
+// Receive a ticket creation directive
+PACK *SiCalledCreateTicket(SERVER *s, PACK *p)
+{
+ char username[MAX_SIZE];
+ char hubname[MAX_SIZE];
+ char groupname[MAX_SIZE];
+ char realusername[MAX_SIZE];
+ char sessionname[MAX_SESSION_NAME_LEN + 1];
+ POLICY policy;
+ UCHAR ticket[SHA1_SIZE];
+ char ticket_str[MAX_SIZE];
+ HUB *h;
+ UINT i;
+ PACK *ret;
+ TICKET *t;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return NewPack();
+ }
+
+ PackGetStr(p, "UserName", username, sizeof(username));
+ PackGetStr(p, "GroupName", groupname, sizeof(groupname));
+ PackGetStr(p, "HubName", hubname, sizeof(hubname));
+ PackGetStr(p, "RealUserName", realusername, sizeof(realusername));
+ PackGetStr(p, "SessionName", sessionname, sizeof(sessionname));
+
+ InRpcPolicy(&policy, p);
+ if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
+ {
+ PackGetData(p, "Ticket", ticket);
+ }
+
+ BinToStr(ticket_str, sizeof(ticket_str), ticket, SHA1_SIZE);
+
+ SLog(s->Cedar, "LS_TICKET_2", hubname, username, realusername, sessionname,
+ ticket_str, TICKET_EXPIRES / 1000);
+
+ // Get the HUB
+ h = GetHub(s->Cedar, hubname);
+ if (h == NULL)
+ {
+ return NewPack();
+ }
+
+ LockList(h->TicketList);
+ {
+ LIST *o = NewListFast(NULL);
+ // Discard old tickets
+ for (i = 0;i < LIST_NUM(h->TicketList);i++)
+ {
+ TICKET *t = LIST_DATA(h->TicketList, i);
+ if ((t->CreatedTick + TICKET_EXPIRES) < Tick64())
+ {
+ Add(o, t);
+ }
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TICKET *t = LIST_DATA(o, i);
+ Delete(h->TicketList, t);
+ Free(t);
+ }
+ ReleaseList(o);
+
+ // Create a ticket
+ t = ZeroMalloc(sizeof(TICKET));
+ t->CreatedTick = Tick64();
+ Copy(&t->Policy, &policy, sizeof(POLICY));
+ Copy(t->Ticket, ticket, SHA1_SIZE);
+ StrCpy(t->Username, sizeof(t->Username), username);
+ StrCpy(t->UsernameReal, sizeof(t->UsernameReal), realusername);
+ StrCpy(t->GroupName, sizeof(t->GroupName), groupname);
+ StrCpy(t->SessionName, sizeof(t->SessionName), sessionname);
+
+ Add(h->TicketList, t);
+ }
+ UnlockList(h->TicketList);
+
+ ReleaseHub(h);
+
+ ret = NewPack();
+
+ PackAddInt(ret, "Point", SiGetPoint(s));
+
+ return ret;
+}
+
+// Receive a HUB creation directive
+void SiCalledCreateHub(SERVER *s, PACK *p)
+{
+ char name[MAX_SIZE];
+ UINT type;
+ HUB_OPTION o;
+ HUB_LOG log;
+ bool save_packet_log;
+ UINT packet_log_switch_type;
+ UINT packet_log_config[NUM_PACKET_LOG];
+ bool save_security_log;
+ UINT security_log_switch_type;
+ UINT i;
+ HUB *h;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ PackGetStr(p, "HubName", name, sizeof(name));
+ type = PackGetInt(p, "HubType");
+ Zero(&o, sizeof(o));
+ o.MaxSession = PackGetInt(p, "MaxSession");
+ save_packet_log = PackGetInt(p, "SavePacketLog");
+ packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ packet_log_config[i] = PackGetIntEx(p, "PacketLogConfig", i);
+ }
+ save_security_log = PackGetInt(p, "SaveSecurityLog");
+ security_log_switch_type = PackGetInt(p, "SecurityLogSwitchType");
+
+ Zero(&log, sizeof(log));
+ log.SavePacketLog = save_packet_log;
+ log.PacketLogSwitchType = packet_log_switch_type;
+ Copy(log.PacketLogConfig, packet_log_config, sizeof(log.PacketLogConfig));
+ log.SaveSecurityLog = save_security_log;
+ log.SecurityLogSwitchType = security_log_switch_type;
+
+ h = NewHub(s->Cedar, name, &o);
+ h->LastCommTime = h->LastLoginTime = h->CreatedTime = 0;
+ SetHubLogSetting(h, &log);
+ h->Type = type;
+ h->FarmMember_MaxSessionClient = PackGetInt(p, "MaxSessionClient");
+ h->FarmMember_MaxSessionBridge = PackGetInt(p, "MaxSessionBridge");
+ h->FarmMember_MaxSessionClientBridgeApply = PackGetBool(p, "MaxSessionClientBridgeApply");
+
+ if (h->FarmMember_MaxSessionClientBridgeApply == false)
+ {
+ h->FarmMember_MaxSessionClient = INFINITE;
+ h->FarmMember_MaxSessionBridge = INFINITE;
+ }
+
+ PackGetData2(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
+ PackGetData2(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
+
+ for (i = 0;i < SiNumAccessFromPack(p);i++)
+ {
+ ACCESS *a = SiPackToAccess(p, i);
+ AddAccessList(h, a);
+ Free(a);
+ }
+
+ if (PackGetBool(p, "EnableSecureNAT"))
+ {
+ VH_OPTION t;
+
+ InVhOption(&t, p);
+
+ Copy(h->SecureNATOption, &t, sizeof(VH_OPTION));
+ EnableSecureNAT(h, true);
+
+ Debug("SiCalledCreateHub: SecureNAT Created.\n");
+ }
+
+ AddHub(s->Cedar, h);
+ h->Offline = true;
+ SetHubOnline(h);
+
+ ReleaseHub(h);
+}
+
+// Farm control thread
+void SiFarmControlThread(THREAD *thread, void *param)
+{
+ SERVER *s;
+ CEDAR *c;
+ EVENT *e;
+ LIST *o;
+ UINT i;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ s = (SERVER *)param;
+ c = s->Cedar;
+ e = s->FarmControlThreadHaltEvent;
+
+ while (true)
+ {
+ Lock(c->CedarSuperLock);
+
+ // Enumerate HUB list which is hosted by each farm member
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ LockList(s->FarmMemberList);
+ {
+ UINT i;
+ UINT num;
+ UINT assigned_client_license = 0;
+ UINT assigned_bridge_license = 0;
+ LIST *fm_list = NewListFast(NULL);
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ num = 0;
+
+ while (true)
+ {
+ bool escape = true;
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsInList(fm_list, f) == false)
+ {
+ SiCallEnumHub(s, f);
+ // Get the total number of sessions across the server farm
+ num += f->NumSessions;
+
+ assigned_client_license += f->AssignedClientLicense;
+ assigned_bridge_license += f->AssignedBridgeLicense;
+
+ escape = false;
+
+ Add(fm_list, f);
+ break;
+ }
+ }
+
+ if (escape)
+ {
+ break;
+ }
+
+ UnlockList(s->FarmMemberList);
+ LockList(s->FarmMemberList);
+ }
+
+ ReleaseList(fm_list);
+
+ s->CurrentTotalNumSessionsOnFarm = num;
+
+ // Update the number of assigned licenses
+ s->CurrentAssignedBridgeLicense = assigned_bridge_license;
+ s->CurrentAssignedClientLicense = assigned_client_license;
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+ }
+ UnlockList(s->FarmMemberList);
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ o = NewListFast(NULL);
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ // Emit an update notification for each HUB
+ LockList(c->HubList);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ AddRef(h->ref);
+ Add(o, h);
+ }
+ }
+ UnlockList(c->HubList);
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HUB *h = LIST_DATA(o, i);
+ SiHubUpdateProc(h);
+ ReleaseHub(h);
+ }
+
+ Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
+ SiDebugLog(s, tmp);
+
+ ReleaseList(o);
+
+ Unlock(c->CedarSuperLock);
+
+ Wait(e, SERVER_FARM_CONTROL_INTERVAL);
+ if (s->Halt)
+ {
+ break;
+ }
+ }
+}
+
+// Start the farm controling
+void SiStartFarmControl(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return;
+ }
+
+ s->FarmControlThreadHaltEvent = NewEvent();
+ s->FarmControlThread = NewThread(SiFarmControlThread, s);
+}
+
+// Stop the farm controling
+void SiStopFarmControl(SERVER *s)
+{
+ // Validate arguments
+ if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return;
+ }
+
+ Set(s->FarmControlThreadHaltEvent);
+ WaitThread(s->FarmControlThread, INFINITE);
+ ReleaseEvent(s->FarmControlThreadHaltEvent);
+ ReleaseThread(s->FarmControlThread);
+}
+
+// HUB enumeration directive (asynchronous start)
+void SiCallEnumHubBegin(SERVER *s, FARM_MEMBER *f)
+{
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+}
+
+// HUB enumeration directive (asynchronous end)
+void SiCallEnumHubEnd(SERVER *s, FARM_MEMBER *f)
+{
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+}
+
+
+// HUB enumeration directive
+void SiCallEnumHub(SERVER *s, FARM_MEMBER *f)
+{
+ CEDAR *c;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ c = s->Cedar;
+
+ if (f->Me)
+ {
+
+ // Enumerate local HUBs
+ LockList(f->HubList);
+ {
+ // For a local HUB, re-enumerate by erasing all STATIC HUB list once first
+ UINT i;
+ LIST *o = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *h = LIST_DATA(f->HubList, i);
+ if (h->DynamicHub == false)
+ {
+ Add(o, h);
+ }
+ }
+
+ // Clear all the STATIC HUB
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HUB_LIST *h = LIST_DATA(o, i);
+ Free(h);
+ Delete(f->HubList, h);
+ }
+ ReleaseList(o);
+
+ // Second, stop DYNAMIC HUBs without user
+ o = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *h = LIST_DATA(f->HubList, i);
+ if (h->DynamicHub == true)
+ {
+ LockList(c->HubList);
+ {
+ HUB *hub = GetHub(s->Cedar, h->Name);
+ if (hub != NULL)
+ {
+ if (Count(hub->NumSessions) == 0 || hub->Type != HUB_TYPE_FARM_DYNAMIC)
+ {
+ Add(o, h);
+ }
+ ReleaseHub(hub);
+ }
+ }
+ UnlockList(c->HubList);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HUB_LIST *h = LIST_DATA(o, i);
+ Debug("Delete HUB: %s\n", h->Name);
+ Free(h);
+ Delete(f->HubList, h);
+ }
+
+ ReleaseList(o);
+
+ // Set the enumeration results
+ LockList(c->HubList);
+ {
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ if (h->Offline == false)
+ {
+ if (h->Type == HUB_TYPE_FARM_STATIC)
+ {
+ HUB_LIST *hh = ZeroMalloc(sizeof(HUB_LIST));
+ hh->FarmMember = f;
+ hh->DynamicHub = false;
+ StrCpy(hh->Name, sizeof(hh->Name), h->Name);
+ Add(f->HubList, hh);
+
+ LockList(h->SessionList);
+ {
+ hh->NumSessions = LIST_NUM(h->SessionList);
+ hh->NumSessionsBridge = Count(h->NumSessionsBridge);
+ hh->NumSessionsClient = Count(h->NumSessionsClient);
+ }
+ UnlockList(h->SessionList);
+
+ LockList(h->MacTable);
+ {
+ hh->NumMacTables = LIST_NUM(h->MacTable);
+ }
+ UnlockList(h->MacTable);
+
+ LockList(h->IpTable);
+ {
+ hh->NumIpTables = LIST_NUM(h->IpTable);
+ }
+ UnlockList(h->IpTable);
+ }
+ }
+ }
+ }
+ UnlockList(c->HubList);
+ }
+ UnlockList(f->HubList);
+
+ // Point
+ f->Point = SiGetPoint(s);
+ f->NumSessions = Count(s->Cedar->CurrentSessions);
+ f->MaxSessions = GetServerCapsInt(s, "i_max_sessions");
+ f->NumTcpConnections = Count(s->Cedar->CurrentTcpConnections);
+
+ Lock(s->Cedar->TrafficLock);
+ {
+ Copy(&f->Traffic, s->Cedar->Traffic, sizeof(TRAFFIC));
+ }
+ Unlock(s->Cedar->TrafficLock);
+
+ f->AssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
+ f->AssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
+
+ Copy(f->RandomKey, s->MyRandomKey, SHA1_SIZE);
+
+
+ Debug("Server %s: Point %u\n", f->hostname, f->Point);
+ }
+ else
+ {
+ // Enumerate HUBs which are remote member
+ PACK *p = NewPack();
+ UINT i, num, j;
+ LIST *o = NewListFast(NULL);
+
+ num = 0;
+
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsZero(f->RandomKey, SHA1_SIZE) == false && f->SystemId != 0)
+ {
+ num++;
+ }
+ }
+
+ j = 0;
+
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsZero(f->RandomKey, SHA1_SIZE) == false && f->SystemId != 0)
+ {
+ PackAddDataEx(p, "MemberRandomKey", f->RandomKey, SHA1_SIZE, j, num);
+ PackAddInt64Ex(p, "MemberSystemId", f->SystemId, j, num);
+ j++;
+ }
+ }
+ PackAddInt(p, "MemberSystemIdNum", num);
+
+ p = SiCallTask(f, p, "enumhub");
+ if (p != NULL)
+ {
+ LockList(f->HubList);
+ {
+ UINT i;
+ // Erase the list
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *hh = LIST_DATA(f->HubList, i);
+ Free(hh);
+ }
+ DeleteAll(f->HubList);
+
+ for (i = 0;i < PackGetIndexCount(p, "HubName");i++)
+ {
+ HUB_LIST *hh = ZeroMalloc(sizeof(HUB_LIST));
+ UINT num;
+ UINT64 LastCommTime;
+
+ PackGetStrEx(p, "HubName", hh->Name, sizeof(hh->Name), i);
+ num = PackGetIntEx(p, "NumSession", i);
+ hh->DynamicHub = ((PackGetIntEx(p, "HubType", i) == HUB_TYPE_FARM_DYNAMIC) ? true : false);
+ hh->FarmMember = f;
+ hh->NumSessions = PackGetIntEx(p, "NumSessions", i);
+ hh->NumSessionsClient = PackGetIntEx(p, "NumSessionsClient", i);
+ hh->NumSessionsBridge = PackGetIntEx(p, "NumSessionsBridge", i);
+ hh->NumIpTables = PackGetIntEx(p, "NumIpTables", i);
+ hh->NumMacTables = PackGetIntEx(p, "NumMacTables", i);
+ LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);
+ Add(f->HubList, hh);
+ //Debug("%s\n", hh->Name);
+
+ LockList(c->HubList);
+ {
+ HUB *h = GetHub(c, hh->Name);
+
+ if (h != NULL)
+ {
+ // Update the LastCommTime of the Virtual HUB
+ Lock(h->lock);
+ {
+ if (h->LastCommTime < LastCommTime)
+ {
+ h->LastCommTime = LastCommTime;
+ }
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+ }
+ }
+ UnlockList(c->HubList);
+
+ if (hh->DynamicHub && num >= 1)
+ {
+ // It is not necessary to be registered in the virtual HUB creation
+ // history list because user session is already connected.
+ // Remove from the Virtual HUB creation history list
+ SiDelHubCreateHistory(s, hh->Name);
+ }
+
+ if (hh->DynamicHub && num == 0)
+ {
+ // Check the Virtual HUB creation history list.
+ // If it is created within 60 seconds of the most recent
+ // in the case of Virtual HUB which the first user is not
+ // connected yet, not to remove because there is no user
+ if (SiIsHubRegistedOnCreateHistory(s, hh->Name) == false)
+ {
+ // Stop because all uses have gone in the dynamic HUB
+ HUB *h;
+ LockList(c->HubList);
+ {
+ h = GetHub(c, hh->Name);
+ }
+ UnlockList(c->HubList);
+
+ if (h != NULL)
+ {
+ Add(o, h);
+ }
+ }
+ }
+ }
+ }
+ UnlockList(f->HubList);
+ f->Point = PackGetInt(p, "Point");
+ Debug("Server %s: Point %u\n", f->hostname, f->Point);
+ f->NumSessions = PackGetInt(p, "NumTotalSessions");
+ if (f->NumSessions == 0)
+ {
+ f->NumSessions = PackGetInt(p, "NumSessions");
+ }
+ f->MaxSessions = PackGetInt(p, "MaxSessions");
+ f->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
+ InRpcTraffic(&f->Traffic, p);
+
+ f->AssignedBridgeLicense = PackGetInt(p, "AssignedBridgeLicense");
+ f->AssignedClientLicense = PackGetInt(p, "AssignedClientLicense");
+
+ if (PackGetDataSize(p, "RandomKey") == SHA1_SIZE)
+ {
+ PackGetData(p, "RandomKey", f->RandomKey);
+ }
+
+ f->SystemId = PackGetInt64(p, "SystemId");
+
+ // Apply the traffic difference information
+ num = PackGetIndexCount(p, "TdType");
+ for (i = 0;i < num;i++)
+ {
+ TRAFFIC traffic;
+ UINT type;
+ HUB *h;
+ char name[MAX_SIZE];
+ char hubname[MAX_SIZE];
+
+ type = PackGetIntEx(p, "TdType", i);
+ PackGetStrEx(p, "TdName", name, sizeof(name), i);
+ PackGetStrEx(p, "TdHubName", hubname, sizeof(hubname), i);
+ InRpcTrafficEx(&traffic, p, i);
+
+ LockList(c->HubList);
+ {
+ h = GetHub(c, hubname);
+ if (h != NULL)
+ {
+ if (type == TRAFFIC_DIFF_HUB)
+ {
+ Lock(h->TrafficLock);
+ {
+ AddTraffic(h->Traffic, &traffic);
+ }
+ Unlock(h->TrafficLock);
+ }
+ else
+ {
+ AcLock(h);
+ {
+ USER *u = AcGetUser(h, name);
+ if (u != NULL)
+ {
+ Lock(u->lock);
+ {
+ AddTraffic(u->Traffic, &traffic);
+ }
+ Unlock(u->lock);
+ if (u->Group != NULL)
+ {
+ Lock(u->Group->lock);
+ {
+ AddTraffic(u->Group->Traffic, &traffic);
+ }
+ Unlock(u->Group->lock);
+ }
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(h);
+ }
+ ReleaseHub(h);
+ }
+ UnlockList(c->HubList);
+ }
+ }
+
+ FreePack(p);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HUB *h = LIST_DATA(o, i);
+ SiCallDeleteHub(s, f, h);
+ Debug("Delete HUB: %s\n", h->Name);
+ ReleaseHub(h);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Send a session information directive
+bool SiCallGetSessionStatus(SERVER *s, FARM_MEMBER *f, RPC_SESSION_STATUS *t)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+ OutRpcSessionStatus(p, t);
+ FreeRpcSessionStatus(t);
+ Zero(t, sizeof(RPC_SESSION_STATUS));
+
+ p = SiCallTask(f, p, "getsessionstatus");
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ InRpcSessionStatus(t, p);
+ FreePack(p);
+
+ return true;
+}
+
+// Log file reading directive
+bool SiCallReadLogFile(SERVER *s, FARM_MEMBER *f, RPC_READ_LOG_FILE *t)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+ OutRpcReadLogFile(p, t);
+ FreeRpcReadLogFile(t);
+ Zero(t, sizeof(RPC_READ_LOG_FILE));
+
+ p = SiCallTask(f, p, "readlogfile");
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ InRpcReadLogFile(t, p);
+ FreePack(p);
+
+ return true;
+}
+
+// Log file enumeration directive
+bool SiCallEnumLogFileList(SERVER *s, FARM_MEMBER *f, RPC_ENUM_LOG_FILE *t, char *hubname)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return false;
+ }
+
+ p = NewPack();
+ OutRpcEnumLogFile(p, t);
+ FreeRpcEnumLogFile(t);
+ Zero(t, sizeof(RPC_ENUM_LOG_FILE));
+
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enumlogfilelist");
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ InRpcEnumLogFile(t, p);
+ FreePack(p);
+
+ return true;
+}
+
+// HUB delete directive
+void SiCallDeleteHub(SERVER *s, FARM_MEMBER *f, HUB *h)
+{
+ PACK *p;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ if (f->Me == false)
+ {
+ p = NewPack();
+
+ PackAddStr(p, "HubName", h->Name);
+
+ p = SiCallTask(f, p, "deletehub");
+ FreePack(p);
+ }
+
+ LockList(f->HubList);
+ {
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *hh = LIST_DATA(f->HubList, i);
+ if (StrCmpi(hh->Name, h->Name) == 0)
+ {
+ Free(hh);
+ Delete(f->HubList, hh);
+ }
+ }
+ }
+ UnlockList(f->HubList);
+}
+
+// Submit a HUB update directive
+void SiCallUpdateHub(SERVER *s, FARM_MEMBER *f, HUB *h)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ if (f->Me == false)
+ {
+ p = NewPack();
+
+ SiPackAddCreateHub(p, h);
+
+ p = SiCallTask(f, p, "updatehub");
+ FreePack(p);
+ }
+}
+
+// Send a ticket creation directive
+void SiCallCreateTicket(SERVER *s, FARM_MEMBER *f, char *hubname, char *username, char *realusername, POLICY *policy, UCHAR *ticket, UINT counter, char *groupname)
+{
+ PACK *p;
+ char name[MAX_SESSION_NAME_LEN + 1];
+ char hub_name_upper[MAX_SIZE];
+ char user_name_upper[MAX_USERNAME_LEN + 1];
+ char ticket_str[MAX_SIZE];
+ UINT point;
+ // Validate arguments
+ if (s == NULL || f == NULL || realusername == NULL || hubname == NULL || username == NULL || policy == NULL || ticket == NULL)
+ {
+ return;
+ }
+ if (groupname == NULL)
+ {
+ groupname = "";
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+ PackAddStr(p, "UserName", username);
+ PackAddStr(p, "groupname", groupname);
+ PackAddStr(p, "RealUserName", realusername);
+ OutRpcPolicy(p, policy);
+ PackAddData(p, "Ticket", ticket, SHA1_SIZE);
+
+ BinToStr(ticket_str, sizeof(ticket_str), ticket, SHA1_SIZE);
+
+ StrCpy(hub_name_upper, sizeof(hub_name_upper), hubname);
+ StrUpper(hub_name_upper);
+ StrCpy(user_name_upper, sizeof(user_name_upper), username);
+ StrUpper(user_name_upper);
+ Format(name, sizeof(name), "SID-%s-%u", user_name_upper,
+ counter);
+ PackAddStr(p, "SessionName", name);
+
+ p = SiCallTask(f, p, "createticket");
+
+ SLog(s->Cedar, "LS_TICKET_1", f->hostname, hubname, username, realusername, name, ticket_str);
+
+ point = PackGetInt(p, "Point");
+ if (point != 0)
+ {
+ f->Point = point;
+ f->NumSessions++;
+ }
+
+ FreePack(p);
+}
+
+// Send a MAC address deletion directive
+void SiCallDeleteMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+ PackAddInt(p, "Key", key);
+
+ p = SiCallTask(f, p, "deletemactable");
+
+ FreePack(p);
+}
+
+// Send an IP address delete directive
+void SiCallDeleteIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+ PackAddInt(p, "Key", key);
+
+ p = SiCallTask(f, p, "deleteiptable");
+
+ FreePack(p);
+}
+
+// Send a session deletion directive
+void SiCallDeleteSession(SERVER *s, FARM_MEMBER *f, char *hubname, char *session_name)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || session_name == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+ PackAddStr(p, "SessionName", session_name);
+
+ p = SiCallTask(f, p, "deletesession");
+
+ FreePack(p);
+}
+
+// Send an IP table enumeration directive
+void SiCallEnumIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_IP_TABLE *t)
+{
+ PACK *p;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enumiptable");
+
+ Zero(t, sizeof(RPC_ENUM_IP_TABLE));
+ InRpcEnumIpTable(t, p);
+
+ for (i = 0;i < t->NumIpTable;i++)
+ {
+ t->IpTables[i].RemoteItem = true;
+ StrCpy(t->IpTables[i].RemoteHostname, sizeof(t->IpTables[i].RemoteHostname),
+ f->hostname);
+ }
+
+ FreePack(p);
+}
+
+// Submit a MAC table enumeration directive
+void SiCallEnumMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_MAC_TABLE *t)
+{
+ PACK *p;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enummactable");
+
+ Zero(t, sizeof(RPC_ENUM_MAC_TABLE));
+ InRpcEnumMacTable(t, p);
+
+ for (i = 0;i < t->NumMacTable;i++)
+ {
+ t->MacTables[i].RemoteItem = true;
+ StrCpy(t->MacTables[i].RemoteHostname, sizeof(t->MacTables[i].RemoteHostname),
+ f->hostname);
+ }
+
+ FreePack(p);
+}
+
+// Send a SecureNAT status acquisition directive
+void SiCallGetNatStatus(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_NAT_STATUS *t)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "getnatstatus");
+
+ Zero(t, sizeof(RPC_NAT_STATUS));
+ InRpcNatStatus(t, p);
+
+ FreePack(p);
+}
+
+// Submit a DHCP entry enumeration directive
+void SiCallEnumDhcp(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_DHCP *t)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enumdhcp");
+
+ Zero(t, sizeof(RPC_ENUM_DHCP));
+ InRpcEnumDhcp(t, p);
+
+ FreePack(p);
+}
+
+// Submit a NAT entry enumeration directive
+void SiCallEnumNat(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_NAT *t)
+{
+ PACK *p;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enumnat");
+
+ Zero(t, sizeof(RPC_ENUM_NAT));
+ InRpcEnumNat(t, p);
+
+ FreePack(p);
+}
+
+// Send a session enumeration directive
+void SiCallEnumSession(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_SESSION *t)
+{
+ PACK *p;
+ UINT i;
+ // Validate arguments
+ if (s == NULL || f == NULL || hubname == NULL || t == NULL)
+ {
+ return;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "HubName", hubname);
+
+ p = SiCallTask(f, p, "enumsession");
+
+ Zero(t, sizeof(RPC_ENUM_SESSION));
+ InRpcEnumSession(t, p);
+
+ for (i = 0;i < t->NumSession;i++)
+ {
+ t->Sessions[i].RemoteSession = true;
+ StrCpy(t->Sessions[i].RemoteHostname, sizeof(t->Sessions[i].RemoteHostname),
+ f->hostname);
+ }
+
+ FreePack(p);
+}
+
+// Send a HUB creation directive
+void SiCallCreateHub(SERVER *s, FARM_MEMBER *f, HUB *h)
+{
+ PACK *p;
+ HUB_LIST *hh;
+ // Validate arguments
+ if (s == NULL || f == NULL)
+ {
+ return;
+ }
+
+ if (f->Me == false)
+ {
+ p = NewPack();
+
+ SiPackAddCreateHub(p, h);
+
+ p = SiCallTask(f, p, "createhub");
+ FreePack(p);
+ }
+
+ hh = ZeroMalloc(sizeof(HUB_LIST));
+ hh->DynamicHub = (h->Type == HUB_TYPE_FARM_DYNAMIC ? true : false);
+ StrCpy(hh->Name, sizeof(hh->Name), h->Name);
+ hh->FarmMember = f;
+
+ LockList(f->HubList);
+ {
+ bool exists = false;
+ UINT i;
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *t = LIST_DATA(f->HubList, i);
+ if (StrCmpi(t->Name, hh->Name) == 0)
+ {
+ exists = true;
+ }
+ }
+ if (exists == false)
+ {
+ Add(f->HubList, hh);
+ }
+ else
+ {
+ Free(hh);
+ }
+ }
+ UnlockList(f->HubList);
+}
+
+// Write the PACK for creating HUB
+void SiPackAddCreateHub(PACK *p, HUB *h)
+{
+ UINT i;
+ UINT max_session;
+ SERVER *s;
+
+
+ // Validate arguments
+ if (p == NULL || h == NULL)
+ {
+ return;
+ }
+
+
+ s = h->Cedar->Server;
+ if (s != NULL)
+ {
+ }
+
+ PackAddStr(p, "HubName", h->Name);
+ PackAddInt(p, "HubType", h->Type);
+
+ max_session = h->Option->MaxSession;
+
+ if (GetHubAdminOption(h, "max_sessions") != 0)
+ {
+ if (max_session == 0)
+ {
+ max_session = GetHubAdminOption(h, "max_sessions");
+ }
+ else
+ {
+ UINT r = GetHubAdminOption(h, "max_sessions");
+ max_session = MIN(max_session, r);
+ }
+ }
+
+ PackAddInt(p, "MaxSession", max_session);
+
+ if (GetHubAdminOption(h, "max_sessions_client_bridge_apply") != 0
+ )
+ {
+ PackAddInt(p, "MaxSessionClient", GetHubAdminOption(h, "max_sessions_client"));
+ PackAddInt(p, "MaxSessionBridge", GetHubAdminOption(h, "max_sessions_bridge"));
+ PackAddBool(p, "MaxSessionClientBridgeApply", true);
+ }
+ else
+ {
+ PackAddInt(p, "MaxSessionClient", INFINITE);
+ PackAddInt(p, "MaxSessionBridge", INFINITE);
+ }
+
+ PackAddBool(p, "NoArpPolling", h->Option->NoArpPolling);
+ PackAddBool(p, "NoIPv6AddrPolling", h->Option->NoIPv6AddrPolling);
+ PackAddBool(p, "NoIpTable", h->Option->NoIpTable);
+ PackAddBool(p, "NoEnum", h->Option->NoEnum);
+ PackAddBool(p, "FilterPPPoE", h->Option->FilterPPPoE);
+ PackAddBool(p, "YieldAfterStorePacket", h->Option->YieldAfterStorePacket);
+ PackAddBool(p, "NoSpinLockForPacketDelay", h->Option->NoSpinLockForPacketDelay);
+ PackAddInt(p, "BroadcastStormDetectionThreshold", h->Option->BroadcastStormDetectionThreshold);
+ PackAddInt(p, "MaxLoggedPacketsPerMinute", h->Option->MaxLoggedPacketsPerMinute);
+ PackAddBool(p, "DoNotSaveHeavySecurityLogs", h->Option->DoNotSaveHeavySecurityLogs);
+ PackAddInt(p, "ClientMinimumRequiredBuild", h->Option->ClientMinimumRequiredBuild);
+ PackAddBool(p, "FixForDLinkBPDU", h->Option->FixForDLinkBPDU);
+ PackAddBool(p, "BroadcastLimiterStrictMode", h->Option->BroadcastLimiterStrictMode);
+ PackAddBool(p, "NoLookBPDUBridgeId", h->Option->NoLookBPDUBridgeId);
+ PackAddBool(p, "NoManageVlanId", h->Option->NoManageVlanId);
+ PackAddInt(p, "VlanTypeId", h->Option->VlanTypeId);
+ PackAddBool(p, "FilterOSPF", h->Option->FilterOSPF);
+ PackAddBool(p, "FilterIPv4", h->Option->FilterIPv4);
+ PackAddBool(p, "FilterIPv6", h->Option->FilterIPv6);
+ PackAddBool(p, "FilterNonIP", h->Option->FilterNonIP);
+ PackAddBool(p, "NoIPv4PacketLog", h->Option->NoIPv4PacketLog);
+ PackAddBool(p, "NoIPv6PacketLog", h->Option->NoIPv6PacketLog);
+ PackAddBool(p, "FilterBPDU", h->Option->FilterBPDU);
+ PackAddBool(p, "NoIPv6DefaultRouterInRAWhenIPv6", h->Option->NoIPv6DefaultRouterInRAWhenIPv6);
+ PackAddBool(p, "NoMacAddressLog", h->Option->NoMacAddressLog);
+ PackAddBool(p, "ManageOnlyPrivateIP", h->Option->ManageOnlyPrivateIP);
+ PackAddBool(p, "ManageOnlyLocalUnicastIPv6", h->Option->ManageOnlyLocalUnicastIPv6);
+ PackAddBool(p, "DisableIPParsing", h->Option->DisableIPParsing);
+ PackAddInt(p, "AdjustTcpMssValue", h->Option->AdjustTcpMssValue);
+ PackAddBool(p, "DisableAdjustTcpMss", h->Option->DisableAdjustTcpMss);
+ PackAddBool(p, "NoDhcpPacketLogOutsideHub", h->Option->NoDhcpPacketLogOutsideHub);
+ PackAddBool(p, "DisableHttpParsing", h->Option->DisableHttpParsing);
+ PackAddBool(p, "DisableUdpAcceleration", h->Option->DisableUdpAcceleration);
+ PackAddBool(p, "DisableUdpFilterForLocalBridgeNic", h->Option->DisableUdpFilterForLocalBridgeNic);
+ PackAddBool(p, "ApplyIPv4AccessListOnArpPacket", h->Option->ApplyIPv4AccessListOnArpPacket);
+ PackAddBool(p, "RemoveDefGwOnDhcpForLocalhost", h->Option->RemoveDefGwOnDhcpForLocalhost);
+
+ PackAddInt(p, "SecureNAT_MaxTcpSessionsPerIp", h->Option->SecureNAT_MaxTcpSessionsPerIp);
+ PackAddInt(p, "SecureNAT_MaxTcpSynSentPerIp", h->Option->SecureNAT_MaxTcpSynSentPerIp);
+ PackAddInt(p, "SecureNAT_MaxUdpSessionsPerIp", h->Option->SecureNAT_MaxUdpSessionsPerIp);
+ PackAddInt(p, "SecureNAT_MaxDnsSessionsPerIp", h->Option->SecureNAT_MaxDnsSessionsPerIp);
+ PackAddInt(p, "SecureNAT_MaxIcmpSessionsPerIp", h->Option->SecureNAT_MaxIcmpSessionsPerIp);
+ PackAddInt(p, "AccessListIncludeFileCacheLifetime", h->Option->AccessListIncludeFileCacheLifetime);
+ PackAddBool(p, "DisableKernelModeSecureNAT", h->Option->DisableKernelModeSecureNAT);
+ PackAddBool(p, "DisableUserModeSecureNAT", h->Option->DisableUserModeSecureNAT);
+ PackAddBool(p, "DisableCheckMacOnLocalBridge", h->Option->DisableCheckMacOnLocalBridge);
+ PackAddBool(p, "DisableCorrectIpOffloadChecksum", h->Option->DisableCorrectIpOffloadChecksum);
+
+ PackAddInt(p, "SavePacketLog", h->LogSetting.SavePacketLog);
+ PackAddInt(p, "PacketLogSwitchType", h->LogSetting.PacketLogSwitchType);
+ for (i = 0;i < NUM_PACKET_LOG;i++)
+ {
+ PackAddIntEx(p, "PacketLogConfig", h->LogSetting.PacketLogConfig[i], i, NUM_PACKET_LOG);
+ }
+ PackAddInt(p, "SaveSecurityLog", h->LogSetting.SaveSecurityLog);
+ PackAddInt(p, "SecurityLogSwitchType", h->LogSetting.SecurityLogSwitchType);
+ PackAddData(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
+ PackAddData(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
+
+ SiAccessListToPack(p, h->AccessList);
+
+ if (h->EnableSecureNAT)
+ {
+ PackAddBool(p, "EnableSecureNAT", h->EnableSecureNAT);
+ OutVhOption(p, h->SecureNATOption);
+ }
+}
+
+// Setting of the HUB has been updated
+void SiHubUpdateProc(HUB *h)
+{
+ SERVER *s;
+ UINT i;
+ // Validate arguments
+ if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ return;
+ }
+
+ s = h->Cedar->Server;
+
+ if (s->FarmMemberList == NULL)
+ {
+ return;
+ }
+
+ if (h->LastVersion != h->CurrentVersion || h->CurrentVersion == 0)
+ {
+ LIST *fm_list;
+ if (h->CurrentVersion == 0)
+ {
+ h->CurrentVersion = 1;
+ }
+ h->LastVersion = h->CurrentVersion;
+
+ Debug("SiHubUpdateProc HUB=%s, Ver=%u, Type=%u, Offline=%u\n", h->Name, h->CurrentVersion,
+ h->Type, h->Offline);
+
+ fm_list = NewListFast(NULL);
+
+ LockList(s->FarmMemberList);
+ {
+ while (true)
+ {
+ bool escape = true;
+ // Update the HUB on all members
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsInList(fm_list, f) == false)
+ {
+ Add(fm_list, f);
+ escape = false;
+
+ if (f->Me == false)
+ {
+ SiCallUpdateHub(s, f, h);
+ }
+
+ break;
+ }
+ }
+
+ if (escape)
+ {
+ break;
+ }
+
+ UnlockList(s->FarmMemberList);
+ LockList(s->FarmMemberList);
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ ReleaseList(fm_list);
+ }
+
+ if (h->Offline == false)
+ {
+ SiHubOnlineProc(h);
+ }
+}
+
+// HUB turns to online
+void SiHubOnlineProc(HUB *h)
+{
+ SERVER *s;
+ UINT i;
+ // Validate arguments
+ if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Process only on the farm controller
+ return;
+ }
+
+ s = h->Cedar->Server;
+
+ if (s->FarmMemberList == NULL)
+ {
+ return;
+ }
+
+ LockList(s->FarmMemberList);
+ {
+ if (h->Type == HUB_TYPE_FARM_STATIC)
+ {
+ // Static HUB
+ // Create the HUB on all members
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ UINT j;
+ bool exists = false;
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ LockList(f->HubList);
+ {
+ for (j = 0;j < LIST_NUM(f->HubList);j++)
+ {
+ HUB_LIST *hh = LIST_DATA(f->HubList, j);
+ if (StrCmpi(hh->Name, h->Name) == 0)
+ {
+ exists = true;
+ }
+ }
+ }
+ UnlockList(f->HubList);
+
+ if (exists == false)
+ {
+ SiCallCreateHub(s, f, h);
+ }
+ }
+ }
+ }
+ UnlockList(s->FarmMemberList);
+}
+
+// HUB turns to offline
+void SiHubOfflineProc(HUB *h)
+{
+ SERVER *s;
+ char hubname[MAX_HUBNAME_LEN + 1];
+ UINT i;
+ LIST *fm_list;
+ // Validate arguments
+ if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
+ {
+ // Process only on the farm controller
+ return;
+ }
+
+ s = h->Cedar->Server;
+
+ if (s->FarmMemberList == NULL)
+ {
+ return;
+ }
+
+ StrCpy(hubname, sizeof(hubname), h->Name);
+
+ fm_list = NewListFast(NULL);
+
+ LockList(s->FarmMemberList);
+ {
+ while (true)
+ {
+ bool escape = true;
+
+ // Stop the HUB on all members
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+
+ if (IsInList(fm_list, f) == false)
+ {
+ Add(fm_list, f);
+ escape = false;
+
+ SiCallDeleteHub(s, f, h);
+
+ break;
+ }
+ }
+
+ if (escape)
+ {
+ break;
+ }
+
+ UnlockList(s->FarmMemberList);
+ LockList(s->FarmMemberList);
+ }
+ }
+ UnlockList(s->FarmMemberList);
+
+ ReleaseList(fm_list);
+}
+
+// Convert an access to PACK
+void SiAccessToPack(PACK *p, ACCESS *a, UINT i, UINT total)
+{
+ // Validate arguments
+ if (p == NULL || a == NULL)
+ {
+ return;
+ }
+
+ PackAddUniStrEx(p, "Note", a->Note, i, total);
+ PackAddIntEx(p, "Active", a->Active, i, total);
+ PackAddIntEx(p, "Priority", a->Priority, i, total);
+ PackAddIntEx(p, "Discard", a->Discard, i, total);
+ if (a->IsIPv6)
+ {
+ PackAddIp32Ex(p, "SrcIpAddress", 0xFDFFFFDF, i, total);
+ PackAddIp32Ex(p, "SrcSubnetMask", 0xFFFFFFFF, i, total);
+ PackAddIp32Ex(p, "DestIpAddress", 0xFDFFFFDF, i, total);
+ PackAddIp32Ex(p, "DestSubnetMask", 0xFFFFFFFF, i, total);
+ }
+ else
+ {
+ PackAddIp32Ex(p, "SrcIpAddress", a->SrcIpAddress, i, total);
+ PackAddIp32Ex(p, "SrcSubnetMask", a->SrcSubnetMask, i, total);
+ PackAddIp32Ex(p, "DestIpAddress", a->DestIpAddress, i, total);
+ PackAddIp32Ex(p, "DestSubnetMask", a->DestSubnetMask, i, total);
+ }
+ PackAddIntEx(p, "Protocol", a->Protocol, i, total);
+ PackAddIntEx(p, "SrcPortStart", a->SrcPortStart, i, total);
+ PackAddIntEx(p, "SrcPortEnd", a->SrcPortEnd, i, total);
+ PackAddIntEx(p, "DestPortStart", a->DestPortStart, i, total);
+ PackAddIntEx(p, "DestPortEnd", a->DestPortEnd, i, total);
+ PackAddStrEx(p, "SrcUsername", a->SrcUsername, i, total);
+ PackAddStrEx(p, "DestUsername", a->DestUsername, i, total);
+ PackAddBoolEx(p, "CheckSrcMac", a->CheckSrcMac, i, total);
+ PackAddDataEx(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), i, total);
+ PackAddDataEx(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), i, total);
+ PackAddBoolEx(p, "CheckDstMac", a->CheckDstMac, i, total);
+ PackAddDataEx(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), i, total);
+ PackAddDataEx(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), i, total);
+ PackAddBoolEx(p, "CheckTcpState", a->CheckTcpState, i, total);
+ PackAddBoolEx(p, "Established", a->Established, i, total);
+ PackAddIntEx(p, "Delay", a->Delay, i, total);
+ PackAddIntEx(p, "Jitter", a->Jitter, i, total);
+ PackAddIntEx(p, "Loss", a->Loss, i, total);
+ PackAddStrEx(p, "RedirectUrl", a->RedirectUrl, i, total);
+ PackAddBoolEx(p, "IsIPv6", a->IsIPv6, i, total);
+ if (a->IsIPv6)
+ {
+ PackAddIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, i, total);
+ PackAddIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, i, total);
+ PackAddIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, i, total);
+ PackAddIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, i, total);
+ }
+ else
+ {
+ IPV6_ADDR zero;
+
+ Zero(&zero, sizeof(zero));
+
+ PackAddIp6AddrEx(p, "SrcIpAddress6", &zero, i, total);
+ PackAddIp6AddrEx(p, "SrcSubnetMask6", &zero, i, total);
+ PackAddIp6AddrEx(p, "DestIpAddress6", &zero, i, total);
+ PackAddIp6AddrEx(p, "DestSubnetMask6", &zero, i, total);
+ }
+}
+
+// Get number of access contained in the PACK
+UINT SiNumAccessFromPack(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetIndexCount(p, "Active");
+}
+
+// Convert the PACK to access
+ACCESS *SiPackToAccess(PACK *p, UINT i)
+{
+ ACCESS *a;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(ACCESS));
+
+ PackGetUniStrEx(p, "Note", a->Note, sizeof(a->Note), i);
+ a->Active = PackGetIntEx(p, "Active", i);
+ a->Priority = PackGetIntEx(p, "Priority", i);
+ a->Discard = PackGetIntEx(p, "Discard", i);
+ a->SrcIpAddress = PackGetIp32Ex(p, "SrcIpAddress", i);
+ a->SrcSubnetMask = PackGetIp32Ex(p, "SrcSubnetMask", i);
+ a->DestIpAddress = PackGetIp32Ex(p, "DestIpAddress", i);
+ a->DestSubnetMask = PackGetIp32Ex(p, "DestSubnetMask", i);
+ a->Protocol = PackGetIntEx(p, "Protocol", i);
+ a->SrcPortStart = PackGetIntEx(p, "SrcPortStart", i);
+ a->SrcPortEnd = PackGetIntEx(p, "SrcPortEnd", i);
+ a->DestPortStart = PackGetIntEx(p, "DestPortStart", i);
+ a->DestPortEnd = PackGetIntEx(p, "DestPortEnd", i);
+ PackGetStrEx(p, "SrcUsername", a->SrcUsername, sizeof(a->SrcUsername), i);
+ PackGetStrEx(p, "DestUsername", a->DestUsername, sizeof(a->DestUsername), i);
+ a->CheckSrcMac = PackGetBoolEx(p, "CheckSrcMac", i);
+ PackGetDataEx2(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), i);
+ PackGetDataEx2(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), i);
+ a->CheckDstMac = PackGetBoolEx(p, "CheckDstMac", i);
+ PackGetDataEx2(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), i);
+ PackGetDataEx2(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), i);
+ a->CheckTcpState = PackGetBoolEx(p, "CheckTcpState", i);
+ a->Established = PackGetBoolEx(p, "Established", i);
+ a->Delay = PackGetIntEx(p, "Delay", i);
+ a->Jitter = PackGetIntEx(p, "Jitter", i);
+ a->Loss = PackGetIntEx(p, "Loss", i);
+ a->IsIPv6 = PackGetBoolEx(p, "IsIPv6", i);
+ PackGetStrEx(p, "RedirectUrl", a->RedirectUrl, sizeof(a->RedirectUrl), i);
+ if (a->IsIPv6)
+ {
+ PackGetIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, i);
+ PackGetIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, i);
+ PackGetIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, i);
+ PackGetIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, i);
+ }
+
+ return a;
+}
+
+// Convert the PACK to an access list
+void SiAccessListToPack(PACK *p, LIST *o)
+{
+ // Validate arguments
+ if (p == NULL || o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ACCESS *a = LIST_DATA(o, i);
+ SiAccessToPack(p, a, i, LIST_NUM(o));
+ }
+ }
+ UnlockList(o);
+}
+
+// Get the member that is hosting the specified HUB
+FARM_MEMBER *SiGetHubHostingMember(SERVER *s, HUB *h, bool admin_mode, CONNECTION *c)
+{
+ FARM_MEMBER *ret = NULL;
+ char name[MAX_SIZE];
+ UINT i;
+ // Validate arguments
+ if (s == NULL || h == NULL || c == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(name, sizeof(name), h->Name);
+
+ if (h->Type == HUB_TYPE_FARM_STATIC)
+ {
+ // It is good to select any member in the case of static HUB
+ if (admin_mode == false)
+ {
+ ret = SiGetNextFarmMember(s, c, h);
+ }
+ else
+ {
+ UINT i;
+ ret = NULL;
+
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ if (f->Me)
+ {
+ ret = f;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Examine whether there is a member that is hosting the HUB already in the case of dynamic HUB
+ for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
+ {
+ FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
+ HUB_LIST *hh, t;
+ StrCpy(t.Name, sizeof(t.Name), name);
+ LockList(f->HubList);
+ {
+ hh = Search(f->HubList, &t);
+ if (hh != NULL)
+ {
+ // Found
+ ret = f;
+ }
+ }
+ UnlockList(f->HubList);
+ }
+
+ if (ret == NULL)
+ {
+ // Let host the new HUB
+ FARM_MEMBER *f;
+
+ // Select the member to host
+ ret = SiGetNextFarmMember(s, c, h);
+
+ f = ret;
+ if (f != NULL)
+ {
+ // HUB creation directive
+ SiAddHubCreateHistory(s, name);
+ SiCallCreateHub(s, f, h);
+ SiCallUpdateHub(s, f, h);
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Task is called
+PACK *SiCalledTask(FARM_CONTROLLER *f, PACK *p, char *taskname)
+{
+ PACK *ret;
+ SERVER *s;
+ // Validate arguments
+ if (f == NULL || p == NULL || taskname == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NULL;
+ s = f->Server;
+
+ if (StrCmpi(taskname, "noop") == 0)
+ {
+ // NO OPERATION
+ ret = NewPack();
+ }
+ else
+ {
+ Debug("Task Called: [%s].\n", taskname);
+ if (StrCmpi(taskname, "createhub") == 0)
+ {
+ SiCalledCreateHub(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "deletehub") == 0)
+ {
+ SiCalledDeleteHub(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "enumhub") == 0)
+ {
+ ret = NewPack();
+ SiCalledEnumHub(s, ret, p);
+ }
+ else if (StrCmpi(taskname, "updatehub") == 0)
+ {
+ SiCalledUpdateHub(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "createticket") == 0)
+ {
+ ret = SiCalledCreateTicket(s, p);
+ }
+ else if (StrCmpi(taskname, "enumnat") == 0)
+ {
+ ret = SiCalledEnumNat(s, p);
+ }
+ else if (StrCmpi(taskname, "enumdhcp") == 0)
+ {
+ ret = SiCalledEnumDhcp(s, p);
+ }
+ else if (StrCmpi(taskname, "getnatstatus") == 0)
+ {
+ ret = SiCalledGetNatStatus(s, p);
+ }
+ else if (StrCmpi(taskname, "enumsession") == 0)
+ {
+ ret = SiCalledEnumSession(s, p);
+ }
+ else if (StrCmpi(taskname, "deletesession") == 0)
+ {
+ SiCalledDeleteSession(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "deletemactable") == 0)
+ {
+ SiCalledDeleteMacTable(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "deleteiptable") == 0)
+ {
+ SiCalledDeleteIpTable(s, p);
+ ret = NewPack();
+ }
+ else if (StrCmpi(taskname, "enummactable") == 0)
+ {
+ ret = SiCalledEnumMacTable(s, p);
+ }
+ else if (StrCmpi(taskname, "enumiptable") == 0)
+ {
+ ret = SiCalledEnumIpTable(s, p);
+ }
+ else if (StrCmpi(taskname, "getsessionstatus") == 0)
+ {
+ ret = SiCalledGetSessionStatus(s, p);
+ }
+ else if (StrCmpi(taskname, "enumlogfilelist") == 0)
+ {
+ ret = SiCalledEnumLogFileList(s, p);
+ }
+ else if (StrCmpi(taskname, "readlogfile") == 0)
+ {
+ ret = SiCalledReadLogFile(s, p);
+ }
+ }
+
+ return ret;
+}
+
+// Call the task (asynchronous)
+FARM_TASK *SiCallTaskAsyncBegin(FARM_MEMBER *f, PACK *p, char *taskname)
+{
+ char tmp[MAX_PATH];
+ FARM_TASK *t;
+ // Validate arguments
+ if (f == NULL || p == NULL || taskname == NULL)
+ {
+ return NULL;
+ }
+
+ PackAddStr(p, "taskname", taskname);
+
+ Debug("Call Async Task [%s] (%s)\n", taskname, f->hostname);
+
+ Format(tmp, sizeof(tmp), "CLUSTER_CALL_ASYNC: Entering Call [%s] to %s", taskname, f->hostname);
+ SiDebugLog(f->Cedar->Server, tmp);
+
+ t = SiFarmServPostTask(f, p);
+ StrCpy(t->TaskName, sizeof(t->TaskName), taskname);
+ StrCpy(t->HostName, sizeof(t->HostName), f->hostname);
+ t->FarmMember = f;
+
+ return t;
+}
+
+// Get the results of the asynchronous task
+PACK *SiCallTaskAsyncEnd(CEDAR *c, FARM_TASK *t)
+{
+ PACK *p;
+ char taskname[MAX_PATH];
+ char hostname[MAX_PATH];
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (t == NULL || c == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(taskname, sizeof(taskname), t->TaskName);
+ StrCpy(hostname, sizeof(hostname), t->HostName);
+
+ p = SiFarmServWaitTask(t);
+ if (p == NULL)
+ {
+ Format(tmp, sizeof(tmp), "CLUSTER_CALL_ASYNC: Call ERROR [%s] to %s", taskname, hostname);
+ SiDebugLog(c->Server, tmp);
+ return NULL;
+ }
+
+ Format(tmp, sizeof(tmp), "CLUSTER_CALL_ASYNC: Retrieving Call Result [%s] to %s", taskname, hostname);
+ SiDebugLog(c->Server, tmp);
+
+ return p;
+}
+
+// Call the task
+PACK *SiCallTask(FARM_MEMBER *f, PACK *p, char *taskname)
+{
+ PACK *ret;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (f == NULL || p == NULL || taskname == NULL)
+ {
+ return NULL;
+ }
+
+ PackAddStr(p, "taskname", taskname);
+
+ Debug("Call Task [%s] (%s)\n", taskname, f->hostname);
+
+ Format(tmp, sizeof(tmp), "CLUSTER_CALL: Entering Call [%s] to %s", taskname, f->hostname);
+ SiDebugLog(f->Cedar->Server, tmp);
+
+ ret = SiExecTask(f, p);
+
+ Format(tmp, sizeof(tmp), "CLUSTER_CALL: Leaving Call [%s] to %s", taskname, f->hostname);
+ SiDebugLog(f->Cedar->Server, tmp);
+
+ return ret;
+}
+
+// Task listening procedure (Main Process)
+void SiAcceptTasksFromControllerMain(FARM_CONTROLLER *f, SOCK *sock)
+{
+ PACK *request;
+ PACK *response;
+ char taskname[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || sock == NULL)
+ {
+ return;
+ }
+
+ f->IsConnected = true;
+
+ while (true)
+ {
+ bool ret;
+ // Receive the PACK
+ request = HttpClientRecv(sock);
+ if (request == NULL)
+ {
+ // Disconnect
+ break;
+ }
+
+ response = NULL;
+
+ // Get the name
+ if (PackGetStr(request, "taskname", taskname, sizeof(taskname)))
+ {
+ Lock(f->Server->TasksFromFarmControllerLock);
+ {
+ response = SiCalledTask(f, request, taskname);
+ }
+ Unlock(f->Server->TasksFromFarmControllerLock);
+ }
+
+ FreePack(request);
+
+ // Return a response
+ if (response == NULL)
+ {
+ response = NewPack();
+ }
+ else
+ {
+ PackAddInt(response, "succeed", 1);
+ }
+
+ ret = HttpClientSend(sock, response);
+ FreePack(response);
+
+ if (ret == false)
+ {
+ // Disconnect
+ break;
+ }
+ }
+
+ f->IsConnected = false;
+}
+
+// Task waiting procedure
+void SiAcceptTasksFromController(FARM_CONTROLLER *f, SOCK *sock)
+{
+ UINT i;
+ HUB **hubs;
+ UINT num_hubs;
+ CEDAR *c;
+ SERVER *s;
+ // Validate arguments
+ if (f == NULL || sock == NULL)
+ {
+ return;
+ }
+
+ s = f->Server;
+ c = s->Cedar;
+
+ // Main process
+ SiAcceptTasksFromControllerMain(f, sock);
+
+ // Stop all Virtual HUBs since the connection to the controller is disconnected
+ LockList(c->HubList);
+ {
+ hubs = ToArray(c->HubList);
+ num_hubs = LIST_NUM(c->HubList);
+ for (i = 0;i < num_hubs;i++)
+ {
+ AddRef(hubs[i]->ref);
+ }
+ }
+ UnlockList(c->HubList);
+
+ for (i = 0;i < num_hubs;i++)
+ {
+ SetHubOffline(hubs[i]);
+ DelHub(c, hubs[i]);
+ ReleaseHub(hubs[i]);
+ }
+
+ Free(hubs);
+}
+
+// Execute the task
+PACK *SiExecTask(FARM_MEMBER *f, PACK *p)
+{
+ FARM_TASK *t;
+ // Validate arguments
+ if (f == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ t = SiFarmServPostTask(f, p);
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ return SiFarmServWaitTask(t);
+}
+
+// Task queuing
+FARM_TASK *SiFarmServPostTask(FARM_MEMBER *f, PACK *request)
+{
+ FARM_TASK *t;
+ // Validate arguments
+ if (f == NULL || request == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(FARM_TASK));
+ t->CompleteEvent = NewEvent();
+ t->Request = request;
+
+ LockQueue(f->TaskQueue);
+ {
+ if (f->Halting)
+ {
+ // Halting (failure)
+ UnlockQueue(f->TaskQueue);
+ ReleaseEvent(t->CompleteEvent);
+ Free(t);
+ return NULL;
+ }
+
+ InsertQueue(f->TaskQueue, t);
+ }
+ UnlockQueue(f->TaskQueue);
+
+ Set(f->TaskPostEvent);
+
+ return t;
+}
+
+// Wait for task results
+PACK *SiFarmServWaitTask(FARM_TASK *t)
+{
+ PACK *response;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Wait(t->CompleteEvent, INFINITE);
+ ReleaseEvent(t->CompleteEvent);
+ FreePack(t->Request);
+
+ response = t->Response;
+ Free(t);
+
+ if (PackGetInt(response, "succeed") == 0)
+ {
+ // Task calling fails for any reason
+ FreePack(response);
+ return NULL;
+ }
+
+ return response;
+}
+
+// Server farm processing main
+void SiFarmServMain(SERVER *server, SOCK *sock, FARM_MEMBER *f)
+{
+ UINT wait_time = SERVER_CONTROL_TCP_TIMEOUT / 2;
+ bool send_noop = false;
+ UINT i;
+ CEDAR *c;
+ // Validate arguments
+ if (server == NULL || sock == NULL || f == NULL)
+ {
+ Debug("SiFarmServMain Failed.\n");
+ return;
+ }
+
+ Debug("SiFarmServMain Started.\n");
+
+ c = server->Cedar;
+
+ // Send a directive to create all static HUBs at the stage
+ // where the members have been connected to the controller
+ LockList(c->HubList);
+ {
+ for (i = 0;i < LIST_NUM(c->HubList);i++)
+ {
+ HUB *h = LIST_DATA(c->HubList, i);
+ if (h->Offline == false)
+ {
+ if (h->Type == HUB_TYPE_FARM_STATIC)
+ {
+ PACK *p;
+ HUB_LIST *hh;
+ p = NewPack();
+ SiPackAddCreateHub(p, h);
+ PackAddStr(p, "taskname", "createhub");
+ HttpServerSend(sock, p);
+ FreePack(p);
+ p = HttpServerRecv(sock);
+ FreePack(p);
+
+ p = NewPack();
+ SiPackAddCreateHub(p, h);
+ PackAddStr(p, "taskname", "updatehub");
+ HttpServerSend(sock, p);
+ FreePack(p);
+ p = HttpServerRecv(sock);
+ FreePack(p);
+
+ hh = ZeroMalloc(sizeof(HUB_LIST));
+ hh->DynamicHub = false;
+ hh->FarmMember = f;
+ StrCpy(hh->Name, sizeof(hh->Name), h->Name);
+ LockList(f->HubList);
+ {
+ Add(f->HubList, hh);
+ }
+ UnlockList(f->HubList);
+ }
+ }
+ }
+ }
+ UnlockList(c->HubList);
+
+ Debug("SiFarmServMain: while (true)\n");
+
+ while (true)
+ {
+ FARM_TASK *t;
+ UINT64 tick;
+
+ do
+ {
+ // Check whether a new task arrived
+ LockQueue(f->TaskQueue);
+ {
+ t = GetNext(f->TaskQueue);
+ }
+ UnlockQueue(f->TaskQueue);
+
+ if (t != NULL)
+ {
+ // Handle this task
+ PACK *p = t->Request;
+ bool ret;
+
+ // Transmission
+ ret = HttpServerSend(sock, p);
+ send_noop = false;
+
+ if (ret == false)
+ {
+ // Disconnected
+ // Cancel this task
+ Set(t->CompleteEvent);
+ goto DISCONNECTED;
+ }
+
+ // Receive
+ p = HttpServerRecv(sock);
+
+ t->Response = p;
+ Set(t->CompleteEvent);
+
+ send_noop = false;
+ }
+ }
+ while (t != NULL);
+
+ if (send_noop)
+ {
+ // Send a NOOP
+ PACK *p;
+ bool ret;
+ p = NewPack();
+ PackAddStr(p, "taskname", "noop");
+
+ ret = HttpServerSend(sock, p);
+ FreePack(p);
+
+ if (ret == false)
+ {
+ goto DISCONNECTED;
+ }
+
+ p = HttpServerRecv(sock);
+ if (p == NULL)
+ {
+ goto DISCONNECTED;
+ }
+
+ FreePack(p);
+ }
+
+ tick = Tick64();
+
+ while (true)
+ {
+ bool break_flag;
+ if ((tick + wait_time) <= Tick64())
+ {
+ break;
+ }
+
+ Wait(f->TaskPostEvent, 250);
+
+ break_flag = false;
+ LockQueue(f->TaskQueue);
+ {
+ if (f->TaskQueue->num_item != 0)
+ {
+ break_flag = true;
+ }
+ }
+ UnlockQueue(f->TaskQueue);
+
+ if (break_flag || f->Halting || server->Halt)
+ {
+ break;
+ }
+ }
+ send_noop = true;
+ }
+
+DISCONNECTED:
+
+ Debug("SiFarmServMain: DISCONNECTED\n");
+
+ f->Halting = true;
+ // Cancel all outstanding tasks
+ LockQueue(f->TaskQueue);
+ {
+ FARM_TASK *t;
+
+ while (t = GetNext(f->TaskQueue))
+ {
+ Set(t->CompleteEvent);
+ }
+ }
+ UnlockQueue(f->TaskQueue);
+}
+
+// Farm server function that handles the connection from farm members
+void SiFarmServ(SERVER *server, SOCK *sock, X *cert, UINT ip, UINT num_port, UINT *ports, char *hostname, UINT point, UINT weight, UINT max_sessions)
+{
+ PACK *p;
+ FARM_MEMBER *f;
+ UINT i;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (server == NULL || sock == NULL || cert == NULL || num_port == 0 || ports == NULL || hostname == NULL)
+ {
+ return;
+ }
+
+ if (weight == 0)
+ {
+ weight = FARM_DEFAULT_WEIGHT;
+ }
+
+ if (max_sessions == 0)
+ {
+ max_sessions = SERVER_MAX_SESSIONS;
+ }
+
+ if (ip == 0)
+ {
+ // If the public IP address is not specified, specify the connection
+ // source IP address of this farm member server
+ ip = IPToUINT(&sock->RemoteIP);
+ }
+
+ IPToStr32(tmp, sizeof(tmp), ip);
+ SLog(server->Cedar, "LS_FARM_SERV_START", tmp, hostname);
+
+ // Inform the success
+ p = NewPack();
+ HttpServerSend(sock, p);
+ FreePack(p);
+
+ IPToStr32(tmp, sizeof(tmp), ip);
+ Debug("Farm Member %s Connected. IP: %s\n", hostname, tmp);
+
+ SetTimeout(sock, SERVER_CONTROL_TCP_TIMEOUT);
+
+ f = ZeroMalloc(sizeof(FARM_MEMBER));
+ f->Cedar = server->Cedar;
+ f->Ip = ip;
+ f->NumPort = num_port;
+ f->Ports = ports;
+ StrCpy(f->hostname, sizeof(f->hostname), hostname);
+ f->ServerCert = cert;
+ f->ConnectedTime = SystemTime64();
+ f->Weight = weight;
+ f->MaxSessions = max_sessions;
+
+ f->HubList = NewList(CompareHubList);
+ f->Point = point;
+
+ f->TaskQueue = NewQueue();
+ f->TaskPostEvent = NewEvent();
+
+ // Add to the list
+ LockList(server->FarmMemberList);
+ {
+ Add(server->FarmMemberList, f);
+ }
+ UnlockList(server->FarmMemberList);
+
+ // Main process
+ SiFarmServMain(server, sock, f);
+
+ // Remove from the list
+ LockList(server->FarmMemberList);
+ {
+ Delete(server->FarmMemberList, f);
+ }
+ UnlockList(server->FarmMemberList);
+
+ ReleaseQueue(f->TaskQueue);
+ ReleaseEvent(f->TaskPostEvent);
+
+ for (i = 0;i < LIST_NUM(f->HubList);i++)
+ {
+ HUB_LIST *hh = LIST_DATA(f->HubList, i);
+ Free(hh);
+ }
+
+ ReleaseList(f->HubList);
+
+ Free(f);
+
+ SLog(server->Cedar, "LS_FARM_SERV_END", hostname);
+}
+
+// Search in HUB list
+int CompareHubList(void *p1, void *p2)
+{
+ HUB_LIST *h1, *h2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ h1 = *(HUB_LIST **)p1;
+ h2 = *(HUB_LIST **)p2;
+ if (h1 == NULL || h2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(h1->Name, h2->Name);
+}
+
+// Connection thread to the controller
+void SiConnectToControllerThread(THREAD *thread, void *param)
+{
+ FARM_CONTROLLER *f;
+ SESSION *s;
+ CONNECTION *c;
+ SERVER *server;
+ bool first_failed;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ MsSetThreadPriorityRealtime();
+#endif // OS_WIN32
+
+ f = (FARM_CONTROLLER *)param;
+ f->Thread = thread;
+ AddRef(f->Thread->ref);
+ NoticeThreadInit(thread);
+
+ f->StartedTime = SystemTime64();
+
+ server = f->Server;
+
+ f->StartedTime = SystemTime64();
+
+ SLog(server->Cedar, "LS_FARM_CONNECT_1", server->ControllerName);
+
+ first_failed = true;
+
+ while (true)
+ {
+ // Attempt to connect
+ CLIENT_OPTION o;
+
+ f->LastError = ERR_TRYING_TO_CONNECT;
+
+ Zero(&o, sizeof(CLIENT_OPTION));
+ StrCpy(o.Hostname, sizeof(o.Hostname), server->ControllerName);
+ o.Port = server->ControllerPort;
+ f->NumTry++;
+
+ Debug("Try to Connect %s (Controller).\n", server->ControllerName);
+
+ s = NewRpcSessionEx(server->Cedar, &o, NULL, CEDAR_SERVER_FARM_STR);
+
+ if (s != NULL)
+ {
+ // Connection success: send the authentication data
+ PACK *p = NewPack();
+ UCHAR secure_password[SHA1_SIZE];
+ BUF *b;
+
+ c = s->Connection;
+
+ Lock(f->lock);
+ {
+ f->Sock = c->FirstSock;
+ AddRef(f->Sock->ref);
+ SetTimeout(f->Sock, SERVER_CONTROL_TCP_TIMEOUT);
+ }
+ Unlock(f->lock);
+
+ // Method
+ PackAddStr(p, "method", "farm_connect");
+ PackAddClientVersion(p, s->Connection);
+
+ // Password
+ SecurePassword(secure_password, server->MemberPassword, s->Connection->Random);
+ PackAddData(p, "SecurePassword", secure_password, sizeof(secure_password));
+
+ Lock(server->Cedar->lock);
+ {
+ b = XToBuf(server->Cedar->ServerX, false);
+ }
+ Unlock(server->Cedar->lock);
+
+ if (b != NULL)
+ {
+ char tmp[MAX_SIZE];
+ bool ret;
+ UINT i;
+ // Server certificate
+ PackAddBuf(p, "ServerCert", b);
+ FreeBuf(b);
+
+ // Maximum number of sessions
+ PackAddInt(p, "MaxSessions", GetServerCapsInt(server, "i_max_sessions"));
+
+ // Point
+ PackAddInt(p, "Point", SiGetPoint(server));
+ PackAddInt(p, "Weight", server->Weight);
+
+ // Host name
+ GetMachineName(tmp, sizeof(tmp));
+ PackAddStr(p, "HostName", tmp);
+
+ // Public IP
+ PackAddIp32(p, "PublicIp", server->PublicIp);
+
+ // Public port
+ for (i = 0;i < server->NumPublicPort;i++)
+ {
+ PackAddIntEx(p, "PublicPort", server->PublicPorts[i], i, server->NumPublicPort);
+ }
+
+ ret = HttpClientSend(c->FirstSock, p);
+
+ if (ret)
+ {
+ PACK *p;
+ UINT err = ERR_PROTOCOL_ERROR;
+
+ first_failed = true;
+ p = HttpClientRecv(c->FirstSock);
+ if (p != NULL && (err = GetErrorFromPack(p)) == 0)
+ {
+ // Successful connection
+ SLog(server->Cedar, "LS_FARM_START");
+ f->CurrentConnectedTime = SystemTime64();
+ if (f->FirstConnectedTime == 0)
+ {
+ f->FirstConnectedTime = SystemTime64();
+ }
+ f->NumConnected++;
+ Debug("Connect Succeed.\n");
+ f->Online = true;
+
+ // Main process
+ SiAcceptTasksFromController(f, c->FirstSock);
+
+ f->Online = false;
+ }
+ else
+ {
+ // Error
+ f->LastError = err;
+ SLog(server->Cedar, "LS_FARM_CONNECT_2", server->ControllerName,
+ GetUniErrorStr(err), err);
+ }
+ FreePack(p);
+ }
+ else
+ {
+ f->LastError = ERR_DISCONNECTED;
+
+ if (first_failed)
+ {
+ SLog(server->Cedar, "LS_FARM_CONNECT_3", server->ControllerName, RETRY_CONNECT_TO_CONTROLLER_INTERVAL / 1000);
+ first_failed = false;
+ }
+ }
+ }
+
+ FreePack(p);
+
+ // Disconnect
+ Lock(f->lock);
+ {
+ if (f->Sock != NULL)
+ {
+ ReleaseSock(f->Sock);
+ f->Sock = NULL;
+ }
+ }
+ Unlock(f->lock);
+
+ ReleaseSession(s);
+ s = NULL;
+
+ if (f->LastError == ERR_TRYING_TO_CONNECT)
+ {
+ f->LastError = ERR_DISCONNECTED;
+ }
+ }
+ else
+ {
+ // Connection failure
+ f->LastError = ERR_CONNECT_TO_FARM_CONTROLLER;
+
+ if (first_failed)
+ {
+ SLog(server->Cedar, "LS_FARM_CONNECT_3", server->ControllerName, RETRY_CONNECT_TO_CONTROLLER_INTERVAL / 1000);
+ first_failed = false;
+ }
+ }
+
+ Debug("Controller Disconnected. ERROR = %S\n", _E(f->LastError));
+
+ f->NumFailed = f->NumTry - f->NumConnected;
+
+ // Wait for event
+ Wait(f->HaltEvent, RETRY_CONNECT_TO_CONTROLLER_INTERVAL);
+
+ if (f->Halt)
+ {
+ // Halting flag
+ break;
+ }
+ }
+
+ SLog(server->Cedar, "LS_FARM_DISCONNECT");
+}
+
+// Disconnect the connection to the controller
+void SiStopConnectToController(FARM_CONTROLLER *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ f->Halt = true;
+
+ // Stop the connection
+ Lock(f->lock);
+ {
+ Disconnect(f->Sock);
+ }
+ Unlock(f->lock);
+
+ Set(f->HaltEvent);
+
+ // Wait for the thread termination
+ WaitThread(f->Thread, INFINITE);
+ ReleaseThread(f->Thread);
+
+ DeleteLock(f->lock);
+ ReleaseEvent(f->HaltEvent);
+
+ Free(f);
+}
+
+// Start a connection to the controller
+FARM_CONTROLLER *SiStartConnectToController(SERVER *s)
+{
+ FARM_CONTROLLER *f;
+ THREAD *t;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ f = ZeroMalloc(sizeof(FARM_CONTROLLER));
+ f->Server = s;
+ f->LastError = ERR_TRYING_TO_CONNECT;
+ f->HaltEvent = NewEvent();
+ f->lock = NewLock();
+
+ t = NewThread(SiConnectToControllerThread, f);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ return f;
+}
+
+// Create a server
+SERVER *SiNewServer(bool bridge)
+{
+ return SiNewServerEx(bridge, false);
+}
+SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server)
+{
+ SERVER *s;
+ LISTENER *inproc;
+ LISTENER *azure;
+ LISTENER *rudp;
+
+ s = ZeroMalloc(sizeof(SERVER));
+
+ SiInitHubCreateHistory(s);
+
+ InitServerCapsCache(s);
+
+ Rand(s->MyRandomKey, sizeof(s->MyRandomKey));
+
+ s->lock = NewLock();
+
+
+ s->OpenVpnSstpConfigLock = NewLock();
+ s->SaveCfgLock = NewLock();
+ s->ref = NewRef();
+ s->Cedar = NewCedar(NULL, NULL);
+ s->Cedar->Server = s;
+
+
+#ifdef OS_WIN32
+ s->IsInVm = MsIsInVm();
+#else // OS_WIN32
+ s->IsInVm = UnixIsInVm();
+#endif // OS_WIN32
+
+#ifdef ENABLE_AZURE_SERVER
+ if (IsFileExists("@azureserver.config"))
+ {
+ DisableRDUPServerGlobally();
+ s->AzureServer = NewAzureServer(s->Cedar);
+
+ SleepThread(500);
+ }
+#endif // ENABLE_AZURE_SERVER
+
+ s->Cedar->CheckExpires = true;
+ s->ServerListenerList = NewList(CompareServerListener);
+ s->StartTime = SystemTime64();
+ s->Syslog = NewSysLog(NULL, 0);
+ s->SyslogLock = NewLock();
+ s->TasksFromFarmControllerLock = NewLock();
+
+ if (bridge)
+ {
+ SetCedarVpnBridge(s->Cedar);
+ }
+
+#ifdef OS_WIN32
+ if (IsHamMode() == false)
+ {
+ RegistWindowsFirewallAll();
+ }
+#endif
+
+ s->Keep = StartKeep();
+
+ // Log related
+ MakeDir(bridge == false ? SERVER_LOG_DIR_NAME : BRIDGE_LOG_DIR_NAME);
+ s->Logger = NewLog(bridge == false ? SERVER_LOG_DIR_NAME : BRIDGE_LOG_DIR_NAME, SERVER_LOG_PERFIX, LOG_SWITCH_DAY);
+
+ SLog(s->Cedar, "L_LINE");
+ SLog(s->Cedar, "LS_START_2", s->Cedar->ServerStr, s->Cedar->VerString);
+ SLog(s->Cedar, "LS_START_3", s->Cedar->BuildInfo);
+ SLog(s->Cedar, "LS_START_UTF8");
+ SLog(s->Cedar, "LS_START_1");
+
+
+
+ // Initialize the configuration
+ SiInitConfiguration(s);
+
+
+ if (s->DisableIntelAesAcceleration)
+ {
+ // Disable the Intel AES acceleration
+ DisableIntelAesAccel();
+ }
+
+ // Raise the priority
+ if (s->NoHighPriorityProcess == false)
+ {
+ OSSetHighPriority();
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ // Start a connection to the controller
+ s->FarmController = SiStartConnectToController(s);
+ }
+ else if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ FARM_MEMBER *f;
+ // Start operating as a controller
+ s->FarmMemberList = NewList(NULL);
+
+ f = ZeroMalloc(sizeof(FARM_MEMBER));
+ f->Cedar = s->Cedar;
+ GetMachineName(f->hostname, sizeof(f->hostname));
+ f->Me = true;
+ f->HubList = NewList(CompareHubList);
+ f->Weight = s->Weight;
+
+ s->Me = f;
+
+ Add(s->FarmMemberList, f);
+
+ SiStartFarmControl(s);
+
+ s->FarmControllerInited = true;
+ }
+
+ // Start a in-processlistener
+ inproc = NewListener(s->Cedar, LISTENER_INPROC, 0);
+ ReleaseListener(inproc);
+
+ // Start a listener for Azure
+ if (s->AzureClient != NULL)
+ {
+ azure = NewListener(s->Cedar, LISTENER_REVERSE, 0);
+ ReleaseListener(azure);
+ }
+
+ // Start a R-UDP listener
+ if (s->DisableNatTraversal == false && s->Cedar->Bridge == false)
+ {
+ rudp = NewListenerEx4(s->Cedar, LISTENER_RUDP, 0, TCPAcceptedThread, NULL, false, false,
+ &s->NatTGlobalUdpPort, RAND_PORT_ID_SERVER_LISTEN);
+ ReleaseListener(rudp);
+ }
+
+ // Start a VPN-over-ICMP listener
+ s->DynListenerIcmp = NewDynamicListener(s->Cedar, &s->EnableVpnOverIcmp, LISTENER_ICMP, 0);
+
+ // Start a VPN-over-DNS listener
+ s->DynListenerDns = NewDynamicListener(s->Cedar, &s->EnableVpnOverDns, LISTENER_DNS, 53);
+
+
+ SiInitDeadLockCheck(s);
+
+ return s;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Server.h b/src/Cedar/Server.h
new file mode 100644
index 00000000..a1532c78
--- /dev/null
+++ b/src/Cedar/Server.h
@@ -0,0 +1,664 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Server.h
+// Header of Server.c
+
+#ifndef SERVER_H
+#define SERVER_H
+
+// Default ports
+#define SERVER_DEF_PORTS_1 443
+#define SERVER_DEF_PORTS_2 992
+#define SERVER_DEF_PORTS_3 1194
+#define SERVER_DEF_PORTS_4 GC_DEFAULT_PORT
+
+#define SERVER_DEF_PORTS_INCLIENT_1 995
+#define SERVER_DEF_PORTS_INCLIENT_2 465
+#define SERVER_DEF_PORTS_INCLIENT_3 9008 // for admin (in client)
+#define SERVER_DEF_PORTS_INCLIENT_4 1195
+
+#define SERVER_DEF_PORTS_INCLIENT_DYN_MIN 1201
+#define SERVER_DEF_PORTS_INCLIENT_DYN_MAX 1999
+
+extern char *SERVER_CONFIG_FILE_NAME;
+#define SERVER_DEFAULT_CIPHER_NAME "RC4-MD5"
+#define SERVER_DEFAULT_CERT_DAYS (365 * 10)
+#define SERVER_DEFAULT_HUB_NAME "DEFAULT"
+#define SERVER_DEFAULT_BRIDGE_NAME "BRIDGE"
+#define SERVER_CONTROL_TCP_TIMEOUT (60 * 1000)
+#define SERVER_FARM_CONTROL_INTERVAL (10 * 1000)
+
+#define SERVER_FILE_SAVE_INTERVAL_DEFAULT (5 * 60 * 1000)
+#define SERVER_FILE_SAVE_INTERVAL_MIN (5 * 1000)
+#define SERVER_FILE_SAVE_INTERVAL_MAX (3600 * 1000)
+#define SERVER_FILE_SAVE_INTERVAL_USERMODE (1 * 60 * 1000)
+
+#define SERVER_LICENSE_VIOLATION_SPAN (SERVER_FARM_CONTROL_INTERVAL * 2)
+
+
+#define SERVER_DEADLOCK_CHECK_SPAN (2 * 60 * 1000)
+#define SERVER_DEADLOCK_CHECK_TIMEOUT (10 * 60 * 1000)
+
+
+#define RETRY_CONNECT_TO_CONTROLLER_INTERVAL (1 * 1000)
+
+#define MAX_PUBLIC_PORT_NUM 128
+
+#define MEMBER_SELECTOR_TXT_FILENAME "@member_selector.config"
+#define MEMBER_SELECTOR_CONNECT_TIMEOUT 2000
+#define MEMBER_SELECTOR_DATA_TIMEOUT 5000
+
+
+// Virtual HUB list hosted by each farm member
+struct HUB_LIST
+{
+ struct FARM_MEMBER *FarmMember; // Farm member
+ bool DynamicHub; // Dynamic HUB
+ char Name[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumSessions; // Number of sessions
+ UINT NumSessionsClient; // Number of client sessions
+ UINT NumSessionsBridge; // Number of bridge sessions
+ UINT NumMacTables; // Number of MAC table entries
+ UINT NumIpTables; // Number of IP table entries
+};
+
+// Task
+struct FARM_TASK
+{
+ EVENT *CompleteEvent; // Completion notice
+ PACK *Request; // Request
+ PACK *Response; // Response
+ FARM_MEMBER *FarmMember; // Destination farm member
+ char TaskName[MAX_PATH]; // Task name
+ char HostName[MAX_PATH]; // Host name
+};
+
+// Farm member
+struct FARM_MEMBER
+{
+ CEDAR *Cedar; // Cedar
+ UINT64 ConnectedTime; // Connection date and time
+ UINT Me; // Myself
+ UINT Ip; // IP address
+ UINT NumPort; // Number of port numbers
+ UINT *Ports; // Port number
+ char hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ X *ServerCert; // Server certificate
+ LIST *HubList; // Virtual HUB list
+ QUEUE *TaskQueue; // Task queue
+ EVENT *TaskPostEvent; // Task queuing event
+ UINT Point; // Point
+ volatile bool Halting; // Stopped
+ UINT NumSessions; // Number of sessions
+ UINT MaxSessions; // Maximum number of sessions
+ UINT NumTcpConnections; // Number of TCP connections
+ TRAFFIC Traffic; // Traffic information
+ UINT AssignedClientLicense; // Number of assigned client licenses
+ UINT AssignedBridgeLicense; // Number of assigned bridge licenses
+ UINT Weight; // Performance ratio
+ UCHAR RandomKey[SHA1_SIZE]; // Random number key (license check)
+ UINT64 SystemId; // System ID (license check)
+};
+
+// Connection to the farm controller
+struct FARM_CONTROLLER
+{
+ LOCK *lock; // Lock
+ struct SERVER *Server; // Server
+ THREAD *Thread; // Thread
+ SOCK *Sock; // Socket
+ SESSION *Session; // Session
+ volatile bool Halt; // Halting flag
+ EVENT *HaltEvent; // Halting event
+ UINT LastError; // Last error
+ bool Online; // Online flag
+ UINT64 StartedTime; // Connection start time
+ UINT64 CurrentConnectedTime; // Connection time of this time
+ UINT64 FirstConnectedTime; // First connection time
+ UINT NumConnected; // Number of connection count
+ UINT NumTry; // Number of trials
+ UINT NumFailed; // Connection failure count
+ bool IsConnected; // Whether it's connected
+};
+
+// Server listener
+struct SERVER_LISTENER
+{
+ UINT Port; // Port number
+ bool Enabled; // Active flag
+ LISTENER *Listener; // Listener object
+ bool DisableDos; // Disable the DoS detection
+};
+
+// Syslog configuration
+struct SYSLOG_SETTING
+{
+ UINT SaveType; // Save type
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+};
+
+// Setting of SSTP and OpenVPN
+struct OPENVPN_SSTP_CONFIG
+{
+ bool EnableOpenVPN; // OpenVPN is enabled
+ char OpenVPNPortList[MAX_SIZE]; // OpenVPN UDP port number list
+ bool EnableSSTP; // SSTP is enabled
+};
+
+// Server object
+struct SERVER
+{
+ UINT ServerType; // Type of server
+ UINT UpdatedServerType; // Type of updated server
+ LIST *ServerListenerList; // Server listener list
+ UCHAR HashedPassword[SHA1_SIZE]; // Password
+ char ControllerName[MAX_HOST_NAME_LEN + 1]; // Controller name
+ UINT ControllerPort; // Controller port
+ UINT Weight; // Performance ratio
+ bool ControllerOnly; // Only controller function
+ UCHAR MemberPassword[SHA1_SIZE]; // Password for farm members
+ UINT PublicIp; // Public IP
+ UINT NumPublicPort; // Number of public ports
+ UINT *PublicPorts; // Public port array
+ UINT64 StartTime; // Start-up time
+ UINT AutoSaveConfigSpan; // Auto save interval
+ UINT AutoSaveConfigSpanSaved; // Auto save interval (stored value)
+ bool DontBackupConfig; // Do not save a backup of the configuration automatically
+ bool BackupConfigOnlyWhenModified; // Save a backup of the configuration only if there is a modification
+ UINT ConfigRevision; // Configuration file revision
+ bool DisableDosProction; // Disable the DoS attack protection
+ UCHAR MyRandomKey[SHA1_SIZE]; // Their own random key
+ bool FarmControllerInited; // Initialization of farm controller has been completed
+ bool DisableDeadLockCheck; // Disable the deadlock check
+ bool UseWebUI; // Use the WebUI
+ bool SaveDebugLog; // Save the debug log
+ bool NoSendSignature; // Let the client not to send a signature
+ bool UseWebTimePage; // Use WebTimePage
+ bool NoLinuxArpFilter; // Not to set arp_filter in Linux
+ bool NoHighPriorityProcess; // Not to raise the priority of the process
+ bool NoDebugDump; // Not to output the debug dump
+ bool DisableSSTPServer; // Disable the SSTP server function
+ bool DisableOpenVPNServer; // Disable the OpenVPN server function
+ bool DisableNatTraversal; // Disable the NAT-traversal feature
+ bool EnableVpnOverIcmp; // VPN over ICMP is enabled
+ bool EnableVpnOverDns; // VPN over DNS is enabled
+ bool DisableIntelAesAcceleration; // Disable the Intel AES acceleration
+ bool NoMoreSave; // Do not save any more
+ bool EnableConditionalAccept; // Apply the Conditional Accept the Listener
+
+ volatile bool Halt; // Halting flag
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ CFG_RW *CfgRw; // Configuration file R/W
+ LOCK *SaveCfgLock; // Settings saving lock
+ EVENT *SaveHaltEvent; // Saving thread halting event
+ THREAD *SaveThread; // Settings saving thread
+ FARM_CONTROLLER *FarmController; // Farm controller
+ LOCK *TasksFromFarmControllerLock; // Lock while processing tasks from farm controller
+ LIST *FarmMemberList; // Farm members list
+ FARM_MEMBER *Me; // Register myself as a farm member
+ THREAD *FarmControlThread; // Farm control thread
+ EVENT *FarmControlThreadHaltEvent; // Farm control thread halting event
+ LIST *HubCreateHistoryList; // Virtual HUB creation history list
+
+ KEEP *Keep; // Maintaining connections
+ LOG *Logger; // Server logger
+ ERASER *Eraser; // Eraser
+
+ bool Led; // Use the LED display board
+ bool LedSpecial; // LED Special
+
+ UINT CurrentTotalNumSessionsOnFarm; // Total number of sessions in this server farm
+ UINT CurrentAssignedClientLicense; // Current number of assigned client licenses
+ UINT CurrentAssignedBridgeLicense; // Current number of assigned bridge license
+
+
+ LOCK *SyslogLock; // The lock of the syslog configuration
+ SYSLOG_SETTING SyslogSetting; // Syslog configuration
+ SLOG *Syslog; // Syslog object
+
+ LOCK *CapsCacheLock; // Lock for Caps cache
+ CAPSLIST *CapsListCache; // Caps cache
+ UINT LicenseHash; // Hash value of the license list
+
+ bool SnapshotInited;
+ EVENT *SnapshotHaltEvent; // Snapshot halting event
+ volatile bool HaltSnapshot; // Snapshot halting flag
+ THREAD *SnapshotThread; // Snapshot thread
+ LOG *SnapshotLogger; // Snapshot logger
+ UINT64 LastSnapshotTime; // Time that the last snapshot created
+
+ THREAD *DeadLockCheckThread; // Deadlock check thread
+ volatile bool HaltDeadLockThread; // Halting flag
+ EVENT *DeadLockWaitEvent; // Waiting Event
+
+ IPSEC_SERVER *IPsecServer; // IPsec server function
+ OPENVPN_SERVER_UDP *OpenVpnServerUdp; // OpenVPN server function
+ char OpenVpnServerUdpPorts[MAX_SIZE]; // UDP port list string
+ DDNS_CLIENT *DDnsClient; // DDNS client feature
+ LOCK *OpenVpnSstpConfigLock; // Lock OpenVPN and SSTP configuration
+
+ AZURE_CLIENT *AzureClient; // VPN Azure client
+ bool EnableVpnAzure; // Flag whether VPN Azure client is enabled
+
+ TINY_LOG *DebugLog; // Debug log
+
+ DYNAMIC_LISTENER *DynListenerIcmp; // VPN over ICMP listener
+ DYNAMIC_LISTENER *DynListenerDns; // VPN over DNS listener
+
+ bool IPsecMessageDisplayed; // Flag for whether the message about IPsec is displayed
+
+ bool IsInVm; // Whether I'm within the VM
+
+
+
+ volatile UINT NatTGlobalUdpPort; // NAT-T global UDP port
+};
+
+
+// Enumerate sessions *
+struct RPC_ENUM_SESSION
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ UINT NumSession; // Number of sessions
+ struct RPC_ENUM_SESSION_ITEM *Sessions; // Session list
+};
+
+// Session status *
+struct RPC_SESSION_STATUS
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
+ char Name[MAX_SESSION_NAME_LEN + 1]; // Session name
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ char RealUsername[MAX_USERNAME_LEN + 1]; // Real user name
+ char GroupName[MAX_USERNAME_LEN + 1]; // Group name
+ bool LinkMode; // Link mode
+ RPC_CLIENT_GET_CONNECTION_STATUS Status; // Status
+ UINT ClientIp; // Client IP address
+ UCHAR ClientIp6[16]; // Client IPv6 address
+ char ClientHostName[MAX_HOST_NAME_LEN + 1]; // Client host name
+ NODE_INFO NodeInfo; // Node information
+};
+
+
+// Type of server
+#define SERVER_TYPE_STANDALONE 0 // Stand-alone server
+#define SERVER_TYPE_FARM_CONTROLLER 1 // Farm controller server
+#define SERVER_TYPE_FARM_MEMBER 2 // Farm member server
+
+
+// Caps related
+struct CAPS
+{
+ char *Name; // Name
+ UINT Value; // Value
+};
+struct CAPSLIST
+{
+ LIST *CapsList; // Caps list
+};
+
+// Log file
+struct LOG_FILE
+{
+ char Path[MAX_PATH]; // Path name
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT FileSize; // File size
+ UINT64 UpdatedTime; // Updating date
+};
+
+
+// Virtual HUB creation history
+struct SERVER_HUB_CREATE_HISTORY
+{
+ char HubName[MAX_HUBNAME_LEN + 1];
+ UINT64 CreatedTime;
+};
+
+// Function prototype declaration
+SERVER *SiNewServer(bool bridge);
+SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server);
+void SiReleaseServer(SERVER *s);
+void SiCleanupServer(SERVER *s);
+void StStartServer(bool bridge);
+void StStopServer();
+void SiInitConfiguration(SERVER *s);
+void SiFreeConfiguration(SERVER *s);
+UINT SiWriteConfigurationFile(SERVER *s);
+void SiLoadInitialConfiguration(SERVER *s);
+bool SiLoadConfigurationFile(SERVER *s);
+bool SiLoadConfigurationFileMain(SERVER *s, FOLDER *root);
+void SiInitDefaultServerCert(SERVER *s);
+void SiInitCipherName(SERVER *s);
+void SiGenerateDefaultCert(X **server_x, K **server_k);
+void SiGenerateDefaultCertEx(X **server_x, K **server_k, char *common_name);
+void SiInitListenerList(SERVER *s);
+void SiLockListenerList(SERVER *s);
+void SiUnlockListenerList(SERVER *s);
+bool SiAddListener(SERVER *s, UINT port, bool enabled);
+bool SiAddListenerEx(SERVER *s, UINT port, bool enabled, bool disable_dos);
+bool SiEnableListener(SERVER *s, UINT port);
+bool SiDisableListener(SERVER *s, UINT port);
+bool SiDeleteListener(SERVER *s, UINT port);
+SERVER_LISTENER *SiGetListener(SERVER *s, UINT port);
+int CompareServerListener(void *p1, void *p2);
+void SiStopAllListener(SERVER *s);
+void SiInitDefaultHubList(SERVER *s);
+void SiSetDefaultHubOption(HUB_OPTION *o);
+void SiInitBridge(SERVER *s);
+void SiTest(SERVER *s);
+FOLDER *SiWriteConfigurationToCfg(SERVER *s);
+bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root);
+void SiWriteLocalBridges(FOLDER *f, SERVER *s);
+void SiLoadLocalBridges(SERVER *s, FOLDER *f);
+void SiWriteLocalBridgeCfg(FOLDER *f, LOCALBRIDGE *br);
+void SiLoadLocalBridgeCfg(SERVER *s, FOLDER *f);
+void SiWriteListeners(FOLDER *f, SERVER *s);
+void SiLoadListeners(SERVER *s, FOLDER *f);
+void SiWriteListenerCfg(FOLDER *f, SERVER_LISTENER *r);
+void SiLoadListenerCfg(SERVER *s, FOLDER *f);
+void SiWriteServerCfg(FOLDER *f, SERVER *s);
+void SiLoadServerCfg(SERVER *s, FOLDER *f);
+void SiWriteTraffic(FOLDER *parent, char *name, TRAFFIC *t);
+void SiWriteTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e);
+void SiLoadTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e);
+void SiLoadTraffic(FOLDER *parent, char *name, TRAFFIC *t);
+void SiSaverThread(THREAD *thread, void *param);
+void SiLoadLicenseManager(SERVER *s, FOLDER *f);
+void SiWriteLicenseManager(FOLDER *f, SERVER *s);
+void SiLoadL3Switchs(SERVER *s, FOLDER *f);
+void SiLoadL3SwitchCfg(L3SW *sw, FOLDER *f);
+void SiWriteL3Switchs(FOLDER *f, SERVER *s);
+void SiWriteL3SwitchCfg(FOLDER *f, L3SW *sw);
+void SiLoadIPsec(SERVER *s, FOLDER *f);
+void SiWriteIPsec(FOLDER *f, SERVER *s);
+void SiWriteHubs(FOLDER *f, SERVER *s);
+void SiLoadHubs(SERVER *s, FOLDER *f);
+void SiWriteHubCfg(FOLDER *f, HUB *h);
+void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name);
+void SiLoadHubLogCfg(HUB_LOG *g, FOLDER *f);
+void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o);
+void SiWriteHubLogCfg(FOLDER *f, HUB_LOG *g);
+void SiWriteHubLogCfgEx(FOLDER *f, HUB_LOG *g, bool el_mode);
+void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o);
+void SiWriteHubLinks(FOLDER *f, HUB *h);
+void SiLoadHubLinks(HUB *h, FOLDER *f);
+void SiWriteHubAdminOptions(FOLDER *f, HUB *h);
+void SiLoadHubAdminOptions(HUB *h, FOLDER *f);
+void SiWriteHubLinkCfg(FOLDER *f, LINK *k);
+void SiLoadHubLinkCfg(FOLDER *f, HUB *h);
+void SiWriteHubAccessLists(FOLDER *f, HUB *h);
+void SiLoadHubAccessLists(HUB *h, FOLDER *f);
+void SiWriteHubAccessCfg(FOLDER *f, ACCESS *a);
+void SiLoadHubAccessCfg(HUB *h, FOLDER *f);
+void SiWriteHubDb(FOLDER *f, HUBDB *db, bool no_save_ac_list);
+void SiLoadHubDb(HUB *h, FOLDER *f);
+void SiWriteUserList(FOLDER *f, LIST *o);
+void SiLoadUserList(HUB *h, FOLDER *f);
+void SiWriteUserCfg(FOLDER *f, USER *u);
+void SiLoadUserCfg(HUB *h, FOLDER *f);
+void SiWriteGroupList(FOLDER *f, LIST *o);
+void SiLoadGroupList(HUB *h, FOLDER *f);
+void SiWriteGroupCfg(FOLDER *f, USERGROUP *g);
+void SiLoadGroupCfg(HUB *h, FOLDER *f);
+void SiWriteCertList(FOLDER *f, LIST *o);
+void SiLoadCertList(LIST *o, FOLDER *f);
+void SiWriteCrlList(FOLDER *f, LIST *o);
+void SiLoadCrlList(LIST *o, FOLDER *f);
+void SiWriteAcList(FOLDER *f, LIST *o);
+void SiLoadAcList(LIST *o, FOLDER *f);
+void SiWritePolicyCfg(FOLDER *f, POLICY *p, bool cascade_mode);
+void SiLoadPolicyCfg(POLICY *p, FOLDER *f);
+void SiLoadSecureNAT(HUB *h, FOLDER *f);
+void SiWriteSecureNAT(HUB *h, FOLDER *f);
+void SiRebootServerEx(bool bridge, bool reset_setting);
+void SiRebootServer(bool bridge);
+void SiRebootServerThread(THREAD *thread, void *param);
+void StInit();
+void StFree();
+SERVER *StGetServer();
+void SiSetServerType(SERVER *s, UINT type,
+ UINT ip, UINT num_port, UINT *ports,
+ char *controller_name, UINT controller_port, UCHAR *password, UINT weight, bool controller_only);
+FARM_CONTROLLER *SiStartConnectToController(SERVER *s);
+void SiStopConnectToController(FARM_CONTROLLER *f);
+void SiFarmServ(SERVER *server, SOCK *sock, X *cert, UINT ip, UINT num_port, UINT *ports, char *hostname, UINT point, UINT weight, UINT max_sessions);
+int CompareHubList(void *p1, void *p2);
+void SiFarmServMain(SERVER *server, SOCK *sock, FARM_MEMBER *f);
+FARM_TASK *SiFarmServPostTask(FARM_MEMBER *f, PACK *request);
+PACK *SiFarmServWaitTask(FARM_TASK *t);
+PACK *SiExecTask(FARM_MEMBER *f, PACK *p);
+PACK *SiCallTask(FARM_MEMBER *f, PACK *p, char *taskname);
+FARM_TASK *SiCallTaskAsyncBegin(FARM_MEMBER *f, PACK *p, char *taskname);
+PACK *SiCallTaskAsyncEnd(CEDAR *c, FARM_TASK *t);
+void SiAcceptTasksFromController(FARM_CONTROLLER *f, SOCK *sock);
+void SiAcceptTasksFromControllerMain(FARM_CONTROLLER *f, SOCK *sock);
+PACK *SiCalledTask(FARM_CONTROLLER *f, PACK *p, char *taskname);
+void SiHubOnlineProc(HUB *h);
+void SiHubOfflineProc(HUB *h);
+FARM_MEMBER *SiGetNextFarmMember(SERVER *s, CONNECTION *c, HUB *h);
+bool SiGetMemberSelectorUrl(char *url, UINT url_size);
+void SiCallCreateHub(SERVER *s, FARM_MEMBER *f, HUB *h);
+void SiCallUpdateHub(SERVER *s, FARM_MEMBER *f, HUB *h);
+void SiCallDeleteHub(SERVER *s, FARM_MEMBER *f, HUB *h);
+void SiCallEnumSession(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_SESSION *t);
+void SiCallEnumNat(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_NAT *t);
+void SiCallEnumDhcp(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_DHCP *t);
+void SiCallGetNatStatus(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_NAT_STATUS *t);
+void SiCallEnumMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_MAC_TABLE *t);
+void SiCallEnumIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_IP_TABLE *t);
+void SiCallDeleteSession(SERVER *s, FARM_MEMBER *f, char *hubname, char *session_name);
+void SiCallCreateTicket(SERVER *s, FARM_MEMBER *f, char *hubname, char *username, char *realusername, POLICY *policy, UCHAR *ticket, UINT counter, char *groupname);
+void SiCallDeleteMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key);
+void SiCallDeleteIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key);
+void SiCalledCreateHub(SERVER *s, PACK *p);
+void SiCalledUpdateHub(SERVER *s, PACK *p);
+void SiCalledDeleteHub(SERVER *s, PACK *p);
+void SiCalledDeleteSession(SERVER *s, PACK *p);
+void SiCalledDeleteMacTable(SERVER *s, PACK *p);
+void SiCalledDeleteIpTable(SERVER *s, PACK *p);
+PACK *SiCalledCreateTicket(SERVER *s, PACK *p);
+PACK *SiCalledEnumSession(SERVER *s, PACK *p);
+PACK *SiCalledEnumNat(SERVER *s, PACK *p);
+PACK *SiCalledEnumDhcp(SERVER *s, PACK *p);
+PACK *SiCalledGetNatStatus(SERVER *s, PACK *p);
+PACK *SiCalledEnumMacTable(SERVER *s, PACK *p);
+PACK *SiCalledEnumIpTable(SERVER *s, PACK *p);
+void SiCalledEnumHub(SERVER *s, PACK *p, PACK *req);
+void SiPackAddCreateHub(PACK *p, HUB *h);
+FARM_MEMBER *SiGetHubHostingMember(SERVER *s, HUB *h, bool admin_mode, CONNECTION *c);
+void SiCallEnumHub(SERVER *s, FARM_MEMBER *f);
+void SiCallEnumHubBegin(SERVER *s, FARM_MEMBER *f);
+void SiCallEnumHubEnd(SERVER *s, FARM_MEMBER *f);
+void SiStartFarmControl(SERVER *s);
+void SiStopFarmControl(SERVER *s);
+void SiFarmControlThread(THREAD *thread, void *param);
+void SiAccessListToPack(PACK *p, LIST *o);
+void SiAccessToPack(PACK *p, ACCESS *a, UINT i, UINT total);
+ACCESS *SiPackToAccess(PACK *p, UINT i);
+UINT SiNumAccessFromPack(PACK *p);
+void SiHubUpdateProc(HUB *h);
+bool SiCheckTicket(HUB *h, UCHAR *ticket, char *username, UINT username_size, char *usernamereal, UINT usernamereal_size, POLICY *policy, char *sessionname, UINT sessionname_size, char *groupname, UINT groupname_size);
+UINT SiGetPoint(SERVER *s);
+UINT SiCalcPoint(SERVER *s, UINT num, UINT weight);
+bool SiCallGetSessionStatus(SERVER *s, FARM_MEMBER *f, RPC_SESSION_STATUS *t);
+PACK *SiCalledGetSessionStatus(SERVER *s, PACK *p);
+bool SiCallEnumLogFileList(SERVER *s, FARM_MEMBER *f, RPC_ENUM_LOG_FILE *t, char *hubname);
+PACK *SiCalledEnumLogFileList(SERVER *s, PACK *p);
+bool SiCallReadLogFile(SERVER *s, FARM_MEMBER *f, RPC_READ_LOG_FILE *t);
+PACK *SiCalledReadLogFile(SERVER *s, PACK *p);
+int CmpLogFile(void *p1, void *p2);
+LIST *EnumLogFile(char *hubname);
+void EnumLogFileDir(LIST *o, char *dirname);
+void FreeEnumLogFile(LIST *o);
+bool CheckLogFileNameFromEnumList(LIST *o, char *name, char *server_name);
+void AdjoinEnumLogFile(LIST *o, LIST *src);
+void IncrementServerConfigRevision(SERVER *s);
+void GetServerProductName(SERVER *s, char *name, UINT size);
+void GetServerProductNameInternal(SERVER *s, char *name, UINT size);
+
+
+void SiSetSysLogSetting(SERVER *s, SYSLOG_SETTING *setting);
+void SiGetSysLogSetting(SERVER *s, SYSLOG_SETTING *setting);
+void SiWriteSysLog(SERVER *s, char *typestr, char *hubname, wchar_t *message);
+UINT SiGetSysLogSaveStatus(SERVER *s);
+void SiInitDeadLockCheck(SERVER *s);
+void SiFreeDeadLockCheck(SERVER *s);
+void SiDeadLockCheckThread(THREAD *t, void *param);
+void SiCheckDeadLockMain(SERVER *s, UINT timeout);
+void SiDebugLog(SERVER *s, char *msg);
+UINT SiDebug(SERVER *s, RPC_TEST *ret, UINT i, char *str);
+UINT SiDebugProcHelloWorld(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcExit(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcDump(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcRestorePriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcSetHighPriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcGetExeFileName(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcCrash(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcGetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcSetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcGetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcSetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+
+typedef UINT (SI_DEBUG_PROC)(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+
+CAPS *NewCaps(char *name, UINT value);
+void FreeCaps(CAPS *c);
+CAPSLIST *NewCapsList();
+int CompareCaps(void *p1, void *p2);
+void AddCaps(CAPSLIST *caps, CAPS *c);
+CAPS *GetCaps(CAPSLIST *caps, char *name);
+void FreeCapsList(CAPSLIST *caps);
+bool GetCapsBool(CAPSLIST *caps, char *name);
+UINT GetCapsInt(CAPSLIST *caps, char *name);
+void AddCapsBool(CAPSLIST *caps, char *name, bool b);
+void AddCapsInt(CAPSLIST *caps, char *name, UINT i);
+void InRpcCapsList(CAPSLIST *t, PACK *p);
+void OutRpcCapsList(PACK *p, CAPSLIST *t);
+void FreeRpcCapsList(CAPSLIST *t);
+void InitCapsList(CAPSLIST *t);
+void InRpcSysLogSetting(SYSLOG_SETTING *t, PACK *p);
+void OutRpcSysLogSetting(PACK *p, SYSLOG_SETTING *t);
+
+void GetServerCaps(SERVER *s, CAPSLIST *t);
+bool GetServerCapsBool(SERVER *s, char *name);
+UINT GetServerCapsInt(SERVER *s, char *name);
+void GetServerCapsMain(SERVER *s, CAPSLIST *t);
+void InitServerCapsCache(SERVER *s);
+void FreeServerCapsCache(SERVER *s);
+void DestroyServerCapsCache(SERVER *s);
+
+
+bool IsAdminPackSupportedServerProduct(char *name);
+
+void SiInitHubCreateHistory(SERVER *s);
+void SiFreeHubCreateHistory(SERVER *s);
+void SiDeleteOldHubCreateHistory(SERVER *s);
+void SiAddHubCreateHistory(SERVER *s, char *name);
+void SiDelHubCreateHistory(SERVER *s, char *name);
+bool SiIsHubRegistedOnCreateHistory(SERVER *s, char *name);
+
+UINT SiGetServerNumUserObjects(SERVER *s);
+bool SiTooManyUserObjectsInServer(SERVER *s, bool oneMore);
+
+void SiGetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c);
+void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c);
+
+bool SiCanOpenVpnOverDnsPort();
+bool SiCanOpenVpnOverIcmpPort();
+void SiApplySpecialListenerStatus(SERVER *s);
+
+bool SiIsAzureEnabled(SERVER *s);
+bool SiIsAzureSupported(SERVER *s);
+void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status);
+void SiSetAzureEnable(SERVER *s, bool enabled);
+bool SiGetAzureEnable(SERVER *s);
+
+#endif // SERVER_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c
new file mode 100644
index 00000000..685529d2
--- /dev/null
+++ b/src/Cedar/Session.c
@@ -0,0 +1,2242 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Session.c
+// Session Manager
+
+#include "CedarPch.h"
+
+// Main routine of the session
+void SessionMain(SESSION *s)
+{
+ CONNECTION *c;
+ POLICY *policy;
+ UINT64 now;
+ UINT i = 0;
+ PACKET_ADAPTER *pa;
+ bool pa_inited = false;
+ UINT packet_size;
+ void *packet;
+ bool packet_put;
+ bool pa_fail = false;
+ UINT test = 0;
+ bool update_hub_last_comm = false;
+ UINT err = ERR_SESSION_TIMEOUT;
+ UINT64 next_black_list_check = 0;
+ UINT64 next_update_hub_last_comm = 0;
+ UINT64 auto_disconnect_tick = 0;
+ bool block_all_packets = false;
+ UINT64 next_check_block_all_packets = 0;
+ TRAFFIC t;
+ SOCK *msgdlg_sock = NULL;
+ SOCK *nicinfo_sock = NULL;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+ Debug("SessionMain: %s\n", s->Name);
+
+ Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+ // Generate a string from the session key
+ BinToStr(s->SessionKeyStr, sizeof(s->SessionKeyStr), s->SessionKey, sizeof(s->SessionKey));
+
+ // Reset the number of retries
+ s->CurrentRetryCount = 0;
+ s->ConnectSucceed = true;
+ s->SessionTimeOuted = false;
+ s->NumDisconnected = 0;
+
+ c = s->Connection;
+ policy = s->Policy;
+
+ // Initialize the packet adapter
+ pa = s->PacketAdapter;
+ if (pa->Init(s) == false)
+ {
+ // Initialization Failed
+ if (s->VLanDeviceErrorCount >= 2)
+ {
+ s->ForceStopFlag = true;
+ }
+ else
+ {
+ s->VLanDeviceErrorCount++;
+ }
+ err = ERR_DEVICE_DRIVER_ERROR;
+ goto CLEANUP;
+ }
+ pa_inited = true;
+
+ if (s->BridgeMode == false)
+ {
+ s->Cancel2 = pa->GetCancel(s);
+ }
+ else
+ {
+ CANCEL *c = pa->GetCancel(s);
+ CANCEL *old = s->Cancel1;
+ s->Cancel1 = c;
+ ReleaseCancel(old);
+ }
+
+ s->RetryFlag = false;
+
+ s->LastCommTime = Tick64();
+ if (s->ServerMode == false)
+ {
+ s->NextConnectionTime = Tick64() + (UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000);
+ }
+
+ s->NumConnectionsEatablished++;
+ s->CurrentConnectionEstablishTime = Tick64();
+ if (s->FirstConnectionEstablisiedTime == 0)
+ {
+ s->FirstConnectionEstablisiedTime = Tick64();
+ }
+
+ if (s->ServerMode == false && s->Cedar->Client != NULL)
+ {
+ if (s->Policy != NULL)
+ {
+ if (s->Policy->AutoDisconnect)
+ {
+ auto_disconnect_tick = s->CurrentConnectionEstablishTime +
+ (UINT64)s->Policy->AutoDisconnect * 1000ULL;
+ }
+ }
+ }
+
+ s->LastIncrementTraffic = Tick64();
+
+ c->Err = ERR_SESSION_TIMEOUT;
+ s->VLanDeviceErrorCount = 0;
+
+ s->LastTryAddConnectTime = Tick64();
+
+ Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+ if (policy != NULL)
+ {
+ // Determine the mode by referencing the contents of the policy
+ if (policy->MonitorPort)
+ {
+ s->IsMonitorMode = true;
+ }
+
+ if (policy->NoRouting == false || policy->NoBridge == false)
+ {
+ s->IsBridgeMode = true;
+ }
+ }
+
+ if (s->ServerMode == false && s->Cedar->Client != NULL)
+ {
+ if (IsEmptyUniStr(s->Client_Message) == false)
+ {
+ UI_MSG_DLG dlg;
+
+ Zero(&dlg, sizeof(dlg));
+ if (s->ClientOption != NULL)
+ {
+ StrCpy(dlg.HubName, sizeof(dlg.HubName), s->ClientOption->HubName);
+ StrCpy(dlg.ServerName, sizeof(dlg.ServerName), s->ClientOption->Hostname);
+ }
+
+ dlg.Msg = s->Client_Message;
+
+ msgdlg_sock = CncMsgDlg(&dlg);
+ }
+
+ if (s->Win32HideNicInfoWindow == false)
+ {
+ UI_NICINFO info;
+
+ Zero(&info, sizeof(info));
+ if (s->ClientOption != NULL)
+ {
+ StrCpy(info.NicName, sizeof(info.NicName), s->ClientOption->DeviceName);
+ UniStrCpy(info.AccountName, sizeof(info.AccountName), s->ClientOption->AccountName);
+ }
+
+ nicinfo_sock = CncNicInfo(&info);
+ }
+ }
+
+ while (true)
+ {
+ now = Tick64();
+ Zero(&t, sizeof(t));
+
+
+ if (next_update_hub_last_comm == 0 ||
+ (next_update_hub_last_comm <= now))
+ {
+ next_update_hub_last_comm = now + 1000;
+
+ if (s->Hub != NULL)
+ {
+ if (update_hub_last_comm)
+ {
+ Lock(s->Hub->lock);
+ {
+ s->Hub->LastCommTime = SystemTime64();
+ }
+ Unlock(s->Hub->lock);
+
+ update_hub_last_comm = false;
+ }
+ }
+ }
+
+
+ if (s->InProcMode)
+ {
+ if (c->TubeSock == NULL || IsTubeConnected(c->TubeSock->SendTube) == false || IsTubeConnected(c->TubeSock->RecvTube) == false)
+ {
+ // Disconnection occurs in the in-process mode
+ err = ERR_DISCONNECTED;
+ pa_fail = true;
+ }
+ }
+
+ if (s->IsRUDPSession)
+ {
+ if (s->NumDisconnected >= 1 && s->EnableUdpRecovery == false)
+ {
+ // Disconnection occurs in the R-UDP session (UDP recovery is invalid)
+ err = ERR_DISCONNECTED;
+ pa_fail = true;
+ }
+ }
+
+ // Chance of additional connection
+ ClientAdditionalConnectChance(s);
+
+ // Receive a block
+ ConnectionReceive(c, s->Cancel1, s->Cancel2);
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->FatalError)
+ {
+ // A serious error occurs during sending any data on UDP socket
+ // in the case of using UDP acceleration function
+ err = ERR_DISCONNECTED;
+ pa_fail = true;
+ }
+
+ // Pass the received block to the PacketAdapter
+ LockQueue(c->ReceivedBlocks);
+ {
+ BLOCK *b;
+ packet_put = false;
+ while (true)
+ {
+ b = GetNext(c->ReceivedBlocks);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ PROBE_DATA2("GetNext", b->Buf, b->Size);
+
+ update_hub_last_comm = true;
+
+ if (s->ServerMode == false && b->Size >= 14)
+ {
+ if (b->Buf[0] & 0x40)
+ {
+ t.Recv.BroadcastCount++;
+ t.Recv.BroadcastBytes += (UINT64)b->Size;
+ }
+ else
+ {
+ t.Recv.UnicastCount++;
+ t.Recv.UnicastBytes += (UINT64)b->Size;
+ }
+ }
+
+ packet_put = true;
+ PROBE_DATA2("pa->PutPacket", b->Buf, b->Size);
+ if (pa->PutPacket(s, b->Buf, b->Size) == false)
+ {
+ pa_fail = true;
+ err = ERR_DEVICE_DRIVER_ERROR;
+ Free(b->Buf);
+ Debug(" Error: pa->PutPacket(Packet) Failed.\n");
+ }
+ Free(b);
+ }
+
+ if (packet_put || s->ServerMode)
+ {
+ PROBE_DATA2("pa->PutPacket", NULL, 0);
+ if (pa->PutPacket(s, NULL, 0) == false)
+ {
+ Debug(" Error: pa->PutPacket(NULL) Failed.\n");
+ pa_fail = true;
+ err = ERR_DEVICE_DRIVER_ERROR;
+ }
+ }
+ }
+ UnlockQueue(c->ReceivedBlocks);
+
+ // Add the packet to be transmitted to SendBlocks by acquiring from PacketAdapter
+ LockQueue(c->SendBlocks);
+ {
+ UINT i, max_num = MAX_SEND_SOCKET_QUEUE_NUM;
+ i = 0;
+ while (packet_size = pa->GetNextPacket(s, &packet))
+ {
+ BLOCK *b;
+ if (packet_size == INFINITE)
+ {
+ err = ERR_DEVICE_DRIVER_ERROR;
+ pa_fail = true;
+ Debug(" Error: pa->GetNextPacket() Failed.\n");
+ break;
+ }
+
+ update_hub_last_comm = true;
+
+ if ((c->CurrentSendQueueSize > MAX_BUFFERING_PACKET_SIZE) ||
+ block_all_packets)
+ {
+// WHERE;
+ // Discard because it exceeded the buffer size limit
+ Free(packet);
+ }
+ else
+ {
+ bool priority;
+ // Buffering
+ if (s->ServerMode == false && packet_size >= 14)
+ {
+ UCHAR *buf = (UCHAR *)packet;
+ if (buf[0] & 0x01)
+ {
+ t.Send.BroadcastCount++;
+ t.Send.BroadcastBytes += (UINT64)packet_size;
+ }
+ else
+ {
+ t.Send.UnicastCount++;
+ t.Send.UnicastBytes += (UINT64)packet_size;
+ }
+ }
+ priority = IsPriorityHighestPacketForQoS(packet, packet_size);
+ b = NewBlock(packet, packet_size, s->UseCompress ? 1 : 0);
+ b->PriorityQoS = priority;
+ c->CurrentSendQueueSize += b->Size;
+
+ if (b->PriorityQoS && c->Protocol == CONNECTION_TCP && s->QoS)
+ {
+ InsertQueue(c->SendBlocks2, b);
+ }
+ else
+ {
+ InsertQueue(c->SendBlocks, b);
+ }
+ }
+ i++;
+ if (i >= max_num)
+ {
+ break;
+ }
+ }
+ }
+ UnlockQueue(c->SendBlocks);
+
+ AddTrafficForSession(s, &t);
+
+ // Send a block
+ ConnectionSend(c);
+
+ // Determine the automatic disconnection
+ if (auto_disconnect_tick != 0 && auto_disconnect_tick <= Tick64())
+ {
+ err = ERR_AUTO_DISCONNECTED;
+ s->CurrentRetryCount = INFINITE;
+ break;
+ }
+
+ // Stop determination
+ if (s->Halt)
+ {
+ if (s->ForceStopFlag)
+ {
+ err = ERR_USER_CANCEL;
+ }
+ break;
+ }
+
+ // Get the current time
+ now = Tick64();
+
+ // Increments the number of logins for user object and Virtual HUB object.
+ // (It's incremented only if the time 30 seconds passed after connection.
+ // If not do this, it will be incremented on DoS attacks or any error.)
+ if (s->NumLoginIncrementTick != 0 && s->NumLoginIncrementTick <= now)
+ {
+ s->NumLoginIncrementTick = 0;
+
+ if (s->NumLoginIncrementHubObject != NULL)
+ {
+ s->NumLoginIncrementHubObject->NumLogin++;
+ }
+
+ if (s->NumLoginIncrementUserObject != NULL)
+ {
+ s->NumLoginIncrementUserObject->NumLogin++;
+ }
+ }
+
+ if (s->ServerMode)
+ {
+ HUB *hub;
+
+ // Update of traffic data of the user
+ if ((s->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
+ {
+ IncrementUserTraffic(s->Hub, s->UserNameReal, s);
+ s->LastIncrementTraffic = now;
+ }
+
+ hub = s->Hub;
+
+ if (hub != NULL)
+ {
+ Lock(hub->lock);
+ {
+ if ((hub->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
+ {
+ IncrementHubTraffic(s->Hub);
+ hub->LastIncrementTraffic = now;
+ }
+ }
+ Unlock(hub->lock);
+ }
+ }
+
+ if (s->LinkModeServer == false && s->SecureNATMode == false && s->BridgeMode == false && s->L3SwitchMode == false && s->InProcMode == false)
+ {
+ bool timeouted = false;
+
+ if ((now > s->LastCommTime) && ((now - s->LastCommTime) >= ((UINT64)s->Timeout)))
+ {
+ // When communication is not possible for the predetermined time
+ timeouted = true;
+ WHERE;
+ }
+
+ if (s->ServerMode == false && s->ClientOption != NULL && s->ClientOption->ConnectionDisconnectSpan == 0)
+ {
+ if (LIST_NUM(s->Connection->Tcp->TcpSockList) < s->MaxConnection)
+ {
+ if ((s->LastTryAddConnectTime +
+ (UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2))
+ <= Tick64())
+ {
+ if (s->IsRUDPSession == false || LIST_NUM(s->Connection->Tcp->TcpSockList) == 0)
+ {
+ timeouted = true;
+ WHERE;
+ }
+ }
+ }
+ }
+
+ if (timeouted)
+ {
+ // Timeout occurs
+ Debug("** Session Timeouted.\n");
+ s->SessionTimeOuted = true;
+ err = ERR_SESSION_TIMEOUT;
+ }
+ }
+
+ // Time-out decision
+ if (pa_fail || s->SessionTimeOuted)
+ {
+ s->Halt = true;
+ s->RetryFlag = true; // Retry flag
+ break;
+ }
+ }
+
+CLEANUP:
+ Debug("Session %s Finishing...\n", s->Name);
+
+ // Remove from the session list of the HUB
+ if (s->ServerMode)
+ {
+ // Update the user information
+ IncrementUserTraffic(s->Hub, s->UserNameReal, s);
+
+ DelSession(s->Hub, s);
+ }
+
+ s->ConnectSucceed = false;
+ Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+ if (s->Connection)
+ {
+ s->Connection->Halt = true;
+ }
+
+ // Release the packet adapter
+ if (pa_inited)
+ {
+ pa->Free(s);
+ }
+
+ if (s->ServerMode == false)
+ {
+ // Cancel to make all additional connection
+ StopAllAdditionalConnectThread(s->Connection);
+ }
+
+ if (s->BridgeMode)
+ {
+ // Terminate the bridge
+ if (s->Bridge->Active)
+ {
+ CloseEth(s->Bridge->Eth);
+ s->Bridge->Eth = NULL;
+ }
+ }
+
+ if (s->Cancel2 != NULL)
+ {
+ // Release the Cancel 2
+ ReleaseCancel(s->Cancel2);
+ s->Cancel2 = NULL;
+ }
+
+ // Terminate the connection
+ EndTunnelingMode(c);
+
+ if (nicinfo_sock != NULL)
+ {
+ CncNicInfoFree(nicinfo_sock);
+ }
+
+ if (msgdlg_sock != NULL)
+ {
+ CndMsgDlgFree(msgdlg_sock);
+ }
+
+ c->Err = err;
+}
+
+// Get the time for the next delayed packet
+UINT GetNextDelayedPacketTickDiff(SESSION *s)
+{
+ UINT i;
+ UINT ret = 0x7fffffff;
+ UINT64 now;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ if (LIST_NUM(s->DelayedPacketList) >= 1)
+ {
+ now = TickHighres64();
+
+ LockList(s->DelayedPacketList);
+ {
+ for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
+ {
+ PKT *p = LIST_DATA(s->DelayedPacketList, i);
+ UINT64 t = p->DelayedForwardTick;
+ UINT d = 0x7fffffff;
+
+ if (now >= t)
+ {
+ d = 0;
+ }
+ else
+ {
+ d = (UINT)(t - now);
+ }
+
+ ret = MIN(ret, d);
+ }
+ }
+ UnlockList(s->DelayedPacketList);
+ }
+
+ return ret;
+}
+
+// Determine whether the packet have priority in the VoIP / QoS function
+bool IsPriorityHighestPacketForQoS(void *data, UINT size)
+{
+ UCHAR *buf;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return false;
+ }
+
+ buf = (UCHAR *)data;
+ if (size >= 16)
+ {
+ if (buf[12] == 0x08 && buf[13] == 0x00 && buf[15] != 0x00 && buf[15] != 0x08)
+ {
+ // IPv4 packet and ToS != 0
+ return true;
+ }
+
+ if (size >= 34 && size <= 128)
+ {
+ if (buf[12] == 0x08 && buf[13] == 0x00 && buf[23] == 0x01)
+ {
+ // IMCPv4 packet
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Update the traffic information of the user
+void IncrementUserTraffic(HUB *hub, char *username, SESSION *s)
+{
+ TRAFFIC report_traffic;
+ // Validate arguments
+ if (hub == NULL || username == NULL || s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->TrafficLock);
+ {
+ // Calculate the traffic information (difference between last time) to be reported
+ report_traffic.Send.BroadcastBytes =
+ s->Traffic->Send.BroadcastBytes - s->OldTraffic->Send.BroadcastBytes;
+ report_traffic.Send.BroadcastCount =
+ s->Traffic->Send.BroadcastCount - s->OldTraffic->Send.BroadcastCount;
+ report_traffic.Send.UnicastBytes =
+ s->Traffic->Send.UnicastBytes - s->OldTraffic->Send.UnicastBytes;
+ report_traffic.Send.UnicastCount =
+ s->Traffic->Send.UnicastCount - s->OldTraffic->Send.UnicastCount;
+ report_traffic.Recv.BroadcastBytes =
+ s->Traffic->Recv.BroadcastBytes - s->OldTraffic->Recv.BroadcastBytes;
+ report_traffic.Recv.BroadcastCount =
+ s->Traffic->Recv.BroadcastCount - s->OldTraffic->Recv.BroadcastCount;
+ report_traffic.Recv.UnicastBytes =
+ s->Traffic->Recv.UnicastBytes - s->OldTraffic->Recv.UnicastBytes;
+ report_traffic.Recv.UnicastCount =
+ s->Traffic->Recv.UnicastCount - s->OldTraffic->Recv.UnicastCount;
+ Copy(s->OldTraffic, s->Traffic, sizeof(TRAFFIC));
+
+ if (hub->FarmMember == false)
+ {
+ // Update the user information in the local database if it is not a farm member
+ AcLock(hub);
+ {
+ USER *u = AcGetUser(hub, username);
+ if (u != NULL)
+ {
+ Lock(u->lock);
+ {
+ AddTraffic(u->Traffic, &report_traffic);
+ }
+ Unlock(u->lock);
+ if (u->Group != NULL)
+ {
+ Lock(u->Group->lock);
+ {
+ AddTraffic(u->Group->Traffic, &report_traffic);
+ }
+ Unlock(u->Group->lock);
+ }
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(hub);
+ }
+ else
+ {
+ // Update the traffic difference report list in the case of farm member
+ AddTrafficDiff(hub, username, TRAFFIC_DIFF_USER, &report_traffic);
+ }
+ }
+ Unlock(s->TrafficLock);
+}
+
+// Cummulate the traffic information of the connection
+void AddTrafficForSession(SESSION *s, TRAFFIC *t)
+{
+ HUB *h;
+ TRAFFIC t2;
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Lock(s->TrafficLock);
+ {
+ AddTraffic(s->Traffic, t);
+ }
+ Unlock(s->TrafficLock);
+
+ if (s->ServerMode)
+ {
+ Copy(&t2.Recv, &t->Send, sizeof(TRAFFIC_ENTRY));
+ Copy(&t2.Send, &t->Recv, sizeof(TRAFFIC_ENTRY));
+ Lock(s->Cedar->TrafficLock);
+ {
+ AddTraffic(s->Cedar->Traffic, &t2);
+ }
+ Unlock(s->Cedar->TrafficLock);
+
+ h = s->Hub;
+ Lock(h->TrafficLock);
+ {
+ AddTraffic(h->Traffic, &t2);
+ }
+ Unlock(h->TrafficLock);
+ }
+}
+
+// A chance to establish an additional connection for client
+void ClientAdditionalConnectChance(SESSION *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->ServerMode)
+ {
+ // Do not connect additionally in the server mode
+ return;
+ }
+ if (s->Connection->Protocol != CONNECTION_TCP)
+ {
+ // Connect additionally only in the case of TCP protocol
+ return;
+ }
+ if (s->IsRUDPSession && s->EnableUdpRecovery == false)
+ {
+ // Do not connect additionally if the UDP recovery is disabled in the case of R-UDP session
+ return;
+ }
+
+ if (s->IsRUDPSession && (s->Connection->AdditionalConnectionFailedCounter > MAX_ADDITONAL_CONNECTION_FAILED_COUNTER))
+ {
+ // Not to make a large amount of repeated connection retry within a certain time in the case of R-UDP session
+ return;
+ }
+
+ while (true)
+ {
+ if (s->Halt)
+ {
+ return;
+ }
+ // Consider whether there is a need to put an additional connection
+ // by examining the number of current connections and MaxConnection property
+ if (Count(s->Connection->CurrentNumConnection) < s->MaxConnection)
+ {
+ // Get the current time
+ UINT64 now = Tick64();
+
+ // Examine the NextConnectionTime, and if the time passed,
+ // attempt to make a connection
+ if (s->NextConnectionTime == 0 ||
+ s->ClientOption->AdditionalConnectionInterval == 0 ||
+ (s->NextConnectionTime <= now))
+ {
+ // Start the work to put an additional connection
+ s->NextConnectionTime = now + (UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000);
+ SessionAdditionalConnect(s);
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+// Release the packet adapter
+void FreePacketAdapter(PACKET_ADAPTER *pa)
+{
+ // Validate arguments
+ if (pa == NULL)
+ {
+ return;
+ }
+
+ Free(pa);
+}
+
+// Create a new packet adapter
+PACKET_ADAPTER *NewPacketAdapter(PA_INIT *init, PA_GETCANCEL *getcancel, PA_GETNEXTPACKET *getnext,
+ PA_PUTPACKET *put, PA_FREE *free)
+{
+ PACKET_ADAPTER *pa;
+ // Validate arguments
+ if (init == NULL || getcancel == NULL || getnext == NULL || put == NULL || free == NULL)
+ {
+ return NULL;
+ }
+
+ pa = ZeroMalloc(sizeof(PACKET_ADAPTER));
+
+ pa->Init = init;
+ pa->Free = free;
+ pa->GetCancel = getcancel;
+ pa->GetNextPacket = getnext;
+ pa->PutPacket = put;
+
+ return pa;
+}
+
+// Thread for putting an additional connection
+void ClientAdditionalThread(THREAD *t, void *param)
+{
+ SESSION *s;
+ CONNECTION *c;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ s = (SESSION *)param;
+
+ s->LastTryAddConnectTime = Tick64();
+
+ c = s->Connection;
+ // Increment of connection counter
+ Inc(c->CurrentNumConnection);
+ LockList(c->ConnectingThreads);
+ {
+ // Add to processing thread
+ Add(c->ConnectingThreads, t);
+ AddRef(t->ref);
+ }
+ UnlockList(c->ConnectingThreads);
+
+ // Notify the completion of initialization
+ NoticeThreadInit(t);
+
+ Debug("Additional Connection #%u\n", Count(c->CurrentNumConnection));
+
+ // Put an additional connection
+ if (ClientAdditionalConnect(c, t) == false)
+ {
+ // Decrement the counter which is currently processing
+ Dec(c->CurrentNumConnection);
+
+ if (c->AdditionalConnectionFailedCounter == 0)
+ {
+ c->LastCounterResetTick = Tick64();
+ }
+
+ c->AdditionalConnectionFailedCounter++;
+
+ if ((c->LastCounterResetTick + (UINT64)ADDITIONAL_CONNECTION_COUNTER_RESET_INTERVAL) <= Tick64())
+ {
+ // Reset the number of failures periodically
+ c->AdditionalConnectionFailedCounter = 0;
+ c->LastCounterResetTick = Tick64();
+ }
+ }
+ else
+ {
+ s->LastTryAddConnectTime = Tick64();
+ c->AdditionalConnectionFailedCounter = 0;
+ c->LastCounterResetTick = Tick64();
+ }
+
+ // Remove from the processing thread
+ LockList(c->ConnectingThreads);
+ {
+ // Remove from the processing thread
+ if (Delete(c->ConnectingThreads, t))
+ {
+ ReleaseThread(t);
+ }
+ }
+ UnlockList(c->ConnectingThreads);
+ ReleaseSession(s);
+}
+
+// Put an additional connection from the client to the server
+void SessionAdditionalConnect(SESSION *s)
+{
+ THREAD *t;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // s->LastTryAddConnectTime = Tick64();
+
+ AddRef(s->ref);
+ t = NewThread(ClientAdditionalThread, (void *)s);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+}
+
+// Connect the client session to the server
+bool SessionConnect(SESSION *s)
+{
+ CONNECTION *c;
+ bool ret = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ s->ClientStatus = CLIENT_STATUS_CONNECTING;
+
+ Debug("SessionConnect() Started.\n");
+
+ // Initialize the session
+ Lock(s->lock);
+ {
+ s->Err = ERR_NO_ERROR;
+ if (s->Policy != NULL)
+ {
+ Free(s->Policy);
+ s->Policy = NULL;
+ }
+ }
+ Unlock(s->lock);
+
+ s->CancelConnect = false;
+
+ // Create a Client Connection
+ c = NewClientConnection(s);
+ s->Connection = c;
+
+ // Connect the client to the server
+ ret = ClientConnect(c);
+ s->Err = c->Err;
+
+ s->CancelConnect = false;
+
+ if (s->Cedar->Client != NULL)
+ {
+ if (s->Policy != NULL)
+ {
+ if (s->Policy->NoSavePassword)
+ {
+ s->Client_NoSavePassword = true;
+
+ if (s->Account != NULL)
+ {
+ Lock(s->Account->lock);
+ {
+ if (s->Account->ClientAuth != NULL)
+ {
+ if (s->Account->ClientAuth->AuthType == AUTHTYPE_PASSWORD ||
+ s->Account->ClientAuth->AuthType == AUTHTYPE_RADIUS)
+ {
+ Zero(s->Account->ClientAuth->HashedPassword, sizeof(s->Account->ClientAuth->HashedPassword));
+ Zero(s->Account->ClientAuth->PlainPassword, sizeof(s->Account->ClientAuth->PlainPassword));
+ }
+ }
+ }
+ Unlock(s->Account->lock);
+
+ CiSaveConfigurationFile(s->Cedar->Client);
+ }
+ }
+ }
+ }
+
+ if (c->ClientConnectError_NoSavePassword)
+ {
+ s->Client_NoSavePassword = true;
+ }
+
+ // Release the client connection
+ s->Connection = NULL;
+ ReleaseConnection(c);
+
+ Lock(s->lock);
+ {
+ if (s->Policy != NULL)
+ {
+ Free(s->Policy);
+ s->Policy = NULL;
+ }
+ }
+ Unlock(s->lock);
+
+ return ret;
+}
+
+// Stop the session
+void StopSession(SESSION *s)
+{
+ StopSessionEx(s, false);
+}
+void StopSessionEx(SESSION *s, bool no_wait)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Halting flag
+ s->UserCanceled = true;
+ s->CancelConnect = true;
+ s->Halt = true;
+
+ Debug("Stop Session %s\n", s->Name);
+
+ // Cancel
+ Cancel(s->Cancel1);
+
+ // Event
+ Set(s->HaltEvent);
+
+ if (s->ServerMode == false)
+ {
+ // Client mode
+ if (s->Connection)
+ {
+ StopConnection(s->Connection, no_wait);
+ }
+ }
+ else
+ {
+ // Server mode
+ if (s->Connection)
+ {
+ StopConnection(s->Connection, no_wait);
+ }
+ }
+
+ // Wait until the stop
+ if (no_wait == false)
+ {
+ while (true)
+ {
+ s->ForceStopFlag = true;
+ s->Halt = true;
+ if (WaitThread(s->Thread, 20))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ s->ForceStopFlag = true;
+ s->Halt = true;
+ }
+}
+
+// Cleanup the session
+void CleanupSession(SESSION *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Release the delayed packet list
+ if (s->DelayedPacketList != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
+ {
+ PKT *p = LIST_DATA(s->DelayedPacketList, i);
+
+ Free(p->PacketData);
+ FreePacket(p);
+ }
+
+ ReleaseList(s->DelayedPacketList);
+ }
+
+ // Release the client connection options
+ if (s->ClientOption != NULL)
+ {
+ Free(s->ClientOption);
+ }
+
+ // Release the client authentication data
+ if (s->ClientAuth != NULL)
+ {
+ if (s->ClientAuth->ClientX != NULL)
+ {
+ FreeX(s->ClientAuth->ClientX);
+ }
+ if (s->ClientAuth->ClientX != NULL)
+ {
+ FreeK(s->ClientAuth->ClientK);
+ }
+ Free(s->ClientAuth);
+ }
+
+ FreeTraffic(s->Traffic);
+ Free(s->Name);
+
+ if (s->Thread != NULL)
+ {
+ ReleaseThread(s->Thread);
+ }
+
+ DeleteLock(s->lock);
+
+ ReleaseEvent(s->HaltEvent);
+
+ if (s->Cancel1)
+ {
+ ReleaseCancel(s->Cancel1);
+ }
+
+ if (s->Cancel2)
+ {
+ ReleaseCancel(s->Cancel2);
+ }
+
+ if (s->Policy)
+ {
+ Free(s->Policy);
+ }
+
+ if (s->Connection)
+ {
+ ReleaseConnection(s->Connection);
+ }
+
+ Free(s->Username);
+
+ if (s->PacketAdapter)
+ {
+ FreePacketAdapter(s->PacketAdapter);
+ }
+
+ if (s->OldTraffic != NULL)
+ {
+ FreeTraffic(s->OldTraffic);
+ }
+
+ DeleteLock(s->TrafficLock);
+
+ if (s->CancelList != NULL)
+ {
+ ReleaseCancelList(s->CancelList);
+ }
+
+ if (s->Client_Message != NULL)
+ {
+ Free(s->Client_Message);
+ }
+
+ DeleteCounter(s->LoggingRecordCount);
+
+ Free(s);
+}
+
+// Release the session
+void ReleaseSession(SESSION *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ CleanupSession(s);
+ }
+}
+
+// Display the total data transfer size of the session
+void PrintSessionTotalDataSize(SESSION *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Debug(
+ "-- SESSION TOTAL PKT INFORMATION --\n\n"
+ " TotalSendSize: %I64u\n"
+ " TotalSendSizeReal: %I64u\n"
+ " TotalRecvSize: %I64u\n"
+ " TotalRecvSizeReal: %I64u\n"
+ " Compression Rate: %.2f%% (Send)\n"
+ " %.2f%% (Recv)\n",
+ s->TotalSendSize, s->TotalSendSizeReal,
+ s->TotalRecvSize, s->TotalRecvSizeReal,
+ (float)((double)s->TotalSendSizeReal / (double)s->TotalSendSize * 100.0f),
+ (float)((double)s->TotalRecvSizeReal / (double)s->TotalRecvSize * 100.0f)
+ );
+
+}
+
+// Client thread
+void ClientThread(THREAD *t, void *param)
+{
+ SESSION *s;
+ bool use_password_dlg;
+ bool no_save_password = false;
+ bool is_vpngate_connection = false;
+ CEDAR *cedar;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ CiIncrementNumActiveSessions();
+
+ Debug("ClientThread 0x%x Started.\n", t);
+
+ s = (SESSION *)param;
+ AddRef(s->ref);
+ s->Thread = t;
+ AddRef(t->ref);
+ NoticeThreadInit(t);
+
+ cedar = s->Cedar;
+
+ s->ClientStatus = CLIENT_STATUS_CONNECTING;
+ s->RetryFlag = true;
+ s->CurrentRetryCount = 0;
+
+ Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+ if (s->Cedar->Client != NULL)
+ {
+ no_save_password = s->Cedar->Client->DontSavePassword;
+ }
+
+ s->Win32HideConnectWindow = s->ClientOption->HideStatusWindow;
+ s->Win32HideNicInfoWindow = s->ClientOption->HideNicInfoWindow;
+
+
+ while (true)
+ {
+ CLog(s->Cedar->Client, "LC_CONNECT_1", s->ClientOption->AccountName, s->CurrentRetryCount + 1);
+ if (s->LinkModeClient && s->Link != NULL)
+ {
+ HLog(s->Link->Hub, "LH_CONNECT_1", s->ClientOption->AccountName, s->CurrentRetryCount + 1);
+ }
+
+ Debug("Trying to Connect to Server... (%u / %u)\n", s->CurrentRetryCount + 0,
+ s->ClientOption->NumRetry);
+
+ // Initialize
+// s->TotalRecvSize = s->TotalRecvSizeReal =
+// s->TotalSendSize = s->TotalSendSizeReal = 0;
+ s->NextConnectionTime = 0;
+
+ // Connect
+ s->ClientStatus = CLIENT_STATUS_CONNECTING;
+ s->Halt = false;
+ SessionConnect(s);
+ if (s->UserCanceled)
+ {
+ s->Err = ERR_USER_CANCEL;
+ }
+ Debug("Disconnected. Err = %u : %S\n", s->Err, _E(s->Err));
+
+ PrintSessionTotalDataSize(s);
+
+ CLog(s->Cedar->Client, "LC_CONNECT_ERROR", s->ClientOption->AccountName,
+ GetUniErrorStr(s->Err), s->Err);
+
+ if (s->LinkModeClient && s->Link != NULL)
+ {
+ HLog(s->Link->Hub, "LH_CONNECT_ERROR", s->ClientOption->AccountName,
+ GetUniErrorStr(s->Err), s->Err);
+ }
+
+ s->ClientStatus = CLIENT_STATUS_RETRY;
+
+ if (s->Link != NULL)
+ {
+ ((LINK *)s->Link)->LastError = s->Err;
+ }
+
+ if (s->Halt && (s->RetryFlag == false) || s->ForceStopFlag)
+ {
+ // Must be aborted
+ if (s->Err == ERR_DEVICE_DRIVER_ERROR)
+ {
+#ifdef OS_WIN32
+ wchar_t tmp[MAX_SIZE];
+ if (s->Account != NULL && s->Cedar->Client != NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_DEVICE_ERROR"), s->ClientOption->DeviceName,
+ s->Err, _E(s->Err));
+ MsgBox(NULL, 0x10000 | 0x40000 | 0x200000 | 0x30, tmp);
+ }
+#endif // OS_WIN32
+ }
+ break;
+ }
+ // Determine whether to display the password re-entry dialog
+ use_password_dlg = false;
+
+ if (s->Account != NULL && s->Cedar->Client != NULL)
+ {
+#ifdef OS_WIN32
+ if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD || s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
+ {
+ if (s->Err == ERR_AUTH_FAILED || s->Err == ERR_PROXY_AUTH_FAILED)
+ {
+ use_password_dlg = true;
+ }
+ }
+#endif // OS_WIN32
+ }
+
+ // Failed to connect or the connection is disconnected
+ // Wait for retry interval
+ if (use_password_dlg == false)
+ {
+ UINT retry_interval = s->RetryInterval;
+
+ if (s->Err == ERR_HUB_IS_BUSY || s->Err == ERR_LICENSE_ERROR ||
+ s->Err == ERR_HUB_STOPPING || s->Err == ERR_TOO_MANY_USER_SESSION)
+ {
+ retry_interval = RETRY_INTERVAL_SPECIAL;
+ }
+
+ if (s->CurrentRetryCount >= s->ClientOption->NumRetry)
+ {
+ // Retry count excess
+
+#ifndef OS_WIN32
+
+ break;
+
+#else // OS_WIN32
+
+ if (s->Win32HideConnectWindow == false &&
+ s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ // Show a reconnection dialog
+ UI_CONNECTERROR_DLG p;
+ Zero(&p, sizeof(p));
+ UniStrCpy(p.AccountName, sizeof(p.AccountName), s->ClientOption->AccountName);
+ StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
+ p.Err = s->Err;
+ p.CurrentRetryCount = s->CurrentRetryCount + 1;
+ s->Halt = false;
+ p.RetryLimit = 0;
+ p.RetryIntervalSec = 0;
+ p.CancelEvent = s->HaltEvent;
+ p.HideWindow = s->Win32HideConnectWindow;
+ if (CncConnectErrorDlg(s, &p) == false)
+ {
+ // Abort
+ break;
+ }
+ else
+ {
+ s->Win32HideConnectWindow = p.HideWindow;
+ goto SKIP;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+#endif
+ }
+
+#ifndef OS_WIN32
+
+ // Simple wait
+ Wait(s->HaltEvent, retry_interval);
+
+#else // OS_WIN32
+
+ if (s->Win32HideConnectWindow == false &&
+ s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ // Show a reconnection dialog
+ UI_CONNECTERROR_DLG p;
+ Zero(&p, sizeof(p));
+ UniStrCpy(p.AccountName, sizeof(p.AccountName), s->ClientOption->AccountName);
+ StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
+ p.Err = s->Err;
+ p.CurrentRetryCount = s->CurrentRetryCount + 1;
+ p.RetryLimit = s->ClientOption->NumRetry;
+ p.RetryIntervalSec = retry_interval;
+ p.CancelEvent = s->HaltEvent;
+ s->Halt = false;
+ p.HideWindow = s->Win32HideConnectWindow;
+ if (CncConnectErrorDlg(s, &p) == false)
+ {
+ // Abort
+ break;
+ }
+ s->Win32HideConnectWindow = p.HideWindow;
+ }
+ else
+ {
+ // Simple wait
+ Wait(s->HaltEvent, s->RetryInterval);
+ }
+
+#endif // OS_WIN32
+ }
+ else
+ {
+#ifdef OS_WIN32
+ // Wait for re-entry the password
+ UI_PASSWORD_DLG p;
+ Zero(&p, sizeof(p));
+ if (s->Client_NoSavePassword == false)
+ {
+ p.ShowNoSavePassword = true;
+ }
+ p.NoSavePassword = no_save_password;
+ p.CancelEvent = s->HaltEvent;
+ if (s->Err == ERR_PROXY_AUTH_FAILED)
+ {
+ p.ProxyServer = true;
+ }
+
+ if (p.ProxyServer)
+ {
+ StrCpy(p.Username, sizeof(p.Username), s->ClientOption->ProxyUsername);
+ StrCpy(p.Password, sizeof(p.Password), s->ClientOption->ProxyPassword);
+ StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->ProxyName);
+ }
+ else
+ {
+ bool empty = false;
+
+ StrCpy(p.Username, sizeof(p.Username), s->ClientAuth->Username);
+ if (s->ClientAuth->AuthType == AUTHTYPE_RADIUS)
+ {
+ if (StrLen(s->ClientAuth->PlainPassword) == 0)
+ {
+ empty = true;
+ }
+ }
+ else if (s->ClientAuth->AuthType == AUTHTYPE_PASSWORD)
+ {
+ if (IsZero(s->ClientAuth->HashedPassword, sizeof(s->ClientAuth->HashedPassword)))
+ {
+ empty = true;
+ }
+ }
+
+ StrCpy(p.Password, sizeof(p.Password), empty ? "" : HIDDEN_PASSWORD);
+ StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
+ }
+
+ p.RetryIntervalSec = s->RetryInterval / 1000;
+ p.Type = s->ClientAuth->AuthType;
+
+ // Display the password re-entry dialog
+ if (CncPasswordDlg(s, &p) == false)
+ {
+ // Abort the connection
+ break;
+ }
+ else
+ {
+ // Overwrite the user name
+ if (p.ProxyServer)
+ {
+ // User name of the proxy
+ StrCpy(s->ClientOption->ProxyUsername, sizeof(s->ClientOption->ProxyUsername), p.Username);
+ }
+ else
+ {
+ // The user name for connecting to the server
+ StrCpy(s->ClientAuth->Username, sizeof(s->ClientAuth->Username), p.Username);
+ s->ClientAuth->AuthType = p.Type;
+ }
+
+ if (StrCmp(p.Password, HIDDEN_PASSWORD) != 0)
+ {
+ // Password is re-entered
+ if (p.ProxyServer)
+ {
+ // Password for the proxy server
+ StrCpy(s->ClientOption->ProxyPassword, sizeof(s->ClientOption->ProxyPassword), p.Password);
+ }
+ else
+ {
+ if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
+ {
+ // Plaintext password authentication
+ StrCpy(s->ClientAuth->PlainPassword, sizeof(s->ClientAuth->PlainPassword), p.Password);
+ }
+ else
+ {
+ // Encrypted password authentication
+ HashPassword(s->ClientAuth->HashedPassword, s->ClientAuth->Username, p.Password);
+ }
+ }
+ }
+
+ no_save_password = p.NoSavePassword;
+
+ if (s->Account != NULL && s->Cedar->Client != NULL)
+ {
+ s->Cedar->Client->DontSavePassword = no_save_password;
+ if (p.NoSavePassword == false)
+ {
+ // Update the account database of the client
+ if (p.ProxyServer == false)
+ {
+ // Update the Server connection information
+ ACCOUNT *a = s->Account;
+ Lock(a->lock);
+ {
+ CiFreeClientAuth(a->ClientAuth);
+ a->ClientAuth = CopyClientAuth(s->ClientAuth);
+ }
+ Unlock(a->lock);
+ CiSaveConfigurationFile(s->Cedar->Client);
+ }
+ else
+ {
+ // Update the proxy connection information
+ ACCOUNT *a = s->Account;
+ Lock(a->lock);
+ {
+ Copy(a->ClientOption, s->ClientOption, sizeof(CLIENT_OPTION));
+ }
+ Unlock(a->lock);
+ CiSaveConfigurationFile(s->Cedar->Client);
+ }
+ }
+ }
+ }
+#endif // OS_WIN32
+ }
+
+SKIP:
+ // Increase the number of retries
+ if (s->ConnectSucceed == false)
+ {
+ s->CurrentRetryCount++;
+ }
+
+ if (s->ForceStopFlag)
+ {
+ break;
+ }
+ }
+
+ Debug("Session Halt.\n");
+
+ s->ClientStatus = CLIENT_STATUS_IDLE;
+
+ // Regard as that the session is ended here
+ if (s->Account != NULL)
+ {
+ s->Account->ClientSession = NULL;
+ ReleaseSession(s);
+ }
+
+ Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
+
+
+ ReleaseSession(s);
+
+ CiDecrementNumActiveSessions();
+}
+
+// Name comparison of sessions
+int CompareSession(void *p1, void *p2)
+{
+ SESSION *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(SESSION **)p1;
+ s2 = *(SESSION **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(s1->Name, s2->Name);
+}
+
+// Create an RPC session
+SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option)
+{
+ return NewRpcSessionEx(cedar, option, NULL, NULL);
+}
+SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str)
+{
+ return NewRpcSessionEx2(cedar, option, err, client_str, NULL);
+}
+SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd)
+{
+ SESSION *s;
+ CONNECTION *c;
+ SOCK *sock;
+ // Validate arguments
+ if (cedar == NULL || option == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(SESSION));
+
+ s->LoggingRecordCount = NewCounter();
+ s->lock = NewLock();
+ s->ref = NewRef();
+ s->Cedar = cedar;
+ s->ServerMode = false;
+ s->Name = CopyStr("CLIENT_RPC_SESSION");
+ s->CreatedTime = s->LastCommTime = Tick64();
+ s->Traffic = NewTraffic();
+ s->HaltEvent = NewEvent();
+ s->TrafficLock = NewLock();
+ s->Cancel1 = NewCancel();
+
+ // Copy the client connection options
+ s->ClientOption = Malloc(sizeof(CLIENT_OPTION));
+ Copy(s->ClientOption, option, sizeof(CLIENT_OPTION));
+
+ s->MaxConnection = option->MaxConnection;
+ s->UseEncrypt = option->UseEncrypt;
+ s->UseCompress = option->UseCompress;
+
+ // Create a connection
+ c = s->Connection = NewClientConnectionEx(s, client_str, cedar->Version, cedar->Build);
+ c->hWndForUI = hWnd;
+
+ // Connect to the server
+ sock = ClientConnectToServer(c);
+ if (sock == NULL)
+ {
+ // Connection failure
+ if (err != NULL)
+ {
+ *err = c->Err;
+ }
+ ReleaseSession(s);
+ return NULL;
+ }
+
+ // Send a signature
+ if (ClientUploadSignature(sock) == false)
+ {
+ // Failure
+ if (err != NULL)
+ {
+ *err = c->Err;
+ }
+ ReleaseSession(s);
+ return NULL;
+ }
+
+ // Receive a Hello packet
+ if (ClientDownloadHello(c, sock) == false)
+ {
+ // Failure
+ if (err != NULL)
+ {
+ *err = c->Err;
+ }
+ ReleaseSession(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+// Create a client session
+SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, ACCOUNT *account)
+{
+ SESSION *s;
+ THREAD *t;
+ // Validate arguments
+ if (cedar == NULL || option == NULL || auth == NULL || pa == NULL ||
+ (auth->AuthType == CLIENT_AUTHTYPE_SECURE && auth->SecureSignProc == NULL))
+ {
+ return NULL;
+ }
+
+ // Initialize the SESSION object
+ s = ZeroMalloc(sizeof(SESSION));
+
+ s->LoggingRecordCount = NewCounter();
+
+ s->lock = NewLock();
+ s->ref = NewRef();
+ s->Cedar = cedar;
+ s->ServerMode = false;
+ s->Name = CopyStr("CLIENT_SESSION");
+ s->CreatedTime = s->LastCommTime = Tick64();
+ s->Traffic = NewTraffic();
+ s->HaltEvent = NewEvent();
+ s->PacketAdapter = pa;
+ s->TrafficLock = NewLock();
+ s->OldTraffic = NewTraffic();
+ s->Cancel1 = NewCancel();
+ s->CancelList = NewCancelList();
+
+ // Copy the client connection options
+ s->ClientOption = Malloc(sizeof(CLIENT_OPTION));
+ Copy(s->ClientOption, option, sizeof(CLIENT_OPTION));
+
+ s->MaxConnection = option->MaxConnection;
+ s->UseEncrypt = option->UseEncrypt;
+ s->UseCompress = option->UseCompress;
+
+ // Set the retry interval
+ s->RetryInterval = MAKESURE(option->RetryInterval, 0, 4000000) * 1000;
+ s->RetryInterval = MAKESURE(s->RetryInterval, MIN_RETRY_INTERVAL, MAX_RETRY_INTERVAL);
+
+ // Interval for additional connection creation is at least 1 second
+ s->ClientOption->AdditionalConnectionInterval = MAX(s->ClientOption->AdditionalConnectionInterval, 1);
+
+ // Hold whether the virtual LAN card is used in client mode
+ s->ClientModeAndUseVLan = (StrLen(s->ClientOption->DeviceName) == 0) ? false : true;
+ if (s->ClientOption->NoRoutingTracking)
+ {
+ s->ClientModeAndUseVLan = false;
+ }
+
+ if (StrLen(option->DeviceName) == 0)
+ {
+ // NAT mode
+ s->ClientModeAndUseVLan = false;
+ s->VirtualHost = true;
+ }
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ // Prohibit the half-duplex mode in the case of Win9x
+ s->ClientOption->HalfConnection = false;
+ }
+
+ // Copy the client authentication data
+ s->ClientAuth = Malloc(sizeof(CLIENT_AUTH));
+ Copy(s->ClientAuth, auth, sizeof(CLIENT_AUTH));
+
+ // Clone the certificate and the private key
+ if (s->ClientAuth->ClientX != NULL)
+ {
+ s->ClientAuth->ClientX = CloneX(s->ClientAuth->ClientX);
+ }
+ if (s->ClientAuth->ClientK != NULL)
+ {
+ s->ClientAuth->ClientK = CloneK(s->ClientAuth->ClientK);
+ }
+
+ if (StrCmpi(s->ClientOption->DeviceName, LINK_DEVICE_NAME) == 0)
+ {
+ // Link client mode
+ s->LinkModeClient = true;
+ s->Link = (LINK *)s->PacketAdapter->Param;
+ }
+
+ if (StrCmpi(s->ClientOption->DeviceName, SNAT_DEVICE_NAME) == 0)
+ {
+ // SecureNAT mode
+ s->SecureNATMode = true;
+ }
+
+ if (StrCmpi(s->ClientOption->DeviceName, BRIDGE_DEVICE_NAME) == 0)
+ {
+ // Bridge mode
+ s->BridgeMode = true;
+ }
+
+ if (s->VirtualHost)
+ {
+ VH *v = (VH *)s->PacketAdapter->Param;
+
+ // Add the session object to VH
+ v->Session = s;
+ AddRef(s->ref);
+ }
+
+ s->Account = account;
+
+ if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
+ {
+ // Do not retry in the case of a smart card authentication
+ s->ClientOption->NumRetry = 0;
+ }
+
+ // Create a client thread
+ t = NewThread(ClientThread, (void *)s);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ return s;
+}
+SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa)
+{
+ return NewClientSessionEx(cedar, option, auth, pa, NULL);
+}
+
+// Get the session from the 32bit session key
+SESSION *GetSessionFromKey32(CEDAR *cedar, UINT key32)
+{
+ HUB *h;
+ UINT i, j;
+ // Validate arguments
+ if (cedar == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(cedar->HubList);
+ {
+ for (i = 0;i < LIST_NUM(cedar->HubList);i++)
+ {
+ h = LIST_DATA(cedar->HubList, i);
+ LockList(h->SessionList);
+ {
+ for (j = 0;j < LIST_NUM(h->SessionList);j++)
+ {
+ SESSION *s = LIST_DATA(h->SessionList, j);
+ Lock(s->lock);
+ {
+ if (s->SessionKey32 == key32)
+ {
+ // Session found
+ AddRef(s->ref);
+
+ // Unlock
+ Unlock(s->lock);
+ UnlockList(h->SessionList);
+ UnlockList(cedar->HubList);
+ return s;
+ }
+ }
+ Unlock(s->lock);
+ }
+ }
+ UnlockList(h->SessionList);
+ }
+ }
+ UnlockList(cedar->HubList);
+
+ return NULL;
+}
+
+// Get the session from the session key
+SESSION *GetSessionFromKey(CEDAR *cedar, UCHAR *session_key)
+{
+ HUB *h;
+ UINT i, j;
+ // Validate arguments
+ if (cedar == NULL || session_key == NULL)
+ {
+ return NULL;
+ }
+
+ LockList(cedar->HubList);
+ {
+ for (i = 0;i < LIST_NUM(cedar->HubList);i++)
+ {
+ h = LIST_DATA(cedar->HubList, i);
+ LockList(h->SessionList);
+ {
+ for (j = 0;j < LIST_NUM(h->SessionList);j++)
+ {
+ SESSION *s = LIST_DATA(h->SessionList, j);
+ Lock(s->lock);
+ {
+ if (Cmp(s->SessionKey, session_key, SHA1_SIZE) == 0)
+ {
+ // Session found
+ AddRef(s->ref);
+
+ // Unlock
+ Unlock(s->lock);
+ UnlockList(h->SessionList);
+ UnlockList(cedar->HubList);
+ return s;
+ }
+ }
+ Unlock(s->lock);
+ }
+ }
+ UnlockList(h->SessionList);
+ }
+ }
+ UnlockList(cedar->HubList);
+
+ return NULL;
+}
+
+// Create a new session key
+void NewSessionKey(CEDAR *cedar, UCHAR *session_key, UINT *session_key_32)
+{
+ // Validate arguments
+ if (cedar == NULL || session_key == NULL || session_key_32 == NULL)
+ {
+ return;
+ }
+
+ Rand(session_key, SHA1_SIZE);
+ *session_key_32 = Rand32();
+}
+
+bool if_init(SESSION *s);
+CANCEL *if_getcancel(SESSION *s);
+UINT if_getnext(SESSION *s, void **data);
+bool if_putpacket(SESSION *s, void *data, UINT size);
+void if_free(SESSION *s);
+
+
+// Create a server session
+SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy)
+{
+ return NewServerSessionEx(cedar, c, h, username, policy, false);
+}
+SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode)
+{
+ SESSION *s;
+ char name[MAX_SIZE];
+ char hub_name_upper[MAX_SIZE];
+ char user_name_upper[MAX_USERNAME_LEN + 1];
+ // Validate arguments
+ if (cedar == NULL || c == NULL || h == NULL || username == NULL || policy == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize the SESSION object
+ s = ZeroMalloc(sizeof(SESSION));
+
+ s->LoggingRecordCount = NewCounter();
+ s->lock = NewLock();
+ s->ref = NewRef();
+ s->Cedar = cedar;
+ s->ServerMode = true;
+ s->CreatedTime = s->LastCommTime = Tick64();
+ s->Traffic = NewTraffic();
+ s->HaltEvent = NewEvent();
+ s->Cancel1 = NewCancel();
+ s->CancelList = NewCancelList();
+ s->Thread = c->Thread;
+ s->TrafficLock = NewLock();
+ s->OldTraffic = NewTraffic();
+ s->QoS = GetServerCapsBool(cedar->Server, "b_support_qos");
+ AddRef(s->Thread->ref);
+ s->Hub = h;
+ s->ClientStatus = CLIENT_STATUS_ESTABLISHED;
+
+ // Delayed packet list
+ s->DelayedPacketList = NewList(NULL);
+
+ // Packet adapter for the HUB
+ s->PacketAdapter = GetHubPacketAdapter();
+
+ s->Connection = c;
+ AddRef(c->ref);
+
+ // Determine the new session name
+ StrCpy(hub_name_upper, sizeof(hub_name_upper), h->Name);
+ StrUpper(hub_name_upper);
+ StrCpy(user_name_upper, sizeof(user_name_upper), username);
+ StrUpper(user_name_upper);
+
+ if ((StrCmpi(username, ADMINISTRATOR_USERNAME) != 0) && (StrCmpi(username, BRIDGE_USER_NAME) != 0) || (cedar->Server == NULL || cedar->Server->ServerType == SERVER_TYPE_STANDALONE))
+ {
+ if (IsEmptyStr(c->InProcPrefix))
+ {
+ Format(name, sizeof(name), "SID-%s-%u", user_name_upper, Inc(h->SessionCounter));
+ }
+ else
+ {
+ Format(name, sizeof(name), "SID-%s-[%s]-%u", user_name_upper, c->InProcPrefix, Inc(h->SessionCounter));
+ }
+ }
+ else
+ {
+ UCHAR rand[SHA1_SIZE];
+ char tmp[MAX_SIZE];
+ Rand(rand, sizeof(rand));
+ BinToStr(tmp, sizeof(tmp), rand, 3);
+
+ if (StrCmpi(username, BRIDGE_USER_NAME) != 0)
+ {
+ Format(name, sizeof(name), "SID-%s-%s", user_name_upper,
+ tmp);
+ }
+ else
+ {
+ char pc_name[MAX_SIZE];
+ TOKEN_LIST *t;
+
+ GetMachineName(tmp, sizeof(tmp));
+ t = ParseToken(tmp, ".");
+ if (t->NumTokens >= 1)
+ {
+ StrCpy(pc_name, sizeof(pc_name), t->Token[0]);
+ }
+ else
+ {
+ StrCpy(pc_name, sizeof(pc_name), "pc");
+ }
+ FreeToken(t);
+
+ StrUpper(pc_name);
+
+ Format(name, sizeof(name), "SID-%s-%s-%u", user_name_upper, pc_name,
+ Inc(h->SessionCounter));
+ }
+ }
+
+ s->Name = CopyStr(name);
+ s->Policy = policy;
+ s->InProcMode = inproc_mode;
+
+ // Add a SESSION to the HUB
+ AddSession(h, s);
+
+ // Create a key
+ NewSessionKey(cedar, s->SessionKey, &s->SessionKey32);
+
+ // Generate a MAC address for IPC
+ if (s->InProcMode)
+ {
+ char tmp[MAX_SIZE];
+ char machine[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+
+ GetMachineName(machine, sizeof(machine));
+
+ Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId);
+
+ StrUpper(tmp);
+ Trim(tmp);
+
+ Hash(hash, tmp, StrLen(tmp), true);
+
+ s->IpcMacAddress[0] = 0xCA;
+ s->IpcMacAddress[1] = hash[1];
+ s->IpcMacAddress[2] = hash[2];
+ s->IpcMacAddress[3] = hash[3];
+ s->IpcMacAddress[4] = hash[4];
+ s->IpcMacAddress[5] = hash[5];
+
+ MacToStr(tmp, sizeof(tmp), s->IpcMacAddress);
+ Debug("MAC Address for IPC: %s\n", tmp);
+ }
+
+ return s;
+}
+
+// Display the session key for debugging
+void DebugPrintSessionKey(UCHAR *session_key)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (session_key == NULL)
+ {
+ return;
+ }
+
+ Bit160ToStr(tmp, session_key);
+ Debug("SessionKey: %s\n", tmp);
+}
+
+// Display the status on the client
+void PrintStatus(SESSION *s, wchar_t *str)
+{
+ // Validate arguments
+ if (s == NULL || str == NULL || s->Account == NULL || s->Cedar->Client == NULL
+ || s->Account->StatusPrinter == NULL)
+ {
+ return;
+ }
+
+ // Inform the status to the callback function
+ s->Account->StatusPrinter(s, str);
+}
+
+// Create a cancellation list
+LIST *NewCancelList()
+{
+ return NewList(NULL);
+}
+
+// Add a Cancel to the cancellation list
+void AddCancelList(LIST *o, CANCEL *c)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || c == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANCEL *t = LIST_DATA(o, i);
+ if (t == c)
+ {
+ return;
+ }
+ }
+
+ AddRef(c->ref);
+ Add(o, c);
+}
+
+// Issue all cancellations in the cancellation list
+void CancelList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANCEL *c = LIST_DATA(o, i);
+ Cancel(c);
+ ReleaseCancel(c);
+ }
+
+ DeleteAll(o);
+}
+
+// Release the cancellation list
+void ReleaseCancelList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANCEL *c = LIST_DATA(o, i);
+ ReleaseCancel(c);
+ }
+
+ ReleaseList(o);
+}
+
+// Notify to the client
+void Notify(SESSION *s, UINT code)
+{
+ // Validate arguments
+ if (s == NULL || s->Account == NULL || s->Cedar->Client == NULL)
+ {
+ return;
+ }
+
+ CiNotify(s->Cedar->Client);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h
new file mode 100644
index 00000000..1214604f
--- /dev/null
+++ b/src/Cedar/Session.h
@@ -0,0 +1,408 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Session.h
+// Header of Session.c
+
+#ifndef SESSION_H
+#define SESSION_H
+
+
+// Interval to increment the number of logins after the connection
+#define NUM_LOGIN_INCREMENT_INTERVAL (30 * 1000)
+
+// Packet adapter function
+typedef bool (PA_INIT)(SESSION *s);
+typedef CANCEL *(PA_GETCANCEL)(SESSION *s);
+typedef UINT (PA_GETNEXTPACKET)(SESSION *s, void **data);
+typedef bool (PA_PUTPACKET)(SESSION *s, void *data, UINT size);
+typedef void (PA_FREE)(SESSION *s);
+
+// Client related function
+typedef void (CLIENT_STATUS_PRINTER)(SESSION *s, wchar_t *status);
+
+// Node information
+struct NODE_INFO
+{
+ char ClientProductName[64]; // Client product name
+ UINT ClientProductVer; // Client version
+ UINT ClientProductBuild; // Client build number
+ char ServerProductName[64]; // Server product name
+ UINT ServerProductVer; // Server version
+ UINT ServerProductBuild; // Server build number
+ char ClientOsName[64]; // Client OS name
+ char ClientOsVer[128]; // Client OS version
+ char ClientOsProductId[64]; // Client OS Product ID
+ char ClientHostname[64]; // Client host name
+ UINT ClientIpAddress; // Client IP address
+ UINT ClientPort; // Client port number
+ char ServerHostname[64]; // Server host name
+ UINT ServerIpAddress; // Server IP address
+ UINT ServerPort; // Server port number
+ char ProxyHostname[64]; // Proxy host name
+ UINT ProxyIpAddress; // Proxy Server IP Address
+ UINT ProxyPort; // Proxy port number
+ char HubName[64]; // HUB name
+ UCHAR UniqueId[16]; // Unique ID
+ // The following is for IPv6 support
+ UCHAR ClientIpAddress6[16]; // Client IPv6 address
+ UCHAR ServerIpAddress6[16]; // Server IP address
+ UCHAR ProxyIpAddress6[16]; // Proxy Server IP Address
+ char Padding[304 - (16 * 3)]; // Padding
+};
+
+// Packet adapter
+struct PACKET_ADAPTER
+{
+ PA_INIT *Init;
+ PA_GETCANCEL *GetCancel;
+ PA_GETNEXTPACKET *GetNextPacket;
+ PA_PUTPACKET *PutPacket;
+ PA_FREE *Free;
+ void *Param;
+};
+
+// Session structure
+struct SESSION
+{
+ LOCK *lock; // Lock
+ REF *ref; // Reference counter
+ CEDAR *Cedar; // Cedar
+ bool LocalHostSession; // Local host session
+ bool ServerMode; // Server mode session
+ bool NormalClient; // Connecting session from a regular client (not such as localbridge)
+ bool LinkModeClient; // Link mode client
+ bool LinkModeServer; // Link mode server
+ bool SecureNATMode; // SecureNAT session
+ bool BridgeMode; // Bridge session
+ bool BridgeIsEthLoopbackBlock; // Loopback is disabled on the Ethernet level
+ bool VirtualHost; // Virtual host mode
+ bool L3SwitchMode; // Layer-3 switch mode
+ bool InProcMode; // In-process mode
+ THREAD *Thread; // Management thread
+ CONNECTION *Connection; // Connection
+ CLIENT_OPTION *ClientOption; // Client connection options
+ CLIENT_AUTH *ClientAuth; // Client authentication data
+ volatile bool Halt; // Halting flag
+ volatile bool CancelConnect; // Cancel the connection
+ EVENT *HaltEvent; // Halting event
+ UINT Err; // Error value
+ HUB *Hub; // HUB
+ CANCEL *Cancel1; // Cancel object 1
+ CANCEL *Cancel2; // Cancel object 2
+ PACKET_ADAPTER *PacketAdapter; // Packet adapter
+ UCHAR UdpSendKey[16]; // UDP encryption key for transmission
+ UCHAR UdpRecvKey[16]; // UDP encryption key for reception
+ UINT ClientStatus; // Client Status
+ bool RetryFlag; // Retry flag (client)
+ bool ForceStopFlag; // Forced stop flag (client)
+ UINT CurrentRetryCount; // Current retry counter (client)
+ UINT RetryInterval; // Retry interval (client)
+ bool ConnectSucceed; // Connection success flag (client)
+ bool SessionTimeOuted; // Session times out
+ UINT Timeout; // Time-out period
+ UINT64 NextConnectionTime; // Time to put next additional connection
+ IP ServerIP; // IP address of the server
+ bool ClientModeAndUseVLan; // Use a virtual LAN card in client mode
+ bool UseSSLDataEncryption; // Use SSL data encryption
+ LOCK *TrafficLock; // Traffic data lock
+ LINK *Link; // A reference to the link object
+ SNAT *SecureNAT; // A reference to the SecureNAT object
+ BRIDGE *Bridge; // A reference to the Bridge object
+ NODE_INFO NodeInfo; // Node information
+ UINT64 LastIncrementTraffic; // Last time that updated the traffic data of the user
+ bool AdministratorMode; // Administrator mode
+ LIST *CancelList; // Cancellation list
+ L3IF *L3If; // Layer-3 interface
+ IP DefaultDns; // IP address of the default DNS server
+ bool IPv6Session; // IPv6 session (Physical communication is IPv6)
+ UINT VLanId; // VLAN ID
+ UINT UniqueId; // Unique ID
+ UCHAR IpcMacAddress[6]; // MAC address for IPC
+ UCHAR Padding[2];
+
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 LastCommTime; // Last communication date and time
+ TRAFFIC *Traffic; // Traffic data
+ TRAFFIC *OldTraffic; // Old traffic data
+ UINT64 TotalSendSize; // Total transmitted data size
+ UINT64 TotalRecvSize; // Total received data size
+ UINT64 TotalSendSizeReal; // Total transmitted data size (no compression)
+ UINT64 TotalRecvSizeReal; // Total received data size (no compression)
+ char *Name; // Session name
+ char *Username; // User name
+ char UserNameReal[MAX_USERNAME_LEN + 1]; // User name (real)
+ char GroupName[MAX_USERNAME_LEN + 1]; // Group name
+ POLICY *Policy; // Policy
+ UCHAR SessionKey[SHA1_SIZE]; // Session key
+ UINT SessionKey32; // 32bit session key
+ char SessionKeyStr[64]; // Session key string
+ UINT MaxConnection; // Maximum number of concurrent TCP connections
+ bool UseEncrypt; // Use encrypted communication
+ bool UseFastRC4; // Use high speed RC4 encryption
+ bool UseCompress; // Use data compression
+ bool HalfConnection; // Half connection mode
+ bool QoS; // VoIP / QoS
+ bool NoSendSignature; // Do not send a signature
+ bool IsOpenVPNL3Session; // Whether OpenVPN L3 session
+ bool IsOpenVPNL2Session; // Whether OpenVPN L2 session
+ UINT NumDisconnected; // Number of socket disconnection
+ bool NoReconnectToSession; // Disable to reconnect to the session
+ char UnderlayProtocol[64]; // Physical communication protocol
+ UINT64 FirstConnectionEstablisiedTime; // Connection completion time of the first connection
+ UINT64 CurrentConnectionEstablishTime; // Completion time of this connection
+ UINT NumConnectionsEatablished; // Number of connections established so far
+ UINT AdjustMss; // MSS adjustment value
+
+ bool IsRUDPSession; // Whether R-UDP session
+ UINT RUdpMss; // The value of the MSS should be applied while the R-UDP is used
+ bool EnableBulkOnRUDP; // Allow the bulk transfer in the R-UDP session
+ bool EnableHMacOnBulkOfRUDP; // Use the HMAC to sign the bulk transfer of R-UDP session
+ bool EnableUdpRecovery; // Enable the R-UDP recovery
+
+ bool UseUdpAcceleration; // Use of UDP acceleration mode
+ bool UseHMacOnUdpAcceleration; // Use the HMAC in the UDP acceleration mode
+ UDP_ACCEL *UdpAccel; // UDP acceleration
+ bool IsUsingUdpAcceleration; // Flag of whether the UDP acceleration is used
+ UINT UdpAccelMss; // MSS value to be applied while the UDP acceleration is used
+ bool UdpAccelFastDisconnectDetect; // Fast disconnection detection is enabled
+
+ bool IsAzureSession; // Whether the session via VPN Azure
+ IP AzureRealServerGlobalIp; // Real global IP of the server-side in the case of session via VPN Azure
+
+ ACCOUNT *Account; // Client account
+ UINT VLanDeviceErrorCount; // Number of times that the error occurred in the virtual LAN card
+ bool Win32HideConnectWindow; // Hide the status window
+ bool Win32HideNicInfoWindow; // Hide the NIC information window
+ bool UserCanceled; // Canceled by the user
+ UINT64 LastTryAddConnectTime; // Last time that attempted to add a connection
+
+ bool IsMonitorMode; // Whether the monitor mode
+ bool IsBridgeMode; // Whether the bridge mode
+ bool UseClientLicense; // Number of assigned client licenses
+ bool UseBridgeLicense; // Number of assigned bridge licenses
+
+ COUNTER *LoggingRecordCount; // Counter for the number of logging records
+
+ bool FreeInfoShowed; // Whether a warning about Free Edition has already displayed
+
+ bool Client_NoSavePassword; // Prohibit the password saving
+ wchar_t *Client_Message; // Message that has been sent from the server
+
+ LIST *DelayedPacketList; // Delayed packet list
+ UINT Flag1;
+
+ USER *NumLoginIncrementUserObject; // User objects to increment the nymber of logins
+ HUB *NumLoginIncrementHubObject; // Virtual HUB object to increment the number of logins
+ UINT64 NumLoginIncrementTick; // Time to perform increment a number of log
+
+ bool FirstTimeHttpRedirect; // Redirect HTTP only for the first time
+ char FirstTimeHttpRedirectUrl[128]; // URL for redirection only the first time
+ UINT FirstTimeHttpAccessCheckIp; // IP address for access checking
+
+ // To examine the maximum number of alowed logging target packets per minute
+ UINT64 MaxLoggedPacketsPerMinuteStartTick; // Inspection start time
+ UINT CurrentNumPackets; // Current number of packets
+
+ // Measures for D-Link bug
+ UINT64 LastDLinkSTPPacketSendTick; // Last D-Link STP packet transmission time
+ UCHAR LastDLinkSTPPacketDataHash[MD5_SIZE]; // Last D-Link STP packet hash
+};
+
+// Password dialog
+struct UI_PASSWORD_DLG
+{
+ UINT Type; // Type of password
+ char Username[MAX_USERNAME_LEN + 1]; // User name
+ char Password[MAX_PASSWORD_LEN + 1]; // Password
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT RetryIntervalSec; // Time to retry
+ EVENT *CancelEvent; // Event to cancel the dialog display
+ bool ProxyServer; // The authentication by the proxy server
+ UINT64 StartTick; // Start time
+ bool AdminMode; // Administrative mode
+ bool ShowNoSavePassword; // Whether to display a check box that does not save the password
+ bool NoSavePassword; // Mode that not to save the password
+ SOCK *Sock; // Socket
+};
+
+// Message dialog
+struct UI_MSG_DLG
+{
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ char HubName[MAX_HUBNAME_LEN + 1]; // Virtual HUB name
+ wchar_t *Msg; // Body
+ SOCK *Sock; // Socket
+ bool Halt; // Flag to close
+};
+
+// NIC information
+struct UI_NICINFO
+{
+ wchar_t AccountName[MAX_SIZE]; // Connection setting name
+ char NicName[MAX_SIZE]; // Virtual NIC name
+
+ SOCK *Sock; // Socket
+ bool Halt; // Flag to close
+ ROUTE_CHANGE *RouteChange; // Routing table change notification
+ UINT CurrentIcon; // Current icon
+ UINT64 CloseAfterTime; // Close automatically
+};
+
+// Connection Error dialog
+struct UI_CONNECTERROR_DLG
+{
+ EVENT *CancelEvent; // Event to cancel the dialog display
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ UINT Err; // Error code
+ UINT CurrentRetryCount; // Current retry count
+ UINT RetryLimit; // Limit of the number of retries
+ UINT64 StartTick; // Start time
+ UINT RetryIntervalSec; // Time to retry
+ bool HideWindow; // Hide the window
+ SOCK *Sock; // Socket
+};
+
+// Server certificate checking dialog
+struct UI_CHECKCERT
+{
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1]; // Account name
+ char ServerName[MAX_HOST_NAME_LEN + 1]; // Server name
+ X *x; // Server certificate
+ X *parent_x; // Parent certificate
+ X *old_x; // Certificate of previous
+ bool DiffWarning; // Display a warning of certificate forgery
+ bool Ok; // Connection permission flag
+ bool SaveServerCert; // Save the server certificate
+ SESSION *Session; // Session
+ volatile bool Halt; // Halting flag
+ SOCK *Sock; // Socket
+};
+
+
+// Function prototype
+SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, struct ACCOUNT *account);
+SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa);
+SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option);
+SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str);
+SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd);
+SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy);
+SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode);
+void ClientThread(THREAD *t, void *param);
+void ReleaseSession(SESSION *s);
+void CleanupSession(SESSION *s);
+void StopSession(SESSION *s);
+void StopSessionEx(SESSION *s, bool no_wait);
+bool SessionConnect(SESSION *s);
+bool ClientConnect(CONNECTION *c);
+int CompareSession(void *p1, void *p2);
+PACKET_ADAPTER *NewPacketAdapter(PA_INIT *init, PA_GETCANCEL *getcancel, PA_GETNEXTPACKET *getnext,
+ PA_PUTPACKET *put, PA_FREE *free);
+void FreePacketAdapter(PACKET_ADAPTER *pa);
+void SessionMain(SESSION *s);
+void NewSessionKey(CEDAR *cedar, UCHAR *session_key, UINT *session_key_32);
+SESSION *GetSessionFromKey(CEDAR *cedar, UCHAR *session_key);
+SESSION *GetSessionFromKey32(CEDAR *cedar, UINT key32);
+void DebugPrintSessionKey(UCHAR *session_key);
+void ClientAdditionalConnectChance(SESSION *s);
+void SessionAdditionalConnect(SESSION *s);
+void ClientAdditionalThread(THREAD *t, void *param);
+void PrintSessionTotalDataSize(SESSION *s);
+void AddTrafficForSession(SESSION *s, TRAFFIC *t);
+void IncrementUserTraffic(HUB *hub, char *username, SESSION *s);
+void Notify(SESSION *s, UINT code);
+void PrintStatus(SESSION *s, wchar_t *str);
+LIST *NewCancelList();
+void ReleaseCancelList(LIST *o);
+void AddCancelList(LIST *o, CANCEL *c);
+void CancelList(LIST *o);
+bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b);
+bool IsPriorityHighestPacketForQoS(void *data, UINT size);
+UINT GetNextDelayedPacketTickDiff(SESSION *s);
+
+#endif // SESSION_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/UT.c b/src/Cedar/UT.c
new file mode 100644
index 00000000..957a7079
--- /dev/null
+++ b/src/Cedar/UT.c
@@ -0,0 +1,393 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// UT.c
+// SoftEther Network Utility For Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define UT_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "../PenCore/resource.h"
+
+static char *selected_adapter = NULL;
+
+// Update status
+void UtSpeedMeterDlgRefreshStatus(HWND hWnd)
+{
+ char *title;
+ MS_ADAPTER *a;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ title = selected_adapter;
+
+ a = MsGetAdapter(title);
+ if (a == NULL)
+ {
+ LbReset(hWnd, L_STATUS);
+ Disable(hWnd, L_STATUS);
+ }
+ else
+ {
+ LVB *b;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ char str[MAX_SIZE];
+ b = LvInsertStart();
+
+ UniStrCpy(tmp, sizeof(tmp), a->TitleW);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_TITLE"), tmp);
+
+ StrToUni(tmp, sizeof(tmp), a->Guid);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_GUID"), tmp);
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_TYPE"), MsGetAdapterTypeStr(a->Type));
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_TYPE2"), (!a->IsNotEthernetLan ? _UU("SEC_YES") : _UU("SEC_NO")));
+
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_STATUS"), MsGetAdapterStatusStr(a->Status));
+
+ UniToStr3(tmp, sizeof(tmp), a->Mtu);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_MTU"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->Speed);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_SPEED"), tmp);
+
+ Zero(str, sizeof(str));
+ BinToStrEx2(str, sizeof(str), a->Address, a->AddressSize, '-');
+ StrToUni(tmp, sizeof(tmp), str);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_ADDRESS"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->RecvBytes);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_RECV_BYTES"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->RecvPacketsBroadcast);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_RECV_BCASTS"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->RecvPacketsUnicast);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_RECV_UNICASTS"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->SendBytes);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_SEND_BYTES"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->SendPacketsBroadcast);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_SEND_BCASTS"), tmp);
+
+ UniToStr3(tmp, sizeof(tmp), a->SendPacketsUnicast);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_SEND_UNICASTS"), tmp);
+
+ for (i = 0;i < a->NumIpAddress;i++)
+ {
+ UniFormat(tmp2, sizeof(tmp2), _UU("UT_SM_ST_IP"), i + 1);
+ IPToUniStr(tmp, sizeof(tmp), &a->IpAddresses[i]);
+ LvInsertAdd(b, 0, NULL, 2, tmp2, tmp);
+
+ UniFormat(tmp2, sizeof(tmp2), _UU("UT_SM_ST_SUBNET"), i + 1);
+ IPToUniStr(tmp, sizeof(tmp), &a->SubnetMasks[i]);
+ LvInsertAdd(b, 0, NULL, 2, tmp2, tmp);
+ }
+
+ for (i = 0;i < a->NumGateway;i++)
+ {
+ UniFormat(tmp2, sizeof(tmp2), _UU("UT_SM_ST_GATEWAY"), i + 1);
+ IPToUniStr(tmp, sizeof(tmp), &a->Gateways[i]);
+ LvInsertAdd(b, 0, NULL, 2, tmp2, tmp);
+ }
+
+ if (a->UseDhcp)
+ {
+ IPToUniStr(tmp, sizeof(tmp), &a->DhcpServer);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_DHCP"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), a->DhcpLeaseStart, NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_DHCP_1"), tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), a->DhcpLeaseExpires, NULL);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_DHCP_2"), tmp);
+ }
+
+ if (a->UseWins)
+ {
+ IPToUniStr(tmp, sizeof(tmp), &a->PrimaryWinsServer);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_WINS_1"), tmp);
+
+ IPToUniStr(tmp, sizeof(tmp), &a->SecondaryWinsServer);
+ LvInsertAdd(b, 0, NULL, 2, _UU("UT_SM_ST_WINS_2"), tmp);
+ }
+
+ LvInsertEnd(b, hWnd, L_STATUS);
+ Enable(hWnd, L_STATUS);
+
+ MsFreeAdapter(a);
+ }
+
+}
+
+static bool g_ut_adapter_list_updating = false;
+
+// Update the adapter list
+void UtSpeedMeterDlgRefreshList(HWND hWnd)
+{
+ wchar_t *old;
+ MS_ADAPTER_LIST *o;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (g_ut_adapter_list_updating)
+ {
+ return;
+ }
+ g_ut_adapter_list_updating = true;
+
+ // Get the current selection
+ old = GetText(hWnd, E_LIST);
+ if (old != NULL)
+ {
+ if (UniStrLen(old) == 0)
+ {
+ Free(old);
+ old = NULL;
+ }
+ }
+
+ o = MsCreateAdapterList();
+ CbReset(hWnd, E_LIST);
+ CbSetHeight(hWnd, E_LIST, 18);
+
+ for (i = 0;i < o->Num;i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ MS_ADAPTER *a = o->Adapters[i];
+
+ if (a->Info)
+ {
+ StrToUni(tmp, sizeof(tmp), a->Title);
+ CbAddStr(hWnd, E_LIST, tmp, 0);
+ }
+ }
+
+
+ // Re-select the previous selection
+ if (old != NULL)
+ {
+ CbSelectIndex(hWnd, E_LIST, CbFindStr(hWnd, E_LIST, old));
+ Free(old);
+ }
+
+ MsFreeAdapterList(o);
+
+ g_ut_adapter_list_updating = false;
+}
+
+// Speedometer dialog control update
+void UtSpeedMeterDlgUpdate(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+}
+
+// Speedometer dialog initialization
+void UtSpeedMeterDlgInit(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ LvInitEx(hWnd, L_STATUS, true);
+ LvInsertColumn(hWnd, L_STATUS, 0, _UU("UT_SM_COLUMN_1"), 150);
+ LvInsertColumn(hWnd, L_STATUS, 1, _UU("UT_SM_COLUMN_2"), 290);
+
+ UtSpeedMeterDlgRefreshList(hWnd);
+ selected_adapter = GetTextA(hWnd, E_LIST);
+ UtSpeedMeterDlgRefreshStatus(hWnd);
+ UtSpeedMeterDlgUpdate(hWnd);
+}
+
+// Speedometer dialog
+UINT UtSpeedMeterDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_NIC_ONLINE);
+ UtSpeedMeterDlgInit(hWnd);
+ SetTimer(hWnd, 1, SPEED_METER_REFRESH_INTERVAL, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ UtSpeedMeterDlgRefreshStatus(hWnd);
+ UtSpeedMeterDlgUpdate(hWnd);
+ SetTimer(hWnd, 1, SPEED_METER_REFRESH_INTERVAL, NULL);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) == CBN_SELCHANGE) {
+ Free(selected_adapter);
+ selected_adapter = GetTextA(hWnd, E_LIST);
+ UtSpeedMeterDlgUpdate(hWnd);
+ } else {
+ switch (wParam)
+ {
+ case B_REFRESH:
+ UtSpeedMeterDlgRefreshList(hWnd);
+ Free(selected_adapter);
+ selected_adapter = GetTextA(hWnd, E_LIST);
+ UtSpeedMeterDlgUpdate(hWnd);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ Free(selected_adapter);
+ selected_adapter = NULL;
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Speedometer
+void UtSpeedMeter()
+{
+ UtSpeedMeterEx(NULL);
+}
+void UtSpeedMeterEx(void *hWnd)
+{
+ Dialog((HWND)hWnd, D_SPEEDMETER, UtSpeedMeterDlgProc, NULL);
+}
+
+#endif // WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/UT.h b/src/Cedar/UT.h
new file mode 100644
index 00000000..0c6acafa
--- /dev/null
+++ b/src/Cedar/UT.h
@@ -0,0 +1,112 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// UT.h
+// Header of UT.c
+
+#ifndef UT_H
+#define UT_H
+
+// Constant
+#define SPEED_METER_REFRESH_INTERVAL 500
+
+#ifdef UT_C
+// For internal declaration
+
+// Function prototype
+UINT UtSpeedMeterDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void UtSpeedMeterDlgInit(HWND hWnd);
+void UtSpeedMeterDlgRefreshList(HWND hWnd);
+void UtSpeedMeterDlgRefreshStatus(HWND hWnd);
+void UtSpeedMeterDlgUpdate(HWND hWnd);
+void UtSpeedMeterDlgRefreshStatus(HWND hWnd);
+
+#endif // UT_C
+
+// Function prototype
+void UtSpeedMeter();
+void UtSpeedMeterEx(void *hWnd);
+
+#endif // UT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/UdpAccel.c b/src/Cedar/UdpAccel.c
new file mode 100644
index 00000000..9d0bcd78
--- /dev/null
+++ b/src/Cedar/UdpAccel.c
@@ -0,0 +1,1157 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// UdpAccel.c
+// UDP acceleration function
+
+#include "CedarPch.h"
+
+// Polling process
+void UdpAccelPoll(UDP_ACCEL *a)
+{
+ UCHAR *tmp = a->TmpBuf;
+ IP nat_t_ip;
+ UINT num_ignore_errors = 0;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Lock(a->NatT_Lock);
+ {
+ Copy(&nat_t_ip, &a->NatT_IP, sizeof(IP));
+ }
+ Unlock(a->NatT_Lock);
+
+ if (IsZeroIp(&nat_t_ip) == false)
+ {
+ // Release the thread which gets the IP address of the NAT-T server because it is no longer needed
+ if (a->NatT_GetIpThread != NULL)
+ {
+ WaitThread(a->NatT_GetIpThread, INFINITE);
+ ReleaseThread(a->NatT_GetIpThread);
+ a->NatT_GetIpThread = NULL;
+ }
+ }
+
+ // Receive a new UDP packet
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ UINT ret;
+
+ ret = RecvFrom(a->UdpSock, &src_ip, &src_port, tmp, UDP_ACCELERATION_TMP_BUF_SIZE);
+
+ if (ret != 0 && ret != SOCK_LATER)
+ {
+ if (a->UseUdpIpQuery && a->UdpIpQueryPacketSize >= 8 && CmpIpAddr(&a->UdpIpQueryHost, &src_ip) == 0 &&
+ src_port == a->UdpIpQueryPort)
+ {
+ // Receive a response of the query for IP and port number
+ IP my_ip = {0};
+ UINT myport = 0;
+ BUF *b = MemToBuf(a->UdpIpQueryPacketData, a->UdpIpQueryPacketSize);
+
+
+ FreeBuf(b);
+ }
+ else if (IsZeroIp(&nat_t_ip) == false && CmpIpAddr(&nat_t_ip, &src_ip) == 0 &&
+ src_port == UDP_NAT_T_PORT)
+ {
+ // Receive a response from the NAT-T server
+ IP my_ip;
+ UINT myport;
+
+ if (RUDPParseIPAndPortStr(tmp, ret, &my_ip, &myport))
+ {
+ if (myport >= 1 && myport <= 65535)
+ {
+ if (a->MyPortByNatTServer != myport)
+ {
+ a->MyPortByNatTServer = myport;
+ a->MyPortByNatTServerChanged = true;
+ a->CommToNatT_NumFail = 0;
+
+ Debug("NAT-T: MyPort = %u\n", myport);
+ }
+ }
+ }
+/*
+ BUF *b = NewBuf();
+ PACK *p;
+
+ WriteBuf(b, tmp, ret);
+ SeekBufToBegin(b);
+
+ p = BufToPack(b);
+ if (p != NULL)
+ {
+ if (PackCmpStr(p, "opcode", "query_for_nat_traversal"))
+ {
+ if (PackGetBool(p, "ok"))
+ {
+ if (PackGetInt64(p, "tran_id") == a->NatT_TranId)
+ {
+ UINT myport = PackGetInt(p, "your_port");
+
+ if (myport >= 1 && myport <= 65535)
+ {
+ if (a->MyPortByNatTServer != myport)
+ {
+ a->MyPortByNatTServer = myport;
+ a->MyPortByNatTServerChanged = true;
+
+ Debug("NAT-T: MyPort = %u\n", myport);
+ }
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(b);*/
+ }
+ else
+ {
+ BLOCK *b = UdpAccelProcessRecvPacket(a, tmp, ret, &src_ip, src_port);
+
+ //Debug("UDP Recv: %u %u %u\n", ret, (b == NULL ? 0 : b->Size), (b == NULL ? 0 : b->Compressed));
+
+ /*if (b != NULL)
+ {
+ char tmp[MAX_SIZE * 10];
+ BinToStr(tmp, sizeof(tmp), b->Buf, b->Size);
+ Debug("Recv Pkt: %s\n", tmp);
+ }*/
+
+ if (b != NULL)
+ {
+ // Receive a packet
+ InsertQueue(a->RecvBlockQueue, b);
+ }
+ }
+ }
+ else
+ {
+ if (ret == 0)
+ {
+ if (a->UdpSock->IgnoreRecvErr == false)
+ {
+ // Serious UDP reception error occurs
+ a->FatalError = true;
+ break;
+ }
+
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ a->FatalError = true;
+ break;
+ }
+ }
+ else
+ {
+ // SOCK_LATER
+ break;
+ }
+ }
+ }
+
+ // Send a Keep-Alive packet
+ if (a->NextSendKeepAlive == 0 || (a->NextSendKeepAlive <= a->Now) || a->YourPortByNatTServerChanged)
+ {
+ a->YourPortByNatTServerChanged = false;
+
+ if (UdpAccelIsSendReady(a, false))
+ {
+ UINT rand_interval;
+
+ if (a->FastDetect == false)
+ {
+ rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN;
+ }
+ else
+ {
+ rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST;
+ }
+
+ a->NextSendKeepAlive = a->Now + (UINT64)rand_interval;
+
+ //Debug("UDP KeepAlive\n");
+
+ UdpAccelSend(a, NULL, 0, false, 1000, false);
+ }
+ }
+
+ // Send a NAT-T request packet (Only if the connection by UDP has not be established yet)
+ if (a->NoNatT == false)
+ {
+ // In the usual case
+ if (IsZeroIp(&nat_t_ip) == false)
+ {
+ if (UdpAccelIsSendReady(a, true) == false)
+ {
+ if (a->NextPerformNatTTick == 0 || (a->NextPerformNatTTick <= a->Now))
+ {
+ UINT rand_interval;
+ UCHAR c = 'B';
+
+ a->CommToNatT_NumFail++;
+
+ rand_interval = UDP_NAT_T_INTERVAL_INITIAL * MIN(a->CommToNatT_NumFail, UDP_NAT_T_INTERVAL_FAIL_MAX);
+ //PACK *p = NewPack();
+ //BUF *b;
+
+ if (a->MyPortByNatTServer != 0)
+ {
+ rand_interval = GenRandInterval(UDP_NAT_T_INTERVAL_MIN, UDP_NAT_T_INTERVAL_MAX);
+ }
+
+ a->NextPerformNatTTick = a->Now + (UINT64)rand_interval;
+
+ // Generate the request packet
+ /*PackAddStr(p, "description", UDP_NAT_T_SIGNATURE);
+ PackAddStr(p, "opcode", "query_for_nat_traversal");
+ PackAddInt64(p, "tran_id", a->NatT_TranId);
+ b = PackToBuf(p);
+ FreePack(p);*/
+
+ // Send the request packet
+ SendTo(a->UdpSock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1);
+
+ //FreeBuf(b);
+ }
+ }
+ else
+ {
+ a->NextPerformNatTTick = 0;
+ a->CommToNatT_NumFail = 0;
+ }
+ }
+ }
+ else
+ {
+ // NAT_T is disabled, but there is a reference host (such as VGC)
+ if (a->UseUdpIpQuery)
+ {
+ }
+ }
+}
+
+// Send a packet block
+void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b)
+{
+ // Validate arguments
+ if (a == NULL || b == NULL)
+ {
+ return;
+ }
+
+ UdpAccelSend(a, b->Buf, b->Size, b->Compressed, a->MaxUdpPacketSize, b->PriorityQoS);
+}
+
+// Calculate the best MSS
+UINT UdpAccelCalcMss(UDP_ACCEL *a)
+{
+ UINT ret;
+
+ // Validate arguments
+ if (a == NULL)
+ {
+ return 0;
+ }
+
+ ret = MTU_FOR_PPPOE;
+
+ // IPv4
+ if (a->IsIPv6)
+ {
+ ret -= 40;
+ }
+ else
+ {
+ ret -= 20;
+ }
+
+ // UDP
+ ret -= 8;
+
+ if (a->PlainTextMode == false)
+ {
+ // IV
+ ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
+ }
+
+ // Cookie
+ ret -= sizeof(UINT);
+
+ // My Tick
+ ret -= sizeof(UINT64);
+
+ // Your Tick
+ ret -= sizeof(UINT64);
+
+ // Size
+ ret -= sizeof(USHORT);
+
+ // Compress Flag
+ ret -= sizeof(UCHAR);
+
+ if (a->PlainTextMode == false)
+ {
+ // Verify
+ ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
+ }
+
+ // Ethernet header (communication packets)
+ ret -= 14;
+
+ // IPv4 Header (communication packets)
+ ret -= 20;
+
+ // TCP header (communication packet)
+ ret -= 20;
+
+ return ret;
+}
+
+// Send
+void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority)
+{
+ UCHAR tmp[UDP_ACCELERATION_TMP_BUF_SIZE];
+ UCHAR *buf;
+ UINT size;
+ UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
+ UINT64 ui64;
+ USHORT us;
+ UCHAR c;
+ UINT current_size;
+ UINT ui32;
+ bool fatal_error = false;
+ UINT r;
+ // Validate arguments
+ if (a == NULL || (data_size != 0 && data == NULL))
+ {
+ return;
+ }
+ if (max_size == 0)
+ {
+ max_size = INFINITE;
+ }
+
+ buf = tmp;
+ size = 0;
+
+ // IV
+ if (a->PlainTextMode == false)
+ {
+ // IV
+ Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
+
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE;
+ size += UDP_ACCELERATION_PACKET_IV_SIZE;
+
+ // Calculate the key
+ UdpAccelCalcKey(key, a->MyKey, a->NextIv);
+
+ if (false)
+ {
+ char tmp1[256];
+ char tmp2[256];
+ char tmp3[256];
+ BinToStr(tmp1, sizeof(tmp1), a->MyKey, sizeof(a->MyKey));
+ BinToStr(tmp2, sizeof(tmp2), a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
+ BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
+ Debug("My Key : %s\n"
+ "IV : %s\n"
+ "Comm Key: %s\n",
+ tmp1, tmp2, tmp3);
+ }
+ }
+
+ // Cookie
+ ui32 = Endian32(a->YourCookie);
+ Copy(buf, &ui32, sizeof(UINT));
+ buf += sizeof(UINT);
+ size += sizeof(UINT);
+
+ // My Tick
+ ui64 = Endian64(a->Now == 0 ? 1ULL : a->Now);
+ Copy(buf, &ui64, sizeof(UINT64));
+ buf += sizeof(UINT64);
+ size += sizeof(UINT64);
+
+ // Your Tick
+ ui64 = Endian64(a->LastRecvYourTick);
+ Copy(buf, &ui64, sizeof(UINT64));
+ buf += sizeof(UINT64);
+ size += sizeof(UINT64);
+
+ // Size
+ us = Endian16(data_size);
+ Copy(buf, &us, sizeof(USHORT));
+ buf += sizeof(USHORT);
+ size += sizeof(USHORT);
+
+ // Compress Flag
+ c = (compressed ? 1 : 0);
+ Copy(buf, &c, sizeof(UCHAR));
+ buf += sizeof(UCHAR);
+ size += sizeof(UCHAR);
+
+ // Data
+ if (data_size >= 1)
+ {
+ Copy(buf, data, data_size);
+ buf += data_size;
+ size += data_size;
+ }
+
+ if (a->PlainTextMode == false)
+ {
+ static UCHAR zero[UDP_ACCELERATION_PACKET_IV_SIZE] = {0};
+ CRYPT *c;
+
+ current_size = UDP_ACCELERATION_PACKET_IV_SIZE + sizeof(UINT) + sizeof(UINT64) * 2 +
+ sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_IV_SIZE;
+
+ if (current_size < max_size)
+ {
+ // Padding
+ UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
+ UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
+ pad_size = rand() % pad_size;
+
+ Zero(pad, sizeof(pad));
+ Copy(buf, pad, pad_size);
+ buf += pad_size;
+ size += pad_size;
+ }
+
+ // Verify
+ Copy(buf, zero, UDP_ACCELERATION_PACKET_IV_SIZE);
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE;
+ size += UDP_ACCELERATION_PACKET_IV_SIZE;
+
+ // Encryption
+ c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
+ Encrypt(c, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, size - UDP_ACCELERATION_PACKET_IV_SIZE);
+ FreeCrypt(c);
+
+ // Next Iv
+ Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE, UDP_ACCELERATION_PACKET_IV_SIZE);
+ }
+
+ // Send
+ SetSockHighPriority(a->UdpSock, high_priority);
+
+ r = SendTo(a->UdpSock, &a->YourIp, a->YourPort, tmp, size);
+ if (r == 0 && a->UdpSock->IgnoreSendErr == false)
+ {
+ fatal_error = true;
+ Debug("Error: SendTo: %r %u %u\n", &a->YourIp, a->YourPort, size);
+ WHERE;
+ }
+
+ if (data_size == 0)
+ {
+ if (UdpAccelIsSendReady(a, true) == false)
+ {
+ if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
+ {
+ r = SendTo(a->UdpSock, &a->YourIp, a->YourPortByNatTServer, tmp, size);
+ if (r == 0 && a->UdpSock->IgnoreSendErr == false)
+ {
+ fatal_error = true;
+ WHERE;
+ }
+ }
+ }
+ }
+
+ if (data_size == 0)
+ {
+ if (IsZeroIP(&a->YourIp2) == false && CmpIpAddr(&a->YourIp, &a->YourIp2) != 0)
+ {
+ if (UdpAccelIsSendReady(a, true) == false)
+ {
+ // When the KeepAlive, if the opponent may be behind a NAT,
+ // send the packet to the IP address of outside of the NAT
+ r = SendTo(a->UdpSock, &a->YourIp2, a->YourPort, tmp, size);
+ if (r == 0 && a->UdpSock->IgnoreSendErr == false)
+ {
+ fatal_error = true;
+ WHERE;
+ }
+
+ if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
+ {
+ r = SendTo(a->UdpSock, &a->YourIp2, a->YourPortByNatTServer, tmp, size);
+ if (r == 0 && a->UdpSock->IgnoreSendErr == false)
+ {
+ fatal_error = true;
+ WHERE;
+ }
+ }
+ }
+ }
+ }
+
+ if (fatal_error)
+ {
+ a->FatalError = true;
+ WHERE;
+ }
+
+ //Debug("UDP Send: %u\n", size);
+}
+
+// Determine whether transmission is possible
+bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive)
+{
+ UINT64 timeout_value;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ if (a->Inited == false)
+ {
+ return false;
+ }
+
+ if (a->YourPort == 0)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(&a->YourIp))
+ {
+ return false;
+ }
+
+ timeout_value = UDP_ACCELERATION_KEEPALIVE_TIMEOUT;
+
+ if (a->FastDetect)
+ {
+ timeout_value = UDP_ACCELERATION_KEEPALIVE_TIMEOUT_FAST;
+ }
+
+ if (check_keepalive)
+ {
+ if (a->LastRecvTick == 0 || ((a->LastRecvTick + timeout_value) < a->Now))
+ {
+ a->FirstStableReceiveTick = 0;
+ return false;
+ }
+ else
+ {
+ if ((a->FirstStableReceiveTick + (UINT64)UDP_ACCELERATION_REQUIRE_CONTINUOUS) <= a->Now)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Process the received packet
+BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port)
+{
+ UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
+ UCHAR *iv;
+ CRYPT *c;
+ UINT64 my_tick, your_tick;
+ UINT inner_size;
+ UCHAR *inner_data = NULL;
+ UINT pad_size;
+ UCHAR *verify;
+ bool compress_flag;
+ BLOCK *b = NULL;
+ UINT cookie;
+ // Validate arguments
+ if (a == NULL || buf == NULL || size == 0 || src_ip == NULL)
+ {
+ return NULL;
+ }
+
+ if (a->PlainTextMode == false)
+ {
+ // IV
+ if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
+ {
+ return NULL;
+ }
+ iv = buf;
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE;
+ size -= UDP_ACCELERATION_PACKET_IV_SIZE;
+
+ // Calculate the key
+ UdpAccelCalcKey(key, a->YourKey, iv);
+
+ if (false)
+ {
+ char tmp1[256];
+ char tmp2[256];
+ char tmp3[256];
+ BinToStr(tmp1, sizeof(tmp1), a->YourKey, sizeof(a->YourKey));
+ BinToStr(tmp2, sizeof(tmp2), iv, UDP_ACCELERATION_PACKET_IV_SIZE);
+ BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
+ Debug("Your Key: %s\n"
+ "IV : %s\n"
+ "Comm Key: %s\n",
+ tmp1, tmp2, tmp3);
+ }
+
+ // Decryption
+ c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
+ Encrypt(c, buf, buf, size);
+ FreeCrypt(c);
+ }
+
+ // Cookie
+ if (size < sizeof(UINT))
+ {
+ return NULL;
+ }
+ cookie = READ_UINT(buf);
+ buf += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ if (cookie != a->MyCookie)
+ {
+ return NULL;
+ }
+
+ // My Tick
+ if (size < sizeof(UINT64))
+ {
+ return NULL;
+ }
+ my_tick = READ_UINT64(buf);
+ buf += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // Your Tick
+ if (size < sizeof(UINT64))
+ {
+ return NULL;
+ }
+ your_tick = READ_UINT64(buf);
+ buf += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // inner_size
+ if (size < sizeof(USHORT))
+ {
+ return NULL;
+ }
+ inner_size = READ_USHORT(buf);
+ buf += sizeof(USHORT);
+ size -= sizeof(USHORT);
+
+ // compress_flag
+ if (size < sizeof(UCHAR))
+ {
+ return NULL;
+ }
+ compress_flag = *((UCHAR *)buf);
+ buf += sizeof(UCHAR);
+ size -= sizeof(UCHAR);
+
+ if (size < inner_size)
+ {
+ return NULL;
+ }
+
+ // inner_data
+ if (inner_size >= 1)
+ {
+ inner_data = buf;
+ buf += inner_size;
+ size -= inner_size;
+ }
+
+ if (a->PlainTextMode == false)
+ {
+ // padding
+ if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
+ {
+ return false;
+ }
+ pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE;
+ buf += pad_size;
+ size -= pad_size;
+
+ // verify
+ if (size != UDP_ACCELERATION_PACKET_IV_SIZE)
+ {
+ return NULL;
+ }
+
+ verify = buf;
+
+ if (IsZero(verify, UDP_ACCELERATION_PACKET_IV_SIZE) == false)
+ {
+ return NULL;
+ }
+ }
+
+ if (my_tick < a->LastRecvYourTick)
+ {
+ if ((a->LastRecvYourTick - my_tick) >= ((UINT64)UDP_ACCELERATION_WINDOW_SIZE_MSEC))
+ {
+ return NULL;
+ }
+ }
+
+ a->LastRecvMyTick = MAX(a->LastRecvMyTick, your_tick);
+ a->LastRecvYourTick = MAX(a->LastRecvYourTick, my_tick);
+
+ if (inner_size >= 1)
+ {
+ b = NewBlock(Clone(inner_data, inner_size), inner_size, compress_flag ? -1 : 0);
+ }
+
+ if (a->LastSetSrcIpAndPortTick < a->LastRecvYourTick)
+ {
+ a->LastSetSrcIpAndPortTick = a->LastRecvYourTick;
+
+ Copy(&a->YourIp, src_ip, sizeof(IP));
+ a->YourPort = src_port;
+ }
+
+ if (a->LastRecvMyTick != 0)
+ {
+ if ((a->LastRecvMyTick + (UINT64)(UDP_ACCELERATION_WINDOW_SIZE_MSEC)) >= a->Now)
+ {
+ a->LastRecvTick = a->Now;
+
+ a->IsReachedOnce = true;
+
+ if (a->FirstStableReceiveTick == 0)
+ {
+ a->FirstStableReceiveTick = a->Now;
+ }
+ }
+ }
+
+ return b;
+}
+
+// Calculate the key
+void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv)
+{
+ UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE + UDP_ACCELERATION_PACKET_IV_SIZE];
+ // Validate arguments
+ if (key == NULL || common_key == NULL || iv == NULL)
+ {
+ return;
+ }
+
+ Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE, iv, UDP_ACCELERATION_PACKET_IV_SIZE);
+
+ HashSha1(key, tmp, sizeof(tmp));
+}
+
+// Set the current time
+void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ a->Now = tick64;
+}
+
+// Initialize the server-side
+bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT client_port, IP *client_ip_2)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (a == NULL || client_key == NULL)
+ {
+ return false;
+ }
+
+ IPToStr(tmp, sizeof(tmp), client_ip);
+ Debug("UdpAccelInitServer: client_ip=%s, client_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, client_port,
+ a->MyCookie, a->YourCookie);
+
+ if (IsIP6(client_ip) != a->IsIPv6)
+ {
+ return false;
+ }
+
+ Copy(a->YourKey, client_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
+
+ Copy(&a->YourIp, client_ip, sizeof(IP));
+ Copy(&a->YourIp2, client_ip_2, sizeof(IP));
+ a->YourPort = client_port;
+
+ a->Now = Tick64();
+
+ a->Inited = true;
+
+ return true;
+}
+
+// Initialize the client-side
+bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *server_key, IP *server_ip, UINT server_port, UINT server_cookie, UINT client_cookie, IP *server_ip_2)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (a == NULL || server_key == NULL || server_ip == NULL || server_port == 0)
+ {
+ return false;
+ }
+
+ IPToStr(tmp, sizeof(tmp), server_ip);
+ Debug("UdpAccelInitClient: server_ip=%s, server_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, server_port, server_cookie, client_cookie);
+
+ if (IsIP6(server_ip) != a->IsIPv6)
+ {
+ return false;
+ }
+
+ Copy(a->YourKey, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
+
+ Copy(&a->YourIp, server_ip, sizeof(IP));
+ Copy(&a->YourIp2, server_ip_2, sizeof(IP));
+ a->YourPort = server_port;
+
+ a->Now = Tick64();
+
+ a->MyCookie = client_cookie;
+ a->YourCookie = server_cookie;
+
+ a->Inited = true;
+
+ return true;
+}
+
+// Create a new UDP acceleration function
+UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t)
+{
+ UDP_ACCEL *a;
+ SOCK *s;
+ UINT max_udp_size;
+ bool is_in_cedar_port_list = false;
+
+ if (IsZeroIP(ip))
+ {
+ ip = NULL;
+ }
+
+ if (client_mode || random_port)
+ {
+ // Use a appropriate vacant port number in the case of using random port or client mode
+ s = NewUDPEx3(0, ip);
+ }
+ else
+ {
+ // Specify in the range in the case of server mode
+ UINT i;
+ s = NULL;
+
+ LockList(cedar->UdpPortList);
+ {
+ for (i = UDP_SERVER_PORT_LOWER;i <= UDP_SERVER_PORT_HIGHER;i++)
+ {
+ if (IsIntInList(cedar->UdpPortList, i) == false)
+ {
+ s = NewUDPEx3(i, ip);
+
+ if (s != NULL)
+ {
+ is_in_cedar_port_list = true;
+ break;
+ }
+ }
+ }
+
+ if (s == NULL)
+ {
+ // Leave the port selection to the OS because the available port is not found within the range
+ s = NewUDPEx3(0, ip);
+ }
+
+ if (s != NULL && is_in_cedar_port_list)
+ {
+ AddIntDistinct(cedar->UdpPortList, i);
+ }
+ }
+ UnlockList(cedar->UdpPortList);
+ }
+
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ a = ZeroMalloc(sizeof(UDP_ACCEL));
+
+ a->Cedar = cedar;
+ AddRef(a->Cedar->ref);
+
+ a->NoNatT = no_nat_t;
+
+
+ a->NatT_TranId = Rand64();
+
+ a->CreatedTick = Tick64();
+
+ a->IsInCedarPortList = is_in_cedar_port_list;
+
+ a->ClientMode = client_mode;
+
+ a->Now = Tick64();
+ a->UdpSock = s;
+ Rand(a->MyKey, sizeof(a->MyKey));
+ Rand(a->YourKey, sizeof(a->YourKey));
+
+ Copy(&a->MyIp, ip, sizeof(IP));
+ a->MyPort = s->LocalPort;
+
+ a->IsIPv6 = IsIP6(ip);
+
+ a->RecvBlockQueue = NewQueue();
+
+ Rand(a->NextIv, sizeof(a->NextIv));
+
+ do
+ {
+ a->MyCookie = Rand32();
+ }
+ while (a->MyCookie == 0);
+
+ do
+ {
+ a->YourCookie = Rand32();
+ }
+ while (a->MyCookie == 0 || a->MyCookie == a->YourCookie);
+
+ // Calculate the maximum transmittable UDP packet size
+ max_udp_size = MTU_FOR_PPPOE;
+
+ if (a->IsIPv6 == false)
+ {
+ // IPv4
+ max_udp_size -= 20;
+ }
+ else
+ {
+ // IPv6
+ max_udp_size -= 40;
+ }
+
+ // UDP
+ max_udp_size -= 8;
+
+ a->MaxUdpPacketSize = max_udp_size;
+
+ Debug("Udp Accel My Port = %u\n", a->MyPort);
+
+ // Initialize the NAT-T server IP address acquisition thread
+ a->NatT_Lock = NewLock();
+ a->NatT_HaltEvent = NewEvent();
+
+ if (a->NoNatT == false)
+ {
+ a->NatT_GetIpThread = NewThread(NatT_GetIpThread, a);
+ }
+
+ return a;
+}
+
+// NAT-T server IP address acquisition thread
+void NatT_GetIpThread(THREAD *thread, void *param)
+{
+ UDP_ACCEL *a;
+ char hostname[MAX_SIZE];
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ a = (UDP_ACCEL *)param;
+
+ RUDPGetRegisterHostNameByIP(hostname, sizeof(hostname), NULL);
+
+ while (a->NatT_Halt == false)
+ {
+ IP ip;
+
+ // Get the IP address
+ bool ret = GetIP4Ex(&ip, hostname, 0, &a->NatT_Halt);
+
+ if (ret && (IsZeroIp(&ip) == false))
+ {
+ char tmp[128];
+
+ // Success to get
+ Lock(a->NatT_Lock);
+ {
+ Copy(&a->NatT_IP, &ip, sizeof(IP));
+ }
+ Unlock(a->NatT_Lock);
+
+ IPToStr(tmp, sizeof(tmp), &ip);
+ Debug("NAT-T IP Address Resolved: %s = %s\n", hostname, tmp);
+
+ a->NatT_IP_Changed = true;
+
+ break;
+ }
+
+ // Fail to get
+ Wait(a->NatT_HaltEvent, UDP_NAT_T_GET_IP_INTERVAL);
+ }
+}
+
+// Release the UDP acceleration function
+void FreeUdpAccel(UDP_ACCEL *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ BLOCK *b = GetNext(a->RecvBlockQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+
+ ReleaseQueue(a->RecvBlockQueue);
+
+ ReleaseSock(a->UdpSock);
+
+ if (a->IsInCedarPortList)
+ {
+ LockList(a->Cedar->UdpPortList);
+ {
+ DelInt(a->Cedar->UdpPortList, a->MyPort);
+ }
+ UnlockList(a->Cedar->UdpPortList);
+ }
+
+ // Release of NAT-T related
+ a->NatT_Halt = true;
+ Set(a->NatT_HaltEvent);
+
+ if (a->NatT_GetIpThread != NULL)
+ {
+ WaitThread(a->NatT_GetIpThread, INFINITE);
+ ReleaseThread(a->NatT_GetIpThread);
+ }
+
+ ReleaseEvent(a->NatT_HaltEvent);
+ DeleteLock(a->NatT_Lock);
+
+ ReleaseCedar(a->Cedar);
+
+ Free(a);
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/UdpAccel.h b/src/Cedar/UdpAccel.h
new file mode 100644
index 00000000..472a113d
--- /dev/null
+++ b/src/Cedar/UdpAccel.h
@@ -0,0 +1,195 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// UdpAccel.h
+// Header of UdpAccel.c
+
+#ifndef UDPACCEL_H
+#define UDPACCEL_H
+
+// Constants
+#define UDP_ACCELERATION_COMMON_KEY_SIZE 20 // Common key size
+#define UDP_ACCELERATION_PACKET_KEY_SIZE 20 // Key size for the packet
+#define UDP_ACCELERATION_PACKET_IV_SIZE 20 // IV size for the packet
+#define UDP_ACCELERATION_TMP_BUF_SIZE 2048 // Temporary buffer size
+#define UDP_ACCELERATION_WINDOW_SIZE_MSEC (30 * 1000) // Receive window size (in milliseconds)
+
+#define UDP_ACCELERATION_SUPPORTED_MAX_PAYLOAD_SIZE 1600 // Maximum supported payload size
+#define UDP_ACCELERATION_MAX_PADDING_SIZE 32 // Maximum padding size
+
+#define UDP_ACCELERATION_REQUIRE_CONTINUOUS (10 * 1000) // Not to use if stable communication is not continued at least for this time
+
+// Time constant for Build 8534 or earlier
+#define UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN (1 * 1000) // Keep Alive Interval (minimum)
+#define UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX (3 * 1000) // Keep Alive Interval (maximum)
+#define UDP_ACCELERATION_KEEPALIVE_TIMEOUT (9 * 1000) // Time to disconnect time by non-communication
+
+// Time constant for Build 8535 or later
+#define UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST (500) // Keep Alive Interval (minimum)
+#define UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST (1000) // Keep Alive Interval (maximum)
+#define UDP_ACCELERATION_KEEPALIVE_TIMEOUT_FAST (2100) // Time to disconnect time by non-communication
+
+// Range of port numbers
+#define UDP_SERVER_PORT_LOWER 40000 // Minimum port
+#define UDP_SERVER_PORT_HIGHER 44999 // Maximum port
+
+// NAT-T port signature to be embedded in the Keep Alive of the session
+#define UDP_NAT_T_PORT_SIGNATURE_IN_KEEP_ALIVE "NATT_MY_PORT"
+
+// UDP Acceleration Mode
+struct UDP_ACCEL
+{
+ CEDAR *Cedar; // Cedar
+ bool NoNatT; // Not to communicate with the NAT-T server (To communicate with the query server instead)
+ bool ClientMode; // Whether client mode
+ bool IsInCedarPortList; // Whether included in the port list of the Cedar
+ UINT64 Now; // Current time
+ UCHAR MyKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Submit-direction common key
+ UCHAR YourKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Receiving-direction common key
+ SOCK *UdpSock; // UDP socket
+ UINT MyPort; // My port number
+ UINT YourPort; // Port number of the other party
+ IP MyIp; // My IP address
+ IP YourIp; // IP address of the other party
+ IP YourIp2; // IP address of the other party (second)
+ bool IsIPv6; // Whether it's an IPv6
+ UCHAR TmpBuf[UDP_ACCELERATION_TMP_BUF_SIZE]; // Temporary buffer
+ UINT64 LastRecvYourTick; // Opponent's tick value of the last reception
+ UINT64 LastRecvMyTick; // My tick value of the last reception
+ QUEUE *RecvBlockQueue; // Reception block queue
+ bool UseHMac; // Flag to use the HMAC
+ bool PlainTextMode; // No encryption
+ UINT64 LastSetSrcIpAndPortTick; // Opponent's tick ??value at the time of storing the IP address and port number of the opponent at the end
+ UINT64 LastRecvTick; // Tick when data has received at the end
+ UINT64 NextSendKeepAlive; // Next time to send a KeepAlive packet
+ UCHAR NextIv[UDP_ACCELERATION_PACKET_IV_SIZE]; // IV to be used next
+ UINT MyCookie; // My cookie
+ UINT YourCookie; // Cookie of the other party
+ bool Inited; // Initialized flag
+ UINT Mss; // Optimal MSS
+ UINT MaxUdpPacketSize; // Get the maximum transmittable UDP size
+ LOCK *NatT_Lock; // Lock the IP address field of NAT-T server
+ IP NatT_IP; // IP address of the NAT-T server
+ THREAD *NatT_GetIpThread; // IP address acquisition thread of NAT-T server
+ bool NatT_Halt; // Halting flag of IP address acquisition thread of NAT-T server
+ EVENT *NatT_HaltEvent; // Halting event of IP address acquisition thread of NAT-T server
+ UINT64 NextPerformNatTTick; // Time to communicate with NAT-T server next time
+ UINT CommToNatT_NumFail; // Number of failures to communicate with NAT-T server
+ UINT MyPortByNatTServer; // Self port number which is received from the NAT-T server
+ bool MyPortByNatTServerChanged; // The self port number which is received from the NAT-T server changes
+ UINT YourPortByNatTServer; // Port number of the opponent that was found via the NAT-T server
+ bool YourPortByNatTServerChanged; // Port number of the opponent that was found via the NAT-T server has been changed
+ bool FatalError; // A fatal error occurred
+ bool NatT_IP_Changed; // IP address of the NAT-T server has changed
+ UINT64 NatT_TranId; // Transaction ID to be exchanged with the NAT-T server
+ bool IsReachedOnce; // It is true if it succeeds in mutual transmission and reception of packets at least once
+ UINT64 CreatedTick; // Object creation time
+ bool FastDetect; // Fast disconnection detection mode
+ UINT64 FirstStableReceiveTick; // Start time of current stable continued receivable period
+ bool UseUdpIpQuery; // Use the self IP address query by UDP
+ IP UdpIpQueryHost; // Host for the self IP address query by UDP
+ UINT UdpIpQueryPort; // Port number for self IP address for query by UDP
+ UCHAR UdpIpQueryPacketData[16]; // Query packet data (final transmission)
+ UINT UdpIpQueryPacketSize; // Query packet data size (final transmission)
+ UCHAR UdpHostUniqueKey[SHA1_SIZE]; // Unique key for UDP self endpoint query
+};
+
+// Function prototype
+UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t);
+void FreeUdpAccel(UDP_ACCEL *a);
+bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *server_key, IP *server_ip, UINT server_port, UINT server_cookie, UINT client_cookie, IP *server_ip_2);
+bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT client_port, IP *client_ip_2);
+void UdpAccelPoll(UDP_ACCEL *a);
+void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64);
+BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port);
+void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv);
+bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive);
+void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority);
+void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b);
+UINT UdpAccelCalcMss(UDP_ACCEL *a);
+void NatT_GetIpThread(THREAD *thread, void *param);
+
+#endif // UDPACCEL_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VG.c b/src/Cedar/VG.c
new file mode 100644
index 00000000..6c7c5638
--- /dev/null
+++ b/src/Cedar/VG.c
@@ -0,0 +1,105 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VG.c
+// VPN Gate Plugin Main Implementation
+
+#include "CedarPch.h"
+
+
+bool InitVg()
+{
+ return false;
+}
+
+void FreeVg()
+{
+}
+
+void VgUseStaticLink()
+{
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VG.h b/src/Cedar/VG.h
new file mode 100644
index 00000000..54339232
--- /dev/null
+++ b/src/Cedar/VG.h
@@ -0,0 +1,101 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VG.h
+// Header for VG.c
+
+#ifndef VG_H
+#define VG_H
+
+#define VG_HUBNAME "VPNGATE"
+
+
+bool InitVg();
+void FreeVg();
+void VgUseStaticLink();
+
+#endif // VG_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLan.c b/src/Cedar/VLan.c
new file mode 100644
index 00000000..6186e2b6
--- /dev/null
+++ b/src/Cedar/VLan.c
@@ -0,0 +1,108 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLan.c
+// Virtual LAN card adapter manipulation library
+
+#include <GlobalConst.h>
+
+#define VLAN_C
+
+#ifdef WIN32
+#define OS_WIN32
+#endif
+
+#ifdef OS_WIN32
+
+// For Win32
+#include "VLanWin32.c"
+
+#else
+
+// For UNIX
+#include "VLanUnix.c"
+
+#endif // OS_WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLan.h b/src/Cedar/VLan.h
new file mode 100644
index 00000000..1c2fdba7
--- /dev/null
+++ b/src/Cedar/VLan.h
@@ -0,0 +1,112 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLan.h
+// Header of VLan.c
+
+#ifndef VLAN_H
+#define VLAN_H
+
+// Parameters related to VLAN
+struct VLAN_PARAM
+{
+ UCHAR MacAddress[6];
+ UCHAR Padding[2];
+};
+
+#ifdef OS_WIN32
+
+// For Win32
+#include <Cedar/VLanWin32.h>
+
+#else // OS_WIN32
+
+// For UNIX
+#include <Cedar/VLanUnix.h>
+
+#endif // OS_WIN32
+
+#endif // VLAN_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLanUnix.c b/src/Cedar/VLanUnix.c
new file mode 100644
index 00000000..c3e77d0c
--- /dev/null
+++ b/src/Cedar/VLanUnix.c
@@ -0,0 +1,791 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLanUnix.c
+// Virtual device driver library for UNIX
+
+#include <GlobalConst.h>
+
+#ifdef VLAN_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+#ifdef OS_UNIX
+
+static LIST *unix_vlan = NULL;
+
+#ifndef NO_VLAN
+
+// Get the PACKET_ADAPTER
+PACKET_ADAPTER *VLanGetPacketAdapter()
+{
+ PACKET_ADAPTER *pa;
+
+ pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
+ VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
+ if (pa == NULL)
+ {
+ return NULL;
+ }
+
+ return pa;
+}
+
+// PA initialization
+bool VLanPaInit(SESSION *s)
+{
+ VLAN *v;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ // Connect to the driver
+ v = NewVLan(s->ClientOption->DeviceName, NULL);
+ if (v == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ s->PacketAdapter->Param = v;
+
+ return true;
+}
+
+// Get the cancel object
+CANCEL *VLanPaGetCancel(SESSION *s)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return NULL;
+ }
+
+ return VLanGetCancel(v);
+}
+
+// Release the packet adapter
+void VLanPaFree(SESSION *s)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return;
+ }
+
+ // End the virtual LAN card
+ FreeVLan(v);
+
+ s->PacketAdapter->Param = NULL;
+}
+
+// Write a packet
+bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return false;
+ }
+
+ return VLanPutPacket(v, data, size);
+}
+
+// Get the next packet
+UINT VLanPaGetNextPacket(SESSION *s, void **data)
+{
+ VLAN *v;
+ UINT size;
+ // Validate arguments
+ if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return INFINITE;
+ }
+
+ if (VLanGetNextPacket(v, data, &size) == false)
+ {
+ return INFINITE;
+ }
+
+ return size;
+}
+
+// Write a packet to the virtual LAN card
+bool VLanPutPacket(VLAN *v, void *buf, UINT size)
+{
+ UINT ret;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+ if (size > MAX_PACKET_SIZE)
+ {
+ return false;
+ }
+ if (buf == NULL || size == 0)
+ {
+ if (buf != NULL)
+ {
+ Free(buf);
+ }
+ return true;
+ }
+
+ ret = write(v->fd, buf, size);
+
+ if (ret >= 1)
+ {
+ Free(buf);
+ return true;
+ }
+
+ if (errno == EAGAIN || ret == 0)
+ {
+ Free(buf);
+ return true;
+ }
+
+ return false;
+}
+
+// Get the next packet from the virtual LAN card
+bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
+{
+ UCHAR tmp[TAP_READ_BUF_SIZE];
+ int ret;
+ // Validate arguments
+ if (v == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+
+ // Read
+ ret = read(v->fd, tmp, sizeof(tmp));
+
+ if (ret == 0 ||
+ (ret == -1 && errno == EAGAIN))
+ {
+ // No packet
+ *buf = NULL;
+ *size = 0;
+ return true;
+ }
+ else if (ret == -1 || ret > TAP_READ_BUF_SIZE)
+ {
+ // Error
+ return false;
+ }
+ else
+ {
+ // Reading packet success
+ *buf = Malloc(ret);
+ Copy(*buf, tmp, ret);
+ *size = ret;
+ return true;
+ }
+}
+
+// Get the cancel object
+CANCEL *VLanGetCancel(VLAN *v)
+{
+ CANCEL *c;
+ int fd;
+ int yes = 0;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ c = NewCancel();
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ c->pipe_read = c->pipe_write = -1;
+
+ fd = v->fd;
+
+#ifndef UNIX_MACOS
+ UnixSetSocketNonBlockingMode(fd, true);
+#else // UNIX_MACOS
+ UnixSetSocketNonBlockingMode(fd, false);
+#endif // UNIX_MACOS
+
+ c->SpecialFlag = true;
+ c->pipe_read = fd;
+
+ return c;
+}
+
+// Close the Virtual LAN card
+void FreeVLan(VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Free(v->InstanceName);
+
+ Free(v);
+}
+
+// Create a tap
+VLAN *NewTap(char *name, char *mac_address)
+{
+ int fd;
+ VLAN *v;
+ // Validate arguments
+ if (name == NULL || mac_address == NULL)
+ {
+ return NULL;
+ }
+
+ fd = UnixCreateTapDeviceEx(name, "tap", mac_address);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(VLAN));
+ v->Halt = false;
+ v->InstanceName = CopyStr(name);
+ v->fd = fd;
+
+ return v;
+}
+
+// Close the tap
+void FreeTap(VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ close(v->fd);
+ FreeVLan(v);
+}
+
+// Get the Virtual LAN card list
+VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
+{
+ int fd;
+ VLAN *v;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Open the tap
+ fd = UnixVLanGet(instance_name);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(VLAN));
+ v->Halt = false;
+ v->InstanceName = CopyStr(instance_name);
+ v->fd = fd;
+
+ return v;
+}
+
+// Create a tap device
+int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
+{
+ int fd;
+ struct ifreq ifr;
+ char eth_name[MAX_SIZE];
+ char instance_name_lower[MAX_SIZE];
+ struct sockaddr sa;
+ char *tap_name = TAP_FILENAME_1;
+ int s;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return -1;
+ }
+
+ // Generate the device name
+ StrCpy(instance_name_lower, sizeof(instance_name_lower), name);
+ Trim(instance_name_lower);
+ StrLower(instance_name_lower);
+ Format(eth_name, sizeof(eth_name), "%s_%s", prefix, instance_name_lower);
+
+ eth_name[15] = 0;
+
+ // Open the tun / tap
+#ifndef UNIX_MACOS
+ if (GetOsInfo()->OsType == OSTYPE_LINUX)
+ {
+ // Linux
+ if (IsFile(TAP_FILENAME_1) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ Format(tmp, sizeof(tmp), "%s c 10 200", TAP_FILENAME_1);
+ Run("mknod", tmp, true, true);
+
+ Format(tmp, sizeof(tmp), "600 %s", TAP_FILENAME_1);
+ Run("chmod", tmp, true, true);
+ }
+ }
+ // Other than MacOS X
+ fd = open(TAP_FILENAME_1, O_RDWR);
+ if (fd == -1)
+ {
+ // Failure
+ fd = open(TAP_FILENAME_2, O_RDWR);
+ if (fd == -1)
+ {
+ return -1;
+ }
+ tap_name = TAP_FILENAME_2;
+ }
+#else // UNIX_MACOS
+ // MacOS X
+ fd = open(TAP_MACOS_FILENAME, O_RDWR);
+ if (fd == -1)
+ {
+ return -1;
+ }
+ tap_name = TAP_MACOS_FILENAME;
+#endif // UNIX_MACOS
+
+#ifdef UNIX_LINUX
+ // Create a tap for Linux
+
+ // Set the device name
+ Zero(&ifr, sizeof(ifr));
+
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
+
+ if (ioctl(fd, TUNSETIFF, &ifr) == -1)
+ {
+ // Failure
+ close(fd);
+ return -1;
+ }
+
+ // MAC address setting
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s != -1)
+ {
+ if (mac_address != NULL)
+ {
+ Zero(&ifr, sizeof(ifr));
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
+ ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
+ Copy(&ifr.ifr_hwaddr.sa_data, mac_address, 6);
+ ioctl(s, SIOCSIFHWADDR, &ifr);
+ }
+
+ Zero(&ifr, sizeof(ifr));
+ StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
+ ioctl(s, SIOCGIFFLAGS, &ifr);
+
+ ifr.ifr_flags |= IFF_UP;
+ ioctl(s, SIOCSIFFLAGS, &ifr);
+
+ close(s);
+ }
+
+#else // UNIX_LINUX
+#ifdef UNIX_SOLARIS
+ // Create a tap for Solaris
+ {
+ int ip_fd;
+ int tun_fd;
+ int ppa;
+
+ tun_fd = open(tap_name, O_RDWR);
+ if (tun_fd == -1)
+ {
+ // Failure
+ close(fd);
+ return -1;
+ }
+
+ ip_fd = open("/dev/ip", O_RDWR);
+ if (ip_fd == -1)
+ {
+ // Failure
+ close(tun_fd);
+ close(fd);
+ return -1;
+ }
+
+ ppa = -1;
+ ppa = ioctl(tun_fd, TUNNEWPPA, ppa);
+ if (ppa == -1)
+ {
+ // Failure
+ close(tun_fd);
+ close(fd);
+ close(ip_fd);
+ return -1;
+ }
+
+ if (ioctl(fd, I_PUSH, "ip") < 0)
+ {
+ // Failure
+ close(tun_fd);
+ close(fd);
+ close(ip_fd);
+ return -1;
+ }
+
+ if (ioctl(fd, IF_UNITSEL, (char *)&ppa) < 0)
+ {
+ // Failure
+ close(tun_fd);
+ close(fd);
+ close(ip_fd);
+ return -1;
+ }
+
+ if (ioctl(ip_fd, I_LINK, fd) < 0)
+ {
+ // Failure
+ close(tun_fd);
+ close(fd);
+ close(ip_fd);
+ return -1;
+ }
+
+ close(tun_fd);
+ close(ip_fd);
+ }
+
+#endif // UNIX_SOLARIS
+#endif // UNIX_LINUX
+
+ return fd;
+}
+int UnixCreateTapDevice(char *name, UCHAR *mac_address)
+{
+ return UnixCreateTapDeviceEx(name, "vpn", mac_address);
+}
+
+// Close the tap device
+void UnixCloseTapDevice(int fd)
+{
+ // Validate arguments
+ if (fd == -1)
+ {
+ return;
+ }
+
+ close(fd);
+}
+
+#else // NO_VLAN
+
+void UnixCloseTapDevice(int fd)
+{
+}
+
+int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
+{
+ return -1;
+}
+int UnixCreateTapDevice(char *name, UCHAR *mac_address)
+{
+ return -1;
+}
+
+#endif // NO_VLAN
+
+// Comparison of the VLAN list entries
+int UnixCompareVLan(void *p1, void *p2)
+{
+ UNIX_VLAN_LIST *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(UNIX_VLAN_LIST **)p1;
+ v2 = *(UNIX_VLAN_LIST **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// Initialize the VLAN list
+void UnixVLanInit()
+{
+ unix_vlan = NewList(UnixCompareVLan);
+}
+
+// Create a VLAN
+bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address)
+{
+ // Validate arguments
+ char tmp[MAX_SIZE];
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ Trim(tmp);
+ name = tmp;
+
+ LockList(unix_vlan);
+ {
+ UNIX_VLAN_LIST *t, tt;
+ int fd;
+
+ // Check whether a device with the same name exists
+ Zero(&tt, sizeof(tt));
+ StrCpy(tt.Name, sizeof(tt.Name), name);
+
+ t = Search(unix_vlan, &tt);
+ if (t != NULL)
+ {
+ // Already exist
+ UnlockList(unix_vlan);
+ return false;
+ }
+
+ // Create a tap device
+ fd = UnixCreateTapDeviceEx(name, prefix, mac_address);
+ if (fd == -1)
+ {
+ // Failure to create
+ UnlockList(unix_vlan);
+ return false;
+ }
+
+ t = ZeroMalloc(sizeof(UNIX_VLAN_LIST));
+ t->fd = fd;
+ StrCpy(t->Name, sizeof(t->Name), name);
+
+ Insert(unix_vlan, t);
+ }
+ UnlockList(unix_vlan);
+
+ return true;
+}
+bool UnixVLanCreate(char *name, UCHAR *mac_address)
+{
+ return UnixVLanCreateEx(name, "vpn", mac_address);
+}
+
+// Enumerate VLANs
+TOKEN_LIST *UnixVLanEnum()
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ if (unix_vlan == NULL)
+ {
+ return NullToken();
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+
+ LockList(unix_vlan);
+ {
+ ret->NumTokens = LIST_NUM(unix_vlan);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
+
+ ret->Token[i] = CopyStr(t->Name);
+ }
+ }
+ UnlockList(unix_vlan);
+
+ return ret;
+}
+
+// Delete the VLAN
+void UnixVLanDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL || unix_vlan == NULL)
+ {
+ return;
+ }
+
+ LockList(unix_vlan);
+ {
+ UINT i;
+ UNIX_VLAN_LIST *t, tt;
+
+ Zero(&tt, sizeof(tt));
+ StrCpy(tt.Name, sizeof(tt.Name), name);
+
+ t = Search(unix_vlan, &tt);
+ if (t != NULL)
+ {
+ UnixCloseTapDevice(t->fd);
+ Delete(unix_vlan, t);
+ Free(t);
+ }
+ }
+ UnlockList(unix_vlan);
+}
+
+// Get the VLAN
+int UnixVLanGet(char *name)
+{
+ int fd = -1;
+ // Validate arguments
+ if (name == NULL || unix_vlan == NULL)
+ {
+ return -1;
+ }
+
+ LockList(unix_vlan);
+ {
+ UINT i;
+ UNIX_VLAN_LIST *t, tt;
+
+ Zero(&tt, sizeof(tt));
+ StrCpy(tt.Name, sizeof(tt.Name), name);
+
+ t = Search(unix_vlan, &tt);
+ if (t != NULL)
+ {
+ fd = t->fd;
+ }
+ }
+ UnlockList(unix_vlan);
+
+ return fd;
+}
+
+// Release the VLAN list
+void UnixVLanFree()
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(unix_vlan);i++)
+ {
+ UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
+
+ UnixCloseTapDevice(t->fd);
+ Free(t);
+ }
+
+ ReleaseList(unix_vlan);
+ unix_vlan = NULL;
+}
+
+#endif // OS_UNIX
+
+#endif // VLAN_C
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLanUnix.h b/src/Cedar/VLanUnix.h
new file mode 100644
index 00000000..90449494
--- /dev/null
+++ b/src/Cedar/VLanUnix.h
@@ -0,0 +1,144 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLanUnix.h
+// Header of VLanUnix.c
+
+#ifndef VLANUNIX_H
+#define VLANUNIX_H
+
+// Constant
+#define TAP_READ_BUF_SIZE 1600
+
+#ifndef NO_VLAN
+
+// VLAN structure
+struct VLAN
+{
+ volatile bool Halt; // Halt flag
+ char *InstanceName; // Instance name
+ int fd; // File
+};
+
+// Function prototype
+VLAN *NewVLan(char *instance_name, VLAN_PARAM *param);
+VLAN *NewTap(char *name, char *mac_address);
+void FreeVLan(VLAN *v);
+CANCEL *VLanGetCancel(VLAN *v);
+bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size);
+bool VLanPutPacket(VLAN *v, void *buf, UINT size);
+
+PACKET_ADAPTER *VLanGetPacketAdapter();
+bool VLanPaInit(SESSION *s);
+CANCEL *VLanPaGetCancel(SESSION *s);
+UINT VLanPaGetNextPacket(SESSION *s, void **data);
+bool VLanPaPutPacket(SESSION *s, void *data, UINT size);
+void VLanPaFree(SESSION *s);
+
+#else // NO_VLAN
+
+#define VLanGetPacketAdapter NullGetPacketAdapter
+
+#endif // NO_VLAN
+
+struct UNIX_VLAN_LIST
+{
+ char Name[MAX_SIZE]; // Device name
+ int fd; // fd
+};
+
+int UnixCreateTapDevice(char *name, UCHAR *mac_address);
+int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address);
+void UnixCloseTapDevice(int fd);
+void UnixVLanInit();
+void UnixVLanFree();
+bool UnixVLanCreate(char *name, UCHAR *mac_address);
+bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address);
+TOKEN_LIST *UnixVLanEnum();
+void UnixVLanDelete(char *name);
+int UnixVLanGet(char *name);
+int UnixCompareVLan(void *p1, void *p2);
+
+#endif // VLANUNIX_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLanWin32.c b/src/Cedar/VLanWin32.c
new file mode 100644
index 00000000..777c9ca0
--- /dev/null
+++ b/src/Cedar/VLanWin32.c
@@ -0,0 +1,1587 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLanWin32.c
+// Virtual device driver library for Win32
+
+#include <GlobalConst.h>
+
+#ifdef VLAN_C
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+#ifdef OS_WIN32
+
+typedef DWORD(CALLBACK* OPENVXDHANDLE)(HANDLE);
+
+// Get the version information of Windows
+void Win32GetWinVer(RPC_WINVER *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Zero(v, sizeof(RPC_WINVER));
+
+ v->IsWindows = true;
+
+ if (OS_IS_WINDOWS_NT(GetOsType()) == false)
+ {
+ // Windows 9x
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+
+ v->Build = LOWORD(os.dwBuildNumber);
+ v->VerMajor = os.dwMajorVersion;
+ v->VerMinor = os.dwMinorVersion;
+
+ Format(v->Title, sizeof(v->Title), "%s %s",
+ GetOsInfo()->OsProductName,
+ GetOsInfo()->OsVersion);
+ Trim(v->Title);
+ }
+ else
+ {
+ // Windows NT 4.0 SP6 or later
+ OSVERSIONINFOEX os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ Win32GetVersionExInternal((LPOSVERSIONINFOA)&os);
+
+ v->IsNT = true;
+ v->Build = os.dwBuildNumber;
+ v->ServicePack = os.wServicePackMajor;
+
+ if (os.wProductType != VER_NT_WORKSTATION)
+ {
+ v->IsServer = true;
+ }
+ v->VerMajor = os.dwMajorVersion;
+ v->VerMinor = os.dwMinorVersion;
+
+ if (GetOsInfo()->OsServicePack == 0)
+ {
+ StrCpy(v->Title, sizeof(v->Title), GetOsInfo()->OsProductName);
+ }
+ else
+ {
+ Format(v->Title, sizeof(v->Title), "%s Service Pack %u",
+ GetOsInfo()->OsProductName,
+ GetOsInfo()->OsServicePack);
+ }
+ Trim(v->Title);
+
+ if (InStr(GetOsInfo()->OsVersion, "rc") ||
+ InStr(GetOsInfo()->OsVersion, "beta"))
+ {
+ v->IsBeta = true;
+ }
+ }
+}
+
+// Release the DHCP addresses of all virtual LAN cards
+void Win32ReleaseAllDhcp9x(bool wait)
+{
+ TOKEN_LIST *t;
+ UINT i;
+
+ t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ UINT id = GetInstanceId(name);
+ if (id != 0)
+ {
+ Win32ReleaseDhcp9x(id, wait);
+ }
+ }
+
+ FreeToken(t);
+}
+
+// Routing table tracking main
+void RouteTrackingMain(SESSION *s)
+{
+ ROUTE_TRACKING *t;
+ UINT64 now;
+ ROUTE_TABLE *table;
+ ROUTE_ENTRY *rs;
+ bool changed = false;
+ bool check = false;
+ bool any_modified = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+ if (s->ClientModeAndUseVLan == false)
+ {
+ return;
+ }
+
+ // Get the state
+ t = ((VLAN *)s->PacketAdapter->Param)->RouteState;
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Current time
+ PROBE_STR("RouteTrackingMain 1");
+ now = Tick64();
+
+ if (t->RouteChange != NULL)
+ {
+ if (t->NextRouteChangeCheckTime == 0 ||
+ t->NextRouteChangeCheckTime <= now)
+ {
+ t->NextRouteChangeCheckTime = now + 1000ULL;
+
+ check = IsRouteChanged(t->RouteChange);
+
+ if (check)
+ {
+ Debug("*** Routing Table Changed ***\n");
+ t->NextTrackingTime = 0;
+ }
+ }
+ }
+ if (t->NextTrackingTime != 0 && t->NextTrackingTime > now)
+ {
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->NatT_IP_Changed)
+ {
+ // Check always if the IP address of the NAT-T server has changed
+ }
+ else
+ {
+ PROBE_STR("RouteTrackingMain 2");
+ return;
+ }
+ }
+ PROBE_STR("RouteTrackingMain 3");
+
+ if (s->UseUdpAcceleration && s->UdpAccel != NULL)
+ {
+ IP nat_t_ip;
+
+ s->UdpAccel->NatT_IP_Changed = false;
+
+ Zero(&nat_t_ip, sizeof(nat_t_ip));
+
+ Lock(s->UdpAccel->NatT_Lock);
+ {
+ Copy(&nat_t_ip, &s->UdpAccel->NatT_IP, sizeof(IP));
+ }
+ Unlock(s->UdpAccel->NatT_Lock);
+
+ // Add a route to the NAT-T server
+ if (IsZeroIp(&nat_t_ip) == false)
+ {
+ if (t->RouteToNatTServer == NULL)
+ {
+ if (t->RouteToEight != NULL)
+ {
+ ROUTE_ENTRY *e = Clone(t->RouteToEight, sizeof(ROUTE_ENTRY));
+ char ip_str[64];
+ char ip_str2[64];
+
+ Copy(&e->DestIP, &nat_t_ip, sizeof(IP));
+ e->Metric = e->OldIfMetric;
+
+ IPToStr(ip_str, sizeof(ip_str), &e->DestIP);
+ IPToStr(ip_str2, sizeof(ip_str2), &e->GatewayIP);
+
+ t->RouteToNatTServer = e;
+
+ if (AddRouteEntry(t->RouteToNatTServer))
+ {
+ Debug("Adding Static Route to %s via %s metric %u: ok.\n", ip_str, ip_str2, e->Metric);
+ }
+ else
+ {
+ FreeRouteEntry(t->RouteToNatTServer);
+ t->RouteToNatTServer = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ // Get the current routing table
+ table = GetRouteTable();
+ rs = t->RouteToServer;
+ if (table != NULL)
+ {
+ UINT i;
+ bool route_to_server_erased = true;
+ bool is_vlan_want_to_be_default_gateway = false;
+ UINT vlan_default_gatewat_metric = 0;
+ UINT other_if_default_gateway_metric_min = INFINITE;
+
+ // Get whether the routing table have been changed
+ if (t->LastRoutingTableHash != table->HashedValue)
+ {
+ t->LastRoutingTableHash = table->HashedValue;
+ changed = true;
+ }
+
+ //DebugPrintRouteTable(table);
+
+ // Scan the routing table
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+
+ if (rs != NULL)
+ {
+ if (CmpIpAddr(&e->DestIP, &rs->DestIP) == 0 &&
+ CmpIpAddr(&e->DestMask, &rs->DestMask) == 0
+// && CmpIpAddr(&e->GatewayIP, &rs->GatewayIP) == 0
+// && e->InterfaceID == rs->InterfaceID &&
+// e->LocalRouting == rs->LocalRouting &&
+// e->Metric == rs->Metric
+ )
+ {
+ // Routing entry to the server that added at the time of connection is found
+ route_to_server_erased = false;
+ }
+ }
+
+ // Search for the default gateway
+ if (IPToUINT(&e->DestIP) == 0 &&
+ IPToUINT(&e->DestMask) == 0)
+ {
+ Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
+ e->InterfaceID, t->VLanInterfaceId);
+
+ if (e->InterfaceID == t->VLanInterfaceId)
+ {
+ // The virtual LAN card think that he want to be a default gateway
+ is_vlan_want_to_be_default_gateway = true;
+ vlan_default_gatewat_metric = e->Metric;
+
+ if (vlan_default_gatewat_metric >= 2 &&
+ t->OldDefaultGatewayMetric == (vlan_default_gatewat_metric - 1))
+ {
+ // Restore because the PPP server rewrites
+ // the routing table selfishly
+ DeleteRouteEntry(e);
+ e->Metric--;
+ AddRouteEntry(e);
+ Debug("** Restore metric destroyed by PPP.\n");
+
+ any_modified = true;
+ }
+
+ // Keep this entry
+ if (t->DefaultGatewayByVLan != NULL)
+ {
+ // Delete if there is one added last time
+ FreeRouteEntry(t->DefaultGatewayByVLan);
+ }
+
+ t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY));
+ Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY));
+
+ t->OldDefaultGatewayMetric = vlan_default_gatewat_metric;
+ }
+ else
+ {
+ // There are default gateway other than the virtual LAN card
+ // Save the metric value of the default gateway
+ if (other_if_default_gateway_metric_min > e->Metric)
+ {
+ // Ignore the metric value of all PPP connection in the case of Windows Vista
+ if (MsIsVista() == false || e->PPPConnection == false)
+ {
+ other_if_default_gateway_metric_min = e->Metric;
+ }
+ else
+ {
+ // a PPP is used to Connect to the network
+ // in using Windows Vista
+ t->VistaAndUsingPPP = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (t->VistaAndUsingPPP)
+ {
+ if (t->DefaultGatewayByVLan != NULL)
+ {
+ if (is_vlan_want_to_be_default_gateway)
+ {
+ if (t->VistaOldDefaultGatewayByVLan == NULL || Cmp(t->VistaOldDefaultGatewayByVLan, t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY)) != 0)
+ {
+ ROUTE_ENTRY *e;
+ // Add the route of 0.0.0.0/1 and 128.0.0.0/1
+ // to the system if the virtual LAN card should be
+ // the default gateway in the case of the connection
+ // using PPP in Windows Vista
+
+ if (t->VistaOldDefaultGatewayByVLan != NULL)
+ {
+ FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
+ }
+
+ if (t->VistaDefaultGateway1 != NULL)
+ {
+ DeleteRouteEntry(t->VistaDefaultGateway1);
+ FreeRouteEntry(t->VistaDefaultGateway1);
+
+ DeleteRouteEntry(t->VistaDefaultGateway2);
+ FreeRouteEntry(t->VistaDefaultGateway2);
+ }
+
+ t->VistaOldDefaultGatewayByVLan = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
+
+ e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
+ SetIP(&e->DestIP, 0, 0, 0, 0);
+ SetIP(&e->DestMask, 128, 0, 0, 0);
+ t->VistaDefaultGateway1 = e;
+
+ e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
+ SetIP(&e->DestIP, 128, 0, 0, 0);
+ SetIP(&e->DestMask, 128, 0, 0, 0);
+ t->VistaDefaultGateway2 = e;
+
+ AddRouteEntry(t->VistaDefaultGateway1);
+ AddRouteEntry(t->VistaDefaultGateway2);
+
+ Debug("Vista PPP Fix Route Table Added.\n");
+
+ any_modified = true;
+ }
+ }
+ else
+ {
+ if (t->VistaOldDefaultGatewayByVLan != NULL)
+ {
+ FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
+ t->VistaOldDefaultGatewayByVLan = NULL;
+ }
+
+ if (t->VistaDefaultGateway1 != NULL)
+ {
+ Debug("Vista PPP Fix Route Table Deleted.\n");
+ DeleteRouteEntry(t->VistaDefaultGateway1);
+ FreeRouteEntry(t->VistaDefaultGateway1);
+
+ DeleteRouteEntry(t->VistaDefaultGateway2);
+ FreeRouteEntry(t->VistaDefaultGateway2);
+
+ any_modified = true;
+
+ t->VistaDefaultGateway1 = t->VistaDefaultGateway2 = NULL;
+ }
+ }
+ }
+ }
+
+ // If the virtual LAN card want to be the default gateway and
+ // there is no LAN card with smaller metric of 0.0.0.0/0 than
+ // the virtual LAN card, delete other default gateway entries
+ // to elect the virtual LAN card as the default gateway
+// Debug("is_vlan_want_to_be_default_gateway = %u, rs = %u, route_to_server_erased = %u, other_if_default_gateway_metric_min = %u, vlan_default_gatewat_metric = %u\n",
+// is_vlan_want_to_be_default_gateway, rs, route_to_server_erased, other_if_default_gateway_metric_min, vlan_default_gatewat_metric);
+ if (is_vlan_want_to_be_default_gateway && (rs != NULL && route_to_server_erased == false) &&
+ other_if_default_gateway_metric_min >= vlan_default_gatewat_metric)
+ {
+ // Scan the routing table again
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+
+ if (e->InterfaceID != t->VLanInterfaceId)
+ {
+ if (IPToUINT(&e->DestIP) == 0 &&
+ IPToUINT(&e->DestMask) == 0)
+ {
+ char str[64];
+ // Default gateway is found
+ ROUTE_ENTRY *r = ZeroMalloc(sizeof(ROUTE_ENTRY));
+
+ Copy(r, e, sizeof(ROUTE_ENTRY));
+
+ // Put in the queue
+ InsertQueue(t->DeletedDefaultGateway, r);
+
+ // Delete this gateway entry once
+ DeleteRouteEntry(e);
+
+ IPToStr(str, sizeof(str), &e->GatewayIP);
+ Debug("Default Gateway %s Deleted.\n", str);
+
+ any_modified = true;
+ }
+ }
+ }
+ }
+
+ if (rs != NULL && route_to_server_erased)
+ {
+ // Physical entry to the server has disappeared
+ Debug("Route to Server entry ERASED !!!\n");
+
+ // Forced disconnection (reconnection enabled)
+ s->RetryFlag = true;
+ s->Halt = true;
+ }
+
+ // Release the routing table
+ FreeRouteTable(table);
+ }
+
+ // Set the time to perform the next track
+ if (t->NextTrackingTimeAdd == 0 || changed)
+ {
+ t->NextTrackingTimeAdd = TRACKING_INTERVAL_INITIAL;
+ }
+ else
+ {
+ UINT64 max_value = TRACKING_INTERVAL_MAX;
+ if (t->RouteChange != NULL)
+ {
+ max_value = TRACKING_INTERVAL_MAX_RC;
+ }
+
+ t->NextTrackingTimeAdd += TRACKING_INTERVAL_ADD;
+
+ if (t->NextTrackingTimeAdd >= max_value)
+ {
+ t->NextTrackingTimeAdd = max_value;
+ }
+ }
+ //Debug("t->NextTrackingTimeAdd = %I64u\n", t->NextTrackingTimeAdd);
+ t->NextTrackingTime = now + t->NextTrackingTimeAdd;
+
+ if (any_modified)
+ {
+ // Clear the DNS cache
+ Win32FlushDnsCache();
+ }
+}
+
+// Start tracking of the routing table
+void RouteTrackingStart(SESSION *s)
+{
+ VLAN *v;
+ ROUTE_TRACKING *t;
+ UINT if_id = 0;
+ ROUTE_ENTRY *e;
+ ROUTE_ENTRY *dns = NULL;
+ ROUTE_ENTRY *route_to_real_server_global = NULL;
+ char tmp[64];
+ UINT exclude_if_id = 0;
+ bool already_exists = false;
+ bool already_exists_by_other_account = false;
+ IP eight;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ v = (VLAN *)s->PacketAdapter->Param;
+ if (v->RouteState != NULL)
+ {
+ return;
+ }
+
+ // Get the interface ID of the virtual LAN card
+ if_id = GetInstanceId(v->InstanceName);
+ Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id);
+
+ if (MsIsVista())
+ {
+ // The routing table by the virtual LAN card body should be
+ // excluded explicitly in Windows Vista
+ exclude_if_id = if_id;
+ }
+
+ // Get the route to the server
+ e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id);
+ if (e == NULL)
+ {
+ // Acquisition failure
+ Debug("Failed to get GetBestRouteEntry().\n");
+ return;
+ }
+ IPToStr(tmp, sizeof(tmp), &e->GatewayIP);
+ Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp);
+
+ // Add a route
+ if (MsIsVista())
+ {
+ e->Metric = e->OldIfMetric;
+ }
+ if (AddRouteEntryEx(e, &already_exists) == false)
+ {
+ FreeRouteEntry(e);
+ e = NULL;
+ }
+ Debug("already_exists: %u\n", already_exists);
+
+ if (already_exists)
+ {
+ if (s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ UINT i;
+ ACCOUNT *a;
+ for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
+ {
+ a = LIST_DATA(s->Cedar->Client->AccountList, i);
+ Lock(a->lock);
+ {
+ SESSION *sess = a->ClientSession;
+ if (sess != NULL && sess != s)
+ {
+ VLAN *v = sess->PacketAdapter->Param;
+ if (v != NULL)
+ {
+ ROUTE_TRACKING *tr = v->RouteState;
+ if (tr != NULL && e != NULL)
+ {
+ if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0)
+ {
+ already_exists_by_other_account = true;
+ }
+ }
+ }
+ }
+ }
+ Unlock(a->lock);
+ }
+ }
+
+ if (already_exists_by_other_account)
+ {
+ Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account);
+ already_exists = false;
+ }
+ }
+
+ // Get the routing table to the DNS server
+ // (If the DNS server is this PC itself, there's no need to get)
+ if (IsZeroIP(&s->DefaultDns) == false)
+ {
+ if (IsMyIPAddress(&s->DefaultDns) == false)
+ {
+ dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id);
+ if (dns == NULL)
+ {
+ // Getting failure
+ Debug("Failed to get GetBestRouteEntry DNS.\n");
+ }
+ else
+ {
+ // Add a route
+ if (MsIsVista())
+ {
+ dns->Metric = dns->OldIfMetric;
+
+ if (AddRouteEntry(dns) == false)
+ {
+ FreeRouteEntry(dns);
+ dns = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ if (s->IsAzureSession && IsZeroIP(&s->AzureRealServerGlobalIp) == false)
+ {
+ // Add also a static route to the real server in the case of via VPN Azure
+ if (IsMyIPAddress(&s->AzureRealServerGlobalIp) == false)
+ {
+ route_to_real_server_global = GetBestRouteEntryEx(&s->AzureRealServerGlobalIp, exclude_if_id);
+
+ if (route_to_real_server_global != NULL)
+ {
+ if (MsIsVista())
+ {
+ route_to_real_server_global->Metric = route_to_real_server_global->OldIfMetric;
+ }
+
+ if (AddRouteEntry(route_to_real_server_global) == false)
+ {
+ FreeRouteEntry(route_to_real_server_global);
+ route_to_real_server_global = NULL;
+ }
+ }
+ }
+ }
+
+ // Initialize
+ if (s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ Lock(s->Account->lock);
+ }
+
+ t = ZeroMalloc(sizeof(ROUTE_TRACKING));
+ v->RouteState = t;
+
+ t->RouteToServerAlreadyExists = already_exists;
+ t->RouteToServer = e;
+ t->RouteToDefaultDns = dns;
+ t->RouteToRealServerGlobal = route_to_real_server_global;
+ t->VLanInterfaceId = if_id;
+ t->NextTrackingTime = 0;
+ t->DeletedDefaultGateway = NewQueue();
+ t->OldDefaultGatewayMetric = 0x7fffffff;
+
+ if (s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ Unlock(s->Account->lock);
+ }
+
+ // Get the route to 8.8.8.8
+ SetIP(&eight, 8, 8, 8, 8);
+ t->RouteToEight = GetBestRouteEntryEx(&eight, exclude_if_id);
+
+ // Get the current default DNS server to detect network changes
+ GetDefaultDns(&t->OldDnsServer);
+
+ // Get as soon as releasing the IP address in the case of using DHCP
+ if (IsNt())
+ {
+ char tmp[MAX_SIZE];
+ MS_ADAPTER *a;
+
+ Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
+ a = MsGetAdapter(tmp);
+
+ if (a != NULL)
+ {
+ if (a->UseDhcp)
+ {
+ bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100);
+ Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret);
+
+ ret = Win32RenewAddressByGuidEx(a->Guid, 100);
+ Debug("*** Win32RenewAddressByGuidEx = %u\n", ret);
+ }
+
+ MsFreeAdapter(a);
+ }
+ }
+ else
+ {
+ // For Win9x
+ Win32RenewDhcp9x(if_id);
+ }
+
+ // Clear the DNS cache
+ Win32FlushDnsCache();
+
+ // Detect a change in the routing table (for only supported OS)
+ t->RouteChange = NewRouteChange();
+ Debug("t->RouteChange = 0x%p\n", t->RouteChange);
+}
+
+// End the tracking of the routing table
+void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t)
+{
+ ROUTE_ENTRY *e;
+ ROUTE_TABLE *table;
+ IP dns_ip;
+ bool network_has_changed = false;
+ bool do_not_delete_routing_entry = false;
+ // Validate arguments
+ if (s == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Zero(&dns_ip, sizeof(dns_ip));
+
+ // Remove the default gateway added by the virtual LAN card
+ if (MsIsVista() == false)
+ {
+ if (t->DefaultGatewayByVLan != NULL)
+ {
+ Debug("Default Gateway by VLAN was deleted.\n");
+ DeleteRouteEntry(t->DefaultGatewayByVLan);
+ }
+
+ if (t->VistaOldDefaultGatewayByVLan != NULL)
+ {
+ FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
+ }
+ }
+
+ if (t->DefaultGatewayByVLan != NULL)
+ {
+ FreeRouteEntry(t->DefaultGatewayByVLan);
+ t->DefaultGatewayByVLan = NULL;
+ }
+
+ if (t->VistaDefaultGateway1 != NULL)
+ {
+ Debug("Vista PPP Fix Route Table Deleted.\n");
+ DeleteRouteEntry(t->VistaDefaultGateway1);
+ FreeRouteEntry(t->VistaDefaultGateway1);
+
+ DeleteRouteEntry(t->VistaDefaultGateway2);
+ FreeRouteEntry(t->VistaDefaultGateway2);
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Only in the case of Windows 9x, release the DHCP address of the virtual LAN card
+ Win32ReleaseDhcp9x(t->VLanInterfaceId, false);
+ }
+
+ // Clear the DNS cache
+ Win32FlushDnsCache();
+
+ if (s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ UINT i;
+ ACCOUNT *a;
+ for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
+ {
+ a = LIST_DATA(s->Cedar->Client->AccountList, i);
+ Lock(a->lock);
+ {
+ SESSION *sess = a->ClientSession;
+ if (sess != NULL && sess != s)
+ {
+ VLAN *v = sess->PacketAdapter->Param;
+ if (v != NULL)
+ {
+ ROUTE_TRACKING *tr = v->RouteState;
+ if (tr != NULL)
+ {
+ if (Cmp(tr->RouteToServer, t->RouteToServer, sizeof(ROUTE_ENTRY)) == 0)
+ {
+ do_not_delete_routing_entry = true;
+ }
+ }
+ }
+ }
+ }
+ Unlock(a->lock);
+ }
+
+ Lock(s->Account->lock);
+ }
+
+ if (do_not_delete_routing_entry == false)
+ {
+ // Delete the route that is added firstly
+ if (t->RouteToServerAlreadyExists == false)
+ {
+ DeleteRouteEntry(t->RouteToServer);
+ }
+
+ DeleteRouteEntry(t->RouteToDefaultDns);
+
+ DeleteRouteEntry(t->RouteToNatTServer);
+
+ DeleteRouteEntry(t->RouteToRealServerGlobal);
+ }
+
+ FreeRouteEntry(t->RouteToDefaultDns);
+ FreeRouteEntry(t->RouteToServer);
+ FreeRouteEntry(t->RouteToEight);
+ FreeRouteEntry(t->RouteToNatTServer);
+ FreeRouteEntry(t->RouteToRealServerGlobal);
+ t->RouteToDefaultDns = t->RouteToServer = t->RouteToEight =
+ t->RouteToNatTServer = t->RouteToRealServerGlobal = NULL;
+
+ if (s->Cedar->Client != NULL && s->Account != NULL)
+ {
+ Unlock(s->Account->lock);
+ }
+
+#if 0
+ // Get the current DNS server
+ if (GetDefaultDns(&dns_ip))
+ {
+ if (IPToUINT(&t->OldDnsServer) != 0)
+ {
+ if (IPToUINT(&t->OldDnsServer) != IPToUINT(&dns_ip))
+ {
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ network_has_changed = true;
+ IPToStr(s1, sizeof(s1), &t->OldDnsServer);
+ IPToStr(s2, sizeof(s2), &dns_ip);
+ Debug("Old Dns: %s, New Dns: %s\n",
+ s1, s2);
+ }
+ }
+ }
+
+ if (network_has_changed == false)
+ {
+ Debug("Network: not changed.\n");
+ }
+ else
+ {
+ Debug("Network: Changed.\n");
+ }
+
+#endif
+
+ // Get the current routing table
+ table = GetRouteTable();
+
+ // Restore the routing table which has been removed so far
+ while (e = GetNext(t->DeletedDefaultGateway))
+ {
+ bool restore = true;
+ UINT i;
+ // If the restoring routing entry is a default gateway and
+ // the existing routing table contains another default gateway
+ // on the interface, give up restoring the entry
+ if (IPToUINT(&e->DestIP) == 0 && IPToUINT(&e->DestMask) == 0)
+ {
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *r = table->Entry[i];
+ if (IPToUINT(&r->DestIP) == 0 && IPToUINT(&r->DestMask) == 0)
+ {
+ if (r->InterfaceID == e->InterfaceID)
+ {
+ restore = false;
+ }
+ }
+ }
+ if (network_has_changed)
+ {
+ restore = false;
+ }
+ }
+
+ if (restore)
+ {
+ // Routing table restoration
+ AddRouteEntry(e);
+ }
+
+ // Memory release
+ FreeRouteEntry(e);
+ }
+
+ // Release
+ FreeRouteTable(table);
+ ReleaseQueue(t->DeletedDefaultGateway);
+
+ FreeRouteChange(t->RouteChange);
+
+ Free(t);
+}
+
+// Get the instance ID of the virtual LAN card
+UINT GetInstanceId(char *name)
+{
+ char tmp[MAX_SIZE];
+ UINT id = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, name);
+
+ id = GetVLanInterfaceID(tmp);
+ if (id != 0)
+ {
+ return id;
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG_OLD, name);
+
+ id = GetVLanInterfaceID(tmp);
+ return id;
+ }
+}
+
+// Get the instance list of virtual LAN card
+INSTANCE_LIST *GetInstanceList()
+{
+ INSTANCE_LIST *n = ZeroMalloc(sizeof(INSTANCE_LIST));
+
+ // Enumeration
+ char **ss = EnumVLan(VLAN_ADAPTER_NAME);
+
+ if (ss == NULL)
+ {
+ // Failure
+ n->NumInstance = 0;
+ n->InstanceName = Malloc(0);
+ return n;
+ }
+ else
+ {
+ UINT i, num;
+ i = num = 0;
+ while (true)
+ {
+ if (ss[i++] == NULL)
+ {
+ break;
+ }
+ num++;
+ }
+ i = 0;
+ n->NumInstance = num;
+ n->InstanceName = (char **)ZeroMalloc(sizeof(char *) * n->NumInstance);
+ for (i = 0;i < num;i++)
+ {
+ char *s = ss[i] + StrLen(VLAN_ADAPTER_NAME) + StrLen(" - ");
+ if (StrLen(ss[i]) > StrLen(VLAN_ADAPTER_NAME) + StrLen(" - "))
+ {
+ n->InstanceName[i] = CopyStr(s);
+ }
+ }
+ FreeEnumVLan(ss);
+ }
+
+ ss = EnumVLan(VLAN_ADAPTER_NAME_OLD);
+ if (ss != NULL)
+ {
+ UINT i, num, j;
+
+ i = num = 0;
+ while (true)
+ {
+ if (ss[i++] == NULL)
+ {
+ break;
+ }
+ num++;
+ }
+ j = n->NumInstance;
+ n->NumInstance += num;
+ n->InstanceName = (char **)ReAlloc(n->InstanceName, sizeof(char) * n->NumInstance);
+ for (i = 0;i < num;i++)
+ {
+ char *s = ss[i] + StrLen(VLAN_ADAPTER_NAME_OLD) + StrLen(" - ");
+ if (StrLen(ss[i]) > StrLen(VLAN_ADAPTER_NAME_OLD) + StrLen(" - "))
+ {
+ n->InstanceName[j] = CopyStr(s);
+ }
+ j++;
+ }
+ FreeEnumVLan(ss);
+ }
+
+ return n;
+}
+
+// Release the instance list
+void FreeInstanceList(INSTANCE_LIST *n)
+{
+ UINT i;
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < n->NumInstance;i++)
+ {
+ Free(n->InstanceName[i]);
+ }
+ Free(n->InstanceName);
+ Free(n);
+}
+
+// Release the packet adapter
+void VLanPaFree(SESSION *s)
+{
+ VLAN *v;
+ ROUTE_TRACKING *t;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return;
+ }
+
+ // Release the IP address if you are using DHCP
+ if (IsNt())
+ {
+ char tmp[MAX_SIZE];
+ MS_ADAPTER *a;
+
+ Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
+ a = MsGetAdapter(tmp);
+
+ if (a != NULL)
+ {
+ if (a->UseDhcp)
+ {
+ bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 50);
+ Debug("*** Win32ReleaseAddressByGuid = %u\n", ret);
+ }
+
+ MsFreeAdapter(a);
+ }
+ }
+
+ t = v->RouteState;
+ // End the virtual LAN card
+ FreeVLan(v);
+
+ // End the routing table tracking
+ if (s->ClientModeAndUseVLan)
+ {
+ RouteTrackingStop(s, t);
+ }
+ s->PacketAdapter->Param = NULL;
+}
+
+
+// Write a packet
+bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return false;
+ }
+
+ return VLanPutPacket(v, data, size);
+}
+
+// Get the next packet
+UINT VLanPaGetNextPacket(SESSION *s, void **data)
+{
+ VLAN *v;
+ UINT size;
+ // Validate arguments
+ if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return 0;
+ }
+
+ RouteTrackingMain(s);
+
+ if (VLanGetNextPacket(v, data, &size) == false)
+ {
+ return INFINITE;
+ }
+
+ return size;
+}
+
+// Get the cancel object
+CANCEL *VLanPaGetCancel(SESSION *s)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
+ {
+ return NULL;
+ }
+
+ return VLanGetCancel(v);
+}
+
+// Initialize the packet adapter
+bool VLanPaInit(SESSION *s)
+{
+ VLAN *v;
+ // Validate arguments
+ if ((s == NULL)/* || (s->ServerMode != false) || (s->ClientOption == NULL)*/)
+ {
+ return false;
+ }
+
+ // Get the IP address of the DNS server at the time just before the connection
+ if (s->ClientModeAndUseVLan)
+ {
+ Zero(&s->DefaultDns, sizeof(IP));
+ GetDefaultDns(&s->DefaultDns);
+ }
+
+ // Normalize the setting of interface metric of the default gateway
+ if (s->ClientModeAndUseVLan)
+ {
+ if (MsIsVista())
+ {
+ MsNormalizeInterfaceDefaultGatewaySettings(VLAN_ADAPTER_NAME_TAG, s->ClientOption->DeviceName);
+ MsNormalizeInterfaceDefaultGatewaySettings(VLAN_ADAPTER_NAME_TAG_OLD, s->ClientOption->DeviceName);
+ }
+ }
+
+ // Connect to the driver
+ v = NewVLan(s->ClientOption->DeviceName, NULL);
+ if (v == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ s->PacketAdapter->Param = v;
+
+ // Routing table tracking start
+ if (s->ClientModeAndUseVLan)
+ {
+ RouteTrackingStart(s);
+ }
+
+ return true;
+}
+
+// Get the packet adapter of the VLAN
+PACKET_ADAPTER *VLanGetPacketAdapter()
+{
+ PACKET_ADAPTER *pa;
+
+ pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
+ VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
+ if (pa == NULL)
+ {
+ return NULL;
+ }
+
+ return pa;
+}
+
+
+// Write the next received packet to the driver
+bool VLanPutPacket(VLAN *v, void *buf, UINT size)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+ if (size > MAX_PACKET_SIZE)
+ {
+ return false;
+ }
+
+ // First, examine whether the current buffer is full
+ if ((NEO_NUM_PACKET(v->PutBuffer) >= NEO_MAX_PACKET_EXCHANGE) ||
+ (buf == NULL && NEO_NUM_PACKET(v->PutBuffer) != 0))
+ {
+#ifdef USE_PROBE
+ {
+ char tmp[MAX_SIZE];
+ snprintf(tmp, sizeof(tmp), "VLanPutPacket: NEO_NUM_PACKET(v->PutBuffer) = %u", NEO_NUM_PACKET(v->PutBuffer));
+ PROBE_DATA2(tmp, NULL, 0);
+ }
+#endif // USE_PROBE
+ // Write a packet to the driver
+ if (VLanPutPacketsToDriver(v) == false)
+ {
+ return false;
+ }
+ NEO_NUM_PACKET(v->PutBuffer) = 0;
+ }
+
+ // Add the next packet to the buffer
+ if (buf != NULL)
+ {
+ UINT i = NEO_NUM_PACKET(v->PutBuffer);
+ NEO_NUM_PACKET(v->PutBuffer)++;
+
+ NEO_SIZE_OF_PACKET(v->PutBuffer, i) = size;
+ Copy(NEO_ADDR_OF_PACKET(v->PutBuffer, i), buf, size);
+ Free(buf);
+ }
+
+ return true;
+}
+
+// Read the next sent packet from the driver
+bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
+{
+ // Validate arguments
+ if (v == NULL || buf == NULL || size == NULL)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+
+ PROBE_STR("VLanGetNextPacket");
+
+ while (true)
+ {
+ if (v->CurrentPacketCount < NEO_NUM_PACKET(v->GetBuffer))
+ {
+ // There are still packets that have been read already
+ *size = NEO_SIZE_OF_PACKET(v->GetBuffer, v->CurrentPacketCount);
+ *buf = MallocFast(*size);
+ Copy(*buf, NEO_ADDR_OF_PACKET(v->GetBuffer, v->CurrentPacketCount), *size);
+
+ // Increment the packet number
+ v->CurrentPacketCount++;
+
+ return true;
+ }
+ else
+ {
+ // Read the next packet from the driver
+ if (VLanGetPacketsFromDriver(v) == false)
+ {
+ return false;
+ }
+
+ if (NEO_NUM_PACKET(v->GetBuffer) == 0)
+ {
+ // Packet is not received currently
+ *buf = NULL;
+ *size = 0;
+ return true;
+ }
+
+ v->CurrentPacketCount = 0;
+ }
+ }
+}
+
+// Write all the current packets to the driver
+bool VLanPutPacketsToDriver(VLAN *v)
+{
+ DWORD write_size;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+
+ if (v->Win9xMode == false)
+ {
+ // Windows NT
+ PROBE_STR("VLanPutPacketsToDriver: WriteFile");
+ if (WriteFile(v->Handle, v->PutBuffer, NEO_EXCHANGE_BUFFER_SIZE, &write_size,
+ NULL) == false)
+ {
+ v->Halt = true;
+ return false;
+ }
+ PROBE_STR("VLanPutPacketsToDriver: WriteFile Completed.");
+
+ if (write_size != NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ v->Halt = true;
+ return false;
+ }
+ }
+ else
+ {
+ // Windows 9x
+ if (DeviceIoControl(v->Handle, NEO_IOCTL_PUT_PACKET, v->PutBuffer,
+ NEO_EXCHANGE_BUFFER_SIZE, NULL, 0, &write_size, NULL) == false)
+ {
+ v->Halt = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Read the next packet from the driver
+bool VLanGetPacketsFromDriver(VLAN *v)
+{
+ DWORD read_size;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+ if (v->Halt)
+ {
+ return false;
+ }
+
+ if (v->Win9xMode == false)
+ {
+ // Windows NT
+ PROBE_STR("VLanGetPacketsFromDriver: ReadFile");
+ if (ReadFile(v->Handle, v->GetBuffer, NEO_EXCHANGE_BUFFER_SIZE,
+ &read_size, NULL) == false)
+ {
+ v->Halt = true;
+ return false;
+ }
+ }
+ else
+ {
+ // Windows 9x
+ if (DeviceIoControl(v->Handle, NEO_IOCTL_GET_PACKET, NULL, 0,
+ v->GetBuffer, NEO_EXCHANGE_BUFFER_SIZE, &read_size, NULL) == false)
+ {
+ v->Halt = true;
+ return false;
+ }
+ }
+
+ if (read_size != NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ v->Halt = true;
+ return false;
+ }
+
+ return true;
+}
+
+// Get the cancel object
+CANCEL *VLanGetCancel(VLAN *v)
+{
+ CANCEL *c;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a cancel object
+ c = NewCancel();
+ c->SpecialFlag = true;
+ CloseHandle(c->hEvent);
+
+ c->hEvent = v->Event;
+
+ return c;
+}
+
+// Release the VLAN object
+void FreeVLan(VLAN *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Close the handle
+ CloseHandle(v->Event);
+ CloseHandle(v->Handle);
+
+ // Memory release
+ Free(v->InstanceName);
+ Free(v->EventNameWin32);
+ Free(v->DeviceNameWin32);
+ Free(v->PutBuffer);
+ Free(v->GetBuffer);
+ Free(v);
+}
+
+// Create a VLAN object
+VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
+{
+ VLAN *v;
+ HANDLE h = INVALID_HANDLE_VALUE;
+ HANDLE e = INVALID_HANDLE_VALUE;
+ char tmp[MAX_SIZE];
+ char name_upper[MAX_SIZE];
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(VLAN));
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ v->Win9xMode = true;
+ }
+
+ // Initialize the name
+ Format(name_upper, sizeof(name_upper), "%s", instance_name);
+ StrUpper(name_upper);
+ v->InstanceName = CopyStr(name_upper);
+ Format(tmp, sizeof(tmp), NDIS_NEO_DEVICE_FILE_NAME, v->InstanceName);
+ v->DeviceNameWin32 = CopyStr(tmp);
+
+ if (v->Win9xMode == false)
+ {
+ Format(tmp, sizeof(tmp), NDIS_NEO_EVENT_NAME_WIN32, v->InstanceName);
+ v->EventNameWin32 = CopyStr(tmp);
+ }
+
+ // Connect to the device
+ h = CreateFile(v->DeviceNameWin32,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ // Connection failure
+ goto CLEANUP;
+ }
+
+ if (v->Win9xMode == false)
+ {
+ // Connect to the event
+ e = OpenEvent(SYNCHRONIZE, FALSE, v->EventNameWin32);
+ if (e == INVALID_HANDLE_VALUE)
+ {
+ // Connection failure
+ goto CLEANUP;
+ }
+ }
+ else
+ {
+ OPENVXDHANDLE OpenVxDHandle;
+ DWORD vxd_handle;
+ UINT bytes_returned;
+
+ OpenVxDHandle = (OPENVXDHANDLE)GetProcAddress(GetModuleHandle("KERNEL32"),
+ "OpenVxDHandle");
+
+ // Deliver to the driver by creating an event
+ e = CreateEvent(NULL, FALSE, FALSE, NULL);
+ vxd_handle = (DWORD)OpenVxDHandle(e);
+
+ DeviceIoControl(h, NEO_IOCTL_SET_EVENT, &vxd_handle, sizeof(DWORD),
+ NULL, 0, &bytes_returned, NULL);
+ }
+
+ v->Event = e;
+ v->Handle = h;
+
+ v->GetBuffer = ZeroMalloc(NEO_EXCHANGE_BUFFER_SIZE);
+ v->PutBuffer = ZeroMalloc(NEO_EXCHANGE_BUFFER_SIZE);
+
+ return v;
+
+CLEANUP:
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(h);
+ }
+ if (e != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(e);
+ }
+
+ Free(v->InstanceName);
+ Free(v->EventNameWin32);
+ Free(v->DeviceNameWin32);
+ Free(v);
+
+ return NULL;
+}
+
+#endif // OS_WIN32
+
+#endif //VLAN_C
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/VLanWin32.h b/src/Cedar/VLanWin32.h
new file mode 100644
index 00000000..c481efd9
--- /dev/null
+++ b/src/Cedar/VLanWin32.h
@@ -0,0 +1,174 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// VLanWin32.h
+// Header of VLanWin32.c
+
+#ifndef VLANWIN32_H
+#define VLANWIN32_H
+
+// Routing table tracking timer
+#define TRACKING_INTERVAL_INITIAL 444 // Initial
+#define TRACKING_INTERVAL_ADD 444 // Adding value
+#define TRACKING_INTERVAL_MAX 12345 // Maximum value
+#define TRACKING_INTERVAL_MAX_RC 87654 // Maximum value (OS which change detection mechanism enabled)
+
+
+typedef void *HANDLE;
+
+// Routing tracking state machine
+struct ROUTE_TRACKING
+{
+ UINT VLanInterfaceId;
+ ROUTE_ENTRY *RouteToServer;
+ bool RouteToServerAlreadyExists;
+ ROUTE_ENTRY *DefaultGatewayByVLan;
+ ROUTE_ENTRY *VistaDefaultGateway1, *VistaDefaultGateway2, *VistaOldDefaultGatewayByVLan;
+ ROUTE_ENTRY *RouteToDefaultDns;
+ ROUTE_ENTRY *RouteToEight;
+ ROUTE_ENTRY *RouteToNatTServer;
+ ROUTE_ENTRY *RouteToRealServerGlobal;
+ UINT64 NextTrackingTime;
+ UINT64 NextTrackingTimeAdd;
+ UINT64 NextRouteChangeCheckTime;
+ UINT LastRoutingTableHash;
+ QUEUE *DeletedDefaultGateway;
+ UINT OldDefaultGatewayMetric;
+ IP OldDnsServer;
+ bool VistaAndUsingPPP;
+ ROUTE_CHANGE *RouteChange;
+};
+
+// VLAN structure
+struct VLAN
+{
+ volatile bool Halt; // Halting flag
+ bool Win9xMode; // Windows 9x
+ char *InstanceName; // Instance name
+ char *DeviceNameWin32; // Win32 device name
+ char *EventNameWin32; // Win32 event name
+ HANDLE Handle; // Device driver file
+ HANDLE Event; // Handle of the event
+ void *GetBuffer; // Sent packet capturing buffer
+ UINT CurrentPacketCount; // Packet number to be read next
+ void *PutBuffer; // Buffer for writing received packet
+ ROUTE_TRACKING *RouteState; // Routing tracking state machine
+};
+
+// Instance list
+struct INSTANCE_LIST
+{
+ UINT NumInstance;
+ char **InstanceName;
+};
+
+
+// Function prototype
+VLAN *NewVLan(char *instance_name, VLAN_PARAM *param);
+void FreeVLan(VLAN *v);
+CANCEL *VLanGetCancel(VLAN *v);
+bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size);
+bool VLanGetPacketsFromDriver(VLAN *v);
+bool VLanPutPacketsToDriver(VLAN *v);
+bool VLanPutPacket(VLAN *v, void *buf, UINT size);
+
+PACKET_ADAPTER *VLanGetPacketAdapter();
+bool VLanPaInit(SESSION *s);
+CANCEL *VLanPaGetCancel(SESSION *s);
+UINT VLanPaGetNextPacket(SESSION *s, void **data);
+bool VLanPaPutPacket(SESSION *s, void *data, UINT size);
+void VLanPaFree(SESSION *s);
+
+INSTANCE_LIST *GetInstanceList();
+void FreeInstanceList(INSTANCE_LIST *n);
+UINT GetInstanceId(char *name);
+
+void RouteTrackingStart(SESSION *s);
+void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t);
+void RouteTrackingMain(SESSION *s);
+void Win32ReleaseAllDhcp9x(bool wait);
+
+void Win32GetWinVer(RPC_WINVER *v);
+
+#endif // VLANWIN32_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Virtual.c b/src/Cedar/Virtual.c
new file mode 100644
index 00000000..ebd32b58
--- /dev/null
+++ b/src/Cedar/Virtual.c
@@ -0,0 +1,10117 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Virtual.c
+// User-mode virtual host program
+
+#include "CedarPch.h"
+
+static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static char v_vgs_hostname[256] = {0};
+
+static char secure_nat_target_hostname[MAX_SIZE] = {0};
+
+// Specify the destination host name to be used for connectivity testing in SecureNAT
+void NnSetSecureNatTargetHostname(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(secure_nat_target_hostname, sizeof(secure_nat_target_hostname), name);
+}
+
+// Delete the oldest NAT session if necessary
+void NnDeleteOldestNatSessionIfNecessary(NATIVE_NAT *t, UINT ip, UINT protocol)
+{
+ UINT current_num;
+ UINT max_sessions = 0;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->v->HubOption != NULL)
+ {
+ HUB_OPTION *o = t->v->HubOption;
+
+ switch (protocol)
+ {
+ case NAT_TCP:
+ max_sessions = o->SecureNAT_MaxTcpSessionsPerIp;
+ break;
+
+ case NAT_UDP:
+ max_sessions = o->SecureNAT_MaxUdpSessionsPerIp;
+ break;
+
+ case NAT_ICMP:
+ max_sessions = o->SecureNAT_MaxIcmpSessionsPerIp;
+ break;
+ }
+ }
+
+ if (max_sessions == 0)
+ {
+ return;
+ }
+
+ current_num = NnGetNumNatEntriesPerIp(t, ip, protocol);
+
+ if (current_num >= max_sessions)
+ {
+ NnDeleteOldestNatSession(t, ip, protocol);
+ }
+}
+
+// Delete the oldest NAT session
+void NnDeleteOldestNatSession(NATIVE_NAT *t, UINT ip, UINT protocol)
+{
+ NATIVE_NAT_ENTRY *e;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ e = NnGetOldestNatEntryOfIp(t, ip, protocol);
+
+ if (e != NULL)
+ {
+ NnDeleteSession(t, e);
+ }
+}
+
+// Get the oldest NAT session
+NATIVE_NAT_ENTRY *NnGetOldestNatEntryOfIp(NATIVE_NAT *t, UINT ip, UINT protocol)
+{
+ UINT i;
+ NATIVE_NAT_ENTRY *oldest = NULL;
+ UINT64 oldest_tick = 0xFFFFFFFFFFFFFFFFULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(t->NatTableForRecv->AllList);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForRecv->AllList, i);
+
+ if (e->SrcIp == ip)
+ {
+ if (e->Protocol == protocol)
+ {
+ if (e->LastCommTime <= oldest_tick)
+ {
+ oldest_tick = e->LastCommTime;
+ oldest = e;
+ }
+ }
+ }
+ }
+
+ return oldest;
+}
+
+// Get the number of NAT sessions per IP address
+UINT NnGetNumNatEntriesPerIp(NATIVE_NAT *t, UINT src_ip, UINT protocol)
+{
+ UINT ret = 0;
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < LIST_NUM(t->NatTableForRecv->AllList);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForRecv->AllList, i);
+
+ if (e->SrcIp == src_ip)
+ {
+ if (e->Protocol == protocol)
+ {
+ ret++;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Delete the old NAT sessions
+void NnDeleteOldSessions(NATIVE_NAT *t)
+{
+ UINT i;
+ LIST *o;
+ UINT64 now;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ o = NULL;
+ now = t->v->Now;
+
+ for (i = 0;i < LIST_NUM(t->NatTableForSend->AllList);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForSend->AllList, i);
+ UINT64 timeout;
+
+ if (e->Status == NAT_TCP_CONNECTED || e->Status == NAT_TCP_ESTABLISHED)
+ {
+ timeout = e->LastCommTime + (UINT64)(e->Protocol == NAT_TCP ? t->v->NatTcpTimeout : t->v->NatUdpTimeout);
+ }
+ else
+ {
+ timeout = e->LastCommTime + (UINT64)NN_TIMEOUT_FOR_UNESTBALISHED_TCP;
+ }
+
+ if (timeout < now)
+ {
+ // Time-out occurs
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, e);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(o, i);
+
+ NnDeleteSession(t, e);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Delete the NAT entry
+void NnDeleteSession(NATIVE_NAT *t, NATIVE_NAT_ENTRY *e)
+{
+ // Validate arguments
+ if (t == NULL || e == NULL)
+ {
+ return;
+ }
+
+ switch (e->Protocol)
+ {
+ case NAT_TCP:
+ // Send a RST to the client side
+ SendTcp(t->v, e->DestIp, e->DestPort, e->SrcIp, e->SrcPort,
+ e->LastAck, e->LastSeq + (e->Status == NAT_TCP_CONNECTING ? 1 : 0), TCP_RST | TCP_ACK, 0, 0, NULL, 0);
+
+ NLog(t->v, "LH_NAT_TCP_DELETED", e->Id);
+ break;
+
+ case NAT_UDP:
+ NLog(t->v, "LH_NAT_UDP_DELETED", e->Id);
+ break;
+
+ case NAT_ICMP:
+ Debug("NAT ICMP %u Deleted.", e->Id);
+ break;
+ }
+
+ DeleteHash(t->NatTableForSend, e);
+ DeleteHash(t->NatTableForRecv, e);
+
+ Free(e);
+}
+
+// Poll the IP combining object
+void NnPollingIpCombine(NATIVE_NAT *t)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Discard the old combining object
+ o = NULL;
+ for (i = 0;i < LIST_NUM(t->IpCombine);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(t->IpCombine, i);
+
+ if (c->Expire < t->v->Now)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, c);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(o, i);
+
+ // Remove from the list
+ Delete(t->IpCombine, c);
+
+ // Release the memory
+ NnFreeIpCombine(t, c);
+ }
+ ReleaseList(o);
+ }
+}
+
+// Combine the IP packet received to the IP combining object
+void NnCombineIp(NATIVE_NAT *t, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size)
+{
+ UINT i;
+ IP_PART *p;
+ UINT need_size;
+ UINT data_size_delta;
+ // Validate arguments
+ if (c == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Check the size and offset
+ if ((offset + size) > 65535)
+ {
+ // Do not process a packet larger than 64Kbytes
+ return;
+ }
+
+ if (last_packet == false && c->Size != 0)
+ {
+ if ((offset + size) > c->Size)
+ {
+ // Do not process a packet larger than the packet size
+ return;
+ }
+ }
+
+ if (head_ip_header_data != NULL && head_ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ if (c->HeadIpHeaderData == NULL)
+ {
+ c->HeadIpHeaderData = Clone(head_ip_header_data, head_ip_header_size);
+ c->HeadIpHeaderDataSize = head_ip_header_size;
+ }
+ }
+
+ need_size = offset + size;
+ data_size_delta = c->DataReserved;
+ // Ensure sufficient if the buffer is insufficient
+ while (c->DataReserved < need_size)
+ {
+ c->DataReserved = c->DataReserved * 4;
+ c->Data = ReAlloc(c->Data, c->DataReserved);
+ }
+ data_size_delta = c->DataReserved - data_size_delta;
+ t->CurrentIpQuota += data_size_delta;
+
+ // Overwrite the data into the buffer
+ Copy(((UCHAR *)c->Data) + offset, data, size);
+
+ if (last_packet)
+ {
+ // If No More Flagment packet arrives, the size of this datagram is finalized
+ c->Size = offset + size;
+ }
+
+ // Check the overlap between the region which is represented by the offset and size of the
+ // existing received list and the region which is represented by the offset and size
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ UINT moving_size;
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ // Check the overlapping between the existing area and head area
+ if ((p->Offset <= offset) && ((p->Offset + p->Size) > offset))
+ {
+ // Compress behind the offset of this packet since a duplication is
+ // found in the first part with the existing packet and this packet
+
+ if ((offset + size) <= (p->Offset + p->Size))
+ {
+ // This packet is buried in the existing packet
+ size = 0;
+ }
+ else
+ {
+ // Retral region is not overlapped
+ moving_size = p->Offset + p->Size - offset;
+ offset += moving_size;
+ size -= moving_size;
+ }
+ }
+ if ((p->Offset < (offset + size)) && ((p->Offset + p->Size) >= (offset + size)))
+ {
+ // Compress the size of this packet forward because a duplication is
+ // found between the posterior portion the existing packet and this packet
+
+ moving_size = p->Offset + p->Size - offset - size;
+ size -= moving_size;
+ }
+
+ if ((p->Offset >= offset) && ((p->Offset + p->Size) <= (offset + size)))
+ {
+ // This packet was overwritten to completely hunched over a existing packet
+ p->Size = 0;
+ }
+ }
+
+ if (size != 0)
+ {
+ // Register this packet
+ p = ZeroMalloc(sizeof(IP_PART));
+
+ p->Offset = offset;
+ p->Size = size;
+
+ Add(c->IpParts, p);
+ }
+
+ if (c->Size != 0)
+ {
+ // Get the total size of the data portion list already received
+ UINT total_size = 0;
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ total_size += p->Size;
+ }
+
+ if (total_size == c->Size)
+ {
+ // Received whole of the IP packet
+ NnIpReceived(t, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->Ttl,
+ c->HeadIpHeaderData, c->HeadIpHeaderDataSize, c->MaxL3Size);
+
+ // Release the combining object
+ NnFreeIpCombine(t, c);
+
+ // Remove from the combining object list
+ Delete(t->IpCombine, c);
+ }
+ }
+}
+
+// Release the IP combining object
+void NnFreeIpCombine(NATIVE_NAT *t, IP_COMBINE *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Release the data
+ t->CurrentIpQuota -= c->DataReserved;
+ Free(c->Data);
+
+ // Release the partial list
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ Free(p);
+ }
+
+ Free(c->HeadIpHeaderData);
+
+ ReleaseList(c->IpParts);
+ Free(c);
+}
+
+// Search the IP combining list
+IP_COMBINE *NnSearchIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol)
+{
+ IP_COMBINE *c, tt;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ tt.DestIP = dest_ip;
+ tt.SrcIP = src_ip;
+ tt.Id = id;
+ tt.Protocol = protocol;
+
+ c = Search(t->IpCombine, &tt);
+
+ return c;
+}
+
+// Insert by creating a new object to the IP combining list
+IP_COMBINE *NnInsertIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac)
+{
+ IP_COMBINE *c;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ // Examine the quota
+ if ((t->CurrentIpQuota + IP_COMBINE_INITIAL_BUF_SIZE) > IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA)
+ {
+ // IP packet can not be stored any more
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(IP_COMBINE));
+ c->SrcIsLocalMacAddr = src_is_localmac;
+ c->DestIP = dest_ip;
+ c->SrcIP = src_ip;
+ c->Id = id;
+ c->Expire = t->v->Now + (UINT64)IP_COMBINE_TIMEOUT;
+ c->Size = 0;
+ c->IpParts = NewList(NULL);
+ c->Protocol = protocol;
+ c->MacBroadcast = mac_broadcast;
+ c->Ttl = ttl;
+
+ // Secure the memory
+ c->DataReserved = IP_COMBINE_INITIAL_BUF_SIZE;
+ c->Data = Malloc(c->DataReserved);
+ t->CurrentIpQuota += c->DataReserved;
+
+ Insert(t->IpCombine, c);
+
+ return c;
+}
+
+// Initialize the IP combining list
+void NnInitIpCombineList(NATIVE_NAT *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ t->IpCombine = NewList(CompareIpCombine);
+}
+
+// Release the IP combining list
+void NnFreeIpCombineList(NATIVE_NAT *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(t->IpCombine);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(t->IpCombine, i);
+
+ NnFreeIpCombine(t, c);
+ }
+
+ ReleaseList(t->IpCombine);
+}
+
+// A TCP packet is received
+void NnTcpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
+{
+ TCP_HEADER *tcp;
+ UCHAR *payload;
+ UINT payload_size;
+ UINT tcp_header_size;
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // TCP header
+ if (size < sizeof(TCP_HEADER))
+ {
+ return;
+ }
+
+ tcp = (TCP_HEADER *)data;
+
+ // Get the TCP header size
+ tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ if (size < tcp_header_size || tcp_header_size < sizeof(TCP_HEADER))
+ {
+ return;
+ }
+
+ // Payload
+ payload = ((UCHAR *)data) + tcp_header_size;
+ payload_size = size - tcp_header_size;
+
+ // Search the port from the NAT table
+ if (true)
+ {
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT_ENTRY *e;
+
+ NnSetNat(&tt, NAT_TCP, 0, 0, src_ip, Endian16(tcp->SrcPort), dest_ip, Endian16(tcp->DstPort));
+
+ e = SearchHash(t->NatTableForRecv, &tt);
+
+ if (e != NULL)
+ {
+ // Last communication time
+ e->LastCommTime = t->v->Now;
+ e->TotalRecv += (UINT64)size;
+
+ // Rewrite the TCP header
+ tcp->Checksum = 0;
+ tcp->DstPort = Endian16(e->SrcPort);
+
+ if (tcp->Flag & TCP_FIN || tcp->Flag & TCP_RST)
+ {
+ // Disconnect
+ e->Status = NAT_TCP_WAIT_DISCONNECT;
+ }
+
+ if (tcp->Flag & TCP_SYN && tcp->Flag & TCP_ACK)
+ {
+ // Connection complete
+ if (e->Status != NAT_TCP_WAIT_DISCONNECT)
+ {
+ e->Status = NAT_TCP_ESTABLISHED;
+ }
+ }
+
+ e->LastSeq = Endian32(tcp->AckNumber);
+ e->LastAck = Endian32(tcp->SeqNumber);
+
+ // Checksum recalculation
+ tcp->Checksum = CalcChecksumForIPv4(src_ip, e->SrcIp, IP_PROTO_TCP, tcp, size, 0);
+
+ // IP transmission
+ SendIp(t->v, e->SrcIp, src_ip, IP_PROTO_TCP, tcp, size);
+ }
+ }
+}
+
+// An ICMP packet has been received
+void NnIcmpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
+{
+ ICMP_HEADER *icmp;
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+ if (ttl == 0)
+ {
+ ttl = 1;
+ }
+
+ // ICMP header
+ if (size < sizeof(ICMP_HEADER))
+ {
+ return;
+ }
+
+ icmp = (ICMP_HEADER *)data;
+
+ if (icmp->Type == ICMP_TYPE_ECHO_RESPONSE)
+ {
+ UCHAR *payload;
+ UINT payload_size;
+ ICMP_ECHO *echo;
+ NATIVE_NAT_ENTRY tt, *e;
+
+ // Echo Response
+ echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
+
+ if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ return;
+ }
+
+ payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ // Search the NAT
+ NnSetNat(&tt, NAT_ICMP, 0, 0, 0, 0, dest_ip, Endian16(echo->Identifier));
+
+ e = SearchHash(t->NatTableForRecv, &tt);
+
+ if (e != NULL)
+ {
+ // Rewrite the header
+ icmp->Checksum = 0;
+ echo->Identifier = Endian16(e->SrcPort);
+ icmp->Checksum = IpChecksum(icmp, size);
+
+ e->LastCommTime = t->v->Now;
+ e->TotalRecv += (UINT64)size;
+
+ // Transmission
+ SendIpEx(t->v, e->SrcIp, src_ip, IP_PROTO_ICMPV4, icmp, size, MAX(ttl - 1, 1));
+ }
+ }
+ else if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
+ {
+ UCHAR *payload;
+ UINT payload_size;
+ ICMP_ECHO *echo;
+
+ // Echo Response
+ echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
+
+ if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ return;
+ }
+
+ payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ if (dest_ip == t->PublicIP)
+ {
+ // Respond as soon as the Echo Request is received at the public side interface
+ ICMP_HEADER *ret_icmp;
+ ICMP_ECHO *ret_echo;
+ UINT ret_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size;
+
+ ret_icmp = ZeroMalloc(ret_size);
+ ret_echo = (ICMP_ECHO *)(((UCHAR *)ret_icmp) + sizeof(ICMP_HEADER));
+
+ ret_icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
+ ret_icmp->Code = icmp->Code;
+
+ ret_echo->Identifier = echo->Identifier;
+ ret_echo->SeqNo = echo->SeqNo;
+
+ Copy((UCHAR *)ret_icmp + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
+ payload, payload_size);
+
+ ret_icmp->Checksum = IpChecksum(ret_icmp, ret_size);
+
+ NnIpSendForInternet(t, IP_PROTO_ICMPV4, 0, dest_ip, src_ip, ret_icmp, ret_size, max_l3_size);
+
+ Free(ret_icmp);
+ }
+ }
+ else
+ {
+ if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
+ {
+ // Rewrite the Src IP of the IPv4 header of the ICMP response packet
+ if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + sizeof(IPV4_HEADER)))
+ {
+ IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ UINT orig_ipv4_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
+
+ if (orig_ipv4_header_size >= sizeof(IPV4_HEADER) && orig_ipv4_size >= orig_ipv4_header_size)
+ {
+ if (orig_ipv4->Protocol == IP_PROTO_ICMPV4)
+ {
+ // Search the inner ICMP header
+ UINT inner_icmp_size = orig_ipv4_size - orig_ipv4_header_size;
+
+ if (inner_icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ ICMP_HEADER *inner_icmp = (ICMP_HEADER *)(((UCHAR *)data) +
+ sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
+
+ if (inner_icmp->Type == ICMP_TYPE_ECHO_REQUEST)
+ {
+ ICMP_ECHO *inner_echo = (ICMP_ECHO *)(((UCHAR *)inner_icmp) + sizeof(ICMP_HEADER));
+ NATIVE_NAT_ENTRY tt, *e;
+
+ // Search for the existing NAT table entry
+ NnSetNat(&tt, NAT_ICMP, 0, 0, 0, 0, orig_ipv4->SrcIP, Endian16(inner_echo->Identifier));
+
+ e = SearchHash(t->NatTableForRecv, &tt);
+
+ if (e != NULL)
+ {
+ e->LastCommTime = t->v->Now;
+
+ // Rewrite the inner IP packet and the ICMP header according to the NAT table
+ inner_echo->Identifier = Endian16(e->SrcPort);
+ inner_icmp->Checksum = 0;
+
+ orig_ipv4->SrcIP = e->SrcIp;
+
+ orig_ipv4->Checksum = 0;
+ orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
+
+ // Rewrite the outer ICMP header
+ if (true)
+ {
+ UCHAR *payload;
+ UINT payload_size;
+ ICMP_ECHO *echo;
+
+ // Echo Response
+ echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
+
+ if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ return;
+ }
+
+ payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ // Rewrite the header
+ icmp->Checksum = 0;
+ echo->Identifier = Endian16(e->SrcPort);
+ icmp->Checksum = IpChecksum(icmp, size);
+
+ // Transmission
+ SendIpEx(t->v, e->SrcIp, src_ip, IP_PROTO_ICMPV4, icmp, size, MAX(ttl - 1, 1));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// An UDP packet has been received
+void NnUdpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
+{
+ UDP_HEADER *udp;
+ UCHAR *payload;
+ UINT payload_size;
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // UDP header
+ if (size <= sizeof(UDP_HEADER))
+ {
+ return;
+ }
+
+ udp = (UDP_HEADER *)data;
+
+ // Payload
+ payload = ((UCHAR *)data) + sizeof(UDP_HEADER);
+ payload_size = size - sizeof(UDP_HEADER);
+
+ // Inspect the payload size
+ if (payload_size < (Endian16(udp->PacketLength) - sizeof(UDP_HEADER)))
+ {
+ return;
+ }
+
+ // Truncate the payload
+ payload_size = Endian16(udp->PacketLength) - sizeof(UDP_HEADER);
+
+ // Search the port number from the NAT table
+ if (true)
+ {
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT_ENTRY *e;
+
+ NnSetNat(&tt, NAT_UDP, 0, 0, 0, 0, dest_ip, Endian16(udp->DstPort));
+
+ e = SearchHash(t->NatTableForRecv, &tt);
+
+ if (e != NULL)
+ {
+ // Last communication time
+ e->LastCommTime = t->v->Now;
+ e->TotalRecv += (UINT64)payload_size;
+
+ // Deliver to the client by rewriting the port number
+ SendUdp(t->v, e->SrcIp, e->SrcPort, src_ip, Endian16(udp->SrcPort),
+ payload, payload_size);
+ }
+ }
+}
+
+// A combined IP packet is received
+void NnIpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size,
+ UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
+{
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (dest_ip != t->PublicIP)
+ {
+ // Destination IP is not a unicast
+ return;
+ }
+
+ switch (protocol)
+ {
+ case IP_PROTO_UDP:
+ // UDP
+ NnUdpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
+ break;
+
+ case IP_PROTO_TCP:
+ // TCP
+ NnTcpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
+ break;
+
+ case IP_PROTO_ICMPV4:
+ // ICMP
+ NnIcmpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
+ break;
+ }
+}
+
+// Received an IP packet
+void NnFragmentedIpReceived(NATIVE_NAT *t, PKT *packet)
+{
+ IPV4_HEADER *ip;
+ void *data;
+ UINT data_size_recved;
+ UINT size;
+ UINT ipv4_header_size;
+ bool last_packet = false;
+ UINT l3_size = 0;
+ UCHAR *head_ip_header_data = NULL;
+ UINT head_ip_header_size = 0;
+ // Validate arguments
+ if (t == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ ip = packet->L3.IPv4Header;
+
+ // Get the size of the IPv4 header
+ ipv4_header_size = IPV4_GET_HEADER_LEN(packet->L3.IPv4Header) * 4;
+ head_ip_header_size = ipv4_header_size;
+
+ // Get the pointer to the data
+ data = ((UCHAR *)packet->L3.PointerL3) + ipv4_header_size;
+
+ // Get the data size
+ size = l3_size = Endian16(ip->TotalLength);
+ if (size <= ipv4_header_size)
+ {
+ // There is no data
+ return;
+ }
+ size -= ipv4_header_size;
+
+ // Get the size of data actually received
+ data_size_recved = packet->PacketSize - (ipv4_header_size + MAC_HEADER_SIZE);
+ if (data_size_recved < size)
+ {
+ // Data insufficient (It may be missing on the way)
+ return;
+ }
+
+ if (IPV4_GET_OFFSET(ip) == 0 && (IPV4_GET_FLAGS(ip) & 0x01) == 0)
+ {
+ // Because this packet has not been fragmented, it can be passed to the upper layer immediately
+ head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
+ NnIpReceived(t, ip->SrcIP, ip->DstIP, ip->Protocol, data, size, ip->TimeToLive,
+ head_ip_header_data, head_ip_header_size, l3_size);
+ }
+ else
+ {
+ // This packet is necessary to combine because it is fragmented
+ UINT offset = IPV4_GET_OFFSET(ip) * 8;
+ IP_COMBINE *c = NnSearchIpCombine(t, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol);
+
+ if (offset == 0)
+ {
+ head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
+ }
+
+ last_packet = ((IPV4_GET_FLAGS(ip) & 0x01) == 0 ? true : false);
+
+ if (c != NULL)
+ {
+ // It is the second or subsequent packet
+ c->MaxL3Size = MAX(c->MaxL3Size, l3_size);
+ NnCombineIp(t, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
+ }
+ else
+ {
+ // Create a combining object because it is the first packet
+ c = NnInsertIpCombine(
+ t, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol, packet->BroadcastPacket,
+ ip->TimeToLive, false);
+ c->MaxL3Size = MAX(c->MaxL3Size, l3_size);
+ if (c != NULL)
+ {
+ NnCombineIp(t, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
+ }
+ }
+ }
+}
+
+// Layer 2 packet processing
+void NnLayer2(NATIVE_NAT *t, PKT *packet)
+{
+ // Validate arguments
+ if (t == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ if (packet->TypeL3 == L3_IPV4)
+ {
+ // IPv4
+ NnFragmentedIpReceived(t, packet);
+ }
+}
+
+// Extract the received packets of native NAT, and deliver it to the VPN client
+void NnPoll(NATIVE_NAT *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ LockQueue(t->RecvQueue);
+ {
+ while (true)
+ {
+ PKT *pkt = GetNext(t->RecvQueue);
+
+ if (pkt == NULL)
+ {
+ break;
+ }
+
+ NnLayer2(t, pkt);
+
+ FreePacketWithData(pkt);
+ }
+ }
+ UnlockQueue(t->RecvQueue);
+
+ if (t->SendStateChanged)
+ {
+ TUBE *halt_tube = NULL;
+
+ Lock(t->Lock);
+ {
+ if (t->HaltTube != NULL)
+ {
+ halt_tube = t->HaltTube;
+
+ AddRef(halt_tube->Ref);
+ }
+ }
+ Unlock(t->Lock);
+
+ if (halt_tube != NULL)
+ {
+ TubeFlushEx(halt_tube, true);
+
+ t->SendStateChanged = false;
+
+ ReleaseTube(halt_tube);
+ }
+ }
+
+ NnPollingIpCombine(t);
+
+ NnDeleteOldSessions(t);
+}
+
+// Send a fragmented IP packet to the Internet
+void NnIpSendFragmentedForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UINT src_ip, UINT dest_ip, USHORT id, USHORT total_size,
+ USHORT offset, void *data, UINT size, UCHAR ttl)
+{
+ UCHAR *buf;
+ IPV4_HEADER *ip;
+ BLOCK *b;
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Memory allocation
+ buf = Malloc(size + IP_HEADER_SIZE);
+ ip = (IPV4_HEADER *)&buf[0];
+
+ // IP header construction
+ ip->VersionAndHeaderLength = 0;
+ IPV4_SET_VERSION(ip, 4);
+ IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
+ ip->TypeOfService = DEFAULT_IP_TOS;
+ ip->TotalLength = Endian16((USHORT)(size + IP_HEADER_SIZE));
+ ip->Identification = Endian16(id);
+ ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
+ IPV4_SET_OFFSET(ip, (offset / 8));
+ if ((offset + size) >= total_size)
+ {
+ IPV4_SET_FLAGS(ip, 0x00);
+ }
+ else
+ {
+ IPV4_SET_FLAGS(ip, 0x01);
+ }
+ ip->TimeToLive = (ttl == 0 ? DEFAULT_IP_TTL : ttl);
+ ip->Protocol = ip_protocol;
+ ip->Checksum = 0;
+ ip->SrcIP = src_ip;
+ ip->DstIP = dest_ip;
+
+ // Checksum calculation
+ ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
+
+ // Data copy
+ Copy(buf + IP_HEADER_SIZE, data, size);
+
+ // Transmission
+ b = NewBlock(buf, size + IP_HEADER_SIZE, 0);
+
+ LockQueue(t->SendQueue);
+ {
+ if (t->SendQueue->num_item <= NN_MAX_QUEUE_LENGTH)
+ {
+ InsertQueue(t->SendQueue, b);
+
+ t->SendStateChanged = true;
+ }
+ else
+ {
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(t->SendQueue);
+}
+
+// Send an IP packet to the Internet
+void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size)
+{
+ UINT mss = 0;
+ UCHAR *buf;
+ USHORT offset;
+ USHORT id;
+ USHORT total_size;
+ UINT size_of_this_packet;
+ // Validate arguments
+ if (t == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Maximum segment size
+ if (max_l3_size > IP_HEADER_SIZE)
+ {
+ mss = max_l3_size - IP_HEADER_SIZE;
+ }
+
+ if (mss == 0)
+ {
+ mss = t->v->IpMss;
+ }
+
+ mss = MAX(mss, 1000);
+
+ // Buffer
+ buf = (UCHAR *)data;
+
+ // ID
+ id = (t->NextId++);
+
+ // Total size
+ total_size = (USHORT)size;
+
+ // Start to fragment
+ offset = 0;
+
+ while (true)
+ {
+ bool last_packet = false;
+ // Get the size of this packet
+ size_of_this_packet = MIN((USHORT)mss, (total_size - offset));
+ if ((offset + (USHORT)size_of_this_packet) == total_size)
+ {
+ last_packet = true;
+ }
+
+ // Transmit the fragmented packet
+ NnIpSendFragmentedForInternet(t, ip_protocol, src_ip, dest_ip, id, total_size, offset,
+ buf + offset, size_of_this_packet, ttl);
+ if (last_packet)
+ {
+ break;
+ }
+
+ offset += (USHORT)size_of_this_packet;
+ }
+}
+
+// Communication of ICMP towards the Internet
+void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
+{
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT_ENTRY *e;
+ NATIVE_NAT *t;
+ USHORT src_port;
+ ICMP_HEADER *old_icmp_header;
+ ICMP_ECHO *old_icmp_echo;
+ ICMP_HEADER *icmp;
+ ICMP_ECHO *echo;
+ UCHAR *payload_data;
+ UINT payload_size;
+ // Validate arguments
+ if (NnIsActive(v) == false || icmp_data == NULL)
+ {
+ return;
+ }
+
+ t = v->NativeNat;
+
+ old_icmp_header = (ICMP_HEADER *)icmp_data;
+ old_icmp_echo = (ICMP_ECHO *)(((UCHAR *)icmp_data) + sizeof(ICMP_HEADER));
+
+ if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ return;
+ }
+
+ payload_data = ((UCHAR *)icmp_data) + (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ payload_size = icmp_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ if (dest_ip == v->HostIP)
+ {
+ // Respond because it is addressed to me
+ VirtualIcmpEchoSendResponse(v, dest_ip, src_ip, Endian16(old_icmp_echo->Identifier),
+ Endian16(old_icmp_echo->SeqNo), payload_data, payload_size);
+
+ return;
+ }
+
+ if (ttl <= 1)
+ {
+ // Reply the Time Exceeded immediately for the packet whose TTL is 1
+ UINT reply_size = sizeof(ICMP_HEADER) + 4 + ip_header_size + 8;
+ UCHAR *reply_data = ZeroMalloc(reply_size);
+ ICMP_HEADER *icmp = (ICMP_HEADER *)reply_data;
+ icmp->Type = ICMP_TYPE_TIME_EXCEEDED;
+ icmp->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
+ Copy(reply_data + sizeof(ICMP_HEADER) + 4, ip_header, ip_header_size);
+ Copy(reply_data + sizeof(ICMP_HEADER) + 4 + ip_header_size, icmp_data, MIN(icmp_size, 8));
+
+ icmp->Checksum = IpChecksum(icmp, reply_size);
+
+ SendIp(v, src_ip, v->HostIP, IP_PROTO_ICMPV4, reply_data, reply_size);
+
+ Free(reply_data);
+
+ return;
+ }
+
+ src_port = Endian16(old_icmp_echo->Identifier);
+
+ // Search whether there is an existing session
+ NnSetNat(&tt, NAT_ICMP, src_ip, src_port, 0, 0, 0, 0);
+
+ e = SearchHash(t->NatTableForSend, &tt);
+
+ if (e == NULL)
+ {
+ // Create a new session because there is no existing one
+ UINT public_port;
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ // Can not make any more
+ return;
+ }
+
+ NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_ICMP);
+
+ // Get a free port
+ public_port = NnMapNewPublicPort(t, NAT_ICMP, 0, 0, t->PublicIP);
+ if (public_port == 0)
+ {
+ // There are no free ports
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
+
+ e->Status = NAT_TCP_ESTABLISHED;
+
+ e->HashCodeForSend = INFINITE;
+ e->HashCodeForRecv = INFINITE;
+ e->Id = Inc(v->Counter);
+ e->Protocol = NAT_ICMP;
+ e->SrcIp = src_ip;
+ e->SrcPort = src_port;
+ e->DestIp = 0;
+ e->DestPort = 0;
+ e->PublicIp = t->PublicIP;
+ e->PublicPort = public_port;
+
+ e->CreatedTime = v->Now;
+ e->LastCommTime = v->Now;
+
+ // Add to the list
+ AddHash(t->NatTableForSend, e);
+ AddHash(t->NatTableForRecv, e);
+
+ // Log
+ if (true)
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+
+ Debug("ICMP Session %u: %s:0x%x -> %s:0x%x\n", e->Id, s1, src_port, s2, public_port);
+ }
+ }
+
+ // Rebuild the ICMP header
+ icmp = ZeroMalloc(sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size);
+ icmp->Code = old_icmp_header->Code;
+ icmp->Type = old_icmp_header->Type;
+ icmp->Checksum = 0;
+
+ echo = (ICMP_ECHO *)(((UCHAR *)icmp) + sizeof(ICMP_HEADER));
+ echo->SeqNo = old_icmp_echo->SeqNo;
+ echo->Identifier = Endian16(e->PublicPort);
+
+ Copy(((UCHAR *)icmp) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), payload_data, payload_size);
+
+ icmp->Checksum = IpChecksum(icmp, sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size);
+
+ e->TotalSent += (UINT64)payload_size;
+ e->LastCommTime = v->Now;
+
+ // Send to the Internet
+ NnIpSendForInternet(t, IP_PROTO_ICMPV4, ttl - 1, e->PublicIp, dest_ip, icmp, sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size, max_l3_size);
+
+ Free(icmp);
+}
+
+// Communication of UDP towards the Internet
+void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, UINT max_l3_size)
+{
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT_ENTRY *e;
+ NATIVE_NAT *t;
+ UDP_HEADER *udp;
+ // Validate arguments
+ if (NnIsActive(v) == false || data == NULL)
+ {
+ return;
+ }
+
+ t = v->NativeNat;
+
+ // Search whether there is an existing session
+ NnSetNat(&tt, NAT_UDP, src_ip, src_port, 0, 0, 0, 0);
+
+ e = SearchHash(t->NatTableForSend, &tt);
+
+ if (e == NULL)
+ {
+ // Create a new session because there is no existing one
+ UINT public_port;
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ // Can not make any more
+ return;
+ }
+
+ NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_UDP);
+
+ // Get a free port
+ public_port = NnMapNewPublicPort(t, NAT_UDP, 0, 0, t->PublicIP);
+ if (public_port == 0)
+ {
+ // There are no free ports
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
+
+ e->Status = NAT_TCP_ESTABLISHED;
+
+ e->HashCodeForSend = INFINITE;
+ e->HashCodeForRecv = INFINITE;
+ e->Id = Inc(v->Counter);
+ e->Protocol = NAT_UDP;
+ e->SrcIp = src_ip;
+ e->SrcPort = src_port;
+ e->DestIp = 0;
+ e->DestPort = 0;
+ e->PublicIp = t->PublicIP;
+ e->PublicPort = public_port;
+
+ e->CreatedTime = v->Now;
+ e->LastCommTime = v->Now;
+
+ // Add to the list
+ AddHash(t->NatTableForSend, e);
+ AddHash(t->NatTableForRecv, e);
+
+ // Log
+ if (true)
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+
+ NLog(v, "LH_NAT_UDP_CREATED", e->Id, s1, src_port, s2, dest_port);
+ }
+ }
+
+ // Rebuild the UDP header
+ udp = ZeroMalloc(sizeof(UDP_HEADER) + size);
+
+ udp->SrcPort = Endian16(e->PublicPort);
+ udp->DstPort = Endian16(dest_port);
+ udp->PacketLength = Endian16((USHORT)sizeof(UDP_HEADER) + size);
+
+ Copy(((UCHAR *)udp) + sizeof(UDP_HEADER), data, size);
+
+ udp->Checksum = CalcChecksumForIPv4(e->PublicIp, dest_ip, IP_PROTO_UDP, udp, sizeof(UDP_HEADER) + size, 0);
+
+ e->TotalSent += (UINT64)size;
+ e->LastCommTime = v->Now;
+
+ // Send to the Internet
+ NnIpSendForInternet(t, IP_PROTO_UDP, 127, e->PublicIp, dest_ip, udp, sizeof(UDP_HEADER) + size, max_l3_size);
+
+ Free(udp);
+}
+
+// Communication of TCP towards the Internet
+void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *old_tcp, void *data, UINT size, UINT max_l3_size)
+{
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT_ENTRY *e;
+ NATIVE_NAT *t;
+ UINT tcp_header_size;
+ TCP_HEADER *tcp;
+ // Validate arguments
+ if (NnIsActive(v) == false || old_tcp == NULL || data == NULL)
+ {
+ return;
+ }
+
+ t = v->NativeNat;
+
+ // Search whether there is an existing session
+ NnSetNat(&tt, NAT_TCP, src_ip, src_port, dest_ip, dest_port, 0, 0);
+
+ e = SearchHash(t->NatTableForSend, &tt);
+
+ if (e == NULL)
+ {
+ // Create a new session because there is no existing one
+ UINT public_port;
+
+ if (old_tcp->Flag != TCP_SYN)
+ {
+ // If there is no existing session, pass through only for SYN packet
+ return;
+ }
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ // Can not make any more
+ return;
+ }
+
+ NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_TCP);
+
+ // Get a free port
+ public_port = NnMapNewPublicPort(t, NAT_TCP, dest_ip, dest_port, t->PublicIP);
+ if (public_port == 0)
+ {
+ // There are no free ports
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
+
+ e->HashCodeForSend = INFINITE;
+ e->HashCodeForRecv = INFINITE;
+ e->Id = Inc(v->Counter);
+ e->Status = NAT_TCP_CONNECTING;
+ e->Protocol = NAT_TCP;
+ e->SrcIp = src_ip;
+ e->SrcPort = src_port;
+ e->DestIp = dest_ip;
+ e->DestPort = dest_port;
+ e->PublicIp = t->PublicIP;
+ e->PublicPort = public_port;
+
+ e->CreatedTime = v->Now;
+ e->LastCommTime = v->Now;
+
+ // Add to the list
+ AddHash(t->NatTableForSend, e);
+ AddHash(t->NatTableForRecv, e);
+
+ // Log
+ if (true)
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+
+ NLog(v, "LH_NAT_TCP_CREATED", e->Id, s1, src_port, s2, dest_port);
+ }
+ }
+
+ // Update the last communication time
+ e->LastCommTime = v->Now;
+
+ e->TotalSent += (UINT64)size;
+
+ tcp_header_size = TCP_GET_HEADER_SIZE(old_tcp) * 4;
+
+ // Create a new TCP packet
+ tcp = ZeroMalloc(tcp_header_size + size);
+
+ // Copy the old TCP header
+ Copy(tcp, old_tcp, tcp_header_size);
+
+ if (tcp->Flag & TCP_RST || tcp->Flag & TCP_FIN)
+ {
+ // Disconnect
+ e->Status = NAT_TCP_WAIT_DISCONNECT;
+ }
+
+ // Rewrite the TCP header
+ tcp->Checksum = 0;
+ tcp->SrcPort = Endian16(e->PublicPort);
+
+ e->LastSeq = Endian32(tcp->SeqNumber);
+ e->LastAck = Endian32(tcp->AckNumber);
+
+ // Payload
+ Copy(((UCHAR *)tcp) + tcp_header_size, data, size);
+
+ // Checksum calculation
+ tcp->Checksum = CalcChecksumForIPv4(e->PublicIp, dest_ip, IP_PROTO_TCP, tcp, tcp_header_size + size, 0);
+
+ // Send to the Internet
+ NnIpSendForInternet(t, IP_PROTO_TCP, 127, e->PublicIp, dest_ip, tcp, tcp_header_size + size, max_l3_size);
+
+ Free(tcp);
+}
+
+// Assign a new public-side port
+UINT NnMapNewPublicPort(NATIVE_NAT *t, UINT protocol, UINT dest_ip, UINT dest_port, UINT public_ip)
+{
+ UINT i;
+ UINT base_port;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ base_port = Rand32() % (65500 - 1025) + 1025;
+
+ for (i = 0;i < (65500 - 1025);i++)
+ {
+ UINT port;
+ NATIVE_NAT_ENTRY tt;
+ NATIVE_NAT *e;
+
+ port = base_port + i;
+ if (port > 65500)
+ {
+ port = port - 65500 + 1025;
+ }
+
+ // Is this port vacant?
+ NnSetNat(&tt, protocol, 0, 0, dest_ip, dest_port, public_ip, port);
+
+ e = SearchHash(t->NatTableForRecv, &tt);
+
+ if (e == NULL)
+ {
+ // Free port is found
+ return port;
+ }
+ }
+
+ return 0;
+}
+
+// Examine whether the native NAT is available
+bool NnIsActive(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+
+ if (v->NativeNat == NULL)
+ {
+ return false;
+ }
+
+ if (v->NativeNat->PublicIP == 0)
+ {
+ return false;
+ }
+
+ return v->NativeNat->Active;
+}
+
+// Native NAT main loop
+void NnMainLoop(NATIVE_NAT *t, NATIVE_STACK *a)
+{
+ IPC *ipc;
+ TUBE *tubes[3];
+ UINT num_tubes = 0;
+ UINT64 next_poll_tick = 0;
+ INTERRUPT_MANAGER *interrupt;
+ USHORT dns_src_port = 0;
+ USHORT dns_tran_id = 0;
+ USHORT tcp_src_port = 0;
+ UINT tcp_seq = 0;
+ IP yahoo_ip;
+ bool wait_for_dns = false;
+ UINT64 tcp_last_recv_tick = 0;
+ UINT dhcp_renew_interval;
+ UINT64 next_dhcp_renew_tick = 0;
+ // Validate arguments
+ if (t == NULL || a == NULL)
+ {
+ return;
+ }
+
+ dhcp_renew_interval = a->CurrentDhcpOptionList.LeaseTime;
+
+ if (dhcp_renew_interval == 0)
+ {
+ dhcp_renew_interval = IPC_DHCP_DEFAULT_LEASE;
+ }
+
+ dhcp_renew_interval = MAX(dhcp_renew_interval, IPC_DHCP_MIN_LEASE) / 2;
+
+ interrupt = NewInterruptManager();
+
+ ipc = a->Ipc;
+
+ tubes[num_tubes++] = ipc->Sock->RecvTube;
+ tubes[num_tubes++] = ipc->Sock->SendTube;
+ tubes[num_tubes++] = t->HaltTube;
+
+ Zero(&yahoo_ip, sizeof(yahoo_ip));
+
+ next_poll_tick = Tick64() + (UINT64)NN_POLL_CONNECTIVITY_INTERVAL;
+ AddInterrupt(interrupt, next_poll_tick);
+
+ tcp_last_recv_tick = Tick64();
+ next_dhcp_renew_tick = Tick64() + (UINT64)dhcp_renew_interval;
+ AddInterrupt(interrupt, next_dhcp_renew_tick);
+
+ while (t->Halt == false && t->v->UseNat && ((t->v->HubOption == NULL) || (t->v->HubOption->DisableKernelModeSecureNAT == false)))
+ {
+ UINT64 now = Tick64();
+ bool call_cancel = false;
+ bool state_changed = false;
+ UINT wait_interval;
+
+ IPCFlushArpTable(ipc);
+ call_cancel = false;
+
+LABEL_RESTART:
+ state_changed = false;
+
+ if (next_poll_tick == 0 || next_poll_tick <= now)
+ {
+ BUF *dns_query;
+
+ dns_src_port = NnGenSrcPort();
+ dns_tran_id = Rand16();
+
+ // Start a connectivity check periodically
+ dns_query = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
+ IPToUINT(&ipc->ClientIPAddress), dns_src_port, IPToUINT(&a->DnsServerIP), 53),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP), IP_PROTO_UDP, 0);
+
+ IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
+
+ wait_for_dns = true;
+
+ FreeBuf(dns_query);
+
+ next_poll_tick = now + (UINT64)NN_POLL_CONNECTIVITY_INTERVAL;
+ AddInterrupt(interrupt, next_poll_tick);
+ }
+
+ if (next_dhcp_renew_tick == 0 || next_dhcp_renew_tick <= now)
+ {
+ IP ip;
+
+ UINTToIP(&ip, a->CurrentDhcpOptionList.ServerAddress);
+
+ IPCDhcpRenewIP(ipc, &ip);
+
+ next_dhcp_renew_tick = now + (UINT64)dhcp_renew_interval;
+ AddInterrupt(interrupt, next_dhcp_renew_tick);
+ }
+
+ // Send an IP packet to IPC
+ LockQueue(t->SendQueue);
+ {
+ while (true)
+ {
+ BLOCK *b = GetNext(t->SendQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ IPCSendIPv4(ipc, b->Buf, b->Size);
+
+ state_changed = true;
+
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(t->SendQueue);
+
+ // Happy processing
+ IPCProcessL3Events(ipc);
+
+ LockQueue(t->RecvQueue);
+ {
+ while (true)
+ {
+ // Receive an IP packet from IPC
+ BLOCK *b = IPCRecvIPv4(ipc);
+ PKT *pkt;
+
+ if (b == NULL)
+ {
+ // Can not receive any more
+ break;
+ }
+
+ // Parse the packet
+ pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
+
+ FreeBlock(b);
+
+ if (pkt != NULL)
+ {
+ bool no_store = false;
+
+ // Read the contents of the packet first, to determine whether it is a response for the connectivity test packet
+ if (wait_for_dns)
+ {
+ if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP &&
+ pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) &&
+ pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
+ pkt->L4.UDPHeader->SrcPort == Endian16(53) && pkt->L4.UDPHeader->DstPort == Endian16(dns_src_port))
+ {
+ DNSV4_HEADER *dns_header = (DNSV4_HEADER *)pkt->Payload;
+ if (pkt->PayloadSize >= sizeof(DNSV4_HEADER))
+ {
+ if (dns_header->TransactionId == Endian16(dns_tran_id))
+ {
+ IP ret_ip;
+
+ if (NnParseDnsResponsePacket(pkt->Payload, pkt->PayloadSize, &ret_ip))
+ {
+ BUF *tcp_query;
+
+ Copy(&yahoo_ip, &ret_ip, sizeof(IP));
+
+ //SetIP(&yahoo_ip, 192, 168, 2, 32);
+
+ // DNS response has been received
+ no_store = true;
+
+ tcp_src_port = NnGenSrcPort();
+
+ // Generate a TCP connection attempt packet
+ tcp_seq = Rand32();
+ tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), tcp_src_port,
+ IPToUINT(&yahoo_ip), 80, tcp_seq, 0, TCP_SYN, 8192, 1414),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
+
+ IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
+
+ FreeBuf(tcp_query);
+
+ wait_for_dns = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_TCP &&
+ pkt->L3.IPv4Header->SrcIP == IPToUINT(&yahoo_ip) &&
+ pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
+ pkt->L4.TCPHeader->SrcPort == Endian16(80) && pkt->L4.TCPHeader->DstPort == Endian16(tcp_src_port))
+ {
+ TCP_HEADER *tcp_header = (TCP_HEADER *)pkt->L4.TCPHeader;
+ if ((tcp_header->Flag & TCP_SYN) && (tcp_header->Flag & TCP_ACK))
+ {
+ // There was a TCP response
+ BUF *tcp_query;
+ UINT recv_seq = Endian32(tcp_header->SeqNumber) + 1;
+
+ no_store = true;
+
+ // Send a RST
+ tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), tcp_src_port,
+ IPToUINT(&yahoo_ip), 80, tcp_seq + 1, recv_seq, TCP_RST | TCP_ACK, 8192, 0),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
+
+ IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
+
+ FreeBuf(tcp_query);
+
+ tcp_last_recv_tick = now;
+ }
+ }
+
+ if (t->RecvQueue->num_item > NN_MAX_QUEUE_LENGTH)
+ {
+ no_store = true;
+ }
+
+ if (no_store == false)
+ {
+ // Put in the queue
+ InsertQueue(t->RecvQueue, pkt);
+ call_cancel = true;
+ state_changed = true;
+ }
+ else
+ {
+ // Release the packet
+ FreePacketWithData(pkt);
+ }
+ }
+ }
+ }
+ UnlockQueue(t->RecvQueue);
+
+ if (state_changed)
+ {
+ goto LABEL_RESTART;
+ }
+
+ if (call_cancel)
+ {
+ CANCEL *c = NULL;
+
+ Lock(t->CancelLock);
+ {
+ c = t->Cancel;
+
+ AddRef(c->ref);
+ }
+ Unlock(t->CancelLock);
+
+ if (c != NULL)
+ {
+ Cancel(c);
+
+ ReleaseCancel(c);
+ }
+ }
+
+ if (IsTubeConnected(ipc->Sock->RecvTube) == false || IsTubeConnected(ipc->Sock->SendTube) == false)
+ {
+ // Disconnected
+ break;
+ }
+
+ if ((tcp_last_recv_tick + (UINT64)NN_POLL_CONNECTIVITY_TIMEOUT) < now)
+ {
+ // Connectivity test has timed out because a certain period of time has elapsed
+ Debug("NN_POLL_CONNECTIVITY_TIMEOUT\n");
+ break;
+ }
+
+ wait_interval = GetNextIntervalForInterrupt(interrupt);
+ wait_interval = MIN(wait_interval, 1234);
+
+ if (wait_interval != 0)
+ {
+ WaitForTubes(tubes, num_tubes, wait_interval);
+ }
+ }
+
+ FreeInterruptManager(interrupt);
+}
+
+// Build an IP packet
+BUF *NnBuildIpPacket(BUF *payload, UINT src_ip, UINT dst_ip, UCHAR protocol, UCHAR ttl)
+{
+ BUF *ret = NewBuf();
+ IPV4_HEADER h;
+
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ // IP header
+ Zero(&h, sizeof(h));
+ IPV4_SET_VERSION(&h, 4);
+ IPV4_SET_HEADER_LEN(&h, sizeof(IPV4_HEADER) / 4);
+ h.TotalLength = Endian16((USHORT)sizeof(IPV4_HEADER) + payload->Size);
+ h.Identification = Rand16();
+ h.TimeToLive = ttl;
+ h.Protocol = protocol;
+ h.SrcIP = src_ip;
+ h.DstIP = dst_ip;
+
+ h.Checksum = IpChecksum(&h, sizeof(h));
+
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBufBuf(ret, payload);
+
+ SeekBufToBegin(ret);
+
+ FreeBuf(payload);
+
+ return ret;
+}
+
+// Build an UDP packet
+BUF *NnBuildUdpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port)
+{
+ BUF *ret = NewBuf();
+ BUF *phbuf = NewBuf();
+ UDPV4_PSEUDO_HEADER ph;
+ UDP_HEADER h;
+
+ // UDP pseudo header
+ Zero(&ph, sizeof(ph));
+
+ ph.SrcIP = src_ip;
+ ph.DstIP = dst_ip;
+ ph.SrcPort = Endian16(src_port);
+ ph.DstPort = Endian16(dst_port);
+ ph.Protocol = IP_PROTO_UDP;
+ ph.PacketLength1 = ph.PacketLength2 = Endian16(payload->Size + (USHORT)sizeof(UDP_HEADER));
+
+ WriteBuf(phbuf, &ph, sizeof(ph));
+ WriteBufBuf(phbuf, payload);
+
+ // UDP header
+ Zero(&h, sizeof(h));
+ h.SrcPort = Endian16(src_port);
+ h.DstPort = Endian16(dst_port);
+ h.PacketLength = Endian16(payload->Size + (USHORT)sizeof(UDP_HEADER));
+ h.Checksum = IpChecksum(phbuf->Buf, phbuf->Size);
+
+ WriteBuf(ret, &h, sizeof(h));
+ WriteBuf(ret, payload->Buf, payload->Size);
+
+ SeekBufToBegin(ret);
+
+ FreeBuf(payload);
+ FreeBuf(phbuf);
+
+ return ret;
+}
+
+// Build a TCP packet
+BUF *NnBuildTcpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss)
+{
+ BUF *ret;
+ IPV4_PSEUDO_HEADER *vh;
+ TCP_HEADER *tcp;
+ static UCHAR tcp_mss_option[] = {0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00};
+ UINT header_size = TCP_HEADER_SIZE;
+ UINT total_size;
+
+ // Memory allocation
+ vh = Malloc(sizeof(IPV4_PSEUDO_HEADER) + TCP_HEADER_SIZE + payload->Size + 32);
+ tcp = (TCP_HEADER *)(((UCHAR *)vh) + sizeof(IPV4_PSEUDO_HEADER));
+
+ if (mss != 0)
+ {
+ USHORT *mss_size;
+ mss_size = (USHORT *)(&tcp_mss_option[2]);
+ *mss_size = Endian16((USHORT)mss);
+ header_size += sizeof(tcp_mss_option);
+ }
+
+ total_size = header_size + payload->Size;
+
+ // Pseudo header generation
+ vh->SrcIP = src_ip;
+ vh->DstIP = dst_ip;
+ vh->Reserved = 0;
+ vh->Protocol = IP_PROTO_TCP;
+ vh->PacketLength = Endian16((USHORT)total_size);
+
+ // TCP header generation
+ tcp->SrcPort = Endian16((USHORT)src_port);
+ tcp->DstPort = Endian16((USHORT)dst_port);
+ tcp->SeqNumber = Endian32(seq);
+ tcp->AckNumber = Endian32(ack);
+ tcp->HeaderSizeAndReserved = 0;
+ TCP_SET_HEADER_SIZE(tcp, (UCHAR)(header_size / 4));
+ tcp->Flag = (UCHAR)flag;
+ tcp->WindowSize = Endian16((USHORT)window_size);
+ tcp->Checksum = 0;
+ tcp->UrgentPointer = 0;
+
+ // Copy the option values
+ if (mss != 0)
+ {
+ Copy(((UCHAR *)tcp) + TCP_HEADER_SIZE, tcp_mss_option, sizeof(tcp_mss_option));
+ }
+
+ // Data copy
+ Copy(((UCHAR *)tcp) + header_size, payload->Buf, payload->Size);
+
+ // Checksum calculation
+ tcp->Checksum = IpChecksum(vh, total_size + 12);
+
+ ret = NewBufFromMemory(tcp, total_size);
+
+ Free(vh);
+
+ FreeBuf(payload);
+
+ return ret;
+}
+
+// Build a DNS query packet
+BUF *NnBuildDnsQueryPacket(char *hostname, USHORT tran_id)
+{
+ BUF *buf = NewBuf();
+ DNSV4_HEADER header;
+
+ Zero(&header, sizeof(header));
+
+ header.TransactionId = Endian16(tran_id);
+ header.Flag1 = 0x01;
+ header.Flag2 = 0x00;
+ header.NumQuery = Endian16(1);
+
+ WriteBuf(buf, &header, sizeof(header));
+
+ BuildDnsQueryPacket(buf, hostname, false);
+
+ SeekBufToBegin(buf);
+
+ return buf;
+}
+
+// Read a DNS record
+BUF *NnReadDnsRecord(BUF *buf, bool answer, USHORT *ret_type, USHORT *ret_class)
+{
+ USHORT type;
+ USHORT clas;
+ UINT ttl;
+ BUF *ret = NULL;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the DNS label
+ if (NnReadDnsLabel(buf) == false)
+ {
+ return false;
+ }
+
+ // Type and Class
+ if (ReadBuf(buf, &type, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ return false;
+ }
+
+ if (ret_type != NULL)
+ {
+ *ret_type = Endian16(type);
+ }
+
+ if (ReadBuf(buf, &clas, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ return false;
+ }
+
+ if (ret_class != NULL)
+ {
+ *ret_class = Endian16(clas);
+ }
+
+ if (answer)
+ {
+ USHORT data_len;
+ UCHAR *data;
+
+ // TTL
+ if (ReadBuf(buf, &ttl, sizeof(UINT)) != sizeof(UINT))
+ {
+ return false;
+ }
+
+ // data_len
+ if (ReadBuf(buf, &data_len, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ return false;
+ }
+
+ data_len = Endian16(data_len);
+
+ // data
+ data = Malloc(data_len);
+ if (ReadBuf(buf, data, data_len) != data_len)
+ {
+ return false;
+ }
+
+ ret = NewBufFromMemory(data, data_len);
+
+ Free(data);
+ }
+ else
+ {
+ ret = NewBuf();
+ }
+
+ return ret;
+}
+
+// Read the DNS label
+bool NnReadDnsLabel(BUF *buf)
+{
+ UCHAR c;
+ UCHAR tmp[256];
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return false;
+ }
+
+LABEL_START:
+
+ if (ReadBuf(buf, &c, 1) != 1)
+ {
+ return false;
+ }
+
+ if (c == 0)
+ {
+ return true;
+ }
+
+ if (c & 0xC0)
+ {
+ // Compression label
+ if (ReadBuf(buf, &c, 1) != 1)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ // Usual label
+ if (ReadBuf(buf, tmp, c) != c)
+ {
+ return false;
+ }
+ else
+ {
+ goto LABEL_START;
+ }
+ }
+
+}
+
+// Parse the DNS response packet
+bool NnParseDnsResponsePacket(UCHAR *data, UINT size, IP *ret_ip)
+{
+ BUF *buf = NewBufFromMemory(data, size);
+ bool ret = false;
+ DNSV4_HEADER h;
+
+ if (ReadBuf(buf, &h, sizeof(h)) == sizeof(h))
+ {
+ UINT num_questions = Endian16(h.NumQuery);
+ UINT num_answers = Endian16(h.AnswerRRs);
+ UINT i;
+
+ for (i = 0;i < num_questions;i++)
+ {
+ BUF *r = NnReadDnsRecord(buf, false, NULL, NULL);
+
+ if (r != NULL)
+ {
+ FreeBuf(r);
+ }
+ else
+ {
+ goto LABEL_CLEANUP;
+ }
+ }
+
+ for (i = 0;i < num_answers;i++)
+ {
+ USHORT tp, cl;
+ BUF *r = NnReadDnsRecord(buf, true, &tp, &cl);
+
+ if (r != NULL)
+ {
+ if (tp == 0x0001 && cl == 0x0001 && r->Size == 4)
+ {
+ ret = true;
+
+ if (ret_ip != NULL)
+ {
+ Zero(ret_ip, sizeof(IP));
+
+ Copy(ret_ip->addr, r->Buf, 4);
+ }
+ }
+
+ FreeBuf(r);
+ }
+ else
+ {
+ goto LABEL_CLEANUP;
+ }
+ }
+ }
+
+LABEL_CLEANUP:
+ FreeBuf(buf);
+
+ return ret;
+}
+
+// Test the connectivity of the stack to the Internet
+bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
+{
+ BUF *dns_query;
+ bool ok = false;
+ USHORT dns_tran_id = Rand16();
+ UINT64 next_send_tick = 0;
+ UINT64 giveup_time;
+ IPC *ipc;
+ UINT src_port = NnGenSrcPort();
+ INTERRUPT_MANAGER *interrupt;
+ TUBE *tubes[3];
+ UINT num_tubes = 0;
+ IP yahoo_ip;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ ipc = a->Ipc;
+ interrupt = NewInterruptManager();
+
+ tubes[num_tubes++] = ipc->Sock->RecvTube;
+ tubes[num_tubes++] = ipc->Sock->SendTube;
+
+ if (halt_tube != NULL)
+ {
+ tubes[num_tubes++] = halt_tube;
+ }
+
+ Zero(&yahoo_ip, sizeof(yahoo_ip));
+
+ // Try to get an IP address of www.yahoo.com
+ dns_query = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
+ IPToUINT(&ipc->ClientIPAddress), src_port, IPToUINT(&a->DnsServerIP), 53),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP), IP_PROTO_UDP, 0);
+
+ giveup_time = Tick64() + NN_CHECK_CONNECTIVITY_TIMEOUT;
+ AddInterrupt(interrupt, giveup_time);
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ IPCFlushArpTable(a->Ipc);
+
+ if (now >= giveup_time)
+ {
+ break;
+ }
+
+ // Send a packet periodically
+ if (next_send_tick == 0 || next_send_tick <= now)
+ {
+ next_send_tick = now + (UINT64)NN_CHECK_CONNECTIVITY_INTERVAL;
+
+ AddInterrupt(interrupt, next_send_tick);
+
+ IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
+ }
+
+ // Happy processing
+ IPCProcessL3Events(ipc);
+
+ while (true)
+ {
+ // Receive a packet
+ BLOCK *b = IPCRecvIPv4(ipc);
+ PKT *pkt;
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ // Parse the packet
+ pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
+
+ if (pkt != NULL)
+ {
+ if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP &&
+ pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) &&
+ pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
+ pkt->L4.UDPHeader->SrcPort == Endian16(53) && pkt->L4.UDPHeader->DstPort == Endian16(src_port))
+ {
+ DNSV4_HEADER *dns_header = (DNSV4_HEADER *)pkt->Payload;
+ if (pkt->PayloadSize >= sizeof(DNSV4_HEADER))
+ {
+ if (dns_header->TransactionId == Endian16(dns_tran_id))
+ {
+ IP ret_ip;
+
+ if (NnParseDnsResponsePacket(pkt->Payload, pkt->PayloadSize, &ret_ip))
+ {
+ Copy(&yahoo_ip, &ret_ip, sizeof(IP));
+ }
+ }
+ }
+ }
+ }
+
+ FreePacketWithData(pkt);
+ FreeBlock(b);
+ }
+
+ if ((halt_tube != NULL && IsTubeConnected(halt_tube) == false) ||
+ IsTubeConnected(ipc->Sock->SendTube) == false || IsTubeConnected(ipc->Sock->RecvTube) == false)
+ {
+ // Disconnected
+ break;
+ }
+
+ if (IsZeroIP(&yahoo_ip) == false)
+ {
+ // There is a response
+ break;
+ }
+
+ // Keep the CPU waiting
+ WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(interrupt));
+ }
+
+ FreeBuf(dns_query);
+
+ if (IsZeroIP(&yahoo_ip) == false)
+ {
+ BUF *tcp_query;
+ UINT seq = Rand32();
+ bool tcp_get_response = false;
+ UINT recv_seq = 0;
+
+ // Since the IP address of www.yahoo.com has gotten, try to connect by TCP
+ giveup_time = Tick64() + NN_CHECK_CONNECTIVITY_TIMEOUT;
+ AddInterrupt(interrupt, giveup_time);
+
+ // Generate a TCP packet
+ tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), src_port,
+ IPToUINT(&yahoo_ip), 80, seq, 0, TCP_SYN, 8192, 1414),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
+
+ Debug("Test TCP to %r\n", &yahoo_ip);
+
+ next_send_tick = 0;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ IPCFlushArpTable(a->Ipc);
+
+ if (now >= giveup_time)
+ {
+ break;
+ }
+
+ // Send the packet periodically
+ if (next_send_tick == 0 || next_send_tick <= now)
+ {
+ next_send_tick = now + (UINT64)NN_CHECK_CONNECTIVITY_INTERVAL;
+
+ AddInterrupt(interrupt, next_send_tick);
+
+ IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
+ }
+
+ // Happy procedure
+ IPCProcessL3Events(ipc);
+
+ while (true)
+ {
+ // Receive a packet
+ BLOCK *b = IPCRecvIPv4(ipc);
+ PKT *pkt;
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ // Parse the packet
+ pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
+
+ if (pkt != NULL)
+ {
+ if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_TCP &&
+ pkt->L3.IPv4Header->SrcIP == IPToUINT(&yahoo_ip) &&
+ pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
+ pkt->L4.TCPHeader->SrcPort == Endian16(80) && pkt->L4.TCPHeader->DstPort == Endian16(src_port))
+ {
+ TCP_HEADER *tcp_header = (TCP_HEADER *)pkt->L4.TCPHeader;
+ if ((tcp_header->Flag & TCP_SYN) && (tcp_header->Flag & TCP_ACK))
+ {
+ // There was a TCP response
+ tcp_get_response = true;
+ recv_seq = Endian32(tcp_header->SeqNumber);
+ }
+ }
+ }
+
+ FreePacketWithData(pkt);
+ FreeBlock(b);
+ }
+
+ if ((halt_tube != NULL && IsTubeConnected(halt_tube) == false) ||
+ IsTubeConnected(ipc->Sock->SendTube) == false || IsTubeConnected(ipc->Sock->RecvTube) == false)
+ {
+ // Disconnected
+ break;
+ }
+
+ if (tcp_get_response)
+ {
+ WHERE;
+ break;
+ }
+
+ // Keep the CPU waiting
+ WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(interrupt));
+ }
+
+ FreeBuf(tcp_query);
+
+ // Send a RST
+ if (recv_seq != 0)
+ {
+ recv_seq++;
+ }
+
+ tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), src_port,
+ IPToUINT(&yahoo_ip), 80, seq + 1, recv_seq, TCP_RST | TCP_ACK, 8192, 0),
+ IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
+
+ IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
+
+ FreeBuf(tcp_query);
+
+ SleepThread(100);
+
+ if (tcp_get_response)
+ {
+ ok = true;
+ }
+ }
+
+ FreeInterruptManager(interrupt);
+
+ return ok;
+}
+
+// Generate source port number by a random number
+UINT NnGenSrcPort()
+{
+ return 1025 + Rand32() % (65500 - 1025);
+}
+
+// Get a next good interface for the native NAT
+NATIVE_STACK *NnGetNextInterface(NATIVE_NAT *t)
+{
+ NATIVE_STACK *ret = NULL;
+ UINT current_hash;
+ TOKEN_LIST *device_list;
+ UINT i;
+ char tmp[MAX_SIZE];
+ char *dev_name;
+ UINT current_ip_hash;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ t->NextWaitTimeForRetry = NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM * MIN((t->FailedCount + 1), NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT);
+
+ // Get the device list
+ device_list = GetEthList();
+
+ if (device_list == NULL || device_list->NumTokens == 0)
+ {
+ // Device list acquisition failure (Or no device acquired as a result)
+ FreeToken(device_list);
+ t->FailedCount++;
+ return NULL;
+ }
+
+ current_hash = GetEthDeviceHash();
+ current_ip_hash = GetHostIPAddressHash32();
+
+ if (t->LastInterfaceDeviceHash != current_hash || t->LastHostAddressHash != current_ip_hash)
+ {
+ // Device list is altered from the previous search
+ t->LastInterfaceIndex = INFINITE;
+ t->FailedCount = 0;
+ }
+
+ t->LastInterfaceDeviceHash = current_hash;
+ t->LastHostAddressHash = current_ip_hash;
+
+ if (t->LastInterfaceIndex == INFINITE)
+ {
+ i = 0;
+ }
+ else
+ {
+ i = t->LastInterfaceIndex + 1;
+ if (i >= device_list->NumTokens)
+ {
+ i = 0;
+ }
+ }
+
+ if ((i + 1) == device_list->NumTokens)
+ {
+ // Searched to the end
+ t->LastInterfaceIndex = INFINITE;
+
+ // Increase the number of search failures by one
+ t->FailedCount++;
+ }
+ else
+ {
+ // It is not the end yet
+ t->LastInterfaceIndex = i;
+ t->NextWaitTimeForRetry = 0;
+ }
+
+ dev_name = device_list->Token[i];
+
+ if (IsInLinesFile(NN_NO_NATIVE_NAT_FILENAME, dev_name, true) == false)
+ {
+ // Try to open the device
+ BinToStr(tmp, sizeof(tmp), t->v->MacAddress, 6);
+ ret = NewNativeStack(NULL, dev_name, tmp);
+
+ if (ret != NULL)
+ {
+ // Test whether an IP address can be obtained from a DHCP server
+ DHCP_OPTION_LIST opt;
+
+ Copy(t->CurrentMacAddress, ret->Ipc->MacAddress, 6);
+
+ Zero(&opt, sizeof(opt));
+
+ BinToStr(tmp, sizeof(tmp), ret->MacAddress, 6);
+ Format(ret->Ipc->ClientHostname, sizeof(ret->Ipc->ClientHostname), NN_HOSTNAME_FORMAT, tmp);
+ StrLower(ret->Ipc->ClientHostname);
+
+ Debug("IPCDhcpAllocateIP for %s\n", ret->DeviceName);
+ if (IPCDhcpAllocateIP(ret->Ipc, &opt, t->HaltTube2))
+ {
+ char client_ip[64];
+ char dhcp_ip[64];
+ char client_mask[64];
+ char gateway_ip[64];
+
+ IP ip;
+ IP subnet;
+ IP gw;
+
+ IPToStr32(client_ip, sizeof(client_ip), opt.ClientAddress);
+ IPToStr32(client_mask, sizeof(client_mask), opt.SubnetMask);
+ IPToStr32(dhcp_ip, sizeof(dhcp_ip), opt.ServerAddress);
+ IPToStr32(gateway_ip, sizeof(gateway_ip), opt.Gateway);
+
+ Debug("DHCP: client_ip=%s, client_mask=%s, dhcp_ip=%s, gateway_ip=%s\n",
+ client_ip, client_mask, dhcp_ip, gateway_ip);
+
+ Copy(&ret->CurrentDhcpOptionList, &opt, sizeof(DHCP_OPTION_LIST));
+
+ // IP parameter settings
+ UINTToIP(&ip, opt.ClientAddress);
+ UINTToIP(&subnet, opt.SubnetMask);
+ UINTToIP(&gw, opt.Gateway);
+
+ IPCSetIPv4Parameters(ret->Ipc, &ip, &subnet, &gw);
+
+ // Determine the DNS server to use
+ UINTToIP(&ret->DnsServerIP, opt.DnsServer);
+ if (IsZeroIP(&ret->DnsServerIP))
+ {
+ // Use 8.8.8.8 instead If the DNS is not assigned from the DHCP server
+ SetIP(&ret->DnsServerIP, 8, 8, 8, 8);
+ }
+
+ // Connectivity test
+ // (always fail if the default gateway is not set)
+ if (opt.Gateway != 0 &&
+ NnTestConnectivity(ret, t->HaltTube2))
+ {
+ // Reset the number of search failures
+ t->FailedCount = 0;
+ Debug("Connectivity OK.\n");
+ }
+ else
+ {
+ Debug("Connectivity Failed.\n");
+ FreeNativeStack(ret);
+ ret = NULL;
+ }
+ }
+ else
+ {
+ Debug("DHCP Failed.\n");
+ FreeNativeStack(ret);
+ ret = NULL;
+
+ Zero(t->CurrentMacAddress, sizeof(t->CurrentMacAddress));
+ }
+ }
+ }
+
+ FreeToken(device_list);
+
+ return ret;
+}
+
+// Native NAT thread
+void NativeNatThread(THREAD *thread, void *param)
+{
+ NATIVE_NAT *t = (NATIVE_NAT *)param;
+ void *wait_handle = InitWaitUntilHostIPAddressChanged();
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (t->Halt == false)
+ {
+ NATIVE_STACK *a;
+
+ while (t->v->UseNat == false || (t->v->HubOption != NULL && t->v->HubOption->DisableKernelModeSecureNAT))
+ {
+ if (t->Halt)
+ {
+ break;
+ }
+
+ // If the NAT is disabled, wait until it becomes enabled
+ Wait(t->HaltEvent, 1234);
+ }
+
+ if (t->Halt)
+ {
+ break;
+ }
+
+ // Get a next good native NAT stack
+ Debug("NnGetNextInterface Start.\n");
+
+ NnClearQueue(t);
+
+ a = NnGetNextInterface(t);
+
+ if (a != NULL)
+ {
+ char macstr[64];
+ // Acquisition success
+ Debug("NnGetNextInterface Ok: %s\n", a->DeviceName);
+
+ Lock(t->Lock);
+ {
+ if (a->Sock1 != NULL)
+ {
+ t->HaltTube = a->Sock2->RecvTube;
+
+ if (t->HaltTube != NULL)
+ {
+ AddRef(t->HaltTube->Ref);
+ }
+ }
+ }
+ Unlock(t->Lock);
+
+ NnClearQueue(t);
+
+ t->PublicIP = IPToUINT(&a->Ipc->ClientIPAddress);
+ t->Active = true;
+
+
+ Debug("NnMainLoop Start.\n");
+ MacToStr(macstr, sizeof(macstr), a->Ipc->MacAddress);
+ NLog(t->v, "LH_KERNEL_MODE_START", a->DeviceName,
+ &a->Ipc->ClientIPAddress, &a->Ipc->SubnetMask, &a->Ipc->DefaultGateway, &a->Ipc->BroadcastAddress,
+ macstr, &a->CurrentDhcpOptionList.ServerAddress, &a->DnsServerIP);
+ NnMainLoop(t, a);
+ Debug("NnMainLoop End.\n");
+
+ t->Active = false;
+ t->PublicIP = 0;
+
+
+ NnClearQueue(t);
+
+ // Close the stack
+ Lock(t->Lock);
+ {
+ if (t->HaltTube != NULL)
+ {
+ ReleaseTube(t->HaltTube);
+ t->HaltTube = NULL;
+ }
+ }
+ Unlock(t->Lock);
+ FreeNativeStack(a);
+
+ Zero(t->CurrentMacAddress, 6);
+ }
+ else
+ {
+ Debug("NnGetNextInterface Failed.\n");
+ }
+
+ // Wait for a certain period of time
+ if (t->NextWaitTimeForRetry != 0)
+ {
+ WaitUntilHostIPAddressChanged(wait_handle, t->HaltEvent, t->NextWaitTimeForRetry, 1000);
+ }
+ }
+
+ FreeWaitUntilHostIPAddressChanged(wait_handle);
+}
+
+// Erase the contents of the queue for transmission and reception
+void NnClearQueue(NATIVE_NAT *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ LockQueue(t->SendQueue);
+ {
+ while (true)
+ {
+ BLOCK *b = GetNext(t->SendQueue);
+
+ if (b == NULL)
+ {
+ break;
+ }
+
+ FreeBlock(b);
+ }
+ }
+ UnlockQueue(t->SendQueue);
+
+ LockQueue(t->RecvQueue);
+ {
+ while (true)
+ {
+ PKT *p = GetNext(t->RecvQueue);
+
+ if (p == NULL)
+ {
+ break;
+ }
+
+ FreePacketWithData(p);
+ }
+ }
+ UnlockQueue(t->RecvQueue);
+}
+
+// Structure setting function to search for native NAT
+void NnSetNat(NATIVE_NAT_ENTRY *e, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT pub_ip, UINT pub_port)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Zero(e, sizeof(NATIVE_NAT_ENTRY));
+
+ e->Protocol = protocol;
+ e->SrcIp = src_ip;
+ e->SrcPort = src_port;
+ e->DestIp = dest_ip;
+ e->DestPort = dest_port;
+ e->PublicIp = pub_ip;
+ e->PublicPort = pub_port;
+ e->HashCodeForSend = e->HashCodeForRecv = INFINITE;
+}
+
+// Get the hash code of the native NAT table (receiving direction)
+UINT GetHashNativeNatTableForRecv(void *p)
+{
+ UINT r;
+ NATIVE_NAT_ENTRY *e = (NATIVE_NAT_ENTRY *)p;
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ if (e->HashCodeForRecv != INFINITE)
+ {
+ return e->HashCodeForRecv;
+ }
+
+ r = 0;
+
+ r += e->Protocol;
+ r += e->PublicIp;
+ r += e->PublicPort;
+
+ if (e->Protocol == NAT_TCP)
+ {
+ r += e->DestIp;
+ r += e->DestPort;
+ }
+
+ e->HashCodeForRecv = r;
+
+ return r;
+}
+
+// Comparison function of native NAT table (receiving direction)
+int CmpNativeNatTableForRecv(void *p1, void *p2)
+{
+ int r;
+ NATIVE_NAT_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(NATIVE_NAT_ENTRY **)p1;
+ e2 = *(NATIVE_NAT_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(e1->Protocol, e2->Protocol);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->PublicIp, e2->PublicIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->PublicPort, e2->PublicPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ if (e1->Protocol == NAT_TCP)
+ {
+ r = COMPARE_RET(e1->DestIp, e2->DestIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->DestPort, e2->DestPort);
+ if (r != 0)
+ {
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+// Get the hash code of the native NAT table (transmit direction)
+UINT GetHashNativeNatTableForSend(void *p)
+{
+ UINT r;
+ NATIVE_NAT_ENTRY *e = (NATIVE_NAT_ENTRY *)p;
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ if (e->HashCodeForSend != INFINITE)
+ {
+ return e->HashCodeForSend;
+ }
+
+ r = 0;
+
+ r += e->Protocol;
+ r += e->SrcIp;
+ r += e->SrcPort;
+
+ if (e->Protocol == NAT_TCP)
+ {
+ r += e->DestIp;
+ r += e->DestPort;
+ }
+
+ e->HashCodeForSend = r;
+
+ return r;
+}
+
+// Comparison function of native NAT table (transmit direction)
+int CmpNativeNatTableForSend(void *p1, void *p2)
+{
+ int r;
+ NATIVE_NAT_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(NATIVE_NAT_ENTRY **)p1;
+ e2 = *(NATIVE_NAT_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(e1->Protocol, e2->Protocol);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->SrcIp, e2->SrcIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->SrcPort, e2->SrcPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ if (e1->Protocol == NAT_TCP)
+ {
+ r = COMPARE_RET(e1->DestIp, e2->DestIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(e1->DestPort, e2->DestPort);
+ if (r != 0)
+ {
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+// Start the native NAT
+NATIVE_NAT *NewNativeNat(VH *v)
+{
+ NATIVE_NAT *t;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(NATIVE_NAT));
+
+ t->v = v;
+
+ t->Cancel = v->Cancel;
+ AddRef(t->Cancel->ref);
+
+ // Data structure initialization
+ t->LastInterfaceIndex = INFINITE;
+ t->SendQueue = NewQueue();
+ t->RecvQueue = NewQueue();
+ NnInitIpCombineList(t);
+
+ t->Lock = NewLock();
+
+ t->CancelLock = NewLock();
+
+ t->HaltEvent = NewEvent();
+
+ NewTubePair(&t->HaltTube2, &t->HaltTube3, 0);
+
+ // Create a NAT table
+ t->NatTableForSend = NewHashList(GetHashNativeNatTableForSend, CmpNativeNatTableForSend, 11, true);
+ t->NatTableForRecv = NewHashList(GetHashNativeNatTableForRecv, CmpNativeNatTableForRecv, 11, true);
+
+ t->Thread = NewThread(NativeNatThread, t);
+
+ return t;
+}
+
+// Stop the native NAT
+void FreeNativeNat(NATIVE_NAT *t)
+{
+ TUBE *tube;
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ t->Halt = true;
+
+ Lock(t->Lock);
+ {
+ tube = t->HaltTube;
+
+ if (tube != NULL)
+ {
+ AddRef(tube->Ref);
+ }
+ }
+ Unlock(t->Lock);
+
+ if (tube != NULL)
+ {
+ TubeFlushEx(tube, true);
+
+ SleepThread(100);
+
+ TubeDisconnect(tube);
+
+ ReleaseTube(tube);
+ }
+
+ TubeDisconnect(t->HaltTube2);
+ TubeDisconnect(t->HaltTube3);
+
+ Set(t->HaltEvent);
+
+ WaitThread(t->Thread, INFINITE);
+
+ ReleaseThread(t->Thread);
+
+ DeleteLock(t->Lock);
+
+ DeleteLock(t->CancelLock);
+
+ ReleaseEvent(t->HaltEvent);
+
+ ReleaseTube(t->HaltTube2);
+ ReleaseTube(t->HaltTube3);
+
+ NnClearQueue(t);
+
+ ReleaseQueue(t->RecvQueue);
+ ReleaseQueue(t->SendQueue);
+
+ ReleaseCancel(t->Cancel);
+
+ // Release the NAT table
+ for (i = 0;i < LIST_NUM(t->NatTableForSend->AllList);i++)
+ {
+ NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForSend->AllList, i);
+
+ Free(e);
+ }
+
+ ReleaseHashList(t->NatTableForSend);
+ ReleaseHashList(t->NatTableForRecv);
+
+ NnFreeIpCombineList(t);
+
+ Free(t);
+}
+
+// Take the log of Virtual Host
+void VLog(VH *v, char *str)
+{
+ // Not take!!
+ return;
+}
+
+// Disconnect the NAT entry immediately
+void DisconnectNatEntryNow(VH *v, NAT_ENTRY *e)
+{
+ // Validate arguments
+ if (v == NULL || e == NULL)
+ {
+ return;
+ }
+
+ if (e->DisconnectNow == false)
+ {
+ e->DisconnectNow = true;
+
+ SetSockEvent(v->SockEvent);
+ }
+}
+
+// Get the NAT entry with specified source IP address and the oldest last communication time
+NAT_ENTRY *GetOldestNatEntryOfIp(VH *v, UINT ip, UINT protocol)
+{
+ UINT i;
+ NAT_ENTRY *oldest = NULL;
+ UINT64 oldest_tick = 0xFFFFFFFFFFFFFFFFULL;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(v->NatTable);i++)
+ {
+ NAT_ENTRY *e = LIST_DATA(v->NatTable, i);
+
+ if (e->DisconnectNow == false)
+ {
+ if (e->SrcIp == ip)
+ {
+ if (e->Protocol == protocol)
+ {
+ if (protocol != NAT_TCP || e->TcpStatus != NAT_TCP_CONNECTING)
+ {
+ if (e->LastCommTime <= oldest_tick)
+ {
+ oldest_tick = e->LastCommTime;
+ oldest = e;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return oldest;
+}
+
+// Get the number of current NAT entries per IP address
+UINT GetNumNatEntriesPerIp(VH *v, UINT ip, UINT protocol, bool tcp_syn_sent)
+{
+ UINT ret = 0;
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < LIST_NUM(v->NatTable);i++)
+ {
+ NAT_ENTRY *e = LIST_DATA(v->NatTable, i);
+
+ if (e->DisconnectNow == false)
+ {
+ if (e->SrcIp == ip)
+ {
+ if (e->Protocol == protocol)
+ {
+ bool ok = false;
+
+ if (protocol == NAT_TCP)
+ {
+ if (tcp_syn_sent)
+ {
+ if (e->TcpStatus == NAT_TCP_CONNECTING)
+ {
+ ok = true;
+ }
+ }
+ else
+ {
+ if (e->TcpStatus != NAT_TCP_CONNECTING)
+ {
+ ok = true;
+ }
+ }
+ }
+ else
+ {
+ ok = true;
+ }
+
+ if (ok)
+ {
+ ret++;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Check whether the NAT is available
+bool CanCreateNewNatEntry(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return false;
+ }
+
+ if (v->UseNat == false)
+ {
+ // NAT stopped
+ return false;
+ }
+
+ if (NnIsActive(v) && v->NativeNat != NULL && v->NativeNat->NatTableForRecv != NULL)
+ {
+ if (v->NativeNat->NatTableForRecv->AllList->num_item > NAT_MAX_SESSIONS_KERNEL)
+ {
+ // Number of sessions exceeded (kernel mode)
+ return false;
+ }
+ }
+ else
+ {
+ if (v->NatTable->num_item > NAT_MAX_SESSIONS)
+ {
+ // Number of sessions exceeded (user mode)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Set a pointer to the Virtual HUB options
+void NatSetHubOption(VH *v, HUB_OPTION *o)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->HubOption = o;
+}
+
+// Get a pointer to the Virtual HUB options
+HUB_OPTION *NatGetHubOption(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ return v->HubOption;
+}
+
+// The main function of NAT processing thread
+void NatThreadMain(VH *v)
+{
+ bool halt_flag;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->TmpBuf = Malloc(NAT_TMPBUF_SIZE);
+
+ while (true)
+ {
+ // Wait until the next event is set
+ WaitSockEvent(v->SockEvent, SELECT_TIME);
+
+ halt_flag = false;
+
+ LockVirtual(v);
+ {
+ // Process on all NAT sessions
+ UINT i, num;
+
+ v->Now = Tick64();
+ v->NatDoCancelFlag = false;
+
+LIST_ELEMENT_DELETED:
+ num = LIST_NUM(v->NatTable);
+ for (i = 0;i < num;i++)
+ {
+ NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
+
+ switch (n->Protocol)
+ {
+ case NAT_TCP: // TCP
+ if (NatTransactTcp(v, n) == false)
+ {
+ goto LIST_ELEMENT_DELETED;
+ }
+ break;
+
+ case NAT_UDP: // UDP
+ if (NatTransactUdp(v, n) == false)
+ {
+ goto LIST_ELEMENT_DELETED;
+ }
+ break;
+
+ case NAT_ICMP: // ICMP
+ if (NatTransactIcmp(v, n) == false)
+ {
+ goto LIST_ELEMENT_DELETED;
+ }
+ break;
+
+ case NAT_DNS: // DNS
+ if (NatTransactDns(v, n) == false)
+ {
+ goto LIST_ELEMENT_DELETED;
+ }
+ break;
+ }
+ }
+
+ if (v->NatDoCancelFlag)
+ {
+ // Hit the cancel of the parent thread
+ Cancel(v->Cancel);
+ }
+
+ // Halting flag check
+ if (v->HaltNat)
+ {
+ halt_flag = true;
+ }
+ }
+ UnlockVirtual(v);
+
+ if (halt_flag)
+ {
+ // Terminate the thread by disconnecting all entries forcibly
+ LockVirtual(v);
+ {
+ UINT num = LIST_NUM(v->NatTable);
+ NAT_ENTRY **nn = ToArray(v->NatTable);
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ NAT_ENTRY *n = nn[i];
+ n->DisconnectNow = true;
+
+ switch (n->Protocol)
+ {
+ case NAT_TCP: // TCP
+ NatTransactTcp(v, n);
+ break;
+
+ case NAT_UDP: // UDP
+ NatTransactUdp(v, n);
+ break;
+
+ case NAT_ICMP: // ICMP
+ NatTransactIcmp(v, n);
+ break;
+
+ case NAT_DNS: // DNS
+ NatTransactDns(v, n);
+ break;
+ }
+ }
+
+ Free(nn);
+ }
+ UnlockVirtual(v);
+ break;
+ }
+ }
+
+ Free(v->TmpBuf);
+}
+
+// DNS: Thread to get the IP address
+void NatGetIPThread(THREAD *t, void *param)
+{
+ NAT_DNS_QUERY *q;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ q = (NAT_DNS_QUERY *)param;
+ AddWaitThread(t);
+
+ q->Ok = GetIP(&q->Ip, q->Hostname);
+
+ DelWaitThread(t);
+
+ if (Release(q->ref) == 0)
+ {
+ Free(q);
+ }
+}
+
+// DNS: Get an IP address from host name
+bool NatGetIP(IP *ip, char *hostname)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ t = ParseToken(hostname, ".");
+ if (t == NULL)
+ {
+ return false;
+ }
+ if (t->NumTokens == 0)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ if (t->NumTokens == 1)
+ {
+ ret = GetIP(ip, hostname);
+ }
+ else
+ {
+ char *hostname2 = t->Token[0];
+ NAT_DNS_QUERY *q1, *q2;
+ THREAD *t1, *t2;
+
+ q1 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
+ q2 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
+ q1->ref = NewRef();
+ q2->ref = NewRef();
+ AddRef(q1->ref);
+ AddRef(q2->ref);
+ StrCpy(q1->Hostname, sizeof(q1->Hostname), hostname);
+ StrCpy(q2->Hostname, sizeof(q2->Hostname), hostname2);
+
+ t1 = NewThread(NatGetIPThread, q1);
+ t2 = NewThread(NatGetIPThread, q2);
+
+ WaitThread(t1, NAT_DNS_QUERY_TIMEOUT);
+
+ if (q1->Ok)
+ {
+ ret = true;
+ Copy(ip, &q1->Ip, sizeof(IP));
+ }
+ else
+ {
+ WaitThread(t2, NAT_DNS_QUERY_TIMEOUT);
+ if (q1->Ok)
+ {
+ ret = true;
+ Copy(ip, &q1->Ip, sizeof(IP));
+ }
+ else if (q2->Ok)
+ {
+ ret = true;
+ Copy(ip, &q2->Ip, sizeof(IP));
+ }
+ }
+
+ ReleaseThread(t1);
+ ReleaseThread(t2);
+
+ if (Release(q1->ref) == 0)
+ {
+ Free(q1);
+ }
+ if (Release(q2->ref) == 0)
+ {
+ Free(q2);
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// DNS query function
+void NatDnsThread(THREAD *t, void *param)
+{
+ NAT_ENTRY *n;
+ IP ip;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+ n = (NAT_ENTRY *)param;
+
+ // Notify the initialization completion
+ NoticeThreadInit(t);
+
+ // Run processing
+ if (EndWith(n->DnsTargetHostName, ".in-addr.arpa") == false)
+ {
+ // Forward resolution
+ if (NatGetIP(&ip, n->DnsTargetHostName))
+ {
+ // Forward resolution success
+ Copy(&n->DnsResponseIp, &ip, sizeof(IP));
+ n->DnsOk = true;
+ }
+ }
+ else
+ {
+ // Reverse resolution
+ IP ip;
+ n->DnsGetIpFromHost = true; // Set the reverse resolution flag
+ // Convert a *.in-addr.arpa string to an IP address
+ if (ArpaToIP(&ip, n->DnsTargetHostName))
+ {
+ // Reverse resolution process
+ char tmp[256];
+ if (GetHostName(tmp, sizeof(tmp), &ip))
+ {
+ // Reverse resolution success
+ n->DnsResponseHostName = CopyStr(tmp);
+ n->DnsOk = true;
+ }
+ }
+ }
+
+ // Notify the results
+ n->DnsFinished = true;
+
+ SetSockEvent(n->v->SockEvent);
+}
+
+// Convert a reverse resolution address to an IP address
+bool ArpaToIP(IP *ip, char *str)
+{
+ TOKEN_LIST *token;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // Token conversion
+ token = ParseToken(str, ".");
+ if (token->NumTokens == 6)
+ {
+ // Convert the token [0, 1, 2, 3] to IP
+ UINT i;
+ Zero(ip, sizeof(IP));
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = (UCHAR)ToInt(token->Token[3 - i]);
+ }
+ ret = true;
+ }
+
+ FreeToken(token);
+
+ if (IPToUINT(ip) == 0)
+ {
+ ret = false;
+ }
+
+ return ret;
+}
+
+// Handle a DNS entry
+bool NatTransactDns(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return true;
+ }
+
+ if (n->DisconnectNow)
+ {
+ goto DISCONNECT;
+ }
+
+ if (n->DnsThread == NULL && n->DnsFinished == false)
+ {
+ // Create a thread
+ THREAD *t = NewThread(NatDnsThread, (void *)n);
+ WaitThreadInit(t);
+ n->DnsThread = t;
+ }
+ else
+ {
+ // Wait for the result
+ if (n->DnsFinished)
+ {
+ // Results have been received
+ WaitThread(n->DnsThread, INFINITE);
+ ReleaseThread(n->DnsThread);
+ n->DnsThread = NULL;
+ // Notify to the main thread
+ v->NatDoCancelFlag = true;
+ }
+ }
+
+ return true;
+
+DISCONNECT:
+
+ // Releasing process
+ if (n->DnsThread != NULL)
+ {
+ WaitThread(n->DnsThread, INFINITE);
+ ReleaseThread(n->DnsThread);
+ n->DnsThread = NULL;
+ }
+
+ if (n->DnsTargetHostName != NULL)
+ {
+ Free(n->DnsTargetHostName);
+ n->DnsTargetHostName = NULL;
+ }
+
+ if (n->DnsResponseHostName != NULL)
+ {
+ Free(n->DnsResponseHostName);
+ n->DnsResponseHostName = NULL;
+ }
+
+ DeleteLock(n->lock);
+ Delete(v->NatTable, n);
+ Free(n);
+
+ return false;
+}
+
+// ICMP thread procedure
+void NatIcmpThreadProc(THREAD *thread, void *param)
+{
+ NAT_ENTRY *n;
+ ICMP_RESULT *ret = NULL;
+ USHORT src_id = 0, src_seqno = 0;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ n = (NAT_ENTRY *)param;
+
+ if (n->IcmpQueryBlock)
+ {
+ UCHAR *data = n->IcmpQueryBlock->Buf;
+ UINT size = n->IcmpQueryBlock->Size;
+
+ if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ ICMP_HEADER *icmp = (ICMP_HEADER *)data;
+ ICMP_ECHO *echo = (ICMP_ECHO *)(data + sizeof(ICMP_HEADER));
+
+ if (icmp->Type == ICMP_TYPE_ECHO_REQUEST && icmp->Code == 0)
+ {
+ UCHAR *icmp_payload = data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ UINT icmp_payload_size = size - sizeof(ICMP_HEADER) - sizeof(ICMP_ECHO);
+ IP dest_ip;
+
+ src_id = Endian16(echo->Identifier);
+ src_seqno = Endian16(echo->SeqNo);
+
+ UINTToIP(&dest_ip, n->DestIp);
+
+ // Send a query by using the ICMP API
+ ret = IcmpApiEchoSend(&dest_ip, n->IcmpQueryBlock->Ttl,
+ icmp_payload, icmp_payload_size, NAT_ICMP_TIMEOUT_WITH_API);
+ }
+ }
+ }
+
+ if (ret != NULL && ret->Timeout == false)
+ {
+ // Convert to an IPv4 + ICMP packet since the result of ICMP API was obtained
+ IPV4_HEADER ipv4;
+ ICMP_HEADER icmp;
+ ICMP_ECHO echo;
+ BUF *buf = NewBuf();
+
+ // IPv4 header
+ Zero(&ipv4, sizeof(ipv4));
+ IPV4_SET_VERSION(&ipv4, 4);
+ IPV4_SET_HEADER_LEN(&ipv4, sizeof(IPV4_HEADER) / 4);
+ ipv4.TimeToLive = ret->Ttl;
+ ipv4.Protocol = IP_PROTO_ICMPV4;
+ ipv4.SrcIP = IPToUINT(&ret->IpAddress);
+ ipv4.DstIP = 0x01010101;
+
+
+ // ICMP header
+ Zero(&icmp, sizeof(icmp));
+ Zero(&echo, sizeof(echo));
+
+ if (ret->Ok)
+ {
+ // Normal response
+ echo.Identifier = Endian16(src_id);
+ echo.SeqNo = Endian16(src_seqno);
+
+ ipv4.TotalLength = Endian16((USHORT)(sizeof(ipv4) + sizeof(icmp) + sizeof(echo) + ret->DataSize));
+
+ WriteBuf(buf, &ipv4, sizeof(ipv4));
+ WriteBuf(buf, &icmp, sizeof(icmp));
+ WriteBuf(buf, &echo, sizeof(echo));
+ WriteBuf(buf, ret->Data, ret->DataSize);
+ }
+ else
+ {
+ // Error reply
+ icmp.Type = ret->Type;
+ icmp.Code = ret->Code;
+ echo.Identifier = Endian16(src_id);
+ echo.SeqNo = Endian16(src_seqno);
+
+ ipv4.TotalLength = Endian16((USHORT)(sizeof(ipv4) + sizeof(icmp) + sizeof(echo) + n->IcmpOriginalCopySize));
+
+ WriteBuf(buf, &ipv4, sizeof(ipv4));
+ WriteBuf(buf, &icmp, sizeof(icmp));
+ WriteBuf(buf, &echo, sizeof(echo));
+
+ // Copy of the original packet to be included in the response packet
+ WriteBuf(buf, n->IcmpOriginalCopy, n->IcmpOriginalCopySize);
+ }
+
+ n->IcmpResponseBlock = NewBlock(Clone(buf->Buf, buf->Size), buf->Size, 0);
+ n->IcmpResponseBlock->Ttl = ret->Ttl;
+
+ FreeBuf(buf);
+ }
+ IcmpApiFreeResult(ret);
+
+ // Inform the completion of the processing
+ n->IcmpTaskFinished = true;
+ SetSockEvent(n->v->SockEvent);
+}
+
+// Process ICMP entry
+bool NatTransactIcmp(VH *v, NAT_ENTRY *n)
+{
+ void *buf;
+ UINT recv_size;
+ BLOCK *block;
+ UINT dest_port = n->DestPort;
+ IP dest_ip;
+ UINT num_ignore_errors = 0;
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return true;
+ }
+
+ if (n->DisconnectNow)
+ {
+ goto DISCONNECT;
+ }
+
+ if (v->IcmpRawSocketOk)
+ {
+ // Environment that the Raw sockets are available
+ if (n->UdpSocketCreated == false)
+ {
+ // Create a UDP socket
+ n->Sock = NewUDP(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4));
+ if (n->Sock == NULL)
+ {
+ // Socket creation failure
+ goto DISCONNECT;
+ }
+ else
+ {
+ n->PublicIp = IPToUINT(&n->Sock->LocalIP);
+ n->PublicPort = n->Sock->LocalPort;
+
+ JoinSockToSockEvent(n->Sock, v->SockEvent);
+ n->UdpSocketCreated = true;
+ }
+ }
+ }
+ else
+ {
+ // Create a thread for using ICMP API if Raw sockets are not available
+ if (n->IcmpThread == NULL)
+ {
+ if (n->UdpSendQueue->num_item >= 1)
+ {
+ // Since UdpSendQueue contains only 1 query, get a first query
+ // and create a thread and pass the query to the thread
+ BLOCK *block = GetNext(n->UdpSendQueue);
+
+ n->IcmpQueryBlock = block;
+
+ n->IcmpThread = NewThread(NatIcmpThreadProc, n);
+ }
+ }
+
+ if (n->IcmpTaskFinished)
+ {
+ if (n->IcmpResponseBlock != NULL)
+ {
+ // Because there was a response from the thread that calls ICMP API, pass this result to the stack
+ block = n->IcmpResponseBlock;
+ n->IcmpResponseBlock = NULL;
+ InsertQueue(n->UdpRecvQueue, block);
+ v->NatDoCancelFlag = true;
+ n->LastCommTime = v->Now;
+ }
+ else
+ {
+ // Disconnect immediately when it fails
+ goto DISCONNECT;
+ }
+ }
+
+ // Examine whether this session timed-out
+ if ((n->LastCommTime + (UINT64)NAT_ICMP_TIMEOUT_WITH_API) < v->Now || n->LastCommTime > v->Now)
+ {
+ // Time-out
+ goto DISCONNECT;
+ }
+
+ return true;
+ }
+
+ // Following are processed only for if the raw sockets are available
+ buf = v->TmpBuf;
+ UINTToIP(&dest_ip, n->DestIp);
+
+ // Try to receive data from the UDP socket
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ recv_size = RecvFrom(n->Sock, &src_ip, &src_port, buf, 65536);
+
+ if (recv_size == SOCK_LATER)
+ {
+ // Packet has not arrived
+ break;
+ }
+ else if (recv_size == 0)
+ {
+ Debug("ICMP ERROR\n");
+ // Error?
+ if (n->Sock->IgnoreRecvErr == false)
+ {
+ // A fatal error occurred
+ goto DISCONNECT;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto DISCONNECT;
+ }
+ }
+ }
+ else
+ {
+ // Analyze the arriving packet
+ ICMP_RESULT *ret = IcmpParseResult(&dest_ip, n->SrcPort, 0, buf, recv_size);
+
+ if (ret != NULL)
+ {
+ if ((ret->Ok && CmpIpAddr(&ret->IpAddress, &dest_ip) == 0) ||
+ (ret->DataSize >= sizeof(IPV4_HEADER) && ((IPV4_HEADER *)ret->Data)->DstIP == n->DestIp))
+ {
+ // Insert to the queue
+ void *data = Malloc(recv_size);
+ Copy(data, buf, recv_size);
+ block = NewBlock(data, recv_size, 0);
+ InsertQueue(n->UdpRecvQueue, block);
+ v->NatDoCancelFlag = true;
+ n->LastCommTime = v->Now;
+ }
+
+ IcmpFreeResult(ret);
+ }
+ }
+ }
+
+ // Try to send data to the UDP socket
+ while (block = GetNext(n->UdpSendQueue))
+ {
+ // Assemble the Echo header and ICMP header
+ UINT send_size;
+
+ SetTtl(n->Sock, block->Ttl);
+ send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
+
+ FreeBlock(block);
+ if (send_size == 0)
+ {
+ Debug("ICMP ERROR\n");
+ // Determine whether a fatal error
+ if (n->Sock->IgnoreSendErr == false)
+ {
+ // A fatal error occurred
+ goto DISCONNECT;
+ }
+ }
+ else
+ {
+ n->LastCommTime = v->Now;
+ }
+ }
+
+ // Examine whether this session timed-out
+ if ((n->LastCommTime + (UINT64)NAT_ICMP_TIMEOUT) < v->Now || n->LastCommTime > v->Now)
+ {
+ // Time-out
+ goto DISCONNECT;
+ }
+
+ return true;
+
+DISCONNECT:
+ // Disconnect this session
+ if (n->UdpSocketCreated)
+ {
+ // Close the socket
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+ n->Sock = NULL;
+ }
+
+ // Terminate if the thread has been created
+ if (n->IcmpThread != NULL)
+ {
+ WaitThread(n->IcmpThread, INFINITE);
+ ReleaseThread(n->IcmpThread);
+ n->IcmpThread = NULL;
+ }
+
+ // Delete the entry
+ DeleteNatIcmp(v, n);
+
+ return false;
+}
+
+// Process the UDP entry
+bool NatTransactUdp(VH *v, NAT_ENTRY *n)
+{
+ void *buf;
+ UINT recv_size;
+ BLOCK *block;
+ UINT dest_port = n->DestPort;
+ IP dest_ip;
+ UINT num_ignore_errors;
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return true;
+ }
+
+ if (n->DisconnectNow)
+ {
+ goto DISCONNECT;
+ }
+
+ if (n->UdpSocketCreated == false)
+ {
+ // Create a UDP socket
+ n->Sock = NewUDP(0);
+ if (n->Sock == NULL)
+ {
+ // Socket creation failure
+ goto DISCONNECT;
+ }
+ else
+ {
+ n->PublicIp = IPToUINT(&n->Sock->LocalIP);
+ n->PublicPort = n->Sock->LocalPort;
+
+ JoinSockToSockEvent(n->Sock, v->SockEvent);
+ n->UdpSocketCreated = true;
+ }
+ }
+
+ buf = v->TmpBuf;
+ if (n->ProxyDns == false)
+ {
+ UINTToIP(&dest_ip, n->DestIp);
+ }
+ else
+ {
+ UINTToIP(&dest_ip, n->DestIpProxy);
+ }
+
+ num_ignore_errors = 0;
+
+ // Try to receive data from the UDP socket
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ recv_size = RecvFrom(n->Sock, &src_ip, &src_port, buf, 65536);
+
+ if (recv_size == SOCK_LATER)
+ {
+ // Packet has not arrived
+ break;
+ }
+ else if (recv_size == 0)
+ {
+ // Error?
+ if (n->Sock->IgnoreRecvErr == false)
+ {
+ // A fatal error occurred
+ goto DISCONNECT;
+ }
+ else
+ {
+ if ((num_ignore_errors++) > MAX_NUM_IGNORE_ERRORS)
+ {
+ goto DISCONNECT;
+ }
+ }
+ }
+ else
+ {
+ // Packet arrives. Check the source IP
+ if (IPToUINT(&src_ip) == n->DestIp || n->DestIp == 0xFFFFFFFF || (IPToUINT(&src_ip) == n->DestIpProxy && n->ProxyDns) && src_port == n->DestPort)
+ {
+ // Insert to the queue
+ void *data = Malloc(recv_size);
+ Copy(data, buf, recv_size);
+ block = NewBlock(data, recv_size, 0);
+
+ if (block != NULL)
+ {
+ if (src_port == SPECIAL_UDP_PORT_WSD || src_port == SPECIAL_UDP_PORT_SSDP)
+ {
+ // Make believe there is a response from the host really in the case of WSD packet
+ block->Param1 = IPToUINT(&src_ip);
+ }
+ }
+
+ InsertQueue(n->UdpRecvQueue, block);
+ v->NatDoCancelFlag = true;
+ n->LastCommTime = v->Now;
+ }
+ }
+ }
+
+ // Try to send data to the UDP socket
+ while (block = GetNext(n->UdpSendQueue))
+ {
+ UINT send_size;
+ bool is_nbtdgm = false;
+ LIST *local_ip_list = NULL;
+
+ if (dest_port == SPECIAL_UDP_PORT_NBTDGM)
+ {
+ // Determine whether NetBIOS Datagram packet
+ NBTDG_HEADER *nh = (NBTDG_HEADER *)block->Buf;
+
+ if (nh != NULL && block->Size >= sizeof(NBTDG_HEADER))
+ {
+ if (nh->SrcIP == n->SrcIp && Endian16(nh->SrcPort) == n->SrcPort)
+ {
+ local_ip_list = GetHostIPAddressList();
+
+ if (local_ip_list != NULL)
+ {
+ is_nbtdgm = true;
+ }
+ }
+ }
+ }
+
+ if (is_nbtdgm == false)
+ {
+ // Normal UDP packet
+ send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
+ }
+ else
+ {
+ // IP address and port number is embedded in the NetBIOS Datagram Packet.
+ // Transfer by rewriting it properly
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(local_ip_list);i++)
+ {
+ IP *my_ip = LIST_DATA(local_ip_list, i);
+
+ if (IsIP4(my_ip) && IsZeroIp(my_ip) == false && IsLocalHostIP(my_ip) == false)
+ {
+ NBTDG_HEADER *nh = (NBTDG_HEADER *)block->Buf;
+
+ nh->SrcIP = IPToUINT(my_ip);
+ nh->SrcPort = Endian16(n->PublicPort);
+
+ send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
+ }
+ }
+ }
+
+ if (local_ip_list != NULL)
+ {
+ FreeHostIPAddressList(local_ip_list);
+ }
+
+ FreeBlock(block);
+ if (send_size == 0)
+ {
+ // Determining whether a fatal error
+ if (n->Sock->IgnoreSendErr == false)
+ {
+ // A fatal error occurred
+ goto DISCONNECT;
+ }
+ }
+ else
+ {
+ n->LastCommTime = v->Now;
+ }
+ }
+
+ // Examine whether this session timed-out
+ if ((n->LastCommTime + (UINT64)v->NatUdpTimeout) < v->Now || n->LastCommTime > v->Now)
+ {
+ // Time-out
+ goto DISCONNECT;
+ }
+
+ return true;
+
+DISCONNECT:
+ // Disconnect this session
+ if (n->UdpSocketCreated)
+ {
+ // Close the socket
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+ n->Sock = NULL;
+ }
+
+ // Delete the entry
+ DeleteNatUdp(v, n);
+
+ return false;
+}
+
+// Thread to make a connection to the TCP host
+void NatTcpConnectThread(THREAD *t, void *p)
+{
+ NAT_ENTRY *n = (NAT_ENTRY *)p;
+ IP ip;
+ char hostname[MAX_SIZE];
+ UINT port_number;
+ SOCK *sock;
+ SOCK_EVENT *e;
+ // Validate arguments
+ if (n == NULL || t == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip, n->DestIp);
+ IPToStr(hostname, sizeof(hostname), &ip);
+ port_number = n->DestPort;
+ e = n->v->SockEvent;
+ AddRef(e->ref);
+
+ // Notify the initialization completion
+ NoticeThreadInit(t);
+
+ // Attempt to connect to the TCP host
+ Debug("NatTcpConnect Connecting to %s:%u\n", hostname, port_number);
+ sock = ConnectEx3(hostname, port_number, 0, &n->NatTcpCancelFlag, NULL, NULL, false, false, true);
+ if (sock == NULL)
+ {
+ // Connection failure
+ n->TcpMakeConnectionFailed = true;
+ }
+ else
+ {
+ // Successful connection
+ n->TcpMakeConnectionSucceed = true;
+ }
+ n->Sock = sock;
+ JoinSockToSockEvent(sock, e);
+ SetSockEvent(e);
+
+ ReleaseSockEvent(e);
+}
+
+// Create a thread for trying to connect to the TCP host
+void CreateNatTcpConnectThread(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ // Create a thread
+ n->NatTcpConnectThread = NewThread(NatTcpConnectThread, (void *)n);
+
+ // Wait for a thread initialization completion
+ WaitThreadInit(n->NatTcpConnectThread);
+}
+
+// Handle the TCP entry
+bool NatTransactTcp(VH *v, NAT_ENTRY *n)
+{
+ char str[MAX_SIZE];
+ bool timeouted = false;
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return false;
+ }
+
+ if (n->DisconnectNow)
+ {
+ goto DISCONNECT;
+ }
+
+ // Process by state of the TCP
+ switch (n->TcpStatus)
+ {
+ case NAT_TCP_CONNECTING: // Waiting for connection
+ if (n->NatTcpConnectThread == NULL)
+ {
+ // Start a connection by creating a connection thread
+ CreateNatTcpConnectThread(v, n);
+ }
+ else
+ {
+ // Wait for the result of the connection thread that has already started
+ if (n->TcpMakeConnectionFailed || n->TcpMakeConnectionSucceed)
+ {
+ // Use the results because operation thread has already finished
+ WaitThread(n->NatTcpConnectThread, INFINITE);
+ ReleaseThread(n->NatTcpConnectThread);
+ n->NatTcpConnectThread = NULL;
+
+ if (n->TcpMakeConnectionSucceed)
+ {
+ // Connection is successful, and a Sock was created
+ n->TcpStatus = NAT_TCP_CONNECTED;
+ IPToStr32(str, sizeof(str), n->DestIp);
+ NLog(v, "LH_NAT_TCP_SUCCEED", n->Id, n->Sock->RemoteHostname, str, n->DestPort);
+ }
+ else
+ {
+ // Failed to connect
+ n->TcpStatus = NAT_TCP_SEND_RESET;
+ IPToStr32(str, sizeof(str), n->DestIp);
+ NLog(v, "LH_NAT_TCP_FAILED", n->Id, str, n->DestPort);
+ }
+ v->NatDoCancelFlag = true;
+ }
+ }
+ break;
+
+ case NAT_TCP_CONNECTED: // TCP socket connection completed. Negotiating with the client host
+ break;
+
+ case NAT_TCP_SEND_RESET: // TCP communication disconnection: Send a RST to the client host
+ break;
+
+ case NAT_TCP_ESTABLISHED: // TCP connection established
+ {
+ UINT old_send_fifo_size = 0;
+
+ // Transmit to the socket if there is data in the receive buffer
+ while (n->RecvFifo->size > 0)
+ {
+ UINT sent_size = Send(n->Sock, ((UCHAR *)n->RecvFifo->p) + n->RecvFifo->pos,
+ n->RecvFifo->size, false);
+ if (sent_size == 0)
+ {
+ // Communication has been disconnected
+ n->TcpFinished = true;
+ v->NatDoCancelFlag = true;
+ break;
+ }
+ else if (sent_size == SOCK_LATER)
+ {
+ // Blocking
+ break;
+ }
+ else
+ {
+ // Successful transmission
+ ReadFifo(n->RecvFifo, NULL, sent_size);
+ n->SendAckNext = true;
+ }
+ }
+
+ old_send_fifo_size = FifoSize(n->SendFifo);
+
+ // Write to the transmission buffer by obtaining data from the socket
+ while (true)
+ {
+ void *buf = (void *)v->TmpBuf;
+ UINT want_to_recv_size = 0;
+ UINT recv_size;
+ // Calculate the size of wanting to receive
+ if (n->SendFifo->size < NAT_SEND_BUF_SIZE)
+ {
+ // Still can receive
+ want_to_recv_size = MIN(NAT_SEND_BUF_SIZE - n->SendFifo->size, NAT_TMPBUF_SIZE);
+ }
+ if (want_to_recv_size == 0)
+ {
+ SetNoNeedToRead(n->Sock);
+ break;
+ }
+ recv_size = Recv(n->Sock, buf, want_to_recv_size, false);
+ if (recv_size == 0)
+ {
+ // Communication has been disconnected
+ n->TcpFinished = true;
+ v->NatDoCancelFlag = true;
+ break;
+ }
+ else if (recv_size == SOCK_LATER)
+ {
+ // Blocking
+ break;
+ }
+ else
+ {
+ // Successful reception
+ WriteFifo(n->SendFifo, buf, recv_size);
+ v->NatDoCancelFlag = true;
+ }
+ }
+
+ if (old_send_fifo_size == 0 && FifoSize(n->SendFifo) != 0)
+ {
+ // Reset the time data for timeout when the data is newly queued
+ // in the empty transmission buffer in the transmission process
+ n->TcpLastRecvAckTime = v->Now;
+ }
+
+ // Raise a transmission time-out if a certain period of time elapsed
+ // after receiving the last ACK, and the transmission buffer is not
+ // empty, and the reception window size of other party is not 0
+ if ((n->TcpLastRecvAckTime + (UINT64)VIRTUAL_TCP_SEND_TIMEOUT) < v->Now)
+ {
+ if (FifoSize(n->SendFifo) != 0 && n->TcpSendWindowSize != 0)
+ {
+ timeouted = true;
+ }
+ }
+ }
+ break;
+
+ }
+
+ // Timeout Detection
+ if ((n->LastCommTime + (UINT64)v->NatTcpTimeout) < v->Now || n->LastCommTime > v->Now)
+ {
+ timeouted = true;
+ }
+
+ if (timeouted)
+ {
+ // Time-out occurs, the session close
+ n->TcpStatus = NAT_TCP_SEND_RESET;
+ v->NatDoCancelFlag = true;
+ }
+
+ return true;
+
+DISCONNECT: // Disconnect and session disposal
+ DeleteNatTcp(v, n);
+
+ return false;
+}
+
+// Delete the entry of TCP NAT
+void DeleteNatTcp(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ NLog(v, "LH_NAT_TCP_DELETED", n->Id);
+
+ // Shutdown of connection thread
+ if (n->NatTcpConnectThread != NULL)
+ {
+ n->NatTcpCancelFlag = true;
+
+ WaitThread(n->NatTcpConnectThread, INFINITE);
+ ReleaseThread(n->NatTcpConnectThread);
+ n->NatTcpConnectThread = NULL;
+ }
+ if (n->Sock != NULL)
+ {
+ // Disconnect the socket
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+ n->Sock = NULL;
+ }
+
+ // Release the window memory
+ if (n->TcpRecvWindow != NULL)
+ {
+ ReleaseFifo(n->TcpRecvWindow);
+ n->TcpRecvWindow = NULL;
+ }
+
+ // Release the window reception list
+ if (n->TcpRecvList != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
+ {
+ IP_PART *p = LIST_DATA(n->TcpRecvList, i);
+ Free(p);
+ }
+ ReleaseList(n->TcpRecvList);
+ n->TcpRecvList = NULL;
+ }
+
+ // FIFO release
+ ReleaseFifo(n->SendFifo);
+ ReleaseFifo(n->RecvFifo);
+
+ // Delete from the NAT entry
+ Delete(v->NatTable, n);
+
+ DeleteLock(n->lock);
+
+ // Release the memory
+ Free(n);
+
+ Debug("NAT_ENTRY: DeleteNatTcp\n");
+}
+
+// NAT processing thread
+void NatThread(THREAD *t, void *param)
+{
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Notify the initialization completion
+ NoticeThreadInit(t);
+
+ NatThreadMain((VH *)param);
+}
+
+// Send a beacon packet
+void SendBeacon(VH *v)
+{
+ UINT dest_ip;
+ ARPV4_HEADER arp;
+ static char beacon_str[] =
+ "SecureNAT Virtual TCP/IP Stack Beacon";
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Send an UDP
+ dest_ip = (v->HostIP & v->HostMask) | (~v->HostMask);
+ SendUdp(v, dest_ip, 7, v->HostIP, 7, beacon_str, sizeof(beacon_str));
+
+ // Build the ARP header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
+ Copy(arp.SrcAddress, v->MacAddress, 6);
+ arp.SrcIP = v->HostIP;
+ arp.TargetAddress[0] =
+ arp.TargetAddress[1] =
+ arp.TargetAddress[2] =
+ arp.TargetAddress[3] =
+ arp.TargetAddress[4] =
+ arp.TargetAddress[5] = 0xff;
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
+}
+
+// Send a TCP packet
+void SendTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss, void *data, UINT size)
+{
+ static UCHAR tcp_mss_option[] = {0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00};
+ IPV4_PSEUDO_HEADER *vh;
+ TCP_HEADER *tcp;
+ UINT header_size = TCP_HEADER_SIZE;
+ UINT total_size;
+ // Validate arguments
+ if (v == NULL || (size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ // Memory allocation
+ vh = Malloc(sizeof(IPV4_PSEUDO_HEADER) + TCP_HEADER_SIZE + size + 32);
+ tcp = (TCP_HEADER *)(((UCHAR *)vh) + sizeof(IPV4_PSEUDO_HEADER));
+
+ if (mss != 0)
+ {
+ USHORT *mss_size;
+ mss_size = (USHORT *)(&tcp_mss_option[2]);
+ *mss_size = Endian16((USHORT)mss);
+ header_size += sizeof(tcp_mss_option);
+ }
+
+ total_size = header_size + size;
+ if (total_size > 65536)
+ {
+ // Packet is too long
+ Free(vh);
+ return;
+ }
+
+ // Pseudo header generation
+ vh->SrcIP = src_ip;
+ vh->DstIP = dest_ip;
+ vh->Reserved = 0;
+ vh->Protocol = IP_PROTO_TCP;
+ vh->PacketLength = Endian16((USHORT)total_size);
+
+ // TCP header generation
+ tcp->SrcPort = Endian16((USHORT)src_port);
+ tcp->DstPort = Endian16((USHORT)dest_port);
+ tcp->SeqNumber = Endian32(seq);
+ tcp->AckNumber = Endian32(ack);
+ tcp->HeaderSizeAndReserved = 0;
+ TCP_SET_HEADER_SIZE(tcp, (UCHAR)(header_size / 4));
+ tcp->Flag = (UCHAR)flag;
+ tcp->WindowSize = Endian16((USHORT)window_size);
+ tcp->Checksum = 0;
+ tcp->UrgentPointer = 0;
+
+ // Copy the option values
+ if (mss != 0)
+ {
+ Copy(((UCHAR *)tcp) + TCP_HEADER_SIZE, tcp_mss_option, sizeof(tcp_mss_option));
+ }
+
+ // Data copy
+ Copy(((UCHAR *)tcp) + header_size, data, size);
+
+ // Checksum calculation
+ tcp->Checksum = IpChecksum(vh, total_size + 12);
+
+ // Submit as an IP packet
+ SendIp(v, dest_ip, src_ip, IP_PROTO_TCP, tcp, total_size);
+
+ // Release the memory
+ Free(vh);
+}
+
+// Polling process of TCP
+void PollingNatTcp(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ switch (n->TcpStatus)
+ {
+ case NAT_TCP_CONNECTING: // Socket connecting: nothing to do
+ break;
+
+ case NAT_TCP_CONNECTED: // The socket connected: process SYN + ACK, ACK
+ if ((n->LastSynAckSentTime > v->Now) || n->LastSynAckSentTime == 0 || ((n->LastSynAckSentTime + (UINT64)(NAT_TCP_SYNACK_SEND_TIMEOUT * (UINT64)(n->SynAckSentCount + 1)) <= v->Now)))
+ {
+ n->LastSynAckSentTime = v->Now;
+ // Send a SYN + ACK
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeqInit + n->SendSeq),
+ (UINT)(n->RecvSeqInit + n->RecvSeq),
+ TCP_SYN | TCP_ACK, n->TcpRecvWindowSize,
+ v->TcpMss, NULL, 0);
+ n->SynAckSentCount++;
+ }
+ break;
+
+ case NAT_TCP_SEND_RESET: // Reset the connection
+ // Send a RST
+ if (n->TcpFinished == false)
+ {
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeq + n->SendSeqInit),
+ (UINT)(n->SendSeq + n->SendSeqInit),
+ TCP_RST, 0,
+ 0, NULL, 0);
+ // Disconnect
+ n->TcpStatus = NAT_TCP_WAIT_DISCONNECT;
+ n->DisconnectNow = true;
+ }
+ else
+ {
+ // Send FINs for NAT_FIN_SEND_MAX_COUNT times
+ if (n->FinSentTime == 0 || (n->FinSentTime > v->Now) || (n->FinSentTime + NAT_FIN_SEND_INTERVAL * (n->FinSentCount + 1)) < v->Now)
+ {
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeq + n->SendSeqInit),
+ (UINT)(n->RecvSeq + n->RecvSeqInit),
+ TCP_ACK | TCP_FIN, 0,
+ 0, NULL, 0);
+ n->FinSentTime = v->Now;
+ n->FinSentCount++;
+ if (n->FinSentCount >= NAT_FIN_SEND_MAX_COUNT)
+ {
+ n->TcpFinished = false;
+ }
+ }
+ }
+ break;
+
+ case NAT_TCP_ESTABLISHED: // Connection established
+ {
+ UINT send_data_size;
+ UINT current_pointer;
+ UINT notice_window_size_value = 0;
+ UINT buf_free_bytes = 0;
+ // Determine the value of the window size to be notified
+ if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
+ {
+ buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
+ }
+ notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
+ if (n->LastSentKeepAliveTime == 0 ||
+ (n->LastSentKeepAliveTime + (UINT64)NAT_ACK_KEEPALIVE_SPAN) < v->Now ||
+ (n->LastSentKeepAliveTime > v->Now))
+ {
+ if (n->LastSentKeepAliveTime != 0)
+ {
+ // Send an ACK packet for Keep-Alive
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeqInit + n->SendSeq),
+ (UINT)(n->RecvSeqInit + n->RecvSeq) - 1,
+ TCP_ACK,
+ notice_window_size_value,
+ 0,
+ NULL,
+ 0);
+ }
+ n->LastSentKeepAliveTime = v->Now;
+ }
+ if (n->TcpLastSentTime == 0 ||
+ (n->TcpLastSentTime > v->Now) ||
+ ((n->TcpLastSentTime + (UINT64)n->TcpSendTimeoutSpan) < v->Now) ||
+ n->SendAckNext)
+ {
+ // If there is data to send, send the data
+ // Calculate the segment size to be transmitted
+ send_data_size = n->TcpSendWindowSize;
+ if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
+ {
+ // Apply the cwnd value
+ send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
+ }
+ if (send_data_size > n->SendFifo->size)
+ {
+ // Can not be sent over the data that is currently held
+ send_data_size = n->SendFifo->size;
+ }
+ if (send_data_size >= 1)
+ {
+ // Transmit the fragmented segments
+ current_pointer = 0;
+ while (send_data_size > 0)
+ {
+ UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
+ void *send_segment = (void *)(((UCHAR *)n->SendFifo->p) + n->SendFifo->pos + current_pointer);
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer),
+ (UINT)(n->RecvSeqInit + n->RecvSeq),
+ TCP_ACK | TCP_PSH,
+ notice_window_size_value,
+ 0,
+ send_segment,
+ send_segment_size);
+ current_pointer += send_segment_size;
+ send_data_size -= send_segment_size;
+ }
+ // Record the transmission time
+ n->TcpLastSentTime = v->Now;
+ // Record the stream size to be transmitted this time
+ n->SendMissionSize = current_pointer;
+ n->CurrentSendingMission = true;
+ // RTT measurement
+ if (n->CalcRTTStartTime == 0)
+ {
+ n->CalcRTTStartTime = v->Now;
+ n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
+ }
+ if (n->RetransmissionUsedFlag == false)
+ {
+ n->RetransmissionUsedFlag = true;
+ }
+ else
+ {
+ // Congestion is detected
+ if (n->TcpSendCWnd > 2)
+ {
+ n->TcpSendCWnd--;
+ }
+ }
+ }
+ else if (n->SendAckNext)
+ {
+ // Send only an ACK
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeqInit + n->SendSeq),
+ (UINT)(n->RecvSeqInit + n->RecvSeq),
+ TCP_ACK,
+ notice_window_size_value,
+ 0,
+ NULL,
+ 0);
+ }
+ n->SendAckNext = false;
+ }
+ if (n->TcpFinished)
+ {
+ // Disconnect if all data transmission has completed
+ if (n->SendFifo->size == 0)
+ {
+ n->TcpStatus = NAT_TCP_SEND_RESET;
+ }
+ }
+ }
+ break;
+ }
+}
+
+// Reception of TCP packets addressed to the Internet
+void TcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *tcp, void *data, UINT size, UINT max_l3_size)
+{
+ NAT_ENTRY *n, t;
+ UINT seq, ack;
+ UINT64 seq64 = 0, ack64 = 0;
+ // Validate arguments
+ if (v == NULL || tcp == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (NnIsActive(v))
+ {
+ NnTcpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, tcp, data, size, max_l3_size);
+ return;
+ }
+
+ seq = Endian32(tcp->SeqNumber);
+ ack = Endian32(tcp->AckNumber);
+
+ if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
+ {
+ // Disable User-mode NAT
+ SendTcp(v, dest_ip, dest_port, src_ip, src_port,
+ 0, seq + 1, TCP_RST | TCP_ACK, 0, 0, NULL, 0);
+ return;
+ }
+
+ // Search for a session for this packet from the NAT table
+ SetNat(&t, NAT_TCP, src_ip, src_port, dest_ip, dest_port, 0, 0);
+ n = SearchNat(v, &t);
+
+ if (n == NULL)
+ {
+ // There is no existing session
+ // Allow through only SYN packet
+ if ((tcp->Flag & TCP_SYN) && ((tcp->Flag & TCP_ACK) == false))
+ {
+ TCP_OPTION o;
+ // Create a new session
+ n = CreateNatTcp(v, src_ip, src_port, dest_ip, dest_port);
+ if (n == NULL)
+ {
+ // Return the RST if it was not possible to create
+ SendTcp(v, dest_ip, dest_port, src_ip, src_port,
+ 0, seq + 1, TCP_RST | TCP_ACK, 0, 0, NULL, 0);
+ return;
+ }
+
+ // Get the options
+ ParseTcpOption(&o, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
+ if (o.MaxSegmentSize == 0)
+ {
+ o.MaxSegmentSize = v->TcpMss;
+ }
+
+ Debug("TCP SYN: MSS=%u, WS=%u\n", o.MaxSegmentSize, o.WindowScaling);
+
+ // Initial sequence number
+ n->RecvSeqInit = (UINT64)Endian32(tcp->SeqNumber);
+ n->RecvSeq = 1;
+
+ n->TcpSendMaxSegmentSize = o.MaxSegmentSize;
+ n->TcpRecvWindowSize = NAT_TCP_RECV_WINDOW_SIZE;
+ n->TcpSendWindowSize = (UINT)Endian16(tcp->WindowSize);
+ if (o.WindowScaling != 0)
+ {
+ if (o.WindowScaling > 14)
+ {
+ o.WindowScaling = 14;
+ }
+ n->TcpSendWindowSize = (n->TcpSendWindowSize << o.WindowScaling);
+ }
+ }
+ }
+
+ if (n == NULL)
+ {
+ // Return a RST since a packet which is not registered in the NAT entry arrived
+ SendTcp(v, dest_ip, dest_port, src_ip, src_port,
+ ack, ack, TCP_RST, 0, 0, NULL, 0);
+ return;
+ }
+
+ n->TcpLastRecvAckTime = v->Now;
+
+ switch (n->TcpStatus)
+ {
+ case NAT_TCP_SEND_RESET: // Disconnect the connection by sending a RST
+ break;
+
+ case NAT_TCP_CONNECTED: // Socket connection completion: SYN + ACK, ACK processing
+ if ((tcp->Flag & TCP_ACK) && ((tcp->Flag & TCP_SYN) == false))
+ {
+ if (seq == (UINT)(n->RecvSeqInit + n->RecvSeq) &&
+ ack == (UINT)(n->SendSeqInit + n->SendSeq + 1))
+ {
+ // Handshake complete since the ACK packet came back
+ n->SendSeq++; // SYN packet consumes the seq by 1
+ Debug("TCP Connection Established.\n");
+ n->TcpStatus = NAT_TCP_ESTABLISHED;
+ // Initialize the congestion window size
+ n->TcpSendCWnd = 1;
+ n->LastCommTime = v->Now;
+ }
+ else
+ {
+ goto TCP_RESET;
+ }
+ }
+ else if (tcp->Flag & TCP_RST)
+ {
+TCP_RESET:
+ // Receive a RST
+ Debug("TCP Connection Reseted.\n");
+ n->TcpStatus = NAT_TCP_SEND_RESET;
+ }
+ break;
+
+ case NAT_TCP_ESTABLISHED: // Connection established
+ if (tcp->Flag & TCP_FIN)
+ {
+ // Complete the connection
+ n->TcpFinished = true;
+ }
+ if (tcp->Flag & TCP_RST)
+ {
+ // Receive a RST
+ goto TCP_RESET;
+ }
+ else if (tcp->Flag & TCP_ACK)
+ {
+ TCP_OPTION opt;
+ n->LastCommTime = v->Now;
+ // Get the options, such as window size
+ n->TcpSendWindowSize = Endian16(tcp->WindowSize);
+ ParseTcpOption(&opt, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
+ if (opt.WindowScaling != 0)
+ {
+ if (opt.WindowScaling > 14)
+ {
+ opt.WindowScaling = 14;
+ }
+ n->TcpSendWindowSize = (n->TcpSendWindowSize << opt.WindowScaling);
+ }
+ // First, process the received ACK
+ // Store the end position of the stream that has received the acknowledgment to ack64
+ ack64 = n->SendSeq + (UINT64)ack - (n->SendSeqInit + n->SendSeq) % X32;
+ if ((n->SendSeqInit + n->SendSeq) % X32 > ack)
+ {
+ if (((n->SendSeqInit + n->SendSeq) % X32 - ack) >= 0x80000000)
+ {
+ ack64 = n->SendSeq + (UINT64)ack + X32 - (n->SendSeqInit + n->SendSeq) % X32;
+ }
+ }
+ if (ack64 > n->SendSeq)
+ {
+ // Reception of 1 byte or more seems to have been completed by the client
+ UINT slide_offset = (UINT)(ack64 - n->SendSeq); // Sliding size of the window
+ if (slide_offset == 0 || slide_offset > n->TcpSendWindowSize || slide_offset > n->SendFifo->size)
+ {
+ // Ignore because the offset value of acknowledgment is
+ // larger than the size that should have been sent so far
+ }
+ else
+ {
+ // RTT measurement
+ if (n->CalcRTTStartTime != 0)
+ {
+ if (n->CalcRTTStartValue < ack64)
+ {
+ UINT time_span;
+ if (v->Now > n->CalcRTTStartTime)
+ {
+ time_span = (UINT)(v->Now - n->CalcRTTStartTime);
+ }
+ else
+ {
+ time_span = 100;
+ }
+ n->CalcRTTStartTime = 0;
+
+ // Smoothing
+ n->CurrentRTT =
+ (UINT)
+ (
+ ((UINT64)n->CurrentRTT * (UINT64)9 +
+ (UINT64)time_span * (UINT64)1) / (UINT64)10
+ );
+ n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
+ }
+ }
+ // Reduce the transmission size
+ n->SendMissionSize -= slide_offset;
+ if (n->SendMissionSize == 0)
+ {
+ // Try to increase the transmission segment size because
+ // all segments to be sent this time have been sent
+ if (n->TcpSendCWnd < 65536)
+ {
+ n->TcpSendCWnd++;
+ }
+ n->CurrentSendingMission = false;
+ n->TcpLastSentTime = 0;
+ n->RetransmissionUsedFlag = false;
+ }
+ // Slide the buffer
+ n->SendSeq += slide_offset;
+ ReadFifo(n->SendFifo, NULL, slide_offset);
+ // Send further by the size of confirmed transmission completion by the ACK this time
+ if (n->SendMissionSize != 0 && false)
+ {
+ UINT notice_window_size_value = 0;
+ UINT send_data_size;
+ UINT buf_free_bytes;
+ UINT send_offset = n->SendMissionSize;
+ // Determine the value of the window size to be notified
+ if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
+ {
+ buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
+ }
+ notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
+ // Calculate the segment size to be transmitted
+ send_data_size = n->TcpSendWindowSize;
+ if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
+ {
+ // Apply the cwnd value
+ send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
+ }
+ if (n->SendFifo->size > send_offset)
+ {
+ send_data_size = MIN(send_data_size, n->SendFifo->size - send_offset);
+ send_data_size = MIN(send_data_size, slide_offset);
+ }
+ else
+ {
+ send_data_size = 0;
+ }
+ if (send_data_size >= 1)
+ {
+ // Transmit the fragmented segments
+ UINT current_pointer = 0;
+ while (send_data_size > 0)
+ {
+ UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
+ void *send_segment = (void *)((
+ (UCHAR *)n->SendFifo->p) + n->SendFifo->pos +
+ current_pointer + send_offset);
+
+ SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
+ (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer
+ + (UINT)send_offset),
+ (UINT)(n->RecvSeqInit + n->RecvSeq),
+ TCP_ACK | TCP_PSH,
+ notice_window_size_value,
+ 0,
+ send_segment,
+ send_segment_size);
+ current_pointer += send_segment_size;
+ send_data_size -= send_segment_size;
+ }
+ n->SendMissionSize += current_pointer;
+ n->CurrentSendingMission = true;
+ n->TcpLastSentTime = v->Now;
+ // RTT measurement
+ if (n->CalcRTTStartTime == 0)
+ {
+ n->CalcRTTStartTime = v->Now;
+ n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
+ }
+ }
+ }
+ // Event occurs
+ SetSockEvent(v->SockEvent);
+ }
+ }
+ // Next, receive the data
+ seq64 = n->RecvSeq + (UINT64)seq - (n->RecvSeqInit + n->RecvSeq) % X32;
+ if ((n->RecvSeqInit + n->RecvSeq) % X32 > seq)
+ {
+ if (((n->RecvSeqInit + n->RecvSeq) % X32 - ack) >= 0x80000000)
+ {
+ seq64 = n->RecvSeq + (UINT64)seq + X32 - (n->RecvSeqInit + n->RecvSeq) % X32;
+ }
+ }
+ // Position of the starting point of the data from the client is in the seq64 at this time
+ if (seq64 >= n->RecvSeq && (seq64 + size) <= (n->RecvSeq + n->TcpRecvWindowSize))
+ {
+ if (size >= 1)
+ {
+ // One or more bytes of data has been received within the receive window
+ UINT offset = (UINT)(seq64 - n->RecvSeq);
+ UINT i;
+ IP_PART *me;
+ if (n->TcpRecvWindow == NULL)
+ {
+ n->TcpRecvWindow = NewFifo();
+ }
+ if (n->TcpRecvList == NULL)
+ {
+ n->TcpRecvList = NewListFast(NULL);
+ }
+ // Add to the list by overwriting arriving packets to the buffer
+ if (FifoSize(n->TcpRecvWindow) < (offset + size))
+ {
+ // Buffer size expansion
+ WriteFifo(n->TcpRecvWindow, NULL, offset + size - FifoSize(n->TcpRecvWindow));
+ }
+ Copy(((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos +
+ offset, data, size);
+ me = ZeroMalloc(sizeof(IP_PART));
+ me->Offset = offset;
+ me->Size = size;
+ for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
+ {
+ IP_PART *p = LIST_DATA(n->TcpRecvList, i);
+ // If there are overlapped region, remove these
+ if (p->Size != 0)
+ {
+ if (me->Offset <= p->Offset && (me->Offset + me->Size) >= (p->Offset + p->Size))
+ {
+ // This packet completely overwrite the existing packet
+ p->Size = 0;
+ }
+ else if (me->Offset >= p->Offset && (me->Offset + me->Size) <= (p->Offset + p->Size))
+ {
+ // Existing packet completely override this packet
+ me->Size = 0;
+ }
+ else if (me->Offset > p->Offset && me->Offset < (p->Offset + p->Size) &&
+ (me->Offset + me->Size) > (p->Offset + p->Size))
+ {
+ // Partially overlapped
+ p->Size -= p->Offset + p->Size - me->Offset;
+ }
+ else if (me->Offset < p->Offset && (me->Offset + size) > p->Offset && (me->Offset + size) < (p->Offset + p->Size))
+ {
+ // Partially overlapped
+ me->Size -= me->Offset + me->Size - p->Offset;
+ }
+ }
+ }
+ if (me->Size == 0)
+ {
+ Free(me);
+ }
+ else
+ {
+ Add(n->TcpRecvList, me);
+ }
+KILL_NULL_FIRST:
+ // Remove all blank items from reception list
+ for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
+ {
+ IP_PART *p = LIST_DATA(n->TcpRecvList, i);
+ if (p->Size == 0)
+ {
+ Delete(n->TcpRecvList, p);
+ Free(p);
+ goto KILL_NULL_FIRST;
+ }
+ }
+SCAN_FIRST:
+ // Extract if there is something starting at offset 0 in the received list
+ for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
+ {
+ IP_PART *p = LIST_DATA(n->TcpRecvList, i);
+ UINT sz;
+ if (p->Offset == 0)
+ {
+ // Since a data block starts with 0 is found,
+ // slide it left by that amount and write the buffer
+ // for extracting data to the FIFO
+ sz = p->Size;
+ WriteFifo(n->RecvFifo, ((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos, sz);
+ // Release from the list
+ Delete(n->TcpRecvList, p);
+ Free(p);
+ ReadFifo(n->TcpRecvWindow, NULL, sz);
+ // Slide all the items to the left
+ for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
+ {
+ p = LIST_DATA(n->TcpRecvList, i);
+ p->Offset -= sz;
+ }
+ // Update the parameters of the TCB
+ n->RecvSeq += (UINT64)sz;
+ SetSockEvent(v->SockEvent);
+ n->SendAckNext = true;
+ // Re-scan from the beginning
+ goto SCAN_FIRST;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ SetSockEvent(v->SockEvent);
+}
+
+// Parse the TCP options
+void ParseTcpOption(TCP_OPTION *o, void *data, UINT size)
+{
+ UCHAR *buf = (UCHAR *)data;
+ UINT i;
+ UINT value_size = 0;
+ UINT value_id = 0;
+ UCHAR value[128];
+ // Validate arguments
+ if (o == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Zero(o, sizeof(TCP_OPTION));
+
+ for (i = 0;i < size;i++)
+ {
+ if (buf[i] == 0)
+ {
+ return;
+ }
+ if (buf[i] != 1)
+ {
+ value_id = buf[i];
+ i++;
+ if (i >= size)
+ {
+ return;
+ }
+ value_size = buf[i];
+ if (value_size <= 1 || value_size > sizeof(value))
+ {
+ return;
+ }
+ i++;
+ if (i >= size)
+ {
+ return;
+ }
+ value_size -= 2;
+ Copy(value, &buf[i], value_size);
+ i += value_size;
+ if (i >= size)
+ {
+ return;
+ }
+ switch (value_id)
+ {
+ case 2: // MSS
+ if (value_size == 2)
+ {
+ USHORT *mss = (USHORT *)value;
+ o->MaxSegmentSize = Endian16(*mss);
+ }
+ break;
+
+ case 3: // WSS
+ if (value_size == 1)
+ {
+ UCHAR *wss = (UCHAR *)value;
+ o->WindowScaling = Endian16(*wss);
+ }
+ break;
+
+ }
+ }
+ }
+
+}
+
+// Create a new NAT TCP session
+NAT_ENTRY *CreateNatTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port)
+{
+ NAT_ENTRY *n;
+ HUB_OPTION *o;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ return NULL;
+ }
+
+ o = NatGetHubOption(v);
+
+ // Fail immediately if the connection with SYN_SENT are too many
+ if (o != NULL && o->SecureNAT_MaxTcpSynSentPerIp != 0)
+ {
+ if (GetNumNatEntriesPerIp(v, src_ip, NAT_TCP, true) >= o->SecureNAT_MaxTcpSynSentPerIp)
+ {
+ return NULL;
+ }
+ }
+
+ // If the connections other than SYN_SENT are too many, delete old ones
+ if (o != NULL && o->SecureNAT_MaxTcpSessionsPerIp != 0)
+ {
+ if (GetNumNatEntriesPerIp(v, src_ip, NAT_TCP, false) >= o->SecureNAT_MaxTcpSessionsPerIp)
+ {
+ NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_TCP);
+
+ if (oldest != NULL)
+ {
+ DisconnectNatEntryNow(v, oldest);
+ }
+ }
+ }
+
+ // Create a NAT entry
+ n = ZeroMalloc(sizeof(NAT_ENTRY));
+ n->Id = Inc(v->Counter);
+ n->v = v;
+ n->lock = NewLock();
+ n->Protocol = NAT_TCP;
+ n->SrcIp = src_ip;
+ n->SrcPort = src_port;
+ n->DestIp = dest_ip;
+ n->DestPort = dest_port;
+ n->CreatedTime = n->LastCommTime = v->Now;
+ n->TcpLastRecvAckTime = v->Now;
+ n->Sock = NULL;
+ n->DisconnectNow = false;
+ n->TcpSendMaxSegmentSize = n->TcpRecvMaxSegmentSize = v->TcpMss;
+
+ n->SendFifo = NewFifo();
+ n->RecvFifo = NewFifo();
+
+ n->TcpStatus = NAT_TCP_CONNECTING;
+
+ n->SendSeqInit = Rand32();
+ n->CurrentRTT = NAT_INITIAL_RTT_VALUE;
+ n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
+
+ // Add to the NAT table
+ Add(v->NatTable, n);
+
+
+#if 1
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+ Debug("NAT_ENTRY: CreateNatTcp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
+
+ NLog(v, "LH_NAT_TCP_CREATED", n->Id, s1, src_port, s2, dest_port);
+ }
+#endif
+
+ return n;
+}
+
+// Received TCP packets from the virtual network
+void VirtualTcpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size)
+{
+ TCP_HEADER *tcp;
+ UINT src_port, dest_port;
+ UINT header_size, buf_size;
+ void *buf;
+ IP ip1, ip2;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Get the header
+ if (size < TCP_HEADER_SIZE)
+ {
+ // Size is too small
+ return;
+ }
+ tcp = (TCP_HEADER *)data;
+ src_port = Endian16(tcp->SrcPort);
+ dest_port = Endian16(tcp->DstPort);
+ if (src_port == 0 || dest_port == 0)
+ {
+ // Port number is invalid
+ return;
+ }
+ if (src_ip == dest_ip || src_ip == 0 || src_ip == 0xffffffff || dest_ip == 0 || dest_ip == 0xffffffff)
+ {
+ // IP address is invalid
+ return;
+ }
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ if (ip1.addr[0] == 127 || ip2.addr[0] == 127)
+ {
+ // Loopback IP address can not be specified
+ return;
+ }
+ if (IsInNetwork(dest_ip, v->HostIP, v->HostMask))
+ {
+ // Ignore the packets toward the network of the virtual LAN side
+ return;
+ }
+ // Get the header size
+ header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ if (size < header_size)
+ {
+ // Header size is invalid
+ return;
+ }
+ // Get the address and size of the buffer
+ buf_size = size - header_size;
+ buf = (void *)(((UCHAR *)data) + header_size);
+
+ TcpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, tcp, buf, buf_size, max_l3_size);
+}
+
+// NAT ICMP polling
+void PollingNatIcmp(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ // Process if there are any packets in the receive queue
+ if (n->UdpRecvQueue->num_item != 0)
+ {
+ BLOCK *block;
+
+ // Send all ICMP packets to the virtual network
+ while (block = GetNext(n->UdpRecvQueue))
+ {
+ // Rewrite the destination IP address of the returned packet to the IP address of the client
+ UCHAR *data;
+ UINT size;
+
+ data = (UCHAR *)block->Buf;
+ size = block->Size;
+
+ if (size >= sizeof(IPV4_HEADER))
+ {
+ IPV4_HEADER *ipv4 = (IPV4_HEADER *)data;
+ UINT ipv4_header_size = GetIpHeaderSize((UCHAR *)ipv4, size);
+
+ if (ipv4_header_size >= sizeof(IPV4_HEADER) && (Endian16(ipv4->TotalLength) >= ipv4_header_size))
+ {
+ UCHAR *ipv4_payload = data + ipv4_header_size;
+ UINT ipv4_payload_size = Endian16(ipv4->TotalLength) - ipv4_header_size;
+
+ if (ipv4_payload_size >= sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO))
+ {
+ ICMP_HEADER *icmp = (ICMP_HEADER *)(data + ipv4_header_size);
+ UINT icmp_size = ipv4_payload_size;
+
+ if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
+ {
+ // Rewrite the Src IP of the IPv4 header of the ICMP response packet
+ if (icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + sizeof(IPV4_HEADER)))
+ {
+ IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(data + ipv4_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ UINT orig_ipv4_size = icmp_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+
+ UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
+
+ if (orig_ipv4_header_size >= sizeof(IPV4_HEADER))
+ {
+ orig_ipv4->SrcIP = n->SrcIp;
+ orig_ipv4->Checksum = 0;
+ orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
+ }
+ }
+ }
+
+ // Recalculate the checksum of ICMP
+ icmp->Checksum = IpChecksum(icmp, icmp_size);
+
+ SendIpEx(v, n->SrcIp, ipv4->SrcIP, ipv4->Protocol, ipv4_payload, ipv4_payload_size,
+ MAX(ipv4->TimeToLive - 1, 1));
+ }
+ }
+ }
+
+ FreeBlock(block);
+ }
+
+ if (v->IcmpRawSocketOk == false)
+ {
+ // Release the NAT entry as soon as the results is received in the case of using ICMP API
+ n->DisconnectNow = true;
+ }
+ }
+}
+
+// NAT UDP polling
+void PoolingNatUdp(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ // Process if there are any packets in the receive queue
+ if (n->UdpRecvQueue->num_item != 0)
+ {
+ BLOCK *block;
+
+ // Send all UDP packets to the virtual network
+ while (block = GetNext(n->UdpRecvQueue))
+ {
+ UINT src_ip = n->DestIp;
+
+ if (src_ip == 0xFFFFFFFF)
+ {
+ src_ip = v->HostIP;
+ }
+
+ if (block->Param1 != 0)
+ {
+ src_ip = block->Param1;
+ }
+
+ SendUdp(v, n->SrcIp, n->SrcPort, src_ip, n->DestPort,
+ block->Buf, block->Size);
+
+ FreeBlock(block);
+ }
+ }
+}
+
+// NAT polling
+void PoolingNat(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (NnIsActive(v))
+ {
+ // Poll whether the packet comes from native NAT
+ NnPoll(v->NativeNat);
+ }
+
+ // Process by scanning the all NAT entries
+ for (i = 0;i < LIST_NUM(v->NatTable);i++)
+ {
+ NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
+
+ switch (n->Protocol)
+ {
+ case NAT_TCP:
+ PollingNatTcp(v, n);
+ break;
+
+ case NAT_UDP:
+ PoolingNatUdp(v, n);
+ break;
+
+ case NAT_ICMP:
+ PollingNatIcmp(v, n);
+ break;
+
+ case NAT_DNS:
+ PollingNatDns(v, n);
+ break;
+ }
+ }
+}
+
+// Comparison function of the NAT table entry
+int CompareNat(void *p1, void *p2)
+{
+ NAT_ENTRY *n1, *n2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ n1 = *(NAT_ENTRY **)p1;
+ n2 = *(NAT_ENTRY **)p2;
+ if (n1 == n2)
+ {
+ return 0;
+ }
+
+ if (n1->SrcIp > n2->SrcIp) return 1;
+ else if (n1->SrcIp < n2->SrcIp) return -1;
+ else if (n1->DestIp > n2->DestIp) return 1;
+ else if (n1->DestIp < n2->DestIp) return -1;
+ else if (n1->SrcPort > n2->SrcPort) return 1;
+ else if (n1->SrcPort < n2->SrcPort) return -1;
+ else if (n1->DestPort > n2->DestPort) return 1;
+ else if (n1->DestPort < n2->DestPort) return -1;
+ else if (n1->Protocol > n2->Protocol) return 1;
+ else if (n1->Protocol < n2->Protocol) return -1;
+ else return 0;
+}
+
+// Configure the NAT structure
+void SetNat(NAT_ENTRY *n, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT public_ip, UINT public_port)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ n->Protocol = protocol;
+ n->SrcIp = src_ip;
+ n->SrcPort = src_port;
+ n->DestIp = dest_ip;
+ n->DestPort = dest_port;
+ n->PublicIp = public_ip;
+ n->PublicPort = public_port;
+}
+
+// Initialize the NAT
+void InitNat(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Create a NAT table
+ v->NatTable = NewList(CompareNat);
+
+ // Create a socket event
+ v->SockEvent = NewSockEvent();
+
+ // Create the NAT thread
+ v->HaltNat = false;
+ v->NatThread = NewThread(NatThread, (void *)v);
+ WaitThreadInit(v->NatThread);
+
+ if (IsEthSupported())
+ {
+ // Start a native NAT if access to the layer 2 Ethernet is supported
+ v->NativeNat = NewNativeNat(v);
+ }
+}
+
+// Release the NAT
+void FreeNat(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Stop the native NAT
+ if (v->NativeNat != NULL)
+ {
+ FreeNativeNat(v->NativeNat);
+ v->NativeNat = NULL;
+ }
+
+ // Stop the NAT thread
+ v->HaltNat = true;
+ SetSockEvent(v->SockEvent);
+ WaitThread(v->NatThread, INFINITE);
+ ReleaseThread(v->NatThread);
+ v->NatThread = NULL;
+ ReleaseSockEvent(v->SockEvent);
+ v->SockEvent = NULL;
+
+ // Release the NAT table
+ ReleaseList(v->NatTable);
+}
+
+// Search the NAT table
+NAT_ENTRY *SearchNat(VH *v, NAT_ENTRY *target)
+{
+ NAT_ENTRY *n;
+ // Validate arguments
+ if (v == NULL || target == NULL)
+ {
+ return NULL;
+ }
+
+ // Binary search
+ n = (NAT_ENTRY *)Search(v->NatTable, target);
+
+ return n;
+}
+
+// Delete the UDP NAT entry
+void DeleteNatUdp(VH *v, NAT_ENTRY *n)
+{
+ BLOCK *block;
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ NLog(v, "LH_NAT_UDP_DELETED", n->Id);
+
+ // Release all queues
+ while (block = GetNext(n->UdpRecvQueue))
+ {
+ FreeBlock(block);
+ }
+ ReleaseQueue(n->UdpRecvQueue);
+ while (block = GetNext(n->UdpSendQueue))
+ {
+ FreeBlock(block);
+ }
+ ReleaseQueue(n->UdpSendQueue);
+
+ // Release the socket
+ if (n->Sock != NULL)
+ {
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+ n->Sock = NULL;
+ }
+
+ DeleteLock(n->lock);
+
+ // Remove from the table
+ Delete(v->NatTable, n);
+
+ // Release the memory
+ Free(n);
+
+ Debug("NAT: DeleteNatUdp\n");
+
+}
+
+// Delete the ICMP NAT entry
+void DeleteNatIcmp(VH *v, NAT_ENTRY *n)
+{
+ BLOCK *block;
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ //NLog(v, "LH_NAT_ICMP_DELETED", n->Id);
+
+ // Release all queues
+ while (block = GetNext(n->UdpRecvQueue))
+ {
+ FreeBlock(block);
+ }
+ ReleaseQueue(n->UdpRecvQueue);
+ while (block = GetNext(n->UdpSendQueue))
+ {
+ FreeBlock(block);
+ }
+ ReleaseQueue(n->UdpSendQueue);
+
+ if (n->IcmpQueryBlock != NULL)
+ {
+ FreeBlock(n->IcmpQueryBlock);
+ }
+
+ if (n->IcmpResponseBlock != NULL)
+ {
+ FreeBlock(n->IcmpResponseBlock);
+ }
+
+ if (n->IcmpOriginalCopy != NULL)
+ {
+ Free(n->IcmpOriginalCopy);
+ }
+
+ // Release the socket
+ if (n->Sock != NULL)
+ {
+ Disconnect(n->Sock);
+ ReleaseSock(n->Sock);
+ n->Sock = NULL;
+ }
+
+ DeleteLock(n->lock);
+
+ // Remove from the table
+ Delete(v->NatTable, n);
+
+ // Release the memory
+ Free(n);
+
+ Debug("NAT: DeleteNatIcmp\n");
+
+}
+
+// Create a NAT ICMP entry
+NAT_ENTRY *CreateNatIcmp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UCHAR *original_copy, UINT original_copy_size)
+{
+ NAT_ENTRY *n;
+ HUB_OPTION *o;
+ // Validate arguments
+ if (v == NULL || original_copy == NULL || original_copy_size == 0)
+ {
+ return NULL;
+ }
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ return NULL;
+ }
+
+ o = NatGetHubOption(v);
+ if (o != NULL && o->SecureNAT_MaxIcmpSessionsPerIp != 0)
+ {
+ if (GetNumNatEntriesPerIp(v, src_ip, NAT_ICMP, false) >= o->SecureNAT_MaxIcmpSessionsPerIp)
+ {
+ NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_ICMP);
+
+ if (oldest != NULL)
+ {
+ DisconnectNatEntryNow(v, oldest);
+ }
+ }
+ }
+
+ n = ZeroMalloc(sizeof(NAT_ENTRY));
+ n->Id = Inc(v->Counter);
+ n->v = v;
+ n->lock = NewLock();
+ n->Protocol = NAT_ICMP;
+ n->SrcIp = src_ip;
+ n->SrcPort = src_port;
+ n->DestIp = dest_ip;
+ n->DestPort = dest_port;
+
+ n->CreatedTime = n->LastCommTime = v->Now;
+
+ n->UdpSendQueue = NewQueue();
+ n->UdpRecvQueue = NewQueue();
+
+ n->UdpSocketCreated = false;
+
+ n->IcmpOriginalCopy = Clone(original_copy, original_copy_size);
+ n->IcmpOriginalCopySize = original_copy_size;
+
+ SetSockEvent(v->SockEvent);
+
+#if 1
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+ Debug("NAT_ENTRY: CreateNatIcmp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
+
+ //NLog(v, "LH_NAT_ICMP_CREATED", n->Id, s1, s2, src_port);
+ }
+#endif
+
+ Add(v->NatTable, n);
+
+ return n;
+}
+
+// Create a NAT UDP entry
+NAT_ENTRY *CreateNatUdp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT dns_proxy_ip)
+{
+ NAT_ENTRY *n;
+ HUB_OPTION *o;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ return NULL;
+ }
+
+ o = NatGetHubOption(v);
+ if (o != NULL && o->SecureNAT_MaxTcpSessionsPerIp != 0)
+ {
+ if (GetNumNatEntriesPerIp(v, src_ip, NAT_UDP, false) >= o->SecureNAT_MaxUdpSessionsPerIp)
+ {
+ NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_UDP);
+
+ if (oldest != NULL)
+ {
+ DisconnectNatEntryNow(v, oldest);
+ }
+ }
+ }
+
+ n = ZeroMalloc(sizeof(NAT_ENTRY));
+ n->Id = Inc(v->Counter);
+ n->v = v;
+ n->lock = NewLock();
+ n->Protocol = NAT_UDP;
+ n->SrcIp = src_ip;
+ n->SrcPort = src_port;
+ n->DestIp = dest_ip;
+ n->DestPort = dest_port;
+
+ if (dns_proxy_ip != 0)
+ {
+ n->ProxyDns = true;
+ n->DestIpProxy = dns_proxy_ip;
+ }
+
+ n->CreatedTime = n->LastCommTime = v->Now;
+
+ n->UdpSendQueue = NewQueue();
+ n->UdpRecvQueue = NewQueue();
+
+ n->UdpSocketCreated = false;
+
+ SetSockEvent(v->SockEvent);
+
+#if 1
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+ Debug("NAT_ENTRY: CreateNatUdp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
+
+ NLog(v, "LH_NAT_UDP_CREATED", n->Id, s1, src_port, s2, dest_port);
+ }
+#endif
+
+ Add(v->NatTable, n);
+
+ return n;
+}
+
+// Ignore for NetBIOS name registration packet
+bool IsNetbiosRegistrationPacket(UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ if (size >= 4)
+ {
+ USHORT us = *((USHORT *)(buf + 2));
+
+ us = Endian16(us);
+
+ if (((us & 0x7800) >> 11) == 5)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Generate the encoded NetBIOS name
+void EncodeNetBiosName(UCHAR *dst, char *src)
+{
+ char tmp[17];
+ UINT i;
+ UINT copy_len;
+ UINT wp;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < 16;i++)
+ {
+ tmp[i] = ' ';
+ }
+ tmp[16] = 0;
+
+ copy_len = StrLen(src);
+ if (copy_len > 16)
+ {
+ copy_len = 16;
+ }
+
+ Copy(tmp, src, StrLen(src));
+
+ wp = 0;
+
+ tmp[15] = 0;
+
+ for (i = 0;i < 16;i++)
+ {
+ char c = tmp[i];
+ char *s = CharToNetBiosStr(c);
+
+ dst[wp++] = s[0];
+ dst[wp++] = s[1];
+ }
+}
+
+// Convert the string to NetBIOS characters
+char *CharToNetBiosStr(char c)
+{
+ c = ToUpper(c);
+
+ switch (c)
+ {
+ case '\0': return "AA";
+ case 'A': return "EB";
+ case 'B': return "EC";
+ case 'C': return "ED";
+ case 'D': return "EE";
+ case 'E': return "EF";
+ case 'F': return "EG";
+ case 'G': return "EH";
+ case 'H': return "EI";
+ case 'I': return "EJ";
+ case 'J': return "EK";
+ case 'K': return "EL";
+ case 'L': return "EM";
+ case 'M': return "EN";
+ case 'N': return "EO";
+ case 'O': return "EP";
+ case 'P': return "FA";
+ case 'Q': return "FB";
+ case 'R': return "FC";
+ case 'S': return "FD";
+ case 'T': return "FE";
+ case 'U': return "FF";
+ case 'V': return "FG";
+ case 'W': return "FH";
+ case 'X': return "FI";
+ case 'Y': return "FJ";
+ case 'Z': return "FK";
+ case '0': return "DA";
+ case '1': return "DB";
+ case '2': return "DC";
+ case '3': return "DD";
+ case '4': return "DE";
+ case '5': return "DF";
+ case '6': return "DG";
+ case '7': return "DH";
+ case '8': return "DI";
+ case '9': return "DJ";
+ case ' ': return "CA";
+ case '!': return "CB";
+ case '\"': return "CC";
+ case '#': return "CD";
+ case '$': return "CE";
+ case '%': return "CF";
+ case '&': return "CG";
+ case '\'': return "CH";
+ case '(': return "CI";
+ case ')': return "CJ";
+ case '*': return "CK";
+ case '+': return "CL";
+ case ',': return "CM";
+ case '-': return "CN";
+ case '.': return "CO";
+ case '=': return "DN";
+ case ':': return "DK";
+ case ';': return "DL";
+ case '@': return "EA";
+ case '^': return "FO";
+ case '_': return "FP";
+ case '{': return "HL";
+ case '}': return "HN";
+ case '~': return "HO";
+ }
+
+ return "CA";
+}
+
+// Process if a NetBIOS name resolution packet for the my host name
+bool ProcessNetBiosNameQueryPacketForMyself(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ BUF *rb;
+ USHORT tran_id;
+ USHORT flags;
+ USHORT num_query;
+ USHORT zero1, zero2, zero3;
+ UCHAR name_size;
+ UCHAR encoded_name[32];
+ UCHAR node_type;
+ USHORT type, classid;
+ UCHAR my_pc_encoded_name[32];
+ bool ret = false;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ rb = NewBufFromMemory(data, size);
+
+ ReadBuf(rb, &tran_id, sizeof(USHORT));
+
+ ReadBuf(rb, &flags, sizeof(USHORT));
+ flags = Endian16(flags);
+
+ ReadBuf(rb, &num_query, sizeof(USHORT));
+ num_query = Endian16(num_query);
+
+ ReadBuf(rb, &zero1, sizeof(USHORT));
+ ReadBuf(rb, &zero2, sizeof(USHORT));
+ ReadBuf(rb, &zero3, sizeof(USHORT));
+
+ ReadBuf(rb, &name_size, 1);
+
+ ReadBuf(rb, encoded_name, 32);
+
+ ReadBuf(rb, &node_type, 1);
+
+ ReadBuf(rb, &type, sizeof(USHORT));
+ type = Endian16(type);
+
+ if (ReadBuf(rb, &classid, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ classid = Endian16(classid);
+
+ if (((flags >> 11) & 0x0F) == 0 &&
+ num_query == 1 && name_size == 0x20 &&
+ zero1 == 0 && zero2 == 0 && zero3 == 0 && node_type == 0 && type == 0x0020 && classid == 0x0001)
+ {
+ char my_pcname[MAX_SIZE];
+
+ // Get the encoded name of this PC
+ Zero(my_pcname, sizeof(my_pcname));
+ GetMachineHostName(my_pcname, sizeof(my_pcname));
+
+ EncodeNetBiosName(my_pc_encoded_name, my_pcname);
+
+ if (Cmp(my_pc_encoded_name, encoded_name, 30) == 0)
+ {
+ // Assemble the response packet since the name resolution packet which targets this PC name received
+ BUF *sb = NewBuf();
+ USHORT us;
+ UINT ui;
+ LIST *ip_list;
+ BUF *ip_list_buf;
+ bool found = false;
+
+ WriteBuf(sb, &tran_id, sizeof(USHORT));
+
+ flags = Endian16(0x8500);
+ WriteBuf(sb, &flags, sizeof(USHORT));
+
+ num_query = 0;
+ WriteBuf(sb, &num_query, sizeof(USHORT));
+
+ us = Endian16(1);
+ WriteBuf(sb, &us, sizeof(USHORT));
+
+ us = 0;
+ WriteBuf(sb, &us, sizeof(USHORT));
+ WriteBuf(sb, &us, sizeof(USHORT));
+
+ name_size = 0x20;
+ WriteBuf(sb, &name_size, 1);
+
+ WriteBuf(sb, encoded_name, 32);
+
+ node_type = 0;
+ WriteBuf(sb, &node_type, 1);
+
+ type = Endian16(type);
+ classid = Endian16(classid);
+
+ WriteBuf(sb, &type, sizeof(USHORT));
+ WriteBuf(sb, &classid, sizeof(USHORT));
+
+ ui = Endian32((UINT)(Tick64() / 1000ULL));
+ WriteBuf(sb, &ui, sizeof(UINT));
+
+ ip_list_buf = NewBuf();
+
+ ip_list = GetHostIPAddressList();
+ if (ip_list != NULL)
+ {
+ UINT i;
+
+ // Return only private IP if there is a private IP
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ if (IsIP4(ip) && IsLocalHostIP4(ip) == false && IsZeroIp(ip) == false)
+ {
+ if (IsIPPrivate(ip))
+ {
+ USHORT flags = Endian16(0x4000);
+ UINT ip_uint = IPToUINT(ip);
+
+ WriteBuf(ip_list_buf, &flags, sizeof(USHORT));
+ WriteBuf(ip_list_buf, &ip_uint, sizeof(UINT));
+
+ found = true;
+ }
+ }
+ }
+
+ if (found == false)
+ {
+ // Return all IP if no private IP are found
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ if (IsIP4(ip) && IsLocalHostIP4(ip) == false && IsZeroIp(ip) == false)
+ {
+ USHORT flags = Endian16(0x4000);
+ UINT ip_uint = IPToUINT(ip);
+
+ WriteBuf(ip_list_buf, &flags, sizeof(USHORT));
+ WriteBuf(ip_list_buf, &ip_uint, sizeof(UINT));
+
+ found = true;
+ }
+ }
+ }
+
+ FreeHostIPAddressList(ip_list);
+ }
+
+ us = Endian16(ip_list_buf->Size);
+ WriteBuf(sb, &us, sizeof(USHORT));
+
+ WriteBufBuf(sb, ip_list_buf);
+
+ SendUdp(v, src_ip, src_port, v->HostIP, dest_port, sb->Buf, sb->Size);
+
+ FreeBuf(ip_list_buf);
+
+ FreeBuf(sb);
+
+ WHERE;
+ }
+ }
+ }
+
+ FreeBuf(rb);
+
+ return ret;
+}
+
+// Process the NetBIOS broadcast packet
+void UdpRecvForNetBiosBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy, bool unicast)
+{
+ // Validate arguments
+ if (data == NULL || v == NULL)
+ {
+ return;
+ }
+
+ // Ignore for NetBIOS name registration packet
+ if (IsNetbiosRegistrationPacket(data, size) == false)
+ {
+ if (unicast == false)
+ {
+ dest_ip = 0xFFFFFFFF;
+ }
+
+ if (ProcessNetBiosNameQueryPacketForMyself(v, src_ip, src_port, dest_ip, dest_port, data, size) == false)
+ {
+ UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, data, size, false);
+ }
+ }
+}
+
+// Process the UDP packet to the Internet
+void UdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy)
+{
+ NAT_ENTRY *n, t;
+ BLOCK *block;
+ void *buf;
+ UINT dns_ip = 0;
+ // Validate arguments
+ if (data == NULL || v == NULL)
+ {
+ return;
+ }
+
+ if (dns_proxy)
+ {
+ // Get the DNS server of the proxy to connect to
+ IP ip;
+ char tmp[MAX_SIZE];
+ if (GetDefaultDns(&ip) == false)
+ {
+ // Failure
+ Debug("Failed to GetDefaultDns()\n");
+ return;
+ }
+ dns_ip = IPToUINT(&ip);
+ IPToStr(tmp, sizeof(tmp), &ip);
+ Debug("Redirect to DNS Server %s\n", tmp);
+ }
+
+ // Examine whether the NAT entry for this packet has already been created
+ SetNat(&t, NAT_UDP, src_ip, src_port, dest_ip, dest_port, 0, 0);
+ n = SearchNat(v, &t);
+
+ if (n == NULL)
+ {
+ // Create a NAT entry because it is the first packet
+ n = CreateNatUdp(v, src_ip, src_port, dest_ip, dest_port, dns_proxy ? dns_ip : 0);
+ if (n == NULL)
+ {
+ // Entry creation failed
+ return;
+ }
+
+ if (dns_proxy)
+ {
+ n->ProxyDns = true;
+ n->DestIpProxy = dns_ip;
+ }
+ }
+
+ // Set the event by inserting the packet into the queue
+ buf = Malloc(size);
+ Copy(buf, data, size);
+ block = NewBlock(buf, size, 0);
+ InsertQueue(n->UdpSendQueue, block);
+
+ SetSockEvent(v->SockEvent);
+}
+
+// Attempt to interpret the DNS packet
+bool ParseDnsPacket(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ return ParseDnsPacketEx(v, src_ip, src_port, dest_ip, dest_port, data, size, NULL);
+}
+bool ParseDnsPacketEx(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, DNS_PARSED_PACKET *parsed_result)
+{
+ DNSV4_HEADER *dns;
+ NAT_ENTRY *nat;
+ UINT transaction_id;
+ void *query_data;
+ UINT query_data_size;
+ char hostname[256];
+ // Validate arguments
+ if (v == NULL || data == NULL || size == 0)
+ {
+ return false;
+ }
+
+ // Check the header size
+ if (size < sizeof(DNSV4_HEADER))
+ {
+ // Undersize
+ return false;
+ }
+
+ // DNS header acquisition
+ dns = (DNSV4_HEADER *)data;
+ transaction_id = Endian16(dns->TransactionId);
+ if ((dns->Flag1 & 78) != 0 || (dns->Flag1 & 0x80) != 0)
+ {
+ // Illegal opcode
+ return false;
+ }
+ if (Endian16(dns->NumQuery) != 1)
+ {
+ // Number of queries is invalid
+ return false;
+ }
+
+ query_data = ((UCHAR *)dns) + sizeof(DNSV4_HEADER);
+ query_data_size = size - sizeof(DNSV4_HEADER);
+
+ // Interpret the query
+ if (ParseDnsQuery(hostname, sizeof(hostname), query_data, query_data_size) == false)
+ {
+ // Interpretation fails
+ return false;
+ }
+
+ if (parsed_result != NULL)
+ {
+ // Only analyse without processing
+ Zero(parsed_result, sizeof(DNS_PARSED_PACKET));
+ StrCpy(parsed_result->Hostname, sizeof(parsed_result->Hostname), hostname);
+ parsed_result->TransactionId = transaction_id;
+
+ return true;
+ }
+
+ // Create a DNS entry
+ nat = CreateNatDns(v, src_ip, src_port, dest_ip, dest_port, transaction_id,
+ false, hostname);
+
+ if (nat == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Send the NAT DNS response packet
+void SendNatDnsResponse(VH *v, NAT_ENTRY *n)
+{
+ BUF *b;
+ UINT dns_header_size;
+ DNSV4_HEADER *dns;
+ UINT src_ip;
+ // Validate arguments
+ if (n == NULL || v == NULL)
+ {
+ return;
+ }
+
+ // Generate the data
+ b = NewBuf();
+
+ // Add a Query
+ if (n->DnsGetIpFromHost == false)
+ {
+ BuildDnsQueryPacket(b, n->DnsTargetHostName, false);
+ }
+ else
+ {
+ BuildDnsQueryPacket(b, n->DnsTargetHostName, true);
+ }
+
+ // Add a Response
+ if (n->DnsOk)
+ {
+ if (n->DnsGetIpFromHost == false)
+ {
+ BuildDnsResponsePacketA(b, &n->DnsResponseIp);
+ }
+ else
+ {
+ BuildDnsResponsePacketPtr(b, n->DnsResponseHostName);
+ }
+ }
+
+ // Generate a DNS header
+ dns_header_size = sizeof(DNSV4_HEADER) + b->Size;
+
+ dns = ZeroMalloc(dns_header_size);
+ dns->TransactionId = Endian16((USHORT)n->DnsTransactionId);
+
+ // Generate a response flag
+ if (n->DnsOk)
+ {
+ dns->Flag1 = 0x85;
+ dns->Flag2 = 0x80;
+ }
+ else
+ {
+ dns->Flag1 = 0x85;
+ dns->Flag2 = 0x83;
+ }
+
+ dns->NumQuery = Endian16(1);
+ dns->AnswerRRs = Endian16(n->DnsOk != false ? 1 : 0);
+ dns->AuthorityRRs = 0;
+ dns->AdditionalRRs = 0;
+
+ // Settings, such as the source IP address
+ src_ip = n->DestIp;
+ if (src_ip == Endian32(SPECIAL_IPV4_ADDR_LLMNR_DEST) && n->DestPort == SPECIAL_UDP_PORT_LLMNR)
+ {
+ // Make a unicast response in the case of LLMNR packet
+ src_ip = v->HostIP;
+
+ dns->Flag1 = 0x84;
+ dns->Flag2 = 0x00;
+ }
+
+ // Copy data
+ Copy(((UCHAR *)dns) + sizeof(DNSV4_HEADER), b->Buf, b->Size);
+
+ // Send this packet
+ SendUdp(v, n->SrcIp, n->SrcPort, src_ip, n->DestPort, dns, dns_header_size);
+
+ // Release the memory
+ Free(dns);
+ FreeBuf(b);
+}
+
+// Generate a DNS response packet (host name)
+void BuildDnsResponsePacketPtr(BUF *b, char *hostname)
+{
+ USHORT magic;
+ USHORT type, clas;
+ UINT ttl;
+ USHORT len;
+ BUF *c;
+ // Validate arguments
+ if (b == NULL || hostname == NULL)
+ {
+ return;
+ }
+
+ magic = Endian16(0xc00c);
+ type = Endian16(0x000c);
+ clas = Endian16(0x0001);
+ ttl = Endian32(NAT_DNS_RESPONSE_TTL);
+
+ c = BuildDnsHostName(hostname);
+ if (c == NULL)
+ {
+ return;
+ }
+ len = Endian16((USHORT)c->Size);
+
+ WriteBuf(b, &magic, 2);
+ WriteBuf(b, &type, 2);
+ WriteBuf(b, &clas, 2);
+ WriteBuf(b, &ttl, 4);
+ WriteBuf(b, &len, 2);
+ WriteBuf(b, c->Buf, c->Size);
+ FreeBuf(c);
+}
+
+// Generate a DNS response packet (host IP address)
+void BuildDnsResponsePacketA(BUF *b, IP *ip)
+{
+ UINT ip_addr;
+ USHORT magic;
+ USHORT type, clas;
+ UINT ttl;
+ USHORT len;
+ // Validate arguments
+ if (b == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ ip_addr = IPToUINT(ip);
+ magic = Endian16(0xc00c);
+ type = Endian16(0x0001);
+ clas = Endian16(0x0001);
+ ttl = Endian32(NAT_DNS_RESPONSE_TTL);
+ len = Endian16((USHORT)sizeof(ttl));
+
+ WriteBuf(b, &magic, sizeof(magic));
+ WriteBuf(b, &type, sizeof(type));
+ WriteBuf(b, &clas, sizeof(clas));
+ WriteBuf(b, &ttl, sizeof(ttl));
+ WriteBuf(b, &len, sizeof(len));
+ WriteBuf(b, &ip_addr, sizeof(ip_addr));
+}
+
+// Generate a DNS query data packet
+void BuildDnsQueryPacket(BUF *b, char *hostname, bool ptr)
+{
+ USHORT val;
+ BUF *c;
+ // Validate arguments
+ if (b == NULL || hostname == NULL)
+ {
+ return;
+ }
+
+ // Convert the host name to a buffer
+ c = BuildDnsHostName(hostname);
+ if (c == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, c->Buf, c->Size);
+ FreeBuf(c);
+
+ // Type and class
+ if (ptr == false)
+ {
+ val = Endian16(0x0001);
+ }
+ else
+ {
+ val = Endian16(0x000c);
+ }
+ WriteBuf(b, &val, 2);
+
+ val = Endian16(0x0001);
+ WriteBuf(b, &val, 2);
+}
+
+// Generate a DNS host name buffer
+BUF *BuildDnsHostName(char *hostname)
+{
+ UINT i;
+ UCHAR size;
+ TOKEN_LIST *token;
+ BUF *b;
+ // Validate arguments
+ if (hostname == NULL)
+ {
+ return NULL;
+ }
+
+ // Split the host name into tokens
+ token = ParseToken(hostname, ".");
+ if (token == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Add a host string
+ for (i = 0;i < token->NumTokens;i++)
+ {
+ size = (UCHAR)StrLen(token->Token[i]);
+ WriteBuf(b, &size, 1);
+ WriteBuf(b, token->Token[i], size);
+ }
+
+ // NULL character
+ size = 0;
+ WriteBuf(b, &size, 1);
+
+ SeekBuf(b, 0, 0);
+
+ FreeToken(token);
+
+ return b;
+}
+
+// Process the NAT DNS entry
+void PollingNatDns(VH *v, NAT_ENTRY *n)
+{
+ // Validate arguments
+ if (v == NULL || n == NULL)
+ {
+ return;
+ }
+
+ if (n->DnsFinished)
+ {
+ if (n->DnsPollingFlag == false)
+ {
+ n->DnsPollingFlag = true;
+ // Process has been completed
+ SendNatDnsResponse(v, n);
+
+ // Terminating
+ n->DisconnectNow = true;
+ }
+ }
+}
+
+// Create a NAT DNS entry
+NAT_ENTRY *CreateNatDns(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port,
+ UINT transaction_id, bool dns_get_ip_from_host, char *dns_target_host_name)
+{
+ NAT_ENTRY *n;
+ HUB_OPTION *o;
+ // Validate arguments
+ if (v == NULL || dns_target_host_name == NULL)
+ {
+ return NULL;
+ }
+
+ if (CanCreateNewNatEntry(v) == false)
+ {
+ return NULL;
+ }
+
+ o = NatGetHubOption(v);
+ if (o != NULL && o->SecureNAT_MaxDnsSessionsPerIp != 0)
+ {
+ if (GetNumNatEntriesPerIp(v, src_ip, NAT_DNS, false) >= o->SecureNAT_MaxDnsSessionsPerIp)
+ {
+ NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_DNS);
+
+ if (oldest != NULL)
+ {
+ DisconnectNatEntryNow(v, oldest);
+ }
+ }
+ }
+
+ n = ZeroMalloc(sizeof(NAT_ENTRY));
+ n->Id = Inc(v->Counter);
+ n->v = v;
+ n->lock = NewLock();
+ n->Protocol = NAT_DNS;
+ n->SrcIp = src_ip;
+ n->SrcPort = src_port;
+ n->DestIp = dest_ip;
+ n->DestPort = dest_port;
+ n->DnsTransactionId = transaction_id;
+ n->CreatedTime = n->LastCommTime = v->Now;
+ n->DisconnectNow = false;
+
+ n->DnsGetIpFromHost = false;
+ n->DnsTargetHostName = CopyStr(dns_target_host_name);
+
+ Add(v->NatTable, n);
+
+#if 1
+ {
+ IP ip1, ip2;
+ char s1[MAX_SIZE], s2[MAX_SIZE];
+ UINTToIP(&ip1, src_ip);
+ UINTToIP(&ip2, dest_ip);
+ IPToStr(s1, 0, &ip1);
+ IPToStr(s2, 0, &ip2);
+ Debug("NAT_ENTRY: CreateNatDns %s %u -> %s %u\n", s1, src_port, s2, dest_port);
+ }
+#endif
+
+
+ return n;
+}
+
+// Get the next byte
+UCHAR GetNextByte(BUF *b)
+{
+ UCHAR c = 0;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &c, 1) != 1)
+ {
+ return 0;
+ }
+
+ return c;
+}
+
+// Interpret the DNS query
+bool ParseDnsQuery(char *name, UINT name_size, void *data, UINT data_size)
+{
+ BUF *b;
+ char tmp[257];
+ bool ok = true;
+ USHORT val;
+ // Validate arguments
+ if (name == NULL || data == NULL || data_size == 0)
+ {
+ return false;
+ }
+ StrCpy(name, name_size, "");
+
+ b = NewBuf();
+ WriteBuf(b, data, data_size);
+ SeekBuf(b, 0, 0);
+
+ while (true)
+ {
+ UINT next_len = (UINT)GetNextByte(b);
+ if (next_len > 0)
+ {
+ // Read only the specified length
+ Zero(tmp, sizeof(tmp));
+ if (ReadBuf(b, tmp, next_len) != next_len)
+ {
+ ok = false;
+ break;
+ }
+ // Append
+ if (StrLen(name) != 0)
+ {
+ StrCat(name, name_size, ".");
+ }
+ StrCat(name, name_size, tmp);
+ }
+ else
+ {
+ // Read all
+ break;
+ }
+ }
+
+ if (ReadBuf(b, &val, sizeof(val)) != sizeof(val))
+ {
+ ok = false;
+ }
+ else
+ {
+ if (Endian16(val) != 0x01 && Endian16(val) != 0x0c)
+ {
+ ok = false;
+ }
+ }
+
+ if (ReadBuf(b, &val, sizeof(val)) != sizeof(val))
+ {
+ ok = false;
+ }
+ else
+ {
+ if (Endian16(val) != 0x01)
+ {
+ ok = false;
+ }
+ }
+
+ FreeBuf(b);
+
+ if (ok == false || StrLen(name) == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Set the VGS host name
+void SetDnsProxyVgsHostname(char *hostname)
+{
+ // Validate arguments
+ if (hostname == NULL)
+ {
+ return;
+ }
+
+ StrCpy(v_vgs_hostname, sizeof(v_vgs_hostname), hostname);
+}
+
+// Operate as a DNS proxy
+void DnsProxy(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ // Validate arguments
+ if (v == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (dest_port == SPECIAL_UDP_PORT_LLMNR)
+ {
+ // Process by analyzing the DNS query in the case of LLMNR
+ ParseDnsPacket(v, src_ip, src_port, dest_ip, dest_port, data, size);
+ }
+ else
+ {
+ // Forward the packet as it is in the case of a normal DNS packet
+ if (IsEmptyStr(v_vgs_hostname) == false)
+ {
+ // Response by proxy in the case of trying to get the IP of the VGS
+ DNS_PARSED_PACKET p;
+
+ Zero(&p, sizeof(p));
+ if (ParseDnsPacketEx(v, src_ip, src_port, dest_ip, dest_port, data, size, &p))
+ {
+ if (StrCmpi(p.Hostname, "254.254.211.10.in-addr.arpa") == 0)
+ {
+ NAT_ENTRY n;
+
+ Zero(&n, sizeof(n));
+ n.DnsTargetHostName = p.Hostname;
+ n.DnsGetIpFromHost = true;
+ n.DnsResponseHostName = v_vgs_hostname;
+ n.DnsTransactionId = p.TransactionId;
+ n.DnsOk = true;
+ n.DestIp = dest_ip;
+ n.SrcIp = src_ip;
+ n.DestPort = dest_port;
+ n.SrcPort = src_port;
+
+ SendNatDnsResponse(v, &n);
+ return;
+ }
+ }
+ }
+
+ UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, data, size, true);
+ }
+}
+
+// Process the LLMNR query
+void UdpRecvLlmnr(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ // Validate arguments
+ if (data == NULL || v == NULL)
+ {
+ return;
+ }
+
+ if (dest_port == SPECIAL_UDP_PORT_LLMNR)
+ {
+ // DNS proxy start
+ DnsProxy(v, src_ip, src_port, dest_ip, dest_port, data, size);
+ }
+}
+
+// Process the UDP packet to the virtual host
+void UdpRecvForMe(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ // Validate arguments
+ if (data == NULL || v == NULL)
+ {
+ return;
+ }
+
+ if (dest_port == NAT_DNS_PROXY_PORT)
+ {
+ // DNS proxy start
+ DnsProxy(v, src_ip, src_port, dest_ip, dest_port, data, size);
+ }
+}
+
+// Process the UDP broadcast packet
+void UdpRecvForBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
+{
+ // Validate arguments
+ if (data == NULL || v == NULL)
+ {
+ return;
+ }
+}
+
+// An UDP packet has been received
+void VirtualUdpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, bool mac_broadcast, bool is_localmac, UINT max_l3_size)
+{
+ UDP_HEADER *udp;
+ UINT packet_length;
+ void *buf;
+ UINT buf_size;
+ UINT src_port, dest_port;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Check the header
+ udp = (UDP_HEADER *)data;
+ if (size < UDP_HEADER_SIZE)
+ {
+ return;
+ }
+ packet_length = Endian16(udp->PacketLength);
+ if (packet_length != size)
+ {
+ return;
+ }
+ buf = ((UCHAR *)data) + UDP_HEADER_SIZE;
+ buf_size = size - UDP_HEADER_SIZE;
+ src_port = Endian16(udp->SrcPort);
+ dest_port = Endian16(udp->DstPort);
+ // Check the port number
+ if (dest_port == 0)
+ {
+ // Port number is invalid
+ return;
+ }
+
+ // Determine whether it's broadcast packet or packet addressed to myself
+ if (dest_ip == v->HostIP)
+ {
+ // IP packet addressed to myself has arrived
+ UdpRecvForMe(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
+ }
+ else if ((mac_broadcast || dest_ip == Endian32(0xE00000FC)) && dest_port == SPECIAL_UDP_PORT_LLMNR)
+ {
+ if (is_localmac == false)
+ {
+ // Packet addressed to 224.0.0.252 (LLMNR) arrives
+ UdpRecvLlmnr(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
+ }
+ }
+ else if (mac_broadcast && (dest_port == SPECIAL_UDP_PORT_WSD || dest_port == SPECIAL_UDP_PORT_SSDP))
+ {
+ if (is_localmac == false)
+ {
+ // WS-Discovery packet arrives
+ UdpRecvForInternet(v, src_ip, src_port, 0xFFFFFFFF, dest_port, buf, buf_size, false);
+ }
+ }
+ else if (mac_broadcast && (dest_port == SPECIAL_UDP_PORT_NBTDGM || dest_port == SPECIAL_UDP_PORT_NBTNS))
+ {
+ if (is_localmac == false)
+ {
+ // NetBIOS Broadcast packet arrived
+ UdpRecvForNetBiosBroadcast(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, false, false);
+ }
+ }
+ else if (mac_broadcast || dest_ip == 0xffffffff || dest_ip == GetBroadcastAddress(v->HostIP, v->HostMask))
+ {
+ if (is_localmac == false)
+ {
+ // Broadcast packet arrived
+ UdpRecvForBroadcast(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
+ }
+ }
+ else if (IsInNetwork(dest_ip, v->HostIP, v->HostMask) == false)
+ {
+ // Packets to other than local address (that is on the Internet) has been received
+ if (NnIsActive(v) == false)
+ {
+ if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
+ {
+ // User-mode NAT is disabled
+ return;
+ }
+
+ // User-mode NAT
+ UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, false);
+ }
+ else
+ {
+ // Kernel-mode NAT
+ NnUdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, max_l3_size);
+ }
+ }
+ else
+ {
+ // Local address has arrived. Ignore it
+ }
+}
+
+// Determine the network address of the subnet to which the specified IP address belongs
+UINT GetNetworkAddress(UINT addr, UINT mask)
+{
+ return (addr & mask);
+}
+
+// Determine the broadcast address of the subnet to which the specified IP address belongs
+UINT GetBroadcastAddress(UINT addr, UINT mask)
+{
+ return ((addr & mask) | (~mask));
+}
+void GetBroadcastAddress4(IP *dst, IP *addr, IP *mask)
+{
+ // Validate arguments
+ if (dst == NULL || IsIP4(addr) == false || IsIP4(mask) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ UINTToIP(dst, GetBroadcastAddress(IPToUINT(addr), IPToUINT(mask)));
+}
+
+// Determine whether the specified IP address belongs to the sub-network that is
+// represented by a another specified network address and a subnet mask
+bool IsInNetwork(UINT uni_addr, UINT network_addr, UINT mask)
+{
+ if (GetNetworkAddress(uni_addr, mask) == GetNetworkAddress(network_addr, mask))
+ {
+ return true;
+ }
+ return false;
+}
+
+// Send an UDP packet
+void SendUdp(VH *v, UINT dest_ip, UINT dest_port, UINT src_ip, UINT src_port, void *data, UINT size)
+{
+ UDPV4_PSEUDO_HEADER *vh;
+ UDP_HEADER *udp;
+ UINT udp_packet_length = UDP_HEADER_SIZE + size;
+ USHORT checksum;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+ if (udp_packet_length > 65536)
+ {
+ return;
+ }
+
+ // Generate a virtual header
+ vh = Malloc(sizeof(UDPV4_PSEUDO_HEADER) + size);
+ udp = (UDP_HEADER *)(((UCHAR *)vh) + 12);
+
+ vh->SrcIP = src_ip;
+ vh->DstIP = dest_ip;
+ vh->Reserved = 0;
+ vh->Protocol = IP_PROTO_UDP;
+ vh->PacketLength1 = Endian16((USHORT)udp_packet_length);
+ udp->SrcPort = Endian16((USHORT)src_port);
+ udp->DstPort = Endian16((USHORT)dest_port);
+ udp->PacketLength = Endian16((USHORT)udp_packet_length);
+ udp->Checksum = 0;
+
+ // Copy data
+ Copy(((UCHAR *)udp) + UDP_HEADER_SIZE, data, size);
+
+ // Calculate the checksum
+ checksum = IpChecksum(vh, udp_packet_length + 12);
+ if (checksum == 0x0000)
+ {
+ checksum = 0xffff;
+ }
+ udp->Checksum = checksum;
+
+ // Send a packet
+ SendIp(v, dest_ip, src_ip, IP_PROTO_UDP, udp, udp_packet_length);
+
+ // Release the memory
+ Free(vh);
+}
+
+// Poll the IP combining object
+void PollingIpCombine(VH *v)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Discard the old combining object
+ o = NULL;
+ for (i = 0;i < LIST_NUM(v->IpCombine);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
+
+ if (c->Expire < v->Now)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, c);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(o, i);
+
+ // Remove from the list
+ Delete(v->IpCombine, c);
+
+ // Release the memory
+ FreeIpCombine(v, c);
+ }
+ ReleaseList(o);
+ }
+}
+
+// Send an ICMP packet
+void VirtualIcmpSend(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size)
+{
+ ICMP_HEADER *icmp;
+ void *data_buf;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Build the header
+ icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
+ // Data copy
+ data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
+ Copy(data_buf, data, size);
+ // Other
+ icmp->Checksum = 0;
+ icmp->Code = 0;
+ icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
+ // Checksum
+ icmp->Checksum = IpChecksum(icmp, sizeof(ICMP_HEADER) + size);
+
+ // IP packet transmission
+ SendIp(v, dst_ip, src_ip, IP_PROTO_ICMPV4, icmp, sizeof(ICMP_HEADER) + size);
+
+ // Release the memory
+ Free(icmp);
+}
+
+// Send the ICMP Echo Response packet
+void VirtualIcmpEchoSendResponse(VH *v, UINT src_ip, UINT dst_ip, USHORT id, USHORT seq_no, void *data, UINT size)
+{
+ ICMP_ECHO *e;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Build the header
+ e = ZeroMalloc(sizeof(ICMP_ECHO) + size);
+ e->Identifier = Endian16(id);
+ e->SeqNo = Endian16(seq_no);
+
+ // Data copy
+ Copy(((UCHAR *)e) + sizeof(ICMP_ECHO), data, size);
+
+ // Send an ICMP
+ VirtualIcmpSend(v, src_ip, dst_ip, e, sizeof(ICMP_ECHO) + size);
+
+ // Release the memory
+ Free(e);
+}
+
+// Treat the ICMP Echo Request packet with a Raw Socket
+void VirtualIcmpEchoRequestReceivedRaw(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size)
+{
+ ICMP_ECHO *echo;
+ UINT data_size;
+ void *data_buf;
+ USHORT id, seq_no;
+ void *buf;
+ BLOCK *block;
+ // Validate arguments
+ if (v == NULL || data == NULL || icmp_data == NULL || ip_header == NULL)
+ {
+ return;
+ }
+ if (ttl == 0)
+ {
+ ttl = 1;
+ }
+
+ echo = (ICMP_ECHO *)data;
+
+ // Echo size check
+ if (size < sizeof(ICMP_ECHO))
+ {
+ // Insufficient data
+ return;
+ }
+
+ id = Endian16(echo->Identifier);
+ seq_no = Endian16(echo->SeqNo);
+
+ // Data size
+ data_size = size - sizeof(ICMP_ECHO);
+
+ // Data body
+ data_buf = ((UCHAR *)data) + sizeof(ICMP_ECHO);
+
+ if (dst_ip == v->HostIP)
+ {
+ // Respond because it is addressed to me
+ VirtualIcmpEchoSendResponse(v, v->HostIP, src_ip, id, seq_no, data_buf, data_size);
+ }
+ else if (IsInNetwork(dst_ip, v->HostIP, v->HostMask) == false)
+ {
+ NAT_ENTRY *n = NULL, t;
+ // Process by creating a NAT entry because it is addressed to the Internet
+
+ if (ttl <= 1)
+ {
+ // Reply the Time Exceeded immediately for the packet whose TTL is 1
+ UINT reply_size = sizeof(ICMP_HEADER) + 4 + ip_header_size + 8;
+ UCHAR *reply_data = ZeroMalloc(reply_size);
+ ICMP_HEADER *icmp = (ICMP_HEADER *)reply_data;
+ icmp->Type = ICMP_TYPE_TIME_EXCEEDED;
+ icmp->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
+ Copy(reply_data + sizeof(ICMP_HEADER) + 4, ip_header, ip_header_size);
+ Copy(reply_data + sizeof(ICMP_HEADER) + 4 + ip_header_size, icmp_data, MIN(icmp_size, 8));
+
+ icmp->Checksum = IpChecksum(icmp, reply_size);
+
+ SendIp(v, src_ip, v->HostIP, IP_PROTO_ICMPV4, reply_data, reply_size);
+
+ Free(reply_data);
+ }
+ else
+ {
+ SetNat(&t, NAT_ICMP, src_ip, id, dst_ip, id, 0, 0);
+
+ if (v->IcmpRawSocketOk)
+ {
+ // Examine whether a NAT entry for this packet has already been created
+ n = SearchNat(v, &t);
+ }
+
+ if (n == NULL)
+ {
+ // Create a NAT entry because it is the first packet
+ n = CreateNatIcmp(v, src_ip, id, dst_ip, id, (UCHAR *)ip_header, ip_header_size + 8);
+
+ if (n == NULL)
+ {
+ // Entry creation failed
+ return;
+ }
+ }
+
+ // Set the event by inserting the packet into the queue
+ buf = Malloc(icmp_size);
+ Copy(buf, icmp_data, icmp_size);
+ block = NewBlock(buf, icmp_size, 0);
+ block->Ttl = MAKESURE(ttl - 1, 1, 255);
+ InsertQueue(n->UdpSendQueue, block);
+
+ SetSockEvent(v->SockEvent);
+ }
+ }
+}
+
+// Receive an ICMP Echo Request packet
+void VirtualIcmpEchoRequestReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
+{
+ ICMP_ECHO *echo;
+ UINT data_size;
+ void *data_buf;
+ USHORT id, seq_no;
+ // Validate arguments
+ if (v == NULL || data == NULL || icmp_data == NULL)
+ {
+ return;
+ }
+
+ if (NnIsActive(v))
+ {
+ // Process by the Native NAT
+ NnIcmpEchoRecvForInternet(v, src_ip, dst_ip, data, size, ttl, icmp_data, icmp_size,
+ ip_header, ip_header_size, max_l3_size);
+ return;
+ }
+
+ if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
+ {
+ // User-mode NAT is disabled
+ return;
+ }
+
+ if (v->IcmpRawSocketOk || v->IcmpApiOk)
+ {
+ // Process in the Raw Socket
+ VirtualIcmpEchoRequestReceivedRaw(v, src_ip, dst_ip, data, size, ttl, icmp_data, icmp_size,
+ ip_header, ip_header_size);
+ return;
+ }
+
+ // Returns the fake ICMP forcibly if any of Native NAT or Raw Socket can not be used
+
+ echo = (ICMP_ECHO *)data;
+
+ // Echo size check
+ if (size < sizeof(ICMP_ECHO))
+ {
+ // Insufficient data
+ return;
+ }
+
+ id = Endian16(echo->Identifier);
+ seq_no = Endian16(echo->SeqNo);
+
+ // Data size
+ data_size = size - sizeof(ICMP_ECHO);
+
+ // Data body
+ data_buf = ((UCHAR *)data) + sizeof(ICMP_ECHO);
+
+ // Return the ICMP Echo Response
+ VirtualIcmpEchoSendResponse(v, dst_ip, src_ip, id, seq_no, data_buf, data_size);
+}
+
+// An ICMP packet has been received
+void VirtualIcmpReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
+{
+ ICMP_HEADER *icmp;
+ UINT msg_size;
+ USHORT checksum_calc, checksum_original;
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Size check
+ if (size < sizeof(ICMP_HEADER))
+ {
+ return;
+ }
+
+ // ICMP header
+ icmp = (ICMP_HEADER *)data;
+
+ // Get the ICMP message size
+ msg_size = size - sizeof(ICMP_HEADER);
+
+ // Check the checksum of the ICMP header
+ checksum_original = icmp->Checksum;
+ icmp->Checksum = 0;
+ checksum_calc = IpChecksum(data, size);
+ icmp->Checksum = checksum_original;
+
+ if (checksum_calc != checksum_original)
+ {
+ // Checksum is invalid
+ Debug("ICMP CheckSum Failed.\n");
+ return;
+ }
+
+ // Identified by the opcode
+ switch (icmp->Type)
+ {
+ case ICMP_TYPE_ECHO_REQUEST: // ICMP Echo request
+ VirtualIcmpEchoRequestReceived(v, src_ip, dst_ip, ((UCHAR *)data) + sizeof(ICMP_HEADER), msg_size, ttl,
+ icmp, size, ip_header, ip_header_size, max_l3_size);
+ break;
+
+ case ICMP_TYPE_ECHO_RESPONSE: // ICMP Echo response
+ // Do Nothing
+ break;
+ }
+}
+
+// Received an IP packet
+void IpReceived(VH *v, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size, bool mac_broadcast, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, bool is_local_mac, UINT max_l3_size)
+{
+ // Validate arguments
+ if (v == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Deliver the data to the supported high-level protocol
+ switch (protocol)
+ {
+ case IP_PROTO_ICMPV4: // ICMPv4
+ if (mac_broadcast == false)
+ {
+ VirtualIcmpReceived(v, src_ip, dest_ip, data, size, ttl, ip_header, ip_header_size, max_l3_size);
+ }
+ break;
+
+ case IP_PROTO_TCP: // TCP
+ if (mac_broadcast == false)
+ {
+ VirtualTcpReceived(v, src_ip, dest_ip, data, size, max_l3_size);
+ }
+ break;
+
+ case IP_PROTO_UDP: // UDP
+ VirtualUdpReceived(v, src_ip, dest_ip, data, size, mac_broadcast, is_local_mac, max_l3_size);
+ break;
+ }
+}
+
+// Combine the IP packet received to the IP combining object
+void CombineIp(VH *v, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size)
+{
+ UINT i;
+ IP_PART *p;
+ UINT need_size;
+ UINT data_size_delta;
+ // Validate arguments
+ if (c == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Check the size and offset
+ if ((offset + size) > 65535)
+ {
+ // Do not process packet larger than 64Kbytes
+ return;
+ }
+
+ if (last_packet == false && c->Size != 0)
+ {
+ if ((offset + size) > c->Size)
+ {
+ // Do not process the packet larger than the packet size
+ return;
+ }
+ }
+
+ if (head_ip_header_data != NULL && head_ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ if (c->HeadIpHeaderData == NULL)
+ {
+ c->HeadIpHeaderData = Clone(head_ip_header_data, head_ip_header_size);
+ c->HeadIpHeaderDataSize = head_ip_header_size;
+ }
+ }
+
+ need_size = offset + size;
+ data_size_delta = c->DataReserved;
+ // Ensure sufficient if the buffer is insufficient
+ while (c->DataReserved < need_size)
+ {
+ c->DataReserved = c->DataReserved * 4;
+ c->Data = ReAlloc(c->Data, c->DataReserved);
+ }
+ data_size_delta = c->DataReserved - data_size_delta;
+ v->CurrentIpQuota += data_size_delta;
+
+ // Overwrite the data into the buffer
+ Copy(((UCHAR *)c->Data) + offset, data, size);
+
+ if (last_packet)
+ {
+ // If No More Flagment packet arrives, the size of this datagram is finalized
+ c->Size = offset + size;
+ }
+
+ // Check the overlap between the region which is represented by the offset and size of the
+ // existing received list and the region which is represented by the offset and size
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ UINT moving_size;
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ // Check the overlapping between the existing area and head area
+ if ((p->Offset <= offset) && ((p->Offset + p->Size) > offset))
+ {
+ // Compress behind the offset of this packet since a duplication is
+ // found in the first part with the existing packet and this packet
+
+ if ((offset + size) <= (p->Offset + p->Size))
+ {
+ // This packet is buried in the existing packet
+ size = 0;
+ }
+ else
+ {
+ // Retral region is not overlapped
+ moving_size = p->Offset + p->Size - offset;
+ offset += moving_size;
+ size -= moving_size;
+ }
+ }
+ if ((p->Offset < (offset + size)) && ((p->Offset + p->Size) >= (offset + size)))
+ {
+ // Compress the size of this packet forward because a duplication is
+ // found between the posterior portion the existing packet and this packet
+
+ moving_size = p->Offset + p->Size - offset - size;
+ size -= moving_size;
+ }
+
+ if ((p->Offset >= offset) && ((p->Offset + p->Size) <= (offset + size)))
+ {
+ // This packet was overwritten to completely cover an existing packet
+ p->Size = 0;
+ }
+ }
+
+ if (size != 0)
+ {
+ // Register this packet
+ p = ZeroMalloc(sizeof(IP_PART));
+
+ p->Offset = offset;
+ p->Size = size;
+
+ Add(c->IpParts, p);
+ }
+
+ if (c->Size != 0)
+ {
+ // Get the total size of the data portion list already received
+ UINT total_size = 0;
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ total_size += p->Size;
+ }
+
+ if (total_size == c->Size)
+ {
+ // Received all of the IP packet
+ IpReceived(v, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->MacBroadcast, c->Ttl,
+ c->HeadIpHeaderData, c->HeadIpHeaderDataSize, c->SrcIsLocalMacAddr, c->MaxL3Size);
+
+ // Release the combining object
+ FreeIpCombine(v, c);
+
+ // Remove from the combining object list
+ Delete(v->IpCombine, c);
+ }
+ }
+}
+
+// Release the IP combining object
+void FreeIpCombine(VH *v, IP_COMBINE *c)
+{
+ UINT i;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Release the data
+ v->CurrentIpQuota -= c->DataReserved;
+ Free(c->Data);
+
+ // Release the partial list
+ for (i = 0;i < LIST_NUM(c->IpParts);i++)
+ {
+ IP_PART *p = LIST_DATA(c->IpParts, i);
+
+ Free(p);
+ }
+
+ Free(c->HeadIpHeaderData);
+
+ ReleaseList(c->IpParts);
+ Free(c);
+}
+
+// Search the IP combining list
+IP_COMBINE *SearchIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol)
+{
+ IP_COMBINE *c, t;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ t.DestIP = dest_ip;
+ t.SrcIP = src_ip;
+ t.Id = id;
+ t.Protocol = protocol;
+
+ c = Search(v->IpCombine, &t);
+
+ return c;
+}
+
+// Insert by creating a new object to the IP combining list
+IP_COMBINE *InsertIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac)
+{
+ IP_COMBINE *c;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ // Examine the quota
+ if ((v->CurrentIpQuota + IP_COMBINE_INITIAL_BUF_SIZE) > IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA)
+ {
+ // IP packet can not be stored any more
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(IP_COMBINE));
+ c->SrcIsLocalMacAddr = src_is_localmac;
+ c->DestIP = dest_ip;
+ c->SrcIP = src_ip;
+ c->Id = id;
+ c->Expire = v->Now + (UINT64)IP_COMBINE_TIMEOUT;
+ c->Size = 0;
+ c->IpParts = NewList(NULL);
+ c->Protocol = protocol;
+ c->MacBroadcast = mac_broadcast;
+ c->Ttl = ttl;
+
+ // Secure the memory
+ c->DataReserved = IP_COMBINE_INITIAL_BUF_SIZE;
+ c->Data = Malloc(c->DataReserved);
+ v->CurrentIpQuota += c->DataReserved;
+
+ Insert(v->IpCombine, c);
+
+ return c;
+}
+
+// Initialize the IP combining list
+void InitIpCombineList(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->IpCombine = NewList(CompareIpCombine);
+}
+
+// Release the IP combining list
+void FreeIpCombineList(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(v->IpCombine);i++)
+ {
+ IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
+
+ FreeIpCombine(v, c);
+ }
+
+ ReleaseList(v->IpCombine);
+}
+
+// Comparison of IP combining list entry
+int CompareIpCombine(void *p1, void *p2)
+{
+ IP_COMBINE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(IP_COMBINE **)p1;
+ c2 = *(IP_COMBINE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+ if (c1->Id > c2->Id)
+ {
+ return 1;
+ }
+ else if (c1->Id < c2->Id)
+ {
+ return -1;
+ }
+ else if (c1->DestIP > c2->DestIP)
+ {
+ return 1;
+ }
+ else if (c1->DestIP < c2->DestIP)
+ {
+ return -1;
+ }
+ else if (c1->SrcIP > c2->SrcIP)
+ {
+ return 1;
+ }
+ else if (c1->SrcIP < c2->SrcIP)
+ {
+ return -1;
+ }
+ else if (c1->Protocol > c2->Protocol)
+ {
+ return 1;
+ }
+ else if (c1->Protocol < c2->Protocol)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Received an IP packet
+void VirtualIpReceived(VH *v, PKT *packet)
+{
+ IPV4_HEADER *ip;
+ void *data;
+ UINT data_size_recved;
+ UINT size;
+ UINT ipv4_header_size;
+ bool last_packet;
+ UCHAR *head_ip_header_data = NULL;
+ UINT head_ip_header_size = 0;
+ bool is_local_mac = false;
+ UINT ip_l3_size;
+ // Validate arguments
+ if (v == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ ip = packet->L3.IPv4Header;
+
+ if (packet->BroadcastPacket)
+ {
+ is_local_mac = IsMacAddressLocalFast(packet->MacAddressSrc);
+ }
+
+ // Get the size of the IPv4 header
+ ipv4_header_size = IPV4_GET_HEADER_LEN(packet->L3.IPv4Header) * 4;
+ head_ip_header_size = ipv4_header_size;
+
+ // Calculate the checksum of the IPv4 header
+ if (IpCheckChecksum(ip) == false)
+ {
+ return;
+ }
+
+ // Get a pointer to the data
+ data = ((UCHAR *)packet->L3.PointerL3) + ipv4_header_size;
+
+ // Register to the ARP table
+ ArpIpWasKnown(v, packet->L3.IPv4Header->SrcIP, packet->MacAddressSrc);
+
+ // Get the data size
+ size = ip_l3_size = Endian16(ip->TotalLength);
+ if (size <= ipv4_header_size)
+ {
+ // There is no data
+ return;
+ }
+ size -= ipv4_header_size;
+
+ // Get the size of data actually received
+ data_size_recved = packet->PacketSize - (ipv4_header_size + MAC_HEADER_SIZE);
+ if (data_size_recved < size)
+ {
+ // Data insufficient (It may be missing on the way)
+ return;
+ }
+
+ if (IPV4_GET_OFFSET(ip) == 0 && (IPV4_GET_FLAGS(ip) & 0x01) == 0)
+ {
+ // Because this packet has not been fragmented, it can be delivered to the upper layer immediately
+ head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
+ IpReceived(v, ip->SrcIP, ip->DstIP, ip->Protocol, data, size, packet->BroadcastPacket, ip->TimeToLive,
+ head_ip_header_data, head_ip_header_size, is_local_mac, ip_l3_size);
+ }
+ else
+ {
+ // This packet is necessary to combine because it is fragmented
+ UINT offset = IPV4_GET_OFFSET(ip) * 8;
+ IP_COMBINE *c = SearchIpCombine(v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol);
+
+ if (offset == 0)
+ {
+ head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
+ }
+
+ last_packet = ((IPV4_GET_FLAGS(ip) & 0x01) == 0 ? true : false);
+
+ if (c != NULL)
+ {
+ // It is the second or subsequent packet
+ c->MaxL3Size = MAX(c->MaxL3Size, ip_l3_size);
+ CombineIp(v, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
+ }
+ else
+ {
+ // Create a combining object because it is the first packet
+ c = InsertIpCombine(
+ v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol, packet->BroadcastPacket,
+ ip->TimeToLive, is_local_mac);
+ if (c != NULL)
+ {
+ c->MaxL3Size = ip_l3_size;
+
+ CombineIp(v, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
+ }
+ }
+ }
+}
+
+// Send the waiting IP packets from the specified IP address
+void SendWaitingIp(VH *v, UCHAR *mac, UINT dest_ip)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (v == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ // Get a target list
+ for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
+ {
+ IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
+
+ if (w->DestIP == dest_ip)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, w);
+ }
+ }
+
+ // Send the target packets at once
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_WAIT *w = LIST_DATA(o, i);
+
+ // Transmission processing
+ VirtualIpSend(v, mac, w->Data, w->Size);
+
+ // Remove from the list
+ Delete(v->IpWaitTable, w);
+
+ // Release the memory
+ Free(w->Data);
+ Free(w);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Remove the old IP waiting table entries
+void DeleteOldIpWaitTable(VH *v)
+{
+ UINT i;
+ LIST *o = NULL;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Get the deleting list
+ for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
+ {
+ IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
+
+ if (w->Expire < v->Now)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, w);
+ }
+ }
+
+ // Delete all at once
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP_WAIT *w = LIST_DATA(o, i);
+
+ // Remove from the list
+ Delete(v->IpWaitTable, w);
+
+ // Release the memory
+ Free(w->Data);
+ Free(w);
+ }
+ ReleaseList(o);
+ }
+}
+
+// Poll the IP waiting table
+void PollingIpWaitTable(VH *v)
+{
+ // Delete the old table entries
+ DeleteOldIpWaitTable(v);
+}
+
+// Insert the IP packet to the IP waiting table
+void InsertIpWaitTable(VH *v, UINT dest_ip, UINT src_ip, void *data, UINT size)
+{
+ IP_WAIT *w;
+ // Validate arguments
+ if (v == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ w = ZeroMalloc(sizeof(IP_WAIT));
+ w->Data = data;
+ w->Size = size;
+ w->SrcIP = src_ip;
+ w->DestIP = dest_ip;
+ w->Expire = v->Now + (UINT64)IP_WAIT_FOR_ARP_TIMEOUT;
+
+ Add(v->IpWaitTable, w);
+}
+
+// Initialize the IP waiting table
+void InitIpWaitTable(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->IpWaitTable = NewList(NULL);
+}
+
+// Release the IP waiting table
+void FreeIpWaitTable(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
+ {
+ IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
+
+ Free(w->Data);
+ Free(w);
+ }
+
+ ReleaseList(v->IpWaitTable);
+}
+
+// MAC address for the IP address is found because something such as an ARP Response arrives
+void ArpIpWasKnown(VH *v, UINT ip, UCHAR *mac)
+{
+ // Validate arguments
+ if (v == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ // If there is a query for this IP address in the ARP queue, delete it
+ DeleteArpWaitTable(v, ip);
+
+ // Update or register in the ARP table
+ InsertArpTable(v, mac, ip);
+
+ // Send the IP packets waiting in the IP waiting list
+ SendWaitingIp(v, mac, ip);
+}
+
+// Re-issue ARPs by checking the ARP waiting list
+void PollingArpWaitTable(VH *v)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Initialize the deletion list
+ o = NULL;
+
+ // Scan whole ARP waiting list
+ for (i = 0;i < LIST_NUM(v->ArpWaitTable);i++)
+ {
+ ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
+
+ if (w->GiveupTime < v->Now || (w->GiveupTime - 100 * 1000) > v->Now)
+ {
+ // Give up the sending of ARP
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, w);
+ }
+ else
+ {
+ if (w->TimeoutTime < v->Now)
+ {
+ // Send an ARP again
+ VirtualArpSendRequest(v, w->IpAddress);
+
+ // Set the next timeout time
+ w->TimeoutTime = v->Now + (UINT64)w->NextTimeoutTimeValue;
+ // Increase the ARP transmission interval of the second and subsequent
+ w->NextTimeoutTimeValue = w->NextTimeoutTimeValue + ARP_REQUEST_TIMEOUT;
+ }
+ }
+ }
+
+ // Remove if there is a ARP waiting record to be deleted
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ARP_WAIT *w = LIST_DATA(o, i);
+
+ DeleteArpWaitTable(v, w->IpAddress);
+ }
+ ReleaseList(o);
+ }
+}
+
+// Issue an ARP
+void SendArp(VH *v, UINT ip)
+{
+ ARP_WAIT *w;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Examine whether the destination IP address has been registered in the ARP waiting list first
+ w = SearchArpWaitTable(v, ip);
+ if (w != NULL)
+ {
+ // Do not do anything because it is already registered
+ return;
+ }
+
+ // Send an ARP packet first
+ VirtualArpSendRequest(v, ip);
+
+ // Register in the ARP waiting list
+ w = ZeroMalloc(sizeof(ARP_WAIT));
+ w->GiveupTime = v->Now + (UINT64)ARP_REQUEST_GIVEUP;
+ w->TimeoutTime = v->Now + (UINT64)ARP_REQUEST_TIMEOUT;
+ w->NextTimeoutTimeValue = ARP_REQUEST_TIMEOUT;
+ w->IpAddress = ip;
+
+ InsertArpWaitTable(v, w);
+}
+
+// Delete the ARP waiting table
+void DeleteArpWaitTable(VH *v, UINT ip)
+{
+ ARP_WAIT *w;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ w = SearchArpWaitTable(v, ip);
+ if (w == NULL)
+ {
+ return;
+ }
+ Delete(v->ArpWaitTable, w);
+
+ Free(w);
+}
+
+// Search the ARP waiting table
+ARP_WAIT *SearchArpWaitTable(VH *v, UINT ip)
+{
+ ARP_WAIT *w, t;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ t.IpAddress = ip;
+ w = Search(v->ArpWaitTable, &t);
+
+ return w;
+}
+
+// Register in the ARP waiting table
+void InsertArpWaitTable(VH *v, ARP_WAIT *w)
+{
+ // Validate arguments
+ if (v == NULL || w == NULL)
+ {
+ return;
+ }
+
+ Add(v->ArpWaitTable, w);
+}
+
+// Initialize the ARP waiting table
+void InitArpWaitTable(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->ArpWaitTable = NewList(CompareArpWaitTable);
+}
+
+// Release the ARP waiting table
+void FreeArpWaitTable(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(v->ArpWaitTable);i++)
+ {
+ ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
+
+ Free(w);
+ }
+
+ ReleaseList(v->ArpWaitTable);
+}
+
+// Check whether the MAC address is valid
+bool IsMacInvalid(UCHAR *mac)
+{
+ UINT i;
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < 6;i++)
+ {
+ if (mac[i] != 0x00)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the MAC address is a broadcast address
+bool IsMacBroadcast(UCHAR *mac)
+{
+ UINT i;
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < 6;i++)
+ {
+ if (mac[i] != 0xff)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Insert an entry in the ARP table
+void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
+{
+ ARP_ENTRY *e, t;
+ // Validate arguments
+ if (v == NULL || mac == NULL || ip == 0 || ip == 0xffffffff || IsMacBroadcast(mac) || IsMacInvalid(mac))
+ {
+ return;
+ }
+
+ // Check whether the same IP address is not already registered
+ t.IpAddress = ip;
+ e = Search(v->ArpTable, &t);
+ if (e != NULL)
+ {
+ // Override this simply because it was registered
+ if (Cmp(e->MacAddress, mac, 6) != 0)
+ {
+ e->Created = v->Now;
+ Copy(e->MacAddress, mac, 6);
+ }
+ e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
+ }
+ else
+ {
+ // Create a new entry
+ e = ZeroMalloc(sizeof(ARP_ENTRY));
+
+ e->Created = v->Now;
+ e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
+ Copy(e->MacAddress, mac, 6);
+ e->IpAddress = ip;
+
+ Add(v->ArpTable, e);
+ }
+}
+
+// Poll the ARP table
+void PollingArpTable(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (v->Now > v->NextArpTablePolling)
+ {
+ v->NextArpTablePolling = v->Now + (UINT64)ARP_ENTRY_POLLING_TIME;
+ RefreshArpTable(v);
+ }
+}
+
+// Remove the old ARP entries
+void RefreshArpTable(VH *v)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(v->ArpTable);i++)
+ {
+ ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
+
+ // Check for expired
+ if (e->Expire < v->Now)
+ {
+ // Expired
+ Add(o, e);
+ }
+ }
+
+ // Remove expired entries at once
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ARP_ENTRY *e = LIST_DATA(o, i);
+
+ Delete(v->ArpTable, e);
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Search the ARP table
+ARP_ENTRY *SearchArpTable(VH *v, UINT ip)
+{
+ ARP_ENTRY *e, t;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ t.IpAddress = ip;
+ e = Search(v->ArpTable, &t);
+
+ return e;
+}
+
+// Initialize the ARP table
+void InitArpTable(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ v->ArpTable = NewList(CompareArpTable);
+}
+
+// Release the ARP table
+void FreeArpTable(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Delete all entries
+ for (i = 0;i < LIST_NUM(v->ArpTable);i++)
+ {
+ ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
+ Free(e);
+ }
+ ReleaseList(v->ArpTable);
+}
+
+// Comparison of the ARP waiting table entry
+int CompareArpWaitTable(void *p1, void *p2)
+{
+ ARP_WAIT *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(ARP_WAIT **)p1;
+ e2 = *(ARP_WAIT **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->IpAddress > e2->IpAddress)
+ {
+ return 1;
+ }
+ else if (e1->IpAddress < e2->IpAddress)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Comparison of the ARP table entry
+int CompareArpTable(void *p1, void *p2)
+{
+ ARP_ENTRY *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(ARP_ENTRY **)p1;
+ e2 = *(ARP_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->IpAddress > e2->IpAddress)
+ {
+ return 1;
+ }
+ else if (e1->IpAddress < e2->IpAddress)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Initialize the virtual host
+bool VirtualInit(VH *v)
+{
+ // Initialize the log
+ v->Logger = NULL;
+
+ LockVirtual(v);
+ {
+ // Initialize
+ v->Cancel = NewCancel();
+ v->SendQueue = NewQueue();
+ }
+ UnlockVirtual(v);
+
+ // Counter reset
+ v->Counter->c = 0;
+ v->DhcpId = 0;
+
+ // Initialize the ARP table
+ InitArpTable(v);
+
+ // Initialize the ARP waiting table
+ InitArpWaitTable(v);
+
+ // Initialize the IP waiting table
+ InitIpWaitTable(v);
+
+ // Initialize the IP combining list
+ InitIpCombineList(v);
+
+ // Initialize the NAT
+ InitNat(v);
+
+ // Initialize the DHCP server
+ InitDhcpServer(v);
+
+ // Other initialization
+ v->flag1 = false;
+ v->NextArpTablePolling = Tick64() + (UINT64)ARP_ENTRY_POLLING_TIME;
+ v->CurrentIpQuota = 0;
+ v->Active = true;
+
+ return true;
+}
+bool VirtualPaInit(SESSION *s)
+{
+ VH *v;
+ // Validate arguments
+ if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
+ {
+ return false;
+ }
+
+ return VirtualInit(v);
+}
+
+// Get the cancel object of the virtual host
+CANCEL *VirtualPaGetCancel(SESSION *s)
+{
+ VH *v;
+ // Validate arguments
+ if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
+ {
+ return NULL;
+ }
+
+ AddRef(v->Cancel->ref);
+ return v->Cancel;
+}
+
+// Get the next packet from the virtual host
+UINT VirtualGetNextPacket(VH *v, void **data)
+{
+ UINT ret = 0;
+
+START:
+ // Examine the transmission queue
+ LockQueue(v->SendQueue);
+ {
+ BLOCK *block = GetNext(v->SendQueue);
+
+ if (block != NULL)
+ {
+ // There is a packet
+ ret = block->Size;
+ *data = block->Buf;
+ // Discard the structure
+ Free(block);
+ }
+ }
+ UnlockQueue(v->SendQueue);
+
+ if (ret == 0)
+ {
+ LockVirtual(v);
+ {
+ v->Now = Tick64();
+ // Polling process
+ VirtualPolling(v);
+ }
+ UnlockVirtual(v);
+ if (v->SendQueue->num_item != 0)
+ {
+ goto START;
+ }
+ }
+
+ return ret;
+}
+UINT VirtualPaGetNextPacket(SESSION *s, void **data)
+{
+ VH *v;
+ // Validate arguments
+ if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
+ {
+ return INFINITE;
+ }
+
+ return VirtualGetNextPacket(v, data);
+}
+
+// Polling process (Always called once in a SessionMain loop)
+void VirtualPolling(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // DHCP polling
+ PollingDhcpServer(v);
+
+ // NAT polling
+ PoolingNat(v);
+
+ // Clear the old ARP table entries
+ PollingArpTable(v);
+
+ // Poll the ARP waiting list
+ PollingArpWaitTable(v);
+
+ // Poll the IP waiting list
+ PollingIpWaitTable(v);
+
+ // Poll the IP combining list
+ PollingIpCombine(v);
+
+ // Beacon transmission procedure
+ PollingBeacon(v);
+}
+
+// Beacon transmission procedure
+void PollingBeacon(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (v->LastSendBeacon == 0 ||
+ ((v->LastSendBeacon + BEACON_SEND_INTERVAL) <= Tick64()))
+ {
+ v->LastSendBeacon = Tick64();
+
+ SendBeacon(v);
+ }
+}
+
+// Send a Layer-2 packet
+void VirtualLayer2Send(VH *v, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
+{
+ MAC_HEADER *mac_header;
+ UCHAR *buf;
+ BLOCK *block;
+ // Validate arguments
+ if (v == NULL || dest_mac == NULL || src_mac == NULL || data == NULL || size > (MAX_PACKET_SIZE - sizeof(MAC_HEADER)))
+ {
+ return;
+ }
+
+ // Create buffer
+ buf = Malloc(MAC_HEADER_SIZE + size);
+
+ // MAC header
+ mac_header = (MAC_HEADER *)&buf[0];
+ Copy(mac_header->DestAddress, dest_mac, 6);
+ Copy(mac_header->SrcAddress, src_mac, 6);
+ mac_header->Protocol = Endian16(protocol);
+
+ // Copy data
+ Copy(&buf[sizeof(MAC_HEADER)], data, size);
+
+ // Size
+ size += sizeof(MAC_HEADER);
+
+ // Generate the packet
+ block = NewBlock(buf, size, 0);
+
+ // Insert into the queue
+ LockQueue(v->SendQueue);
+ {
+ InsertQueue(v->SendQueue, block);
+ }
+ UnlockQueue(v->SendQueue);
+
+ // Cancel
+ Cancel(v->Cancel);
+}
+
+// Send an IP packet (with automatic fragmentation)
+void SendIp(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size)
+{
+ SendIpEx(v, dest_ip, src_ip, protocol, data, size, 0);
+}
+void SendIpEx(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size, UCHAR ttl)
+{
+ UINT mss;
+ UCHAR *buf;
+ USHORT offset;
+ USHORT id;
+ USHORT total_size;
+ UINT size_of_this_packet;
+ // Validate arguments
+ if (v == NULL || data == NULL || size == 0 || size > MAX_IP_DATA_SIZE_TOTAL)
+ {
+ return;
+ }
+
+ // Maximum segment size
+ mss = v->IpMss;
+
+ // Buffer
+ buf = (UCHAR *)data;
+
+ // ID
+ id = (v->NextId++);
+
+ // Total size
+ total_size = (USHORT)size;
+
+ // Start to split
+ offset = 0;
+
+ while (true)
+ {
+ bool last_packet = false;
+ // Gets the size of this packet
+ size_of_this_packet = MIN((USHORT)mss, (total_size - offset));
+ if ((offset + (USHORT)size_of_this_packet) == total_size)
+ {
+ last_packet = true;
+ }
+
+ // Transmit the fragmented packet
+ SendFragmentedIp(v, dest_ip, src_ip, id,
+ total_size, offset, protocol, buf + offset, size_of_this_packet, NULL, ttl);
+ if (last_packet)
+ {
+ break;
+ }
+
+ offset += (USHORT)size_of_this_packet;
+ }
+}
+
+// Reserve to send the fragmented IP packet
+void SendFragmentedIp(VH *v, UINT dest_ip, UINT src_ip, USHORT id, USHORT total_size, USHORT offset, UCHAR protocol, void *data, UINT size, UCHAR *dest_mac, UCHAR ttl)
+{
+ UCHAR *buf;
+ IPV4_HEADER *ip;
+ ARP_ENTRY *arp;
+ // Validate arguments
+ if (v == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Memory allocation
+ buf = Malloc(size + IP_HEADER_SIZE);
+ ip = (IPV4_HEADER *)&buf[0];
+
+ // IP header construction
+ ip->VersionAndHeaderLength = 0;
+ IPV4_SET_VERSION(ip, 4);
+ IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
+ ip->TypeOfService = DEFAULT_IP_TOS;
+ ip->TotalLength = Endian16((USHORT)(size + IP_HEADER_SIZE));
+ ip->Identification = Endian16(id);
+ ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
+ IPV4_SET_OFFSET(ip, (offset / 8));
+ if ((offset + size) >= total_size)
+ {
+ IPV4_SET_FLAGS(ip, 0x00);
+ }
+ else
+ {
+ IPV4_SET_FLAGS(ip, 0x01);
+ }
+ ip->TimeToLive = (ttl == 0 ? DEFAULT_IP_TTL : ttl);
+ ip->Protocol = protocol;
+ ip->Checksum = 0;
+ ip->SrcIP = src_ip;
+ ip->DstIP = dest_ip;
+
+ // Checksum calculation
+ ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
+
+ // Data copy
+ Copy(buf + IP_HEADER_SIZE, data, size);
+
+ if (dest_mac == NULL)
+ {
+ if (ip->DstIP == 0xffffffff ||
+ (IsInNetwork(ip->DstIP, v->HostIP, v->HostMask) && (ip->DstIP & (~v->HostMask)) == (~v->HostMask)))
+ {
+ // Broadcast address
+ dest_mac = broadcast;
+ }
+ else
+ {
+ // Send an ARP query if the destination MAC address is unknown
+ arp = SearchArpTable(v, dest_ip);
+ if (arp != NULL)
+ {
+ dest_mac = arp->MacAddress;
+ }
+ }
+ }
+ if (dest_mac != NULL)
+ {
+ // Send the packet immediately
+ VirtualIpSend(v, dest_mac, buf, size + IP_HEADER_SIZE);
+
+ // Packet data may be released
+ Free(buf);
+ }
+ else
+ {
+ // Because this packet still can not be transferred, add it to the IP waiting table
+ InsertIpWaitTable(v, dest_ip, src_ip, buf, size + IP_HEADER_SIZE);
+
+ // Issue an ARP
+ SendArp(v, dest_ip);
+ }
+}
+
+// Send an IP packet (fragmented)
+void VirtualIpSend(VH *v, UCHAR *dest_mac, void *data, UINT size)
+{
+ // Validate arguments
+ if (v == NULL || dest_mac == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Transmission
+ VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_IPV4, data, size);
+}
+
+// Send an ARP request packet
+void VirtualArpSendRequest(VH *v, UINT dest_ip)
+{
+ ARPV4_HEADER arp;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Build the ARP header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_REQUEST);
+ Copy(arp.SrcAddress, v->MacAddress, 6);
+ arp.SrcIP = v->HostIP;
+ Zero(&arp.TargetAddress, 6);
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
+}
+
+// Send an ARP response packet
+void VirtualArpSendResponse(VH *v, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
+{
+ ARPV4_HEADER arp;
+ // Validate arguments
+ if (v == NULL || dest_mac == NULL)
+ {
+ return;
+ }
+
+ // Build the ARP header
+ arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
+ arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
+ arp.HardwareSize = 6;
+ arp.ProtocolSize = 4;
+ arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
+ Copy(arp.SrcAddress, v->MacAddress, 6);
+ Copy(arp.TargetAddress, dest_mac, 6);
+ arp.SrcIP = src_ip;
+ arp.TargetIP = dest_ip;
+
+ // Transmission
+ VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(ARPV4_HEADER));
+}
+
+// An ARP request packet was received
+void VirtualArpResponseRequest(VH *v, PKT *packet)
+{
+ ARPV4_HEADER *arp;
+ // Validate arguments
+ if (v == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ arp = packet->L3.ARPv4Header;
+
+ // Memory the information of the host IP address and the MAC address of the other party
+ ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
+
+ // Search whether it matches with the IP address of this host
+ if (v->HostIP == arp->TargetIP)
+ {
+ // Respond since the match
+ VirtualArpSendResponse(v, arp->SrcAddress, arp->SrcIP, v->HostIP);
+ return;
+ }
+ // Do nothing if it doesn't match
+}
+
+// An ARP response packet is received
+void VirtualArpResponseReceived(VH *v, PKT *packet)
+{
+ ARPV4_HEADER *arp;
+ // Validate arguments
+ if (v == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ arp = packet->L3.ARPv4Header;
+
+ // Regard this information as known information
+ ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
+}
+
+// Received an ARP packet
+void VirtualArpReceived(VH *v, PKT *packet)
+{
+ ARPV4_HEADER *arp;
+ // Validate arguments
+ if (v == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ arp = packet->L3.ARPv4Header;
+
+ if (Endian16(arp->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET)
+ {
+ // Ignore if hardware type is other than Ethernet
+ return;
+ }
+ if (Endian16(arp->ProtocolType) != MAC_PROTO_IPV4)
+ {
+ // Ignore if the protocol type is a non-IPv4
+ return;
+ }
+ if (arp->HardwareSize != 6 || arp->ProtocolSize != 4)
+ {
+ // Ignore because the size of protocol address or hardware address is invalid
+ return;
+ }
+ // Check the source MAC address
+ if (Cmp(arp->SrcAddress, packet->MacAddressSrc, 6) != 0)
+ {
+ // MAC address in the MAC header and the MAC address of the ARP packet are different
+ return;
+ }
+
+ switch (Endian16(arp->Operation))
+ {
+ case ARP_OPERATION_REQUEST: // ARP request
+ VirtualArpResponseRequest(v, packet);
+ break;
+
+ case ARP_OPERATION_RESPONSE: // ARP response
+ VirtualArpResponseReceived(v, packet);
+ break;
+ }
+}
+
+// Release the DHCP server
+void FreeDhcpServer(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Remove the all lease entries
+ for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
+ {
+ DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
+ FreeDhcpLease(d);
+ }
+
+ ReleaseList(v->DhcpLeaseList);
+ v->DhcpLeaseList = NULL;
+}
+
+// Initialize the DHCP server
+void InitDhcpServer(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Create a list
+ v->DhcpLeaseList = NewList(CompareDhcpLeaseList);
+}
+
+// Search for a DHCP lease item by the IP address
+DHCP_LEASE *SearchDhcpLeaseByIp(VH *v, UINT ip)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
+ {
+ DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
+ if (d->IpAddress == ip)
+ {
+ return d;
+ }
+ }
+
+ return NULL;
+}
+
+// Search for a DHCP lease item by the MAC address
+DHCP_LEASE *SearchDhcpLeaseByMac(VH *v, UCHAR *mac)
+{
+ DHCP_LEASE *d, t;
+ // Validate arguments
+ if (v == NULL || mac == NULL)
+ {
+ return NULL;
+ }
+
+ Copy(&t.MacAddress, mac, 6);
+ d = Search(v->DhcpLeaseList, &t);
+
+ return d;
+}
+
+// Release the DHCP lease item
+void FreeDhcpLease(DHCP_LEASE *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Free(d->Hostname);
+ Free(d);
+}
+
+// Create a DHCP lease item
+DHCP_LEASE *NewDhcpLease(UINT expire, UCHAR *mac_address, UINT ip, UINT mask, char *hostname)
+{
+ DHCP_LEASE *d;
+ // Validate arguments
+ if (mac_address == NULL || hostname == NULL)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(DHCP_LEASE));
+ d->LeasedTime = (UINT64)Tick64();
+ if (expire == INFINITE)
+ {
+ d->ExpireTime = INFINITE;
+ }
+ else
+ {
+ d->ExpireTime = d->LeasedTime + (UINT64)expire;
+ }
+ d->IpAddress = ip;
+ d->Mask = mask;
+ d->Hostname = CopyStr(hostname);
+ Copy(d->MacAddress, mac_address, 6);
+
+
+ return d;
+}
+
+// Comparison of the items in the DHCP list
+int CompareDhcpLeaseList(void *p1, void *p2)
+{
+ DHCP_LEASE *d1, *d2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ d1 = *(DHCP_LEASE **)p1;
+ d2 = *(DHCP_LEASE **)p2;
+ if (d1 == NULL || d2 == NULL)
+ {
+ return 0;
+ }
+
+ return Cmp(d1->MacAddress, d2->MacAddress, 6);
+}
+
+// Poll the DHCP server
+void PollingDhcpServer(VH *v)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (v->LastDhcpPolling != 0)
+ {
+ if ((v->LastDhcpPolling + (UINT64)DHCP_POLLING_INTERVAL) > v->Now &&
+ v->LastDhcpPolling < v->Now)
+ {
+ return;
+ }
+ }
+ v->LastDhcpPolling = v->Now;
+
+ // Remove expired entries
+FIRST_LIST:
+ for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
+ {
+ DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
+
+ if (d->ExpireTime < v->Now)
+ {
+ FreeDhcpLease(d);
+ Delete(v->DhcpLeaseList, d);
+ goto FIRST_LIST;
+ }
+ }
+}
+
+// Correspond to the DHCP REQUEST
+UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip)
+{
+ UINT ret;
+ // Validate arguments
+ if (v == NULL || mac == NULL)
+ {
+ return 0;
+ }
+
+ ret = ServeDhcpDiscover(v, mac, request_ip);
+ if (ret != request_ip)
+ {
+ if (request_ip != 0)
+ {
+ // Raise an error if the requested IP address cannot to be assigned
+ return 0;
+ }
+ }
+
+ return ret;
+}
+
+// Correspond to the DHCP DISCOVER
+UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (v == NULL || mac == NULL)
+ {
+ return 0;
+ }
+
+ if (request_ip != 0)
+ {
+ // IP address is specified
+ DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip);
+ if (d != NULL)
+ {
+ // If an entry for the same IP address already exists,
+ // check whether it is a request from the same MAC address
+ if (Cmp(mac, d->MacAddress, 6) == 0)
+ {
+ // Examine whether the specified IP address is within the range of assignment
+ if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
+ Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
+ {
+ // Accept if within the range
+ ret = request_ip;
+ }
+ }
+ }
+ else
+ {
+ // Examine whether the specified IP address is within the range of assignment
+ if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
+ Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
+ {
+ // Accept if within the range
+ ret = request_ip;
+ }
+ else
+ {
+ // Propose an IP in the range since it's a Discover although It is out of range
+ }
+ }
+ }
+
+ if (ret == 0)
+ {
+ // If there is any entry with the same MAC address
+ // that are already registered, use it with priority
+ DHCP_LEASE *d = SearchDhcpLeaseByMac(v, mac);
+ if (d != NULL)
+ {
+ // Examine whether the found IP address is in the allocation region
+ if (Endian32(v->DhcpIpStart) <= Endian32(d->IpAddress) &&
+ Endian32(d->IpAddress) <= Endian32(v->DhcpIpEnd))
+ {
+ // Use the IP address if it's found within the range
+ ret = d->IpAddress;
+ }
+ }
+ }
+
+ if (ret == 0)
+ {
+ // Take an appropriate IP addresses that can be assigned newly
+ ret = GetFreeDhcpIpAddress(v);
+ }
+
+ return ret;
+}
+
+// Take an appropriate IP addresses that can be assigned newly
+UINT GetFreeDhcpIpAddress(VH *v)
+{
+ UINT ip_start, ip_end;
+ UINT i;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return 0;
+ }
+
+ ip_start = Endian32(v->DhcpIpStart);
+ ip_end = Endian32(v->DhcpIpEnd);
+
+ for (i = ip_start; i <= ip_end;i++)
+ {
+ UINT ip = Endian32(i);
+ if (SearchDhcpLeaseByIp(v, ip) == NULL)
+ {
+ // A free IP address is found
+ return ip;
+ }
+ }
+
+ // There is no free address
+ return 0;
+}
+
+// Virtual DHCP Server
+void VirtualDhcpServer(VH *v, PKT *p)
+{
+ DHCPV4_HEADER *dhcp;
+ UCHAR *data;
+ UINT size;
+ UINT dhcp_header_size;
+ UINT dhcp_data_offset;
+ UINT tran_id;
+ UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
+ bool ok;
+ DHCP_OPTION_LIST *opt;
+ // Validate arguments
+ if (v == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (v->NativeNat != NULL)
+ {
+ if (Cmp(p->MacAddressSrc, v->NativeNat->CurrentMacAddress, 6) == 0)
+ {
+ // DHCP server is kept from responding for the native NAT interface
+ // ** Not be needed to return yet **
+ //return;
+ }
+ }
+
+ dhcp = p->L7.DHCPv4Header;
+
+ tran_id = Endian32(dhcp->TransactionId);
+
+ // Get the DHCP data and size
+ dhcp_header_size = sizeof(DHCPV4_HEADER);
+ dhcp_data_offset = (UINT)(((UCHAR *)p->L7.DHCPv4Header) - ((UCHAR *)p->MacHeader) + dhcp_header_size);
+ data = ((UCHAR *)dhcp) + dhcp_header_size;
+ size = p->PacketSize - dhcp_data_offset;
+ if (dhcp_header_size < 5)
+ {
+ // Data size is invalid
+ return;
+ }
+
+ // Search for Magic Cookie
+ ok = false;
+ while (size >= 5)
+ {
+ if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
+ {
+ // Found
+ data += 4;
+ size -= 4;
+ ok = true;
+ break;
+ }
+ data++;
+ size--;
+ }
+
+ if (ok == false)
+ {
+ // The packet is invalid
+ return;
+ }
+
+ // Parse DHCP options list
+ opt = ParseDhcpOptionList(data, size);
+ if (opt == NULL)
+ {
+ // The packet is invalid
+ return;
+ }
+
+ if (StartWith(opt->Hostname, NN_HOSTNAME_STARTWITH))
+ {
+ Free(opt);
+ return;
+ }
+
+ if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST || opt->Opcode == DHCP_INFORM))
+ {
+ // Operate as the server
+ UINT ip = 0;
+
+ if (opt->RequestedIp == 0)
+ {
+ opt->RequestedIp = p->L3.IPv4Header->SrcIP;
+ }
+ if (opt->Opcode == DHCP_DISCOVER)
+ {
+ // Return an IP address that can be used
+ ip = ServeDhcpDiscover(v, p->MacAddressSrc, opt->RequestedIp);
+ }
+ else if (opt->Opcode == DHCP_REQUEST)
+ {
+ // Determine the IP address
+ ip = ServeDhcpRequest(v, p->MacAddressSrc, opt->RequestedIp);
+ }
+
+ if (ip != 0 || opt->Opcode == DHCP_INFORM)
+ {
+ // Respond if there is providable IP address
+
+ if (opt->Opcode == DHCP_REQUEST)
+ {
+ DHCP_LEASE *d;
+ char mac[MAX_SIZE];
+ char str[MAX_SIZE];
+ // Remove old records with the same IP address
+ d = SearchDhcpLeaseByIp(v, ip);
+ if (d != NULL)
+ {
+ FreeDhcpLease(d);
+ Delete(v->DhcpLeaseList, d);
+ }
+
+ // Create a new entry
+ d = NewDhcpLease(v->DhcpExpire, p->MacAddressSrc,
+ ip, v->DhcpMask,
+ opt->Hostname);
+ d->Id = ++v->DhcpId;
+ Add(v->DhcpLeaseList, d);
+ MacToStr(mac, sizeof(mac), d->MacAddress);
+
+ IPToStr32(str, sizeof(str), d->IpAddress);
+
+ NLog(v, "LH_NAT_DHCP_CREATED", d->Id, mac, str, d->Hostname, v->DhcpExpire / 1000);
+ }
+
+ // Respond
+ if (true)
+ {
+ DHCP_OPTION_LIST ret;
+ LIST *o;
+ Zero(&ret, sizeof(ret));
+
+ ret.Opcode = (opt->Opcode == DHCP_DISCOVER ? DHCP_OFFER : DHCP_ACK);
+ ret.ServerAddress = v->HostIP;
+ if (v->DhcpExpire == INFINITE)
+ {
+ ret.LeaseTime = INFINITE;
+ }
+ else
+ {
+ ret.LeaseTime = Endian32(v->DhcpExpire / 1000);
+ }
+
+ if (opt->Opcode == DHCP_INFORM)
+ {
+ ret.LeaseTime = 0;
+ }
+
+ StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
+ ret.SubnetMask = v->DhcpMask;
+ ret.DnsServer = v->DhcpDns;
+ ret.DnsServer2 = v->DhcpDns2;
+ ret.Gateway = v->DhcpGateway;
+
+ if (opt->Opcode != DHCP_INFORM)
+ {
+ char client_mac[MAX_SIZE];
+ char client_ip[64];
+ IP ips;
+ BinToStr(client_mac, sizeof(client_mac), p->MacAddressSrc, 6);
+ UINTToIP(&ips, ip);
+ IPToStr(client_ip, sizeof(client_ip), &ips);
+ Debug("DHCP %s : %s given %s\n",
+ ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
+ client_mac, client_ip);
+ }
+
+ // Build a DHCP option
+ o = BuildDhcpOption(&ret);
+ if (o != NULL)
+ {
+ BUF *b = BuildDhcpOptionsBuf(o);
+ if (b != NULL)
+ {
+ UINT dest_ip = p->L3.IPv4Header->SrcIP;
+ if (dest_ip == 0)
+ {
+ dest_ip = 0xffffffff;
+ }
+ // Transmission
+ VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
+ ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize);
+
+ // Release the memory
+ FreeBuf(b);
+ }
+ FreeDhcpOptions(o);
+ }
+ }
+ }
+ else
+ {
+ // There is no IP address that can be provided
+ DHCP_OPTION_LIST ret;
+ LIST *o;
+ Zero(&ret, sizeof(ret));
+
+ ret.Opcode = DHCP_NACK;
+ ret.ServerAddress = v->HostIP;
+ StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
+ ret.SubnetMask = v->DhcpMask;
+
+ // Build the DHCP option
+ o = BuildDhcpOption(&ret);
+ if (o != NULL)
+ {
+ BUF *b = BuildDhcpOptionsBuf(o);
+ if (b != NULL)
+ {
+ UINT dest_ip = p->L3.IPv4Header->SrcIP;
+ if (dest_ip == 0)
+ {
+ dest_ip = 0xffffffff;
+ }
+ // Transmission
+ VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
+ ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize);
+
+ // Release the memory
+ FreeBuf(b);
+ }
+ FreeDhcpOptions(o);
+ }
+ }
+ }
+
+ // Release the memory
+ Free(opt);
+}
+
+// Submit the DHCP response packet
+void VirtualDhcpSend(VH *v, UINT tran_id, UINT dest_ip, UINT dest_port,
+ UINT new_ip, UCHAR *client_mac, BUF *b, UINT hw_type, UINT hw_addr_size)
+{
+ UINT blank_size = 128 + 64;
+ UINT dhcp_packet_size;
+ UINT magic = Endian32(DHCP_MAGIC_COOKIE);
+ DHCPV4_HEADER *dhcp;
+ void *magic_cookie_addr;
+ void *buffer_addr;
+ // Validate arguments
+ if (v == NULL || b == NULL)
+ {
+ return;
+ }
+
+ // Calculate the DHCP packet size
+ dhcp_packet_size = blank_size + sizeof(DHCPV4_HEADER) + sizeof(magic) + b->Size;
+
+ if (dhcp_packet_size < DHCP_MIN_SIZE)
+ {
+ // Padding
+ dhcp_packet_size = DHCP_MIN_SIZE;
+ }
+
+ // Create a header
+ dhcp = ZeroMalloc(dhcp_packet_size);
+
+ dhcp->OpCode = 2;
+ dhcp->HardwareType = hw_type;
+ dhcp->HardwareAddressSize = hw_addr_size;
+ dhcp->Hops = 0;
+ dhcp->TransactionId = Endian32(tran_id);
+ dhcp->Seconds = 0;
+ dhcp->Flags = 0;
+ dhcp->YourIP = new_ip;
+ dhcp->ServerIP = v->HostIP;
+ Copy(dhcp->ClientMacAddress, client_mac, 6);
+
+ // Calculate the address
+ magic_cookie_addr = (((UCHAR *)dhcp) + sizeof(DHCPV4_HEADER) + blank_size);
+ buffer_addr = ((UCHAR *)magic_cookie_addr) + sizeof(magic);
+
+ // Magic Cookie
+ Copy(magic_cookie_addr, &magic, sizeof(magic));
+
+ // Buffer
+ Copy(buffer_addr, b->Buf, b->Size);
+
+ // Transmission
+ SendUdp(v, dest_ip, dest_port, v->HostIP, NAT_DHCP_SERVER_PORT, dhcp, dhcp_packet_size);
+
+ Free(dhcp);
+}
+
+// Virtual host: Process the Layer2
+void VirtualLayer2(VH *v, PKT *packet)
+{
+ bool ok;
+ // Validate arguments
+ if (packet == NULL || v == NULL)
+ {
+ return;
+ }
+
+ // Packet filter
+ if (VirtualLayer2Filter(v, packet) == false)
+ {
+ // Packet was ignored
+ return;
+ }
+
+ ok = false;
+ if (packet->TypeL3 == L3_IPV4 && packet->TypeL4 == L4_UDP && packet->TypeL7 == L7_DHCPV4)
+ {
+ if (v->UseDhcp)
+ {
+ // A special treatment on the DHCP packet
+ if (packet->BroadcastPacket || Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
+ {
+ // Virtual DHCP server processing
+ VirtualDhcpServer(v, packet);
+ ok = true;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ // The process for each supported protocol
+ switch (packet->TypeL3)
+ {
+ case L3_ARPV4: // ARPv4
+ VirtualArpReceived(v, packet);
+ break;
+
+ case L3_IPV4: // IPv4
+ VirtualIpReceived(v, packet);
+ break;
+ }
+ }
+}
+
+// Packet filter (Blocking packets to other than me)
+bool VirtualLayer2Filter(VH *v, PKT *packet)
+{
+ // Validate arguments
+ if (v == NULL || packet == NULL)
+ {
+ return false;
+ }
+
+ // Pass through if broadcast packet
+ if (packet->BroadcastPacket)
+ {
+ return true;
+ }
+
+ // Ignore if the sender of the packet is myself
+ if (Cmp(packet->MacAddressSrc, v->MacAddress, 6) == 0)
+ {
+ return false;
+ }
+ // Pass through in the case of a packet addressed to me
+ if (Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
+ {
+ return true;
+ }
+
+ // Discard if the other packets
+ return false;
+}
+
+// The virtual host is made to receive a packet
+bool VirtualPutPacket(VH *v, void *data, UINT size)
+{
+ if (data == NULL)
+ {
+ // Flush
+ v->flag1 = false;
+
+ if (v->NativeNat != NULL)
+ {
+ if (v->NativeNat->SendStateChanged)
+ {
+ TUBE *halt_tube = NULL;
+
+ Lock(v->NativeNat->Lock);
+ {
+ if (v->NativeNat->HaltTube != NULL)
+ {
+ halt_tube = v->NativeNat->HaltTube;
+
+ AddRef(halt_tube->Ref);
+ }
+ }
+ Unlock(v->NativeNat->Lock);
+
+ if (halt_tube != NULL)
+ {
+ TubeFlushEx(halt_tube, true);
+
+ v->NativeNat->SendStateChanged = false;
+
+ ReleaseTube(halt_tube);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Interpret the received packet
+ PKT *packet = ParsePacket(data, size);
+
+ if (v->flag1 == false)
+ {
+ v->flag1 = true;
+ v->Now = Tick64();
+ }
+
+ // Lock the entire virtual machine in here
+ LockVirtual(v);
+ {
+ if (packet != NULL)
+ {
+ // Process the Layer-2
+ VirtualLayer2(v, packet);
+
+ // Release the packet structure
+ FreePacket(packet);
+ }
+ }
+ UnlockVirtual(v);
+
+ Free(data);
+ }
+
+ return true;
+}
+bool VirtualPaPutPacket(SESSION *s, void *data, UINT size)
+{
+ VH *v;
+ // Validate arguments
+ if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
+ {
+ return false;
+ }
+
+ return VirtualPutPacket(v, data, size);
+}
+
+// Get the options for the virtual host
+void GetVirtualHostOption(VH *v, VH_OPTION *o)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ LockVirtual(v);
+ {
+ Zero(o, sizeof(VH_OPTION));
+
+ // MAC address
+ Copy(o->MacAddress, v->MacAddress, 6);
+
+ // Host information
+ UINTToIP(&o->Ip, v->HostIP);
+ UINTToIP(&o->Mask, v->HostMask);
+
+ o->Mtu = v->Mtu;
+
+ // NAT timeout information
+ o->NatTcpTimeout = v->NatTcpTimeout / 1000;
+ o->NatUdpTimeout = v->NatUdpTimeout / 1000;
+
+ // NAT using flag
+ o->UseNat = v->UseNat;
+
+ // DHCP using flag
+ o->UseDhcp = v->UseDhcp;
+
+ // IP address range for DHCP distribution
+ UINTToIP(&o->DhcpLeaseIPStart, v->DhcpIpStart);
+ UINTToIP(&o->DhcpLeaseIPEnd, v->DhcpIpEnd);
+
+ // Subnet mask
+ UINTToIP(&o->DhcpSubnetMask, v->DhcpMask);
+
+ // Expiration date
+ if (v->DhcpExpire != INFINITE)
+ {
+ o->DhcpExpireTimeSpan = v->DhcpExpire / 1000;
+ }
+ else
+ {
+ o->DhcpExpireTimeSpan = INFINITE;
+ }
+
+ // Gateway address
+ UINTToIP(&o->DhcpGatewayAddress, v->DhcpGateway);
+
+ // DNS server address
+ UINTToIP(&o->DhcpDnsServerAddress, v->DhcpDns);
+ UINTToIP(&o->DhcpDnsServerAddress2, v->DhcpDns2);
+
+ // Domain name
+ StrCpy(o->DhcpDomainName, sizeof(o->DhcpDomainName), v->DhcpDomain);
+
+ // Save a log
+ o->SaveLog = v->SaveLog;
+ }
+ UnlockVirtual(v);
+}
+
+// Set the option to the virtual host
+void SetVirtualHostOption(VH *v, VH_OPTION *vo)
+{
+ UINT i;
+ // Validate arguments
+ if (v == NULL || vo == NULL)
+ {
+ return;
+ }
+
+ LockVirtual(v);
+ {
+ // Set the MAC address
+ for (i = 0;i < 6;i++)
+ {
+ if (vo->MacAddress[i] != 0)
+ {
+ Copy(v->MacAddress, vo->MacAddress, 6);
+ break;
+ }
+ }
+
+ // Set the host information list
+ v->HostIP = IPToUINT(&vo->Ip);
+ v->HostMask = IPToUINT(&vo->Mask);
+
+ // Set the MTU, MMS
+ v->Mtu = MIN(vo->Mtu, MAX_L3_DATA_SIZE);
+ if (v->Mtu == 0)
+ {
+ v->Mtu = MAX_L3_DATA_SIZE;
+ }
+ v->Mtu = MAX(v->Mtu, TCP_HEADER_SIZE + IP_HEADER_SIZE + MAC_HEADER_SIZE + 8);
+ v->IpMss = ((v->Mtu - IP_HEADER_SIZE) / 8) * 8;
+ v->TcpMss = ((v->IpMss - TCP_HEADER_SIZE) / 8) * 8;
+ v->UdpMss = ((v->IpMss - UDP_HEADER_SIZE) / 8) * 8;
+
+ if (vo->NatTcpTimeout != 0)
+ {
+ v->NatTcpTimeout = MIN(vo->NatTcpTimeout, 4000000) * 1000;
+ }
+ if (vo->NatUdpTimeout != 0)
+ {
+ v->NatUdpTimeout = MIN(vo->NatUdpTimeout, 4000000) * 1000;
+ }
+ v->NatTcpTimeout = MAKESURE(v->NatTcpTimeout, NAT_TCP_MIN_TIMEOUT, NAT_TCP_MAX_TIMEOUT);
+ v->NatUdpTimeout = MAKESURE(v->NatUdpTimeout, NAT_UDP_MIN_TIMEOUT, NAT_UDP_MAX_TIMEOUT);
+ Debug("Timeout: %d , %d\n", v->NatTcpTimeout, v->NatUdpTimeout);
+
+ // NAT using flag
+ v->UseNat = vo->UseNat;
+
+ // DHCP using flag
+ v->UseDhcp = vo->UseDhcp;
+
+ // Expiration date
+ if (vo->DhcpExpireTimeSpan == 0 || vo->DhcpExpireTimeSpan == INFINITE)
+ {
+ v->DhcpExpire = INFINITE;
+ }
+ else
+ {
+ v->DhcpExpire = MAKESURE(DHCP_MIN_EXPIRE_TIMESPAN,
+ MIN(vo->DhcpExpireTimeSpan * 1000, 2000000000),
+ INFINITE);
+ }
+
+ // Address range to be distributed
+ v->DhcpIpStart = IPToUINT(&vo->DhcpLeaseIPStart);
+ v->DhcpIpEnd = IPToUINT(&vo->DhcpLeaseIPEnd);
+ if (Endian32(v->DhcpIpEnd) < Endian32(v->DhcpIpStart))
+ {
+ v->DhcpIpEnd = v->DhcpIpStart;
+ }
+
+ // Subnet mask
+ v->DhcpMask = IPToUINT(&vo->DhcpSubnetMask);
+
+ // Gateway address
+ v->DhcpGateway = IPToUINT(&vo->DhcpGatewayAddress);
+
+ // DNS server address
+ v->DhcpDns = IPToUINT(&vo->DhcpDnsServerAddress);
+ v->DhcpDns2 = IPToUINT(&vo->DhcpDnsServerAddress2);
+
+ // Domain name
+ StrCpy(v->DhcpDomain, sizeof(v->DhcpDomain), vo->DhcpDomainName);
+
+ // Save a log
+ v->SaveLog = vo->SaveLog;
+ }
+ UnlockVirtual(v);
+}
+
+// Release the virtual host
+void Virtual_Free(VH *v)
+{
+ // Release the DHCP server
+ FreeDhcpServer(v);
+
+ // NAT release
+ FreeNat(v);
+
+ LockVirtual(v);
+ {
+ // Release the IP combining list
+ FreeIpCombineList(v);
+
+ // Release the IP waiting table
+ FreeIpWaitTable(v);
+
+ // Release the ARP waiting table
+ FreeArpWaitTable(v);
+
+ // Release the ARP table
+ FreeArpTable(v);
+
+ // Release the transmission queue
+ LockQueue(v->SendQueue);
+ {
+ BLOCK *block;
+
+ // Release all queues
+ while (block = GetNext(v->SendQueue))
+ {
+ FreeBlock(block);
+ }
+ }
+ UnlockQueue(v->SendQueue);
+ ReleaseQueue(v->SendQueue);
+ v->SendQueue = NULL;
+
+ // Release the cancel object
+ ReleaseCancel(v->Cancel);
+
+ v->Active = false;
+ }
+ UnlockVirtual(v);
+
+ // Release the logger
+ FreeLog(v->Logger);
+}
+void VirtualPaFree(SESSION *s)
+{
+ VH *v;
+ // Validate arguments
+ if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
+ {
+ return;
+ }
+
+ Virtual_Free(v);
+}
+
+// Release the virtual host
+void ReleaseVirtual(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (Release(v->ref) == 0)
+ {
+ CleanupVirtual(v);
+ }
+}
+
+// Lock the virtual host
+void LockVirtual(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Lock(v->lock);
+}
+
+// Unlock the virtual host
+void UnlockVirtual(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Unlock(v->lock);
+}
+
+// Cleanup the virtual host
+void CleanupVirtual(VH *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ if (v->Session != NULL)
+ {
+ ReleaseSession(v->Session);
+ }
+
+ DeleteCounter(v->Counter);
+ DeleteLock(v->lock);
+
+ Free(v);
+}
+
+// Stop the virtual host
+void StopVirtualHost(VH *v)
+{
+ SESSION *s;
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ // Get the session corresponding to the virtual host
+ LockVirtual(v);
+ {
+ s = v->Session;
+ if (s != NULL)
+ {
+ AddRef(s->ref);
+ }
+ }
+ UnlockVirtual(v);
+
+ if (s == NULL)
+ {
+ // This session is already stopped
+ return;
+ }
+
+ // Stop Session
+ StopSession(s);
+
+ ReleaseSession(s);
+}
+
+// Create a new virtual host
+VH *NewVirtualHost(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option)
+{
+ return NewVirtualHostEx(cedar, option, auth, vh_option, NULL);
+}
+VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option, NAT *nat)
+{
+ VH *v;
+ SOCK *s;
+ // Validate arguments
+ if (vh_option == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a VH
+ v = ZeroMalloc(sizeof(VH));
+ v->ref = NewRef();
+ v->lock = NewLock();
+ v->Counter = NewCounter();
+
+ v->nat = nat;
+
+ // Examine whether ICMP Raw Socket can be created
+ s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
+ if (s != NULL)
+ {
+ if (s->IsTtlSupported)
+ {
+ v->IcmpRawSocketOk = true;
+ }
+
+ ReleaseSock(s);
+ }
+
+ if (v->IcmpRawSocketOk == false)
+ {
+ if (IsIcmpApiSupported())
+ {
+ v->IcmpApiOk = true;
+ }
+ }
+
+ // Set the options
+ SetVirtualHostOption(v, vh_option);
+
+ return v;
+}
+
+// Generate a random MAC address
+void GenMacAddress(UCHAR *mac)
+{
+ UCHAR rand_data[32];
+ UINT64 now;
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return;
+ }
+
+ // Get the current time
+ now = SystemTime64();
+
+ // Generate a random number
+ Rand(rand_data, sizeof(rand_data));
+
+ // Add to the buffer
+ b = NewBuf();
+ WriteBuf(b, &now, sizeof(now));
+ WriteBuf(b, rand_data, sizeof(rand_data));
+
+ // Hash
+ Hash(hash, b->Buf, b->Size, true);
+
+ // Generate a MAC address
+ mac[0] = 0x00;
+ mac[1] = 0xAC; // AC hurray
+ mac[2] = hash[0];
+ mac[3] = hash[1];
+ mac[4] = hash[2];
+ mac[5] = hash[3];
+
+ FreeBuf(b);
+}
+
+// Get a packet of virtual host adapter
+PACKET_ADAPTER *VirtualGetPacketAdapter()
+{
+ return NewPacketAdapter(VirtualPaInit, VirtualPaGetCancel,
+ VirtualPaGetNextPacket, VirtualPaPutPacket, VirtualPaFree);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Virtual.h b/src/Cedar/Virtual.h
new file mode 100644
index 00000000..ff7be8a8
--- /dev/null
+++ b/src/Cedar/Virtual.h
@@ -0,0 +1,659 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Virtual.h
+// Header of Virtual.c
+
+#ifndef VIRTUAL_H
+#define VIRTUAL_H
+
+
+#define VIRTUAL_TCP_SEND_TIMEOUT (21 * 1000)
+
+#define NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM (60 * 1000)
+#define NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT 15
+
+#define NN_HOSTNAME_FORMAT "securenat_%s"
+#define NN_HOSTNAME_STARTWITH "securenat_"
+#define NN_CHECK_CONNECTIVITY_TIMEOUT (5 * 1000)
+#define NN_CHECK_CONNECTIVITY_INTERVAL (1 * 1000)
+
+#define NN_POLL_CONNECTIVITY_TIMEOUT (4 * 60 * 1000 + 10)
+#define NN_POLL_CONNECTIVITY_INTERVAL (1 * 60 * 1000)
+
+#define NN_MAX_QUEUE_LENGTH 10000
+#define NN_NO_NATIVE_NAT_FILENAME L"@no_native_nat_niclist.txt"
+
+#define NN_TIMEOUT_FOR_UNESTBALISHED_TCP (10 * 1000) // Time-out period of a TCP connection incomplete session
+
+// Destination host name of the connectivity test for the Internet
+// (Access the www.yahoo.com. Access the www.baidu.com from China. I am sorry.)
+#define NN_CHECK_HOSTNAME (IsEmptyStr(secure_nat_target_hostname) ? (IsUseAlternativeHostname() ? "www.baidu.com" : "www.yahoo.com") : secure_nat_target_hostname)
+
+
+// Native NAT entry
+struct NATIVE_NAT_ENTRY
+{
+ UINT Id; // ID
+ UINT Status; // Status
+ UINT Protocol; // Protocol
+ UINT SrcIp; // Source IP address
+ UINT SrcPort; // Source port number
+ UINT DestIp; // Destination IP address
+ UINT DestPort; // Destination port number
+ UINT PublicIp; // Public IP address
+ UINT PublicPort; // Public port number
+ UINT64 CreatedTime; // Connection time
+ UINT64 LastCommTime; // Last communication time
+ UINT64 TotalSent; // Total number of bytes sent
+ UINT64 TotalRecv; // Total number of bytes received
+ UINT LastSeq; // Last sequence number
+ UINT LastAck; // Last acknowledgment number
+ UINT HashCodeForSend; // Cached hash code (transmit direction)
+ UINT HashCodeForRecv; // Cached hash code (receive direction)
+};
+
+// Native NAT
+struct NATIVE_NAT
+{
+ struct VH *v; // Virtual machine
+ bool Active; // Whether currently available
+ THREAD *Thread; // Main thread
+ bool Halt; // Halting flag
+ TUBE *HaltTube; // Tube to be disconnected in order to stop
+ TUBE *HaltTube2; // Tube 2 to be disconnected in order to stop
+ TUBE *HaltTube3; // Tube 3 to be disconnected in order to stop
+ LOCK *Lock; // Lock
+ EVENT *HaltEvent; // Halting event
+ UINT LastInterfaceIndex; // Index number of the interface that is used for attempting last
+ UINT LastInterfaceDeviceHash; // Hash value of the device list at the time of the last attempted
+ UINT NextWaitTimeForRetry; // Time for waiting next time for the device list enumeration
+ UINT FailedCount; // The number of failed searching for the interface
+ UINT LastHostAddressHash; // Hash of the last host IP address
+ DHCP_OPTION_LIST CurrentDhcpOptions; // Current DHCP options
+ QUEUE *SendQueue; // Transmission queue
+ QUEUE *RecvQueue; // Reception queue
+ CANCEL *Cancel; // Cancel object (Hit if there is a received packet)
+ LOCK *CancelLock; // Lock of the cancel object
+ HASH_LIST *NatTableForSend; // Native NAT table (for transmission)
+ HASH_LIST *NatTableForRecv; // Native NAT table (for reception)
+ UINT PublicIP; // Public IP
+ USHORT NextId; // Next IP packet ID
+ bool SendStateChanged; // Transmission state changed
+ LIST *IpCombine; // IP combining list
+ UINT CurrentIpQuota; // Current IP combining quota
+ UCHAR CurrentMacAddress[6]; // Current MAC address
+};
+
+// ARP entry
+struct ARP_ENTRY
+{
+ UINT IpAddress; // IP address
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT64 Created; // Creation date and time
+ UINT64 Expire; // Expiration date
+};
+
+// ARP waiting list
+struct ARP_WAIT
+{
+ UINT IpAddress; // IP address trying to solve
+ UINT NextTimeoutTimeValue; // Next time before timing out
+ UINT64 TimeoutTime; // Current Time-out of transmission
+ UINT64 GiveupTime; // Time to give up the transmission
+};
+
+// IP waiting list
+struct IP_WAIT
+{
+ UINT DestIP; // Destination IP address
+ UINT SrcIP; // Source IP address
+ UINT64 Expire; // Storage life
+ void *Data; // Data
+ UINT Size; // Size
+};
+
+// IP partial list
+struct IP_PART
+{
+ UINT Offset; // Offset
+ UINT Size; // Size
+};
+
+// IP restore list
+struct IP_COMBINE
+{
+ UINT DestIP; // Destination IP address
+ UINT SrcIP; // Source IP address
+ USHORT Id; // IP packet ID
+ UCHAR Ttl; // TTL
+ UINT64 Expire; // Storage life
+ void *Data; // Packet data
+ UINT DataReserved; // Area reserved for data
+ UINT Size; // Packet size (Total)
+ LIST *IpParts; // IP partial list
+ UCHAR Protocol; // Protocol number
+ bool MacBroadcast; // Broadcast packets at the MAC level
+ UCHAR *HeadIpHeaderData; // Data of the IP header of the top
+ UINT HeadIpHeaderDataSize; // Data size of the IP header of the top
+ bool SrcIsLocalMacAddr; // Source MAC address is on the same machine
+ UINT MaxL3Size; // Largest L3 size
+};
+
+#define IP_COMBINE_INITIAL_BUF_SIZE (MAX_IP_DATA_SIZE) // Initial buffer size
+
+// NAT session table
+struct NAT_ENTRY
+{
+ // TCP | UDP common items
+ struct VH *v; // Virtual machine
+ UINT Id; // ID
+ LOCK *lock; // Lock
+ UINT Protocol; // Protocol
+ UINT SrcIp; // Source IP address
+ UINT SrcPort; // Source port number
+ UINT DestIp; // Destination IP address
+ UINT DestPort; // Destination port number
+ UINT PublicIp; // Public IP address
+ UINT PublicPort; // Public port number
+ UINT64 CreatedTime; // Connection time
+ UINT64 LastCommTime; // Last communication time
+ SOCK *Sock; // Socket
+ bool DisconnectNow; // Flag to stop immediately
+ UINT tag1;
+ bool ProxyDns; // DNS proxy
+ UINT DestIpProxy; // Proxy DNS address
+
+ // ICMP NAT item (only for the calling ICMP API mode)
+ THREAD *IcmpThread; // ICMP query thread
+ BLOCK *IcmpQueryBlock; // Block that contains the ICMP query
+ BLOCK *IcmpResponseBlock; // Block that contains ICMP result
+ bool IcmpTaskFinished; // Flag indicating that the processing of ICMP has been completed
+ UCHAR *IcmpOriginalCopy; // Copy of the original ICMP packet
+ UINT IcmpOriginalCopySize; // The size of the copy of original ICMP packet
+
+ // DNS NAT item
+ THREAD *DnsThread; // DNS query thread
+ bool DnsGetIpFromHost; // Reverse resolution flag
+ char *DnsTargetHostName; // Target host name
+ IP DnsResponseIp; // Response IP address
+ char *DnsResponseHostName; // Response host name
+ UINT DnsTransactionId; // DNS transaction ID
+ bool DnsFinished; // DNS query completion flag
+ bool DnsOk; // DNS success flag
+ bool DnsPollingFlag; // DNS polling completion flag
+
+ // UDP item
+ QUEUE *UdpSendQueue; // UDP send queue
+ QUEUE *UdpRecvQueue; // UDP receive queue
+ bool UdpSocketCreated; // Whether an UDP socket was created
+
+ // TCP items
+ FIFO *SendFifo; // Transmission FIFO
+ FIFO *RecvFifo; // Receive FIFO
+ UINT TcpStatus; // TCP state
+ bool NatTcpCancelFlag; // TCP connection cancel flag
+ THREAD *NatTcpConnectThread; // TCP socket connection thread
+ bool TcpMakeConnectionFailed; // Failed to connect with connection thread
+ bool TcpMakeConnectionSucceed; // Successfully connected by the connection thread
+ UINT TcpSendMaxSegmentSize; // Maximum transmission segment size
+ UINT TcpRecvMaxSegmentSize; // Maximum reception segment size
+ UINT64 LastSynAckSentTime; // Time which the SYN+ACK was sent last
+ UINT SynAckSentCount; // SYN + ACK transmission times
+ UINT TcpSendWindowSize; // Transmission window size
+ UINT TcpSendCWnd; // Transmission congestion window size (/mss)
+ UINT TcpRecvWindowSize; // Receive window size
+ UINT TcpSendTimeoutSpan; // Transmission time-out period
+ UINT64 TcpLastSentTime; // Time for the last transmitted over TCP
+ UINT64 LastSentKeepAliveTime; // Time which the keep-alive ACK was sent last
+ FIFO *TcpRecvWindow; // TCP receive window
+ LIST *TcpRecvList; // TCP reception list
+ bool SendAckNext; // Send an ACK at the time of the next transmission
+ UINT LastSentWindowSize; // My window size that sent the last
+ UINT64 TcpLastRecvAckTime; // Time that the other party has received the last data in TCP
+
+ UINT64 SendSeqInit; // Initial send sequence number
+ UINT64 SendSeq; // Send sequence number
+ UINT64 RecvSeqInit; // Initial receive sequence number
+ UINT64 RecvSeq; // Receive sequence number
+
+ bool CurrentSendingMission; // Burst transmission ongoing
+ UINT SendMissionSize; // Transmission size of this time
+ bool RetransmissionUsedFlag; // Retransmission using record flag
+
+ UINT CurrentRTT; // Current RTT value
+ UINT64 CalcRTTStartTime; // RTT measurement start time
+ UINT64 CalcRTTStartValue; // RTT measurement start value
+
+ bool TcpFinished; // Data communication end flag of TCP
+ UINT64 FinSentTime; // Time which the FIN was sent last
+ UINT FinSentCount; // Number of FIN transmissions
+};
+
+
+// TCP options
+struct TCP_OPTION
+{
+ UINT MaxSegmentSize; // Maximum segment size
+ UINT WindowScaling; // Window scaling
+};
+
+// Virtual host structure
+struct VH
+{
+ REF *ref; // Reference counter
+ LOCK *lock; // Lock
+ SESSION *Session; // Session
+ CANCEL *Cancel; // Cancel object
+ QUEUE *SendQueue; // Transmission queue
+ bool Active; // Active flag
+ volatile bool HaltNat; // NAT halting flag
+ LIST *ArpTable; // ARP table
+ LIST *ArpWaitTable; // ARP waiting table
+ LIST *IpWaitTable; // IP waiting table
+ LIST *IpCombine; // IP combining table
+ UINT64 Now; // Current time
+ UINT64 NextArpTablePolling; // Next time to poll the ARP table
+ UINT Mtu; // MTU value
+ UINT IpMss; // Maximum IP data size
+ UINT TcpMss; // TCP maximum data size
+ UINT UdpMss; // UDP maximum data size
+ bool flag1; // Flag 1
+ bool flag2; // Flag 2
+ USHORT NextId; // ID of the IP packet
+ UINT CurrentIpQuota; // IP packet memory quota
+ LIST *NatTable; // NAT table
+ SOCK_EVENT *SockEvent; // Socket event
+ THREAD *NatThread; // NAT thread
+ void *TmpBuf; // Buffer that can be used temporarily
+ bool NatDoCancelFlag; // Flag of whether to hit the cancel
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ UINT HostIP; // Host IP
+ UINT HostMask; // Host subnet mask
+ UINT NatTcpTimeout; // NAT TCP timeout in seconds
+ UINT NatUdpTimeout; // NAT UDP timeout in seconds
+ bool UseNat; // NAT use flag
+ bool UseDhcp; // DHCP using flag
+ UINT DhcpIpStart; // Distribution start address
+ UINT DhcpIpEnd; // Distribution end address
+ UINT DhcpMask; // Subnet mask
+ UINT DhcpExpire; // Address distribution expiration date
+ UINT DhcpGateway; // Gateway address
+ UINT DhcpDns; // DNS server address 1
+ UINT DhcpDns2; // DNS server address 2
+ char DhcpDomain[MAX_HOST_NAME_LEN + 1]; // Assigned domain name
+ LIST *DhcpLeaseList; // DHCP lease list
+ UINT64 LastDhcpPolling; // Time which the DHCP list polled last
+ bool SaveLog; // Save a log
+ COUNTER *Counter; // Session counter
+ UINT DhcpId; // DHCP ID
+ UINT64 LastSendBeacon; // Time which the beacon has been sent last
+ LOG *Logger; // Logger
+ NAT *nat; // A reference to the NAT object
+ bool IcmpRawSocketOk; // ICMP RAW SOCKET is available
+ bool IcmpApiOk; // ICMP API is available
+ HUB_OPTION *HubOption; // Pointer to the Virtual HUB options
+
+ NATIVE_NAT *NativeNat; // Native NAT
+};
+
+// Virtual host option
+struct VH_OPTION
+{
+ char HubName[MAX_HUBNAME_LEN + 1]; // Target Virtual HUB name
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2];
+ IP Ip; // IP address
+ IP Mask; // Subnet mask
+ bool UseNat; // Use flag of NAT function
+ UINT Mtu; // MTU value
+ UINT NatTcpTimeout; // NAT TCP timeout in seconds
+ UINT NatUdpTimeout; // NAT UDP timeout in seconds
+ bool UseDhcp; // Using flag of DHCP function
+ IP DhcpLeaseIPStart; // Start of IP address range for DHCP distribution
+ IP DhcpLeaseIPEnd; // End of IP address range for DHCP distribution
+ IP DhcpSubnetMask; // DHCP subnet mask
+ UINT DhcpExpireTimeSpan; // DHCP expiration date
+ IP DhcpGatewayAddress; // Assigned gateway address
+ IP DhcpDnsServerAddress; // Assigned DNS server address 1
+ IP DhcpDnsServerAddress2; // Assigned DNS server address 2
+ char DhcpDomainName[MAX_HOST_NAME_LEN + 1]; // Assigned domain name
+ bool SaveLog; // Save a log
+};
+
+// DHCP lease entry
+struct DHCP_LEASE
+{
+ UINT Id; // ID
+ UINT64 LeasedTime; // Leased time
+ UINT64 ExpireTime; // Expiration date
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding[2]; // Padding
+ UINT IpAddress; // IP address
+ UINT Mask; // Subnet mask
+ char *Hostname; // Host name
+};
+
+// DNS query
+typedef struct NAT_DNS_QUERY
+{
+ REF *ref; // Reference counter
+ char Hostname[256]; // Host name
+ bool Ok; // Result success flag
+ IP Ip; // Result IP address
+} NAT_DNS_QUERY;
+
+// Parsed DNS query
+struct DNS_PARSED_PACKET
+{
+ UINT TransactionId;
+ char Hostname[128];
+};
+
+
+// Virtual LAN card of the virtual host
+PACKET_ADAPTER *VirtualGetPacketAdapter();
+bool VirtualPaInit(SESSION *s);
+CANCEL *VirtualPaGetCancel(SESSION *s);
+UINT VirtualPaGetNextPacket(SESSION *s, void **data);
+bool VirtualPaPutPacket(SESSION *s, void *data, UINT size);
+void VirtualPaFree(SESSION *s);
+
+bool VirtualInit(VH *v);
+UINT VirtualGetNextPacket(VH *v, void **data);
+bool VirtualPutPacket(VH *v, void *data, UINT size);
+void Virtual_Free(VH *v);
+
+VH *NewVirtualHost(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option);
+VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option, NAT *nat);
+void LockVirtual(VH *v);
+void UnlockVirtual(VH *v);
+void ReleaseVirtual(VH *v);
+void CleanupVirtual(VH *v);
+void StopVirtualHost(VH *v);
+void SetVirtualHostOption(VH *v, VH_OPTION *vo);
+void GenMacAddress(UCHAR *mac);
+void GetVirtualHostOption(VH *v, VH_OPTION *o);
+
+void VirtualLayer2(VH *v, PKT *packet);
+bool VirtualLayer2Filter(VH *v, PKT *packet);
+void VirtualArpReceived(VH *v, PKT *packet);
+void VirtualArpResponseRequest(VH *v, PKT *packet);
+void VirtualArpResponseReceived(VH *v, PKT *packet);
+void VirtualArpSendResponse(VH *v, UCHAR *dest_mac, UINT dest_ip, UINT src_ip);
+void VirtualArpSendRequest(VH *v, UINT dest_ip);
+void VirtualIpSend(VH *v, UCHAR *dest_mac, void *data, UINT size);
+void VirtualLayer2Send(VH *v, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size);
+void VirtualPolling(VH *v);
+void InitArpTable(VH *v);
+void FreeArpTable(VH *v);
+int CompareArpTable(void *p1, void *p2);
+ARP_ENTRY *SearchArpTable(VH *v, UINT ip);
+void RefreshArpTable(VH *v);
+void PollingArpTable(VH *v);
+void InsertArpTable(VH *v, UCHAR *mac, UINT ip);
+bool IsMacBroadcast(UCHAR *mac);
+bool IsMacInvalid(UCHAR *mac);
+void InitArpWaitTable(VH *v);
+void FreeArpWaitTable(VH *v);
+int CompareArpWaitTable(void *p1, void *p2);
+ARP_WAIT *SearchArpWaitTable(VH *v, UINT ip);
+void DeleteArpWaitTable(VH *v, UINT ip);
+void SendArp(VH *v, UINT ip);
+void InsertArpWaitTable(VH *v, ARP_WAIT *w);
+void PollingArpWaitTable(VH *v);
+void ArpIpWasKnown(VH *v, UINT ip, UCHAR *mac);
+void InitIpWaitTable(VH *v);
+void FreeIpWaitTable(VH *v);
+void InsertIpWaitTable(VH *v, UINT dest_ip, UINT src_ip, void *data, UINT size);
+void SendFragmentedIp(VH *v, UINT dest_ip, UINT src_ip, USHORT id, USHORT total_size, USHORT offset, UCHAR protocol, void *data, UINT size, UCHAR *dest_mac, UCHAR ttl);
+void SendIp(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size);
+void SendIpEx(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size, UCHAR ttl);
+void PollingIpWaitTable(VH *v);
+void DeleteOldIpWaitTable(VH *v);
+void SendWaitingIp(VH *v, UCHAR *mac, UINT dest_ip);
+void VirtualIpReceived(VH *v, PKT *packet);
+void InitIpCombineList(VH *v);
+void FreeIpCombineList(VH *v);
+int CompareIpCombine(void *p1, void *p2);
+void CombineIp(VH *v, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size);
+void IpReceived(VH *v, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size, bool mac_broadcast, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, bool is_local_mac, UINT max_l3_size);
+void FreeIpCombine(VH *v, IP_COMBINE *c);
+void PollingIpCombine(VH *v);
+IP_COMBINE *InsertIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac);
+IP_COMBINE *SearchIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol);
+void VirtualIcmpReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size);
+void VirtualIcmpEchoRequestReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size);
+void VirtualIcmpEchoRequestReceivedRaw(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size);
+void VirtualIcmpEchoSendResponse(VH *v, UINT src_ip, UINT dst_ip, USHORT id, USHORT seq_no, void *data, UINT size);
+void VirtualIcmpSend(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size);
+void VirtualUdpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, bool mac_broadcast, bool is_localmac, UINT max_l3_size);
+void SendUdp(VH *v, UINT dest_ip, UINT dest_port, UINT src_ip, UINT src_port, void *data, UINT size);
+UINT GetNetworkAddress(UINT addr, UINT mask);
+UINT GetBroadcastAddress(UINT addr, UINT mask);
+void GetBroadcastAddress4(IP *dst, IP *addr, IP *mask);
+bool IsInNetwork(UINT uni_addr, UINT network_addr, UINT mask);
+void UdpRecvForMe(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+void UdpRecvLlmnr(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+void UdpRecvForBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+void UdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy);
+void UdpRecvForNetBiosBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy, bool unicast);
+bool IsNetbiosRegistrationPacket(UCHAR *buf, UINT size);
+bool ProcessNetBiosNameQueryPacketForMyself(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+void EncodeNetBiosName(UCHAR *dst, char *src);
+char *CharToNetBiosStr(char c);
+void InitNat(VH *v);
+void FreeNat(VH *v);
+int CompareNat(void *p1, void *p2);
+NAT_ENTRY *SearchNat(VH *v, NAT_ENTRY *target);
+void SetNat(NAT_ENTRY *n, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT public_ip, UINT public_port);
+void DeleteNatTcp(VH *v, NAT_ENTRY *n);
+void DeleteNatUdp(VH *v, NAT_ENTRY *n);
+void DeleteNatIcmp(VH *v, NAT_ENTRY *n);
+NAT_ENTRY *CreateNatUdp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT dns_proxy_ip);
+NAT_ENTRY *CreateNatIcmp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UCHAR *original_copy, UINT original_copy_size);
+void NatThread(THREAD *t, void *param);
+void NatThreadMain(VH *v);
+bool NatTransactUdp(VH *v, NAT_ENTRY *n);
+bool NatTransactIcmp(VH *v, NAT_ENTRY *n);
+void NatIcmpThreadProc(THREAD *thread, void *param);
+void PoolingNat(VH *v);
+void PoolingNatUdp(VH *v, NAT_ENTRY *n);
+void PollingNatIcmp(VH *v, NAT_ENTRY *n);
+void VirtualTcpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size);
+void TcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *tcp, void *data, UINT size, UINT max_l3_size);
+NAT_ENTRY *CreateNatTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port);
+bool NatTransactTcp(VH *v, NAT_ENTRY *n);
+void CreateNatTcpConnectThread(VH *v, NAT_ENTRY *n);
+void NatTcpConnectThread(THREAD *t, void *p);
+void PollingNatTcp(VH *v, NAT_ENTRY *n);
+void ParseTcpOption(TCP_OPTION *o, void *data, UINT size);
+void SendTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss, void *data, UINT size);
+void DnsProxy(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+bool ParseDnsPacket(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size);
+bool ParseDnsPacketEx(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, DNS_PARSED_PACKET *parsed_result);
+bool ParseDnsQuery(char *name, UINT name_size, void *data, UINT data_size);
+void SetDnsProxyVgsHostname(char *hostname);
+UCHAR GetNextByte(BUF *b);
+bool NatTransactDns(VH *v, NAT_ENTRY *n);
+void NatDnsThread(THREAD *t, void *param);
+bool NatGetIP(IP *ip, char *hostname);
+void NatGetIPThread(THREAD *t, void *param);
+NAT_ENTRY *CreateNatDns(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port,
+ UINT transaction_id, bool dns_get_ip_from_host, char *dns_target_host_name);
+void PollingNatDns(VH *v, NAT_ENTRY *n);
+void SendNatDnsResponse(VH *v, NAT_ENTRY *n);
+void BuildDnsQueryPacket(BUF *b, char *hostname, bool ptr);
+void BuildDnsResponsePacketA(BUF *b, IP *ip);
+void BuildDnsResponsePacketPtr(BUF *b, char *hostname);
+bool ArpaToIP(IP *ip, char *str);
+BUF *BuildDnsHostName(char *hostname);
+bool CanCreateNewNatEntry(VH *v);
+void VirtualDhcpServer(VH *v, PKT *p);
+void InitDhcpServer(VH *v);
+void FreeDhcpServer(VH *v);
+void PollingDhcpServer(VH *v);
+int CompareDhcpLeaseList(void *p1, void *p2);
+DHCP_LEASE *NewDhcpLease(UINT expire, UCHAR *mac_address, UINT ip, UINT mask, char *hostname);
+void FreeDhcpLease(DHCP_LEASE *d);
+DHCP_LEASE *SearchDhcpLeaseByMac(VH *v, UCHAR *mac);
+DHCP_LEASE *SearchDhcpLeaseByIp(VH *v, UINT ip);
+UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip);
+UINT GetFreeDhcpIpAddress(VH *v);
+UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip);
+void VirtualDhcpSend(VH *v, UINT tran_id, UINT dest_ip, UINT dest_port,
+ UINT new_ip, UCHAR *client_mac, BUF *b, UINT hw_type, UINT hw_addr_size);
+void VLog(VH *v, char *str);
+void SendBeacon(VH *v);
+void PollingBeacon(VH *v);
+HUB_OPTION *NatGetHubOption(VH *v);
+UINT GetNumNatEntriesPerIp(VH *v, UINT ip, UINT protocol, bool tcp_syn_sent);
+void NatSetHubOption(VH *v, HUB_OPTION *o);
+NAT_ENTRY *GetOldestNatEntryOfIp(VH *v, UINT ip, UINT protocol);
+void DisconnectNatEntryNow(VH *v, NAT_ENTRY *e);
+
+NATIVE_NAT *NewNativeNat(VH *v);
+void FreeNativeNat(NATIVE_NAT *t);
+void NativeNatThread(THREAD *thread, void *param);
+NATIVE_STACK *NnGetNextInterface(NATIVE_NAT *t);
+
+bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube);
+void NnMainLoop(NATIVE_NAT *t, NATIVE_STACK *a);
+
+BUF *NnBuildDnsQueryPacket(char *hostname, USHORT tran_id);
+BUF *NnBuildUdpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port);
+BUF *NnBuildTcpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss);
+BUF *NnBuildIpPacket(BUF *payload, UINT src_ip, UINT dst_ip, UCHAR protocol, UCHAR ttl);
+UINT NnGenSrcPort();
+bool NnParseDnsResponsePacket(UCHAR *data, UINT size, IP *ret_ip);
+BUF *NnReadDnsRecord(BUF *buf, bool answer, USHORT *ret_type, USHORT *ret_class);
+bool NnReadDnsLabel(BUF *buf);
+void NnClearQueue(NATIVE_NAT *t);
+
+int CmpNativeNatTableForSend(void *p1, void *p2);
+int CmpNativeNatTableForRecv(void *p1, void *p2);
+UINT GetHashNativeNatTableForSend(void *p);
+UINT GetHashNativeNatTableForRecv(void *p);
+void NnSetNat(NATIVE_NAT_ENTRY *e, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT pub_ip, UINT pub_port);
+
+bool NnIsActive(VH *v);
+void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, UINT max_l3_size);
+void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *old_tcp, void *data, UINT size, UINT max_l3_size);
+void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size);
+UINT NnMapNewPublicPort(NATIVE_NAT *t, UINT protocol, UINT dest_ip, UINT dest_port, UINT public_ip);
+void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size);
+void NnIpSendFragmentedForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UINT src_ip, UINT dest_ip, USHORT id, USHORT total_size,
+ USHORT offset, void *data, UINT size, UCHAR ttl);
+void NnPoll(NATIVE_NAT *t);
+void NnLayer2(NATIVE_NAT *t, PKT *packet);
+void NnFragmentedIpReceived(NATIVE_NAT *t, PKT *packet);
+void NnIpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size,
+ UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size);
+void NnUdpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size);
+void NnTcpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size);
+void NnIcmpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size);
+
+void NnCombineIp(NATIVE_NAT *t, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size);
+void NnFreeIpCombine(NATIVE_NAT *t, IP_COMBINE *c);
+IP_COMBINE *NnSearchIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol);
+IP_COMBINE *NnInsertIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac);
+void NnInitIpCombineList(NATIVE_NAT *t);
+void NnFreeIpCombineList(NATIVE_NAT *t);
+void NnPollingIpCombine(NATIVE_NAT *t);
+void NnDeleteOldSessions(NATIVE_NAT *t);
+void NnDeleteSession(NATIVE_NAT *t, NATIVE_NAT_ENTRY *e);
+
+NATIVE_NAT_ENTRY *NnGetOldestNatEntryOfIp(NATIVE_NAT *t, UINT ip, UINT protocol);
+void NnDeleteOldestNatSession(NATIVE_NAT *t, UINT ip, UINT protocol);
+UINT NnGetNumNatEntriesPerIp(NATIVE_NAT *t, UINT src_ip, UINT protocol);
+void NnDeleteOldestNatSessionIfNecessary(NATIVE_NAT *t, UINT ip, UINT protocol);
+
+void NnSetSecureNatTargetHostname(char *name);
+
+
+#endif // VIRTUAL_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WaterMark.c b/src/Cedar/WaterMark.c
new file mode 100644
index 00000000..f7a9a967
--- /dev/null
+++ b/src/Cedar/WaterMark.c
@@ -0,0 +1,4386 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WaterMark.c
+// SoftEther protocol digital watermark data
+
+#include "CedarPch.h"
+
+// Digital watermark image data (JPEG)
+BYTE WaterMark[] =
+{
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0xC8, 0x00, 0x33, 0x00, 0xF2, 0x00, 0x00, 0x36, 0x37, 0x34,
+ 0x79, 0x68, 0x54, 0x80, 0x80, 0x80, 0xAF, 0x7F, 0x5B, 0xB3, 0xA8, 0x9D, 0xD5, 0xD5, 0xD4, 0xFF,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x33, 0x00, 0x00, 0x03,
+ 0xFE, 0x08, 0x1A, 0xDC, 0x34, 0x0A, 0x04, 0x41, 0x6B, 0x65, 0x31, 0x4F, 0x11, 0x80, 0xF9, 0x60,
+ 0x28, 0x8E, 0x64, 0x69, 0x9E, 0x68, 0xAA, 0xAE, 0x6C, 0xEB, 0x9A, 0x4B, 0xE3, 0x0C, 0x0C, 0x25,
+ 0x6F, 0x56, 0xA7, 0xE9, 0xD2, 0xEB, 0xFF, 0xC0, 0xA0, 0x70, 0xC8, 0x8A, 0xDC, 0x2C, 0x9C, 0xC6,
+ 0x05, 0xC7, 0x31, 0x66, 0x24, 0x04, 0xA2, 0x74, 0x4A, 0xAD, 0x4E, 0x05, 0xB1, 0x0D, 0x61, 0xCB,
+ 0x25, 0xD4, 0xB8, 0x49, 0x1B, 0xE6, 0x19, 0xB1, 0x9A, 0xCF, 0xE8, 0xF4, 0x07, 0x2B, 0x11, 0x74,
+ 0x09, 0x85, 0x78, 0xFC, 0x0D, 0x6E, 0x90, 0x9F, 0xEA, 0x02, 0x81, 0x12, 0x35, 0xEF, 0x29, 0x6A,
+ 0x81, 0x2C, 0x04, 0x0A, 0x6E, 0x5C, 0x72, 0x88, 0x7A, 0x7A, 0x6F, 0x4D, 0x77, 0x19, 0x25, 0x71,
+ 0x16, 0x71, 0x2F, 0x05, 0x92, 0x06, 0x95, 0x80, 0x22, 0x48, 0x16, 0x7D, 0x98, 0x02, 0x9A, 0x7C,
+ 0x82, 0x06, 0x16, 0x23, 0x7F, 0x02, 0x05, 0x6B, 0x48, 0x70, 0x23, 0x15, 0x7D, 0x1F, 0x98, 0xA8,
+ 0x21, 0x7F, 0x87, 0x89, 0xB5, 0x8B, 0x7C, 0x7B, 0x3C, 0x8E, 0x23, 0x9E, 0x9B, 0xAE, 0x2B, 0xAD,
+ 0x20, 0xA6, 0xAC, 0x9B, 0x14, 0xB1, 0xC3, 0x21, 0x15, 0xB1, 0x81, 0x9E, 0x22, 0x9E, 0xAE, 0xC5,
+ 0x99, 0x20, 0x96, 0xAF, 0xC6, 0xA0, 0x70, 0xB6, 0xB6, 0x5B, 0x03, 0x1C, 0x16, 0x8E, 0x65, 0x21,
+ 0xBD, 0x9B, 0xCB, 0x2A, 0x9E, 0xCB, 0xC1, 0xE1, 0xD1, 0xA7, 0xA9, 0x6E, 0xE9, 0xD6, 0x82, 0xCD,
+ 0xC9, 0xCA, 0xD5, 0xD1, 0xAE, 0xBD, 0xCB, 0x7F, 0xAC, 0xB4, 0xD9, 0x73, 0x34, 0x37, 0x76, 0xDF,
+ 0x3C, 0xC8, 0x9A, 0x07, 0x42, 0x4E, 0x38, 0x4C, 0xAB, 0x0A, 0xFA, 0x12, 0x17, 0xEA, 0x52, 0x05,
+ 0x12, 0x0C, 0xDB, 0x35, 0xD3, 0xF3, 0xCE, 0xD9, 0x2C, 0x72, 0x13, 0xB7, 0x40, 0x22, 0xE8, 0xFE,
+ 0xB0, 0x61, 0xC7, 0x4F, 0xEC, 0x40, 0x7E, 0x94, 0xF6, 0x50, 0x13, 0x36, 0x83, 0xA8, 0x6A, 0x79,
+ 0xF9, 0x77, 0xE3, 0x1B, 0x28, 0x69, 0x1B, 0x55, 0x09, 0x1B, 0x67, 0x8A, 0x1A, 0xA9, 0x52, 0xC5,
+ 0x50, 0x71, 0x42, 0x82, 0x31, 0xDA, 0xB4, 0x56, 0x15, 0x9D, 0x71, 0xBC, 0x19, 0xF2, 0x27, 0x49,
+ 0x3E, 0xEF, 0x3C, 0x4E, 0xDB, 0x92, 0xED, 0x52, 0xBF, 0x01, 0xFE, 0x02, 0x44, 0x95, 0xB1, 0x6B,
+ 0xA0, 0x32, 0x72, 0x0A, 0x25, 0x72, 0x1C, 0xE5, 0x11, 0x99, 0x3C, 0x5F, 0x33, 0x61, 0x72, 0x75,
+ 0x93, 0x92, 0x28, 0x42, 0xA3, 0x7D, 0x72, 0x9A, 0x20, 0x68, 0x8A, 0x1C, 0x3A, 0x73, 0x3F, 0xE1,
+ 0x84, 0x82, 0x55, 0xEA, 0xE4, 0xA5, 0xBB, 0x89, 0xDE, 0x4C, 0x60, 0x30, 0x75, 0x0C, 0x9E, 0x97,
+ 0xD4, 0x8C, 0xC6, 0x32, 0x3B, 0xB4, 0x64, 0xD6, 0x71, 0x46, 0x45, 0x7E, 0x3C, 0x67, 0xB8, 0x30,
+ 0x20, 0xB8, 0x29, 0x82, 0x3D, 0x73, 0xE7, 0x93, 0x1E, 0xAA, 0x3F, 0x91, 0xD6, 0x89, 0x60, 0x9A,
+ 0xC8, 0x69, 0x36, 0xA8, 0x1B, 0xA4, 0xFE, 0x23, 0x03, 0x51, 0xED, 0xC7, 0xC4, 0x87, 0x19, 0xB7,
+ 0xA3, 0xCC, 0x13, 0x2D, 0x65, 0xD5, 0xB1, 0x22, 0x4A, 0xDE, 0xBA, 0xF6, 0xA1, 0x57, 0x7A, 0x0B,
+ 0xB3, 0x96, 0x3D, 0x95, 0xAF, 0x2E, 0x4A, 0xBC, 0x2A, 0xB9, 0x25, 0x61, 0x09, 0x10, 0x1C, 0x24,
+ 0x53, 0x7D, 0xBC, 0xA2, 0x33, 0xE0, 0x15, 0x72, 0x58, 0xC5, 0xAF, 0xAD, 0x8A, 0x84, 0x5C, 0x13,
+ 0xF1, 0xED, 0x13, 0xE6, 0x68, 0x57, 0x3F, 0x85, 0xB5, 0xF7, 0x58, 0xC3, 0xB2, 0x3A, 0xA7, 0x54,
+ 0xB9, 0x87, 0x86, 0x98, 0xBD, 0xA3, 0x8D, 0xD7, 0xCE, 0x44, 0xD4, 0xF1, 0x74, 0xDA, 0x44, 0x85,
+ 0x06, 0x25, 0x7C, 0x54, 0xEC, 0x57, 0xE8, 0x26, 0x18, 0xFE, 0x2A, 0xBA, 0xFE, 0xB9, 0xFE, 0xE6,
+ 0xCD, 0x88, 0x00, 0x57, 0x0B, 0x54, 0xFE, 0x20, 0x31, 0x1A, 0x0F, 0x01, 0x14, 0x94, 0xD0, 0x61,
+ 0x69, 0x95, 0x14, 0x0F, 0x3B, 0xAE, 0x5C, 0x37, 0x16, 0x56, 0xCF, 0xBD, 0x14, 0xA1, 0x61, 0x12,
+ 0x0E, 0xA6, 0x14, 0x76, 0x88, 0xBD, 0x44, 0xA1, 0x3C, 0xF6, 0x04, 0x76, 0x90, 0x78, 0xE4, 0x81,
+ 0x26, 0x80, 0x70, 0x0F, 0x10, 0xA7, 0xC4, 0x61, 0x95, 0x2D, 0xC6, 0x5C, 0x45, 0xCE, 0x89, 0x28,
+ 0x1B, 0x34, 0x1C, 0xC5, 0xE8, 0xD1, 0x64, 0xAF, 0xAC, 0xE2, 0x1C, 0x0A, 0xE2, 0xEC, 0xE7, 0x62,
+ 0x4C, 0xE4, 0xB4, 0x05, 0x51, 0x80, 0x93, 0x04, 0xE7, 0x8F, 0x70, 0x01, 0x6C, 0xA1, 0x62, 0x0D,
+ 0xFE, 0x75, 0xF8, 0xC1, 0x76, 0x3D, 0x55, 0x54, 0x5D, 0x27, 0xD1, 0xE0, 0x23, 0x13, 0x64, 0x3B,
+ 0x6E, 0x67, 0xCD, 0x8E, 0x28, 0x20, 0x51, 0x5A, 0x50, 0xF2, 0x45, 0x89, 0xDF, 0x2B, 0xB5, 0x78,
+ 0x26, 0x07, 0x17, 0x04, 0x8A, 0xE6, 0x46, 0x5F, 0x2C, 0x1D, 0x84, 0xDC, 0x24, 0xBC, 0x60, 0xD6,
+ 0x1D, 0x78, 0x1F, 0x25, 0xA4, 0xE5, 0x7F, 0x75, 0x5E, 0x66, 0x18, 0x97, 0x73, 0xF0, 0x01, 0xA7,
+ 0x84, 0x27, 0x88, 0x58, 0xA1, 0x09, 0xDE, 0xC5, 0x05, 0x09, 0x3F, 0x88, 0xA0, 0x79, 0x24, 0x54,
+ 0x0F, 0x80, 0xC6, 0x66, 0x07, 0xA2, 0x44, 0x2A, 0xE9, 0xA4, 0x23, 0x22, 0x3A, 0xC7, 0x36, 0x0D,
+ 0x0C, 0xD0, 0x28, 0x81, 0xA0, 0xB5, 0x44, 0xE9, 0xA7, 0xA0, 0xA2, 0x71, 0x52, 0x36, 0x70, 0xE8,
+ 0x25, 0x55, 0x9A, 0x9C, 0x46, 0xE5, 0x8F, 0x40, 0xA1, 0xB6, 0xEA, 0x6A, 0x10, 0xA3, 0x9E, 0x49,
+ 0x9E, 0x92, 0xA7, 0xA6, 0xCA, 0xA9, 0xA7, 0xAF, 0xE6, 0xAA, 0xEB, 0x0A, 0xA5, 0x4E, 0x99, 0x57,
+ 0x1D, 0xB5, 0x6E, 0x8A, 0xEA, 0x18, 0xBB, 0x16, 0x6B, 0xAC, 0x3E, 0x71, 0x20, 0xFE, 0x48, 0x16,
+ 0x36, 0x5D, 0x24, 0xC1, 0xA9, 0xB0, 0x69, 0xEA, 0x70, 0xEC, 0xB4, 0xC6, 0x26, 0xD9, 0x45, 0x0D,
+ 0x1C, 0x8C, 0x0A, 0x2C, 0x81, 0xD0, 0x76, 0x2A, 0x2D, 0xB5, 0xE0, 0xBE, 0x9A, 0xA4, 0x21, 0xB9,
+ 0x0C, 0x47, 0x6E, 0x9F, 0xB5, 0xDA, 0xEA, 0x28, 0xB1, 0x25, 0x88, 0x54, 0xD2, 0x98, 0x8D, 0xD5,
+ 0xA7, 0x09, 0x31, 0xF6, 0x25, 0x33, 0x4A, 0x48, 0x9F, 0x80, 0x34, 0xA6, 0x0A, 0x74, 0x56, 0xA1,
+ 0xAF, 0x0F, 0x6D, 0x10, 0x27, 0x41, 0x1B, 0x4C, 0x79, 0xA1, 0x2E, 0x5F, 0x9D, 0xAA, 0x67, 0xEF,
+ 0x1A, 0xD3, 0x30, 0xBC, 0xF0, 0xBD, 0xEE, 0xDE, 0xEB, 0x30, 0x57, 0xF3, 0x36, 0x4C, 0xC2, 0xBF,
+ 0x12, 0x5B, 0xBC, 0x6F, 0x97, 0x16, 0x9B, 0xB1, 0xB1, 0x0A, 0x59, 0xC8, 0x30, 0x9C, 0xC8, 0xDB,
+ 0x68, 0x9A, 0xEA, 0x02, 0x09, 0x2B, 0x70, 0x71, 0xC7, 0x15, 0xB3, 0x92, 0x71, 0xBE, 0x1A, 0x67,
+ 0x3C, 0xF1, 0x57, 0xF8, 0xC2, 0x6C, 0x14, 0xC4, 0xEE, 0xB2, 0x27, 0x33, 0xBC, 0x3A, 0xC3, 0x2C,
+ 0x2F, 0xC4, 0xEC, 0x8C, 0x25, 0xF1, 0xBB, 0xFD, 0x7E, 0x10, 0xB2, 0x12, 0xC4, 0x91, 0x5B, 0x32,
+ 0x54, 0x46, 0x14, 0xB7, 0xF2, 0xCC, 0x0F, 0xCF, 0x1B, 0x71, 0xC4, 0x40, 0x83, 0xF2, 0x30, 0xC6,
+ 0xFA, 0x92, 0x92, 0x35, 0xC3, 0x53, 0x43, 0x87, 0x5F, 0xD7, 0xA9, 0x70, 0xDD, 0xB0, 0xCE, 0x62,
+ 0x57, 0x6D, 0xF6, 0x98, 0x4D, 0x8B, 0x3C, 0x32, 0xD2, 0xE4, 0xA6, 0x8A, 0xB0, 0x5F, 0x4F, 0xCB,
+ 0x1C, 0x75, 0xCC, 0x65, 0x57, 0xBD, 0x2F, 0xD9, 0x43, 0x3B, 0xEC, 0xF5, 0xC4, 0xF9, 0x6A, 0xED,
+ 0x72, 0xCB, 0x36, 0xBF, 0x2C, 0xB8, 0x62, 0x7E, 0x9F, 0x2D, 0xF8, 0x08, 0x69, 0x87, 0xB1, 0xF6,
+ 0x3F, 0x6B, 0xAA, 0x0B, 0x9A, 0xC2, 0x7C, 0xB7, 0xFB, 0xF7, 0xE0, 0x63, 0xFE, 0xC7, 0x27, 0x35,
+ 0xDD, 0x18, 0xD3, 0x6D, 0x36, 0xD4, 0x72, 0x53, 0x1E, 0xF9, 0xD4, 0x1D, 0xDB, 0x1C, 0xF8, 0xE8,
+ 0x24, 0x2C, 0xB0, 0x44, 0x0E, 0x2C, 0x99, 0xDE, 0x6D, 0x9A, 0x90, 0xEF, 0x1C, 0x7A, 0xCB, 0x9E,
+ 0xBB, 0x1E, 0x35, 0xE9, 0x79, 0xCB, 0x9D, 0x39, 0xE9, 0xF0, 0x8E, 0xAD, 0x7B, 0xD8, 0x86, 0x53,
+ 0x0D, 0xC8, 0xBF, 0xA0, 0x73, 0x6E, 0x80, 0x12, 0x39, 0x9C, 0x27, 0x72, 0x07, 0x3A, 0xB4, 0xED,
+ 0x76, 0xEB, 0x5E, 0xC3, 0x44, 0xF8, 0x4D, 0xF1, 0xEE, 0x0D, 0xD8, 0xCD, 0x7A, 0xF7, 0xFD, 0xD0,
+ 0xEF, 0x1A, 0xE3, 0xFD, 0x12, 0xF5, 0x60, 0x07, 0xBD, 0xB3, 0xCF, 0xA2, 0xE3, 0x9D, 0xB9, 0x01,
+ 0xA6, 0x9F, 0x6E, 0x7C, 0x0D, 0x18, 0xE8, 0x60, 0x2D, 0xB4, 0xEC, 0x4E, 0x1E, 0x77, 0xB8, 0x81,
+ 0x7C, 0x9C, 0x06, 0xF1, 0x17, 0xD8, 0x60, 0x6E, 0x68, 0x03, 0x2F, 0xA0, 0x68, 0x54, 0x2A, 0x4B,
+ 0xFE, 0x3E, 0xFC, 0x6A, 0x90, 0x1F, 0x1A, 0xCA, 0x57, 0xBF, 0xD0, 0x98, 0x2B, 0x09, 0xF9, 0x03,
+ 0x80, 0x21, 0x6E, 0xD5, 0x3A, 0x00, 0x3A, 0x30, 0x0D, 0x04, 0xB4, 0x1F, 0x0E, 0x8E, 0xE0, 0x17,
+ 0x23, 0x48, 0xF0, 0x11, 0x67, 0x20, 0xDC, 0xF7, 0xDE, 0xF5, 0x3F, 0xF9, 0x79, 0x29, 0x52, 0x02,
+ 0x7C, 0x60, 0x1A, 0x70, 0x37, 0xBB, 0xB5, 0xC0, 0xEE, 0x7D, 0x21, 0x94, 0x42, 0x0A, 0x45, 0xE8,
+ 0xB1, 0xD8, 0xB9, 0x6E, 0x6B, 0xE0, 0x13, 0x9A, 0x0C, 0x59, 0x96, 0xB5, 0x9C, 0xD9, 0x50, 0x6C,
+ 0xBE, 0x3B, 0x4A, 0xE7, 0x58, 0x28, 0x0A, 0x12, 0x26, 0x06, 0x78, 0x61, 0xEB, 0x59, 0xE4, 0x7E,
+ 0xF8, 0xB9, 0xDD, 0xE1, 0xAC, 0x88, 0x65, 0xAB, 0x17, 0x0F, 0x03, 0x18, 0x33, 0x0D, 0xC6, 0xCE,
+ 0x87, 0x14, 0xAB, 0x98, 0x0D, 0xD9, 0x33, 0xC5, 0xC0, 0xD9, 0xAD, 0x55, 0x70, 0x3B, 0x5C, 0xE2,
+ 0x08, 0xA1, 0x27, 0xBB, 0xBC, 0x05, 0x6F, 0x73, 0xB6, 0xD3, 0x9C, 0x14, 0x61, 0x27, 0x3A, 0xC0,
+ 0x69, 0x11, 0x84, 0x97, 0x73, 0xA2, 0x17, 0x83, 0xB8, 0x3B, 0xAA, 0x0D, 0xF1, 0x8B, 0x50, 0x1C,
+ 0xE2, 0x15, 0xCF, 0xD8, 0xC3, 0x34, 0x96, 0x10, 0x86, 0x83, 0xAB, 0x21, 0x19, 0xBD, 0x37, 0x43,
+ 0x0E, 0xCE, 0x4E, 0x87, 0xE3, 0xA3, 0x63, 0xB8, 0x56, 0x28, 0xC8, 0x42, 0x82, 0xB0, 0x68, 0x86,
+ 0x4C, 0xA4, 0x22, 0x17, 0xC9, 0xC8, 0x46, 0x3A, 0xF2, 0x91, 0x90, 0x8C, 0xA4, 0x24, 0x75, 0x95,
+ 0x00, 0x00, 0x3B,
+};
+
+// Bonus data
+BYTE Saitama[] =
+{
+ 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x03, 0x03,
+ 0x03, 0x04, 0x03, 0x02, 0x02, 0x04, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x03, 0x03,
+ 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x02, 0x04, 0x03, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00,
+ 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04,
+ 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05,
+ 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+ 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A,
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5,
+ 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
+ 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
+ 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02,
+ 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03,
+ 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81,
+ 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1,
+ 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92,
+ 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
+ 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
+ 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC0,
+ 0x00, 0x11, 0x08, 0x01, 0x9B, 0x02, 0x1C, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11,
+ 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xFA,
+ 0xFE, 0xBF, 0x5F, 0x3E, 0x18, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF3, 0xB3,
+ 0xF6, 0x8A, 0xFF, 0x00, 0x82, 0xA1, 0xFE, 0xCA, 0xFF, 0x00, 0xB2, 0xE7, 0xC5, 0x3D, 0x5F, 0xE0,
+ 0xEF, 0xC5, 0x3B, 0xCF, 0x1F, 0x41, 0xE3, 0x2D, 0x0F, 0x4E, 0xB0, 0xD4, 0xEF, 0xA3, 0xF0, 0xFF,
+ 0x00, 0x83, 0x4E, 0xB1, 0xA6, 0x2C, 0x5A, 0x85, 0xA2, 0x5C, 0x5B, 0x6C, 0x9F, 0xCE, 0x4C, 0x9F,
+ 0x2E, 0x64, 0xC8, 0xDA, 0x30, 0x72, 0x3B, 0x57, 0x93, 0x8A, 0xCE, 0xB0, 0x38, 0x2A, 0xCF, 0x0F,
+ 0x5A, 0xFC, 0xC9, 0x2D, 0x96, 0x9A, 0xAD, 0x3F, 0x03, 0xB6, 0x86, 0x5F, 0x5E, 0xBD, 0x35, 0x52,
+ 0x9A, 0x5C, 0xBE, 0xB6, 0xD8, 0xF1, 0xD5, 0xFF, 0x00, 0x82, 0xD9, 0xFE, 0xC4, 0xCD, 0x67, 0x0D,
+ 0xFA, 0xFF, 0x00, 0xC2, 0xE6, 0x36, 0x33, 0xCA, 0x6D, 0xED, 0xEE, 0xD7, 0xE1, 0x74, 0x9F, 0x66,
+ 0x99, 0xD4, 0x7C, 0xC9, 0x1B, 0xFD, 0xA3, 0x6B, 0x11, 0xC6, 0x40, 0xE9, 0x59, 0x47, 0x3F, 0xC0,
+ 0x38, 0xA9, 0x46, 0x32, 0xB3, 0xD1, 0x5A, 0x3D, 0x7B, 0x2F, 0xF2, 0x3A, 0x61, 0x92, 0xE3, 0xE7,
+ 0x75, 0x4E, 0x17, 0xB2, 0x4F, 0x4E, 0x89, 0xE8, 0xB6, 0x5B, 0x74, 0x42, 0x43, 0xFF, 0x00, 0x05,
+ 0xB6, 0xFD, 0x88, 0x67, 0x1F, 0xB9, 0xB9, 0xF8, 0xB4, 0xFB, 0x47, 0x2A, 0x3E, 0x1E, 0xA2, 0x32,
+ 0xE3, 0xB1, 0x53, 0x74, 0x08, 0xE9, 0xD3, 0x15, 0xF7, 0x3C, 0x39, 0xC2, 0x7C, 0x53, 0xC5, 0xD8,
+ 0x7F, 0xAC, 0xF0, 0xCE, 0x01, 0xE2, 0x29, 0xA4, 0xDF, 0xB9, 0x57, 0x0C, 0x9A, 0x4B, 0x47, 0x78,
+ 0x4A, 0xB4, 0x66, 0x9F, 0x93, 0x8A, 0x7D, 0x91, 0xC5, 0x5F, 0x0B, 0x2C, 0x24, 0x9D, 0x3C, 0x43,
+ 0x51, 0x6B, 0x4B, 0x35, 0x25, 0xFF, 0x00, 0xB6, 0x93, 0x47, 0xFF, 0x00, 0x05, 0xAF, 0xFD, 0x89,
+ 0xA4, 0x46, 0x68, 0xE7, 0xF8, 0xB2, 0xCA, 0x98, 0xDD, 0x8F, 0x00, 0x44, 0x36, 0x8C, 0x71, 0xC7,
+ 0xDA, 0xC7, 0xA7, 0xA5, 0x7D, 0x16, 0x5B, 0xE1, 0x3F, 0x89, 0x79, 0xB6, 0x16, 0xAE, 0x2F, 0x2D,
+ 0xC9, 0xA5, 0x3A, 0x74, 0xB4, 0x9B, 0x58, 0x8C, 0x1A, 0x71, 0xF5, 0x8C, 0xB1, 0x2A, 0x5F, 0x72,
+ 0xB7, 0x4E, 0x86, 0x12, 0xF6, 0x34, 0xDA, 0x8C, 0xAA, 0x24, 0xDE, 0xDA, 0x4B, 0xF4, 0x8D, 0x8F,
+ 0x54, 0xF8, 0x65, 0xFF, 0x00, 0x05, 0x40, 0xFD, 0x9E, 0x7E, 0x32, 0x4B, 0xAA, 0x5B, 0xFC, 0x32,
+ 0xF0, 0xDF, 0xC5, 0x8F, 0x14, 0x4F, 0xA2, 0x47, 0x0C, 0xBA, 0xA4, 0x0B, 0xA1, 0x68, 0x9A, 0x14,
+ 0x96, 0x51, 0xCE, 0xC5, 0x62, 0x90, 0xAD, 0xEE, 0xAD, 0x06, 0xE4, 0xCA, 0x36, 0x59, 0x72, 0xAB,
+ 0x8C, 0xB1, 0x51, 0x5E, 0x7E, 0x71, 0xE1, 0xDF, 0x1E, 0xF0, 0xF5, 0x18, 0x56, 0xCE, 0x72, 0x99,
+ 0xD2, 0x84, 0xAF, 0xCB, 0xFB, 0xDC, 0x2C, 0xAF, 0x64, 0x9B, 0xB2, 0x85, 0x79, 0x37, 0x64, 0xD6,
+ 0x89, 0x79, 0x2D, 0x9A, 0x5C, 0x58, 0xAC, 0xC3, 0x2D, 0xC0, 0xA4, 0xF1, 0x55, 0xD4, 0x63, 0xDF,
+ 0x92, 0xA3, 0x5D, 0xB7, 0x50, 0x69, 0x7A, 0x36, 0xAD, 0xA7, 0x4B, 0x09, 0x27, 0xFC, 0x15, 0x07,
+ 0xF6, 0x7A, 0xB6, 0xF8, 0x85, 0x0F, 0xC2, 0x8B, 0xCF, 0x0B, 0xFC, 0x5F, 0xD3, 0x7E, 0x20, 0xCF,
+ 0x78, 0x9A, 0x7C, 0x1E, 0x1D, 0xD5, 0xFC, 0x33, 0xA4, 0x68, 0xAB, 0x2C, 0xB2, 0x21, 0x68, 0x95,
+ 0x2F, 0xA7, 0xD5, 0x23, 0xB2, 0x2A, 0xCA, 0x8C, 0x55, 0xC4, 0xDB, 0x1B, 0x18, 0x56, 0x27, 0x8A,
+ 0xD7, 0x0B, 0xE1, 0xB7, 0x88, 0x18, 0xCC, 0xAA, 0x59, 0xD6, 0x0F, 0x29, 0x94, 0xF0, 0xB1, 0xD1,
+ 0xCA, 0x35, 0xB0, 0x8E, 0x4B, 0x6F, 0xF9, 0x76, 0xB1, 0x1E, 0xD3, 0x4B, 0xA5, 0xF0, 0x69, 0xB7,
+ 0x4D, 0x1C, 0x71, 0xF9, 0x6C, 0xA9, 0x2A, 0xB4, 0xEB, 0xA7, 0x06, 0x9B, 0x56, 0x8C, 0xDE, 0x8A,
+ 0xD7, 0xD1, 0x42, 0xEA, 0xD7, 0x5A, 0x5B, 0xAA, 0xD3, 0x54, 0x69, 0x7C, 0x46, 0xFF, 0x00, 0x82,
+ 0x94, 0xFC, 0x0F, 0xF8, 0x47, 0x67, 0xA6, 0xDF, 0xFC, 0x46, 0xF0, 0x37, 0xC6, 0xCF, 0x0B, 0xD8,
+ 0x6A, 0xD7, 0x52, 0x58, 0x69, 0xD7, 0x72, 0xF8, 0x4B, 0x4A, 0xD5, 0x2D, 0xAE, 0x27, 0x84, 0x02,
+ 0xF0, 0x96, 0xB5, 0xD4, 0xE5, 0x08, 0xE0, 0x11, 0x85, 0x7D, 0xA4, 0xFF, 0x00, 0x08, 0x38, 0xE2,
+ 0x32, 0x8F, 0x0E, 0xB8, 0xFB, 0x3D, 0x9B, 0xA3, 0x94, 0x65, 0x33, 0x9C, 0x97, 0x4F, 0x6D, 0x85,
+ 0x83, 0x56, 0xF2, 0x9E, 0x22, 0x3D, 0xB4, 0x5D, 0x74, 0xB5, 0xF4, 0x0C, 0x1E, 0x3F, 0x2D, 0xC7,
+ 0xCE, 0x54, 0xF0, 0x58, 0x88, 0xC9, 0xC5, 0x2B, 0xA4, 0xA6, 0xB7, 0xDA, 0xD7, 0x82, 0xBD, 0xFA,
+ 0x25, 0xBD, 0xAC, 0x95, 0xD5, 0x88, 0x63, 0xFF, 0x00, 0x82, 0x99, 0x7C, 0x06, 0x97, 0xC1, 0x96,
+ 0x7F, 0x10, 0x6D, 0xFC, 0x1F, 0xF1, 0x8A, 0xEB, 0xC1, 0x77, 0xF6, 0xF3, 0x5C, 0x58, 0xEB, 0xD6,
+ 0x5E, 0x1A, 0xD1, 0xEF, 0x60, 0xBA, 0x4B, 0x76, 0x2B, 0x38, 0x8E, 0x08, 0xF5, 0x56, 0x98, 0xB2,
+ 0x15, 0x60, 0x53, 0xCB, 0xDC, 0x30, 0x78, 0xC0, 0xE2, 0x9F, 0x86, 0xDE, 0x20, 0xC7, 0x18, 0xF2,
+ 0xE7, 0x94, 0x4D, 0x57, 0x5B, 0xC3, 0xDB, 0x61, 0x6E, 0xB6, 0xDF, 0xFD, 0xA2, 0xC9, 0x6D, 0xAE,
+ 0xCB, 0x4B, 0xB4, 0x72, 0xBC, 0xF7, 0x23, 0x85, 0x7F, 0xAA, 0xD4, 0xC5, 0x46, 0x33, 0xDA, 0xD2,
+ 0x8D, 0x48, 0x76, 0x5B, 0xCA, 0x09, 0x7A, 0x2B, 0xEB, 0xD3, 0x44, 0xED, 0x83, 0xE0, 0x7F, 0xF8,
+ 0x2A, 0xC7, 0xEC, 0xD5, 0xF1, 0x22, 0xE6, 0xF2, 0xC7, 0xC0, 0xBE, 0x1E, 0xF8, 0xC7, 0xE2, 0x3B,
+ 0xDD, 0x3E, 0xD1, 0x6F, 0x6E, 0xAC, 0xAD, 0x3C, 0x1B, 0xA7, 0xDA, 0xDE, 0x24, 0x24, 0x90, 0x24,
+ 0x48, 0x66, 0xD4, 0x63, 0x69, 0x14, 0x15, 0x20, 0xEC, 0x0D, 0x8C, 0x73, 0x8C, 0x8A, 0xD7, 0x13,
+ 0xE1, 0x87, 0x88, 0x98, 0x2A, 0xB1, 0xA1, 0x8A, 0xCA, 0x25, 0x19, 0x35, 0x75, 0x7A, 0xF8, 0x3B,
+ 0x34, 0xAC, 0xB4, 0x92, 0xC4, 0xF2, 0xE9, 0x75, 0xA5, 0xEE, 0xBB, 0x59, 0x1D, 0xD8, 0xAC, 0x4E,
+ 0x0F, 0x03, 0x4E, 0x15, 0x31, 0x35, 0x79, 0x63, 0x2B, 0x28, 0xBE, 0x4A, 0x8D, 0x3B, 0xE8, 0xAD,
+ 0xCB, 0x07, 0xDB, 0xD2, 0xC9, 0xBD, 0x93, 0xB6, 0x27, 0x8A, 0xBF, 0xE0, 0xAF, 0x7F, 0xB2, 0x87,
+ 0x81, 0xB5, 0xDB, 0xCF, 0x0B, 0xF8, 0xBB, 0x49, 0xF8, 0xCD, 0xA0, 0x6B, 0xFA, 0x7A, 0xA1, 0xBC,
+ 0xD2, 0xAF, 0x7E, 0x1F, 0xC1, 0xF6, 0x8B, 0x71, 0x22, 0x06, 0x42, 0x4A, 0x5E, 0xB2, 0x90, 0x54,
+ 0xA9, 0xE0, 0x9F, 0xD3, 0x8E, 0xAC, 0xBB, 0xC2, 0x3F, 0x13, 0xF3, 0x58, 0xCA, 0x59, 0x66, 0x49,
+ 0x3A, 0x89, 0x68, 0xF9, 0x6B, 0xE0, 0xDD, 0xAC, 0xED, 0xFF, 0x00, 0x41, 0x3D, 0x1A, 0xB6, 0x9E,
+ 0x5D, 0x1A, 0x2E, 0x9D, 0x6C, 0x25, 0x4A, 0x6A, 0x70, 0xAA, 0xB9, 0x76, 0xDA, 0x6B, 0xF0, 0x71,
+ 0x4D, 0x7D, 0xC8, 0xE6, 0xFF, 0x00, 0xE1, 0xF5, 0x7F, 0xB1, 0x48, 0x1F, 0xEB, 0x7E, 0x2C, 0x80,
+ 0x00, 0xFF, 0x00, 0x99, 0x02, 0x2F, 0xC0, 0x01, 0xF6, 0xBF, 0xA5, 0x74, 0x4B, 0xC1, 0x8F, 0x16,
+ 0x20, 0xBD, 0xEC, 0x8A, 0x76, 0xFF, 0x00, 0xAF, 0xF8, 0x2F, 0xCB, 0xEB, 0x26, 0x89, 0xD0, 0xB2,
+ 0xB5, 0x48, 0xDB, 0xD2, 0x5F, 0xFC, 0x88, 0x9F, 0xF0, 0xFA, 0xCF, 0xD8, 0xA0, 0x0F, 0xF5, 0xBF,
+ 0x16, 0x80, 0x18, 0xFF, 0x00, 0x9A, 0x7F, 0x18, 0x03, 0xD3, 0xFE, 0x5E, 0xFE, 0x95, 0x9F, 0xFC,
+ 0x41, 0xDF, 0x15, 0x22, 0xB5, 0xC8, 0xAA, 0x5B, 0xFE, 0xBF, 0xE0, 0xFF, 0x00, 0xF9, 0xA4, 0x2F,
+ 0x43, 0xFE, 0x7E, 0x2F, 0xBA, 0x5F, 0xFC, 0x88, 0x9F, 0xF0, 0xFA, 0xFF, 0x00, 0xD8, 0x98, 0x0F,
+ 0xF5, 0xFF, 0x00, 0x16, 0x40, 0x18, 0x18, 0xFF, 0x00, 0x84, 0x02, 0x21, 0x8E, 0x38, 0x18, 0xFB,
+ 0x5D, 0x63, 0x3F, 0x09, 0x7C, 0x4D, 0xA5, 0x16, 0xE7, 0x92, 0xC9, 0x25, 0xFF, 0x00, 0x51, 0x18,
+ 0x2F, 0x96, 0x9F, 0x59, 0xFB, 0x92, 0xDF, 0xA2, 0x1A, 0x54, 0x74, 0x4A, 0xA2, 0xFB, 0xA5, 0xFF,
+ 0x00, 0xC8, 0x91, 0x2F, 0xFC, 0x16, 0xD3, 0xF6, 0x22, 0x27, 0x60, 0xB8, 0xF8, 0xB6, 0x08, 0xC0,
+ 0xF9, 0xBE, 0x1E, 0x2C, 0x6A, 0x3D, 0x30, 0x4D, 0xD0, 0x1D, 0xAB, 0xCA, 0xA3, 0xC0, 0x3C, 0x77,
+ 0x5B, 0x12, 0xF0, 0x70, 0xC9, 0xEA, 0xA9, 0xAF, 0xE7, 0x95, 0x0A, 0x71, 0xFF, 0x00, 0xC0, 0xE7,
+ 0x56, 0x34, 0xED, 0xA7, 0x49, 0x59, 0x2B, 0x74, 0xB1, 0x7E, 0xCA, 0x0A, 0x29, 0xF3, 0xC6, 0xDE,
+ 0x57, 0x7F, 0x82, 0x57, 0xFC, 0x07, 0xBF, 0xFC, 0x16, 0xC7, 0xF6, 0x23, 0x8D, 0xB6, 0x1B, 0xAF,
+ 0x8A, 0xC4, 0x80, 0x3F, 0xD5, 0xF8, 0x0A, 0x29, 0x13, 0x18, 0xEC, 0xCB, 0x78, 0x47, 0x61, 0xDE,
+ 0xB4, 0x9F, 0x87, 0x9C, 0x77, 0x4E, 0xA3, 0xA2, 0xF2, 0xB9, 0x73, 0x2E, 0xD5, 0xB0, 0x92, 0x5A,
+ 0x79, 0xC7, 0x10, 0xE3, 0xF7, 0x3F, 0x24, 0x53, 0xA3, 0x18, 0x59, 0x39, 0xC7, 0xE5, 0x76, 0xBF,
+ 0x05, 0x6F, 0xF2, 0x23, 0x4F, 0xF8, 0x2D, 0xB7, 0xEC, 0x40, 0xCD, 0xE5, 0xAD, 0xD7, 0xC5, 0x90,
+ 0x46, 0x07, 0xCF, 0xF0, 0xF5, 0x62, 0x8C, 0x71, 0xC7, 0xCC, 0x6E, 0x82, 0xFA, 0x77, 0xAF, 0x3A,
+ 0x9F, 0x09, 0x71, 0x75, 0x4A, 0xB3, 0xA1, 0x1C, 0xAE, 0xAA, 0x71, 0xDD, 0xC9, 0xD2, 0x84, 0x57,
+ 0xFD, 0xBF, 0x3A, 0x91, 0x83, 0xF9, 0x4B, 0x6F, 0x22, 0xA3, 0x86, 0xBD, 0x94, 0x67, 0x1D, 0x76,
+ 0xD6, 0xDF, 0xA6, 0x9F, 0xD2, 0x10, 0xFF, 0x00, 0xC1, 0x6E, 0x3F, 0x61, 0xF4, 0xE0, 0xDE, 0x7C,
+ 0x57, 0x00, 0x71, 0xC7, 0xC3, 0xF4, 0x65, 0xC0, 0x1D, 0x01, 0x17, 0x78, 0xED, 0x4B, 0x11, 0xC2,
+ 0x7C, 0x53, 0x84, 0x6A, 0x35, 0xB0, 0x0D, 0x2E, 0xEA, 0xAE, 0x1A, 0x51, 0xF2, 0xF7, 0xA3, 0x5D,
+ 0xC7, 0xD1, 0x5F, 0xC9, 0x2D, 0x89, 0x8E, 0x1E, 0xFA, 0x46, 0x4B, 0xEE, 0x6B, 0xF0, 0xB2, 0x18,
+ 0xBF, 0xF0, 0x5B, 0xCF, 0xD8, 0x70, 0xE0, 0x0B, 0xCF, 0x8B, 0x2A, 0x31, 0xC1, 0x6F, 0x87, 0x62,
+ 0x34, 0xC0, 0x1D, 0x98, 0xDD, 0x01, 0xDA, 0xB8, 0xA8, 0xE4, 0x99, 0xFD, 0x59, 0xAA, 0x71, 0xC0,
+ 0xCE, 0x2B, 0xF9, 0xA7, 0x2A, 0x54, 0xE1, 0xFF, 0x00, 0x83, 0x2A, 0x54, 0x8D, 0x3B, 0x2F, 0xF1,
+ 0x59, 0x22, 0xFE, 0xAB, 0x24, 0x97, 0xBC, 0xBE, 0x57, 0x7F, 0x82, 0x57, 0xFC, 0x06, 0x7F, 0xC3,
+ 0xF0, 0x3F, 0x61, 0x90, 0x76, 0x0B, 0xEF, 0x8B, 0x04, 0x80, 0x38, 0x5F, 0x87, 0x81, 0x97, 0x18,
+ 0xE3, 0x04, 0x5D, 0x63, 0xF2, 0xAE, 0x39, 0x61, 0x73, 0x08, 0x57, 0x78, 0x55, 0x86, 0x6E, 0x6B,
+ 0xA4, 0x67, 0x4A, 0x6B, 0x6E, 0x92, 0x85, 0x49, 0x41, 0xAE, 0xD6, 0x93, 0x5D, 0x8A, 0x58, 0x2A,
+ 0x9C, 0xA9, 0xA6, 0xAD, 0xF3, 0x5F, 0x85, 0x90, 0xDF, 0xF8, 0x7E, 0x0F, 0xEC, 0x30, 0x38, 0xFB,
+ 0x77, 0xC5, 0x91, 0x81, 0xD3, 0xFE, 0x15, 0xD0, 0x18, 0xC7, 0x6F, 0xF8, 0xF9, 0xAC, 0x5C, 0x31,
+ 0x70, 0xBC, 0x65, 0x86, 0x92, 0x6B, 0x4B, 0x37, 0x4D, 0x5B, 0xC9, 0xFB, 0xEA, 0xDE, 0x80, 0xB0,
+ 0x35, 0x6C, 0xAC, 0xD5, 0xBE, 0x7F, 0xE4, 0x1F, 0xF0, 0xFC, 0x2F, 0xD8, 0x5C, 0x01, 0xFE, 0x9F,
+ 0xF1, 0x60, 0x0E, 0xDF, 0xF1, 0x6E, 0xC0, 0x1C, 0x74, 0xC7, 0xFA, 0x4D, 0x66, 0xE5, 0x5E, 0x29,
+ 0x5E, 0x84, 0x92, 0xE9, 0xAD, 0x35, 0xFF, 0x00, 0xB7, 0xFD, 0xDF, 0x80, 0xD6, 0x06, 0xAE, 0xC9,
+ 0xAF, 0xC7, 0xFC, 0x80, 0x7F, 0xC1, 0x70, 0xBF, 0x61, 0x7C, 0x71, 0x7F, 0xF1, 0x63, 0x03, 0x1C,
+ 0x0F, 0x87, 0x63, 0x8F, 0x4E, 0x3E, 0xD3, 0xED, 0x49, 0x4E, 0xB5, 0x9B, 0x8D, 0x09, 0x59, 0x6F,
+ 0x67, 0x4D, 0xDB, 0xE4, 0xA7, 0xFA, 0x7E, 0x40, 0xB0, 0x15, 0x74, 0x57, 0x56, 0xF9, 0xFF, 0x00,
+ 0x90, 0x9F, 0xF0, 0xFC, 0x3F, 0xD8, 0x5F, 0xA7, 0xDB, 0xFE, 0x2C, 0xFA, 0x63, 0xFE, 0x15, 0xCF,
+ 0xB7, 0x4C, 0x7D, 0xA6, 0x92, 0xA9, 0x5B, 0x65, 0x42, 0x7F, 0xF9, 0x2F, 0xFF, 0x00, 0x24, 0x1F,
+ 0x50, 0xAB, 0xDD, 0x7D, 0xFF, 0x00, 0xF0, 0x03, 0xFE, 0x1F, 0x87, 0xFB, 0x0B, 0x0E, 0x3E, 0xDF,
+ 0xF1, 0x64, 0x76, 0xC7, 0xFC, 0x2B, 0xAC, 0x74, 0x1D, 0x31, 0xF6, 0x9F, 0xA5, 0x27, 0x5A, 0xA4,
+ 0x2C, 0xA5, 0x46, 0x4B, 0xFF, 0x00, 0x00, 0x5F, 0xFB, 0x70, 0xD6, 0x5F, 0x5B, 0xA3, 0x5F, 0x7F,
+ 0xFC, 0x01, 0x3F, 0xE1, 0xF8, 0x9F, 0xB0, 0xB7, 0xFC, 0xFF, 0x00, 0xFC, 0x58, 0xFF, 0x00, 0xC3,
+ 0x75, 0xFF, 0x00, 0xDD, 0x35, 0x1F, 0x5A, 0x69, 0x7F, 0x0A, 0x56, 0xF5, 0x87, 0xFF, 0x00, 0x24,
+ 0x1F, 0xD9, 0xF5, 0xFB, 0xAF, 0xEB, 0xE4, 0x1F, 0xF0, 0xFC, 0x4F, 0xD8, 0x5B, 0xFE, 0x7F, 0xFE,
+ 0x2C, 0x7F, 0xE1, 0xBA, 0xFF, 0x00, 0xEE, 0x9A, 0x7F, 0x59, 0x6A, 0xCB, 0xD9, 0x4B, 0xEF, 0x87,
+ 0xFF, 0x00, 0x24, 0x1F, 0xD9, 0xF5, 0xFB, 0xAF, 0xEB, 0xE4, 0x1F, 0xF0, 0xFC, 0x4F, 0xD8, 0x58,
+ 0x0F, 0xF8, 0xFF, 0x00, 0xF8, 0xB3, 0x80, 0x3A, 0x0F, 0x87, 0x5D, 0x80, 0xE8, 0x07, 0xDA, 0x7D,
+ 0xA9, 0x3C, 0x57, 0x2C, 0x5B, 0x74, 0xA5, 0x64, 0xBA, 0x72, 0xF4, 0xF2, 0x52, 0xBF, 0xC9, 0x2F,
+ 0x24, 0x0B, 0x2E, 0xAF, 0xA2, 0x4D, 0x7D, 0xFF, 0x00, 0xF0, 0x06, 0x8F, 0xF8, 0x2E, 0x3F, 0xEC,
+ 0x27, 0xD0, 0x6A, 0x1F, 0x16, 0x78, 0xC0, 0xC0, 0xF8, 0x70, 0x70, 0x38, 0xE0, 0x0F, 0xF4, 0x9F,
+ 0xA5, 0x71, 0xAC, 0xEB, 0x0A, 0xDB, 0x84, 0x69, 0xCD, 0xB4, 0xED, 0x65, 0x1B, 0xEA, 0xAD, 0xA6,
+ 0x97, 0x57, 0x5A, 0x69, 0xD0, 0xB5, 0x96, 0x62, 0x2C, 0xBE, 0x1B, 0x7A, 0x89, 0xFF, 0x00, 0x0F,
+ 0xC9, 0xFD, 0x84, 0xBF, 0xE8, 0x23, 0xF1, 0x63, 0xFF, 0x00, 0x0D, 0xC9, 0xFF, 0x00, 0xE4, 0x9A,
+ 0xC3, 0xFD, 0x63, 0xCB, 0x56, 0x9E, 0xF7, 0xFE, 0x02, 0x35, 0x95, 0x62, 0xAC, 0xAC, 0x95, 0xBD,
+ 0x7F, 0xE0, 0x07, 0xFC, 0x3F, 0x27, 0xF6, 0x12, 0xFF, 0x00, 0xA0, 0x8F, 0xC5, 0x8F, 0xFC, 0x37,
+ 0x27, 0xFF, 0x00, 0x92, 0x69, 0x7F, 0xAC, 0x99, 0x67, 0x79, 0x7F, 0xE0, 0x3F, 0xF0, 0x43, 0xFB,
+ 0x27, 0x15, 0xD9, 0x7D, 0xFF, 0x00, 0xF0, 0x07, 0x37, 0xFC, 0x17, 0x17, 0xF6, 0x15, 0x40, 0xBB,
+ 0xAF, 0xFE, 0x2D, 0x28, 0x65, 0x05, 0x7F, 0xE2, 0xDC, 0x10, 0x08, 0x23, 0x8C, 0x7F, 0xA4, 0xFD,
+ 0x2B, 0x79, 0x67, 0x78, 0x3A, 0x74, 0x63, 0x88, 0x94, 0x65, 0xEC, 0xDE, 0x8A, 0x5C, 0xBE, 0xEB,
+ 0x6B, 0xA2, 0x69, 0xDA, 0xEB, 0xAA, 0xDD, 0x6C, 0xD2, 0xB5, 0x87, 0x2C, 0xA3, 0x17, 0x09, 0x2A,
+ 0x72, 0x49, 0x3B, 0x27, 0x6B, 0xDB, 0x46, 0xB4, 0x76, 0xB6, 0xD6, 0xB5, 0x84, 0x5F, 0xF8, 0x2E,
+ 0x37, 0xEC, 0x28, 0x47, 0xCB, 0x7F, 0xF1, 0x68, 0x85, 0xC0, 0x3B, 0x7E, 0x1C, 0x1C, 0x2E, 0x7A,
+ 0x0F, 0xF8, 0xF9, 0xAE, 0x7F, 0xF5, 0x97, 0x2B, 0x8D, 0x93, 0x6D, 0x7C, 0xBB, 0x7C, 0xCA, 0x86,
+ 0x4D, 0x8E, 0x92, 0x6E, 0x11, 0x4D, 0x2B, 0x6D, 0xD2, 0xFA, 0x2D, 0x96, 0x97, 0xD9, 0x7E, 0x01,
+ 0xFF, 0x00, 0x0F, 0xC7, 0xFD, 0x85, 0x02, 0x86, 0xFE, 0xD0, 0xF8, 0xB4, 0x10, 0xFC, 0xAA, 0x7F,
+ 0xE1, 0x5C, 0x10, 0xB9, 0x03, 0x90, 0x0F, 0xDA, 0x7E, 0x95, 0xA2, 0xE2, 0x1C, 0xBB, 0x91, 0xCE,
+ 0x2A, 0x5C, 0xAA, 0xDB, 0x47, 0x45, 0x7B, 0xDB, 0xAE, 0x97, 0xB3, 0xB7, 0xA1, 0x9A, 0xCB, 0x31,
+ 0x17, 0xE4, 0x56, 0xBF, 0x6B, 0xFF, 0x00, 0xC0, 0x24, 0x87, 0xFE, 0x0B, 0x85, 0xFB, 0x0C, 0x4D,
+ 0xB8, 0x45, 0x7D, 0xF1, 0x65, 0x84, 0x69, 0xBD, 0xFF, 0x00, 0xE2, 0xDD, 0x05, 0x08, 0xA3, 0xB9,
+ 0xCD, 0xC8, 0xF6, 0xAF, 0x63, 0x25, 0xFA, 0xCF, 0x10, 0xFB, 0x75, 0x92, 0xE1, 0xE5, 0x55, 0x51,
+ 0x83, 0xA9, 0x52, 0xCE, 0x11, 0x50, 0x82, 0x69, 0x39, 0x37, 0x39, 0xC5, 0x59, 0x36, 0x96, 0x8D,
+ 0xBF, 0x2B, 0x19, 0xD4, 0xC0, 0x55, 0xA0, 0xA3, 0xED, 0x1A, 0x57, 0xD1, 0x7F, 0x49, 0x11, 0x7F,
+ 0xC3, 0xF2, 0x3F, 0x61, 0x30, 0x07, 0xFC, 0x4C, 0x7E, 0x2C, 0x0E, 0x38, 0x1F, 0xF0, 0xAE, 0x4F,
+ 0x00, 0x74, 0x18, 0xFB, 0x4F, 0xD2, 0xBC, 0x89, 0xE7, 0xF8, 0x0A, 0x36, 0x53, 0x52, 0x4F, 0xB5,
+ 0x95, 0xFE, 0x69, 0x3B, 0xAF, 0x2B, 0xA5, 0x75, 0x66, 0xB4, 0xB1, 0xA4, 0x72, 0xBC, 0x4B, 0x5E,
+ 0xEA, 0x56, 0xF5, 0xFF, 0x00, 0x80, 0x1F, 0xF0, 0xFC, 0x9F, 0xD8, 0x4B, 0xFE, 0x82, 0x3F, 0x16,
+ 0x3F, 0xF0, 0xDC, 0x9F, 0xFE, 0x49, 0xAC, 0xFF, 0x00, 0xD6, 0x4C, 0xB3, 0xBC, 0xBF, 0xF0, 0x1F,
+ 0xF8, 0x23, 0xFE, 0xC9, 0xC5, 0x76, 0x5F, 0x7F, 0xFC, 0x00, 0xFF, 0x00, 0x87, 0xE4, 0xFE, 0xC2,
+ 0x5F, 0xF4, 0x11, 0xF8, 0xB1, 0xFF, 0x00, 0x86, 0xE4, 0xFF, 0x00, 0xF2, 0x4D, 0x1F, 0xEB, 0x26,
+ 0x59, 0xDE, 0x5F, 0xF8, 0x0F, 0xFC, 0x10, 0xFE, 0xC9, 0xC5, 0x76, 0x5F, 0x7F, 0xFC, 0x03, 0x67,
+ 0x44, 0xFF, 0x00, 0x82, 0xD2, 0xFE, 0xC6, 0x5E, 0x24, 0xD5, 0x2C, 0xB4, 0x3F, 0x0F, 0x5B, 0x7C,
+ 0x6C, 0xD6, 0xF5, 0x8D, 0x44, 0x1F, 0xEC, 0xFD, 0x2F, 0x4A, 0xF8, 0x59, 0x25, 0xED, 0xF5, 0xD8,
+ 0x54, 0x2C, 0xDE, 0x5C, 0x49, 0x70, 0x58, 0xE1, 0x51, 0xCF, 0x03, 0x80, 0xA4, 0xF6, 0xAD, 0xE9,
+ 0xE7, 0x78, 0x3A, 0xA9, 0x3A, 0x71, 0x95, 0xB6, 0xBD, 0x92, 0x5B, 0x5E, 0xD7, 0x6D, 0x24, 0xEC,
+ 0xB4, 0x57, 0x57, 0xB6, 0x86, 0x53, 0xC0, 0xD5, 0xA5, 0x07, 0x39, 0xB4, 0x92, 0xDF, 0x5E, 0xDD,
+ 0x92, 0x57, 0x7F, 0x24, 0x5F, 0xF1, 0x1F, 0xFC, 0x16, 0x4B, 0xF6, 0x40, 0xF0, 0x79, 0xB0, 0x5F,
+ 0x13, 0xD8, 0x7C, 0x6A, 0xD1, 0x06, 0xA5, 0xA6, 0x5B, 0xEA, 0xF6, 0x06, 0xEF, 0xE1, 0xA0, 0xF2,
+ 0xEE, 0x2D, 0x6E, 0xD0, 0xB5, 0xB4, 0xAA, 0xEB, 0x74, 0x54, 0x6F, 0x55, 0x62, 0x14, 0x90, 0xC3,
+ 0x1C, 0x81, 0x5B, 0x62, 0x33, 0x3A, 0x78, 0x48, 0x46, 0xA5, 0x7A, 0x53, 0x8C, 0x1A, 0x4D, 0x3E,
+ 0x5B, 0xC6, 0xCF, 0x44, 0xEE, 0x9B, 0x5A, 0xDB, 0x4D, 0x76, 0xB5, 0xB4, 0xB1, 0x34, 0xF0, 0x73,
+ 0xA9, 0x2F, 0x65, 0x09, 0x47, 0x9B, 0xB5, 0xEC, 0xEC, 0xAD, 0xB2, 0x69, 0x3B, 0x2D, 0x35, 0x4A,
+ 0xDD, 0x0E, 0x6F, 0xFE, 0x1F, 0x87, 0xFB, 0x0C, 0x02, 0x89, 0xF6, 0xCF, 0x8B, 0xA1, 0x9F, 0x02,
+ 0x34, 0xFF, 0x00, 0x85, 0x6C, 0xC0, 0xBF, 0xA0, 0x51, 0xF6, 0x9E, 0x7B, 0x74, 0xAC, 0x5E, 0x77,
+ 0x85, 0x83, 0x8C, 0x25, 0x4E, 0x69, 0xB5, 0x74, 0xB9, 0x1A, 0xBA, 0xB6, 0xE9, 0x76, 0xB7, 0x6D,
+ 0x2C, 0x68, 0xB2, 0xEA, 0xDC, 0xAE, 0x4A, 0x51, 0xE5, 0x5B, 0xBB, 0xAB, 0x2F, 0xF2, 0x23, 0xFF,
+ 0x00, 0x87, 0xE3, 0xFE, 0xC2, 0x80, 0xED, 0xFE, 0xD0, 0xF8, 0xB2, 0x08, 0xF9, 0x76, 0xFF, 0x00,
+ 0xC2, 0xB8, 0x20, 0x82, 0x3B, 0x63, 0xED, 0x3E, 0xD5, 0x9A, 0xE2, 0x0C, 0x03, 0x9A, 0xA5, 0x18,
+ 0xCB, 0x9B, 0x6B, 0x72, 0xEB, 0x7D, 0xAD, 0x6F, 0xD0, 0xA5, 0x95, 0xE2, 0x79, 0x53, 0x5C, 0xB6,
+ 0xF5, 0xD0, 0x07, 0xFC, 0x17, 0x23, 0xF6, 0x13, 0xC7, 0x1A, 0x8F, 0xC5, 0x9C, 0x0C, 0x0E, 0x3E,
+ 0x1C, 0x1C, 0x0F, 0x41, 0xFF, 0x00, 0x1F, 0x3E, 0xD4, 0x97, 0x10, 0xE5, 0xFC, 0xAE, 0x49, 0x4B,
+ 0x95, 0x5A, 0xFE, 0xEE, 0x8B, 0xB7, 0xA6, 0xDA, 0x0D, 0x65, 0x58, 0x9D, 0x12, 0xB7, 0xDE, 0x03,
+ 0xFE, 0x0B, 0x91, 0xFB, 0x09, 0xF0, 0x06, 0xA3, 0xF1, 0x67, 0xD8, 0x0F, 0x87, 0x27, 0xB0, 0xEC,
+ 0x3E, 0xD3, 0xED, 0x44, 0x38, 0x87, 0x2E, 0x93, 0x51, 0x82, 0x93, 0x7D, 0x94, 0x7B, 0x79, 0x2E,
+ 0xC8, 0x3F, 0xB2, 0xB1, 0x49, 0x6C, 0xAD, 0xEB, 0xFF, 0x00, 0x00, 0x3F, 0xE1, 0xF9, 0x3F, 0xB0,
+ 0x97, 0xFD, 0x04, 0x7E, 0x2C, 0x7F, 0xE1, 0xB9, 0x3F, 0xFC, 0x93, 0x53, 0xFE, 0xB2, 0x65, 0x9D,
+ 0xE5, 0xFF, 0x00, 0x80, 0xFF, 0x00, 0xC1, 0x0F, 0xEC, 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0,
+ 0x0F, 0xF8, 0x7E, 0x4F, 0xEC, 0x25, 0xFF, 0x00, 0x41, 0x1F, 0x8B, 0x1F, 0xF8, 0x6E, 0x4F, 0xFF,
+ 0x00, 0x24, 0xD1, 0xFE, 0xB2, 0x65, 0x89, 0x2D, 0x65, 0x6F, 0xF0, 0xFF, 0x00, 0xC1, 0x0F, 0xEC,
+ 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0, 0x0F, 0xF8, 0x7E, 0x4F, 0xEC, 0x25, 0xFF, 0x00, 0x41,
+ 0x1F, 0x8B, 0x1F, 0xF8, 0x6E, 0x4F, 0xFF, 0x00, 0x24, 0xD1, 0xFE, 0xB2, 0x65, 0x9D, 0xE5, 0xFF,
+ 0x00, 0x80, 0xFF, 0x00, 0xC1, 0x0F, 0xEC, 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0, 0x03, 0xFF,
+ 0x00, 0x05, 0xC7, 0xFD, 0x85, 0x17, 0x00, 0xEA, 0x1F, 0x16, 0x57, 0xE5, 0x04, 0x03, 0xF0, 0xE0,
+ 0x8E, 0x08, 0xE0, 0x81, 0xF6, 0x9E, 0x9D, 0x29, 0x2E, 0x25, 0xCA, 0xDA, 0xF7, 0x5C, 0xAD, 0xE9,
+ 0xFF, 0x00, 0x04, 0xA9, 0x64, 0xF8, 0xD8, 0x59, 0x4A, 0x29, 0x68, 0x9A, 0xBE, 0x9A, 0x3D, 0xBA,
+ 0x6D, 0x6D, 0x83, 0xFE, 0x1F, 0x93, 0xFB, 0x09, 0x7F, 0xD0, 0x47, 0xE2, 0xC7, 0xFE, 0x1B, 0x93,
+ 0xFF, 0x00, 0xC9, 0x34, 0xFF, 0x00, 0xD6, 0x4C, 0xB3, 0xBC, 0xBF, 0xF0, 0x1F, 0xF8, 0x24, 0xFF,
+ 0x00, 0x64, 0xE2, 0xBB, 0x2F, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0xF2, 0x7F, 0x61, 0x2F, 0xFA, 0x08,
+ 0xFC, 0x58, 0xFF, 0x00, 0xC3, 0x72, 0x7F, 0xF9, 0x26, 0x8F, 0xF5, 0x93, 0x2C, 0xEF, 0x2F, 0xFC,
+ 0x07, 0xFE, 0x08, 0x7F, 0x64, 0xE2, 0xBB, 0x2F, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0xF2, 0x7F, 0x61,
+ 0x2F, 0xFA, 0x08, 0xFC, 0x58, 0xFF, 0x00, 0xC3, 0x72, 0x7F, 0xF9, 0x26, 0x8F, 0xF5, 0x93, 0x2C,
+ 0xEF, 0x2F, 0xFC, 0x07, 0xFE, 0x08, 0x7F, 0x64, 0xE2, 0xBB, 0x2F, 0xBF, 0xFE, 0x00, 0xE4, 0xFF,
+ 0x00, 0x82, 0xE2, 0xFE, 0xC2, 0xAE, 0x42, 0xA5, 0xFF, 0x00, 0xC5, 0xA3, 0xD8, 0x01, 0xF0, 0xE0,
+ 0x81, 0xC0, 0xE9, 0xFF, 0x00, 0x1F, 0x3F, 0x4A, 0xED, 0xC1, 0x66, 0x54, 0xF3, 0x09, 0xC6, 0x8E,
+ 0x06, 0x94, 0xE7, 0x27, 0xB5, 0xA3, 0x65, 0xA2, 0xEE, 0xDA, 0x4A, 0xDE, 0xAB, 0xA2, 0xEC, 0x89,
+ 0x96, 0x5B, 0x5E, 0x9A, 0xF7, 0x9C, 0x52, 0xF5, 0xFF, 0x00, 0x80, 0x5C, 0x4F, 0xF8, 0x2D, 0xB7,
+ 0xEC, 0x40, 0xEA, 0x0A, 0x5D, 0x7C, 0x59, 0x23, 0xA0, 0xC7, 0xC3, 0xD5, 0x5E, 0x83, 0xD3, 0xED,
+ 0x43, 0xDA, 0xBE, 0xDB, 0x07, 0xC1, 0x7C, 0x63, 0x8E, 0xA7, 0x1A, 0x98, 0x4C, 0xB2, 0x6E, 0x2F,
+ 0x6F, 0x7F, 0x0F, 0x1F, 0xC2, 0x55, 0x93, 0xFC, 0x0E, 0x57, 0x45, 0x43, 0x47, 0x25, 0xF8, 0xFE,
+ 0x88, 0x5F, 0xF8, 0x7D, 0xA7, 0xEC, 0x44, 0x38, 0xFB, 0x4F, 0xC5, 0x91, 0x81, 0xFF, 0x00, 0x44,
+ 0xF9, 0x30, 0x30, 0x3A, 0x7F, 0xC7, 0xDF, 0xD2, 0xBA, 0xDF, 0x87, 0xDC, 0x77, 0x15, 0xAE, 0x55,
+ 0x3B, 0x79, 0x55, 0xC3, 0x3F, 0xCA, 0xBB, 0xFC, 0x04, 0xA9, 0xC3, 0x44, 0xA6, 0xBF, 0x1F, 0xF2,
+ 0x01, 0xFF, 0x00, 0x05, 0xB4, 0xFD, 0x88, 0x71, 0xFF, 0x00, 0x1F, 0x5F, 0x16, 0x46, 0x38, 0xC7,
+ 0xFC, 0x2B, 0xD4, 0x1D, 0x07, 0x18, 0xFF, 0x00, 0x4A, 0xFA, 0x56, 0x1F, 0xEA, 0x37, 0x1A, 0x47,
+ 0x4F, 0xEC, 0xB9, 0xFF, 0x00, 0xE0, 0xCC, 0x37, 0xFF, 0x00, 0x2E, 0x1A, 0xA2, 0xAC, 0xAD, 0x25,
+ 0x6F, 0x9F, 0xF9, 0x07, 0xFC, 0x3E, 0xD7, 0xF6, 0x20, 0x18, 0x1F, 0x6A, 0xF8, 0xB3, 0xD0, 0x70,
+ 0x3E, 0x1E, 0xA6, 0x00, 0xED, 0xFF, 0x00, 0x2F, 0x55, 0x3F, 0xEA, 0x4F, 0x19, 0xAD, 0x3F, 0xB3,
+ 0x27, 0xD3, 0xFE, 0x5E, 0x61, 0xFF, 0x00, 0xF9, 0x77, 0xFC, 0x37, 0x5B, 0x68, 0x1E, 0xC5, 0x59,
+ 0x7B, 0xCA, 0xDF, 0x3F, 0xF2, 0x2A, 0xCB, 0xFF, 0x00, 0x05, 0xC1, 0xFD, 0x86, 0x2D, 0xC8, 0x49,
+ 0x6F, 0xBE, 0x2D, 0x46, 0x71, 0xC0, 0xFF, 0x00, 0x85, 0x75, 0x91, 0x80, 0x3B, 0x11, 0x73, 0x8F,
+ 0x4A, 0xF9, 0x6C, 0xEF, 0xEB, 0x5C, 0x35, 0x5E, 0x38, 0x5C, 0xF3, 0x0D, 0x3A, 0x33, 0x7B, 0x26,
+ 0xA3, 0x24, 0xEC, 0x96, 0xCE, 0x12, 0x94, 0x5A, 0x57, 0x5B, 0x3F, 0x2E, 0x86, 0xF4, 0xB0, 0x15,
+ 0x6B, 0x46, 0xF4, 0x9A, 0x6B, 0xD6, 0xDF, 0xA2, 0x22, 0xFF, 0x00, 0x87, 0xE4, 0xFE, 0xC2, 0x5F,
+ 0xF4, 0x11, 0xF8, 0xB1, 0xFF, 0x00, 0x86, 0xE4, 0xFF, 0x00, 0xF2, 0x4D, 0x78, 0x7F, 0xEB, 0x26,
+ 0x59, 0xDE, 0x5F, 0xF8, 0x0F, 0xFC, 0x13, 0x5F, 0xEC, 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0,
+ 0x0F, 0xF8, 0x7E, 0x4F, 0xEC, 0x25, 0xFF, 0x00, 0x41, 0x1F, 0x8B, 0x1F, 0xF8, 0x6E, 0x4F, 0xFF,
+ 0x00, 0x24, 0xD1, 0xFE, 0xB2, 0x65, 0x9D, 0xE5, 0xFF, 0x00, 0x80, 0xFF, 0x00, 0xC1, 0x0F, 0xEC,
+ 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0, 0x0F, 0xF8, 0x7E, 0x4F, 0xEC, 0x25, 0xFF, 0x00, 0x41,
+ 0x1F, 0x8B, 0x1F, 0xF8, 0x6E, 0x4F, 0xFF, 0x00, 0x24, 0xD1, 0xFE, 0xB2, 0x65, 0x9D, 0xE5, 0xFF,
+ 0x00, 0x80, 0xFF, 0x00, 0xC1, 0x0F, 0xEC, 0x9C, 0x57, 0x65, 0xF7, 0xFF, 0x00, 0xC0, 0x3B, 0xAF,
+ 0x08, 0xFF, 0x00, 0xC1, 0x5E, 0xBF, 0x65, 0x5F, 0x1D, 0xB8, 0x8F, 0xC1, 0xDE, 0x1F, 0xF8, 0xED,
+ 0xAF, 0x0E, 0x07, 0x9D, 0x65, 0xF0, 0xB4, 0xC7, 0x66, 0x3D, 0x01, 0xB8, 0x7B, 0xA5, 0x88, 0x74,
+ 0xE8, 0x58, 0x57, 0x44, 0x33, 0x9C, 0x2C, 0xE2, 0xA5, 0x08, 0x4E, 0xCF, 0x6F, 0x75, 0x2B, 0xFA,
+ 0x5D, 0xAB, 0xFC, 0x8C, 0x67, 0x82, 0x9D, 0x2D, 0x27, 0x28, 0xAF, 0x2B, 0xFE, 0x89, 0x1E, 0xA6,
+ 0x3F, 0xE0, 0xA1, 0xDF, 0x09, 0x76, 0x07, 0xFF, 0x00, 0x85, 0x71, 0xF1, 0xC4, 0x26, 0x38, 0xFF,
+ 0x00, 0x8A, 0x53, 0x47, 0x04, 0x01, 0xEA, 0xBF, 0xDA, 0xB9, 0x1D, 0x07, 0x6F, 0x4A, 0xDD, 0x66,
+ 0x11, 0xB5, 0xD5, 0x19, 0xDB, 0xBF, 0x2A, 0xB7, 0xE7, 0x63, 0x0F, 0x65, 0x04, 0xBE, 0x38, 0xFE,
+ 0x3F, 0xE4, 0x79, 0xA7, 0x8B, 0x3F, 0xE0, 0xAE, 0x1F, 0xB2, 0xEF, 0x80, 0xD7, 0x77, 0x8B, 0xBC,
+ 0x35, 0xF1, 0xDF, 0x42, 0x88, 0x0E, 0x6E, 0x2E, 0x3E, 0x17, 0x79, 0xF6, 0x49, 0x83, 0x8C, 0x19,
+ 0xE2, 0xBA, 0x78, 0x87, 0x4E, 0x85, 0x85, 0x63, 0x3C, 0xE3, 0x0B, 0x4A, 0x37, 0x9C, 0x24, 0x97,
+ 0xF8, 0x56, 0x96, 0xB7, 0x44, 0xF4, 0xDD, 0x76, 0xED, 0xD1, 0xA5, 0xB5, 0x3C, 0x1C, 0xEA, 0x59,
+ 0x53, 0x94, 0x7E, 0xFB, 0x7E, 0x87, 0x9E, 0xFF, 0x00, 0xC3, 0xF2, 0x7F, 0x61, 0x2F, 0xFA, 0x08,
+ 0xFC, 0x58, 0xFF, 0x00, 0xC3, 0x72, 0x7F, 0xF9, 0x26, 0xB9, 0xBF, 0xD6, 0x4C, 0xB3, 0xBC, 0xBF,
+ 0xF0, 0x1F, 0xF8, 0x26, 0xFF, 0x00, 0xD9, 0x38, 0xAE, 0xCB, 0xEF, 0xFF, 0x00, 0x80, 0x7D, 0x93,
+ 0xFB, 0x25, 0x7E, 0xDB, 0x5F, 0x04, 0x7F, 0x6D, 0x48, 0x3E, 0x22, 0xDC, 0x7C, 0x0F, 0x3E, 0x31,
+ 0xBB, 0xB7, 0xF8, 0x58, 0x74, 0x75, 0xF1, 0x64, 0xBE, 0x25, 0xF0, 0xC9, 0xD0, 0x52, 0x03, 0xAE,
+ 0x2D, 0xF9, 0xB1, 0xF2, 0x71, 0x23, 0xEF, 0x18, 0xD1, 0x6F, 0x4B, 0x13, 0xB4, 0x2E, 0x13, 0xAE,
+ 0x7E, 0x5F, 0x43, 0x01, 0x99, 0x61, 0xB3, 0x05, 0x3F, 0xAB, 0x5E, 0xD1, 0xB5, 0xEE, 0xAD, 0xBD,
+ 0xED, 0x6F, 0xB8, 0xE6, 0xC4, 0x61, 0x2A, 0xE1, 0x79, 0x55, 0x44, 0xB5, 0xDA, 0xDE, 0x56, 0xFF,
+ 0x00, 0x34, 0x7D, 0x77, 0x5D, 0xE7, 0x30, 0x50, 0x01, 0x40, 0x05, 0x00, 0x7F, 0x14, 0x5F, 0xF0,
+ 0x5A, 0xFF, 0x00, 0xF9, 0x48, 0x1F, 0xC4, 0x8F, 0xFB, 0x12, 0xFC, 0x27, 0xFF, 0x00, 0xA8, 0xF5,
+ 0xAD, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE,
+ 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0x58, 0xE9, 0x5A, 0xBD, 0xEE, 0x91, 0x75, 0x6F, 0x75, 0x69, 0x3C,
+ 0x91, 0xBD, 0xB1, 0x2D, 0x00, 0x59, 0x64, 0x8D, 0x22, 0x2C, 0x30, 0xC5, 0x42, 0x32, 0x91, 0x91,
+ 0x91, 0xC1, 0x15, 0xE6, 0xE1, 0x2A, 0xD3, 0xC3, 0xD4, 0x75, 0x25, 0x14, 0xDD, 0xAC, 0xB4, 0x5D,
+ 0xD7, 0x5D, 0xD6, 0x97, 0xD6, 0x2D, 0x3E, 0x89, 0xA4, 0x7A, 0x4A, 0xA5, 0x78, 0x45, 0x42, 0x95,
+ 0x47, 0x18, 0xDE, 0xED, 0x68, 0xD3, 0xF5, 0x8B, 0x4E, 0x2F, 0xA6, 0x8D, 0x74, 0x47, 0xAB, 0x9F,
+ 0xEC, 0xFF, 0x00, 0x16, 0xAE, 0x90, 0x9E, 0x18, 0xB2, 0x98, 0xF8, 0x86, 0x35, 0xB8, 0x6D, 0x40,
+ 0xD9, 0xE9, 0xB7, 0xD3, 0xFF, 0x00, 0x68, 0x00, 0x01, 0x86, 0x12, 0x86, 0x69, 0xD8, 0x15, 0x55,
+ 0x6C, 0x6D, 0x00, 0x63, 0x76, 0x49, 0xE2, 0xBF, 0x6D, 0xF0, 0xBF, 0x31, 0xE3, 0xDC, 0xAF, 0x19,
+ 0x2E, 0x2A, 0xE1, 0x0C, 0x15, 0x49, 0xE0, 0x30, 0xCD, 0x46, 0xBC, 0xA1, 0x07, 0xC8, 0xAF, 0x1D,
+ 0x14, 0xB5, 0xBC, 0xA4, 0x93, 0xBD, 0xB5, 0xBE, 0x9A, 0xEC, 0x8E, 0x2C, 0xD3, 0xFB, 0x32, 0x58,
+ 0x7F, 0x69, 0x9A, 0x62, 0x52, 0xAD, 0x34, 0xB9, 0x57, 0xBA, 0x92, 0x6B, 0x74, 0xE2, 0xA3, 0x15,
+ 0x15, 0xA2, 0xB5, 0x9B, 0x5B, 0xBB, 0x6B, 0x65, 0x07, 0x87, 0x35, 0x26, 0xD0, 0xF5, 0xFB, 0x1B,
+ 0xDB, 0x9B, 0x37, 0x8E, 0x5D, 0x36, 0xF5, 0x4D, 0xEE, 0x9F, 0x73, 0x6A, 0x48, 0x2D, 0x1B, 0x7C,
+ 0xD1, 0xCB, 0x0B, 0x15, 0x0C, 0x38, 0xC1, 0x42, 0x57, 0x23, 0x23, 0x23, 0x39, 0x1F, 0xDC, 0xDC,
+ 0x07, 0xC5, 0xF4, 0x73, 0x59, 0x43, 0x36, 0xC9, 0xE8, 0xBB, 0xD4, 0x8B, 0x8D, 0x7A, 0x5C, 0xAE,
+ 0x0A, 0x57, 0x8D, 0x9B, 0xBB, 0x56, 0x52, 0x57, 0xE6, 0x8F, 0x33, 0xDD, 0x25, 0x6E, 0x87, 0xC2,
+ 0xE6, 0x18, 0x5F, 0xAC, 0x60, 0xA5, 0x46, 0x13, 0x5C, 0xB2, 0x5E, 0xEC, 0xB4, 0x69, 0x2F, 0x2D,
+ 0xD2, 0x7D, 0x9D, 0x9D, 0x9D, 0x9D, 0xB4, 0xB1, 0xF6, 0xA6, 0xA1, 0xE3, 0x3F, 0x03, 0xFC, 0x1C,
+ 0xF1, 0x17, 0x80, 0xFE, 0x3C, 0x7E, 0xCE, 0xFF, 0x00, 0x10, 0xB4, 0xA8, 0x7C, 0x4E, 0x97, 0x82,
+ 0xCF, 0xC5, 0x7F, 0x0C, 0xE4, 0x17, 0x29, 0x1C, 0x64, 0xC4, 0x3E, 0xD0, 0xA2, 0x31, 0x1C, 0x49,
+ 0x26, 0x9D, 0x32, 0x86, 0x47, 0x89, 0x98, 0x61, 0x89, 0xC0, 0x23, 0x04, 0xFA, 0x54, 0x70, 0x78,
+ 0xDE, 0x2E, 0xFA, 0xC7, 0x0E, 0x66, 0x94, 0x13, 0xC2, 0x35, 0x29, 0x50, 0x9D, 0x49, 0x41, 0xD4,
+ 0xA3, 0x27, 0x7D, 0x23, 0xCC, 0xEC, 0xAD, 0x7B, 0x59, 0x7C, 0x2A, 0xFC, 0xAE, 0xFB, 0x7C, 0x7E,
+ 0x45, 0x4B, 0x34, 0x96, 0x0E, 0x59, 0x6E, 0x79, 0x41, 0xB8, 0x5B, 0x49, 0x4A, 0xD2, 0xBA, 0x56,
+ 0xB2, 0x7B, 0xB6, 0xD3, 0xD5, 0x3D, 0x1D, 0x92, 0x4F, 0x4B, 0x1F, 0x62, 0xFE, 0xD0, 0x7E, 0x36,
+ 0xFD, 0x97, 0xFF, 0x00, 0x6A, 0x8F, 0x84, 0x3E, 0x1C, 0xF1, 0x86, 0x8F, 0xF1, 0x13, 0xC3, 0x3F,
+ 0x0C, 0x3E, 0x2F, 0x78, 0x6C, 0x47, 0x3E, 0x87, 0xA7, 0x78, 0x8E, 0xF1, 0xED, 0x75, 0x6D, 0x3D,
+ 0x95, 0x43, 0x4B, 0xA2, 0xDC, 0x4D, 0xE4, 0xB4, 0x92, 0x5B, 0x2B, 0xB1, 0x78, 0x66, 0x46, 0x18,
+ 0x63, 0x82, 0xA0, 0x27, 0x3F, 0x15, 0xC2, 0xB9, 0x67, 0x1C, 0x70, 0x67, 0x11, 0x3C, 0x16, 0x37,
+ 0x05, 0x3A, 0x94, 0x2A, 0x73, 0x42, 0xD0, 0xB5, 0x9B, 0xBA, 0x49, 0xBB, 0x5A, 0x31, 0x4D, 0x45,
+ 0x2F, 0x7B, 0x9A, 0x56, 0xBD, 0xA5, 0x75, 0x61, 0x42, 0x55, 0x72, 0x89, 0xFD, 0x4E, 0x8D, 0x19,
+ 0x55, 0xC3, 0xA8, 0xBD, 0x14, 0x64, 0xDA, 0x57, 0x6E, 0xC9, 0xB5, 0x18, 0xC9, 0x7E, 0x37, 0x6F,
+ 0xA6, 0x8A, 0x5F, 0x84, 0xBF, 0xB4, 0x6F, 0xC1, 0xFF, 0x00, 0x8E, 0x1F, 0x05, 0xEF, 0x3E, 0x0F,
+ 0xFE, 0xD2, 0x3E, 0x24, 0xD0, 0xF4, 0x8D, 0x6A, 0xC5, 0x63, 0xD1, 0xA4, 0xD5, 0x6E, 0xB4, 0x89,
+ 0x9D, 0x3C, 0x56, 0x40, 0x64, 0xD3, 0xB5, 0x1B, 0x29, 0x21, 0x8C, 0x95, 0xBC, 0x85, 0x4E, 0x0B,
+ 0xB2, 0x86, 0x94, 0x9C, 0x82, 0x30, 0x05, 0x7A, 0xFC, 0x61, 0xC1, 0x5C, 0x55, 0xC3, 0xD9, 0xAD,
+ 0x3C, 0xF7, 0x22, 0xC3, 0x54, 0xF6, 0x36, 0x53, 0x71, 0x72, 0xF7, 0xA3, 0x17, 0x6E, 0x66, 0xDD,
+ 0xDC, 0x5B, 0x6D, 0x26, 0xE2, 0xA7, 0xCA, 0xA2, 0x92, 0x7A, 0x5E, 0xD9, 0xD7, 0xCB, 0x6B, 0x65,
+ 0xD5, 0xDE, 0x3B, 0x06, 0xD2, 0xA5, 0xA4, 0x9A, 0xD5, 0x72, 0xAB, 0x5D, 0xA7, 0xEE, 0xA8, 0x27,
+ 0x14, 0xAD, 0x1B, 0xFB, 0xB6, 0x52, 0xD5, 0xA7, 0xAF, 0x83, 0xFC, 0x35, 0xF1, 0x31, 0xFD, 0x99,
+ 0xBC, 0x73, 0xE2, 0x4F, 0x00, 0xF8, 0x9B, 0x53, 0x6F, 0x15, 0xFC, 0x08, 0xF1, 0x05, 0xD4, 0xDF,
+ 0x63, 0xF1, 0x8D, 0xB5, 0x9D, 0xCA, 0xDB, 0x69, 0xC0, 0xA4, 0x82, 0xDE, 0xE6, 0x2B, 0x77, 0x83,
+ 0xCE, 0xCB, 0xAA, 0xC7, 0x1C, 0x88, 0xAA, 0x07, 0xCE, 0x59, 0x72, 0x47, 0x1F, 0x79, 0x8D, 0xC1,
+ 0x62, 0xB8, 0xC7, 0x25, 0xA7, 0x99, 0x50, 0xA0, 0xE9, 0xE6, 0x09, 0x46, 0x33, 0x4D, 0x2E, 0x69,
+ 0xBB, 0x45, 0xDE, 0xC9, 0xB4, 0xA3, 0x7F, 0x89, 0x35, 0xAB, 0xEB, 0x6D, 0x1F, 0x97, 0x98, 0x3C,
+ 0xAF, 0x3C, 0xC2, 0xA8, 0x61, 0xE4, 0xBE, 0xB4, 0xD4, 0x5D, 0x92, 0xB3, 0x92, 0xB5, 0xAF, 0xB2,
+ 0xD1, 0x2B, 0xBE, 0xAD, 0x46, 0x36, 0xB6, 0xC8, 0xF1, 0xDF, 0x89, 0xBE, 0x1C, 0x9F, 0xE1, 0x67,
+ 0xC4, 0x3D, 0x1F, 0xE2, 0x67, 0xC1, 0x6D, 0x42, 0xF7, 0x53, 0xD0, 0x24, 0x95, 0xB5, 0x78, 0xDF,
+ 0x4F, 0xD2, 0x6E, 0xAC, 0xAC, 0xF4, 0x6F, 0x9F, 0x33, 0x5A, 0x32, 0x4B, 0x04, 0x43, 0xEC, 0xF2,
+ 0x2B, 0x36, 0x13, 0x61, 0x18, 0xC8, 0x20, 0x64, 0x2D, 0x74, 0x64, 0xD2, 0xA5, 0x9B, 0xE5, 0x2F,
+ 0x87, 0xF1, 0x54, 0x17, 0xB4, 0x8D, 0x9B, 0x6D, 0xAD, 0xFE, 0x1B, 0x36, 0x9B, 0x76, 0xF7, 0x53,
+ 0xBA, 0x6D, 0xAB, 0xA7, 0x16, 0xD9, 0xE8, 0xE5, 0x59, 0x8D, 0x0C, 0x7E, 0x5F, 0x1C, 0xA7, 0x38,
+ 0xAF, 0x1A, 0x92, 0x4F, 0x92, 0x3A, 0x3B, 0x49, 0x73, 0x7B, 0xAA, 0x37, 0xD2, 0x4D, 0x3D, 0x2E,
+ 0xAD, 0x7D, 0xAD, 0xA5, 0xCF, 0x56, 0xFD, 0xA4, 0xFC, 0x71, 0xFB, 0x3F, 0x7C, 0x6E, 0xF8, 0x63,
+ 0xE1, 0x9F, 0x1A, 0xE9, 0xBE, 0x3A, 0xB1, 0xD1, 0x3E, 0x2F, 0xE9, 0x5A, 0x54, 0x24, 0xF8, 0x4A,
+ 0x4D, 0x1F, 0x52, 0x92, 0x79, 0xE1, 0x77, 0x02, 0xE3, 0x4D, 0xBA, 0xBB, 0x4B, 0x51, 0x6C, 0x65,
+ 0x8C, 0x96, 0x91, 0x66, 0xDC, 0x03, 0x0D, 0xA8, 0x00, 0x0B, 0x5F, 0x31, 0xC2, 0xD9, 0x77, 0x15,
+ 0xF0, 0xC7, 0x12, 0x4E, 0x8E, 0x17, 0x0B, 0x27, 0x97, 0xCD, 0xA8, 0xC9, 0xA7, 0x15, 0x17, 0x07,
+ 0x74, 0xE6, 0x9D, 0xF9, 0x96, 0xDE, 0xEC, 0x53, 0x6D, 0x6E, 0xD6, 0xA9, 0x1E, 0xB6, 0x1E, 0x96,
+ 0x23, 0x2F, 0xB5, 0x1F, 0x67, 0xCD, 0x1B, 0xEC, 0xAE, 0xDA, 0xEC, 0x93, 0x71, 0x8C, 0x7D, 0xDD,
+ 0x6F, 0x7B, 0x69, 0x64, 0xBA, 0x5B, 0xF3, 0xD6, 0xCB, 0x47, 0xBF, 0xD5, 0x27, 0x10, 0x69, 0x76,
+ 0x37, 0x57, 0x65, 0xD8, 0x08, 0xD2, 0x18, 0x8B, 0xF5, 0x20, 0x01, 0x91, 0xC7, 0x52, 0x05, 0x7E,
+ 0xB7, 0x8B, 0xAB, 0x80, 0xCB, 0xE0, 0xE7, 0x8A, 0xAD, 0x18, 0xC5, 0x79, 0xC5, 0xEC, 0xAE, 0xD2,
+ 0xB5, 0xAF, 0xB3, 0xB5, 0x92, 0x5A, 0x6B, 0x67, 0xA2, 0xFA, 0xDC, 0x16, 0x59, 0x98, 0xE6, 0x75,
+ 0x1C, 0x32, 0xDC, 0x3C, 0xA6, 0xBC, 0x96, 0x89, 0x79, 0xBD, 0x22, 0x92, 0x5B, 0xB6, 0xD2, 0x4B,
+ 0x5D, 0x11, 0xE9, 0x7A, 0x5F, 0xC1, 0x1F, 0x1A, 0x5F, 0xC6, 0xB3, 0xDD, 0xDB, 0x5B, 0x69, 0x56,
+ 0xBB, 0x41, 0x69, 0x6F, 0x65, 0x55, 0xD8, 0xB9, 0x00, 0x9C, 0x74, 0xEE, 0x31, 0xC8, 0xCF, 0x6A,
+ 0xF8, 0x5C, 0xD3, 0x8F, 0x78, 0x6B, 0x0E, 0xD5, 0x1C, 0x3C, 0x9D, 0x59, 0x5B, 0x45, 0x18, 0xBB,
+ 0x7C, 0xB7, 0x76, 0xB2, 0xBB, 0xD1, 0x59, 0x6B, 0xD2, 0xC7, 0xD6, 0xE0, 0x7C, 0x3F, 0xCC, 0xEA,
+ 0xA4, 0xF1, 0xB5, 0x61, 0x49, 0x76, 0x57, 0x9C, 0xAD, 0xE4, 0xA2, 0xB9, 0x76, 0x4E, 0xD7, 0x92,
+ 0xDA, 0xCE, 0xC7, 0x62, 0xFF, 0x00, 0xB3, 0xF4, 0x1A, 0x75, 0x8C, 0xD7, 0xBA, 0xCE, 0xBC, 0x7C,
+ 0xAB, 0x68, 0x44, 0x93, 0x47, 0xA7, 0x46, 0x19, 0x94, 0x8C, 0x64, 0x29, 0x23, 0x07, 0x86, 0x5E,
+ 0x33, 0xEB, 0xE9, 0x8A, 0xF8, 0x2C, 0x67, 0x88, 0x2B, 0x12, 0xFD, 0x86, 0x1F, 0x0B, 0xC9, 0x16,
+ 0xD6, 0xB3, 0x7A, 0x47, 0x5B, 0x6B, 0xCA, 0xEE, 0xBE, 0xEB, 0x77, 0xB5, 0xB4, 0xFA, 0xAC, 0xB3,
+ 0xC3, 0x7C, 0xB2, 0xB5, 0x58, 0x61, 0xEA, 0x57, 0xA9, 0x3A, 0x8E, 0xC9, 0x28, 0xA8, 0x41, 0x5F,
+ 0x6D, 0xDF, 0x3E, 0x9A, 0x5A, 0xD6, 0x4E, 0xF6, 0x39, 0x96, 0xF0, 0x07, 0x84, 0xE2, 0x26, 0x37,
+ 0x9B, 0x50, 0x65, 0x00, 0xAC, 0x2E, 0xD8, 0x51, 0x23, 0x63, 0xE5, 0x0C, 0xA1, 0x88, 0xEA, 0x07,
+ 0x39, 0x1F, 0x4E, 0x80, 0xFE, 0x7F, 0xC7, 0x9C, 0x6B, 0xE2, 0x1E, 0x59, 0x81, 0x82, 0xC9, 0x68,
+ 0x53, 0xAB, 0x18, 0xBD, 0x6D, 0x09, 0x49, 0xD9, 0x5A, 0xDE, 0xEF, 0x34, 0x5D, 0xAF, 0x78, 0xCA,
+ 0xD7, 0x71, 0x7C, 0xAD, 0x2B, 0x58, 0xFB, 0x9A, 0x5E, 0x14, 0xF0, 0xCD, 0x2A, 0x14, 0xEB, 0x38,
+ 0x4A, 0x52, 0x6D, 0x47, 0x95, 0xD4, 0x7B, 0xB5, 0xA6, 0xD0, 0x8E, 0xFD, 0x12, 0xD1, 0xE8, 0xB4,
+ 0x7A, 0xA8, 0xFC, 0x4B, 0xF0, 0xC7, 0x44, 0xD1, 0x26, 0x8A, 0xDC, 0x59, 0xDE, 0x79, 0x8D, 0x1C,
+ 0x44, 0x5B, 0xC9, 0x70, 0x62, 0x9B, 0xE7, 0x23, 0x2A, 0xA3, 0x90, 0x48, 0xC8, 0xC0, 0x03, 0xF9,
+ 0x54, 0xE1, 0x73, 0xBC, 0x6C, 0xF0, 0x71, 0xAB, 0x9D, 0x42, 0x38, 0x69, 0x49, 0x2D, 0x2A, 0xA8,
+ 0xD3, 0x4B, 0x44, 0xFD, 0xDE, 0x66, 0xD6, 0xFA, 0x25, 0x77, 0x6B, 0x6A, 0x93, 0x22, 0xB7, 0x00,
+ 0xF0, 0x83, 0xCA, 0x9E, 0x63, 0x4A, 0x8C, 0xAF, 0x19, 0xA8, 0xB8, 0xC2, 0xA3, 0x4B, 0x95, 0xB4,
+ 0xB9, 0xB5, 0xBE, 0xCB, 0xA6, 0xD6, 0x5B, 0xA3, 0xE8, 0x7F, 0x09, 0xFF, 0x00, 0xC1, 0x31, 0x7F,
+ 0x6C, 0x0F, 0x8A, 0xFA, 0x4D, 0xB6, 0xB5, 0xF0, 0xD7, 0xF6, 0x7E, 0xF8, 0xA6, 0xBA, 0x24, 0xAA,
+ 0xB7, 0x2F, 0xAF, 0xF8, 0xC3, 0x41, 0x1E, 0x02, 0xF0, 0x74, 0x36, 0xCC, 0xA0, 0x9B, 0x87, 0xD5,
+ 0xF5, 0x36, 0xB5, 0xB5, 0x48, 0x40, 0x39, 0x32, 0x34, 0x9B, 0x31, 0x9F, 0x9B, 0x8E, 0x7F, 0x26,
+ 0xE3, 0x3F, 0x12, 0xB3, 0x2C, 0x1D, 0x6C, 0x3E, 0x0F, 0x26, 0x54, 0xAA, 0x61, 0x9C, 0xAD, 0x28,
+ 0xC2, 0x57, 0x94, 0x9A, 0x7F, 0x0D, 0xE3, 0x78, 0x7B, 0xC9, 0x5E, 0x2A, 0x32, 0x96, 0x9A, 0x4D,
+ 0x45, 0xD9, 0x1F, 0x2F, 0x9D, 0xF0, 0xA7, 0x01, 0x60, 0x69, 0xCA, 0xB6, 0x13, 0x34, 0xE5, 0x97,
+ 0x2D, 0xF9, 0x5B, 0x55, 0x39, 0x6C, 0x96, 0x8D, 0x41, 0x5E, 0xFA, 0x5A, 0xCA, 0x4E, 0xDB, 0xBB,
+ 0x23, 0xA3, 0x9F, 0xFE, 0x09, 0xA3, 0x17, 0x82, 0xE0, 0x5B, 0xBF, 0x8F, 0xDF, 0xB6, 0xA7, 0xEC,
+ 0x51, 0xF0, 0x3E, 0xDA, 0x38, 0xE4, 0x37, 0x7A, 0x4C, 0x7F, 0x14, 0xEF, 0xBE, 0x34, 0xF8, 0xBE,
+ 0xD1, 0xE3, 0x6C, 0x79, 0x42, 0xC7, 0xC2, 0xDA, 0x7E, 0xA5, 0x03, 0xB1, 0x0A, 0xC4, 0x2A, 0x5C,
+ 0xB1, 0x38, 0xE0, 0x1E, 0x71, 0xEE, 0x57, 0xE2, 0xCF, 0xED, 0x38, 0xD1, 0xA1, 0x97, 0x64, 0xF5,
+ 0xAF, 0xCA, 0x9C, 0xA3, 0xEE, 0x53, 0x69, 0xD9, 0x36, 0xBD, 0xED, 0x54, 0x75, 0x5D, 0x12, 0x7B,
+ 0xDE, 0xCA, 0xE7, 0xE7, 0x78, 0xAC, 0xA3, 0x1D, 0x81, 0x8B, 0xAD, 0x52, 0x9C, 0xFD, 0x8D, 0xED,
+ 0x19, 0xB8, 0x4A, 0x31, 0x7A, 0x5D, 0x2F, 0x79, 0x2B, 0x36, 0x96, 0xDF, 0x75, 0xF4, 0x31, 0xA1,
+ 0xF8, 0x09, 0xFF, 0x00, 0x04, 0xD7, 0xF0, 0xF5, 0xC5, 0xB5, 0x97, 0x89, 0xBF, 0x6E, 0x6F, 0x8D,
+ 0xBF, 0x16, 0x64, 0x54, 0x6B, 0xDB, 0xD5, 0xFD, 0x9D, 0xFF, 0x00, 0x63, 0xDB, 0xA1, 0xA4, 0x25,
+ 0xBC, 0x4B, 0xBA, 0x65, 0x17, 0x7E, 0x29, 0xD6, 0x34, 0x7B, 0x84, 0x60, 0xAA, 0xFF, 0x00, 0x38,
+ 0xB3, 0x91, 0x47, 0x07, 0x04, 0x0C, 0x57, 0xC5, 0x66, 0xB9, 0xC7, 0x88, 0x78, 0xAB, 0x61, 0x28,
+ 0xE5, 0xA9, 0x61, 0x5A, 0x7C, 0xB4, 0xE5, 0x4D, 0x27, 0x1E, 0x89, 0xCA, 0x53, 0x9C, 0x62, 0xFA,
+ 0x6C, 0xDA, 0x6A, 0xDA, 0xAD, 0x97, 0x0C, 0x5D, 0x28, 0x2E, 0x79, 0x24, 0xAD, 0x65, 0x76, 0xFA,
+ 0x69, 0xAA, 0xE5, 0x4E, 0xC9, 0x75, 0xBD, 0xAD, 0x6E, 0xCA, 0xE4, 0x0D, 0x65, 0xFF, 0x00, 0x04,
+ 0xA4, 0x82, 0xE2, 0x2B, 0x6F, 0x0F, 0x78, 0x2F, 0xFE, 0x0A, 0x3D, 0xF1, 0x24, 0xC2, 0x49, 0xFB,
+ 0x4A, 0x78, 0xB3, 0xE1, 0xDF, 0x80, 0xED, 0x6E, 0xF0, 0xC3, 0xCB, 0x51, 0x69, 0x1E, 0x8F, 0xA8,
+ 0x4A, 0x8A, 0x40, 0x39, 0xC4, 0xD9, 0x1C, 0x00, 0x7B, 0xD7, 0x93, 0x5F, 0x0B, 0xC5, 0xB1, 0xA5,
+ 0x0E, 0x77, 0x4A, 0x11, 0xFE, 0x5E, 0x78, 0xC2, 0xCA, 0xDD, 0x25, 0x04, 0xD5, 0xD3, 0xEC, 0x9A,
+ 0x4A, 0xDB, 0xB7, 0x60, 0xFA, 0xC5, 0x3A, 0x56, 0xF6, 0xD5, 0x20, 0xB6, 0x4F, 0xA7, 0xA2, 0x57,
+ 0x7D, 0xB4, 0xD5, 0x7A, 0x2E, 0x87, 0x71, 0x61, 0x65, 0xFB, 0x05, 0x4D, 0x23, 0x7F, 0x60, 0x7F,
+ 0xC1, 0x3E, 0x3F, 0x6B, 0xDF, 0x15, 0x5B, 0x04, 0x1F, 0x67, 0x3E, 0x26, 0xFD, 0xAF, 0x74, 0xBF,
+ 0x0A, 0x49, 0x28, 0x55, 0xF9, 0x77, 0xBC, 0x5E, 0x14, 0x65, 0x05, 0x88, 0x39, 0x0A, 0x0E, 0x06,
+ 0x30, 0x0D, 0x7C, 0xED, 0x6C, 0x17, 0x10, 0x41, 0x45, 0x3C, 0x5C, 0x54, 0x76, 0x76, 0xAA, 0xA6,
+ 0xED, 0x7D, 0xB4, 0xA5, 0xA5, 0x92, 0xF3, 0xBD, 0x92, 0x4B, 0x42, 0x23, 0x99, 0xE0, 0x21, 0x27,
+ 0xFB, 0xE4, 0xEF, 0xA4, 0x52, 0x83, 0xD3, 0xD6, 0xCF, 0x5E, 0xCB, 0x64, 0xFA, 0x6E, 0x91, 0xD9,
+ 0xE9, 0xBE, 0x04, 0xFD, 0x91, 0xB5, 0x34, 0x1B, 0xBF, 0xE0, 0x9A, 0xBF, 0x15, 0x74, 0xC0, 0xF1,
+ 0x92, 0x8D, 0x7F, 0xFF, 0x00, 0x05, 0x12, 0x01, 0x93, 0x8C, 0x0F, 0x91, 0x3C, 0x14, 0xD9, 0x23,
+ 0x23, 0x80, 0x3B, 0x11, 0x5E, 0x6C, 0xA7, 0x9A, 0xC6, 0xA7, 0x2E, 0x33, 0x1B, 0xA2, 0xD3, 0x47,
+ 0xCC, 0xFA, 0x69, 0x67, 0x08, 0xDB, 0x45, 0xDF, 0x7B, 0x2D, 0xAE, 0x44, 0xB3, 0x7C, 0x3C, 0x12,
+ 0xE5, 0x5D, 0x6D, 0x65, 0x0B, 0x5B, 0xB3, 0xD6, 0x69, 0x5B, 0xF1, 0xE9, 0x6E, 0x87, 0xAA, 0xE8,
+ 0xBF, 0xB2, 0x2F, 0xEC, 0x51, 0xE2, 0xB8, 0xD6, 0x5D, 0x47, 0xF6, 0x52, 0xFD, 0xAB, 0xBC, 0x23,
+ 0x0D, 0xE2, 0xC6, 0xA0, 0x78, 0x17, 0xF6, 0x9B, 0xD2, 0x3C, 0x5F, 0xF6, 0x14, 0x50, 0x37, 0xC9,
+ 0x04, 0xD7, 0x7E, 0x10, 0x55, 0x91, 0x8E, 0x3A, 0x3A, 0x00, 0x39, 0xEA, 0x06, 0x46, 0x2A, 0xAE,
+ 0x61, 0xCA, 0xF9, 0x6B, 0xCA, 0x53, 0xE9, 0x65, 0x14, 0x9A, 0x5F, 0xCD, 0x68, 0xF3, 0x6D, 0x65,
+ 0x78, 0xDD, 0x25, 0x7D, 0x51, 0x2B, 0x36, 0x93, 0xAA, 0xBD, 0x8D, 0x2B, 0xD3, 0x49, 0x5E, 0xE9,
+ 0xDE, 0xF6, 0xD1, 0x24, 0x9D, 0x92, 0xED, 0x76, 0x9D, 0xBA, 0x2B, 0x23, 0x76, 0x1F, 0xF8, 0x26,
+ 0xAF, 0xEC, 0x3B, 0xAE, 0x59, 0xC9, 0x1D, 0xB0, 0xFF, 0x00, 0x82, 0x80, 0x78, 0x26, 0xFC, 0xC1,
+ 0x21, 0x82, 0xEA, 0xE3, 0x4E, 0xF0, 0x3F, 0xC4, 0xAB, 0x31, 0x27, 0x22, 0x15, 0x6B, 0x61, 0x69,
+ 0xA5, 0x39, 0x00, 0x85, 0x0C, 0x3C, 0xC1, 0xD0, 0xE3, 0xDB, 0x69, 0x4F, 0x39, 0x95, 0x59, 0x4A,
+ 0xA5, 0x59, 0xA5, 0xA3, 0x49, 0x28, 0x49, 0x25, 0xDA, 0xEE, 0x2D, 0xB5, 0x65, 0x64, 0xF4, 0x6B,
+ 0xB3, 0x4B, 0x5D, 0x23, 0x9A, 0x41, 0x28, 0xC5, 0xD3, 0x49, 0xA7, 0x66, 0xAC, 0xD7, 0x45, 0xA2,
+ 0xD6, 0xD7, 0xBB, 0x5A, 0x68, 0xAD, 0xDB, 0xA7, 0x9E, 0xCD, 0xFF, 0x00, 0x04, 0x9B, 0xFD, 0x9F,
+ 0x35, 0x6B, 0xC4, 0xB5, 0xD0, 0x7F, 0x6B, 0xAF, 0x89, 0x7E, 0x10, 0x6F, 0x31, 0x61, 0x16, 0xDF,
+ 0x19, 0x3F, 0x64, 0x5F, 0x13, 0xE8, 0x82, 0x46, 0x72, 0x42, 0x91, 0x79, 0xA1, 0x49, 0xAC, 0xDA,
+ 0x45, 0x18, 0x0B, 0xF7, 0xE6, 0x92, 0x30, 0x72, 0x08, 0x1C, 0x10, 0x3D, 0x0F, 0x63, 0x99, 0x4E,
+ 0x92, 0x9E, 0x25, 0xA9, 0xC7, 0x5B, 0x28, 0xA5, 0x15, 0x1B, 0x5A, 0xFC, 0xD7, 0x92, 0x7B, 0x74,
+ 0x49, 0xB5, 0xDB, 0x54, 0x63, 0x0C, 0xDA, 0xBD, 0x56, 0xA3, 0x87, 0xA3, 0xCA, 0xD7, 0xC4, 0xA4,
+ 0x9A, 0x6D, 0x2D, 0xF9, 0x34, 0xB3, 0xB6, 0x97, 0xE9, 0xAA, 0xD7, 0x43, 0xB1, 0xD3, 0xFF, 0x00,
+ 0xE0, 0x84, 0xDE, 0x30, 0xD6, 0xAD, 0xF4, 0xF9, 0x3C, 0x15, 0xF1, 0x53, 0xE1, 0xFF, 0x00, 0xC5,
+ 0x26, 0xBF, 0x8B, 0x30, 0x5A, 0xF8, 0x17, 0xE2, 0x96, 0x87, 0xA2, 0xEB, 0x0C, 0x09, 0xFD, 0xD6,
+ 0x74, 0xDD, 0x69, 0x2C, 0x6E, 0x4B, 0x38, 0x20, 0xAA, 0x45, 0x1C, 0x87, 0x04, 0x0C, 0x7A, 0xF9,
+ 0xF5, 0x27, 0x8B, 0x8C, 0x9D, 0x1A, 0x54, 0xEC, 0x9D, 0x95, 0xAD, 0xAE, 0x8A, 0xFA, 0x2D, 0xAC,
+ 0xB6, 0x6E, 0xEB, 0x6D, 0x2C, 0x82, 0x96, 0x65, 0x8A, 0x74, 0xDD, 0x69, 0x72, 0xB8, 0xA7, 0x6B,
+ 0xD9, 0xA4, 0x96, 0x89, 0x76, 0xD3, 0xF0, 0xED, 0xD0, 0xF3, 0x5F, 0x1E, 0x7F, 0xC1, 0x22, 0xBC,
+ 0x51, 0xF0, 0x87, 0xCC, 0x6F, 0x8A, 0x1F, 0x0E, 0xFF, 0x00, 0x68, 0x3F, 0x08, 0xDB, 0xC7, 0x0A,
+ 0x5C, 0x3D, 0xEF, 0x88, 0x3C, 0x25, 0x26, 0x9B, 0xA5, 0xC5, 0x1B, 0x01, 0xB5, 0xBE, 0xD6, 0x2C,
+ 0xFC, 0x9C, 0x10, 0xCA, 0x73, 0xBF, 0xB8, 0xF5, 0x15, 0xC6, 0xAA, 0xD5, 0x51, 0x57, 0x94, 0x53,
+ 0x57, 0xD2, 0xCF, 0xA6, 0x9D, 0x1F, 0x7D, 0x17, 0xF9, 0x6D, 0x53, 0xCC, 0x31, 0x52, 0xA6, 0x9D,
+ 0x35, 0x6D, 0x2F, 0xA2, 0x4F, 0x45, 0x6E, 0xF7, 0x5F, 0xD7, 0xA2, 0x3E, 0x55, 0xD4, 0x7E, 0x04,
+ 0x7E, 0xCC, 0x9A, 0x27, 0x88, 0xED, 0xBC, 0x2B, 0xA9, 0xEB, 0x9E, 0x31, 0x4D, 0x52, 0xED, 0xDA,
+ 0x38, 0x21, 0x17, 0x29, 0xF3, 0xB2, 0x1C, 0x32, 0x03, 0xE5, 0x81, 0xC6, 0x06, 0x4E, 0x3F, 0xFA,
+ 0xDE, 0xA5, 0x2C, 0x9F, 0x34, 0xAD, 0x43, 0xDA, 0x42, 0x70, 0xB5, 0xBE, 0x1E, 0xB6, 0xF4, 0xBE,
+ 0x8B, 0xA5, 0xB4, 0xBE, 0xC9, 0x6C, 0x78, 0x32, 0xE2, 0xFF, 0x00, 0x63, 0xED, 0x5B, 0xA7, 0x37,
+ 0x4E, 0x9B, 0x51, 0x9C, 0xD4, 0x3D, 0xC8, 0xB7, 0x6B, 0x5D, 0xE9, 0xE5, 0x6B, 0x45, 0xDA, 0xFA,
+ 0xF9, 0x7A, 0xEC, 0x1F, 0xB1, 0x2F, 0xC1, 0x2B, 0x88, 0x62, 0x9A, 0x19, 0x7C, 0x52, 0x63, 0x74,
+ 0x0C, 0x9B, 0x75, 0xA1, 0xB4, 0x02, 0xA3, 0x1F, 0xC1, 0xF4, 0xE3, 0xA5, 0x7C, 0xEB, 0xA1, 0xCB,
+ 0x65, 0x39, 0x6A, 0x9E, 0x8B, 0xB5, 0xB4, 0xB2, 0xB3, 0xF8, 0x55, 0xB4, 0x5B, 0x2E, 0x8A, 0xFA,
+ 0x9E, 0xF5, 0x3C, 0xD3, 0x13, 0x3A, 0x71, 0x9A, 0xB5, 0x9F, 0x97, 0xF9, 0x3B, 0x2E, 0xC3, 0xFF,
+ 0x00, 0xE1, 0x87, 0x7E, 0x0A, 0x74, 0x1F, 0xF0, 0x94, 0x93, 0x8E, 0xDA, 0xC8, 0x23, 0x8F, 0x70,
+ 0x9E, 0xC6, 0xB8, 0xDE, 0x53, 0x85, 0xAA, 0xDD, 0x4B, 0xEE, 0xF5, 0xDF, 0x7E, 0xBD, 0x7B, 0x9B,
+ 0x2C, 0xD3, 0x19, 0x18, 0xE8, 0xD5, 0x97, 0x95, 0xBB, 0x7E, 0x9F, 0xD6, 0xC3, 0x7F, 0xE1, 0x87,
+ 0xFE, 0x0A, 0x0F, 0x97, 0x3E, 0x28, 0x04, 0x10, 0x98, 0x1A, 0xDA, 0x83, 0xDB, 0xA1, 0x29, 0x8E,
+ 0xE3, 0xF2, 0xA7, 0x4F, 0x2B, 0xC1, 0xD3, 0xBA, 0x49, 0x59, 0xAB, 0x6A, 0xAF, 0x6B, 0xA5, 0xB6,
+ 0xBA, 0x35, 0xD2, 0xC2, 0xFE, 0xD5, 0xC5, 0xAB, 0x5D, 0xAB, 0x7A, 0x5B, 0xF2, 0x7D, 0xBA, 0x75,
+ 0x35, 0x2F, 0x7F, 0x63, 0x9F, 0x84, 0x5A, 0x86, 0x95, 0xA6, 0xE9, 0x21, 0xBC, 0x41, 0x69, 0x6D,
+ 0xA4, 0xA3, 0xA2, 0xB5, 0xBD, 0xE4, 0x30, 0xCB, 0x71, 0xB9, 0xCB, 0x16, 0x9A, 0x41, 0x10, 0x32,
+ 0x63, 0xA7, 0xCC, 0x4E, 0x00, 0x18, 0xC6, 0x0E, 0x3D, 0x4C, 0x64, 0xFE, 0xB9, 0x95, 0xE1, 0xF2,
+ 0x8A, 0xB6, 0xF6, 0x34, 0x6F, 0xCB, 0x6B, 0xDF, 0x5B, 0xDA, 0xFA, 0xA5, 0xA5, 0xED, 0xB6, 0xDA,
+ 0x2B, 0x58, 0xE7, 0x58, 0xFC, 0x4D, 0x3A, 0xBE, 0xD1, 0x34, 0xDB, 0xDA, 0xEA, 0xF6, 0xD9, 0x3B,
+ 0x75, 0x4B, 0xCA, 0x36, 0x5A, 0xBB, 0xA6, 0xD9, 0xE9, 0x7A, 0x97, 0xEC, 0xF9, 0xF0, 0x3B, 0xFE,
+ 0x11, 0x1F, 0x04, 0xF8, 0x6F, 0x42, 0xF0, 0x35, 0x86, 0x91, 0x37, 0x87, 0x3C, 0x29, 0x77, 0xA1,
+ 0xF8, 0x8F, 0x55, 0xBA, 0xD3, 0xF4, 0xFD, 0x5E, 0xEF, 0xC6, 0x17, 0x77, 0x25, 0x80, 0xD4, 0xE5,
+ 0x77, 0x80, 0x48, 0x93, 0xC7, 0x1B, 0xA2, 0xA1, 0x0C, 0x76, 0x95, 0xC8, 0xE7, 0x18, 0xFB, 0x5E,
+ 0x16, 0xE2, 0xEC, 0x93, 0x86, 0xF2, 0x89, 0xE5, 0x78, 0xAC, 0x9E, 0x86, 0x26, 0x6D, 0x59, 0x4A,
+ 0xA4, 0x13, 0xD1, 0xA5, 0xA3, 0x6D, 0xDD, 0x27, 0xD5, 0x47, 0x46, 0xAD, 0x64, 0x9D, 0xDC, 0xBC,
+ 0x2C, 0x5C, 0x71, 0x58, 0xBC, 0xC2, 0x18, 0xF8, 0xE2, 0x67, 0x4E, 0x49, 0x25, 0x68, 0xCA, 0xD1,
+ 0x69, 0x3B, 0xD9, 0xC6, 0xDC, 0xAF, 0xAD, 0xB4, 0xBA, 0xD3, 0x6B, 0x59, 0xF8, 0xEF, 0x8D, 0xFF,
+ 0x00, 0x62, 0xEF, 0x85, 0x9A, 0xF4, 0xFA, 0x4C, 0x3A, 0x2E, 0xAD, 0xA9, 0xE9, 0x16, 0x7A, 0x1E,
+ 0x8B, 0x0E, 0x93, 0x0C, 0xDA, 0x46, 0x9F, 0x6B, 0x65, 0x26, 0xAC, 0x50, 0xE5, 0xAE, 0x6F, 0x81,
+ 0x8B, 0x2F, 0x39, 0x2C, 0xC0, 0xB7, 0x19, 0xC2, 0x81, 0xC0, 0x00, 0x7C, 0x87, 0x14, 0x4B, 0x25,
+ 0xCD, 0xF3, 0x57, 0x8B, 0xCB, 0x70, 0xB1, 0xA3, 0x49, 0x24, 0x94, 0x63, 0xCC, 0x94, 0xB4, 0x4D,
+ 0xDD, 0x39, 0x49, 0xC5, 0x27, 0xEE, 0xA5, 0x16, 0x92, 0x4A, 0xF6, 0xBB, 0x6C, 0xF5, 0x30, 0xB9,
+ 0xB6, 0x61, 0x86, 0xA4, 0xFD, 0xAB, 0x4E, 0x4F, 0xBA, 0xBD, 0xAD, 0xD1, 0x5B, 0x97, 0x4B, 0x79,
+ 0x3D, 0xB4, 0xF2, 0xF3, 0xD7, 0xFD, 0x84, 0x3C, 0x39, 0x05, 0xBC, 0xE9, 0x63, 0xE3, 0xCD, 0x62,
+ 0x33, 0x30, 0x58, 0x4F, 0xDA, 0xB4, 0xC8, 0x25, 0x2A, 0x33, 0xDB, 0x69, 0x5E, 0x31, 0x9E, 0xC7,
+ 0xA0, 0xFC, 0x7D, 0x6E, 0x19, 0xC5, 0xAC, 0x83, 0x87, 0x33, 0x3A, 0x58, 0x68, 0x3B, 0xE2, 0x62,
+ 0xA8, 0xB9, 0x3B, 0x5D, 0x42, 0x51, 0x77, 0x49, 0x24, 0x93, 0xD6, 0xDA, 0x37, 0x65, 0xDA, 0xF6,
+ 0x15, 0x5C, 0xF3, 0x11, 0x3A, 0xB4, 0xFD, 0xA4, 0x15, 0xE3, 0xAE, 0x8A, 0xCB, 0xCB, 0x4B, 0xF7,
+ 0xB5, 0x9A, 0x69, 0x79, 0x6D, 0x6E, 0x1E, 0xFB, 0xF6, 0x0F, 0xB9, 0x4F, 0xF8, 0xF0, 0xF8, 0x85,
+ 0x6C, 0x40, 0x07, 0x02, 0xEB, 0x45, 0x6C, 0x11, 0xC6, 0xD0, 0x19, 0x64, 0x03, 0xA0, 0x6E, 0xDC,
+ 0x6D, 0xAF, 0x8A, 0x96, 0x45, 0x46, 0xA4, 0x12, 0xA5, 0x51, 0xF3, 0x2B, 0x2B, 0xBB, 0x35, 0xD9,
+ 0x5A, 0xC9, 0x59, 0x5A, 0xC9, 0x2B, 0xF4, 0x7D, 0x12, 0x3B, 0x69, 0x71, 0x2D, 0x48, 0xE9, 0x52,
+ 0x94, 0x6D, 0xD2, 0xCD, 0xAB, 0x74, 0xF3, 0xEB, 0xB6, 0xD7, 0xEC, 0xBA, 0x70, 0xFA, 0x9F, 0xEC,
+ 0x57, 0xE2, 0xEB, 0x16, 0x55, 0x87, 0xC6, 0x7E, 0x13, 0x62, 0xF8, 0x58, 0xE3, 0xBC, 0x79, 0x2C,
+ 0x64, 0x93, 0xFD, 0xD5, 0xF9, 0xB3, 0xD3, 0xB5, 0x25, 0xC3, 0x15, 0xE5, 0x04, 0xE8, 0x4F, 0x9B,
+ 0xD2, 0x3A, 0x25, 0xA7, 0x5B, 0xAB, 0x7E, 0x16, 0xB0, 0x2E, 0x2D, 0xC3, 0xD3, 0x51, 0x8D, 0x7A,
+ 0x6A, 0x32, 0x7B, 0x2E, 0x64, 0x97, 0x45, 0xD5, 0x27, 0xE5, 0xA2, 0x7D, 0x3E, 0x5C, 0x7E, 0xA1,
+ 0xFB, 0x21, 0xFC, 0x5D, 0xB0, 0x0C, 0x62, 0x8B, 0xC3, 0x97, 0xEA, 0x00, 0x31, 0x8B, 0x5D, 0x64,
+ 0x23, 0x38, 0x39, 0xC0, 0x01, 0xD1, 0x54, 0x7D, 0xD3, 0xD4, 0x8E, 0x9E, 0xDC, 0x62, 0xF8, 0x6B,
+ 0x1A, 0x9D, 0xA1, 0x28, 0xDB, 0xE6, 0xBA, 0x76, 0xB7, 0xDD, 0x6D, 0x7C, 0x96, 0x88, 0xE8, 0x8F,
+ 0x15, 0xE5, 0xE9, 0xA8, 0xCE, 0x12, 0x4A, 0xDB, 0xD9, 0x5B, 0xE5, 0xAD, 0xFF, 0x00, 0x0F, 0x43,
+ 0xB9, 0xF8, 0x73, 0xF0, 0x8B, 0xE2, 0xEC, 0x7E, 0x36, 0xD0, 0x2E, 0x7C, 0x6B, 0xA1, 0x6A, 0x13,
+ 0x5A, 0xE8, 0x3A, 0x4C, 0x3A, 0x26, 0x8D, 0x31, 0xD3, 0xAD, 0x7C, 0x53, 0x67, 0x6B, 0x02, 0x9C,
+ 0x0B, 0x76, 0xB2, 0x84, 0x3D, 0xC4, 0x91, 0x08, 0x4D, 0xC2, 0x9F, 0x25, 0x1A, 0x45, 0x2C, 0xA7,
+ 0xA6, 0x6B, 0xDF, 0xC9, 0xB2, 0x0A, 0xEA, 0x51, 0xAF, 0x39, 0x72, 0xCA, 0x36, 0x56, 0xF7, 0x67,
+ 0x77, 0xD6, 0xD1, 0xE5, 0x49, 0x45, 0xA4, 0xD3, 0x77, 0x93, 0x8A, 0xB3, 0x4A, 0x4B, 0x6E, 0x1C,
+ 0x5E, 0x7B, 0x93, 0xCB, 0x08, 0xE1, 0x4E, 0x56, 0x52, 0x7B, 0x59, 0xA7, 0x7E, 0xF7, 0xD9, 0x3B,
+ 0xA5, 0xAB, 0xFD, 0x34, 0xD5, 0xFD, 0xA2, 0x3C, 0x03, 0x79, 0xAF, 0xF8, 0xBF, 0x40, 0xD0, 0xFC,
+ 0x2F, 0x67, 0x6F, 0x3F, 0xF6, 0x9D, 0xDF, 0xF6, 0x57, 0x86, 0xED, 0xF4, 0xED, 0x2A, 0xF2, 0x18,
+ 0xB4, 0x8D, 0x16, 0xD4, 0xAC, 0x7A, 0x54, 0x72, 0x08, 0xA2, 0x10, 0x80, 0x11, 0xE7, 0x62, 0xAC,
+ 0xA6, 0x54, 0x08, 0x77, 0x00, 0x4E, 0x0F, 0xD0, 0x67, 0xB9, 0x6D, 0x7A, 0xB4, 0x70, 0x99, 0x56,
+ 0x0A, 0x2E, 0x31, 0xA8, 0xD4, 0x9F, 0x95, 0x38, 0x35, 0xCA, 0xDC, 0xAC, 0xF5, 0x69, 0xA6, 0x9C,
+ 0x74, 0x6A, 0x2D, 0x35, 0x74, 0x91, 0x39, 0x56, 0x65, 0x96, 0x51, 0xF6, 0xB8, 0xBC, 0x46, 0x22,
+ 0x2B, 0x95, 0x45, 0x25, 0xCB, 0x67, 0x26, 0xEC, 0xA5, 0xC8, 0xAC, 0x9B, 0x69, 0xA4, 0xA5, 0xCC,
+ 0xD3, 0x77, 0x49, 0xAB, 0xD8, 0xF2, 0x5B, 0x9F, 0x07, 0xEB, 0x7A, 0x8F, 0x8F, 0x3C, 0x4F, 0x73,
+ 0xF6, 0x18, 0x12, 0xC7, 0xE1, 0x46, 0x93, 0x1F, 0xFC, 0x24, 0xD3, 0x49, 0x25, 0xC6, 0xAB, 0xA2,
+ 0xDA, 0x3D, 0x90, 0x16, 0xF1, 0x4B, 0x24, 0x8E, 0x89, 0xB2, 0x39, 0xA6, 0x44, 0xC6, 0xE2, 0xBD,
+ 0x70, 0x0E, 0x70, 0x07, 0x9B, 0x4E, 0xA6, 0x1E, 0xB7, 0x11, 0xD4, 0xFA, 0xD5, 0x48, 0xBC, 0x35,
+ 0x38, 0x38, 0xB9, 0x25, 0x28, 0xA4, 0xD4, 0x1F, 0x2B, 0x4A, 0xCE, 0x57, 0xDE, 0x29, 0xD9, 0x5D,
+ 0xDD, 0x34, 0x95, 0xCE, 0xDC, 0x35, 0x3C, 0x1D, 0x1C, 0xB5, 0xAA, 0x11, 0x76, 0xA9, 0x2E, 0x64,
+ 0xED, 0xAC, 0x94, 0x9A, 0xD2, 0xC9, 0x6C, 0xAE, 0x97, 0x2C, 0xB4, 0xB7, 0xBB, 0x67, 0x14, 0x79,
+ 0xA0, 0xD2, 0xF5, 0xA8, 0x7C, 0x27, 0xAD, 0x78, 0xDA, 0x7D, 0x1F, 0x45, 0x1A, 0x4E, 0xBD, 0xAE,
+ 0x3E, 0x91, 0x65, 0x75, 0x2A, 0x45, 0x2D, 0xC5, 0xA5, 0xDA, 0x91, 0x24, 0xB1, 0xDA, 0x43, 0xB8,
+ 0x94, 0x01, 0x25, 0xC6, 0x4A, 0x91, 0x85, 0x00, 0x1C, 0x8E, 0x7E, 0x69, 0x50, 0xC1, 0xC3, 0x01,
+ 0x8D, 0x9D, 0x79, 0x4B, 0xDA, 0xD4, 0x95, 0xA1, 0x16, 0xD2, 0x6A, 0xCD, 0xB6, 0xE4, 0xF4, 0xD6,
+ 0xD6, 0x6A, 0xD6, 0xD6, 0x3A, 0x5F, 0x67, 0xEA, 0xC6, 0xAA, 0xA7, 0x8C, 0xC3, 0xA8, 0x5E, 0xF1,
+ 0x57, 0xD9, 0x72, 0xD9, 0x6D, 0xCD, 0x1D, 0x17, 0x4D, 0x17, 0x2B, 0x5D, 0x2C, 0x93, 0x4D, 0x69,
+ 0x45, 0xE0, 0x5F, 0x16, 0x6A, 0x97, 0x5E, 0x1A, 0xF8, 0x77, 0x61, 0xE1, 0x5B, 0x73, 0xE2, 0x4B,
+ 0xDB, 0xF2, 0xF6, 0xE2, 0x2F, 0x21, 0x75, 0x1D, 0x45, 0xA7, 0x8C, 0xB2, 0x42, 0xD3, 0x6E, 0xDB,
+ 0x85, 0x58, 0x5C, 0x85, 0x27, 0x8E, 0x78, 0x1D, 0xFE, 0x93, 0x37, 0xCA, 0x70, 0x78, 0x58, 0xE0,
+ 0x72, 0x2C, 0x1D, 0x39, 0x3A, 0xEB, 0x92, 0x55, 0x92, 0x70, 0x51, 0xB2, 0x4A, 0xE9, 0xDD, 0xE8,
+ 0xDB, 0x7E, 0xEF, 0x3A, 0x49, 0xB5, 0xB5, 0xAC, 0xDC, 0xE1, 0xB1, 0x54, 0xB1, 0x14, 0x2B, 0x63,
+ 0x61, 0x27, 0x68, 0x35, 0x1B, 0x3D, 0x1D, 0xE5, 0x7B, 0x5A, 0x2D, 0x45, 0xE8, 0x93, 0xBB, 0xBF,
+ 0x2A, 0xB6, 0x96, 0xD4, 0xA0, 0xBE, 0x10, 0xBE, 0xFE, 0xD0, 0xD7, 0x6F, 0xEE, 0x34, 0x6B, 0xD3,
+ 0xA3, 0x78, 0x7A, 0x46, 0xB3, 0xD4, 0x1E, 0xDE, 0xD4, 0xC0, 0xB0, 0x4A, 0x43, 0xAC, 0x68, 0xC5,
+ 0x54, 0x46, 0x1C, 0x98, 0xDB, 0x0A, 0xA4, 0x67, 0x1C, 0x71, 0x92, 0x3C, 0x5C, 0x77, 0xF6, 0x2E,
+ 0x2F, 0x34, 0xC4, 0xB7, 0x85, 0xA9, 0x4F, 0x0B, 0x08, 0xF2, 0xC1, 0x28, 0xDD, 0xF3, 0x27, 0x16,
+ 0x93, 0xE5, 0x93, 0x51, 0xBA, 0x76, 0x5A, 0xB5, 0x6F, 0xC1, 0xCB, 0xDB, 0x60, 0xB0, 0xD4, 0x3D,
+ 0x9C, 0xEC, 0xE6, 0x94, 0xEE, 0xE4, 0x9B, 0x51, 0xBB, 0x56, 0x6D, 0xCA, 0x2F, 0x75, 0x67, 0x67,
+ 0xA2, 0xBA, 0xDE, 0xC8, 0xC0, 0xFF, 0x00, 0x84, 0x57, 0x54, 0x4D, 0x16, 0xCB, 0x51, 0x97, 0x4E,
+ 0xD4, 0x52, 0xE3, 0x57, 0xBF, 0x16, 0x7A, 0x1D, 0xB4, 0x9A, 0x65, 0xC0, 0xFE, 0xD6, 0x89, 0x4F,
+ 0x97, 0x23, 0xDA, 0xC8, 0x17, 0x63, 0xED, 0x94, 0x47, 0x1E, 0xD0, 0x49, 0xCB, 0x01, 0x8E, 0xC5,
+ 0x50, 0xC2, 0xE0, 0x70, 0x39, 0x1C, 0xAA, 0x54, 0xA2, 0xBE, 0xB3, 0x56, 0xAF, 0x22, 0xD6, 0x4B,
+ 0x96, 0x9D, 0x93, 0x6D, 0x59, 0xFB, 0xAF, 0x99, 0x72, 0xDD, 0xB7, 0x75, 0x74, 0xD3, 0x5B, 0xF5,
+ 0x53, 0x94, 0x2A, 0xCB, 0x96, 0x93, 0xD5, 0x24, 0xF4, 0xE5, 0xB3, 0xBA, 0x6F, 0x6B, 0xA6, 0xDB,
+ 0x5A, 0xE8, 0xAD, 0x6F, 0x3D, 0xBA, 0x79, 0xBC, 0x09, 0xA9, 0xDC, 0x6B, 0x7A, 0x3F, 0x84, 0x74,
+ 0xEF, 0x0F, 0xEB, 0x6D, 0xA9, 0xDA, 0x59, 0xAC, 0xDE, 0x20, 0x9A, 0x0D, 0x13, 0x55, 0x7B, 0xEB,
+ 0x28, 0x09, 0xDF, 0x71, 0x3C, 0xF6, 0x4D, 0x08, 0x78, 0xE2, 0x8A, 0x27, 0x04, 0xB2, 0xC7, 0x8D,
+ 0xAB, 0xBB, 0x3C, 0xF1, 0xCB, 0x8A, 0xCB, 0x30, 0x78, 0x7C, 0x45, 0x1C, 0x0E, 0x1A, 0x9F, 0xBF,
+ 0x3B, 0x73, 0x4A, 0x51, 0x8B, 0xE5, 0x4D, 0x2B, 0x34, 0xE3, 0x29, 0x27, 0x65, 0x77, 0x29, 0x35,
+ 0x1E, 0x5B, 0x5D, 0x24, 0x91, 0x9D, 0x2A, 0xB2, 0xA4, 0xAA, 0xD4, 0x8D, 0x45, 0xCC, 0xD3, 0x76,
+ 0x57, 0xD2, 0xCA, 0xD6, 0xD1, 0x26, 0xD3, 0xB2, 0xBA, 0xF7, 0x9B, 0xD9, 0x59, 0x68, 0x5A, 0xD5,
+ 0x34, 0xAF, 0x05, 0x69, 0x36, 0x96, 0xF2, 0x5D, 0xD9, 0xEA, 0x1A, 0x77, 0xF6, 0xFE, 0xA2, 0xAF,
+ 0xA6, 0xDD, 0x5B, 0xC7, 0x35, 0xD4, 0xBA, 0x6E, 0x9B, 0x01, 0x0A, 0x2F, 0xAD, 0x11, 0xCC, 0x69,
+ 0x3F, 0x9E, 0xC9, 0x26, 0x15, 0x9C, 0x6D, 0x1B, 0x48, 0xC7, 0x7D, 0x33, 0x3C, 0xAF, 0x2F, 0xC1,
+ 0xE0, 0x28, 0xCE, 0x69, 0x35, 0x51, 0xAB, 0x28, 0xB8, 0xEC, 0x92, 0xBE, 0xAD, 0xB6, 0x95, 0xAD,
+ 0x67, 0x67, 0x1D, 0x5B, 0x4E, 0xEA, 0xC1, 0x85, 0xA9, 0x8B, 0xA5, 0x17, 0x3A, 0x32, 0x6E, 0x71,
+ 0xB7, 0x2B, 0x97, 0xBA, 0xEF, 0xA3, 0x57, 0x4A, 0x29, 0x2B, 0x5F, 0xA2, 0x5D, 0x13, 0x57, 0xDB,
+ 0xC9, 0xEE, 0x64, 0x12, 0x4F, 0x23, 0x2C, 0x92, 0x4B, 0x18, 0x62, 0xB0, 0xBC, 0xB1, 0xAC, 0x52,
+ 0x32, 0x29, 0xC2, 0x16, 0x40, 0x48, 0x53, 0x80, 0x38, 0x04, 0x81, 0xEB, 0x5F, 0x23, 0x1A, 0x74,
+ 0xE9, 0x27, 0x0A, 0x4A, 0xD1, 0xE8, 0x7A, 0x3C, 0xF5, 0x6A, 0x46, 0x2E, 0xB4, 0x9B, 0x92, 0x49,
+ 0x6A, 0xDB, 0xD9, 0x6D, 0x77, 0xAD, 0x97, 0x4F, 0x22, 0x0A, 0xA0, 0x0A, 0x00, 0x55, 0x52, 0x70,
+ 0x14, 0x7D, 0x00, 0x1D, 0x38, 0xE3, 0xF9, 0x56, 0xD8, 0x7C, 0x35, 0x6C, 0x4C, 0xD5, 0x2C, 0x3C,
+ 0x2E, 0xFC, 0xBA, 0x7F, 0x91, 0x2E, 0x51, 0x82, 0x57, 0xD8, 0xE8, 0x2D, 0x2C, 0xC4, 0x11, 0xA4,
+ 0xCF, 0x1E, 0x41, 0x03, 0x74, 0x68, 0x01, 0x74, 0x5C, 0x75, 0x3D, 0x38, 0x15, 0xFD, 0x3D, 0xC1,
+ 0xFC, 0x1B, 0x1C, 0x83, 0x2E, 0xA3, 0x9F, 0x62, 0x70, 0xD2, 0x94, 0x5A, 0x4A, 0x74, 0xE9, 0xC5,
+ 0x3A, 0x94, 0xE2, 0xD2, 0xBC, 0xE6, 0xDD, 0x97, 0x2A, 0xFB, 0x4E, 0x32, 0x7A, 0x2D, 0x22, 0xF4,
+ 0x3C, 0x3A, 0xF8, 0x8F, 0x69, 0x27, 0x4A, 0x2D, 0x2E, 0xCF, 0xA7, 0xA2, 0xFD, 0x34, 0x47, 0x49,
+ 0x1C, 0x49, 0xE5, 0xAB, 0x26, 0x19, 0x0A, 0x82, 0xA5, 0x7A, 0x11, 0x8E, 0x30, 0x3F, 0x0A, 0xFE,
+ 0xAB, 0xCB, 0xB2, 0xDC, 0x33, 0xCB, 0xE8, 0xE2, 0x30, 0x32, 0x52, 0xA3, 0x38, 0xA9, 0x46, 0x49,
+ 0xBB, 0x34, 0xD6, 0x8F, 0x64, 0xD7, 0xCD, 0x2D, 0x0F, 0x0E, 0x53, 0xB3, 0x71, 0x92, 0xB3, 0x5A,
+ 0x58, 0x0A, 0x00, 0x06, 0xD0, 0x06, 0x31, 0x8E, 0xC3, 0x18, 0xE3, 0x1F, 0xA5, 0x5C, 0xF0, 0xAE,
+ 0x2B, 0xDD, 0x56, 0xB7, 0xDC, 0xD6, 0x9B, 0x74, 0xFC, 0x81, 0x35, 0x65, 0x62, 0x2C, 0x63, 0x8E,
+ 0x06, 0x38, 0xC0, 0x1D, 0x87, 0x61, 0x5E, 0x25, 0x4C, 0x2C, 0xEF, 0x75, 0x6E, 0x55, 0xD3, 0xCB,
+ 0xB2, 0xE8, 0xBB, 0x2F, 0x97, 0xA1, 0xAC, 0x5C, 0x62, 0x92, 0x48, 0x00, 0x1C, 0x71, 0x8C, 0x0C,
+ 0x01, 0xC0, 0xC7, 0x1D, 0x3F, 0x41, 0x51, 0xF5, 0x78, 0x69, 0xEE, 0xB5, 0x6F, 0x2F, 0xEA, 0xDF,
+ 0x2F, 0x45, 0x60, 0xE6, 0x69, 0x69, 0x62, 0x8D, 0xFD, 0x92, 0x5C, 0x42, 0xA3, 0x18, 0x91, 0x40,
+ 0xD8, 0x7B, 0x28, 0xC7, 0x03, 0xF4, 0xAF, 0x82, 0xF1, 0x27, 0x81, 0xB0, 0x7C, 0x57, 0x93, 0xD3,
+ 0xA2, 0xD5, 0xB1, 0x31, 0x8D, 0xE1, 0x27, 0xB4, 0x52, 0x5D, 0x5A, 0x5F, 0x7A, 0xB6, 0xDA, 0x69,
+ 0xA1, 0xD5, 0x82, 0xC4, 0x4A, 0x84, 0xEE, 0xBE, 0x1E, 0xA7, 0x20, 0xF1, 0x98, 0x9C, 0xC6, 0xC0,
+ 0x02, 0x87, 0x1C, 0x0C, 0x0C, 0x0E, 0x98, 0x1F, 0x95, 0x7F, 0x0C, 0x66, 0xB9, 0x66, 0x23, 0x27,
+ 0xC7, 0xD5, 0xCB, 0xB1, 0x4B, 0xDF, 0x83, 0xB6, 0xCD, 0x27, 0x6D, 0x9A, 0xBA, 0x5A, 0x5B, 0xC8,
+ 0xFA, 0x7A, 0x53, 0x8D, 0x48, 0x29, 0x47, 0x61, 0x95, 0xE7, 0x9A, 0x1F, 0xA3, 0x5F, 0xB1, 0xDF,
+ 0xEC, 0x78, 0x7E, 0x28, 0x1B, 0x3F, 0x1C, 0xF8, 0xE6, 0xCE, 0x46, 0xF0, 0xDF, 0x9A, 0xAF, 0xA4,
+ 0x68, 0xE4, 0x05, 0x5D, 0x49, 0x54, 0x9F, 0xDE, 0x4C, 0xB8, 0xE5, 0x4E, 0xD1, 0xB5, 0x7A, 0x10,
+ 0x09, 0x39, 0x1C, 0x0F, 0xAD, 0xE1, 0xEE, 0x1D, 0xAB, 0x99, 0x54, 0x8E, 0x9A, 0x68, 0xDB, 0xE9,
+ 0x15, 0xBA, 0xB7, 0x46, 0xDA, 0x5B, 0x74, 0xEA, 0xBB, 0x7C, 0xDE, 0x73, 0x9B, 0xC7, 0x05, 0x0E,
+ 0x48, 0xBD, 0x36, 0xEC, 0xDB, 0x76, 0x56, 0x4F, 0xA2, 0x5E, 0x49, 0xDF, 0x44, 0x95, 0xF4, 0x7F,
+ 0xD0, 0xFF, 0x00, 0xC2, 0xFF, 0x00, 0xD9, 0xAB, 0xC3, 0xBA, 0x26, 0x8F, 0x69, 0x01, 0xD3, 0x6D,
+ 0xB4, 0xAB, 0x48, 0xA0, 0x45, 0x86, 0xC6, 0xC6, 0x04, 0x80, 0xA0, 0x0B, 0xB5, 0x54, 0xED, 0x5E,
+ 0x3B, 0x0C, 0x73, 0xD4, 0xF4, 0xC0, 0xCF, 0xE8, 0x70, 0xA5, 0x95, 0xE5, 0x91, 0x54, 0xF0, 0xB4,
+ 0x94, 0xA7, 0xB3, 0x94, 0xB5, 0x6E, 0xD6, 0xDB, 0x6F, 0xF2, 0x56, 0xD1, 0x58, 0xF9, 0x35, 0xF5,
+ 0xFC, 0xC2, 0xD2, 0x9C, 0xF9, 0x29, 0xE9, 0x64, 0xBB, 0x6B, 0x65, 0xA5, 0xBD, 0x35, 0xBD, 0xED,
+ 0xBD, 0x99, 0xED, 0x9F, 0xF0, 0xA9, 0xBC, 0x0C, 0x22, 0xF2, 0x1B, 0x4E, 0x80, 0xE5, 0x40, 0x04,
+ 0xBA, 0x86, 0x50, 0x00, 0x03, 0x00, 0x77, 0x19, 0x1C, 0x77, 0xE0, 0x77, 0xAA, 0x8E, 0x3A, 0xBA,
+ 0xB7, 0x2C, 0x55, 0xBD, 0x17, 0xF9, 0x6D, 0xA7, 0xF5, 0x65, 0x66, 0xB2, 0xDC, 0x3A, 0x87, 0x2B,
+ 0x9C, 0xAF, 0xEA, 0xBB, 0x5B, 0x55, 0xB6, 0xD6, 0xDD, 0x75, 0x5D, 0x16, 0x9E, 0x3B, 0xF1, 0x13,
+ 0xF6, 0x6C, 0xF0, 0xC6, 0xBF, 0xA6, 0xDD, 0x47, 0xA7, 0xDB, 0xDB, 0x4E, 0xCD, 0x13, 0x2B, 0xD8,
+ 0xDD, 0x46, 0x93, 0x43, 0x2A, 0x95, 0x19, 0x50, 0x08, 0x38, 0xE3, 0x23, 0x27, 0x8F, 0x63, 0x9C,
+ 0x07, 0x2F, 0xA8, 0x63, 0xA2, 0xA9, 0xE3, 0xA9, 0x2B, 0x59, 0x2B, 0xA5, 0xAA, 0xF9, 0xAD, 0x56,
+ 0xDA, 0x25, 0xE6, 0xAF, 0xA6, 0xB0, 0xE8, 0xE2, 0xF0, 0x51, 0xBE, 0x12, 0xAB, 0x71, 0x49, 0x5E,
+ 0x32, 0xBB, 0x56, 0xB7, 0x4D, 0xDE, 0x9D, 0x34, 0xED, 0xBA, 0x3F, 0x9F, 0xDF, 0xDB, 0x0B, 0xF6,
+ 0x2C, 0x6F, 0x01, 0xC1, 0xA8, 0x78, 0xEF, 0xC0, 0x7A, 0x64, 0x96, 0x96, 0x96, 0x8C, 0xD2, 0xEB,
+ 0xBE, 0x1E, 0x85, 0x14, 0x45, 0x02, 0x80, 0x4B, 0xCB, 0x02, 0x0C, 0x6D, 0xC0, 0x00, 0xED, 0x03,
+ 0x91, 0xD0, 0x0C, 0x73, 0xF0, 0x1C, 0x43, 0xC3, 0x8F, 0x01, 0x35, 0x3A, 0x29, 0x72, 0x35, 0xEE,
+ 0xB5, 0x6B, 0x4B, 0xAD, 0x9D, 0xB4, 0xE6, 0xED, 0x6D, 0x1E, 0xDB, 0xED, 0xF5, 0x39, 0x1E, 0x73,
+ 0xF5, 0xBA, 0x71, 0x85, 0x4E, 0x9A, 0x5B, 0xAA, 0x7D, 0x2D, 0x65, 0xAA, 0x7B, 0x74, 0xB5, 0xAD,
+ 0xA5, 0xB5, 0xF9, 0xC3, 0xF6, 0x0D, 0xBB, 0xBA, 0xB6, 0xFD, 0xB5, 0xFF, 0x00, 0x64, 0x18, 0x6D,
+ 0xEE, 0x6E, 0x20, 0x86, 0xE7, 0xF6, 0xA3, 0xF8, 0x7D, 0x1D, 0xCC, 0x50, 0xCC, 0xD1, 0x45, 0x70,
+ 0xA3, 0xC5, 0x76, 0x20, 0x2C, 0x8A, 0x08, 0x0C, 0x30, 0xCC, 0x30, 0x47, 0x73, 0xEB, 0x5F, 0x2F,
+ 0x96, 0x69, 0x98, 0x61, 0xD2, 0xDB, 0x9E, 0x1F, 0xFA, 0x52, 0x3E, 0x87, 0x12, 0x97, 0xD5, 0xAA,
+ 0x69, 0xF6, 0x5F, 0xE4, 0x7F, 0xA0, 0x6D, 0x7E, 0xA6, 0x7C, 0x70, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x7F, 0x14, 0x5F, 0xF0, 0x5A, 0xFF, 0x00, 0xF9, 0x48, 0x1F, 0xC4, 0x8F, 0xFB, 0x12, 0xFC, 0x27,
+ 0xFF, 0x00, 0xA8, 0xF5, 0xAD, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94,
+ 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0x78, 0x7C, 0x31, 0xF8, 0x37, 0xE3, 0x9F,
+ 0x8B, 0x1A, 0x9C, 0x1A, 0x7F, 0x85, 0xB4, 0xC5, 0x5B, 0x47, 0xB8, 0x5B, 0x5B, 0x8D, 0x73, 0x52,
+ 0x63, 0x65, 0xA2, 0x59, 0x31, 0xC6, 0x55, 0xA6, 0xC1, 0xDC, 0xC0, 0x10, 0x76, 0x46, 0xAE, 0xD8,
+ 0xFE, 0x1C, 0x57, 0x1E, 0x0B, 0x2E, 0xC4, 0xE3, 0x54, 0xA5, 0x46, 0x3E, 0xE4, 0x56, 0xAF, 0xA2,
+ 0xF2, 0xFE, 0xB4, 0xEF, 0x61, 0xE3, 0x73, 0x2C, 0x26, 0x03, 0x96, 0x15, 0xA5, 0xEF, 0xCB, 0x48,
+ 0xC5, 0x6E, 0xFF, 0x00, 0x44, 0x97, 0x9F, 0xCB, 0xB1, 0xF7, 0xB7, 0x89, 0xFF, 0x00, 0xE0, 0x9E,
+ 0xED, 0xE0, 0x2F, 0x06, 0x47, 0xAC, 0x2F, 0xC4, 0x9B, 0x8B, 0x8F, 0x13, 0xB1, 0x8F, 0x2D, 0x6B,
+ 0x60, 0xDA, 0x7E, 0x8D, 0x01, 0xE3, 0x7A, 0x05, 0x0D, 0xE6, 0x9F, 0xBC, 0xA0, 0x31, 0x61, 0xD3,
+ 0xEE, 0xF6, 0xAF, 0xAF, 0xE1, 0x7F, 0xAB, 0xD1, 0xAB, 0x2C, 0x1C, 0xE5, 0x51, 0xC1, 0xB4, 0xDA,
+ 0x53, 0x94, 0x22, 0xDA, 0xEF, 0x18, 0xC9, 0x27, 0xDB, 0x57, 0xB6, 0x9A, 0x2B, 0x9F, 0x3D, 0x9B,
+ 0xE6, 0x98, 0xCC, 0x35, 0x38, 0xE2, 0xA9, 0x53, 0x83, 0x84, 0x77, 0x4F, 0x77, 0x75, 0x64, 0x94,
+ 0xAC, 0xD4, 0x6D, 0xBD, 0xF9, 0x5A, 0x69, 0x5B, 0x4B, 0xDD, 0x67, 0x78, 0x53, 0xF6, 0x06, 0xF1,
+ 0xE6, 0xAD, 0xA4, 0x5B, 0xEB, 0x17, 0x5E, 0x26, 0xD0, 0x61, 0x96, 0xE7, 0x32, 0x1D, 0xB6, 0x93,
+ 0x5C, 0x45, 0x1C, 0x78, 0xE1, 0xDA, 0x52, 0xC0, 0x93, 0x81, 0xD0, 0x29, 0xEA, 0x39, 0xAF, 0xDE,
+ 0x78, 0x3F, 0xC5, 0xDE, 0x1C, 0xE0, 0xEC, 0x54, 0x70, 0xB4, 0xF2, 0x7A, 0x36, 0x57, 0xBB, 0x8C,
+ 0x64, 0x9D, 0xEC, 0xD5, 0xD2, 0x72, 0xB5, 0xDB, 0xEA, 0xF5, 0x7D, 0xAF, 0x63, 0xC8, 0x95, 0x5C,
+ 0xE3, 0x19, 0x42, 0x35, 0x70, 0x94, 0x23, 0x18, 0x36, 0xAD, 0x19, 0x54, 0xB3, 0xB7, 0x57, 0xEE,
+ 0xD3, 0x69, 0x7A, 0x5E, 0xDA, 0x59, 0xB5, 0xD3, 0xD5, 0x35, 0x3F, 0xF8, 0x27, 0xFF, 0x00, 0xC4,
+ 0x3D, 0x17, 0xC3, 0xB7, 0xDA, 0xDF, 0x84, 0x6D, 0xB4, 0x2F, 0x1E, 0xCB, 0xA6, 0x58, 0x1B, 0xFB,
+ 0xED, 0x2D, 0x74, 0x2B, 0x99, 0x2E, 0xAD, 0xE2, 0x8D, 0x5C, 0xC8, 0xC8, 0xC9, 0x2F, 0x4C, 0x02,
+ 0x30, 0x41, 0xF6, 0x2A, 0x42, 0xE7, 0xFA, 0x27, 0x85, 0xFC, 0x68, 0xE1, 0xFC, 0xE2, 0x93, 0xFA,
+ 0xEE, 0x5D, 0xEC, 0xA0, 0x9C, 0x5F, 0x3C, 0x6D, 0x64, 0xB4, 0xD1, 0xBB, 0xA7, 0x64, 0xD6, 0xC9,
+ 0x29, 0x37, 0x7B, 0xA6, 0xAE, 0x7C, 0xFE, 0x39, 0x66, 0x98, 0x38, 0xC2, 0x78, 0xC9, 0xBF, 0x67,
+ 0x75, 0x77, 0x4E, 0x49, 0x34, 0x9A, 0xD5, 0x72, 0xB8, 0xA5, 0x2B, 0x5B, 0x45, 0x78, 0xEB, 0xB5,
+ 0xAE, 0xD1, 0x43, 0xE0, 0xD7, 0xEC, 0xF5, 0xA8, 0xF8, 0xFF, 0x00, 0xC3, 0xB7, 0x5E, 0x21, 0xD4,
+ 0x74, 0x0F, 0x87, 0x3A, 0x4A, 0xDB, 0xCB, 0x25, 0xA5, 0xBD, 0x95, 0xEE, 0x87, 0x73, 0x7B, 0x34,
+ 0x4F, 0x0E, 0xE1, 0x22, 0xC8, 0x9F, 0x6B, 0x55, 0x5C, 0xB0, 0x38, 0x03, 0x00, 0x11, 0x81, 0xD7,
+ 0x8F, 0xB6, 0xCD, 0x78, 0xD3, 0x07, 0x93, 0x62, 0x21, 0x83, 0xC3, 0xD4, 0x9D, 0x45, 0x34, 0xA5,
+ 0xCC, 0xA4, 0xD2, 0x4A, 0x49, 0x4A, 0x29, 0x3B, 0x5D, 0xC5, 0x2B, 0x24, 0x92, 0xDA, 0xEE, 0xDA,
+ 0x2B, 0xFC, 0xFD, 0x3A, 0x19, 0x9E, 0x69, 0xCD, 0xFD, 0x99, 0x8E, 0xAA, 0xE8, 0x41, 0x38, 0xA9,
+ 0x4E, 0x69, 0x4A, 0x5B, 0x69, 0x18, 0xA8, 0x5A, 0x0A, 0x37, 0x6F, 0x99, 0xBB, 0xF5, 0x6A, 0xDA,
+ 0x8E, 0xF8, 0x4D, 0xE0, 0xF9, 0xE1, 0xF8, 0xD1, 0x7D, 0xE1, 0xBD, 0x57, 0xC0, 0xBF, 0x0E, 0x1A,
+ 0xCB, 0xC1, 0x64, 0x6A, 0x72, 0xEA, 0x3A, 0x46, 0x93, 0x75, 0x1A, 0xCE, 0x48, 0xC5, 0xB2, 0xAB,
+ 0x3D, 0xC3, 0x60, 0x70, 0x40, 0x53, 0x9E, 0xA0, 0x74, 0xE2, 0xBD, 0x7C, 0xEF, 0x15, 0x7E, 0x1E,
+ 0x86, 0x6B, 0x84, 0xC5, 0xD6, 0x75, 0x2B, 0x7B, 0xAA, 0x37, 0x94, 0xA2, 0x96, 0x8A, 0x4D, 0xA5,
+ 0x24, 0xBC, 0xD5, 0xBC, 0xED, 0xAA, 0x8A, 0x5C, 0x75, 0x2A, 0x62, 0x73, 0x0A, 0x14, 0xB0, 0x33,
+ 0xC5, 0x56, 0x72, 0x94, 0x9A, 0x9C, 0x65, 0x28, 0xDA, 0xD4, 0xD2, 0xB2, 0xF7, 0x63, 0x1B, 0xAB,
+ 0xB8, 0xDB, 0x45, 0xCA, 0x93, 0x49, 0x2D, 0x4F, 0x6F, 0xF8, 0xC5, 0xE2, 0x1B, 0x6F, 0x13, 0x78,
+ 0xCF, 0xC0, 0xBF, 0x0B, 0x6C, 0x7C, 0x27, 0xE1, 0x3B, 0xCF, 0xED, 0x82, 0xDA, 0xA6, 0xBC, 0xD7,
+ 0x3A, 0x5C, 0xF3, 0x25, 0x9C, 0x10, 0x38, 0x65, 0x2A, 0x04, 0xBB, 0x55, 0xF3, 0x1A, 0xE0, 0x63,
+ 0x83, 0x8C, 0xE4, 0x6D, 0xDB, 0xF3, 0xFC, 0x31, 0x95, 0xCB, 0x05, 0x96, 0x62, 0x78, 0x83, 0x17,
+ 0x5A, 0xA4, 0x63, 0x04, 0xA3, 0x0B, 0xB9, 0xC5, 0x36, 0xD3, 0x4D, 0x7C, 0x5A, 0xB7, 0x17, 0x6D,
+ 0x6F, 0xA6, 0xA9, 0xAB, 0xD9, 0xF2, 0xE6, 0x14, 0xAA, 0xBA, 0xAA, 0x9D, 0x1A, 0xD3, 0xE6, 0x8D,
+ 0xA3, 0x16, 0xB9, 0x64, 0xEF, 0x3B, 0xA7, 0x6F, 0x76, 0xF6, 0x50, 0x53, 0x72, 0x5D, 0x9C, 0x5A,
+ 0xB3, 0xBB, 0x3D, 0x2B, 0xC7, 0x3A, 0x74, 0x3A, 0xEE, 0x87, 0x63, 0xE0, 0x6D, 0x1E, 0xC3, 0xC3,
+ 0x96, 0x17, 0x1A, 0xFE, 0x34, 0xAB, 0x76, 0xB8, 0xD3, 0x9A, 0x45, 0x82, 0x05, 0x5F, 0xDE, 0x10,
+ 0x9E, 0x71, 0xCF, 0xC8, 0x63, 0x50, 0x32, 0x33, 0xBB, 0xD1, 0x4E, 0x3E, 0x7F, 0x2F, 0x9D, 0x3C,
+ 0x25, 0x6A, 0x99, 0xC6, 0x3F, 0x95, 0xC6, 0x9A, 0x6D, 0xA4, 0xE6, 0x9B, 0x7B, 0x24, 0x9F, 0x32,
+ 0xB2, 0x76, 0x49, 0xDD, 0x34, 0xB4, 0x5B, 0xB4, 0x8F, 0x52, 0x39, 0x2E, 0x3F, 0x16, 0xA8, 0xE0,
+ 0x32, 0xD7, 0x37, 0x28, 0xB8, 0xBB, 0xA7, 0xEE, 0xC1, 0x45, 0xA7, 0x77, 0x34, 0xBD, 0xDB, 0x59,
+ 0x38, 0xB5, 0xCA, 0xFA, 0xA7, 0x6B, 0x33, 0xCF, 0xAE, 0xFF, 0x00, 0x62, 0xBD, 0x27, 0xC3, 0x11,
+ 0xDB, 0x6A, 0x9A, 0x9C, 0x3E, 0x12, 0xD6, 0x6D, 0xE5, 0x22, 0x39, 0x22, 0x8F, 0xC3, 0x23, 0x4F,
+ 0xB7, 0x80, 0xB2, 0x80, 0xAA, 0x54, 0x48, 0xD8, 0xCE, 0x18, 0xE7, 0x9C, 0x1F, 0x4E, 0x05, 0x72,
+ 0xD6, 0xF1, 0x72, 0xB6, 0x61, 0x09, 0x60, 0x72, 0xEA, 0x72, 0xA5, 0x18, 0xDB, 0x4E, 0x69, 0x3D,
+ 0x13, 0xFB, 0x29, 0xCA, 0x2A, 0xCA, 0xC9, 0x26, 0x9A, 0xEA, 0xDE, 0x89, 0x5F, 0xF5, 0x6C, 0x83,
+ 0x84, 0xB0, 0x78, 0x75, 0x1A, 0xB9, 0xAD, 0x6A, 0xB5, 0x6B, 0x5D, 0x35, 0xFB, 0xD9, 0x28, 0x2B,
+ 0x6A, 0xEF, 0x1D, 0x5C, 0xEC, 0xF4, 0x6A, 0x4E, 0xCD, 0x36, 0xF9, 0x53, 0x49, 0x1D, 0x3E, 0xBF,
+ 0xF0, 0x12, 0xFB, 0xC1, 0xFE, 0x1A, 0x8B, 0x5B, 0xF0, 0xAE, 0x9D, 0xA0, 0x45, 0x6B, 0x0C, 0xAA,
+ 0x2F, 0x6D, 0x13, 0x41, 0x53, 0x24, 0x50, 0x1C, 0x6E, 0x11, 0x80, 0xC0, 0xE0, 0x02, 0x4F, 0xDE,
+ 0xFE, 0x11, 0x9E, 0xA3, 0x1F, 0x1D, 0x4B, 0x88, 0xF0, 0xB9, 0x86, 0x61, 0x2C, 0xB7, 0x18, 0xAF,
+ 0x56, 0xDE, 0xEB, 0x77, 0x6B, 0x4B, 0xDA, 0xEB, 0x5B, 0xC9, 0xE9, 0xE6, 0xAF, 0x64, 0xEC, 0x9D,
+ 0xBF, 0x47, 0x87, 0x12, 0x46, 0x86, 0x0B, 0x5A, 0x55, 0x27, 0x4E, 0x0A, 0xCA, 0x31, 0x92, 0x4D,
+ 0x28, 0xE8, 0xE5, 0x18, 0xF2, 0xF2, 0xB6, 0x92, 0x72, 0x51, 0x4A, 0x2A, 0x5B, 0x26, 0xB4, 0x46,
+ 0x7E, 0xB5, 0xF0, 0x7E, 0xD3, 0x53, 0xD1, 0xED, 0xA7, 0x17, 0x76, 0x89, 0x6F, 0x3C, 0xB1, 0x2B,
+ 0x34, 0xB6, 0x70, 0x3F, 0x94, 0xCC, 0x32, 0xAB, 0x08, 0x6C, 0x64, 0x70, 0x79, 0xE3, 0x95, 0x5E,
+ 0xFC, 0x57, 0x2E, 0x5F, 0x9E, 0x62, 0x30, 0x38, 0x99, 0xDE, 0x84, 0x65, 0x08, 0xFC, 0x56, 0x8B,
+ 0x4E, 0x29, 0x74, 0x6A, 0xFA, 0x59, 0xA4, 0xAE, 0xF4, 0x49, 0x3B, 0x36, 0xB5, 0x5D, 0x0B, 0x89,
+ 0xF1, 0x4A, 0x84, 0xE5, 0x80, 0x93, 0x55, 0x25, 0x06, 0xE1, 0x24, 0xF5, 0x57, 0x8B, 0x4A, 0x4B,
+ 0x44, 0x9D, 0xB4, 0x7C, 0xB6, 0x7A, 0x36, 0xB9, 0x76, 0x89, 0xED, 0xBA, 0x67, 0xFC, 0x13, 0xCF,
+ 0xE3, 0x2E, 0xA5, 0xE0, 0x75, 0xD7, 0xEF, 0x6E, 0x3C, 0x1F, 0xF0, 0xD7, 0xE1, 0x84, 0xD6, 0xCB,
+ 0x04, 0x1F, 0x13, 0xBE, 0x34, 0xDD, 0x41, 0xF0, 0xDB, 0xC0, 0x31, 0x89, 0xC6, 0xC8, 0x52, 0xCE,
+ 0x69, 0x10, 0xDC, 0xDF, 0x93, 0xE6, 0x9F, 0xDD, 0xD8, 0xDB, 0x5C, 0xC8, 0x48, 0xC2, 0x8E, 0x48,
+ 0x5F, 0x9F, 0xC4, 0xF8, 0x85, 0x80, 0xA9, 0x8A, 0xE5, 0xC2, 0xE1, 0x9D, 0x4C, 0x4A, 0x92, 0x6E,
+ 0x9C, 0x21, 0xCD, 0x29, 0x28, 0xDB, 0x99, 0xA4, 0xDA, 0xB2, 0x8A, 0x8D, 0xF9, 0x9F, 0x2C, 0x14,
+ 0x52, 0x77, 0xEF, 0xAE, 0x53, 0xC5, 0xD5, 0x28, 0x54, 0xA3, 0xFD, 0xAE, 0xA5, 0x3C, 0x44, 0x6D,
+ 0xCD, 0x2A, 0x4A, 0xFC, 0xF6, 0xB3, 0x72, 0xB6, 0x8A, 0x32, 0xB2, 0x6A, 0x4A, 0xE9, 0x5F, 0x5B,
+ 0x24, 0xD5, 0xB9, 0x8D, 0x6F, 0xE1, 0x3F, 0xEC, 0x3D, 0xFB, 0x36, 0x84, 0xD0, 0xBE, 0x21, 0xD9,
+ 0x7C, 0x62, 0xFD, 0xB0, 0xBC, 0x77, 0x04, 0x31, 0x6B, 0x0B, 0x07, 0x87, 0x2D, 0xCF, 0xEC, 0xD7,
+ 0xFB, 0x3B, 0xDC, 0x92, 0xA3, 0x36, 0xE3, 0x54, 0xB8, 0x49, 0xBC, 0x47, 0xA8, 0xDB, 0xE1, 0xD7,
+ 0x7B, 0xC3, 0x06, 0x9E, 0xDF, 0x22, 0xA8, 0x68, 0xB2, 0x0B, 0xED, 0xFE, 0xB8, 0x71, 0x8E, 0x6F,
+ 0x88, 0x8D, 0x6C, 0xBA, 0x9D, 0x0C, 0x2D, 0x1D, 0x55, 0xED, 0x1A, 0xD5, 0x15, 0xF4, 0xE6, 0x7A,
+ 0xBA, 0x30, 0x5A, 0x24, 0x9B, 0x8C, 0xA3, 0x6B, 0xC9, 0xF3, 0xDB, 0x91, 0x7D, 0x3E, 0x1F, 0x38,
+ 0xCE, 0x73, 0xFA, 0x1E, 0xD7, 0x07, 0x3A, 0x78, 0x6A, 0x32, 0x6E, 0x0E, 0xED, 0xD6, 0xA8, 0x92,
+ 0x69, 0xAF, 0x75, 0x38, 0xC2, 0x32, 0x4F, 0x58, 0xA6, 0xF7, 0xBB, 0x57, 0xB5, 0xD7, 0x9B, 0x4D,
+ 0xFF, 0x00, 0x05, 0x09, 0xF8, 0xDB, 0xE0, 0xD9, 0xE7, 0xD0, 0x7F, 0x66, 0xBF, 0x85, 0xFF, 0x00,
+ 0x02, 0xBF, 0x64, 0x5D, 0x33, 0xE7, 0x4D, 0x30, 0x7C, 0x28, 0xF8, 0x63, 0xA7, 0x5F, 0x7C, 0x40,
+ 0x8A, 0xDE, 0x58, 0xC2, 0x98, 0xBF, 0xE1, 0x34, 0xD6, 0x96, 0xFB, 0x59, 0xDC, 0x7C, 0xA6, 0x26,
+ 0x48, 0xAE, 0x61, 0x24, 0x92, 0x4D, 0x79, 0x3F, 0xEA, 0xAE, 0x57, 0x83, 0xA9, 0x46, 0x39, 0xFD,
+ 0x79, 0xE3, 0x6A, 0xD4, 0xB3, 0xB4, 0xAA, 0x4A, 0x51, 0x6F, 0x74, 0x9C, 0x14, 0x94, 0x39, 0x52,
+ 0x71, 0x4E, 0x3F, 0x0B, 0x8A, 0x4A, 0x31, 0x8D, 0xDA, 0x5F, 0x4B, 0x4F, 0x85, 0xB8, 0x7B, 0x13,
+ 0x86, 0x9D, 0x6C, 0xF7, 0x15, 0x57, 0x17, 0x38, 0xB4, 0xDD, 0xE7, 0x35, 0x06, 0x93, 0x49, 0x4F,
+ 0xD9, 0xC1, 0xA4, 0x9A, 0x8D, 0xD3, 0x4F, 0x99, 0xAB, 0xBB, 0x26, 0x9A, 0x3C, 0x03, 0xC4, 0xF0,
+ 0xFE, 0xD0, 0x9F, 0xB4, 0x2D, 0xFB, 0x78, 0xAB, 0xE2, 0xDF, 0x8D, 0x3C, 0x63, 0xE3, 0x51, 0x34,
+ 0xCD, 0x72, 0xDA, 0xA7, 0xC4, 0xAD, 0x7E, 0xF7, 0xC4, 0x5E, 0x4B, 0xB8, 0x0B, 0x24, 0xB6, 0xD1,
+ 0x5C, 0x4A, 0xE5, 0x32, 0xB1, 0xA8, 0x3B, 0x51, 0x06, 0x00, 0xC7, 0x18, 0xCE, 0xD8, 0xAC, 0xD3,
+ 0x2E, 0xCB, 0xE8, 0x3C, 0x16, 0x0B, 0x28, 0xC3, 0xFB, 0x34, 0xEC, 0xA3, 0xEC, 0xE0, 0xE3, 0xEE,
+ 0xEB, 0x76, 0x9A, 0xDD, 0x5D, 0xF5, 0x6E, 0x2E, 0xE9, 0x69, 0xAB, 0xCF, 0x35, 0xE2, 0x1E, 0x0F,
+ 0xE1, 0x1A, 0x12, 0x8E, 0x02, 0x09, 0xC5, 0x2B, 0x35, 0x4D, 0xA4, 0xD7, 0x44, 0xDB, 0x49, 0x26,
+ 0xAF, 0x65, 0x67, 0x75, 0x75, 0xAF, 0x53, 0x9B, 0xF1, 0xCF, 0xEC, 0xF9, 0xAF, 0xD9, 0x78, 0x3E,
+ 0xF7, 0xFB, 0x0F, 0x46, 0xD5, 0xBC, 0x67, 0xA9, 0xDC, 0xDA, 0x0B, 0x5B, 0x4D, 0x33, 0xC3, 0x7A,
+ 0x11, 0xD6, 0xE5, 0x9A, 0x46, 0x4C, 0xAA, 0xAD, 0x94, 0x0A, 0xF3, 0x67, 0xE5, 0x66, 0x07, 0x03,
+ 0x01, 0x7F, 0x0A, 0xE7, 0xC1, 0x71, 0x26, 0x6B, 0x4B, 0x13, 0x87, 0xC4, 0x56, 0xC1, 0x50, 0xA7,
+ 0x05, 0x35, 0x18, 0xB9, 0x42, 0x2E, 0x2B, 0x7B, 0x2B, 0x5D, 0xA4, 0xAC, 0xAD, 0xF0, 0xC6, 0x2D,
+ 0x3B, 0x7B, 0xAA, 0xD6, 0xF0, 0xB1, 0x1C, 0x77, 0x84, 0xE2, 0x2C, 0xA3, 0x11, 0x81, 0xC5, 0xC6,
+ 0x2A, 0x83, 0xA4, 0xDA, 0xE6, 0x94, 0xAE, 0xDB, 0x8D, 0xE0, 0xE2, 0xF6, 0x6D, 0x36, 0xBD, 0xD8,
+ 0xA6, 0xEF, 0xE6, 0x8E, 0x57, 0xE1, 0x77, 0xEC, 0xE1, 0xAE, 0xF8, 0x46, 0xE2, 0xD8, 0xFC, 0x52,
+ 0x97, 0xE1, 0x47, 0xC3, 0xFB, 0xF9, 0x49, 0x91, 0x6D, 0xBC, 0x4D, 0xAC, 0xC7, 0xE2, 0x8F, 0x17,
+ 0x40, 0xA3, 0x69, 0x08, 0x74, 0x3B, 0x05, 0xB8, 0x96, 0x39, 0x00, 0x03, 0xE4, 0x94, 0xC5, 0xD5,
+ 0x73, 0xB4, 0x8C, 0xD7, 0xD3, 0x66, 0xBC, 0x4B, 0x86, 0xC7, 0xE1, 0xF9, 0x30, 0xF8, 0x0A, 0x0E,
+ 0xCB, 0x45, 0xEC, 0xA3, 0x16, 0xE5, 0x66, 0xA2, 0xED, 0x1E, 0x69, 0x24, 0xDD, 0xB5, 0x4D, 0x34,
+ 0x93, 0xB2, 0x7A, 0x23, 0xF9, 0x1F, 0x8A, 0xE8, 0x56, 0xE7, 0x84, 0xE5, 0x98, 0xBA, 0x14, 0x76,
+ 0xE5, 0xDE, 0xF6, 0xFE, 0x54, 0xAE, 0xE7, 0x76, 0xD4, 0x52, 0xB6, 0xFA, 0x5E, 0xDB, 0x7D, 0x5F,
+ 0xA7, 0x78, 0x1B, 0xC2, 0x96, 0xF0, 0xA8, 0xFB, 0x7F, 0x8C, 0xFC, 0x4E, 0xF1, 0x94, 0x91, 0x7E,
+ 0xC7, 0x63, 0x61, 0xF0, 0xD7, 0x42, 0x65, 0xC1, 0xC4, 0x7B, 0x31, 0x73, 0x73, 0x82, 0xA4, 0x64,
+ 0xFC, 0x87, 0x04, 0x63, 0x19, 0xC0, 0xF8, 0xEC, 0x5F, 0x10, 0x60, 0xF2, 0xFB, 0xA7, 0x81, 0xA3,
+ 0x29, 0xDA, 0xD7, 0x54, 0x20, 0xA3, 0x7D, 0x2E, 0xD3, 0x7C, 0xCE, 0x51, 0xD2, 0xC9, 0xB8, 0xC5,
+ 0xAE, 0xAA, 0xE9, 0x27, 0xF3, 0xB4, 0xB2, 0x7A, 0x35, 0x94, 0x64, 0xA7, 0x5E, 0xAB, 0xB5, 0x94,
+ 0xA5, 0x25, 0x4A, 0x32, 0x4F, 0x5F, 0x86, 0x37, 0x6B, 0x4B, 0x2D, 0x6F, 0xB5, 0xB4, 0x7B, 0x69,
+ 0xDC, 0x41, 0xAE, 0x69, 0x2A, 0xCD, 0xE0, 0x7F, 0x06, 0x7C, 0x3C, 0xD2, 0x65, 0xE1, 0x56, 0x6F,
+ 0x11, 0xC1, 0xA8, 0xF8, 0xDA, 0xEF, 0x80, 0x30, 0xE1, 0xAF, 0x2E, 0x1A, 0x25, 0x62, 0x15, 0x49,
+ 0xDB, 0x18, 0x19, 0xCE, 0x14, 0x64, 0xD7, 0xCC, 0x57, 0xE2, 0x7A, 0x13, 0xAA, 0x9D, 0x6A, 0x54,
+ 0x6D, 0xCC, 0x9D, 0xA3, 0x46, 0x0F, 0x4D, 0x6E, 0xB4, 0xB5, 0xD7, 0x55, 0xB2, 0xD1, 0x34, 0xD6,
+ 0x89, 0x7A, 0x3F, 0xD9, 0x75, 0xB0, 0xF1, 0x7F, 0x51, 0xC1, 0xD2, 0xE5, 0xB6, 0x8A, 0x55, 0x2A,
+ 0x49, 0xDB, 0x4D, 0x79, 0x9D, 0xEC, 0xEC, 0x93, 0x56, 0x49, 0x2D, 0x94, 0x56, 0x87, 0x23, 0xF1,
+ 0x47, 0xE3, 0x2F, 0xC7, 0xDF, 0x84, 0x36, 0x7F, 0x0F, 0x75, 0xAB, 0x3F, 0x17, 0x59, 0xDC, 0xE8,
+ 0xFE, 0x2C, 0xB8, 0x7B, 0x7D, 0x46, 0xD7, 0x40, 0xF0, 0x76, 0x89, 0xE1, 0xBB, 0xFD, 0x05, 0xE3,
+ 0x74, 0x44, 0x58, 0xD2, 0xC1, 0x4D, 0xC3, 0xC5, 0xBE, 0x53, 0x8F, 0x33, 0x6B, 0xE0, 0x29, 0x00,
+ 0x92, 0x71, 0xF6, 0x38, 0x5C, 0x26, 0x16, 0x4F, 0x0D, 0x4E, 0xAA, 0xA5, 0xEC, 0xB1, 0x0F, 0x97,
+ 0x9A, 0x38, 0x78, 0x5A, 0x37, 0x77, 0x4A, 0x30, 0x94, 0xD3, 0x8D, 0xF9, 0x5E, 0xAA, 0x5C, 0x8D,
+ 0xC7, 0x46, 0xBA, 0x67, 0x43, 0xDB, 0x66, 0x15, 0xE1, 0x97, 0xD3, 0xC4, 0xCA, 0x86, 0x22, 0xD7,
+ 0x84, 0x25, 0x18, 0xB8, 0x4A, 0x51, 0xB7, 0x32, 0xE6, 0x49, 0x69, 0xAA, 0xE5, 0xB3, 0xD6, 0xCD,
+ 0x3B, 0x6C, 0x7A, 0x5F, 0x80, 0x7E, 0x3A, 0x78, 0xB3, 0xE2, 0x05, 0xAD, 0xDC, 0xFA, 0x9F, 0x8A,
+ 0x7C, 0x48, 0xD7, 0xF6, 0x37, 0x4D, 0x67, 0x72, 0x92, 0x6A, 0x17, 0x96, 0xAE, 0x4A, 0x80, 0x18,
+ 0x98, 0xCB, 0x02, 0x9D, 0x40, 0x2A, 0xC1, 0x4F, 0xB7, 0x35, 0xF2, 0x1C, 0x47, 0x96, 0x4B, 0x2D,
+ 0xC0, 0x62, 0xF3, 0x8C, 0x2E, 0x22, 0x33, 0x85, 0x3A, 0xDE, 0xCD, 0x46, 0x58, 0x78, 0x6A, 0x93,
+ 0x69, 0x4A, 0x52, 0xF6, 0x92, 0xE5, 0x6B, 0x64, 0xA2, 0x9C, 0x6F, 0x65, 0x7B, 0x24, 0x7A, 0x19,
+ 0x5E, 0x65, 0x88, 0xA9, 0x8A, 0x9E, 0x59, 0x8D, 0x49, 0x55, 0x86, 0xEE, 0x2D, 0xF2, 0xC9, 0x74,
+ 0x94, 0x5B, 0x4B, 0x47, 0xD2, 0xDA, 0xAD, 0x3B, 0x26, 0x65, 0xFC, 0x40, 0x93, 0xE2, 0x8E, 0xAB,
+ 0x11, 0x6F, 0x0F, 0x6B, 0x89, 0x80, 0x98, 0x91, 0x75, 0x29, 0x65, 0xBA, 0x32, 0xA0, 0x4E, 0x10,
+ 0x96, 0x63, 0xE9, 0x80, 0x71, 0x8E, 0x78, 0xC6, 0x39, 0xF8, 0xFC, 0xA3, 0x3F, 0xC0, 0x53, 0x4A,
+ 0x35, 0xF0, 0xD4, 0x9B, 0x4B, 0x4B, 0x52, 0x8A, 0x49, 0xF7, 0x56, 0xB6, 0xDA, 0x5A, 0xF7, 0xB7,
+ 0x66, 0xB6, 0xD7, 0x39, 0xC3, 0x67, 0x75, 0xA2, 0x9E, 0x5F, 0x59, 0xA8, 0xF5, 0x57, 0x49, 0xB5,
+ 0xD2, 0xCD, 0xA6, 0xBC, 0xAC, 0xD6, 0xDA, 0x26, 0xAC, 0xEF, 0xF9, 0x61, 0xF1, 0x71, 0x3C, 0x79,
+ 0x6D, 0xF1, 0x27, 0x43, 0x5D, 0x52, 0xE7, 0x4B, 0xB9, 0xD5, 0x65, 0xBC, 0xFF, 0x00, 0x40, 0x75,
+ 0xB3, 0xDB, 0x14, 0x52, 0x02, 0x9B, 0xD9, 0xCE, 0xE2, 0x4F, 0x51, 0xD3, 0x1C, 0x00, 0x38, 0xC5,
+ 0x7E, 0x89, 0x4F, 0x8A, 0x31, 0x7E, 0xC9, 0x2C, 0x36, 0x13, 0x0A, 0xE0, 0xD7, 0x5C, 0x3C, 0x1B,
+ 0xB2, 0xE8, 0x9F, 0x4B, 0x5A, 0xDB, 0x36, 0xDB, 0xBB, 0x67, 0x3F, 0x0D, 0x53, 0xC9, 0xD6, 0x45,
+ 0x98, 0xD2, 0xC5, 0x42, 0xA2, 0x94, 0x6F, 0xED, 0xAF, 0x34, 0xDC, 0xAE, 0x9D, 0xAC, 0xD2, 0x4B,
+ 0x6F, 0x96, 0xBB, 0x5B, 0x45, 0xFA, 0x0B, 0xF0, 0xE5, 0xBE, 0x36, 0x7D, 0x83, 0x4A, 0x6B, 0xC9,
+ 0x7C, 0x3E, 0x9A, 0x47, 0xD9, 0xD5, 0x0A, 0x15, 0x71, 0x72, 0x91, 0x95, 0x00, 0x2A, 0x1F, 0xBC,
+ 0x07, 0x04, 0xF5, 0xE9, 0xEB, 0xC5, 0x7C, 0x76, 0x67, 0xC4, 0x39, 0x6A, 0x94, 0xE9, 0xCA, 0x85,
+ 0x2F, 0x68, 0xF7, 0xE5, 0xA5, 0x1B, 0x37, 0xAF, 0x4D, 0xBC, 0xB4, 0x4B, 0x64, 0xD2, 0x48, 0xF3,
+ 0xF2, 0x6C, 0x3E, 0x7A, 0xA9, 0xD1, 0x96, 0x06, 0x52, 0x58, 0x7B, 0xAE, 0x5E, 0x77, 0x1E, 0x65,
+ 0x0B, 0x69, 0x65, 0x15, 0x75, 0xA5, 0x92, 0xBE, 0xAB, 0xAD, 0xAD, 0xA7, 0xD8, 0x3A, 0x17, 0xED,
+ 0x2B, 0xFB, 0x5D, 0x7C, 0x18, 0xB4, 0x69, 0x3E, 0x01, 0x7C, 0x5C, 0xF1, 0xA7, 0x84, 0x27, 0x96,
+ 0xDD, 0x2D, 0xAE, 0x74, 0xEB, 0x4F, 0x17, 0x5E, 0xC3, 0xA3, 0x5C, 0x44, 0x8F, 0xB9, 0x21, 0x96,
+ 0xC1, 0x9D, 0xAD, 0x64, 0x8C, 0x30, 0x07, 0xCB, 0x78, 0xD9, 0x4F, 0x39, 0x1E, 0xBF, 0x39, 0x83,
+ 0xCD, 0x70, 0xD5, 0xD3, 0xA3, 0x98, 0x46, 0x2A, 0x29, 0xDE, 0x36, 0xA7, 0x15, 0x67, 0x6B, 0x5F,
+ 0x4D, 0x16, 0x9A, 0x2D, 0xD2, 0xD2, 0xC9, 0x23, 0xE8, 0xF3, 0x05, 0x9C, 0xD2, 0xA5, 0x0F, 0xEC,
+ 0xD8, 0xC6, 0xFF, 0x00, 0x6B, 0x6B, 0xDB, 0x7D, 0x16, 0x8B, 0xE4, 0xDA, 0x56, 0x56, 0xF4, 0xF1,
+ 0xCD, 0x6F, 0xFE, 0x0A, 0xA5, 0xF1, 0xA7, 0x57, 0xF1, 0xD5, 0x8F, 0x84, 0x3F, 0x6A, 0x9F, 0xD9,
+ 0xB7, 0xE0, 0x07, 0xC7, 0xE9, 0xF5, 0x19, 0xCC, 0x96, 0xDE, 0x28, 0xD0, 0x74, 0x88, 0xFE, 0x0A,
+ 0xFC, 0x50, 0x56, 0x00, 0xF9, 0xF2, 0xC9, 0xAA, 0x69, 0x50, 0x0D, 0x3E, 0x79, 0x40, 0x65, 0x20,
+ 0x5D, 0x69, 0xB7, 0x28, 0x71, 0xF3, 0xAC, 0x9B, 0x88, 0xAF, 0x66, 0x86, 0x16, 0xBE, 0x1F, 0x11,
+ 0x4F, 0x17, 0x94, 0x4A, 0x9C, 0x57, 0x2D, 0x92, 0x94, 0x23, 0x38, 0xA5, 0xA2, 0xD3, 0x9B, 0x5E,
+ 0x9A, 0xEB, 0xE9, 0x64, 0x74, 0x60, 0x33, 0x8C, 0x0D, 0x4C, 0x87, 0x13, 0x3C, 0xCE, 0x73, 0xE6,
+ 0xA4, 0xD2, 0xAA, 0xB9, 0x62, 0xB5, 0x7F, 0x0F, 0x2C, 0x63, 0x78, 0xBD, 0xD5, 0xAD, 0xEA, 0xD6,
+ 0x89, 0x9F, 0x7E, 0xF8, 0x56, 0xDF, 0xF6, 0x7C, 0xF8, 0xBF, 0xA6, 0x2C, 0xDE, 0x15, 0xF1, 0x9E,
+ 0x85, 0xF0, 0x8B, 0xC4, 0x66, 0xD9, 0x4C, 0x5E, 0x00, 0xFD, 0xA9, 0xBC, 0x1B, 0x6F, 0xA0, 0xDB,
+ 0x6A, 0xD2, 0xB1, 0x3B, 0x57, 0x4F, 0xF8, 0x81, 0xE1, 0x59, 0x06, 0x9F, 0x18, 0x20, 0xC6, 0x14,
+ 0x5E, 0xE9, 0xF6, 0x89, 0x90, 0x0B, 0x48, 0xA3, 0x81, 0xE3, 0x63, 0x33, 0x7A, 0xB7, 0x54, 0xEA,
+ 0x53, 0xA0, 0xE7, 0x1D, 0x9C, 0x69, 0x41, 0x2E, 0xF6, 0x97, 0xB9, 0x1B, 0xEA, 0xB5, 0xEE, 0x9D,
+ 0x92, 0xB2, 0x3A, 0x30, 0x56, 0x9C, 0x17, 0xB3, 0x53, 0x54, 0xD7, 0x49, 0xAE, 0x56, 0xF6, 0x57,
+ 0xBC, 0x25, 0xAE, 0xDA, 0xAB, 0x2D, 0x5B, 0x69, 0x59, 0xD9, 0x7C, 0xFB, 0xFB, 0x4E, 0x68, 0x7A,
+ 0xA7, 0xEC, 0xBF, 0x63, 0x6D, 0xAC, 0x7C, 0x5D, 0xF8, 0x41, 0xF1, 0x37, 0xC2, 0x1E, 0x1C, 0xD4,
+ 0x64, 0x58, 0x74, 0xAF, 0x89, 0xBE, 0x0B, 0x9A, 0xCB, 0xE2, 0x37, 0xC1, 0xDD, 0x71, 0x5C, 0xAE,
+ 0xC9, 0xB4, 0xED, 0x69, 0x59, 0x2D, 0x2E, 0x21, 0x6F, 0x31, 0x36, 0x18, 0xAF, 0xA4, 0x63, 0x90,
+ 0x0E, 0x0F, 0x03, 0x2C, 0x16, 0x22, 0xBD, 0x7A, 0x73, 0xAB, 0xEE, 0x28, 0xA7, 0x1B, 0x25, 0x4E,
+ 0x9E, 0xAB, 0xFB, 0xA9, 0xC1, 0xAD, 0x3A, 0xED, 0x6D, 0xD2, 0x77, 0x3A, 0xA5, 0x26, 0xF1, 0xB4,
+ 0x72, 0xDA, 0x74, 0xE5, 0x17, 0x3B, 0xDA, 0x4E, 0xDC, 0x89, 0xA4, 0x9D, 0x9B, 0x7C, 0xB6, 0xD2,
+ 0xFA, 0x2B, 0xFE, 0x16, 0x7E, 0x11, 0xE0, 0xEF, 0x15, 0x69, 0xFF, 0x00, 0x16, 0x74, 0xC1, 0x71,
+ 0xF0, 0x67, 0xC5, 0x3E, 0x08, 0xF1, 0xEE, 0xA9, 0x24, 0x24, 0xC7, 0xA0, 0xEA, 0xFA, 0xC1, 0xF8,
+ 0x6B, 0xAC, 0xE1, 0x63, 0x2C, 0x55, 0xA2, 0xD4, 0x15, 0x2D, 0xCB, 0x02, 0xAA, 0x30, 0x97, 0x2F,
+ 0x93, 0xC0, 0x39, 0x27, 0x1E, 0xBD, 0x3C, 0x16, 0x63, 0x3A, 0x53, 0xC4, 0x4E, 0xAC, 0x23, 0x46,
+ 0x9D, 0xB5, 0xF6, 0x54, 0x93, 0xBC, 0xBA, 0x2D, 0x35, 0xDF, 0x65, 0xB2, 0xE9, 0xA1, 0xE7, 0x63,
+ 0x2B, 0x57, 0xC3, 0xD7, 0x78, 0x0A, 0x12, 0x84, 0xAB, 0xDD, 0x5A, 0x2E, 0x4E, 0x1A, 0x59, 0x7B,
+ 0xD6, 0xB4, 0xB4, 0xD5, 0x25, 0xAD, 0xAF, 0xA3, 0x6B, 0x46, 0xFC, 0xD7, 0xC5, 0x7E, 0x28, 0xFD,
+ 0xA0, 0xBC, 0x11, 0x24, 0x8D, 0xE2, 0x4F, 0x81, 0x1A, 0x9D, 0xA4, 0x11, 0x6E, 0x22, 0x2F, 0xB5,
+ 0x29, 0x79, 0x95, 0x0E, 0x09, 0x89, 0xC8, 0xF2, 0xA4, 0xED, 0x82, 0x8C, 0x41, 0x03, 0x8E, 0xBC,
+ 0xC5, 0x0A, 0xB8, 0x7E, 0x65, 0x4E, 0x96, 0x2D, 0x45, 0xE9, 0x6F, 0x72, 0x92, 0xFB, 0x97, 0x22,
+ 0x49, 0x2F, 0x5D, 0x2D, 0xDD, 0x58, 0xF2, 0xEA, 0xE3, 0x33, 0x7A, 0x3E, 0xEE, 0x2A, 0x8F, 0x2C,
+ 0x56, 0xEF, 0x96, 0x72, 0x8E, 0x9D, 0x9C, 0x39, 0x9D, 0xB4, 0xD1, 0xF2, 0xDB, 0xAA, 0xD0, 0xA5,
+ 0xE0, 0x6F, 0xDA, 0x0B, 0xC3, 0x1E, 0x31, 0xD5, 0x5B, 0xC3, 0xB7, 0x56, 0xB7, 0xDE, 0x16, 0xF1,
+ 0x2C, 0x20, 0xA4, 0x9A, 0x26, 0xB5, 0x0A, 0xC1, 0x37, 0xA6, 0x63, 0x70, 0x30, 0xC0, 0x90, 0x00,
+ 0x20, 0x9F, 0xC3, 0xB7, 0x26, 0x32, 0x96, 0x6F, 0x4E, 0x9B, 0xAB, 0x4A, 0xA4, 0x67, 0x04, 0xB6,
+ 0xF6, 0x74, 0xE3, 0x24, 0xAD, 0xBF, 0x2F, 0x2E, 0xD6, 0xDD, 0xAF, 0x91, 0xD5, 0x87, 0xCC, 0xE8,
+ 0xF2, 0x42, 0x58, 0x88, 0xA5, 0x4E, 0x4E, 0xD1, 0x9C, 0x65, 0xCD, 0x4D, 0xCB, 0xF9, 0x79, 0xAD,
+ 0x17, 0x19, 0x59, 0x7C, 0x32, 0x8C, 0x5F, 0x44, 0x99, 0xED, 0x57, 0xF7, 0xEF, 0x63, 0x63, 0x71,
+ 0x78, 0xCA, 0x64, 0x5B, 0x68, 0x5A, 0x57, 0x8E, 0x14, 0x0C, 0x5C, 0x2A, 0xE4, 0x2A, 0x8C, 0x63,
+ 0x3D, 0x3F, 0xFD, 0x5C, 0x1F, 0x0B, 0x0B, 0x8E, 0xCC, 0x1D, 0x48, 0xE1, 0xE1, 0x51, 0x2B, 0xE9,
+ 0x7E, 0x48, 0x7A, 0x6F, 0xCB, 0x7F, 0xEA, 0xFB, 0x9D, 0xD8, 0x8A, 0xB0, 0xA3, 0x46, 0x55, 0x79,
+ 0x6F, 0x18, 0xAB, 0xE9, 0xE5, 0xFF, 0x00, 0x0D, 0xB6, 0xDE, 0x5D, 0x0F, 0x28, 0xF0, 0x77, 0xC6,
+ 0x4D, 0x07, 0xC6, 0xDA, 0xA5, 0xCF, 0x87, 0x74, 0xFD, 0x33, 0x5C, 0xB2, 0xBE, 0xB1, 0x2F, 0x2D,
+ 0xC3, 0xEA, 0x36, 0x8B, 0x05, 0xBB, 0x81, 0xC2, 0x18, 0xDB, 0xA9, 0xC8, 0x52, 0x70, 0x3D, 0xBD,
+ 0x6B, 0xEC, 0xB3, 0xCC, 0xA7, 0x13, 0x82, 0xE1, 0x6C, 0x2F, 0xB4, 0xAB, 0x16, 0xE7, 0x39, 0x4A,
+ 0x49, 0x45, 0xAD, 0xAC, 0xA2, 0xF6, 0x49, 0x2B, 0x5E, 0xD6, 0xD1, 0xF4, 0xDB, 0x5F, 0x13, 0x0B,
+ 0x98, 0x2C, 0x46, 0x26, 0x8C, 0x65, 0x49, 0xC7, 0xDA, 0x43, 0x9E, 0x0E, 0xF1, 0x77, 0x8A, 0x4B,
+ 0xA2, 0x77, 0x5B, 0xE9, 0x75, 0x6D, 0x1A, 0x57, 0x4A, 0xC7, 0xA0, 0xDD, 0xC8, 0xAA, 0x9B, 0xCB,
+ 0x60, 0x2A, 0x07, 0x24, 0x01, 0xB5, 0x54, 0x73, 0xEC, 0x0A, 0x80, 0xAB, 0xEA, 0x0E, 0x3A, 0xF1,
+ 0x5F, 0x0F, 0x42, 0x17, 0xB2, 0xB7, 0x92, 0x4B, 0xEE, 0xFE, 0xAD, 0xB3, 0xED, 0x63, 0xD7, 0xA9,
+ 0xCA, 0xA2, 0x97, 0x4F, 0x2F, 0x2D, 0xFF, 0x00, 0xE0, 0x79, 0x76, 0x3E, 0x3C, 0x13, 0x49, 0xF1,
+ 0x4B, 0xE3, 0x54, 0x8D, 0x1B, 0x93, 0xE1, 0xBF, 0x00, 0xAB, 0x44, 0x76, 0x30, 0x68, 0x6E, 0x2E,
+ 0xCA, 0x8D, 0xA0, 0x91, 0xC7, 0xCA, 0x88, 0x09, 0xE7, 0xF8, 0x87, 0xA5, 0x7D, 0x8A, 0x8C, 0x72,
+ 0xFC, 0xBA, 0x11, 0x4B, 0xDF, 0x6B, 0xB7, 0x59, 0x7D, 0xDB, 0x45, 0xDB, 0x6D, 0x1B, 0xE9, 0xA5,
+ 0xFE, 0x46, 0x71, 0x78, 0xFA, 0xB1, 0x8C, 0x96, 0xB5, 0xA5, 0xA7, 0xF7, 0x68, 0x52, 0x6F, 0x55,
+ 0xFF, 0x00, 0x5F, 0x67, 0xA2, 0x6B, 0xEC, 0xAD, 0x36, 0x47, 0xAA, 0xFC, 0x52, 0xF1, 0x34, 0xBE,
+ 0x17, 0xF0, 0x7E, 0xA3, 0x7B, 0x65, 0x1B, 0x1B, 0xB9, 0xD6, 0x3D, 0x2F, 0x4D, 0x48, 0xF6, 0xA6,
+ 0x6E, 0x2E, 0x58, 0x45, 0x6C, 0x85, 0xF8, 0x58, 0xF2, 0x4A, 0x60, 0xB6, 0xD1, 0xCA, 0xE4, 0x90,
+ 0x33, 0x5E, 0x7E, 0x02, 0x8C, 0x25, 0x55, 0xD4, 0xAA, 0xBD, 0xC8, 0x6A, 0xF4, 0x6D, 0x68, 0xB4,
+ 0x56, 0x5B, 0xEA, 0xD2, 0xB7, 0xDC, 0xBA, 0x1E, 0xAE, 0x22, 0x9D, 0x4C, 0x44, 0xA1, 0x81, 0xC2,
+ 0xE9, 0x2A, 0x8D, 0x46, 0xFA, 0x7B, 0xB1, 0x4A, 0xF3, 0x97, 0x64, 0xA3, 0x04, 0xDA, 0x7A, 0x6B,
+ 0x6B, 0x3D, 0x8F, 0x42, 0xF8, 0x7D, 0xA7, 0xDC, 0xFC, 0x3C, 0xB6, 0xF0, 0xC6, 0x8B, 0xE2, 0x1D,
+ 0x63, 0xC2, 0xFF, 0x00, 0x0D, 0xFC, 0x73, 0xE1, 0xAB, 0x0B, 0x2B, 0x5B, 0xB5, 0x93, 0x5B, 0x3A,
+ 0x66, 0xAF, 0xE2, 0x5B, 0xCB, 0x95, 0x70, 0xB7, 0xB6, 0xEB, 0xF6, 0x97, 0x32, 0x12, 0xA6, 0x5F,
+ 0x32, 0x58, 0x18, 0xC4, 0xA4, 0xAA, 0x9C, 0x16, 0xAF, 0xA7, 0x84, 0xA1, 0x84, 0xA1, 0x41, 0xCE,
+ 0x0D, 0xB9, 0x47, 0x9E, 0x52, 0xBC, 0x9B, 0x92, 0x95, 0xD4, 0x53, 0xD5, 0x72, 0x38, 0x2B, 0xF2,
+ 0xE9, 0x1B, 0xAD, 0x1D, 0xD7, 0x29, 0xCE, 0xA8, 0x29, 0xD6, 0xAB, 0x52, 0x34, 0x63, 0x42, 0x95,
+ 0x39, 0x46, 0x2E, 0xD6, 0xE5, 0x82, 0xBD, 0xA0, 0xDC, 0x95, 0xD3, 0x73, 0x56, 0xBD, 0x9D, 0x9C,
+ 0x95, 0xB4, 0x6A, 0xEA, 0x9E, 0xAB, 0x7B, 0xA4, 0xE8, 0xCD, 0xE2, 0x7F, 0x11, 0xB7, 0x8E, 0xF4,
+ 0x7D, 0x27, 0x4A, 0xF0, 0xA5, 0xAB, 0x9B, 0x2D, 0x7B, 0xC4, 0x26, 0x3D, 0x37, 0xFB, 0x69, 0x59,
+ 0xC4, 0x69, 0x04, 0x11, 0x48, 0x5C, 0x09, 0x1D, 0x1D, 0x98, 0x29, 0xCE, 0x02, 0xF5, 0xCE, 0x2B,
+ 0xC4, 0x84, 0x63, 0x4A, 0x33, 0x9C, 0xA7, 0x15, 0x18, 0xAB, 0xAB, 0xD9, 0x2E, 0x8B, 0x77, 0x64,
+ 0x97, 0xE2, 0xB7, 0xB7, 0x6B, 0x85, 0x1F, 0x69, 0x7A, 0x74, 0x97, 0x32, 0xD6, 0xD1, 0x49, 0xBE,
+ 0x66, 0x95, 0xED, 0x14, 0xAE, 0xDB, 0x56, 0x69, 0x24, 0xAE, 0xD6, 0xB6, 0xB2, 0x39, 0x3B, 0x8F,
+ 0x08, 0xCB, 0x27, 0x85, 0x6D, 0x2D, 0x6C, 0xF4, 0xBD, 0x3A, 0x7D, 0x27, 0xE2, 0xF4, 0x09, 0x63,
+ 0x6F, 0x69, 0x67, 0x0A, 0x2B, 0xF8, 0xC2, 0xDE, 0x1B, 0xB5, 0xF2, 0xE1, 0x66, 0x42, 0x37, 0xA0,
+ 0xB8, 0x50, 0x54, 0x1C, 0x7C, 0xE1, 0x4F, 0xB8, 0x5F, 0x56, 0xA7, 0x37, 0x15, 0x51, 0x46, 0x49,
+ 0xAD, 0x53, 0x49, 0xDB, 0xA2, 0x5A, 0xA7, 0x6E, 0x96, 0x4B, 0x4B, 0x6C, 0xAC, 0xAC, 0x79, 0xB4,
+ 0xEB, 0x63, 0x30, 0x54, 0x14, 0x30, 0x32, 0x74, 0xE3, 0x59, 0xA5, 0x05, 0x1B, 0xC5, 0xC9, 0xA7,
+ 0xA5, 0xB6, 0xB5, 0x9D, 0x93, 0xBD, 0x9A, 0xD9, 0x5B, 0x44, 0x79, 0xC6, 0xBB, 0xF0, 0x8B, 0xFE,
+ 0x13, 0xAD, 0x63, 0x41, 0xF8, 0x74, 0xDA, 0x25, 0x96, 0xA1, 0x6F, 0xF0, 0x7B, 0x46, 0x9E, 0xEB,
+ 0xFE, 0x11, 0xCD, 0x2F, 0x5A, 0xB8, 0xB4, 0xD3, 0x56, 0xDA, 0xD0, 0x99, 0x6E, 0x96, 0xF4, 0xC7,
+ 0x28, 0xDD, 0x22, 0x15, 0x74, 0xCA, 0xEC, 0x6C, 0x29, 0x50, 0x78, 0x38, 0x2A, 0xE4, 0x39, 0x3D,
+ 0x7E, 0x4C, 0x4D, 0x45, 0xFB, 0xCD, 0x1C, 0x5A, 0x69, 0x5A, 0xDD, 0x95, 0xEC, 0xE3, 0x7D, 0x1D,
+ 0xD5, 0x9F, 0x55, 0xB1, 0x74, 0x38, 0xAB, 0x8C, 0x30, 0xD9, 0x85, 0x4C, 0x24, 0x54, 0x27, 0x4E,
+ 0x8C, 0x5F, 0x3B, 0x9A, 0xB5, 0xD2, 0x49, 0xD9, 0xCE, 0xCA, 0xD2, 0xB3, 0x49, 0x25, 0x6B, 0xEF,
+ 0xAE, 0xEF, 0xC9, 0xB5, 0x9F, 0x0A, 0xFC, 0x42, 0xB0, 0xD5, 0x7C, 0x6F, 0xF1, 0x99, 0xE0, 0xD3,
+ 0x3C, 0x5D, 0x75, 0xF1, 0x1F, 0x4A, 0xBD, 0xF0, 0x6E, 0x9B, 0x73, 0xAB, 0xAC, 0x76, 0x33, 0x69,
+ 0xB3, 0xB5, 0xBC, 0x69, 0x1B, 0xDA, 0x28, 0x8D, 0xD2, 0x57, 0x82, 0x28, 0x21, 0x50, 0x0A, 0xAE,
+ 0x40, 0x19, 0x6C, 0x9E, 0x79, 0x6A, 0x70, 0xF6, 0x33, 0x0B, 0x5A, 0xA6, 0x23, 0x2A, 0xAF, 0xFE,
+ 0xD0, 0xEE, 0xDD, 0xFD, 0xD5, 0xCA, 0x92, 0xD1, 0xA8, 0xD9, 0x28, 0xAD, 0x2F, 0xEE, 0x5D, 0xB4,
+ 0x93, 0x7D, 0xBD, 0xEC, 0xAB, 0x8D, 0xF0, 0x38, 0xAC, 0xA2, 0x11, 0xCD, 0xB0, 0x93, 0xA5, 0x85,
+ 0x94, 0x9C, 0x53, 0x8C, 0xE5, 0x3B, 0xBD, 0x53, 0x8B, 0x72, 0xF7, 0xF5, 0xBE, 0x8D, 0x4B, 0x44,
+ 0x9A, 0x8A, 0x4A, 0xC9, 0x78, 0x5C, 0xFE, 0x19, 0xF8, 0xA3, 0x69, 0xA7, 0x78, 0x67, 0xE0, 0x35,
+ 0xBF, 0x81, 0xB5, 0x81, 0xE2, 0x5F, 0x17, 0x5C, 0x2F, 0x8D, 0x35, 0x4D, 0x36, 0xC8, 0x5B, 0xBE,
+ 0xAB, 0xE2, 0x58, 0x62, 0x59, 0x25, 0xB6, 0x10, 0x6F, 0xB7, 0x57, 0xB6, 0x68, 0xA1, 0x8A, 0x71,
+ 0xF2, 0x4A, 0xCA, 0x40, 0x19, 0x5E, 0x30, 0x3F, 0x3F, 0xC5, 0x61, 0xF3, 0x08, 0xD1, 0x8E, 0x4B,
+ 0x2C, 0x3F, 0xBC, 0xE4, 0xE5, 0x29, 0xE9, 0x15, 0x2D, 0x79, 0x9A, 0x5A, 0x28, 0xB6, 0xB4, 0xF8,
+ 0xAF, 0xA5, 0x92, 0xE5, 0x56, 0x47, 0xEA, 0x58, 0x79, 0x65, 0xF5, 0xA9, 0xFD, 0x6D, 0x4E, 0xF0,
+ 0xE5, 0x8C, 0x63, 0x75, 0x29, 0x38, 0xA8, 0xAB, 0x45, 0x72, 0xB6, 0xAD, 0x16, 0x9E, 0xAA, 0xD7,
+ 0xBA, 0xBB, 0xEE, 0x5B, 0xBD, 0xF8, 0x8D, 0x1F, 0x88, 0x7C, 0x65, 0xA6, 0x78, 0xF2, 0xDB, 0xE1,
+ 0xE5, 0xFD, 0xAF, 0x81, 0x3E, 0x14, 0xE8, 0x16, 0xDA, 0x5D, 0x9F, 0x86, 0xEC, 0x6F, 0xE1, 0xB2,
+ 0xD3, 0x6C, 0x2F, 0xAD, 0xBF, 0xD4, 0xDE, 0x31, 0x8E, 0xDD, 0x60, 0x32, 0xB4, 0xCB, 0x0C, 0x92,
+ 0x20, 0x4C, 0xBF, 0x97, 0x96, 0x24, 0x70, 0x7A, 0x9E, 0x23, 0x1F, 0x8C, 0xAD, 0x0C, 0x74, 0x68,
+ 0xFE, 0xE6, 0x94, 0x22, 0xDA, 0x82, 0x49, 0x25, 0x1D, 0x39, 0xA4, 0xF5, 0x4A, 0x49, 0xD9, 0x35,
+ 0x25, 0xB5, 0xE2, 0x9D, 0x9A, 0x4F, 0x47, 0x46, 0x34, 0xA8, 0xAC, 0x35, 0x1A, 0xAE, 0x2A, 0x57,
+ 0x4D, 0xB4, 0xEE, 0xEF, 0xBA, 0x49, 0xBB, 0x2B, 0xDD, 0x59, 0x27, 0xA2, 0xB3, 0x49, 0x3B, 0x35,
+ 0x4B, 0xC2, 0x7E, 0x31, 0xD5, 0xE2, 0x9F, 0x5D, 0xD7, 0xBC, 0x4A, 0x35, 0x0D, 0x27, 0xC4, 0x1F,
+ 0x12, 0x84, 0xD7, 0xB3, 0xF8, 0xC9, 0x8C, 0x36, 0x4B, 0x63, 0xA2, 0xC7, 0x39, 0x3A, 0x9C, 0x5A,
+ 0x4B, 0xB3, 0xAB, 0xAC, 0x8E, 0x0C, 0xD1, 0x08, 0x49, 0xD8, 0xC3, 0xCB, 0x4C, 0x00, 0x2B, 0xD8,
+ 0xC9, 0xA7, 0x9D, 0x51, 0xC5, 0xBA, 0xD2, 0xC3, 0xB9, 0x2A, 0xB0, 0x9B, 0x73, 0x8C, 0x1B, 0x8A,
+ 0xA4, 0xE2, 0xF9, 0x9A, 0x49, 0x45, 0xF2, 0xD9, 0xE9, 0xAD, 0xDB, 0x5B, 0xE8, 0x8E, 0x2A, 0xD0,
+ 0xC3, 0xBA, 0x6E, 0x9D, 0x29, 0x24, 0xA3, 0x68, 0xA4, 0xEF, 0x6E, 0x77, 0xA2, 0xBB, 0xD6, 0xE9,
+ 0x75, 0xE5, 0x4D, 0xDD, 0x5B, 0xAB, 0x3C, 0x3F, 0xC7, 0xBE, 0x2F, 0xB8, 0xF1, 0x9F, 0x89, 0x6E,
+ 0xF5, 0x89, 0x12, 0xDA, 0x2B, 0x58, 0xD5, 0x2C, 0x34, 0xBB, 0x5B, 0x4B, 0x31, 0xA7, 0xD9, 0xC1,
+ 0x6B, 0x6E, 0xA1, 0x20, 0x09, 0x6C, 0x19, 0x92, 0x32, 0x51, 0x14, 0xB2, 0xA9, 0xC6, 0xE2, 0xD8,
+ 0xAF, 0x8B, 0xCE, 0xF3, 0x17, 0x99, 0xE2, 0xE5, 0x38, 0xCA, 0x5E, 0xCD, 0x7B, 0xB0, 0xBE, 0x96,
+ 0x8A, 0x56, 0x56, 0x4A, 0xCA, 0x37, 0x49, 0x68, 0x97, 0x45, 0x76, 0xDD, 0xDB, 0xF5, 0x70, 0xF8,
+ 0x68, 0x50, 0xA2, 0xA9, 0x45, 0x5B, 0xD3, 0x43, 0x8B, 0xFC, 0x00, 0xF6, 0x03, 0x00, 0x7B, 0x01,
+ 0x5E, 0x42, 0x56, 0x49, 0x1D, 0x29, 0x59, 0x24, 0x14, 0xC6, 0x00, 0x74, 0x00, 0x7D, 0x00, 0x1E,
+ 0x83, 0xB0, 0xFC, 0x29, 0xC2, 0x12, 0x93, 0x50, 0x82, 0xBB, 0xE8, 0x92, 0xFD, 0x10, 0xB4, 0x4B,
+ 0xC8, 0xDD, 0xD2, 0xEC, 0x0C, 0x87, 0x24, 0x7A, 0x0C, 0x0E, 0x14, 0x63, 0xA6, 0x2B, 0xFA, 0x4F,
+ 0xC1, 0xFF, 0x00, 0x0E, 0x6B, 0x66, 0xB5, 0xBD, 0xA5, 0x68, 0xB6, 0xDD, 0xAE, 0xAE, 0xD4, 0x55,
+ 0xAF, 0xA6, 0xC9, 0x6D, 0xA2, 0x6E, 0xF6, 0x77, 0xE5, 0xF2, 0xF1, 0x71, 0xF8, 0xB8, 0xC1, 0x24,
+ 0xAD, 0x6F, 0xF8, 0x63, 0xB0, 0x8E, 0x08, 0xD2, 0x2F, 0x2F, 0x23, 0x38, 0x00, 0x71, 0xC7, 0x03,
+ 0xA1, 0xF6, 0xE2, 0xBF, 0xB7, 0xF2, 0xFE, 0x1F, 0xCB, 0xB0, 0xD9, 0x5C, 0xB2, 0xF7, 0x35, 0xED,
+ 0x1A, 0xB2, 0x6D, 0x6F, 0x65, 0x6E, 0x56, 0xF4, 0xBC, 0x7C, 0xB5, 0x4B, 0x56, 0x7C, 0xE4, 0xAA,
+ 0xC9, 0xC9, 0x49, 0x2D, 0x08, 0x2C, 0xD3, 0xC9, 0x9D, 0xB4, 0xE6, 0x11, 0xA0, 0x94, 0x09, 0x6D,
+ 0xA7, 0x6C, 0x84, 0x8C, 0x00, 0x77, 0x20, 0x03, 0xB7, 0x03, 0x8C, 0x1E, 0xD5, 0xF1, 0xDC, 0x33,
+ 0x4E, 0xB7, 0x0E, 0x67, 0xF5, 0x78, 0x0B, 0x13, 0x0F, 0x72, 0xB2, 0xF6, 0xB8, 0x5A, 0x89, 0x2E,
+ 0x48, 0xB9, 0x5D, 0xD5, 0x82, 0x5D, 0x54, 0x2C, 0x9A, 0x8D, 0xED, 0x18, 0xB4, 0x96, 0xD6, 0x5D,
+ 0x52, 0x51, 0xAF, 0x49, 0x57, 0x8B, 0x49, 0xAD, 0x1D, 0xEF, 0xD1, 0x69, 0xB6, 0xD7, 0xDB, 0x6F,
+ 0xB8, 0x9C, 0xA0, 0x2B, 0xB9, 0x31, 0x8C, 0x80, 0x06, 0x31, 0xD0, 0x73, 0x8F, 0xCA, 0xBE, 0xD7,
+ 0x13, 0x83, 0xA3, 0x5A, 0x93, 0xC4, 0x61, 0xE4, 0x9D, 0x3E, 0x6E, 0x54, 0xAD, 0x6D, 0x63, 0xA3,
+ 0x6B, 0x6D, 0x1B, 0x5D, 0x34, 0xD3, 0xA6, 0xC7, 0x1C, 0x5F, 0x2D, 0x95, 0xB5, 0xFE, 0xBF, 0x22,
+ 0x3F, 0x24, 0x71, 0xC0, 0xF4, 0xF6, 0xE9, 0xC6, 0x05, 0x79, 0x7F, 0xD9, 0x70, 0xB2, 0xD3, 0xF1,
+ 0xFF, 0x00, 0x81, 0xF2, 0xF2, 0xB7, 0x62, 0xF9, 0xDA, 0xB2, 0x4B, 0x41, 0x86, 0x3C, 0x01, 0x80,
+ 0x06, 0x06, 0x00, 0xC0, 0x18, 0xC0, 0xE9, 0x8F, 0xCA, 0xB8, 0xEA, 0xE0, 0x65, 0x0B, 0x28, 0x2D,
+ 0x15, 0xF4, 0xF4, 0xB7, 0xA5, 0xFC, 0x8A, 0x52, 0x56, 0x5F, 0x22, 0x2C, 0x6D, 0x39, 0x18, 0xF9,
+ 0x70, 0x06, 0x06, 0x17, 0x18, 0xE0, 0x63, 0xF0, 0xAF, 0x3B, 0xD9, 0x2A, 0x75, 0xD5, 0x5B, 0x5A,
+ 0x6B, 0x4F, 0x2F, 0xBB, 0x6F, 0xC0, 0xB5, 0xF0, 0xD9, 0x6C, 0x61, 0xEA, 0xD6, 0x21, 0xE3, 0xFB,
+ 0x4C, 0x4A, 0x14, 0xA6, 0x44, 0x98, 0x1C, 0x1C, 0xFD, 0xD0, 0x07, 0xE0, 0x6B, 0xF9, 0xD7, 0xC6,
+ 0xBF, 0x0E, 0xA9, 0x63, 0x70, 0x0F, 0x8A, 0xF2, 0xC8, 0x28, 0xCE, 0x95, 0xFD, 0xAB, 0x57, 0x7C,
+ 0xD7, 0x4B, 0x95, 0x24, 0xB4, 0x56, 0xB3, 0xD9, 0x75, 0xDA, 0xD7, 0x67, 0xAD, 0x96, 0x62, 0xF9,
+ 0x24, 0xA8, 0x4D, 0xE8, 0xF6, 0x2E, 0xFC, 0x3B, 0xF0, 0xC1, 0xF1, 0x97, 0x8E, 0x7C, 0x29, 0xE1,
+ 0x50, 0x06, 0xDD, 0x6F, 0x5B, 0xB7, 0xB0, 0x94, 0x64, 0xA7, 0xEE, 0xD9, 0xC7, 0x98, 0x01, 0x03,
+ 0x23, 0xE4, 0x56, 0xE9, 0x5F, 0xC9, 0x78, 0x7A, 0x57, 0xC4, 0x42, 0x94, 0xD5, 0xAC, 0xF5, 0x56,
+ 0xED, 0xAD, 0xAC, 0xFD, 0x2D, 0xB7, 0xCB, 0xA1, 0xED, 0xD7, 0xA9, 0xEC, 0xE8, 0x4A, 0x71, 0xED,
+ 0xA7, 0xF5, 0xA7, 0xF5, 0xB7, 0x63, 0xFA, 0xEE, 0xFD, 0x99, 0x7E, 0x1E, 0x69, 0x9A, 0x4E, 0x97,
+ 0x60, 0xB0, 0x58, 0x43, 0x0D, 0x86, 0x89, 0x6D, 0x1D, 0xA5, 0x8C, 0x6B, 0x19, 0x48, 0xD4, 0xC6,
+ 0x00, 0xCA, 0x01, 0xC7, 0x00, 0x28, 0xED, 0x8E, 0x0F, 0xB8, 0xFD, 0xB3, 0x0F, 0x4E, 0x39, 0x6E,
+ 0x4F, 0x4E, 0x8C, 0x1D, 0xAA, 0x4D, 0x5E, 0x4D, 0x79, 0xEB, 0x67, 0xE4, 0x9D, 0xF6, 0x56, 0x76,
+ 0xB7, 0x4B, 0x3F, 0xCC, 0x1B, 0x58, 0xFC, 0xCE, 0x53, 0x97, 0xC3, 0x0D, 0x12, 0xFB, 0xBB, 0x3B,
+ 0x6B, 0x6D, 0xD2, 0x7E, 0xA9, 0x68, 0x7D, 0x11, 0xE3, 0xEF, 0x1E, 0xDB, 0xF8, 0x50, 0x58, 0x68,
+ 0xD6, 0x0A, 0xB7, 0x1A, 0xF6, 0xB1, 0x28, 0xB4, 0xD3, 0x6D, 0x23, 0x0A, 0xEC, 0xB9, 0x1C, 0xB1,
+ 0x40, 0x0F, 0xCA, 0x02, 0xFE, 0x87, 0xD3, 0x15, 0xBE, 0x55, 0x95, 0x3C, 0x72, 0x96, 0x26, 0xAB,
+ 0xE5, 0xA3, 0x0D, 0x64, 0xFE, 0x5B, 0x6E, 0xBF, 0x44, 0xB4, 0xEE, 0x83, 0x32, 0xCC, 0xE1, 0x81,
+ 0x8C, 0x68, 0x52, 0x57, 0xA8, 0xF4, 0x49, 0x5B, 0xA5, 0x93, 0xD3, 0xA2, 0xB5, 0x97, 0x96, 0xD6,
+ 0xD9, 0x2B, 0xD6, 0xFA, 0x04, 0xD6, 0xFA, 0x0C, 0xFA, 0x8E, 0xB1, 0x7B, 0x3C, 0xFA, 0x8F, 0xD9,
+ 0xCD, 0xD3, 0x48, 0x58, 0x46, 0xB0, 0xB1, 0x53, 0x80, 0x14, 0x11, 0xD3, 0x23, 0xE5, 0xCE, 0x38,
+ 0x1D, 0x33, 0xC6, 0x13, 0xC4, 0x53, 0x96, 0x21, 0x51, 0xC3, 0x41, 0x28, 0x6D, 0xD5, 0xE9, 0xA6,
+ 0x9F, 0xF0, 0x77, 0xE9, 0xB5, 0x91, 0x51, 0xC1, 0xCE, 0x9E, 0x0A, 0x55, 0xF1, 0x12, 0xF7, 0xD2,
+ 0xBE, 0xFB, 0x26, 0xBF, 0xE0, 0x5A, 0xEB, 0xB5, 0x9B, 0xB5, 0xAD, 0xE2, 0x1F, 0x00, 0x2E, 0xFC,
+ 0x47, 0xE2, 0x0D, 0x6F, 0xC6, 0x3A, 0xA6, 0xAF, 0xAA, 0xDD, 0xEA, 0x1A, 0x5D, 0xAE, 0xAC, 0xF6,
+ 0x1A, 0x5C, 0x52, 0xE0, 0x44, 0xB1, 0xC2, 0x4A, 0x83, 0xC0, 0xEF, 0x8C, 0x63, 0x07, 0x1C, 0x7D,
+ 0x0F, 0xD1, 0x71, 0x2C, 0x30, 0xB8, 0x5A, 0x34, 0x68, 0xD0, 0xA7, 0x18, 0xB6, 0xAF, 0x74, 0x92,
+ 0x7D, 0x34, 0x76, 0xE9, 0x7B, 0xDB, 0xD3, 0xA7, 0x4F, 0x1F, 0x20, 0xF6, 0xB5, 0xB1, 0x33, 0xAE,
+ 0xE5, 0x74, 0xAF, 0xA5, 0xD6, 0x8F, 0x75, 0x6D, 0x76, 0xE5, 0x76, 0xDA, 0xD7, 0xD3, 0x65, 0xA1,
+ 0xF1, 0x67, 0xC1, 0xBA, 0x6F, 0x89, 0xE4, 0xF1, 0x4E, 0x8F, 0x25, 0xAA, 0x4F, 0x1C, 0x9A, 0x2C,
+ 0x93, 0x4B, 0x16, 0xD0, 0x54, 0x1C, 0x6D, 0x6D, 0xC3, 0xD0, 0x80, 0x38, 0xE4, 0x64, 0x8C, 0x63,
+ 0x1C, 0xFC, 0xF6, 0x36, 0x9A, 0xC5, 0x64, 0x6A, 0x15, 0x52, 0xBA, 0x7E, 0xEF, 0x4D, 0x2C, 0x9E,
+ 0x9F, 0x7B, 0xE9, 0xD3, 0x67, 0xA5, 0xBD, 0x8C, 0x1C, 0xA5, 0x47, 0x36, 0x95, 0x28, 0x2D, 0x25,
+ 0xA3, 0xE9, 0xB2, 0x4D, 0x3B, 0x3D, 0x15, 0x9B, 0xDE, 0xCA, 0xC9, 0x5B, 0xD3, 0xF9, 0xB5, 0xF8,
+ 0x03, 0xE0, 0xB8, 0xFE, 0x1E, 0xFF, 0x00, 0xC1, 0x4C, 0xBF, 0x67, 0x0F, 0x08, 0xC0, 0x02, 0xDA,
+ 0xE9, 0x5F, 0xB5, 0xFF, 0x00, 0x80, 0x3E, 0xC6, 0xAB, 0xF7, 0x52, 0x19, 0xBC, 0x55, 0xA7, 0x4B,
+ 0x12, 0x8E, 0x07, 0x01, 0x65, 0x51, 0xF8, 0x57, 0xE4, 0x54, 0xE9, 0xFB, 0x3C, 0xEE, 0x92, 0xB7,
+ 0xFC, 0xBC, 0x83, 0xDA, 0xDB, 0xB4, 0xF6, 0xF5, 0x3F, 0x44, 0x8C, 0xDD, 0x4C, 0xB6, 0x52, 0x6B,
+ 0x5E, 0x59, 0x2F, 0xB9, 0x35, 0xFD, 0x6D, 0xE8, 0xB6, 0x3F, 0xBC, 0x2A, 0xFD, 0x1C, 0xF9, 0x60,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFE, 0x28, 0xFF, 0x00, 0xE0, 0xB5, 0xEB, 0x8F, 0xF8, 0x28, 0x17,
+ 0xC4, 0x83, 0x8F, 0x97, 0xFE, 0x10, 0xCF, 0x09, 0xA8, 0xC6, 0x38, 0xC7, 0x87, 0x6D, 0x78, 0xC7,
+ 0xE5, 0x5F, 0x03, 0xC4, 0x18, 0x6A, 0xBF, 0x5C, 0x9E, 0x29, 0x47, 0xF7, 0x77, 0x51, 0xBF, 0x9A,
+ 0x8C, 0x5D, 0xAD, 0xDA, 0xCD, 0x79, 0x1F, 0x4F, 0x95, 0xCA, 0x2B, 0x09, 0x18, 0x75, 0xD7, 0xF3,
+ 0xB1, 0x8F, 0xA5, 0x5A, 0x41, 0xAB, 0x78, 0x67, 0xF6, 0x69, 0xF1, 0x37, 0xC2, 0xF9, 0xD6, 0xD7,
+ 0xC1, 0xBE, 0x1B, 0x7B, 0x5D, 0x37, 0xC5, 0x96, 0xF6, 0x17, 0x82, 0xD9, 0xAD, 0x75, 0x23, 0x22,
+ 0x0B, 0xB8, 0xAE, 0xE0, 0x53, 0x9F, 0x31, 0xA4, 0x2C, 0xE5, 0x98, 0x7C, 0xCA, 0x54, 0x82, 0x41,
+ 0x15, 0xF5, 0xFC, 0x2B, 0x53, 0x0D, 0x3C, 0x9E, 0xB6, 0x1A, 0x9B, 0x4A, 0x76, 0x6E, 0xDD, 0xD2,
+ 0x8B, 0xBE, 0x9B, 0x3D, 0x57, 0x53, 0xF3, 0x9E, 0x2A, 0x6B, 0x0B, 0x99, 0xFB, 0x6C, 0x5D, 0x26,
+ 0xD4, 0x94, 0x14, 0x27, 0x6B, 0xA8, 0x49, 0x4E, 0x2D, 0xEB, 0xF6, 0x6F, 0x1D, 0x13, 0x4A, 0xCF,
+ 0x6E, 0x96, 0x3E, 0xE6, 0xFD, 0xAA, 0x7C, 0x33, 0xE2, 0x2F, 0x17, 0xFC, 0x1C, 0x16, 0xFE, 0x18,
+ 0x9E, 0xE2, 0x3B, 0x94, 0x10, 0x5C, 0xC8, 0xF6, 0x77, 0xBF, 0x63, 0x93, 0x62, 0x94, 0x2D, 0xB5,
+ 0xB3, 0x83, 0x80, 0xAC, 0x71, 0xFE, 0xCF, 0xD2, 0xBC, 0xFE, 0x19, 0xAD, 0x4F, 0x0D, 0x99, 0xCA,
+ 0x33, 0xB2, 0x93, 0x4D, 0x46, 0xEB, 0x44, 0xFE, 0x5A, 0xA5, 0x6D, 0x34, 0xB6, 0xFD, 0x11, 0xE8,
+ 0x71, 0x05, 0x39, 0xCF, 0x01, 0x4A, 0xA2, 0xA4, 0xAA, 0x42, 0x32, 0x8C, 0xA5, 0x16, 0x93, 0x52,
+ 0x8F, 0x2B, 0x56, 0xB6, 0x89, 0xEA, 0xD3, 0x4B, 0xCB, 0x45, 0x7B, 0x1E, 0x87, 0xE1, 0x25, 0xD5,
+ 0xEE, 0x7E, 0x07, 0x69, 0xC9, 0x6D, 0x24, 0xAB, 0xAC, 0x8F, 0x0B, 0x08, 0xF7, 0xC6, 0xE1, 0x66,
+ 0x49, 0x96, 0x1C, 0xE1, 0x58, 0x8C, 0x02, 0x08, 0x3F, 0x95, 0x72, 0xE3, 0x15, 0x1A, 0x79, 0xF4,
+ 0xB4, 0xF7, 0x14, 0xD7, 0xDD, 0x7F, 0xF2, 0xFF, 0x00, 0x80, 0x3C, 0xB9, 0x62, 0x67, 0xC3, 0x54,
+ 0xEC, 0xDF, 0xB4, 0xF6, 0x49, 0x2D, 0x93, 0x4F, 0x97, 0x6F, 0x5F, 0x5B, 0x6B, 0xBD, 0x8F, 0x42,
+ 0xFD, 0x8F, 0xBE, 0x26, 0xF8, 0xA7, 0xE1, 0xB7, 0x84, 0xEC, 0x75, 0x2F, 0x8B, 0xBF, 0xE9, 0x1F,
+ 0xBB, 0x9A, 0xD7, 0x5E, 0x8E, 0xF9, 0xD2, 0xF6, 0xE4, 0x5A, 0x86, 0x71, 0x15, 0xC1, 0x00, 0x95,
+ 0x32, 0x28, 0x00, 0x80, 0x08, 0x07, 0x00, 0x90, 0x70, 0x01, 0xFD, 0x17, 0x0B, 0x9A, 0xD2, 0x86,
+ 0x75, 0x4A, 0x96, 0x5D, 0x36, 0xA9, 0x54, 0x51, 0x53, 0x51, 0x8D, 0xA3, 0x7D, 0x2C, 0xF4, 0x5A,
+ 0x35, 0xD9, 0x25, 0x75, 0xB3, 0x4D, 0x9C, 0x38, 0x4C, 0x2D, 0x4A, 0xD9, 0x13, 0x79, 0xAC, 0x2F,
+ 0x28, 0x29, 0x38, 0xF3, 0xB4, 0xDD, 0xAE, 0xD2, 0xBB, 0xBB, 0x5A, 0x69, 0xAB, 0x77, 0xD3, 0x56,
+ 0x92, 0x3C, 0xAB, 0xE3, 0xDF, 0xEC, 0xD9, 0xF1, 0x2A, 0xF7, 0xC4, 0x9A, 0xA7, 0xC5, 0x7F, 0xD9,
+ 0xCF, 0xC7, 0x1A, 0x7F, 0x86, 0x3E, 0x15, 0xFC, 0x40, 0xBB, 0x6B, 0xFB, 0xFD, 0x1A, 0xD1, 0x7E,
+ 0xD1, 0xA5, 0xE9, 0x1A, 0x84, 0xC9, 0xF2, 0xC9, 0x65, 0x28, 0xC8, 0xF2, 0xA7, 0x0A, 0xAD, 0x90,
+ 0x51, 0xFC, 0xCD, 0xE3, 0x68, 0x00, 0x33, 0x7F, 0x50, 0xF0, 0x5F, 0x1D, 0x64, 0x59, 0x4D, 0x28,
+ 0x61, 0xF8, 0xA3, 0x07, 0xCC, 0xE3, 0x68, 0x45, 0xDA, 0x2F, 0x44, 0xD7, 0x2B, 0x69, 0x34, 0xF5,
+ 0x77, 0x4D, 0x5B, 0x91, 0x2D, 0x9B, 0xBB, 0x4F, 0xE3, 0xF0, 0xF8, 0x78, 0xE2, 0xE9, 0xCA, 0x78,
+ 0x1A, 0x4D, 0xC9, 0xAE, 0x67, 0xCB, 0x39, 0x53, 0x8E, 0xBB, 0x6B, 0x67, 0x79, 0x35, 0x66, 0xE7,
+ 0xA3, 0xBB, 0x77, 0xD1, 0x24, 0xBC, 0x8B, 0xE0, 0x8F, 0xC3, 0xAD, 0x4F, 0xE1, 0x9E, 0x83, 0xE2,
+ 0x1B, 0xCF, 0x18, 0xDE, 0xC7, 0xA8, 0x78, 0xA7, 0x52, 0xD4, 0x1F, 0x52, 0xD5, 0x75, 0x17, 0x76,
+ 0x91, 0x65, 0x48, 0x8B, 0x08, 0x83, 0x12, 0x07, 0xCA, 0xA3, 0x2D, 0x8E, 0xC4, 0x0C, 0x74, 0xAF,
+ 0xD3, 0xF8, 0x93, 0x33, 0xC3, 0x67, 0xD8, 0xDC, 0x3E, 0x13, 0x28, 0x87, 0x2E, 0x1E, 0x31, 0x5C,
+ 0xB1, 0x56, 0xB2, 0xE6, 0xE5, 0x76, 0x6A, 0xCA, 0xF7, 0x49, 0xEE, 0x9A, 0xD5, 0xAB, 0x3D, 0x9C,
+ 0xE1, 0x69, 0x2C, 0x2B, 0xAD, 0x88, 0x9D, 0x25, 0x49, 0x45, 0x28, 0x28, 0x5D, 0x3E, 0x54, 0x96,
+ 0xAF, 0x99, 0x5D, 0x36, 0xDB, 0x6D, 0xBE, 0xD6, 0x4D, 0xC6, 0xED, 0xAE, 0x4F, 0xE0, 0x55, 0x8C,
+ 0x9E, 0x3C, 0xF1, 0xA7, 0xC4, 0x2F, 0x8A, 0xF7, 0x7B, 0xA5, 0xB4, 0x97, 0x54, 0x3E, 0x18, 0xD0,
+ 0x24, 0x6F, 0x9B, 0xCB, 0xB3, 0xB4, 0x07, 0x70, 0x45, 0x39, 0xE4, 0x85, 0x04, 0xFD, 0x09, 0xC7,
+ 0x07, 0x1E, 0xCF, 0x16, 0x57, 0x86, 0x47, 0x95, 0x61, 0x32, 0x08, 0x46, 0xD6, 0xD6, 0x4D, 0x25,
+ 0x67, 0x51, 0xDE, 0x4A, 0x3A, 0x6B, 0x7B, 0x24, 0x93, 0x69, 0x27, 0xF0, 0xDE, 0xEE, 0xCF, 0x87,
+ 0x2F, 0xF6, 0x75, 0xB1, 0xAB, 0xDB, 0x24, 0xB9, 0x57, 0xB4, 0x92, 0x49, 0xB6, 0x9C, 0xED, 0xAE,
+ 0xDB, 0x42, 0x1C, 0xB1, 0xB3, 0x4D, 0xBB, 0xB5, 0xA6, 0xEB, 0x1F, 0xE3, 0xEF, 0x89, 0x6E, 0xA0,
+ 0xF1, 0x06, 0x8C, 0xDA, 0x13, 0x47, 0x15, 0xEE, 0x99, 0x71, 0x0A, 0x68, 0x46, 0x3B, 0x88, 0x82,
+ 0xDE, 0x48, 0x18, 0x19, 0x91, 0xD8, 0x31, 0xDA, 0x32, 0x02, 0x1F, 0x30, 0xA6, 0x03, 0x36, 0x41,
+ 0x07, 0x29, 0xF9, 0xC6, 0x0F, 0x8A, 0xB8, 0x67, 0x21, 0xC5, 0x51, 0xCA, 0xB8, 0xA7, 0x10, 0xA9,
+ 0x55, 0xC4, 0x35, 0x15, 0x07, 0x19, 0xBF, 0x7A, 0x4F, 0x96, 0x09, 0x72, 0xC5, 0xC6, 0x2E, 0x3E,
+ 0xEC, 0x96, 0x96, 0xD2, 0xD1, 0x49, 0xBD, 0x7F, 0xAB, 0x32, 0x1E, 0x1F, 0xCA, 0xEB, 0xF0, 0x6E,
+ 0x61, 0x0A, 0x1F, 0xC0, 0x95, 0x29, 0x4E, 0x53, 0x49, 0xF3, 0xA5, 0x05, 0xCC, 0xA5, 0x16, 0x95,
+ 0xDC, 0x95, 0xAF, 0x0E, 0x58, 0xB7, 0x74, 0x93, 0xD1, 0x28, 0x9F, 0xA1, 0xFF, 0x00, 0x0B, 0x7C,
+ 0x53, 0x63, 0xE3, 0x9F, 0x03, 0xDA, 0x5A, 0x6B, 0x32, 0x5B, 0x4F, 0x27, 0xD9, 0x7C, 0x99, 0x63,
+ 0x79, 0xE3, 0xB8, 0xF9, 0xED, 0xD5, 0x5A, 0x54, 0x0C, 0x09, 0x52, 0x63, 0xF9, 0x0E, 0x41, 0xE3,
+ 0x00, 0xF6, 0x15, 0xF9, 0x96, 0x7D, 0x96, 0x62, 0x32, 0xFC, 0xC2, 0x59, 0x8E, 0x59, 0x16, 0xE0,
+ 0xA5, 0x66, 0xE2, 0x9D, 0x97, 0x5B, 0x35, 0xBD, 0x9A, 0x6D, 0x3B, 0x2D, 0xEC, 0x9E, 0x8D, 0x23,
+ 0xE4, 0x63, 0x4D, 0xE5, 0xB8, 0x87, 0x96, 0x56, 0xA9, 0x79, 0x47, 0x58, 0x4A, 0xD6, 0x72, 0x8B,
+ 0xD2, 0x3A, 0x6E, 0x9A, 0x56, 0x4D, 0x4A, 0xCE, 0x4B, 0xDE, 0x4B, 0x57, 0x6F, 0xA4, 0xBE, 0x04,
+ 0xFC, 0x1C, 0xD7, 0xFE, 0x26, 0xF8, 0x7F, 0x5A, 0xD7, 0x35, 0xFB, 0x8D, 0x23, 0xC0, 0x1F, 0x07,
+ 0xBC, 0x31, 0xA8, 0x3E, 0x91, 0xAD, 0x7C, 0x60, 0xF1, 0xEC, 0xAD, 0xA6, 0x78, 0x3A, 0x70, 0x81,
+ 0x7F, 0x73, 0xA6, 0xC6, 0x37, 0x5C, 0x6A, 0x97, 0x78, 0x20, 0xFD, 0x96, 0xCA, 0x39, 0x9B, 0x81,
+ 0x9D, 0xBC, 0x91, 0xF2, 0xFC, 0x45, 0x5E, 0x8E, 0x07, 0x1F, 0x42, 0xB6, 0x19, 0x73, 0xE2, 0xE4,
+ 0x93, 0x54, 0xA1, 0x34, 0xA5, 0x19, 0x36, 0xD2, 0x52, 0x71, 0x56, 0x87, 0x92, 0x9B, 0x8B, 0xB2,
+ 0x5B, 0x26, 0xAF, 0x2B, 0x17, 0x46, 0x94, 0xEA, 0x52, 0xB3, 0x8C, 0xAE, 0x95, 0xAC, 0xF5, 0x72,
+ 0x4A, 0x5A, 0x69, 0x6B, 0x6B, 0x6B, 0xEC, 0x9A, 0x6B, 0xA5, 0x97, 0xCD, 0xBF, 0x1C, 0xFF, 0x00,
+ 0x69, 0xBF, 0x83, 0x3F, 0xB2, 0xD7, 0x88, 0xF4, 0xCF, 0x04, 0x7E, 0xCC, 0xFF, 0x00, 0x0D, 0xB4,
+ 0xEF, 0x1D, 0x78, 0x9A, 0xDE, 0x43, 0x75, 0x79, 0xFB, 0x47, 0xFC, 0x79, 0xD1, 0xF4, 0xFF, 0x00,
+ 0x10, 0x6A, 0x1A, 0x0C, 0xEE, 0x76, 0xDB, 0x37, 0x85, 0xBC, 0x17, 0x22, 0xC9, 0xA6, 0xE9, 0xE1,
+ 0x59, 0x8B, 0x2C, 0xD7, 0x6D, 0x7B, 0x71, 0x85, 0xCA, 0x98, 0x99, 0x85, 0x7D, 0x5F, 0x0D, 0x70,
+ 0x9E, 0x67, 0xC5, 0x14, 0xE7, 0x9A, 0xE7, 0xB8, 0x88, 0xC6, 0x94, 0x24, 0x93, 0xC3, 0x51, 0xAA,
+ 0xE1, 0xCD, 0x1B, 0x3B, 0xFB, 0x5A, 0xAA, 0xD2, 0x6D, 0x5D, 0x59, 0x46, 0xEB, 0x95, 0x3B, 0xE8,
+ 0xAE, 0x7D, 0x2F, 0x0C, 0xF0, 0xEC, 0x73, 0x15, 0x52, 0x58, 0xEA, 0xAE, 0x18, 0x77, 0xEE, 0xC2,
+ 0x9C, 0x13, 0x51, 0x72, 0x93, 0x52, 0x71, 0x6F, 0xA4, 0x64, 0x93, 0xE5, 0x4B, 0xDD, 0x52, 0x6A,
+ 0x3A, 0x2E, 0x54, 0x43, 0xA6, 0xFC, 0x65, 0xD5, 0xBF, 0x68, 0x1F, 0x09, 0xB6, 0xBF, 0xF1, 0x43,
+ 0xC6, 0x7A, 0xBF, 0x8C, 0x3C, 0x55, 0x10, 0x65, 0x7D, 0x5F, 0xC5, 0x37, 0xD3, 0x6A, 0x72, 0xCA,
+ 0x42, 0x96, 0x46, 0xB7, 0x12, 0x65, 0x52, 0x2D, 0xAC, 0xC5, 0x55, 0x42, 0x2A, 0x8D, 0xA4, 0x01,
+ 0x8E, 0x3E, 0x7B, 0x1F, 0x91, 0xAE, 0x16, 0xCF, 0xE5, 0x4F, 0x29, 0xA4, 0xA1, 0x4A, 0x49, 0x2B,
+ 0x38, 0x27, 0xEE, 0x3B, 0x59, 0x4B, 0x95, 0xA5, 0x34, 0xDA, 0x4E, 0xF7, 0xE5, 0x76, 0xBF, 0x2A,
+ 0xBD, 0xCE, 0x0A, 0xB8, 0x19, 0x61, 0xB9, 0x68, 0xB8, 0xD9, 0xAB, 0x3D, 0x1E, 0x89, 0xA4, 0x93,
+ 0x4D, 0xAD, 0x1F, 0x66, 0x92, 0xB3, 0x5A, 0x5B, 0x44, 0x8F, 0x99, 0x3E, 0x21, 0xFC, 0x41, 0xF0,
+ 0x56, 0xAF, 0xE1, 0x0D, 0x4B, 0xC2, 0x9A, 0x8C, 0x76, 0xBA, 0x96, 0xB3, 0xA0, 0x6B, 0xD1, 0x43,
+ 0xA7, 0xD8, 0x88, 0x08, 0xBC, 0x59, 0x55, 0x90, 0xCE, 0xEA, 0xDD, 0x55, 0x04, 0x4C, 0xFB, 0x9B,
+ 0x18, 0x39, 0x51, 0xC9, 0x38, 0x3D, 0x13, 0xE1, 0xBA, 0xF8, 0x4C, 0x7D, 0x3C, 0xCA, 0xF1, 0xF6,
+ 0x75, 0x62, 0xB9, 0xA2, 0xA9, 0x4B, 0x95, 0xC6, 0xCF, 0x95, 0x36, 0xBD, 0xDB, 0xDD, 0xA8, 0xC5,
+ 0x5D, 0x5B, 0x55, 0x64, 0x95, 0xCF, 0x6F, 0x85, 0xFE, 0xBD, 0x5F, 0x11, 0x52, 0xBD, 0x0A, 0x53,
+ 0xA7, 0x04, 0xE5, 0x17, 0x29, 0x68, 0x9D, 0x97, 0x4B, 0xA5, 0x75, 0xCC, 0xAC, 0xAC, 0xDA, 0xD1,
+ 0xB4, 0xEC, 0x7C, 0xF5, 0xE1, 0x3F, 0x82, 0x5E, 0x21, 0xF1, 0x67, 0x8A, 0x24, 0xF1, 0x0E, 0x97,
+ 0x61, 0x04, 0x7E, 0x1C, 0xF0, 0xDD, 0xC3, 0x4B, 0xAC, 0xF8, 0x8F, 0x5C, 0xBE, 0x83, 0x45, 0xF0,
+ 0x8E, 0x8D, 0x1C, 0x71, 0x16, 0x32, 0x3E, 0xA1, 0x23, 0xF9, 0x2E, 0xD1, 0x0D, 0xA1, 0xA2, 0x8D,
+ 0x9D, 0xDF, 0x2B, 0xB5, 0x4E, 0x78, 0xF5, 0xB0, 0xF8, 0xC9, 0x65, 0x78, 0x5A, 0xF9, 0x4D, 0x14,
+ 0xEB, 0xD4, 0xFB, 0x2D, 0x45, 0xA8, 0x72, 0xB6, 0xB7, 0x6A, 0x2D, 0x45, 0x59, 0xBB, 0x59, 0xDD,
+ 0x2B, 0x26, 0xB6, 0xBF, 0xDA, 0x67, 0x99, 0xB5, 0x3C, 0x47, 0x0F, 0xCB, 0x24, 0x75, 0x5D, 0x3A,
+ 0xF3, 0xB3, 0xA6, 0xE0, 0x9B, 0xAA, 0xDD, 0xD5, 0xE3, 0xCB, 0xFC, 0xB3, 0xD9, 0x39, 0x24, 0x92,
+ 0xBA, 0x4D, 0x3B, 0x5B, 0xED, 0xDB, 0x2B, 0xDF, 0x84, 0x5A, 0x36, 0x9D, 0x1D, 0xC5, 0x8E, 0xA9,
+ 0xFF, 0x00, 0x0B, 0x3A, 0x54, 0xB6, 0x74, 0x53, 0x62, 0x92, 0x68, 0x3E, 0x09, 0x8A, 0x40, 0x3E,
+ 0x42, 0x1C, 0xA8, 0xBC, 0xB9, 0x41, 0xB1, 0xB7, 0x02, 0xB6, 0xBD, 0x32, 0x09, 0x18, 0xAF, 0x85,
+ 0x95, 0x0A, 0x4E, 0x6E, 0x92, 0x4F, 0xDA, 0xD9, 0x5A, 0x2A, 0x2E, 0xC9, 0xDB, 0x58, 0xB9, 0x26,
+ 0x9A, 0xBA, 0x76, 0x4E, 0x2A, 0xCE, 0xD6, 0x49, 0xD9, 0x27, 0xF9, 0x7E, 0x3E, 0xAE, 0x2B, 0x0B,
+ 0x0A, 0x8F, 0x34, 0x4A, 0x8C, 0x23, 0xBA, 0x95, 0x9C, 0xAC, 0x96, 0xA9, 0xAB, 0x72, 0xEA, 0xAC,
+ 0xEC, 0xAE, 0xB6, 0x5A, 0x5B, 0x4F, 0x8D, 0xBF, 0x69, 0xAF, 0x8B, 0x9A, 0xCE, 0xAB, 0xE1, 0x6B,
+ 0xDF, 0x0F, 0x5A, 0x78, 0xB6, 0x5F, 0x86, 0x7A, 0x05, 0xAC, 0x9B, 0x53, 0x4B, 0xF0, 0x1F, 0x87,
+ 0xDF, 0x48, 0xB1, 0xBB, 0x42, 0x09, 0x41, 0x70, 0xF6, 0x8D, 0x1C, 0xD3, 0xFC, 0xFB, 0x50, 0x99,
+ 0xE4, 0x90, 0xFC, 0xCC, 0xC4, 0xE0, 0x36, 0xEF, 0xD2, 0x78, 0x3B, 0x87, 0xF0, 0xCE, 0x0F, 0x11,
+ 0x89, 0xA7, 0xED, 0x71, 0x0E, 0x36, 0xA7, 0x4E, 0x70, 0x4E, 0x94, 0x55, 0x95, 0xDA, 0xEA, 0x9B,
+ 0x4B, 0x4E, 0xA9, 0x2B, 0x37, 0xCD, 0xCA, 0x97, 0xE4, 0x58, 0x9E, 0x31, 0x78, 0xEE, 0x22, 0xA3,
+ 0x92, 0x65, 0xCB, 0x97, 0x0D, 0x1D, 0x5B, 0x76, 0xE6, 0x9F, 0xBB, 0xA6, 0x96, 0x51, 0x8C, 0x53,
+ 0x8F, 0xBB, 0x15, 0x67, 0xB6, 0x9A, 0x26, 0x79, 0x1F, 0xEC, 0x13, 0xA4, 0xF8, 0x27, 0x59, 0xF1,
+ 0xA6, 0x87, 0x07, 0xC4, 0xE8, 0xAF, 0xCF, 0x85, 0xEF, 0x6F, 0xE7, 0x8F, 0x58, 0xBE, 0xD3, 0x6F,
+ 0xA3, 0xD3, 0x2E, 0x61, 0x91, 0xCE, 0xDB, 0x69, 0xE4, 0xBA, 0x96, 0x29, 0x51, 0x15, 0x58, 0x29,
+ 0x25, 0x90, 0x8C, 0x01, 0x9C, 0x63, 0x23, 0xE7, 0x38, 0x83, 0x1F, 0x9F, 0x4E, 0xAD, 0x7C, 0xB7,
+ 0x30, 0x84, 0x69, 0xD3, 0xA5, 0x07, 0xA5, 0x35, 0x68, 0x25, 0xCA, 0x9C, 0x6D, 0x3D, 0x3A, 0xB5,
+ 0x65, 0x2B, 0x6A, 0xF5, 0x69, 0x5E, 0xFF, 0x00, 0x3B, 0x9D, 0x2A, 0x15, 0x78, 0xD2, 0x93, 0xC4,
+ 0x45, 0xCE, 0x94, 0x20, 0x9A, 0x5A, 0x68, 0xDA, 0x49, 0xDB, 0xB7, 0xC4, 0xED, 0xD5, 0x6E, 0xBA,
+ 0x23, 0xF4, 0x5B, 0xE2, 0xAF, 0x86, 0xFC, 0x1F, 0xE1, 0x8F, 0x1A, 0xEA, 0x3A, 0x6F, 0x80, 0x35,
+ 0xEB, 0x7F, 0x11, 0xF8, 0x40, 0x2C, 0x52, 0xE8, 0x9A, 0x94, 0x1A, 0x8C, 0x5A, 0x9C, 0xC6, 0x23,
+ 0x18, 0xDE, 0x93, 0x4B, 0x1A, 0xAA, 0x86, 0x0C, 0x1B, 0x80, 0x07, 0x18, 0xF5, 0xAF, 0xCF, 0xAA,
+ 0xD0, 0xC1, 0xD5, 0x8A, 0x9B, 0x9B, 0x6A, 0x50, 0x4D, 0x34, 0xD3, 0xE5, 0x76, 0xE5, 0x6B, 0xCA,
+ 0xF6, 0xD1, 0x6A, 0xAF, 0xB2, 0x49, 0x33, 0xE8, 0x29, 0xF2, 0xA7, 0x15, 0x49, 0x3E, 0x5B, 0xDB,
+ 0x5B, 0x74, 0xDB, 0x44, 0x96, 0x96, 0xB7, 0x45, 0xA5, 0xB4, 0x3C, 0xFC, 0x0C, 0x00, 0x30, 0x07,
+ 0x03, 0x80, 0x30, 0x3D, 0xB0, 0x3F, 0x2A, 0xF9, 0xEC, 0x4A, 0x8C, 0x6A, 0x4E, 0x34, 0xDF, 0xBA,
+ 0x9D, 0x97, 0xA2, 0xD1, 0x74, 0x5B, 0x69, 0xD1, 0x1D, 0x4A, 0xD6, 0x56, 0x5A, 0x1F, 0x26, 0xFE,
+ 0xD2, 0xF3, 0xCD, 0xA6, 0xE9, 0x29, 0xA9, 0xD9, 0xC9, 0xF6, 0x4B, 0xDD, 0x35, 0x5B, 0x52, 0xB3,
+ 0xBA, 0x50, 0x14, 0xDB, 0xCB, 0x02, 0xA3, 0xC7, 0x20, 0xFA, 0x34, 0x6A, 0x46, 0x01, 0xF4, 0xF5,
+ 0xC7, 0xBB, 0x90, 0x61, 0xA3, 0x57, 0x0F, 0x7A, 0xF1, 0x6E, 0x8A, 0x9C, 0x1C, 0x92, 0xB6, 0xCA,
+ 0x4B, 0xE1, 0xBB, 0x4A, 0xF6, 0xBA, 0x49, 0xE9, 0x6E, 0xA9, 0x1F, 0x25, 0x98, 0x5A, 0x3C, 0x53,
+ 0x97, 0x72, 0xAD, 0x5B, 0x6A, 0xD6, 0xDD, 0x37, 0x15, 0x67, 0xD3, 0xAA, 0xD1, 0xE9, 0x6B, 0x37,
+ 0xD1, 0x1B, 0x3F, 0xB3, 0xDB, 0xDB, 0xEA, 0xBA, 0x9E, 0xB9, 0x7D, 0x14, 0xBA, 0xD5, 0xCD, 0xD6,
+ 0xAF, 0xA6, 0x5B, 0x6A, 0x92, 0xBE, 0xA8, 0xD1, 0xB5, 0xE5, 0xC5, 0xE4, 0xAA, 0x92, 0x5D, 0xCD,
+ 0x28, 0x45, 0x00, 0xA9, 0xDC, 0xFB, 0x70, 0x09, 0xE8, 0x4F, 0x4E, 0x7F, 0x45, 0xE2, 0xDE, 0x19,
+ 0x79, 0x7E, 0x03, 0x31, 0xCA, 0x68, 0xE2, 0x29, 0x4B, 0xEB, 0x34, 0x69, 0xD4, 0xA6, 0xA9, 0xF3,
+ 0x3F, 0x75, 0x4E, 0x2E, 0xD3, 0x8C, 0x60, 0xDF, 0x34, 0x6C, 0xEF, 0x65, 0x24, 0x9A, 0x6F, 0x45,
+ 0x76, 0xB9, 0x68, 0xD6, 0xA8, 0xF8, 0xA5, 0x4D, 0xAB, 0x46, 0x11, 0xB4, 0xAF, 0xA2, 0xDD, 0xC5,
+ 0x72, 0x2E, 0xCD, 0xA5, 0x65, 0xA5, 0x96, 0x8B, 0xA2, 0x3E, 0xA7, 0x96, 0x33, 0x83, 0x0A, 0x14,
+ 0xF9, 0xD0, 0xE0, 0x07, 0xE1, 0x14, 0xFD, 0xD1, 0x9E, 0x3B, 0x1F, 0xE8, 0x3D, 0xFF, 0x00, 0x9E,
+ 0x6A, 0xE5, 0x35, 0xF0, 0x39, 0x8C, 0x32, 0xE9, 0x54, 0x8D, 0xDD, 0x9A, 0x69, 0x4F, 0x95, 0x5F,
+ 0xAB, 0xBC, 0x39, 0xAD, 0xA7, 0x48, 0xB4, 0xBD, 0x36, 0xFD, 0x0B, 0x9F, 0xF7, 0x4D, 0xF2, 0xF4,
+ 0xB7, 0x4E, 0x8A, 0xD6, 0xB2, 0xEB, 0xA7, 0xDD, 0xF8, 0x7E, 0x69, 0x7C, 0x67, 0xF0, 0xE5, 0xFD,
+ 0xFF, 0x00, 0xC5, 0x4F, 0x0F, 0x5E, 0x27, 0x93, 0x6F, 0x6F, 0x65, 0x77, 0x33, 0x99, 0x27, 0x8A,
+ 0x62, 0x92, 0x32, 0x22, 0x6E, 0x89, 0x1D, 0x62, 0x61, 0xBC, 0x6D, 0xC7, 0x25, 0x47, 0x23, 0xF1,
+ 0xFD, 0xD7, 0x26, 0xE0, 0xAC, 0xCF, 0x17, 0x80, 0x78, 0x8A, 0x1E, 0xCD, 0xD3, 0x8C, 0x5B, 0x6D,
+ 0xAA, 0xCB, 0x48, 0x59, 0xC9, 0xC5, 0x7B, 0x1D, 0x55, 0xA4, 0xBB, 0x68, 0xBA, 0xDF, 0x5F, 0xCF,
+ 0xF0, 0x58, 0xAA, 0x14, 0x30, 0x79, 0xE5, 0x3A, 0xBA, 0x39, 0xDA, 0xCB, 0xD2, 0x2B, 0x4B, 0x2E,
+ 0xD7, 0xE8, 0xAC, 0xAC, 0xF5, 0x4B, 0x6F, 0xD1, 0xEF, 0x01, 0x69, 0xB3, 0xDC, 0x68, 0x1A, 0x6C,
+ 0x31, 0xF9, 0x6B, 0x88, 0x10, 0x2E, 0xE5, 0x70, 0x84, 0x01, 0xD0, 0x00, 0xA4, 0xFA, 0x0E, 0x71,
+ 0xDB, 0xD2, 0xBF, 0x21, 0xC7, 0xF0, 0xF5, 0x59, 0x66, 0x95, 0x29, 0x7B, 0x68, 0x45, 0xDE, 0xD7,
+ 0xE5, 0xAD, 0x65, 0x64, 0xDE, 0xCA, 0x93, 0x7E, 0x9A, 0x7C, 0x92, 0x3E, 0xC7, 0x24, 0xAA, 0xA9,
+ 0xE5, 0x34, 0x13, 0x8E, 0xAA, 0x11, 0xBA, 0x56, 0xD2, 0xD1, 0x4A, 0xFA, 0xB4, 0x95, 0xAD, 0x7F,
+ 0x93, 0xD3, 0x4B, 0x1D, 0x65, 0xD5, 0xBF, 0xD9, 0xE2, 0x52, 0xF2, 0xC4, 0xFE, 0x64, 0x41, 0xC8,
+ 0x8D, 0x24, 0x40, 0x8B, 0x91, 0xC1, 0x0C, 0x8B, 0xD0, 0x0E, 0x80, 0x11, 0x5F, 0x2F, 0x57, 0x0F,
+ 0x1C, 0x2C, 0xE3, 0x1E, 0x74, 0xD5, 0xB7, 0x8A, 0x92, 0xB6, 0x96, 0xB5, 0xA5, 0x18, 0xBB, 0xDE,
+ 0xC9, 0xD9, 0x35, 0xD8, 0xF5, 0x22, 0xA2, 0xAF, 0x14, 0xAC, 0xD6, 0x89, 0x69, 0xDB, 0xCB, 0x4F,
+ 0xCA, 0xD7, 0xEF, 0xA1, 0xF9, 0x7F, 0xF1, 0x56, 0xD0, 0xC9, 0xFB, 0x41, 0xF8, 0x41, 0x51, 0xA0,
+ 0x0D, 0x2D, 0xF5, 0xC8, 0xDD, 0x2C, 0x82, 0xDE, 0x35, 0xDD, 0x1A, 0xE7, 0x73, 0x1C, 0x05, 0x00,
+ 0x9E, 0xA4, 0xF4, 0xC7, 0xA1, 0xC7, 0xEA, 0xB8, 0x2C, 0x1D, 0x2F, 0xEC, 0xAA, 0x75, 0xA8, 0x4E,
+ 0x2D, 0x28, 0x45, 0x59, 0xF3, 0x27, 0xBF, 0x4F, 0x75, 0x2B, 0x5F, 0x4B, 0xDD, 0x5E, 0xDA, 0x24,
+ 0x91, 0xF0, 0x3C, 0xEE, 0x58, 0x0C, 0xEA, 0x92, 0xDF, 0xDA, 0x51, 0x4A, 0xF6, 0x4B, 0x74, 0x96,
+ 0xFA, 0x25, 0x65, 0xF8, 0x75, 0xD0, 0xFD, 0x34, 0xD2, 0xAD, 0xB6, 0xE9, 0xB0, 0x85, 0x16, 0x8A,
+ 0x12, 0x24, 0x8C, 0x2C, 0x37, 0x02, 0x68, 0xC6, 0xD4, 0x00, 0x04, 0x7E, 0x77, 0x0F, 0xBD, 0x8F,
+ 0xA7, 0xD2, 0xBF, 0x32, 0xCC, 0x30, 0xB2, 0x85, 0x7A, 0x93, 0x4A, 0x11, 0x82, 0xB7, 0xBA, 0xA4,
+ 0x9D, 0xAF, 0xD1, 0x27, 0x66, 0xDA, 0xD2, 0xFA, 0x69, 0xF9, 0x7D, 0xEE, 0x0A, 0x50, 0x78, 0x78,
+ 0x4A, 0xCD, 0x2B, 0x2D, 0x2D, 0xB6, 0xD6, 0x5A, 0x68, 0xAD, 0xBF, 0x4F, 0x97, 0x4F, 0x39, 0xF8,
+ 0x81, 0xFB, 0x54, 0xFE, 0xD0, 0x1F, 0xB3, 0x0D, 0x97, 0xF6, 0xCF, 0xC1, 0xCF, 0x18, 0xC9, 0x69,
+ 0xA4, 0x5E, 0xAA, 0xDA, 0xF8, 0x9F, 0xE1, 0xEF, 0x89, 0x74, 0xDB, 0x7F, 0x1B, 0xFC, 0x27, 0xF1,
+ 0xA5, 0xB3, 0x4A, 0xAA, 0xF6, 0xDA, 0xDF, 0x86, 0x2F, 0x52, 0x5D, 0x3E, 0xF1, 0x30, 0xC4, 0x0D,
+ 0xF1, 0x6F, 0x5C, 0xE5, 0x59, 0x48, 0x06, 0xBE, 0xA3, 0x86, 0xB8, 0x5E, 0xBE, 0x7D, 0x97, 0x56,
+ 0xF6, 0x74, 0xD5, 0xA3, 0x67, 0xCD, 0xCC, 0xA3, 0x64, 0x93, 0xEF, 0xB2, 0x76, 0x49, 0xD9, 0x35,
+ 0x74, 0x95, 0xBB, 0x79, 0xD2, 0xC5, 0x62, 0x69, 0xF1, 0x36, 0x0B, 0x03, 0x46, 0xEE, 0x35, 0x54,
+ 0xE3, 0xC8, 0x95, 0xEE, 0xD4, 0x79, 0xA3, 0x6B, 0x2B, 0x26, 0xAC, 0xEC, 0xD6, 0xB6, 0xBE, 0x96,
+ 0x3E, 0xBA, 0xF8, 0x1B, 0x2F, 0xEC, 0x6F, 0xF1, 0xFB, 0xC2, 0x16, 0x17, 0xCD, 0xE0, 0xEF, 0x0B,
+ 0xFE, 0xC6, 0x3F, 0x17, 0xF5, 0xA5, 0x3B, 0xDB, 0xC3, 0x56, 0xB7, 0x7A, 0x9F, 0xEC, 0x97, 0xE2,
+ 0x3B, 0xA7, 0x1F, 0xBB, 0x56, 0xD3, 0xD1, 0x65, 0xD5, 0x3C, 0x36, 0xD2, 0x33, 0x03, 0xBD, 0x24,
+ 0xBC, 0xB3, 0x43, 0xD5, 0x61, 0x4E, 0x47, 0x9B, 0x98, 0xC9, 0x60, 0x25, 0x3C, 0xBB, 0x13, 0x49,
+ 0x54, 0x51, 0x49, 0xC1, 0xC9, 0xBB, 0xC3, 0x4D, 0x95, 0x9A, 0xBE, 0xF6, 0xD3, 0xC9, 0xD9, 0xEC,
+ 0x2C, 0x9A, 0xA5, 0x3C, 0xD6, 0x32, 0xCC, 0xA3, 0x1F, 0x67, 0x56, 0x4D, 0xF3, 0xB4, 0x93, 0xBB,
+ 0x8B, 0xE5, 0xDD, 0xAD, 0x15, 0xA2, 0x9F, 0x2E, 0x89, 0x6C, 0xB5, 0x37, 0x75, 0x6F, 0x83, 0x3F,
+ 0xB4, 0xBF, 0xC2, 0x6F, 0x17, 0x69, 0x7F, 0x0E, 0xEE, 0x3C, 0x35, 0xA8, 0xCD, 0x37, 0x89, 0xB4,
+ 0xFB, 0x8D, 0x67, 0xC2, 0xD1, 0x59, 0xDD, 0x59, 0x78, 0xBF, 0xE1, 0x9F, 0xC4, 0x3B, 0x0B, 0x68,
+ 0x4B, 0xCD, 0xA8, 0x68, 0xF7, 0xE5, 0x9F, 0x4D, 0xBE, 0xB5, 0x11, 0x6E, 0x62, 0xF1, 0xB9, 0x2A,
+ 0x32, 0x18, 0x29, 0xE0, 0x78, 0x0A, 0x55, 0x22, 0x92, 0xA2, 0xF4, 0xBE, 0x89, 0xE8, 0x96, 0x96,
+ 0xD1, 0x6C, 0xB4, 0xF2, 0x5D, 0x3A, 0xA5, 0x6F, 0xA2, 0x97, 0x32, 0x82, 0x8C, 0x2D, 0x6D, 0x1B,
+ 0x56, 0x49, 0x69, 0x6B, 0x69, 0xB6, 0x96, 0x5B, 0xAB, 0x25, 0x6B, 0xE8, 0x7E, 0x75, 0x7E, 0xD7,
+ 0x9E, 0x12, 0xF8, 0x5B, 0xE1, 0x4F, 0x1F, 0x68, 0x36, 0x3F, 0x15, 0x7C, 0x21, 0xE2, 0x0F, 0x82,
+ 0xDF, 0x13, 0xEC, 0x75, 0x0B, 0x59, 0x57, 0xC4, 0x9F, 0x0E, 0x22, 0xB7, 0xD5, 0x74, 0x88, 0xCD,
+ 0xDA, 0xAB, 0xC6, 0xBA, 0x86, 0x86, 0xCF, 0xB9, 0x91, 0xD5, 0xC1, 0xDD, 0x6B, 0x73, 0x1E, 0xD5,
+ 0x23, 0xF7, 0x67, 0x6E, 0xD3, 0xF5, 0x79, 0x44, 0xB3, 0x3F, 0xA9, 0xA7, 0x4E, 0x29, 0xC2, 0x12,
+ 0x49, 0xA6, 0x9B, 0xB4, 0x1E, 0x97, 0xDF, 0x64, 0xF6, 0xF4, 0xB5, 0x92, 0xBB, 0x5F, 0x37, 0x38,
+ 0x65, 0x72, 0xC5, 0x62, 0x72, 0xCA, 0xB4, 0xB9, 0x5D, 0x5A, 0x32, 0x9C, 0x9C, 0x5D, 0xA0, 0x9C,
+ 0x76, 0x9B, 0x8D, 0xB4, 0x92, 0xBA, 0xB4, 0x93, 0x4D, 0xD9, 0xAD, 0x5D, 0xAD, 0xF4, 0x1D, 0xB7,
+ 0x83, 0x35, 0x6B, 0x7F, 0x0A, 0xE9, 0xFA, 0xD5, 0x95, 0xD6, 0x9F, 0xE2, 0xDF, 0x0F, 0x1B, 0x58,
+ 0x99, 0xBC, 0x47, 0xE1, 0xB7, 0x6B, 0xAB, 0x14, 0x47, 0x5C, 0x23, 0x5D, 0xC0, 0xCA, 0x27, 0xB5,
+ 0x62, 0x03, 0x7C, 0x93, 0x22, 0x1E, 0xB8, 0x24, 0x00, 0x4F, 0xCC, 0xE3, 0x30, 0xED, 0x62, 0x27,
+ 0x0A, 0x11, 0xB2, 0x6D, 0x24, 0xBF, 0x95, 0xDE, 0xDA, 0xA5, 0x6B, 0x6E, 0xB5, 0xB5, 0xBB, 0x76,
+ 0x37, 0xC1, 0x42, 0x73, 0xC1, 0x53, 0x97, 0x32, 0x9C, 0x6C, 0xBD, 0xE8, 0xEA, 0x9A, 0xB6, 0x92,
+ 0xDB, 0x4B, 0xDA, 0xE9, 0x34, 0x9A, 0x5D, 0x17, 0x5E, 0x5E, 0x5B, 0x2B, 0x08, 0xA7, 0xDD, 0x6F,
+ 0x67, 0x67, 0x13, 0xA4, 0x62, 0x03, 0x24, 0x36, 0xE8, 0x0B, 0x60, 0x92, 0x72, 0xEA, 0x06, 0x7E,
+ 0xF0, 0x18, 0xE9, 0xD7, 0xAE, 0x33, 0x5E, 0xB7, 0x13, 0x62, 0xA5, 0x2C, 0x5D, 0x2C, 0x1A, 0x93,
+ 0xB5, 0x1A, 0x54, 0xE9, 0xCA, 0xCD, 0xB8, 0xB9, 0x41, 0x59, 0xB5, 0x7E, 0x8F, 0x65, 0x6B, 0x26,
+ 0x96, 0x89, 0x2B, 0x25, 0xCB, 0x47, 0x0D, 0x46, 0x84, 0xA4, 0xE9, 0xC2, 0x29, 0xB7, 0xD2, 0x29,
+ 0x3B, 0x6E, 0x96, 0x89, 0x68, 0xBB, 0x6B, 0xFE, 0x5E, 0x45, 0xF1, 0x93, 0xC6, 0x31, 0x78, 0x2F,
+ 0xC1, 0x5A, 0x9D, 0xFE, 0xFD, 0xD7, 0xD7, 0x10, 0xB5, 0x8D, 0x8C, 0x23, 0x22, 0x59, 0x65, 0x95,
+ 0x48, 0x45, 0x53, 0x8E, 0xA4, 0xB2, 0xA8, 0x00, 0xF5, 0xF4, 0xE9, 0x59, 0x64, 0xB8, 0x65, 0x5F,
+ 0x11, 0xCF, 0x28, 0xFB, 0x90, 0x57, 0xE8, 0x96, 0x9B, 0x2B, 0x74, 0x5B, 0x7C, 0xB5, 0xB5, 0x8E,
+ 0x7C, 0xDE, 0x72, 0xF6, 0x10, 0xC2, 0xD1, 0x76, 0x9D, 0x57, 0xCA, 0x9E, 0xDC, 0xB1, 0xB7, 0xBF,
+ 0x2D, 0xAD, 0x68, 0xC5, 0x37, 0xD2, 0xCD, 0x2E, 0x87, 0x21, 0xF0, 0x4F, 0xC1, 0xEF, 0xE1, 0x4F,
+ 0x05, 0xDA, 0xDD, 0x6A, 0x08, 0x3F, 0xB6, 0xB5, 0xEC, 0xEB, 0x3A, 0xA4, 0xAC, 0x06, 0x5A, 0x59,
+ 0x8E, 0xE6, 0x04, 0x1E, 0x70, 0x37, 0x00, 0x3B, 0xFC, 0xB8, 0xED, 0x5E, 0x86, 0x67, 0x5F, 0xDA,
+ 0xE2, 0x3D, 0x94, 0x7E, 0x15, 0xA7, 0x6D, 0x7A, 0xF9, 0x69, 0xA2, 0xD3, 0x4B, 0x5B, 0x43, 0x93,
+ 0x2B, 0xA5, 0x1A, 0x8A, 0x78, 0xE8, 0x2B, 0x53, 0x92, 0x51, 0xA6, 0xB4, 0xF7, 0x69, 0x41, 0x38,
+ 0xC1, 0x76, 0x57, 0x5E, 0xF3, 0xB5, 0xB5, 0x6C, 0xE6, 0xAF, 0x2E, 0x63, 0xF1, 0xE7, 0xC6, 0x9F,
+ 0x0D, 0x78, 0x2E, 0xEA, 0x6D, 0x56, 0x6F, 0x03, 0xF8, 0x66, 0x44, 0xD7, 0x3C, 0x6D, 0xA6, 0xE8,
+ 0x97, 0x2B, 0x6B, 0x36, 0xA4, 0xD1, 0x12, 0x6D, 0x61, 0x66, 0x78, 0xE4, 0x87, 0x86, 0x1B, 0x87,
+ 0x98, 0x8C, 0x32, 0x99, 0xC0, 0xAF, 0x4F, 0x2D, 0xC3, 0x53, 0x85, 0x3A, 0x5C, 0xE9, 0x5D, 0xB5,
+ 0x2D, 0x5B, 0x4B, 0xB2, 0x57, 0x49, 0xBD, 0x77, 0x56, 0x4D, 0xAD, 0xBC, 0x97, 0x32, 0xC7, 0xC2,
+ 0x12, 0xAD, 0xCE, 0xA5, 0xC9, 0x51, 0xFB, 0x15, 0x6B, 0x2B, 0xC5, 0x6B, 0x55, 0xEA, 0x9E, 0x8D,
+ 0x72, 0xD3, 0xD9, 0x5E, 0xEE, 0xDA, 0xBB, 0x2E, 0x83, 0xE3, 0xDD, 0xA7, 0x86, 0xF4, 0x7F, 0x06,
+ 0xBF, 0x8F, 0x34, 0xDF, 0x0D, 0x4D, 0xA9, 0x6A, 0x9E, 0x17, 0x79, 0xB6, 0x8D, 0x7A, 0x67, 0xFB,
+ 0x25, 0xAD, 0xB3, 0xCA, 0xBF, 0xD9, 0xD7, 0x36, 0x62, 0x01, 0x08, 0xF3, 0xA1, 0x09, 0x36, 0xE2,
+ 0xE4, 0xC6, 0xDC, 0x81, 0x19, 0xC8, 0x03, 0xAB, 0x1B, 0x5A, 0xAD, 0x0C, 0x33, 0xA3, 0x42, 0x0E,
+ 0x3A, 0xF3, 0x24, 0x95, 0xA1, 0x68, 0xE9, 0x2E, 0x56, 0xF7, 0x4D, 0x75, 0x51, 0x8B, 0x4F, 0x95,
+ 0xEB, 0xB1, 0xD1, 0x95, 0x51, 0xC2, 0x57, 0xC7, 0x4B, 0x0D, 0x59, 0x47, 0xD9, 0xD6, 0x84, 0xE9,
+ 0x6A, 0xED, 0x66, 0xD3, 0xF6, 0x7A, 0x27, 0x6B, 0xDF, 0xDD, 0x56, 0xBB, 0x4D, 0xA4, 0xAD, 0x64,
+ 0x9F, 0x8E, 0x7C, 0x56, 0x1E, 0x1F, 0xF8, 0x8D, 0x6F, 0xF0, 0xA7, 0xC0, 0x56, 0xA5, 0xA6, 0x7F,
+ 0x11, 0xC2, 0xDE, 0x32, 0xF1, 0x5D, 0xFC, 0x69, 0x24, 0x73, 0x69, 0x56, 0x91, 0xC0, 0x3E, 0xCD,
+ 0x0D, 0xB0, 0x2C, 0xB9, 0x0C, 0xF2, 0x80, 0xDB, 0x90, 0x8C, 0x85, 0x28, 0xF8, 0xC9, 0x1E, 0x76,
+ 0x33, 0x03, 0x84, 0xC4, 0x61, 0x29, 0xE1, 0xE5, 0x2E, 0x6A, 0x52, 0x7C, 0xD3, 0x4A, 0xE9, 0x38,
+ 0x24, 0xDC, 0x53, 0x69, 0x24, 0xB5, 0xE5, 0x6D, 0x2E, 0xCD, 0x76, 0x44, 0xE5, 0x99, 0x9B, 0xCA,
+ 0xB0, 0x55, 0x73, 0x47, 0x4A, 0xD8, 0x9A, 0x6A, 0x34, 0xA3, 0xCC, 0xB4, 0xF6, 0x92, 0x92, 0x73,
+ 0x51, 0x49, 0xA7, 0xA4, 0x21, 0x27, 0xCC, 0xD2, 0x4D, 0x34, 0x93, 0xB5, 0xAD, 0x52, 0xC3, 0x5D,
+ 0xD2, 0x35, 0x4F, 0x87, 0x5E, 0x38, 0x8B, 0x40, 0xB7, 0xD4, 0x74, 0x0D, 0x33, 0xE1, 0xC8, 0x5D,
+ 0x02, 0x2B, 0x08, 0x3C, 0x4A, 0x9A, 0x7F, 0x8A, 0x4B, 0xB4, 0x89, 0x0D, 0xA5, 0xC5, 0x94, 0x92,
+ 0xF9, 0x87, 0xCD, 0x69, 0x64, 0x47, 0xD8, 0x9B, 0x88, 0x03, 0x82, 0x02, 0x8A, 0xEC, 0x82, 0xCB,
+ 0xB0, 0x70, 0x9D, 0x1A, 0xCA, 0x72, 0x8C, 0x53, 0xA4, 0x92, 0xB5, 0xF9, 0x9A, 0x51, 0x85, 0xEF,
+ 0x14, 0x9C, 0x75, 0x4F, 0x58, 0xAF, 0x73, 0x56, 0xF6, 0x14, 0xB2, 0xEF, 0xAF, 0x71, 0x4D, 0x2C,
+ 0xC3, 0x0A, 0xA3, 0x0C, 0x2B, 0x8C, 0x31, 0x57, 0x5A, 0x2B, 0x28, 0xB9, 0x4E, 0xD1, 0x6F, 0xAC,
+ 0xA2, 0xDC, 0xA3, 0xCC, 0x92, 0xBE, 0x8A, 0xEE, 0xC7, 0x45, 0xE3, 0x7F, 0x03, 0xEB, 0xBF, 0x0A,
+ 0xFC, 0x03, 0xF0, 0x7B, 0xC6, 0x50, 0x78, 0x87, 0xC4, 0xD6, 0x7E, 0x20, 0xF1, 0xBE, 0xB1, 0x6D,
+ 0xA2, 0xDF, 0x68, 0xF6, 0xFA, 0x8A, 0xFD, 0x83, 0xC5, 0x5A, 0x2C, 0xA4, 0xC6, 0x6F, 0x2F, 0x4A,
+ 0xB8, 0x9E, 0x59, 0x0D, 0xD3, 0x4A, 0x3E, 0x7C, 0x80, 0x49, 0x39, 0x3B, 0xB8, 0xE2, 0xAD, 0x08,
+ 0xD1, 0x9E, 0x17, 0xD8, 0x53, 0x4E, 0x34, 0x5C, 0x60, 0xDD, 0xF6, 0x83, 0x8F, 0x2F, 0x9D, 0xDA,
+ 0x92, 0x4F, 0xDE, 0x4F, 0x6B, 0xAE, 0x57, 0xAA, 0xC7, 0x2D, 0xA5, 0x5B, 0x1D, 0x95, 0x66, 0x52,
+ 0xC4, 0xD5, 0x71, 0xAD, 0x8E, 0x84, 0xEB, 0x53, 0x57, 0xB3, 0xF7, 0x7D, 0xE5, 0xCB, 0xAD, 0xEC,
+ 0xE3, 0x64, 0xD2, 0x56, 0xB6, 0x97, 0xE8, 0x72, 0x97, 0xBA, 0x67, 0x89, 0x75, 0x0F, 0x1D, 0xCF,
+ 0xA7, 0x69, 0x1F, 0x10, 0xA7, 0xD4, 0x7C, 0x0B, 0xF0, 0xC7, 0x52, 0x97, 0x51, 0xD4, 0xEC, 0x9E,
+ 0x45, 0xB7, 0xD0, 0xB4, 0xE9, 0xDB, 0x4F, 0x8D, 0xAF, 0x65, 0xD2, 0xC1, 0x20, 0xCD, 0x3E, 0x64,
+ 0x85, 0x70, 0xEA, 0x99, 0x65, 0x70, 0x31, 0xB2, 0xB6, 0xA9, 0x4B, 0x0E, 0xF8, 0x8D, 0xE3, 0xA5,
+ 0x89, 0xB6, 0x1A, 0x12, 0x54, 0x5B, 0x4B, 0xDD, 0x92, 0x94, 0x3D, 0xEB, 0x45, 0xA4, 0xF9, 0x93,
+ 0x71, 0x5A, 0x49, 0x2B, 0x26, 0xBD, 0x7A, 0x28, 0x61, 0xAA, 0x61, 0xF8, 0x62, 0x3C, 0x2D, 0xEC,
+ 0x5F, 0xD6, 0x55, 0x27, 0x89, 0x4D, 0x5A, 0xF1, 0xB4, 0xD7, 0x2E, 0x8D, 0x26, 0xA3, 0x64, 0xEC,
+ 0x97, 0x4B, 0x3B, 0x7B, 0xC7, 0x90, 0x6B, 0xDF, 0x12, 0x7C, 0x65, 0x67, 0x2F, 0x8D, 0x3E, 0x25,
+ 0xE9, 0xDE, 0x29, 0xF1, 0x44, 0x1E, 0x3B, 0xF1, 0xF7, 0x8A, 0xDF, 0xC3, 0x9E, 0x1F, 0xD5, 0x46,
+ 0x82, 0xD7, 0xF1, 0x78, 0x8B, 0x4D, 0xB5, 0x1E, 0x4D, 0xC2, 0xDB, 0xEA, 0x12, 0x02, 0xB1, 0xB8,
+ 0x72, 0xB9, 0x58, 0x81, 0x24, 0x90, 0x32, 0x31, 0x5F, 0x35, 0x9D, 0x4D, 0x61, 0xE8, 0xCF, 0x19,
+ 0x42, 0xBD, 0xA5, 0x56, 0xB7, 0xB3, 0xA7, 0x69, 0xDA, 0x51, 0x8D, 0x3B, 0x41, 0xB7, 0x1D, 0x13,
+ 0x4D, 0xA6, 0xEE, 0xF6, 0xBA, 0xD8, 0xFB, 0xFC, 0x8E, 0x86, 0x61, 0x18, 0x61, 0xDE, 0x2E, 0x3F,
+ 0xB9, 0xF6, 0x4A, 0x53, 0x52, 0x8A, 0x8A, 0x95, 0x49, 0xFB, 0xD7, 0x69, 0x6F, 0xCA, 0xB9, 0x52,
+ 0x8B, 0xD1, 0x2D, 0xDB, 0xD8, 0xF3, 0xCF, 0x0C, 0x4D, 0xE3, 0xEF, 0x10, 0x69, 0xAD, 0xFB, 0x3F,
+ 0xFF, 0x00, 0xC2, 0x47, 0xA3, 0x68, 0x9E, 0x0E, 0xB8, 0xF1, 0x18, 0xF8, 0x85, 0xE2, 0x1B, 0x7D,
+ 0x4A, 0xCA, 0x3D, 0x3C, 0x58, 0xEA, 0x16, 0xD6, 0x8D, 0x1C, 0x93, 0x5C, 0xCD, 0x2C, 0x71, 0xDC,
+ 0x34, 0xD1, 0xC0, 0xCE, 0x8B, 0x0E, 0xF0, 0xAC, 0xC1, 0x07, 0x7D, 0xC3, 0xE6, 0x2B, 0xE5, 0xD8,
+ 0x88, 0x4D, 0x65, 0x14, 0xF1, 0x2A, 0x74, 0x6D, 0x19, 0xBE, 0x5E, 0x55, 0x14, 0xDF, 0xBA, 0xDC,
+ 0x92, 0x92, 0x5C, 0xD1, 0x82, 0x6E, 0xF6, 0xBB, 0xD3, 0x99, 0x2E, 0x9E, 0xE3, 0xC5, 0x61, 0x1C,
+ 0x63, 0x98, 0x4E, 0x16, 0x9F, 0xC2, 0xA5, 0x65, 0x77, 0x1D, 0x25, 0xA5, 0xAE, 0xB9, 0x7A, 0xDB,
+ 0xA2, 0x4E, 0xCB, 0x44, 0x64, 0x7C, 0x51, 0xF8, 0xA1, 0xE2, 0xFF, 0x00, 0x18, 0x6A, 0x57, 0xB3,
+ 0xEB, 0xDE, 0x2C, 0x3E, 0x26, 0x9A, 0xF3, 0x4E, 0xB5, 0xD0, 0x56, 0xFA, 0x3D, 0x1A, 0xDB, 0x45,
+ 0x82, 0x7D, 0x33, 0x4F, 0x8C, 0x47, 0xA7, 0xA9, 0xB5, 0x8D, 0x17, 0xC9, 0x72, 0x88, 0x8E, 0x40,
+ 0xE4, 0xE7, 0xE6, 0x27, 0x15, 0xEC, 0x67, 0x38, 0x99, 0x64, 0xDC, 0x3F, 0x2C, 0xB3, 0x0D, 0x56,
+ 0xA2, 0xAD, 0x5A, 0x56, 0xA8, 0xAC, 0xD5, 0x35, 0x4D, 0x26, 0xE3, 0x14, 0xAE, 0xA2, 0xD4, 0x9A,
+ 0x53, 0x8B, 0xE5, 0xBD, 0x9B, 0xBD, 0xB4, 0x3B, 0x70, 0xB3, 0xC2, 0xD7, 0x85, 0xA3, 0x09, 0x5E,
+ 0x32, 0x96, 0xFA, 0x45, 0xED, 0xAA, 0xB5, 0xA4, 0xEC, 0xD7, 0x5F, 0x77, 0x4D, 0xAF, 0x73, 0xC4,
+ 0xEB, 0xF3, 0x83, 0xB8, 0x28, 0x00, 0xA0, 0x0D, 0x2D, 0x3E, 0xCC, 0xCC, 0xEA, 0xC4, 0x61, 0x06,
+ 0x30, 0x00, 0xED, 0x8E, 0x98, 0xFC, 0xAB, 0xF5, 0xFF, 0x00, 0x0C, 0x38, 0x22, 0xB6, 0x77, 0x8D,
+ 0x86, 0x3E, 0xBC, 0x3F, 0x74, 0x9E, 0x9B, 0xDE, 0xD6, 0x69, 0xDD, 0x5A, 0xD6, 0x7A, 0x59, 0xEA,
+ 0x9F, 0x63, 0xCD, 0xC6, 0xE2, 0x55, 0x38, 0xF2, 0x44, 0xEF, 0x2D, 0x2D, 0x44, 0x30, 0xAF, 0x0A,
+ 0x00, 0x51, 0x81, 0xD3, 0x00, 0x0E, 0x9D, 0x3D, 0x85, 0x7F, 0xA3, 0x3C, 0x19, 0xC2, 0x94, 0xB2,
+ 0x4C, 0x96, 0x9C, 0xDA, 0x49, 0x72, 0xAD, 0x2F, 0x6D, 0x3B, 0x3D, 0x17, 0xF9, 0x5F, 0x6D, 0x34,
+ 0x3E, 0x4A, 0xBD, 0x67, 0x52, 0x6E, 0xDB, 0x7F, 0x5B, 0x0D, 0x5B, 0xB8, 0x1E, 0xE3, 0xEC, 0x8A,
+ 0x58, 0xCD, 0x8C, 0x85, 0x08, 0x42, 0xED, 0x1D, 0xC1, 0xF4, 0x18, 0x15, 0xE7, 0x61, 0x78, 0xD3,
+ 0x20, 0xC6, 0x71, 0x43, 0xE0, 0xEC, 0x2D, 0x49, 0xCB, 0x1E, 0x95, 0xD4, 0x55, 0x39, 0xF2, 0xB8,
+ 0x68, 0xB9, 0xD4, 0xAD, 0x6E, 0x58, 0xBD, 0x1B, 0x76, 0x69, 0xD9, 0x5B, 0x44, 0x5B, 0xC3, 0xD5,
+ 0x8D, 0x05, 0x5D, 0xC5, 0x72, 0x7A, 0xAF, 0xBA, 0xC2, 0xDD, 0x5B, 0x19, 0x51, 0x36, 0x90, 0x92,
+ 0xC0, 0xDB, 0xAD, 0x88, 0x05, 0x7E, 0x60, 0x39, 0x03, 0x8E, 0x84, 0x0C, 0x1A, 0xDB, 0x8C, 0xB8,
+ 0x67, 0x11, 0x9D, 0x60, 0x29, 0xCF, 0x05, 0x35, 0x1C, 0x7E, 0x12, 0x4E, 0x78, 0x49, 0x3B, 0xC5,
+ 0x7B, 0x5B, 0x5D, 0xA4, 0xF9, 0x79, 0x9C, 0x26, 0x93, 0x84, 0xDA, 0x4B, 0xDD, 0x6D, 0x59, 0xDD,
+ 0x35, 0x38, 0x7A, 0xCA, 0x93, 0x69, 0xAF, 0x71, 0xA4, 0xA4, 0xBC, 0xBF, 0x2D, 0x37, 0x5F, 0xF0,
+ 0x09, 0xED, 0xC2, 0xDC, 0x5B, 0x3D, 0xCC, 0x40, 0xF9, 0x51, 0x5C, 0x7D, 0x9D, 0xD2, 0x45, 0x54,
+ 0x96, 0x16, 0x2A, 0x70, 0x85, 0x41, 0x38, 0xE1, 0x73, 0xC6, 0x6B, 0x5E, 0x0C, 0xCD, 0xE8, 0xF1,
+ 0x4E, 0x4B, 0xF5, 0xCA, 0xA9, 0x47, 0x13, 0x4E, 0x6E, 0x15, 0xE9, 0x34, 0x93, 0xA1, 0x56, 0x3A,
+ 0x4E, 0x92, 0x4D, 0xBF, 0x72, 0xEF, 0x9A, 0x0D, 0xFC, 0x51, 0xE5, 0x6D, 0x2D, 0x82, 0xA6, 0x1E,
+ 0xB5, 0x18, 0x2A, 0x92, 0x4B, 0x97, 0x44, 0x9A, 0xD9, 0xDD, 0x5D, 0x5B, 0x44, 0xF6, 0x5D, 0x95,
+ 0x85, 0xDA, 0x00, 0xC7, 0x1C, 0x0E, 0x30, 0xA0, 0x0E, 0x07, 0x61, 0xF9, 0x57, 0xD2, 0x4B, 0x09,
+ 0x04, 0x9C, 0x16, 0xF6, 0xD3, 0xDD, 0x56, 0xEC, 0xAF, 0x65, 0x75, 0xD2, 0xDF, 0x86, 0x9A, 0x18,
+ 0x29, 0x2D, 0x34, 0xD0, 0x85, 0x94, 0xE0, 0x01, 0x80, 0x31, 0xC7, 0x18, 0xE9, 0xED, 0x5E, 0x16,
+ 0x27, 0x0D, 0x38, 0xB5, 0x1D, 0x2D, 0x6F, 0xCB, 0xCA, 0xC9, 0xA5, 0xD1, 0x5D, 0x2D, 0x8D, 0x15,
+ 0xAC, 0xAC, 0x57, 0x65, 0xE3, 0x6F, 0x03, 0x18, 0x03, 0x18, 0xC7, 0x03, 0x80, 0x05, 0x78, 0x38,
+ 0xAC, 0x3C, 0xE4, 0xDD, 0x9A, 0xD2, 0xDF, 0x87, 0xF5, 0xFE, 0x66, 0xB0, 0x69, 0x25, 0x1B, 0x11,
+ 0xAA, 0x80, 0x55, 0x5F, 0x21, 0x08, 0xC1, 0xDA, 0x07, 0x1C, 0x71, 0x81, 0x5E, 0x5C, 0x28, 0x51,
+ 0xA9, 0x5E, 0x34, 0xF1, 0xB7, 0xFA, 0xBB, 0x8B, 0x52, 0xE5, 0xB3, 0x69, 0xE9, 0x6D, 0x2E, 0xBF,
+ 0x35, 0xE5, 0xD8, 0xBD, 0x54, 0x7D, 0xD5, 0xAE, 0x96, 0x3B, 0x1F, 0x82, 0xB2, 0xDB, 0x78, 0x77,
+ 0xE3, 0x67, 0xC3, 0xAD, 0x4A, 0xE8, 0xC6, 0xB6, 0x2B, 0xE2, 0x58, 0x11, 0xDD, 0xC1, 0x2B, 0x1F,
+ 0x9A, 0x0C, 0x6A, 0x48, 0xED, 0xCB, 0xAE, 0x2B, 0xF8, 0xB3, 0xC5, 0x4E, 0x00, 0xAD, 0xC2, 0x3C,
+ 0x4F, 0x2C, 0xC3, 0x0B, 0x14, 0xF0, 0x75, 0x6E, 0xD3, 0xBB, 0xBA, 0x6E, 0xEB, 0x54, 0xD2, 0x4A,
+ 0xF7, 0x56, 0x49, 0xBB, 0xED, 0xA5, 0xCF, 0x6E, 0x96, 0x25, 0x62, 0x70, 0x2E, 0x9B, 0xF8, 0x95,
+ 0xB6, 0xF2, 0xB7, 0xF9, 0x7D, 0xC7, 0xF5, 0xEF, 0xFB, 0x3B, 0x5E, 0xDB, 0xDC, 0x78, 0x5A, 0xE1,
+ 0x22, 0xC1, 0x92, 0x29, 0x99, 0x99, 0x55, 0x81, 0x21, 0x5D, 0x03, 0x29, 0x1F, 0x86, 0xEF, 0xCA,
+ 0xAB, 0x1A, 0xD5, 0x4A, 0x14, 0x2A, 0x53, 0xB7, 0x27, 0x2C, 0x52, 0xB7, 0x6D, 0x7F, 0xCF, 0xA2,
+ 0xED, 0xB1, 0xF1, 0x39, 0x74, 0x3D, 0x9E, 0x26, 0xB5, 0x1B, 0x6A, 0x9E, 0xD6, 0xE9, 0xAB, 0xD5,
+ 0x2B, 0x77, 0xD3, 0xAF, 0x4B, 0x1C, 0x05, 0x8E, 0xA9, 0x6D, 0xAB, 0xFE, 0xD1, 0xB7, 0xF6, 0xDA,
+ 0xEC, 0xAB, 0x6E, 0xBA, 0x26, 0x99, 0xFF, 0x00, 0x12, 0x98, 0x6E, 0x58, 0x2C, 0x79, 0x60, 0x7C,
+ 0xD7, 0x4C, 0xF1, 0xC6, 0x3A, 0x8C, 0x71, 0xF8, 0xE3, 0xE9, 0xEA, 0x52, 0x95, 0x0E, 0x18, 0x82,
+ 0xC3, 0xC5, 0x5E, 0x56, 0x6E, 0xC9, 0x3D, 0xDB, 0x4B, 0x6D, 0x74, 0xB2, 0x5D, 0x12, 0xD2, 0xD6,
+ 0xE6, 0x57, 0xF0, 0x29, 0xA5, 0x57, 0x3B, 0x75, 0x6B, 0xA4, 0xA2, 0x9D, 0x97, 0x6D, 0x6D, 0x65,
+ 0xAE, 0x8A, 0xED, 0xDB, 0x6D, 0xD2, 0xE8, 0x8F, 0x55, 0xF8, 0xED, 0xE3, 0x99, 0xF4, 0x5F, 0x01,
+ 0xEB, 0x3F, 0xF0, 0x8E, 0xA7, 0xDA, 0x6E, 0xBE, 0xCA, 0xF0, 0x97, 0x83, 0x2B, 0x14, 0x4B, 0xE5,
+ 0x9D, 0xCF, 0xB8, 0x60, 0x00, 0x14, 0x37, 0x42, 0x0E, 0x07, 0xD3, 0x3E, 0x37, 0x0D, 0xE5, 0xF1,
+ 0xAB, 0x8F, 0x8C, 0xB1, 0x09, 0x5A, 0x29, 0xB4, 0x9D, 0xB5, 0x6A, 0xD6, 0x8B, 0xD1, 0xEE, 0xED,
+ 0x75, 0x67, 0xA2, 0x6A, 0xD6, 0xBD, 0xBD, 0x6C, 0xF7, 0x1F, 0x1F, 0xAA, 0x2A, 0x34, 0x5F, 0xBA,
+ 0xDA, 0x4D, 0xAD, 0x92, 0xBA, 0x4E, 0xDE, 0x89, 0xBB, 0x5F, 0x7B, 0x58, 0xCF, 0xF8, 0x09, 0x06,
+ 0x9F, 0xE1, 0xCF, 0x85, 0xDA, 0x4D, 0xDC, 0xD7, 0x11, 0xBC, 0xF7, 0x96, 0xBF, 0x6D, 0xB8, 0x55,
+ 0x3F, 0xBC, 0x92, 0x59, 0x57, 0x73, 0x80, 0x3A, 0x82, 0x49, 0x1F, 0x87, 0xD2, 0xAB, 0x88, 0x1D,
+ 0x7C, 0x4E, 0x69, 0x2A, 0x7C, 0xBB, 0x5A, 0x2A, 0xC9, 0x6D, 0x1B, 0x25, 0xA2, 0xD3, 0x4F, 0xF2,
+ 0x23, 0x24, 0x74, 0x70, 0xB8, 0x09, 0x55, 0x6D, 0x5D, 0xBB, 0x25, 0xBB, 0x69, 0x6C, 0xB4, 0xF2,
+ 0xB6, 0xB6, 0x49, 0x2D, 0x16, 0x8B, 0x5D, 0x0D, 0x4E, 0x64, 0xB0, 0xD0, 0x7C, 0x4F, 0xE2, 0x6D,
+ 0x61, 0xD2, 0xC9, 0xB5, 0x0B, 0x49, 0x2D, 0xED, 0x55, 0xBE, 0x51, 0xE5, 0x91, 0x84, 0x61, 0x81,
+ 0xC8, 0xEA, 0x40, 0xF4, 0x1D, 0x38, 0xC9, 0xF3, 0xF1, 0xD2, 0xA7, 0x0C, 0x2C, 0x70, 0xB4, 0xBE,
+ 0x18, 0xA6, 0xDB, 0x5A, 0xDB, 0x7B, 0xA5, 0xB6, 0x89, 0x25, 0xB5, 0x93, 0xB2, 0xB3, 0x6D, 0xA4,
+ 0xBB, 0x32, 0xE8, 0xC7, 0xEB, 0x2F, 0x17, 0x57, 0xAB, 0xD1, 0x77, 0x49, 0xDD, 0xEB, 0x64, 0xAD,
+ 0x7D, 0x2F, 0x6B, 0x7A, 0xD9, 0x5B, 0xF9, 0xB6, 0xF0, 0x4E, 0xB1, 0x69, 0xAE, 0x7F, 0xC1, 0x57,
+ 0xFF, 0x00, 0x67, 0xEB, 0xDB, 0x22, 0x8D, 0x6E, 0x9F, 0xB5, 0xAF, 0xC3, 0x6B, 0x30, 0xD1, 0x8C,
+ 0x29, 0x68, 0x3C, 0x41, 0xA5, 0xA4, 0x98, 0xFA, 0x32, 0xB0, 0xFA, 0x01, 0x5F, 0x93, 0xCE, 0x7C,
+ 0xD9, 0xDD, 0x08, 0xD9, 0x69, 0x38, 0x6C, 0xD3, 0xDE, 0x5C, 0xDD, 0x3B, 0x5E, 0xD6, 0xF2, 0x3F,
+ 0x40, 0xA3, 0x15, 0x1C, 0xB2, 0x7F, 0xE1, 0x97, 0x4B, 0x2D, 0xAC, 0xAD, 0xE5, 0x64, 0xAC, 0x7F,
+ 0x70, 0xF5, 0xFA, 0x09, 0xF3, 0x41, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFC, 0x57, 0xFF, 0x00, 0xC1,
+ 0x6A, 0x13, 0x3F, 0xB7, 0xF7, 0xC4, 0xA3, 0x81, 0x81, 0xE0, 0xEF, 0x0A, 0x0C, 0x60, 0x60, 0x81,
+ 0xE1, 0xDB, 0x4E, 0x31, 0x51, 0x43, 0x06, 0xAB, 0xE1, 0xF1, 0x13, 0x49, 0x59, 0x4E, 0xD6, 0x7B,
+ 0x35, 0xEC, 0xE9, 0x3B, 0x5B, 0xFE, 0x07, 0x6D, 0xB4, 0x3D, 0xBC, 0x13, 0x51, 0xA1, 0x05, 0xD2,
+ 0xCF, 0xF3, 0x67, 0xE5, 0xA6, 0x8F, 0xE2, 0x3F, 0x11, 0xF8, 0x5C, 0xDC, 0xB6, 0x81, 0xAC, 0x5F,
+ 0xE9, 0x49, 0x78, 0xAA, 0xB7, 0x71, 0x59, 0xCE, 0xD1, 0x41, 0x72, 0x10, 0xE5, 0x04, 0x91, 0x7D,
+ 0xC6, 0xDA, 0x49, 0xC1, 0x20, 0xE3, 0x9C, 0x63, 0x35, 0xF2, 0x35, 0xF0, 0x99, 0xAE, 0x49, 0x5E,
+ 0x59, 0x8E, 0x5F, 0x2E, 0x58, 0x6A, 0xEC, 0x92, 0x56, 0x4F, 0xA7, 0x2B, 0x5C, 0xAD, 0x74, 0xD3,
+ 0xA7, 0x44, 0x8D, 0xF1, 0x78, 0x0C, 0xBB, 0x36, 0xC3, 0xAC, 0x26, 0x61, 0x49, 0x4E, 0x1A, 0x68,
+ 0xFC, 0xB6, 0xD5, 0x59, 0xAF, 0xC8, 0xFA, 0x7E, 0x1F, 0xDB, 0x7B, 0xE3, 0x47, 0xFC, 0x22, 0x71,
+ 0x78, 0x4A, 0xEE, 0xEB, 0x47, 0xB9, 0x86, 0x2B, 0x61, 0x68, 0x35, 0x56, 0xB0, 0x23, 0x50, 0xD8,
+ 0x17, 0x01, 0x8A, 0x86, 0x11, 0x96, 0xC7, 0x70, 0xA3, 0xA0, 0xE9, 0x8A, 0x30, 0x3C, 0x45, 0x81,
+ 0x85, 0x78, 0xD6, 0xC6, 0xE1, 0x17, 0x36, 0x97, 0x70, 0x6D, 0x2F, 0x5E, 0x47, 0x75, 0xF2, 0xBA,
+ 0x8F, 0x68, 0xA5, 0x64, 0x79, 0x15, 0xB8, 0x5A, 0x53, 0xA4, 0xF0, 0xD4, 0xB1, 0x73, 0x54, 0x76,
+ 0x51, 0x7C, 0xAD, 0xA5, 0xFC, 0xAA, 0x5C, 0xB7, 0x49, 0x6C, 0x9D, 0x9C, 0x92, 0xFB, 0x4C, 0xFD,
+ 0x1C, 0xF8, 0x45, 0xFB, 0x5E, 0x7C, 0x0F, 0x4F, 0x84, 0xFA, 0x76, 0x8B, 0x7B, 0xF1, 0x0E, 0xD7,
+ 0x4A, 0xF1, 0x3D, 0x9E, 0x8C, 0x2D, 0xEE, 0x6D, 0x75, 0xFB, 0x19, 0x74, 0xD7, 0x69, 0xF6, 0x00,
+ 0xD8, 0x91, 0x97, 0xCB, 0x60, 0x4A, 0xB1, 0xC8, 0x73, 0xD4, 0x7B, 0x01, 0x38, 0xAC, 0x5E, 0x0F,
+ 0x1D, 0x9A, 0xBA, 0xB4, 0x26, 0x95, 0x39, 0x49, 0x5A, 0xEF, 0x95, 0x25, 0xBF, 0x5D, 0x15, 0xBE,
+ 0xE5, 0xB2, 0xD8, 0xE6, 0xC1, 0x60, 0x31, 0xF9, 0x5E, 0x49, 0x1A, 0x15, 0x20, 0xDD, 0x48, 0x45,
+ 0xAD, 0x13, 0x9D, 0xDF, 0xD9, 0xB2, 0x5A, 0xBE, 0x9D, 0x13, 0xB2, 0xBB, 0x3F, 0x3B, 0xFE, 0x26,
+ 0xFE, 0xD6, 0x3F, 0x12, 0xBC, 0x44, 0xFA, 0xA7, 0x85, 0xE1, 0xD7, 0x34, 0x75, 0xD0, 0x04, 0x86,
+ 0xDC, 0x5C, 0x68, 0x31, 0x18, 0x86, 0xA1, 0x0F, 0x50, 0x4C, 0x9B, 0xDB, 0x83, 0x91, 0x90, 0x0E,
+ 0x32, 0x3D, 0x00, 0xAF, 0xD4, 0xB8, 0x7F, 0x31, 0xE1, 0xBC, 0x9F, 0x1A, 0xAA, 0x42, 0x74, 0xEA,
+ 0x46, 0xCF, 0x69, 0xC5, 0xC9, 0x74, 0xD1, 0xA9, 0x2B, 0x5B, 0xD3, 0xB7, 0x91, 0xE6, 0xE0, 0xF2,
+ 0x1A, 0xB9, 0xA6, 0x06, 0x8D, 0x6C, 0xD2, 0x55, 0x15, 0xD5, 0xDD, 0x27, 0x15, 0x08, 0xDF, 0xFB,
+ 0xC9, 0x25, 0x26, 0xBA, 0xA8, 0xB7, 0x6B, 0x5A, 0xEA, 0xE8, 0xFB, 0x6F, 0xFE, 0x09, 0xE5, 0xFB,
+ 0x71, 0x5C, 0x78, 0x1E, 0x3B, 0x9F, 0xD9, 0xF3, 0xE2, 0x96, 0xAE, 0x8F, 0xF0, 0xE7, 0xC6, 0x5B,
+ 0xEC, 0xFC, 0x37, 0xAC, 0x6A, 0x72, 0x41, 0x1E, 0x9F, 0xE1, 0x6B, 0xAB, 0x95, 0x0B, 0x25, 0xBD,
+ 0xD4, 0xAE, 0x54, 0xA5, 0xAC, 0xA1, 0x54, 0x6E, 0x42, 0x5D, 0x19, 0x50, 0x26, 0x37, 0x57, 0xEB,
+ 0xD9, 0xAD, 0x0A, 0x59, 0x9E, 0x1A, 0x86, 0x69, 0x93, 0x61, 0xD5, 0x47, 0xA2, 0x94, 0x14, 0xAF,
+ 0x4E, 0x31, 0x76, 0x76, 0x94, 0x55, 0xD4, 0x93, 0x69, 0x6A, 0xEE, 0xA3, 0x76, 0xEC, 0xEE, 0x63,
+ 0x98, 0x64, 0xB5, 0xE9, 0xFE, 0xF3, 0x2F, 0xAA, 0xE9, 0xB5, 0x6B, 0xA4, 0xF5, 0xD3, 0x4F, 0x71,
+ 0xB4, 0xF9, 0x5D, 0xB7, 0xB5, 0xAE, 0x95, 0xAF, 0xA2, 0x47, 0x29, 0xFB, 0x5C, 0x58, 0xFC, 0x70,
+ 0xF8, 0x2B, 0xE3, 0x2D, 0x53, 0xC3, 0x17, 0xBA, 0xC9, 0xBD, 0xF0, 0x0F, 0x8E, 0x21, 0x96, 0xF3,
+ 0xC1, 0xFE, 0x2B, 0x48, 0x5A, 0x18, 0x35, 0x0B, 0x47, 0x53, 0xE6, 0x59, 0xCB, 0x70, 0x42, 0xC4,
+ 0x97, 0x11, 0x82, 0x55, 0xA3, 0x19, 0x60, 0x3C, 0xB2, 0x79, 0x3C, 0x7F, 0x56, 0xF8, 0x39, 0x9B,
+ 0x70, 0x7F, 0x11, 0xE0, 0x29, 0xE1, 0xEB, 0xD0, 0x70, 0xC7, 0xD0, 0x8A, 0x4A, 0x2D, 0xA4, 0xAF,
+ 0x0E, 0x55, 0x75, 0x14, 0xDC, 0x9A, 0x49, 0xDA, 0xEA, 0xE9, 0x3B, 0xC6, 0xD6, 0x52, 0x3E, 0x46,
+ 0x9E, 0x4F, 0x85, 0xAD, 0x07, 0x5E, 0xBC, 0xEA, 0x49, 0x42, 0x49, 0x4A, 0x37, 0xBC, 0x5B, 0x4D,
+ 0x35, 0x65, 0x14, 0xEE, 0x96, 0x97, 0x49, 0xD9, 0xA5, 0xAA, 0x4A, 0xE9, 0x78, 0x0F, 0xC0, 0x9F,
+ 0x8D, 0xDA, 0x9F, 0xC3, 0x9D, 0x4A, 0x1D, 0x27, 0x54, 0x9A, 0x75, 0xF0, 0x3E, 0xAC, 0x1B, 0x4D,
+ 0xD6, 0x11, 0x11, 0xA4, 0xFB, 0x11, 0x96, 0x3F, 0xDD, 0x5C, 0x42, 0x72, 0x0A, 0x6C, 0x71, 0x1B,
+ 0xB0, 0x5C, 0x92, 0x37, 0xED, 0xC6, 0x40, 0x1F, 0xA2, 0xF1, 0xA7, 0x07, 0xAC, 0xFB, 0x29, 0xAB,
+ 0x89, 0xC3, 0x5D, 0x62, 0xD4, 0x95, 0xB9, 0x6D, 0x05, 0x28, 0xAB, 0x3F, 0x3B, 0x38, 0xE9, 0xEF,
+ 0x24, 0xBA, 0x5D, 0xDD, 0x24, 0xFE, 0x8B, 0x27, 0xCB, 0xB2, 0xAA, 0x1C, 0x43, 0x4F, 0x34, 0xC4,
+ 0x49, 0xA9, 0x24, 0xD5, 0x93, 0x4A, 0x2D, 0x35, 0xCA, 0xD4, 0xD2, 0xB2, 0x69, 0xC5, 0xCA, 0x0B,
+ 0x58, 0xA4, 0x9A, 0xE6, 0xBA, 0x4E, 0xFF, 0x00, 0x44, 0xEA, 0xFE, 0x1F, 0xD6, 0xB5, 0xAB, 0x39,
+ 0x3C, 0x15, 0x03, 0xCB, 0xE2, 0x45, 0xBB, 0xBD, 0x86, 0xDB, 0x48, 0x83, 0x46, 0xD3, 0xA1, 0xBA,
+ 0x9B, 0xC4, 0x91, 0xDE, 0xB1, 0x16, 0x33, 0xD9, 0xDB, 0xA4, 0x66, 0x49, 0xAE, 0xD8, 0x90, 0xA6,
+ 0x14, 0x04, 0xE3, 0x7F, 0x3C, 0x82, 0xBF, 0x81, 0x67, 0xB9, 0x27, 0x0F, 0xF1, 0x64, 0x23, 0x53,
+ 0x88, 0xE8, 0x5A, 0xBE, 0x19, 0x27, 0x26, 0xE5, 0x38, 0xB8, 0xC5, 0x5A, 0xD5, 0x3D, 0xD9, 0x59,
+ 0x28, 0x36, 0xB9, 0xE4, 0xD2, 0xE9, 0xCB, 0xA6, 0x8F, 0xF5, 0xEE, 0x17, 0xC5, 0x65, 0xDC, 0x25,
+ 0x98, 0xC7, 0x01, 0x86, 0x9C, 0x5E, 0x51, 0x8D, 0x8C, 0xD6, 0x12, 0x52, 0x9C, 0xA7, 0x1A, 0x35,
+ 0x54, 0x3F, 0x7D, 0x86, 0xAB, 0x27, 0x2B, 0x46, 0x9C, 0x93, 0xE7, 0xA0, 0xDB, 0xD5, 0xFB, 0xBB,
+ 0xE8, 0xBF, 0x4D, 0xF4, 0xEF, 0x02, 0x78, 0x33, 0xF6, 0x33, 0xF0, 0x96, 0x9F, 0xAD, 0xFE, 0xD2,
+ 0xB6, 0xB3, 0xFC, 0x41, 0xF8, 0xFD, 0xA9, 0x68, 0x16, 0x5A, 0xFF, 0x00, 0x81, 0xBF, 0x64, 0x9F,
+ 0x0F, 0xEB, 0xE2, 0x6F, 0x0E, 0xF8, 0x11, 0x9A, 0xD5, 0x4D, 0xBD, 0xEF, 0xC5, 0x3B, 0xFB, 0x73,
+ 0x14, 0xD6, 0xEC, 0x42, 0x89, 0x17, 0x4B, 0xB2, 0x91, 0xA4, 0x7C, 0x91, 0x2C, 0x91, 0xA3, 0x97,
+ 0x5F, 0xCE, 0xA8, 0xE3, 0x31, 0xDC, 0x53, 0x8C, 0x79, 0x3F, 0x08, 0x46, 0x54, 0xB2, 0x8E, 0x69,
+ 0x52, 0xA9, 0x8A, 0x9C, 0x64, 0xE5, 0x56, 0x2D, 0xD9, 0xFD, 0x56, 0x13, 0x72, 0x5C, 0x89, 0x2B,
+ 0x73, 0x4D, 0x5A, 0x2E, 0xDC, 0xA9, 0xC9, 0x28, 0x2D, 0x23, 0x95, 0x53, 0xE2, 0xDC, 0x16, 0x19,
+ 0xC2, 0x11, 0x84, 0xA1, 0x18, 0x37, 0x5D, 0xC6, 0x50, 0x92, 0x9C, 0x56, 0xAA, 0x92, 0x52, 0xBD,
+ 0x93, 0x76, 0x69, 0xB5, 0x78, 0x37, 0x16, 0x95, 0xD2, 0x7F, 0x0A, 0x78, 0xA7, 0xF6, 0xC4, 0xFD,
+ 0xA3, 0x3E, 0x3E, 0xFC, 0x4A, 0xB9, 0xF1, 0x6F, 0xC5, 0x8F, 0x15, 0x4F, 0x34, 0xBA, 0x7E, 0x94,
+ 0x74, 0x6D, 0x03, 0xC2, 0xF6, 0x1A, 0x6C, 0x5A, 0x17, 0xC3, 0x5F, 0x07, 0x5B, 0x43, 0x13, 0x95,
+ 0xB7, 0xF0, 0xF6, 0x8F, 0x1A, 0xA5, 0xB5, 0x8D, 0xB0, 0x58, 0xA3, 0x5D, 0xB1, 0x2F, 0x23, 0x2C,
+ 0xE5, 0xD8, 0x92, 0x7F, 0x48, 0xAB, 0xC0, 0x1C, 0x39, 0xC3, 0x39, 0x05, 0x0C, 0x26, 0x43, 0x49,
+ 0x4E, 0xD2, 0xE6, 0x72, 0x76, 0x9D, 0x4A, 0x8E, 0x52, 0x49, 0x3A, 0xB3, 0x51, 0x52, 0x72, 0xD7,
+ 0x45, 0x15, 0x14, 0x94, 0x7D, 0xD4, 0x91, 0xF5, 0xB8, 0x3E, 0x1B, 0xCA, 0xE9, 0xE1, 0xEA, 0xC2,
+ 0x58, 0x5F, 0x67, 0x51, 0x72, 0x27, 0x24, 0xE5, 0x79, 0x3B, 0xEA, 0xD4, 0xBA, 0xC5, 0xBB, 0x3B,
+ 0x74, 0xD1, 0x5D, 0x6A, 0x72, 0xFE, 0x2D, 0x5B, 0xAF, 0x18, 0xDB, 0x5C, 0x26, 0xB7, 0x70, 0x2E,
+ 0x65, 0x11, 0x18, 0xE2, 0x9E, 0x48, 0x55, 0x7C, 0xA2, 0xC3, 0x00, 0xAC, 0x6B, 0xD4, 0x1E, 0x0B,
+ 0x0C, 0xF2, 0x14, 0x7C, 0xC7, 0x68, 0x0D, 0xE6, 0xE0, 0xA1, 0x98, 0x60, 0x67, 0x2A, 0xF8, 0x48,
+ 0xA8, 0x41, 0x24, 0x9A, 0x4A, 0x31, 0x56, 0x4B, 0xAB, 0x49, 0xB5, 0xDD, 0x5F, 0x4B, 0x3D, 0xA2,
+ 0xDE, 0x9E, 0xA6, 0x03, 0x0F, 0x85, 0xC0, 0x53, 0x78, 0x6A, 0x10, 0x5E, 0xCE, 0x57, 0xE6, 0x8D,
+ 0xDD, 0x9D, 0xF7, 0x57, 0xD1, 0xAF, 0x2E, 0xCD, 0xDD, 0x59, 0xBD, 0x35, 0x7E, 0x1D, 0x58, 0xF8,
+ 0xC5, 0x2C, 0x2C, 0xB4, 0x2F, 0x0F, 0xDD, 0xDC, 0x6A, 0x9A, 0xF4, 0xF7, 0x51, 0xE9, 0x3F, 0x65,
+ 0xD1, 0xA3, 0x92, 0xE7, 0x53, 0xBA, 0x62, 0x42, 0xDB, 0xC8, 0xA0, 0x80, 0x3E, 0x52, 0xB1, 0xC4,
+ 0x4E, 0x31, 0x80, 0xBC, 0x0C, 0x1D, 0xDE, 0x4E, 0x77, 0x8A, 0xA3, 0x8D, 0x6F, 0x13, 0x8D, 0xA6,
+ 0x92, 0x8F, 0xBB, 0x35, 0x6B, 0x4F, 0x91, 0xB4, 0xD3, 0x5E, 0xF5, 0x92, 0xE6, 0xD1, 0x7B, 0xAE,
+ 0xCD, 0xBB, 0xBB, 0x34, 0x71, 0xE3, 0x30, 0x79, 0x3E, 0x0F, 0x91, 0x72, 0xB8, 0xE1, 0xE0, 0xAF,
+ 0x1E, 0x76, 0xAC, 0x92, 0x4D, 0xB8, 0xBB, 0x6D, 0x7D, 0x64, 0xFA, 0xDF, 0x4D, 0x9D, 0x97, 0x55,
+ 0xE2, 0x26, 0xF8, 0x31, 0xF0, 0x36, 0x69, 0x65, 0xF8, 0xAA, 0xFA, 0x0F, 0xC4, 0x0F, 0x8A, 0x56,
+ 0x11, 0x08, 0x93, 0xC0, 0x3A, 0x4E, 0xBC, 0x66, 0xF0, 0x7F, 0x86, 0x67, 0x2A, 0x59, 0x9F, 0xC4,
+ 0x1A, 0x84, 0x33, 0xB3, 0x5D, 0x4C, 0x0E, 0xDC, 0xDA, 0xDA, 0xB4, 0x67, 0x3B, 0x43, 0xCC, 0xA4,
+ 0x61, 0x70, 0xC2, 0x70, 0xFF, 0x00, 0x1A, 0x71, 0x64, 0xA9, 0x43, 0x09, 0x87, 0x73, 0xA3, 0xAF,
+ 0x23, 0xB3, 0x8C, 0x54, 0x5D, 0x92, 0x72, 0xE6, 0x56, 0x8C, 0x6C, 0xEF, 0xAA, 0x9A, 0x6F, 0xDE,
+ 0x8C, 0x1A, 0x69, 0xBE, 0x4F, 0xED, 0x3A, 0xB5, 0xB0, 0xDC, 0xF4, 0x71, 0x0B, 0x0B, 0x81, 0x6F,
+ 0xF8, 0x93, 0xE5, 0x8C, 0xA6, 0x96, 0x96, 0xA5, 0x16, 0x97, 0x2A, 0xDD, 0x29, 0x34, 0xF4, 0xBF,
+ 0x2A, 0x6F, 0x43, 0xE5, 0xFF, 0x00, 0x88, 0x7F, 0xB5, 0x27, 0x89, 0xBC, 0x7D, 0x77, 0x65, 0x34,
+ 0xE9, 0xA3, 0x6A, 0x5A, 0x26, 0x9D, 0x1C, 0x92, 0xE9, 0x3E, 0x15, 0x69, 0xAC, 0xFC, 0x33, 0xE0,
+ 0x9D, 0x0D, 0x11, 0x76, 0x91, 0xA6, 0xE9, 0x7B, 0xC4, 0x36, 0xEE, 0x16, 0x38, 0xD5, 0x58, 0x46,
+ 0x5D, 0xC2, 0xFC, 0xC5, 0x8B, 0x02, 0x7E, 0xBF, 0x28, 0xF0, 0xBF, 0x13, 0x87, 0xA9, 0x4F, 0x11,
+ 0x98, 0x42, 0x1E, 0xC6, 0x17, 0x5C, 0xAA, 0x2D, 0xB5, 0xA6, 0xB2, 0xE6, 0x4F, 0x9A, 0xFE, 0xF2,
+ 0xB7, 0x3B, 0x94, 0x79, 0xAE, 0xD2, 0x5B, 0x2F, 0x9A, 0xC6, 0x71, 0xBF, 0x0D, 0x64, 0xB8, 0x79,
+ 0xE1, 0xB2, 0x58, 0x54, 0xAB, 0x89, 0x96, 0xF5, 0x2C, 0xFC, 0x9B, 0xE6, 0x95, 0x9C, 0xE4, 0x9F,
+ 0x44, 0x94, 0x15, 0xEC, 0xA2, 0xED, 0x1D, 0x3E, 0x6D, 0x4F, 0x1D, 0xF8, 0xF7, 0x46, 0xDF, 0x7F,
+ 0xA6, 0xF9, 0xBE, 0x75, 0xF2, 0x43, 0xA9, 0xC5, 0x79, 0x65, 0x2B, 0x4C, 0x96, 0xB6, 0xC0, 0x32,
+ 0xAC, 0x73, 0x24, 0x0D, 0xB7, 0x71, 0xE3, 0x21, 0xC9, 0x6E, 0x14, 0x10, 0x2B, 0xDF, 0x7C, 0x17,
+ 0x95, 0x52, 0xCB, 0x55, 0x18, 0xE1, 0xD4, 0xF9, 0x64, 0x9B, 0xE7, 0xB4, 0xA4, 0xA3, 0xBA, 0x57,
+ 0x85, 0x9B, 0x4B, 0x65, 0x18, 0xEF, 0xB7, 0x45, 0x6F, 0xCC, 0xF8, 0x8F, 0x3F, 0xC7, 0xF1, 0x6D,
+ 0x7A, 0x5F, 0xDB, 0xB8, 0xA4, 0xA3, 0x0B, 0xA8, 0xC2, 0x16, 0x84, 0x13, 0x49, 0x5F, 0x92, 0x2D,
+ 0xDA, 0xCA, 0xEE, 0xF7, 0x4E, 0x49, 0xBD, 0xED, 0xA3, 0xD3, 0xB8, 0xF8, 0x9B, 0xE3, 0xAD, 0x7A,
+ 0x0F, 0xB4, 0x78, 0x9B, 0xC3, 0x3E, 0x18, 0xD7, 0xB4, 0xF9, 0x40, 0xBB, 0x4B, 0x7F, 0x13, 0xC1,
+ 0x71, 0xA6, 0x69, 0xB7, 0xB1, 0x44, 0xE0, 0x14, 0x46, 0x5B, 0x98, 0x1E, 0x40, 0x19, 0x63, 0x18,
+ 0x49, 0x32, 0x30, 0x07, 0x7C, 0x57, 0x87, 0x5F, 0x87, 0x30, 0x38, 0x0C, 0x3C, 0x71, 0x34, 0x63,
+ 0x28, 0x7B, 0xCE, 0xEA, 0x29, 0xD9, 0x37, 0x6B, 0xF3, 0x26, 0x9C, 0xA2, 0x96, 0xBB, 0xC9, 0x2E,
+ 0x8D, 0x59, 0x34, 0x7C, 0x55, 0x3E, 0x1E, 0xC9, 0xBF, 0xB5, 0xFE, 0xB9, 0x84, 0xC5, 0x4E, 0x35,
+ 0xE3, 0x74, 0xF9, 0x25, 0x07, 0xCB, 0x75, 0x64, 0x9A, 0xE4, 0x6A, 0x29, 0x26, 0xEC, 0x9A, 0x49,
+ 0xEE, 0xEF, 0x66, 0x7A, 0x17, 0xC1, 0xAF, 0x89, 0x76, 0xDE, 0x0E, 0xBD, 0x9D, 0xF5, 0x3F, 0x0B,
+ 0xEA, 0x36, 0x76, 0x77, 0x17, 0x73, 0x4E, 0x90, 0xF8, 0x4A, 0x16, 0xD5, 0xB4, 0xDB, 0x48, 0xCB,
+ 0x99, 0x4A, 0x45, 0x08, 0x91, 0xE5, 0xF2, 0x91, 0x49, 0xC3, 0x16, 0x7C, 0x2A, 0x8F, 0x9F, 0x38,
+ 0xAF, 0x92, 0xE2, 0x0C, 0xA2, 0xA6, 0x3B, 0x08, 0xA5, 0x46, 0x50, 0x4E, 0xDC, 0xBE, 0xF3, 0x51,
+ 0x6E, 0xE9, 0x24, 0xAE, 0xD2, 0x4D, 0x5B, 0x5B, 0x5B, 0x7D, 0x34, 0x57, 0xB7, 0x3E, 0x2F, 0x27,
+ 0x9C, 0xF3, 0xB8, 0xE6, 0x18, 0x4C, 0x44, 0x65, 0x15, 0x1E, 0x49, 0x46, 0x52, 0x51, 0x9F, 0x32,
+ 0x4A, 0xD2, 0x7B, 0x29, 0x2B, 0xC7, 0x56, 0xAD, 0x66, 0xF4, 0x5D, 0x0F, 0xAD, 0xB4, 0x6F, 0xDA,
+ 0x1F, 0xE0, 0xE6, 0xA6, 0xA8, 0x57, 0xC6, 0x76, 0x16, 0x24, 0xC6, 0x18, 0x47, 0xAB, 0x23, 0xE9,
+ 0xC5, 0x01, 0xE8, 0x18, 0xB8, 0x03, 0x23, 0x03, 0x80, 0x4F, 0x6E, 0xD5, 0xF9, 0x1E, 0x6F, 0xC3,
+ 0x39, 0xD6, 0x1A, 0x8C, 0xB0, 0xEB, 0x0B, 0x68, 0xED, 0xEE, 0x24, 0xDE, 0xCB, 0x66, 0xB5, 0xB6,
+ 0x8A, 0xCF, 0xA3, 0xED, 0x64, 0x7B, 0xD0, 0xC3, 0xE2, 0x69, 0xB5, 0x1F, 0x66, 0xFB, 0x6C, 0xDE,
+ 0xB6, 0xD3, 0x6E, 0x8B, 0xBE, 0x8B, 0xA7, 0x4B, 0x1E, 0x9B, 0xA6, 0x78, 0xD3, 0xC1, 0x9A, 0xB2,
+ 0x07, 0xD3, 0x7C, 0x55, 0xE1, 0xEB, 0xD4, 0x61, 0x94, 0xFB, 0x36, 0xB1, 0x6E, 0xFC, 0x63, 0x8E,
+ 0x37, 0x7A, 0x02, 0x78, 0xF4, 0x3E, 0x95, 0xF9, 0xEE, 0x27, 0x2F, 0xC4, 0x61, 0xDA, 0x85, 0x4A,
+ 0x32, 0x8B, 0xBB, 0x5A, 0xC5, 0xAD, 0xBA, 0x3B, 0xA5, 0x6B, 0x5E, 0xDB, 0x5B, 0xA5, 0xDB, 0x45,
+ 0x29, 0x34, 0xD5, 0xB6, 0xDB, 0xCA, 0xFA, 0x5D, 0x2E, 0x9A, 0x5D, 0x2B, 0x74, 0x3E, 0x74, 0xFD,
+ 0xA6, 0x2C, 0xA6, 0xD5, 0xFC, 0x35, 0x77, 0x0E, 0x95, 0x17, 0xDB, 0x9E, 0x4D, 0x3E, 0x6B, 0x7C,
+ 0x59, 0xED, 0x98, 0xEE, 0x64, 0x01, 0x50, 0x10, 0x71, 0x92, 0x09, 0xFC, 0x05, 0x7B, 0x5C, 0x39,
+ 0x4E, 0x95, 0x4A, 0x55, 0x28, 0x4E, 0x56, 0x8E, 0x8D, 0xDB, 0x47, 0x65, 0x34, 0xAF, 0xDB, 0x45,
+ 0xE4, 0xF5, 0x69, 0x5B, 0xBF, 0xC8, 0xE6, 0xB5, 0x69, 0xE1, 0x78, 0x87, 0x2E, 0xC6, 0x57, 0x6A,
+ 0x34, 0xA1, 0x3F, 0x7A, 0x4F, 0xE1, 0x5F, 0x0D, 0xAF, 0xFF, 0x00, 0x80, 0xB4, 0xB6, 0xD5, 0x59,
+ 0x1A, 0x3F, 0xB2, 0xAD, 0xAE, 0xA6, 0x90, 0x68, 0x57, 0x1A, 0x9A, 0xEA, 0x3A, 0x66, 0xA1, 0x26,
+ 0x8B, 0x3D, 0xB6, 0xA5, 0xF6, 0xC8, 0xD8, 0xC5, 0x10, 0x89, 0x59, 0x60, 0x48, 0x94, 0xE7, 0x1B,
+ 0x80, 0x07, 0x04, 0x91, 0xF3, 0x37, 0xDD, 0x00, 0x01, 0xF6, 0xBC, 0x47, 0x1A, 0x78, 0xE7, 0x96,
+ 0xD6, 0xAD, 0x35, 0xCD, 0x52, 0x85, 0x5A, 0x72, 0x6A, 0x2D, 0x5B, 0xD9, 0xC7, 0x96, 0x0A, 0xCA,
+ 0xDA, 0xDA, 0x36, 0xE6, 0x5A, 0x3B, 0x27, 0x6D, 0x8C, 0xE9, 0xD6, 0xA1, 0x89, 0xE2, 0x4C, 0x5D,
+ 0x7C, 0x03, 0xF6, 0x94, 0x57, 0x24, 0x53, 0x4D, 0x38, 0xB5, 0x78, 0xD9, 0x26, 0xF5, 0xF7, 0x52,
+ 0x69, 0xDB, 0x45, 0x65, 0x6B, 0xDF, 0x5F, 0xAB, 0xC8, 0x02, 0x37, 0xDB, 0x1A, 0xAF, 0xEE, 0xFE,
+ 0xE9, 0x1B, 0x70, 0xA4, 0x02, 0x54, 0xFA, 0x77, 0xFE, 0x7C, 0xF4, 0xAF, 0xE6, 0xDF, 0x66, 0xF0,
+ 0xEA, 0x71, 0xE5, 0x4D, 0xA4, 0xE2, 0xD3, 0x57, 0xB6, 0xEA, 0xE9, 0x74, 0x6A, 0xD6, 0x4E, 0xEB,
+ 0xB2, 0x56, 0x3F, 0x43, 0x71, 0xBC, 0x54, 0x62, 0xAD, 0xA6, 0xDA, 0x2B, 0xDB, 0xA7, 0xA5, 0xBB,
+ 0x5A, 0xD6, 0x3E, 0x48, 0xF8, 0x83, 0xE1, 0xFD, 0x66, 0xC3, 0xC4, 0x77, 0x5A, 0xE5, 0xD7, 0x86,
+ 0x2F, 0x35, 0x8F, 0x0F, 0xE9, 0xF6, 0xD7, 0x71, 0xDB, 0x8D, 0x32, 0x13, 0x34, 0xD6, 0xD7, 0x17,
+ 0xAB, 0x12, 0xC2, 0xEC, 0x41, 0x19, 0x00, 0xC0, 0xC3, 0x68, 0xC7, 0xDE, 0x18, 0xCE, 0x7E, 0x5F,
+ 0xE8, 0x9E, 0x1E, 0x58, 0x6C, 0x45, 0x2C, 0x3E, 0x4B, 0x83, 0xA9, 0x19, 0x37, 0x39, 0x53, 0x9F,
+ 0x25, 0xEC, 0x94, 0xA9, 0xAB, 0x5B, 0x54, 0x95, 0xD2, 0xB2, 0x6F, 0x9A, 0xF2, 0xBA, 0x71, 0xB6,
+ 0xDF, 0x9D, 0x73, 0xBC, 0xBB, 0x15, 0x8D, 0xA5, 0x98, 0x47, 0x96, 0x95, 0x5B, 0x38, 0xC9, 0xC5,
+ 0x38, 0xC9, 0x34, 0xA3, 0x28, 0xC9, 0x36, 0x92, 0x4E, 0xC9, 0x5E, 0x36, 0x69, 0x75, 0x5A, 0xA3,
+ 0xB3, 0xF8, 0x73, 0xF1, 0x76, 0xDE, 0x6B, 0x2D, 0x3B, 0x47, 0xBD, 0xF0, 0xEE, 0xB9, 0x6B, 0x7D,
+ 0x0C, 0x7E, 0x40, 0x7F, 0xEC, 0xD7, 0x8E, 0x30, 0x14, 0x63, 0x24, 0x63, 0x8C, 0x60, 0xF0, 0x38,
+ 0x03, 0x1C, 0xE0, 0xE4, 0xFE, 0x4B, 0x99, 0x70, 0xF3, 0xF6, 0xB5, 0x31, 0x74, 0x6A, 0x2B, 0x36,
+ 0xDB, 0x4F, 0x46, 0xAC, 0xDE, 0x8A, 0xD6, 0xD3, 0x45, 0x7B, 0x2E, 0xB6, 0xB6, 0x8A, 0xDE, 0x96,
+ 0x47, 0xC4, 0x94, 0xF0, 0xF4, 0xA8, 0xE5, 0x53, 0xA5, 0x76, 0x94, 0x62, 0xA5, 0x06, 0xA5, 0x16,
+ 0x92, 0x49, 0x3B, 0x2F, 0x79, 0x69, 0xBD, 0xD5, 0x96, 0xB7, 0x7A, 0x59, 0x7D, 0x27, 0x04, 0xBF,
+ 0x69, 0x84, 0xB0, 0x05, 0x15, 0xE1, 0x66, 0x11, 0x72, 0xAC, 0x00, 0x4E, 0x14, 0xE7, 0xF9, 0x74,
+ 0xFC, 0x2B, 0xE4, 0x28, 0x50, 0xF6, 0x78, 0xB8, 0x53, 0x8B, 0x69, 0xF4, 0x6A, 0xCB, 0x64, 0xEC,
+ 0xD5, 0x9E, 0x8A, 0xEB, 0x74, 0xD3, 0xB6, 0xCA, 0xFA, 0x1F, 0x6F, 0x15, 0x17, 0x18, 0xCA, 0x31,
+ 0xB7, 0x4F, 0xBB, 0xF2, 0xB7, 0x97, 0x96, 0x87, 0xC0, 0xBF, 0x17, 0xFC, 0x0B, 0xF1, 0x0A, 0xD3,
+ 0xE2, 0x9F, 0x85, 0x7C, 0x67, 0xE1, 0xAF, 0x0F, 0x6A, 0xDA, 0xE4, 0x7A, 0x6E, 0xA6, 0x5A, 0x38,
+ 0xF4, 0x39, 0x36, 0x6A, 0xA7, 0x78, 0x0A, 0x86, 0x06, 0xC8, 0x01, 0xF8, 0x18, 0x24, 0x8E, 0x71,
+ 0xD3, 0x3C, 0x7E, 0x99, 0x91, 0xE7, 0x15, 0x31, 0x58, 0x0A, 0x58, 0x5F, 0x6F, 0x2B, 0xAE, 0x58,
+ 0xF2, 0xA9, 0xB5, 0xAA, 0x92, 0xE5, 0x51, 0x57, 0xB5, 0xD6, 0xF1, 0xB2, 0xD3, 0x74, 0xB6, 0xBF,
+ 0xC4, 0xBC, 0x1C, 0xF0, 0xB5, 0xF1, 0xF8, 0x4C, 0x42, 0x95, 0x35, 0x5D, 0xC2, 0x54, 0xE7, 0x18,
+ 0xB7, 0x14, 0xE2, 0xD6, 0x92, 0xE5, 0x8C, 0x9C, 0x5E, 0x8B, 0x5E, 0x56, 0xAD, 0x6D, 0xED, 0x63,
+ 0xEA, 0x0F, 0x04, 0xFC, 0x4F, 0xD5, 0xF5, 0x99, 0x46, 0x91, 0xA9, 0x78, 0x4F, 0xC5, 0xDA, 0x45,
+ 0xEC, 0x44, 0x25, 0xD4, 0xBA, 0xBD, 0xBB, 0xA2, 0x17, 0x18, 0x0D, 0xE6, 0xC9, 0x9E, 0x4F, 0x4C,
+ 0x91, 0x9E, 0xE6, 0xBE, 0x5F, 0x3B, 0xC2, 0xE2, 0xE9, 0x7B, 0x5C, 0x55, 0x3C, 0x54, 0xB9, 0x2E,
+ 0xEF, 0x19, 0x4D, 0xDF, 0x4E, 0x8F, 0x65, 0xA7, 0x45, 0xDE, 0xD6, 0x47, 0xA5, 0x94, 0xE7, 0x2E,
+ 0x73, 0x86, 0x06, 0xA6, 0x19, 0xDD, 0x2B, 0x29, 0x47, 0xE0, 0xB2, 0xD1, 0x5A, 0xE9, 0x35, 0xB5,
+ 0x92, 0xB3, 0x56, 0x56, 0x5D, 0x2D, 0xF3, 0xE7, 0xED, 0x98, 0x65, 0x9B, 0xC2, 0x03, 0x60, 0x95,
+ 0x9C, 0xC4, 0x80, 0x2C, 0x4C, 0x01, 0x04, 0x4C, 0x80, 0x31, 0xF6, 0xE0, 0x75, 0xE9, 0x81, 0xE9,
+ 0xC7, 0xA5, 0xC2, 0x50, 0xC6, 0xCA, 0x85, 0x68, 0x52, 0xE7, 0x6E, 0xC9, 0xA4, 0xA6, 0xA3, 0xB2,
+ 0x76, 0x7D, 0x92, 0x4A, 0xFA, 0x6E, 0xD5, 0xEC, 0xD1, 0xB6, 0x2D, 0xC2, 0x97, 0x15, 0xE5, 0xB2,
+ 0x6D, 0x24, 0x9D, 0x4D, 0x5A, 0xD7, 0xE0, 0xBF, 0x4B, 0x59, 0xF4, 0xB7, 0xC8, 0x8B, 0xE0, 0x84,
+ 0xBF, 0x15, 0x3C, 0x09, 0xF0, 0xF2, 0xDA, 0xE1, 0x3C, 0x2B, 0x7D, 0xE3, 0x5D, 0x16, 0x38, 0x92,
+ 0x38, 0xA6, 0xD3, 0xAF, 0x62, 0x1F, 0x64, 0xC8, 0xF9, 0x36, 0xC5, 0xB7, 0x2C, 0xA0, 0x29, 0x5F,
+ 0xBC, 0x39, 0x15, 0xE9, 0x66, 0xB9, 0x76, 0x57, 0x8B, 0xCA, 0x69, 0xD6, 0xC7, 0x42, 0x71, 0xC6,
+ 0x59, 0xFE, 0xF1, 0x4E, 0x3C, 0x96, 0x56, 0xDE, 0x0E, 0x2B, 0x65, 0xE7, 0xAD, 0xD7, 0x44, 0x93,
+ 0xF1, 0xB0, 0xB9, 0xA4, 0xFE, 0xB9, 0x88, 0xC6, 0xE5, 0x18, 0x79, 0xAA, 0x33, 0x93, 0x76, 0x6B,
+ 0xDD, 0xE6, 0x4E, 0xD2, 0x6B, 0x95, 0x39, 0x45, 0x3B, 0x6A, 0xB9, 0x5A, 0xD3, 0x4B, 0x58, 0xFB,
+ 0xF7, 0xF6, 0x7B, 0xFF, 0x00, 0x82, 0x99, 0x7C, 0x68, 0xFD, 0x9D, 0xD0, 0xF8, 0x5B, 0x4A, 0xF8,
+ 0x29, 0xE2, 0x0F, 0x89, 0xDF, 0x0B, 0xB5, 0x9B, 0x81, 0x27, 0x89, 0x7E, 0x0E, 0xFC, 0x44, 0xD3,
+ 0x23, 0xD5, 0xFC, 0x19, 0x20, 0x72, 0x56, 0x5B, 0xCD, 0x1E, 0x47, 0x24, 0xE9, 0x1A, 0x88, 0x49,
+ 0x1C, 0x2D, 0xDD, 0xB0, 0x07, 0x3C, 0x48, 0xB2, 0xA1, 0x68, 0xCF, 0xCB, 0xAC, 0x8F, 0x04, 0xA8,
+ 0xC6, 0x70, 0xC5, 0x24, 0xD6, 0xFA, 0xAD, 0x5E, 0xEA, 0xCA, 0xFA, 0x6F, 0x67, 0x6F, 0x55, 0xAA,
+ 0x4C, 0xF5, 0x28, 0xF1, 0x26, 0x26, 0xA3, 0x8A, 0x8D, 0x15, 0x1D, 0x52, 0x77, 0x75, 0x1B, 0xB7,
+ 0x5B, 0x25, 0x4A, 0xFA, 0x2B, 0xD9, 0x3B, 0x2D, 0x76, 0xE8, 0x59, 0xFD, 0xA4, 0x7F, 0x63, 0x2B,
+ 0xBF, 0xDA, 0x67, 0x5C, 0x5F, 0xDB, 0x27, 0xE0, 0x97, 0x8E, 0xBC, 0x4F, 0xF1, 0x1B, 0xE0, 0x8D,
+ 0x94, 0x56, 0xDA, 0xA7, 0x8F, 0xFE, 0x13, 0x78, 0xCF, 0x4B, 0xB5, 0xB1, 0xF8, 0xFF, 0x00, 0xF0,
+ 0x02, 0xFD, 0x90, 0x2A, 0xDB, 0x78, 0x8B, 0x4C, 0xB4, 0x2F, 0x0D, 0xCE, 0x97, 0x1E, 0x76, 0x41,
+ 0xA8, 0xDB, 0x13, 0x09, 0x1C, 0x39, 0x56, 0x47, 0xDB, 0x78, 0x6C, 0xF6, 0x78, 0x3C, 0x35, 0x4C,
+ 0x3C, 0xDA, 0x73, 0xDA, 0xF1, 0x77, 0x4E, 0xC9, 0x6A, 0xF7, 0xEC, 0xAC, 0x95, 0x92, 0x4B, 0x54,
+ 0x74, 0x63, 0x72, 0xB7, 0x8C, 0x55, 0x6B, 0x60, 0xE4, 0xEF, 0x5F, 0xDC, 0x9C, 0xE5, 0xA4, 0xA3,
+ 0x49, 0x6B, 0xEC, 0xE9, 0xC1, 0x45, 0x38, 0xA7, 0xD5, 0xCD, 0x26, 0xF5, 0x5A, 0xB5, 0xAF, 0x1F,
+ 0xA2, 0x6A, 0xFA, 0xCF, 0x84, 0x96, 0xD6, 0xE3, 0xC2, 0x57, 0xF3, 0x69, 0xD7, 0xD6, 0xD6, 0xBE,
+ 0x55, 0xAB, 0xD9, 0xCF, 0xE4, 0xC7, 0x32, 0xAA, 0xFC, 0xB0, 0xC8, 0xA3, 0xE5, 0x92, 0x36, 0xF9,
+ 0x41, 0x56, 0x52, 0xA4, 0x71, 0x8E, 0x95, 0xE7, 0x70, 0xD5, 0x0C, 0x3E, 0x65, 0xC4, 0x38, 0x4C,
+ 0x36, 0x3E, 0x6D, 0x52, 0xA9, 0x34, 0xA6, 0xE2, 0xD2, 0x92, 0x56, 0x6D, 0x34, 0xDA, 0x69, 0x6A,
+ 0x96, 0x8D, 0x35, 0xE4, 0xFA, 0x76, 0xD7, 0xE7, 0xC2, 0x60, 0x65, 0x0C, 0x22, 0x57, 0x51, 0x69,
+ 0x2D, 0x52, 0xD1, 0x59, 0x27, 0x6E, 0x9D, 0xF7, 0xD3, 0x4D, 0x3A, 0xE2, 0xF8, 0x47, 0xC6, 0x1A,
+ 0xCF, 0xC5, 0x2D, 0x7B, 0x58, 0x8B, 0xE2, 0x6F, 0x86, 0x74, 0xBF, 0x85, 0x9E, 0x23, 0x9A, 0xE9,
+ 0xCE, 0x9F, 0xE2, 0xAD, 0x0E, 0x08, 0xA1, 0xF8, 0x7B, 0xE2, 0x1C, 0x63, 0x0D, 0xA8, 0xD8, 0xAB,
+ 0x19, 0x74, 0xF9, 0x49, 0x0A, 0x77, 0xC0, 0xAF, 0x11, 0x38, 0x26, 0x35, 0xC9, 0xC6, 0xF9, 0xDB,
+ 0xC1, 0x62, 0x71, 0xF8, 0x8C, 0x5A, 0xA9, 0x16, 0xE5, 0x26, 0xD5, 0xB9, 0xAF, 0xDB, 0x64, 0xAD,
+ 0x6B, 0x59, 0x2D, 0x13, 0xB6, 0xBA, 0xEE, 0x73, 0x65, 0xD3, 0xF6, 0x98, 0x3A, 0x14, 0xF1, 0x34,
+ 0xE5, 0x0A, 0xEA, 0x36, 0x9B, 0x71, 0x8A, 0xA7, 0x74, 0x92, 0x4A, 0x2D, 0xC9, 0xEE, 0xF6, 0x7A,
+ 0x2D, 0x36, 0x49, 0x24, 0x78, 0x47, 0xC6, 0x1F, 0x84, 0xBE, 0x3F, 0xD4, 0x3E, 0x26, 0x78, 0x6E,
+ 0xC3, 0xC4, 0xBA, 0x23, 0xD8, 0x78, 0x4F, 0x41, 0x74, 0xD4, 0xA2, 0xBB, 0x92, 0xE2, 0x39, 0xF4,
+ 0xFD, 0x68, 0xA8, 0x06, 0x19, 0x6D, 0x1D, 0x09, 0x49, 0x62, 0x3B, 0xB7, 0x6E, 0x53, 0x83, 0xC7,
+ 0x4E, 0x95, 0xB6, 0x0A, 0xBE, 0x1F, 0x03, 0x81, 0xF6, 0x71, 0x92, 0xE7, 0x7A, 0xF6, 0x77, 0x5A,
+ 0x47, 0xB2, 0xB2, 0xD5, 0xDD, 0x3B, 0x69, 0x66, 0xBB, 0x78, 0xD9, 0x8E, 0x0F, 0x19, 0x5F, 0x1F,
+ 0x38, 0xBA, 0x6E, 0x31, 0x92, 0x54, 0xD4, 0xB4, 0xE5, 0x50, 0x6D, 0x39, 0xB8, 0xB4, 0xEF, 0xCD,
+ 0x24, 0x94, 0x57, 0x96, 0xBB, 0x1D, 0xED, 0xFA, 0x4F, 0x06, 0x9F, 0x34, 0x7A, 0x75, 0xB2, 0xCD,
+ 0x70, 0x90, 0x18, 0x2D, 0x60, 0x52, 0x22, 0x46, 0x21, 0x02, 0xA2, 0x92, 0x70, 0x3A, 0x90, 0x39,
+ 0x03, 0xE8, 0x3A, 0x0E, 0x0C, 0x32, 0x84, 0xEB, 0x47, 0xDA, 0xBB, 0x46, 0xEA, 0xEE, 0xDD, 0x34,
+ 0xDB, 0xE5, 0xD3, 0xC9, 0x74, 0xB1, 0xE9, 0xE2, 0x63, 0x56, 0x8E, 0x0A, 0x4B, 0x09, 0x04, 0xE4,
+ 0xA3, 0x68, 0xC7, 0x44, 0x9B, 0x4A, 0xC9, 0x74, 0xF2, 0x5D, 0x2C, 0xBB, 0x5E, 0xC7, 0x95, 0xFC,
+ 0x1B, 0xF0, 0x3E, 0xAD, 0xE1, 0x79, 0xFC, 0x43, 0x7D, 0xAF, 0x08, 0x66, 0xD7, 0xFC, 0x4B, 0xA9,
+ 0x49, 0x7F, 0xAB, 0x5F, 0xD9, 0xDA, 0xC9, 0x74, 0xF6, 0x36, 0xAA, 0x00, 0x45, 0x52, 0xA3, 0x72,
+ 0x84, 0x50, 0xAA, 0xC4, 0x8C, 0x67, 0x92, 0x2B, 0xE9, 0x61, 0x8A, 0xA1, 0x5A, 0xAA, 0xA7, 0x29,
+ 0x28, 0xD2, 0x5A, 0xBD, 0x2E, 0xE2, 0x97, 0x58, 0xEC, 0xEC, 0x96, 0xB6, 0xD1, 0x5D, 0xB5, 0x7B,
+ 0x2D, 0x3C, 0x3A, 0x58, 0x79, 0xF2, 0xC7, 0x96, 0x0F, 0x96, 0x14, 0xD4, 0x20, 0x9D, 0xAF, 0xB7,
+ 0x34, 0xE5, 0x24, 0x97, 0xBA, 0xE5, 0x36, 0xDB, 0x49, 0xDB, 0x95, 0x45, 0x35, 0xA5, 0x9E, 0xDF,
+ 0x8F, 0xAF, 0x3C, 0x3B, 0xAA, 0x69, 0xFA, 0xDE, 0x99, 0x79, 0xAA, 0xDB, 0xDA, 0xE9, 0x77, 0x96,
+ 0xAF, 0x6F, 0x1C, 0x5A, 0xA6, 0xA9, 0x16, 0xE8, 0xD0, 0x26, 0x17, 0x71, 0x24, 0x0C, 0x02, 0xB9,
+ 0x00, 0x01, 0x80, 0x05, 0x72, 0xD6, 0xC7, 0xAA, 0xB8, 0xE5, 0x59, 0x37, 0xEC, 0xEF, 0xCB, 0x14,
+ 0xDD, 0xDA, 0x8D, 0xAD, 0x65, 0xBD, 0x9D, 0x9B, 0xD1, 0x5E, 0xD7, 0x7E, 0x64, 0xFB, 0x2A, 0xF2,
+ 0xA2, 0xE3, 0x06, 0xA3, 0x51, 0x59, 0xC5, 0xEA, 0x94, 0x65, 0x16, 0xA5, 0x16, 0xBA, 0xA4, 0xA4,
+ 0x97, 0x4D, 0xFA, 0x1F, 0x22, 0x7C, 0x37, 0xF1, 0x0D, 0xAF, 0xC3, 0x3F, 0x14, 0x6A, 0xBE, 0x28,
+ 0xF1, 0xEF, 0xC5, 0x6D, 0x0F, 0x5A, 0xD6, 0x2D, 0x74, 0xC5, 0xF0, 0xEF, 0x86, 0x6E, 0x57, 0x5D,
+ 0x3E, 0x21, 0xBE, 0xB0, 0xD3, 0xA3, 0x66, 0x0B, 0x02, 0xAB, 0x83, 0xB5, 0x02, 0xC8, 0x42, 0xA8,
+ 0xC8, 0x1C, 0xE0, 0x8C, 0x71, 0xE7, 0xD3, 0xC4, 0x61, 0x30, 0x94, 0x65, 0x4A, 0xAE, 0x26, 0x1C,
+ 0xAE, 0x5E, 0xED, 0xF9, 0x63, 0xCB, 0x0B, 0x5F, 0x95, 0xDE, 0xD7, 0x6B, 0x4D, 0x77, 0xB2, 0x8F,
+ 0x56, 0xAF, 0xEE, 0x66, 0x58, 0xAC, 0xD7, 0x3D, 0xC4, 0x61, 0x6A, 0xE0, 0x70, 0x95, 0x22, 0xA0,
+ 0xA5, 0x29, 0xB7, 0x1E, 0x64, 0xEA, 0xCA, 0x2A, 0x37, 0x8B, 0x57, 0x8D, 0x94, 0x6E, 0xB5, 0xB6,
+ 0xEA, 0xD1, 0xBE, 0xDE, 0x5B, 0xE2, 0x9F, 0x8A, 0x1E, 0x15, 0x1E, 0x2D, 0x49, 0xAC, 0x35, 0x6B,
+ 0x4D, 0x43, 0xC1, 0x51, 0xEB, 0xEB, 0xE2, 0xD7, 0xD1, 0xEC, 0xF4, 0x04, 0x8F, 0x54, 0x9B, 0x52,
+ 0x8E, 0xDC, 0xC7, 0x14, 0x86, 0xE9, 0xA3, 0x0C, 0x63, 0x00, 0x8F, 0x94, 0xC9, 0x81, 0xB4, 0x71,
+ 0x93, 0x91, 0xE7, 0x57, 0xCF, 0xB2, 0x78, 0x66, 0x10, 0xC6, 0x4B, 0x11, 0xCD, 0x05, 0x18, 0xDE,
+ 0x0A, 0x32, 0x77, 0x94, 0x53, 0x51, 0x6B, 0x68, 0xE9, 0xD6, 0xFA, 0xA6, 0x93, 0x8A, 0x56, 0x3A,
+ 0x70, 0x99, 0x27, 0x10, 0xD6, 0xE1, 0x8A, 0xD9, 0x1C, 0x30, 0xCE, 0x9D, 0x59, 0x73, 0x42, 0x33,
+ 0x9C, 0xA3, 0x65, 0x4A, 0x52, 0x52, 0x94, 0x74, 0x6E, 0x49, 0xEE, 0x92, 0x4A, 0xCD, 0x6E, 0xB4,
+ 0x45, 0xCF, 0x1B, 0xFE, 0xD4, 0xEB, 0xE2, 0xA3, 0x78, 0x8B, 0xF0, 0xF3, 0xC2, 0xD7, 0x76, 0x77,
+ 0x1A, 0x3A, 0xE8, 0xF0, 0x69, 0xDA, 0xAD, 0xAC, 0xB6, 0xDA, 0x3D, 0x88, 0x48, 0xD5, 0x52, 0xE6,
+ 0x1B, 0x4B, 0x69, 0x93, 0x6C, 0xC0, 0xA0, 0x70, 0x43, 0xED, 0xDF, 0x92, 0x54, 0xF4, 0x1C, 0x78,
+ 0xDE, 0x37, 0xC2, 0x3A, 0x12, 0xA1, 0x81, 0xC3, 0xB7, 0x76, 0x9B, 0xE7, 0x6A, 0xCD, 0xAE, 0xE9,
+ 0x5D, 0xCA, 0x3A, 0x27, 0x6B, 0xA6, 0xDF, 0x54, 0x75, 0xE4, 0xBE, 0x1F, 0x62, 0xB0, 0x99, 0x95,
+ 0x2C, 0xD3, 0x31, 0xC4, 0x43, 0x9A, 0x9C, 0x79, 0x63, 0x0A, 0x71, 0x6A, 0x31, 0xD2, 0xD7, 0x8D,
+ 0xEC, 0x93, 0xB6, 0xF7, 0x8B, 0x4D, 0x68, 0xD3, 0xDC, 0xF0, 0xA3, 0xF1, 0x13, 0x50, 0x6F, 0x04,
+ 0xDD, 0x78, 0x22, 0xEB, 0x45, 0xD0, 0x2E, 0xE0, 0xB9, 0xD6, 0x06, 0xB1, 0x3F, 0x88, 0x64, 0x7B,
+ 0xA3, 0xE2, 0x65, 0x73, 0x20, 0x66, 0x48, 0xA5, 0x17, 0x1E, 0x46, 0xD3, 0x82, 0x0E, 0x61, 0x73,
+ 0xCF, 0x5C, 0x81, 0x8F, 0x93, 0xC4, 0x71, 0x36, 0x61, 0x8D, 0xC2, 0x3C, 0x05, 0x4B, 0x2A, 0x53,
+ 0x94, 0xA6, 0xD4, 0x62, 0xE2, 0xFD, 0xE9, 0x73, 0x34, 0xDB, 0x6D, 0x59, 0x3D, 0xAE, 0xAF, 0x6B,
+ 0x2D, 0x52, 0x3E, 0xF6, 0x97, 0x0C, 0x65, 0xB8, 0x4C, 0xCA, 0x59, 0xBD, 0x38, 0x2F, 0x6F, 0x18,
+ 0x46, 0x9A, 0xB4, 0xE2, 0xE2, 0xA0, 0x95, 0x92, 0x8C, 0x56, 0x9B, 0x68, 0xDA, 0xBA, 0x5B, 0x69,
+ 0xD7, 0x6A, 0x5F, 0x89, 0xF6, 0x0B, 0xE2, 0x0F, 0x0F, 0x6A, 0xD6, 0x5E, 0x0A, 0xB3, 0x6D, 0x0B,
+ 0xC2, 0x9A, 0x6A, 0x59, 0x69, 0x3E, 0x16, 0xD6, 0x3C, 0x41, 0xAA, 0x6A, 0xFA, 0x47, 0xDA, 0x15,
+ 0x08, 0xFB, 0x6C, 0xAE, 0xD3, 0x89, 0x16, 0x52, 0x4A, 0x3E, 0xD8, 0x1A, 0x05, 0xDD, 0x1C, 0x78,
+ 0x5C, 0x29, 0x06, 0x16, 0x63, 0x4D, 0xD7, 0xA7, 0x56, 0x95, 0x38, 0x45, 0xC2, 0x36, 0xB6, 0xAA,
+ 0xFC, 0xAD, 0x5A, 0x57, 0x94, 0xA5, 0x79, 0xB4, 0x96, 0xB1, 0x50, 0x57, 0xD9, 0x69, 0xAE, 0x98,
+ 0x8C, 0x1B, 0xAB, 0xCD, 0x4E, 0x55, 0x5B, 0x72, 0x6E, 0xF7, 0xD1, 0xB8, 0xBD, 0x2D, 0xEE, 0xB8,
+ 0xBB, 0x25, 0x65, 0xAB, 0x93, 0xB6, 0x97, 0x30, 0x17, 0xC4, 0x3A, 0x4E, 0xA7, 0x63, 0x77, 0x79,
+ 0xAE, 0x68, 0x9A, 0x86, 0xA7, 0xE3, 0x1B, 0xDF, 0x12, 0xA6, 0xB9, 0x3F, 0x8B, 0x2F, 0xF5, 0xE9,
+ 0xAE, 0x60, 0xBB, 0xB4, 0x54, 0x22, 0x4B, 0x19, 0x6D, 0x1D, 0x0E, 0xF2, 0xD2, 0x95, 0x63, 0x31,
+ 0x94, 0xB6, 0x17, 0x6E, 0x39, 0xCD, 0x7D, 0x87, 0x0A, 0xE0, 0xF0, 0x79, 0xD5, 0x7C, 0x45, 0x7C,
+ 0x64, 0xA5, 0x49, 0x28, 0xF3, 0x54, 0x96, 0xEA, 0x51, 0x96, 0x8A, 0x31, 0xBA, 0x5C, 0xB1, 0xE6,
+ 0x49, 0x37, 0xAD, 0xA0, 0x9A, 0xBF, 0x6C, 0xAA, 0xC6, 0x74, 0x22, 0xA8, 0xD0, 0x71, 0xE5, 0x49,
+ 0x25, 0x1B, 0x7C, 0x2F, 0xBB, 0xB3, 0xED, 0xB2, 0xF4, 0x38, 0xFD, 0x56, 0xEE, 0xE3, 0x50, 0xBE,
+ 0xB8, 0xBC, 0xBB, 0x65, 0x33, 0xDC, 0x31, 0x96, 0x41, 0x1A, 0x04, 0x8D, 0x49, 0x3F, 0x2A, 0xAA,
+ 0xF6, 0x00, 0x60, 0x0E, 0xBC, 0x57, 0x8F, 0xC4, 0xB4, 0x2B, 0x51, 0xC4, 0x7D, 0x5F, 0x19, 0x52,
+ 0xF2, 0x84, 0x36, 0x5A, 0xD9, 0x26, 0xD4, 0x12, 0x57, 0x49, 0x45, 0x2B, 0x45, 0x36, 0xDB, 0x51,
+ 0xD5, 0x27, 0xD3, 0xAB, 0x0A, 0xA3, 0x1A, 0x71, 0x85, 0x3B, 0xD9, 0x24, 0x95, 0xDB, 0x7A, 0x24,
+ 0x95, 0xAE, 0xEE, 0xF4, 0x5A, 0x25, 0xB2, 0x49, 0x25, 0x64, 0x91, 0x99, 0x5F, 0x1E, 0x76, 0x8B,
+ 0xF2, 0xE0, 0x00, 0x31, 0x80, 0x07, 0x6C, 0x74, 0xEC, 0x31, 0xEC, 0x2B, 0x69, 0x3C, 0x37, 0xB2,
+ 0x4A, 0x9C, 0x64, 0xA7, 0xA6, 0xED, 0x34, 0xF4, 0xD6, 0xC9, 0x45, 0x35, 0xE5, 0xAB, 0xD3, 0x4E,
+ 0x84, 0x25, 0x24, 0xFA, 0x58, 0x9A, 0xDA, 0xDD, 0xA7, 0x75, 0x45, 0x1F, 0x2F, 0x00, 0xF4, 0x00,
+ 0x71, 0xC0, 0x1F, 0x95, 0x7D, 0x0F, 0x0A, 0xF0, 0xC6, 0x33, 0x89, 0x73, 0x0A, 0x78, 0x5C, 0x3C,
+ 0x3F, 0x77, 0x74, 0xA4, 0xF6, 0xE9, 0x7B, 0x27, 0x6B, 0x6C, 0xB5, 0xEC, 0xBE, 0x49, 0xE5, 0x5E,
+ 0xB4, 0x68, 0x43, 0x5D, 0xED, 0xA1, 0xE8, 0x1A, 0x6E, 0x9E, 0xB6, 0xF1, 0x20, 0x0B, 0x81, 0xB4,
+ 0x63, 0x20, 0x60, 0x71, 0xD7, 0x1F, 0xFD, 0x6A, 0xFF, 0x00, 0x4C, 0x3C, 0x2C, 0xF0, 0xDF, 0x0D,
+ 0xC3, 0xD9, 0x55, 0x0A, 0x74, 0xE1, 0x68, 0x59, 0x59, 0xCB, 0x55, 0x17, 0x64, 0xAF, 0xB2, 0x76,
+ 0x8F, 0x5D, 0x35, 0xEF, 0xD4, 0xF8, 0xDC, 0x66, 0x29, 0xD4, 0x93, 0xEF, 0xE4, 0x4F, 0xA9, 0xDC,
+ 0x9B, 0x68, 0x7C, 0xB4, 0x8B, 0x32, 0xE3, 0x0B, 0x81, 0xF2, 0x8C, 0x0E, 0x01, 0x1E, 0xF8, 0xAF,
+ 0x73, 0xC5, 0x5E, 0x2C, 0xAD, 0xC2, 0xF9, 0x27, 0xD4, 0x30, 0x98, 0x57, 0x2C, 0x63, 0x56, 0x8A,
+ 0x4B, 0xDD, 0x56, 0xDB, 0x9A, 0x37, 0x4D, 0xF3, 0xFD, 0x94, 0x9A, 0xB5, 0xD2, 0xE9, 0xA6, 0x58,
+ 0x1A, 0x0A, 0xBC, 0xD4, 0x9C, 0xBD, 0xDF, 0xEB, 0x6F, 0x43, 0x92, 0x39, 0x0F, 0x15, 0xC3, 0x09,
+ 0xD0, 0x46, 0x37, 0x4D, 0x3C, 0x41, 0x92, 0x58, 0xB9, 0xFF, 0x00, 0x55, 0xB7, 0x38, 0x07, 0xA5,
+ 0x7F, 0x19, 0xE2, 0x61, 0x5E, 0x8E, 0x61, 0x85, 0xE2, 0x5C, 0x62, 0xC4, 0x52, 0x8D, 0x2B, 0xCF,
+ 0x11, 0x88, 0xA5, 0xED, 0xA1, 0x5A, 0x8D, 0xE4, 0x9F, 0xD4, 0xF9, 0x1C, 0xDC, 0x54, 0xAC, 0xD3,
+ 0xBB, 0xF7, 0x5A, 0xD1, 0x45, 0x3B, 0x35, 0xF4, 0x10, 0xE5, 0xE4, 0x74, 0x69, 0xA8, 0xBB, 0xE8,
+ 0xA2, 0xEC, 0xD3, 0xD3, 0xE2, 0xDB, 0x6F, 0x4D, 0x8E, 0xD6, 0xDE, 0x7B, 0x7B, 0xA8, 0xE1, 0x96,
+ 0xD9, 0xC3, 0xC6, 0xA8, 0x15, 0x73, 0xF7, 0x94, 0xE3, 0xB8, 0xF5, 0x18, 0xAF, 0xEF, 0x2E, 0x1B,
+ 0xE2, 0x0E, 0x1C, 0xE2, 0xEC, 0x06, 0x0F, 0x39, 0xE1, 0x8C, 0x52, 0xAD, 0x86, 0x85, 0x3E, 0x58,
+ 0xF3, 0x36, 0xE7, 0x17, 0xA2, 0x7C, 0xDA, 0xB6, 0xAA, 0x45, 0xAB, 0x74, 0x51, 0xD5, 0x38, 0xB3,
+ 0xE6, 0x6A, 0xD1, 0xAB, 0x41, 0xCA, 0x95, 0x68, 0xDA, 0x57, 0xF9, 0x7C, 0xB6, 0xD0, 0xA8, 0xCA,
+ 0x2C, 0x66, 0x6B, 0xC6, 0x59, 0x1E, 0xCE, 0x62, 0x12, 0xE5, 0x21, 0xC0, 0x2A, 0xD8, 0xF9, 0x24,
+ 0x23, 0xA7, 0x04, 0x00, 0x7D, 0xAB, 0xE0, 0x73, 0x8C, 0x2D, 0x6E, 0x01, 0xCF, 0xA7, 0xC7, 0x74,
+ 0x69, 0x4A, 0xAE, 0x53, 0x89, 0x94, 0x69, 0xE2, 0xE3, 0x4D, 0x7B, 0xCA, 0x76, 0xF7, 0x71, 0x12,
+ 0xD9, 0x29, 0x5D, 0x46, 0x13, 0x93, 0x4D, 0x72, 0xD9, 0x5A, 0x36, 0x3B, 0x68, 0x3A, 0x78, 0x9A,
+ 0x4B, 0x0B, 0x51, 0xDA, 0x71, 0x4D, 0xC7, 0xB6, 0xDA, 0x2F, 0x4F, 0x24, 0x5D, 0x29, 0xF2, 0x2B,
+ 0x80, 0xBC, 0xE0, 0x80, 0xA0, 0x70, 0xA7, 0xA0, 0xFE, 0x55, 0xFA, 0x5D, 0x4C, 0x2C, 0xDE, 0x16,
+ 0x9E, 0x32, 0xE9, 0xB9, 0x59, 0xD9, 0x25, 0xA4, 0x25, 0xAC, 0x13, 0xDF, 0x5D, 0xB9, 0x9D, 0xBD,
+ 0x12, 0xB1, 0xC0, 0x9A, 0x5E, 0xEA, 0x5A, 0x7E, 0xAB, 0xFA, 0xD0, 0x88, 0xAF, 0x03, 0x80, 0x31,
+ 0x81, 0xC6, 0x71, 0xD3, 0x8E, 0x3F, 0x0A, 0xF2, 0x31, 0x18, 0x6A, 0x89, 0x45, 0x34, 0x92, 0xF2,
+ 0xBD, 0xBC, 0xBD, 0x3E, 0xE5, 0xDB, 0xA6, 0xBA, 0x45, 0xAD, 0x91, 0x0B, 0x46, 0x40, 0xE3, 0xF0,
+ 0x1C, 0x7E, 0x9F, 0x90, 0xAF, 0x0B, 0x11, 0x84, 0xA9, 0x05, 0xA2, 0xD1, 0xF4, 0xD3, 0x7D, 0x36,
+ 0xB7, 0x4B, 0x7E, 0x46, 0x91, 0x69, 0x59, 0x5B, 0x4F, 0xD0, 0x83, 0x68, 0xE9, 0x8E, 0x06, 0x30,
+ 0x00, 0x00, 0x0C, 0x76, 0xC5, 0x78, 0x9F, 0x57, 0x71, 0x4E, 0x9C, 0xF6, 0xD1, 0xAB, 0x6D, 0xA6,
+ 0x96, 0xB7, 0x4D, 0xD2, 0xE9, 0x7F, 0x2B, 0x58, 0xD1, 0x34, 0xED, 0xCA, 0x87, 0xB2, 0x92, 0xB1,
+ 0xB4, 0x6C, 0x62, 0x9E, 0x06, 0x59, 0x6D, 0xE6, 0x84, 0xEC, 0x96, 0x27, 0x46, 0x05, 0x19, 0x4F,
+ 0x6C, 0x10, 0x2B, 0x8B, 0x8A, 0xB8, 0x6B, 0x2F, 0xE2, 0xEC, 0x8E, 0xA6, 0x4F, 0x8D, 0x86, 0xF1,
+ 0x4A, 0x32, 0x86, 0x93, 0x4D, 0x34, 0xE3, 0xAE, 0xBA, 0x5D, 0x25, 0xB6, 0xDA, 0x7A, 0x3A, 0x15,
+ 0xA5, 0x42, 0x6A, 0x71, 0xDB, 0xB7, 0x4D, 0x8F, 0xE8, 0x0B, 0xF6, 0x16, 0xFD, 0xAB, 0x2C, 0x75,
+ 0xBD, 0x27, 0x4E, 0xB5, 0xD5, 0xAE, 0xE2, 0x8B, 0x57, 0xB1, 0x86, 0x3D, 0x37, 0xC4, 0x1A, 0x71,
+ 0x65, 0x49, 0x15, 0x90, 0xFC, 0xB3, 0xA2, 0x93, 0xF7, 0x5B, 0xEF, 0x2F, 0x6E, 0xA0, 0xF2, 0x31,
+ 0x5F, 0xC6, 0x38, 0xCC, 0xAB, 0x17, 0xC3, 0x78, 0xDA, 0x9C, 0x2B, 0x9E, 0x47, 0x92, 0xA4, 0x5B,
+ 0x74, 0xE5, 0xD2, 0x49, 0xDE, 0xCA, 0xFD, 0x1F, 0x4B, 0x24, 0xBA, 0x59, 0x6C, 0x8E, 0x3C, 0x6E,
+ 0x1F, 0xD9, 0x57, 0x58, 0xDC, 0x2A, 0xF7, 0x6D, 0xEF, 0x2B, 0x5F, 0x64, 0xAD, 0x6D, 0x3C, 0xAD,
+ 0xD7, 0x64, 0xDE, 0x88, 0xFD, 0x4F, 0xBC, 0xF0, 0x27, 0xC3, 0x5F, 0x88, 0xF7, 0x3A, 0x77, 0x89,
+ 0x5E, 0xDA, 0xCE, 0xF2, 0xF6, 0xD9, 0x52, 0x4B, 0x6B, 0x9B, 0x3B, 0xA3, 0x0D, 0xC4, 0x47, 0x00,
+ 0x85, 0x25, 0x09, 0x3C, 0x64, 0x70, 0x7A, 0x71, 0x9E, 0xBC, 0x14, 0x73, 0x1C, 0xD3, 0x2A, 0x84,
+ 0xB0, 0xF4, 0xDD, 0xA3, 0xE6, 0x93, 0x56, 0xEE, 0xAE, 0xB6, 0x76, 0xE9, 0x64, 0xED, 0xA2, 0xD0,
+ 0xE0, 0xAB, 0x96, 0xE5, 0xF9, 0x8C, 0x95, 0x48, 0xE9, 0x2F, 0x27, 0x6E, 0x9B, 0x69, 0x7D, 0x3D,
+ 0x34, 0x7A, 0xBB, 0x6E, 0x7A, 0x03, 0x78, 0x5F, 0x41, 0x97, 0x4B, 0x93, 0x45, 0x7D, 0x3A, 0x29,
+ 0x34, 0xD9, 0x62, 0x11, 0x4B, 0x6F, 0x22, 0x86, 0xF3, 0x50, 0x60, 0x01, 0x26, 0x73, 0xC0, 0x00,
+ 0x0E, 0x87, 0xA7, 0x3E, 0xFE, 0x6A, 0xC6, 0x62, 0x61, 0x56, 0x35, 0x94, 0xDF, 0x3A, 0xD9, 0xAE,
+ 0x8F, 0xCA, 0xD6, 0xDF, 0xCA, 0xDE, 0x5A, 0x6D, 0xDE, 0xB0, 0x38, 0x47, 0x45, 0xE1, 0xB9, 0x3D,
+ 0xC6, 0xB4, 0xEF, 0x6D, 0x16, 0xFB, 0x25, 0xDF, 0xD1, 0xF6, 0x39, 0xA8, 0xFC, 0x3D, 0xE0, 0x7F,
+ 0x03, 0xD8, 0x2B, 0xAC, 0x76, 0xFA, 0x75, 0x9D, 0xB0, 0x06, 0x38, 0x64, 0x94, 0x18, 0xA2, 0xE3,
+ 0xA4, 0x68, 0x7D, 0x48, 0x1E, 0xBF, 0x90, 0xAE, 0xB9, 0x62, 0xF3, 0x0C, 0xC6, 0x7C, 0xB2, 0x7C,
+ 0xCD, 0xF5, 0xB2, 0x5A, 0x2D, 0x35, 0x7A, 0x2B, 0x25, 0xA5, 0xB6, 0x56, 0xE8, 0x71, 0x47, 0x03,
+ 0x96, 0xE0, 0x60, 0xA2, 0x95, 0xA2, 0x96, 0x89, 0xB5, 0xFA, 0xD9, 0x5A, 0xFE, 0x8B, 0x6D, 0xF7,
+ 0x7F, 0x98, 0xBF, 0xB7, 0x17, 0xED, 0x59, 0xA0, 0xF8, 0x2B, 0xC2, 0xD7, 0xC2, 0xDE, 0xF2, 0x2F,
+ 0xB5, 0x35, 0xBB, 0x5A, 0x68, 0x9A, 0x54, 0x52, 0x01, 0x3D, 0xCC, 0xCC, 0xA4, 0x21, 0x31, 0xF6,
+ 0xC7, 0x3C, 0x9E, 0x80, 0x1E, 0x99, 0xE3, 0xC5, 0xCE, 0xB3, 0x2C, 0x3E, 0x07, 0x07, 0x3C, 0x1D,
+ 0x39, 0x5E, 0x6F, 0xE3, 0x92, 0xED, 0x67, 0xEE, 0xAD, 0xB5, 0x7F, 0xF0, 0x76, 0x8A, 0x3D, 0x1C,
+ 0xB7, 0x05, 0x5B, 0x1B, 0x8A, 0x8D, 0x6A, 0x8A, 0xD1, 0xD3, 0x95, 0x5A, 0xDA, 0x25, 0x6B, 0x3D,
+ 0x34, 0xB6, 0xB6, 0xD2, 0xDB, 0x68, 0xB6, 0x5F, 0x87, 0x7F, 0xB1, 0x36, 0xA3, 0x77, 0xAB, 0xFE,
+ 0xDD, 0xBF, 0xB2, 0x46, 0xAB, 0x7F, 0x29, 0x9A, 0xF7, 0x51, 0xFD, 0xAC, 0x3C, 0x05, 0x7B, 0x75,
+ 0x29, 0xFE, 0x39, 0x25, 0xF1, 0x75, 0x8B, 0x39, 0xC7, 0xD4, 0x9E, 0x2B, 0xF3, 0x4C, 0x15, 0x47,
+ 0x57, 0x35, 0xA3, 0x52, 0x5B, 0xBA, 0x91, 0x7E, 0x9E, 0xF2, 0xD1, 0x79, 0x25, 0xA2, 0xEC, 0x91,
+ 0xF7, 0x15, 0xA1, 0x1A, 0x78, 0x39, 0xC2, 0x2A, 0xC9, 0x45, 0xFE, 0x47, 0xFA, 0x04, 0x57, 0xE9,
+ 0xE7, 0xC8, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xF2, 0x31, 0xFF, 0x00, 0x05, 0x5D, 0xFD, 0x9F,
+ 0xFE, 0x31, 0x7C, 0x5A, 0xFD, 0xB9, 0x3E, 0x2B, 0xEB, 0xDF, 0x0E, 0x7E, 0x1F, 0x6B, 0xBE, 0x2D,
+ 0xD1, 0x74, 0xDD, 0x17, 0xC2, 0xDA, 0x1D, 0xEE, 0xA1, 0xA5, 0xC7, 0x17, 0xD9, 0x6D, 0xEE, 0xD3,
+ 0xC2, 0xDA, 0x7C, 0xAF, 0x6E, 0x59, 0xDD, 0x7E, 0x71, 0x15, 0xCD, 0xB3, 0x10, 0x3A, 0x09, 0x13,
+ 0xD6, 0xBD, 0x3C, 0x9F, 0x34, 0xC9, 0xF0, 0x58, 0x5C, 0x4E, 0x1B, 0x31, 0xAA, 0xA3, 0x27, 0x55,
+ 0xB4, 0x9A, 0x6F, 0xDD, 0x74, 0xA9, 0x24, 0xD5, 0x93, 0xB6, 0xA9, 0xAE, 0x9D, 0x7D, 0x0F, 0x5F,
+ 0x0B, 0x09, 0xBA, 0x10, 0x70, 0x5A, 0x25, 0xFA, 0xB3, 0xF3, 0x7E, 0x4F, 0xD8, 0xB3, 0xF6, 0xA2,
+ 0x65, 0x0B, 0xFF, 0x00, 0x0A, 0x5B, 0xC5, 0x98, 0xDA, 0x08, 0x1E, 0x5D, 0xAE, 0x30, 0x07, 0x6F,
+ 0xDE, 0xFF, 0x00, 0xB2, 0x78, 0xF6, 0xAC, 0xF3, 0x4C, 0xD3, 0x87, 0x71, 0x74, 0x9D, 0x07, 0x5A,
+ 0x2E, 0x29, 0x24, 0x97, 0x2C, 0x9F, 0x6E, 0xF1, 0xFB, 0xD5, 0x92, 0xED, 0xAA, 0x3A, 0xA0, 0xAA,
+ 0x53, 0x69, 0xF2, 0xFD, 0xDF, 0xF0, 0x3F, 0xA5, 0xF2, 0x33, 0x65, 0xFD, 0x8A, 0x3F, 0x6A, 0x44,
+ 0x20, 0x27, 0xC1, 0x6F, 0x16, 0xE3, 0x03, 0x8D, 0xB6, 0xBD, 0xFA, 0x00, 0x3C, 0xDE, 0x9C, 0x0F,
+ 0xD2, 0xBF, 0x2E, 0xCD, 0x70, 0x79, 0x7C, 0x67, 0x1F, 0xEC, 0xC9, 0xA7, 0x1D, 0x5B, 0xF8, 0x96,
+ 0xEF, 0x44, 0x93, 0x56, 0xB2, 0x5B, 0x6B, 0xEB, 0xB1, 0xD7, 0x4B, 0x11, 0x14, 0xAD, 0x3F, 0xCB,
+ 0xFE, 0x07, 0xF5, 0xD0, 0x8F, 0xFE, 0x18, 0xAB, 0xF6, 0xA7, 0xFF, 0x00, 0xA2, 0x29, 0xE2, 0xEF,
+ 0xFB, 0xE6, 0xD7, 0xFF, 0x00, 0x8E, 0xD7, 0x8D, 0xEC, 0x2A, 0x7F, 0x29, 0xB7, 0xB7, 0xA3, 0xDF,
+ 0xF0, 0x7F, 0xE4, 0x1F, 0xF0, 0xC5, 0x5F, 0xB5, 0x3F, 0xFD, 0x11, 0x4F, 0x17, 0x7F, 0xDF, 0x36,
+ 0xBF, 0xFC, 0x76, 0x8F, 0x61, 0x53, 0xF9, 0x43, 0xDB, 0xD1, 0xEF, 0xF8, 0x3F, 0xF2, 0x35, 0x34,
+ 0xFF, 0x00, 0xD8, 0xF7, 0xF6, 0xAB, 0xB2, 0x60, 0x0F, 0xC1, 0x6F, 0x17, 0xF9, 0x43, 0x18, 0x2A,
+ 0xB6, 0xA1, 0xA3, 0xC7, 0x42, 0x08, 0x97, 0xB6, 0x2B, 0xF6, 0x2F, 0x0E, 0xBC, 0x4E, 0xCC, 0x78,
+ 0x4A, 0x6F, 0x01, 0x98, 0xAE, 0x6C, 0x14, 0x92, 0x8B, 0xF7, 0x53, 0x71, 0x5A, 0x2D, 0x2C, 0xB6,
+ 0x4B, 0xEE, 0xD3, 0x46, 0xB6, 0xF3, 0xB1, 0x54, 0x30, 0xF5, 0x92, 0x95, 0x37, 0x69, 0x2F, 0x54,
+ 0x7E, 0xA4, 0x7C, 0x2C, 0xF0, 0xBF, 0xC6, 0x7F, 0x8A, 0x5F, 0x07, 0xEF, 0x7E, 0x00, 0xFE, 0xD4,
+ 0x9F, 0x0A, 0x3C, 0x77, 0x3D, 0xB5, 0xBD, 0xAB, 0x1F, 0x86, 0x3F, 0x13, 0x64, 0xB1, 0x8F, 0x50,
+ 0xBE, 0xF0, 0x55, 0xD4, 0x51, 0x95, 0x83, 0xED, 0x29, 0x0C, 0x9E, 0x64, 0xC8, 0x37, 0x15, 0xCB,
+ 0x02, 0x00, 0x20, 0xB6, 0x71, 0x5F, 0xD3, 0x9C, 0x3D, 0xC6, 0xDC, 0x1B, 0x57, 0x1B, 0x86, 0xCC,
+ 0xF8, 0x67, 0x1F, 0x4E, 0x9E, 0x2A, 0x32, 0x4E, 0x51, 0x92, 0x70, 0x5A, 0x6A, 0xED, 0x2A, 0x89,
+ 0x45, 0x37, 0x64, 0xB9, 0x61, 0x6D, 0x13, 0x5A, 0x69, 0x6F, 0xCD, 0xF3, 0x0C, 0x87, 0x31, 0xCB,
+ 0x31, 0x6F, 0x31, 0xC0, 0xD1, 0x95, 0x4A, 0x5D, 0x69, 0xA9, 0x5B, 0x96, 0xFB, 0xB8, 0xAB, 0xDE,
+ 0xCD, 0xA5, 0xCD, 0x15, 0x17, 0xD6, 0xF6, 0x4A, 0xCB, 0xE3, 0x2B, 0x2F, 0xD8, 0xCB, 0xF6, 0x96,
+ 0xB7, 0xF1, 0x0B, 0xE8, 0x8F, 0xF0, 0x9F, 0xC4, 0x77, 0x90, 0x49, 0x7C, 0xBA, 0x20, 0xD5, 0x2D,
+ 0xAC, 0x93, 0x53, 0x82, 0x44, 0x32, 0x84, 0x8E, 0x78, 0x6D, 0x92, 0x5D, 0xD2, 0xE0, 0x88, 0xD9,
+ 0x50, 0x2B, 0x13, 0xF2, 0x85, 0x52, 0x48, 0x07, 0xFB, 0x2A, 0x9F, 0x8C, 0x1C, 0x13, 0x89, 0xC1,
+ 0xC6, 0x78, 0xAC, 0xC2, 0x95, 0x3C, 0x5D, 0x38, 0x27, 0x38, 0xDA, 0x51, 0x4D, 0xB5, 0x78, 0xA5,
+ 0x51, 0x45, 0xD3, 0x84, 0x93, 0xB5, 0xDB, 0x6D, 0x26, 0xED, 0xA5, 0x82, 0xAE, 0x07, 0x1D, 0x3C,
+ 0x1A, 0xC4, 0x61, 0xA8, 0xB5, 0x24, 0x9C, 0x94, 0x3D, 0xD4, 0xEF, 0x6D, 0x62, 0xDB, 0x4D, 0xC6,
+ 0xFA, 0xAB, 0xA4, 0x9A, 0x5A, 0xDD, 0x6B, 0x6F, 0xE8, 0x1F, 0xC3, 0x5F, 0xB3, 0x67, 0x8E, 0xFF,
+ 0x00, 0xE0, 0x96, 0xBF, 0x0E, 0x7C, 0x3B, 0xA4, 0xE8, 0xFE, 0x19, 0xB7, 0xF8, 0xC9, 0xFF, 0x00,
+ 0x05, 0x0E, 0xF1, 0xF6, 0x8E, 0x1B, 0xC0, 0xBE, 0x2D, 0x97, 0x48, 0x17, 0x5F, 0x0B, 0x7F, 0x63,
+ 0x9F, 0x0F, 0xEA, 0xD1, 0x03, 0x1B, 0xC6, 0x5C, 0xB3, 0x5C, 0xF8, 0x8A, 0xE0, 0x3A, 0x91, 0x23,
+ 0xA0, 0x5B, 0x34, 0x72, 0xE9, 0x24, 0x52, 0x5B, 0xED, 0x97, 0xF9, 0x53, 0x36, 0xE3, 0x0C, 0x9F,
+ 0xC6, 0x4C, 0xEE, 0x75, 0x73, 0x27, 0x0C, 0x27, 0x0D, 0xE1, 0xAA, 0x45, 0xCA, 0x9D, 0xA4, 0xEB,
+ 0xE3, 0xA5, 0x09, 0x24, 0xD3, 0x95, 0xAD, 0x1A, 0x71, 0x8D, 0xEE, 0xA2, 0xEC, 0xF4, 0xE7, 0x84,
+ 0xF9, 0xBD, 0xCC, 0x29, 0xBC, 0xD3, 0x26, 0xCA, 0xB1, 0x15, 0xB0, 0x94, 0xEA, 0x39, 0x54, 0x51,
+ 0x75, 0x29, 0xC2, 0xAA, 0x70, 0x8B, 0x8A, 0x95, 0xAA, 0x72, 0xBB, 0x41, 0xCA, 0x11, 0xD5, 0x5A,
+ 0x17, 0x77, 0x49, 0x5E, 0xEE, 0xFF, 0x00, 0x91, 0xBE, 0x32, 0xF8, 0x37, 0xFB, 0x59, 0xDA, 0xF8,
+ 0x9B, 0xC4, 0x5A, 0x9C, 0x1E, 0x0B, 0xF1, 0x6F, 0x8D, 0xAE, 0x75, 0xFD, 0x5A, 0xE3, 0x56, 0xD5,
+ 0xBC, 0x51, 0xE2, 0x9B, 0x53, 0xAB, 0xEA, 0x9A, 0xAE, 0xA1, 0x73, 0x2E, 0xFB, 0xA2, 0x6F, 0x0D,
+ 0xD1, 0x79, 0xF7, 0x4B, 0x28, 0xCC, 0xD2, 0x28, 0x2D, 0x85, 0x20, 0x1D, 0xA0, 0x57, 0xEC, 0xD9,
+ 0x1E, 0x75, 0xE1, 0x46, 0x26, 0x82, 0xA7, 0x5A, 0xB4, 0x70, 0x94, 0x29, 0xA5, 0x18, 0x72, 0x3B,
+ 0x45, 0xA5, 0x75, 0x65, 0x17, 0x07, 0x64, 0x92, 0x76, 0x51, 0x6A, 0x29, 0x3B, 0x68, 0xB6, 0xFA,
+ 0x2E, 0x18, 0xE3, 0xEE, 0x34, 0xA5, 0x97, 0x61, 0xF0, 0x78, 0x8C, 0x14, 0x1C, 0x29, 0x45, 0x25,
+ 0x15, 0x68, 0xB7, 0x1F, 0xE6, 0x96, 0xBA, 0x49, 0xDD, 0xCA, 0xD7, 0xB3, 0x6D, 0xDD, 0x2B, 0xDD,
+ 0xF2, 0x53, 0xFC, 0x29, 0xFD, 0xAB, 0x5C, 0xB4, 0xF0, 0x7C, 0x19, 0xD7, 0xAD, 0x6E, 0xE5, 0xB9,
+ 0x32, 0x4D, 0x2A, 0x69, 0xB6, 0xAD, 0x1C, 0x25, 0x93, 0x25, 0x8B, 0x09, 0x10, 0x12, 0xA4, 0x9C,
+ 0x15, 0x63, 0xCA, 0xE4, 0x7D, 0xE1, 0x8F, 0x57, 0xEB, 0x9E, 0x15, 0x53, 0x5F, 0x57, 0xA9, 0x9C,
+ 0x27, 0x18, 0xC5, 0x2B, 0x25, 0x35, 0xD5, 0x59, 0x25, 0xCA, 0xDA, 0xD2, 0xD6, 0x8B, 0x8E, 0xD6,
+ 0x4E, 0xC8, 0xFB, 0x08, 0x78, 0x87, 0xC5, 0x0A, 0x2E, 0x1F, 0xD9, 0x94, 0xDC, 0x54, 0x5D, 0xAF,
+ 0x39, 0x6E, 0xB4, 0xD2, 0x29, 0xBD, 0xD5, 0x9A, 0x4F, 0x96, 0xE9, 0xA5, 0xA3, 0x5A, 0xB3, 0xC2,
+ 0x9F, 0xB3, 0xCF, 0xED, 0xC3, 0xE3, 0xFF, 0x00, 0x11, 0xD8, 0xF8, 0x76, 0xDB, 0xE1, 0xFE, 0xA3,
+ 0xE1, 0xB8, 0x6E, 0x1C, 0xCB, 0x7B, 0xAE, 0x6A, 0x16, 0x76, 0xD6, 0xDA, 0x3E, 0x83, 0x6A, 0x8C,
+ 0x0C, 0x97, 0x37, 0x6C, 0x8E, 0xED, 0x1C, 0x49, 0xB4, 0x92, 0xAA, 0xA4, 0x9C, 0x6D, 0x00, 0x9C,
+ 0x0A, 0xE6, 0xC6, 0x66, 0xFE, 0x0B, 0xE5, 0x38, 0x6F, 0xAD, 0x51, 0xC6, 0xC6, 0xBE, 0x25, 0x5F,
+ 0x92, 0x9A, 0xE7, 0x6E, 0x5A, 0x5A, 0xFA, 0xF2, 0xAD, 0xEC, 0xBB, 0x5E, 0xD6, 0xB3, 0x68, 0x78,
+ 0x8E, 0x3E, 0xE2, 0x25, 0x49, 0xB5, 0x87, 0xA7, 0x04, 0xAC, 0x9B, 0x49, 0xBE, 0x9A, 0xA4, 0xDC,
+ 0x9E, 0xB6, 0x5B, 0xAD, 0x56, 0xDA, 0x68, 0x7B, 0xA7, 0x8B, 0xF4, 0x3F, 0xDA, 0x17, 0xE1, 0x46,
+ 0x8F, 0x37, 0x80, 0x3F, 0x67, 0x9F, 0x85, 0xBE, 0x35, 0xD4, 0xF5, 0x9B, 0xCB, 0x59, 0xF4, 0x9F,
+ 0x88, 0x9F, 0x1E, 0x35, 0x26, 0x4B, 0x3D, 0x47, 0xC7, 0x6B, 0x2A, 0x6C, 0x96, 0xDF, 0x46, 0xB7,
+ 0x2F, 0x14, 0x96, 0x3A, 0x78, 0xC1, 0x00, 0x9D, 0xAE, 0xE0, 0x65, 0x80, 0xDC, 0xDB, 0xBE, 0x43,
+ 0x2A, 0xAD, 0xE1, 0xD6, 0x37, 0x16, 0xF3, 0x7E, 0x26, 0xC7, 0x51, 0xA6, 0xDB, 0x4E, 0x9D, 0x08,
+ 0xC1, 0xC9, 0x41, 0x47, 0xA4, 0xA4, 0xA2, 0xD4, 0xE7, 0x7D, 0x74, 0xBC, 0x63, 0x2B, 0x59, 0x4B,
+ 0x46, 0xBE, 0x5B, 0x38, 0xC7, 0x71, 0x36, 0x79, 0x08, 0x2C, 0x65, 0x69, 0x46, 0x29, 0x27, 0x18,
+ 0xC7, 0x96, 0x2E, 0x2D, 0x49, 0x49, 0x34, 0x95, 0xA2, 0x9A, 0x57, 0x8E, 0xB0, 0xE6, 0x69, 0xA4,
+ 0xDA, 0xB2, 0x8A, 0xF8, 0x3B, 0x4E, 0xFD, 0x94, 0x3F, 0x69, 0x9D, 0x3E, 0x61, 0x70, 0x3E, 0x09,
+ 0x6B, 0xF7, 0xB2, 0xBC, 0x32, 0x44, 0x53, 0x53, 0xB4, 0xB3, 0xBD, 0x81, 0x0B, 0x2E, 0x15, 0xA3,
+ 0x47, 0x90, 0xE1, 0x97, 0x2B, 0xC9, 0xCE, 0x08, 0x1E, 0x95, 0xFA, 0x55, 0x7F, 0x11, 0x7C, 0x3F,
+ 0x78, 0x49, 0x60, 0x70, 0xD9, 0x9D, 0x18, 0xD1, 0x49, 0x24, 0xB9, 0x67, 0xA6, 0xDD, 0xA2, 0xF4,
+ 0xB2, 0x7B, 0xBB, 0xBD, 0xAE, 0xA2, 0x71, 0x62, 0x70, 0x53, 0xC6, 0xC6, 0x9B, 0xC4, 0x4E, 0xAF,
+ 0x3A, 0xD6, 0x4D, 0x54, 0x8E, 0xB6, 0x56, 0x8A, 0x77, 0x4E, 0xF1, 0xB5, 0x93, 0x4F, 0xA2, 0xD2,
+ 0xCE, 0xD6, 0x4D, 0x33, 0xF6, 0x56, 0xFD, 0xAA, 0x74, 0x91, 0x2C, 0x70, 0xFC, 0x14, 0xD6, 0x6E,
+ 0xA1, 0x96, 0x64, 0x9D, 0xAD, 0x75, 0x1D, 0x2E, 0xC2, 0xFE, 0x04, 0x78, 0xF3, 0xB7, 0x62, 0x33,
+ 0xFC, 0x9C, 0xB1, 0x24, 0x2E, 0x01, 0xDA, 0xB9, 0x18, 0x5A, 0xF2, 0x71, 0x1C, 0x7B, 0xE1, 0xEB,
+ 0xA6, 0xD4, 0x73, 0x3A, 0x49, 0x2B, 0x3F, 0xB4, 0xEC, 0x95, 0xAC, 0xAE, 0xE0, 0xAE, 0xBF, 0x2E,
+ 0x89, 0x3D, 0x5E, 0x33, 0xCA, 0x7D, 0xAC, 0xA3, 0x27, 0x4D, 0xF3, 0x25, 0x64, 0xD4, 0xAC, 0xDA,
+ 0x6A, 0xD6, 0x6D, 0x3D, 0x74, 0xEF, 0x7E, 0xEB, 0x5D, 0x47, 0xA7, 0xEC, 0xB9, 0xFB, 0x56, 0x41,
+ 0x64, 0x96, 0xB6, 0x7F, 0x05, 0xB5, 0xAD, 0x3A, 0x48, 0xE6, 0x7B, 0x85, 0xD4, 0x74, 0xDB, 0x3B,
+ 0x3B, 0x0D, 0x4C, 0x09, 0x24, 0x0E, 0x53, 0xCF, 0x49, 0x81, 0xD8, 0x0A, 0x28, 0x0B, 0xFC, 0x20,
+ 0x00, 0x31, 0x8A, 0xF2, 0x6A, 0xF1, 0xEF, 0x00, 0x43, 0x9A, 0x3F, 0xDA, 0x70, 0x57, 0x6A, 0xEB,
+ 0x96, 0x4E, 0xFA, 0x59, 0x25, 0xEE, 0x5B, 0x6D, 0xAD, 0xAD, 0xB6, 0xD3, 0x62, 0xA6, 0x4D, 0xED,
+ 0x6A, 0xB9, 0x55, 0x8C, 0x9C, 0x6D, 0x67, 0x16, 0xEF, 0x06, 0xAD, 0x6B, 0x38, 0xB6, 0xD3, 0xD1,
+ 0xF5, 0xEB, 0xBB, 0xD1, 0x5A, 0x9D, 0xC7, 0xEC, 0xB3, 0xFB, 0x5A, 0xCD, 0x0C, 0x91, 0x37, 0xC2,
+ 0x9F, 0x1C, 0x01, 0x32, 0xFF, 0x00, 0xA4, 0xC8, 0x2F, 0x15, 0xA4, 0xB9, 0x0C, 0x41, 0x60, 0xE0,
+ 0xDC, 0x11, 0xCB, 0x80, 0x48, 0x00, 0x7C, 0xDE, 0x9D, 0x2B, 0xC4, 0xAD, 0xE2, 0x0F, 0x87, 0xB1,
+ 0x5C, 0x93, 0xCC, 0xA9, 0xBA, 0x6F, 0xDD, 0xE5, 0xE5, 0x97, 0x5B, 0x6F, 0x68, 0x27, 0xA2, 0x56,
+ 0x4D, 0xBB, 0x28, 0xDA, 0xDA, 0x1A, 0x53, 0xC9, 0xF9, 0x5D, 0xFD, 0x9A, 0x6B, 0xA2, 0xB4, 0x6C,
+ 0xB5, 0xBA, 0xB2, 0x49, 0x6D, 0xA7, 0x7B, 0x5B, 0x5D, 0x51, 0x97, 0x1F, 0xEC, 0x93, 0xFB, 0x5A,
+ 0xC0, 0x58, 0xDB, 0x7C, 0x2E, 0xF1, 0xE5, 0xBB, 0x15, 0x68, 0x4F, 0x93, 0x7D, 0x14, 0x25, 0xD5,
+ 0x80, 0x46, 0x43, 0x89, 0xC6, 0x41, 0x1B, 0x57, 0x1E, 0x9E, 0xC2, 0xBE, 0x5B, 0x19, 0xC7, 0xBC,
+ 0x03, 0x56, 0x2A, 0x94, 0x31, 0xF0, 0xB4, 0x75, 0x8A, 0x51, 0xA9, 0xB2, 0x57, 0x57, 0x4D, 0x59,
+ 0xD9, 0x75, 0xB2, 0xB7, 0xA2, 0x3B, 0xA1, 0x96, 0xA8, 0xC1, 0x25, 0x45, 0x72, 0xAE, 0x96, 0x8E,
+ 0xEB, 0xAA, 0x49, 0x7F, 0x4B, 0x63, 0x11, 0xFF, 0x00, 0x63, 0x1F, 0xDA, 0x87, 0x00, 0x8F, 0x82,
+ 0xFE, 0x2C, 0xC2, 0x83, 0x92, 0x16, 0xD7, 0x00, 0x0E, 0xBF, 0xF2, 0xD7, 0xB6, 0x2B, 0xE6, 0xAB,
+ 0x71, 0xFF, 0x00, 0x06, 0x24, 0x93, 0xC7, 0x42, 0xC9, 0x2F, 0xB3, 0x3F, 0x92, 0xB7, 0x2F, 0x9E,
+ 0x96, 0x5D, 0xED, 0xB3, 0x4B, 0xB1, 0x61, 0x6B, 0xBB, 0x25, 0x0D, 0x3E, 0x5D, 0x3F, 0xAF, 0xEB,
+ 0x42, 0x1F, 0xF8, 0x63, 0x4F, 0xDA, 0x8D, 0x0F, 0xEE, 0xFE, 0x0D, 0x78, 0xB9, 0x4F, 0x1C, 0xC7,
+ 0xF6, 0x55, 0x20, 0x13, 0x80, 0x09, 0x12, 0xF1, 0xCA, 0x91, 0x8F, 0x6F, 0x6A, 0xF9, 0xCC, 0x5F,
+ 0x1D, 0x70, 0x73, 0x72, 0x71, 0xC6, 0x45, 0xAB, 0xE9, 0x68, 0xCF, 0x6D, 0x1D, 0xAC, 0xA1, 0xDA,
+ 0xDA, 0x5B, 0x63, 0x78, 0xE1, 0x6B, 0x24, 0x93, 0x8E, 0xDE, 0x9F, 0x87, 0xFC, 0x0F, 0xC8, 0xEA,
+ 0x3C, 0x31, 0xFB, 0x1D, 0x7E, 0xD6, 0xFA, 0xAE, 0xB1, 0xA7, 0x69, 0x1F, 0xF0, 0x84, 0x78, 0xD3,
+ 0xC3, 0x90, 0x5E, 0x4C, 0xB6, 0xCB, 0xA9, 0x5E, 0x5E, 0x95, 0xB1, 0xB5, 0x62, 0x40, 0x51, 0x20,
+ 0x8A, 0x56, 0x65, 0x1C, 0x01, 0x9C, 0x60, 0x71, 0xD2, 0xBE, 0x7F, 0xFD, 0x61, 0xE0, 0xDC, 0xC3,
+ 0x10, 0xB0, 0x50, 0xC4, 0xD3, 0x4A, 0x56, 0xFB, 0x2D, 0x5D, 0x29, 0x46, 0xFA, 0xB8, 0xC5, 0x25,
+ 0xCB, 0xCC, 0xDB, 0x72, 0x49, 0x2D, 0xBA, 0x1C, 0x58, 0xBC, 0xBE, 0x94, 0x30, 0xB2, 0x75, 0x30,
+ 0xAA, 0xA4, 0x56, 0xAE, 0x36, 0x8B, 0xD3, 0xBD, 0x9E, 0x9A, 0x6F, 0xF2, 0xE8, 0xB5, 0x5E, 0xD3,
+ 0xE1, 0xAF, 0x80, 0x1F, 0xB6, 0xAF, 0x80, 0x75, 0x4B, 0x6B, 0x0B, 0x5D, 0x0F, 0xC6, 0xBA, 0x83,
+ 0xF8, 0x73, 0xE2, 0x14, 0x71, 0xDC, 0xCA, 0xD7, 0xD1, 0x5D, 0x69, 0x17, 0xF6, 0x4A, 0x55, 0x5E,
+ 0x54, 0xCB, 0x79, 0xD2, 0x44, 0x59, 0x98, 0x00, 0xAE, 0x4E, 0x06, 0xE0, 0xA0, 0x1E, 0x79, 0x5E,
+ 0x6D, 0xC2, 0x71, 0xE1, 0x9C, 0x56, 0x03, 0x19, 0x89, 0xA5, 0x1A, 0xB4, 0x73, 0x17, 0x3A, 0x4E,
+ 0x29, 0xC9, 0xBC, 0x3B, 0xA6, 0xE0, 0x9C, 0x7D, 0xD5, 0x17, 0x28, 0xC9, 0xDE, 0x50, 0x92, 0xB2,
+ 0xE5, 0xF7, 0xAE, 0x95, 0xA3, 0xE6, 0x4F, 0x2D, 0x4A, 0xAC, 0x1E, 0x1F, 0x08, 0xA3, 0x09, 0x51,
+ 0xB7, 0xBA, 0xB4, 0x52, 0x4E, 0xF1, 0x8B, 0x49, 0x72, 0xC7, 0x4B, 0xD9, 0xF5, 0x6D, 0xA5, 0x7D,
+ 0x19, 0x53, 0xC4, 0x3E, 0x0D, 0xFF, 0x00, 0x82, 0x83, 0xDA, 0x78, 0x8B, 0x58, 0x6D, 0x2B, 0xC2,
+ 0xBE, 0x2D, 0xBB, 0xB3, 0x3A, 0x9C, 0xD3, 0x5A, 0xCF, 0x6B, 0x61, 0x63, 0x3D, 0x91, 0x8E, 0x47,
+ 0xDE, 0x89, 0x17, 0x9A, 0x77, 0x61, 0x41, 0x03, 0xE6, 0xC9, 0x1D, 0x33, 0xC5, 0x7E, 0x67, 0x8F,
+ 0xAB, 0xC1, 0x34, 0xEA, 0x4A, 0x32, 0xAF, 0x79, 0x73, 0x36, 0xDF, 0xBC, 0xEF, 0x6B, 0xE9, 0x64,
+ 0xAC, 0x96, 0xDC, 0xC9, 0x2E, 0x5B, 0xDD, 0x47, 0x45, 0xAF, 0xB5, 0x82, 0xCA, 0x94, 0x30, 0x90,
+ 0x55, 0x20, 0xD3, 0xE5, 0x57, 0x5A, 0xAB, 0x3B, 0x2B, 0xE9, 0xA5, 0xAD, 0xB2, 0x5E, 0x47, 0xA5,
+ 0xFC, 0x3A, 0xB3, 0xFD, 0xB9, 0xB4, 0xCD, 0x27, 0x5C, 0xD6, 0xBC, 0x57, 0xF0, 0xC7, 0x5A, 0xD5,
+ 0xE2, 0xD1, 0xF5, 0x7D, 0x2A, 0x54, 0xF0, 0xC3, 0x69, 0x36, 0x70, 0x5D, 0xF8, 0x82, 0x09, 0x0C,
+ 0x82, 0xE0, 0xC7, 0x20, 0x73, 0x1A, 0xF9, 0x60, 0x46, 0xD9, 0x6D, 0xBC, 0x1E, 0x33, 0x92, 0x06,
+ 0x9C, 0x3D, 0xC4, 0x5C, 0x37, 0x94, 0xE5, 0xB9, 0xA4, 0xE8, 0x54, 0xFD, 0xF2, 0xAD, 0x85, 0xA9,
+ 0x49, 0x72, 0xC9, 0x45, 0xD3, 0x83, 0x92, 0xAB, 0x77, 0x67, 0xB5, 0xD7, 0x2C, 0x53, 0x8B, 0x6D,
+ 0x75, 0xD2, 0xDE, 0x5E, 0x69, 0x91, 0x57, 0xC4, 0xD5, 0xA3, 0x4B, 0x0A, 0x9A, 0x87, 0x24, 0xD4,
+ 0xA4, 0xDA, 0xD1, 0xD9, 0x38, 0xF6, 0x96, 0xBB, 0x5E, 0x29, 0xD9, 0x36, 0xAC, 0x91, 0x06, 0x9D,
+ 0x37, 0xED, 0x85, 0x19, 0x57, 0xBC, 0xFD, 0x9F, 0x3C, 0x50, 0x64, 0x69, 0x67, 0x73, 0x1D, 0x96,
+ 0x9B, 0xA5, 0x2C, 0x69, 0x13, 0x37, 0xEE, 0x02, 0x31, 0x91, 0x4E, 0x54, 0x10, 0x1B, 0xA0, 0xF4,
+ 0xEB, 0xC7, 0xCC, 0xCF, 0x17, 0xC3, 0x70, 0x6A, 0x4B, 0x15, 0x52, 0x49, 0xAE, 0x69, 0x59, 0xD9,
+ 0x5D, 0xB6, 0xED, 0x14, 0xE1, 0x65, 0x6B, 0x6B, 0x76, 0xFA, 0x25, 0x75, 0x76, 0x77, 0xC7, 0x25,
+ 0xE5, 0x51, 0x54, 0x92, 0x4A, 0xCA, 0xEA, 0xCD, 0x59, 0xA5, 0xD2, 0xC9, 0xDD, 0x37, 0xDD, 0x26,
+ 0x97, 0x7D, 0x0D, 0x19, 0x75, 0x4F, 0xDB, 0x58, 0x0B, 0x58, 0xB4, 0xBF, 0xD9, 0xC3, 0x5C, 0x9A,
+ 0x34, 0x85, 0xBE, 0xD0, 0x75, 0x38, 0x6D, 0xA2, 0xF9, 0xC8, 0x1B, 0x44, 0x62, 0x3B, 0x8C, 0x60,
+ 0x0E, 0xC7, 0x9A, 0xF6, 0x72, 0xAC, 0xB7, 0x86, 0x33, 0x5A, 0xF0, 0xA3, 0x2C, 0x45, 0x58, 0xB7,
+ 0x16, 0xDB, 0x6A, 0x09, 0x37, 0x18, 0xB7, 0x64, 0xDA, 0x82, 0x57, 0xB3, 0xF7, 0x5B, 0xBD, 0xAC,
+ 0xB7, 0x57, 0x2E, 0x79, 0x5D, 0x7A, 0x71, 0x4E, 0x12, 0x4B, 0x6D, 0x2D, 0x7E, 0xDB, 0x2B, 0xA6,
+ 0xB4, 0xD2, 0xFA, 0xFA, 0x25, 0xA0, 0xE8, 0x35, 0xCF, 0xDB, 0x41, 0x2D, 0xEE, 0x3E, 0xD3, 0xFB,
+ 0x2F, 0xDF, 0x49, 0x20, 0xDA, 0xB6, 0xD1, 0xAC, 0xB1, 0x34, 0x72, 0xB3, 0x30, 0xDC, 0xAE, 0xDE,
+ 0x78, 0xDB, 0xF2, 0x9C, 0x83, 0x86, 0x07, 0x81, 0x81, 0x9C, 0x8F, 0x26, 0xAD, 0x0E, 0x1D, 0xA3,
+ 0xC9, 0x37, 0x56, 0xA4, 0xA0, 0xEC, 0xD2, 0x4A, 0x29, 0xDA, 0xF6, 0xF7, 0x6F, 0x2B, 0x5E, 0xEB,
+ 0x76, 0xD5, 0x92, 0xBD, 0xAC, 0x8D, 0xBF, 0xB2, 0xAA, 0x37, 0x18, 0xDF, 0x47, 0xA5, 0xF6, 0xB2,
+ 0x49, 0xDB, 0x44, 0xAC, 0xF6, 0x4B, 0x4B, 0x77, 0xEC, 0x89, 0xE2, 0xD7, 0xBF, 0x6C, 0xA5, 0xE1,
+ 0xBF, 0x65, 0x0D, 0x46, 0x28, 0xCC, 0x04, 0xC4, 0xB1, 0x6A, 0xF0, 0xE4, 0xB0, 0x18, 0x48, 0xD8,
+ 0x19, 0x38, 0xE7, 0xA9, 0xC7, 0x00, 0xD7, 0x1E, 0x2D, 0xE4, 0x90, 0x49, 0xE0, 0x69, 0xD7, 0xE5,
+ 0xB6, 0x89, 0xCA, 0x83, 0x77, 0xFF, 0x00, 0xB7, 0x65, 0xA2, 0x4A, 0xDB, 0xA5, 0x6E, 0xD6, 0xB0,
+ 0xD6, 0x52, 0xF6, 0xE6, 0x76, 0xDB, 0x45, 0x64, 0xBC, 0xFE, 0x1D, 0x52, 0xD3, 0x4D, 0xDE, 0xD7,
+ 0xDA, 0xDE, 0x37, 0xF1, 0x73, 0xC0, 0x7F, 0xB5, 0xFF, 0x00, 0xC5, 0x5D, 0x1E, 0x3B, 0x0B, 0xDF,
+ 0xD9, 0xCF, 0x58, 0xD2, 0x06, 0xD5, 0x42, 0x6D, 0xAE, 0x21, 0xBA, 0x95, 0x48, 0x60, 0xC5, 0x46,
+ 0xE9, 0x02, 0xFF, 0x00, 0x08, 0xE7, 0xA7, 0x6E, 0xBD, 0x3E, 0x97, 0x0F, 0x5F, 0x86, 0x72, 0x4C,
+ 0xA6, 0x95, 0x78, 0x62, 0xDD, 0x5A, 0xD5, 0x21, 0x17, 0x3A, 0x4D, 0x72, 0x3A, 0x72, 0x69, 0x2E,
+ 0x55, 0x26, 0x9C, 0x24, 0x96, 0xD7, 0x8B, 0xB6, 0x9A, 0x6C, 0xCF, 0x32, 0x7C, 0x35, 0xED, 0x73,
+ 0x5A, 0x39, 0x85, 0x49, 0xBE, 0x5A, 0x5C, 0xDC, 0xA9, 0x2D, 0x1F, 0x32, 0xE5, 0x57, 0x7B, 0xD9,
+ 0x2B, 0x24, 0x92, 0x5D, 0x3A, 0x1D, 0xF7, 0x82, 0x47, 0xED, 0x57, 0xE0, 0xDF, 0x03, 0xAE, 0x83,
+ 0x17, 0xEC, 0xBF, 0xE2, 0x9B, 0xED, 0x6E, 0xCA, 0xE2, 0x2F, 0xB3, 0x5E, 0xB6, 0xA5, 0x6D, 0x6F,
+ 0xA5, 0xC9, 0x6E, 0x10, 0x09, 0x51, 0xE0, 0x04, 0xB8, 0x93, 0x76, 0xD2, 0x18, 0x30, 0x5C, 0x64,
+ 0x11, 0xEB, 0xE0, 0xF1, 0x0E, 0x6B, 0xC2, 0xD8, 0xF9, 0xAC, 0x46, 0x57, 0x3A, 0xB1, 0x94, 0x62,
+ 0xF9, 0xA3, 0x34, 0xA4, 0xA5, 0x25, 0xB2, 0x87, 0x2C, 0x52, 0x4B, 0xB3, 0x95, 0xBE, 0x57, 0x49,
+ 0x4E, 0x57, 0xC3, 0x71, 0xCB, 0x29, 0x3C, 0x32, 0xA9, 0xCD, 0x07, 0x26, 0xD3, 0x6B, 0x54, 0x9B,
+ 0x6E, 0xCF, 0xA3, 0x4B, 0xC9, 0x27, 0xB6, 0x87, 0xD4, 0xFF, 0x00, 0x09, 0x3E, 0x0A, 0x7E, 0xD9,
+ 0xDF, 0x16, 0x3E, 0x1E, 0x78, 0xB3, 0xE2, 0x19, 0xF0, 0x27, 0x82, 0x7E, 0x1D, 0xC1, 0xE1, 0x0B,
+ 0x99, 0xED, 0x2E, 0xBC, 0x39, 0xE2, 0xD5, 0xD5, 0xEE, 0xB5, 0x5B, 0xF5, 0x8A, 0xCB, 0xCE, 0x8E,
+ 0x58, 0x66, 0xB5, 0xB6, 0x92, 0x00, 0x24, 0x60, 0x22, 0x55, 0x67, 0x04, 0x36, 0x09, 0x01, 0x4D,
+ 0x7C, 0xBA, 0xAE, 0xAA, 0x51, 0x95, 0x6C, 0x34, 0x63, 0xC9, 0x1D, 0xD4, 0x9A, 0x8C, 0xAD, 0xA6,
+ 0xAA, 0x36, 0x77, 0x8E, 0xA9, 0x2E, 0xBE, 0x5A, 0x5C, 0xF6, 0x16, 0x53, 0x47, 0x48, 0xA9, 0xBD,
+ 0x7E, 0x5F, 0x24, 0xBC, 0xAD, 0xD2, 0xD6, 0xFC, 0x17, 0x90, 0xFC, 0x2A, 0xF8, 0xF1, 0xFF, 0x00,
+ 0x05, 0x25, 0xF8, 0x1F, 0xE3, 0x7D, 0x23, 0xE2, 0x2F, 0xC3, 0x2F, 0x81, 0x17, 0xBE, 0x1C, 0xF1,
+ 0x0D, 0x8D, 0xBB, 0xD9, 0x5C, 0x21, 0x78, 0xEF, 0x74, 0xED, 0x7A, 0xC6, 0xE5, 0x76, 0xDE, 0x69,
+ 0x5A, 0x9D, 0xA9, 0x98, 0x47, 0x73, 0x65, 0x3C, 0x65, 0x92, 0x5B, 0x79, 0x55, 0x91, 0x94, 0x9C,
+ 0x8C, 0x1C, 0x57, 0x4C, 0xEA, 0x61, 0x29, 0xE1, 0xE9, 0xD5, 0x55, 0xE3, 0xED, 0x1A, 0x4F, 0x95,
+ 0x6B, 0xCA, 0xEC, 0xAD, 0x19, 0x5A, 0x3A, 0x6B, 0xBA, 0xBF, 0x46, 0xD3, 0xE8, 0x4C, 0x72, 0xB5,
+ 0x4A, 0x49, 0xAA, 0x9E, 0xEF, 0x9C, 0x5B, 0xBA, 0xF9, 0x49, 0x59, 0x76, 0x56, 0x5E, 0x5D, 0x2D,
+ 0xF7, 0x57, 0xED, 0x1B, 0xF0, 0x9F, 0xE2, 0x8F, 0xC6, 0x9F, 0x83, 0x1A, 0x8F, 0xED, 0x87, 0xFB,
+ 0x1D, 0x7C, 0x16, 0xBA, 0xF0, 0x3D, 0xD6, 0x9F, 0x1C, 0x36, 0x9F, 0xB4, 0x7F, 0xEC, 0x85, 0xAD,
+ 0xE9, 0x12, 0x6A, 0x3A, 0x97, 0xC0, 0x7D, 0x56, 0xF9, 0x0A, 0xDB, 0x6B, 0x5E, 0x17, 0xD4, 0x84,
+ 0x8A, 0x35, 0x1D, 0x06, 0xEE, 0x68, 0x26, 0x65, 0x5C, 0x17, 0xB5, 0x3B, 0xCC, 0xBE, 0x4C, 0x61,
+ 0x11, 0x7D, 0xBE, 0x1A, 0xCD, 0x72, 0x3C, 0x0F, 0xD6, 0xEB, 0x66, 0x33, 0x77, 0x95, 0x0A, 0xB0,
+ 0x82, 0x8A, 0x6A, 0xD5, 0x64, 0xAD, 0x4B, 0x97, 0x7B, 0xC6, 0xFA, 0x36, 0xD4, 0x52, 0x5E, 0xF5,
+ 0xD3, 0xF7, 0x4E, 0x2C, 0x46, 0x59, 0xED, 0x2B, 0x28, 0x4E, 0x2D, 0x46, 0x4F, 0x46, 0xB9, 0x6D,
+ 0x65, 0x6B, 0xA7, 0x17, 0x14, 0x96, 0x9A, 0xD9, 0x75, 0x69, 0x45, 0x1F, 0x90, 0xF7, 0x30, 0xFF,
+ 0x00, 0xC1, 0x44, 0x6E, 0x31, 0xE5, 0xFC, 0x21, 0xBF, 0xB5, 0x50, 0xA0, 0x6D, 0x83, 0x45, 0xB4,
+ 0xC1, 0xC0, 0xF7, 0xB8, 0x3D, 0x78, 0xAF, 0x83, 0x79, 0x9E, 0x35, 0xC5, 0x46, 0x34, 0xE2, 0x97,
+ 0xA7, 0xA5, 0xBA, 0xF4, 0x6A, 0xEB, 0xFC, 0xB4, 0x3D, 0x3A, 0x59, 0x26, 0x55, 0x4D, 0x5B, 0x99,
+ 0xDF, 0xA6, 0xEA, 0xDF, 0x72, 0xFF, 0x00, 0x81, 0xF7, 0x23, 0xD3, 0xBE, 0x18, 0x6B, 0xFF, 0x00,
+ 0xB7, 0x25, 0x9B, 0xA7, 0x83, 0xBE, 0x31, 0x7C, 0x19, 0xF1, 0x97, 0x8C, 0x3E, 0x17, 0xDF, 0x07,
+ 0x87, 0xC8, 0xD3, 0x6C, 0xEC, 0x6C, 0xBC, 0x49, 0xE0, 0x39, 0xA5, 0xC8, 0x3A, 0xA6, 0x89, 0x38,
+ 0x94, 0x1F, 0x31, 0x0B, 0x06, 0x68, 0x18, 0x98, 0xE5, 0x0A, 0x54, 0x85, 0x27, 0x70, 0xDA, 0x86,
+ 0x6F, 0x8D, 0x52, 0xE5, 0xC4, 0xC5, 0xBA, 0x69, 0x5A, 0xC9, 0xDB, 0xB6, 0xD7, 0x7E, 0x56, 0xD7,
+ 0xBB, 0xB7, 0x44, 0x6D, 0x1C, 0xA7, 0x2B, 0x85, 0x17, 0x4D, 0xB7, 0x24, 0xD6, 0xCF, 0x4B, 0x7A,
+ 0x59, 0x2B, 0x69, 0xDA, 0xCB, 0x6E, 0xCA, 0xDE, 0x6D, 0xF1, 0x8F, 0xF6, 0x67, 0xFD, 0xBA, 0x7C,
+ 0x2B, 0xAD, 0x45, 0x2F, 0x84, 0xAE, 0x7C, 0x75, 0xF1, 0x13, 0xC0, 0x9A, 0xD4, 0x6D, 0x77, 0xE1,
+ 0x5F, 0x15, 0xE8, 0xB6, 0xF0, 0xE8, 0x4F, 0x2C, 0x41, 0xF8, 0xB7, 0xBF, 0xB4, 0x6D, 0x8F, 0x05,
+ 0xD2, 0x0C, 0xAB, 0xC6, 0x72, 0x32, 0x19, 0x94, 0xB2, 0x90, 0x4A, 0xAD, 0x8E, 0xCC, 0xE8, 0xCA,
+ 0x2E, 0x8D, 0x44, 0xE9, 0xDE, 0xE9, 0x59, 0x6C, 0xAD, 0xA6, 0x96, 0xB2, 0x5B, 0x69, 0xD3, 0x45,
+ 0x6D, 0x05, 0x0C, 0x9F, 0x26, 0xF6, 0x3C, 0x95, 0xA8, 0xEB, 0x6B, 0x27, 0xCD, 0x25, 0x65, 0x65,
+ 0x6B, 0xDB, 0x7D, 0x2E, 0xB9, 0x6F, 0xA3, 0xD7, 0x54, 0x8F, 0x2A, 0xF0, 0xE7, 0xC2, 0x7F, 0xF8,
+ 0x28, 0x17, 0x85, 0x5F, 0x58, 0x9F, 0x46, 0xF0, 0x67, 0xC4, 0xA8, 0xAE, 0xF5, 0xFF, 0x00, 0x0F,
+ 0x5F, 0xF8, 0x57, 0x55, 0xBA, 0xB9, 0xBC, 0x82, 0xFA, 0x5B, 0x8B, 0x0D, 0x4A, 0x25, 0x4B, 0xA8,
+ 0x00, 0x92, 0x76, 0x55, 0xCA, 0xA7, 0x0C, 0xA0, 0x32, 0xEE, 0x6C, 0x11, 0x93, 0x99, 0xFE, 0xD6,
+ 0xCC, 0x7E, 0xAE, 0xA8, 0xDB, 0xDE, 0xBB, 0x69, 0xE8, 0xAC, 0xAC, 0xAC, 0x92, 0x56, 0x5A, 0x35,
+ 0x77, 0x7B, 0xDF, 0x4D, 0x34, 0x46, 0xD0, 0xCB, 0xF2, 0xBA, 0x72, 0x52, 0xA3, 0x05, 0x17, 0x64,
+ 0x9D, 0xA3, 0xAB, 0x4B, 0xA3, 0xBA, 0x77, 0x4F, 0x66, 0xB6, 0xB1, 0xE4, 0xD3, 0x7E, 0xC6, 0xBF,
+ 0xB5, 0x8D, 0xC1, 0xCC, 0xFF, 0x00, 0x07, 0x7C, 0x6B, 0x39, 0xC6, 0x33, 0x34, 0x96, 0xF2, 0x1C,
+ 0x63, 0xA6, 0x4C, 0xD5, 0xE5, 0x4B, 0xEB, 0x73, 0x4A, 0x32, 0x94, 0x9A, 0xF3, 0x7F, 0xF0, 0x4E,
+ 0xEA, 0x7F, 0x52, 0xA4, 0x92, 0xA7, 0x18, 0xA5, 0xE5, 0x1B, 0x7E, 0x48, 0xAF, 0xFF, 0x00, 0x0C,
+ 0x55, 0xFB, 0x53, 0xFF, 0x00, 0xD1, 0x14, 0xF1, 0x77, 0xFD, 0xF3, 0x6B, 0xFF, 0x00, 0xC7, 0x6B,
+ 0x1F, 0x61, 0x53, 0xF9, 0x4D, 0x7D, 0xBD, 0x1E, 0xFF, 0x00, 0x83, 0xFF, 0x00, 0x20, 0xFF, 0x00,
+ 0x86, 0x2A, 0xFD, 0xA9, 0xFF, 0x00, 0xE8, 0x8A, 0x78, 0xBB, 0xFE, 0xF9, 0xB5, 0xFF, 0x00, 0xE3,
+ 0xB4, 0x7B, 0x0A, 0x9F, 0xCA, 0x1E, 0xDE, 0x8F, 0x7F, 0xC1, 0xFF, 0x00, 0x90, 0x7F, 0xC3, 0x15,
+ 0x7E, 0xD4, 0xFF, 0x00, 0xF4, 0x45, 0x3C, 0x5D, 0xFF, 0x00, 0x7C, 0xDA, 0xFF, 0x00, 0xF1, 0xDA,
+ 0x3D, 0x85, 0x4F, 0xE5, 0x0F, 0x6F, 0x47, 0xBF, 0xE0, 0xFF, 0x00, 0xC8, 0x3F, 0xE1, 0x8A, 0xBF,
+ 0x6A, 0x7F, 0xFA, 0x22, 0x9E, 0x2E, 0xFF, 0x00, 0xBE, 0x6D, 0x7F, 0xF8, 0xED, 0x1E, 0xC2, 0xA7,
+ 0xF2, 0x87, 0xB7, 0xA3, 0xDF, 0xF0, 0x7F, 0xE4, 0x3E, 0x2F, 0xD8, 0xA3, 0xF6, 0xA5, 0x77, 0x44,
+ 0x6F, 0x83, 0x1E, 0x2A, 0x85, 0x49, 0x00, 0xC8, 0xEB, 0x6D, 0xB2, 0x30, 0x07, 0x24, 0x85, 0x94,
+ 0x9E, 0xDD, 0x81, 0xAD, 0x21, 0x4A, 0x5C, 0xAA, 0x9C, 0xA0, 0x92, 0x6D, 0x6A, 0xEE, 0x9A, 0x4B,
+ 0xA6, 0x9A, 0x24, 0xFD, 0x1E, 0xCB, 0xA6, 0x84, 0xBA, 0xF4, 0x56, 0xB7, 0xD1, 0x74, 0x49, 0xFF,
+ 0x00, 0x91, 0xD4, 0xEB, 0xDF, 0xB1, 0x77, 0xED, 0x1B, 0x62, 0xB6, 0x3A, 0x66, 0x81, 0xF0, 0x97,
+ 0xC4, 0xBA, 0xCD, 0xBD, 0xBD, 0xB8, 0x96, 0x7D, 0x5E, 0x2D, 0x31, 0x74, 0xC6, 0xB8, 0x92, 0x4E,
+ 0x5A, 0x26, 0x8A, 0x59, 0xB2, 0x7C, 0xB2, 0x0A, 0x86, 0x00, 0x02, 0x30, 0x47, 0xBF, 0xDB, 0x50,
+ 0xE2, 0x8A, 0xB9, 0x6E, 0x55, 0x1C, 0xAF, 0x2D, 0x83, 0x71, 0xBE, 0xBC, 0xD6, 0xB3, 0xB6, 0x89,
+ 0xAB, 0x59, 0xAB, 0x2B, 0x2B, 0x5A, 0xDB, 0x6B, 0xEE, 0xA4, 0x71, 0x42, 0x95, 0x19, 0x55, 0x95,
+ 0x79, 0x4D, 0xEB, 0xD1, 0xAD, 0x12, 0x5B, 0x59, 0x6B, 0x6B, 0xF5, 0xDB, 0xB5, 0xB4, 0x39, 0x33,
+ 0xFB, 0x15, 0xFE, 0xD4, 0xE7, 0x9F, 0xF8, 0x52, 0xBE, 0x2E, 0xFF, 0x00, 0xBE, 0x6D, 0x7D, 0x38,
+ 0x00, 0x79, 0xDE, 0xC2, 0xBE, 0x32, 0xBB, 0xC4, 0xE2, 0x6A, 0xCA, 0xB5, 0x54, 0xDC, 0x9F, 0xF5,
+ 0x65, 0xE4, 0xB6, 0x4B, 0xA2, 0xD0, 0xEE, 0x85, 0x5A, 0x10, 0x8A, 0x8A, 0x7A, 0x2F, 0x2F, 0xF8,
+ 0x01, 0xFF, 0x00, 0x0C, 0x55, 0xFB, 0x53, 0xFF, 0x00, 0xD1, 0x14, 0xF1, 0x77, 0xFD, 0xF3, 0x6B,
+ 0xFF, 0x00, 0xC7, 0x6B, 0x0F, 0x61, 0x53, 0xF9, 0x47, 0xED, 0xE8, 0xF7, 0xFC, 0x1F, 0xF9, 0x02,
+ 0xFE, 0xC5, 0x3F, 0xB5, 0x39, 0x2A, 0xAB, 0xF0, 0x53, 0xC5, 0xD9, 0x38, 0x0A, 0x02, 0xDA, 0xFA,
+ 0x70, 0x00, 0xF3, 0x7D, 0xAA, 0xA1, 0x86, 0xA9, 0x29, 0x46, 0x16, 0xB5, 0xEC, 0xB5, 0xB2, 0x4B,
+ 0xA7, 0xF5, 0xE4, 0x1E, 0xDE, 0x8A, 0x49, 0x27, 0xF8, 0x3F, 0xF2, 0x3B, 0x4D, 0x2B, 0xF6, 0x21,
+ 0xFD, 0xA7, 0x6D, 0xA1, 0x43, 0x27, 0xC1, 0x9F, 0x16, 0x23, 0x30, 0x0E, 0xE0, 0xAD, 0xA9, 0xC6,
+ 0x00, 0xE9, 0xFB, 0xDE, 0xD9, 0x1F, 0x4A, 0xFE, 0xDF, 0xF0, 0x73, 0x07, 0xE1, 0xDE, 0x41, 0x91,
+ 0xD2, 0xC4, 0xE2, 0xF3, 0x08, 0x46, 0xAC, 0x9C, 0x5D, 0x45, 0xCB, 0x26, 0xD4, 0x9A, 0xB2, 0xB7,
+ 0xBB, 0x76, 0xB4, 0xB7, 0xBA, 0xAD, 0xA7, 0xDF, 0xF3, 0x98, 0xF9, 0xE2, 0x6A, 0x54, 0x71, 0x8C,
+ 0x34, 0xD9, 0x6D, 0xF7, 0x7E, 0x1B, 0x76, 0x47, 0x48, 0xBF, 0xB1, 0xDF, 0xED, 0x2F, 0x6A, 0x9E,
+ 0x6B, 0xFC, 0x19, 0xF1, 0x6B, 0x2C, 0x63, 0x6E, 0xD4, 0x8E, 0xD1, 0x8A, 0x92, 0xBF, 0x29, 0xDA,
+ 0x64, 0x20, 0x81, 0x8C, 0x9E, 0x3A, 0x0A, 0xFE, 0x9C, 0xCD, 0x7C, 0x59, 0xF0, 0xD3, 0x87, 0x72,
+ 0x9F, 0x6C, 0xB3, 0x28, 0x4A, 0x6E, 0x29, 0x45, 0x28, 0xD4, 0x6D, 0x5E, 0xC9, 0x4F, 0xDD, 0x8D,
+ 0xFD, 0xCD, 0x65, 0xBA, 0xBF, 0x2D, 0x92, 0x68, 0xF2, 0xF0, 0xF8, 0x2C, 0x44, 0xEB, 0x24, 0xE0,
+ 0xED, 0xE5, 0x6E, 0xDB, 0x6A, 0x9A, 0xED, 0xA5, 0xBE, 0xE3, 0x90, 0x97, 0xF6, 0x37, 0xFD, 0xA9,
+ 0xE5, 0x95, 0xA4, 0x6F, 0x82, 0xFE, 0x30, 0x56, 0x97, 0xF7, 0x45, 0xB6, 0xDB, 0x61, 0x63, 0x07,
+ 0x02, 0x6D, 0x9E, 0x6F, 0xD0, 0x00, 0x31, 0x8A, 0xFE, 0x2D, 0xCF, 0x3C, 0x44, 0xFE, 0xDD, 0xE2,
+ 0x58, 0xE7, 0x0F, 0x32, 0xF6, 0x70, 0xAC, 0xEA, 0xD0, 0xAB, 0x78, 0xD5, 0x9F, 0x35, 0x08, 0xA6,
+ 0xE1, 0x8E, 0x51, 0x4A, 0xCB, 0x95, 0x45, 0xDA, 0x9A, 0x8F, 0x3A, 0x4D, 0xDE, 0xCA, 0x37, 0x3D,
+ 0xBA, 0x78, 0x5F, 0x65, 0x4E, 0x34, 0xD4, 0x55, 0x92, 0xE6, 0x4A, 0xCB, 0x7B, 0x2F, 0x76, 0xFA,
+ 0x5B, 0xF2, 0x7A, 0x24, 0x49, 0x6B, 0xFB, 0x1A, 0x7E, 0xD4, 0x71, 0x8B, 0x58, 0x8F, 0xC1, 0xDF,
+ 0x1B, 0x47, 0x1D, 0xBC, 0xE1, 0xF1, 0x11, 0xB6, 0x12, 0xC6, 0x49, 0x01, 0xA5, 0x45, 0x32, 0xE0,
+ 0x96, 0x05, 0x06, 0x39, 0xC0, 0xC5, 0x63, 0x82, 0xE2, 0xBE, 0x1D, 0xA1, 0x94, 0x61, 0x30, 0x78,
+ 0x0C, 0xC9, 0xD3, 0xAB, 0x4A, 0xAF, 0x32, 0x9B, 0xF6, 0xD3, 0x9C, 0x1C, 0x54, 0xB9, 0xF1, 0x5E,
+ 0xCD, 0x46, 0xD5, 0x3E, 0xB1, 0x1E, 0x58, 0xBA, 0x49, 0xB7, 0x49, 0x2B, 0xD9, 0x37, 0x63, 0x49,
+ 0x47, 0x18, 0xAE, 0xE8, 0xAD, 0x52, 0xF7, 0x56, 0xC9, 0x5D, 0x2D, 0x34, 0x69, 0xAB, 0x77, 0x56,
+ 0xBA, 0xF2, 0x1B, 0xA2, 0xFE, 0xC7, 0xFF, 0x00, 0xB5, 0x45, 0xBC, 0xE2, 0xD1, 0xFE, 0x0A, 0xF8,
+ 0xA4, 0xDB, 0xEE, 0x67, 0x69, 0x59, 0x2D, 0x54, 0x82, 0x4F, 0x20, 0x9F, 0x3B, 0xDE, 0xBE, 0x9B,
+ 0xC0, 0xCF, 0x19, 0xBF, 0xD5, 0x8C, 0xF2, 0x8F, 0x06, 0xE3, 0xE7, 0x45, 0xE5, 0xD3, 0xA9, 0x39,
+ 0x7B, 0x69, 0xC6, 0x51, 0x97, 0x35, 0x49, 0xCA, 0x4D, 0x49, 0xDB, 0x5D, 0x5D, 0xD3, 0xB2, 0x4B,
+ 0x45, 0xBA, 0x39, 0xB3, 0x0C, 0x0C, 0x2B, 0x41, 0xD5, 0xA7, 0x7E, 0x74, 0xB6, 0x5B, 0x59, 0x24,
+ 0xBD, 0x11, 0xD5, 0xCF, 0xFB, 0x18, 0x7E, 0xD3, 0x4E, 0xB2, 0xC2, 0xDF, 0x06, 0x7C, 0x56, 0x23,
+ 0x64, 0x11, 0x3F, 0xCD, 0x68, 0xD1, 0xE0, 0x9C, 0x00, 0x3F, 0x7B, 0xEC, 0x31, 0xED, 0xED, 0x5F,
+ 0xD6, 0x79, 0xF7, 0x1D, 0xF8, 0x61, 0x9B, 0xC3, 0x13, 0x90, 0x55, 0xCC, 0x23, 0xEC, 0xAB, 0xC5,
+ 0xD1, 0x9A, 0x6D, 0xCA, 0x0D, 0x3B, 0x49, 0xD9, 0x28, 0x68, 0xD5, 0x95, 0xDB, 0xDB, 0x6B, 0xDF,
+ 0x43, 0xC4, 0xA3, 0x87, 0xC5, 0x53, 0xE5, 0xA8, 0xA3, 0xAA, 0xDB, 0x6E, 0xDF, 0x75, 0xBF, 0x0E,
+ 0x85, 0x0B, 0x4F, 0xD8, 0xDF, 0xF6, 0xA2, 0x0D, 0xF6, 0x39, 0x3E, 0x0C, 0xF8, 0xB3, 0xF7, 0x20,
+ 0x24, 0x6E, 0x12, 0xDB, 0x12, 0xA6, 0x7E, 0x42, 0xC7, 0xCD, 0xC0, 0xF4, 0xC7, 0xB5, 0x7C, 0x07,
+ 0x08, 0xF8, 0xA5, 0xC3, 0x18, 0x4C, 0x45, 0x5E, 0x0E, 0xCE, 0xB3, 0x18, 0xF3, 0x61, 0x14, 0xA3,
+ 0x09, 0xA5, 0x36, 0xAB, 0x51, 0x8A, 0xE6, 0x84, 0xE5, 0x25, 0x0E, 0x55, 0x28, 0xC6, 0xD0, 0xE5,
+ 0xBB, 0x6F, 0x97, 0x6D, 0x51, 0xD5, 0x5F, 0x07, 0x55, 0xC6, 0x35, 0xE9, 0xC3, 0x47, 0x6B, 0xAD,
+ 0x15, 0x9D, 0xB5, 0x4B, 0xBF, 0xCB, 0x62, 0x76, 0xFD, 0x8D, 0xBF, 0x69, 0xD0, 0x31, 0xFF, 0x00,
+ 0x0A, 0x6B, 0xC5, 0x43, 0x68, 0x1F, 0x2E, 0x2D, 0x46, 0x30, 0x3A, 0x63, 0xCD, 0x1D, 0xB1, 0xC7,
+ 0xA6, 0x2B, 0xE8, 0xEB, 0x78, 0x9F, 0xC0, 0x73, 0x84, 0x79, 0x33, 0x08, 0xF4, 0x4A, 0xD1, 0xA9,
+ 0xE9, 0x67, 0x68, 0xAF, 0x4B, 0x37, 0xF3, 0xDC, 0xCE, 0x38, 0x2C, 0x4A, 0x4B, 0xDC, 0xD3, 0xE5,
+ 0xFD, 0x7C, 0xAD, 0xB7, 0x90, 0xC3, 0xFB, 0x19, 0xFE, 0xD3, 0xF9, 0x20, 0x7C, 0x19, 0xF1, 0x57,
+ 0xCB, 0x90, 0x57, 0xFD, 0x10, 0x30, 0x00, 0xE3, 0x21, 0x7C, 0xEE, 0x9E, 0xF8, 0xC7, 0x07, 0xD3,
+ 0x8F, 0x23, 0x11, 0xE2, 0x5F, 0x03, 0x2F, 0x7D, 0x66, 0x10, 0xB3, 0x5A, 0x7B, 0xB3, 0xEB, 0xE4,
+ 0xA1, 0xA5, 0xBB, 0x5A, 0x36, 0x56, 0xD1, 0x68, 0x5A, 0xC2, 0xD6, 0x51, 0xD2, 0x3A, 0x2F, 0x4E,
+ 0x8B, 0xB7, 0xF5, 0xDB, 0xC8, 0x83, 0xFE, 0x18, 0xCB, 0xF6, 0xA1, 0x24, 0x2A, 0xFC, 0x18, 0xF1,
+ 0x6F, 0xCA, 0x07, 0xCB, 0xB2, 0xDB, 0x80, 0x46, 0x47, 0x1E, 0x6F, 0x70, 0x2B, 0xE7, 0xAB, 0x78,
+ 0x8F, 0xC1, 0x13, 0x92, 0x8C, 0x71, 0xF0, 0xB6, 0xAB, 0xE1, 0x9F, 0x7E, 0x96, 0x8A, 0x5D, 0x35,
+ 0xED, 0xA7, 0x95, 0xF5, 0x8E, 0x13, 0x11, 0x15, 0xF0, 0x69, 0xA7, 0x6F, 0xEB, 0xFE, 0x1A, 0xC2,
+ 0xAF, 0xEC, 0x65, 0xFB, 0x4F, 0xE0, 0x2F, 0xFC, 0x29, 0x9F, 0x15, 0x8D, 0xA7, 0x18, 0x02, 0xD7,
+ 0x3C, 0x11, 0xD0, 0x79, 0xBD, 0x3E, 0x61, 0x5D, 0x31, 0xF1, 0x1B, 0x81, 0x54, 0x23, 0x2A, 0x99,
+ 0x8C, 0x54, 0x55, 0xAD, 0xEE, 0xCD, 0xD9, 0xAD, 0x56, 0xD1, 0x7A, 0x75, 0xE9, 0x6F, 0x42, 0x56,
+ 0x0F, 0x11, 0xA5, 0xA1, 0xF9, 0x7C, 0xBF, 0x2F, 0xCB, 0xBA, 0x35, 0xB4, 0x7F, 0xD9, 0x6B, 0xF6,
+ 0xC4, 0xF0, 0x86, 0xA7, 0x6D, 0xE2, 0x4F, 0x0A, 0xFC, 0x2E, 0xF1, 0x96, 0x93, 0xAC, 0x59, 0x9D,
+ 0x91, 0x49, 0x6C, 0xD6, 0xBB, 0x25, 0x03, 0x19, 0x8A, 0x54, 0xF3, 0xB0, 0xC0, 0xE0, 0x0D, 0xA4,
+ 0x7A, 0x63, 0x9C, 0x57, 0xE6, 0x3E, 0x34, 0xE6, 0x3C, 0x19, 0xC6, 0x59, 0x42, 0xCC, 0xE9, 0x66,
+ 0x10, 0x58, 0xEA, 0x49, 0x7B, 0x34, 0xA3, 0x26, 0x9A, 0xB2, 0xD1, 0xBE, 0x54, 0x92, 0x76, 0xD7,
+ 0x6B, 0x6F, 0x75, 0xA3, 0x3A, 0x70, 0x54, 0x2A, 0x42, 0x4A, 0x94, 0xE9, 0xDE, 0x1F, 0x2B, 0xAF,
+ 0x4F, 0xEB, 0x6E, 0x87, 0xE8, 0x47, 0xC2, 0x7F, 0x8C, 0x1F, 0xB5, 0xEF, 0x86, 0x6D, 0x2D, 0xED,
+ 0x3C, 0x65, 0xFB, 0x3B, 0xFC, 0x45, 0x8A, 0xEE, 0xDD, 0x04, 0x4F, 0xAA, 0x78, 0x5E, 0xE6, 0xCD,
+ 0xD2, 0x72, 0xAB, 0x82, 0x5A, 0xDA, 0x49, 0xD7, 0x6E, 0x4A, 0x8E, 0x8C, 0xDD, 0xBF, 0x0F, 0xE5,
+ 0x4C, 0x2F, 0x15, 0xE2, 0xF0, 0xB0, 0xF6, 0x35, 0x63, 0xCF, 0x14, 0xED, 0x66, 0x94, 0x96, 0x8E,
+ 0xDA, 0x3D, 0x1B, 0x56, 0xD9, 0x34, 0xAC, 0xBA, 0xBD, 0x08, 0xC4, 0xF0, 0xFE, 0x0E, 0xAC, 0xB9,
+ 0xE8, 0xCF, 0x92, 0x5D, 0x5A, 0xBA, 0x7A, 0x2B, 0x2B, 0xD9, 0x34, 0xFB, 0x76, 0xB6, 0xDA, 0x33,
+ 0xE9, 0xA5, 0xFD, 0xA6, 0xBE, 0x3A, 0x2D, 0xBA, 0xAF, 0xFC, 0x29, 0xEF, 0x8E, 0x45, 0x92, 0x35,
+ 0x0B, 0x11, 0xF0, 0xEE, 0x96, 0xDC, 0xAA, 0xE0, 0x0F, 0x30, 0xDD, 0xFB, 0x01, 0xC6, 0x3E, 0xBC,
+ 0x66, 0xBD, 0x4F, 0xF5, 0xBB, 0x02, 0xE9, 0xB6, 0xF0, 0xD1, 0xE7, 0xD7, 0x4F, 0x7B, 0x7E, 0xC9,
+ 0x25, 0x6B, 0x75, 0xF8, 0x92, 0xFD, 0x38, 0x7F, 0xB0, 0x2B, 0xD9, 0x47, 0xEB, 0x12, 0xB5, 0xB7,
+ 0xD3, 0x4F, 0x35, 0xDB, 0xC9, 0x2B, 0x5A, 0xFA, 0x2D, 0x11, 0xF3, 0xD7, 0xC5, 0x1F, 0x8D, 0x5F,
+ 0xB5, 0x8E, 0xB9, 0x67, 0x71, 0x6F, 0xE0, 0xCF, 0xD9, 0xDB, 0xE2, 0x5D, 0xDD, 0xF4, 0x91, 0xEC,
+ 0x87, 0x54, 0xF1, 0x4C, 0xF6, 0x30, 0x43, 0x01, 0x20, 0x02, 0xEB, 0x6F, 0x1C, 0xEF, 0xD0, 0x0C,
+ 0x60, 0x10, 0x0F, 0x1C, 0xFA, 0x79, 0x78, 0xAE, 0x2D, 0xC5, 0x56, 0xA6, 0xE9, 0x50, 0x87, 0x2C,
+ 0x76, 0x6A, 0x29, 0x45, 0x7A, 0x5F, 0x57, 0x6F, 0x97, 0x96, 0xCC, 0xEE, 0xC1, 0xE4, 0x18, 0x3A,
+ 0x13, 0xF6, 0x95, 0x67, 0xCC, 0xF4, 0xD5, 0xA6, 0xFD, 0x6C, 0xAC, 0x92, 0xED, 0xA2, 0x7A, 0x5A,
+ 0xDD, 0x2D, 0xF9, 0x77, 0xE3, 0xAF, 0xD9, 0xB3, 0xF6, 0xD3, 0xF8, 0x91, 0xAD, 0xCD, 0xAF, 0xF8,
+ 0xBB, 0xE1, 0x57, 0x8D, 0x75, 0x3B, 0xE9, 0x32, 0xB1, 0x2B, 0xFD, 0x95, 0x6D, 0xAD, 0x10, 0x9C,
+ 0x88, 0xE1, 0x8F, 0xCE, 0xC2, 0xA8, 0xE0, 0x7A, 0xF0, 0x32, 0x78, 0xAF, 0x8D, 0xAF, 0x3C, 0x56,
+ 0x26, 0x4A, 0x55, 0x16, 0x9D, 0x17, 0x45, 0xFD, 0x7F, 0x92, 0xD9, 0x24, 0xBE, 0x92, 0x82, 0xC2,
+ 0x61, 0xE0, 0xA1, 0x4B, 0x45, 0xB6, 0xDF, 0xF0, 0x0D, 0x1F, 0xD9, 0x5B, 0xE1, 0x77, 0xC4, 0x0F,
+ 0x84, 0xFF, 0x00, 0xB7, 0xA7, 0xEC, 0x63, 0xE1, 0xFF, 0x00, 0x88, 0xBE, 0x13, 0xD5, 0x7C, 0x23,
+ 0xAB, 0xDE, 0x7E, 0xD2, 0xDF, 0x0F, 0x35, 0x3B, 0x3B, 0x1D, 0x56, 0x15, 0x8D, 0xEE, 0x6D, 0x9F,
+ 0xC5, 0xF6, 0x48, 0xB2, 0xC6, 0xCA, 0x4A, 0xB2, 0xEE, 0x8A, 0x45, 0xE0, 0xF0, 0x54, 0x83, 0xD2,
+ 0xAB, 0x2E, 0x83, 0x86, 0x63, 0x86, 0x4D, 0x5B, 0xDF, 0x87, 0xFE, 0x94, 0x8B, 0xAF, 0x28, 0x4B,
+ 0x09, 0x51, 0xC1, 0xE9, 0xCA, 0xFF, 0x00, 0x23, 0xFB, 0xD8, 0xAF, 0xD4, 0x4F, 0x90, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x0F, 0x67, 0xFD, 0x85, 0xFF, 0x00, 0x64, 0xDD, 0x37, 0xE3, 0xD8, 0xFD, 0xAE,
+ 0xBC, 0x5F, 0x75, 0xA5, 0xC5, 0x7D, 0x36, 0x93, 0xFB, 0x58, 0xDB, 0xF8, 0x50, 0x31, 0x85, 0x5D,
+ 0x91, 0x20, 0xF8, 0x31, 0xF0, 0xF2, 0xE1, 0x53, 0x3B, 0x49, 0x03, 0x3A, 0x83, 0x90, 0x3E, 0xB8,
+ 0xAF, 0x83, 0xCE, 0xEA, 0xAA, 0x79, 0x8D, 0x48, 0xDD, 0xAF, 0x87, 0x67, 0x65, 0xF0, 0xAE, 0xDF,
+ 0xD6, 0xC7, 0xD1, 0x65, 0xFF, 0x00, 0xEE, 0x90, 0x5C, 0xAB, 0xAF, 0x7E, 0xFE, 0x47, 0xDE, 0xA7,
+ 0xFE, 0x09, 0xAF, 0xE1, 0xE5, 0xDA, 0x06, 0x8D, 0x1F, 0x0B, 0x82, 0xEB, 0x65, 0x11, 0x19, 0x03,
+ 0xE5, 0x07, 0x81, 0xEC, 0x38, 0x1D, 0xBF, 0x2F, 0x29, 0x62, 0x22, 0x97, 0xC5, 0x2B, 0x5B, 0xBF,
+ 0xF5, 0xFD, 0x74, 0xD0, 0xEA, 0x53, 0x6E, 0xCA, 0x34, 0xD5, 0xBD, 0x5A, 0xB7, 0x6E, 0xBF, 0xF0,
+ 0xD6, 0x23, 0x6F, 0xF8, 0x26, 0xB7, 0x87, 0xB1, 0xB8, 0x68, 0x96, 0xED, 0x85, 0xC7, 0xCD, 0xA7,
+ 0xC2, 0x3A, 0x8E, 0x41, 0x3B, 0x4F, 0xBF, 0xA5, 0x4F, 0xB7, 0x85, 0xB4, 0x72, 0xD3, 0xCF, 0xF2,
+ 0xFF, 0x00, 0x80, 0x52, 0xA8, 0xD5, 0x97, 0xB3, 0x4B, 0xD1, 0xBB, 0x7E, 0x6B, 0xF4, 0xEC, 0x56,
+ 0x4F, 0xF8, 0x26, 0xBE, 0x81, 0x95, 0x5F, 0xF8, 0x47, 0x2D, 0xC0, 0xE0, 0x64, 0xD8, 0x42, 0x02,
+ 0x8E, 0x9D, 0x3C, 0xBF, 0x6A, 0x9F, 0xAC, 0x45, 0x2D, 0x1C, 0xBE, 0xFF, 0x00, 0xF8, 0x06, 0x8A,
+ 0x4D, 0x24, 0xB9, 0x57, 0xDF, 0x2F, 0xF3, 0x27, 0x1F, 0xF0, 0x4D, 0x3F, 0x0E, 0x71, 0x8D, 0x06,
+ 0xDB, 0x00, 0x76, 0xD3, 0xA2, 0xC7, 0x03, 0x80, 0x3F, 0x77, 0xF4, 0xFA, 0x54, 0xFD, 0x61, 0x2D,
+ 0x13, 0x7F, 0x7F, 0xFC, 0x02, 0x79, 0xDD, 0x92, 0x50, 0x5F, 0x7C, 0xBF, 0xCC, 0x6B, 0x7F, 0xC1,
+ 0x35, 0x3C, 0x3C, 0xA9, 0x95, 0xF0, 0xFD, 0xB1, 0xE8, 0x15, 0x7F, 0xB3, 0xA2, 0x53, 0x8E, 0x31,
+ 0xC7, 0x97, 0xC7, 0x51, 0xE9, 0x4E, 0x38, 0x85, 0xA2, 0xBB, 0xFB, 0xFF, 0x00, 0xE0, 0x02, 0xA8,
+ 0xF4, 0x5C, 0xAA, 0xDE, 0xB2, 0xFF, 0x00, 0x3F, 0x21, 0xD6, 0xFF, 0x00, 0xF0, 0x4D, 0xDD, 0x11,
+ 0x4E, 0x3F, 0xB0, 0x6D, 0xD5, 0x40, 0x0D, 0xFB, 0xCB, 0x28, 0xF0, 0x31, 0x8C, 0x00, 0x02, 0x2F,
+ 0xA0, 0x1C, 0xF6, 0xE3, 0xE9, 0xD1, 0x47, 0x1A, 0xE9, 0x49, 0x3A, 0x73, 0x69, 0xF7, 0xBE, 0xDE,
+ 0x9E, 0x7B, 0x79, 0xE8, 0xAC, 0x4B, 0x49, 0x46, 0xFC, 0x8B, 0x4E, 0xD7, 0xFF, 0x00, 0x35, 0xB1,
+ 0xEA, 0xDF, 0x0F, 0xBF, 0x60, 0xBF, 0x0D, 0xF8, 0x0A, 0xF0, 0xF8, 0xCA, 0xD7, 0x40, 0xB4, 0xB9,
+ 0xF1, 0x3E, 0x9A, 0x4C, 0x3E, 0x13, 0x8A, 0xEB, 0x4E, 0x82, 0xEE, 0xDB, 0x4C, 0x9D, 0xD7, 0x03,
+ 0x50, 0x96, 0x06, 0x5C, 0x33, 0x44, 0xAC, 0xDE, 0x59, 0xC8, 0x2B, 0x26, 0xC7, 0x1F, 0x74, 0x57,
+ 0xB9, 0x1E, 0x21, 0xAD, 0x52, 0x2A, 0x9C, 0xEB, 0x49, 0xAB, 0x25, 0x2B, 0xB6, 0xAE, 0xBA, 0xAD,
+ 0x1E, 0xCD, 0xF4, 0xB5, 0xAC, 0xB6, 0x38, 0xAA, 0xD2, 0xA9, 0x38, 0x25, 0xCB, 0xA3, 0xE8, 0x9B,
+ 0xB7, 0x4B, 0x6A, 0xDD, 0x96, 0x8A, 0xDA, 0x6A, 0xB6, 0xE8, 0x71, 0x97, 0xDF, 0xF0, 0x4F, 0x3D,
+ 0x3B, 0x51, 0xBF, 0xB8, 0xD5, 0x6F, 0x34, 0xEF, 0xB7, 0xEA, 0x9A, 0x85, 0xE3, 0xDE, 0xDF, 0x5E,
+ 0xEA, 0x10, 0x06, 0xBD, 0xBD, 0x9E, 0x57, 0x2F, 0x34, 0xF2, 0xCC, 0x41, 0x2E, 0xEC, 0xE7, 0x25,
+ 0x89, 0xC9, 0x27, 0x35, 0xEA, 0x47, 0x8A, 0x15, 0x2A, 0x71, 0x84, 0x26, 0xAD, 0x15, 0x64, 0xB6,
+ 0x49, 0x25, 0x65, 0x64, 0x93, 0x49, 0xE9, 0x65, 0x64, 0xB4, 0xEC, 0xB4, 0x08, 0xD3, 0x97, 0x2B,
+ 0x84, 0xE2, 0x94, 0x74, 0x56, 0x4D, 0xB5, 0x6D, 0xAD, 0x6B, 0xED, 0x6E, 0x9A, 0xEB, 0xE4, 0x32,
+ 0x2F, 0xF8, 0x27, 0x7E, 0x86, 0xE0, 0xC6, 0xFE, 0x1F, 0xB6, 0x48, 0xD9, 0x41, 0x78, 0xC5, 0x9A,
+ 0xC8, 0x91, 0xC8, 0x83, 0x0A, 0xF1, 0xA8, 0x00, 0x00, 0x40, 0x50, 0x71, 0xE8, 0xB8, 0xE8, 0x33,
+ 0xA5, 0x0E, 0x2E, 0x94, 0x1D, 0xE3, 0x51, 0xC6, 0x2F, 0x59, 0x2D, 0x34, 0x69, 0x68, 0xD7, 0x4D,
+ 0x6D, 0x67, 0xAA, 0xBE, 0xED, 0x6A, 0xCC, 0x6A, 0x61, 0x1A, 0x8A, 0x7C, 0xA9, 0xBD, 0x95, 0xDB,
+ 0xF8, 0x5F, 0x47, 0xBB, 0xF7, 0x7A, 0x25, 0xA6, 0xB6, 0x4A, 0xC3, 0x47, 0xFC, 0x13, 0xA3, 0xC3,
+ 0xFB, 0x4A, 0x0D, 0x19, 0x5B, 0x72, 0x88, 0xA2, 0x59, 0x34, 0xB8, 0x7C, 0x94, 0x19, 0xE4, 0x90,
+ 0x38, 0xE3, 0x91, 0xE9, 0xCF, 0xE7, 0xBA, 0xE3, 0x39, 0xA8, 0xBF, 0xDE, 0xBE, 0xE9, 0x72, 0xDB,
+ 0x7B, 0x74, 0xFC, 0xF4, 0x5B, 0x68, 0x9A, 0x12, 0xC2, 0xB7, 0x67, 0xEC, 0x63, 0x65, 0xFD, 0xE6,
+ 0xF4, 0xD3, 0x6F, 0xE9, 0x6D, 0x6D, 0x36, 0x34, 0xE6, 0xFF, 0x00, 0x82, 0x7D, 0xE8, 0xD6, 0x5A,
+ 0x71, 0xD2, 0x34, 0xDD, 0x0E, 0x14, 0xB7, 0xBB, 0x1B, 0xB5, 0x79, 0xC5, 0xA2, 0xA4, 0xBA, 0x87,
+ 0xCB, 0x8F, 0x29, 0x98, 0x03, 0x88, 0x4E, 0x4F, 0xC8, 0x00, 0x04, 0xF2, 0x41, 0x20, 0x63, 0x9A,
+ 0x3C, 0x59, 0x3A, 0x69, 0x35, 0x57, 0xDE, 0x7E, 0x6D, 0x25, 0xB6, 0xC9, 0xDF, 0xD2, 0xCA, 0xDA,
+ 0x68, 0xAC, 0x8D, 0x61, 0x42, 0x53, 0x6E, 0x55, 0x23, 0xB7, 0xC2, 0x95, 0xEC, 0xB4, 0xDD, 0x6D,
+ 0xAE, 0x9F, 0x2D, 0xBD, 0x31, 0x57, 0xFE, 0x09, 0xD7, 0xA2, 0x49, 0xF3, 0x49, 0xA3, 0x44, 0x8D,
+ 0x9E, 0x02, 0x59, 0x46, 0x5E, 0x31, 0x9C, 0xAE, 0xD3, 0x81, 0x8C, 0x64, 0x00, 0x01, 0x1D, 0x0E,
+ 0x08, 0xA7, 0xFE, 0xB6, 0x56, 0x92, 0x72, 0xA9, 0x57, 0xCA, 0xC9, 0xB7, 0xA2, 0x49, 0x74, 0xB7,
+ 0x65, 0xD1, 0xE9, 0xD9, 0x68, 0x57, 0xB0, 0x74, 0xEC, 0xA9, 0xC1, 0x25, 0xEA, 0xD7, 0xE0, 0x9D,
+ 0xAE, 0xDF, 0xF5, 0xA0, 0xA3, 0xFE, 0x09, 0xCD, 0xA0, 0x63, 0x3F, 0xD8, 0xC7, 0xB8, 0xC7, 0xF6,
+ 0x6C, 0x6B, 0x80, 0x7A, 0x0C, 0x76, 0x1F, 0x77, 0xB0, 0xEE, 0x3B, 0x52, 0x5C, 0x55, 0xAA, 0x8A,
+ 0xA8, 0xED, 0xE8, 0xFA, 0x25, 0x6F, 0xB5, 0x6D, 0x3D, 0x76, 0xB6, 0xDD, 0x05, 0x1A, 0xC9, 0x25,
+ 0xC8, 0x95, 0x97, 0xF3, 0x3B, 0x7A, 0x6C, 0x8A, 0xF2, 0x7F, 0xC1, 0x39, 0xF4, 0x54, 0x24, 0x0D,
+ 0x06, 0x07, 0x5D, 0xA7, 0x05, 0x6C, 0xD0, 0x6E, 0x07, 0xAE, 0x72, 0xBE, 0xC0, 0x63, 0xD8, 0x74,
+ 0xAE, 0x5A, 0xBC, 0x4D, 0x51, 0x7B, 0xAE, 0xA5, 0xD6, 0x8D, 0x59, 0xB5, 0x6B, 0x2B, 0x2D, 0x2F,
+ 0xD9, 0x25, 0xA6, 0xBF, 0x76, 0x9A, 0xC2, 0x9B, 0xB2, 0xD3, 0x5D, 0x36, 0x6D, 0xF9, 0xDB, 0x7E,
+ 0xFF, 0x00, 0xD2, 0xD0, 0x91, 0x7F, 0xE0, 0x9C, 0x9A, 0x17, 0x97, 0xB9, 0xB4, 0x38, 0xC3, 0x1C,
+ 0xE1, 0x52, 0xC1, 0x5C, 0x29, 0x00, 0x63, 0xE6, 0xE3, 0x81, 0xB7, 0x19, 0xC7, 0x7C, 0x7A, 0x54,
+ 0x2E, 0x21, 0x76, 0x4D, 0xD5, 0x76, 0x7B, 0xA5, 0x7F, 0xBA, 0xDC, 0xD1, 0x49, 0x6D, 0xA5, 0xB4,
+ 0xB6, 0x9A, 0x24, 0x94, 0xDA, 0xAC, 0x5A, 0x50, 0x8A, 0xB2, 0xB5, 0xBD, 0xE6, 0xAD, 0xA5, 0xAC,
+ 0x96, 0xB6, 0xD1, 0x58, 0x07, 0xFC, 0x13, 0x8B, 0xC3, 0xD8, 0x50, 0xBA, 0x2C, 0x4B, 0xC6, 0x33,
+ 0xF6, 0x08, 0xC2, 0x21, 0x00, 0x6D, 0x0A, 0x07, 0x61, 0x93, 0xD3, 0x18, 0xED, 0xC7, 0x35, 0x9F,
+ 0xF6, 0xEB, 0x6A, 0xCA, 0x6F, 0xA2, 0xEB, 0x6B, 0x5E, 0xFF, 0x00, 0xCD, 0xFA, 0x74, 0x5D, 0x6E,
+ 0x17, 0xAB, 0xD1, 0x2B, 0x7F, 0x89, 0xFF, 0x00, 0x4B, 0xA7, 0xCB, 0xB1, 0x55, 0xBF, 0xE0, 0x9C,
+ 0xBA, 0x12, 0x9C, 0x0F, 0x0E, 0xDB, 0x95, 0x52, 0x40, 0x3F, 0x66, 0x4C, 0x15, 0x1D, 0x80, 0xDB,
+ 0xD3, 0x1E, 0xDC, 0x7A, 0x57, 0x24, 0xF3, 0xD9, 0xB8, 0xB8, 0x39, 0x6D, 0xA2, 0xB3, 0xD3, 0x45,
+ 0xA7, 0x5E, 0x9D, 0xB6, 0xF2, 0xED, 0xB4, 0x61, 0x37, 0x15, 0xA3, 0xDB, 0x6B, 0xBD, 0x3F, 0x1E,
+ 0x9A, 0x6D, 0xE9, 0xB0, 0xF5, 0xFF, 0x00, 0x82, 0x6F, 0x78, 0x7B, 0xCB, 0x50, 0x74, 0x08, 0xB3,
+ 0xC0, 0x3B, 0x6C, 0x23, 0x28, 0x08, 0x1C, 0x0C, 0x9C, 0x1E, 0xCB, 0x9E, 0x0F, 0xE4, 0x6B, 0x29,
+ 0x66, 0x70, 0x92, 0x49, 0xCD, 0xED, 0xD3, 0xA6, 0x8B, 0xAE, 0x9F, 0x87, 0x6F, 0x24, 0x45, 0xEA,
+ 0x27, 0x68, 0xC3, 0x4F, 0x56, 0xBB, 0x74, 0xBF, 0x65, 0xA6, 0xDD, 0x3A, 0x00, 0xFF, 0x00, 0x82,
+ 0x6E, 0xF8, 0x77, 0x03, 0x67, 0x87, 0xA1, 0x52, 0x08, 0xE5, 0xF4, 0xF8, 0x99, 0x50, 0x02, 0x71,
+ 0x80, 0x07, 0x3D, 0x08, 0xE4, 0x7A, 0x66, 0xB9, 0x9E, 0x32, 0x12, 0x6D, 0x73, 0xBF, 0xC3, 0xFA,
+ 0xF3, 0x4B, 0xBF, 0x61, 0xC5, 0xCF, 0x4B, 0xD3, 0xFC, 0x5F, 0x6E, 0xC9, 0xFE, 0x5F, 0x81, 0x4C,
+ 0x7F, 0xC1, 0x38, 0x74, 0x5C, 0x04, 0x3E, 0x1D, 0xB4, 0xC1, 0xC2, 0x12, 0xD6, 0x80, 0xAA, 0xF2,
+ 0x01, 0xC6, 0x07, 0x0A, 0x39, 0xE9, 0xE9, 0xF9, 0xE0, 0xF1, 0x69, 0xDD, 0x5D, 0xDB, 0xCA, 0xDE,
+ 0x5F, 0xD7, 0x4E, 0xDB, 0x68, 0x6C, 0x96, 0xC9, 0x45, 0x7E, 0x3F, 0xD6, 0x9A, 0x7D, 0xDE, 0x96,
+ 0x97, 0xFE, 0x1D, 0xB1, 0xE1, 0xBD, 0xA8, 0xA7, 0x41, 0xB6, 0x50, 0x80, 0xFC, 0xA9, 0x60, 0x9D,
+ 0x08, 0xE0, 0x01, 0xC8, 0x1D, 0x00, 0x3D, 0x3F, 0x4A, 0x97, 0x88, 0xA7, 0x1D, 0x39, 0x9B, 0xB7,
+ 0x6D, 0xBE, 0x4D, 0xFF, 0x00, 0x49, 0x5A, 0xD7, 0x25, 0x4A, 0x56, 0xD2, 0x9A, 0x5F, 0x37, 0xF9,
+ 0x2F, 0xEB, 0xC9, 0x74, 0x63, 0x7F, 0xC1, 0x36, 0x7C, 0x3C, 0xAA, 0x4A, 0xE8, 0x51, 0x39, 0x03,
+ 0x84, 0x7B, 0x28, 0xD5, 0x70, 0x07, 0x0A, 0x40, 0x1D, 0x3A, 0x0F, 0xE5, 0xD6, 0xA7, 0xEB, 0x11,
+ 0x4B, 0x95, 0x49, 0xD9, 0x69, 0xAB, 0x6B, 0xA7, 0xF4, 0xBD, 0x3E, 0xE4, 0xE1, 0x37, 0xA2, 0xF6,
+ 0x6B, 0xE4, 0xDB, 0xFF, 0x00, 0x80, 0x97, 0xFC, 0x37, 0x6B, 0xB6, 0x1F, 0xF8, 0x26, 0xFE, 0x88,
+ 0x03, 0x47, 0xFD, 0x83, 0x6C, 0x11, 0xD5, 0x73, 0xE6, 0x5A, 0x28, 0x5E, 0x07, 0x00, 0x80, 0xA3,
+ 0xDC, 0x7F, 0xFA, 0xE8, 0x8E, 0x2F, 0x91, 0x38, 0xDD, 0xD9, 0xAB, 0x6E, 0xFF, 0x00, 0x0F, 0xD3,
+ 0xB7, 0x42, 0x9B, 0x8A, 0x49, 0xF2, 0x2B, 0x2F, 0x52, 0x55, 0xFF, 0x00, 0x82, 0x6D, 0xF8, 0x75,
+ 0x42, 0x81, 0xE1, 0xFB, 0x35, 0x03, 0x8D, 0x82, 0xC0, 0x04, 0x51, 0x9E, 0x00, 0x00, 0xE3, 0xD3,
+ 0xD2, 0x94, 0x71, 0x51, 0x56, 0xDE, 0xDE, 0xAF, 0xFC, 0xD7, 0xCA, 0xD6, 0xF4, 0xB2, 0x15, 0xE5,
+ 0xAF, 0xB8, 0xB6, 0xEF, 0xE4, 0xBC, 0x9D, 0xBF, 0x1D, 0x2D, 0xE8, 0x36, 0x4F, 0xF8, 0x26, 0xE6,
+ 0x80, 0xAA, 0x0C, 0x5A, 0x05, 0x91, 0x00, 0x11, 0xB3, 0xFB, 0x38, 0x8E, 0xAB, 0xC0, 0x03, 0x24,
+ 0x0C, 0x7C, 0xC3, 0x8C, 0x70, 0x07, 0xE1, 0xA4, 0x71, 0x6A, 0x09, 0x72, 0xB7, 0x6D, 0xAD, 0x76,
+ 0xBA, 0x5B, 0x6B, 0xBE, 0x9B, 0x59, 0x68, 0xBC, 0xF5, 0x14, 0x5F, 0x47, 0x04, 0xBD, 0x1B, 0xF2,
+ 0xED, 0x6F, 0xBB, 0xF3, 0x4A, 0xC3, 0x22, 0xFF, 0x00, 0x82, 0x6E, 0xE8, 0x4C, 0x76, 0x1F, 0x0F,
+ 0xDA, 0x22, 0xED, 0x18, 0x26, 0xC4, 0x12, 0x72, 0x41, 0x23, 0x18, 0x03, 0x3F, 0x40, 0x3D, 0x3B,
+ 0xD6, 0x71, 0xC5, 0x24, 0xB9, 0x53, 0x76, 0xF5, 0x7D, 0x2D, 0xFF, 0x00, 0x00, 0xA7, 0x64, 0x93,
+ 0x50, 0xD7, 0xB2, 0x6D, 0x79, 0x7C, 0xBF, 0x4D, 0x2C, 0x89, 0x87, 0xFC, 0x13, 0x67, 0xC3, 0x78,
+ 0x38, 0xD0, 0xAD, 0x41, 0x2A, 0x54, 0x63, 0x4E, 0x50, 0x79, 0xFC, 0x48, 0xEC, 0x07, 0x4A, 0x7F,
+ 0x5A, 0x8F, 0x46, 0xFF, 0x00, 0xAF, 0x9F, 0xF4, 0xBE, 0x44, 0xA9, 0x4D, 0x59, 0x7B, 0x35, 0x65,
+ 0xD2, 0xEE, 0xDF, 0x82, 0xF9, 0x69, 0x6E, 0x9E, 0x76, 0x85, 0xFF, 0x00, 0xE0, 0x9B, 0x7A, 0x12,
+ 0x84, 0xC6, 0x85, 0x6E, 0xEB, 0x8D, 0xA6, 0x35, 0xB2, 0x54, 0x18, 0x03, 0x39, 0xFB, 0xA7, 0xAE,
+ 0x0F, 0xF8, 0x0E, 0x00, 0x1E, 0x29, 0x59, 0x26, 0xDD, 0xBA, 0x6B, 0xFD, 0x7C, 0xBC, 0xBA, 0x58,
+ 0xA8, 0x35, 0xAA, 0x54, 0xD2, 0x7F, 0x3F, 0x2D, 0xBF, 0x2D, 0x3F, 0x30, 0x4F, 0xF8, 0x26, 0xCF,
+ 0x87, 0xE5, 0x50, 0x5B, 0xC3, 0xB6, 0x70, 0x95, 0x21, 0x1B, 0xCB, 0xD3, 0x93, 0x74, 0x80, 0xE3,
+ 0x25, 0xB7, 0x29, 0xCF, 0x4E, 0x9D, 0x28, 0xFA, 0xCC, 0x5C, 0x54, 0x6C, 0xD2, 0x5D, 0x9B, 0xBB,
+ 0xF5, 0xBB, 0xE9, 0xE4, 0x90, 0x73, 0x59, 0x24, 0xA3, 0x75, 0xD3, 0x57, 0xA7, 0xE5, 0x6E, 0xDF,
+ 0xA1, 0x20, 0xFF, 0x00, 0x82, 0x6C, 0xE8, 0x22, 0x36, 0x45, 0xD2, 0x63, 0x44, 0x60, 0x33, 0x0C,
+ 0x76, 0x51, 0xC7, 0x13, 0x60, 0x71, 0x94, 0x0B, 0x8E, 0xC3, 0xB7, 0x61, 0xE9, 0x50, 0xAB, 0xC1,
+ 0x25, 0x67, 0x2F, 0xBF, 0xCB, 0xFA, 0xFE, 0xB4, 0x05, 0x39, 0x68, 0x95, 0x35, 0x6F, 0x57, 0xF8,
+ 0x6B, 0xFD, 0x76, 0x2B, 0x4B, 0xFF, 0x00, 0x04, 0xD8, 0xD0, 0x54, 0xA2, 0xFF, 0x00, 0x60, 0x42,
+ 0xE0, 0x28, 0xC6, 0x2C, 0x62, 0xDA, 0xA3, 0x3C, 0x00, 0x0C, 0x67, 0x1D, 0x3F, 0x9F, 0xE0, 0x2C,
+ 0x44, 0x76, 0xBB, 0xB7, 0xAF, 0xA7, 0xF5, 0xFA, 0x0D, 0x4B, 0x4D, 0x20, 0x97, 0x4E, 0xBE, 0x5E,
+ 0x67, 0x79, 0xF0, 0xF7, 0xF6, 0x18, 0x97, 0xE1, 0xB6, 0xAE, 0x35, 0xEF, 0x0D, 0x58, 0x45, 0x6B,
+ 0x25, 0xD5, 0x9C, 0x9A, 0x46, 0xB1, 0xA6, 0x3D, 0x82, 0x4B, 0xA6, 0x6B, 0xFA, 0x74, 0xCB, 0xB6,
+ 0xEB, 0x4F, 0xBF, 0xB7, 0xDA, 0x12, 0x7B, 0x69, 0x54, 0xA8, 0x68, 0x9C, 0x6D, 0x38, 0x5C, 0x8E,
+ 0x29, 0xFD, 0x62, 0x2A, 0x0D, 0x6B, 0xF7, 0xEC, 0xBF, 0x4E, 0x9A, 0x75, 0x5D, 0x6C, 0x65, 0x36,
+ 0xA6, 0xD4, 0x1C, 0x16, 0x96, 0xB3, 0xBB, 0xDF, 0x4B, 0x35, 0xAF, 0x4E, 0x8D, 0x6D, 0xF2, 0x31,
+ 0xBC, 0x4B, 0xFF, 0x00, 0x04, 0xD1, 0xF0, 0x29, 0xD5, 0xA5, 0xB8, 0xD0, 0x34, 0x18, 0x53, 0x48,
+ 0xBF, 0x02, 0xF6, 0xD2, 0xD2, 0x5D, 0x36, 0xDC, 0x4F, 0xA5, 0x89, 0x0E, 0x5A, 0xD6, 0x40, 0x91,
+ 0x85, 0xF9, 0x3A, 0x02, 0xA0, 0x0C, 0x63, 0x1D, 0x2A, 0x3E, 0xB1, 0x15, 0xB3, 0x76, 0xF2, 0x7F,
+ 0xA7, 0x4F, 0x4F, 0xD2, 0xC5, 0xC2, 0x75, 0x14, 0x23, 0xCD, 0x15, 0x7E, 0xBA, 0xBF, 0xC3, 0x54,
+ 0xAC, 0x73, 0x27, 0xFE, 0x09, 0xB1, 0xA0, 0x03, 0x81, 0xE1, 0xB8, 0x08, 0x07, 0x03, 0x1A, 0x7C,
+ 0x40, 0x11, 0xD8, 0xE3, 0xCA, 0xFA, 0x55, 0x2A, 0xF1, 0xB5, 0xB9, 0x9F, 0xDF, 0xFF, 0x00, 0x02,
+ 0xC5, 0xA9, 0x3B, 0x2F, 0x75, 0x5B, 0xD6, 0x5F, 0xE6, 0x6C, 0xD8, 0x7F, 0xC1, 0x39, 0xB4, 0x1B,
+ 0x7B, 0x79, 0x6C, 0x2E, 0x34, 0x28, 0xA6, 0xD3, 0x6E, 0x80, 0x69, 0xAD, 0x05, 0x84, 0x72, 0x2C,
+ 0x0E, 0x07, 0xCB, 0x34, 0x69, 0xB0, 0x00, 0xE3, 0xA6, 0x46, 0x32, 0x38, 0xEF, 0x4A, 0x38, 0x88,
+ 0xA6, 0xAE, 0xDD, 0xB4, 0x57, 0xBE, 0xC9, 0x79, 0x69, 0xF7, 0x7F, 0xC3, 0x12, 0xE7, 0x24, 0xAD,
+ 0x18, 0xAB, 0xFA, 0xBD, 0x7C, 0xB7, 0xD3, 0xFC, 0xBC, 0xB4, 0x28, 0x49, 0xFF, 0x00, 0x04, 0xD0,
+ 0xF0, 0xDC, 0x72, 0x14, 0x4D, 0x0E, 0xD9, 0x93, 0xFE, 0x59, 0xB9, 0xD3, 0x22, 0x04, 0xAE, 0x46,
+ 0x32, 0xA2, 0x33, 0x83, 0xC8, 0xE0, 0x7F, 0x4E, 0x07, 0x5E, 0x29, 0xDA, 0x2D, 0xDB, 0xD6, 0xDF,
+ 0xA6, 0x82, 0x55, 0x65, 0xCA, 0x9B, 0x82, 0xDB, 0xA3, 0x93, 0xB7, 0x96, 0xE8, 0xAB, 0xFF, 0x00,
+ 0x0E, 0xD8, 0xF0, 0xF8, 0x6D, 0xA3, 0xC3, 0x96, 0xD8, 0x1C, 0x67, 0xEC, 0x11, 0x05, 0xC0, 0x1C,
+ 0x63, 0xF7, 0x7E, 0x98, 0xA1, 0x57, 0x8D, 0x97, 0xBC, 0xFE, 0xFF, 0x00, 0xF8, 0x06, 0xAA, 0x4F,
+ 0x44, 0xA0, 0xAD, 0xEB, 0x2F, 0xF3, 0x27, 0xFF, 0x00, 0x87, 0x69, 0xF8, 0x70, 0x00, 0x06, 0x83,
+ 0x6B, 0xD0, 0x63, 0x1A, 0x74, 0x40, 0x74, 0x18, 0x03, 0xF7, 0x63, 0xB1, 0x15, 0x3F, 0x58, 0xB2,
+ 0xDD, 0xDB, 0xD7, 0xFE, 0x01, 0x0A, 0xA3, 0xB6, 0x90, 0x56, 0xF5, 0x97, 0xE5, 0x71, 0xA7, 0xFE,
+ 0x09, 0xA9, 0xE1, 0xD0, 0xA7, 0x1A, 0x05, 0xB7, 0xCA, 0x38, 0x53, 0xA7, 0xC2, 0xA0, 0x91, 0xD1,
+ 0x41, 0xF2, 0xFE, 0x94, 0x2C, 0x46, 0x9A, 0x37, 0xF7, 0xFF, 0x00, 0xC0, 0x05, 0x51, 0xE8, 0xB9,
+ 0x15, 0xBC, 0x9C, 0xBF, 0xCC, 0x89, 0x3F, 0xE0, 0x9B, 0x1E, 0x1F, 0x24, 0x2F, 0xFC, 0x23, 0x96,
+ 0xCA, 0x38, 0x19, 0x36, 0x11, 0x60, 0x74, 0xE0, 0x01, 0x17, 0xB8, 0xE9, 0xFD, 0x2A, 0xBE, 0xB1,
+ 0x14, 0x95, 0xA4, 0xFE, 0xFB, 0x7E, 0x9A, 0x15, 0xCC, 0xD6, 0x9C, 0xAB, 0xE4, 0xE5, 0xFE, 0x64,
+ 0xE3, 0xFE, 0x09, 0xA7, 0xE1, 0xCC, 0x0C, 0x78, 0x7E, 0x0E, 0xC0, 0x01, 0xA6, 0xC4, 0x3A, 0x8E,
+ 0x01, 0x1E, 0x5F, 0x1D, 0xAA, 0x7E, 0xB0, 0x96, 0x97, 0x76, 0xF5, 0xFF, 0x00, 0x80, 0x4A, 0xA8,
+ 0xEC, 0xBD, 0xD5, 0x6F, 0x59, 0x7F, 0x9F, 0x41, 0x8D, 0xFF, 0x00, 0x04, 0xD5, 0xF0, 0xEA, 0x26,
+ 0x57, 0xC3, 0xF6, 0xCD, 0x8C, 0x00, 0xA3, 0x4E, 0x88, 0x1C, 0x63, 0xFE, 0xB9, 0xFB, 0x0A, 0xA5,
+ 0x5D, 0x75, 0x6E, 0xDE, 0xBF, 0xF0, 0x3F, 0xAF, 0xB8, 0x6A, 0x6F, 0x6E, 0x45, 0xF7, 0xCA, 0xDF,
+ 0x9F, 0xF5, 0xF2, 0x1B, 0x1F, 0xFC, 0x13, 0x5F, 0xC3, 0xCD, 0xC1, 0xF0, 0xED, 0xB4, 0x60, 0x28,
+ 0x3F, 0x35, 0x84, 0x20, 0x75, 0xC0, 0x03, 0xF7, 0x7E, 0xD4, 0x7B, 0x78, 0xE8, 0x94, 0x9F, 0xDF,
+ 0xFF, 0x00, 0x00, 0x39, 0xDA, 0x8D, 0xF9, 0x55, 0xBD, 0x65, 0xFE, 0x64, 0xBF, 0xF0, 0xED, 0x3F,
+ 0x0E, 0x05, 0xCF, 0xF6, 0x05, 0xB8, 0x00, 0x1E, 0x06, 0x99, 0x17, 0x18, 0x38, 0xC7, 0xFA, 0xBF,
+ 0x61, 0xFE, 0x45, 0x25, 0x88, 0x49, 0x25, 0x77, 0xF7, 0xFF, 0x00, 0xC0, 0x12, 0xA8, 0xF6, 0xE4,
+ 0x5F, 0x7C, 0xBF, 0xCF, 0xFA, 0xF2, 0x23, 0x7F, 0xF8, 0x26, 0xAF, 0x87, 0x90, 0x0D, 0xBE, 0x1E,
+ 0xB6, 0x6E, 0x71, 0xB4, 0x69, 0xD1, 0x29, 0x00, 0x0E, 0x0E, 0x3C, 0xBA, 0x6A, 0xBA, 0xB2, 0xD5,
+ 0xDB, 0xD7, 0xFE, 0x00, 0x2A, 0x8D, 0xE8, 0xA0, 0xAD, 0x6E, 0xF2, 0xB7, 0x6E, 0xFF, 0x00, 0xD7,
+ 0xE5, 0x25, 0xBF, 0xFC, 0x13, 0x5B, 0xC3, 0x83, 0x12, 0x3F, 0x87, 0xED, 0xD4, 0x47, 0x82, 0x10,
+ 0x69, 0xF0, 0x92, 0x71, 0xD3, 0x23, 0x60, 0xC7, 0x41, 0xDF, 0xB5, 0x6F, 0x87, 0xAB, 0x4F, 0x99,
+ 0x39, 0x49, 0xF2, 0xAB, 0x3D, 0xF7, 0xF2, 0x4B, 0x6B, 0x7E, 0x16, 0xD0, 0x9A, 0x93, 0x94, 0x62,
+ 0x94, 0x62, 0xB6, 0xEE, 0xD2, 0xB5, 0xBD, 0x7A, 0x79, 0x1A, 0xC3, 0xFE, 0x09, 0xC3, 0xE1, 0xC5,
+ 0x04, 0x1D, 0x05, 0x14, 0x70, 0x46, 0xDD, 0x32, 0x2D, 0x8A, 0x40, 0xEC, 0x09, 0x03, 0xBE, 0x07,
+ 0x1F, 0xCB, 0x8F, 0xA3, 0xC3, 0xE7, 0xD4, 0xF0, 0xF4, 0xE3, 0x4E, 0x35, 0x1F, 0x22, 0xE8, 0x93,
+ 0xD6, 0xCA, 0xCB, 0xED, 0x79, 0x2B, 0xE8, 0xBE, 0x6A, 0xC7, 0x27, 0xEF, 0xAE, 0x9C, 0x60, 0xBB,
+ 0x7C, 0x4F, 0x6F, 0xBB, 0xD2, 0xDD, 0xEC, 0x67, 0xDD, 0x7F, 0xC1, 0x38, 0x74, 0x49, 0x24, 0x5F,
+ 0xF8, 0xA7, 0xE0, 0x60, 0xA0, 0x61, 0xBE, 0xC6, 0xAA, 0xD9, 0x04, 0xE3, 0x23, 0x69, 0xC7, 0x45,
+ 0xC6, 0x00, 0xC7, 0xE3, 0xC7, 0x97, 0x99, 0x67, 0x13, 0xC6, 0xD6, 0x5C, 0xD3, 0x7C, 0x89, 0x2B,
+ 0x59, 0xF6, 0x4B, 0x7F, 0xBB, 0x66, 0xF7, 0xBB, 0x37, 0xA3, 0x1E, 0x4A, 0x69, 0x38, 0x6B, 0xB6,
+ 0xF2, 0x6A, 0xDE, 0x5E, 0x9D, 0x34, 0x5A, 0x5B, 0x4B, 0x09, 0x1F, 0xFC, 0x13, 0x6F, 0x41, 0x31,
+ 0xE5, 0xB4, 0x2B, 0x75, 0x7D, 0xC7, 0xE5, 0x16, 0x2A, 0xC5, 0x80, 0x1C, 0x28, 0x18, 0x5F, 0x97,
+ 0x83, 0xC6, 0x7B, 0x0E, 0x6B, 0xCE, 0x8E, 0x25, 0x24, 0x92, 0x93, 0xED, 0xA3, 0xFC, 0x3D, 0x2D,
+ 0xF2, 0xE8, 0x5B, 0x97, 0x2D, 0x92, 0x82, 0xB7, 0x6B, 0xBF, 0xEB, 0xEE, 0x5F, 0x86, 0xD2, 0x0F,
+ 0xF8, 0x26, 0xD7, 0x87, 0x78, 0x0B, 0xA1, 0xC0, 0xA8, 0x09, 0x21, 0x05, 0x8A, 0xE5, 0x46, 0x06,
+ 0x76, 0x91, 0xF4, 0x00, 0x71, 0x8E, 0x3A, 0x75, 0xC9, 0x1C, 0x5C, 0x39, 0x79, 0x5B, 0x76, 0xF5,
+ 0xED, 0x6D, 0x9E, 0x9D, 0x9A, 0xB6, 0xDB, 0x69, 0x72, 0x5B, 0x92, 0x8D, 0xF9, 0x15, 0xEC, 0xBA,
+ 0xBF, 0x4B, 0x5B, 0x65, 0x6D, 0x3E, 0xEE, 0xC4, 0x71, 0xFF, 0x00, 0xC1, 0x37, 0xF4, 0x18, 0xE6,
+ 0x59, 0x0E, 0x81, 0x6F, 0x22, 0xC4, 0x36, 0xC7, 0xB6, 0xD1, 0x00, 0x00, 0x0C, 0x80, 0xA7, 0x6E,
+ 0x47, 0x7E, 0x33, 0xFF, 0x00, 0xD6, 0xDB, 0x09, 0x8A, 0xA7, 0x4A, 0xB4, 0x6B, 0x54, 0x93, 0xB4,
+ 0x5A, 0x69, 0x39, 0x75, 0x5B, 0x7E, 0x2B, 0xD3, 0x42, 0x9D, 0xF9, 0x14, 0x61, 0x0B, 0x7A, 0x5F,
+ 0xFC, 0xD2, 0xFB, 0xBE, 0x5E, 0x57, 0x57, 0xFE, 0x09, 0xC9, 0xA1, 0x37, 0xCE, 0xDA, 0x15, 0xBA,
+ 0x39, 0x39, 0x0A, 0x96, 0x29, 0xB5, 0x47, 0x4C, 0x64, 0x80, 0x47, 0x40, 0x38, 0xFE, 0x95, 0xF4,
+ 0x12, 0xE2, 0x29, 0xA5, 0xED, 0x63, 0x51, 0xDD, 0xEA, 0x92, 0x6E, 0xD7, 0xFF, 0x00, 0xC0, 0x96,
+ 0xBE, 0x89, 0x5A, 0xCA, 0xD6, 0xD8, 0xE6, 0x94, 0x6A, 0x69, 0x15, 0x1B, 0xAB, 0x6B, 0x79, 0x3F,
+ 0xC9, 0x7F, 0x5B, 0x21, 0xC9, 0xFF, 0x00, 0x04, 0xE0, 0xF0, 0xE6, 0x49, 0xFE, 0xC3, 0x45, 0x2E,
+ 0x0E, 0x0B, 0x69, 0xD1, 0xB0, 0x00, 0x8E, 0x41, 0x3C, 0xF6, 0x1F, 0xC8, 0x74, 0xC5, 0x73, 0x50,
+ 0xCE, 0x21, 0x4A, 0xAC, 0xEB, 0xFB, 0x46, 0xA7, 0x25, 0x67, 0xA6, 0x96, 0xDB, 0x74, 0xEE, 0xAC,
+ 0xAD, 0x6D, 0x5E, 0xBA, 0xDA, 0xE9, 0xD8, 0x97, 0xB5, 0xB2, 0x5C, 0x8A, 0xDD, 0x7D, 0xE7, 0x7D,
+ 0x36, 0xF2, 0xE9, 0xE5, 0xB7, 0x62, 0xA7, 0xFC, 0x3B, 0x97, 0x45, 0x18, 0x51, 0xE1, 0xEB, 0x70,
+ 0xAA, 0x7E, 0x5C, 0x5B, 0x2A, 0x85, 0xF9, 0x7A, 0x8F, 0x97, 0x8E, 0x83, 0xF2, 0xFC, 0xA2, 0xA6,
+ 0x7B, 0x51, 0xB6, 0xA5, 0x37, 0x6D, 0xB7, 0xD1, 0xF4, 0xEF, 0x7D, 0x3A, 0x5A, 0xCD, 0x76, 0xE8,
+ 0x6D, 0x1A, 0x6F, 0x49, 0x24, 0xD6, 0x96, 0xDD, 0xF9, 0x79, 0xF4, 0xD8, 0x9C, 0xFF, 0x00, 0xC1,
+ 0x37, 0xFC, 0x38, 0x02, 0xAF, 0xF6, 0x1C, 0x38, 0x00, 0x1C, 0x2D, 0x84, 0x7C, 0x81, 0xD3, 0x1D,
+ 0x3A, 0xFC, 0xA3, 0xB7, 0x4A, 0xA9, 0xE7, 0x3C, 0xD1, 0xB4, 0xEA, 0xB6, 0xFB, 0xAF, 0xF3, 0x76,
+ 0x7D, 0x6C, 0xAC, 0x95, 0xAD, 0x7B, 0x2B, 0x69, 0x9F, 0x35, 0x4D, 0x94, 0x55, 0xBF, 0xC4, 0xD7,
+ 0xE1, 0x7F, 0xEB, 0x6E, 0xC3, 0x1B, 0xFE, 0x09, 0xBB, 0xE1, 0xD0, 0x98, 0x5D, 0x09, 0x37, 0x28,
+ 0x1B, 0x73, 0x63, 0x1A, 0x82, 0x06, 0x32, 0x06, 0x07, 0x19, 0xDA, 0x3B, 0x7A, 0xE3, 0xAD, 0x72,
+ 0xAC, 0xC6, 0x2B, 0x9B, 0x96, 0xA3, 0x5A, 0x6D, 0xA2, 0x5F, 0x87, 0x6E, 0xDD, 0x76, 0x7B, 0x21,
+ 0xC5, 0xD4, 0xD1, 0x72, 0x2B, 0x79, 0x37, 0x7F, 0x2E, 0xDA, 0x7F, 0xC3, 0x2E, 0xC4, 0x43, 0xFE,
+ 0x09, 0xC5, 0xA1, 0x13, 0xB7, 0xFE, 0x11, 0xEB, 0x65, 0x52, 0x73, 0xF2, 0xDB, 0x28, 0x0B, 0x81,
+ 0xC0, 0x03, 0x68, 0xFE, 0xF1, 0xF4, 0xC7, 0x1E, 0x94, 0xA3, 0x9B, 0x5D, 0x28, 0xA9, 0xB4, 0xBB,
+ 0xBB, 0x7E, 0x9F, 0x76, 0x8B, 0x5D, 0x0B, 0x71, 0x94, 0x55, 0xD2, 0xE9, 0xD1, 0xCB, 0xFC, 0xFC,
+ 0xAD, 0xD9, 0x7A, 0x13, 0x8F, 0xF8, 0x26, 0xFF, 0x00, 0x87, 0x70, 0x33, 0xA0, 0x46, 0x48, 0x18,
+ 0x03, 0xFB, 0x3E, 0x1C, 0x70, 0x06, 0x38, 0xE3, 0x00, 0x10, 0x6B, 0x65, 0x9A, 0x41, 0x5A, 0x2E,
+ 0x4E, 0xDF, 0x2F, 0xB9, 0x6A, 0xBE, 0xED, 0x17, 0x97, 0x6C, 0xBF, 0x7B, 0x74, 0xB9, 0x17, 0x92,
+ 0xE6, 0x7F, 0xD7, 0x96, 0x9F, 0x79, 0x9F, 0x27, 0xFC, 0x13, 0x57, 0xC3, 0xAA, 0x18, 0xA7, 0x87,
+ 0xED, 0xDB, 0x04, 0x61, 0x0D, 0x84, 0x21, 0xB9, 0xC7, 0x03, 0xE4, 0x3C, 0x0C, 0x7F, 0x9E, 0x2B,
+ 0xC5, 0x9D, 0x68, 0xC6, 0x76, 0x8B, 0x76, 0xF5, 0xFD, 0x2D, 0xD0, 0xEA, 0x85, 0x49, 0x72, 0xA5,
+ 0xC8, 0xBE, 0xF7, 0xD3, 0xD1, 0xFF, 0x00, 0x5E, 0x5D, 0x22, 0x8F, 0xFE, 0x09, 0xAF, 0xE1, 0xF6,
+ 0x21, 0x4F, 0x87, 0x6D, 0xA3, 0x18, 0x1C, 0xB5, 0x84, 0x40, 0x0C, 0x8E, 0x00, 0x1E, 0x57, 0xD2,
+ 0x97, 0xB7, 0x8A, 0x4A, 0xCE, 0x5F, 0x7F, 0xFC, 0x02, 0xF9, 0x9D, 0xB4, 0x8A, 0xFB, 0xE5, 0xFE,
+ 0x64, 0xBF, 0xF0, 0xED, 0x3F, 0x0E, 0xED, 0x18, 0xD0, 0x2D, 0xF3, 0xD0, 0x2F, 0xF6, 0x6C, 0x5C,
+ 0x0C, 0xE0, 0x67, 0xF7, 0x7C, 0x7F, 0xF5, 0xBD, 0xB8, 0x85, 0x88, 0x4A, 0xDA, 0xBB, 0x7A, 0xFF,
+ 0x00, 0xC0, 0x21, 0x55, 0x76, 0x56, 0x82, 0xB7, 0xAC, 0xBF, 0xCC, 0x6B, 0xFF, 0x00, 0xC1, 0x35,
+ 0x7C, 0x3A, 0x8A, 0x36, 0xF8, 0x7E, 0xD9, 0xF8, 0xFB, 0xAB, 0xA7, 0xC4, 0x08, 0x00, 0x75, 0xFF,
+ 0x00, 0x57, 0x8E, 0xC2, 0xA9, 0x57, 0x49, 0x2D, 0x5D, 0xBD, 0x7F, 0xE0, 0x15, 0x19, 0xC9, 0xE9,
+ 0xC8, 0xAD, 0xEB, 0x2B, 0x7E, 0x67, 0xF2, 0x2B, 0xFF, 0x00, 0x05, 0xB0, 0xF8, 0x05, 0x65, 0xFB,
+ 0x3F, 0x7F, 0xC1, 0x64, 0xFF, 0x00, 0xE0, 0x95, 0x5E, 0x1F, 0xB1, 0xB0, 0x8F, 0x4F, 0x8F, 0x5E,
+ 0xBF, 0xF8, 0x7B, 0xAE, 0x3C, 0x51, 0xC2, 0xB0, 0x6E, 0x65, 0xF8, 0xAF, 0x3C, 0x3B, 0x8A, 0x85,
+ 0x51, 0xD2, 0x10, 0x3A, 0x76, 0xAD, 0xB0, 0x32, 0x53, 0xCC, 0xB0, 0xF6, 0x6E, 0xDC, 0xF0, 0xDF,
+ 0xFC, 0x48, 0x8A, 0xDA, 0xE1, 0x6A, 0x69, 0x6F, 0x75, 0xF7, 0xEC, 0xFB, 0x9F, 0xB2, 0xF5, 0xFA,
+ 0x79, 0xF2, 0x21, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFA, 0xF5, 0xFF, 0x00, 0x04, 0x4A, 0xB4, 0xB7,
+ 0xBA, 0xF0, 0x27, 0xED, 0xD0, 0x27, 0x8F, 0x78, 0x8F, 0xF6, 0xE7, 0x84, 0x20, 0x0E, 0xC9, 0xB4,
+ 0x1F, 0x80, 0xFF, 0x00, 0x0C, 0x72, 0x38, 0x23, 0xD0, 0x57, 0xE7, 0x5C, 0x41, 0xFF, 0x00, 0x23,
+ 0x49, 0xFA, 0x47, 0xFF, 0x00, 0x49, 0x47, 0xD4, 0x65, 0x7F, 0xEE, 0x51, 0xF9, 0xFE, 0x67, 0xED,
+ 0x6F, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x6B, 0xC4, 0xB2, 0xD3,
+ 0x43, 0xD1, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD1, 0x65, 0x64,
+ 0xAD, 0xA0, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x69, 0x80,
+ 0x7F, 0x64, 0xE9, 0xFF, 0x00, 0xF3, 0xC0, 0xFF, 0x00, 0xDF, 0xE9, 0x3F, 0xC6, 0x80, 0x0F, 0xEC,
+ 0x9D, 0x3F, 0xFE, 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD2, 0x49, 0x2D, 0x90, 0xAC, 0xBB, 0x07,
+ 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x69, 0x82, 0x49, 0x24, 0x92,
+ 0xD0, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x4A, 0xCB, 0x4D,
+ 0x06, 0x1F, 0xD9, 0x3A, 0x7F, 0xFC, 0xF0, 0x3F, 0xF7, 0xFA, 0x4F, 0xF1, 0xA2, 0xCB, 0x4D, 0x00,
+ 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x45, 0x96, 0x9A, 0x09,
+ 0x24, 0xB6, 0x41, 0xFD, 0x93, 0xA7, 0xFF, 0x00, 0xCF, 0x03, 0xFF, 0x00, 0x7F, 0xA4, 0xFF, 0x00,
+ 0x1A, 0x12, 0x49, 0x59, 0x2D, 0x06, 0x1F, 0xD9, 0x3A, 0x7F, 0xFC, 0xF0, 0x3F, 0xF7, 0xFA, 0x4F,
+ 0xF1, 0xA6, 0x01, 0xFD, 0x93, 0xA7, 0xFF, 0x00, 0xCF, 0x03, 0xFF, 0x00, 0x7F, 0xA4, 0xFF, 0x00,
+ 0x1A, 0x49, 0x24, 0xAC, 0x96, 0x82, 0x49, 0x25, 0x64, 0xB4, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78,
+ 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD1, 0x65, 0xA6, 0x83, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78, 0x1F,
+ 0xFB, 0xFD, 0x27, 0xF8, 0xD3, 0x15, 0x96, 0x9A, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F,
+ 0xFD, 0xFE, 0x93, 0xFC, 0x69, 0x24, 0x92, 0xB2, 0x5A, 0x0C, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9,
+ 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x45, 0x95, 0xAD, 0x6D, 0x00, 0x3F, 0xB2, 0x74, 0xFF, 0x00,
+ 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x4C, 0x56, 0x5D, 0x83, 0xFB, 0x27, 0x4F, 0xFF, 0x00,
+ 0x9E, 0x07, 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34, 0x0C, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0,
+ 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x40, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE,
+ 0x93, 0xFC, 0x68, 0x15, 0x95, 0xAD, 0x6D, 0x03, 0xFB, 0x27, 0x4F, 0xFF, 0x00, 0x9E, 0x07, 0xFE,
+ 0xFF, 0x00, 0x49, 0xFE, 0x34, 0x92, 0x4B, 0x64, 0x30, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7, 0x81,
+ 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x09, 0x25, 0x6B, 0x20, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78,
+ 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD1, 0x65, 0x64, 0xAD, 0xA0, 0x92, 0x4B, 0x64, 0x1F, 0xD9, 0x3A,
+ 0x7F, 0xFC, 0xF0, 0x3F, 0xF7, 0xFA, 0x4F, 0xF1, 0xA6, 0x30, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7,
+ 0x81, 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x02, 0xB2, 0xD3, 0x40, 0xFE, 0xC9, 0xD3, 0xFF, 0x00,
+ 0xE7, 0x81, 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x00, 0x92, 0x5B, 0x20, 0xFE, 0xC9, 0xD3, 0xFF,
+ 0x00, 0xE7, 0x81, 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x03, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78,
+ 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD0, 0x01, 0xFD, 0x93, 0xA7, 0xFF, 0x00, 0xCF, 0x03, 0xFF, 0x00,
+ 0x7F, 0xA4, 0xFF, 0x00, 0x1A, 0x00, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4,
+ 0x9F, 0xE3, 0x40, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x69,
+ 0x24, 0x96, 0xC8, 0x56, 0x5D, 0x83, 0xFB, 0x27, 0x4F, 0xFF, 0x00, 0x9E, 0x07, 0xFE, 0xFF, 0x00,
+ 0x49, 0xFE, 0x34, 0x59, 0x76, 0x04, 0x92, 0x56, 0x4B, 0x40, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7,
+ 0x81, 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x31, 0x87, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F,
+ 0xFD, 0xFE, 0x93, 0xFC, 0x68, 0x15, 0x95, 0x92, 0xB6, 0x81, 0xFD, 0x93, 0xA7, 0xFF, 0x00, 0xCF,
+ 0x03, 0xFF, 0x00, 0x7F, 0xA4, 0xFF, 0x00, 0x1A, 0x49, 0x25, 0xB2, 0x18, 0x7F, 0x64, 0xE9, 0xFF,
+ 0x00, 0xF3, 0xC0, 0xFF, 0x00, 0xDF, 0xE9, 0x3F, 0xC6, 0x98, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00,
+ 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x68, 0x15, 0x95, 0xAD, 0x6D, 0x03, 0xFB, 0x27, 0x4F, 0xFF,
+ 0x00, 0x9E, 0x07, 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34, 0x0C, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9,
+ 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x49, 0x24, 0xB6, 0x42, 0x49, 0x2D, 0x90, 0x7F, 0x64, 0xE9,
+ 0xFF, 0x00, 0xF3, 0xC0, 0xFF, 0x00, 0xDF, 0xE9, 0x3F, 0xC6, 0x8B, 0x2B, 0x5A, 0xDA, 0x05, 0x95,
+ 0xAD, 0x6D, 0x03, 0xFB, 0x27, 0x4F, 0xFF, 0x00, 0x9E, 0x07, 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34,
+ 0xC6, 0x1F, 0xD9, 0x3A, 0x7F, 0xFC, 0xF0, 0x3F, 0xF7, 0xFA, 0x4F, 0xF1, 0xA0, 0x03, 0xFB, 0x27,
+ 0x4F, 0xFF, 0x00, 0x9E, 0x07, 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34, 0xAC, 0xAD, 0x6B, 0x68, 0x24,
+ 0x92, 0xD9, 0x07, 0xF6, 0x4E, 0x9F, 0xFF, 0x00, 0x3C, 0x0F, 0xFD, 0xFE, 0x93, 0xFC, 0x68, 0x49,
+ 0x24, 0x92, 0x5A, 0x0C, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3,
+ 0x42, 0x49, 0x6C, 0x84, 0x92, 0x5B, 0x20, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7, 0x81, 0xFF, 0x00,
+ 0xBF, 0xD2, 0x7F, 0x8D, 0x16, 0x5A, 0x68, 0x09, 0x25, 0xB2, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78,
+ 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD3, 0x18, 0x7F, 0x64, 0xE9, 0xFF, 0x00, 0xF3, 0xC0, 0xFF, 0x00,
+ 0xDF, 0xE9, 0x3F, 0xC6, 0x80, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE, 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8,
+ 0xD2, 0xB2, 0xD3, 0x41, 0x24, 0x92, 0x49, 0x2D, 0x03, 0xFB, 0x27, 0x4F, 0xFF, 0x00, 0x9E, 0x07,
+ 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34, 0x59, 0x5A, 0xD6, 0xD0, 0x2C, 0xAD, 0x6B, 0x68, 0x1F, 0xD9,
+ 0x3A, 0x7F, 0xFC, 0xF0, 0x3F, 0xF7, 0xFA, 0x4F, 0xF1, 0xA6, 0x16, 0x56, 0xB5, 0xB4, 0x0F, 0xEC,
+ 0x9D, 0x3F, 0xFE, 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD2, 0x49, 0x2D, 0x90, 0xC3, 0xFB, 0x27,
+ 0x4F, 0xFF, 0x00, 0x9E, 0x07, 0xFE, 0xFF, 0x00, 0x49, 0xFE, 0x34, 0xC0, 0x3F, 0xB2, 0x74, 0xFF,
+ 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x40, 0xAC, 0xB4, 0xD0, 0x3F, 0xB2, 0x74, 0xFF,
+ 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x49, 0x24, 0xB6, 0x43, 0x0F, 0xEC, 0x9D, 0x3F,
+ 0xFE, 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD0, 0x92, 0x5B, 0x20, 0x0F, 0xEC, 0x9D, 0x3F, 0xFE,
+ 0x78, 0x1F, 0xFB, 0xFD, 0x27, 0xF8, 0xD3, 0x00, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7, 0x81, 0xFF,
+ 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x2B, 0x2D, 0x34, 0x00, 0xFE, 0xC9, 0xD3, 0xFF, 0x00, 0xE7, 0x81,
+ 0xFF, 0x00, 0xBF, 0xD2, 0x7F, 0x8D, 0x16, 0x5D, 0x85, 0x65, 0x64, 0xAD, 0xA0, 0x7F, 0x64, 0xE9,
+ 0xFF, 0x00, 0xF3, 0xC0, 0xFF, 0x00, 0xDF, 0xE9, 0x3F, 0xC6, 0x8B, 0x2B, 0x5A, 0xDA, 0x02, 0x49,
+ 0x24, 0x92, 0xD0, 0x3F, 0xB2, 0x74, 0xFF, 0x00, 0xF9, 0xE0, 0x7F, 0xEF, 0xF4, 0x9F, 0xE3, 0x4C,
+ 0x61, 0xFD, 0x93, 0xA7, 0xFF, 0x00, 0xCF, 0x03, 0xFF, 0x00, 0x7F, 0xA4, 0xFF, 0x00, 0x1A, 0x05,
+ 0x65, 0x6B, 0x5B, 0x43, 0xF8, 0x00, 0xFF, 0x00, 0x83, 0x9D, 0xE1, 0x8A, 0xDF, 0xFE, 0x0B, 0x97,
+ 0xFF, 0x00, 0x04, 0x86, 0x8A, 0x14, 0xD8, 0x89, 0xA5, 0x7C, 0x3D, 0x0A, 0xB9, 0x2D, 0x80, 0x7E,
+ 0x2F, 0xDD, 0x1C, 0x64, 0xFD, 0x4D, 0x76, 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F,
+ 0xFA, 0x52, 0x30, 0xC4, 0xA4, 0xB0, 0xB5, 0x2C, 0xBE, 0xCB, 0xFC, 0x8F, 0xB6, 0x2B, 0xF5, 0x33,
+ 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27,
+ 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F,
+ 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99,
+ 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x7F, 0x9F, 0x9F, 0xFC, 0x1C, 0xFB, 0xFF, 0x00, 0x29, 0xCF, 0xFF, 0x00, 0x82, 0x43, 0xFF, 0x00,
+ 0xD8, 0x2B, 0xE1, 0xEF, 0xFE, 0xAD, 0xEB, 0x9A, 0xEC, 0xCB, 0x3F, 0xE4, 0x61, 0x87, 0xFF, 0x00,
+ 0x1C, 0x3F, 0xF4, 0xA4, 0x73, 0xE2, 0x7F, 0xDD, 0x6A, 0x7F, 0x85, 0xFE, 0x47, 0xDA, 0x95, 0xFA,
+ 0x99, 0xF1, 0xC1, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFB, 0x05, 0xFF, 0x00, 0x04, 0x42, 0xFF, 0x00,
+ 0x91, 0x13, 0xF6, 0xEB, 0xFF, 0x00, 0xB3, 0xE7, 0x83, 0xFF, 0x00, 0x54, 0x37, 0xC3, 0x2A, 0xFC,
+ 0xEB, 0x88, 0x3F, 0xE4, 0x69, 0x3F, 0x48, 0xFF, 0x00, 0xE9, 0x28, 0xFA, 0x8C, 0xAF, 0xFD, 0xCA,
+ 0x3F, 0x3F, 0xCC, 0xFD, 0xB6, 0xAF, 0x14, 0xF4, 0x42, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7, 0xFF, 0x00, 0xC1,
+ 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76, 0x65, 0x9F, 0xF2,
+ 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5, 0x3F, 0xC2, 0xFF,
+ 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFD, 0x82, 0xFF,
+ 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1, 0xFF, 0x00, 0xAA,
+ 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46,
+ 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F, 0xE7, 0xE7, 0xFF, 0x00, 0x07, 0x3E, 0xFF, 0x00, 0xCA,
+ 0x73, 0xFF, 0x00, 0xE0, 0x90, 0xFF, 0x00, 0xF6, 0x0A, 0xF8, 0x7B, 0xFF, 0x00, 0xAB, 0x7A, 0xE6,
+ 0xBB, 0x32, 0xCF, 0xF9, 0x18, 0x61, 0xFF, 0x00, 0xC7, 0x0F, 0xFD, 0x29, 0x1C, 0xF8, 0x9F, 0xF7,
+ 0x5A, 0x9F, 0xE1, 0x7F, 0x91, 0xF6, 0xA5, 0x7E, 0xA6, 0x7C, 0x70, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x7E, 0xC1, 0x7F, 0xC1, 0x10, 0xBF, 0xE4, 0x44, 0xFD, 0xBA, 0xFF, 0x00, 0xEC, 0xF9, 0xE0, 0xFF,
+ 0x00, 0xD5, 0x0D, 0xF0, 0xCA, 0xBF, 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2, 0x3F, 0xFA, 0x4A,
+ 0x3E, 0xA3, 0x2B, 0xFF, 0x00, 0x72, 0x8F, 0xCF, 0xF3, 0x3F, 0x6D, 0xAB, 0xC5, 0x3D, 0x10, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xF3, 0xF3, 0xFF, 0x00, 0x83, 0x9F,
+ 0x7F, 0xE5, 0x39, 0xFF, 0x00, 0xF0, 0x48, 0x7F, 0xFB, 0x05, 0x7C, 0x3D, 0xFF, 0x00, 0xD5, 0xBD,
+ 0x73, 0x5D, 0x99, 0x67, 0xFC, 0x8C, 0x30, 0xFF, 0x00, 0xE3, 0x87, 0xFE, 0x94, 0x8E, 0x7C, 0x4F,
+ 0xFB, 0xAD, 0x4F, 0xF0, 0xBF, 0xC8, 0xFB, 0x52, 0xBF, 0x53, 0x3E, 0x38, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x3F, 0x60, 0xBF, 0xE0, 0x88, 0x5F, 0xF2, 0x22, 0x7E, 0xDD, 0x7F, 0xF6, 0x7C, 0xF0, 0x7F,
+ 0xEA, 0x86, 0xF8, 0x65, 0x5F, 0x9D, 0x71, 0x07, 0xFC, 0x8D, 0x27, 0xE9, 0x1F, 0xFD, 0x25, 0x1F,
+ 0x51, 0x95, 0xFF, 0x00, 0xB9, 0x47, 0xE7, 0xF9, 0x9F, 0xB6, 0xD5, 0xE2, 0x9E, 0x88, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xF9, 0xF9, 0xFF, 0x00, 0xC1, 0xCF, 0xBF,
+ 0xF2, 0x9C, 0xFF, 0x00, 0xF8, 0x24, 0x3F, 0xFD, 0x82, 0xBE, 0x1E, 0xFF, 0x00, 0xEA, 0xDE, 0xB9,
+ 0xAE, 0xCC, 0xB3, 0xFE, 0x46, 0x18, 0x7F, 0xF1, 0xC3, 0xFF, 0x00, 0x4A, 0x47, 0x3E, 0x27, 0xFD,
+ 0xD6, 0xA7, 0xF8, 0x5F, 0xE4, 0x7D, 0xA9, 0x5F, 0xA9, 0x9F, 0x1C, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x1F, 0xB0, 0x5F, 0xF0, 0x44, 0x2F, 0xF9, 0x11, 0x3F, 0x6E, 0xBF, 0xFB, 0x3E, 0x78, 0x3F, 0xF5,
+ 0x43, 0x7C, 0x32, 0xAF, 0xCE, 0xB8, 0x83, 0xFE, 0x46, 0x93, 0xF4, 0x8F, 0xFE, 0x92, 0x8F, 0xA8,
+ 0xCA, 0xFF, 0x00, 0xDC, 0xA3, 0xF3, 0xFC, 0xCF, 0xDB, 0x6A, 0xF1, 0x4F, 0x44, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xFC, 0xFC, 0xFF, 0x00, 0xE0, 0xE7, 0xDF, 0xF9,
+ 0x4E, 0x7F, 0xFC, 0x12, 0x1F, 0xFE, 0xC1, 0x5F, 0x0F, 0x7F, 0xF5, 0x6F, 0x5C, 0xD7, 0x66, 0x59,
+ 0xFF, 0x00, 0x23, 0x0C, 0x3F, 0xF8, 0xE1, 0xFF, 0x00, 0xA5, 0x23, 0x9F, 0x13, 0xFE, 0xEB, 0x53,
+ 0xFC, 0x2F, 0xF2, 0x3E, 0xD4, 0xAF, 0xD4, 0xCF, 0x8E, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xD8,
+ 0x2F, 0xF8, 0x22, 0x17, 0xFC, 0x88, 0x9F, 0xB7, 0x5F, 0xFD, 0x9F, 0x3C, 0x1F, 0xFA, 0xA1, 0xBE,
+ 0x19, 0x57, 0xE7, 0x5C, 0x41, 0xFF, 0x00, 0x23, 0x49, 0xFA, 0x47, 0xFF, 0x00, 0x49, 0x47, 0xD4,
+ 0x65, 0x7F, 0xEE, 0x51, 0xF9, 0xFE, 0x67, 0xED, 0xB5, 0x78, 0xA7, 0xA2, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFE, 0x7E, 0x7F, 0xF0, 0x73, 0xEF, 0xFC, 0xA7, 0x3F,
+ 0xFE, 0x09, 0x0F, 0xFF, 0x00, 0x60, 0xAF, 0x87, 0xBF, 0xFA, 0xB7, 0xAE, 0x6B, 0xB3, 0x2C, 0xFF,
+ 0x00, 0x91, 0x86, 0x1F, 0xFC, 0x70, 0xFF, 0x00, 0xD2, 0x91, 0xCF, 0x89, 0xFF, 0x00, 0x75, 0xA9,
+ 0xFE, 0x17, 0xF9, 0x1F, 0x6A, 0x57, 0xEA, 0x67, 0xC7, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xEC,
+ 0x17, 0xFC, 0x11, 0x0B, 0xFE, 0x44, 0x4F, 0xDB, 0xAF, 0xFE, 0xCF, 0x9E, 0x0F, 0xFD, 0x50, 0xDF,
+ 0x0C, 0xAB, 0xF3, 0xAE, 0x20, 0xFF, 0x00, 0x91, 0xA4, 0xFD, 0x23, 0xFF, 0x00, 0xA4, 0xA3, 0xEA,
+ 0x32, 0xBF, 0xF7, 0x28, 0xFC, 0xFF, 0x00, 0x33, 0xF6, 0xDA, 0xBC, 0x53, 0xD1, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00, 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE,
+ 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57, 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35,
+ 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9, 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA,
+ 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33, 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28,
+ 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27, 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF,
+ 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F, 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00,
+ 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99, 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x08, 0x7E, 0xE9,
+ 0xFF, 0x00, 0x77, 0xFA, 0x50, 0x04, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x05, 0x8A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x03, 0xFC, 0xFC, 0xFF, 0x00, 0xE0, 0xE7, 0xDF, 0xF9, 0x4E, 0x7F, 0xFC, 0x12, 0x1F, 0xFE,
+ 0xC1, 0x5F, 0x0F, 0x7F, 0xF5, 0x6F, 0x5C, 0xD7, 0x66, 0x59, 0xFF, 0x00, 0x23, 0x0C, 0x3F, 0xF8,
+ 0xE1, 0xFF, 0x00, 0xA5, 0x23, 0x9F, 0x13, 0xFE, 0xEB, 0x53, 0xFC, 0x2F, 0xF2, 0x3E, 0xD4, 0xAF,
+ 0xD4, 0xCF, 0x8E, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xD8, 0x2F, 0xF8, 0x22, 0x17, 0xFC, 0x88,
+ 0x9F, 0xB7, 0x5F, 0xFD, 0x9F, 0x3C, 0x1F, 0xFA, 0xA1, 0xBE, 0x19, 0x57, 0xE7, 0x5C, 0x41, 0xFF,
+ 0x00, 0x23, 0x49, 0xFA, 0x47, 0xFF, 0x00, 0x49, 0x47, 0xD4, 0x65, 0x7F, 0xEE, 0x51, 0xF9, 0xFE,
+ 0x67, 0xED, 0xB5, 0x78, 0xA7, 0xA2, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x21, 0xFB, 0xA7, 0xFD, 0xDF, 0xE9, 0x40, 0x10, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x03, 0x8C, 0x70, 0x38, 0xC7, 0x18, 0xE3, 0x8E, 0xD8, 0xFC,
+ 0x28, 0x03, 0xE6, 0x3F, 0x87, 0xBE, 0x3E, 0xF1, 0x87, 0xC3, 0xCF, 0x17, 0xE9, 0x7F, 0x02, 0xFE,
+ 0x39, 0x6A, 0xAF, 0xAE, 0x6B, 0x1A, 0xC7, 0xDA, 0xBF, 0xE1, 0x4A, 0x7C, 0x6A, 0x7D, 0x3D, 0x34,
+ 0xFD, 0x37, 0xE3, 0x5D, 0x9D, 0xA4, 0x72, 0xDC, 0x4D, 0xA4, 0xEB, 0x31, 0xDB, 0xDB, 0xC7, 0x63,
+ 0xA6, 0xF8, 0xB2, 0xCA, 0xCE, 0x20, 0xD3, 0xDA, 0xA1, 0x8E, 0x1D, 0x56, 0x0B, 0x7B, 0x9D, 0x57,
+ 0x4E, 0x8A, 0x38, 0xE1, 0xD5, 0x34, 0xDF, 0x0E, 0x80, 0x7D, 0x39, 0x40, 0x19, 0xDA, 0xBC, 0xD2,
+ 0xDA, 0xE9, 0x1A, 0x9D, 0xC5, 0xBB, 0x79, 0x73, 0x5B, 0xE9, 0xB3, 0xCD, 0x0B, 0x85, 0x53, 0xE5,
+ 0xBA, 0x44, 0x4A, 0x90, 0x08, 0x23, 0x82, 0x07, 0x04, 0x62, 0x80, 0x3C, 0x7F, 0xF6, 0x61, 0xF1,
+ 0x5F, 0x88, 0x7C, 0x79, 0xFB, 0x35, 0x7E, 0xCF, 0x1E, 0x38, 0xF1, 0x76, 0xA6, 0xFA, 0xD7, 0x8B,
+ 0x3C, 0x67, 0xF0, 0x33, 0xC2, 0x3E, 0x2B, 0xF1, 0x3E, 0xB3, 0x25, 0xAC, 0x16, 0x52, 0x6A, 0xDA,
+ 0x8E, 0xA3, 0xE1, 0xFB, 0x4B, 0x8B, 0xDB, 0xA6, 0x86, 0x04, 0x8E, 0x18, 0xCC, 0x93, 0x4D, 0x2B,
+ 0xEC, 0x8E, 0x34, 0x45, 0xDD, 0x85, 0x55, 0x00, 0x00, 0x01, 0xEE, 0x34, 0x01, 0xF2, 0xF7, 0xC4,
+ 0x3F, 0x88, 0xDE, 0x2F, 0xF1, 0xF7, 0x8C, 0xF5, 0x5F, 0x80, 0x5F, 0x01, 0x75, 0x65, 0xD1, 0xFC,
+ 0x4F, 0xA2, 0x0B, 0x43, 0xF1, 0xB3, 0xE3, 0x4A, 0xE9, 0x96, 0xBA, 0xF6, 0x89, 0xF0, 0x06, 0xCA,
+ 0xF2, 0x18, 0x2E, 0x61, 0xD2, 0x2C, 0x6D, 0xA6, 0x26, 0x0B, 0xCF, 0x19, 0x6A, 0x1A, 0x7D, 0xCA,
+ 0xCD, 0x63, 0x6B, 0x24, 0x57, 0x16, 0xBA, 0x64, 0x13, 0x5B, 0x6B, 0x1A, 0xA4, 0x32, 0xC3, 0x2E,
+ 0x95, 0xA4, 0xF8, 0xA0, 0x03, 0xE9, 0xC8, 0x23, 0x30, 0xC1, 0x0C, 0x2D, 0x2C, 0x93, 0xB4, 0x51,
+ 0x2C, 0x46, 0x79, 0xB6, 0x79, 0xD3, 0x15, 0x50, 0x0B, 0xBE, 0xD5, 0x55, 0xC9, 0xC6, 0x4E, 0xD5,
+ 0x51, 0xE8, 0x00, 0xE0, 0x00, 0x4B, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0x62, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00, 0x3F, 0x3F, 0xF8, 0x39, 0xF7,
+ 0xFE, 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57, 0xC3, 0xDF, 0xFD, 0x5B, 0xD7,
+ 0x35, 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9, 0x48, 0xE7, 0xC4, 0xFF, 0x00,
+ 0xBA, 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33, 0xE3, 0x82, 0x80, 0x0A, 0x00,
+ 0x28, 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27, 0xED, 0xD7, 0xFF, 0x00, 0x67,
+ 0xCF, 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F, 0xC8, 0xD2, 0x7E, 0x91, 0xFF,
+ 0x00, 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99, 0xFB, 0x6D, 0x5E, 0x29, 0xE8,
+ 0x85, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x08, 0x7E,
+ 0xE9, 0xFF, 0x00, 0x77, 0xFA, 0x50, 0x04, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x71, 0xDE, 0x3D, 0xF0, 0x07, 0x84, 0x3E, 0x27, 0x78, 0x53, 0x51, 0xF0, 0x4F,
+ 0x8E, 0x74, 0x58, 0x75, 0xDF, 0x0E, 0x6A, 0x72, 0xDA, 0x5E, 0x3D, 0xA9, 0xB8, 0x9F, 0x4E, 0xBD,
+ 0xD3, 0xEF, 0x34, 0xEB, 0xC8, 0xAF, 0x34, 0xAD, 0x4F, 0x4E, 0xBE, 0xB7, 0x78, 0xEE, 0xAC, 0x75,
+ 0x0B, 0x2B, 0xDB, 0x3B, 0x2B, 0xBB, 0x4B, 0xDB, 0x59, 0x61, 0xB8, 0xB4, 0xB9, 0xB6, 0xB6, 0xB9,
+ 0x82, 0x58, 0xA6, 0x82, 0x39, 0x10, 0x02, 0x8F, 0xC3, 0x1F, 0x0F, 0xF8, 0xE3, 0xC2, 0x9E, 0x11,
+ 0xB1, 0xF0, 0xDF, 0x8F, 0xBC, 0x71, 0x17, 0xC4, 0x9D, 0x67, 0x45, 0x96, 0x4D, 0x36, 0xC7, 0xC7,
+ 0x12, 0x68, 0x11, 0x78, 0x6F, 0x5E, 0xF1, 0x1E, 0x9D, 0x11, 0xDB, 0xA7, 0xDC, 0x6B, 0x76, 0xF0,
+ 0xB9, 0xB4, 0x7D, 0x54, 0xC2, 0x23, 0x17, 0x73, 0xDA, 0x45, 0x69, 0x6D, 0x3C, 0xE2, 0x59, 0xE0,
+ 0xB2, 0xB1, 0x8E, 0x54, 0xB4, 0xB7, 0x00, 0xF1, 0x1F, 0x1C, 0xFE, 0xD6, 0xDF, 0x07, 0x34, 0x48,
+ 0x2E, 0x34, 0x78, 0x6C, 0xFE, 0x38, 0xF8, 0xC0, 0x6A, 0x9A, 0x6E, 0xA5, 0x6F, 0x69, 0xAE, 0x7C,
+ 0x26, 0xFD, 0x94, 0x3E, 0x2B, 0x7C, 0x6E, 0xF0, 0x6F, 0x9B, 0x65, 0xAA, 0xDF, 0xE9, 0x37, 0x96,
+ 0xEF, 0xAD, 0xF8, 0x73, 0xC3, 0x7A, 0x85, 0x82, 0x4F, 0x15, 0xF6, 0x8F, 0x7E, 0x8F, 0x01, 0x9B,
+ 0xCD, 0x08, 0xB0, 0xCD, 0xB3, 0xCA, 0xB8, 0x82, 0x49, 0x40, 0x3C, 0x4B, 0xF6, 0x76, 0xFD, 0xA9,
+ 0x7E, 0x11, 0xFC, 0x2D, 0xF8, 0x15, 0xF0, 0x2F, 0xE1, 0x6F, 0x8D, 0xAC, 0x3E, 0x3F, 0xF8, 0x77,
+ 0x51, 0xF8, 0x6F, 0xF0, 0x8F, 0xC3, 0x1E, 0x02, 0xF1, 0x77, 0x8C, 0xBC, 0x4B, 0xFB, 0x16, 0x7C,
+ 0x6F, 0xF0, 0x07, 0xC2, 0x8D, 0x12, 0x7D, 0x1B, 0x45, 0xB6, 0xB4, 0xD4, 0x35, 0x2B, 0xEF, 0x13,
+ 0xEB, 0x5E, 0x0F, 0xB0, 0xB0, 0xD3, 0xF4, 0xA8, 0xDA, 0xDA, 0x59, 0x5E, 0xFB, 0x50, 0x92, 0xCE,
+ 0x18, 0x61, 0x53, 0x2C, 0xCD, 0x0A, 0xAB, 0x6C, 0x00, 0xFB, 0x83, 0xE2, 0x4E, 0x83, 0xE3, 0x4F,
+ 0x13, 0xF8, 0x2B, 0x59, 0xF0, 0xEF, 0xC3, 0xEF, 0x1C, 0xB7, 0xC3, 0x3F, 0x13, 0x6B, 0x4B, 0x06,
+ 0x9B, 0x07, 0x8F, 0xAD, 0x34, 0x0B, 0x2F, 0x12, 0xEB, 0x5E, 0x12, 0xB4, 0x96, 0xE2, 0x35, 0xD4,
+ 0x6F, 0x74, 0x8B, 0x3B, 0xC4, 0x92, 0xC0, 0xEA, 0x69, 0x68, 0x6E, 0x8D, 0x9B, 0xDE, 0xDB, 0xDE,
+ 0xDA, 0x45, 0x75, 0xF6, 0x69, 0x6E, 0x6C, 0xAF, 0x60, 0x8E, 0x4B, 0x4B, 0x80, 0x09, 0x7E, 0x1D,
+ 0xFC, 0x3B, 0xF0, 0x6F, 0xC2, 0x9F, 0x08, 0x69, 0x7E, 0x06, 0xF0, 0x16, 0x89, 0x1E, 0x83, 0xE1,
+ 0xBD, 0x2A, 0x5B, 0xBB, 0xD8, 0xED, 0xBE, 0xD7, 0x73, 0xAA, 0x5F, 0x6A, 0x17, 0xBA, 0x8D, 0xEC,
+ 0xB7, 0x9A, 0xAE, 0xA9, 0xA8, 0xDF, 0xDC, 0xC9, 0x2D, 0xDD, 0xF6, 0xA1, 0x7B, 0x7D, 0x79, 0x7B,
+ 0x79, 0x77, 0x7B, 0x75, 0x2C, 0xD7, 0x37, 0x77, 0x57, 0x37, 0x37, 0x33, 0xCB, 0x2C, 0xD3, 0x49,
+ 0x23, 0x80, 0x76, 0xB4, 0x00, 0x50, 0x07, 0x01, 0xF1, 0x07, 0xE2, 0x7F, 0x82, 0x3E, 0x16, 0xD8,
+ 0xE8, 0x37, 0xBE, 0x34, 0xD5, 0xAE, 0x2C, 0x5F, 0xC5, 0x5E, 0x24, 0x83, 0xC1, 0xDE, 0x12, 0xD1,
+ 0x74, 0x8D, 0x0B, 0x50, 0xF1, 0x6F, 0x8A, 0xFC, 0x5F, 0xAA, 0x4D, 0x6F, 0x35, 0xC0, 0xD3, 0xF4,
+ 0x7D, 0x13, 0x4F, 0x82, 0x7B, 0xFB, 0xE9, 0xA3, 0xB3, 0xB0, 0xD4, 0x6F, 0x25, 0x4B, 0x68, 0x25,
+ 0x30, 0x59, 0xD8, 0xDF, 0xDE, 0x4B, 0xE5, 0xDB, 0xD9, 0xCF, 0x2C, 0x40, 0x1F, 0x3E, 0x7F, 0xC3,
+ 0x72, 0x7C, 0x15, 0xFF, 0x00, 0xA1, 0x27, 0xF6, 0xC3, 0xFF, 0x00, 0xC5, 0x77, 0x7E, 0xD0, 0x3F,
+ 0xFC, 0xC5, 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0xC9, 0xF0, 0x57, 0xFE, 0x84, 0x9F, 0xDB, 0x0F, 0xFF,
+ 0x00, 0x15, 0xDD, 0xFB, 0x40, 0xFF, 0x00, 0xF3, 0x17, 0x40, 0x07, 0xFC, 0x37, 0x27, 0xC1, 0x5F,
+ 0xFA, 0x12, 0x7F, 0x6C, 0x3F, 0xFC, 0x57, 0x77, 0xED, 0x03, 0xFF, 0x00, 0xCC, 0x5D, 0x00, 0x1F,
+ 0xF0, 0xDC, 0x9F, 0x05, 0x7F, 0xE8, 0x49, 0xFD, 0xB0, 0xFF, 0x00, 0xF1, 0x5D, 0xDF, 0xB4, 0x0F,
+ 0xFF, 0x00, 0x31, 0x74, 0x00, 0x7F, 0xC3, 0x72, 0x7C, 0x15, 0xFF, 0x00, 0xA1, 0x27, 0xF6, 0xC3,
+ 0xFF, 0x00, 0xC5, 0x77, 0x7E, 0xD0, 0x3F, 0xFC, 0xC5, 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0xC9, 0xF0,
+ 0x57, 0xFE, 0x84, 0x9F, 0xDB, 0x0F, 0xFF, 0x00, 0x15, 0xDD, 0xFB, 0x40, 0xFF, 0x00, 0xF3, 0x17,
+ 0x40, 0x07, 0xFC, 0x37, 0x27, 0xC1, 0x5F, 0xFA, 0x12, 0x7F, 0x6C, 0x3F, 0xFC, 0x57, 0x77, 0xED,
+ 0x03, 0xFF, 0x00, 0xCC, 0x5D, 0x00, 0x1F, 0xF0, 0xDC, 0x9F, 0x05, 0x7F, 0xE8, 0x49, 0xFD, 0xB0,
+ 0xFF, 0x00, 0xF1, 0x5D, 0xDF, 0xB4, 0x0F, 0xFF, 0x00, 0x31, 0x74, 0x00, 0x7F, 0xC3, 0x72, 0x7C,
+ 0x15, 0xFF, 0x00, 0xA1, 0x27, 0xF6, 0xC3, 0xFF, 0x00, 0xC5, 0x77, 0x7E, 0xD0, 0x3F, 0xFC, 0xC5,
+ 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0xC9, 0xF0, 0x57, 0xFE, 0x84, 0x9F, 0xDB, 0x0F, 0xFF, 0x00, 0x15,
+ 0xDD, 0xFB, 0x40, 0xFF, 0x00, 0xF3, 0x17, 0x40, 0x07, 0xFC, 0x37, 0x27, 0xC1, 0x5F, 0xFA, 0x12,
+ 0x7F, 0x6C, 0x3F, 0xFC, 0x57, 0x77, 0xED, 0x03, 0xFF, 0x00, 0xCC, 0x5D, 0x00, 0x1F, 0xF0, 0xDC,
+ 0x9F, 0x05, 0x7F, 0xE8, 0x49, 0xFD, 0xB0, 0xFF, 0x00, 0xF1, 0x5D, 0xDF, 0xB4, 0x0F, 0xFF, 0x00,
+ 0x31, 0x74, 0x01, 0xEB, 0x7F, 0x09, 0xFE, 0x3C, 0xF8, 0x1F, 0xE3, 0x34, 0xFA, 0xE5, 0xAF, 0x83,
+ 0xF4, 0x2F, 0x8D, 0x1A, 0x34, 0x9E, 0x1D, 0x86, 0xDA, 0x7B, 0xF6, 0xF8, 0xB1, 0xFB, 0x36, 0xFC,
+ 0x45, 0xF8, 0x09, 0x6F, 0x3A, 0xDD, 0x34, 0xA2, 0x21, 0x61, 0x37, 0x89, 0xB4, 0x3D, 0x36, 0x3B,
+ 0xD6, 0x1F, 0x66, 0x93, 0x7A, 0xDA, 0xB4, 0xCD, 0x10, 0x31, 0x19, 0x02, 0x09, 0x63, 0xDE, 0x01,
+ 0xEC, 0xF4, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x58,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D,
+ 0xFF, 0x00, 0x94, 0xE7, 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00,
+ 0x56, 0xF5, 0xCD, 0x76, 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39,
+ 0xF1, 0x3F, 0xEE, 0xB5, 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF,
+ 0x00, 0xD9, 0xF3, 0xC1, 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34,
+ 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57,
+ 0x8A, 0x7A, 0x21, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x02, 0x1F, 0xBA, 0x7F, 0xDD, 0xFE, 0x94, 0x01, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x00, 0x1D, 0x00, 0x1E, 0x80, 0x00, 0x3F, 0x20, 0x07, 0xE5, 0x40, 0x1F,
+ 0x24, 0x6A, 0x9A, 0xB5, 0xFF, 0x00, 0xED, 0x45, 0xA8, 0x6A, 0x3E, 0x10, 0xF0, 0x6E, 0xA7, 0x71,
+ 0xA6, 0xFE, 0xCE, 0x5A, 0x5D, 0xDC, 0xFA, 0x2F, 0xC4, 0x1F, 0x88, 0x9A, 0x1D, 0xEC, 0x49, 0x73,
+ 0xF1, 0xAE, 0x78, 0x4C, 0x4B, 0x73, 0xE1, 0x9F, 0x0C, 0x5D, 0xA0, 0x71, 0xFD, 0x8E, 0x37, 0x5E,
+ 0x5B, 0x6A, 0x5A, 0x8C, 0x4D, 0x1C, 0x9E, 0x64, 0x52, 0x59, 0x5A, 0x38, 0x91, 0x6E, 0x2E, 0x2D,
+ 0x00, 0x3E, 0xA7, 0xD2, 0x34, 0x8D, 0x27, 0x40, 0xD2, 0x74, 0xBD, 0x07, 0x41, 0xD3, 0x34, 0xED,
+ 0x13, 0x43, 0xD1, 0x34, 0xE8, 0x34, 0x8D, 0x1B, 0x46, 0xD2, 0x2C, 0xA2, 0xD3, 0x74, 0x9D, 0x22,
+ 0xD2, 0xDA, 0x25, 0x8E, 0xDA, 0xD6, 0xD6, 0xDA, 0x35, 0x58, 0xE2, 0x86, 0x38, 0xE3, 0x8D, 0x12,
+ 0x34, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x73, 0x6B, 0x6B, 0x7B, 0x6B, 0x71,
+ 0x63, 0x7B, 0x6D, 0x6F, 0x77, 0x65, 0x77, 0x6E, 0xF6, 0x97, 0x76, 0x77, 0x50, 0xA5, 0xC5, 0xAD,
+ 0xD4, 0x52, 0x21, 0x59, 0x22, 0x92, 0x36, 0x05, 0x59, 0x19, 0x49, 0x05, 0x48, 0x20, 0x82, 0x41,
+ 0x18, 0xA0, 0x0F, 0x90, 0xD2, 0xE6, 0x6F, 0xD9, 0x0E, 0x61, 0x6F, 0xA8, 0xCF, 0xE6, 0xFE, 0xC9,
+ 0x37, 0x37, 0x01, 0x6C, 0x75, 0x5B, 0x87, 0x82, 0x0F, 0xF8, 0x65, 0x29, 0xAE, 0x6E, 0x98, 0x25,
+ 0xA5, 0xDC, 0x8D, 0x22, 0xE7, 0xC1, 0x4C, 0xF7, 0x36, 0xB0, 0x5B, 0x08, 0xA2, 0x3F, 0xD8, 0x01,
+ 0x42, 0x39, 0xFE, 0xC7, 0x0A, 0xDE, 0x1C, 0x00, 0xFB, 0x0F, 0xDB, 0xD3, 0x8C, 0x7A, 0x63, 0xB6,
+ 0x3F, 0x0A, 0x00, 0x28, 0x03, 0xCC, 0x3E, 0x2C, 0x7C, 0x57, 0xF0, 0xEF, 0xC2, 0x1F, 0x0C, 0xDA,
+ 0xEB, 0x7A, 0xC5, 0x8E, 0xB7, 0xE2, 0x2D, 0x67, 0x5D, 0xD6, 0xAD, 0xFC, 0x23, 0xE0, 0x1F, 0x87,
+ 0xFE, 0x10, 0xB3, 0x87, 0x52, 0xF1, 0xD7, 0xC4, 0xBD, 0x7A, 0xF1, 0x24, 0x6B, 0x1D, 0x0F, 0x44,
+ 0xB4, 0x96, 0x58, 0x61, 0x69, 0xDD, 0x2D, 0xAE, 0x66, 0x92, 0x7B, 0x89, 0xAD, 0xED, 0x2C, 0xED,
+ 0x6D, 0xAF, 0xAF, 0xEF, 0x6E, 0x6D, 0x2C, 0x6C, 0x6E, 0xAE, 0xED, 0x80, 0x38, 0x7F, 0x84, 0x9F,
+ 0x09, 0xFC, 0x47, 0x6B, 0xAF, 0xDD, 0xFC, 0x69, 0xF8, 0xD5, 0x75, 0xA3, 0xEB, 0xFF, 0x00, 0x1D,
+ 0x7C, 0x49, 0xA2, 0xB6, 0x83, 0x1D, 0xA6, 0x81, 0x73, 0x75, 0x7B, 0xF0, 0xFF, 0x00, 0xE0, 0xA6,
+ 0x81, 0x2D, 0xC2, 0xDC, 0x27, 0x84, 0x3C, 0x22, 0x97, 0x01, 0x4B, 0x2E, 0xF8, 0xED, 0x1B, 0x52,
+ 0xD6, 0x0C, 0x16, 0xD7, 0x5A, 0xE5, 0xCD, 0xA5, 0xAC, 0xF3, 0xC3, 0x6B, 0x67, 0x63, 0xA4, 0x69,
+ 0x1A, 0x18, 0x07, 0xD0, 0xF4, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0x62, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00, 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00,
+ 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57, 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8,
+ 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9, 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B,
+ 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33, 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE,
+ 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27, 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F,
+ 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F, 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19,
+ 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99, 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x08, 0x7E, 0xE9, 0xFF, 0x00, 0x77, 0xFA,
+ 0x50, 0x04, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0xC0, 0x1D, 0x80, 0x03, 0xD8,
+ 0x00, 0x00, 0xA0, 0x05, 0xDA, 0x7F, 0xBA, 0x7F, 0x2A, 0x00, 0xF0, 0x9F, 0xDA, 0x17, 0xE2, 0x0E,
+ 0xA5, 0xE0, 0x2F, 0x03, 0xE9, 0x5A, 0x7F, 0x87, 0x3C, 0x33, 0xA4, 0x78, 0xC3, 0xC6, 0xBF, 0x13,
+ 0xFC, 0x6B, 0xA4, 0xFC, 0x23, 0xF0, 0x4F, 0x86, 0x7C, 0x45, 0x84, 0xF0, 0xC5, 0xDD, 0xD6, 0xB9,
+ 0x71, 0xB2, 0xFA, 0xF7, 0x55, 0x2C, 0x55, 0x1E, 0xC7, 0x4F, 0xD2, 0xE2, 0xD6, 0x35, 0x29, 0xED,
+ 0xFC, 0xC8, 0xA4, 0xBA, 0x8B, 0x4F, 0x92, 0xCE, 0x06, 0x37, 0x37, 0x50, 0x23, 0x80, 0x51, 0xF1,
+ 0xBC, 0xBF, 0x1C, 0x7C, 0x16, 0xFF, 0x00, 0x00, 0x3C, 0x33, 0xF0, 0x5B, 0xC0, 0x7F, 0x0D, 0x3C,
+ 0x41, 0xE1, 0x8F, 0xF8, 0x4B, 0xB4, 0xFF, 0x00, 0x0B, 0xFC, 0x5E, 0x7B, 0xA9, 0x5B, 0xC0, 0xBA,
+ 0x27, 0x83, 0x7C, 0x33, 0x6F, 0x65, 0xB6, 0xE6, 0xEB, 0x45, 0xB3, 0x49, 0x64, 0x6B, 0x34, 0x8A,
+ 0x38, 0x65, 0x6B, 0x68, 0xE2, 0x8F, 0x54, 0x66, 0xB9, 0x8B, 0x4B, 0xD3, 0x1E, 0xDE, 0xDE, 0xD7,
+ 0x52, 0xBB, 0xF1, 0x07, 0x86, 0xC0, 0x31, 0xFE, 0x39, 0x7E, 0xD1, 0xD6, 0xBF, 0xB3, 0xF7, 0x8E,
+ 0xBE, 0x12, 0xDB, 0x78, 0xE7, 0xC2, 0x9A, 0xFB, 0x7C, 0x1F, 0xF8, 0x91, 0x67, 0xAE, 0xF8, 0x66,
+ 0xFB, 0xE2, 0x47, 0x85, 0x7C, 0x2F, 0xAF, 0xFC, 0x44, 0xD6, 0x7C, 0x3D, 0xE3, 0x58, 0x64, 0xD3,
+ 0x25, 0xF0, 0x87, 0x86, 0x8F, 0x87, 0xB4, 0x6D, 0x3A, 0xF2, 0xF4, 0xC3, 0xAA, 0xD8, 0x7F, 0xC2,
+ 0x69, 0x20, 0xBF, 0x91, 0x62, 0xB7, 0x86, 0xE3, 0x48, 0xB0, 0xB2, 0x2E, 0x6E, 0x35, 0x6B, 0x38,
+ 0xA5, 0x00, 0x8B, 0xE0, 0x7F, 0xED, 0x27, 0x65, 0xF1, 0xEB, 0xE2, 0x77, 0xC6, 0x8F, 0x0E, 0xF8,
+ 0x2F, 0xC2, 0x9E, 0x22, 0xB7, 0xF8, 0x69, 0xF0, 0x8B, 0x4B, 0xF0, 0xAE, 0x85, 0x2F, 0x8E, 0x7C,
+ 0x5B, 0xE1, 0x4F, 0x10, 0x7C, 0x37, 0xF1, 0x1D, 0xEF, 0x8D, 0x35, 0x6B, 0x7B, 0xFD, 0x43, 0xC4,
+ 0x1E, 0x18, 0xB8, 0xF0, 0xD6, 0xB5, 0xA7, 0x59, 0x5F, 0x40, 0x96, 0x1A, 0x1D, 0xCF, 0xC3, 0xDD,
+ 0x41, 0x2E, 0xC2, 0x3C, 0x37, 0x2B, 0xE2, 0x4D, 0x88, 0xDB, 0xAC, 0xE5, 0x00, 0x03, 0xB5, 0xF8,
+ 0x6F, 0xAC, 0xFC, 0x74, 0xD4, 0xFE, 0x20, 0x7C, 0x6B, 0xD3, 0xBE, 0x27, 0x78, 0x33, 0xC1, 0x9E,
+ 0x1E, 0xF8, 0x69, 0xA2, 0xF8, 0x87, 0x4F, 0xB3, 0xF8, 0x23, 0xAF, 0xE8, 0x3A, 0xDB, 0xDD, 0xF8,
+ 0x8F, 0xC5, 0x96, 0x32, 0x58, 0x97, 0xD4, 0x9E, 0xFE, 0xD3, 0x74, 0x89, 0xE4, 0xC6, 0xED, 0x64,
+ 0x63, 0xB9, 0x73, 0x63, 0x33, 0x5C, 0x4D, 0xAA, 0xD8, 0x9D, 0x3B, 0xEC, 0xDA, 0x55, 0x9E, 0xB7,
+ 0xE2, 0x60, 0x0E, 0x0F, 0xF6, 0x60, 0xF8, 0x99, 0xA6, 0x6A, 0x3F, 0x0D, 0x7C, 0x5D, 0xE0, 0x4F,
+ 0x10, 0x68, 0xBE, 0x08, 0xF8, 0x6F, 0xE2, 0x9F, 0xD9, 0x4B, 0xC5, 0xD7, 0x3F, 0x00, 0x7E, 0x29,
+ 0xF8, 0x5F, 0xC1, 0xBA, 0x29, 0xF0, 0x57, 0xC3, 0x0F, 0x08, 0x1D, 0x0B, 0x46, 0xB0, 0xD4, 0xB4,
+ 0x1B, 0xED, 0x12, 0xD5, 0x9E, 0x4B, 0x5B, 0x1D, 0x22, 0xFF, 0x00, 0xC2, 0x7A, 0xDF, 0x84, 0x75,
+ 0x98, 0x2C, 0xE2, 0xBB, 0xBC, 0x5D, 0x32, 0x0D, 0x56, 0x3D, 0x36, 0x7B, 0x86, 0xBA, 0xD3, 0xAE,
+ 0x96, 0x30, 0x07, 0x78, 0x43, 0xF6, 0x98, 0x8F, 0xE3, 0x16, 0xBF, 0xE1, 0x08, 0x3F, 0x67, 0xAF,
+ 0x00, 0xEB, 0x5F, 0x13, 0x7E, 0x1A, 0xEA, 0xD1, 0xA6, 0xBF, 0xE2, 0x1F, 0x8F, 0x9A, 0xE7, 0xDB,
+ 0x7E, 0x1B, 0xFC, 0x13, 0x1A, 0x0C, 0x86, 0x1F, 0xB0, 0xDE, 0xF8, 0x3B, 0x56, 0xB8, 0xB1, 0x96,
+ 0x4F, 0x17, 0x4D, 0xA8, 0x45, 0x72, 0x6E, 0xB4, 0xF9, 0x74, 0x98, 0x25, 0xD2, 0x27, 0xB4, 0xB6,
+ 0xB8, 0x9E, 0x5D, 0x62, 0xD4, 0x4F, 0xA6, 0xA6, 0xA8, 0x01, 0xF4, 0x3D, 0xC7, 0x85, 0x7C, 0x2F,
+ 0x77, 0xE2, 0x7D, 0x1F, 0xC6, 0xD7, 0x5E, 0x1C, 0xD0, 0xAE, 0x7C, 0x67, 0xE1, 0xED, 0x03, 0x52,
+ 0xF0, 0xAE, 0x81, 0xE2, 0xD9, 0xF4, 0x8B, 0x79, 0xBC, 0x4D, 0xA1, 0xE9, 0x7A, 0xC5, 0xC5, 0x8C,
+ 0xFA, 0xBE, 0x9B, 0x67, 0x7E, 0x50, 0xCF, 0x0D, 0xAD, 0xD4, 0xFA, 0x16, 0x89, 0x2C, 0xF0, 0xA3,
+ 0x2A, 0x4C, 0xFA, 0x75, 0x83, 0xBA, 0xB3, 0x5B, 0x44, 0x50, 0x03, 0xF3, 0x7F, 0xE2, 0x77, 0xED,
+ 0xB5, 0xFB, 0x50, 0x78, 0x5B, 0xC7, 0x9F, 0x0C, 0xFC, 0x31, 0xA3, 0x7E, 0xC0, 0x5F, 0x15, 0x7E,
+ 0x1E, 0x78, 0x77, 0xC7, 0x9E, 0x3A, 0x9F, 0xE1, 0x6D, 0xB7, 0xC4, 0xBF, 0xDA, 0x6F, 0xE2, 0x7F,
+ 0xC3, 0x2F, 0x06, 0xFC, 0x0D, 0x93, 0x5D, 0xBD, 0x8C, 0xB7, 0x85, 0xE3, 0xD4, 0xBC, 0x53, 0xE0,
+ 0xFF, 0x00, 0x15, 0x78, 0xAF, 0x58, 0xD0, 0x6D, 0xB5, 0x19, 0x2C, 0xAE, 0xEC, 0x6C, 0xE5, 0xB9,
+ 0xF0, 0xCD, 0xCF, 0xDB, 0x35, 0x6D, 0x47, 0xC3, 0x5A, 0x48, 0x16, 0xD3, 0x6A, 0x89, 0x24, 0x60,
+ 0x1F, 0x78, 0xFC, 0x24, 0xF8, 0x97, 0x67, 0xF1, 0x5F, 0xC2, 0x17, 0xDE, 0x2E, 0xB2, 0xD2, 0xAE,
+ 0x74, 0x7B, 0x7B, 0x1F, 0x88, 0x5E, 0x31, 0xF8, 0x7F, 0xF6, 0x2B, 0x89, 0xD6, 0xEE, 0x69, 0x1F,
+ 0xC1, 0xFE, 0x2E, 0xD4, 0xF4, 0x19, 0xAE, 0x43, 0x2A, 0x80, 0x16, 0x77, 0xD0, 0xDE, 0x65, 0x4C,
+ 0x12, 0xAB, 0x2A, 0xA1, 0x24, 0xAE, 0x48, 0x07, 0xC8, 0xBF, 0x16, 0x3F, 0x6B, 0x9F, 0x8B, 0xB7,
+ 0x1E, 0x24, 0xFD, 0x92, 0xF4, 0x9F, 0xD9, 0x47, 0xE0, 0x4D, 0xAF, 0xC5, 0xDF, 0x0D, 0x7E, 0xD2,
+ 0xAD, 0x2F, 0x8A, 0x2D, 0x7E, 0x2B, 0x7C, 0x4E, 0xF1, 0xB6, 0x9B, 0xF0, 0x8B, 0xE0, 0xB4, 0x7A,
+ 0x18, 0xF0, 0x66, 0xB3, 0xAA, 0xC1, 0xA6, 0x5C, 0x5D, 0x89, 0xEE, 0xFC, 0x5F, 0xA7, 0x6A, 0xEF,
+ 0x2E, 0x9F, 0xA2, 0x4C, 0x8D, 0x1F, 0x84, 0x75, 0x6B, 0x63, 0x0C, 0x93, 0x5B, 0xCA, 0xD6, 0xD2,
+ 0x48, 0xD7, 0x16, 0x20, 0x1E, 0xAD, 0xE3, 0x0F, 0xDA, 0xAF, 0xC3, 0x36, 0x3F, 0x06, 0xFE, 0x26,
+ 0x7C, 0x53, 0xF0, 0x87, 0xFC, 0x23, 0x5E, 0x1F, 0x1F, 0x0B, 0x2D, 0x2C, 0x75, 0x0F, 0x12, 0xEA,
+ 0x5F, 0xB5, 0xAC, 0xDE, 0x2F, 0xFD, 0x8C, 0x3E, 0x0F, 0x69, 0x16, 0xB3, 0xDD, 0x2A, 0xDE, 0xDD,
+ 0xDF, 0x78, 0xBF, 0x5B, 0xF0, 0xBC, 0xA6, 0x28, 0x21, 0xB7, 0x8E, 0xED, 0xC4, 0xB0, 0xD8, 0xDC,
+ 0x21, 0x91, 0x2D, 0xA2, 0x95, 0xAD, 0xD6, 0xE0, 0x4A, 0x80, 0x1F, 0x02, 0xFE, 0xC5, 0x9F, 0xF0,
+ 0x55, 0x0D, 0x5F, 0xF6, 0xAA, 0xFD, 0xA1, 0xBE, 0x37, 0xFC, 0x1B, 0xB1, 0xF1, 0x6F, 0xFC, 0x13,
+ 0x67, 0xC7, 0x76, 0x5E, 0x02, 0xF8, 0x9C, 0xFA, 0x2F, 0x82, 0xB4, 0x5F, 0xD9, 0xBB, 0xF6, 0xFE,
+ 0x4F, 0x8A, 0xBF, 0x18, 0x3C, 0x57, 0xE1, 0xCB, 0x7F, 0x86, 0x3E, 0x1D, 0xD7, 0x2E, 0x35, 0x2F,
+ 0x0D, 0x68, 0x72, 0x78, 0x72, 0xDE, 0xDF, 0xC5, 0x10, 0x2E, 0xB9, 0xAE, 0x6A, 0xB6, 0x52, 0xEA,
+ 0x22, 0xE7, 0x43, 0xB6, 0xB6, 0x30, 0x5D, 0x5A, 0x3C, 0x4F, 0x2E, 0x93, 0x25, 0xCE, 0xA2, 0x01,
+ 0xF4, 0x25, 0xAF, 0xED, 0x8B, 0xFB, 0x4E, 0xEB, 0x7F, 0x1F, 0x7E, 0x08, 0xFC, 0x32, 0x97, 0xF6,
+ 0x1C, 0xF1, 0xD7, 0xC0, 0x1F, 0x06, 0xFC, 0x4B, 0xD3, 0xF5, 0xEB, 0x3B, 0xEF, 0x10, 0xFE, 0xD6,
+ 0x9F, 0x16, 0xBE, 0x1A, 0x78, 0x5A, 0x2F, 0x11, 0x6A, 0xFA, 0x6C, 0xBA, 0x65, 0xDC, 0x1A, 0x57,
+ 0x83, 0xEF, 0xBC, 0x11, 0xE2, 0x7F, 0x18, 0x35, 0xE6, 0xB1, 0x1E, 0x85, 0x17, 0x8D, 0xB5, 0x01,
+ 0xA4, 0x5D, 0xD8, 0x59, 0x8B, 0xB8, 0x74, 0xAB, 0x89, 0xD3, 0x50, 0xB6, 0x8B, 0x4E, 0xBA, 0xDE,
+ 0x01, 0xF5, 0x07, 0xC1, 0x0F, 0xDA, 0x23, 0x41, 0xF8, 0xC5, 0xFB, 0x27, 0x7C, 0x21, 0xFD, 0xAC,
+ 0xA4, 0xF0, 0xFE, 0xB7, 0xE1, 0x9F, 0x0C, 0x7C, 0x53, 0xFD, 0x9D, 0xBC, 0x3F, 0xFB, 0x44, 0xBF,
+ 0x85, 0x2D, 0x6D, 0x67, 0xF1, 0x8F, 0x88, 0xFC, 0x3F, 0x61, 0xAE, 0x78, 0x66, 0xDF, 0x59, 0x3A,
+ 0x74, 0x70, 0x59, 0xC2, 0x66, 0xBE, 0xB9, 0x86, 0x1B, 0xAF, 0x28, 0x25, 0xBC, 0x25, 0xE6, 0x74,
+ 0x01, 0x23, 0xCB, 0xAA, 0xD0, 0x07, 0x80, 0xFC, 0x49, 0xFD, 0xAF, 0x7E, 0x2A, 0x5A, 0xFE, 0xD0,
+ 0xFF, 0x00, 0x04, 0xBE, 0x0E, 0xFC, 0x11, 0xF8, 0x1D, 0x67, 0xE3, 0x7F, 0x05, 0xFC, 0x44, 0xF8,
+ 0x3F, 0xAF, 0x7E, 0xD0, 0xFA, 0xA7, 0xC6, 0x1F, 0x1D, 0x78, 0xDA, 0xCB, 0xC3, 0x5F, 0x0E, 0x3C,
+ 0x51, 0xE0, 0xBD, 0x01, 0xB4, 0x38, 0x35, 0x29, 0x7C, 0x1E, 0xFA, 0x33, 0xEB, 0x1E, 0x23, 0xB8,
+ 0xD6, 0x6D, 0xAE, 0x3C, 0x69, 0xE1, 0xA2, 0x2C, 0x6E, 0xFC, 0x39, 0x6F, 0x6F, 0x79, 0x1D, 0xE1,
+ 0x10, 0xEA, 0x08, 0xD0, 0xB0, 0x60, 0x0E, 0xDF, 0xE2, 0xEF, 0xED, 0x7D, 0xA0, 0x78, 0x2B, 0xE0,
+ 0x76, 0xA7, 0xF1, 0xD7, 0xC2, 0x97, 0x7F, 0x09, 0x7C, 0x27, 0xE0, 0xDF, 0x0A, 0xF8, 0xD6, 0xD7,
+ 0xC2, 0xBE, 0x37, 0xF1, 0x37, 0xED, 0xC3, 0xE3, 0xFF, 0x00, 0x13, 0xFE, 0xC0, 0xBF, 0x0F, 0xBC,
+ 0x37, 0x05, 0xD4, 0x28, 0xB0, 0xDC, 0xAE, 0xB1, 0xAE, 0x78, 0x4E, 0xEE, 0x69, 0x64, 0x92, 0xF2,
+ 0xFF, 0x00, 0x46, 0xB6, 0x85, 0x4D, 0x9C, 0x76, 0xF3, 0x3D, 0xC4, 0xE8, 0xB7, 0x5E, 0x75, 0xBF,
+ 0xD9, 0xE5, 0x00, 0xF9, 0x47, 0xFE, 0x09, 0xB5, 0xFF, 0x00, 0x05, 0x28, 0xD5, 0xBF, 0x6E, 0x1D,
+ 0x4F, 0xC5, 0x3E, 0x1F, 0xBE, 0xF1, 0x7F, 0xFC, 0x13, 0xE3, 0xC4, 0x5A, 0xBF, 0x86, 0x3C, 0x73,
+ 0xF1, 0x32, 0xD2, 0xFB, 0x43, 0xFD, 0x99, 0x7F, 0x6D, 0x49, 0x7E, 0x2F, 0xFC, 0x54, 0xD3, 0x7C,
+ 0x3B, 0xE1, 0x5F, 0x88, 0xFA, 0x9E, 0x83, 0xE1, 0x8D, 0x66, 0x5F, 0x04, 0x9F, 0x0F, 0xC4, 0xED,
+ 0xA5, 0x5D, 0xE9, 0xF6, 0x9A, 0x24, 0xCB, 0xAC, 0xB6, 0xA3, 0x0C, 0x37, 0xAB, 0x7B, 0x69, 0x7B,
+ 0x0D, 0x9D, 0xAA, 0x6A, 0x11, 0x59, 0x5A, 0x80, 0x7E, 0x91, 0x5F, 0x7C, 0x4B, 0x9E, 0xCB, 0xE3,
+ 0xB7, 0x85, 0x7E, 0x0E, 0x2E, 0x8D, 0x0B, 0xDA, 0x78, 0x8B, 0xE1, 0x26, 0xBF, 0xF1, 0x2D, 0xF5,
+ 0xFF, 0x00, 0xB6, 0xB2, 0x4F, 0x67, 0x26, 0x89, 0xAC, 0x68, 0xD6, 0x29, 0x64, 0xB6, 0xBE, 0x5E,
+ 0xD6, 0x59, 0x17, 0x5F, 0x77, 0x2F, 0xBC, 0x15, 0x30, 0x2A, 0x85, 0x3B, 0xF2, 0xA0, 0x1E, 0xB5,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x01, 0x62, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00,
+ 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57,
+ 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9,
+ 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33,
+ 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27,
+ 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F,
+ 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99,
+ 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x08, 0x7E, 0xE9, 0xFF, 0x00, 0x77, 0xFA, 0x50, 0x04, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x00, 0x38, 0x00, 0x0E, 0x30, 0x00, 0x18, 0xE3, 0x18, 0x1C, 0x63, 0xF2,
+ 0x14, 0x01, 0xF2, 0x3C, 0xBF, 0xB0, 0x07, 0xEC, 0x1D, 0x71, 0x2C, 0x93, 0xCF, 0xFB, 0x12, 0xFE,
+ 0xC8, 0xB3, 0x4F, 0x34, 0x8D, 0x2C, 0xD3, 0x4B, 0xFB, 0x36, 0x78, 0x32, 0x49, 0x65, 0x76, 0x39,
+ 0x66, 0x66, 0x3A, 0x76, 0x49, 0x24, 0x92, 0x49, 0xA0, 0x0C, 0x4F, 0x1F, 0x7E, 0xC9, 0x9E, 0x02,
+ 0xF0, 0x2F, 0xC3, 0x9B, 0x46, 0xFD, 0x93, 0x7E, 0x16, 0xFC, 0x06, 0xF8, 0x23, 0xE3, 0x3F, 0x00,
+ 0xFC, 0x4B, 0xD1, 0xFE, 0x37, 0xE8, 0x1A, 0x16, 0x87, 0xE0, 0x3D, 0x3F, 0xE1, 0x8F, 0xC3, 0x8F,
+ 0x1E, 0x6A, 0x3A, 0x1A, 0xBC, 0x57, 0x7A, 0x4F, 0x88, 0x26, 0xD2, 0x6D, 0x51, 0xED, 0x52, 0xFB,
+ 0x49, 0xBB, 0xD5, 0x74, 0xF4, 0xD4, 0xC4, 0x17, 0x8F, 0xA7, 0x3D, 0xD4, 0x17, 0xDF, 0x63, 0xBF,
+ 0x5B, 0x33, 0x61, 0x76, 0x01, 0xF6, 0x46, 0x9F, 0x74, 0x2F, 0xEC, 0x2C, 0x6F, 0x84, 0x2F, 0x6E,
+ 0x2F, 0x2C, 0xE2, 0xBA, 0x16, 0xF2, 0x49, 0x0C, 0xD2, 0x40, 0x24, 0x8C, 0x30, 0x46, 0x78, 0x5E,
+ 0x48, 0x98, 0x8C, 0xE0, 0x98, 0xDD, 0xD4, 0xE3, 0xE5, 0x66, 0x18, 0x24, 0x03, 0xCA, 0xBE, 0x3C,
+ 0x7C, 0x24, 0x83, 0xE3, 0x67, 0xC2, 0xCF, 0x11, 0xF8, 0x01, 0x3C, 0x43, 0xAB, 0x78, 0x2B, 0x5F,
+ 0x9D, 0xAC, 0xFC, 0x47, 0xE0, 0x0F, 0x88, 0x1E, 0x1F, 0xF2, 0x8E, 0xBB, 0xF0, 0xDB, 0xC5, 0x1A,
+ 0x1D, 0xEC, 0x3A, 0x87, 0x85, 0xFC, 0x47, 0x67, 0x0C, 0xA9, 0x25, 0xB5, 0xC3, 0xD8, 0x6A, 0x96,
+ 0x1A, 0x75, 0xC9, 0xB4, 0xBB, 0x86, 0xE2, 0xCE, 0xE9, 0x61, 0x7B, 0x5B, 0xBB, 0x7B, 0x8B, 0x5B,
+ 0x89, 0xED, 0xE5, 0x00, 0xA5, 0xFB, 0x3C, 0x7C, 0x29, 0x9F, 0xE0, 0xF7, 0xC2, 0xAF, 0x0F, 0xF8,
+ 0x6B, 0x5B, 0x9E, 0xD7, 0x54, 0xF8, 0x83, 0xAB, 0xBC, 0xFE, 0x39, 0xF8, 0xC3, 0xE2, 0x8B, 0x5D,
+ 0x46, 0xEF, 0x57, 0x8F, 0xC6, 0xBE, 0x34, 0xD7, 0x24, 0x37, 0x9E, 0x29, 0xD5, 0xE3, 0xB8, 0xB9,
+ 0x02, 0x61, 0x6F, 0x2D, 0xFC, 0xF7, 0x22, 0xDA, 0xDC, 0x24, 0x30, 0x5A, 0x5A, 0x25, 0x9D, 0x95,
+ 0xAD, 0xBD, 0xAD, 0xAD, 0xA5, 0xBD, 0xAD, 0xB8, 0x07, 0xB6, 0x8C, 0x70, 0x38, 0x03, 0x81, 0xD3,
+ 0xA7, 0xA0, 0x03, 0xF2, 0xA0, 0x0F, 0x8E, 0x3E, 0x09, 0xFE, 0xCF, 0xFA, 0x0F, 0x88, 0x7E, 0x1C,
+ 0xFC, 0x5C, 0xD6, 0xBE, 0x39, 0xF8, 0x6F, 0xE1, 0xF7, 0xC4, 0x4D, 0x43, 0xF6, 0xB8, 0xF8, 0xA3,
+ 0x1F, 0xED, 0x03, 0xF1, 0x3B, 0xC1, 0x33, 0xE9, 0x76, 0x5E, 0x32, 0xF8, 0x5D, 0x62, 0xD1, 0xE8,
+ 0xBA, 0x26, 0x95, 0xE1, 0x1D, 0x26, 0xD2, 0x29, 0x9A, 0xE6, 0xDE, 0xF0, 0xE9, 0xDA, 0x0F, 0x82,
+ 0xBC, 0x19, 0x1C, 0xB7, 0xCA, 0xED, 0x1D, 0xDE, 0xA3, 0x67, 0x79, 0xA9, 0x5B, 0xC7, 0x69, 0x1D,
+ 0xCC, 0x36, 0xB6, 0x80, 0x1D, 0x47, 0x84, 0xBE, 0x02, 0xF8, 0xE3, 0xE1, 0x57, 0x8A, 0x2D, 0xA4,
+ 0xF8, 0x4B, 0xF1, 0xBB, 0xC4, 0x16, 0xBF, 0x0A, 0x6F, 0xB5, 0xE3, 0xA8, 0xEB, 0xFF, 0x00, 0x06,
+ 0x7E, 0x2F, 0xE9, 0x57, 0x1F, 0x19, 0x34, 0x4F, 0x0E, 0x5A, 0xCB, 0x71, 0x24, 0xD7, 0x76, 0xBE,
+ 0x06, 0xD6, 0xE4, 0xBF, 0xB4, 0xD6, 0x34, 0x61, 0x2C, 0x97, 0x0C, 0xB1, 0xDB, 0xDE, 0xDD, 0xEB,
+ 0x1A, 0x6D, 0x94, 0x31, 0x5B, 0x5B, 0x58, 0x69, 0xB6, 0x50, 0x42, 0x22, 0x20, 0x1F, 0x49, 0x3E,
+ 0xA5, 0xA6, 0xC3, 0xA8, 0xD9, 0xE8, 0xF2, 0xDF, 0xD8, 0xC7, 0xAB, 0x5F, 0x59, 0x5C, 0x6A, 0x56,
+ 0x3A, 0x53, 0xDD, 0x46, 0x9A, 0x8D, 0xE5, 0xB5, 0xA4, 0x90, 0x47, 0x75, 0x71, 0x0C, 0x04, 0xEF,
+ 0x78, 0xA2, 0x7B, 0xDB, 0x25, 0x77, 0x50, 0x55, 0x0C, 0xF0, 0x82, 0x41, 0x91, 0x41, 0x00, 0xFC,
+ 0x9F, 0xF0, 0xC7, 0xFC, 0x13, 0xFD, 0x6D, 0x7C, 0x7B, 0xE1, 0xAF, 0x0A, 0xFC, 0x54, 0xFD, 0x97,
+ 0x3F, 0x63, 0x3F, 0x8D, 0x9E, 0x05, 0x83, 0x50, 0xB4, 0xD7, 0xFC, 0x4D, 0xFB, 0x6B, 0xDC, 0x78,
+ 0xB3, 0x5A, 0xF8, 0x61, 0xFB, 0x72, 0x6B, 0x5A, 0x8E, 0x8B, 0x2A, 0xEA, 0x1E, 0x1E, 0xD5, 0x35,
+ 0x6D, 0x36, 0xD7, 0xC3, 0x37, 0x2D, 0xAB, 0x6B, 0x71, 0xEA, 0xDA, 0x4F, 0x87, 0xE7, 0x9F, 0x56,
+ 0x4F, 0x17, 0xE9, 0x6A, 0xF3, 0xA3, 0x5F, 0xC1, 0xA7, 0xDA, 0x9B, 0x4B, 0x7B, 0x26, 0x00, 0xFB,
+ 0x3B, 0xF6, 0x7F, 0xF8, 0x6B, 0xF1, 0x77, 0xE1, 0x5E, 0xB9, 0xF1, 0x2B, 0xC2, 0x9E, 0x22, 0xBD,
+ 0xF8, 0x7D, 0x73, 0xF0, 0x73, 0xFE, 0x13, 0x8F, 0x12, 0xF8, 0xDF, 0xE1, 0x8D, 0xE6, 0x89, 0x75,
+ 0xA8, 0x5D, 0xFC, 0x41, 0xD7, 0xEE, 0x7C, 0x67, 0xE2, 0xDD, 0x4F, 0xC4, 0x5A, 0xAB, 0x6B, 0x96,
+ 0xB2, 0xDB, 0x45, 0x6B, 0xA6, 0xA5, 0x8C, 0xBA, 0xE3, 0x69, 0xF0, 0xC5, 0x6F, 0x71, 0xA8, 0xFD,
+ 0xB1, 0x2D, 0xC5, 0xEB, 0xC9, 0x64, 0xD2, 0xFD, 0x86, 0x20, 0x0F, 0x16, 0xF0, 0xBF, 0xEC, 0x4F,
+ 0xA9, 0xF8, 0x07, 0xE2, 0xA7, 0x8C, 0x7C, 0x61, 0xF0, 0xE3, 0xC6, 0xD6, 0xDE, 0x0B, 0xB2, 0xD2,
+ 0xBE, 0x10, 0xFC, 0x5A, 0xD2, 0xBE, 0x02, 0xF8, 0xB2, 0x7B, 0x08, 0xFC, 0x5F, 0xE3, 0x3F, 0x03,
+ 0xF8, 0xDF, 0xF6, 0x82, 0xF8, 0xA7, 0x7D, 0xE3, 0x9F, 0x8A, 0xFA, 0xC6, 0xB1, 0xA6, 0x4F, 0x0C,
+ 0x56, 0x17, 0xDA, 0x6D, 0xBE, 0xAB, 0xA4, 0xFC, 0x39, 0x7D, 0x22, 0xD8, 0x3A, 0x32, 0xA5, 0xB6,
+ 0xB7, 0x05, 0xD3, 0x4C, 0x25, 0x82, 0x55, 0x00, 0xED, 0x6C, 0xEF, 0x7F, 0x6F, 0xDF, 0x18, 0x7C,
+ 0x3D, 0xF8, 0xA5, 0xA0, 0x78, 0x9F, 0xE1, 0xF7, 0xEC, 0xD3, 0xF0, 0x37, 0xC7, 0x03, 0xC2, 0x69,
+ 0x07, 0xC2, 0x5F, 0x1B, 0x7C, 0x33, 0xFD, 0xA6, 0xB5, 0xDF, 0x8E, 0x17, 0xBA, 0xB6, 0xA5, 0xE6,
+ 0x62, 0xE1, 0x35, 0x18, 0xB5, 0x5F, 0x86, 0x7A, 0x4D, 0x96, 0x88, 0xEF, 0x02, 0x6D, 0x86, 0xFB,
+ 0xEC, 0x7E, 0x21, 0x86, 0xDA, 0x79, 0x96, 0x79, 0x74, 0x8B, 0xF8, 0xAD, 0x8D, 0x95, 0xE0, 0x07,
+ 0x84, 0x7E, 0xC8, 0xDF, 0xB2, 0xDF, 0xED, 0xA3, 0xF0, 0x8E, 0xDF, 0xE2, 0xFE, 0xB3, 0xF1, 0x93,
+ 0xE3, 0xA7, 0x83, 0x3C, 0x55, 0xAD, 0xFE, 0xD4, 0x1F, 0x15, 0x6F, 0xFE, 0x22, 0x7C, 0x64, 0xD3,
+ 0xE3, 0x96, 0x1F, 0x13, 0xFC, 0x42, 0xF8, 0x79, 0x2C, 0x7F, 0x0F, 0xB4, 0x3F, 0x09, 0xE8, 0x57,
+ 0xDE, 0x19, 0xF8, 0x83, 0xA5, 0x78, 0x77, 0xC2, 0xBA, 0x5E, 0xA3, 0x71, 0x15, 0xBF, 0x81, 0xF4,
+ 0x8B, 0x87, 0x8A, 0x4F, 0x05, 0x69, 0x28, 0xA2, 0xED, 0x60, 0x59, 0x1E, 0x5D, 0x36, 0x4B, 0xED,
+ 0x74, 0x02, 0x2F, 0x83, 0x3F, 0xB0, 0x9D, 0x9F, 0x86, 0xBE, 0x26, 0xF8, 0x6C, 0x7C, 0x50, 0xFD,
+ 0x92, 0xFF, 0x00, 0x62, 0x31, 0x65, 0xF0, 0xBF, 0x52, 0xB0, 0xF8, 0x87, 0xE0, 0xAF, 0xDB, 0x1B,
+ 0xE0, 0x76, 0xBF, 0xAE, 0x7C, 0x2C, 0xFD, 0xA7, 0x3C, 0x73, 0xE2, 0xFD, 0x36, 0x58, 0x5E, 0x0D,
+ 0x47, 0x5B, 0xF0, 0xAC, 0x5E, 0x1F, 0x13, 0x59, 0x9B, 0x88, 0xEE, 0xF5, 0xCB, 0x6B, 0xF9, 0xDF,
+ 0xC6, 0xDA, 0xBF, 0xF6, 0x8C, 0x32, 0x5E, 0x47, 0x73, 0x6C, 0xF6, 0xDA, 0xD5, 0xDD, 0x9D, 0xB8,
+ 0x07, 0xD3, 0x1F, 0xB1, 0xDF, 0xC1, 0xCF, 0x8A, 0x9F, 0xB3, 0xDF, 0xC3, 0x1D, 0x0F, 0xE0, 0x57,
+ 0x8B, 0x2F, 0xBE, 0x1F, 0xCB, 0xF0, 0x97, 0xE0, 0x57, 0x82, 0xBC, 0x3D, 0xF0, 0x37, 0xF6, 0x75,
+ 0x87, 0xC2, 0xF7, 0x5A, 0x8E, 0xB7, 0xE3, 0x2D, 0x63, 0xC2, 0x9E, 0x14, 0xB2, 0x7B, 0x3D, 0x33,
+ 0x5D, 0xF1, 0x6D, 0xF5, 0xC4, 0x16, 0xB0, 0xC3, 0xAA, 0xCF, 0x60, 0x34, 0x6B, 0x49, 0xB4, 0xFB,
+ 0x58, 0x27, 0x82, 0x29, 0x74, 0xAB, 0x8B, 0xD4, 0xBE, 0x90, 0x6A, 0xC2, 0xC3, 0x48, 0x00, 0xF3,
+ 0xEF, 0x04, 0xFE, 0xC8, 0x5E, 0x27, 0xF8, 0x39, 0x69, 0xF1, 0x9F, 0x50, 0xF8, 0x2F, 0xE2, 0xFD,
+ 0x3B, 0xC3, 0x1E, 0x35, 0xBB, 0xFD, 0x97, 0xFE, 0x1B, 0xFE, 0xCA, 0x3F, 0xB3, 0xEF, 0x88, 0xB5,
+ 0x76, 0x4D, 0x6C, 0x68, 0x1E, 0x1D, 0xF8, 0x55, 0xA5, 0x6B, 0x52, 0x78, 0x5A, 0x7F, 0x11, 0x43,
+ 0x2D, 0x83, 0xC2, 0xD7, 0xE7, 0x58, 0xF1, 0xCF, 0x8A, 0x8C, 0xF3, 0xC5, 0x0C, 0xF0, 0xB5, 0xA9,
+ 0xD3, 0xF6, 0xDA, 0x89, 0x21, 0x91, 0x67, 0x00, 0xD2, 0xF1, 0x29, 0xFF, 0x00, 0x82, 0x84, 0xFC,
+ 0x43, 0xF8, 0x1F, 0xF1, 0x37, 0x49, 0x8F, 0xC2, 0x9F, 0xB3, 0xBF, 0xEC, 0xE1, 0xF1, 0xBC, 0x5C,
+ 0x69, 0x67, 0xE1, 0x6E, 0xAB, 0xF0, 0xA7, 0xF6, 0x97, 0xD4, 0xFE, 0x32, 0x69, 0x5A, 0xBD, 0xB2,
+ 0x5E, 0x23, 0xEB, 0x10, 0xDE, 0xEB, 0x5A, 0xFF, 0x00, 0xC2, 0xB8, 0x2D, 0xF4, 0x3B, 0x87, 0xB7,
+ 0x89, 0xA1, 0x86, 0x76, 0xF0, 0xF7, 0x88, 0xE3, 0x53, 0x33, 0x48, 0xD6, 0xD9, 0x8D, 0x55, 0x80,
+ 0x30, 0x3F, 0x61, 0xBF, 0xD9, 0xDF, 0xF6, 0xA0, 0xFD, 0x99, 0x7E, 0x1E, 0x78, 0x6B, 0xC0, 0x9F,
+ 0x14, 0xFE, 0x2C, 0x7C, 0x38, 0xF8, 0xB3, 0xA5, 0xEB, 0xFE, 0x34, 0xF8, 0x81, 0xF1, 0x5B, 0xE2,
+ 0x3C, 0x27, 0xC3, 0xB2, 0x58, 0xF8, 0xF3, 0xC2, 0xFE, 0x23, 0xF8, 0x87, 0xE3, 0x8D, 0x6F, 0xC5,
+ 0xB7, 0xED, 0x65, 0xE2, 0x9B, 0x3B, 0x6D, 0x3F, 0x4C, 0xD7, 0xAD, 0xED, 0xEF, 0x3C, 0x49, 0x2D,
+ 0x83, 0x11, 0xE1, 0x9F, 0x0E, 0x0B, 0x81, 0xBF, 0x50, 0x8E, 0x2B, 0x15, 0x0B, 0xA4, 0x80, 0x0F,
+ 0xA6, 0xB5, 0x5F, 0x04, 0x78, 0xAA, 0xE3, 0xF6, 0x8B, 0xF0, 0x17, 0xC4, 0x6B, 0x2D, 0x17, 0xC0,
+ 0x32, 0x78, 0x23, 0x46, 0xF8, 0x2B, 0xE2, 0xDF, 0x04, 0x78, 0x8B, 0xC4, 0x17, 0xDA, 0xCE, 0xB7,
+ 0x17, 0xC5, 0x0B, 0x2D, 0x53, 0x52, 0xD7, 0x3C, 0x39, 0x75, 0xA3, 0x59, 0x69, 0x7A, 0x74, 0x7F,
+ 0xF1, 0x27, 0x93, 0x4B, 0x96, 0x0D, 0x27, 0x5C, 0x7B, 0xB9, 0xAE, 0x00, 0xBA, 0x8E, 0x68, 0x34,
+ 0x94, 0xB7, 0xFD, 0xD4, 0xD7, 0x58, 0x00, 0xF6, 0xBA, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0B, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xF9, 0xF9, 0xFF, 0x00, 0xC1, 0xCF, 0xBF, 0xF2, 0x9C,
+ 0xFF, 0x00, 0xF8, 0x24, 0x3F, 0xFD, 0x82, 0xBE, 0x1E, 0xFF, 0x00, 0xEA, 0xDE, 0xB9, 0xAE, 0xCC,
+ 0xB3, 0xFE, 0x46, 0x18, 0x7F, 0xF1, 0xC3, 0xFF, 0x00, 0x4A, 0x47, 0x3E, 0x27, 0xFD, 0xD6, 0xA7,
+ 0xF8, 0x5F, 0xE4, 0x7D, 0xA9, 0x5F, 0xA9, 0x9F, 0x1C, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F, 0xB0,
+ 0x5F, 0xF0, 0x44, 0x2F, 0xF9, 0x11, 0x3F, 0x6E, 0xBF, 0xFB, 0x3E, 0x78, 0x3F, 0xF5, 0x43, 0x7C,
+ 0x32, 0xAF, 0xCE, 0xB8, 0x83, 0xFE, 0x46, 0x93, 0xF4, 0x8F, 0xFE, 0x92, 0x8F, 0xA8, 0xCA, 0xFF,
+ 0x00, 0xDC, 0xA3, 0xF3, 0xFC, 0xCF, 0xDB, 0x6A, 0xF1, 0x4F, 0x44, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x43, 0xF7, 0x4F, 0xFB, 0xBF, 0xD2, 0x80,
+ 0x20, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x01, 0x0A, 0xAB, 0x29,
+ 0x42, 0xA0, 0xA9, 0x5D, 0xA5, 0x48, 0x1B, 0x48, 0x23, 0x90, 0x45, 0x00, 0x7C, 0x52, 0x73, 0xFB,
+ 0x14, 0xEE, 0x75, 0x56, 0x7F, 0xD8, 0xB4, 0xE3, 0x31, 0xC6, 0x92, 0x4D, 0x2F, 0xEC, 0x62, 0x71,
+ 0x2B, 0xCD, 0x34, 0x92, 0x34, 0xAC, 0x4F, 0xC3, 0xB3, 0x8B, 0x68, 0xE3, 0x86, 0x28, 0xC7, 0xFC,
+ 0x22, 0xDC, 0xF5, 0xF0, 0xE9, 0xFF, 0x00, 0x8A, 0x28, 0x03, 0xED, 0x71, 0x8C, 0x71, 0x8C, 0x0E,
+ 0x38, 0x18, 0xC6, 0x3B, 0x63, 0xF0, 0xA0, 0x03, 0xA0, 0xE0, 0x70, 0x07, 0x00, 0x0E, 0xC0, 0x70,
+ 0x00, 0xFC, 0xA8, 0x03, 0xE3, 0x02, 0xE3, 0xF6, 0xCE, 0x02, 0x3B, 0x77, 0x82, 0x4F, 0xD8, 0xC5,
+ 0xD0, 0xAD, 0xC5, 0xC2, 0x7D, 0x9E, 0xFE, 0xD3, 0xF6, 0xCD, 0x89, 0xE3, 0x85, 0x92, 0x38, 0x72,
+ 0xB2, 0x45, 0x27, 0xC3, 0xB7, 0x49, 0x6E, 0x23, 0x93, 0xEE, 0x3F, 0x88, 0x99, 0x30, 0xB8, 0xD0,
+ 0x79, 0xF1, 0x68, 0x07, 0xD9, 0x91, 0xC7, 0x1C, 0x31, 0xC7, 0x0C, 0x48, 0xB1, 0xC5, 0x14, 0x6B,
+ 0x14, 0x51, 0xA2, 0x85, 0x48, 0xD5, 0x46, 0x15, 0x54, 0x76, 0x00, 0x00, 0x31, 0x40, 0x0F, 0xA0,
+ 0x0F, 0x2E, 0xF8, 0xA9, 0xF0, 0xAB, 0x47, 0xF8, 0xA5, 0xA4, 0x69, 0x51, 0x4B, 0xA9, 0xEA, 0x9E,
+ 0x13, 0xF1, 0x77, 0x84, 0xB5, 0x43, 0xE2, 0x3F, 0x87, 0x5F, 0x11, 0x7C, 0x34, 0x96, 0xDF, 0xF0,
+ 0x96, 0x7C, 0x3B, 0xD5, 0xBE, 0xCD, 0x25, 0xB8, 0xBF, 0xD3, 0xCD, 0xC4, 0x52, 0xDB, 0xB8, 0x7B,
+ 0x7B, 0x9B, 0x98, 0x26, 0x82, 0x78, 0xA5, 0x82, 0xE2, 0x09, 0xA7, 0x82, 0x68, 0xDE, 0x39, 0x19,
+ 0x48, 0x07, 0x39, 0xF0, 0xAF, 0xE2, 0xA6, 0xAD, 0xAD, 0x6A, 0xD7, 0xFF, 0x00, 0x0B, 0x7E, 0x29,
+ 0xE9, 0xBA, 0x4F, 0x84, 0xBE, 0x36, 0xF8, 0x63, 0x4D, 0xFE, 0xD1, 0xD4, 0xB4, 0x8D, 0x22, 0x4B,
+ 0x83, 0xE1, 0x2F, 0x88, 0x5A, 0x64, 0x62, 0x05, 0x6F, 0x13, 0xF8, 0x4A, 0x5B, 0x85, 0x59, 0xAE,
+ 0x34, 0xE1, 0x25, 0xED, 0xAC, 0x37, 0x10, 0xB6, 0xE9, 0x74, 0xFB, 0x99, 0x16, 0xDA, 0x66, 0x91,
+ 0x24, 0xB4, 0xBA, 0xBE, 0x00, 0xF7, 0x4A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xB1, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x7F, 0x9F, 0x9F, 0xFC, 0x1C, 0xFB, 0xFF, 0x00, 0x29, 0xCF,
+ 0xFF, 0x00, 0x82, 0x43, 0xFF, 0x00, 0xD8, 0x2B, 0xE1, 0xEF, 0xFE, 0xAD, 0xEB, 0x9A, 0xEC, 0xCB,
+ 0x3F, 0xE4, 0x61, 0x87, 0xFF, 0x00, 0x1C, 0x3F, 0xF4, 0xA4, 0x73, 0xE2, 0x7F, 0xDD, 0x6A, 0x7F,
+ 0x85, 0xFE, 0x47, 0xDA, 0x95, 0xFA, 0x99, 0xF1, 0xC1, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFB, 0x05,
+ 0xFF, 0x00, 0x04, 0x42, 0xFF, 0x00, 0x91, 0x13, 0xF6, 0xEB, 0xFF, 0x00, 0xB3, 0xE7, 0x83, 0xFF,
+ 0x00, 0x54, 0x37, 0xC3, 0x2A, 0xFC, 0xEB, 0x88, 0x3F, 0xE4, 0x69, 0x3F, 0x48, 0xFF, 0x00, 0xE9,
+ 0x28, 0xFA, 0x8C, 0xAF, 0xFD, 0xCA, 0x3F, 0x3F, 0xCC, 0xFD, 0xB6, 0xAF, 0x14, 0xF4, 0x42, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x04, 0x3F, 0x74, 0xFF,
+ 0x00, 0xBB, 0xFD, 0x28, 0x02, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x30, 0x3C, 0x55, 0xE2, 0xAF, 0x0C, 0xF8, 0x17, 0xC3, 0x1A, 0xF7, 0x8C, 0xFC, 0x65, 0xAF,
+ 0x69, 0x3E, 0x16, 0xF0, 0x8F, 0x85, 0x74, 0x89, 0xF5, 0xEF, 0x12, 0x78, 0x8F, 0x5D, 0xBD, 0x8F,
+ 0x4C, 0xD1, 0x74, 0x2B, 0x1B, 0x48, 0x8C, 0x97, 0x37, 0x57, 0x57, 0x0E, 0x42, 0x47, 0x14, 0x68,
+ 0x8C, 0xCC, 0xCC, 0x40, 0x00, 0x50, 0x07, 0x3B, 0xF0, 0xD3, 0xC5, 0xFA, 0xFF, 0x00, 0x8F, 0x3C,
+ 0x36, 0xDE, 0x28, 0xD6, 0xFC, 0x05, 0xAD, 0x7C, 0x3A, 0xB3, 0xD4, 0xB5, 0x09, 0x1F, 0xC2, 0xBA,
+ 0x17, 0x8A, 0xA7, 0x58, 0xBC, 0x69, 0x75, 0xA5, 0x2A, 0x20, 0xB6, 0xD4, 0x35, 0x7D, 0x35, 0x53,
+ 0x1A, 0x64, 0xF3, 0xB8, 0x9E, 0x44, 0xB2, 0x69, 0x65, 0x9A, 0x28, 0x0D, 0xA9, 0xB9, 0x16, 0xD7,
+ 0x4F, 0x3D, 0x95, 0x90, 0x07, 0xCC, 0xDE, 0x31, 0xFD, 0x92, 0xB5, 0xFD, 0x23, 0x48, 0xD1, 0x74,
+ 0xBF, 0x80, 0x7F, 0xB5, 0xBF, 0xED, 0x2B, 0xFB, 0x26, 0x7C, 0x31, 0xF0, 0x27, 0x84, 0x64, 0xD1,
+ 0xF4, 0x0F, 0x83, 0x1F, 0x02, 0xB4, 0x0F, 0x84, 0x1E, 0x20, 0xF8, 0x77, 0xA6, 0xA4, 0x77, 0xB7,
+ 0x77, 0x6A, 0x6C, 0x7F, 0xE1, 0x32, 0xF0, 0x2F, 0x88, 0xB5, 0x0B, 0x08, 0x23, 0x8E, 0xF2, 0x1B,
+ 0x3B, 0x7D, 0x3E, 0xCE, 0xEE, 0xDF, 0x4D, 0xB2, 0xB3, 0xB1, 0xB0, 0xB6, 0xB4, 0xB2, 0xB7, 0x8E,
+ 0x12, 0x1C, 0x03, 0xC9, 0x7E, 0x07, 0xFE, 0xCD, 0xDE, 0x36, 0xF8, 0xE3, 0xF0, 0xA7, 0xE1, 0x2F,
+ 0xC4, 0x4F, 0x8C, 0x5F, 0xB6, 0xCF, 0xED, 0x85, 0xF1, 0x9F, 0xE1, 0x77, 0xC5, 0x9F, 0x86, 0xBA,
+ 0x27, 0x8F, 0x3C, 0x5D, 0xFB, 0x3B, 0x7C, 0x4B, 0xB0, 0xF8, 0x23, 0xA2, 0x7C, 0x3D, 0xF1, 0x65,
+ 0xAE, 0xB9, 0xA3, 0xC5, 0x78, 0x9A, 0x1E, 0xBB, 0xA9, 0xF8, 0x4B, 0xE1, 0xBF, 0x87, 0xF5, 0xCB,
+ 0xAB, 0x18, 0xE4, 0xB9, 0x87, 0xCE, 0xB7, 0x86, 0xFE, 0xD6, 0xDE, 0xF9, 0x21, 0x6B, 0x5B, 0xC8,
+ 0x2E, 0x6C, 0xAE, 0xAE, 0xAC, 0xAE, 0x00, 0x3F, 0x40, 0x3C, 0x7F, 0xE2, 0x0F, 0x11, 0xF8, 0x53,
+ 0xC2, 0xB7, 0xDA, 0xFF, 0x00, 0x85, 0x3C, 0x13, 0x77, 0xF1, 0x07, 0x53, 0xD3, 0x6E, 0x6D, 0x26,
+ 0x9F, 0xC2, 0x7A, 0x5E, 0xAD, 0x6F, 0xA2, 0xEB, 0x17, 0xF6, 0x2D, 0x79, 0x12, 0xEA, 0x52, 0xD8,
+ 0x3C, 0xE0, 0x41, 0x2D, 0xD4, 0x36, 0xAF, 0x73, 0x34, 0x56, 0xF2, 0x3C, 0x2B, 0x3B, 0xC4, 0x90,
+ 0xF9, 0xD1, 0x79, 0x9E, 0x62, 0x80, 0x5A, 0xF0, 0x47, 0x8D, 0x7C, 0x2F, 0xF1, 0x1B, 0xC2, 0x7A,
+ 0x17, 0x8D, 0xFC, 0x17, 0xAA, 0xC7, 0xAD, 0x78, 0x63, 0xC4, 0x76, 0x0B, 0x7F, 0xA5, 0x5F, 0xA5,
+ 0xB4, 0xD6, 0x12, 0x95, 0xDC, 0x56, 0x48, 0x6E, 0x2D, 0x66, 0x44, 0x9E, 0xDA, 0xE2, 0x29, 0x23,
+ 0x92, 0x29, 0x6D, 0xE7, 0x8E, 0x39, 0xA1, 0x96, 0x39, 0x62, 0x91, 0x12, 0x48, 0xD9, 0x14, 0x03,
+ 0xAA, 0xA0, 0x02, 0x80, 0x3C, 0xE3, 0xE2, 0x3F, 0xC2, 0xEF, 0x0E, 0x7C, 0x4B, 0xB1, 0xD2, 0x57,
+ 0x54, 0x9F, 0x59, 0xD0, 0x7C, 0x43, 0xE1, 0x7D, 0x40, 0xEB, 0x9E, 0x07, 0xF1, 0xD7, 0x84, 0xF5,
+ 0x01, 0xA3, 0x78, 0xCB, 0xC0, 0xDA, 0x88, 0x89, 0xA3, 0x4B, 0xDD, 0x3E, 0xE4, 0xAB, 0xC4, 0xE3,
+ 0x6B, 0x95, 0x96, 0xD6, 0xE6, 0x2B, 0x8B, 0x3B, 0xA8, 0xCB, 0x5B, 0xDD, 0x5B, 0x5C, 0xC1, 0x24,
+ 0x90, 0xB8, 0x07, 0xCA, 0x3F, 0xF0, 0xC7, 0xDF, 0xB4, 0x27, 0xFD, 0x25, 0x57, 0xF6, 0xF6, 0xFF,
+ 0x00, 0xC3, 0x75, 0xFB, 0x2E, 0x7F, 0xF3, 0x9D, 0xA0, 0x03, 0xFE, 0x18, 0xFB, 0xF6, 0x84, 0xFF,
+ 0x00, 0xA4, 0xAA, 0xFE, 0xDE, 0xDF, 0xF8, 0x6E, 0xBF, 0x65, 0xCF, 0xFE, 0x73, 0xB4, 0x00, 0x7F,
+ 0xC3, 0x1F, 0x7E, 0xD0, 0x9F, 0xF4, 0x95, 0x5F, 0xDB, 0xDB, 0xFF, 0x00, 0x0D, 0xD7, 0xEC, 0xB9,
+ 0xFF, 0x00, 0xCE, 0x76, 0x80, 0x0F, 0xF8, 0x63, 0xEF, 0xDA, 0x13, 0xFE, 0x92, 0xAB, 0xFB, 0x7B,
+ 0x7F, 0xE1, 0xBA, 0xFD, 0x97, 0x3F, 0xF9, 0xCE, 0xD0, 0x01, 0xFF, 0x00, 0x0C, 0x7D, 0xFB, 0x42,
+ 0x7F, 0xD2, 0x55, 0x7F, 0x6F, 0x6F, 0xFC, 0x37, 0x5F, 0xB2, 0xE7, 0xFF, 0x00, 0x39, 0xDA, 0x00,
+ 0x3F, 0xE1, 0x8F, 0xBF, 0x68, 0x4F, 0xFA, 0x4A, 0xAF, 0xED, 0xED, 0xFF, 0x00, 0x86, 0xEB, 0xF6,
+ 0x5C, 0xFF, 0x00, 0xE7, 0x3B, 0x40, 0x07, 0xFC, 0x31, 0xF7, 0xED, 0x09, 0xFF, 0x00, 0x49, 0x55,
+ 0xFD, 0xBD, 0xBF, 0xF0, 0xDD, 0x7E, 0xCB, 0x9F, 0xFC, 0xE7, 0x68, 0x00, 0xFF, 0x00, 0x86, 0x3E,
+ 0xFD, 0xA1, 0x3F, 0xE9, 0x2A, 0xBF, 0xB7, 0xB7, 0xFE, 0x1B, 0xAF, 0xD9, 0x73, 0xFF, 0x00, 0x9C,
+ 0xED, 0x00, 0x1F, 0xF0, 0xC7, 0xDF, 0xB4, 0x27, 0xFD, 0x25, 0x57, 0xF6, 0xF6, 0xFF, 0x00, 0xC3,
+ 0x75, 0xFB, 0x2E, 0x7F, 0xF3, 0x9D, 0xA0, 0x03, 0xFE, 0x18, 0xFB, 0xF6, 0x84, 0xFF, 0x00, 0xA4,
+ 0xAA, 0xFE, 0xDE, 0xDF, 0xF8, 0x6E, 0xBF, 0x65, 0xCF, 0xFE, 0x73, 0xB4, 0x00, 0x7F, 0xC3, 0x1F,
+ 0x7E, 0xD0, 0x9F, 0xF4, 0x95, 0x5F, 0xDB, 0xDB, 0xFF, 0x00, 0x0D, 0xD7, 0xEC, 0xB9, 0xFF, 0x00,
+ 0xCE, 0x76, 0x80, 0x0F, 0xF8, 0x63, 0xEF, 0xDA, 0x13, 0xFE, 0x92, 0xAB, 0xFB, 0x7B, 0x7F, 0xE1,
+ 0xBA, 0xFD, 0x97, 0x3F, 0xF9, 0xCE, 0xD0, 0x07, 0xBA, 0x7C, 0x11, 0xF8, 0x33, 0xF1, 0x17, 0xE1,
+ 0x44, 0xFE, 0x23, 0x9B, 0xC7, 0x7F, 0xB5, 0x9F, 0xED, 0x03, 0xFB, 0x4C, 0x45, 0xAD, 0xC1, 0x69,
+ 0x16, 0x97, 0x67, 0xF1, 0xBB, 0xC3, 0x7F, 0x0A, 0x74, 0x0B, 0x6F, 0x06, 0xB5, 0xB3, 0x4A, 0x66,
+ 0x93, 0x4D, 0x3E, 0x0E, 0xF0, 0x67, 0x87, 0xA4, 0x76, 0x9C, 0x4D, 0x10, 0x90, 0x5E, 0x3D, 0xDA,
+ 0x81, 0x6F, 0x17, 0x94, 0xB1, 0x13, 0x21, 0x94, 0x03, 0xE8, 0x1A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x2C, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x1F, 0xE7, 0xE7, 0xFF, 0x00, 0x07, 0x3E, 0xFF, 0x00, 0xCA, 0x73, 0xFF, 0x00,
+ 0xE0, 0x90, 0xFF, 0x00, 0xF6, 0x0A, 0xF8, 0x7B, 0xFF, 0x00, 0xAB, 0x7A, 0xE6, 0xBB, 0x32, 0xCF,
+ 0xF9, 0x18, 0x61, 0xFF, 0x00, 0xC7, 0x0F, 0xFD, 0x29, 0x1C, 0xF8, 0x9F, 0xF7, 0x5A, 0x9F, 0xE1,
+ 0x7F, 0x91, 0xF6, 0xA5, 0x7E, 0xA6, 0x7C, 0x70, 0x50, 0x01, 0x40, 0x05, 0x00, 0x7E, 0xC1, 0x7F,
+ 0xC1, 0x10, 0xBF, 0xE4, 0x44, 0xFD, 0xBA, 0xFF, 0x00, 0xEC, 0xF9, 0xE0, 0xFF, 0x00, 0xD5, 0x0D,
+ 0xF0, 0xCA, 0xBF, 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2, 0x3F, 0xFA, 0x4A, 0x3E, 0xA3, 0x2B,
+ 0xFF, 0x00, 0x72, 0x8F, 0xCF, 0xF3, 0x3F, 0x6D, 0xAB, 0xC5, 0x3D, 0x10, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x01, 0x0F, 0xDD, 0x3F, 0xEE, 0xFF, 0x00,
+ 0x4A, 0x00, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xE0, 0x0E, 0x9C,
+ 0x01, 0xD3, 0x81, 0xC0, 0x1D, 0x3D, 0x3B, 0x0A, 0x00, 0xF9, 0x57, 0xC2, 0x5E, 0x1A, 0xF1, 0x17,
+ 0xC7, 0xAF, 0x10, 0x78, 0x77, 0xE2, 0xCF, 0xC5, 0x0D, 0x13, 0x55, 0xF0, 0xC7, 0xC3, 0x7F, 0x0D,
+ 0xEA, 0x36, 0xBE, 0x28, 0xF8, 0x21, 0xF0, 0x5F, 0xC4, 0x16, 0x32, 0x69, 0x9A, 0xC4, 0xB7, 0x90,
+ 0x2C, 0x86, 0xC7, 0xC6, 0xDE, 0x34, 0xD3, 0xE7, 0xB7, 0x86, 0xE6, 0xDB, 0x53, 0x09, 0x72, 0x0D,
+ 0x96, 0x89, 0x3E, 0xE5, 0xD3, 0x4C, 0x71, 0x5E, 0x5C, 0xAF, 0xF6, 0x9F, 0x93, 0x0E, 0x82, 0x01,
+ 0xF5, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x07, 0xE0, 0x28,
+ 0x03, 0x2F, 0x5C, 0x46, 0x7D, 0x13, 0x57, 0x8E, 0x34, 0x2C, 0xCD, 0xA5, 0x5C, 0x22, 0x22, 0x29,
+ 0x66, 0x62, 0x61, 0x60, 0x15, 0x40, 0xFC, 0x06, 0x05, 0x00, 0x78, 0x67, 0xEC, 0x87, 0xA7, 0xDF,
+ 0x69, 0x3F, 0xB2, 0x6F, 0xEC, 0xBD, 0xA5, 0x6A, 0x96, 0x37, 0x9A, 0x5E, 0xA7, 0xA6, 0x7E, 0xCE,
+ 0xDE, 0x08, 0xD3, 0xF5, 0x1D, 0x33, 0x51, 0xB5, 0x92, 0xC7, 0x50, 0xD3, 0xAE, 0x20, 0xF0, 0xCD,
+ 0x92, 0x4D, 0x6F, 0x3C, 0x0E, 0x15, 0xE3, 0x91, 0x1D, 0x19, 0x59, 0x18, 0x02, 0xA4, 0x10, 0x40,
+ 0x23, 0x00, 0x03, 0xE8, 0x7A, 0x00, 0xF9, 0x87, 0xC6, 0xDE, 0x09, 0xF1, 0x2F, 0xC2, 0x6F, 0x12,
+ 0xEB, 0x9F, 0x1A, 0x3E, 0x0B, 0xE8, 0x57, 0x1A, 0xED, 0xBE, 0xB9, 0x39, 0xD5, 0xFE, 0x35, 0x7C,
+ 0x14, 0xD1, 0xD6, 0xD6, 0xD0, 0x7C, 0x4B, 0x10, 0xDA, 0xB2, 0xB7, 0x88, 0x3C, 0x3C, 0x8C, 0xA8,
+ 0x89, 0xE2, 0xA5, 0x48, 0x6C, 0x61, 0x06, 0x59, 0xA2, 0xB7, 0xBF, 0xB7, 0x85, 0x2D, 0xA7, 0x64,
+ 0x92, 0x3B, 0x5B, 0xAB, 0x40, 0x0F, 0xA5, 0xED, 0x6E, 0x23, 0xBB, 0xB5, 0xB6, 0xBA, 0x85, 0x27,
+ 0x48, 0xAE, 0x6D, 0xD2, 0xE2, 0x24, 0xB9, 0xB4, 0x96, 0xC6, 0xE5, 0x15, 0xD4, 0x15, 0x59, 0x20,
+ 0x91, 0x56, 0x48, 0xD8, 0x02, 0x01, 0x47, 0x55, 0x65, 0x3C, 0x10, 0x08, 0xC0, 0x00, 0x9E, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x02, 0xC5, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x01, 0xFE, 0x7E, 0x7F, 0xF0, 0x73, 0xEF, 0xFC, 0xA7, 0x3F, 0xFE, 0x09, 0x0F, 0xFF, 0x00,
+ 0x60, 0xAF, 0x87, 0xBF, 0xFA, 0xB7, 0xAE, 0x6B, 0xB3, 0x2C, 0xFF, 0x00, 0x91, 0x86, 0x1F, 0xFC,
+ 0x70, 0xFF, 0x00, 0xD2, 0x91, 0xCF, 0x89, 0xFF, 0x00, 0x75, 0xA9, 0xFE, 0x17, 0xF9, 0x1F, 0x6A,
+ 0x57, 0xEA, 0x67, 0xC7, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xEC, 0x17, 0xFC, 0x11, 0x0B, 0xFE,
+ 0x44, 0x4F, 0xDB, 0xAF, 0xFE, 0xCF, 0x9E, 0x0F, 0xFD, 0x50, 0xDF, 0x0C, 0xAB, 0xF3, 0xAE, 0x20,
+ 0xFF, 0x00, 0x91, 0xA4, 0xFD, 0x23, 0xFF, 0x00, 0xA4, 0xA3, 0xEA, 0x32, 0xBF, 0xF7, 0x28, 0xFC,
+ 0xFF, 0x00, 0x33, 0xF6, 0xDA, 0xBC, 0x53, 0xD1, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x10, 0xFD, 0xD3, 0xFE, 0xEF, 0xF4, 0xA0, 0x08, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3E,
+ 0x5C, 0xFD, 0xA2, 0xFC, 0x4D, 0xF1, 0x38, 0xEB, 0x9F, 0x06, 0x3E, 0x0F, 0xFC, 0x2A, 0xF1, 0xB5,
+ 0x8F, 0xC2, 0xED, 0x5B, 0xE3, 0x57, 0x89, 0xF5, 0xAD, 0x03, 0xC4, 0x5F, 0x13, 0x7F, 0xE1, 0x12,
+ 0xB6, 0xF1, 0xA7, 0x8A, 0xBC, 0x15, 0xA3, 0x69, 0xBE, 0x18, 0xBE, 0xBB, 0xB9, 0xB8, 0xF0, 0xBD,
+ 0x9D, 0xDB, 0x9D, 0x32, 0x2D, 0x6F, 0xCF, 0x8E, 0xC0, 0xDA, 0xDC, 0xEA, 0x56, 0x9A, 0xA5, 0x8C,
+ 0x26, 0x37, 0x33, 0xE9, 0xB7, 0xA8, 0xDE, 0x49, 0x00, 0xA1, 0xFB, 0x29, 0xFC, 0x40, 0xF1, 0xF7,
+ 0x88, 0x1B, 0xF6, 0x82, 0xF8, 0x49, 0xF1, 0x2F, 0xC5, 0x29, 0xF1, 0x13, 0xC5, 0x7F, 0xB2, 0xDF,
+ 0xC7, 0x38, 0x7E, 0x06, 0x49, 0xF1, 0x52, 0x4F, 0x0E, 0xDA, 0x78, 0x47, 0x59, 0xF8, 0xA5, 0x63,
+ 0x75, 0xE0, 0x0F, 0x0B, 0xF8, 0xAF, 0x49, 0xD6, 0x35, 0x9D, 0x32, 0xCF, 0x16, 0x11, 0x6A, 0xCB,
+ 0x63, 0xE3, 0xBB, 0x2B, 0x4B, 0xE9, 0x2C, 0x61, 0xB2, 0xB3, 0xB9, 0xBB, 0xB2, 0xBA, 0xBB, 0xB5,
+ 0xB0, 0xD3, 0x6D, 0xEE, 0xA2, 0xD3, 0xAC, 0x80, 0x39, 0x1F, 0xDB, 0x2F, 0xC6, 0xDF, 0x15, 0xB1,
+ 0xF0, 0xD7, 0xE0, 0xAF, 0xEC, 0xF5, 0xE2, 0x38, 0xF4, 0x2F, 0x8E, 0x3E, 0x37, 0x5D, 0x7F, 0xE3,
+ 0x16, 0x91, 0x1C, 0x76, 0x66, 0xF2, 0xE6, 0x6D, 0x13, 0xE1, 0x9D, 0x8C, 0x3A, 0x97, 0x97, 0x71,
+ 0x1B, 0x4D, 0x04, 0x72, 0xE9, 0x37, 0xBE, 0x2A, 0xBF, 0xF8, 0x6D, 0xA0, 0xEA, 0x90, 0x2C, 0xD1,
+ 0x5C, 0x4F, 0xA6, 0x78, 0x93, 0x51, 0x86, 0xDA, 0x5B, 0x49, 0x64, 0x5D, 0x47, 0x4E, 0x00, 0xFA,
+ 0x97, 0xE1, 0x67, 0xC4, 0x3F, 0x0F, 0x7C, 0x5D, 0xF8, 0x61, 0xF0, 0xE3, 0xE2, 0xC7, 0x84, 0x6E,
+ 0x63, 0xBC, 0xF0, 0x9F, 0xC4, 0xFF, 0x00, 0x01, 0x68, 0xFF, 0x00, 0x11, 0x3C, 0x2F, 0x79, 0x16,
+ 0xF3, 0x15, 0xDE, 0x9D, 0xAD, 0xE9, 0xD0, 0xDE, 0x58, 0xCA, 0x85, 0xD1, 0x1F, 0x0D, 0x0D, 0xCC,
+ 0x44, 0x6E, 0x44, 0x3C, 0xF2, 0xAA, 0x78, 0x00, 0x0B, 0xF1, 0x43, 0xE2, 0x17, 0x86, 0xFE, 0x11,
+ 0x7C, 0x32, 0xF8, 0x89, 0xF1, 0x63, 0xC6, 0x17, 0x71, 0x69, 0xDE, 0x10, 0xF8, 0x5F, 0xE0, 0x4D,
+ 0x5F, 0xE2, 0x1F, 0x8A, 0xB5, 0x09, 0x7C, 0xC1, 0x0D, 0x86, 0x99, 0xA2, 0x69, 0xF2, 0xDE, 0x5F,
+ 0x4C, 0xFE, 0x5A, 0x3B, 0xED, 0x48, 0x2D, 0x65, 0x63, 0xB5, 0x1C, 0xE0, 0x70, 0xA4, 0xE0, 0x10,
+ 0x0F, 0x95, 0xFF, 0x00, 0x63, 0x1F, 0x1B, 0x7C, 0x59, 0xC7, 0xC4, 0x8F, 0x83, 0x1F, 0xB4, 0x27,
+ 0x88, 0x13, 0x59, 0xF8, 0xDD, 0xE0, 0xB8, 0xBC, 0x3F, 0xF1, 0x9F, 0x55, 0x82, 0x5B, 0x53, 0x6B,
+ 0x79, 0x65, 0xA2, 0xFC, 0x4D, 0xB2, 0x9F, 0x51, 0x36, 0xF0, 0xA2, 0xCD, 0x3C, 0x49, 0xA5, 0x58,
+ 0x78, 0xAB, 0x4E, 0xF8, 0x8F, 0xA1, 0x69, 0x70, 0x99, 0xA4, 0x9E, 0x0D, 0x33, 0xC3, 0xBA, 0x6C,
+ 0x17, 0x12, 0x5D, 0xCB, 0x13, 0x6A, 0x3A, 0x88, 0x07, 0xDC, 0x54, 0x00, 0x50, 0x07, 0xCB, 0xDF,
+ 0x11, 0x7E, 0x22, 0xF8, 0xBB, 0xC7, 0xFE, 0x2F, 0xD6, 0x3E, 0x00, 0xFC, 0x05, 0xD6, 0x1F, 0x45,
+ 0xF1, 0x36, 0x92, 0xB1, 0x5A, 0x7C, 0x6D, 0xF8, 0xDB, 0x65, 0x69, 0x6B, 0xA9, 0xD9, 0x7E, 0xCE,
+ 0x96, 0xB7, 0xB6, 0x31, 0x5C, 0xDB, 0x58, 0xE9, 0x50, 0xDD, 0x5A, 0xDC, 0xE9, 0xDA, 0x87, 0x8D,
+ 0x6E, 0x6D, 0x6F, 0xB4, 0xFB, 0x9B, 0x3D, 0x36, 0xEE, 0x29, 0x6D, 0xAC, 0x2D, 0x2E, 0x6D, 0xF5,
+ 0x7D, 0x4A, 0x29, 0x60, 0x97, 0x4B, 0xD2, 0xFC, 0x4C, 0x01, 0x36, 0xA1, 0xFB, 0x22, 0xFC, 0x1E,
+ 0xD5, 0x27, 0x86, 0xE6, 0xF7, 0x53, 0xF8, 0xF6, 0xD3, 0xC3, 0xA6, 0x58, 0xE9, 0x21, 0xAD, 0xBF,
+ 0x6B, 0x5F, 0x8B, 0x16, 0x09, 0x24, 0x5A, 0x75, 0x8C, 0x36, 0x96, 0xEF, 0x22, 0x45, 0xE2, 0x45,
+ 0x57, 0x98, 0xC5, 0x69, 0x11, 0x96, 0x66, 0x0D, 0x2C, 0xF2, 0x99, 0x67, 0x99, 0xE4, 0x96, 0x59,
+ 0x24, 0x70, 0x0A, 0x3F, 0xF0, 0xC6, 0x9F, 0x05, 0x3F, 0xE8, 0x23, 0xFB, 0x41, 0x7F, 0xE2, 0x61,
+ 0x7C, 0x5E, 0xFF, 0x00, 0xE6, 0x9A, 0x80, 0x0F, 0xF8, 0x63, 0x4F, 0x82, 0x9F, 0xF4, 0x11, 0xFD,
+ 0xA0, 0xBF, 0xF1, 0x30, 0xBE, 0x2F, 0x7F, 0xF3, 0x4D, 0x40, 0x07, 0xFC, 0x31, 0xA7, 0xC1, 0x4F,
+ 0xFA, 0x08, 0xFE, 0xD0, 0x5F, 0xF8, 0x98, 0x5F, 0x17, 0xBF, 0xF9, 0xA6, 0xA0, 0x03, 0xFE, 0x18,
+ 0xD3, 0xE0, 0xA7, 0xFD, 0x04, 0x7F, 0x68, 0x2F, 0xFC, 0x4C, 0x2F, 0x8B, 0xDF, 0xFC, 0xD3, 0x50,
+ 0x01, 0xFF, 0x00, 0x0C, 0x69, 0xF0, 0x53, 0xFE, 0x82, 0x3F, 0xB4, 0x17, 0xFE, 0x26, 0x17, 0xC5,
+ 0xEF, 0xFE, 0x69, 0xA8, 0x00, 0xFF, 0x00, 0x86, 0x34, 0xF8, 0x29, 0xFF, 0x00, 0x41, 0x1F, 0xDA,
+ 0x0B, 0xFF, 0x00, 0x13, 0x0B, 0xE2, 0xF7, 0xFF, 0x00, 0x34, 0xD4, 0x00, 0x7F, 0xC3, 0x1A, 0x7C,
+ 0x14, 0xFF, 0x00, 0xA0, 0x8F, 0xED, 0x05, 0xFF, 0x00, 0x89, 0x85, 0xF1, 0x7B, 0xFF, 0x00, 0x9A,
+ 0x6A, 0x00, 0x3F, 0xE1, 0x8D, 0x3E, 0x0A, 0x7F, 0xD0, 0x47, 0xF6, 0x82, 0xFF, 0x00, 0xC4, 0xC2,
+ 0xF8, 0xBD, 0xFF, 0x00, 0xCD, 0x35, 0x00, 0x1F, 0xF0, 0xC6, 0x9F, 0x05, 0x3F, 0xE8, 0x23, 0xFB,
+ 0x41, 0x7F, 0xE2, 0x61, 0x7C, 0x5E, 0xFF, 0x00, 0xE6, 0x9A, 0x80, 0x0F, 0xF8, 0x63, 0x4F, 0x82,
+ 0x9F, 0xF4, 0x11, 0xFD, 0xA0, 0xBF, 0xF1, 0x30, 0xBE, 0x2F, 0x7F, 0xF3, 0x4D, 0x40, 0x07, 0xFC,
+ 0x31, 0xA7, 0xC1, 0x4F, 0xFA, 0x08, 0xFE, 0xD0, 0x5F, 0xF8, 0x98, 0x5F, 0x17, 0xBF, 0xF9, 0xA6,
+ 0xA0, 0x03, 0xFE, 0x18, 0xD3, 0xE0, 0xA7, 0xFD, 0x04, 0x7F, 0x68, 0x2F, 0xFC, 0x4C, 0x2F, 0x8B,
+ 0xDF, 0xFC, 0xD3, 0x50, 0x01, 0xFF, 0x00, 0x0C, 0x69, 0xF0, 0x53, 0xFE, 0x82, 0x3F, 0xB4, 0x17,
+ 0xFE, 0x26, 0x17, 0xC5, 0xEF, 0xFE, 0x69, 0xA8, 0x03, 0xDF, 0x7C, 0x0D, 0xE0, 0x9D, 0x0B, 0xE1,
+ 0xD7, 0x85, 0xB4, 0xCF, 0x07, 0x78, 0x6E, 0x4F, 0x11, 0x4D, 0xA2, 0xE9, 0x0D, 0x70, 0xD6, 0x72,
+ 0x78, 0xB3, 0xC6, 0x7A, 0xCF, 0xC4, 0x1D, 0x7C, 0x9B, 0xAB, 0xA9, 0x2E, 0x25, 0x13, 0xEA, 0xFA,
+ 0xAD, 0xD5, 0xD5, 0xFC, 0xE0, 0x49, 0x71, 0x20, 0x41, 0x2C, 0xEE, 0x23, 0x40, 0x91, 0x26, 0xD8,
+ 0xE3, 0x44, 0x50, 0x0E, 0xB2, 0x80, 0x0A, 0x00, 0x28, 0x02, 0xC5, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x01, 0xFE, 0x7E, 0x7F, 0xF0, 0x73, 0xEF, 0xFC, 0xA7, 0x3F, 0xFE, 0x09,
+ 0x0F, 0xFF, 0x00, 0x60, 0xAF, 0x87, 0xBF, 0xFA, 0xB7, 0xAE, 0x6B, 0xB3, 0x2C, 0xFF, 0x00, 0x91,
+ 0x86, 0x1F, 0xFC, 0x70, 0xFF, 0x00, 0xD2, 0x91, 0xCF, 0x89, 0xFF, 0x00, 0x75, 0xA9, 0xFE, 0x17,
+ 0xF9, 0x1F, 0x6A, 0x57, 0xEA, 0x67, 0xC7, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xEC, 0x17, 0xFC,
+ 0x11, 0x0B, 0xFE, 0x44, 0x4F, 0xDB, 0xAF, 0xFE, 0xCF, 0x9E, 0x0F, 0xFD, 0x50, 0xDF, 0x0C, 0xAB,
+ 0xF3, 0xAE, 0x20, 0xFF, 0x00, 0x91, 0xA4, 0xFD, 0x23, 0xFF, 0x00, 0xA4, 0xA3, 0xEA, 0x32, 0xBF,
+ 0xF7, 0x28, 0xFC, 0xFF, 0x00, 0x33, 0xF6, 0xDA, 0xBC, 0x53, 0xD1, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x10, 0xFD, 0xD3, 0xFE, 0xEF, 0xF4, 0xA0,
+ 0x0F, 0x2B, 0xF8, 0xA3, 0xE3, 0xCF, 0x14, 0xFC, 0x3F, 0xD1, 0xF4, 0xDD, 0x4B, 0xC2, 0x7F, 0x04,
+ 0xFE, 0x26, 0xFC, 0x71, 0xBC, 0xBD, 0xD5, 0x06, 0x9D, 0x73, 0xE1, 0xDF, 0x85, 0x9A, 0xAF, 0x82,
+ 0xF4, 0x8D, 0x5F, 0x46, 0x84, 0xC1, 0x23, 0x9B, 0xEB, 0x97, 0xF1, 0x26, 0xBF, 0xA3, 0x5A, 0x18,
+ 0x03, 0x45, 0x1C, 0x5B, 0x61, 0x9E, 0x59, 0x77, 0x4B, 0x19, 0x11, 0x6C, 0x0E, 0xE8, 0x01, 0xE2,
+ 0x1F, 0xF0, 0xD2, 0x7F, 0x19, 0x7F, 0xE9, 0x1F, 0x1F, 0xB5, 0xEF, 0xFE, 0x16, 0x9F, 0x00, 0x7F,
+ 0xF9, 0xE5, 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0x27, 0xF1, 0x97, 0xFE, 0x91, 0xF1, 0xFB, 0x5E, 0xFF,
+ 0x00, 0xE1, 0x69, 0xF0, 0x07, 0xFF, 0x00, 0x9E, 0x5D, 0x00, 0x1F, 0xF0, 0xD2, 0x7F, 0x19, 0x7F,
+ 0xE9, 0x1F, 0x1F, 0xB5, 0xEF, 0xFE, 0x16, 0x9F, 0x00, 0x7F, 0xF9, 0xE5, 0xD0, 0x01, 0xFF, 0x00,
+ 0x0D, 0x27, 0xF1, 0x97, 0xFE, 0x91, 0xF1, 0xFB, 0x5E, 0xFF, 0x00, 0xE1, 0x69, 0xF0, 0x07, 0xFF,
+ 0x00, 0x9E, 0x5D, 0x00, 0x1F, 0xF0, 0xD2, 0x7F, 0x19, 0x7F, 0xE9, 0x1F, 0x1F, 0xB5, 0xEF, 0xFE,
+ 0x16, 0x9F, 0x00, 0x7F, 0xF9, 0xE5, 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0x27, 0xF1, 0x97, 0xFE, 0x91,
+ 0xF1, 0xFB, 0x5E, 0xFF, 0x00, 0xE1, 0x69, 0xF0, 0x07, 0xFF, 0x00, 0x9E, 0x5D, 0x00, 0x1F, 0xF0,
+ 0xD2, 0x7F, 0x19, 0x7F, 0xE9, 0x1F, 0x1F, 0xB5, 0xEF, 0xFE, 0x16, 0x9F, 0x00, 0x7F, 0xF9, 0xE5,
+ 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0x27, 0xF1, 0x97, 0xFE, 0x91, 0xF1, 0xFB, 0x5E, 0xFF, 0x00, 0xE1,
+ 0x69, 0xF0, 0x07, 0xFF, 0x00, 0x9E, 0x5D, 0x00, 0x1F, 0xF0, 0xD2, 0x7F, 0x19, 0x7F, 0xE9, 0x1F,
+ 0x1F, 0xB5, 0xEF, 0xFE, 0x16, 0x9F, 0x00, 0x7F, 0xF9, 0xE5, 0xD0, 0x01, 0xFF, 0x00, 0x0D, 0x27,
+ 0xF1, 0x97, 0xFE, 0x91, 0xF1, 0xFB, 0x5E, 0xFF, 0x00, 0xE1, 0x69, 0xF0, 0x07, 0xFF, 0x00, 0x9E,
+ 0x5D, 0x00, 0x55, 0xBC, 0xFD, 0xA9, 0xFE, 0x25, 0x68, 0x96, 0x93, 0x6A, 0xFE, 0x26, 0xFD, 0x83,
+ 0x7F, 0x6C, 0x6D, 0x07, 0xC3, 0x5A, 0x62, 0x0B, 0xDF, 0x10, 0xEB, 0xB6, 0x72, 0xFC, 0x22, 0xF8,
+ 0x81, 0x73, 0xA0, 0xD8, 0x44, 0x41, 0xBC, 0xBE, 0x8F, 0x40, 0xD0, 0x3C, 0x77, 0xA8, 0xEB, 0xDA,
+ 0x99, 0x86, 0x11, 0x24, 0xBF, 0x62, 0xD2, 0xB4, 0xED, 0x42, 0xFE, 0xE3, 0x67, 0x93, 0x6B, 0x69,
+ 0x73, 0x3C, 0x91, 0x41, 0x20, 0x07, 0xD5, 0xDE, 0x1E, 0xF1, 0x06, 0x81, 0xE2, 0xDD, 0x03, 0x43,
+ 0xF1, 0x57, 0x85, 0x75, 0xBD, 0x1F, 0xC4, 0xBE, 0x17, 0xF1, 0x2E, 0x8F, 0x6B, 0xE2, 0x0F, 0x0E,
+ 0x78, 0x8B, 0xC3, 0xFA, 0x94, 0x1A, 0xCE, 0x83, 0xAF, 0xD8, 0x5E, 0xC0, 0x93, 0x59, 0x5E, 0xD8,
+ 0xDE, 0x42, 0xCD, 0x0C, 0xF6, 0xF2, 0xC3, 0x2C, 0x52, 0x47, 0x2C, 0x6C, 0xC8, 0xE8, 0xCA, 0xCA,
+ 0x48, 0x20, 0x90, 0x0E, 0x3F, 0xE2, 0x47, 0xC6, 0x2F, 0x84, 0x9F, 0x06, 0xF4, 0xFD, 0x3F, 0x55,
+ 0xF8, 0xB5, 0xF1, 0x3B, 0xC0, 0x1F, 0x0C, 0xB4, 0xDD, 0x56, 0xE5, 0xAC, 0xB4, 0x9B, 0xCF, 0x1E,
+ 0x78, 0xBB, 0x4F, 0xF0, 0x95, 0xBE, 0xA9, 0x34, 0x6A, 0x0C, 0x90, 0xDA, 0xB5, 0xCC, 0xB1, 0xF9,
+ 0xAE, 0xAA, 0xCA, 0x4A, 0xA6, 0xE2, 0xA0, 0x82, 0x40, 0x14, 0x01, 0xD9, 0xE8, 0x5A, 0xEE, 0x87,
+ 0xE2, 0x7D, 0x17, 0x4A, 0xF1, 0x1F, 0x86, 0x75, 0x8D, 0x27, 0xC4, 0x3E, 0x1D, 0xD7, 0x74, 0xF8,
+ 0x75, 0x5D, 0x0F, 0x5E, 0xD0, 0xB5, 0x08, 0x75, 0x6D, 0x17, 0x58, 0xB4, 0xB8, 0x8C, 0x3D, 0xBD,
+ 0xCD, 0xA5, 0xD4, 0x4C, 0xD1, 0x4B, 0x13, 0xA3, 0x2B, 0x2B, 0xA3, 0x15, 0x60, 0x41, 0x04, 0x83,
+ 0x40, 0x1C, 0x97, 0x8C, 0xFE, 0x2A, 0x78, 0x0B, 0xE1, 0xEE, 0xBF, 0xF0, 0xCB, 0xC2, 0xDE, 0x2E,
+ 0xD7, 0x57, 0x48, 0xD6, 0xFE, 0x30, 0x78, 0xC6, 0x5F, 0x00, 0xFC, 0x3D, 0xB3, 0xFE, 0xCE, 0xBB,
+ 0xBD, 0x4D, 0x63, 0x54, 0x87, 0x48, 0xBC, 0xD4, 0x9E, 0x19, 0xA6, 0x86, 0x27, 0x8A, 0xCE, 0x2F,
+ 0xB2, 0xE9, 0x37, 0x4A, 0xB7, 0x17, 0x4D, 0x04, 0x0D, 0x3B, 0xD9, 0xDA, 0x2C, 0x86, 0xE6, 0xF6,
+ 0xD6, 0x0B, 0x80, 0x0F, 0x42, 0xA0, 0x0A, 0x97, 0xD7, 0xD6, 0x3A, 0x55, 0x85, 0xE6, 0xA7, 0xA9,
+ 0x5D, 0xDA, 0xE9, 0xFA, 0x6E, 0x9B, 0x69, 0x25, 0xF5, 0xFD, 0xFD, 0xED, 0xC4, 0x76, 0x76, 0x56,
+ 0x30, 0x43, 0x19, 0x79, 0x66, 0x9A, 0x57, 0x21, 0x12, 0x34, 0x44, 0x66, 0x66, 0x62, 0x00, 0x00,
+ 0x92, 0x40, 0x14, 0x01, 0xC9, 0xFC, 0x33, 0xF8, 0x8D, 0xE0, 0xFF, 0x00, 0x8B, 0xFF, 0x00, 0x0F,
+ 0x3C, 0x11, 0xF1, 0x4F, 0xE1, 0xF6, 0xA5, 0x71, 0xAC, 0x78, 0x1F, 0xE2, 0x1F, 0x85, 0xAC, 0x7C,
+ 0x63, 0xE1, 0x4D, 0x4A, 0xF3, 0x45, 0xBE, 0xF0, 0xD6, 0xA1, 0x73, 0x61, 0xA8, 0x5B, 0xA4, 0xD6,
+ 0xC6, 0xEB, 0x4C, 0xBD, 0x86, 0x0B, 0xDB, 0x29, 0xC2, 0x48, 0xAB, 0x25, 0xAD, 0xD4, 0x10, 0xCF,
+ 0x03, 0x87, 0x8A, 0x58, 0xA3, 0x92, 0x36, 0x45, 0x00, 0xE6, 0x3E, 0x2D, 0xAF, 0x83, 0xBC, 0x33,
+ 0x63, 0xA3, 0x7C, 0x64, 0xF1, 0x37, 0x83, 0xFC, 0x49, 0xE2, 0xBB, 0xBF, 0x83, 0xB3, 0x5C, 0x6B,
+ 0x7A, 0x63, 0xF8, 0x45, 0x26, 0xBF, 0xD6, 0xFC, 0x37, 0x67, 0xA8, 0xC2, 0x2C, 0xB5, 0xDD, 0x52,
+ 0x3D, 0x31, 0x2E, 0x22, 0x17, 0xD1, 0xDB, 0x69, 0xD7, 0x17, 0x77, 0x12, 0xC0, 0x91, 0xDC, 0xDC,
+ 0xBC, 0x56, 0xF2, 0xAD, 0xA5, 0xB5, 0xC5, 0xD3, 0x41, 0x04, 0xC0, 0x1A, 0x1F, 0x0D, 0xBC, 0x21,
+ 0xF0, 0xC7, 0x4B, 0x97, 0xC7, 0x1F, 0x12, 0xFE, 0x19, 0x0D, 0x36, 0xF6, 0x1F, 0xDA, 0x1B, 0xC4,
+ 0xBA, 0x7F, 0xC6, 0x4F, 0x15, 0x78, 0xAB, 0x45, 0xF1, 0x14, 0xDE, 0x24, 0xD1, 0x3C, 0x7B, 0x7C,
+ 0x7C, 0x27, 0xA3, 0x68, 0x9A, 0x6E, 0xB1, 0x65, 0x29, 0x9E, 0x5B, 0x64, 0x81, 0xF4, 0x3F, 0x0B,
+ 0xF8, 0x6E, 0x24, 0x16, 0x9E, 0x5C, 0x0E, 0xB6, 0xEB, 0x38, 0x56, 0x92, 0x79, 0x65, 0x94, 0x03,
+ 0x8C, 0xBC, 0x97, 0xE1, 0x47, 0xC3, 0xFF, 0x00, 0xDA, 0x12, 0xC6, 0x76, 0x7B, 0xAB, 0xDF, 0x8D,
+ 0xDF, 0xB4, 0x87, 0x84, 0xED, 0xFC, 0x3D, 0x06, 0x95, 0x6A, 0xD0, 0x6A, 0x3A, 0xA2, 0xF8, 0x5F,
+ 0xE1, 0xC2, 0x5E, 0xDC, 0xC9, 0xA9, 0x3C, 0x1F, 0x2C, 0xD6, 0xFA, 0x35, 0x85, 0xE7, 0x8D, 0x96,
+ 0x19, 0x67, 0x25, 0xE2, 0x8E, 0xFB, 0xC4, 0x9A, 0x74, 0x58, 0x59, 0x35, 0x14, 0x12, 0x00, 0x79,
+ 0x67, 0x83, 0xBE, 0x2F, 0xFE, 0xCE, 0x1F, 0x02, 0xFC, 0x7F, 0xF1, 0xBB, 0xE0, 0xCE, 0x90, 0xFE,
+ 0x24, 0xF0, 0x9C, 0x9E, 0x1E, 0xF1, 0x5B, 0x7C, 0x63, 0xF1, 0xA4, 0x6F, 0xE1, 0x6B, 0xA9, 0x3C,
+ 0x1B, 0x65, 0xAD, 0x7C, 0x42, 0xD6, 0xAD, 0x6E, 0x35, 0x38, 0xF4, 0x98, 0x2D, 0x61, 0x32, 0xA7,
+ 0xDA, 0xF5, 0x6F, 0x14, 0xD8, 0x5E, 0xC9, 0x37, 0x90, 0xB6, 0xF7, 0x97, 0xBA, 0xCE, 0xAC, 0xD0,
+ 0x5C, 0xDD, 0xDD, 0x69, 0xDA, 0xE4, 0x7A, 0x50, 0x07, 0xB3, 0xFC, 0x6D, 0xD1, 0xBE, 0x14, 0xF8,
+ 0x8A, 0xCF, 0xE1, 0x7E, 0x8B, 0xF1, 0x66, 0x69, 0x1F, 0x4B, 0x9B, 0xE3, 0x67, 0x85, 0xF5, 0xAF,
+ 0x05, 0xE8, 0xED, 0x65, 0x2E, 0xA3, 0xA5, 0x6B, 0xBE, 0x2A, 0xD0, 0xEF, 0xBF, 0xB5, 0x7C, 0x2E,
+ 0x97, 0x90, 0xAC, 0x12, 0xC6, 0x56, 0xDF, 0x50, 0xD2, 0xAD, 0x2F, 0xA1, 0x79, 0x44, 0x6B, 0x15,
+ 0xD5, 0x8D, 0x94, 0xCB, 0x22, 0x49, 0x14, 0x46, 0x80, 0x3E, 0x7F, 0xF8, 0x53, 0xF1, 0xEB, 0xF6,
+ 0x7D, 0xFD, 0xA5, 0x3E, 0x33, 0xFC, 0x3A, 0xF1, 0xC7, 0x86, 0xF4, 0x4F, 0x88, 0x3A, 0x37, 0x8D,
+ 0x3C, 0x2B, 0xE0, 0xAF, 0x1A, 0x78, 0x7F, 0xE1, 0x8F, 0x8B, 0x3C, 0x49, 0xE1, 0x94, 0xF0, 0xF6,
+ 0x8B, 0xE2, 0xED, 0x2E, 0xEE, 0xFF, 0x00, 0x45, 0x3E, 0x2D, 0xD1, 0x63, 0x9D, 0x5A, 0x49, 0xA2,
+ 0x9D, 0x23, 0xB2, 0xF8, 0x7F, 0xA8, 0xCB, 0xA7, 0x5E, 0x0B, 0x39, 0xD1, 0xA6, 0x86, 0xDE, 0x58,
+ 0x06, 0xA3, 0xA0, 0x6B, 0x76, 0x3A, 0x00, 0x07, 0xDB, 0x5A, 0xD6, 0xB5, 0xA3, 0x78, 0x6B, 0x45,
+ 0xD5, 0xBC, 0x45, 0xE2, 0x2D, 0x5B, 0x4B, 0xF0, 0xFF, 0x00, 0x87, 0xBC, 0x3F, 0xA5, 0xDC, 0x6B,
+ 0x5A, 0xEE, 0xBB, 0xAD, 0x5F, 0xC3, 0xA4, 0xE8, 0xBA, 0x25, 0x95, 0xA4, 0x2D, 0x2D, 0xD5, 0xDD,
+ 0xDD, 0xD4, 0xAC, 0xB1, 0x43, 0x04, 0x51, 0x46, 0xEE, 0xF2, 0x3B, 0x2A, 0xA2, 0xAB, 0x31, 0x20,
+ 0x0E, 0x00, 0x38, 0xCD, 0x3B, 0xC4, 0xDE, 0x1C, 0xF8, 0xC9, 0xF0, 0xD2, 0xF7, 0x5B, 0xF8, 0x45,
+ 0xF1, 0x3F, 0x4C, 0xBA, 0xD1, 0x7C, 0x5D, 0xA3, 0xEA, 0x5A, 0x47, 0x85, 0x3E, 0x2A, 0xFC, 0x39,
+ 0xBE, 0xD2, 0x3C, 0x65, 0x69, 0xA5, 0xDD, 0x46, 0xF3, 0x59, 0xBE, 0xA1, 0xA6, 0x49, 0x2C, 0x77,
+ 0x5A, 0x75, 0xCC, 0xD6, 0xB7, 0x50, 0x4A, 0x02, 0x4D, 0x14, 0xF0, 0xF9, 0x90, 0x14, 0x92, 0x37,
+ 0x50, 0xC8, 0x40, 0x38, 0x18, 0xFC, 0x4D, 0xFB, 0x34, 0xFE, 0xC9, 0xDE, 0x15, 0xF0, 0x7F, 0xC3,
+ 0x9D, 0x6B, 0xE2, 0x37, 0xC3, 0x4F, 0x83, 0x9A, 0x34, 0xB6, 0xF7, 0x52, 0x78, 0x6A, 0xD3, 0xE2,
+ 0x77, 0xC5, 0x2B, 0x5D, 0x33, 0xC4, 0x7E, 0x30, 0x98, 0x4E, 0x25, 0xD5, 0xB5, 0x4B, 0xAD, 0x53,
+ 0x58, 0xBC, 0x3A, 0x86, 0xB3, 0xA8, 0x4D, 0x75, 0x7C, 0x6E, 0x2F, 0x75, 0x0B, 0x99, 0xAE, 0x6E,
+ 0xAE, 0x6E, 0x6E, 0xE4, 0xB8, 0xB9, 0x9A, 0x59, 0xAE, 0x1E, 0x49, 0x00, 0x33, 0xBF, 0x67, 0xDF,
+ 0xDA, 0xFB, 0xF6, 0x70, 0xFD, 0xA7, 0xBC, 0x2B, 0xF0, 0xDB, 0xC4, 0xFF, 0x00, 0x06, 0xBE, 0x2D,
+ 0x78, 0x1B, 0xC5, 0x32, 0xFC, 0x52, 0xF8, 0x70, 0xBF, 0x14, 0xFC, 0x31, 0xE1, 0x0B, 0x3F, 0x15,
+ 0x69, 0x97, 0x5E, 0x39, 0x8F, 0x49, 0x8E, 0xCF, 0x47, 0xB8, 0xD4, 0x5A, 0xEB, 0x4B, 0x86, 0xE2,
+ 0x49, 0x23, 0x92, 0xC4, 0x78, 0xC3, 0xC3, 0x11, 0xDE, 0x28, 0xDC, 0x2D, 0xA5, 0xD4, 0xEC, 0x63,
+ 0x90, 0x83, 0x3C, 0x7B, 0xC0, 0x3D, 0xEF, 0xC4, 0x3E, 0x24, 0xF0, 0xE7, 0x84, 0x34, 0x2D, 0x57,
+ 0xC4, 0xFE, 0x2C, 0xD7, 0xB4, 0x4F, 0x0B, 0xF8, 0x67, 0x40, 0xB0, 0x93, 0x53, 0xD7, 0x3C, 0x43,
+ 0xE2, 0x2D, 0x52, 0xDF, 0x44, 0xD0, 0xB4, 0x5B, 0x58, 0x57, 0x74, 0xB7, 0x17, 0x77, 0x73, 0x32,
+ 0x45, 0x0C, 0x48, 0xB8, 0x2C, 0xEE, 0xCA, 0xA0, 0x72, 0x48, 0x14, 0x01, 0xE4, 0xFF, 0x00, 0x01,
+ 0x7F, 0x69, 0x0F, 0x82, 0xBF, 0xB4, 0xC7, 0x86, 0x75, 0x5F, 0x15, 0xFC, 0x15, 0xF1, 0xFF, 0x00,
+ 0x86, 0xBC, 0x75, 0xA4, 0xE8, 0x1E, 0x24, 0xD4, 0x7C, 0x27, 0xAE, 0x8D, 0x07, 0x5B, 0xB2, 0xD5,
+ 0xEE, 0x34, 0x5B, 0xDD, 0x37, 0x51, 0xB9, 0xB2, 0x96, 0x3B, 0xA4, 0xB7, 0x96, 0x41, 0x18, 0x92,
+ 0x4D, 0x3E, 0x77, 0x88, 0xB1, 0x1B, 0xE2, 0x28, 0xE0, 0x61, 0xB8, 0x00, 0xF2, 0xEF, 0x88, 0x3F,
+ 0xB7, 0xE7, 0xEC, 0x75, 0xF0, 0xBF, 0xC6, 0xDE, 0x13, 0xF8, 0x77, 0xE2, 0xEF, 0xDA, 0x1B, 0xE1,
+ 0x26, 0x9F, 0xE2, 0xBF, 0x14, 0x7C, 0x47, 0xD4, 0x7E, 0x15, 0xDC, 0x69, 0x67, 0xE2, 0x16, 0x8B,
+ 0x1C, 0xBE, 0x0C, 0xD5, 0x74, 0xAD, 0x03, 0x58, 0xD5, 0x6F, 0x97, 0x5F, 0x47, 0xBA, 0x46, 0xB1,
+ 0x89, 0x22, 0xF0, 0xB6, 0xA1, 0x6C, 0x59, 0xD7, 0x3F, 0x6A, 0x96, 0xCE, 0xDF, 0x68, 0x69, 0x86,
+ 0x00, 0x24, 0xF8, 0xD5, 0xFB, 0x7A, 0xFE, 0xC8, 0x9F, 0x01, 0x3E, 0x11, 0xF8, 0xBF, 0xE3, 0x2F,
+ 0x8E, 0x3E, 0x3D, 0xFC, 0x2D, 0x7F, 0x0D, 0x78, 0x4B, 0xE0, 0xF6, 0xAD, 0xF1, 0xCE, 0xDB, 0x45,
+ 0xD0, 0xBE, 0x20, 0x68, 0x7A, 0x87, 0x8C, 0xFC, 0x6F, 0xE1, 0xED, 0x1E, 0xD2, 0xF6, 0x79, 0x67,
+ 0xF0, 0xDE, 0x96, 0xD7, 0x69, 0x26, 0xA2, 0xF3, 0x1D, 0x1F, 0x50, 0x82, 0xDD, 0x62, 0xCA, 0xCB,
+ 0x3C, 0x2F, 0x12, 0xB6, 0xE5, 0x6D, 0xA0, 0x1E, 0xE1, 0xF0, 0xFB, 0xE3, 0x67, 0xC1, 0xCF, 0x8B,
+ 0x17, 0xDA, 0xF6, 0x97, 0xF0, 0xB7, 0xE2, 0xAF, 0xC3, 0xAF, 0x88, 0xDA, 0x8F, 0x85, 0x6D, 0xAD,
+ 0x2F, 0x3C, 0x49, 0x61, 0xE0, 0x6F, 0x19, 0x69, 0xDE, 0x29, 0xBA, 0xD0, 0x60, 0xBE, 0xB9, 0xBC,
+ 0xB7, 0xB1, 0x9E, 0xEE, 0x3B, 0x69, 0x5C, 0xC5, 0x14, 0xD3, 0xE8, 0xBA, 0xBC, 0x51, 0x3B, 0x00,
+ 0xAE, 0xF6, 0x37, 0x6A, 0xA4, 0x98, 0x5C, 0x28, 0x07, 0x59, 0xE2, 0xCF, 0x18, 0xF8, 0x43, 0xC0,
+ 0x3A, 0x05, 0xDF, 0x8A, 0x7C, 0x73, 0xE2, 0xAF, 0x0D, 0x78, 0x2B, 0xC2, 0xFA, 0x7C, 0xD6, 0xD6,
+ 0xD7, 0xDE, 0x23, 0xF1, 0x6E, 0xB9, 0x6B, 0xE1, 0xBD, 0x02, 0xC6, 0x4B, 0xCB, 0xA8, 0xED, 0xAC,
+ 0xE3, 0x9A, 0xF2, 0xE1, 0xD2, 0x14, 0x69, 0x6E, 0x6E, 0x2D, 0xE1, 0x8C, 0x33, 0x02, 0xF2, 0x4B,
+ 0x1A, 0x2E, 0x59, 0x80, 0x20, 0x1E, 0x63, 0xFB, 0x38, 0x7E, 0xD1, 0x9F, 0x08, 0x3F, 0x6A, 0xFF,
+ 0x00, 0x83, 0x7E, 0x04, 0xF8, 0xEB, 0xF0, 0x3B, 0xC5, 0xDA, 0x5F, 0x8C, 0x7C, 0x01, 0xE3, 0xFF,
+ 0x00, 0x0C, 0xE9, 0x7E, 0x25, 0xD3, 0x6E, 0x74, 0xFB, 0xFB, 0x5B, 0xCB, 0xED, 0x1B, 0xFB, 0x53,
+ 0x4A, 0xB5, 0xD4, 0x22, 0xD3, 0x75, 0x48, 0xA0, 0x96, 0x45, 0xB5, 0xBF, 0x8A, 0xDF, 0x51, 0xB4,
+ 0xF3, 0xAD, 0xD9, 0xCB, 0x44, 0xCD, 0xB4, 0xFB, 0x80, 0x79, 0x26, 0xB5, 0xFF, 0x00, 0x05, 0x0C,
+ 0xFD, 0x89, 0xFC, 0x3F, 0xE3, 0x5F, 0x0F, 0xF8, 0x0B, 0x51, 0xFD, 0xA6, 0xBE, 0x0A, 0xC7, 0xAD,
+ 0x78, 0x82, 0xD3, 0x55, 0xB9, 0x8A, 0x68, 0xFE, 0x25, 0xE8, 0x6D, 0xA5, 0x69, 0x27, 0x46, 0x6B,
+ 0x75, 0xBA, 0x82, 0xFE, 0x7F, 0xB5, 0x0F, 0x22, 0x56, 0x37, 0xB1, 0x88, 0xD1, 0x86, 0x5B, 0xCB,
+ 0x98, 0x71, 0xB0, 0xD0, 0x06, 0xCF, 0xC4, 0xFF, 0x00, 0xDB, 0xA3, 0xF6, 0x46, 0xF8, 0x43, 0xA7,
+ 0xE8, 0xB7, 0x9E, 0x31, 0xFD, 0xA0, 0xFE, 0x10, 0x5B, 0xDC, 0x6B, 0xDE, 0x25, 0xF0, 0x57, 0x86,
+ 0x74, 0xDD, 0x0E, 0xD3, 0xE2, 0x5E, 0x81, 0x27, 0x88, 0xA4, 0x3E, 0x3E, 0xD6, 0x74, 0xBD, 0x3B,
+ 0xC3, 0x97, 0xE6, 0xC5, 0xEF, 0x12, 0x51, 0x62, 0xE7, 0xC4, 0x7A, 0x65, 0xD3, 0xCF, 0xB7, 0x6A,
+ 0xDA, 0x33, 0x5C, 0x0D, 0xC8, 0x06, 0xE0, 0x0F, 0x71, 0xF8, 0x73, 0xF1, 0x67, 0xE1, 0x6F, 0xC5,
+ 0xFD, 0x22, 0x6D, 0x7B, 0xE1, 0x4F, 0xC4, 0x4F, 0x04, 0x7C, 0x48, 0xD0, 0xED, 0xA6, 0xFB, 0x2D,
+ 0xC6, 0xAB, 0xE0, 0x6F, 0x13, 0xD9, 0x78, 0xA3, 0x4F, 0xB6, 0x90, 0x12, 0x04, 0x72, 0x4B, 0x6D,
+ 0x23, 0xAA, 0xB7, 0xEE, 0xDF, 0x82, 0x41, 0xF9, 0x4F, 0xA5, 0x00, 0x71, 0x9F, 0xB4, 0x9F, 0xED,
+ 0x1F, 0xF0, 0x8B, 0xF6, 0x4B, 0xF8, 0x2B, 0xF1, 0x07, 0xE3, 0xD7, 0xC6, 0xDF, 0x14, 0xE9, 0xFE,
+ 0x15, 0xF0, 0x1F, 0xC3, 0x9F, 0x07, 0x6B, 0x3E, 0x30, 0xBE, 0x59, 0xEF, 0xAD, 0x2D, 0xB5, 0xBF,
+ 0x11, 0xAE, 0x89, 0xA2, 0xDD, 0xEA, 0x97, 0x3A, 0x5E, 0x87, 0x6B, 0x3C, 0xD1, 0x0B, 0xDD, 0x4A,
+ 0x4B, 0x4D, 0x26, 0xF9, 0xA1, 0xB5, 0x8D, 0xB7, 0xC8, 0x62, 0x60, 0x30, 0x14, 0x95, 0x00, 0xF4,
+ 0x5F, 0x0B, 0x7C, 0x42, 0xF0, 0x17, 0x8D, 0xFC, 0x23, 0x17, 0x8F, 0xBC, 0x17, 0xE3, 0x4F, 0x0A,
+ 0x78, 0xB7, 0xC0, 0xB3, 0xA5, 0xEB, 0xDB, 0xF8, 0xCB, 0xC3, 0x3A, 0xFD, 0xA6, 0xB9, 0xE1, 0x5B,
+ 0x85, 0xD3, 0xAE, 0x65, 0xB7, 0xBF, 0x68, 0xB5, 0x08, 0x5D, 0xA0, 0x65, 0x86, 0x7B, 0x4B, 0xA8,
+ 0xDC, 0xAB, 0x10, 0xAD, 0x14, 0x8A, 0x70, 0x54, 0xE0, 0x03, 0xE5, 0x9B, 0xAF, 0xF8, 0x28, 0xC7,
+ 0xEC, 0x39, 0x65, 0xE3, 0x2D, 0x23, 0xC1, 0x12, 0xFE, 0xD4, 0x7F, 0x03, 0xBE, 0xDF, 0xAB, 0xF8,
+ 0x4B, 0x53, 0xF1, 0x8C, 0x3A, 0xAC, 0x7F, 0x14, 0x34, 0x26, 0xF0, 0xDD, 0xA5, 0xAE, 0x95, 0x77,
+ 0x63, 0x6F, 0x3C, 0x37, 0x17, 0x9F, 0x6A, 0xDB, 0x1D, 0xC3, 0xB6, 0xAF, 0x6E, 0xD1, 0xC6, 0x47,
+ 0xCE, 0x91, 0x5C, 0x30, 0x20, 0x44, 0x72, 0x01, 0xF4, 0xEF, 0xC4, 0x4F, 0x89, 0x3E, 0x0B, 0xF8,
+ 0x51, 0xE1, 0xFD, 0x3F, 0xC4, 0xFE, 0x3D, 0xD5, 0xCE, 0x85, 0xA1, 0xEA, 0x7E, 0x39, 0xF0, 0xBF,
+ 0xC3, 0x5B, 0x0B, 0xC4, 0xD3, 0x2E, 0xF5, 0x53, 0x3E, 0xB7, 0xE3, 0x3F, 0x12, 0xD8, 0x78, 0x7F,
+ 0xC3, 0x56, 0x5E, 0x55, 0xB4, 0x52, 0x48, 0xBF, 0x69, 0xD5, 0xF5, 0xDD, 0x2A, 0xDB, 0xCD, 0x65,
+ 0x11, 0x45, 0xE7, 0xF9, 0xB3, 0x3C, 0x51, 0x47, 0x24, 0x88, 0x01, 0xDC, 0xD0, 0x01, 0x40, 0x05,
+ 0x00, 0x58, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE,
+ 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7, 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7,
+ 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76, 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA,
+ 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5, 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8,
+ 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB,
+ 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1, 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F,
+ 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E,
+ 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x02, 0x1F, 0xBA, 0x7F, 0xDD, 0xFE, 0x94, 0x01, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F,
+ 0x20, 0x6B, 0xFE, 0x13, 0xF1, 0x27, 0xEC, 0xD7, 0xE2, 0x5D, 0x67, 0xE2, 0x57, 0xC2, 0x4F, 0x0D,
+ 0x6A, 0xDE, 0x29, 0xF8, 0x27, 0xE2, 0xED, 0x7E, 0xEB, 0xC4, 0xFF, 0x00, 0x1B, 0x3E, 0x03, 0xF8,
+ 0x3B, 0x47, 0x1A, 0x8E, 0xBD, 0xE1, 0x1D, 0x57, 0x55, 0xBF, 0x6B, 0x9D, 0x67, 0xE2, 0x2F, 0x80,
+ 0xB4, 0xD8, 0x54, 0x49, 0x3D, 0xC4, 0xF7, 0x17, 0x77, 0xB7, 0xBA, 0xEE, 0x87, 0x08, 0x92, 0x4D,
+ 0x51, 0xCC, 0xFA, 0xA6, 0x99, 0x13, 0x6B, 0x4D, 0x7B, 0x63, 0xE3, 0x10, 0x0D, 0x3F, 0x0E, 0xC5,
+ 0x63, 0xF1, 0x13, 0xF6, 0x90, 0xF8, 0x7F, 0xF1, 0xDB, 0xC1, 0xD7, 0x1A, 0x37, 0x8E, 0xBE, 0x13,
+ 0xEA, 0xDF, 0xB2, 0x9D, 0xC4, 0x5F, 0x0E, 0xBE, 0x29, 0xF8, 0x6F, 0x51, 0xB4, 0xF1, 0x37, 0x83,
+ 0xF5, 0x18, 0x3C, 0x4B, 0xAE, 0xE9, 0xBA, 0x87, 0x99, 0xA1, 0x6A, 0x90, 0xBB, 0xC5, 0x25, 0xB6,
+ 0xA1, 0x67, 0xA6, 0xE8, 0xF7, 0x26, 0x5B, 0x76, 0x31, 0x5C, 0xC7, 0x69, 0x60, 0xE5, 0x9C, 0x41,
+ 0x09, 0x40, 0x0A, 0x7F, 0xB1, 0x17, 0x82, 0xFC, 0x67, 0xF0, 0xF3, 0xE0, 0x6E, 0xB3, 0xE1, 0x0F,
+ 0x1C, 0x69, 0x1A, 0xBE, 0x81, 0x75, 0xA4, 0xFE, 0xD2, 0xBF, 0x1B, 0x9B, 0xC1, 0xFA, 0x1E, 0xAF,
+ 0x2B, 0x38, 0xD1, 0xFC, 0x1B, 0x73, 0xF1, 0xA7, 0xC5, 0x53, 0xF8, 0x02, 0xD7, 0x4E, 0x8C, 0xB3,
+ 0x2C, 0x1A, 0x5C, 0x7E, 0x19, 0x9F, 0xC3, 0xA9, 0x61, 0x6D, 0x1E, 0xD8, 0xAD, 0xEC, 0x96, 0xCA,
+ 0x08, 0x92, 0x38, 0xE2, 0x48, 0xD0, 0x03, 0xC9, 0xFE, 0x29, 0xFC, 0x18, 0xF8, 0x83, 0xFB, 0x4E,
+ 0xF8, 0xF3, 0xE3, 0x86, 0xBB, 0x1C, 0x96, 0x9F, 0x0E, 0x17, 0xE1, 0x07, 0x85, 0xED, 0x7E, 0x16,
+ 0x7E, 0xCB, 0xBA, 0xAF, 0x8B, 0x7C, 0x1F, 0x7D, 0x7B, 0x63, 0xAC, 0x78, 0xB6, 0xDB, 0x56, 0xF0,
+ 0xFF, 0x00, 0x8B, 0xEF, 0xBC, 0x69, 0xAB, 0xDB, 0x9B, 0x88, 0x27, 0xBA, 0xD0, 0xA2, 0xD7, 0xFC,
+ 0x2B, 0xE0, 0x7B, 0x0B, 0x78, 0x2C, 0x1B, 0x4C, 0xBA, 0x3F, 0xD8, 0xBE, 0x23, 0x9D, 0x2F, 0xE4,
+ 0x17, 0xDA, 0x5C, 0xFA, 0x50, 0x07, 0xD9, 0xBF, 0x09, 0x7C, 0x6B, 0xAA, 0x7C, 0x46, 0xF8, 0x67,
+ 0xE0, 0x6F, 0x1B, 0xEB, 0xDE, 0x0A, 0xD7, 0xFE, 0x1B, 0xF8, 0x8B, 0xC4, 0x7E, 0x1B, 0xB5, 0xD4,
+ 0x3C, 0x4B, 0xF0, 0xF3, 0xC5, 0x11, 0x15, 0xD7, 0xBC, 0x0B, 0xAA, 0x18, 0xC2, 0xEA, 0x5A, 0x3D,
+ 0xCC, 0xBB, 0x12, 0x3B, 0x83, 0x6D, 0x72, 0x97, 0x10, 0x8B, 0x98, 0x41, 0x82, 0xE1, 0x63, 0x59,
+ 0xE0, 0x67, 0x86, 0x58, 0xDD, 0x80, 0x3C, 0x57, 0xF6, 0xB1, 0xD1, 0x3C, 0x4F, 0xF1, 0x2F, 0xC2,
+ 0x5E, 0x16, 0xFD, 0x9E, 0x3C, 0x35, 0xE1, 0xEB, 0x9D, 0x43, 0x4B, 0xF8, 0xFB, 0xE2, 0x41, 0xE0,
+ 0xEF, 0x8B, 0x1E, 0x26, 0xB8, 0xD1, 0x25, 0xD4, 0xFC, 0x2D, 0xE0, 0x5F, 0x00, 0x5A, 0xC0, 0x6E,
+ 0x7C, 0x61, 0x35, 0xF6, 0x5A, 0x3B, 0x69, 0x67, 0xD4, 0x2D, 0x62, 0x8F, 0x44, 0xB4, 0xB6, 0x91,
+ 0xE5, 0xCD, 0xC6, 0xB7, 0x15, 0xDC, 0xB6, 0x57, 0xD6, 0x3A, 0x76, 0xA1, 0x01, 0x00, 0x9F, 0xE0,
+ 0x46, 0x8D, 0xE2, 0xDF, 0x86, 0x3F, 0x11, 0xBE, 0x37, 0x7C, 0x1C, 0xD5, 0x74, 0xFB, 0xCD, 0x43,
+ 0xE1, 0xFC, 0x9E, 0x29, 0xB9, 0xF8, 0xF5, 0xF0, 0x8F, 0xC7, 0x0B, 0xA3, 0x5C, 0xC1, 0x6F, 0x25,
+ 0xB7, 0x8F, 0x75, 0xAD, 0x4B, 0x50, 0xF1, 0x37, 0x85, 0xF5, 0x2B, 0xDC, 0xB5, 0xAC, 0xB7, 0xFA,
+ 0x76, 0xBC, 0x75, 0x69, 0xE1, 0x68, 0x92, 0xD1, 0x7F, 0xB2, 0xF5, 0x7D, 0x0A, 0x03, 0x14, 0xF7,
+ 0x16, 0x57, 0xB7, 0xB7, 0x60, 0x1F, 0x53, 0x0E, 0x31, 0x8E, 0x31, 0x8C, 0x63, 0x8C, 0x63, 0xA6,
+ 0x3F, 0x21, 0x40, 0x1F, 0x28, 0x6B, 0x3A, 0x07, 0x88, 0x3F, 0x67, 0x3F, 0x10, 0x6A, 0xFE, 0x3C,
+ 0xF8, 0x7D, 0xA3, 0x6B, 0x3E, 0x28, 0xF8, 0x25, 0xE2, 0x9D, 0x6E, 0x7F, 0x10, 0x7C, 0x54, 0xF8,
+ 0x4D, 0xE1, 0xED, 0x3E, 0xEB, 0x5E, 0xF1, 0x27, 0x80, 0xB5, 0x4D, 0x4E, 0xFD, 0xE7, 0xD4, 0xBC,
+ 0x65, 0xE0, 0xAD, 0x2E, 0xDA, 0xDE, 0x5B, 0x9B, 0xBF, 0xB4, 0xDD, 0x5F, 0x4D, 0x71, 0xAA, 0xE9,
+ 0x28, 0xC3, 0xCD, 0x0B, 0x36, 0xA1, 0x63, 0x19, 0xBE, 0x37, 0x56, 0x9A, 0xE8, 0x07, 0x21, 0xA2,
+ 0x78, 0xA3, 0x4C, 0xD2, 0x7F, 0x6C, 0xCB, 0x2F, 0x88, 0x30, 0xDE, 0x69, 0xFE, 0x22, 0xF8, 0x59,
+ 0xFB, 0x5B, 0x7E, 0xCB, 0x9E, 0x0E, 0xF0, 0xB7, 0xC1, 0x9F, 0x89, 0x9E, 0x18, 0xD5, 0xAD, 0xB5,
+ 0xAF, 0x04, 0x5E, 0xEA, 0xFE, 0x02, 0xD5, 0xFC, 0x53, 0xAD, 0x5C, 0xE9, 0xB3, 0x5E, 0xAB, 0x88,
+ 0xDA, 0x5D, 0x5F, 0x46, 0xF8, 0x87, 0x69, 0x7F, 0xA5, 0x35, 0xA1, 0xBA, 0x4B, 0xAB, 0x7F, 0x0E,
+ 0xF8, 0x91, 0xE5, 0x6B, 0x61, 0x6B, 0x69, 0xFD, 0xA0, 0x01, 0xF5, 0x9F, 0x8E, 0x3C, 0x0D, 0xE1,
+ 0x2F, 0x89, 0x3E, 0x0C, 0xF1, 0x97, 0xC3, 0xDF, 0x1C, 0xE8, 0x36, 0x1E, 0x24, 0xF0, 0x67, 0xC4,
+ 0x1F, 0x09, 0xDF, 0xF8, 0x17, 0xC6, 0x7E, 0x1F, 0xD4, 0x23, 0x63, 0x63, 0xE2, 0x2D, 0x23, 0x53,
+ 0xB4, 0x96, 0xDA, 0xFF, 0x00, 0x4F, 0xB8, 0xDA, 0x55, 0x8C, 0x52, 0xC1, 0x75, 0x71, 0x19, 0x01,
+ 0x94, 0xE2, 0x46, 0xC1, 0x04, 0xE6, 0x80, 0x3F, 0x28, 0xFF, 0x00, 0x62, 0x8F, 0xD9, 0x33, 0xC4,
+ 0xBE, 0x1B, 0xF8, 0xD7, 0x63, 0xAF, 0x7C, 0x52, 0xF1, 0x0F, 0xED, 0x57, 0xE2, 0x79, 0xBF, 0x63,
+ 0xCF, 0x0C, 0xEA, 0x1F, 0x07, 0xBC, 0x21, 0xAC, 0x7C, 0x7D, 0xFD, 0xA2, 0x7E, 0x20, 0x7C, 0x5C,
+ 0xD0, 0x7E, 0x30, 0x78, 0xA7, 0x53, 0xB9, 0xBC, 0xB7, 0xFF, 0x00, 0x85, 0x91, 0x3D, 0x9E, 0xBF,
+ 0xAA, 0x5D, 0xE9, 0x97, 0x5A, 0xB1, 0xF0, 0x2A, 0xF8, 0x41, 0xA2, 0xD4, 0x74, 0x38, 0x2C, 0x6C,
+ 0xED, 0xEE, 0x3C, 0x6B, 0xE3, 0x9D, 0x36, 0x48, 0xCD, 0xCD, 0xBC, 0xB6, 0x3A, 0x10, 0x07, 0xD6,
+ 0x1F, 0x1C, 0xA1, 0x8F, 0xC7, 0x7F, 0xB5, 0x0F, 0xEC, 0x5B, 0xE0, 0x4F, 0x08, 0x5C, 0x58, 0xDD,
+ 0xEB, 0xFF, 0x00, 0x03, 0x7E, 0x2C, 0x6B, 0x3F, 0xB4, 0xF7, 0xC5, 0x7D, 0x3A, 0xDE, 0x47, 0x73,
+ 0xE1, 0x3F, 0x0A, 0xEA, 0x3F, 0x0B, 0xFC, 0x73, 0xE1, 0x0D, 0x1E, 0x6B, 0xE5, 0x85, 0x1F, 0xEC,
+ 0xF3, 0xEA, 0x5A, 0xE7, 0x8B, 0x47, 0xD8, 0x92, 0xE4, 0x40, 0x97, 0x91, 0xE8, 0x9E, 0x25, 0x78,
+ 0x64, 0x77, 0xD2, 0xE5, 0x88, 0x80, 0x70, 0xDF, 0x1B, 0xFE, 0x00, 0x7C, 0x60, 0x3F, 0x13, 0x6E,
+ 0x3E, 0x32, 0x35, 0x95, 0xB7, 0xED, 0x8D, 0xF0, 0xFB, 0xC3, 0x7A, 0xA6, 0x97, 0xE3, 0xFF, 0x00,
+ 0x0B, 0xFE, 0xCC, 0xBF, 0x10, 0xFC, 0x58, 0xFF, 0x00, 0x0E, 0xB5, 0x6F, 0x05, 0x6A, 0x7A, 0x25,
+ 0xF8, 0xBC, 0x88, 0xF8, 0x42, 0x08, 0x64, 0xB7, 0xF0, 0x56, 0xBB, 0x79, 0x6F, 0x2D, 0xA6, 0x9D,
+ 0x7B, 0xA2, 0xC7, 0xE2, 0x8D, 0x3E, 0x0B, 0xBB, 0x4D, 0x5E, 0xDC, 0x4D, 0x2F, 0x8A, 0xAD, 0xA0,
+ 0x96, 0xD2, 0x4D, 0x00, 0x03, 0xEE, 0x0F, 0x00, 0x78, 0xB6, 0x0F, 0x1D, 0x78, 0x43, 0x46, 0xF1,
+ 0x44, 0x1E, 0x1A, 0xF1, 0x77, 0x83, 0x86, 0xA3, 0x1C, 0xB0, 0xCD, 0xE1, 0x5F, 0x1D, 0xF8, 0x72,
+ 0x5F, 0x0A, 0x78, 0xAF, 0x40, 0x9E, 0xD6, 0xE1, 0xED, 0xEE, 0x2D, 0x6E, 0xEC, 0x9F, 0x2B, 0xF2,
+ 0x4B, 0x6F, 0x20, 0x49, 0x61, 0x79, 0x6D, 0xE7, 0x8F, 0xCB, 0x9E, 0xDE, 0x69, 0xA0, 0x96, 0x29,
+ 0x64, 0x00, 0xF9, 0x17, 0xF6, 0xBB, 0xD5, 0x3C, 0x76, 0x9E, 0x24, 0xF8, 0x77, 0xA1, 0xC1, 0xE3,
+ 0xFF, 0x00, 0x8D, 0xFF, 0x00, 0x04, 0xFE, 0x14, 0xCD, 0xA1, 0xEA, 0xDA, 0xBF, 0x88, 0xBE, 0x2D,
+ 0x7E, 0xCE, 0xBF, 0x02, 0xB4, 0xBF, 0x8F, 0x3F, 0x12, 0x1F, 0x5D, 0x82, 0x7B, 0x28, 0xB4, 0x7D,
+ 0x02, 0xE6, 0xCF, 0x50, 0xF0, 0xB7, 0x89, 0xAD, 0x6C, 0x34, 0x99, 0x6D, 0xAE, 0xB5, 0x79, 0xE5,
+ 0x94, 0xE9, 0x02, 0x59, 0x6E, 0x2D, 0xB4, 0xD4, 0x8E, 0xFA, 0xD9, 0x23, 0x9E, 0x0D, 0x40, 0x03,
+ 0xE2, 0xCF, 0x87, 0xDF, 0x0D, 0x7E, 0x30, 0x7E, 0xCB, 0x7E, 0x3D, 0xFD, 0x9D, 0x3F, 0x68, 0x2F,
+ 0x13, 0xDF, 0xF8, 0xC3, 0xF6, 0xA6, 0xF8, 0x4B, 0xE0, 0xBF, 0x86, 0xDF, 0x1F, 0x3E, 0x10, 0xFC,
+ 0x2B, 0xD2, 0xBE, 0x13, 0x7E, 0xCF, 0x3A, 0xBF, 0x81, 0x7F, 0x68, 0x0B, 0x5D, 0x3F, 0xE2, 0xE6,
+ 0xBB, 0xE0, 0x3F, 0x18, 0xF8, 0x2B, 0x49, 0xF1, 0x0F, 0x85, 0xAE, 0xA5, 0x8E, 0xCA, 0xDF, 0xEC,
+ 0xD7, 0x5F, 0x0C, 0xBC, 0x57, 0xA1, 0x9B, 0xE9, 0x0E, 0x8B, 0x6F, 0x0B, 0x6A, 0x5E, 0x10, 0x8E,
+ 0x6B, 0x3B, 0x68, 0xCE, 0xA1, 0x7B, 0x68, 0x01, 0xF6, 0x67, 0xED, 0x71, 0xE0, 0x5F, 0x8B, 0xDE,
+ 0x1B, 0xB9, 0xF1, 0xA7, 0xED, 0x09, 0xFB, 0x38, 0x5A, 0xE8, 0xF6, 0x3F, 0x17, 0x63, 0xFD, 0x96,
+ 0x7C, 0x63, 0xF0, 0x72, 0xCE, 0xE6, 0xD7, 0x49, 0xB9, 0xD5, 0xB5, 0x9F, 0x13, 0xF8, 0x92, 0xF6,
+ 0xEE, 0xC2, 0x5F, 0x85, 0x57, 0x5A, 0xB6, 0x9B, 0x05, 0x95, 0xC2, 0x6A, 0x7A, 0x66, 0x85, 0xAA,
+ 0xDD, 0x78, 0x96, 0xEB, 0x33, 0xA4, 0xCF, 0x63, 0x0E, 0xAF, 0xAD, 0x9B, 0x58, 0x24, 0xFE, 0xD2,
+ 0xBC, 0x8E, 0x50, 0x0E, 0x47, 0x53, 0xF0, 0xC7, 0xEC, 0xF1, 0xF0, 0x0F, 0xC4, 0x3F, 0x02, 0xFE,
+ 0x04, 0x4D, 0xE0, 0xFF, 0x00, 0xDA, 0xCB, 0xC1, 0xBF, 0x0F, 0x7F, 0x66, 0x4F, 0x83, 0x5E, 0x05,
+ 0xD1, 0xBE, 0x00, 0xEA, 0x5F, 0x08, 0xFC, 0x59, 0xF1, 0xC3, 0x5F, 0xF8, 0x6D, 0xAB, 0xD8, 0xE8,
+ 0xF7, 0x17, 0x36, 0x16, 0xBE, 0x1D, 0xD7, 0xEC, 0x7C, 0x2D, 0x34, 0xB6, 0x1A, 0xAC, 0x9A, 0x7D,
+ 0xBF, 0x86, 0x34, 0x33, 0x70, 0x35, 0xE5, 0xBA, 0xFB, 0x54, 0x1A, 0x9A, 0x24, 0x8B, 0x24, 0x6D,
+ 0x38, 0x70, 0x0F, 0x90, 0x7F, 0x6C, 0xCF, 0xF8, 0x5B, 0x7E, 0x2C, 0xFD, 0xB7, 0xBE, 0x08, 0x5A,
+ 0x78, 0x53, 0xE0, 0xCF, 0xED, 0x79, 0xE3, 0x1F, 0x03, 0xFC, 0x21, 0xFD, 0xA0, 0x53, 0xC5, 0xFE,
+ 0x33, 0xBF, 0xF8, 0x51, 0xF1, 0x2F, 0xC4, 0x9A, 0x1E, 0xA2, 0xBA, 0x75, 0xE7, 0xC0, 0xFF, 0x00,
+ 0x11, 0xE9, 0x73, 0x6B, 0xDE, 0x0D, 0xD3, 0x6F, 0x34, 0xDB, 0x3F, 0x08, 0x45, 0xA7, 0xDB, 0x5D,
+ 0x78, 0xAF, 0x4F, 0x8A, 0xE6, 0x41, 0xE2, 0x88, 0x75, 0x49, 0xA7, 0xB7, 0xD6, 0x2D, 0xED, 0xF4,
+ 0x9B, 0x99, 0x26, 0x81, 0x2F, 0x00, 0x3E, 0x93, 0xF8, 0xBB, 0xE2, 0xDF, 0x15, 0x6B, 0x3A, 0xFF,
+ 0x00, 0x82, 0x74, 0x78, 0xFE, 0x28, 0x7E, 0xD7, 0x7F, 0x00, 0xBE, 0x07, 0xE9, 0xFF, 0x00, 0x06,
+ 0x74, 0x0B, 0xEF, 0x02, 0x7C, 0x58, 0xF8, 0x5B, 0xFB, 0x33, 0xC5, 0xF1, 0x87, 0xE2, 0xFF, 0x00,
+ 0xC4, 0xEF, 0x11, 0x1D, 0x43, 0x56, 0xB4, 0xF1, 0x16, 0x87, 0xE3, 0x4B, 0x1F, 0x11, 0x78, 0x0F,
+ 0xC4, 0x97, 0x5A, 0x3B, 0x69, 0xD6, 0x7A, 0x67, 0x86, 0x6E, 0xA3, 0x6B, 0x8B, 0x0D, 0x3E, 0x5B,
+ 0xE9, 0x75, 0xAB, 0xF6, 0x59, 0x66, 0x16, 0x52, 0x24, 0x40, 0x1C, 0x17, 0xEC, 0xF5, 0xE1, 0xEF,
+ 0x8B, 0xDF, 0xB1, 0xDF, 0xC4, 0xBF, 0x86, 0x3A, 0x77, 0xC4, 0x6F, 0x05, 0xF8, 0x83, 0xE3, 0xD6,
+ 0x97, 0xF1, 0x6B, 0xF6, 0x5F, 0xF8, 0x55, 0xFB, 0x31, 0x78, 0x0F, 0xC7, 0x3F, 0xB3, 0x4F, 0xC1,
+ 0x7D, 0x6B, 0xC2, 0x9E, 0x13, 0xF0, 0x84, 0x7F, 0x0F, 0x7E, 0x23, 0x78, 0x9E, 0x1B, 0x19, 0x7C,
+ 0x5F, 0xA1, 0x6B, 0x7A, 0xBD, 0xE5, 0xD7, 0x87, 0x61, 0x8F, 0xC2, 0x9F, 0x16, 0x7C, 0x3D, 0xA8,
+ 0x3C, 0x93, 0xEA, 0x77, 0x9E, 0x62, 0xF8, 0x53, 0xC6, 0x9C, 0x43, 0x71, 0x1E, 0x97, 0x61, 0xAB,
+ 0x00, 0x7A, 0xF7, 0xED, 0x91, 0xFB, 0x3A, 0xEB, 0x7E, 0x24, 0xD3, 0xFE, 0x36, 0xAF, 0x85, 0x74,
+ 0x8B, 0x9D, 0x4B, 0xE1, 0xAF, 0xED, 0x77, 0xF0, 0xF3, 0xC3, 0x7F, 0xB3, 0x7F, 0xED, 0x13, 0xE0,
+ 0x2F, 0x0E, 0xCF, 0xAA, 0xDC, 0x5F, 0xF8, 0xB2, 0x6F, 0x11, 0xF8, 0xBF, 0x46, 0xF0, 0xCC, 0xFE,
+ 0x26, 0x1A, 0x6D, 0xB4, 0x4D, 0x0D, 0x9B, 0xC5, 0xE0, 0xFD, 0x7F, 0xC4, 0xD6, 0xBA, 0x9E, 0xB7,
+ 0x0B, 0xC5, 0x7A, 0xB6, 0x1A, 0x66, 0x85, 0xE6, 0x34, 0xB1, 0x68, 0x56, 0x7F, 0x61, 0x00, 0xEF,
+ 0xAF, 0x7C, 0x73, 0xF0, 0xEA, 0xF7, 0xF6, 0xAA, 0xD6, 0x87, 0xC4, 0x0F, 0x08, 0xFE, 0xD5, 0xFE,
+ 0x0C, 0xF1, 0xEF, 0x80, 0x3C, 0x67, 0xA3, 0xFC, 0x36, 0xF8, 0x57, 0x7F, 0xE1, 0xED, 0x67, 0xE3,
+ 0x1E, 0xAD, 0xFB, 0x3B, 0xFC, 0x5A, 0xD2, 0xF5, 0x6F, 0x0E, 0x58, 0x5C, 0xC5, 0xE2, 0x1B, 0x9D,
+ 0x13, 0x44, 0x66, 0xF0, 0x52, 0xC7, 0x16, 0xA5, 0xE2, 0x9D, 0x73, 0x4B, 0x9A, 0x5D, 0x5A, 0x16,
+ 0x96, 0x29, 0x74, 0x4F, 0xB4, 0xCB, 0x24, 0x71, 0x43, 0x6A, 0xF0, 0x80, 0x7E, 0x78, 0xF8, 0xE6,
+ 0xE7, 0xE2, 0x8F, 0x8D, 0xBF, 0x6D, 0x68, 0xF5, 0xFB, 0x8F, 0x83, 0x9F, 0xB7, 0xA5, 0x9F, 0xC2,
+ 0x7F, 0x87, 0x5A, 0xA7, 0xC4, 0xAF, 0x0F, 0x78, 0x83, 0x5F, 0xF0, 0x07, 0xC5, 0x2F, 0x14, 0x9F,
+ 0x1D, 0x78, 0x4E, 0xDE, 0xE3, 0x58, 0xD3, 0x6D, 0xD7, 0xC4, 0x90, 0x78, 0x7E, 0xEB, 0x4D, 0xB0,
+ 0xD1, 0xCF, 0x86, 0xEE, 0x3F, 0xB3, 0x6F, 0xAE, 0xAC, 0x2D, 0x3C, 0x2F, 0xAE, 0xF8, 0x9B, 0x59,
+ 0xB9, 0xB1, 0x97, 0x46, 0x3F, 0xD8, 0xB0, 0xCC, 0x6E, 0xED, 0x74, 0xC0, 0x0F, 0x6F, 0xFD, 0xA8,
+ 0x67, 0xF1, 0x3F, 0xC7, 0xFD, 0x43, 0xE3, 0x4F, 0xC3, 0xEF, 0x88, 0x5E, 0x35, 0xF8, 0xED, 0xF0,
+ 0x17, 0xE1, 0x07, 0x8A, 0xFC, 0x1D, 0x6F, 0xE0, 0xFF, 0x00, 0x85, 0x5E, 0x17, 0xF0, 0x5F, 0xEC,
+ 0x7F, 0x79, 0xFB, 0x40, 0x7C, 0x34, 0xFD, 0xA9, 0xFC, 0x27, 0xE2, 0x9F, 0x06, 0xD8, 0xC9, 0xAC,
+ 0xDF, 0xFC, 0x4E, 0x74, 0xF0, 0xA5, 0xD6, 0xB9, 0xA6, 0xD9, 0xC9, 0x7F, 0xA9, 0xEB, 0xFE, 0x1F,
+ 0xB8, 0xF0, 0xEE, 0x9F, 0xAC, 0xF8, 0x53, 0x5A, 0x86, 0xCF, 0x4C, 0xBB, 0xBB, 0xFB, 0x7D, 0xB3,
+ 0x6B, 0x1A, 0x75, 0xCE, 0x9E, 0x01, 0xEE, 0xFF, 0x00, 0x01, 0xEF, 0x3E, 0x2A, 0x7C, 0x11, 0xF8,
+ 0xDF, 0x75, 0xF0, 0xA3, 0xE3, 0x3F, 0x87, 0xFC, 0x7B, 0xF1, 0x5F, 0xC7, 0xBF, 0x1A, 0xBC, 0x3D,
+ 0xE0, 0x7D, 0x5B, 0x52, 0xFD, 0xA0, 0xFE, 0x1E, 0x7C, 0x35, 0x93, 0x4D, 0xF8, 0x23, 0xA8, 0xDF,
+ 0xE8, 0x3F, 0x0E, 0xE7, 0xB1, 0xF1, 0x46, 0xA5, 0xAB, 0xCE, 0xF7, 0x72, 0x1D, 0x16, 0x4F, 0xED,
+ 0x3F, 0x06, 0x2F, 0xFA, 0x13, 0xBD, 0xC1, 0xFF, 0x00, 0x8A, 0x9F, 0xC3, 0x6B, 0x6F, 0x2D, 0xD0,
+ 0x3A, 0x8B, 0x69, 0x40, 0x1C, 0xE7, 0xC6, 0xEF, 0x83, 0xBE, 0x3D, 0xD2, 0x7E, 0x2F, 0x8F, 0x0A,
+ 0x78, 0x7B, 0x42, 0xBD, 0xD7, 0xBE, 0x0A, 0x7E, 0xD3, 0x9F, 0xB4, 0x6F, 0xC1, 0xDF, 0x18, 0xE9,
+ 0x5A, 0x36, 0x95, 0x06, 0xA5, 0xE2, 0x6D, 0x2B, 0xE1, 0x47, 0x8C, 0x7C, 0x15, 0xA8, 0xEB, 0xBE,
+ 0x2C, 0xF8, 0x9F, 0xE2, 0x5F, 0x10, 0xEF, 0x89, 0xA0, 0xF0, 0xEE, 0x81, 0xAA, 0x68, 0x5F, 0x0E,
+ 0x7C, 0x0F, 0x65, 0x67, 0xF6, 0x26, 0x78, 0x6E, 0x7C, 0x49, 0x7F, 0x37, 0x9F, 0x6D, 0x6B, 0x2E,
+ 0xB9, 0x77, 0xA8, 0xDC, 0x80, 0x7A, 0x6F, 0xC2, 0xFF, 0x00, 0x17, 0xFC, 0x38, 0xF1, 0x07, 0xED,
+ 0x05, 0xE2, 0x2D, 0x67, 0xC4, 0x1E, 0x16, 0xFD, 0xAB, 0xBC, 0x01, 0xF1, 0xCA, 0xFF, 0x00, 0xC6,
+ 0xBE, 0x26, 0xF0, 0x27, 0xFC, 0x21, 0xFE, 0x26, 0xF1, 0x0F, 0xC6, 0x3F, 0x10, 0x7E, 0xCF, 0x97,
+ 0x5A, 0x6F, 0x87, 0xEE, 0xAE, 0xAC, 0x74, 0x7D, 0x7A, 0xCA, 0xCF, 0x7B, 0x7C, 0x3C, 0xB3, 0x87,
+ 0x54, 0xD1, 0x74, 0x3D, 0x37, 0x54, 0x85, 0xA1, 0x8E, 0x29, 0x15, 0xF5, 0x11, 0x1C, 0x8C, 0x6F,
+ 0xA4, 0x9B, 0xCC, 0x00, 0xFC, 0xD8, 0xF8, 0x77, 0xE2, 0x5F, 0x89, 0x5A, 0xCF, 0xED, 0x49, 0xE0,
+ 0x4F, 0x8D, 0x5E, 0x3F, 0xF8, 0x35, 0xFB, 0x7B, 0xF8, 0x57, 0xE1, 0x4F, 0x83, 0x7E, 0x1E, 0x78,
+ 0x97, 0x4A, 0xD7, 0x35, 0x4D, 0x1B, 0xC7, 0xDE, 0x39, 0xF8, 0x9D, 0xE2, 0xAF, 0x85, 0x72, 0x6A,
+ 0x7A, 0xFE, 0x85, 0x7D, 0xA4, 0x69, 0xBE, 0x3D, 0xF0, 0xB5, 0xCE, 0x89, 0xA7, 0x5D, 0x4C, 0xD3,
+ 0x9D, 0x01, 0xAC, 0xEE, 0x2C, 0xBC, 0x14, 0xDE, 0x3A, 0xB3, 0x8E, 0x73, 0x2C, 0x97, 0x17, 0xD0,
+ 0xE9, 0xD6, 0x89, 0xA9, 0xDC, 0x80, 0x7E, 0xAA, 0x7E, 0xDC, 0x9A, 0x4E, 0x93, 0xA8, 0x7E, 0xCF,
+ 0xF1, 0xEA, 0x5A, 0xED, 0xE7, 0x8B, 0xEC, 0xB4, 0x6F, 0x00, 0x7C, 0x7B, 0xF8, 0x3D, 0xF1, 0x8F,
+ 0x54, 0xFF, 0x00, 0x84, 0x03, 0xE1, 0x27, 0x89, 0xBE, 0x39, 0xF8, 0xC2, 0xFA, 0xDF, 0xC0, 0xBF,
+ 0x17, 0xBC, 0x31, 0xE2, 0x19, 0x6C, 0x2C, 0x3C, 0x2F, 0xE1, 0xEB, 0x3B, 0xBD, 0x5E, 0xE9, 0xEE,
+ 0x57, 0x41, 0x36, 0xFB, 0xED, 0xED, 0xA5, 0x16, 0xEB, 0x33, 0x5C, 0xCA, 0x04, 0x36, 0xF2, 0x15,
+ 0x00, 0xFA, 0xF3, 0x18, 0xE3, 0x8E, 0x38, 0xE3, 0xA7, 0x1E, 0x94, 0x00, 0x50, 0x01, 0x40, 0x16,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xF3, 0xF3, 0xFF, 0x00, 0x83,
+ 0x9F, 0x7F, 0xE5, 0x39, 0xFF, 0x00, 0xF0, 0x48, 0x7F, 0xFB, 0x05, 0x7C, 0x3D, 0xFF, 0x00, 0xD5,
+ 0xBD, 0x73, 0x5D, 0x99, 0x67, 0xFC, 0x8C, 0x30, 0xFF, 0x00, 0xE3, 0x87, 0xFE, 0x94, 0x8E, 0x7C,
+ 0x4F, 0xFB, 0xAD, 0x4F, 0xF0, 0xBF, 0xC8, 0xFB, 0x52, 0xBF, 0x53, 0x3E, 0x38, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x3F, 0x60, 0xBF, 0xE0, 0x88, 0x5F, 0xF2, 0x22, 0x7E, 0xDD, 0x7F, 0xF6, 0x7C, 0xF0,
+ 0x7F, 0xEA, 0x86, 0xF8, 0x65, 0x5F, 0x9D, 0x71, 0x07, 0xFC, 0x8D, 0x27, 0xE9, 0x1F, 0xFD, 0x25,
+ 0x1F, 0x51, 0x95, 0xFF, 0x00, 0xB9, 0x47, 0xE7, 0xF9, 0x9F, 0xB6, 0xD5, 0xE2, 0x9E, 0x88, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x87, 0xEE, 0x9F,
+ 0xF7, 0x7F, 0xA5, 0x00, 0x7C, 0xBD, 0xFB, 0x56, 0x7C, 0x67, 0xF1, 0xD7, 0xC0, 0x4F, 0x86, 0xB6,
+ 0xFF, 0x00, 0x10, 0xBC, 0x19, 0x61, 0xFB, 0x32, 0x49, 0x65, 0x65, 0xE2, 0x0B, 0x6D, 0x3B, 0xC5,
+ 0x9A, 0xC7, 0xED, 0x5B, 0xFB, 0x50, 0xDE, 0x7E, 0xC9, 0x9F, 0x0D, 0x3C, 0x3D, 0x65, 0x74, 0xAD,
+ 0x1D, 0xBC, 0xD1, 0xF8, 0x92, 0x0F, 0x0A, 0xF8, 0x85, 0x64, 0xBA, 0x92, 0xED, 0xAC, 0xA1, 0x4B,
+ 0x69, 0x6D, 0xED, 0x95, 0xC4, 0xAC, 0x44, 0xFB, 0x91, 0x62, 0x94, 0x03, 0xF3, 0x9B, 0xF6, 0x54,
+ 0xFD, 0xBC, 0xFE, 0x37, 0xF8, 0xDF, 0xC5, 0x1F, 0x07, 0xFC, 0x35, 0xE3, 0x9F, 0x89, 0x3F, 0xB2,
+ 0xBF, 0xC5, 0xD7, 0xF8, 0xA9, 0xFB, 0x7D, 0x78, 0xCB, 0xF6, 0x60, 0xF1, 0x6E, 0x9B, 0xF0, 0x0B,
+ 0x5E, 0xB8, 0xF8, 0xA3, 0xA5, 0x7C, 0x22, 0xD3, 0xDF, 0xE1, 0x5F, 0x8E, 0xBE, 0x28, 0x78, 0x59,
+ 0x74, 0xDF, 0x88, 0x96, 0xE3, 0x4D, 0xD3, 0xFC, 0x47, 0x0A, 0xE8, 0x1A, 0x3F, 0x80, 0x2C, 0x22,
+ 0x94, 0x78, 0x7B, 0x4F, 0x75, 0x8C, 0xDF, 0x0B, 0xA9, 0x2E, 0x2F, 0x52, 0x63, 0x08, 0x07, 0xEB,
+ 0x17, 0x8E, 0xFE, 0x27, 0x5B, 0x78, 0x1B, 0xC4, 0xFF, 0x00, 0x0E, 0x3C, 0x23, 0x3E, 0x85, 0x7F,
+ 0x75, 0x7D, 0xF1, 0x5A, 0xFF, 0x00, 0x55, 0xF0, 0xC7, 0x83, 0xF5, 0xB9, 0x6E, 0x20, 0xB2, 0xF0,
+ 0x84, 0x1A, 0xF6, 0x9F, 0xA3, 0xCF, 0xA9, 0xD9, 0x68, 0xFA, 0xA5, 0xC2, 0x99, 0x2E, 0xED, 0x8D,
+ 0xE5, 0xA6, 0x9B, 0xAB, 0xBC, 0x53, 0xC7, 0x69, 0x71, 0x1A, 0x9B, 0x19, 0x11, 0xCA, 0xC9, 0x2D,
+ 0xB4, 0x77, 0x00, 0x1F, 0x03, 0x7E, 0xC9, 0xFF, 0x00, 0xB4, 0xA7, 0xED, 0x75, 0xF1, 0x03, 0xE1,
+ 0x8E, 0xB1, 0xFB, 0x44, 0x7C, 0x4F, 0xF8, 0x61, 0xA7, 0x7C, 0x47, 0xF0, 0x1F, 0xC5, 0x2F, 0x88,
+ 0x5E, 0x23, 0xB5, 0xF8, 0x35, 0xF0, 0x7B, 0xF6, 0x68, 0x87, 0x4A, 0xF1, 0xB5, 0xEF, 0x84, 0x3C,
+ 0x3D, 0xA1, 0x6A, 0x72, 0x69, 0x5A, 0x67, 0x89, 0xAC, 0xFE, 0x25, 0xEB, 0xDA, 0x97, 0x86, 0x2C,
+ 0xFC, 0x51, 0xE1, 0x9D, 0x7D, 0x34, 0x59, 0xB5, 0xBD, 0x1E, 0xF2, 0x1D, 0x02, 0xD5, 0xE6, 0xD3,
+ 0xF5, 0xCD, 0x32, 0x51, 0x3D, 0xC4, 0x2C, 0x92, 0x30, 0x07, 0x96, 0xFF, 0x00, 0xC1, 0x4A, 0xBF,
+ 0x6B, 0x7F, 0xDA, 0x2B, 0xF6, 0x67, 0xD5, 0x74, 0x7D, 0x3F, 0xE1, 0xDF, 0xC5, 0x7B, 0xBF, 0x0B,
+ 0x58, 0x78, 0x83, 0xE2, 0xBF, 0xC2, 0x08, 0x74, 0x6B, 0x2F, 0x0B, 0xFF, 0x00, 0xC1, 0x2A, 0xFE,
+ 0x35, 0xFE, 0xD4, 0x1F, 0x60, 0xD0, 0xBC, 0x43, 0xF1, 0x33, 0x43, 0xD1, 0x7C, 0x45, 0x61, 0xA8,
+ 0xFC, 0x43, 0xD0, 0xB5, 0x09, 0xFC, 0x31, 0x35, 0xDD, 0xCC, 0x0D, 0xAF, 0x2A, 0xE9, 0x51, 0xDA,
+ 0x59, 0xEA, 0xD2, 0xC3, 0x75, 0x65, 0x69, 0x67, 0xE5, 0x5E, 0xDD, 0xD8, 0x5F, 0x48, 0x01, 0xF6,
+ 0x17, 0x80, 0x7F, 0x69, 0xFD, 0x4A, 0xC3, 0xE1, 0x47, 0x80, 0x7C, 0x4F, 0xE3, 0x8B, 0x3F, 0x1F,
+ 0x7C, 0x5F, 0xF1, 0x97, 0xC4, 0x09, 0x35, 0xDD, 0x6B, 0x4A, 0xF0, 0xFF, 0x00, 0xC3, 0x9F, 0xD9,
+ 0x07, 0xC6, 0xDF, 0xB3, 0x57, 0x8F, 0x6D, 0x3C, 0x3F, 0xE1, 0xFB, 0xA4, 0xB7, 0xD5, 0xF5, 0x5B,
+ 0xEF, 0x86, 0x9E, 0x2F, 0xD4, 0x65, 0xF1, 0x15, 0xAC, 0x56, 0x72, 0x4D, 0x68, 0x0E, 0xF6, 0x37,
+ 0x17, 0x9F, 0x6D, 0xD3, 0xBE, 0xC5, 0x67, 0x39, 0xBB, 0x80, 0x4C, 0x01, 0xDC, 0x68, 0x7F, 0xB6,
+ 0x9F, 0xEC, 0xB3, 0xE2, 0x1B, 0x0D, 0x0A, 0xFB, 0x4A, 0xF8, 0xD1, 0xE1, 0x27, 0x5D, 0x5F, 0x4B,
+ 0xD6, 0xF5, 0xBD, 0x53, 0x4E, 0xBB, 0xFB, 0x56, 0x95, 0xE2, 0x0F, 0x86, 0x76, 0x5E, 0x18, 0xB1,
+ 0x9E, 0xE7, 0xC5, 0x37, 0x7E, 0x3D, 0xD2, 0xE7, 0x85, 0x2F, 0x3C, 0x21, 0x0E, 0x94, 0x6C, 0xE4,
+ 0xB4, 0xD4, 0x5F, 0x5F, 0x87, 0x4D, 0x5B, 0x0B, 0xF9, 0x2D, 0x74, 0xCB, 0xA3, 0x05, 0xF5, 0xD5,
+ 0xBD, 0xAC, 0xC0, 0x19, 0x9A, 0x2F, 0xED, 0xAD, 0xF0, 0x27, 0xFB, 0x46, 0x4D, 0x0F, 0xE2, 0x76,
+ 0xA9, 0xAD, 0x7E, 0xCD, 0xDA, 0xF4, 0xBE, 0x1E, 0x1E, 0x33, 0xF0, 0xF6, 0x8D, 0xFB, 0x4D, 0x69,
+ 0x2B, 0xF0, 0x42, 0x5F, 0x1B, 0x68, 0x7B, 0x4B, 0x3E, 0xAB, 0xA1, 0xDC, 0xEA, 0x32, 0x25, 0xA5,
+ 0xE7, 0xD9, 0xD0, 0x40, 0xD7, 0xD6, 0x71, 0xCC, 0x6F, 0xF4, 0x91, 0x75, 0xA7, 0xAE, 0xA7, 0x69,
+ 0x60, 0xD7, 0xD6, 0xAB, 0x38, 0x04, 0xBA, 0xDF, 0xED, 0x91, 0xF0, 0xA7, 0x43, 0x7B, 0x6B, 0xD7,
+ 0xF0, 0xFF, 0x00, 0xC5, 0xDB, 0xBF, 0x07, 0x69, 0xDA, 0x16, 0x85, 0xE2, 0x0F, 0x89, 0xFE, 0x3F,
+ 0x8F, 0xE1, 0x26, 0xB5, 0xA5, 0x78, 0x73, 0xE0, 0x1D, 0xBF, 0x89, 0xAD, 0xE2, 0x9F, 0x44, 0x8B,
+ 0xC7, 0x36, 0x77, 0x90, 0xDB, 0xEA, 0xBA, 0x5D, 0xCF, 0xD9, 0xEE, 0xAD, 0xAE, 0x75, 0x0B, 0x53,
+ 0x63, 0x24, 0xFA, 0x0D, 0x94, 0xD6, 0xFA, 0x8E, 0xBB, 0x1E, 0x91, 0x61, 0x71, 0x05, 0xDC, 0xA0,
+ 0x1D, 0x25, 0xD7, 0xED, 0x55, 0xF0, 0x4E, 0xE3, 0x46, 0xD5, 0x75, 0x4F, 0x00, 0xF8, 0xA1, 0x7E,
+ 0x33, 0x5C, 0xD8, 0xA6, 0x85, 0x6F, 0xA4, 0x68, 0xDF, 0x05, 0xE1, 0x5F, 0x88, 0x57, 0x1E, 0x30,
+ 0xBE, 0xF1, 0x34, 0xB7, 0x11, 0xE8, 0x5A, 0x5E, 0x93, 0x7F, 0x6E, 0xDF, 0xD9, 0xB2, 0x4F, 0x28,
+ 0xB0, 0xB9, 0x9E, 0x76, 0x92, 0xEE, 0x28, 0x34, 0xEB, 0x25, 0xFE, 0xD2, 0xD4, 0x26, 0xB2, 0xD3,
+ 0xC1, 0xBC, 0x50, 0x0C, 0xAF, 0x0D, 0xFE, 0xD8, 0xDF, 0x00, 0xB5, 0xA8, 0x6F, 0xEC, 0x35, 0x8F,
+ 0x16, 0xCD, 0xF0, 0xF7, 0xE2, 0x06, 0x83, 0xAD, 0x5A, 0xF8, 0x5B, 0xC4, 0xFF, 0x00, 0x05, 0xBE,
+ 0x21, 0xE9, 0x33, 0xF8, 0x6F, 0xE3, 0x4E, 0x81, 0xAA, 0xDE, 0x5F, 0x9B, 0x1B, 0x3B, 0x24, 0xF0,
+ 0xDE, 0xD7, 0xB9, 0xD4, 0x62, 0xB9, 0xBC, 0x8E, 0x58, 0xAC, 0xEF, 0xF4, 0xC1, 0x7D, 0xA7, 0xEA,
+ 0x4A, 0x86, 0x7D, 0x3E, 0xEE, 0xF2, 0xDD, 0x92, 0x77, 0x00, 0xEC, 0xFE, 0x36, 0xFC, 0x42, 0xD7,
+ 0xFE, 0x1E, 0xC7, 0xF0, 0x98, 0xF8, 0x7E, 0x3D, 0x31, 0xFF, 0x00, 0xE1, 0x35, 0xF8, 0xDD, 0xE1,
+ 0xDF, 0x87, 0x9A, 0xC8, 0xD4, 0x6D, 0x5E, 0xE4, 0x26, 0x9F, 0xAA, 0x49, 0x2A, 0xDC, 0xB5, 0xB8,
+ 0x57, 0x4D, 0x93, 0x01, 0x12, 0x6D, 0x63, 0xB8, 0x0E, 0x72, 0xA7, 0xB0, 0x07, 0xB7, 0x60, 0x63,
+ 0x18, 0x18, 0xC6, 0x31, 0x81, 0x8C, 0x63, 0xA6, 0x28, 0x03, 0xE3, 0xEF, 0x19, 0x7C, 0x7B, 0xF8,
+ 0xA7, 0xF0, 0x02, 0x4F, 0x1D, 0x6B, 0xFF, 0x00, 0x1E, 0xBE, 0x15, 0xCF, 0xE2, 0x8F, 0x82, 0xBA,
+ 0x2E, 0xA3, 0x79, 0xAD, 0x78, 0x7F, 0xE3, 0x27, 0xEC, 0xEB, 0xA3, 0x6A, 0x9E, 0x3E, 0xD7, 0x74,
+ 0x5D, 0x11, 0xEE, 0x5E, 0x48, 0x2D, 0xFC, 0x57, 0xF0, 0xE5, 0x12, 0x7D, 0x75, 0x2E, 0xED, 0xA2,
+ 0xB8, 0xB1, 0xB3, 0x59, 0xB4, 0x13, 0xE2, 0x11, 0xA8, 0x3D, 0xB5, 0xD5, 0xF3, 0xDA, 0xE8, 0xEB,
+ 0x34, 0x76, 0x11, 0x00, 0x6C, 0xFC, 0x4C, 0xF8, 0xBB, 0x2F, 0x8A, 0x74, 0xFF, 0x00, 0xD9, 0xCB,
+ 0x4A, 0xF8, 0x1F, 0xF1, 0x0B, 0xC3, 0xED, 0xA1, 0xFE, 0xD3, 0x3E, 0x31, 0x6D, 0x2B, 0x45, 0xF8,
+ 0xCD, 0xE0, 0xD9, 0xB4, 0xBF, 0x1D, 0xE9, 0xF6, 0x5E, 0x1D, 0x8B, 0xC1, 0xFA, 0xB6, 0xBC, 0xDA,
+ 0xC7, 0x86, 0xA7, 0x6F, 0xB4, 0x69, 0x97, 0x77, 0x17, 0x11, 0xE8, 0xD6, 0xB1, 0x5B, 0x4D, 0x2C,
+ 0x77, 0x56, 0xAA, 0xB7, 0x2D, 0x3B, 0x45, 0x38, 0x8D, 0x62, 0x94, 0x03, 0xD1, 0xFC, 0x57, 0xA0,
+ 0x7C, 0x68, 0xBE, 0xF8, 0xC1, 0xF0, 0x8B, 0x5D, 0xF0, 0x77, 0x8F, 0xBC, 0x2F, 0xE1, 0xEF, 0x83,
+ 0x1E, 0x1F, 0xD3, 0x3C, 0x44, 0xBF, 0x19, 0x3C, 0x09, 0xAA, 0x78, 0x4C, 0x6B, 0xBE, 0x21, 0xF8,
+ 0x83, 0x3D, 0xD5, 0xA4, 0x11, 0xF8, 0x72, 0x3D, 0x2A, 0xF8, 0x34, 0x4D, 0xA7, 0x3D, 0xB5, 0xC8,
+ 0x9E, 0xE1, 0xEE, 0x4C, 0xB2, 0x21, 0x8A, 0x29, 0xAD, 0x5A, 0xCE, 0x76, 0xBE, 0x8A, 0xF3, 0x47,
+ 0x00, 0xFC, 0xFB, 0xD2, 0xFF, 0x00, 0x6E, 0x0F, 0xDA, 0x0F, 0x55, 0xFD, 0x9F, 0x3C, 0x3F, 0xE1,
+ 0x9B, 0x5F, 0xD9, 0xFB, 0xC5, 0xEB, 0xFB, 0x5C, 0xF8, 0x8F, 0x50, 0xBE, 0xFD, 0x96, 0x74, 0xFF,
+ 0x00, 0x1D, 0x4B, 0xA6, 0xF8, 0x5A, 0x3F, 0xD9, 0xA2, 0x2F, 0x8D, 0x3A, 0x4A, 0x5E, 0x69, 0x7A,
+ 0xBE, 0xAD, 0x3D, 0x8F, 0xFC, 0x25, 0x3F, 0xF0, 0x90, 0xC5, 0xE0, 0xEB, 0x6D, 0x4F, 0x44, 0xD5,
+ 0xF5, 0x72, 0x5A, 0xD4, 0x5F, 0x4D, 0xA2, 0x5A, 0x89, 0x6D, 0xE0, 0x9E, 0x7B, 0x8B, 0x68, 0x6E,
+ 0x00, 0x3F, 0x41, 0x3C, 0x0D, 0xE1, 0xFF, 0x00, 0x8D, 0x1A, 0x77, 0xC4, 0xDF, 0x8D, 0x5A, 0xCF,
+ 0x8F, 0x3C, 0x7F, 0xE1, 0x7F, 0x10, 0xFC, 0x28, 0xF1, 0x0E, 0xA3, 0xA1, 0x9F, 0x81, 0xDE, 0x04,
+ 0xD2, 0xFC, 0x26, 0x34, 0xEF, 0x12, 0xFC, 0x3E, 0x82, 0xD7, 0x49, 0x09, 0xAF, 0xBE, 0xA7, 0xAC,
+ 0xAB, 0xA0, 0xBB, 0x4B, 0xBB, 0xD6, 0x46, 0x86, 0xD8, 0xC3, 0x23, 0xDB, 0xFD, 0x9E, 0x79, 0x7E,
+ 0xD9, 0x2A, 0x5F, 0xC5, 0x65, 0xA4, 0x80, 0x79, 0xD7, 0xEC, 0xBB, 0xF1, 0x47, 0x5E, 0xF1, 0x84,
+ 0x1F, 0x1C, 0xFE, 0x15, 0x78, 0xDF, 0x59, 0xD4, 0x3C, 0x55, 0xF1, 0x03, 0xF6, 0x52, 0xF8, 0xDC,
+ 0xFF, 0x00, 0x00, 0xBC, 0x69, 0xE3, 0xFD, 0x47, 0x4E, 0xD3, 0xB4, 0xAF, 0xF8, 0x58, 0x8B, 0x3F,
+ 0x84, 0x34, 0x0F, 0x15, 0xF8, 0x77, 0x5C, 0x92, 0x3B, 0x28, 0xED, 0xED, 0x7E, 0xD9, 0x2F, 0x87,
+ 0x3C, 0x79, 0xE1, 0x95, 0xD4, 0x0C, 0x16, 0x5A, 0x7D, 0xB0, 0xD5, 0x22, 0xD5, 0xD6, 0xD6, 0xD2,
+ 0x2B, 0x45, 0xB6, 0xDE, 0x01, 0xD9, 0x7E, 0xCE, 0x7F, 0x13, 0x3C, 0x51, 0xF1, 0x9F, 0xE1, 0x7E,
+ 0x9D, 0xF1, 0x63, 0xC4, 0x1A, 0x26, 0x8D, 0xE1, 0xBD, 0x13, 0xE2, 0x06, 0xAD, 0x7F, 0xE2, 0x2F,
+ 0x85, 0xBA, 0x36, 0x95, 0x71, 0x36, 0xA1, 0x79, 0xFF, 0x00, 0x08, 0x63, 0xDC, 0xB4, 0x7E, 0x15,
+ 0xD5, 0x35, 0x3B, 0xA7, 0xD9, 0xBA, 0xF7, 0x53, 0xD3, 0xE1, 0xB5, 0xD5, 0x64, 0xB7, 0x58, 0x20,
+ 0xFB, 0x0F, 0xF6, 0x9A, 0x69, 0xCD, 0xF6, 0x87, 0xB0, 0x7B, 0xDB, 0xD0, 0x0A, 0x77, 0x3E, 0x34,
+ 0xF1, 0x3C, 0x7F, 0xB5, 0x36, 0x89, 0xF0, 0xE9, 0x35, 0x52, 0xBE, 0x0A, 0xBB, 0xFD, 0x9F, 0xB5,
+ 0x4F, 0x1A, 0x5C, 0x68, 0x5F, 0x61, 0xB5, 0x29, 0x26, 0xA9, 0x6F, 0xE2, 0x2D, 0x3E, 0xD6, 0x0B,
+ 0xBF, 0xB4, 0xF9, 0x5F, 0x68, 0x1B, 0x60, 0xB9, 0x9D, 0x3C, 0xB1, 0x20, 0x8C, 0xEF, 0xC9, 0x42,
+ 0xC0, 0x10, 0x01, 0xF4, 0x00, 0xE3, 0xA7, 0x1F, 0x4E, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x10, 0x28,
+ 0x1D, 0x00, 0x1F, 0x40, 0x07, 0x61, 0xFE, 0x03, 0xF2, 0x1E, 0x94, 0x01, 0xE1, 0x9A, 0xC7, 0xC4,
+ 0xAF, 0x13, 0x4B, 0xFB, 0x43, 0xF8, 0x2F, 0xE0, 0xC7, 0x86, 0x34, 0xDD, 0x0F, 0xFB, 0x0A, 0xD7,
+ 0xE1, 0xAE, 0xA7, 0xF1, 0x5F, 0xE2, 0xB7, 0x88, 0xF5, 0x33, 0x35, 0xD6, 0xA9, 0xA6, 0xDA, 0xB5,
+ 0xE4, 0x7A, 0x77, 0x85, 0xF4, 0x5D, 0x32, 0xCD, 0x1A, 0x34, 0x49, 0x6F, 0xAE, 0x9F, 0x5A, 0xBA,
+ 0x7B, 0xD9, 0x1E, 0x65, 0x82, 0x2F, 0x0F, 0xCB, 0x6A, 0x2D, 0x24, 0x7D, 0x4D, 0x2E, 0xB4, 0xD0,
+ 0x0E, 0xFF, 0x00, 0xE2, 0x1E, 0x81, 0xE2, 0xDF, 0x12, 0x78, 0x43, 0x53, 0xD2, 0x7C, 0x07, 0xE3,
+ 0xAB, 0x8F, 0x86, 0xDE, 0x2F, 0x32, 0x5A, 0xDF, 0xE8, 0x1E, 0x2E, 0x87, 0xC3, 0xB6, 0x5E, 0x2D,
+ 0xB3, 0xB3, 0x9E, 0xCA, 0xEE, 0x2B, 0x85, 0xB4, 0xD4, 0x34, 0xBB, 0x90, 0x12, 0xEB, 0x4F, 0xBA,
+ 0x16, 0xED, 0x6B, 0x77, 0x14, 0x32, 0xDA, 0x5C, 0xB5, 0xAD, 0xC5, 0xC8, 0xB5, 0xBD, 0xB1, 0xB9,
+ 0xF2, 0x2F, 0x2D, 0x80, 0x38, 0x6F, 0x83, 0xDF, 0x18, 0xBF, 0xE1, 0x61, 0xB6, 0xBD, 0xE0, 0xDF,
+ 0x18, 0xF8, 0x7A, 0x1F, 0x87, 0x3F, 0x1B, 0xFE, 0x1E, 0x43, 0x65, 0x17, 0xC5, 0x2F, 0x85, 0x6D,
+ 0xAC, 0xB6, 0xBD, 0x06, 0x8C, 0x6F, 0xA3, 0x63, 0x65, 0xAC, 0xF8, 0x7B, 0x54, 0x7B, 0x7B, 0x66,
+ 0xD6, 0x7C, 0x37, 0x7A, 0xD6, 0xF7, 0x82, 0xC7, 0x56, 0x5B, 0x5B, 0x61, 0x33, 0x5A, 0xDE, 0xDA,
+ 0xDC, 0x5B, 0xD8, 0xEA, 0x3A, 0x7E, 0xA3, 0xA6, 0xE9, 0xE0, 0x1E, 0xDD, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x58, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7,
+ 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76,
+ 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5,
+ 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1,
+ 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4,
+ 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x02, 0x1F, 0xBA, 0x7F,
+ 0xDD, 0xFE, 0x94, 0x01, 0xE0, 0x3F, 0x1C, 0x7E, 0x0E, 0x6B, 0x3F, 0x14, 0x20, 0xF0, 0x66, 0xBF,
+ 0xE0, 0x8F, 0x88, 0x57, 0x7F, 0x0B, 0xFE, 0x29, 0xFC, 0x2A, 0xD6, 0xAF, 0x3C, 0x5D, 0xF0, 0xC3,
+ 0xC5, 0xB2, 0x78, 0x62, 0xCB, 0xC7, 0x3E, 0x12, 0x83, 0x53, 0xB9, 0xD2, 0x2E, 0xAC, 0x0D, 0xAF,
+ 0x88, 0xF4, 0x19, 0xCC, 0x52, 0x5F, 0xE9, 0x33, 0x45, 0x7F, 0x22, 0x5C, 0xC1, 0x67, 0x7B, 0xA5,
+ 0x5E, 0xB4, 0x46, 0x44, 0xB6, 0xD4, 0xAC, 0x64, 0x7F, 0x39, 0x40, 0x3C, 0x37, 0x5E, 0xFD, 0x93,
+ 0xBC, 0x71, 0xE3, 0x3F, 0x0A, 0xF8, 0x6B, 0xC7, 0x9E, 0x2B, 0xF1, 0x77, 0xEC, 0xED, 0x69, 0xFB,
+ 0x70, 0xF8, 0x17, 0xC5, 0xB6, 0x1E, 0x37, 0xF0, 0x67, 0xED, 0x47, 0xF0, 0xFF, 0x00, 0xF6, 0x5E,
+ 0xD4, 0x3C, 0x25, 0xE1, 0x2B, 0x7B, 0xCD, 0x1A, 0x0D, 0x7F, 0x4F, 0xD1, 0xEC, 0xF5, 0x7F, 0x07,
+ 0xDC, 0x78, 0xBA, 0xF7, 0x53, 0xD4, 0xF4, 0xD5, 0xD0, 0x7E, 0x20, 0x78, 0xEF, 0x4C, 0x92, 0xD6,
+ 0x6F, 0x11, 0x0D, 0xAB, 0xE2, 0x2D, 0x62, 0xEA, 0xCE, 0x4D, 0x3E, 0xE6, 0x68, 0xE6, 0x80, 0x03,
+ 0xE8, 0x7D, 0x4B, 0xE1, 0x12, 0xEA, 0xBF, 0x0F, 0x7C, 0x0B, 0xE1, 0x8D, 0x53, 0xC6, 0x3E, 0x20,
+ 0xF1, 0x2F, 0x8E, 0xFE, 0x19, 0x69, 0x11, 0xCB, 0xE0, 0x9F, 0x8C, 0x5E, 0x2E, 0xB5, 0xD3, 0xEF,
+ 0xBC, 0x65, 0x6F, 0xE2, 0x48, 0x7C, 0x3B, 0x75, 0xA4, 0x27, 0x8B, 0x75, 0x0B, 0x3B, 0x1B, 0x7B,
+ 0x2D, 0x2E, 0xE6, 0xF9, 0xE2, 0xD4, 0xEF, 0xE5, 0x96, 0x18, 0xED, 0x2D, 0xED, 0x19, 0xE7, 0x90,
+ 0x25, 0xBC, 0x4A, 0x11, 0x63, 0x00, 0xF0, 0x7D, 0x67, 0xF6, 0x6B, 0xF8, 0xD3, 0xE0, 0x0F, 0x06,
+ 0x7E, 0xCE, 0xDE, 0x12, 0xFD, 0x91, 0x3E, 0x38, 0xFC, 0x3D, 0xF8, 0x2D, 0x63, 0xF0, 0x07, 0xE1,
+ 0x07, 0xFC, 0x28, 0xC8, 0x7C, 0x2B, 0xF1, 0x6F, 0xE0, 0xD7, 0x88, 0xFE, 0x3C, 0x7C, 0x26, 0xF1,
+ 0x26, 0x85, 0x15, 0xA6, 0x8F, 0x0E, 0x9D, 0x3F, 0xFC, 0x23, 0xF6, 0x1E, 0x34, 0xF0, 0xF5, 0xC4,
+ 0x5A, 0xA5, 0x92, 0xF8, 0x66, 0x08, 0xAD, 0xAF, 0x27, 0xBF, 0xBC, 0x31, 0xDB, 0xDF, 0x6A, 0x71,
+ 0x18, 0xD9, 0xAE, 0x4C, 0xAA, 0x01, 0xE4, 0xDF, 0xB4, 0x7F, 0xEC, 0x15, 0xF1, 0x47, 0xF6, 0x9C,
+ 0xF8, 0x93, 0xF0, 0x17, 0xC6, 0x3E, 0x34, 0xFD, 0xAA, 0xFC, 0x4D, 0xE1, 0x4F, 0x0B, 0x7C, 0x34,
+ 0x1E, 0x08, 0xF1, 0x17, 0xC4, 0x3F, 0x01, 0xFC, 0x31, 0xB3, 0xF1, 0xBF, 0x81, 0x74, 0x4F, 0x14,
+ 0xF8, 0xAB, 0xC0, 0xBE, 0x27, 0x87, 0xC4, 0x56, 0x1A, 0xF7, 0x86, 0xF4, 0xCB, 0x7F, 0x1A, 0x8F,
+ 0x0F, 0x59, 0xC7, 0x73, 0xAB, 0x58, 0xE9, 0x82, 0x7B, 0x7F, 0x12, 0x68, 0xDE, 0x30, 0x78, 0xED,
+ 0x2C, 0xAD, 0xE2, 0xB4, 0xB8, 0xB3, 0xB8, 0x0D, 0x7A, 0xE0, 0x1F, 0x79, 0xFC, 0x36, 0xF0, 0xAF,
+ 0x8B, 0xFC, 0x19, 0xA0, 0x5C, 0x68, 0x1E, 0x2F, 0xF8, 0x97, 0xAC, 0xFC, 0x57, 0x92, 0xDB, 0x54,
+ 0x92, 0x5D, 0x0B, 0xC5, 0x9E, 0x29, 0xF0, 0xFE, 0x95, 0xA1, 0x78, 0xCD, 0xAC, 0x24, 0x8A, 0x36,
+ 0x5B, 0x5D, 0x61, 0xF4, 0xC8, 0x2D, 0x74, 0xEB, 0xB9, 0xA2, 0xB8, 0x37, 0x8B, 0x1C, 0xF6, 0xD6,
+ 0x16, 0x03, 0xEC, 0xC6, 0xCE, 0x29, 0x22, 0x96, 0x78, 0x66, 0xBC, 0xBC, 0x00, 0xEB, 0xED, 0xF4,
+ 0x7D, 0x22, 0xD3, 0x51, 0xBE, 0xD5, 0xED, 0x74, 0xBD, 0x3A, 0xDB, 0x56, 0xD5, 0x12, 0x18, 0xF5,
+ 0x3D, 0x52, 0xDE, 0xC6, 0x28, 0x75, 0x1D, 0x45, 0x6D, 0xD7, 0x6D, 0xBA, 0xCF, 0x38, 0x50, 0xF2,
+ 0x04, 0x52, 0x42, 0x86, 0x27, 0x68, 0x38, 0x18, 0x14, 0x00, 0x6A, 0x5A, 0x3E, 0x93, 0xAC, 0xDB,
+ 0xC7, 0x69, 0xAB, 0xE9, 0x7A, 0x76, 0xAB, 0x6B, 0x15, 0xC4, 0x77, 0x71, 0x5B, 0x6A, 0x56, 0x31,
+ 0x5F, 0x5B, 0xC5, 0x2C, 0x27, 0x31, 0x4A, 0xA8, 0xEA, 0x54, 0x3A, 0x9E, 0x55, 0x80, 0xC8, 0xED,
+ 0x8A, 0x00, 0xD1, 0xF4, 0xF6, 0xC6, 0x3D, 0xB1, 0xD3, 0x14, 0x01, 0x9F, 0xA6, 0xE9, 0x1A, 0x4E,
+ 0x8D, 0x1D, 0xCC, 0x5A, 0x3E, 0x97, 0xA7, 0x69, 0x51, 0x5E, 0xDE, 0xC9, 0xA9, 0x5E, 0x47, 0xA6,
+ 0xD9, 0x45, 0x63, 0x1D, 0xDD, 0xCC, 0xC4, 0x79, 0xD7, 0x12, 0xAA, 0x28, 0x0D, 0x23, 0xED, 0x5D,
+ 0xCE, 0x72, 0x4E, 0x06, 0x4F, 0x14, 0x00, 0xDB, 0x9D, 0x1B, 0x47, 0xBD, 0xD4, 0x34, 0xBD, 0x5A,
+ 0xF3, 0x4A, 0xD3, 0x6E, 0xF5, 0x5D, 0x0C, 0x4E, 0x34, 0x5D, 0x4E, 0xE6, 0xC6, 0x29, 0xF5, 0x0D,
+ 0x1C, 0x5C, 0xC6, 0x12, 0xE4, 0x5A, 0xCC, 0xCA, 0x5E, 0x2F, 0x31, 0x15, 0x55, 0xF6, 0x15, 0xDC,
+ 0x00, 0x07, 0x20, 0x50, 0x07, 0x9B, 0x7C, 0x61, 0xF8, 0x7B, 0xE2, 0x5F, 0x88, 0x9A, 0x3F, 0x82,
+ 0xAC, 0xFC, 0x27, 0xE2, 0xBF, 0x0E, 0x78, 0x33, 0x54, 0xF0, 0xA7, 0xC5, 0xBF, 0x0A, 0x7C, 0x41,
+ 0xB9, 0xD5, 0x7C, 0x47, 0xF0, 0xDA, 0xC3, 0xE2, 0x6C, 0x57, 0xBA, 0x66, 0x87, 0xAE, 0x5B, 0xDC,
+ 0xEB, 0x5A, 0x45, 0x95, 0xB5, 0xD4, 0xB1, 0x2D, 0x85, 0xDD, 0xFE, 0x9D, 0x15, 0xFD, 0x8C, 0x5A,
+ 0x9C, 0x45, 0xA6, 0xB1, 0x6B, 0xBF, 0xB4, 0xC6, 0x92, 0x34, 0x41, 0x18, 0x03, 0xD3, 0x35, 0x5D,
+ 0x57, 0x4A, 0xD0, 0x74, 0xAD, 0x4B, 0x5B, 0xD6, 0xF5, 0x2D, 0x3F, 0x45, 0xD1, 0x34, 0x5D, 0x3E,
+ 0x6D, 0x57, 0x57, 0xD5, 0xF5, 0x5B, 0xC8, 0xB4, 0xED, 0x2B, 0x49, 0xB4, 0xB6, 0x88, 0xC9, 0x71,
+ 0x73, 0x73, 0x71, 0x21, 0x58, 0xE2, 0x8A, 0x38, 0xD1, 0xDD, 0x9D, 0xCA, 0xAA, 0xAA, 0x92, 0x48,
+ 0x03, 0x80, 0x0F, 0x97, 0x34, 0xBF, 0xD9, 0xA7, 0xE1, 0x2F, 0xC4, 0xEF, 0x11, 0xF8, 0x7B, 0xE3,
+ 0x57, 0xC4, 0x8D, 0x6B, 0xC6, 0x5F, 0xB4, 0x4E, 0x6E, 0xEE, 0x3C, 0x7B, 0xF0, 0x8B, 0x49, 0xF8,
+ 0xD4, 0x6D, 0x2F, 0xFE, 0x1E, 0x7C, 0x2B, 0x4D, 0x64, 0xF9, 0xD6, 0x37, 0x3E, 0x1F, 0xF0, 0x64,
+ 0x56, 0x16, 0x5A, 0x5D, 0xBE, 0xA1, 0x6B, 0x63, 0x70, 0x2C, 0x6D, 0x75, 0x5B, 0xDB, 0x29, 0xF5,
+ 0x9B, 0x7B, 0x49, 0x6F, 0xAD, 0xCD, 0xF7, 0xFC, 0x4C, 0x75, 0x0F, 0xB6, 0x80, 0x6F, 0xFC, 0x4B,
+ 0xD0, 0xAD, 0xBE, 0x30, 0x6B, 0x1A, 0x1E, 0xA7, 0xF0, 0x9F, 0xC7, 0x1E, 0x17, 0x5F, 0x8A, 0xFF,
+ 0x00, 0xB2, 0xAF, 0xC6, 0x9B, 0x6D, 0x46, 0xF7, 0x4A, 0xD5, 0x92, 0x4D, 0x57, 0xC3, 0x69, 0xA8,
+ 0xDE, 0xF8, 0x45, 0x7F, 0xB5, 0x7C, 0x29, 0xE2, 0x18, 0xE0, 0x65, 0xB9, 0xB4, 0x7B, 0xCF, 0x0B,
+ 0xF8, 0xE6, 0x29, 0xED, 0xEE, 0xA2, 0x2E, 0xD6, 0x57, 0x17, 0x7A, 0x3D, 0xFB, 0xDB, 0x6A, 0x16,
+ 0xF0, 0x4D, 0xA6, 0x6A, 0x00, 0x1F, 0x49, 0xE0, 0x0E, 0x07, 0x41, 0xC0, 0xE0, 0x0E, 0x07, 0x4E,
+ 0x28, 0x03, 0xE6, 0x1B, 0x6F, 0xD9, 0x5F, 0xC0, 0x90, 0xFE, 0xD4, 0x1A, 0x87, 0xED, 0x36, 0xF2,
+ 0xB9, 0xD4, 0xA6, 0xF0, 0xC4, 0x31, 0xE9, 0xDE, 0x05, 0xB5, 0xB5, 0x36, 0x3E, 0x10, 0xB7, 0xF1,
+ 0x74, 0x96, 0x5F, 0xD9, 0x7A, 0x9F, 0xC4, 0x5B, 0xDB, 0x44, 0x93, 0xEC, 0xD7, 0xBE, 0x26, 0x97,
+ 0xC3, 0x76, 0x7A, 0x1F, 0x87, 0xE0, 0xD5, 0x25, 0xB7, 0xFB, 0x6D, 0xA6, 0x95, 0x6B, 0x77, 0xA7,
+ 0xC7, 0x72, 0x6D, 0x6F, 0xA4, 0xB7, 0x40, 0x0F, 0xA7, 0x86, 0x38, 0xF4, 0xE3, 0xA6, 0x3A, 0x7B,
+ 0x50, 0x07, 0xC0, 0x9E, 0x30, 0xF8, 0x3C, 0xDF, 0x0C, 0xFF, 0x00, 0x66, 0x6F, 0xDA, 0x3B, 0xC4,
+ 0x7E, 0x3D, 0xF8, 0xB3, 0xA3, 0xFC, 0x18, 0xD7, 0xBE, 0x30, 0x78, 0x92, 0xFB, 0xE3, 0xEF, 0xED,
+ 0x7F, 0xF1, 0xDF, 0xC3, 0x7E, 0x23, 0xD4, 0xBC, 0x27, 0x1F, 0x83, 0xF4, 0x2B, 0x6D, 0x3F, 0x4F,
+ 0xB4, 0xF1, 0x1B, 0x68, 0x5A, 0xDD, 0xBB, 0x5A, 0xDC, 0xE9, 0xF3, 0x69, 0x9E, 0x03, 0xF0, 0xA6,
+ 0x99, 0xA0, 0xD9, 0x6B, 0x30, 0x2D, 0x84, 0xF0, 0x8D, 0x32, 0xD7, 0x59, 0x68, 0xD6, 0xF1, 0x65,
+ 0x59, 0x40, 0x3E, 0xE7, 0xD0, 0xB4, 0x2D, 0x13, 0xC2, 0xFA, 0x26, 0x8F, 0xE1, 0x9F, 0x0C, 0xE8,
+ 0xDA, 0x57, 0x87, 0x7C, 0x37, 0xE1, 0xDD, 0x2A, 0xDB, 0x41, 0xF0, 0xFF, 0x00, 0x87, 0xB4, 0x2D,
+ 0x3A, 0x1D, 0x23, 0x43, 0xD0, 0x6C, 0x6C, 0xE1, 0x58, 0xAD, 0x2C, 0xAC, 0xAD, 0x22, 0x55, 0x8A,
+ 0x08, 0x22, 0x8A, 0x28, 0xE3, 0x48, 0xE3, 0x55, 0x54, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x7C,
+ 0xFB, 0xE2, 0x8B, 0x2D, 0x3F, 0xC3, 0x1F, 0xB5, 0x27, 0xC2, 0xEF, 0x1D, 0xF8, 0x8B, 0xC5, 0x1E,
+ 0x14, 0xD0, 0xF4, 0xFF, 0x00, 0x88, 0x1F, 0x0F, 0x35, 0x7F, 0x80, 0x5E, 0x04, 0xD1, 0x35, 0x2D,
+ 0x51, 0xED, 0xBC, 0x4F, 0xE3, 0x0F, 0x13, 0xB9, 0x7F, 0x12, 0xB5, 0x86, 0x9D, 0x6A, 0x62, 0xF2,
+ 0xE5, 0xD9, 0xA2, 0xF8, 0x47, 0xC4, 0x57, 0x4D, 0x89, 0x43, 0x84, 0xB2, 0x98, 0x84, 0x2A, 0xA5,
+ 0x94, 0x03, 0xE9, 0x6A, 0x00, 0x28, 0x00, 0xA0, 0x0C, 0x0F, 0x15, 0xF8, 0xA7, 0xC3, 0x7E, 0x04,
+ 0xF0, 0xAF, 0x89, 0x7C, 0x6F, 0xE3, 0x0D, 0x67, 0x4F, 0xF0, 0xDF, 0x84, 0x3C, 0x1B, 0xE1, 0xFB,
+ 0xDF, 0x15, 0x78, 0xA7, 0xC4, 0x3A, 0xB4, 0xEB, 0x69, 0xA5, 0x68, 0x1A, 0x6E, 0x9D, 0x6C, 0xF7,
+ 0x17, 0xD7, 0xB7, 0x32, 0x9E, 0x12, 0x28, 0xA0, 0x86, 0x59, 0x19, 0x8F, 0x01, 0x50, 0x9E, 0xD4,
+ 0x01, 0xE5, 0x7F, 0x08, 0xFE, 0x0E, 0x7F, 0xC2, 0x03, 0xE2, 0x8F, 0x8C, 0x5F, 0x11, 0xFC, 0x49,
+ 0x7F, 0x0F, 0x89, 0x3E, 0x25, 0xFC, 0x64, 0xF1, 0xCB, 0xEA, 0x7A, 0xDF, 0x89, 0x4B, 0xCD, 0x72,
+ 0xDA, 0x4F, 0x86, 0xF4, 0x83, 0x25, 0xAF, 0x82, 0xFC, 0x2B, 0xA7, 0xB4, 0xC4, 0xB5, 0xAE, 0x9B,
+ 0x61, 0x62, 0xF3, 0x5C, 0x1B, 0x38, 0x7C, 0xBB, 0x6F, 0xED, 0x3D, 0x5B, 0xC4, 0x77, 0xEB, 0x18,
+ 0x9F, 0x55, 0xBA, 0x96, 0x70, 0x0F, 0x73, 0xA0, 0x0F, 0x15, 0xF8, 0xC3, 0xF0, 0x81, 0xBE, 0x22,
+ 0x47, 0xA0, 0x78, 0xA7, 0xC2, 0x3E, 0x21, 0x4F, 0x87, 0x9F, 0x1A, 0x7E, 0x1D, 0x0B, 0xDB, 0xBF,
+ 0x84, 0xFF, 0x00, 0x13, 0xD3, 0x4C, 0x9B, 0x5B, 0xB5, 0xD0, 0x65, 0xBE, 0x8E, 0x35, 0xBD, 0xD2,
+ 0x75, 0xFD, 0x26, 0x2B, 0xAB, 0x43, 0xAD, 0x78, 0x72, 0xF8, 0xDA, 0x58, 0x8B, 0xFD, 0x22, 0x4B,
+ 0x9B, 0x75, 0x9C, 0xDA, 0xD8, 0xDD, 0x5B, 0xCF, 0x65, 0xA8, 0xE9, 0xDA, 0x6E, 0xA5, 0xA7, 0x00,
+ 0x71, 0x97, 0xFE, 0x34, 0xFD, 0xAF, 0x6D, 0xEE, 0xA4, 0x87, 0x4E, 0xFD, 0x9D, 0xFE, 0x04, 0xEA,
+ 0x16, 0x71, 0x84, 0x58, 0xAF, 0x26, 0xFD, 0xAA, 0x35, 0x8B, 0x07, 0x9C, 0xEC, 0x1B, 0xC8, 0x8B,
+ 0xFE, 0x10, 0x66, 0xC2, 0x86, 0xDC, 0x01, 0x24, 0x12, 0x00, 0x24, 0x29, 0x3B, 0x54, 0x02, 0x9F,
+ 0xFC, 0x27, 0x5F, 0xB6, 0x5F, 0xFD, 0x1B, 0x57, 0xC0, 0x4F, 0xFC, 0x4B, 0x4D, 0x63, 0xFF, 0x00,
+ 0x98, 0x3A, 0x00, 0x3F, 0xE1, 0x3A, 0xFD, 0xB2, 0xFF, 0x00, 0xE8, 0xDA, 0xBE, 0x02, 0x7F, 0xE2,
+ 0x5A, 0x6B, 0x1F, 0xFC, 0xC1, 0xD0, 0x01, 0xFF, 0x00, 0x09, 0xD7, 0xED, 0x97, 0xFF, 0x00, 0x46,
+ 0xD5, 0xF0, 0x13, 0xFF, 0x00, 0x12, 0xD3, 0x58, 0xFF, 0x00, 0xE6, 0x0E, 0x80, 0x0F, 0xF8, 0x4E,
+ 0xBF, 0x6C, 0xBF, 0xFA, 0x36, 0xAF, 0x80, 0x9F, 0xF8, 0x96, 0x9A, 0xC7, 0xFF, 0x00, 0x30, 0x74,
+ 0x00, 0x7F, 0xC2, 0x75, 0xFB, 0x65, 0xFF, 0x00, 0xD1, 0xB5, 0x7C, 0x04, 0xFF, 0x00, 0xC4, 0xB4,
+ 0xD6, 0x3F, 0xF9, 0x83, 0xA0, 0x03, 0xFE, 0x13, 0xAF, 0xDB, 0x2F, 0xFE, 0x8D, 0xAB, 0xE0, 0x27,
+ 0xFE, 0x25, 0xA6, 0xB1, 0xFF, 0x00, 0xCC, 0x1D, 0x00, 0x1F, 0xF0, 0x9D, 0x7E, 0xD9, 0x7F, 0xF4,
+ 0x6D, 0x5F, 0x01, 0x3F, 0xF1, 0x2D, 0x35, 0x8F, 0xFE, 0x60, 0xE8, 0x00, 0xFF, 0x00, 0x84, 0xEB,
+ 0xF6, 0xCB, 0xFF, 0x00, 0xA3, 0x6A, 0xF8, 0x09, 0xFF, 0x00, 0x89, 0x69, 0xAC, 0x7F, 0xF3, 0x07,
+ 0x40, 0x07, 0xFC, 0x27, 0x5F, 0xB6, 0x5F, 0xFD, 0x1B, 0x57, 0xC0, 0x4F, 0xFC, 0x4B, 0x4D, 0x63,
+ 0xFF, 0x00, 0x98, 0x3A, 0x00, 0x3F, 0xE1, 0x3A, 0xFD, 0xB2, 0xFF, 0x00, 0xE8, 0xDA, 0xBE, 0x02,
+ 0x7F, 0xE2, 0x5A, 0x6B, 0x1F, 0xFC, 0xC1, 0xD0, 0x01, 0xFF, 0x00, 0x09, 0xD7, 0xED, 0x97, 0xFF,
+ 0x00, 0x46, 0xD5, 0xF0, 0x13, 0xFF, 0x00, 0x12, 0xD3, 0x58, 0xFF, 0x00, 0xE6, 0x0E, 0x80, 0x0F,
+ 0xF8, 0x4E, 0xBF, 0x6C, 0xBF, 0xFA, 0x36, 0xAF, 0x80, 0x9F, 0xF8, 0x96, 0x9A, 0xC7, 0xFF, 0x00,
+ 0x30, 0x74, 0x00, 0x7F, 0xC2, 0x75, 0xFB, 0x65, 0xFF, 0x00, 0xD1, 0xB5, 0x7C, 0x04, 0xFF, 0x00,
+ 0xC4, 0xB4, 0xD6, 0x3F, 0xF9, 0x83, 0xA0, 0x0F, 0xA3, 0x3C, 0x31, 0x75, 0xE2, 0x2B, 0xDF, 0x0F,
+ 0x68, 0xF7, 0x7E, 0x2E, 0xD1, 0x74, 0x9F, 0x0E, 0xF8, 0x9A, 0xE2, 0xC2, 0x39, 0x75, 0xCD, 0x0B,
+ 0x42, 0xD7, 0xA4, 0xF1, 0x4E, 0x8F, 0xA5, 0x5C, 0x95, 0xFD, 0xE4, 0x16, 0xDA, 0x8C, 0x96, 0xB6,
+ 0xAF, 0x71, 0x1A, 0x9E, 0x04, 0x8D, 0x6D, 0x09, 0x3F, 0xDC, 0x5E, 0x94, 0x01, 0xBB, 0x40, 0x05,
+ 0x00, 0x14, 0x01, 0x62, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00,
+ 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57,
+ 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9,
+ 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33,
+ 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27,
+ 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F,
+ 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99,
+ 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x08, 0x7E, 0xE9, 0xFF, 0x00, 0x77, 0xFA, 0x50, 0x04, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x15,
+ 0x6F, 0xAF, 0xAC, 0x74, 0xAB, 0x1B, 0xCD, 0x4F, 0x53, 0xBC, 0xB4, 0xD3, 0x74, 0xCD, 0x36, 0xD2,
+ 0x4B, 0xFD, 0x43, 0x50, 0xBE, 0xB8, 0x4B, 0x3B, 0x0B, 0x0B, 0x78, 0x50, 0xBC, 0xD3, 0x4D, 0x33,
+ 0x90, 0x91, 0xC6, 0x88, 0x8C, 0xCC, 0xCC, 0x40, 0x00, 0x12, 0x48, 0x02, 0x80, 0x3E, 0x52, 0xD2,
+ 0xB4, 0xEB, 0xFF, 0x00, 0xDA, 0x92, 0xF7, 0x4C, 0xF1, 0x67, 0x89, 0xAC, 0x6F, 0x74, 0xAF, 0xD9,
+ 0xBB, 0x4E, 0xB8, 0x83, 0x58, 0xF0, 0x17, 0x81, 0xF5, 0x3B, 0x49, 0xF4, 0xCD, 0x47, 0xE3, 0x9C,
+ 0x82, 0x24, 0x92, 0xD3, 0xC4, 0x3E, 0x21, 0xB6, 0x32, 0x2B, 0x26, 0x86, 0x3C, 0xD7, 0x36, 0xBA,
+ 0x4D, 0xD4, 0x01, 0xA7, 0x78, 0xE2, 0xBB, 0xB9, 0x50, 0xA2, 0x08, 0x10, 0x03, 0xEB, 0x7A, 0x00,
+ 0xF8, 0xA7, 0xF6, 0x56, 0xFF, 0x00, 0x92, 0xE7, 0xFF, 0x00, 0x05, 0x2A, 0xFF, 0x00, 0xB3, 0xD7,
+ 0xD0, 0x7F, 0xF5, 0x9C, 0x3E, 0x14, 0xD0, 0x07, 0xDA, 0xD4, 0x00, 0x50, 0x01, 0x40, 0x1F, 0x1E,
+ 0x7E, 0xD8, 0xF1, 0x5C, 0x1D, 0x23, 0xF6, 0x76, 0xB9, 0xD5, 0xE3, 0xD2, 0x24, 0xF8, 0x4D, 0xA6,
+ 0x7E, 0xD7, 0x3F, 0x0F, 0xB5, 0x3F, 0x8C, 0xC9, 0x7B, 0x0B, 0xCD, 0xAB, 0x47, 0x69, 0x0E, 0xA6,
+ 0xDF, 0xF0, 0x83, 0xCF, 0xA5, 0xAF, 0xFA, 0x91, 0x2C, 0x3F, 0x10, 0x0F, 0xC3, 0x49, 0xEE, 0x1E,
+ 0x70, 0x12, 0x3B, 0x08, 0x35, 0x49, 0x14, 0xAC, 0xD1, 0xC2, 0x40, 0x07, 0xD8, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x1F, 0x80, 0xA0, 0x0F, 0x82, 0xBF, 0x6C,
+ 0x0F, 0xF9, 0x38, 0x4F, 0xF8, 0x25, 0x4F, 0xFD, 0x9F, 0xB7, 0x88, 0xBF, 0xF5, 0x97, 0x3E, 0x30,
+ 0xD0, 0x07, 0xDE, 0xB4, 0x00, 0x50, 0x01, 0x40, 0x1F, 0x24, 0x7E, 0xDF, 0xBF, 0xF2, 0x61, 0xDF,
+ 0xB6, 0xC7, 0xFD, 0x9A, 0x2F, 0xC4, 0x9F, 0xFD, 0x43, 0x35, 0x1A, 0x00, 0xFA, 0xE0, 0xF5, 0x34,
+ 0x00, 0x94, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x58, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F,
+ 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7, 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC,
+ 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76, 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00,
+ 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5, 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A,
+ 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F,
+ 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1, 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E,
+ 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F,
+ 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x02, 0x1F, 0xBA, 0x7F, 0xDD, 0xFE, 0x94, 0x01, 0xE2, 0xBF, 0x1A,
+ 0x7E, 0x05, 0x78, 0x27, 0xE3, 0xE7, 0x87, 0xB4, 0xAF, 0x0C, 0x78, 0xE7, 0x5B, 0xF8, 0xC9, 0xA0,
+ 0xE9, 0xBA, 0x36, 0xB2, 0xBA, 0xED, 0x9D, 0xC7, 0xC1, 0x4F, 0xDA, 0x2F, 0xE2, 0x17, 0xEC, 0xD5,
+ 0xE2, 0x09, 0x67, 0x5B, 0x79, 0x21, 0x11, 0xDD, 0x6A, 0xDE, 0x10, 0xD6, 0xB4, 0xAB, 0xEB, 0xAB,
+ 0x6D, 0x97, 0x0E, 0x7E, 0xCD, 0x3C, 0xD2, 0x40, 0x5C, 0x47, 0x21, 0x8F, 0x7C, 0x48, 0xC8, 0x01,
+ 0xF3, 0x57, 0xFC, 0x3B, 0x6F, 0xF6, 0x78, 0xFF, 0x00, 0xA2, 0x89, 0xFB, 0x7C, 0xFF, 0x00, 0xE2,
+ 0xD6, 0xFF, 0x00, 0x6A, 0x4F, 0xFE, 0x78, 0x54, 0x00, 0x7F, 0xC3, 0xB6, 0xFF, 0x00, 0x67, 0x8F,
+ 0xFA, 0x28, 0x9F, 0xB7, 0xCF, 0xFE, 0x2D, 0x6F, 0xF6, 0xA4, 0xFF, 0x00, 0xE7, 0x85, 0x40, 0x07,
+ 0xFC, 0x3B, 0x6F, 0xF6, 0x78, 0xFF, 0x00, 0xA2, 0x89, 0xFB, 0x7C, 0xFF, 0x00, 0xE2, 0xD6, 0xFF,
+ 0x00, 0x6A, 0x4F, 0xFE, 0x78, 0x54, 0x00, 0x7F, 0xC3, 0xB6, 0xFF, 0x00, 0x67, 0x8F, 0xFA, 0x28,
+ 0x9F, 0xB7, 0xCF, 0xFE, 0x2D, 0x6F, 0xF6, 0xA4, 0xFF, 0x00, 0xE7, 0x85, 0x40, 0x07, 0xFC, 0x3B,
+ 0x6F, 0xF6, 0x78, 0xFF, 0x00, 0xA2, 0x89, 0xFB, 0x7C, 0xFF, 0x00, 0xE2, 0xD6, 0xFF, 0x00, 0x6A,
+ 0x4F, 0xFE, 0x78, 0x54, 0x00, 0x7F, 0xC3, 0xB6, 0xFF, 0x00, 0x67, 0x8F, 0xFA, 0x28, 0x9F, 0xB7,
+ 0xCF, 0xFE, 0x2D, 0x6F, 0xF6, 0xA4, 0xFF, 0x00, 0xE7, 0x85, 0x40, 0x07, 0xFC, 0x3B, 0x6F, 0xF6,
+ 0x78, 0xFF, 0x00, 0xA2, 0x89, 0xFB, 0x7C, 0xFF, 0x00, 0xE2, 0xD6, 0xFF, 0x00, 0x6A, 0x4F, 0xFE,
+ 0x78, 0x54, 0x00, 0x7F, 0xC3, 0xB6, 0xFF, 0x00, 0x67, 0x8F, 0xFA, 0x28, 0x9F, 0xB7, 0xCF, 0xFE,
+ 0x2D, 0x6F, 0xF6, 0xA4, 0xFF, 0x00, 0xE7, 0x85, 0x40, 0x07, 0xFC, 0x3B, 0x6F, 0xF6, 0x78, 0xFF,
+ 0x00, 0xA2, 0x89, 0xFB, 0x7C, 0xFF, 0x00, 0xE2, 0xD6, 0xFF, 0x00, 0x6A, 0x4F, 0xFE, 0x78, 0x54,
+ 0x00, 0x7F, 0xC3, 0xB6, 0xFF, 0x00, 0x67, 0x8F, 0xFA, 0x28, 0x9F, 0xB7, 0xCF, 0xFE, 0x2D, 0x6F,
+ 0xF6, 0xA4, 0xFF, 0x00, 0xE7, 0x85, 0x40, 0x1B, 0x5E, 0x1C, 0xFF, 0x00, 0x82, 0x79, 0xFE, 0xCE,
+ 0x3E, 0x1D, 0xD7, 0x74, 0x8D, 0x76, 0x7D, 0x57, 0xF6, 0xA8, 0xF1, 0xE2, 0x68, 0xD7, 0xB1, 0xEA,
+ 0x30, 0xF8, 0x53, 0xE3, 0x47, 0xED, 0xF7, 0xF1, 0xEB, 0xE3, 0xE7, 0xC3, 0x2D, 0x4A, 0x68, 0x4E,
+ 0xEB, 0x76, 0xD5, 0x3C, 0x21, 0xE2, 0x5F, 0x18, 0xEA, 0x1A, 0x1E, 0xA0, 0x22, 0x90, 0x47, 0x34,
+ 0x6B, 0x77, 0x67, 0x3A, 0xC7, 0x34, 0x50, 0x4C, 0x81, 0x64, 0x86, 0x37, 0x40, 0x0F, 0xB7, 0xA8,
+ 0x03, 0x9A, 0xF1, 0x9F, 0x8C, 0xBC, 0x25, 0xF0, 0xE7, 0xC1, 0xDE, 0x2B, 0xF8, 0x83, 0xE3, 0xDF,
+ 0x11, 0xE8, 0x9E, 0x0D, 0xF0, 0x27, 0x80, 0xFC, 0x33, 0x7F, 0xE3, 0x2F, 0x1A, 0x78, 0xBB, 0xC4,
+ 0x9A, 0x8C, 0x5A, 0x3F, 0x87, 0x3C, 0x29, 0xA4, 0x69, 0x56, 0x8F, 0x73, 0xA9, 0x6A, 0x57, 0xF7,
+ 0x72, 0x15, 0x8E, 0x0B, 0x68, 0x2D, 0xED, 0xE6, 0x96, 0x49, 0x1C, 0x85, 0x44, 0x46, 0x62, 0x40,
+ 0x1C, 0x00, 0x70, 0x3F, 0x05, 0x74, 0x3F, 0x0D, 0x1D, 0x03, 0x56, 0xF8, 0xAD, 0xA4, 0xFC, 0x3D,
+ 0xD7, 0xFE, 0x19, 0xF8, 0x9F, 0xF6, 0x89, 0xBC, 0xD2, 0x7E, 0x34, 0x7C, 0x4C, 0xF0, 0xC7, 0x8B,
+ 0x24, 0xB8, 0x4F, 0x16, 0x5A, 0xEB, 0x72, 0xF8, 0x4F, 0x47, 0xD2, 0x20, 0x8B, 0x55, 0xB3, 0x79,
+ 0x5E, 0x2B, 0x3B, 0xCB, 0x7D, 0x27, 0xC3, 0x7A, 0x0D, 0x94, 0xD6, 0xF0, 0x04, 0x8D, 0x5E, 0xC9,
+ 0xC9, 0x0D, 0x23, 0xC9, 0x24, 0xA0, 0x1E, 0xA1, 0xAD, 0x6B, 0x5A, 0x37, 0x86, 0xB4, 0x6D, 0x5B,
+ 0xC4, 0x5E, 0x22, 0xD5, 0xB4, 0xBD, 0x03, 0xC3, 0xDA, 0x06, 0x97, 0x3E, 0xB5, 0xAE, 0xEB, 0xBA,
+ 0xD5, 0xF4, 0x3A, 0x56, 0x8B, 0xA2, 0x59, 0x5A, 0x42, 0xD2, 0xDD, 0x5D, 0xDD, 0xDD, 0x4A, 0xCB,
+ 0x14, 0x30, 0x45, 0x14, 0x6E, 0xEF, 0x23, 0xB2, 0xAA, 0x2A, 0xB3, 0x12, 0x00, 0x24, 0x00, 0x7C,
+ 0xC1, 0x1F, 0xC5, 0x8F, 0x8E, 0xDE, 0x25, 0xD0, 0xF5, 0x0F, 0x8A, 0xDF, 0x0F, 0xFE, 0x18, 0xE9,
+ 0x9A, 0x9F, 0xC3, 0x0B, 0x1D, 0x52, 0xD2, 0xEB, 0xC3, 0x5F, 0x0F, 0xF5, 0x88, 0x26, 0xD2, 0x3E,
+ 0x36, 0xFC, 0x57, 0xF0, 0xFD, 0xBC, 0x1A, 0x8A, 0x6A, 0xBA, 0xA6, 0x92, 0x67, 0xB9, 0x83, 0x4F,
+ 0xD3, 0xEE, 0x2E, 0xA4, 0x93, 0xC3, 0xF7, 0x3A, 0x5D, 0xAD, 0xF0, 0x5F, 0x36, 0xDE, 0xDA, 0xE6,
+ 0x3B, 0xB9, 0x2C, 0x64, 0xD4, 0x91, 0xB4, 0x80, 0x0F, 0xA1, 0x7C, 0x09, 0xE3, 0xBF, 0x08, 0x7C,
+ 0x4C, 0xF0, 0x9E, 0x91, 0xE3, 0x7F, 0x02, 0x6B, 0xB6, 0x7E, 0x23, 0xF0, 0xBE, 0xB7, 0x1C, 0xBF,
+ 0x60, 0xD4, 0xEC, 0x83, 0xC5, 0xB6, 0x4B, 0x69, 0xDE, 0x0B, 0xCB, 0x4B, 0x88, 0x24, 0x54, 0x9A,
+ 0xDE, 0xEA, 0xDE, 0xE6, 0xDE, 0xE2, 0xDE, 0x7B, 0x69, 0x92, 0x39, 0xAD, 0xE7, 0x86, 0x68, 0x65,
+ 0x8E, 0x39, 0x22, 0x74, 0x50, 0x0E, 0x2B, 0xE3, 0xD7, 0x88, 0x3E, 0x19, 0xE8, 0x5F, 0x0C, 0x75,
+ 0x2D, 0x3F, 0xE3, 0x17, 0x85, 0x6C, 0x7C, 0x71, 0xF0, 0xDB, 0xE2, 0x47, 0x88, 0xFC, 0x39, 0xF0,
+ 0x1B, 0xC4, 0xDE, 0x0C, 0xD5, 0xBC, 0x39, 0x67, 0xE2, 0xDF, 0x0F, 0xF8, 0xAA, 0x3F, 0x88, 0xFE,
+ 0x23, 0xB0, 0xF0, 0xAD, 0xB6, 0x9D, 0xAA, 0xE9, 0x97, 0x5F, 0xE8, 0xD7, 0x3A, 0x74, 0xD7, 0x1E,
+ 0x25, 0xB6, 0x8E, 0xEA, 0x39, 0x55, 0xD4, 0xDB, 0x35, 0xC6, 0x63, 0x90, 0x7E, 0xED, 0xC0, 0x3D,
+ 0x88, 0x70, 0x00, 0xF4, 0x00, 0x7E, 0x43, 0xFF, 0x00, 0xAC, 0x28, 0x03, 0xE7, 0x3F, 0x89, 0x3F,
+ 0xF0, 0xAF, 0x7C, 0x53, 0xF1, 0xEB, 0xF6, 0x6F, 0xF0, 0x4E, 0xBD, 0xE0, 0xBB, 0xCF, 0x15, 0xF8,
+ 0xEB, 0xC0, 0x7A, 0x97, 0x89, 0x3F, 0x68, 0x9F, 0x03, 0xF8, 0x82, 0x2D, 0x5A, 0x7D, 0x2F, 0x49,
+ 0xF8, 0x52, 0xFA, 0x77, 0x86, 0xEE, 0xFC, 0x2B, 0x73, 0xAA, 0xDC, 0xA4, 0x52, 0x28, 0xB9, 0xB9,
+ 0xBB, 0xB4, 0xF8, 0x8F, 0xA8, 0x69, 0xF6, 0xF6, 0x93, 0xC6, 0xF1, 0x3C, 0x77, 0x1A, 0x9D, 0xD0,
+ 0xDB, 0x2E, 0x9B, 0x19, 0xA0, 0x0F, 0xA3, 0x28, 0x03, 0xC5, 0x3E, 0x30, 0xFC, 0x5E, 0x7F, 0x87,
+ 0x29, 0xE1, 0xBF, 0x0A, 0xF8, 0x47, 0xC3, 0x32, 0x7C, 0x45, 0xF8, 0xC9, 0xF1, 0x16, 0x6B, 0x9B,
+ 0x0F, 0x86, 0x1F, 0x0C, 0xAD, 0x75, 0x17, 0xD1, 0x60, 0xD5, 0x8D, 0x92, 0xC4, 0x75, 0x2D, 0x67,
+ 0x5D, 0xD5, 0x56, 0xDE, 0xE1, 0x74, 0x6F, 0x0F, 0xE9, 0xE9, 0x77, 0x68, 0xF7, 0xDA, 0x9C, 0xB0,
+ 0x4A, 0x23, 0x37, 0x16, 0x56, 0x76, 0xD0, 0x5E, 0xEA, 0x3A, 0x96, 0x9B, 0xA6, 0xEA, 0x20, 0x1C,
+ 0x9F, 0x80, 0xFE, 0x27, 0x7C, 0x41, 0xF0, 0x97, 0x8B, 0xB4, 0x7F, 0x83, 0xFF, 0x00, 0xB4, 0x6C,
+ 0x9E, 0x0C, 0x7F, 0x1A, 0x78, 0x96, 0xD5, 0xA7, 0xF8, 0x69, 0xF1, 0x63, 0xE1, 0xEF, 0x86, 0x75,
+ 0x3F, 0x06, 0x7C, 0x2C, 0xF8, 0xC7, 0x25, 0xBD, 0xA9, 0x9F, 0x54, 0xD2, 0xA2, 0xD2, 0xAF, 0x2F,
+ 0x35, 0x07, 0xD0, 0x75, 0xCB, 0x44, 0x49, 0x9D, 0x74, 0xBB, 0x8D, 0x56, 0xFD, 0xAF, 0xEC, 0xA0,
+ 0x93, 0x51, 0xB3, 0x9E, 0x51, 0x6B, 0xAA, 0xD9, 0xE8, 0x40, 0x1D, 0x5F, 0xED, 0x2B, 0x7F, 0xF0,
+ 0xD3, 0x4A, 0xFD, 0x9C, 0x7E, 0x3F, 0xEA, 0x7F, 0x19, 0xF4, 0x6D, 0x43, 0xC4, 0x3F, 0x07, 0x74,
+ 0xDF, 0x82, 0x5E, 0x2B, 0xBF, 0xF8, 0xB1, 0xE1, 0xED, 0x21, 0xE5, 0x8B, 0x55, 0xD7, 0x7C, 0x33,
+ 0x06, 0x83, 0x74, 0xFA, 0xF5, 0x95, 0xAB, 0x45, 0x34, 0x12, 0x89, 0x65, 0xB1, 0x4B, 0xA8, 0xD0,
+ 0xA4, 0xF0, 0xB0, 0x66, 0x5D, 0xB2, 0x21, 0xC3, 0x28, 0x07, 0xB6, 0x63, 0x1C, 0x71, 0xC7, 0x1C,
+ 0x63, 0x1C, 0x7A, 0x7E, 0x54, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0x62, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00, 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00,
+ 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57, 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8,
+ 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9, 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B,
+ 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33, 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE,
+ 0x08, 0x85, 0xFF, 0x00, 0x22, 0x27, 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F,
+ 0x86, 0x55, 0xF9, 0xD7, 0x10, 0x7F, 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19,
+ 0x5F, 0xFB, 0x94, 0x7E, 0x7F, 0x99, 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x08, 0x7E, 0xE9, 0xFF, 0x00, 0x77, 0xFA,
+ 0x50, 0x04, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0xF3, 0x07, 0xED, 0x2F, 0xE0, 0x7F, 0x12,
+ 0x7C, 0x5D, 0xB3, 0xF8, 0x7B, 0xF0, 0x61, 0x7C, 0x3F, 0xA4, 0x5E, 0x7C, 0x20, 0xF1, 0xCF, 0x8B,
+ 0xA3, 0xD4, 0x7F, 0x68, 0xBD, 0x5F, 0xC4, 0x9A, 0xBD, 0xB5, 0xBF, 0x87, 0xEF, 0xBC, 0x1D, 0xA2,
+ 0xEC, 0xB9, 0xB8, 0xF0, 0x73, 0x69, 0x44, 0xBC, 0xBA, 0xB1, 0xD7, 0xAF, 0x06, 0x9B, 0xA7, 0xDD,
+ 0x58, 0xCD, 0x0A, 0xE9, 0xF2, 0xE8, 0xCD, 0xE2, 0x65, 0xBA, 0x9F, 0x79, 0xB4, 0xB0, 0xD5, 0x80,
+ 0x3E, 0x92, 0x5D, 0x43, 0x4E, 0xF9, 0x55, 0x6F, 0xAC, 0xCF, 0x45, 0x50, 0x2E, 0x90, 0x93, 0xE8,
+ 0x3A, 0xFD, 0x28, 0x03, 0xC0, 0xB5, 0x8F, 0x87, 0xBE, 0x2D, 0xF8, 0xB3, 0xF1, 0x06, 0x49, 0xBE,
+ 0x26, 0x5A, 0xC5, 0xA3, 0xFC, 0x1B, 0xF8, 0x7F, 0xAE, 0x5B, 0xDE, 0xF8, 0x1F, 0xE1, 0xED, 0xA6,
+ 0xAB, 0xF6, 0x99, 0xBE, 0x27, 0xEA, 0xB6, 0x6D, 0x6B, 0x73, 0x69, 0xE2, 0x6F, 0x12, 0x3C, 0x0E,
+ 0xAA, 0xB6, 0x96, 0x97, 0x31, 0x4E, 0x96, 0x7A, 0x4B, 0x19, 0x63, 0x77, 0x44, 0xBE, 0xB9, 0xDD,
+ 0x2A, 0xDA, 0xC1, 0xA7, 0x80, 0x7D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0x01, 0xF8, 0x0A, 0x00, 0xF9, 0xD3, 0xC5, 0x3F, 0x0F, 0x3C, 0x5D, 0xE0, 0x9F, 0x1E,
+ 0xCD, 0xF1, 0x6F, 0xE0, 0xC5, 0xAC, 0x17, 0xF3, 0xF8, 0xAF, 0x51, 0xB5, 0x4F, 0x8D, 0x5F, 0x0A,
+ 0xAF, 0x75, 0x6F, 0xEC, 0xBD, 0x1B, 0xE2, 0x44, 0x29, 0x1D, 0xA5, 0xA4, 0x5E, 0x21, 0xD3, 0x26,
+ 0x94, 0x98, 0x2C, 0x7C, 0x41, 0x61, 0x63, 0x66, 0x12, 0x32, 0x04, 0x30, 0x6A, 0x50, 0xA4, 0x76,
+ 0x77, 0x8E, 0x86, 0x2B, 0x1B, 0xDD, 0x2C, 0x03, 0xE7, 0x1F, 0xDA, 0x0B, 0xC7, 0xFF, 0x00, 0x11,
+ 0xBE, 0x3D, 0x78, 0x4F, 0xE1, 0x47, 0x82, 0x7E, 0x16, 0x7E, 0xCB, 0x7F, 0xB4, 0x5E, 0xB3, 0xA7,
+ 0x6A, 0x1F, 0xB5, 0x07, 0xC2, 0x8F, 0x16, 0xF8, 0xB3, 0xC7, 0x5E, 0x25, 0xD2, 0x7C, 0x29, 0xF0,
+ 0xA3, 0xC3, 0x9F, 0x0C, 0x34, 0xCF, 0x03, 0x7C, 0x54, 0xF0, 0xA7, 0x88, 0xF5, 0x8B, 0xED, 0x5F,
+ 0x4D, 0xF1, 0x0E, 0xBD, 0xA7, 0x6B, 0xB7, 0x30, 0xB6, 0x9B, 0xA6, 0xDF, 0x98, 0x4E, 0x95, 0xA6,
+ 0xEA, 0x45, 0xE4, 0xB7, 0x92, 0x2C, 0x2B, 0x80, 0xA4, 0x03, 0xF4, 0x66, 0x80, 0x3E, 0x70, 0xF8,
+ 0x43, 0xF0, 0xDF, 0xC4, 0xD0, 0xFC, 0x4D, 0xF8, 0xD5, 0xF1, 0xB7, 0xE2, 0x54, 0x17, 0x49, 0xE3,
+ 0x0F, 0x1A, 0x78, 0x94, 0xF8, 0x07, 0xE1, 0xC6, 0x91, 0x77, 0xAA, 0xAD, 0xFD, 0xAF, 0xC3, 0xEF,
+ 0x87, 0xDE, 0x1C, 0x73, 0x0E, 0x91, 0x63, 0x65, 0x04, 0x13, 0x3D, 0x92, 0x3E, 0xA7, 0xA8, 0xB6,
+ 0xB5, 0xAE, 0xCF, 0x70, 0xB1, 0xAD, 0xEC, 0xA9, 0xAA, 0xE9, 0x96, 0x37, 0x92, 0x32, 0x68, 0x96,
+ 0x56, 0xF6, 0x00, 0x1E, 0xAD, 0xF1, 0x23, 0x5E, 0xF1, 0x8F, 0x86, 0xBC, 0x19, 0xAB, 0x6A, 0x7F,
+ 0x0F, 0x3C, 0x0E, 0x3E, 0x22, 0xF8, 0xDF, 0x36, 0xDA, 0x77, 0x86, 0x3C, 0x25, 0x2F, 0x88, 0xAD,
+ 0x3C, 0x21, 0xA5, 0xDD, 0xDD, 0xDE, 0x5D, 0x47, 0x6F, 0x1D, 0xD6, 0xA7, 0xA9, 0xCF, 0xBB, 0xEC,
+ 0xDA, 0x6D, 0xA8, 0x9D, 0xAE, 0xEF, 0x24, 0x82, 0x1B, 0xCB, 0xA5, 0xB4, 0xB6, 0xBA, 0x36, 0x96,
+ 0x57, 0xD7, 0x22, 0x0B, 0x2B, 0x90, 0x0E, 0x2F, 0xE0, 0xEF, 0xC1, 0xA8, 0xFE, 0x1C, 0x37, 0x88,
+ 0x7C, 0x61, 0xE2, 0xBD, 0x76, 0x3F, 0x88, 0x9F, 0x1B, 0xBE, 0x22, 0x45, 0x69, 0xFF, 0x00, 0x0B,
+ 0x4F, 0xE2, 0xCD, 0xC6, 0x89, 0x1E, 0x85, 0x73, 0xAF, 0xC5, 0x61, 0x2D, 0xD4, 0xBA, 0x47, 0x87,
+ 0xF4, 0x8B, 0x11, 0x24, 0xC7, 0x4C, 0xF0, 0xDE, 0x96, 0x75, 0x5D, 0x4E, 0x3D, 0x37, 0x4B, 0x13,
+ 0xDC, 0x18, 0x05, 0xDD, 0xED, 0xCD, 0xC5, 0xC5, 0xF6, 0xA3, 0xA8, 0xEA, 0x5A, 0x96, 0xA2, 0x01,
+ 0xDE, 0x78, 0xF7, 0xC0, 0x1E, 0x10, 0xF8, 0x9F, 0xE1, 0x3D, 0x4B, 0xC1, 0x3E, 0x39, 0xD1, 0x62,
+ 0xD7, 0x3C, 0x39, 0xAA, 0x49, 0x6B, 0x77, 0x25, 0xB7, 0xDA, 0xAE, 0x34, 0xCB, 0xED, 0x3E, 0xF3,
+ 0x4F, 0xBB, 0x8A, 0xEF, 0x4B, 0xD4, 0xF4, 0xEB, 0xEB, 0x77, 0x8E, 0xEA, 0xC7, 0x50, 0xB3, 0xBD,
+ 0xB4, 0xB2, 0xBB, 0xB4, 0xBD, 0xB5, 0x96, 0x1B, 0x9B, 0x4B, 0x9B, 0x6B, 0x6B, 0x98, 0x25, 0x8A,
+ 0x68, 0x23, 0x91, 0x00, 0x3F, 0x3D, 0xFF, 0x00, 0x69, 0xFB, 0x6F, 0xDA, 0xAA, 0x3F, 0xD9, 0x2B,
+ 0xF6, 0x91, 0xFD, 0x9C, 0x2D, 0x7E, 0x05, 0xFC, 0x4E, 0xFD, 0xAA, 0xFC, 0x61, 0xE3, 0x7F, 0x83,
+ 0xDA, 0xFF, 0x00, 0xC1, 0xFF, 0x00, 0x86, 0x3F, 0x15, 0xBE, 0x1B, 0xEB, 0xDF, 0x0D, 0x7C, 0x14,
+ 0xFE, 0x2A, 0xB2, 0xF1, 0x47, 0x85, 0xF5, 0x5B, 0x1D, 0x3B, 0x51, 0xF1, 0x8D, 0xA7, 0x88, 0x3C,
+ 0x4D, 0xA2, 0xC7, 0x6D, 0xAA, 0xD8, 0x4F, 0x05, 0xB4, 0x7A, 0xA4, 0x9A, 0x7C, 0x0D, 0x6B, 0x75,
+ 0xF6, 0xEB, 0x0B, 0xDB, 0x0B, 0x68, 0x85, 0xC5, 0xE6, 0x97, 0xA0, 0x80, 0x7E, 0x9D, 0x71, 0xDB,
+ 0xA7, 0x6E, 0x31, 0xC7, 0x6E, 0x3F, 0x2A, 0x00, 0x4A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x2C, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F, 0xE7, 0xE7, 0xFF, 0x00, 0x07, 0x3E, 0xFF, 0x00, 0xCA,
+ 0x73, 0xFF, 0x00, 0xE0, 0x90, 0xFF, 0x00, 0xF6, 0x0A, 0xF8, 0x7B, 0xFF, 0x00, 0xAB, 0x7A, 0xE6,
+ 0xBB, 0x32, 0xCF, 0xF9, 0x18, 0x61, 0xFF, 0x00, 0xC7, 0x0F, 0xFD, 0x29, 0x1C, 0xF8, 0x9F, 0xF7,
+ 0x5A, 0x9F, 0xE1, 0x7F, 0x91, 0xF6, 0xA5, 0x7E, 0xA6, 0x7C, 0x70, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x7E, 0xC1, 0x7F, 0xC1, 0x10, 0xBF, 0xE4, 0x44, 0xFD, 0xBA, 0xFF, 0x00, 0xEC, 0xF9, 0xE0, 0xFF,
+ 0x00, 0xD5, 0x0D, 0xF0, 0xCA, 0xBF, 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2, 0x3F, 0xFA, 0x4A,
+ 0x3E, 0xA3, 0x2B, 0xFF, 0x00, 0x72, 0x8F, 0xCF, 0xF3, 0x3F, 0x6D, 0xAB, 0xC5, 0x3D, 0x10, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x01, 0x0F, 0xDD, 0x3F,
+ 0xEE, 0xFF, 0x00, 0x4A, 0x00, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3C, 0xDF, 0xE2, 0x2F,
+ 0xC1, 0xAF, 0x84, 0x1F, 0x18, 0x2D, 0xB4, 0xAB, 0x3F, 0x8B, 0x7F, 0x0A, 0x7E, 0x1A, 0xFC, 0x52,
+ 0xB4, 0xD0, 0xA6, 0x96, 0xE3, 0x44, 0xB5, 0xF8, 0x8D, 0xE0, 0x5D, 0x2F, 0xC6, 0xF6, 0xDA, 0x34,
+ 0x93, 0xAA, 0xAC, 0xD2, 0x5A, 0x47, 0x7B, 0x04, 0xAB, 0x0B, 0x3A, 0xC5, 0x18, 0x62, 0x81, 0x49,
+ 0x08, 0xA0, 0xF4, 0x18, 0x00, 0xF3, 0x2B, 0x4F, 0xD8, 0xBF, 0xF6, 0x3B, 0xB0, 0xBA, 0xB5, 0xBE,
+ 0xB0, 0xFD, 0x93, 0xBF, 0x66, 0x7B, 0x2B, 0xDB, 0x29, 0xE3, 0xBA, 0xB3, 0xBB, 0xB4, 0xF8, 0x0F,
+ 0xE1, 0x5B, 0x6B, 0xAB, 0x49, 0x62, 0x60, 0xD1, 0xCB, 0x14, 0x8B, 0x62, 0x19, 0x19, 0x59, 0x54,
+ 0x86, 0x04, 0x10, 0x40, 0x23, 0xA5, 0x00, 0x7D, 0x2B, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07,
+ 0xC9, 0x1F, 0x16, 0xFC, 0x47, 0x77, 0xE3, 0x8F, 0xDA, 0x1F, 0xE0, 0x5F, 0xEC, 0xFF, 0x00, 0xE1,
+ 0x8F, 0x15, 0xF8, 0x87, 0x4D, 0x8F, 0xC3, 0xAB, 0x2F, 0xED, 0x23, 0xF1, 0xCB, 0x4F, 0xF0, 0x46,
+ 0xB7, 0x2E, 0x8B, 0x7B, 0x6F, 0xE1, 0xED, 0x1E, 0x47, 0xB5, 0xF0, 0x5E, 0x93, 0xAF, 0xEA, 0x16,
+ 0x8C, 0x2F, 0x2C, 0x2D, 0x75, 0x6F, 0x12, 0x7F, 0xA4, 0xC1, 0x6D, 0xBE, 0xD9, 0x35, 0x9B, 0x7F,
+ 0x08, 0xF8, 0x96, 0xCA, 0x46, 0xBA, 0xB1, 0xB7, 0xD5, 0x6C, 0x6E, 0x80, 0x3D, 0xC7, 0xE2, 0x7F,
+ 0xC4, 0xFF, 0x00, 0x0D, 0xFC, 0x28, 0xF0, 0xE5, 0xBE, 0xB9, 0xAE, 0xC7, 0x7F, 0xA9, 0xEA, 0x1A,
+ 0xC6, 0xAF, 0x6F, 0xE1, 0x4F, 0x04, 0xF8, 0x37, 0x40, 0x5B, 0x79, 0xFC, 0x5D, 0xF1, 0x0F, 0x5D,
+ 0xBD, 0x0D, 0xFD, 0x9F, 0xA1, 0x68, 0xB6, 0xF3, 0x4B, 0x0C, 0x2F, 0x75, 0x37, 0x95, 0x2B, 0x6E,
+ 0x9A, 0x58, 0x2D, 0xE0, 0x86, 0x2B, 0x8B, 0xAB, 0x99, 0xAD, 0xED, 0xAD, 0xA7, 0x9E, 0x10, 0x0E,
+ 0x03, 0xE1, 0x8F, 0xC2, 0xCD, 0x7A, 0x7F, 0x11, 0xFF, 0x00, 0xC2, 0xE8, 0xF8, 0xD3, 0xFD, 0x8F,
+ 0xAC, 0x7C, 0x60, 0xD4, 0x34, 0xF7, 0xD3, 0xFC, 0x3D, 0xA3, 0xE9, 0xEA, 0x2F, 0xFC, 0x27, 0xF0,
+ 0x2F, 0x48, 0x99, 0xDD, 0x8E, 0x83, 0xE1, 0xB7, 0x90, 0x16, 0x37, 0x32, 0x24, 0x90, 0xA6, 0xA5,
+ 0xAA, 0x28, 0x8A, 0x4D, 0x4E, 0x5B, 0x78, 0x18, 0xC7, 0x05, 0xAD, 0xB5, 0x95, 0x8D, 0x88, 0x07,
+ 0xD0, 0xB4, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x58, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7,
+ 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76,
+ 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5,
+ 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1,
+ 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4,
+ 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x02, 0x1F, 0xBA, 0x7F,
+ 0xDD, 0xFE, 0x94, 0x01, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x01, 0x8F, 0xE2, 0x19, 0xB5, 0xFB, 0x5F, 0x0F, 0xEB, 0x97, 0x1E, 0x13, 0xD3,
+ 0x34, 0x6D, 0x6B, 0xC5, 0x36, 0xFA, 0x3D, 0xCC, 0xDE, 0x1A, 0xD1, 0xBC, 0x43, 0xAE, 0x4F, 0xE1,
+ 0x7F, 0x0F, 0xEA, 0xDA, 0x82, 0x40, 0xC6, 0xCA, 0xD6, 0xFB, 0x53, 0x86, 0xD2, 0xF2, 0x6B, 0x4B,
+ 0x79, 0x25, 0x11, 0x24, 0x93, 0xC7, 0x69, 0x74, 0xF1, 0x23, 0x33, 0xAC, 0x12, 0x95, 0x11, 0xB0,
+ 0x07, 0xC5, 0xFE, 0x1E, 0xB4, 0xFD, 0xB2, 0x7C, 0x31, 0xE2, 0x5F, 0x1E, 0xF8, 0xBF, 0x49, 0xFD,
+ 0x99, 0x3F, 0x64, 0xE8, 0xF5, 0xFF, 0x00, 0x89, 0x5A, 0xB5, 0x8E, 0xB1, 0xE2, 0xAB, 0xD9, 0xFF,
+ 0x00, 0x6E, 0x6F, 0x1B, 0xDD, 0x0B, 0x99, 0x34, 0xDD, 0x2A, 0xDF, 0x4F, 0xB3, 0x8A, 0x08, 0xDB,
+ 0xE1, 0x59, 0x58, 0x61, 0x48, 0x2C, 0x90, 0x88, 0xE3, 0x0A, 0xBE, 0x64, 0x93, 0xC8, 0x46, 0xE9,
+ 0x58, 0x90, 0x0F, 0x7E, 0xF0, 0x0F, 0x82, 0xB5, 0xBD, 0x5F, 0x5E, 0xD2, 0xBE, 0x30, 0x7C, 0x5C,
+ 0xF0, 0x5F, 0x84, 0xBC, 0x31, 0xF1, 0x9E, 0xD3, 0xC2, 0x37, 0x5F, 0x0F, 0xED, 0xF4, 0xCF, 0x05,
+ 0x7C, 0x4A, 0xD4, 0xFE, 0x2A, 0x78, 0x2B, 0xC2, 0x5A, 0x4C, 0xDA, 0xA1, 0xB9, 0x9C, 0x68, 0xF7,
+ 0xF7, 0xBA, 0x46, 0x92, 0xE9, 0x35, 0xFF, 0x00, 0xD9, 0xF4, 0x87, 0xBC, 0x65, 0xD3, 0xE1, 0x2E,
+ 0x74, 0xFD, 0x3E, 0x26, 0x79, 0x56, 0xCE, 0x27, 0x20, 0x1E, 0xD5, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x16, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x0F, 0xF3, 0xF3, 0xFF, 0x00, 0x83, 0x9F, 0x7F, 0xE5, 0x39, 0xFF, 0x00, 0xF0, 0x48, 0x7F,
+ 0xFB, 0x05, 0x7C, 0x3D, 0xFF, 0x00, 0xD5, 0xBD, 0x73, 0x5D, 0x99, 0x67, 0xFC, 0x8C, 0x30, 0xFF,
+ 0x00, 0xE3, 0x87, 0xFE, 0x94, 0x8E, 0x7C, 0x4F, 0xFB, 0xAD, 0x4F, 0xF0, 0xBF, 0xC8, 0xFB, 0x52,
+ 0xBF, 0x53, 0x3E, 0x38, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0x60, 0xBF, 0xE0, 0x88, 0x5F, 0xF2,
+ 0x22, 0x7E, 0xDD, 0x7F, 0xF6, 0x7C, 0xF0, 0x7F, 0xEA, 0x86, 0xF8, 0x65, 0x5F, 0x9D, 0x71, 0x07,
+ 0xFC, 0x8D, 0x27, 0xE9, 0x1F, 0xFD, 0x25, 0x1F, 0x51, 0x95, 0xFF, 0x00, 0xB9, 0x47, 0xE7, 0xF9,
+ 0x9F, 0xB6, 0xD5, 0xE2, 0x9E, 0x88, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x87, 0xEE, 0x9F, 0xF7, 0x7F, 0xA5, 0x00, 0x41, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x58, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94,
+ 0xE7, 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD,
+ 0x76, 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE,
+ 0xB5, 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3,
+ 0xC1, 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F,
+ 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x81, 0x8C,
+ 0x63, 0x8C, 0x63, 0x1D, 0x38, 0xC7, 0x4A, 0x00, 0x6E, 0xC5, 0xF4, 0xA0, 0x03, 0x62, 0xFA, 0x50,
+ 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F, 0x4A, 0x00, 0x36, 0x2F, 0xA5,
+ 0x00, 0x1B, 0x17, 0xD2, 0x80, 0x0D, 0x8B, 0xE9, 0x40, 0x06, 0xC5, 0xF4, 0xA0, 0x03, 0x62, 0xFA,
+ 0x50, 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F, 0x4A, 0x00, 0x36, 0x2F,
+ 0xA5, 0x00, 0x1B, 0x17, 0xD2, 0x80, 0x0D, 0x8B, 0xE9, 0x40, 0x06, 0xC5, 0xF4, 0xA0, 0x03, 0x62,
+ 0xFA, 0x50, 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F, 0x4A, 0x00, 0x36,
+ 0x2F, 0xA5, 0x00, 0x1B, 0x17, 0xD2, 0x80, 0x0D, 0x8B, 0xE9, 0x40, 0x06, 0xC5, 0xF4, 0xA0, 0x03,
+ 0x62, 0xFA, 0x50, 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F, 0x4A, 0x00,
+ 0x36, 0x2F, 0xA5, 0x00, 0x1B, 0x17, 0xD2, 0x80, 0x0D, 0x8B, 0xE9, 0x40, 0x06, 0xC5, 0xF4, 0xA0,
+ 0x03, 0x62, 0xFA, 0x50, 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F, 0x4A,
+ 0x00, 0x36, 0x2F, 0xA5, 0x00, 0x1B, 0x17, 0xD2, 0x80, 0x0D, 0x8B, 0xE9, 0x40, 0x06, 0xC5, 0xF4,
+ 0xA0, 0x03, 0x62, 0xFA, 0x50, 0x01, 0xB1, 0x7D, 0x28, 0x00, 0xD8, 0xBE, 0x94, 0x00, 0x6C, 0x5F,
+ 0x4A, 0x00, 0x36, 0x2F, 0xA5, 0x00, 0x3A, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0xFF, 0x00, 0x3F, 0x3F, 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF,
+ 0x00, 0xB0, 0x57, 0xC3, 0xDF, 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE,
+ 0x38, 0x7F, 0xE9, 0x48, 0xE7, 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5,
+ 0x2B, 0xF5, 0x33, 0xE3, 0x82, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x0B, 0xFE, 0x08, 0x85, 0xFF,
+ 0x00, 0x22, 0x27, 0xED, 0xD7, 0xFF, 0x00, 0x67, 0xCF, 0x07, 0xFE, 0xA8, 0x6F, 0x86, 0x55, 0xF9,
+ 0xD7, 0x10, 0x7F, 0xC8, 0xD2, 0x7E, 0x91, 0xFF, 0x00, 0xD2, 0x51, 0xF5, 0x19, 0x5F, 0xFB, 0x94,
+ 0x7E, 0x7F, 0x99, 0xFB, 0x6D, 0x5E, 0x29, 0xE8, 0x85, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x7F, 0x9F, 0x9F, 0xFC, 0x1C, 0xFB, 0xFF, 0x00, 0x29, 0xCF, 0xFF, 0x00, 0x82,
+ 0x43, 0xFF, 0x00, 0xD8, 0x2B, 0xE1, 0xEF, 0xFE, 0xAD, 0xEB, 0x9A, 0xEC, 0xCB, 0x3F, 0xE4, 0x61,
+ 0x87, 0xFF, 0x00, 0x1C, 0x3F, 0xF4, 0xA4, 0x73, 0xE2, 0x7F, 0xDD, 0x6A, 0x7F, 0x85, 0xFE, 0x47,
+ 0xDA, 0x95, 0xFA, 0x99, 0xF1, 0xC1, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFB, 0x05, 0xFF, 0x00, 0x04,
+ 0x42, 0xFF, 0x00, 0x91, 0x13, 0xF6, 0xEB, 0xFF, 0x00, 0xB3, 0xE7, 0x83, 0xFF, 0x00, 0x54, 0x37,
+ 0xC3, 0x2A, 0xFC, 0xEB, 0x88, 0x3F, 0xE4, 0x69, 0x3F, 0x48, 0xFF, 0x00, 0xE9, 0x28, 0xFA, 0x8C,
+ 0xAF, 0xFD, 0xCA, 0x3F, 0x3F, 0xCC, 0xFD, 0xB6, 0xAF, 0x14, 0xF4, 0x42, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x3F, 0xCF, 0xCF, 0xFE, 0x0E, 0x7D, 0xFF, 0x00, 0x94, 0xE7,
+ 0xFF, 0x00, 0xC1, 0x21, 0xFF, 0x00, 0xEC, 0x15, 0xF0, 0xF7, 0xFF, 0x00, 0x56, 0xF5, 0xCD, 0x76,
+ 0x65, 0x9F, 0xF2, 0x30, 0xC3, 0xFF, 0x00, 0x8E, 0x1F, 0xFA, 0x52, 0x39, 0xF1, 0x3F, 0xEE, 0xB5,
+ 0x3F, 0xC2, 0xFF, 0x00, 0x23, 0xED, 0x4A, 0xFD, 0x4C, 0xF8, 0xE0, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0xFD, 0x82, 0xFF, 0x00, 0x82, 0x21, 0x7F, 0xC8, 0x89, 0xFB, 0x75, 0xFF, 0x00, 0xD9, 0xF3, 0xC1,
+ 0xFF, 0x00, 0xAA, 0x1B, 0xE1, 0x95, 0x7E, 0x75, 0xC4, 0x1F, 0xF2, 0x34, 0x9F, 0xA4, 0x7F, 0xF4,
+ 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xDB, 0x57, 0x8A, 0x7A, 0x21, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F, 0xE7, 0xE7, 0xFF, 0x00, 0x07, 0x3E,
+ 0xFF, 0x00, 0xCA, 0x73, 0xFF, 0x00, 0xE0, 0x90, 0xFF, 0x00, 0xF6, 0x0A, 0xF8, 0x7B, 0xFF, 0x00,
+ 0xAB, 0x7A, 0xE6, 0xBB, 0x32, 0xCF, 0xF9, 0x18, 0x61, 0xFF, 0x00, 0xC7, 0x0F, 0xFD, 0x29, 0x1C,
+ 0xF8, 0x9F, 0xF7, 0x5A, 0x9F, 0xE1, 0x7F, 0x91, 0xF6, 0xA5, 0x7E, 0xA6, 0x7C, 0x70, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x7E, 0xC1, 0x7F, 0xC1, 0x10, 0xBF, 0xE4, 0x44, 0xFD, 0xBA, 0xFF, 0x00, 0xEC,
+ 0xF9, 0xE0, 0xFF, 0x00, 0xD5, 0x0D, 0xF0, 0xCA, 0xBF, 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2,
+ 0x3F, 0xFA, 0x4A, 0x3E, 0xA3, 0x2B, 0xFF, 0x00, 0x72, 0x8F, 0xCF, 0xF3, 0x3F, 0x6D, 0xAB, 0xC5,
+ 0x3D, 0x10, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xF3, 0xF3, 0xFF,
+ 0x00, 0x83, 0x9F, 0x7F, 0xE5, 0x39, 0xFF, 0x00, 0xF0, 0x48, 0x7F, 0xFB, 0x05, 0x7C, 0x3D, 0xFF,
+ 0x00, 0xD5, 0xBD, 0x73, 0x5D, 0x99, 0x67, 0xFC, 0x8C, 0x30, 0xFF, 0x00, 0xE3, 0x87, 0xFE, 0x94,
+ 0x8E, 0x7C, 0x4F, 0xFB, 0xAD, 0x4F, 0xF0, 0xBF, 0xC8, 0xFB, 0x52, 0xBF, 0x53, 0x3E, 0x38, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x3F, 0x60, 0xBF, 0xE0, 0x88, 0x5F, 0xF2, 0x22, 0x7E, 0xDD, 0x7F, 0xF6,
+ 0x7C, 0xF0, 0x7F, 0xEA, 0x86, 0xF8, 0x65, 0x5F, 0x9D, 0x71, 0x07, 0xFC, 0x8D, 0x27, 0xE9, 0x1F,
+ 0xFD, 0x25, 0x1F, 0x51, 0x95, 0xFF, 0x00, 0xB9, 0x47, 0xE7, 0xF9, 0x9F, 0xB6, 0xD5, 0xE2, 0x9E,
+ 0x88, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x07, 0xF9, 0xF9, 0xFF, 0x00,
+ 0xC1, 0xCF, 0xBF, 0xF2, 0x9C, 0xFF, 0x00, 0xF8, 0x24, 0x3F, 0xFD, 0x82, 0xBE, 0x1E, 0xFF, 0x00,
+ 0xEA, 0xDE, 0xB9, 0xAE, 0xCC, 0xB3, 0xFE, 0x46, 0x18, 0x7F, 0xF1, 0xC3, 0xFF, 0x00, 0x4A, 0x47,
+ 0x3E, 0x27, 0xFD, 0xD6, 0xA7, 0xF8, 0x5F, 0xE4, 0x7D, 0xA9, 0x5F, 0xA9, 0x9F, 0x1C, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x1F, 0xB0, 0x5F, 0xF0, 0x44, 0x2F, 0xF9, 0x11, 0x3F, 0x6E, 0xBF, 0xFB, 0x3E,
+ 0x78, 0x3F, 0xF5, 0x43, 0x7C, 0x32, 0xAF, 0xCE, 0xB8, 0x83, 0xFE, 0x46, 0x93, 0xF4, 0x8F, 0xFE,
+ 0x92, 0x8F, 0xA8, 0xCA, 0xFF, 0x00, 0xDC, 0xA3, 0xF3, 0xFC, 0xCF, 0xDB, 0x6A, 0xF1, 0x4F, 0x44,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02,
+ 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x03, 0xFC, 0xFC, 0xFF, 0x00, 0xE0,
+ 0xE7, 0xDF, 0xF9, 0x4E, 0x7F, 0xFC, 0x12, 0x1F, 0xFE, 0xC1, 0x5F, 0x0F, 0x7F, 0xF5, 0x6F, 0x5C,
+ 0xD7, 0x66, 0x59, 0xFF, 0x00, 0x23, 0x0C, 0x3F, 0xF8, 0xE1, 0xFF, 0x00, 0xA5, 0x23, 0x9F, 0x13,
+ 0xFE, 0xEB, 0x53, 0xFC, 0x2F, 0xF2, 0x3E, 0xD4, 0xAF, 0xD4, 0xCF, 0x8E, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x0F, 0xD8, 0x2F, 0xF8, 0x22, 0x17, 0xFC, 0x88, 0x9F, 0xB7, 0x5F, 0xFD, 0x9F, 0x3C, 0x1F,
+ 0xFA, 0xA1, 0xBE, 0x19, 0x57, 0xE7, 0x5C, 0x41, 0xFF, 0x00, 0x23, 0x49, 0xFA, 0x47, 0xFF, 0x00,
+ 0x49, 0x47, 0xD4, 0x65, 0x7F, 0xEE, 0x51, 0xF9, 0xFE, 0x67, 0xED, 0xB5, 0x78, 0xA7, 0xA2, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x01, 0xFE, 0x7E, 0x7F, 0xF0, 0x73, 0xEF,
+ 0xFC, 0xA7, 0x3F, 0xFE, 0x09, 0x0F, 0xFF, 0x00, 0x60, 0xAF, 0x87, 0xBF, 0xFA, 0xB7, 0xAE, 0x6B,
+ 0xB3, 0x2C, 0xFF, 0x00, 0x91, 0x86, 0x1F, 0xFC, 0x70, 0xFF, 0x00, 0xD2, 0x91, 0xCF, 0x89, 0xFF,
+ 0x00, 0x75, 0xA9, 0xFE, 0x17, 0xF9, 0x1F, 0x6A, 0x57, 0xEA, 0x67, 0xC7, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x07, 0xEC, 0x0F, 0xFC, 0x11, 0x0F, 0x8F, 0x01, 0xFE, 0xDD, 0x98, 0x03, 0x8F, 0xDB, 0x9E,
+ 0x1C, 0x0C, 0x71, 0xC7, 0xC0, 0x6F, 0x86, 0x58, 0x18, 0xFC, 0x05, 0x7E, 0x75, 0xC4, 0x1F, 0xF2,
+ 0x34, 0x9F, 0xA4, 0x7F, 0xF4, 0x94, 0x7D, 0x46, 0x57, 0xFE, 0xE5, 0x1F, 0x9F, 0xE6, 0x7E, 0xD2,
+ 0xEA, 0x1A, 0xA5, 0x86, 0x91, 0x65, 0x3E, 0xA3, 0xA9, 0xDD, 0xDA, 0xE9, 0xF6, 0x16, 0x91, 0x99,
+ 0x6E, 0x2E, 0xEE, 0xE5, 0x58, 0x2D, 0xE1, 0x50, 0x3A, 0x96, 0x38, 0x1D, 0xBA, 0x0F, 0xC2, 0xBC,
+ 0x68, 0xC5, 0xC9, 0xA8, 0xC5, 0x6B, 0xD1, 0x23, 0xBD, 0xB8, 0xC2, 0x37, 0x6E, 0xC8, 0xF3, 0xBD,
+ 0x3F, 0xE3, 0x1F, 0x82, 0xF5, 0x52, 0x4E, 0x9B, 0x79, 0x2C, 0xD6, 0xA8, 0x8C, 0xEF, 0xA8, 0x4D,
+ 0x6A, 0xF6, 0x9A, 0x64, 0x4A, 0xA3, 0xAB, 0xCC, 0xD8, 0x0A, 0x0E, 0x30, 0x33, 0x8C, 0xF1, 0x5B,
+ 0xAC, 0x25, 0x7D, 0x23, 0x18, 0xDD, 0xBD, 0x12, 0x5A, 0xBF, 0x44, 0x96, 0xBF, 0x77, 0xF9, 0x1C,
+ 0xEB, 0x15, 0x41, 0x26, 0xEF, 0x68, 0xA5, 0xBB, 0xD1, 0x76, 0xFE, 0xBA, 0x1A, 0xDF, 0xF0, 0xB2,
+ 0x7C, 0x2E, 0x93, 0xC3, 0x6C, 0xD7, 0xF0, 0xBB, 0x39, 0x09, 0x24, 0x96, 0xA4, 0x5C, 0xDA, 0xD9,
+ 0x64, 0x70, 0x67, 0x90, 0x7C, 0xB1, 0x83, 0x85, 0x00, 0x1E, 0x49, 0x2A, 0x00, 0xE6, 0xB3, 0x95,
+ 0x1A, 0x94, 0xE0, 0xE5, 0x52, 0x2E, 0x29, 0x2E, 0xAA, 0xDF, 0x72, 0x7F, 0xA6, 0x9A, 0x1A, 0xD2,
+ 0xAB, 0x4E, 0xB4, 0xE3, 0x4E, 0x8B, 0xBB, 0x6D, 0x24, 0x97, 0x77, 0xA2, 0x5F, 0x96, 0x9E, 0x87,
+ 0x87, 0xFC, 0x10, 0xFD, 0xAD, 0x3C, 0x27, 0xF1, 0xFB, 0xE2, 0xD7, 0xC6, 0x6F, 0x86, 0xBE, 0x03,
+ 0xF0, 0xBF, 0x89, 0x1B, 0x44, 0xF8, 0x29, 0x06, 0x95, 0x69, 0xAD, 0xFC, 0x42, 0xD4, 0x52, 0x1B,
+ 0x6F, 0x0F, 0xEB, 0x5A, 0x9E, 0xA4, 0xF7, 0x3B, 0xB4, 0xEB, 0x18, 0x55, 0x9A, 0x43, 0xE5, 0x43,
+ 0x69, 0x1C, 0x85, 0xDF, 0x69, 0x22, 0x55, 0x1B, 0x14, 0x05, 0x2F, 0xF3, 0xF9, 0x4E, 0x77, 0x4B,
+ 0x37, 0xC5, 0x62, 0xA8, 0xE1, 0x69, 0xB5, 0x4A, 0x83, 0x8C, 0x1C, 0xDD, 0x92, 0x94, 0xDA, 0x72,
+ 0x6A, 0x29, 0x74, 0x84, 0x79, 0x5B, 0x6E, 0xD7, 0xE6, 0x49, 0x2B, 0x2B, 0x9F, 0xA0, 0x71, 0x7F,
+ 0x01, 0xE2, 0xF8, 0x27, 0x2A, 0xCA, 0x31, 0x39, 0xAE, 0x22, 0x0F, 0x17, 0x8E, 0xA7, 0x52, 0xB2,
+ 0xA1, 0x04, 0xDB, 0xA3, 0x46, 0x32, 0x8C, 0x29, 0xCE, 0xAC, 0x9D, 0x92, 0x95, 0x69, 0xAA, 0xAA,
+ 0x10, 0x8A, 0x92, 0x51, 0xA5, 0x26, 0xE7, 0x76, 0xA2, 0xBE, 0xAC, 0x0C, 0x78, 0x18, 0x00, 0x70,
+ 0x38, 0x18, 0xC0, 0xF6, 0xAF, 0x70, 0xF8, 0x42, 0x4A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A,
+ 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28,
+ 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0,
+ 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80,
+ 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00,
+ 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00,
+ 0xA0, 0x02, 0x80, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0x80, 0x0A, 0x00, 0xFF, 0x00, 0x3F, 0x3F,
+ 0xF8, 0x39, 0xF7, 0xFE, 0x53, 0x9F, 0xFF, 0x00, 0x04, 0x87, 0xFF, 0x00, 0xB0, 0x57, 0xC3, 0xDF,
+ 0xFD, 0x5B, 0xD7, 0x35, 0xD9, 0x96, 0x7F, 0xC8, 0xC3, 0x0F, 0xFE, 0x38, 0x7F, 0xE9, 0x48, 0xE7,
+ 0xC4, 0xFF, 0x00, 0xBA, 0xD4, 0xFF, 0x00, 0x0B, 0xFC, 0x8F, 0xB5, 0x2B, 0xF5, 0x33, 0xE3, 0x82,
+ 0x80, 0x0A, 0x00, 0x28, 0x03, 0xF6, 0x07, 0xFE, 0x08, 0x88, 0x3F, 0xE2, 0x83, 0xFD, 0xBB, 0x00,
+ 0x1F, 0xF3, 0x7C, 0xD0, 0x80, 0x00, 0xFF, 0x00, 0xAA, 0x0D, 0xF0, 0xCB, 0x00, 0x0F, 0xCA, 0xBF,
+ 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2, 0x3F, 0xFA, 0x4A, 0x3E, 0xA3, 0x2B, 0xFF, 0x00, 0x72,
+ 0x8F, 0xCF, 0xF3, 0x3E, 0x97, 0xFD, 0xA5, 0x7E, 0x2D, 0x34, 0xDE, 0x21, 0xB9, 0xD1, 0x61, 0x96,
+ 0x39, 0x74, 0xAD, 0x06, 0xFB, 0xFB, 0x1B, 0x4A, 0xD3, 0x64, 0x6C, 0xD9, 0x6A, 0x5A, 0x8A, 0x45,
+ 0xBA, 0xEA, 0xE6, 0xE2, 0x3E, 0x03, 0xA4, 0x0A, 0xCA, 0x02, 0x9E, 0x09, 0x64, 0x07, 0x86, 0x61,
+ 0x5E, 0xE7, 0x09, 0x64, 0x51, 0xCC, 0x6B, 0x27, 0x51, 0xDA, 0x9A, 0x4A, 0x52, 0xB6, 0x8E, 0xD7,
+ 0xB2, 0x8A, 0x7D, 0x39, 0xAC, 0xEE, 0xD5, 0xAC, 0x93, 0xD9, 0xD9, 0x9F, 0x39, 0xC5, 0x19, 0xC5,
+ 0x5C, 0xBF, 0x0C, 0xFD, 0x84, 0x53, 0x9B, 0xD2, 0x2B, 0xA5, 0xEC, 0xAF, 0x26, 0xBA, 0xF2, 0xDD,
+ 0x24, 0xB6, 0x6D, 0xAD, 0x2D, 0x73, 0xE7, 0x18, 0xFE, 0x21, 0xF8, 0x9F, 0xC1, 0xDA, 0x2D, 0xFE,
+ 0xBB, 0x67, 0xE2, 0x6D, 0x59, 0xAD, 0xAC, 0xE5, 0x8E, 0xEF, 0x56, 0x94, 0xA2, 0x6A, 0x16, 0x2A,
+ 0xF2, 0x0D, 0x89, 0xE7, 0x40, 0x57, 0x6E, 0xCF, 0x9B, 0x6A, 0xA7, 0xCA, 0xA0, 0xE0, 0x28, 0x1C,
+ 0x63, 0xF4, 0x4C, 0x5E, 0x55, 0x93, 0x4E, 0x2A, 0x18, 0xBA, 0x10, 0x8C, 0x23, 0x16, 0xA3, 0xBC,
+ 0x5A, 0x4A, 0xCF, 0xDD, 0x6B, 0x54, 0xF4, 0x57, 0x69, 0x37, 0x6F, 0x2D, 0x0F, 0x81, 0xCA, 0xF1,
+ 0x79, 0xCA, 0xA9, 0x7A, 0x35, 0xE6, 0xE5, 0x27, 0x79, 0x27, 0x66, 0x9B, 0xDB, 0x54, 0xD3, 0xBD,
+ 0x96, 0xC9, 0xB4, 0x96, 0xCA, 0xC7, 0xCD, 0xFA, 0x67, 0xED, 0xE7, 0xF0, 0xC7, 0xE2, 0x47, 0xC5,
+ 0x2F, 0x89, 0x9A, 0x3E, 0x89, 0xAF, 0x6A, 0xDA, 0xEF, 0x8A, 0x7E, 0x0B, 0xFC, 0x38, 0xD7, 0xFC,
+ 0x49, 0xE2, 0x6F, 0x12, 0xE8, 0x36, 0x57, 0x1E, 0x13, 0xF0, 0x5E, 0x9D, 0x69, 0xA6, 0xBC, 0x56,
+ 0xD1, 0x59, 0xEA, 0x71, 0xDB, 0xDA, 0x8D, 0x3E, 0x49, 0x52, 0xFA, 0xEA, 0x03, 0xE4, 0xBD, 0xE4,
+ 0xB2, 0xAB, 0xBC, 0x8A, 0xE9, 0xFE, 0x8F, 0xB6, 0x2F, 0xC5, 0xF8, 0xBB, 0x38, 0xC3, 0x65, 0x99,
+ 0x06, 0x2A, 0x8E, 0x12, 0x2A, 0x34, 0xED, 0x6E, 0x4B, 0xBA, 0x8E, 0x32, 0xB3, 0x4E, 0xD3, 0x92,
+ 0xD1, 0xDB, 0x44, 0xA2, 0x96, 0xC9, 0xA4, 0x9B, 0x77, 0xFE, 0x82, 0xF0, 0xB7, 0x86, 0x71, 0x1C,
+ 0x49, 0xC6, 0xD9, 0x6E, 0x12, 0xB3, 0xE6, 0x6E, 0x71, 0x6E, 0x56, 0x50, 0x4E, 0x11, 0x69, 0xEB,
+ 0x05, 0xA5, 0xAF, 0x67, 0x77, 0xD3, 0x76, 0xD2, 0x56, 0xFD, 0x28, 0xFF, 0x00, 0x82, 0x64, 0xFC,
+ 0x31, 0x87, 0xC0, 0x5F, 0xB2, 0xE6, 0x81, 0xE3, 0x8B, 0xFB, 0xA4, 0xB9, 0xF1, 0x3F, 0xC7, 0xAB,
+ 0xF9, 0x7E, 0x36, 0xF8, 0xA6, 0xE4, 0x4F, 0x14, 0xF6, 0xD1, 0x2E, 0xB0, 0x8A, 0xDA, 0x54, 0x31,
+ 0x4A, 0xA0, 0x65, 0x23, 0xD3, 0x23, 0xD3, 0x81, 0x25, 0x98, 0x6E, 0xF3, 0x08, 0xC0, 0x38, 0x1F,
+ 0x27, 0xC3, 0xD9, 0x5A, 0xCA, 0x32, 0x8A, 0x38, 0x49, 0x2F, 0xDE, 0xB5, 0xCF, 0x51, 0xF7, 0x9C,
+ 0xFD, 0xE9, 0x7F, 0xE0, 0x37, 0x50, 0x5F, 0xDD, 0x8A, 0x3E, 0xAB, 0xC4, 0xAE, 0x2C, 0x5C, 0x67,
+ 0xC6, 0xB8, 0xEC, 0xDF, 0x0F, 0x2F, 0xF6, 0x48, 0x38, 0xD0, 0xC3, 0xAE, 0x91, 0xC3, 0xD0, 0x8A,
+ 0xA7, 0x4A, 0xCB, 0xA7, 0x3A, 0x8B, 0xAB, 0x2F, 0xEF, 0xD4, 0x91, 0xFA, 0x15, 0x14, 0xF6, 0xEE,
+ 0x91, 0xC9, 0x1C, 0xF6, 0xEF, 0x13, 0xAA, 0xBC, 0x6F, 0x1C, 0xC8, 0xC8, 0xCA, 0x47, 0xCA, 0x54,
+ 0x83, 0x82, 0x08, 0xC7, 0x4A, 0xF6, 0x8F, 0x85, 0x27, 0xF3, 0xA0, 0xFF, 0x00, 0x9E, 0xB1, 0x7F,
+ 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB, 0x5A, 0x00, 0x3C, 0xE8, 0x3F,
+ 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00, 0x3D, 0x62, 0xFF, 0x00, 0xBE,
+ 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4, 0x00, 0x79, 0xD0, 0x7F, 0xCF,
+ 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5, 0xFF, 0x00, 0x7D, 0xAD, 0x00,
+ 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3, 0xA0, 0xFF, 0x00, 0x9E, 0xB1,
+ 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB, 0x5A, 0x00, 0x3C, 0xE8,
+ 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00, 0x3D, 0x62, 0xFF, 0x00,
+ 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4, 0x00, 0x79, 0xD0, 0x7F,
+ 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5, 0xFF, 0x00, 0x7D, 0xAD,
+ 0x00, 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3, 0xA0, 0xFF, 0x00, 0x9E,
+ 0xB1, 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB, 0x5A, 0x00, 0x3C,
+ 0xE8, 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00, 0x3D, 0x62, 0xFF,
+ 0x00, 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4, 0x00, 0x79, 0xD0,
+ 0x7F, 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5, 0xFF, 0x00, 0x7D,
+ 0xAD, 0x00, 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3, 0xA0, 0xFF, 0x00,
+ 0x9E, 0xB1, 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB, 0x5A, 0x00,
+ 0x3C, 0xE8, 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00, 0x3D, 0x62,
+ 0xFF, 0x00, 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4, 0x00, 0x79,
+ 0xD0, 0x7F, 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5, 0xFF, 0x00,
+ 0x7D, 0xAD, 0x00, 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3, 0xA0, 0xFF,
+ 0x00, 0x9E, 0xB1, 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB, 0x5A,
+ 0x00, 0x3C, 0xE8, 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00, 0x3D,
+ 0x62, 0xFF, 0x00, 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4, 0x00,
+ 0x79, 0xD0, 0x7F, 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5, 0xFF,
+ 0x00, 0x7D, 0xAD, 0x00, 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3, 0xA0,
+ 0xFF, 0x00, 0x9E, 0xB1, 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE, 0xFB,
+ 0x5A, 0x00, 0x3C, 0xE8, 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF, 0x00,
+ 0x3D, 0x62, 0xFF, 0x00, 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6, 0xB4,
+ 0x00, 0x79, 0xD0, 0x7F, 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A, 0xC5,
+ 0xFF, 0x00, 0x7D, 0xAD, 0x00, 0x1E, 0x74, 0x1F, 0xF3, 0xD6, 0x2F, 0xFB, 0xED, 0x68, 0x00, 0xF3,
+ 0xA0, 0xFF, 0x00, 0x9E, 0xB1, 0x7F, 0xDF, 0x6B, 0x40, 0x07, 0x9D, 0x07, 0xFC, 0xF5, 0x8B, 0xFE,
+ 0xFB, 0x5A, 0x00, 0x3C, 0xE8, 0x3F, 0xE7, 0xAC, 0x5F, 0xF7, 0xDA, 0xD0, 0x01, 0xE7, 0x41, 0xFF,
+ 0x00, 0x3D, 0x62, 0xFF, 0x00, 0xBE, 0xD6, 0x80, 0x0F, 0x3A, 0x0F, 0xF9, 0xEB, 0x17, 0xFD, 0xF6,
+ 0xB4, 0x00, 0x79, 0xD0, 0x7F, 0xCF, 0x58, 0xBF, 0xEF, 0xB5, 0xA0, 0x03, 0xCE, 0x83, 0xFE, 0x7A,
+ 0xC5, 0xFF, 0x00, 0x7D, 0xAD, 0x00, 0x3D, 0x1E, 0x37, 0xFF, 0x00, 0x56, 0xC8, 0xDB, 0x71, 0xF7,
+ 0x08, 0x38, 0xF4, 0xE9, 0xF4, 0xA0, 0x07, 0x0C, 0x76, 0xC7, 0x1C, 0x71, 0x8E, 0x31, 0xDB, 0xF9,
+ 0x50, 0x07, 0xF9, 0xF9, 0xFF, 0x00, 0xC1, 0xCF, 0xBF, 0xF2, 0x9C, 0xFF, 0x00, 0xF8, 0x24, 0x3F,
+ 0xFD, 0x82, 0xBE, 0x1E, 0xFF, 0x00, 0xEA, 0xDE, 0xB9, 0xAE, 0xCC, 0xB3, 0xFE, 0x46, 0x18, 0x7F,
+ 0xF1, 0xC3, 0xFF, 0x00, 0x4A, 0x47, 0x3E, 0x27, 0xFD, 0xD6, 0xA7, 0xF8, 0x5F, 0xE4, 0x7D, 0xA9,
+ 0x5F, 0xA9, 0x9F, 0x1C, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1F, 0xB0, 0x5F, 0xF0, 0x44, 0x3C, 0x0F,
+ 0x01, 0xFE, 0xDD, 0x7C, 0x70, 0x3F, 0x6E, 0x78, 0x78, 0x00, 0x74, 0x1F, 0x01, 0xBE, 0x19, 0x70,
+ 0x07, 0xE1, 0x5F, 0x9D, 0x71, 0x07, 0xFC, 0x8D, 0x27, 0xE9, 0x1F, 0xFD, 0x25, 0x1F, 0x51, 0x95,
+ 0xFF, 0x00, 0xB9, 0x47, 0xE7, 0xF9, 0x9E, 0x5F, 0xFF, 0x00, 0x05, 0x05, 0xF8, 0x53, 0xFB, 0x61,
+ 0x6A, 0x7A, 0xCF, 0xC2, 0x9D, 0x67, 0xF6, 0x45, 0xF0, 0x55, 0xAF, 0x8B, 0xBC, 0x6B, 0xE0, 0x6F,
+ 0x8C, 0xFE, 0x36, 0x87, 0xE2, 0x5F, 0x87, 0x6F, 0xEC, 0x34, 0xF9, 0xB4, 0x6D, 0x73, 0x48, 0xD7,
+ 0xBC, 0x25, 0x72, 0xDE, 0x15, 0xBC, 0xBE, 0x8A, 0xEA, 0x78, 0x16, 0x68, 0x63, 0xD6, 0xA1, 0xD2,
+ 0xB7, 0x6D, 0x95, 0x02, 0x70, 0xD2, 0x1F, 0x25, 0x1C, 0x1D, 0xF0, 0x39, 0xC6, 0x2F, 0x2F, 0xA2,
+ 0xFE, 0xA7, 0x51, 0xC1, 0xB4, 0xAC, 0xD5, 0xB4, 0xB4, 0x5A, 0x6B, 0xE6, 0xDA, 0xB5, 0xBF, 0x03,
+ 0x8F, 0x15, 0x97, 0x61, 0xB1, 0x53, 0x51, 0xC4, 0xD3, 0x52, 0x49, 0xED, 0xF3, 0x56, 0x7F, 0x72,
+ 0xF4, 0xD9, 0x1E, 0x85, 0xFB, 0x2A, 0x78, 0x1B, 0xE2, 0x27, 0x84, 0xFE, 0x23, 0xF8, 0xEF, 0xE1,
+ 0x4F, 0xC5, 0x0F, 0x0C, 0xBF, 0x88, 0xBE, 0x0C, 0x7C, 0x40, 0xF8, 0x2F, 0xA8, 0x6B, 0x9A, 0xBF,
+ 0xC6, 0x4F, 0x16, 0xAD, 0xEE, 0x8D, 0xE2, 0xBF, 0x01, 0x6B, 0x3A, 0x9E, 0xA5, 0x2D, 0xD4, 0xFE,
+ 0x12, 0xBD, 0xB5, 0x2F, 0xFD, 0x9F, 0x25, 0xAE, 0x9D, 0x0D, 0xDD, 0x9C, 0x11, 0xDC, 0xDB, 0xB2,
+ 0x4B, 0x14, 0x96, 0x8A, 0x92, 0x83, 0xB5, 0x2E, 0x6E, 0x3A, 0x33, 0x6C, 0xF7, 0x33, 0xCC, 0x79,
+ 0x53, 0xA8, 0xB9, 0x23, 0x2E, 0x68, 0x28, 0xDA, 0xEA, 0x4E, 0xE9, 0xEC, 0x93, 0xB5, 0x9D, 0xA2,
+ 0x9E, 0xD1, 0x56, 0x77, 0x32, 0xCB, 0x72, 0x9C, 0x06, 0x0E, 0xEE, 0x30, 0xF7, 0x9C, 0x79, 0x64,
+ 0xF5, 0x4A, 0xDA, 0x59, 0x5A, 0xF6, 0xBE, 0x8A, 0xF6, 0xEB, 0xB5, 0x96, 0x87, 0xE0, 0xDF, 0xC3,
+ 0x2D, 0x53, 0x4B, 0xFD, 0x89, 0x7C, 0x03, 0xE2, 0xBF, 0xD9, 0xCF, 0xE2, 0xD7, 0xC0, 0xFF, 0x00,
+ 0x1E, 0x6A, 0x7F, 0x16, 0x9F, 0xC5, 0x7E, 0x1D, 0x87, 0xC4, 0xA9, 0xE0, 0xFF, 0x00, 0x09, 0xEB,
+ 0x9E, 0x35, 0xF0, 0xFF, 0x00, 0xED, 0x37, 0xA0, 0xE9, 0x12, 0xC2, 0x91, 0xE9, 0xFE, 0x18, 0xD7,
+ 0xEC, 0xEC, 0xA6, 0xD3, 0x17, 0x4E, 0xD4, 0xE1, 0xB6, 0x37, 0x22, 0x69, 0xE7, 0x52, 0x3E, 0xDD,
+ 0x2F, 0x9E, 0x91, 0xBC, 0x6C, 0xAD, 0xF1, 0x39, 0xBE, 0x0E, 0xB6, 0x61, 0x84, 0xC2, 0xE1, 0xE2,
+ 0xD2, 0x54, 0xAA, 0xC6, 0x72, 0x8C, 0xA2, 0xF9, 0x66, 0x94, 0x93, 0x6B, 0x99, 0x3B, 0xDD, 0x24,
+ 0xD2, 0x4E, 0x2E, 0x29, 0xA5, 0x7B, 0xA6, 0xED, 0xFA, 0x4F, 0x05, 0xF1, 0x0E, 0x0B, 0x86, 0xB1,
+ 0x39, 0x8D, 0x7A, 0xF4, 0xE6, 0xE7, 0x88, 0xC2, 0xD5, 0xA1, 0x4E, 0xA5, 0x29, 0xC5, 0x4E, 0x8C,
+ 0xAA, 0x53, 0x71, 0x8C, 0xB9, 0x64, 0xAC, 0xE3, 0x76, 0xB9, 0xB9, 0x65, 0x19, 0x72, 0xDD, 0xC1,
+ 0xA9, 0x28, 0x9F, 0xD3, 0xF7, 0xFC, 0x12, 0x93, 0xC0, 0xDF, 0x13, 0x7C, 0x09, 0xFB, 0x17, 0x7C,
+ 0x3F, 0xD0, 0xBE, 0x2C, 0x68, 0x51, 0x78, 0x63, 0x56, 0xB8, 0xBF, 0xD5, 0x75, 0x2D, 0x1F, 0xC1,
+ 0x28, 0x64, 0x96, 0xD3, 0xC1, 0x1A, 0x45, 0xEE, 0xA1, 0x34, 0xF6, 0x1A, 0x0C, 0x0B, 0x20, 0x04,
+ 0x5B, 0x59, 0xC5, 0x70, 0x2D, 0x22, 0x4C, 0x00, 0xB1, 0x5B, 0xC4, 0x80, 0x2A, 0xA8, 0x55, 0xEE,
+ 0x6F, 0x44, 0xBB, 0x1F, 0x25, 0x45, 0x24, 0x9D, 0x92, 0x4B, 0x45, 0xA6, 0xDA, 0x2B, 0x69, 0xF9,
+ 0x7C, 0x8F, 0x34, 0xF1, 0xF7, 0xFC, 0x10, 0x9B, 0xFE, 0x09, 0x35, 0xF1, 0x2B, 0xC5, 0xBA, 0xDF,
+ 0x8D, 0xBC, 0x49, 0xFB, 0x11, 0x7C, 0x0E, 0x4F, 0x10, 0x78, 0x97, 0x53, 0x9F, 0x59, 0xD6, 0xE7,
+ 0xD1, 0x7C, 0x13, 0x61, 0xA1, 0xDA, 0xDF, 0xDD, 0xDD, 0x4A, 0xD2, 0x5C, 0x5C, 0x35, 0xBC, 0x30,
+ 0xAC, 0x61, 0xDE, 0x49, 0x1D, 0x8E, 0xD5, 0x03, 0x24, 0xD2, 0x36, 0x39, 0x0F, 0xF8, 0x87, 0xA7,
+ 0xFE, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x46, 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE,
+ 0x37, 0x40, 0x07, 0xFC, 0x43, 0xD3, 0xFF, 0x00, 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B,
+ 0xFF, 0x00, 0x84, 0xFD, 0xB7, 0xFF, 0x00, 0x1B, 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82,
+ 0x3F, 0xFF, 0x00, 0xD1, 0x94, 0x7C, 0x25, 0xFF, 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0,
+ 0x01, 0xFF, 0x00, 0x10, 0xF4, 0xFF, 0x00, 0xC1, 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF,
+ 0x00, 0xE1, 0x3F, 0x6D, 0xFF, 0x00, 0xC6, 0xE8, 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F,
+ 0xFF, 0x00, 0xF4, 0x65, 0x1F, 0x09, 0x7F, 0xF0, 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F,
+ 0xC4, 0x3D, 0x3F, 0xF0, 0x47, 0xFF, 0x00, 0xFA, 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F,
+ 0xF1, 0xBA, 0x00, 0x3F, 0xE2, 0x1E, 0x9F, 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F,
+ 0xFC, 0x27, 0xED, 0xBF, 0xF8, 0xDD, 0x00, 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE,
+ 0x8C, 0xA3, 0xE1, 0x2F, 0xFE, 0x13, 0xF6, 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE,
+ 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x46, 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37,
+ 0x40, 0x07, 0xFC, 0x43, 0xD3, 0xFF, 0x00, 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF,
+ 0x00, 0x84, 0xFD, 0xB7, 0xFF, 0x00, 0x1B, 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82, 0x3F,
+ 0xFF, 0x00, 0xD1, 0x94, 0x7C, 0x25, 0xFF, 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0, 0x01,
+ 0xFF, 0x00, 0x10, 0xF4, 0xFF, 0x00, 0xC1, 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF, 0x00,
+ 0xE1, 0x3F, 0x6D, 0xFF, 0x00, 0xC6, 0xE8, 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F, 0xFF,
+ 0x00, 0xF4, 0x65, 0x1F, 0x09, 0x7F, 0xF0, 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F, 0xC4,
+ 0x3D, 0x3F, 0xF0, 0x47, 0xFF, 0x00, 0xFA, 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F, 0xF1,
+ 0xBA, 0x00, 0x3F, 0xE2, 0x1E, 0x9F, 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC,
+ 0x27, 0xED, 0xBF, 0xF8, 0xDD, 0x00, 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C,
+ 0xA3, 0xE1, 0x2F, 0xFE, 0x13, 0xF6, 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08,
+ 0xFF, 0x00, 0xFF, 0x00, 0x46, 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40,
+ 0x07, 0xFC, 0x43, 0xD3, 0xFF, 0x00, 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF, 0x00,
+ 0x84, 0xFD, 0xB7, 0xFF, 0x00, 0x1B, 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82, 0x3F, 0xFF,
+ 0x00, 0xD1, 0x94, 0x7C, 0x25, 0xFF, 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0, 0x01, 0xFF,
+ 0x00, 0x10, 0xF4, 0xFF, 0x00, 0xC1, 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF, 0x00, 0xE1,
+ 0x3F, 0x6D, 0xFF, 0x00, 0xC6, 0xE8, 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F, 0xFF, 0x00,
+ 0xF4, 0x65, 0x1F, 0x09, 0x7F, 0xF0, 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F, 0xC4, 0x3D,
+ 0x3F, 0xF0, 0x47, 0xFF, 0x00, 0xFA, 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F, 0xF1, 0xBA,
+ 0x00, 0x3F, 0xE2, 0x1E, 0x9F, 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC, 0x27,
+ 0xED, 0xBF, 0xF8, 0xDD, 0x00, 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C, 0xA3,
+ 0xE1, 0x2F, 0xFE, 0x13, 0xF6, 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08, 0xFF,
+ 0x00, 0xFF, 0x00, 0x46, 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40, 0x1C,
+ 0x7F, 0x8F, 0xFF, 0x00, 0xE0, 0x85, 0x9F, 0xF0, 0x44, 0x0F, 0x84, 0xFE, 0x0C, 0xF1, 0x0F, 0xC4,
+ 0x5F, 0x8A, 0x5F, 0xB3, 0x0F, 0xEC, 0xEB, 0xF0, 0xD3, 0xE1, 0xEF, 0x84, 0x74, 0xF3, 0xAA, 0xF8,
+ 0xAF, 0xC7, 0x7E, 0x3F, 0x9B, 0x49, 0xF0, 0x6F, 0x83, 0x3C, 0x31, 0x68, 0xAC, 0x15, 0xAE, 0x75,
+ 0x1D, 0x52, 0xEC, 0xC5, 0x6D, 0x6D, 0x10, 0x67, 0x41, 0xBE, 0x47, 0x45, 0x04, 0x81, 0x9E, 0x45,
+ 0x00, 0x76, 0x03, 0xFE, 0x0D, 0xEA, 0xFF, 0x00, 0x82, 0x3F, 0xE0, 0x63, 0xF6, 0x28, 0xF8, 0x4A,
+ 0x06, 0x06, 0x07, 0xFC, 0x23, 0xD6, 0xE3, 0x03, 0x1C, 0x0C, 0x79, 0x7F, 0x4A, 0x00, 0x3F, 0xE2,
+ 0x1E, 0x9F, 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC, 0x27, 0xED, 0xBF, 0xF8,
+ 0xDD, 0x00, 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C, 0xA3, 0xE1, 0x2F, 0xFE,
+ 0x13, 0xF6, 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08, 0xFF, 0x00, 0xFF, 0x00,
+ 0x46, 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40, 0x07, 0xFC, 0x43, 0xD3,
+ 0xFF, 0x00, 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF, 0x00, 0x84, 0xFD, 0xB7, 0xFF,
+ 0x00, 0x1B, 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82, 0x3F, 0xFF, 0x00, 0xD1, 0x94, 0x7C,
+ 0x25, 0xFF, 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0, 0x01, 0xFF, 0x00, 0x10, 0xF4, 0xFF,
+ 0x00, 0xC1, 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF, 0x00, 0xE1, 0x3F, 0x6D, 0xFF, 0x00,
+ 0xC6, 0xE8, 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F, 0xFF, 0x00, 0xF4, 0x65, 0x1F, 0x09,
+ 0x7F, 0xF0, 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F, 0xC4, 0x3D, 0x3F, 0xF0, 0x47, 0xFF,
+ 0x00, 0xFA, 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F, 0xF1, 0xBA, 0x00, 0x3F, 0xE2, 0x1E,
+ 0x9F, 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC, 0x27, 0xED, 0xBF, 0xF8, 0xDD,
+ 0x00, 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C, 0xA3, 0xE1, 0x2F, 0xFE, 0x13,
+ 0xF6, 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x46,
+ 0x51, 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40, 0x07, 0xFC, 0x43, 0xD3, 0xFF,
+ 0x00, 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF, 0x00, 0x84, 0xFD, 0xB7, 0xFF, 0x00,
+ 0x1B, 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82, 0x3F, 0xFF, 0x00, 0xD1, 0x94, 0x7C, 0x25,
+ 0xFF, 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0, 0x01, 0xFF, 0x00, 0x10, 0xF4, 0xFF, 0x00,
+ 0xC1, 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF, 0x00, 0xE1, 0x3F, 0x6D, 0xFF, 0x00, 0xC6,
+ 0xE8, 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F, 0xFF, 0x00, 0xF4, 0x65, 0x1F, 0x09, 0x7F,
+ 0xF0, 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F, 0xC4, 0x3D, 0x3F, 0xF0, 0x47, 0xFF, 0x00,
+ 0xFA, 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F, 0xF1, 0xBA, 0x00, 0x3F, 0xE2, 0x1E, 0x9F,
+ 0xF8, 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC, 0x27, 0xED, 0xBF, 0xF8, 0xDD, 0x00,
+ 0x1F, 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C, 0xA3, 0xE1, 0x2F, 0xFE, 0x13, 0xF6,
+ 0xDF, 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x46, 0x51,
+ 0xF0, 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40, 0x07, 0xFC, 0x43, 0xD3, 0xFF, 0x00,
+ 0x04, 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF, 0x00, 0x84, 0xFD, 0xB7, 0xFF, 0x00, 0x1B,
+ 0xA0, 0x03, 0xFE, 0x21, 0xE9, 0xFF, 0x00, 0x82, 0x3F, 0xFF, 0x00, 0xD1, 0x94, 0x7C, 0x25, 0xFF,
+ 0x00, 0xC2, 0x7E, 0xDB, 0xFF, 0x00, 0x8D, 0xD0, 0x01, 0xFF, 0x00, 0x10, 0xF4, 0xFF, 0x00, 0xC1,
+ 0x1F, 0xFF, 0x00, 0xE8, 0xCA, 0x3E, 0x12, 0xFF, 0x00, 0xE1, 0x3F, 0x6D, 0xFF, 0x00, 0xC6, 0xE8,
+ 0x00, 0xFF, 0x00, 0x88, 0x7A, 0x7F, 0xE0, 0x8F, 0xFF, 0x00, 0xF4, 0x65, 0x1F, 0x09, 0x7F, 0xF0,
+ 0x9F, 0xB6, 0xFF, 0x00, 0xE3, 0x74, 0x00, 0x7F, 0xC4, 0x3D, 0x3F, 0xF0, 0x47, 0xFF, 0x00, 0xFA,
+ 0x32, 0x8F, 0x84, 0xBF, 0xF8, 0x4F, 0xDB, 0x7F, 0xF1, 0xBA, 0x00, 0x3F, 0xE2, 0x1E, 0x9F, 0xF8,
+ 0x23, 0xFF, 0x00, 0xFD, 0x19, 0x47, 0xC2, 0x5F, 0xFC, 0x27, 0xED, 0xBF, 0xF8, 0xDD, 0x00, 0x1F,
+ 0xF1, 0x0F, 0x4F, 0xFC, 0x11, 0xFF, 0x00, 0xFE, 0x8C, 0xA3, 0xE1, 0x2F, 0xFE, 0x13, 0xF6, 0xDF,
+ 0xFC, 0x6E, 0x80, 0x0F, 0xF8, 0x87, 0xA7, 0xFE, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x46, 0x51, 0xF0,
+ 0x97, 0xFF, 0x00, 0x09, 0xFB, 0x6F, 0xFE, 0x37, 0x40, 0x07, 0xFC, 0x43, 0xD3, 0xFF, 0x00, 0x04,
+ 0x7F, 0xFF, 0x00, 0xA3, 0x28, 0xF8, 0x4B, 0xFF, 0x00, 0x84, 0xFD, 0xB7, 0xFF, 0x00, 0x1B, 0xA0,
+ 0x0F, 0x5A, 0xF8, 0x21, 0xFF, 0x00, 0x04, 0x5F, 0xFF, 0x00, 0x82, 0x70, 0x7E, 0xCD, 0xBF, 0x11,
+ 0xF4, 0x1F, 0x8B, 0xBF, 0x02, 0x3F, 0x66, 0xFF, 0x00, 0x0A, 0x7C, 0x2A, 0xF8, 0x91, 0xE1, 0xAF,
+ 0x35, 0x74, 0x7F, 0x17, 0x78, 0x21, 0x4F, 0x87, 0xB5, 0x9B, 0x58, 0xE7, 0x88, 0xC7, 0x3C, 0x26,
+ 0x58, 0x42, 0x97, 0x89, 0xD1, 0x8A, 0xB4, 0x6D, 0x95, 0x6E, 0x32, 0x38, 0x18, 0x00, 0xFD, 0x47,
+ 0x8A, 0x31, 0x14, 0x69, 0x18, 0x2C, 0xC1, 0x14, 0x28, 0x2C, 0x72, 0xC4, 0x00, 0x00, 0x24, 0xFA,
+ 0xF0, 0x28, 0x03, 0xFC, 0xFD, 0xBF, 0xE0, 0xE7, 0xDF, 0xF9, 0x4E, 0x7F, 0xFC, 0x12, 0x1F, 0xFE,
+ 0xC1, 0x5F, 0x0F, 0x7F, 0xF5, 0x6F, 0x5C, 0xD7, 0x66, 0x59, 0xFF, 0x00, 0x23, 0x0C, 0x3F, 0xF8,
+ 0xE1, 0xFF, 0x00, 0xA5, 0x23, 0x9F, 0x13, 0xFE, 0xEB, 0x53, 0xFC, 0x2F, 0xF2, 0x3E, 0xD4, 0xAF,
+ 0xD4, 0xCF, 0x8E, 0x0A, 0x00, 0x28, 0x00, 0xA0, 0x0F, 0xD8, 0x1F, 0xF8, 0x22, 0x1E, 0x3F, 0xE1,
+ 0x03, 0xFD, 0xBB, 0x00, 0xC7, 0x1F, 0xB7, 0x3C, 0x23, 0x03, 0x1C, 0x7F, 0xC5, 0x86, 0xF8, 0x63,
+ 0x81, 0x8F, 0xCA, 0xBF, 0x3A, 0xE2, 0x0F, 0xF9, 0x1A, 0x4F, 0xD2, 0x3F, 0xFA, 0x4A, 0x3E, 0xA3,
+ 0x2B, 0xFF, 0x00, 0x72, 0x8F, 0xCF, 0xF3, 0x3E, 0xAE, 0xFD, 0xBA, 0x3F, 0x62, 0x9D, 0x43, 0xF6,
+ 0xC5, 0xD5, 0xBF, 0x66, 0x25, 0xFF, 0x00, 0x84, 0xEB, 0x53, 0xF0, 0x67, 0x85, 0x3E, 0x0C, 0x7C,
+ 0x65, 0x7F, 0x88, 0x7E, 0x3C, 0xD3, 0x34, 0x0B, 0xEB, 0xDD, 0x07, 0xC4, 0x3E, 0x35, 0xD3, 0x9F,
+ 0x49, 0x9A, 0xDA, 0x3D, 0x3E, 0xD3, 0x54, 0xB5, 0x9E, 0x29, 0x6D, 0x0A, 0x5D, 0x49, 0x67, 0x70,
+ 0x59, 0x49, 0x66, 0x16, 0xE1, 0x14, 0xA1, 0x6D, 0xE9, 0xE2, 0xAF, 0x76, 0xDC, 0xA7, 0x74, 0xA3,
+ 0x74, 0x92, 0x5A, 0x1F, 0x8E, 0xDF, 0xB5, 0x97, 0xEC, 0x5F, 0xFF, 0x00, 0x05, 0x1E, 0xD7, 0xF4,
+ 0x2B, 0x5F, 0x83, 0x76, 0xBF, 0xB6, 0x07, 0xC5, 0x5F, 0x16, 0x78, 0x02, 0x4D, 0x17, 0xC3, 0x3F,
+ 0xF0, 0x9C, 0x8D, 0x47, 0xC0, 0x3A, 0x80, 0xD1, 0xBC, 0x51, 0xAC, 0xF8, 0x7F, 0xC5, 0x76, 0x3A,
+ 0xBD, 0xD6, 0xA1, 0x6D, 0x7D, 0x01, 0x90, 0xC9, 0x6F, 0x7D, 0x06, 0x9E, 0xD0, 0x35, 0x9B, 0x01,
+ 0x0C, 0x5E, 0x63, 0x46, 0xC9, 0x34, 0x43, 0x63, 0xFA, 0x98, 0x4A, 0x74, 0x6A, 0xC2, 0xF5, 0x5D,
+ 0xDE, 0x8B, 0xA3, 0x69, 0x26, 0x9E, 0xDA, 0x5B, 0x45, 0x65, 0x6E, 0xF6, 0xD8, 0xF3, 0x6B, 0x3A,
+ 0x94, 0x9A, 0x8C, 0x34, 0x56, 0xEB, 0x74, 0xB6, 0x6B, 0xA7, 0x9D, 0xBE, 0xEF, 0x43, 0xD5, 0xFE,
+ 0x01, 0xFE, 0xC5, 0xBF, 0xF0, 0x54, 0xAD, 0x73, 0xC0, 0x9F, 0x0F, 0x2C, 0xBC, 0x6B, 0xFB, 0x71,
+ 0x5E, 0x5D, 0xDB, 0x78, 0x25, 0xF4, 0x8B, 0x7F, 0x10, 0x68, 0x7E, 0x25, 0xF8, 0x5F, 0x2E, 0x9D,
+ 0x6F, 0xE2, 0xE5, 0xB3, 0xB9, 0xBC, 0x6D, 0x5D, 0x60, 0xBA, 0x9D, 0x22, 0x9C, 0xD9, 0x6A, 0x56,
+ 0xFA, 0x92, 0x2B, 0xA1, 0x2D, 0x24, 0x12, 0x59, 0x58, 0x6D, 0x90, 0xC5, 0x04, 0x90, 0x5E, 0xF2,
+ 0xE2, 0x62, 0xA1, 0x34, 0xA2, 0xD6, 0xCB, 0xAA, 0x7A, 0xAE, 0xE9, 0x6D, 0xE9, 0xF9, 0x9B, 0xE1,
+ 0xD3, 0x9C, 0x36, 0xD1, 0x6D, 0xA5, 0xB4, 0xB6, 0x89, 0x6D, 0x7F, 0x5B, 0x6D, 0xDB, 0x65, 0xF4,
+ 0x07, 0x87, 0xFF, 0x00, 0x62, 0xBF, 0xF8, 0x29, 0xEF, 0x86, 0xBC, 0x2F, 0xE1, 0x1D, 0x02, 0xC7,
+ 0xF6, 0xF2, 0xD3, 0x5D, 0xFC, 0x17, 0xE2, 0xD8, 0x75, 0x5D, 0x33, 0xCA, 0xF0, 0x3A, 0x69, 0x1A,
+ 0x4D, 0xE6, 0x93, 0x06, 0xBF, 0x0D, 0xD4, 0x1A, 0x2C, 0xF6, 0x56, 0xEE, 0x91, 0x9B, 0x64, 0xD2,
+ 0x20, 0xFE, 0xC8, 0xF2, 0xFE, 0xE7, 0x97, 0x1C, 0x77, 0x40, 0x0B, 0x89, 0xA7, 0x2D, 0xC9, 0x6D,
+ 0x2C, 0x75, 0x59, 0xE9, 0x65, 0xE8, 0x7B, 0xCF, 0xEC, 0x89, 0xFB, 0x32, 0xFE, 0xD9, 0x1F, 0x07,
+ 0xFE, 0x3B, 0xF8, 0xBF, 0xE2, 0xBF, 0xC7, 0xBF, 0x8D, 0xFE, 0x10, 0xF8, 0xC1, 0xA5, 0x7C, 0x40,
+ 0xF8, 0x5B, 0xA7, 0x7C, 0x35, 0xD7, 0xAC, 0x6D, 0xF4, 0xBB, 0xED, 0x3B, 0x5A, 0xD2, 0xE4, 0xF0,
+ 0xEF, 0x8B, 0x7C, 0x49, 0xA9, 0xF8, 0x7B, 0x50, 0xB5, 0x94, 0xDC, 0x1B, 0x77, 0x55, 0xD3, 0xFC,
+ 0x68, 0xD6, 0x13, 0x09, 0x20, 0xF3, 0x59, 0x74, 0xDB, 0x47, 0xF3, 0x4E, 0xE6, 0x54, 0x12, 0xB2,
+ 0x48, 0x22, 0x9A, 0xE9, 0xA7, 0xF5, 0xFD, 0x7F, 0x56, 0x3F, 0x50, 0xA9, 0x9A, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1E, 0x3D, 0xF1, 0xF3, 0xE1, 0xBF, 0x88, 0x3E, 0x2D,
+ 0xFC, 0x22, 0xF1, 0x9F, 0xC3, 0xBF, 0x09, 0xF8, 0x9F, 0x47, 0xF0, 0x4F, 0x88, 0x7C, 0x4B, 0xA7,
+ 0x47, 0x65, 0xA5, 0x78, 0xB3, 0x5B, 0xD0, 0xF5, 0x8D, 0x76, 0xD3, 0xC3, 0xCE, 0xB3, 0xA3, 0x35,
+ 0xD4, 0x29, 0xA4, 0x6B, 0x3A, 0x2E, 0xAF, 0x6F, 0x72, 0xA8, 0x8E, 0x60, 0xBB, 0xD3, 0xB5, 0x6D,
+ 0x3A, 0xF2, 0xD2, 0x6F, 0x26, 0xE6, 0xDE, 0xE6, 0x29, 0x60, 0x46, 0x00, 0x1D, 0x1F, 0xC2, 0x8F,
+ 0x87, 0xDA, 0x6F, 0xC2, 0x5F, 0x85, 0xBF, 0x0D, 0x7E, 0x15, 0x68, 0xD3, 0xC5, 0x75, 0xA3, 0xFC,
+ 0x33, 0xF0, 0x06, 0x8D, 0xF0, 0xFB, 0x49, 0xB9, 0x83, 0xC3, 0x9A, 0x2F, 0x83, 0xA0, 0xB8, 0xB6,
+ 0xD1, 0x74, 0xE8, 0x6C, 0xED, 0xE4, 0x4D, 0x23, 0x47, 0xB2, 0xB2, 0xD2, 0x2C, 0x55, 0x92, 0xD9,
+ 0x08, 0xB6, 0xB0, 0xB3, 0xB4, 0xB5, 0x84, 0x11, 0x1C, 0x16, 0xF0, 0xC4, 0x89, 0x1A, 0x00, 0x77,
+ 0xD4, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x07, 0xF9, 0xFA, 0x7F, 0xC1, 0xCF, 0xAB, 0x8F, 0xF8, 0x2E, 0x77, 0xFC,
+ 0x12, 0x1C, 0xE3, 0x0B, 0xFD, 0x97, 0xF0, 0xF5, 0x41, 0xC6, 0x07, 0x1F, 0x17, 0xAE, 0x72, 0x07,
+ 0xD3, 0x23, 0xF4, 0xAE, 0xCC, 0xB3, 0xFE, 0x46, 0x18, 0x7F, 0xF1, 0xC3, 0xFF, 0x00, 0x4A, 0x47,
+ 0x3E, 0x27, 0xFD, 0xD6, 0xA7, 0xF8, 0x5F, 0xE4, 0x7D, 0xA7, 0x5F, 0xA9, 0x9F, 0x1C, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x1F, 0x09, 0xFE, 0xDA, 0xBF, 0xB0, 0x7F, 0x81, 0x3F, 0x6C, 0x1F, 0x05, 0xDA,
+ 0xE8, 0xB6, 0x3A, 0xBE, 0x83, 0xF0, 0x57, 0xE2, 0x08, 0xF1, 0xC6, 0x9D, 0xE2, 0xCD, 0x5F, 0xE3,
+ 0x47, 0x85, 0xFE, 0x18, 0x69, 0xDA, 0xE7, 0xC4, 0x8F, 0x10, 0xD9, 0xE9, 0xDA, 0x55, 0xDD, 0x8A,
+ 0xE8, 0x77, 0x9A, 0x8A, 0xCF, 0x67, 0x79, 0x25, 0xA3, 0x0B, 0xCB, 0x27, 0xDA, 0xF7, 0x4E, 0x8B,
+ 0xFD, 0x9F, 0x6A, 0xBE, 0x51, 0xD8, 0x86, 0x2F, 0x2B, 0x32, 0xCA, 0x68, 0x66, 0x14, 0xD4, 0x52,
+ 0x50, 0x9D, 0xD3, 0x72, 0x51, 0x4D, 0xB4, 0x93, 0x56, 0xBE, 0x8E, 0xDB, 0x75, 0xB6, 0x8B, 0x4E,
+ 0xDD, 0x98, 0x4C, 0x65, 0x4C, 0x2B, 0xD3, 0x58, 0xDA, 0xD6, 0xBD, 0x92, 0xDB, 0x5B, 0x6D, 0xD3,
+ 0xB1, 0xF9, 0xA1, 0xFF, 0x00, 0x0E, 0x0B, 0x3F, 0xF4, 0x7C, 0x5F, 0x11, 0x3F, 0xF0, 0xD2, 0xFF,
+ 0x00, 0xF8, 0x47, 0x5E, 0x2F, 0xFA, 0xA7, 0x1F, 0xF9, 0xFF, 0x00, 0xFF, 0x00, 0x92, 0x7F, 0xF6,
+ 0xC7, 0x77, 0xF6, 0xC4, 0xBF, 0xE7, 0xDA, 0xFB, 0xFF, 0x00, 0xE0, 0x08, 0x7F, 0xE0, 0x81, 0x20,
+ 0x80, 0x0F, 0xED, 0xC1, 0xF1, 0x0C, 0x81, 0x8C, 0x03, 0xF0, 0x8C, 0x10, 0x30, 0x38, 0xC0, 0xFF,
+ 0x00, 0x84, 0x8E, 0x8F, 0xF5, 0x4E, 0x3F, 0xF3, 0xFF, 0x00, 0xFF, 0x00, 0x24, 0xFF, 0x00, 0xED,
+ 0x83, 0xFB, 0x62, 0x56, 0x4B, 0xD9, 0xAB, 0x7A, 0xFF, 0x00, 0xC0, 0x14, 0x7F, 0xC1, 0x02, 0xB6,
+ 0x80, 0x17, 0xF6, 0xE1, 0xF8, 0x88, 0xA0, 0x74, 0x03, 0xE1, 0x26, 0x00, 0xE3, 0xB0, 0xFF, 0x00,
+ 0x84, 0x8F, 0xD8, 0x51, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F,
+ 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4,
+ 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F,
+ 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD,
+ 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF,
+ 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3,
+ 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7,
+ 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE,
+ 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1,
+ 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D,
+ 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF,
+ 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C,
+ 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F,
+ 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD,
+ 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F,
+ 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00,
+ 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82,
+ 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE,
+ 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00,
+ 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE,
+ 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF,
+ 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE,
+ 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B,
+ 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC,
+ 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0,
+ 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17,
+ 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4,
+ 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF,
+ 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F,
+ 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F,
+ 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9,
+ 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF,
+ 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11,
+ 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE,
+ 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34,
+ 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F,
+ 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4,
+ 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F,
+ 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD,
+ 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF,
+ 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3,
+ 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7,
+ 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE,
+ 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1,
+ 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D,
+ 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF,
+ 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C,
+ 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F,
+ 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD,
+ 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F,
+ 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00,
+ 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82,
+ 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE,
+ 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00,
+ 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE,
+ 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF,
+ 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE,
+ 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B,
+ 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC,
+ 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0,
+ 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17,
+ 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4,
+ 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF,
+ 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F,
+ 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F,
+ 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9,
+ 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF,
+ 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11,
+ 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE,
+ 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34,
+ 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F,
+ 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4,
+ 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F,
+ 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD,
+ 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF,
+ 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3,
+ 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7,
+ 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE,
+ 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1,
+ 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D,
+ 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF,
+ 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C,
+ 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F,
+ 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD,
+ 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F,
+ 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00,
+ 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82,
+ 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE,
+ 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00,
+ 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE,
+ 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF,
+ 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE,
+ 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B,
+ 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC,
+ 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0,
+ 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17,
+ 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4,
+ 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF,
+ 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F,
+ 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F,
+ 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9,
+ 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF,
+ 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11,
+ 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE,
+ 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34,
+ 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F,
+ 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4,
+ 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F,
+ 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD,
+ 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF,
+ 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3,
+ 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7,
+ 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE,
+ 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1,
+ 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D,
+ 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF,
+ 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C,
+ 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F,
+ 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD,
+ 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F,
+ 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00,
+ 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82,
+ 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE,
+ 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00,
+ 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE,
+ 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF,
+ 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC, 0x34, 0xBF, 0xFE,
+ 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0, 0x7F, 0x6C, 0x4B,
+ 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x00, 0x7F, 0xC3, 0x82, 0xCF, 0xFD, 0x1F, 0x17, 0xC4, 0x4F, 0xFC,
+ 0x34, 0xBF, 0xFE, 0x11, 0xD1, 0xFE, 0xA9, 0xC7, 0xFE, 0x7F, 0xFF, 0x00, 0xE4, 0x9F, 0xFD, 0xB0,
+ 0x7F, 0x6C, 0x4B, 0xFE, 0x7D, 0xAF, 0xBF, 0xFE, 0x01, 0xDE, 0x7C, 0x1E, 0xFF, 0x00, 0x82, 0x1D,
+ 0xE9, 0x7F, 0x0A, 0x7E, 0x36, 0x7C, 0x1E, 0xF8, 0xD3, 0x77, 0xFB, 0x58, 0x78, 0xAF, 0xC6, 0xB7,
+ 0xBF, 0x08, 0x7E, 0x25, 0x68, 0x1F, 0x11, 0xAC, 0xF4, 0x2D, 0x57, 0xE1, 0x2C, 0x76, 0x6B, 0xAD,
+ 0x1D, 0x07, 0x56, 0x82, 0xF9, 0x2C, 0x0D, 0xE1, 0xD7, 0x66, 0x68, 0x12, 0x56, 0xB5, 0xD8, 0x5C,
+ 0x47, 0x26, 0xCD, 0xE5, 0x82, 0x36, 0x30, 0x77, 0xC3, 0x70, 0xCA, 0xC3, 0x62, 0x29, 0xD7, 0x55,
+ 0xAF, 0xCB, 0x24, 0xED, 0xCB, 0x6B, 0xD9, 0xA7, 0x6F, 0x8B, 0x4D, 0xBB, 0x11, 0x53, 0x35, 0x95,
+ 0x4A, 0x52, 0xA5, 0xEC, 0xD2, 0x4D, 0x35, 0xBE, 0xD7, 0x56, 0xEC, 0x7E, 0xEF, 0xD7, 0xD4, 0x1E,
+ 0x40, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
+ 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00,
+ 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00,
+ 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01,
+ 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05,
+ 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14,
+ 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50,
+ 0x07, 0xFF, 0xD9,
+};
+
+UINT SizeOfWaterMark()
+{
+ return sizeof(WaterMark);
+}
+
+UINT SizeOfSaitama()
+{
+ return sizeof(Saitama);
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WaterMark.h b/src/Cedar/WaterMark.h
new file mode 100644
index 00000000..cfd10767
--- /dev/null
+++ b/src/Cedar/WaterMark.h
@@ -0,0 +1,110 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WaterMark.h
+// Header of WaterMark.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+#ifndef WATERMARK_H
+#define WATERMARK_H
+
+// Digital watermark
+extern BYTE WaterMark[];
+extern BYTE Saitama[];
+
+UINT SizeOfWaterMark();
+UINT SizeOfSaitama();
+
+#define MAX_WATERMARK_SIZE (SizeOfWaterMark() + HTTP_PACK_RAND_SIZE_MAX * 2)
+
+#endif // WATERMARK_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WebUI.c b/src/Cedar/WebUI.c
new file mode 100644
index 00000000..86541f49
--- /dev/null
+++ b/src/Cedar/WebUI.c
@@ -0,0 +1,1961 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Tetsuo Sugiyama
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WebUI.c
+// Web User Interface module
+
+#include "CedarPch.h"
+
+static WU_CONTEXT *WuNewContext(WEBUI *wu, char *hubname);
+static void WuFreeContext(WU_CONTEXT *context);
+static WU_WEBPAGE *WuNewUniWebPage(wchar_t *content);
+static WU_WEBPAGE *WuNewWebPage(char *content, UINT size, char *filename);
+static wchar_t *WuErrorPage(UINT errorcode);
+static wchar_t *WuRedirectPage(char *url);
+static wchar_t *WuUniReadFile(char *filename);
+static void WuUniReplace(wchar_t **buf, wchar_t *from, wchar_t *to);
+static void WuUniInsertBefore(wchar_t **buf, wchar_t *insert, wchar_t *before);
+static LIST *WuAnalyzeTarget(char *target,char *filename, UINT size);
+static void WuFreeStrStrMap(LIST *params);
+static void WuEnableTag(wchar_t **buf, wchar_t *keyword);
+static char *WuNewSessionKey();
+static void WuUniStrReplace(wchar_t **buf, wchar_t *from, char *to);
+static wchar_t *WuUniGetTemplate(wchar_t **str, wchar_t *start, wchar_t *end, bool erase);
+static void WuUniUintReplace(wchar_t **buf, wchar_t *key, UINT num);
+static void WuUniUint64Replace(wchar_t **buf, wchar_t *key, UINT64 num);
+static wchar_t *WuUniGetTemplate(wchar_t **str, wchar_t *start, wchar_t *end, bool erase);
+static LIST *WuUniMakeTable(wchar_t *def);
+static LIST *WuUniMakeTableFromTemplate(wchar_t **str, wchar_t *start, wchar_t *end);
+static void WuExpireSessionKey(WEBUI *wu);
+static WU_CONTEXT *WuGetContext(LIST *contexts, char *sessionkey);
+
+#define WP_DEFAULT "/webui/"
+#define WP_LOGIN "/webui/login.cgi"
+#define WP_REDIRECT "/webui/redirect.cgi"
+#define WP_ERROR "/webui/error.cgi"
+#define WP_SERVER "/webui/server.cgi"
+#define WP_LISTENER "/webui/listener.cgi"
+#define WP_HUB "/webui/hub.cgi"
+#define WP_USER "/webui/user.cgi"
+#define WP_EDITUSER "/webui/edituser.cgi"
+#define WP_NEWHUB "/webui/newhub.cgi"
+#define WP_LICENSE "/webui/license.cgi"
+#define WP_LOCALBRIDGE "/webui/localbridge.cgi"
+#define WP_SECURENAT "/webui/securenat.cgi"
+#define WP_SESSION "/webui/session.cgi"
+
+static wchar_t *WpDefault(WEBUI *wu, LIST *params);
+static wchar_t *WpLogin(WEBUI *wu, LIST *params);
+static wchar_t *WpServer(WEBUI *wu, LIST *params);
+static wchar_t *WpListener(WEBUI *wu, LIST *params);
+static wchar_t *WpHub(WEBUI *wu, LIST *params);
+static wchar_t *WpUser(WEBUI *wu, LIST *params);
+static wchar_t *WpEditUser(WEBUI *wu, LIST *params);
+static wchar_t *WpNewHub(WEBUI *wu, LIST *params);
+static wchar_t *WpLicense(WEBUI *wu, LIST *params);
+static wchar_t *WpLocalBridge(WEBUI *wu, LIST *params);
+static wchar_t *WpSecureNAT(WEBUI *wu, LIST *params);
+static wchar_t *WpSession(WEBUI *wu, LIST *params);
+
+// WebUI page handler table
+static STRMAP_ENTRY wu_pages[] = {
+ {WP_DEFAULT, WpDefault},
+ {WP_LOGIN, WpLogin},
+ {WP_SERVER, WpServer},
+ {WP_LISTENER, WpListener},
+ {WP_HUB, WpHub},
+ {WP_USER, WpUser},
+ {WP_EDITUSER, WpEditUser},
+ {WP_NEWHUB, WpNewHub},
+ {WP_LICENSE, WpLicense},
+ {WP_LOCALBRIDGE, WpLocalBridge},
+ {WP_SECURENAT, WpSecureNAT},
+ {WP_SESSION, WpSession},
+};
+
+// **** Page handlers
+
+// Redirect the directory access to the login screen
+static wchar_t *WpDefault(WEBUI *wu, LIST *params)
+{
+ return WuRedirectPage(WP_LOGIN);
+}
+
+// Login page
+static wchar_t *WpLogin(WEBUI *wu, LIST *params)
+{
+ UINT result;
+ char random[20], securepass[SHA1_SIZE];
+ char *password = (char*)StrMapSearch(params, "PASS");
+ char *hubname = (char*)StrMapSearch(params, "HUB");
+
+ if(password == NULL)
+ {
+ wchar_t *buf = WuUniReadFile("|"WP_LOGIN);
+ WuUniStrReplace(&buf, L"ACTION", WP_LOGIN);
+ WuUniStrReplace(&buf, L"HUBNAME", hubname == NULL ? "" : hubname);
+ return buf;
+ }
+
+ // Administrator authentication
+ Rand(random,sizeof(random));
+ Hash(securepass, password, StrLen(password), true);
+ SecurePassword(securepass, securepass, random);
+ result = AdminCheckPassword(wu->Cedar, random, securepass, hubname, false, NULL);
+
+ if(result == ERR_NO_ERROR)
+ {
+ // Successful login
+ char tmp[MAX_SIZE];
+ STRMAP_ENTRY *context;
+
+ // Create a new context
+ context = Malloc(sizeof(STRMAP_ENTRY));
+ context->Name = WuNewSessionKey();
+ context->Value = WuNewContext(wu, hubname);
+ Add(wu->Contexts, context);
+
+ // Transfer to the server management screen
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_SERVER, context->Name);
+ return WuRedirectPage(tmp);
+ }else{
+ // Login failure
+ wchar_t *buf = WuUniReadFile("|"WP_LOGIN);
+ WuUniStrReplace(&buf, L"ACTION", WP_LOGIN);
+ WuUniStrReplace(&buf, L"HUBNAME",hubname == NULL ? "" : hubname);
+ WuUniReplace(&buf, L"<!--ERR1-->", GetUniErrorStr(result));
+ return buf;
+ }
+}
+
+// Server management
+static wchar_t *WpServer(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ UINT i;
+ wchar_t *buf;
+ LIST *strmap;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ buf = WuUniReadFile("|"WP_SERVER);
+ strmap = WuUniMakeTableFromTemplate(&buf, L"<!--STRMAP:", L":STRMAP-->");
+
+ // Show the Virtual HUB list
+ {
+ wchar_t *tmpl = WuUniGetTemplate(&buf, L"<!--HUBS_TMPL:", L":HUBS_TMPL-->", true);
+ RPC_ENUM_HUB t;
+
+ t.Hubs = NULL;
+ StEnumHub(context->Admin, &t);
+ for(i=0; i<t.NumHub; i++)
+ {
+ wchar_t *tmp = UniCopyStr(tmpl);
+ wchar_t lastlogin[MAX_SIZE], lastcomm[MAX_SIZE];
+ RPC_ENUM_HUB_ITEM *item = &t.Hubs[i];
+
+ GetDateTimeStr64Uni(lastlogin,sizeof(lastlogin), SystemToLocal64(item->LastLoginTime));
+ GetDateTimeStr64Uni(lastcomm, sizeof(lastcomm), SystemToLocal64(item->LastCommTime));
+ WuUniStrReplace(&tmp, L"{HUBNAME}", item->HubName);
+ WuUniReplace(&tmp, L"{HUBSTATE}", item->Online ? StrMapSearch(strmap, "HUB_ONLINE") : StrMapSearch(strmap, "HUB_OFFLINE"));
+ WuUniReplace(&tmp, L"{HUBTYPE}", item->HubType == HUB_TYPE_STANDALONE ? StrMapSearch(strmap, "HUB_STANDALONE")
+ : item->HubType == HUB_TYPE_FARM_DYNAMIC ? StrMapSearch(strmap,"HUB_DYNAMIC") : StrMapSearch(strmap, "HUB_STATIC"));
+ WuUniUintReplace(&tmp, L"{HUBUSERS}", item->NumUsers);
+ WuUniUintReplace(&tmp, L"{HUBGROUPS}", item->NumGroups);
+ WuUniUintReplace(&tmp, L"{HUBSESSIONS}", item->NumSessions);
+ WuUniUintReplace(&tmp, L"{HUBMACS}", item->NumMacTables);
+ WuUniUintReplace(&tmp, L"{HUBIPS}", item->NumIpTables);
+ WuUniUintReplace(&tmp, L"{HUBLOGINS}", item->NumLogin);
+ WuUniReplace(&tmp, L"{HUBLASTLOGINDATE}", lastlogin);
+ WuUniReplace(&tmp, L"{HUBLASTCOMMDATE}", lastcomm);
+
+ WuUniInsertBefore(&buf, tmp, L"<!--HUBS-->");
+ Free(tmp);
+ }
+ FreeRpcEnumHub(&t);
+ Free(tmpl);
+ }
+
+ // Show the listener list
+ {
+ RPC_LISTENER_LIST t;
+ wchar_t *tmpl = WuUniGetTemplate(&buf, L"<!--LISTENER_TMPL:", L":LISTENER_TMPL-->", true);
+ Zero(&t, sizeof(t));
+ StEnumListener(context->Admin, &t);
+ for(i=0; i<t.NumPort; i++)
+ {
+ wchar_t *tmp = UniCopyStr(tmpl);
+ WuUniReplace(&tmp, L"{PORT_STATE}", t.Enables[i] == false ? StrMapSearch(strmap,"LISTENER_OFFLINE")
+ : t.Errors[i] == true ? StrMapSearch(strmap,"LISTENER_ERROR") : StrMapSearch(strmap, "LISTENER_ONLINE"));
+ WuUniUintReplace(&tmp, L"{PORTNUM}", t.Ports[i]);
+ WuEnableTag(&tmp, t.Enables[i] ? L"STOPA" : L"STARTA");
+ WuUniInsertBefore(&buf, tmp, L"<!--LISTENERS-->");
+ Free(tmp);
+ }
+ FreeRpcListenerList(&t);
+ Free(tmpl);
+ }
+ WuUniStrReplace(&buf, L"{LINK_HUB}", WP_HUB);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{LISTENER_LINK}", WP_LISTENER);
+ WuUniStrReplace(&buf, L"{LINK_NEWHUB}", WP_NEWHUB);
+ WuUniStrReplace(&buf, L"{LINK_SERVER}", WP_SERVER);
+ WuUniStrReplace(&buf, L"{LINK_LICENSE}", WP_LICENSE);
+ WuUniStrReplace(&buf, L"{LINK_LOCALBRIDGE}", WP_LOCALBRIDGE);
+
+ WuFreeStrStrMap(strmap);
+
+ return buf;
+}
+
+// Listener management
+static wchar_t *WpListener(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ RPC_LISTENER t;
+ UINT retcode;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ t.Port = ToInt((char*)StrMapSearch(params, "PORT"));
+
+ if( StrCmp(cmd, "CREATE") == 0 )
+ {
+ // Create a new listener
+ if(t.Port == 0)
+ {
+ wchar_t *buf = WuUniReadFile("|"WP_LISTENER);
+ WuUniStrReplace(&buf, L"ACTION", WP_LISTENER);
+ WuUniStrReplace(&buf, L"SESSIONKEY", sessionkey);
+ return buf;
+ }
+ else
+ {
+ t.Enable = true;
+ retcode = StCreateListener(context->Admin, &t);
+ }
+ }
+ else if( StrCmp(cmd, "DEL")==0 )
+ {
+ retcode = StDeleteListener(context->Admin, &t);
+ }
+ else if(StrCmp(cmd, "START")==0 )
+ {
+ t.Enable = true;
+ retcode = StEnableListener(context->Admin, &t);
+ }
+ else if(StrCmp(cmd, "STOP")==0 )
+ {
+ t.Enable = false;
+ retcode = StEnableListener(context->Admin, &t);
+ }
+
+ if(retcode == ERR_NO_ERROR)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_SERVER, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+ return WuErrorPage(retcode);
+}
+
+// Virtual HUB management
+static wchar_t *WpHub(WEBUI *wu, LIST *params)
+{
+ char *hubname = (char*)StrMapSearch(params, "HUB");
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+
+ // Confirm the session
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ if(StrCmp(cmd, "ONLINE") == 0 || StrCmp(cmd, "OFFLINE") == 0)
+ {
+ // Online / offline switching
+ UINT retcode;
+ RPC_SET_HUB_ONLINE t;
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ t.Online = (StrCmp(cmd, "ONLINE") == 0) ? true : false;
+ retcode = StSetHubOnline(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR){
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "%s?HUB=%s&KEY=%s", WP_HUB, hubname, sessionkey);
+ return WuRedirectPage(tmp);
+ }else{
+ return WuErrorPage(retcode);
+ }
+ }
+ else if(StrCmp(cmd, "DELETE") == 0)
+ {
+ // Delete the Virtual HUB
+ RPC_DELETE_HUB t;
+ UINT retcode;
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ retcode = StDeleteHub(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_SERVER, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+ return WuErrorPage(retcode);
+ }
+ else
+ {
+ // Show the status and commands of the virtual HUB
+ RPC_HUB_STATUS t;
+ UINT retcode;
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ retcode = StGetHubStatus(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR)
+ {
+ wchar_t tmp[MAX_SIZE];
+ wchar_t *buf = WuUniReadFile("|"WP_HUB);
+ LIST *strmap = WuUniMakeTableFromTemplate(&buf, L"<!--STRMAP:", L":STRMAP-->");
+
+ WuUniStrReplace(&buf, L"{HUBNAME}", t.HubName);
+ WuUniReplace(&buf, L"{HUBSTATE}", StrMapSearch(strmap, t.Online == false ? "HUB_OFFLINE" : "HUB_ONLINE"));
+ WuUniReplace(&buf, L"{HUBTYPE}", GetHubTypeStr(t.HubType));
+ WuUniReplace(&buf, L"{HUBSNAT}", StrMapSearch(strmap, t.SecureNATEnabled == false ? "SECNAT_OFF" : "SECNAT_ON"));
+ WuUniUintReplace(&buf, L"{HUBSESSIONS}", t.NumSessions);
+ WuUniUintReplace(&buf, L"{HUBACLS}", t.NumAccessLists);
+ WuUniUintReplace(&buf, L"{HUBUSERS}", t.NumUsers);
+ WuUniUintReplace(&buf, L"{HUBGROUPS}", t.NumGroups);
+ WuUniUintReplace(&buf, L"{HUBMACTBLS}", t.NumMacTables);
+ WuUniUintReplace(&buf, L"{HUBIPTBLS}", t.NumIpTables);
+ WuUniUintReplace(&buf, L"{HUBLOGINS}", t.NumLogin);
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastLoginTime));
+ WuUniReplace(&buf, L"{HUBLASTLOGIN}", tmp);
+ GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastCommTime));
+ WuUniReplace(&buf, L"{HUBLASTCOMM}", tmp);
+ WuUniUint64Replace(&buf, L"{HUBTXUNIPKTS}", t.Traffic.Send.UnicastCount);
+ WuUniUint64Replace(&buf, L"{HUBTXUNISIZE}", t.Traffic.Send.UnicastBytes);
+ WuUniUint64Replace(&buf, L"{HUBTXBRPKTS}", t.Traffic.Send.BroadcastCount);
+ WuUniUint64Replace(&buf, L"{HUBTXBRSIZE}", t.Traffic.Send.BroadcastBytes);
+ WuUniUint64Replace(&buf, L"{HUBRXUNIPKTS}", t.Traffic.Recv.UnicastCount);
+ WuUniUint64Replace(&buf, L"{HUBRXUNISIZE}", t.Traffic.Recv.UnicastBytes);
+ WuUniUint64Replace(&buf, L"{HUBRXBRPKTS}", t.Traffic.Recv.BroadcastCount);
+ WuUniUint64Replace(&buf, L"{HUBRXBRSIZE}", t.Traffic.Recv.BroadcastBytes);
+
+ WuEnableTag(&buf, t.Online ? L"ENABLE_OFFLINE" : L"ENABLE_ONLINE");
+
+ WuUniStrReplace(&buf, L"{LINK_HUB}", WP_HUB);
+ WuUniStrReplace(&buf, L"{LINK_USER}", WP_USER);
+ WuUniStrReplace(&buf, L"{LINK_SERVER}", WP_SERVER);
+ WuUniStrReplace(&buf, L"{LINK_SESSION}", WP_SESSION);
+ WuUniStrReplace(&buf, L"{HUBNAME}", hubname);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{LINK_SECURENAT}", WP_SECURENAT);
+
+ WuFreeStrStrMap(strmap);
+
+ return buf;
+ }else{
+ return WuErrorPage(retcode);
+ }
+ }
+}
+
+// User list
+static wchar_t *WpUser(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *hubname = (char*)StrMapSearch(params, "HUB");
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ UINT retcode;
+ RPC_ENUM_USER t;
+
+ // Check the context
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ if(cmd != NULL && StrCmp(cmd, "DEL") == 0)
+ {
+ char *username = (char*)StrMapSearch(params, "USER");
+ RPC_DELETE_USER t;
+ UINT retcode;
+
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ StrCpy(t.Name, sizeof(t.Name), username);
+ retcode = StDeleteUser(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "%s?HUB=%s&KEY=%s", WP_USER, hubname, sessionkey);
+ return WuRedirectPage(tmp);
+ }else
+ {
+ return WuErrorPage(retcode);
+ }
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ retcode = StEnumUser(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR)
+ {
+ UINT i;
+ wchar_t *buf = WuUniReadFile("|"WP_USER);
+ wchar_t *tmpl = WuUniGetTemplate(&buf, L"<!--USER_TMPL:", L"-->", true);
+ wchar_t tmp[MAX_SIZE];
+ wchar_t datestr[MAX_SIZE];
+
+ for(i=0; i<t.NumUser; i++)
+ {
+ RPC_ENUM_USER_ITEM *item = &t.Users[i];
+ GetDateTimeStr64Uni(datestr, sizeof(datestr), SystemToLocal64(item->LastLoginTime));
+ UniFormat(tmp, sizeof(tmp), tmpl, item->Name, item->Name, item->Name, item->Realname, item->GroupName,
+ item->Note, GetAuthTypeStr(item->AuthType), item->NumLogin, datestr);
+ WuUniInsertBefore(&buf, tmp, L"<!--USERS-->");
+ }
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{HUBNAME}", hubname);
+ WuUniStrReplace(&buf, L"{LINK_USER}", WP_USER);
+ WuUniStrReplace(&buf, L"{LINK_EDITUSER}", WP_EDITUSER);
+ WuUniStrReplace(&buf, L"{LINK_HUB}", WP_HUB);
+
+ FreeRpcEnumUser(&t);
+ Free(tmpl);
+ return buf;
+ }else{
+ return WuErrorPage(retcode);
+ }
+}
+
+// User edit page
+static wchar_t *WpEditUser(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *hubname = (char*)StrMapSearch(params, "HUB");
+ char *username = (char*)StrMapSearch(params, "USER");
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ char tmp[MAX_SIZE];
+ wchar_t utmp[MAX_SIZE];
+ UINT retcode;
+ RPC_SET_USER t;
+ wchar_t *buf;
+
+ // Check the context
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ if(cmd != NULL && (StrCmp(cmd, "SET") == 0 || StrCmp(cmd, "CREATE") == 0))
+ {
+ char *authtype = (char*)StrMapSearch(params, "AUTHTYPE");
+ char *password = (char*)StrMapSearch(params, "PASSWORD");
+ char *password2 = (char*)StrMapSearch(params, "PASSWORD2");
+ bool create = (StrCmp(cmd, "CREATE") == 0);
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.Name, sizeof(t.Name), username);
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ // Read the original user data in the case of edit mode.
+ if(!create)
+ {
+ retcode = StGetUser(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+ }
+
+ // Set the authentication method
+ if(StrCmp(authtype, "ANONYMOUS") == 0)
+ {
+ FreeAuthData(t.AuthType, t.AuthData);
+ t.AuthType = AUTHTYPE_ANONYMOUS;
+ t.AuthData = NULL;
+ }
+ else if(StrCmp(authtype, "PASSWORD") == 0)
+ {
+ if(StrCmp(password,password2) != 0)
+ {
+ // Password for confirmation is mismatched
+ return WuErrorPage(ERR_INVALID_PARAMETER);
+ }
+
+ // If the password field has not changed, leave as is
+ if(t.AuthType != AUTHTYPE_PASSWORD || StrCmp(password, WU_PASSWORD_NOCHANGE) != 0)
+ {
+ FreeAuthData(t.AuthType, t.AuthData);
+ t.AuthType = AUTHTYPE_PASSWORD;
+ t.AuthData = NewPasswordAuthData(username, password);
+ }
+ }
+ else
+ {
+ // Parameters of the authentication method is invalid
+ return WuErrorPage(ERR_INVALID_PARAMETER);
+ }
+
+ // Set the user information
+ if(create)
+ {
+ retcode = StCreateUser(context->Admin, &t);
+ }
+ else
+ {
+ retcode = StSetUser(context->Admin, &t);
+ }
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s&HUB=%s", WP_USER, sessionkey, hubname);
+ return WuRedirectPage(tmp);
+ }
+
+ // Generate the user edit page
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if( username == NULL )
+ {
+ t.AuthType = AUTHTYPE_PASSWORD;
+ }else{
+ UINT retcode;
+ StrCpy(t.Name, sizeof(t.Name), username);
+ retcode = StGetUser(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+ }
+
+ buf = WuUniReadFile("|"WP_EDITUSER);
+
+ if( username == NULL)
+ {
+ WuEnableTag(&buf, L"{USERNAMEINPUT}");
+ WuUniReplace(&buf, L"{USERNAME}", L"");
+ WuUniReplace(&buf, L"{CMDNAME}", L"CREATE");
+ WuUniReplace(&buf, L"{PASSWORD}", L"");
+ }
+ else
+ {
+ WuEnableTag(&buf, L"{USERNAMEHIDDEN}");
+ WuUniStrReplace(&buf, L"{USERNAME}", username);
+ WuUniReplace(&buf, L"{CMDNAME}", L"SET");
+ WuUniStrReplace(&buf, L"{PASSWORD}", WU_PASSWORD_NOCHANGE);
+ }
+
+ // Select the authentication method
+ if(t.AuthType == AUTHTYPE_ANONYMOUS)
+ {
+ WuUniReplace(&buf, L"{SELANONYM}", L"checked");
+ }
+ else
+ {
+ WuUniReplace(&buf, L"{SELANONYM}", L"");
+ if(t.AuthType == AUTHTYPE_PASSWORD)
+ {
+ WuUniReplace(&buf, L"{SELPASSWD}", L"checked");
+ }
+ else
+ {
+ WuUniReplace(&buf, L"{SELPASSWD}", L"");
+ }
+ }
+
+ WuUniReplace(&buf, L"{REALNAME}", t.Realname);
+ WuUniReplace(&buf, L"{NOTETEXT}", t.Note);
+ WuUniStrReplace(&buf, L"{GROUPNAME}", t.GroupName);
+ GetDateTimeStr64Uni(utmp, sizeof(utmp), SystemToLocal64(t.ExpireTime));
+ WuUniReplace(&buf, L"{EXPIREDATE}", utmp);
+
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{HUBNAME}", hubname);
+ WuUniStrReplace(&buf, L"{LINK_EDITUSER}", WP_EDITUSER);
+ WuUniStrReplace(&buf, L"{LINK_USER}", WP_USER);
+
+ return buf;
+}
+
+// Create a new Virtual HUB
+static wchar_t *WpNewHub(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ wchar_t *buf;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ if(StrCmp(cmd, "CREATE") == 0)
+ {
+ UINT retcode;
+ char tmp[MAX_SIZE];
+ RPC_CREATE_HUB t;
+ RPC_SERVER_INFO t2;
+ char *hubname = (char*)StrMapSearch(params, "NAME");
+ char *passwd = (char*)StrMapSearch(params, "PASSWD");
+ char *passwd2 = (char*)StrMapSearch(params, "PASSWD2");
+
+ if(strcmp(passwd,passwd2) != 0)
+ {
+ return WuErrorPage(ERR_INVALID_PARAMETER);
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ Hash(t.HashedPassword, passwd, StrLen(passwd), true);
+ HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, passwd);
+ t.Online = true;
+ t.HubType = HUB_TYPE_STANDALONE;
+
+ // Set to dynamic HUB in the case of cluster controller
+ Zero(&t2, sizeof(t2));
+ if (StGetServerInfo(context->Admin, &t2) == ERR_NO_ERROR)
+ {
+ if (t2.ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ t.HubType = HUB_TYPE_FARM_DYNAMIC;
+ }
+ FreeRpcServerInfo(&t2);
+ }
+
+ retcode = StCreateHub(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_SERVER, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+
+ buf = WuUniReadFile("|"WP_NEWHUB);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{LINK_NEWHUB}", WP_NEWHUB);
+ WuUniStrReplace(&buf, L"{LINK_SERVER}", WP_SERVER);
+ return buf;
+}
+
+// License management page
+static wchar_t *WpLicense(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ UINT retcode;
+ wchar_t *buf;
+ LIST *strmap;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ // Add a license
+ if(StrCmp(cmd, "ADD") == 0)
+ {
+ RPC_TEST t;
+ char tmp[MAX_SIZE];
+ char *licensekey = (char*)StrMapSearch(params, "KEYSTRINGS");
+
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.StrValue, sizeof(t.StrValue), licensekey);
+
+ retcode = StAddLicenseKey(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_LICENSE, sessionkey);
+ return WuRedirectPage(tmp);
+
+ }
+ // Remove the license
+ else if(StrCmp(cmd, "DEL") == 0)
+ {
+ RPC_TEST t;
+ char tmp[MAX_SIZE];
+ char *id = (char*)StrMapSearch(params, "ID");
+
+ Zero(&t, sizeof(t));
+ t.IntValue = ToInt(id);
+
+ retcode = StDelLicenseKey(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_LICENSE, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+
+ buf = WuUniReadFile("|"WP_LICENSE);
+ strmap = WuUniMakeTableFromTemplate(&buf, L"<!--STRMAP:", L"-->");
+
+ // Enumerate the license keys
+ {
+ UINT i;
+ RPC_ENUM_LICENSE_KEY t;
+ wchar_t *tmpl;
+ Zero(&t, sizeof(t));
+
+ retcode = StEnumLicenseKey(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ WuFreeStrStrMap(strmap);
+ Free(buf);
+ return WuErrorPage(retcode);
+ }
+
+ tmpl = WuUniGetTemplate(&buf, L"<!--LICENSES_TMPL:", L":LICENSES_TMPL-->", true);
+
+ for(i = 0; i < t.NumItem; i++)
+ {
+ wchar_t *status, expires[128];
+ wchar_t *tmp = UniCopyStr(tmpl);
+ RPC_ENUM_LICENSE_KEY_ITEM *item = &t.Items[i];
+
+ status = LiGetLicenseStatusStr(item->Status);
+
+ if(item->Expires == 0)
+ {
+ UniStrCpy(expires, sizeof(expires), StrMapSearch(strmap, "EXPIRE_INFINITE"));
+ }
+ else
+ {
+ GetDateStrEx64(expires, sizeof(expires), item->Expires, NULL);
+ }
+
+ WuUniUintReplace(&tmp, L"{ID}", i);
+ WuUniStrReplace(&tmp, L"{LICENSEKEY}", item->LicenseKey);
+ WuUniStrReplace(&tmp, L"{LICENSENAME}", item->LicenseName);
+ WuUniReplace(&tmp, L"{STATUS}", status);
+ WuUniReplace(&tmp, L"{EXPIRES}", expires);
+ WuUniStrReplace(&tmp, L"{LICENSEID}", item->LicenseId);
+ WuUniUintReplace(&tmp, L"{PRODUCTID}", item->ProductId);
+ WuUniUint64Replace(&tmp, L"{SYSTEMID}", item->SystemId);
+ WuUniUintReplace(&tmp, L"{SERIALID}", item->SerialId);
+
+ WuUniInsertBefore(&buf, tmp, L"<!--LICENSES-->");
+ Free(tmp);
+ }
+ FreeRpcEnumLicenseKey(&t);
+ Free(tmpl);
+ }
+
+ // Show the license status
+ {
+ RPC_LICENSE_STATUS t;
+
+ Zero(&t, sizeof(t));
+
+ retcode = StGetLicenseStatus(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ WuFreeStrStrMap(strmap);
+ Free(buf);
+ return WuErrorPage(retcode);
+ }
+
+ WuUniStrReplace(&buf, L"{LSEDITIONNAME}", t.EditionStr);
+ WuUniUint64Replace(&buf, L"{LSSERVERID}", t.SystemId);
+ if(t.SystemExpires == 0)
+ {
+ WuUniReplace(&buf, L"{LSEXPIRES}", StrMapSearch(strmap, "NOEXPIRE"));
+ }
+ else
+ {
+ wchar_t expires[128];
+ GetDateStrEx64(expires, sizeof(expires), t.SystemExpires, NULL);
+ WuUniReplace(&buf, L"{LSEXPIRES}", expires);
+ }
+
+ if(t.NumBridgeConnectLicense == INFINITE)
+ {
+ WuUniReplace(&buf, L"{LSNUMBRIDGES}", StrMapSearch(strmap, "LICENSE_INFINITE"));
+ }
+ else
+ {
+ WuUniUintReplace(&buf, L"{LSNUMBRIDGES}", t.NumBridgeConnectLicense);
+ }
+
+ if(t.NumClientConnectLicense == INFINITE)
+ {
+ WuUniReplace(&buf, L"{LSNUMCLIENTS}", StrMapSearch(strmap, "LICENSE_INFINITE"));
+ }
+ else
+ {
+ WuUniUintReplace(&buf, L"{LSNUMCLIENTS}", t.NumClientConnectLicense);
+ }
+
+ }
+
+ WuUniStrReplace(&buf, L"{LINK_LICENSE}", WP_LICENSE);
+ WuUniStrReplace(&buf, L"{LINK_SERVER}", WP_SERVER);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuFreeStrStrMap(strmap);
+
+ return buf;
+
+}
+
+// Local bridge setup page
+static wchar_t *WpLocalBridge(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ UINT retcode;
+ wchar_t *buf;
+ LIST *strmap;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ // Create a local bridge
+ if(StrCmp(cmd, "CREATE") == 0)
+ {
+ RPC_LOCALBRIDGE t;
+ RPC_ENUM_ETH eth;
+ char tmp[MAX_SIZE];
+ char *tapmode = (char*)StrMapSearch(params, "TAPMODE");
+ char *tapname = (char*)StrMapSearch(params, "TAPNAME");
+ char *devid = (char*)StrMapSearch(params, "DEVID");
+ char *hubname = (char*)StrMapSearch(params, "LBHUBNAME");
+ UINT id = ToInt(devid);
+
+ Zero(&eth, sizeof(eth));
+ retcode = StEnumEthernet(context->Admin, &eth);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ FreeRpcEnumEth(&eth);
+ return WuErrorPage(retcode);
+ }
+
+ Zero(&t, sizeof(t));
+ t.Active = true;
+ if(StrCmp(tapmode, "YES") == 0)
+ {
+ t.TapMode = true;
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), tapname);
+ }
+ else
+ {
+ t.TapMode = false;
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), eth.Items[id].DeviceName);
+ }
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+ t.Online = true;
+ FreeRpcEnumEth(&eth);
+
+ retcode = StAddLocalBridge(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_LOCALBRIDGE, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+
+ // Delete the local bridge
+ if(StrCmp(cmd, "DEL") == 0)
+ {
+ RPC_LOCALBRIDGE t;
+ RPC_ENUM_LOCALBRIDGE et;
+ char tmp[MAX_SIZE];
+ char *listid = (char*)StrMapSearch(params, "LISTID");
+ UINT id = ToInt(listid);
+
+ Zero(&et, sizeof(et));
+ retcode = StEnumLocalBridge(context->Admin, &et);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.DeviceName, sizeof(t.DeviceName), et.Items[id].DeviceName);
+ StrCpy(t.HubName, sizeof(t.HubName), et.Items[id].HubName);
+ FreeRpcEnumLocalBridge(&et);
+
+ retcode = StDeleteLocalBridge(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?KEY=%s", WP_LOCALBRIDGE, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+
+ // Show the current local bridge list and the Virtual HUB list and the device list to be bridged
+ buf = WuUniReadFile("|"WP_LOCALBRIDGE);
+ strmap = WuUniMakeTableFromTemplate(&buf, L"<!--STRMAP:", L"-->");
+
+ // Show the current local bridge list
+ {
+ UINT i;
+ RPC_ENUM_LOCALBRIDGE t;
+ wchar_t *tmpl;
+
+ Zero(&t, sizeof(t));
+ retcode = StEnumLocalBridge(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ FreeRpcEnumLocalBridge(&t);
+ Free(buf);
+ WuFreeStrStrMap(strmap);
+ return WuErrorPage(retcode);
+ }
+
+ tmpl = WuUniGetTemplate(&buf, L"<!--LBLIST_TMPL", L"LBLIST_TMPL-->", true);
+
+ for(i = 0; i < t.NumItem; i++)
+ {
+ RPC_LOCALBRIDGE *item = &t.Items[i];
+ wchar_t *tmp = UniCopyStr(tmpl);
+ WuUniUintReplace(&tmp, L"{LISTID}", i);
+ WuUniStrReplace(&tmp, L"{HUBNAME}", item->HubName);
+ WuUniStrReplace(&tmp, L"{DEVICENAME}", item->DeviceName);
+ WuUniReplace(&tmp, L"{STATUS}", item->Online ? item->Active ? StrMapSearch(strmap, "BRIDGE_ONLINE")
+ : StrMapSearch(strmap, "BRIDGE_ERROR") : StrMapSearch(strmap, "BRIDGE_OFFLINE"));
+ WuUniInsertBefore(&buf, tmp, L"<!--LBLIST-->");
+ Free(tmp);
+ }
+ Free(tmpl);
+ FreeRpcEnumLocalBridge(&t);
+ }
+
+ // Show the Virtual HUB list
+ {
+ wchar_t *tmpl;
+ RPC_ENUM_HUB t;
+ UINT i;
+
+ Zero(&t, sizeof(t));
+ retcode = StEnumHub(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ FreeRpcEnumHub(&t);
+ Free(buf);
+ WuFreeStrStrMap(strmap);
+ return WuErrorPage(retcode);
+ }
+
+ tmpl = WuUniGetTemplate(&buf, L"<!--HUBS_TMPL", L"HUBS_TMPL-->", true);
+ for(i=0; i<t.NumHub; i++)
+ {
+ wchar_t *tmp = UniCopyStr(tmpl);
+ WuUniStrReplace(&tmp, L"{LBHUBNAME}", t.Hubs[i].HubName);
+ WuUniInsertBefore(&buf, tmp, L"<!--HUBS-->");
+ Free(tmp);
+ }
+ FreeRpcEnumHub(&t);
+ Free(tmpl);
+ }
+
+ // Get the device list to be bridge
+ {
+ UINT i;
+ RPC_ENUM_ETH t;
+ wchar_t *tmpl;
+
+ Zero(&t, sizeof(t));
+ retcode = StEnumEthernet(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ FreeRpcEnumEth(&t);
+ Free(buf);
+ WuFreeStrStrMap(strmap);
+ return WuErrorPage(retcode);
+ }
+
+ tmpl = WuUniGetTemplate(&buf, L"<!--LBDEVLIST_TMPL", L"LBDEVLIST_TMPL-->", true);
+
+ for(i = 0; i < t.NumItem; i++)
+ {
+ wchar_t *tmp = UniCopyStr(tmpl);
+ WuUniUintReplace(&tmp, L"{DEVID}", i);
+ WuUniStrReplace(&tmp, L"{ABLEDEVICE}", t.Items[i].DeviceName);
+ WuUniInsertBefore(&buf, tmp, L"<!--LBDEVLIST-->");
+ Free(tmp);
+ }
+ FreeRpcEnumEth(&t);
+ Free(tmpl);
+ }
+
+ WuUniStrReplace(&buf, L"{LINK_LOCALBRIDGE}", WP_LOCALBRIDGE);
+ WuUniStrReplace(&buf, L"{LINK_SERVER}", WP_SERVER);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuFreeStrStrMap(strmap);
+
+ return buf;
+
+}
+
+// Configure the virtual DHCP function and virtual NAT (SecureNAT)
+static wchar_t *WpSecureNAT(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+ char *hubname = (char*)StrMapSearch(params, "HUB");
+
+ UINT retcode;
+ wchar_t *buf;
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ // Enable / disable the SecureNAT function
+ if(StrCmp(cmd, "ENABLE") == 0 || StrCmp(cmd, "DISABLE") == 0)
+ {
+ RPC_HUB t;
+ char tmp[MAX_SIZE];
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ if(StrCmp(cmd, "ENABLE") == 0)
+ {
+ retcode = StEnableSecureNAT(context->Admin, &t);
+ }
+ else
+ {
+ retcode = StDisableSecureNAT(context->Admin, &t);
+ }
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?HUB=%s&KEY=%s", WP_SECURENAT, hubname, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+ // Set the SecureNAT options
+ else if(StrCmp(cmd, "SAVE") == 0)
+ {
+ char tmp[MAX_SIZE];
+ VH_OPTION t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ // Configure the a virtual host
+ StrToMac(t.MacAddress, (char*)StrMapSearch(params, "HOSTMAC"));
+ StrToIP(&t.Ip, (char*)StrMapSearch(params, "HOSTIP"));
+ StrToIP(&t.Mask, (char*)StrMapSearch(params, "HOSTMASK"));
+
+ // Configure the virtual NAT function
+ t.UseNat = (StrCmp((char*)StrMapSearch(params, "NATCHECK"), "on") == 0);
+ t.Mtu = ToInt((char*)StrMapSearch(params, "NATMTU"));
+ t.NatTcpTimeout = ToInt((char*)StrMapSearch(params, "NATTCPTIMEOUT"));
+ t.NatUdpTimeout = ToInt((char*)StrMapSearch(params, "NATUDPTIMEOUT"));
+ t.SaveLog = (StrCmp((char*)StrMapSearch(params, "NATSAVELOG"), "on") == 0);
+
+ // Configure the virtual DHCP server function
+ t.UseDhcp = (StrCmp((char*)StrMapSearch(params, "DHCPCHECK"), "on") == 0);
+ StrToIP(&t.DhcpLeaseIPStart, (char*)StrMapSearch(params, "DHCPIPS"));
+ StrToIP(&t.DhcpLeaseIPEnd, (char*)StrMapSearch(params, "DHCPIPE"));
+ StrToIP(&t.DhcpSubnetMask, (char*)StrMapSearch(params, "DHCPMASK"));
+ t.DhcpExpireTimeSpan = ToInt((char*)StrMapSearch(params, "DHCPEXPIRE"));
+ StrToIP(&t.DhcpGatewayAddress, (char*)StrMapSearch(params, "DHCPGW"));
+ StrToIP(&t.DhcpDnsServerAddress, (char*)StrMapSearch(params, "DHCPDNS"));
+ StrCpy(t.DhcpDomainName, sizeof(t.DhcpDomainName), (char*)StrMapSearch(params, "DHCPDOMAIN"));
+
+ retcode = StSetSecureNATOption(context->Admin, &t);
+ if(retcode == ERR_NO_ERROR)
+ {
+ Format(tmp, sizeof(tmp), "%s?HUB=%s&KEY=%s", WP_SECURENAT, hubname, sessionkey);
+ return WuRedirectPage(tmp);
+ }
+ return WuErrorPage(retcode);
+ }
+
+ buf = WuUniReadFile("|"WP_SECURENAT);
+
+ // Get the enable / disable state of the current SecureNAT
+ {
+ RPC_HUB_STATUS t;
+ Zero(&t, sizeof(&t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ retcode = StGetHubStatus(context->Admin, &t);
+
+ if(retcode != ERR_NO_ERROR)
+ {
+ Free(buf);
+ return WuErrorPage(retcode);
+ }
+
+ WuEnableTag(&buf, t.SecureNATEnabled ? L"DISABLESNAT" : L"ENABLESNAT");
+ }
+
+ // Show the advanced settings of the current SecureNAT
+ {
+ char mac[MAX_SIZE], ip[MAX_SIZE], mask[MAX_SIZE];
+ char dhcpips[MAX_SIZE], dhcpipe[MAX_SIZE], dhcpmask[MAX_SIZE];
+ char optgw[MAX_SIZE], optdns[MAX_SIZE];
+ VH_OPTION t;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hubname);
+
+ retcode = StGetSecureNATOption(context->Admin, &t);
+
+
+ // Configure the virtual interfaces
+ MacToStr(mac, sizeof(mac), t.MacAddress);
+ IPToStr(ip, sizeof(ip), &t.Ip);
+ IPToStr(mask, sizeof(mask), &t.Mask);
+ WuUniStrReplace(&buf, L"{HOSTMAC}", mac);
+ WuUniStrReplace(&buf, L"{HOSTIP}", ip);
+ WuUniStrReplace(&buf, L"{HOSTMASK}", mask);
+
+ // Configure the Virtual NAT
+ WuUniStrReplace(&buf, L"{NATCHECK}", t.UseNat ? "CHECKED" : "");
+ WuUniUintReplace(&buf, L"{NATMTU}", t.Mtu);
+ WuUniUintReplace(&buf, L"{NATTCPTIMEOUT}", t.NatTcpTimeout);
+ WuUniUintReplace(&buf, L"{NATUDPTIMEOUT}", t.NatUdpTimeout);
+
+ WuUniStrReplace(&buf, L"{NATSAVELOG}", t.SaveLog ? "CHECKED" : "");
+
+ // Configure the Virtual DHCP server
+ WuUniStrReplace(&buf, L"{DHCPCHECK}", t.UseDhcp ? "CHECKED" : "");
+
+ IPToStr(dhcpips, sizeof(dhcpips), &t.DhcpLeaseIPStart);
+ IPToStr(dhcpipe, sizeof(dhcpipe), &t.DhcpLeaseIPEnd);
+ IPToStr(dhcpmask, sizeof(dhcpmask), &t.DhcpSubnetMask);
+ WuUniStrReplace(&buf, L"{DHCPIPS}", dhcpips);
+ WuUniStrReplace(&buf, L"{DHCPIPE}", dhcpipe);
+ WuUniStrReplace(&buf, L"{DHCPMASK}", dhcpmask);
+ WuUniUintReplace(&buf, L"{DHCPEXPIRE}", t.DhcpExpireTimeSpan);
+
+ IPToStr(optgw, sizeof(optgw), &t.DhcpGatewayAddress);
+ IPToStr(optdns, sizeof(optdns), &t.DhcpDnsServerAddress);
+ WuUniStrReplace(&buf, L"{DHCPGW}", optgw);
+ WuUniStrReplace(&buf, L"{DHCPDNS}", optdns);
+ WuUniStrReplace(&buf, L"{DHCPDOMAIN}", t.DhcpDomainName);
+ }
+
+ WuUniStrReplace(&buf, L"{LINK_HUB}", WP_HUB);
+ WuUniStrReplace(&buf, L"{LINK_SECURENAT}", WP_SECURENAT);
+ WuUniStrReplace(&buf, L"{HUBNAME}", hubname);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+
+ return buf;
+}
+
+static wchar_t *WpSession(WEBUI *wu, LIST *params)
+{
+ char *sessionkey = (char*)StrMapSearch(params, "KEY");
+ WU_CONTEXT *context = WuGetContext(wu->Contexts, sessionkey);
+ char *hub = (char*)StrMapSearch(params, "HUB");
+ char *cmd = (char*)StrMapSearch(params, "CMD");
+
+ if(context == NULL)
+ {
+ return WuRedirectPage(WP_LOGIN);
+ }
+
+ if(StrCmp(cmd, "DEL") == 0)
+ {
+ char *session = (char*)StrMapSearch(params, "SESSION");
+ RPC_DELETE_SESSION t;
+ UINT retcode;
+ char tmp[MAX_SIZE];
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hub);
+ StrCpy(t.Name, sizeof(t.Name), session);
+
+ retcode = StDeleteSession(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }
+
+ Format(tmp, sizeof(tmp), "%s?HUB=%s&KEY=%s", WP_SESSION, hub, session);
+ return WuRedirectPage(tmp);
+ }
+
+ // Show the session list
+ {
+ RPC_ENUM_SESSION t;
+ UINT retcode;
+
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hub);
+
+ retcode = StEnumSession(context->Admin, &t);
+ if(retcode != ERR_NO_ERROR)
+ {
+ return WuErrorPage(retcode);
+ }else{
+ wchar_t *buf = WuUniReadFile("|"WP_SESSION);
+ wchar_t *tmpl = WuUniGetTemplate(&buf, L"<!--SESSION_TMPL:", L":SESSION_TMPL-->", true);
+ UINT i;
+ for(i=0; i<t.NumSession; i++){
+ RPC_ENUM_SESSION_ITEM *item = &(t.Sessions[i]);
+ wchar_t *tmp = CopyUniStr(tmpl);
+
+ WuUniStrReplace(&tmp, L"{SESSION_NAME}", item->Name);
+ WuUniStrReplace(&tmp, L"{SESSION_SERVER}", item->RemoteHostname);
+ WuUniStrReplace(&tmp, L"{SESSION_USER}", item->Username);
+ WuUniStrReplace(&tmp, L"{SESSION_HOST}", item->Hostname);
+ WuUniUintReplace(&tmp, L"{SESSION_TCP}", item->CurrentNumTcp);
+ WuUniUint64Replace(&tmp, L"{SESSION_BYTES}", item->PacketSize);
+ WuUniUint64Replace(&tmp, L"{SESSION_PKTS}", item->PacketNum);
+ WuUniStrReplace(&tmp, L"{SESSION}", item->Name);
+
+ WuUniInsertBefore(&buf, tmp, L"<!--SESSIONS-->");
+ Free(tmp);
+ }
+
+ WuUniStrReplace(&buf, L"{HUBNAME}", hub);
+ WuUniStrReplace(&buf, L"{SESSIONKEY}", sessionkey);
+ WuUniStrReplace(&buf, L"{LINK_HUB}", WP_HUB);
+ WuUniStrReplace(&buf, L"{LINK_SESSION}", WP_SESSION);
+
+ FreeRpcEnumSession(&t);
+ Free(tmpl);
+ return buf;
+ }
+ }
+}
+
+
+// **** Public interface of the WebUI module
+
+// Get the page
+WU_WEBPAGE *WuGetPage(char *target, WEBUI *wu)
+{
+ char filename[MAX_SIZE];
+ LIST *params;
+ wchar_t *(*handler)(WEBUI *wu, LIST *params);
+
+ // Delete the expired session keys
+ WuExpireSessionKey(wu);
+
+ params = WuAnalyzeTarget(target, filename, sizeof(filename));
+
+ // Search for the handler corresponding to the URL
+ handler = StrMapSearch(wu->PageList, filename);
+
+ // Call the handler
+ if(handler != NULL)
+ {
+ wchar_t *unitmp;
+ WU_WEBPAGE *page;
+ unitmp = handler(wu, params);
+ WuFreeStrStrMap(params);
+ page = WuNewUniWebPage(unitmp);
+ Free(unitmp);
+ return page;
+ }
+
+ WuFreeStrStrMap(params);
+
+ // If it missed, try to read the file directly
+ if(StartWith(filename, WP_DEFAULT))
+ {
+ char tmp[MAX_SIZE] = "|";
+ BUF *buf;
+ WU_WEBPAGE *page;
+
+ StrCat(tmp, sizeof(tmp), filename);
+ buf = ReadDump(tmp);
+ if(buf == NULL)
+ {
+ return NULL;
+ }
+
+ page = WuNewWebPage(buf->Buf, buf->Size, filename);
+ FreeBuf(buf);
+ return page;
+ }
+
+ return NULL;
+}
+
+// Start the WebUI
+WEBUI *WuNewWebUI(CEDAR *cedar)
+{
+ WEBUI *wu = (WEBUI*)Malloc(sizeof(WEBUI));
+ int i;
+
+ wu->Cedar = cedar;
+
+ wu->PageList = NewStrMap();
+ for(i=0;i<sizeof(wu_pages)/sizeof(STRMAP_ENTRY);i++)
+ {
+ Add(wu->PageList, &wu_pages[i]);
+ }
+
+ wu->Contexts = NewStrMap();
+
+ return wu;
+}
+
+// Release the WebUI
+bool WuFreeWebUI(WEBUI *wu)
+{
+ UINT i;
+
+ if(wu == NULL)
+ {
+ return false;
+ }
+
+ for(i=0; i<LIST_NUM(wu->Contexts); i++)
+ {
+ STRMAP_ENTRY *se = LIST_DATA(wu->Contexts, i);
+ Free(se->Name);
+ WuFreeContext((WU_CONTEXT*)se->Value);
+ Free(se);
+ }
+ ReleaseList(wu->Contexts);
+
+ ReleaseList(wu->PageList);
+ Free(wu);
+ return true;
+}
+
+void WuFreeWebPage(WU_WEBPAGE *page)
+{
+ if(page == NULL)
+ {
+ return;
+ }
+
+ FreeHttpHeader(page->header);
+ Free(page->data);
+ Free(page);
+}
+
+// **** Module local utility functions
+
+// Initialize the context
+static WU_CONTEXT *WuNewContext(WEBUI *wu, char *hubname)
+{
+ WU_CONTEXT *context = (WU_CONTEXT*)Malloc(sizeof(WU_CONTEXT));
+
+ if(StrLen(hubname) == 0)
+ {
+ hubname=NULL;
+ }
+ context->Admin = (ADMIN*)ZeroMalloc(sizeof(ADMIN));
+ context->Admin->HubName = hubname != NULL ? CopyStr(hubname) : NULL;
+ context->Admin->Server = wu->Cedar->Server;
+ context->Admin->ServerAdmin = hubname == NULL ? true: false;
+ context->Admin->Rpc = (RPC*)ZeroMalloc(sizeof(RPC));
+ StrCpy(context->Admin->Rpc->Name, sizeof(context->Admin->Rpc->Name), "WEBUI");
+ context->Admin->Rpc->Param = context->Admin;
+ context->Admin->Rpc->ServerAdminMode = context->Admin->ServerAdmin;
+ context->Admin->Rpc->ServerMode = true;
+ context->Admin->Rpc->IsVpnServer = true;
+ context->Admin->Rpc->Lock = NewLock();
+ context->Admin->LogFileList = NULL;
+
+ context->ExpireDate = Tick64() + WU_CONTEXT_EXPIRE;
+
+ return context;
+}
+
+// Release the context
+static void WuFreeContext(WU_CONTEXT *context)
+{
+ DeleteLock(context->Admin->Rpc->Lock);
+ Free(context->Admin->Rpc);
+ Free(context->Admin->HubName);
+ Free(context->Admin);
+ Free(context);
+}
+
+// Create a WebPage structure from the Unicode string
+static WU_WEBPAGE *WuNewUniWebPage(wchar_t *content)
+{
+ WU_WEBPAGE *ret;
+
+ if(content == NULL)
+ {
+ return NULL;
+ }
+
+ ret = (WU_WEBPAGE*)Malloc(sizeof(WU_WEBPAGE));
+ ret->size = CalcUniToUtf8(content);
+ ret->data = (char*)Malloc(ret->size);
+ UniToUtf8(ret->data, ret->size, content);
+
+ ret->header = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(ret->header, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
+ AddHttpValue(ret->header, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(ret->header, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+
+ return ret;
+}
+
+// Generate the WebPage structure from the raw data
+static WU_WEBPAGE *WuNewWebPage(char *content, UINT size, char *filename)
+{
+ WU_WEBPAGE *ret;
+
+ if(content == NULL)
+ {
+ return NULL;
+ }
+
+ ret = (WU_WEBPAGE*)Malloc(sizeof(WU_WEBPAGE));
+ ret->size = size;
+ ret->data = (char*)Malloc(size);
+ Copy(ret->data, content, size);
+
+ ret->header = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(ret->header, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(ret->header, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+
+ if(EndWith(filename, "jpg"))
+ {
+ AddHttpValue(ret->header, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
+ }
+ AddHttpValue(ret->header, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
+
+ return ret;
+}
+
+// Return an error page
+static wchar_t *WuErrorPage(UINT errorcode)
+{
+ wchar_t *buf = WuUniReadFile("|"WP_ERROR);
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), L"%d\n<H2>%s</H2>", errorcode, GetUniErrorStr(errorcode));
+ WuUniReplace(&buf, L"ERRMSG", tmp);
+ return buf;
+}
+
+// Redirect
+static wchar_t *WuRedirectPage(char *url)
+{
+ wchar_t *buf = WuUniReadFile("|"WP_REDIRECT);
+ wchar_t tmp[MAX_SIZE];
+ StrToUni(tmp, sizeof(tmp), url);
+ WuUniReplace(&buf, L"REDIRECT_TO", tmp);
+ return buf;
+}
+
+// Analyse the URL
+static LIST *WuAnalyzeTarget(char *target,char *filename, UINT size)
+{
+ char *start, tmp;
+
+ if(target == NULL || filename == NULL)
+ {
+ return NULL;
+ }
+
+ // Process the absolute path specification
+ if(StartWith(target,"http://"))
+ {
+ // Skip http://
+ target += 7;
+
+ // Skip the host name portion
+ while(*target != '/' && *target != '\0')
+ {
+ target ++;
+ }
+
+ // Error if the "/" isn't included after "http://"
+ if(*target == '\0')
+ {
+ return NULL;
+ }
+
+ target++;
+ }
+
+ // Unescape
+ // (not implemented)
+
+ // Extract the file name portion
+ start = target;
+ while(*target != '?' && *target != '\0')
+ {
+ target ++;
+ }
+ tmp = *target;
+ *target = '\0';
+ StrCpy(filename, size, start);
+ *target = tmp;
+
+ // Interpret if there are parameters
+ if(*target == '?')
+ {
+ LIST *params = NewStrMap();
+ UINT i;
+ TOKEN_LIST *tl;
+ target++;
+ tl =ParseToken(target,"&");
+ for(i=0;i<tl->NumTokens;i++)
+ {
+ char *token = tl->Token[i];
+ char *body = token;
+ STRMAP_ENTRY *newentry = (STRMAP_ENTRY*)Malloc(sizeof(STRMAP_ENTRY));
+
+ while(*body != '=' && *body != '\0')
+ {
+ *body ++;
+ }
+ if(*body == '=')
+ {
+ *body = '\0';
+ body++;
+ }
+ newentry->Name = CopyStr(token);
+ newentry->Value = CopyStr(body);
+ Add(params, newentry);
+// Debug("PARAMS: %s : %s\n",token,body);
+ }
+ FreeToken(tl);
+ return params;
+ }
+ return NULL;
+}
+
+// Release the parameter list
+static void WuFreeStrStrMap(LIST *params)
+{
+ UINT i;
+
+ if(params == NULL)
+ {
+ return;
+ }
+
+ for(i=0; i<LIST_NUM(params); i++)
+ {
+ STRMAP_ENTRY *e = (STRMAP_ENTRY*)LIST_DATA(params, i);
+ Free(e->Name);
+ Free(e->Value);
+ Free(e);
+ }
+ ReleaseList(params);
+}
+
+// Read the UTF-8 file and convert as an Unicode string
+static wchar_t *WuUniReadFile(char *filename)
+{
+ IO *io;
+ UINT size, usize;
+ BYTE *utf8;
+ wchar_t *wchars;
+
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ io = FileOpen(filename, false);
+ if (io == NULL)
+ {
+ return NULL;
+ }
+
+ // Load the file
+ size = FileSize(io);
+ utf8 = (BYTE*)Malloc(size);
+ FileRead(io, (void*)utf8, size);
+ FileClose(io);
+
+ usize = CalcUtf8ToUni(utf8, size);
+ wchars = (wchar_t*)ZeroMalloc(usize+sizeof(wchar_t));
+ Utf8ToUni(wchars, usize, utf8, size);
+ Free(utf8);
+
+ return wchars;
+}
+
+// Replace string (with memory reallocation)
+static void WuUniReplace(wchar_t **buf, wchar_t *from, wchar_t *to)
+{
+ UINT dstsize;
+ wchar_t *oldbuf = *buf;
+
+ if(buf == NULL || from == NULL || to == NULL)
+ {
+ return;
+ }
+
+ dstsize = (UniCalcReplaceStrEx(*buf, from, to, true) + 1) * sizeof(wchar_t);
+ *buf = (wchar_t*)Malloc(dstsize);
+ UniReplaceStr(*buf, dstsize, oldbuf, from, to);
+ Free(oldbuf);
+}
+
+// Insert the string in front of a specified pattern
+static void WuUniInsertBefore(wchar_t **buf, wchar_t *insert, wchar_t *before)
+{
+ UINT tmpsize;
+ wchar_t *tmp;
+
+ if(buf == NULL || insert == NULL || before == NULL)
+ {
+ return;
+ }
+
+ tmpsize = (UniStrLen(insert)+UniStrLen(before)+1)*sizeof(wchar_t);
+ tmp = (wchar_t*)Malloc(tmpsize);
+ UniStrCpy(tmp, tmpsize, insert);
+ UniStrCat(tmp, tmpsize, before);
+ WuUniReplace(buf, before, tmp);
+ Free(tmp);
+}
+
+// Uncomment the tag specified by the keyword
+static void WuEnableTag(wchar_t **buf, wchar_t *keyword)
+{
+ wchar_t tmp[MAX_SIZE];
+ if(buf == NULL || keyword == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"!--%s", keyword);
+ WuUniReplace(buf, tmp, L"");
+
+ UniFormat(tmp, sizeof(tmp), L"%s--", keyword);
+ WuUniReplace(buf, tmp, L"");
+ return;
+}
+
+// Generate a session key
+static char *WuNewSessionKey()
+{
+ char tmp[MD5_SIZE], *ret;
+ UINT size;
+ Rand(tmp, sizeof(tmp));
+ size = sizeof(tmp)*2+1;
+ ret = Malloc(size);
+ BinToStr(ret, size, tmp, sizeof(tmp));
+ return ret;
+}
+
+// Replace the Unicode pattern in Unicode string with ASCII string
+static void WuUniStrReplace(wchar_t **buf, wchar_t *from, char *to)
+{
+ UINT unisize;
+ wchar_t *tmp;
+
+ if(buf == NULL || *buf == NULL || from == NULL || to == NULL)
+ {
+ return;
+ }
+
+ unisize = CalcStrToUni(to);
+ tmp = (wchar_t*)Malloc(unisize);
+ StrToUni(tmp, unisize, to);
+ WuUniReplace(buf, from, tmp);
+ Free(tmp);
+}
+
+// Extract the template surrounded by specified Unicode string from Unicode string
+static wchar_t *WuUniGetTemplate(wchar_t **str, wchar_t *start, wchar_t *end, bool erase)
+{
+ UINT startidx, endidx, len, size, i;
+ wchar_t *ret;
+
+ if(str == NULL || *str == NULL || start == NULL || end == NULL)
+ {
+ return NULL;
+ }
+
+ startidx = UniSearchStr(*str, start, 0);
+ if(startidx == INFINITE)
+ {
+ return NULL;
+ }
+ startidx += UniStrLen(start);
+
+ endidx = UniSearchStr(*str, end, startidx);
+ if(endidx == INFINITE)
+ {
+ return NULL;
+ }
+
+ len = endidx - startidx;
+ size = (len + 1) * sizeof(wchar_t);
+ ret = (wchar_t*)Malloc(size);
+ for(i=0; i<len; i++)
+ {
+ ret[i] = (*str)[startidx + i];
+ }
+ ret[i] = 0;
+
+ if(erase)
+ {
+ wchar_t tmp[MAX_SIZE*10];
+ UniFormat(tmp, sizeof(tmp), L"%s%s%s", start, ret, end);
+ WuUniReplace(str, tmp, L"");
+ }
+ return ret;
+}
+
+// Replace the Unicode pattern in the Unicode string with the UINT number
+static void WuUniUintReplace(wchar_t **buf, wchar_t *key, UINT num)
+{
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), L"%d", num);
+ WuUniReplace(buf, key, tmp);
+}
+
+// Replace the Unicode pattern in the Unicode string with the UINT64 number
+static void WuUniUint64Replace(wchar_t **buf, wchar_t *key, UINT64 num)
+{
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), L"%I64d", num);
+ WuUniReplace(buf, key, tmp);
+}
+
+// Copy the Unicode string until the appearance of the specified character (escapable with '\')
+static wchar_t *WuUniCopyStrTill(wchar_t *str, wchar_t delimiter, wchar_t **ret){
+ UINT num = 0, i;
+ wchar_t *next = str;
+ wchar_t *ptr = str;
+
+ // Count the number of characters to copy
+ while(*next)
+ {
+ if(*next==L'\\')
+ {
+ next++;
+ if(*next == 0)
+ {
+ break;
+ }
+ }
+ else
+ {
+ if(*next == delimiter)
+ {
+ break;
+ }
+ }
+ next++;
+ num++;
+ }
+
+ // Allocate the memory and copy the string
+ *ret = (wchar_t*)Malloc((num+1)*sizeof(wchar_t));
+ for(i=0;i<num;i++)
+ {
+ if(*ptr == L'\\')
+ {
+ ptr++;
+ }
+ (*ret)[i] = *ptr;
+ ptr++;
+ }
+ (*ret)[num]=0;
+
+ // Return a pointer to the next to the delimiter or the end of the string
+ return *next ? next+1 : next;
+}
+
+// Create a string table from Unicode string
+static LIST *WuUniMakeTable(wchar_t *def)
+{
+ LIST *table;
+ STRMAP_ENTRY *entry;
+
+ if(def==NULL)
+ {
+ return NULL;
+ }
+
+ table = NewStrMap();
+ while(*def)
+ {
+ wchar_t *keytmp;
+ UINT keylen;
+ entry = (STRMAP_ENTRY*)Malloc(sizeof(STRMAP_ENTRY));
+ def = WuUniCopyStrTill(def, L':', &keytmp);
+ keylen = CalcUniToStr(keytmp);
+ entry->Name = (char*)Malloc(keylen);
+ UniToStr(entry->Name, keylen, keytmp);
+ def = WuUniCopyStrTill(def, L',', (wchar_t**)&(entry->Value));
+ Add(table, entry);
+ Free(keytmp);
+ }
+ return table;
+}
+
+// Extract the template from Unicode string, and create a string table from it
+static LIST *WuUniMakeTableFromTemplate(wchar_t **str, wchar_t *start, wchar_t *end)
+{
+ wchar_t *tmpl = WuUniGetTemplate(str, start, end, true);
+ LIST *ret = WuUniMakeTable(tmpl);
+ Free(tmpl);
+ return ret;
+}
+
+// Delete the expired session key
+static void WuExpireSessionKey(WEBUI *wu)
+{
+ LIST *Expired = NewList(NULL);
+ UINT i;
+
+ LockList(wu->Contexts);
+
+ for(i=0; i<LIST_NUM(wu->Contexts); i++)
+ {
+ STRMAP_ENTRY *entry = (STRMAP_ENTRY*)LIST_DATA(wu->Contexts, i);
+ WU_CONTEXT *context = (WU_CONTEXT*)entry->Value;
+ if(context->ExpireDate < Tick64())
+ {
+ Add(Expired, entry);
+ }
+ }
+
+ for(i=0; i<LIST_NUM(Expired); i++)
+ {
+ STRMAP_ENTRY *entry = LIST_DATA(Expired, i);
+ Delete(wu->Contexts, entry);
+ Free(entry->Name);
+ WuFreeContext(entry->Value);
+ Free(entry);
+ }
+ ReleaseList(Expired);
+
+ UnlockList(wu->Contexts);
+}
+
+// Get the context, and extend its expiration date
+static WU_CONTEXT *WuGetContext(LIST *contexts, char *sessionkey)
+{
+ WU_CONTEXT *ret = StrMapSearch(contexts, sessionkey);
+ if(ret != NULL)
+ {
+ ret->ExpireDate = Tick64() + WU_CONTEXT_EXPIRE;
+ }
+ return ret;
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WebUI.h b/src/Cedar/WebUI.h
new file mode 100644
index 00000000..944db614
--- /dev/null
+++ b/src/Cedar/WebUI.h
@@ -0,0 +1,119 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Tetsuo Sugiyama
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WebUI.h
+// Header of WebUI.c
+
+#define WU_PASSWORD_NOCHANGE "********"
+#define WU_CONTEXT_EXPIRE 600000
+
+// Prototype declaration
+
+typedef struct WEBUI
+{
+ CEDAR *Cedar;
+ LIST *PageList;
+ LIST *Contexts;
+} WEBUI;
+
+// WebUI context
+typedef struct WU_CONTEXT
+{
+ ADMIN *Admin;
+ UINT64 ExpireDate;
+} WU_CONTEXT;
+
+typedef struct WU_WEBPAGE
+{
+ char *data;
+ UINT size;
+ HTTP_HEADER *header;
+} WU_WEBPAGE;
+
+// Prototype declaration
+bool WuFreeWebUI(WEBUI *wu);
+WEBUI *WuNewWebUI(CEDAR *cedar);
+WU_WEBPAGE *WuGetPage(char *target, WEBUI *wu);
+void WuFreeWebPage(WU_WEBPAGE *page);
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Win32Com.cpp b/src/Cedar/Win32Com.cpp
new file mode 100644
index 00000000..0500fd00
--- /dev/null
+++ b/src/Cedar/Win32Com.cpp
@@ -0,0 +1,979 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32Com.c
+// Win32 COM module call
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define WIN32COM_CPP
+
+#define _WIN32_DCOM
+
+//#define _WIN32_WINNT 0x0502
+//#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <Wbemidl.h>
+#include <comdef.h>
+#include <Mshtmhst.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <iphlpapi.h>
+#include <Natupnp.h>
+#include <devguid.h>
+#include <regstr.h>
+#include <cfgmgr32.h>
+#include <tchar.h>
+#include <objbase.h>
+#include <Setupapi.h>
+#include "netcfgn.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+extern "C"
+{
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+}
+#include "../PenCore/resource.h"
+
+// Add a UPnP port
+bool Win32UPnPAddPort(UINT outside_port, UINT inside_port, bool udp, char *local_ip, wchar_t *description, bool remove_before_add)
+{
+ bool ret = false;
+ HRESULT hr;
+ IUPnPNAT *nat = NULL;
+ wchar_t ip_str[MAX_SIZE];
+ BSTR bstr_ip, bstr_description, bstr_protocol;
+ wchar_t *protocol_str = (udp ? L"UDP" : L"TCP");
+ // Validate arguments
+ if (outside_port == 0 || outside_port >= 65536 || inside_port == 0 || inside_port >= 65536 ||
+ IsEmptyStr(local_ip) || UniIsEmptyStr(description))
+ {
+ return false;
+ }
+
+ StrToUni(ip_str, sizeof(ip_str), local_ip);
+ bstr_ip = SysAllocString(ip_str);
+ bstr_description = SysAllocString(description);
+ bstr_protocol = SysAllocString(protocol_str);
+
+ hr = CoCreateInstance(CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void **)&nat);
+
+ if (SUCCEEDED(hr))
+ {
+ if (nat != NULL)
+ {
+ IStaticPortMappingCollection *collection = NULL;
+ hr = nat->get_StaticPortMappingCollection(&collection);
+
+ if (SUCCEEDED(hr))
+ {
+ if (collection != NULL)
+ {
+ IStaticPortMapping *mapping = NULL;
+
+ if (remove_before_add)
+ {
+ hr = collection->Remove((long)outside_port, bstr_protocol);
+ }
+
+ hr = collection->Add((long)outside_port, bstr_protocol, (long)inside_port,
+ bstr_ip, VARIANT_TRUE, bstr_description, &mapping);
+
+ if (SUCCEEDED(hr))
+ {
+ ret = true;
+
+ if (mapping != NULL)
+ {
+ mapping->Release();
+ }
+ }
+
+ collection->Release();
+ }
+ else
+ {
+ WHERE;
+ }
+ }
+ else
+ {
+ WHERE;
+ }
+
+ nat->Release();
+ }
+ else
+ {
+ WHERE;
+ }
+ }
+ else
+ {
+ WHERE;
+ }
+
+ SysFreeString(bstr_ip);
+ SysFreeString(bstr_description);
+ SysFreeString(bstr_protocol);
+
+ return ret;
+}
+
+// Install the NDIS protocol driver
+bool InstallNdisProtocolDriver(wchar_t *inf_path, wchar_t *id, UINT lock_timeout)
+{
+ bool ret = false;
+ HRESULT hr;
+ INetCfg *pNetCfg;
+ HINSTANCE hSetupApiDll = NULL;
+ BOOL (WINAPI *_SetupCopyOEMInfW)(PCWSTR, PCWSTR, DWORD, DWORD, PWSTR, DWORD, PDWORD, PWSTR *) = NULL;
+ BOOL (WINAPI *_SetupUninstallOEMInfW)(PCWSTR, DWORD, PVOID) = NULL;
+ // Validate arguments
+ if (inf_path == NULL || id == NULL)
+ {
+ return false;
+ }
+
+ hSetupApiDll = LoadLibraryA("setupapi.dll");
+ if (hSetupApiDll == NULL)
+ {
+ WHERE;
+ goto LABEL_CLEANUP;
+ }
+
+ _SetupCopyOEMInfW =
+ (UINT (__stdcall *)(PCWSTR,PCWSTR,DWORD,DWORD,PWSTR,DWORD,PDWORD,PWSTR *))
+ GetProcAddress(hSetupApiDll, "SetupCopyOEMInfW");
+
+ _SetupUninstallOEMInfW =
+ (UINT (__stdcall *)(PCWSTR,DWORD,PVOID))
+ GetProcAddress(hSetupApiDll, "SetupUninstallOEMInfW");
+
+ if (_SetupCopyOEMInfW == NULL || _SetupUninstallOEMInfW == NULL)
+ {
+ WHERE;
+ goto LABEL_CLEANUP;
+ }
+
+ hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void **)&pNetCfg);
+
+ if (SUCCEEDED(hr))
+ {
+ INetCfgLock *pLock;
+
+ hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
+
+ if (SUCCEEDED(hr))
+ {
+ LPWSTR locked_by;
+
+ hr = pLock->AcquireWriteLock(lock_timeout, L"SoftEther VPN", &locked_by);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pNetCfg->Initialize(NULL);
+
+ if (SUCCEEDED(hr))
+ {
+ wchar_t inf_dir[MAX_PATH];
+
+ GetDirNameFromFilePathW(inf_dir, sizeof(inf_dir), inf_path);
+
+ if (_SetupCopyOEMInfW(inf_path, inf_dir, SPOST_PATH, 0, NULL, 0, NULL, 0))
+ {
+ INetCfgClassSetup *pSetup;
+
+ hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS, IID_INetCfgClassSetup, (void **)&pSetup);
+
+ if (SUCCEEDED(hr))
+ {
+ OBO_TOKEN token;
+ INetCfgComponent *pComponent;
+
+ Zero(&token, sizeof(token));
+
+ token.Type = OBO_USER;
+
+ hr = pSetup->Install(id, &token, 0, 0, NULL, NULL, &pComponent);
+
+ if (SUCCEEDED(hr))
+ {
+ pNetCfg->Apply();
+
+ ret = true;
+ }
+ else
+ {
+ WHERE;
+ Debug("0x%x\n", hr);
+ }
+
+ pSetup->Release();
+ }
+ else
+ {
+ WHERE;
+ }
+
+ if (ret == false)
+ {
+ wchar_t dst_inf_name[MAX_PATH];
+ DWORD dst_inf_name_size = MAX_PATH;
+
+ if (_SetupCopyOEMInfW(inf_path, inf_dir, SPOST_PATH, SP_COPY_REPLACEONLY,
+ dst_inf_name, dst_inf_name_size, &dst_inf_name_size, NULL) == false &&
+ GetLastError() == ERROR_FILE_EXISTS)
+ {
+ _SetupUninstallOEMInfW(dst_inf_name, 0, NULL);
+ }
+ }
+ }
+ else
+ {
+ WHERE;
+ }
+ }
+ else
+ {
+ WHERE;
+ }
+
+ pLock->ReleaseWriteLock();
+ }
+ else
+ {
+ WHERE;
+ }
+
+ pLock->Release();
+ }
+
+ pNetCfg->Release();
+ }
+ else
+ {
+ WHERE;
+ }
+
+LABEL_CLEANUP:
+
+ if (hSetupApiDll != NULL)
+ {
+ FreeLibrary(hSetupApiDll);
+ }
+
+ return ret;
+}
+
+typedef struct FOLDER_DLG_INNER_DATA
+{
+ wchar_t *default_dir;
+} FOLDER_DLG_INNER_DATA;
+
+int CALLBACK FolderDlgInnerCallbackA(HWND hWnd, UINT msg, LPARAM lParam, LPARAM lData)
+{
+ FOLDER_DLG_INNER_DATA *data = (FOLDER_DLG_INNER_DATA *)lData;
+ LPITEMIDLIST pidl;
+
+ switch (msg)
+ {
+ case BFFM_INITIALIZED:
+ if (data->default_dir != NULL)
+ {
+ char *default_dir_a = CopyUniToStr(data->default_dir);
+
+ SendMessage(hWnd, BFFM_SETSELECTIONA, true, (LPARAM)default_dir_a);
+
+ Free(default_dir_a);
+ }
+ break;
+
+ case BFFM_SELCHANGED:
+ pidl = (LPITEMIDLIST)lParam;
+
+ if (pidl)
+ {
+ char tmp[MAX_PATH];
+
+ Zero(tmp, sizeof(tmp));
+ if (SHGetPathFromIDListA(pidl, tmp))
+ {
+ SendMessage(hWnd, BFFM_ENABLEOK, 0, 1);
+ }
+ else
+ {
+ SendMessage(hWnd, BFFM_ENABLEOK, 0, 0);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+char *FolderDlgInnerA(HWND hWnd, wchar_t *title, char *default_dir)
+{
+ BROWSEINFOA info;
+ char display_name[MAX_PATH];
+ FOLDER_DLG_INNER_DATA data;
+ LPMALLOC pMalloc;
+ char *ret = NULL;
+ char *title_a;
+ if (UniIsEmptyStr(title))
+ {
+ title = NULL;
+ }
+ if (IsEmptyStr(default_dir))
+ {
+ default_dir = NULL;
+ }
+
+ Zero(&data, sizeof(data));
+ data.default_dir = CopyStrToUni(default_dir);
+
+ Zero(display_name, sizeof(display_name));
+ Zero(&info, sizeof(info));
+ info.hwndOwner = hWnd;
+ info.pidlRoot = NULL;
+ info.pszDisplayName = display_name;
+ title_a = CopyUniToStr(title);
+ info.lpszTitle = title_a;
+ info.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_SHAREABLE;
+ info.lpfn = FolderDlgInnerCallbackA;
+ info.lParam = (LPARAM)&data;
+
+ if (SUCCEEDED(SHGetMalloc(&pMalloc)))
+ {
+ LPITEMIDLIST pidl;
+
+ pidl = SHBrowseForFolderA(&info);
+
+ if (pidl)
+ {
+ char tmp[MAX_PATH];
+
+ if (SHGetPathFromIDListA(pidl, tmp))
+ {
+ ret = CopyStr(tmp);
+ }
+
+ pMalloc->Free(pidl);
+ }
+
+ pMalloc->Release();
+ }
+
+ Free(data.default_dir);
+ Free(title_a);
+
+ return ret;
+}
+
+int CALLBACK FolderDlgInnerCallbackW(HWND hWnd, UINT msg, LPARAM lParam, LPARAM lData)
+{
+ FOLDER_DLG_INNER_DATA *data = (FOLDER_DLG_INNER_DATA *)lData;
+ LPITEMIDLIST pidl;
+
+ switch (msg)
+ {
+ case BFFM_INITIALIZED:
+ if (data->default_dir != NULL)
+ {
+ SendMessage(hWnd, BFFM_SETSELECTIONW, true, (LPARAM)data->default_dir);
+ }
+ break;
+
+ case BFFM_SELCHANGED:
+ pidl = (LPITEMIDLIST)lParam;
+
+ if (pidl)
+ {
+ wchar_t tmp[MAX_PATH];
+
+ Zero(tmp, sizeof(tmp));
+ if (SHGetPathFromIDListW(pidl, tmp))
+ {
+ SendMessage(hWnd, BFFM_ENABLEOK, 0, 1);
+ }
+ else
+ {
+ SendMessage(hWnd, BFFM_ENABLEOK, 0, 0);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+wchar_t *FolderDlgInnerW(HWND hWnd, wchar_t *title, wchar_t *default_dir)
+{
+ BROWSEINFOW info;
+ wchar_t display_name[MAX_PATH];
+ FOLDER_DLG_INNER_DATA data;
+ LPMALLOC pMalloc;
+ wchar_t *ret = NULL;
+ if (UniIsEmptyStr(title))
+ {
+ title = NULL;
+ }
+ if (UniIsEmptyStr(default_dir))
+ {
+ default_dir = NULL;
+ }
+
+ Zero(&data, sizeof(data));
+ data.default_dir = default_dir;
+
+ Zero(display_name, sizeof(display_name));
+ Zero(&info, sizeof(info));
+ info.hwndOwner = hWnd;
+ info.pidlRoot = NULL;
+ info.pszDisplayName = display_name;
+ info.lpszTitle = title;
+ info.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_SHAREABLE;
+ info.lpfn = FolderDlgInnerCallbackW;
+ info.lParam = (LPARAM)&data;
+
+ if (SUCCEEDED(SHGetMalloc(&pMalloc)))
+ {
+ LPITEMIDLIST pidl;
+
+ pidl = SHBrowseForFolderW(&info);
+
+ if (pidl)
+ {
+ wchar_t tmp[MAX_PATH];
+
+ if (SHGetPathFromIDListW(pidl, tmp))
+ {
+ ret = CopyUniStr(tmp);
+ }
+
+ pMalloc->Free(pidl);
+ }
+
+ pMalloc->Release();
+ }
+
+ return ret;
+}
+
+
+class CModule
+{
+public:
+ CModule()
+ {
+ m_hInstLib = NULL;
+ }
+ CModule( HINSTANCE hInstLib )
+ {
+ m_hInstLib = NULL;
+ this->Attach( hInstLib );
+ }
+ CModule( LPCTSTR pszModuleName )
+ {
+ m_hInstLib = NULL;
+ this->LoadLibrary( pszModuleName );
+ }
+ virtual ~CModule()
+ {
+ this->FreeLibrary();
+ }
+
+public:
+ BOOL Attach( HINSTANCE hInstLib )
+ {
+ this->FreeLibrary();
+ m_hInstLib = hInstLib;
+
+ return TRUE;
+ }
+ BOOL Detach()
+ {
+ m_hInstLib = NULL;
+
+ return TRUE;
+ }
+
+public:
+ HMODULE GetHandle()
+ {
+ return m_hInstLib;
+ }
+ // Load the DLL
+ HINSTANCE LoadLibrary( LPCTSTR pszModuleName )
+ {
+ this->FreeLibrary();
+ m_hInstLib = ::LoadLibrary( pszModuleName );
+
+ return m_hInstLib;
+ }
+ // Release the DLL
+ BOOL FreeLibrary()
+ {
+ if (m_hInstLib == NULL)
+ {
+ return FALSE;
+ }
+
+ BOOL bResult = ::FreeLibrary( m_hInstLib );
+ m_hInstLib = NULL;
+
+ return bResult;
+ }
+ // Get the address of the function
+ FARPROC GetProcAddress( LPCTSTR pszProcName )
+ {
+ if (m_hInstLib == NULL)
+ {
+ return NULL;
+ }
+
+ return ::GetProcAddress(m_hInstLib, pszProcName);
+ }
+ // Get a handle to the information block of resource with the specified name and the type
+ HRSRC FindResource(LPCTSTR lpName, LPCTSTR lpType)
+ {
+ if (m_hInstLib == NULL)
+ {
+ return NULL;
+ }
+
+ return ::FindResource(m_hInstLib, lpName, lpType);
+ }
+ // Load the specified resource
+ HGLOBAL LoadResource(HRSRC hResInfo)
+ {
+ if (m_hInstLib == NULL)
+ {
+ return NULL;
+ }
+
+ return ::LoadResource(m_hInstLib, hResInfo);
+ }
+
+protected:
+ HINSTANCE m_hInstLib;
+};
+
+
+
+static HRESULT _ShowHTMLDialog(
+ HWND hwndParent,
+ IMoniker* pMk,
+ VARIANT* pvarArgIn = NULL,
+ WCHAR* pchOptions = NULL,
+ VARIANT* pvarArgOut = NULL)
+{
+ HRESULT hr = S_OK;
+
+ try
+ {
+ CModule Module("MSHTML.DLL");
+ if (Module.GetHandle() == NULL)
+ {
+ return E_FAIL;
+ }
+
+ SHOWHTMLDIALOGFN* fnShowHTMLDialog =
+ (SHOWHTMLDIALOGFN*)Module.GetProcAddress("ShowHTMLDialog");
+ if (fnShowHTMLDialog == NULL)
+ {
+ return E_FAIL;
+ }
+
+ hr = (*fnShowHTMLDialog)(hwndParent, pMk, pvarArgIn, pchOptions, pvarArgOut);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ catch (...)
+ {
+ return E_FAIL;
+ }
+
+ return hr;
+}
+
+HRESULT ShowHTMLDialogFromURL(HWND hwndParent,wchar_t *szURL,VARIANT* pvarArgIn,WCHAR* pchOptions,VARIANT* pvarArgOut)
+{
+ HRESULT hr = S_OK;
+
+ try
+ {
+ IMonikerPtr spMoniker;
+ hr = ::CreateURLMoniker(NULL, szURL, &spMoniker);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = ::_ShowHTMLDialog(hwndParent, spMoniker, pvarArgIn, pchOptions, pvarArgOut);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ catch (...)
+ {
+ return E_FAIL;
+ }
+
+ return hr;
+}
+
+// Create a shortcut
+bool CreateLinkInnerA(char *filename, char *target, char *workdir, char *args,
+ char *comment, char *icon, UINT icon_index)
+{
+ HRESULT r;
+ wchar_t tmp[MAX_SIZE];
+ IShellLinkA* pShellLink;
+ IPersistFile* pPersistFile;
+
+ r = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (void **)&pShellLink);
+ if (FAILED(r))
+ {
+ return false;
+ }
+
+ r = pShellLink->QueryInterface(IID_IPersistFile,(void **)&pPersistFile);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ return false;
+ }
+
+ r = pShellLink->SetPath(target);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+
+ if (workdir != NULL)
+ {
+ r = pShellLink->SetWorkingDirectory(workdir);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (args != NULL)
+ {
+ r = pShellLink->SetArguments(args);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (comment != NULL)
+ {
+ r = pShellLink->SetDescription(comment);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (icon != NULL)
+ {
+ r = pShellLink->SetIconLocation(icon, icon_index);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ StrToUni(tmp, sizeof(tmp), filename);
+ r = pPersistFile->Save(tmp, true);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+
+ pShellLink->Release();
+ pPersistFile->Release();
+ return true;
+}
+bool CreateLinkInner(wchar_t *filename, wchar_t *target, wchar_t *workdir, wchar_t *args,
+ wchar_t *comment, wchar_t *icon, UINT icon_index)
+{
+ HRESULT r;
+ bool ret;
+ IShellLinkW* pShellLink;
+ IPersistFile* pPersistFile;
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ char *a1, *a2, *a3, *a4, *a5, *a6;
+ a1 = CopyUniToStr(filename);
+ a2 = CopyUniToStr(target);
+ a3 = CopyUniToStr(workdir);
+ a4 = CopyUniToStr(args);
+ a5 = CopyUniToStr(icon);
+ a6 = CopyUniToStr(comment);
+
+ ret = CreateLinkInnerA(a1, a2, a3, a4, a6, a5, icon_index);
+
+ Free(a1);
+ Free(a2);
+ Free(a3);
+ Free(a4);
+ Free(a5);
+ Free(a6);
+
+ return ret;
+ }
+
+ r = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void **)&pShellLink);
+ if (FAILED(r))
+ {
+ return false;
+ }
+
+ r = pShellLink->QueryInterface(IID_IPersistFile,(void **)&pPersistFile);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ return false;
+ }
+
+ r = pShellLink->SetPath(target);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+
+ if (workdir != NULL)
+ {
+ r = pShellLink->SetWorkingDirectory(workdir);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (comment != NULL)
+ {
+ r = pShellLink->SetDescription(comment);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (args != NULL)
+ {
+ r = pShellLink->SetArguments(args);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ if (icon != NULL)
+ {
+ r = pShellLink->SetIconLocation(icon, icon_index);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+ }
+
+ r = pPersistFile->Save(filename, true);
+ if (FAILED(r))
+ {
+ pShellLink->Release();
+ pPersistFile->Release();
+ return false;
+ }
+
+ pShellLink->Release();
+ pPersistFile->Release();
+ return true;
+}
+
+extern "C"
+{
+
+// Show the folder selection dialog
+wchar_t *FolderDlgW(HWND hWnd, wchar_t *title, wchar_t *default_dir)
+{
+ wchar_t *ret;
+
+ if (MsIsNt() == false)
+ {
+ char *default_dir_a = CopyUniToStr(default_dir);
+ char *ret_a = FolderDlgA(hWnd, title, default_dir_a);
+
+ ret = CopyStrToUni(ret_a);
+ Free(ret_a);
+ Free(default_dir_a);
+
+ return ret;
+ }
+
+ ret = FolderDlgInnerW(hWnd, title, default_dir);
+
+ return ret;
+}
+char *FolderDlgA(HWND hWnd, wchar_t *title, char *default_dir)
+{
+ char *ret;
+
+ ret = FolderDlgInnerA(hWnd, title, default_dir);
+
+ return ret;
+}
+
+// Create a shortcut
+bool CreateLink(wchar_t *filename, wchar_t *target, wchar_t *workdir, wchar_t *args,
+ wchar_t *comment, wchar_t *icon, UINT icon_index)
+{
+ if (filename == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ return CreateLinkInner(filename, target, workdir, args, comment, icon, icon_index);
+}
+
+// Show the HTML
+void ShowHtml(HWND hWnd, char *url, wchar_t *option)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (url == NULL || option == NULL)
+ {
+ return;
+ }
+
+ StrToUni(tmp, sizeof(tmp), url);
+
+ ShowHTMLDialogFromURL(hWnd, tmp, NULL, option, NULL);
+}
+
+}
+
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Win32Com.h b/src/Cedar/Win32Com.h
new file mode 100644
index 00000000..abf3048d
--- /dev/null
+++ b/src/Cedar/Win32Com.h
@@ -0,0 +1,400 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32Com.h
+// Header of Win32Com.c
+
+#ifndef WIN32COM_H
+#define WIN32COM_H
+
+#ifdef WIN32COM_CPP
+
+// Internal function
+
+#endif // WIN32COM_CPP
+
+// For external function
+
+#pragma comment(lib,"htmlhelp.lib")
+#pragma comment(lib,"Urlmon.lib")
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+ void ShowHtml(HWND hWnd, char *url, wchar_t *option);
+ bool CreateLink(wchar_t *filename, wchar_t *target, wchar_t *workdir, wchar_t *args,
+ wchar_t *comment, wchar_t *icon, UINT icon_index);
+ wchar_t *FolderDlgW(HWND hWnd, wchar_t *title, wchar_t *default_dir);
+ char *FolderDlgA(HWND hWnd, wchar_t *title, char *default_dir);
+
+ bool InstallNdisProtocolDriver(wchar_t *inf_path, wchar_t *id, UINT lock_timeout);
+ bool Win32UPnPAddPort(UINT outside_port, UINT inside_port, bool udp, char *local_ip, wchar_t *description, bool remove_before_add);
+
+ //////////////////////////////////////////////////////////////////////////
+ //JumpList
+
+ //Application ID for VPN Client Manager
+ #define APPID_CM GC_UI_APPID_CM
+
+ typedef void* JL_PCustomDestinationList;
+ typedef void* JL_PObjectArray;
+ typedef void* JL_PShellLink;
+ typedef void* JL_PObjectCollection;
+ typedef long JL_HRESULT;
+
+ JL_HRESULT JL_CreateCustomDestinationList(JL_PCustomDestinationList* poc, wchar_t* appID);
+ JL_HRESULT JL_ReleaseCustomDestinationList(JL_PCustomDestinationList poc);
+
+ JL_HRESULT JL_BeginList(JL_PCustomDestinationList poc, JL_PObjectArray* oaRemoved);
+ JL_HRESULT JL_CommitList(JL_PCustomDestinationList cdl);
+
+
+ JL_HRESULT JL_CreateObjectCollection(JL_PObjectCollection* poc);
+ JL_HRESULT JL_ReleaseObjectCollection(JL_PObjectCollection poc);
+ JL_HRESULT JL_ObjectCollectionAddShellLink(JL_PObjectCollection poc, JL_PShellLink ppsl);
+
+ JL_HRESULT JL_AddCategoryToList(JL_PCustomDestinationList pcdl,
+ JL_PObjectCollection poc,
+ wchar_t* categoryName,
+ JL_PObjectArray poaRemoved);
+ JL_HRESULT JL_DeleteJumpList(JL_PCustomDestinationList jpcdl,wchar_t* appID);
+
+
+ JL_HRESULT JL_CreateShellLink(
+ wchar_t* pszPath,
+ wchar_t* pszArguments,
+ wchar_t* pszTitle,
+ wchar_t* iconLocation,
+ int iconIndex,
+ wchar_t* description, JL_PShellLink *ppsl);
+ JL_HRESULT JL_ReleaseShellLink(JL_PShellLink ppsl);
+
+
+ //SetApplicationID for Windows 7
+ JL_HRESULT JL_SetCurrentProcessExplicitAppUserModelID(wchar_t* appID);
+
+
+ //JL_HRESULT JL_AddTasksToList(JL_PCustomDestinationList pcdl, JL_PObjectCollection poc);
+
+ //////////////////////////////////////////////////////////////////////////
+ //DrawImage
+ //
+
+ #if defined(__cplusplus)
+
+typedef UCHAR ct_uchar;
+typedef char ct_char;
+
+#define ct_max(a,b) (((a) > (b)) ? (a): (b))
+#define ct_min(a,b) (((a) < (b)) ? (a): (b))
+#define ct_clamp(n,mi,ma) (ct_max(ct_min((n),(ma)),(mi)))
+#define ct_clamp01(n) ct_clamp(n,0,1)
+
+/**
+* Union representing 32-bit color with alpha channel.
+* CT_Color32, CT_AHSV32, CT_AYCbCr32 are also the same.
+*
+*/
+typedef union CT_ARGB32
+{
+public:
+
+ /** 32-bit integer intensity */
+ UINT ARGB;
+
+ /** RGB Color System */
+ struct
+ {
+ ct_uchar B;
+ ct_uchar G;
+ ct_uchar R;
+ ct_uchar A;
+ };
+
+ /** HSV Color System */
+ struct HSVA
+ {
+ ct_uchar V;
+ ct_uchar S;
+ ct_uchar H;
+ ct_uchar A;
+ }HSVA;
+
+ /** YCbCr Color System */
+ struct YCbCrA
+ {
+ ct_uchar Y;
+ ct_char Cb;
+ ct_char Cr;
+ ct_uchar A;
+ }YCbCrA;
+
+
+ /** Default constructor */
+ CT_ARGB32(){}
+
+ /** Constructor to initialize by specified color.
+ * @param a Alpha channel
+ * @param r Red, Hue, Cr
+ * @param g Green, Saturation, Cb
+ * @param b Blue, Value, Y
+ */
+ CT_ARGB32(ct_uchar a,ct_uchar r,ct_uchar g,ct_uchar b)
+ {
+ A = a;
+ R = r;
+ G = g;
+ B = b;
+ }
+
+
+
+}CT_ARGB32;
+
+
+class CT_Size
+{
+public:
+ int Width;
+ int Height;
+
+ CT_Size(int w, int h)
+ {
+ Width = w;
+ Height = h;
+ }
+};
+
+class CT_Rect
+{
+public:
+ int X;
+ int Y;
+ int Width;
+ int Height;
+
+ CT_Rect()
+ {
+ X = 0;
+ Y = 0;
+ Width = 0;
+ Height = 0;
+ }
+
+ CT_Rect(int x, int y,int w, int h)
+ {
+ X = x;
+ Y = y;
+ Width = w;
+ Height = h;
+ }
+
+ int Right(){return X + Width;}
+ int Bottom(){return Y + Height;}
+
+ void Right(int r){ Width = r - X;}
+ void Bottom(int b){ Height = b - Y;}
+
+};
+
+
+
+#endif //__cplusplus
+
+typedef struct CT_RectF_c
+{
+ float X;
+ float Y;
+ float Width;
+ float Height;
+} CT_RectF_c;
+
+void CT_DrawImage(UCHAR* dest, CT_RectF_c destRect, int destWidth, int destHeight,
+ UCHAR* src, CT_RectF_c srcRect, int srcWidth, int srcHeight);
+
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+//EXTERN_C const IID IID_IObjectCollection;
+//EXTERN_C const IID IID_ICustomDestinationList;
+
+#if defined(__cplusplus)
+
+
+#ifndef __IObjectArray_INTERFACE_DEFINED__
+#define __IObjectArray_INTERFACE_DEFINED__
+
+MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")
+IObjectArray : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetCount(
+ /* [out] */ __RPC__out UINT *pcObjects) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAt(
+ /* [in] */ UINT uiIndex,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+
+};
+
+MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295")
+IObjectCollection : public IObjectArray
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE AddObject(
+ /* [in] */ __RPC__in_opt IUnknown *punk) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddFromArray(
+ /* [in] */ __RPC__in_opt IObjectArray *poaSource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveObjectAt(
+ /* [in] */ UINT uiIndex) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Clear( void) = 0;
+
+};
+
+#endif // __IObjectArray_INTERFACE_DEFINED__
+
+#ifndef __ICustomDestinationList_INTERFACE_DEFINED__
+#define __ICustomDestinationList_INTERFACE_DEFINED__
+
+typedef /* [v1_enum] */
+enum KNOWNDESTCATEGORY
+{
+ KDC_FREQUENT = 1,
+ KDC_RECENT = ( KDC_FREQUENT + 1 )
+} KNOWNDESTCATEGORY;
+
+MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e")
+ICustomDestinationList : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetAppID(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszAppID) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginList(
+ /* [out] */ __RPC__out UINT *pcMinSlots,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AppendCategory(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszCategory,
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AppendKnownCategory(
+ /* [in] */ KNOWNDESTCATEGORY category) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddUserTasks(
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CommitList( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetRemovedDestinations(
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeleteList(
+ /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR pszAppID) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AbortList( void) = 0;
+
+};
+
+
+#endif // __ICustomDestinationList_INTERFACE_DEFINED__
+
+
+#endif //defined(__cplusplus)
+
+
+
+#endif // WIN32COM_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WinJumpList.cpp b/src/Cedar/WinJumpList.cpp
new file mode 100644
index 00000000..9ba6eeac
--- /dev/null
+++ b/src/Cedar/WinJumpList.cpp
@@ -0,0 +1,759 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WinJumpList.cpp
+// HTML display module source code for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+//#define NTDDI_WIN7 0x06010000
+//#define _WIN32_WINNT _WIN32_WINNT_VISTA
+//#define NTDDI_VERSION NTDDI_VISTA // Specifies that the minimum required platform is Windows 7.
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define STRICT_TYPED_ITEMIDS // Utilize strictly typed IDLists
+
+//#include <objectarray.h>
+#include <shobjidl.h>
+#include <propkey.h>
+#include <propvarutil.h>
+//#include <knownfolders.h>
+//#include <shlobj.h>
+
+
+#ifdef StrCpy
+#undef StrCpy
+#endif
+
+#ifdef StrCat
+#undef StrCat
+#endif
+
+#ifdef StrCmp
+#undef StrCmp
+#endif
+
+
+#define WIN32COM_CPP
+
+//#define _WIN32_WINNT 0x0502
+//#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <comdef.h>
+#include <Mshtmhst.h>
+//#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+
+extern "C"
+{
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+}
+#include "../PenCore/resource.h"
+
+extern "C"
+{
+
+ //////////////////////////////////////////////////////////////////////////
+ //JumpList
+ //#define NTDDI_WIN7 0x06010000
+ //#define NTDDI_VERSION NTDDI_WIN7 // Specifies that the minimum required platform is Windows 7.
+ //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+ //#define STRICT_TYPED_ITEMIDS // Utilize strictly typed IDLists
+ //
+ //
+ //#include <shobjidl.h>
+ //#include <propkey.h>
+ //#include <propvarutil.h>
+ //#include <knownfolders.h>
+ //#include <shlobj.h>
+ //
+ //#pragma comment(lib, "propsys.lib")
+ //#pragma comment(lib, "shlwapi.lib")
+
+ #define CREATE_PROPERTYKEY(l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
+
+
+ // Determines if the provided IShellItem is listed in the array of items that the user has removed
+ bool _IsItemInArray(IShellItem *psi, IObjectArray *poaRemoved)
+ {
+ bool fRet = false;
+ UINT cItems;
+ if (SUCCEEDED(poaRemoved->GetCount(&cItems)))
+ {
+ IShellItem *psiCompare;
+ for (UINT i = 0; !fRet && i < cItems; i++)
+ {
+ if (SUCCEEDED(poaRemoved->GetAt(i, IID_PPV_ARGS(&psiCompare))))
+ {
+ int iOrder;
+ fRet = SUCCEEDED(psiCompare->Compare(psi, SICHINT_CANONICAL, &iOrder)) && (0 == iOrder);
+ psiCompare->Release();
+ }
+ }
+ }
+ return fRet;
+ }
+
+
+ JL_HRESULT JL_CreateCustomDestinationList(JL_PCustomDestinationList* poc, wchar_t* appID)
+ {
+ ICustomDestinationList *pcdl;
+
+ //CLSID_DestinationList = 6332DEBF-87B5-4670-90C0-5E57-B408-A49E
+
+ GUID destList;
+
+ destList.Data1 = 2012286192;
+ destList.Data2 = 15797;
+ destList.Data3 = 18790;
+
+ destList.Data4[0] = 181;
+ destList.Data4[1] = 32;
+ destList.Data4[2] = 183;
+ destList.Data4[3] = 197;
+ destList.Data4[4] = 79;
+ destList.Data4[5] = 211;
+ destList.Data4[6] = 94;
+ destList.Data4[7] = 214;
+
+ //destList = CLSID_DestinationList;
+
+ //HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcdl));
+ HRESULT hr = CoCreateInstance(destList,
+ NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcdl));
+
+ if (SUCCEEDED(hr))
+ {
+ pcdl->SetAppID(appID);
+ (*poc) = (void*)pcdl;
+ }
+ else
+ {
+ (*poc) = NULL;
+ }
+
+ return hr;
+ }
+
+ JL_HRESULT JL_ReleaseCustomDestinationList(JL_PCustomDestinationList poc)
+ {
+ ICustomDestinationList *pcdl = (ICustomDestinationList*)poc;
+ if(pcdl != NULL)
+ {
+ pcdl->Release();
+ }
+
+ return 0;
+ }
+
+ JL_HRESULT JL_BeginList(JL_PCustomDestinationList poc, JL_PObjectArray* oaRemoved)
+ {
+ UINT cMinSlots;
+ IObjectArray *poaRemoved;
+
+ ICustomDestinationList *pcdl = (ICustomDestinationList*)poc;
+
+ HRESULT hr = pcdl->BeginList(&cMinSlots, IID_PPV_ARGS(&poaRemoved));
+
+ (*oaRemoved) = poaRemoved;
+
+ return hr;
+ }
+
+ JL_HRESULT JL_CommitList(JL_PCustomDestinationList cdl)
+ {
+ ICustomDestinationList *pcdl = (ICustomDestinationList*)cdl;
+
+ return pcdl->CommitList();
+ }
+
+
+ //JL_HRESULT JL_AddTasksToList(JL_PCustomDestinationList pcdl, JL_PObjectCollection poc)
+ //{
+ // return 0;
+ //}
+
+ JL_HRESULT JL_CreateObjectCollection(JL_PObjectCollection* jpoc)
+ {
+
+ //CLSID_EnumerableObjectCollection = 2D3468C1-36A7-43B6-AC24-D3F0-2FD9-607A
+
+
+ GUID enumObjCol;
+
+ enumObjCol.Data1 = 758409409;
+ enumObjCol.Data2 = 13991;
+ enumObjCol.Data3 = 17334;
+
+ enumObjCol.Data4[0] = 172;
+ enumObjCol.Data4[1] = 36;
+ enumObjCol.Data4[2] = 211;
+ enumObjCol.Data4[3] = 240;
+ enumObjCol.Data4[4] = 47;
+ enumObjCol.Data4[5] = 217;
+ enumObjCol.Data4[6] = 96;
+ enumObjCol.Data4[7] = 122;
+
+ //enumObjCol = CLSID_EnumerableObjectCollection;
+
+ IObjectCollection *poc;
+ //HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc));
+ HRESULT hr = CoCreateInstance(enumObjCol,
+ NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc));
+
+ if (SUCCEEDED(hr))
+ {
+ (*jpoc) = poc;
+ }
+ else{
+ (*jpoc) = NULL;
+ }
+ return hr;
+ }
+
+ JL_HRESULT JL_ReleaseObjectCollection(JL_PObjectCollection jpoc)
+ {
+ IObjectCollection *poc = (IObjectCollection *)jpoc;
+ if(poc != NULL)
+ {
+ return poc->Release();
+ }
+
+ return 0;
+ }
+
+ JL_HRESULT JL_ObjectCollectionAddShellLink(JL_PObjectCollection jpoc, JL_PShellLink jpsl)
+ {
+ IObjectCollection *poc = (IObjectCollection *)jpoc;
+ IShellLink *psl = (IShellLink *) jpsl;
+
+ return poc->AddObject(psl);
+
+ }
+
+
+ JL_HRESULT JL_AddCategoryToList(JL_PCustomDestinationList jpcdl,
+ JL_PObjectCollection jpoc,
+ wchar_t* categoryName,
+ JL_PObjectArray jpoaRemoved)
+ {
+ ICustomDestinationList *pcdl = (ICustomDestinationList*)jpcdl;
+ IObjectCollection *poc = (IObjectCollection *)jpoc;
+ IObjectArray *poaRemoved = (IObjectArray*)jpoaRemoved;
+
+ //for (UINT i = 0; i < ARRAYSIZE(c_rgpszFiles); i++)
+ //{
+ // IShellItem *psi;
+ // if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_Documents, KF_FLAG_DEFAULT, c_rgpszFiles[i], IID_PPV_ARGS(&psi))))
+ // {
+ // // Items listed in the removed list may not be re-added to the Jump List during this
+ // // list-building transaction. They should not be re-added to the Jump List until
+ // // the user has used the item again. The AppendCategory call below will fail if
+ // // an attempt to add an item in the removed list is made.
+ // if (!_IsItemInArray(psi, poaRemoved))
+ // {
+ // poc->AddObject(psi);
+ // }
+ // psi->Release();
+ // }
+ //}
+
+ IObjectArray *poa;
+ HRESULT hr = poc->QueryInterface(IID_PPV_ARGS(&poa));
+ if (SUCCEEDED(hr))
+ {
+
+ // Add the category to the Jump List. If there were more categories, they would appear
+ // from top to bottom in the order they were appended.
+ hr = pcdl->AppendCategory(categoryName, poa);
+ //hr = pcdl->AddUserTasks(poa);
+ poa->Release();
+
+ if (SUCCEEDED(hr))
+ {
+ }
+ else
+ {
+ Print("Failed AppendCategory\n");
+ }
+ }
+ else
+ {
+ Print("Failed QueryInterface\n");
+ }
+
+
+ return hr;
+ }
+
+
+
+ JL_HRESULT JL_CreateShellLink(
+ wchar_t* pszPath,
+ wchar_t* pszArguments,
+ wchar_t* pszTitle,
+ wchar_t* iconLocation,
+ int iconIndex,
+ wchar_t* description, JL_PShellLink *ppsl)
+ {
+ IShellLinkW *psl;
+ HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
+ if (SUCCEEDED(hr))
+ {
+ // Determine our executable's file path so the task will execute this application
+ //WCHAR szAppPath[MAX_PATH];
+ //if (GetModuleFileName(NULL, szAppPath, ARRAYSIZE(szAppPath)))
+ //{
+ //hr = psl->SetPath(L"C:\\Program Files\\PacketiX VPN Client\\vpncmgr.exe");
+ //hr = psl->SetArguments(L"50792311B00B9E01E7534AAA881087AB2BB83A1F");
+
+
+ psl->SetPath(pszPath);
+ psl->SetArguments(pszArguments);
+ if(iconLocation != NULL)
+ {
+ psl->SetIconLocation(iconLocation,iconIndex);
+ }
+
+ if(description != NULL)
+ {
+ psl->SetDescription(description);
+ }
+ if (SUCCEEDED(hr))
+ {
+ // The title property is required on Jump List items provided as an IShellLink
+ // instance. This value is used as the display name in the Jump List.
+ IPropertyStore *pps;
+ hr = psl->QueryInterface(IID_PPV_ARGS(&pps));
+ if (SUCCEEDED(hr))
+ {
+ PROPVARIANT propvar;
+ hr = InitPropVariantFromString(pszTitle, &propvar);
+ if (SUCCEEDED(hr))
+ {
+
+ ////PKEY_Title
+ //#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid)
+ //EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY name
+ // = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
+ //DEFINE_PROPERTYKEY(PKEY_Title, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2);
+
+ PROPERTYKEY pkey_title =
+ CREATE_PROPERTYKEY(0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2);
+
+
+ //hr = pps->SetValue(PKEY_Title, propvar);
+ hr = pps->SetValue(pkey_title, propvar);
+
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pps->Commit();
+ if (SUCCEEDED(hr))
+ {
+ IShellLink *tpsl;
+ hr = psl->QueryInterface(IID_PPV_ARGS(&tpsl));
+ (*ppsl) = tpsl;
+ }
+ }
+ PropVariantClear(&propvar);
+ }
+ pps->Release();
+ }
+ }
+
+ /*
+ hr = psl->SetPath(szAppPath);
+ if (SUCCEEDED(hr))
+ {
+ hr = psl->SetArguments(pszArguments);
+ if (SUCCEEDED(hr))
+ {
+ // The title property is required on Jump List items provided as an IShellLink
+ // instance. This value is used as the display name in the Jump List.
+ IPropertyStore *pps;
+ hr = psl->QueryInterface(IID_PPV_ARGS(&pps));
+ if (SUCCEEDED(hr))
+ {
+ PROPVARIANT propvar;
+ hr = InitPropVariantFromString(pszTitle, &propvar);
+ if (SUCCEEDED(hr))
+ {
+ hr = pps->SetValue(PKEY_Title, propvar);
+ if (SUCCEEDED(hr))
+ {
+ hr = pps->Commit();
+ if (SUCCEEDED(hr))
+ {
+ hr = psl->QueryInterface(IID_PPV_ARGS(ppsl));
+ }
+ }
+ PropVariantClear(&propvar);
+ }
+ pps->Release();
+ }
+ }
+ }
+ */
+ //}
+ //else
+ //{
+ // hr = HRESULT_FROM_WIN32(GetLastError());
+ //}
+ psl->Release();
+ }
+ return hr;
+ }
+
+ JL_HRESULT JL_ReleaseShellLink(JL_PShellLink jpsl)
+ {
+ IShellLink *psl = (IShellLink *) jpsl;
+
+ if(psl != NULL)
+ {
+ return psl->Release();
+ }
+
+ return 0;
+ }
+
+ // Removes that existing custom Jump List for this application.
+ JL_HRESULT JL_DeleteJumpList(JL_PCustomDestinationList jpcdl,wchar_t* appID)
+ {
+ ICustomDestinationList *pcdl = (ICustomDestinationList *)jpcdl;
+ //HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcdl));
+
+ HRESULT hr = pcdl->DeleteList(appID);
+
+
+ return hr;
+ }
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //SetApplicationID for Windows 7
+ JL_HRESULT JL_SetCurrentProcessExplicitAppUserModelID(wchar_t* appID)
+ {
+#ifdef UNICODE
+ HMODULE hModule = LoadLibraryW( L"shell32.dll");
+#else
+ HMODULE hModule = LoadLibraryA( "shell32.dll");
+#endif
+ HRESULT (__stdcall *SetAppID) (PCWSTR);
+
+ if( hModule == NULL )
+ {
+ //// Load failure (there is no DLL)
+ // MessageBoxW( NULL, L"shell32.dll not found", L"Error", MB_OK );
+ Print("Not Found shell32.dll");
+ }
+ else
+ {
+ // Get the address of the function in the DLL
+ SetAppID = (HRESULT (__stdcall *)(PCWSTR))
+ GetProcAddress( hModule, "SetCurrentProcessExplicitAppUserModelID" );
+ if( SetAppID != NULL )
+ {
+ FreeLibrary( hModule );
+ return SetAppID(appID);
+ }
+ else
+ {
+ //MessageBoxW( NULL, L"There may not be a function", L"Error", MB_OK );
+ Print("Not Found SetCurrentProcessExplicitAppUserModelID");
+
+ }
+
+ // Release the loaded DLL
+ FreeLibrary( hModule );
+ }
+ return 0;
+
+
+ }
+
+
+
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// Size Rect
+//
+
+CT_Rect GetBoundingRect(CT_RectF_c* rect)
+{
+ CT_Rect r = CT_Rect((int)rect->X,(int)rect->Y,(int)rect->Width,(int)rect->Height);
+ if(r.Right() < (rect->X + rect->Width))
+ r.Width+=1;
+ if(r.Bottom() < (rect->Y + rect->Height))
+ r.Height+=1;
+
+ return r;
+}
+
+
+CT_ARGB32 CT_GetAAPix32(UCHAR* srcPtr, int width, int height, int xFix, int yFix);
+
+//////////////////////////////////////////////////////////////////////////
+// DrawImage method
+void CT_DrawImage(UCHAR* dest, CT_RectF_c destRect, int destWidth, int destHeight,
+ UCHAR* src, CT_RectF_c srcRect, int srcWidth, int srcHeight)
+{
+
+ double scaleW = destRect.Width / srcRect.Width;
+ double scaleH = destRect.Height / srcRect.Height;
+
+
+ CT_ARGB32* dest32 = (CT_ARGB32*)(dest);
+ CT_ARGB32* src32 = (CT_ARGB32*)(src);
+
+ float dfx = (float)(1 / scaleW);
+ float dfy = (float)(1 / scaleH);
+
+ float srcSX = srcRect.X;
+ float srcSY = srcRect.Y;
+
+ int srcSXFix = (int)(srcSX*65536);
+ int srcSYFix = (int)(srcSY*65536);
+ int dfxFix = (int)(dfx*65536);
+ int dfyFix = (int)(dfy*65536);
+
+ //CT_Rect dRect = destRect.GetBoundingRect();
+
+ CT_Rect dRect = GetBoundingRect(&destRect);
+
+ // Clipping not supported: ToDo
+ dRect.X = ct_max(0,dRect.X);
+ dRect.Y = ct_max(0,dRect.Y);
+ dRect.Right((int)ct_min(destRect.X + destRect.Width,dRect.Right()));
+ dRect.Bottom((int)ct_min(destRect.Y + destRect.Height,dRect.Bottom()));
+
+ //CT_ARGB32* dPix = dest32->GetPixelAddressNC(dRect.X, dRect.Y);
+ CT_ARGB32* dPix = &(dest32[destWidth*dRect.Y + dRect.X]);
+
+ //int dpW = dest32->GetWidth() - dRect.Width;
+ int dpW = destWidth - dRect.Width;
+ for (int dy = dRect.Y; dy < dRect.Bottom(); dy++)
+ {
+
+ int syFix = srcSYFix;
+ int sxFix = srcSXFix;
+
+ // Anti-aliasing
+ for (int dx = dRect.X; dx < dRect.Right(); dx++)
+ {
+ int rPixX = ( ((sxFix >> 15) & 0x00000001) == 1) ? (sxFix >> 16)+1 : (sxFix >> 16);
+ int rPixY = ( ((syFix >> 15) & 0x00000001) == 1) ? (syFix >> 16)+1 : (syFix >> 16);
+
+ //CT_ARGB32* sPix = &(src32[rPixY * srcWidth + rPixX]);
+
+ //*dPix = *sPix;
+ //if(sPix != NULL)
+ {
+ //*dPix = src32->GetAAPix32(sxFix,syFix);
+ *dPix = CT_GetAAPix32((UCHAR*)src32, srcWidth, srcHeight,sxFix, syFix);
+ }
+
+ sxFix += dfxFix;
+ dPix++;
+ }
+
+
+ srcSYFix += dfyFix;
+ dPix += dpW;
+ }
+
+}
+
+bool isWhiteColor(CT_ARGB32 col)
+{
+ return
+ (col.R == 255 &&
+ col.G == 255 &&
+ col.B == 255);
+}
+
+
+CT_ARGB32 CT_GetAAPix32(UCHAR* srcPtr, int width, int height, int xFix, int yFix)
+{
+
+ //return CT_ARGB32(255,255,255,255);
+
+ //CT_Bitmap32* src = this;
+ CT_ARGB32* src = (CT_ARGB32*)(srcPtr);
+
+ int fixx = xFix;
+ int fixy = yFix;
+
+ int fx = (fixx >> 8) & 0xFF;
+ int fy = (fixy >> 8) & 0xFF;
+
+ int f[4];
+ f[0] = ((255 - fx) * (255 - fy)) >> 8;
+ f[1] = (fx * (255 - fy)) >> 8;
+ f[2] = ((255 - fx) * fy) >> 8;
+ f[3] = (fx * fy) >> 8;
+
+ int px = fixx >> 16;
+ int py = fixy >> 16;
+
+ int a, r, g, b;
+ a = r = g = b = 0;
+ CT_Size size = CT_Size(width, height);
+ CT_ARGB32 col = CT_ARGB32(0,255,255,255);
+
+ CT_ARGB32 pixs[4];
+ for(int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ int sx = px + i;
+ int sy = py + j;
+
+ CT_ARGB32* c;
+
+ if(sx < 0 || sx >= width || sy < 0 || sy >= height)
+ {
+ c = &col;
+ }
+ else
+ {
+ //c = src->GetPixelAddressNC(sx, sy);
+ c = &(src[sy * width + sx]);
+ }
+ pixs[j*2+i] = *c;
+
+ a += c->A * f[j*2 + i];
+ r += c->R * f[j*2 + i];
+ g += c->G * f[j*2 + i];
+ b += c->B * f[j*2 + i];
+
+ }
+ }
+
+ bool isAllWhite = true;
+ for(int k = 0; k < 4; k++)
+ {
+ if(!isWhiteColor(pixs[k]))
+ {
+ isAllWhite = false;
+ break;
+ }
+ }
+
+ if(isAllWhite)
+ {
+ //
+ return CT_ARGB32(0, 255, 255, 255);
+ }
+ else
+ {
+ a = a >> 8;
+ r = r >> 8;
+ g = g >> 8;
+ b = b >> 8;
+
+ return CT_ARGB32(a, r, g, b);
+ }
+
+}
+
+//
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WinUi.c b/src/Cedar/WinUi.c
new file mode 100644
index 00000000..0cdf6ff8
--- /dev/null
+++ b/src/Cedar/WinUi.c
@@ -0,0 +1,11339 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WinUi.c
+// User interface code for Win32
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define WINUI_C
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <Iphlpapi.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "../PenCore/resource.h"
+
+char cached_pin_code[MAX_SIZE] = {0};
+UINT64 cached_pin_code_expires = 0;
+
+static HINSTANCE hDll = NULL;
+static wchar_t *title_bar = NULL;
+static char *font_name = NULL;
+static UINT font_size = 9;
+static HIMAGELIST large_image_list = NULL, small_image_list = NULL;
+static LIST *icon_list = NULL;
+static HINSTANCE hMsHtml = NULL;
+static UINT init_winui_counter = 0;
+static HDC hCommonDC = NULL;
+static LOCK *lock_common_dc = NULL;
+
+bool UseAlpha = false;
+UINT AlphaValue = 100;
+
+static THREAD *led_thread = NULL;
+static bool thread_stop = false;
+static bool g_led_special = false;
+static bool g_tcpip_topmost = false;
+static DWORD tls_current_wizard = 0xFFFFFFFF;
+
+#define WINUI_PSM_SHOWWIZBUTTONS (WM_USER + 138)
+#define WINUI_PropSheet_ShowWizButtons(hDlg, dwFlag, dwButton) \
+ PSTMSG(hDlg, WINUI_PSM_SHOWWIZBUTTONS, (WPARAM)(dwFlag), (LPARAM)(dwButton))
+
+typedef struct _WINUI_SHSTOCKICONINFO
+{
+ DWORD cbSize;
+ HICON hIcon;
+ int iSysImageIndex;
+ int iIcon;
+ WCHAR szPath[MAX_PATH];
+} WINUI_SHSTOCKICONINFO;
+
+// Get whether the current process is foreground
+bool IsThisProcessForeground()
+{
+ HWND hWnd = GetForegroundWindow();
+ DWORD proc_id, thread_id;
+
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ proc_id = 0;
+ thread_id = GetWindowThreadProcessId(hWnd, &proc_id);
+
+ if (proc_id == MsGetCurrentProcessId())
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsThisProcessForegroundForUpdateUi(UPDATE_CLIENT *c, void *p)
+{
+ return IsThisProcessForeground();
+}
+
+// Update notification screen dialog procedure
+UINT UpdateConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINUI_UPDATE *u = (WINUI_UPDATE *)param;
+ UPDATE_CLIENT_SETTING s;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetTimer(hWnd, 1, 100, NULL);
+
+ LoadUpdateUiSetting(u, &s);
+
+ Check(hWnd, S_ENABLE, s.DisableCheck == false);
+ Check(hWnd, S_DISBLE, s.DisableCheck);
+
+ DlgFont(hWnd, S_TITLE, 10, true);
+ FormatText(hWnd, S_TITLE, u->SoftwareTitle);
+ FormatText(hWnd, S_INFO, u->SoftwareTitle);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (u->UpdateClient->HaltFlag)
+ {
+ goto LABEL_CLOSE;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+LABEL_CLOSE:
+ LoadUpdateUiSetting(u, &s);
+
+ s.DisableCheck = IsChecked(hWnd, S_DISBLE);
+
+ if (s.DisableCheck)
+ {
+ s.LatestIgnoreBuild = 0;
+ }
+
+ SaveUpdateUiSetting(u, &s);
+
+ SetUpdateClientSetting(u->UpdateClient, &s);
+
+ EndDialog(hWnd, !s.DisableCheck);
+
+ break;
+ }
+
+ return 0;
+}
+
+// Show the update notification setting screen
+bool ConfigUpdateUi(WINUI_UPDATE *u, HWND hWnd)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return false;
+ }
+
+ return Dialog(hWnd, D_UPDATE_CONFIG, UpdateConfigDlgProc, u);
+}
+
+// Update notification dialog procedure
+UINT UpdateNoticeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINUI_UPDATE_DLG_PARAM *p = (WINUI_UPDATE_DLG_PARAM *)param;
+ WINUI_UPDATE *u = NULL;
+ UPDATE_CLIENT_SETTING s;
+ char date_current[64];
+ char date_latest[64];
+ wchar_t date_current_str[128];
+ wchar_t date_latest_str[128];
+ char *font_name = NULL;
+
+ if (p != NULL)
+ {
+ u = p->Update;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ Zero(date_current_str, sizeof(date_current_str));
+ Zero(date_latest_str, sizeof(date_latest_str));
+
+ GetDateStr64(date_current, sizeof(date_current), u->CurrentDate);
+ if (u->CurrentDate != 0)
+ {
+ UniFormat(date_current_str, sizeof(date_current_str), _UU("DLG_UPDATE_DATE"), date_current);
+ }
+
+ GetDateStr64(date_latest, sizeof(date_latest), p->LatestDate);
+ if (p->LatestDate != 0)
+ {
+ UniFormat(date_latest_str, sizeof(date_latest_str), _UU("DLG_UPDATE_DATE"), date_latest);
+ }
+
+ FormatText(hWnd, 0, u->UpdateClient->SoftwareTitle);
+ FormatText(hWnd, S_INFO, u->UpdateClient->SoftwareTitle);
+ SetText(hWnd, S_PRODUCT_STR, u->UpdateClient->SoftwareTitle);
+
+ FormatText(hWnd, S_CURRENT_STR, u->CurrentVer / 100, u->CurrentVer % 100, u->CurrentBuild, date_current_str);
+ FormatText(hWnd, S_LATEST_STR, p->LatestVer, date_latest_str);
+
+ if (MsIsWindows7())
+ {
+ if (_GETLANG() == 0)
+ {
+ font_name = GetMeiryoFontName();
+ }
+ else if (_GETLANG() == 2)
+ {
+ font_name = "Microsoft YaHei";
+ }
+ }
+
+ SetFont(hWnd, S_INFO, GetFont(font_name, 11, false, false, false, false));
+ SetFont(hWnd, IDOK, GetFont(font_name, 0, true, false, false, false));
+ SetFont(hWnd, IDCANCEL, GetFont(font_name, 0, false, false, false, false));
+ SetFont(hWnd, S_PRODUCT_STR, GetFont(font_name, 10, true, false, false, false));
+ SetFont(hWnd, S_CURRENT_STR, GetFont(font_name, 10, true, false, false, false));
+ SetFont(hWnd, S_LATEST_STR, GetFont(font_name, 10, true, false, false, false));
+
+ SetFont(hWnd, S_PRODUCT, GetFont(font_name, 0, false, false, false, false));
+ SetFont(hWnd, S_CURRENT, GetFont(font_name, 0, false, false, false, false));
+ SetFont(hWnd, S_LATEST, GetFont(font_name, 0, false, false, false, false));
+ SetFont(hWnd, B_CONFIG, GetFont(font_name, 0, false, false, false, false));
+
+ SetTimer(hWnd, 1, 100, NULL);
+
+ //MessageBeep(MB_ICONASTERISK);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK: // Web View
+ OnceMsgEx(hWnd, NULL, _UU("DLG_UPDATE_HINT"), true, ICO_INTERNET, (bool *)p->halt_flag);
+
+ ShellExecuteA(hWnd, "open", p->Url, NULL, NULL, SW_SHOWNORMAL);
+ SleepThread(250);
+
+ // Ignore the update notification of this version for future
+ LoadUpdateUiSetting(u, &s);
+ s.LatestIgnoreBuild = p->LatestBuild;
+ SaveUpdateUiSetting(u, &s);
+
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL: // Ignore this version
+ LoadUpdateUiSetting(u, &s);
+ s.LatestIgnoreBuild = p->LatestBuild;
+ SaveUpdateUiSetting(u, &s);
+ Close(hWnd);
+ break;
+
+ case B_CONFIG: // Show the notification settings screen
+ p->IsInConfigDialog = true;
+
+ if (ConfigUpdateUi(u, hWnd) == false)
+ {
+ // Decided not to notify any more as a result of setting
+ Close(hWnd);
+ }
+
+ p->IsInConfigDialog = false;
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (p->IsInConfigDialog == false)
+ {
+ if (*(p->halt_flag))
+ {
+ // Close the screen forcibly
+ EndDialog(hWnd, 0);
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE: // Close
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Update notification dialog
+void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param)
+{
+ WINUI_UPDATE *u = (WINUI_UPDATE *)param;
+ WINUI_UPDATE_DLG_PARAM p;
+ // Validate arguments
+ if (c == NULL || latest_build == 0 || latest_date == 0 || latest_ver == NULL || url == NULL || halt_flag == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // Show the update screen
+ Zero(&p, sizeof(p));
+
+ p.Update = u;
+ p.LatestBuild = latest_build;
+ p.LatestDate = latest_date;
+ p.LatestVer = latest_ver;
+ p.Url = url;
+ p.halt_flag = halt_flag;
+
+ Dialog(NULL, D_UPDATE_NOTICE, UpdateNoticeDlgProc, &p);
+}
+
+// Initialize the update notification
+WINUI_UPDATE *InitUpdateUi(wchar_t *title, char *name, char *family_name, UINT64 current_date, UINT current_build, UINT current_ver, char *client_id)
+{
+ WINUI_UPDATE *u;
+ UPDATE_CLIENT_SETTING s;
+ LANGLIST t;
+ // Validate arguments
+ if (title == NULL || name == NULL || current_build == 0 || current_ver == 0)
+ {
+ return NULL;
+ }
+ if (IsEmptyStr(family_name))
+ {
+ family_name = UPDATE_FAMILY_NAME;
+ }
+
+ u = ZeroMalloc(sizeof(WINUI_UPDATE));
+
+ StrCpy(u->ClientId, sizeof(u->ClientId), client_id);
+ UniStrCpy(u->SoftwareTitle, sizeof(u->SoftwareTitle), title);
+ StrCpy(u->SoftwareName, sizeof(u->SoftwareName), name);
+ u->CurrentDate = current_date;
+ u->CurrentBuild = current_build;
+ u->CurrentVer = current_ver;
+
+ Format(u->RegKey, sizeof(u->RegKey), WINUI_UPDATE_REGKEY, u->SoftwareName);
+
+ Zero(&s, sizeof(s));
+ LoadUpdateUiSetting(u, &s);
+
+ Zero(&t, sizeof(t));
+ GetCurrentLang(&t);
+
+ u->UpdateClient = NewUpdateClient(UpdateNotifyProcUi, IsThisProcessForegroundForUpdateUi, u, family_name, u->SoftwareName, u->SoftwareTitle,
+ u->CurrentBuild, u->CurrentDate, t.Name, &s, client_id);
+
+ if (u->UpdateClient == NULL)
+ {
+ Free(u);
+ return NULL;
+ }
+
+ return u;
+}
+
+// Release the update notification
+void FreeUpdateUi(WINUI_UPDATE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ if (u->UpdateClient != NULL)
+ {
+ FreeUpdateClient(u->UpdateClient);
+ }
+
+ Free(u);
+}
+
+// Read the current settings from the registry
+void LoadUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
+{
+ Zero(s, sizeof(UPDATE_CLIENT_SETTING));
+ // Validate arguments
+ if (u == NULL || s == NULL)
+ {
+ return;
+ }
+
+ s->DisableCheck = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "DisableCheck");
+ s->LatestIgnoreBuild = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild");
+}
+
+// Write the current settings to the registry
+void SaveUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
+{
+ // Validate arguments
+ if (u == NULL || s == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "DisableCheck", s->DisableCheck);
+ MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild", s->LatestIgnoreBuild);
+}
+
+// Set the UAC icon to the control in the dialog
+void SetUacIcon(HWND hWnd, UINT id)
+{
+ static HINSTANCE hShell32 = NULL;
+ static HRESULT (__stdcall *_SHGetStockIconInfo)(UINT siid, UINT uFlags, void *psii) = NULL;
+ bool ok = false;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (MsIsVista() == false)
+ {
+ goto LABEL_FAILED;
+ }
+
+ if (hShell32 == NULL)
+ {
+ hShell32 = LoadLibraryA("shell32.dll");
+ }
+
+ if (hShell32 != NULL)
+ {
+ if (_SHGetStockIconInfo == NULL)
+ {
+ _SHGetStockIconInfo = (HRESULT (__stdcall *)(UINT,UINT,void *))GetProcAddress(hShell32, "SHGetStockIconInfo");
+ }
+ }
+
+ if (_SHGetStockIconInfo != NULL)
+ {
+ WINUI_SHSTOCKICONINFO sii;
+
+ Zero(&sii, sizeof(sii));
+
+ sii.cbSize = sizeof(sii);
+ if (_SHGetStockIconInfo(77, 0x000000100 | 0x000000001, &sii) == S_OK)
+ {
+ SendMessage(DlgItem(hWnd, id), STM_SETICON, (WPARAM)sii.hIcon, 0);
+
+ ok = true;
+ }
+ }
+
+ if (ok)
+ {
+ return;
+ }
+
+LABEL_FAILED:
+
+ Hide(hWnd, id);
+}
+
+// Procedure of the wizard page
+UINT CALLBACK WizardPageDefDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DIALOG_PARAM *dp = (DIALOG_PARAM *)GetParam(hWnd);
+ WIZARD_PAGE *wizard_page = NULL;
+ WIZARD *wizard = NULL;
+ UINT ret_value = 0;
+ bool do_not_send_msg = false;
+
+ if (dp != NULL)
+ {
+ wizard_page = dp->wizard_page;
+ wizard = wizard_page->Wizard;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ PROPSHEETPAGEW_V3 *t = (PROPSHEETPAGEW_V3 *)lParam;
+ dp = (DIALOG_PARAM *)t->lParam;
+ wizard_page = dp->wizard_page;
+ wizard = wizard_page->Wizard;
+
+ wizard->hWndWizard = GetParent(hWnd);
+ wizard_page->hWndPage = hWnd;
+
+ SetParam(hWnd, dp);
+
+ InitDialogInternational(hWnd, dp);
+ }
+ break;
+
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ return (UINT)GetStockObject(WHITE_BRUSH);
+ break;
+
+ case WM_NOTIFY:
+ {
+ NMHDR *pnmh = (NMHDR *)lParam;
+ UINT ret = 0;
+ UINT next_page = INFINITE;
+
+ switch (pnmh->code)
+ {
+ case PSN_SETACTIVE: // Activate
+ SetWizardButton(wizard_page, true, true, true, false);
+ dp->wizard_proc(hWnd, WM_WIZ_SHOW, 0, 0, wizard, wizard_page, wizard->Param);
+ break;
+
+ case PSN_KILLACTIVE: // Deactivate
+ dp->wizard_proc(hWnd, WM_WIZ_HIDE, 0, 0, wizard, wizard_page, wizard->Param);
+ break;
+
+ case PSN_WIZNEXT: // Determine the destination of [Next] button
+ ret = dp->wizard_proc(hWnd, WM_WIZ_NEXT, 0, 0, wizard, wizard_page, wizard->Param);
+ do_not_send_msg = true;
+
+ if (ret == 0)
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
+ }
+ else
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
+ }
+
+ ret_value = 1;
+ break;
+
+ case PSN_WIZBACK: // Determine the destination of [back] button
+ ret = dp->wizard_proc(hWnd, WM_WIZ_BACK, 0, 0, wizard, wizard_page, wizard->Param);
+ do_not_send_msg = true;
+
+ if (ret == 0)
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
+ }
+ else
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
+ }
+
+ ret_value = 1;
+ break;
+
+ case PSN_QUERYCANCEL: // Determine the process of the [Cancel] button
+ if (dp->wizard_page->EnableClose == false)
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
+ }
+ else
+ {
+
+ ret = dp->wizard_proc(hWnd, WM_WIZ_CLOSE, 0, 0, wizard, wizard_page, wizard->Param);
+
+ if (ret == 0)
+ {
+ if (IsEmptyUniStr(wizard->CloseConfirmMsg) == false &&
+ MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, wizard->CloseConfirmMsg) == IDNO)
+ {
+ ret = 1;
+ }
+ }
+
+ if (ret == 0)
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, 0);
+ }
+ else
+ {
+ SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
+ }
+ }
+ ret_value = 1;
+ do_not_send_msg = true;
+ break;
+ }
+ break;
+ }
+ }
+
+ if (do_not_send_msg == false)
+ {
+ if (dp != NULL)
+ {
+ UINT ret = dp->wizard_proc(hWnd, msg, wParam, lParam, wizard, wizard_page, wizard->Param);
+
+ if (ret != 0)
+ {
+ ret_value = ret;
+ }
+ }
+ }
+
+ if (msg == WM_INITDIALOG)
+ {
+ if (wizard->SetCenterFlag == false)
+ {
+ wizard->SetCenterFlag = true;
+
+ Center(wizard->hWndWizard);
+ }
+
+ SetForegroundWindow(wizard->hWndWizard);
+ SetActiveWindow(wizard->hWndWizard);
+ }
+
+ return ret_value;
+}
+
+// Button setting of the wizard
+void SetWizardButton(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish)
+{
+ SetWizardButtonEx(p, enable_next, enable_back, enable_close, is_finish, false);
+}
+void SetWizardButtonEx(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish, bool shield_icon)
+{
+ DWORD flags = 0;
+ DWORD flags2 = 0;
+ DWORD flags3 = 0;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->EnableNext = enable_next;
+ p->EnableBack = enable_back;
+ p->EnableClose = enable_close;
+ p->IsFinish = is_finish;
+
+ if (is_finish == false)
+ {
+ if (p->EnableNext)
+ {
+ flags |= PSWIZB_NEXT;
+ flags2 |= PSWIZB_NEXT;
+
+ if (shield_icon)
+ {
+ if (p->Wizard->IsAreoStyle)
+ {
+ if (MsIsAdmin() == false)
+ {
+ flags3 |= PSWIZBF_ELEVATIONREQUIRED;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (p->EnableNext)
+ {
+ flags |= PSWIZB_FINISH;
+ flags2 |= PSWIZB_FINISH;
+ }
+ else
+ {
+ flags |= PSWIZB_DISABLEDFINISH;
+ flags2 |= PSWIZB_FINISH;
+ }
+ }
+
+ if (p->EnableBack)
+ {
+ flags |= PSWIZB_BACK;
+ flags2 |= PSWIZB_BACK;
+ }
+
+ if (p->EnableClose)
+ {
+ flags2 |= 0x00000010;
+ }
+
+ PostMessage(p->Wizard->hWndWizard, PSM_SETWIZBUTTONS, flags3, flags);
+
+ SetEnable(p->Wizard->hWndWizard, IDCANCEL, p->EnableClose);
+
+ WINUI_PropSheet_ShowWizButtons(p->Wizard->hWndWizard,
+ flags2, PSWIZB_BACK | PSWIZB_NEXT | PSWIZB_FINISH | 0x00000010);
+
+ if (p->EnableClose)
+ {
+ EnableClose(p->Wizard->hWndWizard);
+ }
+ else
+ {
+ DisableClose(p->Wizard->hWndWizard);
+ }
+}
+
+LRESULT CALLBACK WizardCustomizedWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
+
+ if (wizard != NULL)
+ {
+ switch (msg)
+ {
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ return (UINT)GetStockObject(WHITE_BRUSH);
+ break;
+ }
+
+ if (MsIsNt())
+ {
+ return CallWindowProcW(wizard->OriginalWindowProc, hWnd, msg, wParam, lParam);
+ }
+ else
+ {
+ return CallWindowProcA(wizard->OriginalWindowProc, hWnd, msg, wParam, lParam);
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Procedure of the wizard
+UINT CALLBACK WizardDlgProc(HWND hWnd, UINT msg, LPARAM lParam)
+{
+ WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
+ switch (msg)
+ {
+ case PSCB_INITIALIZED:
+ if (wizard != NULL)
+ {
+ if (wizard->hWndWizard != NULL)
+ {
+ wizard->hWndWizard = hWnd;
+ }
+
+ if (wizard->ReplaceWindowProcFlag == false)
+ {
+ wizard->ReplaceWindowProcFlag = true;
+
+ if (MsIsNt())
+ {
+ wizard->OriginalWindowProc = (void *)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
+ }
+ else
+ {
+ wizard->OriginalWindowProc = (void *)GetWindowLongPtrA(hWnd, GWLP_WNDPROC);
+ }
+
+ if (wizard->OriginalWindowProc != NULL)
+ {
+ if (MsIsNt())
+ {
+ SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)WizardCustomizedWindowProc);
+ }
+ else
+ {
+ SetWindowLongPtrA(hWnd, GWLP_WNDPROC, (LONG_PTR)WizardCustomizedWindowProc);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Jump to another wizard page
+void JumpWizard(WIZARD_PAGE *p, UINT next_id)
+{
+ // Validate arguments
+ if (p == NULL || next_id == 0)
+ {
+ return;
+ }
+
+ PropSheet_SetCurSelByID(p->Wizard->hWndWizard, next_id);
+}
+
+// Close the wizard
+void CloseWizard(WIZARD_PAGE *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->Wizard->CloseConfirmMsg = NULL;
+ SetWizardButton(p, false, false, true, false);
+
+ if (p->Wizard->IsAreoStyle)
+ {
+ PropSheet_PressButton(p->hWndPage, PSBTN_CANCEL);
+ }
+ else
+ {
+ Close(p->Wizard->hWndWizard);
+ }
+}
+
+// Show the wizard
+void ShowWizard(HWND hWndParent, WIZARD *w, UINT start_id)
+{
+ void **pages_array;
+ UINT num_pages;
+ UINT i;
+ PROPSHEETHEADERW_V2 h;
+ WIZARD_PAGE *start_page;
+ // Validate arguments
+ if (w == NULL)
+ {
+ return;
+ }
+
+ num_pages = LIST_NUM(w->Pages);
+ pages_array = ZeroMalloc(sizeof(void *) * num_pages);
+
+ for (i = 0;i < num_pages;i++)
+ {
+ WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
+
+ pages_array[i] = CreateWizardPageInstance(w, p);
+
+ p->Index = i;
+ }
+
+ Zero(&h, sizeof(h));
+ h.dwSize = sizeof(PROPSHEETHEADERW_V2);
+ h.dwFlags = PSH_WIZARD97 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
+
+ if (MsIsVista() == false)
+ {
+ // Aero Wizard is unavailable in pre-Vista
+ w->IsAreoStyle = false;
+ }
+
+ if (MsIsAeroColor() == false)
+ {
+ // Aero Wizard can not be used If the color of Aero is disabled
+ // even in Vista or later (if the background color is not white)
+ w->IsAreoStyle = false;
+ }
+
+ if (w->IsAreoStyle)
+ {
+ // Aero Wizard
+ h.dwFlags = PSH_WIZARD | 0x00004000 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
+ }
+
+ h.hInstance = hDll;
+ h.pszIcon = MAKEINTRESOURCEW(w->Icon);
+ h.hwndParent = hWndParent;
+ h.nPages = num_pages;
+ h.phpage = (HPROPSHEETPAGE *)pages_array;
+ h.pszbmHeader = MAKEINTRESOURCEW(w->Bitmap);
+ h.pszCaption = w->Caption;
+ h.pfnCallback = WizardDlgProc;
+
+ start_page = GetWizardPage(w, start_id);
+ if (start_page != NULL)
+ {
+ h.nStartPage = start_page->Index;
+ }
+
+ w->hWndParent = hWndParent;
+ w->hWndWizard = NULL;
+ w->SetCenterFlag = false;
+
+ TlsSetValue(tls_current_wizard, w);
+
+ PropertySheetW(&h);
+
+ TlsSetValue(tls_current_wizard, NULL);
+
+ Free(pages_array);
+}
+
+// Create an instance of the wizard page
+void *CreateWizardPageInstance(WIZARD *w, WIZARD_PAGE *p)
+{
+ PROPSHEETPAGEW_V3 t;
+ // Validate arguments
+ if (w == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.dwSize = sizeof(PROPSHEETPAGEW_V3);
+ t.dwFlags = PSP_USETITLE | PSP_USEHEADERTITLE;// | PSP_USEHEADERSUBTITLE;
+ t.hInstance = hDll;
+ t.pszTemplate = MAKEINTRESOURCEW(p->Id);
+ t.pfnDlgProc = (DLGPROC)WizardPageDefDlgProc;
+ t.pszHeaderTitle = p->Title;
+ t.pszTitle = w->Caption;
+
+ if (p->DialogParam != NULL)
+ {
+ FreeBitmapList(p->DialogParam->BitmapList);
+ Free(p->DialogParam);
+ }
+
+ p->DialogParam = ZeroMalloc(sizeof(DIALOG_PARAM));
+
+ p->DialogParam->BitmapList = NewBitmapList();
+ p->DialogParam->wizard = w;
+ p->DialogParam->wizard_page = p;
+ p->DialogParam->wizard_proc = p->Proc;
+ p->DialogParam->param = w->Param;
+ p->DialogParam->white = false;
+ p->DialogParam->meiryo = false;
+
+ t.lParam = (LPARAM)p->DialogParam;
+
+ return CreatePropertySheetPageW(&t);
+}
+
+// Create a new wizard
+WIZARD *NewWizard(UINT icon, UINT bitmap, wchar_t *caption, void *param)
+{
+ WIZARD *w = ZeroMalloc(sizeof(WIZARD));
+
+ w->Icon = icon;
+ w->Pages = NewList(NULL);
+ w->Param = param;
+ w->Bitmap = bitmap;
+ w->Caption = CopyUniStr(caption);
+
+ return w;
+}
+
+// Release the wizard
+void FreeWizard(WIZARD *w)
+{
+ UINT i;
+ // Validate arguments
+ if (w == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(w->Pages);i++)
+ {
+ WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
+
+ FreeWizardPage(p);
+ }
+
+ ReleaseList(w->Pages);
+
+ Free(w->Caption);
+
+ Free(w);
+}
+
+// Get the index page of the wizard
+UINT GetWizardPageIndex(WIZARD *w, UINT id)
+{
+ WIZARD_PAGE *p;
+ // Validate arguments
+ if (w == NULL || id == 0)
+ {
+ return INFINITE;
+ }
+
+ p = GetWizardPage(w, id);
+ if (p == NULL)
+ {
+ return INFINITE;
+ }
+
+ return p->Index;
+}
+
+// Get the wizard page
+WIZARD_PAGE *GetWizardPage(WIZARD *w, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (w == NULL || id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(w->Pages);i++)
+ {
+ WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
+
+ if (p->Id == id)
+ {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+// Add a wizard page
+void AddWizardPage(WIZARD *w, WIZARD_PAGE *p)
+{
+ // Validate arguments
+ if (w == NULL || p == NULL)
+ {
+ return;
+ }
+
+ Add(w->Pages, p);
+
+ p->Wizard = w;
+}
+
+// Create a new wizard page
+WIZARD_PAGE *NewWizardPage(UINT id, WINUI_WIZARD_PROC *proc, wchar_t *title)
+{
+ WIZARD_PAGE *p;
+ // Validate arguments
+ if (id == 0 || proc == NULL)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(WIZARD_PAGE));
+ p->Id = id;
+ p->Proc = proc;
+ p->Title = CopyUniStr(title);
+
+ return p;
+}
+
+// Release the wizard page
+void FreeWizardPage(WIZARD_PAGE *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->DialogParam != NULL)
+ {
+ FreeBitmapList(p->DialogParam->BitmapList);
+ Free(p->DialogParam);
+ }
+
+ Free(p->Title);
+
+ Free(p);
+}
+
+// NIC information dialog procedure
+UINT NicInfoProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UI_NICINFO *info = (UI_NICINFO *)param;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ NicInfoInit(hWnd, info);
+
+ SetTimer(hWnd, 1, 50, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+
+ NicInfoOnTimer(hWnd, info);
+
+ SetTimer(hWnd, 1, 50, NULL);
+ break;
+
+ case 2:
+ KillTimer(hWnd, 2);
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ KillTimer(hWnd, 1);
+ KillTimer(hWnd, 2);
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+void NicInfoCloseAfterTime(HWND hWnd, UI_NICINFO *info, UINT tick)
+{
+ UINT64 now;
+ UINT64 closetime;
+ // Validate arguments
+ if (hWnd == NULL || info == NULL)
+ {
+ return;
+ }
+
+ now = Tick64();
+ closetime = now + (UINT64)tick;
+
+ if (info->CloseAfterTime == 0 || info->CloseAfterTime >= closetime)
+ {
+ info->CloseAfterTime = closetime;
+ KillTimer(hWnd, 2);
+ SetTimer(hWnd, 2, tick, NULL);
+ }
+}
+void NicInfoShowStatus(HWND hWnd, UI_NICINFO *info, wchar_t *msg1, wchar_t *msg2, UINT icon, bool animate)
+{
+ // Validate arguments
+ if (hWnd == NULL || info == NULL)
+ {
+ return;
+ }
+ if (icon == 0)
+ {
+ icon = ICO_TEST;
+ }
+ if (msg1 == NULL)
+ {
+ msg1 = L"";
+ }
+ if (msg2 == NULL)
+ {
+ msg2 = L"";
+ }
+
+ if (info->CurrentIcon != icon)
+ {
+ SetIcon(hWnd, S_ICON, icon);
+ info->CurrentIcon = icon;
+ }
+
+ SetText(hWnd, S_STATUS1, msg1);
+ SetText(hWnd, S_STATUS2, msg2);
+
+ SetShow(hWnd, P_BAR, animate && MsIsWinXPOrWinVista());
+}
+void NicInfoRefresh(HWND hWnd, UI_NICINFO *info)
+{
+ MS_ADAPTER *a;
+ IP ip;
+ char ip_str[MAX_SIZE];
+ char title[MAX_SIZE];
+ UINT i;
+ wchar_t tmp[MAX_SIZE];
+ bool has_ip = false;
+ // Validate arguments
+ if (hWnd == NULL || info == NULL)
+ {
+ return;
+ }
+
+ Format(title, sizeof(title), VLAN_ADAPTER_NAME_TAG, info->NicName);
+
+ a = MsGetAdapter(title);
+ if (a == NULL)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ // Check whether an IP address is assigned
+ Zero(&ip, sizeof(ip));
+ for (i = 0;i < MAX_MS_ADAPTER_IP_ADDRESS;i++)
+ {
+ if (IsZeroIP(&a->IpAddresses[i]) == false)
+ {
+ Copy(&ip, &a->IpAddresses[i], sizeof(IP));
+
+ if (!(ip.addr[0] == 169 && ip.addr[1] == 254))
+ {
+ has_ip = true;
+ }
+ }
+ }
+ IPToStr(ip_str, sizeof(ip_str), &ip);
+
+ if (has_ip == false)
+ {
+ if (a->UseDhcp)
+ {
+ NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_1"), ICO_NIC_OFFLINE, true);
+ }
+ else
+ {
+ NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_2"), ICO_NIC_OFFLINE, true);
+ }
+ }
+ else
+ {
+ if (a->UseDhcp)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("NICINFO_2_1"), ip_str);
+ NicInfoShowStatus(hWnd, info, _UU("NICINFO_2"), tmp, ICO_NIC_ONLINE, false);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("NICINFO_3_1"), ip_str);
+ NicInfoShowStatus(hWnd, info, _UU("NICINFO_3"), tmp, ICO_NIC_ONLINE, false);
+ }
+
+ NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_2);
+ }
+
+ MsFreeAdapter(a);
+}
+void NicInfoInit(HWND hWnd, UI_NICINFO *info)
+{
+ // Validate arguments
+ if (hWnd == NULL || info == NULL)
+ {
+ return;
+ }
+
+ if (MsIsWinXPOrWinVista())
+ {
+ // Show a progress bar for Windows XP or later
+ SendMsg(hWnd, P_BAR, PBM_SETMARQUEE, TRUE, 150);
+ SetStyle(hWnd, P_BAR, PBS_MARQUEE);
+ }
+
+ DlgFont(hWnd, S_STATUS1, 9, false);
+ DlgFont(hWnd, S_STATUS2, 11, false);
+
+ SetIcon(hWnd, 0, ICO_NIC_ONLINE);
+
+ FormatText(hWnd, 0, info->NicName);
+
+ NicInfoRefresh(hWnd, info);
+
+ NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_1);
+}
+void NicInfoOnTimer(HWND hWnd, UI_NICINFO *info)
+{
+ // Validate arguments
+ if (hWnd == NULL || info == NULL)
+ {
+ return;
+ }
+
+ if (info->Halt)
+ {
+ Close(hWnd);
+ return;
+ }
+
+ if (info->RouteChange != NULL &&
+ IsRouteChanged(info->RouteChange) == false)
+ {
+ return;
+ }
+
+ NicInfoRefresh(hWnd, info);
+}
+
+// Show the NIC information dialog
+void NicInfo(UI_NICINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ info->RouteChange = NewRouteChange();
+
+ DialogEx2(NULL, D_NICINFO, NicInfoProc, info, true, true);
+
+ FreeRouteChange(info->RouteChange);
+ info->RouteChange = NULL;
+}
+
+// TCP connection thread
+void WinConnectDlgThread(THREAD *thread, void *param)
+{
+ SOCK *s;
+ WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
+ UINT nat_t_error_code;
+ char *nat_t_svc_name = NULL;
+ // Validate arguments
+ if (d == NULL || thread == NULL)
+ {
+ return;
+ }
+
+ // Socket connection
+ if (IsEmptyStr(d->nat_t_svc_name) == false)
+ {
+ nat_t_svc_name = d->nat_t_svc_name;
+ }
+
+ s = ConnectEx3(d->hostname, d->port, d->timeout, &d->cancel, nat_t_svc_name, &nat_t_error_code, d->try_start_ssl, d->ssl_no_tls, false);
+
+ d->ret_sock = s;
+ d->nat_t_error_code = nat_t_error_code;
+
+ PostMessageA(d->hWnd, WM_APP + 68, 0, 0);
+}
+
+// TCP connection dialog procedure
+UINT WinConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // UI setting
+ CenterParent(hWnd);
+ SetText(hWnd, 0, d->caption);
+ SetText(hWnd, S_INFO, d->info);
+ SetIcon(hWnd, S_ICON, d->icon_id);
+ d->hWnd = hWnd;
+
+ if (MsIsWinXPOrWinVista())
+ {
+ // Show a progress bar for Windows XP or later
+ SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100);
+ SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE);
+ }
+ else
+ {
+ // Hide the progress bar in the case of pre-Windows 2000
+ Hide(hWnd, IDC_PROGRESS1);
+ }
+
+ // Create a thread
+ d->thread = NewThread(WinConnectDlgThread, d);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_APP + 68:
+ case WM_CLOSE:
+ if (d->cancel == false)
+ {
+ d->cancel = true;
+ Disable(hWnd, IDCANCEL);
+ if (d->ret_sock == NULL)
+ {
+ SetText(hWnd, S_INFO, _UU("CONNECTDLG_CANCELING"));
+ }
+ DoEvents(hWnd);
+ Refresh(hWnd);
+ WaitThread(d->thread, INFINITE);
+ ReleaseThread(d->thread);
+ EndDialog(hWnd, 0);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// TCP connection with showing the UI
+SOCK *WinConnectEx2(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info, bool try_start_ssl, bool ssl_no_tls)
+{
+ return WinConnectEx3(hWnd, server, port, timeout, icon_id, caption, info, NULL, false, try_start_ssl, ssl_no_tls);
+}
+SOCK *WinConnectEx3(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info, UINT *nat_t_error_code, char *nat_t_svc_name, bool try_start_ssl, bool ssl_no_tls)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ WINCONNECT_DLG_DATA d;
+ // Validate arguments
+ if (server == NULL || port == 0)
+ {
+ return NULL;
+ }
+ if (icon_id == 0)
+ {
+ icon_id = ICO_USER_ADMIN;
+ }
+ if (caption == NULL)
+ {
+ if (hWnd == NULL)
+ {
+ caption = _UU("CONNECTDLG_CAPTION");
+ }
+ else
+ {
+ GetTxt(hWnd, 0, tmp2, sizeof(tmp2));
+ caption = tmp2;
+ }
+ }
+ if (info == NULL)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CONNECTDLG_MESSAGE"), server, port);
+
+ info = tmp;
+ }
+
+ Zero(&d, sizeof(d));
+
+ d.try_start_ssl = try_start_ssl;
+ d.ssl_no_tls = ssl_no_tls;
+ d.cancel = false;
+ d.caption = caption;
+ d.icon_id = icon_id;
+ d.info = info;
+ d.timeout = timeout;
+ d.hostname = server;
+ d.port = port;
+ StrCpy(d.nat_t_svc_name, sizeof(d.nat_t_svc_name), nat_t_svc_name);
+
+ Dialog(hWnd, D_CONNECT, WinConnectDlgProc, &d);
+
+ if (nat_t_error_code != NULL)
+ {
+ *nat_t_error_code = d.nat_t_error_code;
+ }
+
+ return d.ret_sock;
+}
+
+// Show the Windows Network Setup screen
+bool ShowWindowsNetworkConnectionDialog()
+{
+ wchar_t exe_name[MAX_SIZE];
+ void *proc;
+
+ CombinePathW(exe_name, sizeof(exe_name), MsGetSystem32DirW(), L"control.exe");
+
+ proc = Win32RunEx2W(exe_name, L"netconnections", false, NULL);
+
+ if (proc == NULL)
+ {
+ return false;
+ }
+
+ Win32CloseProcess(proc);
+
+ return true;
+}
+
+// Get the best Meiryo font name for the current OS
+char *GetMeiryoFontName()
+{
+ if (MsIsWindows7())
+ {
+ return "Meiryo UI";
+ }
+ else
+ {
+ if (MsIsVista())
+ {
+ return "Meiryo";
+ }
+ else
+ {
+ return "MS UI Gothic";
+ }
+ }
+}
+
+// Get the Meiryo font
+HFONT GetMeiryoFont()
+{
+ return GetMeiryoFontEx(0);
+}
+HFONT GetMeiryoFontEx(UINT font_size)
+{
+ return GetMeiryoFontEx2(font_size, false);
+}
+HFONT GetMeiryoFontEx2(UINT font_size, bool bold)
+{
+ if (_GETLANG() == 0)
+ {
+ return GetFont(GetMeiryoFontName(), font_size, bold, false, false, false);
+ }
+ else if (_GETLANG() == 2)
+ {
+ return GetFont("Microsoft YaHei", font_size, bold, false, false, false);
+ }
+ else
+ {
+ return GetFont(NULL, font_size, bold, false, false, false);
+ }
+}
+
+// Set font to Meiryo
+void SetFontMeiryo(HWND hWnd, UINT id, UINT font_size)
+{
+ SetFont(hWnd, id, GetMeiryoFontEx(font_size));
+}
+
+// Set as the default font
+void SetFontDefault(HWND hWnd, UINT id)
+{
+ SetFont(hWnd, id, GetDialogDefaultFont());
+}
+
+// Display the warning messages about bad process
+void ShowBadProcessWarning(HWND hWnd, BAD_PROCESS *bad)
+{
+ wchar_t title[MAX_SIZE];
+ wchar_t message[8192];
+ // Validate arguments
+ if (bad == NULL)
+ {
+ return;
+ }
+
+ UniFormat(title, sizeof(title), _UU("BAD_PROCESS_TITLE"), bad->Title);
+ UniFormat(message, sizeof(message), _UU("BAD_PROCESS_MESSAGE"),
+ bad->Title, bad->Title, bad->Title, bad->Title);
+
+ OnceMsg(hWnd, title, message, true, ICO_WARNING);
+}
+
+// If there is process which is included in incompatible anti-virus software list, show appropriate
+bool CheckBadProcesses(HWND hWnd)
+{
+ bool ret = true;
+ UINT i;
+ LIST *o;
+
+ o = MsGetProcessList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ char exe[MAX_PATH];
+ BAD_PROCESS *bad;
+
+ GetFileNameFromFilePath(exe, sizeof(exe), p->ExeFilename);
+
+ bad = IsBadProcess(exe);
+
+ if (bad != NULL)
+ {
+ // Display the message because a bad process have been found
+ ret = false;
+
+ ShowBadProcessWarning(hWnd, bad);
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+
+// Search whether the specified process name is the appropriate to a bad process
+BAD_PROCESS *IsBadProcess(char *exe)
+{
+ UINT i;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < num_bad_processes;i++)
+ {
+ BAD_PROCESS *bad = &bad_processes[i];
+
+ if (StrCmpi(bad->ExeName, exe) == 0)
+ {
+ return bad;
+ }
+ }
+
+ return NULL;
+}
+
+// Message display procedure
+UINT OnceMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ ONCEMSG_DLG *d = (ONCEMSG_DLG *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetText(hWnd, 0, d->Title);
+ SetText(hWnd, E_TEXT, d->Message);
+ SetShow(hWnd, C_DONTSHOWAGAIN, d->ShowCheckbox);
+ //DisableClose(hWnd);
+ Focus(hWnd, IDCANCEL);
+ if (d->Icon != 0)
+ {
+ SetIcon(hWnd, 0, d->Icon);
+ }
+
+ if (MsIsVista())
+ {
+ SetFont(hWnd, E_TEXT, GetMeiryoFont());
+ }
+ else
+ {
+ DlgFont(hWnd, E_TEXT, 11, false);
+ }
+
+ SetTimer(hWnd, 1, 50, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (*d->halt)
+ {
+ Close(hWnd);
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ KillTimer(hWnd, 1);
+ d->Checked = IsChecked(hWnd, C_DONTSHOWAGAIN);
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Show a message
+void OnceMsg(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon)
+{
+ OnceMsgEx(hWnd, title, message, show_checkbox, icon, NULL);
+}
+void OnceMsgEx(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon, bool *halt)
+{
+ ONCEMSG_DLG d;
+ UINT hash;
+ char valuename[MAX_PATH];
+ bool b_dummy = false;
+ // Validate arguments
+ if (title == NULL)
+ {
+ title = title_bar;
+ }
+ if (message == NULL)
+ {
+ message = L"message";
+ }
+ if (halt == NULL)
+ {
+ halt = &b_dummy;
+ }
+
+ Zero(&d, sizeof(d));
+ d.Message = message;
+ d.Title = title;
+ d.ShowCheckbox = show_checkbox;
+ d.Icon = icon;
+ d.halt = halt;
+
+ hash = GetOnceMsgHash(title, message);
+ Format(valuename, sizeof(valuename), ONCE_MSG_REGVALUE, hash);
+
+ if (MsRegReadInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename) == 0)
+ {
+ switch (icon)
+ {
+ case ICO_WARNING:
+ MessageBeep(MB_ICONEXCLAMATION);
+ break;
+
+ case ICO_INFORMATION:
+ MessageBeep(MB_ICONASTERISK);
+ break;
+ }
+
+ Dialog(hWnd, D_ONCEMSG, OnceMsgProc, &d);
+
+ if (show_checkbox)
+ {
+ if (d.Checked)
+ {
+ MsRegWriteInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename, 1);
+ }
+ }
+ }
+}
+
+// Get the message hash
+UINT GetOnceMsgHash(wchar_t *title, wchar_t *message)
+{
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ UINT ret;
+ // Validate arguments
+ if (title == NULL)
+ {
+ title = title_bar;
+ }
+ if (message == NULL)
+ {
+ message = L"message";
+ }
+
+ b = NewBuf();
+ // 2013.5.19: Exclude the title from the hash calculation
+ //WriteBuf(b, title, UniStrSize(title));
+ WriteBuf(b, message, UniStrSize(message));
+ HashSha1(hash, b->Buf, b->Size);
+ FreeBuf(b);
+
+ Copy(&ret, hash, sizeof(UINT));
+
+ return ret;
+}
+
+// Set a theme for Windows Vista
+void InitVistaWindowTheme(HWND hWnd)
+{
+ static HINSTANCE hInstDll = NULL;
+ HRESULT (WINAPI *_SetWindowTheme)(HWND, LPCWSTR, LPCWSTR) = NULL;
+
+ if (MsIsVista() == false)
+ {
+ return;
+ }
+
+ if (hInstDll == NULL)
+ {
+ hInstDll = LoadLibraryA("uxtheme.dll");
+ }
+
+ if (hInstDll == NULL)
+ {
+ return;
+ }
+
+ if (_SetWindowTheme == NULL)
+ {
+ _SetWindowTheme = (HRESULT (WINAPI *)(HWND,LPCWSTR,LPCWSTR))GetProcAddress(hInstDll, "SetWindowTheme");
+ }
+
+ if (_SetWindowTheme == NULL)
+ {
+ return;
+ }
+
+ _SetWindowTheme(hWnd, L"explorer", NULL);
+}
+
+// Register all applications to be registered in the Windows firewall
+// that may be present in the current directory
+void RegistWindowsFirewallAll()
+{
+ char exedir[MAX_SIZE];
+
+ GetExeDir(exedir, sizeof(exedir));
+
+ RegistWindowsFirewallAllEx(exedir);
+}
+void RegistWindowsFirewallAllEx(char *dir)
+{
+ MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "vpnclient.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "vpnclient_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "vpncmgr.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "vpncmgr_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_MANAGER_STR, "vpnsmgr.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_MANAGER_STR, "vpnsmgr_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "vpnserver.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "vpnserver_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_BRIDGE_STR, "vpnbridge.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_BRIDGE_STR, "vpnbridge_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "vpncmd.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "vpncmd_x64.exe", dir);
+
+ MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "ham.exe", dir);
+ MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "ham_x64.exe", dir);
+}
+
+// Check whether the notification service is already running
+bool Win32CnCheckAlreadyExists(bool lock)
+{
+ char tmp[MAX_SIZE];
+ HANDLE hMutex;
+
+ HashInstanceNameLocal(tmp, sizeof(tmp), CLIENT_NOTIFY_SERVICE_INSTANCENAME);
+
+ hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, tmp);
+ if (hMutex != NULL)
+ {
+ CloseHandle(hMutex);
+ return true;
+ }
+
+ if (lock == false)
+ {
+ return false;
+ }
+
+ hMutex = CreateMutex(NULL, FALSE, tmp);
+ if (hMutex == NULL)
+ {
+ CloseHandle(hMutex);
+ return true;
+ }
+
+ return false;
+}
+
+// Get whether it is set to not display the dialog about the free version
+bool IsRegistedToDontShowFreeEditionDialog(char *server_name)
+{
+ // Validate arguments
+ if (server_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsRegReadInt(REG_LOCAL_MACHINE, FREE_REGKEY, server_name) != 0)
+ {
+ return true;
+ }
+
+ if (MsRegWriteInt(REG_LOCAL_MACHINE, FREE_REGKEY, "__test__", 1) == false)
+ {
+ return true;
+ }
+
+ MsRegDeleteValue(REG_LOCAL_MACHINE, FREE_REGKEY, "__test__");
+
+ return false;
+}
+
+// Set in the registry not to show a dialog about the free version
+void RegistToDontShowFreeEditionDialog(char *server_name)
+{
+ // Validate arguments
+ if (server_name == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, FREE_REGKEY, server_name, 1);
+}
+
+// Free Edition dialog procedure
+UINT FreeInfoDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ FREEINFO *info = (FREEINFO *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_HUB);
+ Top(hWnd);
+ info->hWnd = hWnd;
+ Set(info->Event);
+ FormatText(hWnd, S_INFO_2, info->ServerName);
+ DlgFont(hWnd, S_INFO_1, 13, true);
+ DlgFont(hWnd, S_INFO_3, 13, false);
+ DlgFont(hWnd, B_HIDE, 10, true);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ if (IsChecked(hWnd, B_HIDE))
+ {
+ RegistToDontShowFreeEditionDialog(info->ServerName);
+ }
+
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Display the dialog about the Free Edition
+void ShowFreeInfoDialog(HWND hWnd, FREEINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Dialog(hWnd, D_FREEINFO, FreeInfoDialogProc, info);
+ Set(info->Event);
+}
+
+// Free Edition dialog thread
+void FreeInfoThread(THREAD *thread, void *param)
+{
+ FREEINFO *info = (FREEINFO *)param;
+ // Validate arguments
+ if (thread == NULL || info == NULL)
+ {
+ return;
+ }
+
+ ShowFreeInfoDialog(NULL, info);
+}
+
+// Start the Free Edition Announcement dialog
+FREEINFO *StartFreeInfoDlg(char *server_name)
+{
+ FREEINFO *info;
+
+ if (IsRegistedToDontShowFreeEditionDialog(server_name))
+ {
+ return NULL;
+ }
+
+ info = ZeroMalloc(sizeof(FREEINFO));
+
+ StrCpy(info->ServerName, sizeof(info->ServerName), server_name);
+ info->Event = NewEvent();
+
+ info->Thread = NewThread(FreeInfoThread, info);
+ Wait(info->Event, INFINITE);
+ ReleaseEvent(info->Event);
+ info->Event = NULL;
+
+ return info;
+}
+
+// End the Free Edition Announcement dialog
+void EndFreeInfoDlg(FREEINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ SendMsg(info->hWnd, 0, WM_CLOSE, 0, 0);
+ WaitThread(info->Thread, INFINITE);
+ ReleaseThread(info->Thread);
+
+ Free(info);
+}
+
+// Execute a EXE in the hamcore
+bool ExecuteHamcoreExe(char *name)
+{
+ BUF *b;
+ wchar_t tmp[MAX_PATH];
+ char tmp2[MAX_PATH];
+ UCHAR hash[MD5_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(name);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ Hash(hash, name, StrLen(name), false);
+ BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));
+ UniFormat(tmp, sizeof(tmp), L"%s\\tmp_%S.exe", MsGetMyTempDirW(), tmp2);
+ SeekBuf(b, 0, 0);
+ DumpBufW(b, tmp);
+
+ FreeBuf(b);
+
+ return RunW(tmp, NULL, false, false);
+}
+
+// Show the Easter Egg
+void ShowEasterEgg(HWND hWnd)
+{
+ ExecuteHamcoreExe("|egg1.exe");
+ ExecuteHamcoreExe("|egg2.exe");
+ ExecuteHamcoreExe("|egg3.exe");
+ ShellExecute(hWnd, "open", "http://www.softether.co.jp/jp/special/vpn3egg/", NULL, NULL, SW_SHOW);
+}
+
+void KakushiThread(THREAD *thread, void *param)
+{
+ KAKUSHI *k;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ k = (KAKUSHI *)param;
+
+ k->Thread = thread;
+ AddRef(k->Thread->ref);
+ NoticeThreadInit(thread);
+
+ Dialog(NULL, D_CM_KAKUSHI, KakushiDlgProc, k);
+ k->hWnd = NULL;
+}
+
+KAKUSHI *InitKakushi()
+{
+ THREAD *t;
+ KAKUSHI *k = ZeroMalloc(sizeof(KAKUSHI));
+
+ t = NewThread(KakushiThread, k);
+
+ WaitThreadInit(t);
+ ReleaseThread(t);
+
+ return k;
+}
+
+UINT KakushiDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ KAKUSHI *k = (KAKUSHI *)param;
+ UINT64 now;
+ bool b;
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetText(hWnd, S_INFO, _UU("CM_VLAN_CREATING"));
+
+ b = false;
+
+ if (MsIsVista())
+ {
+ if (_GETLANG() == 0)
+ {
+ SetFont(hWnd, S_INFO, GetFont(GetMeiryoFontName(), 11, false, false, false, false));
+ b = true;
+ }
+ else if (_GETLANG() == 2)
+ {
+ SetFont(hWnd, S_INFO, GetFont("Microsoft YaHei", 11, false, false, false, false));
+ b = true;
+ }
+ }
+
+ if (b == false)
+ {
+ DlgFont(hWnd, S_INFO, 11, false);
+ }
+
+ SetTimer(hWnd, 1, 50, NULL);
+ k->hWnd = hWnd;
+
+ k->Span = 20 * 1000;
+ k->StartTick = Tick64();
+
+ SetRange(hWnd, P_PROGRESS, 0, (UINT)k->Span);
+
+ case WM_APP + 9821:
+ now = Tick64();
+
+ if (((k->StartTick + k->Span) <= now) || k->Halt)
+ {
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ SetPos(hWnd, P_PROGRESS, (UINT)(now - k->StartTick));
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ AllowSetForegroundWindow(ASFW_ANY);
+ SetForegroundWindow(hWnd);
+ SetActiveWindow(hWnd);
+
+ now = Tick64();
+
+ if (((k->StartTick + k->Span) <= now) || k->Halt)
+ {
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ SetPos(hWnd, P_PROGRESS, (UINT)(now - k->StartTick));
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ return 1;
+ }
+
+ return 0;
+}
+
+// Release the Kakushi screen
+void FreeKakushi(KAKUSHI *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ k->Halt = true;
+
+ if (k->hWnd != NULL)
+ {
+ PostMessage(k->hWnd, WM_APP + 9821, 0, 0);
+ }
+
+ WaitThread(k->Thread, INFINITE);
+ ReleaseThread(k->Thread);
+
+ Free(k);
+}
+
+// TCP/IP optimization selection dialog procedure
+UINT TcpMsgDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_SETUP);
+ //DlgFont(hWnd, R_OPTIMIZE, 0, true);
+
+ Check(hWnd, R_NO, true);
+
+ if (g_tcpip_topmost)
+ {
+ Top(hWnd);
+ }
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ ret = 1;
+ if (IsChecked(hWnd, R_MANUAL))
+ {
+ ret = 2;
+ }
+ else if (IsChecked(hWnd, R_NO))
+ {
+ ret = 0;
+ }
+
+ EndDialog(hWnd, ret);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ return 1;
+ }
+
+ return 0;
+}
+
+// Initialize the dialog
+void TcpIpDlgInit(HWND hWnd)
+{
+ MS_TCP tcp;
+
+ SetIcon(hWnd, 0, ICO_SETUP);
+
+ MsGetTcpConfig(&tcp);
+
+ Check(hWnd, R_RECV_DISABLE, tcp.RecvWindowSize == 0);
+ Check(hWnd, R_RECV_ENABLE, tcp.RecvWindowSize != 0);
+ SetInt(hWnd, E_RECV, tcp.RecvWindowSize != 0 ? tcp.RecvWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
+
+ Check(hWnd, R_SEND_DISABLE, tcp.SendWindowSize == 0);
+ Check(hWnd, R_SEND_ENABLE, tcp.SendWindowSize != 0);
+ SetInt(hWnd, E_SEND, tcp.SendWindowSize != 0 ? tcp.SendWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
+
+ TcpIpDlgUpdate(hWnd);
+
+ Top(hWnd);
+}
+
+// Update the dialog
+void TcpIpDlgUpdate(HWND hWnd)
+{
+ bool ok = true;
+
+ SetEnable(hWnd, E_RECV, IsChecked(hWnd, R_RECV_ENABLE));
+ SetEnable(hWnd, S_RECV, IsChecked(hWnd, R_RECV_ENABLE));
+ SetEnable(hWnd, E_SEND, IsChecked(hWnd, R_SEND_ENABLE));
+ SetEnable(hWnd, S_SEND, IsChecked(hWnd, R_SEND_ENABLE));
+
+ if (IsChecked(hWnd, R_RECV_ENABLE) && GetInt(hWnd, E_RECV) < 1454)
+ {
+ ok = false;
+ }
+
+ if (IsChecked(hWnd, R_SEND_ENABLE) && GetInt(hWnd, E_SEND) < 1454)
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// TCP/IP dialog procedure
+UINT TcpIpDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ MS_TCP tcp, old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TcpIpDlgInit(hWnd);
+
+ if (g_tcpip_topmost)
+ {
+ Top(hWnd);
+ }
+
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_RECV_DISABLE:
+ case R_RECV_ENABLE:
+ case R_SEND_DISABLE:
+ case R_SEND_ENABLE:
+ case E_RECV:
+ case E_SEND:
+ TcpIpDlgUpdate(hWnd);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ Zero(&tcp, sizeof(tcp));
+
+ if (IsChecked(hWnd, R_RECV_ENABLE))
+ {
+ tcp.RecvWindowSize = GetInt(hWnd, E_RECV);
+ }
+
+ if (IsChecked(hWnd, R_SEND_ENABLE))
+ {
+ tcp.SendWindowSize = GetInt(hWnd, E_SEND);
+ }
+
+ MsGetTcpConfig(&old);
+
+ MsSetTcpConfig(&tcp);
+ MsSaveTcpConfigReg(&tcp);
+
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+
+ case R_RECV_ENABLE:
+ FocusEx(hWnd, E_RECV);
+ break;
+
+ case R_SEND_ENABLE:
+ FocusEx(hWnd, E_SEND);
+ break;
+
+ case B_RECV:
+ SetInt(hWnd, E_RECV, DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
+ Check(hWnd, R_RECV_DISABLE, false);
+ Check(hWnd, R_RECV_ENABLE, true);
+ TcpIpDlgUpdate(hWnd);
+ FocusEx(hWnd, E_RECV);
+ break;
+
+ case B_SEND:
+ SetInt(hWnd, E_SEND, DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
+ Check(hWnd, R_SEND_DISABLE, false);
+ Check(hWnd, R_SEND_ENABLE, true);
+ TcpIpDlgUpdate(hWnd);
+ FocusEx(hWnd, E_SEND);
+ break;
+
+ case B_DELETE:
+ Zero(&tcp, sizeof(tcp));
+ MsSetTcpConfig(&tcp);
+ MsDeleteTcpConfigReg();
+ EndDialog(hWnd, 0);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Warning dialog about 64-bit
+UINT Cpu64DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_WARNING);
+ DlgFont(hWnd, S_BOLD, 9, true);
+ SetTimer(hWnd, 1, 30 * 1000, NULL);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ Command(hWnd, IDOK);
+ break;
+ }
+
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Display a warning dialog about 64-bit
+void ShowCpu64Warning()
+{
+ Dialog(NULL, D_CPU64_WARNING, Cpu64DlgProc, NULL);
+}
+
+// Show the TCP/IP configuration utility
+void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode)
+{
+ if (MsIsTcpConfigSupported() == false)
+ {
+ if (util_mode)
+ {
+ // Show a message that is not supported by the current OS
+ if (MsIsAdmin() == false)
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_ADMIN"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_SUPPORTED"));
+ }
+ }
+ return;
+ }
+
+ if (util_mode == false)
+ {
+ // Exit immediately by start the vpncmd
+ wchar_t tmp[MAX_PATH];
+ wchar_t exedir[MAX_PATH];
+ HANDLE h;
+
+ GetExeDirW(exedir, sizeof(exedir));
+
+ if (IsX64())
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s\\vpncmd_x64.exe", exedir);
+ }
+ else if (IsIA64())
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s\\vpncmd_ia64.exe", exedir);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), L"%s\\vpncmd.exe", exedir);
+ }
+
+ if (IsFileW(tmp))
+ {
+ RunW(tmp, L"/tool /cmd:exit", true, false);
+ }
+
+ // Disable the task off-loading by netsh
+ if (MsIsVista())
+ {
+ DIRLIST *dl;
+ UINT i;
+ bool b = false;
+
+ dl = EnumDirW(exedir);
+
+ for (i = 0;i < dl->NumFiles;i++)
+ {
+ if (UniInStr(dl->File[i]->FileNameW, L"vpnbridge") ||
+ UniInStr(dl->File[i]->FileNameW, L"vpnserver"))
+ {
+ b = true;
+ }
+ }
+
+ FreeDir(dl);
+
+ if (b)
+ {
+ // Disable the off-loading
+ MsDisableNetworkOffloadingEtc();
+ }
+ }
+
+ // Windows Firewall registration
+ RegistWindowsFirewallAll();
+
+ SleepThread(1000);
+
+ // Start vpnclient.exe /uihelp
+ h = CmExecUiHelperMain();
+ if (h != NULL)
+ {
+ CloseHandle(h);
+ }
+
+ if (Is64() == false)
+ {
+ if (MsIs64BitWindows())
+ {
+ // Show a warning message if a 32-bit version is used in 64-bit Windows
+ ShowCpu64Warning();
+ }
+ }
+
+ if (MsIsAdmin())
+ {
+ if (MsIsVista())
+ {
+ // If installing on Windows Vista,
+ // dispel the network limitation of MMCSS
+ if (MsIsMMCSSNetworkThrottlingEnabled())
+ {
+ MsSetMMCSSNetworkThrottlingEnable(false);
+ }
+ }
+ }
+ }
+
+ if (util_mode == false && MsIsShouldShowTcpConfigApp() == false)
+ {
+ return;
+ }
+
+ if (util_mode == false)
+ {
+ // 2006.07.04 nobori
+ // I decided not to show TCP/IP optimization utility in the installer
+ return;
+ }
+
+ g_tcpip_topmost = util_mode ? false : true;
+
+ if (util_mode == false)
+ {
+ UINT ret = Dialog(hWnd, D_TCP_MSG, TcpMsgDlgProc, NULL);
+
+ if (ret == 0)
+ {
+ MS_TCP tcp;
+
+ Zero(&tcp, sizeof(tcp));
+ MsGetTcpConfig(&tcp);
+ MsSaveTcpConfigReg(&tcp);
+ return;
+ }
+ else if (ret == 1)
+ {
+ MS_TCP tcp;
+
+ Zero(&tcp, sizeof(tcp));
+
+ tcp.RecvWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_RECV;
+ tcp.SendWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_SEND;
+ MsSetTcpConfig(&tcp);
+ MsSaveTcpConfigReg(&tcp);
+
+ return;
+ }
+ }
+
+ Dialog(hWnd, D_TCP, TcpIpDlgProc, NULL);
+}
+
+// Internationalization of menu (Unicode)
+void InitMenuInternationalUni(HMENU hMenu, char *prefix)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hMenu == NULL || prefix == NULL)
+ {
+ return;
+ }
+
+ // Get the number of items in the menu
+ num = GetMenuItemCount(hMenu);
+
+ // Enumerate the menu items
+ for (i = 0;i < num;i++)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ MENUITEMINFOW info;
+ wchar_t tmp[MAX_SIZE];
+
+ if (hSubMenu != NULL)
+ {
+ // If there is a sub-menu, call it recursively
+ InitMenuInternational(hSubMenu, prefix);
+ }
+
+ // Get the menu item
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.cch = sizeof(tmp);
+ info.dwTypeData = tmp;
+ info.fMask = MIIM_STRING;
+ Zero(tmp, sizeof(tmp));
+
+ if (GetMenuItemInfoW(hMenu, i, true, &info))
+ {
+ if (tmp[0] == L'@')
+ {
+ char name[256];
+ wchar_t *ret;
+
+ Format(name, sizeof(name), "%s@%S", prefix, &tmp[1]);
+
+ ret = _UU(name);
+ if (UniIsEmptyStr(ret) == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), ret);
+ info.cch = UniStrLen(tmp);
+
+ SetMenuItemInfoW(hMenu, i, true, &info);
+ }
+ }
+ }
+ }
+}
+
+// Internationalization of menu
+void InitMenuInternational(HMENU hMenu, char *prefix)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hMenu == NULL || prefix == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt())
+ {
+ InitMenuInternationalUni(hMenu, prefix);
+ return;
+ }
+
+ // Get the number of items in the menu
+ num = GetMenuItemCount(hMenu);
+
+ // Enumerate the menu items
+ for (i = 0;i < num;i++)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ MENUITEMINFO info;
+ char tmp[MAX_SIZE];
+
+ if (hSubMenu != NULL)
+ {
+ // If there is a sub-menu, call it recursively
+ InitMenuInternational(hSubMenu, prefix);
+ }
+
+ // Get the menu item
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.cch = sizeof(tmp);
+ info.dwTypeData = tmp;
+ info.fMask = MIIM_STRING;
+ Zero(tmp, sizeof(tmp));
+
+ if (GetMenuItemInfo(hMenu, i, true, &info))
+ {
+ if (tmp[0] == '@')
+ {
+ char name[256];
+ char *ret;
+
+ Format(name, sizeof(name), "%s@%s", prefix, &tmp[1]);
+
+ ret = _SS(name);
+ if (IsEmptyStr(ret) == false)
+ {
+ StrCpy(tmp, sizeof(tmp), ret);
+ info.cch = StrLen(tmp);
+
+ SetMenuItemInfo(hMenu, i, true, &info);
+ }
+ }
+ }
+ }
+}
+
+// Get the default font for the dialog box
+HFONT GetDialogDefaultFont()
+{
+ return GetDialogDefaultFontEx(false);
+}
+HFONT GetDialogDefaultFontEx(bool meiryo)
+{
+ char *default_font_name = _SS("DEFAULT_FONT");
+ UINT default_font_size = _II("DEFAULT_FONT_SIZE");
+ char *win7_font = _SS("DEFAULT_FONT_WIN7");
+
+ if (meiryo)
+ {
+ if (_GETLANG() == 2)
+ {
+ default_font_name = "Microsoft YaHei";
+ }
+ else
+ {
+ default_font_name = GetMeiryoFontName();
+ }
+ }
+
+ if (MsIsWindows7())
+ {
+ if (IsEmptyStr(win7_font) == false)
+ {
+ default_font_name = win7_font;
+ }
+
+ if (GetTextScalingFactor() >= 1.44)
+ {
+ // Use a substitute font in the case of high-DPI in Windows 7 and later
+ char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
+
+ if (IsEmptyStr(alternative_font) == false)
+ {
+ default_font_name = alternative_font;
+ }
+ }
+ }
+
+ if (IsEmptyStr(default_font_name))
+ {
+ default_font_name = font_name;
+ }
+
+ if (default_font_size == 0)
+ {
+ default_font_size = 9;
+ }
+
+ return GetFont(default_font_name, default_font_size, false, false, false, false);
+}
+
+// Get the adjustment scale between the control size and the window size
+void GetWindowAndControlSizeResizeScale(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y)
+{
+ UINT dlgfont_x, dlgfont_y;
+ HFONT hDlgFont;
+ // Validate arguments
+ if (hWnd == NULL || need_resize == NULL || factor_x == NULL || factor_y == NULL)
+ {
+ return;
+ }
+
+ *need_resize = true;
+
+ // Get the font of the current window
+ hDlgFont = (HFONT)SendMsg(hWnd, 0, WM_GETFONT, 0, 0);
+
+ // Get the width and height of the font of the current window
+ CalcFontSize(hDlgFont, &dlgfont_x, &dlgfont_y);
+
+ if ((dlgfont_x == WINUI_DEFAULT_DIALOG_UNIT_X) &&
+ (dlgfont_y == WINUI_DEFAULT_DIALOG_UNIT_Y))
+ {
+ // There is no need to adjust
+ *need_resize = false;
+ *factor_x = 1.0;
+ *factor_y = 1.0;
+ return;
+ }
+
+ // Calculate the adjustment amount
+ *factor_x = (double)dlgfont_x / (double)WINUI_DEFAULT_DIALOG_UNIT_X;
+ *factor_y = (double)dlgfont_y / (double)WINUI_DEFAULT_DIALOG_UNIT_Y;
+}
+
+// Adjust the control size and window size
+void AdjustWindowAndControlSize(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y)
+{
+ HFONT hDlgFont;
+ UINT dlgfont_x, dlgfont_y;
+ RECT rect, rect2;
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || need_resize == NULL || factor_x == NULL || factor_y == NULL)
+ {
+ return;
+ }
+
+ *need_resize = true;
+
+ // Get the font of the current window
+ hDlgFont = (HFONT)SendMsg(hWnd, 0, WM_GETFONT, 0, 0);
+
+ // Get the width and height of the font of the current window
+ CalcFontSize(hDlgFont, &dlgfont_x, &dlgfont_y);
+
+ if ((dlgfont_x == WINUI_DEFAULT_DIALOG_UNIT_X) &&
+ (dlgfont_y == WINUI_DEFAULT_DIALOG_UNIT_Y))
+ {
+ // There is no need to adjust
+ *need_resize = false;
+ *factor_x = 1.0;
+ *factor_y = 1.0;
+ return;
+ }
+
+ // Calculate the adjustment amount
+ *factor_x = (double)dlgfont_x / (double)WINUI_DEFAULT_DIALOG_UNIT_X;
+ *factor_y = (double)dlgfont_y / (double)WINUI_DEFAULT_DIALOG_UNIT_Y;
+
+ if (MsIsVista())
+ {
+ // In Windows Vista or later, trust the size expansion by the OS to follow this (not adjusted)
+ return;
+ }
+
+ // Adjust the size of the window
+ if (GetWindowRect(hWnd, &rect))
+ {
+ if (GetClientRect(hWnd, &rect2))
+ {
+ UINT width = rect2.right - rect2.left;
+ UINT height = rect2.bottom - rect2.top;
+
+ AdjustDialogXY(&width, &height, dlgfont_x, dlgfont_y);
+
+ width += (rect.right - rect.left) - (rect2.right - rect2.left);
+ height += (rect.bottom - rect.top) - (rect2.bottom - rect2.top);
+
+ if (true)
+ {
+ HWND hParent = GetParent(hWnd);
+
+ if (hParent != NULL)
+ {
+ RECT r;
+
+ Zero(&r, sizeof(r));
+
+ if (GetWindowRect(hParent, &r))
+ {
+ RECT r2;
+
+ rect.top = r.top + GetSystemMetrics(SM_CYCAPTION);
+
+ Zero(&r2, sizeof(r2));
+ if (SystemParametersInfo(SPI_GETWORKAREA, 0, &r2, 0))
+ {
+ if (r2.bottom < (rect.top + (int)height))
+ {
+ rect.top -= (rect.top + (int)height) - r2.bottom;
+
+ if (rect.top < 0)
+ {
+ rect.top = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ MoveWindow(hWnd, rect.left, rect.top, width, height, false);
+ }
+ }
+
+ // Enumerate the child windows
+ o = EnumAllChildWindowEx(hWnd, false, true, true);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ // Adjust the size of the child window
+ HWND h = *((HWND *)LIST_DATA(o, i));
+ HWND hWndParent = GetParent(h);
+ RECT current_rect;
+ char class_name[MAX_PATH];
+ bool is_image = false;
+
+ // Get the class name
+ Zero(class_name, sizeof(class_name));
+ GetClassNameA(h, class_name, sizeof(class_name));
+
+ if (StrCmpi(class_name, "static") == 0)
+ {
+ if (SendMsg(h, 0, STM_GETIMAGE, IMAGE_BITMAP, 0) != 0 ||
+ SendMsg(h, 0, STM_GETIMAGE, IMAGE_ICON, 0) != 0 ||
+ SendMsg(h, 0, STM_GETICON, 0, 0) != 0)
+ {
+ is_image = true;
+ }
+ }
+
+ // Get the position
+ if (GetWindowRect(h, &current_rect))
+ {
+ // Convert to client coordinates
+ POINT p1, p2;
+
+ p1.x = current_rect.left;
+ p1.y = current_rect.top;
+
+ p2.x = current_rect.right;
+ p2.y = current_rect.bottom;
+
+ ScreenToClient(hWndParent, &p1);
+ ScreenToClient(hWndParent, &p2);
+
+ // Adjust the position
+ AdjustDialogXY(&p1.x, &p1.y, dlgfont_x, dlgfont_y);
+ AdjustDialogXY(&p2.x, &p2.y, dlgfont_x, dlgfont_y);
+
+ if (is_image)
+ {
+ p2.x = p1.x + (current_rect.right - current_rect.left);
+ p2.y = p1.y + (current_rect.bottom - current_rect.top);
+ }
+
+ // Move
+ MoveWindow(h, p1.x, p1.y, p2.x - p1.x, p2.y - p1.y, false);
+ }
+ }
+
+ FreeWindowList(o);
+}
+
+// Adjust the values of x and y according to the font
+void AdjustDialogXY(UINT *x, UINT *y, UINT dlgfont_x, UINT dlgfont_y)
+{
+ if (x != NULL)
+ {
+ *x = (UINT)(((double)*x) * (double)WINUI_DEFAULT_DIALOG_UNIT_X / (double)dlgfont_x);
+ }
+
+ if (y != NULL)
+ {
+ *y = (UINT)(((double)*y) * (double)WINUI_DEFAULT_DIALOG_UNIT_Y / (double)dlgfont_y);
+ }
+}
+
+// Internationalizing process for the dialog box
+void InitDialogInternational(HWND hWnd, void *pparam)
+{
+ LIST *o;
+ UINT i;
+ bool is_managed_dialog = false;
+ char caption[MAX_PATH];
+ char *dialog_name;
+ DIALOG_PARAM *param = (DIALOG_PARAM *)pparam;
+ HDC hDC;
+ bool need_resize = false;
+ double factor_x = 0.0, factor_y = 0.0;
+ // Validate arguments
+ if (hWnd == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hDC = CreateCompatibleDC(NULL);
+
+ AdjustWindowAndControlSize(hWnd, &need_resize, &factor_x, &factor_y);
+
+ GetTxtA(hWnd, 0, caption, sizeof(caption));
+ if (caption[0] == '@')
+ {
+ dialog_name = &caption[1];
+
+ is_managed_dialog = true;
+ }
+
+ // Enumerate all window handles
+ o = EnumAllChildWindow(hWnd);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND hControl = *((HWND *)LIST_DATA(o, i));
+
+ if (hControl != NULL)
+ {
+ HFONT hFont = GetDialogDefaultFontEx(param && ((DIALOG_PARAM *)param)->meiryo);
+
+ SetFont(hControl, 0, hFont);
+
+ if (MsIsVista())
+ {
+ char classname[MAX_PATH];
+ GetClassNameA(hControl, classname, sizeof(classname));
+
+ if (StrCmpi(classname, "syslistview32") == 0)
+ {
+ InitVistaWindowTheme(hControl);
+ }
+ }
+
+ if (is_managed_dialog)
+ {
+ char str[MAX_PATH];
+
+ GetTxtA(hControl, 0, str, sizeof(str));
+ if (str[0] == '@')
+ {
+ char *control_name = &str[1];
+ char tmp[MAX_PATH];
+ wchar_t *ret;
+
+ StrCpy(tmp, sizeof(tmp), dialog_name);
+ StrCat(tmp, sizeof(tmp), "@");
+
+ if (hWnd == hControl)
+ {
+ StrCat(tmp, sizeof(tmp), "CAPTION");
+ }
+ else
+ {
+ StrCat(tmp, sizeof(tmp), control_name);
+ }
+
+ ret = _UU(tmp);
+
+ if (ret != NULL && UniIsEmptyStr(ret) == false)
+ {
+ SetText(hControl, 0, ret);
+ }
+ }
+ }
+ }
+ }
+
+ FreeWindowList(o);
+
+ if (MsIsVista() && need_resize)
+ {
+ // Since the window size is changed automatically by the OS by the dpi setting
+ // in Windows Vista or later, a static (bitmap) control needs to be expanded
+ // by anticipating the size after changing
+
+ // Enumerate all child window (not recursive)
+ o = EnumAllChildWindowEx(hWnd, true, false, true);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND hControl = *((HWND *)LIST_DATA(o, i));
+
+ if (hControl != NULL)
+ {
+ char class_name[MAX_SIZE];
+
+ Zero(class_name, sizeof(class_name));
+ GetClassNameA(hControl, class_name, sizeof(class_name));
+
+ if (StrCmpi(class_name, "static") == 0)
+ {
+ UINT style = GetStyle(hControl, 0);
+
+ if (style & SS_BITMAP)
+ {
+ // Get the Bitmap
+ HBITMAP hBitmap = (HBITMAP)SendMessage(hControl, STM_GETIMAGE, IMAGE_BITMAP, 0);
+
+ if (hBitmap != NULL)
+ {
+ // Get the size of this bitmap
+ UINT src_x;
+ UINT src_y;
+
+ if (GetBitmapSize(hBitmap, &src_x, &src_y))
+ {
+ RECT ctl_rect;
+
+ Zero(&ctl_rect, sizeof(ctl_rect));
+
+ if (GetWindowRect(hControl, &ctl_rect))
+ {
+ // Use the smaller magnification of the height and the width
+ //double scale_factor = 1.5;
+ double scale_factor = MIN(factor_x, factor_y);
+ UINT dst_x = (UINT)((double)src_x * scale_factor);
+ UINT dst_y = (UINT)((double)src_y * scale_factor);
+
+ HBITMAP hDst = ResizeBitmap(hBitmap, src_x, src_y, dst_x, dst_y);
+
+ if (hDst != NULL)
+ {
+ Add(param->BitmapList, hDst);
+
+ SendMessage(hControl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hDst);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeWindowList(o);
+ }
+
+ DeleteDC(hDC);
+}
+
+// Get the size of the bitmap
+bool GetBitmapSize(void *bmp, UINT *x, UINT *y)
+{
+ BITMAP info;
+ // Validate arguments
+ if (bmp == NULL || x == NULL || y == NULL)
+ {
+ return false;
+ }
+
+ Zero(&info, sizeof(info));
+ if (GetObject((HANDLE)bmp, sizeof(info), &info) == 0)
+ {
+ return false;
+ }
+
+ *x = info.bmWidth;
+ *y = info.bmHeight;
+
+ return true;
+}
+
+// Resize the bitmap
+HBITMAP ResizeBitmap(HBITMAP hSrc, UINT src_x, UINT src_y, UINT dst_x, UINT dst_y)
+{
+ HDC hMemDC;
+ HDC hSrcDC;
+ HBITMAP ret = NULL;
+ BITMAPINFOHEADER h;
+ BITMAPINFO bi;
+ UCHAR *data = NULL;
+ // Validate arguments
+ if (hSrc == NULL)
+ {
+ return NULL;
+ }
+
+ hSrcDC = CreateCompatibleDC(NULL);
+ if (hSrcDC != NULL)
+ {
+ HBITMAP hOld = SelectObject(hSrcDC, hSrc);
+
+ if (hOld != NULL)
+ {
+ hMemDC = CreateCompatibleDC(NULL);
+
+ if (hMemDC != NULL)
+ {
+ HBITMAP hOld;
+ HBITMAP srcHbitMap;
+ UCHAR* srcData;
+ CT_RectF_c destRect;
+ CT_RectF_c srcRect;
+
+ Zero(&h, sizeof(h));
+ h.biSize = sizeof(h);
+ h.biWidth = src_x;
+ h.biHeight = src_y;
+ h.biPlanes = 1;
+ h.biBitCount = 32;
+ h.biXPelsPerMeter = 2834;
+ h.biYPelsPerMeter = 2834;
+ h.biCompression = BI_RGB;
+
+ // Copy once the transfer source
+ Zero(&bi, sizeof(bi));
+ Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
+ srcHbitMap = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &srcData, NULL, 0);
+
+ hOld = SelectObject(hMemDC, srcHbitMap);
+
+ BitBlt(hMemDC,0,0,src_x,src_y,hSrcDC,0,0, SRCCOPY);
+
+ GdiFlush();
+
+
+
+ // Generate a resized version
+ if(src_x != dst_x || src_y != dst_y)
+ {
+ h.biWidth = dst_x;
+ h.biHeight = dst_y;
+ Zero(&bi, sizeof(bi));
+ Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
+
+ ret = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &data, NULL, 0);
+
+ if(srcData != NULL && data != NULL)
+ {
+ destRect.X = 0; destRect.Y = 0;
+ destRect.Width = (float)dst_x; destRect.Height = (float)dst_y;
+ srcRect = destRect;
+ srcRect.Width = (float)src_x; srcRect.Height = (float)src_y;
+
+ CT_DrawImage((UCHAR*)data, destRect, dst_x,dst_y,
+ (UCHAR*)srcData, srcRect,src_x, src_y);
+ }
+
+ if(srcHbitMap != NULL)
+ {
+ DeleteObject(srcHbitMap);
+ }
+ }
+ else
+ {
+ ret = srcHbitMap;
+ }
+
+ SelectObject(hMemDC, hOld);
+
+ DeleteDC(hMemDC);
+ }
+
+ SelectObject(hSrcDC, hOld);
+ }
+
+ DeleteDC(hSrcDC);
+ }
+
+ return ret;
+}
+
+// Initialize the bitmap list
+LIST *NewBitmapList()
+{
+ LIST *o = NewListFast(NULL);
+
+ return o;
+}
+
+// Release the bitmap list
+void FreeBitmapList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HBITMAP *h = LIST_DATA(o, i);
+
+ DeleteObject(h);
+ }
+
+ ReleaseList(o);
+}
+
+// Child window enumeration procedure
+// Initialize the dialog
+void StringDlgInit(HWND hWnd, STRING_DLG *s)
+{
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ SetText(hWnd, E_STRING, s->String);
+
+ SetIcon(hWnd, S_ICON, s->Icon);
+ SetText(hWnd, S_INFO, s->Info);
+ SetText(hWnd, 0, s->Title);
+
+ FocusEx(hWnd, E_STRING);
+
+ StringDlgUpdate(hWnd, s);
+}
+
+// Update the dialog control
+void StringDlgUpdate(HWND hWnd, STRING_DLG *s)
+{
+ wchar_t *tmp;
+ bool b = true;
+ // Validate arguments
+ if (hWnd == NULL || s == NULL)
+ {
+ return;
+ }
+
+ tmp = GetText(hWnd, E_STRING);
+
+ if (tmp != NULL)
+ {
+ if (s->AllowEmpty == false)
+ {
+ if (UniIsEmptyStr(tmp))
+ {
+ b = false;
+ }
+ }
+
+ if (s->AllowUnsafe == false)
+ {
+ if (IsSafeUniStr(tmp) == false)
+ {
+ b = false;
+ }
+ }
+
+ Free(tmp);
+ }
+
+ SetEnable(hWnd, IDOK, b);
+}
+
+// String dialog procedure
+UINT StringDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ STRING_DLG *s = (STRING_DLG *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ StringDlgInit(hWnd, s);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case E_STRING:
+ StringDlgUpdate(hWnd, s);
+ break;
+ }
+
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxt(hWnd, E_STRING, s->String, sizeof(s->String));
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the string dialog
+wchar_t *StringDlg(HWND hWnd, wchar_t *title, wchar_t *info, wchar_t *def, UINT icon, bool allow_empty, bool allow_unsafe)
+{
+ STRING_DLG s;
+ // Validate arguments
+ if (title == NULL)
+ {
+ title = _UU("DLG_STRING_DEFTITLE");
+ }
+ if (info == NULL)
+ {
+ info = _UU("DLG_STRING_DEFINFO");
+ }
+ if (def == NULL)
+ {
+ def = L"";
+ }
+ if (icon == 0)
+ {
+ icon = ICO_NULL;
+ }
+
+ Zero(&s, sizeof(s));
+ s.Icon = icon;
+ s.Info = info;
+ s.Title = title;
+ s.Icon = icon;
+ UniStrCpy(s.String, sizeof(s.String), def);
+ s.AllowEmpty = allow_empty;
+ s.AllowUnsafe = allow_unsafe;
+
+ if (Dialog(hWnd, D_STRING, StringDlgProc, &s) == false)
+ {
+ return NULL;
+ }
+ else
+ {
+ return CopyUniStr(s.String);
+ }
+}
+char *StringDlgA(HWND hWnd, wchar_t *title, wchar_t *info, char *def, UINT icon, bool allow_empty, bool allow_unsafe)
+{
+ wchar_t unidef[MAX_SIZE];
+ wchar_t *tmp;
+ char *ret;
+ if (def == NULL)
+ {
+ def = "";
+ }
+
+ StrToUni(unidef, sizeof(unidef), def);
+
+ tmp = StringDlg(hWnd, title, info, unidef, icon, allow_empty, allow_unsafe);
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = CopyUniToStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Draw frame
+void LedDrawRect(LED *d)
+{
+ RECT r;
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ SetRect(&r, 0, 0, LED_WIDTH, LED_HEIGHT);
+ FrameRect(d->hDC, &r, GetStockObject(WHITE_BRUSH));
+}
+
+// Restarting dialog
+UINT Win9xRebootDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WIN9X_REBOOT_DLG *d = (WIN9X_REBOOT_DLG *)param;
+ UINT64 now;
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ d->StartTime = Tick64();
+ SetRange(hWnd, P_PROGRESS, 0, d->TotalTime);
+ SetTimer(hWnd, 1, 100, NULL);
+ goto UPDATE;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+UPDATE:
+ now = Tick64();
+ if ((d->StartTime + (UINT64)d->TotalTime) <= now)
+ {
+ KillTimer(hWnd, 1);
+ UniStrCpy(tmp, sizeof(tmp), _UU("DLG_REBOOT_INFO_2"));
+ SetText(hWnd, S_INFO, tmp);
+ if (MsShutdown(true, false) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_REBOOT_ERROR"));
+ }
+ EndDialog(hWnd, 0);
+ }
+ else
+ {
+ SetPos(hWnd, P_PROGRESS, (UINT)(now - d->StartTime));
+ UniFormat(tmp, sizeof(tmp), _UU("DLG_REBOOT_INFO"),
+ (UINT)((UINT64)d->TotalTime - (now - d->StartTime)) / 1000 + 1);
+ SetText(hWnd, S_INFO, tmp);
+ }
+
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+
+// Restarting thread
+void Win9xRebootThread(THREAD *t, void *p)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Win9xReboot(NULL);
+}
+
+// Restart automatically
+void Win9xReboot(HWND hWnd)
+{
+ WIN9X_REBOOT_DLG d;
+
+ Zero(&d, sizeof(d));
+ d.TotalTime = 10 * 1000;
+
+ Dialog(hWnd, D_WIN9X_REBOOT, Win9xRebootDlgProc, &d);
+}
+
+// Show a text file
+void ShowTextFile(HWND hWnd, char *filename, wchar_t *caption, UINT icon)
+{
+ BUF *b;
+ wchar_t *str;
+ // Validate arguments
+ if (filename == NULL || caption == NULL)
+ {
+ return;
+ }
+ if (icon == 0)
+ {
+ icon = ICO_NULL;
+ }
+
+ // Read the text file
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBufToEnd(b);
+ WriteBufChar(b, 0);
+
+ str = CopyUtfToUni(b->Buf);
+
+ OnceMsg(hWnd, caption, str, false, icon);
+
+ FreeBuf(b);
+ Free(str);
+}
+
+// Initialize the version information
+void AboutDlgInit(HWND hWnd, WINUI_ABOUT *a)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || a == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, ICO_INFORMATION);
+
+ UniFormat(tmp, sizeof(tmp), _UU("ABOUT_CAPTION"), a->ProductName);
+ SetText(hWnd, 0, tmp);
+
+ SetFont(hWnd, S_INFO1, GetFont("Arial", 12, false, false, false, false));
+ FormatText(hWnd, S_INFO1, CEDAR_VER / 100, CEDAR_VER / 100, CEDAR_VER % 100, CEDAR_BUILD);
+
+ SetFont(hWnd, S_INFO2, GetFont("Arial", 8, false, false, false, false));
+ FormatText(hWnd, S_INFO2, BUILD_DATE_Y, a->Cedar->BuildInfo);
+
+ SetFont(hWnd, S_INFO3, GetFont("Arial", 7, false, false, false, false));
+
+ //DlgFont(hWnd, S_INFO4, 8, false);
+
+ SetShow(hWnd, B_UPDATE_CONFIG, (a->Update != NULL));
+}
+
+// Version information procedure
+UINT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINUI_ABOUT *a = (WINUI_ABOUT *)param;
+ char tmp[MAX_PATH];
+ LANGLIST t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ AboutDlgInit(hWnd, a);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ if ((GetKeyState(VK_SHIFT) & 0x8000) &&
+ (GetKeyState(VK_CONTROL) & 0x8000) &&
+ (GetKeyState(VK_MENU) & 0x8000))
+ {
+ ShowEasterEgg(hWnd);
+ }
+ EndDialog(hWnd, true);
+ break;
+ case B_WEB:
+ ShellExecute(hWnd, "open", _SS("SE_COMPANY_URL"), NULL, NULL, SW_SHOW);
+ break;
+ case B_EULA:
+ ShowTextFile(hWnd, "|eula.txt", _UU("SW_EULA_TITLE"), ICO_LOG);
+ break;
+ case B_IMPORTANT:
+ GetCurrentLang(&t);
+ Format(tmp, sizeof(tmp), "|warning_%s.txt", t.Name);
+ ShowTextFile(hWnd, tmp, _UU("SW_WARNING_TITLE"), ICO_LOG);
+ break;
+ case B_LEGAL:
+ ShowTextFile(hWnd, "|legal.txt", _UU("DLG_ABOUT_LEGAL"), ICO_LOG);
+ break;
+ case B_UPDATE_CONFIG:
+ ConfigUpdateUi(a->Update, hWnd);
+ break;
+ case B_LANGUAGE:
+ // Language settings
+ if (true)
+ {
+ wchar_t path[MAX_SIZE];
+
+ CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"vpnsetup.exe");
+
+ if (MsExecuteW(path, L"/language:yes") == false)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Version information
+void About(HWND hWnd, CEDAR *cedar, wchar_t *product_name)
+{
+ AboutEx(hWnd, cedar, product_name, NULL);
+}
+void AboutEx(HWND hWnd, CEDAR *cedar, wchar_t *product_name, WINUI_UPDATE *u)
+{
+ WINUI_ABOUT a;
+ // Validate arguments
+ if (cedar == NULL || product_name == NULL)
+ {
+ return;
+ }
+
+ Zero(&a, sizeof(a));
+ a.Cedar = cedar;
+ a.ProductName = product_name;
+ a.Update = u;
+
+ Dialog(hWnd, D_ABOUT, AboutDlgProc, &a);
+}
+
+// Test
+void UiTest()
+{
+}
+
+// Examine the number of fields that an IP address is entered
+UINT IpGetFilledNum(HWND hWnd, UINT id)
+{
+ UINT ret;
+ DWORD value;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
+
+ return ret;
+}
+
+// Examine whether an IP address has been entered
+bool IpIsFilled(HWND hWnd, UINT id)
+{
+ UINT ret;
+ DWORD value;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
+
+ if (ret != 4)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Clear the IP address
+void IpClear(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, IPM_CLEARADDRESS, 0, 0);
+}
+
+// Get an IP address
+UINT IpGet(HWND hWnd, UINT id)
+{
+ UINT ret;
+ DWORD value;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
+
+ if (ret != 4)
+ {
+ return 0;
+ }
+ else
+ {
+ return Endian32((UINT)value);
+ }
+}
+
+// Set the IP addresses
+void IpSet(HWND hWnd, UINT id, UINT ip)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, IPM_SETADDRESS, 0, Endian32(ip));
+}
+
+// Write the candidates to the registry
+void WriteCandidateToReg(UINT root, char *key, LIST *o, char *name)
+{
+ BUF *b;
+ // Validate arguments
+ if (key == NULL || o == NULL || name == NULL)
+ {
+ return;
+ }
+
+ b = CandidateToBuf(o);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteBin(root, key, name, b->Buf, b->Size);
+
+ FreeBuf(b);
+}
+
+// Read the candidates from the registry
+LIST *ReadCandidateFromReg(UINT root, char *key, char *name)
+{
+ BUF *b;
+ // Validate arguments
+ if (key == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = MsRegReadBin(root, key, name);
+ if (b == NULL)
+ {
+ return NewCandidateList();
+ }
+ else
+ {
+ LIST *o = BufToCandidate(b);
+ FreeBuf(b);
+
+ return o;
+ }
+}
+
+// initialize the remote connection dialog
+void RemoteDlgInit(HWND hWnd, WINUI_REMOTE *r)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ SetIcon(hWnd, 0, r->Icon);
+
+ SetText(hWnd, 0, r->Caption);
+ SetText(hWnd, S_TITLE, r->Title);
+ SetIcon(hWnd, S_ICON, r->Icon);
+
+ // Read candidates
+ o = ReadCandidateFromReg(REG_CURRENT_USER, r->RegKeyName, "RemoteHostCandidate");
+ r->CandidateList = o;
+
+ // Show the candidates
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ CbAddStr(hWnd, C_HOSTNAME, c->Str, 0);
+ }
+
+ if (r->DefaultHostname != NULL)
+ {
+ SetTextA(hWnd, C_HOSTNAME, r->DefaultHostname);
+ }
+
+ FocusEx(hWnd, C_HOSTNAME);
+
+ RemoteDlgRefresh(hWnd, r);
+}
+
+// Remote connection dialog update
+void RemoteDlgRefresh(HWND hWnd, WINUI_REMOTE *r)
+{
+ char *s;
+ bool ok = true;
+ bool localhost_mode = false;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ s = GetTextA(hWnd, C_HOSTNAME);
+ if (s != NULL)
+ {
+ Trim(s);
+ if (StrCmpi(s, "localhost") == 0 || StartWith(s, "127."))
+ {
+ localhost_mode = true;
+ }
+ Free(s);
+ }
+
+ if (localhost_mode == false)
+ {
+ Enable(hWnd, C_HOSTNAME);
+ Enable(hWnd, S_HOSTNAME);
+ Check(hWnd, R_LOCAL, false);
+ }
+ else
+ {
+ if (r->Title != _UU("NM_CONNECT_TITLE"))
+ {
+ Disable(hWnd, C_HOSTNAME);
+ Disable(hWnd, S_HOSTNAME);
+ }
+ Check(hWnd, R_LOCAL, true);
+ SetTextA(hWnd, C_HOSTNAME, "localhost");
+
+ if (r->flag1 == false)
+ {
+ Focus(hWnd, IDOK);
+ }
+ }
+
+ if (IsEmpty(hWnd, C_HOSTNAME))
+ {
+ ok = false;
+ }
+
+ SetEnable(hWnd, IDOK, ok);
+
+ r->flag1 = true;
+}
+
+// Remote connection dialog OK button
+void RemoteDlgOnOk(HWND hWnd, WINUI_REMOTE *r)
+{
+ char *hostname;
+ wchar_t *s;
+ LIST *o;
+ // Validate arguments
+ if (hWnd == NULL || r == NULL)
+ {
+ return;
+ }
+
+ // Get the entered host name
+ hostname = GetTextA(hWnd, C_HOSTNAME);
+ if (hostname == NULL)
+ {
+ return;
+ }
+ Trim(hostname);
+
+ // Add a candidate
+ o = r->CandidateList;
+ s = CopyStrToUni(hostname);
+ AddCandidate(o, s, 64);
+ Free(s);
+
+ // Write the candidates
+ WriteCandidateToReg(REG_CURRENT_USER, r->RegKeyName, o, "RemoteHostCandidate");
+ FreeCandidateList(o);
+
+ r->Hostname = hostname;
+
+ EndDialog(hWnd, true);
+}
+
+// Remote connection dialog procedure
+UINT RemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ WINUI_REMOTE *r = (WINUI_REMOTE *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ RemoteDlgInit(hWnd, r);
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ RemoteDlgRefresh(hWnd, r);
+ SetTimer(hWnd, 1, 100, NULL);
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case R_LOCAL:
+ if (IsChecked(hWnd, R_LOCAL) == false)
+ {
+ SetTextA(hWnd, C_HOSTNAME, "");
+ RemoteDlgRefresh(hWnd, r);
+ FocusEx(hWnd, C_HOSTNAME);
+ }
+ else
+ {
+ SetTextA(hWnd, C_HOSTNAME, "localhost");
+ RemoteDlgRefresh(hWnd, r);
+ Focus(hWnd, IDOK);
+ }
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case IDOK:
+ RemoteDlgOnOk(hWnd, r);
+ break;
+ }
+ switch (LOWORD(wParam))
+ {
+ case R_LOCAL:
+ case C_HOSTNAME:
+ RemoteDlgRefresh(hWnd, r);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ FreeCandidateList(r->CandidateList);
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Remote connection dialog
+char *RemoteDlg(HWND hWnd, char *regkey, UINT icon, wchar_t *caption, wchar_t *title, char *default_host)
+{
+ WINUI_REMOTE r;
+ // Validate arguments
+ if (regkey == NULL)
+ {
+ regkey = "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\WinUI Common Module";
+ }
+ if (caption == NULL)
+ {
+ caption = _UU("REMOTE_DEF_CAPTION");
+ }
+ if (title == NULL)
+ {
+ title = _UU("REMOTE_DEF_TITLE");
+ }
+ if (icon == 0)
+ {
+ icon = ICO_INTERNET;
+ }
+
+ Zero(&r, sizeof(r));
+ r.RegKeyName = regkey;
+ r.Caption = caption;
+ r.Title = title;
+ r.Icon = icon;
+ r.DefaultHostname = default_host;
+
+ if (Dialog(hWnd, D_REMOTE, RemoteDlgProc, &r) == false)
+ {
+ return NULL;
+ }
+
+ return r.Hostname;
+}
+
+// Window Searching procedure
+bool CALLBACK SearchWindowEnumProc(HWND hWnd, LPARAM lParam)
+{
+ if (hWnd != NULL && lParam != 0)
+ {
+ wchar_t *s = GetText(hWnd, 0);
+ SEARCH_WINDOW_PARAM *p = (SEARCH_WINDOW_PARAM *)lParam;
+ if (s != NULL)
+ {
+ if (UniStrCmpi(p->caption, s) == 0)
+ {
+ p->hWndFound = hWnd;
+ }
+ Free(s);
+ }
+ }
+ return true;
+}
+
+// Search for the window
+HWND SearchWindow(wchar_t *caption)
+{
+ SEARCH_WINDOW_PARAM p;
+ // Validate arguments
+ if (caption == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&p, sizeof(p));
+ p.caption = caption;
+ p.hWndFound = NULL;
+
+ EnumWindows(SearchWindowEnumProc, (LPARAM)&p);
+
+ return p.hWndFound;
+}
+
+// Allow for the specified process to become the foreground window
+void AllowFGWindow(UINT process_id)
+{
+ if (process_id == 0)
+ {
+ return;
+ }
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&
+ GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ AllowSetForegroundWindow(process_id);
+ }
+}
+
+// Rename the item
+void LvRename(HWND hWnd, UINT id, UINT pos)
+{
+ // Validate arguments
+ if (hWnd == NULL || pos == INFINITE)
+ {
+ return;
+ }
+
+ ListView_EditLabel(DlgItem(hWnd, id), pos);
+}
+
+// Show the menu
+void PrintMenu(HWND hWnd, HMENU hMenu)
+{
+ POINT p;
+ // Validate arguments
+ if (hMenu == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ GetCursorPos(&p);
+
+ TrackPopupMenu(hMenu, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
+}
+
+// Remove a shortcut string from the menu
+void RemoveShortcutKeyStrFromMenu(HMENU hMenu)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hMenu == NULL)
+ {
+ return;
+ }
+
+ num = GetMenuNum(hMenu);
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *str = GetMenuStr(hMenu, i);
+ if (str != NULL)
+ {
+ UINT j, len;
+ len = UniStrLen(str);
+ for (j = 0;j < len;j++)
+ {
+ if (str[j] == L'\t')
+ {
+ str[j] = 0;
+ }
+ }
+ SetMenuStr(hMenu, i, str);
+ Free(str);
+ }
+ }
+}
+
+// Get the number of items in the menu
+UINT GetMenuNum(HMENU hMenu)
+{
+ UINT ret;
+ // Validate arguments
+ if (hMenu == NULL)
+ {
+ return 0;
+ }
+
+ ret = GetMenuItemCount(hMenu);
+ if (ret == INFINITE)
+ {
+ return 0;
+ }
+ else
+ {
+ return ret;
+ }
+}
+
+// Set the string into the menu
+void SetMenuStr(HMENU hMenu, UINT pos, wchar_t *str)
+{
+ MENUITEMINFOW info;
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE || str == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ SetMenuStrA(hMenu, pos, s);
+ Free(s);
+ return;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STRING;
+ info.dwTypeData = str;
+ SetMenuItemInfoW(hMenu, pos, true, &info);
+}
+void SetMenuStrA(HMENU hMenu, UINT pos, char *str)
+{
+ MENUITEMINFOA info;
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE || str == NULL)
+ {
+ return;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STRING;
+ info.dwTypeData = str;
+ SetMenuItemInfoA(hMenu, pos, true, &info);
+}
+
+// Get a string in the menu
+wchar_t *GetMenuStr(HMENU hMenu, UINT pos)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE)
+ {
+ return NULL;
+ }
+ if (MsIsNt() == false)
+ {
+ char *s = GetMenuStrA(hMenu, pos);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ wchar_t *ret = CopyStrToUni(s);
+ Free(s);
+ return ret;
+ }
+ }
+
+ if (GetMenuStringW(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
+ {
+ return NULL;
+ }
+
+ return UniCopyStr(tmp);
+}
+char *GetMenuStrA(HMENU hMenu, UINT pos)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE)
+ {
+ return NULL;
+ }
+
+ if (GetMenuString(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
+ {
+ return NULL;
+ }
+
+ return CopyStr(tmp);
+}
+
+// Bold the menu item
+void SetMenuItemBold(HMENU hMenu, UINT pos, bool bold)
+{
+ MENUITEMINFO info;
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE)
+ {
+ return;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+
+ if (GetMenuItemInfo(hMenu, pos, true, &info) == false)
+ {
+ return;
+ }
+
+ if (bold)
+ {
+ info.fState |= MFS_DEFAULT;
+ }
+ else
+ {
+ info.fState = info.fState & ~MFS_DEFAULT;
+ }
+
+ SetMenuItemInfo(hMenu, pos, true, &info);
+}
+
+// Enable / disable the menu item
+void SetMenuItemEnable(HMENU hMenu, UINT pos, bool enable)
+{
+ MENUITEMINFO info;
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE)
+ {
+ return;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+
+ if (GetMenuItemInfo(hMenu, pos, true, &info) == false)
+ {
+ return;
+ }
+
+ if (enable)
+ {
+ info.fState |= MFS_ENABLED;
+ info.fState = info.fState & ~MFS_DISABLED;
+ }
+ else
+ {
+ info.fState |= MFS_DISABLED;
+ info.fState = info.fState & ~MFS_ENABLED;
+ }
+
+ SetMenuItemInfo(hMenu, pos, true, &info);
+}
+
+// Remove a menu item
+void DeleteMenuItem(HMENU hMenu, UINT pos)
+{
+ // Validate arguments
+ if (hMenu == NULL || pos == INFINITE)
+ {
+ return;
+ }
+
+ DeleteMenu(hMenu, pos, MF_BYPOSITION);
+}
+
+// Get the position from the ID in the menu
+UINT GetMenuItemPos(HMENU hMenu, UINT id)
+{
+ UINT num, i;
+ // Validate arguments
+ if (hMenu == NULL)
+ {
+ return INFINITE;
+ }
+
+ num = GetMenuItemCount(hMenu);
+ if (num == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ if (GetMenuItemID(hMenu, i) == id)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Get a sub-menu
+HMENU LoadSubMenu(UINT menu_id, UINT pos, HMENU *parent_menu)
+{
+ HMENU h = LoadMenu(hDll, MAKEINTRESOURCE(menu_id));
+ HMENU ret;
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ ret = GetSubMenu(h, pos);
+
+ if (parent_menu != NULL)
+ {
+ *parent_menu = h;
+ }
+
+ return ret;
+}
+
+// Get the DLL of the user interface
+HINSTANCE GetUiDll()
+{
+ return hDll;
+}
+
+// Connection Error dialog procedure
+UINT ConnectErrorDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UI_CONNECTERROR_DLG *p = (UI_CONNECTERROR_DLG *)param;
+ wchar_t tmp[1024];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (p->Err == ERR_DISCONNECTED || p->Err == ERR_SESSION_TIMEOUT)
+ {
+ // Message indicating that the connection has been disconnected
+ SetText(hWnd, S_TITLE, _UU("ERRDLG_DISCONNECTED_MSG"));
+ }
+ if (p->HideWindow)
+ {
+ Hide(hWnd, R_HIDE);
+ }
+ FormatText(hWnd, 0, p->AccountName);
+ FormatText(hWnd, S_TITLE, p->ServerName);
+ UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_ERRMSG"), p->Err, _E(p->Err));
+ SetText(hWnd, E_ERROR, tmp);
+
+ SetIcon(hWnd, 0, ICO_SERVER_OFFLINE);
+
+ if (p->RetryIntervalSec == 0)
+ {
+ SetText(hWnd, S_COUNTDOWN, _UU("ERRDLG_INFORMATION"));
+ Hide(hWnd, P_PROGRESS);
+ Hide(hWnd, S_RETRYINFO);
+ }
+ else
+ {
+ if (p->RetryLimit != INFINITE)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_1"), p->CurrentRetryCount, p->RetryLimit);
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_2"), p->CurrentRetryCount);
+ }
+ SetText(hWnd, S_RETRYINFO, tmp);
+ SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec);
+ SetPos(hWnd, P_PROGRESS, 0);
+ SetTimer(hWnd, 1, 10, NULL);
+ p->StartTick = Tick64();
+ }
+ SetTimer(hWnd, 2, 10, NULL);
+ Focus(hWnd, IDOK);
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (p->RetryIntervalSec != 0)
+ {
+ UINT64 start, end, now;
+ now = Tick64();
+ start = p->StartTick;
+ end = start + (UINT64)p->RetryIntervalSec;
+
+ if (end > now)
+ {
+ SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
+ UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRYCOUNT"), ((UINT)(end - now)) / 1000);
+ SetText(hWnd, S_COUNTDOWN, tmp);
+ }
+ else
+ {
+ Command(hWnd, IDOK);
+ }
+ }
+ break;
+ case 2:
+ if (p->CancelEvent != NULL)
+ {
+ if (WaitForSingleObject((HANDLE)p->CancelEvent->pData, 0) != WAIT_TIMEOUT)
+ {
+ // Forced Cancel
+ Close(hWnd);
+ }
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case R_HIDE:
+ p->HideWindow = IsChecked(hWnd, R_HIDE);
+ break;
+ }
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog(hWnd, true);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Show the connection error dialog
+bool ConnectErrorDlg(UI_CONNECTERROR_DLG *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return DialogEx2(NULL, D_CONNECTERROR, ConnectErrorDlgProc, p, true, true);
+}
+
+// Display the contents of the certificate
+void PrintCheckCertInfo(HWND hWnd, UI_CHECKCERT *p)
+{
+ wchar_t tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UCHAR md5[MD5_SIZE];
+ UCHAR sha1[SHA1_SIZE];
+ X *x;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ x = p->x;
+
+ GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
+ SetText(hWnd, E_SUBJECT, tmp);
+
+ GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
+ SetText(hWnd, E_ISSUER, tmp);
+
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
+ SetText(hWnd, E_EXPIRES, tmp);
+
+ GetXDigest(x, md5, false);
+ BinToStr(tmp2, sizeof(tmp2), md5, sizeof(md5));
+ SetTextA(hWnd, E_MD5, tmp2);
+
+ GetXDigest(x, sha1, true);
+ BinToStr(tmp2, sizeof(tmp2), sha1, sizeof(sha1));
+ SetTextA(hWnd, E_SHA1, tmp2);
+
+ SetFont(hWnd, E_MD5, GetFont("Arial", 8, false, false, false, false));
+ SetFont(hWnd, E_SHA1, GetFont("Arial", 8, false, false, false, false));
+}
+
+// Warn that the certificate is different
+void ShowDlgDiffWarning(HWND hWnd, UI_CHECKCERT *p)
+{
+ UCHAR sha1_new[SHA1_SIZE], sha1_old[SHA1_SIZE];
+ UCHAR md5_new[MD5_SIZE], md5_old[MD5_SIZE];
+ char sha1_new_str[MAX_SIZE], sha1_old_str[MAX_SIZE];
+ char md5_new_str[MAX_SIZE], md5_old_str[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || p->x == NULL || p->old_x == NULL)
+ {
+ return;
+ }
+
+ GetXDigest(p->x, sha1_new, true);
+ GetXDigest(p->x, md5_new, false);
+
+ GetXDigest(p->old_x, sha1_old, true);
+ GetXDigest(p->old_x, md5_old, false);
+
+ BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
+ BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
+ BinToStrEx(sha1_old_str, sizeof(sha1_old_str), sha1_old, sizeof(sha1_old));
+ BinToStrEx(md5_old_str, sizeof(md5_old_str), md5_old, sizeof(md5_old));
+
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CC_DANGEROUS_MSG"),
+ p->ServerName, md5_old_str, sha1_old_str, md5_new_str, sha1_new_str);
+}
+
+// [OK] button is pressed
+void CheckCertDialogOnOk(HWND hWnd, UI_CHECKCERT *p)
+{
+ UCHAR sha1_new[SHA1_SIZE];
+ UCHAR md5_new[MD5_SIZE];
+ char sha1_new_str[MAX_SIZE];
+ char md5_new_str[MAX_SIZE];
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ GetXDigest(p->x, sha1_new, true);
+ GetXDigest(p->x, md5_new, false);
+ BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
+ BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
+
+ ret = MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2,
+ _UU("CC_WARNING_MSG"),
+ p->AccountName, sha1_new_str, md5_new_str);
+
+ if (ret == IDYES)
+ {
+ p->SaveServerCert = true;
+ }
+
+ if (ret == IDCANCEL)
+ {
+ return;
+ }
+
+ p->Ok = true;
+ EndDialog(hWnd, true);
+}
+
+// Certificate dialog procedure
+UINT CheckCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UI_CHECKCERT *p = (UI_CHECKCERT *)param;
+ // Validate arguments
+ if (hWnd == NULL || param == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ FormatText(hWnd, 0, p->AccountName);
+ FormatText(hWnd, S_TITLE, p->ServerName);
+ FormatText(hWnd, S_MSG1, p->ServerName);
+
+ PrintCheckCertInfo(hWnd, p);
+
+ Focus(hWnd, IDCANCEL);
+
+ SetIcon(hWnd, 0, ICO_WARNING);
+
+ if (p->DiffWarning)
+ {
+ SetTimer(hWnd, 1, 1, NULL);
+ }
+
+ SetTimer(hWnd, 2, 100, NULL);
+
+ break;
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ ShowDlgDiffWarning(hWnd, p);
+ break;
+ case 2:
+ if ((p->Session != NULL && p->Session->Halt) ||
+ (p->Halt))
+ {
+ p->Ok = false;
+ EndDialog(hWnd, false);
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_SHOW:
+ CertDlg(hWnd, p->x, p->parent_x, false);
+ break;
+ case IDOK:
+ CheckCertDialogOnOk(hWnd, p);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ p->Ok = false;
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Certificate Check dialog
+void CheckCertDlg(UI_CHECKCERT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Dialog(NULL, D_CHECKCERT, CheckCertDlgProc, p);
+}
+
+// Get the image list ID from the icon ID
+UINT GetIcon(UINT icon_id)
+{
+ IMAGELIST_ICON *c, t;
+ t.id = icon_id;
+
+ c = Search(icon_list, &t);
+ if (c == NULL)
+ {
+ if (icon_id != ICO_NULL)
+ {
+ return GetIcon(ICO_NULL);
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+ else
+ {
+ return c->Index;
+ }
+}
+
+// Load an icon for the image list
+IMAGELIST_ICON *LoadIconForImageList(UINT id)
+{
+ IMAGELIST_ICON *ret = ZeroMalloc(sizeof(IMAGELIST_ICON));
+ HICON small_icon, large_icon;
+
+ ret->id = id;
+
+ large_icon = LoadLargeIcon(id);
+ if (large_icon == NULL)
+ {
+ large_icon = LoadSmallIcon(id);
+ }
+
+ small_icon = LoadSmallIcon(id);
+ if (small_icon == NULL)
+ {
+ small_icon = LoadLargeIcon(id);
+ }
+
+ ret->hSmallImage = small_icon;
+ ret->hLargeImage = large_icon;
+ ret->Index = ImageList_AddIcon(large_image_list, large_icon);
+ ImageList_AddIcon(small_image_list, small_icon);
+
+ return ret;
+}
+
+// Comparison of the image list icons
+int CompareImageListIcon(void *p1, void *p2)
+{
+ IMAGELIST_ICON *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(IMAGELIST_ICON **)p1;
+ c2 = *(IMAGELIST_ICON **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ if (c1->id > c2->id)
+ {
+ return 1;
+ }
+ else if (c1->id < c2->id)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Initialize thr image list
+void InitImageList()
+{
+ large_image_list = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 1, 0);
+ ImageList_SetBkColor(large_image_list, RGB(255, 255, 255));
+ small_image_list = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);
+ ImageList_SetBkColor(small_image_list, RGB(255, 255, 255));
+ icon_list = NewList(CompareImageListIcon);
+
+ // Enumeration
+ EnumResourceNames(hDll, RT_GROUP_ICON, EnumResNameProc, 0);
+}
+
+// Icon resource enumeration procedure
+BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
+{
+ if (IS_INTRESOURCE(lpszName))
+ {
+ UINT icon_id = (UINT)lpszName;
+ IMAGELIST_ICON *img = LoadIconForImageList(icon_id);
+
+ Add(icon_list, img);
+ }
+
+ return TRUE;
+}
+
+// Release the image list
+void FreeImageList()
+{
+ UINT i;
+ ImageList_Destroy(large_image_list);
+ ImageList_Destroy(small_image_list);
+ large_image_list = small_image_list = NULL;
+
+ for (i = 0;i < LIST_NUM(icon_list);i++)
+ {
+ IMAGELIST_ICON *c = LIST_DATA(icon_list, i);
+ Free(c);
+ }
+
+ ReleaseList(icon_list);
+ icon_list = NULL;
+}
+
+// Get the width of the column of the list view
+UINT LvGetColumnWidth(HWND hWnd, UINT id, UINT index)
+{
+ return (UINT)((double)ListView_GetColumnWidth(DlgItem(hWnd, id), index) / GetTextScalingFactor());
+}
+
+// Insert the column into the list view
+void LvInsertColumn(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT width)
+{
+ LVCOLUMNW c;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ width = (UINT)((double)width * GetTextScalingFactor());
+
+ Zero(&c, sizeof(c));
+ c.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
+
+ c.pszText = str;
+ c.iSubItem = index;
+ c.cx = width;
+
+ SendMsg(hWnd, id, LVM_INSERTCOLUMNW, index, (LPARAM)&c);
+}
+
+// Remove all items from list view
+void LvReset(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ ListView_DeleteAllItems(DlgItem(hWnd, id));
+}
+
+// Initialize the list view
+void LvInitEx(HWND hWnd, UINT id, bool no_image)
+{
+ LvInitEx2(hWnd, id, no_image, false);
+}
+void LvInitEx2(HWND hWnd, UINT id, bool no_image, bool large_icon)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ ListView_SetUnicodeFormat(DlgItem(hWnd, id), true);
+
+ if (no_image == false)
+ {
+ ListView_SetImageList(DlgItem(hWnd, id), large_image_list, LVSIL_NORMAL);
+ ListView_SetImageList(DlgItem(hWnd, id), large_icon ? large_image_list : small_image_list, LVSIL_SMALL);
+ }
+
+ ListView_SetExtendedListViewStyle(DlgItem(hWnd, id), LVS_EX_FULLROWSELECT);
+
+ if (MsIsVista())
+ {
+ LvSetStyle(hWnd, id, LVS_EX_DOUBLEBUFFER);
+ }
+}
+void LvInit(HWND hWnd, UINT id)
+{
+ LvInitEx(hWnd, id, false);
+}
+
+// Adding batch complete (high-speed)
+void LvInsertEnd(LVB *b, HWND hWnd, UINT id)
+{
+ LvInsertEndEx(b, hWnd, id, false);
+}
+void LvInsertEndEx(LVB *b, HWND hWnd, UINT id, bool force_reset)
+{
+ UINT i, num;
+ LIST *new_list, *exist_list;
+ wchar_t *last_selected = NULL;
+ // Validate arguments
+ if (b == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ new_list = NewListFast(CompareUniStr);
+
+ for (i = 0;i < LIST_NUM(b->ItemList);i++)
+ {
+ LVB_ITEM *t = LIST_DATA(b->ItemList, i);
+ Add(new_list, t->Strings[0]);
+ }
+
+ Sort(new_list);
+
+ if ((LIST_NUM(b->ItemList) >= LV_INSERT_RESET_ALL_ITEM_MIN) || force_reset)
+ {
+ last_selected = LvGetFocusedStr(hWnd, id, 0);
+ LvReset(hWnd, id);
+ }
+
+ exist_list = NewListFast(CompareUniStr);
+
+ num = LvNum(hWnd, id);
+
+ // Delete the items which isn't contained in the batch list of existing items
+ for (i = 0;i < num;i++)
+ {
+ bool exists = false;
+ wchar_t *s = LvGetStr(hWnd, id, i, 0);
+ if (Search(new_list, s) != NULL)
+ {
+ exists = true;
+ }
+ if (exists == false)
+ {
+ // Remove items that don't exist in the batch list of the adding plan from the list view
+ LvDeleteItem(hWnd, id, i);
+ num = LvNum(hWnd, id);
+ i--;
+ Free(s);
+ }
+ else
+ {
+ Add(exist_list, s);
+ }
+ }
+
+ Sort(exist_list);
+
+ // Add items in the batch one by one
+ for (i = 0;i < LIST_NUM(b->ItemList);i++)
+ {
+ LVB_ITEM *t = LIST_DATA(b->ItemList, i);
+ UINT index;
+ UINT j;
+ bool exists = false;
+
+ if (Search(exist_list, t->Strings[0]) != NULL)
+ {
+ index = LvSearchStr(hWnd, id, 0, t->Strings[0]);
+ }
+ else
+ {
+ index = INFINITE;
+ }
+
+ if (index != INFINITE)
+ {
+ UINT j;
+ // If an item with the string same to adding item already exists,
+ // update instead of adding
+ for (j = 0;j < t->NumStrings;j++)
+ {
+ LvSetItem(hWnd, id, index, j, t->Strings[j]);
+ }
+ LvSetItemImageByImageListId(hWnd, id, index, t->Image);
+ LvSetItemParam(hWnd, id, index, t->Param);
+ }
+ else
+ {
+ // Add newly
+ UINT index = INFINITE;
+ UINT j;
+ for (j = 0;j < t->NumStrings;j++)
+ {
+ if (j == 0)
+ {
+ index = LvInsertItemByImageListId(hWnd, id, t->Image, t->Param, t->Strings[j]);
+ }
+ else
+ {
+ LvSetItem(hWnd, id, index, j, t->Strings[j]);
+ }
+ }
+ }
+
+ // Release the memory
+ for (j = 0;j < t->NumStrings;j++)
+ {
+ Free(t->Strings[j]);
+ }
+ Free(t->Strings);
+ Free(t);
+ }
+
+ // Release the list
+ ReleaseList(b->ItemList);
+
+ // Release the memory
+ Free(b);
+
+ ReleaseList(new_list);
+
+ for (i = 0;i < LIST_NUM(exist_list);i++)
+ {
+ Free(LIST_DATA(exist_list, i));
+ }
+ ReleaseList(exist_list);
+
+ if (last_selected != NULL)
+ {
+ UINT pos = LvSearchStr(hWnd, id, 0, last_selected);
+
+ if (pos != INFINITE)
+ {
+ LvSelect(hWnd, id, pos);
+ }
+
+ Free(last_selected);
+ }
+}
+
+// Get the number of columns of the list view
+UINT LvGetColumnNum(HWND hWnd, UINT id)
+{
+ UINT i;
+ LVCOLUMN c;
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0;;i++)
+ {
+ Zero(&c, sizeof(c));
+ c.mask = LVCF_SUBITEM;
+ if (ListView_GetColumn(DlgItem(hWnd, id), i, &c) == false)
+ {
+ break;
+ }
+ }
+
+ return i;
+}
+
+// List-view sort function
+int CALLBACK LvSortProc(LPARAM param1, LPARAM param2, LPARAM sort_param)
+{
+ WINUI_LV_SORT *sort = (WINUI_LV_SORT *)sort_param;
+ HWND hWnd;
+ UINT id;
+ UINT i1, i2;
+ int ret = 0;
+ wchar_t *s1, *s2;
+ if (sort == NULL)
+ {
+ return 0;
+ }
+
+ hWnd = sort->hWnd;
+ id = sort->id;
+
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ i1 = (UINT)param1;
+ i2 = (UINT)param2;
+
+ s1 = LvGetStr(hWnd, id, i1, sort->subitem);
+ if (s1 == NULL)
+ {
+ return 0;
+ }
+
+ s2 = LvGetStr(hWnd, id, i2, sort->subitem);
+ if (s2 == NULL)
+ {
+ Free(s1);
+ return 0;
+ }
+
+ if (sort->numeric == false)
+ {
+ if (UniStrCmpi(s1, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
+ {
+ ret = -1;
+ }
+ else if (UniStrCmpi(s2, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s2, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
+ {
+ ret = 1;
+ }
+ else
+ {
+ ret = UniStrCmpi(s1, s2);
+ }
+ }
+ else
+ {
+ UINT64 v1, v2;
+ v1 = UniToInt64(s1);
+ v2 = UniToInt64(s2);
+ if (v1 > v2)
+ {
+ ret = 1;
+ }
+ else if (v1 < v2)
+ {
+ ret = -1;
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+
+ Free(s1);
+ Free(s2);
+
+ if (sort->desc)
+ {
+ ret = -ret;
+ }
+
+ return ret;
+}
+
+// Standard handler
+void LvStandardHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
+{
+ NMHDR *n;
+ NMLVKEYDOWN *key;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, id);
+
+ switch (msg)
+ {
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ if (n->idFrom == id)
+ {
+ switch (n->code)
+ {
+ case NM_DBLCLK:
+ Command(hWnd, IDOK);
+ break;
+ case LVN_KEYDOWN:
+ key = (NMLVKEYDOWN *)n;
+ if (key != NULL)
+ {
+ UINT code = key->wVKey;
+ switch (code)
+ {
+ case VK_DELETE:
+ Command(hWnd, B_DELETE);
+ break;
+
+ case VK_RETURN:
+ Command(hWnd, IDOK);
+ break;
+
+ case VK_F5:
+ Command(hWnd, B_REFRESH);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+}
+
+// Sort header handler
+void LvSortHander(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
+{
+ NMHDR *nmhdr;
+ UINT subitem;
+ bool desc;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ switch (msg)
+ {
+ case WM_NOTIFY:
+ nmhdr = (NMHDR *)lParam;
+
+ if (nmhdr != NULL)
+ {
+ if (nmhdr->idFrom == id)
+ {
+ NMLISTVIEW *v;
+ switch (nmhdr->code)
+ {
+ case LVN_COLUMNCLICK:
+ desc = false;
+ v = (NMLISTVIEW *)lParam;
+ subitem = v->iSubItem;
+
+ if ((GetStyle(hWnd, id) & LVS_SORTDESCENDING) == 0)
+ {
+ desc = true;
+ SetStyle(hWnd, id, LVS_SORTDESCENDING);
+ RemoveStyle(hWnd, id, LVS_SORTASCENDING);
+ }
+ else
+ {
+ SetStyle(hWnd, id, LVS_SORTASCENDING);
+ RemoveStyle(hWnd, id, LVS_SORTDESCENDING);
+ }
+
+ LvSort(hWnd, id, subitem, desc);
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+// Do sort
+void LvSort(HWND hWnd, UINT id, UINT subitem, bool desc)
+{
+ UINT i, num;
+ bool numeric = true;
+ wchar_t na[2] = {0xff0d, 0x0, };
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ num = LvNum(hWnd, id);
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *s = LvGetStr(hWnd, id, i, subitem);
+ if (s != NULL)
+ {
+ if (UniIsNum(s) == false && UniStrCmp(s, na) != 0)
+ {
+ numeric = false;
+ Free(s);
+ break;
+ }
+ Free(s);
+ }
+ else
+ {
+ numeric = false;
+ break;
+ }
+ }
+
+ LvSortEx(hWnd, id, subitem, desc, numeric);
+}
+
+void LvSortEx(HWND hWnd, UINT id, UINT subitem, bool desc, bool numeric)
+{
+ WINUI_LV_SORT s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+ if (subitem >= LvGetColumnNum(hWnd, id))
+ {
+ return;
+ }
+
+ Zero(&s, sizeof(s));
+ s.desc = desc;
+ s.numeric = numeric;
+ s.id = id;
+ s.hWnd = hWnd;
+ s.subitem = subitem;
+
+ ListView_SortItemsEx(DlgItem(hWnd, id), LvSortProc, (LPARAM)&s);
+}
+
+// Add an item to adding batch
+void LvInsertAdd(LVB *b, UINT icon, void *param, UINT num_str, ...)
+{
+ UINT i;
+ va_list va;
+ UINT index = 0;
+ LVB_ITEM *t;
+ // Validate arguments
+ if (b == NULL || num_str == 0)
+ {
+ return;
+ }
+
+ t = ZeroMalloc(sizeof(LVB_ITEM));
+
+ va_start(va, num_str);
+
+ t->Strings = (wchar_t **)ZeroMalloc(sizeof(wchar_t *) * num_str);
+ t->NumStrings = num_str;
+
+ for (i = 0;i < num_str;i++)
+ {
+ wchar_t *s = va_arg(va, wchar_t *);
+
+ t->Strings[i] = UniCopyStr(s);
+ }
+
+ t->Param = param;
+ t->Image = GetIcon(icon);
+
+ Add(b->ItemList, t);
+
+ va_end(va);
+}
+
+// Start the item adding batch
+LVB *LvInsertStart()
+{
+ LVB *b = ZeroMalloc(sizeof(LVB));
+ b->ItemList = NewListFast(NULL);
+
+ return b;
+}
+
+// Add items to the list view
+void LvInsert(HWND hWnd, UINT id, UINT icon, void *param, UINT num_str, ...)
+{
+ UINT i;
+ va_list va;
+ UINT index = 0;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ va_start(va, num_str);
+
+ for (i = 0;i < num_str;i++)
+ {
+ wchar_t *s = va_arg(va, wchar_t *);
+ if (i == 0)
+ {
+ index = LvInsertItem(hWnd, id, icon, param, s);
+ }
+ else
+ {
+ LvSetItem(hWnd, id, index, i, s);
+ }
+ }
+
+ va_end(va);
+}
+
+// Adjust the item size automatically
+void LvAutoSize(HWND hWnd, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ i = 0;
+ while (true)
+ {
+ if (ListView_SetColumnWidth(DlgItem(hWnd, id), i, LVSCW_AUTOSIZE) == false)
+ {
+ break;
+ }
+ i++;
+ }
+}
+
+// Add an item
+UINT LvInsertItem(HWND hWnd, UINT id, UINT icon, void *param, wchar_t *str)
+{
+ return LvInsertItemByImageListId(hWnd, id, GetIcon(icon), param, str);
+}
+UINT LvInsertItemByImageListId(HWND hWnd, UINT id, UINT image, void *param, wchar_t *str)
+{
+ LVITEMW t;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ UINT ret;
+ ret = LvInsertItemByImageListIdA(hWnd, id, image, param, s);
+ Free(s);
+ return ret;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
+ t.pszText = str;
+ t.iImage = image;
+ t.lParam = (LPARAM)param;
+ t.iItem = LvNum(hWnd, id);
+
+ return SendMsg(hWnd, id, LVM_INSERTITEMW, 0, (LPARAM)&t);
+}
+UINT LvInsertItemByImageListIdA(HWND hWnd, UINT id, UINT image, void *param, char *str)
+{
+ LVITEM t;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
+ t.pszText = str;
+ t.iImage = image;
+ t.lParam = (LPARAM)param;
+ t.iItem = LvNum(hWnd, id);
+
+ return SendMsg(hWnd, id, LVM_INSERTITEM, 0, (LPARAM)&t);
+}
+
+// Change the image
+void LvSetItemImage(HWND hWnd, UINT id, UINT index, UINT icon)
+{
+ LvSetItemImageByImageListId(hWnd, id, index, GetIcon(icon));
+}
+void LvSetItemImageByImageListId(HWND hWnd, UINT id, UINT index, UINT image)
+{
+ LVITEM t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_IMAGE;
+ t.iImage = image;
+ t.iItem = index;
+
+ SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
+}
+
+// Set the parameters of the item
+void LvSetItemParam(HWND hWnd, UINT id, UINT index, void *param)
+{
+ LvSetItemParamEx(hWnd, id, index, 0, param);
+}
+void LvSetItemParamEx(HWND hWnd, UINT id, UINT index, UINT subitem, void *param)
+{
+ LVITEM t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_PARAM;
+ t.iItem = index;
+ t.iSubItem = subitem;
+ t.lParam = (LPARAM)param;
+
+ SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
+}
+
+// Set the item
+void LvSetItem(HWND hWnd, UINT id, UINT index, UINT pos, wchar_t *str)
+{
+ LVITEMW t;
+ wchar_t *old_str;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ LvSetItemA(hWnd, id, index, pos, s);
+ Free(s);
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_TEXT;
+ t.pszText = str;
+ t.iItem = index;
+ t.iSubItem = pos;
+
+ old_str = LvGetStr(hWnd, id, index, pos);
+
+ if (UniStrCmp(old_str, str) != 0)
+ {
+ SendMsg(hWnd, id, LVM_SETITEMW, 0, (LPARAM)&t);
+ }
+
+ Free(old_str);
+}
+void LvSetItemA(HWND hWnd, UINT id, UINT index, UINT pos, char *str)
+{
+ LVITEM t;
+ wchar_t *old_str;
+ char *old_str_2;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_TEXT;
+ t.pszText = str;
+ t.iItem = index;
+ t.iSubItem = pos;
+
+ old_str = LvGetStr(hWnd, id, index, pos);
+ old_str_2 = CopyUniToStr(old_str);
+
+ if (StrCmp(old_str_2, str) != 0)
+ {
+ SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
+ }
+
+ Free(old_str_2);
+ Free(old_str);
+}
+
+// Set the view of the list box
+void LvSetView(HWND hWnd, UINT id, bool details)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (details)
+ {
+ RemoveStyle(hWnd, id, LVS_ICON);
+ SetStyle(hWnd, id, LVS_REPORT);
+ }
+ else
+ {
+ RemoveStyle(hWnd, id, LVS_REPORT);
+ SetStyle(hWnd, id, LVS_ICON);
+ }
+}
+
+// Ensure that the specified item is visible
+void LvShow(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ ListView_EnsureVisible(DlgItem(hWnd, id), index, false);
+}
+
+// Get whether there is currently selected item
+bool LvIsSelected(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ if (LvGetSelected(hWnd, id) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the currently selected item
+UINT LvGetFocused(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED);
+}
+
+// Get the parameter of the currently selected item
+void *LvGetSelectedParam(HWND hWnd, UINT id)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ index = LvGetSelected(hWnd, id);
+
+ if (index == INFINITE)
+ {
+ return NULL;
+ }
+
+ return LvGetParam(hWnd, id, index);
+}
+
+// Get a string that is currently selected
+wchar_t *LvGetFocusedStr(HWND hWnd, UINT id, UINT pos)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ i = LvGetFocused(hWnd, id);
+ if (i == INFINITE)
+ {
+ return NULL;
+ }
+
+ return LvGetStr(hWnd, id, i, pos);
+}
+
+// Get the currently selected item
+UINT LvGetSelected(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED | LVNI_SELECTED);
+}
+
+// Get a string that is currently selected
+wchar_t *LvGetSelectedStr(HWND hWnd, UINT id, UINT pos)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ i = LvGetSelected(hWnd, id);
+ if (i == INFINITE)
+ {
+ return NULL;
+ }
+
+ return LvGetStr(hWnd, id, i, pos);
+}
+char *LvGetSelectedStrA(HWND hWnd, UINT id, UINT pos)
+{
+ char *ret;
+ wchar_t *tmp = LvGetSelectedStr(hWnd, id, pos);
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+ ret = CopyUniToStr(tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Get whether two or more items are masked
+bool LvIsMultiMasked(HWND hWnd, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ i = INFINITE;
+ i = LvGetNextMasked(hWnd, id, i);
+ if (i != INFINITE)
+ {
+ if (LvGetNextMasked(hWnd, id, i) != INFINITE)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Examine whether just only one item is selected
+bool LvIsSingleSelected(HWND hWnd, UINT id)
+{
+ return LvIsSelected(hWnd, id) && (LvIsMultiMasked(hWnd, id) == false);
+}
+
+// Get whether there are items that are currently masked
+bool LvIsMasked(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ if (LvGetNextMasked(hWnd, id, INFINITE) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the number of items that are currently masked
+UINT LvGetMaskedNum(HWND hWnd, UINT id)
+{
+ UINT i = INFINITE;
+ UINT num = 0;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ i = LvGetNextMasked(hWnd, id, i);
+ if (i == INFINITE)
+ {
+ break;
+ }
+
+ num++;
+ }
+
+ return num;
+}
+
+// Get the items that is currently masked
+UINT LvGetNextMasked(HWND hWnd, UINT id, UINT start)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return ListView_GetNextItem(DlgItem(hWnd, id), start, LVNI_SELECTED);
+}
+
+// Search an item with the specified string
+UINT LvSearchStr_(HWND hWnd, UINT id, UINT pos, wchar_t *str)
+{
+ UINT ret;
+ LVFINDINFOW t;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ Zero(&t, sizeof(t));
+ t.flags = LVFI_STRING;
+ t.psz = str;
+ t.vkDirection = VK_DOWN;
+
+ ret = SendMsg(hWnd, id, LVM_FINDITEMW, -1, (LPARAM)&t);
+
+ return ret;
+}
+
+// Search an item with the specified string
+UINT LvSearchStr(HWND hWnd, UINT id, UINT pos, wchar_t *str)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ num = LvNum(hWnd, id);
+
+ for (i = 0;i < num;i++)
+ {
+ wchar_t *s = LvGetStr(hWnd, id, i, pos);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, str) == 0)
+ {
+ Free(s);
+ return i;
+ }
+ else
+ {
+ Free(s);
+ }
+ }
+ }
+
+ return INFINITE;
+}
+UINT LvSearchStrA(HWND hWnd, UINT id, UINT pos, char *str)
+{
+ wchar_t *tmp = CopyStrToUni(str);
+ UINT ret = LvSearchStr(hWnd, id, pos, tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Search for item that have a specified param
+UINT LvSearchParam(HWND hWnd, UINT id, void *param)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ num = LvNum(hWnd, id);
+
+ for (i = 0;i < num;i++)
+ {
+ if (LvGetParam(hWnd, id, i) == param)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Get the number of items
+UINT LvNum(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return ListView_GetItemCount(DlgItem(hWnd, id));
+}
+
+// Remove an item
+void LvDeleteItem(HWND hWnd, UINT id, UINT index)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ ListView_DeleteItem(DlgItem(hWnd, id), index);
+
+ i = LvGetSelected(hWnd, id);
+ if (i != INFINITE)
+ {
+ LvSelect(hWnd, id, i);
+ }
+}
+
+// Get the data from the item
+void *LvGetParam(HWND hWnd, UINT id, UINT index)
+{
+ return LvGetParamEx(hWnd, id, index, 0);
+}
+void *LvGetParamEx(HWND hWnd, UINT id, UINT index, UINT subitem)
+{
+ LVITEM t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+ if (index == INFINITE)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_PARAM;
+ t.iItem = index;
+ t.iSubItem = subitem;
+
+ if (ListView_GetItem(DlgItem(hWnd, id), &t) == false)
+ {
+ return NULL;
+ }
+
+ return (void *)t.lParam;
+}
+
+// Get the string of item
+wchar_t *LvGetStr(HWND hWnd, UINT id, UINT index, UINT pos)
+{
+ wchar_t *tmp;
+ UINT size;
+ LVITEMW t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+ if (MsIsNt() == false)
+ {
+ char *s = LvGetStrA(hWnd, id, index, pos);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ wchar_t *ret = CopyStrToUni(s);
+ Free(s);
+
+ return ret;
+ }
+ }
+
+ size = 65536;
+ tmp = Malloc(size);
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_TEXT;
+ t.iItem = index;
+ t.iSubItem = pos;
+ t.pszText = tmp;
+ t.cchTextMax = size;
+
+ if (SendMsg(hWnd, id, LVM_GETITEMTEXTW, index, (LPARAM)&t) <= 0)
+ {
+ Free(tmp);
+ return UniCopyStr(L"");
+ }
+ else
+ {
+ wchar_t *ret = UniCopyStr(tmp);
+ Free(tmp);
+ return ret;
+ }
+}
+char *LvGetStrA(HWND hWnd, UINT id, UINT index, UINT pos)
+{
+ char *tmp;
+ UINT size;
+ LVITEM t;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ size = 65536;
+ tmp = Malloc(size);
+
+ Zero(&t, sizeof(t));
+ t.mask = LVIF_TEXT;
+ t.iItem = index;
+ t.iSubItem = pos;
+ t.pszText = tmp;
+ t.cchTextMax = size;
+
+ if (SendMsg(hWnd, id, LVM_GETITEMTEXT, index, (LPARAM)&t) <= 0)
+ {
+ Free(tmp);
+ return CopyStr("");
+ }
+ else
+ {
+ char *ret = CopyStr(tmp);
+ Free(tmp);
+ return ret;
+ }
+}
+
+// Set the style
+void LvSetStyle(HWND hWnd, UINT id, UINT style)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) == 0)
+ {
+ ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, style);
+ }
+}
+
+// Remove the style
+void LvRemoveStyle(HWND hWnd, UINT id, UINT style)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) != 0)
+ {
+ ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, 0);
+ }
+}
+
+// Invert the selection of items
+void LvSwitchSelect(HWND hWnd, UINT id)
+{
+ UINT i, num;
+ bool *states;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ num = LvNum(hWnd, id);
+ states = ZeroMalloc(sizeof(bool) * num);
+
+ i = INFINITE;
+ while (true)
+ {
+ i = LvGetNextMasked(hWnd, id, i);
+ if (i == INFINITE)
+ {
+ break;
+ }
+
+ states[i] = true;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ if (states[i] == false)
+ {
+ ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
+ }
+ else
+ {
+ ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
+ }
+ }
+
+ Free(states);
+}
+
+// Select all items
+void LvSelectAll(HWND hWnd, UINT id)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ num = LvNum(hWnd, id);
+ for (i = 0;i < num;i++)
+ {
+ ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
+ }
+}
+
+// Select the item by specifying the parameter
+void LvSelectByParam(HWND hWnd, UINT id, void *param)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL || param == NULL)
+ {
+ return;
+ }
+
+ index = LvSearchParam(hWnd, id, param);
+ if (index == INFINITE)
+ {
+ return;
+ }
+
+ LvSelect(hWnd, id, index);
+}
+
+// Select an item
+void LvSelect(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (index == INFINITE)
+ {
+ UINT i, num;
+ // Deselect all
+ num = LvNum(hWnd, id);
+ for (i = 0;i < num;i++)
+ {
+ ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
+ }
+ }
+ else
+ {
+ // Select
+ ListView_SetItemState(DlgItem(hWnd, id), index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
+ ListView_EnsureVisible(DlgItem(hWnd, id), index, true);
+ }
+}
+
+// Show the certificate information
+void PrintCertInfo(HWND hWnd, CERT_DLG *p)
+{
+ X *x;
+ char *serial_tmp;
+ UINT serial_size;
+ wchar_t *wchar_tmp;
+ wchar_t tmp[1024 * 5];
+ UCHAR md5[MD5_SIZE];
+ UCHAR sha1[SHA1_SIZE];
+ char *s_tmp;
+ K *k;
+ // Validate arguments
+ if (p == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ x = p->x;
+
+ // Serial number
+ if (x->serial != NULL)
+ {
+ serial_size = x->serial->size * 3 + 1;
+ serial_tmp = ZeroMalloc(serial_size);
+ BinToStrEx(serial_tmp, serial_size, x->serial->data, x->serial->size);
+ wchar_tmp = CopyStrToUni(serial_tmp);
+ Free(serial_tmp);
+ }
+ else
+ {
+ wchar_tmp = CopyUniStr(_UU("CERT_NO_SERIAL"));
+ }
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SERIAL"), wchar_tmp);
+
+ // Issuer
+ GetAllNameFromName(tmp, sizeof(tmp), x->issuer_name);
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_ISSUER"), tmp);
+
+ // Subject
+ GetAllNameFromName(tmp, sizeof(tmp), x->subject_name);
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SUBJECT"), tmp);
+
+ // Not available before
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notBefore), NULL);
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_BEFORE"), tmp);
+
+ // Not available after
+ GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_AFTER"), tmp);
+
+ // Number of bits
+ if (x->is_compatible_bit)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("CERT_BITS_FORMAT"), x->bits);
+ LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_BITS"), tmp);
+ }
+
+ // Public key
+ k = GetKFromX(x);
+ if (k != NULL)
+ {
+ BUF *b = KToBuf(k, false, NULL);
+ s_tmp = CopyBinToStrEx(b->Buf, b->Size);
+ StrToUni(tmp, sizeof(tmp), s_tmp);
+ Free(s_tmp);
+ LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_PUBLIC_KEY"), tmp);
+ FreeBuf(b);
+ }
+ FreeK(k);
+
+ GetXDigest(x, md5, false);
+ GetXDigest(x, sha1, true);
+
+ // Digest (MD5)
+ s_tmp = CopyBinToStrEx(md5, sizeof(md5));
+ StrToUni(tmp, sizeof(tmp), s_tmp);
+ Free(s_tmp);
+ LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_MD5"), tmp);
+
+ // Digest (SHA-1)
+ s_tmp = CopyBinToStrEx(sha1, sizeof(sha1));
+ StrToUni(tmp, sizeof(tmp), s_tmp);
+ Free(s_tmp);
+ LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_SHA1"), tmp);
+
+ Free(wchar_tmp);
+
+ LvSelect(hWnd, L_CERTINFO, 0);
+}
+
+// Update the display
+void CertDlgUpdate(HWND hWnd, CERT_DLG *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (LvIsSelected(hWnd, L_CERTINFO) == false)
+ {
+ SetText(hWnd, E_DETAIL, L"");
+ }
+ else
+ {
+ UINT i = LvGetSelected(hWnd, L_CERTINFO);
+ wchar_t *tmp = LvGetStr(hWnd, L_CERTINFO, i, 1);
+ SetText(hWnd, E_DETAIL, tmp);
+ Free(tmp);
+ }
+}
+
+// Save the certificate
+void CertDlgSave(HWND hWnd, CERT_DLG *p)
+{
+ wchar_t *name;
+ X *x;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Save to a file
+ name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
+ x = p->x;
+ if (name != NULL)
+ {
+ wchar_t str[MAX_SIZE];
+ UniStrCpy(str, sizeof(str), name);
+ if (XToFileW(x, str, true))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
+ }
+ else
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
+ }
+ Free(name);
+ }
+}
+
+// Certificate display dialog procedure
+UINT CertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ CERT_DLG *p = (CERT_DLG *)param;
+ X *x;
+ wchar_t tmp[MAX_SIZE];
+ NMHDR *n;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_CERT);
+ x = p->x;
+ GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
+ SetText(hWnd, E_SUBJECT, tmp);
+ GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
+ SetText(hWnd, E_ISSUER, tmp);
+ GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
+ SetText(hWnd, E_EXPIRES, tmp);
+ SetFont(hWnd, E_SUBJECT, Font(0, 1));
+ SetFont(hWnd, E_ISSUER, Font(0, 1));
+ SetFont(hWnd, E_EXPIRES, Font(0, 1));
+ SetIcon(hWnd, B_PARENT, ICO_CERT);
+ if (x->root_cert)
+ {
+ // Root certificate
+ Hide(hWnd, S_WARNING_ICON);
+ SetText(hWnd, S_PARENT, _UU("CERT_ROOT"));
+ Hide(hWnd, B_PARENT);
+ Hide(hWnd, S_PARENT_BUTTON_STR);
+ }
+ else if (p->issuer_x != NULL)
+ {
+ // Parent certificate exists
+ Hide(hWnd, S_WARNING_ICON);
+ }
+ else
+ {
+ // There is no parent certificate
+ Hide(hWnd, S_CERT_ICON);
+ Hide(hWnd, B_PARENT);
+ Hide(hWnd, S_PARENT_BUTTON_STR);
+ SetText(hWnd, S_PARENT, _UU("CERT_NOT_FOUND"));
+ if (p->ManagerMode)
+ {
+ Hide(hWnd, IDC_STATIC1);
+ Hide(hWnd, S_PARENT);
+ Hide(hWnd, S_WARNING_ICON);
+ Hide(hWnd, S_CERT_ICON);
+ Hide(hWnd, B_PARENT);
+ Hide(hWnd, S_PARENT_BUTTON_STR);
+ }
+ }
+
+
+ LvInit(hWnd, L_CERTINFO);
+ LvInsertColumn(hWnd, L_CERTINFO, 0, _UU("CERT_LV_C1"), 130);
+ LvInsertColumn(hWnd, L_CERTINFO, 1, _UU("CERT_LV_C2"), 250);
+
+ PrintCertInfo(hWnd, p);
+ Focus(hWnd, L_CERTINFO);
+
+ CertDlgUpdate(hWnd, p);
+
+ if (p->ManagerMode)
+ {
+ Show(hWnd, B_SAVE);
+ }
+ else
+ {
+ // Hide for security
+ Hide(hWnd, B_SAVE);
+ }
+
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ case B_PARENT:
+ CertDlg(hWnd, p->issuer_x, NULL, p->ManagerMode);
+ break;
+ case B_SAVE:
+ // Save to the file
+ CertDlgSave(hWnd, p);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ case WM_NOTIFY:
+ n = (NMHDR *)lParam;
+ switch (n->idFrom)
+ {
+ case L_CERTINFO:
+ switch (n->code)
+ {
+ case LVN_ITEMCHANGED:
+ CertDlgUpdate(hWnd, p);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ LvSortHander(hWnd, msg, wParam, lParam, L_CERTINFO);
+
+ return 0;
+}
+
+// Certificate display dialog
+void CertDlg(HWND hWnd, X *x, X *issuer_x, bool manager)
+{
+ CERT_DLG p;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ p.x = x;
+ if (CompareX(x, issuer_x) == false)
+ {
+ p.issuer_x = issuer_x;
+ }
+ p.ManagerMode = manager;
+ Dialog(hWnd, D_CERT, CertDlgProc, &p);
+}
+
+// Status window dialog
+UINT StatusPrinterWindowDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
+ PACK *pack;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // Initialize
+ SetIcon(hWnd, 0, ICO_SERVER_ONLINE);
+ RemoveExStyle(hWnd, 0, WS_EX_APPWINDOW);
+ p->hWnd = hWnd;
+ NoticeThreadInit(p->Thread);
+ FormatText(hWnd, 0, p->AccountName);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ // Cancel button
+ Close(hWnd);
+ break;
+ }
+
+ break;
+
+ case WM_APP + 1:
+ // Set a string
+ SetText(hWnd, S_STATUS, (wchar_t *)lParam);
+ break;
+
+ case WM_APP + 2:
+ // Close this window
+ EndDialog(hWnd, false);
+ break;
+
+ case WM_CLOSE:
+ // End the session
+ pack = NewPack();
+ SendPack(p->Sock, pack);
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// Status window control thread
+void StatusPrinterWindowThread(THREAD *thread, void *param)
+{
+ STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p->Thread = thread;
+ DialogEx2(NULL, D_STATUS, StatusPrinterWindowDlg, p, true, true);
+
+ Free(p);
+}
+
+// Show a message in the status window
+void StatusPrinterWindowPrint(STATUS_WINDOW *sw, wchar_t *str)
+{
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ SendMessage(sw->hWnd, WM_APP + 1, 0, (LPARAM)str);
+}
+
+// End and release the status window
+void StatusPrinterWindowStop(STATUS_WINDOW *sw)
+{
+ // Validate arguments
+ if (sw == NULL)
+ {
+ return;
+ }
+
+ // Send stop message
+ SendMessage(sw->hWnd, WM_APP + 2, 0, 0);
+
+ // Wait until the thread terminates
+ WaitThread(sw->Thread, INFINITE);
+
+ // Release the memory
+ ReleaseThread(sw->Thread);
+ Free(sw);
+}
+
+// Initialize the status window
+STATUS_WINDOW *StatusPrinterWindowStart(SOCK *s, wchar_t *account_name)
+{
+ STATUS_WINDOW_PARAM *p;
+ STATUS_WINDOW *sw;
+ THREAD *t;
+ // Validate arguments
+ if (s == NULL || account_name == NULL)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(STATUS_WINDOW_PARAM));
+ p->Sock = s;
+ UniStrCpy(p->AccountName, sizeof(p->AccountName), account_name);
+
+ // Create a thread
+ t = NewThread(StatusPrinterWindowThread, p);
+ WaitThreadInit(t);
+
+ sw = ZeroMalloc(sizeof(STATUS_WINDOW));
+ sw->hWnd = p->hWnd;
+ sw->Thread = t;
+
+ return sw;
+}
+
+// Get the string
+wchar_t *LbGetStr(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ return GetText(hWnd, id);
+}
+
+// String search
+UINT LbFindStr(HWND hWnd, UINT id, wchar_t *str)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, LB_FINDSTRING, -1, (LPARAM)str);
+
+ return ret;
+}
+
+// Get the number of items
+UINT LbNum(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, LB_GETCOUNT, 0, 0);
+}
+
+// Add a string
+UINT LbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)
+{
+ UINT ret;
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ ret = LbAddStrA(hWnd, id, s, data);
+ Free(s);
+ return ret;
+ }
+
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, LB_ADDSTRING, 0, (LPARAM)str);
+ SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (LbNum(hWnd, id) == 1)
+ {
+ LbSelectIndex(hWnd, id, 0);
+ }
+
+ return ret;
+}
+UINT LbAddStrA(HWND hWnd, UINT id, char *str, UINT data)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, LB_ADDSTRING, 0, (LPARAM)str);
+ SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (LbNum(hWnd, id) == 1)
+ {
+ LbSelectIndex(hWnd, id, 0);
+ }
+
+ return ret;
+}
+
+// Insert a string
+UINT LbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data)
+{
+ UINT ret;
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ ret = LbInsertStrA(hWnd, id, index, s, data);
+ Free(s);
+ return ret;
+ }
+
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, LB_INSERTSTRING, index, (LPARAM)str);
+ SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (LbNum(hWnd, id) == 1)
+ {
+ LbSelect(hWnd, id, 0);
+ }
+
+ return ret;
+}
+UINT LbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, LB_INSERTSTRING, index, (LPARAM)str);
+ SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (LbNum(hWnd, id) == 1)
+ {
+ LbSelect(hWnd, id, 0);
+ }
+
+ return ret;
+}
+
+// Remove all
+void LbReset(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, LB_RESETCONTENT, 0, 0);
+}
+
+// Select by specifying the index
+void LbSelectIndex(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, LB_SETCURSEL, index, 0);
+}
+
+// Get the data
+UINT LbGetData(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL || index == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, LB_GETITEMDATA, index, 0);
+}
+
+// Search for the data
+UINT LbFindData(HWND hWnd, UINT id, UINT data)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ num = LbNum(hWnd, id);
+ if (num == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ if (LbGetData(hWnd, id, i) == data)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Set the height of the item
+void LbSetHeight(HWND hWnd, UINT id, UINT value)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, LB_SETITEMHEIGHT, 0, (UINT)(GetTextScalingFactor() * (double)value));
+}
+
+// Search by specifying the data
+void LbSelect(HWND hWnd, UINT id, int data)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (data == INFINITE)
+ {
+ // Get the first item
+ LbSelectIndex(hWnd, id, 0);
+ return;
+ }
+
+ index = LbFindData(hWnd, id, data);
+ if (index == INFINITE)
+ {
+ // Can not be found
+ return;
+ }
+
+ // Select
+ LbSelectIndex(hWnd, id, index);
+}
+
+// Get the currently selected item
+UINT LbGetSelectIndex(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, LB_GETCURSEL, 0, 0);
+}
+
+// Get the value that is currently selected
+UINT LbGetSelect(HWND hWnd, UINT id)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ index = LbGetSelectIndex(hWnd, id);
+ if (index == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ return LbGetData(hWnd, id, index);
+}
+
+// Password input dialog state change
+void PasswordDlgProcChange(HWND hWnd, UI_PASSWORD_DLG *p)
+{
+ bool b;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ b = true;
+ if (IsEmpty(hWnd, E_USERNAME))
+ {
+ b = false;
+ }
+
+ SetEnable(hWnd, IDOK, b);
+
+ p->StartTick = Tick64();
+ if (p->RetryIntervalSec)
+ {
+ KillTimer(hWnd, 1);
+ Hide(hWnd, P_PROGRESS);
+ Hide(hWnd, S_COUNTDOWN);
+ }
+}
+
+// Get the string
+wchar_t *CbGetStr(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ return GetText(hWnd, id);
+}
+
+// String search
+UINT CbFindStr(HWND hWnd, UINT id, wchar_t *str)
+{
+ UINT ret;
+ if (MsIsNt() == false)
+ {
+ char *tmp = CopyUniToStr(str);
+ ret = CbFindStr9xA(hWnd, id, tmp);
+ Free(tmp);
+ return ret;
+ }
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
+
+ return ret;
+}
+UINT CbFindStr9xA(HWND hWnd, UINT id, char *str)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
+
+ return ret;
+}
+
+// Get the number of items
+UINT CbNum(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, CB_GETCOUNT, 0, 0);
+}
+
+// Add a string
+UINT CbAddStrA(HWND hWnd, UINT id, char *str, UINT data)
+{
+ wchar_t *tmp;
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+ tmp = CopyStrToUni(str);
+ ret = CbAddStr(hWnd, id, tmp, data);
+ Free(tmp);
+ return ret;
+}
+UINT CbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)
+{
+ UINT ret;
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ ret = CbAddStr9xA(hWnd, id, s, data);
+ Free(s);
+ return ret;
+ }
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
+ SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (CbNum(hWnd, id) == 1)
+ {
+ wchar_t tmp[MAX_SIZE];
+ GetTxt(hWnd, id, tmp, sizeof(tmp));
+ if (UniStrLen(tmp) == 0)
+ {
+ CbSelectIndex(hWnd, id, 0);
+ }
+ }
+
+ return ret;
+}
+UINT CbAddStr9xA(HWND hWnd, UINT id, char *str, UINT data)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
+ SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (CbNum(hWnd, id) == 1)
+ {
+ wchar_t tmp[MAX_SIZE];
+ GetTxt(hWnd, id, tmp, sizeof(tmp));
+ if (UniStrLen(tmp) == 0)
+ {
+ CbSelectIndex(hWnd, id, 0);
+ }
+ }
+
+ return ret;
+}
+
+// Insert a string
+UINT CbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data)
+{
+ wchar_t *tmp;
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+ tmp = CopyStrToUni(str);
+ ret = CbInsertStr(hWnd, id, index, tmp, data);
+ Free(tmp);
+ return ret;
+}
+UINT CbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(str);
+ ret = CbInsertStr9xA(hWnd, id, index, s, data);
+ Free(s);
+ return ret;
+ }
+
+ ret = SendMsg(hWnd, id, CB_INSERTSTRING, index, (LPARAM)str);
+ SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (CbNum(hWnd, id) == 1)
+ {
+ CbSelect(hWnd, id, 0);
+ }
+
+ return ret;
+}
+UINT CbInsertStr9xA(HWND hWnd, UINT id, UINT index, char *str, UINT data)
+{
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ ret = SendMsg(hWnd, id, CB_INSERTSTRING, index, (LPARAM)str);
+ SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
+
+ if (CbNum(hWnd, id) == 1)
+ {
+ CbSelect(hWnd, id, 0);
+ }
+
+ return ret;
+}
+
+// Remove all
+void CbReset(HWND hWnd, UINT id)
+{
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ s = GetText(hWnd, id);
+
+ SendMsg(hWnd, id, CB_RESETCONTENT, 0, 0);
+
+ if (s != NULL)
+ {
+ SetText(hWnd, id, s);
+ Free(s);
+ }
+}
+
+// Select by specifying the index
+void CbSelectIndex(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, CB_SETCURSEL, index, 0);
+}
+
+// Get the data
+UINT CbGetData(HWND hWnd, UINT id, UINT index)
+{
+ // Validate arguments
+ if (hWnd == NULL || index == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, CB_GETITEMDATA, index, 0);
+}
+
+// Search for the data
+UINT CbFindData(HWND hWnd, UINT id, UINT data)
+{
+ UINT i, num;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ num = CbNum(hWnd, id);
+ if (num == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ if (CbGetData(hWnd, id, i) == data)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Set the height of the item
+void CbSetHeight(HWND hWnd, UINT id, UINT value)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, CB_SETITEMHEIGHT, 0, (UINT)(GetTextScalingFactor() * (double)value));
+}
+
+// Search by specifying the data
+void CbSelect(HWND hWnd, UINT id, int data)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (data == INFINITE)
+ {
+ // Get the first item
+ CbSelectIndex(hWnd, id, 0);
+ return;
+ }
+
+ index = CbFindData(hWnd, id, data);
+ if (index == INFINITE)
+ {
+ // Can not be found
+ return;
+ }
+
+ // Select
+ CbSelectIndex(hWnd, id, index);
+}
+
+// Get the currently selected item
+UINT CbGetSelectIndex(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ return SendMsg(hWnd, id, CB_GETCURSEL, 0, 0);
+}
+
+// Get the value that is currently selected
+UINT CbGetSelect(HWND hWnd, UINT id)
+{
+ UINT index;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return INFINITE;
+ }
+
+ index = CbGetSelectIndex(hWnd, id);
+ if (index == INFINITE)
+ {
+ return INFINITE;
+ }
+
+ return CbGetData(hWnd, id, index);
+}
+
+// OK button is pressed
+void PasswordDlgOnOk(HWND hWnd, UI_PASSWORD_DLG *p)
+{
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ GetTxtA(hWnd, E_USERNAME, p->Username, sizeof(p->Username));
+ GetTxtA(hWnd, E_PASSWORD, p->Password, sizeof(p->Password));
+ p->Type = CbGetSelect(hWnd, C_TYPE);
+
+ if (p->ShowNoSavePassword)
+ {
+ p->NoSavePassword = IsChecked(hWnd, R_NO_SAVE_PASSWORD);
+ }
+
+ EndDialog(hWnd, true);
+}
+
+// Password input dialog procedure
+UINT PasswordDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ UI_PASSWORD_DLG *p = (UI_PASSWORD_DLG *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetIcon(hWnd, 0, ICO_KEY);
+ CbSetHeight(hWnd, C_TYPE, 18);
+ if (p->ServerName != NULL)
+ {
+ FormatText(hWnd, 0, p->ServerName);
+ }
+ else
+ {
+ SetText(hWnd, 0, _UU("PW_LOGIN_DLG_TITLE"));
+ }
+
+ if (p->ProxyServer == false)
+ {
+ FormatText(hWnd, S_TITLE, p->ServerName == NULL ? "" : p->ServerName);
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("PW_MSG_PROXY"), p->ServerName == NULL ? "" : p->ServerName);
+ SetText(hWnd, S_TITLE, tmp);
+ }
+
+ // Enumerate the connection methods
+ SendMsg(hWnd, C_TYPE, CBEM_SETUNICODEFORMAT, true, 0);
+
+ if (StrCmpi(p->Username, WINUI_PASSWORD_NULL_USERNAME) != 0)
+ {
+ SetTextA(hWnd, E_USERNAME, p->Username);
+ SetTextA(hWnd, E_PASSWORD, p->Password);
+ }
+ else
+ {
+ p->RetryIntervalSec = 0;
+ SetTextA(hWnd, E_USERNAME, "");
+ SetTextA(hWnd, E_PASSWORD, "");
+ }
+
+ if (p->AdminMode == false)
+ {
+ if (p->ProxyServer == false)
+ {
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);
+ }
+ else
+ {
+ CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_PROXY"), 0);
+ Disable(hWnd, C_TYPE);
+ }
+
+ CbSelect(hWnd, C_TYPE, p->Type);
+ }
+ else
+ {
+ CbAddStr(hWnd, C_TYPE, _UU("SM_PASSWORD_TYPE_STR"), 0);
+ Disable(hWnd, C_TYPE);
+ SetTextA(hWnd, E_USERNAME, "Administrator");
+ Disable(hWnd, E_USERNAME);
+ }
+
+ if (IsEmpty(hWnd, E_USERNAME))
+ {
+ FocusEx(hWnd, E_USERNAME);
+ }
+ else
+ {
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ LimitText(hWnd, E_USERNAME, MAX_USERNAME_LEN);
+ LimitText(hWnd, E_PASSWORD, MAX_PASSWORD_LEN);
+
+ PasswordDlgProcChange(hWnd, p);
+
+ if (p->RetryIntervalSec != 0)
+ {
+ SetTimer(hWnd, 1, 50, NULL);
+ FormatText(hWnd, S_COUNTDOWN, p->RetryIntervalSec);
+ Show(hWnd, S_COUNTDOWN);
+ Show(hWnd, P_PROGRESS);
+ SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec * 1000);
+ }
+ else
+ {
+ Hide(hWnd, S_COUNTDOWN);
+ Hide(hWnd, P_PROGRESS);
+ }
+
+ if (p->ShowNoSavePassword)
+ {
+ Show(hWnd, R_NO_SAVE_PASSWORD);
+ Check(hWnd, R_NO_SAVE_PASSWORD, p->NoSavePassword);
+ }
+ else
+ {
+ Hide(hWnd, R_NO_SAVE_PASSWORD);
+ }
+
+ p->StartTick = Tick64();
+
+ if (p->CancelEvent != NULL)
+ {
+ SetTimer(hWnd, 2, 50, NULL);
+ }
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ if (p->RetryIntervalSec != 0)
+ {
+ wchar_t tmp[MAX_SIZE];
+ UINT64 end, now, start;
+ start = p->StartTick;
+ end = p->StartTick + (UINT64)(p->RetryIntervalSec * 1000);
+ now = Tick64();
+
+ if (now <= end)
+ {
+ UniFormat(tmp, sizeof(tmp), _UU("PW_RETRYCOUNT"), (UINT)((end - now) / 1000));
+ SetText(hWnd, S_COUNTDOWN, tmp);
+ SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
+ }
+ else
+ {
+ EndDialog(hWnd, true);
+ }
+ }
+ break;
+
+ case 2:
+ if (p->CancelEvent != NULL)
+ {
+ // Wait for the end event
+ HANDLE hEvent = (HANDLE)p->CancelEvent->pData;
+ UINT ret = WaitForSingleObject(hEvent, 0);
+ if (ret != WAIT_TIMEOUT)
+ {
+ // Forced termination event is set
+ Close(hWnd);
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ PasswordDlgOnOk(hWnd, p);
+ break;
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ switch (LOWORD(wParam))
+ {
+ case E_USERNAME:
+ case E_PASSWORD:
+ PasswordDlgProcChange(hWnd, p);
+ break;
+ }
+ break;
+ case CBN_SELCHANGE:
+ switch (LOWORD(wParam))
+ {
+ case C_TYPE:
+ PasswordDlgProcChange(hWnd, p);
+ if (IsEmpty(hWnd, E_USERNAME))
+ {
+ FocusEx(hWnd, E_USERNAME);
+ }
+ else
+ {
+ FocusEx(hWnd, E_PASSWORD);
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Set the position of the progress bar
+void SetPos(HWND hWnd, UINT id, UINT pos)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, PBM_SETPOS, pos, 0);
+}
+
+// Set the range of the progress bar
+void SetRange(HWND hWnd, UINT id, UINT start, UINT end)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, PBM_SETRANGE32, start, end);
+}
+
+// Password input dialog
+bool PasswordDlg(HWND hWnd, UI_PASSWORD_DLG *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ p->StartTick = Tick64();
+
+ return Dialog(hWnd, D_PASSWORD, PasswordDlgProc, p);
+}
+
+// Passphrase input dialog
+bool PassphraseDlg(HWND hWnd, char *pass, UINT pass_size, BUF *buf, bool p12)
+{
+ PASSPHRASE_DLG p;
+ // Validate arguments
+ if (pass == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(PASSPHRASE_DLG));
+
+ p.buf = buf;
+ p.p12 = p12;
+
+ // Examine whether it is encrypted first
+ if (p12 == false)
+ {
+ // Secret key
+ if (IsEncryptedK(buf, true) == false)
+ {
+ // Unencrypted
+ StrCpy(pass, pass_size, "");
+ return true;
+ }
+ }
+ else
+ {
+ // PKCS#12
+ P12 *p12 = BufToP12(buf);
+ if (p12 == NULL)
+ {
+ // It is in unknown format, but not encrypted
+ StrCpy(pass, pass_size, "");
+ return true;
+ }
+
+ if (IsEncryptedP12(p12) == false)
+ {
+ // Unencrypted
+ StrCpy(pass, pass_size, "");
+ FreeP12(p12);
+ return true;
+ }
+ FreeP12(p12);
+ }
+
+ // Show the dialog
+ if (Dialog(hWnd, D_PASSPHRASE, PassphraseDlgProc, &p) == false)
+ {
+ // Cancel
+ return false;
+ }
+
+ StrCpy(pass, pass_size, p.pass);
+
+ return true;
+}
+
+// WM_COMMAND handler
+void PassphraseDlgProcCommand(HWND hWnd, PASSPHRASE_DLG *p)
+{
+ char *pass;
+ bool ok;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return;
+ }
+
+ pass = GetTextA(hWnd, E_PASSPHRASE);
+ if (pass == NULL)
+ {
+ return;
+ }
+
+ ok = false;
+
+ if (p->p12 == false)
+ {
+ K *k;
+ k = BufToK(p->buf, true, true, pass);
+ if (k != NULL)
+ {
+ ok = true;
+ FreeK(k);
+ }
+ }
+ else
+ {
+ X *x;
+ K *k;
+ P12 *p12;
+ p12 = BufToP12(p->buf);
+ if (p12 != NULL)
+ {
+ if (ParseP12(p12, &x, &k, pass))
+ {
+ FreeX(x);
+ FreeK(k);
+ ok = true;
+ }
+ FreeP12(p12);
+ }
+ }
+
+ Free(pass);
+
+ SetEnable(hWnd, IDOK, ok);
+}
+
+// Passphrase input dialog procedure
+UINT PassphraseDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ PASSPHRASE_DLG *p = (PASSPHRASE_DLG *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ PassphraseDlgProcCommand(hWnd, p);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ GetTxtA(hWnd, E_PASSPHRASE, p->pass, sizeof(p->pass));
+ EndDialog(hWnd, true);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+
+ switch (LOWORD(wParam))
+ {
+ case E_PASSPHRASE:
+ PassphraseDlgProcCommand(hWnd, p);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, false);
+ break;
+ }
+
+ return 0;
+}
+
+// PKCS utility
+void PkcsUtil()
+{
+ InitWinUi(_UU("PKCS_UTIL_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+ Dialog(NULL, D_PKCSUTIL, PkcsUtilProc, NULL);
+ FreeWinUi();
+}
+
+// PKCS writing
+void PkcsUtilWrite(HWND hWnd)
+{
+ wchar_t *filename;
+ BUF *in_buf;
+ char filename_ansi[MAX_SIZE];
+ char pass[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ filename = OpenDlg(hWnd, _UU("DLG_PKCS12_FILTER"), _UU("PKCS_UTIL_SAVEDLG_TITLE"));
+ if (filename == NULL)
+ {
+ return;
+ }
+
+ UniToStr(filename_ansi, sizeof(filename_ansi), filename);
+
+ in_buf = ReadDump(filename_ansi);
+
+ if (in_buf == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("PKCS_UTIL_READ_ERROR"), filename);
+ }
+ else
+ {
+ if (PassphraseDlg(hWnd, pass, sizeof(pass), in_buf, true))
+ {
+ P12 *p12 = BufToP12(in_buf);
+ if (p12 == NULL)
+ {
+ MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("PKCS_UTIL_BAD_FILE"));
+ }
+ else
+ {
+ X *x = NULL;
+ K *k = NULL;
+ BUF *b;
+ ParseP12(p12, &x, &k, pass);
+ FreeP12(p12);
+ p12 = NewP12(x, k, NULL);
+ FreeX(x);
+ FreeK(k);
+ b = P12ToBuf(p12);
+ FreeP12(p12);
+ if (b != NULL)
+ {
+ // Batch processing
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_WRITE_DATA, _SS("PKCS_UTIL_SECA_FILENAME"), false,
+ b, NULL, NULL, NULL, NULL, NULL},
+ };
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), 2, 0))
+ {
+ MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("PKCS_UTIL_WRITE_OK_MSG"), filename);
+ }
+ }
+ FreeBuf(b);
+ }
+ }
+
+ FreeBuf(in_buf);
+ }
+
+ Free(filename);
+}
+
+// PKCS erase
+void PkcsUtilErase(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ _UU("PKCS_MAKE_SURE")) == IDYES)
+ {
+ // Batch processing
+ WINUI_SECURE_BATCH batch[] =
+ {
+ {WINUI_SECURE_DELETE_OBJECT, _SS("PKCS_UTIL_SECA_FILENAME"), false,
+ NULL, NULL, NULL, NULL, NULL, NULL},
+ };
+
+ if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), 2, 0))
+ {
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("PKCS_UTIL_DELETE_OK_MSG"));
+ }
+ }
+}
+
+// PKCS Utility dialog
+UINT PkcsUtilProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ DlgFont(hWnd, S_TITLE, 12, true);
+ SetIcon(hWnd, 0, ICO_CERT);
+ SetFont(hWnd, S_COPYRIGHT, GetFont("Arial", 8, false, false, false, false));
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_WRITE:
+ PkcsUtilWrite(hWnd);
+ break;
+
+ case B_ERASE:
+ PkcsUtilErase(hWnd);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// [Save File] dialog
+wchar_t *SaveDlg(HWND hWnd, wchar_t *filter, wchar_t *title, wchar_t *default_name, wchar_t *default_ext)
+{
+ wchar_t *filter_str;
+ wchar_t tmp[MAX_SIZE];
+ OPENFILENAMEW o;
+
+ if (MsIsNt() == false)
+ {
+ char *ret, *s1, *s2, *s3, *s4;
+ wchar_t *wr;
+ s1 = CopyUniToStr(filter);
+ s2 = CopyUniToStr(title);
+ s3 = CopyUniToStr(default_name);
+ s4 = CopyUniToStr(default_ext);
+ ret = SaveDlgA(hWnd, s1, s2, s3, s4);
+ Free(s1);
+ Free(s2);
+ Free(s3);
+ Free(s4);
+ wr = CopyStrToUni(ret);
+ Free(ret);
+ return wr;
+ }
+
+ // Validate arguments
+ if (filter == NULL)
+ {
+ filter = _UU("DLG_ALL_FILES");
+ }
+
+ filter_str = MakeFilter(filter);
+
+ Zero(&o, sizeof(o));
+ Zero(tmp, sizeof(tmp));
+
+ if (default_name != NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), default_name);
+ }
+
+ o.lStructSize = sizeof(o);
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))
+ {
+ o.lStructSize = OPENFILENAME_SIZE_VERSION_400W;
+ }
+
+ o.hwndOwner = hWnd;
+ o.hInstance = GetModuleHandle(NULL);
+ o.lpstrFile = tmp;
+ o.lpstrTitle = title;
+ o.lpstrFilter = filter_str;
+ o.nMaxFile = sizeof(tmp);
+ o.Flags = OFN_OVERWRITEPROMPT;
+ o.lpstrDefExt = default_ext;
+
+ if (GetSaveFileNameW(&o) == false)
+ {
+ Free(filter_str);
+ return NULL;
+ }
+
+ Free(filter_str);
+
+ return UniCopyStr(tmp);
+}
+char *SaveDlgA(HWND hWnd, char *filter, char *title, char *default_name, char *default_ext)
+{
+ char *filter_str;
+ char tmp[MAX_SIZE];
+ OPENFILENAME o;
+ // Validate arguments
+ if (filter == NULL)
+ {
+ filter = _SS("DLG_ALL_FILES");
+ }
+
+ filter_str = MakeFilterA(filter);
+
+ Zero(&o, sizeof(o));
+ Zero(tmp, sizeof(tmp));
+
+ if (default_name != NULL)
+ {
+ StrCpy(tmp, sizeof(tmp), default_name);
+ }
+
+ o.lStructSize = sizeof(o);
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))
+ {
+ o.lStructSize = OPENFILENAME_SIZE_VERSION_400A;
+ }
+
+ o.hwndOwner = hWnd;
+ o.hInstance = GetModuleHandle(NULL);
+ o.lpstrFile = tmp;
+ o.lpstrTitle = title;
+ o.lpstrFilter = filter_str;
+ o.nMaxFile = sizeof(tmp);
+ o.Flags = OFN_OVERWRITEPROMPT;
+ o.lpstrDefExt = default_ext;
+
+ if (GetSaveFileName(&o) == false)
+ {
+ Free(filter_str);
+ return NULL;
+ }
+
+ Free(filter_str);
+
+ return CopyStr(tmp);
+}
+
+// [Open File] dialog
+wchar_t *OpenDlg(HWND hWnd, wchar_t *filter, wchar_t *title)
+{
+ wchar_t *filter_str;
+ wchar_t tmp[MAX_SIZE];
+ OPENFILENAMEW o;
+
+ if (MsIsNt() == false)
+ {
+ char *ret;
+ char *filter_a;
+ char *title_a;
+ wchar_t *w;
+ filter_a = CopyUniToStr(filter);
+ title_a = CopyUniToStr(title);
+ ret = OpenDlgA(hWnd, filter_a, title_a);
+ Free(filter_a);
+ Free(title_a);
+ w = CopyStrToUni(ret);
+ Free(ret);
+ return w;
+ }
+
+ // Validate arguments
+ if (filter == NULL)
+ {
+ filter = _UU("DLG_ALL_FILES");
+ }
+
+ filter_str = MakeFilter(filter);
+
+ Zero(&o, sizeof(OPENFILENAMEW));
+ Zero(tmp, sizeof(tmp));
+
+ o.lStructSize = sizeof(o);
+
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))
+ {
+ o.lStructSize = OPENFILENAME_SIZE_VERSION_400W;
+ }
+
+
+ o.hwndOwner = hWnd;
+ o.hInstance = GetModuleHandle(NULL);
+ o.lpstrFilter = filter_str;
+ o.lpstrFile = tmp;
+ o.nMaxFile = sizeof(tmp);
+ o.lpstrTitle = title;
+ o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+
+ if (GetOpenFileNameW(&o) == false)
+ {
+ Free(filter_str);
+ return NULL;
+ }
+
+ Free(filter_str);
+
+ return UniCopyStr(tmp);
+}
+char *OpenDlgA(HWND hWnd, char *filter, char *title)
+{
+ char *filter_str;
+ char tmp[MAX_SIZE];
+ OPENFILENAME o;
+ // Validate arguments
+ if (filter == NULL)
+ {
+ filter = _SS("DLG_ALL_FILES");
+ }
+
+ filter_str = MakeFilterA(filter);
+
+ Zero(&o, sizeof(OPENFILENAME));
+ Zero(tmp, sizeof(tmp));
+
+ o.lStructSize = sizeof(o);
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))
+ {
+ o.lStructSize = OPENFILENAME_SIZE_VERSION_400A;
+ }
+
+ o.hwndOwner = hWnd;
+ o.hInstance = GetModuleHandle(NULL);
+ o.lpstrFilter = filter_str;
+ o.lpstrFile = tmp;
+ o.nMaxFile = sizeof(tmp);
+ o.lpstrTitle = title;
+ o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+
+ if (GetOpenFileName(&o) == false)
+ {
+ Free(filter_str);
+ return NULL;
+ }
+
+ Free(filter_str);
+
+ return CopyStr(tmp);
+}
+
+// Generate the filter string
+wchar_t *MakeFilter(wchar_t *str)
+{
+ UINT i;
+ wchar_t *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(UniStrSize(str) + 32);
+
+ for (i = 0;i < UniStrLen(str);i++)
+ {
+ if (str[i] == L'|')
+ {
+ ret[i] = L'\0';
+ }
+ else
+ {
+ ret[i] = str[i];
+ }
+ }
+
+ return ret;
+}
+char *MakeFilterA(char *str)
+{
+ UINT i;
+ char *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(StrSize(str) + 32);
+
+ for (i = 0;i < StrLen(str);i++)
+ {
+ if (str[i] == '|')
+ {
+ ret[i] = '\0';
+ }
+ else
+ {
+ ret[i] = str[i];
+ }
+ }
+
+ return ret;
+}
+
+// Execution of batch
+bool ExecuteSecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev, WINUI_SECURE_BATCH *batch)
+{
+ LIST *o;
+ void *buf;
+ UINT size = 10 * 1024; // Maximum size of the data
+ UINT type = INFINITE;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || dev == NULL || batch == NULL || sec == NULL)
+ {
+ return false;
+ }
+
+ switch (batch->Type)
+ {
+ case WINUI_SECURE_DELETE_CERT:
+ type = SEC_X;
+ goto DELETE_OBJECT;
+
+ case WINUI_SECURE_DELETE_KEY:
+ type = SEC_K;
+ goto DELETE_OBJECT;
+
+ case WINUI_SECURE_DELETE_DATA:
+ type = SEC_DATA;
+ goto DELETE_OBJECT;
+
+ case WINUI_SECURE_DELETE_OBJECT:
+ // Delete the object
+DELETE_OBJECT:
+ SetText(hWnd, S_STATUS, _UU("SEC_DELETE"));
+ if (DeleteSecObjectByName(sec, batch->Name, type) == false)
+ {
+ p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_DELETE"));
+ return false;
+ }
+ break;
+
+ case WINUI_SECURE_ENUM_OBJECTS:
+ // Enumerate objects
+ SetText(hWnd, S_STATUS, _UU("SEC_ENUM"));
+ o = EnumSecObject(sec);
+ if (o == NULL)
+ {
+ p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_ENUM"));
+ return false;
+ }
+
+ batch->EnumList = o;
+ break;
+
+ case WINUI_SECURE_WRITE_DATA:
+ // Write the data
+ SetText(hWnd, S_STATUS, _UU("SEC_WRITE_DATA"));
+ if (WriteSecData(sec, batch->Private, batch->Name, batch->InputData->Buf, batch->InputData->Size) == false)
+ {
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
+ return false;
+ }
+ break;
+
+ case WINUI_SECURE_READ_DATA:
+ // Read the data
+ SetText(hWnd, S_STATUS, _UU("SEC_READ_DATA"));
+ buf = MallocEx(size, true);
+ size = ReadSecData(sec, batch->Name, buf, size);
+ if (size == 0)
+ {
+ Free(buf);
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
+ return false;
+ }
+ batch->OutputData = NewBuf();
+ WriteBuf(batch->OutputData, buf, size);
+ SeekBuf(batch->OutputData, 0, 0);
+ Free(buf);
+ break;
+
+ case WINUI_SECURE_WRITE_CERT:
+ // Write the certificate
+ SetText(hWnd, S_STATUS, _UU("SEC_WRITE_CERT"));
+ if (WriteSecCert(sec, batch->Private, batch->Name, batch->InputX) == false)
+ {
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
+ return false;
+ }
+ break;
+
+ case WINUI_SECURE_READ_CERT:
+ // Read the certificate
+ SetText(hWnd, S_STATUS, _UU("SEC_READ_CERT"));
+ batch->OutputX = ReadSecCert(sec, batch->Name);
+ if (batch->OutputX == NULL)
+ {
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
+ return false;
+ }
+ break;
+
+ case WINUI_SECURE_WRITE_KEY:
+ // Write the secret key
+ SetText(hWnd, S_STATUS, _UU("SEC_WRITE_KEY"));
+ if (WriteSecKey(sec, batch->Private, batch->Name, batch->InputK) == false)
+ {
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
+ return false;
+ }
+ break;
+
+ case WINUI_SECURE_SIGN_WITH_KEY:
+ // Signature
+ SetText(hWnd, S_STATUS, _UU("SEC_SIGN"));
+ if (SignSec(sec, batch->Name, batch->OutputSign, batch->InputData->Buf, batch->InputData->Size) == false)
+ {
+ p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
+ _UU("SEC_ERROR_SIGN_1") : _UU("SEC_ERROR_SIGN_2"));
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+// Run the secure device operations as a batch job
+void SecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev)
+{
+ UINT i;
+ // Validate arguments
+ if (hWnd == NULL || p == NULL || dev == NULL || sec == NULL)
+ {
+ return;
+ }
+
+ // Sequential processing
+ for (i = 0;i < p->w->num_batch;i++)
+ {
+ WINUI_SECURE_BATCH *batch = &p->w->batch[i];
+
+ if (ExecuteSecureDeviceBatch(hWnd, sec, p, dev, batch) == false)
+ {
+ // If fail even one, abort immediately
+ return;
+ }
+ }
+
+ // All batch job succeeded
+ p->Succeed = true;
+}
+
+// Thread to perform a secure device operation
+void SecureDeviceThread(THREAD *t, void *param)
+{
+ SECURE *sec;
+ SECURE_DEVICE_THREAD *p = (SECURE_DEVICE_THREAD *)param;
+ SECURE_DEVICE *dev;
+ HWND hWnd;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p->Succeed = false;
+ p->ErrorMessage = NULL;
+
+ hWnd = p->hWnd;
+
+ // Open the device
+ dev = GetSecureDevice(p->w->device_id);
+ SetText(hWnd, S_STATUS, _UU("SEC_OPENING"));
+ sec = OpenSec(p->w->device_id);
+ if (sec == NULL)
+ {
+ // Device open failure
+ if (p->w->device_id != 9)
+ {
+ p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICE"), dev->DeviceName);
+ }
+ else
+ {
+ p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICEEX"), dev->DeviceName);
+ }
+ }
+ else
+ {
+ // Open the session
+ SetText(hWnd, S_STATUS, _UU("SEC_OPEN_SESSION"));
+ if (OpenSecSession(sec, 0) == false)
+ {
+ // Session initialization failure
+ p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_SESSION"), dev->DeviceName);
+ }
+ else
+ {
+ // Login
+ SetText(hWnd, S_STATUS, _UU("SEC_LOGIN"));
+ if (LoginSec(sec, p->pin) == false)
+ {
+ // Login failure
+ p->ErrorMessage =UniCopyStr(_UU("SEC_ERROR_LOGIN"));
+ }
+ else
+ {
+ // Batch processing main
+ SetText(hWnd, S_STATUS, _UU("SEC_INIT_BATCH"));
+ SecureDeviceBatch(hWnd, sec, p, dev);
+
+ // Logout
+ SetText(hWnd, S_STATUS, _UU("SEC_LOGOUT"));
+ LogoutSec(sec);
+ }
+
+ // Close the session
+ SetText(hWnd, S_STATUS, _UU("SEC_CLOSE_SESSION"));
+ CloseSecSession(sec);
+ }
+
+ // Close the device
+ SetText(hWnd, S_STATUS, _UU("SEC_CLOSING"));
+ CloseSec(sec);
+ }
+
+ if (p->Succeed)
+ {
+ // If successful, show the message for 150ms (service)
+ SetText(hWnd, S_STATUS, _UU("SEC_FINISHED"));
+ SleepThread(150);
+ }
+
+ SendMessage(p->hWnd, WM_APP + 1, 0, 0);
+}
+
+// Start a secure device operation
+void StartSecureDevice(HWND hWnd, SECURE_DEVICE_WINDOW *w)
+{
+ SECURE_DEVICE_THREAD *p;
+ // Validate arguments
+ if (hWnd == NULL || w == NULL)
+ {
+ return;
+ }
+
+ // Disable the control
+ EnableSecureDeviceWindowControls(hWnd, false);
+
+ // Start the thread
+ p = ZeroMalloc(sizeof(SECURE_DEVICE_THREAD));
+ p->w = w;
+ p->hWnd = hWnd;
+ w->p = p;
+ p->pin = GetTextA(hWnd, E_PIN);
+ ReleaseThread(NewThread(SecureDeviceThread, p));
+}
+
+// Enable or disable the control of the secure device operation window
+void EnableSecureDeviceWindowControls(HWND hWnd, bool enable)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (enable)
+ {
+ Show(hWnd, S_PIN_CODE);
+ Show(hWnd, E_PIN);
+ Show(hWnd, S_WARNING);
+ }
+ else
+ {
+ Hide(hWnd, S_PIN_CODE);
+ Hide(hWnd, E_PIN);
+ Hide(hWnd, S_WARNING);
+ }
+
+ SetEnable(hWnd, IDOK, enable);
+ SetEnable(hWnd, IDCANCEL, enable);
+ SetEnable(hWnd, S_TITLE, enable);
+ SetEnable(hWnd, S_DEVICE_INFO, enable);
+ SetEnable(hWnd, S_INSERT_SECURE, enable);
+
+ if (enable == false)
+ {
+ DisableClose(hWnd);
+ SetText(hWnd, S_STATUS, L"");
+ Show(hWnd, S_STATUS);
+ PlayAvi(hWnd, A_PROGRESS, true);
+ }
+ else
+ {
+ EnableClose(hWnd);
+ SetText(hWnd, S_STATUS, L"");
+ Hide(hWnd, S_STATUS);
+ StopAvi(hWnd, A_PROGRESS);
+ }
+}
+
+// Secure device operation window procedure
+UINT SecureDeviceWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ SECURE_DEVICE_WINDOW *w = (SECURE_DEVICE_WINDOW *)param;
+ SECURE_DEVICE *dev = GetSecureDevice(w->device_id);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (dev == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_ERROR_INVALID_ID"), w->device_id);
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ if (IsJPKI(dev->Id))
+ {
+ // Juki card
+ Hide(hWnd, S_IMAGE);
+ Show(hWnd, S_IMAGE2);
+ Hide(hWnd, S_IMAGE_TSUKUBA);
+ }
+ else
+ {
+ // Regular card
+ Hide(hWnd, S_IMAGE2);
+
+ if (w->BitmapId != 0)
+ {
+ // For University of Tsukuba
+ Hide(hWnd, S_IMAGE);
+ Show(hWnd, S_IMAGE_TSUKUBA);
+ }
+ else
+ {
+ // For general use
+ Show(hWnd, S_IMAGE);
+ Hide(hWnd, S_IMAGE_TSUKUBA);
+ }
+ }
+
+ FormatText(hWnd, 0, dev->Type != SECURE_USB_TOKEN ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN"),
+ dev->DeviceName);
+ FormatText(hWnd, S_TITLE, dev->DeviceName);
+ FormatText(hWnd, S_INSERT_SECURE,
+ dev->Type != SECURE_USB_TOKEN ? _UU("SEC_INIT_MSG_1") : _UU("SEC_INIT_MSG_2"));
+ FormatText(hWnd, S_DEVICE_INFO,
+ dev->DeviceName, dev->Manufacturer, dev->ModuleName);
+
+ DlgFont(hWnd, S_SOFTWARE_TITLE, 11, 0);
+ SetText(hWnd, S_SOFTWARE_TITLE, title_bar);
+
+ DlgFont(hWnd, S_TITLE, 14, true);
+ DlgFont(hWnd, S_DEVICE_INFO, 11, false);
+ DlgFont(hWnd, S_STATUS, 13, true);
+ EnableSecureDeviceWindowControls(hWnd, true);
+ OpenAvi(hWnd, A_PROGRESS, AVI_PROGRESS);
+
+ SetIcon(hWnd, 0, ICO_KEY);
+
+ // Initial PIN
+ if ((w->default_pin != NULL && StrLen(w->default_pin) != 0) || (cached_pin_code_expires >= Tick64()))
+ {
+ if (w->default_pin != NULL && StrLen(w->default_pin) != 0)
+ {
+ SetTextA(hWnd, E_PIN, w->default_pin);
+ }
+ else
+ {
+ SetTextA(hWnd, E_PIN, cached_pin_code);
+ }
+ SetTimer(hWnd, 1, 1, NULL);
+ }
+
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ Command(hWnd, IDOK);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ StartSecureDevice(hWnd, w);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ if (IsEnable(hWnd, IDCANCEL))
+ {
+ CloseAvi(hWnd, A_PROGRESS);
+ EndDialog(hWnd, false);
+ }
+ break;
+
+ case WM_APP + 1:
+ // There is a response from the thread
+ if (w->p != NULL)
+ {
+ if (w->p->Succeed)
+ {
+ // Success
+ if (w->default_pin != NULL)
+ {
+ StrCpy(w->default_pin, 128, w->p->pin);
+ }
+ StrCpy(cached_pin_code, sizeof(cached_pin_code), w->p->pin);
+ cached_pin_code_expires = Tick64() + (UINT64)WINUI_SECUREDEVICE_PIN_CACHE_TIME;
+ Free(w->p->pin);
+ Free(w->p);
+ EndDialog(hWnd, true);
+ }
+ else
+ {
+ // Failure
+ cached_pin_code_expires = 0;
+ EnableSecureDeviceWindowControls(hWnd, true);
+ FocusEx(hWnd, E_PIN);
+ MsgBox(hWnd, MB_ICONEXCLAMATION, w->p->ErrorMessage);
+ Free(w->p->pin);
+ Free(w->p->ErrorMessage);
+ Free(w->p);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Send a WM_COMMAND
+void Command(HWND hWnd, UINT id)
+{
+ SendMessage(hWnd, WM_COMMAND, id, 0);
+}
+
+// Show the secure device window
+bool SecureDeviceWindow(HWND hWnd, WINUI_SECURE_BATCH *batch, UINT num_batch, UINT device_id, UINT bitmap_id)
+{
+ SECURE_DEVICE_WINDOW w;
+ UINT i;
+ // Validate arguments
+ if (batch == NULL || num_batch == 0 || device_id == 0)
+ {
+ return false;
+ }
+
+ // Initialize the success flag
+ for (i = 0;i < num_batch;i++)
+ {
+ batch[i].Succeed = false;
+ }
+
+ Zero(&w, sizeof(w));
+ w.batch = batch;
+ w.device_id = device_id;
+ w.num_batch = num_batch;
+ w.BitmapId = bitmap_id;
+
+ // Open a dialog
+ return (bool)Dialog(hWnd, D_SECURE, SecureDeviceWindowProc, &w);
+}
+
+// Stop playing the AVI
+void StopAvi(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Animate_Stop(DlgItem(hWnd, id));
+ Hide(hWnd, id);
+}
+
+// Play an AVI
+void PlayAvi(HWND hWnd, UINT id, bool repeat)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Show(hWnd, id);
+ Animate_Play(DlgItem(hWnd, id), 0, -1, (repeat ? -1 : 0));
+}
+
+// Close the AVI file
+void CloseAvi(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ StopAvi(hWnd, id);
+ Animate_Close(DlgItem(hWnd, id));
+}
+
+// Open an AVI file
+void OpenAvi(HWND hWnd, UINT id, UINT avi_id)
+{
+ // Validate arguments
+ if (hWnd == NULL || avi_id == 0)
+ {
+ return;
+ }
+
+ Hide(hWnd, id);
+ Animate_OpenEx(DlgItem(hWnd, id), hDll, MAKEINTRESOURCE(avi_id));
+}
+
+// Set the font to the control
+void DlgFont(HWND hWnd, UINT id, UINT size, UINT bold)
+{
+ DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
+
+ if (param == NULL || param->meiryo == false)
+ {
+ SetFont(hWnd, id, Font(size, bold));
+ }
+ else
+ {
+ SetFont(hWnd, id, GetFont((_GETLANG() == 2 ? "Microsoft YaHei" : GetMeiryoFontName()), size, bold, false, false, false));
+ }
+}
+
+// Generate a standard font
+HFONT Font(UINT size, UINT bold)
+{
+ return GetFont(NULL, size, bold, false, false, false);
+}
+
+// Dialog procedure for internal management
+UINT CALLBACK InternalDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
+ void *app_param = NULL;
+ bool white_flag = false;
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ if (msg == WM_INITDIALOG)
+ {
+ DoEvents(hWnd);
+ }
+
+ if (param == NULL)
+ {
+ if (msg == WM_INITDIALOG)
+ {
+ param = (void *)lParam;
+ InitDialogInternational(hWnd, param);
+ }
+ }
+ if (param != NULL)
+ {
+ app_param = param->param;
+ white_flag = param->white;
+ }
+
+ ret = DlgProc(hWnd, msg, wParam, lParam, white_flag);
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ ret = 0;
+
+ if (param != NULL)
+ {
+ if (param->proc != NULL)
+ {
+ ret = param->proc(hWnd, msg, wParam, lParam, app_param);
+ }
+ else
+ {
+ if (msg == WM_CLOSE)
+ {
+ EndDialog(hWnd, 0);
+ }
+ else if (msg == WM_COMMAND && (wParam == IDOK || wParam == IDCANCEL))
+ {
+ Close(hWnd);
+ }
+ }
+ }
+
+ if (msg == WM_INITDIALOG)
+ {
+ SetForegroundWindow(hWnd);
+ SetActiveWindow(hWnd);
+ }
+
+ return ret;
+}
+
+// Show a dialog box
+UINT Dialog(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param)
+{
+ bool white = true;
+
+ return DialogEx(hWnd, id, proc, param, white);
+}
+UINT DialogEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)
+{
+ return DialogEx2(hWnd, id, proc, param, white, false);
+}
+UINT DialogEx2(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white, bool meiryo)
+{
+ UINT ret;
+ DIALOG_PARAM p;
+ // Validate arguments
+ if (id == 0)
+ {
+ return 0;
+ }
+
+ Zero(&p, sizeof(p));
+ p.param = param;
+ p.white = white;
+ p.proc = proc;
+
+ p.BitmapList = NewBitmapList();
+
+ if (MsIsVista())
+ {
+ p.meiryo = meiryo;
+ }
+
+ ret = DialogInternal(hWnd, id, InternalDialogProc, &p);
+
+ FreeBitmapList(p.BitmapList);
+
+ return ret;
+}
+
+// Create a modeless dialog
+HWND DialogCreateEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)
+{
+ HWND ret = NULL;
+ DIALOG_PARAM p;
+ // Validate arguments
+ if (id == 0)
+ {
+ return 0;
+ }
+
+ Zero(&p, sizeof(p));
+ p.param = param;
+ p.white = white;
+ p.proc = proc;
+
+ if (MsIsNt() == false)
+ {
+ // Win9x
+ ret = CreateDialogParamA(hDll, MAKEINTRESOURCEA(id), hWnd,
+ (DLGPROC)proc, (LPARAM)param);
+ }
+ else
+ {
+ // WinNT
+ ret = CreateDialogParamW(hDll, MAKEINTRESOURCEW(id), hWnd,
+ (DLGPROC)proc, (LPARAM)param);
+ }
+
+ return ret;
+}
+
+// Set the bitmap to the button
+void SetBitmap(HWND hWnd, UINT id, UINT bmp_id)
+{
+ HBITMAP bmp;
+ char *class_name;
+ DIALOG_PARAM *dialog_param = NULL;
+ bool need_resize = 0;
+ double resize_x = 1.0;
+ double resize_y = 1.0;
+ bool add_to_free_list = false;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ bmp = LoadImage(hDll, MAKEINTRESOURCE(bmp_id), IMAGE_BITMAP, 0, 0, (MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR);
+ if (bmp == NULL)
+ {
+ return;
+ }
+
+ dialog_param = GetParam(hWnd);
+
+ // Determine the need for resizing
+ if (dialog_param)
+ {
+ if (MsIsVista())
+ {
+ GetWindowAndControlSizeResizeScale(hWnd, &need_resize, &resize_x, &resize_y);
+
+ if (need_resize)
+ {
+ // Resize
+ UINT src_x, src_y, dst_x, dst_y;
+
+ if (GetBitmapSize(bmp, &src_x, &src_y))
+ {
+ HBITMAP new_bmp;
+ double scale_factor = MIN(resize_x, resize_y);
+
+ dst_x = (UINT)((double)src_x * scale_factor);
+ dst_y = (UINT)((double)src_y * scale_factor);
+
+ new_bmp = ResizeBitmap(bmp, src_x, src_y, dst_x, dst_y);
+
+ if (new_bmp != NULL)
+ {
+ bmp = new_bmp;
+
+ add_to_free_list = true;
+ }
+ }
+ }
+ }
+ }
+
+ class_name = GetClassA(hWnd, id);
+
+ if (StrCmpi(class_name, "Static") != 0)
+ {
+ SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ }
+ else
+ {
+ SendMsg(hWnd, id, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ }
+
+ Free(class_name);
+
+ if (add_to_free_list)
+ {
+ Add(dialog_param->BitmapList, bmp);
+ }
+}
+
+// Initialize the icon cache
+void InitIconCache()
+{
+ if (icon_cache_list != NULL)
+ {
+ return;
+ }
+
+ icon_cache_list = NewList(NULL);
+}
+
+// Release the icon cache
+void FreeIconCache()
+{
+ UINT i;
+ if (icon_cache_list == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(icon_cache_list);i++)
+ {
+ ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
+ DestroyIcon(c->hIcon);
+ Free(c);
+ }
+
+ ReleaseList(icon_cache_list);
+ icon_cache_list = NULL;
+}
+
+// Get the Icon
+HICON LoadIconEx(UINT id, bool small_icon)
+{
+ HICON h = NULL;
+ UINT i;
+ if (icon_cache_list == NULL)
+ {
+ return small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
+ }
+
+ LockList(icon_cache_list);
+ {
+ for (i = 0;i < LIST_NUM(icon_cache_list);i++)
+ {
+ ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
+ if (c->id == id && c->small_icon == small_icon)
+ {
+ h = c->hIcon;
+ break;
+ }
+ }
+
+ if (h == NULL)
+ {
+ h = small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
+ if (h != NULL)
+ {
+ ICON_CACHE *c = ZeroMalloc(sizeof(ICON_CACHE));
+ c->hIcon = h;
+ c->id = id;
+ c->small_icon = small_icon;
+ Add(icon_cache_list, c);
+ }
+ }
+ }
+ UnlockList(icon_cache_list);
+
+ return h;
+}
+
+// Get a large Icon
+HICON LoadLargeIcon(UINT id)
+{
+ return LoadIconEx(id, false);
+}
+
+// Get a small icon
+HICON LoadSmallIcon(UINT id)
+{
+ return LoadIconEx(id, true);
+}
+
+// Get a large icon
+HICON LoadLargeIconInner(UINT id)
+{
+ HICON ret;
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, 0);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, LR_VGACOLOR);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
+ if (ret == NULL)
+ {
+ ret = LoadIcon(hDll, MAKEINTRESOURCE(id));
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+// Get a small icon
+HICON LoadSmallIconInner(UINT id)
+{
+ HICON ret;
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, 0);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, LR_VGACOLOR);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
+ if (ret == NULL)
+ {
+ ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
+ if (ret == NULL)
+ {
+ ret = LoadLargeIconInner(id);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+// Set the icon to the button or window
+void SetIcon(HWND hWnd, UINT id, UINT icon_id)
+{
+ HICON icon1, icon2;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ icon1 = LoadLargeIcon(icon_id);
+ if (icon1 == NULL)
+ {
+ return;
+ }
+
+ if (id == 0)
+ {
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon1);
+ icon2 = LoadSmallIcon(icon_id);
+ if (icon2 == NULL)
+ {
+ icon2 = icon1;
+ }
+ SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon2);
+ }
+ else
+ {
+ bool is_btn = true;
+ wchar_t *s = GetClass(hWnd, id);
+ if (s != NULL)
+ {
+ if (UniStrCmpi(s, L"Static") == 0)
+ {
+ is_btn = false;
+ }
+ Free(s);
+ }
+
+ if (is_btn)
+ {
+ SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon1);
+ }
+ else
+ {
+ SendMsg(hWnd, id, STM_SETICON, (WPARAM)icon1, 0);
+ }
+ }
+}
+
+// Check whether the radio button is checked
+bool IsChecked(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ return IsDlgButtonChecked(hWnd, id) == BST_CHECKED ? true : false;
+}
+
+// Check the radio button
+void Check(HWND hWnd, UINT id, bool b)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if ((!(!IsChecked(hWnd, id))) != (!(!b)))
+ {
+ CheckDlgButton(hWnd, id, b ? BST_CHECKED : BST_UNCHECKED);
+ }
+}
+
+// Confirm that the character size of the text-box is less than or equal to specified size
+bool CheckTextSize(HWND hWnd, UINT id, UINT size, bool unicode)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ if (GetTextSize(hWnd, id, unicode) <= size)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Confirm that a length of the string in the text-box is less than or equal to the specified size
+bool CheckTextLen(HWND hWnd, UINT id, UINT len, bool unicode)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ if (GetTextLen(hWnd, id, unicode) <= len)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Limit the number of characters that can be entered into the text-box
+void LimitText(HWND hWnd, UINT id, UINT count)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, EM_LIMITTEXT, count, 0);
+}
+
+// Font settings
+void SetFont(HWND hWnd, UINT id, HFONT hFont)
+{
+ SetFontEx(hWnd, id, hFont, false);
+}
+void SetFontEx(HWND hWnd, UINT id, HFONT hFont, bool no_adjust_font_size)
+{
+ // Validate arguments
+ if (hWnd == NULL || hFont == NULL)
+ {
+ return;
+ }
+
+ SendMessage(DlgItem(hWnd, id), WM_SETFONT, (WPARAM)hFont, true);
+
+ if (no_adjust_font_size == false)
+ {
+ AdjustFontSize(hWnd, id);
+ }
+}
+
+// Get the font size
+bool GetFontSize(HFONT hFont, UINT *x, UINT *y)
+{
+ bool ret = false;
+ UINT xx = 0;
+ UINT yy = 0;
+
+ // Search for the font handle
+ LockList(font_list);
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(font_list);i++)
+ {
+ FONT *f = LIST_DATA(font_list, i);
+
+ if (f->hFont == hFont)
+ {
+ xx = f->x;
+ yy = f->y;
+
+ ret = true;
+ break;
+ }
+ }
+ }
+ UnlockList(font_list);
+
+ if (ret == false)
+ {
+ ret = CalcFontSize(hFont, &xx, &yy);
+ }
+
+ if (xx == 0 || yy == 0)
+ {
+ xx = 8;
+ yy = 16;
+ }
+
+ if (x != NULL)
+ {
+ *x = xx;
+ }
+
+ if (y != NULL)
+ {
+ *y = yy;
+ }
+
+ return ret;
+}
+
+// Calculate the font size
+bool CalcFontSize(HFONT hFont, UINT *x, UINT *y)
+{
+ UINT xx = 0, yy = 0;
+ TEXTMETRIC tm;
+ SIZE sz;
+ bool ret = false;
+ HDC hDC;
+
+ hDC = CreateCompatibleDC(NULL);
+
+ SelectObject(hDC, hFont);
+
+ Zero(&tm, sizeof(tm));
+ Zero(&sz, sizeof(sz));
+
+ if (GetTextMetrics(hDC, &tm))
+ {
+ xx = tm.tmAveCharWidth;
+ yy = tm.tmHeight;
+
+ ret = true;
+
+ if (GetTextExtentPoint32(hDC,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ 52, &sz))
+ {
+ xx = (sz.cx / 26 + 1) / 2;
+ }
+ }
+
+ if (x != NULL)
+ {
+ *x = xx;
+ }
+
+ if (y != NULL)
+ {
+ *y = yy;
+ }
+
+ DeleteDC(hDC);
+
+ return ret;
+}
+
+// Get the font magnification
+double GetTextScalingFactor()
+{
+ static int cached_dpi = 0;
+ double ret = 1.0;
+
+ if (MsIsVista() == false)
+ {
+ // It's always 1.0 in Windows XP or earlier
+ return 1.0;
+ }
+
+ if (cached_dpi == 0)
+ {
+ HDC hDC = CreateCompatibleDC(NULL);
+
+ if (hDC != NULL)
+ {
+ cached_dpi = GetDeviceCaps(hDC, LOGPIXELSY);
+
+ DeleteDC(hDC);
+ }
+ }
+
+ if (cached_dpi != 0)
+ {
+ ret = (double)cached_dpi / 96.0;
+
+ if (ret < 0)
+ {
+ ret = -ret;
+ }
+ }
+
+ return ret;
+}
+
+// Get the parameters of the font that was created in the past
+bool GetFontParam(HFONT hFont, struct FONT *f)
+{
+ bool ret = false;
+ // Validate arguments
+ if (hFont == NULL || f == NULL)
+ {
+ return false;
+ }
+
+ // Search for the existing font
+ LockList(font_list);
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(font_list);i++)
+ {
+ FONT *n = LIST_DATA(font_list, i);
+
+ if (n->hFont == hFont)
+ {
+ Copy(f, n, sizeof(FONT));
+
+ ret = true;
+
+ break;
+ }
+ }
+ }
+ UnlockList(font_list);
+
+ return ret;
+}
+
+// Get the font
+HFONT GetFont(char *name, UINT size, bool bold, bool italic, bool underline, bool strikeout)
+{
+ HFONT hFont;
+ HDC hDC;
+ // Validate arguments
+ if (name == NULL)
+ {
+ name = font_name;
+ }
+ if (size == 0)
+ {
+ size = font_size;
+ if (size == 0)
+ {
+ size = 9;
+ }
+ }
+
+ // Search for the existing font
+ LockList(font_list);
+ {
+ FONT *f, t;
+ DWORD font_quality = ANTIALIASED_QUALITY;
+ OS_INFO *os = GetOsInfo();
+ UINT x = 0;
+ UINT y = 0;
+ int rotate = 0;
+ UINT dpi;
+
+ Zero(&t, sizeof(t));
+ t.Bold = bold;
+ t.Italic = italic;
+ t.Size = size;
+ t.StrikeOut = strikeout;
+ t.UnderLine = underline;
+ t.Name = CopyStr(name);
+ f = Search(font_list, &t);
+ Free(t.Name);
+
+ if (f != NULL)
+ {
+ // Font is found
+ UnlockList(font_list);
+ return f->hFont;
+ }
+
+ // Create a new font
+ hDC = CreateCompatibleDC(NULL);
+
+ // Specify the ClearType in Windows XP or later
+ if (OS_IS_WINDOWS_NT(os->OsType) && GET_KETA(os->OsType, 100) >= 3)
+ {
+ font_quality = CLEARTYPE_NATURAL_QUALITY;
+ rotate = 3600;
+ }
+
+ if (MsIsVista())
+ {
+ dpi = GetDeviceCaps(hDC, LOGPIXELSY);
+ }
+ else
+ {
+ dpi = 96;
+ }
+
+ // Create a font
+ hFont = CreateFontA(-MulDiv(size, dpi, 72),
+ 0, rotate, rotate, (bold == false ? 500 : FW_BOLD),
+ italic, underline, strikeout, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, font_quality, DEFAULT_PITCH, name);
+
+ if (hFont == NULL)
+ {
+ // Failure
+ DeleteDC(hDC);
+ UnlockList(font_list);
+
+ return NULL;
+ }
+
+ CalcFontSize(hFont, &x, &y);
+
+ // Add to the table
+ f = ZeroMalloc(sizeof(FONT));
+ f->Bold = bold;
+ f->hFont = hFont;
+ f->Italic = italic;
+ f->Name = CopyStr(name);
+ f->Size = size;
+ f->StrikeOut = strikeout;
+ f->UnderLine = underline;
+ f->x = x;
+ f->y = y;
+
+ Insert(font_list, f);
+
+ DeleteDC(hDC);
+ }
+ UnlockList(font_list);
+
+ return hFont;
+}
+
+// Comparison of the font
+int CompareFont(void *p1, void *p2)
+{
+ FONT *f1, *f2;
+ UINT r;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(FONT **)p1;
+ f2 = *(FONT **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ r = StrCmpi(f1->Name, f2->Name);
+ if (r != 0)
+ {
+ return r;
+ }
+ else
+ {
+ if (f1->Bold > f2->Bold)
+ {
+ return 1;
+ }
+ else if (f1->Bold < f2->Bold)
+ {
+ return -1;
+ }
+ else if (f1->Italic > f2->Italic)
+ {
+ return 1;
+ }
+ else if (f1->Italic < f2->Italic)
+ {
+ return -1;
+ }
+ else if (f1->Size > f2->Size)
+ {
+ return 1;
+ }
+ else if (f1->Size < f2->Size)
+ {
+ return -1;
+ }
+ else if (f1->StrikeOut > f2->StrikeOut)
+ {
+ return 1;
+ }
+ else if (f1->StrikeOut < f2->StrikeOut)
+ {
+ return -1;
+ }
+ else if (f1->UnderLine > f2->UnderLine)
+ {
+ return 1;
+ }
+ else if (f1->UnderLine < f2->UnderLine)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+// Initialize the font
+void InitFont()
+{
+ if (font_list != NULL)
+ {
+ return;
+ }
+ font_list = NewList(CompareFont);
+}
+
+// Release the font
+void FreeFont()
+{
+ UINT i;
+ if (font_list == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < LIST_NUM(font_list);i++)
+ {
+ FONT *f = LIST_DATA(font_list, i);
+ Free(f->Name);
+ DeleteObject((HGDIOBJ)f->hFont);
+ Free(f);
+ }
+ ReleaseList(font_list);
+ font_list = NULL;
+}
+
+// Show a button to close the window
+void EnableClose(HWND hWnd)
+{
+ HMENU h;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ h = GetSystemMenu(hWnd, false);
+ EnableMenuItem(h, SC_CLOSE, MF_ENABLED);
+ DrawMenuBar(hWnd);
+}
+
+// Hide the button to close the window
+void DisableClose(HWND hWnd)
+{
+ HMENU h;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ h = GetSystemMenu(hWnd, false);
+ EnableMenuItem(h, SC_CLOSE, MF_GRAYED);
+ DrawMenuBar(hWnd);
+}
+
+// Move to the center of the parent window
+void CenterParent(HWND hWnd)
+{
+ RECT rp;
+ RECT r;
+ HWND hWndParent = GetParent(hWnd);
+ int win_x, win_y;
+ int x, y;
+
+ if (hWndParent == NULL || IsHide(hWndParent, 0) || IsIconic(hWndParent))
+ {
+ Center(hWnd);
+ return;
+ }
+
+ if (GetWindowRect(hWndParent, &rp) == false)
+ {
+ Center(hWnd);
+ return;
+ }
+
+ GetWindowRect(hWnd, &r);
+
+ win_x = r.right - r.left;
+ win_y = r.bottom - r.top;
+
+ x = (rp.right - rp.left - win_x) / 2 + rp.left;
+ y = (rp.bottom - rp.top - win_y) / 2 + rp.top;
+
+ x = MAX(x, 0);
+ y = MAX(y, 0);
+
+ SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
+}
+
+// Get the coordinates of the client region of the window
+void GetWindowClientRect(HWND hWnd, struct tagRECT *rect)
+{
+ RECT r1, r2;
+ HWND hParent;
+ WINDOWINFO info;
+ Zero(rect, sizeof(RECT));
+ // Validate arguments
+ if (hWnd == NULL || rect == NULL)
+ {
+ return;
+ }
+
+ hParent = GetParent(hWnd);
+ if (hParent == NULL)
+ {
+ return;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(WINDOWINFO);
+
+ if (GetWindowInfo(hParent, &info) == false)
+ {
+ return;
+ }
+
+ if (GetWindowRect(hWnd, &r1) == false ||
+ GetWindowRect(hParent, &r2) == false)
+ {
+ return;
+ }
+
+ rect->left = r1.left - r2.left - (info.rcClient.left - info.rcWindow.left);
+ rect->right = r1.right - r2.left - (info.rcClient.left - info.rcWindow.left);
+ rect->top = r1.top - r2.top - (info.rcClient.top - info.rcWindow.top);
+ rect->bottom = r1.bottom - r2.top - (info.rcClient.top - info.rcWindow.top);
+}
+
+// Move the window to the center
+void Center(HWND hWnd)
+{
+ RECT screen;
+ RECT win;
+ UINT x, y;
+ UINT win_x, win_y;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)
+ {
+ return;
+ }
+
+ GetWindowRect(hWnd, &win);
+ win_x = win.right - win.left;
+ win_y = win.bottom - win.top;
+
+ if (win_x < (UINT)(screen.right - screen.left))
+ {
+ x = (screen.right - screen.left - win_x) / 2;
+ }
+ else
+ {
+ x = 0;
+ }
+
+ if (win_y < (UINT)(screen.bottom - screen.top))
+ {
+ y = (screen.bottom - screen.top - win_y) / 2;
+ }
+ else
+ {
+ y = 0;
+ }
+
+ SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
+}
+
+// Move the window to the center 2
+void Center2(HWND hWnd)
+{
+ RECT screen;
+ RECT win;
+ UINT x, y;
+ UINT win_x, win_y;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)
+ {
+ return;
+ }
+
+ GetWindowRect(hWnd, &win);
+ win_x = win.right - win.left;
+ win_y = win.bottom - win.top;
+
+ if (win_x < (UINT)(screen.right - screen.left))
+ {
+ x = (screen.right - screen.left - win_x) / 2;
+ }
+ else
+ {
+ x = 0;
+ }
+
+ if (win_y < (UINT)(screen.bottom - screen.top))
+ {
+ y = (screen.bottom - screen.top - win_y) / 4;
+ }
+ else
+ {
+ y = 0;
+ }
+
+ SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
+}
+
+// Get the size of the monitor
+void GetMonitorSize(UINT *width, UINT *height)
+{
+ // Validate arguments
+ if (width == NULL || height == NULL)
+ {
+ return;
+ }
+
+ *width = GetSystemMetrics(SM_CXSCREEN);
+ *height = GetSystemMetrics(SM_CYSCREEN);
+}
+
+// Format the string in the window
+void FormatText(HWND hWnd, UINT id, ...)
+{
+ va_list args;
+ wchar_t *buf;
+ UINT size;
+ wchar_t *str;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ str = GetText(hWnd, id);
+ if (str == NULL)
+ {
+ return;
+ }
+
+ size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);
+ buf = MallocEx(size, true);
+
+ va_start(args, id);
+ UniFormatArgs(buf, size, str, args);
+
+ SetText(hWnd, id, buf);
+
+ Free(buf);
+
+ Free(str);
+ va_end(args);
+}
+void FormatTextA(HWND hWnd, UINT id, ...)
+{
+ va_list args;
+ char *buf;
+ UINT size;
+ char *str;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ str = GetTextA(hWnd, id);
+ if (str == NULL)
+ {
+ return;
+ }
+
+ size = MAX(StrSize(str) * 10, MAX_SIZE * 10);
+ buf = MallocEx(size, true);
+
+ va_start(args, id);
+ FormatArgs(buf, size, str, args);
+
+ SetTextA(hWnd, id, buf);
+
+ Free(buf);
+
+ Free(str);
+ va_end(args);
+}
+
+// Set a variable-length argument string to the window
+void SetTextEx(HWND hWnd, UINT id, wchar_t *str, ...)
+{
+ va_list args;
+ wchar_t *buf;
+ UINT size;
+ // Validate arguments
+ if (str == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);
+ buf = MallocEx(size, true);
+
+ va_start(args, str);
+ UniFormatArgs(buf, size, str, args);
+
+ SetText(hWnd, id, buf);
+
+ Free(buf);
+ va_end(args);
+}
+void SetTextExA(HWND hWnd, UINT id, char *str, ...)
+{
+ va_list args;
+ char *buf;
+ UINT size;
+ // Validate arguments
+ if (str == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ size = MAX(StrSize(str) * 10, MAX_SIZE * 10);
+ buf = MallocEx(size, true);
+
+ va_start(args, str);
+ FormatArgs(buf, size, str, args);
+
+ SetTextA(hWnd, id, buf);
+
+ Free(buf);
+ va_end(args);
+}
+
+// Show the variable-length message box
+UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...)
+{
+ va_list args;
+ wchar_t *buf;
+ UINT size;
+ UINT ret;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = L"MessageBox";
+ }
+
+ size = MAX(UniStrSize(msg) * 10, MAX_SIZE * 10);
+ buf = MallocEx(size, true);
+
+ va_start(args, msg);
+ UniFormatArgs(buf, size, msg, args);
+
+ ret = MsgBox(hWnd, flag, buf);
+ Free(buf);
+ va_end(args);
+
+ return ret;
+}
+
+// Show the message box
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg)
+{
+ UINT ret;
+ wchar_t *title;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = L"MessageBox";
+ }
+
+ if (title_bar != NULL)
+ {
+ title = CopyUniStr(title_bar);
+ }
+ else
+ {
+ title = CopyStrToUni(CEDAR_PRODUCT_STR);
+ }
+
+ if (hWnd)
+ {
+ // Raise the message box to top-level if the parent window is the top-level window
+ if (GetExStyle(hWnd, 0) & WS_EX_TOPMOST)
+ {
+ flag |= MB_SYSTEMMODAL;
+ }
+ }
+
+ ret = MessageBoxW(hWnd, msg, title, flag);
+
+ Free(title);
+
+ return ret;
+}
+
+// Create a dialog (internal)
+UINT DialogInternal(HWND hWnd, UINT id, DIALOG_PROC *proc, void *param)
+{
+ // Validate arguments
+ if (proc == NULL)
+ {
+ return 0;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Win9x
+ return (UINT)DialogBoxParam(hDll, MAKEINTRESOURCE(id), hWnd, (DLGPROC)proc, (LPARAM)param);
+ }
+ else
+ {
+ // WinNT
+ return (UINT)DialogBoxParamW(hDll, MAKEINTRESOURCEW(id), hWnd, (DLGPROC)proc, (LPARAM)param);
+ }
+}
+
+// Notice that the system configuration has been updated
+void NoticeSettingChange()
+{
+ PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);
+ DoEvents(NULL);
+}
+
+// Dialog box procedure managed by WinUi
+UINT DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, bool white_color)
+{
+ void *param;
+ HWND hWndParent;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ param = (void *)lParam;
+ SetParam(hWnd, param);
+
+ // Examine whether the parent window exists
+ hWndParent = GetParent(hWnd);
+ if (hWndParent == NULL || IsShow(hWndParent, 0) == false)
+ {
+ // Place in the center if parent does not exist
+ Center(hWnd);
+ }
+
+ if (UseAlpha)
+ {
+ UINT os_type = GetOsInfo()->OsType;
+ if (OS_IS_WINDOWS_NT(os_type) && GET_KETA(os_type, 100) >= 2)
+ {
+ bool (WINAPI *_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD);
+ HINSTANCE hInst;
+
+ hInst = LoadLibrary("user32.dll");
+ _SetLayeredWindowAttributes =
+ (bool (__stdcall *)(HWND,COLORREF,BYTE,DWORD))
+ GetProcAddress(hInst, "SetLayeredWindowAttributes");
+
+ if (_SetLayeredWindowAttributes != NULL)
+ {
+ // Only available on Windows 2000 or later
+ SetExStyle(hWnd, 0, WS_EX_LAYERED);
+ _SetLayeredWindowAttributes(hWnd, 0, AlphaValue * 255 / 100, LWA_ALPHA);
+ }
+ }
+ }
+
+ break;
+
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ if (white_color)
+ {
+ return (UINT)GetStockObject(WHITE_BRUSH);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Set the parameters of the dialog box
+void SetParam(HWND hWnd, void *param)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)param);
+}
+
+// Get the parameters of the dialog box
+void *GetParam(HWND hWnd)
+{
+ void *ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ ret = (void *)GetWindowLongPtr(hWnd, DWLP_USER);
+ return ret;
+}
+
+// Relieve the window from foreground
+void NoTop(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+}
+
+// Show the windows as foreground
+void Top(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+}
+
+// Hide the window
+void Hide(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsShow(hWnd, id))
+ {
+ ShowWindow(DlgItem(hWnd, id), SW_HIDE);
+ }
+}
+
+// Show the window
+void Show(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsHide(hWnd, id))
+ {
+ ShowWindow(DlgItem(hWnd, id), SW_SHOW);
+ }
+}
+
+// Change the display settings
+void SetShow(HWND hWnd, UINT id, bool b)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (b)
+ {
+ Show(hWnd, id);
+ }
+ else
+ {
+ Hide(hWnd, id);
+ }
+}
+
+// Get whether the window is shown
+bool IsShow(HWND hWnd, UINT id)
+{
+ return IsHide(hWnd, id) ? false : true;
+}
+
+// Get whether the window is hidden
+bool IsHide(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return true;
+ }
+
+ if (GetStyle(hWnd, id) & WS_VISIBLE)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Remove the window style
+void RemoveExStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetExStyle(hWnd, id);
+ if ((old & style) == 0)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old & ~style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Set the window style
+void SetExStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetExStyle(hWnd, id);
+ if (old & style)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old | style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Get the window style
+UINT GetExStyle(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return GetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE);
+}
+
+// Remove the window style
+void RemoveStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetStyle(hWnd, id);
+ if ((old & style) == 0)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old & ~style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Set the window style
+void SetStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetStyle(hWnd, id);
+ if (old & style)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old | style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Get the window style
+UINT GetStyle(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return GetWindowLong(DlgItem(hWnd, id), GWL_STYLE);
+}
+
+// Get the number of bytes of the text
+UINT GetTextSize(HWND hWnd, UINT id, bool unicode)
+{
+ UINT len;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ len = GetTextLen(hWnd, id, unicode);
+
+ return len + (unicode ? 2 : 1);
+}
+
+// Get the number of characters in the text
+UINT GetTextLen(HWND hWnd, UINT id, bool unicode)
+{
+ wchar_t *s;
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ s = GetText(hWnd, id);
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ if (unicode)
+ {
+ ret = UniStrLen(s);
+ }
+ else
+ {
+ char *tmp = CopyUniToStr(s);
+ ret = StrLen(tmp);
+ Free(tmp);
+ }
+
+ Free(s);
+
+ return ret;
+}
+
+// Check whether the text is blank
+bool IsEmpty(HWND hWnd, UINT id)
+{
+ bool ret;
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return true;
+ }
+
+ s = GetText(hWnd, id);
+
+ UniTrim(s);
+ if (UniStrLen(s) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(s);
+
+ return ret;
+}
+
+// Get the window class
+wchar_t *GetClass(HWND hWnd, UINT id)
+{
+ wchar_t tmp[MAX_SIZE];
+
+ if (MsIsNt() == false)
+ {
+ wchar_t *ret;
+ char *s;
+ s = GetClassA(hWnd, id);
+ ret = CopyStrToUni(s);
+ Free(s);
+ return ret;
+ }
+
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return CopyUniStr(L"");
+ }
+
+ GetClassNameW(DlgItem(hWnd, id), tmp, sizeof(tmp));
+
+ return UniCopyStr(tmp);
+}
+char *GetClassA(HWND hWnd, UINT id)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return CopyStr("");
+ }
+
+ GetClassName(DlgItem(hWnd, id), tmp, sizeof(tmp));
+
+ return CopyStr(tmp);
+}
+
+// Transmit a message to the control
+UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ if (MsIsNt())
+ {
+ return (UINT)SendMessageW(DlgItem(hWnd, id), msg, wParam, lParam);
+ }
+ else
+ {
+ return (UINT)SendMessageA(DlgItem(hWnd, id), msg, wParam, lParam);
+ }
+}
+
+// Move the cursor to the right edge of the text in the EDIT
+void SetCursorOnRight(HWND hWnd, UINT id)
+{
+ wchar_t *class_name;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ class_name = GetClass(hWnd, id);
+
+ if (class_name != NULL)
+ {
+ if (UniStrCmpi(class_name, L"edit") == 0)
+ {
+ wchar_t *str = GetText(hWnd, id);
+
+ if (str != NULL)
+ {
+ UINT len = UniStrLen(str);
+
+ SendMsg(hWnd, id, EM_SETSEL, len, len);
+
+ Free(str);
+ }
+ }
+ Free(class_name);
+ }
+}
+
+// Select entire the text in the EDIT
+void SelectEdit(HWND hWnd, UINT id)
+{
+ wchar_t *class_name;
+
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ class_name = GetClass(hWnd, id);
+
+ if (class_name != NULL)
+ {
+ if (UniStrCmpi(class_name, L"edit") == 0)
+ {
+ SendMsg(hWnd, id, EM_SETSEL, 0, -1);
+ }
+ Free(class_name);
+ }
+}
+
+// Deselect the text of EDIT
+void UnselectEdit(HWND hWnd, UINT id)
+{
+ wchar_t *class_name;
+
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ class_name = GetClass(hWnd, id);
+
+ if (class_name != NULL)
+ {
+ if (UniStrCmpi(class_name, L"edit") == 0)
+ {
+ SendMsg(hWnd, id, EM_SETSEL, -1, 0);
+ }
+ Free(class_name);
+ }
+}
+
+// Select all by setting the focus to the EDIT
+void FocusEx(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
+ {
+ return;
+ }
+
+ SelectEdit(hWnd, id);
+
+ Focus(hWnd, id);
+}
+
+// Get whether the specified window has focus
+bool IsFocus(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ if (GetFocus() == DlgItem(hWnd, id))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Set the focus
+void Focus(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
+ {
+ return;
+ }
+
+ SetFocus(DlgItem(hWnd, id));
+}
+
+// Set the value of the int type
+void SetInt(HWND hWnd, UINT id, UINT value)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ UniToStru(tmp, value);
+ SetText(hWnd, id, tmp);
+}
+void SetIntEx(HWND hWnd, UINT id, UINT value)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (value == 0)
+ {
+ // Leave blank in the case of 0
+ SetText(hWnd, id, L"");
+ }
+ else
+ {
+ SetInt(hWnd, id, value);
+ }
+}
+
+// Get the value of the int type
+UINT GetInt(HWND hWnd, UINT id)
+{
+ wchar_t *s;
+ UINT ret;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ s = GetText(hWnd, id);
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ ret = UniToInt(s);
+ Free(s);
+
+ return ret;
+}
+
+// Update the window appearance
+void Refresh(HWND hWnd)
+{
+ HWND parent;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ DoEvents(hWnd);
+ UpdateWindow(hWnd);
+ DoEvents(hWnd);
+
+ parent = GetParent(hWnd);
+ if (parent != NULL)
+ {
+ Refresh(parent);
+ }
+}
+
+// Handle the event
+void DoEvents(HWND hWnd)
+{
+ MSG msg;
+
+ if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ UpdateWindow(hWnd);
+
+ if (hWnd)
+ {
+ DoEvents(NULL);
+ }
+}
+
+// Close the window
+void Close(HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+}
+
+// Disable the window
+void Disable(HWND hWnd, UINT id)
+{
+ SetEnable(hWnd, id, false);
+}
+
+// Enable the window
+void Enable(HWND hWnd, UINT id)
+{
+ SetEnable(hWnd, id, true);
+}
+
+// Set the enabled state of a window
+void SetEnable(HWND hWnd, UINT id, bool b)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (b == false)
+ {
+ if (IsEnable(hWnd, id))
+ {
+ if (id != 0 && IsFocus(hWnd, id))
+ {
+ Focus(hWnd, IDCANCEL);
+ Focus(hWnd, IDOK);
+ }
+ EnableWindow(DlgItem(hWnd, id), false);
+ Refresh(DlgItem(hWnd, id));
+ }
+ }
+ else
+ {
+ if (IsDisable(hWnd, id))
+ {
+ EnableWindow(DlgItem(hWnd, id), true);
+ Refresh(DlgItem(hWnd, id));
+ }
+ }
+}
+
+// Examine whether the window is disabled
+bool IsDisable(HWND hWnd, UINT id)
+{
+ return IsEnable(hWnd, id) ? false : true;
+}
+
+// Examine whether the window is enabled
+bool IsEnable(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ return IsWindowEnabled(DlgItem(hWnd, id));
+}
+
+static LOCK *winui_debug_lock = NULL;
+
+// Initialize the debug function
+void WinUiDebugInit()
+{
+ winui_debug_lock = NewLock();
+}
+
+// Release the debug function
+void WinUiDebugFree()
+{
+ DeleteLock(winui_debug_lock);
+}
+
+// Write a string to the debug file
+void WinUiDebug(wchar_t *str)
+{
+ wchar_t tmp[1024];
+ char dtstr[256];
+ char *buf;
+ wchar_t exename[MAX_PATH];
+ UINT tid;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ tid = GetCurrentThreadId();
+
+ GetExeNameW(exename, sizeof(exename));
+ GetFileNameFromFilePathW(exename, sizeof(exename), exename);
+
+ GetDateTimeStrMilli64(dtstr, sizeof(dtstr), LocalTime64());
+
+ UniFormat(tmp, sizeof(tmp), L"[%S] (%s:%u) %s\r\n", dtstr, exename, tid, str);
+
+ buf = CopyUniToUtf(tmp);
+
+ Lock(winui_debug_lock);
+ {
+ IO *o = FileOpenEx(WINUI_DEBUG_TEXT, true, true);
+ if (o == NULL)
+ {
+ o = FileCreate(WINUI_DEBUG_TEXT);
+ }
+
+ if (o != NULL)
+ {
+ UINT size = FileSize(o);
+
+ FileSeek(o, FILE_BEGIN, size);
+
+ FileWrite(o, buf, StrLen(buf));
+ FileFlush(o);
+
+ FileClose(o);
+ }
+ }
+ Unlock(winui_debug_lock);
+
+ Free(buf);
+}
+
+// If the control protrude by large font size, adjust into appropriate size
+void AdjustFontSize(HWND hWnd, UINT id)
+{
+ char class_name[MAX_PATH];
+ UINT style;
+ UINT format = 0;
+ HFONT current_font;
+ FONT font;
+ wchar_t *text;
+ RECT rect;
+ UINT width, height;
+ HFONT new_font = NULL;
+ UINT old_font_size;
+ UINT style1;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ hWnd = DlgItem(hWnd, id);
+
+ if (GetClassNameA(hWnd, class_name, sizeof(class_name)) == 0)
+ {
+ return;
+ }
+
+ if (StrCmpi(class_name, "static") != 0)
+ {
+ return;
+ }
+
+ style = GetStyle(hWnd, 0);
+
+ if ((style & SS_ENDELLIPSIS) || (style & SS_PATHELLIPSIS))
+ {
+ return;
+ }
+
+ style1 = style & 0x0F;
+
+ // Create a format for DrawText
+ if (style1 == SS_RIGHT)
+ {
+ // Right justification
+ format |= DT_RIGHT;
+ }
+ else if (style1 == SS_CENTER)
+ {
+ // Center justification
+ format |= DT_CENTER;
+ }
+ else if (style1 == SS_LEFT)
+ {
+ // Left justification
+ format |= DT_LEFT;
+ }
+ else
+ {
+ // Others
+ return;
+ }
+
+ if (style & DT_NOPREFIX)
+ {
+ // Without prefix
+ format |= DT_NOPREFIX;
+ }
+
+ // Get the font parameters currently set
+ current_font = (HFONT)SendMessageA(hWnd, WM_GETFONT, 0, 0);
+ if (current_font == NULL)
+ {
+ return;
+ }
+
+ Zero(&font, sizeof(font));
+ if (GetFontParam(current_font, &font) == false)
+ {
+ return;
+ }
+
+ // Get the size of the static area
+ Zero(&rect, sizeof(rect));
+ if (GetWindowRect(hWnd, &rect) == false)
+ {
+ return;
+ }
+
+ // Get the text that is currently set
+ text = GetText(hWnd, 0);
+ if (text == NULL)
+ {
+ return;
+ }
+
+ if (IsEmptyUniStr(text))
+ {
+ Free(text);
+ return;
+ }
+
+ width = GET_ABS(rect.right - rect.left);
+ height = GET_ABS(rect.bottom - rect.top);
+
+ new_font = NULL;
+ old_font_size = font.Size;
+
+ // Try to gradually reduce the font size until drawing succeeds
+ while (font.Size != 0)
+ {
+ // Drawing test
+ bool aborted = false;
+
+ if (IsFontFitInRect(&font, width, height, text, format, &aborted))
+ {
+ // Drawing success
+ if (old_font_size != font.Size)
+ {
+ // Font size is changed
+ new_font = GetFont(font.Name, font.Size, font.Bold, font.Italic, font.UnderLine, font.StrikeOut);
+ }
+ break;
+ }
+ else
+ {
+ if (aborted)
+ {
+ // Fatal error
+ break;
+ }
+ }
+
+ font.Size--;
+
+ if (font.Size == 1)
+ {
+ // Not supposed to become a font size like this. Fatal error
+ break;
+ }
+ }
+
+ Free(text);
+
+ if (new_font != NULL)
+ {
+ // Change the font size
+ SetFontEx(hWnd, 0, new_font, true);
+ }
+}
+
+// Check whether the specified string can be drawn in the specified area with the specified font
+bool IsFontFitInRect(struct FONT *f, UINT width, UINT height, wchar_t *text, UINT format, bool *aborted)
+{
+ RECT r;
+ int i;
+ bool dummy_bool;
+ UINT new_height;
+ HFONT hCreatedFont, hOldFont;
+ // Validate arguments
+ if (f == NULL || text == NULL)
+ {
+ return false;
+ }
+ if (aborted == NULL)
+ {
+ aborted = &dummy_bool;
+ }
+
+ format |= DT_CALCRECT | DT_WORDBREAK;
+
+ *aborted = false;
+
+ // Create a font
+ hCreatedFont = GetFont(f->Name, f->Size, f->Bold, f->Italic, f->UnderLine, f->StrikeOut);
+ if (hCreatedFont == NULL)
+ {
+ *aborted = true;
+ return false;
+ }
+
+ Lock(lock_common_dc);
+ {
+ hOldFont = SelectObject(hCommonDC, hCreatedFont);
+
+ Zero(&r, sizeof(r));
+ r.left = r.top = 0;
+ r.right = width;
+ r.bottom = height;
+
+ if (MsIsNt())
+ {
+ i = DrawTextW(hCommonDC, text, -1, &r, format);
+ }
+ else
+ {
+ char *a = CopyUniToStr(text);
+
+ i = DrawTextA(hCommonDC, a, -1, &r, format);
+
+ Free(a);
+ }
+
+ SelectObject(hCommonDC, hOldFont);
+ }
+ Unlock(lock_common_dc);
+
+ if (i == 0)
+ {
+ *aborted = true;
+ return false;
+ }
+
+ new_height = GET_ABS(r.bottom - r.top);
+
+ if (new_height > height)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Set a text string
+void SetText(HWND hWnd, UINT id, wchar_t *str)
+{
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ SetTextInner(hWnd, id, str);
+}
+void SetTextInner(HWND hWnd, UINT id, wchar_t *str)
+{
+ wchar_t *old;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ // Get the old string
+ old = GetText(hWnd, id);
+ if (UniStrCmp(str, old) == 0)
+ {
+ // Identity
+ Free(old);
+ return;
+ }
+
+ Free(old);
+
+ if (MsIsNt())
+ {
+ SetWindowTextW(DlgItem(hWnd, id), str);
+ }
+ else
+ {
+ char *tmp = CopyUniToStr(str);
+
+ if (MsIsNt() == false && StrLen(tmp) >= 32000)
+ {
+ // Truncate to less than 32k
+ tmp[32000] = 0;
+ }
+
+ SetWindowTextA(DlgItem(hWnd, id), tmp);
+ Free(tmp);
+ }
+
+ AdjustFontSize(hWnd, id);
+
+ if (id != 0)
+ {
+ Refresh(DlgItem(hWnd, id));
+ }
+}
+void SetTextA(HWND hWnd, UINT id, char *str)
+{
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ s = CopyStrToUni(str);
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SetText(hWnd, id, s);
+
+ Free(s);
+}
+
+// Get the text string to the buffer
+bool GetTxt(HWND hWnd, UINT id, wchar_t *str, UINT size)
+{
+ wchar_t *s;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ s = GetText(hWnd, id);
+ if (s == NULL)
+ {
+ UniStrCpy(str, size, L"");
+ return false;
+ }
+
+ UniStrCpy(str, size, s);
+ Free(s);
+
+ return true;
+}
+bool GetTxtA(HWND hWnd, UINT id, char *str, UINT size)
+{
+ char *s;
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ s = GetTextA(hWnd, id);
+ if (s == NULL)
+ {
+ StrCpy(str, size, "");
+ return false;
+ }
+
+ StrCpy(str, size, s);
+ Free(s);
+
+ return true;
+}
+
+// Get the text string
+wchar_t *GetText(HWND hWnd, UINT id)
+{
+ wchar_t *ret;
+ UINT size, len;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = GetTextA(hWnd, id);
+ ret = CopyStrToUni(s);
+ Free(s);
+
+ return ret;
+ }
+
+ len = GetWindowTextLengthW(DlgItem(hWnd, id));
+ if (len == 0)
+ {
+ return CopyUniStr(L"");
+ }
+
+ size = (len + 1) * 2;
+ ret = ZeroMallocEx(size, true);
+
+ GetWindowTextW(DlgItem(hWnd, id), ret, size);
+
+ return ret;
+}
+char *GetTextA(HWND hWnd, UINT id)
+{
+ char *ret;
+ UINT size, len;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ len = GetWindowTextLengthA(DlgItem(hWnd, id));
+ if (len == 0)
+ {
+ return CopyStr("");
+ }
+
+ size = len + 1;
+ ret = ZeroMallocEx(size, true);
+
+ GetWindowTextA(DlgItem(hWnd, id), ret, size);
+
+ return ret;
+}
+
+// Get the item in the dialog
+HWND DlgItem(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ if (id == 0)
+ {
+ return hWnd;
+ }
+ else
+ {
+ return GetDlgItem(hWnd, id);
+ }
+}
+
+// Set the title
+void SetWinUiTitle(wchar_t *title)
+{
+ // Validate arguments
+ if (title == NULL)
+ {
+ return;
+ }
+
+ Free(title_bar);
+ title_bar = CopyUniStr(title);
+}
+
+// Initialize the WinUi
+void InitWinUi(wchar_t *software_name, char *font, UINT fontsize)
+{
+ if (tls_current_wizard == 0xffffffff)
+ {
+ tls_current_wizard = TlsAlloc();
+ }
+
+ if ((init_winui_counter++) != 0)
+ {
+ return;
+ }
+
+ if (hDll != NULL)
+ {
+ return;
+ }
+
+ WinUiDebugInit();
+
+ if (MayaquaIsMinimalMode() == false)
+ {
+ if (Is64())
+ {
+ hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName());
+ }
+ else
+ {
+ hDll = MsLoadLibrary(MsGetPenCoreDllFileName());
+ }
+
+ if (hDll == NULL)
+ {
+ Alert(PENCORE_DLL_NAME " not found. "CEDAR_PRODUCT_STR " VPN couldn't start.\r\n\r\n"
+ "Please reinstall all files with "CEDAR_PRODUCT_STR " VPN Installer.",
+ NULL);
+ exit(0);
+ }
+ }
+ else
+ {
+ hDll = LoadLibrary(MsGetExeFileName());
+
+ if (hDll == NULL)
+ {
+ Alert("MsLoadLibrary() Error.",
+ NULL);
+ exit(0);
+ }
+ }
+
+ if (software_name != NULL)
+ {
+ title_bar = CopyUniStr(software_name);
+ }
+ else
+ {
+ title_bar = CopyUniStr(CEDAR_PRODUCT_STR_W L" VPN");
+ }
+
+ if (font != NULL)
+ {
+ font_name = CopyStr(font);
+ }
+ else
+ {
+ font_name = CopyStr(_SS("DEFAULT_FONT"));
+ }
+
+ if (MsIsWindows7())
+ {
+ char *win7_font = _SS("DEFAULT_FONT_WIN7");
+
+ if (IsEmptyStr(win7_font) == false)
+ {
+ Free(font_name);
+ font_name = CopyStr(win7_font);
+ }
+
+ if (GetTextScalingFactor() >= 1.44)
+ {
+ // Use a substitute font in the case of high-DPI in Windows 7 and later
+ char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
+
+ if (IsEmptyStr(alternative_font) == false)
+ {
+ Free(font_name);
+ font_name = CopyStr(alternative_font);
+ }
+ }
+ }
+
+ if (fontsize != 0)
+ {
+ font_size = fontsize;
+ }
+ else
+ {
+ font_size = _II("DEFAULT_FONT_SIZE");
+ if (font_size == 0)
+ {
+ font_size = 9;
+ }
+ }
+
+ lock_common_dc = NewLock();
+
+ hCommonDC = CreateCompatibleDC(NULL);
+
+ InitIconCache();
+
+ InitFont();
+
+ InitImageList();
+}
+
+// Release the WinUi
+void FreeWinUi()
+{
+ if ((--init_winui_counter) != 0)
+ {
+ return;
+ }
+
+ if (hDll == NULL)
+ {
+ return;
+ }
+
+ FreeImageList();
+
+ FreeFont();
+
+ FreeIconCache();
+
+ FreeLibrary(hDll);
+ hDll = NULL;
+
+ Free(title_bar);
+ title_bar = NULL;
+
+ Free(font_name);
+ font_name = NULL;
+
+ WinUiDebugFree();
+
+ if (hCommonDC != NULL)
+ {
+ DeleteDC(hCommonDC);
+ hCommonDC = NULL;
+ }
+
+ DeleteLock(lock_common_dc);
+ lock_common_dc = NULL;
+}
+
+#endif // WIN32
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/WinUi.h b/src/Cedar/WinUi.h
new file mode 100644
index 00000000..06bd5f77
--- /dev/null
+++ b/src/Cedar/WinUi.h
@@ -0,0 +1,906 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WinUi.h
+// User interface code for Win32
+
+#ifdef OS_WIN32
+
+#define WINUI_DEBUG_TEXT "@winui_debug.txt"
+
+#define LV_INSERT_RESET_ALL_ITEM_MIN 500
+
+#define WINUI_PASSWORD_NULL_USERNAME "NULL"
+
+#define WINUI_DEFAULT_DIALOG_UNIT_X 7
+#define WINUI_DEFAULT_DIALOG_UNIT_Y 12
+
+// Make available the types for Windows even if windows.h is not included
+#ifndef _WINDEF_
+
+typedef void *HWND;
+typedef void *HFONT;
+typedef void *HICON;
+typedef void *HMENU;
+typedef UINT_PTR WPARAM;
+typedef LONG_PTR LPARAM;
+typedef void *HINSTANCE;
+
+#endif // _WINDEF_
+
+
+// Constants
+#define FREE_REGKEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN Client\\Free Edition Info"
+#define ONCE_MSG_REGKEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Common"
+#define ONCE_MSG_REGVALUE "HideMessage_%u"
+
+#define NICINFO_AUTOCLOSE_TIME_1 (20 * 1000)
+#define NICINFO_AUTOCLOSE_TIME_2 1800
+
+extern bool UseAlpha;
+extern UINT AlphaValue;
+
+
+// Minimum font size
+#define WINUI_MIN_FONTSIZE 5
+
+
+// Macro
+#define DIALOG DIALOGEX(false)
+#define DIALOG_WHITE DIALOGEX(true)
+#define DIALOGEX(white) \
+ void *param = GetParam(hWnd); \
+ { \
+ UINT ret; \
+ ret = DlgProc(hWnd, msg, wParam, lParam, white); \
+ if (ret != 0) return ret; \
+ }
+
+typedef UINT (__stdcall DIALOG_PROC)(HWND, UINT, WPARAM, LPARAM);
+
+typedef UINT (WINUI_DIALOG_PROC)(HWND, UINT, WPARAM, LPARAM, void *);
+
+typedef UINT (WINUI_WIZARD_PROC)(HWND, UINT, WPARAM, LPARAM, WIZARD *, WIZARD_PAGE *, void *);
+
+
+// Special message to be used for this wizard
+#define WM_WIZ_BASE (WM_APP + 201)
+#define WM_WIZ_NEXT (WM_WIZ_BASE + 0)
+#define WM_WIZ_BACK (WM_WIZ_BASE + 1)
+#define WM_WIZ_CLOSE (WM_WIZ_BASE + 2)
+#define WM_WIZ_SHOW (WM_WIZ_BASE + 3)
+#define WM_WIZ_HIDE (WM_WIZ_BASE + 4)
+
+
+// Secure operation contents
+#define WINUI_SECURE_ENUM_OBJECTS 1 // Enumerate objects
+#define WINUI_SECURE_WRITE_DATA 2 // Write the data
+#define WINUI_SECURE_READ_DATA 3 // Read the data
+#define WINUI_SECURE_WRITE_CERT 4 // Write the certificate
+#define WINUI_SECURE_READ_CERT 5 // Read the certificate
+#define WINUI_SECURE_WRITE_KEY 6 // Write the secret key
+#define WINUI_SECURE_SIGN_WITH_KEY 7 // Signature by the private key
+#define WINUI_SECURE_DELETE_OBJECT 8 // Delete the object
+#define WINUI_SECURE_DELETE_CERT 9 // Delete the certificate
+#define WINUI_SECURE_DELETE_KEY 10 // Delete the private key
+#define WINUI_SECURE_DELETE_DATA 11 // Delete the Data
+
+// Secure operation structure
+typedef struct WINUI_SECURE_BATCH
+{
+ UINT Type; // Type of operation
+ char *Name; // Name
+ bool Private; // Private mode
+ BUF *InputData; // Input data
+ BUF *OutputData; // Output data
+ X *InputX; // Input certificate
+ X *OutputX; // Output certificate
+ K *InputK; // Input secret key
+ LIST *EnumList; // Enumerated list
+ UCHAR OutputSign[128]; // Output signature
+ bool Succeed; // Success flag
+} WINUI_SECURE_BATCH;
+
+// Status window
+typedef struct STATUS_WINDOW
+{
+ HWND hWnd;
+ THREAD *Thread;
+} STATUS_WINDOW;
+
+// Batch processing items
+typedef struct LVB_ITEM
+{
+ UINT NumStrings; // The number of strings
+ wchar_t **Strings; // String buffer
+ UINT Image; // Image number
+ void *Param; // Parameters
+} LVB_ITEM;
+
+// LV insertion batch process
+typedef struct LVB
+{
+ LIST *ItemList; // Item list
+} LVB;
+
+
+#ifdef CreateWindow
+
+// Internal code
+
+// Font
+typedef struct FONT
+{
+ UINT Size; // Size
+ bool Bold; // Bold type
+ bool Italic; // Italic type
+ bool UnderLine; // Underline
+ bool StrikeOut; // Strike through
+ char *Name; // Font name
+ HFONT hFont; // Font
+ UINT x, y; // Font size
+} FONT;
+
+// Font cache list
+static LIST *font_list = NULL;
+
+// Dialog related
+typedef struct DIALOG_PARAM
+{
+ bool white;
+ void *param;
+ WINUI_DIALOG_PROC *proc;
+ bool meiryo;
+ LIST *BitmapList;
+
+ WIZARD *wizard;
+ WIZARD_PAGE *wizard_page;
+ WINUI_WIZARD_PROC *wizard_proc;
+} DIALOG_PARAM;
+
+// Secure device window related
+typedef struct SECURE_DEVICE_WINDOW
+{
+ WINUI_SECURE_BATCH *batch;
+ UINT num_batch;
+ UINT device_id;
+ struct SECURE_DEVICE_THREAD *p;
+ char *default_pin;
+ UINT BitmapId;
+} SECURE_DEVICE_WINDOW;
+
+// Thread
+typedef struct SECURE_DEVICE_THREAD
+{
+ SECURE_DEVICE_WINDOW *w;
+ HWND hWnd;
+ bool Succeed;
+ wchar_t *ErrorMessage;
+ char *pin;
+} SECURE_DEVICE_THREAD;
+
+void StartSecureDevice(HWND hWnd, SECURE_DEVICE_WINDOW *w);
+
+// Passphrase
+typedef struct PASSPHRASE_DLG
+{
+ char pass[MAX_SIZE];
+ BUF *buf;
+ bool p12;
+} PASSPHRASE_DLG;
+
+void PassphraseDlgProcCommand(HWND hWnd, PASSPHRASE_DLG *p);
+
+// Status window
+typedef struct STATUS_WINDOW_PARAM
+{
+ HWND hWnd;
+ SOCK *Sock;
+ THREAD *Thread;
+ wchar_t AccountName[MAX_ACCOUNT_NAME_LEN + 1];
+} STATUS_WINDOW_PARAM;
+
+// Certificate display dialog
+typedef struct CERT_DLG
+{
+ X *x, *issuer_x;
+ bool ManagerMode;
+} CERT_DLG;
+
+
+typedef struct IMAGELIST_ICON
+{
+ UINT id;
+ HICON hSmallImage;
+ HICON hLargeImage;
+ UINT Index;
+} IMAGELIST_ICON;
+
+typedef struct SEARCH_WINDOW_PARAM
+{
+ wchar_t *caption;
+ HWND hWndFound;
+} SEARCH_WINDOW_PARAM;
+
+// Remote connection screen setting
+typedef struct WINUI_REMOTE
+{
+ bool flag1;
+ char *RegKeyName; // Registry key name
+ UINT Icon; // Icon
+ wchar_t *Caption; // Caption
+ wchar_t *Title; // Title
+ char *Hostname; // Host name
+ char *DefaultHostname; // Default host name
+ LIST *CandidateList; // Candidate list
+} WINUI_REMOTE;
+
+void InitImageList();
+void FreeImageList();
+IMAGELIST_ICON *LoadIconForImageList(UINT id);
+int CompareImageListIcon(void *p1, void *p2);
+BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam);
+void PrintCertInfo(HWND hWnd, CERT_DLG *p);
+void CertDlgUpdate(HWND hWnd, CERT_DLG *p);
+bool CALLBACK SearchWindowEnumProc(HWND hWnd, LPARAM lParam);
+UINT RemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void RemoteDlgInit(HWND hWnd, WINUI_REMOTE *r);
+void RemoteDlgRefresh(HWND hWnd, WINUI_REMOTE *r);
+void RemoteDlgOnOk(HWND hWnd, WINUI_REMOTE *r);
+int CALLBACK LvSortProc(LPARAM param1, LPARAM param2, LPARAM sort_param);
+
+// Icon cache
+typedef struct ICON_CACHE
+{
+ UINT id;
+ bool small_icon;
+ HICON hIcon;
+} ICON_CACHE;
+
+static LIST *icon_cache_list = NULL;
+
+// Sort related
+typedef struct WINUI_LV_SORT
+{
+ HWND hWnd;
+ UINT id;
+ UINT subitem;
+ bool desc;
+ bool numeric;
+} WINUI_LV_SORT;
+
+// Version information
+typedef struct WINUI_ABOUT
+{
+ CEDAR *Cedar;
+ wchar_t *ProductName;
+ UINT Bitmap;
+ WINUI_UPDATE *Update;
+} WINUI_ABOUT;
+
+UINT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void AboutDlgInit(HWND hWnd, WINUI_ABOUT *a);
+
+typedef struct WIN9X_REBOOT_DLG
+{
+ UINT64 StartTime;
+ UINT TotalTime;
+} WIN9X_REBOOT_DLG;
+
+#define LED_WIDTH 96
+#define LED_HEIGHT 16
+#define LED_FORCE_UPDATE 60000
+
+// LED
+struct LED
+{
+ HDC hDC;
+ HBITMAP hBM;
+ void *Buf;
+ UCHAR px[LED_WIDTH][LED_HEIGHT];
+ bool Updated;
+ UINT64 LastUpdated;
+};
+
+void LedDrawString(LED *d, char *str, HFONT f);
+void LedDrawRect(LED *d);
+void LedMainDraw(LED *d, HANDLE h);
+void LedSpecial(LED *d, HANDLE h, UINT n);
+
+
+// STRING
+typedef struct STRING_DLG
+{
+ wchar_t String[MAX_SIZE];
+ wchar_t *Title;
+ wchar_t *Info;
+ UINT Icon;
+ bool AllowEmpty;
+ bool AllowUnsafe;
+} STRING_DLG;
+
+void StringDlgInit(HWND hWnd, STRING_DLG *s);
+void StringDlgUpdate(HWND hWnd, STRING_DLG *s);
+
+// PIN code is cached for five minutes
+#define WINUI_SECUREDEVICE_PIN_CACHE_TIME (5 * 60 * 1000)
+extern char cached_pin_code[MAX_SIZE];
+extern UINT64 cached_pin_code_expires;
+
+// TCP connection dialog related
+typedef struct WINCONNECT_DLG_DATA
+{
+ wchar_t *caption;
+ wchar_t *info;
+ UINT icon_id;
+ UINT timeout;
+ char *hostname;
+ UINT port;
+ bool cancel;
+ SOCK *ret_sock;
+ THREAD *thread;
+ HWND hWnd;
+ char nat_t_svc_name[MAX_SIZE];
+ UINT nat_t_error_code;
+ bool try_start_ssl;
+ bool ssl_no_tls;
+} WINCONNECT_DLG_DATA;
+
+HBITMAP ResizeBitmap(HBITMAP hSrc, UINT src_x, UINT src_y, UINT dst_x, UINT dst_y);
+
+#endif // WINUI_C
+
+// Kakushi
+typedef struct KAKUSHI
+{
+ HWND hWnd;
+ THREAD *Thread;
+ volatile bool Halt;
+ UINT64 StartTick, Span;
+} KAKUSHI;
+
+// The information screen about the free version
+typedef struct FREEINFO
+{
+ char ServerName[MAX_SERVER_STR_LEN + 1];
+ HWND hWnd;
+ THREAD *Thread;
+ EVENT *Event;
+} FREEINFO;
+
+// Message
+typedef struct ONCEMSG_DLG
+{
+ UINT Icon;
+ wchar_t *Title;
+ wchar_t *Message;
+ bool ShowCheckbox;
+ bool Checked;
+ UINT MessageHash;
+ bool *halt;
+} ONCEMSG_DLG;
+
+// Definition of bad process
+typedef struct BAD_PROCESS
+{
+ char *ExeName;
+ char *Title;
+} BAD_PROCESS;
+
+#ifdef WINUI_C
+
+// Process name list of incompatible anti-virus software
+static BAD_PROCESS bad_processes[] =
+{
+ {"nod32krn.exe", "NOD32 Antivirus",},
+};
+
+static UINT num_bad_processes = sizeof(bad_processes) / sizeof(bad_processes[0]);
+
+#endif // WINUI_C
+
+// Page in the wizard
+struct WIZARD_PAGE
+{
+ UINT Id;
+ UINT Index;
+ WINUI_WIZARD_PROC *Proc;
+ wchar_t *Title;
+ WIZARD *Wizard;
+
+ struct DIALOG_PARAM *DialogParam;
+ HWND hWndPage;
+ bool EnableNext;
+ bool EnableBack;
+ bool EnableClose;
+ bool IsFinish;
+};
+
+// Wizard
+struct WIZARD
+{
+ UINT Icon;
+ HWND hWndParent;
+ LIST *Pages;
+ void *Param;
+ UINT Bitmap;
+ wchar_t *Caption;
+ wchar_t *CloseConfirmMsg;
+ bool IsAreoStyle;
+
+ HWND hWndWizard;
+ bool SetCenterFlag;
+ bool ReplaceWindowProcFlag;
+ void *OriginalWindowProc;
+};
+
+// Update notification
+struct WINUI_UPDATE
+{
+ wchar_t SoftwareTitle[MAX_SIZE];
+ char SoftwareName[MAX_SIZE];
+ UINT64 CurrentDate;
+ UINT CurrentBuild;
+ UINT CurrentVer;
+ char ClientId[128];
+ char RegKey[MAX_PATH];
+ UPDATE_CLIENT *UpdateClient;
+};
+
+// Update notification parameters
+struct WINUI_UPDATE_DLG_PARAM
+{
+ WINUI_UPDATE *Update;
+ UINT LatestBuild;
+ UINT64 LatestDate;
+ char *LatestVer;
+ char *Url;
+ volatile bool *halt_flag;
+ bool IsInConfigDialog;
+};
+
+// Registry key to save the update notification settings
+#define WINUI_UPDATE_REGKEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Check Update\\%s"
+
+
+// Function prototype
+void InitWinUi(wchar_t *software_name, char *font, UINT fontsize);
+void SetWinUiTitle(wchar_t *title);
+void FreeWinUi();
+
+WINUI_UPDATE *InitUpdateUi(wchar_t *title, char *name, char *family_name, UINT64 current_date, UINT current_build, UINT current_ver, char *client_id);
+void FreeUpdateUi(WINUI_UPDATE *u);
+void LoadUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s);
+void SaveUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s);
+void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param);
+UINT UpdateNoticeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool ConfigUpdateUi(WINUI_UPDATE *u, HWND hWnd);
+UINT UpdateConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+
+bool IsThisProcessForeground();
+HWND DlgItem(HWND hWnd, UINT id);
+void SetText(HWND hWnd, UINT id, wchar_t *str);
+void SetTextInner(HWND hWnd, UINT id, wchar_t *str);
+void SetTextA(HWND hWnd, UINT id, char *str);
+wchar_t *GetText(HWND hWnd, UINT id);
+char *GetTextA(HWND hWnd, UINT id);
+bool GetTxt(HWND hWnd, UINT id, wchar_t *str, UINT size);
+bool GetTxtA(HWND hWnd, UINT id, char *str, UINT size);
+bool IsEnable(HWND hWnd, UINT id);
+bool IsDisable(HWND hWnd, UINT id);
+void Enable(HWND hWnd, UINT id);
+void Disable(HWND hWnd, UINT id);
+void SetEnable(HWND hWnd, UINT id, bool b);
+void Close(HWND hWnd);
+void DoEvents(HWND hWnd);
+void Refresh(HWND hWnd);
+UINT GetInt(HWND hWnd, UINT id);
+void SetInt(HWND hWnd, UINT id, UINT value);
+void SetIntEx(HWND hWnd, UINT id, UINT value);
+void Focus(HWND hWnd, UINT id);
+void FocusEx(HWND hWnd, UINT id);
+bool IsFocus(HWND hWnd, UINT id);
+wchar_t *GetClass(HWND hWnd, UINT id);
+char *GetClassA(HWND hWnd, UINT id);
+void SelectEdit(HWND hWnd, UINT id);
+void SetCursorOnRight(HWND hWnd, UINT id);
+void UnselectEdit(HWND hWnd, UINT id);
+UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam);
+bool IsEmpty(HWND hWnd, UINT id);
+UINT GetTextLen(HWND hWnd, UINT id, bool unicode);
+UINT GetTextSize(HWND hWnd, UINT id, bool unicode);
+UINT GetStyle(HWND hWnd, UINT id);
+void SetStyle(HWND hWnd, UINT id, UINT style);
+void RemoveStyle(HWND hWnd, UINT id, UINT style);
+UINT GetExStyle(HWND hWnd, UINT id);
+void SetExStyle(HWND hWnd, UINT id, UINT style);
+void RemoveExStyle(HWND hWnd, UINT id, UINT style);
+void Hide(HWND hWnd, UINT id);
+void Show(HWND hWnd, UINT id);
+void SetShow(HWND hWnd, UINT id, bool b);
+bool IsHide(HWND hWnd, UINT id);
+bool IsShow(HWND hWnd, UINT id);
+void Top(HWND hWnd);
+void NoTop(HWND hWnd);
+void *GetParam(HWND hWnd);
+void SetParam(HWND hWnd, void *param);
+UINT DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, bool white_color);
+void NoticeSettingChange();
+void UiTest();
+UINT DialogInternal(HWND hWnd, UINT id, DIALOG_PROC *proc, void *param);
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg);
+UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...);
+void SetTextEx(HWND hWnd, UINT id, wchar_t *str, ...);
+void SetTextExA(HWND hWnd, UINT id, char *str, ...);
+void FormatText(HWND hWnd, UINT id, ...);
+void FormatTextA(HWND hWnd, UINT id, ...);
+void Center(HWND hWnd);
+void Center2(HWND hWnd);
+void GetWindowClientRect(HWND hWnd, struct tagRECT *rect);
+void CenterParent(HWND hWnd);
+void GetMonitorSize(UINT *width, UINT *height);
+void DisableClose(HWND hWnd);
+void EnableClose(HWND hWnd);
+void InitFont();
+void FreeFont();
+int CompareFont(void *p1, void *p2);
+HFONT GetFont(char *name, UINT size, bool bold, bool italic, bool underline, bool strikeout);
+double GetTextScalingFactor();
+bool CalcFontSize(HFONT hFont, UINT *x, UINT *y);
+bool GetFontSize(HFONT hFont, UINT *x, UINT *y);
+void SetFont(HWND hWnd, UINT id, HFONT hFont);
+void SetFontEx(HWND hWnd, UINT id, HFONT hFont, bool no_adjust_font_size);
+void LimitText(HWND hWnd, UINT id, UINT count);
+bool CheckTextLen(HWND hWnd, UINT id, UINT len, bool unicode);
+bool CheckTextSize(HWND hWnd, UINT id, UINT size, bool unicode);
+void Check(HWND hWnd, UINT id, bool b);
+bool IsChecked(HWND hWnd, UINT id);
+void SetIcon(HWND hWnd, UINT id, UINT icon_id);
+void SetBitmap(HWND hWnd, UINT id, UINT bmp_id);
+bool SecureDeviceWindow(HWND hWnd, WINUI_SECURE_BATCH *batch, UINT num_batch, UINT device_id, UINT bitmap_id);
+UINT Dialog(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param);
+UINT DialogEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white);
+UINT DialogEx2(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white, bool meiryo);
+HWND DialogCreateEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white);
+UINT __stdcall InternalDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+UINT SecureDeviceWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+HFONT Font(UINT size, UINT bold);
+void DlgFont(HWND hWnd, UINT id, UINT size, UINT bold);
+void OpenAvi(HWND hWnd, UINT id, UINT avi_id);
+void CloseAvi(HWND hWnd, UINT id);
+void PlayAvi(HWND hWnd, UINT id, bool repeat);
+void StopAvi(HWND hWnd, UINT id);
+void EnableSecureDeviceWindowControls(HWND hWnd, bool enable);
+void SecureDeviceThread(THREAD *t, void *param);
+void Command(HWND hWnd, UINT id);
+wchar_t *OpenDlg(HWND hWnd, wchar_t *filter, wchar_t *title);
+char *OpenDlgA(HWND hWnd, char *filter, char *title);
+wchar_t *SaveDlg(HWND hWnd, wchar_t *filter, wchar_t *title, wchar_t *default_name, wchar_t *default_ext);
+char *SaveDlgA(HWND hWnd, char *filter, char *title, char *default_name, char *default_ext);
+wchar_t *MakeFilter(wchar_t *str);
+char *MakeFilterA(char *str);
+void PkcsUtil();
+UINT PkcsUtilProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void PkcsUtilWrite(HWND hWnd);
+void PkcsUtilErase(HWND hWnd);
+bool PassphraseDlg(HWND hWnd, char *pass, UINT pass_size, BUF *buf, bool p12);
+UINT PassphraseDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool PasswordDlg(HWND hWnd, UI_PASSWORD_DLG *p);
+void PasswordDlgOnOk(HWND hWnd, UI_PASSWORD_DLG *p);
+UINT PasswordDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void PasswordDlgProcChange(HWND hWnd, UI_PASSWORD_DLG *p);
+UINT CbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data);
+UINT CbAddStrA(HWND hWnd, UINT id, char *str, UINT data);
+UINT CbAddStr9xA(HWND hWnd, UINT id, char *str, UINT data);
+UINT CbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data);
+UINT CbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data);
+UINT CbInsertStr9xA(HWND hWnd, UINT id, UINT index, char *str, UINT data);
+void CbSelectIndex(HWND hWnd, UINT id, UINT index);
+UINT CbNum(HWND hWnd, UINT id);
+UINT CbFindStr(HWND hWnd, UINT id, wchar_t *str);
+UINT CbFindStr9xA(HWND hWnd, UINT id, char *str);
+wchar_t *CbGetStr(HWND hWnd, UINT id);
+UINT CbFindData(HWND hWnd, UINT id, UINT data);
+UINT CbGetData(HWND hWnd, UINT id, UINT index);
+void CbSelect(HWND hWnd, UINT id, int data);
+void CbReset(HWND hWnd, UINT id);
+void CbSetHeight(HWND hWnd, UINT id, UINT value);
+UINT CbGetSelectIndex(HWND hWnd, UINT id);
+UINT CbGetSelect(HWND hWnd, UINT id);
+void SetRange(HWND hWnd, UINT id, UINT start, UINT end);
+void SetPos(HWND hWnd, UINT id, UINT pos);
+UINT LbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data);
+UINT LbAddStrA(HWND hWnd, UINT id, char *str, UINT data);
+UINT LbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data);
+UINT LbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data);
+void LbSelectIndex(HWND hWnd, UINT id, UINT index);
+UINT LbNum(HWND hWnd, UINT id);
+UINT LbFindStr(HWND hWnd, UINT id, wchar_t *str);
+wchar_t *LbGetStr(HWND hWnd, UINT id);
+UINT LbFindData(HWND hWnd, UINT id, UINT data);
+UINT LbGetData(HWND hWnd, UINT id, UINT index);
+void LbSelect(HWND hWnd, UINT id, int data);
+void LbReset(HWND hWnd, UINT id);
+void LbSetHeight(HWND hWnd, UINT id, UINT value);
+UINT LbGetSelectIndex(HWND hWnd, UINT id);
+UINT LbGetSelect(HWND hWnd, UINT id);
+STATUS_WINDOW *StatusPrinterWindowStart(SOCK *s, wchar_t *account_name);
+void StatusPrinterWindowStop(STATUS_WINDOW *sw);
+void StatusPrinterWindowPrint(STATUS_WINDOW *sw, wchar_t *str);
+void StatusPrinterWindowThread(THREAD *thread, void *param);
+UINT StatusPrinterWindowDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void CertDlg(HWND hWnd, X *x, X *issuer_x, bool manager);
+UINT CertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void LvInit(HWND hWnd, UINT id);
+void LvInitEx(HWND hWnd, UINT id, bool no_image);
+void LvInitEx2(HWND hWnd, UINT id, bool no_image, bool large_icon);
+void LvReset(HWND hWnd, UINT id);
+void LvInsertColumn(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT width);
+UINT GetIcon(UINT icon_id);
+void LvInsert(HWND hWnd, UINT id, UINT icon, void *param, UINT num_str, ...);
+UINT LvInsertItem(HWND hWnd, UINT id, UINT icon, void *param, wchar_t *str);
+UINT LvInsertItemByImageListId(HWND hWnd, UINT id, UINT image, void *param, wchar_t *str);
+UINT LvInsertItemByImageListIdA(HWND hWnd, UINT id, UINT image, void *param, char *str);
+void LvSetItem(HWND hWnd, UINT id, UINT index, UINT pos, wchar_t *str);
+void LvSetItemA(HWND hWnd, UINT id, UINT index, UINT pos, char *str);
+void LvSetItemParam(HWND hWnd, UINT id, UINT index, void *param);
+void LvSetItemImage(HWND hWnd, UINT id, UINT index, UINT icon);
+void LvSetItemImageByImageListId(HWND hWnd, UINT id, UINT index, UINT image);
+void LvDeleteItem(HWND hWnd, UINT id, UINT index);
+UINT LvNum(HWND hWnd, UINT id);
+void *LvGetParam(HWND hWnd, UINT id, UINT index);
+wchar_t *LvGetStr(HWND hWnd, UINT id, UINT index, UINT pos);
+char *LvGetStrA(HWND hWnd, UINT id, UINT index, UINT pos);
+void LvShow(HWND hWnd, UINT id, UINT index);
+UINT LvSearchParam(HWND hWnd, UINT id, void *param);
+UINT LvSearchStr(HWND hWnd, UINT id, UINT pos, wchar_t *str);
+UINT LvSearchStrA(HWND hWnd, UINT id, UINT pos, char *str);
+UINT LvGetSelected(HWND hWnd, UINT id);
+void *LvGetSelectedParam(HWND hWnd, UINT id);
+UINT LvGetFocused(HWND hWnd, UINT id);
+wchar_t *LvGetFocusedStr(HWND hWnd, UINT id, UINT pos);
+wchar_t *LvGetSelectedStr(HWND hWnd, UINT id, UINT pos);
+char *LvGetSelectedStrA(HWND hWnd, UINT id, UINT pos);
+bool LvIsSelected(HWND hWnd, UINT id);
+UINT LvGetNextMasked(HWND hWnd, UINT id, UINT start);
+bool LvIsMasked(HWND hWnd, UINT id);
+bool LvIsSingleSelected(HWND hWnd, UINT id);
+bool LvIsMultiMasked(HWND hWnd, UINT id);
+UINT LvGetMaskedNum(HWND hWnd, UINT id);
+void LvAutoSize(HWND hWnd, UINT id);
+void LvSelect(HWND hWnd, UINT id, UINT index);
+void LvSelectByParam(HWND hWnd, UINT id, void *param);
+void LvSelectAll(HWND hWnd, UINT id);
+void LvSwitchSelect(HWND hWnd, UINT id);
+void LvSetView(HWND hWnd, UINT id, bool details);
+UINT LvGetColumnWidth(HWND hWnd, UINT id, UINT index);
+void CheckCertDlg(UI_CHECKCERT *p);
+UINT CheckCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void PrintCheckCertInfo(HWND hWnd, UI_CHECKCERT *p);
+void ShowDlgDiffWarning(HWND hWnd, UI_CHECKCERT *p);
+void CheckCertDialogOnOk(HWND hWnd, UI_CHECKCERT *p);
+bool ConnectErrorDlg(UI_CONNECTERROR_DLG *p);
+UINT ConnectErrorDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+HINSTANCE GetUiDll();
+HICON LoadLargeIconInner(UINT id);
+HICON LoadSmallIconInner(UINT id);
+HICON LoadLargeIcon(UINT id);
+HICON LoadSmallIcon(UINT id);
+HICON LoadIconEx(UINT id, bool small_icon);
+void InitIconCache();
+void FreeIconCache();
+LVB *LvInsertStart();
+void LvInsertAdd(LVB *b, UINT icon, void *param, UINT num_str, ...);
+void LvInsertEnd(LVB *b, HWND hWnd, UINT id);
+void LvInsertEndEx(LVB *b, HWND hWnd, UINT id, bool force_reset);
+void LvSetStyle(HWND hWnd, UINT id, UINT style);
+void LvRemoveStyle(HWND hWnd, UINT id, UINT style);
+HMENU LoadSubMenu(UINT menu_id, UINT pos, HMENU *parent_menu);
+UINT GetMenuItemPos(HMENU hMenu, UINT id);
+void DeleteMenuItem(HMENU hMenu, UINT pos);
+void SetMenuItemEnable(HMENU hMenu, UINT pos, bool enable);
+void SetMenuItemBold(HMENU hMenu, UINT pos, bool bold);
+wchar_t *GetMenuStr(HMENU hMenu, UINT pos);
+char *GetMenuStrA(HMENU hMenu, UINT pos);
+void SetMenuStr(HMENU hMenu, UINT pos, wchar_t *str);
+void SetMenuStrA(HMENU hMenu, UINT pos, char *str);
+void RemoveShortcutKeyStrFromMenu(HMENU hMenu);
+UINT GetMenuNum(HMENU hMenu);
+void PrintMenu(HWND hWnd, HMENU hMenu);
+void LvRename(HWND hWnd, UINT id, UINT pos);
+void AllowFGWindow(UINT process_id);
+HWND SearchWindow(wchar_t *caption);
+char *RemoteDlg(HWND hWnd, char *regkey, UINT icon, wchar_t *caption, wchar_t *title, char *default_host);
+LIST *ReadCandidateFromReg(UINT root, char *key, char *name);
+void WriteCandidateToReg(UINT root, char *key, LIST *o, char *name);
+UINT LvGetColumnNum(HWND hWnd, UINT id);
+void LvSetItemParamEx(HWND hWnd, UINT id, UINT index, UINT subitem, void *param);
+void LvSortEx(HWND hWnd, UINT id, UINT subitem, bool desc, bool numeric);
+void LvSort(HWND hWnd, UINT id, UINT subitem, bool desc);
+void *LvGetParamEx(HWND hWnd, UINT id, UINT index, UINT subitem);
+void LvSortHander(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id);
+void LvStandardHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id);
+void IpSet(HWND hWnd, UINT id, UINT ip);
+UINT IpGet(HWND hWnd, UINT id);
+void IpClear(HWND hWnd, UINT id);
+bool IpIsFilled(HWND hWnd, UINT id);
+UINT IpGetFilledNum(HWND hWnd, UINT id);
+void About(HWND hWnd, CEDAR *cedar, wchar_t *product_name);
+void AboutEx(HWND hWnd, CEDAR *cedar, wchar_t *product_name, WINUI_UPDATE *u);
+void Win9xReboot(HWND hWnd);
+void Win9xRebootThread(THREAD *t, void *p);
+UINT Win9xRebootDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+wchar_t *StringDlg(HWND hWnd, wchar_t *title, wchar_t *info, wchar_t *def, UINT icon, bool allow_empty, bool allow_unsafe);
+char *StringDlgA(HWND hWnd, wchar_t *title, wchar_t *info, char *def, UINT icon, bool allow_empty, bool allow_unsafe);
+UINT StringDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void InitDialogInternational(HWND hWnd, void *pparam);
+void AdjustWindowAndControlSize(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y);
+void GetWindowAndControlSizeResizeScale(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y);
+void AdjustDialogXY(UINT *x, UINT *y, UINT dlgfont_x, UINT dlgfont_y);
+HFONT GetDialogDefaultFont();
+HFONT GetDialogDefaultFontEx(bool meiryo);
+void InitMenuInternational(HMENU hMenu, char *prefix);
+void InitMenuInternationalUni(HMENU hMenu, char *prefix);
+void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode);
+void ShowCpu64Warning();
+UINT Cpu64DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+UINT TcpIpDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void TcpIpDlgInit(HWND hWnd);
+void TcpIpDlgUpdate(HWND hWnd);
+UINT TcpMsgDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+UINT KakushiDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void KakushiThread(THREAD *thread, void *param);
+KAKUSHI *InitKakushi();
+void FreeKakushi(KAKUSHI *k);
+void ShowEasterEgg(HWND hWnd);
+bool ExecuteHamcoreExe(char *name);
+bool IsRegistedToDontShowFreeEditionDialog(char *server_name);
+void RegistToDontShowFreeEditionDialog(char *server_name);
+void ShowFreeInfoDialog(HWND hWnd, FREEINFO *info);
+UINT FreeInfoDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+FREEINFO *StartFreeInfoDlg(char *server_name);
+void FreeInfoThread(THREAD *thread, void *param);
+void EndFreeInfoDlg(FREEINFO *info);
+bool Win32CnCheckAlreadyExists(bool lock);
+void RegistWindowsFirewallAll();
+void RegistWindowsFirewallAllEx(char *dir);
+void InitVistaWindowTheme(HWND hWnd);
+void WinUiDebug(wchar_t *str);
+void WinUiDebugInit();
+void WinUiDebugFree();
+void OnceMsg(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon);
+void OnceMsgEx(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon, bool *halt);
+UINT GetOnceMsgHash(wchar_t *title, wchar_t *message);
+UINT OnceMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool CheckBadProcesses(HWND hWnd);
+BAD_PROCESS *IsBadProcess(char *exe);
+void ShowBadProcessWarning(HWND hWnd, BAD_PROCESS *bad);
+void SetFontMeiryo(HWND hWnd, UINT id, UINT font_size);
+char *GetMeiryoFontName();
+void SetFontDefault(HWND hWnd, UINT id);
+HFONT GetMeiryoFont();
+HFONT GetMeiryoFontEx(UINT font_size);
+HFONT GetMeiryoFontEx2(UINT font_size, bool bold);
+bool ShowWindowsNetworkConnectionDialog();
+SOCK *WinConnectEx2(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info, bool try_start_ssl, bool ssl_no_tls);
+SOCK *WinConnectEx3(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info, UINT *nat_t_error_code, char *nat_t_svc_name, bool try_start_ssl, bool ssl_no_tls);
+UINT WinConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void WinConnectDlgThread(THREAD *thread, void *param);
+void NicInfo(UI_NICINFO *info);
+UINT NicInfoProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void NicInfoInit(HWND hWnd, UI_NICINFO *info);
+void NicInfoOnTimer(HWND hWnd, UI_NICINFO *info);
+void NicInfoRefresh(HWND hWnd, UI_NICINFO *info);
+void NicInfoShowStatus(HWND hWnd, UI_NICINFO *info, wchar_t *msg1, wchar_t *msg2, UINT icon, bool animate);
+void NicInfoCloseAfterTime(HWND hWnd, UI_NICINFO *info, UINT tick);
+
+WIZARD *NewWizard(UINT icon, UINT bitmap, wchar_t *caption, void *param);
+void FreeWizard(WIZARD *w);
+WIZARD_PAGE *NewWizardPage(UINT id, WINUI_WIZARD_PROC *proc, wchar_t *title);
+void FreeWizardPage(WIZARD_PAGE *p);
+void AddWizardPage(WIZARD *w, WIZARD_PAGE *p);
+WIZARD_PAGE *GetWizardPage(WIZARD *w, UINT id);
+UINT GetWizardPageIndex(WIZARD *w, UINT id);
+void *CreateWizardPageInstance(WIZARD *w, WIZARD_PAGE *p);
+void ShowWizard(HWND hWndParent, WIZARD *w, UINT start_id);
+void SetWizardButton(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish);
+void SetWizardButtonEx(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish, bool shield_icon);
+void JumpWizard(WIZARD_PAGE *p, UINT next_id);
+void CloseWizard(WIZARD_PAGE *p);
+void SetUacIcon(HWND hWnd, UINT id);
+
+LIST *NewBitmapList();
+void FreeBitmapList(LIST *o);
+
+bool GetBitmapSize(void *bmp, UINT *x, UINT *y);
+
+bool GetFontParam(HFONT hFont, struct FONT *f);
+void AdjustFontSize(HWND hWnd, UINT id);
+bool IsFontFitInRect(struct FONT *f, UINT width, UINT height, wchar_t *text, UINT format, bool *aborted);
+
+void ShowTextFile(HWND hWnd, char *filename, wchar_t *caption, UINT icon);
+
+#endif // OS_WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Wpc.c b/src/Cedar/Wpc.c
new file mode 100644
index 00000000..45a30222
--- /dev/null
+++ b/src/Cedar/Wpc.c
@@ -0,0 +1,1326 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Wpc.c
+// RPC over HTTP
+
+#include <GlobalConst.h>
+
+#include "CedarPch.h"
+
+// Get whether the proxy server is specified by a private IP
+bool IsProxyPrivateIp(INTERNET_SETTING *s)
+{
+ IP ip;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->ProxyType == PROXY_DIRECT)
+ {
+ return false;
+ }
+
+ if (GetIP(&ip, s->ProxyHostName) == false)
+ {
+ return false;
+ }
+
+ if (IsIPPrivate(&ip))
+ {
+ return true;
+ }
+
+ if (IsIPMyHost(&ip))
+ {
+ return true;
+ }
+
+ if (IsLocalHostIP(&ip))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Call
+PACK *WpcCall(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm,
+ char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash)
+{
+ return WpcCallEx(url, setting, timeout_connect, timeout_comm, function_name, pack, cert, key,
+ sha1_cert_hash, NULL, 0);
+}
+PACK *WpcCallEx(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm,
+ char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash, bool *cancel, UINT max_recv_size)
+{
+ URL_DATA data;
+ BUF *b, *recv;
+ UINT error;
+ WPC_PACKET packet;
+ // Validate arguments
+ if (function_name == NULL || pack == NULL)
+ {
+ return PackError(ERR_INTERNAL_ERROR);
+ }
+
+ if (ParseUrl(&data, url, true, NULL) == false)
+ {
+ return PackError(ERR_INTERNAL_ERROR);
+ }
+
+ PackAddStr(pack, "function", function_name);
+
+ b = WpcGeneratePacket(pack, cert, key);
+ if (b == NULL)
+ {
+ return PackError(ERR_INTERNAL_ERROR);
+ }
+
+ SeekBuf(b, b->Size, 0);
+ WriteBufInt(b, 0);
+ SeekBuf(b, 0, 0);
+
+ recv = HttpRequestEx(&data, setting, timeout_connect, timeout_comm, &error,
+ false, b->Buf, NULL, NULL, sha1_cert_hash, cancel, max_recv_size);
+
+ FreeBuf(b);
+
+ if (recv == NULL)
+ {
+ return PackError(error);
+ }
+
+ if (WpcParsePacket(&packet, recv) == false)
+ {
+ FreeBuf(recv);
+ return PackError(ERR_PROTOCOL_ERROR);
+ }
+
+ FreeBuf(recv);
+
+ FreeX(packet.Cert);
+
+ return packet.Pack;
+}
+
+// Release the packet
+void WpcFreePacket(WPC_PACKET *packet)
+{
+ // Validate arguments
+ if (packet == NULL)
+ {
+ return;
+ }
+
+ FreePack(packet->Pack);
+ FreeX(packet->Cert);
+}
+
+// Parse the packet
+bool WpcParsePacket(WPC_PACKET *packet, BUF *buf)
+{
+ LIST *o;
+ BUF *b;
+ bool ret = false;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (packet == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(packet, sizeof(WPC_PACKET));
+
+ o = WpcParseDataEntry(buf);
+
+ b = WpcDataEntryToBuf(WpcFindDataEntry(o, "PACK"));
+ if (b != NULL)
+ {
+ HashSha1(hash, b->Buf, b->Size);
+
+ packet->Pack = BufToPack(b);
+ FreeBuf(b);
+
+ if (packet->Pack != NULL)
+ {
+ BUF *b;
+
+ ret = true;
+
+ b = WpcDataEntryToBuf(WpcFindDataEntry(o, "HASH"));
+
+ if (b != NULL)
+ {
+ if (b->Size != SHA1_SIZE || Cmp(b->Buf, hash, SHA1_SIZE) != 0)
+ {
+ ret = false;
+ FreePack(packet->Pack);
+ }
+ else
+ {
+ BUF *b;
+
+ Copy(packet->Hash, hash, SHA1_SIZE);
+
+ b = WpcDataEntryToBuf(WpcFindDataEntry(o, "CERT"));
+
+ if (b != NULL)
+ {
+ X *cert = BufToX(b, false);
+ if (cert == NULL)
+ {
+ ret = false;
+ FreePack(packet->Pack);
+ }
+ else
+ {
+ BUF *b = WpcDataEntryToBuf(WpcFindDataEntry(o, "SIGN"));
+
+ if (b == NULL || (b->Size != 128))
+ {
+ ret = false;
+ FreeX(cert);
+ FreePack(packet->Pack);
+ }
+ else
+ {
+ K *k = GetKFromX(cert);
+
+ if (RsaVerify(hash, SHA1_SIZE, b->Buf, k) == false)
+ {
+ ret = false;
+ FreeX(cert);
+ FreePack(packet->Pack);
+ }
+ else
+ {
+ packet->Cert = cert;
+ Copy(packet->Sign, b->Buf, 128);
+ }
+
+ FreeK(k);
+ }
+
+ FreeBuf(b);
+ }
+ FreeBuf(b);
+ }
+ }
+ FreeBuf(b);
+ }
+ }
+ }
+
+ WpcFreeDataEntryList(o);
+
+ return ret;
+}
+
+// Generate the packet
+BUF *WpcGeneratePacket(PACK *pack, X *cert, K *key)
+{
+ UCHAR hash[SHA1_SIZE];
+ BUF *pack_data;
+ BUF *cert_data = NULL;
+ BUF *sign_data = NULL;
+ BUF *b;
+ // Validate arguments
+ if (pack == NULL)
+ {
+ return NULL;
+ }
+
+ pack_data = PackToBuf(pack);
+ HashSha1(hash, pack_data->Buf, pack_data->Size);
+
+ if (cert != NULL && key != NULL)
+ {
+ UCHAR sign[128];
+ cert_data = XToBuf(cert, false);
+
+ RsaSign(sign, hash, sizeof(hash), key);
+
+ sign_data = NewBuf();
+ WriteBuf(sign_data, sign, sizeof(sign));
+ SeekBuf(sign_data, 0, 0);
+ }
+
+ b = NewBuf();
+
+ WpcAddDataEntryBin(b, "PACK", pack_data->Buf, pack_data->Size);
+ WpcAddDataEntryBin(b, "HASH", hash, sizeof(hash));
+
+ if (cert_data != NULL)
+ {
+ WpcAddDataEntryBin(b, "CERT", cert_data->Buf, cert_data->Size);
+ WpcAddDataEntryBin(b, "SIGN", sign_data->Buf, sign_data->Size);
+ }
+
+ FreeBuf(pack_data);
+ FreeBuf(cert_data);
+ FreeBuf(sign_data);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Decode the buffer from WPC_ENTRY
+BUF *WpcDataEntryToBuf(WPC_ENTRY *e)
+{
+ void *data;
+ UINT data_size;
+ UINT size;
+ BUF *b;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ data_size = e->Size + 4096;
+ data = Malloc(data_size);
+ size = DecodeSafe64(data, e->Data, e->Size);
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ Free(data);
+
+ return b;
+}
+
+// Search for the data entry
+WPC_ENTRY *WpcFindDataEntry(LIST *o, char *name)
+{
+ UINT i;
+ char name_str[WPC_DATA_ENTRY_SIZE];
+ // Validate arguments
+ if (o == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ WpcFillEntryName(name_str, name);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ WPC_ENTRY *e = LIST_DATA(o, i);
+
+ if (Cmp(e->EntryName, name_str, WPC_DATA_ENTRY_SIZE) == 0)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Release the data entry list
+void WpcFreeDataEntryList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ WPC_ENTRY *e = LIST_DATA(o, i);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Parse the data entry
+LIST *WpcParseDataEntry(BUF *b)
+{
+ char entry_name[WPC_DATA_ENTRY_SIZE];
+ char size_str[11];
+ LIST *o;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ o = NewListFast(NULL);
+
+ while (true)
+ {
+ UINT size;
+ WPC_ENTRY *e;
+
+ if (ReadBuf(b, entry_name, WPC_DATA_ENTRY_SIZE) != WPC_DATA_ENTRY_SIZE)
+ {
+ break;
+ }
+
+ Zero(size_str, sizeof(size_str));
+ if (ReadBuf(b, size_str, 10) != 10)
+ {
+ break;
+ }
+
+ size = ToInt(size_str);
+ if ((b->Size - b->Current) < size)
+ {
+ break;
+ }
+
+ e = ZeroMalloc(sizeof(WPC_ENTRY));
+ e->Data = (UCHAR *)b->Buf + b->Current;
+ Copy(e->EntryName, entry_name, WPC_DATA_ENTRY_SIZE);
+ e->Size = size;
+
+ SeekBuf(b, size, 1);
+
+ Add(o, e);
+ }
+
+ return o;
+}
+
+// Generate a entry name
+void WpcFillEntryName(char *dst, char *name)
+{
+ UINT i, len;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (dst == NULL || name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ StrUpper(tmp);
+ len = StrLen(tmp);
+
+ for (i = 0;i < WPC_DATA_ENTRY_SIZE;i++)
+ {
+ dst[i] = ' ';
+ }
+
+ if (len <= WPC_DATA_ENTRY_SIZE)
+ {
+ Copy(dst, tmp, len);
+ }
+ else
+ {
+ Copy(dst, tmp, WPC_DATA_ENTRY_SIZE);
+ }
+}
+
+// Add the data entry (binary)
+void WpcAddDataEntryBin(BUF *b, char *name, void *data, UINT size)
+{
+ char *str;
+ // Validate arguments
+ if (b == NULL || name == NULL || (data == NULL && size != 0))
+ {
+ return;
+ }
+
+ str = Malloc(size * 2 + 64);
+
+ EncodeSafe64(str, data, size);
+
+ WpcAddDataEntry(b, name, str, StrLen(str));
+
+ Free(str);
+}
+
+
+// Add the data entry
+void WpcAddDataEntry(BUF *b, char *name, void *data, UINT size)
+{
+ char entry_name[WPC_DATA_ENTRY_SIZE];
+ char size_str[11];
+ // Validate arguments
+ if (b == NULL || name == NULL || (data == NULL && size != 0))
+ {
+ return;
+ }
+
+ WpcFillEntryName(entry_name, name);
+ WriteBuf(b, entry_name, WPC_DATA_ENTRY_SIZE);
+
+ Format(size_str, sizeof(size_str), "%010u", size);
+ WriteBuf(b, size_str, 10);
+
+ WriteBuf(b, data, size);
+}
+
+// Get the empty INTERNET_SETTING
+INTERNET_SETTING *GetNullInternetSetting()
+{
+ static INTERNET_SETTING ret;
+
+ Zero(&ret, sizeof(ret));
+
+ return &ret;
+}
+
+// Socket connection
+SOCK *WpcSockConnect(WPC_CONNECT *param, UINT *error_code, UINT timeout)
+{
+ return WpcSockConnectEx(param, error_code, timeout, NULL);
+}
+SOCK *WpcSockConnectEx(WPC_CONNECT *param, UINT *error_code, UINT timeout, bool *cancel)
+{
+ CONNECTION c;
+ SOCK *sock;
+ UINT err = ERR_NO_ERROR;
+ // Validate arguments
+ if (param == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&c, sizeof(c));
+
+ sock = NULL;
+ err = ERR_INTERNAL_ERROR;
+
+ switch (param->ProxyType)
+ {
+ case PROXY_DIRECT:
+ sock = TcpConnectEx3(param->HostName, param->Port, timeout, cancel, NULL, true, NULL, false, false);
+ if (sock == NULL)
+ {
+ err = ERR_CONNECT_FAILED;
+ }
+ break;
+
+ case PROXY_HTTP:
+ sock = ProxyConnectEx2(&c, param->ProxyHostName, param->ProxyPort,
+ param->HostName, param->Port,
+ param->ProxyUsername, param->ProxyPassword, false, cancel, NULL, timeout);
+ if (sock == NULL)
+ {
+ err = c.Err;
+ }
+ break;
+
+ case PROXY_SOCKS:
+ sock = SocksConnectEx2(&c, param->ProxyHostName, param->ProxyPort,
+ param->HostName, param->Port,
+ param->ProxyUsername, false, cancel, NULL, timeout);
+ if (sock == NULL)
+ {
+ err = c.Err;
+ }
+ break;
+ }
+
+ if (error_code != NULL)
+ {
+ *error_code = err;
+ }
+
+ return sock;
+}
+SOCK *WpcSockConnect2(char *hostname, UINT port, INTERNET_SETTING *t, UINT *error_code, UINT timeout)
+{
+ // Validate arguments
+ INTERNET_SETTING t2;
+ WPC_CONNECT c;
+ if (t == NULL)
+ {
+ Zero(&t2, sizeof(t2));
+
+ t = &t2;
+ }
+
+ Zero(&c, sizeof(c));
+ StrCpy(c.HostName, sizeof(c.HostName), hostname);
+ c.Port = port;
+ c.ProxyType = t->ProxyType;
+ StrCpy(c.ProxyHostName, sizeof(c.HostName), t->ProxyHostName);
+ c.ProxyPort = t->ProxyPort;
+ StrCpy(c.ProxyUsername, sizeof(c.ProxyUsername), t->ProxyUsername);
+ StrCpy(c.ProxyPassword, sizeof(c.ProxyPassword), t->ProxyPassword);
+
+ return WpcSockConnect(&c, error_code, timeout);
+}
+
+// Handle the HTTP request
+BUF *HttpRequest(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash)
+{
+ return HttpRequestEx(data, setting, timeout_connect, timeout_comm,
+ error_code, check_ssl_trust, post_data,
+ recv_callback, recv_callback_param, sha1_cert_hash, NULL, 0);
+}
+BUF *HttpRequestEx(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash,
+ bool *cancel, UINT max_recv_size)
+{
+ return HttpRequestEx2(data, setting, timeout_connect, timeout_comm, error_code,
+ check_ssl_trust, post_data, recv_callback, recv_callback_param, sha1_cert_hash,
+ cancel, max_recv_size, NULL, NULL);
+}
+BUF *HttpRequestEx2(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash,
+ bool *cancel, UINT max_recv_size, char *header_name, char *header_value)
+{
+ WPC_CONNECT con;
+ SOCK *s;
+ HTTP_HEADER *h;
+ bool use_http_proxy = false;
+ char target[MAX_SIZE * 4];
+ char *send_str;
+ BUF *send_buf;
+ BUF *recv_buf;
+ UINT http_error_code;
+ char len_str[100];
+ UINT content_len;
+ void *socket_buffer;
+ UINT socket_buffer_size = WPC_RECV_BUF_SIZE;
+ UINT num_continue = 0;
+ INTERNET_SETTING wt_setting;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+ if (setting == NULL)
+ {
+ Zero(&wt_setting, sizeof(wt_setting));
+ setting = &wt_setting;
+ }
+ if (error_code == NULL)
+ {
+ static UINT ret = 0;
+ error_code = &ret;
+ }
+ if (timeout_comm == 0)
+ {
+ timeout_comm = WPC_TIMEOUT;
+ }
+
+ // Connection
+ Zero(&con, sizeof(con));
+ StrCpy(con.HostName, sizeof(con.HostName), data->HostName);
+ con.Port = data->Port;
+ con.ProxyType = setting->ProxyType;
+ StrCpy(con.ProxyHostName, sizeof(con.ProxyHostName), setting->ProxyHostName);
+ con.ProxyPort = setting->ProxyPort;
+ StrCpy(con.ProxyUsername, sizeof(con.ProxyUsername), setting->ProxyUsername);
+ StrCpy(con.ProxyPassword, sizeof(con.ProxyPassword), setting->ProxyPassword);
+
+ if (setting->ProxyType != PROXY_HTTP || data->Secure)
+ {
+ use_http_proxy = false;
+ StrCpy(target, sizeof(target), data->Target);
+ }
+ else
+ {
+ use_http_proxy = true;
+ CreateUrl(target, sizeof(target), data);
+ }
+
+ if (use_http_proxy == false)
+ {
+ // If the connection is not via HTTP Proxy, or is a SSL connection even via HTTP Proxy
+ s = WpcSockConnectEx(&con, error_code, timeout_connect, cancel);
+ }
+ else
+ {
+ // If the connection is not SSL via HTTP Proxy
+ s = TcpConnectEx3(con.ProxyHostName, con.ProxyPort, timeout_connect, cancel, NULL, true, NULL, false, false);
+ if (s == NULL)
+ {
+ *error_code = ERR_PROXY_CONNECT_FAILED;
+ }
+ }
+
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ if (data->Secure)
+ {
+ // Start the SSL communication
+ if (StartSSLEx(s, NULL, NULL, true, 0, NULL) == false)
+ {
+ // SSL connection failed
+ *error_code = ERR_PROTOCOL_ERROR;
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ if (sha1_cert_hash != NULL)
+ {
+ UCHAR hash[SHA1_SIZE];
+ Zero(hash, sizeof(hash));
+ GetXDigest(s->RemoteX, hash, true);
+
+ if (Cmp(hash, sha1_cert_hash, SHA1_SIZE) != 0)
+ {
+ // Destination certificate hash mismatch
+ *error_code = ERR_CERT_NOT_TRUSTED;
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+ }
+ }
+
+ // Timeout setting
+ SetTimeout(s, timeout_comm);
+
+ // Generate a request
+ h = NewHttpHeader(data->Method, target, use_http_proxy ? "HTTP/1.0" : "HTTP/1.1");
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Accept-Language", "ja"));
+ AddHttpValue(h, NewHttpValue("User-Agent", WPC_USER_AGENT));
+ AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
+ AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache"));
+ AddHttpValue(h, NewHttpValue("Host", data->HeaderHostName));
+
+ if (IsEmptyStr(header_name) == false && IsEmptyStr(header_value) == false)
+ {
+ AddHttpValue(h, NewHttpValue(header_name, header_value));
+ }
+
+ if (IsEmptyStr(data->Referer) == false)
+ {
+ AddHttpValue(h, NewHttpValue("Referer", data->Referer));
+ }
+
+ if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0)
+ {
+ ToStr(len_str, StrLen(post_data));
+ AddHttpValue(h, NewHttpValue("Content-Type", "application/x-www-form-urlencoded"));
+ AddHttpValue(h, NewHttpValue("Content-Length", len_str));
+ }
+
+ if (use_http_proxy)
+ {
+ AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
+
+ if (IsEmptyStr(setting->ProxyUsername) == false || IsEmptyStr(setting->ProxyPassword) == false)
+ {
+ char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
+ char basic_str[MAX_SIZE * 2];
+
+ // Generate the authentication string
+ Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
+ setting->ProxyUsername, setting->ProxyPassword);
+
+ // Base64 encode
+ Zero(auth_b64_str, sizeof(auth_b64_str));
+ Encode64(auth_b64_str, auth_tmp_str);
+ Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
+
+ AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
+ }
+ }
+
+ send_str = HttpHeaderToStr(h);
+ FreeHttpHeader(h);
+
+ send_buf = NewBuf();
+ WriteBuf(send_buf, send_str, StrLen(send_str));
+ Free(send_str);
+
+ // Append to the sending data in the case of POST
+ if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0)
+ {
+ WriteBuf(send_buf, post_data, StrLen(post_data));
+ }
+
+ // Send
+ if (SendAll(s, send_buf->Buf, send_buf->Size, s->SecureMode) == false)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ FreeBuf(send_buf);
+
+ *error_code = ERR_DISCONNECTED;
+
+ return NULL;
+ }
+
+ FreeBuf(send_buf);
+
+CONT:
+ // Receive
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+
+ *error_code = ERR_DISCONNECTED;
+
+ return NULL;
+ }
+
+ http_error_code = 0;
+ if (StrLen(h->Method) == 8)
+ {
+ if (Cmp(h->Method, "HTTP/1.", 7) == 0)
+ {
+ http_error_code = ToInt(h->Target);
+ }
+ }
+
+ *error_code = ERR_NO_ERROR;
+
+ switch (http_error_code)
+ {
+ case 401:
+ case 407:
+ // Proxy authentication error
+ *error_code = ERR_PROXY_AUTH_FAILED;
+ break;
+
+ case 404:
+ // 404 File Not Found
+ *error_code = ERR_OBJECT_NOT_FOUND;
+ break;
+
+ case 100:
+ // Continue
+ num_continue++;
+ if (num_continue >= 10)
+ {
+ goto DEF;
+ }
+ FreeHttpHeader(h);
+ goto CONT;
+
+ case 200:
+ // Success
+ break;
+
+ default:
+ // Protocol error
+DEF:
+ *error_code = ERR_PROTOCOL_ERROR;
+ break;
+ }
+
+ if (*error_code != ERR_NO_ERROR)
+ {
+ // An error has occured
+ Disconnect(s);
+ ReleaseSock(s);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ // Get the length of the content
+ content_len = GetContentLength(h);
+ if (max_recv_size != 0)
+ {
+ content_len = MIN(content_len, max_recv_size);
+ }
+
+ FreeHttpHeader(h);
+
+ socket_buffer = Malloc(socket_buffer_size);
+
+ // Receive the content
+ recv_buf = NewBuf();
+
+ while (true)
+ {
+ UINT recvsize = MIN(socket_buffer_size, content_len - recv_buf->Size);
+ UINT size;
+
+ if (recv_callback != NULL)
+ {
+ if (recv_callback(recv_callback_param,
+ content_len, recv_buf->Size, recv_buf) == false)
+ {
+ // Cancel the reception
+ *error_code = ERR_USER_CANCEL;
+ goto RECV_CANCEL;
+ }
+ }
+
+ if (recvsize == 0)
+ {
+ break;
+ }
+
+ size = Recv(s, socket_buffer, recvsize, s->SecureMode);
+ if (size == 0)
+ {
+ // Disconnected
+ *error_code = ERR_DISCONNECTED;
+
+RECV_CANCEL:
+ FreeBuf(recv_buf);
+ Free(socket_buffer);
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return NULL;
+ }
+
+ WriteBuf(recv_buf, socket_buffer, size);
+ }
+
+ SeekBuf(recv_buf, 0, 0);
+ Free(socket_buffer);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ // Transmission
+ return recv_buf;
+}
+
+// Get the proxy server settings from the registry string of IE
+bool GetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type)
+{
+#ifdef OS_WIN32
+ TOKEN_LIST *t;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL || port == NULL || str == NULL || server_type == NULL)
+ {
+ return false;
+ }
+
+ t = ParseToken(str, ";");
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+ UINT i;
+
+ Trim(s);
+
+ i = SearchStrEx(s, "=", 0, false);
+ if (i != INFINITE)
+ {
+ char tmp[MAX_PATH];
+
+ StrCpy(name, name_size, s);
+ name[i] = 0;
+
+ if (StrCmpi(name, server_type) == 0)
+ {
+ char *host;
+ StrCpy(tmp, sizeof(tmp), s + i + 1);
+
+ if (ParseHostPort(tmp, &host, port, 0))
+ {
+ StrCpy(name, name_size, host);
+ Free(host);
+
+ if (*port != 0)
+ {
+ ret = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+#else // OS_WIN32
+ return true;
+#endif // OS_WIN32
+}
+
+// Get the internet connection settings of the system
+void GetSystemInternetSetting(INTERNET_SETTING *setting)
+{
+#ifdef OS_WIN32
+ bool use_proxy;
+ // Validate arguments
+ if (setting == NULL)
+ {
+ return;
+ }
+
+ Zero(setting, sizeof(INTERNET_SETTING));
+
+ use_proxy = MsRegReadInt(REG_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
+ "ProxyEnable");
+
+ if (use_proxy)
+ {
+ char *str = MsRegReadStr(REG_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
+ "ProxyServer");
+ if (str != NULL)
+ {
+ char name[MAX_HOST_NAME_LEN + 1];
+ UINT port;
+
+ if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "https"))
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "http"))
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
+ &port, str, "socks"))
+ {
+ setting->ProxyType = PROXY_SOCKS;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
+ setting->ProxyPort = port;
+ }
+ else
+ {
+ if (SearchStrEx(str, "=", 0, false) == INFINITE)
+ {
+ char *host;
+ UINT port;
+ if (ParseHostPort(str, &host, &port, 0))
+ {
+ if (port != 0)
+ {
+ setting->ProxyType = PROXY_HTTP;
+ StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), host);
+ setting->ProxyPort = port;
+ }
+ Free(host);
+ }
+ }
+ }
+
+ Free(str);
+ }
+ }
+#else // OS_WIN32
+ Zero(setting, sizeof(INTERNET_SETTING));
+#endif // OS_WIN32
+}
+
+// Generate the URL
+void CreateUrl(char *url, UINT url_size, URL_DATA *data)
+{
+ char *protocol;
+ // Validate arguments
+ if (url == NULL || data == NULL)
+ {
+ return;
+ }
+
+ if (data->Secure == false)
+ {
+ protocol = "http://";
+ }
+ else
+ {
+ protocol = "https://";
+ }
+
+ Format(url, url_size, "%s%s%s", protocol, data->HeaderHostName, data->Target);
+}
+
+
+// Parse the URL
+bool ParseUrl(URL_DATA *data, char *str, bool is_post, char *referrer)
+{
+ char tmp[MAX_SIZE * 3];
+ char server_port[MAX_HOST_NAME_LEN + 16];
+ char *s = NULL;
+ char *host;
+ UINT port;
+ UINT i;
+ // Validate arguments
+ if (data == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ Zero(data, sizeof(URL_DATA));
+
+ if (is_post)
+ {
+ StrCpy(data->Method, sizeof(data->Method), WPC_HTTP_POST_NAME);
+ }
+ else
+ {
+ StrCpy(data->Method, sizeof(data->Method), WPC_HTTP_GET_NAME);
+ }
+
+ if (referrer != NULL)
+ {
+ StrCpy(data->Referer, sizeof(data->Referer), referrer);
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ // Determine the protocol
+ if (StartWith(tmp, "http://"))
+ {
+ data->Secure = false;
+ s = &tmp[7];
+ }
+ else if (StartWith(tmp, "https://"))
+ {
+ data->Secure = true;
+ s = &tmp[8];
+ }
+ else
+ {
+ if (SearchStrEx(tmp, "://", 0, false) != INFINITE)
+ {
+ return false;
+ }
+ data->Secure = false;
+ s = &tmp[0];
+ }
+
+ // Get the "server name:port number"
+ StrCpy(server_port, sizeof(server_port), s);
+ i = SearchStrEx(server_port, "/", 0, false);
+ if (i != INFINITE)
+ {
+ server_port[i] = 0;
+ s += StrLen(server_port);
+ StrCpy(data->Target, sizeof(data->Target), s);
+ }
+ else
+ {
+ StrCpy(data->Target, sizeof(data->Target), "/");
+ }
+
+ if (ParseHostPort(server_port, &host, &port, data->Secure ? 443 : 80) == false)
+ {
+ return false;
+ }
+
+ StrCpy(data->HostName, sizeof(data->HostName), host);
+ data->Port = port;
+
+ Free(host);
+
+ if ((data->Secure && data->Port == 443) || (data->Secure == false && data->Port == 80))
+ {
+ StrCpy(data->HeaderHostName, sizeof(data->HeaderHostName), data->HostName);
+ }
+ else
+ {
+ Format(data->HeaderHostName, sizeof(data->HeaderHostName),
+ "%s:%u", data->HostName, data->Port);
+ }
+
+ return true;
+}
+
+// String replacement
+void Base64ToSafe64(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ switch (str[i])
+ {
+ case '=':
+ str[i] = '(';
+ break;
+
+ case '+':
+ str[i] = ')';
+ break;
+
+ case '/':
+ str[i] = '_';
+ break;
+ }
+ }
+}
+void Safe64ToBase64(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ switch (str[i])
+ {
+ case '(':
+ str[i] = '=';
+ break;
+
+ case ')':
+ str[i] = '+';
+ break;
+
+ case '_':
+ str[i] = '/';
+ break;
+ }
+ }
+}
+
+// Decode from Safe64
+UINT DecodeSafe64(void *dst, char *src, UINT src_strlen)
+{
+ char *tmp;
+ UINT ret;
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ if (src_strlen == 0)
+ {
+ src_strlen = StrLen(src);
+ }
+
+ tmp = Malloc(src_strlen + 1);
+ Copy(tmp, src, src_strlen);
+ tmp[src_strlen] = 0;
+ Safe64ToBase64(tmp);
+
+ ret = B64_Decode(dst, tmp, src_strlen);
+ Free(tmp);
+
+ return ret;
+}
+
+// Encode to Safe64
+void EncodeSafe64(char *dst, void *src, UINT src_size)
+{
+ UINT size;
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ size = B64_Encode(dst, src, src_size);
+ dst[size] = 0;
+
+ Base64ToSafe64(dst);
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/Wpc.h b/src/Cedar/Wpc.h
new file mode 100644
index 00000000..f1a29866
--- /dev/null
+++ b/src/Cedar/Wpc.h
@@ -0,0 +1,201 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Wpc.h
+// Header of Wpc.c
+
+#ifndef WPC_H
+#define WPC_H
+
+// Constant
+#define WPC_HTTP_POST_NAME "POST" // POST
+#define WPC_HTTP_GET_NAME "GET" // GET
+#define WPC_USER_AGENT DEFAULT_USER_AGENT // User Agent
+#define WPC_TIMEOUT (15 * 1000) // Time-out
+#define WPC_RECV_BUF_SIZE 64000 // Receive buffer size
+#define WPC_DATA_ENTRY_SIZE 4 // Data entry size
+#define WPC_MAX_HTTP_DATASIZE (134217728) // Maximum HTTP data size
+
+// Connection parameters
+struct WPC_CONNECT
+{
+ char HostName[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+ UINT ProxyType; // Type of proxy server
+ char ProxyHostName[MAX_HOST_NAME_LEN + 1]; // Proxy server host name
+ UINT ProxyPort; // Proxy server port number
+ char ProxyUsername[MAX_USERNAME_LEN + 1]; // Proxy server user name
+ char ProxyPassword[MAX_USERNAME_LEN + 1]; // Proxy server password
+ bool UseCompress; // Use of compression
+ bool DontCheckCert; // Do not check the certificate
+};
+
+// Internet connection settings
+struct INTERNET_SETTING
+{
+ UINT ProxyType; // Type of proxy server
+ char ProxyHostName[MAX_HOST_NAME_LEN + 1]; // Proxy server host name
+ UINT ProxyPort; // Proxy server port number
+ char ProxyUsername[MAX_USERNAME_LEN + 1]; // Proxy server user name
+ char ProxyPassword[MAX_USERNAME_LEN + 1]; // Proxy server password
+};
+
+// URL
+struct URL_DATA
+{
+ bool Secure; // Whether HTTPS
+ char HostName[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+ char HeaderHostName[MAX_HOST_NAME_LEN + 16]; // Host name on the header
+ char Method[32]; // Method
+ char Target[MAX_SIZE * 3]; // Target
+ char Referer[MAX_SIZE * 3]; // Referer
+};
+
+// WPC entry
+struct WPC_ENTRY
+{
+ char EntryName[WPC_DATA_ENTRY_SIZE]; // Entry name
+ void *Data; // Data
+ UINT Size; // Data size
+};
+
+// WPC packet
+struct WPC_PACKET
+{
+ PACK *Pack; // Pack (data body)
+ UCHAR Hash[SHA1_SIZE]; // Data hash
+ X *Cert; // Certificate
+ UCHAR Sign[128]; // Digital signature
+};
+
+// Reception callback
+typedef bool (WPC_RECV_CALLBACK)(void *param, UINT total_size, UINT current_size, BUF *recv_buf);
+
+// Function prototype
+void EncodeSafe64(char *dst, void *src, UINT src_size);
+UINT DecodeSafe64(void *dst, char *src, UINT src_strlen);
+void Base64ToSafe64(char *str);
+void Safe64ToBase64(char *str);
+bool ParseUrl(URL_DATA *data, char *str, bool is_post, char *referrer);
+void CreateUrl(char *url, UINT url_size, URL_DATA *data);
+void GetSystemInternetSetting(INTERNET_SETTING *setting);
+bool GetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type);
+BUF *HttpRequest(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash);
+BUF *HttpRequestEx(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash,
+ bool *cancel, UINT max_recv_size);
+BUF *HttpRequestEx2(URL_DATA *data, INTERNET_SETTING *setting,
+ UINT timeout_connect, UINT timeout_comm,
+ UINT *error_code, bool check_ssl_trust, char *post_data,
+ WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash,
+ bool *cancel, UINT max_recv_size, char *header_name, char *header_value);
+SOCK *WpcSockConnect(WPC_CONNECT *param, UINT *error_code, UINT timeout);
+SOCK *WpcSockConnectEx(WPC_CONNECT *param, UINT *error_code, UINT timeout, bool *cancel);
+SOCK *WpcSockConnect2(char *hostname, UINT port, INTERNET_SETTING *t, UINT *error_code, UINT timeout);
+INTERNET_SETTING *GetNullInternetSetting();
+void WpcAddDataEntry(BUF *b, char *name, void *data, UINT size);
+void WpcAddDataEntryBin(BUF *b, char *name, void *data, UINT size);
+void WpcFillEntryName(char *dst, char *name);
+LIST *WpcParseDataEntry(BUF *b);
+void WpcFreeDataEntryList(LIST *o);
+WPC_ENTRY *WpcFindDataEntry(LIST *o, char *name);
+BUF *WpcDataEntryToBuf(WPC_ENTRY *e);
+BUF *WpcGeneratePacket(PACK *pack, X *cert, K *key);
+bool WpcParsePacket(WPC_PACKET *packet, BUF *buf);
+void WpcFreePacket(WPC_PACKET *packet);
+PACK *WpcCall(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm,
+ char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash);
+PACK *WpcCallEx(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm,
+ char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash, bool *cancel, UINT max_recv_size);
+bool IsProxyPrivateIp(INTERNET_SETTING *s);
+
+#endif // WPC_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Cedar/netcfgn.h b/src/Cedar/netcfgn.h
new file mode 100644
index 00000000..796f32be
--- /dev/null
+++ b/src/Cedar/netcfgn.h
@@ -0,0 +1,1335 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0555 */
+/* Compiler settings for netcfgn.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the <rpcsal.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __netcfgn_h__
+#define __netcfgn_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __INetCfgPnpReconfigCallback_FWD_DEFINED__
+#define __INetCfgPnpReconfigCallback_FWD_DEFINED__
+typedef interface INetCfgPnpReconfigCallback INetCfgPnpReconfigCallback;
+#endif /* __INetCfgPnpReconfigCallback_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentControl_FWD_DEFINED__
+#define __INetCfgComponentControl_FWD_DEFINED__
+typedef interface INetCfgComponentControl INetCfgComponentControl;
+#endif /* __INetCfgComponentControl_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentSetup_FWD_DEFINED__
+#define __INetCfgComponentSetup_FWD_DEFINED__
+typedef interface INetCfgComponentSetup INetCfgComponentSetup;
+#endif /* __INetCfgComponentSetup_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentPropertyUi_FWD_DEFINED__
+#define __INetCfgComponentPropertyUi_FWD_DEFINED__
+typedef interface INetCfgComponentPropertyUi INetCfgComponentPropertyUi;
+#endif /* __INetCfgComponentPropertyUi_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentNotifyBinding_FWD_DEFINED__
+#define __INetCfgComponentNotifyBinding_FWD_DEFINED__
+typedef interface INetCfgComponentNotifyBinding INetCfgComponentNotifyBinding;
+#endif /* __INetCfgComponentNotifyBinding_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentNotifyGlobal_FWD_DEFINED__
+#define __INetCfgComponentNotifyGlobal_FWD_DEFINED__
+typedef interface INetCfgComponentNotifyGlobal INetCfgComponentNotifyGlobal;
+#endif /* __INetCfgComponentNotifyGlobal_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentUpperEdge_FWD_DEFINED__
+#define __INetCfgComponentUpperEdge_FWD_DEFINED__
+typedef interface INetCfgComponentUpperEdge INetCfgComponentUpperEdge;
+#endif /* __INetCfgComponentUpperEdge_FWD_DEFINED__ */
+
+
+#ifndef __INetLanConnectionUiInfo_FWD_DEFINED__
+#define __INetLanConnectionUiInfo_FWD_DEFINED__
+typedef interface INetLanConnectionUiInfo INetLanConnectionUiInfo;
+#endif /* __INetLanConnectionUiInfo_FWD_DEFINED__ */
+
+
+#ifndef __INetRasConnectionIpUiInfo_FWD_DEFINED__
+#define __INetRasConnectionIpUiInfo_FWD_DEFINED__
+typedef interface INetRasConnectionIpUiInfo INetRasConnectionIpUiInfo;
+#endif /* __INetRasConnectionIpUiInfo_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentSysPrep_FWD_DEFINED__
+#define __INetCfgComponentSysPrep_FWD_DEFINED__
+typedef interface INetCfgComponentSysPrep INetCfgComponentSysPrep;
+#endif /* __INetCfgComponentSysPrep_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "unknwn.h"
+#include "netcfgx.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_netcfgn_0000_0000 */
+/* [local] */
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+#if ( _MSC_VER >= 800 )
+#pragma warning(disable:4201)
+#endif
+
+
+extern RPC_IF_HANDLE __MIDL_itf_netcfgn_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_netcfgn_0000_0000_v0_0_s_ifspec;
+
+#ifndef __INetCfgPnpReconfigCallback_INTERFACE_DEFINED__
+#define __INetCfgPnpReconfigCallback_INTERFACE_DEFINED__
+
+/* interface INetCfgPnpReconfigCallback */
+/* [unique][uuid][object][local] */
+
+typedef /* [v1_enum] */
+enum tagNCPNP_RECONFIG_LAYER
+ { NCRL_NDIS = 1,
+ NCRL_TDI = 2
+ } NCPNP_RECONFIG_LAYER;
+
+
+EXTERN_C const IID IID_INetCfgPnpReconfigCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("8d84bd35-e227-11d2-b700-00a0c98a6a85")
+ INetCfgPnpReconfigCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SendPnpReconfig(
+ /* [annotation][in] */
+ __in NCPNP_RECONFIG_LAYER Layer,
+ /* [annotation][in] */
+ __in LPCWSTR pszwUpper,
+ /* [annotation][in] */
+ __in LPCWSTR pszwLower,
+ /* [annotation][in] */
+ __in_bcount(dwSizeOfData) PVOID pvData,
+ /* [annotation][in] */
+ __in DWORD dwSizeOfData) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgPnpReconfigCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgPnpReconfigCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgPnpReconfigCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgPnpReconfigCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SendPnpReconfig )(
+ INetCfgPnpReconfigCallback * This,
+ /* [annotation][in] */
+ __in NCPNP_RECONFIG_LAYER Layer,
+ /* [annotation][in] */
+ __in LPCWSTR pszwUpper,
+ /* [annotation][in] */
+ __in LPCWSTR pszwLower,
+ /* [annotation][in] */
+ __in_bcount(dwSizeOfData) PVOID pvData,
+ /* [annotation][in] */
+ __in DWORD dwSizeOfData);
+
+ END_INTERFACE
+ } INetCfgPnpReconfigCallbackVtbl;
+
+ interface INetCfgPnpReconfigCallback
+ {
+ CONST_VTBL struct INetCfgPnpReconfigCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgPnpReconfigCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgPnpReconfigCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgPnpReconfigCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgPnpReconfigCallback_SendPnpReconfig(This,Layer,pszwUpper,pszwLower,pvData,dwSizeOfData) \
+ ( (This)->lpVtbl -> SendPnpReconfig(This,Layer,pszwUpper,pszwLower,pvData,dwSizeOfData) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgPnpReconfigCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentControl_INTERFACE_DEFINED__
+#define __INetCfgComponentControl_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentControl */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgComponentControl;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238df-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentControl : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Initialize(
+ /* [annotation][in] */
+ __in INetCfgComponent *pIComp,
+ /* [annotation][in] */
+ __in INetCfg *pINetCfg,
+ /* [annotation][in] */
+ __in BOOL fInstalling) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ApplyRegistryChanges( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ApplyPnpChanges(
+ /* [annotation][in] */
+ __in INetCfgPnpReconfigCallback *pICallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CancelChanges( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentControlVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentControl * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentControl * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentControl * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Initialize )(
+ INetCfgComponentControl * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pIComp,
+ /* [annotation][in] */
+ __in INetCfg *pINetCfg,
+ /* [annotation][in] */
+ __in BOOL fInstalling);
+
+ HRESULT ( STDMETHODCALLTYPE *ApplyRegistryChanges )(
+ INetCfgComponentControl * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ApplyPnpChanges )(
+ INetCfgComponentControl * This,
+ /* [annotation][in] */
+ __in INetCfgPnpReconfigCallback *pICallback);
+
+ HRESULT ( STDMETHODCALLTYPE *CancelChanges )(
+ INetCfgComponentControl * This);
+
+ END_INTERFACE
+ } INetCfgComponentControlVtbl;
+
+ interface INetCfgComponentControl
+ {
+ CONST_VTBL struct INetCfgComponentControlVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentControl_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentControl_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentControl_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentControl_Initialize(This,pIComp,pINetCfg,fInstalling) \
+ ( (This)->lpVtbl -> Initialize(This,pIComp,pINetCfg,fInstalling) )
+
+#define INetCfgComponentControl_ApplyRegistryChanges(This) \
+ ( (This)->lpVtbl -> ApplyRegistryChanges(This) )
+
+#define INetCfgComponentControl_ApplyPnpChanges(This,pICallback) \
+ ( (This)->lpVtbl -> ApplyPnpChanges(This,pICallback) )
+
+#define INetCfgComponentControl_CancelChanges(This) \
+ ( (This)->lpVtbl -> CancelChanges(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentControl_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentSetup_INTERFACE_DEFINED__
+#define __INetCfgComponentSetup_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentSetup */
+/* [unique][uuid][object][local] */
+
+typedef /* [v1_enum] */
+enum tagNETWORK_INSTALL_TIME
+ { NSF_PRIMARYINSTALL = 0x1,
+ NSF_POSTSYSINSTALL = 0x2
+ } NETWORK_INSTALL_TIME;
+
+typedef /* [v1_enum] */
+enum tagNETWORK_UPGRADE_TYPE
+ { NSF_WIN16_UPGRADE = 0x10,
+ NSF_WIN95_UPGRADE = 0x20,
+ NSF_WINNT_WKS_UPGRADE = 0x40,
+ NSF_WINNT_SVR_UPGRADE = 0x80,
+ NSF_WINNT_SBS_UPGRADE = 0x100,
+ NSF_COMPONENT_UPDATE = 0x200
+ } NETWORK_UPGRADE_TYPE;
+
+
+EXTERN_C const IID IID_INetCfgComponentSetup;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238e3-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentSetup : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Install(
+ /* [annotation][in] */
+ __in DWORD dwSetupFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Upgrade(
+ /* [annotation][in] */
+ __in DWORD dwSetupFlags,
+ /* [annotation][in] */
+ __in DWORD dwUpgradeFomBuildNo) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ReadAnswerFile(
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerFile,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSections) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Removing( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentSetupVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentSetup * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentSetup * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentSetup * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Install )(
+ INetCfgComponentSetup * This,
+ /* [annotation][in] */
+ __in DWORD dwSetupFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *Upgrade )(
+ INetCfgComponentSetup * This,
+ /* [annotation][in] */
+ __in DWORD dwSetupFlags,
+ /* [annotation][in] */
+ __in DWORD dwUpgradeFomBuildNo);
+
+ HRESULT ( STDMETHODCALLTYPE *ReadAnswerFile )(
+ INetCfgComponentSetup * This,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerFile,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSections);
+
+ HRESULT ( STDMETHODCALLTYPE *Removing )(
+ INetCfgComponentSetup * This);
+
+ END_INTERFACE
+ } INetCfgComponentSetupVtbl;
+
+ interface INetCfgComponentSetup
+ {
+ CONST_VTBL struct INetCfgComponentSetupVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentSetup_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentSetup_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentSetup_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentSetup_Install(This,dwSetupFlags) \
+ ( (This)->lpVtbl -> Install(This,dwSetupFlags) )
+
+#define INetCfgComponentSetup_Upgrade(This,dwSetupFlags,dwUpgradeFomBuildNo) \
+ ( (This)->lpVtbl -> Upgrade(This,dwSetupFlags,dwUpgradeFomBuildNo) )
+
+#define INetCfgComponentSetup_ReadAnswerFile(This,pszwAnswerFile,pszwAnswerSections) \
+ ( (This)->lpVtbl -> ReadAnswerFile(This,pszwAnswerFile,pszwAnswerSections) )
+
+#define INetCfgComponentSetup_Removing(This) \
+ ( (This)->lpVtbl -> Removing(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentSetup_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentPropertyUi_INTERFACE_DEFINED__
+#define __INetCfgComponentPropertyUi_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentPropertyUi */
+/* [unique][uuid][object][local] */
+
+typedef /* [v1_enum] */
+enum tagDEFAULT_PAGES
+ { DPP_ADVANCED = 1
+ } DEFAULT_PAGES;
+
+
+EXTERN_C const IID IID_INetCfgComponentPropertyUi;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238e0-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentPropertyUi : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE QueryPropertyUi(
+ /* [annotation][in] */
+ __in IUnknown *pUnkReserved) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetContext(
+ /* [annotation][in] */
+ __in IUnknown *pUnkReserved) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MergePropPages(
+ /* [annotation][out][in] */
+ __inout DWORD *pdwDefPages,
+ /* [annotation][out] */
+ __out BYTE **pahpspPrivate,
+ /* [annotation][out] */
+ __out UINT *pcPages,
+ /* [annotation][in] */
+ __in HWND hwndParent,
+ /* [annotation][in] */
+ __in_opt LPCWSTR *pszStartPage) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ValidateProperties(
+ /* [annotation][in] */
+ __in HWND hwndSheet) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ApplyProperties( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CancelProperties( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentPropertyUiVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentPropertyUi * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentPropertyUi * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentPropertyUi * This);
+
+ HRESULT ( STDMETHODCALLTYPE *QueryPropertyUi )(
+ INetCfgComponentPropertyUi * This,
+ /* [annotation][in] */
+ __in IUnknown *pUnkReserved);
+
+ HRESULT ( STDMETHODCALLTYPE *SetContext )(
+ INetCfgComponentPropertyUi * This,
+ /* [annotation][in] */
+ __in IUnknown *pUnkReserved);
+
+ HRESULT ( STDMETHODCALLTYPE *MergePropPages )(
+ INetCfgComponentPropertyUi * This,
+ /* [annotation][out][in] */
+ __inout DWORD *pdwDefPages,
+ /* [annotation][out] */
+ __out BYTE **pahpspPrivate,
+ /* [annotation][out] */
+ __out UINT *pcPages,
+ /* [annotation][in] */
+ __in HWND hwndParent,
+ /* [annotation][in] */
+ __in_opt LPCWSTR *pszStartPage);
+
+ HRESULT ( STDMETHODCALLTYPE *ValidateProperties )(
+ INetCfgComponentPropertyUi * This,
+ /* [annotation][in] */
+ __in HWND hwndSheet);
+
+ HRESULT ( STDMETHODCALLTYPE *ApplyProperties )(
+ INetCfgComponentPropertyUi * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CancelProperties )(
+ INetCfgComponentPropertyUi * This);
+
+ END_INTERFACE
+ } INetCfgComponentPropertyUiVtbl;
+
+ interface INetCfgComponentPropertyUi
+ {
+ CONST_VTBL struct INetCfgComponentPropertyUiVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentPropertyUi_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentPropertyUi_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentPropertyUi_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentPropertyUi_QueryPropertyUi(This,pUnkReserved) \
+ ( (This)->lpVtbl -> QueryPropertyUi(This,pUnkReserved) )
+
+#define INetCfgComponentPropertyUi_SetContext(This,pUnkReserved) \
+ ( (This)->lpVtbl -> SetContext(This,pUnkReserved) )
+
+#define INetCfgComponentPropertyUi_MergePropPages(This,pdwDefPages,pahpspPrivate,pcPages,hwndParent,pszStartPage) \
+ ( (This)->lpVtbl -> MergePropPages(This,pdwDefPages,pahpspPrivate,pcPages,hwndParent,pszStartPage) )
+
+#define INetCfgComponentPropertyUi_ValidateProperties(This,hwndSheet) \
+ ( (This)->lpVtbl -> ValidateProperties(This,hwndSheet) )
+
+#define INetCfgComponentPropertyUi_ApplyProperties(This) \
+ ( (This)->lpVtbl -> ApplyProperties(This) )
+
+#define INetCfgComponentPropertyUi_CancelProperties(This) \
+ ( (This)->lpVtbl -> CancelProperties(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentPropertyUi_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentNotifyBinding_INTERFACE_DEFINED__
+#define __INetCfgComponentNotifyBinding_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentNotifyBinding */
+/* [unique][uuid][object][local] */
+
+typedef /* [v1_enum] */
+enum tagBIND_FLAGS1
+ { NCN_ADD = 0x1,
+ NCN_REMOVE = 0x2,
+ NCN_UPDATE = 0x4,
+ NCN_ENABLE = 0x10,
+ NCN_DISABLE = 0x20,
+ NCN_BINDING_PATH = 0x100,
+ NCN_PROPERTYCHANGE = 0x200,
+ NCN_NET = 0x10000,
+ NCN_NETTRANS = 0x20000,
+ NCN_NETCLIENT = 0x40000,
+ NCN_NETSERVICE = 0x80000
+ } BIND_FLAGS1;
+
+
+EXTERN_C const IID IID_INetCfgComponentNotifyBinding;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238e1-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentNotifyBinding : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE QueryBindingPath(
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE NotifyBindingPath(
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentNotifyBindingVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentNotifyBinding * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentNotifyBinding * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentNotifyBinding * This);
+
+ HRESULT ( STDMETHODCALLTYPE *QueryBindingPath )(
+ INetCfgComponentNotifyBinding * This,
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath);
+
+ HRESULT ( STDMETHODCALLTYPE *NotifyBindingPath )(
+ INetCfgComponentNotifyBinding * This,
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath);
+
+ END_INTERFACE
+ } INetCfgComponentNotifyBindingVtbl;
+
+ interface INetCfgComponentNotifyBinding
+ {
+ CONST_VTBL struct INetCfgComponentNotifyBindingVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentNotifyBinding_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentNotifyBinding_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentNotifyBinding_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentNotifyBinding_QueryBindingPath(This,dwChangeFlag,pIPath) \
+ ( (This)->lpVtbl -> QueryBindingPath(This,dwChangeFlag,pIPath) )
+
+#define INetCfgComponentNotifyBinding_NotifyBindingPath(This,dwChangeFlag,pIPath) \
+ ( (This)->lpVtbl -> NotifyBindingPath(This,dwChangeFlag,pIPath) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentNotifyBinding_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentNotifyGlobal_INTERFACE_DEFINED__
+#define __INetCfgComponentNotifyGlobal_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentNotifyGlobal */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgComponentNotifyGlobal;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238e2-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentNotifyGlobal : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetSupportedNotifications(
+ /* [annotation][out] */
+ __out DWORD *dwNotifications) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SysQueryBindingPath(
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SysNotifyBindingPath(
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SysNotifyComponent(
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgComponent *pIComp) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentNotifyGlobalVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentNotifyGlobal * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentNotifyGlobal * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentNotifyGlobal * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetSupportedNotifications )(
+ INetCfgComponentNotifyGlobal * This,
+ /* [annotation][out] */
+ __out DWORD *dwNotifications);
+
+ HRESULT ( STDMETHODCALLTYPE *SysQueryBindingPath )(
+ INetCfgComponentNotifyGlobal * This,
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath);
+
+ HRESULT ( STDMETHODCALLTYPE *SysNotifyBindingPath )(
+ INetCfgComponentNotifyGlobal * This,
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pIPath);
+
+ HRESULT ( STDMETHODCALLTYPE *SysNotifyComponent )(
+ INetCfgComponentNotifyGlobal * This,
+ /* [annotation][in] */
+ __in DWORD dwChangeFlag,
+ /* [annotation][in] */
+ __in INetCfgComponent *pIComp);
+
+ END_INTERFACE
+ } INetCfgComponentNotifyGlobalVtbl;
+
+ interface INetCfgComponentNotifyGlobal
+ {
+ CONST_VTBL struct INetCfgComponentNotifyGlobalVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentNotifyGlobal_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentNotifyGlobal_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentNotifyGlobal_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentNotifyGlobal_GetSupportedNotifications(This,dwNotifications) \
+ ( (This)->lpVtbl -> GetSupportedNotifications(This,dwNotifications) )
+
+#define INetCfgComponentNotifyGlobal_SysQueryBindingPath(This,dwChangeFlag,pIPath) \
+ ( (This)->lpVtbl -> SysQueryBindingPath(This,dwChangeFlag,pIPath) )
+
+#define INetCfgComponentNotifyGlobal_SysNotifyBindingPath(This,dwChangeFlag,pIPath) \
+ ( (This)->lpVtbl -> SysNotifyBindingPath(This,dwChangeFlag,pIPath) )
+
+#define INetCfgComponentNotifyGlobal_SysNotifyComponent(This,dwChangeFlag,pIComp) \
+ ( (This)->lpVtbl -> SysNotifyComponent(This,dwChangeFlag,pIComp) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentNotifyGlobal_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentUpperEdge_INTERFACE_DEFINED__
+#define __INetCfgComponentUpperEdge_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentUpperEdge */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgComponentUpperEdge;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("932238e4-bea1-11d0-9298-00c04fc99dcf")
+ INetCfgComponentUpperEdge : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetInterfaceIdsForAdapter(
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][out] */
+ __out DWORD *pdwNumInterfaces,
+ /* [annotation][out] */
+ __deref_out_opt GUID **ppguidInterfaceIds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddInterfacesToAdapter(
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][in] */
+ __in DWORD dwNumInterfaces) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveInterfacesFromAdapter(
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][in] */
+ __in DWORD dwNumInterfaces,
+ /* [annotation][in] */
+ __in const GUID *pguidInterfaceIds) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentUpperEdgeVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentUpperEdge * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentUpperEdge * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentUpperEdge * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInterfaceIdsForAdapter )(
+ INetCfgComponentUpperEdge * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][out] */
+ __out DWORD *pdwNumInterfaces,
+ /* [annotation][out] */
+ __deref_out_opt GUID **ppguidInterfaceIds);
+
+ HRESULT ( STDMETHODCALLTYPE *AddInterfacesToAdapter )(
+ INetCfgComponentUpperEdge * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][in] */
+ __in DWORD dwNumInterfaces);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveInterfacesFromAdapter )(
+ INetCfgComponentUpperEdge * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pAdapter,
+ /* [annotation][in] */
+ __in DWORD dwNumInterfaces,
+ /* [annotation][in] */
+ __in const GUID *pguidInterfaceIds);
+
+ END_INTERFACE
+ } INetCfgComponentUpperEdgeVtbl;
+
+ interface INetCfgComponentUpperEdge
+ {
+ CONST_VTBL struct INetCfgComponentUpperEdgeVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentUpperEdge_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentUpperEdge_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentUpperEdge_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentUpperEdge_GetInterfaceIdsForAdapter(This,pAdapter,pdwNumInterfaces,ppguidInterfaceIds) \
+ ( (This)->lpVtbl -> GetInterfaceIdsForAdapter(This,pAdapter,pdwNumInterfaces,ppguidInterfaceIds) )
+
+#define INetCfgComponentUpperEdge_AddInterfacesToAdapter(This,pAdapter,dwNumInterfaces) \
+ ( (This)->lpVtbl -> AddInterfacesToAdapter(This,pAdapter,dwNumInterfaces) )
+
+#define INetCfgComponentUpperEdge_RemoveInterfacesFromAdapter(This,pAdapter,dwNumInterfaces,pguidInterfaceIds) \
+ ( (This)->lpVtbl -> RemoveInterfacesFromAdapter(This,pAdapter,dwNumInterfaces,pguidInterfaceIds) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentUpperEdge_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetLanConnectionUiInfo_INTERFACE_DEFINED__
+#define __INetLanConnectionUiInfo_INTERFACE_DEFINED__
+
+/* interface INetLanConnectionUiInfo */
+/* [unique][uuid][object] */
+
+
+EXTERN_C const IID IID_INetLanConnectionUiInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C08956A6-1CD3-11D1-B1C5-00805FC1270E")
+ INetLanConnectionUiInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceGuid(
+ /* [out] */ __RPC__out GUID *pguid) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetLanConnectionUiInfoVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ __RPC__in INetLanConnectionUiInfo * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ __RPC__in INetLanConnectionUiInfo * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ __RPC__in INetLanConnectionUiInfo * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeviceGuid )(
+ __RPC__in INetLanConnectionUiInfo * This,
+ /* [out] */ __RPC__out GUID *pguid);
+
+ END_INTERFACE
+ } INetLanConnectionUiInfoVtbl;
+
+ interface INetLanConnectionUiInfo
+ {
+ CONST_VTBL struct INetLanConnectionUiInfoVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetLanConnectionUiInfo_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetLanConnectionUiInfo_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetLanConnectionUiInfo_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetLanConnectionUiInfo_GetDeviceGuid(This,pguid) \
+ ( (This)->lpVtbl -> GetDeviceGuid(This,pguid) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetLanConnectionUiInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetRasConnectionIpUiInfo_INTERFACE_DEFINED__
+#define __INetRasConnectionIpUiInfo_INTERFACE_DEFINED__
+
+/* interface INetRasConnectionIpUiInfo */
+/* [unique][uuid][object] */
+
+typedef
+enum tagRASCON_IPUI_FLAGS
+ { RCUIF_VPN = 0x1,
+ RCUIF_DEMAND_DIAL = 0x2,
+ RCUIF_NOT_ADMIN = 0x4,
+ RCUIF_USE_IPv4_STATICADDRESS = 0x8,
+ RCUIF_USE_IPv4_NAME_SERVERS = 0x10,
+ RCUIF_USE_IPv4_REMOTE_GATEWAY = 0x20,
+ RCUIF_USE_IPv4_EXPLICIT_METRIC = 0x40,
+ RCUIF_USE_HEADER_COMPRESSION = 0x80,
+ RCUIF_USE_DISABLE_REGISTER_DNS = 0x100,
+ RCUIF_USE_PRIVATE_DNS_SUFFIX = 0x200,
+ RCUIF_ENABLE_NBT = 0x400,
+ RCUIF_USE_IPv6_STATICADDRESS = 0x800,
+ RCUIF_USE_IPv6_NAME_SERVERS = 0x1000,
+ RCUIF_USE_IPv6_REMOTE_GATEWAY = 0x2000,
+ RCUIF_USE_IPv6_EXPLICIT_METRIC = 0x4000,
+ RCUIF_DISABLE_CLASS_BASED_ROUTE = 0x8000
+ } RASCON_UIINFO_FLAGS;
+
+typedef struct tagRASCON_IPUI
+ {
+ GUID guidConnection;
+ BOOL fIPv6Cfg;
+ DWORD dwFlags;
+ WCHAR pszwIpAddr[ 16 ];
+ WCHAR pszwDnsAddr[ 16 ];
+ WCHAR pszwDns2Addr[ 16 ];
+ WCHAR pszwWinsAddr[ 16 ];
+ WCHAR pszwWins2Addr[ 16 ];
+ WCHAR pszwDnsSuffix[ 256 ];
+ WCHAR pszwIpv6Addr[ 65 ];
+ DWORD dwIpv6PrefixLength;
+ WCHAR pszwIpv6DnsAddr[ 65 ];
+ WCHAR pszwIpv6Dns2Addr[ 65 ];
+ DWORD dwIPv4InfMetric;
+ DWORD dwIPv6InfMetric;
+ } RASCON_IPUI;
+
+
+EXTERN_C const IID IID_INetRasConnectionIpUiInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("FAEDCF58-31FE-11D1-AAD2-00805FC1270E")
+ INetRasConnectionIpUiInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetUiInfo(
+ /* [out] */ __RPC__out RASCON_IPUI *pInfo) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetRasConnectionIpUiInfoVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ __RPC__in INetRasConnectionIpUiInfo * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ __RPC__in INetRasConnectionIpUiInfo * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ __RPC__in INetRasConnectionIpUiInfo * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetUiInfo )(
+ __RPC__in INetRasConnectionIpUiInfo * This,
+ /* [out] */ __RPC__out RASCON_IPUI *pInfo);
+
+ END_INTERFACE
+ } INetRasConnectionIpUiInfoVtbl;
+
+ interface INetRasConnectionIpUiInfo
+ {
+ CONST_VTBL struct INetRasConnectionIpUiInfoVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetRasConnectionIpUiInfo_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetRasConnectionIpUiInfo_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetRasConnectionIpUiInfo_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetRasConnectionIpUiInfo_GetUiInfo(This,pInfo) \
+ ( (This)->lpVtbl -> GetUiInfo(This,pInfo) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetRasConnectionIpUiInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentSysPrep_INTERFACE_DEFINED__
+#define __INetCfgComponentSysPrep_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentSysPrep */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgComponentSysPrep;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE9A-306E-11D1-AACF-00805FC1270E")
+ INetCfgComponentSysPrep : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SaveAdapterParameters(
+ /* [annotation][in] */
+ __in INetCfgSysPrep *pncsp,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSections,
+ /* [annotation][in] */
+ __in GUID *pAdapterInstanceGuid) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RestoreAdapterParameters(
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerFile,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSection,
+ /* [annotation][in] */
+ __in GUID *pAdapterInstanceGuid) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentSysPrepVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentSysPrep * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentSysPrep * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentSysPrep * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SaveAdapterParameters )(
+ INetCfgComponentSysPrep * This,
+ /* [annotation][in] */
+ __in INetCfgSysPrep *pncsp,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSections,
+ /* [annotation][in] */
+ __in GUID *pAdapterInstanceGuid);
+
+ HRESULT ( STDMETHODCALLTYPE *RestoreAdapterParameters )(
+ INetCfgComponentSysPrep * This,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerFile,
+ /* [annotation][in] */
+ __in LPCWSTR pszwAnswerSection,
+ /* [annotation][in] */
+ __in GUID *pAdapterInstanceGuid);
+
+ END_INTERFACE
+ } INetCfgComponentSysPrepVtbl;
+
+ interface INetCfgComponentSysPrep
+ {
+ CONST_VTBL struct INetCfgComponentSysPrepVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentSysPrep_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentSysPrep_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentSysPrep_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentSysPrep_SaveAdapterParameters(This,pncsp,pszwAnswerSections,pAdapterInstanceGuid) \
+ ( (This)->lpVtbl -> SaveAdapterParameters(This,pncsp,pszwAnswerSections,pAdapterInstanceGuid) )
+
+#define INetCfgComponentSysPrep_RestoreAdapterParameters(This,pszwAnswerFile,pszwAnswerSection,pAdapterInstanceGuid) \
+ ( (This)->lpVtbl -> RestoreAdapterParameters(This,pszwAnswerFile,pszwAnswerSection,pAdapterInstanceGuid) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentSysPrep_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/Cedar/netcfgx.h b/src/Cedar/netcfgx.h
new file mode 100644
index 00000000..59c9f52c
--- /dev/null
+++ b/src/Cedar/netcfgx.h
@@ -0,0 +1,1941 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0555 */
+/* Compiler settings for netcfgx.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the <rpcsal.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __netcfgx_h__
+#define __netcfgx_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IEnumNetCfgBindingInterface_FWD_DEFINED__
+#define __IEnumNetCfgBindingInterface_FWD_DEFINED__
+typedef interface IEnumNetCfgBindingInterface IEnumNetCfgBindingInterface;
+#endif /* __IEnumNetCfgBindingInterface_FWD_DEFINED__ */
+
+
+#ifndef __IEnumNetCfgBindingPath_FWD_DEFINED__
+#define __IEnumNetCfgBindingPath_FWD_DEFINED__
+typedef interface IEnumNetCfgBindingPath IEnumNetCfgBindingPath;
+#endif /* __IEnumNetCfgBindingPath_FWD_DEFINED__ */
+
+
+#ifndef __IEnumNetCfgComponent_FWD_DEFINED__
+#define __IEnumNetCfgComponent_FWD_DEFINED__
+typedef interface IEnumNetCfgComponent IEnumNetCfgComponent;
+#endif /* __IEnumNetCfgComponent_FWD_DEFINED__ */
+
+
+#ifndef __INetCfg_FWD_DEFINED__
+#define __INetCfg_FWD_DEFINED__
+typedef interface INetCfg INetCfg;
+#endif /* __INetCfg_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgLock_FWD_DEFINED__
+#define __INetCfgLock_FWD_DEFINED__
+typedef interface INetCfgLock INetCfgLock;
+#endif /* __INetCfgLock_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgBindingInterface_FWD_DEFINED__
+#define __INetCfgBindingInterface_FWD_DEFINED__
+typedef interface INetCfgBindingInterface INetCfgBindingInterface;
+#endif /* __INetCfgBindingInterface_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgBindingPath_FWD_DEFINED__
+#define __INetCfgBindingPath_FWD_DEFINED__
+typedef interface INetCfgBindingPath INetCfgBindingPath;
+#endif /* __INetCfgBindingPath_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgClass_FWD_DEFINED__
+#define __INetCfgClass_FWD_DEFINED__
+typedef interface INetCfgClass INetCfgClass;
+#endif /* __INetCfgClass_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgClassSetup_FWD_DEFINED__
+#define __INetCfgClassSetup_FWD_DEFINED__
+typedef interface INetCfgClassSetup INetCfgClassSetup;
+#endif /* __INetCfgClassSetup_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponent_FWD_DEFINED__
+#define __INetCfgComponent_FWD_DEFINED__
+typedef interface INetCfgComponent INetCfgComponent;
+#endif /* __INetCfgComponent_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgComponentBindings_FWD_DEFINED__
+#define __INetCfgComponentBindings_FWD_DEFINED__
+typedef interface INetCfgComponentBindings INetCfgComponentBindings;
+#endif /* __INetCfgComponentBindings_FWD_DEFINED__ */
+
+
+#ifndef __INetCfgSysPrep_FWD_DEFINED__
+#define __INetCfgSysPrep_FWD_DEFINED__
+typedef interface INetCfgSysPrep INetCfgSysPrep;
+#endif /* __INetCfgSysPrep_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "unknwn.h"
+#include "prsht.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_netcfgx_0000_0000 */
+/* [local] */
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+#if ( _MSC_VER >= 800 )
+#pragma warning(disable:4201)
+#endif
+
+EXTERN_C const CLSID CLSID_CNetCfg;
+
+#define NETCFG_E_ALREADY_INITIALIZED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA020)
+#define NETCFG_E_NOT_INITIALIZED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA021)
+#define NETCFG_E_IN_USE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA022)
+#define NETCFG_E_NO_WRITE_LOCK MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA024)
+#define NETCFG_E_NEED_REBOOT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA025)
+#define NETCFG_E_ACTIVE_RAS_CONNECTIONS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA026)
+#define NETCFG_E_ADAPTER_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA027)
+#define NETCFG_E_COMPONENT_REMOVED_PENDING_REBOOT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA028)
+#define NETCFG_E_MAX_FILTER_LIMIT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA029)
+#define NETCFG_S_REBOOT MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA020)
+#define NETCFG_S_DISABLE_QUERY MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA022)
+#define NETCFG_S_STILL_REFERENCED MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA023)
+#define NETCFG_S_CAUSED_SETUP_CHANGE MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA024)
+#define NETCFG_S_COMMIT_NOW MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA025)
+
+#define NETCFG_CLIENT_CID_MS_MSClient TEXT("ms_msclient")
+#define NETCFG_SERVICE_CID_MS_SERVER TEXT("ms_server")
+#define NETCFG_SERVICE_CID_MS_NETBIOS TEXT("ms_netbios")
+#define NETCFG_SERVICE_CID_MS_PSCHED TEXT("ms_pschedpc")
+#define NETCFG_SERVICE_CID_MS_WLBS TEXT("ms_wlbs")
+#define NETCFG_TRANS_CID_MS_APPLETALK TEXT("ms_appletalk")
+#define NETCFG_TRANS_CID_MS_NETBEUI TEXT("ms_netbeui")
+#define NETCFG_TRANS_CID_MS_NETMON TEXT("ms_netmon")
+#define NETCFG_TRANS_CID_MS_NWIPX TEXT("ms_nwipx")
+#define NETCFG_TRANS_CID_MS_NWSPX TEXT("ms_nwspx")
+#define NETCFG_TRANS_CID_MS_TCPIP TEXT("ms_tcpip")
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_netcfgx_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_netcfgx_0000_0000_v0_0_s_ifspec;
+
+#ifndef __IEnumNetCfgBindingInterface_INTERFACE_DEFINED__
+#define __IEnumNetCfgBindingInterface_INTERFACE_DEFINED__
+
+/* interface IEnumNetCfgBindingInterface */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_IEnumNetCfgBindingInterface;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE90-306E-11D1-AACF-00805FC1270E")
+ IEnumNetCfgBindingInterface : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgBindingInterface **rgelt,
+ /* [annotation][out] */
+ __out_opt ULONG *pceltFetched) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Skip(
+ /* [annotation][in] */
+ __in ULONG celt) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Clone(
+ /* [annotation][out] */
+ __out IEnumNetCfgBindingInterface **ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumNetCfgBindingInterfaceVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IEnumNetCfgBindingInterface * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IEnumNetCfgBindingInterface * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IEnumNetCfgBindingInterface * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IEnumNetCfgBindingInterface * This,
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgBindingInterface **rgelt,
+ /* [annotation][out] */
+ __out_opt ULONG *pceltFetched);
+
+ HRESULT ( STDMETHODCALLTYPE *Skip )(
+ IEnumNetCfgBindingInterface * This,
+ /* [annotation][in] */
+ __in ULONG celt);
+
+ HRESULT ( STDMETHODCALLTYPE *Reset )(
+ IEnumNetCfgBindingInterface * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Clone )(
+ IEnumNetCfgBindingInterface * This,
+ /* [annotation][out] */
+ __out IEnumNetCfgBindingInterface **ppenum);
+
+ END_INTERFACE
+ } IEnumNetCfgBindingInterfaceVtbl;
+
+ interface IEnumNetCfgBindingInterface
+ {
+ CONST_VTBL struct IEnumNetCfgBindingInterfaceVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumNetCfgBindingInterface_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IEnumNetCfgBindingInterface_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IEnumNetCfgBindingInterface_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IEnumNetCfgBindingInterface_Next(This,celt,rgelt,pceltFetched) \
+ ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) )
+
+#define IEnumNetCfgBindingInterface_Skip(This,celt) \
+ ( (This)->lpVtbl -> Skip(This,celt) )
+
+#define IEnumNetCfgBindingInterface_Reset(This) \
+ ( (This)->lpVtbl -> Reset(This) )
+
+#define IEnumNetCfgBindingInterface_Clone(This,ppenum) \
+ ( (This)->lpVtbl -> Clone(This,ppenum) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IEnumNetCfgBindingInterface_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumNetCfgBindingPath_INTERFACE_DEFINED__
+#define __IEnumNetCfgBindingPath_INTERFACE_DEFINED__
+
+/* interface IEnumNetCfgBindingPath */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_IEnumNetCfgBindingPath;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE91-306E-11D1-AACF-00805FC1270E")
+ IEnumNetCfgBindingPath : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgBindingPath **rgelt,
+ /* [annotation][out] */
+ __out ULONG *pceltFetched) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Skip(
+ /* [annotation][in] */
+ __in ULONG celt) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Clone(
+ /* [annotation][out] */
+ __out IEnumNetCfgBindingPath **ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumNetCfgBindingPathVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IEnumNetCfgBindingPath * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IEnumNetCfgBindingPath * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IEnumNetCfgBindingPath * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IEnumNetCfgBindingPath * This,
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgBindingPath **rgelt,
+ /* [annotation][out] */
+ __out ULONG *pceltFetched);
+
+ HRESULT ( STDMETHODCALLTYPE *Skip )(
+ IEnumNetCfgBindingPath * This,
+ /* [annotation][in] */
+ __in ULONG celt);
+
+ HRESULT ( STDMETHODCALLTYPE *Reset )(
+ IEnumNetCfgBindingPath * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Clone )(
+ IEnumNetCfgBindingPath * This,
+ /* [annotation][out] */
+ __out IEnumNetCfgBindingPath **ppenum);
+
+ END_INTERFACE
+ } IEnumNetCfgBindingPathVtbl;
+
+ interface IEnumNetCfgBindingPath
+ {
+ CONST_VTBL struct IEnumNetCfgBindingPathVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumNetCfgBindingPath_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IEnumNetCfgBindingPath_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IEnumNetCfgBindingPath_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IEnumNetCfgBindingPath_Next(This,celt,rgelt,pceltFetched) \
+ ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) )
+
+#define IEnumNetCfgBindingPath_Skip(This,celt) \
+ ( (This)->lpVtbl -> Skip(This,celt) )
+
+#define IEnumNetCfgBindingPath_Reset(This) \
+ ( (This)->lpVtbl -> Reset(This) )
+
+#define IEnumNetCfgBindingPath_Clone(This,ppenum) \
+ ( (This)->lpVtbl -> Clone(This,ppenum) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IEnumNetCfgBindingPath_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumNetCfgComponent_INTERFACE_DEFINED__
+#define __IEnumNetCfgComponent_INTERFACE_DEFINED__
+
+/* interface IEnumNetCfgComponent */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_IEnumNetCfgComponent;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE92-306E-11D1-AACF-00805FC1270E")
+ IEnumNetCfgComponent : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgComponent **rgelt,
+ /* [annotation][out] */
+ __out ULONG *pceltFetched) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Skip(
+ /* [annotation][in] */
+ __in ULONG celt) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Clone(
+ /* [annotation][out] */
+ __out IEnumNetCfgComponent **ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumNetCfgComponentVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IEnumNetCfgComponent * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IEnumNetCfgComponent * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IEnumNetCfgComponent * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IEnumNetCfgComponent * This,
+ /* [annotation][in] */
+ __in ULONG celt,
+ /* [annotation][length_is][size_is][out] */
+ __out_ecount(celt) INetCfgComponent **rgelt,
+ /* [annotation][out] */
+ __out ULONG *pceltFetched);
+
+ HRESULT ( STDMETHODCALLTYPE *Skip )(
+ IEnumNetCfgComponent * This,
+ /* [annotation][in] */
+ __in ULONG celt);
+
+ HRESULT ( STDMETHODCALLTYPE *Reset )(
+ IEnumNetCfgComponent * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Clone )(
+ IEnumNetCfgComponent * This,
+ /* [annotation][out] */
+ __out IEnumNetCfgComponent **ppenum);
+
+ END_INTERFACE
+ } IEnumNetCfgComponentVtbl;
+
+ interface IEnumNetCfgComponent
+ {
+ CONST_VTBL struct IEnumNetCfgComponentVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumNetCfgComponent_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IEnumNetCfgComponent_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IEnumNetCfgComponent_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IEnumNetCfgComponent_Next(This,celt,rgelt,pceltFetched) \
+ ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) )
+
+#define IEnumNetCfgComponent_Skip(This,celt) \
+ ( (This)->lpVtbl -> Skip(This,celt) )
+
+#define IEnumNetCfgComponent_Reset(This) \
+ ( (This)->lpVtbl -> Reset(This) )
+
+#define IEnumNetCfgComponent_Clone(This,ppenum) \
+ ( (This)->lpVtbl -> Clone(This,ppenum) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IEnumNetCfgComponent_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfg_INTERFACE_DEFINED__
+#define __INetCfg_INTERFACE_DEFINED__
+
+/* interface INetCfg */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfg;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE93-306E-11D1-AACF-00805FC1270E")
+ INetCfg : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Initialize(
+ /* [annotation][in] */
+ __in PVOID pvReserved) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Uninitialize( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Apply( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Cancel( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnumComponents(
+ /* [annotation][in] */
+ __in const GUID *pguidClass,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgComponent **ppenumComponent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FindComponent(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwInfId,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **pComponent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE QueryNetCfgClass(
+ /* [annotation][in] */
+ __in const GUID *pguidClass,
+ /* [annotation][in] */
+ __in REFIID riid,
+ /* [annotation][iid_is][out] */
+ __deref_out_opt void **ppvObject) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfg * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfg * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfg * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Initialize )(
+ INetCfg * This,
+ /* [annotation][in] */
+ __in PVOID pvReserved);
+
+ HRESULT ( STDMETHODCALLTYPE *Uninitialize )(
+ INetCfg * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Apply )(
+ INetCfg * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Cancel )(
+ INetCfg * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EnumComponents )(
+ INetCfg * This,
+ /* [annotation][in] */
+ __in const GUID *pguidClass,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgComponent **ppenumComponent);
+
+ HRESULT ( STDMETHODCALLTYPE *FindComponent )(
+ INetCfg * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwInfId,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **pComponent);
+
+ HRESULT ( STDMETHODCALLTYPE *QueryNetCfgClass )(
+ INetCfg * This,
+ /* [annotation][in] */
+ __in const GUID *pguidClass,
+ /* [annotation][in] */
+ __in REFIID riid,
+ /* [annotation][iid_is][out] */
+ __deref_out_opt void **ppvObject);
+
+ END_INTERFACE
+ } INetCfgVtbl;
+
+ interface INetCfg
+ {
+ CONST_VTBL struct INetCfgVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfg_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfg_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfg_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfg_Initialize(This,pvReserved) \
+ ( (This)->lpVtbl -> Initialize(This,pvReserved) )
+
+#define INetCfg_Uninitialize(This) \
+ ( (This)->lpVtbl -> Uninitialize(This) )
+
+#define INetCfg_Apply(This) \
+ ( (This)->lpVtbl -> Apply(This) )
+
+#define INetCfg_Cancel(This) \
+ ( (This)->lpVtbl -> Cancel(This) )
+
+#define INetCfg_EnumComponents(This,pguidClass,ppenumComponent) \
+ ( (This)->lpVtbl -> EnumComponents(This,pguidClass,ppenumComponent) )
+
+#define INetCfg_FindComponent(This,pszwInfId,pComponent) \
+ ( (This)->lpVtbl -> FindComponent(This,pszwInfId,pComponent) )
+
+#define INetCfg_QueryNetCfgClass(This,pguidClass,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryNetCfgClass(This,pguidClass,riid,ppvObject) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfg_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgLock_INTERFACE_DEFINED__
+#define __INetCfgLock_INTERFACE_DEFINED__
+
+/* interface INetCfgLock */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgLock;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE9F-306E-11D1-AACF-00805FC1270E")
+ INetCfgLock : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AcquireWriteLock(
+ /* [annotation][in] */
+ __in DWORD cmsTimeout,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwClientDescription,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwClientDescription) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ReleaseWriteLock( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsWriteLocked(
+ /* [annotation][string][out] */
+ __deref_out __nullterminated LPWSTR *ppszwClientDescription) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgLockVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgLock * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgLock * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgLock * This);
+
+ HRESULT ( STDMETHODCALLTYPE *AcquireWriteLock )(
+ INetCfgLock * This,
+ /* [annotation][in] */
+ __in DWORD cmsTimeout,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwClientDescription,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwClientDescription);
+
+ HRESULT ( STDMETHODCALLTYPE *ReleaseWriteLock )(
+ INetCfgLock * This);
+
+ HRESULT ( STDMETHODCALLTYPE *IsWriteLocked )(
+ INetCfgLock * This,
+ /* [annotation][string][out] */
+ __deref_out __nullterminated LPWSTR *ppszwClientDescription);
+
+ END_INTERFACE
+ } INetCfgLockVtbl;
+
+ interface INetCfgLock
+ {
+ CONST_VTBL struct INetCfgLockVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgLock_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgLock_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgLock_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgLock_AcquireWriteLock(This,cmsTimeout,pszwClientDescription,ppszwClientDescription) \
+ ( (This)->lpVtbl -> AcquireWriteLock(This,cmsTimeout,pszwClientDescription,ppszwClientDescription) )
+
+#define INetCfgLock_ReleaseWriteLock(This) \
+ ( (This)->lpVtbl -> ReleaseWriteLock(This) )
+
+#define INetCfgLock_IsWriteLocked(This,ppszwClientDescription) \
+ ( (This)->lpVtbl -> IsWriteLocked(This,ppszwClientDescription) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgLock_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgBindingInterface_INTERFACE_DEFINED__
+#define __INetCfgBindingInterface_INTERFACE_DEFINED__
+
+/* interface INetCfgBindingInterface */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgBindingInterface;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE94-306E-11D1-AACF-00805FC1270E")
+ INetCfgBindingInterface : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [annotation][string][out] */
+ __deref_out LPWSTR *ppszwInterfaceName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetUpperComponent(
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetLowerComponent(
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgBindingInterfaceVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgBindingInterface * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgBindingInterface * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgBindingInterface * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ INetCfgBindingInterface * This,
+ /* [annotation][string][out] */
+ __deref_out LPWSTR *ppszwInterfaceName);
+
+ HRESULT ( STDMETHODCALLTYPE *GetUpperComponent )(
+ INetCfgBindingInterface * This,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *GetLowerComponent )(
+ INetCfgBindingInterface * This,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem);
+
+ END_INTERFACE
+ } INetCfgBindingInterfaceVtbl;
+
+ interface INetCfgBindingInterface
+ {
+ CONST_VTBL struct INetCfgBindingInterfaceVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgBindingInterface_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgBindingInterface_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgBindingInterface_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgBindingInterface_GetName(This,ppszwInterfaceName) \
+ ( (This)->lpVtbl -> GetName(This,ppszwInterfaceName) )
+
+#define INetCfgBindingInterface_GetUpperComponent(This,ppnccItem) \
+ ( (This)->lpVtbl -> GetUpperComponent(This,ppnccItem) )
+
+#define INetCfgBindingInterface_GetLowerComponent(This,ppnccItem) \
+ ( (This)->lpVtbl -> GetLowerComponent(This,ppnccItem) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgBindingInterface_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgBindingPath_INTERFACE_DEFINED__
+#define __INetCfgBindingPath_INTERFACE_DEFINED__
+
+/* interface INetCfgBindingPath */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgBindingPath;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE96-306E-11D1-AACF-00805FC1270E")
+ INetCfgBindingPath : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE IsSamePathAs(
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pPath) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsSubPathOf(
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pPath) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsEnabled( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Enable(
+ /* [annotation][in] */
+ __in BOOL fEnable) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPathToken(
+ /* [annotation][string][out] */
+ __deref_out __nullterminated LPWSTR *ppszwPathToken) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetOwner(
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppComponent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDepth(
+ /* [annotation][out] */
+ __out ULONG *pcInterfaces) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnumBindingInterfaces(
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgBindingInterface **ppenumInterface) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgBindingPathVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgBindingPath * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgBindingPath * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgBindingPath * This);
+
+ HRESULT ( STDMETHODCALLTYPE *IsSamePathAs )(
+ INetCfgBindingPath * This,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pPath);
+
+ HRESULT ( STDMETHODCALLTYPE *IsSubPathOf )(
+ INetCfgBindingPath * This,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pPath);
+
+ HRESULT ( STDMETHODCALLTYPE *IsEnabled )(
+ INetCfgBindingPath * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Enable )(
+ INetCfgBindingPath * This,
+ /* [annotation][in] */
+ __in BOOL fEnable);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPathToken )(
+ INetCfgBindingPath * This,
+ /* [annotation][string][out] */
+ __deref_out __nullterminated LPWSTR *ppszwPathToken);
+
+ HRESULT ( STDMETHODCALLTYPE *GetOwner )(
+ INetCfgBindingPath * This,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppComponent);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDepth )(
+ INetCfgBindingPath * This,
+ /* [annotation][out] */
+ __out ULONG *pcInterfaces);
+
+ HRESULT ( STDMETHODCALLTYPE *EnumBindingInterfaces )(
+ INetCfgBindingPath * This,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgBindingInterface **ppenumInterface);
+
+ END_INTERFACE
+ } INetCfgBindingPathVtbl;
+
+ interface INetCfgBindingPath
+ {
+ CONST_VTBL struct INetCfgBindingPathVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgBindingPath_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgBindingPath_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgBindingPath_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgBindingPath_IsSamePathAs(This,pPath) \
+ ( (This)->lpVtbl -> IsSamePathAs(This,pPath) )
+
+#define INetCfgBindingPath_IsSubPathOf(This,pPath) \
+ ( (This)->lpVtbl -> IsSubPathOf(This,pPath) )
+
+#define INetCfgBindingPath_IsEnabled(This) \
+ ( (This)->lpVtbl -> IsEnabled(This) )
+
+#define INetCfgBindingPath_Enable(This,fEnable) \
+ ( (This)->lpVtbl -> Enable(This,fEnable) )
+
+#define INetCfgBindingPath_GetPathToken(This,ppszwPathToken) \
+ ( (This)->lpVtbl -> GetPathToken(This,ppszwPathToken) )
+
+#define INetCfgBindingPath_GetOwner(This,ppComponent) \
+ ( (This)->lpVtbl -> GetOwner(This,ppComponent) )
+
+#define INetCfgBindingPath_GetDepth(This,pcInterfaces) \
+ ( (This)->lpVtbl -> GetDepth(This,pcInterfaces) )
+
+#define INetCfgBindingPath_EnumBindingInterfaces(This,ppenumInterface) \
+ ( (This)->lpVtbl -> EnumBindingInterfaces(This,ppenumInterface) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgBindingPath_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgClass_INTERFACE_DEFINED__
+#define __INetCfgClass_INTERFACE_DEFINED__
+
+/* interface INetCfgClass */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgClass;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE97-306E-11D1-AACF-00805FC1270E")
+ INetCfgClass : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE FindComponent(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwInfId,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnumComponents(
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgComponent **ppenumComponent) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgClassVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgClass * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgClass * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgClass * This);
+
+ HRESULT ( STDMETHODCALLTYPE *FindComponent )(
+ INetCfgClass * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pszwInfId,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *EnumComponents )(
+ INetCfgClass * This,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgComponent **ppenumComponent);
+
+ END_INTERFACE
+ } INetCfgClassVtbl;
+
+ interface INetCfgClass
+ {
+ CONST_VTBL struct INetCfgClassVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgClass_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgClass_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgClass_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgClass_FindComponent(This,pszwInfId,ppnccItem) \
+ ( (This)->lpVtbl -> FindComponent(This,pszwInfId,ppnccItem) )
+
+#define INetCfgClass_EnumComponents(This,ppenumComponent) \
+ ( (This)->lpVtbl -> EnumComponents(This,ppenumComponent) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgClass_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgClassSetup_INTERFACE_DEFINED__
+#define __INetCfgClassSetup_INTERFACE_DEFINED__
+
+/* interface INetCfgClassSetup */
+/* [unique][uuid][object][local] */
+
+typedef
+enum tagOBO_TOKEN_TYPE
+ { OBO_USER = 1,
+ OBO_COMPONENT = 2,
+ OBO_SOFTWARE = 3
+ } OBO_TOKEN_TYPE;
+
+typedef struct tagOBO_TOKEN
+ {
+ OBO_TOKEN_TYPE Type;
+ INetCfgComponent *pncc;
+ LPCWSTR pszwManufacturer;
+ LPCWSTR pszwProduct;
+ LPCWSTR pszwDisplayName;
+ BOOL fRegistered;
+ } OBO_TOKEN;
+
+
+EXTERN_C const IID IID_INetCfgClassSetup;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE9D-306E-11D1-AACF-00805FC1270E")
+ INetCfgClassSetup : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SelectAndInstall(
+ /* [annotation][in] */
+ __in HWND hwndParent,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Install(
+ /* [annotation][string][in] */
+ __in LPCWSTR pszwInfId,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][in] */
+ __in_opt DWORD dwSetupFlags,
+ /* [annotation][in] */
+ __in_opt DWORD dwUpgradeFromBuildNo,
+ /* [annotation][string][in] */
+ __in_opt LPCWSTR pszwAnswerFile,
+ /* [annotation][string][in] */
+ __in_opt LPCWSTR pszwAnswerSections,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeInstall(
+ /* [annotation][in] */
+ __in INetCfgComponent *pComponent,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][out] */
+ __deref_out_opt LPWSTR *pmszwRefs) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgClassSetupVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgClassSetup * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgClassSetup * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgClassSetup * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SelectAndInstall )(
+ INetCfgClassSetup * This,
+ /* [annotation][in] */
+ __in HWND hwndParent,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *Install )(
+ INetCfgClassSetup * This,
+ /* [annotation][string][in] */
+ __in LPCWSTR pszwInfId,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][in] */
+ __in_opt DWORD dwSetupFlags,
+ /* [annotation][in] */
+ __in_opt DWORD dwUpgradeFromBuildNo,
+ /* [annotation][string][in] */
+ __in_opt LPCWSTR pszwAnswerFile,
+ /* [annotation][string][in] */
+ __in_opt LPCWSTR pszwAnswerSections,
+ /* [annotation][out] */
+ __deref_out_opt INetCfgComponent **ppnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *DeInstall )(
+ INetCfgClassSetup * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pComponent,
+ /* [annotation][in] */
+ __in_opt OBO_TOKEN *pOboToken,
+ /* [annotation][out] */
+ __deref_out_opt LPWSTR *pmszwRefs);
+
+ END_INTERFACE
+ } INetCfgClassSetupVtbl;
+
+ interface INetCfgClassSetup
+ {
+ CONST_VTBL struct INetCfgClassSetupVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgClassSetup_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgClassSetup_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgClassSetup_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgClassSetup_SelectAndInstall(This,hwndParent,pOboToken,ppnccItem) \
+ ( (This)->lpVtbl -> SelectAndInstall(This,hwndParent,pOboToken,ppnccItem) )
+
+#define INetCfgClassSetup_Install(This,pszwInfId,pOboToken,dwSetupFlags,dwUpgradeFromBuildNo,pszwAnswerFile,pszwAnswerSections,ppnccItem) \
+ ( (This)->lpVtbl -> Install(This,pszwInfId,pOboToken,dwSetupFlags,dwUpgradeFromBuildNo,pszwAnswerFile,pszwAnswerSections,ppnccItem) )
+
+#define INetCfgClassSetup_DeInstall(This,pComponent,pOboToken,pmszwRefs) \
+ ( (This)->lpVtbl -> DeInstall(This,pComponent,pOboToken,pmszwRefs) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgClassSetup_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponent_INTERFACE_DEFINED__
+#define __INetCfgComponent_INTERFACE_DEFINED__
+
+/* interface INetCfgComponent */
+/* [unique][uuid][object][local] */
+
+typedef
+enum tagCOMPONENT_CHARACTERISTICS
+ { NCF_VIRTUAL = 0x1,
+ NCF_SOFTWARE_ENUMERATED = 0x2,
+ NCF_PHYSICAL = 0x4,
+ NCF_HIDDEN = 0x8,
+ NCF_NO_SERVICE = 0x10,
+ NCF_NOT_USER_REMOVABLE = 0x20,
+ NCF_MULTIPORT_INSTANCED_ADAPTER = 0x40,
+ NCF_HAS_UI = 0x80,
+ NCF_SINGLE_INSTANCE = 0x100,
+ NCF_FILTER = 0x400,
+ NCF_DONTEXPOSELOWER = 0x1000,
+ NCF_HIDE_BINDING = 0x2000,
+ NCF_NDIS_PROTOCOL = 0x4000,
+ NCF_FIXED_BINDING = 0x20000,
+ NCF_LW_FILTER = 0x40000
+ } COMPONENT_CHARACTERISTICS;
+
+typedef
+enum tagNCRP_FLAGS
+ { NCRP_QUERY_PROPERTY_UI = 0x1,
+ NCRP_SHOW_PROPERTY_UI = 0x2
+ } NCRP_FLAGS;
+
+
+EXTERN_C const IID IID_INetCfgComponent;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE99-306E-11D1-AACF-00805FC1270E")
+ INetCfgComponent : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayName(
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwDisplayName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetDisplayName(
+ /* [annotation][string][in] */
+ __in LPCWSTR pszwDisplayName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHelpText(
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *pszwHelpText) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetId(
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwId) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCharacteristics(
+ /* [annotation][out] */
+ __out LPDWORD pdwCharacteristics) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInstanceGuid(
+ /* [annotation][out] */
+ __out_opt GUID *pGuid) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPnpDevNodeId(
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwDevNodeId) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetClassGuid(
+ /* [annotation][out] */
+ __out_opt GUID *pGuid) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBindName(
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwBindName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceStatus(
+ /* [annotation][out] */
+ __out ULONG *pulStatus) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE OpenParamKey(
+ /* [annotation][out] */
+ __deref_out_opt HKEY *phkey) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RaisePropertyUi(
+ /* [annotation][in] */
+ __in_opt HWND hwndParent,
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][in] */
+ __in_opt IUnknown *punkContext) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponent * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponent * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponent * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayName )(
+ INetCfgComponent * This,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwDisplayName);
+
+ HRESULT ( STDMETHODCALLTYPE *SetDisplayName )(
+ INetCfgComponent * This,
+ /* [annotation][string][in] */
+ __in LPCWSTR pszwDisplayName);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHelpText )(
+ INetCfgComponent * This,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *pszwHelpText);
+
+ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ INetCfgComponent * This,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwId);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCharacteristics )(
+ INetCfgComponent * This,
+ /* [annotation][out] */
+ __out LPDWORD pdwCharacteristics);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInstanceGuid )(
+ INetCfgComponent * This,
+ /* [annotation][out] */
+ __out_opt GUID *pGuid);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPnpDevNodeId )(
+ INetCfgComponent * This,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwDevNodeId);
+
+ HRESULT ( STDMETHODCALLTYPE *GetClassGuid )(
+ INetCfgComponent * This,
+ /* [annotation][out] */
+ __out_opt GUID *pGuid);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBindName )(
+ INetCfgComponent * This,
+ /* [annotation][string][out] */
+ __deref_out_opt LPWSTR *ppszwBindName);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeviceStatus )(
+ INetCfgComponent * This,
+ /* [annotation][out] */
+ __out ULONG *pulStatus);
+
+ HRESULT ( STDMETHODCALLTYPE *OpenParamKey )(
+ INetCfgComponent * This,
+ /* [annotation][out] */
+ __deref_out_opt HKEY *phkey);
+
+ HRESULT ( STDMETHODCALLTYPE *RaisePropertyUi )(
+ INetCfgComponent * This,
+ /* [annotation][in] */
+ __in_opt HWND hwndParent,
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][in] */
+ __in_opt IUnknown *punkContext);
+
+ END_INTERFACE
+ } INetCfgComponentVtbl;
+
+ interface INetCfgComponent
+ {
+ CONST_VTBL struct INetCfgComponentVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponent_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponent_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponent_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponent_GetDisplayName(This,ppszwDisplayName) \
+ ( (This)->lpVtbl -> GetDisplayName(This,ppszwDisplayName) )
+
+#define INetCfgComponent_SetDisplayName(This,pszwDisplayName) \
+ ( (This)->lpVtbl -> SetDisplayName(This,pszwDisplayName) )
+
+#define INetCfgComponent_GetHelpText(This,pszwHelpText) \
+ ( (This)->lpVtbl -> GetHelpText(This,pszwHelpText) )
+
+#define INetCfgComponent_GetId(This,ppszwId) \
+ ( (This)->lpVtbl -> GetId(This,ppszwId) )
+
+#define INetCfgComponent_GetCharacteristics(This,pdwCharacteristics) \
+ ( (This)->lpVtbl -> GetCharacteristics(This,pdwCharacteristics) )
+
+#define INetCfgComponent_GetInstanceGuid(This,pGuid) \
+ ( (This)->lpVtbl -> GetInstanceGuid(This,pGuid) )
+
+#define INetCfgComponent_GetPnpDevNodeId(This,ppszwDevNodeId) \
+ ( (This)->lpVtbl -> GetPnpDevNodeId(This,ppszwDevNodeId) )
+
+#define INetCfgComponent_GetClassGuid(This,pGuid) \
+ ( (This)->lpVtbl -> GetClassGuid(This,pGuid) )
+
+#define INetCfgComponent_GetBindName(This,ppszwBindName) \
+ ( (This)->lpVtbl -> GetBindName(This,ppszwBindName) )
+
+#define INetCfgComponent_GetDeviceStatus(This,pulStatus) \
+ ( (This)->lpVtbl -> GetDeviceStatus(This,pulStatus) )
+
+#define INetCfgComponent_OpenParamKey(This,phkey) \
+ ( (This)->lpVtbl -> OpenParamKey(This,phkey) )
+
+#define INetCfgComponent_RaisePropertyUi(This,hwndParent,dwFlags,punkContext) \
+ ( (This)->lpVtbl -> RaisePropertyUi(This,hwndParent,dwFlags,punkContext) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponent_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgComponentBindings_INTERFACE_DEFINED__
+#define __INetCfgComponentBindings_INTERFACE_DEFINED__
+
+/* interface INetCfgComponentBindings */
+/* [unique][uuid][object][local] */
+
+typedef
+enum tagSUPPORTS_BINDING_INTERFACE_FLAGS
+ { NCF_LOWER = 0x1,
+ NCF_UPPER = 0x2
+ } SUPPORTS_BINDING_INTERFACE_FLAGS;
+
+typedef
+enum tagENUM_BINDING_PATHS_FLAGS
+ { EBP_ABOVE = 0x1,
+ EBP_BELOW = 0x2
+ } ENUM_BINDING_PATHS_FLAGS;
+
+
+EXTERN_C const IID IID_INetCfgComponentBindings;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE9E-306E-11D1-AACF-00805FC1270E")
+ INetCfgComponentBindings : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE BindTo(
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE UnbindFrom(
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SupportsBindingInterface(
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][in] */
+ __in __nullterminated LPCWSTR pszwInterfaceName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsBoundTo(
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsBindableTo(
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnumBindingPaths(
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgBindingPath **ppIEnum) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MoveBefore(
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemSrc,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemDest) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MoveAfter(
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemSrc,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemDest) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgComponentBindingsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgComponentBindings * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgComponentBindings * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgComponentBindings * This);
+
+ HRESULT ( STDMETHODCALLTYPE *BindTo )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *UnbindFrom )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *SupportsBindingInterface )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][in] */
+ __in __nullterminated LPCWSTR pszwInterfaceName);
+
+ HRESULT ( STDMETHODCALLTYPE *IsBoundTo )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *IsBindableTo )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgComponent *pnccItem);
+
+ HRESULT ( STDMETHODCALLTYPE *EnumBindingPaths )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in DWORD dwFlags,
+ /* [annotation][out] */
+ __deref_out_opt IEnumNetCfgBindingPath **ppIEnum);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveBefore )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemSrc,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemDest);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveAfter )(
+ INetCfgComponentBindings * This,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemSrc,
+ /* [annotation][in] */
+ __in INetCfgBindingPath *pncbItemDest);
+
+ END_INTERFACE
+ } INetCfgComponentBindingsVtbl;
+
+ interface INetCfgComponentBindings
+ {
+ CONST_VTBL struct INetCfgComponentBindingsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgComponentBindings_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgComponentBindings_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgComponentBindings_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgComponentBindings_BindTo(This,pnccItem) \
+ ( (This)->lpVtbl -> BindTo(This,pnccItem) )
+
+#define INetCfgComponentBindings_UnbindFrom(This,pnccItem) \
+ ( (This)->lpVtbl -> UnbindFrom(This,pnccItem) )
+
+#define INetCfgComponentBindings_SupportsBindingInterface(This,dwFlags,pszwInterfaceName) \
+ ( (This)->lpVtbl -> SupportsBindingInterface(This,dwFlags,pszwInterfaceName) )
+
+#define INetCfgComponentBindings_IsBoundTo(This,pnccItem) \
+ ( (This)->lpVtbl -> IsBoundTo(This,pnccItem) )
+
+#define INetCfgComponentBindings_IsBindableTo(This,pnccItem) \
+ ( (This)->lpVtbl -> IsBindableTo(This,pnccItem) )
+
+#define INetCfgComponentBindings_EnumBindingPaths(This,dwFlags,ppIEnum) \
+ ( (This)->lpVtbl -> EnumBindingPaths(This,dwFlags,ppIEnum) )
+
+#define INetCfgComponentBindings_MoveBefore(This,pncbItemSrc,pncbItemDest) \
+ ( (This)->lpVtbl -> MoveBefore(This,pncbItemSrc,pncbItemDest) )
+
+#define INetCfgComponentBindings_MoveAfter(This,pncbItemSrc,pncbItemDest) \
+ ( (This)->lpVtbl -> MoveAfter(This,pncbItemSrc,pncbItemDest) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgComponentBindings_INTERFACE_DEFINED__ */
+
+
+#ifndef __INetCfgSysPrep_INTERFACE_DEFINED__
+#define __INetCfgSysPrep_INTERFACE_DEFINED__
+
+/* interface INetCfgSysPrep */
+/* [unique][uuid][object][local] */
+
+
+EXTERN_C const IID IID_INetCfgSysPrep;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C0E8AE98-306E-11D1-AACF-00805FC1270E")
+ INetCfgSysPrep : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE HrSetupSetFirstDword(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [in] */ DWORD dwValue) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE HrSetupSetFirstString(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszValue) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE HrSetupSetFirstStringAsBool(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [in] */ BOOL fValue) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE HrSetupSetFirstMultiSzField(
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [annotation][in] */
+ __in __nullterminated LPCWSTR pmszValue) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct INetCfgSysPrepVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ INetCfgSysPrep * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ INetCfgSysPrep * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ INetCfgSysPrep * This);
+
+ HRESULT ( STDMETHODCALLTYPE *HrSetupSetFirstDword )(
+ INetCfgSysPrep * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [in] */ DWORD dwValue);
+
+ HRESULT ( STDMETHODCALLTYPE *HrSetupSetFirstString )(
+ INetCfgSysPrep * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszValue);
+
+ HRESULT ( STDMETHODCALLTYPE *HrSetupSetFirstStringAsBool )(
+ INetCfgSysPrep * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [in] */ BOOL fValue);
+
+ HRESULT ( STDMETHODCALLTYPE *HrSetupSetFirstMultiSzField )(
+ INetCfgSysPrep * This,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszSection,
+ /* [annotation][string][in] */
+ __in __nullterminated LPCWSTR pwszKey,
+ /* [annotation][in] */
+ __in __nullterminated LPCWSTR pmszValue);
+
+ END_INTERFACE
+ } INetCfgSysPrepVtbl;
+
+ interface INetCfgSysPrep
+ {
+ CONST_VTBL struct INetCfgSysPrepVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define INetCfgSysPrep_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define INetCfgSysPrep_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define INetCfgSysPrep_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define INetCfgSysPrep_HrSetupSetFirstDword(This,pwszSection,pwszKey,dwValue) \
+ ( (This)->lpVtbl -> HrSetupSetFirstDword(This,pwszSection,pwszKey,dwValue) )
+
+#define INetCfgSysPrep_HrSetupSetFirstString(This,pwszSection,pwszKey,pwszValue) \
+ ( (This)->lpVtbl -> HrSetupSetFirstString(This,pwszSection,pwszKey,pwszValue) )
+
+#define INetCfgSysPrep_HrSetupSetFirstStringAsBool(This,pwszSection,pwszKey,fValue) \
+ ( (This)->lpVtbl -> HrSetupSetFirstStringAsBool(This,pwszSection,pwszKey,fValue) )
+
+#define INetCfgSysPrep_HrSetupSetFirstMultiSzField(This,pwszSection,pwszKey,pmszValue) \
+ ( (This)->lpVtbl -> HrSetupSetFirstMultiSzField(This,pwszSection,pwszKey,pmszValue) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __INetCfgSysPrep_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/Cedar/winpcap/Devioctl.h b/src/Cedar/winpcap/Devioctl.h
new file mode 100644
index 00000000..af8784bf
--- /dev/null
+++ b/src/Cedar/winpcap/Devioctl.h
@@ -0,0 +1,90 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+ Copyright (c) 1992-1993 Microsoft Corporation
+ Module Name:
+ devioctl.h
+ Revision History:
+ -- */
+// begin_winioctl
+#ifndef _DEVIOCTL_
+#define _DEVIOCTL_
+// begin_ntddk begin_nthal begin_ntifs
+//
+// Define the various device type values. Note that values used by Microsoft
+// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
+// by customers.
+//
+#define DEVICE_TYPE ULONG
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+//
+// Macro definition for defining IOCTL and FSCTL function control codes. Note
+// that function codes 0-2047 are reserved for Microsoft Corporation, and
+// 2048-4095 are reserved for customers.
+//
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+//
+// Define the method codes for how buffers are passed for I/O and FS controls
+//
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+//
+// Define the access check value for any access
+//
+//
+// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+// constants *MUST* always be in sync.
+//
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+// end_ntddk end_nthal end_ntifs
+#endif // _DEVIOCTL_
+// end_winioctl
diff --git a/src/Cedar/winpcap/Gnuc.h b/src/Cedar/winpcap/Gnuc.h
new file mode 100644
index 00000000..b7cfb59c
--- /dev/null
+++ b/src/Cedar/winpcap/Gnuc.h
@@ -0,0 +1,46 @@
+/* @(#) $Header: /tcpdump/master/libpcap/Win32/Include/Gnuc.h,v 1.1 2002/08/01 08:33:05 risso Exp $ (LBL) */
+
+/* Define __P() macro, if necessary */
+
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifndef __cplusplus
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+#endif
+
+/*
+ * Handle new and old "dead" routine prototypes
+ *
+ * For example:
+ *
+ * __dead void foo(void) __attribute__((volatile));
+ *
+ */
+#ifdef __GNUC__
+#ifndef __dead
+#define __dead volatile
+#endif
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
+#else
+#ifndef __dead
+#define __dead
+#endif
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
diff --git a/src/Cedar/winpcap/Ntddndis.h b/src/Cedar/winpcap/Ntddndis.h
new file mode 100644
index 00000000..0b629806
--- /dev/null
+++ b/src/Cedar/winpcap/Ntddndis.h
@@ -0,0 +1,1400 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+ Copyright (c) 1990-1993 Microsoft Corporation
+ Module Name:
+ ntddndis.h
+ Abstract:
+ This is the include file that defines all constants and types for
+ accessing the Network driver interface device.
+ Author:
+ Steve Wood (stevewo) 27-May-1990
+ Revision History:
+ Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0.
+ Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures
+ Kyle Brandon (kyleb) 09/24/96 added general co ndis oids.
+ -- */
+#ifndef _NTDDNDIS_
+#define _NTDDNDIS_
+//
+// Device Name - this string is the name of the device. It is the name
+// that should be passed to NtOpenFile when accessing the device.
+//
+// Note: For devices that support multiple units, it should be suffixed
+// with the Ascii representation of the unit number.
+//
+#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN"
+//
+// NtDeviceIoControlFile IoControlCode values for this device.
+//
+// Warning: Remember that the low two bits of the code specify how the
+// buffers are passed to the driver!
+//
+#define _NDIS_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED )
+#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED )
+#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED )
+#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED )
+#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED )
+#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT )
+//
+// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for
+// this device.
+//
+//
+// This is the type of an NDIS OID value.
+//
+typedef ULONG NDIS_OID, *PNDIS_OID;
+//
+// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed
+// together (no padding is required since statistics all have
+// four or eight bytes of data).
+//
+typedef struct _NDIS_STATISTICS_VALUE {
+ NDIS_OID Oid;
+ ULONG DataLength;
+ UCHAR Data[1]; // variable length
+
+} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE;
+
+//
+// Structure used by TRANSLATE_NAME IOCTL
+//
+typedef struct _NET_PNP_ID {
+ ULONG ClassId;
+ ULONG Token;
+} NET_PNP_ID, *PNET_PNP_ID;
+
+typedef struct _NET_PNP_TRANSLATE_LIST {
+ ULONG BytesNeeded;
+ NET_PNP_ID IdArray[ANYSIZE_ARRAY];
+} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST;
+
+//
+// Structure used to define a self-contained variable data structure
+//
+typedef struct _NDIS_VAR_DATA_DESC {
+ USHORT Length; // # of octects of data
+
+ USHORT MaximumLength; // # of octects available
+
+ LONG Offset; // Offset of data relative to the descriptor
+
+} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC;
+
+//
+// Object Identifiers used by NdisRequest Query/Set Information
+//
+//
+// General Objects
+//
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+//
+// These are connection-oriented general OIDs.
+// These replace the above OIDs for connection-oriented media.
+//
+#define OID_GEN_CO_SUPPORTED_LIST 0x00010101
+#define OID_GEN_CO_HARDWARE_STATUS 0x00010102
+#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_CO_MEDIA_IN_USE 0x00010104
+#define OID_GEN_CO_LINK_SPEED 0x00010105
+#define OID_GEN_CO_VENDOR_ID 0x00010106
+#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
+#define OID_GEN_CO_DRIVER_VERSION 0x00010108
+#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
+#define OID_GEN_CO_MAC_OPTIONS 0x0001010A
+#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
+#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
+#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
+#define OID_GEN_CO_GET_TIME_CAPS 0x00010201
+#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202
+//
+// These are connection-oriented statistics OIDs.
+//
+#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101
+#define OID_GEN_CO_RCV_PDUS_OK 0x00020102
+#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
+#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
+#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
+#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201
+#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
+#define OID_GEN_CO_BYTES_XMIT 0x00020203
+#define OID_GEN_CO_BYTES_RCV 0x00020204
+#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
+#define OID_GEN_CO_NETCARD_LOAD 0x00020206
+//
+// These are objects for Connection-oriented media call-managers and are not
+// valid for ndis drivers. Under construction.
+//
+#define OID_CO_ADD_PVC 0xFF000001
+#define OID_CO_DELETE_PVC 0xFF000002
+#define OID_CO_GET_CALL_INFORMATION 0xFF000003
+#define OID_CO_ADD_ADDRESS 0xFF000004
+#define OID_CO_DELETE_ADDRESS 0xFF000005
+#define OID_CO_GET_ADDRESSES 0xFF000006
+#define OID_CO_ADDRESS_CHANGE 0xFF000007
+#define OID_CO_SIGNALING_ENABLED 0xFF000008
+#define OID_CO_SIGNALING_DISABLED 0xFF000009
+//
+// 802.3 Objects (Ethernet)
+//
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+//
+//
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+//
+// 802.5 Objects (Token-Ring)
+//
+#define OID_802_5_PERMANENT_ADDRESS 0x02010101
+#define OID_802_5_CURRENT_ADDRESS 0x02010102
+#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103
+#define OID_802_5_CURRENT_GROUP 0x02010104
+#define OID_802_5_LAST_OPEN_STATUS 0x02010105
+#define OID_802_5_CURRENT_RING_STATUS 0x02010106
+#define OID_802_5_CURRENT_RING_STATE 0x02010107
+#define OID_802_5_LINE_ERRORS 0x02020101
+#define OID_802_5_LOST_FRAMES 0x02020102
+#define OID_802_5_BURST_ERRORS 0x02020201
+#define OID_802_5_AC_ERRORS 0x02020202
+#define OID_802_5_ABORT_DELIMETERS 0x02020203
+#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204
+#define OID_802_5_FREQUENCY_ERRORS 0x02020205
+#define OID_802_5_TOKEN_ERRORS 0x02020206
+#define OID_802_5_INTERNAL_ERRORS 0x02020207
+//
+// FDDI Objects
+//
+#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101
+#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102
+#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103
+#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104
+#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105
+#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106
+#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107
+#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108
+#define OID_FDDI_ATTACHMENT_TYPE 0x03020101
+#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102
+#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103
+#define OID_FDDI_FRAME_ERRORS 0x03020104
+#define OID_FDDI_FRAMES_LOST 0x03020105
+#define OID_FDDI_RING_MGT_STATE 0x03020106
+#define OID_FDDI_LCT_FAILURES 0x03020107
+#define OID_FDDI_LEM_REJECTS 0x03020108
+#define OID_FDDI_LCONNECTION_STATE 0x03020109
+#define OID_FDDI_SMT_STATION_ID 0x03030201
+#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202
+#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203
+#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204
+#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205
+#define OID_FDDI_SMT_USER_DATA 0x03030206
+#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207
+#define OID_FDDI_SMT_MAC_CT 0x03030208
+#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209
+#define OID_FDDI_SMT_MASTER_CT 0x0303020A
+#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B
+#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C
+#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D
+#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E
+#define OID_FDDI_SMT_T_NOTIFY 0x0303020F
+#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210
+#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211
+#define OID_FDDI_SMT_PORT_INDEXES 0x03030212
+#define OID_FDDI_SMT_MAC_INDEXES 0x03030213
+#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214
+#define OID_FDDI_SMT_ECM_STATE 0x03030215
+#define OID_FDDI_SMT_CF_STATE 0x03030216
+#define OID_FDDI_SMT_HOLD_STATE 0x03030217
+#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218
+#define OID_FDDI_SMT_STATION_STATUS 0x03030219
+#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A
+#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B
+#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C
+#define OID_FDDI_SMT_SET_COUNT 0x0303021D
+#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E
+#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F
+#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220
+#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221
+#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222
+#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223
+#define OID_FDDI_MAC_CURRENT_PATH 0x03030224
+#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225
+#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226
+#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227
+#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228
+#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229
+#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A
+#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B
+#define OID_FDDI_MAC_INDEX 0x0303022C
+#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D
+#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E
+#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F
+#define OID_FDDI_MAC_T_REQ 0x03030230
+#define OID_FDDI_MAC_T_NEG 0x03030231
+#define OID_FDDI_MAC_T_MAX 0x03030232
+#define OID_FDDI_MAC_TVX_VALUE 0x03030233
+#define OID_FDDI_MAC_T_PRI0 0x03030234
+#define OID_FDDI_MAC_T_PRI1 0x03030235
+#define OID_FDDI_MAC_T_PRI2 0x03030236
+#define OID_FDDI_MAC_T_PRI3 0x03030237
+#define OID_FDDI_MAC_T_PRI4 0x03030238
+#define OID_FDDI_MAC_T_PRI5 0x03030239
+#define OID_FDDI_MAC_T_PRI6 0x0303023A
+#define OID_FDDI_MAC_FRAME_CT 0x0303023B
+#define OID_FDDI_MAC_COPIED_CT 0x0303023C
+#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D
+#define OID_FDDI_MAC_TOKEN_CT 0x0303023E
+#define OID_FDDI_MAC_ERROR_CT 0x0303023F
+#define OID_FDDI_MAC_LOST_CT 0x03030240
+#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241
+#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242
+#define OID_FDDI_MAC_LATE_CT 0x03030243
+#define OID_FDDI_MAC_RING_OP_CT 0x03030244
+#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245
+#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246
+#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247
+#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248
+#define OID_FDDI_MAC_RMT_STATE 0x03030249
+#define OID_FDDI_MAC_DA_FLAG 0x0303024A
+#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B
+#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C
+#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D
+#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E
+#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F
+#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250
+#define OID_FDDI_PATH_INDEX 0x03030251
+#define OID_FDDI_PATH_RING_LATENCY 0x03030252
+#define OID_FDDI_PATH_TRACE_STATUS 0x03030253
+#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254
+#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255
+#define OID_FDDI_PATH_CONFIGURATION 0x03030256
+#define OID_FDDI_PATH_T_R_MODE 0x03030257
+#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258
+#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259
+#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A
+#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B
+#define OID_FDDI_PORT_MY_TYPE 0x0303025C
+#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D
+#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E
+#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F
+#define OID_FDDI_PORT_CURRENT_PATH 0x03030260
+#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261
+#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262
+#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263
+#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264
+#define OID_FDDI_PORT_PMD_CLASS 0x03030265
+#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266
+#define OID_FDDI_PORT_INDEX 0x03030267
+#define OID_FDDI_PORT_MAINT_LS 0x03030268
+#define OID_FDDI_PORT_BS_FLAG 0x03030269
+#define OID_FDDI_PORT_PC_LS 0x0303026A
+#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B
+#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C
+#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D
+#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E
+#define OID_FDDI_PORT_LEM_CT 0x0303026F
+#define OID_FDDI_PORT_LER_CUTOFF 0x03030270
+#define OID_FDDI_PORT_LER_ALARM 0x03030271
+#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272
+#define OID_FDDI_PORT_PCM_STATE 0x03030273
+#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274
+#define OID_FDDI_PORT_LER_FLAG 0x03030275
+#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276
+#define OID_FDDI_SMT_STATION_ACTION 0x03030277
+#define OID_FDDI_PORT_ACTION 0x03030278
+#define OID_FDDI_IF_DESCR 0x03030279
+#define OID_FDDI_IF_TYPE 0x0303027A
+#define OID_FDDI_IF_MTU 0x0303027B
+#define OID_FDDI_IF_SPEED 0x0303027C
+#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D
+#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E
+#define OID_FDDI_IF_OPER_STATUS 0x0303027F
+#define OID_FDDI_IF_LAST_CHANGE 0x03030280
+#define OID_FDDI_IF_IN_OCTETS 0x03030281
+#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282
+#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283
+#define OID_FDDI_IF_IN_DISCARDS 0x03030284
+#define OID_FDDI_IF_IN_ERRORS 0x03030285
+#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286
+#define OID_FDDI_IF_OUT_OCTETS 0x03030287
+#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288
+#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289
+#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A
+#define OID_FDDI_IF_OUT_ERRORS 0x0303028B
+#define OID_FDDI_IF_OUT_QLEN 0x0303028C
+#define OID_FDDI_IF_SPECIFIC 0x0303028D
+//
+// WAN objects
+//
+#define OID_WAN_PERMANENT_ADDRESS 0x04010101
+#define OID_WAN_CURRENT_ADDRESS 0x04010102
+#define OID_WAN_QUALITY_OF_SERVICE 0x04010103
+#define OID_WAN_PROTOCOL_TYPE 0x04010104
+#define OID_WAN_MEDIUM_SUBTYPE 0x04010105
+#define OID_WAN_HEADER_FORMAT 0x04010106
+#define OID_WAN_GET_INFO 0x04010107
+#define OID_WAN_SET_LINK_INFO 0x04010108
+#define OID_WAN_GET_LINK_INFO 0x04010109
+#define OID_WAN_LINE_COUNT 0x0401010A
+#define OID_WAN_GET_BRIDGE_INFO 0x0401020A
+#define OID_WAN_SET_BRIDGE_INFO 0x0401020B
+#define OID_WAN_GET_COMP_INFO 0x0401020C
+#define OID_WAN_SET_COMP_INFO 0x0401020D
+#define OID_WAN_GET_STATS_INFO 0x0401020E
+//
+// LocalTalk objects
+//
+#define OID_LTALK_CURRENT_NODE_ID 0x05010102
+#define OID_LTALK_IN_BROADCASTS 0x05020101
+#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102
+#define OID_LTALK_OUT_NO_HANDLERS 0x05020201
+#define OID_LTALK_COLLISIONS 0x05020202
+#define OID_LTALK_DEFERS 0x05020203
+#define OID_LTALK_NO_DATA_ERRORS 0x05020204
+#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205
+#define OID_LTALK_FCS_ERRORS 0x05020206
+//
+// Arcnet objects
+//
+#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101
+#define OID_ARCNET_CURRENT_ADDRESS 0x06010102
+#define OID_ARCNET_RECONFIGURATIONS 0x06020201
+//
+// TAPI objects
+//
+#define OID_TAPI_ACCEPT 0x07030101
+#define OID_TAPI_ANSWER 0x07030102
+#define OID_TAPI_CLOSE 0x07030103
+#define OID_TAPI_CLOSE_CALL 0x07030104
+#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105
+#define OID_TAPI_CONFIG_DIALOG 0x07030106
+#define OID_TAPI_DEV_SPECIFIC 0x07030107
+#define OID_TAPI_DIAL 0x07030108
+#define OID_TAPI_DROP 0x07030109
+#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A
+#define OID_TAPI_GET_ADDRESS_ID 0x0703010B
+#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C
+#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D
+#define OID_TAPI_GET_CALL_INFO 0x0703010E
+#define OID_TAPI_GET_CALL_STATUS 0x0703010F
+#define OID_TAPI_GET_DEV_CAPS 0x07030110
+#define OID_TAPI_GET_DEV_CONFIG 0x07030111
+#define OID_TAPI_GET_EXTENSION_ID 0x07030112
+#define OID_TAPI_GET_ID 0x07030113
+#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114
+#define OID_TAPI_MAKE_CALL 0x07030115
+#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116
+#define OID_TAPI_OPEN 0x07030117
+#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118
+#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119
+#define OID_TAPI_SECURE_CALL 0x0703011A
+#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B
+#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C
+#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D
+#define OID_TAPI_SET_CALL_PARAMS 0x0703011E
+#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F
+#define OID_TAPI_SET_DEV_CONFIG 0x07030120
+#define OID_TAPI_SET_MEDIA_MODE 0x07030121
+#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122
+//
+// ATM Connection Oriented Ndis
+//
+#define OID_ATM_SUPPORTED_VC_RATES 0x08010101
+#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102
+#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103
+#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104
+#define OID_ATM_MAX_ACTIVE_VCS 0x08010105
+#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106
+#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107
+#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108
+#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109
+#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A
+#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B
+#define OID_ATM_SIGNALING_VPIVCI 0x08010201
+#define OID_ATM_ASSIGNED_VPI 0x08010202
+#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203
+#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204
+#define OID_ATM_ILMI_VPIVCI 0x08010205
+#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206
+#define OID_ATM_GET_NEAREST_FLOW 0x08010207
+#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208
+//
+// ATM specific statistics OIDs.
+//
+#define OID_ATM_RCV_CELLS_OK 0x08020101
+#define OID_ATM_XMIT_CELLS_OK 0x08020102
+#define OID_ATM_RCV_CELLS_DROPPED 0x08020103
+#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201
+#define OID_ATM_CELLS_HEC_ERROR 0x08020202
+#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203
+//
+// PCCA (Wireless) object
+//
+//
+// All WirelessWAN devices must support the following OIDs
+//
+#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101
+#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102
+#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103
+#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104
+#define OID_WW_GEN_INDICATION_REQUEST 0x09010105
+#define OID_WW_GEN_DEVICE_INFO 0x09010106
+#define OID_WW_GEN_OPERATION_MODE 0x09010107
+#define OID_WW_GEN_LOCK_STATUS 0x09010108
+#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109
+#define OID_WW_GEN_NETWORK_ID 0x0901010A
+#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B
+#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C
+#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D
+#define OID_WW_GEN_BASESTATION_ID 0x0901010E
+#define OID_WW_GEN_CHANNEL_ID 0x0901010F
+#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110
+#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111
+#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112
+#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113
+#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114
+#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115
+#define OID_WW_GEN_LATENCY 0x09010116
+#define OID_WW_GEN_BATTERY_LEVEL 0x09010117
+#define OID_WW_GEN_EXTERNAL_POWER 0x09010118
+//
+// Network Dependent OIDs - Mobitex:
+//
+#define OID_WW_MBX_SUBADDR 0x09050101
+// OID 0x09050102 is reserved and may not be used
+#define OID_WW_MBX_FLEXLIST 0x09050103
+#define OID_WW_MBX_GROUPLIST 0x09050104
+#define OID_WW_MBX_TRAFFIC_AREA 0x09050105
+#define OID_WW_MBX_LIVE_DIE 0x09050106
+#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107
+//
+// Network Dependent OIDs - Pinpoint:
+//
+#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101
+#define OID_WW_PIN_LAST_LOCATION 0x09090102
+#define OID_WW_PIN_LOC_FIX 0x09090103
+//
+// Network Dependent - CDPD:
+//
+#define OID_WW_CDPD_SPNI 0x090D0101
+#define OID_WW_CDPD_WASI 0x090D0102
+#define OID_WW_CDPD_AREA_COLOR 0x090D0103
+#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104
+#define OID_WW_CDPD_EID 0x090D0105
+#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106
+#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107
+#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108
+#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109
+#define OID_WW_CDPD_NEI 0x090D010A
+#define OID_WW_CDPD_NEI_STATE 0x090D010B
+#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C
+#define OID_WW_CDPD_SLEEP_MODE 0x090D010D
+#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E
+#define OID_WW_CDPD_TEI 0x090D010F
+#define OID_WW_CDPD_RSSI 0x090D0110
+//
+// Network Dependent - Ardis:
+//
+#define OID_WW_ARD_SNDCP 0x09110101
+#define OID_WW_ARD_TMLY_MSG 0x09110102
+#define OID_WW_ARD_DATAGRAM 0x09110103
+//
+// Network Dependent - DataTac:
+//
+#define OID_WW_TAC_COMPRESSION 0x09150101
+#define OID_WW_TAC_SET_CONFIG 0x09150102
+#define OID_WW_TAC_GET_STATUS 0x09150103
+#define OID_WW_TAC_USER_HEADER 0x09150104
+//
+// Network Dependent - Metricom:
+//
+#define OID_WW_MET_FUNCTION 0x09190101
+//
+// IRDA objects
+//
+#define OID_IRDA_RECEIVING 0x0A010100
+#define OID_IRDA_TURNAROUND_TIME 0x0A010101
+#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102
+#define OID_IRDA_LINK_SPEED 0x0A010103
+#define OID_IRDA_MEDIA_BUSY 0x0A010104
+#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200
+#define OID_IRDA_RATE_SNIFF 0x0A010201
+#define OID_IRDA_UNICAST_LIST 0x0A010202
+#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203
+#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204
+#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205
+//
+// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/
+// OID_GEN_MEDIA_IN_USE).
+//
+typedef enum _NDIS_MEDIUM {
+ NdisMedium802_3,
+ NdisMedium802_5,
+ NdisMediumFddi,
+ NdisMediumWan,
+ NdisMediumLocalTalk,
+ NdisMediumDix, // defined for convenience, not a real medium
+ NdisMediumArcnetRaw,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMediumWirelessWan,
+ NdisMediumIrda,
+ NdisMediumMax // Not a real medium, defined as an upper-bound
+} NDIS_MEDIUM, *PNDIS_MEDIUM;
+
+//
+// Hardware status codes (OID_GEN_HARDWARE_STATUS).
+//
+typedef enum _NDIS_HARDWARE_STATUS {
+ NdisHardwareStatusReady,
+ NdisHardwareStatusInitializing,
+ NdisHardwareStatusReset,
+ NdisHardwareStatusClosing,
+ NdisHardwareStatusNotReady
+} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS;
+
+//
+// this is the type passed in the OID_GEN_GET_TIME_CAPS request
+//
+typedef struct _GEN_GET_TIME_CAPS {
+ ULONG Flags; // Bits defined below
+
+ ULONG ClockPrecision;
+} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS;
+
+#define READABLE_LOCAL_CLOCK 0x000000001
+#define CLOCK_NETWORK_DERIVED 0x000000002
+#define CLOCK_PRECISION 0x000000004
+#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008
+#define TIMED_SEND_CAPABLE 0x000000010
+#define TIME_STAMP_CAPABLE 0x000000020
+//
+//
+// this is the type passed in the OID_GEN_GET_NETCARD_TIME request
+//
+typedef struct _GEN_GET_NETCARD_TIME {
+ ULONG ReadTime;
+} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME;
+
+//
+// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE).
+//
+typedef enum _NDIS_FDDI_ATTACHMENT_TYPE {
+ NdisFddiTypeIsolated = 1,
+ NdisFddiTypeLocalA,
+ NdisFddiTypeLocalB,
+ NdisFddiTypeLocalAB,
+ NdisFddiTypeLocalS,
+ NdisFddiTypeWrapA,
+ NdisFddiTypeWrapB,
+ NdisFddiTypeWrapAB,
+ NdisFddiTypeWrapS,
+ NdisFddiTypeCWrapA,
+ NdisFddiTypeCWrapB,
+ NdisFddiTypeCWrapS,
+ NdisFddiTypeThrough
+} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE;
+
+//
+// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE).
+//
+typedef enum _NDIS_FDDI_RING_MGT_STATE {
+ NdisFddiRingIsolated = 1,
+ NdisFddiRingNonOperational,
+ NdisFddiRingOperational,
+ NdisFddiRingDetect,
+ NdisFddiRingNonOperationalDup,
+ NdisFddiRingOperationalDup,
+ NdisFddiRingDirected,
+ NdisFddiRingTrace
+} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE;
+
+//
+// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE).
+//
+typedef enum _NDIS_FDDI_LCONNECTION_STATE {
+ NdisFddiStateOff = 1,
+ NdisFddiStateBreak,
+ NdisFddiStateTrace,
+ NdisFddiStateConnect,
+ NdisFddiStateNext,
+ NdisFddiStateSignal,
+ NdisFddiStateJoin,
+ NdisFddiStateVerify,
+ NdisFddiStateActive,
+ NdisFddiStateMaintenance
+} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE;
+
+//
+// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE).
+//
+typedef enum _NDIS_WAN_MEDIUM_SUBTYPE {
+ NdisWanMediumHub,
+ NdisWanMediumX_25,
+ NdisWanMediumIsdn,
+ NdisWanMediumSerial,
+ NdisWanMediumFrameRelay,
+ NdisWanMediumAtm,
+ NdisWanMediumSonet,
+ NdisWanMediumSW56K
+} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE;
+
+//
+// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT).
+//
+typedef enum _NDIS_WAN_HEADER_FORMAT {
+ NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID
+ NdisWanHeaderEthernet // emulation of ethernet header
+} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT;
+
+//
+// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE).
+//
+typedef enum _NDIS_WAN_QUALITY {
+ NdisWanRaw,
+ NdisWanErrorControl,
+ NdisWanReliable
+} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY;
+
+//
+// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE).
+//
+typedef enum _NDIS_802_5_RING_STATE {
+ NdisRingStateOpened = 1,
+ NdisRingStateClosed,
+ NdisRingStateOpening,
+ NdisRingStateClosing,
+ NdisRingStateOpenFailure,
+ NdisRingStateRingFailure
+} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE;
+
+//
+// Defines the state of the LAN media
+//
+typedef enum _NDIS_MEDIA_STATE {
+ NdisMediaStateConnected,
+ NdisMediaStateDisconnected
+} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority
+//
+typedef ULONG Priority_802_3; // 0-7 priority levels
+//
+// The following structure is used to query OID_GEN_CO_LINK_SPEED and
+// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current
+// link speed of the adapter. The second will return the minimum link speed
+// the adapter is capable of.
+//
+
+typedef struct _NDIS_CO_LINK_SPEED {
+ ULONG Outbound;
+ ULONG Inbound;
+} NDIS_CO_LINK_SPEED,
+
+*PNDIS_CO_LINK_SPEED;
+//
+// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).
+//
+#define NDIS_PACKET_TYPE_DIRECTED 0x0001
+#define NDIS_PACKET_TYPE_MULTICAST 0x0002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
+#define NDIS_PACKET_TYPE_BROADCAST 0x0008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
+#define NDIS_PACKET_TYPE_SMT 0x0040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000
+#define NDIS_PACKET_TYPE_GROUP 0x1000
+//
+// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS).
+//
+#define NDIS_RING_SIGNAL_LOSS 0x00008000
+#define NDIS_RING_HARD_ERROR 0x00004000
+#define NDIS_RING_SOFT_ERROR 0x00002000
+#define NDIS_RING_TRANSMIT_BEACON 0x00001000
+#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800
+#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400
+#define NDIS_RING_REMOVE_RECEIVED 0x00000200
+#define NDIS_RING_COUNTER_OVERFLOW 0x00000100
+#define NDIS_RING_SINGLE_STATION 0x00000080
+#define NDIS_RING_RING_RECOVERY 0x00000040
+//
+// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS).
+//
+#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001
+#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002
+#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004
+//
+// Ndis MAC option bits (OID_GEN_MAC_OPTIONS).
+//
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+//
+// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS.
+//
+#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001
+#ifdef IRDA
+//
+// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo
+// This is the per-packet info specified on a per-packet basis
+//
+typedef struct _NDIS_IRDA_PACKET_INFO {
+ UINT ExtraBOFs;
+ UINT MinTurnAroundTime;
+} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO;
+
+#endif
+#ifdef WIRELESS_WAN
+//
+// Wireless WAN structure definitions
+//
+//
+// currently defined Wireless network subtypes
+//
+typedef enum _NDIS_WW_NETWORK_TYPE {
+ NdisWWGeneric,
+ NdisWWMobitex,
+ NdisWWPinpoint,
+ NdisWWCDPD,
+ NdisWWArdis,
+ NdisWWDataTAC,
+ NdisWWMetricom,
+ NdisWWGSM,
+ NdisWWCDMA,
+ NdisWWTDMA,
+ NdisWWAMPS,
+ NdisWWInmarsat,
+ NdisWWpACT
+} NDIS_WW_NETWORK_TYPE;
+
+//
+// currently defined header formats
+//
+typedef enum _NDIS_WW_HEADER_FORMAT {
+ NdisWWDIXEthernetFrames,
+ NdisWWMPAKFrames,
+ NdisWWRDLAPFrames,
+ NdisWWMDC4800Frames
+} NDIS_WW_HEADER_FORMAT;
+
+//
+// currently defined encryption types
+//
+typedef enum _NDIS_WW_ENCRYPTION_TYPE {
+ NdisWWUnknownEncryption = -1,
+ NdisWWNoEncryption,
+ NdisWWDefaultEncryption
+} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE;
+
+//
+// OID_WW_GEN_INDICATION_REQUEST
+//
+typedef struct _NDIS_WW_INDICATION_REQUEST {
+ NDIS_OID Oid; // IN
+
+ UINT uIndicationFlag; // IN
+
+ UINT uApplicationToken; // IN OUT
+
+ HANDLE hIndicationHandle; // IN OUT
+
+ INT iPollingInterval; // IN OUT
+
+ NDIS_VAR_DATA_DESC InitialValue; // IN OUT
+
+ NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication
+
+ NDIS_VAR_DATA_DESC TriggerValue; // IN
+
+} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST;
+
+#define OID_INDICATION_REQUEST_ENABLE 0x0000
+#define OID_INDICATION_REQUEST_CANCEL 0x0001
+//
+// OID_WW_GEN_DEVICE_INFO
+//
+typedef struct _WW_DEVICE_INFO {
+ NDIS_VAR_DATA_DESC Manufacturer;
+ NDIS_VAR_DATA_DESC ModelNum;
+ NDIS_VAR_DATA_DESC SWVersionNum;
+ NDIS_VAR_DATA_DESC SerialNum;
+} WW_DEVICE_INFO, *PWW_DEVICE_INFO;
+
+//
+// OID_WW_GEN_OPERATION_MODE
+//
+typedef INT WW_OPERATION_MODE; // 0 = Normal mode
+ // 1 = Power saving mode
+ // -1 = mode unknown
+//
+// OID_WW_GEN_LOCK_STATUS
+//
+
+typedef INT WW_LOCK_STATUS; // 0 = unlocked
+ // 1 = locked
+ // -1 = unknown lock status
+//
+// OID_WW_GEN_DISABLE_TRANSMITTER
+//
+
+typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled
+ // 1 = transmitter disabled
+ // -1 = unknown value
+//
+// OID_WW_GEN_NETWORK_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID;
+//
+// OID_WW_GEN_PERMANENT_ADDRESS
+//
+typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS;
+//
+// OID_WW_GEN_CURRENT_ADDRESS
+//
+typedef struct _WW_CURRENT_ADDRESS {
+ NDIS_WW_HEADER_FORMAT Format;
+ NDIS_VAR_DATA_DESC Address;
+} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS;
+
+//
+// OID_WW_GEN_SUSPEND_DRIVER
+//
+typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational
+ // 1 = driver suspended
+//
+// OID_WW_GEN_BASESTATION_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID;
+//
+// OID_WW_GEN_CHANNEL_ID
+//
+typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID;
+//
+// OID_WW_GEN_ENCRYPTION_STATE
+//
+typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled
+ // 1 = if encryption is enabled
+//
+// OID_WW_GEN_CHANNEL_QUALITY
+//
+
+typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact,
+ // 1-100 = Quality of Channel (100 is highest quality).
+ // -1 = channel quality is unknown
+//
+// OID_WW_GEN_REGISTRATION_STATUS
+//
+
+typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied
+ // 1 = Registration pending
+ // 2 = Registered
+ // -1 = unknown registration status
+//
+// OID_WW_GEN_RADIO_LINK_SPEED
+//
+
+typedef UINT WW_RADIO_LINK_SPEED; // Bits per second.
+//
+// OID_WW_GEN_LATENCY
+//
+
+typedef UINT WW_LATENCY; // milliseconds
+//
+// OID_WW_GEN_BATTERY_LEVEL
+//
+
+typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage
+ // (100=fully charged)
+ // -1 = unknown battery level.
+//
+// OID_WW_GEN_EXTERNAL_POWER
+//
+
+typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected
+ // 1 = external power connected
+ // -1 = unknown
+//
+// OID_WW_MET_FUNCTION
+//
+
+typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION;
+//
+// OID_WW_TAC_COMPRESSION
+//
+typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression
+ // is being used.
+//
+// OID_WW_TAC_SET_CONFIG
+//
+
+typedef struct _WW_TAC_SETCONFIG {
+ NDIS_VAR_DATA_DESC RCV_MODE;
+ NDIS_VAR_DATA_DESC TX_CONTROL;
+ NDIS_VAR_DATA_DESC RX_CONTROL;
+ NDIS_VAR_DATA_DESC FLOW_CONTROL;
+ NDIS_VAR_DATA_DESC RESET_CNF;
+ NDIS_VAR_DATA_DESC READ_CNF;
+} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG;
+
+//
+// OID_WW_TAC_GET_STATUS
+//
+typedef struct _WW_TAC_GETSTATUS {
+ BOOLEAN Action; // Set = Execute command.
+
+ NDIS_VAR_DATA_DESC Command;
+ NDIS_VAR_DATA_DESC Option;
+ NDIS_VAR_DATA_DESC Response; // The response to the requested command
+ // - max. length of string is 256 octets.
+
+} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS;
+
+//
+// OID_WW_TAC_USER_HEADER
+//
+typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets.
+//
+// OID_WW_ARD_SNDCP
+//
+
+typedef struct _WW_ARD_SNDCP {
+ NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported.
+
+ INT BlockSize; // The block size used for SNDCP
+
+ INT Window; // The window size used in SNDCP
+
+} WW_ARD_SNDCP, *PWW_ARD_SNDCP;
+
+//
+// OID_WW_ARD_TMLY_MSG
+//
+typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel.
+//
+// OID_WW_ARD_DATAGRAM
+//
+
+typedef struct _WW_ARD_DATAGRAM {
+ BOOLEAN LoadLevel; // Byte that contains the load level info.
+
+ INT SessionTime; // Datagram session time remaining.
+
+ NDIS_VAR_DATA_DESC HostAddr; // Host address.
+
+ NDIS_VAR_DATA_DESC THostAddr; // Test host address.
+
+} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM;
+
+//
+// OID_WW_CDPD_SPNI
+//
+typedef struct _WW_CDPD_SPNI {
+ UINT SPNI[10]; //10 16-bit service provider network IDs
+
+ INT OperatingMode; // 0 = ignore SPNI,
+ // 1 = require SPNI from list,
+ // 2 = prefer SPNI from list.
+ // 3 = exclude SPNI from list.
+
+} WW_CDPD_SPNI, *PWW_CDPD_SPNI;
+
+//
+// OID_WW_CDPD_WASI
+//
+typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID {
+ UINT WASI[10]; //10 16-bit wide area service IDs
+
+ INT OperatingMode; // 0 = ignore WASI,
+ // 1 = Require WASI from list,
+ // 2 = prefer WASI from list
+ // 3 = exclude WASI from list.
+
+} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID;
+
+//
+// OID_WW_CDPD_AREA_COLOR
+//
+typedef INT WW_CDPD_AREA_COLOR;
+//
+// OID_WW_CDPD_TX_POWER_LEVEL
+//
+typedef UINT WW_CDPD_TX_POWER_LEVEL;
+//
+// OID_WW_CDPD_EID
+//
+typedef NDIS_VAR_DATA_DESC WW_CDPD_EID;
+//
+// OID_WW_CDPD_HEADER_COMPRESSION
+//
+typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression,
+ // 1 = always compress headers,
+ // 2 = compress headers if MD-IS does
+ // -1 = unknown
+//
+// OID_WW_CDPD_DATA_COMPRESSION
+//
+
+typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression,
+ // 1 = data compression enabled
+ // -1 = unknown
+//
+// OID_WW_CDPD_CHANNEL_SELECT
+//
+
+typedef struct _WW_CDPD_CHANNEL_SELECT {
+ UINT ChannelID; // channel number
+
+ UINT fixedDuration; // duration in seconds
+
+} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT;
+
+//
+// OID_WW_CDPD_CHANNEL_STATE
+//
+typedef enum _WW_CDPD_CHANNEL_STATE {
+ CDPDChannelNotAvail,
+ CDPDChannelScanning,
+ CDPDChannelInitAcquired,
+ CDPDChannelAcquired,
+ CDPDChannelSleeping,
+ CDPDChannelWaking,
+ CDPDChannelCSDialing,
+ CDPDChannelCSRedial,
+ CDPDChannelCSAnswering,
+ CDPDChannelCSConnected,
+ CDPDChannelCSSuspended
+} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE;
+
+//
+// OID_WW_CDPD_NEI
+//
+typedef enum _WW_CDPD_NEI_FORMAT {
+ CDPDNeiIPv4,
+ CDPDNeiCLNP,
+ CDPDNeiIPv6
+} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT;
+typedef enum _WW_CDPD_NEI_TYPE {
+ CDPDNeiIndividual,
+ CDPDNeiMulticast,
+ CDPDNeiBroadcast
+} WW_CDPD_NEI_TYPE;
+typedef struct _WW_CDPD_NEI {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_FORMAT NeiFormat;
+ WW_CDPD_NEI_TYPE NeiType;
+ WORD NeiGmid; // group member identifier, only
+ // meaningful if NeiType ==
+ // CDPDNeiMulticast
+
+ NDIS_VAR_DATA_DESC NeiAddress;
+} WW_CDPD_NEI;
+
+//
+// OID_WW_CDPD_NEI_STATE
+//
+typedef enum _WW_CDPD_NEI_STATE {
+ CDPDUnknown,
+ CDPDRegistered,
+ CDPDDeregistered
+} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE;
+typedef enum _WW_CDPD_NEI_SUB_STATE {
+ CDPDPending, // Registration pending
+ CDPDNoReason, // Registration denied - no reason given
+ CDPDMDISNotCapable, // Registration denied - MD-IS not capable of
+ // handling M-ES at this time
+ CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to
+ // use this subnetwork
+ CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient
+ // authentication credentials
+ CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported
+ // authentication credentials
+ CDPDUsageExceeded, // Registration denied - NEI has exceeded usage
+ // limitations
+ CDPDDeniedThisNetwork // Registration denied on this network, service
+ // may be obtained on alternate Service Provider
+ // network
+} WW_CDPD_NEI_SUB_STATE;
+typedef struct _WW_CDPD_NEI_REG_STATE {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_STATE NeiState;
+ WW_CDPD_NEI_SUB_STATE NeiSubState;
+} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE;
+
+//
+// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER
+//
+typedef struct _WW_CDPD_SERVICE_PROVIDER_ID {
+ UINT SPI[10]; //10 16-bit service provider IDs
+
+ INT OperatingMode; // 0 = ignore SPI,
+ // 1 = require SPI from list,
+ // 2 = prefer SPI from list.
+ // 3 = exclude SPI from list.
+
+} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID;
+
+//
+// OID_WW_CDPD_SLEEP_MODE
+//
+typedef INT WW_CDPD_SLEEP_MODE;
+//
+// OID_WW_CDPD_TEI
+//
+typedef ULONG WW_CDPD_TEI;
+//
+// OID_WW_CDPD_CIRCUIT_SWITCHED
+//
+typedef struct _WW_CDPD_CIRCUIT_SWITCHED {
+ INT service_preference; // -1 = unknown,
+ // 0 = always use packet switched CDPD,
+ // 1 = always use CS CDPD via AMPS,
+ // 2 = always use CS CDPD via PSTN,
+ // 3 = use circuit switched via AMPS only
+ // when packet switched is not available.
+ // 4 = use packet switched only when circuit
+ // switched via AMPS is not available.
+ // 5 = device manuf. defined service
+ // preference.
+ // 6 = device manuf. defined service
+ // preference.
+
+ INT service_status; // -1 = unknown,
+ // 0 = packet switched CDPD,
+ // 1 = circuit switched CDPD via AMPS,
+ // 2 = circuit switched CDPD via PSTN.
+
+ INT connect_rate; // CS connection bit rate (bits per second).
+ // 0 = no active connection,
+ // -1 = unknown
+ // Dial code last used to dial.
+
+ NDIS_VAR_DATA_DESC dial_code[20];
+
+ UINT sid; // Current AMPS system ID
+
+ INT a_b_side_selection; // -1 = unknown,
+ // 0 = no AMPS service
+ // 1 = AMPS "A" side channels selected
+ // 2 = AMPS "B" side channels selected
+
+ INT AMPS_channel; // -1= unknown
+ // 0 = no AMPS service.
+ // 1-1023 = AMPS channel number in use
+
+ UINT action; // 0 = no action
+ // 1 = suspend (hangup)
+ // 2 = dial
+
+ // Default dial code for CS CDPD service
+ // encoded as specified in the CS CDPD
+ // implementor guidelines.
+ NDIS_VAR_DATA_DESC default_dial[20];
+
+ // Number for the CS CDPD network to call
+ // back the mobile, encoded as specified in
+ // the CS CDPD implementor guidelines.
+ NDIS_VAR_DATA_DESC call_back[20];
+
+ UINT sid_list[10]; // List of 10 16-bit preferred AMPS
+ // system IDs for CS CDPD.
+
+ UINT inactivity_timer; // Wait time after last data before dropping
+ // call.
+ // 0-65535 = inactivity time limit (seconds).
+
+ UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED;
+typedef UINT WW_CDPD_RSSI;
+//
+// OID_WW_PIN_LOC_AUTHORIZE
+//
+typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized
+ // 1 = authorized
+ // -1 = unknown
+//
+// OID_WW_PIN_LAST_LOCATION
+// OID_WW_PIN_LOC_FIX
+//
+
+typedef struct _WW_PIN_LOCATION {
+ INT Latitude; // Latitude in hundredths of a second
+
+ INT Longitude; // Longitude in hundredths of a second
+
+ INT Altitude; // Altitude in feet
+
+ INT FixTime; // Time of the location fix, since midnight, local time (of the
+ // current day), in tenths of a second
+
+ INT NetTime; // Current local network time of the current day, since midnight,
+ // in tenths of a second
+
+ INT LocQuality; // 0-100 = location quality
+
+ INT LatReg; // Latitude registration offset, in hundredths of a second
+
+ INT LongReg; // Longitude registration offset, in hundredths of a second
+
+ INT GMTOffset; // Offset in minutes of the local time zone from GMT
+
+} WW_PIN_LOCATION, *PWW_PIN_LOCATION;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox
+//
+typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag
+//
+// OID_WW_MBX_SUBADDR
+//
+
+typedef struct _WW_MBX_PMAN {
+ BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN
+
+ UINT MAN;
+ UCHAR PASSWORD[8]; // Password should be null for Logout and indications.
+ // Maximum length of password is 8 chars.
+
+} WW_MBX_PMAN, *PWW_MBX_PMAN;
+
+//
+// OID_WW_MBX_FLEXLIST
+//
+typedef struct _WW_MBX_FLEXLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[7]; // List of MANs.
+
+} WW_MBX_FLEXLIST;
+
+//
+// OID_WW_MBX_GROUPLIST
+//
+typedef struct _WW_MBX_GROUPLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[15]; // List of MANs.
+
+} WW_MBX_GROUPLIST;
+
+//
+// OID_WW_MBX_TRAFFIC_AREA
+//
+typedef enum _WW_MBX_TRAFFIC_AREA {
+ unknown_traffic_area, // The driver has no information about the current traffic area.
+ in_traffic_area, // Mobile unit has entered a subscribed traffic area.
+ in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized.
+ unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized.
+} WW_MBX_TRAFFIC_AREA;
+
+//
+// OID_WW_MBX_LIVE_DIE
+//
+typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received
+ // 1 = LIVE last received
+ // -1 = unknown
+//
+// OID_WW_MBX_TEMP_DEFAULTLIST
+//
+
+typedef struct _WW_MBX_CHANNEL_PAIR {
+ UINT Mobile_Tx;
+ UINT Mobile_Rx;
+} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR;
+typedef struct _WW_MBX_TEMPDEFAULTLIST {
+ UINT Length;
+ WW_MBX_CHANNEL_PAIR ChannelPair[1];
+} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST;
+
+#endif // WIRELESS_WAN
+#endif // _NTDDNDIS_
diff --git a/src/Cedar/winpcap/Ntddpack.h b/src/Cedar/winpcap/Ntddpack.h
new file mode 100644
index 00000000..30945c1e
--- /dev/null
+++ b/src/Cedar/winpcap/Ntddpack.h
@@ -0,0 +1,26 @@
+
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+#include "devioctl.h"
+/*#include <packon.h> */
+struct _PACKET_OID_DATA {
+ ULONG Oid;
+ ULONG Length;
+ UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL 0x8000
+#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/src/Cedar/winpcap/Packet32.h b/src/Cedar/winpcap/Packet32.h
new file mode 100644
index 00000000..8c2c8c4a
--- /dev/null
+++ b/src/Cedar/winpcap/Packet32.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup packetapi
+ * @{
+ */
+
+/** @defgroup packet32h Packet.dll definitions and data structures
+ * Packet32.h contains the data structures and the definitions used by packet.dll.
+ * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
+ * by the applications that use the functions of this library
+ * @{
+ */
+
+#ifndef __PACKET32
+#define __PACKET32
+
+#include <winsock2.h>
+#include "devioctl.h"
+#ifdef HAVE_DAG_API
+#include <dagc.h>
+#endif /* HAVE_DAG_API */
+
+// Working modes
+#define PACKET_MODE_CAPT 0x0 ///< Capture mode
+#define PACKET_MODE_STAT 0x1 ///< Statistical mode
+#define PACKET_MODE_MON 0x2 ///< Monitoring mode
+#define PACKET_MODE_DUMP 0x10 ///< Dump mode
+#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
+
+// ioctls
+#define FILE_DEVICE_PROTOCOL 0x8000
+
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size.
+#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program.
+#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats.
+#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout.
+#define pBIOCSMODE 7412 ///< IOCTL code: set working mode.
+#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app.
+#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call.
+#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value.
+#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value.
+#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only.
+#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only.
+#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode.
+#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer.
+#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets.
+#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets.
+#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function.
+#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function.
+
+#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only.
+
+
+/// Alignment macro. Defines the alignment size.
+#define Packet_ALIGNMENT sizeof(int)
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
+
+
+#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent
+
+/*!
+ \brief Network type structure.
+
+ This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
+*/
+typedef struct NetType
+{
+ UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
+ ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
+}NetType;
+
+
+//some definitions stolen from libpcap
+
+#ifndef BPF_MAJOR_VERSION
+
+/*!
+ \brief A BPF pseudo-assembly program.
+
+ The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
+*/
+struct bpf_program
+{
+ UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
+ struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
+};
+
+/*!
+ \brief A single BPF pseudo-instruction.
+
+ bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
+*/
+struct bpf_insn
+{
+ USHORT code; ///< Instruction type and addressing mode.
+ UCHAR jt; ///< Jump if true
+ UCHAR jf; ///< Jump if false
+ int k; ///< Generic field used for various purposes.
+};
+
+/*!
+ \brief Structure that contains a couple of statistics values on the current capture.
+
+ It is used by packet.dll to return statistics about a capture session.
+*/
+struct bpf_stat
+{
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*!
+ \brief Packet header.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+struct bpf_hdr
+{
+ struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
+ ///< It is stored in a TimeVal structure.
+ UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
+ ///< from the original packet, because it is possible (with a proper filter)
+ ///< to instruct the driver to capture only a portion of the packets.
+ UINT bh_datalen; ///< Original length of packet
+ USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
+ ///< a padding could be added between the end of this structure and the packet
+ ///< data for performance reasons. This filed can be used to retrieve the actual data
+ ///< of the packet.
+};
+
+/*!
+ \brief Dump packet header.
+
+ This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
+ It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
+ packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
+*/
+struct dump_bpf_hdr{
+ struct timeval ts; ///< Time stamp of the packet
+ UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+
+#endif
+
+#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
+#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
+#define NMAX_PACKET 65535
+
+/*!
+ \brief Addresses of a network adapter.
+
+ This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
+ an adapter.
+*/
+typedef struct npf_if_addr {
+ struct sockaddr_storage IPAddress; ///< IP address.
+ struct sockaddr_storage SubnetMask; ///< Netmask for that address.
+ struct sockaddr_storage Broadcast; ///< Broadcast address.
+}npf_if_addr;
+
+
+#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
+#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
+#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+
+
+typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+
+#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
+#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter
+#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
+#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
+#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
+
+/*!
+ \brief Contains comprehensive information about a network adapter.
+
+ This structure is filled with all the accessory information that the user can need about an adapter installed
+ on his system.
+*/
+typedef struct _ADAPTER_INFO
+{
+ struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list.
+ CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter.
+ CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter
+ UINT MacAddressLen; ///< Length of the link layer address.
+ UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address.
+ NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter.
+ INT NNetworkAddresses; ///< Number of network layer addresses of this adapter.
+ npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter.
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+}
+ADAPTER_INFO, *PADAPTER_INFO;
+
+/*!
+ \brief Describes an opened network adapter.
+
+ This structure is the most important for the functioning of packet.dll, but the great part of its fields
+ should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
+*/
+typedef struct _ADAPTER {
+ HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
+ CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
+ int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
+ ///< on the wire.
+ HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
+ ///< It can be passed to standard Win32 functions (like WaitForSingleObject
+ ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
+ ///< data. It is particularly useful in GUI applications that need to wait
+ ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
+ ///< function can be used to define the minimum amount of data in the kernel buffer
+ ///< that will cause the event to be signalled.
+
+ UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
+ ///< ReadEvent will be signaled, also if no packets were captured
+ CHAR Name[ADAPTER_NAME_LENGTH];
+ PWAN_ADAPTER pWanAdapter;
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+#ifdef HAVE_DAG_API
+ dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
+ PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
+ struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
+ unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
+ DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
+#endif // HAVE_DAG_API
+} ADAPTER, *LPADAPTER;
+
+/*!
+ \brief Structure that contains a group of packets coming from the driver.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+typedef struct _PACKET {
+ HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
+ OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
+ PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
+ ///< details about the organization of the data in this buffer
+ UINT Length; ///< Length of the buffer
+ DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
+ ///< received by the last call to PacketReceivePacket()
+ BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
+} PACKET, *LPPACKET;
+
+/*!
+ \brief Structure containing an OID request.
+
+ It is used by the PacketRequest() function to send an OID to the interface card driver.
+ It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
+ the list of the multicast groups defined on it, and so on.
+*/
+struct _PACKET_OID_DATA {
+ ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+ ///< for a complete list of valid codes.
+ ULONG Length; ///< Length of the data field
+ UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
+ ///< from the adapter.
+};
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+
+#if _DBG
+#define ODS(_x) OutputDebugString(TEXT(_x))
+#define ODSEx(_x, _y)
+#else
+#ifdef _DEBUG_TO_FILE
+/*!
+ \brief Macro to print a debug string. The behavior differs depending on the debug level
+*/
+#define ODS(_x) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, "%s", _x); \
+ fclose(f); \
+}
+/*!
+ \brief Macro to print debug data with the printf convention. The behavior differs depending on
+ the debug level
+*/
+#define ODSEx(_x, _y) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, _x, _y); \
+ fclose(f); \
+}
+
+
+
+LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
+#else
+#define ODS(_x)
+#define ODSEx(_x, _y)
+#endif
+#endif
+
+/* We load dinamically the dag library in order link it only when it's present on the system */
+#ifdef HAVE_DAG_API
+typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll
+typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll
+#endif // HAVE_DAG_API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @}
+ */
+
+// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent
+// opening of firewire adapters
+#define FIREWIRE_SUBSTR L"1394"
+
+void PacketPopulateAdaptersInfoList();
+PWCHAR SChar2WChar(PCHAR string);
+PCHAR WChar2SChar(PWCHAR string);
+BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen);
+PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName);
+BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName);
+BOOLEAN IsFireWire(TCHAR *AdapterDesc);
+
+
+//---------------------------------------------------------------------------
+// EXPORTED FUNCTIONS
+//---------------------------------------------------------------------------
+
+PCHAR PacketGetVersion();
+PCHAR PacketGetDriverVersion();
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
+INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
+BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
+LPPACKET PacketAllocatePacket(void);
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
+VOID PacketFreePacket(LPPACKET lpPacket);
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
+BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
+BOOL PacketStopDriver();
+VOID PacketCloseAdapter(LPADAPTER lpAdapter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__PACKET32
diff --git a/src/Cedar/winpcap/Win32-Extensions.h b/src/Cedar/winpcap/Win32-Extensions.h
new file mode 100644
index 00000000..8466e0c2
--- /dev/null
+++ b/src/Cedar/winpcap/Win32-Extensions.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Definitions */
+
+/*!
+ \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
+*/
+struct pcap_send_queue{
+ u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field.
+ u_int len; ///< Current size of the queue, in bytes.
+ char *buffer; ///< Buffer containing the packets to be sent.
+};
+
+typedef struct pcap_send_queue pcap_send_queue;
+
+#define BPF_MEM_EX_IMM 0xc0
+#define BPF_MEM_EX_IND 0xe0
+
+/*used for ST*/
+#define BPF_MEM_EX 0xc0
+#define BPF_TME 0x08
+
+#define BPF_LOOKUP 0x90
+#define BPF_EXECUTE 0xa0
+#define BPF_INIT 0xb0
+#define BPF_VALIDATE 0xc0
+#define BPF_SET_ACTIVE 0xd0
+#define BPF_RESET 0xe0
+#define BPF_SET_MEMORY 0x80
+#define BPF_GET_REGISTER_VALUE 0x70
+#define BPF_SET_REGISTER_VALUE 0x60
+#define BPF_SET_WORKING 0x50
+#define BPF_SET_ACTIVE_READ 0x40
+#define BPF_SET_AUTODELETION 0x30
+#define BPF_SEPARATION 0xff
+
+/* Prototypes */
+pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
+
+void pcap_sendqueue_destroy(pcap_send_queue* queue);
+
+int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
+
+u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
+
+HANDLE pcap_getevent(pcap_t *p);
+
+struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
+
+int pcap_setuserbuffer(pcap_t *p, int size);
+
+int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+
+int pcap_live_dump_ended(pcap_t *p, int sync);
+
+int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data);
diff --git a/src/Cedar/winpcap/bittypes.h b/src/Cedar/winpcap/bittypes.h
new file mode 100644
index 00000000..1a2611d8
--- /dev/null
+++ b/src/Cedar/winpcap/bittypes.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _BITTYPES_H
+#define _BITTYPES_H
+
+#ifndef HAVE_U_INT8_T
+
+#if SIZEOF_CHAR == 1
+typedef unsigned char u_int8_t;
+typedef signed char int8_t;
+#elif SIZEOF_INT == 1
+typedef unsigned int u_int8_t;
+typedef signed int int8_t;
+#else /* XXX */
+#error "there's no appropriate type for u_int8_t"
+#endif
+#define HAVE_U_INT8_T 1
+#define HAVE_INT8_T 1
+
+#endif /* HAVE_U_INT8_T */
+
+#ifndef HAVE_U_INT16_T
+
+#if SIZEOF_SHORT == 2
+typedef unsigned short u_int16_t;
+typedef signed short int16_t;
+#elif SIZEOF_INT == 2
+typedef unsigned int u_int16_t;
+typedef signed int int16_t;
+#elif SIZEOF_CHAR == 2
+typedef unsigned char u_int16_t;
+typedef signed char int16_t;
+#else /* XXX */
+#error "there's no appropriate type for u_int16_t"
+#endif
+#define HAVE_U_INT16_T 1
+#define HAVE_INT16_T 1
+
+#endif /* HAVE_U_INT16_T */
+
+#ifndef HAVE_U_INT32_T
+
+#if SIZEOF_INT == 4
+typedef unsigned int u_int32_t;
+typedef signed int int32_t;
+#elif SIZEOF_LONG == 4
+typedef unsigned long u_int32_t;
+typedef signed long int32_t;
+#elif SIZEOF_SHORT == 4
+typedef unsigned short u_int32_t;
+typedef signed short int32_t;
+#else /* XXX */
+#error "there's no appropriate type for u_int32_t"
+#endif
+#define HAVE_U_INT32_T 1
+#define HAVE_INT32_T 1
+
+#endif /* HAVE_U_INT32_T */
+
+#ifndef HAVE_U_INT64_T
+#if SIZEOF_LONG_LONG == 8
+typedef unsigned long long u_int64_t;
+#elif defined(_MSC_EXTENSIONS)
+typedef unsigned _int64 u_int64_t;
+#elif SIZEOF_INT == 8
+typedef unsigned int u_int64_t;
+#elif SIZEOF_LONG == 8
+typedef unsigned long u_int64_t;
+#elif SIZEOF_SHORT == 8
+typedef unsigned short u_int64_t;
+#else /* XXX */
+#error "there's no appropriate type for u_int64_t"
+#endif
+
+#endif /* HAVE_U_INT64_T */
+
+#ifndef PRId64
+#ifdef _MSC_EXTENSIONS
+#define PRId64 "I64d"
+#else /* _MSC_EXTENSIONS */
+#define PRId64 "lld"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRId64 */
+
+#ifndef PRIo64
+#ifdef _MSC_EXTENSIONS
+#define PRIo64 "I64o"
+#else /* _MSC_EXTENSIONS */
+#define PRIo64 "llo"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIo64 */
+
+#ifndef PRIx64
+#ifdef _MSC_EXTENSIONS
+#define PRIx64 "I64x"
+#else /* _MSC_EXTENSIONS */
+#define PRIx64 "llx"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIx64 */
+
+#ifndef PRIu64
+#ifdef _MSC_EXTENSIONS
+#define PRIu64 "I64u"
+#else /* _MSC_EXTENSIONS */
+#define PRIu64 "llu"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIu64 */
+
+#endif /* _BITTYPES_H */
diff --git a/src/Cedar/winpcap/bucket_lookup.h b/src/Cedar/winpcap/bucket_lookup.h
new file mode 100644
index 00000000..d8700b54
--- /dev/null
+++ b/src/Cedar/winpcap/bucket_lookup.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define BUCKET_LOOKUP_INSERT 0x00000011
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define BUCKET_LOOKUP 0x00000010
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+
+#endif
diff --git a/src/Cedar/winpcap/count_packets.h b/src/Cedar/winpcap/count_packets.h
new file mode 100644
index 00000000..9853bda3
--- /dev/null
+++ b/src/Cedar/winpcap/count_packets.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+typedef struct __c_p_data
+{
+ struct timeval timestamp;
+ uint64 packets;
+ uint64 bytes;
+}
+ c_p_data;
+
+#define COUNT_PACKETS 0x00000000
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
+
diff --git a/src/Cedar/winpcap/ip6_misc.h b/src/Cedar/winpcap/ip6_misc.h
new file mode 100644
index 00000000..1965ecab
--- /dev/null
+++ b/src/Cedar/winpcap/ip6_misc.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1993, 1994, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.4 2004/07/06 23:45:29 risso Exp $ (LBL)
+ */
+
+/*
+ * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
+ */
+
+#include <winsock2.h>
+
+#ifndef __MINGW32__
+#include <ws2tcpip.h>
+#endif /* __MINGW32__ */
+
+#define IN_MULTICAST(a) IN_CLASSD(a)
+
+#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
+
+#define IN_LOOPBACKNET 127
+
+#ifdef __MINGW32__
+/* IPv6 address */
+struct in6_addr
+ {
+ union
+ {
+ u_int8_t u6_addr8[16];
+ u_int16_t u6_addr16[8];
+ u_int32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+#define s6_addr64 in6_u.u6_addr64
+ };
+
+#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+#endif /* __MINGW32__ */
+
+
+#if (defined WIN32) || (defined __MINGW32__)
+typedef unsigned short sa_family_t;
+#endif
+
+
+#ifdef __MINGW32__
+
+#define __SOCKADDR_COMMON(sa_prefix) \
+ sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6. */
+struct sockaddr_in6
+ {
+ __SOCKADDR_COMMON (sin6_);
+ u_int16_t sin6_port; /* Transport layer port # */
+ u_int32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ };
+
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
+ (((u_int32_t *) (a))[2] == htonl (0xffff)))
+
+#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+ ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
+
+#define IN6_IS_ADDR_LOOPBACK(a) \
+ (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
+ ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
+#endif /* __MINGW32__ */
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define nd_rd_type nd_rd_hdr.icmp6_type
+#define nd_rd_code nd_rd_hdr.icmp6_code
+#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
+
+/*
+ * IPV6 extension headers
+ */
+#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */
+#define IPPROTO_IPV6 41 /* IPv6 header. */
+#define IPPROTO_ROUTING 43 /* IPv6 routing header */
+#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
+#define IPPROTO_ESP 50 /* encapsulating security payload */
+#define IPPROTO_AH 51 /* authentication header */
+#define IPPROTO_ICMPV6 58 /* ICMPv6 */
+#define IPPROTO_NONE 59 /* IPv6 no next header */
+#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
+#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */
+
+#define IPV6_RTHDR_TYPE_0 0
+
+/* Option types and related macros */
+#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
+#define IP6OPT_PADN 0x01 /* 00 0 00001 */
+#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
+#define IP6OPT_JUMBO_LEN 6
+#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */
+
+#define IP6OPT_RTALERT_LEN 4
+#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
+#define IP6OPT_MINLEN 2
+
+#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */
+#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */
+#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */
+#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */
+#define IP6OPT_EID 0x8a /* 10 0 01010 */
+
+#define IP6OPT_TYPE(o) ((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP 0x00
+#define IP6OPT_TYPE_DISCARD 0x40
+#define IP6OPT_TYPE_FORCEICMP 0x80
+#define IP6OPT_TYPE_ICMP 0xC0
+
+#define IP6OPT_MUTABLE 0x20
+
+
+#ifdef __MINGW32__
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+#endif
+#endif /* __MINGW32__ */
diff --git a/src/Cedar/winpcap/memory_t.h b/src/Cedar/winpcap/memory_t.h
new file mode 100644
index 00000000..ab3c85db
--- /dev/null
+++ b/src/Cedar/winpcap/memory_t.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define uint8 UCHAR
+#define int8 CHAR
+#define uint16 USHORT
+#define int16 SHORT
+#define uint32 ULONG
+#define int32 LONG
+#define uint64 ULONGLONG
+#define int64 LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+ uint8 *buffer;
+ uint32 size;
+} MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ { \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
+ if ((dest)!=NULL) \
+ RtlZeroMemory((dest),sizeof(type)*(amount)); \
+ }
+
+#define FREE_MEMORY(dest) ExFreePool(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+#else
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+
+#define FREE_MEMORY(dest) GlobalFree(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+
+#endif /*WIN_NT_DRIVER*/
+
+
+
+#endif
+
diff --git a/src/Cedar/winpcap/normal_lookup.h b/src/Cedar/winpcap/normal_lookup.h
new file mode 100644
index 00000000..45ac4fd1
--- /dev/null
+++ b/src/Cedar/winpcap/normal_lookup.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define NORMAL_LUT_W_INSERT 0x00000000
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define NORMAL_LUT_WO_INSERT 0x00000001
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define DUMMY_INSERT 1234
+
+#endif
diff --git a/src/Cedar/winpcap/pcap-bpf.h b/src/Cedar/winpcap/pcap-bpf.h
new file mode 100644
index 00000000..6e5d64af
--- /dev/null
+++ b/src/Cedar/winpcap/pcap-bpf.h
@@ -0,0 +1,685 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34.2.5 2005/05/27 23:33:00 guy Exp $ (LBL)
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * XXX - should this all just be moved to "pcap.h"?
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * Data-link level type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@tcpdump.org" for a value. Otherwise, you run the
+ * risk of using a value that's already being used for some other purpose,
+ * and of having tools that read libpcap-format captures not being able
+ * to handle captures with your new DLT_ value, with no hope that they
+ * will ever be changed to do so (as that would destroy their ability
+ * to read captures using that value for that other purpose).
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 is used for DLT_OLD_PFLOG in OpenBSD;
+ * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
+ * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
+ */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 as a DLT_ value.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
+ * in SuSE 6.3, so we can't use 17 for it in capture-file headers.
+ *
+ * XXX: is there a conflict with DLT_PFSYNC 18 as well?
+ */
+#ifdef __OpenBSD__
+#define DLT_OLD_PFLOG 17
+#define DLT_PFSYNC 18
+#endif
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define DLT_HHDLC 121
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * Reserved for BACnet MS/TP.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(struct bpf_insn *, int);
+extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Cedar/winpcap/pcap-int.h b/src/Cedar/winpcap/pcap-int.h
new file mode 100644
index 00000000..1ffcd03f
--- /dev/null
+++ b/src/Cedar/winpcap/pcap-int.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.6 2005/07/07 06:56:04 guy Exp $ (LBL)
+ */
+
+#ifndef pcap_int_h
+#define pcap_int_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pcap.h>
+
+#ifdef WIN32
+#include <packet32.h>
+#endif /* WIN32 */
+
+#ifdef MSDOS
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+/*
+ * Savefile
+ */
+typedef enum {
+ NOT_SWAPPED,
+ SWAPPED,
+ MAYBE_SWAPPED
+} swapped_type_t;
+
+struct pcap_sf {
+ FILE *rfile;
+ int swapped;
+ int hdrsize;
+ swapped_type_t lengths_swapped;
+ int version_major;
+ int version_minor;
+ u_char *base;
+};
+
+struct pcap_md {
+ struct pcap_stat stat;
+ /*XXX*/
+ int use_bpf; /* using kernel filter */
+ u_long TotPkts; /* can't oflow for 79 hrs on ether */
+ u_long TotAccepted; /* count accepted by filter */
+ u_long TotDrops; /* count of dropped packets */
+ long TotMissed; /* missed by i/f during this run */
+ long OrigMissed; /* missed by i/f before this run */
+ char *device; /* device name */
+#ifdef linux
+ int sock_packet; /* using Linux 2.0 compatible interface */
+ int timeout; /* timeout specified to pcap_open_live */
+ int clear_promisc; /* must clear promiscuous mode when we close */
+ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
+ int ifindex; /* interface index of device we're bound to */
+ int lo_ifindex; /* interface index of the loopback device */
+ struct pcap *next; /* list of open promiscuous sock_packet pcaps */
+#endif
+
+#ifdef HAVE_DAG_API
+#ifdef HAVE_DAG_STREAMS_API
+ u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */
+ u_char *dag_mem_top; /* DAG card current memory top pointer */
+#else
+ void *dag_mem_base; /* DAG card memory base address */
+ u_int dag_mem_bottom; /* DAG card current memory bottom offset */
+ u_int dag_mem_top; /* DAG card current memory top offset */
+#endif /* HAVE_DAG_STREAMS_API */
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+ int dag_offset_flags; /* Flags to pass to dag_offset(). */
+ int dag_stream; /* DAG stream number */
+ int dag_timeout; /* timeout specified to pcap_open_live.
+ * Same as in linux above, introduce
+ * generally? */
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_REMOTE
+/*!
+ There is really a mess with previous variables, and it seems to me that they are not used
+ (they are used in pcap_pf.c only). I think we have to start using them.
+ The meaning is the following:
+
+ - TotPkts: the amount of packets received by the bpf filter, *before* applying the filter
+ - TotAccepted: the amount of packets that satisfies the filter
+ - TotDrops: the amount of packet that were dropped into the kernel buffer because of lack of space
+ - TotMissed: the amount of packets that were dropped by the physical interface; it is basically
+ the value of the hardware counter into the card. This number is never put to zero, so this number
+ takes into account the *total* number of interface drops starting from the interface power-on.
+ - OrigMissed: the amount of packets that were dropped by the interface *when the capture begins*.
+ This value is used to detect the number of packets dropped by the interface *during the present
+ capture*, so that (ps_ifdrops= TotMissed - OrigMissed).
+*/
+ unsigned int TotNetDrops; //!< keeps the number of packets that have been dropped by the network
+/*!
+ \brief It keeps the number of packets that have been received by the application.
+
+ Packets dropped by the kernel buffer are not counted in this variable. The variable is always
+ equal to (TotAccepted - TotDrops), exept for the case of remote capture, in which we have also
+ packets in fligh, i.e. that have been transmitted by the remote host, but that have not been
+ received (yet) from the client. In this case, (TotAccepted - TotDrops - TotNetDrops) gives a
+ wrong result, since this number does not corresponds always to the number of packet received by
+ the application. For this reason, in the remote capture we need another variable that takes
+ into account of the number of packets actually received by the application.
+*/
+ unsigned int TotCapt;
+#endif /* HAVE_REMOTE */
+};
+
+/*
+ * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H
+ * Tru64 UNIX, and NetBSD pad to make everything line up on a nice boundary.
+ */
+#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000)
+#define PCAP_FDDIPAD 3
+#endif
+
+struct pcap {
+#ifdef WIN32
+ ADAPTER *adapter;
+ LPPACKET Packet;
+ int timeout;
+ int nonblock;
+#else
+ int fd;
+ int selectable_fd;
+ int send_fd;
+#endif /* WIN32 */
+ int snapshot;
+ int linktype;
+ int tzoff; /* timezone offset */
+ int offset; /* offset for proper alignment */
+
+ int break_loop; /* flag set to force break from packet-reading loop */
+
+#ifdef PCAP_FDDIPAD
+ int fddipad;
+#endif
+
+#ifdef MSDOS
+ int inter_packet_wait; /* offline: wait between packets */
+ void (*wait_proc)(void); /* call proc while waiting */
+#endif
+
+ struct pcap_sf sf;
+ struct pcap_md md;
+
+ /*
+ * Read buffer.
+ */
+ int bufsize;
+ u_char *buffer;
+ u_char *bp;
+ int cc;
+
+ /*
+ * Place holder for pcap_next().
+ */
+ u_char *pkt;
+
+ /* We're accepting only packets in this direction/these directions. */
+ pcap_direction_t direction;
+
+ /*
+ * Methods.
+ */
+ int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
+ int (*inject_op)(pcap_t *, const void *, size_t);
+ int (*setfilter_op)(pcap_t *, struct bpf_program *);
+ int (*setdirection_op)(pcap_t *, pcap_direction_t);
+ int (*set_datalink_op)(pcap_t *, int);
+ int (*getnonblock_op)(pcap_t *, char *);
+ int (*setnonblock_op)(pcap_t *, int, char *);
+ int (*stats_op)(pcap_t *, struct pcap_stat *);
+ void (*close_op)(pcap_t *);
+
+ /*
+ * Placeholder for filter code if bpf not in kernel.
+ */
+ struct bpf_program fcode;
+
+ char errbuf[PCAP_ERRBUF_SIZE + 1];
+ int dlt_count;
+ u_int *dlt_list;
+
+ struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
+
+#ifdef HAVE_REMOTE
+#ifndef WIN32 // Win32 already defines 'timeout'
+ int timeout; //!< timeout to be used in the pcap_open()
+#endif
+ /*! \brief '1' if we're the network client; needed by several functions (like pcap_setfilter() ) to know if
+ they have to use the socket or they have to open the local adapter. */
+ int rmt_clientside;
+
+ SOCKET rmt_sockctrl; //!< socket ID of the socket used for the control connection
+ SOCKET rmt_sockdata; //!< socket ID of the socket used for the data connection
+ int rmt_flags; //!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture()
+ int rmt_capstarted; //!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture()
+ struct pcap_samp rmt_samp; //!< Keeps the parameters related to the sampling process.
+ char *currentfilter; //!< Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on.
+#endif /* HAVE_REMOTE */
+};
+
+/*
+ * This is a timeval as stored in disk in a dumpfile.
+ * It has to use the same types everywhere, independent of the actual
+ * `struct timeval'
+ */
+
+struct pcap_timeval {
+ bpf_int32 tv_sec; /* seconds */
+ bpf_int32 tv_usec; /* microseconds */
+};
+
+/*
+ * How a `pcap_pkthdr' is actually stored in the dumpfile.
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure),
+ * and do not make the time stamp anything other than seconds and
+ * microseconds (e.g., seconds and nanoseconds). Instead:
+ *
+ * introduce a new structure for the new format;
+ *
+ * send mail to "tcpdump-workers@tcpdump.org", requesting a new
+ * magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed record
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old record header as well as files with the new record header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes to "patches@tcpdump.org", so that future
+ * versions of libpcap and programs that use it (such as tcpdump) will
+ * be able to read your new capture file format.
+ */
+
+struct pcap_sf_pkthdr {
+ struct pcap_timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+};
+
+/*
+ * How a `pcap_pkthdr' is actually stored in dumpfiles written
+ * by some patched versions of libpcap (e.g. the ones in Red
+ * Hat Linux 6.1 and 6.2).
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ * Instead, introduce a new structure, as per the above.
+ */
+
+struct pcap_sf_patched_pkthdr {
+ struct pcap_timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+ int index;
+ unsigned short protocol;
+ unsigned char pkt_type;
+};
+
+int yylex(void);
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+/* XXX should these be in pcap.h? */
+int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
+int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
+
+#ifndef HAVE_STRLCPY
+#define strlcpy(x, y, z) \
+ (strncpy((x), (y), (z)), \
+ ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
+ strlen((y)))
+#endif
+
+#include <stdarg.h>
+
+#if !defined(HAVE_SNPRINTF)
+#define snprintf pcap_snprintf
+extern int snprintf (char *, size_t, const char *, ...);
+#endif
+
+#if !defined(HAVE_VSNPRINTF)
+#define vsnprintf pcap_vsnprintf
+extern int vsnprintf (char *, size_t, const char *, va_list ap);
+#endif
+
+/*
+ * Routines that most pcap implementations can use for non-blocking mode.
+ */
+#if !defined(WIN32) && !defined(MSDOS)
+int pcap_getnonblock_fd(pcap_t *, char *);
+int pcap_setnonblock_fd(pcap_t *p, int, char *);
+#endif
+
+void pcap_close_common(pcap_t *);
+
+/*
+ * Internal interfaces for "pcap_findalldevs()".
+ *
+ * "pcap_platform_finddevs()" is a platform-dependent routine to
+ * add devices not found by the "standard" mechanisms (SIOCGIFCONF,
+ * "getifaddrs()", etc..
+ *
+ * "pcap_add_if()" adds an interface to the list of interfaces.
+ */
+int pcap_platform_finddevs(pcap_if_t **, char *);
+int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *,
+ size_t, struct sockaddr *, size_t, struct sockaddr *, size_t,
+ struct sockaddr *, size_t, char *);
+int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *);
+struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
+int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
+ const char *, char *);
+
+#ifdef WIN32
+char *pcap_win32strerror(void);
+#endif
+
+int install_bpf_program(pcap_t *, struct bpf_program *);
+
+int pcap_strcasecmp(const char *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Cedar/winpcap/pcap-stdinc.h b/src/Cedar/winpcap/pcap-stdinc.h
new file mode 100644
index 00000000..b04f9be7
--- /dev/null
+++ b/src/Cedar/winpcap/pcap-stdinc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define SIZEOF_CHAR 1
+#define SIZEOF_SHORT 2
+#define SIZEOF_INT 4
+#ifndef _MSC_EXTENSIONS
+#define SIZEOF_LONG_LONG 8
+#endif
+
+
+/*
+ * Avoids a compiler warning in case this was already defined
+ * (someone defined _WINSOCKAPI_ when including 'windows.h', in order
+ * to prevent it from including 'winsock.h')
+ */
+#ifdef _WINSOCKAPI_
+#undef _WINSOCKAPI_
+#endif
+#include <winsock2.h>
+
+#include <fcntl.h>
+
+#include "bittypes.h"
+#include <time.h>
+#include <io.h>
+
+#ifndef __MINGW32__
+#include "IP6_misc.h"
+#endif
+
+#define caddr_t char*
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define inline __inline
diff --git a/src/Cedar/winpcap/pcap.h b/src/Cedar/winpcap/pcap.h
new file mode 100644
index 00000000..7e5a773f
--- /dev/null
+++ b/src/Cedar/winpcap/pcap.h
@@ -0,0 +1,337 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52.2.5 2005/07/07 02:04:36 guy Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_h
+#define lib_pcap_h
+
+#if defined(WIN32)
+ #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+ #include <sys/types.h>
+ #include <sys/socket.h> /* u_int, u_char etc. */
+#else /* UN*X */
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap-bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_REMOTE
+ // We have to define the SOCKET here, although it has been defined in sockutils.h
+ // This is to avoid the distribution of the 'sockutils.h' file around
+ // (for example in the WinPcap developer's pack)
+ #ifndef SOCKET
+ #ifdef WIN32
+ #define SOCKET unsigned int
+ #else
+ #define SOCKET int
+ #endif
+ #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ * introduce a new structure for the new format, if the layout
+ * of the structure changed;
+ *
+ * send mail to "tcpdump-workers@tcpdump.org", requesting a new
+ * magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed file
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old file header as well as files with the new file header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes to "patches@tcpdump.org", so that future
+ * versions of libpcap and programs that use it (such as tcpdump) will
+ * be able to read your new capture file format.
+ */
+struct pcap_file_header {
+ bpf_u_int32 magic;
+ u_short version_major;
+ u_short version_minor;
+ bpf_int32 thiszone; /* gmt to local correction */
+ bpf_u_int32 sigfigs; /* accuracy of timestamps */
+ bpf_u_int32 snaplen; /* max length saved portion of each pkt */
+ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
+};
+
+typedef enum {
+ PCAP_D_INOUT = 0,
+ PCAP_D_IN,
+ PCAP_D_OUT
+} pcap_direction_t;
+
+/*
+ * Each packet in the dump file is prepended with this generic header.
+ * This gets around the problem of different headers for different
+ * packet interfaces.
+ */
+struct pcap_pkthdr {
+ struct timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+ u_int ps_recv; /* number of packets received */
+ u_int ps_drop; /* number of packets dropped */
+ u_int ps_ifdrop; /* drops by interface XXX not yet supported */
+#ifdef HAVE_REMOTE
+ u_int ps_capt; /* number of packets that are received by the application; please get rid off the Win32 ifdef */
+ u_int ps_sent; /* number of packets sent by the server on the network */
+ u_int ps_netdrop; /* number of packets lost on the network */
+#endif /* HAVE_REMOTE */
+};
+
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+ u_long rx_packets; /* total packets received */
+ u_long tx_packets; /* total packets transmitted */
+ u_long rx_bytes; /* total bytes received */
+ u_long tx_bytes; /* total bytes transmitted */
+ u_long rx_errors; /* bad packets received */
+ u_long tx_errors; /* packet transmit problems */
+ u_long rx_dropped; /* no space in Rx buffers */
+ u_long tx_dropped; /* no space available for Tx */
+ u_long multicast; /* multicast packets received */
+ u_long collisions;
+
+ /* detailed rx_errors: */
+ u_long rx_length_errors;
+ u_long rx_over_errors; /* receiver ring buff overflow */
+ u_long rx_crc_errors; /* recv'd pkt with crc error */
+ u_long rx_frame_errors; /* recv'd frame alignment error */
+ u_long rx_fifo_errors; /* recv'r fifo overrun */
+ u_long rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ u_long tx_aborted_errors;
+ u_long tx_carrier_errors;
+ u_long tx_fifo_errors;
+ u_long tx_heartbeat_errors;
+ u_long tx_window_errors;
+ };
+#endif
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+ struct pcap_if *next;
+ char *name; /* name to hand to "pcap_open_live()" */
+ char *description; /* textual description of interface, or NULL */
+ struct pcap_addr *addresses;
+ bpf_u_int32 flags; /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+ struct pcap_addr *next;
+ struct sockaddr *addr; /* address */
+ struct sockaddr *netmask; /* netmask for that address */
+ struct sockaddr *broadaddr; /* broadcast address for that address */
+ struct sockaddr *dstaddr; /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+ const u_char *);
+
+char *pcap_lookupdev(char *);
+int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
+pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_offline(const char *, char *);
+pcap_t *pcap_fopen_offline(FILE *, char *);
+void pcap_close(pcap_t *);
+int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+ pcap_next(pcap_t *, struct pcap_pkthdr *);
+int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+void pcap_breakloop(pcap_t *);
+int pcap_stats(pcap_t *, struct pcap_stat *);
+int pcap_setfilter(pcap_t *, struct bpf_program *);
+int pcap_setdirection(pcap_t *, pcap_direction_t);
+int pcap_getnonblock(pcap_t *, char *);
+int pcap_setnonblock(pcap_t *, int, char *);
+void pcap_perror(pcap_t *, char *);
+int pcap_inject(pcap_t *, const void *, size_t);
+int pcap_sendpacket(pcap_t *, const u_char *, int);
+char *pcap_strerror(int);
+char *pcap_geterr(pcap_t *);
+int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
+ bpf_u_int32);
+int pcap_compile_nopcap(int, int, struct bpf_program *,
+ char *, int, bpf_u_int32);
+void pcap_freecode(struct bpf_program *);
+int pcap_datalink(pcap_t *);
+int pcap_list_datalinks(pcap_t *, int **);
+int pcap_set_datalink(pcap_t *, int);
+int pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+int pcap_snapshot(pcap_t *);
+int pcap_is_swapped(pcap_t *);
+int pcap_major_version(pcap_t *);
+int pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE *pcap_file(pcap_t *);
+int pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+FILE *pcap_dump_file(pcap_dumper_t *);
+long pcap_dump_ftell(pcap_dumper_t *);
+int pcap_dump_flush(pcap_dumper_t *);
+void pcap_dump_close(pcap_dumper_t *);
+void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+int pcap_findalldevs(pcap_if_t **, char *);
+void pcap_freealldevs(pcap_if_t *);
+
+const char *pcap_lib_version(void);
+
+/* XXX this guy lives in the bpf tree */
+u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+int bpf_validate(struct bpf_insn *f, int len);
+char *bpf_image(struct bpf_insn *, int);
+void bpf_dump(struct bpf_program *, int);
+
+#if defined(WIN32)
+
+/*
+ * Win32 definitions
+ */
+
+int pcap_setbuff(pcap_t *p, int dim);
+int pcap_setmode(pcap_t *p, int mode);
+int pcap_setmintocopy(pcap_t *p, int size);
+
+#ifdef WPCAP
+/* Include file with the wpcap-specific extensions */
+#include <Win32-Extensions.h>
+#endif /* WPCAP */
+
+#define MODE_CAPT 0
+#define MODE_STAT 1
+#define MODE_MON 2
+
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
+/*
+ * UN*X definitions
+ */
+
+int pcap_get_selectable_fd(pcap_t *);
+
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifdef HAVE_REMOTE
+/* Includes most of the public stuff that is needed for the remote capture */
+#include "remote-ext.h"
+#endif /* HAVE_REMOTE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Cedar/winpcap/pthread.h b/src/Cedar/winpcap/pthread.h
new file mode 100644
index 00000000..25c3cb5a
--- /dev/null
+++ b/src/Cedar/winpcap/pthread.h
@@ -0,0 +1,1300 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#ifdef _UWIN
+# define HAVE_STRUCT_TIMESPEC 1
+# define HAVE_SIGNAL_H 1
+# undef HAVE_CONFIG_H
+# pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ * Provides an implementation of PThreads based upon the
+ * standard:
+ *
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
+ *
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
+ *
+ * See the ANNOUNCE file for a full list of conforming
+ * routines and defined constants, and a list of missing
+ * routines and constants not defined in this implementation.
+ *
+ * Authors:
+ * There have been many contributors to this library.
+ * The initial implementation was contributed by
+ * John Bossom, and several others have provided major
+ * sections or revisions of parts of the implementation.
+ * Often significant effort has been contributed to
+ * find and fix important bugs and other problems to
+ * improve the reliability of the library, which sometimes
+ * is not reflected in the amount of code which changed as
+ * result.
+ * As much as possible, the contributors are acknowledged
+ * in the ChangeLog file in the source code distribution
+ * where their changes are noted in detail.
+ *
+ * Contributors are listed in the CONTRIBUTORS file.
+ *
+ * As usual, all bouquets go to the contributors, and all
+ * brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ * The code base for this project is coordinated and
+ * eventually pre-tested, packaged, and made available by
+ *
+ * Ross Johnson <rpj@ise.canberra.edu.au>
+ *
+ * QA Testers:
+ * Ultimately, the library is tested in the real world by
+ * a host of competent and demanding scientists and
+ * engineers who report bugs and/or provide solutions
+ * which are then fixed or incorporated into subsequent
+ * versions of the library. Each time a bug is fixed, a
+ * test case is written to prove the fix and ensure
+ * that later changes to the code don't reintroduce the
+ * same error. The number of test cases is slowly growing
+ * and therefore so is the code reliability.
+ *
+ * Compliance:
+ * See the file ANNOUNCE for the list of implemented
+ * and not-implemented routines and defined options.
+ * Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ * The source code and other information about this library
+ * are available from
+ *
+ * http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+/*
+ * FIXME: The pthreadGCE.dll build gets linker unresolved errors
+ * on pthread_key_create() unless windows.h is included here.
+ * It appears to have something to do with an argument type mismatch.
+ * Looking at tsd.o with 'nm' shows this line:
+ * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v
+ * instead of
+ * 00000000 T _pthread_key_create
+ */
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+/*
+ * FIXME: The pthreadGCE.dll build gets linker unresolved errors
+ * on pthread_key_create() unless windows.h is included here.
+ * It appears to have something to do with an argument type mismatch.
+ * Looking at tsd.o with 'nm' shows this line:
+ * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v
+ * instead of
+ * 00000000 T _pthread_key_create
+ */
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#ifndef NEED_FTIME
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <setjmp.h>
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+ PTW32_FALSE = 0,
+ PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define ENOTSUP. If not, we use
+ * the same value as Solaris.
+ */
+#ifndef ENOTSUP
+# define ENOTSUP 48
+#endif
+
+#ifndef ETIMEDOUT
+# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
+#endif
+
+#include <sched.h>
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it. I don't like the potential incompatibility that
+ * this creates with future versions of windows.
+ */
+#ifndef PTW32_INCLUDE_WINDOWS_H
+#ifndef HANDLE
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#ifndef DWORD
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * _POSIX_THREADS (set)
+ * If set, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (set)
+ * If set, you can control the size of a thread's
+ * stack
+ * pthread_attr_getstacksize
+ * pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (not set)
+ * If set, you can allocate and control a thread's
+ * stack. If not supported, the following functions
+ * will return ENOSYS, indicating they are not
+ * supported:
+ * pthread_attr_getstackaddr
+ * pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (set)
+ * If set, you can use realtime scheduling.
+ * Indicates the availability of:
+ * pthread_attr_getinheritsched
+ * pthread_attr_getschedparam
+ * pthread_attr_getschedpolicy
+ * pthread_attr_getscope
+ * pthread_attr_setinheritsched
+ * pthread_attr_setschedparam
+ * pthread_attr_setschedpolicy
+ * pthread_attr_setscope
+ * pthread_getschedparam
+ * pthread_setschedparam
+ * sched_get_priority_max
+ * sched_get_priority_min
+ * sched_rr_set_interval
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (not set)
+ * If set, you can create priority inheritance
+ * mutexes.
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (not set)
+ * If set, you can create priority ceiling mutexes
+ * Indicates the availability of:
+ * pthread_mutex_getprioceiling
+ * pthread_mutex_setprioceiling
+ * pthread_mutexattr_getprioceiling
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprioceiling
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (not set)
+ * If set, you can create mutexes and condition
+ * variables that can be shared with another
+ * process.If set, indicates the availability
+ * of:
+ * pthread_mutexattr_getpshared
+ * pthread_mutexattr_setpshared
+ * pthread_condattr_getpshared
+ * pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (set)
+ * If set you can use the special *_r library
+ * functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (set)
+ * If set, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (set)
+ * If set, you can use spin locks
+ *
+ * _POSIX_BARRIERS (set)
+ * If set, you can use barriers
+ *
+ * + These functions provide both 'inherit' and/or
+ * 'protect' protocol, based upon these macro
+ * settings.
+ *
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Maximum number of attempts to destroy
+ * a thread's thread-specific data on
+ * termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ * Maximum number of thread-specific data keys
+ * available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ * Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ * Maximum number of threads supported per
+ * process (must be at least 64).
+ *
+ * _POSIX_SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (only defined if not already defined)
+ *
+ * _POSIX_SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (only defined if not already defined)
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#ifndef _POSIX_THREADS
+#define _POSIX_THREADS
+#endif
+
+#ifndef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS
+#endif
+
+#ifndef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS
+#endif
+
+#ifndef _POSIX_BARRIERS
+#define _POSIX_BARRIERS
+#endif
+
+#define _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_PRIORITY_SCHEDULING
+
+#if defined( KLUDGE )
+/*
+ * The following are not supported
+ */
+#define _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PROCESS_SHARED
+
+#endif /* KLUDGE */
+
+/*
+ * POSIX Limits
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Standard states this must be at least
+ * 4.
+ *
+ * PTHREAD_KEYS_MAX
+ * WIN32 permits only 64 TLS keys per process.
+ * This limitation could be worked around by
+ * simply simulating keys.
+ *
+ * PTHREADS_STACK_MIN
+ * POSIX specifies 0 which is also the value WIN32
+ * interprets as allowing the system to
+ * set the size to that of the main thread. The
+ * maximum stack size in Win32 is 1Meg. WIN32
+ * allocates more stack as required up to the 1Meg
+ * limit.
+ *
+ * PTHREAD_THREADS_MAX
+ * Not documented by WIN32. Wrote a test program
+ * that kept creating threads until it failed
+ * revealed this approximate number (Windows NT).
+ * This number is somewhat less for Windows 9x
+ * and is effectively less than 64. Perhaps this
+ * constant should be set at DLL load time.
+ *
+ */
+#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+#define PTHREAD_KEYS_MAX 64
+#define PTHREAD_STACK_MIN 0
+#define PTHREAD_THREADS_MAX 2019
+#ifndef _POSIX_SEM_NSEMS_MAX
+/* Not used and only an arbitrary value. */
+# define _POSIX_SEM_NSEMS_MAX 1024
+#endif
+#ifndef _POSIX_SEM_VALUE_MAX
+# define _POSIX_SEM_VALUE_MAX (INT_MAX/2)
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef _DLL
+# ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#endif
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+# include <sys/types.h>
+#else
+typedef struct pthread_t_ *pthread_t;
+typedef struct pthread_attr_t_ *pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ *pthread_key_t;
+typedef struct pthread_mutex_t_ *pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t;
+typedef struct pthread_cond_t_ *pthread_cond_t;
+typedef struct pthread_condattr_t_ *pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ *pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ *pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ *pthread_spinlock_t;
+typedef struct pthread_barrier_t_ *pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ *pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+ PTHREAD_CREATE_JOINABLE = 0, /* Default */
+ PTHREAD_CREATE_DETACHED = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+ PTHREAD_INHERIT_SCHED = 0,
+ PTHREAD_EXPLICIT_SCHED = 1, /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+ PTHREAD_SCOPE_PROCESS = 0,
+ PTHREAD_SCOPE_SYSTEM = 1, /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+ PTHREAD_CANCEL_ENABLE = 0, /* Default */
+ PTHREAD_CANCEL_DISABLE = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+ PTHREAD_CANCEL_ASYNCHRONOUS = 0,
+ PTHREAD_CANCEL_DEFERRED = 1, /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+ PTHREAD_PROCESS_PRIVATE = 0,
+ PTHREAD_PROCESS_SHARED = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+ PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT { PTW32_FALSE, -1 }
+
+struct pthread_once_t_
+{
+ int done; /* indicates if user function executed */
+ long started; /* First thread to increment this value */
+ /* to zero executes the user function */
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+ /* Compatibility with LinuxThreads */
+ PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+ /* For compatibility with POSIX */
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ * WIN32 SEH
+ * C
+ * C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && defined(__GNUC__)
+#error ERROR [__FILE__, line __LINE__]: GNUC does not support SEH.
+#endif
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+typedef void (__cdecl *ptw32_cleanup_callback_t)(void *);
+
+struct ptw32_cleanup_t
+{
+ ptw32_cleanup_callback_t routine;
+ void *arg;
+ struct ptw32_cleanup_t *prev;
+};
+
+#ifdef __CLEANUP_SEH
+ /*
+ * WIN32 SEH version of cancel cleanup.
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
+ _cleanup.arg = (_arg); \
+ __try \
+ { \
+
+#define pthread_cleanup_pop( _execute ) \
+ } \
+ __finally \
+ { \
+ if( _execute || AbnormalTermination()) \
+ { \
+ (*(_cleanup.routine))( _cleanup.arg ); \
+ } \
+ } \
+ }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+ /*
+ * C implementation of PThreads cancel cleanup
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+ (void) ptw32_pop_cleanup( _execute ); \
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+ /*
+ * C++ version of cancel cleanup.
+ * - John E. Bossom.
+ */
+
+ class PThreadCleanup {
+ /*
+ * PThreadCleanup
+ *
+ * Purpose
+ * This class is a C++ helper class that is
+ * used to implement pthread_cleanup_push/
+ * pthread_cleanup_pop.
+ * The destructor of this class automatically
+ * pops the pushed cleanup routine regardless
+ * of how the code exits the scope
+ * (i.e. such as by an exception)
+ */
+ ptw32_cleanup_callback_t cleanUpRout;
+ void * obj;
+ int executeIt;
+
+ public:
+ PThreadCleanup() :
+ cleanUpRout( 0 ),
+ obj( 0 ),
+ executeIt( 0 )
+ /*
+ * No cleanup performed
+ */
+ {
+ }
+
+ PThreadCleanup(
+ ptw32_cleanup_callback_t routine,
+ void * arg ) :
+ cleanUpRout( routine ),
+ obj( arg ),
+ executeIt( 1 )
+ /*
+ * Registers a cleanup routine for 'arg'
+ */
+ {
+ }
+
+ ~PThreadCleanup()
+ {
+ if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+ {
+ (void) (*cleanUpRout)( obj );
+ }
+ }
+
+ void execute( int exec )
+ {
+ executeIt = exec;
+ }
+ };
+
+ /*
+ * C++ implementation of PThreads cancel cleanup;
+ * This implementation takes advantage of a helper
+ * class who's destructor automatically calls the
+ * cleanup routine if we exit our scope weirdly
+ */
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
+ (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+ cleanup.execute( _execute ); \
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int pthread_attr_getdetachstate (const pthread_attr_t * attr,
+ int *detachstate);
+
+PTW32_DLLPORT int pthread_attr_getstackaddr (const pthread_attr_t * attr,
+ void **stackaddr);
+
+PTW32_DLLPORT int pthread_attr_getstacksize (const pthread_attr_t * attr,
+ size_t * stacksize);
+
+PTW32_DLLPORT int pthread_attr_setdetachstate (pthread_attr_t * attr,
+ int detachstate);
+
+PTW32_DLLPORT int pthread_attr_setstackaddr (pthread_attr_t * attr,
+ void *stackaddr);
+
+PTW32_DLLPORT int pthread_attr_setstacksize (pthread_attr_t * attr,
+ size_t stacksize);
+
+PTW32_DLLPORT int pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+
+PTW32_DLLPORT int pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int pthread_attr_setschedpolicy (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int pthread_attr_getschedpolicy (pthread_attr_t *,
+ int *);
+
+PTW32_DLLPORT int pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched);
+
+PTW32_DLLPORT int pthread_attr_getinheritsched(pthread_attr_t * attr,
+ int * inheritsched);
+
+PTW32_DLLPORT int pthread_attr_setscope (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int pthread_attr_getscope (const pthread_attr_t *,
+ int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(*start) (void *),
+ void *arg);
+
+PTW32_DLLPORT int pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int pthread_equal (pthread_t t1,
+ pthread_t t2);
+
+PTW32_DLLPORT void pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int pthread_join (pthread_t thread,
+ void **value_ptr);
+
+PTW32_DLLPORT pthread_t pthread_self (void);
+
+PTW32_DLLPORT int pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int pthread_setcancelstate (int state,
+ int *oldstate);
+
+PTW32_DLLPORT int pthread_setcanceltype (int type,
+ int *oldtype);
+
+PTW32_DLLPORT void pthread_testcancel (void);
+
+PTW32_DLLPORT int pthread_once (pthread_once_t * once_control,
+ void (*init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t *ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ void (*routine) (void *),
+ void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int pthread_key_create (pthread_key_t * key,
+ void (*destructor) (void *));
+
+PTW32_DLLPORT int pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int pthread_setspecific (pthread_key_t key,
+ const void *value);
+
+PTW32_DLLPORT void *pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int pthread_mutexattr_getpshared (const pthread_mutexattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared);
+
+PTW32_DLLPORT int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int pthread_barrierattr_getpshared (const pthread_barrierattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+ int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int pthread_mutex_init (pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int pthread_mutex_timedlock(pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr,
+ unsigned int count);
+
+PTW32_DLLPORT int pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int pthread_condattr_getpshared (const pthread_condattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int pthread_condattr_setpshared (pthread_condattr_t * attr,
+ int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int pthread_cond_init (pthread_cond_t * cond,
+ const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int pthread_setschedparam (pthread_t thread,
+ int policy,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int pthread_getschedparam (pthread_t thread,
+ int *policy,
+ struct sched_param *param);
+
+PTW32_DLLPORT int pthread_setconcurrency (int);
+
+PTW32_DLLPORT int pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int pthread_rwlock_init(pthread_rwlock_t *lock,
+ const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+ int kind);
+PTW32_DLLPORT int pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+ int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int pthread_num_processors_np(void);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int pthread_win32_thread_detach_np(void);
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE pthread_getw32threadhandle_np(pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ * WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int pthreadCancelableTimedWait (HANDLE waitHandle,
+ DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#ifndef _UWIN
+# if defined(NEED_ERRNO)
+ PTW32_DLLPORT int * _errno( void );
+# else
+# ifndef errno
+# if (defined(_MT) || defined(_DLL))
+ __declspec(dllimport) extern int * __cdecl _errno(void);
+# define errno (*_errno())
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * WIN32 C runtime library had been made thread-safe
+ * without affecting the user interface. Provide
+ * mappings from the UNIX thread-safe versions to
+ * the standard C runtime library calls.
+ * Only provide function mappings for functions that
+ * actually exist on WIN32.
+ */
+
+#if !defined(__MINGW32__)
+#define strtok_r( _s, _sep, _lasts ) \
+ ( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+#define asctime_r( _tm, _buf ) \
+ ( strcpy( (_buf), asctime( (_tm) ) ), \
+ (_buf) )
+
+#define ctime_r( _clock, _buf ) \
+ ( strcpy( (_buf), ctime( (_clock) ) ), \
+ (_buf) )
+
+#define gmtime_r( _clock, _result ) \
+ ( *(_result) = *gmtime( (_clock) ), \
+ (_result) )
+
+#define localtime_r( _clock, _result ) \
+ ( *(_result) = *localtime( (_clock) ), \
+ (_result) )
+
+#define rand_r( _seed ) \
+ ( _seed == _seed? rand() : rand() )
+
+
+#ifdef __cplusplus
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef PTW32_BUILD
+
+#ifdef __CLEANUP_SEH
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+ ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_CXX
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#ifdef _MSC_VER
+ /*
+ * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+ * if you want Pthread-Win32 cancelation and pthread_exit to work.
+ */
+
+#ifndef PtW32NoCatchWarn
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message(" cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message(" #ifdef PtW32CatchAll")
+#pragma message(" PtW32CatchAll")
+#pragma message(" #else")
+#pragma message(" catch(...)")
+#pragma message(" #endif")
+#pragma message(" {")
+#pragma message(" /* Catchall block processing */")
+#pragma message(" }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+ catch( ptw32_exception & ) { throw; } \
+ catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+ catch( ptw32_exception & ) { throw; } \
+ catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#ifdef PTW32__HANDLE_DEF
+# undef HANDLE
+#endif
+#ifdef PTW32__DWORD_DEF
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* PTHREAD_H */
diff --git a/src/Cedar/winpcap/remote-ext.h b/src/Cedar/winpcap/remote-ext.h
new file mode 100644
index 00000000..e8e675ec
--- /dev/null
+++ b/src/Cedar/winpcap/remote-ext.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef __REMOTE_EXT_H__
+#define __REMOTE_EXT_H__
+
+
+
+// Definition for Microsoft Visual Studio
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ \file remote-ext.h
+
+ The goal of this file it to include most of the new definitions that should be
+ placed into the pcap.h file.
+
+ It includes all new definitions (structures and functions like pcap_open().
+ Some of the functions are not really a remote feature, but, right now,
+ they are placed here.
+*/
+
+
+
+// All this stuff is public
+/*! \addtogroup remote_struct
+ \{
+*/
+
+
+
+
+/*!
+ \brief Defines the maximum buffer size in which address, port, interface names are kept.
+
+ In case the adapter name or such is larger than this value, it is truncated.
+ This is not used by the user; however it must be aware that an hostname / interface
+ name longer than this value will be truncated.
+*/
+#define PCAP_BUF_SIZE 1024
+
+
+/*! \addtogroup remote_source_ID
+ \{
+*/
+
+
+/*!
+ \brief Internal representation of the type of source in use (file,
+ remote/local interface).
+
+ This indicates a file, i.e. the user want to open a capture from a local file.
+*/
+#define PCAP_SRC_FILE 2
+/*!
+ \brief Internal representation of the type of source in use (file,
+ remote/local interface).
+
+ This indicates a local interface, i.e. the user want to open a capture from
+ a local interface. This does not involve the RPCAP protocol.
+*/
+#define PCAP_SRC_IFLOCAL 3
+/*!
+ \brief Internal representation of the type of source in use (file,
+ remote/local interface).
+
+ This indicates a remote interface, i.e. the user want to open a capture from
+ an interface on a remote host. This does involve the RPCAP protocol.
+*/
+#define PCAP_SRC_IFREMOTE 4
+
+/*!
+ \}
+*/
+
+
+
+/*! \addtogroup remote_source_string
+
+ The formats allowed by the pcap_open() are the following:
+ - file://path_and_filename [opens a local file]
+ - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
+ - rpcap://host/devicename [opens the selected device available on a remote host]
+ - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
+ - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
+ - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
+
+ The formats allowed by the pcap_findalldevs_ex() are the following:
+ - file://folder/ [lists all the files in the given folder]
+ - rpcap:// [lists all local adapters]
+ - rpcap://host:port/ [lists the devices available on a remote host]
+
+ Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since
+ IPv6 is fully supported, these are the allowed formats:
+
+ - host (literal): e.g. host.foo.bar
+ - host (numeric IPv4): e.g. 10.11.12.13
+ - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
+ - host (numeric IPv6): e.g. [1:2:3::4]
+ - port: can be either numeric (e.g. '80') or literal (e.g. 'http')
+
+ Here you find some allowed examples:
+ - rpcap://host.foo.bar/devicename [everything literal, no port number]
+ - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
+ - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
+ - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
+ - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
+ - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
+ - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
+ - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
+
+ \{
+*/
+
+
+/*!
+ \brief String that will be used to determine the type of source in use (file,
+ remote/local interface).
+
+ This string will be prepended to the interface name in order to create a string
+ that contains all the information required to open the source.
+
+ This string indicates that the user wants to open a capture from a local file.
+*/
+#define PCAP_SRC_FILE_STRING "file://"
+/*!
+ \brief String that will be used to determine the type of source in use (file,
+ remote/local interface).
+
+ This string will be prepended to the interface name in order to create a string
+ that contains all the information required to open the source.
+
+ This string indicates that the user wants to open a capture from a network interface.
+ This string does not necessarily involve the use of the RPCAP protocol. If the
+ interface required resides on the local host, the RPCAP protocol is not involved
+ and the local functions are used.
+*/
+#define PCAP_SRC_IF_STRING "rpcap://"
+
+/*!
+ \}
+*/
+
+
+
+
+
+/*!
+ \addtogroup remote_open_flags
+ \{
+*/
+
+/*!
+ \brief It defines if the adapter has to go in promiscuous mode.
+
+ It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.
+ Note that even if this parameter is false, the interface could well be in promiscuous
+ mode for some other reason (for example because another capture process with
+ promiscuous mode enabled is currently using that interface).
+ On on Linux systems with 2.2 or later kernels (that have the "any" device), this
+ flag does not work on the "any" device; if an argument of "any" is supplied,
+ the 'promisc' flag is ignored.
+*/
+#define PCAP_OPENFLAG_PROMISCUOUS 1
+
+/*!
+ \brief It defines if the data trasfer (in case of a remote
+ capture) has to be done with UDP protocol.
+
+ If it is '1' if you want a UDP data connection, '0' if you want
+ a TCP data connection; control connection is always TCP-based.
+ A UDP connection is much lighter, but it does not guarantee that all
+ the captured packets arrive to the client workstation. Moreover,
+ it could be harmful in case of network congestion.
+ This flag is meaningless if the source is not a remote interface.
+ In that case, it is simply ignored.
+*/
+#define PCAP_OPENFLAG_DATATX_UDP 2
+
+
+/*!
+ \brief It defines if the remote probe has to capture its own generated traffic.
+
+ In case the remote probe uses the same interface to capture traffic and to send
+ data back to the caller, the captured traffic includes the RPCAP traffic as well.
+ If this flag is turned on, the RPCAP traffic is excluded from the capture, so that
+ the trace returned back to the collector is does not include this traffic.
+*/
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4
+/*!
+ \}
+*/
+
+
+/*!
+ \addtogroup remote_samp_methods
+ \{
+*/
+
+/*!
+ \brief No sampling has to be done on the current capture.
+
+ In this case, no sampling algorithms are applied to the current capture.
+*/
+#define PCAP_SAMP_NOSAMP 0
+
+/*!
+ \brief It defines that only 1 out of N packets must be returned to the user.
+
+ In this case, the 'value' field of the 'pcap_samp' structure indicates the
+ number of packets (minus 1) that must be discarded before one packet got accepted.
+ In other words, if 'value = 10', the first packet is returned to the caller, while
+ the following 9 are discarded.
+*/
+#define PCAP_SAMP_1_EVERY_N 1
+
+/*!
+ \brief It defines that we have to return 1 packet every N milliseconds.
+
+ In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting
+ time' in milliseconds before one packet got accepted.
+ In other words, if 'value = 10', the first packet is returned to the caller; the next
+ returned one will be the first packet that arrives when 10ms have elapsed.
+*/
+#define PCAP_SAMP_FIRST_AFTER_N_MS 2
+
+/*!
+ \}
+*/
+
+
+/*!
+ \addtogroup remote_auth_methods
+ \{
+*/
+
+/*!
+ \brief It defines the NULL authentication.
+
+ This value has to be used within the 'type' member of the pcap_rmtauth structure.
+ The 'NULL' authentication has to be equal to 'zero', so that old applications
+ can just put every field of struct pcap_rmtauth to zero, and it does work.
+*/
+#define RPCAP_RMTAUTH_NULL 0
+/*!
+ \brief It defines the username/password authentication.
+
+ With this type of authentication, the RPCAP protocol will use the username/
+ password provided to authenticate the user on the remote machine. If the
+ authentication is successful (and the user has the right to open network devices)
+ the RPCAP connection will continue; otherwise it will be dropped.
+
+ This value has to be used within the 'type' member of the pcap_rmtauth structure.
+*/
+#define RPCAP_RMTAUTH_PWD 1
+
+/*!
+ \}
+*/
+
+
+
+
+/*!
+
+ \brief This structure keeps the information needed to autheticate
+ the user on a remote machine.
+
+ The remote machine can either grant or refuse the access according
+ to the information provided.
+ In case the NULL authentication is required, both 'username' and
+ 'password' can be NULL pointers.
+
+ This structure is meaningless if the source is not a remote interface;
+ in that case, the functions which requires such a structure can accept
+ a NULL pointer as well.
+*/
+struct pcap_rmtauth
+{
+ /*!
+ \brief Type of the authentication required.
+
+ In order to provide maximum flexibility, we can support different types
+ of authentication based on the value of this 'type' variable. The currently
+ supported authentication methods are defined into the
+ \link remote_auth_methods Remote Authentication Methods Section\endlink.
+
+ */
+ int type;
+ /*!
+ \brief Zero-terminated string containing the username that has to be
+ used on the remote machine for authentication.
+
+ This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ and it can be NULL.
+ */
+ char *username;
+ /*!
+ \brief Zero-terminated string containing the password that has to be
+ used on the remote machine for authentication.
+
+ This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ and it can be NULL.
+ */
+ char *password;
+};
+
+
+/*!
+ \brief This structure defines the information related to sampling.
+
+ In case the sampling is requested, the capturing device should read
+ only a subset of the packets coming from the source. The returned packets depend
+ on the sampling parameters.
+
+ \warning The sampling process is applied <strong>after</strong> the filtering process.
+ In other words, packets are filtered first, then the sampling process selects a
+ subset of the 'filtered' packets and it returns them to the caller.
+*/
+struct pcap_samp
+{
+ /*!
+ Method used for sampling. Currently, the supported methods are listed in the
+ \link remote_samp_methods Sampling Methods Section\endlink.
+ */
+ int method;
+
+ /*!
+ This value depends on the sampling method defined. For its meaning, please check
+ at the \link remote_samp_methods Sampling Methods Section\endlink.
+ */
+ int value;
+};
+
+
+
+
+//! Maximum lenght of an host name (needed for the RPCAP active mode)
+#define RPCAP_HOSTLIST_SIZE 1024
+
+
+/*!
+ \}
+*/ // end of public documentation
+
+
+// Exported functions
+
+
+
+/** \name New WinPcap functions
+
+ This section lists the new functions that are able to help considerably in writing
+ WinPcap programs because of their easiness of use.
+ */
+//\{
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);
+int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);
+int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+struct pcap_samp *pcap_setsampling(pcap_t *p);
+
+//\}
+// End of new winpcap functions
+
+
+
+/** \name Remote Capture functions
+ */
+//\{
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);
+int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);
+int pcap_remoteact_close(const char *host, char *errbuf);
+void pcap_remoteact_cleanup();
+//\}
+// End of remote capture functions
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/src/Cedar/winpcap/sched.h b/src/Cedar/winpcap/sched.h
new file mode 100644
index 00000000..8f4ddf4c
--- /dev/null
+++ b/src/Cedar/winpcap/sched.h
@@ -0,0 +1,174 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ * Provides an implementation of POSIX realtime extensions
+ * as defined in
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+#else
+# define PTW32_DLLPORT __declspec (dllimport)
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if defined(__MINGW32__) || defined(_UWIN)
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+/* For pid_t */
+# include <sys/types.h>
+/* Required by Unix 98 */
+# include <time.h>
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+#else
+typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+ SCHED_OTHER = 0,
+ SCHED_FIFO,
+ SCHED_RR,
+ SCHED_MIN = SCHED_OTHER,
+ SCHED_MAX = SCHED_RR
+};
+
+struct sched_param {
+ int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+PTW32_DLLPORT int sched_yield (void);
+
+PTW32_DLLPORT int sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+ ( errno = ENOTSUP, (int) -1 )
+
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !_SCHED_H */
+
diff --git a/src/Cedar/winpcap/semaphore.h b/src/Cedar/winpcap/semaphore.h
new file mode 100644
index 00000000..733f0ae3
--- /dev/null
+++ b/src/Cedar/winpcap/semaphore.h
@@ -0,0 +1,163 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+#else
+# define PTW32_DLLPORT __declspec (dllimport)
+#endif
+
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifndef HAVE_MODE_T
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int sem_init (sem_t * sem,
+ int pshared,
+ unsigned int value);
+
+PTW32_DLLPORT int sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int sem_timedwait (sem_t * sem,
+ const struct timespec * abstime);
+
+PTW32_DLLPORT int sem_post (sem_t * sem);
+
+PTW32_DLLPORT int sem_post_multiple (sem_t * sem,
+ int count);
+
+PTW32_DLLPORT int sem_open (const char * name,
+ int oflag,
+ mode_t mode,
+ unsigned int value);
+
+PTW32_DLLPORT int sem_close (sem_t * sem);
+
+PTW32_DLLPORT int sem_unlink (const char * name);
+
+PTW32_DLLPORT int sem_getvalue (sem_t * sem,
+ int * sval);
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !SEMAPHORE_H */
diff --git a/src/Cedar/winpcap/tcp_session.h b/src/Cedar/winpcap/tcp_session.h
new file mode 100644
index 00000000..33aa99e1
--- /dev/null
+++ b/src/Cedar/winpcap/tcp_session.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define UNKNOWN 0
+#define SYN_RCV 1
+#define SYN_ACK_RCV 2
+#define ESTABLISHED 3
+#define CLOSED_RST 4
+#define FIN_CLN_RCV 5
+#define FIN_SRV_RCV 6
+#define CLOSED_FIN 7
+#define ERROR_TCP 8
+#define FIRST_IS_CLN 0
+#define FIRST_IS_SRV 0xffffffff
+#define FIN_CLN 1
+#define FIN_SRV 2
+
+#define MAX_WINDOW 65536
+
+typedef struct __tcp_data
+{
+ struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
+ struct timeval syn_timestamp;
+ struct timeval last_timestamp;
+ struct timeval syn_ack_timestamp;
+ uint32 direction;
+ uint32 seq_n_0_srv;
+ uint32 seq_n_0_cln;
+ uint32 ack_srv; /* acknowledge of (data sent by server) */
+ uint32 ack_cln; /* acknowledge of (data sent by client) */
+ uint32 status;
+ uint32 pkts_cln_to_srv;
+ uint32 pkts_srv_to_cln;
+ uint32 bytes_srv_to_cln;
+ uint32 bytes_cln_to_srv;
+ uint32 close_state;
+}
+ tcp_data;
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+#define TCP_SESSION 0x00000800
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
diff --git a/src/Cedar/winpcap/time_calls.h b/src/Cedar/winpcap/time_calls.h
new file mode 100644
index 00000000..6532162a
--- /dev/null
+++ b/src/Cedar/winpcap/time_calls.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+#include "ndis.h"
+
+#define DEFAULT_TIMESTAMPMODE 0
+
+#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
+#define TIMESTAMPMODE_QUERYSYSTEMTIME 2
+#define TIMESTAMPMODE_RDTSC 3
+
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
+
+#define TIMESTAMPMODE_REGKEY L"TimestampMode"
+
+extern ULONG TimestampMode;
+
+/*!
+ \brief A microsecond precise timestamp.
+
+ included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
+*/
+
+struct timeval {
+ long tv_sec; ///< seconds
+ long tv_usec; ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv
+{
+ ULONGLONG reference;
+ struct timeval start[32];
+};
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+// data->start.tv_sec = 0;
+// data->start.tv_usec = 0;
+}
+
+
+__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
+{
+ ULONG NewLength;
+ PWSTR NullTerminatedString;
+ RTL_QUERY_REGISTRY_TABLE Queries[2];
+ ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
+
+ NewLength = RegistryPath->Length/2;
+
+ NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));
+
+ if (NullTerminatedString != NULL)
+ {
+ RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
+
+ NullTerminatedString[NewLength]=0;
+
+ RtlZeroMemory(Queries, sizeof(Queries));
+
+ Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Queries[0].Name = TIMESTAMPMODE_REGKEY;
+ Queries[0].EntryContext = &TimestampMode;
+ Queries[0].DefaultType = REG_DWORD;
+ Queries[0].DefaultData = &DefaultTimestampMode;
+ Queries[0].DefaultLength = sizeof(ULONG);
+
+ if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
+ {
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+ }
+
+ RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY, REG_DWORD, &TimestampMode,sizeof(ULONG));
+ ExFreePool(NullTerminatedString);
+ }
+ else
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+}
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+/* KeQueryPerformanceCounter TimeStamps */
+__inline void SynchronizeOnCpu(struct timeval *start)
+{
+// struct timeval *start = (struct timeval*)Data;
+
+ struct timeval tmp;
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER i;
+ ULONG tmp2;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ // get the absolute value of the system boot time.
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+
+ start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+
+ start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+ start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (start->tv_usec < 0)
+ {
+ start->tv_sec --;
+ start->tv_usec += 1000000;
+ }
+}
+
+/*RDTSC timestamps */
+/* callers must be at IRQL=PASSIVE_LEVEL*/
+__inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+
+ i.QuadPart=-3500000;
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ KeLowerIrql(old);
+
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+ KeLowerIrql(old);
+
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000)
+ {
+ delta/=16;
+ delta2/=16;
+ }
+
+ reference=delta*(start_freq.QuadPart)/delta2;
+
+ data->reference=reference/1000;
+
+ if (reference%1000>500)
+ data->reference++;
+
+ data->reference*=1000;
+
+ reference=data->reference;
+
+ KeQuerySystemTime(&system_time);
+
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+
+ system_time.QuadPart-=116444736000000000;
+
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+
+ if (tmp.tv_usec<0)
+ {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+
+ data->start[0] = tmp;
+
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ ULONG NumberOfCpus, i;
+ KAFFINITY AffinityMask;
+
+ if (data->reference != 0)
+ return;
+
+ NumberOfCpus = NdisSystemProcessorCount();
+
+ if ( TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ for (i = 0 ; i < NumberOfCpus ; i++ )
+ {
+ AffinityMask = (1 << i);
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ SynchronizeOnCpu(&(data->start[i]));
+ }
+ AffinityMask = 0xFFFFFFFF;
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ data->reference = 1;
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ //do nothing
+ data->reference = 1;
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ TimeSynchronizeRDTSC(data);
+ }
+ else
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ SynchronizeOnCpu(data->start);
+ data->reference = 1;
+ }
+ return;
+}
+
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+ ULONG CurrentCpu;
+ static struct timeval old_ts={0,0};
+
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ //actually this code is ok only if we are guaranteed that no thread scheduling will take place.
+ CurrentCpu = KeGetCurrentProcessorNumber();
+
+ dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
+ dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
+ {
+ if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec && old_ts.tv_usec > dst->tv_usec) )
+ *dst = old_ts;
+
+ else
+ old_ts = *dst;
+ }
+ }
+ else
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ dst->tv_sec = data->start[0].tv_sec + tmp;
+ dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+ }
+}
+
+__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
+{
+
+ ULONGLONG tmp;
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ if (data->reference==0)
+ {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+
+ dst->tv_sec+=data->start[0].tv_sec;
+
+ dst->tv_usec+=data->start[0].tv_usec;
+
+ if (dst->tv_usec>=1000000)
+ {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+
+
+}
+
+__inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER SystemTime;
+
+ KeQuerySystemTime(&SystemTime);
+
+ dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+ dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+}
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ GetTimeRDTSC(dst,data);
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ GetTimeQST(dst,data);
+ }
+ else
+ {
+ GetTimeKQPC(dst,data);
+ }
+}
+
+
+#else /*WIN_NT_DRIVER*/
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start[0]=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+ *dst=data->start[0];
+}
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif /*_time_calls*/
diff --git a/src/Cedar/winpcap/tme.h b/src/Cedar/winpcap/tme.h
new file mode 100644
index 00000000..eb8d4b12
--- /dev/null
+++ b/src/Cedar/winpcap/tme.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+#include "ndis.h"
+#else
+#include <windows.h>
+#endif /*WIN_NT_DRIVER*/
+
+#include "memory_t.h"
+#include "time_calls.h"
+
+
+/* error codes */
+#define TME_ERROR 0
+#define TME_SUCCESS 1
+#define TME_TRUE 2
+#define TME_FALSE 3
+
+/* some constants */
+#define DEFAULT_MEM_EX_SIZE 65536
+#define MAX_TME_DATA_BLOCKS 4
+#define TME_NONE_ACTIVE 0xffffffff
+#define DELTA_READ 2 /* secs */
+
+#define TME_LUT_ENTRIES 0x00000000
+#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
+#define TME_REHASHING_VALUE 0x00000002
+#define TME_KEY_LEN 0x00000003
+#define TME_SHARED_MEMORY_BLOCKS 0x00000004
+#define TME_FILLED_ENTRIES 0x00000005
+#define TME_BLOCK_SIZE 0x00000006
+#define TME_EXTRA_SEGMENT_SIZE 0x00000007
+#define TME_LOOKUP_CODE 0x00000008
+#define TME_OUT_LUT_EXEC 0x00000009
+#define TME_FILLED_BLOCKS 0x0000000a
+#define TME_DEFAULT_EXEC 0x0000000b
+#define TME_LUT_BASE_ADDRESS 0x0000000c
+#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
+#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
+#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
+#define TME_LAST_FOUND_BLOCK 0x00000010
+/* TME default values */
+#define TME_LUT_ENTRIES_DEFAULT 32007
+#define TME_REHASHING_VALUE_DEFAULT 1
+#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
+#define TME_BLOCK_SIZE_DEFAULT 64
+#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
+#define TME_LOOKUP_CODE_DEFAULT 0
+#define TME_OUT_LUT_EXEC_DEFAULT 0
+#define TME_DEFAULT_EXEC_DEFAULT 0
+#define TME_MAX_FILL_STATE_DEFAULT 15000
+
+#define IS_VALIDATED(src,index) (src&(1<<index))
+
+#define VALIDATE(src,index) src|=(1<<index);
+
+
+#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
+
+/* TME callback prototypes */
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+ uint32 block;
+ uint32 exec_fcn;
+}
+ RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+ uint32 lut_entries;
+ uint32 max_fill_state;
+ uint32 rehashing_value;
+ uint32 key_len;
+ uint32 shared_memory_blocks;
+ uint32 filled_entries;
+ uint32 block_size;
+ uint32 extra_segment_size;
+ uint32 filled_blocks;
+ lut_fcn lookup_code;
+ uint32 default_exec;
+ uint32 out_lut_exec;
+ uint8 *lut_base_address;
+ uint8 *shared_memory_base_address;
+ uint8 *extra_segment_base_address;
+ struct timeval last_read;
+ uint32 enable_deletion;
+ uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+ uint32 working;
+ uint32 active;
+ uint32 validated_blocks;
+ TME_DATA block_data[MAX_TME_DATA_BLOCKS];
+ uint32 active_read;
+
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+ struct timeval *ts=(struct timeval*)timestamp;
+
+ if (data->enable_deletion==FALSE)
+ return FALSE;
+ if (data->filled_entries<data->max_fill_state)
+ return FALSE;
+ if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
diff --git a/src/CurrentBuild.txt b/src/CurrentBuild.txt
new file mode 100644
index 00000000..07224bce
--- /dev/null
+++ b/src/CurrentBuild.txt
@@ -0,0 +1,4 @@
+BUILD_NUMBER 9408
+VERSION 403
+BUILD_NAME rtm
+BUILD_DATE 20140104_191055
diff --git a/src/GlobalConst.h b/src/GlobalConst.h
new file mode 100644
index 00000000..2c199ed6
--- /dev/null
+++ b/src/GlobalConst.h
@@ -0,0 +1,151 @@
+// SoftEther VPN Source Code
+// Global Constants Header
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#pragma warning(disable : 4819)
+
+#ifndef GLOBAL_CONST_H
+#define GLOBAL_CONST_H
+
+//// Brand
+// (Define it if building SoftEther VPN Project.)
+#define GC_SOFTETHER_VPN
+#define GC_SOFTETHER_OSS
+
+//// Basic Variables
+
+#define CEDAR_PRODUCT_STR "SoftEther"
+#define CEDAR_PRODUCT_STR_W L"SoftEther"
+#define CEDAR_SERVER_STR "SoftEther VPN Server"
+#define CEDAR_BRIDGE_STR "SoftEther VPN Bridge"
+#define CEDAR_BETA_SERVER "SoftEther VPN Server Pre Release"
+#define CEDAR_MANAGER_STR "SoftEther VPN Server Manager"
+#define CEDAR_CUI_STR "SoftEther VPN Command-Line Admin Tool"
+#define CEDAR_ELOG "SoftEther EtherLogger"
+#define CEDAR_CLIENT_STR "SoftEther VPN Client"
+#define CEDAR_CLIENT_MANAGER_STR "SoftEther VPN Client Connection Manager"
+#define CEDAR_ROUTER_STR "SoftEther VPN User-mode Router"
+#define CEDAR_SERVER_LINK_STR "SoftEther VPN Server (Cascade Mode)"
+#define CEDAR_BRIDGE_LINK_STR "SoftEther VPN Bridge (Cascade Mode)"
+#define CEDAR_SERVER_FARM_STR "SoftEther VPN Server (Cluster RPC Mode)"
+
+
+
+//// Default Port Number
+
+#define GC_DEFAULT_PORT 5555
+#define GC_CLIENT_CONFIG_PORT 9930
+#define GC_CLIENT_NOTIFY_PORT 9983
+
+
+//// Software Name
+
+#define GC_SVC_NAME_VPNSERVER "SEVPNSERVER"
+#define GC_SVC_NAME_VPNCLIENT "SEVPNCLIENT"
+#define GC_SVC_NAME_VPNBRIDGE "SEVPNBRIDGE"
+
+
+
+//// Registry
+
+#define GC_REG_COMPANY_NAME "SoftEther Project"
+
+
+
+
+//// Setup Wizard
+
+#define GC_SW_UIHELPER_REGVALUE "SoftEther VPN Client UI Helper"
+#define GC_SW_SOFTETHER_PREFIX "se"
+#define GC_SW_SOFTETHER_PREFIX_W L"se"
+
+
+
+//// VPN UI Components
+
+#define GC_UI_APPID_CM L"SoftEther.SoftEther VPN Client"
+
+
+
+#endif // GLOBAL_CONST_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Ham/Cert.ico b/src/Ham/Cert.ico
new file mode 100644
index 00000000..ec86d51a
--- /dev/null
+++ b/src/Ham/Cert.ico
Binary files differ
diff --git a/src/Ham/Ham.c b/src/Ham/Ham.c
new file mode 100644
index 00000000..faf24a80
--- /dev/null
+++ b/src/Ham/Ham.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, VPN Hamster !!\n");
+ return 0;
+}
diff --git a/src/Ham/Ham.h b/src/Ham/Ham.h
new file mode 100644
index 00000000..d3f5a12f
--- /dev/null
+++ b/src/Ham/Ham.h
@@ -0,0 +1 @@
+
diff --git a/src/Ham/Ham.rc b/src/Ham/Ham.rc
new file mode 100644
index 00000000..f39cbd95
--- /dev/null
+++ b/src/Ham/Ham.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON2 ICON "NIC.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/Ham/Ham.vcproj b/src/Ham/Ham.vcproj
new file mode 100644
index 00000000..0cf4a043
--- /dev/null
+++ b/src/Ham/Ham.vcproj
@@ -0,0 +1,471 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Ham"
+ ProjectGUID="{1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}"
+ RootNamespace="Ham"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\Ham.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="1"
+ Profile="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\Ham_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="17"
+ Profile="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\Ham.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ IgnoreAllDefaultLibraries="false"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="1"
+ Profile="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\Ham_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ IgnoreAllDefaultLibraries="false"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="17"
+ Profile="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Ham.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Mon.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Scan.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Ham.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Mon.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Scan.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Cert.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Ham.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\NIC.ico"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Ham/Mon.c b/src/Ham/Mon.c
new file mode 100644
index 00000000..d3f5a12f
--- /dev/null
+++ b/src/Ham/Mon.c
@@ -0,0 +1 @@
+
diff --git a/src/Ham/Mon.h b/src/Ham/Mon.h
new file mode 100644
index 00000000..d3f5a12f
--- /dev/null
+++ b/src/Ham/Mon.h
@@ -0,0 +1 @@
+
diff --git a/src/Ham/NIC.ico b/src/Ham/NIC.ico
new file mode 100644
index 00000000..0310b265
--- /dev/null
+++ b/src/Ham/NIC.ico
Binary files differ
diff --git a/src/Ham/Scan.c b/src/Ham/Scan.c
new file mode 100644
index 00000000..d3f5a12f
--- /dev/null
+++ b/src/Ham/Scan.c
@@ -0,0 +1 @@
+
diff --git a/src/Ham/Scan.h b/src/Ham/Scan.h
new file mode 100644
index 00000000..d3f5a12f
--- /dev/null
+++ b/src/Ham/Scan.h
@@ -0,0 +1 @@
+
diff --git a/src/Ham/resource.h b/src/Ham/resource.h
new file mode 100644
index 00000000..2f5bec73
--- /dev/null
+++ b/src/Ham/resource.h
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Ham.rc
+//
+#define IDR_TEST1 101
+#define IDI_ICON1 102
+#define IDI_CERT 102
+#define IDI_ICON2 103
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/LICENSE b/src/LICENSE
new file mode 100644
index 00000000..52c728da
--- /dev/null
+++ b/src/LICENSE
@@ -0,0 +1,2350 @@
+SoftEther VPN Server, Client and Bridge are free software, and released as
+open-source. You can redistribute them and/or modify them under the terms of
+the GNU General Public License version 2 as published by the Free Software
+Foundation.
+
+Copyright (c) 2012-2014 Daiyuu Nobori.
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+Copyright (c) 2012-2014 SoftEther Corporation.
+All Rights Reserved.
+http://www.softether.org/
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License version 2 as published by the Free
+Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License version 2
+along with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+Neither the name of SoftEther nor the names of its contributors may be used to
+endorse or promote products derived from this software without specific prior
+written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
+JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
+DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
+JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
+AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
+SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
+OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
+AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
+JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
+ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
+PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
+LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS SOFTWARE
+INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES PROHIBIT ENCRYPTED
+COMMUNICATIONS. USING THIS SOFTWARE IN OTHER COUNTRIES MIGHT BE RESTRICTED.
+
+THE FOLLOWING GPLV2 CONDITIONS APPLY ON ALL SOFTETHER VPN PROGRAMS WHICH ARE
+DEVELOPED BY SOFTETHER VPN PROJECT.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Lesser General Public License instead.) You can apply it
+to your programs, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and modification
+follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included
+without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running the Program
+is not restricted, and the output from the Program is covered only if its
+contents constitute a work based on the Program (independent of having been
+made by running the Program). Whether that is true depends on what the Program
+does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole
+or in part contains or is derived from the Program or any part thereof, to be
+licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+ c) If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the most
+ordinary way, to print or display an announcement including an appropriate
+copyright notice and a notice that there is no warranty (or else, saying that
+you provide a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this License.
+(Exception: if the Program itself is interactive but does not normally print
+such an announcement, your work based on the Program is not required to print
+an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with
+the Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections 1 and
+2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only for
+noncommercial distribution and only if you received the program in object code
+or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the executable. However, as a special exception, the source
+code distributed need not include anything that is normally distributed (in
+either source or binary form) with the major components (compiler, kernel, and
+so on) of the operating system on which the executable runs, unless that
+component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to
+copy from a designated place, then offering equivalent access to copy the
+source code from the same place counts as distribution of the source code,
+even though third parties are not compelled to copy the source along with the
+object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the
+Program (or any work based on the Program), you indicate your acceptance of
+this License to do so, and all its terms and conditions for copying,
+distributing or modifying the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of this License,
+you may choose any version ever published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+Note that the above copyright notices and use conditions do not apply on the
+software components listed in below which are included in this Software. When
+you use or distribute Software with including these libraries, you have to
+follow the conditions of these libraries.
+
+These library's copyright notices and conditions are following;
+
+-------------------
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES
+
+SoftEther provides source codes of some GPL/LGPL/other libraries listed above
+on its web server. Anyone can download, use and re-distribute them under
+individual licenses which are contained on each archive file, available from
+the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES WRITTEN BY SOFTETHER CORPORATION
+
+Note for users of non-Windows version of PacketiX VPN: The enumerated bundle
+of License Agreements above are copies of original License Agreements of each
+library programs which PacketiX VPN uses. PacketiX VPN is not a delivered work
+from these libraries. PacketiX VPN is a separated work from the libraries, but
+it may call functions of the libraries (whether or not PacketiX VPN calls such
+functions are depended on the user's intention to link them or not on user's
+side computer). While some libraries indicate GPL or LGPL as a condition to
+re-distribute, PacketiX VPN is not license under GPL nor LGPL. Therefore, we
+took special care not to make PacketiX VPN become delivered works of any GPL
+or LGPL libraries. In order to achieve that, both PacketiX VPN and GPL/LGPL
+libraries are distributed with isolated forms (means that any program files of
+PacketiX VPN are not bound nor linked to any GPL/LGPL libraries). If a user of
+PacketiX VPN wants to link GPL/LGPL libraries by their own decisions,
+operations and responsibilities, he may do that on his computer. However, if a
+delivered work under copyright law is created as a result of such an
+operation, such a delivered work must not re-distributed to other people,
+because it may violate GPL/LGPL libraries' conditions.
+
+Note for users of Windows version of PacketiX VPN: For technical reason, the
+above texts are exactly same as a file which is also contained on the
+non-Windows version of PacketiX VPN. Actually, the Windows version of PacketiX
+VPN has no relations to any GPL/LGPL libraries enumerated above.
+
+SoftEther Corporation provides source codes of some GPL/LGPL/other libraries
+listed above on its web server. Anyone can download, use and re-distribute
+them under individual licenses which are contained on each archive file,
+available from the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+THE IMPORTANT NOTICES ABOUT SOFTETHER VPN
+
+FUNCTIONS OF VPN COMMUNICATIONS EMBEDDED ON THIS SOFTWARE ARE VERY POWERFUL
+THAN EVER. THIS STRONG VPN ABILITY WILL BRING YOU HUGE BENEFITS. HOWEVER, IF
+YOU MISUSE THIS SOFTWARE, IT MIGHT DAMAGES YOURSELF. IN ORDER TO AVOID SUCH
+RISKS, THIS DOCUMENT ACCOUNTS IMPORTANT NOTICES FOR CUSTOMERS WHO ARE WILLING
+TO USE THIS SOFTWARE. THE FOLLOWING INSTRUCTIONS ARE VERY IMPORTANT. READ AND
+UNDERSTAND IT CAREFULLY. ADDITIONALLY, IF YOU ARE PLANNING TO USE THE DYNAMIC
+DNS, THE NAT TRAVERSAL OR THE VPN AZURE FUNCTIONS, READ THE SECTION 3.5
+CAREFULLY. THESE FUNCTIONS ARE FREE SERVICES PROVIDED VIA THE INTERNET, ARE
+NOT GUARANTEED, AND ARE NOT INTENDED TO BE USED FOR BUSINESS OR COMMERCIAL
+USE. DO NOT USE THESE SERVICES FOR YOUR BUSINESS OR COMMERCIAL USE.
+
+
+1. VPN Communication Protocols
+1.1. SoftEther VPN Protocol
+SoftEther VPN can perform VPN communication. Unlike traditional VPN protocols,
+SoftEther VPN has an implementation of the newly-designed "SoftEther VPN
+Protocol (SE-VPN Protocol)" . SE-VPN protocol encapsulates any Ethernet
+packets into a HTTPS (HTTP over SSL) connection. Therefore SE-VPN protocol can
+communicate beyond firewalls even if the firewall is configured to block
+traditional VPN packets by network administrator. SE-VPN protocol is designed
+and implemented to comply TLS 1.0 (RFC 5246) and HTTPS (RFC 2818). However, it
+sometimes have different behavior to RFCs. If you are a network administrator
+and want to block SE-VPN protocols on the firewall, you can adopt a
+"white-list" policy on the firewall to filter any TCP or UDP packets on the
+border except explicitly allowed packets towards specific web sites and
+servers.
+
+1.2. NAT Traversal Function
+Generally, if you use traditional VPN systems you have to request a network
+administrator to make the NAT or firewall to "open" or "relay" specific TCP or
+UDP ports. However, there are demands somehow to eliminate such working costs
+on network administrators. In order to satisfy such demands, SoftEther VPN has
+the newly-implemented "NAT Traversal" function. NAT Traversal is enabled by
+default. A SoftEther VPN Server running on the computer behind NAT or firewall
+can accept VPN connections from the Internet, without any special
+configurations on firewalls or NATs. If you want to disable the NAT Traversal
+function, modify the "DisableNatTraversal" to "true" on the configuration file
+of SoftEther VPN Server. In order to disable it on the client-side, append
+"/tcp" suffix on the destination hostname.
+
+1.3. Dynamic DNS Function
+Traditional legacy VPN system requires a static global IP address on the VPN
+server. In consideration of shortage of global IP addresses, SoftEther
+Corporation implements the "Dynamic DNS Function" on SoftEther VPN Server.
+Dynamic DNS is enabled by default. Dynamic DNS function notify the current
+global IP address of the PC to the Dynamic DNS Servers which are operated by
+SoftEther Corporation. A globally-unique hostname (FQDN) such as
+"abc.softether.net" ( "abc" varies as unique per a user) will be assigned on
+the VPN Server. If you tell this unique hostname to a VPN user, the user can
+specify it as the destination VPN Sever hostname on the VPN Client and will be
+able to connect the VPN Server. No IP addresses are required to know
+beforehand. If the IP address of the VPN Server varies, the registered IP
+address related to the hostname of Dynamic DNS service will be changed
+automatically. By this mechanism, no longer need a static global IP address
+which costs monthly to ISPs. You can use consumer-level inexpensive Internet
+connection with dynamic IP address in order to operate an enterprise-level VPN
+system. If you want to disable Dynamic DNS, specify "true" on the "Disabled"
+items of the "DDnsClient" directive on the SoftEther VPN Server configuration
+file. * Note for residents in People's Republic of China: If your VPN Server
+is running on the People's Republic of China, the DNS suffix will be replaced
+to "sedns.cn" domain. The "sedns.cn" domain is the service possessed and
+operated by "Beijing Daiyuu SoftEther Technology Co., Ltd" which is a
+Chinese-local enterprise.
+
+1.4. VPN over ICMP / VPN over DNS functions
+If you want to make a VPN connection between SoftEther VPN Client / Bridge and
+SoftEther VPN Server, but if TCP and UDP packets are prohibited by the
+firewall, then you can encapsulates payloads into "ICMP" (as known as Ping) or
+"DNS" packets. This function can realize a VPN connection by using ICMP or DNS
+even if the firewall or router blocks every TCP or UDP connections. VPN over
+ICMP / VPN over DNS functions are designed to comply standard ICMP and DNS
+specifications as possible, however it sometimes has a behavior not to fully
+comply them. Therefore, few poor-quality routers may be caused a
+memory-overflow or something troubles when a lot of ICMP or DNS packets are
+passed, and such routers sometimes freezes or reboots. It might affects other
+users on the same network. To avoid such risks, append the suffix "/tcp" on
+the destination hostname which is specified on the VPN-client side to disable
+VPN over ICMP / DNS functions.
+
+1.5. VPN Azure Cloud Service
+If your SoftEther VPN Server is placed behind the NAT or firwall, and by some
+reason you cannot use NAT Traversal function, Dynamic DNS function or VPN over
+ICMP/DNS function, you can use VPN Azure Clouse Service. SoftEther Corporation
+operates VPN Azure Cloud on Internet. After the VPN Server makes a connection
+to the VPN Azure Cloud, the hostname "abc.vpnazure.net" ( "abc" is a unique
+hostname) can be specified to connect to the VPN Server via the VPN Azure
+Cloud. Practically, such a hostname is pointing a global IP address of one of
+cloud servers which are operated by SoftEther Corporation. If A VPN Client
+connects to such a VPN Azure host, then the VPN Azure host will relay all
+traffics between the VPN Client and the VPN Server. VPN Azure is disabled by
+default. You can activate it easily by using VPN Server Configuration Tool.
+
+1.6. UDP Acceleration
+SoftEther VPN has the UDP Acceleration Function. If a VPN consists of two
+sites detects that UDP channel can be established, UDP will be automatically
+used. By this function, throughput of UDP increases. If direct UDP channel can
+be established, direct UDP packets will be used. However, if there is
+something obstacles such as firewalls or NATs, the "UDP Hole Punching"
+technology will be used, instead. The "UDP Hole Punching" uses the cloud
+servers which SoftEther Corporation operates on Internet. UDP Acceleration can
+be disabled anytime by setting up so on the VPN-client side.
+
+
+2. VPN Software
+2.1. SoftEther VPN Client
+If you use SoftEther VPN Client on Windows, the Virtual Network Adapter device
+driver will be installed on Windows. The Virtual Network Adapter is
+implemented as a kernel-mode driver for Windows. The driver is
+digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed
+by Symantec Corporation. A message to ask you want to sure install the driver
+might be popped up on the screen. SoftEther VPN Client may response the
+message if possible. SoftEther VPN Client also optimizes the configuration of
+MMCSS (Multimedia Class Scheduler Service) on Windows. You can undo the
+optimizations of MMCSS afterwards.
+
+2.2. SoftEther VPN Server / Bridge
+If you use SoftEther VPN Server / Bridge on Windows with "Local Bridge"
+functions, you have to install the low-level Ethernet packet processing driver
+on the computer. The driver is digitally-signed by a certificate issued by
+VeriSign, Inc. and also sub-signed by Symantec Corporation. SoftEther VPN
+Server / Bridge may disable the TCP/IP offloading features on the physical
+network adapter for Local Bridge function. In Windows Vista / 2008 or greater
+version, VPN Server may inject a packet-filter driver which complies Windows
+Filter Platform (WPF) specification into the kernel in order to provide IPsec
+function. The packet-filter driver will be loaded available only if IPsec
+function is enabled. Once you enables IPsec function of SoftEther VPN Server,
+the built-in IPsec function of Windows will be disabled. After you disabled
+IPsec function of SoftEther VPN Server, then the built-in IPsec function of
+Windows will revive. In order to provide the Local Bridge function, SoftEther
+VPN Server / Bridge disables the TCP/IP offloading function on the operating
+system.
+
+2.3. User-mode Installation
+You can install SoftEther VPN Server and SoftEther VPN Bridge as "User-mode"
+on Windows. In other words, even if you don't have Windows system
+administrator's privileges, you can install SoftEther VPN as a normal user.
+User-mode install will disable a few functions, however other most functions
+work well. Therefore, for example, an employee can install SoftEther VPN
+Server on the computer in the office network, and he will be able to connect
+to the server from his home. In order to realize such a system by user-self,
+no system administrative privileges are required in the view-point of
+technical. However, breaking rules of the company to install software on the
+computer without authority might be regarded as an unfavorable behavior. If
+you are an employee and belong to the company, and the company-policy
+prohibits installing software or making communications towards Internet
+without permission, you have to obtain a permission from the network
+administrator or the executive officer of your company in advance to install
+SoftEther VPN. If you install VPN Server / Bridge as User-mode, an icon will
+be appeared on the Windows task-tray. If you feel that the icon disturbs you,
+you can hide it by your operation. However, you must not exploit this hiding
+function to install VPN Server on other person's computer as a spyware. Such
+behavior might be an offence against the criminal law.
+
+2.4. Keep Alive Function
+SoftEther VPN Server and SoftEther VPN Bridge has Keep Alive Function by
+default. The purpose of this function is to sustain the Internet line active.
+The function transmits UDP packets with a random-byte-array-payload
+periodically. This function is useful to avoid automatic disconnection on
+mobile or dial-up connections. You can disable Keep Alive Function anytime.
+
+2.5. Uninstallation
+The uninstallation process of SoftEther VPN software will delete all program
+files. However, non-program files (such as files and data which are generated
+by running of programs) ) will not be deleted. For technical reason, the exe
+and resource files of uninstaller might remain. Such remaining files never
+affects to use the computer, however you can delete it manually. Kernel-mode
+drivers might not be deleted, however such drivers will not be loaded after
+the next boot of Windows. You can use "sc" command of Windows to delete
+kernel-mode drivers manually.
+
+2.6. Security
+You should set the administrator's password on SoftEther VPN Server / Bridge
+after installation. If you neglect to do it, another person can access to
+SoftEther VPN Server / Bridge and can set the password without your
+permission. This caution might be also applied on SoftEther VPN Client for
+Linux.
+
+2.7. Automatic Update Notification
+SoftEther VPN software for Windows has an automatic update notification
+function. It accesses to the SoftEther Update server periodically to check
+whether or not the latest version of software is released. If the latest
+version is released, the notification message will be popped up on the screen.
+In order to achieve this purpose, the version, language settings, the unique
+identifier, the IP address of your computer and the hostname of VPN Server
+which is connected to will be sent to the SoftEther Update server. No personal
+information will be sent. Automatic Update Notification is enabled by default,
+however you can disable it on the configuration screen. The setting whether
+turned on or turned off will be saved individually corresponding to each
+destination VPN server, by VPN Server Manager.
+
+2.8. Virtual NAT Function
+A Virtual Hub on SoftEther VPN Server / Bridge has "Virtual NAT Function" .
+Virtual NAT Function can share a single IP address on the physical network by
+multiple private IP address of VPN Clients. There are two operation mode of
+Virtual NAT: User-mode and Kernel-mode. In the user-mode operation, Virtual
+NAT shares an IP address which is assigned on the host operating system.
+Unlike user-mode, the kernel-mode operation attempts to find DHCP servers on
+the physical network. If there are two or more physical networks, a DHCP
+server will be sought automatically for each segments serially. If a DHCP
+server found, and an IP address is acquired, the IP address will be used by
+the Virtual NAT. In this case, an IP entry as a DHCP client will be registered
+on the IP pool of the physical DHCP Server. The physical default gateway and
+the DNS server will be used by the Virtual NAT in order to communicate with
+hosts in Internet. In kernel-mode operation, a Virtual Hub has a virtual MAC
+address which is operating on the physical Ethernet segment. In order to check
+the connectivity to Internet, SoftEther VPN periodically sends DNS query
+packet to resolve the IP address of host "www.yahoo.com" or "www.baidu.com" ,
+and attempts to connect to the TCP port 80 of such a resulted IP address for
+connectivity check.
+
+2.9. Unattended Installation of Kernel-mode Components
+When SoftEther VPN will detect a necessity to install the kernel-mode
+components on Windows, a confirmation message will be appeared by Windows
+system. In this occasion, SoftEther VPN software will switch to the Unattended
+Installation mode in order to respond "Yes" to Windows. This is a solution to
+prevent dead-locks when a remote-administration is performed from remote
+place.
+
+2.10. Windows Firewall
+SoftEther VPN software will register itself as a safe-program. Such an entry
+will be remain after the uninstallation. You can remove it manually from the
+Control Panel of Windows.
+
+
+3. Internet Services
+3.1. Internet Services which are provided by SoftEther Corporation
+SoftEther Corporation provides Dynamic DNS, NAT Traversal and VPN Azure server
+services on the Internet. These services are free of charge. Customers can
+access to the services by using SoftEther VPN software, via Internet. These
+service will be planned to be available from Open-Source version of "SoftEther
+VPN" which will be released in the future.
+
+3.2. Sent Information and Privacy Protection
+SoftEther VPN software may send an IP address, hostname, the version of VPN
+software on the customer's computer to the cloud service operated by SoftEther
+Corporation, in order to use the above services. These sending of information
+are minimal necessary to use the services. No personal information will be
+sent. SoftEther Corporation records log files of the cloud service servers for
+90 days at least with the received information. Such logs will be used for
+troubleshooting and other legitimate activities. SoftEther Corporation may
+provide logs to a public servant of Japanese government who are belonging to
+courts, police stations and the prosecutor's office, in order to comply such
+authorities' order. (Every Japanese public servants are liable by law to keep
+the information close.) Moreover, the IP addresses or other information will
+be processed statistically and provided to the public, not to expose the each
+concrete IP address, in order to release the release of research activities.
+
+3.3. Communication Data via VPN Azure Service
+Regardless of the above 3.2 rule, if the customer sends or receives VPN
+packets using VPN Azure Cloud Service, the actual payloads will stored and
+forwarded via the volatile memory of the servers for very short period. Such a
+behavior is naturally needed to provide the "VPN relay service" . No payloads
+will be recorded on "fixed" storages such as hard-drives. However, the
+"Wiretapping for Criminals Procedures Act" (The 137th legislation ruled on
+August 18, 1999 in Japan) requires telecommunication companies to allow the
+Japanese government authority to conduct a wire-tapping on the line. VPN Azure
+Servers which are physically placed on Japan are subjects of this law.
+
+3.4. Comply to Japanese Telecommunication Laws
+SoftEther Corporation complies with Japanese Telecommunication Laws as
+necessary to provide online services via Internet.
+
+3.5. Free and Academic Experiment Services
+SoftEther provides Dynamic DNS, NAT Traversal and VPN Azure as academic
+experiment services. Therefore, there services can be used for free of charge.
+These services are not parts of "SoftEther VPN Software Products" . These
+services are provided without any warranty. The services may be suspended or
+discontinued by technical or operational matters. In such occasions, users
+will not be able to use the services. A user have to understand such risks,
+and to acknowledge that such risks are borne by a user-self. SoftEther will
+never be liable to results or damages of use or unable-to-use of the service.
+Even if the user has already paid the license-fee of the commercial version of
+SoftEther VPN, such paid fees don't include any fees of these services.
+Therefore, if the online services will stop or be discontinued, no refunds or
+recoveries of damages will be provided by SoftEther Corporation.
+
+3.6. DNS Proxy Cloud Servers
+In some regions, when a user uses Internet, a DNS query sometimes broken or
+lost when it is passing through the ISP line. If SoftEther VPN Server, Client
+or Bridge detects a possibility that the accessing to the actual VPN server
+might be unstable, then DNS queries will be also transferred to the DNS proxy
+cloud servers which are operated by SoftEther Corporation. A DNS proxy cloud
+server will respond DNS queries with answering correct a IP address.
+
+
+4. General Cautions
+4.1. Needs an Approval from Network Administrator
+SoftEther VPN has powerful functions which don't require special settings by
+network administrators. For example, you need not to ask the administrator to
+configure the existing firewall in order to "open" a TCP/UDP port. Such
+characteristic features are for the purpose to eliminate working times and
+costs of network administrators, and avoid misconfiguration-risks around the
+tasks to open specific exception ports on the firewall. However, any employees
+belong to the company have to obtain an approval from the network
+administrator before installs SoftEther VPN. If your network administrator
+neglects to provide such an approval, you can consider to take an approval
+from an upper authority. (For example, executive officer of the company.) If
+you use SoftEther VPN without any approvals from the authority of your
+company, you might have disadvantage. SoftEther Corporation will be never
+liable for results or damages of using SoftEther VPN.
+
+4.2. Observe Laws of Your Country
+If your country's law prohibits the use of encryption, you have to disable the
+encryption function of SoftEther VPN by yourself. Similarly, in some countries
+or regions, some functions of SoftEther VPN might be prohibited to use by
+laws. Other countries' laws are none of SoftEther Corporation's concern
+because SoftEther Corporation is an enterprise which is located and registered
+in Japan physically. For example, there might be a risk that a part of
+SoftEther VPN conflicts an existing patent which is valid only on the specific
+region. SoftEther Corporation has no interests in such specific region outside
+Japan's territory. Therefore, if you want to use SoftEther VPN in regions
+outside Japan, you have to be careful not to violate third-person's rights.
+You have to verify the legitimacy of the use of SoftEther VPN in the specific
+region before you actually use it in such region. By nature, there are almost
+200 countries in the World, and each country's law is different each other. It
+is practically impossible to verify every countries' laws and regulations and
+make the software comply with all countries' laws in advance to release the
+software. Therefore SoftEther Corporation has verified the legitimacy of
+SoftEther VPN against the laws and regulations of only Japan. If a user uses
+SoftEther VPN in a specific country, and damaged by public servants of the
+government authority, SoftEther Corporation will never be liable to recover or
+compensate such damages or criminal responsibilities.
+
+
+5. VPN Gate Academic Experiment Project
+(This chapter applies only on SoftEther VPN software package which contains
+the extension plug-in for VPN Gate Academic Experiment Project.)
+5.1. About VPN Gate Academic Experiment Project
+VPN Gate Academic Experiment Project is an online service operated for just
+the academic research purpose at the graduate school of University of Tsukuba,
+Japan. The purpose of this research is to expend our knowledge about the
+"Global Distributed Public VPN Relay Server" (GDPVRS) technology. For details,
+please visit http://www.vpngate.net/.
+
+5.2. About VPN Gate Service
+SoftEther VPN Server and SoftEther VPN Client may contain "VPN Gate Service"
+program. However, VPN Gate Service is disabled by default.
+VPN Gate Service should be activated and enabled by the voluntary intention of
+the owner of the computer which SoftEther VPN Server or SoftEther VPN Client
+is installed on. After you activate VPN Gate Service, the computer will be
+start to serve as a part of the Global Distributed Public VPN Relay Servers.
+The IP address, hostname and related information of the computer will be sent
+and registered to the directory server of VPN Gate Academic Experiment
+Project, and they will be published and disclosed to the public. This
+mechanism will allow any VPN Gate Client software's user to connect to the VPN
+Gate Service running on your computer. While the VPN session between a VPN
+Gate Client and your VPN Gate Service is established, the VPN Gate Client's
+user can send/receive any IP packets towards the Internet via the VPN Gate
+Service. The global IP address of the VPN Gate Service's hosing computer will
+be used as the source IP address of such communications which a VPN Gate
+Client initiates.
+VPN Gate Service will send some information to the VPN Gate Academic
+Experiment Service Directory Server. The information includes the operator's
+information which described in section 5.5, logging settings, uptime,
+operating system version, type of protocol, port numbers, quality information,
+statistical information, VPN Gate clients' log history data (includes dates,
+IP addresses, version numbers and IDs) and the version of the software. These
+information will be exposed on the directory. VPN Gate Service also receives a
+key for encoding which is described on the chapter 5.9 from the directory
+server.
+
+5.3. Details of VPN Gate Service's Behavior
+If you enable VPN Gate Service manually, which is disabled by default, the
+"VPNGATE" Virtual Hub will be created on the SoftEther VPN Server. If you are
+using SoftEther VPN Client and attempt to active VPN Gate Service on it, an
+equivalent program to SoftEther VPN Server will be invoked on the same process
+of SoftEther VPN Client, and the "VPNGATE" Virtual Hub will be created. The
+"VPNGATE" Virtual Hub contains a user named "VPN" by default which permits
+anyone on the Internet to make a VPN connection to the Virtual Hub. Once a VPN
+Client connects to the "VPNGATE" Virtual Hub, any communication between the
+user and the Internet will pass through the Virtual Hub, and
+transmitted/received using the physical network interface on the computer
+which SoftEther VPN Server (or SoftEther VPN Client) is running on. This will
+cause the result that a destination host specified by the VPN Client will
+identify that the source of the communication has initiated from the VPN Gate
+Service's hosting computer's IP address. However, for safety, any packets
+which destinations are within 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0
+or 10.0.0.0/255.0.0.0 will be blocked by the "VPNGATE" Virtual Hub in order to
+protect your local network. Therefore, if you run VPN Gate Service on your
+corporate network or private network, it is safe because anonymous VPN Client
+users will not be permitted to access such private networks. VPN Gate Service
+also serves as relay for accessing to the VPN Gate Directory Server.
+In order to make VPN Gate Service familiar with firewalls and NATs, it opens
+an UDP port by using the NAT Traversal function which is described on the
+section 1.2. It also opens and listens on some TCP ports, and some TCP and UDP
+ports will be specified as the target port of Universal Plug and Play (UPnP)
+Port Transfer entries which are requested to your local routers. UPnP request
+packets will be sent periodically. Some routers keep such an opened TCP/UDP
+port permanently on the device. If you wish to close them, do it manually.
+VPN Gate Service also provides the mirror-site function for www.vpngate.net.
+This is a mechanism that a copy of the latest contents from www.vpngate.net
+will be hosted by the mirror-site tiny HTTP server which is running on the VPN
+Gate Service program. It will register itself on the mirror-sites list in
+www.vpngate.net. However, it never relays any other communications which are
+not towards www.vpngate.net.
+
+5.4. Communication between Internet via VPN Gate Service
+VPN Gate Service provides a routing between users and the Internet, by using
+the Virtual NAT Function which is described on the section 2.8. VPN Gate
+Service sends polling Ping packets to the server which is located on
+University of Tsukuba, and the Google Public DNS Server which is identified as
+8.8.8.8, in order to check the latest quality of your Internet line. VPN Gate
+Service also sends and receives a lot of random packets to/from the Speed Test
+Server on University of Tsukuba. These quality data will be reported to VPN
+Gate Directory Server, automatically and periodically. The result will be
+saved and disclosed to the public. These periodical polling communication are
+adjusted not to occupy the Internet line, however in some circumstances they
+might occupy the line.
+
+5.5. Operator's Information of VPN Gate Service
+If you activate VPN Gate Service on your computer, the computer will be a part
+of the Global Distributed Public VPN Relay Servers. Therefore, the Operator's
+administrative information of your VPN Gate Service should be reported and
+registered on the VPN Gate Service Directory. Operator's information contains
+the name of the operator and the abuse-reporting contact e-mail address. These
+information can be inputted on the screen if the VPN Gate configuration.
+Inputted information will be transmitted to the VPN Gate Directory Server,
+stored and disclosed to the public. So you have to be careful to input
+information. By the way, until you specify something as the operator's
+information, the computer's hostname will be used automatically as the field
+of the name of the operator, by appending the "'s owner" string after the
+hostname.
+
+5.6. Observe Laws to Operate VPN Gate Service
+In some countries or regions, a user who is planning to activate and operate
+VPN Gate Service, he are mandated to obtain a license or register a service
+from/to the government. If your region has such a regulation, you must fulfill
+mandated process before activating VPN Gate Service in advance. Neither the
+developers nor operators of the VPN Gate Academic Experiment Project will be
+liable for legal/criminal responsibilities or damages which are occurred from
+failure to comply your local laws.
+
+5.7. Protect Privacy of Communication
+Most of countries have a law which requires communication service's operators,
+including VPN Gate Service operators, to protect the privacy of communication
+of third-persons. When you operate VPN Gate Service, you must always protect
+user's privacy.
+
+5.8. Packet Logs
+The packet logging function is implemented on VPN Gate Service. It records
+essential headers of major TCP/IP packets which are transmitted via the
+Virtual Hub. This function will be helpful to investigate the "original IP
+address" of the initiator of communication who was a connected user of your
+VPN Gate Service, by checking the packet logs and the connection logs. The
+packet logs are recorded only for such legitimate investigates purpose. Do not
+peek nor leak packet logs except the rightful purpose. Such act will be
+violate the section 5.7.
+
+5.9. Packet Logs Automatic Archiving and Encoding Function
+The VPN Gate Academic Experiment Service is operated and running under the
+Japanese constitution and laws. The Japanese constitution laws demand strictly
+protection over the privacy of communication. Because this service is under
+Japanese rules, the program of VPN Gate Service implements this "Automatic Log
+File Encoding" protection mechanism, and enabled by default.
+The VPN Gate Service is currently configured to encode packet log files which
+has passed two or more weeks automatically, by default. In order to protect
+privacy of communication, if a packet log file is once encoded, even the
+administrator of the local computer cannot censor the packet log file. This
+mechanism protects privacy of end-users of VPN Gate Service.
+You can change the VPN Gate Service setting to disable this automatic encoding
+function. Then packet log files will never be encoded even after two weeks
+passed. In such a configuration, all packet logs will remain as plain-text on
+the disk. Therefore you have to take care not to violate user's privacy.
+If you are liable to decode an encoded packet log files (for example: a VPN
+Gate Service's user illegally abused your VPN Gate Service and you have to
+decode the packet logs in order to comply the laws), contact the administrator
+of the VPN Gate Academic Experiment Service at Graduate School of University
+of Tsukuba, Japan. You can find the contact address at
+http://www.vpngate.net/. The administrator of VPN Gate Service will respond to
+decode the packet logs if there is an appropriate and legal request from court
+or other judicial authorities, according to laws.
+
+5.10. Caution if You Operate VPN Gate Service in the Japan's Territories
+When a user operates VPN Gate Service in the Japan's territories, such an act
+may be regulated under the Japanese Telecommunication Laws if the operation is
+a subject to the law. However, in such a circumstance, according to the
+"Japanese Telecommunication Business Compete Manual [supplemental version]" ,
+non- profitable operations of communications are not identified as a
+"telecommunication business" . So usual operators of VPN Gate Service are not
+subjects to "telecommunication business operators" , and not be mandated to
+register to the government. Even so, legalities to protect the privacy of
+communication still imposed. As a conclusion, if you operate VPN Gate Service
+in the Japan's Territories, you must not leak the secrets of communications
+which are transmitted via your operating VPN Gate Service.
+
+5.11. VPN Gate Client
+If SoftEther VPN Client contains the VPN Gate Client plug-in, you can use it
+to obtain the list of current operating VPN Gate Service servers in the
+Internet, and make a VPN connection to a specific server on the list.
+VPN Gate Client always keeps the latest list of the VPN Gate Services
+periodically. Be careful if you are using a pay-per-use Internet line.
+When you start the VPN Gate Client software, the screen which asks you
+activate or not VPN Gate Service will be appeared. For details of VPN Gate
+Service, read the above sections.
+
+5.12. Caution before Joining or Exploiting VPN Gate Academic Experiment
+Project
+The VPN Gate Academic Experiment Service is operated as a research project at
+the graduate school on University of Tsukuba, Japan. The service is governed
+under the Japanese laws. Other countries' laws are none of our concerns nor
+responsibilities.
+By nature, there are almost 200 countries in the World, with different laws.
+It is impossible to verify every countries' laws and regulations and make the
+software comply with all countries' laws in advance to release the software.
+If a user uses VPN Gate service in a specific country, and damaged by public
+servants of the authority, the developer of either the service or software
+will never be liable to recover or compensate such damages or criminal
+responsibilities.
+By using this software and service, the user must observe all concerned laws
+and rules with user's own responsibility. The user will be completely liable
+to any damages and responsibilities which are results of using this software
+and service, regardless of either inside or outside of Japan's territory.
+If you don't agree nor understand the above warnings, do not use any of VPN
+Gate Academic Experiment Service functions.
+VPN Gate is a research project for just academic purpose only. VPN Gate was
+developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN
+Gate were developed on this research project at University of Tsukuba. Any
+parts of VPN Gate are not developed by SoftEther Corporation. The VPN Gate
+Research Project is not a subject to be led, operated, promoted nor guaranteed
+by SoftEther Corporation.
+
+
diff --git a/src/LICENSE.TXT b/src/LICENSE.TXT
new file mode 100644
index 00000000..52c728da
--- /dev/null
+++ b/src/LICENSE.TXT
@@ -0,0 +1,2350 @@
+SoftEther VPN Server, Client and Bridge are free software, and released as
+open-source. You can redistribute them and/or modify them under the terms of
+the GNU General Public License version 2 as published by the Free Software
+Foundation.
+
+Copyright (c) 2012-2014 Daiyuu Nobori.
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+Copyright (c) 2012-2014 SoftEther Corporation.
+All Rights Reserved.
+http://www.softether.org/
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License version 2 as published by the Free
+Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License version 2
+along with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+Neither the name of SoftEther nor the names of its contributors may be used to
+endorse or promote products derived from this software without specific prior
+written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
+JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
+DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
+JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
+AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
+SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
+OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
+AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
+JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
+ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
+PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
+LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS SOFTWARE
+INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES PROHIBIT ENCRYPTED
+COMMUNICATIONS. USING THIS SOFTWARE IN OTHER COUNTRIES MIGHT BE RESTRICTED.
+
+THE FOLLOWING GPLV2 CONDITIONS APPLY ON ALL SOFTETHER VPN PROGRAMS WHICH ARE
+DEVELOPED BY SOFTETHER VPN PROJECT.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Lesser General Public License instead.) You can apply it
+to your programs, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and modification
+follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included
+without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running the Program
+is not restricted, and the output from the Program is covered only if its
+contents constitute a work based on the Program (independent of having been
+made by running the Program). Whether that is true depends on what the Program
+does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole
+or in part contains or is derived from the Program or any part thereof, to be
+licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+ c) If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the most
+ordinary way, to print or display an announcement including an appropriate
+copyright notice and a notice that there is no warranty (or else, saying that
+you provide a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this License.
+(Exception: if the Program itself is interactive but does not normally print
+such an announcement, your work based on the Program is not required to print
+an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with
+the Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections 1 and
+2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only for
+noncommercial distribution and only if you received the program in object code
+or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the executable. However, as a special exception, the source
+code distributed need not include anything that is normally distributed (in
+either source or binary form) with the major components (compiler, kernel, and
+so on) of the operating system on which the executable runs, unless that
+component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to
+copy from a designated place, then offering equivalent access to copy the
+source code from the same place counts as distribution of the source code,
+even though third parties are not compelled to copy the source along with the
+object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the
+Program (or any work based on the Program), you indicate your acceptance of
+this License to do so, and all its terms and conditions for copying,
+distributing or modifying the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of this License,
+you may choose any version ever published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+Note that the above copyright notices and use conditions do not apply on the
+software components listed in below which are included in this Software. When
+you use or distribute Software with including these libraries, you have to
+follow the conditions of these libraries.
+
+These library's copyright notices and conditions are following;
+
+-------------------
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES
+
+SoftEther provides source codes of some GPL/LGPL/other libraries listed above
+on its web server. Anyone can download, use and re-distribute them under
+individual licenses which are contained on each archive file, available from
+the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications
+Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is
+identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+(Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such
+works are identified as "derived from the RSA Security Inc. PKCS #11
+Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the
+merchantability of this software or the suitability of this software for any
+particular purpose. It is provided "as is" without express or implied warranty
+of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All
+rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas
+of Cornell University.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are intended
+to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object
+files to the recipients so that they can relink them with the library, after
+making changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated
+libraries. This license is quite different from the ordinary one; be sure to
+read it in full, and don't assume that anything in it is the same as in the
+ordinary license.
+
+ The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to
+running a utility program or application program. However, in a textual and
+legal sense, the linked executable is a combined work, a derivative of the
+original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker conditions
+might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving
+your freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards changes
+in header files, but we have achieved it as regards changes in the actual
+functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it may
+be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+ Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License
+along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+of data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make a
+good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function or
+table used by this function must be optional: if the application does not
+supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they refer
+to the ordinary GNU General Public License, version 2, instead of to this
+License. (If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you wish.)
+Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software
+interchange.
+
+ If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the
+object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+ However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold for
+this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten lines
+or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables containing
+this object code plus portions of the Library will still fall under Section
+6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your choice,
+provided that the terms permit modification of the work for the customer's own
+use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+source code for the Library including whatever changes were used in the work
+(which must be distributed under Sections 1 and 2 above) ; and, if the work is
+an executable linked with the Library, with the complete machine-readable
+"work that uses the Library", as object code and/or source code, so that the
+user can modify the Library and then relink to produce a modified executable
+containing the modified Library. (It is understood that the user who changes
+the contents of definitions files in the Library will not necessarily be able
+to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three
+years, to give the same user the materials specified in Subsection 6a, above,
+for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a
+designated place, offer equivalent access to copy the above specified
+materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or
+that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+ a) Accompany the combined library with a copy of the same work based on
+the Library, uncombined with any other library facilities. This must be
+distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+of it is a work based on the Library, and explaining where to find the
+accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this
+License to do so, and all its terms and conditions for copying, distributing
+or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein. You are not responsible for
+enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or otherwise)
+that contradict the conditions of this License, they do not excuse you from
+the conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software
+Foundation. If the Library does not specify a license version number, you may
+choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, distribute with
+modifications, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgment: "This product includes software
+developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+(http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+endorse or promote products derived from this software without prior written
+permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may
+"OpenSSL" appear in their names without prior written permission of the
+OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+acknowledgment: "This product includes software developed by the OpenSSL
+Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim Hudson
+(tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young
+(eay@cryptsoft.com). The implementation was written so as to conform with
+Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the
+following conditions are aheared to. The following conditions apply to all
+code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code;
+not just the SSL code. The SSL documentation included with this distribution
+is covered by the same copyright terms except that the holder is Tim Hudson
+(tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code
+are not to be removed. If this package is used in a product, Eric Young should
+be given attribution as the author of the parts of the library used. This can
+be in the form of a textual message at program startup or in documentation
+(online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list
+of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must
+display the following acknowledgement: "This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic'
+can be left out if the rouines from the library being used are not
+cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the
+apps directory (application code) you must include an acknowledgement: "This
+product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence [including the GNU Public
+Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the people
+who reported problems and suggested various improvements in zlib; they are too
+numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES WRITTEN BY SOFTETHER CORPORATION
+
+Note for users of non-Windows version of PacketiX VPN: The enumerated bundle
+of License Agreements above are copies of original License Agreements of each
+library programs which PacketiX VPN uses. PacketiX VPN is not a delivered work
+from these libraries. PacketiX VPN is a separated work from the libraries, but
+it may call functions of the libraries (whether or not PacketiX VPN calls such
+functions are depended on the user's intention to link them or not on user's
+side computer). While some libraries indicate GPL or LGPL as a condition to
+re-distribute, PacketiX VPN is not license under GPL nor LGPL. Therefore, we
+took special care not to make PacketiX VPN become delivered works of any GPL
+or LGPL libraries. In order to achieve that, both PacketiX VPN and GPL/LGPL
+libraries are distributed with isolated forms (means that any program files of
+PacketiX VPN are not bound nor linked to any GPL/LGPL libraries). If a user of
+PacketiX VPN wants to link GPL/LGPL libraries by their own decisions,
+operations and responsibilities, he may do that on his computer. However, if a
+delivered work under copyright law is created as a result of such an
+operation, such a delivered work must not re-distributed to other people,
+because it may violate GPL/LGPL libraries' conditions.
+
+Note for users of Windows version of PacketiX VPN: For technical reason, the
+above texts are exactly same as a file which is also contained on the
+non-Windows version of PacketiX VPN. Actually, the Windows version of PacketiX
+VPN has no relations to any GPL/LGPL libraries enumerated above.
+
+SoftEther Corporation provides source codes of some GPL/LGPL/other libraries
+listed above on its web server. Anyone can download, use and re-distribute
+them under individual licenses which are contained on each archive file,
+available from the following URL:
+http://uploader.softether.co.jp/src/
+
+
+
+THE IMPORTANT NOTICES ABOUT SOFTETHER VPN
+
+FUNCTIONS OF VPN COMMUNICATIONS EMBEDDED ON THIS SOFTWARE ARE VERY POWERFUL
+THAN EVER. THIS STRONG VPN ABILITY WILL BRING YOU HUGE BENEFITS. HOWEVER, IF
+YOU MISUSE THIS SOFTWARE, IT MIGHT DAMAGES YOURSELF. IN ORDER TO AVOID SUCH
+RISKS, THIS DOCUMENT ACCOUNTS IMPORTANT NOTICES FOR CUSTOMERS WHO ARE WILLING
+TO USE THIS SOFTWARE. THE FOLLOWING INSTRUCTIONS ARE VERY IMPORTANT. READ AND
+UNDERSTAND IT CAREFULLY. ADDITIONALLY, IF YOU ARE PLANNING TO USE THE DYNAMIC
+DNS, THE NAT TRAVERSAL OR THE VPN AZURE FUNCTIONS, READ THE SECTION 3.5
+CAREFULLY. THESE FUNCTIONS ARE FREE SERVICES PROVIDED VIA THE INTERNET, ARE
+NOT GUARANTEED, AND ARE NOT INTENDED TO BE USED FOR BUSINESS OR COMMERCIAL
+USE. DO NOT USE THESE SERVICES FOR YOUR BUSINESS OR COMMERCIAL USE.
+
+
+1. VPN Communication Protocols
+1.1. SoftEther VPN Protocol
+SoftEther VPN can perform VPN communication. Unlike traditional VPN protocols,
+SoftEther VPN has an implementation of the newly-designed "SoftEther VPN
+Protocol (SE-VPN Protocol)" . SE-VPN protocol encapsulates any Ethernet
+packets into a HTTPS (HTTP over SSL) connection. Therefore SE-VPN protocol can
+communicate beyond firewalls even if the firewall is configured to block
+traditional VPN packets by network administrator. SE-VPN protocol is designed
+and implemented to comply TLS 1.0 (RFC 5246) and HTTPS (RFC 2818). However, it
+sometimes have different behavior to RFCs. If you are a network administrator
+and want to block SE-VPN protocols on the firewall, you can adopt a
+"white-list" policy on the firewall to filter any TCP or UDP packets on the
+border except explicitly allowed packets towards specific web sites and
+servers.
+
+1.2. NAT Traversal Function
+Generally, if you use traditional VPN systems you have to request a network
+administrator to make the NAT or firewall to "open" or "relay" specific TCP or
+UDP ports. However, there are demands somehow to eliminate such working costs
+on network administrators. In order to satisfy such demands, SoftEther VPN has
+the newly-implemented "NAT Traversal" function. NAT Traversal is enabled by
+default. A SoftEther VPN Server running on the computer behind NAT or firewall
+can accept VPN connections from the Internet, without any special
+configurations on firewalls or NATs. If you want to disable the NAT Traversal
+function, modify the "DisableNatTraversal" to "true" on the configuration file
+of SoftEther VPN Server. In order to disable it on the client-side, append
+"/tcp" suffix on the destination hostname.
+
+1.3. Dynamic DNS Function
+Traditional legacy VPN system requires a static global IP address on the VPN
+server. In consideration of shortage of global IP addresses, SoftEther
+Corporation implements the "Dynamic DNS Function" on SoftEther VPN Server.
+Dynamic DNS is enabled by default. Dynamic DNS function notify the current
+global IP address of the PC to the Dynamic DNS Servers which are operated by
+SoftEther Corporation. A globally-unique hostname (FQDN) such as
+"abc.softether.net" ( "abc" varies as unique per a user) will be assigned on
+the VPN Server. If you tell this unique hostname to a VPN user, the user can
+specify it as the destination VPN Sever hostname on the VPN Client and will be
+able to connect the VPN Server. No IP addresses are required to know
+beforehand. If the IP address of the VPN Server varies, the registered IP
+address related to the hostname of Dynamic DNS service will be changed
+automatically. By this mechanism, no longer need a static global IP address
+which costs monthly to ISPs. You can use consumer-level inexpensive Internet
+connection with dynamic IP address in order to operate an enterprise-level VPN
+system. If you want to disable Dynamic DNS, specify "true" on the "Disabled"
+items of the "DDnsClient" directive on the SoftEther VPN Server configuration
+file. * Note for residents in People's Republic of China: If your VPN Server
+is running on the People's Republic of China, the DNS suffix will be replaced
+to "sedns.cn" domain. The "sedns.cn" domain is the service possessed and
+operated by "Beijing Daiyuu SoftEther Technology Co., Ltd" which is a
+Chinese-local enterprise.
+
+1.4. VPN over ICMP / VPN over DNS functions
+If you want to make a VPN connection between SoftEther VPN Client / Bridge and
+SoftEther VPN Server, but if TCP and UDP packets are prohibited by the
+firewall, then you can encapsulates payloads into "ICMP" (as known as Ping) or
+"DNS" packets. This function can realize a VPN connection by using ICMP or DNS
+even if the firewall or router blocks every TCP or UDP connections. VPN over
+ICMP / VPN over DNS functions are designed to comply standard ICMP and DNS
+specifications as possible, however it sometimes has a behavior not to fully
+comply them. Therefore, few poor-quality routers may be caused a
+memory-overflow or something troubles when a lot of ICMP or DNS packets are
+passed, and such routers sometimes freezes or reboots. It might affects other
+users on the same network. To avoid such risks, append the suffix "/tcp" on
+the destination hostname which is specified on the VPN-client side to disable
+VPN over ICMP / DNS functions.
+
+1.5. VPN Azure Cloud Service
+If your SoftEther VPN Server is placed behind the NAT or firwall, and by some
+reason you cannot use NAT Traversal function, Dynamic DNS function or VPN over
+ICMP/DNS function, you can use VPN Azure Clouse Service. SoftEther Corporation
+operates VPN Azure Cloud on Internet. After the VPN Server makes a connection
+to the VPN Azure Cloud, the hostname "abc.vpnazure.net" ( "abc" is a unique
+hostname) can be specified to connect to the VPN Server via the VPN Azure
+Cloud. Practically, such a hostname is pointing a global IP address of one of
+cloud servers which are operated by SoftEther Corporation. If A VPN Client
+connects to such a VPN Azure host, then the VPN Azure host will relay all
+traffics between the VPN Client and the VPN Server. VPN Azure is disabled by
+default. You can activate it easily by using VPN Server Configuration Tool.
+
+1.6. UDP Acceleration
+SoftEther VPN has the UDP Acceleration Function. If a VPN consists of two
+sites detects that UDP channel can be established, UDP will be automatically
+used. By this function, throughput of UDP increases. If direct UDP channel can
+be established, direct UDP packets will be used. However, if there is
+something obstacles such as firewalls or NATs, the "UDP Hole Punching"
+technology will be used, instead. The "UDP Hole Punching" uses the cloud
+servers which SoftEther Corporation operates on Internet. UDP Acceleration can
+be disabled anytime by setting up so on the VPN-client side.
+
+
+2. VPN Software
+2.1. SoftEther VPN Client
+If you use SoftEther VPN Client on Windows, the Virtual Network Adapter device
+driver will be installed on Windows. The Virtual Network Adapter is
+implemented as a kernel-mode driver for Windows. The driver is
+digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed
+by Symantec Corporation. A message to ask you want to sure install the driver
+might be popped up on the screen. SoftEther VPN Client may response the
+message if possible. SoftEther VPN Client also optimizes the configuration of
+MMCSS (Multimedia Class Scheduler Service) on Windows. You can undo the
+optimizations of MMCSS afterwards.
+
+2.2. SoftEther VPN Server / Bridge
+If you use SoftEther VPN Server / Bridge on Windows with "Local Bridge"
+functions, you have to install the low-level Ethernet packet processing driver
+on the computer. The driver is digitally-signed by a certificate issued by
+VeriSign, Inc. and also sub-signed by Symantec Corporation. SoftEther VPN
+Server / Bridge may disable the TCP/IP offloading features on the physical
+network adapter for Local Bridge function. In Windows Vista / 2008 or greater
+version, VPN Server may inject a packet-filter driver which complies Windows
+Filter Platform (WPF) specification into the kernel in order to provide IPsec
+function. The packet-filter driver will be loaded available only if IPsec
+function is enabled. Once you enables IPsec function of SoftEther VPN Server,
+the built-in IPsec function of Windows will be disabled. After you disabled
+IPsec function of SoftEther VPN Server, then the built-in IPsec function of
+Windows will revive. In order to provide the Local Bridge function, SoftEther
+VPN Server / Bridge disables the TCP/IP offloading function on the operating
+system.
+
+2.3. User-mode Installation
+You can install SoftEther VPN Server and SoftEther VPN Bridge as "User-mode"
+on Windows. In other words, even if you don't have Windows system
+administrator's privileges, you can install SoftEther VPN as a normal user.
+User-mode install will disable a few functions, however other most functions
+work well. Therefore, for example, an employee can install SoftEther VPN
+Server on the computer in the office network, and he will be able to connect
+to the server from his home. In order to realize such a system by user-self,
+no system administrative privileges are required in the view-point of
+technical. However, breaking rules of the company to install software on the
+computer without authority might be regarded as an unfavorable behavior. If
+you are an employee and belong to the company, and the company-policy
+prohibits installing software or making communications towards Internet
+without permission, you have to obtain a permission from the network
+administrator or the executive officer of your company in advance to install
+SoftEther VPN. If you install VPN Server / Bridge as User-mode, an icon will
+be appeared on the Windows task-tray. If you feel that the icon disturbs you,
+you can hide it by your operation. However, you must not exploit this hiding
+function to install VPN Server on other person's computer as a spyware. Such
+behavior might be an offence against the criminal law.
+
+2.4. Keep Alive Function
+SoftEther VPN Server and SoftEther VPN Bridge has Keep Alive Function by
+default. The purpose of this function is to sustain the Internet line active.
+The function transmits UDP packets with a random-byte-array-payload
+periodically. This function is useful to avoid automatic disconnection on
+mobile or dial-up connections. You can disable Keep Alive Function anytime.
+
+2.5. Uninstallation
+The uninstallation process of SoftEther VPN software will delete all program
+files. However, non-program files (such as files and data which are generated
+by running of programs) ) will not be deleted. For technical reason, the exe
+and resource files of uninstaller might remain. Such remaining files never
+affects to use the computer, however you can delete it manually. Kernel-mode
+drivers might not be deleted, however such drivers will not be loaded after
+the next boot of Windows. You can use "sc" command of Windows to delete
+kernel-mode drivers manually.
+
+2.6. Security
+You should set the administrator's password on SoftEther VPN Server / Bridge
+after installation. If you neglect to do it, another person can access to
+SoftEther VPN Server / Bridge and can set the password without your
+permission. This caution might be also applied on SoftEther VPN Client for
+Linux.
+
+2.7. Automatic Update Notification
+SoftEther VPN software for Windows has an automatic update notification
+function. It accesses to the SoftEther Update server periodically to check
+whether or not the latest version of software is released. If the latest
+version is released, the notification message will be popped up on the screen.
+In order to achieve this purpose, the version, language settings, the unique
+identifier, the IP address of your computer and the hostname of VPN Server
+which is connected to will be sent to the SoftEther Update server. No personal
+information will be sent. Automatic Update Notification is enabled by default,
+however you can disable it on the configuration screen. The setting whether
+turned on or turned off will be saved individually corresponding to each
+destination VPN server, by VPN Server Manager.
+
+2.8. Virtual NAT Function
+A Virtual Hub on SoftEther VPN Server / Bridge has "Virtual NAT Function" .
+Virtual NAT Function can share a single IP address on the physical network by
+multiple private IP address of VPN Clients. There are two operation mode of
+Virtual NAT: User-mode and Kernel-mode. In the user-mode operation, Virtual
+NAT shares an IP address which is assigned on the host operating system.
+Unlike user-mode, the kernel-mode operation attempts to find DHCP servers on
+the physical network. If there are two or more physical networks, a DHCP
+server will be sought automatically for each segments serially. If a DHCP
+server found, and an IP address is acquired, the IP address will be used by
+the Virtual NAT. In this case, an IP entry as a DHCP client will be registered
+on the IP pool of the physical DHCP Server. The physical default gateway and
+the DNS server will be used by the Virtual NAT in order to communicate with
+hosts in Internet. In kernel-mode operation, a Virtual Hub has a virtual MAC
+address which is operating on the physical Ethernet segment. In order to check
+the connectivity to Internet, SoftEther VPN periodically sends DNS query
+packet to resolve the IP address of host "www.yahoo.com" or "www.baidu.com" ,
+and attempts to connect to the TCP port 80 of such a resulted IP address for
+connectivity check.
+
+2.9. Unattended Installation of Kernel-mode Components
+When SoftEther VPN will detect a necessity to install the kernel-mode
+components on Windows, a confirmation message will be appeared by Windows
+system. In this occasion, SoftEther VPN software will switch to the Unattended
+Installation mode in order to respond "Yes" to Windows. This is a solution to
+prevent dead-locks when a remote-administration is performed from remote
+place.
+
+2.10. Windows Firewall
+SoftEther VPN software will register itself as a safe-program. Such an entry
+will be remain after the uninstallation. You can remove it manually from the
+Control Panel of Windows.
+
+
+3. Internet Services
+3.1. Internet Services which are provided by SoftEther Corporation
+SoftEther Corporation provides Dynamic DNS, NAT Traversal and VPN Azure server
+services on the Internet. These services are free of charge. Customers can
+access to the services by using SoftEther VPN software, via Internet. These
+service will be planned to be available from Open-Source version of "SoftEther
+VPN" which will be released in the future.
+
+3.2. Sent Information and Privacy Protection
+SoftEther VPN software may send an IP address, hostname, the version of VPN
+software on the customer's computer to the cloud service operated by SoftEther
+Corporation, in order to use the above services. These sending of information
+are minimal necessary to use the services. No personal information will be
+sent. SoftEther Corporation records log files of the cloud service servers for
+90 days at least with the received information. Such logs will be used for
+troubleshooting and other legitimate activities. SoftEther Corporation may
+provide logs to a public servant of Japanese government who are belonging to
+courts, police stations and the prosecutor's office, in order to comply such
+authorities' order. (Every Japanese public servants are liable by law to keep
+the information close.) Moreover, the IP addresses or other information will
+be processed statistically and provided to the public, not to expose the each
+concrete IP address, in order to release the release of research activities.
+
+3.3. Communication Data via VPN Azure Service
+Regardless of the above 3.2 rule, if the customer sends or receives VPN
+packets using VPN Azure Cloud Service, the actual payloads will stored and
+forwarded via the volatile memory of the servers for very short period. Such a
+behavior is naturally needed to provide the "VPN relay service" . No payloads
+will be recorded on "fixed" storages such as hard-drives. However, the
+"Wiretapping for Criminals Procedures Act" (The 137th legislation ruled on
+August 18, 1999 in Japan) requires telecommunication companies to allow the
+Japanese government authority to conduct a wire-tapping on the line. VPN Azure
+Servers which are physically placed on Japan are subjects of this law.
+
+3.4. Comply to Japanese Telecommunication Laws
+SoftEther Corporation complies with Japanese Telecommunication Laws as
+necessary to provide online services via Internet.
+
+3.5. Free and Academic Experiment Services
+SoftEther provides Dynamic DNS, NAT Traversal and VPN Azure as academic
+experiment services. Therefore, there services can be used for free of charge.
+These services are not parts of "SoftEther VPN Software Products" . These
+services are provided without any warranty. The services may be suspended or
+discontinued by technical or operational matters. In such occasions, users
+will not be able to use the services. A user have to understand such risks,
+and to acknowledge that such risks are borne by a user-self. SoftEther will
+never be liable to results or damages of use or unable-to-use of the service.
+Even if the user has already paid the license-fee of the commercial version of
+SoftEther VPN, such paid fees don't include any fees of these services.
+Therefore, if the online services will stop or be discontinued, no refunds or
+recoveries of damages will be provided by SoftEther Corporation.
+
+3.6. DNS Proxy Cloud Servers
+In some regions, when a user uses Internet, a DNS query sometimes broken or
+lost when it is passing through the ISP line. If SoftEther VPN Server, Client
+or Bridge detects a possibility that the accessing to the actual VPN server
+might be unstable, then DNS queries will be also transferred to the DNS proxy
+cloud servers which are operated by SoftEther Corporation. A DNS proxy cloud
+server will respond DNS queries with answering correct a IP address.
+
+
+4. General Cautions
+4.1. Needs an Approval from Network Administrator
+SoftEther VPN has powerful functions which don't require special settings by
+network administrators. For example, you need not to ask the administrator to
+configure the existing firewall in order to "open" a TCP/UDP port. Such
+characteristic features are for the purpose to eliminate working times and
+costs of network administrators, and avoid misconfiguration-risks around the
+tasks to open specific exception ports on the firewall. However, any employees
+belong to the company have to obtain an approval from the network
+administrator before installs SoftEther VPN. If your network administrator
+neglects to provide such an approval, you can consider to take an approval
+from an upper authority. (For example, executive officer of the company.) If
+you use SoftEther VPN without any approvals from the authority of your
+company, you might have disadvantage. SoftEther Corporation will be never
+liable for results or damages of using SoftEther VPN.
+
+4.2. Observe Laws of Your Country
+If your country's law prohibits the use of encryption, you have to disable the
+encryption function of SoftEther VPN by yourself. Similarly, in some countries
+or regions, some functions of SoftEther VPN might be prohibited to use by
+laws. Other countries' laws are none of SoftEther Corporation's concern
+because SoftEther Corporation is an enterprise which is located and registered
+in Japan physically. For example, there might be a risk that a part of
+SoftEther VPN conflicts an existing patent which is valid only on the specific
+region. SoftEther Corporation has no interests in such specific region outside
+Japan's territory. Therefore, if you want to use SoftEther VPN in regions
+outside Japan, you have to be careful not to violate third-person's rights.
+You have to verify the legitimacy of the use of SoftEther VPN in the specific
+region before you actually use it in such region. By nature, there are almost
+200 countries in the World, and each country's law is different each other. It
+is practically impossible to verify every countries' laws and regulations and
+make the software comply with all countries' laws in advance to release the
+software. Therefore SoftEther Corporation has verified the legitimacy of
+SoftEther VPN against the laws and regulations of only Japan. If a user uses
+SoftEther VPN in a specific country, and damaged by public servants of the
+government authority, SoftEther Corporation will never be liable to recover or
+compensate such damages or criminal responsibilities.
+
+
+5. VPN Gate Academic Experiment Project
+(This chapter applies only on SoftEther VPN software package which contains
+the extension plug-in for VPN Gate Academic Experiment Project.)
+5.1. About VPN Gate Academic Experiment Project
+VPN Gate Academic Experiment Project is an online service operated for just
+the academic research purpose at the graduate school of University of Tsukuba,
+Japan. The purpose of this research is to expend our knowledge about the
+"Global Distributed Public VPN Relay Server" (GDPVRS) technology. For details,
+please visit http://www.vpngate.net/.
+
+5.2. About VPN Gate Service
+SoftEther VPN Server and SoftEther VPN Client may contain "VPN Gate Service"
+program. However, VPN Gate Service is disabled by default.
+VPN Gate Service should be activated and enabled by the voluntary intention of
+the owner of the computer which SoftEther VPN Server or SoftEther VPN Client
+is installed on. After you activate VPN Gate Service, the computer will be
+start to serve as a part of the Global Distributed Public VPN Relay Servers.
+The IP address, hostname and related information of the computer will be sent
+and registered to the directory server of VPN Gate Academic Experiment
+Project, and they will be published and disclosed to the public. This
+mechanism will allow any VPN Gate Client software's user to connect to the VPN
+Gate Service running on your computer. While the VPN session between a VPN
+Gate Client and your VPN Gate Service is established, the VPN Gate Client's
+user can send/receive any IP packets towards the Internet via the VPN Gate
+Service. The global IP address of the VPN Gate Service's hosing computer will
+be used as the source IP address of such communications which a VPN Gate
+Client initiates.
+VPN Gate Service will send some information to the VPN Gate Academic
+Experiment Service Directory Server. The information includes the operator's
+information which described in section 5.5, logging settings, uptime,
+operating system version, type of protocol, port numbers, quality information,
+statistical information, VPN Gate clients' log history data (includes dates,
+IP addresses, version numbers and IDs) and the version of the software. These
+information will be exposed on the directory. VPN Gate Service also receives a
+key for encoding which is described on the chapter 5.9 from the directory
+server.
+
+5.3. Details of VPN Gate Service's Behavior
+If you enable VPN Gate Service manually, which is disabled by default, the
+"VPNGATE" Virtual Hub will be created on the SoftEther VPN Server. If you are
+using SoftEther VPN Client and attempt to active VPN Gate Service on it, an
+equivalent program to SoftEther VPN Server will be invoked on the same process
+of SoftEther VPN Client, and the "VPNGATE" Virtual Hub will be created. The
+"VPNGATE" Virtual Hub contains a user named "VPN" by default which permits
+anyone on the Internet to make a VPN connection to the Virtual Hub. Once a VPN
+Client connects to the "VPNGATE" Virtual Hub, any communication between the
+user and the Internet will pass through the Virtual Hub, and
+transmitted/received using the physical network interface on the computer
+which SoftEther VPN Server (or SoftEther VPN Client) is running on. This will
+cause the result that a destination host specified by the VPN Client will
+identify that the source of the communication has initiated from the VPN Gate
+Service's hosting computer's IP address. However, for safety, any packets
+which destinations are within 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0
+or 10.0.0.0/255.0.0.0 will be blocked by the "VPNGATE" Virtual Hub in order to
+protect your local network. Therefore, if you run VPN Gate Service on your
+corporate network or private network, it is safe because anonymous VPN Client
+users will not be permitted to access such private networks. VPN Gate Service
+also serves as relay for accessing to the VPN Gate Directory Server.
+In order to make VPN Gate Service familiar with firewalls and NATs, it opens
+an UDP port by using the NAT Traversal function which is described on the
+section 1.2. It also opens and listens on some TCP ports, and some TCP and UDP
+ports will be specified as the target port of Universal Plug and Play (UPnP)
+Port Transfer entries which are requested to your local routers. UPnP request
+packets will be sent periodically. Some routers keep such an opened TCP/UDP
+port permanently on the device. If you wish to close them, do it manually.
+VPN Gate Service also provides the mirror-site function for www.vpngate.net.
+This is a mechanism that a copy of the latest contents from www.vpngate.net
+will be hosted by the mirror-site tiny HTTP server which is running on the VPN
+Gate Service program. It will register itself on the mirror-sites list in
+www.vpngate.net. However, it never relays any other communications which are
+not towards www.vpngate.net.
+
+5.4. Communication between Internet via VPN Gate Service
+VPN Gate Service provides a routing between users and the Internet, by using
+the Virtual NAT Function which is described on the section 2.8. VPN Gate
+Service sends polling Ping packets to the server which is located on
+University of Tsukuba, and the Google Public DNS Server which is identified as
+8.8.8.8, in order to check the latest quality of your Internet line. VPN Gate
+Service also sends and receives a lot of random packets to/from the Speed Test
+Server on University of Tsukuba. These quality data will be reported to VPN
+Gate Directory Server, automatically and periodically. The result will be
+saved and disclosed to the public. These periodical polling communication are
+adjusted not to occupy the Internet line, however in some circumstances they
+might occupy the line.
+
+5.5. Operator's Information of VPN Gate Service
+If you activate VPN Gate Service on your computer, the computer will be a part
+of the Global Distributed Public VPN Relay Servers. Therefore, the Operator's
+administrative information of your VPN Gate Service should be reported and
+registered on the VPN Gate Service Directory. Operator's information contains
+the name of the operator and the abuse-reporting contact e-mail address. These
+information can be inputted on the screen if the VPN Gate configuration.
+Inputted information will be transmitted to the VPN Gate Directory Server,
+stored and disclosed to the public. So you have to be careful to input
+information. By the way, until you specify something as the operator's
+information, the computer's hostname will be used automatically as the field
+of the name of the operator, by appending the "'s owner" string after the
+hostname.
+
+5.6. Observe Laws to Operate VPN Gate Service
+In some countries or regions, a user who is planning to activate and operate
+VPN Gate Service, he are mandated to obtain a license or register a service
+from/to the government. If your region has such a regulation, you must fulfill
+mandated process before activating VPN Gate Service in advance. Neither the
+developers nor operators of the VPN Gate Academic Experiment Project will be
+liable for legal/criminal responsibilities or damages which are occurred from
+failure to comply your local laws.
+
+5.7. Protect Privacy of Communication
+Most of countries have a law which requires communication service's operators,
+including VPN Gate Service operators, to protect the privacy of communication
+of third-persons. When you operate VPN Gate Service, you must always protect
+user's privacy.
+
+5.8. Packet Logs
+The packet logging function is implemented on VPN Gate Service. It records
+essential headers of major TCP/IP packets which are transmitted via the
+Virtual Hub. This function will be helpful to investigate the "original IP
+address" of the initiator of communication who was a connected user of your
+VPN Gate Service, by checking the packet logs and the connection logs. The
+packet logs are recorded only for such legitimate investigates purpose. Do not
+peek nor leak packet logs except the rightful purpose. Such act will be
+violate the section 5.7.
+
+5.9. Packet Logs Automatic Archiving and Encoding Function
+The VPN Gate Academic Experiment Service is operated and running under the
+Japanese constitution and laws. The Japanese constitution laws demand strictly
+protection over the privacy of communication. Because this service is under
+Japanese rules, the program of VPN Gate Service implements this "Automatic Log
+File Encoding" protection mechanism, and enabled by default.
+The VPN Gate Service is currently configured to encode packet log files which
+has passed two or more weeks automatically, by default. In order to protect
+privacy of communication, if a packet log file is once encoded, even the
+administrator of the local computer cannot censor the packet log file. This
+mechanism protects privacy of end-users of VPN Gate Service.
+You can change the VPN Gate Service setting to disable this automatic encoding
+function. Then packet log files will never be encoded even after two weeks
+passed. In such a configuration, all packet logs will remain as plain-text on
+the disk. Therefore you have to take care not to violate user's privacy.
+If you are liable to decode an encoded packet log files (for example: a VPN
+Gate Service's user illegally abused your VPN Gate Service and you have to
+decode the packet logs in order to comply the laws), contact the administrator
+of the VPN Gate Academic Experiment Service at Graduate School of University
+of Tsukuba, Japan. You can find the contact address at
+http://www.vpngate.net/. The administrator of VPN Gate Service will respond to
+decode the packet logs if there is an appropriate and legal request from court
+or other judicial authorities, according to laws.
+
+5.10. Caution if You Operate VPN Gate Service in the Japan's Territories
+When a user operates VPN Gate Service in the Japan's territories, such an act
+may be regulated under the Japanese Telecommunication Laws if the operation is
+a subject to the law. However, in such a circumstance, according to the
+"Japanese Telecommunication Business Compete Manual [supplemental version]" ,
+non- profitable operations of communications are not identified as a
+"telecommunication business" . So usual operators of VPN Gate Service are not
+subjects to "telecommunication business operators" , and not be mandated to
+register to the government. Even so, legalities to protect the privacy of
+communication still imposed. As a conclusion, if you operate VPN Gate Service
+in the Japan's Territories, you must not leak the secrets of communications
+which are transmitted via your operating VPN Gate Service.
+
+5.11. VPN Gate Client
+If SoftEther VPN Client contains the VPN Gate Client plug-in, you can use it
+to obtain the list of current operating VPN Gate Service servers in the
+Internet, and make a VPN connection to a specific server on the list.
+VPN Gate Client always keeps the latest list of the VPN Gate Services
+periodically. Be careful if you are using a pay-per-use Internet line.
+When you start the VPN Gate Client software, the screen which asks you
+activate or not VPN Gate Service will be appeared. For details of VPN Gate
+Service, read the above sections.
+
+5.12. Caution before Joining or Exploiting VPN Gate Academic Experiment
+Project
+The VPN Gate Academic Experiment Service is operated as a research project at
+the graduate school on University of Tsukuba, Japan. The service is governed
+under the Japanese laws. Other countries' laws are none of our concerns nor
+responsibilities.
+By nature, there are almost 200 countries in the World, with different laws.
+It is impossible to verify every countries' laws and regulations and make the
+software comply with all countries' laws in advance to release the software.
+If a user uses VPN Gate service in a specific country, and damaged by public
+servants of the authority, the developer of either the service or software
+will never be liable to recover or compensate such damages or criminal
+responsibilities.
+By using this software and service, the user must observe all concerned laws
+and rules with user's own responsibility. The user will be completely liable
+to any damages and responsibilities which are results of using this software
+and service, regardless of either inside or outside of Japan's territory.
+If you don't agree nor understand the above warnings, do not use any of VPN
+Gate Academic Experiment Service functions.
+VPN Gate is a research project for just academic purpose only. VPN Gate was
+developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN
+Gate were developed on this research project at University of Tsukuba. Any
+parts of VPN Gate are not developed by SoftEther Corporation. The VPN Gate
+Research Project is not a subject to be led, operated, promoted nor guaranteed
+by SoftEther Corporation.
+
+
diff --git a/src/Mayaqua/Cfg.c b/src/Mayaqua/Cfg.c
new file mode 100644
index 00000000..aa43eb84
--- /dev/null
+++ b/src/Mayaqua/Cfg.c
@@ -0,0 +1,2306 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cfg.c
+// Configuration information manipulation module
+
+#include <GlobalConst.h>
+
+#define CFG_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Create a backup of the configuration file
+void BackupCfgWEx(CFG_RW *rw, FOLDER *f, wchar_t *original, UINT revision_number)
+{
+ wchar_t dirname[MAX_PATH];
+ wchar_t filename[MAX_PATH];
+ wchar_t fullpath[MAX_PATH];
+ wchar_t datestr[MAX_PATH];
+ SYSTEMTIME st;
+ // Validate arguments
+ if (f == NULL || filename == NULL || rw == NULL)
+ {
+ return;
+ }
+
+ // Determine the directory name
+ UniFormat(dirname, sizeof(dirname), L"@backup.%s", original[0] == L'@' ? original + 1 : original);
+
+ // Determine the file name
+ LocalTime(&st);
+ UniFormat(datestr, sizeof(datestr), L"%04u%02u%02u%02u_%s",
+ st.wYear, st.wMonth, st.wDay, st.wHour, original[0] == L'@' ? original + 1 : original);
+
+ if (revision_number == INFINITE)
+ {
+ UniStrCpy(filename, sizeof(filename), datestr);
+ }
+ else
+ {
+ UniFormat(filename, sizeof(filename), L"%08u_%s",
+ revision_number, original[0] == L'@' ? original + 1 : original);
+ }
+
+ // Don't save if the date and time has not been changed
+ if (UniStrCmpi(datestr, rw->LastSavedDateStr) == 0)
+ {
+ return;
+ }
+
+ UniStrCpy(rw->LastSavedDateStr, sizeof(rw->LastSavedDateStr), datestr);
+
+ // Check the existence of file name
+ if (IsFileExistsW(filename))
+ {
+ return;
+ }
+
+ // Create the directory
+ MakeDirW(dirname);
+
+ // Save the file
+ UniFormat(fullpath, sizeof(fullpath), L"%s/%s", dirname, filename);
+ CfgSaveW(f, fullpath);
+}
+
+// Close the configuration file R/W
+void FreeCfgRw(CFG_RW *rw)
+{
+ // Validate arguments
+ if (rw == NULL)
+ {
+ return;
+ }
+
+ if (rw->Io != NULL)
+ {
+ FileClose(rw->Io);
+ }
+
+ DeleteLock(rw->lock);
+ Free(rw->FileNameW);
+ Free(rw->FileName);
+ Free(rw);
+}
+
+// Writing to the configuration file
+UINT SaveCfgRw(CFG_RW *rw, FOLDER *f)
+{
+ return SaveCfgRwEx(rw, f, INFINITE);
+}
+UINT SaveCfgRwEx(CFG_RW *rw, FOLDER *f, UINT revision_number)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (rw == NULL || f == NULL)
+ {
+ return 0;
+ }
+
+ Lock(rw->lock);
+ {
+ if (rw->Io != NULL)
+ {
+ FileClose(rw->Io);
+ rw->Io = NULL;
+ }
+
+ if (CfgSaveExW2(rw, f, rw->FileNameW, &ret))
+ {
+ if (rw->DontBackup == false)
+ {
+ BackupCfgWEx(rw, f, rw->FileNameW, revision_number);
+ }
+ }
+ else
+ {
+ ret = 0;
+ }
+
+ rw->Io = FileOpenW(rw->FileNameW, false);
+ }
+ Unlock(rw->lock);
+
+ return ret;
+}
+
+// Creating a configuration file R/W
+CFG_RW *NewCfgRw(FOLDER **root, char *cfg_name)
+{
+ return NewCfgRwEx(root, cfg_name, false);
+}
+CFG_RW *NewCfgRwW(FOLDER **root, wchar_t *cfg_name)
+{
+ return NewCfgRwExW(root, cfg_name, false);
+}
+CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup)
+{
+ wchar_t *cfg_name_w = CopyStrToUni(cfg_name);
+ CFG_RW *ret = NewCfgRwExW(root, cfg_name_w, dont_backup);
+
+ Free(cfg_name_w);
+
+ return ret;
+}
+CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup)
+{
+ CFG_RW *rw;
+ FOLDER *f;
+ // Validate arguments
+ if (cfg_name == NULL || root == NULL)
+ {
+ return NULL;
+ }
+
+ f = CfgReadW(cfg_name);
+ if (f == NULL)
+ {
+ rw = ZeroMalloc(sizeof(CFG_RW));
+ rw->lock = NewLock();
+ rw->FileNameW = CopyUniStr(cfg_name);
+ rw->FileName = CopyUniToStr(cfg_name);
+ rw->Io = FileCreateW(cfg_name);
+ *root = NULL;
+ rw->DontBackup = dont_backup;
+
+ return rw;
+ }
+
+ rw = ZeroMalloc(sizeof(CFG_RW));
+ rw->FileNameW = CopyUniStr(cfg_name);
+ rw->FileName = CopyUniToStr(cfg_name);
+ rw->Io = FileOpenW(cfg_name, false);
+ rw->lock = NewLock();
+
+ *root = f;
+
+ rw->DontBackup = dont_backup;
+
+ return rw;
+}
+
+// Copy a file
+bool FileCopy(char *src, char *dst)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(src);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ ret = DumpBuf(b, dst);
+
+ FreeBuf(b);
+
+ return ret;
+}
+bool FileCopyW(wchar_t *src, wchar_t *dst)
+{
+ return FileCopyExW(src, dst, true);
+}
+bool FileCopyExW(wchar_t *src, wchar_t *dst, bool read_lock)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpExW(src, false);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ ret = DumpBufW(b, dst);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Save the settings to a file
+void CfgSave(FOLDER *f, char *name)
+{
+ CfgSaveEx(NULL, f, name);
+}
+void CfgSaveW(FOLDER *f, wchar_t *name)
+{
+ CfgSaveExW(NULL, f, name);
+}
+bool CfgSaveEx(CFG_RW *rw, FOLDER *f, char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = CfgSaveExW(rw, f, name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool CfgSaveExW(CFG_RW *rw, FOLDER *f, wchar_t *name)
+{
+ return CfgSaveExW2(rw, f, name, NULL);
+}
+bool CfgSaveExW2(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size)
+{
+ return CfgSaveExW3(rw, f, name, written_size, IsFileExistsW(SAVE_BINARY_FILE_NAME_SWITCH));
+}
+bool CfgSaveExW3(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size, bool write_binary)
+{
+ wchar_t tmp[MAX_SIZE];
+ bool text = !write_binary;
+ UCHAR hash[SHA1_SIZE];
+ BUF *b;
+ IO *o;
+ bool ret = true;
+ UINT dummy_int = 0;
+ // Validate arguments
+ if (name == NULL || f == NULL)
+ {
+ return false;
+ }
+ if (written_size == NULL)
+ {
+ written_size = &dummy_int;
+ }
+
+ // Convert to buffer
+ b = CfgFolderToBuf(f, text);
+ if (b == NULL)
+ {
+ return false;
+ }
+ // Hash the contents
+ Hash(hash, b->Buf, b->Size, true);
+
+ // Compare the contents to be written with the content which was written last
+ if (rw != NULL)
+ {
+ if (Cmp(hash, rw->LashHash, SHA1_SIZE) == 0)
+ {
+ // Contents are not changed
+ ret = false;
+ }
+ else
+ {
+ Copy(rw->LashHash, hash, SHA1_SIZE);
+ }
+ }
+
+ if (ret || OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ // Generate a temporary file name
+ UniFormat(tmp, sizeof(tmp), L"%s.log", name);
+ // Copy the file that currently exist to a temporary file
+ FileCopyW(name, tmp);
+
+ // Save the new file
+ o = FileCreateW(name);
+ if (o != NULL)
+ {
+ if (FileWrite(o, b->Buf, b->Size) == false)
+ {
+ // File saving failure
+ FileClose(o);
+ FileDeleteW(name);
+ FileRenameW(tmp, name);
+
+ if (rw != NULL)
+ {
+ Zero(rw->LashHash, sizeof(rw->LashHash));
+ }
+ }
+ else
+ {
+ // Successful saving file
+ FileClose(o);
+ // Delete the temporary file
+ FileDeleteW(tmp);
+ }
+ }
+ else
+ {
+ // File saving failure
+ FileRenameW(tmp, name);
+
+ if (rw != NULL)
+ {
+ Zero(rw->LashHash, sizeof(rw->LashHash));
+ }
+ }
+ }
+
+ *written_size = b->Size;
+
+ // Release memory
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read the settings from the file
+FOLDER *CfgRead(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ FOLDER *ret = CfgReadW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+FOLDER *CfgReadW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t newfile[MAX_SIZE];
+ BUF *b;
+ IO *o;
+ UINT size;
+ void *buf;
+ FOLDER *f;
+ bool delete_new = false;
+ bool binary_file = false;
+ bool invalid_file = false;
+ UCHAR header[8];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate a new file name
+ UniFormat(newfile, sizeof(newfile), L"%s.new", name);
+ // Generate a temporary file name
+ UniFormat(tmp, sizeof(tmp), L"%s.log", name);
+
+ // Read the new file if it exists
+ o = FileOpenW(newfile, false);
+ if (o == NULL)
+ {
+ // Read the temporary file
+ o = FileOpenW(tmp, false);
+ }
+ else
+ {
+ delete_new = true;
+ }
+ if (o == NULL)
+ {
+ // Read the original file if there is no temporary file
+ o = FileOpenW(name, false);
+ }
+ else
+ {
+ // Read the original file too if the size of temporary file is 0
+ if (FileSize(o) == 0)
+ {
+ invalid_file = true;
+ }
+
+ if (invalid_file)
+ {
+ FileClose(o);
+ o = FileOpenW(name, false);
+ }
+ }
+ if (o == NULL)
+ {
+ // Failed to read
+ return NULL;
+ }
+
+ // Read into the buffer
+ size = FileSize(o);
+ buf = Malloc(size);
+ FileRead(o, buf, size);
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBuf(b, 0, 0);
+
+ // Close the file
+ FileClose(o);
+
+ if (delete_new)
+ {
+ // Delete the new file
+ FileDeleteW(newfile);
+ }
+
+ // If the beginning 8 character of the buffer is "SEVPN_DB", it is binary file
+ ReadBuf(b, header, sizeof(header));
+ if (Cmp(header, TAG_BINARY, 8) == 0)
+ {
+ UCHAR hash1[SHA1_SIZE], hash2[SHA1_SIZE];
+ binary_file = true;
+
+ // Check the hash
+ ReadBuf(b, hash1, sizeof(hash1));
+
+ Hash(hash2, ((UCHAR *)b->Buf) + 8 + SHA1_SIZE, b->Size - 8 - SHA1_SIZE, true);
+
+ if (Cmp(hash1, hash2, SHA1_SIZE) != 0)
+ {
+ // Corrupted file
+ invalid_file = true;
+ FreeBuf(b);
+ return NULL;
+ }
+ }
+
+ SeekBuf(b, 0, 0);
+
+ if (binary_file)
+ {
+ SeekBuf(b, 8 + SHA1_SIZE, 0);
+ }
+
+ // Convert the buffer into a folder
+ if (binary_file == false)
+ {
+ // Text mode
+ f = CfgBufTextToFolder(b);
+ }
+ else
+ {
+ // Binary mode
+ f = CfgBufBinToFolder(b);
+ }
+
+ // Memory release
+ Free(buf);
+ FreeBuf(b);
+
+ FileDeleteW(newfile);
+
+ return f;
+}
+
+// Test of Cfg
+void CfgTest2(FOLDER *f, UINT n)
+{
+}
+
+void CfgTest()
+{
+#if 0
+ FOLDER *root;
+ BUF *b;
+ Debug("\nCFG Test Begin\n");
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+ CfgTest2(root, 5);
+
+ b = CfgFolderToBufText(root);
+ //Print("%s\n", b->Buf);
+ SeekBuf(b, 0, 0);
+
+ CfgDeleteFolder(root);
+
+ DumpBuf(b, "test1.config");
+
+ root = CfgBufTextToFolder(b);
+
+ FreeBuf(b);
+
+ b = CfgFolderToBufText(root);
+// Print("%s\n", b->Buf);
+ DumpBuf(b, "test2.config");
+ FreeBuf(b);
+
+ CfgSave(root, "test.txt");
+
+ CfgDeleteFolder(root);
+
+ Debug("\nCFG Test End\n");
+#endif
+}
+
+// Read one line
+char *CfgReadNextLine(BUF *b)
+{
+ char *tmp;
+ char *buf;
+ UINT len;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Examine the number of characters up to the next newline
+ tmp = (char *)b->Buf + b->Current;
+ if ((b->Size - b->Current) == 0)
+ {
+ // Read to the end
+ return NULL;
+ }
+ len = 0;
+ while (true)
+ {
+ if (tmp[len] == 13 || tmp[len] == 10)
+ {
+ if (tmp[len] == 13)
+ {
+ if (len < (b->Size - b->Current))
+ {
+ len++;
+ }
+ }
+ break;
+ }
+ len++;
+ if (len >= (b->Size - b->Current))
+ {
+ break;
+ }
+ }
+
+ // Read ahead only 'len' bytes
+ buf = ZeroMalloc(len + 1);
+ ReadBuf(b, buf, len);
+ SeekBuf(b, 1, 1);
+
+ if (StrLen(buf) >= 1)
+ {
+ if (buf[StrLen(buf) - 1] == 13)
+ {
+ buf[StrLen(buf) - 1] = 0;
+ }
+ }
+
+ return buf;
+}
+
+// Read the text stream
+bool CfgReadNextTextBUF(BUF *b, FOLDER *current)
+{
+ char *buf;
+ TOKEN_LIST *token;
+ char *name;
+ char *string;
+ char *data;
+ bool ret;
+ FOLDER *f;
+
+ // Validate arguments
+ if (b == NULL || current == NULL)
+ {
+ return false;
+ }
+
+ ret = true;
+
+ // Read one line
+ buf = CfgReadNextLine(b);
+ if (buf == NULL)
+ {
+ return false;
+ }
+
+ // Analyze this line
+ token = ParseToken(buf, "\t ");
+ if (token == NULL)
+ {
+ Free(buf);
+ return false;
+ }
+
+ if (token->NumTokens >= 1)
+ {
+ if (!StrCmpi(token->Token[0], TAG_DECLARE))
+ {
+ if (token->NumTokens >= 2)
+ {
+ // declare
+ name = CfgUnescape(token->Token[1]);
+
+ // Create a folder
+ f = CfgCreateFolder(current, name);
+
+ // Read the next folder
+ while (true)
+ {
+ if (CfgReadNextTextBUF(b, f) == false)
+ {
+ break;
+ }
+ }
+
+ Free(name);
+ }
+ }
+ if (!StrCmpi(token->Token[0], "}"))
+ {
+ // end
+ ret = false;
+ }
+ if (token->NumTokens >= 3)
+ {
+ name = CfgUnescape(token->Token[1]);
+ data = token->Token[2];
+
+ if (!StrCmpi(token->Token[0], TAG_STRING))
+ {
+ // string
+ wchar_t *uni;
+ UINT uni_size;
+ string = CfgUnescape(data);
+ uni_size = CalcUtf8ToUni(string, StrLen(string));
+ if (uni_size != 0)
+ {
+ uni = Malloc(uni_size);
+ Utf8ToUni(uni, uni_size, string, StrLen(string));
+ CfgAddUniStr(current, name, uni);
+ Free(uni);
+ }
+ Free(string);
+ }
+ if (!StrCmpi(token->Token[0], TAG_INT))
+ {
+ // uint
+ CfgAddInt(current, name, ToInt(data));
+ }
+ if (!StrCmpi(token->Token[0], TAG_INT64))
+ {
+ // uint64
+ CfgAddInt64(current, name, ToInt64(data));
+ }
+ if (!StrCmpi(token->Token[0], TAG_BOOL))
+ {
+ // bool
+ bool b = false;
+ if (!StrCmpi(data, TAG_TRUE))
+ {
+ b = true;
+ }
+ else if (ToInt(data) != 0)
+ {
+ b = true;
+ }
+ CfgAddBool(current, name, b);
+ }
+ if (!StrCmpi(token->Token[0], TAG_BYTE))
+ {
+ // byte
+ char *unescaped_b64 = CfgUnescape(data);
+ void *tmp = Malloc(StrLen(unescaped_b64) * 4 + 64);
+ int size = B64_Decode(tmp, unescaped_b64, StrLen(unescaped_b64));
+ CfgAddByte(current, name, tmp, size);
+ Free(tmp);
+ Free(unescaped_b64);
+ }
+
+ Free(name);
+ }
+ }
+
+ // Release of the token
+ FreeToken(token);
+
+ Free(buf);
+
+ return ret;
+}
+
+// Convert the stream text to a folder
+FOLDER *CfgBufTextToFolder(BUF *b)
+{
+ FOLDER *f, *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Read recursively from the root folder
+ c = CfgCreateFolder(NULL, "tmp");
+
+ while (true)
+ {
+ // Read the text stream
+ if (CfgReadNextTextBUF(b, c) == false)
+ {
+ break;
+ }
+ }
+
+ // Getting root folder
+ f = CfgGetFolder(c, TAG_ROOT);
+ if (f == NULL)
+ {
+ // Root folder is not found
+ CfgDeleteFolder(c);
+ return NULL;
+ }
+
+ // Remove the reference from tmp folder to the root
+ Delete(c->Folders, f);
+ f->Parent = NULL;
+
+ // Delete the tmp folder
+ CfgDeleteFolder(c);
+
+ // Return the root folder
+ return f;
+}
+
+// Read the next folder
+void CfgReadNextFolderBin(BUF *b, FOLDER *parent)
+{
+ char name[MAX_SIZE];
+ FOLDER *f;
+ UINT n, i;
+ UINT size;
+ UCHAR *buf;
+ wchar_t *string;
+ // Validate arguments
+ if (b == NULL || parent == NULL)
+ {
+ return;
+ }
+
+ // Folder name
+ ReadBufStr(b, name, sizeof(name));
+ f = CfgCreateFolder(parent, name);
+
+ // The number of the subfolder
+ n = ReadBufInt(b);
+ for (i = 0;i < n;i++)
+ {
+ // Subfolder
+ CfgReadNextFolderBin(b, f);
+ }
+
+ // The number of items
+ n = ReadBufInt(b);
+ for (i = 0;i < n;i++)
+ {
+ UINT type;
+
+ // Name
+ ReadBufStr(b, name, sizeof(name));
+ // Type
+ type = ReadBufInt(b);
+
+ switch (type)
+ {
+ case ITEM_TYPE_INT:
+ // int
+ CfgAddInt(f, name, ReadBufInt(b));
+ break;
+
+ case ITEM_TYPE_INT64:
+ // int64
+ CfgAddInt64(f, name, ReadBufInt64(b));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ // data
+ size = ReadBufInt(b);
+ buf = ZeroMalloc(size);
+ ReadBuf(b, buf, size);
+ CfgAddByte(f, name, buf, size);
+ Free(buf);
+ break;
+
+ case ITEM_TYPE_STRING:
+ // string
+ size = ReadBufInt(b);
+ buf = ZeroMalloc(size + 1);
+ ReadBuf(b, buf, size);
+ string = ZeroMalloc(CalcUtf8ToUni(buf, StrLen(buf)) + 4);
+ Utf8ToUni(string, 0, buf, StrLen(buf));
+ CfgAddUniStr(f, name, string);
+ Free(string);
+ Free(buf);
+ break;
+
+ case ITEM_TYPE_BOOL:
+ // bool
+ CfgAddBool(f, name, ReadBufInt(b) == 0 ? false : true);
+ break;
+ }
+ }
+}
+
+// Convert the binary to folder
+FOLDER *CfgBufBinToFolder(BUF *b)
+{
+ FOLDER *f, *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a temporary folder
+ c = CfgCreateFolder(NULL, "tmp");
+
+ // Read a binary
+ CfgReadNextFolderBin(b, c);
+
+ // Get root folder
+ f = CfgGetFolder(c, TAG_ROOT);
+ if (f == NULL)
+ {
+ // Missing
+ CfgDeleteFolder(c);
+ return NULL;
+ }
+
+ Delete(c->Folders, f);
+ f->Parent = NULL;
+
+ CfgDeleteFolder(c);
+
+ return f;
+}
+
+// Convert the folder to binary
+BUF *CfgFolderToBufBin(FOLDER *f)
+{
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Header
+ WriteBuf(b, TAG_BINARY, 8);
+
+ // Hash area
+ Zero(hash, sizeof(hash));
+ WriteBuf(b, hash, sizeof(hash));
+
+ // Output the root folder (recursive)
+ CfgOutputFolderBin(b, f);
+
+ // Hash
+ Hash(((UCHAR *)b->Buf) + 8, ((UCHAR *)b->Buf) + 8 + SHA1_SIZE, b->Size - 8 - SHA1_SIZE, true);
+
+ return b;
+}
+
+// Convert the folder to a stream text
+BUF *CfgFolderToBufText(FOLDER *f)
+{
+ return CfgFolderToBufTextEx(f, false);
+}
+BUF *CfgFolderToBufTextEx(FOLDER *f, bool no_banner)
+{
+ BUF *b;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a stream
+ b = NewBuf();
+
+ // Copyright notice
+ if (no_banner == false)
+ {
+ WriteBuf(b, TAG_CPYRIGHT, StrLen(TAG_CPYRIGHT));
+ }
+
+ // Output the root folder (recursive)
+ CfgOutputFolderText(b, f, 0);
+
+ return b;
+}
+
+// Output the folder contents (Enumerate folders)
+bool CfgEnumFolderProc(FOLDER *f, void *param)
+{
+ CFG_ENUM_PARAM *p;
+ // Validate arguments
+ if (f == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ p = (CFG_ENUM_PARAM *)param;
+ // Output the folder contents (recursive)
+ CfgOutputFolderText(p->b, f, p->depth);
+
+ return true;
+}
+
+// Output the contents of the item (enumeration)
+bool CfgEnumItemProc(ITEM *t, void *param)
+{
+ CFG_ENUM_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ p = (CFG_ENUM_PARAM *)param;
+ CfgAddItemText(p->b, t, p->depth);
+
+ return true;
+}
+
+// Output the folder contents (Recursive, binary)
+void CfgOutputFolderBin(BUF *b, FOLDER *f)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Folder name
+ WriteBufStr(b, f->Name);
+
+ // The number of the subfolder
+ WriteBufInt(b, LIST_NUM(f->Folders));
+
+ // Subfolder
+ for (i = 0;i < LIST_NUM(f->Folders);i++)
+ {
+ FOLDER *sub = LIST_DATA(f->Folders, i);
+ CfgOutputFolderBin(b, sub);
+
+ if ((i % 100) == 99)
+ {
+ YieldCpu();
+ }
+ }
+
+ // The number of Items
+ WriteBufInt(b, LIST_NUM(f->Items));
+
+ // Item
+ for (i = 0;i < LIST_NUM(f->Items);i++)
+ {
+ char *utf8;
+ UINT utf8_size;
+ ITEM *t = LIST_DATA(f->Items, i);
+
+ // Item Name
+ WriteBufStr(b, t->Name);
+
+ // Type
+ WriteBufInt(b, t->Type);
+
+ switch (t->Type)
+ {
+ case ITEM_TYPE_INT:
+ // Integer
+ WriteBufInt(b, *((UINT *)t->Buf));
+ break;
+
+ case ITEM_TYPE_INT64:
+ // 64-bit integer
+ WriteBufInt64(b, *((UINT64 *)t->Buf));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ // Data size
+ WriteBufInt(b, t->size);
+ // Data
+ WriteBuf(b, t->Buf, t->size);
+ break;
+
+ case ITEM_TYPE_STRING:
+ // String
+ utf8_size = CalcUniToUtf8((wchar_t *)t->Buf) + 1;
+ utf8 = ZeroMalloc(utf8_size);
+ UniToUtf8(utf8, utf8_size, (wchar_t *)t->Buf);
+ WriteBufInt(b, StrLen(utf8));
+ WriteBuf(b, utf8, StrLen(utf8));
+ Free(utf8);
+ break;
+
+ case ITEM_TYPE_BOOL:
+ // Boolean type
+ if (*((bool *)t->Buf) == false)
+ {
+ WriteBufInt(b, 0);
+ }
+ else
+ {
+ WriteBufInt(b, 1);
+ }
+ break;
+ }
+ }
+}
+
+// Output the contents of the folder (Recursive, text)
+void CfgOutputFolderText(BUF *b, FOLDER *f, UINT depth)
+{
+ CFG_ENUM_PARAM p;
+ // Validate arguments
+ if (b == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Output starting of the folder
+ CfgAddDeclare(b, f->Name, depth);
+ depth++;
+
+ Zero(&p, sizeof(CFG_ENUM_PARAM));
+ p.depth = depth;
+ p.b = b;
+ p.f = f;
+
+ // Enumerate the list of items
+ CfgEnumItem(f, CfgEnumItemProc, &p);
+
+ if (LIST_NUM(f->Folders) != 0 && LIST_NUM(f->Items) != 0)
+ {
+ WriteBuf(b, "\r\n", 2);
+ }
+
+ // Enumerate the folder list
+ CfgEnumFolder(f, CfgEnumFolderProc, &p);
+ // Output the end of the folder
+ depth--;
+ CfgAddEnd(b, depth);
+
+ //WriteBuf(b, "\r\n", 2);
+}
+
+// Output contents of the item
+void CfgAddItemText(BUF *b, ITEM *t, UINT depth)
+{
+ char *data;
+ char *sub = NULL;
+ UINT len;
+ UINT size;
+ char *utf8;
+ UINT utf8_size;
+ wchar_t *string;
+ // Validate arguments
+ if (b == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // Process the data by its type
+ data = NULL;
+ switch (t->Type)
+ {
+ case ITEM_TYPE_INT:
+ data = Malloc(32);
+ ToStr(data, *((UINT *)t->Buf));
+ break;
+
+ case ITEM_TYPE_INT64:
+ data = Malloc(64);
+ ToStr64(data, *((UINT64 *)t->Buf));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ data = ZeroMalloc(t->size * 4 + 32);
+ len = B64_Encode(data, t->Buf, t->size);
+ data[len] = 0;
+ break;
+
+ case ITEM_TYPE_STRING:
+ string = t->Buf;
+ utf8_size = CalcUniToUtf8(string);
+ utf8_size++;
+ utf8 = ZeroMalloc(utf8_size);
+ utf8[0] = 0;
+ UniToUtf8(utf8, utf8_size, string);
+ size = utf8_size;
+ data = utf8;
+ break;
+
+ case ITEM_TYPE_BOOL:
+ size = 32;
+ data = Malloc(size);
+ if (*((bool *)t->Buf) == false)
+ {
+ StrCpy(data, size, TAG_FALSE);
+ }
+ else
+ {
+ StrCpy(data, size, TAG_TRUE);
+ }
+ break;
+ }
+ if (data == NULL)
+ {
+ return;
+ }
+
+ // Output the data line
+ CfgAddData(b, t->Type, t->Name, data, sub, depth);
+
+ // Memory release
+ Free(data);
+ if (sub != NULL)
+ {
+ Free(sub);
+ }
+}
+
+// Output the data line
+void CfgAddData(BUF *b, UINT type, char *name, char *data, char *sub, UINT depth)
+{
+ char *tmp;
+ char *name2;
+ char *data2;
+ char *sub2 = NULL;
+ UINT tmp_size;
+ // Validate arguments
+ if (b == NULL || type == 0 || name == NULL || data == NULL)
+ {
+ return;
+ }
+
+ name2 = CfgEscape(name);
+ data2 = CfgEscape(data);
+ if (sub != NULL)
+ {
+ sub2 = CfgEscape(sub);
+ }
+
+ tmp_size = StrLen(name2) + StrLen(data2) + 2 + 64 + 1;
+ tmp = Malloc(tmp_size);
+
+ if (sub2 != NULL)
+ {
+ StrCpy(tmp, tmp_size, CfgTypeToStr(type));
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, name2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, data2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, sub2);
+ }
+ else
+ {
+ StrCpy(tmp, tmp_size, CfgTypeToStr(type));
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, name2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, data2);
+ }
+
+ Free(name2);
+ Free(data2);
+ if (sub2 != NULL)
+ {
+ Free(sub2);
+ }
+ CfgAddLine(b, tmp, depth);
+ Free(tmp);
+}
+
+// Convert the data type string to an integer value
+UINT CfgStrToType(char *str)
+{
+ if (!StrCmpi(str, TAG_INT)) return ITEM_TYPE_INT;
+ if (!StrCmpi(str, TAG_INT64)) return ITEM_TYPE_INT64;
+ if (!StrCmpi(str, TAG_BYTE)) return ITEM_TYPE_BYTE;
+ if (!StrCmpi(str, TAG_STRING)) return ITEM_TYPE_STRING;
+ if (!StrCmpi(str, TAG_BOOL)) return ITEM_TYPE_BOOL;
+ return 0;
+}
+
+// Convert the type of data to a string
+char *CfgTypeToStr(UINT type)
+{
+ switch (type)
+ {
+ case ITEM_TYPE_INT:
+ return TAG_INT;
+ case ITEM_TYPE_INT64:
+ return TAG_INT64;
+ case ITEM_TYPE_BYTE:
+ return TAG_BYTE;
+ case ITEM_TYPE_STRING:
+ return TAG_STRING;
+ case ITEM_TYPE_BOOL:
+ return TAG_BOOL;
+ }
+ return NULL;
+}
+
+// Outputs the End line
+void CfgAddEnd(BUF *b, UINT depth)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ CfgAddLine(b, "}", depth);
+// CfgAddLine(b, TAG_END, depth);
+}
+
+// Outputs the Declare lines
+void CfgAddDeclare(BUF *b, char *name, UINT depth)
+{
+ char *tmp;
+ char *name2;
+ UINT tmp_size;
+ // Validate arguments
+ if (b == NULL || name == NULL)
+ {
+ return;
+ }
+
+ name2 = CfgEscape(name);
+
+ tmp_size = StrLen(name2) + 2 + StrLen(TAG_DECLARE);
+ tmp = Malloc(tmp_size);
+
+ Format(tmp, 0, "%s %s", TAG_DECLARE, name2);
+ CfgAddLine(b, tmp, depth);
+ CfgAddLine(b, "{", depth);
+ Free(tmp);
+ Free(name2);
+}
+
+// Outputs one line
+void CfgAddLine(BUF *b, char *str, UINT depth)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < depth;i++)
+ {
+ WriteBuf(b, "\t", 1);
+ }
+ WriteBuf(b, str, StrLen(str));
+ WriteBuf(b, "\r\n", 2);
+}
+
+// Convert the folder to a stream
+BUF *CfgFolderToBuf(FOLDER *f, bool textmode)
+{
+ return CfgFolderToBufEx(f, textmode, false);
+}
+BUF *CfgFolderToBufEx(FOLDER *f, bool textmode, bool no_banner)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ if (textmode)
+ {
+ return CfgFolderToBufTextEx(f, no_banner);
+ }
+ else
+ {
+ return CfgFolderToBufBin(f);;
+ }
+}
+
+// Escape restoration of the string
+char *CfgUnescape(char *str)
+{
+ char *tmp;
+ char *ret;
+ char tmp2[16];
+ UINT len, wp, i;
+ UINT code;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp = ZeroMalloc(len + 1);
+ wp = 0;
+ if (len == 1 && str[0] == '$')
+ {
+ // Empty character
+ tmp[0] = 0;
+ }
+ else
+ {
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != '$')
+ {
+ tmp[wp++] = str[i];
+ }
+ else
+ {
+ tmp2[0] = '0';
+ tmp2[1] = 'x';
+ tmp2[2] = str[i + 1];
+ tmp2[3] = str[i + 2];
+ i += 2;
+ tmp2[4] = 0;
+ code = ToInt(tmp2);
+ tmp[wp++] = (char)code;
+ }
+ }
+ }
+ ret = Malloc(StrLen(tmp) + 1);
+ StrCpy(ret, StrLen(tmp) + 1, tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Escape the string
+char *CfgEscape(char *str)
+{
+ char *tmp;
+ char *ret;
+ char tmp2[16];
+ UINT len;
+ UINT wp, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp = ZeroMalloc(len * 3 + 2);
+ if (len == 0)
+ {
+ // Empty character
+ StrCpy(tmp, (len * 3 + 2), "$");
+ }
+ else
+ {
+ // Non null character
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (CfgCheckCharForName(str[i]))
+ {
+ tmp[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp++] = '$';
+ Format(tmp2, sizeof(tmp2), "%02X", (UINT)str[i]);
+ tmp[wp++] = tmp2[0];
+ tmp[wp++] = tmp2[1];
+ }
+ }
+ }
+ ret = Malloc(StrLen(tmp) + 1);
+ StrCpy(ret, 0, tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Check if the character can be used in the name
+bool CfgCheckCharForName(char c)
+{
+ if (c >= 0 && c <= 31)
+ {
+ return false;
+ }
+ if (c == ' ' || c == '\t')
+ {
+ return false;
+ }
+ if (c == '$')
+ {
+ return false;
+ }
+ return true;
+}
+
+// Get the string type value
+bool CfgGetStr(FOLDER *f, char *name, char *str, UINT size)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ // Get unicode string temporarily
+ tmp_size = size * 4 + 10; // Just to make sure, a quantity of this amount is secured.
+ tmp = Malloc(tmp_size);
+ if (CfgGetUniStr(f, name, tmp, tmp_size) == false)
+ {
+ // Failure
+ Free(tmp);
+ return false;
+ }
+
+ // Copy to the ANSI string
+ UniToStr(str, size, tmp);
+ Free(tmp);
+
+ return true;
+}
+
+// Get the value of the unicode_string type
+bool CfgGetUniStr(FOLDER *f, char *name, wchar_t *str, UINT size)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return false;
+ }
+ if (t->Type != ITEM_TYPE_STRING)
+ {
+ return false;
+ }
+ UniStrCpy(str, size, t->Buf);
+ return true;
+}
+
+// Check for the existence of a folder
+bool CfgIsFolder(FOLDER *f, char *name)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ return (CfgGetFolder(f, name) == NULL) ? false : true;
+}
+
+// Check for the existence of item
+bool CfgIsItem(FOLDER *f, char *name)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the byte[] type as a BUF
+BUF *CfgGetBuf(FOLDER *f, char *name)
+{
+ ITEM *t;
+ BUF *b;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, t->Buf, t->size);
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Get the value of type byte[]
+UINT CfgGetByte(FOLDER *f, char *name, void *buf, UINT size)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || buf == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_BYTE)
+ {
+ return 0;
+ }
+ if (t->size <= size)
+ {
+ Copy(buf, t->Buf, t->size);
+ return t->size;
+ }
+ else
+ {
+ Copy(buf, t->Buf, size);
+ return t->size;
+ }
+}
+
+// Get the value of type int64
+UINT64 CfgGetInt64(FOLDER *f, char *name)
+{
+ ITEM *t;
+ UINT64 *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_INT64)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(UINT64))
+ {
+ return 0;
+ }
+
+ ret = (UINT64 *)t->Buf;
+ return *ret;
+}
+
+// Get the value of the bool type
+bool CfgGetBool(FOLDER *f, char *name)
+{
+ ITEM *t;
+ bool *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_BOOL)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(bool))
+ {
+ return 0;
+ }
+
+ ret = (bool *)t->Buf;
+ if (*ret == false)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Get the value of the int type
+UINT CfgGetInt(FOLDER *f, char *name)
+{
+ ITEM *t;
+ UINT *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_INT)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(UINT))
+ {
+ return 0;
+ }
+
+ ret = (UINT *)t->Buf;
+ return *ret;
+}
+
+// Search for an item
+ITEM *CfgFindItem(FOLDER *parent, char *name)
+{
+ ITEM *t, tt;
+ // Validate arguments
+ if (parent == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ tt.Name = ZeroMalloc(StrLen(name) + 1);
+ StrCpy(tt.Name, 0, name);
+ t = Search(parent->Items, &tt);
+ Free(tt.Name);
+
+ return t;
+}
+
+// Get a folder
+FOLDER *CfgGetFolder(FOLDER *parent, char *name)
+{
+ return CfgFindFolder(parent, name);
+}
+
+// Search a folder
+FOLDER *CfgFindFolder(FOLDER *parent, char *name)
+{
+ FOLDER *f, ff;
+ // Validate arguments
+ if (parent == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ ff.Name = ZeroMalloc(StrLen(name) + 1);
+ StrCpy(ff.Name, 0, name);
+ f = Search(parent->Folders, &ff);
+ Free(ff.Name);
+
+ return f;
+}
+
+// Adding a string type
+ITEM *CfgAddStr(FOLDER *f, char *name, char *str)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert to a Unicode string
+ tmp_size = CalcStrToUni(str);
+ if (tmp_size == 0)
+ {
+ return NULL;
+ }
+ tmp = Malloc(tmp_size);
+ StrToUni(tmp, tmp_size, str);
+ t = CfgAddUniStr(f, name, tmp);
+ Free(tmp);
+
+ return t;
+}
+
+// Add unicode_string type
+ITEM *CfgAddUniStr(FOLDER *f, char *name, wchar_t *str)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ return CfgCreateItem(f, name, ITEM_TYPE_STRING, str, UniStrSize(str));
+}
+
+// Add a binary
+ITEM *CfgAddBuf(FOLDER *f, char *name, BUF *b)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || b == NULL)
+ {
+ return NULL;
+ }
+ return CfgAddByte(f, name, b->Buf, b->Size);
+}
+
+// Add byte type
+ITEM *CfgAddByte(FOLDER *f, char *name, void *buf, UINT size)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || buf == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_BYTE, buf, size);
+}
+
+// Add a 64-bit integer type
+ITEM *CfgAddInt64(FOLDER *f, char *name, UINT64 i)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_INT64, &i, sizeof(UINT64));
+}
+
+// Get an IP address type
+bool CfgGetIp(FOLDER *f, char *name, struct IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || name == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ if (CfgGetStr(f, name, tmp, sizeof(tmp)) == false)
+ {
+ return false;
+ }
+
+ if (StrToIP(ip, tmp) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+UINT CfgGetIp32(FOLDER *f, char *name)
+{
+ IP p;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ if (CfgGetIp(f, name, &p) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&p);
+}
+bool CfgGetIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ Zero(addr, sizeof(IPV6_ADDR));
+ if (f == NULL || name == NULL || addr == NULL)
+ {
+ return false;
+ }
+
+ if (CfgGetIp(f, name, &ip) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(&ip) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(addr, &ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Add an IP address type
+ITEM *CfgAddIp(FOLDER *f, char *name, struct IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || name == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ IPToStr(tmp, sizeof(tmp), ip);
+
+ return CfgAddStr(f, name, tmp);
+}
+ITEM *CfgAddIp32(FOLDER *f, char *name, UINT ip)
+{
+ IP p;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ UINTToIP(&p, ip);
+
+ return CfgAddIp(f, name, &p);
+}
+ITEM *CfgAddIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ if (f == NULL || name == NULL || addr == NULL)
+ {
+ return NULL;
+ }
+
+ IPv6AddrToIP(&ip, addr);
+
+ return CfgAddIp(f, name, &ip);
+}
+
+// Add an integer type
+ITEM *CfgAddInt(FOLDER *f, char *name, UINT i)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_INT, &i, sizeof(UINT));
+}
+
+// Adding a bool type
+ITEM *CfgAddBool(FOLDER *f, char *name, bool b)
+{
+ bool v;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ v = b ? 1 : 0;
+ return CfgCreateItem(f, name, ITEM_TYPE_BOOL, &b, sizeof(bool));
+}
+
+// Comparison function of the item names
+int CmpItemName(void *p1, void *p2)
+{
+ ITEM *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(ITEM **)p1;
+ f2 = *(ITEM **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(f1->Name, f2->Name);
+}
+
+// Comparison function of the folder names
+int CmpFolderName(void *p1, void *p2)
+{
+ FOLDER *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(FOLDER **)p1;
+ f2 = *(FOLDER **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(f1->Name, f2->Name);
+}
+
+// Enumeration of items
+void CfgEnumItem(FOLDER *f, ENUM_ITEM proc, void *param)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL || proc == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->Items);i++)
+ {
+ ITEM *tt = LIST_DATA(f->Items, i);
+ if (proc(tt, param) == false)
+ {
+ break;
+ }
+ }
+}
+
+// Enumerate the folders and store it in the token list
+TOKEN_LIST *CfgEnumFolderToTokenList(FOLDER *f)
+{
+ TOKEN_LIST *t, *ret;
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(f->Folders);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Folders, i);
+ t->Token[i] = CopyStr(ff->Name);
+ }
+
+ ret = UniqueToken(t);
+ FreeToken(t);
+
+ return ret;
+}
+
+// Enumerate items and store these to the token list
+TOKEN_LIST *CfgEnumItemToTokenList(FOLDER *f)
+{
+ TOKEN_LIST *t, *ret;
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(f->Items);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Items, i);
+ t->Token[i] = CopyStr(ff->Name);
+ }
+
+ ret = UniqueToken(t);
+ FreeToken(t);
+
+ return ret;
+}
+
+// Folder enumeration
+void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL || proc == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->Folders);i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Folders, i);
+ if (proc(ff, param) == false)
+ {
+ break;
+ }
+
+ if ((i % 100) == 99)
+ {
+ YieldCpu();
+ }
+ }
+}
+
+// Create an item
+ITEM *CfgCreateItem(FOLDER *parent, char *name, UINT type, void *buf, UINT size)
+{
+ UINT name_size;
+ ITEM *t;
+#ifdef CHECK_CFG_NAME_EXISTS
+ ITEM tt;
+#endif // CHECK_CFG_NAME_EXISTS
+ // Validate arguments
+ if (parent == NULL || name == NULL || type == 0 || buf == NULL)
+ {
+ return NULL;
+ }
+
+ name_size = StrLen(name) + 1;
+
+#ifdef CHECK_CFG_NAME_EXISTS
+
+ // Check whether there are any items with the same name already
+ tt.Name = ZeroMalloc(name_size);
+ StrCpy(tt.Name, 0, name);
+ t = Search(parent->Items, &tt);
+ Free(tt.Name);
+ if (t != NULL)
+ {
+ // Duplicated
+ return NULL;
+ }
+
+#endif // CHECK_CFG_NAME_EXISTS
+
+ t = ZeroMalloc(sizeof(ITEM));
+ t->Buf = Malloc(size);
+ Copy(t->Buf, buf, size);
+ t->Name = ZeroMalloc(name_size);
+ StrCpy(t->Name, 0, name);
+ t->Type = type;
+ t->size = size;
+ t->Parent = parent;
+
+ // Add to the parent list
+ Insert(parent->Items, t);
+
+ return t;
+}
+
+// Delete the item
+void CfgDeleteItem(ITEM *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Remove from the parent list
+ Delete(t->Parent->Items, t);
+
+ // Memory release
+ Free(t->Buf);
+ Free(t->Name);
+ Free(t);
+}
+
+
+// Delete the folder
+void CfgDeleteFolder(FOLDER *f)
+{
+ FOLDER **ff;
+ ITEM **tt;
+ UINT num, i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ // Remove all subfolders
+ num = LIST_NUM(f->Folders);
+ ff = Malloc(sizeof(FOLDER *) * num);
+ Copy(ff, f->Folders->p, sizeof(FOLDER *) * num);
+ for (i = 0;i < num;i++)
+ {
+ CfgDeleteFolder(ff[i]);
+ }
+ Free(ff);
+
+ // Remove all items
+ num = LIST_NUM(f->Items);
+ tt = Malloc(sizeof(ITEM *) * num);
+ Copy(tt, f->Items->p, sizeof(ITEM *) * num);
+ for (i = 0;i < num;i++)
+ {
+ CfgDeleteItem(tt[i]);
+ }
+ Free(tt);
+
+ // Memory release
+ Free(f->Name);
+ // Remove from the parent list
+ if (f->Parent != NULL)
+ {
+ Delete(f->Parent->Folders, f);
+ }
+ // Release the list
+ ReleaseList(f->Folders);
+ ReleaseList(f->Items);
+
+ // Release of the memory of the body
+ Free(f);
+}
+
+// Creating a root
+FOLDER *CfgCreateRoot()
+{
+ return CfgCreateFolder(NULL, TAG_ROOT);
+}
+
+// Create a folder
+FOLDER *CfgCreateFolder(FOLDER *parent, char *name)
+{
+ UINT size;
+ FOLDER *f;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ size = StrLen(name) + 1;
+
+#ifdef CHECK_CFG_NAME_EXISTS
+
+ // Check the name in the parent list
+ if (parent != NULL)
+ {
+ FOLDER ff;
+ ff.Name = ZeroMalloc(size);
+ StrCpy(ff.Name, 0, name);
+ f = Search(parent->Folders, &ff);
+ Free(ff.Name);
+ if (f != NULL)
+ {
+ // Folder with the same name already exists
+ return NULL;
+ }
+ }
+
+#endif // CHECK_CFG_NAME_EXISTS
+
+ f = ZeroMalloc(sizeof(FOLDER));
+ f->Items = NewListFast(CmpItemName);
+ f->Folders = NewListFast(CmpFolderName);
+ f->Name = ZeroMalloc(size);
+ StrCpy(f->Name, 0, name);
+ f->Parent = parent;
+
+ // Add to parentlist
+ if (f->Parent != NULL)
+ {
+ Insert(f->Parent->Folders, f);
+ }
+ return f;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Cfg.h b/src/Mayaqua/Cfg.h
new file mode 100644
index 00000000..da403ebc
--- /dev/null
+++ b/src/Mayaqua/Cfg.h
@@ -0,0 +1,249 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cfg.h
+// Header of Cfg.c
+
+#ifndef CFG_H
+#define CFG_H
+
+// Macro
+//#define CHECK_CFG_NAME_EXISTS // Check duplication of the existing name
+
+#define SAVE_BINARY_FILE_NAME_SWITCH L"@save_binary"
+
+// Constants
+#define TAG_DECLARE "declare"
+#define TAG_STRING "string"
+#define TAG_INT "uint"
+#define TAG_INT64 "uint64"
+#define TAG_BOOL "bool"
+#define TAG_BYTE "byte"
+#define TAG_TRUE "true"
+#define TAG_FALSE "false"
+#define TAG_END "end"
+#define TAG_ROOT "root"
+
+#define TAG_CPYRIGHT "\xef\xbb\xbf# Software Configuration File\r\n# \r\n# You can edit this file when the program is not working.\r\n# \r\n"
+#define TAG_BINARY "SEVPN_DB"
+
+// Data type
+#define ITEM_TYPE_INT 1 // int
+#define ITEM_TYPE_INT64 2 // int64
+#define ITEM_TYPE_BYTE 3 // byte
+#define ITEM_TYPE_STRING 4 // string
+#define ITEM_TYPE_BOOL 5 // bool
+
+// Folder
+struct FOLDER
+{
+ char *Name; // Folder name
+ LIST *Items; // List of items
+ LIST *Folders; // Subfolder
+ struct FOLDER *Parent; // Parent Folder
+};
+
+// Item
+struct ITEM
+{
+ char *Name; // Item Name
+ UINT Type; // Data type
+ void *Buf; // Data
+ UINT size; // Data size
+ FOLDER *Parent; // Parent Folder
+};
+
+// Configuration file reader and writer
+struct CFG_RW
+{
+ LOCK *lock; // Lock
+ char *FileName; // File name (ANSI)
+ wchar_t *FileNameW; // File name (Unicode)
+ IO *Io; // IO
+ UCHAR LashHash[SHA1_SIZE]; // Hash value which is written last
+ bool DontBackup; // Do not use the backup
+ wchar_t LastSavedDateStr[MAX_SIZE]; // Date and time string that last saved
+};
+
+typedef bool (*ENUM_FOLDER)(FOLDER *f, void *param);
+typedef bool (*ENUM_ITEM)(ITEM *t, void *param);
+
+// Parameters for the enumeration
+struct CFG_ENUM_PARAM
+{
+ BUF *b;
+ FOLDER *f;
+ UINT depth;
+};
+
+int CmpItemName(void *p1, void *p2);
+int CmpFolderName(void *p1, void *p2);
+ITEM *CfgCreateItem(FOLDER *parent, char *name, UINT type, void *buf, UINT size);
+void CfgDeleteFolder(FOLDER *f);
+FOLDER *CfgCreateFolder(FOLDER *parent, char *name);
+void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param);
+TOKEN_LIST *CfgEnumFolderToTokenList(FOLDER *f);
+TOKEN_LIST *CfgEnumItemToTokenList(FOLDER *f);
+void CfgEnumItem(FOLDER *f, ENUM_ITEM proc, void *param);
+FOLDER *CfgFindFolder(FOLDER *parent, char *name);
+ITEM *CfgFindItem(FOLDER *parent, char *name);
+ITEM *CfgAddInt(FOLDER *f, char *name, UINT i);
+ITEM *CfgAddBool(FOLDER *f, char *name, bool b);
+ITEM *CfgAddInt64(FOLDER *f, char *name, UINT64 i);
+ITEM *CfgAddByte(FOLDER *f, char *name, void *buf, UINT size);
+ITEM *CfgAddBuf(FOLDER *f, char *name, BUF *b);
+ITEM *CfgAddStr(FOLDER *f, char *name, char *str);
+ITEM *CfgAddUniStr(FOLDER *f, char *name, wchar_t *str);
+FOLDER *CfgGetFolder(FOLDER *parent, char *name);
+UINT CfgGetInt(FOLDER *f, char *name);
+bool CfgGetBool(FOLDER *f, char *name);
+UINT64 CfgGetInt64(FOLDER *f, char *name);
+UINT CfgGetByte(FOLDER *f, char *name, void *buf, UINT size);
+BUF *CfgGetBuf(FOLDER *f, char *name);
+bool CfgGetStr(FOLDER *f, char *name, char *str, UINT size);
+bool CfgGetUniStr(FOLDER *f, char *name, wchar_t *str, UINT size);
+bool CfgIsItem(FOLDER *f, char *name);
+bool CfgIsFolder(FOLDER *f, char *name);
+void CfgTest();
+void CfgTest2(FOLDER *f, UINT n);
+char *CfgEscape(char *name);
+bool CfgCheckCharForName(char c);
+char *CfgUnescape(char *str);
+BUF *CfgFolderToBuf(FOLDER *f, bool textmode);
+BUF *CfgFolderToBufEx(FOLDER *f, bool textmode, bool no_banner);
+BUF *CfgFolderToBufText(FOLDER *f);
+BUF *CfgFolderToBufTextEx(FOLDER *f, bool no_banner);
+BUF *CfgFolderToBufBin(FOLDER *f);
+void CfgOutputFolderText(BUF *b, FOLDER *f, UINT depth);
+void CfgOutputFolderBin(BUF *b, FOLDER *f);
+void CfgAddLine(BUF *b, char *str, UINT depth);
+void CfgAddDeclare(BUF *b, char *name, UINT depth);
+void CfgAddEnd(BUF *b, UINT depth);
+void CfgAddData(BUF *b, UINT type, char *name, char *data, char *sub, UINT depth);
+UINT CfgStrToType(char *str);
+char *CfgTypeToStr(UINT type);
+void CfgAddItemText(BUF *b, ITEM *t, UINT depth);
+bool CfgEnumFolderProc(FOLDER *f, void *param);
+bool CfgEnumItemProc(ITEM *t, void *param);
+FOLDER *CfgBufTextToFolder(BUF *b);
+FOLDER *CfgBufBinToFolder(BUF *b);
+void CfgReadNextFolderBin(BUF *b, FOLDER *parent);
+char *CfgReadNextLine(BUF *b);
+bool CfgReadNextTextBuf(BUF *b, FOLDER *current);
+void CfgSave(FOLDER *f, char *name);
+void CfgSaveW(FOLDER *f, wchar_t *name);
+bool CfgSaveEx(CFG_RW *rw, FOLDER *f, char *name);
+bool CfgSaveExW(CFG_RW *rw, FOLDER *f, wchar_t *name);
+bool CfgSaveExW2(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size);
+bool CfgSaveExW3(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size, bool write_binary);
+FOLDER *CfgRead(char *name);
+FOLDER *CfgReadW(wchar_t *name);
+FOLDER *CfgCreateRoot();
+void CfgTest();
+void CfgTest2(FOLDER *f, UINT n);
+CFG_RW *NewCfgRw(FOLDER **root, char *cfg_name);
+CFG_RW *NewCfgRwW(FOLDER **root, wchar_t *cfg_name);
+CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup);
+CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup);
+UINT SaveCfgRw(CFG_RW *rw, FOLDER *f);
+UINT SaveCfgRwEx(CFG_RW *rw, FOLDER *f, UINT revision_number);
+void FreeCfgRw(CFG_RW *rw);
+ITEM *CfgAddIp32(FOLDER *f, char *name, UINT ip);
+UINT CfgGetIp32(FOLDER *f, char *name);
+bool CfgGetIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr);
+ITEM *CfgAddIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr);
+bool FileCopy(char *src, char *dst);
+bool FileCopyW(wchar_t *src, wchar_t *dst);
+bool FileCopyExW(wchar_t *src, wchar_t *dst, bool read_lock);
+void BackupCfgWEx(CFG_RW *rw, FOLDER *f, wchar_t *original, UINT revision_number);
+
+#if (!defined(CFG_C)) || (!defined(OS_UNIX))
+bool CfgGetIp(FOLDER *f, char *name, struct IP *ip);
+ITEM *CfgAddIp(FOLDER *f, char *name, struct IP *ip);
+#endif
+
+#endif // CFG_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Encrypt.c b/src/Mayaqua/Encrypt.c
new file mode 100644
index 00000000..5c6e32e5
--- /dev/null
+++ b/src/Mayaqua/Encrypt.c
@@ -0,0 +1,4691 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Encrypt.c
+// Encryption and digital certification routine
+
+#include <GlobalConst.h>
+
+#define ENCRYPT_C
+
+#define __WINCRYPT_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/md4.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/des.h>
+#include <openssl/aes.h>
+#include <openssl/dh.h>
+#include <openssl/pem.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+#include <intelaes/iaesni.h>
+#endif // USE_INTEL_AESNI_LIBRARY
+
+LOCK *openssl_lock = NULL;
+
+LOCK **ssl_lock_obj = NULL;
+UINT ssl_lock_num;
+static bool openssl_inited = false;
+static bool is_intel_aes_supported = false;
+
+// For the callback function
+typedef struct CB_PARAM
+{
+ char *password;
+} CB_PARAM;
+
+// Copied from t1_enc.c of OpenSSL
+#define HMAC_Init_ex(ctx,sec,len,md,impl) HMAC_Init(ctx, sec, len, md)
+#define HMAC_CTX_cleanup(ctx) HMAC_cleanup(ctx)
+void Enc_tls1_P_hash(const EVP_MD *md, const unsigned char *sec, int sec_len,
+ const unsigned char *seed, int seed_len, unsigned char *out, int olen)
+{
+ int chunk,n;
+ unsigned int j;
+ HMAC_CTX ctx;
+ HMAC_CTX ctx_tmp;
+ unsigned char A1[EVP_MAX_MD_SIZE];
+ unsigned int A1_len;
+
+ chunk=EVP_MD_size(md);
+
+ Zero(&ctx, sizeof(ctx));
+ Zero(&ctx_tmp, sizeof(ctx_tmp));
+ HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);
+ HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);
+ HMAC_Update(&ctx,seed,seed_len);
+ HMAC_Final(&ctx,A1,&A1_len);
+
+ n=0;
+ for (;;)
+ {
+ HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */
+ HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */
+ HMAC_Update(&ctx,A1,A1_len);
+ HMAC_Update(&ctx_tmp,A1,A1_len);
+ HMAC_Update(&ctx,seed,seed_len);
+
+ if (olen > chunk)
+ {
+ HMAC_Final(&ctx,out,&j);
+ out+=j;
+ olen-=j;
+ HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */
+ }
+ else /* last one */
+ {
+ HMAC_Final(&ctx,A1,&A1_len);
+ memcpy(out,A1,olen);
+ break;
+ }
+ }
+ HMAC_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&ctx_tmp);
+ Zero (A1, sizeof(A1));
+}
+
+void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
+ int slen, unsigned char *out1, int olen)
+{
+ const EVP_MD *md5 = EVP_md5();
+ const EVP_MD *sha1 = EVP_sha1();
+ int len,i;
+ const unsigned char *S1,*S2;
+ unsigned char *out2;
+
+ out2 = (unsigned char *) Malloc (olen);
+
+ len=slen/2;
+ S1=sec;
+ S2= &(sec[len]);
+ len+=(slen&1); /* add for odd, make longer */
+
+
+ Enc_tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);
+ Enc_tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);
+
+ for (i=0; i<olen; i++)
+ out1[i]^=out2[i];
+
+ memset (out2, 0, olen);
+ Free(out2);
+}
+
+// Calculation of HMAC (MD5)
+void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR k[HMAC_BLOCK_SIZE];
+ UCHAR hash1[MD5_SIZE];
+ UCHAR data2[HMAC_BLOCK_SIZE];
+ MD5_CTX md5_ctx1;
+ UCHAR pad1[HMAC_BLOCK_SIZE];
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ // Creating a K
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = 0 ^ 0x36;
+ }
+ }
+ else
+ {
+ Zero(k, sizeof(k));
+ Hash(k, key, key_size, false);
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = k[i] ^ 0x36;
+ }
+ }
+
+ MD5_Init(&md5_ctx1);
+ MD5_Update(&md5_ctx1, pad1, sizeof(pad1));
+ MD5_Update(&md5_ctx1, data, data_size);
+ MD5_Final(hash1, &md5_ctx1);
+
+ // Generation of data 2
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = 0 ^ 0x5c;
+ }
+ }
+ else
+ {
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = k[i] ^ 0x5c;
+ }
+ }
+
+ MD5_Init(&md5_ctx1);
+ MD5_Update(&md5_ctx1, data2, HMAC_BLOCK_SIZE);
+ MD5_Update(&md5_ctx1, hash1, MD5_SIZE);
+ MD5_Final(dst, &md5_ctx1);
+}
+
+// Calculation of HMAC (SHA-1)
+void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR k[HMAC_BLOCK_SIZE];
+ UCHAR hash1[SHA1_SIZE];
+ UCHAR data2[HMAC_BLOCK_SIZE];
+ SHA_CTX sha_ctx1;
+ UCHAR pad1[HMAC_BLOCK_SIZE];
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ // Creating a K
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = 0 ^ 0x36;
+ }
+ }
+ else
+ {
+ Zero(k, sizeof(k));
+ HashSha1(k, key, key_size);
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = k[i] ^ 0x36;
+ }
+ }
+
+ SHA1_Init(&sha_ctx1);
+ SHA1_Update(&sha_ctx1, pad1, sizeof(pad1));
+ SHA1_Update(&sha_ctx1, data, data_size);
+ SHA1_Final(hash1, &sha_ctx1);
+
+ // Generation of data 2
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = 0 ^ 0x5c;
+ }
+ }
+ else
+ {
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = k[i] ^ 0x5c;
+ }
+ }
+
+ SHA1_Init(&sha_ctx1);
+ SHA1_Update(&sha_ctx1, data2, HMAC_BLOCK_SIZE);
+ SHA1_Update(&sha_ctx1, hash1, SHA1_SIZE);
+ SHA1_Final(dst, &sha_ctx1);
+}
+
+// Calculate the HMAC
+void MdProcess(MD *md, void *dest, void *src, UINT size)
+{
+ int r;
+ // Validate arguments
+ if (md == NULL || dest == NULL || (src != NULL && size == 0))
+ {
+ return;
+ }
+
+ HMAC_Init(md->Ctx, NULL, 0, NULL);
+ HMAC_Update(md->Ctx, src, size);
+
+ r = 0;
+ HMAC_Final(md->Ctx, dest, &r);
+}
+
+// Set the key to the message digest object
+void SetMdKey(MD *md, void *key, UINT key_size)
+{
+ // Validate arguments
+ if (md == NULL || (key != NULL && key_size == 0))
+ {
+ return;
+ }
+
+ HMAC_Init(md->Ctx, key, key_size, md->Md);
+}
+
+// Creating a message digest object
+MD *NewMd(char *name)
+{
+ MD *m;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ m = ZeroMalloc(sizeof(MD));
+
+ StrCpy(m->Name, sizeof(m->Name), name);
+ m->Md = EVP_get_digestbyname(name);
+ if (m->Md == NULL)
+ {
+ FreeMd(m);
+ return NULL;
+ }
+
+ m->Ctx = ZeroMalloc(sizeof(struct hmac_ctx_st));
+ HMAC_CTX_init(m->Ctx);
+
+ m->Size = EVP_MD_size(m->Md);
+
+ return m;
+}
+
+// Release of the message digest object
+void FreeMd(MD *md)
+{
+ // Validate arguments
+ if (md == NULL)
+ {
+ return;
+ }
+
+ if (md->Ctx != NULL)
+ {
+ HMAC_CTX_cleanup(md->Ctx);
+ Free(md->Ctx);
+ }
+
+ Free(md);
+}
+
+// Creating a cipher object
+CIPHER *NewCipher(char *name)
+{
+ CIPHER *c;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CIPHER));
+
+ StrCpy(c->Name, sizeof(c->Name), name);
+
+ if (StrCmpi(name, "[null-cipher]") == 0 ||
+ StrCmpi(name, "NULL") == 0 ||
+ IsEmptyStr(name))
+ {
+ c->IsNullCipher = true;
+ return c;
+ }
+
+ c->Cipher = EVP_get_cipherbyname(c->Name);
+ if (c->Cipher == NULL)
+ {
+ FreeCipher(c);
+ return NULL;
+ }
+
+ c->Ctx = ZeroMalloc(sizeof(struct evp_cipher_ctx_st));
+ EVP_CIPHER_CTX_init(c->Ctx);
+
+ c->BlockSize = EVP_CIPHER_block_size(c->Cipher);
+ c->KeySize = EVP_CIPHER_key_length(c->Cipher);
+ c->IvSize = EVP_CIPHER_iv_length(c->Cipher);
+
+ return c;
+}
+
+// Set the key to the cipher object
+void SetCipherKey(CIPHER *c, void *key, bool enc)
+{
+ // Validate arguments
+ if (c == NULL || key == NULL)
+ {
+ return;
+ }
+
+ if (c->IsNullCipher == false)
+ {
+ if (c->Ctx != NULL)
+ {
+ EVP_CipherInit(c->Ctx, c->Cipher, key, NULL, enc);
+ }
+ }
+
+ c->Encrypt = enc;
+}
+
+// Process encryption / decryption
+UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size)
+{
+ int r = size;
+ int r2 = 0;
+ if (c != NULL && c->IsNullCipher)
+ {
+ if (dest != src)
+ {
+ Copy(dest, src, size);
+ }
+ return size;
+ }
+ // Validate arguments
+ if (c == NULL || iv == NULL || dest == NULL || src == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherInit(c->Ctx, NULL, NULL, iv, c->Encrypt) == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherUpdate(c->Ctx, dest, &r, src, size) == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherFinal(c->Ctx, ((UCHAR *)dest) + (UINT)r, &r2) == 0)
+ {
+ return 0;
+ }
+
+ return r + r2;
+}
+
+// Release of the cipher object
+void FreeCipher(CIPHER *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->Ctx != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(c->Ctx);
+ Free(c->Ctx);
+ }
+
+ Free(c);
+}
+
+// Verify whether the certificate is disabled by CRL in a particular directory
+bool IsXRevoked(X *x)
+{
+ char dirname[MAX_PATH];
+ UINT i;
+ bool ret = false;
+ DIRLIST *t;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ GetExeDir(dirname, sizeof(dirname));
+
+ // Search the CRL file
+ t = EnumDir(dirname);
+
+ for (i = 0;i < t->NumFiles;i++)
+ {
+ char *name = t->File[i]->FileName;
+ if (t->File[i]->Folder == false)
+ {
+ if (EndWith(name, ".crl"))
+ {
+ char filename[MAX_PATH];
+ X_CRL *r;
+
+ ConbinePath(filename, sizeof(filename), dirname, name);
+
+ r = FileToXCrl(filename);
+
+ if (r != NULL)
+ {
+ if (IsXRevokedByXCrl(x, r))
+ {
+ ret = true;
+ }
+
+ FreeXCrl(r);
+ }
+ }
+ }
+ }
+
+ FreeDir(t);
+
+ return ret;
+}
+
+// Verify whether the certificate is disabled by the CRL
+bool IsXRevokedByXCrl(X *x, X_CRL *r)
+{
+#ifdef OS_WIN32
+ X509_REVOKED tmp;
+ X509_CRL_INFO *info;
+ int index;
+ // Validate arguments
+ if (x == NULL || r == NULL)
+ {
+ return false;
+ }
+
+ Zero(&tmp, sizeof(tmp));
+ tmp.serialNumber = X509_get_serialNumber(x->x509);
+
+ info = r->Crl->crl;
+
+ if (sk_X509_REVOKED_is_sorted(info->revoked) == false)
+ {
+ sk_X509_REVOKED_sort(info->revoked);
+ }
+
+ index = sk_X509_REVOKED_find(info->revoked, &tmp);
+
+ if (index < 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// Release of the CRL
+void FreeXCrl(X_CRL *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ X509_CRL_free(r->Crl);
+
+ Free(r);
+}
+
+// Convert a file to a CRL
+X_CRL *FileToXCrl(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ X_CRL *ret = FileToXCrlW(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+X_CRL *FileToXCrlW(wchar_t *filename)
+{
+ BUF *b;
+ X_CRL *r;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ r = BufToXCrl(b);
+
+ FreeBuf(b);
+
+ return r;
+}
+
+// Convert the buffer to the CRL
+X_CRL *BufToXCrl(BUF *b)
+{
+ X_CRL *r;
+ X509_CRL *x509crl;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ x509crl = NULL;
+
+ if (d2i_X509_CRL_bio(bio, &x509crl) == NULL || x509crl == NULL)
+ {
+ FreeBio(bio);
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(X_CRL));
+ r->Crl = x509crl;
+
+ FreeBio(bio);
+
+ return r;
+}
+
+// Convert the buffer to the public key
+K *RsaBinToPublic(void *data, UINT size)
+{
+ RSA *rsa;
+ K *k;
+ BIO *bio;
+ // Validate arguments
+ if (data == NULL || size < 4)
+ {
+ return NULL;
+ }
+
+ rsa = RSA_new();
+
+ if (rsa->e != NULL)
+ {
+ BN_free(rsa->e);
+ }
+
+ rsa->e = BN_new();
+ BN_set_word(rsa->e, RSA_F4);
+
+ if (rsa->n != NULL)
+ {
+ BN_free(rsa->n);
+ }
+
+ rsa->n = BinToBigNum(data, size);
+
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ k = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ RSA_free(rsa);
+
+ return k;
+}
+
+// Convert the public key to a buffer
+BUF *RsaPublicToBuf(K *k)
+{
+ BUF *b;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL)
+ {
+ return NULL;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ return b;
+}
+
+// Convert the public key to a binary
+void RsaPublicToBin(K *k, void *data)
+{
+ BUF *b;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL || data == NULL)
+ {
+ return;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Copy(data, b->Buf, b->Size);
+
+ FreeBuf(b);
+}
+
+// Get public key size
+UINT RsaPublicSize(K *k)
+{
+ BUF *b;
+ UINT ret;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL)
+ {
+ return 0;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ ret = b->Size;
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Stupid test
+void CertTest2()
+{
+}
+
+// Yagi test
+void CertTest()
+{
+}
+
+// Test function related to certificate
+void CertTest_()
+{
+}
+
+// Hash a pointer to a 32-bit
+UINT HashPtrToUINT(void *p)
+{
+ UCHAR hash_data[MD5_SIZE];
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ Hash(hash_data, &p, sizeof(p), false);
+
+ Copy(&ret, hash_data, sizeof(ret));
+
+ return ret;
+}
+
+// Copy of the NAME
+NAME *CopyName(NAME *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return NULL;
+ }
+
+ return NewName(n->CommonName, n->Organization, n->Unit,
+ n->Country, n->State, n->Local);
+}
+
+// Convert a BIGNUM to a string
+char *BigNumToStr(BIGNUM *bn)
+{
+ BIO *bio;
+ BUF *b;
+ char *ret;
+ // Validate arguments
+ if (bn == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ BN_print(bio, bn);
+
+ b = BioToBuf(bio);
+
+ FreeBio(bio);
+
+ ret = ZeroMalloc(b->Size + 1);
+ Copy(ret, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert the binary to the BIGNUM
+BIGNUM *BinToBigNum(void *data, UINT size)
+{
+ BIGNUM *bn;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ bn = BN_new();
+ BN_bin2bn(data, size, bn);
+
+ return bn;
+}
+
+// Convert the buffer to a BIGNUM
+BIGNUM *BufToBigNum(BUF *b)
+{
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ return BinToBigNum(b->Buf, b->Size);
+}
+
+// Convert a BIGNUM to a buffer
+BUF *BigNumToBuf(BIGNUM *bn)
+{
+ UINT size;
+ UCHAR *tmp;
+ BUF *b;
+ // Validate arguments
+ if (bn == NULL)
+ {
+ return NULL;
+ }
+
+ size = BN_num_bytes(bn);
+ tmp = ZeroMalloc(size);
+ BN_bn2bin(bn, tmp);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Initialization of the lock of OpenSSL
+void OpenSSL_InitLock()
+{
+ UINT i;
+
+ // Initialization of the lock object
+ ssl_lock_num = CRYPTO_num_locks();
+ ssl_lock_obj = Malloc(sizeof(LOCK *) * ssl_lock_num);
+ for (i = 0;i < ssl_lock_num;i++)
+ {
+ ssl_lock_obj[i] = NewLock();
+ }
+
+ // Setting the lock function
+ CRYPTO_set_locking_callback(OpenSSL_Lock);
+ CRYPTO_set_id_callback(OpenSSL_Id);
+}
+
+// Release of the lock of OpenSSL
+void OpenSSL_FreeLock()
+{
+ UINT i;
+
+ for (i = 0;i < ssl_lock_num;i++)
+ {
+ DeleteLock(ssl_lock_obj[i]);
+ }
+ Free(ssl_lock_obj);
+ ssl_lock_obj = NULL;
+
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_id_callback(NULL);
+}
+
+// Lock function for OpenSSL
+void OpenSSL_Lock(int mode, int n, const char *file, int line)
+{
+ LOCK *lock = ssl_lock_obj[n];
+
+ if (mode & CRYPTO_LOCK)
+ {
+ // Lock
+ Lock(lock);
+ }
+ else
+ {
+ // Unlock
+ Unlock(lock);
+ }
+}
+
+// Return the thread ID
+unsigned long OpenSSL_Id(void)
+{
+ return (unsigned long)ThreadId();
+}
+
+// Get the display name of the certificate
+void GetPrintNameFromX(wchar_t *str, UINT size, X *x)
+{
+ // Validate arguments
+ if (x == NULL || str == NULL)
+ {
+ return;
+ }
+
+ GetPrintNameFromName(str, size, x->subject_name);
+}
+void GetPrintNameFromXA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetPrintNameFromX(tmp, sizeof(tmp), x);
+
+ UniToStr(str, size, tmp);
+}
+void GetAllNameFromXEx(wchar_t *str, UINT size, X *x)
+{
+ // Validate arguments
+ if (x == NULL || str == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromNameEx(str, size, x->subject_name);
+}
+void GetAllNameFromXExA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromXEx(tmp, sizeof(tmp), x);
+
+ UniToStr(str, size, tmp);
+}
+
+// Get the display name from NAME
+void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ if (name->CommonName != NULL)
+ {
+ UniStrCpy(str, size, name->CommonName);
+ }
+ else if (name->Organization != NULL)
+ {
+ UniStrCpy(str, size, name->Organization);
+ }
+ else if (name->Unit != NULL)
+ {
+ UniStrCpy(str, size, name->Unit);
+ }
+ else if (name->State != NULL)
+ {
+ UniStrCpy(str, size, name->State);
+ }
+ else if (name->Local != NULL)
+ {
+ UniStrCpy(str, size, name->Local);
+ }
+ else if (name->Country != NULL)
+ {
+ UniStrCpy(str, size, name->Country);
+ }
+ else
+ {
+ UniStrCpy(str, size, L"untitled");
+ }
+}
+
+// Get all the name strings from the certificate
+void GetAllNameFromX(wchar_t *str, UINT size, X *x)
+{
+ UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];
+ char tmp1[MD5_SIZE * 3 + 8], tmp2[SHA1_SIZE * 3 + 8];
+ wchar_t tmp3[sizeof(tmp1) + sizeof(tmp2) + 64];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromName(str, size, x->subject_name);
+
+ if (x->serial != NULL && x->serial->size >= 1)
+ {
+ char tmp[128];
+ wchar_t tmp2[128];
+
+ BinToStr(tmp, sizeof(tmp), x->serial->data, x->serial->size);
+ UniFormat(tmp2, sizeof(tmp2), L", SERIAL=\"%S\"", tmp);
+
+ UniStrCat(str, size, tmp2);
+ }
+
+ // Digest value
+ GetXDigest(x, md5, false);
+ GetXDigest(x, sha1, true);
+
+ BinToStr(tmp1, sizeof(tmp1), md5, MD5_SIZE);
+ BinToStr(tmp2, sizeof(tmp2), sha1, SHA1_SIZE);
+
+ UniFormat(tmp3, sizeof(tmp3), L" (Digest: MD5=\"%S\", SHA1=\"%S\")", tmp1, tmp2);
+ UniStrCat(str, size, tmp3);
+}
+void GetAllNameFromA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromX(tmp, sizeof(tmp), x);
+ UniToStr(str, size, tmp);
+}
+
+// Get the all name strings from NAME
+void GetAllNameFromName(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(str, size, L"");
+ if (name->CommonName != NULL)
+ {
+ UniFormat(str, size, L"%sCN=%s, ", str, name->CommonName);
+ }
+ if (name->Organization != NULL)
+ {
+ UniFormat(str, size, L"%sO=%s, ", str, name->Organization);
+ }
+ if (name->Unit != NULL)
+ {
+ UniFormat(str, size, L"%sOU=%s, ", str, name->Unit);
+ }
+ if (name->State != NULL)
+ {
+ UniFormat(str, size, L"%sS=%s, ", str, name->State);
+ }
+ if (name->Local != NULL)
+ {
+ UniFormat(str, size, L"%sL=%s, ", str, name->Local);
+ }
+ if (name->Country != NULL)
+ {
+ UniFormat(str, size, L"%sC=%s, ", str, name->Country);
+ }
+
+ if (UniStrLen(str) >= 3)
+ {
+ UINT len = UniStrLen(str);
+ if (str[len - 2] == L',' &&
+ str[len - 1] == L' ')
+ {
+ str[len - 2] = 0;
+ }
+ }
+}
+void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(str, size, L"");
+ if (name->CommonName != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->CommonName);
+ }
+ if (name->Organization != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Organization);
+ }
+ if (name->Unit != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Unit);
+ }
+ if (name->State != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->State);
+ }
+ if (name->Local != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Local);
+ }
+ if (name->Country != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Country);
+ }
+
+ if (UniStrLen(str) >= 3)
+ {
+ UINT len = UniStrLen(str);
+ if (str[len - 2] == L',' &&
+ str[len - 1] == L' ')
+ {
+ str[len - 2] = 0;
+ }
+ }
+}
+
+// Clone of the key
+K *CloneK(K *k)
+{
+ BUF *b;
+ K *ret;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ b = KToBuf(k, false, NULL);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ ret = BufToK(b, k->private_key, false, NULL);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Clone of certificate
+X *CloneX(X *x)
+{
+ BUF *b;
+ X *ret;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ ret = BufToX(b, false);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Generate a P12
+P12 *NewP12(X *x, K *k, char *password)
+{
+ PKCS12 *pkcs12;
+ P12 *p12;
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+ if (password && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ pkcs12 = PKCS12_create(password, NULL, k->pkey, x->x509, NULL, 0, 0, 0, 0, 0);
+ if (pkcs12 == NULL)
+ {
+ Unlock(openssl_lock);
+ return NULL;
+ }
+ }
+ Unlock(openssl_lock);
+
+ p12 = PKCS12ToP12(pkcs12);
+
+ return p12;
+}
+
+// Check whether the P12 is encrypted
+bool IsEncryptedP12(P12 *p12)
+{
+ X *x;
+ K *k;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return false;
+ }
+
+ if (ParseP12(p12, &x, &k, NULL) == true)
+ {
+ FreeX(x);
+ FreeK(k);
+ return false;
+ }
+
+ return true;
+}
+
+// Extract the X and the K from the P12
+bool ParseP12(P12 *p12, X **x, K **k, char *password)
+{
+ EVP_PKEY *pkey;
+ X509 *x509;
+ // Validate arguments
+ if (p12 == NULL || x == NULL || k == NULL)
+ {
+ return false;
+ }
+ if (password && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ // Password confirmation
+ Lock(openssl_lock);
+ {
+ if (PKCS12_verify_mac(p12->pkcs12, password, -1) == false &&
+ PKCS12_verify_mac(p12->pkcs12, NULL, -1) == false)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ Unlock(openssl_lock);
+
+ // Extraction
+ Lock(openssl_lock);
+ {
+ if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, NULL) == false)
+ {
+ if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, NULL) == false)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ }
+ Unlock(openssl_lock);
+
+ // Conversion
+ *x = X509ToX(x509);
+
+ if (*x == NULL)
+ {
+ FreePKey(pkey);
+ return false;
+ }
+
+ *k = ZeroMalloc(sizeof(K));
+ (*k)->private_key = true;
+ (*k)->pkey = pkey;
+
+ return true;
+}
+
+// Write the P12 to a file
+bool P12ToFile(P12 *p12, char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = P12ToFileW(p12, filename_w);
+
+ return ret;
+}
+bool P12ToFileW(P12 *p12, wchar_t *filename)
+{
+ BUF *b;
+ // Validate arguments
+ if (p12 == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = P12ToBuf(p12);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, filename) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Read a P12 from the file
+P12 *FileToP12(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ P12 *ret = FileToP12W(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+P12 *FileToP12W(wchar_t *filename)
+{
+ BUF *b;
+ P12 *p12;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = BufToP12(b);
+ FreeBuf(b);
+
+ return p12;
+}
+
+// Release of P12
+void FreeP12(P12 *p12)
+{
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return;
+ }
+
+ FreePKCS12(p12->pkcs12);
+ Free(p12);
+}
+
+// Release of PKCS12
+void FreePKCS12(PKCS12 *pkcs12)
+{
+ // Validate arguments
+ if (pkcs12 == NULL)
+ {
+ return;
+ }
+
+ PKCS12_free(pkcs12);
+}
+
+// Converted the P12 to a BUF
+BUF *P12ToBuf(P12 *p12)
+{
+ BIO *bio;
+ BUF *buf;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return NULL;
+ }
+
+ bio = P12ToBio(p12);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ buf = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Converted the P12 to a BIO
+BIO *P12ToBio(P12 *p12)
+{
+ BIO *bio;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_PKCS12_bio(bio, p12->pkcs12);
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// Read the P12 from the BUF
+P12 *BufToP12(BUF *b)
+{
+ P12 *p12;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = BioToP12(bio);
+ FreeBio(bio);
+
+ return p12;
+}
+
+// Read the P12 from the BIO
+P12 *BioToP12(BIO *bio)
+{
+ PKCS12 *pkcs12;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ // Conversion
+ Lock(openssl_lock);
+ {
+ pkcs12 = d2i_PKCS12_bio(bio, NULL);
+ }
+ Unlock(openssl_lock);
+ if (pkcs12 == NULL)
+ {
+ // Failure
+ return NULL;
+ }
+
+ return PKCS12ToP12(pkcs12);
+}
+
+// Generate a P12 from a PKCS12
+P12 *PKCS12ToP12(PKCS12 *pkcs12)
+{
+ P12 *p12;
+ // Validate arguments
+ if (pkcs12 == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = ZeroMalloc(sizeof(P12));
+ p12->pkcs12 = pkcs12;
+
+ return p12;
+}
+
+// Convert a binary to a string
+char *ByteToStr(BYTE *src, UINT src_size)
+{
+ UINT size;
+ char *dst;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(src_size * 3, 1);
+ dst = Malloc(size);
+ dst[size - 1] = 0;
+ for (i = 0;i < src_size;i++)
+ {
+ char tmp[3];
+ Format(tmp, sizeof(tmp), "%02x", src[i]);
+ dst[i * 3 + 0] = tmp[0];
+ dst[i * 3 + 1] = tmp[1];
+ dst[i * 3 + 2] = ((i == (src_size - 1) ? 0 : ' '));
+ }
+
+ return dst;
+}
+
+// Release of X_SERIAL
+void FreeXSerial(X_SERIAL *serial)
+{
+ // Validate arguments
+ if (serial == NULL)
+ {
+ return;
+ }
+
+ Free(serial->data);
+ Free(serial);
+}
+
+// Comparison of X_SERIAL
+bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2)
+{
+ // Validate arguments
+ if (s1 == NULL || s2 == NULL)
+ {
+ return false;
+ }
+
+ if (s1->size != s2->size)
+ {
+ return false;
+ }
+
+ if (Cmp(s1->data, s2->data, s1->size) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Copy of X_SERIAL
+X_SERIAL *CloneXSerial(X_SERIAL *src)
+{
+ X_SERIAL *s;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(X_SERIAL));
+ s->data = ZeroMalloc(src->size);
+ Copy(s->data, src->data, src->size);
+ s->size = src->size;
+
+ return s;
+}
+
+// Initialization of X_SERIAL
+X_SERIAL *NewXSerial(void *data, UINT size)
+{
+ X_SERIAL *serial;
+ UCHAR *buf = (UCHAR *)data;
+ UINT i;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ if (buf[i] != 0)
+ {
+ break;
+ }
+ }
+ if (i == size)
+ {
+ i = size - 1;
+ }
+ buf += i;
+
+ serial = Malloc(sizeof(X_SERIAL));
+ serial->size = size - i;
+ serial->data = ZeroMalloc(size + 16);
+ Copy(serial->data, buf, size - i);
+
+ return serial;
+}
+
+// Get the number of days till January 1, 2038
+UINT GetDaysUntil2038()
+{
+ UINT64 now = SystemTime64();
+ UINT64 target;
+ SYSTEMTIME st;
+
+ Zero(&st, sizeof(st));
+ st.wYear = 2038;
+ st.wMonth = 1;
+ st.wDay = 1;
+
+ target = SystemToUINT64(&st);
+
+ if (now >= target)
+ {
+ return 0;
+ }
+ else
+ {
+ return (UINT)((target - now) / (UINT64)(1000 * 60 * 60 * 24));
+ }
+}
+
+// Issue an X509 certificate
+X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ X *x;
+ // Validate arguments
+ if (pub == NULL || priv == NULL || name == NULL || ca == NULL)
+ {
+ return NULL;
+ }
+
+ x509 = NewX509(pub, priv, ca, name, days, serial);
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ return x;
+}
+
+// Create a root certificate
+X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ X *x, *x2;
+ // Validate arguments
+ if (pub == NULL || priv == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ x509 = NewRootX509(pub, priv, name, days, serial);
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ x2 = CloneX(x);
+ FreeX(x);
+
+ return x2;
+}
+
+// Issue an X509 certificate
+X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ UINT64 notBefore, notAfter;
+ ASN1_TIME *t1, *t2;
+ X509_NAME *subject_name, *issuer_name;
+ // Validate arguments
+ if (pub == NULL || name == NULL || ca == NULL)
+ {
+ return NULL;
+ }
+ if (pub->private_key != false)
+ {
+ return NULL;
+ }
+ if (priv->private_key == false)
+ {
+ return NULL;
+ }
+
+ notBefore = SystemTime64();
+ notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
+
+
+ // Creating a X509
+ x509 = X509_new();
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ // Set the Expiration
+ t1 = X509_get_notBefore(x509);
+ t2 = X509_get_notAfter(x509);
+ if (!UINT64ToAsn1Time(t1, notBefore))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ if (!UINT64ToAsn1Time(t2, notAfter))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+
+ // Set the name
+ subject_name = NameToX509Name(name);
+ if (subject_name == NULL)
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ issuer_name = X509_get_subject_name(ca->x509);
+ if (issuer_name == NULL)
+ {
+ FreeX509Name(subject_name);
+ FreeX509(x509);
+ return NULL;
+ }
+
+ X509_set_issuer_name(x509, issuer_name);
+ X509_set_subject_name(x509, subject_name);
+
+ FreeX509Name(subject_name);
+
+ // Set the Serial Number
+ if (serial == NULL)
+ {
+ char zero = 0;
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(sizeof(char));
+ Copy(s->data, &zero, sizeof(char));
+ s->length = sizeof(char);
+ }
+ else
+ {
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(serial->size);
+ Copy(s->data, serial->data, serial->size);
+ s->length = serial->size;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Set the public key
+ X509_set_pubkey(x509, pub->pkey);
+
+ // Signature
+ X509_sign(x509, priv->pkey, EVP_sha1());
+ }
+ Unlock(openssl_lock);
+
+ return x509;
+}
+
+// Create an X509 root certificate
+X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ UINT64 notBefore, notAfter;
+ ASN1_TIME *t1, *t2;
+ X509_NAME *subject_name, *issuer_name;
+ // Validate arguments
+ if (pub == NULL || name == NULL || priv == NULL)
+ {
+ return NULL;
+ }
+ if (days == 0)
+ {
+ days = 365;
+ }
+ if (priv->private_key == false)
+ {
+ return NULL;
+ }
+ if (pub->private_key != false)
+ {
+ return NULL;
+ }
+
+ notBefore = SystemTime64();
+ notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
+
+ // Creating a X509
+ x509 = X509_new();
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ // Set the Expiration
+ t1 = X509_get_notBefore(x509);
+ t2 = X509_get_notAfter(x509);
+ if (!UINT64ToAsn1Time(t1, notBefore))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ if (!UINT64ToAsn1Time(t2, notAfter))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+
+ // Set the name
+ subject_name = NameToX509Name(name);
+ if (subject_name == NULL)
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ issuer_name = NameToX509Name(name);
+ if (issuer_name == NULL)
+ {
+ FreeX509Name(subject_name);
+ FreeX509(x509);
+ return NULL;
+ }
+
+ X509_set_issuer_name(x509, issuer_name);
+ X509_set_subject_name(x509, subject_name);
+
+ FreeX509Name(subject_name);
+ FreeX509Name(issuer_name);
+
+ // Set a Serial Number
+ if (serial == NULL)
+ {
+ char zero = 0;
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(sizeof(char));
+ Copy(s->data, &zero, sizeof(char));
+ s->length = sizeof(char);
+ }
+ else
+ {
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(serial->size);
+ Copy(s->data, serial->data, serial->size);
+ s->length = serial->size;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Set the public key
+ X509_set_pubkey(x509, pub->pkey);
+
+ // Signature
+ X509_sign(x509, priv->pkey, EVP_sha1());
+ }
+ Unlock(openssl_lock);
+
+ return x509;
+}
+
+// Convert the NAMEto a X509_NAME
+void *NameToX509Name(NAME *nm)
+{
+ X509_NAME *xn;
+ // Validate arguments
+ if (nm == NULL)
+ {
+ return NULL;
+ }
+
+ xn = X509_NAME_new();
+ if (xn == NULL)
+ {
+ return NULL;
+ }
+
+ // Add the entries
+ AddX509Name(xn, NID_commonName, nm->CommonName);
+ AddX509Name(xn, NID_organizationName, nm->Organization);
+ AddX509Name(xn, NID_organizationalUnitName, nm->Unit);
+ AddX509Name(xn, NID_countryName, nm->Country);
+ AddX509Name(xn, NID_stateOrProvinceName, nm->State);
+ AddX509Name(xn, NID_localityName, nm->Local);
+
+ return xn;
+}
+
+// Add an entry to the X509_NAME
+bool AddX509Name(void *xn, int nid, wchar_t *str)
+{
+ X509_NAME *x509_name;
+ UINT utf8_size;
+ BYTE *utf8;
+ // Validate arguments
+ if (xn == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // Convert to UTF-8
+ utf8_size = CalcUniToUtf8(str);
+ if (utf8_size == 0)
+ {
+ return false;
+ }
+ utf8 = ZeroMalloc(utf8_size + 1);
+ UniToUtf8(utf8, utf8_size, str);
+ utf8[utf8_size] = 0;
+
+ // Adding
+ x509_name = (X509_NAME *)xn;
+ Lock(openssl_lock);
+ {
+ X509_NAME_add_entry_by_NID(x509_name, nid, MBSTRING_ASC, utf8, utf8_size, -1, 0);
+ }
+ Unlock(openssl_lock);
+ Free(utf8);
+
+ return true;
+}
+
+// Release the X509_NAME
+void FreeX509Name(void *xn)
+{
+ X509_NAME *x509_name;
+ // Validate arguments
+ if (xn == NULL)
+ {
+ return;
+ }
+
+ x509_name = (X509_NAME *)xn;
+ X509_NAME_free(x509_name);
+}
+
+// Creating the NAME
+NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,
+ wchar_t *country, wchar_t *state, wchar_t *local)
+{
+ NAME *nm = ZeroMalloc(sizeof(NAME));
+
+ if (UniIsEmptyStr(common_name) == false)
+ {
+ nm->CommonName = CopyUniStr(common_name);
+ }
+
+ if (UniIsEmptyStr(organization) == false)
+ {
+ nm->Organization = CopyUniStr(organization);
+ }
+
+ if (UniIsEmptyStr(unit) == false)
+ {
+ nm->Unit = CopyUniStr(unit);
+ }
+
+ if (UniIsEmptyStr(country) == false)
+ {
+ nm->Country = CopyUniStr(country);
+ }
+
+ if (UniIsEmptyStr(state) == false)
+ {
+ nm->State = CopyUniStr(state);
+ }
+
+ if (UniIsEmptyStr(local) == false)
+ {
+ nm->Local = CopyUniStr(local);
+ }
+
+ return nm;
+}
+
+// Check the expiration date of the certificate by the current time
+bool CheckXDateNow(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ return CheckXDate(x, SystemTime64());
+}
+
+// Check the expiration date of the certificate
+bool CheckXDate(X *x, UINT64 current_system_time)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ if (x->notBefore >= current_system_time || x->notAfter <= current_system_time)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Read the expiration date of the certificate
+void LoadXDates(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ x->notBefore = Asn1TimeToUINT64(x->x509->cert_info->validity->notBefore);
+ x->notAfter = Asn1TimeToUINT64(x->x509->cert_info->validity->notAfter);
+}
+
+// Convert the 64bit system time to ASN1 time
+bool UINT64ToAsn1Time(void *asn1_time, UINT64 t)
+{
+ SYSTEMTIME st;
+ // Validate arguments
+ if (asn1_time == NULL)
+ {
+ return false;
+ }
+
+ UINT64ToSystem(&st, t);
+ return SystemToAsn1Time(asn1_time, &st);
+}
+
+// Convert the system time to the ASN1 time
+bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s)
+{
+ char tmp[20];
+ ASN1_TIME *t;
+ // Validate arguments
+ if (asn1_time == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (SystemToStr(tmp, sizeof(tmp), s) == false)
+ {
+ return false;
+ }
+ t = (ASN1_TIME *)asn1_time;
+ if (t->data == NULL || t->length < sizeof(tmp))
+ {
+ t->data = OPENSSL_malloc(sizeof(tmp));
+ }
+ StrCpy((char *)t->data, t->length, tmp);
+ t->length = StrLen(tmp);
+ t->type = V_ASN1_UTCTIME;
+
+ return true;
+}
+
+// Convert the system time to a string
+bool SystemToStr(char *str, UINT size, SYSTEMTIME *s)
+{
+ // Validate arguments
+ if (str == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Format(str, size, "%02u%02u%02u%02u%02u%02uZ",
+ s->wYear % 100, s->wMonth, s->wDay,
+ s->wHour, s->wMinute, s->wSecond);
+
+ return true;
+}
+
+// Convert an ASN1 time to an UINT64 time
+UINT64 Asn1TimeToUINT64(void *asn1_time)
+{
+ SYSTEMTIME st;
+ // Validate arguments
+ if (asn1_time == NULL)
+ {
+ return 0;
+ }
+
+ if (Asn1TimeToSystem(&st, asn1_time) == false)
+ {
+ return 0;
+ }
+ return SystemToUINT64(&st);
+}
+
+// Converted an ASN1 time to a system time
+bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time)
+{
+ ASN1_TIME *t;
+ // Validate arguments
+ if (s == NULL || asn1_time == NULL)
+ {
+ return false;
+ }
+
+ t = (ASN1_TIME *)asn1_time;
+ if (StrToSystem(s, (char *)t->data) == false)
+ {
+ return false;
+ }
+
+ if (t->type == V_ASN1_GENERALIZEDTIME)
+ {
+ LocalToSystem(s, s);
+ }
+
+ return true;
+}
+
+// Convert the string to the system time
+bool StrToSystem(SYSTEMTIME *s, char *str)
+{
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return false;
+ }
+ if (StrLen(str) != 13)
+ {
+ return false;
+ }
+ if (str[12] != 'Z')
+ {
+ return false;
+ }
+
+ // Conversion
+ {
+ char year[3] = {str[0], str[1], 0},
+ month[3] = {str[2], str[3], 0},
+ day[3] = {str[4], str[5], 0},
+ hour[3] = {str[6], str[7], 0},
+ minute[3] = {str[8], str[9], 0},
+ second[3] = {str[10], str[11], 0};
+ Zero(s, sizeof(SYSTEMTIME));
+ s->wYear = ToInt(year);
+ if (s->wYear >= 60)
+ {
+ s->wYear += 1900;
+ }
+ else
+ {
+ s->wYear += 2000;
+ }
+ s->wMonth = ToInt(month);
+ s->wDay = ToInt(day);
+ s->wHour = ToInt(hour);
+ s->wMinute = ToInt(minute);
+ s->wSecond = ToInt(second);
+ NormalizeSystem(s);
+ }
+
+ return true;
+}
+
+// Verify the RSA signature
+bool RsaVerify(void *data, UINT data_size, void *sign, K *k)
+{
+ return RsaVerifyEx(data, data_size, sign, k, 0);
+}
+bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits)
+{
+ UCHAR hash_data[SIGN_HASH_SIZE];
+ UCHAR decrypt_data[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (data == NULL || sign == NULL || k == NULL || k->private_key != false)
+ {
+ return false;
+ }
+ if (bits == 0)
+ {
+ bits = 1024;
+ }
+
+ // Hash the data
+ if (HashForSign(hash_data, sizeof(hash_data), data, data_size) == false)
+ {
+ return false;
+ }
+
+ // Decode the signature
+ if (RSA_public_decrypt(bits / 8, sign, decrypt_data, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
+ {
+ return false;
+ }
+
+ // Comparison
+ if (Cmp(decrypt_data, hash_data, SIGN_HASH_SIZE) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// RSA signature
+bool RsaSign(void *dst, void *src, UINT size, K *k)
+{
+ return RsaSignEx(dst, src, size, k, 0);
+}
+bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits)
+{
+ UCHAR hash[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (dst == NULL || src == NULL || k == NULL || k->pkey->type != EVP_PKEY_RSA)
+ {
+ return false;
+ }
+ if (bits == 0)
+ {
+ bits = 1024;
+ }
+
+ Zero(dst, bits / 8);
+
+ // Hash
+ if (HashForSign(hash, sizeof(hash), src, size) == false)
+ {
+ return false;
+ }
+
+ // Signature
+ if (RSA_private_encrypt(sizeof(hash), hash, dst, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Generation of signature data by SHA-1
+bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ UCHAR *buf = (UCHAR *)dst;
+ UCHAR sign_data[] =
+ {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,
+ 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
+ };
+ // Validate arguments
+ if (dst == NULL || src == NULL || src_size == 0 || MIN_SIGN_HASH_SIZE > dst_size)
+ {
+ return false;
+ }
+
+ // Header part
+ Copy(buf, sign_data, sizeof(sign_data));
+
+ // Hash
+ HashSha1(HASHED_DATA(buf), src, src_size);
+
+ return true;
+}
+
+// Decrypt with the RSA public key
+bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_public_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+/* Debug("RSA Error: 0x%x\n",
+ ERR_get_error());
+*/ Free(tmp);
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Encrypt with the RSA private key
+bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_private_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+/* Debug("RSA Error: %u\n",
+ ERR_GET_REASON(ERR_get_error()));
+*/ Free(tmp);
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Decrypt with the RSA private key
+bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_private_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Encrypt with the RSA public key
+bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_public_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// RSA operating environment check
+bool RsaCheckEx()
+{
+ UINT num = 20;
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ if (RsaCheck())
+ {
+ return true;
+ }
+
+ SleepThread(100);
+ }
+
+ return false;
+}
+bool RsaCheck()
+{
+ RSA *rsa;
+ K *priv_key, *pub_key;
+ BIO *bio;
+ char errbuf[MAX_SIZE];
+ UINT size = 0;
+ UINT bit = 32;
+ // Validate arguments
+
+ // Key generation
+ Lock(openssl_lock);
+ {
+ rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ if (rsa == NULL)
+ {
+ Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
+ return false;
+ }
+
+ // Secret key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSAPrivateKey_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ priv_key = BioToK(bio, true, false, NULL);
+ FreeBio(bio);
+
+ // Public key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ pub_key = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ RSA_free(rsa);
+
+ size = RsaPublicSize(pub_key);
+
+ if (size != ((bit + 7) / 8))
+ {
+ FreeK(priv_key);
+ FreeK(pub_key);
+
+ return false;
+ }
+
+ FreeK(priv_key);
+ FreeK(pub_key);
+
+ return true;
+}
+
+// Generation of RSA key
+bool RsaGen(K **priv, K **pub, UINT bit)
+{
+ RSA *rsa;
+ K *priv_key, *pub_key;
+ BIO *bio;
+ char errbuf[MAX_SIZE];
+ UINT size = 0;
+ // Validate arguments
+ if (priv == NULL || pub == NULL)
+ {
+ return false;
+ }
+ if (bit == 0)
+ {
+ bit = 1024;
+ }
+
+ // Key generation
+ Lock(openssl_lock);
+ {
+ rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ if (rsa == NULL)
+ {
+ Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
+ return false;
+ }
+
+ // Secret key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSAPrivateKey_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ priv_key = BioToK(bio, true, false, NULL);
+ FreeBio(bio);
+
+ // Public key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ pub_key = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ *priv = priv_key;
+ *pub = pub_key;
+
+ RSA_free(rsa);
+
+ size = RsaPublicSize(*pub);
+
+ if (size != ((bit + 7) / 8))
+ {
+ FreeK(*priv);
+ FreeK(*pub);
+
+ return RsaGen(priv, pub, bit);
+ }
+
+ return true;
+}
+
+// Confirm whether the certificate X is signed by the issuer of the certificate x_issuer
+bool CheckX(X *x, X *x_issuer)
+{
+ K *k;
+ bool ret;
+ // Validate arguments
+ if (x == NULL || x_issuer == NULL)
+ {
+ return false;
+ }
+
+ k = GetKFromX(x_issuer);
+ if (k == NULL)
+ {
+ return false;
+ }
+
+ ret = CheckSignature(x, k);
+ FreeK(k);
+
+ return ret;
+}
+
+// Confirm the signature of the certificate X with the public key K
+bool CheckSignature(X *x, K *k)
+{
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ {
+ if (X509_verify(x->x509, k->pkey) == 0)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ Unlock(openssl_lock);
+ return true;
+}
+
+// Get the public key from the certificate
+K *GetKFromX(X *x)
+{
+ EVP_PKEY *pkey;
+ K *k;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ pkey = X509_get_pubkey(x->x509);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(K));
+ k->pkey = pkey;
+
+ return k;
+}
+
+// The name comparison
+bool CompareName(NAME *n1, NAME *n2)
+{
+ // Validate arguments
+ if (n1 == NULL || n2 == NULL)
+ {
+ return false;
+ }
+
+ // Name comparison
+ if (UniStrCmpi(n1->CommonName, n2->CommonName) == 0 &&
+ UniStrCmpi(n1->Organization, n2->Organization) == 0 &&
+ UniStrCmpi(n1->Unit, n2->Unit) == 0 &&
+ UniStrCmpi(n1->Country, n2->Country) == 0 &&
+ UniStrCmpi(n1->State, n2->State) == 0 &&
+ UniStrCmpi(n1->Local, n2->Local) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Release the name of the X
+void FreeXNames(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ FreeName(x->issuer_name);
+ x->issuer_name = NULL;
+
+ FreeName(x->subject_name);
+ x->subject_name = NULL;
+}
+
+// Release the name
+void FreeName(NAME *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Release the string
+ Free(n->CommonName);
+ Free(n->Organization);
+ Free(n->Unit);
+ Free(n->Country);
+ Free(n->State);
+ Free(n->Local);
+
+ // Release the object
+ Free(n);
+
+ return;
+}
+
+// Get the name of the certificate
+void LoadXNames(X *x)
+{
+ X509 *x509;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ x509 = x->x509;
+ x->issuer_name = X509NameToName(X509_get_issuer_name(x509));
+ x->subject_name = X509NameToName(X509_get_subject_name(x509));
+}
+
+// Convert the X509_NAME structure to the NAME structure
+NAME *X509NameToName(void *xn)
+{
+ NAME *n;
+ // Validate arguments
+ if (xn == NULL)
+ {
+ return NULL;
+ }
+
+ n = ZeroMalloc(sizeof(NAME));
+
+ // Get the strings one by one
+ n->CommonName = GetUniStrFromX509Name(xn, NID_commonName);
+ n->Organization = GetUniStrFromX509Name(xn, NID_organizationName);
+ n->Unit = GetUniStrFromX509Name(xn, NID_organizationalUnitName);
+ n->Country = GetUniStrFromX509Name(xn, NID_countryName);
+ n->State = GetUniStrFromX509Name(xn, NID_stateOrProvinceName);
+ n->Local = GetUniStrFromX509Name(xn, NID_localityName);
+
+ return n;
+}
+
+// Read a Unicode string from the X509_NAME structure
+wchar_t *GetUniStrFromX509Name(void *xn, int nid)
+{
+ UCHAR txt[1024];
+ bool b = false;
+ UINT i, size;
+ int index;
+ bool unicode = false;
+ bool is_utf_8 = false;
+ ASN1_OBJECT *obj;
+ ASN1_STRING *data;
+ // Validate arguments
+ if (xn == NULL || nid == 0)
+ {
+ return NULL;
+ }
+
+ Zero(txt, sizeof(txt));
+ if (X509_NAME_get_text_by_NID(xn, nid, (char *)txt, sizeof(txt) - 2) <= 0)
+ {
+ return NULL;
+ }
+
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ return NULL;
+ }
+ index = X509_NAME_get_index_by_OBJ(xn, obj, -1);
+ if (index < 0)
+ {
+ return NULL;
+ }
+ data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(xn, index));
+ if (data == NULL)
+ {
+ return NULL;
+ }
+ if (data->type == V_ASN1_BMPSTRING)
+ {
+ unicode = true;
+ }
+ if (data->type == V_ASN1_UTF8STRING || data->type == V_ASN1_T61STRING)
+ {
+ is_utf_8 = true;
+ }
+
+ size = UniStrLen((wchar_t *)txt) * 4 + 8;
+ for (i = 0;i < size;i++)
+ {
+ if (txt[i] >= 0x80)
+ {
+ unicode = true;
+ break;
+ }
+ }
+
+ if (is_utf_8)
+ {
+ wchar_t *ret;
+ UINT ret_size;
+
+ ret_size = CalcUtf8ToUni(txt, StrLen(txt));
+ ret = ZeroMalloc(ret_size + 8);
+ Utf8ToUni(ret, ret_size, txt, StrLen(txt));
+
+ return ret;
+ }
+ else if (unicode == false)
+ {
+ wchar_t tmp[1024];
+ StrToUni(tmp, sizeof(tmp), (char *)txt);
+ return CopyUniStr(tmp);
+ }
+ else
+ {
+ EndianUnicode((wchar_t *)txt);
+ return CopyUniStr((wchar_t *)txt);
+ }
+}
+
+// Check whether the certificate x1 equal to x2
+bool CompareX(X *x1, X *x2)
+{
+ // Validate arguments
+ if (x1 == NULL || x2 == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ if (X509_cmp(x1->x509, x2->x509) == 0)
+ {
+ Unlock(openssl_lock);
+ return true;
+ }
+ else
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+}
+
+// Check whether K is private key of X
+bool CheckXandK(X *x, K *k)
+{
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ if (X509_check_private_key(x->x509, k->pkey) != 0)
+ {
+ Unlock(openssl_lock);
+ return true;
+ }
+ else
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+}
+
+// Read a X from the file
+X *FileToX(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ X *ret = FileToXW(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+X *FileToXW(wchar_t *filename)
+{
+ bool text;
+ BUF *b;
+ X *x;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ text = IsBase64(b);
+
+ x = BufToX(b, text);
+ FreeBuf(b);
+
+ return x;
+}
+
+// Write the X to a file
+bool XToFile(X *x, char *filename, bool text)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = XToFileW(x, filename_w, text);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool XToFileW(X *x, wchar_t *filename, bool text)
+{
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (x == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = XToBuf(x, text);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = DumpBufW(b, filename);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read a K from the file
+K *FileToK(char *filename, bool private_key, char *password)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ K *ret;
+
+ ret = FileToKW(filename_w, private_key, password);
+
+ Free(filename_w);
+
+ return ret;
+}
+K *FileToKW(wchar_t *filename, bool private_key, char *password)
+{
+ bool text;
+ BUF *b;
+ K *k;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ text = IsBase64(b);
+ if (text == false)
+ {
+ k = BufToK(b, private_key, false, NULL);
+ }
+ else
+ {
+ k = BufToK(b, private_key, true, NULL);
+ if (k == NULL)
+ {
+ k = BufToK(b, private_key, true, password);
+ }
+ }
+
+ FreeBuf(b);
+
+ return k;
+}
+
+// Save the K to a file
+bool KToFile(K *k, char *filename, bool text, char *password)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = KToFileW(k, filename_w, text, password);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool KToFileW(K *k, wchar_t *filename, bool text, char *password)
+{
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (k == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = KToBuf(k, text, password);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = DumpBufW(b, filename);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert the K to the BUF
+BUF *KToBuf(K *k, bool text, char *password)
+{
+ BUF *buf;
+ BIO *bio;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ bio = KToBio(k, text, password);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ buf = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Convert the K to the BIO
+BIO *KToBio(K *k, bool text, char *password)
+{
+ BIO *bio;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ if (k->private_key)
+ {
+ // Secret key
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ i2d_PrivateKey_bio(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Text format
+ if (password == 0 || StrLen(password) == 0)
+ {
+ // No encryption
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PrivateKey(bio, k->pkey, NULL, NULL, 0, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Encrypt
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PrivateKey(bio, k->pkey, EVP_des_ede3_cbc(),
+ NULL, 0, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+ }
+ else
+ {
+ // Public key
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ i2d_PUBKEY_bio(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Text format
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PUBKEY(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+
+ return bio;
+}
+
+// Check whether the BUF is encoded as the Base64
+bool IsBase64(BUF *b)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (SearchAsciiInBinary(b->Buf, b->Size, "-----BEGIN", false) != INFINITE)
+ {
+ return true;
+ }
+
+ for (i = 0;i < b->Size;i++)
+ {
+ char c = ((char *)b->Buf)[i];
+ bool b = false;
+ if ('a' <= c && c <= 'z')
+ {
+ b = true;
+ }
+ else if ('A' <= c && c <= 'Z')
+ {
+ b = true;
+ }
+ else if ('0' <= c && c <= '9')
+ {
+ b = true;
+ }
+ else if (c == ':' || c == '.' || c == ';' || c == ',')
+ {
+ b = true;
+ }
+ else if (c == '!' || c == '&' || c == '#' || c == '(' || c == ')')
+ {
+ b = true;
+ }
+ else if (c == '-' || c == ' ')
+ {
+ b = true;
+ }
+ else if (c == 13 || c == 10 || c == EOF)
+ {
+ b = true;
+ }
+ else if (c == '\t' || c == '=' || c == '+' || c == '/')
+ {
+ b = true;
+ }
+ if (b == false)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the K in the BUF is encrypted
+bool IsEncryptedK(BUF *b, bool private_key)
+{
+ K *k;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+ if (IsBase64(b) == false)
+ {
+ return false;
+ }
+
+ k = BufToK(b, private_key, true, NULL);
+ if (k != NULL)
+ {
+ FreeK(k);
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the BUF to a K
+K *BufToK(BUF *b, bool private_key, bool text, char *password)
+{
+ BIO *bio;
+ K *k;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ k = BioToK(bio, private_key, text, password);
+ FreeBio(bio);
+
+ return k;
+}
+
+// Release of K
+void FreeK(K *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ FreePKey(k->pkey);
+ Free(k);
+}
+
+// Release the secret key
+void FreePKey(EVP_PKEY *pkey)
+{
+ // Validate arguments
+ if (pkey == NULL)
+ {
+ return;
+ }
+
+ EVP_PKEY_free(pkey);
+}
+
+// Convert the BIO to the K
+K *BioToK(BIO *bio, bool private_key, bool text, char *password)
+{
+ EVP_PKEY *pkey;
+ K *k;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ if (password != NULL && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+
+ if (private_key == false)
+ {
+ // Public key
+ if (text == false)
+ {
+ // Binary format
+ pkey = d2i_PUBKEY_bio(bio, NULL);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ // Text format
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ pkey = d2i_PrivateKey_bio(bio, NULL);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ // Text format
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ k = ZeroMalloc(sizeof(K));
+ k->pkey = pkey;
+ k->private_key = private_key;
+
+ return k;
+}
+
+// Password callback function
+int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param)
+{
+ CB_PARAM *cb;
+ // Validate arguments
+ if (buf == NULL || param == NULL || bufsize == 0)
+ {
+ return 0;
+ }
+
+ cb = (CB_PARAM *)param;
+ if (cb->password == NULL)
+ {
+ return 0;
+ }
+
+ return StrCpy(buf, bufsize, cb->password);
+}
+
+// Convert the X to a BUF
+BUF *XToBuf(X *x, bool text)
+{
+ BIO *bio;
+ BUF *b;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ bio = XToBio(x, text);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ b = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert the X to a BIO
+BIO *XToBio(X *x, bool text)
+{
+ BIO *bio;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ Lock(openssl_lock);
+ {
+ if (text == false)
+ {
+ // Binary format
+ i2d_X509_bio(bio, x->x509);
+ }
+ else
+ {
+ // Text format
+ PEM_write_bio_X509(bio, x->x509);
+ }
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// Release of the X
+void FreeX(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ // Release the name
+ FreeXNames(x);
+
+
+ // Release the Serial
+ FreeXSerial(x->serial);
+
+ if (x->do_not_free == false)
+ {
+ FreeX509(x->x509);
+ }
+ Free(x);
+}
+
+// Release of the X509
+void FreeX509(X509 *x509)
+{
+ // Validate arguments
+ if (x509 == NULL)
+ {
+ return;
+ }
+
+ Lock(openssl_lock);
+ {
+ X509_free(x509);
+ }
+ Unlock(openssl_lock);
+}
+
+// Convert the BUF to a X
+X *BufToX(BUF *b, bool text)
+{
+ X *x;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+
+ x = BioToX(bio, text);
+
+ FreeBio(bio);
+
+ return x;
+}
+
+// Create a new buffer by skipping the contents of the buffer to the specified string
+BUF *SkipBufBeforeString(BUF *b, char *str)
+{
+ char *tmp;
+ UINT tmp_size;
+ BUF *ret;
+ UINT i;
+ UINT offset = 0;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = b->Size + 1;
+ tmp = ZeroMalloc(tmp_size);
+ Copy(tmp, b->Buf, b->Size);
+
+ i = SearchStrEx(tmp, str, 0, false);
+ if (i != INFINITE)
+ {
+ offset = i;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, ((UCHAR *)b->Buf) + offset, b->Size - offset);
+ SeekBuf(ret, 0, 0);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get a digest of the X
+void GetXDigest(X *x, UCHAR *buf, bool sha1)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ if (sha1 == false)
+ {
+ UINT size = MD5_SIZE;
+ X509_digest(x->x509, EVP_md5(), buf, (unsigned int *)&size);
+ }
+ else
+ {
+ UINT size = SHA1_SIZE;
+ X509_digest(x->x509, EVP_sha1(), buf, (unsigned int *)&size);
+ }
+}
+
+// Convert BIO to X
+X *BioToX(BIO *bio, bool text)
+{
+ X *x;
+ X509 *x509;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Reading x509
+ if (text == false)
+ {
+ // Binary mode
+ x509 = d2i_X509_bio(bio, NULL);
+ }
+ else
+ {
+ // Text mode
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ }
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ return x;
+}
+
+// Convert the X509 to X
+X *X509ToX(X509 *x509)
+{
+ X *x;
+ K *k;
+ BUF *b;
+ UINT size;
+ UINT type;
+ // Validate arguments
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = ZeroMalloc(sizeof(X));
+ x->x509 = x509;
+
+ // Name
+ LoadXNames(x);
+
+ // Expiration date
+ LoadXDates(x);
+
+ // Check whether it is a root certificate
+ if (CompareName(x->issuer_name, x->subject_name))
+ {
+ K *pubkey = GetKFromX(x);
+ if (pubkey != NULL)
+ {
+ if (CheckXandK(x, pubkey))
+ {
+ x->root_cert = true;
+ }
+ FreeK(pubkey);
+ }
+ }
+
+ // Get the Serial Number
+ x->serial = NewXSerial(x509->cert_info->serialNumber->data,
+ x509->cert_info->serialNumber->length);
+ if (x->serial == NULL)
+ {
+ char zero = 0;
+ x->serial = NewXSerial(&zero, sizeof(char));
+ }
+
+ k = GetKFromX(x);
+ if (k == NULL)
+ {
+ FreeX(x);
+ return NULL;
+ }
+
+ b = KToBuf(k, false, NULL);
+
+ size = b->Size;
+ type = k->pkey->type;
+
+ FreeBuf(b);
+
+ FreeK(k);
+
+ if (type == EVP_PKEY_RSA)
+ {
+ x->is_compatible_bit = true;
+
+ switch (size)
+ {
+ case 162:
+ x->bits = 1024;
+ break;
+
+ case 226:
+ x->bits = 1536;
+ break;
+
+ case 294:
+ x->bits = 2048;
+ break;
+
+ case 442:
+ x->bits = 3072;
+ break;
+
+ case 550:
+ x->bits = 4096;
+ break;
+
+ default:
+ x->is_compatible_bit = false;
+ break;
+ }
+ }
+
+ return x;
+}
+
+// Create a BIO
+BIO *NewBio()
+{
+ return BIO_new(BIO_s_mem());
+}
+
+// Release the BIO
+void FreeBio(BIO *bio)
+{
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return;
+ }
+
+ BIO_free(bio);
+}
+
+// Convert the BIO to the BUF
+BUF *BioToBuf(BIO *bio)
+{
+ BUF *b;
+ UINT size;
+ void *tmp;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ BIO_seek(bio, 0);
+ size = bio->num_write;
+ tmp = Malloc(size);
+ BIO_read(bio, tmp, size);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+
+ return b;
+}
+
+// Convert the BUF to a BIO
+BIO *BufToBio(BUF *b)
+{
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ {
+ Unlock(openssl_lock);
+ return NULL;
+ }
+ BIO_write(bio, b->Buf, b->Size);
+ BIO_seek(bio, 0);
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// 128-bit random number generation
+void Rand128(void *buf)
+{
+ Rand(buf, 16);
+}
+
+// 64-bit random number generation
+UINT64 Rand64()
+{
+ UINT64 i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 32-bit random number generation
+UINT Rand32()
+{
+ UINT i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 16-bit random number generation
+USHORT Rand16()
+{
+ USHORT i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 8-bit random number generation
+UCHAR Rand8()
+{
+ UCHAR i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 1-bit random number generation
+bool Rand1()
+{
+ return (Rand32() % 2) == 0 ? false : true;
+}
+
+// Random number generation
+void Rand(void *buf, UINT size)
+{
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+ RAND_bytes(buf, size);
+}
+
+// Delete a thread-specific information that OpenSSL has holded
+void FreeOpenSSLThreadState()
+{
+ ERR_remove_state(0);
+}
+
+// Release the Crypt library
+void FreeCryptLibrary()
+{
+ openssl_inited = false;
+
+ DeleteLock(openssl_lock);
+ openssl_lock = NULL;
+// RAND_Free_For_SoftEther();
+ OpenSSL_FreeLock();
+}
+
+// Initialize the Crypt library
+void InitCryptLibrary()
+{
+ char tmp[16];
+
+ CheckIfIntelAesNiSupportedInit();
+// RAND_Init_For_SoftEther()
+ openssl_lock = NewLock();
+ SSL_library_init();
+ //OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ SSLeay_add_all_digests();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+
+#ifdef OS_UNIX
+ {
+ char *name1 = "/dev/random";
+ char *name2 = "/dev/urandom";
+ IO *o;
+ o = FileOpen(name1, false);
+ if (o == NULL)
+ {
+ o = FileOpen(name2, false);
+ if (o == NULL)
+ {
+ UINT64 now = SystemTime64();
+ BUF *b;
+ UINT i;
+ b = NewBuf();
+ for (i = 0;i < 4096;i++)
+ {
+ UCHAR c = rand() % 256;
+ WriteBuf(b, &c, 1);
+ }
+ WriteBuf(b, &now, sizeof(now));
+ RAND_seed(b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ else
+ {
+ FileClose(o);
+ }
+ }
+ else
+ {
+ FileClose(o);
+ }
+ }
+#endif // OS_UNIX
+
+ RAND_poll();
+
+#ifdef OS_WIN32
+// RAND_screen();
+#endif
+ Rand(tmp, sizeof(tmp));
+ OpenSSL_InitLock();
+
+ openssl_inited = true;
+}
+
+// Hash function
+void Hash(void *dst, void *src, UINT size, bool sha)
+{
+ // Validate arguments
+ if (dst == NULL || (src == NULL && size != 0))
+ {
+ return;
+ }
+
+ if (sha == false)
+ {
+ // MD5 hash
+ MD5(src, size, dst);
+ }
+ else
+ {
+ // SHA hash
+ SHA(src, size, dst);
+ }
+}
+
+// MD4 specific hash function
+void HashMd4(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ MD4(src, size, dst);
+}
+
+// Hash with the SHA-1 and convert it to UINT
+UINT HashToUINT(void *data, UINT size)
+{
+ UCHAR hash[SHA1_SIZE];
+ UINT u;
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ HashSha1(hash, data, size);
+
+ Copy(&u, hash, sizeof(UINT));
+
+ u = Endian32(u);
+
+ return u;
+}
+
+// SHA-1 specific hash function
+void HashSha1(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ SHA1(src, size, dst);
+}
+
+// SHA-256 specific hash function
+void HashSha256(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ SHA256(src, size, dst);
+}
+
+// Creating a new CRYPT object
+CRYPT *NewCrypt(void *key, UINT size)
+{
+ CRYPT *c = ZeroMalloc(sizeof(CRYPT));
+
+ c->Rc4Key = ZeroMalloc(sizeof(struct rc4_key_st));
+
+ RC4_set_key(c->Rc4Key, size, (UCHAR *)key);
+
+ return c;
+}
+
+// Release the CRYPT object
+void FreeCrypt(CRYPT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(c->Rc4Key);
+ Free(c);
+}
+
+// Encryption and decryption
+void Encrypt(CRYPT *c, void *dst, void *src, UINT size)
+{
+ RC4(c->Rc4Key, size, src, dst);
+}
+
+// SHA-1 hash
+void Sha1(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ SHA1(src, size, dst);
+}
+
+// MD5 hash
+void Md5(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ MD5(src, size, dst);
+}
+
+// 3DES encryption
+void Des3Encrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || key == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ key->k1->KeySchedule,
+ key->k2->KeySchedule,
+ key->k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+void Des3Encrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k1 == NULL || k2 == NULL || k3 == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ k1->KeySchedule,
+ k2->KeySchedule,
+ k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+
+// DES encryption
+void DesEncrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_cbc_encrypt(src, dest, size,
+ k->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+
+// 3DES decryption
+void Des3Decrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || key == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ key->k1->KeySchedule,
+ key->k2->KeySchedule,
+ key->k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+void Des3Decrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k1 == NULL || k2 == NULL || k3 == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ k1->KeySchedule,
+ k2->KeySchedule,
+ k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+
+// DES-ECB encryption
+void DesEcbEncrypt(void *dst, void *src, void *key_7bytes)
+{
+ UCHAR *key_56;
+ DES_cblock key;
+ DES_key_schedule ks;
+ // Validate arguments
+ if (dst == NULL || src == NULL || key == NULL)
+ {
+ return;
+ }
+
+ key_56 = (UCHAR *)key_7bytes;
+
+ Zero(&key, sizeof(key));
+ Zero(&ks, sizeof(ks));
+
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+
+ DES_set_odd_parity(&key);
+ DES_set_key_unchecked(&key, &ks);
+
+ DES_ecb_encrypt(src, dst, &ks, 1);
+}
+
+// DES decryption
+void DesDecrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_cbc_encrypt(src, dest, size,
+ k->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+
+// Generate a random 3DES key
+DES_KEY *Des3RandKey()
+{
+ DES_KEY *k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesRandKeyValue();
+ k->k2 = DesRandKeyValue();
+ k->k3 = DesRandKeyValue();
+
+ return k;
+}
+
+// Generate a random DES key
+DES_KEY *DesRandKey()
+{
+ DES_KEY *k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesRandKeyValue();
+ k->k2 = DesNewKeyValue(k->k1->KeyValue);
+ k->k3 = DesNewKeyValue(k->k1->KeyValue);
+
+ return k;
+}
+
+// Release the 3DES key
+void Des3FreeKey(DES_KEY *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ DesFreeKeyValue(k->k1);
+ DesFreeKeyValue(k->k2);
+ DesFreeKeyValue(k->k3);
+
+ Free(k);
+}
+
+// Release the DES key
+void DesFreeKey(DES_KEY *k)
+{
+ Des3FreeKey(k);
+}
+
+// Create a 3DES key
+DES_KEY *Des3NewKey(void *k1, void *k2, void *k3)
+{
+ DES_KEY *k;
+ // Validate arguments
+ if (k1 == NULL || k2 == NULL || k3 == NULL)
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesNewKeyValue(k1);
+ k->k2 = DesNewKeyValue(k2);
+ k->k3 = DesNewKeyValue(k3);
+
+ return k;
+}
+
+// Create a DES key
+DES_KEY *DesNewKey(void *k1)
+{
+ return Des3NewKey(k1, k1, k1);
+}
+
+// Create a new DES key element
+DES_KEY_VALUE *DesNewKeyValue(void *value)
+{
+ DES_KEY_VALUE *v;
+ // Validate arguments
+ if (value == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(DES_KEY_VALUE));
+
+ Copy(v->KeyValue, value, DES_KEY_SIZE);
+
+ v->KeySchedule = ZeroMalloc(sizeof(DES_key_schedule));
+
+ DES_set_key_unchecked(value, v->KeySchedule);
+
+ return v;
+}
+
+// Random generation of new DES key element
+DES_KEY_VALUE *DesRandKeyValue()
+{
+ UCHAR key_value[DES_KEY_SIZE];
+
+ DES_random_key((DES_cblock *)key_value);
+
+ return DesNewKeyValue(key_value);
+}
+
+// Release of DES key element
+void DesFreeKeyValue(DES_KEY_VALUE *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Free(v->KeySchedule);
+ Free(v);
+}
+
+// Create a new AES key
+AES_KEY_VALUE *AesNewKey(void *data, UINT size)
+{
+ AES_KEY_VALUE *k;
+ // Validate arguments
+ if (data == NULL || (!(size == 16 || size == 24 || size == 32)))
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(AES_KEY_VALUE));
+
+ k->EncryptKey = ZeroMalloc(sizeof(struct aes_key_st));
+ k->DecryptKey = ZeroMalloc(sizeof(struct aes_key_st));
+
+ k->KeySize = size;
+ Copy(k->KeyValue, data, size);
+
+ AES_set_encrypt_key(data, size * 8, k->EncryptKey);
+ AES_set_decrypt_key(data, size * 8, k->DecryptKey);
+
+ return k;
+}
+
+// Release the AES key
+void AesFreeKey(AES_KEY_VALUE *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Free(k->EncryptKey);
+ Free(k->DecryptKey);
+
+ Free(k);
+}
+
+// AES encryption
+void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (is_intel_aes_supported)
+ {
+ AesEncryptWithIntel(dest, src, size, k, ivec);
+ return;
+ }
+#endif // USE_INTEL_AESNI_LIBRARY
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ AES_cbc_encrypt(src, dest, size, k->EncryptKey, ivec, 1);
+}
+
+// AES decryption
+void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (is_intel_aes_supported)
+ {
+ AesDecryptWithIntel(dest, src, size, k, ivec);
+ return;
+ }
+#endif // USE_INTEL_AESNI_LIBRARY
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ AES_cbc_encrypt(src, dest, size, k->DecryptKey, ivec, 0);
+}
+
+// Determine whether the Intel AES-NI is supported
+bool IsIntelAesNiSupported()
+{
+ return is_intel_aes_supported;
+}
+void CheckIfIntelAesNiSupportedInit()
+{
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (check_for_aes_instructions())
+ {
+ is_intel_aes_supported = true;
+ }
+ else
+ {
+ is_intel_aes_supported = false;
+ }
+#else // USE_INTEL_AESNI_LIBRARY
+ is_intel_aes_supported = false;
+#endif // USE_INTEL_AESNI_LIBRARY
+}
+
+// Disable the Intel AES-NI
+void DisableIntelAesAccel()
+{
+ is_intel_aes_supported = false;
+}
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+// Encrypt AES using the Intel AES-NI
+void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ switch (k->KeySize)
+ {
+ case 16:
+ intel_AES_enc128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 24:
+ intel_AES_enc192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 32:
+ intel_AES_enc256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+ }
+}
+
+// Decrypt AES using the Intel AES-NI
+void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ switch (k->KeySize)
+ {
+ case 16:
+ intel_AES_dec128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 24:
+ intel_AES_dec192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 32:
+ intel_AES_dec256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+ }
+}
+#endif // USE_INTEL_AESNI_LIBRARY
+
+// Calculation of HMAC-SHA-1-96
+void MacSha196(void *dst, void *key, void *data, UINT data_size)
+{
+ UCHAR tmp[HMAC_SHA1_SIZE];
+ // Validate arguments
+ if (dst == NULL || key == NULL || data == NULL)
+ {
+ return;
+ }
+
+ MacSha1(tmp, key, HMAC_SHA1_96_KEY_SIZE, data, data_size);
+
+ Copy(dst, tmp, HMAC_SHA1_96_HASH_SIZE);
+}
+
+// Calculation of HMAC-SHA-1
+void MacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR key_plus[SHA1_BLOCK_SIZE];
+ UCHAR key_plus2[SHA1_BLOCK_SIZE];
+ UCHAR key_plus5[SHA1_BLOCK_SIZE];
+ UCHAR hash4[SHA1_HASH_SIZE];
+ UINT i;
+ BUF *buf3;
+ BUF *buf6;
+ // Validate arguments
+ if (dst == NULL || key == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Zero(key_plus, sizeof(key_plus));
+ if (key_size <= SHA1_BLOCK_SIZE)
+ {
+ Copy(key_plus, key, key_size);
+ }
+ else
+ {
+ Sha1(key_plus, key, key_size);
+ }
+
+ for (i = 0;i < sizeof(key_plus);i++)
+ {
+ key_plus2[i] = key_plus[i] ^ 0x36;
+ }
+
+ buf3 = NewBuf();
+ WriteBuf(buf3, key_plus2, sizeof(key_plus2));
+ WriteBuf(buf3, data, data_size);
+
+ Sha1(hash4, buf3->Buf, buf3->Size);
+
+ for (i = 0;i < sizeof(key_plus);i++)
+ {
+ key_plus5[i] = key_plus[i] ^ 0x5c;
+ }
+
+ buf6 = NewBuf();
+ WriteBuf(buf6, key_plus5, sizeof(key_plus5));
+ WriteBuf(buf6, hash4, sizeof(hash4));
+
+ Sha1(dst, buf6->Buf, buf6->Size);
+
+ FreeBuf(buf3);
+ FreeBuf(buf6);
+}
+
+// DH calculation
+bool DhCompute(DH_CTX *dh, void *dst_priv_key, void *src_pub_key, UINT key_size)
+{
+ int i;
+ BIGNUM *bn;
+ bool ret = false;
+ // Validate arguments
+ if (dh == NULL || dst_priv_key == NULL || src_pub_key == NULL)
+ {
+ return false;
+ }
+ if (key_size > dh->Size)
+ {
+ return false;
+ }
+
+ bn = BinToBigNum(src_pub_key, key_size);
+
+ i = DH_compute_key(dst_priv_key, bn, dh->dh);
+
+ if (i == dh->Size)
+ {
+ ret = true;
+ }
+ else if ((UINT)i < dh->Size)
+ {
+ UCHAR *dst2 = Clone(dst_priv_key, i);
+
+ Zero(dst_priv_key, dh->Size);
+
+ Copy(((UCHAR *)dst_priv_key) + (dh->Size - i), dst2, i);
+
+ ret = true;
+ }
+
+ BN_free(bn);
+
+ return ret;
+}
+
+// Creating a DH GROUP1
+DH_CTX *DhNewGroup1()
+{
+ return DhNew(DH_GROUP1_PRIME_768, 2);
+}
+
+// Creating a DH GROUP2
+DH_CTX *DhNewGroup2()
+{
+ return DhNew(DH_GROUP2_PRIME_1024, 2);
+}
+
+// Creating a DH GROUP5
+DH_CTX *DhNewGroup5()
+{
+ return DhNew(DH_GROUP5_PRIME_1536, 2);
+}
+
+// Creating a DH SIMPLE 160bits
+DH_CTX *DhNewSimple160()
+{
+ return DhNew(DH_SIMPLE_160, 2);
+}
+
+// Convert the DH parameters to file
+BUF *DhToBuf(DH_CTX *dh)
+{
+ BIO *bio;
+ BUF *buf = NULL;
+ int r;
+ // Validate arguments
+ if (dh == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ r = i2d_DHparams_bio(bio, dh->dh);
+ if (r > 1)
+ {
+ buf = BioToBuf(bio);
+ }
+
+ FreeBio(bio);
+
+ return buf;
+}
+
+// Creating a new DH
+DH_CTX *DhNew(char *prime, UINT g)
+{
+ DH_CTX *dh;
+ BUF *buf;
+ // Validate arguments
+ if (prime == NULL || g == 0)
+ {
+ return NULL;
+ }
+
+ buf = StrToBin(prime);
+
+ dh = ZeroMalloc(sizeof(DH_CTX));
+
+ dh->dh = DH_new();
+ dh->dh->p = BinToBigNum(buf->Buf, buf->Size);
+ dh->dh->g = BN_new();
+ BN_set_word(dh->dh->g, g);
+
+ DH_generate_key(dh->dh);
+
+ dh->MyPublicKey = BigNumToBuf(dh->dh->pub_key);
+ dh->MyPrivateKey = BigNumToBuf(dh->dh->priv_key);
+
+ dh->Size = buf->Size;
+
+ FreeBuf(buf);
+
+ return dh;
+}
+
+// Release of DH
+void DhFree(DH_CTX *dh)
+{
+ // Validate arguments
+ if (dh == NULL)
+ {
+ return;
+ }
+
+ DH_free(dh->dh);
+
+ FreeBuf(dh->MyPrivateKey);
+ FreeBuf(dh->MyPublicKey);
+
+ Free(dh);
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Encrypt.h b/src/Mayaqua/Encrypt.h
new file mode 100644
index 00000000..24cb11e6
--- /dev/null
+++ b/src/Mayaqua/Encrypt.h
@@ -0,0 +1,486 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Encrypt.h
+// Header of Encrypt.c
+
+#ifndef ENCRYPT_H
+#define ENCRYPT_H
+
+// Function of OpenSSL
+void RAND_Init_For_SoftEther();
+void RAND_Free_For_SoftEther();
+
+
+
+// Constant
+#define MIN_SIGN_HASH_SIZE (15 + SHA1_SIZE)
+#define SIGN_HASH_SIZE (MIN_SIGN_HASH_SIZE)
+
+#define DES_KEY_SIZE 8 // DES key size
+#define DES_IV_SIZE 8 // DES IV size
+#define DES_BLOCK_SIZE 8 // DES block size
+#define DES3_KEY_SIZE (8 * 3) // 3DES key size
+#define RSA_KEY_SIZE 128 // RSA key size
+#define DH_KEY_SIZE 128 // DH key size
+#define RSA_MIN_SIGN_HASH_SIZE (15 + SHA1_HASH_SIZE) // Minimum RSA hash size
+#define RSA_SIGN_HASH_SIZE (RSA_MIN_SIGN_HASH_SIZE) // RSA hash size
+#define MD5_HASH_SIZE 16 // MD5 hash size
+#define SHA1_HASH_SIZE 20 // SHA-1 hash size
+#define SHA1_BLOCK_SIZE 64 // SHA-1 block size
+#define HMAC_SHA1_96_KEY_SIZE 20 // HMAC-SHA-1-96 key size
+#define HMAC_SHA1_96_HASH_SIZE 12 // HMAC-SHA-1-96 hash size
+#define HMAC_SHA1_SIZE (SHA1_HASH_SIZE) // HMAC-SHA-1 hash size
+#define AES_IV_SIZE 16 // AES IV size
+#define AES_MAX_KEY_SIZE 32 // Maximum AES key size
+
+// HMAC block size
+#define HMAC_BLOCK_SIZE 64
+
+#define DH_GROUP1_PRIME_768 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+
+#define DH_GROUP2_PRIME_1024 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+ "FFFFFFFFFFFFFFFF"
+
+#define DH_GROUP5_PRIME_1536 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
+
+#define DH_SIMPLE_160 "AEE7561459353C95DDA966AE1FD25D95CD46E935"
+
+// Macro
+#define HASHED_DATA(p) (((UCHAR *)p) + 15)
+
+
+
+// Crypt context
+struct CRYPT
+{
+ struct rc4_key_st *Rc4Key;
+};
+
+// Name in the certificate
+struct NAME
+{
+ wchar_t *CommonName; // CN
+ wchar_t *Organization; // O
+ wchar_t *Unit; // OU
+ wchar_t *Country; // C
+ wchar_t *State; // ST
+ wchar_t *Local; // L
+};
+
+// Serial number
+struct X_SERIAL
+{
+ UINT size;
+ UCHAR *data;
+};
+
+// Certificate
+struct X
+{
+ X509 *x509;
+ NAME *issuer_name;
+ NAME *subject_name;
+ bool root_cert;
+ UINT64 notBefore;
+ UINT64 notAfter;
+ X_SERIAL *serial;
+ bool do_not_free;
+ bool is_compatible_bit;
+ UINT bits;
+};
+
+// Key
+struct K
+{
+ EVP_PKEY *pkey;
+ bool private_key;
+};
+
+// PKCS#12
+struct P12
+{
+ PKCS12 *pkcs12;
+};
+
+// CEL
+struct X_CRL
+{
+ X509_CRL *Crl;
+};
+
+// Constant
+#define MD5_SIZE 16
+#define SHA1_SIZE 20
+#define SHA256_SIZE 32
+
+// Key element of DES
+struct DES_KEY_VALUE
+{
+ struct DES_ks *KeySchedule;
+ UCHAR KeyValue[DES_KEY_SIZE];
+};
+
+// DES key
+struct DES_KEY
+{
+ DES_KEY_VALUE *k1, *k2, *k3;
+};
+
+// AES key
+struct AES_KEY_VALUE
+{
+ struct aes_key_st *EncryptKey;
+ struct aes_key_st *DecryptKey;
+ UCHAR KeyValue[AES_MAX_KEY_SIZE];
+ UINT KeySize;
+};
+
+// DH
+struct DH_CTX
+{
+ struct dh_st *dh;
+ BUF *MyPublicKey;
+ BUF *MyPrivateKey;
+ UINT Size;
+};
+
+// Cipher object
+struct CIPHER
+{
+ char Name[MAX_PATH];
+ bool IsNullCipher;
+ const struct evp_cipher_st *Cipher;
+ struct evp_cipher_ctx_st *Ctx;
+ bool Encrypt;
+ UINT BlockSize, IvSize, KeySize;
+};
+
+// Message digest object
+struct MD
+{
+ char Name[MAX_PATH];
+ const struct env_md_st *Md;
+ struct hmac_ctx_st *Ctx;
+ UINT Size;
+};
+
+
+// Lock of the OpenSSL
+extern LOCK **ssl_lock_obj;
+
+// Function prototype
+CRYPT *NewCrypt(void *key, UINT size);
+void FreeCrypt(CRYPT *c);
+void Encrypt(CRYPT *c, void *dst, void *src, UINT size);
+void Hash(void *dst, void *src, UINT size, bool sha);
+void HashSha1(void *dst, void *src, UINT size);
+void HashSha256(void *dst, void *src, UINT size);
+void HashMd4(void *dst, void *src, UINT size);
+void HashMd4(void *dst, void *src, UINT size);
+void InitCryptLibrary();
+void Rand(void *buf, UINT size);
+void Rand128(void *buf);
+UINT HashToUINT(void *data, UINT size);
+UINT64 Rand64();
+UINT Rand32();
+USHORT Rand16();
+UCHAR Rand8();
+bool Rand1();
+UINT HashPtrToUINT(void *p);
+
+void CertTest();
+BIO *BufToBio(BUF *b);
+BUF *BioToBuf(BIO *bio);
+BIO *NewBio();
+void FreeBio(BIO *bio);
+X *BioToX(BIO *bio, bool text);
+X *BufToX(BUF *b, bool text);
+BUF *SkipBufBeforeString(BUF *b, char *str);
+void FreeX509(X509 *x509);
+void FreeX(X *x);
+BIO *XToBio(X *x, bool text);
+BUF *XToBuf(X *x, bool text);
+K *BioToK(BIO *bio, bool private_key, bool text, char *password);
+int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param);
+void FreePKey(EVP_PKEY *pkey);
+void FreeK(K *k);
+K *BufToK(BUF *b, bool private_key, bool text, char *password);
+bool IsEncryptedK(BUF *b, bool private_key);
+bool IsBase64(BUF *b);
+BIO *KToBio(K *k, bool text, char *password);
+BUF *KToBuf(K *k, bool text, char *password);
+X *FileToX(char *filename);
+X *FileToXW(wchar_t *filename);
+bool XToFile(X *x, char *filename, bool text);
+bool XToFileW(X *x, wchar_t *filename, bool text);
+K *FileToK(char *filename, bool private_key, char *password);
+K *FileToKW(wchar_t *filename, bool private_key, char *password);
+bool KToFile(K *k, char *filename, bool text, char *password);
+bool KToFileW(K *k, wchar_t *filename, bool text, char *password);
+bool CheckXandK(X *x, K *k);
+bool CompareX(X *x1, X *x2);
+NAME *X509NameToName(void *xn);
+wchar_t *GetUniStrFromX509Name(void *xn, int nid);
+void LoadXNames(X *x);
+void FreeXNames(X *x);
+void FreeName(NAME *n);
+bool CompareName(NAME *n1, NAME *n2);
+K *GetKFromX(X *x);
+bool CheckSignature(X *x, K *k);
+X *X509ToX(X509 *x509);
+bool CheckX(X *x, X *x_issuer);
+bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time);
+bool StrToSystem(SYSTEMTIME *s, char *str);
+UINT64 Asn1TimeToUINT64(void *asn1_time);
+bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s);
+bool UINT64ToAsn1Time(void *asn1_time, UINT64 t);
+bool SystemToStr(char *str, UINT size, SYSTEMTIME *s);
+void LoadXDates(X *x);
+bool CheckXDate(X *x, UINT64 current_system_time);
+bool CheckXDateNow(X *x);
+NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,
+ wchar_t *country, wchar_t *state, wchar_t *local);
+void *NameToX509Name(NAME *nm);
+void FreeX509Name(void *xn);
+bool AddX509Name(void *xn, int nid, wchar_t *str);
+X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial);
+X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial);
+X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial);
+X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial);
+UINT GetDaysUntil2038();
+X_SERIAL *NewXSerial(void *data, UINT size);
+void FreeXSerial(X_SERIAL *serial);
+char *ByteToStr(BYTE *src, UINT src_size);
+P12 *BioToP12(BIO *bio);
+P12 *PKCS12ToP12(PKCS12 *pkcs12);
+P12 *BufToP12(BUF *b);
+BIO *P12ToBio(P12 *p12);
+BUF *P12ToBuf(P12 *p12);
+void FreePKCS12(PKCS12 *pkcs12);
+void FreeP12(P12 *p12);
+P12 *FileToP12(char *filename);
+P12 *FileToP12W(wchar_t *filename);
+bool P12ToFile(P12 *p12, char *filename);
+bool P12ToFileW(P12 *p12, wchar_t *filename);
+bool ParseP12(P12 *p12, X **x, K **k, char *password);
+bool IsEncryptedP12(P12 *p12);
+P12 *NewP12(X *x, K *k, char *password);
+X *CloneX(X *x);
+K *CloneK(K *k);
+void FreeCryptLibrary();
+void GetPrintNameFromX(wchar_t *str, UINT size, X *x);
+void GetPrintNameFromXA(char *str, UINT size, X *x);
+void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromX(wchar_t *str, UINT size, X *x);
+void GetAllNameFromA(char *str, UINT size, X *x);
+void GetAllNameFromName(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromXEx(wchar_t *str, UINT size, X *x);
+void GetAllNameFromXExA(char *str, UINT size, X *x);
+BUF *BigNumToBuf(BIGNUM *bn);
+BIGNUM *BinToBigNum(void *data, UINT size);
+BIGNUM *BufToBigNum(BUF *b);
+char *BigNumToStr(BIGNUM *bn);
+X_SERIAL *CloneXSerial(X_SERIAL *src);
+bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2);
+void GetXDigest(X *x, UCHAR *buf, bool sha1);
+NAME *CopyName(NAME *n);
+
+
+bool RsaGen(K **priv, K **pub, UINT bit);
+bool RsaCheck();
+bool RsaCheckEx();
+bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k);
+bool RsaSign(void *dst, void *src, UINT size, K *k);
+bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits);
+bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size);
+bool RsaVerify(void *data, UINT data_size, void *sign, K *k);
+bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits);
+UINT RsaPublicSize(K *k);
+void RsaPublicToBin(K *k, void *data);
+BUF *RsaPublicToBuf(K *k);
+K *RsaBinToPublic(void *data, UINT size);
+
+X_CRL *FileToXCrl(char *filename);
+X_CRL *FileToXCrlW(wchar_t *filename);
+X_CRL *BufToXCrl(BUF *b);
+void FreeXCrl(X_CRL *r);
+bool IsXRevokedByXCrl(X *x, X_CRL *r);
+bool IsXRevoked(X *x);
+
+DES_KEY_VALUE *DesNewKeyValue(void *value);
+DES_KEY_VALUE *DesRandKeyValue();
+void DesFreeKeyValue(DES_KEY_VALUE *v);
+DES_KEY *Des3NewKey(void *k1, void *k2, void *k3);
+void Des3FreeKey(DES_KEY *k);
+DES_KEY *DesNewKey(void *k1);
+void DesFreeKey(DES_KEY *k);
+DES_KEY *Des3RandKey();
+DES_KEY *DesRandKey();
+void Des3Encrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec);
+void Des3Encrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec);
+void Des3Decrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec);
+void Des3Decrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec);
+void Sha1(void *dst, void *src, UINT size);
+void Md5(void *dst, void *src, UINT size);
+void MacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+void MacSha196(void *dst, void *key, void *data, UINT data_size);
+void DesEncrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec);
+void DesDecrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec);
+void DesEcbEncrypt(void *dst, void *src, void *key_7bytes);
+
+bool DhCompute(DH_CTX *dh, void *dst_priv_key, void *src_pub_key, UINT key_size);
+DH_CTX *DhNewGroup1();
+DH_CTX *DhNewGroup2();
+DH_CTX *DhNewGroup5();
+DH_CTX *DhNewSimple160();
+DH_CTX *DhNew(char *prime, UINT g);
+void DhFree(DH_CTX *dh);
+BUF *DhToBuf(DH_CTX *dh);
+
+AES_KEY_VALUE *AesNewKey(void *data, UINT size);
+void AesFreeKey(AES_KEY_VALUE *k);
+void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+
+bool IsIntelAesNiSupported();
+void CheckIfIntelAesNiSupportedInit();
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+#endif // USE_INTEL_AESNI_LIBRARY
+
+void OpenSSL_InitLock();
+void OpenSSL_FreeLock();
+void OpenSSL_Lock(int mode, int n, const char *file, int line);
+unsigned long OpenSSL_Id(void);
+void FreeOpenSSLThreadState();
+
+CIPHER *NewCipher(char *name);
+void FreeCipher(CIPHER *c);
+void SetCipherKey(CIPHER *c, void *key, bool enc);
+UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size);
+
+MD *NewMd(char *name);
+void FreeMd(MD *md);
+void SetMdKey(MD *md, void *key, UINT key_size);
+void MdProcess(MD *md, void *dest, void *src, UINT size);
+void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
+ int slen, unsigned char *out1, int olen);
+
+void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+
+void DisableIntelAesAccel();
+
+#ifdef ENCRYPT_C
+// Inner function
+
+
+#endif // ENCRYPT_C
+
+#endif // ENCRYPT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/FileIO.c b/src/Mayaqua/FileIO.c
new file mode 100644
index 00000000..8cf0178e
--- /dev/null
+++ b/src/Mayaqua/FileIO.c
@@ -0,0 +1,2738 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// FileIO.c
+// File Input / Output code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static char exe_file_name[MAX_SIZE] = "/tmp/a.out";
+static wchar_t exe_file_name_w[MAX_SIZE] = L"/tmp/a.out";
+static LIST *hamcore = NULL;
+static IO *hamcore_io = NULL;
+
+#define NUM_CRC32_TABLE 256
+static UINT crc32_table[NUM_CRC32_TABLE];
+
+// Confirm that the specified string exists as a line
+bool IsInLines(BUF *buf, char *str, bool instr)
+{
+ bool ret = false;
+ // Validate arguments
+ if (buf == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(str))
+ {
+ return false;
+ }
+
+ SeekBufToBegin(buf);
+
+ while (ret == false)
+ {
+ char *line = CfgReadNextLine(buf);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StrCmpi(line, str) == 0)
+ {
+ ret = true;
+ }
+
+ if (instr)
+ {
+ if (InStr(str, line))
+ {
+ ret = true;
+ }
+
+ if (InStr(line, str))
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Free(line);
+ }
+
+ return ret;
+}
+bool IsInLinesFile(wchar_t *filename, char *str, bool instr)
+{
+ bool ret = false;
+ BUF *b;
+ // Validate arguments
+ if (filename == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = IsInLines(b, str, instr);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Check whether the file is write-locked
+bool IsFileWriteLockedW(wchar_t *name)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsFileExistsW(name) == false)
+ {
+ return false;
+ }
+
+ io = FileOpenW(name, true);
+ if (io == NULL)
+ {
+ return true;
+ }
+
+ FileClose(io);
+
+ return false;
+}
+bool IsFileWriteLocked(char *name)
+{
+ bool ret;
+ wchar_t *tmp;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ tmp = CopyStrToUni(name);
+
+ ret = IsFileWriteLockedW(tmp);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Creating a ZIP packer
+ZIP_PACKER *NewZipPacker()
+{
+ ZIP_PACKER *p = ZeroMalloc(sizeof(ZIP_PACKER));
+
+ p->Fifo = NewFifo();
+ p->FileList = NewList(NULL);
+ p->CurrentFile = NULL;
+
+ return p;
+}
+
+// Release of ZIP packer
+void FreeZipPacker(ZIP_PACKER *p)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ ReleaseFifo(p->Fifo);
+
+ for (i = 0;i < LIST_NUM(p->FileList);i++)
+ {
+ ZIP_FILE *f = LIST_DATA(p->FileList, i);
+
+ Free(f);
+ }
+
+ ReleaseList(p->FileList);
+
+ Free(p);
+}
+
+// Simply add the file
+void ZipAddFileSimple(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, void *data, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name) || (size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ ZipAddFileStart(p, name, size, dt, attribute);
+ ZipAddFileData(p, data, 0, size);
+}
+bool ZipAddRealFileW(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, wchar_t *srcname)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name) || srcname == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(srcname);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ZipAddFileSimple(p, name, dt, attribute, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return true;
+}
+bool ZipAddRealFile(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, char *srcname)
+{
+ bool ret = false;
+ wchar_t *s;
+
+ s = CopyStrToUni(srcname);
+
+ ret = ZipAddRealFileW(p, name, dt, attribute, s);
+
+ Free(s);
+
+ return ret;
+}
+
+// Start adding a file
+void ZipAddFileStart(ZIP_PACKER *p, char *name, UINT size, UINT64 dt, UINT attribute)
+{
+ char tmp[MAX_PATH];
+ ZIP_FILE *f;
+ ZIP_DATA_HEADER h;
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name))
+ {
+ return;
+ }
+ if (dt == 0)
+ {
+ dt = LocalTime64();
+ }
+
+ if (p->CurrentFile != NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "\\", true);
+
+ f = ZeroMalloc(sizeof(ZIP_FILE));
+
+ StrCpy(f->Name, sizeof(f->Name), tmp);
+ f->Size = size;
+ f->DateTime = dt;
+ f->Attributes = attribute;
+
+ Add(p->FileList, f);
+
+ Zero(&h, sizeof(h));
+ f->HeaderPos = (UINT)p->Fifo->total_write_size;
+ WriteZipDataHeader(f, &h, false);
+ WriteFifo(p->Fifo, &h, sizeof(h));
+ WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
+ f->Crc32 = 0xffffffff;
+
+ p->CurrentFile = f;
+}
+
+// Add data to the file
+UINT ZipAddFileData(ZIP_PACKER *p, void *data, UINT pos, UINT len)
+{
+ UINT total_size = p->CurrentFile->CurrentSize + len;
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+ if (total_size > p->CurrentFile->Size)
+ {
+ return 0;
+ }
+
+ WriteFifo(p->Fifo, ((UCHAR *)data) + pos, len);
+
+ p->CurrentFile->CurrentSize += len;
+ p->CurrentFile->Crc32 = Crc32Next(data, pos, len, p->CurrentFile->Crc32);
+
+ ret = p->CurrentFile->Size - p->CurrentFile->CurrentSize;
+
+ if (ret == 0)
+ {
+ p->CurrentFile->Crc32 = ~p->CurrentFile->Crc32;
+
+ ZipAddFileFooter(p);
+
+ p->CurrentFile = NULL;
+ }
+
+ return ret;
+}
+
+// Append a file footer
+void ZipAddFileFooter(ZIP_PACKER *p)
+{
+ ZIP_DATA_FOOTER f;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Zero(&f, sizeof(f));
+ WriteZipDataFooter(p->CurrentFile, &f);
+
+ WriteFifo(p->Fifo, &f, sizeof(f));
+}
+
+// Output the ZIP data to a file
+bool ZipWriteW(ZIP_PACKER *p, wchar_t *name)
+{
+ FIFO *f;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ f = ZipFinish(p);
+ if (f == NULL)
+ {
+ return false;
+ }
+
+ return FileWriteAllW(name, FifoPtr(f), FifoSize(f));
+}
+
+// Complete the creation of the ZIP data
+FIFO *ZipFinish(ZIP_PACKER *p)
+{
+ UINT i;
+ UINT pos_start;
+ UINT pos_end;
+ ZIP_END_HEADER e;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ pos_start = (UINT)p->Fifo->total_write_size;
+
+ for (i = 0;i < LIST_NUM(p->FileList);i++)
+ {
+ ZIP_FILE *f = LIST_DATA(p->FileList, i);
+ ZIP_DIR_HEADER d;
+ ZIP_DATA_HEADER dh;
+
+ Zero(&d, sizeof(d));
+ Zero(&dh, sizeof(dh));
+
+ d.Signature = Endian32(Swap32(0x02014B50));
+ d.MadeVer = Endian16(Swap16(ZIP_VERSION));
+
+ WriteZipDataHeader(f, &dh, true);
+
+ d.NeedVer = dh.NeedVer;
+ d.Option = dh.Option;
+ d.CompType = dh.CompType;
+ d.FileTime = dh.FileTime;
+ d.FileDate = dh.FileDate;
+ d.Crc32 = dh.Crc32;
+ d.CompSize = dh.CompSize;
+ d.UncompSize = dh.UncompSize;
+ d.FileNameLen = dh.FileNameLen;
+ d.ExtraLen = dh.ExtraLen;
+ d.CommentLen = 0;
+ d.DiskNum = 0;
+ d.InAttr = 0;
+ d.OutAttr = Endian32(Swap32((USHORT)f->Attributes));
+ d.HeaderPos = Endian32(Swap32(f->HeaderPos));
+
+ WriteFifo(p->Fifo, &d, sizeof(d));
+ WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
+ }
+
+ pos_end = (UINT)p->Fifo->total_write_size;
+
+ Zero(&e, sizeof(e));
+ e.Signature = Endian32(Swap32(ZIP_SIGNATURE_END));
+ e.DiskNum = e.StartDiskNum = 0;
+ e.DiskDirEntry = e.DirEntry = Endian16(Swap16((USHORT)LIST_NUM(p->FileList)));
+ e.DirSize = Endian32(Swap32((UINT)(pos_end - pos_start)));
+ e.StartPos = Endian32(Swap32(pos_start));
+ e.CommentLen = 0;
+
+ WriteFifo(p->Fifo, &e, sizeof(e));
+
+ return p->Fifo;
+}
+
+// Creating a ZIP data header
+void WriteZipDataHeader(ZIP_FILE *f, ZIP_DATA_HEADER *h, bool write_sizes)
+{
+ // Validate arguments
+ if (f == NULL || h ==NULL)
+ {
+ return;
+ }
+
+ h->Signature = Endian32(Swap32(ZIP_SIGNATURE));
+ h->NeedVer = Endian16(Swap16(ZIP_VERSION));
+ h->CompType = 0;
+ h->FileDate = Endian16(Swap16(System64ToDosDate(f->DateTime)));
+ h->FileTime = Endian16(Swap16(System64ToDosTime(f->DateTime)));
+ h->Option = Endian16(Swap16(8)); // bit3: Set the file-size and the CRC in local header to 0
+
+ if (write_sizes == false)
+ {
+ h->CompSize = h->UncompSize = 0;
+ h->Crc32 = 0;
+ }
+ else
+ {
+ h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
+ h->Crc32 = Endian32(Swap32(f->Crc32));
+ }
+
+ h->FileNameLen = Endian16(Swap16(StrLen(f->Name)));
+ h->ExtraLen = 0;
+}
+
+// Creating a ZIP data footer
+void WriteZipDataFooter(ZIP_FILE *f, ZIP_DATA_FOOTER *h)
+{
+ // Validate arguments
+ if (f == NULL || h ==NULL)
+ {
+ return;
+ }
+
+ h->Signature = Endian32(Swap32(0x08074B50));
+ h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
+ h->Crc32 = Endian32(Swap32(f->Crc32));
+}
+
+// Initialize the common table of CRC32
+void InitCrc32()
+{
+ UINT poly = 0xEDB88320;
+ UINT u, i, j;
+
+ for (i = 0;i < 256;i++)
+ {
+ u = i;
+
+ for (j = 0;j < 8;j++)
+ {
+ if ((u & 0x1) != 0)
+ {
+ u = (u >> 1) ^ poly;
+ }
+ else
+ {
+ u >>= 1;
+ }
+ }
+
+ crc32_table[i] = u;
+ }
+}
+
+// CRC32 arithmetic processing
+UINT Crc32(void *buf, UINT pos, UINT len)
+{
+ return Crc32Finish(Crc32First(buf, pos, len));
+}
+UINT Crc32First(void *buf, UINT pos, UINT len)
+{
+ return Crc32Next(buf, pos, len, 0xffffffff);
+}
+UINT Crc32Next(void *buf, UINT pos, UINT len, UINT last_crc32)
+{
+ UINT ret = last_crc32;
+ UINT i;
+
+ for (i = 0;i < len;i++)
+ {
+ ret = (ret >> 8) ^ crc32_table[((UCHAR *)buf)[pos + i] ^ (ret & 0xff)];
+ }
+
+ return ret;
+}
+UINT Crc32Finish(UINT last_crc32)
+{
+ return ~last_crc32;
+}
+
+// Save the file
+bool SaveFileW(wchar_t *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreateW(name);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ if (FileWrite(io, data, size) == false)
+ {
+ FileClose(io);
+ return false;
+ }
+
+ FileClose(io);
+
+ return true;
+}
+bool SaveFile(char *name, void *data, UINT size)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = SaveFileW(name_w, data, size);
+
+ Free(name_w);
+
+ return ret;
+}
+
+// Check whether the file exists
+bool IsFile(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileW(wchar_t *name)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ io = FileOpenExW(name, false, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileClose(io);
+
+ return true;
+}
+
+// Rename to replace the file
+bool FileReplaceRename(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileReplaceRenameW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (FileCopyW(old_name, new_name) == false)
+ {
+ return false;
+ }
+
+ FileDeleteW(old_name);
+
+ return true;
+}
+
+// Make the file name safe
+void ConvertSafeFileName(char *dst, UINT size, char *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ StrCpy(dst, size, src);
+ for (i = 0;i < StrLen(dst);i++)
+ {
+ if (IsSafeChar(dst[i]) == false)
+ {
+ dst[i] = '_';
+ }
+ }
+}
+void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(dst, size, src);
+ for (i = 0;i < UniStrLen(dst);i++)
+ {
+ if (UniIsSafeChar(dst[i]) == false)
+ {
+ dst[i] = L'_';
+ }
+ }
+}
+
+// Get the free disk space
+bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ bool ret;
+ // Validate arguments
+ if (path == NULL)
+ {
+ path = "./";
+ }
+
+#ifdef OS_WIN32
+ ret = Win32GetDiskFree(path, free_size, used_size, total_size);
+#else // OS_WIN32
+ ret = UnixGetDiskFree(path, free_size, used_size, total_size);
+#endif // OS_WIN32
+
+ return ret;
+}
+bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ bool ret;
+ // Validate arguments
+ if (path == NULL)
+ {
+ path = L"./";
+ }
+
+#ifdef OS_WIN32
+ ret = Win32GetDiskFreeW(path, free_size, used_size, total_size);
+#else // OS_WIN32
+ ret = UnixGetDiskFreeW(path, free_size, used_size, total_size);
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Enumeration of directory
+DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
+{
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+ DIRLIST *ret = EnumDirExW(dirname_w, compare);
+
+ Free(dirname_w);
+
+ return ret;
+}
+DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ DIRLIST *d = NULL;
+ // Validate arguments
+ if (dirname == NULL)
+ {
+ dirname = L"./";
+ }
+
+ if (compare == NULL)
+ {
+ compare = CompareDirListByName;
+ }
+
+#ifdef OS_WIN32
+ d = Win32EnumDirExW(dirname, compare);
+#else // OS_WIN32
+ d = UnixEnumDirExW(dirname, compare);
+#endif // OS_WIN32
+
+ return d;
+}
+DIRLIST *EnumDir(char *dirname)
+{
+ return EnumDirEx(dirname, NULL);
+}
+DIRLIST *EnumDirW(wchar_t *dirname)
+{
+ return EnumDirExW(dirname, NULL);
+}
+
+// Comparison of DIRLIST list entry
+int CompareDirListByName(void *p1, void *p2)
+{
+ DIRENT *d1, *d2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ d1 = *(DIRENT **)p1;
+ d2 = *(DIRENT **)p2;
+ if (d1 == NULL || d2 == NULL)
+ {
+ return 0;
+ }
+ return UniStrCmpi(d1->FileNameW, d2->FileNameW);
+}
+
+// Release the enumeration of the directory
+void FreeDir(DIRLIST *d)
+{
+ UINT i;
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < d->NumFiles;i++)
+ {
+ DIRENT *f = d->File[i];
+ Free(f->FileName);
+ Free(f->FileNameW);
+ Free(f);
+ }
+ Free(d->File);
+ Free(d);
+}
+
+
+// Make the file name safe
+void UniSafeFileName(wchar_t *name)
+{
+ UINT i, len, dlen;
+ static wchar_t *danger_str = L"\\/:*?\"<>|";
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ dlen = UniStrLen(danger_str);
+ len = UniStrLen(name);
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = name[i];
+ UINT j;
+ for (j = 0;j < dlen;j++)
+ {
+ if (c == danger_str[j])
+ {
+ c = L'_';
+ }
+ }
+ name[i] = c;
+ }
+}
+void SafeFileNameW(wchar_t *name)
+{
+ UniSafeFileName(name);
+}
+
+// Read HamCore file
+BUF *ReadHamcoreW(wchar_t *filename)
+{
+ char *filename_a = CopyUniToStr(filename);
+ BUF *ret;
+
+ ret = ReadHamcore(filename_a);
+
+ Free(filename_a);
+
+ return ret;
+}
+BUF *ReadHamcore(char *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t exe_dir[MAX_SIZE];
+ BUF *b;
+ char filename[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (name[0] == '|')
+ {
+ name++;
+ }
+
+ if (name[0] == '/' || name[0] == '\\')
+ {
+ name++;
+ }
+
+ StrCpy(filename, sizeof(filename), name);
+
+ ReplaceStrEx(filename, sizeof(filename), filename, "/", "\\", true);
+
+ if (MayaquaIsMinimalMode())
+ {
+ return NULL;
+ }
+
+ // If the file exist in hamcore/ directory on the local disk, read it
+ GetExeDirW(exe_dir, sizeof(exe_dir));
+
+ UniFormat(tmp, sizeof(tmp), L"%s/%S/%S", exe_dir, HAMCORE_DIR_NAME, filename);
+
+ b = ReadDumpW(tmp);
+ if (b != NULL)
+ {
+ return b;
+ }
+
+ // Search from HamCore file system if it isn't found
+ LockList(hamcore);
+ {
+ HC t, *c;
+ UINT i;
+
+ Zero(&t, sizeof(t));
+ t.FileName = filename;
+ c = Search(hamcore, &t);
+
+ if (c == NULL)
+ {
+ // File does not exist
+ b = NULL;
+ }
+ else
+ {
+ // File exists
+ if (c->Buffer != NULL)
+ {
+ // It is already loaded
+ b = NewBuf();
+ WriteBuf(b, c->Buffer, c->Size);
+ SeekBuf(b, 0, 0);
+ c->LastAccess = Tick64();
+ }
+ else
+ {
+ // Read from a file is if it is not read
+ if (FileSeek(hamcore_io, 0, c->Offset) == false)
+ {
+ // Failed to seek
+ b = NULL;
+ }
+ else
+ {
+ // Read the compressed data
+ void *data = Malloc(c->SizeCompressed);
+ if (FileRead(hamcore_io, data, c->SizeCompressed) == false)
+ {
+ // Failed to read
+ Free(data);
+ b = NULL;
+ }
+ else
+ {
+ // Expand
+ c->Buffer = ZeroMalloc(c->Size);
+ if (Uncompress(c->Buffer, c->Size, data, c->SizeCompressed) != c->Size)
+ {
+ // Failed to expand
+ Free(data);
+ Free(c->Buffer);
+ b = NULL;
+ }
+ else
+ {
+ // Successful
+ Free(data);
+ b = NewBuf();
+ WriteBuf(b, c->Buffer, c->Size);
+ SeekBuf(b, 0, 0);
+ c->LastAccess = Tick64();
+ }
+ }
+ }
+ }
+ }
+
+ // Delete the expired cache
+ for (i = 0;i < LIST_NUM(hamcore);i++)
+ {
+ HC *c = LIST_DATA(hamcore, i);
+
+ if (c->Buffer != NULL)
+ {
+ if (((c->LastAccess + HAMCORE_CACHE_EXPIRES) <= Tick64()) ||
+ (StartWith(c->FileName, "Li")))
+ {
+ Free(c->Buffer);
+ c->Buffer = NULL;
+ }
+ }
+ }
+ }
+ UnlockList(hamcore);
+
+ return b;
+}
+
+// Initialization of HamCore file system
+void InitHamcore()
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ wchar_t exe_dir[MAX_PATH];
+ UINT i, num;
+ char header[HAMCORE_HEADER_SIZE];
+
+ hamcore = NewList(CompareHamcore);
+
+ if (MayaquaIsMinimalMode())
+ {
+ return;
+ }
+
+ GetExeDirW(exe_dir, sizeof(exe_dir));
+ UniFormat(tmp, sizeof(tmp), L"%s/%S", exe_dir, HAMCORE_FILE_NAME);
+
+ UniFormat(tmp2, sizeof(tmp2), L"%s/%S", exe_dir, HAMCORE_FILE_NAME_2);
+
+ // If there is _hamcore.se2, overwrite it yo the hamcore.se2
+ FileReplaceRenameW(tmp2, tmp);
+
+ // Read if there is a file hamcore.se2
+ hamcore_io = FileOpenW(tmp, false);
+ if (hamcore_io == NULL)
+ {
+ // Look in other locations if it isn't found
+#ifdef OS_WIN32
+ UniFormat(tmp, sizeof(tmp), L"%S/%S", MsGetSystem32Dir(), HAMCORE_FILE_NAME);
+#else // OS_WIN32
+ UniFormat(tmp, sizeof(tmp), L"/bin/%S", HAMCORE_FILE_NAME);
+#endif // OS_WIN32
+
+ hamcore_io = FileOpenW(tmp, false);
+ if (hamcore_io == NULL)
+ {
+ return;
+ }
+ }
+
+ // Read the file header
+ Zero(header, sizeof(header));
+ FileRead(hamcore_io, header, HAMCORE_HEADER_SIZE);
+
+ if (Cmp(header, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE) != 0)
+ {
+ // Invalid header
+ FileClose(hamcore_io);
+ hamcore_io = NULL;
+ return;
+ }
+
+ // The number of the File
+ num = 0;
+ FileRead(hamcore_io, &num, sizeof(num));
+ num = Endian32(num);
+ for (i = 0;i < num;i++)
+ {
+ // File name
+ char tmp[MAX_SIZE];
+ UINT str_size = 0;
+ HC *c;
+
+ FileRead(hamcore_io, &str_size, sizeof(str_size));
+ str_size = Endian32(str_size);
+ if (str_size >= 1)
+ {
+ str_size--;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ FileRead(hamcore_io, tmp, str_size);
+
+ c = ZeroMalloc(sizeof(HC));
+ c->FileName = CopyStr(tmp);
+
+ FileRead(hamcore_io, &c->Size, sizeof(UINT));
+ c->Size = Endian32(c->Size);
+
+ FileRead(hamcore_io, &c->SizeCompressed, sizeof(UINT));
+ c->SizeCompressed = Endian32(c->SizeCompressed);
+
+ FileRead(hamcore_io, &c->Offset, sizeof(UINT));
+ c->Offset = Endian32(c->Offset);
+
+ Insert(hamcore, c);
+ }
+}
+
+// Release of HamCore file system
+void FreeHamcore()
+{
+ UINT i;
+ for (i = 0;i < LIST_NUM(hamcore);i++)
+ {
+ HC *c = LIST_DATA(hamcore, i);
+ Free(c->FileName);
+ if (c->Buffer != NULL)
+ {
+ Free(c->Buffer);
+ }
+ Free(c);
+ }
+ ReleaseList(hamcore);
+
+ FileClose(hamcore_io);
+ hamcore_io = NULL;
+ hamcore = NULL;
+}
+
+// Build a Hamcore file
+void BuildHamcore()
+{
+ BUF *b;
+ char tmp[MAX_SIZE];
+ char exe_dir[MAX_SIZE];
+ char *s;
+ bool ok = true;
+ LIST *o;
+ UINT i;
+
+ GetExeDir(exe_dir, sizeof(exe_dir));
+ Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_TEXT_NAME);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ Print("Failed to open %s.\n", tmp);
+ return;
+ }
+
+ o = NewListFast(CompareHamcore);
+
+ while ((s = CfgReadNextLine(b)) != NULL)
+ {
+ char tmp[MAX_SIZE];
+ BUF *b;
+ Trim(s);
+
+ Format(tmp, sizeof(tmp), "%s/%s/%s", exe_dir, HAMCORE_DIR_NAME, s);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ Print("Failed to open %s.\n", s);
+ ok = false;
+ }
+ else
+ {
+ HC *c = ZeroMalloc(sizeof(HC));
+ UINT tmp_size;
+ void *tmp;
+ c->FileName = CopyStr(s);
+ c->Size = b->Size;
+ tmp_size = CalcCompress(c->Size);
+ tmp = Malloc(tmp_size);
+ c->SizeCompressed = Compress(tmp, tmp_size, b->Buf, b->Size);
+ c->Buffer = tmp;
+ Insert(o, c);
+ Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);
+ FreeBuf(b);
+ }
+
+ Free(s);
+ }
+
+ if (ok)
+ {
+ // Calculate the offset of the buffer for each file
+ UINT i, z;
+ char tmp[MAX_SIZE];
+ BUF *b;
+ z = 0;
+ z += HAMCORE_HEADER_SIZE;
+ // The number of files
+ z += sizeof(UINT);
+ // For file table first
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // File name
+ z += StrLen(c->FileName) + sizeof(UINT);
+ // File size
+ z += sizeof(UINT);
+ z += sizeof(UINT);
+ // Offset data
+ z += sizeof(UINT);
+ }
+ // File body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // Buffer body
+ c->Offset = z;
+ printf("%s: offset: %u\n", c->FileName, c->Offset);
+ z += c->SizeCompressed;
+ }
+ // Writing
+ b = NewBuf();
+ // Header
+ WriteBuf(b, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
+ WriteBufInt(b, LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // File name
+ WriteBufStr(b, c->FileName);
+ // File size
+ WriteBufInt(b, c->Size);
+ WriteBufInt(b, c->SizeCompressed);
+ // Offset
+ WriteBufInt(b, c->Offset);
+ }
+ // Body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ WriteBuf(b, c->Buffer, c->SizeCompressed);
+ }
+ // Writing
+ Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_FILE_NAME "__");
+ Print("Writing %s...\n", tmp);
+ FileDelete(tmp);
+ DumpBuf(b, tmp);
+ FreeBuf(b);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ Free(c->Buffer);
+ Free(c->FileName);
+ Free(c);
+ }
+
+ ReleaseList(o);
+
+ FreeBuf(b);
+}
+
+// Comparison of the HCs
+int CompareHamcore(void *p1, void *p2)
+{
+ HC *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(HC **)p1;
+ c2 = *(HC **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(c1->FileName, c2->FileName);
+}
+
+// Getting the name of the directory where the EXE file is in
+void GetExeDir(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetDirNameFromFilePath(name, size, exe_file_name);
+}
+void GetExeDirW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetDirNameFromFilePathW(name, size, exe_file_name_w);
+}
+
+// Get the EXE file name
+void GetExeName(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(name, size, exe_file_name);
+}
+void GetExeNameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(name, size, exe_file_name_w);
+}
+
+// Initialization of the aquisition of the EXE file name
+void InitGetExeName(char *arg)
+{
+ wchar_t *arg_w = NULL;
+ // Validate arguments
+ if (arg == NULL)
+ {
+ arg = "./a.out";
+ }
+
+ arg_w = CopyUtfToUni(arg);
+
+#ifdef OS_WIN32
+ Win32GetExeNameW(exe_file_name_w, sizeof(exe_file_name_w));
+#else // OS_WIN32
+ UnixGetExeNameW(exe_file_name_w, sizeof(exe_file_name_w), arg_w);
+#endif // OS_WIN32
+
+ UniToStr(exe_file_name, sizeof(exe_file_name), exe_file_name_w);
+
+ Free(arg_w);
+}
+
+// Get the full path of the executable binary file in Unix
+void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg)
+{
+ UNI_TOKEN_LIST *t;
+ char *path_str;
+ wchar_t *path_str_w;
+ bool ok = false;
+ // Validate arguments
+ if (name == NULL || arg == NULL)
+ {
+ return;
+ }
+
+ path_str = GetCurrentPathEnvStr();
+ path_str_w = CopyUtfToUni(path_str);
+
+ t = ParseSplitedPathW(path_str_w);
+
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *s = t->Token[i];
+ wchar_t tmp[MAX_SIZE];
+
+ ConbinePathW(tmp, sizeof(tmp), s, arg);
+
+ if (IsFileExistsInnerW(tmp))
+ {
+#ifdef OS_UNIX
+ if (UnixCheckExecAccessW(tmp) == false)
+ {
+ continue;
+ }
+#endif // OS_UNIX
+ ok = true;
+ UniStrCpy(name, size, tmp);
+ break;
+ }
+ }
+
+ UniFreeToken(t);
+ }
+
+ Free(path_str);
+ Free(path_str_w);
+
+ if (ok == false)
+ {
+ // In the case of failing to find the path
+#ifdef OS_UNIX
+ UnixGetCurrentDirW(name, size);
+#else // OS_UNIX
+ Win32GetCurrentDirW(name, size);
+#endif // OS_UNIX
+ ConbinePathW(name, size, name, arg);
+ }
+}
+
+// Generate a secure file name
+void MakeSafeFileName(char *dst, UINT size, char *src)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), src);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "..", "__", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "\\", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "@", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "|", "_", false);
+
+ StrCpy(dst, size, tmp);
+}
+void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), src);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"..", L"__", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"/", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"\\", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"@", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"|", L"_", false);
+
+ UniStrCpy(dst, size, tmp);
+}
+
+// Get the file name from the file path
+void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT i, len, wp;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ len = MIN(UniStrLen(filepath), (MAX_SIZE - 2));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ wchar_t c = filepath[i];
+
+ switch (c)
+ {
+ case L'\\':
+ case L'/':
+ case 0:
+ tmp[wp] = 0;
+ wp = 0;
+ break;
+
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+
+ UniStrCpy(dst, size, tmp);
+}
+void GetFileNameFromFilePath(char *dst, UINT size, char *filepath)
+{
+ char tmp[MAX_SIZE];
+ UINT i, len, wp;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ len = MIN(StrLen(filepath), (MAX_SIZE - 2));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = filepath[i];
+
+ switch (c)
+ {
+ case '\\':
+ case '/':
+ case 0:
+ tmp[wp] = 0;
+ wp = 0;
+ break;
+
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+
+ StrCpy(dst, size, tmp);
+}
+void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT wp;
+ UINT i;
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), filepath);
+ if (UniEndWith(tmp, L"\\") || UniEndWith(tmp, L"/"))
+ {
+ tmp[UniStrLen(tmp) - 1] = 0;
+ }
+
+ len = UniStrLen(tmp);
+
+ UniStrCpy(dst, size, L"");
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = tmp[i];
+ if (c == L'/' || c == L'\\')
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+ UniStrCat(dst, size, tmp);
+ tmp[wp++] = c;
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+
+ if (UniStrLen(dst) == 0)
+ {
+ UniStrCpy(dst, size, L"/");
+ }
+
+ NormalizePathW(dst, size, dst);
+}
+
+// Get the directory name from the file path
+void GetDirNameFromFilePath(char *dst, UINT size, char *filepath)
+{
+ char tmp[MAX_SIZE];
+ UINT wp;
+ UINT i;
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), filepath);
+ if (EndWith(tmp, "\\") || EndWith(tmp, "/"))
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+
+ len = StrLen(tmp);
+
+ StrCpy(dst, size, "");
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ char c = tmp[i];
+ if (c == '/' || c == '\\')
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+ StrCat(dst, size, tmp);
+ tmp[wp++] = c;
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+
+ if (StrLen(dst) == 0)
+ {
+ StrCpy(dst, size, "/");
+ }
+
+ NormalizePath(dst, size, dst);
+}
+
+// Combine the two paths
+void ConbinePath(char *dst, UINT size, char *dirname, char *filename)
+{
+ wchar_t dst_w[MAX_PATH];
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+ wchar_t *filename_w = CopyStrToUni(filename);
+
+ ConbinePathW(dst_w, sizeof(dst_w), dirname_w, filename_w);
+
+ Free(dirname_w);
+ Free(filename_w);
+
+ UniToStr(dst, size, dst_w);
+}
+void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
+{
+ bool is_full_path;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t filename_ident[MAX_SIZE];
+ // Validate arguments
+ if (dst == NULL || dirname == NULL || filename == NULL)
+ {
+ return;
+ }
+
+ NormalizePathW(filename_ident, sizeof(filename_ident), filename);
+
+ is_full_path = false;
+
+ if (UniStartWith(filename_ident, L"\\") || UniStartWith(filename_ident, L"/"))
+ {
+ is_full_path = true;
+ }
+
+ filename = &filename_ident[0];
+
+#ifdef OS_WIN32
+ if (UniStrLen(filename) >= 2)
+ {
+ if ((L'a' <= filename[0] && filename[0] <= L'z') || (L'A' <= filename[0] && filename[0] <= L'Z'))
+ {
+ if (filename[1] == L':')
+ {
+ is_full_path = true;
+ }
+ }
+ }
+#endif // OS_WIN32
+
+ if (is_full_path == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), dirname);
+ if (UniEndWith(tmp, L"/") == false && UniEndWith(tmp, L"\\") == false)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+ UniStrCat(tmp, sizeof(tmp), filename);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ }
+
+ NormalizePathW(dst, size, tmp);
+}
+void CombinePath(char *dst, UINT size, char *dirname, char *filename)
+{
+ ConbinePath(dst, size, dirname, filename);
+}
+void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
+{
+ ConbinePathW(dst, size, dirname, filename);
+}
+
+// Check whether the file exists
+bool IsFileExists(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileExistsW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileExistsW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return IsFileExistsInnerW(tmp);
+}
+bool IsFileExistsInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileExistsInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileExistsInnerW(wchar_t *name)
+{
+ IO *o;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ o = FileOpenInnerW(name, false, false);
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ FileClose(o);
+
+ return true;
+}
+
+// Get the current contents of the PATH environment variable
+char *GetCurrentPathEnvStr()
+{
+ char tmp[1024];
+ char *tag_name;
+
+#ifdef OS_WIN32
+ tag_name = "Path";
+#else // OS_WIN32
+ tag_name = "PATH";
+#endif // OS_WIN32
+
+ if (GetEnv(tag_name, tmp, sizeof(tmp)) == false)
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDir(tmp, sizeof(tmp));
+#else // OS_WIN32
+ UnixGetCurrentDir(tmp, sizeof(tmp));
+#endif // OS_WIN32
+ }
+
+ return CopyStr(tmp);
+}
+
+// Get multiple paths separated by colons
+UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)
+{
+ UNI_TOKEN_LIST *ret;
+ wchar_t *tmp = UniCopyStr(path);
+ wchar_t *split_str;
+ UINT i;
+
+ UniTrim(tmp);
+ UniTrimCrlf(tmp);
+ UniTrim(tmp);
+ UniTrimCrlf(tmp);
+
+#ifdef OS_WIN32
+ split_str = L";";
+#else // OS_WIN32
+ split_str = L":";
+#endif // OS_WIN32
+
+ ret = UniParseToken(tmp, split_str);
+
+ if (ret != NULL)
+ {
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ UniTrim(ret->Token[i]);
+ UniTrimCrlf(ret->Token[i]);
+ UniTrim(ret->Token[i]);
+ UniTrimCrlf(ret->Token[i]);
+ }
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+TOKEN_LIST *ParseSplitedPath(char *path)
+{
+ TOKEN_LIST *ret;
+ char *tmp = CopyStr(path);
+ char *split_str;
+ UINT i;
+
+ Trim(tmp);
+ TrimCrlf(tmp);
+ Trim(tmp);
+ TrimCrlf(tmp);
+
+#ifdef OS_WIN32
+ split_str = ";";
+#else // OS_WIN32
+ split_str = ":";
+#endif // OS_WIN32
+
+ ret = ParseToken(tmp, split_str);
+
+ if (ret != NULL)
+ {
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ Trim(ret->Token[i]);
+ TrimCrlf(ret->Token[i]);
+ Trim(ret->Token[i]);
+ TrimCrlf(ret->Token[i]);
+ }
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the current directory
+void GetCurrentDirW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(name, size);
+#else // OS_WIN32
+ UnixGetCurrentDirW(name, size);
+#endif // OS_WIN32
+}
+void GetCurrentDir(char *name, UINT size)
+{
+ wchar_t name_w[MAX_PATH];
+
+ GetCurrentDirW(name_w, sizeof(name_w));
+
+ UniToStr(name, size, name_w);
+}
+
+// Normalize the file path
+void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t tmp[MAX_SIZE];
+ UNI_TOKEN_LIST *t;
+ bool first_double_slash = false;
+ bool first_single_slash = false;
+ wchar_t win32_drive_char = 0;
+ bool is_full_path = false;
+ UINT i;
+ SK *sk;
+ // Validate arguments
+ if (dst == NULL || src == 0)
+ {
+ return;
+ }
+
+ // Convert the path (Win32, UNIX conversion)
+ UniStrCpy(tmp, sizeof(tmp), src);
+ ConvertPathW(tmp);
+ UniTrim(tmp);
+
+ // If the path begins with "./ " or " ../", replace it to the current directory
+ if (UniStartWith(tmp, L"./") || UniStartWith(tmp, L".\\") ||
+ UniStartWith(tmp, L"../") || UniStartWith(tmp, L"..\\") ||
+ UniStrCmpi(tmp, L".") == 0 || UniStrCmpi(tmp, L"..") == 0)
+ {
+ wchar_t cd[MAX_SIZE];
+ Zero(cd, sizeof(cd));
+
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(cd, sizeof(cd));
+#else // OS_WIN32
+ UnixGetCurrentDirW(cd, sizeof(cd));
+#endif // OS_WIN32
+
+ if (UniStartWith(tmp, L".."))
+ {
+ UniStrCat(cd, sizeof(cd), L"/../");
+ UniStrCat(cd, sizeof(cd), tmp + 2);
+ }
+ else
+ {
+ UniStrCat(cd, sizeof(cd), L"/");
+ UniStrCat(cd, sizeof(cd), tmp);
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), cd);
+ }
+
+ // If the path starts with "~/", replace it with the home directory
+ if (UniStartWith(tmp, L"~/") || UniStartWith(tmp, L"~\\"))
+ {
+ wchar_t tmp2[MAX_SIZE];
+ GetHomeDirW(tmp2, sizeof(tmp2));
+ UniStrCat(tmp2, sizeof(tmp2), L"/");
+ UniStrCat(tmp2, sizeof(tmp2), tmp + 2);
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+
+ if (UniStartWith(tmp, L"//") || UniStartWith(tmp, L"\\\\"))
+ {
+ // Begin with "//" or "\\"
+ first_double_slash = true;
+ is_full_path = true;
+ }
+ else if (UniStartWith(tmp, L"/") || UniStartWith(tmp, L"\\"))
+ {
+ // Begin with "\"
+ first_single_slash = true;
+ is_full_path = true;
+ }
+
+#ifdef OS_WIN32
+ if (UniStrLen(tmp) >= 2)
+ {
+ if (tmp[1] == L':')
+ {
+ // The drive string representation of the Win32
+ wchar_t tmp2[MAX_SIZE];
+ is_full_path = true;
+ win32_drive_char = tmp[0];
+ UniStrCpy(tmp2, sizeof(tmp2), tmp + 2);
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+ }
+#endif // OS_WIN32
+
+ if (UniStrLen(tmp) == 1 && (tmp[0] == L'/' || tmp[0] == L'\\'))
+ {
+ tmp[0] = 0;
+ }
+
+ // Tokenize
+ t = UniParseToken(tmp, L"/\\");
+
+ sk = NewSk();
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *s = t->Token[i];
+
+ if (UniStrCmpi(s, L".") == 0)
+ {
+ continue;
+ }
+ else if (UniStrCmpi(s, L"..") == 0)
+ {
+ if (sk->num_item >= 1 && (first_double_slash == false || sk->num_item >= 2))
+ {
+ Pop(sk);
+ }
+ }
+ else
+ {
+ Push(sk, s);
+ }
+ }
+
+ // Token concatenation
+ UniStrCpy(tmp, sizeof(tmp), L"");
+
+ if (first_double_slash)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"//");
+ }
+ else if (first_single_slash)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+
+ if (win32_drive_char != 0)
+ {
+ wchar_t d[2];
+ d[0] = win32_drive_char;
+ d[1] = 0;
+ UniStrCat(tmp, sizeof(tmp), d);
+ UniStrCat(tmp, sizeof(tmp), L":/");
+ }
+
+ for (i = 0;i < sk->num_item;i++)
+ {
+ UniStrCat(tmp, sizeof(tmp), (wchar_t *)sk->p[i]);
+ if (i != (sk->num_item - 1))
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+ }
+
+ ReleaseSk(sk);
+
+ UniFreeToken(t);
+
+ ConvertPathW(tmp);
+
+ UniStrCpy(dst, size, tmp);
+}
+void NormalizePath(char *dst, UINT size, char *src)
+{
+ wchar_t dst_w[MAX_SIZE];
+ wchar_t *src_w = CopyStrToUni(src);
+
+ NormalizePathW(dst_w, sizeof(dst_w), src_w);
+
+ Free(src_w);
+
+ UniToStr(dst, size, dst_w);
+}
+
+// Close and delete the file
+void FileCloseAndDelete(IO *o)
+{
+ wchar_t *name;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ name = CopyUniStr(o->NameW);
+ FileClose(o);
+
+ FileDeleteW(name);
+
+ Free(name);
+}
+
+// Rename the file
+bool FileRename(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileRenameW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp1, sizeof(tmp1), old_name);
+ InnerFilePathW(tmp2, sizeof(tmp2), new_name);
+
+ return FileRenameInnerW(tmp1, tmp2);
+}
+bool FileRenameInner(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileRenameInnerW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ return OSFileRenameW(old_name, new_name);
+}
+
+// Convert the path
+void ConvertPath(char *path)
+{
+ UINT i, len;
+#ifdef PATH_BACKSLASH
+ char new_char = '\\';
+#else
+ char new_char = '/';
+#endif
+
+ len = StrLen(path);
+ for (i = 0;i < len;i++)
+ {
+ if (path[i] == '\\' || path[i] == '/')
+ {
+ path[i] = new_char;
+ }
+ }
+}
+void ConvertPathW(wchar_t *path)
+{
+ UINT i, len;
+#ifdef PATH_BACKSLASH
+ wchar_t new_char = L'\\';
+#else
+ wchar_t new_char = L'/';
+#endif
+
+ len = UniStrLen(path);
+ for (i = 0;i < len;i++)
+ {
+ if (path[i] == L'\\' || path[i] == L'/')
+ {
+ path[i] = new_char;
+ }
+ }
+}
+
+// Delete the directory
+bool DeleteDir(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = DeleteDirW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool DeleteDirW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return DeleteDirInnerW(tmp);
+}
+bool DeleteDirInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = DeleteDirInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool DeleteDirInnerW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return OSDeleteDirW(name);
+}
+
+// Generation of internal file path
+void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (src[0] != L'@')
+ {
+ NormalizePathW(dst, size, src);
+ }
+ else
+ {
+ wchar_t dir[MAX_SIZE];
+ GetExeDirW(dir, sizeof(dir));
+ ConbinePathW(dst, size, dir, &src[1]);
+ }
+}
+void InnerFilePath(char *dst, UINT size, char *src)
+{
+ wchar_t dst_w[MAX_PATH];
+ wchar_t *src_w = CopyStrToUni(src);
+
+ InnerFilePathW(dst_w, sizeof(dst_w), src_w);
+
+ Free(src_w);
+
+ UniToStr(dst, size, dst_w);
+}
+
+// Recursive directory creation
+bool MakeDirEx(char *name)
+{
+ bool ret;
+ wchar_t *name_w = CopyStrToUni(name);
+
+ ret = MakeDirExW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirExW(wchar_t *name)
+{
+ LIST *o;
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ o = NewListFast(NULL);
+
+ UniStrCpy(tmp, sizeof(tmp), name);
+ while (true)
+ {
+ wchar_t *s = CopyUniStr(tmp);
+
+ Add(o, s);
+
+ GetDirNameFromFilePathW(tmp2, sizeof(tmp2), tmp);
+
+ if (UniStrCmpi(tmp2, tmp) == 0)
+ {
+ break;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT j = LIST_NUM(o) - i - 1;
+ wchar_t *s = LIST_DATA(o, j);
+
+ if (UniStrCmpi(s, L"\\") != 0 && UniStrCmpi(s, L"/") != 0)
+ {
+ ret = MakeDirW(s);
+ }
+ }
+
+ UniFreeStrList(o);
+
+ return ret;
+}
+
+// Create a directory
+bool MakeDir(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = MakeDirW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return MakeDirInnerW(tmp);
+}
+bool MakeDirInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = MakeDirInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirInnerW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return OSMakeDirW(name);
+}
+
+// Delete the file
+bool FileDelete(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = FileDeleteW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool FileDeleteW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return FileDeleteInnerW(tmp);
+}
+bool FileDeleteInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = FileDeleteInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool FileDeleteInnerW(wchar_t *name)
+{
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ return OSFileDeleteW(name2);
+}
+
+// Seek the file
+bool FileSeek(IO *o, UINT mode, int offset)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileSeek(o->pData, mode, offset);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Get the file size by specifying the file name
+UINT FileSizeEx(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ UINT ret = FileSizeExW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+UINT FileSizeExW(wchar_t *name)
+{
+ IO *io;
+ UINT size;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ io = FileOpenW(name, false);
+ if (io == NULL)
+ {
+ return 0;
+ }
+
+ size = FileSize(io);
+
+ FileClose(io);
+
+ return size;
+}
+
+// Get the file size
+UINT64 FileSize64(IO *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileSize(o->pData);
+ }
+ else
+ {
+ return (UINT64)o->HamBuf->Size;
+ }
+}
+UINT FileSize(IO *o)
+{
+ UINT64 size = (UINT)(FileSize64(o));
+
+ if (size >= 4294967296ULL)
+ {
+ size = 4294967295ULL;
+ }
+
+ return (UINT)size;
+}
+
+// Read from a file
+bool FileRead(IO *o, void *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_IO_READ_COUNT);
+ KS_ADD(KS_IO_TOTAL_READ_SIZE, size);
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileRead(o->pData, buf, size);
+ }
+ else
+ {
+ return ReadBuf(o->HamBuf, buf, size) == size ? true : false;
+ }
+}
+
+// Write to a file
+bool FileWrite(IO *o, void *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+ if (o->WriteMode == false)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_IO_WRITE_COUNT);
+ KS_ADD(KS_IO_TOTAL_WRITE_SIZE, size);
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ return OSFileWrite(o->pData, buf, size);
+}
+
+// Flush the file
+void FileFlush(IO *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->HamMode)
+ {
+ return;
+ }
+
+ OSFileFlush(o->pData);
+}
+
+// Close the file
+void FileClose(IO *o)
+{
+ FileCloseEx(o, false);
+}
+void FileCloseEx(IO *o, bool no_flush)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->HamMode == false)
+ {
+ if (o->WriteMode)
+ {
+#ifdef OS_WIN32
+ Win32FileSetDate(o->pData, o->SetCreateTime, o->SetUpdateTime);
+#endif // OS_WIN32
+ }
+
+ OSFileClose(o->pData, no_flush);
+ }
+ else
+ {
+ FreeBuf(o->HamBuf);
+ }
+ Free(o);
+
+ // KS
+ KS_INC(KS_IO_CLOSE_COUNT);
+}
+
+// Create a file
+IO *FileCreateInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileCreateInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileCreateInnerW(wchar_t *name)
+{
+ IO *o;
+ void *p;
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ p = OSFileCreateW(name2);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(IO));
+ o->pData = p;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name2);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->WriteMode = true;
+
+ // KS
+ KS_INC(KS_IO_CREATE_COUNT);
+
+ return o;
+}
+IO *FileCreate(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileCreateW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileCreateW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return FileCreateInnerW(tmp);
+}
+
+// Write all the data to the file
+bool FileWriteAll(char *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreate(name);
+
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileWrite(io, data, size);
+
+ FileClose(io);
+
+ return true;
+}
+bool FileWriteAllW(wchar_t *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreateW(name);
+
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileWrite(io, data, size);
+
+ FileClose(io);
+
+ return true;
+}
+
+// Open the file
+IO *FileOpenInner(char *name, bool write_mode, bool read_lock)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileOpenInnerW(name_w, write_mode, read_lock);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ IO *o;
+ void *p;
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ p = OSFileOpenW(name2, write_mode, read_lock);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(IO));
+ o->pData = p;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name2);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->WriteMode = write_mode;
+
+#ifdef OS_WIN32
+ Win32FileGetDate(p, &o->GetCreateTime, &o->GetUpdateTime, &o->GetAccessTime);
+#endif // OS_WIN32
+
+ // KS
+ KS_INC(KS_IO_OPEN_COUNT);
+
+ return o;
+}
+IO *FileOpen(char *name, bool write_mode)
+{
+ return FileOpenEx(name, write_mode, true);
+}
+IO *FileOpenW(wchar_t *name, bool write_mode)
+{
+ return FileOpenExW(name, write_mode, true);
+}
+IO *FileOpenEx(char *name, bool write_mode, bool read_lock)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileOpenExW(name_w, write_mode, read_lock);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ if (name[0] == L'|')
+ {
+ IO *o = ZeroMalloc(sizeof(IO));
+ name++;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->HamMode = true;
+ o->HamBuf = ReadHamcoreW(name);
+ if (o->HamBuf == NULL)
+ {
+ Free(o);
+ return NULL;
+ }
+ return o;
+ }
+ else
+ {
+ return FileOpenInnerW(tmp, write_mode, read_lock);
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/FileIO.h b/src/Mayaqua/FileIO.h
new file mode 100644
index 00000000..91fae2ac
--- /dev/null
+++ b/src/Mayaqua/FileIO.h
@@ -0,0 +1,354 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// FileIO.h
+// Header of FileIO.c
+
+#ifndef FILEIO_H
+#define FILEIO_H
+
+// Constant
+#define HAMCORE_DIR_NAME "hamcore"
+#define HAMCORE_FILE_NAME "hamcore.se2"
+#define HAMCORE_FILE_NAME_2 "_hamcore.se2"
+#define HAMCORE_TEXT_NAME "hamcore.txt"
+#define HAMCORE_HEADER_DATA "HamCore"
+#define HAMCORE_HEADER_SIZE 7
+#define HAMCORE_CACHE_EXPIRES (5 * 60 * 1000)
+
+// IO structure
+struct IO
+{
+ char Name[MAX_SIZE];
+ wchar_t NameW[MAX_SIZE];
+ void *pData;
+ bool WriteMode;
+ bool HamMode;
+ BUF *HamBuf;
+ UINT64 SetUpdateTime, SetCreateTime;
+ UINT64 GetUpdateTime, GetCreateTime, GetAccessTime;
+};
+
+// HC structure
+typedef struct HC
+{
+ char *FileName; // File name
+ UINT Size; // File size
+ UINT SizeCompressed; // Compressed file size
+ UINT Offset; // Offset
+ void *Buffer; // Buffer
+ UINT64 LastAccess; // Access Date
+} HC;
+
+// DIRENT structure
+struct DIRENT
+{
+ bool Folder; // Folder
+ char *FileName; // File name (ANSI)
+ wchar_t *FileNameW; // File name (Unicode)
+ UINT64 FileSize; // File size
+ UINT64 CreateDate; // Creation Date
+ UINT64 UpdateDate; // Updating date
+};
+
+// DIRLIST structure
+struct DIRLIST
+{
+ UINT NumFiles; // Number of files
+ struct DIRENT **File; // File array
+};
+
+// ZIP related structure
+#ifdef OS_WIN32
+#pragma pack(push, 1)
+#endif // OS_WIN32
+
+struct ZIP_DATA_HEADER
+{
+ UINT Signature;
+ USHORT NeedVer;
+ USHORT Option;
+ USHORT CompType;
+ USHORT FileTime;
+ USHORT FileDate;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+ USHORT FileNameLen;
+ USHORT ExtraLen;
+} GCC_PACKED;
+
+struct ZIP_DATA_FOOTER
+{
+ UINT Signature;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+} GCC_PACKED;
+
+struct ZIP_DIR_HEADER
+{
+ UINT Signature;
+ USHORT MadeVer;
+ USHORT NeedVer;
+ USHORT Option;
+ USHORT CompType;
+ USHORT FileTime;
+ USHORT FileDate;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+ USHORT FileNameLen;
+ USHORT ExtraLen;
+ USHORT CommentLen;
+ USHORT DiskNum;
+ USHORT InAttr;
+ UINT OutAttr;
+ UINT HeaderPos;
+} GCC_PACKED;
+
+struct ZIP_END_HEADER
+{
+ UINT Signature;
+ USHORT DiskNum;
+ USHORT StartDiskNum;
+ USHORT DiskDirEntry;
+ USHORT DirEntry;
+ UINT DirSize;
+ UINT StartPos;
+ USHORT CommentLen;
+} GCC_PACKED;
+
+#define ZIP_SIGNATURE 0x04034B50
+#define ZIP_SIGNATURE_END 0x06054B50
+#define ZIP_VERSION 10
+#define ZIP_VERSION_WITH_COMPRESS 20
+
+#ifdef OS_WIN32
+#pragma pack(pop)
+#endif // OS_WIN32
+
+struct ZIP_FILE
+{
+ char Name[MAX_PATH];
+ UINT Size;
+ UINT64 DateTime;
+ UINT Attributes;
+ UINT CurrentSize;
+ UINT CompressSize;
+ UINT Crc32;
+ UINT HeaderPos;
+};
+
+struct ZIP_PACKER
+{
+ FIFO *Fifo;
+ LIST *FileList;
+ ZIP_FILE *CurrentFile;
+};
+
+void InitCrc32();
+UINT Crc32(void *buf, UINT pos, UINT len);
+UINT Crc32First(void *buf, UINT pos, UINT len);
+UINT Crc32Next(void *buf, UINT pos, UINT len, UINT last_crc32);
+UINT Crc32Finish(UINT last_crc32);
+void WriteZipDataHeader(ZIP_FILE *f, ZIP_DATA_HEADER *h, bool write_sizes);
+void WriteZipDataFooter(ZIP_FILE *f, ZIP_DATA_FOOTER *h);
+ZIP_PACKER *NewZipPacker();
+void FreeZipPacker(ZIP_PACKER *p);
+void ZipAddFileSimple(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, void *data, UINT size);
+bool ZipAddRealFileW(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, wchar_t *srcname);
+bool ZipAddRealFile(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, char *srcname);
+void ZipAddFileStart(ZIP_PACKER *p, char *name, UINT size, UINT64 dt, UINT attribute);
+UINT ZipAddFileData(ZIP_PACKER *p, void *data, UINT pos, UINT len);
+void ZipAddFileFooter(ZIP_PACKER *p);
+FIFO *ZipFinish(ZIP_PACKER *p);
+bool ZipWriteW(ZIP_PACKER *p, wchar_t *name);
+
+bool DeleteDirInner(char *name);
+bool DeleteDirInnerW(wchar_t *name);
+bool DeleteDir(char *name);
+bool DeleteDirW(wchar_t *name);
+bool MakeDirInner(char *name);
+bool MakeDirInnerW(wchar_t *name);
+bool MakeDir(char *name);
+bool MakeDirW(wchar_t *name);
+bool MakeDirEx(char *name);
+bool MakeDirExW(wchar_t *name);
+bool FileDeleteInner(char *name);
+bool FileDeleteInnerW(wchar_t *name);
+bool FileDelete(char *name);
+bool FileDeleteW(wchar_t *name);
+bool FileSeek(IO *o, UINT mode, int offset);
+UINT FileSize(IO *o);
+UINT64 FileSize64(IO *o);
+UINT FileSizeEx(char *name);
+UINT FileSizeExW(wchar_t *name);
+bool FileRead(IO *o, void *buf, UINT size);
+bool FileWrite(IO *o, void *buf, UINT size);
+void FileFlush(IO *o);
+void FileClose(IO *o);
+void FileCloseEx(IO *o, bool no_flush);
+void FileCloseAndDelete(IO *o);
+IO *FileCreateInner(char *name);
+IO *FileCreateInnerW(wchar_t *name);
+IO *FileCreate(char *name);
+IO *FileCreateW(wchar_t *name);
+bool FileWriteAll(char *name, void *data, UINT size);
+bool FileWriteAllW(wchar_t *name, void *data, UINT size);
+IO *FileOpenInner(char *name, bool write_mode, bool read_lock);
+IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock);
+IO *FileOpen(char *name, bool write_mode);
+IO *FileOpenW(wchar_t *name, bool write_mode);
+IO *FileOpenEx(char *name, bool write_mode, bool read_lock);
+IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock);
+void ConvertPath(char *path);
+void ConvertPathW(wchar_t *path);
+bool FileRenameInner(char *old_name, char *new_name);
+bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name);
+bool FileRename(char *old_name, char *new_name);
+bool FileRenameW(wchar_t *old_name, wchar_t *new_name);
+void NormalizePath(char *dst, UINT size, char *src);
+void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src);
+TOKEN_LIST *ParseSplitedPath(char *path);
+UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path);
+char *GetCurrentPathEnvStr();
+bool IsFileExistsInner(char *name);
+bool IsFileExistsInnerW(wchar_t *name);
+bool IsFileExists(char *name);
+bool IsFileExistsW(wchar_t *name);
+void InnerFilePath(char *dst, UINT size, char *src);
+void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src);
+void ConbinePath(char *dst, UINT size, char *dirname, char *filename);
+void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename);
+void CombinePath(char *dst, UINT size, char *dirname, char *filename);
+void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename);
+void GetDirNameFromFilePath(char *dst, UINT size, char *filepath);
+void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath);
+void GetFileNameFromFilePath(char *dst, UINT size, char *filepath);
+void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath);
+void MakeSafeFileName(char *dst, UINT size, char *src);
+void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src);
+void InitGetExeName(char *arg);
+void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg);
+void GetExeName(char *name, UINT size);
+void GetExeNameW(wchar_t *name, UINT size);
+void GetExeDir(char *name, UINT size);
+void GetExeDirW(wchar_t *name, UINT size);
+void BuildHamcore();
+int CompareHamcore(void *p1, void *p2);
+void InitHamcore();
+void FreeHamcore();
+BUF *ReadHamcore(char *name);
+BUF *ReadHamcoreW(wchar_t *filename);
+void SafeFileName(char *name);
+void SafeFileNameW(wchar_t *name);
+void UniSafeFileName(wchar_t *name);
+DIRLIST *EnumDir(char *dirname);
+DIRLIST *EnumDirW(wchar_t *dirname);
+DIRLIST *EnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare);
+void FreeDir(DIRLIST *d);
+int CompareDirListByName(void *p1, void *p2);
+bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+void ConvertSafeFileName(char *dst, UINT size, char *src);
+void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src);
+bool FileReplaceRename(char *old_name, char *new_name);
+bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name);
+bool IsFile(char *name);
+bool IsFileW(wchar_t *name);
+void GetCurrentDirW(wchar_t *name, UINT size);
+void GetCurrentDir(char *name, UINT size);
+bool SaveFileW(wchar_t *name, void *data, UINT size);
+bool SaveFile(char *name, void *data, UINT size);
+bool IsFileWriteLockedW(wchar_t *name);
+bool IsFileWriteLocked(char *name);
+bool IsInLines(BUF *buf, char *str, bool instr);
+bool IsInLinesFile(wchar_t *filename, char *str, bool instr);
+
+#endif // FILEIO_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Internat.c b/src/Mayaqua/Internat.c
new file mode 100644
index 00000000..93392f93
--- /dev/null
+++ b/src/Mayaqua/Internat.c
@@ -0,0 +1,3483 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Internat.c
+// String conversion library for internationalization
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+extern LOCK *token_lock;
+static char charset[MAX_SIZE] = "EUCJP";
+static LOCK *iconv_lock = NULL;
+void *iconv_cache_wide_to_str = 0;
+void *iconv_cache_str_to_wide = 0;
+
+// Initialize the string
+void ClearUniStr(wchar_t *str, UINT str_size)
+{
+ UniStrCpy(str, str_size, L"");
+}
+
+// Examine whether the string contains the specified character
+bool UniInChar(wchar_t *string, wchar_t c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (string == NULL)
+ {
+ return false;
+ }
+
+ len = UniStrLen(string);
+
+ for (i = 0;i < len;i++)
+ {
+ if (string[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Check whether the string is included
+bool UniInStr(wchar_t *str, wchar_t *keyword)
+{
+ return UniInStrEx(str, keyword, false);
+}
+bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive)
+{
+ // Validate arguments
+ if (UniIsEmptyStr(str) || UniIsEmptyStr(keyword))
+ {
+ return false;
+ }
+
+ if (UniSearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert to binary data
+BUF *UniStrToBin(wchar_t *str)
+{
+ char *str_a = CopyUniToStr(str);
+ BUF *ret;
+
+ ret = StrToBin(str_a);
+
+ Free(str_a);
+
+ return ret;
+}
+
+// Generate a sequence of specified characters
+wchar_t *UniMakeCharArray(wchar_t c, UINT count)
+{
+ UINT i;
+ wchar_t *ret = Malloc(sizeof(wchar_t) * (count + 1));
+
+ for (i = 0;i < count;i++)
+ {
+ ret[i] = c;
+ }
+
+ ret[count] = 0;
+
+ return ret;
+}
+
+// Check whether the character is safe
+bool UniIsSafeChar(wchar_t c)
+{
+ UINT i, len;
+ wchar_t *check_str =
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ L"abcdefghijklmnopqrstuvwxyz"
+ L"0123456789"
+ L" ()-_#%&.";
+
+ len = UniStrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Convert the token list to a string list
+LIST *UniTokenListToList(UNI_TOKEN_LIST *t)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ Insert(o, UniCopyStr(t->Token[i]));
+ }
+
+ return o;
+}
+
+// Convert a string list to a token list
+UNI_TOKEN_LIST *UniListToTokenList(LIST *o)
+{
+ UINT i;
+ UNI_TOKEN_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = UniCopyStr(LIST_DATA(o, i));
+ }
+
+ return t;
+}
+
+// Free the string list
+void UniFreeStrList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ Free(s);
+ }
+
+ ReleaseList(o);
+}
+
+// Convert the string list to a string
+BUF *UniStrListToStr(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ wchar_t c;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ WriteBuf(b, s, UniStrSize(s));
+ }
+
+ c = 0;
+ WriteBuf(b, &c, sizeof(c));
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert a (NULL delimited) string to list
+LIST *UniStrToStrList(wchar_t *str, UINT size)
+{
+ LIST *o;
+ wchar_t *tmp;
+ UINT tmp_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ i = 0;
+ while (true)
+ {
+ if (i >= size)
+ {
+ break;
+ }
+ if (*str == 0)
+ {
+ break;
+ }
+
+ tmp_size = UniStrSize(str);
+ tmp = ZeroMalloc(tmp_size);
+ UniStrCpy(tmp, tmp_size, str);
+ Add(o, tmp);
+ str += UniStrLen(str) + 1;
+ i++;
+ }
+
+ return o;
+}
+
+// Normalize the line breaks
+wchar_t *UniNormalizeCrlf(wchar_t *str)
+{
+ wchar_t *ret;
+ UINT ret_size, i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+ ret_size = sizeof(wchar_t) * (len + 32) * 2;
+ ret = Malloc(ret_size);
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = str[i];
+
+ switch (c)
+ {
+ case L'\r':
+ if (str[i + 1] == L'\n')
+ {
+ i++;
+ }
+ ret[wp++] = L'\r';
+ ret[wp++] = L'\n';
+ break;
+
+ case L'\n':
+ ret[wp++] = L'\r';
+ ret[wp++] = L'\n';
+ break;
+
+ default:
+ ret[wp++] = c;
+ break;
+ }
+ }
+
+ ret[wp++] = 0;
+
+ return ret;
+}
+
+// Check whether str ends with the key
+bool UniEndWith(wchar_t *str, wchar_t *key)
+{
+ UINT str_len;
+ UINT key_len;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = UniStrLen(str);
+ key_len = UniStrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+
+ if (UniStrCmpi(str + (str_len - key_len), key) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Check whether str starts with the key
+bool UniStartWith(wchar_t *str, wchar_t *key)
+{
+ UINT str_len;
+ UINT key_len;
+ wchar_t *tmp;
+ bool ret;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = UniStrLen(str);
+ key_len = UniStrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+ if (str_len == 0 || key_len == 0)
+ {
+ return false;
+ }
+ tmp = CopyUniStr(str);
+ tmp[key_len] = 0;
+
+ if (UniStrCmpi(tmp, key) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the integer to a comma-separated string
+void UniToStr3(wchar_t *str, UINT size, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr3(tmp, sizeof(tmp), value);
+
+ StrToUni(str, size, tmp);
+}
+
+// Format of the string (internal function)
+wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode)
+{
+ UINT i, len;
+ wchar_t *tmp;
+ UINT tmp_size;
+ LIST *o;
+ UINT mode = 0;
+ UINT wp;
+ UINT total_size;
+ wchar_t *ret;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(fmt);
+ tmp_size = UniStrSize(fmt);
+ tmp = Malloc(tmp_size);
+
+ o = NewListFast(NULL);
+
+ mode = 0;
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = fmt[i];
+
+ if (mode == 0)
+ {
+ // Normal character mode
+ switch (c)
+ {
+ case L'%':
+ // The start of the format specification
+ if (fmt[i + 1] == L'%')
+ {
+ // If the next character is also '%', output a '%' simply
+ i++;
+ tmp[wp++] = c;
+ }
+ else
+ {
+ // Shift the state if the next character is not a '%'
+ mode = 1;
+ tmp[wp++] = 0;
+ wp = 0;
+ Add(o, CopyUniStr(tmp));
+ tmp[wp++] = c;
+ }
+ break;
+ default:
+ // Ordinary character
+ tmp[wp++] = c;
+ break;
+ }
+ }
+ else
+ {
+ char *tag;
+ char dst[MAX_SIZE];
+ wchar_t *target_str;
+ wchar_t *padding_str;
+ bool left_padding;
+ UINT target_str_len;
+ UINT total_len;
+ wchar_t *output_str;
+ UINT padding;
+ // Formatting mode
+ switch (c)
+ {
+ case L'c':
+ case L'C':
+ case L'd':
+ case L'i':
+ case L'o':
+ case L'u':
+ case L'x':
+ case L'X':
+ // int type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = CopyUniToStr(tmp);
+
+ #ifdef OS_WIN32
+ ReplaceStrEx(tag, 0, tag, "ll", "I64", false);
+ #else // OS_WIN32
+ ReplaceStrEx(tag, 0, tag, "I64", "ll", false);
+ #endif // OS_WIN32
+
+ if ((UniStrLen(tmp) >= 5 && tmp[UniStrLen(tmp) - 4] == L'I' &&
+ tmp[UniStrLen(tmp) - 3] == L'6' &&
+ tmp[UniStrLen(tmp) - 2] == L'4') ||
+ (
+ UniStrLen(tmp) >= 4 && tmp[UniStrLen(tmp) - 3] == L'l' &&
+ tmp[UniStrLen(tmp) - 2] == L'l'))
+ {
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
+ #endif // OS_WIN32
+ }
+ else
+ {
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, int));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, int));
+ #endif // OS_WIN32
+ }
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'e':
+ case L'E':
+ case L'f':
+ case L'g':
+ case L'G':
+ // Double type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = CopyUniToStr(tmp);
+
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, double));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, double));
+ #endif // OS_WIN32
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'n':
+ case L'p':
+ // Pointer type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = ZeroMalloc(UniStrSize(tmp) + 32);
+ UniToStr(tag, 0, tmp);
+
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
+ #endif // OS_WIN32
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'r':
+ case L'R':
+ // IP address type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+
+ Zero(dst, sizeof(dst));
+ IPToStr(dst, sizeof(dst), va_arg(args, void *));
+
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+
+ case L's':
+ case L'S':
+ // String type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+
+ if (ansi_mode == false)
+ {
+ if (c == L'S')
+ {
+ c = L's';
+ }
+ else
+ {
+ c = L'S';
+ }
+ }
+
+ if (c == L's')
+ {
+ target_str = CopyStrToUni(va_arg(args, char *));
+ }
+ else
+ {
+ target_str = CopyUniStr(va_arg(args, wchar_t *));
+ }
+
+ if (target_str == NULL)
+ {
+ target_str = CopyUniStr(L"(null)");
+ }
+
+ padding = 0;
+ left_padding = false;
+ if (tmp[1] == L'-')
+ {
+ // Left aligned
+ if (UniStrLen(tmp) >= 3)
+ {
+ padding = UniToInt(&tmp[2]);
+ }
+ left_padding = true;
+ }
+ else
+ {
+ // Right aligned
+ if (UniStrLen(tmp) >= 2)
+ {
+ padding = UniToInt(&tmp[1]);
+ }
+ }
+
+ target_str_len = UniStrWidth(target_str);
+
+ if (padding > target_str_len)
+ {
+ UINT len = padding - target_str_len;
+ UINT i;
+ padding_str = ZeroMalloc(sizeof(wchar_t) * (len + 1));
+ for (i = 0;i < len;i++)
+ {
+ padding_str[i] = L' ';
+ }
+ }
+ else
+ {
+ padding_str = ZeroMalloc(sizeof(wchar_t));
+ }
+
+ total_len = sizeof(wchar_t) * (UniStrLen(padding_str) + UniStrLen(target_str) + 1);
+ output_str = ZeroMalloc(total_len);
+ output_str[0] = 0;
+
+ if (left_padding == false)
+ {
+ UniStrCat(output_str, total_len, padding_str);
+ }
+ UniStrCat(output_str, total_len, target_str);
+ if (left_padding)
+ {
+ UniStrCat(output_str, total_len, padding_str);
+ }
+
+ Add(o, output_str);
+
+ Free(target_str);
+ Free(padding_str);
+
+ wp = 0;
+ mode = 0;
+ break;
+ default:
+ // Normal string
+ tmp[wp++] = c;
+ break;
+ }
+ }
+ }
+ tmp[wp++] = 0;
+ wp = 0;
+
+ if (UniStrLen(tmp) >= 1)
+ {
+ Add(o, CopyUniStr(tmp));
+ }
+
+ total_size = sizeof(wchar_t);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ total_size += UniStrLen(s) * sizeof(wchar_t);
+ }
+
+ ret = ZeroMalloc(total_size);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ UniStrCat(ret, total_size, s);
+ Free(s);
+ }
+
+ ReleaseList(o);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the width of the string
+UINT UniStrWidth(wchar_t *str)
+{
+ UINT i, len, ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] <= 255)
+ {
+ ret++;
+ }
+ else
+ {
+ ret += 2;
+ }
+ }
+ return ret;
+}
+
+// Display a dump of Unicode string
+void DumpUniStr(wchar_t *str)
+{
+ UINT i, len;
+ char *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ s = CopyUniToStr(str);
+
+ Print("DumpUniStr: %s\n ", s);
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ Print("0x%04X ", str[i]);
+ }
+ Print("\n");
+
+ Free(s);
+}
+
+// Display the dump of the string
+void DumpStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ Print("DumpStr: %s\n ", str);
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ Print("0x%02X ", str[i]);
+ }
+ Print("\n");
+}
+
+// Convert string of 2 byte/character to wchar_t of 4 byte/character
+wchar_t *Utf16ToWide(USHORT *str)
+{
+ wchar_t *ret;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = 0;
+ while (true)
+ {
+ if (str[len] == 0)
+ {
+ break;
+ }
+ len++;
+ }
+
+ ret = Malloc((len + 1) * sizeof(wchar_t));
+ for (i = 0;i < len + 1;i++)
+ {
+ ret[i] = (wchar_t)str[i];
+ }
+
+ return ret;
+}
+
+// Convert wchar_t string of 4 byte/character to string of 2 byte/character
+USHORT *WideToUtf16(wchar_t *str)
+{
+ USHORT *ret;
+ UINT len;
+ UINT ret_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+
+ ret_size = (len + 1) * 2;
+ ret = Malloc(ret_size);
+
+ for (i = 0;i < len + 1;i++)
+ {
+ ret[i] = (USHORT)str[i];
+ }
+
+ return ret;
+}
+
+// Initialization of the International Library
+void InitInternational()
+{
+#ifdef OS_UNIX
+ void *d;
+
+ if (iconv_lock != NULL)
+ {
+ return;
+ }
+
+ GetCurrentCharSet(charset, sizeof(charset));
+ d = IconvWideToStrInternal();
+ if (d == (void *)-1)
+ {
+#ifdef UNIX_MACOS
+ StrCpy(charset, sizeof(charset), "utf-8");
+#else // UNIX_MACOS
+ StrCpy(charset, sizeof(charset), "EUCJP");
+#endif // UNIX_MACOS
+ d = IconvWideToStrInternal();
+ if (d == (void *)-1)
+ {
+ StrCpy(charset, sizeof(charset), "US");
+ }
+ else
+ {
+ IconvFreeInternal(d);
+ }
+ }
+ else
+ {
+ IconvFreeInternal(d);
+ }
+
+ iconv_lock = NewLockMain();
+
+ iconv_cache_wide_to_str = IconvWideToStrInternal();
+ iconv_cache_str_to_wide = IconvStrToWideInternal();
+#endif // OS_UNIX
+}
+
+// Release of the International Library
+void FreeInternational()
+{
+#ifdef OS_UNIX
+#endif // OS_UNIX
+}
+
+#ifdef OS_UNIX
+
+// Calculate the size when the string converted to Unicode
+UINT UnixCalcStrToUni(char *str)
+{
+ wchar_t *tmp;
+ UINT len, tmp_size;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ len = StrLen(str);
+ tmp_size = len * 5 + 10;
+ tmp = ZeroMalloc(tmp_size);
+ UnixStrToUni(tmp, tmp_size, str);
+ ret = UniStrLen(tmp);
+ Free(tmp);
+
+ return (ret + 1) * sizeof(wchar_t);
+}
+
+// Convert the strings to Unicode
+UINT UnixStrToUni(wchar_t *s, UINT size, char *str)
+{
+ void *d;
+ char *inbuf;
+ size_t insize;
+ char *outbuf;
+ char *outbuf_orig;
+ size_t outsize;
+ wchar_t *tmp;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ d = IconvStrToWide();
+ if (d == (void *)-1)
+ {
+ UniStrCpy(s, size, L"");
+ return 0;
+ }
+
+ inbuf = (char *)str;
+ insize = StrLen(str) + 1;
+ outsize = insize * 5 + 10;
+ outbuf_orig = outbuf = ZeroMalloc(outsize);
+
+ if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
+ {
+ Free(outbuf_orig);
+ UniStrCpy(s, size, L"");
+ IconvFree(d);
+ return 0;
+ }
+
+ tmp = Utf16ToWide((USHORT *)outbuf_orig);
+ Free(outbuf_orig);
+
+ UniStrCpy(s, size, tmp);
+ IconvFree(d);
+
+ Free(tmp);
+
+ return UniStrLen(s);
+}
+
+// Calculate the size when the Unicode converted to string
+UINT UnixCalcUniToStr(wchar_t *s)
+{
+ char *tmp;
+ UINT tmp_size;
+ UINT ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ tmp_size = UniStrLen(s) * 5 + 10;
+ tmp = ZeroMalloc(tmp_size);
+ UnixUniToStr(tmp, tmp_size, s);
+
+ ret = StrSize(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Converted a Unicode string to a string
+UINT UnixUniToStr(char *str, UINT size, wchar_t *s)
+{
+ USHORT *tmp;
+ char *inbuf;
+ size_t insize;
+ char *outbuf;
+ char *outbuf_orig;
+ size_t outsize;
+ void *d;
+ // Validate arguments
+ if (str == NULL || s == NULL)
+ {
+ return 0;
+ }
+
+ // Convert a wchar_t string to sequence of 2-bytes first
+ tmp = WideToUtf16(s);
+ inbuf = (char *)tmp;
+ insize = (UniStrLen(s) + 1) * 2;
+ outsize = insize * 5 + 10;
+ outbuf_orig = outbuf = ZeroMalloc(outsize);
+
+ d = IconvWideToStr();
+ if (d == (void *)-1)
+ {
+ StrCpy(str, size, "");
+ Free(outbuf);
+ Free(tmp);
+ return 0;
+ }
+
+ if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
+ {
+ Free(outbuf_orig);
+ IconvFree(d);
+ StrCpy(str, size, "");
+ Free(tmp);
+ return 0;
+ }
+
+ StrCpy(str, size, outbuf_orig);
+
+ Free(outbuf_orig);
+ IconvFree(d);
+ Free(tmp);
+
+ return StrLen(str);
+}
+
+// Converted the whcar_t to char
+void *IconvWideToStrInternal()
+{
+ return (void *)iconv_open(charset, IsBigEndian() ? "UTF-16BE" : "UTF-16LE");
+}
+
+// Convert the char to a wchar_t
+void *IconvStrToWideInternal()
+{
+ return (void *)iconv_open(IsBigEndian() ? "UTF-16BE" : "UTF-16LE", charset);
+}
+
+// Close the handle
+int IconvFreeInternal(void *d)
+{
+ iconv_close((iconv_t)d);
+ return 0;
+}
+
+void *IconvWideToStr()
+{
+ if (iconv_cache_wide_to_str == (void *)-1)
+ {
+ return (void *)-1;
+ }
+
+ Lock(iconv_lock);
+
+ return iconv_cache_wide_to_str;
+}
+
+void *IconvStrToWide()
+{
+ if (iconv_cache_str_to_wide == (void *)-1)
+ {
+ return (void *)-1;
+ }
+
+ Lock(iconv_lock);
+
+ return iconv_cache_str_to_wide;
+}
+
+int IconvFree(void *d)
+{
+ Unlock(iconv_lock);
+
+ return 0;
+}
+
+// Get the character set that is currently used from the environment variable
+void GetCurrentCharSet(char *name, UINT size)
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ if (GetEnv("LANG", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
+ {
+ Zero(tmp, sizeof(tmp));
+ if (GetEnv("LOCATION", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
+ {
+ StrCpy(tmp, sizeof(tmp), "C");
+ }
+ }
+
+ Trim(tmp);
+
+ t = ParseToken(tmp, ".");
+ if (t->NumTokens >= 2)
+ {
+ StrCpy(name, size, t->Token[1]);
+ }
+ else
+ {
+ if (t->NumTokens == 1)
+ {
+ StrCpy(name, size, t->Token[0]);
+ }
+ else
+ {
+ StrCpy(name, size, "eucJP");
+ }
+ }
+ FreeToken(t);
+
+ StrUpper(name);
+}
+
+#endif // OS_UNIX
+
+// Check whether the specified string is a space
+bool UniIsEmptyStr(wchar_t *str)
+{
+ return IsEmptyUniStr(str);
+}
+bool IsEmptyUniStr(wchar_t *str)
+{
+ bool ret;
+ wchar_t *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return true;
+ }
+
+ s = UniCopyStr(str);
+
+ UniTrim(s);
+ if (UniStrLen(s) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(s);
+
+ return ret;
+}
+
+// Check whether the specified string is a number
+bool UniIsNum(wchar_t *str)
+{
+ char tmp[MAX_SIZE];
+
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return IsNum(tmp);
+}
+
+
+// Empty Unicode token list
+UNI_TOKEN_LIST *UniNullToken()
+{
+ UNI_TOKEN_LIST *ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Empty Unicode token list (Alias)
+UNI_TOKEN_LIST *NullUniToken()
+{
+ return UniNullToken();
+}
+
+// Convert the token list to Unicode token list
+UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src)
+{
+ UNI_TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyStrToUni(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Convert a Unicode token list to a token list
+TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyUniToStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Unicode string copy
+wchar_t *UniCopyStr(wchar_t *str)
+{
+ return CopyUniStr(str);
+}
+
+// Copy the token list
+UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src)
+{
+ UNI_TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyUniStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Parse the command line string
+UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str)
+{
+ UNI_TOKEN_LIST *t;
+ LIST *o;
+ UINT i, len, wp, mode;
+ wchar_t c;
+ wchar_t *tmp;
+ bool ignore_space = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ // There is no token
+ return UniNullToken();
+ }
+
+ o = NewListFast(NULL);
+ tmp = Malloc(UniStrSize(str) + 32);
+
+ wp = 0;
+ mode = 0;
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ // Mode to discover the next token
+ if (c == L' ' || c == L'\t')
+ {
+ // Advance to the next character
+ }
+ else
+ {
+ // Start of the token
+ if (c == L'\"')
+ {
+ if (str[i + 1] == L'\"')
+ {
+ // Regarded "" as a single " character
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ // Single "(double-quote) enables the flag to ignore space
+ ignore_space = true;
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+
+ mode = 1;
+ }
+ break;
+
+ case 1:
+ if (ignore_space == false && (c == L' ' || c == L'\t'))
+ {
+ // End of the token
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, UniCopyStr(tmp));
+ mode = 0;
+ }
+ else
+ {
+ if (c == L'\"')
+ {
+ if (str[i + 1] == L'\"')
+ {
+ // Regarded "" as a single " character
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ if (ignore_space == false)
+ {
+ // Single "(double-quote) enables the flag to ignore space
+ ignore_space = true;
+ }
+ else
+ {
+ // Disable the flag to ignore space
+ ignore_space = false;
+ }
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+ break;
+ }
+ }
+
+ if (wp != 0)
+ {
+ tmp[wp++] = 0;
+ Insert(o, UniCopyStr(tmp));
+ }
+
+ Free(tmp);
+
+ t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Convert Unicode string to 64bit integer
+UINT64 UniToInt64(wchar_t *str)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInt64(tmp);
+}
+
+// Convert a 64-bit integer to a Unicode string
+void UniToStr64(wchar_t *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr64(tmp, value);
+
+ StrToUni(str, 0, tmp);
+}
+
+// Convert an ANSI string to UTF
+UINT StrToUtf(char *utfstr, UINT size, char *str)
+{
+ char *tmp;
+ // Validate arguments
+ if (utfstr == NULL || str == NULL)
+ {
+ StrCpy(utfstr, size, "");
+ return 0;
+ }
+
+ tmp = CopyStrToUtf(str);
+
+ StrCpy(utfstr, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(utfstr);
+}
+
+// Convert an UTF string to an ANSI string
+UINT UtfToStr(char *str, UINT size, char *utfstr)
+{
+ char *tmp;
+ // Validate arguments
+ if (str == NULL || utfstr == NULL)
+ {
+ StrCpy(str, size, "");
+ return 0;
+ }
+
+ tmp = CopyUtfToStr(utfstr);
+
+ StrCpy(str, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(str);
+}
+
+// Convert the Unicode string to the UTF string
+UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr)
+{
+ char *tmp;
+ // Validate arguments
+ if (utfstr == NULL || unistr == NULL)
+ {
+ StrCpy(utfstr, size, "");
+ return 0;
+ }
+
+ tmp = CopyUniToStr(unistr);
+
+ StrCpy(utfstr, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(utfstr);
+}
+
+// Convert the UTF string to a Unicode string
+UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr)
+{
+ wchar_t *tmp;
+ // Validate arguments
+ if (unistr == NULL || utfstr == NULL)
+ {
+ UniStrCpy(unistr, size, L"");
+ return 0;
+ }
+
+ tmp = CopyUtfToUni(utfstr);
+
+ UniStrCpy(unistr, size, tmp);
+
+ Free(tmp);
+
+ return UniStrLen(unistr);
+}
+
+// Copy the UTF-8 string to a Unicode string
+wchar_t *CopyUtfToUni(char *utfstr)
+{
+ UINT size;
+ wchar_t *ret;
+ UINT utfstr_len;
+ // Validate arguments
+ if (utfstr == NULL)
+ {
+ return NULL;
+ }
+
+ utfstr_len = StrLen(utfstr);
+
+ size = CalcUtf8ToUni((BYTE *)utfstr, utfstr_len);
+ ret = ZeroMalloc(size + sizeof(wchar_t));
+ Utf8ToUni(ret, size, (BYTE *)utfstr, utfstr_len);
+
+ return ret;
+}
+
+// Copy the UTF8 string to the ANSI string
+char *CopyUtfToStr(char *utfstr)
+{
+ wchar_t *uni;
+ char *ret;
+ // Validate arguments
+ if (utfstr == NULL)
+ {
+ return NULL;
+ }
+
+ uni = CopyUtfToUni(utfstr);
+ if (uni == NULL)
+ {
+ return CopyStr("");
+ }
+
+ ret = CopyUniToStr(uni);
+
+ Free(uni);
+
+ return ret;
+}
+
+// Copy a Unicode string to ANSI string
+char *CopyUniToStr(wchar_t *unistr)
+{
+ char *str;
+ UINT str_size;
+ // Validate arguments
+ if (unistr == NULL)
+ {
+ return NULL;
+ }
+
+ str_size = CalcUniToStr(unistr);
+ if (str_size == 0)
+ {
+ return CopyStr("");
+ }
+ str = Malloc(str_size);
+ UniToStr(str, str_size, unistr);
+
+ return str;
+}
+
+// Copy an ANSI string to a Unicode string
+wchar_t *CopyStrToUni(char *str)
+{
+ wchar_t *uni;
+ UINT uni_size;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return CopyUniStr(L"");
+ }
+ uni = Malloc(uni_size);
+ StrToUni(uni, uni_size, str);
+
+ return uni;
+}
+
+// Copy a Unicode string to UTF-8 string
+char *CopyUniToUtf(wchar_t *unistr)
+{
+ UINT size;
+ char *ret;
+ // Validate arguments
+ if (unistr == NULL)
+ {
+ return NULL;
+ }
+
+ size = CalcUniToUtf8(unistr);
+ ret = ZeroMalloc(size + sizeof(char));
+
+ UniToUtf8((char *)ret, size, unistr);
+
+ return ret;
+}
+
+// Copy ANSI string to UTF8 string
+char *CopyStrToUtf(char *str)
+{
+ wchar_t *unistr;
+ char *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ unistr = CopyStrToUni(str);
+ if (unistr == NULL)
+ {
+ return CopyStr("");
+ }
+
+ ret = CopyUniToUtf(unistr);
+
+ Free(unistr);
+
+ return ret;
+}
+
+// Copy the Unicode string
+wchar_t *CopyUniStr(wchar_t *str)
+{
+ UINT len;
+ wchar_t *dst;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+ dst = Malloc((len + 1) * sizeof(wchar_t));
+ UniStrCpy(dst, 0, str);
+
+ return dst;
+}
+
+// Check whether the string is safe
+bool IsSafeUniStr(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (IsSafeUniChar(str[i]) == false)
+ {
+ return false;
+ }
+ }
+ if (str[0] == L' ')
+ {
+ return false;
+ }
+ if (len != 0)
+ {
+ if (str[len - 1] == L' ')
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the character is safe
+bool IsSafeUniChar(wchar_t c)
+{
+ UINT i, len;
+ wchar_t *check_str =
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ L"abcdefghijklmnopqrstuvwxyz"
+ L"0123456789"
+ L" ()-_#%&.";
+
+ len = UniStrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Convert an UTF-8 string to an ANSI string
+UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcUtf8ToUni(u, size);
+ if (uni_size == 0)
+ {
+ if (str_size >= 1)
+ {
+ StrCpy(str, 0, "");
+ return 0;
+ }
+ }
+ tmp = Malloc(uni_size);
+ Utf8ToUni(tmp, uni_size, u, size);
+
+ // Convert to ANSI
+ ret = UniToStr(str, str_size, tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the size required when UTF-8 string is converted to ANSI string
+UINT CalcUtf8ToStr(BYTE *u, UINT size)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcUtf8ToUni(u, size);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ Utf8ToUni(tmp, uni_size, u, size);
+
+ // Convert to ANSI
+ ret = CalcUniToStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert an ANSI string to UTF-8 string
+UINT StrToUtf8(BYTE *u, UINT size, char *str)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ StrToUni(tmp, uni_size, str);
+
+ // Convert to UTF-8
+ ret = UniToUtf8(u, size, tmp);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the required buffer size to convert an ANSI string to an UTF-8 string
+UINT CalcStrToUtf8(char *str)
+{
+ UINT ret;
+ UINT uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ StrToUni(tmp, uni_size, str);
+
+ // Get the size as it was converted to UTF-8
+ ret = CalcUniToUtf8(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert Unicode string to ANSI string
+UINT UniToStr(char *str, UINT size, wchar_t *s)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ char *tmp;
+ UINT new_size;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ new_size = CalcUniToStr(s);
+ if (new_size == 0)
+ {
+ if (size >= 1)
+ {
+ StrCpy(str, 0, "");
+ }
+ return 0;
+ }
+ tmp = Malloc(new_size);
+ tmp[0] = 0;
+ wcstombs(tmp, s, new_size);
+ tmp[new_size - 1] = 0;
+ ret = StrCpy(str, size, tmp);
+ Free(tmp);
+
+ return ret;
+#else // OS_WIN32
+ return UnixUniToStr(str, size, s);
+#endif // OS_WIN32
+}
+
+// Get the required number of bytes to convert Unicode string to the ANSI string
+UINT CalcUniToStr(wchar_t *s)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ ret = (UINT)wcstombs(NULL, s, UniStrLen(s));
+ if (ret == (UINT)-1)
+ {
+ return 0;
+ }
+
+ return ret + 1;
+#else // OS_WIN32
+ return UnixCalcUniToStr(s);
+#endif // OS_WIN32
+}
+
+// Converted an ANSI string to a Unicode string
+UINT StrToUni(wchar_t *s, UINT size, char *str)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ wchar_t *tmp;
+ UINT new_size;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ new_size = CalcStrToUni(str);
+ if (new_size == 0)
+ {
+ if (size >= 2)
+ {
+ UniStrCpy(s, 0, L"");
+ }
+ return 0;
+ }
+ tmp = Malloc(new_size);
+ tmp[0] = 0;
+ mbstowcs(tmp, str, StrLen(str));
+ tmp[(new_size - 1) / sizeof(wchar_t)] = 0;
+ ret = UniStrCpy(s, size, tmp);
+ Free(tmp);
+
+ return ret;
+#else // OS_WIN32
+ return UnixStrToUni(s, size, str);
+#endif // OS_WIN32
+}
+
+// Get the required buffer size for converting an ANSI string to an Unicode string
+UINT CalcStrToUni(char *str)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ ret = (UINT)mbstowcs(NULL, str, StrLen(str));
+ if (ret == (UINT)-1)
+ {
+ return 0;
+ }
+
+ return (ret + 1) * sizeof(wchar_t);
+#else // OS_WIN32
+ return UnixCalcStrToUni(str);
+#endif // OS_WIN32
+}
+
+// Convert the UTF-8 strings to a Unicode string
+UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size)
+{
+ UINT i, wp, num;
+ // Validate arguments
+ if (s == NULL || u == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = 0x3fffffff;
+ }
+ if (u_size == 0)
+ {
+ u_size = StrLen((char *)u);
+ }
+
+ i = 0;
+ wp = 0;
+ num = 0;
+ while (true)
+ {
+ UINT type;
+ wchar_t c;
+ BYTE c1, c2;
+
+ type = GetUtf8Type(u, u_size, i);
+ if (type == 0)
+ {
+ break;
+ }
+ switch (type)
+ {
+ case 1:
+ c1 = 0;
+ c2 = u[i];
+ break;
+ case 2:
+ c1 = (((u[i] & 0x1c) >> 2) & 0x07);
+ c2 = (((u[i] & 0x03) << 6) & 0xc0) | (u[i + 1] & 0x3f);
+ break;
+ case 3:
+ c1 = ((((u[i] & 0x0f) << 4) & 0xf0)) | (((u[i + 1] & 0x3c) >> 2) & 0x0f);
+ c2 = (((u[i + 1] & 0x03) << 6) & 0xc0) | (u[i + 2] & 0x3f);
+ break;
+ }
+ i += type;
+
+ c = 0;
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ ((BYTE *)&c)[0] = c1;
+ ((BYTE *)&c)[1] = c2;
+ }
+ else
+ {
+ ((BYTE *)&c)[2] = c1;
+ ((BYTE *)&c)[3] = c2;
+ }
+ }
+ else
+ {
+ ((BYTE *)&c)[0] = c2;
+ ((BYTE *)&c)[1] = c1;
+ }
+
+ if (wp < ((size / sizeof(wchar_t)) - 1))
+ {
+ s[wp++] = c;
+ num++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (wp < (size / sizeof(wchar_t)))
+ {
+ s[wp++] = 0;
+ }
+
+ return num;
+}
+
+// Get the buffer size when converted UTF-8 to Unicode
+UINT CalcUtf8ToUni(BYTE *u, UINT u_size)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+ if (u_size == 0)
+ {
+ u_size = StrLen((char *)u);
+ }
+
+ return (Utf8Len(u, u_size) + 1) * sizeof(wchar_t);
+}
+
+// Get the number of characters in UTF-8 string
+UINT Utf8Len(BYTE *u, UINT size)
+{
+ UINT i, num;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = StrLen((char *)u);
+ }
+
+ i = num = 0;
+ while (true)
+ {
+ UINT type;
+
+ type = GetUtf8Type(u, size, i);
+ if (type == 0)
+ {
+ break;
+ }
+ i += type;
+ num++;
+ }
+
+ return num;
+}
+
+// Convert an Unicode string to UTF-8 string
+UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s)
+{
+ UINT i, len, type, wp;
+ // Validate arguments
+ if (u == NULL || s == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = 0x3fffffff;
+ }
+
+ len = UniStrLen(s);
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ BYTE c1, c2;
+ wchar_t c = s[i];
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ c1 = ((BYTE *)&c)[0];
+ c2 = ((BYTE *)&c)[1];
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[2];
+ c2 = ((BYTE *)&c)[3];
+ }
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[1];
+ c2 = ((BYTE *)&c)[0];
+ }
+
+ type = GetUniType(s[i]);
+ switch (type)
+ {
+ case 1:
+ if (wp < size)
+ {
+ u[wp++] = c2;
+ }
+ break;
+ case 2:
+ if (wp < size)
+ {
+ u[wp++] = 0xc0 | (((((c1 & 0x07) << 2) & 0x1c)) | (((c2 & 0xc0) >> 6) & 0x03));
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (c2 & 0x3f);
+ }
+ break;
+ case 3:
+ if (wp < size)
+ {
+ u[wp++] = 0xe0 | (((c1 & 0xf0) >> 4) & 0x0f);
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (((c1 & 0x0f) << 2) & 0x3c) | (((c2 & 0xc0) >> 6) & 0x03);
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (c2 & 0x3f);
+ }
+ break;
+ }
+ }
+ if (wp < size)
+ {
+ u[wp] = 0;
+ }
+ return wp;
+}
+
+// Calculating the length of the string when converting Unicode string to UTF-8 string
+UINT CalcUniToUtf8(wchar_t *s)
+{
+ UINT i, len, size;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ size = 0;
+ len = UniStrLen(s);
+ for (i = 0;i < len;i++)
+ {
+ size += GetUniType(s[i]);
+ }
+
+ return size;
+}
+
+// Get the number of bytes of a first character of the offset address of the UTF-8 string that starts with s
+UINT GetUtf8Type(BYTE *s, UINT size, UINT offset)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+ if ((offset + 1) > size)
+ {
+ return 0;
+ }
+ if ((s[offset] & 0x80) == 0)
+ {
+ // 1 byte
+ return 1;
+ }
+ if ((s[offset] & 0x20) == 0)
+ {
+ // 2 bytes
+ if ((offset + 2) > size)
+ {
+ return 0;
+ }
+ return 2;
+ }
+ // 3 bytes
+ if ((offset + 3) > size)
+ {
+ return 0;
+ }
+ return 3;
+}
+
+// Type of the converted character 'c' to UTF-8 (in bytes)
+UINT GetUniType(wchar_t c)
+{
+ BYTE c1, c2;
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ c1 = ((BYTE *)&c)[0];
+ c2 = ((BYTE *)&c)[1];
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[2];
+ c2 = ((BYTE *)&c)[3];
+ }
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[1];
+ c2 = ((BYTE *)&c)[0];
+ }
+
+ if (c1 == 0)
+ {
+ if (c2 <= 0x7f)
+ {
+ // 1 byte
+ return 1;
+ }
+ else
+ {
+ // 2 bytes
+ return 2;
+ }
+ }
+ if ((c1 & 0xf8) == 0)
+ {
+ // 2 bytes
+ return 2;
+ }
+ // 3 bytes
+ return 3;
+}
+
+// String replacing (case-insensitive)
+UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
+{
+ return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
+}
+
+// String replacing (case-sensitive)
+UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
+{
+ return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
+}
+
+// Replacement of string
+UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
+{
+ UINT i, j, num, len_string, len_old, len_new, len_ret, wp;
+ wchar_t *ret;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = UniStrLen(string);
+ len_old = UniStrLen(old_keyword);
+ len_new = UniStrLen(new_keyword);
+
+ // Get the final string length
+ len_ret = UniCalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
+ // Memory allocation
+ ret = Malloc((len_ret + 1) * sizeof(wchar_t));
+ ret[len_ret] = 0;
+
+ // Search and Replace
+ i = j = num = wp = 0;
+ while (true)
+ {
+ i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ Copy(&ret[wp], &string[j], (len_string - j) * sizeof(wchar_t));
+ wp += len_string - j;
+ break;
+ }
+ num++;
+ Copy(&ret[wp], &string[j], (i - j) * sizeof(wchar_t));
+ wp += i - j;
+ Copy(&ret[wp], new_keyword, len_new * sizeof(wchar_t));
+ wp += len_new;
+ i += len_old;
+ j = i;
+ }
+
+ // Copy of the search results
+ UniStrCpy(dst, size, ret);
+
+ // Memory release
+ Free(ret);
+
+ return num;
+}
+
+// Calculate the length of the result of string replacement
+UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
+{
+ UINT i, num;
+ UINT len_string, len_old, len_new;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = UniStrLen(string);
+ len_old = UniStrLen(old_keyword);
+ len_new = UniStrLen(new_keyword);
+
+ if (len_old == len_new)
+ {
+ return len_string;
+ }
+
+ // Search process
+ num = 0;
+ i = 0;
+ while (true)
+ {
+ i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ break;
+ }
+ i += len_old;
+ num++;
+ }
+
+ // Calculation
+ return len_string + len_new * num - len_old * num;
+}
+
+// Search for a string (distinguish between upper / lower case)
+UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start)
+{
+ return UniSearchStrEx(string, keyword, start, true);
+}
+
+// Search for a string (Don't distinguish between upper / lower case)
+UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start)
+{
+ return UniSearchStrEx(string, keyword, start, false);
+}
+
+// Return the position of the first found of the keyword in the string
+// (Found in first character: returns 0, Not found: returns INFINITE)
+UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive)
+{
+ UINT len_string, len_keyword;
+ UINT i;
+ wchar_t *cmp_string, *cmp_keyword;
+ bool found;
+ // Validate arguments
+ if (string == NULL || keyword == NULL)
+ {
+ return INFINITE;
+ }
+
+ // Get the length of string
+ len_string = UniStrLen(string);
+ if (len_string <= start)
+ {
+ // Value of start is invalid
+ return INFINITE;
+ }
+
+ // Get the length of the keyword
+ len_keyword = UniStrLen(keyword);
+ if (len_keyword == 0)
+ {
+ // There is no keyword
+ return INFINITE;
+ }
+
+ if (len_string < len_keyword)
+ {
+ return INFINITE;
+ }
+
+ if (len_string == len_keyword)
+ {
+ if (case_sensitive)
+ {
+ if (UniStrCmp(string, keyword) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+ else
+ {
+ if (UniStrCmpi(string, keyword) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+ }
+
+ if (case_sensitive)
+ {
+ cmp_string = string;
+ cmp_keyword = keyword;
+ }
+ else
+ {
+ cmp_string = Malloc((len_string + 1) * sizeof(wchar_t));
+ UniStrCpy(cmp_string, (len_string + 1) * sizeof(wchar_t), string);
+ cmp_keyword = Malloc((len_keyword + 1) * sizeof(wchar_t));
+ UniStrCpy(cmp_keyword, (len_keyword + 1) * sizeof(wchar_t), keyword);
+ UniStrUpper(cmp_string);
+ UniStrUpper(cmp_keyword);
+ }
+
+ // Search
+ found = false;
+ for (i = start;i < (len_string - len_keyword + 1);i++)
+ {
+ // Compare
+ if (!wcsncmp(&cmp_string[i], cmp_keyword, len_keyword))
+ {
+ // Found
+ found = true;
+ break;
+ }
+ }
+
+ if (case_sensitive == false)
+ {
+ // Memory release
+ Free(cmp_keyword);
+ Free(cmp_string);
+ }
+
+ if (found == false)
+ {
+ return INFINITE;
+ }
+ return i;
+}
+
+// Release of the token list
+void UniFreeToken(UNI_TOKEN_LIST *tokens)
+{
+ UINT i;
+ if (tokens == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < tokens->NumTokens;i++)
+ {
+ Free(tokens->Token[i]);
+ }
+ Free(tokens->Token);
+ Free(tokens);
+}
+
+// Parse token for UNIX
+UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator)
+{
+ UNI_TOKEN_LIST *ret;
+ TOKEN_LIST *t;
+ char *src_s;
+ char *sep_s;
+
+ // Validate arguments
+ if (src == NULL || separator == NULL)
+ {
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+
+ src_s = CopyUniToStr(src);
+ sep_s = CopyUniToStr(separator);
+
+ t = ParseToken(src_s, sep_s);
+
+ ret = TokenListToUniTokenList(t);
+ FreeToken(t);
+
+ Free(src_s);
+ Free(sep_s);
+
+ return ret;
+}
+
+// Parse the token
+UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator)
+{
+#ifdef OS_WIN32
+ UNI_TOKEN_LIST *ret;
+ wchar_t *tmp;
+ wchar_t *str1, *str2;
+ UINT len, num;
+
+#ifdef OS_UNIX
+ wchar_t *state = NULL;
+#endif // OS_UNIX
+
+ // Validate arguments
+ if (src == NULL)
+ {
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+ if (separator == NULL)
+ {
+ separator = L" .\t\r\n";
+ }
+ len = UniStrLen(src);
+ str1 = Malloc((len + 1) * sizeof(wchar_t));
+ str2 = Malloc((len + 1) * sizeof(wchar_t));
+ UniStrCpy(str1, 0, src);
+ UniStrCpy(str2, 0, src);
+
+ Lock(token_lock);
+ {
+ tmp = wcstok(str1, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ num = 0;
+ while (tmp != NULL)
+ {
+ num++;
+ tmp = wcstok(NULL, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ }
+ ret = Malloc(sizeof(UNI_TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = (wchar_t **)Malloc(sizeof(wchar_t *) * num);
+ num = 0;
+ tmp = wcstok(str2, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ while (tmp != NULL)
+ {
+ ret->Token[num] = (wchar_t *)Malloc((UniStrLen(tmp) + 1) * sizeof(wchar_t));
+ UniStrCpy(ret->Token[num], 0, tmp);
+ num++;
+ tmp = wcstok(NULL, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ }
+ }
+ Unlock(token_lock);
+
+ Free(str1);
+ Free(str2);
+ return ret;
+#else // OS_WIN32
+ return UnixUniParseToken(src, separator);
+#endif // OS_WIN32
+}
+
+// Get a line from standard input
+bool UniGetLine(wchar_t *str, UINT size)
+{
+#ifdef OS_WIN32
+ return UniGetLineWin32(str, size);
+#else // OS_WIN32
+ return UniGetLineUnix(str, size);
+#endif // OS_WIN32
+}
+void AnsiGetLineUnix(char *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ char tmp[MAX_SIZE];
+ fgets(tmp, sizeof(tmp) - 1, stdin);
+ return;
+ }
+ if (size <= 1)
+ {
+ return;
+ }
+
+ // Read data from standard input
+ fgets(str, (int)(size - 1), stdin);
+
+ TrimCrlf(str);
+}
+bool UniGetLineUnix(wchar_t *str, UINT size)
+{
+ char *str_a;
+ UINT str_a_size = size;
+ if (str == NULL || size < sizeof(wchar_t))
+ {
+ return false;
+ }
+ if (str_a_size >= 0x7fffffff)
+ {
+ str_a_size = MAX_SIZE;
+ }
+ str_a_size *= 2;
+
+ str_a = ZeroMalloc(str_a_size);
+
+ AnsiGetLineUnix(str_a, str_a_size);
+
+ StrToUni(str, size, str_a);
+
+ Free(str_a);
+
+ return true;
+}
+bool UniGetLineWin32(wchar_t *str, UINT size)
+{
+ bool ret = false;
+
+#ifdef OS_WIN32
+ ret = Win32InputW(str, size);
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Remove '\r\n' at the end
+void UniTrimCrlf(wchar_t *str)
+{
+ UINT len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (str[len - 1] == L'\n')
+ {
+ if (len >= 2 && str[len - 2] == L'\r')
+ {
+ str[len - 2] = 0;
+ }
+ str[len - 1] = 0;
+ }
+ else if(str[len - 1] == L'\r')
+ {
+ str[len - 1] = 0;
+ }
+}
+
+// Remove white space of the both side of the string
+void UniTrim(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ UniTrimLeft(str);
+ UniTrimRight(str);
+}
+
+// Remove white space on the right side of the string
+void UniTrimRight(wchar_t *str)
+{
+ wchar_t *buf, *tmp;
+ UINT len, i, wp, wp2;
+ bool flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[len - 1] != L' ' && str[len - 1] != L'\t')
+ {
+ return;
+ }
+
+ buf = Malloc((len + 1) * sizeof(wchar_t));
+ tmp = Malloc((len + 1) * sizeof(wchar_t));
+ flag = false;
+ wp = wp2 = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != L' ' && str[i] != L'\t')
+ {
+ Copy(&buf[wp], tmp, wp2 * sizeof(wchar_t));
+ wp += wp2;
+ wp2 = 0;
+ buf[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp2++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ UniStrCpy(str, 0, buf);
+ Free(buf);
+ Free(tmp);
+}
+
+// Remove white space from the left side of the string
+void UniTrimLeft(wchar_t *str)
+{
+ wchar_t *buf;
+ UINT len, i, wp;
+ bool flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[0] != L' ' && str[0] != L'\t')
+ {
+ return;
+ }
+
+ buf = Malloc((len + 1) * sizeof(wchar_t));
+ flag = false;
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != L' ' && str[i] != L'\t')
+ {
+ flag = true;
+ }
+ if (flag)
+ {
+ buf[wp++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ UniStrCpy(str, 0, buf);
+ Free(buf);
+}
+
+// Convert an integer to a hexadecimal string (8-digit fixed)
+void UniToStrx8(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"0x%08x", i);
+}
+
+// Convert an integer to a hexadecimal string
+void UniToStrx(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"0x%02x", i);
+}
+
+// Convert a signed integer to a string
+void UniToStri(wchar_t *str, int i)
+{
+ UniFormat(str, 0, L"%i", i);
+}
+
+// Convert an integer to a string
+void UniToStru(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"%u", i);
+}
+
+// Convert the string to signed integer
+int UniToInti(wchar_t *str)
+{
+ char tmp[128];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInt(tmp);
+}
+
+// Convert a string to an integer
+UINT UniToInt(wchar_t *str)
+{
+ char tmp[128];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInti(tmp);
+}
+
+// Convert only single-byte characters in the Unicode string to a char string
+void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < UniStrLen(src) + 1;i++)
+ {
+ wchar_t s = src[i];
+ char d;
+
+ if (s == 0)
+ {
+ d = 0;
+ }
+ else if (s <= 0xff)
+ {
+ d = (char)s;
+ }
+ else
+ {
+ d = ' ';
+ }
+
+ dst[i] = d;
+ }
+}
+
+// Format string replacement for 64-bit
+wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt)
+{
+ wchar_t *tmp;
+ wchar_t *ret;
+ UINT tmp_size;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = UniStrSize(fmt) * 2;
+ tmp = ZeroMalloc(tmp_size);
+
+#ifdef OS_WIN32
+ UniReplaceStrEx(tmp, tmp_size, fmt, L"%ll", L"%I64", false);
+#else // OS_WIN32
+ UniReplaceStrEx(tmp, tmp_size, fmt, L"%I64", L"%ll", false);
+
+ if (1)
+ {
+ UINT i, len;
+ bool f = false;
+ len = UniStrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == L'%')
+ {
+ f = true;
+ }
+
+ if (f)
+ {
+ switch (tmp[i])
+ {
+ case L'c':
+ case L'C':
+ case L'd':
+ case L'i':
+ case L'o':
+ case L'u':
+ case L'x':
+ case L'X':
+ case L'e':
+ case L'E':
+ case L'f':
+ case L'g':
+ case L'G':
+ case L'n':
+ case L'p':
+ case L's':
+ case L'S':
+ if (tmp[i] == L's')
+ {
+ tmp[i] = L'S';
+ }
+ else if (tmp[i] == L'S')
+ {
+ tmp[i] = L's';
+ }
+ f = false;
+ break;
+ }
+ }
+ }
+ }
+
+#endif // OS_WIN32
+
+ ret = CopyUniStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the string on the screen
+void UniPrintStr(wchar_t *string)
+{
+ // Validate arguments
+ if (string == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_UNIX
+ if (true)
+ {
+ char *str = CopyUniToStr(string);
+
+ if (str != NULL)
+ {
+ fputs(str, stdout);
+ }
+ else
+ {
+ fputs("", stdout);
+ }
+
+ Free(str);
+ }
+#else // OS_UNIX
+ Win32PrintW(string);
+#endif // OS_UNIX
+}
+
+// Display a string with arguments
+void UniPrintArgs(wchar_t *fmt, va_list args)
+{
+ wchar_t *str;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ str = InternalFormatArgs(fmt, args, false);
+
+ UniPrintStr(str);
+
+ Free(str);
+}
+
+// Display the string
+void UniPrint(wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniPrintArgs(fmt, args);
+ va_end(args);
+}
+
+// Display debug string with arguments
+void UniDebugArgs(wchar_t *fmt, va_list args)
+{
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ UniPrintArgs(fmt, args);
+}
+
+// Display a debug string
+void UniDebug(wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniDebugArgs(fmt, args);
+ va_end(args);
+}
+
+// Format a string (argument list)
+void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+ if (size == 1)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_FORMAT_COUNT);
+
+ ret = InternalFormatArgs(fmt, args, false);
+
+ UniStrCpy(buf, size, ret);
+
+ Free(ret);
+}
+
+// Format the string, and copy it
+wchar_t *CopyUniFormat(wchar_t *fmt, ...)
+{
+ wchar_t *ret, *str;
+ UINT size;
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(UniStrSize(fmt) * 10, MAX_SIZE * 10);
+ str = Malloc(size);
+
+ va_start(args, fmt);
+ UniFormatArgs(str, size, fmt, args);
+
+ ret = UniCopyStr(str);
+ Free(str);
+ va_end(args);
+
+ return ret;
+}
+
+// Format the string
+void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniFormatArgs(buf, size, fmt, args);
+ va_end(args);
+}
+
+// Flexible string comparison
+int UniSoftStrCmp(wchar_t *str1, wchar_t *str2)
+{
+ UINT ret;
+ wchar_t *tmp1, *tmp2;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ tmp1 = CopyUniStr(str1);
+ tmp2 = CopyUniStr(str2);
+
+ UniTrim(tmp1);
+ UniTrim(tmp2);
+
+ ret = UniStrCmpi(tmp1, tmp2);
+
+ Free(tmp1);
+ Free(tmp2);
+
+ return ret;
+}
+
+// Compare the strings in case-insensitive mode
+int UniStrCmpi(wchar_t *str1, wchar_t *str2)
+{
+ UINT i;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ // String comparison
+ i = 0;
+ while (true)
+ {
+ wchar_t c1, c2;
+ c1 = UniToUpper(str1[i]);
+ c2 = UniToUpper(str2[i]);
+ if (c1 > c2)
+ {
+ return 1;
+ }
+ else if (c1 < c2)
+ {
+ return -1;
+ }
+ if (str1[i] == 0 || str2[i] == 0)
+ {
+ return 0;
+ }
+ i++;
+ }
+}
+
+// Compare the string
+int UniStrCmp(wchar_t *str1, wchar_t *str2)
+{
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ return wcscmp(str1, str2);
+}
+
+// Uncapitalize the string
+void UniStrLower(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = UniToLower(str[i]);
+ }
+}
+
+// Capitalize the string
+void UniStrUpper(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = UniToUpper(str[i]);
+ }
+}
+
+// Uncapitalize a character
+wchar_t UniToLower(wchar_t c)
+{
+ if (c >= L'A' && c <= L'Z')
+ {
+ c += L'a' - L'A';
+ }
+
+ return c;
+}
+
+// Capitalize a character
+wchar_t UniToUpper(wchar_t c)
+{
+ if (c >= L'a' && c <= L'z')
+ {
+ c -= L'a' - L'A';
+ }
+
+ return c;
+}
+
+// String concatenation
+UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT len1, len2, len_test;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+ if (size != 0 && size < sizeof(wchar_t))
+ {
+ return 0;
+ }
+ if (size == sizeof(wchar_t))
+ {
+ wcscpy(dst, L"");
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x3fffffff;
+ }
+
+ len1 = UniStrLen(dst);
+ len2 = UniStrLen(src);
+ len_test = len1 + len2 + 1;
+ if (len_test > (size / sizeof(wchar_t)))
+ {
+ if (len2 <= (len_test - (size / sizeof(wchar_t))))
+ {
+ return 0;
+ }
+ len2 -= len_test - (size / sizeof(wchar_t));
+ }
+ Copy(&dst[len1], src, len2 * sizeof(wchar_t));
+ dst[len1 + len2] = 0;
+
+ return len1 + len2;
+}
+UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t *s;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ s = UniCopyStr(dst);
+ UniStrCpy(dst, size, s);
+ UniStrCat(dst, size, src);
+ Free(s);
+
+ return UniStrLen(dst);
+}
+
+// String copy
+UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ if (src == NULL && dst != NULL)
+ {
+ if (size >= sizeof(wchar_t))
+ {
+ dst[0] = L'\0';
+ }
+ }
+ return 0;
+ }
+ if (dst == src)
+ {
+ return UniStrLen(src);
+ }
+ if (size != 0 && size < sizeof(wchar_t))
+ {
+ return 0;
+ }
+ if (size == sizeof(wchar_t))
+ {
+ wcscpy(dst, L"");
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x3fffffff;
+ }
+
+ // Check the length
+ len = UniStrLen(src);
+ if (len <= (size / sizeof(wchar_t) - 1))
+ {
+ Copy(dst, src, (len + 1) * sizeof(wchar_t));
+ }
+ else
+ {
+ len = size / 2 - 1;
+ Copy(dst, src, len * sizeof(wchar_t));
+ dst[len] = 0;
+ }
+
+ return len;
+}
+
+// Check whether the character is within specified buffer size
+bool UniCheckStrSize(wchar_t *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL || size <= 1)
+ {
+ return false;
+ }
+
+ return UniCheckStrLen(str, size / sizeof(wchar_t) - 1);
+}
+
+// Check whether the number of characters is within specified length
+bool UniCheckStrLen(wchar_t *str, UINT len)
+{
+ UINT count = 0;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;;i++)
+ {
+ if (str[i] == 0)
+ {
+ return true;
+ }
+ count++;
+ if (count > len)
+ {
+ return false;
+ }
+ }
+}
+
+// Get the buffer size needed to store the string
+UINT UniStrSize(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return (UniStrLen(str) + 1) * sizeof(wchar_t);
+}
+
+// Get the length of the string
+UINT UniStrLen(wchar_t *str)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ i = 0;
+ while (true)
+ {
+ if (str[i] == 0)
+ {
+ break;
+ }
+ i++;
+ }
+
+ return i;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Internat.h b/src/Mayaqua/Internat.h
new file mode 100644
index 00000000..4a5181b9
--- /dev/null
+++ b/src/Mayaqua/Internat.h
@@ -0,0 +1,227 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Internat.h
+// Header of Internat.c
+
+#ifndef INTERNAT_H
+#define INTERNAT_H
+
+// String token
+struct UNI_TOKEN_LIST
+{
+ UINT NumTokens;
+ wchar_t **Token;
+};
+
+UINT UniStrLen(wchar_t *str);
+UINT UniStrSize(wchar_t *str);
+UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src);
+bool UniCheckStrSize(wchar_t *str, UINT size);
+bool UniCheckStrLen(wchar_t *str, UINT len);
+UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src);
+UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src);
+wchar_t UniToLower(wchar_t c);
+wchar_t UniToUpper(wchar_t c);
+void UniStrLower(wchar_t *str);
+void UniStrUpper(wchar_t *str);
+int UniStrCmp(wchar_t *str1, wchar_t *str2);
+int UniStrCmpi(wchar_t *str1, wchar_t *str2);
+int UniSoftStrCmp(wchar_t *str1, wchar_t *str2);
+void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...);
+wchar_t *CopyUniFormat(wchar_t *fmt, ...);
+void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args);
+void UniDebugArgs(wchar_t *fmt, va_list args);
+void UniDebug(wchar_t *fmt, ...);
+void UniPrint(wchar_t *fmt, ...);
+void UniPrintArgs(wchar_t *fmt, va_list args);
+void UniPrintStr(wchar_t *string);
+void UniToStrx8(wchar_t *str, UINT i);
+void UniToStrx(wchar_t *str, UINT i);
+void UniToStri(wchar_t *str, int i);
+void UniToStru(wchar_t *str, UINT i);
+int UniToInti(wchar_t *str);
+UINT UniToInt(wchar_t *str);
+void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src);
+void UniTrim(wchar_t *str);
+void UniTrimLeft(wchar_t *str);
+void UniTrimRight(wchar_t *str);
+void UniTrimCrlf(wchar_t *str);
+bool UniGetLine(wchar_t *str, UINT size);
+bool UniGetLineWin32(wchar_t *str, UINT size);
+bool UniGetLineUnix(wchar_t *str, UINT size);
+void UniFreeToken(UNI_TOKEN_LIST *tokens);
+UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator);
+UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive);
+UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start);
+UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start);
+UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive);
+UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive);
+UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword);
+UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword);
+UINT GetUniType(wchar_t c);
+UINT GetUtf8Type(BYTE *s, UINT size, UINT offset);
+UINT CalcUniToUtf8(wchar_t *s);
+UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s);
+UINT Utf8Len(BYTE *u, UINT size);
+UINT CalcUtf8ToUni(BYTE *u, UINT u_size);
+UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size);
+UINT CalcStrToUni(char *str);
+UINT StrToUni(wchar_t *s, UINT size, char *str);
+UINT CalcUniToStr(wchar_t *s);
+UINT UniToStr(char *str, UINT size, wchar_t *s);
+UINT CalcStrToUtf8(char *str);
+UINT StrToUtf8(BYTE *u, UINT size, char *str);
+UINT CalcUtf8ToStr(BYTE *u, UINT size);
+UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size);
+bool IsSafeUniStr(wchar_t *str);
+bool IsSafeUniChar(wchar_t c);
+wchar_t *CopyUniStr(wchar_t *str);
+wchar_t *CopyStrToUni(char *str);
+UINT StrToUtf(char *utfstr, UINT size, char *str);
+UINT UtfToStr(char *str, UINT size, char *utfstr);
+UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr);
+UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr);
+char *CopyUniToUtf(wchar_t *unistr);
+char *CopyStrToUtf(char *str);
+char *CopyUniToStr(wchar_t *unistr);
+wchar_t *CopyUtfToUni(char *utfstr);
+char *CopyUtfToStr(char *utfstr);
+wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt);
+void UniToStr64(wchar_t *str, UINT64 value);
+UINT64 UniToInt64(wchar_t *str);
+UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str);
+UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src);
+wchar_t *UniCopyStr(wchar_t *str);
+TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src);
+UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src);
+UNI_TOKEN_LIST *UniNullToken();
+UNI_TOKEN_LIST *NullUniToken();
+bool UniIsNum(wchar_t *str);
+bool IsEmptyUniStr(wchar_t *str);
+bool UniIsEmptyStr(wchar_t *str);
+void InitInternational();
+void FreeInternational();
+USHORT *WideToUtf16(wchar_t *str);
+wchar_t *Utf16ToWide(USHORT *str);
+void DumpUniStr(wchar_t *str);
+void DumpStr(char *str);
+wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode);
+UINT UniStrWidth(wchar_t *str);
+UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator);
+void UniToStr3(wchar_t *str, UINT size, UINT64 value);
+bool UniEndWith(wchar_t *str, wchar_t *key);
+bool UniStartWith(wchar_t *str, wchar_t *key);
+wchar_t *UniNormalizeCrlf(wchar_t *str);
+LIST *UniStrToStrList(wchar_t *str, UINT size);
+BUF *UniStrListToStr(LIST *o);
+void UniFreeStrList(LIST *o);
+UNI_TOKEN_LIST *UniListToTokenList(LIST *o);
+LIST *UniTokenListToList(UNI_TOKEN_LIST *t);
+bool UniIsSafeChar(wchar_t c);
+wchar_t *UniMakeCharArray(wchar_t c, UINT count);
+BUF *UniStrToBin(wchar_t *str);
+bool UniInStr(wchar_t *str, wchar_t *keyword);
+bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive);
+void ClearUniStr(wchar_t *str, UINT str_size);
+bool UniInChar(wchar_t *string, wchar_t c);
+
+#ifdef OS_UNIX
+void GetCurrentCharSet(char *name, UINT size);
+UINT UnixCalcStrToUni(char *str);
+UINT UnixStrToUni(wchar_t *s, UINT size, char *str);
+UINT UnixCalcUniToStr(wchar_t *s);
+UINT UnixUniToStr(char *str, UINT size, wchar_t *s);
+void *IconvWideToStr();
+void *IconvStrToWide();
+int IconvFree(void *d);
+void *IconvWideToStrInternal();
+void *IconvStrToWideInternal();
+int IconvFreeInternal(void *d);
+#endif // OS_UNIX
+
+#endif // INTERNAT_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Kernel.c b/src/Mayaqua/Kernel.c
new file mode 100644
index 00000000..c331290b
--- /dev/null
+++ b/src/Mayaqua/Kernel.c
@@ -0,0 +1,2172 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Kernel.c
+// System service processing routine
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifndef TM_YEAR_MAX
+#define TM_YEAR_MAX 2106
+#endif
+#ifndef TM_MON_MAX
+#define TM_MON_MAX 1
+#endif
+#ifndef TM_MDAY_MAX
+#define TM_MDAY_MAX 7
+#endif
+#ifndef TM_HOUR_MAX
+#define TM_HOUR_MAX 6
+#endif
+#ifndef TM_MIN_MAX
+#define TM_MIN_MAX 28
+#endif
+#ifndef TM_SEC_MAX
+#define TM_SEC_MAX 14
+#endif
+
+#define ADJUST_TM(tm_member, tm_carry, modulus) \
+ if ((tm_member) < 0){ \
+ tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
+ tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
+ } else if ((tm_member) >= (modulus)) { \
+ tm_carry += (tm_member) / (modulus); \
+ tm_member = (tm_member) % (modulus); \
+ }
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+#define leapday(m, y) ((m) == 1 && leap (y))
+#define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
+static int ydays[] =
+{
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+static UINT current_num_thread = 0;
+
+
+
+static wchar_t *default_locale_str =
+L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
+
+
+static LOCALE current_locale;
+LOCK *tick_manual_lock = NULL;
+UINT g_zero = 0;
+
+// Get the real-time system timer
+UINT TickRealtime()
+{
+#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
+ return Tick() + 1;
+#else
+ return TickRealtimeManual() + 1;
+#endif
+}
+
+#ifndef OS_WIN32
+
+static UINT64 last_manual_tick = 0;
+static UINT64 manual_tick_add_value = 0;
+
+// For systems which not have clock_gettime (such as MacOS X)
+UINT TickRealtimeManual()
+{
+ UINT64 ret;
+ Lock(tick_manual_lock);
+ {
+ ret = TickGetRealtimeTickValue64();
+
+ if (last_manual_tick != 0 && (last_manual_tick > ret))
+ {
+ manual_tick_add_value += (last_manual_tick - ret);
+ }
+
+ last_manual_tick = ret;
+ }
+ Unlock(tick_manual_lock);
+
+ return (UINT)(ret + manual_tick_add_value);
+}
+
+// Returns a appropriate value from the current time
+UINT64 TickGetRealtimeTickValue64()
+{
+ struct timeval tv;
+ struct timezone tz;
+ UINT64 ret;
+
+ memset(&tv, 0, sizeof(tv));
+ memset(&tz, 0, sizeof(tz));
+
+ gettimeofday(&tv, &tz);
+
+ ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
+
+ return ret;
+}
+
+#endif // OS_WIN32
+
+// Creating a thread list
+LIST *NewThreadList()
+{
+ LIST *o = NewList(NULL);
+
+ return o;
+}
+
+// Remove the thread from the thread list
+void DelThreadFromThreadList(LIST *o, THREAD *t)
+{
+ // Validate arguments
+ if (o == NULL || t == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ if (Delete(o, t))
+ {
+ ReleaseThread(t);
+ }
+ }
+ UnlockList(o);
+}
+
+// Add the thread to the thread list
+void AddThreadToThreadList(LIST *o, THREAD *t)
+{
+ // Validate arguments
+ if (o == NULL || t == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ if (IsInList(o, t) == false)
+ {
+ AddRef(t->ref);
+
+ Add(o, t);
+ }
+ }
+ UnlockList(o);
+}
+
+// Maintain thread list
+void MainteThreadList(LIST *o)
+{
+ UINT i;
+ LIST *delete_list = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ if (t->Stopped)
+ {
+ if (delete_list == NULL)
+ {
+ delete_list = NewListFast(NULL);
+ }
+
+ Add(delete_list, t);
+ }
+ }
+
+ if (delete_list != NULL)
+ {
+ for (i = 0;i < LIST_NUM(delete_list);i++)
+ {
+ THREAD *t = LIST_DATA(delete_list, i);
+
+ ReleaseThread(t);
+
+ Delete(o, t);
+ }
+
+ ReleaseList(delete_list);
+ }
+ }
+ UnlockList(o);
+}
+
+// Stop all the threads in the thread list
+void StopThreadList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ WaitThread(t, INFINITE);
+ }
+ }
+ UnlockList(o);
+}
+
+// Release the thread list
+void FreeThreadList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ WaitThread(t, INFINITE);
+
+ ReleaseThread(t);
+ }
+
+ DeleteAll(o);
+ }
+ UnlockList(o);
+
+ ReleaseList(o);
+}
+
+// Get the home directory
+void GetHomeDirW(wchar_t *path, UINT size)
+{
+ // Validate arguments
+ if (path == NULL)
+ {
+ return;
+ }
+
+ if (GetEnvW(L"HOME", path, size) == false)
+ {
+ wchar_t drive[MAX_SIZE];
+ wchar_t hpath[MAX_SIZE];
+ if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
+ GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
+ {
+ UniFormat(path, sizeof(path), L"%s%s", drive, hpath);
+ }
+ else
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(path, size);
+#else // OS_WIN32
+ UnixGetCurrentDirW(path, size);
+#endif // OS_WIN32
+ }
+ }
+}
+void GetHomeDir(char *path, UINT size)
+{
+ // Validate arguments
+ if (path == NULL)
+ {
+ return;
+ }
+
+ if (GetEnv("HOME", path, size) == false)
+ {
+ char drive[MAX_SIZE];
+ char hpath[MAX_SIZE];
+ if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
+ GetEnv("HOMEPATH", hpath, sizeof(hpath)))
+ {
+ Format(path, sizeof(path), "%s%s", drive, hpath);
+ }
+ else
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDir(path, size);
+#else // OS_WIN32
+ UnixGetCurrentDir(path, size);
+#endif // OS_WIN32
+ }
+ }
+}
+
+// Get the environment variable string
+bool GetEnv(char *name, char *data, UINT size)
+{
+ char *ret;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(data, size, "");
+
+ ret = getenv(name);
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(data, size, ret);
+
+ return true;
+}
+bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
+{
+#ifdef OS_WIN32
+ return GetEnvW_ForWin32(name, data, size);
+#else // OS_WIN32
+ return GetEnvW_ForUnix(name, data, size);
+#endif // OS_WIN32
+}
+
+#ifdef OS_WIN32
+bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *name_a = CopyUniToStr(name);
+ char data_a[MAX_SIZE];
+
+ ret = GetEnv(name_a, data_a, sizeof(data_a));
+
+ if (ret)
+ {
+ StrToUni(data, size, data_a);
+ }
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ UniStrCpy(data, size, L"");
+
+ ret = _wgetenv(name);
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ UniStrCpy(data, size, ret);
+
+ return true;
+}
+
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+
+bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
+{
+ char *name_a;
+ bool ret;
+ char data_a[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ name_a = CopyUniToUtf(name);
+
+ ret = GetEnv(name_a, data_a, sizeof(data_a));
+
+ if (ret)
+ {
+ UtfToUni(data, size, data_a);
+ }
+
+ Free(name_a);
+
+ return ret;
+}
+
+#endif // OS_UNIX
+
+// Get the memory information
+void GetMemInfo(MEMINFO *info)
+{
+ OSGetMemInfo(info);
+}
+
+// Start the single-instance
+INSTANCE *NewSingleInstance(char *instance_name)
+{
+ return NewSingleInstanceEx(instance_name, false);
+}
+INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
+{
+ char name[MAX_SIZE];
+ INSTANCE *ret;
+ void *data;
+
+ if (instance_name != NULL)
+ {
+ if (user_local == false)
+ {
+ HashInstanceName(name, sizeof(name), instance_name);
+ }
+ else
+ {
+ HashInstanceNameLocal(name, sizeof(name), instance_name);
+ }
+
+ data = OSNewSingleInstance(name);
+ }
+ else
+ {
+ data = OSNewSingleInstance(NULL);
+ }
+
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(INSTANCE));
+ if (instance_name != NULL)
+ {
+ ret->Name = CopyStr(instance_name);
+ }
+
+ ret->pData = data;
+
+ return ret;
+}
+
+// Release of single instance
+void FreeSingleInstance(INSTANCE *inst)
+{
+ // Validate arguments
+ if (inst == NULL)
+ {
+ return;
+ }
+
+ OSFreeSingleInstance(inst->pData);
+
+ if (inst->Name != NULL)
+ {
+ Free(inst->Name);
+ }
+ Free(inst);
+}
+
+// Hashing the instance name
+void HashInstanceName(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char key[11];
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
+ BinToStr(key, sizeof(key), hash, 5);
+ key[10] = 0;
+
+ Format(name, size, "VPN-%s", key);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ StrCpy(tmp, sizeof(tmp), name);
+ Format(name, size, "Global\\%s", tmp);
+ }
+ }
+}
+void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char key[11];
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
+ BinToStr(key, sizeof(key), hash, 5);
+ key[10] = 0;
+
+ Format(name, size, "VPN-%s", key);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ StrCpy(tmp, sizeof(tmp), name);
+ Format(name, size, "Local\\%s", tmp);
+ }
+ }
+}
+
+// Run the process
+bool Run(char *filename, char *arg, bool hide, bool wait)
+{
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ return OSRun(filename, arg, hide, wait);
+}
+bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ return OSRunW(filename, arg, hide, wait);
+}
+
+// Date and time related functions
+void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ if (str == NULL)
+ {
+ return;
+ }
+
+ GetDateTimeStr64(tmp, sizeof(tmp), sec64);
+ StrToUni(str, size, tmp);
+}
+void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStr(str, size, &st);
+}
+void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStrMilli(str, size, &st);
+}
+void GetDateStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateStr(str, size, &st);
+}
+void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStrEx(str, size, &st, locale);
+}
+void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStrEx(str, size, &st, locale);
+}
+void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateStrEx(str, size, &st, locale);
+}
+void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStrMilli(str, size, &st);
+}
+void GetTimeStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStr(str, size, &st);
+}
+
+// Convert to a time to be used safely in the current POSIX implementation
+UINT64 SafeTime64(UINT64 sec64)
+{
+ return MAKESURE(sec64, 0, 2115947647000ULL);
+}
+
+// Thread pool
+static SK *thread_pool = NULL;
+static COUNTER *thread_count = NULL;
+
+// Initialization of thread pool
+void InitThreading()
+{
+ thread_pool = NewSk();
+ thread_count = NewCounter();
+}
+
+// Release of thread pool
+void FreeThreading()
+{
+ while (true)
+ {
+ if (Count(thread_count) == 0)
+ {
+ break;
+ }
+
+ SleepThread(25);
+ }
+
+ while (true)
+ {
+ THREAD_POOL_DATA *pd;
+ THREAD *t = Pop(thread_pool);
+
+ if (t == NULL)
+ {
+ break;
+ }
+
+ pd = (THREAD_POOL_DATA *)t->param;
+
+ pd->ThreadProc = NULL;
+ Set(pd->Event);
+
+ WaitThreadInternal(t);
+
+ pd = (THREAD_POOL_DATA *)t->param;
+ ReleaseEvent(pd->Event);
+ ReleaseEvent(pd->InitFinishEvent);
+
+ ReleaseThreadInternal(t);
+
+ Free(pd);
+ }
+
+ ReleaseSk(thread_pool);
+
+ DeleteCounter(thread_count);
+ thread_count = NULL;
+}
+
+// Thread pool procedure
+void ThreadPoolProc(THREAD *t, void *param)
+{
+ THREAD_POOL_DATA *pd;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ pd = (THREAD_POOL_DATA *)param;
+
+ NoticeThreadInitInternal(t);
+
+ while (true)
+ {
+ THREAD *thread;
+ UINT i, num;
+ EVENT **ee;
+
+ // Wait for the next job
+ Wait(pd->Event, INFINITE);
+
+ if (pd->ThreadProc == NULL)
+ {
+ // Stop the pool thread
+ break;
+ }
+
+ thread = pd->Thread;
+ thread->ThreadId = ThreadId();
+
+ // Initialization is completed
+ Set(pd->InitFinishEvent);
+
+ // Set the thread name
+ if (thread->Name != NULL)
+ {
+ SetThreadName(thread->ThreadId, thread->Name, thread->param);
+ }
+ else
+ {
+ SetThreadName(thread->ThreadId, "Unknown", 0);
+ }
+
+ // Run the thread procedure
+ pd->ThreadProc(pd->Thread, thread->param);
+
+ // Set the thread name
+ SetThreadName(thread->ThreadId, NULL, 0);
+
+ pd->Thread->Stopped = true;
+
+ thread->PoolHalting = true;
+
+ // Set the waiting event list
+ LockList(thread->PoolWaitList);
+ {
+ num = LIST_NUM(thread->PoolWaitList);
+ ee = ToArray(thread->PoolWaitList);
+
+ DeleteAll(thread->PoolWaitList);
+ }
+ UnlockList(thread->PoolWaitList);
+
+ for (i = 0;i < num;i++)
+ {
+ EVENT *e = ee[i];
+
+ Set(e);
+ ReleaseEvent(e);
+ }
+
+ Free(ee);
+
+ while (true)
+ {
+ if (Count(thread->ref->c) <= 1)
+ {
+ break;
+ }
+
+ Wait(thread->release_event, 256);
+ }
+
+ ReleaseThread(thread);
+
+#ifdef OS_WIN32
+ // For Win32: Recover the priority of the thread
+ MsRestoreThreadPriority();
+#endif // OS_WIN32
+
+ // Register the thread itself to the thread pool
+ LockSk(thread_pool);
+ {
+ Push(thread_pool, t);
+ }
+ UnlockSk(thread_pool);
+
+ Dec(thread_count);
+ }
+}
+
+// Set the thread name
+void SetThreadName(UINT thread_id, char *name, void *param)
+{
+#ifdef OS_WIN32
+ if (IsDebug())
+ {
+ char tmp[MAX_SIZE];
+
+ if (name == NULL)
+ {
+ strcpy(tmp, "idle");
+ }
+ else
+ {
+ sprintf(tmp, "%s (0x%x)", name, param);
+ }
+
+ Win32SetThreadName(thread_id, tmp);
+ }
+#else // OS_WIN32
+#ifdef _DEBUG
+#ifdef PR_SET_NAME
+ char tmp[MAX_SIZE];
+
+ if (name == NULL)
+ {
+ strcpy(tmp, "idle");
+ }
+ else
+ {
+ sprintf(tmp, "%s (%p)", name, param);
+ }
+
+ tmp[15] = 0;
+
+ prctl(PR_SET_NAME, (unsigned long)tmp, 0, 0, 0);
+#endif // PR_SET_NAME
+#endif // _DEBUG
+#endif // OS_WIN32
+}
+
+// Do Nothing
+UINT DoNothing()
+{
+ return g_zero;
+}
+
+// Thread creation (pool)
+THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
+{
+ THREAD *host = NULL;
+ THREAD_POOL_DATA *pd = NULL;
+ THREAD *ret;
+ bool new_thread = false;
+ // Validate arguments
+ if (thread_proc == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTrackingEnabled() == false)
+ {
+ DoNothing();
+ }
+
+ Inc(thread_count);
+
+ LockSk(thread_pool);
+ {
+ // Examine whether there is a thread that is currently vacant in the pool
+ host = Pop(thread_pool);
+ }
+ UnlockSk(thread_pool);
+
+ if (host == NULL)
+ {
+ // Create a new thread because a vacant thread is not found
+ pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
+ pd->Event = NewEvent();
+ pd->InitFinishEvent = NewEvent();
+ host = NewThreadInternal(ThreadPoolProc, pd);
+ WaitThreadInitInternal(host);
+
+ new_thread = true;
+ }
+ else
+ {
+ pd = (THREAD_POOL_DATA *)host->param;
+ }
+
+ // Creating a thread pool
+ ret = ZeroMalloc(sizeof(THREAD));
+ ret->ref = NewRef();
+ ret->thread_proc = thread_proc;
+ ret->param = param;
+ ret->pData = NULL;
+ ret->init_finished_event = NewEvent();
+ ret->PoolThread = true;
+ ret->PoolWaitList = NewList(NULL);
+ ret->PoolHostThread = host;
+ ret->release_event = NewEvent();
+
+ if (IsEmptyStr(name) == false)
+ {
+ ret->Name = CopyStr(name);
+ }
+
+ // Run
+ pd->ThreadProc = thread_proc;
+ pd->Thread = ret;
+ AddRef(ret->ref);
+
+ Set(pd->Event);
+
+ Wait(pd->InitFinishEvent, INFINITE);
+
+ current_num_thread++;
+
+// Debug("current_num_thread = %u\n", current_num_thread);
+
+ return ret;
+}
+
+// Clean up of thread (pool)
+void CleanupThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ ReleaseEvent(t->init_finished_event);
+ ReleaseEvent(t->release_event);
+ ReleaseList(t->PoolWaitList);
+
+ if (t->Name != NULL)
+ {
+ Free(t->Name);
+ }
+
+ Free(t);
+
+ current_num_thread--;
+ //Debug("current_num_thread = %u\n", current_num_thread);
+}
+
+// Release thread (pool)
+void ReleaseThread(THREAD *t)
+{
+ UINT ret;
+ EVENT *e;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ e = t->release_event;
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ ret = Release(t->ref);
+ Set(e);
+
+ ReleaseEvent(e);
+
+ if (ret == 0)
+ {
+ CleanupThread(t);
+ }
+}
+
+// Notify the completion of the thread initialization (pool)
+void NoticeThreadInit(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Notification
+ Set(t->init_finished_event);
+}
+
+// Wait the completion of the thread initialization (pool)
+void WaitThreadInit(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_WAITFORTHREAD_COUNT);
+
+ // Wait
+ Wait(t->init_finished_event, INFINITE);
+}
+
+// Wait for the termination of the thread (pool)
+bool WaitThread(THREAD *t, UINT timeout)
+{
+ bool ret = false;
+ EVENT *e = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ LockList(t->PoolWaitList);
+ {
+ if (t->PoolHalting)
+ {
+ // Has already been stopped
+ ret = true;
+ }
+ else
+ {
+ // Register the completion notifying event to the list
+ e = NewEvent();
+ AddRef(e->ref);
+ Insert(t->PoolWaitList, e);
+ }
+ }
+ UnlockList(t->PoolWaitList);
+
+ if (e != NULL)
+ {
+ // Wait Event
+ ret = Wait(e, timeout);
+
+ LockList(t->PoolWaitList);
+ {
+ if (Delete(t->PoolWaitList, e))
+ {
+ ReleaseEvent(e);
+ }
+ }
+ UnlockList(t->PoolWaitList);
+
+ ReleaseEvent(e);
+ }
+
+ return ret;
+}
+
+// Get Thread ID
+UINT ThreadId()
+{
+ return OSThreadId();
+}
+
+// Creating a thread
+THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
+{
+ THREAD *t;
+ UINT retry = 0;
+ // Validate arguments
+ if (thread_proc == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize Thread object
+ t = ZeroMalloc(sizeof(THREAD));
+ t->init_finished_event = NewEvent();
+
+ t->param = param;
+ t->ref = NewRef();
+ t->thread_proc = thread_proc;
+
+ // Wait until the OS to initialize the thread
+ while (true)
+ {
+ if ((retry++) > 60)
+ {
+ printf("\n\n*** error: new thread create failed.\n\n");
+ AbortExit();
+ }
+ if (OSInitThread(t))
+ {
+ break;
+ }
+ SleepThread(500);
+ }
+
+ // KS
+ KS_INC(KS_NEWTHREAD_COUNT);
+
+ return t;
+}
+
+// Release of thread
+void ReleaseThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (Release(t->ref) == 0)
+ {
+ CleanupThreadInternal(t);
+ }
+}
+
+// Clean up of the thread
+void CleanupThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Release of the thread
+ OSFreeThread(t);
+
+ // Release the event
+ ReleaseEvent(t->init_finished_event);
+ // Memory release
+ Free(t);
+
+ // KS
+ KS_INC(KS_FREETHREAD_COUNT);
+}
+
+// Wait for the termination of the thread
+bool WaitThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ return OSWaitThread(t);
+}
+
+// Notify that the thread initialization is complete
+void NoticeThreadInitInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Notify
+ Set(t->init_finished_event);
+}
+
+// Wait for completion of thread initialization
+void WaitThreadInitInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_WAITFORTHREAD_COUNT);
+
+ // Wait
+ Wait(t->init_finished_event, INFINITE);
+}
+
+// Get the date and time string by using the locale information
+void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
+ GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
+ UniFormat(str, size, L"%s %s", tmp1, tmp2);
+}
+
+// Get the time string by using the locale information
+void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t *tag = L"%02u%s%02u%s%02u%s";
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
+ {
+ tag = L"%2u%s%2u%s%2u%s";
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+ UniFormat(str, size,
+ tag,
+ st->wHour, locale->HourStr,
+ st->wMinute, locale->MinuteStr,
+ st->wSecond, locale->SecondStr);
+}
+
+// Get a date string by using the locale information
+void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
+ {
+ tag = L"%4u%s%2u%s%2u%s(%s)";
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+ UniFormat(str, size,
+ tag,
+ st->wYear, locale->YearStr,
+ st->wMonth, locale->MonthStr,
+ st->wDay, locale->DayStr,
+ locale->DayOfWeek[st->wDayOfWeek]);
+}
+
+// Get the time string to milliseconds (for example, 12:34:56.789)
+void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (st == NULL || str == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02u:%02u:%02u.%03u",
+ st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
+}
+
+// Get the time string (for example, 12:34:56)
+void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02u:%02u:%02u",
+ st->wHour, st->wMinute, st->wSecond);
+}
+
+// Get the date string (example: 2004/07/23)
+void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u",
+ st->wYear, st->wMonth, st->wDay);
+}
+
+// Get the date and time string (example: 2004/07/23 12:34:56)
+void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
+ st->wYear, st->wMonth, st->wDay,
+ st->wHour, st->wMinute, st->wSecond);
+}
+
+// Get the date and time string in milliseconds (example: 2004/07/23 12:34:56.789)
+void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
+ st->wYear, st->wMonth, st->wDay,
+ st->wHour, st->wMinute, st->wSecond,
+ st->wMilliseconds);
+}
+
+// Get the time string
+void GetSpanStr(char *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), "");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
+ }
+
+ Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
+
+ Trim(tmp);
+ StrCpy(str, size, tmp);
+}
+
+// Get the time string (in milliseconds)
+void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), "");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
+ }
+
+ Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
+ (UINT)(sec64 % (UINT64)(1000)));
+
+ Trim(tmp);
+ StrCpy(str, size, tmp);
+}
+
+// Get the time string (extended)
+void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+
+ UniStrCpy(tmp, sizeof(tmp), L"");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
+ locale->SpanDay);
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ locale->SpanHour,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ locale->SpanMinute,
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
+ locale->SpanSecond);
+
+ UniTrim(tmp);
+ UniStrCpy(str, size, tmp);
+}
+
+// Get the current locale information
+void GetCurrentLocale(LOCALE *locale)
+{
+ // Validate arguments
+ if (locale == NULL)
+ {
+ return;
+ }
+
+ Copy(locale, &current_locale, sizeof(LOCALE));
+}
+
+// Set the locale information
+void SetLocale(wchar_t *str)
+{
+ wchar_t *set_locale_str;
+ LOCALE tmp;
+
+ if (str != NULL)
+ {
+ set_locale_str = str;
+ }
+ else
+ {
+ set_locale_str = default_locale_str;
+ }
+
+ if (LoadLocale(&tmp, set_locale_str) == false)
+ {
+ if (LoadLocale(&tmp, default_locale_str) == false)
+ {
+ return;
+ }
+ }
+
+ Copy(&current_locale, &tmp, sizeof(LOCALE));
+}
+
+#define COPY_LOCALE_STR(dest, size, src) UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
+
+// Read the locale information
+bool LoadLocale(LOCALE *locale, wchar_t *str)
+{
+ UNI_TOKEN_LIST *tokens;
+ UINT i;
+ // Validate arguments
+ if (locale == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // Analysis of the token
+ tokens = UniParseToken(str, L" ");
+ if (tokens->NumTokens != 18)
+ {
+ UniFreeToken(tokens);
+ return false;
+ }
+
+ // Set to the structure
+ Zero(locale, sizeof(LOCALE));
+ COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
+ COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
+ COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
+ COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
+ COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
+ COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
+
+ for (i = 0;i < 7;i++)
+ {
+ COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
+ tokens->Token[6 + i]);
+ }
+
+ COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
+ COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
+ COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
+ COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
+
+ COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
+
+ UniFreeToken(tokens);
+ return true;
+}
+
+// Convert SYSTEMTIME into DOS date
+USHORT SystemToDosDate(SYSTEMTIME *st)
+{
+ return (USHORT)(
+ ((UINT)(st->wYear - 1980) << 9) |
+ ((UINT)st->wMonth<< 5) |
+ (UINT)st->wDay);
+}
+USHORT System64ToDosDate(UINT64 i)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, i);
+ return SystemToDosDate(&st);
+}
+
+// Convert SYSTEMTIME into DOS time
+USHORT SystemToDosTime(SYSTEMTIME *st)
+{
+ return (USHORT)(
+ ((UINT)st->wHour << 11) |
+ ((UINT)st->wMinute << 5) |
+ ((UINT)st->wSecond >> 1));
+}
+USHORT System64ToDosTime(UINT64 i)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, i);
+ return SystemToDosTime(&st);
+}
+
+// Convert the tm to the SYSTEMTIME
+void TmToSystem(SYSTEMTIME *st, struct tm *t)
+{
+ struct tm tmp;
+ // Validate arguments
+ if (st == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Copy(&tmp, t, sizeof(struct tm));
+ NormalizeTm(&tmp);
+
+ Zero(st, sizeof(SYSTEMTIME));
+ st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2037);
+ st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
+ st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
+ st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
+ st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
+ st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
+ st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
+ st->wMilliseconds = 0;
+}
+
+// Convert the SYSTEMTIME to tm
+void SystemToTm(struct tm *t, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (t == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(struct tm));
+ t->tm_year = MAKESURE(st->wYear, 1970, 2037) - 1900;
+ t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
+ t->tm_mday = MAKESURE(st->wDay, 1, 31);
+ t->tm_hour = MAKESURE(st->wHour, 0, 23);
+ t->tm_min = MAKESURE(st->wMinute, 0, 59);
+ t->tm_sec = MAKESURE(st->wSecond, 0, 59);
+
+ t->tm_isdst = -1;
+ NormalizeTm(t);
+}
+
+// Convert the time_t to SYSTEMTIME
+void TimeToSystem(SYSTEMTIME *st, time_t t)
+{
+ struct tm tmp;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ TimeToTm(&tmp, t);
+ TmToSystem(st, &tmp);
+}
+
+// Convert the time_t to 64-bit SYSTEMTIME
+UINT64 TimeToSystem64(time_t t)
+{
+ SYSTEMTIME st;
+
+ TimeToSystem(&st, t);
+
+ return SystemToUINT64(&st);
+}
+
+// Convert the SYSTEMTIME to time_t
+time_t SystemToTime(SYSTEMTIME *st)
+{
+ struct tm t;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return 0;
+ }
+
+ SystemToTm(&t, st);
+ return TmToTime(&t);
+}
+
+// Convert a 64-bit SYSTEMTIME to a time_t
+time_t System64ToTime(UINT64 i)
+{
+ SYSTEMTIME st;
+
+ UINT64ToSystem(&st, i);
+
+ return SystemToTime(&st);
+}
+
+// Convert the tm to time_t
+time_t TmToTime(struct tm *t)
+{
+ time_t tmp;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ tmp = c_mkgmtime(t);
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+ return tmp;
+}
+
+// Convert time_t to tm
+void TimeToTm(struct tm *t, time_t time)
+{
+ struct tm *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+#ifndef OS_UNIX
+ ret = gmtime(&time);
+#else // OS_UNIX
+ ret = malloc(sizeof(struct tm));
+ memset(ret, 0, sizeof(ret));
+ gmtime_r(&time, ret);
+#endif // OS_UNIX
+
+ if (ret == NULL)
+ {
+ Zero(t, sizeof(struct tm));
+ }
+ else
+ {
+ Copy(t, ret, sizeof(struct tm));
+ }
+
+#ifdef OS_UNIX
+ free(ret);
+#endif // OS_UNIX
+}
+
+// Normalize the tm
+void NormalizeTm(struct tm *t)
+{
+ struct tm *ret;
+ time_t tmp;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ tmp = c_mkgmtime(t);
+ if (tmp == (time_t)-1)
+ {
+ return;
+ }
+
+#ifndef OS_UNIX
+ ret = gmtime(&tmp);
+#else // OS_UNIX
+ ret = malloc(sizeof(struct tm));
+ memset(ret, 0, sizeof(ret));
+ gmtime_r(&tmp, ret);
+#endif // OS_UNIX
+
+ if (ret == NULL)
+ {
+ Zero(t, sizeof(struct tm));
+ }
+ else
+ {
+ Copy(t, ret, sizeof(struct tm));
+ }
+
+#ifdef OS_UNIX
+ free(ret);
+#endif // OS_UNIX
+}
+
+// Normalize the SYSTEMTIME
+void NormalizeSystem(SYSTEMTIME *st)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ sec64 = SystemToUINT64(st);
+ UINT64ToSystem(st, sec64);
+}
+
+// Convert a 64-bit local time to a system time
+UINT64 LocalToSystem64(UINT64 t)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, t);
+ LocalToSystem(&st, &st);
+ return SystemToUINT64(&st);
+}
+
+// Convert the 64bit system time to local time
+UINT64 SystemToLocal64(UINT64 t)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, t);
+ SystemToLocal(&st, &st);
+ return SystemToUINT64(&st);
+}
+
+// Convert local time to system time
+void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (local == NULL || system == NULL)
+ {
+ return;
+ }
+
+ sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
+ UINT64ToSystem(system, sec64);
+}
+
+// Convert the system time to local time
+void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (local == NULL || system == NULL)
+ {
+ return;
+ }
+
+ sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
+ UINT64ToSystem(local, sec64);
+}
+
+// Get the time difference between the local time and the system time based on the specified time
+INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
+{
+ time_t tmp;
+ struct tm t1, t2;
+ SYSTEMTIME snow;
+ struct tm now;
+ SYSTEMTIME s1, s2;
+ INT64 ret;
+
+ Copy(&snow, basetime, sizeof(SYSTEMTIME));
+
+ SystemToTm(&now, &snow);
+ if (local_time == false)
+ {
+ tmp = c_mkgmtime(&now);
+ }
+ else
+ {
+ tmp = mktime(&now);
+ }
+
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+
+ Copy(&t1, localtime(&tmp), sizeof(struct tm));
+ Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+ TmToSystem(&s1, &t1);
+ TmToSystem(&s2, &t2);
+
+ ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
+
+ return ret;
+}
+
+// Get the time difference between the local time and system time
+INT64 GetTimeDiff()
+{
+ time_t tmp;
+ struct tm t1, t2;
+ SYSTEMTIME snow;
+ struct tm now;
+ SYSTEMTIME s1, s2;
+ INT64 ret;
+
+ static INT64 cache = INFINITE;
+
+ if (cache != INFINITE)
+ {
+ // Returns the cache data after measured once
+ return cache;
+ }
+
+ SystemTime(&snow);
+ SystemToTm(&now, &snow);
+ tmp = c_mkgmtime(&now);
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+
+ Copy(&t1, localtime(&tmp), sizeof(struct tm));
+ Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+ TmToSystem(&s1, &t1);
+ TmToSystem(&s2, &t2);
+
+ cache = ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
+
+ return ret;
+}
+
+// Convert UINT64 to the SYSTEMTIME
+void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
+{
+ UINT64 tmp64;
+ UINT sec, millisec;
+ time_t time;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ sec64 = SafeTime64(sec64 + 32400000ULL);
+ tmp64 = sec64 / (UINT64)1000;
+ millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
+ sec = (UINT)tmp64;
+ time = (time_t)sec;
+ TimeToSystem(st, time);
+ st->wMilliseconds = (WORD)millisec;
+}
+
+// Convert the SYSTEMTIME to UINT64
+UINT64 SystemToUINT64(SYSTEMTIME *st)
+{
+ UINT64 sec64;
+ time_t time;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return 0;
+ }
+
+ time = SystemToTime(st);
+ sec64 = (UINT64)time * (UINT64)1000;
+ sec64 += st->wMilliseconds;
+
+ return sec64 - 32400000ULL;
+}
+
+// Get local time in UINT64
+UINT64 LocalTime64()
+{
+ SYSTEMTIME s;
+ LocalTime(&s);
+ return SystemToUINT64(&s);
+}
+
+// Get the system time in UINT64
+UINT64 SystemTime64()
+{
+ SYSTEMTIME s;
+ SystemTime(&s);
+ return SystemToUINT64(&s);
+}
+
+// Get local time
+void LocalTime(SYSTEMTIME *st)
+{
+ SYSTEMTIME tmp;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ SystemTime(&tmp);
+ SystemToLocal(st, &tmp);
+}
+
+// Get the System Time
+void SystemTime(SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ OSGetSystemTime(st);
+
+ // KS
+ KS_INC(KS_GETTIME_COUNT);
+}
+
+time_t c_mkgmtime(struct tm *tm)
+{
+ int years, months, days, hours, minutes, seconds;
+
+ years = tm->tm_year + 1900; /* year - 1900 -> year */
+ months = tm->tm_mon; /* 0..11 */
+ days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
+ hours = tm->tm_hour; /* 0..23 */
+ minutes = tm->tm_min; /* 0..59 */
+ seconds = tm->tm_sec; /* 0..61 in ANSI C. */
+
+ ADJUST_TM(seconds, minutes, 60);
+ ADJUST_TM(minutes, hours, 60);
+ ADJUST_TM(hours, days, 24);
+ ADJUST_TM(months, years, 12);
+ if (days < 0)
+ do {
+ if (--months < 0) {
+ --years;
+ months = 11;
+ }
+ days += monthlen(months, years);
+ } while (days < 0);
+ else
+ while (days >= monthlen(months, years)) {
+ days -= monthlen(months, years);
+ if (++months >= 12) {
+ ++years;
+ months = 0;
+ }
+ }
+
+ /* Restore adjusted values in tm structure */
+ tm->tm_year = years - 1900;
+ tm->tm_mon = months;
+ tm->tm_mday = days + 1;
+ tm->tm_hour = hours;
+ tm->tm_min = minutes;
+ tm->tm_sec = seconds;
+
+ /* Set `days' to the number of days into the year. */
+ days += ydays[months] + (months > 1 && leap (years));
+ tm->tm_yday = days;
+
+ /* Now calculate `days' to the number of days since Jan 1, 1970. */
+ days = (unsigned)days + 365 * (unsigned)(years - 1970) +
+ (unsigned)(nleap (years));
+ tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
+ tm->tm_isdst = 0;
+
+ if (years < 1970)
+ return (time_t)-1;
+
+#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
+#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
+ if (years > TM_YEAR_MAX ||
+ (years == TM_YEAR_MAX &&
+ (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+ (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
+ (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+ (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
+ (hours > TM_HOUR_MAX ||
+ (hours == TM_HOUR_MAX &&
+ (minutes > TM_MIN_MAX ||
+ (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
+ return (time_t)-1;
+#endif
+#endif
+
+ return (time_t)(86400L * (unsigned long)(unsigned)days +
+ 3600L * (unsigned long)hours +
+ (unsigned long)(60 * minutes + seconds));
+}
+
+// Get the system timer
+UINT Tick()
+{
+ // KS
+ KS_INC(KS_GETTICK_COUNT);
+ return OSGetTick();
+}
+
+// Sleep thread
+void SleepThread(UINT time)
+{
+ // KS
+ KS_INC(KS_SLEEPTHREAD_COUNT);
+
+ OSSleep(time);
+}
+
+// Yield
+void YieldCpu()
+{
+ OSYield();
+}
+
+// Stop system (abnormal termination)
+void AbortExit()
+{
+#ifdef OS_WIN32
+ _exit(1);
+#else // OS_WIN32
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, 0);
+#endif // RLIMIT_CORE
+
+ abort();
+#endif // OS_WIN32
+}
+
+
+void AbortExitEx(char *msg)
+{
+ FILE *f;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Unknown Error";
+ }
+
+ f = fopen("abort_error_log.txt", "w");
+ if (f != NULL)
+ {
+ fwrite(msg, 1, strlen(msg), f);
+ fclose(f);
+ }
+
+ fputs("Fatal Error: ", stdout);
+ fputs(msg, stdout);
+ fputs("\r\n", stdout);
+
+#ifdef OS_WIN32
+ _exit(1);
+#else // OS_WIN32
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, 0);
+#endif // RLIMIT_CORE
+
+ abort();
+#endif // OS_WIN32
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Kernel.h b/src/Mayaqua/Kernel.h
new file mode 100644
index 00000000..9e55979d
--- /dev/null
+++ b/src/Mayaqua/Kernel.h
@@ -0,0 +1,252 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#ifndef KERNEL_H
+#define KERNEL_H
+
+// Memory usage information
+struct MEMINFO
+{
+ UINT64 TotalMemory;
+ UINT64 UsedMemory;
+ UINT64 FreeMemory;
+ UINT64 TotalPhys;
+ UINT64 UsedPhys;
+ UINT64 FreePhys;
+};
+
+// Locale information
+struct LOCALE
+{
+ wchar_t YearStr[16], MonthStr[16], DayStr[16];
+ wchar_t HourStr[16], MinuteStr[16], SecondStr[16];
+ wchar_t DayOfWeek[7][16];
+ wchar_t SpanDay[16], SpanHour[16], SpanMinute[16], SpanSecond[16];
+ wchar_t Unknown[32];
+};
+
+
+// Thread procedure
+typedef void (THREAD_PROC)(THREAD *thread, void *param);
+
+// Thread
+struct THREAD
+{
+ REF *ref;
+ THREAD_PROC *thread_proc;
+ void *param;
+ void *pData;
+ EVENT *init_finished_event;
+ void *AppData1, *AppData2, *AppData3;
+ UINT AppInt1, AppInt2, AppInt3;
+ UINT ThreadId;
+ bool PoolThread;
+ THREAD *PoolHostThread;
+ LIST *PoolWaitList; // Thread termination waiting list
+ volatile bool PoolHalting; // Thread stopped
+ EVENT *release_event;
+ bool Stopped; // Indicates that the operation is Stopped
+ char *Name; // Thread name
+};
+
+// Thread pool data
+struct THREAD_POOL_DATA
+{
+ EVENT *Event; // Waiting Event
+ EVENT *InitFinishEvent; // Initialization is completed event
+ THREAD *Thread; // Threads that are currently assigned
+ THREAD_PROC *ThreadProc; // Thread procedure that is currently assigned
+};
+
+// Instance
+struct INSTANCE
+{
+ char *Name; // Name
+ void *pData; // Data
+};
+
+// Create a new thread
+#define NewThread(thread_proc, param) NewThreadNamed((thread_proc), (param), (#thread_proc))
+
+// Function prototype
+void SleepThread(UINT time);
+THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param);
+void ReleaseThreadInternal(THREAD *t);
+void CleanupThreadInternal(THREAD *t);
+void NoticeThreadInitInternal(THREAD *t);
+void WaitThreadInitInternal(THREAD *t);
+bool WaitThreadInternal(THREAD *t);
+THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name);
+void ReleaseThread(THREAD *t);
+void CleanupThread(THREAD *t);
+void NoticeThreadInit(THREAD *t);
+void WaitThreadInit(THREAD *t);
+bool WaitThread(THREAD *t, UINT timeout);
+void InitThreading();
+void FreeThreading();
+void ThreadPoolProc(THREAD *t, void *param);
+void SetThreadName(UINT thread_id, char *name, void *param);
+
+time_t c_mkgmtime(struct tm *tm);
+time_t System64ToTime(UINT64 i);
+void TmToSystem(SYSTEMTIME *st, struct tm *t);
+void SystemToTm(struct tm *t, SYSTEMTIME *st);
+void TimeToSystem(SYSTEMTIME *st, time_t t);
+UINT64 TimeToSystem64(time_t t);
+time_t SystemToTime(SYSTEMTIME *st);
+time_t TmToTime(struct tm *t);
+void TimeToTm(struct tm *t, time_t time);
+void NormalizeTm(struct tm *t);
+void NormalizeSystem(SYSTEMTIME *st);
+void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local);
+void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system);
+INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time);
+void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64);
+UINT64 SystemToUINT64(SYSTEMTIME *st);
+UINT64 LocalTime64();
+UINT64 SystemTime64();
+USHORT SystemToDosDate(SYSTEMTIME *st);
+USHORT System64ToDosDate(UINT64 i);
+USHORT SystemToDosTime(SYSTEMTIME *st);
+USHORT System64ToDosTime(UINT64 i);
+void LocalTime(SYSTEMTIME *st);
+void SystemTime(SYSTEMTIME *st);
+void SetLocale(wchar_t *str);
+bool LoadLocale(LOCALE *locale, wchar_t *str);
+void GetCurrentLocale(LOCALE *locale);
+void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st);
+void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st);
+void GetDateStr(char *str, UINT size, SYSTEMTIME *st);
+void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st);
+void GetTimeStr(char *str, UINT size, SYSTEMTIME *st);
+UINT Tick();
+UINT TickRealtime();
+UINT TickRealtimeManual();
+UINT64 TickGetRealtimeTickValue64();
+UINT64 SystemToLocal64(UINT64 t);
+UINT64 LocalToSystem64(UINT64 t);
+UINT ThreadId();
+void GetDateTimeStr64(char *str, UINT size, UINT64 sec64);
+void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64);
+void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64);
+void GetDateStr64(char *str, UINT size, UINT64 sec64);
+void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64);
+void GetTimeStr64(char *str, UINT size, UINT64 sec64);
+UINT64 SafeTime64(UINT64 sec64);
+bool Run(char *filename, char *arg, bool hide, bool wait);
+bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+void HashInstanceName(char *name, UINT size, char *instance_name);
+void HashInstanceNameLocal(char *name, UINT size, char *instance_name);
+INSTANCE *NewSingleInstance(char *instance_name);
+INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local);
+void FreeSingleInstance(INSTANCE *inst);
+void GetSpanStr(char *str, UINT size, UINT64 sec64);
+void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetSpanStrMilli(char *str, UINT size, UINT64 sec64);
+void GetMemInfo(MEMINFO *info);
+bool GetEnv(char *name, char *data, UINT size);
+bool GetEnvW(wchar_t *name, wchar_t *data, UINT size);
+bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size);
+bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size);
+void GetHomeDir(char *path, UINT size);
+void GetHomeDirW(wchar_t *path, UINT size);
+void AbortExit();
+void AbortExitEx(char *msg);
+void YieldCpu();
+UINT DoNothing();
+LIST *NewThreadList();
+void AddThreadToThreadList(LIST *o, THREAD *t);
+void DelThreadFromThreadList(LIST *o, THREAD *t);
+void MainteThreadList(LIST *o);
+void FreeThreadList(LIST *o);
+void StopThreadList(LIST *o);
+
+#endif // KERNEL_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/MayaType.h b/src/Mayaqua/MayaType.h
new file mode 100644
index 00000000..c3949872
--- /dev/null
+++ b/src/Mayaqua/MayaType.h
@@ -0,0 +1,553 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// MayaType.h
+// Mayaqua Kernel type declaration header file
+
+#ifndef MAYATYPE_H
+#define MAYATYPE_H
+
+// Check whether the windows.h header is included
+#ifndef WINDOWS_H
+#ifdef _WINDOWS_
+#define WINDOWS_H
+#endif // _WINDOWS_
+#endif // WINDOWS_H
+
+
+#if !defined(ENCRYPT_C) && !defined(HAM_C)
+// Structure which is used by OpenSSL
+typedef struct x509_st X509;
+typedef struct evp_pkey_st EVP_PKEY;
+typedef struct bio_st BIO;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct X509_req_st X509_REQ;
+typedef struct PKCS12 PKCS12;
+typedef struct bignum_st BIGNUM;
+typedef struct x509_crl_st X509_CRL;
+#endif // ENCRYPT_C
+
+//
+// Constant
+//
+
+// Standard buffer size
+#define STD_SIZE 512
+#define MAX_SIZE 512
+#define BUF_SIZE 512
+
+// Support Windows OS list
+#define SUPPORTED_WINDOWS_LIST "Windows 98 / 98 SE / ME / NT 4.0 SP6a / 2000 SP4 / XP SP2, SP3 / Server 2003 SP2 / Vista SP1, SP2 / Server 2008 SP1, SP2 / Hyper-V Server 2008 / 7 SP1 / Server 2008 R2 SP1 / Hyper-V Server 2008 R2 / 8 / Server 2012 / Hyper-V Server 2012 / 8.1 / Server 2012 R2 / Hyper-V Server 2012 R2"
+
+// Infinite
+#ifndef WINDOWS_H
+#define INFINITE (0xFFFFFFFF)
+#endif
+
+
+#define SRC_NAME __FILE__ // File name of the source code
+#define SRC_LINE __LINE__ // Line number in the source code
+
+// Maximum path size
+#ifndef WINDOWS_H
+#define MAX_PATH 260
+#endif // WINDOWS_H
+
+// Types of seek
+#ifndef FILE_BEGIN
+#define FILE_BEGIN SEEK_SET
+#endif // FILE_BEGIN
+#ifndef FILE_END
+#define FILE_END SEEK_END
+#endif // FILE_END
+#ifndef FILE_CURRENT
+#define FILE_CURRENT SEEK_CUR
+#endif // FILE_CURRENT
+
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET (-1)
+#endif // INVALID_SOCKET
+
+#ifndef SOCKET_ERROR
+#define SOCKET_ERROR (-1)
+#endif //SOCKET_ERROR
+
+// Comparison function
+typedef int (COMPARE)(void *p1, void *p2);
+
+
+//
+// Macro
+
+
+#ifdef MAX
+#undef MAX
+#endif // MAX
+
+#ifdef MIN
+#undef MIN
+#endif // MIN
+
+// Minimum value of a and b
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+// Maximum value of a and b
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+// Convert an int value to bool
+#define INT_TO_BOOL(i) (((i) == 0) ? false : true)
+#define MAKEBOOL(i) INT_TO_BOOL(i)
+#define BOOL_TO_INT(i) (((i) == false) ? 0 : 1)
+
+// Invert the bool type value
+#define NEGATIVE_BOOL(i) (((i) == false) ? true : false)
+
+// Return 'a' less than max_value
+#define LESS(a, max_value) ((a) <= (max_value) ? (a) : (max_value))
+// Return 'a' greater than min_value
+#define MORE(a, min_value) ((a) >= (min_value) ? (a) : (min_value))
+// Examine whether the value a is between the b and c
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+// Examine whether the value a is outbound of b and c
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+// Adjust value 'a' to be between b and c
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+// Compare a and b
+#define COMPARE_RET(a, b) (((a) == (b)) ? 0 : (((a) > (b)) ? 1 : -1))
+// Compare bool type values
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+// Get the absolute value
+#define GET_ABS(a) ((a) >= 0 ? (a) : -(a))
+
+// Convert the pointer to UINT
+#define POINTER_TO_KEY(p) ((sizeof(void *) == sizeof(UINT)) ? (UINT)(p) : HashPtrToUINT(p))
+// Compare the pointer and UINT
+#define COMPARE_POINTER_AND_KEY(p, i) (POINTER_TO_KEY(p) == (i))
+// Convert the pointer to UINT64
+#define POINTER_TO_UINT64(p) (((sizeof(void *) == sizeof(UINT64)) ? (UINT64)(p) : (UINT64)((UINT)(p))))
+// Convert a UINT64 to pointer
+#define UINT64_TO_POINTER(i) ((sizeof(void *) == sizeof(UINT64)) ? (void *)(i) : (void *)((UINT)(i)))
+
+// Add the value
+#define UINT_ADD(i, j) ((i == INFINITE || i == 0x7fffffff) ? (i) : (i += j))
+
+// Reading data that is not dependent on the boundary or the endian
+#define READ_USHORT(buf) (USHORT)((((USHORT)((UCHAR *)(buf))[0]) << 8) | (((USHORT)((UCHAR *)(buf))[1])))
+#define READ_UINT(buf) (UINT)((((UINT)((UCHAR *)(buf))[0]) << 24) | (((UINT)((UCHAR *)(buf))[1]) << 16) | (((UINT)((UCHAR *)(buf))[2]) << 8) | (((UINT)((UCHAR *)(buf))[3])))
+#define READ_UINT64(buf) (UINT64)((((UINT64)((UCHAR *)(buf))[0]) << 56) | (((UINT64)((UCHAR *)(buf))[1]) << 48) | (((UINT64)((UCHAR *)(buf))[2]) << 40) | (((UINT64)((UCHAR *)(buf))[3]) << 32) | (((UINT64)((UCHAR *)(buf))[4]) << 24) | (((UINT64)((UCHAR *)(buf))[5]) << 16) | (((UINT64)((UCHAR *)(buf))[6]) << 8) | (((UINT64)((UCHAR *)(buf))[7])))
+
+// Writing data that is not dependent on the boundary or endian
+#define WRITE_USHORT(buf, i) (((UCHAR *)(buf))[0]) = ((((USHORT)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[1]) = ((((USHORT)(i))) & 0xFF)
+#define WRITE_UINT(buf, i) (((UCHAR *)(buf))[0]) = ((((UINT)(i)) >> 24) & 0xFF); (((UCHAR *)(buf))[1]) = ((((UINT)(i)) >> 16) & 0xFF); (((UCHAR *)(buf))[2]) = ((((UINT)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[3]) = ((((UINT)(i))) & 0xFF)
+#define WRITE_UINT64(buf, i) (((UCHAR *)(buf))[0]) = ((((UINT64)(i)) >> 56) & 0xFF); (((UCHAR *)(buf))[1]) = ((((UINT64)(i)) >> 48) & 0xFF); (((UCHAR *)(buf))[2]) = ((((UINT64)(i)) >> 40) & 0xFF); (((UCHAR *)(buf))[3]) = ((((UINT64)(i)) >> 32) & 0xFF); (((UCHAR *)(buf))[4]) = ((((UINT64)(i)) >> 24) & 0xFF); (((UCHAR *)(buf))[5]) = ((((UINT64)(i)) >> 16) & 0xFF); (((UCHAR *)(buf))[6]) = ((((UINT64)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[7]) = ((((UINT64)(i))) & 0xFF)
+
+
+
+//
+// Type declaration
+//
+
+// bool type
+#ifndef WINDOWS_H
+typedef unsigned int BOOL;
+#define TRUE 1
+#define FALSE 0
+#endif // WINDOWS_H
+
+// bool type
+#ifndef WIN32COM_CPP
+typedef unsigned int bool;
+#define true 1
+#define false 0
+#endif // WIN32COM_CPP
+
+// 32bit integer type
+#ifndef WINDOWS_H
+typedef unsigned int UINT;
+typedef unsigned int UINT32;
+typedef unsigned int DWORD;
+typedef signed int INT;
+typedef signed int INT32;
+
+typedef int UINT_PTR;
+typedef long LONG_PTR;
+
+#endif
+
+// 16bit integer type
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+
+// 8bit integer type
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+
+#ifndef WIN32COM_CPP
+typedef signed char CHAR;
+#endif // WIN32COM_CPP
+
+
+// 64-bit integer type
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+
+#ifdef OS_UNIX
+// Avoiding compile error
+#define __cdecl
+#define __declspec(x)
+// socket type
+typedef int SOCKET;
+#else // OS_UNIX
+#ifndef _WINSOCK2API_
+typedef UINT_PTR SOCKET;
+#endif // _WINSOCK2API_
+#endif // OS_UNIX
+
+// OS type
+#define OSTYPE_WINDOWS_95 1100 // Windows 95
+#define OSTYPE_WINDOWS_98 1200 // Windows 98
+#define OSTYPE_WINDOWS_ME 1300 // Windows Me
+#define OSTYPE_WINDOWS_UNKNOWN 1400 // Windows (unknown)
+#define OSTYPE_WINDOWS_NT_4_WORKSTATION 2100 // Windows NT 4.0 Workstation
+#define OSTYPE_WINDOWS_NT_4_SERVER 2110 // Windows NT 4.0 Server
+#define OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE 2111 // Windows NT 4.0 Server, Enterprise Edition
+#define OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER 2112 // Windows NT 4.0 Terminal Server
+#define OSTYPE_WINDOWS_NT_4_BACKOFFICE 2113 // BackOffice Server 4.5
+#define OSTYPE_WINDOWS_NT_4_SMS 2114 // Small Business Server 4.5
+#define OSTYPE_WINDOWS_2000_PROFESSIONAL 2200 // Windows 2000 Professional
+#define OSTYPE_WINDOWS_2000_SERVER 2211 // Windows 2000 Server
+#define OSTYPE_WINDOWS_2000_ADVANCED_SERVER 2212 // Windows 2000 Advanced Server
+#define OSTYPE_WINDOWS_2000_DATACENTER_SERVER 2213 // Windows 2000 Datacenter Server
+#define OSTYPE_WINDOWS_2000_BACKOFFICE 2214 // BackOffice Server 2000
+#define OSTYPE_WINDOWS_2000_SBS 2215 // Small Business Server 2000
+#define OSTYPE_WINDOWS_XP_HOME 2300 // Windows XP Home Edition
+#define OSTYPE_WINDOWS_XP_PROFESSIONAL 2301 // Windows XP Professional
+#define OSTYPE_WINDOWS_2003_WEB 2410 // Windows Server 2003 Web Edition
+#define OSTYPE_WINDOWS_2003_STANDARD 2411 // Windows Server 2003 Standard Edition
+#define OSTYPE_WINDOWS_2003_ENTERPRISE 2412 // Windows Server 2003 Enterprise Edition
+#define OSTYPE_WINDOWS_2003_DATACENTER 2413 // Windows Server 2003 DataCenter Edition
+#define OSTYPE_WINDOWS_2003_BACKOFFICE 2414 // BackOffice Server 2003
+#define OSTYPE_WINDOWS_2003_SBS 2415 // Small Business Server 2003
+#define OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL 2500 // Windows Vista
+#define OSTYPE_WINDOWS_LONGHORN_SERVER 2510 // Windows Server 2008
+#define OSTYPE_WINDOWS_7 2600 // Windows 7
+#define OSTYPE_WINDOWS_SERVER_2008_R2 2610 // Windows Server 2008 R2
+#define OSTYPE_WINDOWS_8 2700 // Windows 8
+#define OSTYPE_WINDOWS_SERVER_8 2710 // Windows Server 2012
+#define OSTYPE_WINDOWS_81 2701 // Windows 8.1
+#define OSTYPE_WINDOWS_SERVER_81 2711 // Windows Server 2012 R2
+#define OSTYPE_WINDOWS_9 2800 // Windows 9
+#define OSTYPE_WINDOWS_SERVER_9 2810 // Windows Server 9
+#define OSTYPE_UNIX_UNKNOWN 3000 // Unknown UNIX
+#define OSTYPE_LINUX 3100 // Linux
+#define OSTYPE_SOLARIS 3200 // Solaris
+#define OSTYPE_CYGWIN 3300 // Cygwin
+#define OSTYPE_BSD 3400 // BSD
+#define OSTYPE_MACOS_X 3500 // MacOS X
+
+
+// OS discrimination macro
+#define GET_KETA(t, i) (((t) % (i * 10)) / i)
+#define OS_IS_WINDOWS_9X(t) (GET_KETA(t, 1000) == 1)
+#define OS_IS_WINDOWS_NT(t) (GET_KETA(t, 1000) == 2)
+#define OS_IS_WINDOWS(t) (OS_IS_WINDOWS_9X(t) || OS_IS_WINDOWS_NT(t))
+#define OS_IS_SERVER(t) (OS_IS_WINDOWS_NT(t) && GET_KETA(t, 10))
+#define OS_IS_WORKSTATION(t) ((OS_IS_WINDOWS_NT(t) && (!(GET_KETA(t, 10)))) || OS_IS_WINDOWS_9X(t))
+#define OS_IS_UNIX(t) (GET_KETA(t, 1000) == 3)
+
+
+// OS information
+typedef struct OS_INFO
+{
+ UINT OsType; // OS type
+ UINT OsServicePack; // Service pack number
+ char *OsSystemName; // OS system name
+ char *OsProductName; // OS product name
+ char *OsVendorName; // OS vendor name
+ char *OsVersion; // OS version
+ char *KernelName; // Kernel name
+ char *KernelVersion; // Kernel version
+} OS_INFO;
+
+// Time type
+#ifndef WINDOWS_H
+typedef struct SYSTEMTIME
+{
+ WORD wYear;
+ WORD wMonth;
+ WORD wDayOfWeek;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wMilliseconds;
+} SYSTEMTIME;
+#endif // WINDOWS_H
+
+
+// Object.h
+typedef struct LOCK LOCK;
+typedef struct COUNTER COUNTER;
+typedef struct REF REF;
+typedef struct EVENT EVENT;
+typedef struct DEADCHECK DEADCHECK;
+
+// Tracking.h
+typedef struct CALLSTACK_DATA CALLSTACK_DATA;
+typedef struct TRACKING_OBJECT TRACKING_OBJECT;
+typedef struct MEMORY_STATUS MEMORY_STATUS;
+typedef struct TRACKING_LIST TRACKING_LIST;
+
+// FileIO.h
+typedef struct IO IO;
+
+// Memory.h
+typedef struct MEMTAG MEMTAG;
+typedef struct BUF BUF;
+typedef struct FIFO FIFO;
+typedef struct LIST LIST;
+typedef struct QUEUE QUEUE;
+typedef struct SK SK;
+typedef struct CANDIDATE CANDIDATE;
+typedef struct STRMAP_ENTRY STRMAP_ENTRY;
+typedef struct SHARED_BUFFER SHARED_BUFFER;
+typedef struct HASH_LIST HASH_LIST;
+typedef struct HASH_ENTRY HASH_ENTRY;
+
+// Str.h
+typedef struct TOKEN_LIST TOKEN_LIST;
+typedef struct INI_ENTRY INI_ENTRY;
+
+// Internat.h
+typedef struct UNI_TOKEN_LIST UNI_TOKEN_LIST;
+
+// Encrypt.h
+typedef struct CRYPT CRYPT;
+typedef struct NAME NAME;
+typedef struct X_SERIAL X_SERIAL;
+typedef struct X X;
+typedef struct K K;
+typedef struct P12 P12;
+typedef struct X_CRL X_CRL;
+typedef struct DES_KEY_VALUE DES_KEY_VALUE;
+typedef struct DES_KEY DES_KEY;
+typedef struct DH_CTX DH_CTX;
+typedef struct AES_KEY_VALUE AES_KEY_VALUE;
+typedef struct CIPHER CIPHER;
+typedef struct MD MD;
+
+// Secure.h
+typedef struct SECURE_DEVICE SECURE_DEVICE;
+typedef struct SEC_INFO SEC_INFO;
+typedef struct SECURE SECURE;
+typedef struct SEC_OBJ SEC_OBJ;
+
+// Kernel.h
+typedef struct MEMINFO MEMINFO;
+typedef struct LOCALE LOCALE;
+typedef struct THREAD THREAD;
+typedef struct THREAD_POOL_DATA THREAD_POOL_DATA;
+typedef struct INSTANCE INSTANCE;
+
+// Pack.h
+typedef struct VALUE VALUE;
+typedef struct ELEMENT ELEMENT;
+typedef struct PACK PACK;
+
+// Cfg.h
+typedef struct FOLDER FOLDER;
+typedef struct ITEM ITEM;
+typedef struct CFG_RW CFG_RW;
+typedef struct CFG_ENUM_PARAM CFG_ENUM_PARAM;
+
+// Table.h
+typedef struct TABLE TABLE;
+typedef struct LANGLIST LANGLIST;
+
+// Network.h
+typedef struct IP IP;
+typedef struct DNSCACHE DNSCACHE;
+typedef struct SOCK_EVENT SOCK_EVENT;
+typedef struct SOCK SOCK;
+typedef struct SOCKSET SOCKSET;
+typedef struct CANCEL CANCEL;
+typedef struct ROUTE_ENTRY ROUTE_ENTRY;
+typedef struct ROUTE_TABLE ROUTE_TABLE;
+typedef struct IP_CLIENT IP_CLIENT;
+typedef struct ROUTE_CHANGE ROUTE_CHANGE;
+typedef struct ROUTE_CHANGE_DATA ROUTE_CHANGE_DATA;
+typedef struct GETIP_THREAD_PARAM GETIP_THREAD_PARAM;
+typedef struct WIN32_RELEASEADDRESS_THREAD_PARAM WIN32_RELEASEADDRESS_THREAD_PARAM;
+typedef struct IPV6_ADDR IPV6_ADDR;
+typedef struct TUBE TUBE;
+typedef struct TUBEDATA TUBEDATA;
+typedef struct PSEUDO PSEUDO;
+typedef struct TUBEPAIR_DATA TUBEPAIR_DATA;
+typedef struct UDPLISTENER UDPLISTENER;
+typedef struct UDPLISTENER_SOCK UDPLISTENER_SOCK;
+typedef struct UDPPACKET UDPPACKET;
+typedef struct INTERRUPT_MANAGER INTERRUPT_MANAGER;
+typedef struct TUBE_FLUSH_LIST TUBE_FLUSH_LIST;
+typedef struct ICMP_RESULT ICMP_RESULT;
+typedef struct SSL_PIPE SSL_PIPE;
+typedef struct SSL_BIO SSL_BIO;
+typedef struct RUDP_STACK RUDP_STACK;
+typedef struct RUDP_SESSION RUDP_SESSION;
+typedef struct RUDP_SEGMENT RUDP_SEGMENT;
+typedef struct CONNECT_TCP_RUDP_PARAM CONNECT_TCP_RUDP_PARAM;
+typedef struct TCP_PAIR_HEADER TCP_PAIR_HEADER;
+typedef struct NIC_ENTRY NIC_ENTRY;
+typedef struct HTTP_VALUE HTTP_VALUE;
+typedef struct HTTP_HEADER HTTP_HEADER;
+typedef struct DNSPROXY_CLIENT DNSPROXY_CLIENT;
+typedef struct DNSPROXY_CACHE DNSPROXY_CACHE;
+typedef struct QUERYIPTHREAD QUERYIPTHREAD;
+typedef struct IPBLOCK IPBLOCK;
+typedef struct SAFE_REQUEST SAFE_REQUEST;
+typedef struct SAFE_LIST SAFE_LIST;
+typedef struct SAFE_QUOTA SAFE_QUOTA;
+typedef struct SAFE_QUOTA2 SAFE_QUOTA2;
+typedef struct SAFE_BLOCK SAFE_BLOCK;
+typedef struct SAFE_REQUEST_LOG SAFE_REQUEST_LOG;
+typedef struct DYN_VALUE DYN_VALUE;
+
+// Tick64.h
+typedef struct ADJUST_TIME ADJUST_TIME;
+typedef struct TICK64 TICK64;
+
+// FileIO.h
+typedef struct DIRENT DIRENT;
+typedef struct DIRLIST DIRLIST;
+typedef struct ZIP_DATA_HEADER ZIP_DATA_HEADER;
+typedef struct ZIP_DATA_FOOTER ZIP_DATA_FOOTER;
+typedef struct ZIP_DIR_HEADER ZIP_DIR_HEADER;
+typedef struct ZIP_END_HEADER ZIP_END_HEADER;
+typedef struct ZIP_FILE ZIP_FILE;
+typedef struct ZIP_PACKER ZIP_PACKER;
+
+// TcpIp.h
+typedef struct MAC_HEADER MAC_HEADER;
+typedef struct ARPV4_HEADER ARPV4_HEADER;
+typedef struct IPV4_HEADER IPV4_HEADER;
+typedef struct TAGVLAN_HEADER TAGVLAN_HEADER;
+typedef struct UDP_HEADER UDP_HEADER;
+typedef struct UDPV4_PSEUDO_HEADER UDPV4_PSEUDO_HEADER;
+typedef struct IPV4_PSEUDO_HEADER IPV4_PSEUDO_HEADER;
+typedef struct TCP_HEADER TCP_HEADER;
+typedef struct ICMP_HEADER ICMP_HEADER;
+typedef struct ICMP_ECHO ICMP_ECHO;
+typedef struct DHCPV4_HEADER DHCPV4_HEADER;
+typedef struct DNSV4_HEADER DNSV4_HEADER;
+typedef struct BPDU_HEADER BPDU_HEADER;
+typedef struct LLC_HEADER LLC_HEADER;
+typedef struct PKT PKT;
+typedef struct IPV6_HEADER_PACKET_INFO IPV6_HEADER_PACKET_INFO;
+typedef struct IPV6_HEADER IPV6_HEADER;
+typedef struct IPV6_OPTION_HEADER IPV6_OPTION_HEADER;
+typedef struct IPV6_FRAGMENT_HEADER IPV6_FRAGMENT_HEADER;
+typedef struct IPV6_PSEUDO_HEADER IPV6_PSEUDO_HEADER;
+typedef struct ICMPV6_ROUTER_SOLICIATION_HEADER ICMPV6_ROUTER_SOLICIATION_HEADER;
+typedef struct ICMPV6_ROUTER_ADVERTISEMENT_HEADER ICMPV6_ROUTER_ADVERTISEMENT_HEADER;
+typedef struct ICMPV6_NEIGHBOR_SOLICIATION_HEADER ICMPV6_NEIGHBOR_SOLICIATION_HEADER;
+typedef struct ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER;
+typedef struct ICMPV6_OPTION_LIST ICMPV6_OPTION_LIST;
+typedef struct ICMPV6_OPTION ICMPV6_OPTION;
+typedef struct ICMPV6_OPTION_LINK_LAYER ICMPV6_OPTION_LINK_LAYER;
+typedef struct ICMPV6_OPTION_PREFIX ICMPV6_OPTION_PREFIX;
+typedef struct ICMPV6_OPTION_MTU ICMPV6_OPTION_MTU;
+typedef struct IPV6_HEADER_INFO IPV6_HEADER_INFO;
+typedef struct ICMPV6_HEADER_INFO ICMPV6_HEADER_INFO;
+typedef struct DHCPV4_DATA DHCPV4_DATA;
+typedef struct DHCP_OPTION DHCP_OPTION;
+typedef struct DHCP_OPTION_LIST DHCP_OPTION_LIST;
+typedef struct HTTPLOG HTTPLOG;
+typedef struct DHCP_MODIFY_OPTION DHCP_MODIFY_OPTION;
+typedef struct NBTDG_HEADER NBTDG_HEADER;
+typedef struct IKE_HEADER IKE_HEADER;
+
+
+
+#endif // MAYATYPE_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.c b/src/Mayaqua/Mayaqua.c
new file mode 100644
index 00000000..5cc78a23
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.c
@@ -0,0 +1,1200 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Mayaqua.c
+// Mayaqua Kernel program
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <locale.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Global variable
+bool g_memcheck; // Enable memory check
+bool g_debug; // Debug mode
+UINT64 kernel_status[NUM_KERNEL_STATUS]; // Kernel state
+UINT64 kernel_status_max[NUM_KERNEL_STATUS]; // Kernel state (maximum value)
+LOCK *kernel_status_lock[NUM_KERNEL_STATUS]; // Kernel state lock
+BOOL kernel_status_inited = false; // Kernel state initialization flag
+bool g_little_endian = true;
+char *cmdline = NULL; // Command line
+wchar_t *uni_cmdline = NULL; // Unicode command line
+
+// Static variable
+static char *exename = NULL; // EXE file name (ANSI)
+static wchar_t *exename_w = NULL; // EXE file name (Unicode)
+static TOKEN_LIST *cmdline_token = NULL; // Command line token
+static UNI_TOKEN_LIST *cmdline_uni_token = NULL; // Command line token (Unicode)
+static OS_INFO *os_info = NULL; // OS information
+static bool dot_net_mode = false;
+static bool minimal_mode = false;
+static UINT last_time_check = 0;
+static UINT first_time_check = 0;
+static bool is_nt = false;
+static bool is_ham_mode = false;
+static UINT init_mayaqua_counter = 0;
+static bool use_probe = false;
+static BUF *probe_buf = NULL;
+static LOCK *probe_lock = NULL;
+static UINT64 probe_start = 0;
+static UINT64 probe_last = 0;
+static bool probe_enabled = false;
+
+
+
+// Calculate the checksum
+USHORT CalcChecksum16(void *buf, UINT size)
+{
+ int sum = 0;
+ USHORT *addr = (USHORT *)buf;
+ int len = (int)size;
+ USHORT *w = addr;
+ int nleft = len;
+ USHORT answer = 0;
+
+ while (nleft > 1)
+ {
+ USHORT ww = 0;
+ Copy(&ww, w++, sizeof(USHORT));
+ sum += ww;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *(UCHAR *)(&answer) = *(UCHAR *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ answer = ~sum;
+
+ return answer;
+}
+
+// Writing a probe with the data
+void WriteProbeData(char *filename, UINT line, char *str, void *data, UINT size)
+{
+ char tmp[MAX_SIZE];
+ USHORT cs;
+
+ if (IsProbeEnabled() == false)
+ {
+ return;
+ }
+
+ // Take a checksum of the data
+ if (size != 0)
+ {
+ cs = CalcChecksum16(data, size);
+ }
+ else
+ {
+ cs = 0;
+ }
+
+ // Generating a String
+ snprintf(tmp, sizeof(tmp), "\"%s\" (Size=%5u, Crc=0x%04X)", str, size, cs);
+
+ WriteProbe(filename, line, tmp);
+}
+
+// Writing Probe
+void WriteProbe(char *filename, UINT line, char *str)
+{
+#ifdef OS_WIN32
+ char *s;
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UINT64 now = 0;
+ UINT64 time;
+
+ if (IsProbeEnabled() == false)
+ {
+ return;
+ }
+
+ now = MsGetHiResCounter();
+
+ Lock(probe_lock);
+ {
+ UINT64 diff;
+
+ time = MsGetHiResTimeSpanUSec(now - probe_start);
+
+ diff = time - probe_last;
+
+ if (time < probe_last)
+ {
+ diff = 0;
+ }
+
+ probe_last = time;
+
+ ToStr64(tmp, time);
+ MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
+ WriteBuf(probe_buf, tmp2, StrLen(tmp2));
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = " [+";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ ToStr64(tmp, diff);
+ MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
+ WriteBuf(probe_buf, tmp2, StrLen(tmp2));
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = "] - ";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ WriteBuf(probe_buf, filename, StrLen(filename));
+
+ s = "(";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ ToStr64(tmp, (UINT64)line);
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = "): ";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ WriteBuf(probe_buf, str, StrLen(str));
+
+ s = "\r\n";
+ WriteBuf(probe_buf, s, StrLen(s));
+ }
+ Unlock(probe_lock);
+#endif // OS_WIN32
+}
+
+// Initialization of Probe
+void InitProbe()
+{
+ probe_buf = NewBuf();
+ probe_lock = NewLock();
+ probe_enabled = false;
+
+ probe_start = 0;
+
+#ifdef OS_WIN32
+ probe_start = MsGetHiResCounter();
+#endif // OS_WIN32
+}
+
+// Release of Probe
+void FreeProbe()
+{
+ if (probe_buf->Size >= 1)
+ {
+ SYSTEMTIME st;
+ char filename[MAX_SIZE];
+
+ // Write all to the file
+ MakeDirEx("@probe_log");
+
+ LocalTime(&st);
+
+ snprintf(filename, sizeof(filename), "@probe_log/%04u%02u%02u_%02u%02u%02u.log",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+
+ DumpBuf(probe_buf, filename);
+ }
+
+ FreeBuf(probe_buf);
+ DeleteLock(probe_lock);
+}
+
+// Set enable / disable the Probe
+void EnableProbe(bool enable)
+{
+ probe_enabled = enable;
+}
+
+// Get whether the Probe is enabled?
+bool IsProbeEnabled()
+{
+#ifndef USE_PROBE
+ return false;
+#else // USE_PROBE
+ return probe_enabled;
+#endif // USE_PROBE
+}
+
+// Set the Ham mode
+void SetHamMode()
+{
+ is_ham_mode = true;
+}
+
+// Get whether in Ham mode
+bool IsHamMode()
+{
+ return is_ham_mode;
+}
+
+// Display the time from the previous call to now
+void TimeCheck()
+{
+#ifdef OS_WIN32
+ UINT now, ret, total;
+ now = Win32GetTick();
+ if (last_time_check == 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = now - last_time_check;
+ }
+ last_time_check = now;
+
+ if (first_time_check == 0)
+ {
+ first_time_check = now;
+ }
+
+ total = now - first_time_check;
+
+ printf(" -- %3.3f / %3.3f\n", (double)ret / 1000.0f, (double)total / 1000.0f);
+#endif // OS_WIN32
+}
+
+// Whether this system is IA64
+bool IsIA64()
+{
+ if (Is64() == false)
+ {
+ return false;
+ }
+
+#ifndef MAYAQUA_IA_64
+ return false;
+#else // MAYAQUA_IA_64
+ return true;
+#endif // MAYAQUA_IA_64
+}
+
+// Whether in x64
+bool IsX64()
+{
+ if (Is64() == false)
+ {
+ return false;
+ }
+
+#ifndef MAYAQUA_IA_64
+ return true;
+#else // MAYAQUA_IA_64
+ return false;
+#endif // MAYAQUA_IA_64
+}
+
+// Whether 64bit
+bool Is64()
+{
+#ifdef CPU_64
+ return true;
+#else // CPU_64
+ return false;
+#endif // CPU_64
+}
+
+// Whether 32bit
+bool Is32()
+{
+ return Is64() ? false : true;
+}
+
+// .NET mode
+void MayaquaDotNetMode()
+{
+ dot_net_mode = true;
+}
+
+// Acquisition whether in .NET mode
+bool MayaquaIsDotNetMode()
+{
+ return dot_net_mode;
+}
+
+// Check the endian
+void CheckEndian()
+{
+ unsigned short test;
+ UCHAR *buf;
+
+ test = 0x1234;
+ buf = (UCHAR *)&test;
+ if (buf[0] == 0x12)
+ {
+ g_little_endian = false;
+ }
+ else
+ {
+ g_little_endian = true;
+ }
+}
+
+// Minimize mode
+void MayaquaMinimalMode()
+{
+ minimal_mode = true;
+}
+bool MayaquaIsMinimalMode()
+{
+ return minimal_mode;
+}
+
+// Whether in NT
+bool IsNt()
+{
+ return is_nt;
+}
+
+// Whether the Unicode is supported
+bool IsUnicode()
+{
+#ifdef OS_WIN32
+ // Windows
+ return IsNt();
+#else // OS_WIN32
+ // UNIX
+ return true;
+#endif // OS_WIN32
+}
+
+// Initialization of Mayaqua library
+void InitMayaqua(bool memcheck, bool debug, int argc, char **argv)
+{
+ wchar_t tmp[MAX_PATH];
+ UCHAR hash[SHA1_SIZE];
+
+ if ((init_mayaqua_counter++) > 0)
+ {
+ return;
+ }
+
+ g_memcheck = memcheck;
+ g_debug = debug;
+ cmdline = NULL;
+ if (dot_net_mode == false)
+ {
+ // Fail this for some reason when this is called this in .NET mode
+ setbuf(stdout, NULL);
+ }
+
+ // Acquisition whether NT
+#ifdef OS_WIN32
+ is_nt = Win32IsNt();
+#endif // OS_WIN32
+
+ // Check endian
+ CheckEndian();
+
+#ifdef OS_WIN32
+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
+#endif // OS_WIN32
+
+ // Set the locale information of the CRT to the Japanese
+ setlocale(LC_ALL, "");
+
+ // Initialization of OS
+ OSInit();
+
+ // Initialize the random number
+ srand((UINT)SystemTime64());
+
+ tick_manual_lock = NewLock();
+
+ // Initialization of CRC32
+ InitCrc32();
+
+ // Initialization of the FIFO system
+ InitFifo();
+
+ // Initialize the Kernel status
+ InitKernelStatus();
+
+ // Initialize the tracking
+ InitTracking();
+
+ // Initialization of thread pool
+ InitThreading();
+
+ // Initialize the string library
+ InitStringLibrary();
+
+ // Initialization of the locale information
+ SetLocale(NULL);
+
+ // Initialization of the crypt library
+ InitCryptLibrary();
+
+ // Initialization of the real-time clock
+ InitTick64();
+
+ // Initialize the network communication module
+ InitNetwork();
+
+ // Initialization of the aquisition of the EXE file name
+ InitGetExeName(argc >= 1 ? argv[0] : NULL);
+
+ // Initialization of the command line string
+ InitCommandLineStr(argc, argv);
+
+ // Initialization of OS information
+ InitOsInfo();
+
+ // Initialization of the operating system-specific module
+#ifdef OS_WIN32
+ MsInit(); // Microsoft Win32
+#endif // OS_WIN32
+
+ // Initialization of the security token module
+ InitSecure();
+
+ if (OSIsSupportedOs() == false)
+ {
+ // Abort
+ exit(0);
+ }
+
+ // RSA Check
+ if (RsaCheckEx() == false)
+ {
+ // Abort
+ Alert("OpenSSL Library Init Failed. (too old?)\nPlease install the latest version of OpenSSL.\n\n", "RsaCheck()");
+ exit(0);
+ }
+
+ // Initialization of HamCore file system
+ InitHamcore();
+
+ // Initialization of string table routine
+ InitTable();
+
+ if (exename == NULL)
+ {
+ // Executable file name
+ exename = CopyStr("unknown");
+ }
+
+ // Check whether the executable file name of themselves is found
+ // (If not found, quit because this is started in strange path)
+ GetExeNameW(tmp, sizeof(tmp));
+ if (IsFileExistsW(tmp) == false)
+ {
+ wchar_t tmp2[MAX_SIZE];
+
+ UniFormat(tmp2, sizeof(tmp2),
+ L"Error: Executable binary file \"%s\" not found.\r\n\r\n"
+ L"Please execute program with full path.\r\n",
+ tmp);
+
+ AlertW(tmp2, NULL);
+ _exit(0);
+ }
+
+ CheckUnixTempDir();
+
+ // Initialization of Probe
+ InitProbe();
+
+ // Initialization of Machine Hash
+ GetCurrentMachineIpProcessHash(hash);
+
+ // Reading Private IP file
+ LoadPrivateIPFile();
+}
+
+// Release of Mayaqua library
+void FreeMayaqua()
+{
+ if ((--init_mayaqua_counter) > 0)
+ {
+ return;
+ }
+
+ // Release of Private IP File
+ FreePrivateIPFile();
+
+ // Release of Probe
+ FreeProbe();
+
+ // Delete the table
+ FreeTable();
+
+ // Release of security token module
+ FreeSecure();
+
+ // Release of the operating system specific module
+#ifdef OS_WIN32
+ MsFree();
+#endif // OS_WIN32
+
+ // Release of OS information
+ FreeOsInfo();
+
+ // Release of HamCore file system
+ FreeHamcore();
+
+ // Release of the command line string
+ FreeCommandLineStr();
+
+ // Release of the command line token
+ FreeCommandLineTokens();
+
+ // Release of network communication module
+ FreeNetwork();
+
+ // Release of real-time clock
+ FreeTick64();
+
+ // Release of crypt library
+ FreeCryptLibrary();
+
+ // Release of the string library
+ FreeStringLibrary();
+
+ // Release of thread pool
+ FreeThreading();
+
+#ifndef VPN_SPEED
+ // Show the kernel status
+ if (g_debug)
+ {
+ PrintKernelStatus();
+ }
+
+ // Display the debug information
+ if (g_memcheck)
+ {
+ PrintDebugInformation();
+ }
+#endif // VPN_SPEED
+
+ // Release the tracking
+ FreeTracking();
+
+ // Release of the kernel status
+ FreeKernelStatus();
+
+ DeleteLock(tick_manual_lock);
+ tick_manual_lock = NULL;
+
+ // Release of OS
+ OSFree();
+}
+
+// Check whether /tmp is available in the UNIX
+void CheckUnixTempDir()
+{
+ if (OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ char tmp[128], tmp2[64];
+ UINT64 now = SystemTime64();
+ IO *o;
+
+ MakeDir("/tmp");
+
+ Format(tmp2, sizeof(tmp2), "%I64u", now);
+
+ Format(tmp, sizeof(tmp), "/tmp/.%s", tmp2);
+
+ o = FileCreate(tmp);
+ if (o == NULL)
+ {
+ o = FileOpen(tmp, false);
+ if (o == NULL)
+ {
+ Print("Unable to use /tmp.\n\n");
+ exit(0);
+ return;
+ }
+ }
+
+ FileClose(o);
+
+ FileDelete(tmp);
+ }
+}
+
+// Show an alert
+void Alert(char *msg, char *caption)
+{
+ OSAlert(msg, caption);
+}
+void AlertW(wchar_t *msg, wchar_t *caption)
+{
+ OSAlertW(msg, caption);
+}
+
+// Display of OS information
+void PrintOsInfo(OS_INFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Print(
+ "OS Type : %u\n"
+ "OS Service Pack : %u\n"
+ "os_is_windows : %s\n"
+ "os_is_windows_nt : %s\n"
+ "OS System Name : %s\n"
+ "OS Product Name : %s\n"
+ "OS Vendor Name : %s\n"
+ "OS Version : %s\n"
+ "Kernel Name : %s\n"
+ "Kernel Version : %s\n",
+ info->OsType,
+ info->OsServicePack,
+ OS_IS_WINDOWS(info->OsType) ? "true" : "false",
+ OS_IS_WINDOWS_NT(info->OsType) ? "true" : "false",
+ info->OsSystemName,
+ info->OsProductName,
+ info->OsVendorName,
+ info->OsVersion,
+ info->KernelName,
+ info->KernelVersion);
+
+#ifdef OS_WIN32
+ {
+ char *exe, *dir;
+ exe = MsGetExeFileName();
+ dir = MsGetExeDirName();
+
+ Print(
+ "EXE File Path : %s\n"
+ "EXE Dir Path : %s\n"
+ "Process Id : %u\n"
+ "Process Handle : 0x%X\n",
+ exe, dir, MsGetCurrentProcessId(), MsGetCurrentProcess());
+ }
+#endif // OS_WIN32
+}
+
+// Get the OS type
+UINT GetOsType()
+{
+ OS_INFO *i = GetOsInfo();
+
+ if (i == NULL)
+ {
+ return 0;
+ }
+
+ return i->OsType;
+}
+
+// Getting OS information
+OS_INFO *GetOsInfo()
+{
+ return os_info;
+}
+
+// Initialization of OS information
+void InitOsInfo()
+{
+ if (os_info != NULL)
+ {
+ return;
+ }
+
+ os_info = ZeroMalloc(sizeof(OS_INFO));
+
+ OSGetOsInfo(os_info);
+}
+
+// Release of OS information
+void FreeOsInfo()
+{
+ if (os_info == NULL)
+ {
+ return;
+ }
+
+ Free(os_info->OsSystemName);
+ Free(os_info->OsProductName);
+ Free(os_info->OsVendorName);
+ Free(os_info->OsVersion);
+ Free(os_info->KernelName);
+ Free(os_info->KernelVersion);
+ Free(os_info);
+
+ os_info = NULL;
+}
+
+// Get the Unicode command line tokens
+UNI_TOKEN_LIST *GetCommandLineUniToken()
+{
+ if (cmdline_uni_token == NULL)
+ {
+ return UniNullToken();
+ }
+ else
+ {
+ return UniCopyToken(cmdline_uni_token);
+ }
+}
+
+// Getting the command line tokens
+TOKEN_LIST *GetCommandLineToken()
+{
+ if (cmdline_token == NULL)
+ {
+ return NullToken();
+ }
+ else
+ {
+ return CopyToken(cmdline_token);
+ }
+}
+
+// Convert the command line string into tokens
+void ParseCommandLineTokens()
+{
+ if (cmdline_token != NULL)
+ {
+ FreeToken(cmdline_token);
+ }
+ cmdline_token = ParseCmdLine(cmdline);
+
+ if (cmdline_uni_token != NULL)
+ {
+ UniFreeToken(cmdline_uni_token);
+ }
+ cmdline_uni_token = UniParseCmdLine(uni_cmdline);
+}
+
+// Release command line tokens
+void FreeCommandLineTokens()
+{
+ if (cmdline_token != NULL)
+ {
+ FreeToken(cmdline_token);
+ }
+ cmdline_token = NULL;
+
+ if (cmdline_uni_token != NULL)
+ {
+ UniFreeToken(cmdline_uni_token);
+ }
+ cmdline_uni_token = NULL;
+}
+
+// Initialization of the command line string
+void InitCommandLineStr(int argc, char **argv)
+{
+ if (argc >= 1)
+ {
+#ifdef OS_UNIX
+ exename_w = CopyUtfToUni(argv[0]);
+ exename = CopyUniToStr(exename_w);
+#else // OS_UNIX
+ exename = CopyStr(argv[0]);
+ exename_w = CopyStrToUni(exename);
+#endif // OS_UNIX
+ }
+ if (argc < 2 || argv == NULL)
+ {
+ // No command-line string
+ SetCommandLineStr(NULL);
+ }
+ else
+ {
+ // There are command-line string
+ int i, total_len = 1;
+ char *tmp;
+
+ for (i = 1;i < argc;i++)
+ {
+ total_len += StrLen(argv[i]) * 2 + 32;
+ }
+ tmp = ZeroMalloc(total_len);
+
+ for (i = 1;i < argc;i++)
+ {
+ UINT s_size = StrLen(argv[i]) * 2;
+ char *s = ZeroMalloc(s_size);
+ bool dq = (SearchStrEx(argv[i], " ", 0, true) != INFINITE);
+ ReplaceStrEx(s, s_size, argv[i], "\"", "\"\"", true);
+ if (dq)
+ {
+ StrCat(tmp, total_len, "\"");
+ }
+ StrCat(tmp, total_len, s);
+ if (dq)
+ {
+ StrCat(tmp, total_len, "\"");
+ }
+ StrCat(tmp, total_len, " ");
+ Free(s);
+ }
+
+ Trim(tmp);
+ SetCommandLineStr(tmp);
+ Free(tmp);
+ }
+}
+
+// Release of the command line string
+void FreeCommandLineStr()
+{
+ SetCommandLineStr(NULL);
+
+ if (exename != NULL)
+ {
+ Free(exename);
+ exename = NULL;
+ }
+
+ if (exename_w != NULL)
+ {
+ Free(exename_w);
+ exename_w = NULL;
+ }
+}
+
+// Get the Unicode command line string
+wchar_t *GetCommandLineUniStr()
+{
+ if (uni_cmdline == NULL)
+ {
+ return UniCopyStr(L"");
+ }
+ else
+ {
+ return UniCopyStr(uni_cmdline);
+ }
+}
+
+// Get the command line string
+char *GetCommandLineStr()
+{
+ if (cmdline == NULL)
+ {
+ return CopyStr("");
+ }
+ else
+ {
+ return CopyStr(cmdline);
+ }
+}
+
+// Set the Unicode command line string
+void SetCommandLineUniStr(wchar_t *str)
+{
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ }
+ if (str == NULL)
+ {
+ uni_cmdline = NULL;
+ }
+ else
+ {
+ uni_cmdline = CopyUniStr(str);
+ }
+
+ ParseCommandLineTokens();
+}
+
+// Set the command-line string
+void SetCommandLineStr(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ if (cmdline != NULL)
+ {
+ Free(cmdline);
+ }
+ cmdline = NULL;
+ }
+ else
+ {
+ if (cmdline != NULL)
+ {
+ Free(cmdline);
+ }
+ cmdline = CopyStr(str);
+ }
+
+ if (cmdline == NULL)
+ {
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ uni_cmdline = NULL;
+ }
+ }
+ else
+ {
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ }
+ uni_cmdline = CopyStrToUni(cmdline);
+ }
+
+ ParseCommandLineTokens();
+}
+
+// Display the kernel status
+void PrintKernelStatus()
+{
+ bool leaked = false;
+
+ Print("\n");
+ Print(
+ " --------- Mayaqua Kernel Status ---------\n"
+ " Malloc Count ............... %u\n"
+ " ReAlloc Count .............. %u\n"
+ " Free Count ................. %u\n"
+ " Total Memory Size .......... %I64u bytes\n"
+ " * Current Memory Blocks ...... %u Blocks (Peek: %u)\n"
+ " Total Memory Blocks ........ %u Blocks\n"
+ " * Current MemPool Blocks ..... %u Blocks (Peek: %u)\n"
+ " Total MemPool Mallocs ...... %u Mallocs\n"
+ " Total MemPool ReAllocs ..... %u ReAllocs\n"
+ " NewLock Count .............. %u\n"
+ " DeleteLock Count ........... %u\n"
+ " * Current Lock Objects ....... %u Objects\n"
+ " * Current Locked Objects ..... %u Objects\n"
+ " NewRef Count ............... %u\n"
+ " FreeRef Count .............. %u\n"
+ " * Current Ref Objects ........ %u Objects\n"
+ " * Current Ref Count .......... %u Refs\n"
+ " GetTime Count .............. %u\n"
+ " GetTick Count .............. %u\n"
+ " NewThread Count ............ %u\n"
+ " FreeThread Count ........... %u\n"
+ " * Current Threads ............ %u Threads\n"
+ " Wait For Event Count ....... %u\n\n",
+ KS_GET(KS_MALLOC_COUNT),
+ KS_GET(KS_REALLOC_COUNT),
+ KS_GET(KS_FREE_COUNT),
+ KS_GET64(KS_TOTAL_MEM_SIZE),
+ KS_GET(KS_CURRENT_MEM_COUNT),
+ KS_GETMAX(KS_CURRENT_MEM_COUNT),
+ KS_GET(KS_TOTAL_MEM_COUNT),
+ KS_GET(KS_MEMPOOL_CURRENT_NUM),
+ KS_GETMAX(KS_MEMPOOL_CURRENT_NUM),
+ KS_GET(KS_MEMPOOL_MALLOC_COUNT),
+ KS_GET(KS_MEMPOOL_REALLOC_COUNT),
+ KS_GET(KS_NEWLOCK_COUNT),
+ KS_GET(KS_DELETELOCK_COUNT),
+ KS_GET(KS_CURRENT_LOCK_COUNT),
+ KS_GET(KS_CURRENT_LOCKED_COUNT),
+ KS_GET(KS_NEWREF_COUNT),
+ KS_GET(KS_FREEREF_COUNT),
+ KS_GET(KS_CURRENT_REF_COUNT),
+ KS_GET(KS_CURRENT_REFED_COUNT),
+ KS_GET(KS_GETTIME_COUNT),
+ KS_GET(KS_GETTICK_COUNT),
+ KS_GET(KS_NEWTHREAD_COUNT),
+ KS_GET(KS_FREETHREAD_COUNT),
+ KS_GET(KS_NEWTHREAD_COUNT) - KS_GET(KS_FREETHREAD_COUNT),
+ KS_GET(KS_WAIT_COUNT)
+ );
+
+ if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
+ KS_GET(KS_MEMPOOL_CURRENT_NUM) != 0 ||
+ KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
+ {
+ leaked = true;
+ }
+
+ if (leaked)
+ {
+ Print(" !!! MEMORY LEAKS DETECTED !!!\n\n");
+ if (g_memcheck == false)
+ {
+ GetLine(NULL, 0);
+ }
+ }
+ else
+ {
+ Print(" @@@ NO MEMORY LEAKS @@@\n\n");
+ }
+}
+
+// Initialize Kernel status
+void InitKernelStatus()
+{
+ UINT i;
+
+ // Memory initialization
+ Zero(kernel_status, sizeof(kernel_status));
+ Zero(kernel_status_max, sizeof(kernel_status_max));
+
+ // Lock initialization
+ for (i = 0;i < NUM_KERNEL_STATUS;i++)
+ {
+ kernel_status_lock[i] = OSNewLock();
+ }
+
+ kernel_status_inited = true;
+}
+
+// Release of the kernel status
+void FreeKernelStatus()
+{
+ UINT i;
+
+ kernel_status_inited = false;
+
+ // Lock release
+ for (i = 0;i < NUM_KERNEL_STATUS;i++)
+ {
+ OSDeleteLock(kernel_status_lock[i]);
+ }
+}
+
+// Lock the kernel status
+void LockKernelStatus(UINT id)
+{
+ // Validate arguments
+ if (id >= NUM_KERNEL_STATUS)
+ {
+ return;
+ }
+
+ OSLock(kernel_status_lock[id]);
+}
+
+// Unlock the kernel status
+void UnlockKernelStatus(UINT id)
+{
+ // Validate arguments
+ if (id >= NUM_KERNEL_STATUS)
+ {
+ return;
+ }
+
+ OSUnlock(kernel_status_lock[id]);
+}
+
+// Display the debug information
+void PrintDebugInformation()
+{
+ MEMORY_STATUS memory_status;
+ GetMemoryStatus(&memory_status);
+
+ // Header
+ Print("====== " CEDAR_PRODUCT_STR " VPN System Debug Information ======\n");
+
+ // Memory information
+ Print(" <Memory Status>\n"
+ " Number of Allocated Memory Blocks: %u\n"
+ " Total Size of Allocated Memory Blocks: %u bytes\n",
+ memory_status.MemoryBlocksNum, memory_status.MemorySize);
+
+ // Footer
+ Print("====================================================\n");
+
+ if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
+ KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
+ {
+ // Show a debug menu because memory leaks suspected
+ MemoryDebugMenu();
+ }
+}
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.h b/src/Mayaqua/Mayaqua.h
new file mode 100644
index 00000000..75e6b9d9
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.h
@@ -0,0 +1,595 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Mayaqua.h
+// Mayaqua Kernel header file
+
+#ifndef MAYAQUA_H
+#define MAYAQUA_H
+
+// PenCore.dll related
+#define PENCORE_DLL_NAME "|PenCore.dll"
+// #define PENCORE_DLL_NAME_X64 "|PenCore_x64.dll" // commonized to x86
+// #define PENCORE_DLL_NAME_IA64 "|PenCore_ia64.dll" // commonized to x86
+
+
+//#define USE_PROBE // Use Probe
+
+// Macro for the release flag
+#ifdef VPN_SPEED
+
+#define DONT_USE_KERNEL_STATUS // Do not update the kernel status
+#define WIN32_USE_HEAP_API_FOR_MEMORY // Use the heap API to allocate memory
+#define WIN32_NO_DEBUG_HELP_DLL // Do not call the DLL for debugging
+#define DONT_CHECK_HEAP // Do not check the status of the heap
+#define DONT_ALLOW_RUN_ON_DEBUGGER // Do not allow running on the debugger
+
+#endif // VPN_SPEED
+
+#ifdef VPN_EXE
+// To build the executable file
+#ifdef WIN32
+#include <windows.h>
+#include "../PenCore/resource.h"
+int main(int argc, char *argv[]);
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ char *argv[] = { CmdLine, };
+ return main(1, argv);
+}
+#endif // WIN32
+#endif // VPN_EXE
+
+// Constant
+#define DEFAULT_TABLE_FILE_NAME "|strtable.stb" // Default string table
+//#define DEFAULT_TABLE_FILE_NAME "@hamcore_zh/strtable.stb" // Test for Chinese
+
+#define STRTABLE_ID "SE_VPN_20121007" // String table identifier
+
+// Determining the OS
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX
+#endif // WIN32
+
+// Directory separator
+#ifdef OS_WIN32
+#define PATH_BACKSLASH // Backslash (\)
+#else // WIN32
+#define PATH_SLASH // Slash (/)
+#endif // WIN32
+
+// Character code
+#ifdef OS_WIN32
+#define CODE_SHIFTJIS // Shift_JIS code
+#else // WIN32
+#define CODE_EUC // euc-jp code
+#endif // WIN32
+
+// Endian
+#define IsBigEndian() (g_little_endian ? false : true)
+#define IsLittleEndian() (g_little_endian)
+
+#ifdef OS_WIN32
+// Replace the snprintf function
+#define snprintf _snprintf
+#endif // OS_WIN32
+
+// Compiler dependent
+#ifndef OS_WIN32
+// Gcc compiler
+#define GCC_PACKED __attribute__ ((__packed__))
+#else // OS_WIN32
+// VC++ compiler
+#define GCC_PACKED
+#endif // OS_WIN32
+
+// Macro that displays the current file name and line number
+#define WHERE if (IsDebug()){printf("%s: %u\n", __FILE__, __LINE__); SleepThread(10);}
+#define WHERE32 if (IsDebug()){ \
+ char tmp[128]; sprintf(tmp, "%s: %u", __FILE__, __LINE__); Win32DebugAlert(tmp); \
+ }
+#define TIMECHECK if (IsDebug()){printf("%-12s:%5u", __FILE__, __LINE__);TimeCheck();}
+
+// Probe related
+#ifdef USE_PROBE
+#define PROBE_WHERE WriteProbe(__FILE__, __LINE__, "");
+#define PROBE_STR(str) WriteProbe(__FILE__, __LINE__, (str));
+#define PROBE_DATA2(str, data, size) WriteProbeData(__FILE__, __LINE__, (str), (data), (size));
+#define PROBE_DATA(data, size) WriteProbeData(__FILE__, __LINE__, "", (data), (size));
+#else // USE_PROBE
+#define PROBE_WHERE
+#define PROBE_STR(str)
+#define PROBE_DATA2(str, data, size)
+#define PROBE_DATA(data, size)
+#endif // USE_PROBE
+
+// About Intel AES-NI Library
+#if (defined(OS_WIN32) || (defined(UNIX_LINUX) && (defined(CPU_X86) || defined(CPU_X64))))
+// Supports only for Linux (x86 / x64) or Windows
+#define USE_INTEL_AESNI_LIBRARY
+#endif
+
+// Macro that displays the current time
+#ifdef WIN32
+#define WHEN if (IsDebug()){WHERE; MsPrintTick();}
+#else // WIN32
+#define WHEN
+#endif // WIN32
+
+#ifdef OS_UNIX
+#ifndef UNIX_SOLARIS
+#ifndef CPU_SH4
+// Getifaddrs system call is supported on UNIX other than Solaris.
+// However, it is not supported also by the Linux on SH4 CPU
+#define MAYAQUA_SUPPORTS_GETIFADDRS
+#endif // CPU_SH4
+#endif // UNIX_SOLARIS
+#endif // OS_UNIX
+
+#ifdef OS_UNIX
+// Header only needed in UNIX OS
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
+#include <dirent.h>
+#ifdef UNIX_LINUX
+#include <sys/vfs.h>
+#elif UNIX_BSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#ifdef UNIX_SOLARIS
+#include <sys/statvfs.h>
+#define USE_STATVFS
+#endif // UNIX_SOLARIS
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#ifdef UNIX_SOLARIS
+#include <sys/filio.h>
+#endif // UNIX_SOLARIS
+#include <sys/poll.h>
+#include <sys/resource.h>
+#include <pthread.h>
+#ifdef UNIX_LINUX
+#include <sys/prctl.h>
+#endif // UNIX_LINUX
+#include <signal.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+//#include <netinet/ip.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+//#include <curses.h>
+#ifdef MAYAQUA_SUPPORTS_GETIFADDRS
+#include <ifaddrs.h>
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+#ifdef UNIX_LINUX
+typedef void *iconv_t;
+iconv_t iconv_open (__const char *__tocode, __const char *__fromcode);
+size_t iconv (iconv_t __cd, char **__restrict __inbuf,
+ size_t *__restrict __inbytesleft,
+ char **__restrict __outbuf,
+ size_t *__restrict __outbytesleft);
+int iconv_close (iconv_t __cd);
+#else // UNIX_LINUX
+#include <iconv.h>
+#endif // UNIX_LINUX
+
+
+
+#ifdef UNIX_LINUX
+#include <netinet/if_ether.h>
+#include <net/ethernet.h>
+#include <netpacket/packet.h>
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+#include <sys/dlpi.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#endif // UNIX_SOLARIS
+
+#ifndef NO_VLAN
+
+#include <Mayaqua/TunTap.h>
+
+#endif // NO_VLAN
+
+#define closesocket(s) close(s)
+
+#else // Win32 only
+
+#include <conio.h>
+
+#endif // OS_UNIX
+
+// IPv6 support flag
+#ifndef WIN32
+#ifndef AF_INET6
+#define NO_IPV6
+#endif // AF_INET6
+#endif // WIN32
+
+// Basic type declaration
+#include <Mayaqua/MayaType.h>
+
+// Object management
+#include <Mayaqua/Object.h>
+
+// Object tracking
+#include <Mayaqua/Tracking.h>
+
+// File I/O
+#include <Mayaqua/FileIO.h>
+
+// Memory management
+#include <Mayaqua/Memory.h>
+
+// String processing
+#include <Mayaqua/Str.h>
+
+// Internationalized string processing
+#include <Mayaqua/Internat.h>
+
+// Encryption processing
+#include <Mayaqua/Encrypt.h>
+
+// Secure token
+#include <Mayaqua/Secure.h>
+
+// Kernel
+#include <Mayaqua/Kernel.h>
+
+// Package
+#include <Mayaqua/Pack.h>
+
+// Configuration file
+#include <Mayaqua/Cfg.h>
+
+// String table
+#include <Mayaqua/Table.h>
+
+// Network communication
+#include <Mayaqua/Network.h>
+
+// TCP/IP
+#include <Mayaqua/TcpIp.h>
+
+// 64 bit real-time clock
+#include <Mayaqua/Tick64.h>
+
+// OS-dependent code
+#include <Mayaqua/OS.h>
+
+// Code for Microsoft Windows
+#include <Mayaqua/Microsoft.h>
+
+
+// Global variables
+extern bool g_memcheck;
+extern bool g_debug;
+extern char *cmdline;
+extern wchar_t *uni_cmdline;
+extern bool g_little_endian;
+extern LOCK *tick_manual_lock;
+
+// Kernel state
+#define NUM_KERNEL_STATUS 128
+extern UINT64 kernel_status[NUM_KERNEL_STATUS];
+extern UINT64 kernel_status_max[NUM_KERNEL_STATUS];
+extern LOCK *kernel_status_lock[NUM_KERNEL_STATUS];
+extern BOOL kernel_status_inited;
+
+// Kernel state operation macro
+#define KS_LOCK(id) LockKernelStatus(id)
+#define KS_UNLOCK(id) UnlockKernelStatus(id)
+#define KS_GET64(id) (kernel_status[id])
+#define KS_GET(id) ((UINT)KS_GET64(id))
+#define KS_GETMAX64(id) (kernel_status_max[id])
+#define KS_GETMAX(id) ((UINT)KS_GETMAX64(id))
+
+#ifdef DONT_USE_KERNEL_STATUS
+// Disable operations of the kernel status
+#define KS_INC(id)
+#define KS_DEC(id)
+#define KS_ADD(id, n)
+#define KS_SUB(id, n)
+#else // DONT_USE_KERNEL_STATUS
+// Enable operations of the kernel status
+#define KS_INC(id) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id]++; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_DEC(id) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id]--; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_ADD(id, n) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id] += n; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_SUB(id, n) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id] -= n; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#endif // DONT_USE_KERNEL_STATUS
+
+// Kernel status
+// String related
+#define KS_STRCPY_COUNT 0 // number of calls StrCpy
+#define KS_STRLEN_COUNT 1 // number of calls StrLen
+#define KS_STRCHECK_COUNT 2 // number of calls StrCheck
+#define KS_STRCAT_COUNT 3 // number of calls StrCat
+#define KS_FORMAT_COUNT 4 // number of calls Format
+// Memory related
+#define KS_MALLOC_COUNT 5 // Number of calls Malloc
+#define KS_REALLOC_COUNT 6 // Number of calls ReAlloc
+#define KS_FREE_COUNT 7 // number of calls Free
+#define KS_TOTAL_MEM_SIZE 8 // The total size of the memory that was allocated so far
+#define KS_CURRENT_MEM_COUNT 9 // Number of memory blocks that are currently reserved
+#define KS_TOTAL_MEM_COUNT 10 // The total number of memory blocks that ware allocated so far
+#define KS_ZERO_COUNT 11 // Number of calls Zero
+#define KS_COPY_COUNT 12 // Number of calls Copy
+// Lock related
+#define KS_NEWLOCK_COUNT 13 // Number of calls NewLock
+#define KS_DELETELOCK_COUNT 14 // Number of calls DeleteLock
+#define KS_LOCK_COUNT 15 // Number of calls Lock
+#define KS_UNLOCK_COUNT 16 // Number of calls Unlock
+#define KS_CURRENT_LOCK_COUNT 17 // Current number of LOCK objects
+#define KS_CURRENT_LOCKED_COUNT 18 // Current number of locked LOCK objects
+// Counter information
+#define KS_NEW_COUNTER_COUNT 19 // Number of calls NewCounter
+#define KS_DELETE_COUNTER_COUNT 20 // Number of calls DeleteCounter
+#define KS_INC_COUNT 21 // Number of calls Inc
+#define KS_DEC_COUNT 22 // Number of calls Dec
+#define KS_CURRENT_COUNT 23 // Current total number of counts
+// Reference counter information
+#define KS_NEWREF_COUNT 24 // Number of calls NewRef
+#define KS_FREEREF_COUNT 72 // Number of times REF objects are deleted
+#define KS_ADDREF_COUNT 25 // Number of calls AddRef
+#define KS_RELEASE_COUNT 26 // Number of calls Release
+#define KS_CURRENT_REF_COUNT 27 // Current number of REF objects
+#define KS_CURRENT_REFED_COUNT 28 // The sum of the current number of references
+// Buffer information
+#define KS_NEWBUF_COUNT 29 // Number of calls NewBuf
+#define KS_FREEBUF_COUNT 30 // NNumber of calls FreeBuf
+#define KS_CURRENT_BUF_COUNT 31 // Current number of objects in the BUF
+#define KS_READ_BUF_COUNT 32 // Number of calls ReadBuf
+#define KS_WRITE_BUF_COUNT 33 // Number of calls WriteBuf
+#define KS_ADJUST_BUFSIZE_COUNT 34 // Number of times to adjust the buffer size
+#define KS_SEEK_BUF_COUNT 35 // Number of calls SeekBuf
+// FIFO information
+#define KS_NEWFIFO_COUNT 36 // Number of calls NewFifo
+#define KS_FREEFIFO_COUNT 37 // Number of times the FIFO object is deleted
+#define KS_READ_FIFO_COUNT 38 // Number of calls ReadFifo
+#define KS_WRITE_FIFO_COUNT 39 // Number of calls WriteFifo
+#define KS_PEEK_FIFO_COUNT 40 // Number of calls PeekFifo
+// List related
+#define KS_NEWLIST_COUNT 41 // Number of calls NewList
+#define KS_FREELIST_COUNT 42 // Number of times the object LIST was deleted
+#define KS_INSERT_COUNT 43 // Number of calls Add
+#define KS_DELETE_COUNT 44 // Number of calls Delete
+#define KS_SORT_COUNT 45 // Number of calls Sort
+#define KS_SEARCH_COUNT 46 // Number of calls Search
+#define KS_TOARRAY_COUNT 47 // Number of calls ToArray
+// Queue related
+#define KS_NEWQUEUE_COUNT 48 // Number of calls NewQueue
+#define KS_FREEQUEUE_COUNT 49 // Number of times you delete the object QUEUE
+#define KS_PUSH_COUNT 50 // Number of calls Push
+#define KS_POP_COUNT 51 // Number of calls POP
+// Stack related
+#define KS_NEWSK_COUNT 52 // Number of calls NewSk
+#define KS_FREESK_COUNT 53 // Number of times you delete the object SK
+#define KS_INSERT_QUEUE_COUNT 54 // Number of calls InsertQueue
+#define KS_GETNEXT_COUNT 55 // Number of calls GetNext
+// Kernel related
+#define KS_GETTIME_COUNT 56 // Number of times to get the time
+#define KS_GETTICK_COUNT 57 // Number of times to get the system timer
+#define KS_NEWTHREAD_COUNT 58 // Number of calls NewThread
+#define KS_FREETHREAD_COUNT 59 // Number of times you delete the object THREAD
+#define KS_WAITFORTHREAD_COUNT 60 // Number of calls WaitForThread
+#define KS_NEWEVENT_COUNT 61 // Number of calls NewEvent
+#define KS_FREEEVENT_COUNT 62 // Number of times which EVENT object is deleted
+#define KS_WAIT_COUNT 63 // Number of calls Wait
+#define KS_SLEEPTHREAD_COUNT 64 // Number of calls SleepThread
+// About IO
+#define KS_IO_OPEN_COUNT 65 // Number of times to open the file
+#define KS_IO_CREATE_COUNT 66 // Number of times that the file was created
+#define KS_IO_CLOSE_COUNT 67 // Number of times to close the file
+#define KS_IO_READ_COUNT 68 // Number of times to read from the file
+#define KS_IO_WRITE_COUNT 69 // Number of times to write to a file
+#define KS_IO_TOTAL_READ_SIZE 70 // Total number of bytes read from the file
+#define KS_IO_TOTAL_WRITE_SIZE 71 // The total number of bytes written to the file
+// Memory pool related
+#define KS_MEMPOOL_MALLOC_COUNT 75 // Number of times to allocate the memory pool
+#define KS_MEMPOOL_FREE_COUNT 73 // Number of times you release the memory pool
+#define KS_MEMPOOL_CURRENT_NUM 74 // Current number of the memory pool
+#define KS_MEMPOOL_REALLOC_COUNT 76 // Number of times you have realloc the memory pool
+
+
+// Macro
+#define IsDebug() (g_debug) // A debug mode
+#define IsMemCheck() (g_memcheck) // Memory check mode
+
+// Function prototype
+void InitMayaqua(bool memcheck, bool debug, int argc, char **argv);
+void FreeMayaqua();
+bool IsNt();
+bool IsUnicode();
+void MayaquaDotNetMode();
+bool MayaquaIsDotNetMode();
+void MayaquaMinimalMode();
+bool MayaquaIsMinimalMode();
+bool Is64();
+bool Is32();
+bool IsIA64();
+bool IsX64();
+void InitKernelStatus();
+void FreeKernelStatus();
+void PrintDebugInformation();
+void LockKernelStatus(UINT id);
+void UnlockKernelStatus(UINT id);
+void PrintKernelStatus();
+void InitCommandLineStr(int argc, char **argv);
+void FreeCommandLineStr();
+void SetCommandLineStr(char *str);
+void SetCommandLineUniStr(wchar_t *str);
+char *GetCommandLineStr();
+wchar_t *GetCommandLineUniStr();
+void ParseCommandLineTokens();
+void FreeCommandLineTokens();
+TOKEN_LIST *GetCommandLineToken();
+UNI_TOKEN_LIST *GetCommandLineUniToken();
+void InitOsInfo();
+void FreeOsInfo();
+void Alert(char *msg, char *caption);
+void AlertW(wchar_t *msg, wchar_t *caption);
+OS_INFO *GetOsInfo();
+UINT GetOsType();
+void PrintOsInfo(OS_INFO *info);
+void CheckEndian();
+void CheckUnixTempDir();
+void TimeCheck();
+void SetHamMode();
+bool IsHamMode();
+void InitProbe();
+void FreeProbe();
+void EnableProbe(bool enable);
+bool IsProbeEnabled();
+void WriteProbe(char *filename, UINT line, char *str);
+void WriteProbeData(char *filename, UINT line, char *str, void *data, UINT size);
+USHORT CalcChecksum16(void *buf, UINT size);
+
+
+#ifdef OS_WIN32
+// Import library (for Win32)
+#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "winmm.lib")
+#pragma comment(lib, "kernel32.lib")
+#pragma comment(lib, "user32.lib")
+#pragma comment(lib, "gdi32.lib")
+#pragma comment(lib, "shell32.lib")
+#pragma comment(lib, "comctl32.lib")
+#pragma comment(lib, "dbghelp.lib")
+#pragma comment(lib, "Iphlpapi.lib")
+#pragma comment(lib, "setupapi.lib")
+#pragma comment(lib, "version.lib")
+#pragma comment(lib, "Netapi32.lib")
+#pragma comment(lib, "shlwapi.lib")
+#pragma warning( disable : 4099 )
+#endif // OS_WIN32
+
+// For Debugging
+#ifndef ENCRYPT_C
+//#define Disconnect(s) {Debug("Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}
+#endif
+
+
+#endif // MAYAQUA_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.vcproj b/src/Mayaqua/Mayaqua.vcproj
new file mode 100644
index 00000000..af36ad18
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.vcproj
@@ -0,0 +1,833 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Mayaqua"
+ ProjectGUID="{70486335-7814-40E2-A561-BBCB6025F5C9}"
+ RootNamespace="Mayaqua"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Cfg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Encrypt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\FileIO.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Internat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Kernel.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Mayaqua.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Memory.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Microsoft.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Network.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Object.c"
+ >
+ </File>
+ <File
+ RelativePath=".\OS.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Pack.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Str.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Table.c"
+ >
+ </File>
+ <File
+ RelativePath=".\TcpIp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Tick64.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Tracking.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Unix.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Cfg.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cryptoki.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Encrypt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\FileIO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Internat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Kernel.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Mayaqua.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MayaType.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Memory.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Microsoft.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Network.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Object.h"
+ >
+ </File>
+ <File
+ RelativePath=".\OS.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Pack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11f.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Str.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Table.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TcpIp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Tick64.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Tracking.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TunTap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Unix.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="openssl"
+ >
+ <File
+ RelativePath=".\openssl\aes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1_mac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\bio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\blowfish.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\bn.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\buffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\cast.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\comp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\conf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\conf_api.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\crypto.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\des.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\des_old.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dh.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dso.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dtls1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\e_os2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ebcdic.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ecdh.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ecdsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\engine.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\err.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\evp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\fips.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\fips_rand.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\hmac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\idea.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\krb5_asn.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\kssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\lhash.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\mdc2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\obj_mac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\objects.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ocsp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\opensslconf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\opensslv.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ossl_typ.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pem2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pkcs12.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pkcs7.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pq_compat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pqueue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rand.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ripemd.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\safestack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\sha.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl23.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl3.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\stack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\store.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\symhacks.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\tls1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\tmdiff.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\txt_db.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ui.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ui_compat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509_vfy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509v3.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="zlib"
+ >
+ <File
+ RelativePath=".\zlib\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\zlib\zlib.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="intelaes"
+ >
+ <File
+ RelativePath=".\intelaes\iaesni.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c
new file mode 100644
index 00000000..2fc00844
--- /dev/null
+++ b/src/Mayaqua/Memory.c
@@ -0,0 +1,4124 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Memory.c
+// Memory management program
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <zlib/zlib.h>
+#include <Mayaqua/Mayaqua.h>
+
+#define MEMORY_SLEEP_TIME 150
+#define MEMORY_MAX_RETRY 30
+#define INIT_BUF_SIZE 10240
+
+#define FIFO_INIT_MEM_SIZE 4096
+#define FIFO_REALLOC_MEM_SIZE (65536 * 10) // Exquisite value
+#define FIFO_REALLOC_MEM_SIZE_SMALL 65536
+
+#define INIT_NUM_RESERVED 32
+
+static UINT fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+
+// Lock the hash list
+void LockHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Lock(h->Lock);
+}
+
+// Unlock the hash list
+void UnlockHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Unlock(h->Lock);
+}
+
+// Write the contents of the hash list to array
+void **HashListToArray(HASH_LIST *h, UINT *num)
+{
+ void **ret = NULL;
+ UINT i;
+ UINT n = 0;
+ // Validate arguments
+ if (h == NULL || num == NULL)
+ {
+ if (num != NULL)
+ {
+ *num = 0;
+ }
+ return NULL;
+ }
+
+ if (h->AllList != NULL)
+ {
+ *num = LIST_NUM(h->AllList);
+
+ return ToArray(h->AllList);
+ }
+
+ ret = ZeroMalloc(sizeof(void *) * h->NumItems);
+
+ for (i = 0;i < h->Size;i++)
+ {
+ LIST *o = h->Entries[i];
+
+ if (o != NULL)
+ {
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ void *p = LIST_DATA(o, j);
+
+ ret[n] = p;
+ n++;
+ }
+ }
+ }
+
+ *num = n;
+
+ return ret;
+}
+
+// Search an item in the hash list
+void *SearchHash(HASH_LIST *h, void *t)
+{
+ UINT r;
+ void *ret = NULL;
+ // Validate arguments
+ if (h == NULL || t == NULL)
+ {
+ return NULL;
+ }
+
+ r = CalcHashForHashList(h, t);
+
+ if (h->Entries[r] != NULL)
+ {
+ LIST *o = h->Entries[r];
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (h->CompareProc(&p, &t) == 0)
+ {
+ ret = p;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Remove an item from the hash list
+bool DeleteHash(HASH_LIST *h, void *p)
+{
+ UINT r;
+ bool ret = false;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ r = CalcHashForHashList(h, p);
+
+ if (h->Entries[r] != NULL)
+ {
+ if (Delete(h->Entries[r], p))
+ {
+ ret = true;
+ h->NumItems--;
+ }
+
+ if (LIST_NUM(h->Entries[r]) == 0)
+ {
+ ReleaseList(h->Entries[r]);
+ h->Entries[r] = NULL;
+ }
+ }
+
+ if (ret)
+ {
+ if (h->AllList != NULL)
+ {
+ Delete(h->AllList, p);
+ }
+ }
+
+ return ret;
+}
+
+// Add an item to the hash list
+void AddHash(HASH_LIST *h, void *p)
+{
+ UINT r;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return;
+ }
+
+ r = CalcHashForHashList(h, p);
+
+ if (h->Entries[r] == NULL)
+ {
+ h->Entries[r] = NewListFast(NULL);
+ }
+
+ Add(h->Entries[r], p);
+
+ if (h->AllList != NULL)
+ {
+ Add(h->AllList, p);
+ }
+
+ h->NumItems++;
+}
+
+// Calculation of the hash value of the object
+UINT CalcHashForHashList(HASH_LIST *h, void *p)
+{
+ UINT r;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return 0;
+ }
+
+ r = h->GetHashProc(p);
+
+ return (r % h->Size);
+}
+
+// Creating a hash list
+HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list)
+{
+ HASH_LIST *h;
+ // Validate arguments
+ if (get_hash_proc == NULL || compare_proc == NULL)
+ {
+ return NULL;
+ }
+ if (bits == 0)
+ {
+ bits = 16;
+ }
+
+ bits = MIN(bits, 31);
+
+ h = ZeroMalloc(sizeof(HASH_LIST));
+
+ h->Bits = bits;
+ h->Size = Power(2, bits);
+
+ h->Lock = NewLock();
+ h->Ref = NewRef();
+
+ h->Entries = ZeroMalloc(sizeof(LIST *) * h->Size);
+
+ h->GetHashProc = get_hash_proc;
+ h->CompareProc = compare_proc;
+
+ if (make_list)
+ {
+ h->AllList = NewListFast(NULL);
+ }
+
+ return h;
+}
+
+// Release the hash list
+void ReleaseHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (Release(h->Ref) == 0)
+ {
+ CleanupHashList(h);
+ }
+}
+void CleanupHashList(HASH_LIST *h)
+{
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < h->Size;i++)
+ {
+ LIST *o = h->Entries[i];
+
+ if (o != NULL)
+ {
+ ReleaseList(o);
+ }
+ }
+
+ Free(h->Entries);
+
+ DeleteLock(h->Lock);
+
+ if (h->AllList != NULL)
+ {
+ ReleaseList(h->AllList);
+ }
+
+ Free(h);
+}
+
+// Append a string to the buffer
+void AppendBufStr(BUF *b, char *str)
+{
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+}
+
+// Add a UTF-8 string to the buffer
+void AppendBufUtf8(BUF *b, wchar_t *str)
+{
+ UINT size;
+ UCHAR *data;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ size = CalcUniToUtf8(str) + 1;
+ data = ZeroMalloc(size);
+
+ UniToUtf8(data, size, str);
+
+ WriteBuf(b, data, size - 1);
+
+ Free(data);
+}
+
+// Creating a shared buffer
+SHARED_BUFFER *NewSharedBuffer(void *data, UINT size)
+{
+ SHARED_BUFFER *b = ZeroMalloc(sizeof(SHARED_BUFFER));
+
+ b->Ref = NewRef();
+ b->Data = ZeroMalloc(size);
+ b->Size = size;
+
+ if (data != NULL)
+ {
+ Copy(b->Data, data, size);
+ }
+
+ return b;
+}
+
+// Release of the shared buffer
+void ReleaseSharedBuffer(SHARED_BUFFER *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (Release(b->Ref) == 0)
+ {
+ CleanupSharedBuffer(b);
+ }
+}
+void CleanupSharedBuffer(SHARED_BUFFER *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Free(b->Data);
+
+ Free(b);
+}
+
+// Calculation of a ^ b (a to the b-th power)
+UINT Power(UINT a, UINT b)
+{
+ UINT ret, i;
+ if (a == 0)
+ {
+ return 0;
+ }
+ if (b == 0)
+ {
+ return 1;
+ }
+
+ ret = 1;
+ for (i = 0;i < b;i++)
+ {
+ ret *= a;
+ }
+
+ return ret;
+}
+
+// Search in the binary
+UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size)
+{
+ UINT i;
+ // Validate arguments
+ if (data == NULL || key == NULL || key_size == 0 || data_size == 0 ||
+ (data_start >= data_size) || (data_start + key_size > data_size))
+ {
+ return INFINITE;
+ }
+
+ for (i = data_start;i < (data_size - key_size + 1);i++)
+ {
+ UCHAR *p = ((UCHAR *)data) + i;
+
+ if (Cmp(p, key, key_size) == 0)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Crash immediately
+void CrashNow()
+{
+ while (true)
+ {
+ UINT r = Rand32();
+ UCHAR *c = (UCHAR *)r;
+
+ *c = Rand8();
+ }
+}
+
+// Convert the buffer to candidate
+LIST *BufToCandidate(BUF *b)
+{
+ LIST *o;
+ UINT i;
+ UINT num;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ num = ReadBufInt(b);
+ o = NewCandidateList();
+
+ for (i = 0;i < num;i++)
+ {
+ CANDIDATE *c;
+ wchar_t *s;
+ UINT64 sec64;
+ UINT len, size;
+ sec64 = ReadBufInt64(b);
+ len = ReadBufInt(b);
+ if (len >= 65536)
+ {
+ break;
+ }
+ size = (len + 1) * 2;
+ s = ZeroMalloc(size);
+ if (ReadBuf(b, s, size) != size)
+ {
+ Free(s);
+ break;
+ }
+ else
+ {
+ c = ZeroMalloc(sizeof(CANDIDATE));
+ c->LastSelectedTime = sec64;
+ c->Str = s;
+ Add(o, c);
+ }
+ }
+
+ Sort(o);
+ return o;
+}
+
+// Convert the candidate to buffer
+BUF *CandidateToBuf(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBufInt(b, LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ WriteBufInt64(b, c->LastSelectedTime);
+ WriteBufInt(b, UniStrLen(c->Str));
+ WriteBuf(b, c->Str, UniStrSize(c->Str));
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Adding a candidate
+void AddCandidate(LIST *o, wchar_t *str, UINT num_max)
+{
+ UINT i;
+ bool exists;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return;
+ }
+ if (num_max == 0)
+ {
+ num_max = 0x7fffffff;
+ }
+
+ // String copy
+ str = UniCopyStr(str);
+ UniTrim(str);
+
+ exists = false;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ if (UniStrCmpi(c->Str, str) == 0)
+ {
+ // Update the time that an existing entry have been found
+ c->LastSelectedTime = SystemTime64();
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ // Insert new
+ CANDIDATE *c = ZeroMalloc(sizeof(CANDIDATE));
+ c->LastSelectedTime = SystemTime64();
+ c->Str = UniCopyStr(str);
+ Insert(o, c);
+ }
+
+ // Release the string
+ Free(str);
+
+ // Check the current number of candidates.
+ // If it is more than num_max, remove from an oldest candidate sequentially.
+ if (LIST_NUM(o) > num_max)
+ {
+ while (LIST_NUM(o) > num_max)
+ {
+ UINT index = LIST_NUM(o) - 1;
+ CANDIDATE *c = LIST_DATA(o, index);
+ Delete(o, c);
+ Free(c->Str);
+ Free(c);
+ }
+ }
+}
+
+// Comparison of candidates
+int ComapreCandidate(void *p1, void *p2)
+{
+ CANDIDATE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(CANDIDATE **)p1;
+ c2 = *(CANDIDATE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+ if (c1->LastSelectedTime > c2->LastSelectedTime)
+ {
+ return -1;
+ }
+ else if (c1->LastSelectedTime < c2->LastSelectedTime)
+ {
+ return 1;
+ }
+ else
+ {
+ return UniStrCmpi(c1->Str, c2->Str);
+ }
+}
+
+// Release of the candidate list
+void FreeCandidateList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ Free(c->Str);
+ Free(c);
+ }
+
+ ReleaseList(o);
+}
+
+// Creating a new candidate list
+LIST *NewCandidateList()
+{
+ return NewList(ComapreCandidate);
+}
+
+// Fill a range of memory
+void FillBytes(void *data, UINT size, UCHAR c)
+{
+ UCHAR *buf = (UCHAR *)data;
+ UINT i;
+
+ for (i = 0;i < size;i++)
+ {
+ buf[i] = c;
+ }
+}
+
+// Examine whether the specified address points all-zero area
+bool IsZero(void *data, UINT size)
+{
+ UINT i;
+ UCHAR *c = (UCHAR *)data;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return true;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ if (c[i] != 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Expand the data
+UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ unsigned long dst_size_long = dst_size;
+ // Validate arguments
+ if (dst == NULL || dst_size_long == 0 || src == NULL)
+ {
+ return 0;
+ }
+
+ if (uncompress(dst, &dst_size_long, src, src_size) != Z_OK)
+ {
+ return 0;
+ }
+
+ return (UINT)dst_size_long;
+}
+BUF *UncompressBuf(BUF *src_buf)
+{
+ UINT dst_size, dst_size2;
+ UCHAR *dst;
+ BUF *b;
+ // Validate arguments
+ if (src_buf == NULL)
+ {
+ return NULL;
+ }
+
+ SeekBuf(src_buf, 0, 0);
+ dst_size = ReadBufInt(src_buf);
+
+ dst = Malloc(dst_size);
+
+ dst_size2 = Uncompress(dst, dst_size, ((UCHAR *)src_buf->Buf) + sizeof(UINT), src_buf->Size - sizeof(UINT));
+
+ b = NewBuf();
+ WriteBuf(b, dst, dst_size2);
+ Free(dst);
+
+ return b;
+}
+
+// Compress the data
+UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ return CompressEx(dst, dst_size, src, src_size, Z_DEFAULT_COMPRESSION);
+}
+BUF *CompressBuf(BUF *src_buf)
+{
+ UINT dst_size;
+ UCHAR *dst_buf;
+ BUF *b;
+ // Validate arguments
+ if (src_buf == NULL)
+ {
+ return NULL;
+ }
+
+ dst_size = CalcCompress(src_buf->Size);
+ dst_buf = Malloc(dst_size);
+
+ dst_size = Compress(dst_buf, dst_size, src_buf->Buf, src_buf->Size);
+
+ if (dst_size == 0)
+ {
+ Free(dst_buf);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBufInt(b, src_buf->Size);
+ WriteBuf(b, dst_buf, dst_size);
+
+ Free(dst_buf);
+
+ return b;
+}
+
+// Compress the data with options
+UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level)
+{
+ unsigned long dst_size_long = dst_size;
+ // Validate arguments
+ if (dst == NULL || dst_size_long == 0 || src == NULL)
+ {
+ return 0;
+ }
+
+ if (compress2(dst, &dst_size_long, src, src_size, (int)level) != Z_OK)
+ {
+ return 0;
+ }
+
+ return dst_size_long;
+}
+
+// Get the maximum size of compressed data from data of src_size
+UINT CalcCompress(UINT src_size)
+{
+ return src_size * 2 + 256;
+}
+
+// Creating a Stack
+SK *NewSk()
+{
+ return NewSkEx(false);
+}
+SK *NewSkEx(bool no_compact)
+{
+ SK *s;
+
+ s = Malloc(sizeof(SK));
+ s->lock = NewLock();
+ s->ref = NewRef();
+ s->num_item = 0;
+ s->num_reserved = INIT_NUM_RESERVED;
+ s->p = Malloc(sizeof(void *) * s->num_reserved);
+ s->no_compact = no_compact;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(s), "SK", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWSK_COUNT);
+
+ return s;
+}
+
+// Release of the stack
+void ReleaseSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ CleanupSk(s);
+ }
+}
+
+// Clean up the stack
+void CleanupSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(s->p);
+ DeleteLock(s->lock);
+ Free(s);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(s));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREESK_COUNT);
+}
+
+// Lock of the stack
+void LockSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->lock);
+}
+
+// Unlock the stack
+void UnlockSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Unlock(s->lock);
+}
+
+// Push to the stack
+void Push(SK *s, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = s->num_item;
+ s->num_item++;
+
+ // Size expansion
+ if (s->num_item > s->num_reserved)
+ {
+ s->num_reserved = s->num_reserved * 2;
+ s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
+ }
+ s->p[i] = p;
+
+ // KS
+ KS_INC(KS_PUSH_COUNT);
+}
+
+// Pop from the stack
+void *Pop(SK *s)
+{
+ void *ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+ if (s->num_item == 0)
+ {
+ return NULL;
+ }
+ ret = s->p[s->num_item - 1];
+ s->num_item--;
+
+ // Size reduction
+ if (s->no_compact == false)
+ {
+ // Not to shrink when no_compact is true
+ if ((s->num_item * 2) <= s->num_reserved)
+ {
+ if (s->num_reserved >= (INIT_NUM_RESERVED * 2))
+ {
+ s->num_reserved = s->num_reserved / 2;
+ s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
+ }
+ }
+ }
+
+ // KS
+ KS_INC(KS_POP_COUNT);
+
+ return ret;
+}
+
+// Peep
+void *PeekQueue(QUEUE *q)
+{
+ void *p = NULL;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ if (q->num_item == 0)
+ {
+ // No items
+ return NULL;
+ }
+
+ // Read from the FIFO
+ PeekFifo(q->fifo, &p, sizeof(void *));
+
+ return p;
+}
+
+// Get one
+void *GetNext(QUEUE *q)
+{
+ void *p = NULL;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ if (q->num_item == 0)
+ {
+ // No items
+ return NULL;
+ }
+
+ // Read from the FIFO
+ ReadFifo(q->fifo, &p, sizeof(void *));
+ q->num_item--;
+
+ // KS
+ KS_INC(KS_GETNEXT_COUNT);
+
+ return p;
+}
+
+// Get one item from the queue (locking)
+void *GetNextWithLock(QUEUE *q)
+{
+ void *p;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ LockQueue(q);
+ {
+ p = GetNext(q);
+ }
+ UnlockQueue(q);
+
+ return p;
+}
+
+// Insert the int type in the queue
+void InsertQueueInt(QUEUE *q, UINT value)
+{
+ UINT *p;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ p = Clone(&value, sizeof(UINT));
+
+ InsertQueue(q, p);
+}
+
+// Insert to the queue
+void InsertQueue(QUEUE *q, void *p)
+{
+ // Validate arguments
+ if (q == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Write to the FIFO
+ WriteFifo(q->fifo, &p, sizeof(void *));
+
+ q->num_item++;
+
+ // KS
+ KS_INC(KS_INSERT_QUEUE_COUNT);
+}
+
+// Insert to the queue (locking)
+void InsertQueueWithLock(QUEUE *q, void *p)
+{
+ // Validate arguments
+ if (q == NULL || p == NULL)
+ {
+ return;
+ }
+
+ LockQueue(q);
+ {
+ InsertQueue(q, p);
+ }
+ UnlockQueue(q);
+}
+
+// Lock the queue
+void LockQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ Lock(q->lock);
+}
+
+// Unlock the queue
+void UnlockQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ Unlock(q->lock);
+}
+
+// Release of the queue
+void ReleaseQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ if (q->ref == NULL || Release(q->ref) == 0)
+ {
+ CleanupQueue(q);
+ }
+}
+
+// Clean-up the queue
+void CleanupQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ ReleaseFifo(q->fifo);
+ DeleteLock(q->lock);
+ Free(q);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(q));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREEQUEUE_COUNT);
+}
+
+// Creating a Queue
+QUEUE *NewQueue()
+{
+ QUEUE *q;
+
+ q = ZeroMalloc(sizeof(QUEUE));
+ q->lock = NewLock();
+ q->ref = NewRef();
+ q->num_item = 0;
+ q->fifo = NewFifo();
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWQUEUE_COUNT);
+
+ return q;
+}
+QUEUE *NewQueueFast()
+{
+ QUEUE *q;
+
+ q = ZeroMalloc(sizeof(QUEUE));
+ q->lock = NULL;
+ q->ref = NULL;
+ q->num_item = 0;
+ q->fifo = NewFifoFast();
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWQUEUE_COUNT);
+
+ return q;
+}
+
+// Set the comparison function to list
+void SetCmp(LIST *o, COMPARE *cmp)
+{
+ // Validate arguments
+ if (o == NULL || cmp == NULL)
+ {
+ return;
+ }
+
+ if (o->cmp != cmp)
+ {
+ o->cmp = cmp;
+ o->sorted = false;
+ }
+}
+
+// Clone the list
+LIST *CloneList(LIST *o)
+{
+ LIST *n = NewList(o->cmp);
+
+ // Memory reallocation
+ Free(n->p);
+ n->p = ToArray(o);
+ n->num_item = n->num_reserved = LIST_NUM(o);
+ n->sorted = o->sorted;
+
+ return n;
+}
+
+// Copy the list to an array
+void CopyToArray(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_TOARRAY_COUNT);
+
+ Copy(p, o->p, sizeof(void *) * o->num_item);
+}
+
+// Arrange the list to an array
+void *ToArray(LIST *o)
+{
+ return ToArrayEx(o, false);
+}
+void *ToArrayEx(LIST *o, bool fast)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ if (fast == false)
+ {
+ p = Malloc(sizeof(void *) * LIST_NUM(o));
+ }
+ else
+ {
+ p = MallocFast(sizeof(void *) * LIST_NUM(o));
+ }
+ // Copy
+ CopyToArray(o, p);
+
+ return p;
+}
+
+// Search in the list
+void *Search(LIST *o, void *target)
+{
+ void **ret;
+ // Validate arguments
+ if (o == NULL || target == NULL)
+ {
+ return NULL;
+ }
+ if (o->cmp == NULL)
+ {
+ return NULL;
+ }
+
+ // Check the sort
+ if (o->sorted == false)
+ {
+ // Sort because it is not sorted
+ Sort(o);
+ }
+
+ ret = (void **)bsearch(&target, o->p, o->num_item, sizeof(void *),
+ (int(*)(const void *, const void *))o->cmp);
+
+ // KS
+ KS_INC(KS_SEARCH_COUNT);
+
+ if (ret != NULL)
+ {
+ return *ret;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+// Insert an item to the list (Do not insert if it already exists)
+void InsertDistinct(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, p))
+ {
+ return;
+ }
+
+ Insert(o, p);
+}
+
+// Insert an item to the list
+void Insert(LIST *o, void *p)
+{
+ int low, high, middle;
+ UINT pos;
+ int i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (o->cmp == NULL)
+ {
+ // adding simply if there is no sort function
+ Add(o, p);
+ return;
+ }
+
+ // Sort immediately if it is not sorted
+ if (o->sorted == false)
+ {
+ Sort(o);
+ }
+
+ low = 0;
+ high = LIST_NUM(o) - 1;
+
+ pos = INFINITE;
+
+ while (low <= high)
+ {
+ int ret;
+
+ middle = (low + high) / 2;
+ ret = o->cmp(&(o->p[middle]), &p);
+
+ if (ret == 0)
+ {
+ pos = middle;
+ break;
+ }
+ else if (ret > 0)
+ {
+ high = middle - 1;
+ }
+ else
+ {
+ low = middle + 1;
+ }
+ }
+
+ if (pos == INFINITE)
+ {
+ pos = low;
+ }
+
+ o->num_item++;
+ if (o->num_item > o->num_reserved)
+ {
+ o->num_reserved *= 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+
+ if (LIST_NUM(o) >= 2)
+ {
+ for (i = (LIST_NUM(o) - 2);i >= (int)pos;i--)
+ {
+ o->p[i + 1] = o->p[i];
+ }
+ }
+
+ o->p[pos] = p;
+
+ // KS
+ KS_INC(KS_INSERT_COUNT);
+}
+
+// Setting the sort flag
+void SetSortFlag(LIST *o, bool sorted)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->sorted = sorted;
+}
+
+// Sort the list
+void Sort(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL || o->cmp == NULL)
+ {
+ return;
+ }
+
+ qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))o->cmp);
+ o->sorted = true;
+
+ // KS
+ KS_INC(KS_SORT_COUNT);
+}
+void SortEx(LIST *o, COMPARE *cmp)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))cmp);
+ o->sorted = false;
+
+ // KS
+ KS_INC(KS_SORT_COUNT);
+}
+
+// Examine whether a certain string items are present in the list (Unicode version)
+bool IsInListUniStr(LIST *o, wchar_t *str)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+
+ if (UniStrCmpi(s, str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Replace the pointer in the list
+bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || oldptr == NULL || newptr == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (p == oldptr)
+ {
+ o->p[i] = newptr;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Examine whether a string items are present in the list
+bool IsInListStr(LIST *o, char *str)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+
+ if (StrCmpi(s, str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get the pointer by scanning by UINT pointer in the list
+void *ListKeyToPointer(LIST *o, UINT key)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (POINTER_TO_KEY(p) == key)
+ {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+// Examine whether the key is present in the list
+bool IsInListKey(LIST *o, UINT key)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return false;
+ }
+
+ p = ListKeyToPointer(o, key);
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Examine whether the item exists in the list
+bool IsInList(LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *q = LIST_DATA(o, i);
+ if (p == q)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Add an element to the list (Don't add if it already exists)
+void AddDistinct(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, p))
+ {
+ return;
+ }
+
+ Add(o, p);
+}
+
+// Add an element to the list
+void Add(LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = o->num_item;
+ o->num_item++;
+
+ if (o->num_item > o->num_reserved)
+ {
+ o->num_reserved = o->num_reserved * 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+
+ o->p[i] = p;
+ o->sorted = false;
+
+ // KS
+ KS_INC(KS_INSERT_COUNT);
+}
+
+// Delete the elements specified by the key from the list
+bool DeleteKey(LIST *o, UINT key)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return false;
+ }
+
+ p = ListKeyToPointer(o, key);
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return Delete(o, p);
+}
+
+// Delete the element from the list
+bool Delete(LIST *o, void *p)
+{
+ UINT i, n;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < o->num_item;i++)
+ {
+ if (o->p[i] == p)
+ {
+ break;
+ }
+ }
+ if (i == o->num_item)
+ {
+ return false;
+ }
+
+ n = i;
+ for (i = n;i < (o->num_item - 1);i++)
+ {
+ o->p[i] = o->p[i + 1];
+ }
+ o->num_item--;
+ if ((o->num_item * 2) <= o->num_reserved)
+ {
+ if (o->num_reserved > (INIT_NUM_RESERVED * 2))
+ {
+ o->num_reserved = o->num_reserved / 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+ }
+
+ // KS
+ KS_INC(KS_DELETE_COUNT);
+
+ return true;
+}
+
+// Delete all elements from the list
+void DeleteAll(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->num_item = 0;
+ o->num_reserved = INIT_NUM_RESERVED;
+ o->p = ReAlloc(o->p, sizeof(void *) * INIT_NUM_RESERVED);
+}
+
+// Lock the list
+void LockList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Lock(o->lock);
+}
+
+// Unlock the list
+void UnlockList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Unlock(o->lock);
+}
+
+// Release the list
+void ReleaseList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->ref == NULL || Release(o->ref) == 0)
+ {
+ CleanupList(o);
+ }
+}
+
+// Clean up the list
+void CleanupList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Free(o->p);
+ if (o->lock != NULL)
+ {
+ DeleteLock(o->lock);
+ }
+ Free(o);
+
+ // KS
+ KS_INC(KS_FREELIST_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(o));
+#endif // DONT_USE_KERNEL_STATUS
+}
+
+// Check whether the specified number is already in the list
+bool IsIntInList(LIST *o, UINT i)
+{
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+bool IsInt64InList(LIST *o, UINT64 i)
+{
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT64 *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Remove all int from the interger list
+void DelAllInt(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ DeleteAll(o);
+}
+
+// Release the integer list
+void ReleaseIntList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+void ReleaseInt64List(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Delete an integer from list
+void DelInt(LIST *o, UINT i)
+{
+ LIST *o2 = NULL;
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ if (o2 == NULL)
+ {
+ o2 = NewListFast(NULL);
+ }
+ Add(o2, p);
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o2);j++)
+ {
+ UINT *p = LIST_DATA(o2, j);
+
+ Delete(o, p);
+
+ Free(p);
+ }
+
+ if (o2 != NULL)
+ {
+ ReleaseList(o2);
+ }
+}
+void DelInt64(LIST *o, UINT64 i)
+{
+ LIST *o2 = NULL;
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT64 *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ if (o2 == NULL)
+ {
+ o2 = NewListFast(NULL);
+ }
+ Add(o2, p);
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o2);j++)
+ {
+ UINT64 *p = LIST_DATA(o2, j);
+
+ Delete(o, p);
+
+ Free(p);
+ }
+
+ if (o2 != NULL)
+ {
+ ReleaseList(o2);
+ }
+}
+
+// Create a new list of integers
+LIST *NewIntList(bool sorted)
+{
+ LIST *o = NewList(sorted ? CompareInt : NULL);
+
+ return o;
+}
+LIST *NewInt64List(bool sorted)
+{
+ LIST *o = NewList(sorted ? CompareInt64 : NULL);
+
+ return o;
+}
+
+// Comparison of items in the list of integers
+int CompareInt(void *p1, void *p2)
+{
+ UINT *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *((UINT **)p1);
+ v2 = *((UINT **)p2);
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return COMPARE_RET(*v1, *v2);
+}
+int CompareInt64(void *p1, void *p2)
+{
+ UINT64 *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *((UINT64 **)p1);
+ v2 = *((UINT64 **)p2);
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return COMPARE_RET(*v1, *v2);
+}
+
+// Add an integer to the list
+void AddInt(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Add(o, Clone(&i, sizeof(UINT)));
+}
+void AddInt64(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Add(o, Clone(&i, sizeof(UINT64)));
+}
+void InsertInt(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(&i, sizeof(UINT)));
+}
+void InsertInt64(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(&i, sizeof(UINT64)));
+}
+
+// Add an integer to the list (no duplicates)
+void AddIntDistinct(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsIntInList(o, i) == false)
+ {
+ AddInt(o, i);
+ }
+}
+void AddInt64Distinct(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsInt64InList(o, i) == false)
+ {
+ AddInt64(o, i);
+ }
+}
+void InsertIntDistinct(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsIntInList(o, i) == false)
+ {
+ InsertInt(o, i);
+ }
+}
+void InsertInt64Distinct(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsInt64InList(o, i) == false)
+ {
+ InsertInt64(o, i);
+ }
+}
+
+// String comparison function (Unicode)
+int CompareUniStr(void *p1, void *p2)
+{
+ wchar_t *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(wchar_t **)p1;
+ s2 = *(wchar_t **)p2;
+
+ return UniStrCmp(s1, s2);
+}
+
+// Insert the string to the list
+bool InsertStr(LIST *o, char *str)
+{
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (Search(o, str) == NULL)
+ {
+ Insert(o, str);
+
+ return true;
+ }
+
+ return false;
+}
+
+// String comparison function
+int CompareStr(void *p1, void *p2)
+{
+ char *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(char **)p1;
+ s2 = *(char **)p2;
+
+ return StrCmpi(s1, s2);
+}
+
+// Create a list with an item
+LIST *NewListSingle(void *p)
+{
+ LIST *o = NewListFast(NULL);
+
+ Add(o, p);
+
+ return o;
+}
+
+// Creating a high-speed list (without lock)
+LIST *NewListFast(COMPARE *cmp)
+{
+ return NewListEx(cmp, true);
+}
+
+// Creating a list
+LIST *NewList(COMPARE *cmp)
+{
+ return NewListEx(cmp, false);
+}
+LIST *NewListEx(COMPARE *cmp, bool fast)
+{
+ return NewListEx2(cmp, fast, false);
+}
+LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc)
+{
+ LIST *o;
+
+ if (fast_malloc == false)
+ {
+ o = Malloc(sizeof(LIST));
+ }
+ else
+ {
+ o = MallocFast(sizeof(LIST));
+ }
+
+ if (fast == false)
+ {
+ o->lock = NewLock();
+ o->ref = NewRef();
+ }
+ else
+ {
+ o->lock = NULL;
+ o->ref = NULL;
+ }
+ o->num_item = 0;
+ o->num_reserved = INIT_NUM_RESERVED;
+ o->Param1 = 0;
+
+ if (fast_malloc == false)
+ {
+ o->p = Malloc(sizeof(void *) * o->num_reserved);
+ }
+ else
+ {
+ o->p = MallocFast(sizeof(void *) * o->num_reserved);
+ }
+
+ o->cmp = cmp;
+ o->sorted = true;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(o), "LIST", 0);
+#endif //DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWLIST_COUNT);
+
+ return o;
+}
+
+// Peek from the FIFO
+UINT PeekFifo(FIFO *f, void *p, UINT size)
+{
+ UINT read_size;
+ if (f == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_PEEK_FIFO_COUNT);
+
+ read_size = MIN(size, f->size);
+ if (read_size == 0)
+ {
+ return 0;
+ }
+
+ if (p != NULL)
+ {
+ Copy(p, (UCHAR *)f->p + f->pos, read_size);
+ }
+
+ return read_size;
+}
+
+// Read from the FIFO
+UINT ReadFifo(FIFO *f, void *p, UINT size)
+{
+ UINT read_size;
+ // Validate arguments
+ if (f == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ read_size = MIN(size, f->size);
+ if (read_size == 0)
+ {
+ return 0;
+ }
+ if (p != NULL)
+ {
+ Copy(p, (UCHAR *)f->p + f->pos, read_size);
+ }
+ f->pos += read_size;
+ f->size -= read_size;
+
+ f->total_read_size += (UINT64)read_size;
+
+ if (f->size == 0)
+ {
+ f->pos = 0;
+ }
+
+ // Rearrange the memory
+ if (f->pos >= FIFO_INIT_MEM_SIZE &&
+ f->memsize >= f->realloc_mem_size &&
+ (f->memsize / 2) > f->size)
+ {
+ void *new_p;
+ UINT new_size;
+
+ new_size = MAX(f->memsize / 2, FIFO_INIT_MEM_SIZE);
+ new_p = Malloc(new_size);
+ Copy(new_p, (UCHAR *)f->p + f->pos, f->size);
+
+ Free(f->p);
+
+ f->memsize = new_size;
+ f->p = new_p;
+ f->pos = 0;
+ }
+
+ // KS
+ KS_INC(KS_READ_FIFO_COUNT);
+
+ return read_size;
+}
+
+// Write to the FIFO
+void WriteFifo(FIFO *f, void *p, UINT size)
+{
+ UINT i, need_size;
+ bool realloc_flag;
+ // Validate arguments
+ if (f == NULL || size == 0)
+ {
+ return;
+ }
+
+ i = f->size;
+ f->size += size;
+ need_size = f->pos + f->size;
+ realloc_flag = false;
+
+ // Memory expansion
+ while (need_size > f->memsize)
+ {
+ f->memsize = MAX(f->memsize, FIFO_INIT_MEM_SIZE) * 3;
+ realloc_flag = true;
+ }
+
+ if (realloc_flag)
+ {
+ f->p = ReAlloc(f->p, f->memsize);
+ }
+
+ // Write the data
+ if (p != NULL)
+ {
+ Copy((UCHAR *)f->p + f->pos + i, p, size);
+ }
+
+ f->total_write_size += (UINT64)size;
+
+ // KS
+ KS_INC(KS_WRITE_FIFO_COUNT);
+}
+
+// Clear the FIFO
+void ClearFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ f->size = f->pos = 0;
+ f->memsize = FIFO_INIT_MEM_SIZE;
+ f->p = ReAlloc(f->p, f->memsize);
+}
+
+// Get the current pointer of the FIFO
+UCHAR *GetFifoPointer(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ return ((UCHAR *)f->p) + f->pos;
+}
+UCHAR *FifoPtr(FIFO *f)
+{
+ return GetFifoPointer(f);
+}
+
+// Get the size of the FIFO
+UINT FifoSize(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ return f->size;
+}
+
+// Lock the FIFO
+void LockFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ Lock(f->lock);
+}
+
+// Unlock the FIFO
+void UnlockFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ Unlock(f->lock);
+}
+
+// Release the FIFO
+void ReleaseFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ if (f->ref == NULL || Release(f->ref) == 0)
+ {
+ CleanupFifo(f);
+ }
+}
+
+// Clean-up the FIFO
+void CleanupFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(f->lock);
+ Free(f->p);
+ Free(f);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(f));
+#endif //DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREEFIFO_COUNT);
+}
+
+// Initialize the FIFO system
+void InitFifo()
+{
+ fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+}
+
+// Create a FIFO
+FIFO *NewFifo()
+{
+ return NewFifoEx(0, false);
+}
+FIFO *NewFifoFast()
+{
+ return NewFifoEx(0, true);
+}
+FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
+{
+ FIFO *f;
+
+ // Memory allocation
+ f = ZeroMalloc(sizeof(FIFO));
+
+ if (fast == false)
+ {
+ f->lock = NewLock();
+ f->ref = NewRef();
+ }
+ else
+ {
+ f->lock = NULL;
+ f->ref = NULL;
+ }
+
+ f->size = f->pos = 0;
+ f->memsize = FIFO_INIT_MEM_SIZE;
+ f->p = Malloc(FIFO_INIT_MEM_SIZE);
+
+ if (realloc_mem_size == 0)
+ {
+ realloc_mem_size = fifo_default_realloc_mem_size;
+ }
+
+ f->realloc_mem_size = realloc_mem_size;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(f), "FIFO", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWFIFO_COUNT);
+
+ return f;
+}
+
+// Get the default memory reclaiming size of the FIFO
+UINT GetFifoDefaultReallocMemSize()
+{
+ return fifo_default_realloc_mem_size;
+}
+
+// Set the default memory reclaiming size of the FIFO
+void SetFifoDefaultReallocMemSize(UINT size)
+{
+ if (size == 0)
+ {
+ size = FIFO_REALLOC_MEM_SIZE;
+ }
+
+ fifo_default_realloc_mem_size = size;
+}
+
+// Read a buffer from a file
+BUF *FileToBuf(IO *o)
+{
+ UCHAR hash1[MD5_SIZE], hash2[MD5_SIZE];
+ UINT size;
+ void *buf;
+ BUF *b;
+
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the size
+ if (FileRead(o, &size, sizeof(size)) == false)
+ {
+ return NULL;
+ }
+ size = Endian32(size);
+
+ if (size > FileSize(o))
+ {
+ return NULL;
+ }
+
+ // Read a hash
+ if (FileRead(o, hash1, sizeof(hash1)) == false)
+ {
+ return NULL;
+ }
+
+ // Read from the buffer
+ buf = Malloc(size);
+ if (FileRead(o, buf, size) == false)
+ {
+ Free(buf);
+ return NULL;
+ }
+
+ // Take a hash
+ Hash(hash2, buf, size, false);
+
+ // Compare the hashes
+ if (Cmp(hash1, hash2, sizeof(hash1)) != 0)
+ {
+ // Hashes are different
+ Free(buf);
+ return NULL;
+ }
+
+ // Create a buffer
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ Free(buf);
+ b->Current = 0;
+
+ return b;
+}
+
+// Read a dump file into a buffer
+BUF *ReadDump(char *filename)
+{
+ return ReadDumpWithMaxSize(filename, 0);
+}
+BUF *ReadDumpWithMaxSize(char *filename, UINT max_size)
+{
+ IO *o;
+ BUF *b;
+ UINT size;
+ void *data;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ o = FileOpen(filename, false);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ size = FileSize(o);
+
+ if (max_size != 0)
+ {
+ if (size > max_size)
+ {
+ size = max_size;
+ }
+ }
+
+ data = Malloc(size);
+ FileRead(o, data, size);
+ FileClose(o);
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ b->Current = 0;
+ Free(data);
+
+ return b;
+}
+BUF *ReadDumpW(wchar_t *filename)
+{
+ return ReadDumpExW(filename, true);
+}
+BUF *ReadDumpExW(wchar_t *filename, bool read_lock)
+{
+ IO *o;
+ BUF *b;
+ UINT size;
+ void *data;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ o = FileOpenExW(filename, false, read_lock);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ size = FileSize(o);
+ data = Malloc(size);
+ FileRead(o, data, size);
+ FileClose(o);
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ b->Current = 0;
+ Free(data);
+
+ return b;
+}
+
+// Write down the data
+bool DumpDataW(void *data, UINT size, wchar_t *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (filename == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ o = FileCreateW(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, data, size);
+ FileClose(o);
+
+ return true;
+}
+bool DumpData(void *data, UINT size, char *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (filename == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, data, size);
+ FileClose(o);
+
+ return true;
+}
+
+// Dump the contents of the buffer to the file
+bool DumpBuf(BUF *b, char *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, b->Buf, b->Size);
+ FileClose(o);
+
+ return true;
+}
+bool DumpBufW(BUF *b, wchar_t *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ o = FileCreateW(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, b->Buf, b->Size);
+ FileClose(o);
+
+ return true;
+}
+
+// Write to the file only if the contents of the file is different
+bool DumpBufWIfNecessary(BUF *b, wchar_t *filename)
+{
+ BUF *now;
+ bool need = true;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ now = ReadDumpW(filename);
+
+ if (now != NULL)
+ {
+ if (CompareBuf(now, b))
+ {
+ need = false;
+ }
+
+ FreeBuf(now);
+ }
+
+ if (need == false)
+ {
+ return true;
+ }
+ else
+ {
+ return DumpBufW(b, filename);
+ }
+}
+
+// Write the buffer to a file
+bool BufToFile(IO *o, BUF *b)
+{
+ UCHAR hash[MD5_SIZE];
+ UINT size;
+
+ // Validate arguments
+ if (o == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ // Hash the data
+ Hash(hash, b->Buf, b->Size, false);
+
+ size = Endian32(b->Size);
+
+ // Write the size
+ if (FileWrite(o, &size, sizeof(size)) == false)
+ {
+ return false;
+ }
+
+ // Write a hash
+ if (FileWrite(o, hash, sizeof(hash)) == false)
+ {
+ return false;
+ }
+
+ // Write the data
+ if (FileWrite(o, b->Buf, b->Size) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a buffer from memory
+BUF *NewBufFromMemory(void *buf, UINT size)
+{
+ BUF *b;
+ // Validate arguments
+ if (buf == NULL && size != 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBufToBegin(b);
+
+ return b;
+}
+
+// Creating a buffer
+BUF *NewBuf()
+{
+ BUF *b;
+
+ // Memory allocation
+ b = Malloc(sizeof(BUF));
+ b->Buf = Malloc(INIT_BUF_SIZE);
+ b->Size = 0;
+ b->Current = 0;
+ b->SizeReserved = INIT_BUF_SIZE;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(b), "BUF", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWBUF_COUNT);
+ KS_INC(KS_CURRENT_BUF_COUNT);
+
+ return b;
+}
+
+// Clearing the buffer
+void ClearBuf(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ b->Size = 0;
+ b->Current = 0;
+}
+
+// Write to the buffer
+void WriteBuf(BUF *b, void *buf, UINT size)
+{
+ UINT new_size;
+ // Validate arguments
+ if (b == NULL || buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ new_size = b->Current + size;
+ if (new_size > b->Size)
+ {
+ // Adjust the size
+ AdjustBufSize(b, new_size);
+ }
+ if (b->Buf != NULL)
+ {
+ Copy((UCHAR *)b->Buf + b->Current, buf, size);
+ }
+ b->Current += size;
+ b->Size = new_size;
+
+ // KS
+ KS_INC(KS_WRITE_BUF_COUNT);
+}
+
+// Append a string to the buffer
+void AddBufStr(BUF *b, char *str)
+{
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+}
+
+// Write a line to the buffer
+void WriteBufLine(BUF *b, char *str)
+{
+ char *crlf = "\r\n";
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+ WriteBuf(b, crlf, StrLen(crlf));
+}
+
+// Write a string to a buffer
+bool WriteBufStr(BUF *b, char *str)
+{
+ UINT len;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // String length
+ len = StrLen(str);
+ if (WriteBufInt(b, len + 1) == false)
+ {
+ return false;
+ }
+
+ // String body
+ WriteBuf(b, str, len);
+
+ return true;
+}
+
+// Read a string from the buffer
+bool ReadBufStr(BUF *b, char *str, UINT size)
+{
+ UINT len;
+ UINT read_size;
+ // Validate arguments
+ if (b == NULL || str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ // Read the length of the string
+ len = ReadBufInt(b);
+ if (len == 0)
+ {
+ return false;
+ }
+ len--;
+ if (len <= (size - 1))
+ {
+ size = len + 1;
+ }
+
+ read_size = MIN(len, (size - 1));
+
+ // Read the string body
+ if (ReadBuf(b, str, read_size) != read_size)
+ {
+ return false;
+ }
+ if (read_size < len)
+ {
+ ReadBuf(b, NULL, len - read_size);
+ }
+ str[read_size] = 0;
+
+ return true;
+}
+
+// Write a 64 bit integer to the buffer
+bool WriteBufInt64(BUF *b, UINT64 value)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ value = Endian64(value);
+
+ WriteBuf(b, &value, sizeof(UINT64));
+ return true;
+}
+
+// Write an integer in the the buffer
+bool WriteBufInt(BUF *b, UINT value)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ value = Endian32(value);
+
+ WriteBuf(b, &value, sizeof(UINT));
+ return true;
+}
+
+// Write a UCHAR to the buffer
+bool WriteBufChar(BUF *b, UCHAR uc)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ WriteBuf(b, &uc, 1);
+
+ return true;
+}
+
+// Read a UCHAR from the buffer
+UCHAR ReadBufChar(BUF *b)
+{
+ UCHAR uc;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &uc, 1) != 1)
+ {
+ return 0;
+ }
+
+ return uc;
+}
+
+// Read a 64bit integer from the buffer
+UINT64 ReadBufInt64(BUF *b)
+{
+ UINT64 value;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &value, sizeof(UINT64)) != sizeof(UINT64))
+ {
+ return 0;
+ }
+ return Endian64(value);
+}
+
+// Read an integer from the buffer
+UINT ReadBufInt(BUF *b)
+{
+ UINT value;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &value, sizeof(UINT)) != sizeof(UINT))
+ {
+ return 0;
+ }
+ return Endian32(value);
+}
+
+// Write the buffer to a buffer
+void WriteBufBuf(BUF *b, BUF *bb)
+{
+ // Validate arguments
+ if (b == NULL || bb == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, bb->Buf, bb->Size);
+}
+
+// Read into a buffer from the buffer
+BUF *ReadBufFromBuf(BUF *b, UINT size)
+{
+ BUF *ret;
+ UCHAR *data;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ data = Malloc(size);
+ if (ReadBuf(b, data, size) != size)
+ {
+ Free(data);
+ return NULL;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, data, size);
+ SeekBuf(ret, 0, 0);
+
+ Free(data);
+
+ return ret;
+}
+
+// Read from the buffer
+UINT ReadBuf(BUF *b, void *buf, UINT size)
+{
+ UINT size_read;
+ // Validate arguments
+ if (b == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ if (b->Buf == NULL)
+ {
+ Zero(buf, size);
+ return 0;
+ }
+ size_read = size;
+ if ((b->Current + size) >= b->Size)
+ {
+ size_read = b->Size - b->Current;
+ if (buf != NULL)
+ {
+ Zero((UCHAR *)buf + size_read, size - size_read);
+ }
+ }
+
+ if (buf != NULL)
+ {
+ Copy(buf, (UCHAR *)b->Buf + b->Current, size_read);
+ }
+
+ b->Current += size_read;
+
+ // KS
+ KS_INC(KS_READ_BUF_COUNT);
+
+ return size_read;
+}
+
+// Adjusting the buffer size
+void AdjustBufSize(BUF *b, UINT new_size)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->SizeReserved >= new_size)
+ {
+ return;
+ }
+
+ while (b->SizeReserved < new_size)
+ {
+ b->SizeReserved = b->SizeReserved * 2;
+ }
+ b->Buf = ReAlloc(b->Buf, b->SizeReserved);
+
+ // KS
+ KS_INC(KS_ADJUST_BUFSIZE_COUNT);
+}
+
+// Seek to the beginning of the buffer
+void SeekBufToBegin(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, 0, 0);
+}
+
+// Seek to end of the buffer
+void SeekBufToEnd(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, b->Size, 0);
+}
+
+// Seek of the buffer
+void SeekBuf(BUF *b, UINT offset, int mode)
+{
+ UINT new_pos;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (mode == 0)
+ {
+ // Absolute position
+ new_pos = offset;
+ }
+ else
+ {
+ if (mode > 0)
+ {
+ // Move Right
+ new_pos = b->Current + offset;
+ }
+ else
+ {
+ // Move Left
+ if (b->Current >= offset)
+ {
+ new_pos = b->Current - offset;
+ }
+ else
+ {
+ new_pos = 0;
+ }
+ }
+ }
+ b->Current = MAKESURE(new_pos, 0, b->Size);
+
+ KS_INC(KS_SEEK_BUF_COUNT);
+}
+
+// Free the buffer
+void FreeBuf(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(b->Buf);
+ Free(b);
+
+ // KS
+ KS_INC(KS_FREEBUF_COUNT);
+ KS_DEC(KS_CURRENT_BUF_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(b));
+#endif // DONT_USE_KERNEL_STATUS
+}
+
+// Compare BUFs whether two are identical
+bool CompareBuf(BUF *b1, BUF *b2)
+{
+ // Validate arguments
+ if (b1 == NULL && b2 == NULL)
+ {
+ return true;
+ }
+ if (b1 == NULL || b2 == NULL)
+ {
+ return false;
+ }
+
+ if (b1->Size != b2->Size)
+ {
+ return false;
+ }
+
+ if (Cmp(b1->Buf, b2->Buf, b1->Size) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a buffer from the memory area
+BUF *MemToBuf(void *data, UINT size)
+{
+ BUF *b;
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Creating a random number buffer
+BUF *RandBuf(UINT size)
+{
+ void *data = Malloc(size);
+ BUF *ret;
+
+ Rand(data, size);
+
+ ret = MemToBuf(data, size);
+
+ Free(data);
+
+ return ret;
+}
+
+// Read the rest part of the buffer
+BUF *ReadRemainBuf(BUF *b)
+{
+ UINT size;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ if (b->Size < b->Current)
+ {
+ return NULL;
+ }
+
+ size = b->Size - b->Current;
+
+ return ReadBufFromBuf(b, size);
+}
+
+// Clone the buffer
+BUF *CloneBuf(BUF *b)
+{
+ BUF *bb;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bb = MemToBuf(b->Buf, b->Size);
+
+ return bb;
+}
+
+// Endian conversion of Unicode string
+void EndianUnicode(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ str[i] = Endian16(str[i]);
+ }
+}
+
+// Endian conversion 16bit
+USHORT Endian16(USHORT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap16(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 32bit
+UINT Endian32(UINT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap32(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 64bit
+UINT64 Endian64(UINT64 src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap64(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Swap data of any
+void Swap(void *buf, UINT size)
+{
+ UCHAR *tmp, *src;
+ UINT i;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ src = (UCHAR *)buf;
+ tmp = Malloc(size);
+ for (i = 0;i < size;i++)
+ {
+ tmp[size - i - 1] = src[i];
+ }
+
+ Copy(buf, tmp, size);
+ Free(buf);
+}
+
+// 16bit swap
+USHORT Swap16(USHORT value)
+{
+ USHORT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 32bit swap
+UINT Swap32(UINT value)
+{
+ UINT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 64-bit swap
+UINT64 Swap64(UINT64 value)
+{
+ UINT64 r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[7];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[6];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[5];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[4];
+ ((BYTE *)&r)[4] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[5] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[6] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[7] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// Base64 encode
+UINT Encode64(char *dst, char *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ return B64_Encode(dst, src, StrLen(src));
+}
+
+// Base64 decoding
+UINT Decode64(char *dst, char *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ return B64_Decode(dst, src, StrLen(src));
+}
+
+// Base64 encode
+int B64_Encode(char *set, char *source, int len)
+{
+ BYTE *src;
+ int i,j;
+ src = (BYTE *)source;
+ j = 0;
+ i = 0;
+ if (!len)
+ {
+ return 0;
+ }
+ while (TRUE)
+ {
+ if (i >= len)
+ {
+ return j;
+ }
+ if (set)
+ {
+ set[j] = B64_CodeToChar((src[i]) >> 2);
+ }
+ if (i + 1 >= len)
+ {
+ if (set)
+ {
+ set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);
+ set[j + 2] = '=';
+ set[j + 3] = '=';
+ }
+ return j + 4;
+ }
+ if (set)
+ {
+ set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));
+ }
+ if (i + 2 >= len)
+ {
+ if (set)
+ {
+ set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);
+ set[j + 3] = '=';
+ }
+ return j + 4;
+ }
+ if (set)
+ {
+ set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));
+ set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);
+ }
+ i += 3;
+ j += 4;
+ }
+}
+
+// Base64 decode
+int B64_Decode(char *set, char *source, int len)
+{
+ int i,j;
+ char a1,a2,a3,a4;
+ char *src;
+ int f1,f2,f3,f4;
+ src = source;
+ i = 0;
+ j = 0;
+ while (TRUE)
+ {
+ f1 = f2 = f3 = f4 = 0;
+ if (i >= len)
+ {
+ break;
+ }
+ f1 = 1;
+ a1 = B64_CharToCode(src[i]);
+ if (a1 == -1)
+ {
+ f1 = 0;
+ }
+ if (i >= len + 1)
+ {
+ a2 = 0;
+ }
+ else
+ {
+ a2 = B64_CharToCode(src[i + 1]);
+ f2 = 1;
+ if (a2 == -1)
+ {
+ f2 = 0;
+ }
+ }
+ if (i >= len + 2)
+ {
+ a3 = 0;
+ }
+ else
+ {
+ a3 = B64_CharToCode(src[i + 2]);
+ f3 = 1;
+ if (a3 == -1)
+ {
+ f3 = 0;
+ }
+ }
+ if (i >= len + 3)
+ {
+ a4 = 0;
+ }
+ else
+ {
+ a4 = B64_CharToCode(src[i + 3]);
+ f4 = 1;
+ if (a4 == -1)
+ {
+ f4 = 0;
+ }
+ }
+ if (f1 && f2)
+ {
+ if (set)
+ {
+ set[j] = (a1 << 2) + (a2 >> 4);
+ }
+ j++;
+ }
+ if (f2 && f3)
+ {
+ if (set)
+ {
+ set[j] = (a2 << 4) + (a3 >> 2);
+ }
+ j++;
+ }
+ if (f3 && f4)
+ {
+ if (set)
+ {
+ set[j] = (a3 << 6) + a4;
+ }
+ j++;
+ }
+ i += 4;
+ }
+ return j;
+}
+
+// Base64 : Convert a code to a character
+char B64_CodeToChar(BYTE c)
+{
+ BYTE r;
+ r = '=';
+ if (c <= 0x19)
+ {
+ r = c + 'A';
+ }
+ if (c >= 0x1a && c <= 0x33)
+ {
+ r = c - 0x1a + 'a';
+ }
+ if (c >= 0x34 && c <= 0x3d)
+ {
+ r = c - 0x34 + '0';
+ }
+ if (c == 0x3e)
+ {
+ r = '+';
+ }
+ if (c == 0x3f)
+ {
+ r = '/';
+ }
+ return r;
+}
+
+// Base64 : Convert a character to a code
+char B64_CharToCode(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ {
+ return c - 'A';
+ }
+ if (c >= 'a' && c <= 'z')
+ {
+ return c - 'a' + 0x1a;
+ }
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0' + 0x34;
+ }
+ if (c == '+')
+ {
+ return 0x3e;
+ }
+ if (c == '/')
+ {
+ return 0x3f;
+ }
+ if (c == '=')
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// High-speed Malloc (currently not implemented)
+void *MallocFast(UINT size)
+{
+ return Malloc(size);
+}
+
+// Malloc
+void *Malloc(UINT size)
+{
+ return MallocEx(size, false);
+}
+void *MallocEx(UINT size, bool zero_clear_when_free)
+{
+ MEMTAG *tag;
+ UINT real_size;
+
+ real_size = CALC_MALLOCSIZE(size);
+
+ tag = InternalMalloc(real_size);
+
+ Zero(tag, sizeof(MEMTAG));
+ tag->Magic = MEMTAG_MAGIC;
+ tag->Size = size;
+ tag->ZeroFree = zero_clear_when_free;
+
+ return MEMTAG_TO_POINTER(tag);
+}
+
+// Get memory size
+UINT GetMemSize(void *addr)
+{
+ MEMTAG *tag;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return 0;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ return tag->Size;
+}
+
+// ReAlloc
+void *ReAlloc(void *addr, UINT size)
+{
+ MEMTAG *tag;
+ bool zerofree;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return NULL;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ zerofree = tag->ZeroFree;
+
+ if (tag->Size == size)
+ {
+ // No size change
+ return addr;
+ }
+ else
+ {
+ if (zerofree)
+ {
+ // Size changed (zero clearing required)
+ void *new_p = MallocEx(size, true);
+
+ if (tag->Size <= size)
+ {
+ // Size expansion
+ Copy(new_p, addr, tag->Size);
+ }
+ else
+ {
+ // Size reduction
+ Copy(new_p, addr, size);
+ }
+
+ // Release the old block
+ Free(addr);
+
+ return new_p;
+ }
+ else
+ {
+ // Size changed
+ MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));
+
+ Zero(tag2, sizeof(MEMTAG));
+ tag2->Magic = MEMTAG_MAGIC;
+ tag2->Size = size;
+
+ return MEMTAG_TO_POINTER(tag2);
+ }
+ }
+}
+
+// Free
+void Free(void *addr)
+{
+ MEMTAG *tag;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ if (tag->ZeroFree)
+ {
+ // Zero clear
+ Zero(addr, tag->Size);
+ }
+
+ // Memory release
+ tag->Magic = 0;
+ InternalFree(tag);
+}
+
+// Check the memtag
+void CheckMemTag(MEMTAG *tag)
+{
+#ifndef DONT_CHECK_HEAP
+ // Validate arguments
+ if (tag == NULL)
+ {
+ AbortExitEx("CheckMemTag: tag == NULL");
+ return;
+ }
+
+ if (tag->Magic != MEMTAG_MAGIC)
+ {
+ AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");
+ return;
+ }
+#endif // DONT_CHECK_HEAP
+}
+
+// ZeroMalloc
+void *ZeroMalloc(UINT size)
+{
+ return ZeroMallocEx(size, false);
+}
+void *ZeroMallocEx(UINT size, bool zero_clear_when_free)
+{
+ void *p = MallocEx(size, zero_clear_when_free);
+ Zero(p, size);
+ return p;
+}
+void *ZeroMallocFast(UINT size)
+{
+ void *p = MallocFast(size);
+ Zero(p, size);
+ return p;
+}
+
+// Memory allocation
+void *InternalMalloc(UINT size)
+{
+ void *addr;
+ UINT retry = 0;
+ size = MORE(size, 1);
+
+ // KS
+ KS_INC(KS_MALLOC_COUNT);
+ KS_INC(KS_TOTAL_MEM_COUNT);
+ KS_ADD(KS_TOTAL_MEM_SIZE, size);
+ KS_INC(KS_CURRENT_MEM_COUNT);
+
+ // Attempt to allocate memory until success
+ while (true)
+ {
+ if ((retry++) > MEMORY_MAX_RETRY)
+ {
+ AbortExitEx("InternalMalloc: error: malloc() failed.\n\n");
+ }
+ addr = OSMemoryAlloc(size);
+ if (addr != NULL)
+ {
+ break;
+ }
+
+ OSSleep(MEMORY_SLEEP_TIME);
+ }
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackNewObj(POINTER_TO_UINT64(addr), "MEM", size);
+#endif //DONT_USE_KERNEL_STATUS
+
+ return addr;
+}
+
+// Memory release
+void InternalFree(void *addr)
+{
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_DEC(KS_CURRENT_MEM_COUNT);
+ KS_INC(KS_FREE_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackDeleteObj(POINTER_TO_UINT64(addr));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // Memory release
+ OSMemoryFree(addr);
+}
+
+// Memory reallocation
+void *InternalReAlloc(void *addr, UINT size)
+{
+ void *new_addr;
+ UINT retry = 0;
+ size = MORE(size, 1);
+
+ // KS
+ KS_INC(KS_REALLOC_COUNT);
+ KS_ADD(KS_TOTAL_MEM_SIZE, size);
+
+ // Attempt to allocate memory until success
+ while (true)
+ {
+ if ((retry++) > MEMORY_MAX_RETRY)
+ {
+ AbortExitEx("InternalReAlloc: error: realloc() failed.\n\n");
+ }
+ new_addr = OSMemoryReAlloc(addr, size);
+ if (new_addr != NULL)
+ {
+ break;
+ }
+
+ OSSleep(MEMORY_SLEEP_TIME);
+ }
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackChangeObjSize((DWORD)addr, size, (DWORD)new_addr);
+#endif // DONT_USE_KERNEL_STATUS
+
+ return new_addr;
+}
+
+// Add the heading space to the memory area
+void *AddHead(void *src, UINT src_size, void *head, UINT head_size)
+{
+ void *ret;
+ UINT ret_size;
+ // Validate arguments
+ if ((src == NULL && src_size != 0) || (head == NULL && head_size != 0))
+ {
+ return NULL;
+ }
+
+ ret_size = src_size + head_size;
+
+ ret = Malloc(ret_size);
+
+ Copy(ret, head, head_size);
+
+ Copy(((UCHAR *)ret) + head_size, src, src_size);
+
+ return ret;
+}
+
+// Clone the memory area (only the tail)
+void *CloneTail(void *src, UINT src_size, UINT dst_size)
+{
+ // Validate arguments
+ if (src_size != 0 && src == NULL)
+ {
+ return NULL;
+ }
+
+ if (src_size >= dst_size)
+ {
+ return Clone(((UCHAR *)src) + (src_size - dst_size), dst_size);
+ }
+ else
+ {
+ return Clone(src, src_size);
+ }
+}
+
+// Clone the memory area
+void *Clone(void *addr, UINT size)
+{
+ void *ret;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return NULL;
+ }
+
+ ret = Malloc(size);
+ Copy(ret, addr, size);
+
+ return ret;
+}
+
+// Memory copy
+void Copy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0 || dst == src)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_COPY_COUNT);
+
+ memcpy(dst, src, size);
+}
+
+// Memory comparison
+int Cmp(void *p1, void *p2, UINT size)
+{
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ return memcmp(p1, p2, (size_t)size);
+}
+
+// Memory comparison (case-insensitive)
+int CmpCaseIgnore(void *p1, void *p2, UINT size)
+{
+ UINT i;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ char c1 = (char)(*(((UCHAR *)p1) + i));
+ char c2 = (char)(*(((UCHAR *)p2) + i));
+
+ c1 = ToUpper(c1);
+ c2 = ToUpper(c2);
+
+ if (c1 != c2)
+ {
+ return COMPARE_RET(c1, c2);
+ }
+ }
+
+ return 0;
+}
+
+// Zero-clear of memory
+void Zero(void *addr, UINT size)
+{
+ // Validate arguments
+ if (addr == NULL || size == 0)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_ZERO_COUNT);
+
+ memset(addr, 0, size);
+}
+
+// Compare the string map entries
+int StrMapCmp(void *p1, void *p2)
+{
+ STRMAP_ENTRY *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(STRMAP_ENTRY **)p1;
+ s2 = *(STRMAP_ENTRY **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(s1->Name, s2->Name);
+}
+
+// Create a string map (the data that can be searched by the string)
+LIST *NewStrMap()
+{
+ return NewList(StrMapCmp);
+}
+
+// Search in string map
+void *StrMapSearch(LIST *map, char *key)
+{
+ STRMAP_ENTRY tmp, *result;
+ tmp.Name = key;
+ result = (STRMAP_ENTRY*)Search(map, &tmp);
+ if(result != NULL)
+ {
+ return result->Value;
+ }
+ return NULL;
+}
+
+// XOR the data
+void XorData(void *dst, void *src1, void *src2, UINT size)
+{
+ UINT i;
+ UCHAR *d, *c1, *c2;
+ // Validate arguments
+ if (dst == NULL || src1 == NULL || src2 == NULL || size == 0)
+ {
+ return;
+ }
+
+ d = (UCHAR *)dst;
+ c1 = (UCHAR *)src1;
+ c2 = (UCHAR *)src2;
+
+ for (i = 0;i < size;i++)
+ {
+ *d = (*c1) ^ (*c2);
+
+ d++;
+ c1++;
+ c2++;
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Memory.h b/src/Mayaqua/Memory.h
new file mode 100644
index 00000000..7ebc4dd6
--- /dev/null
+++ b/src/Mayaqua/Memory.h
@@ -0,0 +1,429 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Memory.h
+// Header of Memory.c
+
+#ifndef MEMORY_H
+#define MEMORY_H
+
+// Memory size that can be passed to the kernel at a time
+#define MAX_SEND_BUF_MEM_SIZE (10 * 1024 * 1024)
+
+// The magic number for memory tag
+#define MEMTAG_MAGIC 0x49414449
+
+#define CALC_MALLOCSIZE(size) ((MAX(size, 1)) + sizeof(MEMTAG))
+#define MEMTAG_TO_POINTER(p) ((void *)(((UCHAR *)(p)) + sizeof(MEMTAG)))
+#define POINTER_TO_MEMTAG(p) ((MEMTAG *)(((UCHAR *)(p)) - sizeof(MEMTAG)))
+#define IS_NULL_POINTER(p) (((p) == NULL) || ((POINTER_TO_UINT64(p) == (UINT64)sizeof(MEMTAG))))
+
+// Fixed size of a block of memory pool
+#define MEMPOOL_MAX_SIZE 3000
+
+
+// Memory tag
+struct MEMTAG
+{
+ UINT Magic;
+ UINT Size;
+ bool ZeroFree;
+ UINT Padding;
+};
+
+// Buffer
+struct BUF
+{
+ void *Buf;
+ UINT Size;
+ UINT SizeReserved;
+ UINT Current;
+};
+
+// FIFO
+struct FIFO
+{
+ REF *ref;
+ LOCK *lock;
+ void *p;
+ UINT pos, size, memsize;
+ UINT realloc_mem_size;
+ UINT64 total_read_size;
+ UINT64 total_write_size;
+};
+
+// List
+struct LIST
+{
+ REF *ref;
+ UINT num_item, num_reserved;
+ void **p;
+ LOCK *lock;
+ COMPARE *cmp;
+ bool sorted;
+ UINT64 Param1;
+};
+
+// Queue
+struct QUEUE
+{
+ REF *ref;
+ UINT num_item;
+ FIFO *fifo;
+ LOCK *lock;
+};
+
+// Stack
+struct SK
+{
+ REF *ref;
+ UINT num_item, num_reserved;
+ void **p;
+ LOCK *lock;
+ bool no_compact;
+};
+
+// Candidate list
+struct CANDIDATE
+{
+ wchar_t *Str; // String
+ UINT64 LastSelectedTime; // Date and time last selected
+};
+
+struct STRMAP_ENTRY
+{
+ char *Name;
+ void *Value;
+};
+
+// Shared buffer
+struct SHARED_BUFFER
+{
+ REF *Ref;
+ void *Data;
+ UINT Size;
+};
+
+// Macro
+#define LIST_DATA(o, i) (((o) != NULL) ? ((o)->p[(i)]) : NULL)
+#define LIST_NUM(o) (((o) != NULL) ? (o)->num_item : 0)
+
+
+// Function pointer type to get a hash function
+typedef UINT (GET_HASH)(void *p);
+
+// Hash list
+struct HASH_LIST
+{
+ UINT Bits;
+ UINT Size;
+ GET_HASH *GetHashProc;
+ COMPARE *CompareProc;
+ LOCK *Lock;
+ REF *Ref;
+ LIST **Entries;
+ UINT NumItems;
+ LIST *AllList;
+};
+
+// Function prototype
+HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list);
+void ReleaseHashList(HASH_LIST *h);
+void CleanupHashList(HASH_LIST *h);
+void AddHash(HASH_LIST *h, void *p);
+bool DeleteHash(HASH_LIST *h, void *p);
+void *SearchHash(HASH_LIST *h, void *t);
+UINT CalcHashForHashList(HASH_LIST *h, void *p);
+void **HashListToArray(HASH_LIST *h, UINT *num);
+void LockHashList(HASH_LIST *h);
+void UnlockHashList(HASH_LIST *h);
+
+LIST *NewCandidateList();
+void FreeCandidateList(LIST *o);
+int ComapreCandidate(void *p1, void *p2);
+void AddCandidate(LIST *o, wchar_t *str, UINT num_max);
+BUF *CandidateToBuf(LIST *o);
+LIST *BufToCandidate(BUF *b);
+
+void *Malloc(UINT size);
+void *MallocEx(UINT size, bool zero_clear_when_free);
+void *MallocFast(UINT size);
+void *ZeroMalloc(UINT size);
+void *ZeroMallocFast(UINT size);
+void *ZeroMallocEx(UINT size, bool zero_clear_when_free);
+void *ReAlloc(void *addr, UINT size);
+void Free(void *addr);
+void CheckMemTag(MEMTAG *tag);
+UINT GetMemSize(void *addr);
+
+void *InternalMalloc(UINT size);
+void *InternalReAlloc(void *addr, UINT size);
+void InternalFree(void *addr);
+
+void Copy(void *dst, void *src, UINT size);
+int Cmp(void *p1, void *p2, UINT size);
+int CmpCaseIgnore(void *p1, void *p2, UINT size);
+void ZeroMem(void *addr, UINT size);
+void Zero(void *addr, UINT size);
+void *Clone(void *addr, UINT size);
+void *CloneTail(void *src, UINT src_size, UINT dst_size);
+void *AddHead(void *src, UINT src_size, void *head, UINT head_size);
+
+char B64_CodeToChar(BYTE c);
+char B64_CharToCode(char c);
+int B64_Encode(char *set, char *source, int len);
+int B64_Decode(char *set, char *source, int len);
+UINT Encode64(char *dst, char *src);
+UINT Decode64(char *dst, char *src);
+
+void Swap(void *buf, UINT size);
+USHORT Swap16(USHORT value);
+UINT Swap32(UINT value);
+UINT64 Swap64(UINT64 value);
+USHORT Endian16(USHORT src);
+UINT Endian32(UINT src);
+UINT64 Endian64(UINT64 src);
+void EndianUnicode(wchar_t *str);
+
+BUF *NewBuf();
+BUF *NewBufFromMemory(void *buf, UINT size);
+void ClearBuf(BUF *b);
+void WriteBuf(BUF *b, void *buf, UINT size);
+void WriteBufBuf(BUF *b, BUF *bb);
+UINT ReadBuf(BUF *b, void *buf, UINT size);
+BUF *ReadBufFromBuf(BUF *b, UINT size);
+void AdjustBufSize(BUF *b, UINT new_size);
+void SeekBuf(BUF *b, UINT offset, int mode);
+void SeekBufToEnd(BUF *b);
+void SeekBufToBegin(BUF *b);
+void FreeBuf(BUF *b);
+bool BufToFile(IO *o, BUF *b);
+BUF *FileToBuf(IO *o);
+UINT ReadBufInt(BUF *b);
+UINT64 ReadBufInt64(BUF *b);
+UCHAR ReadBufChar(BUF *b);
+bool WriteBufInt(BUF *b, UINT value);
+bool WriteBufInt64(BUF *b, UINT64 value);
+bool WriteBufChar(BUF *b, UCHAR uc);
+bool ReadBufStr(BUF *b, char *str, UINT size);
+bool WriteBufStr(BUF *b, char *str);
+void WriteBufLine(BUF *b, char *str);
+void AddBufStr(BUF *b, char *str);
+bool DumpBuf(BUF *b, char *filename);
+bool DumpBufW(BUF *b, wchar_t *filename);
+bool DumpBufWIfNecessary(BUF *b, wchar_t *filename);
+bool DumpData(void *data, UINT size, char *filename);
+bool DumpDataW(void *data, UINT size, wchar_t *filename);
+BUF *ReadDump(char *filename);
+BUF *ReadDumpWithMaxSize(char *filename, UINT max_size);
+BUF *ReadDumpW(wchar_t *filename);
+BUF *ReadDumpExW(wchar_t *filename, bool read_lock);
+BUF *CloneBuf(BUF *b);
+BUF *MemToBuf(void *data, UINT size);
+BUF *RandBuf(UINT size);
+BUF *ReadRemainBuf(BUF *b);
+bool CompareBuf(BUF *b1, BUF *b2);
+
+UINT PeekFifo(FIFO *f, void *p, UINT size);
+UINT ReadFifo(FIFO *f, void *p, UINT size);
+UCHAR *GetFifoPointer(FIFO *f);
+UCHAR *FifoPtr(FIFO *f);
+void WriteFifo(FIFO *f, void *p, UINT size);
+void ClearFifo(FIFO *f);
+UINT FifoSize(FIFO *f);
+void LockFifo(FIFO *f);
+void UnlockFifo(FIFO *f);
+void ReleaseFifo(FIFO *f);
+void CleanupFifo(FIFO *f);
+FIFO *NewFifo();
+FIFO *NewFifoFast();
+FIFO *NewFifoEx(UINT realloc_mem_size, bool fast);
+void InitFifo();
+UINT GetFifoDefaultReallocMemSize();
+void SetFifoDefaultReallocMemSize(UINT size);
+
+void *Search(LIST *o, void *target);
+void Sort(LIST *o);
+void SortEx(LIST *o, COMPARE *cmp);
+void Add(LIST *o, void *p);
+void AddDistinct(LIST *o, void *p);
+void Insert(LIST *o, void *p);
+void InsertDistinct(LIST *o, void *p);
+bool Delete(LIST *o, void *p);
+bool DeleteKey(LIST *o, UINT key);
+void DeleteAll(LIST *o);
+void LockList(LIST *o);
+void UnlockList(LIST *o);
+void ReleaseList(LIST *o);
+void CleanupList(LIST *o);
+LIST *NewList(COMPARE *cmp);
+LIST *NewListFast(COMPARE *cmp);
+LIST *NewListEx(COMPARE *cmp, bool fast);
+LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc);
+LIST *NewListSingle(void *p);
+void CopyToArray(LIST *o, void *p);
+void *ToArray(LIST *o);
+void *ToArrayEx(LIST *o, bool fast);
+LIST *CloneList(LIST *o);
+void SetCmp(LIST *o, COMPARE *cmp);
+void SetSortFlag(LIST *o, bool sorted);
+int CompareStr(void *p1, void *p2);
+bool InsertStr(LIST *o, char *str);
+int CompareUniStr(void *p1, void *p2);
+bool IsInList(LIST *o, void *p);
+bool IsInListKey(LIST *o, UINT key);
+void *ListKeyToPointer(LIST *o, UINT key);
+bool IsInListStr(LIST *o, char *str);
+bool IsInListUniStr(LIST *o, wchar_t *str);
+bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr);
+void AddInt(LIST *o, UINT i);
+void AddInt64(LIST *o, UINT64 i);
+void AddIntDistinct(LIST *o, UINT i);
+void AddInt64Distinct(LIST *o, UINT64 i);
+void DelInt(LIST *o, UINT i);
+void DelInt64(LIST *o, UINT64 i);
+void ReleaseIntList(LIST *o);
+void ReleaseInt64List(LIST *o);
+void DelAllInt(LIST *o);
+bool IsIntInList(LIST *o, UINT i);
+bool IsInt64InList(LIST *o, UINT64 i);
+LIST *NewIntList(bool sorted);
+LIST *NewInt64List(bool sorted);
+int CompareInt(void *p1, void *p2);
+int CompareInt64(void *p1, void *p2);
+void InsertInt(LIST *o, UINT i);
+void InsertInt64(LIST *o, UINT64 i);
+void InsertIntDistinct(LIST *o, UINT i);
+void InsertInt64Distinct(LIST *o, UINT64 i);
+
+void *GetNext(QUEUE *q);
+void *GetNextWithLock(QUEUE *q);
+void *PeekQueue(QUEUE *q);
+void InsertQueue(QUEUE *q, void *p);
+void InsertQueueWithLock(QUEUE *q, void *p);
+void InsertQueueInt(QUEUE *q, UINT value);
+void LockQueue(QUEUE *q);
+void UnlockQueue(QUEUE *q);
+void ReleaseQueue(QUEUE *q);
+void CleanupQueue(QUEUE *q);
+QUEUE *NewQueue();
+QUEUE *NewQueueFast();
+
+SK *NewSk();
+SK *NewSkEx(bool no_compact);
+void ReleaseSk(SK *s);
+void CleanupSk(SK *s);
+void LockSk(SK *s);
+void UnlockSk(SK *s);
+void Push(SK *s, void *p);
+void *Pop(SK *s);
+
+UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size);
+UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size);
+UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level);
+UINT CalcCompress(UINT src_size);
+BUF *CompressBuf(BUF *src_buf);
+BUF *UncompressBuf(BUF *src_buf);
+
+bool IsZero(void *data, UINT size);
+void FillBytes(void *data, UINT size, UCHAR c);
+
+LIST *NewStrMap();
+void *StrMapSearch(LIST *map, char *key);
+
+UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size);
+void CrashNow();
+UINT Power(UINT a, UINT b);
+
+void XorData(void *dst, void *src1, void *src2, UINT size);
+
+SHARED_BUFFER *NewSharedBuffer(void *data, UINT size);
+void ReleaseSharedBuffer(SHARED_BUFFER *b);
+void CleanupSharedBuffer(SHARED_BUFFER *b);
+
+void AppendBufUtf8(BUF *b, wchar_t *str);
+void AppendBufStr(BUF *b, char *str);
+
+#endif // MEMORY_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Microsoft.c b/src/Mayaqua/Microsoft.c
new file mode 100644
index 00000000..b03b826f
--- /dev/null
+++ b/src/Mayaqua/Microsoft.c
@@ -0,0 +1,14824 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Microsoft.c
+// For Microsoft Windows code
+// (not compiled on non-Windows environments)
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define MICROSOFT_C
+
+typedef enum _PNP_VETO_TYPE {
+ PNP_VetoTypeUnknown, // Name is unspecified
+ PNP_VetoLegacyDevice, // Name is an Instance Path
+ PNP_VetoPendingClose, // Name is an Instance Path
+ PNP_VetoWindowsApp, // Name is a Module
+ PNP_VetoWindowsService, // Name is a Service
+ PNP_VetoOutstandingOpen, // Name is an Instance Path
+ PNP_VetoDevice, // Name is an Instance Path
+ PNP_VetoDriver, // Name is a Driver Service Name
+ PNP_VetoIllegalDeviceRequest, // Name is an Instance Path
+ PNP_VetoInsufficientPower, // Name is unspecified
+ PNP_VetoNonDisableable, // Name is an Instance Path
+ PNP_VetoLegacyDriver, // Name is a Service
+ PNP_VetoInsufficientRights // Name is unspecified
+} PNP_VETO_TYPE, *PPNP_VETO_TYPE;
+
+#define _WIN32_IE 0x0600
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#define SECURITY_WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <Wintrust.h>
+#include <Softpub.h>
+#include <Iphlpapi.h>
+#include <ws2ipdef.h>
+#include <netioapi.h>
+#include <tlhelp32.h>
+#include <wincon.h>
+#include <Nb30.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <process.h>
+#include <psapi.h>
+#include <wtsapi32.h>
+#include <Ntsecapi.h>
+#include <security.h>
+#include <Msi.h>
+#include <Msiquery.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <cfgmgr32.h>
+#include <sddl.h>
+#include <Aclapi.h>
+
+static MS *ms = NULL;
+
+// Function prototype
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg);
+UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...);
+void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode);
+void CmTraffic(HWND hWnd);
+void CnStart();
+void InitCedar();
+void FreeCedar();
+void InitWinUi(wchar_t *software_name, char *font, UINT fontsize);
+void FreeWinUi();
+
+// Global variable
+UINT64 ms_uint64_1 = 0;
+
+// Adapter list related
+static LOCK *lock_adapter_list = NULL;
+static MS_ADAPTER_LIST *last_adapter_list = NULL;
+
+// Service related
+static SERVICE_STATUS_HANDLE ssh = NULL;
+static SERVICE_STATUS status = { 0 };
+static HANDLE service_stop_event = NULL;
+static BOOL (WINAPI *_StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY) = NULL;
+static SERVICE_STATUS_HANDLE (WINAPI *_RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION) = NULL;
+static BOOL (WINAPI *_SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS) = NULL;
+static char g_service_name[MAX_SIZE];
+static SERVICE_FUNCTION *g_start, *g_stop;
+static bool exiting = false;
+static bool wnd_end;
+static bool is_usermode = false;
+static HICON tray_icon;
+static NOTIFYICONDATA nid;
+static NOTIFYICONDATAW nid_nt;
+static bool service_for_9x_mode = false;
+static THREAD *service_stopper_thread = NULL;
+static bool tray_inited = false;
+static HWND hWndUsermode = NULL;
+static HANDLE hLsa = NULL;
+static ULONG lsa_package_id = 0;
+static TOKEN_SOURCE lsa_token_source;
+static LOCK *vlan_lock = NULL;
+
+// msi.dll
+static HINSTANCE hMsi = NULL;
+static UINT (WINAPI *_MsiGetProductInfoW)(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD) = NULL;
+static UINT (WINAPI *_MsiConfigureProductW)(LPCWSTR, int, INSTALLSTATE) = NULL;
+static INSTALLUILEVEL (WINAPI *_MsiSetInternalUI)(INSTALLUILEVEL, HWND *) = NULL;
+static INSTALLSTATE (WINAPI *_MsiLocateComponentW)(LPCWSTR, LPWSTR, LPDWORD) = NULL;
+
+#define SE_GROUP_INTEGRITY (0x00000020L)
+
+typedef enum _TOKEN_INFORMATION_CLASS_VISTA
+{
+ VistaTokenUser = 1,
+ VistaTokenGroups,
+ VistaTokenPrivileges,
+ VistaTokenOwner,
+ VistaTokenPrimaryGroup,
+ VistaTokenDefaultDacl,
+ VistaTokenSource,
+ VistaTokenType,
+ VistaTokenImpersonationLevel,
+ VistaTokenStatistics,
+ VistaTokenRestrictedSids,
+ VistaTokenSessionId,
+ VistaTokenGroupsAndPrivileges,
+ VistaTokenSessionReference,
+ VistaTokenSandBoxInert,
+ VistaTokenAuditPolicy,
+ VistaTokenOrigin,
+ VistaTokenElevationType,
+ VistaTokenLinkedToken,
+ VistaTokenElevation,
+ VistaTokenHasRestrictions,
+ VistaTokenAccessInformation,
+ VistaTokenVirtualizationAllowed,
+ VistaTokenVirtualizationEnabled,
+ VistaTokenIntegrityLevel,
+ VistaTokenUIAccess,
+ VistaTokenMandatoryPolicy,
+ VistaTokenLogonSid,
+ VistaMaxTokenInfoClass
+} TOKEN_INFORMATION_CLASS_VISTA, *PTOKEN_INFORMATION_CLASS_VISTA;
+
+typedef struct MS_MSCHAPV2_PARAMS
+{
+ wchar_t Username[MAX_SIZE];
+ wchar_t Workstation[MAX_SIZE];
+ wchar_t Domain[MAX_SIZE];
+ UCHAR ClientResponse24[24];
+ UCHAR ResponseBuffer[MAX_SIZE];
+} MS_MSCHAPV2_PARAMS;
+
+// Collect the information of the VPN software
+bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name)
+{
+ wchar_t *inst_dir;
+ char subkey[MAX_PATH];
+ bool ret = false;
+ wchar_t tmpdir_w[MAX_PATH];
+ // Validate arguments
+ if (bat == NULL || tmpdir == NULL || svc_name == NULL || config_name == NULL || logdir_name == NULL)
+ {
+ return false;
+ }
+
+ StrToUni(tmpdir_w, sizeof(tmpdir_w), tmpdir);
+
+ Format(subkey, sizeof(subkey), "SOFTWARE\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings\\%s", svc_name);
+ inst_dir = MsRegReadStrEx2W(REG_LOCAL_MACHINE, subkey, "InstalledDir", false, true);
+ if (UniIsEmptyStr(inst_dir) == false)
+ {
+ wchar_t config_src[MAX_PATH];
+ wchar_t config_dst[MAX_PATH];
+ wchar_t log_dir[MAX_PATH];
+ DIRLIST *dir;
+ UINT64 max_dt_file = 0;
+
+ // config file
+ CombinePathW(config_src, sizeof(config_src), inst_dir, config_name);
+ UniFormat(config_dst, sizeof(config_dst), L"%s\\%S_%s", tmpdir_w, svc_name, config_name);
+ ret = FileCopyExW(config_src, config_dst, false);
+
+ // Log file
+ CombinePathW(log_dir, sizeof(log_dir), inst_dir, logdir_name);
+
+ dir = EnumDirW(log_dir);
+
+ if (dir != NULL)
+ {
+ UINT i;
+ DIRENT *latest_log = NULL;
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ // Get the most recent file
+ if (max_dt_file <= e->UpdateDate)
+ {
+ max_dt_file = e->UpdateDate;
+
+ latest_log = e;
+ }
+ }
+
+ if (latest_log != NULL)
+ {
+ wchar_t fullpath[MAX_SIZE];
+ IO *f;
+
+ // Open the log file
+ CombinePathW(fullpath, sizeof(fullpath), log_dir, latest_log->FileNameW);
+ f = FileOpenExW(fullpath, false, false);
+
+ if (f != NULL)
+ {
+ UINT size = FileSize(f);
+
+ if (size >= 1)
+ {
+ UINT copy_size = 1024 * 1024;
+ UINT seek_size = 0;
+ UCHAR *buf;
+
+ if (copy_size < size)
+ {
+ seek_size = size - copy_size;
+ }
+ else
+ {
+ copy_size = size;
+ }
+
+ FileSeek(f, 0, seek_size);
+
+ buf = Malloc(copy_size + 3);
+ buf[0] = 0xEF;
+ buf[1] = 0xBB;
+ buf[2] = 0xBF;
+ if (FileRead(f, buf + 3, copy_size))
+ {
+ char log_dst_filename[MAX_PATH];
+
+ Format(log_dst_filename, sizeof(log_dst_filename), "%s\\lastlog_%s_%s",
+ tmpdir, svc_name, latest_log->FileName);
+
+ SaveFile(log_dst_filename, buf, copy_size + 3);
+ }
+
+ Free(buf);
+ }
+
+ FileClose(f);
+ }
+ }
+
+ FreeDir(dir);
+ }
+ }
+ Free(inst_dir);
+
+ return ret;
+}
+
+// Save the system information
+bool MsSaveSystemInfo(wchar_t *dst_filename)
+{
+ char tmpdir[MAX_PATH];
+ UCHAR rand_data[SHA1_SIZE];
+ char rand_str[MAX_SIZE];
+ char filename_bat[MAX_PATH];
+ BUF *bat;
+ char tmp[MAX_PATH];
+ char cmd[MAX_PATH];
+ char cmd_arg[MAX_PATH];
+ bool ret = false;
+ DIRLIST *dir;
+ UINT i;
+ // Validate arguments
+ if (dst_filename == NULL)
+ {
+ return false;
+ }
+ if (MsIsAdmin() == false || MsIsWin2000OrGreater() == false)
+ {
+ return false;
+ }
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, 4);
+
+ // Create a temporary directory
+ Format(tmpdir, sizeof(tmpdir), "%s\\Temp\\se_support_%s", MsGetWindowsDir(), rand_str);
+ MakeDirEx(tmpdir);
+
+ // Create a batch file
+ CombinePath(filename_bat, sizeof(filename_bat), tmpdir, "make_system_info.cmd");
+ bat = NewBuf();
+
+ Format(tmp, sizeof(tmp), "systeminfo > %s\\SystemInfo.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "ipconfig > %s\\ipconfig.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netsh dump > %s\\netsh.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "route print > %s\\route.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -nab > %s\\netstat_nab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -nao > %s\\netstat_nao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -na > %s\\netstat_na.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fab > %s\\netstat_fab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fao > %s\\netstat_fao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fa > %s\\netstat_fa.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -ab > %s\\netstat_ab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -ao > %s\\netstat_ao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -a > %s\\netstat_a.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "\"%s\\Common Files\\Microsoft Shared\\MSInfo\\msinfo32.exe\" /report %s\\SystemInfo.txt", MsGetProgramFilesDir(), tmpdir);
+ WriteBufLine(bat, tmp);
+
+ // Collect the information of the VPN software
+ MsCollectVpnInfo(bat, tmpdir, "vpnclient", L"vpn_client.config", L"client_log");
+ MsCollectVpnInfo(bat, tmpdir, "vpnserver", L"vpn_server.config", L"server_log");
+ MsCollectVpnInfo(bat, tmpdir, "vpnbridge", L"vpn_bridge.config", L"server_log");
+
+ MsCollectVpnInfo(bat, tmpdir, "sevpnclient", L"vpn_client.config", L"client_log");
+ MsCollectVpnInfo(bat, tmpdir, "sevpnserver", L"vpn_server.config", L"server_log");
+ MsCollectVpnInfo(bat, tmpdir, "sevpnbridge", L"vpn_bridge.config", L"server_log");
+
+ WriteBufLine(bat, "");
+
+ DumpBuf(bat, filename_bat);
+
+ FreeBuf(bat);
+
+ // Run the batch file
+ CombinePath(cmd, sizeof(cmd), MsGetSystem32Dir(), "cmd.exe");
+ Format(cmd_arg, sizeof(cmd_arg), "/C %s", filename_bat);
+ if (Win32Run(cmd, cmd_arg, false, true))
+ {
+ dir = EnumDir(tmpdir);
+ if (dir != NULL)
+ {
+ ZIP_PACKER *zip;
+ zip = NewZipPacker();
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ char *name = dir->File[i]->FileName;
+ char full[MAX_PATH];
+
+ CombinePath(full, sizeof(full), tmpdir, name);
+
+ ZipAddRealFile(zip, name, SystemTime64(), 0, full);
+ }
+ FreeDir(dir);
+
+ ret = ZipWriteW(zip, dst_filename);
+ FreeZipPacker(zip);
+ }
+ }
+
+ // Delete the temporary directory
+ dir = EnumDir(tmpdir);
+ if (dir != NULL)
+ {
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ char *name = dir->File[i]->FileName;
+ char full[MAX_PATH];
+
+ CombinePath(full, sizeof(full), tmpdir, name);
+
+ if (EndWith(full, ".txt") || EndWith(full, ".cmd") || EndWith(full, ".config") || EndWith(full, ".log"))
+ {
+ FileDelete(full);
+ }
+ }
+ FreeDir(dir);
+ }
+ DeleteDir(tmpdir);
+
+ return ret;
+}
+
+// Determine whether this is running in a VM
+bool MsIsInVmMain()
+{
+ char *bat_data = "On Error Resume Next\r\n\r\nDim str\r\n\r\nSet wmi_svc = GetObject(\"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2\")\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_BaseBoard\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_ComputerSystem\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet wmi_svc = Nothing\r\n\r\nstr = LCase(str)\r\n\r\nDim ret\r\n\r\nret = 0\r\n\r\nif InStr(str, \"microsoft corporation\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"vmware\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualbox\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualpc\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xen\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"hvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"domu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"kvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"oracle vm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"qemu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"parallels\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtual\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"bochs\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nwscript.quit ret\r\n\r\n";
+ wchar_t bat_filename[MAX_SIZE];
+ wchar_t cscript_exe[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ void *process;
+ bool ret = false;
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (MsIsWin2000OrGreater() == false)
+ {
+ return false;
+ }
+
+ CombinePathW(bat_filename, sizeof(bat_filename), MsGetMyTempDirW(), L"detectvm.vbs");
+
+ if (DumpDataW(bat_data, StrLen(bat_data), bat_filename) == false)
+ {
+ return false;
+ }
+
+ CombinePathW(cscript_exe, sizeof(cscript_exe), MsGetSystem32DirW(), L"cscript.exe");
+
+ UniFormat(tmp, sizeof(tmp), L"\"%s\"", bat_filename);
+
+ process = Win32RunEx3W(cscript_exe, tmp, true, NULL, true);
+
+ if (process == NULL)
+ {
+ return false;
+ }
+
+ if (Win32WaitProcess(process, 30000))
+ {
+ DWORD exit_code = 0;
+
+ if (GetExitCodeProcess(process, &exit_code))
+ {
+ if (exit_code == 1)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Win32CloseProcess(process);
+
+ return ret;
+}
+bool MsIsInVm()
+{
+ static bool flag_detected = false;
+ static bool flag_is_vm = false;
+
+ if (flag_detected == false)
+ {
+ flag_is_vm = MsIsInVmMain();
+
+ flag_detected = true;
+ }
+
+ return flag_is_vm;
+}
+
+// Get the current module handle
+void *MsGetCurrentModuleHandle()
+{
+ return ms->hInst;
+}
+
+// Resource enumeration procedure
+bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam)
+{
+ LIST *o = (LIST *)lParam;
+ // Validate arguments
+ if (type == NULL || name == NULL || o == NULL)
+ {
+ return true;
+ }
+
+ Add(o, CopyStr(name));
+
+ return true;
+}
+
+// Enumeration of resources
+TOKEN_LIST *MsEnumResources(void *hModule, char *type)
+{
+ LIST *o;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (hModule == NULL)
+ {
+ hModule = MsGetCurrentModuleHandle();
+ }
+ if (type == NULL)
+ {
+ return NullToken();
+ }
+
+ o = NewListFast(NULL);
+
+ if (EnumResourceNamesA(hModule, type, MsEnumResourcesInternalProc, (LONG_PTR)o) == false)
+ {
+ ReleaseList(o);
+ return NullToken();
+ }
+
+ ret = ListToTokenList(o);
+
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Get whether the locale ID of the current user is Japanese
+bool MsIsCurrentUserLocaleIdJapanese()
+{
+ UINT lcid = MsGetUserLocaleId();
+
+ if (lcid == 1041)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the locale ID of the user
+UINT MsGetUserLocaleId()
+{
+ static UINT lcid_cache = 0;
+
+ if (lcid_cache == 0)
+ {
+ lcid_cache = (UINT)GetUserDefaultLCID();
+ }
+
+ return lcid_cache;
+}
+
+// Get the locale ID of the system
+UINT MsGetSystemLocaleId()
+{
+ static UINT lcid_cache = 0;
+
+ if (lcid_cache == 0)
+ {
+ lcid_cache = (UINT)GetSystemDefaultLCID();
+ }
+
+ return lcid_cache;
+}
+
+// Set a secure ACL to the specified file or directory
+bool MsSetFileSecureAcl(wchar_t *path)
+{
+ SID *sid_system;
+ SID *sid_admin;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+ if (ms->nt == NULL)
+ {
+ return false;
+ }
+ if (ms->nt->SetNamedSecurityInfoW == NULL || ms->nt->AddAccessAllowedAceEx == NULL)
+ {
+ return false;
+ }
+
+ sid_system = MsGetSidFromAccountName("SYSTEM");
+ sid_admin = MsGetSidFromAccountName("Administrators");
+
+ if (sid_system != NULL && sid_admin != NULL)
+ {
+ UINT acl_size = 4096;
+ ACL *acl;
+
+ acl = ZeroMalloc(acl_size);
+
+ if (InitializeAcl(acl, acl_size, 2))
+ {
+ if (ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_system) &&
+ ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_admin))
+ {
+ if (ms->nt->SetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) == ERROR_SUCCESS)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Free(acl);
+ }
+
+ MsFreeSid(sid_system);
+ MsFreeSid(sid_admin);
+
+ return ret;
+}
+
+// Disable the minimization function of the number of network connections by WCM
+void MsDisableWcmNetworkMinimize()
+{
+ MS_WCM_POLICY_VALUE v;
+ bool b;
+ if (ms->nt == NULL)
+ {
+ return;
+ }
+ if (ms->nt->WcmQueryProperty == NULL || ms->nt->WcmSetProperty == NULL || ms->nt->WcmFreeMemory == NULL || ms->nt->WcmGetProfileList == NULL)
+ {
+ return;
+ }
+
+ if (MsIsWindows8() == false)
+ {
+ return;
+ }
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = true;
+ v.fValue = false;
+ b = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = true;
+ v.fValue = false;
+ b = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = false;
+ v.fValue = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = false;
+ v.fValue = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
+}
+
+// Request the MS-CHAPv2 authentication to the LSA
+bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash)
+{
+ bool ret = false;
+ char user[MAX_SIZE];
+ char domain[MAX_SIZE];
+ wchar_t workstation[MAX_SIZE + 1];
+ LSA_STRING origin;
+ MSV1_0_LM20_LOGON *m;
+ MS_MSCHAPV2_PARAMS *p;
+ UINT m_size;
+ DWORD sz;
+ void *profile_buffer = NULL;
+ LUID logon_id;
+ UINT profile_buffer_size = 0;
+ UINT i;
+ HANDLE hLogon = NULL;
+ QUOTA_LIMITS q;
+ char *origin_str = "SE-VPN";
+ NTSTATUS sub_status = 0;
+ // Validate arguments
+ if (username == NULL || challenge8 == NULL || client_response_24 == NULL || ret_pw_hash_hash == NULL)
+ {
+ return false;
+ }
+ if (hLsa == NULL)
+ {
+ return false;
+ }
+
+ ParseNtUsername(username, user, sizeof(user), domain, sizeof(domain), false);
+
+ // Get the machine name
+ Zero(workstation, sizeof(workstation));
+ sz = MAX_SIZE;
+ GetComputerNameW(workstation, &sz);
+
+ // Build a MSV1_0_INTERACTIVE_LOGON
+ m_size = sizeof(MSV1_0_LM20_LOGON) + sizeof(MS_MSCHAPV2_PARAMS);
+ m = ZeroMalloc(m_size);
+ p = (MS_MSCHAPV2_PARAMS *)(((UCHAR *)m) + sizeof(MSV1_0_LM20_LOGON));
+
+ StrToUni(p->Username, sizeof(p->Username), user);
+ StrToUni(p->Domain, sizeof(p->Domain), domain);
+ UniStrCpy(p->Workstation, sizeof(p->Workstation), workstation);
+ Copy(p->ClientResponse24, client_response_24, 24);
+
+ m->MessageType = MsV1_0Lm20Logon;
+
+ // User name
+ m->UserName.Length = m->UserName.MaximumLength = (USHORT)(UniStrLen(p->Username) * sizeof(wchar_t));
+ m->UserName.Buffer = p->Username;
+
+ // Workstation name
+ m->Workstation.Length = m->Workstation.MaximumLength = (USHORT)(UniStrLen(p->Workstation) * sizeof(wchar_t));
+ m->Workstation.Buffer = p->Workstation;
+
+ // Domain name
+ if (IsEmptyUniStr(p->Domain) == false)
+ {
+ m->LogonDomainName.Length = m->LogonDomainName.MaximumLength = (USHORT)(UniStrLen(p->Domain) * sizeof(wchar_t));
+ m->LogonDomainName.Buffer = p->Domain;
+ }
+
+ // Challenge
+ Copy(m->ChallengeToClient, challenge8, 8);
+
+ // Response
+ m->CaseInsensitiveChallengeResponse.Length = m->CaseInsensitiveChallengeResponse.MaximumLength = 24;
+ m->CaseInsensitiveChallengeResponse.Buffer = p->ClientResponse24;
+
+ m->CaseSensitiveChallengeResponse.Length = m->CaseSensitiveChallengeResponse.MaximumLength = sizeof(p->ResponseBuffer);
+ m->CaseSensitiveChallengeResponse.Buffer = p->ResponseBuffer;
+
+ m->ParameterControl = MSV1_0_ALLOW_MSVCHAPV2;
+
+ Zero(&origin, sizeof(origin));
+ origin.Length = origin.MaximumLength = StrLen(origin_str);
+ origin.Buffer = origin_str;
+
+ Zero(&logon_id, sizeof(logon_id));
+ Zero(&q, sizeof(q));
+
+ i = ms->nt->LsaLogonUser(hLsa, &origin, Network, lsa_package_id, m, m_size, NULL, &lsa_token_source,
+ &profile_buffer, &profile_buffer_size, &logon_id, &hLogon, &q, &sub_status);
+
+ if (i == 0)
+ {
+ if (profile_buffer != NULL)
+ {
+ MSV1_0_LM20_LOGON_PROFILE *response = (MSV1_0_LM20_LOGON_PROFILE *)profile_buffer;
+
+ Copy(ret_pw_hash_hash, response->UserSessionKey, 16);
+
+ ret = true;
+
+ ms->nt->LsaFreeReturnBuffer(profile_buffer);
+ }
+ CloseHandle(hLogon);
+ }
+
+ Free(m);
+
+ return ret;
+}
+
+// Send a pulse
+void MsSendGlobalPulse(void *p)
+{
+ HANDLE h;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ h = (HANDLE)p;
+
+ PulseEvent(h);
+}
+
+// Release a pulse
+void MsCloseGlobalPulse(void *p)
+{
+ HANDLE h;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ h = (HANDLE)p;
+
+ CloseHandle(h);
+}
+
+// Wait for arriving the pulse
+bool MsWaitForGlobalPulse(void *p, UINT timeout)
+{
+ HANDLE h;
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+ if (timeout == TIMEOUT_INFINITE)
+ {
+ timeout = INFINITE;
+ }
+
+ h = (HANDLE)p;
+
+ ret = WaitForSingleObject(h, timeout);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Open or create a pulse
+void *MsOpenOrCreateGlobalPulse(char *name)
+{
+ UCHAR hash[20];
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ HashSha1(hash, name, StrLen(name));
+
+ BinToStr(tmp, sizeof(tmp), hash, sizeof(hash));
+
+ Format(tmp2, sizeof(tmp2), "GlobalPulse_%s", tmp);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ Format(tmp2, sizeof(tmp2), "Global\\GlobalPulse_%s", tmp);
+ }
+ }
+
+ h = CreateEvent(NULL, true, false, tmp2);
+
+ return (void *)h;
+}
+
+// Stop the IPsec service
+bool MsStopIPsecService()
+{
+ if (MsIsServiceRunning(MsGetIPsecServiceName()))
+ {
+ Debug("Stopping Windows Service: %s\n", MsGetIPsecServiceName());
+ if (MsStopService(MsGetIPsecServiceName()))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Start the IPsec service
+bool MsStartIPsecService()
+{
+ if (MsIsServiceRunning(MsGetIPsecServiceName()) == false)
+ {
+ Debug("Starting Windows Service: %s\n", MsGetIPsecServiceName());
+ return MsStartService(MsGetIPsecServiceName());
+ }
+
+ return false;
+}
+
+// Get the IPsec service name
+char *MsGetIPsecServiceName()
+{
+ char *svc_name = "PolicyAgent";
+
+ if (MsIsVista())
+ {
+ svc_name = "ikeext";
+ }
+
+ return svc_name;
+}
+
+// Initialize the global lock
+void *MsInitGlobalLock(char *name, bool ts_local)
+{
+ char tmp[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ name = "default_global_lock";
+ }
+
+ if (ts_local)
+ {
+ HashInstanceNameLocal(tmp, sizeof(tmp), name);
+ }
+ else
+ {
+ HashInstanceName(tmp, sizeof(tmp), name);
+ }
+
+ h = CreateMutexA(NULL, false, tmp);
+ if (h == NULL || h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ return (void *)h;
+}
+
+// Get a global lock
+void MsGlobalLock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ WaitForSingleObject(p, INFINITE);
+}
+
+// Unlock the global lock
+void MsGlobalUnlock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ ReleaseMutex(h);
+}
+
+// Release the global lock
+void MsFreeGlobalLock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(h);
+}
+
+
+// Set the mode not to show the errors
+void MsSetErrorModeToSilent()
+{
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+}
+
+// Get the file information
+bool MsGetFileInformation(void *h, void *info)
+{
+ // Validate arguments
+ if (h == INVALID_HANDLE_VALUE || info == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->GetFileInformationByHandle == NULL)
+ {
+ return false;
+ }
+
+ return ms->nt->GetFileInformationByHandle(h, info);
+}
+
+// Set the shutdown parameters of the process
+void MsSetShutdownParameters(UINT level, UINT flag)
+{
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ if (ms->nt == false || ms->nt->SetProcessShutdownParameters == NULL)
+ {
+ return;
+ }
+
+ ms->nt->SetProcessShutdownParameters(level, flag);
+}
+
+// Get whether the version of the OS is Windows XP or Windows Vista or later
+bool MsIsWinXPOrWinVista()
+{
+ OS_INFO *info = GetOsInfo();
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 3)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Write to the event log
+bool MsWriteEventLog(void *p, UINT type, wchar_t *str)
+{
+ MS_EVENTLOG *g = (MS_EVENTLOG *)p;
+ wchar_t *strings[2];
+ UINT id = 0;
+ UINT typeapi = 0;
+ // Validate arguments
+ if (g == NULL || type >= 5 || str == NULL)
+ {
+ return false;
+ }
+
+ strings[0] = str;
+
+ switch (type)
+ {
+ case MS_EVENTLOG_TYPE_INFORMATION:
+ id = MS_RC_EVENTLOG_TYPE_INFORMATION;
+ typeapi = EVENTLOG_INFORMATION_TYPE;
+ break;
+
+ case MS_EVENTLOG_TYPE_WARNING:
+ id = MS_RC_EVENTLOG_TYPE_WARNING;
+ typeapi = EVENTLOG_WARNING_TYPE;
+ break;
+
+ case MS_EVENTLOG_TYPE_ERROR:
+ id = MS_RC_EVENTLOG_TYPE_ERROR;
+ typeapi = EVENTLOG_ERROR_TYPE;
+ break;
+ }
+
+ return ms->nt->ReportEventW(g->hEventLog, typeapi, 0, id, NULL, 1, 0, strings, NULL);
+}
+
+// Release of the event log
+void MsFreeEventLog(void *p)
+{
+ MS_EVENTLOG *g = (MS_EVENTLOG *)p;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ ms->nt->DeregisterEventSource(g->hEventLog);
+
+ Free(g);
+}
+
+// Initialization of the event log
+void *MsInitEventLog(wchar_t *src_name)
+{
+ MS_EVENTLOG *g;
+ HANDLE h;
+ wchar_t keyname[MAX_PATH];
+ char keyname_a[MAX_PATH];
+ wchar_t *exename;
+ // Validate arguments
+ if (src_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Write the key to the registry
+ exename = MsGetExeFileNameW();
+ UniFormat(keyname, sizeof(keyname),
+ L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s",
+ src_name);
+ UniToStr(keyname_a, sizeof(keyname_a), keyname);
+
+ MsRegWriteStrExpandExW(REG_LOCAL_MACHINE, keyname_a, "EventMessageFile",
+ exename, false);
+
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, keyname_a, "TypesSupported", 7, false);
+
+ h = ms->nt->RegisterEventSourceW(NULL, src_name);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ g = ZeroMalloc(sizeof(MS_EVENTLOG));
+
+ g->hEventLog = h;
+
+ return (void *)g;
+}
+
+// Empty the clipboard
+void MsDeleteClipboard()
+{
+ OpenClipboard(NULL);
+
+ EmptyClipboard();
+
+ CloseClipboard();
+}
+
+// Get the process ID of the clipboard owner
+UINT MsGetClipboardOwnerProcessId()
+{
+ HWND hWnd = GetClipboardOwner();
+ DWORD pid = 0;
+
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ GetWindowThreadProcessId(hWnd, &pid);
+
+ return pid;
+}
+
+// Restart of MMCSS
+void MsRestartMMCSS()
+{
+ MsStopService("CTAudSvcService");
+ MsStopService("audiosrv");
+ MsStopService("MMCSS");
+ MsStartService("MMCSS");
+ MsStartService("audiosrv");
+ MsStartService("CTAudSvcService");
+}
+
+// Enable / disable network throttling by MMCSS
+void MsSetMMCSSNetworkThrottlingEnable(bool enable)
+{
+ UINT value;
+ if (MsIsVista() == false)
+ {
+ return;
+ }
+
+ if (enable)
+ {
+ value = 0x0000000a;
+ }
+ else
+ {
+ value = 0xffffffff;
+ }
+
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, "NetworkThrottlingIndex",
+ value,
+ false, true);
+
+ MsRestartMMCSS();
+}
+
+// Examine whether the Network throttling by MMCSS is enabled
+bool MsIsMMCSSNetworkThrottlingEnabled()
+{
+ UINT value;
+ if (MsIsVista() == false)
+ {
+ return false;
+ }
+
+ if (MsRegIsKeyEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, false, true) == false)
+ {
+ return false;
+ }
+
+ value = MsRegReadIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME,
+ "NetworkThrottlingIndex", false, true);
+
+ if (value == 0)
+ {
+ return false;
+ }
+
+ if (value == 0x0000000a)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Delete all the subkeys
+void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return;
+ }
+
+ t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char tmp[MAX_PATH];
+
+ Format(tmp, sizeof(tmp), "%s\\%s", keyname, t->Token[i]);
+
+ MsRegDeleteKeyEx2(root, tmp, force32bit, force64bit);
+ }
+
+ FreeToken(t);
+}
+
+// Convert the data in the buffer to the subkey of the registry
+void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit)
+{
+ UINT i;
+ UINT a;
+ UINT num_keys;
+ // Validate arguments
+ if (keyname == NULL || b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ num_keys = ReadBufInt(b);
+
+ for (i = 0;i < num_keys;i++)
+ {
+ char subkeyname[MAX_PATH];
+ char fullkeyname[MAX_PATH];
+ UINT j;
+ UINT num_values;
+
+ Zero(subkeyname, sizeof(subkeyname));
+ ReadBufStr(b, subkeyname, sizeof(subkeyname));
+
+ Format(fullkeyname, sizeof(fullkeyname), "%s\\%s", keyname, subkeyname);
+
+ num_values = ReadBufInt(b);
+
+ for (j = 0;j < num_values;j++)
+ {
+ char valuename[MAX_PATH];
+ char data[MAX_SIZE];
+
+ Zero(valuename, sizeof(valuename));
+ ReadBufStr(b, valuename, sizeof(valuename));
+
+ a = ReadBufInt(b);
+
+ if (a == 0)
+ {
+ Zero(data, sizeof(data));
+ ReadBufStr(b, data, sizeof(data));
+
+ if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
+ {
+ MsRegWriteStrEx2(root, fullkeyname, valuename, data, force32bit, force64bit);
+ }
+ }
+ else
+ {
+ if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
+ {
+ MsRegWriteIntEx2(root, fullkeyname, valuename, ReadBufInt(b), force32bit, force64bit);
+ }
+ }
+ }
+ }
+}
+
+// Convert data in the registry subkey to the buffer
+BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ BUF *b;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return NULL;
+ }
+
+ t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
+
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ WriteBufInt(b, t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ char tmp[MAX_PATH];
+ TOKEN_LIST *v;
+
+ Format(tmp, sizeof(tmp), "%s\\%s", keyname, name);
+
+ WriteBufStr(b, name);
+
+ v = MsRegEnumValueEx2(root, tmp, force32bit, force64bit);
+ if (v == NULL)
+ {
+ WriteBufInt(b, 0);
+ }
+ else
+ {
+ UINT j;
+
+ WriteBufInt(b, v->NumTokens);
+
+ for (j = 0;j < v->NumTokens;j++)
+ {
+ char *valuename = v->Token[j];
+ char *str;
+
+ WriteBufStr(b, valuename);
+
+ str = MsRegReadStrEx2(root, tmp, valuename, force32bit, force64bit);
+ if (str != NULL)
+ {
+ WriteBufInt(b, 0);
+ WriteBufStr(b, str);
+ Free(str);
+ }
+ else
+ {
+ WriteBufInt(b, 1);
+ WriteBufInt(b, MsRegReadIntEx2(root, tmp, valuename, force32bit, force64bit));
+ }
+ }
+
+ FreeToken(v);
+ }
+ }
+
+ FreeToken(t);
+
+ return b;
+}
+
+// Check whether the process of specified EXE file name exists
+bool MsIsProcessExists(char *exename)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (exename == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *proc = LIST_DATA(o, i);
+ char exe[MAX_PATH];
+
+ GetFileNameFromFilePath(exe, sizeof(exe), proc->ExeFilename);
+
+ if (StrCmpi(exename, exe) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+bool MsIsProcessExistsW(wchar_t *exename)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (exename == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *proc = LIST_DATA(o, i);
+ wchar_t exe[MAX_PATH];
+
+ GetFileNameFromFilePathW(exe, sizeof(exe), proc->ExeFilenameW);
+
+ if (UniStrCmpi(exename, exe) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+
+typedef struct _ASTAT_
+{
+ ADAPTER_STATUS adapt;
+ NAME_BUFFER NameBuff[30];
+} ASTAT, *PASTAT;
+
+// Get the precise time from the value of the high-resolution counter
+double MsGetHiResTimeSpan(UINT64 diff)
+{
+ LARGE_INTEGER t;
+ UINT64 freq;
+
+ if (QueryPerformanceFrequency(&t) == false)
+ {
+ freq = 1000ULL;
+ }
+ else
+ {
+ Copy(&freq, &t, sizeof(UINT64));
+ }
+
+ return (double)diff / (double)freq;
+}
+UINT64 MsGetHiResTimeSpanUSec(UINT64 diff)
+{
+ LARGE_INTEGER t;
+ UINT64 freq;
+
+ if (QueryPerformanceFrequency(&t) == false)
+ {
+ freq = 1000ULL;
+ }
+ else
+ {
+ Copy(&freq, &t, sizeof(UINT64));
+ }
+
+ return (UINT64)(diff) * 1000ULL * 1000ULL / (UINT64)freq;
+}
+
+// Get a high-resolution counter
+UINT64 MsGetHiResCounter()
+{
+ LARGE_INTEGER t;
+ UINT64 ret;
+
+ if (QueryPerformanceCounter(&t) == false)
+ {
+ return Tick64();
+ }
+
+ Copy(&ret, &t, sizeof(UINT64));
+
+ return ret;
+}
+
+// Whether the Welcome screen is used
+bool MsIsUseWelcomeLogin()
+{
+ UINT os_type;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ os_type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS_NT(os_type))
+ {
+ if (GET_KETA(os_type, 100) == 3)
+ {
+ if (MsRegReadIntEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
+ "LogonType", false, true) == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Get a physical MAC address of the computer
+bool MsGetPhysicalMacAddress(void *address)
+{
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ if (MsGetPhysicalMacAddressFromApi(address))
+ {
+ return true;
+ }
+
+ if (MsGetPhysicalMacAddressFromNetbios(address))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the physical MAC address (from API)
+bool MsGetPhysicalMacAddressFromApi(void *address)
+{
+ MS_ADAPTER_LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ Zero(address, 6);
+
+ o = MsCreateAdapterList();
+
+ for (i = 0;i < o->Num;i++)
+ {
+ MS_ADAPTER *a = o->Adapters[i];
+
+ if (a->AddressSize == 6 && a->Mtu == 1500)
+ {
+ bool b = false;
+ switch (a->Type)
+ {
+ case MIB_IF_TYPE_OTHER:
+ case MIB_IF_TYPE_ETHERNET:
+ b = true;
+ break;
+
+ case MIB_IF_TYPE_TOKENRING:
+ case MIB_IF_TYPE_FDDI:
+ case MIB_IF_TYPE_PPP:
+ case MIB_IF_TYPE_LOOPBACK:
+ case MIB_IF_TYPE_SLIP:
+ b = false;
+ break;
+
+ default:
+ b = true;
+ break;
+ }
+
+ if (b)
+ {
+ if (SearchStrEx(a->Title, "WAN", 0, false) == INFINITE)
+ {
+ if (a->Status == MIB_IF_OPER_STATUS_CONNECTED || a->Status == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ if (a->AddressSize == 6)
+ {
+ if (IsZero(a->Address, 6) == false)
+ {
+ if (Cmp(address, a->Address, 6) <= 0)
+ {
+ Copy(address, a->Address, 6);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+
+// Get the physical MAC address (from NetBIOS)
+bool MsGetPhysicalMacAddressFromNetbios(void *address)
+{
+ NCB ncb;
+ UCHAR ret;
+ LANA_ENUM lenum;
+ UINT i;
+ ASTAT adapter;
+ bool b = false;
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ncb, sizeof(ncb));
+ Zero(&lenum, sizeof(lenum));
+
+ ncb.ncb_command = NCBENUM;
+ ncb.ncb_buffer = (UCHAR *)&lenum;
+ ncb.ncb_length = sizeof(lenum);
+ ret = Netbios(&ncb);
+
+ Zero(address, 6);
+
+ for (i = 0;i < lenum.length;i++)
+ {
+ Zero(&ncb, sizeof(ncb));
+ ncb.ncb_command = NCBRESET;
+ ncb.ncb_lana_num = lenum.lana[i];
+
+ ret = Netbios(&ncb);
+
+ Zero(&ncb, sizeof(ncb));
+ ncb.ncb_command = NCBASTAT;
+ ncb.ncb_lana_num = lenum.lana[i];
+
+ StrCpy(ncb.ncb_callname, sizeof(ncb.ncb_callname), "* ");
+ Zero(&adapter, sizeof(adapter));
+ ncb.ncb_buffer = (char *)&adapter;
+ ncb.ncb_length = sizeof(adapter);
+
+ ret = Netbios(&ncb);
+
+ if (ret == 0)
+ {
+ if (Cmp(address, adapter.adapt.adapter_address, 6) <= 0)
+ {
+ Copy(address, adapter.adapt.adapter_address, 6);
+ b = true;
+ }
+ }
+ }
+
+ return b;
+}
+
+// System-wide updating notification
+void MsUpdateSystem()
+{
+ static DWORD dw = 0;
+
+ SendMessageTimeoutA(HWND_BROADCAST, WM_WININICHANGE, 0, 0, SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
+ SleepThread(25);
+ SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+}
+
+// Get whether the specified path points to a local drive
+bool MsIsLocalDrive(char *name)
+{
+ char tmp[MAX_PATH];
+ UINT ret;
+
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ if (StartWith(tmp, "\\\\"))
+ {
+ // Network directory
+ return false;
+ }
+
+ if (tmp[1] != ':' || tmp[2] != '\\')
+ {
+ // Not a drive letter
+ return false;
+ }
+
+ tmp[3] = 0;
+
+ ret = GetDriveType(tmp);
+
+ if (ret == DRIVE_REMOTE || ret == DRIVE_CDROM || ret == DRIVE_RAMDISK)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsIsLocalDriveW(wchar_t *name)
+{
+ char name_a[MAX_PATH];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsIsLocalDrive(name_a);
+}
+
+// Get whether the specified file is locked
+bool MsIsFileLocked(char *name)
+{
+ HANDLE h;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return true;
+ }
+
+ CloseHandle(h);
+
+ return false;
+}
+bool MsIsFileLockedW(wchar_t *name)
+{
+ HANDLE h;
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_SIZE];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsIsFileLocked(name_a);
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return true;
+ }
+
+ CloseHandle(h);
+
+ return false;
+}
+
+// Wait for the process termination
+UINT MsWaitProcessExit(void *process_handle)
+{
+ HANDLE h = (HANDLE)process_handle;
+ UINT ret = 1;
+
+ if (h == NULL)
+ {
+ return 1;
+ }
+
+ while (true)
+ {
+ WaitForSingleObject(h, INFINITE);
+
+ ret = 1;
+ if (GetExitCodeProcess(h, &ret) == false)
+ {
+ break;
+ }
+
+ if (ret != STILL_ACTIVE)
+ {
+ break;
+ }
+ }
+
+ CloseHandle(h);
+
+ return ret;
+}
+
+// Execution of the file (to get process handle)
+bool MsExecuteEx(char *exe, char *arg, void **process_handle)
+{
+ return MsExecuteEx2(exe, arg, process_handle, false);
+}
+bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas)
+{
+ SHELLEXECUTEINFO info;
+ HANDLE h;
+ // Validate arguments
+ if (exe == NULL || process_handle == NULL)
+ {
+ return false;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = (runas ? "runas" : "open");
+ info.lpFile = exe;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteEx(&info) == false)
+ {
+ return false;
+ }
+
+ h = info.hProcess;
+
+ *process_handle = (void *)h;
+
+ return true;
+}
+bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle)
+{
+ return MsExecuteEx2W(exe, arg, process_handle, false);
+}
+bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas)
+{
+ SHELLEXECUTEINFOW info;
+ HANDLE h;
+ // Validate arguments
+ if (exe == NULL || process_handle == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_SIZE];
+ char arg_a[MAX_SIZE];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+ UniToStr(arg_a, sizeof(arg_a), arg);
+
+ return MsExecuteEx(exe_a, arg_a, process_handle);
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = (runas ? L"runas" : L"open");
+ info.lpFile = exe;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteExW(&info) == false)
+ {
+ return false;
+ }
+
+ h = info.hProcess;
+
+ *process_handle = (void *)h;
+
+ return true;
+}
+
+// Close the handle
+void MsCloseHandle(void *handle)
+{
+ if (handle != NULL)
+ {
+ CloseHandle(handle);
+ }
+}
+
+// Execution of the file
+bool MsExecute(char *exe, char *arg)
+{
+ return MsExecute2(exe, arg, false);
+}
+bool MsExecute2(char *exe, char *arg, bool runas)
+{
+ DWORD d;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return false;
+ }
+
+ d = (DWORD)ShellExecuteA(NULL, (runas ? "runas" : "open"), exe, arg, MsGetExeDirName(), SW_SHOWNORMAL);
+
+ if (d > 32)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool MsExecuteW(wchar_t *exe, wchar_t *arg)
+{
+ return MsExecute2W(exe, arg, false);
+}
+bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas)
+{
+ DWORD d;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_SIZE];
+ char arg_a[MAX_SIZE];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+ UniToStr(arg_a, sizeof(arg_a), arg);
+
+ return MsExecute(exe_a, arg_a);
+ }
+
+ d = (DWORD)ShellExecuteW(NULL, (runas ? L"runas" : L"open"), exe, arg, MsGetExeDirNameW(), SW_SHOWNORMAL);
+
+ if (d > 32)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Recursive directory creation
+void MsUniMakeDirEx(wchar_t *name)
+{
+ UINT wp;
+ wchar_t *tmp;
+ UINT i, len;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ tmp = ZeroMalloc(UniStrSize(name) * 2);
+ wp = 0;
+ len = UniStrLen(name);
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = name[i];
+
+ if (c == '\\')
+ {
+ if (UniStrCmpi(tmp, L"\\\\") != 0 && UniStrCmpi(tmp, L"\\") != 0)
+ {
+ MsUniMakeDir(tmp);
+ }
+ }
+
+ tmp[wp++] = c;
+ }
+
+ Free(tmp);
+
+ MsUniMakeDir(name);
+}
+void MsMakeDirEx(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+
+ MsUniMakeDirEx(name_w);
+
+ Free(name_w);
+}
+
+// Create a directory
+bool MsUniMakeDir(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ bool ret = MsMakeDir(s);
+ Free(s);
+ return ret;
+ }
+
+ return CreateDirectoryW(name, NULL);
+}
+bool MsMakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return CreateDirectoryA(name, NULL);
+}
+
+// Delete the directory
+bool MsUniDirectoryDelete(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ bool ret = MsDirectoryDelete(s);
+ Free(s);
+ return ret;
+ }
+
+ return RemoveDirectoryW(name);
+}
+bool MsDirectoryDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return RemoveDirectoryA(name);
+}
+
+// Delete the File
+bool MsUniFileDelete(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ bool ret;
+ char *s = CopyUniToStr(name);
+ ret = MsFileDelete(s);
+ Free(s);
+ return ret;
+ }
+
+ return DeleteFileW(name);
+}
+bool MsFileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return DeleteFileA(name);
+}
+
+// Get whether the specified file name is a directory
+bool MsUniIsDirectory(wchar_t *name)
+{
+ DWORD ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ ret = MsIsDirectory(s);
+ Free(s);
+
+ return ret;
+ }
+
+ ret = GetFileAttributesW(name);
+ if (ret == 0xffffffff)
+ {
+ return false;
+ }
+
+ if (ret & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool MsIsDirectoryW(wchar_t *name)
+{
+ return MsUniIsDirectory(name);
+}
+bool MsIsDirectory(char *name)
+{
+ DWORD ret;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ ret = GetFileAttributesA(tmp);
+ if (ret == 0xffffffff)
+ {
+ return false;
+ }
+
+ if (ret & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Extract the Cabinet from the MSI file
+bool MsExtractCabFromMsi(char *msi, char *cab)
+{
+ wchar_t msi_w[MAX_PATH];
+ wchar_t cab_w[MAX_PATH];
+
+ StrToUni(msi_w, sizeof(msi_w), msi);
+ StrToUni(cab_w, sizeof(cab_w), cab);
+
+ return MsExtractCabFromMsiW(msi_w, cab_w);
+}
+bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab)
+{
+ BUF *b;
+ bool ret = false;
+ UINT i;
+ char sign[] = {'M', 'S', 'C', 'F', 0, 0, 0, 0,};
+ void *pointer = NULL;
+ UINT current_pos = 0;
+ UINT sign_size;
+ // Validate arguments
+ if (msi == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ // Read the MSI
+ b = ReadDumpW(msi);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size < 128)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ sign_size = sizeof(sign);
+
+ // Search for "MSCF"
+ for (i = 0;i < (b->Size - sign_size);i++)
+ {
+ char *p = ((UCHAR *)b->Buf) + i;
+
+ if (Cmp(p, sign, sign_size) == 0)
+ {
+ pointer = p;
+ current_pos = i;
+ }
+ }
+
+ if (pointer != NULL)
+ {
+ UINT size = b->Size - current_pos;
+ BUF *b2 = NewBuf();
+
+ WriteBuf(b2, pointer, size);
+
+ ret = DumpBufW(b2, cab);
+
+ FreeBuf(b2);
+
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Retrieve a file from Cabinet file
+bool MsExtractCab(char *cab_name, char *dest_dir_name)
+{
+ wchar_t cab_name_w[MAX_SIZE];
+ wchar_t dest_dir_name_w[MAX_SIZE];
+
+ StrToUni(cab_name_w, sizeof(cab_name_w), cab_name);
+ StrToUni(dest_dir_name_w, sizeof(dest_dir_name_w), dest_dir_name);
+
+ return MsExtractCabW(cab_name_w, dest_dir_name_w);
+}
+bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name)
+{
+ wchar_t cabarc[MAX_PATH];
+ wchar_t arg[MAX_PATH * 2];
+ wchar_t tmp[MAX_PATH];
+
+ // Validate arguments
+ if (cab_name == NULL || dest_dir_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsGetCabarcExeFilenameW(cabarc, sizeof(cabarc)) == false)
+ {
+ return false;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), dest_dir_name);
+ if (UniEndWith(tmp, L"\\"))
+ {
+ tmp[UniStrLen(tmp) - 1] = 0;
+ }
+
+ UniFormat(arg, sizeof(arg),
+ L"-o X \"%s\" * \"%s\"\\",
+ cab_name,
+ tmp);
+
+ MakeDirW(dest_dir_name);
+
+ if (RunW(cabarc, arg, true, true) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Extract of cabarc.exe
+bool MsGetCabarcExeFilename(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ ConbinePath(name, size, MsGetMyTempDir(), "cabarc.exe");
+
+ if (IsFileExists(name))
+ {
+ return true;
+ }
+
+ if (FileCopy("|cabarc.exe", name) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ ConbinePathW(name, size, MsGetMyTempDirW(), L"cabarc.exe");
+
+ if (IsFileExistsW(name))
+ {
+ return true;
+ }
+
+ if (FileCopyW(L"|cabarc.exe", name) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Extract the Cabinet file from EXE file
+bool MsExtractCabinetFileFromExe(char *exe, char *cab)
+{
+ BUF *b;
+ // Validate arguments
+ if (exe == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ b = MsExtractResourceFromExe(exe, RT_RCDATA, "CABINET");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBuf(b, cab) == false)
+ {
+ FreeBuf(b);
+
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab)
+{
+ BUF *b;
+ // Validate arguments
+ if (exe == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ b = MsExtractResourceFromExeW(exe, RT_RCDATA, "CABINET");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, cab) == false)
+ {
+ FreeBuf(b);
+
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Extract the resource from EXE file
+BUF *MsExtractResourceFromExe(char *exe, char *type, char *name)
+{
+ HINSTANCE h;
+ HRSRC hr;
+ HGLOBAL hg;
+ UINT size;
+ void *data;
+ BUF *buf;
+ // Validate arguments
+ if (exe == NULL || type == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ hr = FindResourceA(h, name, type);
+ if (hr == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ hg = LoadResource(h, hr);
+ if (hg == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ size = SizeofResource(h, hr);
+ data = (void *)LockResource(hg);
+
+ buf = NewBuf();
+ WriteBuf(buf, data, size);
+
+ FreeResource(hg);
+ FreeLibrary(h);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name)
+{
+ HINSTANCE h;
+ HRSRC hr;
+ HGLOBAL hg;
+ UINT size;
+ void *data;
+ BUF *buf;
+ // Validate arguments
+ if (exe == NULL || type == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_PATH];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+
+ return MsExtractResourceFromExe(exe_a, type, name);
+ }
+
+ h = LoadLibraryExW(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ hr = FindResource(h, name, type);
+ if (hr == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ hg = LoadResource(h, hr);
+ if (hg == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ size = SizeofResource(h, hr);
+ data = (void *)LockResource(hg);
+
+ buf = NewBuf();
+ WriteBuf(buf, data, size);
+
+ FreeResource(hg);
+ FreeLibrary(h);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Get the version information of the file
+bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
+{
+ void *data;
+ UINT size;
+ DWORD h;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ h = 0;
+ size = GetFileVersionInfoSize(name, &h);
+ if (size == 0)
+ {
+ return false;
+ }
+
+ data = ZeroMalloc(size);
+
+ if (GetFileVersionInfoA(name, 0, size, data))
+ {
+ VS_FIXEDFILEINFO *info = NULL;
+ UINT info_size = 0;
+ if (VerQueryValueA(data, "\\", &info, &info_size))
+ {
+ if (v1 != NULL)
+ {
+ *v1 = HIWORD(info->dwFileVersionMS);
+ }
+
+ if (v2 != NULL)
+ {
+ *v2 = LOWORD(info->dwFileVersionMS);
+ }
+
+ if (v3 != NULL)
+ {
+ *v3 = HIWORD(info->dwFileVersionLS);
+ }
+
+ if (v4 != NULL)
+ {
+ *v4 = LOWORD(info->dwFileVersionLS);
+ }
+
+ ret = true;
+ }
+ }
+
+ Free(data);
+
+ return ret;
+}
+bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
+{
+ void *data;
+ UINT size;
+ DWORD h;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsGetFileVersion(name_a, v1, v2, v3, v4);
+ }
+
+ h = 0;
+ size = GetFileVersionInfoSizeW(name, &h);
+ if (size == 0)
+ {
+ return false;
+ }
+
+ data = ZeroMalloc(size);
+
+ if (GetFileVersionInfoW(name, 0, size, data))
+ {
+ VS_FIXEDFILEINFO *info = NULL;
+ UINT info_size = 0;
+ if (VerQueryValue(data, "\\", &info, &info_size))
+ {
+ if (v1 != NULL)
+ {
+ *v1 = HIWORD(info->dwFileVersionMS);
+ }
+
+ if (v2 != NULL)
+ {
+ *v2 = LOWORD(info->dwFileVersionMS);
+ }
+
+ if (v3 != NULL)
+ {
+ *v3 = HIWORD(info->dwFileVersionLS);
+ }
+
+ if (v4 != NULL)
+ {
+ *v4 = LOWORD(info->dwFileVersionLS);
+ }
+
+ ret = true;
+ }
+ }
+
+ Free(data);
+
+ return ret;
+}
+
+// Set the file to a hidden file
+void MsSetFileToHidden(char *name)
+{
+ char tmp[MAX_PATH];
+ DWORD d;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), name);
+
+ d = GetFileAttributesA(tmp);
+ if (d != INVALID_FILE_ATTRIBUTES)
+ {
+ d |= FILE_ATTRIBUTE_HIDDEN;
+
+ SetFileAttributesA(tmp, d);
+ }
+}
+void MsSetFileToHiddenW(wchar_t *name)
+{
+ wchar_t tmp[MAX_PATH];
+ DWORD d;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_SIZE];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ MsSetFileToHidden(name_a);
+
+ return;
+ }
+
+ NormalizePathW(tmp, sizeof(tmp), name);
+
+ d = GetFileAttributesW(tmp);
+ if (d != INVALID_FILE_ATTRIBUTES)
+ {
+ d |= FILE_ATTRIBUTE_HIDDEN;
+
+ SetFileAttributesW(tmp, d);
+ }
+}
+
+// Sleep prevention thread
+void MsNoSleepThread(THREAD *thread, void *param)
+{
+ MS_NOSLEEP *e;
+ EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
+ HINSTANCE hKernel32;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hKernel32 = LoadLibrary("kernel32.dll");
+
+ _SetThreadExecutionState =
+ (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
+ GetProcAddress(hKernel32, "SetThreadExecutionState");
+
+ e = (MS_NOSLEEP *)param;
+
+ while (e->Halt == false)
+ {
+ DWORD flag = ES_SYSTEM_REQUIRED;
+
+ if (e->NoScreenSaver)
+ {
+ flag |= ES_DISPLAY_REQUIRED;
+ }
+
+ if (_SetThreadExecutionState != NULL)
+ {
+ _SetThreadExecutionState(flag);
+ }
+
+ Wait(e->HaltEvent, 30 * 1000);
+ }
+
+ FreeLibrary(hKernel32);
+}
+
+// Sleep prevention thread (for Windows Vista)
+void MsNoSleepThreadVista(THREAD *thread, void *param)
+{
+ MS_NOSLEEP *e;
+ char *key = "Control Panel\\Desktop";
+ UINT64 last_set_flag = 0;
+ UINT last_c_x = INFINITE, last_c_y = INFINITE;
+ UINT64 last_mouse_move_time = 0;
+ EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
+ HINSTANCE hKernel32;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hKernel32 = LoadLibrary("kernel32.dll");
+
+ _SetThreadExecutionState =
+ (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
+ GetProcAddress(hKernel32, "SetThreadExecutionState");
+
+ e = (MS_NOSLEEP *)param;
+
+ while (e->Halt == false)
+ {
+ DWORD flag = ES_SYSTEM_REQUIRED;
+ UINT64 now = Tick64();
+ POINT p;
+ bool mouse_move = false;
+
+ Zero(&p, sizeof(p));
+ GetCursorPos(&p);
+
+ if (p.x != last_c_x || p.y != last_c_y)
+ {
+ if (last_c_x != INFINITE && last_c_y != INFINITE)
+ {
+ mouse_move = true;
+ }
+
+ last_c_x = p.x;
+ last_c_y = p.y;
+ }
+
+ if (mouse_move)
+ {
+ last_mouse_move_time = now;
+ }
+
+ if (last_mouse_move_time == 0 || (now > (last_mouse_move_time + 50000ULL)))
+ {
+ wchar_t *active;
+ wchar_t *exe;
+ // Remove the configuration of the screen saver If the mouse does not move more than 50 seconds
+
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
+ {
+ // Screen saver is set
+ UniStrCpy(e->ScreenSaveActive, sizeof(e->ScreenSaveActive), active);
+ UniStrCpy(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE), exe);
+
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", L"0");
+ MsRegDeleteValue(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ Debug("Push SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+
+ last_mouse_move_time = now;
+ }
+ else
+ {
+ if (mouse_move)
+ {
+ if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
+ {
+ // Restore the settings of screen saver if the screen saver
+ // is not set when the mouse is moved
+ wchar_t *active;
+ wchar_t *exe;
+
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
+ {
+ }
+ else
+ {
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
+ MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
+
+ Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
+ Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
+
+ Debug("Pop SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+ }
+ }
+ }
+
+ if (last_set_flag == 0 || (now > (last_set_flag + 50000ULL)))
+ {
+ // Flag set (interval 50 seconds)
+ last_set_flag = now;
+
+ if (_SetThreadExecutionState != NULL)
+ {
+ _SetThreadExecutionState(flag);
+ }
+ }
+
+ Wait(e->HaltEvent, 512);
+ }
+
+ if (true)
+ {
+ // Restore the settings of the screen saver
+ wchar_t *active;
+ wchar_t *exe;
+
+ if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
+ {
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) != 0)
+ {
+ }
+ else
+ {
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
+ MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
+
+ Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
+ Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
+
+ Debug("Pop SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+ }
+ }
+
+ FreeLibrary(hKernel32);
+}
+
+// The start of the sleep prevention
+void *MsNoSleepStart(bool no_screensaver)
+{
+ MS_NOSLEEP *e;
+ bool is_vista = MsIsVista();
+ bool is_nt_4 = false;
+ UINT os_type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS_NT(os_type))
+ {
+ if (GET_KETA(os_type, 100) == 1)
+ {
+ is_nt_4 = true;
+ }
+ }
+
+ e = ZeroMalloc(sizeof(MS_NOSLEEP));
+
+ e->HaltEvent = NewEvent();
+ e->NoScreenSaver = no_screensaver;
+
+ if (e->NoScreenSaver == false || (is_vista == false && is_nt_4 == false))
+ {
+ e->Thread = NewThread(MsNoSleepThread, e);
+ }
+ else
+ {
+ e->Thread = NewThread(MsNoSleepThreadVista, e);
+ }
+
+ return (void *)e;
+}
+
+// Stop the Sleep prevention
+void MsNoSleepEnd(void *p)
+{
+ MS_NOSLEEP *e;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ e = (MS_NOSLEEP *)p;
+
+ e->Halt = true;
+ Set(e->HaltEvent);
+
+ WaitThread(e->Thread, INFINITE);
+ ReleaseThread(e->Thread);
+ ReleaseEvent(e->HaltEvent);
+
+ Free(e);
+}
+
+static wchar_t ms_computer_name_full_cache[MAX_SIZE] = {0};
+
+// Get the full name of the computer
+void MsGetComputerNameFull(wchar_t *name, UINT size)
+{
+ MsGetComputerNameFullEx(name, size, false);
+}
+void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache)
+{
+ UINT size2 = size;
+ // Validate arguments
+ UniStrCpy(name, size, L"");
+ if (name == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (with_cache)
+ {
+ if (UniIsEmptyStr(ms_computer_name_full_cache) == false)
+ {
+ UniStrCpy(name, size, ms_computer_name_full_cache);
+ return;
+ }
+ }
+
+ if (MsIsNt() == false || ms->nt->GetComputerNameExW == NULL ||
+ ms->nt->GetComputerNameExW(ComputerNameDnsFullyQualified, name, &size2) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetComputerName(tmp, sizeof(tmp));
+
+ StrToUni(name, size, tmp);
+ }
+
+ if (with_cache)
+ {
+ UniStrCpy(ms_computer_name_full_cache, sizeof(ms_computer_name_full_cache), name);
+ }
+}
+
+// Get the computer name
+void MsGetComputerName(char *name, UINT size)
+{
+ DWORD sz;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ sz = size;
+ GetComputerName(name, &sz);
+}
+
+// Get the hash value of the position of the mouse cursor
+UINT MsGetCursorPosHash()
+{
+ POINT p;
+
+ Zero(&p, sizeof(p));
+
+ if (GetCursorPos(&p) == false)
+ {
+ return 0;
+ }
+
+ return MAKELONG((USHORT)p.x, (USHORT)p.y);
+}
+
+// Start the process as a standard user privileges
+void *MsRunAsUserEx(char *filename, char *arg, bool hide)
+{
+ void *ret = MsRunAsUserExInner(filename, arg, hide);
+
+ if (ret == NULL)
+ {
+ Debug("MsRunAsUserExInner Failed.\n");
+ ret = Win32RunEx(filename, arg, hide);
+ }
+
+ return ret;
+}
+void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ void *ret = MsRunAsUserExInnerW(filename, arg, hide);
+
+ if (ret == NULL)
+ {
+ Debug("MsRunAsUserExInner Failed.\n");
+ ret = Win32RunExW(filename, arg, hide);
+ }
+
+ return ret;
+}
+void *MsRunAsUserExInner(char *filename, char *arg, bool hide)
+{
+ void *ret;
+ wchar_t *filename_w;
+ wchar_t *arg_w;
+
+ filename_w = CopyStrToUni(filename);
+ arg_w = CopyStrToUni(arg);
+
+ ret = MsRunAsUserExInnerW(filename_w, arg_w, hide);
+
+ Free(filename_w);
+ Free(arg_w);
+
+ return ret;
+}
+void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ HANDLE hToken;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsVista() == false)
+ {
+ // Can not be used in non-Windows Vista
+ return NULL;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ hToken = MsCreateUserToken();
+
+ if (hToken == NULL)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->CreateProcessAsUserW(hToken, NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return NULL;
+ }
+
+ CloseHandle(hToken);
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+
+// Get the SID from the account name
+SID *MsGetSidFromAccountName(char *name)
+{
+ SID *sid;
+ UINT sid_size = 4096;
+ char *domain_name;
+ UINT domain_name_size = 4096;
+ SID_NAME_USE use = SidTypeUser;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+
+ sid = ZeroMalloc(sid_size);
+ domain_name = ZeroMalloc(domain_name_size);
+
+ if (ms->nt->LookupAccountNameA(NULL, name, sid, &sid_size, domain_name, &domain_name_size, &use) == false)
+ {
+ Free(sid);
+ Free(domain_name);
+ return NULL;
+ }
+
+ Free(domain_name);
+
+ return sid;
+}
+
+// Release the SID
+void MsFreeSid(SID *sid)
+{
+ // Validate arguments
+ if (sid == NULL)
+ {
+ return;
+ }
+
+ Free(sid);
+}
+
+// Create a token of standard user
+HANDLE MsCreateUserToken()
+{
+ char *medium_sid = "S-1-16-8192";
+ char *administrators_sid = "S-1-5-32-544";
+ SID *sid = NULL;
+ TOKEN_MANDATORY_LABEL til;
+ HANDLE hCurrentToken, hNewToken;
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+ if (ms->nt->ConvertStringSidToSidA == NULL ||
+ ms->nt->OpenProcessToken == NULL ||
+ ms->nt->DuplicateTokenEx == NULL ||
+ ms->nt->GetTokenInformation == NULL ||
+ ms->nt->SetTokenInformation == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&til, sizeof(til));
+
+ if (ms->nt->ConvertStringSidToSidA(medium_sid, &sid) == false)
+ {
+ return NULL;
+ }
+
+ til.Label.Attributes = SE_GROUP_INTEGRITY;
+ til.Label.Sid = sid;
+
+ if (ms->nt->OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hCurrentToken) == false)
+ {
+ LocalFree(sid);
+ return NULL;
+ }
+
+ if (ms->nt->DuplicateTokenEx(hCurrentToken, MAXIMUM_ALLOWED, NULL,
+ SecurityImpersonation, TokenPrimary, &hNewToken) == false)
+ {
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+ return NULL;
+ }
+
+ if (ms->nt->SetTokenInformation(hNewToken, VistaTokenIntegrityLevel, &til,
+ sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(sid)) == false)
+ {
+ CloseHandle(hNewToken);
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+ return NULL;
+ }
+
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+
+ return hNewToken;
+}
+
+
+// Check the digital signature of the file
+bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger)
+{
+ wchar_t tmp[MAX_PATH];
+
+ swprintf(tmp, sizeof(tmp), L"%S", name);
+
+ return MsCheckFileDigitalSignatureW(hWnd, tmp, danger);
+}
+bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger)
+{
+ HRESULT ret = S_OK;
+ wchar_t *tmp;
+ LONG (WINAPI *_WinVerifyTrust)(HWND, GUID *, LPVOID) = NULL;
+ HINSTANCE hDll;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (danger != NULL)
+ {
+ *danger = false;
+ }
+
+ tmp = name;
+
+ hDll = LoadLibrary("Wintrust.dll");
+ if (hDll == NULL)
+ {
+ return false;
+ }
+
+ _WinVerifyTrust =
+ (LONG (__stdcall *)(HWND,GUID *,LPVOID))
+ GetProcAddress(hDll, "WinVerifyTrust");
+ if (_WinVerifyTrust == NULL)
+ {
+ FreeLibrary(hDll);
+ return false;
+ }
+ else
+ {
+ GUID action_id = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+ WINTRUST_FILE_INFO file;
+ WINTRUST_DATA data;
+
+ Zero(&file, sizeof(file));
+ file.cbStruct = sizeof(file);
+ file.pcwszFilePath = tmp;
+
+ Zero(&data, sizeof(data));
+ data.cbStruct = sizeof(data);
+ data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
+ data.dwUIChoice = (hWnd != NULL ? WTD_UI_NOGOOD : WTD_UI_NONE);
+ data.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
+ data.dwUnionChoice = WTD_CHOICE_FILE;
+ data.pFile = &file;
+
+ ret = _WinVerifyTrust(hWnd, &action_id, &data);
+
+ if (ret == ERROR_SUCCESS && danger != NULL)
+ {
+ if (hWnd != NULL)
+ {
+ if (MsCheckFileDigitalSignatureW(NULL, name, NULL) == false)
+ {
+ // It's a dangerous file, but the user had to select the [OK]
+ *danger = true;
+ }
+ }
+ }
+ }
+
+ FreeLibrary(hDll);
+
+ if (ret != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Enable or disable the WoW64 redirection
+void MsSetWow64FileSystemRedirectionEnable(bool enable)
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return;
+ }
+
+ if (ms->nt->Wow64EnableWow64FsRedirection == NULL)
+ {
+ return;
+ }
+
+ ms->nt->Wow64EnableWow64FsRedirection(enable ? 1 : 0);
+}
+
+// Disable the WoW64 redirection
+void *MsDisableWow64FileSystemRedirection()
+{
+ void *p = NULL;
+ if (MsIs64BitWindows() == false)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
+ ms->nt->Wow64RevertWow64FsRedirection == NULL)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection(&p) == false)
+ {
+ return NULL;
+ }
+
+ if (p == NULL)
+ {
+ p = (void *)0x12345678;
+ }
+
+ return p;
+}
+
+// Restore the WoW64 redirection
+void MsRestoreWow64FileSystemRedirection(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+ if (p == (void *)0x12345678)
+ {
+ p = NULL;
+ }
+ if (MsIs64BitWindows() == false)
+ {
+ return;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
+ ms->nt->Wow64RevertWow64FsRedirection == NULL)
+ {
+ return;
+ }
+
+ ms->nt->Wow64RevertWow64FsRedirection(p);
+}
+
+// Get whether the x64 version of Windows is currently running
+bool MsIsX64()
+{
+ SYSTEM_INFO info;
+
+ if (MsIs64BitWindows() == false)
+ {
+ return false;
+ }
+ if (ms->nt->GetNativeSystemInfo == NULL)
+ {
+ return false;
+ }
+
+ Zero(&info, sizeof(info));
+ ms->nt->GetNativeSystemInfo(&info);
+
+ if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get whether the IA64 version of Windows is currently running
+bool MsIsIA64()
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return false;
+ }
+
+ if (MsIsX64())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Acquisition whether it's a 64bit Windows
+bool MsIs64BitWindows()
+{
+ if (Is64())
+ {
+ return true;
+ }
+ else
+ {
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+ else
+ {
+ if (ms == NULL || ms->nt == NULL)
+ {
+ return false;
+ }
+
+ if (ms->nt->IsWow64Process == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ bool b = false;
+ if (ms->nt->IsWow64Process(GetCurrentProcess(), &b) == false)
+ {
+ return false;
+ }
+ return b;
+ }
+ }
+ }
+}
+
+// Windows Firewall registration
+void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (title == NULL || exe == NULL)
+ {
+ return;
+ }
+ if (dir == NULL || IsEmptyStr(dir))
+ {
+ dir = MsGetExeDirName();
+ }
+
+ ConbinePath(tmp, sizeof(tmp), dir, exe);
+
+ if (IsFileExists(tmp) == false)
+ {
+ return;
+ }
+
+ MsRegistWindowsFirewallEx(title, tmp);
+}
+void MsRegistWindowsFirewallEx(char *title, char *exe)
+{
+ char *data =
+ "Option Explicit\r\nConst NET_FW_PROFILE_DOMAIN = 0\r\nConst NET_FW_PROFILE_STANDARD = 1\r\n"
+ "Const NET_FW_SCOPE_ALL = 0\r\nConst NET_FW_IP_VERSION_ANY = 2\r\nDim fwMgr\r\n"
+ "Set fwMgr = CreateObject(\"HNetCfg.FwMgr\")\r\nDim profile\r\n"
+ "Set profile = fwMgr.LocalPolicy.CurrentProfile\r\nDim app\r\n"
+ "Set app = CreateObject(\"HNetCfg.FwAuthorizedApplication\")\r\n"
+ "app.ProcessImageFileName = \"$PATH$\"\r\napp.Name = \"$TITLE$\"\r\n"
+ "app.Scope = NET_FW_SCOPE_ALL\r\napp.IpVersion = NET_FW_IP_VERSION_ANY\r\n"
+ "app.Enabled = TRUE\r\nOn Error Resume Next\r\nprofile.AuthorizedApplications."
+ "Add app\r\n";
+ char *tmp;
+ UINT tmp_size;
+ char filename[MAX_PATH];
+ char cscript[MAX_PATH];
+ char arg[MAX_PATH];
+ UINT ostype;
+ IO *o;
+ char hash[MAX_PATH];
+ UCHAR hashbin[SHA1_SIZE];
+ UCHAR file_hash_bin[SHA1_SIZE];
+ char file_hash_str[MAX_SIZE];
+ // Validate arguments
+ if (title == NULL || exe == NULL)
+ {
+ return;
+ }
+
+ // OS check (This Is not performed except Windows XP, Windows Server 2003, Windows Vista or later)
+ ostype = GetOsInfo()->OsType;
+ if (OS_IS_WINDOWS_NT(ostype) == false)
+ {
+ return;
+ }
+ if (MsIsVista() == false && (GET_KETA(ostype, 100) != 3 && GET_KETA(ostype, 100) != 4 && GET_KETA(ostype, 100) != 5 && GET_KETA(ostype, 100) != 6 && GET_KETA(ostype, 100) != 7))
+ {
+ return;
+ }
+ if (MsIsAdmin() == false)
+ {
+ return;
+ }
+
+ if (MsIsVista())
+ {
+ data = "Option Explicit\r\n\r\nConst PROFILES_ALL = 7\r\nConst NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW = 1\r\n"
+ "\r\nDim policy2\r\nDim rules\r\nDim new_rule\r\n\r\nOn Error Resume Next\r\n\r\n"
+ "Set policy2 = CreateObject(\"HNetCfg.FwPolicy2\")\r\nSet rules = policy2.Rules\r\n"
+ "Set new_rule = CreateObject(\"HNetCfg.FWRule\")\r\nnew_rule.Name = \"$TITLE$\"\r\n"
+ "new_rule.Description = \"$TITLE$\"\r\nnew_rule.ApplicationName = \"$PATH$\"\r\n"
+ "new_rule.Enabled = TRUE\r\nnew_rule.Profiles = PROFILES_ALL\r\nnew_rule.Action = "
+ "NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW\r\nrules.Add new_rule\r\n\r\n";
+ }
+
+ tmp_size = StrLen(data) * 4;
+ tmp = ZeroMalloc(tmp_size);
+
+ HashSha1(hashbin, exe, StrLen(exe));
+ BinToStr(hash, sizeof(hash), hashbin, 6);
+
+ ReplaceStrEx(tmp, tmp_size, data, "$TITLE$", title, false);
+ ReplaceStrEx(tmp, tmp_size, tmp, "$PATH$", exe, false);
+
+ HashSha1(file_hash_bin, tmp, StrLen(tmp));
+ BinToStr(file_hash_str, sizeof(file_hash_str), file_hash_bin, sizeof(file_hash_bin));
+
+ if (MsIsVista() == false || MsRegReadIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, false, true) == 0)
+ {
+ Format(filename, sizeof(filename), "%s\\winfire_%s.vbs", MsGetMyTempDir(), hash);
+ o = FileCreate(filename);
+ FileWrite(o, tmp, StrLen(tmp));
+ FileClose(o);
+
+ Format(cscript, sizeof(cscript), "%s\\cscript.exe", MsGetSystem32Dir());
+ Format(arg, sizeof(arg), "\"%s\"", filename);
+
+ if (Run(cscript, arg, true, false))
+ {
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, 1, false, true);
+ }
+
+ Debug("cscript %s\n", arg);
+ }
+
+ Free(tmp);
+}
+
+// Run driver installer for Vista
+bool MsExecDriverInstaller(char *arg)
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t hamcore_dst[MAX_PATH];
+ wchar_t hamcore_src[MAX_PATH];
+ wchar_t lang_config_src[MAX_PATH];
+ wchar_t lang_config_dst[MAX_PATH];
+ HANDLE h;
+ UINT retcode;
+ SHELLEXECUTEINFOW info;
+ wchar_t *src_exe;
+ wchar_t *arg_w;
+ // Validate arguments
+ if (arg == NULL)
+ {
+ return false;
+ }
+
+ UniFormat(hamcore_dst, sizeof(hamcore_dst), L"%s\\hamcore.se2", MsGetMyTempDirW());
+ UniFormat(hamcore_src, sizeof(hamcore_src), L"%s\\hamcore.se2", MsGetExeDirNameW());
+
+ // Extract the File
+ src_exe = VISTA_DRIVER_INSTALLER_SRC;
+
+ if (MsIsX64())
+ {
+ src_exe = VISTA_DRIVER_INSTALLER_SRC_X64;
+ }
+ if (MsIsIA64())
+ {
+ src_exe = VISTA_DRIVER_INSTALLER_SRC_IA64;
+ }
+
+ UniFormat(tmp, sizeof(tmp), VISTA_DRIVER_INSTALLER_DST, MsGetMyTempDirW());
+
+ if (FileCopyW(src_exe, tmp) == false)
+ {
+ return false;
+ }
+
+ if (FileCopyW(hamcore_src, hamcore_dst) == false)
+ {
+ return false;
+ }
+
+ ConbinePathW(lang_config_src, sizeof(lang_config_src), MsGetExeDirNameW(), L"lang.config");
+ ConbinePathW(lang_config_dst, sizeof(lang_config_dst), MsGetMyTempDirW(), L"lang.config");
+ FileCopyW(lang_config_src, lang_config_dst);
+
+ arg_w = CopyStrToUni(arg);
+
+ // Run
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = L"open";
+ info.lpFile = tmp;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg_w;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteExW(&info) == false)
+ {
+ Free(arg_w);
+ return false;
+ }
+
+ Free(arg_w);
+
+ h = info.hProcess;
+ retcode = 1;
+
+ while (true)
+ {
+ // Wait for completion
+ WaitForSingleObject(h, INFINITE);
+
+ // Get the exit code
+ retcode = 1;
+ if (GetExitCodeProcess(h, &retcode) == false)
+ {
+ break;
+ }
+
+ if (retcode != STILL_ACTIVE)
+ {
+ break;
+ }
+ }
+
+ CloseHandle(h);
+
+ if (retcode & 1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the locale of the current thread
+UINT MsGetThreadLocale()
+{
+ return (UINT)GetThreadLocale();
+}
+
+// Set the width of the current console
+UINT MsSetConsoleWidth(UINT size)
+{
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ COORD c;
+ UINT old_x, old_y;
+ // Validate arguments
+ if (size == 0)
+ {
+ return 0;
+ }
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
+
+ Zero(&info, sizeof(info));
+ if (GetConsoleScreenBufferInfo(h, &info) == false)
+ {
+ return 0;
+ }
+
+ old_x = info.dwSize.X;
+ old_y = info.dwSize.Y;
+
+ c.X = size;
+ c.Y = old_y;
+
+ SetConsoleScreenBufferSize(h, c);
+
+ return old_x;
+}
+
+// Get the width of the current console
+UINT MsGetConsoleWidth()
+{
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return 80;
+ }
+
+ Zero(&info, sizeof(info));
+ if (GetConsoleScreenBufferInfo(h, &info) == false)
+ {
+ return 80;
+ }
+
+ return info.dwSize.X;
+}
+
+// Disable the MS-IME
+bool MsDisableIme()
+{
+ HINSTANCE h;
+ bool ret = false;
+ char dll_name[MAX_PATH];
+ BOOL (WINAPI *_ImmDisableIME)(DWORD);
+
+ Format(dll_name, sizeof(dll_name), "%s\\imm32.dll", MsGetSystem32Dir());
+ h = MsLoadLibrary(dll_name);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ _ImmDisableIME = (BOOL (__stdcall *)(DWORD))GetProcAddress(h, "ImmDisableIME");
+
+ if (_ImmDisableIME != NULL)
+ {
+ ret = _ImmDisableIME(-1);
+ }
+
+ FreeLibrary(h);
+
+ return ret;
+}
+
+// Display the current time
+void MsPrintTick()
+{
+ UINT tick = timeGetTime();
+ static UINT tick_init = 0;
+ if (tick_init == 0)
+ {
+ tick_init = tick;
+ tick = 0;
+ }
+ else
+ {
+ tick -= tick_init;
+ }
+
+ printf("[%u]\n", tick);
+}
+
+// LoadLibrary compatible for hamcore (Read as a data file)
+void *MsLoadLibraryAsDataFileW(wchar_t *name)
+{
+ BUF *b;
+ wchar_t tmp_dll_name[MAX_SIZE];
+ char hash_str[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Hash(hash, name, UniStrLen(name), true);
+
+ BinToStr(hash_str, sizeof(hash_str), hash, 4);
+
+ UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
+
+ if (IsFileExistsW(tmp_dll_name) == false)
+ {
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ DumpBufW(b, tmp_dll_name);
+ FreeBuf(b);
+ }
+
+ return LoadLibraryExW(tmp_dll_name, NULL, LOAD_LIBRARY_AS_DATAFILE);
+}
+void *MsLoadLibraryAsDataFile(char *name)
+{
+ wchar_t name_w[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ return MsLoadLibraryAsDataFileW(name_w);
+}
+
+// Simple LoadLibaray
+void *MsLoadLibraryRawW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsNt())
+ {
+ return LoadLibraryW(name);
+ }
+ else
+ {
+ char tmp[MAX_PATH];
+
+ UniToStr(tmp, sizeof(tmp), name);
+
+ return LoadLibraryA(tmp);
+ }
+}
+
+// LoadLibrary (compatible for Hamcore)
+void *MsLoadLibraryW(wchar_t *name)
+{
+ BUF *b;
+ wchar_t tmp_dll_name[MAX_SIZE];
+ char hash_str[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Hash(hash, name, UniStrSize(name), true);
+
+ BinToStr(hash_str, sizeof(hash_str), hash, 4);
+
+ UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
+
+ if (IsFileExistsW(tmp_dll_name) == false)
+ {
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ DumpBufW(b, tmp_dll_name);
+ FreeBuf(b);
+ }
+
+ if (IsNt())
+ {
+ return LoadLibraryW(tmp_dll_name);
+ }
+ else
+ {
+ char tmp_dll_name_a[MAX_SIZE];
+ HINSTANCE ret;
+
+ UniToStr(tmp_dll_name_a, sizeof(tmp_dll_name_a), tmp_dll_name);
+
+ ret = LoadLibraryA(tmp_dll_name_a);
+
+ return ret;
+ }
+}
+void *MsLoadLibrary(char *name)
+{
+ wchar_t name_w[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ return MsLoadLibraryW(name_w);
+}
+
+// Release of the library
+void MsFreeLibrary(void *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ FreeLibrary(h);
+}
+
+// Get the function pointer in the DLL
+void *MsGetProcAddress(void *h, char *name)
+{
+ // Validate arguments
+ if (h == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ return (void *)GetProcAddress(h, name);
+}
+
+// Search for the adapter by GUID
+MS_ADAPTER *MsGetAdapterByGuid(char *guid)
+{
+ MS_ADAPTER_LIST *o;
+ MS_ADAPTER *ret = NULL;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ o = MsCreateAdapterList();
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = MsGetAdapterByGuidFromList(o, guid);
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid)
+{
+ MS_ADAPTER *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (o == NULL || guid == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ if (StrCmpi(o->Adapters[i]->Guid, guid) == 0)
+ {
+ ret = MsCloneAdapter(o->Adapters[i]);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Get a single adapter
+MS_ADAPTER *MsGetAdapter(char *title)
+{
+ MS_ADAPTER_LIST *o;
+ MS_ADAPTER *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (title == NULL)
+ {
+ return NULL;
+ }
+
+ o = MsCreateAdapterList();
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ if (StrCmpi(o->Adapters[i]->Title, title) == 0)
+ {
+ ret = MsCloneAdapter(o->Adapters[i]);
+ break;
+ }
+ }
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+
+// 32-bit overflow checking
+#define CHECK_32BIT_OVERFLOW(old_value, new_value) \
+{ \
+ if ((old_value) > (new_value)) \
+ { \
+ (new_value) += ((UINT64)4294967296ULL); \
+ } \
+}
+
+// Get the TCP/IP information of the specified adapter
+void MsGetAdapterTcpIpInformation(MS_ADAPTER *a)
+{
+ IP_ADAPTER_INFO *info, *info_top;
+ UINT info_size;
+ UINT ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (w32net->GetAdaptersInfo == NULL)
+ {
+ return;
+ }
+
+ info_top = ZeroMalloc(sizeof(IP_ADAPTER_INFO));
+ info_size = sizeof(IP_ADAPTER_INFO);
+
+ ret = w32net->GetAdaptersInfo(info_top, &info_size);
+ if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info_top);
+ info_size *= 2;
+ info_top = ZeroMalloc(info_size);
+
+ if (w32net->GetAdaptersInfo(info_top, &info_size) != NO_ERROR)
+ {
+ Free(info_top);
+ return;
+ }
+ }
+ else if (ret != NO_ERROR)
+ {
+ Free(info_top);
+ return;
+ }
+
+ // Search for their own entry
+ info = info_top;
+
+ while (info != NULL)
+ {
+ if (info->Index == a->Index)
+ {
+ IP_ADDR_STRING *s;
+
+ // IP address
+ a->NumIpAddress = 0;
+ s = &info->IpAddressList;
+ while (s != NULL)
+ {
+ if (a->NumIpAddress < MAX_MS_ADAPTER_IP_ADDRESS)
+ {
+ StrToIP(&a->IpAddresses[a->NumIpAddress], s->IpAddress.String);
+ StrToIP(&a->SubnetMasks[a->NumIpAddress], s->IpMask.String);
+ a->NumIpAddress++;
+ }
+ s = s->Next;
+ }
+
+ // Gateway
+ a->NumGateway = 0;
+ s = &info->GatewayList;
+ while (s != NULL)
+ {
+ if (a->NumGateway < MAX_MS_ADAPTER_IP_ADDRESS)
+ {
+ StrToIP(&a->Gateways[a->NumGateway], s->IpAddress.String);
+ a->NumGateway++;
+ }
+ s = s->Next;
+ }
+
+ // DHCP Server
+ a->UseDhcp = (info->DhcpEnabled == 0 ? false : true);
+ if (a->UseDhcp)
+ {
+ SYSTEMTIME st;
+
+ StrToIP(&a->DhcpServer, info->DhcpServer.IpAddress.String);
+ TimeToSystem(&st, info->LeaseObtained);
+ a->DhcpLeaseStart = SystemToUINT64(&st);
+
+ TimeToSystem(&st, info->LeaseExpires);
+ a->DhcpLeaseExpires = SystemToUINT64(&st);
+ }
+
+ // WINS server
+ a->UseWins = info->HaveWins;
+ if (a->UseWins)
+ {
+ StrToIP(&a->PrimaryWinsServer, info->PrimaryWinsServer.IpAddress.String);
+ StrToIP(&a->SecondaryWinsServer, info->SecondaryWinsServer.IpAddress.String);
+ }
+
+ StrCpy(a->Guid, sizeof(a->Guid), info->AdapterName);
+
+ a->Info = true;
+
+ break;
+ }
+
+ info = info->Next;
+ }
+
+ Free(info_top);
+}
+
+// Generation of adapter list
+MS_ADAPTER_LIST *MsCreateAdapterList()
+{
+ return MsCreateAdapterListEx(false);
+}
+MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info)
+{
+ MS_ADAPTER_LIST *ret;
+
+ if (no_info)
+ {
+ ret = MsCreateAdapterListInnerEx(true);
+
+ return ret;
+ }
+
+ Lock(lock_adapter_list);
+ {
+ MS_ADAPTER_LIST *old = last_adapter_list;
+ UINT i;
+
+ // Fetch a new adapter list
+ ret = MsCreateAdapterListInner();
+
+ if (ret == NULL)
+ {
+ Unlock(lock_adapter_list);
+ return NULL;
+ }
+
+ // Check whether the previously acquired item exists for each entry
+ // in the list of adapters have been taken
+ for (i = 0;i < ret->Num;i++)
+ {
+ UINT j;
+ for (j = 0;j < old->Num;j++)
+ {
+ MS_ADAPTER *o = old->Adapters[j];
+ MS_ADAPTER *n = ret->Adapters[i];
+
+ if (StrCmpi(o->Title, n->Title) == 0)
+ {
+ // If the value of older item is small, increment it
+ CHECK_32BIT_OVERFLOW(o->RecvBytes, n->RecvBytes);
+ CHECK_32BIT_OVERFLOW(o->RecvPacketsBroadcast, n->RecvPacketsBroadcast);
+ CHECK_32BIT_OVERFLOW(o->RecvPacketsUnicast, n->RecvPacketsUnicast);
+ CHECK_32BIT_OVERFLOW(o->SendBytes, n->SendBytes);
+ CHECK_32BIT_OVERFLOW(o->SendPacketsBroadcast, n->SendPacketsBroadcast);
+ CHECK_32BIT_OVERFLOW(o->SendPacketsUnicast, n->SendPacketsUnicast);
+ break;
+ }
+ }
+ }
+
+ // Release the old adapter list
+ MsFreeAdapterList(old);
+
+ // Save a clone of the adapter list that newly acquired
+ last_adapter_list = MsCloneAdapterList(ret);
+ }
+ Unlock(lock_adapter_list);
+
+ return ret;
+}
+
+// Initialization of the adapter module list
+void MsInitAdapterListModule()
+{
+ lock_adapter_list = NewLock(NULL);
+
+ last_adapter_list = MsCreateAdapterListInner();
+}
+
+// Release of the adapter module list
+void MsFreeAdapterListModule()
+{
+ if (last_adapter_list != NULL)
+ {
+ MsFreeAdapterList(last_adapter_list);
+ last_adapter_list = NULL;
+ }
+
+ DeleteLock(lock_adapter_list);
+ lock_adapter_list = NULL;
+}
+
+// Clone the adapter list
+MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o)
+{
+ MS_ADAPTER_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = o->Num;
+ ret->Adapters = ZeroMalloc(sizeof(MS_ADAPTER *) * ret->Num);
+
+ for (i = 0;i < ret->Num;i++)
+ {
+ ret->Adapters[i] = ZeroMalloc(sizeof(MS_ADAPTER));
+ Copy(ret->Adapters[i], o->Adapters[i], sizeof(MS_ADAPTER));
+ }
+
+ return ret;
+}
+
+// Clone the adapter
+MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a)
+{
+ MS_ADAPTER *ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER));
+ Copy(ret, a, sizeof(MS_ADAPTER));
+
+ return ret;
+}
+
+// Creating an adapters list
+MS_ADAPTER_LIST *MsCreateAdapterListInner()
+{
+ return MsCreateAdapterListInnerEx(false);
+}
+MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info)
+{
+ LIST *o;
+ UINT i;
+ UINT retcode;
+ MIB_IFTABLE *table;
+ UINT table_size = sizeof(MIB_IFTABLE);
+ MS_ADAPTER_LIST *ret;
+
+ if (w32net->GetIfTable2 != NULL && w32net->FreeMibTable != NULL)
+ {
+ return MsCreateAdapterListInnerExVista(no_info);
+ }
+
+ if (w32net->GetIfTable == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ table = ZeroMalloc(table_size);
+
+ retcode = w32net->GetIfTable(table, &table_size, TRUE);
+ if (retcode == ERROR_INSUFFICIENT_BUFFER || retcode == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(table);
+ table_size *= 2;
+ table = ZeroMalloc(table_size);
+ if (w32net->GetIfTable(table, &table_size, TRUE) != NO_ERROR)
+ {
+ Free(table);
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+ }
+ else if (retcode != NO_ERROR)
+ {
+ Free(table);
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &table->table[i];
+ char title[MAX_PATH];
+ UINT num = 0;
+ MS_ADAPTER *a;
+ UINT j;
+
+ //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ //if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
+ {
+ for (j = 1;;j++)
+ {
+ UINT k;
+ bool exists;
+ if (j == 1)
+ {
+ StrCpy(title, sizeof(title), (char *)r->bDescr);
+ }
+ else
+ {
+ Format(title, sizeof(title), "%s (%u)", (char *)r->bDescr, j);
+ }
+
+ exists = false;
+
+ for (k = 0;k < LIST_NUM(o);k++)
+ {
+ MS_ADAPTER *a = LIST_DATA(o, k);
+
+ if (StrCmpi(a->Title, title) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ break;
+ }
+ }
+
+ a = ZeroMalloc(sizeof(MS_ADAPTER));
+
+ // Create an adapter information
+ StrCpy(a->Title, sizeof(a->Title), title);
+ StrToUni(a->TitleW, sizeof(a->TitleW), title);
+ a->Index = r->dwIndex;
+ a->Type = r->dwType;
+ a->Status = r->dwOperStatus;
+ a->Mtu = r->dwMtu;
+ a->Speed = r->dwSpeed;
+ a->AddressSize = MIN(sizeof(a->Address), r->dwPhysAddrLen);
+ Copy(a->Address, r->bPhysAddr, a->AddressSize);
+ a->RecvBytes = r->dwInOctets;
+ a->RecvPacketsBroadcast = r->dwInNUcastPkts;
+ a->RecvPacketsUnicast = r->dwInUcastPkts;
+ a->SendBytes = r->dwOutOctets;
+ a->SendPacketsBroadcast = r->dwOutNUcastPkts;
+ a->SendPacketsUnicast = r->dwOutUcastPkts;
+
+ if (a->Type != IF_TYPE_ETHERNET_CSMACD)
+ {
+ a->IsNotEthernetLan = true;
+ }
+
+ // TCP/IP information acquisition
+ if (no_info == false)
+ {
+ MsGetAdapterTcpIpInformation(a);
+ }
+
+ Add(o, a);
+ }
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = LIST_NUM(o);
+ ret->Adapters = ToArray(o);
+
+ ReleaseList(o);
+ Free(table);
+
+ return ret;
+}
+
+// Creating an adapters list (Windows Vista version)
+MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info)
+{
+ LIST *o;
+ UINT i;
+ UINT retcode;
+ MIB_IF_TABLE2 *table;
+ UINT table_size = sizeof(MIB_IFTABLE);
+ MS_ADAPTER_LIST *ret;
+
+ if (w32net->GetIfTable2 == NULL || w32net->FreeMibTable == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ retcode = w32net->GetIfTable2(&table);
+ if (retcode != NO_ERROR || table == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < table->NumEntries;i++)
+ {
+ MIB_IF_ROW2 *r = &table->Table[i];
+ wchar_t title[MAX_PATH];
+ UINT num = 0;
+ MS_ADAPTER *a;
+ UINT j;
+
+ //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ //if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
+ {
+ for (j = 1;;j++)
+ {
+ UINT k;
+ bool exists;
+ if (j == 1)
+ {
+ UniStrCpy(title, sizeof(title), r->Description);
+ }
+ else
+ {
+ UniFormat(title, sizeof(title), L"%s (%u)", r->Description, j);
+ }
+
+ exists = false;
+
+ for (k = 0;k < LIST_NUM(o);k++)
+ {
+ MS_ADAPTER *a = LIST_DATA(o, k);
+
+ if (UniStrCmpi(a->TitleW, title) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ break;
+ }
+ }
+
+ a = ZeroMalloc(sizeof(MS_ADAPTER));
+
+ // Create an adapter information
+ UniStrCpy(a->TitleW, sizeof(a->TitleW), title);
+ UniToStr(a->Title, sizeof(a->Title), title);
+ a->Index = r->InterfaceIndex;
+ a->Type = r->Type;
+ a->Status = ConvertMidStatusVistaToXp(r->OperStatus);
+ a->Mtu = r->Mtu;
+ a->Speed = MAX((UINT)r->TransmitLinkSpeed, (UINT)r->ReceiveLinkSpeed);
+ a->AddressSize = MIN(sizeof(a->Address), r->PhysicalAddressLength);
+ Copy(a->Address, r->PhysicalAddress, a->AddressSize);
+ a->RecvBytes = r->InOctets;
+ a->RecvPacketsBroadcast = r->InNUcastPkts;
+ a->RecvPacketsUnicast = r->InUcastPkts;
+ a->SendBytes = r->OutOctets;
+ a->SendPacketsBroadcast = r->OutNUcastPkts;
+ a->SendPacketsUnicast = r->OutUcastPkts;
+
+ if (r->MediaType == NdisMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWirelessLan ||
+ r->PhysicalMediumType == NdisPhysicalMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWiMax ||
+ r->Type == IF_TYPE_IEEE80211)
+ {
+ a->IsWireless = true;
+ }
+
+ if (a->IsWireless ||
+ r->Type != IF_TYPE_ETHERNET_CSMACD ||
+ r->MediaType != NdisMedium802_3 ||
+ (r->PhysicalMediumType != 0 && r->PhysicalMediumType != NdisPhysicalMedium802_3))
+ {
+ a->IsNotEthernetLan = true;
+ }
+
+ // TCP/IP information acquisition
+ if (no_info == false)
+ {
+ MsGetAdapterTcpIpInformation(a);
+ }
+
+ Add(o, a);
+ }
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = LIST_NUM(o);
+ ret->Adapters = ToArray(o);
+
+ ReleaseList(o);
+ w32net->FreeMibTable(table);
+
+ return ret;
+}
+
+// Convert the MIB Operational Status from Vista format to XP format
+UINT ConvertMidStatusVistaToXp(UINT st)
+{
+ switch (st)
+ {
+ case IfOperStatusUp:
+ return MIB_IF_OPER_STATUS_CONNECTED;
+
+ case IfOperStatusDown:
+ return MIB_IF_OPER_STATUS_DISCONNECTED;
+ }
+
+ return MIB_IF_OPER_STATUS_NON_OPERATIONAL;
+}
+
+// Release the adapter list
+void MsFreeAdapterList(MS_ADAPTER_LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ MsFreeAdapter(o->Adapters[i]);
+ }
+ Free(o->Adapters);
+
+ Free(o);
+}
+
+// Release the adapter information
+void MsFreeAdapter(MS_ADAPTER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Free(a);
+}
+
+// Get the status string of the adapter
+wchar_t *MsGetAdapterStatusStr(UINT status)
+{
+ wchar_t *ret;
+
+ switch (status)
+ {
+ case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
+ ret = _UU("MS_NON_OPERATIONAL");
+ break;
+
+ case MIB_IF_OPER_STATUS_UNREACHABLE:
+ ret = _UU("MS_UNREACHABLE");
+ break;
+
+ case MIB_IF_OPER_STATUS_DISCONNECTED:
+ ret = _UU("MS_DISCONNECTED");
+ break;
+
+ case MIB_IF_OPER_STATUS_CONNECTING:
+ ret = _UU("MS_CONNECTING");
+ break;
+
+ case MIB_IF_OPER_STATUS_CONNECTED:
+ ret = _UU("MS_CONNECTED");
+ break;
+
+ default:
+ ret = _UU("MS_OPERATIONAL");
+ break;
+ }
+
+ return ret;
+}
+
+// Get the type string of the adapter
+wchar_t *MsGetAdapterTypeStr(UINT type)
+{
+ wchar_t *ret;
+
+ switch (type)
+ {
+ case MIB_IF_TYPE_ETHERNET:
+ ret = _UU("MS_ETHERNET");
+ break;
+
+ case IF_TYPE_IEEE80211:
+ ret = _UU("MS_WLAN");
+ break;
+
+ case MIB_IF_TYPE_TOKENRING:
+ ret = _UU("MS_TOKENRING");
+ break;
+
+ case MIB_IF_TYPE_FDDI:
+ ret = _UU("MS_FDDI");
+ break;
+
+ case MIB_IF_TYPE_PPP:
+ ret = _UU("MS_PPP");
+ break;
+
+ case MIB_IF_TYPE_LOOPBACK:
+ ret = _UU("MS_LOOPBACK");
+ break;
+
+ case MIB_IF_TYPE_SLIP:
+ ret = _UU("MS_SLIP");
+ break;
+
+ default:
+ ret = _UU("MS_OTHER");
+ break;
+ }
+
+ return ret;
+}
+
+// Kill the process of specified EXE file name
+UINT MsKillProcessByExeName(wchar_t *name)
+{
+ LIST *o;
+ UINT me, i;
+ UINT num = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ o = MsGetProcessList();
+ me = MsGetProcessId();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ if (p->ProcessId != me)
+ {
+ if (UniStrCmpi(p->ExeFilenameW, name) == 0)
+ {
+ if (MsKillProcess(p->ProcessId))
+ {
+ num++;
+ }
+ }
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return num;
+}
+
+// Terminate all instances except the EXE itself
+void MsKillOtherInstance()
+{
+ MsKillOtherInstanceEx(NULL);
+}
+void MsKillOtherInstanceEx(char *exclude_svcname)
+{
+ UINT me, i;
+ wchar_t me_path[MAX_PATH];
+ wchar_t me_path_short[MAX_PATH];
+ LIST *o = MsGetProcessList();
+ UINT e_procid = 0;
+ UINT e_procid2 = 0;
+
+ if (exclude_svcname != NULL)
+ {
+ e_procid = MsReadCallingServiceManagerProcessId(exclude_svcname, false);
+ e_procid2 = MsReadCallingServiceManagerProcessId(exclude_svcname, true);
+ }
+
+ me = MsGetProcessId();
+
+ MsGetCurrentProcessExeNameW(me_path, sizeof(me_path));
+ MsGetShortPathNameW(me_path, me_path_short, sizeof(me_path_short));
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ if (p->ProcessId != me)
+ {
+ if ((e_procid == 0 || (e_procid != p->ProcessId)) && (e_procid2 == 0 || (e_procid2 != p->ProcessId)))
+ {
+ wchar_t tmp[MAX_PATH];
+ MsGetShortPathNameW(p->ExeFilenameW, tmp, sizeof(tmp));
+ if (UniStrCmpi(me_path_short, tmp) == 0)
+ {
+ MsKillProcess(p->ProcessId);
+ }
+ }
+ }
+ }
+
+ MsFreeProcessList(o);
+}
+
+// Get the short file name
+bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size)
+{
+ // Validate arguments
+ if (long_path == NULL || short_path == NULL)
+ {
+ return false;
+ }
+
+ if (GetShortPathNameA(long_path, short_path, short_path_size) == 0)
+ {
+ StrCpy(short_path, short_path_size, long_path);
+ return false;
+ }
+
+ return true;
+}
+bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size)
+{
+ // Validate arguments
+ if (long_path == NULL || short_path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char short_path_a[MAX_SIZE];
+ char long_path_a[MAX_SIZE];
+ bool ret;
+
+ UniToStr(long_path_a, sizeof(long_path_a), long_path);
+
+ ret = MsGetShortPathNameA(long_path_a, short_path_a, sizeof(short_path_a));
+
+ StrToUni(short_path, short_path_size, short_path_a);
+
+ return ret;
+ }
+
+ if (GetShortPathNameW(long_path, short_path, short_path_size) == 0)
+ {
+ UniStrCpy(short_path, short_path_size, long_path);
+ return false;
+ }
+
+ return true;
+}
+
+// Kill the specified process
+bool MsKillProcess(UINT id)
+{
+ HANDLE h;
+ // Validate arguments
+ if (id == 0)
+ {
+ return false;
+ }
+
+ h = OpenProcess(PROCESS_TERMINATE, FALSE, id);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ if (TerminateProcess(h, 0) == FALSE)
+ {
+ CloseHandle(h);
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Get the current EXE file name
+void MsGetCurrentProcessExeName(char *name, UINT size)
+{
+ UINT id;
+ LIST *o;
+ MS_PROCESS *p;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ id = MsGetCurrentProcessId();
+ o = MsGetProcessList();
+ p = MsSearchProcessById(o, id);
+ if (p != NULL)
+ {
+ p = MsSearchProcessById(o, id);
+ StrCpy(name, size, p->ExeFilename);
+ }
+ else
+ {
+ StrCpy(name, size, MsGetExeFileName());
+ }
+ MsFreeProcessList(o);
+}
+void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size)
+{
+ UINT id;
+ LIST *o;
+ MS_PROCESS *p;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ id = MsGetCurrentProcessId();
+ o = MsGetProcessList();
+ p = MsSearchProcessById(o, id);
+ if (p != NULL)
+ {
+ p = MsSearchProcessById(o, id);
+ UniStrCpy(name, size, p->ExeFilenameW);
+ }
+ else
+ {
+ UniStrCpy(name, size, MsGetExeFileNameW());
+ }
+ MsFreeProcessList(o);
+}
+
+// Search the process by the process ID
+MS_PROCESS *MsSearchProcessById(LIST *o, UINT id)
+{
+ MS_PROCESS *p, t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.ProcessId = id;
+
+ p = Search(o, &t);
+
+ return p;
+}
+
+// Compare the Process List items
+int MsCompareProcessList(void *p1, void *p2)
+{
+ MS_PROCESS *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(MS_PROCESS **)p1;
+ e2 = *(MS_PROCESS **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->ProcessId > e2->ProcessId)
+ {
+ return 1;
+ }
+ else if (e1->ProcessId < e2->ProcessId)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Display the process list
+void MsPrintProcessList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ UniPrint(L"%-4u: %s\n", p->ProcessId, p->ExeFilenameW);
+ }
+}
+
+// Release of the process list
+void MsFreeProcessList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Get the Process List (for WinNT)
+LIST *MsGetProcessListNt()
+{
+ LIST *o;
+ UINT max = 16384;
+ DWORD *processes;
+ UINT needed, num;
+ UINT i;
+
+ o = NewListFast(MsCompareProcessList);
+
+ if (ms->nt->EnumProcesses == NULL)
+ {
+ return o;
+ }
+
+ processes = ZeroMalloc(sizeof(DWORD) * max);
+
+ if (ms->nt->EnumProcesses(processes, sizeof(DWORD) * max, &needed) == FALSE)
+ {
+ Free(processes);
+ return NULL;
+ }
+
+ num = needed / sizeof(DWORD);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT id = processes[i];
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ false, id);
+
+ if (h != NULL)
+ {
+ HINSTANCE hInst = NULL;
+ DWORD needed;
+ char exe[MAX_SIZE];
+ wchar_t exe_w[MAX_SIZE];
+ bool ok = false;
+ DWORD sz1, sz2;
+
+ sz1 = sizeof(exe) - 1;
+ sz2 = sizeof(exe_w) / sizeof(wchar_t) - 1;
+
+ if (ms->nt->EnumProcessModules(h, &hInst, sizeof(hInst), &needed) == false)
+ {
+ hInst = NULL;
+ }
+
+ if (ms->nt->GetModuleFileNameExA(h, hInst, exe, sizeof(exe) - 1) &&
+ ms->nt->GetModuleFileNameExW(h, hInst, exe_w, sizeof(exe_w) / sizeof(wchar_t) - 1))
+ {
+ ok = true;
+ }
+ else if (ms->nt->QueryFullProcessImageNameA != NULL &&
+ ms->nt->QueryFullProcessImageNameW != NULL &&
+ ms->nt->QueryFullProcessImageNameA(h, 0, exe, &sz1) &&
+ ms->nt->QueryFullProcessImageNameW(h, 0, exe_w, &sz2))
+ {
+ ok = true;
+ }
+
+ if (ok)
+ {
+ MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
+
+ StrCpy(p->ExeFilename, sizeof(p->ExeFilename), exe);
+ UniStrCpy(p->ExeFilenameW, sizeof(p->ExeFilenameW), exe_w);
+ p->ProcessId = id;
+
+ Add(o, p);
+ }
+
+ CloseHandle(h);
+ }
+ }
+
+ Sort(o);
+
+ Free(processes);
+
+ return o;
+}
+
+// Get the Process List (for Win9x)
+LIST *MsGetProcessList9x()
+{
+ HANDLE h;
+ LIST *o;
+ HANDLE (WINAPI *CreateToolhelp32Snapshot)(DWORD, DWORD);
+ BOOL (WINAPI *Process32First)(HANDLE, LPPROCESSENTRY32);
+ BOOL (WINAPI *Process32Next)(HANDLE, LPPROCESSENTRY32);
+
+ CreateToolhelp32Snapshot =
+ (HANDLE (__stdcall *)(DWORD,DWORD))
+ GetProcAddress(ms->hKernel32, "CreateToolhelp32Snapshot");
+ Process32First =
+ (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress(ms->hKernel32, "Process32First");
+ Process32Next =
+ (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress(ms->hKernel32, "Process32Next");
+
+ o = NewListFast(MsCompareProcessList);
+
+ if (CreateToolhelp32Snapshot != NULL && Process32First != NULL && Process32Next != NULL)
+ {
+ h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ PROCESSENTRY32 e;
+ Zero(&e, sizeof(e));
+ e.dwSize = sizeof(e);
+
+ if (Process32First(h, &e))
+ {
+ while (true)
+ {
+ MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
+ StrCpy(p->ExeFilename, sizeof(p->ExeFilename), e.szExeFile);
+ StrToUni(p->ExeFilenameW, sizeof(p->ExeFilenameW), p->ExeFilename);
+ p->ProcessId = e.th32ProcessID;
+ Add(o, p);
+ if (Process32Next(h, &e) == false)
+ {
+ break;
+ }
+ }
+ }
+ CloseHandle(h);
+ }
+ }
+
+ Sort(o);
+
+ return o;
+}
+
+// Get the Process List
+LIST *MsGetProcessList()
+{
+ if (MsIsNt() == false)
+ {
+ // Windows 9x
+ return MsGetProcessList9x();
+ }
+ else
+ {
+ // Windows NT, 2000, XP
+ return MsGetProcessListNt();
+ }
+}
+
+// Force to run the current thread on a single CPU
+void MsSetThreadSingleCpu()
+{
+ SetThreadAffinityMask(GetCurrentThread(), 1);
+}
+
+// Playback of sound
+void MsPlaySound(char *name)
+{
+ char tmp[MAX_SIZE];
+ char wav[MAX_SIZE];
+ char *temp;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), "|%s", name);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ temp = MsGetMyTempDir();
+ Format(wav, sizeof(tmp), "%s\\%s", temp, name);
+ DumpBuf(b, wav);
+
+ PlaySound(wav, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT);
+
+ FreeBuf(b);
+}
+
+// Show an icon in the task tray
+bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg)
+{
+ bool ret = true;
+ // Validate arguments
+ if (hWnd == NULL || icon == NULL)
+ {
+ return true;
+ }
+
+ if (MsIsNt() == false)
+ {
+ Zero(&nid, sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hWnd;
+ nid.uID = 1;
+ nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
+ nid.uCallbackMessage = msg;
+ nid.hIcon = icon;
+ UniToStr(nid.szTip, sizeof(nid.szTip), tooltip);
+ ret = Shell_NotifyIcon(NIM_ADD, &nid);
+ }
+ else
+ {
+ Zero(&nid_nt, sizeof(nid_nt));
+ nid_nt.cbSize = sizeof(nid_nt);
+ nid_nt.hWnd = hWnd;
+ nid_nt.uID = 1;
+ nid_nt.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
+ nid_nt.uCallbackMessage = msg;
+ nid_nt.hIcon = icon;
+ UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tooltip);
+
+ ret = Shell_NotifyIconW(NIM_ADD, &nid_nt);
+ }
+
+ tray_inited = true;
+
+ return ret;
+}
+
+// Check whether the task tray has been initialized
+bool MsIsTrayInited()
+{
+ return tray_inited;
+}
+
+// Restore the icon in the task tray
+void MsRestoreIconOnTray()
+{
+ if (tray_inited == false)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ Shell_NotifyIcon(NIM_ADD, &nid);
+ }
+ else
+ {
+ Shell_NotifyIconW(NIM_ADD, &nid_nt);
+ }
+}
+
+// Change the icon in the task tray (go over!)
+void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags)
+{
+ MsChangeIconOnTrayEx((HICON)icon, tooltip, info_title, info, info_flags, false);
+}
+
+// Change the icon in the task tray
+void MsChangeIconOnTray(HICON icon, wchar_t *tooltip)
+{
+ MsChangeIconOnTrayEx(icon, tooltip, NULL, NULL, NIIF_NONE, false);
+}
+bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add)
+{
+ bool changed = false;
+ bool ret = true;
+
+ if (tray_inited == false)
+ {
+ return ret;
+ }
+
+ if (icon != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ if (nid.hIcon != icon)
+ {
+ changed = true;
+ nid.hIcon = icon;
+ }
+ }
+ else
+ {
+ if (nid_nt.hIcon != icon)
+ {
+ changed = true;
+ nid_nt.hIcon = icon;
+ }
+ }
+ }
+
+ if (tooltip != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ char tmp[MAX_SIZE];
+
+ UniToStr(tmp, sizeof(tmp), tooltip);
+
+ if (StrCmp(nid.szTip, tmp) != 0)
+ {
+ StrCpy(nid.szTip, sizeof(nid.szTip), tmp);
+ changed = true;
+ }
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniStrCpy(tmp, sizeof(tmp), tooltip);
+
+ if (UniStrCmp(nid_nt.szTip, tmp) != 0)
+ {
+ UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tmp);
+ changed = true;
+ }
+ }
+ }
+
+ if (info_title != NULL && info != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_PATH];
+
+ UniToStr(tmp1, sizeof(tmp1), info_title);
+ UniToStr(tmp2, sizeof(tmp2), info);
+
+ if (StrCmp(nid.szInfo, tmp1) != 0 ||
+ StrCmp(nid.szInfoTitle, tmp2) != 0)
+ {
+ StrCpy(nid.szInfo, sizeof(nid.szInfo), tmp1);
+ StrCpy(nid.szInfoTitle, sizeof(nid.szInfoTitle), tmp2);
+ nid.dwInfoFlags = info_flags;
+
+ changed = true;
+ }
+ }
+ else
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_PATH];
+
+ UniStrCpy(tmp1, sizeof(tmp1), info_title);
+ UniStrCpy(tmp2, sizeof(tmp2), info);
+
+ if (UniStrCmp(nid_nt.szInfo, tmp1) != 0 ||
+ UniStrCmp(nid_nt.szInfoTitle, tmp2) != 0)
+ {
+ UniStrCpy(nid_nt.szInfo, sizeof(nid_nt.szInfo), tmp1);
+ UniStrCpy(nid_nt.szInfoTitle, sizeof(nid_nt.szInfoTitle), tmp2);
+ nid_nt.dwInfoFlags = info_flags;
+
+ changed = true;
+ }
+ }
+ }
+
+ if (changed || add)
+ {
+ UINT op = (add ? NIM_ADD : NIM_MODIFY);
+ if (MsIsNt() == false)
+ {
+ ret = Shell_NotifyIcon(op, &nid);
+ }
+ else
+ {
+ ret = Shell_NotifyIconW(op, &nid_nt);
+ }
+ }
+
+ return ret;
+}
+
+// Remove the icon in the task tray
+void MsHideIconOnTray()
+{
+ if (MsIsNt() == false)
+ {
+ Shell_NotifyIcon(NIM_DELETE, &nid);
+ }
+ else
+ {
+ Shell_NotifyIconW(NIM_DELETE, &nid_nt);
+ }
+
+ tray_inited = false;
+}
+
+// Insert a menu item
+bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item)
+{
+ bool ret;
+
+ if (MsIsNt())
+ {
+ ret = InsertMenuW(hMenu, pos, flags, id_new_item, lp_new_item);
+ }
+ else
+ {
+ char *s = CopyUniToStr(lp_new_item);
+ ret = InsertMenuA(hMenu, pos, flags, id_new_item, s);
+ Free(s);
+ }
+
+ return ret;
+}
+
+// Adding a menu item
+bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str)
+{
+ bool ret;
+
+ if (MsIsNt())
+ {
+ ret = AppendMenuW(hMenu, flags, id, str);
+ }
+ else
+ {
+ char *s = CopyUniToStr(str);
+ ret = AppendMenuA(hMenu, flags, id, s);
+ Free(s);
+ }
+
+ return ret;
+}
+
+// Display the menu
+void MsUserModeTrayMenu(HWND hWnd)
+{
+ HMENU h;
+ POINT p;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t caption[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Create a menu
+ h = CreatePopupMenu();
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, 10001, _UU("SVC_USERMODE_MENU_1"));
+ MsAppendMenu(h, MF_SEPARATOR, 10002, NULL);
+
+ if (MsIsNt())
+ {
+ GetWindowTextW(hWnd, caption, sizeof(caption));
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ GetWindowTextA(hWnd, tmp, sizeof(tmp));
+ StrToUni(caption, sizeof(caption), tmp);
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("SVC_USERMODE_MENU_2"), caption);
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, 10003, tmp);
+
+ // Display the menu
+ GetCursorPos(&p);
+
+ SetForegroundWindow(hWnd);
+ TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
+ PostMessage(hWnd, WM_NULL, 0, 0);
+
+ DestroyMenu(h);
+}
+
+// Window procedure for the user mode
+LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ wchar_t tmp[MAX_SIZE];
+ char title[MAX_SIZE];
+ wchar_t title_w[MAX_SIZE];
+ char value_name[MAX_SIZE];
+ static UINT taskbar_msg = 0;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ if (msg == taskbar_msg && taskbar_msg != 0)
+ {
+ // The taskbar was regenerated
+ if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
+ service_for_9x_mode == false)
+ {
+ MsRestoreIconOnTray();
+ }
+ }
+
+ switch (msg)
+ {
+ case WM_ENDSESSION:
+ // Resume
+ if (wParam == false)
+ {
+ break;
+ }
+ case WM_CREATE:
+ // Start
+ exiting = false;
+ g_start();
+ GetWindowText(hWnd, title, sizeof(title));
+ StrToUni(title_w, sizeof(title_w), title);
+ UniFormat(tmp, sizeof(tmp), _UU("SVC_TRAY_TOOLTIP"), title);
+
+ if (taskbar_msg == 0)
+ {
+ taskbar_msg = RegisterWindowMessage("TaskbarCreated");
+ }
+
+ Format(value_name, sizeof(value_name), SVC_HIDETRAY_REG_VALUE, title_w);
+ if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
+ service_for_9x_mode == false)
+ {
+ MsShowIconOnTray(hWnd, tray_icon, tmp, WM_APP + 33);
+ }
+
+ break;
+ case WM_APP + 33:
+ if (wParam == 1)
+ {
+ // The operation to the icon in the task tray
+ switch (lParam)
+ {
+ case WM_RBUTTONDOWN:
+ // Right click
+ MsUserModeTrayMenu(hWnd);
+ break;
+ case WM_LBUTTONDBLCLK:
+ // Left double-click
+ break;
+ }
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ MsUserModeTrayMenu(hWnd);
+ break;
+ case WM_QUERYENDSESSION:
+ if (exiting == false)
+ {
+ exiting = true;
+ MsHideIconOnTray();
+ g_stop();
+ DestroyWindow(hWnd);
+ }
+ return TRUE;
+ case WM_CLOSE:
+ // Stop
+ if (exiting == false)
+ {
+ exiting = true;
+ g_stop();
+ MsHideIconOnTray();
+ DestroyWindow(hWnd);
+ }
+ break;
+ case WM_DESTROY:
+ wnd_end = true;
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case 10001:
+ GetWindowText(hWnd, title, sizeof(title));
+ StrToUni(title_w, sizeof(title_w), title);
+ // Display a confirmation message
+ if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2 |
+ MB_SYSTEMMODAL, _UU("SVC_HIDE_TRAY_MSG"), title, title) == IDOK)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, title_w);
+ // Write to the registry
+ MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
+ // Hide the icon
+ MsHideIconOnTray();
+ }
+ break;
+ case 10003:
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+// Get the name of PenCore.dll
+char *MsGetPenCoreDllFileName()
+{
+ /*if (Is64())
+ {
+ if (IsX64())
+ {
+ return PENCORE_DLL_NAME_X64;
+ }
+ else
+ {
+ return PENCORE_DLL_NAME_IA64;
+ }
+ }
+ else*/
+ {
+ return PENCORE_DLL_NAME;
+ }
+}
+
+// Get whether this instance is in user mode
+bool MsIsUserMode()
+{
+ return is_usermode;
+}
+
+// Command to terminate the user-mode from the service side
+void MsStopUserModeFromService()
+{
+ if (hWndUsermode != NULL)
+ {
+ PostMessage(hWndUsermode, WM_CLOSE, 0, 0);
+ }
+}
+
+// Only run the test (for debugging)
+void MsTestOnly()
+{
+ g_start();
+ GetLine(NULL, 0);
+ g_stop();
+
+ _exit(0);
+}
+
+// Stop the user-mode service
+void MsStopUserModeSvc(char *svc_name)
+{
+ void *p;
+ // Validate arguments
+ if (svc_name == NULL)
+ {
+ return;
+ }
+
+ p = MsCreateUserModeSvcGlocalPulse(svc_name);
+ if (p == NULL)
+ {
+ return;
+ }
+
+ MsSendGlobalPulse(p);
+
+ MsCloseGlobalPulse(p);
+}
+
+// Creating a global pulse for user-mode service
+void *MsCreateUserModeSvcGlocalPulse(char *svc_name)
+{
+ char name[MAX_SIZE];
+ // Validate arguments
+ if (svc_name == NULL)
+ {
+ return NULL;
+ }
+
+ MsGenerateUserModeSvcGlobalPulseName(name, sizeof(name), svc_name);
+
+ return MsOpenOrCreateGlobalPulse(name);
+}
+
+// Get the global pulse name for the user-mode service
+void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name)
+{
+ wchar_t tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL || svc_name == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"usersvc_%S_@_%s", svc_name, MsGetUserNameW());
+
+ UniTrim(tmp);
+ UniStrUpper(tmp);
+
+ HashSha1(hash, tmp, UniStrLen(tmp) * sizeof(wchar_t));
+
+ BinToStr(name, size, hash, sizeof(hash));
+}
+
+// Start in user mode
+void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
+{
+ wchar_t *title_w = CopyStrToUni(title);
+
+ MsUserModeW(title_w, start, stop, icon);
+
+ Free(title_w);
+}
+void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
+{
+ WNDCLASS wc;
+ HINSTANCE hDll;
+ HWND hWnd;
+ MSG msg;
+ INSTANCE *inst;
+ char title_a[MAX_PATH];
+ MS_USERMODE_SVC_PULSE_THREAD_PARAM p;
+ THREAD *recv_thread = NULL;
+ // Validate arguments
+ if (title == NULL || start == NULL || stop == NULL)
+ {
+ return;
+ }
+
+ UniToStr(title_a, sizeof(title_a), title);
+
+ is_usermode = true;
+ g_start = start;
+ g_stop = stop;
+
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ if (service_for_9x_mode == false)
+ {
+ // Do not display an error if Win9x service mode
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_USERMODE_MUTEX"), ms->ExeFileNameW);
+ }
+ return;
+ }
+
+ if (Is64())
+ {
+ hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName());
+ }
+ else
+ {
+ hDll = MsLoadLibrary(MsGetPenCoreDllFileName());
+ }
+
+ // Read icon
+ tray_icon = LoadImage(hDll, MAKEINTRESOURCE(icon), IMAGE_ICON, 16, 16,
+ (MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR);
+
+ // Creating the main window
+ Zero(&wc, sizeof(wc));
+ wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hIcon = LoadIcon(hDll, MAKEINTRESOURCE(icon));
+ wc.hInstance = ms->hInst;
+ wc.lpfnWndProc = MsUserModeWindowProc;
+ wc.lpszClassName = title_a;
+ if (RegisterClass(&wc) == 0)
+ {
+ return;
+ }
+
+ hWnd = CreateWindow(title_a, title_a, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, ms->hInst, NULL);
+
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ p.hWnd = hWnd;
+ p.GlobalPulse = MsCreateUserModeSvcGlocalPulse(g_service_name);
+
+ if (p.GlobalPulse != NULL)
+ {
+ // Start the global pulse monitoring thread for termination
+ p.Halt = false;
+
+ recv_thread = NewThread(MsUserModeGlobalPulseRecvThread, &p);
+ }
+
+ hWndUsermode = hWnd;
+
+ wnd_end = false;
+ // Window loop
+ while (wnd_end == false)
+ {
+ GetMessage(&msg, NULL, 0, 0);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ FreeSingleInstance(inst);
+
+ p.hWnd = NULL;
+
+ hWndUsermode = NULL;
+
+ if (p.GlobalPulse != NULL)
+ {
+ // Terminate the monitoring thread of termination global pulse
+ p.Halt = true;
+ MsSendGlobalPulse(p.GlobalPulse);
+
+ WaitThread(recv_thread, INFINITE);
+ ReleaseThread(recv_thread);
+
+ MsCloseGlobalPulse(p.GlobalPulse);
+ }
+
+ // Might abort
+ _exit(0);
+}
+
+// The thread that wait for global pulse to stop the user mode service
+void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param)
+{
+ MS_USERMODE_SVC_PULSE_THREAD_PARAM *p = (MS_USERMODE_SVC_PULSE_THREAD_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ while (p->Halt == false)
+ {
+ if (MsWaitForGlobalPulse(p->GlobalPulse, INFINITE))
+ {
+ break;
+ }
+ }
+
+ if (p->hWnd != NULL)
+ {
+ PostMessageA(p->hWnd, WM_CLOSE, 0, 0);
+ }
+}
+
+// Service stopping procedure main thread
+void MsServiceStoperMainThread(THREAD *t, void *p)
+{
+ // Stopping procedure
+ g_stop();
+}
+
+// Service stop procedure
+bool MsServiceStopProc()
+{
+ THREAD *thread;
+ bool ret = true;
+ UINT64 selfkill_timeout = Tick64() + SVC_SELFKILL_TIMEOUT;
+
+ thread = NewThread(MsServiceStoperMainThread, NULL);
+
+ while (WaitThread(thread, 250) == false)
+ {
+ if (Tick64() >= selfkill_timeout)
+ {
+ // Suicide when it freezes
+ ret = false;
+ break;
+ }
+ // During stopping procedure to complete, call the SetServiceStatus periodically
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 100000;
+ status.dwCheckPoint++;
+ status.dwCurrentState = SERVICE_STOP_PENDING;
+ _SetServiceStatus(ssh, &status);
+ }
+
+ // Report that the stopping is complete
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 0;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_STOPPED;
+ _SetServiceStatus(ssh, &status);
+
+ if (ret == false)
+ {
+ // Force termination here if this has committed suicide
+ _exit(-1);
+ }
+ else
+ {
+ ReleaseThread(thread);
+ }
+
+ return ret;
+}
+
+// Service handler
+void CALLBACK MsServiceHandler(DWORD opcode)
+{
+ switch (opcode)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ // Stopping request
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 100000;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_STOP_PENDING;
+
+ // Set the stopping event
+ if (service_stop_event != NULL)
+ {
+ SetEvent(service_stop_event);
+ }
+ break;
+ }
+
+ _SetServiceStatus(ssh, &status);
+}
+
+// Dispatch function of the service
+void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv)
+{
+ // Creating a stopping event
+ service_stop_event = CreateEventA(NULL, true, false, NULL);
+
+ // Preparing for the service
+ Zero(&status, sizeof(status));
+ status.dwServiceType = SERVICE_WIN32;
+ status.dwCurrentState = SERVICE_START_PENDING;
+ status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+
+ ssh = _RegisterServiceCtrlHandler(g_service_name, MsServiceHandler);
+
+ if (ssh == NULL)
+ {
+ MessageBox(NULL, "RegisterServiceCtrlHandler() Failed.", "MsServiceDispatcher()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ return;
+ }
+
+ status.dwWaitHint = 300000;
+ status.dwCheckPoint = 0;
+ status.dwCheckPoint++;
+ status.dwCurrentState = SERVICE_START_PENDING;
+ _SetServiceStatus(ssh, &status);
+
+ // Report the start completion
+ status.dwWaitHint = 0;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_RUNNING;
+ _SetServiceStatus(ssh, &status);
+
+ //// Initialization
+ // Start of the Mayaqua
+ InitMayaqua(false, false, 0, NULL);
+
+ // Stop the MS-IME
+ MsDisableIme();
+
+ // Service operation start
+ g_start();
+ MsUpdateServiceConfig(g_service_name);
+
+ // Wait for the stopping event to be signaled state
+ WaitForSingleObject(service_stop_event, INFINITE);
+
+ // Service operation stop
+ MsServiceStopProc();
+}
+
+// Start as a test mode
+void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ wchar_t *title_w = CopyStrToUni(title);
+
+ MsTestModeW(title_w, start, stop);
+ Free(title_w);
+}
+void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ INSTANCE *inst;
+ // Validate arguments
+ if (title == NULL || start == NULL || stop == NULL)
+ {
+ return;
+ }
+
+ is_usermode = true;
+
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ // Already started
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_TEST_MUTEX"), ms->ExeFileNameW);
+ return;
+ }
+
+ // Start
+ start();
+
+ // Display the message
+ MsgBoxEx(NULL, MB_ICONINFORMATION | MB_SYSTEMMODAL, _UU("SVC_TEST_MSG"), title);
+
+ // Stop
+ stop();
+
+ FreeSingleInstance(inst);
+}
+
+// Write the process ID of the process which is calling the service manager
+void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid)
+{
+ char tmp[MAX_PATH];
+
+ Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
+
+ if (pid != 0)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
+ MsRegWriteInt(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
+ }
+ else
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+ MsRegDeleteKey(REG_LOCAL_MACHINE, tmp);
+
+ MsRegDeleteValue(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+ MsRegDeleteKey(REG_CURRENT_USER, tmp);
+ }
+}
+
+// Get the process ID of the process which is calling the service manager
+UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (svcname == NULL)
+ {
+ return 0;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
+
+ return MsRegReadInt(current_user ? REG_CURRENT_USER : REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+}
+
+// Dispatch function of the service
+void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv)
+{
+}
+
+// Service main function
+UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line)
+{
+ UINT mode;
+ UINT ret = 0;
+ char *arg;
+ wchar_t *arg_w;
+ TOKEN_LIST *t = NULL;
+ UNI_TOKEN_LIST *ut = NULL;
+ char *service_name;
+ wchar_t *service_title;
+ wchar_t *service_description;
+ wchar_t *service_title_uni;
+ char tmp[MAX_SIZE];
+ bool restoreReg = false;
+ bool silent = false;
+ bool is_win32_service_mode = false;
+ // Validate arguments
+ if (name == NULL || start == NULL || stop == NULL)
+ {
+ return ret;
+ }
+
+ g_start = start;
+ g_stop = stop;
+ StrCpy(g_service_name, sizeof(g_service_name), name);
+ StrLower(g_service_name);
+
+ // Determine whether it's in Win32 service mode
+ if (cmd_line != NULL && lstrcmpiA(cmd_line, SVC_ARG_SERVICE) == 0)
+ {
+ HINSTANCE h_advapi32 = LoadLibraryA("advapi32.dll");
+
+ if (h_advapi32 != NULL)
+ {
+ // Check whether there is the SCM in the service mode
+ _StartServiceCtrlDispatcher =
+ (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
+ GetProcAddress(h_advapi32, "StartServiceCtrlDispatcherW");
+
+ _RegisterServiceCtrlHandler =
+ (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
+ GetProcAddress(h_advapi32, "RegisterServiceCtrlHandlerW");
+
+ _SetServiceStatus =
+ (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(h_advapi32, "SetServiceStatus");
+
+ if (_StartServiceCtrlDispatcher != NULL &&
+ _RegisterServiceCtrlHandler != NULL &&
+ _SetServiceStatus != NULL)
+ {
+ is_win32_service_mode = true;
+ }
+ }
+ }
+
+ // Run the service using the SCM in the case of Win32 service mode
+ if (is_win32_service_mode)
+ {
+ SERVICE_TABLE_ENTRY dispatch_table[] =
+ {
+ {"", MsServiceDispatcher},
+ {NULL, NULL},
+ };
+
+ MsSetErrorModeToSilent();
+
+ if (_StartServiceCtrlDispatcher(dispatch_table) == false)
+ {
+ MessageBox(NULL, "StartServiceCtrlDispatcher() Failed.", "MsServiceMode()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+ else
+ {
+ MsUpdateServiceConfig(g_service_name);
+ }
+
+ // Abort here in the case of using the SCM
+ _exit(0);
+ return 0;
+ }
+
+ // Start of the Mayaqua
+ InitMayaqua(false, false, 0, NULL);
+
+ // Stop the MS-IME
+ MsDisableIme();
+
+ // Get the information about the service from the string table
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ service_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ service_title = _UU(tmp);
+ service_title_uni = _UU(tmp);
+ Format(tmp, sizeof(tmp), SVC_DESCRIPT, name);
+ service_description = _UU(tmp);
+
+ if (StrLen(service_name) == 0 || UniStrLen(service_title) == 0)
+ {
+ // The service information isn't found
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_NOT_FOUND"), name);
+ }
+ else
+ {
+ wchar_t path[MAX_SIZE];
+ // Check the argument
+ mode = SVC_MODE_NONE;
+
+ t = GetCommandLineToken();
+ arg = NULL;
+
+ ut = GetCommandLineUniToken();
+ arg_w = NULL;
+
+ if (t->NumTokens >= 1)
+ {
+ arg = t->Token[0];
+ }
+ if(t->NumTokens >= 2)
+ {
+ if(StrCmpi(t->Token[1], SVC_ARG_SILENT) == 0)
+ {
+ silent = true;
+ }
+ }
+
+ if (ut->NumTokens >= 1)
+ {
+ arg_w = ut->Token[0];
+ }
+
+ if (arg != NULL)
+ {
+ if (StrCmpi(arg, SVC_ARG_INSTALL) == 0)
+ {
+ mode = SVC_MODE_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_START) == 0)
+ {
+ mode = SVC_MODE_START;
+ }
+ if (StrCmpi(arg, SVC_ARG_STOP) == 0)
+ {
+ mode = SVC_MODE_STOP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TEST) == 0)
+ {
+ mode = SVC_MODE_TEST;
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE) == 0)
+ {
+ mode = SVC_MODE_USERMODE;
+ }
+ if (StrCmpi(arg, SVC_ARG_SETUP_INSTALL) == 0)
+ {
+ mode = SVC_MODE_SETUP_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_SETUP_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_SETUP_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_SERVICE) == 0)
+ {
+ mode = SVC_MODE_WIN9X_SERVICE;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_INSTALL) == 0)
+ {
+ mode = SVC_MODE_WIN9X_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_WIN9X_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP) == 0)
+ {
+ mode = SVC_MODE_TCP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP_UAC) == 0)
+ {
+ mode = SVC_MODE_TCP_UAC;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP_SETUP) == 0)
+ {
+ mode = SVC_MODE_TCPSETUP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TRAFFIC) == 0)
+ {
+ mode = SVC_MODE_TRAFFIC;
+ }
+ if (StrCmpi(arg, SVC_ARG_UIHELP) == 0)
+ {
+ mode = SVC_MODE_UIHELP;
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE_SHOWTRAY) == 0)
+ {
+ char tmp[MAX_SIZE];
+ mode = SVC_MODE_USERMODE;
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
+ MsRegDeleteValue(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp);
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE_HIDETRAY) == 0)
+ {
+ char tmp[MAX_SIZE];
+ mode = SVC_MODE_USERMODE;
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
+ MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
+ }
+ if (StrCmpi(arg, SVC_ARG_SERVICE) == 0)
+ {
+ mode = SVC_MODE_SERVICE;
+ }
+
+ if (mode != SVC_MODE_NONE)
+ {
+ // Network Config
+ MsInitGlobalNetworkConfig();
+ }
+ }
+
+ // Get the command-line name when running as a service
+ UniFormat(path, sizeof(path), SVC_RUN_COMMANDLINE, ms->ExeFileNameW);
+
+ if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
+ mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
+ (ms->IsNt == false))
+ {
+ // Tried to use the command for the NT in non-WindowsNT system
+ MsgBox(NULL, MB_ICONSTOP, _UU("SVC_NT_ONLY"));
+ }
+ else if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
+ mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
+ (ms->IsAdmin == false))
+ {
+ // Do not have Administrators privillage
+ MsgBox(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_ADMIN"));
+ }
+ else
+ {
+ // Performs processing depend on mode
+ switch (mode)
+ {
+ case SVC_MODE_NONE:
+ // Exit by showing a guidance message
+ if (arg_w != NULL && UniEndWith(arg_w, L".vpn"))
+ {
+ if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO, _UU("CM_VPN_FILE_CLICKED")) == IDYES)
+ {
+ wchar_t vpncmgr[MAX_PATH];
+ wchar_t filename[MAX_PATH];
+
+ UniFormat(filename, sizeof(filename), L"\"%s\"", arg_w);
+
+ if (Is64() == false)
+ {
+ UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr.exe", MsGetExeDirNameW());
+ }
+ else
+ {
+ UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr_x64.exe", MsGetExeDirNameW());
+ }
+
+ RunW(vpncmgr, filename, false, false);
+ }
+ }
+ else
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_HELP"),
+ service_title, service_name, service_title, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_title);
+ }
+ break;
+
+ case SVC_MODE_SETUP_INSTALL:
+ // Setup.exe installation mode
+ // Uninstall the old version
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ if (MsIsServiceRunning(service_name))
+ {
+ MsStopService(service_name);
+ }
+ MsUninstallService(service_name);
+ }
+ if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
+ {
+ ret = 1;
+ }
+ MsStartService(service_name);
+ MsWriteCallingServiceManagerProcessId(service_name, 0);
+ break;
+
+ case SVC_MODE_SETUP_UNINSTALL:
+ // Setup.exe uninstall mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ if (MsIsServiceRunning(service_name))
+ {
+ MsStopService(service_name);
+ }
+ if (MsUninstallService(service_name) == false)
+ {
+ ret = 1;
+ }
+ }
+ break;
+
+ case SVC_MODE_INSTALL:
+ // Install the service
+ // Check whether it is already installed
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ // Already installed
+ // Show a message asking if you want to uninstall
+ if(silent == true)
+ {
+ // Always cancel the operation
+ break;
+ }
+ if (MsgBoxEx(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SVC_ALREADY_INSTALLED"),
+ service_title, service_name) == IDNO)
+ {
+ // Cancel the operation
+ break;
+ }
+ else
+ {
+ // Whether the existing service is working?
+ if (MsIsServiceRunning(service_name))
+ {
+ // Try to stop
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+ // Uninstall
+ if (MsUninstallService(service_name) == false)
+ {
+ // Failed to uninstall
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+ }
+
+ // Do the installation
+ if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
+ {
+ // Failed to install
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_INSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Start the service
+ if (MsStartService(service_name) == false)
+ {
+ // Failed to start
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_INSTALL_FAILED_2"),
+ service_title, service_name, path);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_INSTALL_OK"),
+ service_title, service_name, path);
+ }
+ break;
+
+ case SVC_MODE_UNINSTALL:
+ // Uninstall the service
+ // Check whether it is already installed
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name, path);
+ }
+ break;
+ }
+
+ // If the service is currently running, stop it
+ if (MsIsServiceRunning(service_name))
+ {
+ // Stop the service
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+
+ // Uninstall the service
+ if (MsUninstallService(service_name) == false)
+ {
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_UNINSTALL_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_START:
+ // Start the service
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ // Service is not installed
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Confirm whether the service is running
+ if (MsIsServiceRunning(service_name))
+ {
+ // Service is running
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVR_ALREADY_START"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Start the service
+ if (MsStartService(service_name) == false)
+ {
+ // Failed to start
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_START_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_START_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_STOP:
+ // Stop the service
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ // Service is not installed
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Confirm whether the service is running
+ if (MsIsServiceRunning(service_name) == false)
+ {
+ // The service is stopped
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_ALREADY_STOP"),
+ service_title, service_name);
+ }
+ break;
+ }
+ // Stop the service
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_STOP_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_TEST:
+ // Test mode
+ MsTestModeW(service_title, start, stop);
+ break;
+
+ case SVC_MODE_WIN9X_SERVICE:
+ // Win9x service mode (hide icon in the task tray unconditionally)
+ if (MsIsNt())
+ {
+ // Don't do this on Windows 2000 or later
+ break;
+ }
+ service_for_9x_mode = true;
+ // Not a oblivion to break
+ case SVC_MODE_USERMODE:
+ // User mode
+ MsUserModeW(service_title, start, stop, icon);
+ break;
+
+ case SVC_MODE_WIN9X_INSTALL:
+ // Win9x installation mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsNt() == false)
+ {
+ // Adding a registry key
+ char cmdline[MAX_PATH];
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s",
+ MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE);
+ MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
+ name, cmdline);
+ MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
+ name, cmdline);
+
+ // Start
+ //Run(MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE, false, false);
+ }
+ break;
+
+ case SVC_MODE_WIN9X_UNINSTALL:
+ // Win9x uninstall mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsNt() == false)
+ {
+ // Delete the registry key
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
+ name);
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
+ name);
+
+ // Terminate all the processes of PacketiX VPN Client other than itself
+ MsKillOtherInstance();
+ }
+ break;
+
+ case SVC_MODE_SERVICE:
+ // Run as a service
+ // Obsolated (2012.12.31) (Do this in the above code)
+ //MsServiceMode(start, stop);
+ break;
+
+ case SVC_MODE_TCP:
+ case SVC_MODE_TCP_UAC:
+ // TCP Utility
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+
+ if (MsIsVista() && MsIsAdmin() == false && mode != SVC_MODE_TCP_UAC)
+ {
+ void *handle = NULL;
+ if (MsExecuteEx2W(ms->ExeFileNameW, SVC_ARG_TCP_UAC_W, &handle, true) == false)
+ {
+ ShowTcpIpConfigUtil(NULL, true);
+ }
+ else
+ {
+ MsWaitProcessExit(handle);
+ }
+ }
+ else
+ {
+ ShowTcpIpConfigUtil(NULL, true);
+ }
+
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_TCPSETUP:
+ // TCP optimization mode (This is called by the installer)
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+
+ if (MsIsVista() && MsIsAdmin() == false)
+ {
+ void *handle = NULL;
+ if (MsExecuteEx2W(ms->ExeFileNameW, arg_w, &handle, true) == false)
+ {
+ ShowTcpIpConfigUtil(NULL, false);
+ }
+ else
+ {
+ MsWaitProcessExit(handle);
+ }
+ }
+ else
+ {
+ ShowTcpIpConfigUtil(NULL, false);
+ }
+
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_TRAFFIC:
+ // Communication throughput measurement tool
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+ CmTraffic(NULL);
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_UIHELP:
+ // Starting the UI Helper
+ CnStart();
+ break;
+ }
+
+ }
+ FreeToken(t);
+ UniFreeToken(ut);
+
+ if (restoreReg)
+ {
+ MsWriteCallingServiceManagerProcessId(service_name, 0);
+ }
+ }
+
+ FreeMayaqua();
+
+ return 0;
+}
+
+// Get the user name of the specified session
+wchar_t *MsGetSessionUserName(UINT session_id)
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ wchar_t *ret;
+ wchar_t *name;
+ UINT size = 0;
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
+ WTSUserName, (wchar_t *)&name, &size) == false)
+ {
+ return NULL;
+ }
+
+ if (name == NULL || UniStrLen(name) == 0)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = UniCopyStr(name);
+ }
+
+ ms->nt->WTSFreeMemory(name);
+
+ return ret;
+ }
+ return NULL;
+}
+
+// Get whether the current desktop is available for the VNC
+bool MsIsCurrentDesktopAvailableForVnc()
+{
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ if (MsIsCurrentTerminalSessionActive() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->OpenDesktopA == NULL ||
+ ms->nt->CloseDesktop == NULL ||
+ ms->nt->SwitchDesktop == NULL)
+ {
+ return true;
+ }
+ else
+ {
+ HDESK hDesk = ms->nt->OpenDesktopA("default", 0, false, DESKTOP_SWITCHDESKTOP);
+ bool ret;
+
+ if (hDesk == NULL)
+ {
+ return false;
+ }
+
+ ret = ms->nt->SwitchDesktop(hDesk);
+ ms->nt->CloseDesktop(hDesk);
+
+ return ret;
+ }
+}
+
+// Get whether the current terminal session is active
+bool MsIsCurrentTerminalSessionActive()
+{
+ return MsIsTerminalSessionActive(MsGetCurrentTerminalSessionId());
+}
+
+// Get whether the specified terminal session is active
+bool MsIsTerminalSessionActive(UINT session_id)
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ UINT *status = NULL;
+ UINT size = sizeof(status);
+ bool active = true;
+
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
+ WTSConnectState, (wchar_t *)&status, &size) == false)
+ {
+ return true;
+ }
+
+ switch (*status)
+ {
+ case WTSDisconnected:
+ case WTSShadow:
+ case WTSIdle:
+ case WTSDown:
+ case WTSReset:
+ active = false;
+ break;
+ }
+
+ ms->nt->WTSFreeMemory(status);
+
+ return active;
+ }
+
+ return true;
+}
+
+// Get the current terminal session ID
+UINT MsGetCurrentTerminalSessionId()
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ UINT ret;
+ UINT *session_id = NULL;
+ UINT size = sizeof(session_id);
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION,
+ WTSSessionId, (wchar_t *)&session_id, &size) == false)
+ {
+ return 0;
+ }
+
+ ret = *session_id;
+
+ ms->nt->WTSFreeMemory(session_id);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+// Examine whether the Terminal Services is installed and the multiple sessions can log in
+bool MsIsTerminalServiceMultiUserInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+ if (MsIsTerminalServiceInstalled() == false)
+ {
+ return false;
+ }
+
+ if (OS_IS_SERVER(info->OsType) == false)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Examine whether the user switching is installed
+bool MsIsUserSwitchingInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->WTSDisconnectSession == NULL ||
+ ms->nt->WTSFreeMemory == NULL ||
+ ms->nt->WTSQuerySessionInformation == NULL)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) < 2)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Enable the remote desktop
+bool MsEnableRemoteDesktop()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (MsIsRemoteDesktopEnabled())
+ {
+ return true;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return false;
+ }
+
+ if (MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+ "fDenyTSConnections", 0) == false)
+ {
+ return false;
+ }
+
+ if (MsIsVista())
+ {
+ if (MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
+ "UserAuthentication", 0) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Examine whether the Remote Desktop is enabled
+bool MsIsRemoteDesktopEnabled()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return MsIsServiceRunning("TermService");
+ }
+ else
+ {
+ // Windows XP or later
+ bool b = MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+ "fDenyTSConnections");
+
+ if (MsIsVista() == false)
+ {
+ return b ? false : true;
+ }
+ else
+ {
+ if (b)
+ {
+ return false;
+ }
+ else
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
+ "UserAuthentication"))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+}
+
+// Examine whether the remote desktop becomes available by registry operation
+bool MsIsRemoteDesktopCanEnableByRegistory()
+{
+ OS_INFO *info = GetOsInfo();
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return false;
+ }
+ else
+ {
+ // Others
+ return true;
+ }
+}
+
+// Examine whether it's running on Windows 2000
+bool MsIsWin2000()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether Windows 2000 or later
+bool MsIsWin2000OrGreater()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 2)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether Windows XP or later
+bool MsIsWinXPOrGreater()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 3)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether the remote desktop is available
+bool MsIsRemoteDesktopAvailable()
+{
+ OS_INFO *info = GetOsInfo();
+ if (MsIsTerminalServiceInstalled() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ if (info->OsType == 2200)
+ {
+ // Windows 2000 Professional
+ return false;
+ }
+ else
+ {
+ // Windows 2000 server series
+ return true;
+ }
+ }
+ else if (GET_KETA(info->OsType, 100) == 3)
+ {
+ // Windows XP
+ if (info->OsType == OSTYPE_WINDOWS_XP_HOME)
+ {
+ // Home Edition
+ return false;
+ }
+ else
+ {
+ // Professional Edition
+ return true;
+ }
+ }
+ else if (GET_KETA(info->OsType, 100) == 4)
+ {
+ // Windows Server 2003
+ return true;
+ }
+ else if (GET_KETA(info->OsType, 100) >= 5)
+ {
+ // Windows Vista or later
+ OSVERSIONINFOEX i;
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_PERSONAL)
+ {
+ // Home series
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Examine whether the Terminal Services is installed
+bool MsIsTerminalServiceInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->WTSDisconnectSession == NULL ||
+ ms->nt->WTSFreeMemory == NULL ||
+ ms->nt->WTSQuerySessionInformation == NULL)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) < 2)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_TERMINAL || i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Stop the service
+bool MsStopService(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ SERVICE_STATUS st;
+ ret = ms->nt->ControlService(service, SERVICE_CONTROL_STOP, &st);
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ if (ret)
+ {
+ UINT64 end = Tick64() + 10000ULL;
+ while (Tick64() < end)
+ {
+ if (MsIsServiceRunning(name) == false)
+ {
+ break;
+ }
+
+ SleepThread(250);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Start the service
+bool MsStartService(char *name)
+{
+ return MsStartServiceEx(name, NULL);
+}
+bool MsStartServiceEx(char *name, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ static UINT dummy = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &dummy;
+ }
+
+ *error_code = 0;
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ ret = ms->nt->StartService(service, 0, NULL);
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ if (ret)
+ {
+ UINT64 end = Tick64() + 10000ULL;
+ while (Tick64() < end)
+ {
+ if (MsIsServiceRunning(name))
+ {
+ break;
+ }
+
+ SleepThread(250);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Get whether the service is running
+bool MsIsServiceRunning(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL || IsEmptyStr(name))
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, GENERIC_READ);
+ if (service != NULL)
+ {
+ SERVICE_STATUS st;
+ Zero(&st, sizeof(st));
+ if (ms->nt->QueryServiceStatus(service, &st))
+ {
+ switch (st.dwCurrentState)
+ {
+ case SERVICE_CONTINUE_PENDING:
+ case SERVICE_PAUSE_PENDING:
+ case SERVICE_PAUSED:
+ case SERVICE_RUNNING:
+ case SERVICE_START_PENDING:
+ case SERVICE_STOP_PENDING:
+ ret = true;
+ break;
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Uninstall the service
+bool MsUninstallService(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ MsStopService(name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (ms->nt->DeleteService(service))
+ {
+ ret = true;
+ }
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Update the title and description of the service
+bool MsSetServiceDescription(char *name, wchar_t *description)
+{
+ SC_HANDLE sc, service;
+ // Validate arguments
+ if (name == NULL || description == NULL)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+
+ if (UniIsEmptyStr(description) == false)
+ {
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ return true;
+}
+
+// Update the service setting
+bool MsUpdateServiceConfig(char *name)
+{
+ SC_HANDLE sc, service;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ // Whether just after Windows startup (deadlock prevention)
+ if (timeGetTime() <= (60 * 30 * 1000))
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name) != 0)
+ {
+ return false;
+ }
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_FAILURE_ACTIONS action;
+ SC_ACTION *e;
+ Zero(&action, sizeof(action));
+ e = ZeroMalloc(sizeof(SC_ACTION) * 3);
+ e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
+ e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
+ e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
+ action.cActions = 3;
+ action.lpsaActions = e;
+ action.dwResetPeriod = 1 * 60 * 60 * 24;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name, 1);
+ }
+
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+ wchar_t *description;
+ char dname[MAX_SIZE];
+
+ Format(dname, sizeof(dname), "SVC_%s_DESCRIPT", name);
+
+ description = _UU(dname);
+
+ if (UniIsEmptyStr(description) == false)
+ {
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ return true;
+}
+
+// Install the device driver
+bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ wchar_t name_w[MAX_SIZE];
+ static UINT temp_int = 0;
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &temp_int;
+ }
+
+ *error_code = 0;
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
+ SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
+
+ if (service != NULL)
+ {
+ ret = true;
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Install the service
+bool MsInstallService(char *name, char *title, wchar_t *description, char *path)
+{
+ wchar_t title_w[MAX_PATH];
+ wchar_t path_w[MAX_PATH];
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+
+ StrToUni(title_w, sizeof(title_w), title);
+ StrToUni(path_w, sizeof(path_w), path);
+
+ return MsInstallServiceW(name, title_w, description, path_w);
+}
+bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path)
+{
+ return MsInstallServiceExW(name, title, description, path, NULL);
+}
+bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ wchar_t name_w[MAX_SIZE];
+ static UINT temp_int = 0;
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &temp_int;
+ }
+
+ *error_code = 0;
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS | (MsIsVista() ? 0 : SERVICE_INTERACTIVE_PROCESS), SERVICE_AUTO_START,
+ SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
+
+ if (service != NULL)
+ {
+ ret = true;
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+ SERVICE_FAILURE_ACTIONS action;
+ SC_ACTION *e;
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ Zero(&action, sizeof(action));
+ e = ZeroMalloc(sizeof(SC_ACTION) * 3);
+ e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
+ e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
+ e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
+ action.cActions = 3;
+ action.lpsaActions = e;
+ action.dwResetPeriod = 1 * 60 * 60 * 24;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
+
+ Free(e);
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Check whether the specified service is installed
+bool MsIsServiceInstalled(char *name)
+{
+ SC_HANDLE sc;
+ SC_HANDLE service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, GENERIC_READ);
+ if (service != NULL)
+ {
+ ret = true;
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ ms->nt->CloseServiceHandle(sc);
+
+ return ret;
+}
+
+// Kill the process
+void MsTerminateProcess()
+{
+ TerminateProcess(GetCurrentProcess(), 0);
+ _exit(0);
+}
+
+// Get the Process ID
+UINT MsGetProcessId()
+{
+ return GetCurrentProcessId();
+}
+
+// Get the MS structure
+MS *MsGetMs()
+{
+ return ms;
+}
+
+// Lower the priority of the thread to lowest
+void MsSetThreadPriorityIdle()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
+}
+
+// Raise the priority of a thread
+void MsSetThreadPriorityHigh()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+}
+
+// Lower the priority of the thread
+void MsSetThreadPriorityLow()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
+}
+
+// Raise the priority of the thread to highest
+void MsSetThreadPriorityRealtime()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+}
+
+// Restore the priority of the thread
+void MsRestoreThreadPriority()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+}
+
+// Check whether should show the TCP setting application
+bool MsIsShouldShowTcpConfigApp()
+{
+ MS_TCP tcp1, tcp2;
+ if (MsIsTcpConfigSupported() == false)
+ {
+ return false;
+ }
+
+ MsGetTcpConfig(&tcp1);
+ if (MsLoadTcpConfigReg(&tcp2) == false)
+ {
+ return true;
+ }
+
+ if (Cmp(&tcp1, &tcp2, sizeof(MS_TCP) != 0))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Apply the temporary settings data of registry to the TCP parameter of the Windows
+void MsApplyTcpConfig()
+{
+ if (MsIsTcpConfigSupported())
+ {
+ MS_TCP tcp;
+
+ if (MsLoadTcpConfigReg(&tcp))
+ {
+ MsSetTcpConfig(&tcp);
+ }
+ }
+}
+
+// Check whether the dynamic configuration of TCP is supported in current state
+bool MsIsTcpConfigSupported()
+{
+ if (MsIsNt() && MsIsAdmin())
+ {
+ UINT type = GetOsInfo()->OsType;
+
+ if (GET_KETA(type, 100) >= 2)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Read the TCP settings from the registry setting
+bool MsLoadTcpConfigReg(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt())
+ {
+ Zero(tcp, sizeof(MS_TCP));
+
+ if (MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true) == false ||
+ MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true) == false)
+ {
+ return false;
+ }
+
+ tcp->RecvWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true);
+ tcp->SendWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true);
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Remove the TCP settings from the registry
+void MsDeleteTcpConfigReg()
+{
+ if (MsIsNt() && MsIsAdmin())
+ {
+ MsRegDeleteKeyEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, true);
+ }
+}
+
+// Write the TCP settings to the registry setting
+void MsSaveTcpConfigReg(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() && MsIsAdmin())
+ {
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", tcp->RecvWindowSize, true);
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", tcp->SendWindowSize, true);
+ }
+}
+
+// Get the current TCP settings
+void MsGetTcpConfig(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ Zero(tcp, sizeof(MS_TCP));
+
+ if (MsIsNt())
+ {
+ UINT v;
+ // Initialize the network setting
+ MsInitGlobalNetworkConfig();
+
+ // Read the value of TcpWindowSize or GlobalMaxTcpWindowSize if there is
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "GlobalMaxTcpWindowSize");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultReceiveWindow");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ // Read the value of DefaultSendWindow if there is
+ tcp->SendWindowSize = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultSendWindow");
+ }
+}
+
+// Write the TCP settings
+void MsSetTcpConfig(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() && MsIsAdmin())
+ {
+ bool window_scaling = false;
+ UINT tcp1323opts;
+
+ if (tcp->RecvWindowSize >= 65536 || tcp->SendWindowSize >= 65536)
+ {
+ window_scaling = true;
+ }
+
+ // Set the Tcp1323Opts
+ tcp1323opts = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts");
+ if (window_scaling)
+ {
+ if (tcp1323opts == 0)
+ {
+ tcp1323opts = 1;
+ }
+ if (tcp1323opts == 2)
+ {
+ tcp1323opts = 3;
+ }
+ }
+ else
+ {
+ if (tcp1323opts == 1)
+ {
+ tcp1323opts = 0;
+ }
+ if (tcp1323opts == 3)
+ {
+ tcp1323opts = 2;
+ }
+ }
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts", tcp1323opts);
+
+ // Set the Receive Window
+ if (tcp->RecvWindowSize == 0)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize");
+ }
+ else
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow", tcp->RecvWindowSize);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize", tcp->RecvWindowSize);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize", tcp->RecvWindowSize);
+ }
+
+ // Setting the Send Window
+ if (tcp->SendWindowSize == 0)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow");
+ }
+ else
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow", tcp->SendWindowSize);
+ }
+ }
+}
+
+// Initialize the global network settings
+void MsInitGlobalNetworkConfig()
+{
+ if (MsIsNt())
+ {
+ UINT current_window_size;
+ current_window_size = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
+
+ if (current_window_size == 65535 || current_window_size == 5980160 ||
+ current_window_size == 16777216 || current_window_size == 16777214)
+ {
+ // Remove the strange value which is written by older version of PacketiX VPN
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "Tcp1323Opts");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize");
+
+ // Set vpn_no_change = true
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "vpn_no_change", 1);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "vpn_no_change", 1);
+ }
+ }
+ else
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
+ "packetix_no_optimize") == 0)
+ {
+ // Disable the DeadGWDetect
+ MsRegWriteStr(REG_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
+ "DeadGWDetect", "0");
+ }
+ }
+
+ MsApplyTcpConfig();
+}
+
+// Process disabling other off-loading of network and others
+void MsDisableNetworkOffloadingEtc()
+{
+ wchar_t netsh[MAX_SIZE];
+ UINT exec_timeout = 10000;
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ // Get the path of netsh.exe
+ CombinePathW(netsh, sizeof(netsh), MsGetSystem32DirW(), L"netsh.exe");
+
+ // Registry settings
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "DisableTaskOffload", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpNumConnections", TCP_MAX_NUM_CONNECTIONS, false, true);
+
+ if (MsIsVista() == false)
+ {
+ // Windows Server 2003 or earlier
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableRSS", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPChimney", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPA", 1, false, true);
+
+ Win32RunAndWaitProcess(netsh, L"netsh int ip set chimney disabled", true, true, exec_timeout);
+ SleepThread(250);
+ }
+ else
+ {
+ // Windows Vista or later
+ Win32RunAndWaitProcess(netsh, L"int ipv4 set global taskoffload=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ Win32RunAndWaitProcess(netsh, L"int ipv6 set global taskoffload=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ Win32RunAndWaitProcess(netsh, L"int tcp set global chimney=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ }
+}
+
+// Upgrade the virtual LAN card
+bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsUpgradeVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ wchar_t infpath[MAX_PATH];
+ char hwid[MAX_PATH];
+ wchar_t hwid_w[MAX_PATH];
+ bool ret = false;
+ bool need_reboot;
+ bool before_status;
+ UCHAR old_mac_address[6];
+ UCHAR new_mac_address[6];
+ char *s;
+ NO_WARNING *nw;
+ char neo_sys[MAX_PATH];
+ char *reg_key;
+ UINT i;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Can not be upgraded in Windows 9x
+ return false;
+ }
+
+ if (MsIsInfCatalogRequired())
+ {
+ if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
+ {
+ return false;
+ }
+
+ StrUpper(instance_name);
+ }
+
+ Zero(hwid, sizeof(hwid));
+ Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
+ StrToUni(hwid_w, sizeof(hwid_w), hwid);
+
+ // Examine whether the virtual LAN card with the specified name has already registered
+ if (MsIsVLanExists(tag_name, instance_name) == false)
+ {
+ // Not registered
+ return false;
+ }
+
+ reg_key = MsGetNetCfgRegKeyName(tag_name, instance_name);
+
+ if (IsEmptyStr(reg_key) == false)
+ {
+ // Add a value to the registry key
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*IfType", 6);
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*MediaType", 0);
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*PhysicalMediaType", 0);
+ }
+ Free(reg_key);
+
+ // Get the .sys file name that is currently being used
+ if (MsGetNeoDeiverFilename(neo_sys, sizeof(neo_sys), instance_name) == false)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ // Can not be upgraded if getting current .sys file name failed
+ // in the Windows 8 or later
+ return false;
+ }
+
+ // Create a new file name because it is unknown
+ if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
+ {
+ // Failure
+ return false;
+ }
+ }
+
+ // Get the current operating status
+ before_status = MsIsVLanEnabled(instance_name);
+
+ // Get the previous MAC address
+ s = MsGetMacAddress(tag_name, instance_name);
+ if (s == NULL)
+ {
+ Zero(old_mac_address, 6);
+ }
+ else
+ {
+ BUF *b;
+ b = StrToBin(s);
+ Free(s);
+
+ if (b->Size == 6)
+ {
+ Copy(old_mac_address, b->Buf, b->Size);
+ }
+ else
+ {
+ Zero(old_mac_address, 6);
+ }
+
+ FreeBuf(b);
+ }
+
+ // Starting the installation
+ if (MsStartDriverInstall(instance_name, IsZero(old_mac_address, 6) ? NULL : old_mac_address, neo_sys,
+ new_mac_address, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
+
+ nw = NULL;
+
+ //if (MsIsVista() == false)
+ {
+ nw = MsInitNoWarning();
+ }
+
+ // Do the installation
+ if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
+ NULL, hwid_w, infpath, 1, &need_reboot))
+ {
+ ret = true;
+ }
+ MsFreeNoWarning(nw);
+
+ // Installation complete
+ MsFinishDriverInstall(instance_name, neo_sys);
+
+ for (i = 0;i < 5;i++)
+ {
+ MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
+ if (MsIsInfCatalogRequired())
+ {
+ // Write the MAC address
+ char mac_address_str[MAX_SIZE];
+ BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+
+ // Restore operation
+ if (before_status)
+ {
+ MsEnableVLan(instance_name);
+ }
+ else
+ {
+ MsDisableVLan(instance_name);
+ }
+
+ return ret;
+}
+
+// Test for Windows 9x
+void MsWin9xTest()
+{
+}
+
+// Update the CompatibleIDs of virtual LAN card
+void MsUpdateCompatibleIDs(char *instance_name)
+{
+ TOKEN_LIST *t;
+ char id[MAX_SIZE];
+ char device_title[MAX_SIZE];
+ char device_title_old[MAX_SIZE];
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ Format(id, sizeof(id), DRIVER_DEVICE_ID_TAG, instance_name);
+ Format(device_title, sizeof(device_title), VLAN_ADAPTER_NAME_TAG, instance_name);
+ Format(device_title_old, sizeof(device_title_old), VLAN_ADAPTER_NAME_TAG_OLD, instance_name);
+
+ t = MsRegEnumKey(REG_LOCAL_MACHINE, "Enum\\Root\\Net");
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char keyname[MAX_PATH];
+ char *str;
+ char *title;
+
+ Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s", t->Token[i]);
+
+ title = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "DeviceDesc");
+
+ if (title != NULL)
+ {
+ if (StrCmpi(title, device_title) == 0 || StrCmpi(title, device_title_old) == 0)
+ {
+ Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s",t->Token[i]);
+ str = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs");
+ if (str != NULL)
+ {
+ Free(str);
+ }
+ else
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs", id);
+ }
+ }
+ Free(title);
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ MsRegWriteStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", "SourcePath",
+ ms->System32Dir);
+}
+
+// Installing the virtual LAN card (for Win9x)
+bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver)
+{
+ char sysdir[MAX_PATH];
+ char infdir[MAX_PATH];
+ char otherdir[MAX_PATH];
+ char syspath[MAX_PATH];
+ char syspath2[MAX_PATH];
+ char infpath[MAX_PATH];
+ char vpn16[MAX_PATH];
+ char infpath_src[MAX_PATH];
+ char syspath_src[MAX_PATH];
+ char neo_sys[MAX_PATH];
+ // Validate arguments
+ if (instance_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(sysdir, sizeof(sysdir), MsGetSystem32Dir());
+ Format(infdir, sizeof(infdir), "%s\\inf", MsGetWindowsDir());
+ Format(otherdir, sizeof(otherdir), "%s\\other", infdir);
+ Format(syspath, sizeof(syspath), "%s\\Neo_%s.sys", sysdir, instance_name);
+ Format(syspath2, sizeof(syspath2), "%s\\Neo_%s.sys", infdir, instance_name);
+ Format(infpath, sizeof(infpath), "%s\\Neo_%s.inf", infdir, instance_name);
+ Format(vpn16, sizeof(vpn16), "%s\\vpn16.exe", MsGetMyTempDir());
+
+ MakeDir(otherdir);
+
+ Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name);
+
+ // Copy of vpn16.exe
+ FileCopy("|vpn16.exe", vpn16);
+
+ // Starting the installation
+ if (MsStartDriverInstall(instance_name, NULL, neo_sys, NULL, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPathA(instance_name, NULL, NULL, infpath_src, syspath_src, NULL, NULL, neo_sys);
+
+ // Copy of the inf file
+ FileCopy(infpath_src, infpath);
+
+ // Copy of the sys file
+ FileCopy(syspath_src, syspath);
+
+ // Install the device driver
+ if (Run(vpn16, instance_name, false, true) == false)
+ {
+ return false;
+ }
+
+ // Update the CompatibleIDs
+ MsUpdateCompatibleIDs(instance_name);
+
+ return true;
+}
+
+// Child window enumeration procedure
+bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+
+ if (o != NULL)
+ {
+ MsEnumChildWindows(o, hWnd);
+ }
+
+ return true;
+}
+
+// Enumerate specified window and all the its child windows
+LIST *MsEnumChildWindows(LIST *o, HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ MsAddWindowToList(o, hWnd);
+
+ EnumChildWindows(hWnd, MsEnumChildWindowProc, (LPARAM)o);
+
+ return o;
+}
+
+// Add a window to the list
+void MsAddWindowToList(LIST *o, HWND hWnd)
+{
+ // Validate arguments
+ if (o == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, hWnd) == false)
+ {
+ Add(o, hWnd);
+ }
+}
+
+// Enumeration of the window that the thread owns
+bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ MsEnumChildWindows(o, hWnd);
+
+ return true;
+}
+
+// Window enumeration procedure
+BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+ HWND hParent;
+ char c1[MAX_SIZE], c2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || o == NULL)
+ {
+ return TRUE;
+ }
+
+ Zero(c1, sizeof(c1));
+ Zero(c2, sizeof(c2));
+
+ hParent = GetParent(hWnd);
+
+ GetClassName(hWnd, c1, sizeof(c1));
+
+ if (hParent != NULL)
+ {
+ GetClassName(hParent, c2, sizeof(c2));
+ }
+
+ if (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0))
+ {
+ AddWindow(o, hWnd);
+ }
+
+ return TRUE;
+}
+
+// Child window enumeration procedure
+BOOL CALLBACK EnumChildWindowProc(HWND hWnd, LPARAM lParam)
+{
+ ENUM_CHILD_WINDOW_PARAM *p = (ENUM_CHILD_WINDOW_PARAM *)lParam;
+ LIST *o;
+ HWND hParent;
+ char c1[MAX_SIZE], c2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return TRUE;
+ }
+
+ o = p->o;
+
+ Zero(c1, sizeof(c1));
+ Zero(c2, sizeof(c2));
+
+ hParent = GetParent(hWnd);
+
+ GetClassName(hWnd, c1, sizeof(c1));
+
+ if (hParent != NULL)
+ {
+ GetClassName(hParent, c2, sizeof(c2));
+ }
+
+ if (p->include_ipcontrol || (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0)))
+ {
+ AddWindow(o, hWnd);
+
+ if (p->no_recursion == false)
+ {
+ EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)p);
+ }
+ }
+
+ return TRUE;
+}
+LIST *EnumAllWindow()
+{
+ return EnumAllWindowEx(false, false);
+}
+LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol)
+{
+ ENUM_CHILD_WINDOW_PARAM p;
+ LIST *o = NewWindowList();
+
+ Zero(&p, sizeof(p));
+ p.o = o;
+ p.no_recursion = no_recursion;
+ p.include_ipcontrol = include_ipcontrol;
+
+ EnumWindows(EnumChildWindowProc, (LPARAM)&p);
+
+ return o;
+}
+LIST *EnumAllTopWindow()
+{
+ LIST *o = NewWindowList();
+
+ EnumWindows(EnumTopWindowProc, (LPARAM)o);
+
+ return o;
+}
+
+// Enumerate the child windows of all that is in the specified window
+LIST *EnumAllChildWindow(HWND hWnd)
+{
+ return EnumAllChildWindowEx(hWnd, false, false, false);
+}
+LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self)
+{
+ ENUM_CHILD_WINDOW_PARAM p;
+ LIST *o = NewWindowList();
+
+ Zero(&p, sizeof(p));
+ p.include_ipcontrol = include_ipcontrol;
+ p.no_recursion = no_recursion;
+ p.o = o;
+
+ if (no_self == false)
+ {
+ AddWindow(o, hWnd);
+ }
+
+ EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)&p);
+
+ return o;
+}
+
+// Release of the window list
+void FreeWindowList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND *e = LIST_DATA(o, i);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Add a window to the window list
+void AddWindow(LIST *o, HWND hWnd)
+{
+ HWND t, *e;
+ // Validate arguments
+ if (o == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ t = hWnd;
+
+ if (Search(o, &t) != NULL)
+ {
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(HWND));
+ *e = hWnd;
+
+ Insert(o, e);
+}
+
+// Comparison of the window list items
+int CmpWindowList(void *p1, void *p2)
+{
+ HWND *h1, *h2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ h1 = *(HWND **)p1;
+ h2 = *(HWND **)p2;
+ if (h1 == NULL || h2 == NULL)
+ {
+ return 0;
+ }
+
+ return Cmp(h1, h2, sizeof(HWND));
+}
+
+// Creating a new window list
+LIST *NewWindowList()
+{
+ return NewListFast(CmpWindowList);
+}
+
+// Determine whether it's Windows Vista or later
+bool MsIsVista()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 5)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Determine whether it's Windows 7 or later
+bool MsIsWindows7()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 6)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Determine whether it's Windows 8 later
+bool MsIsWindows8()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 7)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Whether INF catalog signature is required
+bool MsIsInfCatalogRequired()
+{
+ return MsIsWindows8();
+}
+
+// Get the process path of the owner of the window
+bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd)
+{
+ DWORD procId = 0;
+ // Validate arguments
+ if (path == NULL || hWnd == NULL)
+ {
+ return false;
+ }
+
+ GetWindowThreadProcessId(hWnd, &procId);
+ if (procId == 0)
+ {
+ return false;
+ }
+
+ if (MsGetProcessExeName(path, size, procId) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd)
+{
+ DWORD procId = 0;
+ // Validate arguments
+ if (path == NULL || hWnd == NULL)
+ {
+ return false;
+ }
+
+ GetWindowThreadProcessId(hWnd, &procId);
+ if (procId == 0)
+ {
+ return false;
+ }
+
+ if (MsGetProcessExeNameW(path, size, procId) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the process path from process ID
+bool MsGetProcessExeName(char *path, UINT size, UINT id)
+{
+ LIST *o;
+ MS_PROCESS *proc;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+ proc = MsSearchProcessById(o, id);
+
+ if (proc != NULL)
+ {
+ ret = true;
+ StrCpy(path, size, proc->ExeFilename);
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id)
+{
+ LIST *o;
+ MS_PROCESS *proc;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+ proc = MsSearchProcessById(o, id);
+
+ if (proc != NULL)
+ {
+ ret = true;
+ UniStrCpy(path, size, proc->ExeFilenameW);
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+
+// Close the alert dialog
+bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id)
+{
+ UINT i;
+ LIST *o;
+ bool ret = false;
+ bool press = false;
+
+ if (MsIsVista() == false || nw->StartTimer == 0)
+ {
+ press = true;
+ }
+
+ if (nw->StartTick != 0 && nw->StartTick <= Tick64())
+ {
+ press = true;
+ }
+
+ if (MsIsVista() == false)
+ {
+ o = NewListFast(NULL);
+ EnumThreadWindows(thread_id, MsEnumThreadWindowProc, (LPARAM)o);
+ }
+ else
+ {
+ o = EnumAllTopWindow();
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND hWnd;
+
+ if (MsIsVista() == false)
+ {
+ hWnd = LIST_DATA(o, i);
+ }
+ else
+ {
+ hWnd = *((HWND *)LIST_DATA(o, i));
+ }
+
+ if (hWnd != NULL)
+ {
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsNt())
+ {
+ // Get whether this window is a warning screen of driver
+ if (MsIsVista() == false)
+ {
+ // Other than Windows Vista
+ HWND hStatic, hOk, hCancel, hDetail;
+
+ hStatic = GetDlgItem(hWnd, 0x14C1);
+ hOk = GetDlgItem(hWnd, 0x14B7);
+ hCancel = GetDlgItem(hWnd, 0x14BA);
+ hDetail = GetDlgItem(hWnd, 0x14B9);
+
+ if ((hStatic != NULL || hDetail != NULL) && hOk != NULL && hCancel != NULL)
+ {
+ char tmp[MAX_SIZE];
+ bool b = false;
+
+ if (GetClassName(hStatic, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "static") == 0)
+ {
+ b = true;
+ }
+ }
+
+ if (GetClassName(hDetail, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ b = true;
+ }
+ }
+
+ if (b)
+ {
+ if (GetClassName(hOk, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ if (GetClassName(hCancel, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ // Press the OK button since it was found
+ PostMessage(hWnd, WM_COMMAND, 0x14B7, 0);
+
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Windows Vista
+ char exe[MAX_PATH];
+
+ if (MsGetWindowOwnerProcessExeName(exe, sizeof(exe), hWnd))
+ {
+ if (EndWith(exe, "rundll32.exe"))
+ {
+ LIST *o;
+ HWND h;
+ UINT i;
+
+ o = EnumAllChildWindow(hWnd);
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp[MAX_SIZE];
+
+ h = *((HWND *)LIST_DATA(o, i));
+
+ Zero(tmp, sizeof(tmp));
+ GetClassNameA(h, tmp, sizeof(tmp));
+
+ if (StrCmpi(tmp, "DirectUIHWND") == 0)
+ {
+ LIST *o = EnumAllChildWindow(h);
+
+ if (o != NULL)
+ {
+ UINT j;
+ UINT numDirectUIHWND = 0;
+ UINT numButton = 0;
+ HWND hButton1 = NULL;
+ HWND hButton2 = NULL;
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ HWND hh;
+ char tmp[MAX_SIZE];
+
+ hh = *((HWND *)LIST_DATA(o, j));
+
+ Zero(tmp, sizeof(tmp));
+ GetClassNameA(hh, tmp, sizeof(tmp));
+
+ if (StrCmpi(tmp, "DirectUIHWND") == 0)
+ {
+ numDirectUIHWND++;
+ }
+
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ numButton++;
+ if (hButton1 == NULL)
+ {
+ hButton1 = hh;
+ }
+ else
+ {
+ hButton2 = hh;
+ }
+ }
+ }
+
+ if ((numDirectUIHWND == 1 || numDirectUIHWND == 2) && numButton == 2)
+ {
+ if (hButton1 != NULL && hButton2 != NULL)
+ {
+ HWND hButton;
+ HWND hParent;
+ RECT r1, r2;
+
+ GetWindowRect(hButton1, &r1);
+ GetWindowRect(hButton2, &r2);
+
+ hButton = hButton1;
+
+ if (numDirectUIHWND == 1)
+ {
+ // Warning that there is no signature
+ if (r1.top < r2.top)
+ {
+ hButton = hButton2;
+ }
+ }
+ else
+ {
+ // Notification that there is signature
+ if (r1.left >= r2.left)
+ {
+ hButton = hButton2;
+ }
+ }
+
+ hParent = GetParent(hButton);
+
+ // Press the OK button since it was found
+ if (press)
+ {
+ PostMessage(hParent, WM_COMMAND, 1, 0);
+ }
+
+ ret = true;
+ }
+ }
+
+ FreeWindowList(o);
+ }
+ }
+ }
+
+ FreeWindowList(o);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (MsIsVista() == false)
+ {
+ ReleaseList(o);
+ }
+ else
+ {
+ FreeWindowList(o);
+ }
+
+ if (press == false)
+ {
+ if (ret)
+ {
+ ret = false;
+
+ if (nw->StartTick == 0)
+ {
+ nw->StartTick = Tick64() + nw->StartTimer;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Thread to suppress a warning message
+void MsNoWarningThreadProc(THREAD *thread, void *param)
+{
+ NO_WARNING *nw;
+ UINT interval;
+ UINT i;
+ bool found0 = false;
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+ nw = (NO_WARNING *)param;
+
+ nw->NoWarningThread = thread;
+ AddRef(thread->ref);
+
+ NoticeThreadInit(thread);
+
+ interval = 50;
+
+ if (MsIsVista())
+ {
+ interval = 1000;
+ }
+
+ i = 0;
+
+ while (nw->Halt == false)
+ {
+ bool found = false;
+
+ // Close the alert dialog
+ found = MsCloseWarningWindow(nw, nw->ThreadId);
+ if (i == 0)
+ {
+ found0 = found;
+ }
+ else
+ {
+ if (found0 == false && found)
+ {
+ break;
+ }
+ }
+ i++;
+
+ // Loop until the command incomes from parent thread
+ Wait(nw->HaltEvent, interval);
+ }
+}
+
+// Initialize the procedure to turn off the warning sound
+char *MsNoWarningSoundInit()
+{
+ char *ret = MsRegReadStr(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
+
+ if (IsEmptyStr(ret))
+ {
+ Free(ret);
+ ret = NULL;
+ }
+ else
+ {
+ MsRegWriteStr(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", "");
+ }
+
+ return ret;
+}
+
+// Release of procedure to turn off the warning sound
+void MsNoWarningSoundFree(char *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteStrExpand(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", s);
+
+ Free(s);
+}
+
+// The start of the procedure to suppress the warning
+NO_WARNING *MsInitNoWarning()
+{
+ return MsInitNoWarningEx(0);
+}
+NO_WARNING *MsInitNoWarningEx(UINT start_timer)
+{
+ THREAD *thread;
+ NO_WARNING *nw = ZeroMalloc(sizeof(NO_WARNING));
+
+ nw->StartTimer = (UINT64)start_timer;
+
+ // Get the current sound file name
+ if (MsIsVista() == false)
+ {
+ wchar_t *tmp;
+
+ // Turn off the unnecessary warning tone in Windows XP or earlier
+ tmp = MsRegReadStrW(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
+ if (UniIsEmptyStr(tmp) == false)
+ {
+ nw->SoundFileName = CopyUniStr(tmp);
+
+ MsRegWriteStrW(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", L"");
+ }
+
+ Free(tmp);
+ }
+
+ nw->ThreadId = GetCurrentThreadId();
+ nw->HaltEvent = NewEvent();
+
+ thread = NewThread(MsNoWarningThreadProc, nw);
+ WaitThreadInit(thread);
+
+ ReleaseThread(thread);
+
+ return nw;
+}
+
+// End of the procedure to suppress the warning
+void MsFreeNoWarning(NO_WARNING *nw)
+{
+ // Validate arguments
+ if (nw == NULL)
+ {
+ return;
+ }
+
+ nw->Halt = true;
+ Set(nw->HaltEvent);
+
+ WaitThread(nw->NoWarningThread, INFINITE);
+ ReleaseThread(nw->NoWarningThread);
+
+ ReleaseEvent(nw->HaltEvent);
+
+ if (MsIsVista() == false)
+ {
+ if (nw->SoundFileName != NULL)
+ {
+ MsRegWriteStrExpandW(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", nw->SoundFileName);
+
+ Free(nw->SoundFileName);
+ }
+ }
+
+ Free(nw);
+}
+
+// Obtain the name of the directory that the inf catalog file is stored
+void MsGetInfCatalogDir(char *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ Format(dst, size, "|inf\\%s", (MsIsX64() ? "x64" : "x86"));
+}
+
+// Examine whether the virtual LAN card name can be used as a instance name of the VLAN
+bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name)
+{
+ char src_dir[MAX_SIZE];
+ char tmp[MAX_SIZE];
+ bool ret;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ MsGetInfCatalogDir(src_dir, sizeof(src_dir));
+
+ Format(tmp, sizeof(tmp), "%s\\INF_%s.inf", src_dir, instance_name);
+ ret = IsFile(tmp);
+
+ return ret;
+}
+
+// Delete the device information that is about the device which failed during the installation of the same name before installing the virtual LAN card
+void MsDeleteTroubleVLAN(char *tag_name, char *instance_name)
+{
+ HDEVINFO dev_info;
+ SP_DEVINFO_LIST_DETAIL_DATA detail_data;
+ SP_DEVINFO_DATA data;
+ UINT i;
+ char target_name[MAX_SIZE];
+ LIST *o;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ Format(target_name, sizeof(target_name), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ // Create a device information list
+ dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
+ if (dev_info == NULL)
+ {
+ return;
+ }
+
+ Zero(&detail_data, sizeof(detail_data));
+ detail_data.cbSize = sizeof(detail_data);
+ if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return;
+ }
+
+ Zero(&data, sizeof(data));
+ data.cbSize = sizeof(data);
+
+ // Enumeration start
+ o = NewListFast(NULL);
+
+ for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
+ {
+ char *buffer;
+ UINT buffer_size = 8092;
+ DWORD data_type;
+
+ buffer = ZeroMalloc(buffer_size);
+
+ if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
+ {
+ if (StrCmpi(buffer, target_name) == 0)
+ {
+ // Found
+ SP_DEVINFO_DATA *data2 = Clone(&data, sizeof(SP_DEVINFO_DATA));
+
+ Add(o, data2);
+ }
+ }
+
+ Free(buffer);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SP_DEVINFO_DATA *data = LIST_DATA(o, i);
+ bool ret;
+
+ ret = SetupDiRemoveDevice(dev_info, data);
+
+ Debug("Deleting Troubled NIC %u: %u\n", i, ret);
+
+ Free(data);
+ }
+
+ ReleaseList(o);
+
+ MsDestroyDevInfo(dev_info);
+}
+
+// Install a virtual LAN card
+bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ wchar_t infpath[MAX_PATH];
+ char hwid[MAX_PATH];
+ wchar_t hwid_w[MAX_PATH];
+ bool ret = false;
+ char neo_sys[MAX_PATH];
+ UCHAR new_mac_address[6];
+ UINT i;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // For Windows 9x
+ return MsInstallVLan9x(instance_name, ver);
+ }
+
+ if (MsIsInfCatalogRequired())
+ {
+ if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
+ {
+ Debug("MsIsValidVLanInstanceNameForInfCatalog() returns false.\n");
+ return false;
+ }
+
+ StrUpper(instance_name);
+ }
+
+ Zero(hwid, sizeof(hwid));
+ Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
+ StrToUni(hwid_w, sizeof(hwid_w), hwid);
+
+ // Examine whether the virtual LAN card with the specified name has already registered
+ if (MsIsVLanExists(tag_name, instance_name))
+ {
+ // Already be registered
+ Debug("MsIsVLanExists() returns true.\n");
+ return false;
+ }
+
+ // Determining destination .sys file name of the installation
+ if (MsIsInfCatalogRequired() == false)
+ {
+ if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name);
+ }
+
+ // Starting the Installation
+ if (MsStartDriverInstall(instance_name, NULL, neo_sys, new_mac_address, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
+
+ // Delete the device information that is left on fail of installation
+ if (MsIsNt())
+ {
+ MsDeleteTroubleVLAN(tag_name, instance_name);
+ }
+
+ // Call the Win32 API
+ ret = MsInstallVLanInternal(infpath, hwid_w, hwid);
+
+ // Installation complete
+ MsFinishDriverInstall(instance_name, neo_sys);
+
+ for (i = 0;i < 5;i++)
+ {
+ MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
+ if (MsIsInfCatalogRequired())
+ {
+ // Write the MAC address
+ char mac_address_str[MAX_SIZE];
+ BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+ }
+
+ if (ret)
+ {
+ MsDisableVLan(instance_name);
+ SleepThread(MsIsVista() ? 1000 : 300);
+ MsEnableVLan(instance_name);
+ }
+
+ return ret;
+}
+
+// Test function
+void MsTest()
+{
+}
+
+// Install a virtual LAN card (by calling Win32 API)
+bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid)
+{
+ bool need_reboot;
+ bool ret = false;
+ wchar_t inf_class_name[MAX_PATH];
+ GUID inf_class_guid;
+ HDEVINFO device_info;
+ SP_DEVINFO_DATA device_info_data;
+ // Validate arguments
+ if (infpath == NULL || hwid_w == NULL || hwid == NULL)
+ {
+ return false;
+ }
+
+ Debug("MsInstallVLanInternal('%S', '%S', '%s');\n",
+ infpath, hwid_w, hwid);
+
+ Zero(&inf_class_guid, sizeof(inf_class_guid));
+ Zero(&device_info, sizeof(device_info));
+ Zero(&device_info_data, sizeof(device_info_data));
+ Zero(inf_class_name, sizeof(inf_class_name));
+
+ // Get the class GUID of the inf file
+ if (SetupDiGetINFClassW(infpath, &inf_class_guid, inf_class_name, sizeof(inf_class_name), NULL))
+ {
+ // Get the device information set
+ device_info = SetupDiCreateDeviceInfoList(&inf_class_guid, NULL);
+ if (device_info != INVALID_HANDLE_VALUE)
+ {
+ // Windows 2000 or later
+ Zero(&device_info_data, sizeof(device_info_data));
+ device_info_data.cbSize = sizeof(device_info_data);
+ if (SetupDiCreateDeviceInfoW(device_info, inf_class_name, &inf_class_guid,
+ NULL, NULL, DICD_GENERATE_ID, &device_info_data))
+ {
+ char hwid_copy[MAX_SIZE];
+ Zero(hwid_copy, sizeof(hwid_copy));
+ StrCpy(hwid_copy, sizeof(hwid_copy), hwid);
+
+ // Set the registry information
+ if (SetupDiSetDeviceRegistryProperty(device_info, &device_info_data,
+ SPDRP_HARDWAREID, (BYTE *)hwid_copy, sizeof(hwid_copy)))
+ {
+ NO_WARNING *nw = NULL;
+
+ //if (MsIsVista() == false)
+ {
+ nw = MsInitNoWarning();
+ }
+
+ // Start the class installer
+ if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info,
+ &device_info_data))
+ {
+ // Do the installation
+ if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
+ NULL, hwid_w, infpath, 1, &need_reboot))
+ {
+ ret = true;
+ }
+ else
+ {
+ // Installation Failed
+ Debug("UpdateDriverForPlugAndPlayDevicesW Error: %X\n", GetLastError());
+ if (SetupDiCallClassInstaller(DIF_REMOVE, device_info,
+ &device_info_data) == false)
+ {
+ Debug("SetupDiCallClassInstaller for Delete Failed. Err=%X\n", GetLastError());
+ }
+
+ if (SetupDiRemoveDevice(device_info, &device_info_data) == false)
+ {
+ Debug("SetupDiRemoveDevice for Delete Failed. Err=%X\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Debug("SetupDiCallClassInstaller for Create Error: %X\n", GetLastError());
+ }
+
+ MsFreeNoWarning(nw);
+ }
+ else
+ {
+ Debug("SetupDiSetDeviceRegistryProperty Error: %X\n", GetLastError());
+ }
+ }
+ else
+ {
+ Debug("SetupDiCreateDeviceInfoW Error: %X\n", GetLastError());
+ }
+ // Remove the device information set
+ SetupDiDestroyDeviceInfoList(device_info);
+ }
+ else
+ {
+ Debug("SetupDiCreateDeviceInfoList Error: %X\n", GetLastError());
+ }
+ }
+ else
+ {
+ Debug("SetupDiGetINFClassW Error: %X\n", GetLastError());
+ }
+
+ return ret;
+}
+
+// Get the device information from the device ID
+HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id)
+{
+ HDEVINFO dev_info;
+ SP_DEVINFO_LIST_DETAIL_DATA detail_data;
+ SP_DEVINFO_DATA data;
+ UINT i;
+ bool found;
+ char target_name[MAX_SIZE];
+ // Validate arguments
+ if (dev_info_data == NULL || device_id == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(target_name, sizeof(target_name), device_id);
+
+ // Create a device information list
+ dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
+ if (dev_info == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&detail_data, sizeof(detail_data));
+ detail_data.cbSize = sizeof(detail_data);
+ if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return NULL;
+ }
+
+ Zero(&data, sizeof(data));
+ data.cbSize = sizeof(data);
+
+ // Enumeration start
+ found = false;
+ for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
+ {
+ char *buffer;
+ UINT buffer_size = 8092;
+ DWORD data_type;
+
+ buffer = ZeroMalloc(buffer_size);
+
+ if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
+ {
+ if (StrCmpi(buffer, target_name) == 0)
+ {
+ // Found
+ found = true;
+ }
+ }
+
+ Free(buffer);
+
+ if (found)
+ {
+ break;
+ }
+ }
+
+ if (found == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return NULL;
+ }
+ else
+ {
+ Copy(dev_info_data, &data, sizeof(data));
+ return dev_info;
+ }
+}
+
+// Examine whether the specified device is operating
+bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_DEVINFO_LIST_DETAIL_DATA detail;
+ UINT status = 0, problem = 0;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&detail, sizeof(detail));
+ detail.cbSize = sizeof(detail);
+
+ if (SetupDiGetDeviceInfoListDetail(info, &detail) == false ||
+ ms->nt->CM_Get_DevNode_Status_Ex(&status, &problem, dev_info_data->DevInst,
+ 0, detail.RemoteMachineHandle) != CR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (status & 8)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Start the specified device
+bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_PROPCHANGE_PARAMS p;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_ENABLE;
+ p.Scope = DICS_FLAG_GLOBAL;
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)))
+ {
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data);
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_ENABLE;
+ p.Scope = DICS_FLAG_CONFIGSPECIFIC;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Stop the specified device
+bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_PROPCHANGE_PARAMS p;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_DISABLE;
+ p.Scope = DICS_FLAG_CONFIGSPECIFIC;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Remove the specified device
+bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_REMOVEDEVICE_PARAMS p;
+ SP_DEVINFO_LIST_DETAIL_DATA detail;
+ char device_id[MAX_PATH];
+ CONFIGRET ret;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&detail, sizeof(detail));
+ detail.cbSize = sizeof(detail);
+
+ if (SetupDiGetDeviceInfoListDetail(info, &detail) == false)
+ {
+ Debug("SetupDiGetDeviceInfoListDetail Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ ret = ms->nt->CM_Get_Device_ID_Ex(dev_info_data->DevInst, device_id, sizeof(device_id),
+ 0, detail.RemoteMachineHandle);
+ if (ret != CR_SUCCESS)
+ {
+ Debug("CM_Get_Device_ID_Ex Failed. Err=0x%X\n", ret);
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+ p.Scope = DI_REMOVEDEVICE_GLOBAL;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false)
+ {
+ Debug("SetupDiSetClassInstallParams Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ if (SetupDiCallClassInstaller(DIF_REMOVE, info, dev_info_data) == false)
+ {
+ Debug("SetupDiCallClassInstaller Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ return true;
+}
+
+// Enable the virtual LAN card
+bool MsEnableVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsEnableVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsEnableVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsStartDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Disable the virtual LAN card
+bool MsDisableVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsDisableVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsDisableVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsStopDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Restart the virtual LAN card
+void MsRestartVLan(char *instance_name)
+{
+ Lock(vlan_lock);
+ {
+ MsRestartVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+}
+void MsRestartVLanWithoutLock(char *instance_name)
+{
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ if (MsIsVLanEnabled(instance_name) == false)
+ {
+ return;
+ }
+
+ MsDisableVLan(instance_name);
+ MsEnableVLan(instance_name);
+}
+
+// Get whether the virtual LAN card is working
+bool MsIsVLanEnabled(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsIsVLanEnabledWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsIsVLanEnabledWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsIsDeviceRunning(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Uninstall the virtual LAN card
+bool MsUninstallVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsUninstallVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsUninstallVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsDeleteDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Dispose the device information
+void MsDestroyDevInfo(HDEVINFO info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ SetupDiDestroyDeviceInfoList(info);
+}
+
+// Start the driver installation
+bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver)
+{
+ wchar_t src_inf[MAX_PATH];
+ wchar_t src_sys[MAX_PATH];
+ wchar_t dest_inf[MAX_PATH];
+ wchar_t dest_sys[MAX_PATH];
+ wchar_t src_cat[MAX_PATH];
+ wchar_t dst_cat[MAX_PATH];
+ UCHAR mac_address_bin[6];
+ char mac_address_str[32];
+ UINT size;
+ char *tmp;
+ BUF *b;
+ IO *io;
+ char str_year[16];
+ char str_month[16];
+ char str_day[16];
+ char str_major[16];
+ char str_minor[16];
+ char str_build[16];
+ // Validate arguments
+ if (instance_name == NULL || neo_sys == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ Format(str_year, sizeof(str_year), "%04d", ver->Year);
+ Format(str_month, sizeof(str_month), "%02d", ver->Month);
+ Format(str_day, sizeof(str_day), "%02d", ver->Day);
+
+ ToStr(str_major, ver->Major);
+ ToStr(str_minor, ver->Minor);
+ ToStr(str_build, ver->Build);
+
+ MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
+ Debug("MsStartDriverInstall\n");
+ Debug(" instance_name: %s\n", instance_name);
+ Debug(" src_inf: %S\n", src_inf);
+ Debug(" src_sys: %S\n", src_sys);
+ Debug(" dest_inf: %S\n", dest_inf);
+ Debug(" dest_sys: %S\n", dest_sys);
+ Debug(" src_cat: %S\n", src_cat);
+ Debug(" dst_cat: %S\n", dst_cat);
+ Debug(" neo_sys: %s\n", neo_sys);
+
+ // Processing INF file
+ io = FileOpenW(src_inf, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ size = FileSize(io);
+ tmp = ZeroMalloc(size * 2);
+ if (FileRead(io, tmp, size) == false)
+ {
+ FileClose(io);
+ Free(tmp);
+ return false;
+ }
+
+ FileClose(io);
+
+ if (mac_address == NULL)
+ {
+ MsGenMacAddress(mac_address_bin);
+ }
+ else
+ {
+ Copy(mac_address_bin, mac_address, 6);
+ }
+
+ BinToStr(mac_address_str, sizeof(mac_address_str), mac_address_bin, sizeof(mac_address_bin));
+
+ //ReplaceStrEx(tmp, size * 2, tmp, "$TAG_DRIVER_VER$", DRIVER_VER_STR, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_INSTANCE_NAME$", instance_name, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_MAC_ADDRESS$", mac_address_str, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_SYS_NAME$", neo_sys, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$YEAR$", str_year, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$MONTH$", str_month, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$DAY$", str_day, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_MAJOR$", str_major, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_MINOR$", str_minor, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_BUILD$", str_build, false);
+
+ if (MsIsVista())
+ {
+ //ReplaceStrEx(tmp, size * 2, tmp, "\"100\"", "\"2000\"", false);
+ }
+
+ io = FileCreateW(dest_inf);
+ if (io == NULL)
+ {
+ Free(tmp);
+ return false;
+ }
+
+ FileWrite(io, tmp, StrLen(tmp));
+ FileClose(io);
+
+ Free(tmp);
+
+ // Processing the SYS file
+ b = ReadDumpW(src_sys);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, dest_sys) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeBuf(b);
+
+ // Copy of the catalog file
+ if (IsEmptyUniStr(src_cat) == false && IsEmptyUniStr(dst_cat) == false)
+ {
+ if (FileCopyW(src_cat, dst_cat) == false)
+ {
+ return false;
+ }
+ }
+
+ if (ret_mac_address != NULL)
+ {
+ Copy(ret_mac_address, mac_address_bin, 6);
+ }
+
+ return true;
+}
+
+// Generation of the MAC address
+void MsGenMacAddress(UCHAR *mac)
+{
+ UCHAR hash_src[40];
+ UCHAR hash[20];
+ UINT64 now;
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return;
+ }
+
+ Rand(hash_src, 40);
+ now = SystemTime64();
+ Copy(hash_src, &now, sizeof(now));
+
+ Hash(hash, hash_src, sizeof(hash_src), true);
+
+ mac[0] = 0x00;
+ mac[1] = 0xAC;
+ mac[2] = hash[0];
+ mac[3] = hash[1];
+ mac[4] = hash[2];
+ mac[5] = hash[3];
+}
+
+// Finish the driver installation
+void MsFinishDriverInstall(char *instance_name, char *neo_sys)
+{
+ wchar_t src_inf[MAX_PATH];
+ wchar_t src_sys[MAX_PATH];
+ wchar_t dest_inf[MAX_PATH];
+ wchar_t dest_sys[MAX_PATH];
+ wchar_t src_cat[MAX_SIZE];
+ wchar_t dst_cat[MAX_SIZE];
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
+
+ // Delete the files
+ FileDeleteW(dest_inf);
+ FileDeleteW(dest_sys);
+
+ if (IsEmptyUniStr(dst_cat) == false)
+ {
+ FileDeleteW(dst_cat);
+ }
+}
+
+// Get the path to the driver file
+void MsGetDriverPath(char *instance_name, wchar_t *src_inf, wchar_t *src_sys, wchar_t *dest_inf, wchar_t *dest_sys, wchar_t *src_cat, wchar_t *dest_cat, char *neo_sys)
+{
+ wchar_t *src_filename;
+ wchar_t *src_sys_filename;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ src_filename = DRIVER_INF_FILE_NAME;
+ src_sys_filename = DRIVER_SYS_FILE_NAME;
+
+ if (MsIsNt() == false)
+ {
+ src_filename = DRIVER_INF_FILE_NAME_9X;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_9X;
+ }
+ else if (MsIsIA64() || MsIsX64())
+ {
+ if (MsIsX64())
+ {
+ src_filename = DRIVER_INF_FILE_NAME_X64;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_X64;
+ }
+ else
+ {
+ src_filename = DRIVER_INF_FILE_NAME_IA64;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_IA64;
+ }
+ }
+
+ if (MsIsWindows7())
+ {
+ // Use the NDIS 6.2 driver for Windows 7 or later
+ if (MsIsX64())
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME_X64;
+ }
+ else if (MsIsIA64())
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME_IA64;
+ }
+ else
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME;
+ }
+ }
+
+ if (src_inf != NULL)
+ {
+ if (MsIsInfCatalogRequired() == false)
+ {
+ UniStrCpy(src_inf, MAX_PATH, src_filename);
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetInfCatalogDir(tmp, sizeof(tmp));
+
+ UniFormat(src_inf, MAX_PATH, L"%S\\INF_%S.inf", tmp, instance_name);
+ }
+ }
+
+ if (src_sys != NULL)
+ {
+ UniStrCpy(src_sys, MAX_PATH, src_sys_filename);
+ }
+
+ if (dest_inf != NULL)
+ {
+ char inf_name[MAX_PATH];
+ Format(inf_name, sizeof(inf_name), DRIVER_INSTALL_INF_NAME_TAG, instance_name);
+ UniFormat(dest_inf, MAX_PATH, L"%s\\%S", ms->MyTempDirW, inf_name);
+ }
+
+ if (dest_sys != NULL)
+ {
+ char sys_name[MAX_PATH];
+ StrCpy(sys_name, sizeof(sys_name), neo_sys);
+ UniFormat(dest_sys, MAX_PATH, L"%s\\%S", ms->MyTempDirW, sys_name);
+ }
+
+ if (src_cat != NULL)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetInfCatalogDir(tmp, sizeof(tmp));
+ UniFormat(src_cat, MAX_PATH, L"%S\\inf.cat", tmp);
+ }
+ else
+ {
+ UniStrCpy(src_cat, MAX_PATH, L"");
+ }
+ }
+
+ if (dest_cat != NULL)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ UniFormat(dest_cat, MAX_PATH, L"%s\\inf_%S.cat", ms->MyTempDirW, instance_name);
+ }
+ else
+ {
+ UniStrCpy(dest_cat, MAX_PATH, L"");
+ }
+ }
+}
+void MsGetDriverPathA(char *instance_name, char *src_inf, char *src_sys, char *dest_inf, char *dest_sys, char *src_cat, char *dst_cat, char *neo_sys)
+{
+ wchar_t src_inf_w[MAX_PATH];
+ wchar_t src_sys_w[MAX_PATH];
+ wchar_t dest_inf_w[MAX_PATH];
+ wchar_t dest_sys_w[MAX_PATH];
+ wchar_t src_cat_w[MAX_PATH];
+ wchar_t dst_cat_w[MAX_PATH];
+
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ MsGetDriverPath(instance_name, src_inf_w, src_sys_w, dest_inf_w, dest_sys_w, src_cat_w, dst_cat_w, neo_sys);
+
+ UniToStr(src_inf, MAX_PATH, src_inf_w);
+ UniToStr(src_sys, MAX_PATH, src_sys_w);
+ UniToStr(dest_inf, MAX_PATH, dest_inf_w);
+ UniToStr(dest_sys, MAX_PATH, dest_sys_w);
+ UniToStr(src_cat, MAX_PATH, src_cat_w);
+ UniToStr(dst_cat, MAX_PATH, dst_cat_w);
+}
+
+// Examine whether the virtual LAN card with the specified name has already registered
+bool MsIsVLanExists(char *tag_name, char *instance_name)
+{
+ char *guid;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL)
+ {
+ return false;
+ }
+
+ guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Free(guid);
+ return true;
+}
+
+// Create a temporary file based on the extension
+IO *MsCreateTempFileByExt(char *ext)
+{
+ char *tmp = MsCreateTempFileNameByExt(ext);
+ IO *ret;
+
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = FileCreate(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Create a temporary file with the specified extension
+char *MsCreateTempFileNameByExt(char *ext)
+{
+ UCHAR rand[2];
+ char *ret = NULL;
+ // Validate arguments
+ if (ext == NULL)
+ {
+ ext = "tmp";
+ }
+ if (ext[0] == '.')
+ {
+ ext++;
+ }
+ if (StrLen(ext) == 0)
+ {
+ ext = "tmp";
+ }
+
+ while (true)
+ {
+ char new_filename[MAX_PATH];
+ char *fullpath;
+ char rand_str[MAX_PATH];
+ IO *io;
+ Rand(rand, sizeof(rand));
+
+ BinToStr(rand_str, sizeof(rand_str), rand, sizeof(rand));
+ Format(new_filename, sizeof(new_filename), "__%s.%s", rand_str, ext);
+
+ fullpath = MsCreateTempFileName(new_filename);
+ io = FileOpen(fullpath, false);
+ if (io == NULL)
+ {
+ ret = fullpath;
+ break;
+ }
+ FileClose(io);
+
+ Free(fullpath);
+ }
+
+ return ret;
+}
+
+// Create a temporary file
+IO *MsCreateTempFile(char *name)
+{
+ IO *ret;
+ char *tmp;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ tmp = MsCreateTempFileName(name);
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = FileCreate(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Create a temporary file name
+char *MsCreateTempFileName(char *name)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp, sizeof(tmp), "%s\\%s", ms->MyTempDir, name);
+
+ return CopyStr(tmp);
+}
+
+// Delete VPN temporary directories that remain in the system but not used
+void MsDeleteTempDir()
+{
+ HANDLE h;
+ wchar_t dir_mask[MAX_PATH];
+ WIN32_FIND_DATAA data_a;
+ WIN32_FIND_DATAW data_w;
+
+ Zero(&data_a, sizeof(data_a));
+ Zero(&data_w, sizeof(data_w));
+
+ UniFormat(dir_mask, sizeof(dir_mask), L"%s\\*", ms->TempDirW);
+
+ if (IsNt())
+ {
+ h = FindFirstFileW(dir_mask, &data_w);
+ }
+ else
+ {
+ char *tmp_a = CopyUniToStr(dir_mask);
+
+ h = FindFirstFileA(tmp_a, &data_a);
+
+ Free(tmp_a);
+ }
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ bool b = true;
+
+ do
+ {
+ if (IsNt() == false)
+ {
+ Zero(&data_w, sizeof(data_w));
+ StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
+ data_w.dwFileAttributes = data_a.dwFileAttributes;
+ data_w.ftCreationTime = data_a.ftCreationTime;
+ data_w.ftLastWriteTime = data_a.ftLastWriteTime;
+ data_w.nFileSizeHigh = data_a.nFileSizeHigh;
+ data_w.nFileSizeLow = data_a.nFileSizeLow;
+ }
+
+ if (UniStrCmpi(data_w.cFileName, L".") != 0 &&
+ UniStrCmpi(data_w.cFileName, L"..") != 0)
+ {
+ if (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (UniStartWith(data_w.cFileName, L"VPN_") && UniStrLen(data_w.cFileName) == 8)
+ {
+ wchar_t lock_file_name[MAX_PATH];
+ wchar_t dir_name[MAX_PATH];
+ bool delete_now = false;
+ IO *io;
+
+ UniFormat(dir_name, sizeof(dir_name), L"%s\\%s",
+ ms->TempDirW, data_w.cFileName);
+ MsGenLockFile(lock_file_name, sizeof(lock_file_name), dir_name);
+
+ io = FileOpenExW(lock_file_name, false, false);
+ if (io != NULL)
+ {
+ // Mark to delete if the lock file is not locked
+ FileClose(io);
+ io = FileOpenW(lock_file_name, true);
+ if (io != NULL)
+ {
+ delete_now = true;
+ FileClose(io);
+ }
+ }
+ else
+ {
+ DIRLIST *d;
+
+ // Mark to delete if all files in this folder are not locked
+ delete_now = true;
+
+ d = EnumDirW(dir_name);
+ if (d != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < d->NumFiles;i++)
+ {
+ wchar_t full_path[MAX_PATH];
+
+ UniFormat(full_path, sizeof(full_path), L"%s\\%s", dir_name, d->File[i]->FileNameW);
+
+ io = FileOpenW(full_path, true);
+ if (io != NULL)
+ {
+ delete_now = true;
+ FileClose(io);
+ }
+ }
+ FreeDir(d);
+ }
+ }
+ if (delete_now)
+ {
+ MsDeleteAllFileW(dir_name);
+
+ Win32DeleteDirW(dir_name);
+ }
+ }
+ }
+ }
+
+
+ Zero(&data_w, sizeof(data_w));
+ Zero(&data_a, sizeof(data_a));
+
+ if (IsNt())
+ {
+ b = FindNextFileW(h, &data_w);
+ }
+ else
+ {
+ b = FindNextFileA(h, &data_a);
+ }
+ }
+ while (b);
+
+ FindClose(h);
+ }
+}
+
+// Delete all the files in the specified directory
+void MsDeleteAllFile(char *dir)
+{
+ HANDLE h;
+ char file_mask[MAX_PATH];
+ WIN32_FIND_DATA data;
+ // Validate arguments
+ if (dir == NULL || IsEmptyStr(dir))
+ {
+ return;
+ }
+
+ Format(file_mask, sizeof(file_mask), "%s\\*.*", dir);
+
+ h = FindFirstFile(file_mask, &data);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (StrCmpi(data.cFileName, ".") != 0 &&
+ StrCmpi(data.cFileName, "..") != 0)
+ {
+ char fullpath[MAX_PATH];
+ Format(fullpath, sizeof(fullpath), "%s\\%s", dir, data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
+ {
+ DeleteFile(fullpath);
+ }
+ else
+ {
+ MsDeleteAllFile(fullpath);
+ RemoveDirectory(fullpath);
+ }
+ }
+ }
+ while (FindNextFile(h, &data));
+
+ FindClose(h);
+ }
+}
+void MsDeleteAllFileW(wchar_t *dir)
+{
+ HANDLE h;
+ wchar_t file_mask[MAX_PATH];
+ WIN32_FIND_DATAW data;
+ // Validate arguments
+ if (dir == NULL || UniIsEmptyStr(dir))
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char *dir_a = CopyUniToStr(dir);
+
+ MsDeleteAllFile(dir_a);
+
+ Free(dir_a);
+
+ return;
+ }
+
+ UniFormat(file_mask, sizeof(file_mask), L"%s\\*.*", dir);
+
+ h = FindFirstFileW(file_mask, &data);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (UniStrCmpi(data.cFileName, L".") != 0 &&
+ UniStrCmpi(data.cFileName, L"..") != 0)
+ {
+ wchar_t fullpath[MAX_PATH];
+
+ UniFormat(fullpath, sizeof(fullpath), L"%s\\%s", dir, data.cFileName);
+
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
+ {
+ DeleteFileW(fullpath);
+ }
+ else
+ {
+ MsDeleteAllFileW(fullpath);
+ RemoveDirectoryW(fullpath);
+ }
+ }
+ }
+ while (FindNextFileW(h, &data));
+
+ FindClose(h);
+ }
+}
+
+// Initialize the temporary directory
+void MsInitTempDir()
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[16];
+ UCHAR random[2];
+ wchar_t lockfilename[MAX_PATH];
+ UINT num = 0;
+
+ // Delete the unused temporary directory
+ MsDeleteTempDir();
+
+ // Determine the name of the temporary directory
+ while (true)
+ {
+ random[0] = rand() % 256;
+ random[1] = rand() % 256;
+ BinToStrW(tmp2, sizeof(tmp2), random, sizeof(random));
+
+ UniFormat(tmp, sizeof(tmp), L"%s\\VPN_%s", ms->TempDirW, tmp2);
+
+ // Create Directory
+ if (MakeDirW(tmp))
+ {
+ break;
+ }
+
+ if ((num++) >= 100)
+ {
+ // Failed many times
+ char msg[MAX_SIZE];
+ Format(msg, sizeof(msg),
+ "Couldn't create Temporary Directory: %s\r\n\r\n"
+ "Please contact your system administrator.",
+ tmp);
+ exit(0);
+ }
+ }
+
+ ms->MyTempDirW = CopyUniStr(tmp);
+ ms->MyTempDir = CopyUniToStr(tmp);
+
+ // Create a lock file
+ MsGenLockFile(lockfilename, sizeof(lockfilename), ms->MyTempDirW);
+ ms->LockFile = FileCreateW(lockfilename);
+}
+
+// Release the temporary directory
+void MsFreeTempDir()
+{
+ wchar_t lock_file_name[MAX_SIZE];
+
+ // Delete the lock file
+ MsGenLockFile(lock_file_name, sizeof(lock_file_name), ms->MyTempDirW);
+ FileClose(ms->LockFile);
+
+ // Memory release
+ Free(ms->MyTempDir);
+ Free(ms->MyTempDirW);
+ ms->MyTempDir = NULL;
+ ms->MyTempDirW = NULL;
+
+ // Delete directory
+ MsDeleteTempDir();
+}
+
+// Generation of the name of the lock file
+void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir)
+{
+ // Validate arguments
+ if (name == NULL || temp_dir == NULL)
+ {
+ return;
+ }
+
+ UniFormat(name, size, L"%s\\VPN_Lock.dat", temp_dir);
+}
+
+// Normalization of the configuration of the interface metric of the default gateway in the network configuration
+void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ char netsh[MAX_PATH];
+ char *config_str;
+ char tmp2[MAX_SIZE];
+ UINT if_index;
+ UINT if_metric;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
+
+ if (MsIsVista() == false)
+ {
+ Debug("MsIsVista() == false\n");
+ return;
+ }
+
+ Format(tmp2, sizeof(tmp2), tag_name, instance_name);
+ if_index = Win32GetVLanInterfaceID(tmp2);
+ Debug("if_index=%u\n", if_index);
+
+ if (if_index == 0)
+ {
+ return;
+ }
+
+ CombinePath(netsh, sizeof(netsh), MsGetSystem32Dir(), "netsh.exe");
+
+ // Set the interface metric value
+ config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (config_str != NULL)
+ {
+ LIST *o;
+ LIST *o2;
+
+ Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
+ Debug("if_index(%s) = %u\n", instance_name, if_index);
+
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ config_str);
+
+ o = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGateway");
+ o2 = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGatewayMetric");
+
+ if_metric = MsRegReadInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric");
+ Debug("if_metric = %u\n", if_metric);
+
+ if (if_metric != 0)
+ {
+ if (o != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ char tmp[MAX_SIZE];
+
+ char *cm = NULL;
+ UINT current_metric;
+
+ if (o2 != NULL)
+ {
+ if (LIST_NUM(o2) > i)
+ {
+ current_metric = ToInt(LIST_DATA(o2, i));
+ }
+ }
+
+ Debug("gateway[%u] = %s\n", i, s);
+ Debug("current_metric[%u] = %u\n", i, current_metric);
+
+ if (current_metric == 0)
+ {
+ if (IsEmptyStr(s) == false)
+ {
+ Format(tmp, sizeof(tmp), "int ipv4 delete route prefix=0.0.0.0/0 interface=%u nexthop=%s",
+ if_index, s);
+ Debug("netsh %s\n", tmp);
+ Run(netsh, tmp, true, true);
+
+ Format(tmp, sizeof(tmp), "int ipv4 add route prefix=0.0.0.0/0 interface=%u nexthop=%s metric=%u",
+ if_index, s, if_metric);
+ Debug("netsh %s\n", tmp);
+ Run(netsh, tmp, true, true);
+ }
+ }
+ }
+ }
+ }
+
+ FreeStrList(o);
+ FreeStrList(o2);
+
+ Free(config_str);
+ }
+}
+
+// Initialization of the network configuration
+void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name)
+{
+ char tmp[MAX_SIZE];
+ char *config_str;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL || connection_tag_name == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ // Settings such as string
+ Format(tmp, sizeof(tmp), connection_tag_name, instance_name);
+ MsSetNetworkConfig(tag_name, instance_name, tmp, true);
+
+ // Set the interface metric value
+ config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (config_str != NULL)
+ {
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ config_str);
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric", 1);
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "EnableDeadGWDetect", 0);
+
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "packetix_no_optimize") == 0)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "EnableDeadGWDetect",
+ 0);
+ }
+
+ Free(config_str);
+ }
+}
+
+// Configure the network settings
+void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon)
+{
+ char *key;
+ char *old_name;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL || friendly_name == NULL)
+ {
+ return;
+ }
+
+ key = MsGetNetworkConfigRegKeyNameFromInstanceName(tag_name, instance_name);
+ if (key == NULL)
+ {
+ return;
+ }
+
+ old_name = MsRegReadStr(REG_LOCAL_MACHINE, key, "Name");
+ if (old_name != NULL)
+ {
+ if (MsIsVista())
+ {
+ char arg[MAX_PATH];
+ char netsh[MAX_PATH];
+
+ Format(netsh, sizeof(netsh), "%s\\netsh.exe", MsGetSystem32Dir());
+
+ if (StrCmp(old_name, friendly_name) != 0)
+ {
+ Format(arg, sizeof(arg), "interface set interface name=\"%s\" newname=\"%s\"",
+ old_name, friendly_name);
+
+ Run(netsh, arg, true, true);
+ }
+
+ Format(arg, sizeof(arg), "netsh interface ipv4 set interface interface=\"%s\" metric=1",
+ friendly_name);
+
+ Run(netsh, arg, true, true);
+ }
+ }
+
+ if (StrCmp(old_name, friendly_name) != 0)
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, key, "Name", friendly_name);
+ }
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, key, "ShowIcon", show_icon ? 1 : 0);
+
+ Free(key);
+
+ Free(old_name);
+}
+
+// Get the network configuration key name by the instance name
+char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name)
+{
+ char *guid, *ret;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ ret = MsGetNetworkConfigRegKeyNameFromGuid(guid);
+
+ Free(guid);
+
+ return ret;
+}
+
+// Get the network configuration key name by the GUID
+char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp, sizeof(tmp),
+ "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
+ guid);
+
+ return CopyStr(tmp);
+}
+
+// Configuring the MAC address
+void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char dest_name[MAX_SIZE];
+ char mac_str[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ // Normalization of the MAC address
+ if (NormalizeMacAddress(mac_str, sizeof(mac_str), mac_address) == false)
+ {
+ return;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Writing of the MAC address
+ MsRegWriteStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress", mac_str);
+ Free(driver_desc);
+
+ // Restarting the driver
+ MsRestartVLan(instance_name);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return;
+}
+
+// Get the file name of the device driver
+char *MsGetDriverFileName(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the file name
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DeviceVxDs");
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Get the version of the device driver
+char *MsGetDriverVersion(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *t;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the version information
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverVersion");
+ if (ret == NULL)
+ {
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NeoVersion");
+ }
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ if (ret == NULL)
+ {
+ return NULL;
+ }
+
+ t = ParseToken(ret, ", ");
+ if (t->NumTokens == 2)
+ {
+ Free(ret);
+ ret = CopyStr(t->Token[1]);
+ }
+ FreeToken(t);
+
+ return ret;
+}
+
+// Get the registry key of the NETCFG of the virtual LAN card
+char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ ret = CopyStr(full_key_name);
+
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Get the MAC address
+char *MsGetMacAddress(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the MAC address
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress");
+
+ if (IsEmptyStr(ret) == false)
+ {
+ // Insert hyphens between the MAC address elements
+ BUF *b = StrToBin(ret);
+ if (b != NULL && b->Size == 6)
+ {
+ char tmp[MAX_SIZE];
+ MacToStr(tmp, sizeof(tmp), b->Buf);
+
+ Free(ret);
+ ret = CopyStr(tmp);
+ }
+ FreeBuf(b);
+ }
+
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Check whether the device name of the virtual LAN card exists really
+bool MsCheckVLanDeviceIdFromRootEnum(char *name)
+{
+ TOKEN_LIST *t;
+ char *root;
+ char *keyname;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt())
+ {
+ root = "SYSTEM\\CurrentControlSet\\Enum\\Root\\NET";
+ keyname = "HardwareID";
+ }
+ else
+ {
+ root = "Enum\\Root\\Net";
+ keyname = "CompatibleIDs";
+ }
+
+ t = MsRegEnumKey(REG_LOCAL_MACHINE, root);
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *subname = t->Token[i];
+ char fullname[MAX_SIZE];
+ char *value;
+
+ Format(fullname, sizeof(fullname), "%s\\%s", root, subname);
+
+ value = MsRegReadStr(REG_LOCAL_MACHINE, fullname, keyname);
+ if (value != NULL)
+ {
+ if (StrCmpi(value, name) == 0)
+ {
+ ret = true;
+ }
+ Free(value);
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Get the GUID of the network adapter
+char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the NetCfgInstanceId
+ if (MsIsNt())
+ {
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetCfgInstanceId");
+ }
+ else
+ {
+ ret = CopyStr("");
+ }
+ Free(driver_desc);
+ Free(device_id);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+ Free(device_id);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+// Get the network connection name
+wchar_t *MsGetNetworkConnectionName(char *guid)
+{
+ wchar_t *ncname = NULL;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ // Get the network connection name
+ if (IsNt() != false && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", guid);
+ ncname = MsRegReadStrW(REG_LOCAL_MACHINE, tmp, "Name");
+ }
+
+ return ncname;
+}
+
+// Generate driver file name for the new Neo
+bool MsMakeNewNeoDriverFilename(char *name, UINT size)
+{
+ TOKEN_LIST *t = MsEnumNeoDriverFilenames();
+ UINT i;
+ bool ret = false;
+
+ i = 0;
+ while (true)
+ {
+ char tmp[MAX_PATH];
+ UINT n;
+
+ i++;
+ if (i >= 10000)
+ {
+ break;
+ }
+
+ n = Rand32() % DRIVER_INSTALL_SYS_NAME_TAG_MAXID;
+
+ MsGenerateNeoDriverFilenameFromInt(tmp, sizeof(tmp), n);
+
+ if (IsInToken(t, tmp) == false)
+ {
+ StrCpy(name, size, tmp);
+ ret = true;
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Generate the driver file name of Neo from a integer
+void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n)
+{
+ Format(name, size, DRIVER_INSTALL_SYS_NAME_TAG_NEW, n);
+}
+
+// Enumeration of the driver file names of installed Neo
+TOKEN_LIST *MsEnumNeoDriverFilenames()
+{
+ TOKEN_LIST *neos = MsEnumNetworkAdaptersNeo();
+ LIST *o = NewListFast(NULL);
+ TOKEN_LIST *ret;
+ UINT i;
+
+ for (i = 0;i < neos->NumTokens;i++)
+ {
+ char filename[MAX_PATH];
+ if (MsGetNeoDeiverFilename(filename, sizeof(filename), neos->Token[i]))
+ {
+ Add(o, CopyStr(filename));
+ }
+ }
+
+ FreeToken(neos);
+
+ ret = ListToTokenList(o);
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Get the driver file name of Neo
+bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ char *ret;
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Neo_%s", instance_name);
+
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, tmp, "ImagePath");
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ GetFileNameFromFilePath(name, size, ret);
+ Free(ret);
+
+ return true;
+}
+
+// Enumeration of the network adapter (only Neo)
+TOKEN_LIST *MsEnumNetworkAdaptersNeo()
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *ret;
+ LIST *o;
+ UINT i;
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ // Check whether it starts with the specific name
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ char *tag = "neoadapter_";
+ if (StartWith(device_id, tag))
+ {
+ char tmp[MAX_SIZE];
+ StrCpy(tmp, sizeof(tmp), &device_id[StrLen(tag)]);
+
+ Add(o, CopyStr(tmp));
+ }
+ }
+ Free(device_id);
+ }
+
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(o);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return ret;
+}
+
+// Enumeration of the network adapter
+TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2)
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *ret;
+ LIST *o;
+ UINT i;
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ // Check whether it starts with the specific name
+ if ((IsEmptyStr(start_with_name) && IsEmptyStr(start_with_name_2)) ||
+ (StartWith(driver_desc, start_with_name) || StartWith(driver_desc, start_with_name_2)))
+ {
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ char instance_name[MAX_SIZE];
+ // Extract only the instance name from the name
+ if (StartWith(driver_desc, start_with_name))
+ {
+ if (StrLen(driver_desc) > (StrLen(start_with_name) + 3))
+ {
+ StrCpy(instance_name, sizeof(instance_name),
+ driver_desc + StrLen(start_with_name) + 3);
+ Add(o, CopyStr(instance_name));
+ }
+ }
+ else
+ {
+ if (StrLen(driver_desc) > (StrLen(start_with_name_2) + 3))
+ {
+ StrCpy(instance_name, sizeof(instance_name),
+ driver_desc + StrLen(start_with_name_2) + 3);
+ Add(o, CopyStr(instance_name));
+ }
+ }
+ }
+ Free(device_id);
+ }
+ }
+
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(o);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return ret;
+}
+
+// Attempt to logon to the domain
+bool MsCheckLogon(wchar_t *username, char *password)
+{
+ wchar_t password_unicode[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (username == NULL || password == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ StrToUni(password_unicode, sizeof(password_unicode), password);
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ if (ms->nt->LogonUserW(username, NULL, password_unicode, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ return false;
+ }
+ }
+ else
+ {
+ char username_ansi[MAX_SIZE];
+ UniToStr(username_ansi, sizeof(username_ansi), username);
+
+ if (ms->nt->LogonUserA(username_ansi, NULL, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ return false;
+ }
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Attempt to logon to the domain
+bool MsIsPasswordEmpty(wchar_t *username)
+{
+ HANDLE h;
+ // Validate arguments
+ if (username == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ if (ms->nt->LogonUserW(username, NULL, L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ if (GetLastError() == 1327)
+ {
+ // Password is empty
+ return true;
+ }
+ else
+ {
+ // The password is not correct
+ return false;
+ }
+ }
+ }
+ else
+ {
+ char username_ansi[MAX_SIZE];
+ UniToStr(username_ansi, sizeof(username_ansi), username);
+
+ if (ms->nt->LogonUserA(username_ansi, NULL, "", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ if (GetLastError() == 1327)
+ {
+ // Password is empty
+ return true;
+ }
+ else
+ {
+ // The password is not correct
+ return false;
+ }
+ }
+ }
+
+ CloseHandle(h);
+
+ // Since successful logon, the password should be empty
+ return false;
+}
+
+// Execution of shutdown (NT)
+bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message)
+{
+ if (MsIsNt() == false)
+ {
+ return MsShutdown(reboot, force);
+ }
+
+ // Get the privilege
+ if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
+ {
+ return false;
+ }
+
+ // Execute the shutdown
+ if (ms->nt->InitiateSystemShutdown(NULL, message, time_limit, force, reboot) == false)
+ {
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+ return false;
+ }
+
+ // Release of privilege
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+
+ return true;
+}
+
+// Execute the shutdown
+bool MsShutdown(bool reboot, bool force)
+{
+ UINT flag = 0;
+ // Get the privilege
+ if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
+ {
+ return false;
+ }
+
+ flag |= (reboot ? EWX_REBOOT : EWX_SHUTDOWN);
+ flag |= (force ? EWX_FORCE : 0);
+
+ // Execute the shutdown
+ if (ExitWindowsEx(flag, 0) == false)
+ {
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+ return false;
+ }
+
+ // Release of privilege
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+
+ return true;
+}
+
+// Enable or disable the privilege
+bool MsEnablePrivilege(char *name, bool enable)
+{
+ HANDLE hToken;
+ NT_API *nt = ms->nt;
+ LUID luid;
+ TOKEN_PRIVILEGES *tp;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ // Open the process token
+ if (nt->OpenProcessToken(ms->hCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == false)
+ {
+ return false;
+ }
+
+ // Get a local unique identifier
+ if (nt->LookupPrivilegeValue(NULL, name, &luid) == FALSE)
+ {
+ CloseHandle(hToken);
+ return false;
+ }
+
+ // Create a structure to enable / disable the privilege
+ tp = ZeroMalloc(sizeof(TOKEN_PRIVILEGES));
+ tp->PrivilegeCount = 1;
+ tp->Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
+ Copy(&tp->Privileges[0].Luid, &luid, sizeof(LUID));
+
+ // Manipulate the privilege
+ ret = nt->AdjustTokenPrivileges(hToken, false, tp, sizeof(TOKEN_PRIVILEGES), 0, 0);
+
+ Free(tp);
+ CloseHandle(hToken);
+
+ return ret;
+}
+
+// Get whether the current OS is a NT system
+bool MsIsNt()
+{
+ if (ms == NULL)
+ {
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return ms->IsNt;
+}
+
+// Get whether the current user is an Admin
+bool MsIsAdmin()
+{
+ return ms->IsAdmin;
+}
+
+// Load the NT system function
+NT_API *MsLoadNtApiFunctions()
+{
+ NT_API *nt = ZeroMalloc(sizeof(NT_API));
+ OSVERSIONINFO info;
+
+ Zero(&info, sizeof(info));
+ info.dwOSVersionInfoSize = sizeof(info);
+ GetVersionEx(&info);
+
+ nt->hKernel32 = LoadLibrary("kernel32.dll");
+ if (nt->hKernel32 == NULL)
+ {
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hAdvapi32 = LoadLibrary("advapi32.dll");
+ if (nt->hAdvapi32 == NULL)
+ {
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hShell32 = LoadLibrary("shell32.dll");
+ if (nt->hShell32 == NULL)
+ {
+ FreeLibrary(nt->hAdvapi32);
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hPsApi = LoadLibrary("psapi.dll");
+
+ if (info.dwMajorVersion >= 5)
+ {
+ nt->hNewDev = LoadLibrary("newdev.dll");
+ if (nt->hNewDev == NULL)
+ {
+ FreeLibrary(nt->hShell32);
+ FreeLibrary(nt->hAdvapi32);
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hSetupApi = LoadLibrary("setupapi.dll");
+ }
+
+ nt->hSecur32 = LoadLibrary("secur32.dll");
+
+ nt->hUser32 = LoadLibrary("user32.dll");
+
+ nt->hDbgHelp = LoadLibrary("dbghelp.dll");
+
+ nt->hWcmapi = LoadLibrary("wcmapi.dll");
+
+ nt->hDwmapi = LoadLibrary("dwmapi.dll");
+
+ // Read the function
+ nt->GetComputerNameExW =
+ (BOOL (__stdcall *)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD))
+ GetProcAddress(nt->hKernel32, "GetComputerNameExW");
+
+ nt->IsWow64Process =
+ (BOOL (__stdcall *)(HANDLE,BOOL *))
+ GetProcAddress(nt->hKernel32, "IsWow64Process");
+
+ nt->GetFileInformationByHandle =
+ (BOOL (__stdcall *)(HANDLE,LPBY_HANDLE_FILE_INFORMATION))
+ GetProcAddress(nt->hKernel32, "GetFileInformationByHandle");
+
+ nt->GetProcessHeap =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(nt->hKernel32, "GetProcessHeap");
+
+ nt->SetProcessShutdownParameters =
+ (BOOL (__stdcall *)(DWORD,DWORD))
+ GetProcAddress(nt->hKernel32, "SetProcessShutdownParameters");
+
+ nt->GetNativeSystemInfo =
+ (void (__stdcall *)(SYSTEM_INFO *))
+ GetProcAddress(nt->hKernel32, "GetNativeSystemInfo");
+
+ nt->AdjustTokenPrivileges =
+ (BOOL (__stdcall *)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD))
+ GetProcAddress(nt->hAdvapi32, "AdjustTokenPrivileges");
+
+ nt->LookupPrivilegeValue =
+ (BOOL (__stdcall *)(char *,char *,PLUID))
+ GetProcAddress(nt->hAdvapi32, "LookupPrivilegeValueA");
+
+ nt->OpenProcessToken =
+ (BOOL (__stdcall *)(HANDLE,DWORD,PHANDLE))
+ GetProcAddress(nt->hAdvapi32, "OpenProcessToken");
+
+ nt->InitiateSystemShutdown =
+ (BOOL (__stdcall *)(LPTSTR,LPTSTR,DWORD,BOOL,BOOL))
+ GetProcAddress(nt->hAdvapi32, "InitiateSystemShutdownA");
+
+ nt->LogonUserW =
+ (BOOL (__stdcall *)(wchar_t *,wchar_t *,wchar_t *,DWORD,DWORD,HANDLE *))
+ GetProcAddress(nt->hAdvapi32, "LogonUserW");
+
+ nt->LogonUserA =
+ (BOOL (__stdcall *)(char *,char *,char *,DWORD,DWORD,HANDLE * ))
+ GetProcAddress(nt->hAdvapi32, "LogonUserA");
+
+ nt->DuplicateTokenEx =
+ (BOOL (__stdcall *)(HANDLE,DWORD,SECURITY_ATTRIBUTES *,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,HANDLE *))
+ GetProcAddress(nt->hAdvapi32, "DuplicateTokenEx");
+
+ nt->ConvertStringSidToSidA =
+ (BOOL (__stdcall *)(LPCSTR,PSID *))
+ GetProcAddress(nt->hAdvapi32, "ConvertStringSidToSidA");
+
+ nt->GetTokenInformation =
+ (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD,PDWORD))
+ GetProcAddress(nt->hAdvapi32, "GetTokenInformation");
+
+ nt->SetTokenInformation =
+ (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD))
+ GetProcAddress(nt->hAdvapi32, "SetTokenInformation");
+
+ nt->CreateProcessAsUserA =
+ (BOOL (__stdcall *)(HANDLE,LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION))
+ GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserA");
+
+ nt->CreateProcessAsUserW =
+ (BOOL (__stdcall *)(HANDLE,LPCWSTR,LPWSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION))
+ GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserW");
+
+ nt->LookupAccountSidA =
+ (BOOL (__stdcall *)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
+ GetProcAddress(nt->hAdvapi32, "LookupAccountSidA");
+
+ nt->LookupAccountNameA =
+ (BOOL (__stdcall *)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
+ GetProcAddress(nt->hAdvapi32, "LookupAccountNameA");
+
+ nt->SetNamedSecurityInfoW =
+ (DWORD (__stdcall *)(LPWSTR,UINT,SECURITY_INFORMATION,PSID,PSID,PACL,PACL))
+ GetProcAddress(nt->hAdvapi32, "SetNamedSecurityInfoW");
+
+ nt->AddAccessAllowedAceEx =
+ (BOOL (__stdcall *)(PACL,DWORD,DWORD,DWORD,PSID))
+ GetProcAddress(nt->hAdvapi32, "AddAccessAllowedAceEx");
+
+ nt->QueryFullProcessImageNameA =
+ (BOOL (__stdcall *)(HANDLE,DWORD,LPSTR,PDWORD))
+ GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameA");
+
+ nt->QueryFullProcessImageNameW =
+ (BOOL (__stdcall *)(HANDLE,DWORD,LPWSTR,PDWORD))
+ GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameW");
+
+ if (info.dwMajorVersion >= 5)
+ {
+ nt->UpdateDriverForPlugAndPlayDevicesW =
+ (BOOL (__stdcall *)(HWND,wchar_t *,wchar_t *,UINT,BOOL *))
+ GetProcAddress(nt->hNewDev, "UpdateDriverForPlugAndPlayDevicesW");
+
+ nt->CM_Get_Device_ID_ExA =
+ (UINT (__stdcall *)(DWORD,char *,UINT,UINT,HANDLE))
+ GetProcAddress(nt->hSetupApi, "CM_Get_Device_ID_ExA");
+
+ nt->CM_Get_DevNode_Status_Ex =
+ (UINT (__stdcall *)(UINT *,UINT *,DWORD,UINT,HANDLE))
+ GetProcAddress(nt->hSetupApi, "CM_Get_DevNode_Status_Ex");
+ }
+
+ nt->hWtsApi32 = LoadLibrary("wtsapi32.dll");
+ if (nt->hWtsApi32 != NULL)
+ {
+ // Terminal Services related API
+ nt->WTSQuerySessionInformation =
+ (UINT (__stdcall *)(HANDLE,DWORD,WTS_INFO_CLASS,wchar_t *,DWORD *))
+ GetProcAddress(nt->hWtsApi32, "WTSQuerySessionInformationW");
+ nt->WTSFreeMemory =
+ (void (__stdcall *)(void *))
+ GetProcAddress(nt->hWtsApi32, "WTSFreeMemory");
+ nt->WTSDisconnectSession =
+ (BOOL (__stdcall *)(HANDLE,DWORD,BOOL))
+ GetProcAddress(nt->hWtsApi32, "WTSDisconnectSession");
+ nt->WTSEnumerateSessionsA =
+ (BOOL (__stdcall *)(HANDLE,DWORD,DWORD,PWTS_SESSION_INFOA *,DWORD *))
+ GetProcAddress(nt->hWtsApi32, "WTSEnumerateSessionsA");
+ }
+
+ // Service related API
+ nt->OpenSCManager =
+ (SC_HANDLE (__stdcall *)(LPCTSTR,LPCTSTR,DWORD))
+ GetProcAddress(nt->hAdvapi32, "OpenSCManagerA");
+ nt->CreateServiceA =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR))
+ GetProcAddress(nt->hAdvapi32, "CreateServiceA");
+ nt->CreateServiceW =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCWSTR,LPCWSTR,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPCWSTR,LPDWORD,LPCWSTR,LPCWSTR,LPCWSTR))
+ GetProcAddress(nt->hAdvapi32, "CreateServiceW");
+ nt->ChangeServiceConfig2 =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPVOID))
+ GetProcAddress(nt->hAdvapi32, "ChangeServiceConfig2W");
+ nt->CloseServiceHandle =
+ (BOOL (__stdcall *)(SC_HANDLE))
+ GetProcAddress(nt->hAdvapi32, "CloseServiceHandle");
+ nt->OpenService =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,DWORD))
+ GetProcAddress(nt->hAdvapi32, "OpenServiceA");
+ nt->QueryServiceStatus =
+ (BOOL (__stdcall *)(SC_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "QueryServiceStatus");
+ nt->StartService =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPCTSTR))
+ GetProcAddress(nt->hAdvapi32, "StartServiceA");
+ nt->ControlService =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "ControlService");
+ nt->SetServiceStatus =
+ (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "SetServiceStatus");
+ nt->RegisterServiceCtrlHandler =
+ (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
+ GetProcAddress(nt->hAdvapi32, "RegisterServiceCtrlHandlerW");
+ nt->StartServiceCtrlDispatcher =
+ (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
+ GetProcAddress(nt->hAdvapi32, "StartServiceCtrlDispatcherW");
+ nt->DeleteService =
+ (BOOL (__stdcall *)(SC_HANDLE))
+ GetProcAddress(nt->hAdvapi32, "DeleteService");
+ nt->RegisterEventSourceW =
+ (HANDLE (__stdcall *)(LPCWSTR,LPCWSTR))
+ GetProcAddress(nt->hAdvapi32, "RegisterEventSourceW");
+ nt->ReportEventW =
+ (BOOL (__stdcall *)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCWSTR *,LPVOID))
+ GetProcAddress(nt->hAdvapi32, "ReportEventW");
+ nt->DeregisterEventSource =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(nt->hAdvapi32, "DeregisterEventSource");
+ nt->Wow64DisableWow64FsRedirection =
+ (BOOL (__stdcall *)(void **))
+ GetProcAddress(nt->hKernel32, "Wow64DisableWow64FsRedirection");
+ nt->Wow64EnableWow64FsRedirection =
+ (BOOLEAN (__stdcall *)(BOOLEAN))
+ GetProcAddress(nt->hKernel32, "Wow64EnableWow64FsRedirection");
+ nt->Wow64RevertWow64FsRedirection =
+ (BOOL (__stdcall *)(void *))
+ GetProcAddress(nt->hKernel32, "Wow64RevertWow64FsRedirection");
+
+ if (nt->hPsApi != NULL)
+ {
+ // Process related API
+ nt->EnumProcesses =
+ (BOOL (__stdcall *)(DWORD *,DWORD,DWORD *))
+ GetProcAddress(nt->hPsApi, "EnumProcesses");
+
+ nt->EnumProcessModules =
+ (BOOL (__stdcall *)(HANDLE,HMODULE * ,DWORD,DWORD *))
+ GetProcAddress(nt->hPsApi, "EnumProcessModules");
+
+ nt->GetModuleFileNameExA =
+ (DWORD (__stdcall *)(HANDLE,HMODULE,LPSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetModuleFileNameExA");
+
+ nt->GetModuleFileNameExW =
+ (DWORD (__stdcall *)(HANDLE,HMODULE,LPWSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetModuleFileNameExW");
+
+ nt->GetProcessImageFileNameA =
+ (DWORD (__stdcall *)(HANDLE,LPSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetProcessImageFileNameA");
+
+ nt->GetProcessImageFileNameW =
+ (DWORD (__stdcall *)(HANDLE,LPWSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetProcessImageFileNameW");
+ }
+
+ // Registry related API
+ nt->RegDeleteKeyExA =
+ (LONG (__stdcall *)(HKEY,LPCTSTR,REGSAM,DWORD))
+ GetProcAddress(nt->hAdvapi32, "RegDeleteKeyExA");
+
+ // Security related API
+ if (nt->hSecur32 != NULL)
+ {
+ nt->GetUserNameExA =
+ (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPSTR,PULONG))
+ GetProcAddress(nt->hSecur32, "GetUserNameExA");
+
+ nt->GetUserNameExW =
+ (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPWSTR,PULONG))
+ GetProcAddress(nt->hSecur32, "GetUserNameExW");
+
+ nt->LsaConnectUntrusted =
+ (NTSTATUS (__stdcall *)(PHANDLE))
+ GetProcAddress(nt->hSecur32, "LsaConnectUntrusted");
+
+ nt->LsaLookupAuthenticationPackage =
+ (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,PULONG))
+ GetProcAddress(nt->hSecur32, "LsaLookupAuthenticationPackage");
+
+ nt->LsaLogonUser =
+ (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,SECURITY_LOGON_TYPE,ULONG,PVOID,ULONG,PTOKEN_GROUPS,PTOKEN_SOURCE,PVOID,PULONG,PLUID,PHANDLE,PQUOTA_LIMITS,PNTSTATUS))
+ GetProcAddress(nt->hSecur32, "LsaLogonUser");
+
+ nt->LsaDeregisterLogonProcess =
+ (NTSTATUS (__stdcall *)(HANDLE))
+ GetProcAddress(nt->hSecur32, "LsaDeregisterLogonProcess");
+
+ nt->LsaFreeReturnBuffer =
+ (NTSTATUS (__stdcall *)(PVOID))
+ GetProcAddress(nt->hSecur32, "LsaFreeReturnBuffer");
+ }
+
+ // WCM related API of Windows 8
+ if (nt->hWcmapi != NULL)
+ {
+ nt->WcmQueryProperty =
+ (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,PDWORD,PBYTE *))
+ GetProcAddress(nt->hWcmapi, "WcmQueryProperty");
+
+ nt->WcmSetProperty =
+ (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,DWORD,const BYTE *))
+ GetProcAddress(nt->hWcmapi, "WcmSetProperty");
+
+ nt->WcmFreeMemory =
+ (void (__stdcall *)(PVOID))
+ GetProcAddress(nt->hWcmapi, "WcmFreeMemory");
+
+ nt->WcmGetProfileList =
+ (DWORD (__stdcall *)(PVOID,MS_WCM_PROFILE_INFO_LIST **))
+ GetProcAddress(nt->hWcmapi, "WcmGetProfileList");
+ }
+
+ nt->AllocateLocallyUniqueId =
+ (BOOL (__stdcall *)(PLUID))
+ GetProcAddress(nt->hAdvapi32, "AllocateLocallyUniqueId");
+
+ // Desktop related API
+ if (nt->hUser32 != NULL)
+ {
+ nt->SwitchDesktop =
+ (BOOL (__stdcall *)(HDESK))
+ GetProcAddress(nt->hUser32, "SwitchDesktop");
+ nt->OpenDesktopA =
+ (HDESK (__stdcall *)(LPTSTR,DWORD,BOOL,ACCESS_MASK))
+ GetProcAddress(nt->hUser32, "OpenDesktopA");
+ nt->CloseDesktop =
+ (BOOL (__stdcall *)(HDESK))
+ GetProcAddress(nt->hUser32, "CloseDesktop");
+ }
+
+ // DWM API
+ if (nt->hDwmapi)
+ {
+ nt->DwmIsCompositionEnabled =
+ (HRESULT (__stdcall *)(BOOL *))
+ GetProcAddress(nt->hDwmapi, "DwmIsCompositionEnabled");
+ }
+
+ // Debug related API
+ if (nt->hDbgHelp != NULL)
+ {
+ nt->MiniDumpWriteDump =
+ (BOOL (__stdcall *)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,PMINIDUMP_EXCEPTION_INFORMATION,PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION))
+ GetProcAddress(nt->hDbgHelp, "MiniDumpWriteDump");
+ }
+
+ return nt;
+}
+
+// Release of NT system function
+void MsFreeNtApiFunctions(NT_API *nt)
+{
+ // Validate arguments
+ if (nt == NULL)
+ {
+ return;
+ }
+
+ if (nt->hSecur32 != NULL)
+ {
+ FreeLibrary(nt->hSecur32);
+ }
+
+ if (nt->hNewDev != NULL)
+ {
+ FreeLibrary(nt->hSetupApi);
+ FreeLibrary(nt->hNewDev);
+ }
+
+ FreeLibrary(nt->hAdvapi32);
+
+ FreeLibrary(nt->hShell32);
+
+ if (nt->hWtsApi32 != NULL)
+ {
+ FreeLibrary(nt->hWtsApi32);
+ }
+
+ if (nt->hPsApi != NULL)
+ {
+ FreeLibrary(nt->hPsApi);
+ }
+
+ if (nt->hUser32 != NULL)
+ {
+ FreeLibrary(nt->hUser32);
+ }
+
+ if (nt->hDbgHelp != NULL)
+ {
+ FreeLibrary(nt->hDbgHelp);
+ }
+
+ if (nt->hWcmapi != NULL)
+ {
+ FreeLibrary(nt->hWcmapi);
+ }
+
+ if (nt->hDwmapi != NULL)
+ {
+ FreeLibrary(nt->hDwmapi);
+ }
+
+ FreeLibrary(nt->hKernel32);
+
+ Free(nt);
+}
+
+// Get whether the screen color is like to Aero of Windows Vista or later
+bool MsIsAeroColor()
+{
+ UINT r;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (MsIsVista() == false)
+ {
+ return false;
+ }
+
+ r = GetSysColor(COLOR_MENU);
+ if (r == 0xFFFFFF || r == 0xF0F0F0 || r >= 0xF00000)
+ {
+ return true;
+ }
+
+ if (MsIsAeroEnabled())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get whether Aero is enabled
+bool MsIsAeroEnabled()
+{
+ bool ret;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->DwmIsCompositionEnabled == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ if (ms->nt->DwmIsCompositionEnabled(&ret) != S_OK)
+ {
+ return false;
+ }
+
+ return ret;
+}
+
+// Generate an access mask to force accessing to the 32 bit registry key for 64 bit application
+DWORD MsRegAccessMaskFor64Bit(bool force32bit)
+{
+ return MsRegAccessMaskFor64BitEx(force32bit, false);
+}
+DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit)
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return 0;
+ }
+ if (force32bit)
+ {
+ return KEY_WOW64_32KEY;
+ }
+ if (force64bit)
+ {
+ return KEY_WOW64_64KEY;
+ }
+
+ return 0;
+}
+
+// Delete the value
+bool MsRegDeleteValue(UINT root, char *keyname, char *valuename)
+{
+ return MsRegDeleteValueEx(root, keyname, valuename, false);
+}
+bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegDeleteValueEx2(root, keyname, valuename, force32bit, false);
+}
+bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ bool ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (RegDeleteValue(h, valuename) != ERROR_SUCCESS)
+ {
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+ RegCloseKey(h);
+
+ return ret;
+}
+
+// Delete the key
+bool MsRegDeleteKey(UINT root, char *keyname)
+{
+ return MsRegDeleteKeyEx(root, keyname, false);
+}
+bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegDeleteKeyEx2(root, keyname, force32bit, false);
+}
+bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() && ms->nt->RegDeleteKeyExA != NULL)
+ {
+ if (ms->nt->RegDeleteKeyExA(MsGetRootKeyFromInt(root), keyname, MsRegAccessMaskFor64BitEx(force32bit, force64bit), 0) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (RegDeleteKey(MsGetRootKeyFromInt(root), keyname) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Enumeration of values
+TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname)
+{
+ return MsRegEnumValueEx(root, keyname, false);
+}
+TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegEnumValueEx2(root, keyname, force32bit, false);
+}
+TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT i;
+ TOKEN_LIST *t;
+ LIST *o;
+
+ if (keyname == NULL)
+ {
+ h = MsGetRootKeyFromInt(root);
+ }
+ else
+ {
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;;i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT ret;
+ UINT size = sizeof(tmp);
+
+ Zero(tmp, sizeof(tmp));
+ ret = RegEnumValue(h, i, tmp, &size, NULL, NULL, NULL, NULL);
+ if (ret == ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ if (keyname != NULL)
+ {
+ RegCloseKey(h);
+ }
+
+ return t;
+}
+
+// Enumeration of the keys
+TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname)
+{
+ return MsRegEnumKeyEx(root, keyname, false);
+}
+TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegEnumKeyEx2(root, keyname, force32bit, false);
+}
+TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT i;
+ TOKEN_LIST *t;
+ LIST *o;
+
+ if (keyname == NULL)
+ {
+ h = MsGetRootKeyFromInt(root);
+ }
+ else
+ {
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;;i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT ret;
+ UINT size = sizeof(tmp);
+ FILETIME ft;
+
+ Zero(tmp, sizeof(tmp));
+ ret = RegEnumKeyEx(h, i, tmp, &size, NULL, NULL, NULL, &ft);
+ if (ret == ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ if (keyname != NULL)
+ {
+ RegCloseKey(h);
+ }
+
+ return t;
+}
+
+// Set the binary data
+bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size)
+{
+ return MsRegWriteBinEx(root, keyname, valuename, data, size, false);
+}
+bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteBinEx2(root, keyname, valuename, data, size, force32bit, false);
+}
+bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_BINARY, data, size, force32bit, force64bit);
+}
+
+// Set the integer value
+bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value)
+{
+ return MsRegWriteIntEx(root, keyname, valuename, value, false);
+}
+bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit)
+{
+ return MsRegWriteIntEx2(root, keyname, valuename, value, force32bit, false);
+}
+bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Endian correction
+ if (IsBigEndian())
+ {
+ value = Swap32(value);
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_DWORD_LITTLE_ENDIAN, &value, sizeof(UINT), force32bit, force64bit);
+}
+
+// Set the string
+bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str)
+{
+ return MsRegWriteStrExpandEx(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
+{
+ return MsRegWriteStrExpandEx2(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_EXPAND_SZ, str, StrSize(str), force32bit, force64bit);
+}
+bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str)
+{
+ return MsRegWriteStrExpandExW(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
+{
+ return MsRegWriteStrExpandEx2W(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2W(root, keyname, valuename, REG_EXPAND_SZ, str, UniStrSize(str), force32bit, force64bit);
+}
+
+bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str)
+{
+ return MsRegWriteStrEx(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
+{
+ return MsRegWriteStrEx2(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_SZ, str, StrSize(str), force32bit, force64bit);
+}
+bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str)
+{
+ return MsRegWriteStrExW(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
+{
+ return MsRegWriteStrEx2W(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2W(root, keyname, valuename, REG_SZ, str, UniStrSize(str), force32bit, force64bit);
+}
+
+// Set the value
+bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
+{
+ return MsRegWriteValueEx(root, keyname, valuename, type, data, size, false);
+}
+bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteValueEx2(root, keyname, valuename, type, data, size, force32bit, false);
+}
+bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ // Create a key
+ MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Write the value
+ if (RegSetValueEx(h, valuename, 0, type, data, size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Close the key
+ RegCloseKey(h);
+
+ return true;
+}
+bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
+{
+ return MsRegWriteValueExW(root, keyname, valuename, type, data, size, false);
+}
+bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteValueEx2W(root, keyname, valuename, type, data, size, force32bit, false);
+}
+bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ UINT size_a;
+ void *data_a;
+ bool ret;
+
+ if (type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ)
+ {
+ data_a = CopyUniToStr(data);
+ size_a = StrSize(data_a);
+ }
+ else
+ {
+ data_a = Clone(data, size);
+ size_a = size;
+ }
+
+ ret = MsRegWriteValueEx2(root, keyname, valuename, type, data_a, size_a, force32bit, force64bit);
+
+ Free(data_a);
+
+ return ret;
+ }
+
+ // Create a key
+ MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Write the value
+ if (RegSetValueExW(h, valuename_w, 0, type, data, size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(h);
+ Free(valuename_w);
+ return false;
+ }
+
+ // Close the key
+ RegCloseKey(h);
+ Free(valuename_w);
+
+ return true;
+}
+
+// Get the binary data
+BUF *MsRegReadBin(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadBinEx(root, keyname, valuename, false);
+}
+BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadBinEx2(root, keyname, valuename, force32bit, false);
+}
+BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ BUF *b;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return 0;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return 0;
+ }
+
+ b = NewBuf();
+
+ WriteBuf(b, ret, size);
+ SeekBuf(b, 0, 0);
+
+ Free(ret);
+
+ return b;
+}
+
+// Get an integer value
+UINT MsRegReadInt(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadIntEx(root, keyname, valuename, false);
+}
+UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadIntEx2(root, keyname, valuename, force32bit, false);
+}
+UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ UINT value;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return 0;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return 0;
+ }
+
+ // Check the type
+ if (type != REG_DWORD_LITTLE_ENDIAN && type != REG_DWORD_BIG_ENDIAN)
+ {
+ // It is not a DWORD
+ Free(ret);
+ return 0;
+ }
+
+ // Check the size
+ if (size != sizeof(UINT))
+ {
+ Free(ret);
+ return 0;
+ }
+
+ Copy(&value, ret, sizeof(UINT));
+
+ Free(ret);
+
+ // Endian conversion
+ if (IsLittleEndian())
+ {
+#ifdef REG_DWORD_BIG_ENDIAN
+ if (type == REG_DWORD_BIG_ENDIAN)
+ {
+ value = Swap32(value);
+ }
+#endif // REG_DWORD_BIG_ENDIAN
+ }
+ else
+ {
+#ifdef REG_DWORD_LITTLE_ENDIAN_FLAG
+ if (type == REG_DWORD_LITTLE_ENDIAN_FLAG)
+ {
+ value = Swap32(value);
+ }
+#endif // REG_DWORD_LITTLE_ENDIAN_FLAG
+ }
+
+ return value;
+}
+
+// Get a string list
+LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrListEx(root, keyname, valuename, false);
+}
+LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrListEx2(root, keyname, valuename, force32bit, false);
+}
+LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ LIST *o;
+ char *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_MULTI_SZ)
+ {
+ // It is not a string list
+ Free(ret);
+ return NULL;
+ }
+
+ if (size < 2)
+ {
+ // Invalid size
+ Free(ret);
+ return NULL;
+ }
+
+ if (ret[size - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ // Creating a list
+ o = StrToStrList(ret, size);
+
+ Free(ret);
+
+ return o;
+}
+
+// Get a string
+char *MsRegReadStr(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrEx(root, keyname, valuename, false);
+}
+char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrEx2(root, keyname, valuename, force32bit, false);
+}
+char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ)
+ {
+ // It is not a string
+ Free(ret);
+
+ if (type == REG_MULTI_SZ)
+ {
+ // It is a string list
+ LIST *o = MsRegReadStrList(root, keyname, valuename);
+ if (o != NULL)
+ {
+ if (LIST_NUM(o) >= 1)
+ {
+ ret = CopyStr(LIST_DATA(o, 0));
+ FreeStrList(o);
+ return ret;
+ }
+ }
+ }
+ return NULL;
+ }
+
+ if (size == 0)
+ {
+ // Invalid size
+ Free(ret);
+
+ return CopyStr("");
+ }
+
+ if (ret[size - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrExW(root, keyname, valuename, false);
+}
+wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrEx2W(root, keyname, valuename, force32bit, false);
+}
+wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ wchar_t *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2W(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_SZ && type != REG_EXPAND_SZ)
+ {
+ // It is not a string
+ Free(ret);
+
+ return NULL;
+ }
+
+ if (ret[size / sizeof(wchar_t) - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+// Read the value
+bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
+{
+ return MsRegReadValueEx(root, keyname, valuename, data, type, size, false);
+}
+bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegReadValueEx2(root, keyname, valuename, data, type, size, force32bit, false);
+}
+bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL || data == NULL || type == NULL || size == NULL)
+ {
+ return false;
+ }
+ *type = 0;
+ *size = 0;
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ *data = ZeroMalloc(*size);
+ ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ // Reading is complete
+ RegCloseKey(h);
+ return true;
+ }
+
+ if (ret != ERROR_MORE_DATA)
+ {
+ // Strange error occurs
+ Free(*data);
+ *data = NULL;
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Get the data by re-allocating memory
+ *data = ReAlloc(*data, *size);
+ ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
+ if (ret != ERROR_SUCCESS)
+ {
+ // An error has occured
+ Free(*data);
+ *data = NULL;
+ RegCloseKey(h);
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
+{
+ return MsRegReadValueExW(root, keyname, valuename, data, type, size, false);
+}
+bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegReadValueEx2W(root, keyname, valuename, data, type, size, force32bit, false);
+}
+bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL || data == NULL || type == NULL || size == NULL)
+ {
+ return false;
+ }
+ *type = 0;
+ *size = 0;
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ void *data_a = NULL;
+ UINT type_a = 0, size_a = 0;
+
+ ret = MsRegReadValueEx2(root, keyname, valuename, &data_a, &type_a, &size_a, force32bit, force64bit);
+
+ if (ret != false)
+ {
+ if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
+ {
+ *data = CopyStrToUni(data_a);
+ Free(data_a);
+
+ size_a = UniStrSize(*data);
+ }
+ else
+ {
+ *data = data_a;
+ }
+
+ *type = type_a;
+ *size = size_a;
+ }
+
+ return ret;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Open up the value
+ *data = ZeroMalloc(*size);
+ ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ // Reading is complete
+ RegCloseKey(h);
+ Free(valuename_w);
+ return true;
+ }
+
+ if (ret != ERROR_MORE_DATA)
+ {
+ // Strange error occurs
+ Free(*data);
+ *data = NULL;
+ Free(valuename_w);
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Get the data by re-allocating memory
+ *data = ReAlloc(*data, *size);
+ ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
+ if (ret != ERROR_SUCCESS)
+ {
+ // An error has occured
+ Free(*data);
+ *data = NULL;
+ Free(valuename_w);
+ RegCloseKey(h);
+ }
+
+ Free(valuename_w);
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Get the size and type of value
+bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
+{
+ return MsRegGetValueTypeAndSizeEx(root, keyname, valuename, type, size, false);
+}
+bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, type, size, force32bit, false);
+}
+bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+ if (type != NULL)
+ {
+ *type = 0;
+ }
+ if (size != NULL)
+ {
+ *size = 0;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ ret = RegQueryValueEx(h, valuename, 0, type, NULL, size);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
+{
+ return MsRegGetValueTypeAndSizeExW(root, keyname, valuename, type, size, false);
+}
+bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegGetValueTypeAndSizeEx2W(root, keyname, valuename, type, size, force32bit, false);
+}
+bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+ if (type != NULL)
+ {
+ *type = 0;
+ }
+ if (size != NULL)
+ {
+ *size = 0;
+ }
+ if (IsNt() == false)
+ {
+ UINT type_a = 0;
+ UINT size_a = 0;
+
+ bool ret = MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, &type_a, &size_a, force32bit, force64bit);
+
+ if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
+ {
+ size_a = size_a * sizeof(wchar_t);
+ }
+
+ if (type != NULL)
+ {
+ *type = type_a;
+ }
+
+ if (size != NULL)
+ {
+ *size = size_a;
+ }
+
+ return ret;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Open up the value
+ ret = RegQueryValueExW(h, valuename_w, 0, type, NULL, size);
+
+ Free(valuename_w);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+
+// Confirm that the specified value exists on the registry
+bool MsRegIsValue(UINT root, char *keyname, char *valuename)
+{
+ return MsRegIsValueEx(root, keyname, valuename, false);
+}
+bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegIsValueEx2(root, keyname, valuename, force32bit, false);
+}
+bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT type, size;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ size = 0;
+ ret = RegQueryValueEx(h, valuename, 0, &type, NULL, &size);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+
+// Create a key in the registry
+bool MsRegNewKey(UINT root, char *keyname)
+{
+ return MsRegNewKeyEx(root, keyname, false);
+}
+bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegNewKeyEx2(root, keyname, force32bit, false);
+}
+bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Confirm whether there is the key
+ if (MsRegIsKeyEx2(root, keyname, force32bit, force64bit))
+ {
+ // Already exists
+ return true;
+ }
+
+ // Create a key
+ if (RegCreateKeyEx(MsGetRootKeyFromInt(root), keyname, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), NULL, &h, NULL) != ERROR_SUCCESS)
+ {
+ // Failed
+ return false;
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Confirm the specified key exists on the registry
+bool MsRegIsKey(UINT root, char *name)
+{
+ return MsRegIsKeyEx(root, name, false);
+}
+bool MsRegIsKeyEx(UINT root, char *name, bool force32bit)
+{
+ return MsRegIsKeyEx2(root, name, force32bit, false);
+}
+bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), name, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Getting root key handle
+HKEY MsGetRootKeyFromInt(UINT root)
+{
+ switch (root)
+ {
+ case REG_CLASSES_ROOT:
+ return HKEY_CLASSES_ROOT;
+
+ case REG_LOCAL_MACHINE:
+ return HKEY_LOCAL_MACHINE;
+
+ case REG_CURRENT_USER:
+ return HKEY_CURRENT_USER;
+
+ case REG_USERS:
+ return HKEY_USERS;
+ }
+
+ return NULL;
+}
+
+// Cut the executable file name from the command line string (Unicode version)
+wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ if (str[0] != L'\"')
+ {
+ UINT i = UniSearchStrEx(str, L" ", 0, true);
+ if (i == INFINITE)
+ {
+ return str + UniStrLen(str);
+ }
+ else
+ {
+ return str + i + 1;
+ }
+ }
+ else
+ {
+ str++;
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + UniStrLen(str);
+ }
+ if ((*str) == L'\"')
+ {
+ break;
+ }
+ str++;
+ }
+
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + UniStrLen(str);
+ }
+ if ((*str) == L' ')
+ {
+ return str + 1;
+ }
+ str++;
+ }
+ }
+}
+
+// Cut the executable file name from the command line string
+char *MsCutExeNameFromCommandLine(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ if (str[0] != '\"')
+ {
+ UINT i = SearchStrEx(str, " ", 0, true);
+ if (i == INFINITE)
+ {
+ return str + StrLen(str);
+ }
+ else
+ {
+ return str + i + 1;
+ }
+ }
+ else
+ {
+ str++;
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + StrLen(str);
+ }
+ if ((*str) == '\"')
+ {
+ break;
+ }
+ str++;
+ }
+
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + StrLen(str);
+ }
+ if ((*str) == ' ')
+ {
+ return str + 1;
+ }
+ str++;
+ }
+ }
+}
+
+// Get the Process handle
+void *MsGetCurrentProcess()
+{
+ return ms->hCurrentProcess;
+}
+
+// Get the Process ID
+UINT MsGetCurrentProcessId()
+{
+ return ms->CurrentProcessId;
+}
+
+// Get the EXE file name
+char *MsGetExeFileName()
+{
+ return ms == NULL ? "Unknown" : ms->ExeFileName;
+}
+
+// Get the name of the directory where the EXE file is in
+char *MsGetExeDirName()
+{
+ return ms->ExeFileDir;
+}
+wchar_t *MsGetExeDirNameW()
+{
+ return ms->ExeFileDirW;
+}
+
+// Get the special directory name
+char *MsGetSpecialDir(int id)
+{
+ LPITEMIDLIST t = NULL;
+ char tmp[MAX_PATH];
+
+ if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
+ {
+ return CopyStr(ms->ExeFileDir);
+ }
+
+ if (SHGetPathFromIDList(t, tmp) == false)
+ {
+ return CopyStr(ms->ExeFileDir);
+ }
+
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+
+ return CopyStr(tmp);
+}
+wchar_t *MsGetSpecialDirW(int id)
+{
+ LPITEMIDLIST t = NULL;
+ wchar_t tmp[MAX_PATH];
+
+ if (IsNt() == false)
+ {
+ char *tmp = MsGetSpecialDir(id);
+ wchar_t *ret = CopyStrToUni(tmp);
+
+ Free(tmp);
+
+ return ret;
+ }
+
+ if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
+ {
+ return UniCopyStr(ms->ExeFileDirW);
+ }
+
+ if (SHGetPathFromIDListW(t, tmp) == false)
+ {
+ return UniCopyStr(ms->ExeFileDirW);
+ }
+
+ Win32NukuEnW(tmp, sizeof(tmp), tmp);
+
+ return UniCopyStr(tmp);
+}
+
+// Get all the special directory
+void MsGetSpecialDirs()
+{
+ char tmp[MAX_PATH];
+
+ // System32
+ GetSystemDirectory(tmp, sizeof(tmp));
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->System32Dir = CopyStr(tmp);
+ ms->System32DirW = CopyStrToUni(tmp);
+
+ // The Windows directory is parent of the System32 directory
+ Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->WindowsDir = CopyStr(tmp);
+ ms->WindowsDirW = CopyStrToUni(tmp);
+
+ // Temp directory under the Windows directory
+ Format(tmp, sizeof(tmp), "%s\\Temp", ms->WindowsDir);
+ ms->WinTempDir = CopyStr(tmp);
+ ms->WinTempDirW = CopyStrToUni(tmp);
+ MsUniMakeDirEx(ms->WinTempDirW);
+
+ // System drive
+ tmp[2] = 0;
+ ms->WindowsDrive = CopyStr(tmp);
+ ms->WindowsDriveW = CopyStrToUni(tmp);
+
+ // Temp
+ GetTempPath(MAX_PATH, tmp);
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->TempDir = CopyStr(tmp);
+
+ // Get the Temp (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ GetTempPathW(MAX_PATH, tmp_w);
+ Win32NukuEnW(tmp_w, sizeof(tmp_w), tmp_w);
+
+ ms->TempDirW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->TempDirW = CopyStrToUni(tmp);
+ }
+ MakeDirExW(ms->TempDirW);
+ MakeDirEx(ms->TempDir);
+
+ // Program Files
+ ms->ProgramFilesDir = MsGetSpecialDir(CSIDL_PROGRAM_FILES);
+ if (StrCmpi(ms->ProgramFilesDir, ms->ExeFileDir) == 0)
+ {
+ char tmp[MAX_PATH];
+ Format(tmp, sizeof(tmp), "%s\\Program Files", ms->WindowsDrive);
+
+ Free(ms->ProgramFilesDir);
+ ms->ProgramFilesDir = CopyStr(tmp);
+ }
+
+ ms->ProgramFilesDirW = MsGetSpecialDirW(CSIDL_PROGRAM_FILES);
+ if (UniStrCmpi(ms->ProgramFilesDirW, ms->ExeFileDirW) == 0)
+ {
+ wchar_t tmp[MAX_PATH];
+ UniFormat(tmp, sizeof(tmp), L"%s\\Program Files", ms->WindowsDriveW);
+
+ Free(ms->ProgramFilesDirW);
+ ms->ProgramFilesDirW = UniCopyStr(tmp);
+ }
+
+ // Program Files (x86)
+ ms->ProgramFilesDirX86 = MsGetSpecialDir(CSIDL_PROGRAM_FILESX86);
+ if (StrCmpi(ms->ProgramFilesDirX86, ms->ExeFileDir) == 0)
+ {
+ if (MsIs64BitWindows())
+ {
+ char tmp[MAX_PATH];
+ Format(tmp, sizeof(tmp), "%s\\Program Files (x86)", ms->WindowsDrive);
+
+ Free(ms->ProgramFilesDirX86);
+ ms->ProgramFilesDirX86 = CopyStr(tmp);
+ }
+ else
+ {
+ Free(ms->ProgramFilesDirX86);
+ ms->ProgramFilesDirX86 = CopyStr(ms->ProgramFilesDir);
+ }
+ }
+
+ ms->ProgramFilesDirX86W = MsGetSpecialDirW(CSIDL_PROGRAM_FILESX86);
+ if (UniStrCmpi(ms->ProgramFilesDirX86W, ms->ExeFileDirW) == 0)
+ {
+ if (MsIs64BitWindows())
+ {
+ wchar_t tmp[MAX_PATH];
+ UniFormat(tmp, sizeof(tmp), L"%s\\Program Files (x86)", ms->WindowsDriveW);
+
+ Free(ms->ProgramFilesDirX86W);
+ ms->ProgramFilesDirX86W = UniCopyStr(tmp);
+ }
+ else
+ {
+ Free(ms->ProgramFilesDirX86W);
+ ms->ProgramFilesDirX86W = UniCopyStr(ms->ProgramFilesDirW);
+ }
+ }
+
+ // Program Files (x64)
+ if (MsIs64BitWindows())
+ {
+ if (Is64())
+ {
+ ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
+ ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
+ }
+ else
+ {
+ char tmpa[MAX_SIZE];
+ wchar_t tmpw[MAX_SIZE];
+
+ ReplaceStrEx(tmpa, sizeof(tmpa), ms->ProgramFilesDir, "\\Program Files (x86)", "\\Program Files", false);
+ UniReplaceStrEx(tmpw, sizeof(tmpw), ms->ProgramFilesDirW, L"\\Program Files (x86)", L"\\Program Files", false);
+
+ ms->ProgramFilesDirX64 = CopyStr(tmpa);
+ ms->ProgramFilesDirX64W = CopyUniStr(tmpw);
+ }
+ }
+ else
+ {
+ ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
+ ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
+ }
+
+ if (MsIsNt())
+ {
+ // Common start menu
+ ms->CommonStartMenuDir = MsGetSpecialDir(CSIDL_COMMON_STARTMENU);
+ ms->CommonStartMenuDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTMENU);
+
+ // Common program
+ ms->CommonProgramsDir = MsGetSpecialDir(CSIDL_COMMON_PROGRAMS);
+ ms->CommonProgramsDirW = MsGetSpecialDirW(CSIDL_COMMON_PROGRAMS);
+
+ // Common startup
+ ms->CommonStartupDir = MsGetSpecialDir(CSIDL_COMMON_STARTUP);
+ ms->CommonStartupDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTUP);
+
+ // Common application data
+ ms->CommonAppDataDir = MsGetSpecialDir(CSIDL_COMMON_APPDATA);
+ ms->CommonAppDataDirW = MsGetSpecialDirW(CSIDL_COMMON_APPDATA);
+
+ // Common desktop
+ ms->CommonDesktopDir = MsGetSpecialDir(CSIDL_COMMON_DESKTOPDIRECTORY);
+ ms->CommonDesktopDirW = MsGetSpecialDirW(CSIDL_COMMON_DESKTOPDIRECTORY);
+
+ // Local Settings
+ ms->LocalAppDataDir = MsGetSpecialDir(CSIDL_LOCAL_APPDATA);
+ ms->LocalAppDataDirW = MsGetSpecialDirW(CSIDL_LOCAL_APPDATA);
+ }
+ else
+ {
+ // Start menu of the individual
+ ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
+ ms->CommonStartMenuDir = CopyStr(ms->PersonalStartMenuDir);
+ ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
+ ms->CommonStartMenuDirW = CopyUniStr(ms->PersonalStartMenuDirW);
+
+ // Program of the individual
+ ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
+ ms->CommonProgramsDir = CopyStr(ms->PersonalProgramsDir);
+ ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
+ ms->CommonProgramsDirW = CopyUniStr(ms->PersonalProgramsDirW);
+
+ // Start-up of the individual
+ ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
+ ms->CommonStartupDir = CopyStr(ms->PersonalStartupDir);
+ ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
+ ms->CommonStartupDirW = CopyUniStr(ms->PersonalStartupDirW);
+
+ // Application data of the individual
+ ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
+ ms->CommonAppDataDir = CopyStr(ms->PersonalAppDataDir);
+ ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
+ ms->CommonAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
+
+ // Desktops of the individual
+ ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
+ ms->CommonDesktopDir = CopyStr(ms->PersonalDesktopDir);
+ ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
+ ms->CommonDesktopDirW = CopyUniStr(ms->PersonalDesktopDirW);
+
+ // Local Settings
+ ms->LocalAppDataDir = CopyStr(ms->PersonalAppDataDir);
+ ms->LocalAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
+ }
+}
+
+// Check whether the current user is a Administrators
+bool MsCheckIsAdmin()
+{
+ UCHAR test_bit[32];
+ UCHAR tmp[32];
+ UCHAR exe_hash[SHA1_SIZE];
+ char *name_tag = "Vpn_Check_Admin_Key_%u";
+ DWORD type;
+ DWORD size;
+ char name[MAX_SIZE];
+
+ HashSha1(exe_hash, MsGetExeFileNameW(), UniStrLen(MsGetExeFileNameW()));
+
+ Format(name, sizeof(name), name_tag, *((UINT *)exe_hash));
+
+ Rand(test_bit, sizeof(test_bit));
+
+ if (RegSetValueEx(HKEY_LOCAL_MACHINE, name, 0, REG_BINARY, test_bit, sizeof(test_bit)) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ size = sizeof(tmp);
+ if (RegQueryValueEx(HKEY_LOCAL_MACHINE, name, 0, &type, tmp, &size) != ERROR_SUCCESS)
+ {
+ RegDeleteValue(HKEY_LOCAL_MACHINE, name);
+ return false;
+ }
+
+ RegDeleteValue(HKEY_LOCAL_MACHINE, name);
+
+ if (Cmp(test_bit, tmp, 32) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Library initialization
+void MsInit()
+{
+ char *str_ansi;
+ wchar_t *str_unicode;
+ OSVERSIONINFO os;
+ char tmp[MAX_SIZE];
+ UINT size;
+ if (ms != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ ms = ZeroMalloc(sizeof(MS));
+
+ // Getting instance handle
+ ms->hInst = GetModuleHandle(NULL);
+
+ // Get the KERNEL32.DLL
+ ms->hKernel32 = LoadLibrary("kernel32.dll");
+
+ // Get a command line string from the OS
+ str_ansi = CopyStr(GetCommandLineA());
+ Trim(str_ansi);
+ str_unicode = UniCopyStr(GetCommandLineW());
+ UniTrim(str_unicode);
+
+ SetCommandLineStr(MsCutExeNameFromCommandLine(str_ansi));
+ SetCommandLineUniStr(MsCutExeNameFromUniCommandLine(str_unicode));
+
+ Free(str_unicode);
+ Free(str_ansi);
+
+ // Get the version of the OS
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT series
+ ms->IsNt = true;
+
+ ms->nt = MsLoadNtApiFunctions();
+
+ if (ms->nt == NULL)
+ {
+ ms->IsNt = false;
+ ms->IsAdmin = true;
+ }
+ else
+ {
+ // Whether I am an Administrators
+ ms->IsAdmin = MsCheckIsAdmin();
+ }
+ }
+ else
+ {
+ // In 9x system: Impersonate a Administrators always
+ ms->IsAdmin = true;
+ }
+
+ // Get information about the current process
+ ms->hCurrentProcess = GetCurrentProcess();
+ ms->CurrentProcessId = GetCurrentProcessId();
+
+ // Get the EXE file name
+ GetModuleFileName(NULL, tmp, sizeof(tmp));
+ ms->ExeFileName = CopyStr(tmp);
+ Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
+ ms->ExeFileDir = CopyStr(tmp);
+
+ // Get the EXE file name (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ GetModuleFileNameW(NULL, tmp_w, sizeof(tmp_w));
+ ms->ExeFileNameW = CopyUniStr(tmp_w);
+
+ Win32GetDirFromPathW(tmp_w, sizeof(tmp_w), tmp_w);
+ ms->ExeFileDirW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->ExeFileNameW = CopyStrToUni(ms->ExeFileName);
+ ms->ExeFileDirW = CopyStrToUni(ms->ExeFileDir);
+ }
+
+ // Get the special directories
+ MsGetSpecialDirs();
+
+ // Initialize the temporary directory
+ MsInitTempDir();
+
+ // Get the user name
+ size = sizeof(tmp);
+ GetUserName(tmp, &size);
+ ms->UserName = CopyStr(tmp);
+
+ // Get the user name (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ size = sizeof(tmp_w);
+
+ GetUserNameW(tmp_w, &size);
+ ms->UserNameW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->UserNameW = CopyStrToUni(ms->UserName);
+ }
+
+ // Get the full user name
+ if (ms->nt != NULL && ms->nt->GetUserNameExA != NULL)
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ size = sizeof(tmp);
+ if (ms->nt->GetUserNameExA(NameSamCompatible, tmp, &size))
+ {
+ ms->UserNameEx = CopyStr(tmp);
+ }
+
+ size = sizeof(tmp_w);
+ if (ms->nt->GetUserNameExW(NameSamCompatible, tmp_w, &size))
+ {
+ ms->UserNameExW = CopyUniStr(tmp_w);
+ }
+ }
+
+ if (ms->UserNameEx == NULL)
+ {
+ ms->UserNameEx = CopyStr(ms->UserName);
+ }
+ if (ms->UserNameExW == NULL)
+ {
+ ms->UserNameExW = CopyUniStr(ms->UserNameW);
+ }
+
+ // Initialization of the adapter list
+ MsInitAdapterListModule();
+
+ // Initialization of minidump base file name
+ if (true)
+ {
+ wchar_t tmp[MAX_PATH];
+ if (MsIsAdmin())
+ {
+ CombinePathW(tmp, sizeof(tmp), ms->ExeFileDirW, L"vpn_debug\\dump");
+ }
+ else
+ {
+ CombinePathW(tmp, sizeof(tmp), ms->TempDirW, L"vpn_debug\\dump");
+ }
+ ms->MinidumpBaseFileNameW = CopyUniStr(tmp);
+ }
+
+ MsSetEnableMinidump(true);
+
+ if (MsIsNt())
+ {
+ if (ms->nt->MiniDumpWriteDump != NULL)
+ {
+ SetUnhandledExceptionFilter(MsExceptionHandler);
+ }
+ }
+
+ // Open a LSA handle
+ hLsa = NULL;
+ lsa_package_id = 0;
+ if (MsIsNt())
+ {
+ MsEnablePrivilege(SE_TCB_NAME, true);
+
+ if (ms->nt->AllocateLocallyUniqueId != NULL &&
+ ms->nt->LsaConnectUntrusted != NULL &&
+ ms->nt->LsaLookupAuthenticationPackage != NULL &&
+ ms->nt->LsaLogonUser != NULL &&
+ ms->nt->LsaDeregisterLogonProcess != NULL &&
+ ms->nt->LsaFreeReturnBuffer != NULL)
+ {
+ HANDLE h = NULL;
+ NTSTATUS ret = ms->nt->LsaConnectUntrusted(&h);
+
+ if (ret == 0)
+ {
+ LSA_STRING pkg_name;
+ ULONG ul = 0;
+
+ Zero(&pkg_name, sizeof(pkg_name));
+ pkg_name.Buffer = MSV1_0_PACKAGE_NAME;
+ pkg_name.Length = pkg_name.MaximumLength = StrLen(MSV1_0_PACKAGE_NAME);
+
+ ret = ms->nt->LsaLookupAuthenticationPackage(h, &pkg_name, &ul);
+
+ if (ret == 0)
+ {
+ Zero(&lsa_token_source, sizeof(lsa_token_source));
+
+ ms->nt->AllocateLocallyUniqueId(&lsa_token_source.SourceIdentifier);
+ Copy(lsa_token_source.SourceName, "SE-VPN ", 8);
+
+ lsa_package_id = ul;
+ hLsa = h;
+ }
+ else
+ {
+ ms->nt->LsaDeregisterLogonProcess(h);
+ }
+ }
+ }
+ }
+
+ // Read the msi.dll
+ if (hMsi == NULL)
+ {
+ hMsi = LoadLibrary("msi.dll");
+
+ if (hMsi != NULL)
+ {
+ _MsiConfigureProductW =
+ (UINT (__stdcall *)(LPCWSTR,int,INSTALLSTATE)) GetProcAddress(hMsi, "MsiConfigureProductW");
+ _MsiGetProductInfoW =
+ (UINT (__stdcall *)(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiGetProductInfoW");
+ _MsiSetInternalUI =
+ (INSTALLUILEVEL (__stdcall *)(INSTALLUILEVEL,HWND *)) GetProcAddress(hMsi, "MsiSetInternalUI");
+ _MsiLocateComponentW =
+ (INSTALLSTATE (__stdcall *)(LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiLocateComponentW");
+ }
+ }
+
+ // Lock created
+ vlan_lock = NewLock();
+}
+
+// Uninstall the MSI product
+bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required)
+{
+ wchar_t *product_code_w;
+ bool ret = false;
+ INSTALLUILEVEL old_level;
+ HWND old_hwnd;
+ UINT r;
+ // Validate arguments
+ if (product_code == NULL)
+ {
+ return false;
+ }
+ if (_MsiSetInternalUI == NULL || _MsiConfigureProductW == NULL)
+ {
+ return false;
+ }
+
+ if (reboot_required != NULL)
+ {
+ *reboot_required = false;
+ }
+
+ product_code_w = CopyStrToUni(product_code);
+
+ old_hwnd = hWnd;
+ old_level = _MsiSetInternalUI(INSTALLUILEVEL_PROGRESSONLY, &old_hwnd);
+
+ r = _MsiConfigureProductW(product_code_w, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT);
+
+ if (r == ERROR_SUCCESS || r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
+ {
+ ret = true;
+
+ if (r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
+ {
+ if (reboot_required != NULL)
+ {
+ *reboot_required = true;
+ }
+ }
+ }
+
+ if (old_level != INSTALLUILEVEL_NOCHANGE)
+ {
+ _MsiSetInternalUI(old_level, &old_hwnd);
+ }
+
+ Free(product_code_w);
+
+ return ret;
+}
+
+// Get the installation directory of the MSI component
+bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size)
+{
+ wchar_t *component_code_w;
+ bool ret = false;
+ wchar_t tmp[MAX_SIZE];
+ UINT sz = sizeof(tmp) / sizeof(wchar_t);
+ // Validate arguments
+ if (component_code == NULL || dir == NULL)
+ {
+ return false;
+ }
+ if (_MsiGetProductInfoW == NULL)
+ {
+ return false;
+ }
+
+ component_code_w = CopyStrToUni(component_code);
+
+ Zero(tmp, sizeof(tmp));
+
+ if (_MsiLocateComponentW(component_code_w, tmp, &sz) == INSTALLSTATE_LOCAL)
+ {
+ if (UniIsEmptyStr(tmp) == false)
+ {
+ GetDirNameFromFilePathW(dir, dir_size, tmp);
+ ret = true;
+ }
+ }
+
+ Free(component_code_w);
+
+ return ret;
+}
+
+// Determine whether to create a minidump
+void MsSetEnableMinidump(bool enabled)
+{
+ ms->MiniDumpEnabled = enabled;
+}
+
+// Output the minidump
+void MsWriteMinidump(wchar_t *filename, void *ex)
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t dir[MAX_PATH];
+ HANDLE h;
+ MINIDUMP_EXCEPTION_INFORMATION info;
+ struct _EXCEPTION_POINTERS *exp = (struct _EXCEPTION_POINTERS *)ex;
+
+ if (filename != NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ }
+ else
+ {
+ SYSTEMTIME tm;
+
+ Zero(&tm, sizeof(tm));
+ GetLocalTime(&tm);
+
+ UniFormat(tmp, sizeof(tmp), L"%s_%04u%02u%02u_%02u%02u%02u.dmp",
+ ms->MinidumpBaseFileNameW,
+ tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
+ }
+
+ GetDirNameFromFilePathW(dir, sizeof(dir), tmp);
+
+ CreateDirectoryW(dir, NULL);
+
+ Zero(&info, sizeof(info));
+
+ if (exp != NULL)
+ {
+ info.ThreadId = GetCurrentThreadId();
+ info.ExceptionPointers = exp;
+ info.ClientPointers = true;
+ }
+
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ ms->nt->MiniDumpWriteDump(ms->hCurrentProcess, ms->CurrentProcessId,
+ h,
+ MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithDataSegs |
+ MiniDumpWithHandleData
+ ,
+ info.ThreadId == 0 ? NULL : &info, NULL, NULL);
+
+ FlushFileBuffers(h);
+ CloseHandle(h);
+ }
+}
+
+// Exception handler
+LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
+{
+ if (ms->MiniDumpEnabled)
+ {
+ MsWriteMinidump(NULL, ExceptionInfo);
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+// Release of the library
+void MsFree()
+{
+ if (ms == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Release the LSA
+ if (hLsa != NULL)
+ {
+ ms->nt->LsaDeregisterLogonProcess(hLsa);
+
+ hLsa = NULL;
+ }
+
+ // Release of the adapter list
+ MsFreeAdapterListModule();
+
+ // Release of the temporary directory
+ MsFreeTempDir();
+
+ if (ms->IsNt)
+ {
+ // Release of NT series API
+ MsFreeNtApiFunctions(ms->nt);
+ }
+
+ // Memory release
+ // ANSI
+ Free(ms->WindowsDir);
+ Free(ms->System32Dir);
+ Free(ms->TempDir);
+ Free(ms->WinTempDir);
+ Free(ms->WindowsDrive);
+ Free(ms->ProgramFilesDir);
+ Free(ms->CommonStartMenuDir);
+ Free(ms->CommonProgramsDir);
+ Free(ms->CommonStartupDir);
+ Free(ms->CommonAppDataDir);
+ Free(ms->CommonDesktopDir);
+ Free(ms->PersonalStartMenuDir);
+ Free(ms->PersonalProgramsDir);
+ Free(ms->PersonalStartupDir);
+ Free(ms->PersonalAppDataDir);
+ Free(ms->PersonalDesktopDir);
+ Free(ms->MyDocumentsDir);
+ Free(ms->ExeFileDir);
+ Free(ms->ExeFileName);
+ Free(ms->UserName);
+ Free(ms->UserNameEx);
+ Free(ms->LocalAppDataDir);
+ Free(ms->ProgramFilesDirX86);
+ Free(ms->ProgramFilesDirX64);
+ // Unicode
+ Free(ms->WindowsDirW);
+ Free(ms->System32DirW);
+ Free(ms->TempDirW);
+ Free(ms->WinTempDirW);
+ Free(ms->WindowsDriveW);
+ Free(ms->ProgramFilesDirW);
+ Free(ms->CommonStartMenuDirW);
+ Free(ms->CommonProgramsDirW);
+ Free(ms->CommonStartupDirW);
+ Free(ms->CommonAppDataDirW);
+ Free(ms->CommonDesktopDirW);
+ Free(ms->PersonalStartMenuDirW);
+ Free(ms->PersonalProgramsDirW);
+ Free(ms->PersonalStartupDirW);
+ Free(ms->PersonalAppDataDirW);
+ Free(ms->PersonalDesktopDirW);
+ Free(ms->MyDocumentsDirW);
+ Free(ms->ExeFileDirW);
+ Free(ms->ExeFileNameW);
+ Free(ms->UserNameW);
+ Free(ms->UserNameExW);
+ Free(ms->LocalAppDataDirW);
+ Free(ms->MinidumpBaseFileNameW);
+ Free(ms->ProgramFilesDirX86W);
+ Free(ms->ProgramFilesDirX64W);
+
+ Free(ms);
+ ms = NULL;
+
+ // Delete the lock
+ DeleteLock(vlan_lock);
+ vlan_lock = NULL;
+}
+
+// Directory acquisition related
+char *MsGetCommonAppDataDir()
+{
+ return ms->CommonAppDataDir;
+}
+char *MsGetLocalAppDataDir()
+{
+ return ms->LocalAppDataDir;
+}
+char *MsGetWindowsDir()
+{
+ return ms->WindowsDir;
+}
+wchar_t *MsGetWindowsDirW()
+{
+ return ms->WindowsDirW;
+}
+char *MsGetSystem32Dir()
+{
+ return ms->System32Dir;
+}
+char *MsGetTempDir()
+{
+ return ms->TempDir;
+}
+char *MsGetWindowsDrive()
+{
+ return ms->WindowsDrive;
+}
+char *MsGetProgramFilesDir()
+{
+ return ms->ProgramFilesDir;
+}
+char *MsGetProgramFilesDirX86()
+{
+ return ms->ProgramFilesDirX86;
+}
+char *MsGetProgramFilesDirX64()
+{
+ return ms->ProgramFilesDirX64;
+}
+char *MsGetCommonStartMenuDir()
+{
+ return ms->CommonStartMenuDir;
+}
+char *MsGetCommonProgramsDir()
+{
+ return ms->CommonProgramsDir;
+}
+char *MsGetCommonStartupDir()
+{
+ return ms->CommonStartupDir;
+}
+char *MsGetCommonDesktopDir()
+{
+ return ms->CommonDesktopDir;
+}
+char *MsGetPersonalStartMenuDir()
+{
+ if (ms->PersonalStartMenuDir == NULL)
+ {
+ ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
+ }
+ return ms->PersonalStartMenuDir;
+}
+char *MsGetPersonalProgramsDir()
+{
+ if (ms->PersonalProgramsDir == NULL)
+ {
+ ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
+ }
+ return ms->PersonalProgramsDir;
+}
+char *MsGetPersonalStartupDir()
+{
+ if (ms->PersonalStartupDir == NULL)
+ {
+ ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
+ }
+ return ms->PersonalStartupDir;
+}
+char *MsGetPersonalAppDataDir()
+{
+ if (ms->PersonalAppDataDir == NULL)
+ {
+ ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
+ }
+ return ms->PersonalAppDataDir;
+}
+char *MsGetPersonalDesktopDir()
+{
+ if (ms->PersonalDesktopDir == NULL)
+ {
+ ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
+ }
+ return ms->PersonalDesktopDir;
+}
+char *MsGetMyDocumentsDir()
+{
+ if (ms->MyDocumentsDir == NULL)
+ {
+ ms->MyDocumentsDir = MsGetSpecialDir(CSIDL_PERSONAL);
+ }
+ return ms->MyDocumentsDir;
+}
+char *MsGetMyTempDir()
+{
+ return ms->MyTempDir;
+}
+char *MsGetUserName()
+{
+ return ms->UserName;
+}
+char *MsGetUserNameEx()
+{
+ return ms->UserNameEx;
+}
+char *MsGetWinTempDir()
+{
+ return ms->WinTempDir;
+}
+
+wchar_t *MsGetExeFileNameW()
+{
+ return ms == NULL ? L"Unknown" : ms->ExeFileNameW;
+}
+wchar_t *MsGetExeFileDirW()
+{
+ return ms->ExeFileDirW;
+}
+wchar_t *MsGetWindowDirW()
+{
+ return ms->WindowsDirW;
+}
+wchar_t *MsGetSystem32DirW()
+{
+ return ms->System32DirW;
+}
+wchar_t *MsGetTempDirW()
+{
+ return ms->TempDirW;
+}
+wchar_t *MsGetWindowsDriveW()
+{
+ return ms->WindowsDriveW;
+}
+wchar_t *MsGetProgramFilesDirW()
+{
+ return ms->ProgramFilesDirW;
+}
+wchar_t *MsGetCommonStartMenuDirW()
+{
+ return ms->CommonStartMenuDirW;
+}
+wchar_t *MsGetCommonProgramsDirW()
+{
+ return ms->CommonProgramsDirW;
+}
+wchar_t *MsGetProgramFilesDirX86W()
+{
+ return ms->ProgramFilesDirX86W;
+}
+wchar_t *MsGetProgramFilesDirX64W()
+{
+ return ms->ProgramFilesDirX64W;
+}
+wchar_t *MsGetCommonStartupDirW()
+{
+ return ms->CommonStartupDirW;
+}
+wchar_t *MsGetCommonAppDataDirW()
+{
+ return ms->CommonAppDataDirW;
+}
+wchar_t *MsGetCommonDesktopDirW()
+{
+ return ms->CommonDesktopDirW;
+}
+wchar_t *MsGetPersonalStartMenuDirW()
+{
+ if (ms->PersonalStartMenuDirW == NULL)
+ {
+ ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
+ }
+
+ return ms->PersonalStartMenuDirW;
+}
+wchar_t *MsGetPersonalProgramsDirW()
+{
+ if (ms->PersonalProgramsDirW == NULL)
+ {
+ ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
+ }
+
+ return ms->PersonalProgramsDirW;
+}
+wchar_t *MsGetPersonalStartupDirW()
+{
+ if (ms->PersonalStartupDirW == NULL)
+ {
+ ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
+ }
+
+ return ms->PersonalStartupDirW;
+}
+wchar_t *MsGetPersonalAppDataDirW()
+{
+ if (ms->PersonalAppDataDirW == NULL)
+ {
+ ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
+ }
+
+ return ms->PersonalAppDataDirW;
+}
+wchar_t *MsGetPersonalDesktopDirW()
+{
+ if (ms->PersonalDesktopDirW == NULL)
+ {
+ ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
+ }
+
+ return ms->PersonalDesktopDirW;
+}
+wchar_t *MsGetMyDocumentsDirW()
+{
+ if (ms->MyDocumentsDirW == NULL)
+ {
+ ms->MyDocumentsDirW = MsGetSpecialDirW(CSIDL_PERSONAL);
+ }
+
+ return ms->MyDocumentsDirW;
+}
+wchar_t *MsGetLocalAppDataDirW()
+{
+ return ms->LocalAppDataDirW;
+}
+wchar_t *MsGetMyTempDirW()
+{
+ return ms->MyTempDirW;
+}
+wchar_t *MsGetUserNameW()
+{
+ return ms->UserNameW;
+}
+wchar_t *MsGetUserNameExW()
+{
+ return ms->UserNameExW;
+}
+wchar_t *MsGetWinTempDirW()
+{
+ return ms->WinTempDirW;
+}
+
+
+#endif // WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Microsoft.h b/src/Mayaqua/Microsoft.h
new file mode 100644
index 00000000..b1b752ff
--- /dev/null
+++ b/src/Mayaqua/Microsoft.h
@@ -0,0 +1,1155 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Microsoft.h
+// Header of Microsoft.c
+
+#ifdef OS_WIN32
+
+// Make available the types for Windows even if windows.h is not included
+#ifndef _WINDEF_
+
+typedef void *HWND;
+
+#endif // _WINDEF_
+
+#ifndef MICROSOFT_H
+#define MICROSOFT_H
+
+
+// Constant for Event log
+#define MS_EVENTLOG_TYPE_INFORMATION 0
+#define MS_EVENTLOG_TYPE_WARNING 1
+#define MS_EVENTLOG_TYPE_ERROR 2
+
+#define MS_RC_EVENTLOG_TYPE_INFORMATION 0x40000001L
+#define MS_RC_EVENTLOG_TYPE_WARNING 0x80000002L
+#define MS_RC_EVENTLOG_TYPE_ERROR 0xC0000003L
+
+
+// TCP/IP registry value
+#define TCP_MAX_NUM_CONNECTIONS 16777214
+
+#define DEFAULT_TCP_MAX_WINDOW_SIZE_RECV 5955584
+#define DEFAULT_TCP_MAX_WINDOW_SIZE_SEND 131072
+#define DEFAULT_TCP_MAX_NUM_CONNECTIONS 16777214
+
+// Constant
+#define SVC_ARG_INSTALL "/install"
+#define SVC_ARG_UNINSTALL "/uninstall"
+#define SVC_ARG_START "/start"
+#define SVC_ARG_STOP "/stop"
+#define SVC_ARG_TEST "/test"
+#define SVC_ARG_USERMODE "/usermode"
+#define SVC_ARG_USERMODE_SHOWTRAY "/usermode_showtray"
+#define SVC_ARG_USERMODE_HIDETRAY "/usermode_hidetray"
+#define SVC_ARG_SERVICE "/service"
+#define SVC_ARG_SETUP_INSTALL "/setup_install"
+#define SVC_ARG_SETUP_UNINSTALL "/setup_uninstall"
+#define SVC_ARG_WIN9X_SERVICE "/win9x_service"
+#define SVC_ARG_WIN9X_INSTALL "/win9x_install"
+#define SVC_ARG_WIN9X_UNINSTALL "/win9x_uninstall"
+#define SVC_ARG_TCP "/tcp"
+#define SVC_ARG_TCP_UAC "/tcp_uac"
+#define SVC_ARG_TCP_UAC_W L"/tcp_uac"
+#define SVC_ARG_TCP_SETUP "/tcpsetup"
+#define SVC_ARG_TRAFFIC "/traffic"
+#define SVC_ARG_UIHELP "/uihelp"
+#define SVC_ARG_UIHELP_W L"/uihelp"
+#define SVC_ARG_SILENT "/silent"
+
+// Time to suicide, if the service freezed
+#define SVC_SELFKILL_TIMEOUT (5 * 60 * 1000)
+
+// The name of the device driver of the virtual LAN card for Win32 (first part)
+#define VLAN_ADAPTER_NAME "VPN Client Adapter"
+#define VLAN_ADAPTER_NAME_OLD "SoftEther VPN Client 2.0 Adapter"
+
+// The name of the device driver of the virtual LAN card for Win32 (full name)
+#define VLAN_ADAPTER_NAME_TAG "VPN Client Adapter - %s"
+#define VLAN_ADAPTER_NAME_TAG_OLD "SoftEther VPN Client 2.0 Adapter - %s"
+
+// Display name of Virtual LAN card in the [Network Connections] in Win32 (full name)
+#define VLAN_CONNECTION_NAME "%s - VPN Client"
+#define VLAN_CONNECTION_NAME_OLD "%s - SoftEther VPN Client 2.0"
+
+
+// Command line format in the service mode
+#define SVC_RUN_COMMANDLINE L"\"%s\" /service"
+
+// Mode value
+#define SVC_MODE_NONE 0
+#define SVC_MODE_INSTALL 1
+#define SVC_MODE_UNINSTALL 2
+#define SVC_MODE_START 3
+#define SVC_MODE_STOP 4
+#define SVC_MODE_TEST 5
+#define SVC_MODE_USERMODE 6
+#define SVC_MODE_SERVICE 7
+#define SVC_MODE_SETUP_INSTALL 8
+#define SVC_MODE_SETUP_UNINSTALL 9
+#define SVC_MODE_WIN9X_SERVICE 10
+#define SVC_MODE_WIN9X_INSTALL 11
+#define SVC_MODE_WIN9X_UNINSTALL 12
+#define SVC_MODE_TCP 13
+#define SVC_MODE_TCPSETUP 14
+#define SVC_MODE_TRAFFIC 15
+#define SVC_MODE_UIHELP 16
+#define SVC_MODE_TCP_UAC 17
+
+
+#define WIN9X_SVC_REGKEY_1 "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"
+#define WIN9X_SVC_REGKEY_2 "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
+
+#define VISTA_MMCSS_KEYNAME "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks"
+#define VISTA_MMCSS_FILENAME "mmcss_backup.dat"
+
+#define SVC_NAME "SVC_%s_NAME"
+#define SVC_TITLE "SVC_%s_TITLE"
+#define SVC_DESCRIPT "SVC_%s_DESCRIPT"
+
+#define SVC_USERMODE_SETTING_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\UserMode Settings"
+#define SVC_HIDETRAY_REG_VALUE "HideTray_%S"
+
+#define SVC_CALLING_SM_PROCESS_ID_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\Service Control\\%s"
+#define SVC_CALLING_SM_PROCESS_ID_VALUE "ProcessId"
+
+#define SOFTETHER_FW_SCRIPT_HASH "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\FW ScriptHash"
+
+#define MMCSS_PROFILE_KEYNAME "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile"
+
+// Other constants
+#define MS_REG_TCP_SETTING_KEY "Software\\" GC_REG_COMPANY_NAME "\\Network Settings"
+
+
+
+// Constants about driver
+#define DRIVER_INF_FILE_NAME L"|vpn_driver.inf"
+#define DRIVER_INF_FILE_NAME_X64 L"|vpn_driver_x64.inf"
+#define DRIVER_INF_FILE_NAME_IA64 L"|vpn_driver_ia64.inf"
+#define DRIVER_INF_FILE_NAME_9X L"|vpn_driver_9x.inf"
+#define DRIVER_SYS_FILE_NAME L"|vpn_driver.sys"
+#define DRIVER_SYS_FILE_NAME_X64 L"|vpn_driver_x64.sys"
+#define DRIVER_SYS_FILE_NAME_IA64 L"|vpn_driver_ia64.sys"
+#define DRIVER_SYS_FILE_NAME_9X L"|vpn_driver_9x.sys"
+#define DRIVER_SYS6_FILE_NAME L"|vpn_driver6.sys"
+#define DRIVER_SYS6_FILE_NAME_X64 L"|vpn_driver6_x64.sys"
+#define DRIVER_SYS6_FILE_NAME_IA64 L"|vpn_driver6_ia64.sys"
+#define DRIVER_INSTALL_INF_NAME_TAG "Neo_%s.inf"
+#define DRIVER_INSTALL_SYS_NAME_TAG "Neo_%s.sys"
+#define DRIVER_INSTALL_SYS_NAME_TAG_NEW "Neo_%04u.sys"
+#define DRIVER_INSTALL_SYS_NAME_TAG_MAXID 128 // Maximum number of install
+
+
+// Vista driver installer related
+#define VISTA_DRIVER_INSTALLER_SRC L"|driver_installer.exe"
+#define VISTA_DRIVER_INSTALLER_SRC_X64 L"|driver_installer_x64.exe"
+#define VISTA_DRIVER_INSTALLER_SRC_IA64 L"|driver_installer_ia64.exe"
+#define VISTA_DRIVER_INSTALLER_DST L"%s\\driver_installer.exe"
+
+#define DRIVER_DEVICE_ID_TAG "NeoAdapter_%s"
+
+
+#if (defined(MICROSOFT_C) || defined(NETWORK_C)) && (defined(OS_WIN32))
+
+typedef enum __TCP_TABLE_CLASS {
+ _TCP_TABLE_BASIC_LISTENER,
+ _TCP_TABLE_BASIC_CONNECTIONS,
+ _TCP_TABLE_BASIC_ALL,
+ _TCP_TABLE_OWNER_PID_LISTENER,
+ _TCP_TABLE_OWNER_PID_CONNECTIONS,
+ _TCP_TABLE_OWNER_PID_ALL,
+ _TCP_TABLE_OWNER_MODULE_LISTENER,
+ _TCP_TABLE_OWNER_MODULE_CONNECTIONS,
+ _TCP_TABLE_OWNER_MODULE_ALL
+} _TCP_TABLE_CLASS, *_PTCP_TABLE_CLASS;
+
+// A pointer to the network related Win32 API function
+typedef struct NETWORK_WIN32_FUNCTIONS
+{
+ HINSTANCE hIpHlpApi32;
+ HINSTANCE hIcmp;
+ DWORD (WINAPI *DeleteIpForwardEntry)(PMIB_IPFORWARDROW);
+ DWORD (WINAPI *CreateIpForwardEntry)(PMIB_IPFORWARDROW);
+ DWORD (WINAPI *GetIpForwardTable)(PMIB_IPFORWARDTABLE, PULONG, BOOL);
+ DWORD (WINAPI *GetNetworkParams)(PFIXED_INFO, PULONG);
+ ULONG (WINAPI *GetAdaptersAddresses)(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
+ DWORD (WINAPI *GetIfTable)(PMIB_IFTABLE, PULONG, BOOL);
+ DWORD (WINAPI *GetIfTable2)(void **);
+ void (WINAPI *FreeMibTable)(PVOID);
+ DWORD (WINAPI *IpRenewAddress)(PIP_ADAPTER_INDEX_MAP);
+ DWORD (WINAPI *IpReleaseAddress)(PIP_ADAPTER_INDEX_MAP);
+ DWORD (WINAPI *GetInterfaceInfo)(PIP_INTERFACE_INFO, PULONG);
+ DWORD (WINAPI *GetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG);
+ DWORD (WINAPI *GetExtendedTcpTable)(PVOID, PDWORD, BOOL, ULONG, _TCP_TABLE_CLASS, ULONG);
+ DWORD (WINAPI *AllocateAndGetTcpExTableFromStack)(PVOID *, BOOL, HANDLE, DWORD, DWORD);
+ DWORD (WINAPI *GetTcpTable)(PMIB_TCPTABLE, PDWORD, BOOL);
+ DWORD (WINAPI *NotifyRouteChange)(PHANDLE, LPOVERLAPPED);
+ BOOL (WINAPI *CancelIPChangeNotify)(LPOVERLAPPED);
+ DWORD (WINAPI *NhpAllocateAndGetInterfaceInfoFromStack)(IP_INTERFACE_NAME_INFO **,
+ PDWORD, BOOL, HANDLE, DWORD);
+ HANDLE (WINAPI *IcmpCreateFile)();
+ BOOL (WINAPI *IcmpCloseHandle)(HANDLE);
+ DWORD (WINAPI *IcmpSendEcho)(HANDLE, IPAddr, LPVOID, WORD, PIP_OPTION_INFORMATION,
+ LPVOID, DWORD, DWORD);
+} NETWORK_WIN32_FUNCTIONS;
+#endif
+
+
+#ifdef MICROSOFT_C
+// WCM related code on Windows 8
+typedef enum _MS_WCM_PROPERTY
+{
+ ms_wcm_global_property_domain_policy,
+ ms_wcm_global_property_minimize_policy,
+ ms_wcm_global_property_roaming_policy,
+ ms_wcm_global_property_powermanagement_policy,
+ ms_wcm_intf_property_connection_cost, //used to set/get cost level and flags for the connection
+ ms_wcm_intf_property_dataplan_status, //used by MNO to indicate plan data associated with new cost
+ ms_wcm_intf_property_hotspot_profile, //used to store hotspot profile (WISPr credentials)
+} MS_WCM_PROPERTY, *MS_PWCM_PROPERTY;
+
+typedef struct _MS_WCM_POLICY_VALUE {
+ BOOL fValue;
+ BOOL fIsGroupPolicy;
+} MS_WCM_POLICY_VALUE, *MS_PWCM_POLICY_VALUE;
+
+#define MS_WCM_MAX_PROFILE_NAME 256
+
+typedef enum _MS_WCM_MEDIA_TYPE
+{
+ ms_wcm_media_unknown,
+ ms_wcm_media_ethernet,
+ ms_wcm_media_wlan,
+ ms_wcm_media_mbn,
+ ms_wcm_media_invalid,
+ ms_wcm_media_max
+} MS_WCM_MEDIA_TYPE, *MS_PWCM_MEDIA_TYPE;
+
+typedef struct _MS_WCM_PROFILE_INFO {
+ WCHAR strProfileName[MS_WCM_MAX_PROFILE_NAME];
+ GUID AdapterGUID;
+ MS_WCM_MEDIA_TYPE Media;
+} MS_WCM_PROFILE_INFO, *MS_PWCM_PROFILE_INFO;
+
+typedef struct _MS_WCM_PROFILE_INFO_LIST {
+ DWORD dwNumberOfItems;
+
+ MS_WCM_PROFILE_INFO ProfileInfo[1];
+
+} MS_WCM_PROFILE_INFO_LIST, *MS_PWCM_PROFILE_INFO_LIST;
+
+
+// Internal structure
+typedef struct MS
+{
+ HINSTANCE hInst;
+ HINSTANCE hKernel32;
+ bool IsNt;
+ bool IsAdmin;
+ struct NT_API *nt;
+ HANDLE hCurrentProcess;
+ UINT CurrentProcessId;
+ bool MiniDumpEnabled;
+ char *ExeFileName;
+ char *ExeFileDir;
+ char *WindowsDir;
+ char *System32Dir;
+ char *TempDir;
+ char *WinTempDir;
+ char *WindowsDrive;
+ char *ProgramFilesDir;
+ char *ProgramFilesDirX86;
+ char *ProgramFilesDirX64;
+ char *CommonStartMenuDir;
+ char *CommonProgramsDir;
+ char *CommonStartupDir;
+ char *CommonAppDataDir;
+ char *CommonDesktopDir;
+ char *PersonalStartMenuDir;
+ char *PersonalProgramsDir;
+ char *PersonalStartupDir;
+ char *PersonalAppDataDir;
+ char *PersonalDesktopDir;
+ char *MyDocumentsDir;
+ char *LocalAppDataDir;
+ char *MyTempDir;
+ char *UserName;
+ char *UserNameEx;
+ wchar_t *ExeFileNameW;
+ wchar_t *ExeFileDirW;
+ wchar_t *WindowsDirW;
+ wchar_t *System32DirW;
+ wchar_t *TempDirW;
+ wchar_t *WinTempDirW;
+ wchar_t *WindowsDriveW;
+ wchar_t *ProgramFilesDirW;
+ wchar_t *ProgramFilesDirX86W;
+ wchar_t *ProgramFilesDirX64W;
+ wchar_t *CommonStartMenuDirW;
+ wchar_t *CommonProgramsDirW;
+ wchar_t *CommonStartupDirW;
+ wchar_t *CommonAppDataDirW;
+ wchar_t *CommonDesktopDirW;
+ wchar_t *PersonalStartMenuDirW;
+ wchar_t *PersonalProgramsDirW;
+ wchar_t *PersonalStartupDirW;
+ wchar_t *PersonalAppDataDirW;
+ wchar_t *PersonalDesktopDirW;
+ wchar_t *MyDocumentsDirW;
+ wchar_t *LocalAppDataDirW;
+ wchar_t *MyTempDirW;
+ wchar_t *UserNameW;
+ wchar_t *UserNameExW;
+ wchar_t *MinidumpBaseFileNameW;
+ IO *LockFile;
+} MS;
+
+// For Windows NT API
+typedef struct NT_API
+{
+ HINSTANCE hAdvapi32;
+ HINSTANCE hShell32;
+ HINSTANCE hNewDev;
+ HINSTANCE hSetupApi;
+ HINSTANCE hWtsApi32;
+ HINSTANCE hPsApi;
+ HINSTANCE hKernel32;
+ HINSTANCE hSecur32;
+ HINSTANCE hUser32;
+ HINSTANCE hDbgHelp;
+ HINSTANCE hWcmapi;
+ HINSTANCE hDwmapi;
+ BOOL (WINAPI *OpenProcessToken)(HANDLE, DWORD, PHANDLE);
+ BOOL (WINAPI *LookupPrivilegeValue)(char *, char *, PLUID);
+ BOOL (WINAPI *AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
+ BOOL (WINAPI *InitiateSystemShutdown)(LPTSTR, LPTSTR, DWORD, BOOL, BOOL);
+ BOOL (WINAPI *LogonUserW)(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, HANDLE *);
+ BOOL (WINAPI *LogonUserA)(char *, char *, char *, DWORD, DWORD, HANDLE *);
+ BOOL (WINAPI *UpdateDriverForPlugAndPlayDevicesW)(HWND hWnd, wchar_t *hardware_id, wchar_t *inf_path, UINT flag, BOOL *need_reboot);
+ UINT (WINAPI *CM_Get_DevNode_Status_Ex)(UINT *, UINT *, DWORD, UINT, HANDLE);
+ UINT (WINAPI *CM_Get_Device_ID_ExA)(DWORD, char *, UINT, UINT, HANDLE);
+ UINT (WINAPI *WTSQuerySessionInformation)(HANDLE, DWORD, WTS_INFO_CLASS, wchar_t *, DWORD *);
+ void (WINAPI *WTSFreeMemory)(void *);
+ BOOL (WINAPI *WTSDisconnectSession)(HANDLE, DWORD, BOOL);
+ BOOL (WINAPI *WTSEnumerateSessions)(HANDLE, DWORD, DWORD, PWTS_SESSION_INFO *, DWORD *);
+ SC_HANDLE (WINAPI *OpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
+ SC_HANDLE (WINAPI *CreateServiceA)(SC_HANDLE, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR);
+ SC_HANDLE (WINAPI *CreateServiceW)(SC_HANDLE, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD, DWORD, LPCWSTR, LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+ BOOL (WINAPI *ChangeServiceConfig2)(SC_HANDLE, DWORD, LPVOID);
+ BOOL (WINAPI *CloseServiceHandle)(SC_HANDLE);
+ SC_HANDLE (WINAPI *OpenService)(SC_HANDLE, LPCTSTR, DWORD);
+ BOOL (WINAPI *QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+ BOOL (WINAPI *StartService)(SC_HANDLE, DWORD, LPCTSTR);
+ BOOL (WINAPI *ControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
+ BOOL (WINAPI *SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS);
+ SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION);
+ BOOL (WINAPI *StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY);
+ BOOL (WINAPI *DeleteService)(SC_HANDLE);
+ BOOL (WINAPI *EnumProcesses)(DWORD *, DWORD, DWORD *);
+ BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE *, DWORD, DWORD *);
+ DWORD (WINAPI *GetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD);
+ DWORD (WINAPI *GetModuleFileNameExW)(HANDLE, HMODULE, LPWSTR, DWORD);
+ DWORD (WINAPI *GetProcessImageFileNameA)(HANDLE, LPSTR, DWORD);
+ DWORD (WINAPI *GetProcessImageFileNameW)(HANDLE, LPWSTR, DWORD);
+ BOOL (WINAPI *QueryFullProcessImageNameA)(HANDLE, DWORD, LPSTR, PDWORD);
+ BOOL (WINAPI *QueryFullProcessImageNameW)(HANDLE, DWORD, LPWSTR, PDWORD);
+ LONG (WINAPI *RegDeleteKeyExA)(HKEY, LPCTSTR, REGSAM, DWORD);
+ BOOL (WINAPI *IsWow64Process)(HANDLE, BOOL *);
+ void (WINAPI *GetNativeSystemInfo)(SYSTEM_INFO *);
+ BOOL (WINAPI *DuplicateTokenEx)(HANDLE, DWORD, SECURITY_ATTRIBUTES *, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, HANDLE *);
+ BOOL (WINAPI *ConvertStringSidToSidA)(LPCSTR, PSID *);
+ BOOL (WINAPI *SetTokenInformation)(HANDLE, TOKEN_INFORMATION_CLASS, void *, DWORD);
+ BOOL (WINAPI *GetTokenInformation)(HANDLE, TOKEN_INFORMATION_CLASS, void *, DWORD, PDWORD);
+ BOOL (WINAPI *CreateProcessAsUserA)(HANDLE, LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, void *, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
+ BOOL (WINAPI *CreateProcessAsUserW)(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, void *, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
+ BOOL (WINAPI *LookupAccountSidA)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
+ BOOL (WINAPI *LookupAccountNameA)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
+ BOOL (WINAPI *GetUserNameExA)(EXTENDED_NAME_FORMAT, LPSTR, PULONG);
+ BOOL (WINAPI *GetUserNameExW)(EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
+ BOOL (WINAPI *SwitchDesktop)(HDESK);
+ HDESK (WINAPI *OpenDesktopA)(LPTSTR, DWORD, BOOL, ACCESS_MASK);
+ BOOL (WINAPI *CloseDesktop)(HDESK);
+ BOOL (WINAPI *SetProcessShutdownParameters)(DWORD, DWORD);
+ HANDLE (WINAPI *RegisterEventSourceW)(LPCWSTR, LPCWSTR);
+ BOOL (WINAPI *ReportEventW)(HANDLE, WORD, WORD, DWORD, PSID, WORD, DWORD, LPCWSTR *, LPVOID);
+ BOOL (WINAPI *DeregisterEventSource)(HANDLE);
+ BOOL (WINAPI *Wow64DisableWow64FsRedirection)(void **);
+ BOOLEAN (WINAPI *Wow64EnableWow64FsRedirection)(BOOLEAN);
+ BOOL (WINAPI *Wow64RevertWow64FsRedirection)(void *);
+ BOOL (WINAPI *GetFileInformationByHandle)(HANDLE, LPBY_HANDLE_FILE_INFORMATION);
+ HANDLE (WINAPI *GetProcessHeap)();
+ BOOL (WINAPI *MiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
+ PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION,
+ PMINIDUMP_CALLBACK_INFORMATION);
+ BOOL (WINAPI *AllocateLocallyUniqueId)(PLUID);
+ NTSTATUS (NTAPI *LsaConnectUntrusted)(PHANDLE);
+ NTSTATUS (NTAPI *LsaLookupAuthenticationPackage)(HANDLE, PLSA_STRING, PULONG);
+ NTSTATUS (NTAPI *LsaLogonUser)(HANDLE, PLSA_STRING, SECURITY_LOGON_TYPE, ULONG,
+ PVOID, ULONG, PTOKEN_GROUPS, PTOKEN_SOURCE, PVOID, PULONG, PLUID, PHANDLE,
+ PQUOTA_LIMITS, PNTSTATUS);
+ NTSTATUS (NTAPI *LsaDeregisterLogonProcess)(HANDLE);
+ NTSTATUS (NTAPI *LsaFreeReturnBuffer)(PVOID);
+ DWORD (WINAPI *WcmQueryProperty)(const GUID *, LPCWSTR, MS_WCM_PROPERTY, PVOID, PDWORD, PBYTE *);
+ DWORD (WINAPI *WcmSetProperty)(const GUID *, LPCWSTR, MS_WCM_PROPERTY, PVOID, DWORD, const BYTE *);
+ void (WINAPI *WcmFreeMemory)(PVOID);
+ DWORD (WINAPI *WcmGetProfileList)(PVOID, MS_WCM_PROFILE_INFO_LIST **ppProfileList);
+ DWORD (WINAPI *SetNamedSecurityInfoW)(LPWSTR, UINT, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
+ BOOL (WINAPI *AddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
+ HRESULT (WINAPI *DwmIsCompositionEnabled)(BOOL *);
+ BOOL (WINAPI *GetComputerNameExW)(COMPUTER_NAME_FORMAT, LPWSTR, LPDWORD);
+} NT_API;
+
+typedef struct MS_EVENTLOG
+{
+ HANDLE hEventLog;
+} MS_EVENTLOG;
+
+extern NETWORK_WIN32_FUNCTIONS *w32net;
+
+typedef struct MS_USERMODE_SVC_PULSE_THREAD_PARAM
+{
+ void *hWnd;
+ void *GlobalPulse;
+ volatile bool Halt;
+} MS_USERMODE_SVC_PULSE_THREAD_PARAM;
+
+#endif // MICROSOFT_C
+
+// Structure to suppress the warning message
+typedef struct NO_WARNING
+{
+ DWORD ThreadId;
+ THREAD *NoWarningThread;
+ EVENT *HaltEvent;
+ volatile bool Halt;
+ wchar_t *SoundFileName;
+ UINT64 StartTimer;
+ UINT64 StartTick;
+} NO_WARNING;
+
+// ID of the root key
+#define REG_CLASSES_ROOT 0 // HKEY_CLASSES_ROOT
+#define REG_LOCAL_MACHINE 1 // HKEY_LOCAL_MACHINE
+#define REG_CURRENT_USER 2 // HKEY_CURRENT_USER
+#define REG_USERS 3 // HKEY_USERS
+
+// Service Functions
+typedef void (SERVICE_FUNCTION)();
+
+// Process list item
+typedef struct MS_PROCESS
+{
+ char ExeFilename[MAX_PATH]; // EXE file name
+ wchar_t ExeFilenameW[MAX_PATH]; // EXE file name (Unicode)
+ UINT ProcessId; // Process ID
+} MS_PROCESS;
+
+#define MAX_MS_ADAPTER_IP_ADDRESS 64
+
+// Network adapter
+typedef struct MS_ADAPTER
+{
+ char Title[MAX_PATH]; // Display name
+ wchar_t TitleW[MAX_PATH]; // Display Name (Unicode)
+ UINT Index; // Index
+ UINT Type; // Type
+ UINT Status; // Status
+ UINT Mtu; // MTU
+ UINT Speed; // Speed
+ UINT AddressSize; // Address size
+ UCHAR Address[8]; // Address
+ UINT64 RecvBytes; // Number of received bytes
+ UINT64 RecvPacketsBroadcast; // Number of broadcast packets received
+ UINT64 RecvPacketsUnicast; // Number of unicast packets received
+ UINT64 SendBytes; // Number of bytes sent
+ UINT64 SendPacketsBroadcast; // Number of sent broadcast packets
+ UINT64 SendPacketsUnicast; // Number of sent unicast packets
+ bool Info; // Whether there is detailed information
+ char Guid[MAX_SIZE]; // GUID
+ UINT NumIpAddress; // The number of IP addresses
+ IP IpAddresses[MAX_MS_ADAPTER_IP_ADDRESS]; // IP address
+ IP SubnetMasks[MAX_MS_ADAPTER_IP_ADDRESS]; // Subnet mask
+ UINT NumGateway; // The number of the gateway
+ IP Gateways[MAX_MS_ADAPTER_IP_ADDRESS]; // Gateway
+ bool UseDhcp; // Using DHCP flag
+ IP DhcpServer; // DHCP Server
+ UINT64 DhcpLeaseStart; // DHCP lease start date and time
+ UINT64 DhcpLeaseExpires; // DHCP lease expiration date and time
+ bool UseWins; // WINS use flag
+ IP PrimaryWinsServer; // Primary WINS server
+ IP SecondaryWinsServer; // Secondary WINS server
+ bool IsWireless; // Whether wireless
+ bool IsNotEthernetLan; // Whether It isn't a Ethernet LAN
+} MS_ADAPTER;
+
+// Network adapter list
+typedef struct MS_ADAPTER_LIST
+{
+ UINT Num; // Count
+ MS_ADAPTER **Adapters; // Content
+} MS_ADAPTER_LIST;
+
+// TCP setting
+typedef struct MS_TCP
+{
+ UINT RecvWindowSize; // Receive window size
+ UINT SendWindowSize; // Send window size
+} MS_TCP;
+
+// Sleep prevention
+typedef struct MS_NOSLEEP
+{
+ THREAD *Thread; // Thread
+ EVENT *HaltEvent; // Halting event
+ volatile bool Halt; // Halting flag
+ bool NoScreenSaver; // Prevent Screensaver
+
+ // Following is for Windows Vista
+ wchar_t ScreenSaveActive[MAX_PATH];
+ wchar_t SCRNSAVE_EXE[MAX_PATH];
+} MS_NOSLEEP;
+
+// Child window enumeration
+typedef struct ENUM_CHILD_WINDOW_PARAM
+{
+ LIST *o;
+ bool no_recursion;
+ bool include_ipcontrol;
+} ENUM_CHILD_WINDOW_PARAM;
+
+// Driver version information
+typedef struct MS_DRIVER_VER
+{
+ UINT Year, Month, Day;
+ UINT Major, Minor, Build;
+} MS_DRIVER_VER;
+
+
+// Function prototype
+void MsInit();
+void MsFree();
+char *MsCutExeNameFromCommandLine(char *str);
+wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str);
+
+DWORD MsRegAccessMaskFor64Bit(bool force32bit);
+DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit);
+
+bool MsRegIsKey(UINT root, char *name);
+bool MsRegIsKeyEx(UINT root, char *name, bool force32bit);
+bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit);
+
+bool MsRegIsValue(UINT root, char *keyname, char *valuename);
+bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit);
+bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size);
+bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit);
+bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit);
+bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size);
+bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit);
+bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit);
+
+bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size);
+bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit);
+bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit);
+bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size);
+bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit);
+bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit);
+
+char *MsRegReadStr(UINT root, char *keyname, char *valuename);
+char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit);
+char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename);
+wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit);
+wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+UINT MsRegReadInt(UINT root, char *keyname, char *valuename);
+UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit);
+UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename);
+LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit);
+LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+BUF *MsRegReadBin(UINT root, char *keyname, char *valuename);
+BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit);
+BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsRegNewKey(UINT root, char *keyname);
+bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit);
+bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+
+bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size);
+bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit);
+bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit);
+bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size);
+bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit);
+bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit);
+
+bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str);
+bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit);
+bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str);
+bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit);
+bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str);
+bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit);
+bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str);
+bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit);
+bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit);
+
+bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value);
+bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit);
+bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit);
+bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size);
+bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit);
+bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit);
+
+TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname);
+TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit);
+TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname);
+TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit);
+TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+
+bool MsRegDeleteKey(UINT root, char *keyname);
+bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit);
+bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+bool MsRegDeleteValue(UINT root, char *keyname, char *valuename);
+bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit);
+bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsIsNt();
+bool MsIsAdmin();
+bool MsEnablePrivilege(char *name, bool enable);
+void *MsGetCurrentProcess();
+UINT MsGetCurrentProcessId();
+char *MsGetExeFileName();
+char *MsGetExeDirName();
+wchar_t *MsGetExeDirNameW();
+
+bool MsShutdown(bool reboot, bool force);
+bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message);
+bool MsCheckLogon(wchar_t *username, char *password);
+bool MsIsPasswordEmpty(wchar_t *username);
+TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2);
+TOKEN_LIST *MsEnumNetworkAdaptersNeo();
+bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name);
+bool MsMakeNewNeoDriverFilename(char *name, UINT size);
+void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n);
+TOKEN_LIST *MsEnumNeoDriverFilenames();
+char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name);
+wchar_t *MsGetNetworkConnectionName(char *guid);
+char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid);
+char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name);
+void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon);
+void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name);
+void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name);
+
+char *MsGetSpecialDir(int id);
+wchar_t *MsGetSpecialDirW(int id);
+void MsGetSpecialDirs();
+bool MsCheckIsAdmin();
+void MsInitTempDir();
+void MsFreeTempDir();
+void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir);
+void MsDeleteTempDir();
+void MsDeleteAllFile(char *dir);
+void MsDeleteAllFileW(wchar_t *dir);
+char *MsCreateTempFileName(char *name);
+char *MsCreateTempFileNameByExt(char *ext);
+IO *MsCreateTempFile(char *name);
+IO *MsCreateTempFileByExt(char *ext);
+
+bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid);
+bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsEnableVLan(char *instance_name);
+bool MsEnableVLanWithoutLock(char *instance_name);
+bool MsDisableVLan(char *instance_name);
+bool MsDisableVLanWithoutLock(char *instance_name);
+bool MsUninstallVLan(char *instance_name);
+bool MsUninstallVLanWithoutLock(char *instance_name);
+bool MsIsVLanEnabled(char *instance_name);
+bool MsIsVLanEnabledWithoutLock(char *instance_name);
+bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name);
+void MsGetInfCatalogDir(char *dst, UINT size);
+void MsRestartVLan(char *instance_name);
+void MsRestartVLanWithoutLock(char *instance_name);
+bool MsIsVLanExists(char *tag_name, char *instance_name);
+void MsDeleteTroubleVLAN(char *tag_name, char *instance_name);
+bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver);
+void MsFinishDriverInstall(char *instance_name, char *neo_sys);
+void MsGetDriverPath(char *instance_name, wchar_t *src_inf, wchar_t *src_sys, wchar_t *dest_inf, wchar_t *dest_sys, wchar_t *src_cat, wchar_t *dest_cat, char *neo_sys);
+void MsGetDriverPathA(char *instance_name, char *src_inf, char *src_sys, char *dest_inf, char *dest_sys, char *src_cat, char *dst_cat, char *neo_sys);
+void MsGenMacAddress(UCHAR *mac);
+char *MsGetMacAddress(char *tag_name, char *instance_name);
+char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name);
+void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address);
+char *MsGetDriverVersion(char *tag_name, char *instance_name);
+char *MsGetDriverFileName(char *tag_name, char *instance_name);
+void MsTest();
+void MsInitGlobalNetworkConfig();
+void MsDisableNetworkOffloadingEtc();
+void MsSetThreadPriorityHigh();
+void MsSetThreadPriorityLow();
+void MsSetThreadPriorityIdle();
+void MsSetThreadPriorityRealtime();
+void MsRestoreThreadPriority();
+char *MsGetLocalAppDataDir();
+char *MsGetCommonAppDataDir();
+char *MsGetWindowsDir();
+char *MsGetSystem32Dir();
+char *MsGetTempDir();
+char *MsGetWindowsDrive();
+char *MsGetProgramFilesDir();
+char *MsGetProgramFilesDirX86();
+char *MsGetProgramFilesDirX64();
+char *MsGetCommonStartMenuDir();
+char *MsGetCommonProgramsDir();
+char *MsGetCommonStartupDir();
+char *MsGetCommonAppDataDir();
+char *MsGetCommonDesktopDir();
+char *MsGetPersonalStartMenuDir();
+char *MsGetPersonalProgramsDir();
+char *MsGetPersonalStartupDir();
+char *MsGetPersonalAppDataDir();
+char *MsGetPersonalDesktopDir();
+char *MsGetMyDocumentsDir();
+char *MsGetMyTempDir();
+char *MsGetUserName();
+char *MsGetUserNameEx();
+char *MsGetWinTempDir();
+wchar_t *MsGetWindowsDirW();
+wchar_t *MsGetExeFileNameW();
+wchar_t *MsGetExeFileDirW();
+wchar_t *MsGetWindowDirW();
+wchar_t *MsGetSystem32DirW();
+wchar_t *MsGetTempDirW();
+wchar_t *MsGetWindowsDriveW();
+wchar_t *MsGetProgramFilesDirW();
+wchar_t *MsGetProgramFilesDirX86W();
+wchar_t *MsGetProgramFilesDirX64W();
+wchar_t *MsGetCommonStartMenuDirW();
+wchar_t *MsGetCommonProgramsDirW();
+wchar_t *MsGetCommonStartupDirW();
+wchar_t *MsGetCommonAppDataDirW();
+wchar_t *MsGetCommonDesktopDirW();
+wchar_t *MsGetPersonalStartMenuDirW();
+wchar_t *MsGetPersonalProgramsDirW();
+wchar_t *MsGetPersonalStartupDirW();
+wchar_t *MsGetPersonalAppDataDirW();
+wchar_t *MsGetPersonalDesktopDirW();
+wchar_t *MsGetMyDocumentsDirW();
+wchar_t *MsGetLocalAppDataDirW();
+wchar_t *MsGetMyTempDirW();
+wchar_t *MsGetUserNameW();
+wchar_t *MsGetUserNameExW();
+wchar_t *MsGetWinTempDirW();
+struct SAFE_TABLE *MsGetSafeTable();
+UINT MsGetProcessId();
+void MsTerminateProcess();
+bool MsIsServiceInstalled(char *name);
+bool MsInstallService(char *name, char *title, wchar_t *description, char *path);
+bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code);
+bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path);
+bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code);
+bool MsUpdateServiceConfig(char *name);
+bool MsSetServiceDescription(char *name, wchar_t *description);
+bool MsUninstallService(char *name);
+bool MsStartService(char *name);
+bool MsStartServiceEx(char *name, UINT *error_code);
+bool MsStopService(char *name);
+bool MsIsServiceRunning(char *name);
+bool MsIsTerminalServiceInstalled();
+bool MsIsUserSwitchingInstalled();
+bool MsIsTerminalServiceMultiUserInstalled();
+UINT MsGetCurrentTerminalSessionId();
+bool MsIsTerminalSessionActive(UINT session_id);
+bool MsIsCurrentTerminalSessionActive();
+bool MsIsCurrentDesktopAvailableForVnc();
+wchar_t *MsGetSessionUserName(UINT session_id);
+UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line);
+void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsServiceMode(SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon);
+void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon);
+bool MsIsUserMode();
+void MsTestOnly();
+void MsStopUserModeFromService();
+char *MsGetPenCoreDllFileName();
+void MsPlaySound(char *name);
+void MsSetThreadSingleCpu();
+void MsWin9xTest();
+bool MsCheckVLanDeviceIdFromRootEnum(char *name);
+bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver);
+void MsUpdateCompatibleIDs(char *instance_name);
+LIST *MsGetProcessList();
+LIST *MsGetProcessList9x();
+LIST *MsGetProcessListNt();
+void MsFreeProcessList(LIST *o);
+void MsPrintProcessList(LIST *o);
+int MsCompareProcessList(void *p1, void *p2);
+MS_PROCESS *MsSearchProcessById(LIST *o, UINT id);
+void MsGetCurrentProcessExeName(char *name, UINT size);
+void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size);
+bool MsKillProcess(UINT id);
+UINT MsKillProcessByExeName(wchar_t *name);
+void MsKillOtherInstance();
+void MsKillOtherInstanceEx(char *exclude_svcname);
+bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size);
+bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size);
+void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid);
+UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user);
+bool MsStopIPsecService();
+char *MsGetIPsecServiceName();
+bool MsStartIPsecService();
+
+void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name);
+void *MsCreateUserModeSvcGlocalPulse(char *svc_name);
+void MsStopUserModeSvc(char *svc_name);
+void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param);
+
+MS_ADAPTER_LIST *MsCreateAdapterListInner();
+MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info);
+MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info);
+void MsFreeAdapter(MS_ADAPTER *a);
+void MsFreeAdapterList(MS_ADAPTER_LIST *o);
+wchar_t *MsGetAdapterTypeStr(UINT type);
+wchar_t *MsGetAdapterStatusStr(UINT status);
+MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a);
+MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o);
+void MsInitAdapterListModule();
+void MsFreeAdapterListModule();
+MS_ADAPTER_LIST *MsCreateAdapterList();
+MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info);
+void MsGetAdapterTcpIpInformation(MS_ADAPTER *a);
+MS_ADAPTER *MsGetAdapter(char *title);
+MS_ADAPTER *MsGetAdapterByGuid(char *guid);
+MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid);
+UINT ConvertMidStatusVistaToXp(UINT st);
+
+void *MsLoadLibrary(char *name);
+void *MsLoadLibraryW(wchar_t *name);
+void *MsLoadLibraryAsDataFile(char *name);
+void *MsLoadLibraryAsDataFileW(wchar_t *name);
+void *MsLoadLibraryRawW(wchar_t *name);
+void MsFreeLibrary(void *h);
+void *MsGetProcAddress(void *h, char *name);
+
+void MsPrintTick();
+bool MsDisableIme();
+
+void MsGetTcpConfig(MS_TCP *tcp);
+void MsSetTcpConfig(MS_TCP *tcp);
+void MsSaveTcpConfigReg(MS_TCP *tcp);
+bool MsLoadTcpConfigReg(MS_TCP *tcp);
+bool MsIsTcpConfigSupported();
+void MsApplyTcpConfig();
+bool MsIsShouldShowTcpConfigApp();
+void MsDeleteTcpConfigReg();
+
+UINT MsGetConsoleWidth();
+UINT MsSetConsoleWidth(UINT size);
+NO_WARNING *MsInitNoWarning();
+NO_WARNING *MsInitNoWarningEx(UINT start_timer);
+void MsFreeNoWarning(NO_WARNING *nw);
+void MsNoWarningThreadProc(THREAD *thread, void *param);
+char *MsNoWarningSoundInit();
+void MsNoWarningSoundFree(char *s);
+bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id);
+LIST *MsEnumChildWindows(LIST *o, HWND hWnd);
+void MsAddWindowToList(LIST *o, HWND hWnd);
+UINT MsGetThreadLocale();
+LIST *NewWindowList();
+int CmpWindowList(void *p1, void *p2);
+void AddWindow(LIST *o, HWND hWnd);
+void FreeWindowList(LIST *o);
+LIST *EnumAllChildWindow(HWND hWnd);
+LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self);
+LIST *EnumAllWindow();
+LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol);
+LIST *EnumAllTopWindow();
+
+bool MsExecDriverInstaller(char *arg);
+bool MsIsVista();
+bool MsIsWin2000();
+bool MsIsWin2000OrGreater();
+bool MsIsWinXPOrGreater();
+void MsRegistWindowsFirewallEx(char *title, char *exe);
+void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir);
+bool MsIs64BitWindows();
+bool MsIsX64();
+bool MsIsIA64();
+void *MsDisableWow64FileSystemRedirection();
+void MsRestoreWow64FileSystemRedirection(void *p);
+void MsSetWow64FileSystemRedirectionEnable(bool enable);
+bool MsIsWindows8();
+bool MsIsWindows7();
+bool MsIsInfCatalogRequired();
+
+bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger);
+bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger);
+
+
+bool MsGetProcessExeName(char *path, UINT size, UINT id);
+bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id);
+bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd);
+bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd);
+
+void *MsRunAsUserEx(char *filename, char *arg, bool hide);
+void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide);
+void *MsRunAsUserExInner(char *filename, char *arg, bool hide);
+void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide);
+
+UINT MsGetCursorPosHash();
+bool MsIsProcessExists(char *exename);
+bool MsIsProcessExistsW(wchar_t *exename);
+
+void MsGetComputerName(char *name, UINT size);
+void MsGetComputerNameFull(wchar_t *name, UINT size);
+void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache);
+void MsNoSleepThread(THREAD *thread, void *param);
+void MsNoSleepThreadVista(THREAD *thread, void *param);
+UINT64 MsGetScreenSaverTimeout();
+void *MsNoSleepStart(bool no_screensaver);
+void MsNoSleepEnd(void *p);
+bool MsIsRemoteDesktopAvailable();
+bool MsIsRemoteDesktopCanEnableByRegistory();
+bool MsIsRemoteDesktopEnabled();
+bool MsEnableRemoteDesktop();
+
+void MsSetFileToHidden(char *name);
+void MsSetFileToHiddenW(wchar_t *name);
+bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4);
+bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4);
+
+bool MsExtractCabinetFileFromExe(char *exe, char *cab);
+bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab);
+BUF *MsExtractResourceFromExe(char *exe, char *type, char *name);
+BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name);
+bool MsExtractCab(char *cab_name, char *dest_dir_name);
+bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name);
+bool MsGetCabarcExeFilename(char *name, UINT size);
+bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size);
+bool MsExtractCabFromMsi(char *msi, char *cab);
+bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab);
+bool MsIsDirectory(char *name);
+bool MsIsDirectoryW(wchar_t *name);
+bool MsUniIsDirectory(wchar_t *name);
+bool MsUniFileDelete(wchar_t *name);
+bool MsUniDirectoryDelete(wchar_t *name);
+bool MsUniMakeDir(wchar_t *name);
+void MsUniMakeDirEx(wchar_t *name);
+void MsMakeDirEx(char *name);
+bool MsMakeDir(char *name);
+bool MsDirectoryDelete(char *name);
+bool MsFileDelete(char *name);
+bool MsExecute(char *exe, char *arg);
+bool MsExecute2(char *exe, char *arg, bool runas);
+bool MsExecuteW(wchar_t *exe, wchar_t *arg);
+bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas);
+bool MsExecuteEx(char *exe, char *arg, void **process_handle);
+bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas);
+bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle);
+bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas);
+void MsCloseHandle(void *handle);
+UINT MsWaitProcessExit(void *process_handle);
+bool MsIsFileLocked(char *name);
+bool MsIsFileLockedW(wchar_t *name);
+bool MsIsLocalDrive(char *name);
+bool MsIsLocalDriveW(wchar_t *name);
+void MsUpdateSystem();
+bool MsGetPhysicalMacAddressFromNetbios(void *address);
+bool MsGetPhysicalMacAddressFromApi(void *address);
+bool MsGetPhysicalMacAddress(void *address);
+bool MsIsUseWelcomeLogin();
+UINT64 MsGetHiResCounter();
+double MsGetHiResTimeSpan(UINT64 diff);
+UINT64 MsGetHiResTimeSpanUSec(UINT64 diff);
+BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit);
+void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit);
+void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit);
+void MsRestartMMCSS();
+bool MsIsMMCSSNetworkThrottlingEnabled();
+void MsSetMMCSSNetworkThrottlingEnable(bool enable);
+void MsSetShutdownParameters(UINT level, UINT flag);
+void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags);
+bool MsIsTrayInited();
+UINT MsGetClipboardOwnerProcessId();
+void MsDeleteClipboard();
+void *MsInitEventLog(wchar_t *src_name);
+void MsFreeEventLog(void *p);
+bool MsWriteEventLog(void *p, UINT type, wchar_t *str);
+bool MsIsWinXPOrWinVista();
+bool MsGetFileInformation(void *h, void *info);
+void MsSetErrorModeToSilent();
+void MsSetEnableMinidump(bool enabled);
+void MsWriteMinidump(wchar_t *filename, void *ex);
+
+
+void *MsInitGlobalLock(char *name, bool ts_local);
+void MsGlobalLock(void *p);
+void MsGlobalUnlock(void *p);
+void MsFreeGlobalLock(void *p);
+
+void *MsOpenOrCreateGlobalPulse(char *name);
+bool MsWaitForGlobalPulse(void *p, UINT timeout);
+void MsCloseGlobalPulse(void *p);
+void MsSendGlobalPulse(void *p);
+
+bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash);
+
+void MsDisableWcmNetworkMinimize();
+bool MsSetFileSecureAcl(wchar_t *path);
+
+bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size);
+bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required);
+
+UINT MsGetUserLocaleId();
+UINT MsGetSystemLocaleId();
+bool MsIsCurrentUserLocaleIdJapanese();
+
+TOKEN_LIST *MsEnumResources(void *hModule, char *type);
+void *MsGetCurrentModuleHandle();
+
+bool MsIsAeroEnabled();
+bool MsIsAeroColor();
+
+bool MsIsInVmMain();
+bool MsIsInVm();
+
+void MsTest();
+
+bool MsSaveSystemInfo(wchar_t *dst_filename);
+bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name);
+
+// Inner functions
+#ifdef MICROSOFT_C
+
+LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo);
+HKEY MsGetRootKeyFromInt(UINT root);
+NT_API *MsLoadNtApiFunctions();
+void MsFreeNtApiFunctions(NT_API *nt);
+void MsDestroyDevInfo(HDEVINFO info);
+HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id);
+bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv);
+void CALLBACK MsServiceHandler(DWORD opcode);
+bool MsServiceStopProc();
+void MsServiceStoperMainThread(THREAD *t, void *p);
+void MsServiceStarterMainThread(THREAD *t, void *p);
+LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg);
+void MsRestoreIconOnTray();
+void MsChangeIconOnTray(HICON icon, wchar_t *tooltip);
+bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add);
+void MsHideIconOnTray();
+void MsUserModeTrayMenu(HWND hWnd);
+bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str);
+bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item);
+bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam);
+BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam);
+bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam);
+HANDLE MsCreateUserToken();
+SID *MsGetSidFromAccountName(char *name);
+void MsFreeSid(SID *sid);
+bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam);
+
+void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv);
+
+
+#endif // MICROSOFT_C
+
+#endif // MICROSOFT_H
+
+#endif // OS_WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c
new file mode 100644
index 00000000..3025c5e3
--- /dev/null
+++ b/src/Mayaqua/Network.c
@@ -0,0 +1,21774 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Network.c
+// Network communication module
+
+#include <GlobalConst.h>
+
+#define ENCRYPT_C
+#define NETWORK_C
+
+#define __WINCRYPT_H__
+
+#ifdef WIN32
+// Include windows.h for Socket API
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <Ws2tcpip.h>
+#include <Wspiapi.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <Iphlpapi.h>
+#include <ws2ipdef.h>
+#include <netioapi.h>
+#include <Icmpapi.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifdef OS_WIN32
+NETWORK_WIN32_FUNCTIONS *w32net;
+struct ROUTE_CHANGE_DATA
+{
+ OVERLAPPED Overlapped;
+ HANDLE Handle;
+ UINT NumCalled;
+};
+#endif // OS_WIN32
+
+// Whether the blocking occurs in SSL
+#if defined(UNIX_BSD)
+#define FIX_SSL_BLOCKING
+#endif
+
+// IPV6_V6ONLY constant
+#ifdef UNIX_LINUX
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 26
+#endif // IPV6_V6ONLY
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 0x27
+#endif // IPV6_V6ONLY
+#endif // UNIX_SOLARIS
+
+
+
+// HTTP constant
+static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_500_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>500 Server Error</TITLE>\r\n</HEAD><BODY>\r\n<H1>Server Error</H1>\r\nServer Error<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_detect_server_startwith[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access ";
+static char http_detect_server_tag_future[] = "9C37197CA7C2428388C2E6E59B829B30";
+
+// DNS cache list
+static LIST *DnsCache;
+
+// Lock related
+static LOCK *machine_name_lock = NULL;
+static LOCK *disconnect_function_lock = NULL;
+static LOCK *aho = NULL;
+static LOCK *socket_library_lock = NULL;
+extern LOCK *openssl_lock;
+static LOCK *ssl_accept_lock = NULL;
+static LOCK *ssl_connect_lock = NULL;
+static TOKEN_LIST *cipher_list_token = NULL;
+static COUNTER *num_tcp_connections = NULL;
+static LOCK *dns_lock = NULL;
+static LOCK *unix_dns_server_addr_lock = NULL;
+static IP unix_dns_server;
+static LIST *HostCacheList = NULL;
+static LIST *WaitThreadList = NULL;
+static bool disable_cache = false;
+static bool NetworkReleaseMode = false; // Network release mode
+static UCHAR machine_ip_process_hash[SHA1_SIZE];
+static LOCK *machine_ip_process_hash_lock = NULL;
+static LOCK *current_global_ip_lock = NULL;
+static LOCK *current_fqdn_lock = NULL;
+static bool current_global_ip_set = false;
+static IP current_glocal_ipv4 = {0};
+static IP current_glocal_ipv6 = {0};
+static char current_fqdn[MAX_SIZE];
+static bool g_no_rudp_server = false;
+static bool g_no_rudp_register = false;
+static bool g_natt_low_priority = false;
+static LOCK *host_ip_address_list_cache_lock = NULL;
+static UINT64 host_ip_address_list_cache_last = 0;
+static LIST *host_ip_address_cache = NULL;
+
+
+static char *cipher_list = "RC4-MD5 RC4-SHA AES128-SHA AES256-SHA DES-CBC-SHA DES-CBC3-SHA";
+static LIST *ip_clients = NULL;
+
+static LIST *local_mac_list = NULL;
+static LOCK *local_mac_list_lock = NULL;
+
+static UINT rand_port_numbers[256] = {0};
+
+
+static bool g_use_privateip_file = false;
+
+typedef struct PRIVATE_IP_SUBNET
+{
+ UINT Ip, Mask, Ip2;
+} PRIVATE_IP_SUBNET;
+
+static LIST *g_private_ip_list = NULL;
+
+
+static LIST *g_dyn_value_list = NULL;
+
+
+//#define RUDP_DETAIL_LOG
+
+
+
+
+// Get a value from a dynamic value list (Returns a default value if the value is not found)
+UINT64 GetDynValueOrDefault(char *name, UINT64 default_value, UINT64 min_value, UINT64 max_value)
+{
+ UINT64 ret = GetDynValue(name);
+
+ if (ret == 0)
+ {
+ return default_value;
+ }
+
+ if (ret < min_value)
+ {
+ ret = min_value;
+ }
+
+ if (ret > max_value)
+ {
+ ret = max_value;
+ }
+
+ return ret;
+}
+
+// Get a value from a dynamic value list (Returns a default value if the value is not found)
+// The value is limited to 1/5 to 50 times of the default value for safety
+UINT64 GetDynValueOrDefaultSafe(char *name, UINT64 default_value)
+{
+ return GetDynValueOrDefault(name, default_value, default_value / (UINT64)5, default_value * (UINT64)50);
+}
+
+// Get a value from a dynamic value list
+UINT64 GetDynValue(char *name)
+{
+ UINT64 ret = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ if (g_dyn_value_list == NULL)
+ {
+ return 0;
+ }
+
+ LockList(g_dyn_value_list);
+ {
+ UINT i;
+
+ for (i = 0; i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *vv = LIST_DATA(g_dyn_value_list, i);
+
+ if (StrCmpi(vv->Name, name) == 0)
+ {
+ ret = vv->Value;
+ break;
+ }
+ }
+ }
+ UnlockList(g_dyn_value_list);
+
+ return ret;
+}
+
+// Set the value to the dynamic value list
+void SetDynListValue(char *name, UINT64 value)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (g_dyn_value_list == NULL)
+ {
+ return;
+ }
+
+ LockList(g_dyn_value_list);
+ {
+ UINT i;
+ DYN_VALUE *v = NULL;
+
+ for (i = 0; i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *vv = LIST_DATA(g_dyn_value_list, i);
+
+ if (StrCmpi(vv->Name, name) == 0)
+ {
+ v = vv;
+ break;
+ }
+ }
+
+ if (v == NULL)
+ {
+ v = ZeroMalloc(sizeof(DYN_VALUE));
+ StrCpy(v->Name, sizeof(v->Name), name);
+
+ Add(g_dyn_value_list, v);
+ }
+
+ v->Value = value;
+ }
+ UnlockList(g_dyn_value_list);
+}
+
+// Apply by extracting dynamic value list from the specified PACK
+void ExtractAndApplyDynList(PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ b = PackGetBuf(p, "DynList");
+ if (b == NULL)
+ {
+ return;
+ }
+
+ AddDynList(b);
+
+ FreeBuf(b);
+}
+
+// Insert the data to the dynamic value list
+void AddDynList(BUF *b)
+{
+ PACK *p;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBufToBegin(b);
+
+ p = BufToPack(b);
+ if (p == NULL)
+ {
+ return;
+ }
+
+ t = GetPackElementNames(p);
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ UINT64 v = PackGetInt64(p, name);
+
+ SetDynListValue(name, v);
+ }
+
+ FreeToken(t);
+ }
+
+ FreePack(p);
+}
+
+// Initialization of the dynamic value list
+void InitDynList()
+{
+ g_dyn_value_list = NewList(NULL);
+}
+
+// Solution of dynamic value list
+void FreeDynList()
+{
+ UINT i;
+ if (g_dyn_value_list == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *d = LIST_DATA(g_dyn_value_list, i);
+
+ Free(d);
+ }
+
+ ReleaseList(g_dyn_value_list);
+
+ g_dyn_value_list = NULL;
+}
+
+// Check whether the string in the string list appears in the specified string
+bool IsInStrByStrList(char *str, char *str_list)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (str == NULL || str_list == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(str_list, ", \t\r\n");
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (StrLen(s) >= 1)
+ {
+ if (InStrEx(str, s, true))
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+
+// Search whether the IP address exists on the IP address list string
+bool IsIpInStrList(IP *ip, char *ip_list)
+{
+ char ip_str[128];
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL || ip_list == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip_str, sizeof(ip_str));
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ t = ParseTokenWithoutNullStr(ip_list, ", \t\r\n");
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (StrCmpi(s, ip_str) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+
+// Disable NAT-T function globally
+void DisableRDUPServerGlobally()
+{
+ g_no_rudp_server = true;
+}
+
+// Disable NAT-T registration globally
+void DisableRUDPRegisterGlobally()
+{
+ g_no_rudp_register = true;
+}
+
+// Lower the priority of the host at NAT-T
+void SetNatTLowPriority()
+{
+ g_natt_low_priority = true;
+}
+
+// Extract only the host name part from FQDN
+void GetSimpleHostname(char *hostname, UINT hostname_size, char *fqdn)
+{
+ UINT i;
+ ClearStr(hostname, hostname_size);
+ // Validate arguments
+ if (hostname == NULL || fqdn == NULL)
+ {
+ return;
+ }
+
+ StrCpy(hostname, hostname_size, fqdn);
+ Trim(hostname);
+
+ i = SearchStrEx(hostname, ".", 0, true);
+ if (i != INFINITE)
+ {
+ hostname[i] = 0;
+ }
+}
+
+// Get the current time zone
+int GetCurrentTimezone()
+{
+ int ret = 0;
+
+#ifdef OS_WIN32
+ ret = GetCurrentTimezoneWin32();
+#else // OS_WIN32
+ {
+#if defined(UNIX_MACOS) || defined(UNIX_BSD)
+ struct timeval tv;
+ struct timezone tz;
+
+ Zero(&tv, sizeof(tv));
+ Zero(&tz, sizeof(tz));
+
+ gettimeofday(&tv, &tz);
+
+ ret = tz.tz_minuteswest;
+
+#else // defined(UNIX_MACOS) || defined(UNIX_BSD)
+ tzset();
+
+ ret = timezone / 60;
+#endif // defined(UNIX_MACOS) || defined(UNIX_BSD)
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Flag of whether to use the DNS proxy
+bool IsUseDnsProxy()
+{
+ return false;
+}
+
+// Flag of whether to use an alternate host name
+bool IsUseAlternativeHostname()
+{
+ return IsUseDnsProxy();
+}
+
+#ifdef OS_WIN32
+// Get the current time zone (Win32)
+int GetCurrentTimezoneWin32()
+{
+ TIME_ZONE_INFORMATION info;
+ Zero(&info, sizeof(info));
+
+ if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_INVALID)
+ {
+ return 0;
+ }
+
+ return info.Bias;
+}
+#endif // OS_WIN32
+
+
+// Set the current FQDN of the DDNS
+void SetCurrentDDnsFqdn(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Lock(current_fqdn_lock);
+ {
+ StrCpy(current_fqdn, sizeof(current_fqdn), name);
+ }
+ Unlock(current_fqdn_lock);
+}
+
+// Get the current DDNS FQDN hash
+UINT GetCurrentDDnsFqdnHash()
+{
+ UINT ret;
+ UCHAR hash[SHA1_SIZE];
+ char name[MAX_SIZE];
+
+ ClearStr(name, sizeof(name));
+ GetCurrentDDnsFqdn(name, sizeof(name));
+
+ Trim(name);
+ StrUpper(name);
+
+ HashSha1(hash, name, StrLen(name));
+
+ Copy(&ret, hash, sizeof(UINT));
+
+ return ret;
+}
+
+// Get the current DDNS FQDN
+void GetCurrentDDnsFqdn(char *name, UINT size)
+{
+ ClearStr(name, size);
+ // Validate arguments
+ if (name == NULL || size == 0)
+ {
+ return;
+ }
+
+ Lock(current_fqdn_lock);
+ {
+ StrCpy(name, size, current_fqdn);
+ }
+ Unlock(current_fqdn_lock);
+
+ Trim(name);
+}
+
+// Check whether the specified MAC address exists on the local host (high speed)
+bool IsMacAddressLocalFast(void *addr)
+{
+ bool ret = false;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ Lock(local_mac_list_lock);
+ {
+ if (local_mac_list == NULL)
+ {
+ // First enumeration
+ RefreshLocalMacAddressList();
+ }
+
+ ret = IsMacAddressLocalInner(local_mac_list, addr);
+ }
+ Unlock(local_mac_list_lock);
+
+ return ret;
+}
+
+// Update the local MAC address list
+void RefreshLocalMacAddressList()
+{
+ Lock(local_mac_list_lock);
+ {
+ if (local_mac_list != NULL)
+ {
+ FreeNicList(local_mac_list);
+ }
+
+ local_mac_list = GetNicList();
+ }
+ Unlock(local_mac_list_lock);
+}
+
+// Check whether the specified MAC address exists on the local host
+bool IsMacAddressLocal(void *addr)
+{
+ LIST *o;
+ bool ret;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ o = GetNicList();
+
+ ret = IsMacAddressLocalInner(o, addr);
+
+ FreeNicList(o);
+
+ return ret;
+}
+bool IsMacAddressLocalInner(LIST *o, void *addr)
+{
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (o == NULL || addr == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NIC_ENTRY *e = LIST_DATA(o, i);
+
+ if (Cmp(e->MacAddress, addr, 6) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Get a list of the NICs on the computer
+LIST *GetNicList()
+{
+ LIST *o = NULL;
+
+#ifdef OS_WIN32
+ o = Win32GetNicList();
+#endif // OS_WIN32
+
+#ifdef UNIX_LINUX
+#endif // UNIX_LINUX
+
+ if (o == NULL)
+ {
+ return NewListFast(NULL);
+ }
+
+ return o;
+}
+
+#ifdef OS_WIN32
+LIST *Win32GetNicList()
+{
+ UINT i;
+ LIST *o = NewListFast(NULL);
+ MS_ADAPTER_LIST *al = MsCreateAdapterList();
+
+ if (al == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < al->Num;i++)
+ {
+ MS_ADAPTER *a = al->Adapters[i];
+
+ if (a->Type == 6 && a->AddressSize == 6)
+ {
+ NIC_ENTRY *e = ZeroMalloc(sizeof(NIC_ENTRY));
+
+ StrCpy(e->IfName, sizeof(e->IfName), a->Title);
+ Copy(e->MacAddress, a->Address, 6);
+
+ Add(o, e);
+ }
+ }
+
+ MsFreeAdapterList(al);
+
+ return o;
+}
+#endif // OS_WIN32
+
+// Release the NIC list
+void FreeNicList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NIC_ENTRY *e = LIST_DATA(o, i);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// If the computer is connected to the FLET'S line currently, detect the type of the line (obsolete)
+UINT DetectFletsType()
+{
+ UINT ret = 0;
+ //LIST *o = GetHostIPAddressList();
+// UINT i;
+
+/*
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ if (IsIP6(ip))
+ {
+ char ip_str[MAX_SIZE];
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (IsInSameNetwork6ByStr(ip_str, "2001:c90::", "/32"))
+ {
+ // NTT East B-FLETs
+ ret |= FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE;
+ }
+
+ if (IsInSameNetwork6ByStr(ip_str, "2408:200::", "/23"))
+ {
+ // Wrapping in network of NTT East NGN
+ ret |= FLETS_DETECT_TYPE_EAST_NGN_PRIVATE;
+ }
+
+ if (IsInSameNetwork6ByStr(ip_str, "2001:a200::", "/23"))
+ {
+ // Wrapping in network of NTT West NGN
+ ret |= FLETS_DETECT_TYPE_WEST_NGN_PRIVATE;
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+*/
+ return ret;
+}
+
+// Query for the IP address using the DNS proxy for the B FLETs
+bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname)
+{
+ SOCK *s;
+ char connect_hostname[MAX_SIZE];
+ char connect_hostname2[MAX_SIZE];
+ IP dns_proxy_ip;
+ bool ret = false;
+ bool dummy_flag = false;
+ char request_str[512];
+ // Validate arguments
+ if (ip_ret == NULL || hostname == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_QUERY;
+ }
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+
+ // Get the IP address of the DNS proxy server
+ if (IsEmptyStr(dns_proxy_hostname))
+ {
+ // B FLETs
+ if (GetDnsProxyIPAddressForJapanBFlets(&dns_proxy_ip, BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F, cancel) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // FLET'S NEXT
+ if (GetIP4Ex6Ex2(&dns_proxy_ip, dns_proxy_hostname, FLETS_NGN_DNS_QUERY_TIMEOUT, true, cancel, true) == false)
+ {
+ return false;
+ }
+ }
+
+ if (*cancel)
+ {
+ return false;
+ }
+
+ IPToStr(connect_hostname, sizeof(connect_hostname), &dns_proxy_ip);
+
+ /*{
+ StrCpy(connect_hostname, sizeof(connect_hostname), "2409:250:62c0:100:6a05:caff:fe09:5158");
+ }*/
+
+ StrCpy(connect_hostname2, sizeof(connect_hostname2), connect_hostname);
+ if (IsIP6(&dns_proxy_ip))
+ {
+ Format(connect_hostname2, sizeof(connect_hostname2), "[%s]", connect_hostname);
+ }
+
+ s = ConnectEx3(connect_hostname, BFLETS_DNS_PROXY_PORT, timeout, cancel, NULL, NULL, false, false, false);
+
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (*cancel)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return false;
+ }
+
+ SetTimeout(s, timeout);
+
+ // Start the SSL
+ if (StartSSLEx(s, NULL, NULL, true, 0, NULL) && (*cancel == false))
+ {
+ UCHAR hash[SHA1_SIZE];
+ BUF *hash2 = StrToBin(BFLETS_DNS_PROXY_CERT_HASH);
+
+ Zero(hash, sizeof(hash));
+ GetXDigest(s->RemoteX, hash, true);
+
+ if (Cmp(hash, hash2->Buf, SHA1_SIZE) == 0)
+ {
+ // Send the HTTP Request
+ Format(request_str, sizeof(request_str),
+ "GET " BFLETS_DNS_PROXY_PATH "?q=%s&ipv6=%u\r\n"
+ "\r\n",
+ hostname, ipv6, connect_hostname2);
+
+ if (SendAll(s, request_str, StrLen(request_str), true))
+ {
+ if (*cancel == false)
+ {
+ BUF *recv_buf = NewBuf();
+ UINT port_ret;
+
+ while (true)
+ {
+ UCHAR tmp[MAX_SIZE];
+ UINT r;
+
+ r = Recv(s, tmp, sizeof(tmp), true);
+
+ if (r == 0 || (recv_buf->Size > 65536))
+ {
+ break;
+ }
+ else
+ {
+ WriteBuf(recv_buf, tmp, r);
+ }
+ }
+
+ ret = RUDPParseIPAndPortStr(recv_buf->Buf, recv_buf->Size, ip_ret, &port_ret);
+
+ FreeBuf(recv_buf);
+ }
+ }
+ }
+
+ FreeBuf(hash2);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ if (ret)
+ {
+ NewDnsCache(hostname, ip_ret);
+ }
+
+ return ret;
+}
+
+// Get the IP address of the available DNS proxy in B-FLET'S service that is provided by NTT East of Japan
+bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel)
+{
+ BUF *b;
+ LIST *o;
+ bool ret = false;
+ // Validate arguments
+ if (ip_ret == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F;
+ }
+
+ b = QueryFileByUdpForJapanBFlets(timeout, cancel);
+
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ o = ReadIni(b);
+
+ if (o != NULL)
+ {
+ INI_ENTRY *e = GetIniEntry(o, "DDnsServerForBFlets");
+
+ if (e != NULL)
+ {
+ char *s = e->Value;
+
+ if (IsEmptyStr(s) == false)
+ {
+ IP ip;
+
+ if (StrToIP(&ip, s))
+ {
+ if (IsZeroIp(&ip) == false)
+ {
+ Copy(ip_ret, &ip, sizeof(IP));
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeIni(o);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get a valid F.txt file in B-FLET'S service that is provided by NTT East of Japan
+BUF *QueryFileByUdpForJapanBFlets(UINT timeout, bool *cancel)
+{
+ bool dummy_flag = false;
+ BUF *txt_buf = NULL;
+ BUF *ret = NULL;
+ LIST *ip_list = NULL;
+ UINT i;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F;
+ }
+
+ txt_buf = ReadDump(UDP_FILE_QUERY_BFLETS_TXT_FILENAME);
+ if (txt_buf == NULL)
+ {
+ return NULL;
+ }
+
+ ip_list = NewListFast(NULL);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(txt_buf);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false && StartWith(line, "#") == false)
+ {
+ IP ip;
+
+ if (StrToIP6(&ip, line))
+ {
+ if (IsZeroIp(&ip) == false)
+ {
+ if (IsIPv6LocalNetworkAddress(&ip) == false)
+ {
+ Add(ip_list, Clone(&ip, sizeof(IP)));
+ }
+ }
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(txt_buf);
+
+ ret = QueryFileByIPv6Udp(ip_list, timeout, cancel);
+
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ Free(ip);
+ }
+
+ ReleaseList(ip_list);
+
+ return ret;
+}
+
+// Request a file by UDP (send the requests to the multiple IP addresses at the same time)
+BUF *QueryFileByIPv6Udp(LIST *ip_list, UINT timeout, bool *cancel)
+{
+ bool dummy_flag = false;
+ UINT64 start_tick, giveup_tick;
+ UINT64 next_send_tick;
+ SOCK *s;
+ INTERRUPT_MANAGER *interrupt;
+ BUF *buf = NULL;
+ SOCK_EVENT *se;
+ UCHAR *tmp_buf;
+ UINT tmp_buf_size = 65535;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+ if (ip_list == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewUDP6(0, NULL);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_buf = Malloc(tmp_buf_size);
+
+ start_tick = Tick64();
+ giveup_tick = start_tick + (UINT64)timeout;
+ next_send_tick = 0;
+
+ interrupt = NewInterruptManager();
+
+ AddInterrupt(interrupt, giveup_tick);
+
+ se = NewSockEvent();
+ JoinSockToSockEvent(s, se);
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ if (now >= giveup_tick)
+ {
+ // Time-out
+ break;
+ }
+
+ if (*cancel)
+ {
+ // User canceled
+ break;
+ }
+
+ // Receive
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ UINT r;
+
+ r = RecvFrom(s, &src_ip, &src_port, tmp_buf, tmp_buf_size);
+
+ if (r == SOCK_LATER || r == 0)
+ {
+ break;
+ }
+
+ if (src_port == UDP_FILE_QUERY_DST_PORT)
+ {
+ if (r >= 40)
+ {
+ if (Cmp(tmp_buf, UDP_FILE_QUERY_MAGIC_NUMBER, StrLen(UDP_FILE_QUERY_MAGIC_NUMBER)) == 0)
+ {
+ // Successful reception
+ buf = NewBuf();
+ WriteBuf(buf, tmp_buf, r);
+ SeekBuf(buf, 0, 0);
+ break;
+ }
+ }
+ }
+ }
+
+ if (buf != NULL)
+ {
+ // Successful reception
+ break;
+ }
+
+ if (next_send_tick == 0 || (now >= next_send_tick))
+ {
+ // Transmission
+ UINT i;
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+ UCHAR c = 'F';
+
+ SendTo(s, ip, UDP_FILE_QUERY_DST_PORT, &c, 1);
+ }
+
+ next_send_tick = now + (UINT64)UDP_FILE_QUERY_RETRY_INTERVAL;
+ AddInterrupt(interrupt, next_send_tick);
+ }
+
+ WaitSockEvent(se, GetNextIntervalForInterrupt(interrupt));
+ }
+
+ FreeInterruptManager(interrupt);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ ReleaseSockEvent(se);
+
+ Free(tmp_buf);
+
+ return buf;
+}
+
+// Parse the user name of the NT
+void ParseNtUsername(char *src_username, char *dst_username, UINT dst_username_size, char *dst_domain, UINT dst_domain_size, bool do_not_parse_atmark)
+{
+ char tmp_username[MAX_SIZE];
+ char tmp_domain[MAX_SIZE];
+ TOKEN_LIST *t;
+
+ if (src_username != dst_username)
+ {
+ ClearStr(dst_username, dst_username_size);
+ }
+
+ ClearStr(dst_domain, dst_domain_size);
+ // Validate arguments
+ if (src_username == NULL || dst_username == NULL || dst_domain == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp_username, sizeof(tmp_username), src_username);
+ ClearStr(tmp_domain, sizeof(tmp_domain));
+
+ // Analysis of username@domain.name format
+ if (do_not_parse_atmark == false)
+ {
+ t = ParseTokenWithNullStr(tmp_username, "@");
+ if (t->NumTokens >= 1)
+ {
+ StrCpy(tmp_username, sizeof(tmp_username), t->Token[0]);
+ }
+ if (t->NumTokens >= 2)
+ {
+ StrCpy(tmp_domain, sizeof(tmp_domain), t->Token[1]);
+ }
+ FreeToken(t);
+ }
+
+ // If the username part is in "domain\username" format, split it
+ t = ParseTokenWithNullStr(tmp_username, "\\");
+ if (t->NumTokens >= 2)
+ {
+ if (IsEmptyStr(tmp_domain))
+ {
+ StrCpy(tmp_domain, sizeof(tmp_domain), t->Token[0]);
+ }
+
+ StrCpy(tmp_username, sizeof(tmp_username), t->Token[1]);
+ }
+ FreeToken(t);
+
+ StrCpy(dst_username, dst_username_size, tmp_username);
+ StrCpy(dst_domain, dst_domain_size, tmp_domain);
+}
+
+// The calculation of the optimum MSS value for use in TCP/IP packet in the payload of bulk transfer in R-UDP session
+UINT RUDPCalcBestMssForBulk(RUDP_STACK *r, RUDP_SESSION *se)
+{
+ UINT ret;
+ // Validate arguments
+ if (r == NULL || se == NULL)
+ {
+ return 0;
+ }
+
+ ret = MTU_FOR_PPPOE;
+
+ // IPv4
+ if (IsIP6(&se->YourIp) == false)
+ {
+ ret -= 20;
+ }
+ else
+ {
+ ret -= 40;
+ }
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // ICMP
+ ret -= 8;
+
+ ret -= SHA1_SIZE;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // UDP
+ ret -= 8;
+
+ // DNS
+ ret -= 42;
+ }
+
+ // IV
+ ret -= SHA1_SIZE;
+
+ // Sign
+ ret -= SHA1_SIZE;
+
+ // SEQ_NO
+ ret -= sizeof(UINT64);
+
+ // Padding Max
+ ret -= 31;
+
+ // Ethernet header (target packets of communication)
+ ret -= 14;
+
+ // IPv4 Header (target packet of communication)
+ ret -= 20;
+
+ // TCP header (target packet of communication)
+ ret -= 20;
+
+ // I don't know well, but subtract 24 bytes
+ ret -= 24;
+
+ return ret;
+}
+
+// Processing of the reply packet from the NAT-T server
+void RUDPProcess_NatT_Recv(RUDP_STACK *r, UDPPACKET *udp)
+{
+ BUF *b;
+ PACK *p;
+ // Validate arguments
+ if (r == NULL || udp == NULL)
+ {
+ return;
+ }
+
+ if (udp->Size >= 8)
+ {
+ char tmp[128];
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, udp->Data, MIN(udp->Size, sizeof(tmp) - 1));
+
+ if (StartWith(tmp, "IP="))
+ {
+ IP my_ip;
+ UINT my_port;
+
+ // There was a response to the packet to determine the NAT state
+ if (IsEmptyStr(r->NatT_Registered_IPAndPort) == false)
+ {
+ if (StrCmpi(r->NatT_Registered_IPAndPort, tmp) != 0)
+ {
+ // Redo getting the token and registration because the NAT state is changed
+ ClearStr(r->NatT_Registered_IPAndPort, sizeof(r->NatT_Registered_IPAndPort));
+
+ r->NatT_GetTokenNextTick = 0;
+ r->NatT_GetTokenFailNum = 0;
+ r->NatT_Token_Ok = false;
+ Zero(r->NatT_Token, sizeof(r->NatT_Token));
+
+ r->NatT_RegisterNextTick = 0;
+ r->NatT_RegisterFailNum = 0;
+ r->NatT_Register_Ok = false;
+ }
+ }
+
+ if (RUDPParseIPAndPortStr(udp->Data, udp->Size, &my_ip, &my_port))
+ {
+ if (r->NatTGlobalUdpPort != NULL)
+ {
+ *r->NatTGlobalUdpPort = my_port;
+ }
+ }
+
+ return;
+ }
+ }
+
+ // Interpret the UDP packet
+ b = NewBuf();
+ WriteBuf(b, udp->Data, udp->Size);
+ SeekBuf(b, 0, 0);
+
+ p = BufToPack(b);
+
+ if (p != NULL)
+ {
+ bool is_ok = PackGetBool(p, "ok");
+ UINT64 tran_id = PackGetInt64(p, "tran_id");
+
+ ExtractAndApplyDynList(p);
+
+ if (r->ServerMode)
+ {
+ if (PackCmpStr(p, "opcode", "get_token"))
+ {
+ // Get the Token
+ if (is_ok && (tran_id == r->NatT_TranId))
+ {
+ char tmp[MAX_SIZE];
+
+ if (PackGetStr(p, "token", tmp, sizeof(tmp)) && IsEmptyStr(tmp) == false)
+ {
+ char myip[MAX_SIZE];
+ // Acquisition success
+ StrCpy(r->NatT_Token, sizeof(r->NatT_Token), tmp);
+ r->NatT_Token_Ok = true;
+ r->NatT_GetTokenNextTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN, UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX);
+ r->NatT_GetTokenFailNum = 0;
+
+ // Since success to obtain the self global IPv4 address,
+ // re-obtain the destination NAT-T host from this IPv4 address
+ if (PackGetStr(p, "your_ip", myip, sizeof(myip)))
+ {
+ IP ip;
+ char new_hostname[MAX_SIZE];
+
+ StrToIP(&ip, myip);
+
+ SetCurrentGlobalIP(&ip, false);
+
+ RUDPGetRegisterHostNameByIP(new_hostname,
+ sizeof(new_hostname), &ip);
+
+ Lock(r->Lock);
+ {
+ if (StrCmpi(r->CurrentRegisterHostname, new_hostname) != 0)
+ {
+ // Change the host name
+ Debug("CurrentRegisterHostname Changed: New=%s\n", new_hostname);
+ StrCpy(r->CurrentRegisterHostname, sizeof(r->CurrentRegisterHostname), new_hostname);
+
+ Zero(&r->NatT_IP, sizeof(r->NatT_IP));
+ //Zero(&r->NatT_IP_Safe, sizeof(r->NatT_IP_Safe));
+
+ Set(r->HaltEvent);
+ }
+ }
+ Unlock(r->Lock);
+ }
+
+ AddInterrupt(r->Interrupt, r->NatT_GetTokenNextTick);
+ }
+ }
+ }
+ else if (PackCmpStr(p, "opcode", "nat_t_register"))
+ {
+ // NAT-T server registration result
+ if (is_ok && (tran_id == r->NatT_TranId))
+ {
+ UINT my_global_port;
+ // Successful registration
+ r->NatT_Register_Ok = true;
+ r->NatT_RegisterNextTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_REGISTER_INTERVAL_MIN, UDP_NAT_T_REGISTER_INTERVAL_MAX);
+ r->NatT_RegisterFailNum = 0;
+
+ Debug("NAT-T Registered.\n");
+
+ // Save the IP address and port number at the time of registration
+ PackGetStr(p, "your_ip_and_port", r->NatT_Registered_IPAndPort, sizeof(r->NatT_Registered_IPAndPort));
+
+ // Global port of itself
+ my_global_port = PackGetInt(p, "your_port");
+
+ if (my_global_port != 0)
+ {
+ if (r->NatTGlobalUdpPort != NULL)
+ {
+ *r->NatTGlobalUdpPort = my_global_port;
+ }
+ }
+
+ AddInterrupt(r->Interrupt, r->NatT_RegisterNextTick);
+ }
+ }
+ else if (PackCmpStr(p, "opcode", "nat_t_connect_relay"))
+ {
+ // Connection request from the client via the NAT-T server
+ if (is_ok)
+ {
+ char client_ip_str[MAX_SIZE];
+ UINT client_port;
+ IP client_ip;
+
+ PackGetStr(p, "client_ip", client_ip_str, sizeof(client_ip_str));
+ client_port = PackGetInt(p, "client_port");
+ StrToIP(&client_ip, client_ip_str);
+
+ if (IsZeroIp(&client_ip) == false && client_port != 0)
+ {
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 19;
+ rand_data = Malloc(rand_size);
+
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &client_ip, client_port, rand_data, rand_size, 0);
+
+ Free(rand_data);
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(b);
+}
+
+// Process such as packet transmission for NAT-T server
+void RUDPDo_NatT_Interrupt(RUDP_STACK *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ if (r->ServerMode)
+ {
+ if (IsZeroIp(&r->NatT_IP_Safe) == false)
+ {
+ if (g_no_rudp_register == false)
+ {
+ if (r->NatT_GetTokenNextTick == 0 || r->Now >= r->NatT_GetTokenNextTick)
+ {
+ // Try to get a token from the NAT-T server periodically
+ PACK *p = NewPack();
+ BUF *b;
+
+ PackAddStr(p, "opcode", "get_token");
+ PackAddInt64(p, "tran_id", r->NatT_TranId);
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+ b = PackToBuf(p);
+ FreePack(p);
+
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, b->Buf, b->Size, 0);
+
+ FreeBuf(b);
+
+ // Determine the next acquisition time
+ r->NatT_GetTokenFailNum++;
+ r->NatT_GetTokenNextTick = r->Now + (UINT64)(UDP_NAT_T_GET_TOKEN_INTERVAL_1 * (UINT64)MIN(r->NatT_GetTokenFailNum, UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX));
+ AddInterrupt(r->Interrupt, r->NatT_GetTokenNextTick);
+ r->NatT_Token_Ok = false;
+ }
+ }
+
+ if (r->NatT_NextNatStatusCheckTick == 0 || r->Now >= r->NatT_NextNatStatusCheckTick)
+ {
+ UCHAR a = 'A';
+ UINT ddns_hash;
+ // Check of the NAT state
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, &a, 1, 0);
+
+ // Execution time of the next
+ r->NatT_NextNatStatusCheckTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, r->NatT_NextNatStatusCheckTick);
+
+ // Check whether the DDNS host name changing have not occurred
+ ddns_hash = GetCurrentDDnsFqdnHash();
+
+ if (r->LastDDnsFqdnHash != ddns_hash)
+ {
+ r->LastDDnsFqdnHash = ddns_hash;
+ // Do the Register immediately if there is a change in the DDNS host name
+ r->NatT_RegisterNextTick = 0;
+ }
+ }
+
+ if (r->NatT_Token_Ok && g_no_rudp_register == false)
+ {
+ if (r->NatT_RegisterNextTick == 0 || r->Now >= r->NatT_RegisterNextTick)
+ {
+ // Try to register itself periodically for NAT-T server
+ PACK *p = NewPack();
+ BUF *b;
+ char private_ip_str[MAX_SIZE];
+ char machine_key[MAX_SIZE];
+ char machine_name[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char ddns_fqdn[MAX_SIZE];
+
+ Debug("NAT-T Registering...\n");
+
+ GetCurrentDDnsFqdn(ddns_fqdn, sizeof(ddns_fqdn));
+
+ PackAddStr(p, "opcode", "nat_t_register");
+ PackAddInt64(p, "tran_id", r->NatT_TranId);
+ PackAddStr(p, "token", r->NatT_Token);
+ PackAddStr(p, "svc_name", r->SvcName);
+ PackAddStr(p, "product_str", CEDAR_PRODUCT_STR);
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+
+ if (g_natt_low_priority)
+ {
+ PackAddBool(p, "low_priority", g_natt_low_priority);
+ }
+
+ Zero(private_ip_str, sizeof(private_ip_str));
+ if (IsZeroIp(&r->My_Private_IP_Safe) == false)
+ {
+ IPToStr(private_ip_str, sizeof(private_ip_str), &r->My_Private_IP_Safe);
+ PackAddStr(p, "private_ip", private_ip_str);
+ }
+
+ PackAddInt(p, "private_port", r->UdpSock->LocalPort);
+
+ Zero(hash, sizeof(hash));
+ GetCurrentMachineIpProcessHash(hash);
+ BinToStr(machine_key, sizeof(machine_key), hash, sizeof(hash));
+ PackAddStr(p, "machine_key", machine_key);
+
+ Zero(machine_name, sizeof(machine_name));
+ GetMachineName(machine_name, sizeof(machine_name));
+ PackAddStr(p, "host_name", machine_name);
+ PackAddStr(p, "ddns_fqdn", ddns_fqdn);
+
+ b = PackToBuf(p);
+ FreePack(p);
+
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, b->Buf, b->Size, 0);
+ //RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, "a", 1);
+
+ FreeBuf(b);
+
+ // Determine the next acquisition time
+ r->NatT_RegisterFailNum++;
+ r->NatT_RegisterNextTick = r->Now + (UINT64)UDP_NAT_T_REGISTER_INTERVAL_INITIAL * (UINT64)MIN(r->NatT_RegisterFailNum, UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX);
+ AddInterrupt(r->Interrupt, r->NatT_RegisterNextTick);
+ r->NatT_Register_Ok = false;
+ }
+ }
+ }
+ }
+}
+
+// R-UDP packet reception procedure
+void RUDPRecvProc(RUDP_STACK *r, UDPPACKET *p)
+{
+ RUDP_SESSION *se = NULL;
+ // Validate arguments
+ if (r == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ if (p->SrcPort == UDP_NAT_T_PORT && CmpIpAddr(&p->SrcIP, &r->NatT_IP_Safe) == 0)
+ {
+ // There was a response from the NAT-T server
+ RUDPProcess_NatT_Recv(r, p);
+ return;
+ }
+ }
+
+ if (r->ServerMode)
+ {
+ if (r->ProcRpcRecv != NULL)
+ {
+ if (r->ProcRpcRecv(r, p))
+ {
+ return;
+ }
+ }
+ }
+
+ if (r->ServerMode)
+ {
+ // Search the session by the end-point information if in the server mode
+ se = RUDPSearchSession(r, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort);
+ }
+ else
+ {
+ // Session should exist only one in the case of client mode
+ if (LIST_NUM(r->SessionList) >= 1)
+ {
+ se = LIST_DATA(r->SessionList, 0);
+ }
+ else
+ {
+ se = NULL;
+ }
+ }
+
+ if (p->Size < 20)
+ {
+ // The received packet is too small
+ if (r->ServerMode == false)
+ {
+ if (se != NULL && se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ if (CmpIpAddr(&se->YourIp, &p->SrcIP) == 0)
+ {
+ // If the connection initialization packet which is shorter than 20 bytes
+ // has been received from the server side, overwrite the source port number
+ // of the packet to the client-side session information (for some NAT)
+ se->YourPort = p->SrcPort;
+ }
+ }
+ }
+ return;
+ }
+
+ if (se == NULL && r->ServerMode && p->Size >= 40)
+ {
+ // Corresponding to a sudden change of port number on the client side.
+ // The target session is a session which matches the client side IP address
+ // and the key and the signature is verified
+ UINT i;
+ for (i = 0; i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *s = LIST_DATA(r->SessionList, i);
+
+ if (CmpIpAddr(&s->YourIp, &p->SrcIP) == 0)
+ {
+ if (RUDPCheckSignOfRecvPacket(r, s, p->Data, p->Size))
+ {
+ // Signature matched
+ se = s;
+ break;
+ }
+ }
+ }
+ }
+
+ if (se == NULL)
+ {
+ // There is no session
+ if (r->ServerMode)
+ {
+ if (p->Size < 40)
+ {
+ bool ok = true;
+ UCHAR ctoken_hash[SHA1_SIZE];
+
+ Zero(ctoken_hash, sizeof(ctoken_hash));
+
+ // Examine the quota of new session creation
+ if (LIST_NUM(r->SessionList) >= RUDP_QUOTA_MAX_NUM_SESSIONS)
+ {
+ // Entire number of sessions exceeds the limit
+ ok = false;
+ }
+ else
+ {
+ UINT i;
+ // Check the number of sessions per IP address
+ UINT num = 0;
+
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (CmpIpAddr(&se->YourIp, &p->SrcIP) == 0)
+ {
+ num++;
+ }
+ }
+
+ if (num >= RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP)
+ {
+ // Limit exceeded the number of sessions per IP address
+ ok = false;
+ }
+ }
+
+
+ if (ok)
+ {
+ char ip_str[64];
+
+ // Create a session since a new session creation request packet was received
+ se = RUDPNewSession(true, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, p->Data);
+ se->Status = RUDP_SESSION_STATUS_ESTABLISHED;
+ Insert(r->SessionList, se);
+
+ IPToStr(ip_str, sizeof(ip_str), &p->SrcIP);
+ Debug("RUDPNewSession %X %s:%u\n", se, ip_str, p->SrcPort);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (p->Size < 40)
+ {
+ if (r->ServerMode)
+ {
+ if (Cmp(se->Key_Init, p->Data, SHA1_SIZE) == 0)
+ {
+ // New session creation request packet have received more than once. reply an ACK immediately for second and subsequent
+ se->LastSentTick = 0;
+
+ // Update the endpoint information
+ Copy(&se->YourIp, &p->SrcIP, sizeof(IP));
+ se->YourPort = p->SrcPort;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ else
+ {
+ // Since the different session creation request packet have been received from the same end point, ignore it
+ }
+ }
+ }
+ else
+ {
+ // Process the received packet
+ if (RUDPProcessRecvPacket(r, se, p->Data, p->Size) || RUDPProcessBulkRecvPacket(r, se, p->Data, p->Size))
+ {
+ // Update endpoint information (only the port number)
+ //Copy(&se->YourIp, &p->SrcIP, sizeof(IP));
+ se->YourPort = p->SrcPort;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ if (r->ServerMode)
+ {
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else
+ {
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REPLY ? ICMP_TYPE_INFORMATION_REQUEST : p->Type);
+ }
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ if (r->ServerMode)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ }
+ }
+ }
+}
+
+// R-UDP interrupt processing procedure
+void RUDPInterruptProc(RUDP_STACK *r)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ // Packet transmission and other process for NAT-T server
+ if (r->NoNatTRegister == false)
+ {
+ RUDPDo_NatT_Interrupt(r);
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (r->ClientInitiated == false)
+ {
+ bool client_target_inited = false;
+ Lock(r->Lock);
+ {
+ client_target_inited = r->TargetIpAndPortInited;
+ }
+ Unlock(r->Lock);
+
+ if (client_target_inited)
+ {
+ // Start a connection when there is the end point information of the destination server to connect as a client
+ RUDP_SESSION *se;
+ UCHAR init_key[SHA1_SIZE];
+ char ip_str[128];
+ UINT64 ui;
+
+ Rand(init_key, SHA1_SIZE);
+
+ se = RUDPNewSession(false, &r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ &r->TargetIp, r->TargetPort, init_key);
+
+ IPToStr(ip_str, sizeof(ip_str), &r->TargetIp);
+ Debug("RUDPNewSession %X %s:%u\n", se, ip_str, r->TargetPort);
+
+ Insert(r->SessionList, se);
+
+ ui = Endian64(se->Magic_Disconnect);
+ WriteFifo(se->SendFifo, &ui, sizeof(UINT64));
+
+ r->ClientInitiated = true;
+ }
+ }
+ }
+
+ // Process for all the sessions
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (r->Halt)
+ {
+ // Disconnect all the sessions if the R-UDP stack stopped
+ RUDPDisconnectSession(r, se, false);
+ }
+
+ if (se->FlushBulkSendTube)
+ {
+ if (se->TcpSock != NULL && se->TcpSock->BulkSendTube != NULL)
+ {
+ TubeFlush(se->TcpSock->BulkSendTube);
+ }
+
+ se->FlushBulkSendTube = false;
+ }
+
+ if (se->Status == RUDP_SESSION_STATUS_ESTABLISHED)
+ {
+ // Process for all of the sessions which is established a connection
+ UINT j;
+
+ if (r->Now >= (se->LatestRecvMyTick + (UINT64)RUDP_TIMEOUT))
+ {
+ // Disconnect the session because the fully communication failure is detected for a while
+ Debug("R-UDP Session %X Timed Out.\n", se);
+
+ RUDPDisconnectSession(r, se, false);
+ }
+
+ // If there are received segments, read to the part that has arrived in succession
+ if (FifoSize(se->RecvFifo) <= RUDP_MAX_FIFO_SIZE)
+ {
+ LIST *o;
+ UINT64 current_seq_no;
+
+ o = NULL;
+ current_seq_no = se->LastRecvCompleteSeqNo;
+ for (j = 0;j < LIST_NUM(se->RecvSegmentList);j++)
+ {
+ RUDP_SEGMENT *s;
+
+ current_seq_no++;
+
+ s = LIST_DATA(se->RecvSegmentList, j);
+
+ if (s->SeqNo == current_seq_no)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("%X s->SeqNo = %I64u, current_seq_no = %I64u\n", se, s->SeqNo, current_seq_no);
+#endif // RUDP_DETAIL_LOG
+
+ if (s->Size == sizeof(se->Magic_KeepAliveRequest) && Cmp(s->Data, se->Magic_KeepAliveRequest, sizeof(se->Magic_KeepAliveRequest)) == 0)
+ {
+ // Receive the KeepAlive Request
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv KeepAlive Request\n");
+#endif // RUDP_DETAIL_LOG
+
+ // Send a KeepAlive Response if the transmisson queue is empty
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("Send KeepAlive Response\n");
+#endif // RUDP_DETAIL_LOG
+
+ RUDPSendSegment(r, se, se->Magic_KeepAliveResponse, sizeof(se->Magic_KeepAliveResponse));
+ }
+ }
+ else if (s->Size == sizeof(se->Magic_KeepAliveResponse) && Cmp(s->Data, se->Magic_KeepAliveResponse, sizeof(se->Magic_KeepAliveResponse)) == 0)
+ {
+ // Receive the KeepAlive Response
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv KeepAlive Response\n");
+#endif // RUDP_DETAIL_LOG
+ }
+ else
+ {
+ // Write to the receive FIFO
+ WriteFifo(se->RecvFifo, s->Data, s->Size);
+ }
+ r->TotalLogicalReceived += s->Size;
+
+ // Advance the SEQ NO which has been received completely
+ se->LastRecvCompleteSeqNo = s->SeqNo;
+
+ // Add to the Delete list
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, s);
+ }
+ else
+ {
+ // Continuous reading is interrupted
+#ifdef RUDP_DETAIL_LOG
+ Debug("%X s->SeqNo = %I64u, current_seq_no = %I64u\n", se, s->SeqNo, current_seq_no);
+ WHERE;
+#endif // RUDP_DETAIL_LOG
+ break;
+ }
+ }
+
+ // Delete the segment which has been received completely
+ if (o != NULL)
+ {
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(o, j);
+
+ Delete(se->RecvSegmentList, s);
+ Free(s);
+ }
+ ReleaseList(o);
+ }
+ }
+
+ if (r->ServerMode && se->Magic_Disconnect == 0)
+ {
+ if (FifoSize(se->RecvFifo) >= sizeof(UINT64))
+ {
+ UINT64 ui;
+
+ if (ReadFifo(se->RecvFifo, &ui, sizeof(UINT64)) == sizeof(UINT64))
+ {
+ ui = Endian64(ui);
+
+ if ((ui & 0xffffffff00000000ULL) != 0ULL)
+ {
+ se->Magic_Disconnect = ui;
+ }
+ }
+ }
+ }
+
+ // If the data remains in FIFO, write it to the TCP socket as possible
+ if (r->ServerMode == false || se->Magic_Disconnect != 0)
+ {
+ while (FifoSize(se->RecvFifo) >= 1)
+ {
+ UINT ret;
+
+ RUDPInitSock(r, se);
+
+ ret = Send(se->TcpSock, FifoPtr(se->RecvFifo), FifoSize(se->RecvFifo), false);
+
+ if (ret == SOCK_LATER)
+ {
+ // Can not write any more
+ break;
+ }
+ else if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(se->TcpSock);
+ RUDPDisconnectSession(r, se, false);
+ break;
+ }
+ else
+ {
+ // Writing success
+ ReadFifo(se->RecvFifo, NULL, ret);
+ }
+ }
+ }
+
+ // Read the data as much as possible from the TCP socket and store it to FIFO
+ if (se->TcpSock != NULL)
+ {
+ SetNoNeedToRead(se->TcpSock);
+
+ while (FifoSize(se->SendFifo) <= RUDP_MAX_FIFO_SIZE)
+ {
+ UINT ret = Recv(se->TcpSock, r->TmpBuf, sizeof(r->TmpBuf), false);
+
+ if (ret == SOCK_LATER)
+ {
+ // Can not read any more
+ break;
+ }
+ else if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(se->TcpSock);
+ RUDPDisconnectSession(r, se, false);
+ break;
+ }
+ else
+ {
+ // Reading success
+ WriteFifo(se->SendFifo, r->TmpBuf, ret);
+ }
+ }
+ }
+
+ // Attempt to send a divided segment
+ while (true)
+ {
+ UINT64 seq_no_min, seq_no_max;
+
+ seq_no_min = RUDPGetCurrentSendingMinSeqNo(se);
+ seq_no_max = RUDPGetCurrentSendingMaxSeqNo(se);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("min=%I64u max=%I64u\n", seq_no_min, seq_no_max);
+#endif // RUDP_DETAIL_LOG
+
+ if (seq_no_min == 0 || ((seq_no_min + RUDP_MAX_NUM_ACK - 1) >= se->NextSendSeqNo))
+ {
+ // Because there is a room to send a new segment, send a segment
+ UINT size = MIN(FifoSize(se->SendFifo), RUDP_MAX_SEGMENT_SIZE);
+
+ if (size == 0)
+ {
+ // There is no more data to send in FIFO
+ break;
+ }
+
+ // Transmission
+ RUDPSendSegment(r, se, FifoPtr(se->SendFifo), size);
+
+ r->TotalLogicalSent += size;
+
+ // Advance the FIFO
+ ReadFifo(se->SendFifo, NULL, size);
+ }
+ else
+ {
+ // There is no room to send a new segment further
+ break;
+ }
+ }
+
+ if (se->DisconnectFlag == false)
+ {
+ UINT64 seq_no_min;
+
+ if (se->LastSentTick == 0 || (r->Now >= (se->LastSentTick + (UINT64)se->NextKeepAliveInterval)))
+ {
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ // Send a Keep-Alive if no data was sent for a while and the transmission queue is empty
+ RUDPSendSegment(r, se, se->Magic_KeepAliveRequest, sizeof(se->Magic_KeepAliveRequest));
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("Sent KeepAlive Request\n");
+#endif // RUDP_DETAIL_LOG
+ }
+
+ se->NextKeepAliveInterval = RUDP_KEEPALIVE_INTERVAL_MIN + (Rand32() % (RUDP_KEEPALIVE_INTERVAL_MAX - RUDP_KEEPALIVE_INTERVAL_MIN));
+
+ AddInterrupt(r->Interrupt, r->Now + se->NextKeepAliveInterval);
+ }
+
+ seq_no_min = RUDPGetCurrentSendingMinSeqNo(se);
+ for (j = 0;j < LIST_NUM(se->SendSegmentList);j++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, j);
+
+ if (s->SeqNo <= (seq_no_min + RUDP_MAX_NUM_ACK - 1))
+ {
+ if (s->NextSendTick == 0 || r->Now >= s->NextSendTick)
+ {
+ UINT next_interval;
+ // Transmits a segment which has not been sent even once yet, or whose retransmission time has arrived
+ RUDPSendSegmentNow(r, se, s->SeqNo, s->Data, s->Size);
+
+ if (se->CurrentRtt != 0)
+ {
+ next_interval = (se->CurrentRtt * 120 / 100) * Power(2, MIN(s->NumSent, 10));
+ }
+ else
+ {
+ next_interval = RUDP_RESEND_TIMER * Power(2, MIN(s->NumSent, 10));
+ }
+
+ next_interval = MIN(next_interval, RUDP_RESEND_TIMER_MAX);
+
+ s->NumSent++;
+
+ s->NextSendTick = r->Now + next_interval;
+
+ AddInterrupt(r->Interrupt, s->NextSendTick);
+ }
+ }
+ }
+
+ while (LIST_NUM(se->ReplyAckList) >= 1)
+ {
+ // If there are ACKs which is not responded yet in the list, send all of them
+ RUDPSendSegmentNow(r, se, se->NextSendSeqNo, NULL, 0);
+ }
+
+ // Send all if there are bulk transfer data
+ if (se->TcpSock != NULL)
+ {
+ SOCK *s = se->TcpSock;
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TUBE *t = s->BulkRecvTube;
+
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(t);
+
+ if (d == NULL)
+ {
+ break;
+ }
+
+ if (d->Header != NULL && d->HeaderSize == sizeof(TCP_PAIR_HEADER))
+ {
+ TCP_PAIR_HEADER *h = d->Header;
+
+ if (h->EnableHMac)
+ {
+ se->UseHMac = true;
+ }
+ }
+
+ RUDPBulkSend(r, se, d->Data, d->DataSize);
+
+ FreeTubeData(d);
+ }
+ }
+ }
+ }
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ // Send a connection request periodically from the client side
+ if (se->LastSentTick == 0 || ((se->LastSentTick + (UINT64)RUDP_RESEND_TIMER) <= r->Now))
+ {
+ UCHAR tmp[40];
+ UINT size_of_padding = 19;
+ UINT size = size_of_padding + SHA1_SIZE;
+
+ se->LastSentTick = r->Now;
+
+ Copy(tmp, se->Key_Init, SHA1_SIZE);
+ Rand(tmp + SHA1_SIZE, size_of_padding);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // ICMP packet
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 64 + 64;
+ rand_data = Malloc(rand_size);
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, rand_data, rand_size, ICMP_TYPE_ECHO_REQUEST);
+ Free(rand_data);
+
+ se->Client_Icmp_NextSendEchoRequest = r->Now + GenRandInterval(RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN, RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, se->Client_Icmp_NextSendEchoRequest);
+
+ // Try in both INFORMATION_REQUEST and ECHO_RESPONSE from the client side first
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, ICMP_TYPE_ECHO_RESPONSE);
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, ICMP_TYPE_INFORMATION_REQUEST);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // DNS
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, se->Dns_TranId);
+ }
+ else
+ {
+ // Normal UDP
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, 0);
+ }
+
+ AddInterrupt(r->Interrupt, r->Now + (UINT64)RUDP_RESEND_TIMER);
+ }
+ }
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ if (se->Client_Icmp_NextSendEchoRequest == 0 || (r->Now >= se->Client_Icmp_NextSendEchoRequest))
+ {
+ // Periodic ICMP Echo transmission from the client side when R-UDP used in ICMP mode
+ // (To maintain the mapping table of the NAT)
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 64 + 64;
+ rand_data = Malloc(rand_size);
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, rand_data, rand_size, ICMP_TYPE_ECHO_REQUEST);
+ Free(rand_data);
+
+ se->Client_Icmp_NextSendEchoRequest = r->Now + GenRandInterval(RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN, RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, se->Client_Icmp_NextSendEchoRequest);
+ }
+ }
+ }
+ }
+
+ // Release the disconnected sessions
+ o = NULL;
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (se->DisconnectFlag)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, se);
+ }
+ }
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(o, i);
+
+ Delete(r->SessionList, se);
+
+ RUDPFreeSession(se);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Do the bulk send
+void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
+{
+ UCHAR *buf;
+ UINT buf_size;
+ UINT padding_size;
+ UINT i;
+ CRYPT *c;
+ UCHAR crypt_key_src[SHA1_SIZE * 2];
+ UCHAR crypt_key[SHA1_SIZE];
+ UINT icmp_type;
+ UCHAR sign[SHA1_SIZE];
+ UCHAR iv[SHA1_SIZE + 1];
+ // Validate arguments
+ if (r == NULL || se == NULL || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ padding_size = Rand32() % 31 + 1;
+
+ buf_size = SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size;
+ buf = Malloc(buf_size);
+
+ // SEQ NO
+ WRITE_UINT64(buf + SHA1_SIZE + SHA1_SIZE, se->BulkNextSeqNo);
+ se->BulkNextSeqNo++;
+
+ // Data
+ Copy(buf + SHA1_SIZE + SHA1_SIZE + sizeof(UINT64), data, data_size);
+
+ // Padding
+ for (i = 0;i < padding_size;i++)
+ {
+ buf[SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + i] = (UCHAR)padding_size;
+ }
+
+ // Encryption
+ Copy(iv, se->BulkNextIv, SHA1_SIZE);
+ Copy(crypt_key_src + 0, se->BulkSendKey->Data, SHA1_SIZE);
+ Copy(crypt_key_src + SHA1_SIZE, iv, SHA1_SIZE);
+ HashSha1(crypt_key, crypt_key_src, SHA1_SIZE * 2);
+ c = NewCrypt(crypt_key, sizeof(crypt_key));
+ Encrypt(c, buf + SHA1_SIZE + SHA1_SIZE, buf + SHA1_SIZE + SHA1_SIZE, sizeof(UINT64) + data_size + padding_size);
+ FreeCrypt(c);
+
+ // IV
+ Copy(buf + SHA1_SIZE, iv, SHA1_SIZE);
+
+ // Sign
+ if (se->UseHMac == false)
+ {
+ Copy(buf + 0, se->BulkSendKey->Data, SHA1_SIZE);
+ HashSha1(sign, buf, SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size);
+ Copy(buf + 0, sign, SHA1_SIZE);
+ }
+ else
+ {
+ HMacSha1(buf + 0, se->BulkSendKey->Data, SHA1_SIZE, buf + SHA1_SIZE, SHA1_SIZE + sizeof(UINT64) + data_size + padding_size);
+ }
+
+ // Next IV
+ Copy(se->BulkNextIv, buf + buf_size - SHA1_SIZE, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ icmp_type = se->Icmp_Type;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ icmp_type = se->Dns_TranId;
+ }
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, buf, buf_size, icmp_type);
+
+ Free(buf);
+}
+
+// Start a socket for R-UDP Listening
+SOCK *ListenRUDP(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode)
+{
+ return ListenRUDPEx(svc_name, proc_interrupts, proc_rpc_recv, param, port, no_natt_register, over_dns_mode, NULL, 0);
+}
+SOCK *ListenRUDPEx(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ SOCK *s;
+ RUDP_STACK *r;
+
+ // Creating a R-UDP stack
+ r = NewRUDPServer(svc_name, proc_interrupts, proc_rpc_recv, param, port, no_natt_register, over_dns_mode, natt_global_udp_port, rand_port_id);
+ if (r == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewSock();
+
+ s->Type = SOCK_RUDP_LISTEN;
+ s->ListenMode = true;
+ s->Connected = true;
+
+ s->LocalPort = r->UdpSock->LocalPort;
+
+ s->R_UDP_Stack = r;
+
+ return s;
+}
+
+// Accept on the R-UDP socket
+SOCK *AcceptRUDP(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_RUDP_LISTEN || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ RUDP_STACK *r = s->R_UDP_Stack;
+ SOCK *ret;
+
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ ret = GetNextWithLock(r->NewSockQueue);
+
+ if (ret != NULL)
+ {
+ switch (r->Protocol)
+ {
+ case RUDP_PROTOCOL_UDP:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ break;
+
+ case RUDP_PROTOCOL_DNS:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_DNS);
+ break;
+
+ case RUDP_PROTOCOL_ICMP:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_ICMP);
+ break;
+ }
+
+ return ret;
+ }
+
+ Wait(r->NewSockConnectEvent, INFINITE);
+ }
+}
+
+// Verify the signature of the received packet
+bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UINT size;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Verification the signature (segment packet)
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->Key_Recv, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign2, sign2, r->SvcNameHash, SHA1_SIZE);
+ }
+
+ Copy(p, sign, SHA1_SIZE);
+ if (Cmp(sign, sign2, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+
+ if (se->BulkRecvKey == NULL)
+ {
+ return false;
+ }
+
+ // Verification signature (bulk packet)
+ if (se->UseHMac == false)
+ {
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->BulkRecvKey->Data, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (Cmp(sign, sign2, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+ }
+
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, size - SHA1_SIZE);
+ if (Cmp(p, sign2, SHA1_SIZE) == 0)
+ {
+ se->UseHMac = true;
+ return true;
+ }
+
+ return false;
+}
+
+// Process the received packet (bulk)
+bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ UINT size;
+ UCHAR keygen[SHA1_SIZE * 2];
+ UCHAR key[SHA1_SIZE];
+ CRYPT *c;
+ UCHAR padlen;
+ UINT64 seq_no;
+ UCHAR *payload;
+ UINT payload_size;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0 || se->BulkRecvKey == NULL)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Validate the signature
+ if (se->UseHMac == false)
+ {
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->BulkRecvKey->Data, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (Cmp(sign, sign2, SHA1_SIZE) != 0)
+ {
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, recv_size - SHA1_SIZE);
+
+ if (Cmp(p, sign2, SHA1_SIZE) != 0)
+ {
+ return false;
+ }
+ else
+ {
+ se->UseHMac = true;
+ }
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, recv_size - SHA1_SIZE);
+
+ if (Cmp(p, sign2, SHA1_SIZE) != 0)
+ {
+ return false;
+ }
+ }
+
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // IV
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+ iv = p;
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // Decrypt
+ if (size < 1)
+ {
+ return false;
+ }
+ Copy(keygen + 0, se->BulkRecvKey->Data, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, iv, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, p, p, size);
+ FreeCrypt(c);
+
+ // padlen
+ padlen = p[size - 1];
+ if (padlen == 0)
+ {
+ return false;
+ }
+ if (size < padlen)
+ {
+ return false;
+ }
+ size -= padlen;
+
+ // SEQ NO
+ seq_no = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (seq_no == 0 || seq_no >= (0xF000000000000000ULL))
+ {
+ // Sequence number is invalid
+ return false;
+ }
+
+ if ((seq_no + RUDP_BULK_SEQ_NO_RANGE) < se->BulkRecvSeqNoMax)
+ {
+ // Sequence number is too small
+ return false;
+ }
+
+ se->LastRecvTick = r->Now;
+
+ payload = p;
+ payload_size = size;
+
+ se->BulkRecvSeqNoMax = MAX(seq_no, se->BulkRecvSeqNoMax);
+
+ // Send the received bulk packet to the Tube of the socket
+ RUDPInitSock(r, se);
+
+ if (se->TcpSock != NULL)
+ {
+ SOCK *s = se->TcpSock;
+ TUBE *t = s->BulkSendTube;
+
+ if (t != NULL)
+ {
+ TubeSendEx2(t, payload, payload_size, NULL, true, RUDP_BULK_MAX_RECV_PKTS_IN_QUEUE);
+
+ se->FlushBulkSendTube = true;
+ }
+ }
+
+ return true;
+}
+
+// Process the received packet (segment)
+bool RUDPProcessRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ UINT size;
+ UCHAR keygen[SHA1_SIZE * 2];
+ UCHAR key[SHA1_SIZE];
+ CRYPT *c;
+ UCHAR padlen;
+ UINT num_ack;
+ UINT i;
+ UINT64 seq_no;
+ UCHAR *payload;
+ UINT payload_size;
+ UINT64 max_ack;
+ UINT64 my_tick, your_tick;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Validate the signature
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->Key_Recv, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign2, sign2, r->SvcNameHash, SHA1_SIZE);
+ }
+
+ if (Cmp(sign, sign2, SHA1_SIZE) != 0)
+ {
+ //WHERE;
+ return false;
+ }
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // IV
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+ iv = p;
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // Decrypt
+ if (size < 1)
+ {
+ return false;
+ }
+ Copy(keygen + 0, iv, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, se->Key_Recv, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, p, p, size);
+ FreeCrypt(c);
+
+ // padlen
+ padlen = p[size - 1];
+ if (padlen == 0)
+ {
+ return false;
+ }
+ if (size < padlen)
+ {
+ return false;
+ }
+ size -= padlen;
+
+ // MyTick
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ my_tick = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // YourTick
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ your_tick = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (your_tick > r->Now)
+ {
+ return false;
+ }
+
+ // MAX_ACK
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ max_ack = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // num_ack
+ if (size < sizeof(UINT))
+ {
+ return false;
+ }
+
+ num_ack = READ_UINT(p);
+ if (num_ack > RUDP_MAX_NUM_ACK)
+ {
+ return false;
+ }
+ p += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ // ACKs
+ if (size < (sizeof(UINT64) * num_ack + sizeof(UINT64)))
+ {
+ return false;
+ }
+
+ if (max_ack >= 1)
+ {
+ RUDPProcessAck2(r, se, max_ack);
+ }
+
+ for (i = 0;i < num_ack;i++)
+ {
+ UINT64 seq = READ_UINT64(p);
+
+ RUDPProcessAck(r, se, seq);
+
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+ }
+
+ // Processing of the Tick (Calculation of RTT)
+ if (my_tick >= 2)
+ {
+ my_tick--;
+ }
+ se->YourTick = MAX(se->YourTick, my_tick);
+
+ se->LatestRecvMyTick = MAX(se->LatestRecvMyTick, your_tick);
+
+ if (se->LatestRecvMyTick2 != se->LatestRecvMyTick)
+ {
+ se->LatestRecvMyTick2 = se->LatestRecvMyTick;
+ se->CurrentRtt = (UINT)(r->Now - se->LatestRecvMyTick);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("CurrentRTT = %u\n", se->CurrentRtt);
+#endif // RUDP_DETAIL_LOG
+ }
+
+ // SEQ NO
+ seq_no = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (seq_no == 0)
+ {
+ // Sequence number of 0 is a invalid packet
+ return true;
+ }
+
+ if (seq_no == se->Magic_Disconnect)
+ {
+ // Disconnected from opponent
+ RUDPDisconnectSession(r, se, true);
+ return true;
+ }
+
+ // Update the last reception date and time
+ se->LastRecvTick = r->Now;
+
+ payload = p;
+ payload_size = size;
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("RUDP %X Segment Recv: %I64u (num_ack=%u, size=%u)\n", se, seq_no, num_ack, size);
+#endif // RUDP_DETAIL_LOG
+
+ if (payload_size >= 1 && payload_size <= RUDP_MAX_SEGMENT_SIZE)
+ {
+ // Received one or more bytes of data
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv Size: %X %I64u %u %u\n", se, seq_no, payload_size, recv_size);
+#endif // RUDP_DETAIL_LOG
+
+ RUDPProcessRecvPayload(r, se, seq_no, payload, payload_size);
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ // Shift to the established state if the connection is not yet in established state
+ se->Status = RUDP_SESSION_STATUS_ESTABLISHED;
+
+ RUDPInitSock(r, se);
+ }
+ }
+
+ return true;
+}
+
+// Disconnect the session
+void RUDPDisconnectSession(RUDP_STACK *r, RUDP_SESSION *se, bool disconnected_by_you)
+{
+ // Validate arguments
+ if (r == NULL || se == NULL)
+ {
+ return;
+ }
+
+ if (se->DisconnectFlag == false)
+ {
+ UINT i;
+
+ se->DisconnectFlag = true;
+ se->DisconnectedByYou = disconnected_by_you;
+
+ Debug("R-UDP Session %X Disconnected. by you flag: %u\n", se, disconnected_by_you);
+
+ if (se->TcpSock != NULL)
+ {
+ // Disconnect a TCP socket
+ Disconnect(se->TcpSock);
+ ReleaseSock(se->TcpSock);
+
+ se->TcpSock = NULL;
+ }
+
+ // Send 5 disconnect signals serially if to disconnect from here
+ if (disconnected_by_you == false)
+ {
+ for (i = 0;i < 5;i++)
+ {
+ RUDPSendSegmentNow(r, se, se->Magic_Disconnect, NULL, 0);
+ }
+ }
+ }
+}
+
+// Initialize the TCP socket for the session
+void RUDPInitSock(RUDP_STACK *r, RUDP_SESSION *se)
+{
+ SOCK *s1, *s2;
+ UINT mss;
+ // Validate arguments
+ if (r == NULL || se == NULL || se->DisconnectFlag)
+ {
+ return;
+ }
+
+ if (se->TcpSock != NULL)
+ {
+ // It has already been created
+ return;
+ }
+
+ // Creating a TCP socket pair
+ if (NewTcpPair(&s1, &s2) == false)
+ {
+ // Failed to create. Disconnect the session
+ RUDPDisconnectSession(r, se, false);
+ return;
+ }
+
+ // Calculate the optimal MSS
+ mss = RUDPCalcBestMssForBulk(r, se);
+
+ if (r->ServerMode)
+ {
+ // Server mode
+ se->TcpSock = s2;
+
+ JoinSockToSockEvent(s2, r->SockEvent);
+
+ // Update the end point information of the socket s1
+ ZeroIP4(&s1->LocalIP);
+ s1->LocalPort = se->MyPort;
+ Copy(&s1->RemoteIP, &se->YourIp, sizeof(IP));
+ s1->RemotePort = se->YourPort;
+ if (IsLocalHostIP(&s1->RemoteIP) == false)
+ {
+ AddIpClient(&s1->RemoteIP);
+ s1->IpClientAdded = true;
+ }
+ s1->IsRUDPSocket = true;
+
+ s1->BulkSendKey = se->BulkSendKey;
+ s1->BulkRecvKey = se->BulkRecvKey;
+
+ AddRef(s1->BulkSendKey->Ref);
+ AddRef(s1->BulkRecvKey->Ref);
+
+ s1->RUDP_OptimizedMss = mss;
+
+ // Enqueue the newly created socket, and set the event
+ InsertQueueWithLock(r->NewSockQueue, s1);
+ Set(r->NewSockConnectEvent);
+ }
+ else
+ {
+ // Client mode
+ Lock(r->Lock);
+ {
+ if (r->TargetConnectedSock == NULL && r->DoNotSetTargetConnectedSock == false)
+ {
+ // Update the end point information of the socket s2
+ Copy(&s2->LocalIP, &r->UdpSock->LocalIP, sizeof(IP));
+ s2->LocalPort = se->MyPort;
+ Copy(&s2->RemoteIP, &se->YourIp, sizeof(IP));
+ s2->RemotePort = se->YourPort;
+ if (IsLocalHostIP(&s2->RemoteIP) == false)
+ {
+ AddIpClient(&s2->RemoteIP);
+ s2->IpClientAdded = true;
+ }
+ s2->IsRUDPSocket = true;
+
+ s2->BulkSendKey = se->BulkSendKey;
+ s2->BulkRecvKey = se->BulkRecvKey;
+
+ AddRef(s2->BulkSendKey->Ref);
+ AddRef(s2->BulkRecvKey->Ref);
+
+ s2->RUDP_OptimizedMss = mss;
+
+ // Register the socket to the RUDP stack
+ r->TargetConnectedSock = s2;
+ s2->R_UDP_Stack = r;
+ se->TcpSock = s1;
+
+ JoinSockToSockEvent(s1, r->SockEvent);
+
+ // Set the event to be set when the connection is successful
+ Set(r->TargetConnectedEvent);
+ }
+ else
+ {
+ Disconnect(s1);
+ Disconnect(s2);
+ ReleaseSock(s1);
+ ReleaseSock(s2);
+ }
+ }
+ Unlock(r->Lock);
+ }
+}
+
+// Process the received payload
+void RUDPProcessRecvPayload(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq, void *payload_data, UINT payload_size)
+{
+ RUDP_SEGMENT t;
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || seq == 0 || payload_data == NULL || payload_size == 0 || payload_size > RUDP_MAX_SEGMENT_SIZE)
+ {
+ return;
+ }
+
+ if (seq > (se->LastRecvCompleteSeqNo + RUDP_MAX_NUM_ACK))
+ {
+ // Ignore the segment which have sequence number beyond the window size, and also not to reply an ACK
+ return;
+ }
+
+ if (seq <= se->LastRecvCompleteSeqNo)
+ {
+ // Do not receive the segment which have the sequence number that has been already received. However, reply an ACK for it
+ AddInt64Distinct(se->ReplyAckList, seq);
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.SeqNo = seq;
+
+ s = Search(se->RecvSegmentList, &t);
+ if (s != NULL)
+ {
+ // Do not receive the segment which have the sequence number that has been already received. However, reply an ACK for it
+ AddInt64Distinct(se->ReplyAckList, seq);
+ return;
+ }
+
+ // Received a segment of the new sequence number
+ s = ZeroMalloc(sizeof(RUDP_SEGMENT));
+ s->SeqNo = seq;
+ Copy(s->Data, payload_data, payload_size);
+ s->Size = payload_size;
+ Insert(se->RecvSegmentList, s);
+
+ // Reply an ACK
+ AddInt64Distinct(se->ReplyAckList, seq);
+
+ // Create a socket for session if it have not been created yet
+ //RUDPInitSock(r, se);
+}
+
+// Process the incoming ACK
+void RUDPProcessAck(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq)
+{
+ RUDP_SEGMENT t;
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || seq == 0)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.SeqNo = seq;
+
+ s = Search(se->SendSegmentList, &t);
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Delete(se->SendSegmentList, s);
+ Free(s);
+}
+
+// Remove all segments which are preceding max_seq as already delivered
+void RUDPProcessAck2(RUDP_STACK *r, RUDP_SESSION *se, UINT64 max_seq)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (r == NULL || se == NULL || max_seq == 0)
+ {
+ return;
+ }
+
+ o = NULL;
+
+ for (i = 0;i < LIST_NUM(se->SendSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, i);
+
+ if (s->SeqNo <= max_seq)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, s);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(o, i);
+
+ Delete(se->SendSegmentList, s);
+
+ Free(s);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Get the minimum sequence number which is trying to send
+UINT64 RUDPGetCurrentSendingMinSeqNo(RUDP_SESSION *se)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return 0;
+ }
+
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ return 0;
+ }
+
+ s = LIST_DATA(se->SendSegmentList, 0);
+
+ return s->SeqNo;
+}
+
+// Get the maximum sequence number which is trying to send
+UINT64 RUDPGetCurrentSendingMaxSeqNo(RUDP_SESSION *se)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return 0;
+ }
+
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ return 0;
+ }
+
+ s = LIST_DATA(se->SendSegmentList, (LIST_NUM(se->SendSegmentList) - 1));
+
+ return s->SeqNo;
+}
+
+// R-UDP segment transmission
+void RUDPSendSegmentNow(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq_no, void *data, UINT size)
+{
+ UCHAR dst[RUDP_MAX_PACKET_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ LIST *o = NULL;
+ UINT i;
+ UCHAR padlen;
+ UINT current_size;
+ UCHAR sign[SHA1_SIZE];
+ UCHAR key[SHA1_SIZE];
+ UCHAR keygen[SHA1_SIZE * 2];
+ CRYPT *c;
+ UINT next_iv_pos;
+ UINT num_ack;
+ UINT icmp_type = 0;
+ // Validate arguments
+ if (r == NULL || se == NULL || (size != 0 && data == NULL) || (size > RUDP_MAX_SEGMENT_SIZE))
+ {
+ return;
+ }
+
+ Zero(dst, sizeof(dst));
+ p = dst;
+
+ // SIGN
+ Copy(p, se->Key_Send, SHA1_SIZE);
+ p += SHA1_SIZE;
+
+ // IV
+ iv = p;
+ Copy(iv, se->NextIv, SHA1_SIZE);
+ p += SHA1_SIZE;
+
+ for (i = 0;i < MIN(LIST_NUM(se->ReplyAckList), RUDP_MAX_NUM_ACK);i++)
+ {
+ UINT64 *seq = LIST_DATA(se->ReplyAckList, i);
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, seq);
+ }
+
+ // MyTick
+ WRITE_UINT64(p, r->Now);
+ p += sizeof(UINT64);
+
+ // YourTick
+ WRITE_UINT64(p, se->YourTick);
+ p += sizeof(UINT64);
+
+ // MAX_ACK
+ WRITE_UINT64(p, se->LastRecvCompleteSeqNo);
+ p += sizeof(UINT64);
+
+ // NUM_ACK
+ num_ack = LIST_NUM(o);
+ WRITE_UINT(p, num_ack);
+ p += sizeof(UINT);
+
+ if (o != NULL)
+ {
+ // ACK body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *seq = LIST_DATA(o, i);
+
+ WRITE_UINT64(p, *seq);
+ p += sizeof(UINT64);
+
+ Delete(se->ReplyAckList, seq);
+
+ Free(seq);
+ }
+ ReleaseList(o);
+ }
+
+ // SEQ
+ WRITE_UINT64(p, seq_no);
+ p += sizeof(UINT64);
+
+ // data
+ Copy(p, data, size);
+ p += size;
+
+ // padding
+ padlen = Rand8();
+ padlen = MAX(padlen, 1);
+
+ for (i = 0;i < padlen;i++)
+ {
+ *p = padlen;
+ p++;
+ }
+
+ current_size = (UINT)(p - dst);
+
+ // Encrypt
+ Copy(keygen + 0, iv, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, se->Key_Send, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, dst + SHA1_SIZE * 2, dst + SHA1_SIZE * 2, current_size - (SHA1_SIZE * 2));
+ FreeCrypt(c);
+
+ // Sign
+ HashSha1(sign, dst, current_size);
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign, sign, r->SvcNameHash, SHA1_SIZE);
+ }
+ Copy(dst, sign, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ icmp_type = se->Icmp_Type;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ icmp_type = se->Dns_TranId;
+ }
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, dst, current_size, icmp_type);
+
+ if (size >= 1)
+ {
+ se->LastSentTick = r->Now;
+ }
+
+ // Next IV
+ next_iv_pos = Rand32() % (current_size - SHA1_SIZE);
+ Copy(se->NextIv, dst + next_iv_pos, SHA1_SIZE);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("RUDP %X Segment Sent: %I64u (num_ack=%u, size=%u)\n", se, seq_no, num_ack, size);
+#endif // RUDP_DETAIL_LOG
+
+ if (size >= 1)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("Send Size: %X %I64u %u %u\n", se, seq_no, size, current_size);
+#endif // RUDP_DETAIL_LOG
+ }
+}
+
+// R-UDP segment transmission (only put into the queue)
+void RUDPSendSegment(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT size)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || (size != 0 && data == NULL) || (size > RUDP_MAX_SEGMENT_SIZE))
+ {
+ return;
+ }
+
+ s = ZeroMalloc(sizeof(RUDP_SEGMENT));
+
+ Copy(s->Data, data, size);
+ s->Size = size;
+
+ s->SeqNo = se->NextSendSeqNo++;
+
+ Insert(se->SendSegmentList, s);
+}
+
+// Search for a session
+RUDP_SESSION *RUDPSearchSession(RUDP_STACK *r, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port)
+{
+ RUDP_SESSION t;
+ RUDP_SESSION *se;
+ // Validate arguments
+ if (r == NULL || my_ip == NULL || your_ip == NULL)
+ {
+ return NULL;
+ }
+
+ Copy(&t.MyIp, my_ip, sizeof(IP));
+ t.MyPort = my_port;
+ Copy(&t.YourIp, your_ip, sizeof(IP));
+ t.YourPort = your_port;
+
+ se = Search(r->SessionList, &t);
+
+ return se;
+}
+
+// Release of the session
+void RUDPFreeSession(RUDP_SESSION *se)
+{
+ UINT i;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return;
+ }
+
+ Debug("RUDPFreeSession %X\n", se);
+
+ for (i = 0;i < LIST_NUM(se->SendSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, i);
+
+ Free(s);
+ }
+
+ ReleaseList(se->SendSegmentList);
+
+ for (i = 0;i < LIST_NUM(se->RecvSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->RecvSegmentList, i);
+
+ Free(s);
+ }
+
+ ReleaseList(se->RecvSegmentList);
+
+ if (se->TcpSock != NULL)
+ {
+ Disconnect(se->TcpSock);
+ ReleaseSock(se->TcpSock);
+ }
+
+ ReleaseInt64List(se->ReplyAckList);
+
+ ReleaseFifo(se->RecvFifo);
+ ReleaseFifo(se->SendFifo);
+
+ ReleaseSharedBuffer(se->BulkSendKey);
+ ReleaseSharedBuffer(se->BulkRecvKey);
+
+ Free(se);
+}
+
+// Create a new session
+RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port, UCHAR *init_key)
+{
+ RUDP_SESSION *se;
+ UCHAR key1[SHA1_SIZE];
+ UCHAR key2[SHA1_SIZE];
+ UCHAR bulk_send_key[SHA1_SIZE];
+ UCHAR bulk_recv_key[SHA1_SIZE];
+ BUF *b;
+
+ se = ZeroMalloc(sizeof(RUDP_SESSION));
+
+ Copy(&se->MyIp, my_ip, sizeof(IP));
+ se->MyPort = my_port;
+
+ Copy(&se->YourIp, your_ip, sizeof(IP));
+ se->YourPort = your_port;
+
+ Copy(se->Key_Init, init_key, SHA1_SIZE);
+ se->LastSentTick = 0;
+ se->LastRecvTick = Tick64();
+ se->LatestRecvMyTick = Tick64();
+
+ se->NextSendSeqNo = 1;
+
+ se->ServerMode = server_mode;
+
+ se->SendSegmentList = NewList(RUDPCompareSegmentList);
+ se->RecvSegmentList = NewList(RUDPCompareSegmentList);
+
+ // Generate the two keys
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "zurukko");
+ HashSha1(key1, b->Buf, b->Size);
+ FreeBuf(b);
+
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBuf(b, key1, SHA1_SIZE);
+ WriteBufStr(b, "yasushineko");
+ HashSha1(key2, b->Buf, b->Size);
+ FreeBuf(b);
+
+ // Generate the magic number for the KeepAlive
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "Magic_KeepAliveRequest");
+ HashSha1(se->Magic_KeepAliveRequest, b->Buf, b->Size);
+ FreeBuf(b);
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "Magic_KeepAliveResponse");
+ HashSha1(se->Magic_KeepAliveResponse, b->Buf, b->Size);
+ FreeBuf(b);
+
+ if (server_mode == false)
+ {
+ se->Magic_Disconnect = 0xffffffff00000000ULL | (UINT64)(Rand32());
+ }
+
+ Copy(se->Key_Init, init_key, SHA1_SIZE);
+
+ if (se->ServerMode)
+ {
+ Copy(se->Key_Send, key1, SHA1_SIZE);
+ Copy(se->Key_Recv, key2, SHA1_SIZE);
+ }
+ else
+ {
+ Copy(se->Key_Send, key2, SHA1_SIZE);
+ Copy(se->Key_Recv, key1, SHA1_SIZE);
+ }
+
+ Rand(se->NextIv, sizeof(se->NextIv));
+
+ se->ReplyAckList = NewInt64List(true);
+
+ se->NextKeepAliveInterval = RUDP_KEEPALIVE_INTERVAL_MIN + (Rand32() % (RUDP_KEEPALIVE_INTERVAL_MAX - RUDP_KEEPALIVE_INTERVAL_MIN));
+
+ se->RecvFifo = NewFifo();
+ se->SendFifo = NewFifo();
+
+ se->Dns_TranId = Rand16() % 65535 + 1;
+
+ // Generate the bulk transfer key
+ Rand(bulk_send_key, sizeof(bulk_send_key));
+ Rand(bulk_recv_key, sizeof(bulk_recv_key));
+
+ se->BulkSendKey = NewSharedBuffer(bulk_send_key, sizeof(bulk_send_key));
+ se->BulkRecvKey = NewSharedBuffer(bulk_recv_key, sizeof(bulk_recv_key));
+
+ Rand(se->BulkNextIv, sizeof(se->BulkNextIv));
+ se->BulkNextSeqNo = 1;
+
+ return se;
+}
+
+// Comparison function of the segment list items
+int RUDPCompareSegmentList(void *p1, void *p2)
+{
+ RUDP_SEGMENT *s1, *s2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *((RUDP_SEGMENT **)p1);
+ s2 = *((RUDP_SEGMENT **)p2);
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(s1->SeqNo, s2->SeqNo);
+
+ return r;
+}
+
+// Send a UDP packet
+void RUDPSendPacket(RUDP_STACK *r, IP *dest_ip, UINT dest_port, void *data, UINT size, UINT icmp_type)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (r == NULL || dest_ip == NULL || dest_port == 0 || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ p = NewUdpPacket(&r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ dest_ip, dest_port,
+ Clone(data, size), size);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP || r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // ICMP Type / DNS Tran ID
+ p->Type = icmp_type;
+ }
+
+ Add(r->SendPacketList, p);
+}
+
+// R-UDP main thread
+void RUDPMainThread(THREAD *thread, void *param)
+{
+ RUDP_STACK *r;
+ bool halt_flag = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ r = (RUDP_STACK *)param;
+
+ AddWaitThread(thread);
+ NoticeThreadInit(thread);
+
+ while (true)
+ {
+ UINT wait_interval;
+ UINT i;
+ UINT min_wait_interval;
+ UINT num_ignore_errors = 0;
+
+ r->Now = Tick64();
+
+ Lock(r->Lock);
+ {
+ Copy(&r->NatT_IP_Safe, &r->NatT_IP, sizeof(IP));
+ Copy(&r->My_Private_IP_Safe, &r->My_Private_IP, sizeof(IP));
+ }
+ Unlock(r->Lock);
+
+ // Receive the data from the UDP socket
+ while (true)
+ {
+ UINT ret;
+ IP ip_src;
+ UINT port_src;
+
+ ret = RecvFrom(r->UdpSock, &ip_src, &port_src, r->TmpBuf, sizeof(r->TmpBuf));
+
+ if (ret == SOCK_LATER)
+ {
+ // There is no packet more
+ break;
+ }
+ else if (ret != 0)
+ {
+ // Receive a Packet
+ bool ok = false;
+ UDPPACKET *p = NewUdpPacket(&ip_src, port_src,
+ &r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ Clone(r->TmpBuf, ret), ret);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // Analyse the incoming ICMP packet
+ UINT ip_header_size = GetIpHeaderSize(p->Data, p->Size);
+
+ if (ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ if (p->Size >= (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE))
+ {
+ IPV4_HEADER *ip_header = (IPV4_HEADER *)(((UCHAR *)p->Data) + 0);
+ ICMP_HEADER *icmp_header = (ICMP_HEADER *)(((UCHAR *)p->Data) + ip_header_size);
+ ICMP_ECHO *echo_header = (ICMP_ECHO *)(((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER));
+
+ if (icmp_header->Type == ICMP_TYPE_ECHO_RESPONSE ||
+ icmp_header->Type == (r->ServerMode ? ICMP_TYPE_INFORMATION_REQUEST : ICMP_TYPE_INFORMATION_REPLY))
+ {
+ UCHAR hash[SHA1_SIZE];
+
+ HashSha1(hash, ((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE,
+ p->Size - (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE));
+
+ if (Cmp(hash, ((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), SHA1_SIZE) == 0)
+ {
+ UCHAR *new_data;
+ UINT new_data_size;
+ if (r->ServerMode)
+ {
+ // On the server side, the ICMP ID and the SEQ NO of received messages are treated as a source port number
+ Copy(&p->SrcPort, echo_header, sizeof(UINT));
+ }
+
+ // Record the Type
+ p->Type = icmp_header->Type;
+
+ // Erase the header part
+ new_data_size = p->Size - (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE);
+ new_data = Clone(((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE, new_data_size);
+ Free(p->Data);
+ p->Data = new_data;
+ p->Size = new_data_size;
+
+ ok = true;
+ }
+ }
+ }
+ }
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Analyse the incoming DNS packet
+ UINT offset;
+
+ if (r->ServerMode == false)
+ {
+ offset = 42;
+ }
+ else
+ {
+ offset = 37;
+ }
+
+ if (p->Size > offset)
+ {
+ UCHAR *new_data;
+ UINT new_size = p->Size - offset;
+
+ p->Type = *((USHORT *)p->Data);
+
+ new_data = Clone(((UCHAR *)p->Data) + offset, new_size);
+
+ Free(p->Data);
+ p->Data = new_data;
+ p->Size = new_size;
+
+ ok = true;
+ }
+ }
+ else
+ {
+ // Don't do anything for ordinary UDP packet
+ ok = true;
+ }
+
+ if (ok)
+ {
+ // Process the received packet
+ RUDPRecvProc(r, p);
+
+ r->TotalPhysicalReceived += ret;
+ }
+
+ FreeUdpPacket(p);
+ }
+ else
+ {
+ if (r->UdpSock->IgnoreRecvErr)
+ {
+ // An ignorable reception error occurs
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // A non-ignorable reception error occurs
+ break;
+ }
+ }
+ }
+
+ // Call the interrupt notification callback function
+ if (r->ProcInterrupts != NULL)
+ {
+ r->ProcInterrupts(r);
+ }
+
+ RUDPInterruptProc(r);
+
+ // Send all packets in the transmission packet list
+ for (i = 0;i < LIST_NUM(r->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(r->SendPacketList, i);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of the ICMP protocol, assemble an ICMP header
+ UINT dst_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE + p->Size;
+ UCHAR *dst_data = ZeroMalloc(dst_size);
+
+ ICMP_HEADER *icmp_header = (ICMP_HEADER *)dst_data;
+ ICMP_ECHO *icmp_echo = (ICMP_ECHO *)(dst_data + sizeof(ICMP_HEADER));
+ UCHAR *hash = dst_data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ UCHAR *icmp_data = dst_data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE;
+
+ // Header
+ icmp_header->Type = (UCHAR)p->Type;
+ icmp_header->Code = 0;
+ icmp_header->Checksum = 0;
+
+ if (r->ServerMode)
+ {
+ // On the server side, use the port number in the opponent internal data as ICMP ID and SEQ NO
+ Copy(icmp_echo, &p->DestPort, 4);
+ }
+ else
+ {
+ // Use the fixed ICMP ID and SEQ NO on the client side
+ icmp_echo->Identifier = Endian16(r->Client_IcmpId);
+ icmp_echo->SeqNo = Endian16(r->Client_IcmpSeqNo);
+ }
+
+ // Data body
+ Copy(icmp_data, p->Data, p->Size);
+
+ // Hash
+ HashSha1(hash, icmp_data, p->Size);
+
+ // Checksum calculation
+ icmp_header->Checksum = IpChecksum(dst_data, dst_size);
+
+ // Replacement
+ Free(p->Data);
+ p->Data = dst_data;
+ p->Size = dst_size;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ BUF *b = NewBuf();
+ // In case of over DNS protocol, assemble a header that conforms to the DNS protocol
+ if (r->ServerMode == false)
+ {
+ // DNS query header
+ USHORT us = Rand16() % 65535 + 1;
+ static UCHAR dns_query_header_1[] =
+ {
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ };
+ static UCHAR dns_query_header_2[] =
+ {
+ 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10,
+ 0x00, 0x00, 0x00, 0x80, 0x00,
+ };
+ UCHAR rand_data[4];
+ char rand_str[MAX_SIZE];
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, sizeof(rand_data));
+ StrLower(rand_str);
+
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_query_header_1, sizeof(dns_query_header_1));
+ WriteBuf(b, rand_str, 8);
+ WriteBuf(b, dns_query_header_2, sizeof(dns_query_header_2));
+ us = Endian16((USHORT)p->Size);
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, p->Data, p->Size);
+ }
+ else
+ {
+ // DNS response header
+ USHORT us = p->Type;
+ UINT ui;
+ static UCHAR dns_response_header_1[] =
+ {
+ 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x08,
+ };
+ static UCHAR dns_response_header_2[] =
+ {
+ 0x00, 0x00, 0x30, 0x00, 0x01,
+ 0xc0, 0x0c, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0xa4, 0x5b,
+ };
+ static UCHAR dns_response_header_3[] =
+ {
+ 0x01, 0x00, 0x03, 0x08,
+ };
+ UCHAR rand_data[4];
+ char rand_str[MAX_SIZE];
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, sizeof(rand_data));
+ StrLower(rand_str);
+
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_response_header_1, sizeof(dns_response_header_1));
+ WriteBuf(b, rand_str, 8);
+ WriteBuf(b, dns_response_header_2, sizeof(dns_response_header_2));
+ us = Endian16((USHORT)(p->Size + 4));
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_response_header_3, sizeof(dns_response_header_3));
+ WriteBuf(b, p->Data, p->Size);
+
+ ui = Rand16() % (60 * 60 * 12) + (60 * 60 * 12);
+ WRITE_UINT(((UCHAR *)b->Buf) + 0x20, ui);
+ }
+ Free(p->Data);
+ p->Data = b->Buf;
+ p->Size = b->Size;
+ Free(b);
+ }
+
+ SendTo(r->UdpSock, &p->DstIP, p->DestPort, p->Data, p->Size);
+
+ r->TotalPhysicalSent += p->Size;
+
+ FreeUdpPacket(p);
+ }
+ DeleteAll(r->SendPacketList);
+
+ if (r->Halt)
+ {
+ // If it is necessary to stop, stop it after cycling through a loop
+ if (halt_flag == false)
+ {
+ halt_flag = true;
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // Rest the CPU until the next event
+ wait_interval = GetNextIntervalForInterrupt(r->Interrupt);
+ if (r->ServerMode)
+ {
+ min_wait_interval = RUDP_LOOP_WAIT_INTERVAL_S;
+ }
+ else
+ {
+ min_wait_interval = RUDP_LOOP_WAIT_INTERVAL_C;
+ }
+
+ if (wait_interval == INFINITE)
+ {
+ wait_interval = min_wait_interval;
+ }
+ else
+ {
+ wait_interval = MIN(min_wait_interval, wait_interval);
+ }
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("wait_interval = %u\n", wait_interval);
+#endif // RUDP_DETAIL_LOG
+
+ if (wait_interval >= 1)
+ {
+ WaitSockEvent(r->SockEvent, wait_interval);
+ }
+
+#ifdef RUDP_DETAIL_LOG
+ if (r->ServerMode)
+ {
+ char str1[MAX_SIZE];
+ char str2[MAX_SIZE];
+ double rate = 0.0;
+
+ ToStr64(str1, r->TotalPhysicalReceived);
+ ToStr64(str2, r->TotalLogicalReceived);
+
+ if (r->TotalPhysicalReceived >= 1)
+ {
+ rate = (double)r->TotalLogicalReceived / (double)r->TotalPhysicalReceived;
+ }
+
+ Debug("%s / %s %.4f\n", str1, str2, rate);
+ }
+#endif // RUDP_DETAIL_LOG
+ }
+
+ Disconnect(r->UdpSock);
+
+ DelWaitThread(thread);
+}
+
+// Generate a appropriate register host name from the IP address
+void RUDPGetRegisterHostNameByIP(char *dst, UINT size, IP *ip)
+{
+ char tmp[16];
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ if (ip != NULL && IsIP4(ip))
+ {
+ UCHAR hash[SHA1_SIZE];
+
+ HashSha1(hash, ip->addr, 4);
+ BinToStr(tmp, sizeof(tmp), hash, 2);
+ }
+ else
+ {
+ UCHAR rand[2];
+ Rand(rand, 2);
+ BinToStr(tmp, sizeof(tmp), rand, 2);
+ }
+
+ StrLower(tmp);
+ Format(dst, size,
+ (IsUseAlternativeHostname() ? UDP_NAT_T_SERVER_TAG_ALT : UDP_NAT_T_SERVER_TAG),
+ tmp[0], tmp[1], tmp[2], tmp[3]);
+
+
+ if (false)
+ {
+ Debug("Hash Src IP: %r\n"
+ "Hash Dst HN: %s\n",
+ ip,
+ dst);
+ }
+}
+
+// Analyze the IP address and port number from the string
+bool RUDPParseIPAndPortStr(void *data, UINT data_size, IP *ip, UINT *port)
+{
+ char tmp[MAX_SIZE];
+ UINT i;
+ char ipstr[MAX_SIZE];
+ char *portstr;
+ // Validate arguments
+ if (data == NULL || ip == NULL || port == NULL)
+ {
+ return false;
+ }
+
+ Zero(tmp, sizeof(tmp));
+
+ Copy(tmp, data, MIN(data_size, sizeof(tmp) - 1));
+
+ if (StartWith(tmp, "IP=") == false)
+ {
+ return false;
+ }
+
+ i = SearchStrEx(tmp, "#", 0, true);
+ if (i != INFINITE)
+ {
+ tmp[i] = 0;
+ }
+
+ StrCpy(ipstr, sizeof(ipstr), tmp + 3);
+
+ i = SearchStrEx(ipstr, ",PORT=", 0, true);
+ if (i == INFINITE)
+ {
+ return false;
+ }
+
+ ipstr[i] = 0;
+ portstr = ipstr + i + 6;
+
+ StrToIP(ip, ipstr);
+ *port = ToInt(portstr);
+
+ return true;
+}
+
+// R-UDP NAT-T IP address acquisition thread
+void RUDPIpQueryThread(THREAD *thread, void *param)
+{
+ RUDP_STACK *r;
+ UINT64 next_getip_tick = 0;
+ UINT64 next_getprivate_ip_tick = 0;
+ UINT last_ip_hash = 0;
+ void *route_change_poller = NULL;
+ char current_hostname[MAX_SIZE];
+ bool last_time_ip_changed = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ r = (RUDP_STACK *)param;
+
+ last_ip_hash = GetHostIPAddressHash32();
+
+ route_change_poller = NewRouteChange();
+ IsRouteChanged(route_change_poller);
+
+ Zero(current_hostname, sizeof(current_hostname));
+
+ while (r->Halt == false)
+ {
+ UINT ip_hash = GetHostIPAddressHash32();
+ UINT64 now = Tick64();
+ bool ip_changed = false;
+
+ if (ip_hash != last_ip_hash)
+ {
+ last_time_ip_changed = false;
+ }
+
+ if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)))
+ {
+ if (last_time_ip_changed == false)
+ {
+ // Call all getting functions from the beginning
+ // if the routing table or the IP address of this host has changed
+ next_getip_tick = 0;
+ next_getprivate_ip_tick = 0;
+ ip_changed = true;
+
+ last_ip_hash = ip_hash;
+
+ last_time_ip_changed = true;
+ }
+ }
+ else
+ {
+ last_time_ip_changed = false;
+ }
+
+ Lock(r->Lock);
+ {
+ if (StrCmpi(current_hostname, r->CurrentRegisterHostname) != 0)
+ {
+ // The target host name has changed
+ next_getip_tick = 0;
+ StrCpy(current_hostname, sizeof(current_hostname), r->CurrentRegisterHostname);
+ }
+ }
+ Unlock(r->Lock);
+
+ // Get the IP address of the NAT-T server with DNS
+ if (next_getip_tick == 0 || now >= next_getip_tick)
+ {
+ IP ip;
+
+ if (GetIP4(&ip, current_hostname) && IsZeroIp(&ip) == false)
+ {
+ Lock(r->Lock);
+ {
+// Debug("%r %r\n",&r->NatT_IP, &ip);
+ if (CmpIpAddr(&r->NatT_IP, &ip) != 0)
+ {
+// WHERE;
+ ip_changed = true;
+ Copy(&r->NatT_IP, &ip, sizeof(IP));
+ }
+ }
+ Unlock(r->Lock);
+ }
+
+ if (IsZeroIp(&r->NatT_IP))
+ {
+ next_getip_tick = now + (UINT64)UDP_NAT_T_GET_IP_INTERVAL;
+ }
+ else
+ {
+ next_getip_tick = now + (UINT64)UDP_NAT_T_GET_IP_INTERVAL_AFTER;
+ }
+
+ if (ip_changed)
+ {
+ Debug("NAT-T: NAT-T Server IP (%s): %r\n", current_hostname, &r->NatT_IP);
+
+ r->NatT_GetTokenNextTick = 0;
+ r->NatT_RegisterNextTick = 0;
+ r->NatT_GetTokenFailNum = 0;
+ r->NatT_RegisterFailNum = 0;
+
+ r->NatT_TranId = Rand64();
+
+ SetSockEvent(r->SockEvent);
+ }
+ }
+
+ // Get a private IP address of this host using TCP
+ if (next_getprivate_ip_tick == 0 || now >= next_getprivate_ip_tick)
+ {
+ IP ip;
+
+ if (GetMyPrivateIP(&ip))
+ {
+ Lock(r->Lock);
+ {
+ Copy(&r->My_Private_IP, &ip, sizeof(IP));
+ }
+ Unlock(r->Lock);
+ }
+
+ if (IsZeroIp(&r->My_Private_IP))
+ {
+ next_getprivate_ip_tick = now + (UINT64)UDP_NAT_T_GET_PRIVATE_IP_INTERVAL;
+ }
+ else
+ {
+ next_getprivate_ip_tick = now + (UINT64)GenRandInterval(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN, UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX);
+ }
+
+ Debug("NAT-T: My Private IP: %r\n", &r->My_Private_IP);
+ }
+
+ if (r->Halt)
+ {
+ break;
+ }
+
+ Wait(r->HaltEvent, RUDP_LOOP_WAIT_INTERVAL_S);
+ }
+
+ FreeRouteChange(route_change_poller);
+}
+
+// Generate a random intervals
+UINT GenRandInterval(UINT min, UINT max)
+{
+ UINT a, b;
+
+ a = MIN(min, max);
+ b = MAX(min, max);
+
+ if (a == b)
+ {
+ return a;
+ }
+
+ return (Rand32() % (b - a)) + a;
+}
+
+// Identify the private IP of the interface which is used to connect to the Internet currently
+bool GetMyPrivateIP(IP *ip)
+{
+ SOCK *s;
+ IP t;
+ char *hostname = UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsUseAlternativeHostname())
+ {
+ hostname = UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER_ALT;
+ }
+
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_1, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_2, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_3, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ return false;
+ }
+ }
+ }
+
+ Copy(&t, &s->LocalIP, sizeof(IP));
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ if (IsZeroIp(&t))
+ {
+ return false;
+ }
+
+ Copy(ip, &t, sizeof(IP));
+
+ return true;
+}
+
+// Function to wait until changing any IP address of the host or expiring the specified time or waking the event
+void WaitUntilHostIPAddressChanged(void *p, EVENT *event, UINT timeout, UINT ip_check_interval)
+{
+ UINT64 start, end;
+ UINT last_hash;
+ // Validate arguments
+ if (timeout == 0x7FFFFFFF)
+ {
+ timeout = 0xFFFFFFFF;
+ }
+ if (ip_check_interval == 0)
+ {
+ ip_check_interval = 0xFFFFFFFF;
+ }
+ if (event == NULL || timeout == 0)
+ {
+ return;
+ }
+
+ start = Tick64();
+ end = start + (UINT64)timeout;
+ last_hash = GetHostIPAddressHash32();
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT next_interval;
+
+ if (now >= end)
+ {
+ break;
+ }
+
+ if (p != NULL)
+ {
+ if (IsRouteChanged(p))
+ {
+ break;
+ }
+ }
+
+ if (last_hash != GetHostIPAddressHash32())
+ {
+ break;
+ }
+
+ next_interval = (UINT)(end - now);
+ next_interval = MIN(next_interval, ip_check_interval);
+
+ if (Wait(event, next_interval))
+ {
+ break;
+ }
+ }
+}
+void *InitWaitUntilHostIPAddressChanged()
+{
+ void *p = NewRouteChange();
+
+ if (p != NULL)
+ {
+ IsRouteChanged(p);
+ }
+
+ return p;
+}
+void FreeWaitUntilHostIPAddressChanged(void *p)
+{
+ FreeRouteChange(p);
+}
+
+// Get whether the specified IPv6 address is on the local network
+bool IsIPv6LocalNetworkAddress(IP *ip)
+{
+ UINT type;
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ IP mask64;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+ if (IsZeroIp(ip))
+ {
+ return false;
+ }
+
+ type = GetIPAddrType6(ip);
+
+ if (type & IPV6_ADDR_LOCAL_UNICAST)
+ {
+ return true;
+ }
+
+ if ((type & IPV6_ADDR_GLOBAL_UNICAST) == 0)
+ {
+ return false;
+ }
+
+ IntToSubnetMask6(&mask64, 64);
+
+ o = GetHostIPAddressList();
+
+ ret = false;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP6(p))
+ {
+ if (IsZeroIp(p) == false)
+ {
+ if (IsLocalHostIP6(p) == false)
+ {
+ if (IsInSameNetwork6(p, ip, &mask64))
+ {
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ return ret;
+}
+
+// Check whether the specified IP address is localhost or the IP address of the local interface of itself
+bool IsIPLocalHostOrMySelf(IP *ip)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ o = GetHostIPAddressList();
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (CmpIpAddr(p, ip) == 0)
+ {
+ ret = true;
+
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ if (IsLocalHostIP4(ip) || IsLocalHostIP6(ip))
+ {
+ ret = true;
+ }
+
+ return ret;
+}
+
+// Get the results of the port number that is determined at random
+UINT RUDPGetRandPortNumber(UCHAR rand_port_id)
+{
+ UINT ret;
+ // Validate arguments
+ if (rand_port_id == 0)
+ {
+ return 0;
+ }
+
+ ret = rand_port_numbers[rand_port_id];
+
+ Debug("rand_port_id[%u] = %u\n", rand_port_id, ret);
+ return ret;
+}
+
+// Obtain the hash value of combining all of the IP address assigned to the host
+UINT GetHostIPAddressHash32()
+{
+ BUF *b;
+ UINT i;
+ UCHAR hash[SHA1_SIZE];
+ UINT ret;
+ LIST *o = GetHostIPAddressList();
+
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ b = NewBuf();
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ WriteBuf(b, ip, sizeof(IP));
+
+ WriteBufStr(b, ":-) yas (-:");
+ }
+ FreeHostIPAddressList(o);
+
+ WriteBuf(b, rand_port_numbers, sizeof(rand_port_numbers));
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Copy(&ret, hash, sizeof(UINT));
+
+ return ret;
+}
+
+// Create an IPv4 UDP socket destined for a particular target
+SOCK *NewUDP4ForSpecificIp(IP *target_ip, UINT port)
+{
+ SOCK *s;
+ IP local_ip;
+ // Validate arguments
+ if (target_ip == NULL || IsZeroIP(target_ip) || IsIP4(target_ip) == false)
+ {
+ target_ip = NULL;
+ }
+
+ Zero(&local_ip, sizeof(local_ip));
+ GetBestLocalIpForTarget(&local_ip, target_ip);
+
+ s = NewUDP4(port, &local_ip);
+
+ if (s == NULL)
+ {
+ s = NewUDP4(port, NULL);
+ }
+
+ return s;
+}
+
+// Get the best self IPv4 address to connect to the target IPv4 address
+bool GetBestLocalIpForTarget(IP *local_ip, IP *target_ip)
+{
+ bool ret = false;
+ ROUTE_ENTRY *e;
+ IP ip2;
+ UINT n = 0;
+ IP zero_ip;
+ // Validate arguments
+ Zero(local_ip, sizeof(IP));
+ ZeroIP4(&zero_ip);
+ if (target_ip == NULL)
+ {
+ target_ip = &zero_ip;
+ }
+ if (local_ip == NULL || IsIP4(target_ip) == false)
+ {
+ return false;
+ }
+
+ Copy(&ip2, target_ip, sizeof(IP));
+
+ while (true)
+ {
+ n++;
+ if (n >= 64)
+ {
+ break;
+ }
+
+ e = GetBestRouteEntry(&ip2);
+ if (e != NULL)
+ {
+ if (IsZeroIp(&e->GatewayIP))
+ {
+ Free(e);
+ break;
+ }
+
+ if (e->LocalRouting)
+ {
+ ret = true;
+ Copy(local_ip, &e->GatewayIP, sizeof(IP));
+ Free(e);
+ break;
+ }
+ else
+ {
+ Copy(&ip2, &e->GatewayIP, sizeof(IP));
+ }
+
+ Free(e);
+ }
+ }
+
+ if (ret == false)
+ {
+ if (IsLocalHostIP4(target_ip))
+ {
+ GetLocalHostIP4(local_ip);
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Create a R-UDP client (Connection via NAT-T gateway)
+SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname)
+{
+ IP nat_t_ip;
+ UINT dummy_int = 0;
+ UINT64 giveup_tick;
+ bool dummy_bool = false;
+ SOCK_EVENT *sock_event;
+ SOCK *sock;
+ bool same_lan = false;
+ char hostname[MAX_SIZE];
+ if (timeout == 0)
+ {
+ timeout = RUDP_TIMEOUT;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &dummy_int;
+ }
+ if (cancel == NULL)
+ {
+ cancel = &dummy_bool;
+ }
+ *error_code = RUDP_ERROR_UNKNOWN;
+ if (svc_name == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ giveup_tick = Tick64() + (UINT64)timeout;
+
+ // Get the IP address of the NAT-T server
+ RUDPGetRegisterHostNameByIP(hostname, sizeof(hostname), ip);
+ if (GetIP4Ex(&nat_t_ip, hostname, 0, cancel) == false)
+ {
+ *error_code = RUDP_ERROR_NAT_T_NO_RESPONSE;
+ return NULL;
+ }
+
+ if (Tick64() >= giveup_tick)
+ {
+ *error_code = RUDP_ERROR_TIMEOUT;
+ return NULL;
+ }
+ if (*cancel)
+ {
+ *error_code = RUDP_ERROR_USER_CANCELED;
+ return NULL;
+ }
+
+ sock = NewUDP4ForSpecificIp(&nat_t_ip, 0);
+ if (sock == NULL)
+ {
+ *error_code = RUDP_ERROR_UNKNOWN;
+ return NULL;
+ }
+ else
+ {
+ UINT64 next_send_request_tick = 0;
+ INTERRUPT_MANAGER *interrupt = NewInterruptManager();
+ UINT64 tran_id = Rand64();
+ UINT tmp_size = 65536;
+ UCHAR *tmp = Malloc(tmp_size);
+ char result_ip_str[MAX_SIZE];
+ IP result_ip;
+ UINT result_port;
+ SOCK *ret = NULL;
+ UINT num_tries = 0;
+
+ AddInterrupt(interrupt, giveup_tick);
+
+ sock_event = NewSockEvent();
+ JoinSockToSockEvent(sock, sock_event);
+
+ // Communication with the NAT-T server
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval;
+ UINT r;
+ IP src_ip;
+ UINT src_port;
+ UINT err;
+ UINT num_ignore_errors = 0;
+
+ if (now >= giveup_tick)
+ {
+ // Time-out
+LABEL_TIMEOUT:
+ *error_code = RUDP_ERROR_NAT_T_NO_RESPONSE;
+ break;
+ }
+
+ if (*cancel)
+ {
+ // User canceled
+ *error_code = RUDP_ERROR_USER_CANCELED;
+ break;
+ }
+
+ err = INFINITE;
+
+ // Receive a response packet from the NAT-T server
+ while (err == INFINITE)
+ {
+ r = RecvFrom(sock, &src_ip, &src_port, tmp, tmp_size);
+ if (r == SOCK_LATER)
+ {
+ // No packet
+ break;
+ }
+ else if (r == 0)
+ {
+ if (sock->IgnoreRecvErr == false)
+ {
+ // Communication error
+ goto LABEL_TIMEOUT;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto LABEL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ // Check the source IP address and the port number
+ if (CmpIpAddr(&src_ip, &nat_t_ip) == 0 && src_port == UDP_NAT_T_PORT)
+ {
+ BUF *b = NewBuf();
+ PACK *p;
+
+ WriteBuf(b, tmp, r);
+ SeekBuf(b, 0, 0);
+
+ p = BufToPack(b);
+
+ if (p != NULL)
+ {
+ // Compare tran_id
+ if (PackGetInt64(p, "tran_id") == tran_id)
+ {
+ // Compare opcode
+ if (PackCmpStr(p, "opcode", "nat_t_connect_request"))
+ {
+ bool ok = PackGetBool(p, "ok");
+ bool multi_candidate = PackGetBool(p, "multi_candidates");
+
+ if (ok)
+ {
+ // Success
+ PackGetStr(p, "result_ip", result_ip_str, sizeof(result_ip_str));
+ StrToIP(&result_ip, result_ip_str);
+
+ result_port = PackGetInt(p, "result_port");
+
+ same_lan = PackGetBool(p, "same_lan");
+
+ if (result_port != 0)
+ {
+ if (IsZeroIp(&result_ip) == false)
+ {
+ if ((sock->IPv6 == false && IsIP4(&result_ip)) ||
+ (sock->IPv6 && IsIP6(&result_ip)))
+ {
+ err = RUDP_ERROR_OK;
+ }
+ }
+ }
+ }
+ else if (multi_candidate)
+ {
+ // There are two or more computers behind the specified IP address
+ err = RUDP_ERROR_NAT_T_TWO_OR_MORE;
+ }
+ else
+ {
+ // Failure
+ err = RUDP_ERROR_NAT_T_NOT_FOUND;
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(b);
+ }
+ }
+ }
+
+ if (err != INFINITE)
+ {
+ *error_code = err;
+ break;
+ }
+
+ if (next_send_request_tick == 0 || now >= next_send_request_tick)
+ {
+ // Send a connection request to the NAT-T server
+ BUF *b;
+ char ip_str[MAX_SIZE];
+ PACK *p = NewPack();
+
+ PackAddStr(p, "opcode", "nat_t_connect_request");
+ PackAddInt64(p, "tran_id", tran_id);
+ IPToStr(ip_str, sizeof(ip_str), ip);
+ PackAddStr(p, "dest_ip", ip_str);
+ if (IsEmptyStr(hint_str) == false)
+ {
+ PackAddStr(p, "hint", hint_str);
+ }
+ if (IsEmptyStr(target_hostname) == false)
+ {
+ PackAddStr(p, "target_hostname", target_hostname);
+ }
+ PackAddStr(p, "svc_name", svc_name);
+
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+ b = PackToBuf(p);
+ FreePack(p);
+ SendTo(sock, &nat_t_ip, UDP_NAT_T_PORT, b->Buf, b->Size);
+ FreeBuf(b);
+
+ // Determine the next transmission time
+ next_send_request_tick = now + (UINT64)UDP_NAT_T_CONNECT_INTERVAL * (UINT64)(Power(2, MAX(num_tries, 6)));
+ num_tries++;
+ AddInterrupt(interrupt, next_send_request_tick);
+ }
+
+ interval = GetNextIntervalForInterrupt(interrupt);
+ interval = MIN(interval, 50);
+
+ WaitSockEvent(sock_event, interval);
+ }
+
+ Free(tmp);
+ FreeInterruptManager(interrupt);
+
+ if (*error_code == RUDP_ERROR_OK)
+ {
+ UINT remain_timeout;
+ UINT64 now = Tick64();
+ // Success to get the IP address and the port number of the target
+
+ // Get the rest timeout tolerance
+ if (now <= giveup_tick)
+ {
+ remain_timeout = (UINT)(giveup_tick - now);
+ }
+ else
+ {
+ remain_timeout = 0;
+ }
+
+ remain_timeout = MAX(remain_timeout, 2000);
+
+ if (same_lan)
+ {
+ // Discard current UDP socket and create a new UDP socket in NewRUDPClientDirect().
+ // Because using a UDP socket which used for communication with the NAT-T server
+ // can cause trouble when the client and the server exists in the same LAN.
+ ReleaseSockEvent(sock_event);
+ ReleaseSock(sock);
+
+ sock = NULL;
+ sock_event = NULL;
+ }
+
+ ret = NewRUDPClientDirect(svc_name, &result_ip, result_port, error_code, remain_timeout, cancel,
+ sock, sock_event, 0, false);
+ }
+
+ if (sock_event != NULL)
+ {
+ ReleaseSockEvent(sock_event);
+ }
+
+ if (sock != NULL)
+ {
+ ReleaseSock(sock);
+ }
+
+ return ret;
+ }
+}
+
+// Listen to the TCP for a moment to show the firewall dialog
+void ListenTcpForPopupFirewallDialog()
+{
+#ifdef OS_WIN32
+ static bool tried = false;
+
+ if (tried == false)
+ {
+ SOCK *s;
+ tried = true;
+ s = ListenAnyPortEx2(false, true);
+
+ if (s != NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+ }
+#endif // OS_WIN32
+}
+
+// Create a R-UDP client (direct connection)
+SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode)
+{
+ RUDP_STACK *r;
+ UINT dummy_int = 0;
+ SOCK *ret = NULL;
+ // Validate arguments
+ if (error_code == NULL)
+ {
+ error_code = &dummy_int;
+ }
+ if (timeout == 0)
+ {
+ timeout = RUDP_TIMEOUT;
+ }
+ *error_code = RUDP_ERROR_UNKNOWN;
+ if (svc_name == NULL || ip == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ r = NewRUDP(false, svc_name, NULL, NULL, NULL, local_port, sock, sock_event, false, over_dns_mode, ip, NULL, 0);
+ if (r == NULL)
+ {
+ *error_code = RUDP_ERROR_UNKNOWN;
+ return NULL;
+ }
+
+ // Set the port number and the target IP address
+ Lock(r->Lock);
+ {
+ Copy(&r->TargetIp, ip, sizeof(IP));
+ r->TargetPort = port;
+ r->TargetIpAndPortInited = true;
+ }
+ Unlock(r->Lock);
+ SetSockEvent(r->SockEvent);
+
+ // Wait for a connection success/failure to the target IP address
+ WaitEx(r->TargetConnectedEvent, timeout, cancel);
+ Lock(r->Lock);
+ {
+ if (r->TargetConnectedSock != NULL)
+ {
+ // The connection succeeded
+ ret = r->TargetConnectedSock;
+ r->TargetConnectedSock = NULL;
+ }
+ else
+ {
+ r->DoNotSetTargetConnectedSock = true;
+ }
+ }
+ Unlock(r->Lock);
+
+ if (ret == NULL)
+ {
+ // Stop the R-UDP stack if the connection has failed
+ *error_code = RUDP_ERROR_TIMEOUT;
+ FreeRUDP(r);
+ }
+ else if (cancel != NULL && (*cancel))
+ {
+ // User canceled
+ *error_code = RUDP_ERROR_USER_CANCELED;
+
+ Disconnect(ret);
+ ReleaseSock(ret);
+
+ ret = NULL;
+ }
+ else
+ {
+ *error_code = RUDP_ERROR_OK;
+ }
+
+ return ret;
+}
+
+// Creating a R-UDP server
+RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ RUDP_STACK *r;
+ // Validate arguments
+ if (IsEmptyStr(svc_name))
+ {
+ return NULL;
+ }
+
+ if (g_no_rudp_server)
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ r = NewRUDP(true, svc_name, proc_interrupts, proc_rpc_recv, param, port, NULL, NULL, no_natt_register, over_dns_mode, NULL, natt_global_udp_port, rand_port_id);
+
+ if (r == NULL)
+ {
+ return NULL;
+ }
+
+ return r;
+}
+
+// Creating a R-UDP
+RUDP_STACK *NewRUDP(bool server_mode, char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, SOCK *sock, SOCK_EVENT *sock_event, bool server_no_natt_register, bool over_dns_mode, IP *client_target_ip, volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ RUDP_STACK *r;
+ char tmp[MAX_SIZE];
+ UCHAR pid_hash[SHA1_SIZE];
+ UINT pid;
+ USHORT pid_us;
+
+ // Validate arguments
+ if (IsEmptyStr(svc_name))
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ if (sock == NULL)
+ {
+ if (server_mode == false && client_target_ip != NULL)
+ {
+ sock = NewUDP4ForSpecificIp(client_target_ip, port);
+ }
+ else
+ {
+ if (rand_port_id == 0)
+ {
+ sock = NewUDP(port);
+ }
+ else
+ {
+ sock = NewUDPEx2RandMachineAndExePath(false, NULL, 0, rand_port_id);
+ }
+ }
+
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ AddRef(sock->ref);
+ }
+
+ if (port == 0)
+ {
+ port = sock->LocalPort;
+ }
+
+ if (rand_port_id != 0)
+ {
+ rand_port_numbers[rand_port_id] = port;
+ }
+
+ if (sock_event == NULL)
+ {
+ sock_event = NewSockEvent();
+ }
+ else
+ {
+ AddRef(sock_event->ref);
+ }
+
+ r = ZeroMalloc(sizeof(RUDP_STACK));
+
+ StrCpy(r->SvcName, sizeof(r->SvcName), svc_name);
+ r->RandPortId = rand_port_id;
+ r->NatTGlobalUdpPort = natt_global_udp_port;
+ r->ServerMode = server_mode;
+ r->Interrupt = NewInterruptManager();
+ r->SessionList = NewList(RUDPCompareSessionList);
+ r->UdpSock = sock;
+ r->Port = port;
+ r->SockEvent = sock_event;
+ r->HaltEvent = NewEvent();
+ r->Now = Tick64();
+ r->Lock = NewLock();
+ r->Param = param;
+ r->TargetConnectedEvent = NewEvent();
+ r->SendPacketList = NewList(NULL);
+ r->NewSockConnectEvent = NewEvent();
+ r->NewSockQueue = NewQueue();
+ r->NatT_TranId = Rand64();
+
+ StrCpy(tmp, sizeof(tmp), r->SvcName);
+ Trim(tmp);
+ StrLower(tmp);
+
+ HashSha1(r->SvcNameHash, tmp, StrLen(tmp));
+
+ r->Client_IcmpId = (USHORT)(Rand32() % 65534 + 1);
+ r->Client_IcmpSeqNo = (USHORT)(Rand32() % 65534 + 1);
+
+ // Determination of the type of the protocol
+ r->Protocol = RUDP_PROTOCOL_UDP;
+ if (r->Port == MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4))
+ {
+ r->Protocol = RUDP_PROTOCOL_ICMP;
+
+ // Generate the ICMP ID based on the process ID
+#ifdef OS_WIN32
+ pid = (UINT)MsGetProcessId();
+#else // OS_WIN32
+ pid = (UINT)getpid();
+#endif // OS_WIN32
+
+ pid = Endian32(pid);
+ HashSha1(pid_hash, &pid, sizeof(UINT));
+
+ pid_us = READ_USHORT(pid_hash);
+ if (pid_us == 0 || pid_us == 0xFFFF)
+ {
+ pid_us = 1;
+ }
+
+ r->Client_IcmpId = pid_us;
+ }
+ else if (over_dns_mode)
+ {
+ r->Protocol = RUDP_PROTOCOL_DNS;
+ }
+
+ if (r->ServerMode)
+ {
+ r->NoNatTRegister = server_no_natt_register;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP || r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Never register to the NAT-T server in case of using the DNS or the ICMP
+ r->NoNatTRegister = true;
+ }
+ }
+
+ RUDPGetRegisterHostNameByIP(r->CurrentRegisterHostname, sizeof(r->CurrentRegisterHostname), NULL);
+
+ if (r->ServerMode)
+ {
+ r->ProcInterrupts = proc_interrupts;
+ r->ProcRpcRecv = proc_rpc_recv;
+ }
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ r->IpQueryThread = NewThread(RUDPIpQueryThread, r);
+ }
+
+ JoinSockToSockEvent(r->UdpSock, r->SockEvent);
+
+ r->Thread = NewThread(RUDPMainThread, r);
+ WaitThreadInit(r->Thread);
+
+ return r;
+}
+
+// R-UDP session comparison function
+int RUDPCompareSessionList(void *p1, void *p2)
+{
+ RUDP_SESSION *s1, *s2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *((RUDP_SESSION **)p1);
+ s2 = *((RUDP_SESSION **)p2);
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ r = CmpIpAddr(&s1->YourIp, &s2->YourIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(s1->YourPort, s2->YourPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = CmpIpAddr(&s1->MyIp, &s2->MyIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(s1->MyPort, s2->MyPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ return 0;
+}
+
+// Release of the R-UDP
+void FreeRUDP(RUDP_STACK *r)
+{
+ UINT i;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ r->Halt = true;
+ Set(r->HaltEvent);
+ SetSockEvent(r->SockEvent);
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ WaitThread(r->IpQueryThread, INFINITE);
+ ReleaseThread(r->IpQueryThread);
+ }
+
+ WaitThread(r->Thread, INFINITE);
+ ReleaseThread(r->Thread);
+
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ RUDPFreeSession(se);
+ }
+
+ ReleaseList(r->SessionList);
+
+ for (i = 0;i < LIST_NUM(r->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(r->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ while (true)
+ {
+ SOCK *s = GetNext(r->NewSockQueue);
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ ReleaseQueue(r->NewSockQueue);
+
+ ReleaseList(r->SendPacketList);
+
+ FreeInterruptManager(r->Interrupt);
+
+ Disconnect(r->UdpSock);
+ ReleaseSock(r->UdpSock);
+ ReleaseSockEvent(r->SockEvent);
+ ReleaseEvent(r->HaltEvent);
+ ReleaseEvent(r->TargetConnectedEvent);
+
+ ReleaseEvent(r->NewSockConnectEvent);
+
+ Disconnect(r->TargetConnectedSock);
+ ReleaseSock(r->TargetConnectedSock);
+
+ DeleteLock(r->Lock);
+
+ if (r->RandPortId != 0)
+ {
+ rand_port_numbers[r->RandPortId] = 0;
+ }
+
+ Free(r);
+}
+
+// Generate a hash from the current computer name and the process name
+void GetCurrentMachineIpProcessHash(void *hash)
+{
+ // Validate arguments
+ if (hash == NULL)
+ {
+ return;
+ }
+
+ Lock(machine_ip_process_hash_lock);
+ {
+ if (IsZero(machine_ip_process_hash, SHA1_SIZE))
+ {
+ GetCurrentMachineIpProcessHashInternal(machine_ip_process_hash);
+ }
+
+ Copy(hash, machine_ip_process_hash, SHA1_SIZE);
+ }
+ Unlock(machine_ip_process_hash_lock);
+}
+void GetCurrentMachineIpProcessHashInternal(void *hash)
+{
+ BUF *b;
+ LIST *ip_list;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ // Validate arguments
+ if (hash == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+
+ ip_list = GetHostIPAddressList();
+ if (ip_list != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ WriteBuf(b, ip, sizeof(IP));
+ }
+ }
+ FreeHostIPAddressList(ip_list);
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+}
+
+// Create a pair of pre-bound TCP sockets
+bool NewTcpPair(SOCK **s1, SOCK **s2)
+{
+ SOCK *a;
+ SOCK *s, *c;
+ TUBE *t1, *t2;
+ SOCK_EVENT *e1, *e2;
+ // Validate arguments
+ if (s1 == NULL || s2 == NULL)
+ {
+ return false;
+ }
+
+ a = ListenAnyPortEx2(true, true);
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ c = Connect("127.0.0.1", a->LocalPort);
+ if (c == NULL)
+ {
+ ReleaseSock(a);
+ return false;
+ }
+
+ s = Accept(a);
+ if (s == NULL)
+ {
+ ReleaseSock(c);
+ ReleaseSock(a);
+ return false;
+ }
+
+ ReleaseSock(a);
+
+ if ((s->LocalPort != c->RemotePort) || (s->RemotePort != c->LocalPort))
+ {
+ ReleaseSock(s);
+ ReleaseSock(c);
+ return false;
+ }
+
+ NewTubePair(&t1, &t2, sizeof(TCP_PAIR_HEADER));
+
+ // Creating a socket event
+ e1 = NewSockEvent();
+ e2 = NewSockEvent();
+
+ SetTubeSockEvent(t1, e1);
+ SetTubeSockEvent(t2, e2);
+
+ AddRef(t1->Ref);
+ AddRef(t2->Ref);
+ s->BulkRecvTube = c->BulkSendTube = t1;
+ s->BulkSendTube = c->BulkRecvTube = t2;
+
+ ReleaseSockEvent(e1);
+ ReleaseSockEvent(e2);
+
+ *s1 = s;
+ *s2 = c;
+
+ return true;
+}
+
+// Listen in any available port
+SOCK *ListenAnyPortEx(bool local_only)
+{
+ return ListenAnyPortEx2(local_only, false);
+}
+SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca)
+{
+ UINT i;
+ SOCK *s;
+ for (i = 40000;i < 65536;i++)
+ {
+ s = ListenEx(i, local_only);
+ if (s != NULL)
+ {
+ return s;
+ }
+ }
+
+ return NULL;
+}
+
+int cb_test(int a, X509_STORE_CTX *ctx)
+{
+ WHERE;
+ return 1;
+}
+
+// Create a new SSL pipe
+SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
+{
+ SSL_PIPE *s;
+ SSL *ssl;
+ SSL_CTX *ssl_ctx = NewSSLCtx();
+
+ Lock(openssl_lock);
+ {
+ if (server_mode)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_server_method());
+
+ AddChainSslCertOnDirectory(ssl_ctx);
+
+ if (dh != NULL)
+ {
+ SSL_CTX_set_tmp_dh(ssl_ctx, dh->dh);
+ }
+ }
+ else
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());
+ }
+
+ //SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, cb_test);
+
+ if (dh != NULL)
+ {
+ SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE);
+ }
+
+ ssl = SSL_new(ssl_ctx);
+ }
+ Unlock(openssl_lock);
+
+ s = ZeroMalloc(sizeof(SSL_PIPE));
+
+ s->ssl = ssl;
+ s->ssl_ctx = ssl_ctx;
+ s->ServerMode = server_mode;
+
+ s->SslInOut = NewSslBioSsl();
+ s->RawIn = NewSslBioMem();
+ s->RawOut = NewSslBioMem();
+
+ if (x != NULL && k != NULL)
+ {
+ Lock(openssl_lock);
+ {
+ SSL_use_certificate(s->ssl, x->x509);
+ SSL_use_PrivateKey(s->ssl, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+
+ if (s->ServerMode == false)
+ {
+ SSL_set_connect_state(s->ssl);
+ }
+ else
+ {
+ SSL_set_accept_state(s->ssl);
+ }
+
+ SSL_set_bio(s->ssl, s->RawIn->bio, s->RawOut->bio);
+ BIO_set_ssl(s->SslInOut->bio, s->ssl, BIO_NOCLOSE);
+
+ //s->RawIn->NoFree = true;
+ s->RawOut->NoFree = true;
+
+ return s;
+}
+
+// Synchronization of the SSL pipe
+bool SyncSslPipe(SSL_PIPE *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || s->IsDisconnected)
+ {
+ return false;
+ }
+
+ for (i = 0;i < 2;i++)
+ {
+ if (SslBioSync(s->RawIn, true, false) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->RawIn error.\n");
+ return false;
+ }
+
+ if (SslBioSync(s->RawOut, false, true) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->RawOut error.\n");
+ return false;
+ }
+
+ if (SslBioSync(s->SslInOut, true, true) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->SslInOut error.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Release of the SSL pipe
+void FreeSslPipe(SSL_PIPE *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ FreeSslBio(s->SslInOut);
+ FreeSslBio(s->RawIn);
+ FreeSslBio(s->RawOut);
+
+ SSL_free(s->ssl);
+ SSL_CTX_free(s->ssl_ctx);
+
+ Free(s);
+}
+
+// Release of the SSL BIO
+void FreeSslBio(SSL_BIO *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->NoFree == false)
+ {
+ BIO_free(b->bio);
+ }
+
+ ReleaseFifo(b->RecvFifo);
+ ReleaseFifo(b->SendFifo);
+
+ Free(b);
+}
+
+// Create a new SSL BIO (SSL)
+SSL_BIO *NewSslBioSsl()
+{
+ SSL_BIO *b = ZeroMalloc(sizeof(SSL_BIO));
+
+ b->bio = BIO_new(BIO_f_ssl());
+
+ b->RecvFifo = NewFifo();
+ b->SendFifo = NewFifo();
+
+ return b;
+}
+
+// Create a new SSL BIO (memory)
+SSL_BIO *NewSslBioMem()
+{
+ SSL_BIO *b = ZeroMalloc(sizeof(SSL_BIO));
+
+ b->bio = BIO_new(BIO_s_mem());
+
+ b->RecvFifo = NewFifo();
+ b->SendFifo = NewFifo();
+
+ return b;
+}
+
+// Synchronize memory contents of the SSL BIO with the FIFO
+bool SslBioSync(SSL_BIO *b, bool sync_send, bool sync_recv)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->IsDisconnected)
+ {
+ return false;
+ }
+
+ // Write the contents of the SendFifo to the BIO
+ if (sync_send)
+ {
+ while (b->SendFifo->size >= 1)
+ {
+ int r = BIO_write(b->bio, GetFifoPointer(b->SendFifo), FifoSize(b->SendFifo));
+
+ if (r == 0)
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ else
+ {
+ if (r < 0)
+ {
+ if (BIO_should_retry(b->bio))
+ {
+ break;
+ }
+ else
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ }
+ else
+ {
+ ReadFifo(b->SendFifo, NULL, (UINT)r);
+ }
+ }
+ }
+ }
+
+ // Save to the RecvFifo by reading from the BIO
+ if (sync_recv)
+ {
+ while (true)
+ {
+ UCHAR tmp[4096];
+ int r;
+
+ r = BIO_read(b->bio, tmp, sizeof(tmp));
+
+ if (r == 0)
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ else
+ {
+ if (r < 0)
+ {
+ if (BIO_should_retry(b->bio))
+ {
+ break;
+ }
+ else
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ Debug("OpenSSL Error: %s\n", ERR_error_string(ERR_peek_last_error(), NULL));
+ return false;
+ }
+ }
+ else
+ {
+ WriteFifo(b->RecvFifo, tmp, (UINT)r);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Release the memory for the return value of the ICMP API
+void IcmpApiFreeResult(ICMP_RESULT *ret)
+{
+ // Validate arguments
+ if (ret == NULL)
+ {
+ return;
+ }
+
+ if (ret->Data != NULL)
+ {
+ Free(ret->Data);
+ }
+
+ Free(ret);
+}
+
+// Send an ICMP Echo using ICMP API
+ICMP_RESULT *IcmpApiEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+#ifdef OS_WIN32
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ if (IsIcmpApiSupported())
+ {
+ HANDLE h;
+ DWORD dw;
+ IPAddr dest_addr;
+ UINT reply_size;
+ ICMP_ECHO_REPLY *reply;
+ ICMP_RESULT *ret = NULL;
+ IP_OPTION_INFORMATION opt;
+
+ h = w32net->IcmpCreateFile();
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ Zero(&opt, sizeof(opt));
+ opt.Ttl = ttl;
+
+ IPToInAddr((struct in_addr *)&dest_addr, dest_ip);
+
+ reply_size = sizeof(*reply) + size + 64;
+ reply = ZeroMalloc(reply_size);
+
+ dw = w32net->IcmpSendEcho(h, dest_addr, data, size, &opt, reply, reply_size, timeout);
+
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ if (dw >= 1 && reply->Status == IP_SUCCESS)
+ {
+ ret->Ok = true;
+ }
+ else
+ {
+ switch (reply->Status)
+ {
+ case IP_DEST_NET_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_NET_UNREACHABLE;
+ break;
+
+ case IP_DEST_HOST_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_HOST_UNREACHABLE;
+ break;
+
+ case IP_DEST_PROT_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_PROTOCOL_UNREACHABLE;
+ break;
+
+ case IP_DEST_PORT_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_PORT_UNREACHABLE;
+ break;
+
+ case IP_TTL_EXPIRED_TRANSIT:
+ ret->Type = ICMP_TYPE_TIME_EXCEEDED;
+ ret->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
+ break;
+
+ case IP_TTL_EXPIRED_REASSEM:
+ ret->Type = ICMP_TYPE_TIME_EXCEEDED;
+ ret->Code = ICMP_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEDED;
+ break;
+
+ default:
+ ret->Timeout = true;
+ break;
+ }
+ }
+
+ if (ret->Timeout == false)
+ {
+ ret->Ttl = reply->Options.Ttl;
+ ret->Rtt = reply->RoundTripTime;
+ InAddrToIP(&ret->IpAddress, (struct in_addr *)&reply->Address);
+
+ if (reply->DataSize >= 1 && reply->Data != NULL)
+ {
+ ret->DataSize = reply->DataSize;
+ ret->Data = Clone(reply->Data, reply->DataSize);
+ }
+ }
+
+ Free(reply);
+
+ w32net->IcmpCloseHandle(h);
+
+ return ret;
+ }
+ else
+ {
+ return NULL;
+ }
+
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Detect whether the ICMP API is supported
+bool IsIcmpApiSupported()
+{
+#ifdef OS_WIN32
+ if (w32net->IcmpCloseHandle != NULL &&
+ w32net->IcmpCreateFile != NULL &&
+ w32net->IcmpSendEcho != NULL)
+ {
+ return true;
+ }
+#endif // OS_WIN32
+
+ return false;
+}
+
+// Initialize the routing table change detector
+ROUTE_CHANGE *NewRouteChange()
+{
+#ifdef OS_WIN32
+ return Win32NewRouteChange();
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Release the routing table change detector
+void FreeRouteChange(ROUTE_CHANGE *r)
+{
+#ifdef OS_WIN32
+ Win32FreeRouteChange(r);
+#endif // OS_WIN32
+}
+
+// Get whether the routing table has been changed
+bool IsRouteChanged(ROUTE_CHANGE *r)
+{
+#ifdef OS_WIN32
+ return Win32IsRouteChanged(r);
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// Routing table change detector function (Win32)
+#ifdef OS_WIN32
+ROUTE_CHANGE *Win32NewRouteChange()
+{
+ ROUTE_CHANGE *r;
+ bool ret;
+
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+
+ if (w32net->CancelIPChangeNotify == NULL ||
+ w32net->NotifyRouteChange == NULL)
+ {
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(ROUTE_CHANGE));
+
+ r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA));
+
+ r->Data->Overlapped.hEvent = CreateEventA(NULL, false, true, NULL);
+
+ ret = w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
+ if (!(ret == NO_ERROR || ret == WSA_IO_PENDING || WSAGetLastError() == WSA_IO_PENDING))
+ {
+ Free(r->Data);
+ Free(r);
+
+ return NULL;
+ }
+
+ return r;
+}
+
+void Win32FreeRouteChange(ROUTE_CHANGE *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ w32net->CancelIPChangeNotify(&r->Data->Overlapped);
+ CloseHandle(r->Data->Overlapped.hEvent);
+
+ Free(r->Data);
+ Free(r);
+}
+
+bool Win32IsRouteChanged(ROUTE_CHANGE *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return false;
+ }
+
+ if ((r->Data->NumCalled++) == 0)
+ {
+ return true;
+ }
+
+ if (WaitForSingleObject(r->Data->Overlapped.hEvent, 0) == WAIT_OBJECT_0)
+ {
+ w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
+ return true;
+ }
+
+ return false;
+}
+
+typedef struct WIN32_ACCEPT_CHECK_DATA
+{
+ bool IsIPv6;
+ bool Rejected;
+} WIN32_ACCEPT_CHECK_DATA;
+
+// Function for determining whether accept or not in Win32
+int CALLBACK Win32AcceptCheckCallback_Delay(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
+ LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
+ GROUP FAR * g, DWORD_PTR dwCallbackData)
+{
+ return CF_DEFER;
+}
+
+int CALLBACK Win32AcceptCheckCallback(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
+ LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
+ GROUP FAR * g, DWORD_PTR dwCallbackData)
+{
+ return CF_ACCEPT;
+}
+
+// Accept function for Win32
+SOCKET Win32Accept_XP(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6)
+{
+ SOCKET ret;
+ WIN32_ACCEPT_CHECK_DATA d;
+ UINT err;
+ int initial_addrlen = *addrlen;
+ UINT num_error = 0;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return INVALID_SOCKET;
+ }
+
+L_LOOP:
+
+ Zero(&d, sizeof(d));
+
+ d.IsIPv6 = ipv6;
+
+ *addrlen = initial_addrlen;
+ Zero(addr, initial_addrlen);
+ ret = WSAAccept(s, addr, addrlen, Win32AcceptCheckCallback, (DWORD_PTR)&d);
+
+ if (ret == INVALID_SOCKET)
+ {
+ err = WSAGetLastError();
+
+ num_error++;
+
+ Debug("!!! WSAAccept Error: %u rej=%u num=%u tick=%I64u\n", WSAGetLastError(), d.Rejected, num_error, Tick64());
+
+ if (d.Rejected && err == WSAECONNREFUSED)
+ {
+ goto L_LOOP;
+ }
+
+ if (err == WSAETIMEDOUT)
+ {
+ goto L_LOOP;
+ }
+ }
+
+ return ret;
+}
+
+// Accept function for Win32
+SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6)
+{
+ SOCKET ret;
+ WIN32_ACCEPT_CHECK_DATA d;
+ UINT err;
+ int initial_addrlen = *addrlen;
+ UINT num_error = 0;
+ UINT zero = 0;
+ UINT tmp = 0;
+ UINT ret_size = 0;
+ // Validate arguments
+ if (sock == NULL || s == INVALID_SOCKET)
+ {
+ return INVALID_SOCKET;
+ }
+
+ if (sock->hAcceptEvent == NULL)
+ {
+ sock->hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ WSAEventSelect(s, sock->hAcceptEvent, FD_ACCEPT | FD_CLOSE);
+ }
+
+L_LOOP:
+
+ if (sock->CancelAccept)
+ {
+ return INVALID_SOCKET;
+ }
+
+ Zero(&d, sizeof(d));
+
+ d.IsIPv6 = ipv6;
+
+ *addrlen = initial_addrlen;
+ Zero(addr, initial_addrlen);
+ ret = WSAAccept(s, addr, addrlen, Win32AcceptCheckCallback, (DWORD_PTR)&d);
+
+ if (ret == INVALID_SOCKET)
+ {
+ err = WSAGetLastError();
+
+ if (err == WSAEWOULDBLOCK)
+ {
+ //Debug("!!! WSAAccept: WSAEWOULDBLOCK\n");
+ UINT wait_ret = WaitForSingleObject(sock->hAcceptEvent, 1234);
+
+ if (wait_ret == WAIT_OBJECT_0 || wait_ret == WAIT_TIMEOUT)
+ {
+ goto L_LOOP;
+ }
+
+ Debug("!!! WaitForSingleObject Error. ret=%u GetLastError=%u\n", wait_ret, GetLastError());
+ }
+
+ num_error++;
+
+ Debug("!!! WSAAccept Error: %u rej=%u num=%u tick=%I64u\n", err, d.Rejected, num_error, Tick64());
+
+ if (d.Rejected && err == WSAECONNREFUSED)
+ {
+ goto L_LOOP;
+ }
+
+ if (err == WSAETIMEDOUT)
+ {
+ goto L_LOOP;
+ }
+ }
+ else
+ {
+ // Remove a new socket from the event
+ WSAEventSelect(ret, sock->hAcceptEvent, 0);
+
+ // Restore the new socket to synchronized
+ WSAIoctl(ret, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);
+ }
+
+ return ret;
+}
+
+#endif // OS_WIN32
+
+
+// Get whether the aquirement of the Process ID of the TCP connection succeed
+bool CanGetTcpProcessId()
+{
+ UINT i;
+ bool ret = false;
+ LIST *o = GetTcpTableList();
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ if (t->ProcessId != 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ FreeTcpTableList(o);
+
+ return ret;
+}
+
+
+
+
+#define USE_OLD_GETIP
+
+// Set the arp_filter in Linux
+void SetLinuxArpFilter()
+{
+ char *filename = "/proc/sys/net/ipv4/conf/all/arp_filter";
+ char *data = "1\n";
+ IO *o;
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return;
+ }
+
+ FileWrite(o, data, StrLen(data));
+ FileFlush(o);
+
+ FileClose(o);
+}
+
+// Determine whether the string is a IPv6 mask
+bool IsIpMask6(char *str)
+{
+ IP mask;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return StrToMask6(&mask, str);
+}
+
+// Determine whether the string is a IPv6 address
+bool IsStrIPv6Address(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the subnet mask to an integer
+UINT SubnetMaskToInt6(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP6(a) == false)
+ {
+ return 0;
+ }
+
+ for (i = 0;i <= 128;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask6(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return i;
+ }
+ }
+
+ return 0;
+}
+UINT SubnetMaskToInt4(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP4(a) == false)
+ {
+ return 0;
+ }
+
+ for (i = 0;i <= 32;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask4(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return i;
+ }
+ }
+
+ return 0;
+}
+UINT SubnetMaskToInt(IP *a)
+{
+ if (IsIP6(a))
+ {
+ return SubnetMaskToInt6(a);
+ }
+ else
+ {
+ return SubnetMaskToInt4(a);
+ }
+}
+
+// Determine whether the specified IP address is a subnet mask
+bool IsSubnetMask6(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP6(a) == false)
+ {
+ return false;
+ }
+
+ for (i = 0;i <= 128;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask6(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Generate a global address from the MAC address
+void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac)
+{
+ UCHAR tmp[8];
+ IP a;
+ IP subnet_not;
+ IP or1, or2;
+ // Validate arguments
+ if (ip == NULL || prefix == NULL || subnet == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ GenerateEui64Address6(tmp, mac);
+
+ ZeroIP6(&a);
+
+ Copy(&a.ipv6_addr[8], tmp, 8);
+
+ IPNot6(&subnet_not, subnet);
+ IPAnd6(&or1, &a, &subnet_not);
+ IPAnd6(&or2, prefix, subnet);
+
+ IPOr6(ip, &or1, &or2);
+}
+
+// Generate a local address from the MAC address
+void GenerateEui64LocalAddress(IP *a, UCHAR *mac)
+{
+ UCHAR tmp[8];
+ // Validate arguments
+ if (a == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ GenerateEui64Address6(tmp, mac);
+
+ ZeroIP6(a);
+ a->ipv6_addr[0] = 0xfe;
+ a->ipv6_addr[1] = 0x80;
+
+ Copy(&a->ipv6_addr[8], tmp, 8);
+}
+
+// Generate the EUI-64 address from the MAC address
+void GenerateEui64Address6(UCHAR *dst, UCHAR *mac)
+{
+ // Validate arguments
+ if (dst == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ Copy(dst, mac, 3);
+ Copy(dst + 5, mac, 3);
+
+ dst[3] = 0xff;
+ dst[4] = 0xfe;
+ dst[0] = ((~(dst[0] & 0x02)) & 0x02) | (dst[0] & 0xfd);
+}
+
+// Examine whether two IP addresses are in the same network
+bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet)
+{
+ IP p1, p2, s;
+
+ if (StrToIP6(&p1, ip1) == false)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&p2, ip2) == false)
+ {
+ return false;
+ }
+
+ if (StrToMask6(&s, subnet) == false)
+ {
+ return false;
+ }
+
+ return IsInSameNetwork6(&p1, &p2, &s);
+}
+bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet)
+{
+ IP prefix1, prefix2;
+ // Validate arguments
+ if (IsIP6(a1) == false || IsIP6(a2) == false || IsIP6(subnet) == false)
+ {
+ return false;
+ }
+
+ if (a1->ipv6_scope_id != a2->ipv6_scope_id)
+ {
+ return false;
+ }
+
+ GetPrefixAddress6(&prefix1, a1, subnet);
+ GetPrefixAddress6(&prefix2, a2, subnet);
+
+ if (CmpIpAddr(&prefix1, &prefix2) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet)
+{
+ IP net1, net2;
+ // Validate arguments
+ if (IsIP4(a1) == false || IsIP4(a2) == false || IsIP4(subnet) == false)
+ {
+ return false;
+ }
+
+ IPAnd4(&net1, a1, subnet);
+ IPAnd4(&net2, a2, subnet);
+
+ if (CmpIpAddr(&net1, &net2) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Check whether it is a network address prefix
+bool IsNetworkAddress6(IP *ip, IP *subnet)
+{
+ return IsNetworkPrefixAddress6(ip, subnet);
+}
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet)
+{
+ IP host;
+ // Validate arguments
+ if (ip == NULL || subnet == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false || IsIP6(subnet) == false)
+ {
+ return false;
+ }
+
+ GetHostAddress6(&host, ip, subnet);
+
+ if (IsZeroIp(&host))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Check whether the unicast address is available
+bool CheckUnicastAddress(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if ((GetIPAddrType6(ip) & IPV6_ADDR_UNICAST) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the host address
+void GetHostAddress6(IP *dst, IP *ip, IP *subnet)
+{
+ IP not;
+ // Validate arguments
+ if (dst == NULL || ip == NULL || subnet == NULL)
+ {
+ return;
+ }
+
+ IPNot6(&not, subnet);
+
+ IPAnd6(dst, ip, &not);
+
+ dst->ipv6_scope_id = ip->ipv6_scope_id;
+}
+
+// Get the prefix address
+void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet)
+{
+ // Validate arguments
+ if (dst == NULL || ip == NULL || subnet == NULL)
+ {
+ return;
+ }
+
+ IPAnd6(dst, ip, subnet);
+
+ dst->ipv6_scope_id = ip->ipv6_scope_id;
+}
+
+// Get the solicited-node multicast address
+void GetSoliciationMulticastAddr6(IP *dst, IP *src)
+{
+ IP prefix;
+ IP mask104;
+ IP or1, or2;
+
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(&prefix);
+ prefix.ipv6_addr[0] = 0xff;
+ prefix.ipv6_addr[1] = 0x02;
+ prefix.ipv6_addr[11] = 0x01;
+ prefix.ipv6_addr[12] = 0xff;
+
+ IntToSubnetMask6(&mask104, 104);
+
+ IPAnd6(&or1, &prefix, &mask104);
+ IPAnd6(&or2, src, &mask104);
+
+ IPOr6(dst, &or1, &or2);
+
+ dst->ipv6_scope_id = src->ipv6_scope_id;
+}
+
+// Generate a MAC address corresponding to the multicast address
+void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip)
+{
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return;
+ }
+
+ mac[0] = 0x33;
+ mac[1] = 0x33;
+ mac[2] = ip->ipv6_addr[12];
+ mac[3] = ip->ipv6_addr[13];
+ mac[4] = ip->ipv6_addr[14];
+ mac[5] = ip->ipv6_addr[15];
+}
+
+// Get the type of the IPv6 address
+UINT GetIPv6AddrType(IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return 0;
+ }
+
+ IPv6AddrToIP(&ip, addr);
+
+ return GetIPAddrType6(&ip);
+}
+UINT GetIPAddrType6(IP *ip)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (IsIP6(ip) == false)
+ {
+ return 0;
+ }
+
+ if (ip->ipv6_addr[0] == 0xff)
+ {
+ IP all_node, all_router;
+
+ GetAllNodeMulticaseAddress6(&all_node);
+
+ GetAllRouterMulticastAddress6(&all_router);
+
+ ret |= IPV6_ADDR_MULTICAST;
+
+ if (Cmp(ip->ipv6_addr, all_node.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_ALL_NODE_MULTICAST;
+ }
+ else if (Cmp(ip->ipv6_addr, all_router.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_ALL_ROUTER_MULTICAST;
+ }
+ else
+ {
+ if (ip->ipv6_addr[1] == 0x02 && ip->ipv6_addr[2] == 0 && ip->ipv6_addr[3] == 0 &&
+ ip->ipv6_addr[4] == 0 && ip->ipv6_addr[5] == 0 && ip->ipv6_addr[6] == 0 &&
+ ip->ipv6_addr[7] == 0 && ip->ipv6_addr[8] == 0 && ip->ipv6_addr[9] == 0 &&
+ ip->ipv6_addr[10] == 0 && ip->ipv6_addr[11] == 0x01 && ip->ipv6_addr[12] == 0xff)
+ {
+ ret |= IPV6_ADDR_SOLICIATION_MULTICAST;
+ }
+ }
+ }
+ else
+ {
+ ret |= IPV6_ADDR_UNICAST;
+
+ if (ip->ipv6_addr[0] == 0xfe && (ip->ipv6_addr[1] & 0xc0) == 0x80)
+ {
+ ret |= IPV6_ADDR_LOCAL_UNICAST;
+ }
+ else
+ {
+ ret |= IPV6_ADDR_GLOBAL_UNICAST;
+
+ if (IsZero(&ip->ipv6_addr, 16))
+ {
+ ret |= IPV6_ADDR_ZERO;
+ }
+ else
+ {
+ IP loopback;
+
+ GetLoopbackAddress6(&loopback);
+
+ if (Cmp(ip->ipv6_addr, loopback.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_LOOPBACK;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Address that all of the bits are set
+void GetAllFilledAddress6(IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ for (i = 0;i < 15;i++)
+ {
+ ip->ipv6_addr[i] = 0xff;
+ }
+}
+
+// Loopback address
+void GetLoopbackAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[15] = 0x01;
+}
+
+// All-nodes multicast address
+void GetAllNodeMulticaseAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[0] = 0xff;
+ ip->ipv6_addr[1] = 0x02;
+ ip->ipv6_addr[15] = 0x01;
+}
+
+// All-routers multicast address
+void GetAllRouterMulticastAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[0] = 0xff;
+ ip->ipv6_addr[1] = 0x02;
+ ip->ipv6_addr[15] = 0x02;
+}
+
+// Logical operation of the IPv4 address
+void IPNot4(IP *dst, IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || IsIP4(a) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a);
+ i = ~i;
+
+ UINTToIP(dst, i);
+}
+void IPOr4(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || b == NULL || IsIP4(a) == false || IsIP4(b) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a) | IPToUINT(b);
+
+ UINTToIP(dst, i);
+}
+void IPAnd4(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || b == NULL || IsIP4(a) == false || IsIP4(b) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a) & IPToUINT(b);
+
+ UINTToIP(dst, i);
+}
+
+// Logical operation of the IPv6 address
+void IPAnd6(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = a->ipv6_addr[i] & b->ipv6_addr[i];
+ }
+}
+void IPOr6(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = a->ipv6_addr[i] | b->ipv6_addr[i];
+ }
+}
+void IPNot6(IP *dst, IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = ~(a->ipv6_addr[i]);
+ }
+}
+
+// Creating a subnet mask
+void IntToSubnetMask6(IP *ip, UINT i)
+{
+ UINT j = i / 8;
+ UINT k = i % 8;
+ UINT z;
+ IP a;
+
+ ZeroIP6(&a);
+
+ for (z = 0;z < 16;z++)
+ {
+ if (z < j)
+ {
+ a.ipv6_addr[z] = 0xff;
+ }
+ else if (z == j)
+ {
+ a.ipv6_addr[z] = ~(0xff >> k);
+ }
+ }
+
+ Copy(ip, &a, sizeof(IP));
+}
+
+// Convert the IP address to a string
+void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (str == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ IPToStr6Array(str, size, addr->Value);
+}
+void IPToStr6Array(char *str, UINT size, UCHAR *bytes)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL || bytes == NULL)
+ {
+ return;
+ }
+
+ SetIP6(&ip, bytes);
+
+ IPToStr6(str, size, &ip);
+}
+void IPToStr6(char *str, UINT size, IP *ip)
+{
+ char tmp[MAX_SIZE];
+
+ IPToStr6Inner(tmp, ip);
+
+ StrCpy(str, size, tmp);
+}
+void IPToStr6Inner(char *str, IP *ip)
+{
+ UINT i;
+ USHORT values[8];
+ UINT zero_started_index;
+ UINT max_zero_len;
+ UINT max_zero_start;
+ IP a;
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Copy(&a, ip, sizeof(IP));
+
+ for (i = 0;i < 8;i++)
+ {
+ Copy(&values[i], &a.ipv6_addr[i * 2], sizeof(USHORT));
+ values[i] = Endian16(values[i]);
+ }
+
+ // Search for omitable part
+ zero_started_index = INFINITE;
+ max_zero_len = 0;
+ max_zero_start = INFINITE;
+ for (i = 0;i < 9;i++)
+ {
+ USHORT v = (i != 8 ? values[i] : 1);
+
+ if (v == 0)
+ {
+ if (zero_started_index == INFINITE)
+ {
+ zero_started_index = i;
+ }
+ }
+ else
+ {
+ UINT zero_len;
+
+ if (zero_started_index != INFINITE)
+ {
+ zero_len = i - zero_started_index;
+ if (zero_len >= 2)
+ {
+ if (max_zero_len < zero_len)
+ {
+ max_zero_start = zero_started_index;
+ max_zero_len = zero_len;
+ }
+ }
+
+ zero_started_index = INFINITE;
+ }
+ }
+ }
+
+ // Format a string
+ StrCpy(str, 0, "");
+ for (i = 0;i < 8;i++)
+ {
+ char tmp[16];
+
+ ToHex(tmp, values[i]);
+ StrLower(tmp);
+
+ if (i == max_zero_start)
+ {
+ if (i == 0)
+ {
+ StrCat(str, 0, "::");
+ }
+ else
+ {
+ StrCat(str, 0, ":");
+ }
+ i += max_zero_len - 1;
+ }
+ else
+ {
+ StrCat(str, 0, tmp);
+ if (i != 7)
+ {
+ StrCat(str, 0, ":");
+ }
+ }
+ }
+
+ // Scope ID
+ if (ip->ipv6_scope_id != 0)
+ {
+ char tmp[64];
+
+ StrCat(str, 0, "%");
+ ToStr(tmp, ip->ipv6_scope_id);
+
+ StrCat(str, 0, tmp);
+ }
+}
+
+// Convert the string to an IP address
+bool StrToIP6(IP *ip, char *str)
+{
+ TOKEN_LIST *t;
+ char tmp[MAX_PATH];
+ IP a;
+ UINT i;
+ UINT scope_id = 0;
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ ZeroIP6(&a);
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (StartWith(tmp, "[") && EndWith(tmp, "]"))
+ {
+ // If the string is enclosed in square brackets, remove brackets
+ StrCpy(tmp, sizeof(tmp), &tmp[1]);
+
+ if (StrLen(tmp) >= 1)
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+
+ // Remove the scope ID by analyzing if there is it
+ i = SearchStrEx(tmp, "%", 0, false);
+ if (i != INFINITE)
+ {
+ char ss[MAX_PATH];
+
+ StrCpy(ss, sizeof(ss), &tmp[i + 1]);
+
+ tmp[i] = 0;
+
+ Trim(tmp);
+
+ Trim(ss);
+
+ scope_id = ToInt(ss);
+ }
+
+ // Tokenize
+ t = ParseTokenWithNullStr(tmp, ":");
+ if (t->NumTokens >= 3 && t->NumTokens <= 8)
+ {
+ UINT i, n;
+ bool b = true;
+ UINT k = 0;
+
+ n = 0;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *str = t->Token[i];
+
+ if (i != 0 && i != (t->NumTokens - 1) && StrLen(str) == 0)
+ {
+ n++;
+ if (n == 1)
+ {
+ k += 2 * (8 - t->NumTokens + 1);
+ }
+ else
+ {
+ b = false;
+ break;
+ }
+ }
+ else
+ {
+ UCHAR chars[2];
+
+ if (CheckIPItemStr6(str) == false)
+ {
+ b = false;
+ break;
+ }
+
+ IPItemStrToChars6(chars, str);
+
+ a.ipv6_addr[k++] = chars[0];
+ a.ipv6_addr[k++] = chars[1];
+ }
+ }
+
+ if (n != 0 && n != 1)
+ {
+ b = false;
+ }
+ else if (n == 0 && t->NumTokens != 8)
+ {
+ b = false;
+ }
+
+ if (b == false)
+ {
+ FreeToken(t);
+ return false;
+ }
+ }
+ else
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ FreeToken(t);
+
+ Copy(ip, &a, sizeof(IP));
+
+ ip->ipv6_scope_id = scope_id;
+
+ return true;
+}
+bool StrToIP6Addr(IPV6_ADDR *ip, char *str)
+{
+ IP ip2;
+ // Validate arguments
+ if (ip == NULL || str == NULL)
+ {
+ Zero(ip, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ if (StrToIP6(&ip2, str) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(ip, &ip2) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert an IP address character to the UCHAR type
+void IPItemStrToChars6(UCHAR *chars, char *str)
+{
+ char tmp[5];
+ BUF *b;
+ UINT len;
+ // Validate arguments
+ if (chars == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+
+ len = StrLen(str);
+ switch (len)
+ {
+ case 0:
+ tmp[0] = tmp[1] = tmp[2] = tmp[3] = '0';
+ break;
+
+ case 1:
+ tmp[0] = tmp[1] = tmp[2] = '0';
+ tmp[3] = str[0];
+ break;
+
+ case 2:
+ tmp[0] = tmp[1] = '0';
+ tmp[2] = str[0];
+ tmp[3] = str[1];
+ break;
+
+ case 3:
+ tmp[0] = '0';
+ tmp[1] = str[0];
+ tmp[2] = str[1];
+ tmp[3] = str[2];
+ break;
+
+ case 4:
+ tmp[0] = str[0];
+ tmp[1] = str[1];
+ tmp[2] = str[2];
+ tmp[3] = str[3];
+ break;
+ }
+
+ b = StrToBin(tmp);
+
+ chars[0] = ((UCHAR *)b->Buf)[0];
+ chars[1] = ((UCHAR *)b->Buf)[1];
+
+ FreeBuf(b);
+}
+
+// Check whether invalid characters are included in the element string of the IP address
+bool CheckIPItemStr6(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ if (len >= 5)
+ {
+ // Invalid length
+ return false;
+ }
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F') ||
+ (c >= '0' && c <= '9'))
+ {
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Create an IPv4 address of all zero
+void ZeroIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+}
+
+// Create an IPv6 address of all zero
+void ZeroIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ SetIP6(ip, NULL);
+}
+
+// Get the IP address of the localhost
+void GetLocalHostIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[15] = 1;
+}
+void GetLocalHostIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ SetIP(ip, 127, 0, 0, 1);
+}
+
+// Check whether the specified address is a localhost
+bool IsLocalHostIP6(IP *ip)
+{
+ IP local;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ GetLocalHostIP6(&local);
+
+ if (CmpIpAddr(&local, ip) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsLocalHostIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP4(ip) == false)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 127)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsLocalHostIP(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip))
+ {
+ return IsLocalHostIP4(ip);
+ }
+ else
+ {
+ return IsLocalHostIP6(ip);
+ }
+}
+
+// Convert the IPV6_ADDR to an IP
+void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ SetIP6(ip, addr->Value);
+}
+
+// Convert the IP to an IPV6_ADDR
+bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ for (i = 0;i < 16;i++)
+ {
+ addr->Value[i] = ip->ipv6_addr[i];
+ }
+
+ return true;
+}
+
+// Set an IPv6 address
+void SetIP6(IP *ip, UCHAR *value)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ ip->addr[0] = 223;
+ ip->addr[1] = 255;
+ ip->addr[2] = 255;
+ ip->addr[3] = 254;
+
+ if (value != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < 16;i++)
+ {
+ ip->ipv6_addr[i] = value[i];
+ }
+ }
+}
+
+// Check whether the specified address is a IPv6 address
+bool IsIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 223 && ip->addr[1] == 255 && ip->addr[2] == 255 && ip->addr[3] == 254)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ return (IsIP6(ip) ? false : true);
+}
+
+// Examine whether the version of the two IP addresses are same
+bool IsSameIPVer(IP *ip1, IP *ip2)
+{
+ // Validate arguments
+ if (ip1 == NULL || ip2 == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip1) && IsIP4(ip2))
+ {
+ return true;
+ }
+
+ if (IsIP6(ip1) && IsIP6(ip2))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Copy the IP address
+void CopyIP(IP *dst, IP *src)
+{
+ Copy(dst, src, sizeof(IP));
+}
+
+// Check the length of the IPv6 subnet
+bool CheckSubnetLength6(UINT i)
+{
+ if (i >= 1 && i <= 127)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the process ID of the corresponding TCP connection by the socket
+UINT GetTcpProcessIdFromSocket(SOCK *s)
+{
+ LIST *o;
+ TCPTABLE *t;
+ UINT pid = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ o = GetTcpTableList();
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ t = GetTcpTableFromEndPoint(o, &s->LocalIP, s->LocalPort,
+ &s->RemoteIP, s->RemotePort);
+
+ if (t != NULL)
+ {
+ pid = t->ProcessId;
+ }
+
+ FreeTcpTableList(o);
+
+ return pid;
+}
+UINT GetTcpProcessIdFromSocketReverse(SOCK *s)
+{
+ LIST *o;
+ TCPTABLE *t;
+ UINT pid = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ o = GetTcpTableList();
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ t = GetTcpTableFromEndPoint(o, &s->RemoteIP, s->RemotePort,
+ &s->LocalIP, s->LocalPort);
+
+ if (t != NULL)
+ {
+ pid = t->ProcessId;
+ }
+
+ FreeTcpTableList(o);
+
+ return pid;
+}
+
+// Search in the TCP table by the end point
+TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port)
+{
+ IP local;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ SetIP(&local, 127, 0, 0, 1);
+
+ if (local_ip == NULL)
+ {
+ local_ip = &local;
+ }
+
+ if (remote_ip == NULL)
+ {
+ remote_ip = &local;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ if (t->Status == TCP_STATE_SYN_SENT || t->Status == TCP_STATE_SYN_RCVD ||
+ t->Status == TCP_STATE_ESTAB)
+ {
+ if (CmpIpAddr(&t->LocalIP, local_ip) == 0)
+ {
+ if (CmpIpAddr(&t->RemoteIP, remote_ip) == 0)
+ {
+ if (t->LocalPort == local_port)
+ {
+ if (t->RemotePort == remote_port)
+ {
+ return t;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Get the TCP table list (Win32)
+#ifdef OS_WIN32
+LIST *Win32GetTcpTableList()
+{
+ LIST *o;
+
+ // Windows XP SP2 or later
+ o = Win32GetTcpTableListByGetExtendedTcpTable();
+ if (o != NULL)
+ {
+ return o;
+ }
+
+ // Windows XP or later
+ o = Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();
+ if (o != NULL)
+ {
+ return o;
+ }
+
+ // For legacy Windows
+ return Win32GetTcpTableListByGetTcpTable();
+}
+
+// Get the TCP table list (for Windows XP SP2 or later)
+LIST *Win32GetTcpTableListByGetExtendedTcpTable()
+{
+ UINT need_size;
+ UINT i;
+ MIB_TCPTABLE_OWNER_PID *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->GetExtendedTcpTable == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < 128;i++)
+ {
+ UINT ret;
+ table = MallocFast(sizeof(MIB_TCPTABLE_OWNER_PID));
+ need_size = sizeof(MIB_TCPTABLE_OWNER_PID);
+ ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+
+ table = MallocFast(need_size);
+
+ ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW_OWNER_PID *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->Status = r->dwState;
+ t->ProcessId = r->dwOwningPid;
+
+ Add(o, t);
+ }
+
+ Free(table);
+
+ return o;
+}
+
+// Get the TCP table list (Windows XP or later)
+LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack()
+{
+ HANDLE heap;
+ UINT i;
+ MIB_TCPTABLE_OWNER_PID *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->AllocateAndGetTcpExTableFromStack == NULL)
+ {
+ return NULL;
+ }
+
+ heap = GetProcessHeap();
+
+ if (w32net->AllocateAndGetTcpExTableFromStack(&table, true, heap, HEAP_GROWABLE, AF_INET) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW_OWNER_PID *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->ProcessId = r->dwOwningPid;
+ t->Status = r->dwState;
+
+ Add(o, t);
+ }
+
+ HeapFree(heap, 0, table);
+
+ return o;
+}
+
+// Get the TCP table list (For legacy Windows)
+LIST *Win32GetTcpTableListByGetTcpTable()
+{
+ UINT need_size;
+ UINT i;
+ MIB_TCPTABLE *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->GetTcpTable == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < 128;i++)
+ {
+ UINT ret;
+ table = MallocFast(sizeof(MIB_TCPTABLE));
+ need_size = sizeof(MIB_TCPTABLE);
+ ret = w32net->GetTcpTable(table, &need_size, true);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+
+ table = MallocFast(need_size);
+
+ ret = w32net->GetTcpTable(table, &need_size, true);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->Status = r->dwState;
+
+ Add(o, t);
+ }
+
+ Free(table);
+
+ return o;
+}
+
+#endif // OS_WIN32
+
+// Display the TCP table
+void PrintTcpTableList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ Print("o == NULL\n\n");
+ return;
+ }
+
+ Print("--- TCPTABLE: %u Entries ---\n", LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp1[MAX_PATH], tmp2[MAX_PATH];
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ IPToStr(tmp1, sizeof(tmp1), &t->LocalIP);
+ IPToStr(tmp2, sizeof(tmp2), &t->RemoteIP);
+
+ Print("%s:%u <--> %s:%u state=%u pid=%u\n",
+ tmp1, t->LocalPort,
+ tmp2, t->RemotePort,
+ t->Status,
+ t->ProcessId);
+ }
+ Print("------\n\n");
+}
+
+// Comparison of TCP table items
+int CompareTcpTable(void *p1, void *p2)
+{
+ TCPTABLE *t1, *t2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ t1 = *(TCPTABLE **)p1;
+ t2 = *(TCPTABLE **)p2;
+ if (t1 == NULL || t2 == NULL)
+ {
+ return 0;
+ }
+
+ return Cmp(t1, t2, sizeof(TCPTABLE));
+}
+
+// Get the TCP table list
+LIST *GetTcpTableList()
+{
+#ifdef OS_WIN32
+ return Win32GetTcpTableList();
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Release the TCP table list
+void FreeTcpTableList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ Free(t);
+ }
+
+ ReleaseList(o);
+}
+
+// Get the number of clients connected from the specified IP address
+UINT GetNumIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ UINT ret = 0;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return 0;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c != NULL)
+ {
+ ret = c->NumConnections;
+ }
+ }
+ UnlockList(ip_clients);
+
+ return ret;
+}
+
+// Add to the IP client entry
+void AddIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c == NULL)
+ {
+ c = ZeroMallocFast(sizeof(IP_CLIENT));
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ c->NumConnections = 0;
+
+ Add(ip_clients, c);
+ }
+
+ c->NumConnections++;
+ }
+ UnlockList(ip_clients);
+
+ //Debug("AddIpClient: %r\n", ip);
+}
+
+// Remove from the IP client list
+void DelIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c != NULL)
+ {
+ c->NumConnections--;
+
+ if (c->NumConnections == 0)
+ {
+ Delete(ip_clients, c);
+ Free(c);
+ }
+ }
+ }
+ UnlockList(ip_clients);
+
+ //Debug("DelIpClient: %r\n", ip);
+}
+
+// Search for the IP client entry
+IP_CLIENT *SearchIpClient(IP *ip)
+{
+ IP_CLIENT t;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ return Search(ip_clients, &t);
+}
+
+// Initialization of the client list
+void InitIpClientList()
+{
+ ip_clients = NewList(CompareIpClientList);
+}
+
+// Release of the client list
+void FreeIpClientList()
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(ip_clients);i++)
+ {
+ IP_CLIENT *c = LIST_DATA(ip_clients, i);
+
+ Free(c);
+ }
+
+ ReleaseList(ip_clients);
+ ip_clients = NULL;
+}
+
+// Comparison of the client list entries
+int CompareIpClientList(void *p1, void *p2)
+{
+ IP_CLIENT *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(IP_CLIENT **)p1;
+ c2 = *(IP_CLIENT **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
+}
+
+// Normalization of the MAC address
+bool NormalizeMacAddress(char *dst, UINT size, char *src)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return false;
+ }
+
+ b = StrToBin(src);
+
+ if (b != NULL && b->Size == 6)
+ {
+ ret = true;
+
+ BinToStr(dst, size, b->Buf, b->Size);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Identify whether the IP address is empty
+bool IsZeroIP(IP *ip)
+{
+ return IsZeroIp(ip);
+}
+bool IsZeroIp(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return true;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return IsZero(ip->addr, sizeof(ip->addr));
+ }
+ else
+ {
+ return IsZero(ip->ipv6_addr, sizeof(ip->ipv6_addr));
+ }
+}
+bool IsZeroIP6Addr(IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return true;
+ }
+
+ return IsZero(addr, sizeof(IPV6_ADDR));
+}
+
+// Examine whether the specified IP address is meaningful as a host
+bool IsHostIPAddress4(IP *ip)
+{
+ UINT a;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ a = IPToUINT(ip);
+
+ if (a == 0 || a == 0xffffffff)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool IsHostIPAddress32(UINT ip)
+{
+ IP p;
+
+ UINTToIP(&p, ip);
+
+ return IsHostIPAddress4(&p);
+}
+
+// Check whether the specified IP address and subnet mask indicates a network correctly
+bool IsNetworkAddress(IP *ip, IP *mask)
+{
+ if (IsIP4(ip))
+ {
+ return IsNetworkAddress4(ip, mask);
+ }
+ else
+ {
+ return IsNetworkAddress6(ip, mask);
+ }
+}
+bool IsNetworkAddress4(IP *ip, IP *mask)
+{
+ UINT a, b;
+ // Validate arguments
+ if (ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip) == false || IsIP4(mask) == false)
+ {
+ return false;
+ }
+
+ if (IsSubnetMask4(mask) == false)
+ {
+ return false;
+ }
+
+ a = IPToUINT(ip);
+ b = IPToUINT(mask);
+
+ if ((a & b) == a)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsNetworkAddress32(UINT ip, UINT mask)
+{
+ IP a, b;
+
+ UINTToIP(&a, ip);
+ UINTToIP(&b, mask);
+
+ return IsNetworkAddress4(&a, &b);
+}
+
+// Convert the integer to a subnet mask
+UINT IntToSubnetMask32(UINT i)
+{
+ UINT ret = 0xFFFFFFFF;
+
+ switch (i)
+ {
+ case 0: ret = 0x00000000; break;
+ case 1: ret = 0x80000000; break;
+ case 2: ret = 0xC0000000; break;
+ case 3: ret = 0xE0000000; break;
+ case 4: ret = 0xF0000000; break;
+ case 5: ret = 0xF8000000; break;
+ case 6: ret = 0xFC000000; break;
+ case 7: ret = 0xFE000000; break;
+ case 8: ret = 0xFF000000; break;
+ case 9: ret = 0xFF800000; break;
+ case 10: ret = 0xFFC00000; break;
+ case 11: ret = 0xFFE00000; break;
+ case 12: ret = 0xFFF00000; break;
+ case 13: ret = 0xFFF80000; break;
+ case 14: ret = 0xFFFC0000; break;
+ case 15: ret = 0xFFFE0000; break;
+ case 16: ret = 0xFFFF0000; break;
+ case 17: ret = 0xFFFF8000; break;
+ case 18: ret = 0xFFFFC000; break;
+ case 19: ret = 0xFFFFE000; break;
+ case 20: ret = 0xFFFFF000; break;
+ case 21: ret = 0xFFFFF800; break;
+ case 22: ret = 0xFFFFFC00; break;
+ case 23: ret = 0xFFFFFE00; break;
+ case 24: ret = 0xFFFFFF00; break;
+ case 25: ret = 0xFFFFFF80; break;
+ case 26: ret = 0xFFFFFFC0; break;
+ case 27: ret = 0xFFFFFFE0; break;
+ case 28: ret = 0xFFFFFFF0; break;
+ case 29: ret = 0xFFFFFFF8; break;
+ case 30: ret = 0xFFFFFFFC; break;
+ case 31: ret = 0xFFFFFFFE; break;
+ case 32: ret = 0xFFFFFFFF; break;
+ }
+
+ if (IsLittleEndian())
+ {
+ ret = Swap32(ret);
+ }
+
+ return ret;
+}
+void IntToSubnetMask4(IP *ip, UINT i)
+{
+ UINT m;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ m = IntToSubnetMask32(i);
+
+ UINTToIP(ip, m);
+}
+
+// Examine whether the specified IP address is a subnet mask
+bool IsSubnetMask(IP *ip)
+{
+ if (IsIP6(ip))
+ {
+ return IsSubnetMask6(ip);
+ }
+ else
+ {
+ return IsSubnetMask4(ip);
+ }
+}
+bool IsSubnetMask4(IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip))
+ {
+ return false;
+ }
+
+ i = IPToUINT(ip);
+
+ if (IsLittleEndian())
+ {
+ i = Swap32(i);
+ }
+
+ switch (i)
+ {
+ case 0x00000000:
+ case 0x80000000:
+ case 0xC0000000:
+ case 0xE0000000:
+ case 0xF0000000:
+ case 0xF8000000:
+ case 0xFC000000:
+ case 0xFE000000:
+ case 0xFF000000:
+ case 0xFF800000:
+ case 0xFFC00000:
+ case 0xFFE00000:
+ case 0xFFF00000:
+ case 0xFFF80000:
+ case 0xFFFC0000:
+ case 0xFFFE0000:
+ case 0xFFFF0000:
+ case 0xFFFF8000:
+ case 0xFFFFC000:
+ case 0xFFFFE000:
+ case 0xFFFFF000:
+ case 0xFFFFF800:
+ case 0xFFFFFC00:
+ case 0xFFFFFE00:
+ case 0xFFFFFF00:
+ case 0xFFFFFF80:
+ case 0xFFFFFFC0:
+ case 0xFFFFFFE0:
+ case 0xFFFFFFF0:
+ case 0xFFFFFFF8:
+ case 0xFFFFFFFC:
+ case 0xFFFFFFFE:
+ case 0xFFFFFFFF:
+ return true;
+ }
+
+ return false;
+}
+bool IsSubnetMask32(UINT ip)
+{
+ IP p;
+
+ UINTToIP(&p, ip);
+
+ return IsSubnetMask4(&p);
+}
+
+// Network release mode
+void SetNetworkReleaseMode()
+{
+ NetworkReleaseMode = true;
+}
+
+#ifdef OS_UNIX // Code for UNIX
+
+// Turn on and off the non-blocking mode of the socket
+void UnixSetSocketNonBlockingMode(int fd, bool nonblock)
+{
+ UINT flag = 0;
+ // Validate arguments
+ if (fd == INVALID_SOCKET)
+ {
+ return;
+ }
+
+ if (nonblock)
+ {
+ flag = 1;
+ }
+
+#ifdef FIONBIO
+ ioctl(fd, FIONBIO, &flag);
+#else // FIONBIO
+ {
+ int flag = fcntl(fd, F_GETFL, 0);
+ if (flag != -1)
+ {
+ if (nonblock)
+ {
+ flag |= O_NONBLOCK;
+ }
+ else
+ {
+ flag = flag & ~O_NONBLOCK;
+
+ fcntl(fd, F_SETFL, flag);
+ }
+ }
+ }
+#endif // FIONBIO
+}
+
+// Do Nothing
+void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
+{
+}
+
+// Do Nothing
+void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
+{
+}
+
+// Do Nothing
+int UnixCompareRouteEntryByMetric(void *p1, void *p2)
+{
+ return 1;
+}
+
+// Do Nothing
+ROUTE_TABLE *UnixGetRouteTable()
+{
+ ROUTE_TABLE *ret = ZeroMalloc(sizeof(ROUTE_TABLE));
+ ret->NumEntry = 0;
+ ret->Entry = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Do Nothing
+bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
+{
+ return true;
+}
+
+// Do Nothing
+void UnixDeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ return;
+}
+
+// Do Nothing
+UINT UnixGetVLanInterfaceID(char *instance_name)
+{
+ return 1;
+}
+
+// Do Nothing
+char **UnixEnumVLan(char *tag_name)
+{
+ char **list;
+
+ list = ZeroMalloc(sizeof(char *));
+
+ return list;
+}
+
+// Do Nothing
+void UnixRenewDhcp()
+{
+}
+
+// Get the IP address of the default DNS server
+bool UnixGetDefaultDns(IP *ip)
+{
+ BUF *b;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ Lock(unix_dns_server_addr_lock);
+ {
+ if (IsZero(&unix_dns_server, sizeof(IP)) == false)
+ {
+ Copy(ip, &unix_dns_server, sizeof(IP));
+ Unlock(unix_dns_server_addr_lock);
+ return true;
+ }
+
+ ip->addr[0] = 127;
+ ip->addr[1] = 0;
+ ip->addr[2] = 0;
+ ip->addr[3] = 1;
+
+ b = ReadDump("/etc/resolv.conf");
+ if (b != NULL)
+ {
+ char *s;
+ bool f = false;
+ while ((s = CfgReadNextLine(b)) != NULL)
+ {
+ TOKEN_LIST *t = ParseToken(s, "\" \t,");
+ if (t->NumTokens == 2)
+ {
+ if (StrCmpi(t->Token[0], "nameserver") == 0)
+ {
+ StrToIP(ip, t->Token[1]);
+ f = true;
+ }
+ }
+ FreeToken(t);
+
+ Free(s);
+
+ if (f)
+ {
+ break;
+ }
+ }
+ FreeBuf(b);
+ }
+ Copy(&unix_dns_server, ip, sizeof(IP));
+ }
+ Unlock(unix_dns_server_addr_lock);
+
+ return true;
+}
+
+
+// Select procedure
+void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+ UINT reads[MAXIMUM_WAIT_OBJECTS];
+ UINT writes[MAXIMUM_WAIT_OBJECTS];
+ UINT num_read, num_write, i;
+ UINT p1, p2;
+ SOCK_EVENT *sock_events[MAXIMUM_WAIT_OBJECTS];
+ UINT num_sock_events;
+ SOCK *s;
+ UCHAR tmp[MAX_SIZE];
+ int ret;
+ bool any_of_tubes_are_readable = false;
+ // Initialization of array
+ Zero(reads, sizeof(reads));
+ Zero(writes, sizeof(writes));
+ Zero(sock_events, sizeof(sock_events));
+ num_read = num_write = num_sock_events = 0;
+
+ // Setting the event array
+ if (set != NULL)
+ {
+ for (i = 0;i < set->NumSocket;i++)
+ {
+ s = set->Sock[i];
+ if (s != NULL)
+ {
+ UnixInitAsyncSocket(s);
+ if (s->Type == SOCK_INPROC)
+ {
+ TUBE *t = s->RecvTube;
+ if (t != NULL)
+ {
+ reads[num_read++] = t->SockEvent->pipe_read;
+
+ sock_events[num_sock_events++] = t->SockEvent;
+
+ if (t->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+ }
+ else
+ {
+ if (s->NoNeedToRead == false)
+ {
+ reads[num_read++] = s->socket;
+ }
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TUBE *t = s->BulkRecvTube;
+ if (t != NULL)
+ {
+ reads[num_read++] = t->SockEvent->pipe_read;
+
+ sock_events[num_sock_events++] = t->SockEvent;
+
+ if (t->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+ }
+
+ if (s->WriteBlocked)
+ {
+ writes[num_write++] = s->socket;
+ }
+ }
+ }
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ p1 = p2 = -1;
+
+ if (c1 != NULL)
+ {
+ reads[num_read++] = p1 = c1->pipe_read;
+ }
+ if (c2 != NULL)
+ {
+ reads[num_read++] = p2 = c2->pipe_read;
+ }
+
+ // Call the select
+ if (any_of_tubes_are_readable == false)
+ {
+ UnixSelectInner(num_read, reads, num_write, writes, timeout);
+ }
+
+ // Read from the pipe
+ if (c1 != NULL && c1->SpecialFlag == false && p1 != -1)
+ {
+ do
+ {
+ ret = read(p1, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+ if (c2 != NULL && c2->SpecialFlag == false && p2 != -1)
+ {
+ do
+ {
+ ret = read(p2, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+
+ // Read from the pipe of sockevent
+ for (i = 0;i < num_sock_events;i++)
+ {
+ SOCK_EVENT *e = sock_events[i];
+
+ e->current_pipe_data = 0;
+
+ do
+ {
+ ret = read(e->pipe_read, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+}
+
+// Cancel
+void UnixCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ UnixWritePipe(c->pipe_write);
+}
+
+// Release of the cancel object
+void UnixCleanupCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->SpecialFlag == false)
+ {
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ }
+
+ Free(c);
+}
+
+// Creating a new cancel object
+CANCEL *UnixNewCancel()
+{
+ CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
+
+ c->ref = NewRef();
+ c->SpecialFlag = false;
+
+ UnixNewPipe(&c->pipe_read, &c->pipe_write);
+
+ return c;
+}
+
+// Add the socket to the socket event
+void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (sock == NULL || event == NULL || sock->AsyncMode)
+ {
+ return;
+ }
+ if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ LockList(event->SockList);
+ {
+ Add(event->SockList, sock);
+ AddRef(sock->ref);
+ }
+ UnlockList(event->SockList);
+
+ // Make the socket asynchronous mode
+ if (sock->Type != SOCK_INPROC)
+ {
+ UnixSetSocketNonBlockingMode(sock->socket, true);
+ }
+
+ // Increase the reference count of the SOCK_EVENT
+ AddRef(event->ref);
+ sock->SockEvent = event;
+
+ // Set the socket event
+ SetSockEvent(event);
+}
+
+// Wait for a socket event
+bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ UINT num_read, num_write;
+ UINT *reads, *writes;
+ UINT n;
+ char tmp[MAX_SIZE];
+ int readret = 0;
+ bool event_pipe_is_readable = false;
+ // Validate arguments
+ if (event == NULL)
+ {
+ return false;
+ }
+
+ LockList(event->SockList);
+ {
+ UINT i;
+ reads = ZeroMallocFast(sizeof(SOCK *) * (LIST_NUM(event->SockList) + 1));
+
+ num_write = 0;
+ num_read = 0;
+
+ for (i = 0;i < LIST_NUM(event->SockList);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+
+ if (s->NoNeedToRead == false)
+ {
+ reads[num_read++] = s->socket;
+ }
+
+ if (s->WriteBlocked)
+ {
+ num_write++;
+ }
+ }
+
+ reads[num_read++] = event->pipe_read;
+
+ if (event->current_pipe_data != 0)
+ {
+ event_pipe_is_readable = true;
+ }
+
+ writes = ZeroMallocFast(sizeof(SOCK *) * num_write);
+
+ n = 0;
+
+ for (i = 0;i < (num_read - 1);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+ if (s->WriteBlocked)
+ {
+ writes[n++] = s->socket;
+ }
+ }
+ }
+ UnlockList(event->SockList);
+
+ if (event_pipe_is_readable == false)
+ {
+ UnixSelectInner(num_read, reads, num_write, writes, timeout);
+ }
+
+ event->current_pipe_data = 0;
+ do
+ {
+ readret = read(event->pipe_read, tmp, sizeof(tmp));
+ }
+ while (readret >= 1);
+
+ Free(reads);
+ Free(writes);
+
+ return true;
+}
+
+// Set the socket event
+void UnixSetSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ if (event->current_pipe_data <= 100)
+ {
+ UnixWritePipe(event->pipe_write);
+ event->current_pipe_data++;
+ }
+}
+
+// Execute 'select' for the socket
+void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout)
+{
+ struct pollfd *p;
+ UINT num;
+ UINT i;
+ UINT n;
+ UINT num_read_total, num_write_total;
+
+ if (num_read != 0 && reads == NULL)
+ {
+ num_read = 0;
+ }
+ if (num_write != 0 && writes == NULL)
+ {
+ num_write = 0;
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ num_read_total = num_write_total = 0;
+ for (i = 0;i < num_read;i++)
+ {
+ if (reads[i] != INVALID_SOCKET)
+ {
+ num_read_total++;
+ }
+ }
+ for (i = 0;i < num_write;i++)
+ {
+ if (writes[i] != INVALID_SOCKET)
+ {
+ num_write_total++;
+ }
+ }
+
+ num = num_read_total + num_write_total;
+ p = ZeroMallocFast(sizeof(struct pollfd) * num);
+
+ n = 0;
+
+ for (i = 0;i < num_read;i++)
+ {
+ if (reads[i] != INVALID_SOCKET)
+ {
+ struct pollfd *pfd = &p[n++];
+ pfd->fd = reads[i];
+ pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP;
+ }
+ }
+
+ for (i = 0;i < num_write;i++)
+ {
+ if (writes[i] != INVALID_SOCKET)
+ {
+ struct pollfd *pfd = &p[n++];
+ pfd->fd = writes[i];
+ pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT;
+ }
+ }
+
+ if (num != 0)
+ {
+ poll(p, num, timeout == INFINITE ? -1 : (int)timeout);
+ }
+ else
+ {
+ SleepThread(timeout);
+ }
+
+ Free(p);
+}
+
+// Clean-up of the socket event
+void UnixCleanupSockEvent(SOCK_EVENT *event)
+{
+ UINT i;
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(event->SockList);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+
+ ReleaseSock(s);
+ }
+
+ ReleaseList(event->SockList);
+
+ UnixDeletePipe(event->pipe_read, event->pipe_write);
+
+ Free(event);
+}
+
+// Create a socket event
+SOCK_EVENT *UnixNewSockEvent()
+{
+ SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
+
+ e->SockList = NewList(NULL);
+ e->ref = NewRef();
+
+ UnixNewPipe(&e->pipe_read, &e->pipe_write);
+
+ return e;
+}
+
+// Close the pipe
+void UnixDeletePipe(int p1, int p2)
+{
+ if (p1 != -1)
+ {
+ close(p1);
+ }
+
+ if (p2 != -1)
+ {
+ close(p2);
+ }
+}
+
+// Write to the pipe
+void UnixWritePipe(int pipe_write)
+{
+ char c = 1;
+ write(pipe_write, &c, 1);
+}
+
+// Create a new pipe
+void UnixNewPipe(int *pipe_read, int *pipe_write)
+{
+ int fd[2];
+ // Validate arguments
+ if (pipe_read == NULL || pipe_write == NULL)
+ {
+ return;
+ }
+
+ fd[0] = fd[1] = 0;
+
+ pipe(fd);
+
+ *pipe_read = fd[0];
+ *pipe_write = fd[1];
+
+ UnixSetSocketNonBlockingMode(*pipe_write, true);
+ UnixSetSocketNonBlockingMode(*pipe_read, true);
+}
+
+// Release the asynchronous socket
+void UnixFreeAsyncSocket(SOCK *sock)
+{
+ UINT p;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ Lock(sock->lock);
+ {
+ if (sock->AsyncMode == false)
+ {
+ Unlock(sock->lock);
+ return;
+ }
+
+ sock->AsyncMode = false;
+
+ // Examine whether this socket are associated to SockEvent
+ if (sock->SockEvent != NULL)
+ {
+ SOCK_EVENT *e = sock->SockEvent;
+
+ AddRef(e->ref);
+
+ p = e->pipe_write;
+ LockList(e->SockList);
+ {
+ if (Delete(e->SockList, sock))
+ {
+ ReleaseSock(sock);
+ }
+ }
+ UnlockList(e->SockList);
+
+ // Release the socket event
+ ReleaseSockEvent(sock->SockEvent);
+ sock->SockEvent = NULL;
+
+ SetSockEvent(e);
+
+ ReleaseSockEvent(e);
+ }
+ }
+ Unlock(sock->lock);
+}
+
+// Set the socket to asynchronous mode
+void UnixInitAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->AsyncMode)
+ {
+ // The socket has been set in asynchronous mode already
+ return;
+ }
+ if (sock->ListenMode != false || ((sock->Type == SOCK_TCP || sock->Type == SOCK_INPROC) && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ if (sock->Type != SOCK_INPROC)
+ {
+ UnixSetSocketNonBlockingMode(sock->socket, true);
+ }
+}
+
+// Initializing the socket library
+void UnixInitSocketLibrary()
+{
+ // Do not do anything special
+}
+
+// Release of the socket library
+void UnixFreeSocketLibrary()
+{
+ // Do not do anything special
+}
+
+#endif // OS_UNIX
+
+#ifdef OS_WIN32 // Code for Windows
+
+NETWORK_WIN32_FUNCTIONS *w32net;
+
+// Comparison of IP_ADAPTER_INDEX_MAP
+int CompareIpAdapterIndexMap(void *p1, void *p2)
+{
+ IP_ADAPTER_INDEX_MAP *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(IP_ADAPTER_INDEX_MAP **)p1;
+ a2 = *(IP_ADAPTER_INDEX_MAP **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+
+ if (a1->Index > a2->Index)
+ {
+ return 1;
+ }
+ else if (a1->Index < a2->Index)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Update the IP address of the adapter
+bool Win32RenewAddressByGuid(char *guid)
+{
+ IP_ADAPTER_INDEX_MAP a;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+ if (Win32GetAdapterFromGuid(&a, guid) == false)
+ {
+ return false;
+ }
+
+ return Win32RenewAddress(&a);
+}
+bool Win32RenewAddress(void *a)
+{
+ DWORD ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (w32net->IpRenewAddress == NULL)
+ {
+ return false;
+ }
+
+ ret = w32net->IpRenewAddress(a);
+
+ if (ret == NO_ERROR)
+ {
+ return true;
+ }
+ else
+ {
+ Debug("IpRenewAddress: Error: %u\n", ret);
+ return false;
+ }
+}
+
+// Release the IP address of the adapter
+bool Win32ReleaseAddress(void *a)
+{
+ DWORD ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (w32net->IpReleaseAddress == NULL)
+ {
+ return false;
+ }
+
+ ret = w32net->IpReleaseAddress(a);
+
+ if (ret == NO_ERROR)
+ {
+ return true;
+ }
+ else
+ {
+ Debug("IpReleaseAddress: Error: %u\n", ret);
+ return false;
+ }
+}
+bool Win32ReleaseAddressByGuid(char *guid)
+{
+ IP_ADAPTER_INDEX_MAP a;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+ if (Win32GetAdapterFromGuid(&a, guid) == false)
+ {
+ return false;
+ }
+
+ return Win32ReleaseAddress(&a);
+}
+void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param)
+{
+ WIN32_RELEASEADDRESS_THREAD_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32_RELEASEADDRESS_THREAD_PARAM *)param;
+
+ AddRef(p->Ref);
+
+ NoticeThreadInit(t);
+
+ AddWaitThread(t);
+
+ if (p->Renew == false)
+ {
+ p->Ok = Win32ReleaseAddressByGuid(p->Guid);
+ }
+ else
+ {
+ p->Ok = Win32RenewAddressByGuid(p->Guid);
+ }
+
+ ReleaseWin32ReleaseAddressByGuidThreadParam(p);
+
+ DelWaitThread(t);
+}
+bool Win32RenewAddressByGuidEx(char *guid, UINT timeout)
+{
+ return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, true);
+}
+bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout)
+{
+ return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, false);
+}
+bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew)
+{
+ THREAD *t;
+ WIN32_RELEASEADDRESS_THREAD_PARAM *p;
+ bool ret = false;
+ UINT64 start_tick = 0;
+ UINT64 end_tick = 0;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = INFINITE;
+ }
+
+ p = ZeroMalloc(sizeof(WIN32_RELEASEADDRESS_THREAD_PARAM));
+ p->Ref = NewRef();
+ StrCpy(p->Guid, sizeof(p->Guid), guid);
+ p->Timeout = timeout;
+ p->Renew = renew;
+
+ t = NewThread(Win32ReleaseAddressByGuidExThread, p);
+ WaitThreadInit(t);
+ start_tick = Tick64();
+ end_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT64 remain;
+ UINT remain32;
+
+ if (now >= end_tick)
+ {
+ break;
+ }
+
+ remain = end_tick - now;
+ remain32 = MIN((UINT)remain, 100);
+
+ if (WaitThread(t, remain32))
+ {
+ break;
+ }
+ }
+
+ ReleaseThread(t);
+
+ if (p->Ok)
+ {
+ ret = true;
+ }
+
+ ReleaseWin32ReleaseAddressByGuidThreadParam(p);
+
+ return ret;
+}
+void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (Release(p->Ref) == 0)
+ {
+ Free(p);
+ }
+}
+
+// Get the adapter by the GUID
+bool Win32GetAdapterFromGuid(void *a, char *guid)
+{
+ bool ret = false;
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ wchar_t tmp[MAX_SIZE];
+
+ // Validate arguments
+ if (a == NULL || guid == NULL)
+ {
+ return false;
+ }
+ if (w32net->GetInterfaceInfo == NULL)
+ {
+ return false;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"\\DEVICE\\TCPIP_%S", guid);
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *e = LIST_DATA(o, i);
+
+ if (UniStrCmpi(e->Name, tmp) == 0)
+ {
+ Copy(a, e, sizeof(IP_ADAPTER_INDEX_MAP));
+ ret = true;
+ break;
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+
+ return ret;
+}
+
+// Test
+void Win32NetworkTest()
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ DoNothing();
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Clear the DNS cache on Win32
+void Win32FlushDnsCache()
+{
+ Run("ipconfig.exe", "/flushdns", true, false);
+}
+
+// Update the DHCP address of the specified LAN card
+void Win32RenewDhcp9x(UINT if_id)
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ // Validate arguments
+ if (if_id == 0)
+ {
+ return;
+ }
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ if (a->Index == if_id)
+ {
+ char arg[MAX_PATH];
+ Format(arg, sizeof(arg), "/renew %u", i);
+ Run("ipconfig.exe", arg, true, false);
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Release the DHCP address of the specified LAN card
+void Win32ReleaseDhcp9x(UINT if_id, bool wait)
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ // Validate arguments
+ if (if_id == 0)
+ {
+ return;
+ }
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ if (a->Index == if_id)
+ {
+ char arg[MAX_PATH];
+ Format(arg, sizeof(arg), "/release %u", i);
+ Run("ipconfig.exe", arg, true, wait);
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Re-obtain an IP address from a DHCP server
+void Win32RenewDhcp()
+{
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ Run("ipconfig.exe", "/renew", true, false);
+ if (MsIsVista())
+ {
+ Run("ipconfig.exe", "/renew6", true, false);
+ }
+ else
+ {
+ Run("netsh.exe", "int ipv6 renew", true, false);
+ }
+ }
+ else
+ {
+ Run("ipconfig.exe", "/renew_all", true, false);
+ }
+}
+
+// Enumerate a list of virtual LAN cards that contains the specified string
+char **Win32EnumVLan(char *tag_name)
+{
+ MIB_IFTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ UINT i;
+ LIST *o;
+ char **ss;
+ // Validate arguments
+ if (tag_name == 0)
+ {
+ return NULL;
+ }
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIfTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ return NULL;
+ }
+
+ // Actually get
+ ret = w32net->GetIfTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ goto RETRY;
+ }
+
+ // Search
+ ret = 0;
+ o = NewListFast(CompareStr);
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &p->table[i];
+ if (SearchStrEx(r->bDescr, tag_name, 0, false) != INFINITE)
+ {
+ char *s = CopyStr(r->bDescr);
+ Add(o, s);
+ }
+ }
+
+ Free(p);
+
+ // Sort
+ Sort(o);
+
+ // Convert to string
+ ss = ZeroMallocFast(sizeof(char *) * (LIST_NUM(o) + 1));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ss[i] = LIST_DATA(o, i);
+ }
+ ss[LIST_NUM(o)] = NULL;
+
+ ReleaseList(o);
+
+ return ss;
+}
+
+// Get the ID of the virtual LAN card from the instance name of the virtual LAN card
+UINT Win32GetVLanInterfaceID(char *instance_name)
+{
+ MIB_IFTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ UINT i;
+ char ps_miniport_str[MAX_SIZE];
+ char ps_miniport_str2[MAX_SIZE];
+ UINT min_len = 0x7FFFFFFF;
+ // Validate arguments
+ if (instance_name == 0)
+ {
+ return 0;
+ }
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIfTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ Debug("******** GetIfTable Failed 1. Err = %u\n", ret);
+ return 0;
+ }
+
+ // Actually get
+ ret = w32net->GetIfTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ Debug("******** GetIfTable Failed 2. Err = %u\n", ret);
+ goto RETRY;
+ }
+
+ // "%s - Packet scheduler miniport"
+ Format(ps_miniport_str, sizeof(ps_miniport_str), "%s - ", instance_name);
+ Format(ps_miniport_str2, sizeof(ps_miniport_str2), "%s (Microsoft", instance_name);
+
+ // Search
+ ret = 0;
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &p->table[i];
+ if (instance_name[0] != '@')
+ {
+ if (StrCmpi(r->bDescr, instance_name) == 0 || StartWith(r->bDescr, ps_miniport_str) || StartWith(r->bDescr, ps_miniport_str2))
+ {
+ UINT len = StrLen(r->bDescr);
+
+ if (len < min_len)
+ {
+ ret = r->dwIndex;
+
+ min_len = len;
+ }
+ }
+ }
+ else
+ {
+ if (SearchStrEx(r->bDescr, &instance_name[1], 0, false) != INFINITE)
+ {
+ ret = r->dwIndex;
+ }
+ }
+
+ //Debug("if[%u] (dwIndex=%u): %u, %s\n", i, r->dwIndex, r->dwType, r->bDescr);
+ }
+
+ Free(p);
+
+ return ret;
+}
+
+// Get the DNS suffix in another way
+bool Win32GetDnsSuffix(char *domain, UINT size)
+{
+ IP_ADAPTER_ADDRESSES_XP *info;
+ IP_ADAPTER_ADDRESSES_XP *cur;
+ UINT info_size;
+ bool ret = false;
+ // Validate arguments
+ ClearStr(domain, size);
+ if (domain == NULL)
+ {
+ return false;
+ }
+ if (w32net->GetAdaptersAddresses == NULL)
+ {
+ return false;
+ }
+
+ info_size = 0;
+ info = ZeroMalloc(sizeof(IP_ADAPTER_ADDRESSES_XP));
+ if (w32net->GetAdaptersAddresses(AF_INET, 0, NULL, info, &info_size) == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info);
+ info = ZeroMalloc(info_size);
+ }
+ if (w32net->GetAdaptersAddresses(AF_INET, 0, NULL, info, &info_size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ cur = info;
+
+ while (cur != NULL)
+ {
+ if (UniIsEmptyStr(cur->DnsSuffix) == false)
+ {
+ UniToStr(domain, size, cur->DnsSuffix);
+ ret = true;
+ break;
+ }
+
+ cur = cur->Next;
+ }
+
+ Free(info);
+
+ return ret;
+}
+
+// Get the DNS server address of the default
+bool Win32GetDefaultDns(IP *ip, char *domain, UINT size)
+{
+ FIXED_INFO *info;
+ UINT info_size;
+ char *dns_name;
+ // Validate arguments
+ ClearStr(domain, size);
+ if (ip == NULL)
+ {
+ return false;
+ }
+ Zero(ip, sizeof(IP));
+ if (w32net->GetNetworkParams == NULL)
+ {
+ return false;
+ }
+ info_size = 0;
+ info = ZeroMallocFast(sizeof(FIXED_INFO));
+ if (w32net->GetNetworkParams(info, &info_size) == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info);
+ info = ZeroMallocFast(info_size);
+ }
+ if (w32net->GetNetworkParams(info, &info_size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ if (info->DnsServerList.IpAddress.String == NULL)
+ {
+ Free(info);
+ return false;
+ }
+
+ dns_name = info->DnsServerList.IpAddress.String;
+ StrToIP(ip, dns_name);
+
+ if (domain != NULL)
+ {
+ StrCpy(domain, size, info->DomainName);
+ Trim(domain);
+ }
+
+ Free(info);
+
+ return true;
+}
+
+// IP conversion function for Win32
+void Win32UINTToIP(IP *ip, UINT i)
+{
+ UINTToIP(ip, i);
+}
+
+// IP conversion function for Win32
+UINT Win32IPToUINT(IP *ip)
+{
+ return IPToUINT(ip);
+}
+
+// Remove a routing entry from the routing table
+void Win32DeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ MIB_IPFORWARDROW *p;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
+ Win32RouteEntryToIpForwardRow(p, e);
+
+ // Delete
+ w32net->DeleteIpForwardEntry(p);
+
+ Free(p);
+}
+
+// Add a routing entry to the routing table
+bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
+{
+ bool ret = false;
+ bool dummy = false;
+ MIB_IPFORWARDROW *p;
+ UINT err = 0;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return false;
+ }
+ if (already_exists == NULL)
+ {
+ already_exists = &dummy;
+ }
+
+ *already_exists = false;
+
+ p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
+ Win32RouteEntryToIpForwardRow(p, e);
+
+ // Adding
+ err = w32net->CreateIpForwardEntry(p);
+ if (err != 0)
+ {
+ if (err == ERROR_OBJECT_ALREADY_EXISTS)
+ {
+ Debug("CreateIpForwardEntry: Already Exists\n");
+ *already_exists = true;
+ ret = true;
+ }
+ else
+ {
+ Debug("CreateIpForwardEntry Error: %u\n", err);
+ ret = false;
+ }
+ }
+ else
+ {
+ ret = true;
+ }
+
+ Free(p);
+
+ return ret;
+}
+
+// Get the routing table
+ROUTE_TABLE *Win32GetRouteTable()
+{
+ ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE));
+ MIB_IPFORWARDTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ LIST *o;
+ UINT i;
+ ROUTE_ENTRY *e;
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIpForwardTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ t->Entry = MallocFast(0);
+ return t;
+ }
+
+ // Actually get
+ ret = w32net->GetIpForwardTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ goto RETRY;
+ }
+
+ // Add to the list along
+ o = NewListFast(Win32CompareRouteEntryByMetric);
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ e = ZeroMallocFast(sizeof(ROUTE_ENTRY));
+ Win32IpForwardRowToRouteEntry(e, &p->table[i]);
+ Add(o, e);
+ }
+ Free(p);
+
+ // Sort by metric
+ Sort(o);
+
+ // Combine the results
+ t->NumEntry = LIST_NUM(o);
+ t->Entry = ToArrayEx(o, true);
+ ReleaseList(o);
+
+ return t;
+}
+
+// Sort the routing entries by metric
+int Win32CompareRouteEntryByMetric(void *p1, void *p2)
+{
+ ROUTE_ENTRY *e1, *e2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ e1 = *(ROUTE_ENTRY **)p1;
+ e2 = *(ROUTE_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->Metric > e2->Metric)
+ {
+ return 1;
+ }
+ else if (e1->Metric == e2->Metric)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+// Convert the ROUTE_ENTRY to a MIB_IPFORWARDROW
+void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
+{
+ MIB_IPFORWARDROW *r;
+ // Validate arguments
+ if (entry == NULL || ip_forward_row == NULL)
+ {
+ return;
+ }
+
+ r = (MIB_IPFORWARDROW *)ip_forward_row;
+ Zero(r, sizeof(MIB_IPFORWARDROW));
+
+ // IP address
+ r->dwForwardDest = Win32IPToUINT(&entry->DestIP);
+ // Subnet mask
+ r->dwForwardMask = Win32IPToUINT(&entry->DestMask);
+ // Gateway IP address
+ r->dwForwardNextHop = Win32IPToUINT(&entry->GatewayIP);
+ // Local routing flag
+ if (entry->LocalRouting)
+ {
+ // Local
+ r->dwForwardType = 3;
+ }
+ else
+ {
+ // Remote router
+ r->dwForwardType = 4;
+ }
+ // Protocol
+ r->dwForwardProto = r->dwForwardType - 1; // Subtract by 1 in most cases
+ if (entry->PPPConnection)
+ {
+ // Isn't this a PPP? Danger!
+ r->dwForwardProto++;
+ }
+ // Metric
+ r->dwForwardMetric1 = entry->Metric;
+
+ if (MsIsVista() == false)
+ {
+ r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = INFINITE;
+ }
+ else
+ {
+ r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = 0;
+ r->dwForwardAge = 163240;
+ }
+
+ // Interface ID
+ r->dwForwardIfIndex = entry->InterfaceID;
+
+ Debug("Win32RouteEntryToIpForwardRow()\n");
+ Debug(" r->dwForwardDest=%X\n", r->dwForwardDest);
+ Debug(" r->dwForwardMask=%X\n", r->dwForwardMask);
+ Debug(" r->dwForwardNextHop=%X\n", r->dwForwardNextHop);
+ Debug(" r->dwForwardType=%u\n", r->dwForwardType);
+ Debug(" r->dwForwardProto=%u\n", r->dwForwardProto);
+ Debug(" r->dwForwardMetric1=%u\n", r->dwForwardMetric1);
+ Debug(" r->dwForwardMetric2=%u\n", r->dwForwardMetric2);
+ Debug(" r->dwForwardIfIndex=%u\n", r->dwForwardIfIndex);
+}
+
+// Convert the MIB_IPFORWARDROW to a ROUTE_ENTRY
+void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
+{
+ MIB_IPFORWARDROW *r;
+ // Validate arguments
+ if (entry == NULL || ip_forward_row == NULL)
+ {
+ return;
+ }
+
+ r = (MIB_IPFORWARDROW *)ip_forward_row;
+
+ Zero(entry, sizeof(ROUTE_ENTRY));
+ // IP address
+ Win32UINTToIP(&entry->DestIP, r->dwForwardDest);
+ // Subnet mask
+ Win32UINTToIP(&entry->DestMask, r->dwForwardMask);
+ // Gateway IP address
+ Win32UINTToIP(&entry->GatewayIP, r->dwForwardNextHop);
+ // Local routing flag
+ if (r->dwForwardType == 3)
+ {
+ entry->LocalRouting = true;
+ }
+ else
+ {
+ entry->LocalRouting = false;
+ }
+ if (entry->LocalRouting && r->dwForwardProto == 3)
+ {
+ // PPP. Danger!
+ entry->PPPConnection = true;
+ }
+ // Metric
+ entry->Metric = r->dwForwardMetric1;
+ // Interface ID
+ entry->InterfaceID = r->dwForwardIfIndex;
+}
+
+// Initializing the socket library
+void Win32InitSocketLibrary()
+{
+ WSADATA data;
+ Zero(&data, sizeof(data));
+ WSAStartup(MAKEWORD(2, 2), &data);
+
+ // Load the DLL functions
+ w32net = ZeroMalloc(sizeof(NETWORK_WIN32_FUNCTIONS));
+ w32net->hIpHlpApi32 = LoadLibrary("iphlpapi.dll");
+ w32net->hIcmp = LoadLibrary("icmp.dll");
+
+ if (w32net->hIpHlpApi32 != NULL)
+ {
+ w32net->CreateIpForwardEntry =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
+ GetProcAddress(w32net->hIpHlpApi32, "CreateIpForwardEntry");
+
+ w32net->DeleteIpForwardEntry =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
+ GetProcAddress(w32net->hIpHlpApi32, "DeleteIpForwardEntry");
+
+ w32net->GetIfTable =
+ (DWORD (__stdcall *)(PMIB_IFTABLE, PULONG, BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIfTable");
+
+ w32net->GetIfTable2 =
+ (DWORD (__stdcall *)(void **))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIfTable2");
+
+ w32net->FreeMibTable =
+ (void (__stdcall *)(PVOID))
+ GetProcAddress(w32net->hIpHlpApi32, "FreeMibTable");
+
+ w32net->GetIpForwardTable =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDTABLE, PULONG, BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIpForwardTable");
+
+ w32net->GetNetworkParams =
+ (DWORD (__stdcall *)(PFIXED_INFO,PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetNetworkParams");
+
+ w32net->GetAdaptersAddresses =
+ (ULONG (__stdcall *)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersAddresses");
+
+ w32net->IpRenewAddress =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
+ GetProcAddress(w32net->hIpHlpApi32, "IpRenewAddress");
+
+ w32net->IpReleaseAddress =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
+ GetProcAddress(w32net->hIpHlpApi32, "IpReleaseAddress");
+
+ w32net->GetInterfaceInfo =
+ (DWORD (__stdcall *)(PIP_INTERFACE_INFO, PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetInterfaceInfo");
+
+ w32net->GetAdaptersInfo =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INFO, PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersInfo");
+
+ w32net->GetExtendedTcpTable =
+ (DWORD (__stdcall *)(PVOID,PDWORD,BOOL,ULONG,_TCP_TABLE_CLASS,ULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetExtendedTcpTable");
+
+ w32net->AllocateAndGetTcpExTableFromStack =
+ (DWORD (__stdcall *)(PVOID *,BOOL,HANDLE,DWORD,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "AllocateAndGetTcpExTableFromStack");
+
+ w32net->GetTcpTable =
+ (DWORD (__stdcall *)(PMIB_TCPTABLE,PDWORD,BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetTcpTable");
+
+ w32net->NotifyRouteChange =
+ (DWORD (__stdcall *)(PHANDLE,LPOVERLAPPED))
+ GetProcAddress(w32net->hIpHlpApi32, "NotifyRouteChange");
+
+ w32net->CancelIPChangeNotify =
+ (BOOL (__stdcall *)(LPOVERLAPPED))
+ GetProcAddress(w32net->hIpHlpApi32, "CancelIPChangeNotify");
+
+ w32net->NhpAllocateAndGetInterfaceInfoFromStack =
+ (DWORD (__stdcall *)(IP_INTERFACE_NAME_INFO **,PDWORD,BOOL,HANDLE,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "NhpAllocateAndGetInterfaceInfoFromStack");
+
+ w32net->IcmpCreateFile =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpCreateFile");
+
+ w32net->IcmpCloseHandle =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpCloseHandle");
+
+ w32net->IcmpSendEcho =
+ (DWORD (__stdcall *)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpSendEcho");
+ }
+
+ if (w32net->hIcmp != NULL)
+ {
+ if (w32net->IcmpCreateFile == NULL || w32net->IcmpCloseHandle == NULL || w32net->IcmpSendEcho == NULL)
+ {
+ w32net->IcmpCreateFile =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(w32net->hIcmp, "IcmpCreateFile");
+
+ w32net->IcmpCloseHandle =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(w32net->hIcmp, "IcmpCloseHandle");
+
+ w32net->IcmpSendEcho =
+ (DWORD (__stdcall *)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD))
+ GetProcAddress(w32net->hIcmp, "IcmpSendEcho");
+ }
+ }
+
+ if (w32net->IcmpCreateFile == NULL || w32net->IcmpCloseHandle == NULL || w32net->IcmpSendEcho == NULL)
+ {
+ w32net->IcmpCreateFile = NULL;
+ w32net->IcmpCloseHandle = NULL;
+ w32net->IcmpSendEcho = NULL;
+ }
+}
+
+// Release of the socket library
+void Win32FreeSocketLibrary()
+{
+ if (w32net != NULL)
+ {
+ if (w32net->hIpHlpApi32 != NULL)
+ {
+ FreeLibrary(w32net->hIpHlpApi32);
+ }
+
+ if (w32net->hIcmp != NULL)
+ {
+ FreeLibrary(w32net->hIcmp);
+ }
+
+ Free(w32net);
+ w32net = NULL;
+ }
+
+ WSACleanup();
+}
+
+// Cancel
+void Win32Cancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ SetEvent((HANDLE)c->hEvent);
+}
+
+// Cleanup of the cancel object
+void Win32CleanupCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->SpecialFlag == false)
+ {
+ CloseHandle(c->hEvent);
+ }
+
+ Free(c);
+}
+
+// New cancel object
+CANCEL *Win32NewCancel()
+{
+ CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
+ c->ref = NewRef();
+ c->SpecialFlag = false;
+ c->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ return c;
+}
+
+// Waiting for a socket event
+bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ // Validate arguments
+ if (event == NULL || timeout == 0)
+ {
+ return false;
+ }
+
+ if (WaitForSingleObject((HANDLE)event->hEvent, timeout) == WAIT_OBJECT_0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Clean-up of the socket event
+void Win32CleanupSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ CloseHandle((HANDLE)event->hEvent);
+
+ Free(event);
+}
+
+// Set of the socket event
+void Win32SetSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ SetEvent((HANDLE)event->hEvent);
+}
+
+// Creating a socket event
+SOCK_EVENT *Win32NewSockEvent()
+{
+ SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
+
+ e->ref = NewRef();
+ e->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ return e;
+}
+
+// Associate the socket with socket event and set it to asynchronous mode
+void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ HANDLE hEvent;
+ // Validate arguments
+ if (sock == NULL || event == NULL || sock->AsyncMode)
+ {
+ return;
+ }
+ if (sock->ListenMode != false || (sock->Type != SOCK_UDP && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ hEvent = event->hEvent;
+
+ // Association
+ WSAEventSelect(sock->socket, hEvent, FD_READ | FD_WRITE | FD_CLOSE);
+
+ // Increase the reference count of the SOCK_EVENT
+ AddRef(event->ref);
+ sock->SockEvent = event;
+}
+
+// Set the socket to asynchronous mode
+void Win32InitAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->AsyncMode)
+ {
+ // This socket is already in asynchronous mode
+ return;
+ }
+ if (sock->ListenMode || ((sock->Type == SOCK_TCP || sock->Type == SOCK_INPROC) && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ // Fetch the event of the TUBE
+ TUBE *t = sock->RecvTube;
+
+ if (t != NULL)
+ {
+ if (t->SockEvent != NULL)
+ {
+ sock->hEvent = t->SockEvent->hEvent;
+ }
+ }
+ }
+ else
+ {
+ // Creating an Event
+ sock->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Association
+ WSAEventSelect(sock->socket, sock->hEvent, FD_READ | FD_WRITE | FD_CLOSE);
+ }
+}
+
+// Release the asynchronous socket
+void Win32FreeAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ // Asynchronous socket
+ if (sock->hEvent != NULL)
+ {
+ if (sock->Type != SOCK_INPROC)
+ {
+ CloseHandle((HANDLE)sock->hEvent);
+ }
+ }
+ sock->hEvent = NULL;
+ sock->AsyncMode = false;
+
+ // Socket event
+ if (sock->SockEvent != NULL)
+ {
+ ReleaseSockEvent(sock->SockEvent);
+ sock->SockEvent = NULL;
+ }
+}
+
+// Select function for Win32
+void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+ HANDLE array[MAXIMUM_WAIT_OBJECTS];
+ UINT n, i;
+ SOCK *s;
+ // Initialization of array
+ Zero(array, sizeof(array));
+ n = 0;
+
+ // Setting the event array
+ if (set != NULL)
+ {
+ for (i = 0;i < set->NumSocket;i++)
+ {
+ s = set->Sock[i];
+ if (s != NULL)
+ {
+ Win32InitAsyncSocket(s);
+ if (s->hEvent != NULL)
+ {
+ array[n++] = (HANDLE)s->hEvent;
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ array[n++] = (HANDLE)s->BulkRecvTube->SockEvent->hEvent;
+ }
+ }
+ }
+ }
+ if (c1 != NULL && c1->hEvent != NULL)
+ {
+ array[n++] = c1->hEvent;
+ }
+ if (c2 != NULL && c2->hEvent != NULL)
+ {
+ array[n++] = c2->hEvent;
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ if (n == 0)
+ {
+ // Call normal waiting function if no events to wait are registered
+ SleepThread(timeout);
+ }
+ else
+ {
+ // Wait for the event if events are registered at least one
+ if (n == 1)
+ {
+ // Calling a lightweight version If the event is only one
+ WaitForSingleObject(array[0], timeout);
+ }
+ else
+ {
+ // In case of multiple events
+ WaitForMultipleObjects(n, array, false, timeout);
+ }
+ }
+}
+
+#endif // OS_WIN32
+
+// Check whether the IPv6 is supported
+bool IsIPv6Supported()
+{
+#ifdef NO_IPV6
+ return false;
+#else // NO_IPV6
+ SOCKET s;
+
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return false;
+ }
+
+ closesocket(s);
+
+ return true;
+#endif // NO_IPV6
+}
+
+// Get the host name from the host cache
+bool GetHostCache(char *hostname, UINT size, IP *ip)
+{
+ bool ret;
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ LockList(HostCacheList);
+ {
+ HOSTCACHE t, *c;
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ c = Search(HostCacheList, &t);
+ if (c != NULL)
+ {
+ if (IsEmptyStr(c->HostName) == false)
+ {
+ ret = true;
+ StrCpy(hostname, size, c->HostName);
+ }
+ else
+ {
+ ret = true;
+ StrCpy(hostname, size, "");
+ }
+ }
+ }
+ UnlockList(HostCacheList);
+
+ return ret;
+}
+
+// Add to the host name cache
+void AddHostCache(IP *ip, char *hostname)
+{
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return;
+ }
+ if (IsNetworkNameCacheEnabled() == false)
+ {
+ return;
+ }
+
+ LockList(HostCacheList);
+ {
+ HOSTCACHE t, *c;
+ UINT i;
+ LIST *o;
+
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ c = Search(HostCacheList, &t);
+ if (c == NULL)
+ {
+ c = ZeroMalloc(sizeof(HOSTCACHE));
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ Add(HostCacheList, c);
+ }
+
+ StrCpy(c->HostName, sizeof(c->HostName), hostname);
+ c->Expires = Tick64() + (UINT64)EXPIRES_HOSTNAME;
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(HostCacheList);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(HostCacheList, i);
+
+ if (c->Expires <= Tick64())
+ {
+ Add(o, c);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(o, i);
+
+ if (Delete(HostCacheList, c))
+ {
+ Free(c);
+ }
+ }
+
+ ReleaseList(o);
+ }
+ UnlockList(HostCacheList);
+}
+
+// Comparison of host name cache entries
+int CompareHostCache(void *p1, void *p2)
+{
+ HOSTCACHE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(HOSTCACHE **)p1;
+ c2 = *(HOSTCACHE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
+}
+
+// Release of the host name cache
+void FreeHostCache()
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(HostCacheList);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(HostCacheList, i);
+
+ Free(c);
+ }
+
+ ReleaseList(HostCacheList);
+ HostCacheList = NULL;
+}
+
+// Initialization of the host name cache
+void InitHostCache()
+{
+ HostCacheList = NewList(CompareHostCache);
+}
+
+// Add the thread to the thread waiting list
+void AddWaitThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ AddRef(t->ref);
+
+ LockList(WaitThreadList);
+ {
+ Add(WaitThreadList, t);
+ }
+ UnlockList(WaitThreadList);
+}
+
+// Remove the thread from the waiting list
+void DelWaitThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ LockList(WaitThreadList);
+ {
+ if (Delete(WaitThreadList, t))
+ {
+ ReleaseThread(t);
+ }
+ }
+ UnlockList(WaitThreadList);
+}
+
+// Creating a thread waiting list
+void InitWaitThread()
+{
+ WaitThreadList = NewList(NULL);
+}
+
+// Release of the thread waiting list
+void FreeWaitThread()
+{
+ UINT i, num;
+ THREAD **threads;
+
+ LockList(WaitThreadList);
+ {
+ num = LIST_NUM(WaitThreadList);
+ threads = ToArray(WaitThreadList);
+ DeleteAll(WaitThreadList);
+ }
+ UnlockList(WaitThreadList);
+
+ for (i = 0;i < num;i++)
+ {
+ THREAD *t = threads[i];
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+ }
+
+ Free(threads);
+
+ ReleaseList(WaitThreadList);
+ WaitThreadList = NULL;
+}
+
+// Check the cipher list name
+bool CheckCipherListName(char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < cipher_list_token->NumTokens;i++)
+ {
+ if (StrCmpi(cipher_list_token->Token[i], name) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Renewing the IP address of the DHCP server
+void RenewDhcp()
+{
+#ifdef OS_WIN32
+ Win32RenewDhcp();
+#else
+ UnixRenewDhcp();
+#endif
+}
+
+// Get a domain name for UNIX
+bool UnixGetDomainName(char *name, UINT size)
+{
+ bool ret = false;
+ BUF *b = ReadDump("/etc/resolv.conf");
+
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ char *s = CfgReadNextLine(b);
+ TOKEN_LIST *t;
+
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Trim(s);
+
+ t = ParseToken(s, " \t");
+ if (t != NULL)
+ {
+ if (t->NumTokens == 2)
+ {
+ if (StrCmpi(t->Token[0], "domain") == 0)
+ {
+ StrCpy(name, size, t->Token[1]);
+ ret = true;
+ }
+ }
+ FreeToken(t);
+ }
+
+ Free(s);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the domain name
+bool GetDomainName(char *name, UINT size)
+{
+ bool ret = false;
+ IP ip;
+ // Validate arguments
+ ClearStr(name, size);
+ if (name == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ ClearStr(name, size);
+ ret = Win32GetDefaultDns(&ip, name, size);
+
+ if (ret == false || IsEmptyStr(name))
+ {
+ ret = Win32GetDnsSuffix(name, size);
+ }
+#else // OS_WIN32
+ ret = UnixGetDomainName(name, size);
+#endif // OS_WIN32
+
+ if (ret == false)
+ {
+ return false;
+ }
+
+ return (IsEmptyStr(name) ? false : true);
+}
+
+// Get the default DNS server
+bool GetDefaultDns(IP *ip)
+{
+ bool ret = false;
+#ifdef OS_WIN32
+ ret = Win32GetDefaultDns(ip, NULL, 0);
+#else
+ ret = UnixGetDefaultDns(ip);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Creating a socket event
+SOCK_EVENT *NewSockEvent()
+{
+ SOCK_EVENT *e = NULL;
+#ifdef OS_WIN32
+ e = Win32NewSockEvent();
+#else
+ e = UnixNewSockEvent();
+#endif // OS_WIN32
+ return e;
+}
+
+// Set of the socket event
+void SetSockEvent(SOCK_EVENT *event)
+{
+#ifdef OS_WIN32
+ Win32SetSockEvent(event);
+#else
+ UnixSetSockEvent(event);
+#endif // OS_WIN32
+}
+
+// Clean-up of the socket event
+void CleanupSockEvent(SOCK_EVENT *event)
+{
+#ifdef OS_WIN32
+ Win32CleanupSockEvent(event);
+#else
+ UnixCleanupSockEvent(event);
+#endif // OS_WIN32
+}
+
+// Waiting for the socket event
+bool WaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ bool ret = false;
+#ifdef OS_WIN32
+ ret = Win32WaitSockEvent(event, timeout);
+#else
+ ret = UnixWaitSockEvent(event, timeout);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Release of the socket event
+void ReleaseSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ if (Release(event->ref) == 0)
+ {
+ CleanupSockEvent(event);
+ }
+}
+
+// Let belonging the socket to the socket event
+void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (sock == NULL || event == NULL)
+ {
+ return;
+ }
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ // Set the SockEvent on the receiver TUBE for in-process type socket
+ SetTubeSockEvent(sock->RecvTube, event);
+ return;
+ }
+
+ if (sock->BulkRecvTube != NULL)
+ {
+ // Set the SockEvent on the receiver TUBE in case of R-UDP socket
+ SetTubeSockEvent(sock->BulkRecvTube, event);
+ }
+
+#ifdef OS_WIN32
+ Win32JoinSockToSockEvent(sock, event);
+#else
+ UnixJoinSockToSockEvent(sock, event);
+#endif // OS_WIN32
+}
+
+// New special cancel object
+CANCEL *NewCancelSpecial(void *hEvent)
+{
+ CANCEL *c;
+ // Validate arguments
+ if (hEvent == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CANCEL));
+ c->ref = NewRef();
+ c->SpecialFlag = true;
+
+#ifdef OS_WIN32
+ c->hEvent = (HANDLE)hEvent;
+#else // OS_WIN32
+ c->pipe_read = (int)hEvent;
+ c->pipe_write = -1;
+#endif // OS_WIN32
+
+ return c;
+}
+
+// Creating a cancel object
+CANCEL *NewCancel()
+{
+ CANCEL *c = NULL;
+#ifdef OS_WIN32
+ c = Win32NewCancel();
+#else
+ c = UnixNewCancel();
+#endif // OS_WIN32
+ return c;
+}
+
+// Release of the cancel object
+void ReleaseCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ CleanupCancel(c);
+ }
+}
+
+// Clean up of the cancel object
+void CleanupCancel(CANCEL *c)
+{
+#ifdef OS_WIN32
+ Win32CleanupCancel(c);
+#else
+ UnixCleanupCancel(c);
+#endif
+}
+
+// Cancellation triggered
+void Cancel(CANCEL *c)
+{
+#ifdef OS_WIN32
+ Win32Cancel(c);
+#else
+ UnixCancel(c);
+#endif
+}
+
+// Calculate the optimal route from the specified routing table
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip)
+{
+ return GetBestRouteEntryFromRouteTableEx(table, ip, 0);
+}
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id)
+{
+ UINT i;
+ ROUTE_ENTRY *ret = NULL;
+ ROUTE_ENTRY *tmp = NULL;
+ UINT64 min_score = 0;
+ // Validate arguments
+ if (ip == NULL || table == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsIP6(ip))
+ {
+ // IPv6 is not supported
+ return NULL;
+ }
+
+ // Select routing table entry by following rule
+ // 1. Largest subnet mask
+ // 2. Smallest metric value
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+ UINT dest, net, mask;
+
+ dest = IPToUINT(ip);
+ net = IPToUINT(&e->DestIP);
+ mask = IPToUINT(&e->DestMask);
+
+ if (exclude_if_id != 0)
+ {
+ if (e->InterfaceID == exclude_if_id)
+ {
+ continue;
+ }
+ }
+
+ // Mask test
+ if ((dest & mask) == (net & mask))
+ {
+ // Calculate the score
+ UINT score_high32 = mask;
+ UINT score_low32 = 0xFFFFFFFF - e->Metric;
+ UINT64 score64 = (UINT64)score_high32 * (UINT64)0x80000000 * (UINT64)2 + (UINT64)score_low32;
+ if (score64 == 0)
+ {
+ score64 = 1;
+ }
+
+ e->InnerScore = score64;
+ }
+ }
+
+ tmp = NULL;
+
+ // Search for the item with maximum score
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+
+ if (e->InnerScore != 0)
+ {
+ if (e->InnerScore >= min_score)
+ {
+ tmp = e;
+ min_score = e->InnerScore;
+ }
+ }
+ }
+
+ if (tmp != NULL)
+ {
+ UINT dest, gateway, mask;
+
+ // Generate an entry
+ ret = ZeroMallocFast(sizeof(ROUTE_ENTRY));
+
+ Copy(&ret->DestIP, ip, sizeof(IP));
+ ret->DestMask.addr[0] = 255;
+ ret->DestMask.addr[1] = 255;
+ ret->DestMask.addr[2] = 255;
+ ret->DestMask.addr[3] = 255;
+ Copy(&ret->GatewayIP, &tmp->GatewayIP, sizeof(IP));
+ ret->InterfaceID = tmp->InterfaceID;
+ ret->LocalRouting = tmp->LocalRouting;
+ ret->OldIfMetric = tmp->Metric;
+ ret->Metric = 1;
+ ret->PPPConnection = tmp->PPPConnection;
+
+ // Calculation related to routing control
+ dest = IPToUINT(&tmp->DestIP);
+ gateway = IPToUINT(&tmp->GatewayIP);
+ mask = IPToUINT(&tmp->DestMask);
+ if ((dest & mask) == (gateway & mask))
+ {
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Adjust for Windows
+ ret->PPPConnection = true;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ return ret;
+}
+
+// Release the routing entry
+void FreeRouteEntry(ROUTE_ENTRY *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Free(e);
+}
+
+// Get the best route entry by analyzing the current routing table
+ROUTE_ENTRY *GetBestRouteEntry(IP *ip)
+{
+ return GetBestRouteEntryEx(ip, 0);
+}
+ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id)
+{
+ ROUTE_TABLE *table;
+ ROUTE_ENTRY *e = NULL;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ table = GetRouteTable();
+ if (table == NULL)
+ {
+ return NULL;
+ }
+
+ e = GetBestRouteEntryFromRouteTableEx(table, ip, exclude_if_id);
+ FreeRouteTable(table);
+
+ return e;
+}
+
+// Get the interface ID of the virtual LAN card
+UINT GetVLanInterfaceID(char *tag_name)
+{
+ UINT ret = 0;
+#ifdef OS_WIN32
+ ret = Win32GetVLanInterfaceID(tag_name);
+#else // OS_WIN32
+ ret = UnixGetVLanInterfaceID(tag_name);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Release of enumeration variable of virtual LAN card
+void FreeEnumVLan(char **s)
+{
+ char *a;
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ i = 0;
+ while (true)
+ {
+ a = s[i++];
+ if (a == NULL)
+ {
+ break;
+ }
+ Free(a);
+ }
+
+ Free(s);
+}
+
+// Enumeration of virtual LAN cards
+char **EnumVLan(char *tag_name)
+{
+ char **ret = NULL;
+#ifdef OS_WIN32
+ ret = Win32EnumVLan(tag_name);
+#else // OS_WIN32
+ ret = UnixEnumVLan(tag_name);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Display the routing table
+void DebugPrintRouteTable(ROUTE_TABLE *r)
+{
+ UINT i;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ if (IsDebug() == false)
+ {
+ return;
+ }
+
+ Debug("---- Routing Table (%u Entries) ----\n", r->NumEntry);
+
+ for (i = 0;i < r->NumEntry;i++)
+ {
+ Debug(" ");
+
+ DebugPrintRoute(r->Entry[i]);
+ }
+
+ Debug("------------------------------------\n");
+}
+
+// Display the routing table entry
+void DebugPrintRoute(ROUTE_ENTRY *e)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (IsDebug() == false)
+ {
+ return;
+ }
+
+ RouteToStr(tmp, sizeof(tmp), e);
+
+ Debug("%s\n", tmp);
+}
+
+// Convert the routing table entry to string
+void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e)
+{
+ char dest_ip[MAX_PATH];
+ char dest_mask[MAX_PATH];
+ char gateway_ip[MAX_PATH];
+ // Validate arguments
+ if (str == NULL || e == NULL)
+ {
+ return;
+ }
+
+ IPToStr(dest_ip, sizeof(dest_ip), &e->DestIP);
+ IPToStr(dest_mask, sizeof(dest_mask), &e->DestMask);
+ IPToStr(gateway_ip, sizeof(gateway_ip), &e->GatewayIP);
+
+ Format(str, str_size, "%s/%s %s m=%u oif=%u if=%u lo=%u p=%u",
+ dest_ip, dest_mask, gateway_ip,
+ e->Metric, e->OldIfMetric, e->InterfaceID,
+ e->LocalRouting, e->PPPConnection);
+}
+
+// Delete the routing table
+void DeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ Debug("DeleteRouteEntry();\n");
+#ifdef OS_WIN32
+ Win32DeleteRouteEntry(e);
+#else // OS_WIN32
+ UnixDeleteRouteEntry(e);
+#endif
+}
+
+// Add to the routing table
+bool AddRouteEntry(ROUTE_ENTRY *e)
+{
+ bool dummy = false;
+ return AddRouteEntryEx(e, &dummy);
+}
+bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists)
+{
+ bool ret = false;
+ Debug("AddRouteEntryEx();\n");
+#ifdef OS_WIN32
+ ret = Win32AddRouteEntry(e, already_exists);
+#else // OS_WIN32
+ ret = UnixAddRouteEntry(e, already_exists);
+#endif
+ return ret;
+}
+
+// Get the routing table
+ROUTE_TABLE *GetRouteTable()
+{
+ ROUTE_TABLE *t = NULL;
+ UINT i;
+ BUF *buf = NewBuf();
+ UCHAR hash[MD5_SIZE];
+
+#ifdef OS_WIN32
+ t = Win32GetRouteTable();
+#else //OS_WIN32
+ t = UnixGetRouteTable();
+#endif // OS_WIN32
+
+ WriteBuf(buf, &t->NumEntry, sizeof(t->NumEntry));
+
+ for (i = 0;i < t->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = t->Entry[i];
+
+ WriteBuf(buf, e, sizeof(ROUTE_ENTRY));
+ }
+
+ Hash(hash, buf->Buf, buf->Size, false);
+
+ FreeBuf(buf);
+
+ Copy(&t->HashedValue, hash, sizeof(t->HashedValue));
+
+ return t;
+}
+
+// Release of the routing table
+void FreeRouteTable(ROUTE_TABLE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumEntry;i++)
+ {
+ Free(t->Entry[i]);
+ }
+ Free(t->Entry);
+ Free(t);
+}
+
+// UDP receiving
+UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, sz;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreRecvErr = false;
+ }
+ if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return false;
+ }
+
+ if (sock->IPv6)
+ {
+ return RecvFrom6(sock, src_addr, src_port, data, size);
+ }
+
+ s = sock->socket;
+
+ sz = sizeof(addr);
+ ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
+ if (ret > 0)
+ {
+ InAddrToIP(src_addr, &addr.sin_addr);
+ *src_port = (UINT)ntohs(addr.sin_port);
+ if (sock->IsRawSocket)
+ {
+ *src_port = sock->LocalPort;
+/*
+ {
+ char tmp[MAX_SIZE];
+
+ IPToStr(tmp, sizeof(tmp), &sock->LocalIP);
+ Debug("Raw: %u from %s\n", sock->LocalPort, tmp);
+ }*/
+ }
+
+ Lock(sock->lock);
+ {
+ sock->RecvNum++;
+ sock->RecvSize += (UINT64)ret;
+ }
+ Unlock(sock->lock);
+
+ // Debug("UDP RecvFrom: %u\n", ret);
+
+ return (UINT)ret;
+ }
+ else
+ {
+ sock->IgnoreRecvErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+// Debug("RecvFrom Error: %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+}
+UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, sz;
+ struct sockaddr_in6 addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreRecvErr = false;
+ }
+ if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return false;
+ }
+
+ s = sock->socket;
+
+ sz = sizeof(addr);
+ ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
+ if (ret > 0)
+ {
+ InAddrToIP6(src_addr, &addr.sin6_addr);
+ src_addr->ipv6_scope_id = addr.sin6_scope_id;
+ *src_port = (UINT)ntohs(addr.sin6_port);
+ if (sock->IsRawSocket)
+ {
+ *src_port = sock->LocalPort;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->RecvNum++;
+ sock->RecvSize += (UINT64)ret;
+ }
+ Unlock(sock->lock);
+
+ // Debug("UDP RecvFrom: %u\n", ret);
+
+ return (UINT)ret;
+ }
+ else
+ {
+ sock->IgnoreRecvErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ // Debug("RecvFrom Error: %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+}
+
+// Lock the OpenSSL
+void LockOpenSSL()
+{
+ Lock(openssl_lock);
+}
+
+// Unlock the OpenSSL
+void UnlockOpenSSL()
+{
+ Unlock(openssl_lock);
+}
+
+// UDP transmission
+UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
+{
+ return SendToEx(sock, dest_addr, dest_port, data, size, false);
+}
+UINT SendToEx(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast)
+{
+ SOCKET s;
+ int ret;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreSendErr = false;
+ }
+ if (sock == NULL || dest_addr == NULL || (sock->IsRawSocket == false && dest_port == 0) || data == NULL)
+ {
+ return 0;
+ }
+ if (dest_port >= 65536 && sock->IsRawSocket == false)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ return 0;
+ }
+
+ if (sock->IPv6)
+ {
+ return SendTo6Ex(sock, dest_addr, dest_port, data, size, broadcast);
+ }
+
+ if (IsIP4(dest_addr) == false)
+ {
+ return 0;
+ }
+
+ s = sock->socket;
+ Zero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ if (sock->IsRawSocket == false)
+ {
+ addr.sin_port = htons((USHORT)dest_port);
+ }
+ IPToInAddr(&addr.sin_addr, dest_addr);
+
+ if ((dest_addr->addr[0] == 255 && dest_addr->addr[1] == 255 &&
+ dest_addr->addr[2] == 255 && dest_addr->addr[3] == 255) ||
+ (dest_addr->addr[0] >= 224 && dest_addr->addr[0] <= 239)
+ || broadcast)
+ {
+ if (sock->UdpBroadcast == false)
+ {
+ bool yes = true;
+
+ sock->UdpBroadcast = true;
+
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
+ }
+ }
+
+ ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != (int)size)
+ {
+ sock->IgnoreSendErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS || WSAGetLastError() == WSAEINVAL)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ Debug("SendTo Error; %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)size;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+
+ return ret;
+}
+UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
+{
+ return SendTo6Ex(sock, dest_addr, dest_port, data, size, false);
+}
+UINT SendTo6Ex(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast)
+{
+ SOCKET s;
+ int ret;
+ struct sockaddr_in6 addr;
+ UINT type;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreSendErr = false;
+ }
+ if (sock == NULL || dest_addr == NULL || (sock->IsRawSocket == false && dest_port == 0) || data == NULL)
+ {
+ return 0;
+ }
+ if (dest_port >= 65536 && sock->IsRawSocket == false)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ return 0;
+ }
+
+ if (IsIP6(dest_addr) == false)
+ {
+ return 0;
+ }
+
+ s = sock->socket;
+ Zero(&addr, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ if (sock->IsRawSocket == false)
+ {
+ addr.sin6_port = htons((USHORT)dest_port);
+ }
+ IPToInAddr6(&addr.sin6_addr, dest_addr);
+ addr.sin6_scope_id = dest_addr->ipv6_scope_id;
+
+ type = GetIPAddrType6(dest_addr);
+
+ if ((type & IPV6_ADDR_MULTICAST) || broadcast)
+ {
+ if (sock->UdpBroadcast == false)
+ {
+ bool yes = true;
+
+ sock->UdpBroadcast = true;
+
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
+ }
+ }
+
+ ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != (int)size)
+ {
+ sock->IgnoreSendErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS || WSAGetLastError() == WSAEINVAL)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)size;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+
+ return ret;
+}
+
+// Disable the UDP checksum
+void DisableUDPChecksum(SOCK *s)
+{
+ bool true_flag = true;
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_UDP)
+ {
+ return;
+ }
+
+ if (s->socket != INVALID_SOCKET)
+ {
+ if (s->IPv6 == false)
+ {
+#ifdef UDP_NOCHECKSUM
+ setsockopt(s->socket, IPPROTO_UDP, UDP_NOCHECKSUM, (char *)&true_flag, sizeof(bool));
+#endif // UDP_NOCHECKSUM
+ }
+ }
+}
+
+// Set the socket to asynchronous mode
+void InitAsyncSocket(SOCK *sock)
+{
+#ifdef OS_WIN32
+ Win32InitAsyncSocket(sock);
+#else // OS_WIN32
+ UnixInitAsyncSocket(sock);
+#endif // OS_WIN32
+}
+
+// Open a UDP port (port number is random, but determine the randomness in the seed)
+SOCK *NewUDPEx2Rand(bool ipv6, IP *ip, void *rand_seed, UINT rand_seed_size, UINT num_retry)
+{
+ UINT i;
+ // Validate arguments
+ if (rand_seed == NULL || rand_seed_size == 0)
+ {
+ return NULL;
+ }
+ if (num_retry == 0)
+ {
+ num_retry = RAND_UDP_PORT_DEFAULT_NUM_RETRY;
+ }
+
+ for (i = 0; i < (num_retry + 1);i++)
+ {
+ BUF *buf = NewBuf();
+ UCHAR hash[SHA1_SIZE];
+ UINT port = 0;
+ SOCK *s;
+
+ WriteBuf(buf, rand_seed, rand_seed_size);
+ WriteBufInt(buf, i);
+
+ HashSha1(hash, buf->Buf, buf->Size);
+
+ FreeBuf(buf);
+
+ port = READ_UINT(hash);
+
+ port = RAND_UDP_PORT_START + (port % (RAND_UDP_PORT_END - RAND_UDP_PORT_START));
+
+ s = NewUDPEx2(port, ipv6, ip);
+
+ if (s != NULL)
+ {
+ return s;
+ }
+ }
+
+ return NewUDPEx2(0, ipv6, ip);
+}
+
+// Generate a random port number (based on the EXE path and machine key)
+UINT NewRandPortByMachineAndExePath(UINT start_port, UINT end_port, UINT additional_int)
+{
+ BUF *b;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ UCHAR hash[SHA1_SIZE];
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+ WriteBufInt(b, additional_int);
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+
+ return (READ_UINT(hash) % (end_port - start_port)) + start_port;
+}
+
+// Open the UDP port (based on the EXE path and machine key)
+SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR rand_port_id)
+{
+ BUF *b;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ UCHAR hash[SHA1_SIZE];
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+ WriteBufChar(b, rand_port_id);
+ //WriteBufInt(b, GetHostIPAddressHash32());
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+
+ return NewUDPEx2Rand(ipv6, ip, hash, sizeof(hash), num_retry);
+}
+
+// Create and initialize the UDP socket
+// If port is specified as 0, system assigns a certain port.
+SOCK *NewUDP(UINT port)
+{
+ return NewUDPEx(port, false);
+}
+SOCK *NewUDPEx(UINT port, bool ipv6)
+{
+ return NewUDPEx2(port, ipv6, NULL);
+}
+SOCK *NewUDPEx2(UINT port, bool ipv6, IP *ip)
+{
+ if (ipv6 == false)
+ {
+ return NewUDP4(port, ip);
+ }
+ else
+ {
+ return NewUDP6(port, ip);
+ }
+}
+SOCK *NewUDPEx3(UINT port, IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NewUDPEx2(port, false, NULL);
+ }
+
+ if (IsIP4(ip))
+ {
+ return NewUDPEx2(port, false, ip);
+ }
+ else
+ {
+ return NewUDPEx2(port, true, ip);
+ }
+}
+SOCK *NewUDP4(UINT port, IP *ip)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (ip != NULL && IsIP4(ip) == false)
+ {
+ return NULL;
+ }
+
+ if (IS_SPECIAL_PORT(port) == false)
+ {
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ }
+ else
+ {
+ s = socket(AF_INET, SOCK_RAW, GET_SPECIAL_PORT(port));
+ }
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ Zero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+
+ if (ip == NULL || IsZeroIP(ip))
+ {
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ else
+ {
+ IPToInAddr(&addr.sin_addr, ip);
+ }
+
+ if (port == 0 || IS_SPECIAL_PORT(port))
+ {
+ addr.sin_port = 0;
+ }
+ else
+ {
+ addr.sin_port = htons((USHORT)port);
+ }
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ // Failure
+ if (port != 0)
+ {
+ bool true_flag = true;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ bool false_flag = false;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&false_flag, sizeof(bool));
+#ifdef SO_EXCLUSIVEADDRUSE
+ setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&true_flag, sizeof(bool));
+#endif // SO_EXCLUSIVEADDRUSE
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+
+ sock = NewSock();
+
+ sock->Type = SOCK_UDP;
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = false;
+ if (port != 0)
+ {
+ sock->ServerMode = true;
+ }
+
+ sock->socket = s;
+
+ InitUdpSocketBufferSize((int)s);
+
+ if (IS_SPECIAL_PORT(port))
+ {
+ bool no = false;
+ setsockopt(sock->socket, IPPROTO_IP, IP_HDRINCL, (char *)&no, sizeof(no));
+
+ sock->IsRawSocket = true;
+ sock->RawSocketIPProtocol = GET_SPECIAL_PORT(port);
+ }
+
+ QuerySocketInformation(sock);
+
+ return sock;
+}
+SOCK *NewUDP6(UINT port, IP *ip)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct sockaddr_in6 addr;
+ // Validate arguments
+ if (ip != NULL && IsIP6(ip) == false)
+ {
+ return NULL;
+ }
+
+ if (IS_SPECIAL_PORT(port) == false)
+ {
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ }
+ else
+ {
+ s = socket(AF_INET6, SOCK_RAW, GET_SPECIAL_PORT(port));
+ }
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ Zero(&addr, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ if (port == 0)
+ {
+ addr.sin6_port = 0;
+ }
+ else
+ {
+ addr.sin6_port = htons((USHORT)port);
+ }
+
+ if (ip != NULL && IsZeroIP(ip) == false)
+ {
+ IPToInAddr6(&addr.sin6_addr, ip);
+ addr.sin6_scope_id = ip->ipv6_scope_id;
+ }
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ // Failure
+ if (port != 0)
+ {
+ bool true_flag = true;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ bool false_flag = false;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&false_flag, sizeof(bool));
+#ifdef SO_EXCLUSIVEADDRUSE
+ setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&true_flag, sizeof(bool));
+#endif // SO_EXCLUSIVEADDRUSE
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+
+ sock = NewSock();
+
+ sock->Type = SOCK_UDP;
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = false;
+ sock->IPv6 = true;
+ if (port != 0)
+ {
+ sock->ServerMode = true;
+ }
+
+ sock->socket = s;
+
+ InitUdpSocketBufferSize(s);
+
+ if (IS_SPECIAL_PORT(port))
+ {
+ bool no = false;
+#ifdef IPV6_HDRINCL
+ setsockopt(sock->socket, IPPROTO_IP, IPV6_HDRINCL, (char *)&no, sizeof(no));
+#endif // IPV6_HDRINCL
+ setsockopt(sock->socket, IPPROTO_IP, IP_HDRINCL, (char *)&no, sizeof(no));
+
+ sock->IsRawSocket = true;
+ sock->RawSocketIPProtocol = GET_SPECIAL_PORT(port);
+ }
+
+ QuerySocketInformation(sock);
+
+ return sock;
+}
+
+// Select function
+void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+#ifdef OS_WIN32
+ Win32Select(set, timeout, c1, c2);
+#else
+ UnixSelect(set, timeout, c1, c2);
+#endif // OS_WIN32
+}
+
+// Add a socket to the socket set
+void AddSockSet(SOCKSET *set, SOCK *sock)
+{
+ // Validate arguments
+ if (set == NULL || sock == NULL)
+ {
+ return;
+ }
+ if (sock->Type == SOCK_TCP && sock->Connected == false)
+ {
+ return;
+ }
+
+ if (set->NumSocket >= MAX_SOCKSET_NUM)
+ {
+ // Upper limit
+ return;
+ }
+ set->Sock[set->NumSocket++] = sock;
+}
+
+// Initializing the socket set
+void InitSockSet(SOCKSET *set)
+{
+ // Validate arguments
+ if (set == NULL)
+ {
+ return;
+ }
+
+ Zero(set, sizeof(SOCKSET));
+}
+
+// Receive all by TCP
+bool RecvAll(SOCK *sock, void *data, UINT size, bool secure)
+{
+ UINT recv_size, sz, ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return true;
+ }
+ if (sock->AsyncMode)
+ {
+ return false;
+ }
+
+ recv_size = 0;
+
+ while (true)
+ {
+ sz = size - recv_size;
+ ret = Recv(sock, (UCHAR *)data + recv_size, sz, secure);
+ if (ret == 0)
+ {
+ return false;
+ }
+ recv_size += ret;
+ if (recv_size >= size)
+ {
+ return true;
+ }
+ }
+}
+
+// Send the TCP send buffer
+bool SendNow(SOCK *sock, int secure)
+{
+ bool ret;
+ // Validate arguments
+ if (sock == NULL || sock->AsyncMode != false)
+ {
+ return false;
+ }
+ if (sock->SendBuf->Size == 0)
+ {
+ return true;
+ }
+
+ ret = SendAll(sock, sock->SendBuf->Buf, sock->SendBuf->Size, secure);
+ ClearBuf(sock->SendBuf);
+
+ return ret;
+}
+
+// Append to the TCP send buffer
+void SendAdd(SOCK *sock, void *data, UINT size)
+{
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0 || sock->AsyncMode != false)
+ {
+ return;
+ }
+
+ WriteBuf(sock->SendBuf, data, size);
+}
+
+// Send all by TCP
+bool SendAll(SOCK *sock, void *data, UINT size, bool secure)
+{
+ UCHAR *buf;
+ UINT sent_size;
+ UINT ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->AsyncMode)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return true;
+ }
+
+ buf = (UCHAR *)data;
+ sent_size = 0;
+
+ while (true)
+ {
+ ret = Send(sock, buf, size - sent_size, secure);
+ if (ret == 0)
+ {
+ return false;
+ }
+ sent_size += ret;
+ buf += ret;
+ if (sent_size >= size)
+ {
+ return true;
+ }
+ }
+}
+
+// Set the cipher algorithm name to want to use
+void SetWantToUseCipher(SOCK *sock, char *name)
+{
+ // Validate arguments
+ if (sock == NULL || name == NULL)
+ {
+ return;
+ }
+
+ if (sock->WaitToUseCipher)
+ {
+ Free(sock->WaitToUseCipher);
+ }
+ sock->WaitToUseCipher = CopyStr(name);
+}
+
+// Add all the chain certificates in the chain_certs directory
+void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx)
+{
+ wchar_t dirname[MAX_SIZE];
+ wchar_t exedir[MAX_SIZE];
+ DIRLIST *dir;
+
+ // Validate arguments
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ GetExeDirW(exedir, sizeof(exedir));
+
+ CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
+
+ MakeDirExW(dirname);
+
+ dir = EnumDirW(dirname);
+
+ if (dir != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ X *x;
+
+ CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
+
+ x = FileToXW(tmp);
+
+ if (x != NULL)
+ {
+ AddChainSslCert(ctx, x);
+
+ FreeX(x);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+}
+
+// Add the chain certificate
+bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x)
+{
+ bool ret = false;
+ X *x_copy;
+ // Validate arguments
+ if (ctx == NULL || x == NULL)
+ {
+ return ret;
+ }
+
+ x_copy = CloneX(x);
+
+ if (x_copy != NULL)
+ {
+ SSL_CTX_add_extra_chain_cert(ctx, x_copy->x509);
+ x_copy->do_not_free = true;
+
+ ret = true;
+
+ FreeX(x_copy);
+ }
+
+ return ret;
+}
+
+// Start a TCP-SSL communication
+bool StartSSL(SOCK *sock, X *x, K *priv)
+{
+ return StartSSLEx(sock, x, priv, false, 0, NULL);
+}
+bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls, UINT ssl_timeout, char *sni_hostname)
+{
+ X509 *x509;
+ EVP_PKEY *key;
+ UINT prev_timeout = 1024;
+ SSL_CTX *ssl_ctx;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ // Validate arguments
+ if (sock == NULL)
+ {
+ Debug("StartSSL Error: #0\n");
+ return false;
+ }
+ if (sock->Connected && sock->Type == SOCK_INPROC && sock->ListenMode == false)
+ {
+ sock->SecureMode = true;
+ return true;
+ }
+ if (sock->Connected == false || sock->socket == INVALID_SOCKET ||
+ sock->ListenMode != false)
+ {
+ Debug("StartSSL Error: #1\n");
+ return false;
+ }
+ if (x != NULL && priv == NULL)
+ {
+ Debug("StartSSL Error: #2\n");
+ return false;
+ }
+ if (ssl_timeout == 0)
+ {
+ ssl_timeout = TIMEOUT_SSL_CONNECT;
+ }
+
+ if (sock->SecureMode)
+ {
+ //Debug("StartSSL Error: #3\n");
+ // SSL communication has already started
+ return true;
+ }
+
+ Lock(sock->ssl_lock);
+ if (sock->SecureMode)
+ {
+ //Debug("StartSSL Error: #4\n");
+ // SSL communication has already started
+ Unlock(sock->ssl_lock);
+ return true;
+ }
+
+ ssl_ctx = NewSSLCtx();
+
+ Lock(openssl_lock);
+ {
+ if (sock->ServerMode)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method());
+
+ Unlock(openssl_lock);
+ AddChainSslCertOnDirectory(ssl_ctx);
+ Lock(openssl_lock);
+ }
+ else
+ {
+ if (client_tls == false)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, SSLv3_method());
+ }
+ else
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());
+ }
+ }
+ sock->ssl = SSL_new(ssl_ctx);
+ SSL_set_fd(sock->ssl, (int)sock->socket);
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if (sock->ServerMode == false && client_tls)
+ {
+ if (IsEmptyStr(sni_hostname) == false)
+ {
+ // Set the SNI host name
+ SSL_set_tlsext_host_name(sock->ssl, sni_hostname);
+ }
+ }
+#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
+ }
+ Unlock(openssl_lock);
+
+ if (x != NULL)
+ {
+ // Check the certificate and the private key
+ if (CheckXandK(x, priv))
+ {
+ // Use the certificate
+ x509 = x->x509;
+ key = priv->pkey;
+
+ Lock(openssl_lock);
+ {
+ SSL_use_certificate(sock->ssl, x509);
+ SSL_use_PrivateKey(sock->ssl, key);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+
+ if (sock->WaitToUseCipher != NULL)
+ {
+ // Set the cipher algorithm name to want to use
+ Lock(openssl_lock);
+ {
+ SSL_set_cipher_list(sock->ssl, sock->WaitToUseCipher);
+ }
+ Unlock(openssl_lock);
+ }
+
+ if (sock->ServerMode)
+ {
+// Lock(ssl_connect_lock);
+
+// Run the time-out thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ // Server mode
+ if (SSL_accept(sock->ssl) <= 0)
+ {
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+ // Unlock(ssl_connect_lock);
+ // SSL-Accept failure
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ sock->ssl = NULL;
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+ Debug("StartSSL Error: #5\n");
+ FreeSSLCtx(ssl_ctx);
+ return false;
+ }
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+#ifdef TLSEXT_NAMETYPE_host_name
+ if (true)
+ {
+ // Get the SNI host name
+ const char *sni_recv_hostname = SSL_get_servername(sock->ssl, TLSEXT_NAMETYPE_host_name);
+
+ if (IsEmptyStr((char *)sni_recv_hostname) == false)
+ {
+ StrCpy(sock->SniHostname, sizeof(sock->SniHostname), (char *)sni_recv_hostname);
+ }
+ }
+#endif // TLSEXT_NAMETYPE_host_name
+#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+ // Unlock(ssl_connect_lock);
+ }
+ else
+ {
+ prev_timeout = GetTimeout(sock);
+ SetTimeout(sock, ssl_timeout);
+ Lock(ssl_connect_lock);
+ // Client mode
+ if (SSL_connect(sock->ssl) <= 0)
+ {
+ Unlock(ssl_connect_lock);
+ // SSL-connect failure
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ sock->ssl = NULL;
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+ Debug("StartSSL Error: #5\n");
+ SetTimeout(sock, prev_timeout);
+ FreeSSLCtx(ssl_ctx);
+ return false;
+ }
+ Unlock(ssl_connect_lock);
+ SetTimeout(sock, prev_timeout);
+ }
+
+ // SSL communication is initiated
+ sock->SecureMode = true;
+
+ // Get the certificate of the remote host
+ Lock(openssl_lock);
+ {
+ x509 = SSL_get_peer_certificate(sock->ssl);
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ // The certificate does not exist on the remote host
+ sock->RemoteX = NULL;
+ }
+ else
+ {
+ // Got a certificate
+ sock->RemoteX = X509ToX(x509);
+ }
+
+ // Get the certificate of local host
+ Lock(openssl_lock);
+ {
+ x509 = SSL_get_certificate(sock->ssl);
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ // The certificate does not exist on the remote host
+ sock->LocalX = NULL;
+ }
+ else
+ {
+ X *local_x;
+ // Got a certificate
+ local_x = X509ToX(x509);
+ local_x->do_not_free = true;
+ sock->LocalX = CloneX(local_x);
+ FreeX(local_x);
+ }
+
+ // Automatic retry mode
+ SSL_set_mode(sock->ssl, SSL_MODE_AUTO_RETRY);
+
+ // Strange flag
+ SSL_set_mode(sock->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ sock->ssl_ctx = ssl_ctx;
+
+ // Get the algorithm name used to encrypt
+ Lock(openssl_lock);
+ {
+ sock->CipherName = CopyStr((char *)SSL_get_cipher(sock->ssl));
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+
+ return true;
+}
+
+// Set the flag to indicate that the socket doesn't require reading
+void SetNoNeedToRead(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ sock->NoNeedToRead = true;
+}
+
+// TCP-SSL receive
+UINT SecureRecv(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, e = 0;
+ SSL *ssl;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ s = sock->socket;
+ ssl = sock->ssl;
+
+ if (sock->AsyncMode)
+ {
+ // Confirm whether the data is readable even 1 byte in the case of asynchronous mode.
+ // To read data results blocking, if there is no readable data.
+ // We must avoid blocking.
+ char c;
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ ret = SSL_peek(ssl, &c, sizeof(c));
+ }
+ Unlock(sock->ssl_lock);
+ if (ret == 0)
+ {
+ // The communication have been disconnected
+ Disconnect(sock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ if (ret < 0)
+ {
+ // An error has occurred
+ e = SSL_get_error(ssl, ret);
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ // Packet has not arrived yet, that is not to be read
+ return SOCK_LATER;
+ }
+ }
+ }
+
+ // Receive
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = pthread_self();
+ }
+#endif // OS_UNIX
+
+// Run the time-out thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ ret = SSL_read(ssl, data, size);
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = 0;
+ }
+#endif // OS_UNIX
+
+ if (ret < 0)
+ {
+ e = SSL_get_error(ssl, ret);
+ }
+
+ }
+ Unlock(sock->ssl_lock);
+ if (ret > 0)
+ {
+ // Successful reception
+ sock->RecvSize += (UINT64)ret;
+ sock->RecvNum++;
+ return (UINT)ret;
+ }
+ if (ret == 0)
+ {
+ // Disconnect the communication
+ Disconnect(sock);
+ //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ if (sock->AsyncMode)
+ {
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ // Packet has not yet arrived
+ return SOCK_LATER;
+ }
+ }
+ Disconnect(sock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+}
+
+// TCP-SSL transmission
+UINT SecureSend(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, e;
+ SSL *ssl;
+ s = sock->socket;
+ ssl = sock->ssl;
+
+ if (sock->AsyncMode)
+ {
+ // Asynchronous mode
+ SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ }
+
+ // Transmission
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+
+ ret = SSL_write(ssl, data, size);
+ if (ret < 0)
+ {
+ e = SSL_get_error(ssl, ret);
+ }
+ }
+ Unlock(sock->ssl_lock);
+
+ if (ret > 0)
+ {
+ // Successful transmission
+ sock->SendSize += (UINT64)ret;
+ sock->SendNum++;
+ sock->WriteBlocked = false;
+ return (UINT)ret;
+ }
+ if (ret == 0)
+ {
+ // Disconnect
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ Disconnect(sock);
+ return 0;
+ }
+
+ if (sock->AsyncMode)
+ {
+ // Confirmation of the error value
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+ Debug("%s %u e=%u\n", __FILE__, __LINE__, e);
+ }
+ //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ Disconnect(sock);
+ return 0;
+}
+
+// Peep the TCP
+UINT Peek(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret;
+
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (sock->AsyncMode)
+ {
+ return 0;
+ }
+
+ // Receive
+ s = sock->socket;
+
+ ret = recv(s, data, size, MSG_PEEK);
+
+ //Debug("Peek: %u\n", ret);
+
+ if (ret > 0)
+ {
+ return ret;
+ }
+
+ return 0;
+}
+
+// TCP receive
+UINT Recv(SOCK *sock, void *data, UINT size, bool secure)
+{
+ SOCKET s;
+ int ret;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ sock->NoNeedToRead = false;
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ return RecvInProc(sock, data, size);
+ }
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (secure != false && sock->SecureMode == false)
+ {
+ return 0;
+ }
+
+ if (secure)
+ {
+ return SecureRecv(sock, data, size);
+ }
+
+ // Receive
+ s = sock->socket;
+
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = pthread_self();
+ }
+#endif // OS_UNIX
+
+// Start of the timeout thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ ret = recv(s, data, size, 0);
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = 0;
+ }
+#endif // OS_UNIX
+
+ if (ret > 0)
+ {
+ // Successful reception
+ Lock(sock->lock);
+ {
+ sock->RecvSize += (UINT64)ret;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+ return (UINT)ret;
+ }
+
+ // Transmission failure
+ if (sock->AsyncMode)
+ {
+ // In asynchronous mode, examine the error
+ if (ret == SOCKET_ERROR)
+ {
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ // In blocking
+ return SOCK_LATER;
+ }
+ else
+ {
+ //Debug("Socket Error: %u\n", WSAGetLastError());
+ }
+#else // OS_WIN32
+ if (errno == EAGAIN)
+ {
+ // In blocking
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ // Disconnected
+ Disconnect(sock);
+ return 0;
+}
+
+// TCP transmission
+UINT Send(SOCK *sock, void *data, UINT size, bool secure)
+{
+ SOCKET s;
+ int ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return SendInProc(sock, data, size);
+ }
+ size = MIN(size, MAX_SEND_BUF_MEM_SIZE);
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (secure != false && sock->SecureMode == false)
+ {
+ return 0;
+ }
+
+ if (secure)
+ {
+ return SecureSend(sock, data, size);
+ }
+
+ // Transmission
+ s = sock->socket;
+ ret = send(s, data, size, 0);
+ if (ret > 0)
+ {
+ // Successful transmission
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)ret;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+ sock->WriteBlocked = false;
+ return (UINT)ret;
+ }
+
+ // Transmission failure
+ if (sock->AsyncMode)
+ {
+ // In asynchronous mode, examine the error
+ if (ret == SOCKET_ERROR)
+ {
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ // In blocking
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+ else
+ {
+ //Debug("Socket Error: %u\n", WSAGetLastError());
+ }
+#else // OS_WIN32
+ if (errno == EAGAIN)
+ {
+ // In blocking
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ // Disconnected
+ Disconnect(sock);
+ return 0;
+}
+
+// Get the time-out value (in milliseconds)
+UINT GetTimeout(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return INFINITE;
+ }
+ if (sock->Type != SOCK_TCP && sock->Type != SOCK_INPROC)
+ {
+ return INFINITE;
+ }
+
+ return sock->TimeOut;
+}
+
+// Setting the time-out value (in milliseconds)
+void SetTimeout(SOCK *sock, UINT timeout)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->Type == SOCK_UDP)
+ {
+ return;
+ }
+
+ if (timeout == INFINITE)
+ {
+ timeout = TIMEOUT_INFINITE;
+ }
+
+ sock->TimeOut = timeout;
+
+// Debug("SetTimeout(%u)\n",timeout);
+
+ if (sock->Type != SOCK_INPROC)
+ {
+#ifdef OS_WIN32
+ setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(UINT));
+ setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(UINT));
+#endif
+
+#ifdef OS_UNIX
+#ifndef UNIX_SOLARIS
+ {
+ struct timeval tv_timeout;
+
+ tv_timeout.tv_sec = timeout / 1000; // miliseconds to seconds
+ tv_timeout.tv_usec = (timeout % 1000) * 1000; // miliseconds to microseconds
+
+ setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
+ setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
+ }
+#endif // UNIX_SOLARIS
+#endif // OS_UNIX
+ }
+}
+
+// Initialize the connection acceptance
+void AcceptInit(SOCK *s)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ if (GetHostName(tmp, sizeof(tmp), &s->RemoteIP) == false ||
+ IsEmptyStr(tmp))
+ {
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+ }
+
+ if (s->RemoteHostname != NULL)
+ {
+ Free(s->RemoteHostname);
+ }
+
+ s->RemoteHostname = CopyStr(tmp);
+}
+
+// TCP connection acceptance (IPv4)
+SOCK *Accept(SOCK *sock)
+{
+ SOCK *ret;
+ SOCKET s, new_socket;
+ int size;
+ struct sockaddr_in addr;
+ bool true_flag = true;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return AcceptInProc(sock);
+ }
+ if (sock->Type == SOCK_REVERSE_LISTEN)
+ {
+ return AcceptReverse(sock);
+ }
+ if (sock->Type == SOCK_RUDP_LISTEN)
+ {
+ return AcceptRUDP(sock);
+ }
+ if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
+ {
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ return NULL;
+ }
+ if (sock->IPv6)
+ {
+ return Accept6(sock);
+ }
+
+ s = sock->socket;
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+ Zero(&addr, sizeof(addr));
+ size = sizeof(addr);
+
+#ifdef OS_UNIX
+#ifdef UNIX_LINUX
+ UnixIgnoreSignalForThread(SIGUSR1);
+#endif // UNIX_LINUX
+ sock->CallingThread = pthread_self();
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ if (sock->EnableConditionalAccept)
+ {
+ new_socket = Win32Accept(sock, s, (struct sockaddr *)&addr,(int *)&size, false);
+ }
+ else
+ {
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+ }
+#else // OS_WIN32
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+ sock->CallingThread = 0;
+#endif // OS_UNIX
+
+ if (new_socket == INVALID_SOCKET)
+ {
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ }
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ closesocket(new_socket);
+ return NULL;
+ }
+
+ ret = NewSock();
+ ret->socket = new_socket;
+ ret->Connected = true;
+ ret->AsyncMode = false;
+ ret->Type = SOCK_TCP;
+ ret->ServerMode = true;
+ ret->SecureMode = false;
+
+ // Configuring the TCP options
+ setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialization of the time-out value
+ SetTimeout(ret, TIMEOUT_INFINITE);
+
+ // Socket information
+ QuerySocketInformation(ret);
+
+ if (IsLocalHostIP(&ret->RemoteIP) == false)
+ {
+ ret->IpClientAdded = true;
+ AddIpClient(&ret->RemoteIP);
+ }
+
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, false) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, false);
+ }
+ }
+
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NATIVE_V4);
+
+ return ret;
+}
+
+// TCP connection acceptance (IPv6)
+SOCK *Accept6(SOCK *sock)
+{
+ SOCK *ret;
+ SOCKET s, new_socket;
+ int size;
+ struct sockaddr_in6 addr;
+ bool true_flag = true;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
+ {
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ return NULL;
+ }
+ if (sock->IPv6 == false)
+ {
+ return NULL;
+ }
+
+ s = sock->socket;
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+ Zero(&addr, sizeof(addr));
+ size = sizeof(addr);
+
+#ifdef OS_UNIX
+#ifdef UNIX_LINUX
+ UnixIgnoreSignalForThread(SIGUSR1);
+#endif // UNIX_LINUX
+ sock->CallingThread = pthread_self();
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ if (sock->EnableConditionalAccept)
+ {
+ new_socket = Win32Accept(sock, s, (struct sockaddr *)&addr,(int *)&size, true);
+ }
+ else
+ {
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+ }
+#else // OS_WIN32
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+ sock->CallingThread = 0;
+#endif // OS_UNIX
+
+ if (new_socket == INVALID_SOCKET)
+ {
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ }
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ closesocket(new_socket);
+ return NULL;
+ }
+
+ ret = NewSock();
+ ret->socket = new_socket;
+ ret->Connected = true;
+ ret->AsyncMode = false;
+ ret->Type = SOCK_TCP;
+ ret->ServerMode = true;
+ ret->SecureMode = false;
+
+ // Configuring the TCP options
+ setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialize the time-out value
+ SetTimeout(ret, TIMEOUT_INFINITE);
+
+ // Socket information
+ QuerySocketInformation(ret);
+
+ if (IsLocalHostIP(&ret->RemoteIP) == false)
+ {
+ ret->IpClientAdded = true;
+ AddIpClient(&ret->RemoteIP);
+ }
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, true) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, true);
+ }
+ }
+
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NATIVE_V6);
+
+ return ret;
+}
+
+// Standby for TCP (IPv6)
+SOCK *Listen6(UINT port)
+{
+ return ListenEx6(port, false);
+}
+SOCK *ListenEx6(UINT port, bool local_only)
+{
+ return ListenEx62(port, local_only, false);
+}
+SOCK *ListenEx62(UINT port, bool local_only, bool enable_ca)
+{
+ SOCKET s;
+ SOCK *sock;
+ struct sockaddr_in6 addr;
+ struct in6_addr in;
+ bool true_flag = true;
+ bool disable_conditional_accept = false;
+ IP localhost;
+ UINT backlog = SOMAXCONN;
+ // Validate arguments
+ if (port == 0 || port >= 65536)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Disable the Conditional Accept due to a bug in Windows
+ enable_ca = false;
+ }
+#endif // OS_WIN32
+
+ // Initialization
+ Zero(&addr, sizeof(addr));
+ Zero(&in, sizeof(in));
+ GetLocalHostIP6(&localhost);
+
+ addr.sin6_port = htons((UINT)port);
+ addr.sin6_family = AF_INET6;
+
+ if (local_only)
+ {
+ IPToInAddr6(&addr.sin6_addr, &localhost);
+
+ enable_ca = false;
+ }
+
+ // Creating a socket
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+#ifdef OS_UNIX
+ // It is necessary to set the IPv6 Only flag on a UNIX system
+ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));
+#endif // OS_UNIX
+
+ //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
+
+#ifdef OS_UNIX
+ // This only have enabled for UNIX system since there is a bug
+ // in the implementation of REUSEADDR in Windows OS
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+#endif // OS_UNIX
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) != 0)
+ {
+ // Bind failure
+ closesocket(s);
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (enable_ca)
+ {
+ if (MsIsWinXPOrGreater())
+ {
+ setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(bool));
+
+ backlog = 1;
+ }
+ }
+#endif // OS_WIN32
+
+ if (listen(s, backlog))
+ {
+ // Listen failure
+ closesocket(s);
+ return NULL;
+ }
+
+ // Success
+ sock = NewSock();
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = true;
+ sock->Type = SOCK_TCP;
+ sock->socket = s;
+ sock->ListenMode = true;
+ sock->SecureMode = false;
+ sock->LocalPort = port;
+ sock->IPv6 = true;
+ sock->LocalOnly = local_only;
+ sock->EnableConditionalAccept = enable_ca;
+
+ return sock;
+}
+
+// Standby for the TCP
+SOCK *Listen(UINT port)
+{
+ return ListenEx(port, false);
+}
+SOCK *ListenEx(UINT port, bool local_only)
+{
+ return ListenEx2(port, local_only, false);
+}
+SOCK *ListenEx2(UINT port, bool local_only, bool enable_ca)
+{
+ SOCKET s;
+ SOCK *sock;
+ struct sockaddr_in addr;
+ struct in_addr in;
+ bool true_flag = true;
+ IP localhost;
+ UINT backlog = SOMAXCONN;
+ // Validate arguments
+ if (port == 0 || port >= 65536)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Disable the Conditional Accept due to a bug in Windows
+ enable_ca = false;
+ }
+#endif // OS_WIN32
+
+ // Initialization
+ Zero(&addr, sizeof(addr));
+ Zero(&in, sizeof(in));
+ SetIP(&localhost, 127, 0, 0, 1);
+
+ addr.sin_port = htons((UINT)port);
+ *((UINT *)&addr.sin_addr) = htonl(INADDR_ANY);
+ addr.sin_family = AF_INET;
+
+ if (local_only)
+ {
+ IPToInAddr(&addr.sin_addr, &localhost);
+
+ enable_ca = false;
+ }
+
+ // Creating a socket
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
+
+#ifdef OS_UNIX
+ // This only have enabled for UNIX system since there is a bug
+ // in the implementation of REUSEADDR in Windows OS
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+#endif // OS_UNIX
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
+ {
+ // Bind failure
+ closesocket(s);
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (enable_ca)
+ {
+ if (MsIsWinXPOrGreater())
+ {
+ setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(bool));
+
+ backlog = 1;
+ }
+ }
+#endif // OS_WIN32
+
+ if (listen(s, backlog))
+ {
+ // Listen failure
+ closesocket(s);
+ return NULL;
+ }
+
+ // Success
+ sock = NewSock();
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = true;
+ sock->Type = SOCK_TCP;
+ sock->socket = s;
+ sock->ListenMode = true;
+ sock->SecureMode = false;
+ sock->LocalPort = port;
+ sock->LocalOnly = local_only;
+ sock->EnableConditionalAccept = enable_ca;
+
+ return sock;
+}
+
+// TCP disconnect
+void Disconnect(SOCK *sock)
+{
+ SOCKET s;
+ bool true_flag = true;
+ bool false_flag = false;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ sock->Disconnecting = true;
+
+#ifdef OS_UNIX
+ UnixFreeAsyncSocket(sock);
+#endif // UnixFreeAsyncSocket
+
+ if (sock->Type == SOCK_TCP && sock->ListenMode)
+ {
+ bool no_tcp_check_port = false;
+
+ // Connect to localhost if the socket is in listening
+ sock->CancelAccept = true;
+
+#ifdef UNIX_LINUX
+ {
+ pthread_t t = sock->CallingThread;
+
+ // Send a signal to the socket to abort accept() forcibly on Linux
+ if (t != 0)
+ {
+ pthread_kill(t, SIGUSR1);
+
+ SleepThread(200);
+ }
+ }
+#endif // UNIX_LINUX
+
+#ifdef OS_WIN32
+ if (sock->hAcceptEvent != NULL)
+ {
+ SetEvent(sock->hAcceptEvent);
+
+ no_tcp_check_port = true;
+ }
+#endif // OS_WIN32
+
+ if (sock->AcceptCanceled == false)
+ {
+ if (no_tcp_check_port == false)
+ {
+ if (sock->IPv6 == false)
+ {
+ CheckTCPPort("127.0.0.1", sock->LocalPort);
+ }
+ else
+ {
+ CheckTCPPort("::1", sock->LocalPort);
+ }
+ }
+ }
+ }
+
+ Lock(disconnect_function_lock);
+
+ Lock(sock->disconnect_lock);
+
+ if (sock->Type == SOCK_TCP)
+ {
+ if (sock->socket != INVALID_SOCKET)
+ {
+ // Forced disconnection flag
+ #ifdef SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
+ #else // SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
+ #endif // SO_DONTLINGER
+// setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ }
+
+ // TCP socket
+ Lock(sock->lock);
+ {
+ if (sock->socket == INVALID_SOCKET)
+ {
+ Unlock(sock->lock);
+ Unlock(sock->disconnect_lock);
+ Unlock(disconnect_function_lock);
+ return;
+ }
+ s = sock->socket;
+
+ if (sock->Connected)
+ {
+ struct linger ling;
+ Zero(&ling, sizeof(ling));
+
+
+#if 0
+ // SSL disconnect
+ Lock(sock->ssl_lock);
+ {
+ if (sock->SecureMode)
+ {
+ SSL_shutdown(sock->ssl);
+ }
+ }
+ Unlock(sock->ssl_lock);
+#endif
+ // Disconnect
+ shutdown(s, 2);
+ }
+
+ // Close the socket
+ closesocket(s);
+
+#ifdef OS_UNIX
+#ifdef FIX_SSL_BLOCKING
+ if (sock->CallingThread != NULL)
+ {
+ pthread_kill(sock->CallingThread, 64);
+ }
+#endif // FIX_SSL_BLOCKING
+#endif // OS_UNIX
+
+ // Release the SSL
+ Lock(sock->ssl_lock);
+ {
+ if (sock->SecureMode)
+ {
+ if (sock->ssl != NULL)
+ {
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ FreeSSLCtx(sock->ssl_ctx);
+ }
+ Unlock(openssl_lock);
+ sock->ssl = NULL;
+ sock->ssl_ctx = NULL;
+ }
+ sock->Connected = false;
+ // Release the certificate
+ if (sock->RemoteX != NULL)
+ {
+ FreeX(sock->RemoteX);
+ sock->RemoteX = NULL;
+ }
+ if (sock->LocalX != NULL)
+ {
+ FreeX(sock->LocalX);
+ sock->LocalX = NULL;
+ }
+
+ // Cipher algorithm name
+ if (sock->CipherName != NULL)
+ {
+ Free(sock->CipherName);
+ sock->CipherName = NULL;
+ }
+ sock->SecureMode = false;
+ }
+ }
+ Unlock(sock->ssl_lock);
+
+ // Initialization
+ sock->socket = INVALID_SOCKET;
+ sock->Type = 0;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+
+ if (sock->IpClientAdded)
+ {
+ DelIpClient(&sock->RemoteIP);
+ sock->IpClientAdded = false;
+ }
+ }
+ Unlock(sock->lock);
+
+ if (sock->BulkSendTube != NULL)
+ {
+ TubeDisconnect(sock->BulkSendTube);
+ }
+
+ if (sock->BulkRecvTube != NULL)
+ {
+ TubeDisconnect(sock->BulkRecvTube);
+ }
+ }
+ else if (sock->Type == SOCK_UDP)
+ {
+ // UDP socket
+ Lock(sock->lock);
+ {
+ if (sock->socket == INVALID_SOCKET)
+ {
+ Unlock(sock->lock);
+ Unlock(sock->disconnect_lock);
+ Unlock(disconnect_function_lock);
+ return;
+ }
+
+ s = sock->socket;
+
+ // Close the socket
+ closesocket(s);
+
+ // Initialization
+ sock->socket = INVALID_SOCKET;
+ sock->Type = 0;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+ }
+ Unlock(sock->lock);
+ }
+ else if (sock->Type == SOCK_INPROC)
+ {
+ // In-process socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->InProcAcceptEvent);
+
+ LockQueue(sock->InProcAcceptQueue);
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(sock->InProcAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+ }
+ UnlockQueue(sock->InProcAcceptQueue);
+ }
+ else
+ {
+ // Disconnect the Tube
+ TubeDisconnect(sock->SendTube);
+ TubeDisconnect(sock->RecvTube);
+
+ sock->socket = INVALID_SOCKET;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+ }
+ }
+ else if (sock->Type == SOCK_RUDP_LISTEN)
+ {
+ // RUDP Listen socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->R_UDP_Stack->NewSockConnectEvent);
+
+ sock->R_UDP_Stack->Halt = true;
+ Set(sock->R_UDP_Stack->HaltEvent);
+ SetSockEvent(sock->R_UDP_Stack->SockEvent);
+ }
+ }
+ else if (sock->Type == SOCK_REVERSE_LISTEN)
+ {
+ // Reverse Listen socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->ReverseAcceptEvent);
+
+ LockQueue(sock->ReverseAcceptQueue);
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(sock->ReverseAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+ }
+ UnlockQueue(sock->ReverseAcceptQueue);
+ }
+ }
+ Unlock(sock->disconnect_lock);
+
+ Unlock(disconnect_function_lock);
+}
+
+typedef struct TCP_PORT_CHECK
+{
+ REF *ref;
+ char hostname[MAX_SIZE];
+ UINT port;
+ bool ok;
+} TCP_PORT_CHECK;
+
+// The thread to check the TCP port
+void CheckTCPPortThread(THREAD *thread, void *param)
+{
+ TCP_PORT_CHECK *c;
+ SOCK *s;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ c = (TCP_PORT_CHECK *)param;
+ AddRef(c->ref);
+ NoticeThreadInit(thread);
+
+ AddWaitThread(thread);
+
+ s = Connect(c->hostname, c->port);
+ if (s != NULL)
+ {
+ c->ok = true;
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ Free(c);
+ }
+
+ DelWaitThread(thread);
+}
+
+// Check whether the TCP port can be connected
+bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout)
+{
+ SOCK *s;
+ // Validate arguments
+ if (hostname == NULL || port == 0 || port >= 65536)
+ {
+ return false;
+ }
+
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ s = ConnectEx(hostname, port, timeout);
+ if (s == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ return true;
+ }
+}
+bool CheckTCPPort(char *hostname, UINT port)
+{
+ return CheckTCPPortEx(hostname, port, TIMEOUT_TCP_PORT_CHECK);
+}
+
+#ifdef OS_UNIX
+// Connection with timeout (UNIX version)
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
+{
+ SOCKSET set;
+ bool ok = false;
+ UINT64 start_time;
+ // Validate arguments
+ if (s == INVALID_SOCKET || addr == NULL)
+ {
+ return -1;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ UnixSetSocketNonBlockingMode(s, true);
+
+ start_time = Tick64();
+
+ while (true)
+ {
+ int ret;
+ ret = connect(s, addr, size);
+ if (ret == 0 || errno == EISCONN)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ if (((start_time + (UINT64)timeout) <= Tick64()) || (errno != EAGAIN && errno != EINPROGRESS && errno != EALREADY))
+ {
+ // Failure
+ break;
+ }
+ else if (*cancel_flag)
+ {
+ // Cancel
+ break;
+ }
+ else
+ {
+ // Connecting
+ SleepThread(50);
+ UnixSelectInner(1, (UINT *)&s, 1, (UINT *)&s, 100);
+ }
+ }
+ }
+
+ UnixSetSocketNonBlockingMode(s, false);
+
+ if (ok)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+#else
+// Connection with timeout (Win32 version)
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
+{
+ UINT64 start_time;
+ bool ok = false;
+ bool timeouted = false;
+ WSAEVENT hEvent;
+ UINT zero = 0;
+ UINT tmp = 0;
+ UINT ret_size = 0;
+ bool is_nt = false;
+ // Validate arguments
+ if (s == INVALID_SOCKET || addr == NULL)
+ {
+ return -1;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ is_nt = OS_IS_WINDOWS_NT(GetOsInfo()->OsType);
+
+ // Create an event
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Associate the socket with the event
+ WSAEventSelect(s, hEvent, FD_CONNECT);
+
+ start_time = Tick64();
+
+ while (true)
+ {
+ int ret;
+
+ ret = connect(s, addr, size);
+
+ if (ret == 0)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ int err = WSAGetLastError();
+ //Debug("err=%u\n", err);
+ //Debug("cancel_flag=%u\n", *cancel_flag);
+ if (timeouted && ((err == WSAEALREADY) || (err == WSAEWOULDBLOCK && !is_nt)))
+ {
+ // Time-out
+ ok = false;
+ break;
+ }
+ if (*cancel_flag)
+ {
+ // Cancel
+ ok = false;
+ break;
+ }
+ if (err == WSAEISCONN || (err == WSAEINVAL && is_nt))
+ {
+ ok = true;
+ break;
+ }
+ if (((start_time + (UINT64)timeout) <= Tick64()) || (err != WSAEWOULDBLOCK && err != WSAEALREADY && (is_nt || err != WSAEINVAL)))
+ {
+ // Failure (timeout)
+ break;
+ }
+ else
+ {
+ SleepThread(10);
+ // Connecting
+ if (WaitForSingleObject(hEvent, 100) == WAIT_OBJECT_0)
+ {
+ timeouted = true;
+ }
+ }
+ }
+ }
+
+ // Remove the socket from the event
+ WSAEventSelect(s, hEvent, 0);
+
+ // Restore to synchronized socket
+ WSAIoctl(s, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);
+
+ // Close the event
+ CloseHandle(hEvent);
+
+ if (ok)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+#endif // OS_UNIX
+
+// Set the TOS value of the socket
+void SetSockTos(SOCK *s, int tos)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->CurrentTos == tos)
+ {
+ return;
+ }
+
+#ifdef IP_TOS
+ setsockopt(s->socket, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int));
+#endif // IP_TOS
+
+ s->CurrentTos = tos;
+}
+
+// Set the priority of the socket
+void SetSockHighPriority(SOCK *s, bool flag)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SetSockTos(s, (flag ? 16 : 0));
+}
+
+// Connect to the IPv4 host using a socket
+SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag)
+{
+ SOCKET s;
+ struct sockaddr_in sockaddr4;
+ struct in_addr addr4;
+
+ Zero(&sockaddr4, sizeof(sockaddr4));
+ Zero(&addr4, sizeof(addr4));
+
+ // Generate a sockaddr_in
+ IPToInAddr(&addr4, ip);
+ sockaddr4.sin_port = htons((USHORT)port);
+ sockaddr4.sin_family = AF_INET;
+ sockaddr4.sin_addr.s_addr = addr4.s_addr;
+
+ // Socket creation
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s != INVALID_SOCKET)
+ {
+ // Connection
+ if (connect_timeout(s, (struct sockaddr *)&sockaddr4, sizeof(struct sockaddr_in), timeout, cancel_flag) != 0)
+ {
+ // Connection failure
+ closesocket(s);
+ s = INVALID_SOCKET;
+ }
+ }
+
+ return s;
+}
+
+// Identify whether the HTTPS server to be connected is a SoftEther VPN
+bool DetectIsServerSoftEtherVPN(SOCK *s)
+{
+ HTTP_HEADER *h;
+ char ip_str[MAX_SIZE];
+ char *send_str;
+ UINT content_len;
+ BUF *recv_buf;
+ void *socket_buffer;
+ UINT socket_buffer_size = 32768;
+ bool ok = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
+
+ // Request generation
+ h = NewHttpHeaderEx("GET", "/", "HTTP/1.1", true);
+ AddHttpValue(h, NewHttpValue("X-VPN", "1"));
+ AddHttpValue(h, NewHttpValue("Host", ip_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Accept-Language", "ja"));
+ AddHttpValue(h, NewHttpValue("User-Agent", DEFAULT_USER_AGENT));
+ AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
+ AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache"));
+ send_str = HttpHeaderToStr(h);
+ FreeHttpHeader(h);
+
+ // Transmission
+ if (SendAll(s, send_str, StrLen(send_str), true) == false)
+ {
+ Free(send_str);
+ return false;
+ }
+
+ Free(send_str);
+
+ // Receive
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ // Get the length of the content
+ content_len = GetContentLength(h);
+ FreeHttpHeader(h);
+
+ if (content_len == 0 || content_len >= (1024 * 1024))
+ {
+ return false;
+ }
+
+ // Receive contents
+ recv_buf = NewBuf();
+ socket_buffer = Malloc(socket_buffer_size);
+
+ while (true)
+ {
+ UINT recvsize = MIN(socket_buffer_size, content_len - recv_buf->Size);
+ UINT size;
+
+ if (recvsize == 0)
+ {
+ ok = true;
+ break;
+ }
+
+ size = Recv(s, socket_buffer, recvsize, true);
+ if (size == 0)
+ {
+ // Disconnected
+ break;
+ }
+
+ WriteBuf(recv_buf, socket_buffer, size);
+ }
+
+ SeekBuf(recv_buf, 0, 0);
+ Free(socket_buffer);
+
+ if (ok)
+ {
+ // Examine to confirm whether the incoming data is a SoftEther VPN protocol
+ char tmp[1024];
+
+ Zero(tmp, sizeof(tmp));
+
+ Copy(tmp, recv_buf->Buf, MIN(recv_buf->Size, (sizeof(tmp) - 1)));
+
+ ok = false;
+
+ if (StartWith(tmp, http_detect_server_startwith))
+ {
+ ok = true;
+ }
+ else if (InStr(tmp, http_detect_server_tag_future))
+ {
+ ok = true;
+ }
+ }
+
+ FreeBuf(recv_buf);
+
+ return ok;
+}
+
+// TCP connection thread
+void ConnectThreadForTcp(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ char hostname[MAX_SIZE];
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ IPToStr(hostname, sizeof(hostname), &p->Ip);
+ sock = ConnectEx3(hostname, p->Port, p->Timeout, p->CancelFlag, NULL, NULL, false, false, true);
+
+ if (sock != NULL && p->Tcp_SslNoTls)
+ {
+ bool ssl_ret = false;
+ // Attempt the SSL negotiation to take this opportunity
+ Lock(p->CancelLock);
+ {
+ if ((*p->CancelFlag) == false)
+ {
+ p->CancelDisconnectSock = sock;
+ AddRef(sock->ref);
+ }
+ else
+ {
+ Debug("User Cancel to StartSSL.\n");
+ goto LABEL_CANCEL;
+ }
+ }
+ Unlock(p->CancelLock);
+
+ // Start the SSL communication
+ ssl_ret = StartSSLEx(sock, NULL, NULL, p->Tcp_SslNoTls, 0, p->Hostname);
+
+ if (ssl_ret)
+ {
+ // Identify whether the HTTPS server to be connected is a SoftEther VPN
+ SetTimeout(sock, (10 * 1000));
+ ssl_ret = DetectIsServerSoftEtherVPN(sock);
+ SetTimeout(sock, INFINITE);
+
+ if (ssl_ret == false)
+ {
+ Debug("DetectIsServerSoftEtherVPN Error.\n");
+ }
+ }
+
+ Lock(p->CancelLock);
+ {
+ ReleaseSock(p->CancelDisconnectSock);
+ p->CancelDisconnectSock = NULL;
+LABEL_CANCEL:
+ DoNothing();
+ }
+ Unlock(p->CancelLock);
+
+ if (ssl_ret == false)
+ {
+ // SSL negotiation failure
+ Disconnect(sock);
+ ReleaseSock(sock);
+
+ Debug("Fail to StartSSL.\n");
+
+ sock = NULL;
+ }
+ }
+
+ p->Result_Tcp_Sock = sock;
+ p->Ok = (p->Result_Tcp_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// R-UDP over ICMP / over DNS connection thread
+void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ sock = NewRUDPClientDirect(p->SvcName, &p->Ip,
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? 53 : MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4)),
+ &p->NatT_ErrorCode, p->Timeout, p->CancelFlag, NULL, NULL,
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? 0 : MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4)),
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? true : false));
+
+ p->Result_Nat_T_Sock = sock;
+ p->Ok = (p->Result_Nat_T_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// R-UDP (via NAT-T) connection thread
+void ConnectThreadForRUDP(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ sock = NewRUDPClientNatT(p->SvcName, &p->Ip, &p->NatT_ErrorCode, p->Timeout, p->CancelFlag, p->HintStr, p->TargetHostname);
+
+ p->Result_Nat_T_Sock = sock;
+ p->Ok = (p->Result_Nat_T_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// TCP connection
+SOCK *Connect(char *hostname, UINT port)
+{
+ return ConnectEx(hostname, port, 0);
+}
+SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
+{
+ return ConnectEx2(hostname, port, timeout, NULL);
+}
+SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
+{
+ return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, false, false);
+}
+SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, bool no_get_hostname)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct linger ling;
+ IP ip4;
+ IP ip6;
+ bool true_flag = true;
+ bool false_flag = false;
+ char tmp[MAX_SIZE];
+ IP current_ip;
+ bool is_ipv6 = false;
+ bool dummy = false;
+ bool use_natt = false;
+ char hostname_original[MAX_SIZE];
+ char hint_str[MAX_SIZE];
+ bool force_use_natt = false;
+ UINT dummy_int = 0;
+ // Validate arguments
+ if (hostname == NULL || port == 0 || port >= 65536 || IsEmptyStr(hostname))
+ {
+ return NULL;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+ if (cancel_flag == NULL)
+ {
+ cancel_flag = &dummy;
+ }
+ if (nat_t_error_code == NULL)
+ {
+ nat_t_error_code = &dummy_int;
+ }
+
+ Zero(hint_str, sizeof(hint_str));
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+
+ use_natt = (IsEmptyStr(nat_t_svc_name) ? false : true);
+
+ if (use_natt)
+ {
+ // In case of using NAT-T, split host name if the '/' is included in the host name
+ UINT i = SearchStrEx(hostname, "/", 0, false);
+
+ if (i == INFINITE)
+ {
+ // Not included
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ }
+ else
+ {
+ // Included
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ hostname_original[i] = 0;
+
+ // Force to use the NAT-T
+ force_use_natt = true;
+
+ // Copy the hint string
+ StrCpy(hint_str, sizeof(hint_str), hostname + i + 1);
+
+ if (StrCmpi(hint_str, "tcp") == 0 || StrCmpi(hint_str, "disable") == 0
+ || StrCmpi(hint_str, "disabled") == 0
+ || StrCmpi(hint_str, "no") == 0 || StrCmpi(hint_str, "none") == 0)
+ {
+ // Force not to use the NAT-T
+ force_use_natt = false;
+ use_natt = false;
+ }
+ }
+ }
+ else
+ {
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ }
+
+ Zero(&current_ip, sizeof(current_ip));
+
+ Zero(&ip4, sizeof(ip4));
+ Zero(&ip6, sizeof(ip6));
+
+ // Forward resolution
+ if (GetIP46Ex(&ip4, &ip6, hostname_original, 0, cancel_flag) == false)
+ {
+ return NULL;
+ }
+
+ if (IsZeroIp(&ip4) == false && IsIPLocalHostOrMySelf(&ip4))
+ {
+ // NAT-T isn't used in the case of connection to localhost
+ force_use_natt = false;
+ use_natt = false;
+ }
+
+ s = INVALID_SOCKET;
+
+ // Attempt to connect with IPv4
+ if (IsZeroIp(&ip4) == false)
+ {
+ if (use_natt == false)
+ {
+ // Normal connection without using NAT-T
+ s = ConnectTimeoutIPv4(&ip4, port, timeout, cancel_flag);
+
+ if (s != INVALID_SOCKET)
+ {
+ Copy(&current_ip, &ip4, sizeof(IP));
+ }
+ }
+ else if (force_use_natt)
+ {
+ // The connection by forcing the use of NAT-T (not to connection with normal TCP)
+ SOCK *nat_t_sock = NewRUDPClientNatT(nat_t_svc_name, &ip4, nat_t_error_code, timeout, cancel_flag,
+ hint_str, hostname);
+
+ if (nat_t_sock != NULL)
+ {
+ StrCpy(nat_t_sock->UnderlayProtocol, sizeof(nat_t_sock->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ }
+
+ return nat_t_sock;
+ }
+ else
+ {
+ // Use the connections using NAT-T with normal TCP connection together
+ // (Use multiple threads to try to connect in four connection methods concurrently)
+ CONNECT_TCP_RUDP_PARAM p1, p2, p3, p4;
+ EVENT *finish_event;
+ THREAD *t1, *t2, *t3, *t4;
+ UINT64 start_tick = Tick64();
+ UINT64 giveup_for_all_tick = start_tick + (UINT64)SOCK_CONNECT_WAIT_FOR_ICMP_AND_DNS_AT_LEAST;
+ bool cancel_flag2 = false;
+ SOCK *cancel_sock = NULL;
+
+ finish_event = NewEvent();
+
+ Zero(&p1, sizeof(p1));
+ Zero(&p2, sizeof(p2));
+ Zero(&p3, sizeof(p3));
+ Zero(&p4, sizeof(p4));
+
+ // p1: TCP
+ StrCpy(p1.Hostname, sizeof(p1.Hostname), hostname_original);
+ Copy(&p1.Ip, &ip4, sizeof(IP));
+ p1.Port = port;
+ p1.Timeout = timeout;
+ p1.CancelFlag = &cancel_flag2;
+ p1.FinishEvent = finish_event;
+ p1.Tcp_TryStartSsl = try_start_ssl;
+ p1.Tcp_SslNoTls = ssl_no_tls;
+ p1.CancelLock = NewLock();
+
+ // p2: NAT-T
+ StrCpy(p2.Hostname, sizeof(p2.Hostname), hostname_original);
+ Copy(&p2.Ip, &ip4, sizeof(IP));
+ p2.Port = port;
+ p2.Timeout = timeout;
+ p2.CancelFlag = &cancel_flag2;
+ p2.FinishEvent = finish_event;
+
+ StrCpy(p2.HintStr, sizeof(p2.HintStr), hint_str);
+ StrCpy(p2.TargetHostname, sizeof(p2.TargetHostname), hostname);
+ StrCpy(p2.SvcName, sizeof(p2.SvcName), nat_t_svc_name);
+ p2.Delay = 30; // Delay by 30ms
+
+ // p3: over ICMP
+ StrCpy(p3.Hostname, sizeof(p3.Hostname), hostname_original);
+ Copy(&p3.Ip, &ip4, sizeof(IP));
+ p3.Port = port;
+ p3.Timeout = timeout;
+ p3.CancelFlag = &cancel_flag2;
+ p3.FinishEvent = finish_event;
+ StrCpy(p3.SvcName, sizeof(p3.SvcName), nat_t_svc_name);
+ p3.RUdpProtocol = RUDP_PROTOCOL_ICMP;
+ p3.Delay = 200; // Delay by 200ms
+
+ // p4: over DNS
+ StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname_original);
+ Copy(&p4.Ip, &ip4, sizeof(IP));
+ p4.Port = port;
+ p4.Timeout = timeout;
+ p4.CancelFlag = &cancel_flag2;
+ p4.FinishEvent = finish_event;
+ StrCpy(p4.SvcName, sizeof(p4.SvcName), nat_t_svc_name);
+ p4.RUdpProtocol = RUDP_PROTOCOL_DNS;
+ p4.Delay = 100; // Delay by 100ms
+
+ t1 = NewThread(ConnectThreadForTcp, &p1);
+ t2 = NewThread(ConnectThreadForRUDP, &p2);
+ t4 = NewThread(ConnectThreadForOverDnsOrIcmp, &p4);
+ t3 = NewThread(ConnectThreadForOverDnsOrIcmp, &p3);
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ if (*cancel_flag)
+ {
+ // Cancel by the user
+ break;
+ }
+
+ if (p1.Finished && p2.Finished)
+ {
+ // Results for both the TCP and the NAT-T were confirmed
+ if (now >= giveup_for_all_tick)
+ {
+ // Wait at least minimum time until successful of the ICMP or the DNS
+ break;
+ }
+
+ if (p3.Ok || p4.Ok)
+ {
+ // Exit the loop immediately if any of the ICMP or the DNS is successful
+ break;
+ }
+ }
+
+ if (p1.Finished && p1.Ok)
+ {
+ // Have successfully connected by TCP
+ break;
+ }
+
+ if (p2.Finished && p2.Ok)
+ {
+ UINT p1_wait_time;
+ UINT64 tcp_giveup_tick;
+ UINT p2_spent_time;
+ // Have successfully connected by R-UDP
+ if (p1.Finished)
+ {
+ // Result of TCP is confirmed
+ break;
+ }
+
+ // Calculate the time takes to complete connection of R-UDP
+ p2_spent_time = (UINT)(p2.FinishedTick - start_tick);
+
+ // Decide the grace time for results of TCP until settled.
+ // The grace time is three times the duration of the R-UDP, and at least 250 milliseconds from the start,
+ // and up to 1500 milliseconds after the R-UDP results settled
+ p1_wait_time = p2_spent_time * 3;
+ p1_wait_time = MAX(p1_wait_time, 250);
+ //Debug("p2_spent_time = %u, p1_wait_time = %u\n", p2_spent_time, p1_wait_time);
+
+ tcp_giveup_tick = start_tick + (UINT64)p1_wait_time;
+ tcp_giveup_tick = MIN(tcp_giveup_tick, (p2.FinishedTick + 1500ULL));
+
+ if (now >= tcp_giveup_tick)
+ {
+ // Result of the TCP is uncertain, but give up
+ break;
+ }
+ }
+
+ Wait(finish_event, 25);
+ }
+
+ cancel_flag2 = true;
+
+ Lock(p1.CancelLock);
+ {
+ if (p1.CancelDisconnectSock != NULL)
+ {
+ cancel_sock = p1.CancelDisconnectSock;
+
+ AddRef(cancel_sock->ref);
+ }
+ }
+ Unlock(p1.CancelLock);
+
+ if (cancel_sock != NULL)
+ {
+ Disconnect(cancel_sock);
+ ReleaseSock(cancel_sock);
+ }
+
+ WaitThread(t1, INFINITE);
+ WaitThread(t2, INFINITE);
+ WaitThread(t3, INFINITE);
+ WaitThread(t4, INFINITE);
+ ReleaseThread(t1);
+ ReleaseThread(t2);
+ ReleaseThread(t3);
+ ReleaseThread(t4);
+ ReleaseEvent(finish_event);
+
+ DeleteLock(p1.CancelLock);
+
+ if (*cancel_flag)
+ {
+ // Abandon all the results because the user canceled
+ Disconnect(p1.Result_Nat_T_Sock);
+ ReleaseSock(p1.Result_Nat_T_Sock);
+ Disconnect(p2.Result_Nat_T_Sock);
+ ReleaseSock(p2.Result_Nat_T_Sock);
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ return NULL;
+ }
+
+ if (p1.Ok)
+ {
+ char hostname[MAX_SIZE];
+
+ // Use the results of the TCP
+ // Dispose other results
+ Disconnect(p2.Result_Nat_T_Sock);
+ ReleaseSock(p2.Result_Nat_T_Sock);
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ if (GetHostName(hostname, sizeof(hostname), &ip4))
+ {
+ Free(p1.Result_Tcp_Sock->RemoteHostname);
+ p1.Result_Tcp_Sock->RemoteHostname = CopyStr(hostname);
+ }
+
+ return p1.Result_Tcp_Sock;
+ }
+ else if (p2.Ok)
+ {
+ // Use the results of the R-UDP
+ // Dispose other results
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ StrCpy(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_NAT_T);
+
+ return p2.Result_Nat_T_Sock;
+ }
+ else if (p4.Ok)
+ {
+ // Use this if over-DNS success
+ // Dispose other results
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+
+ StrCpy(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_DNS);
+
+ return p4.Result_Nat_T_Sock;
+ }
+ else if (p3.Ok)
+ {
+ // Use this if over ICMP success
+ StrCpy(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_ICMP);
+
+ return p3.Result_Nat_T_Sock;
+ }
+ else
+ {
+ // Continue the process if all trials failed
+ *nat_t_error_code = p2.NatT_ErrorCode;
+ }
+ }
+ }
+
+ // Attempt to connect with IPv6
+ if (s == INVALID_SOCKET && IsZeroIp(&ip6) == false)
+ {
+ struct sockaddr_in6 sockaddr6;
+ struct in6_addr addr6;
+
+ Zero(&sockaddr6, sizeof(sockaddr6));
+ Zero(&addr6, sizeof(addr6));
+
+ // Generation of the sockaddr_in6
+ IPToInAddr6(&addr6, &ip6);
+ sockaddr6.sin6_port = htons((USHORT)port);
+ sockaddr6.sin6_family = AF_INET6;
+ sockaddr6.sin6_scope_id = ip6.ipv6_scope_id;
+ Copy(&sockaddr6.sin6_addr, &addr6, sizeof(addr6));
+
+ // Socket creation
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s != INVALID_SOCKET)
+ {
+ // Connection
+ if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), timeout, cancel_flag) != 0)
+ {
+ // Connection failure
+ closesocket(s);
+ s = INVALID_SOCKET;
+ }
+ else
+ {
+ Copy(&current_ip, &ip6, sizeof(IP));
+
+ is_ipv6 = true;
+ }
+ }
+ }
+
+ if (s == INVALID_SOCKET)
+ {
+ // Connection fails on both of IPv4, IPv6
+ return NULL;
+ }
+
+ // Creating a SOCK
+ sock = NewSock();
+ sock->socket = s;
+ sock->Type = SOCK_TCP;
+ sock->ServerMode = false;
+
+ StrCpy(sock->UnderlayProtocol, sizeof(sock->UnderlayProtocol),
+ (is_ipv6 ? SOCK_UNDERLAY_NATIVE_V6 : SOCK_UNDERLAY_NATIVE_V4));
+
+ // Host name resolution
+ if (no_get_hostname || (GetHostName(tmp, sizeof(tmp), &current_ip) == false))
+ {
+ StrCpy(tmp, sizeof(tmp), hostname_original);
+ }
+
+ //Debug("PTR: %s\n", tmp);
+
+ sock->RemoteHostname = CopyStr(tmp);
+
+// Debug("new socket: %u\n", s);
+
+ Zero(&ling, sizeof(ling));
+ // Forced disconnection flag
+#ifdef SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
+#else // SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
+#endif // SO_DONTLINGER
+// setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+
+ // Configuring TCP options
+ setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialization of the time-out value
+ SetTimeout(sock, TIMEOUT_INFINITE);
+
+ // Get the socket information
+ QuerySocketInformation(sock);
+
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, is_ipv6) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, is_ipv6);
+ }
+ }
+
+ sock->Connected = true;
+ sock->AsyncMode = false;
+ sock->SecureMode = false;
+ sock->IPv6 = is_ipv6;
+
+ return sock;
+}
+
+// Maximize the I/O buffer size of the socket
+void SetSocketSendRecvBufferSize(SOCKET s, UINT size)
+{
+ int value = (int)size;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return;
+ }
+
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
+ setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
+}
+
+// Get the buffer size of the socket
+UINT GetSocketBufferSize(SOCKET s, bool send)
+{
+ int value = 0;
+ int len = sizeof(int);
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return 0;
+ }
+
+ if (getsockopt(s, SOL_SOCKET, (send ? SO_SNDBUF : SO_RCVBUF), (char *)&value, &len) != 0)
+ {
+ return 0;
+ }
+
+ return value;
+}
+
+// Setting the buffer size of the socket
+bool SetSocketBufferSize(SOCKET s, bool send, UINT size)
+{
+ int value = (int)size;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return false;
+ }
+
+ if (setsockopt(s, SOL_SOCKET, (send ? SO_SNDBUF : SO_RCVBUF), (char *)&value, sizeof(int)) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size)
+{
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ if (SetSocketBufferSize(s, send, size))
+ {
+ return size;
+ }
+
+ size = (UINT)((double)size / 1.5);
+
+ if (size <= 32767)
+ {
+ return 0;
+ }
+ }
+}
+
+// Initialize the buffer size of the UDP socket
+void InitUdpSocketBufferSize(SOCKET s)
+{
+ SetSocketBufferSizeWithBestEffort(s, true, UDP_MAX_BUFFER_SIZE);
+ SetSocketBufferSizeWithBestEffort(s, false, UDP_MAX_BUFFER_SIZE);
+}
+
+// Get the socket information
+void QuerySocketInformation(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ Lock(sock->lock);
+ {
+ struct sockaddr_in6 sockaddr6;
+ struct in6_addr *addr6;
+ int size;
+ DWORD dw;
+ UINT opt_value = 0;
+
+ if (sock->Type == SOCK_TCP)
+ {
+ // Get the information of the remote host
+ size = sizeof(sockaddr6);
+ if (getpeername(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
+ {
+ if (size >= sizeof(struct sockaddr_in6))
+ {
+ sock->RemotePort = (UINT)ntohs(sockaddr6.sin6_port);
+ addr6 = &sockaddr6.sin6_addr;
+ InAddrToIP6(&sock->RemoteIP, addr6);
+ sock->RemoteIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
+ }
+ else
+ {
+ struct sockaddr_in *sockaddr;
+ struct in_addr *addr;
+
+ sockaddr = (struct sockaddr_in *)&sockaddr6;
+ sock->RemotePort = (UINT)ntohs(sockaddr->sin_port);
+ addr = &sockaddr->sin_addr;
+ InAddrToIP(&sock->RemoteIP, addr);
+ }
+ }
+ }
+
+ // Get the local host information
+ size = sizeof(sockaddr6);
+ if (getsockname(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
+ {
+ if (size >= sizeof(struct sockaddr_in6))
+ {
+ sock->LocalPort = (UINT)ntohs(sockaddr6.sin6_port);
+ addr6 = &sockaddr6.sin6_addr;
+ InAddrToIP6(&sock->LocalIP, addr6);
+ sock->LocalIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
+ }
+ else
+ {
+ struct sockaddr_in *sockaddr;
+ struct in_addr *addr;
+
+ sockaddr = (struct sockaddr_in *)&sockaddr6;
+ sock->LocalPort = (UINT)ntohs(sockaddr->sin_port);
+ addr = &sockaddr->sin_addr;
+ InAddrToIP(&sock->LocalIP, addr);
+ }
+ }
+
+ if (sock->IsRawSocket)
+ {
+ sock->LocalPort = sock->RemotePort = MAKE_SPECIAL_PORT(sock->RawSocketIPProtocol);
+ }
+
+ if (sock->Type == SOCK_UDP)
+ {
+ sock->UdpMaxMsgSize = UDP_MAX_MSG_SIZE_DEFAULT;
+
+#ifdef OS_WIN32
+ if (true)
+ {
+ // Get the buffer size that can be transmitted and received at once
+ UINT max_value = 0;
+ int len = sizeof(UINT);
+
+ if (getsockopt(sock->socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&max_value, &len) == 0)
+ {
+ sock->UdpMaxMsgSize = max_value;
+ }
+ }
+#endif // OS_WIN32
+ }
+
+ if (sock->IPv6)
+ {
+#ifdef IPV6_UNICAST_HOPS
+ opt_value = IPV6_UNICAST_HOPS;
+#endif // IPV6_UNICAST_HOPS
+ }
+ else
+ {
+#ifdef IP_TTL
+ opt_value = IP_TTL;
+#endif // IP_TTL
+ }
+
+ // Support of the TTL value
+ size = sizeof(DWORD);
+ if (opt_value == 0 ||
+ getsockopt(sock->socket, (sock->IPv6 ? IPPROTO_IPV6 : IPPROTO_IP), opt_value, (char *)&dw, &size) != 0)
+ {
+ sock->IsTtlSupported = false;
+ }
+ else
+ {
+ sock->IsTtlSupported = true;
+ sock->CurrentTtl = dw;
+ }
+ }
+ Unlock(sock->lock);
+}
+
+// Setting the TTL value
+bool SetTtl(SOCK *sock, UINT ttl)
+{
+ DWORD dw;
+ int size;
+ UINT opt_value = 0;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return false;
+ }
+
+ if (sock->IsTtlSupported == false)
+ {
+ return false;
+ }
+
+ if (sock->CurrentTtl == ttl)
+ {
+ return true;
+ }
+
+ dw = ttl;
+ size = sizeof(DWORD);
+
+ if (sock->IPv6)
+ {
+#ifdef IPV6_UNICAST_HOPS
+ opt_value = IPV6_UNICAST_HOPS;
+#endif // IPV6_UNICAST_HOPS
+ }
+ else
+ {
+#ifdef IP_TTL
+ opt_value = IP_TTL;
+#endif // IP_TTL
+ }
+
+ if (opt_value == 0 ||
+ setsockopt(sock->socket, (sock->IPv6 ? IPPROTO_IPV6 : IPPROTO_IP), opt_value, (char *)&dw, size) == false)
+ {
+ return false;
+ }
+
+ sock->CurrentTtl = ttl;
+
+ return true;
+}
+
+// Release of the socket
+void ReleaseSock(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ if (s->ListenMode == false && s->ServerMode)
+ {
+ Print("");
+ }
+ CleanupSock(s);
+ }
+}
+
+// Clean-up of the socket
+void CleanupSock(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+// {Debug("CleanupSock: Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}
+ Disconnect(s);
+
+ if (s->InProcAcceptQueue != NULL)
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(s->InProcAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+
+ ReleaseQueue(s->InProcAcceptQueue);
+ }
+
+ if (s->InProcAcceptEvent != NULL)
+ {
+ ReleaseEvent(s->InProcAcceptEvent);
+ }
+
+ if (s->ReverseAcceptQueue != NULL)
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(s->ReverseAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+
+ ReleaseQueue(s->ReverseAcceptQueue);
+ }
+
+ if (s->ReverseAcceptEvent != NULL)
+ {
+ ReleaseEvent(s->ReverseAcceptEvent);
+ }
+
+ if (s->SendTube != NULL)
+ {
+ TubeDisconnect(s->SendTube);
+ ReleaseTube(s->SendTube);
+ }
+
+ if (s->RecvTube != NULL)
+ {
+ TubeDisconnect(s->RecvTube);
+ ReleaseTube(s->RecvTube);
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TubeDisconnect(s->BulkRecvTube);
+ ReleaseTube(s->BulkRecvTube);
+ }
+
+ if (s->BulkSendTube != NULL)
+ {
+ TubeDisconnect(s->BulkSendTube);
+ ReleaseTube(s->BulkSendTube);
+ }
+
+ if (s->BulkSendKey != NULL)
+ {
+ ReleaseSharedBuffer(s->BulkSendKey);
+ }
+
+ if (s->BulkRecvKey != NULL)
+ {
+ ReleaseSharedBuffer(s->BulkRecvKey);
+ }
+
+ if (s->InProcRecvFifo != NULL)
+ {
+ ReleaseFifo(s->InProcRecvFifo);
+ }
+
+ if (s->R_UDP_Stack != NULL)
+ {
+ FreeRUDP(s->R_UDP_Stack);
+ }
+
+#ifdef OS_WIN32
+ Win32FreeAsyncSocket(s);
+#else // OS_WIN32
+ UnixFreeAsyncSocket(s);
+#endif // OS_WIN32
+
+ FreeBuf(s->SendBuf);
+ if (s->socket != INVALID_SOCKET)
+ {
+#ifdef OS_WIN32
+ closesocket(s->socket);
+#else // OS_WIN32
+ close(s->socket);
+#endif // OS_WIN32
+ }
+ Free(s->RemoteHostname);
+
+#ifdef OS_WIN32
+ if (s->hAcceptEvent != NULL)
+ {
+ CloseHandle(s->hAcceptEvent);
+ }
+#endif // OS_WIN32
+
+ Free(s->WaitToUseCipher);
+ DeleteLock(s->lock);
+ DeleteLock(s->ssl_lock);
+ DeleteLock(s->disconnect_lock);
+
+ Dec(num_tcp_connections);
+
+ Free(s);
+}
+
+// Creating a new socket
+SOCK *NewSock()
+{
+ SOCK *s = ZeroMallocFast(sizeof(SOCK));
+
+ s->ref = NewRef();
+ s->lock = NewLock();
+ s->SendBuf = NewBuf();
+ s->socket = INVALID_SOCKET;
+ s->ssl_lock = NewLock();
+ s->disconnect_lock = NewLock();
+
+ Inc(num_tcp_connections);
+
+ return s;
+}
+
+// Convert the IP to UINT
+UINT IPToUINT(IP *ip)
+{
+ UCHAR *b;
+ UINT i, value = 0;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return 0;
+ }
+
+ b = (UCHAR *)&value;
+ for (i = 0;i < 4;i++)
+ {
+ b[i] = ip->addr[i];
+ }
+
+ return value;
+}
+
+// Convert UINT to IP
+void UINTToIP(IP *ip, UINT value)
+{
+ UCHAR *b;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP4(ip);
+
+ b = (UCHAR *)&value;
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = b[i];
+ }
+}
+
+// Get the host name of the computer
+void GetMachineHostName(char *name, UINT size)
+{
+ char tmp[MAX_SIZE];
+ UINT i, len;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetMachineName(tmp, sizeof(tmp));
+
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == '.')
+ {
+ tmp[i] = 0;
+ }
+ }
+
+ ConvertSafeFileName(name, size, tmp);
+}
+
+// Get the IP address of this computer
+void GetMachineIp(IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+ SetIP(ip, 127, 0, 0, 1);
+
+ GetMachineName(tmp, sizeof(tmp));
+ GetIP(ip, tmp);
+}
+
+// Get the computer name from 'hosts'
+bool GetMachineNameFromHosts(char *name, UINT size)
+{
+ bool ret = false;
+ char *s;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump("/etc/hosts");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ s = CfgReadNextLine(b);
+ if (s == NULL)
+ {
+ break;
+ }
+ else
+ {
+ TOKEN_LIST *t = ParseToken(s, " \t");
+
+ if (t != NULL)
+ {
+ if (t->NumTokens >= 2)
+ {
+ if (StrCmpi(t->Token[0], "127.0.0.1") == 0)
+ {
+ UINT i;
+
+ for (i = 1;i < t->NumTokens;i++)
+ {
+ if (StartWith(t->Token[i], "localhost") == false)
+ {
+ StrCpy(name, size, t->Token[i]);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ FreeToken(t);
+ }
+
+ Free(s);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the computer name of this computer
+void GetMachineName(char *name, UINT size)
+{
+ GetMachineNameEx(name, size, false);
+}
+void GetMachineNameEx(char *name, UINT size, bool no_load_hosts)
+{
+ static char name_cache[MAX_SIZE];
+ static bool name_cached = false;
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Lock(machine_name_lock);
+ {
+ if (name_cached != false)
+ {
+ StrCpy(name, size, name_cache);
+ Unlock(machine_name_lock);
+ return;
+ }
+ ClearStr(tmp, sizeof(tmp));
+ if (gethostname(tmp, MAX_SIZE) != 0)
+ {
+ StrCpy(name, size, "Unknown");
+ Unlock(machine_name_lock);
+ return;
+ }
+ ClearStr(name, size);
+ StrCpy(name, size, tmp);
+ if (IsEmptyStr(name) || StartWith(name, "localhost"))
+ {
+#ifdef OS_WIN32
+ ClearStr(name, size);
+ MsGetComputerName(name, size);
+#endif // OS_WIN32
+ }
+ if (IsEmptyStr(name) || StartWith(name, "localhost"))
+ {
+ if (no_load_hosts == false && OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ if (GetMachineNameFromHosts(tmp2, sizeof(tmp2)))
+ {
+ StrCpy(name, sizeof(name), tmp2);
+ }
+ }
+ }
+
+ StrCpy(name_cache, sizeof(name_cache), name);
+ name_cached = true;
+ }
+ Unlock(machine_name_lock);
+}
+
+// Host name acquisition thread
+void GetHostNameThread(THREAD *t, void *p)
+{
+ IP *ip;
+ char hostname[256];
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ ip = (IP *)p;
+
+ AddWaitThread(t);
+
+ NoticeThreadInit(t);
+
+ if (GetHostNameInner(hostname, sizeof(hostname), ip))
+ {
+ AddHostCache(ip, hostname);
+ }
+
+ Free(ip);
+
+ DelWaitThread(t);
+}
+
+// Get the host name
+bool GetHostName(char *hostname, UINT size, IP *ip)
+{
+ THREAD *t;
+ IP *p_ip;
+ bool ret;
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ if (GetHostCache(hostname, size, ip))
+ {
+ if (IsEmptyStr(hostname) == false)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ p_ip = ZeroMalloc(sizeof(IP));
+ Copy(p_ip, ip, sizeof(IP));
+
+ t = NewThread(GetHostNameThread, p_ip);
+
+ WaitThreadInit(t);
+
+ WaitThread(t, TIMEOUT_HOSTNAME);
+
+ ReleaseThread(t);
+
+ ret = GetHostCache(hostname, size, ip);
+ if (ret == false)
+ {
+ if (IsIP4(ip))
+ {
+ ret = GetNetBiosName(hostname, size, ip);
+ if (ret)
+ {
+ AddHostCache(ip, hostname);
+ }
+ }
+ }
+ else
+ {
+ if (IsEmptyStr(hostname))
+ {
+ ret = false;
+ }
+ }
+ if (ret == false)
+ {
+ AddHostCache(ip, "");
+ StrCpy(hostname, size, "");
+ }
+
+ return ret;
+}
+
+// Perform a DNS reverse query
+bool GetHostNameInner(char *hostname, UINT size, IP *ip)
+{
+ struct in_addr addr;
+ struct sockaddr_in sa;
+ char tmp[MAX_SIZE];
+ char ip_str[64];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip))
+ {
+ return GetHostNameInner6(hostname, size, ip);
+ }
+
+ // Reverse resolution
+ IPToInAddr(&addr, ip);
+ Zero(&sa, sizeof(sa));
+ sa.sin_family = AF_INET;
+
+#if defined(UNIX_BSD) || defined(UNIX_MACOS)
+ sa.sin_len = INET_ADDRSTRLEN;
+#endif // UNIX_BSD || UNIX_MACOS
+
+ Copy(&sa.sin_addr, &addr, sizeof(struct in_addr));
+ sa.sin_port = 0;
+
+ if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (StrCmpi(tmp, ip_str) == 0)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ StrCpy(hostname, size, tmp);
+
+ return true;
+}
+bool GetHostNameInner6(char *hostname, UINT size, IP *ip)
+{
+ struct in6_addr addr;
+ struct sockaddr_in6 sa;
+ char tmp[MAX_SIZE];
+ char ip_str[256];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ // Reverse resolution
+ IPToInAddr6(&addr, ip);
+ Zero(&sa, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+
+#if defined(UNIX_BSD) || defined(UNIX_MACOS)
+ sa.sin6_len = INET6_ADDRSTRLEN;
+#endif // UNIX_BSD || UNIX_MACOS
+
+ Copy(&sa.sin6_addr, &addr, sizeof(struct in6_addr));
+ sa.sin6_port = 0;
+
+ if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (StrCmpi(tmp, ip_str) == 0)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ StrCpy(hostname, size, tmp);
+
+ return true;
+}
+
+#define NUM_NBT_QUERYS_SEND 3
+
+// Get the NetBIOS name of the machine from the IP address
+bool GetNetBiosName(char *name, UINT size, IP *ip)
+{
+ SOCK *s;
+ UINT i, j;
+ bool flag = false;
+ bool ok = false;
+ NBTREQUEST req;
+ UCHAR buf[1024];
+ USHORT tran_id[NUM_NBT_QUERYS_SEND];
+ UINT64 timeout_tick;
+ // Validate arguments
+ if (name == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ IPToStr(name, size, ip);
+
+ for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
+ {
+ tran_id[i] = Rand16();
+ }
+
+ s = NewUDP(0);
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < NUM_NBT_QUERYS_SEND;j++)
+ {
+ Zero(&req, sizeof(req));
+ req.TransactionId = Endian16(tran_id[j]);
+ req.NumQuestions = Endian16(1);
+ req.Query[0] = 0x20;
+ req.Query[1] = 0x43;
+ req.Query[2] = 0x4b;
+ for (i = 3;i <= 32;i++)
+ {
+ req.Query[i] = 0x41;
+ }
+ req.Query[35] = 0x21;
+ req.Query[37] = 0x01;
+
+ if (SendTo(s, ip, 137, &req, sizeof(req)) == 0)
+ {
+ ReleaseSock(s);
+ return false;
+ }
+ }
+
+ timeout_tick = Tick64() + (UINT64)TIMEOUT_NETBIOS_HOSTNAME;
+
+ while (1)
+ {
+ UINT ret;
+ IP src_ip;
+ UINT src_port;
+ SOCKSET set;
+ if (Tick64() >= timeout_tick)
+ {
+ break;
+ }
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+ Select(&set, 100, NULL, NULL);
+
+ if (flag == false)
+ {
+ flag = true;
+ }
+ else
+ {
+ SleepThread(10);
+ }
+
+ ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));
+
+ if (ret == SOCK_LATER)
+ {
+ continue;
+ }
+ else if (ret == 0)
+ {
+ break;
+ }
+ else
+ {
+ if (ret >= sizeof(NBTRESPONSE))
+ {
+ NBTRESPONSE *r = (NBTRESPONSE *)buf;
+ bool b = false;
+ UINT i;
+ USHORT id = Endian16(r->TransactionId);
+ for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
+ {
+ if (id == tran_id[i])
+ {
+ b = true;
+ break;
+ }
+ }
+ if (b)
+ {
+ if (r->Flags != 0 && r->NumQuestions == 0 && r->AnswerRRs >= 1)
+ {
+ if (r->Response[0] == 0x20 && r->Response[1] == 0x43 &&
+ r->Response[2] == 0x4b)
+ {
+ if (r->Response[34] == 0x00 && r->Response[35] == 0x21 &&
+ r->Response[36] == 0x00 && r->Response[37] == 0x01)
+ {
+ char *a = (char *)(&r->Response[45]);
+ if (StrCheckLen(a, 15))
+ {
+ if (IsEmptyStr(a) == false)
+ {
+ StrCpy(name, size, a);
+ Trim(name);
+ ok = true;
+ }
+ else
+ {
+ ok = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ReleaseSock(s);
+ return ok;
+}
+
+// Set the IP address
+void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+ ip->addr[0] = a1;
+ ip->addr[1] = a2;
+ ip->addr[2] = a3;
+ ip->addr[3] = a4;
+}
+UINT SetIP32(UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)
+{
+ IP ip;
+
+ Zero(&ip, sizeof(ip));
+ SetIP(&ip, a1, a2, a3, a4);
+
+ return IPToUINT(&ip);
+}
+
+// Get either of v4 and v6 results with a DNS forward lookup (The IPv4 precedes in the case of both results)
+bool GetIP46Any4(IP *ip, char *hostname)
+{
+ IP ip4, ip6;
+ bool b = false;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (GetIP46(&ip4, &ip6, hostname) == false)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(&ip6) == false)
+ {
+ Copy(ip, &ip6, sizeof(IP));
+
+ b = true;
+ }
+
+ if (IsZeroIp(&ip4) == false)
+ {
+ Copy(ip, &ip4, sizeof(IP));
+
+ b = true;
+ }
+
+ return b;
+}
+
+// Get either of v4 and v6 results with a DNS forward lookup (The IPv6 precedes in the case of both)
+bool GetIP46Any6(IP *ip, char *hostname)
+{
+ IP ip4, ip6;
+ bool b = false;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (GetIP46(&ip4, &ip6, hostname) == false)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(&ip4) == false)
+ {
+ Copy(ip, &ip4, sizeof(IP));
+
+ b = true;
+ }
+
+ if (IsZeroIp(&ip6) == false)
+ {
+ Copy(ip, &ip6, sizeof(IP));
+
+ b = true;
+ }
+
+ return b;
+}
+
+// Obtain in both v4 and v6 results with a DNS forward lookup
+bool GetIP46(IP *ip4, IP *ip6, char *hostname)
+{
+ return GetIP46Ex(ip4, ip6, hostname, 0, NULL);
+}
+bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel)
+{
+ IP a, b;
+ bool ok_a, ok_b;
+ // Validate arguments
+ if (ip4 == NULL || ip6 == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ ZeroIP4(ip4);
+ ZeroIP6(ip6);
+
+ ok_a = ok_b = false;
+
+ if (GetIP6Ex(&a, hostname, timeout, cancel))
+ {
+ ok_a = true;
+ }
+
+ if (GetIP4Ex(&b, hostname, timeout, cancel))
+ {
+ ok_b = true;
+ }
+
+ if (ok_a)
+ {
+ if (IsIP4(&a))
+ {
+ Copy(ip4, &a, sizeof(IP));
+ }
+ }
+ if (ok_b)
+ {
+ if (IsIP4(&b))
+ {
+ Copy(ip4, &b, sizeof(IP));
+ }
+
+ if (IsIP6(&b))
+ {
+ Copy(ip6, &b, sizeof(IP));
+ }
+ }
+ if (ok_a)
+ {
+ if (IsIP6(&a))
+ {
+ Copy(ip6, &a, sizeof(IP));
+ }
+ }
+
+ if (IsZeroIp(ip4) && IsZeroIp(ip6))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Clean-up of the parameters for GetIP thread
+void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p);
+}
+
+// Release of the parameters of the GetIP for thread
+void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (Release(p->Ref) == 0)
+ {
+ CleanupGetIPThreadParam(p);
+ }
+}
+
+// Thread to perform to query the DNS forward lookup (with timeout)
+void GetIP4Ex6ExThread(THREAD *t, void *param)
+{
+ GETIP_THREAD_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p = (GETIP_THREAD_PARAM *)param;
+
+ AddRef(p->Ref);
+
+ NoticeThreadInit(t);
+
+ AddWaitThread(t);
+
+ // Execution of resolution
+ if (p->IPv6 == false)
+ {
+ // IPv4
+ p->Ok = GetIP4Inner(&p->Ip, p->HostName);
+ }
+ else
+ {
+ // IPv6
+ p->Ok = GetIP6Inner(&p->Ip, p->HostName);
+ }
+
+ ReleaseGetIPThreadParam(p);
+
+ DelWaitThread(t);
+}
+
+// Perform a forward DNS query (with timeout)
+bool GetIP4Ex6Ex(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel)
+{
+ return GetIP4Ex6Ex2(ip, hostname_arg, timeout, ipv6, cancel, false);
+}
+bool GetIP4Ex6Ex2(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns)
+{
+ GETIP_THREAD_PARAM *p;
+ THREAD *t;
+ bool ret = false;
+ UINT64 start_tick = 0;
+ UINT64 end_tick = 0;
+ bool use_dns_proxy = false;
+ char hostname[260];
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || hostname_arg == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_GETIP;
+ }
+
+ Zero(hostname, sizeof(hostname));
+ StrCpy(hostname, sizeof(hostname), hostname_arg);
+
+ i = SearchStrEx(hostname, "/", 0, true);
+ if (i != INFINITE)
+ {
+ hostname[i] = 0;
+ }
+
+ if (ipv6 == false)
+ {
+ IP ip2;
+
+ if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false)
+ {
+ if (IsIP4(&ip2))
+ {
+ // IPv4 address direct specification
+ Copy(ip, &ip2, sizeof(IP));
+ return true;
+ }
+ else
+ {
+ // IPv6 address direct specification
+ return false;
+ }
+ }
+ }
+ else
+ {
+ IP ip2;
+
+ if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false)
+ {
+ if (IsIP6(&ip2))
+ {
+ // IPv6 address direct specification
+ Copy(ip, &ip2, sizeof(IP));
+ return true;
+ }
+ else
+ {
+ // IPv4 address direct specification
+ return false;
+ }
+ }
+ }
+
+ if (only_direct_dns == false)
+ {
+ if (ipv6 == false)
+ {
+ if (IsUseDnsProxy())
+ {
+ use_dns_proxy = true;
+ }
+ }
+ }
+
+
+ p = ZeroMalloc(sizeof(GETIP_THREAD_PARAM));
+ p->Ref = NewRef();
+ StrCpy(p->HostName, sizeof(p->HostName), hostname);
+ p->IPv6 = ipv6;
+ p->Timeout = timeout;
+ p->Ok = false;
+
+ t = NewThread(GetIP4Ex6ExThread, p);
+ WaitThreadInit(t);
+
+ if (cancel == NULL)
+ {
+ WaitThread(t, timeout);
+ }
+ else
+ {
+ start_tick = Tick64();
+ end_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT64 remain;
+ UINT remain32;
+
+ if (*cancel)
+ {
+ break;
+ }
+
+ if (now >= end_tick)
+ {
+ break;
+ }
+
+ remain = end_tick - now;
+ remain32 = MIN((UINT)remain, 100);
+
+ if (WaitThread(t, remain32))
+ {
+ break;
+ }
+ }
+ }
+
+ ReleaseThread(t);
+
+ if (p->Ok)
+ {
+ ret = true;
+ Copy(ip, &p->Ip, sizeof(IP));
+ }
+ else
+ {
+ IP ip2;
+
+ if (only_direct_dns == false)
+ {
+ if (ipv6)
+ {
+ UINT flets_type = DetectFletsType();
+
+ // if I'm in the FLETs of NTT East,
+ // try to get an IP address using the DNS proxy server
+ if ((flets_type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, NULL))
+ {
+ // B FLETs
+ ret = true;
+ }
+ else if ((flets_type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_EAST_DNS_PROXY_HOSTNAME))
+ {
+ // FLET'S Hikar-Next (NTT East)
+ ret = true;
+ }
+ else if ((flets_type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_WEST_DNS_PROXY_HOSTNAME))
+ {
+ // FLET'S Hikar-Next (NTT West)
+ ret = true;
+ }
+ }
+ }
+
+ if (QueryDnsCache(&ip2, hostname))
+ {
+ ret = true;
+
+ Copy(ip, &ip2, sizeof(IP));
+ }
+ }
+
+
+ ReleaseGetIPThreadParam(p);
+
+ return ret;
+}
+bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
+{
+ return GetIP4Ex6Ex(ip, hostname, timeout, false, cancel);
+}
+bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
+{
+ return GetIP4Ex6Ex(ip, hostname, timeout, true, cancel);
+}
+bool GetIP4(IP *ip, char *hostname)
+{
+ return GetIP4Ex(ip, hostname, 0, NULL);
+}
+bool GetIP6(IP *ip, char *hostname)
+{
+ return GetIP6Ex(ip, hostname, 0, NULL);
+}
+
+// Perform a DNS forward lookup query
+bool GetIP(IP *ip, char *hostname)
+{
+ return GetIPEx(ip, hostname, false);
+}
+bool GetIPEx(IP *ip, char *hostname, bool ipv6)
+{
+ if (ipv6 == false)
+ {
+ return GetIP4(ip, hostname);
+ }
+ else
+ {
+ return GetIP6(ip, hostname);
+ }
+}
+bool GetIP6Inner(IP *ip, char *hostname)
+{
+ struct sockaddr_in6 in;
+ struct in6_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(hostname))
+ {
+ return false;
+ }
+
+ if (StrCmpi(hostname, "localhost") == 0)
+ {
+ GetLocalHostIP6(ip);
+ return true;
+ }
+
+ if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
+ {
+ // Forward resolution
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET6;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
+ info->ai_family != AF_INET6)
+ {
+ if (info)
+ {
+ freeaddrinfo(info);
+ }
+ return QueryDnsCacheEx(ip, hostname, true);
+ }
+ // Forward resolution success
+ Copy(&in, info->ai_addr, sizeof(struct sockaddr_in6));
+ freeaddrinfo(info);
+
+ Copy(&addr, &in.sin6_addr, sizeof(addr));
+ InAddrToIP6(ip, &addr);
+ }
+
+ // Save Cache
+ NewDnsCache(hostname, ip);
+
+ return true;
+}
+bool GetIP4Inner(IP *ip, char *hostname)
+{
+ struct sockaddr_in in;
+ struct in_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(hostname))
+ {
+ return false;
+ }
+
+ if (StrCmpi(hostname, "localhost") == 0)
+ {
+ SetIP(ip, 127, 0, 0, 1);
+ return true;
+ }
+
+ if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
+ {
+ // Forward resolution
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
+ info->ai_family != AF_INET)
+ {
+ if (info)
+ {
+ freeaddrinfo(info);
+ }
+ return QueryDnsCache(ip, hostname);
+ }
+ // Forward resolution success
+ Copy(&in, info->ai_addr, sizeof(struct sockaddr_in));
+ freeaddrinfo(info);
+ Copy(&addr, &in.sin_addr, sizeof(addr));
+ InAddrToIP(ip, &addr);
+ }
+
+ // Save Cache
+ NewDnsCache(hostname, ip);
+
+ return true;
+}
+
+// Search in the DNS cache
+bool QueryDnsCache(IP *ip, char *hostname)
+{
+ return QueryDnsCacheEx(ip, hostname, false);
+}
+bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ c = FindDnsCache(tmp);
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Copy(ip, &c->IpAddress, sizeof(IP));
+
+ return true;
+}
+
+// Convert the IP to a string
+void IPToUniStr(wchar_t *str, UINT size, IP *ip)
+{
+ char tmp[128];
+
+ IPToStr(tmp, sizeof(tmp), ip);
+ StrToUni(str, size, tmp);
+}
+
+// Convert the IP to a string (32bit UINT)
+void IPToUniStr32(wchar_t *str, UINT size, UINT ip)
+{
+ char tmp[128];
+
+ IPToStr32(tmp, sizeof(tmp), ip);
+ StrToUni(str, size, tmp);
+}
+
+// Convert the IP to a string (128bit byte array)
+void IPToStr128(char *str, UINT size, UCHAR *ip_bytes)
+{
+ IP ip_st;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ SetIP6(&ip_st, ip_bytes);
+ IPToStr(str, size, &ip_st);
+}
+
+// Convert the IP to a string (32bit UINT)
+void IPToStr32(char *str, UINT size, UINT ip)
+{
+ IP ip_st;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip_st, ip);
+ IPToStr(str, size, &ip_st);
+}
+
+// Convert IPv4 or IPv6 to a string
+void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes)
+{
+ IP ip4;
+ IP ip6;
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ Zero(&ip, sizeof(ip));
+
+ UINTToIP(&ip4, ip_4_uint);
+ SetIP6(&ip6, ip_6_bytes);
+
+ if (IsIP6(&ip4) || (IsZeroIp(&ip4) && (IsZeroIp(&ip6) == false)))
+ {
+ Copy(&ip, &ip6, sizeof(IP));
+ }
+ else
+ {
+ Copy(&ip, &ip4, sizeof(IP));
+ }
+
+ IPToStr(str, size, &ip);
+}
+
+// Convert the IP to a string
+void IPToStr(char *str, UINT size, IP *ip)
+{
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ if (IsIP6(ip))
+ {
+ IPToStr6(str, size, ip);
+ }
+ else
+ {
+ IPToStr4(str, size, ip);
+ }
+}
+
+// Convert the IPv4 to a string
+void IPToStr4(char *str, UINT size, IP *ip)
+{
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ // Conversion
+ snprintf(str, size != 0 ? size : 64, "%u.%u.%u.%u", ip->addr[0], ip->addr[1], ip->addr[2], ip->addr[3]);
+}
+
+// Convert the string to an IP
+bool StrToIP(IP *ip, char *str)
+{
+ TOKEN_LIST *token;
+ char *tmp;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(ip, str))
+ {
+ return true;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ tmp = CopyStr(str);
+ Trim(tmp);
+ token = ParseToken(tmp, ".");
+ Free(tmp);
+
+ if (token->NumTokens != 4)
+ {
+ FreeToken(token);
+ return false;
+ }
+ for (i = 0;i < 4;i++)
+ {
+ char *s = token->Token[i];
+ if (s[0] < '0' || s[0] > '9' ||
+ (ToInt(s) >= 256))
+ {
+ FreeToken(token);
+ return false;
+ }
+ }
+ Zero(ip, sizeof(IP));
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = (UCHAR)ToInt(token->Token[i]);
+ }
+
+ FreeToken(token);
+
+ return true;
+}
+UINT StrToIP32(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (StrToIP(&ip, str) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&ip);
+}
+bool UniStrToIP(IP *ip, wchar_t *str)
+{
+ char *tmp;
+ bool ret;
+
+ tmp = CopyUniToStr(str);
+ ret = StrToIP(ip, tmp);
+ Free(tmp);
+
+ return ret;
+}
+UINT UniStrToIP32(wchar_t *str)
+{
+ UINT ret;
+ char *tmp;
+
+ tmp = CopyUniToStr(str);
+ ret = StrToIP32(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the IP to the in_addr
+void IPToInAddr(struct in_addr *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Zero(addr, sizeof(struct in_addr));
+
+ if (IsIP6(ip) == false)
+ {
+ for (i = 0;i < 4;i++)
+ {
+ ((UCHAR *)addr)[i] = ip->addr[i];
+ }
+ }
+}
+
+// Convert the IP to the in6_addr
+void IPToInAddr6(struct in6_addr *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Zero(addr, sizeof(struct in_addr));
+
+ if (IsIP6(ip))
+ {
+ for (i = 0;i < 16;i++)
+ {
+ ((UCHAR *)addr)[i] = ip->ipv6_addr[i];
+ }
+ }
+}
+
+// Convert the in_addr to the IP
+void InAddrToIP(IP *ip, struct in_addr *addr)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = ((UCHAR *)addr)[i];
+ }
+}
+
+// Convert the in6_addr to the IP
+void InAddrToIP6(IP *ip, struct in6_addr *addr)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+ for (i = 0;i < 16;i++)
+ {
+ ip->ipv6_addr[i] = ((UCHAR *)addr)[i];
+ }
+}
+
+// Search in the DNS cache
+DNSCACHE *FindDnsCache(char *hostname)
+{
+ return FindDnsCacheEx(hostname, false);
+}
+DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_SIZE];
+ if (hostname == NULL)
+ {
+ return NULL;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ LockDnsCache();
+ {
+ DNSCACHE t;
+ t.HostName = tmp;
+ c = Search(DnsCache, &t);
+ }
+ UnlockDnsCache();
+
+ return c;
+}
+
+// Generate the IPv4 / IPv6 key name for the DNS cache
+void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (ipv6 == false)
+ {
+ StrCpy(dst, size, src);
+ }
+ else
+ {
+ Format(dst, size, "%s@ipv6", src);
+ }
+}
+
+// Registration of the new DNS cache
+void NewDnsCache(char *hostname, IP *ip)
+{
+ NewDnsCacheEx(hostname, ip, IsIP6(ip));
+}
+void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ if (IsNetworkNameCacheEnabled() == false)
+ {
+ return;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ LockDnsCache();
+ {
+ DNSCACHE t;
+
+ // Search for anything matches to the hostname first
+ t.HostName = tmp;
+ c = Search(DnsCache, &t);
+
+ if (c == NULL)
+ {
+ // Newly register
+ c = ZeroMalloc(sizeof(DNSCACHE));
+ c->HostName = CopyStr(tmp);
+
+ Copy(&c->IpAddress, ip, sizeof(IP));
+
+ Add(DnsCache, c);
+ }
+ else
+ {
+ // Update
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ }
+ }
+ UnlockDnsCache();
+}
+
+// Name comparison of the DNS cache entries
+int CompareDnsCache(void *p1, void *p2)
+{
+ DNSCACHE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(DNSCACHE **)p1;
+ c2 = *(DNSCACHE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(c1->HostName, c2->HostName);
+}
+
+// Initialization of the DNS cache
+void InitDnsCache()
+{
+ // Creating a List
+ DnsCache = NewList(CompareDnsCache);
+}
+
+// Release of the DNS cache
+void FreeDnsCache()
+{
+ LockDnsCache();
+ {
+ DNSCACHE *c;
+ UINT i;
+ for (i = 0;i < LIST_NUM(DnsCache);i++)
+ {
+ // Release the memory for the entry
+ c = LIST_DATA(DnsCache, i);
+ Free(c->HostName);
+ Free(c);
+ }
+ }
+ UnlockDnsCache();
+
+ // Release the list
+ ReleaseList(DnsCache);
+ DnsCache = NULL;
+}
+
+// Lock the DNS cache
+void LockDnsCache()
+{
+ LockList(DnsCache);
+}
+
+// Unlock the DNS cache
+void UnlockDnsCache()
+{
+ UnlockList(DnsCache);
+}
+
+// Create the SSL_CTX
+struct ssl_ctx_st *NewSSLCtx()
+{
+ struct ssl_ctx_st *ctx = SSL_CTX_new(SSLv23_method());
+
+#ifdef SSL_OP_NO_TICKET
+ SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
+#endif // SSL_OP_NO_TICKET
+
+ return ctx;
+}
+
+// Release of the SSL_CTX
+void FreeSSLCtx(struct ssl_ctx_st *ctx)
+{
+ // Validate arguments
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ SSL_CTX_free(ctx);
+}
+
+// Initialize the network communication module
+void InitNetwork()
+{
+
+ InitDynList();
+
+
+ host_ip_address_list_cache_lock = NewLock();
+ host_ip_address_list_cache_last = 0;
+
+ num_tcp_connections = NewCounter();
+
+ // Initialization of client list
+ InitIpClientList();
+
+ // Thread related initialization
+ InitWaitThread();
+
+ // Initialization of the host name cache
+ InitHostCache();
+
+#ifdef OS_WIN32
+ // Initializing the socket library
+ Win32InitSocketLibrary();
+#else
+ UnixInitSocketLibrary();
+#endif // OS_WIN32
+
+ // Initialization of the DNS cache
+ InitDnsCache();
+
+ // Locking initialization
+ machine_name_lock = NewLock();
+ disconnect_function_lock = NewLock();
+ aho = NewLock();
+ machine_ip_process_hash_lock = NewLock();
+ socket_library_lock = NewLock();
+ //ssl_connect_lock = NewLock(); //2012.9.28 Not required for recent OpenSSL
+// ssl_accept_lock = NewLock();
+ dns_lock = NewLock();
+ unix_dns_server_addr_lock = NewLock();
+ Zero(&unix_dns_server, sizeof(unix_dns_server));
+ local_mac_list_lock = NewLock();
+
+ cipher_list_token = ParseToken(cipher_list, " ");
+
+ current_global_ip_lock = NewLock();
+ current_fqdn_lock = NewLock();
+ current_global_ip_set = false;
+
+ disable_cache = false;
+
+
+ Zero(rand_port_numbers, sizeof(rand_port_numbers));
+}
+
+// Enable the network name cache
+void EnableNetworkNameCache()
+{
+ disable_cache = false;
+}
+
+// Disable the network name cache
+void DisableNetworkNameCache()
+{
+ disable_cache = true;
+}
+
+// Get whether the network name cache is enabled
+bool IsNetworkNameCacheEnabled()
+{
+ return !disable_cache;
+}
+
+// Get the cipher algorithm list
+TOKEN_LIST *GetCipherList()
+{
+ return cipher_list_token;
+}
+
+// Get the TCP connections counter
+COUNTER *GetNumTcpConnectionsCounter()
+{
+ return num_tcp_connections;
+}
+
+// Get the current global IP address
+bool GetCurrentGlobalIP(IP *ip, bool ipv6)
+{
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ Lock(current_global_ip_lock);
+ {
+ if (ipv6 == false)
+ {
+ Copy(ip, &current_glocal_ipv4, sizeof(IP));
+ }
+ else
+ {
+ Copy(ip, &current_glocal_ipv6, sizeof(IP));
+ }
+
+ ret = current_global_ip_set;
+ }
+ Unlock(current_global_ip_lock);
+
+ return ret;
+}
+
+// Check whether the specified IP address is assigned to the local host
+bool IsIPMyHost(IP *ip)
+{
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(ip))
+ {
+ return false;
+ }
+
+ // Search to check whether it matches to any of the IP of the local host
+ o = GetHostIPAddressList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (CmpIpAddr(p, ip) == 0)
+ {
+ // Matched
+ ret = true;
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ if (ret == false)
+ {
+ if (IsLocalHostIP(ip))
+ {
+ // localhost IP addresses
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Check whether the specified IP address is a private IP address
+bool IsIPPrivate(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 10)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 172)
+ {
+ if (ip->addr[1] >= 16 && ip->addr[1] <= 31)
+ {
+ return true;
+ }
+ }
+
+ if (ip->addr[0] == 192 && ip->addr[1] == 168)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 169 && ip->addr[1] == 254)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 100)
+ {
+ if (ip->addr[1] >= 64 && ip->addr[1] <= 127)
+ {
+ return true;
+ }
+ }
+
+ if (g_private_ip_list != NULL)
+ {
+ if (IsIP4(ip))
+ {
+ UINT ip4 = IPToUINT(ip);
+
+ return IsOnPrivateIPFile(ip4);
+ }
+ }
+
+ return false;
+}
+
+// Read a private IP list file
+void LoadPrivateIPFile()
+{
+ BUF *b = ReadDump(PRIVATE_IP_TXT_FILENAME);
+ LIST *o;
+ if (b == NULL)
+ {
+ return;
+ }
+
+ o = NewList(NULL);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ UINT ip = 0, mask = 0;
+
+ if (ParseIpAndSubnetMask4(line, &ip, &mask))
+ {
+ PRIVATE_IP_SUBNET *p = ZeroMalloc(sizeof(PRIVATE_IP_SUBNET));
+
+ p->Ip = ip;
+ p->Mask = mask;
+ p->Ip2 = ip & mask;
+
+ Add(o, p);
+ }
+ }
+
+ Free(line);
+ }
+
+ g_private_ip_list = o;
+ g_use_privateip_file = true;
+
+ FreeBuf(b);
+}
+
+// Examine whether the specified IP address is in the private IP file
+bool IsOnPrivateIPFile(UINT ip)
+{
+ bool ret = false;
+
+ if (g_private_ip_list != NULL)
+ {
+ LIST *o = g_private_ip_list;
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PRIVATE_IP_SUBNET *p = LIST_DATA(o, i);
+
+ if ((ip & p->Mask) == p->Ip2)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Free the private IP file
+void FreePrivateIPFile()
+{
+ if (g_private_ip_list != NULL)
+ {
+ LIST *o = g_private_ip_list;
+ UINT i;
+
+ g_private_ip_list = NULL;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PRIVATE_IP_SUBNET *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+ }
+
+ g_use_privateip_file = false;
+}
+
+// Guess the IPv4, IPv6 global address from the IP address list of the current interface
+void GetCurrentGlobalIPGuess(IP *ip, bool ipv6)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ o = GetHostIPAddressList();
+
+ if (ipv6 == false)
+ {
+ // IPv4
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP4(p))
+ {
+ if (IsZeroIp(p) == false && IsIPPrivate(p) == false && p->addr[0] != 127)
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+
+ if (IsZeroIp(ip))
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP4(p))
+ {
+ if (IsZeroIp(p) == false && IsIPPrivate(p) && p->addr[0] != 127)
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+ }
+
+ if (IsZeroIp(ip))
+ {
+ SetIP(ip, 127, 0, 0, 1);
+ }
+ }
+ else
+ {
+ // IPv6
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP6(p))
+ {
+ UINT type = GetIPAddrType6(p);
+
+ if ((type & IPV6_ADDR_GLOBAL_UNICAST) && ((type & IPV6_ADDR_ZERO) == 0) && ((type & IPV6_ADDR_LOOPBACK) == 0))
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+}
+
+// Record the current global IP address
+void SetCurrentGlobalIP(IP *ip, bool ipv6)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ if (IsZeroIp(ip));
+ {
+ return;
+ }
+
+ Lock(current_global_ip_lock);
+ {
+ if (ipv6 == false)
+ {
+ Copy(&current_glocal_ipv4, ip, sizeof(IP));
+ }
+ else
+ {
+ Copy(&current_glocal_ipv6, ip, sizeof(IP));
+ }
+
+ current_global_ip_set = true;
+ }
+ Unlock(current_global_ip_lock);
+}
+
+// Release of the network communication module
+void FreeNetwork()
+{
+
+ // Release of thread-related
+ FreeWaitThread();
+
+ FreeToken(cipher_list_token);
+ cipher_list_token = NULL;
+
+ Zero(&unix_dns_server, sizeof(unix_dns_server));
+
+ // Release the locks
+ DeleteLock(unix_dns_server_addr_lock);
+ DeleteLock(dns_lock);
+ DeleteLock(ssl_accept_lock);
+ DeleteLock(machine_name_lock);
+ DeleteLock(disconnect_function_lock);
+ DeleteLock(aho);
+ DeleteLock(socket_library_lock);
+ DeleteLock(ssl_connect_lock);
+ DeleteLock(machine_ip_process_hash_lock);
+ machine_name_lock = NULL;
+ ssl_accept_lock = machine_name_lock = disconnect_function_lock =
+ aho = socket_library_lock = ssl_connect_lock = machine_ip_process_hash_lock = NULL;
+
+ // Release of the DNS cache
+ FreeDnsCache();
+
+ // Release of the host name cache
+ FreeHostCache();
+
+#ifdef OS_WIN32
+ // Release of the socket library
+ Win32FreeSocketLibrary();
+#else
+ UnixFreeSocketLibrary();
+#endif // OS_WIN32
+
+ DeleteCounter(num_tcp_connections);
+ num_tcp_connections = NULL;
+
+ // Release of client list
+ FreeIpClientList();
+
+ DeleteLock(current_global_ip_lock);
+ current_global_ip_lock = NULL;
+
+ DeleteLock(current_fqdn_lock);
+ current_fqdn_lock = NULL;
+
+ // Release of the local MAC list
+ if (local_mac_list != NULL)
+ {
+ FreeNicList(local_mac_list);
+ local_mac_list = NULL;
+ }
+
+ DeleteLock(local_mac_list_lock);
+ local_mac_list_lock = NULL;
+
+ DeleteLock(host_ip_address_list_cache_lock);
+ host_ip_address_list_cache_lock = NULL;
+
+ FreeHostIPAddressList(host_ip_address_cache);
+ host_ip_address_cache = NULL;
+
+
+ FreeDynList();
+
+}
+
+// Add a socket to socket list
+void AddSockList(SOCKLIST *sl, SOCK *s)
+{
+ // Validate arguments
+ if (sl == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ if (IsInList(sl->SockList, s) == false)
+ {
+ AddRef(s->ref);
+
+ Insert(sl->SockList, s);
+ }
+ }
+ UnlockList(sl->SockList);
+}
+
+// Remove the socket from socket list
+void DelSockList(SOCKLIST *sl, SOCK *s)
+{
+ // Validate arguments
+ if (sl == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ if (Delete(sl->SockList, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(sl->SockList);
+}
+
+// Stop all the sockets in the list and delete it
+void StopSockList(SOCKLIST *sl)
+{
+ SOCK **ss;
+ UINT num, i;
+ // Validate arguments
+ if (sl == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ num = LIST_NUM(sl->SockList);
+ ss = ToArray(sl->SockList);
+
+ DeleteAll(sl->SockList);
+ }
+ UnlockList(sl->SockList);
+
+ for (i = 0;i < num;i++)
+ {
+ SOCK *s = ss[i];
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ Free(ss);
+}
+
+// Delete the socket list
+void FreeSockList(SOCKLIST *sl)
+{
+ // Validate arguments
+ if (sl == NULL)
+ {
+ return;
+ }
+
+ StopSockList(sl);
+
+ ReleaseList(sl->SockList);
+
+ Free(sl);
+}
+
+// Creating a socket list
+SOCKLIST *NewSockList()
+{
+ SOCKLIST *sl = ZeroMallocFast(sizeof(SOCKLIST));
+
+ sl->SockList = NewList(NULL);
+
+ return sl;
+}
+
+// Time-out thread of the socket on Solaris
+void SocketTimeoutThread(THREAD *t, void *param)
+{
+ SOCKET_TIMEOUT_PARAM *ttparam;
+ ttparam = (SOCKET_TIMEOUT_PARAM *)param;
+
+ // Wait for time-out period
+ Select(NULL, ttparam->sock->TimeOut, ttparam->cancel, NULL);
+
+ // Disconnect if it is blocked
+ if(! ttparam->unblocked)
+ {
+// Debug("Socket timeouted\n");
+ closesocket(ttparam->sock->socket);
+ }
+ else
+ {
+// Debug("Socket timeout cancelled\n");
+ }
+}
+
+// Initialize and start the thread for time-out
+SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock)
+{
+ SOCKET_TIMEOUT_PARAM *ttp;
+ if(! sock->AsyncMode && sock->TimeOut != TIMEOUT_INFINITE)
+ {
+// Debug("NewSockTimeout(%u)\n",sock->TimeOut);
+
+ ttp = (SOCKET_TIMEOUT_PARAM*)Malloc(sizeof(SOCKET_TIMEOUT_PARAM));
+
+ // Set the parameters of the time-out thread
+ ttp->cancel = NewCancel();
+ ttp->sock = sock;
+ ttp->unblocked = false;
+ ttp->thread = NewThread(SocketTimeoutThread, ttp);
+ return ttp;
+ }
+ return NULL;
+}
+
+// Stop and free the thread for timeout
+void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp)
+{
+ if(ttp == NULL)
+ {
+ return;
+ }
+
+ ttp->unblocked = true;
+ Cancel(ttp->cancel);
+ WaitThread(ttp->thread, INFINITE);
+ ReleaseCancel(ttp->cancel);
+ ReleaseThread(ttp->thread);
+ Free(ttp);
+// Debug("FreeSocketTimeout succeed\n");
+ return;
+}
+
+// Parse the IP address and subnet mask
+bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask)
+{
+ // Validate arguments
+ if (src == NULL || ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ if (ParseIpAndMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip))
+ {
+ return IsSubnetMask4(mask);
+ }
+ else
+ {
+ return IsSubnetMask6(mask);
+ }
+}
+bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask)
+{
+ if (ParseIpAndSubnetMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask)
+{
+ IP ip2, mask2;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+
+ if (ParseIpAndSubnetMask46(src, &ip2, &mask2) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(&ip2) == false)
+ {
+ return false;
+ }
+
+ if (ip != NULL)
+ {
+ *ip = IPToUINT(&ip2);
+ }
+
+ if (mask != NULL)
+ {
+ *mask = IPToUINT(&mask2);
+ }
+
+ return true;
+}
+
+
+// Parse the IP address and the mask
+bool ParseIpAndMask46(char *src, IP *ip, IP *mask)
+{
+ TOKEN_LIST *t;
+ char *ipstr;
+ char *subnetstr;
+ bool ret = false;
+ IP ip2;
+ IP mask2;
+ // Validate arguments
+ if (src == NULL || ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip2, sizeof(IP));
+ Zero(&mask2, sizeof(IP));
+
+ t = ParseToken(src, "/");
+ if (t->NumTokens != 2)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ ipstr = t->Token[0];
+ subnetstr = t->Token[1];
+ Trim(ipstr);
+ Trim(subnetstr);
+
+ if (StrToIP(&ip2, ipstr))
+ {
+ if (StrToIP(&mask2, subnetstr))
+ {
+ // Compare the kind of the mask part and the IP address part to confirm same
+ if (IsIP6(&ip2) && IsIP6(&mask2))
+ {
+ // Both are IPv6
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ Copy(mask, &mask2, sizeof(IP));
+ }
+ else if (IsIP4(&ip2) && IsIP4(&mask2))
+ {
+ // Both are IPv4
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ Copy(mask, &mask2, sizeof(IP));
+ }
+ }
+ else
+ {
+ if (IsNum(subnetstr))
+ {
+ UINT i = ToInt(subnetstr);
+ // Mask part is a number
+ if (IsIP6(&ip2) && i <= 128)
+ {
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ IntToSubnetMask6(mask, i);
+ }
+ else if (i <= 32)
+ {
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ IntToSubnetMask4(mask, i);
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask)
+{
+ IP ip_ip, ip_mask;
+ if (ParseIpAndMask46(src, &ip_ip, &ip_mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(&ip_ip) == false)
+ {
+ return false;
+ }
+
+ if (ip != NULL)
+ {
+ *ip = IPToUINT(&ip_ip);
+ }
+
+ if (mask != NULL)
+ {
+ *mask = IPToUINT(&ip_mask);
+ }
+
+ return true;
+}
+bool ParseIpAndMask6(char *src, IP *ip, IP *mask)
+{
+ if (ParseIpAndMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+// Check whether the specification of the IPv4 address is correct
+bool IsIpStr4(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP32(str) == 0 && StrCmpi(str, "0.0.0.0") != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Check whether the specification of the IPv6 address is correct
+bool IsIpStr6(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Check whether the IP address specification is correct
+bool IsIpStr46(char *str)
+{
+ if (IsIpStr4(str) || IsIpStr6(str))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+// Convert the string to an IPv4 mask
+bool StrToMask4(IP *mask, char *str)
+{
+ // Validate arguments
+ if (mask == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (str[0] == '/')
+ {
+ str++;
+ }
+
+ if (IsNum(str))
+ {
+ UINT n = ToInt(str);
+
+ if (n <= 32)
+ {
+ IntToSubnetMask4(mask, n);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (StrToIP(mask, str) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return IsIP4(mask);
+ }
+ }
+}
+
+// Convert the string to an IPv6 mask
+bool StrToMask6(IP *mask, char *str)
+{
+ // Validate arguments
+ if (mask == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (str[0] == '/')
+ {
+ str++;
+ }
+
+ if (IsNum(str))
+ {
+ UINT n = ToInt(str);
+
+ if (n <= 128)
+ {
+ IntToSubnetMask6(mask, n);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (StrToIP(mask, str) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return IsIP6(mask);
+ }
+ }
+}
+bool StrToMask6Addr(IPV6_ADDR *mask, char *str)
+{
+ IP ip;
+
+ if (StrToMask6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(mask, &ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the string to an IPv4 / IPv6 mask
+bool StrToMask46(IP *mask, char *str, bool ipv6)
+{
+ if (ipv6)
+ {
+ return StrToMask6(mask, str);
+ }
+ else
+ {
+ return StrToMask4(mask, str);
+ }
+}
+
+
+// Convert the IPv4 / IPv6 mask to a string
+void MaskToStr(char *str, UINT size, IP *mask)
+{
+ MaskToStrEx(str, size, mask, false);
+}
+void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address)
+{
+ // Validate arguments
+ if (str == NULL || mask == NULL)
+ {
+ return;
+ }
+
+ if (always_full_address == false && IsSubnetMask(mask))
+ {
+ ToStr(str, SubnetMaskToInt(mask));
+ }
+ else
+ {
+ IPToStr(str, size, mask);
+ }
+}
+void MaskToStr32(char *str, UINT size, UINT mask)
+{
+ MaskToStr32Ex(str, size, mask, false);
+}
+void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address)
+{
+ IP ip;
+
+ UINTToIP(&ip, mask);
+
+ MaskToStrEx(str, size, &ip, always_full_address);
+}
+void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address)
+{
+ IP ip;
+
+ // Validate arguments
+ if (str == NULL || mask == NULL)
+ {
+ StrCpy(str, size, "");
+ return;
+ }
+
+ IPv6AddrToIP(&ip, mask);
+
+ MaskToStrEx(str, size, &ip, always_full_address);
+}
+void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask)
+{
+ Mask6AddrToStrEx(str, size, mask, false);
+}
+
+// Disconnecting of the tube
+void TubeDisconnect(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->TubePairData == NULL)
+ {
+ return;
+ }
+
+ Lock(t->TubePairData->Lock);
+ {
+ t->TubePairData->IsDisconnected = true;
+
+ Set(t->TubePairData->Event1);
+ Set(t->TubePairData->Event2);
+ SetSockEvent(t->TubePairData->SockEvent1);
+ SetSockEvent(t->TubePairData->SockEvent2);
+ }
+ Unlock(t->TubePairData->Lock);
+}
+
+// Creating a tube pair
+void NewTubePair(TUBE **t1, TUBE **t2, UINT size_of_header)
+{
+ TUBEPAIR_DATA *d;
+ // Validate arguments
+ if (t1 == NULL || t2 == NULL)
+ {
+ return;
+ }
+
+ *t1 = NewTube(size_of_header);
+ *t2 = NewTube(size_of_header);
+
+ (*t1)->IndexInTubePair = 0;
+ (*t2)->IndexInTubePair = 1;
+
+ d = NewTubePairData();
+ AddRef(d->Ref);
+
+ (*t1)->TubePairData = d;
+ (*t2)->TubePairData = d;
+
+ d->Event1 = (*t1)->Event;
+ d->Event2 = (*t2)->Event;
+
+ AddRef(d->Event1->ref);
+ AddRef(d->Event2->ref);
+}
+
+// Creating a tube pair data
+TUBEPAIR_DATA *NewTubePairData()
+{
+ TUBEPAIR_DATA *d = ZeroMalloc(sizeof(TUBEPAIR_DATA));
+
+ d->Ref = NewRef();
+
+ d->Lock = NewLock();
+
+ return d;
+}
+
+// Set the SockEvent to the tube
+void SetTubeSockEvent(TUBE *t, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Lock(t->Lock);
+ {
+ TUBEPAIR_DATA *d;
+
+ if (t->SockEvent != e)
+ {
+ if (t->SockEvent != NULL)
+ {
+ ReleaseSockEvent(t->SockEvent);
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ t->SockEvent = e;
+ }
+
+ d = t->TubePairData;
+
+ if (d != NULL)
+ {
+ Lock(d->Lock);
+ {
+ SOCK_EVENT **sep = (t->IndexInTubePair == 0 ? &d->SockEvent1 : &d->SockEvent2);
+
+ if (*sep != e)
+ {
+ if (*sep != NULL)
+ {
+ ReleaseSockEvent(*sep);
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ *sep = e;
+ }
+ }
+ Unlock(d->Lock);
+ }
+ }
+ Unlock(t->Lock);
+}
+
+// Release of the tube pair data
+void ReleaseTubePairData(TUBEPAIR_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ if (Release(d->Ref) == 0)
+ {
+ CleanupTubePairData(d);
+ }
+}
+void CleanupTubePairData(TUBEPAIR_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ ReleaseEvent(d->Event1);
+ ReleaseEvent(d->Event2);
+
+ ReleaseSockEvent(d->SockEvent1);
+ ReleaseSockEvent(d->SockEvent2);
+
+ DeleteLock(d->Lock);
+
+ Free(d);
+}
+
+// Check whether the tube is connected to the opponent still
+bool IsTubeConnected(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (t->TubePairData == NULL)
+ {
+ return true;
+ }
+
+ if (t->TubePairData->IsDisconnected)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Send the data to the tube
+bool TubeSend(TUBE *t, void *data, UINT size, void *header)
+{
+ return TubeSendEx(t, data, size, header, false);
+}
+bool TubeSendEx(TUBE *t, void *data, UINT size, void *header, bool no_flush)
+{
+ return TubeSendEx2(t, data, size, header, no_flush, 0);
+}
+bool TubeSendEx2(TUBE *t, void *data, UINT size, void *header, bool no_flush, UINT max_num_in_queue)
+{
+ // Validate arguments
+ if (t == NULL || data == NULL || size == 0)
+ {
+ return false;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return false;
+ }
+
+ LockQueue(t->Queue);
+ {
+ if (max_num_in_queue == 0 || (t->Queue->num_item <= max_num_in_queue))
+ {
+ InsertQueue(t->Queue, NewTubeData(data, size, header, t->SizeOfHeader));
+ }
+ else
+ {
+ no_flush = true;
+ }
+ }
+ UnlockQueue(t->Queue);
+
+ if (no_flush == false)
+ {
+ Set(t->Event);
+ SetSockEvent(t->SockEvent);
+ }
+
+ return true;
+}
+
+// Flush the tube
+void TubeFlush(TUBE *t)
+{
+ TubeFlushEx(t, false);
+}
+void TubeFlushEx(TUBE *t, bool force)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return;
+ }
+
+ if (force == false)
+ {
+ if (t->Queue->num_item == 0)
+ {
+ return;
+ }
+ }
+
+ Set(t->Event);
+ SetSockEvent(t->SockEvent);
+}
+
+// Receive the data from the tube (asynchronous)
+TUBEDATA *TubeRecvAsync(TUBE *t)
+{
+ TUBEDATA *d;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return NULL;
+ }
+
+ LockQueue(t->Queue);
+ {
+ d = GetNext(t->Queue);
+ }
+ UnlockQueue(t->Queue);
+
+ return d;
+}
+
+// Get the SockEvent associated with the tube
+SOCK_EVENT *GetTubeSockEvent(TUBE *t)
+{
+ SOCK_EVENT *e = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(t->Lock);
+ {
+ if (t->SockEvent != NULL)
+ {
+ AddRef(t->SockEvent->ref);
+
+ e = t->SockEvent;
+ }
+ }
+ Unlock(t->Lock);
+
+ return e;
+}
+
+// Receive the data from the tube (synchronous)
+TUBEDATA *TubeRecvSync(TUBE *t, UINT timeout)
+{
+ UINT64 start_tick, timeout_tick;
+ TUBEDATA *d = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return NULL;
+ }
+
+ start_tick = Tick64();
+ timeout_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT remain_time;
+ SOCK_EVENT *e;
+ UINT interval;
+
+ d = NULL;
+
+ if (IsTubeConnected(t) == false)
+ {
+ break;
+ }
+
+ LockQueue(t->Queue);
+ {
+ d = GetNext(t->Queue);
+ }
+ UnlockQueue(t->Queue);
+
+ if (d != NULL)
+ {
+ break;
+ }
+
+ if (timeout != INFINITE && now >= timeout_tick)
+ {
+ return NULL;
+ }
+
+ remain_time = (UINT)(timeout_tick - now);
+
+ e = GetTubeSockEvent(t);
+
+ interval = (timeout == INFINITE ? INFINITE : remain_time);
+
+ if (e == NULL)
+ {
+ Wait(t->Event, interval);
+ }
+ else
+ {
+ WaitSockEvent(e, interval);
+
+ ReleaseSockEvent(e);
+ }
+ }
+
+ return d;
+}
+
+// Creating a tube
+TUBE *NewTube(UINT size_of_header)
+{
+ TUBE *t = ZeroMalloc(sizeof(TUBE));
+
+ t->Event = NewEvent();
+ t->Queue = NewQueue();
+ t->Ref = NewRef();
+ t->Lock = NewLock();
+ t->SockEvent = NewSockEvent();
+
+ t->SizeOfHeader = size_of_header;
+
+ return t;
+}
+
+// Release of the tube
+void ReleaseTube(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (Release(t->Ref) == 0)
+ {
+ CleanupTube(t);
+ }
+}
+void CleanupTube(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ TUBEDATA *d = GetNext(t->Queue);
+ if (d == NULL)
+ {
+ break;
+ }
+
+ FreeTubeData(d);
+ }
+
+ ReleaseQueue(t->Queue);
+ ReleaseEvent(t->Event);
+ ReleaseSockEvent(t->SockEvent);
+
+ ReleaseTubePairData(t->TubePairData);
+
+ DeleteLock(t->Lock);
+
+ Free(t);
+}
+
+// Creating a tube data
+TUBEDATA *NewTubeData(void *data, UINT size, void *header, UINT header_size)
+{
+ TUBEDATA *d;
+ // Validate arguments
+ if (size == 0 || data == NULL)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(TUBEDATA));
+
+ d->Data = Clone(data, size);
+ d->DataSize = size;
+ if (header != NULL)
+ {
+ d->Header = Clone(header, header_size);
+ d->HeaderSize = header_size;
+ }
+ else
+ {
+ d->Header = ZeroMalloc(header_size);
+ }
+
+ return d;
+}
+
+// Release of the tube data
+void FreeTubeData(TUBEDATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Free(d->Data);
+ Free(d->Header);
+
+ Free(d);
+}
+
+// Release of the IP address list of the host
+void FreeHostIPAddressList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ Free(ip);
+ }
+
+ ReleaseList(o);
+}
+
+// Get whether the specified IP address is held by this host
+bool IsMyIPAddress(IP *ip)
+{
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ o = GetHostIPAddressList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *a = LIST_DATA(o, i);
+
+ if (CmpIpAddr(ip, a) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ return ret;
+}
+
+// Add the IP address to the list
+void AddHostIPAddressToList(LIST *o, IP *ip)
+{
+ IP *r;
+ // Validate arguments
+ if (o == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ r = Search(o, ip);
+ if (r != NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(ip, sizeof(IP)));
+}
+
+// Comparison of the IP address list items
+int CmpIpAddressList(void *p1, void *p2)
+{
+ IP *ip1, *ip2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ ip1 = *(IP **)p1;
+ ip2 = *(IP **)p2;
+ if (ip1 == NULL || ip2 == NULL)
+ {
+ return 0;
+ }
+
+ // IPv4 < IPv6
+ r = COMPARE_RET(IsIP6(ip1), IsIP6(ip2));
+ if (r != 0)
+ {
+ return r;
+ }
+
+ // any > specified IP
+ if (IsZeroIP(ip1) && IsZeroIP(ip2) == false)
+ {
+ return 1;
+ }
+ if (IsZeroIP(ip1) == false && IsZeroIP(ip2))
+ {
+ return -1;
+ }
+
+ // local > others
+ if (IsLocalHostIP(ip1) && IsLocalHostIP(ip2) == false)
+ {
+ return 1;
+ }
+ if (IsLocalHostIP(ip1) == false && IsLocalHostIP(ip2))
+ {
+ return -1;
+ }
+
+ // ip address
+ r = CmpIpAddr(ip1, ip2);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ // interface index
+ if (IsIP6(ip1))
+ {
+ r = COMPARE_RET(ip1->ipv6_scope_id, ip2->ipv6_scope_id);
+ }
+ else
+ {
+ r = 0;
+ }
+
+ return r;
+}
+
+// Get the IP address list of the host (using cache)
+LIST *GetHostIPAddressList()
+{
+ LIST *o = NULL;
+ if (host_ip_address_list_cache_lock == NULL)
+ {
+ return GetHostIPAddressListInternal();
+ }
+
+ Lock(host_ip_address_list_cache_lock);
+ {
+ UINT64 now = Tick64();
+
+ if (host_ip_address_list_cache_last == 0 ||
+ ((host_ip_address_list_cache_last + (UINT64)HOST_IP_ADDRESS_LIST_CACHE) < now) ||
+ host_ip_address_cache == NULL)
+ {
+ if (host_ip_address_cache != NULL)
+ {
+ FreeHostIPAddressList(host_ip_address_cache);
+ }
+
+ host_ip_address_cache = GetHostIPAddressListInternal();
+
+ host_ip_address_list_cache_last = now;
+ }
+
+ o = CloneIPAddressList(host_ip_address_cache);
+ }
+ Unlock(host_ip_address_list_cache_lock);
+
+ if (o == NULL)
+ {
+ o = GetHostIPAddressListInternal();
+ }
+
+ return o;
+}
+
+// Copy of the IP address list
+LIST *CloneIPAddressList(LIST *o)
+{
+ LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewListFast(CmpIpAddressList);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ if (ip != NULL)
+ {
+ ip = Clone(ip, sizeof(IP));
+
+ Add(ret, ip);
+ }
+ }
+
+ return ret;
+}
+
+// Get an IP address list of the host
+LIST *GetHostIPAddressListInternal()
+{
+ char hostname[MAX_SIZE];
+ LIST *o;
+ IP any6, any4;
+ IP local6, local4;
+ bool is_v6_supported = IsIPv6Supported();
+
+ GetLocalHostIP4(&local4);
+ GetLocalHostIP6(&local6);
+
+ ZeroIP4(&any4);
+ ZeroIP6(&any6);
+
+ Zero(hostname, sizeof(hostname));
+
+ gethostname(hostname, sizeof(hostname));
+
+ o = NewListFast(CmpIpAddressList);
+
+ // any
+ AddHostIPAddressToList(o, &any4);
+ if (is_v6_supported)
+ {
+ AddHostIPAddressToList(o, &any6);
+ }
+
+ // localhost
+ AddHostIPAddressToList(o, &local4);
+ if (is_v6_supported)
+ {
+ AddHostIPAddressToList(o, &local6);
+ }
+
+#ifndef MAYAQUA_SUPPORTS_GETIFADDRS
+ // IPv4
+ if (true)
+ {
+ struct sockaddr_in in;
+ struct in_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_protocol = IPPROTO_UDP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) == 0)
+ {
+ if (info->ai_family == AF_INET)
+ {
+ struct addrinfo *current = info;
+ while (current != NULL)
+ {
+ IP ip;
+
+ Copy(&in, current->ai_addr, sizeof(in));
+ Copy(&addr, &in.sin_addr, sizeof(addr));
+
+ InAddrToIP(&ip, &addr);
+ AddHostIPAddressToList(o, &ip);
+
+ current = current->ai_next;
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+ }
+
+#ifndef UNIX_LINUX
+ // IPv6
+ if (is_v6_supported)
+ {
+ struct sockaddr_in6 in;
+ struct in6_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET6;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_protocol = IPPROTO_UDP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) == 0)
+ {
+ if (info->ai_family == AF_INET6)
+ {
+ struct addrinfo *current = info;
+ while (current != NULL)
+ {
+ IP ip;
+
+ Copy(&in, current->ai_addr, sizeof(in));
+ Copy(&addr, &in.sin6_addr, sizeof(addr));
+
+ InAddrToIP6(&ip, &addr);
+ ip.ipv6_scope_id = in.sin6_scope_id;
+
+ AddHostIPAddressToList(o, &ip);
+
+ current = current->ai_next;
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+ }
+#endif // UNIX_LINUX
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+#ifdef MAYAQUA_SUPPORTS_GETIFADDRS
+ // If the getifaddrs is available, use this
+ if (true)
+ {
+ struct ifaddrs *aa = NULL;
+
+ if (getifaddrs(&aa) == 0)
+ {
+ struct ifaddrs *a = aa;
+
+ while (a != NULL)
+ {
+ if (a->ifa_addr != NULL)
+ {
+ struct sockaddr *addr = a->ifa_addr;
+
+ if (addr->sa_family == AF_INET)
+ {
+ IP ip;
+ struct sockaddr_in *d = (struct sockaddr_in *)addr;
+ struct in_addr *addr = &d->sin_addr;
+
+ InAddrToIP(&ip, addr);
+
+ AddHostIPAddressToList(o, &ip);
+ }
+ else if (addr->sa_family == AF_INET6)
+ {
+ IP ip;
+ struct sockaddr_in6 *d = (struct sockaddr_in6 *)addr;
+ UINT scope_id = d->sin6_scope_id;
+ struct in6_addr *addr = &d->sin6_addr;
+
+ InAddrToIP6(&ip, addr);
+ ip.ipv6_scope_id = scope_id;
+
+ AddHostIPAddressToList(o, &ip);
+ }
+ }
+
+ a = a->ifa_next;
+ }
+
+ freeifaddrs(aa);
+ }
+ }
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+ return o;
+}
+
+// Get whether the UDP listener opens the specified port
+bool IsUdpPortOpened(UDPLISTENER *u, IP *server_ip, UINT port)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return false;
+ }
+
+ if (server_ip != NULL)
+ {
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == port)
+ {
+ if (CmpIpAddr(server_ip, &us->IpAddress) == 0)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == port)
+ {
+ if (IsZeroIP(&us->IpAddress))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// IP address acquisition thread
+void QueryIpThreadMain(THREAD *thread, void *param)
+{
+ QUERYIPTHREAD *t = (QUERYIPTHREAD *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (t->Halt == false)
+ {
+ UINT next_wait_time = 0;
+ IP ip;
+ bool ok = false;
+
+ if (GetIP4Ex(&ip, t->Hostname, 5000, &t->Halt))
+ {
+ if (IsZeroIP(&ip) == false)
+ {
+ Lock(t->Lock);
+ {
+ Copy(&t->Ip, &ip, sizeof(IP));
+ }
+ Unlock(t->Lock);
+
+ ok = true;
+ }
+ }
+
+ if (ok == false)
+ {
+ next_wait_time = t->IntervalLastNg;
+ }
+ else
+ {
+ next_wait_time = t->IntervalLastOk;
+ }
+
+ if (t->Halt)
+ {
+ break;
+ }
+
+ Wait(t->HaltEvent, next_wait_time);
+ }
+}
+
+// Creating an IP address acquisition thread
+QUERYIPTHREAD *NewQueryIpThread(char *hostname, UINT interval_last_ok, UINT interval_last_ng)
+{
+ QUERYIPTHREAD *t;
+
+ t = ZeroMalloc(sizeof(QUERYIPTHREAD));
+
+ t->HaltEvent = NewEvent();
+ t->Lock = NewLock();
+ StrCpy(t->Hostname, sizeof(t->Hostname), hostname);
+ t->IntervalLastOk = interval_last_ok;
+ t->IntervalLastNg = interval_last_ng;
+
+ t->Thread = NewThread(QueryIpThreadMain, t);
+
+ return t;
+}
+
+// Get the results of the IP address acquisition thread
+bool GetQueryIpThreadResult(QUERYIPTHREAD *t, IP *ip)
+{
+ bool ret = false;
+ Zero(ip, sizeof(IP));
+ // Validate arguments
+ if (t == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ Lock(t->Lock);
+
+ if (IsZero(&t->Ip, sizeof(IP)))
+ {
+ ret = false;
+ }
+ else
+ {
+ Copy(ip, &t->Ip, sizeof(IP));
+ }
+
+ Unlock(t->Lock);
+
+ return ret;
+}
+
+// Release of the IP address acquisition thread
+void FreeQueryIpThread(QUERYIPTHREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ t->Halt = true;
+ Set(t->HaltEvent);
+
+ WaitThread(t->Thread, INFINITE);
+ ReleaseThread(t->Thread);
+
+ ReleaseEvent(t->HaltEvent);
+
+ DeleteLock(t->Lock);
+
+ Free(t);
+}
+
+// Get a public port list which is known by UDP listener
+void UdpListenerGetPublicPortList(UDPLISTENER *u, char *dst, UINT size)
+{
+ UINT k;
+ // Validate arguments
+ ClearStr(dst, size);
+ if (u == NULL || dst == NULL)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->PublicPort != 0)
+ {
+ char tmp[64];
+ ToStr(tmp, us->PublicPort);
+ StrCat(dst, size, tmp);
+ StrCat(dst, size, " ");
+ }
+ }
+ }
+ UnlockList(u->PortList);
+
+ Trim(dst);
+}
+
+// UDP listener thread
+void UdpListenerThread(THREAD *thread, void *param)
+{
+ UDPLISTENER *u = (UDPLISTENER *)param;
+ UINT i, j, k;
+ UINT buf_size = 65536;
+ void *buf;
+ bool cont_flag;
+ BUF *ip_list_buf = NewBuf();
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ buf = Malloc(buf_size);
+
+ // Initializing the socket list
+ u->SockList = NewList(NULL);
+
+ u->LastCheckTick = 0;
+
+// u->PollMyIpAndPort = true;
+
+ // Main loop
+ while (u->Halt == false)
+ {
+ LIST *recv_list;
+ UINT64 now = Tick64();
+ UINT interval;
+ bool stage_changed = false;
+ IP nat_t_ip;
+ Zero(&nat_t_ip, sizeof(nat_t_ip));
+
+ if (u->LastCheckTick == 0 || (now >= (u->LastCheckTick + UDPLISTENER_CHECK_INTERVAL)))
+ {
+ LIST *iplist;
+ LIST *del_us_list = NewListFast(NULL);
+ BUF *ip_list_buf_new = NewBuf();
+
+ u->LastCheckTick = now;
+
+ // Obtain an IP address list
+ iplist = GetHostIPAddressList();
+
+ LockList(u->PortList);
+ {
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ us->Mark = false;
+ }
+
+ // If the combination of the IP address and the port number doesn't exist in the list, add it to the list
+ for (i = 0;i < LIST_NUM(iplist);i++)
+ {
+ IP *ip = LIST_DATA(iplist, i);
+
+ WriteBuf(ip_list_buf_new, ip, sizeof(IP));
+
+ for (j = 0;j < LIST_NUM(u->PortList);j++)
+ {
+ UINT k;
+ UINT *port = LIST_DATA(u->PortList, j);
+ bool existing = false;
+
+ if (IsZeroIP(ip) && (IS_SPECIAL_PORT(*port)))
+ {
+ continue;
+ }
+
+
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (CmpIpAddr(&us->IpAddress, ip) == 0 && us->Port == *port)
+ {
+ existing = true;
+
+ us->Mark = true;
+
+ break;
+ }
+ }
+
+ if (existing == false)
+ {
+ UDPLISTENER_SOCK *us = ZeroMalloc(sizeof(UDPLISTENER_SOCK));
+
+ Copy(&us->IpAddress, ip, sizeof(IP));
+ us->Port = *port;
+
+ us->Mark = true;
+
+ Add(u->SockList, us);
+ }
+ }
+ }
+
+ // If any errors suspected or the combination of IP address and port number
+ // has been regarded to delete already, delete it
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Mark == false || us->HasError)
+ {
+ Debug("mark=%u error=%u\n", us->Mark, us->HasError);
+ Add(del_us_list, us);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(del_us_list);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(del_us_list, i);
+
+ char ipstr[MAX_SIZE];
+
+ IPToStr(ipstr, sizeof(ipstr), &us->IpAddress);
+ Debug("Closed UDP Port %u at %s.\n", us->Port, ipstr);
+
+ Delete(u->SockList, us);
+
+ if (us->Sock != NULL)
+ {
+ Disconnect(us->Sock);
+ ReleaseSock(us->Sock);
+ }
+
+ Free(us);
+ }
+ }
+ UnlockList(u->PortList);
+
+ // Open the UDP sockets which is not opend yet
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Sock == NULL)
+ {
+ char ipstr[MAX_SIZE];
+
+ IPToStr(ipstr, sizeof(ipstr), &us->IpAddress);
+
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Opening UDP Port %u at %s ...", us->Port, ipstr);
+ }
+
+ us->Sock = NewUDPEx2(us->Port, IsIP6(&us->IpAddress), &us->IpAddress);
+
+ if (us->Sock != NULL)
+ {
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Ok.\n");
+ }
+ else
+ {
+ Debug("Opening UDP Port %u at %s ...", us->Port, ipstr);
+ Debug("Ok.\n");
+ }
+ JoinSockToSockEvent(us->Sock, u->Event);
+
+ us->ErrorDebugDisplayed = false;
+ }
+ else
+ {
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Error.\n");
+ }
+
+ us->ErrorDebugDisplayed = true;
+ }
+ }
+ }
+
+ FreeHostIPAddressList(iplist);
+
+ ReleaseList(del_us_list);
+
+ if (CompareBuf(ip_list_buf, ip_list_buf_new) == false)
+ {
+ u->HostIPAddressListChanged = true;
+ }
+
+ FreeBuf(ip_list_buf);
+ ip_list_buf = ip_list_buf_new;
+ }
+
+LABEL_RESTART:
+
+ stage_changed = false;
+
+ recv_list = NewListFast(NULL);
+
+ if (u->PollMyIpAndPort)
+ {
+ // Create a thread to get a NAT-T IP address if necessary
+ if (u->GetNatTIpThread == NULL)
+ {
+ char natt_hostname[MAX_SIZE];
+
+ RUDPGetRegisterHostNameByIP(natt_hostname, sizeof(natt_hostname), NULL);
+
+ u->GetNatTIpThread = NewQueryIpThread(natt_hostname, QUERYIPTHREAD_INTERVAL_LAST_OK, QUERYIPTHREAD_INTERVAL_LAST_NG);
+ }
+
+ GetQueryIpThreadResult(u->GetNatTIpThread, &nat_t_ip);
+ }
+
+ // Receive the data that is arriving at the socket
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Sock != NULL)
+ {
+ UINT num_ignore_errors = 0;
+
+ if (u->PollMyIpAndPort && IsZeroIP(&nat_t_ip) == false && IsIP4(&us->IpAddress))
+ {
+ if (us->NextMyIpAndPortPollTick == 0 || us->NextMyIpAndPortPollTick <= now)
+ {
+ UCHAR c = 'A';
+
+ // Examine the self IP address and the self port number by using NAT-T server
+ us->NextMyIpAndPortPollTick = now + (UINT64)GenRandInterval(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX);
+
+ SendTo(us->Sock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1);
+ }
+ }
+
+ while (true)
+ {
+ IP src_addr;
+ UINT src_port;
+ UDPPACKET *p;
+
+ UINT size = RecvFrom(us->Sock, &src_addr, &src_port, buf, buf_size);
+ if (size == 0)
+ {
+ // Socket failure
+ if (us->Sock->IgnoreRecvErr == false)
+ {
+LABEL_FATAL_ERROR:
+ Debug("RecvFrom has Error.\n");
+ us->HasError = true;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+ }
+ break;
+ }
+ else if (size == SOCK_LATER)
+ {
+ // No packet
+ break;
+ }
+ //Debug("UDP %u\n", size);
+
+ if (src_port == UDP_NAT_T_PORT && CmpIpAddr(&src_addr, &nat_t_ip) == 0)
+ {
+ // Receive a packet in which the IP address and the port number are written from the NAT-T server
+ if (size >= 8)
+ {
+ IP my_ip;
+ UINT my_port;
+
+ if (RUDPParseIPAndPortStr(buf, size, &my_ip, &my_port))
+ {
+ Copy(&us->PublicIpAddress, &my_ip, sizeof(IP));
+ us->PublicPort = my_port;
+ }
+ }
+ }
+ else
+ {
+ // Receive a regular packet
+ p = NewUdpPacket(&src_addr, src_port, &us->Sock->LocalIP, us->Sock->LocalPort,
+ Clone(buf, size), size);
+
+ if (p->SrcPort == MAKE_SPECIAL_PORT(52))
+ {
+ p->SrcPort = p->DestPort = MAKE_SPECIAL_PORT(50);
+ }
+
+ Add(recv_list, p);
+ }
+
+ stage_changed = true;
+ }
+ }
+ }
+
+ // Pass the received packet to the procedure
+ u->RecvProc(u, recv_list);
+
+ // Release the packet
+ for (i = 0;i < LIST_NUM(recv_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(recv_list, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(recv_list);
+
+ cont_flag = true;
+
+ do
+ {
+ // When there are packets to be transmitted, transmit it
+ LockList(u->SendPacketList);
+ {
+ UDPLISTENER_SOCK *last_us = NULL;
+ IP last_src_ip;
+ UINT last_src_port;
+
+ Zero(&last_src_ip, sizeof(IP));
+ last_src_port = 0;
+
+ for (i = 0;i < LIST_NUM(u->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(u->SendPacketList, i);
+ UDPLISTENER_SOCK *us;
+
+ if (last_us != NULL && last_src_port == p->SrcPort && CmpIpAddr(&last_src_ip, &p->SrcIP) == 0)
+ {
+ us = last_us;
+ }
+ else
+ {
+ // Search for a good interface for the transmission
+ us = DetermineUdpSocketForSending(u, p);
+
+ if (us != NULL)
+ {
+ last_us = us;
+ last_src_port = p->SrcPort;
+ Copy(&last_src_ip, &p->SrcIP, sizeof(IP));
+ }
+ }
+
+ if (us != NULL)
+ {
+ // Send
+ UINT ret = SendTo(us->Sock, &p->DstIP, p->DestPort, p->Data, p->Size);
+
+ if (ret == 0)
+ {
+ if (us->Sock->IgnoreSendErr == false)
+ {
+ // Socket failure
+ Debug("SendTo has Error.\n");
+ us->HasError = true;
+ last_us = NULL;
+ }
+ }
+ else
+ {
+ if (ret != SOCK_LATER)
+ {
+ stage_changed = true;
+ }
+ }
+ }
+
+ FreeUdpPacket(p);
+ }
+ DeleteAll(u->SendPacketList);
+ }
+ UnlockList(u->SendPacketList);
+
+ if (LIST_NUM(u->SendPacketList) == 0)
+ {
+ cont_flag = false;
+ }
+ }
+ while (cont_flag);
+
+ if (stage_changed && u->Halt == false)
+ {
+ goto LABEL_RESTART;
+ }
+
+ // Timing adjustment
+ interval = GetNextIntervalForInterrupt(u->Interrupts);
+
+ if (interval == INFINITE)
+ {
+ interval = UDPLISTENER_WAIT_INTERVAL;
+ }
+ else
+ {
+ interval = MIN(UDPLISTENER_WAIT_INTERVAL, interval);
+ }
+
+ if (interval >= 1)
+ {
+ WaitSockEvent(u->Event, interval);
+ }
+ }
+
+ if (u->GetNatTIpThread != NULL)
+ {
+ FreeQueryIpThread(u->GetNatTIpThread);
+ }
+
+ // Release of the socket list
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = (UDPLISTENER_SOCK *)LIST_DATA(u->SockList, i);
+
+ Disconnect(us->Sock);
+ ReleaseSock(us->Sock);
+
+ Free(us);
+ }
+ ReleaseList(u->SockList);
+
+ FreeBuf(ip_list_buf);
+
+ Free(buf);
+}
+
+// Select the best UDP socket to be used for transmission
+UDPLISTENER_SOCK *DetermineUdpSocketForSending(UDPLISTENER *u, UDPPACKET *p)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == p->SrcPort)
+ {
+ if (CmpIpAddr(&us->IpAddress, &p->SrcIP) == 0)
+ {
+ return us;
+ }
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == p->SrcPort)
+ {
+ if (IsZeroIP(&us->IpAddress))
+ {
+ if ((IsIP4(&p->DstIP) && IsIP4(&us->IpAddress)) ||
+ (IsIP6(&p->DstIP) && IsIP6(&us->IpAddress)))
+ {
+ return us;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Release of the UDP packet
+void FreeUdpPacket(UDPPACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p->Data);
+ Free(p);
+}
+
+// Create a new UDP packet
+UDPPACKET *NewUdpPacket(IP *src_ip, UINT src_port, IP *dst_ip, UINT dst_port, void *data, UINT size)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (data == NULL || size == 0 || dst_ip == NULL || dst_port == 0)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(UDPPACKET));
+
+ p->Data = data;
+ p->Size = size;
+
+ Copy(&p->SrcIP, src_ip, sizeof(IP));
+ p->SrcPort = src_port;
+
+ Copy(&p->DstIP, dst_ip, sizeof(IP));
+ p->DestPort = dst_port;
+
+ return p;
+}
+
+// Transmit the packets via UDP Listener
+void UdpListenerSendPackets(UDPLISTENER *u, LIST *packet_list)
+{
+ UINT num = 0;
+ // Validate arguments
+ if (u == NULL || packet_list == NULL)
+ {
+ return;
+ }
+
+ LockList(u->SendPacketList);
+ {
+ UINT i;
+
+ num = LIST_NUM(packet_list);
+
+ for (i = 0;i < LIST_NUM(packet_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(packet_list, i);
+
+ Add(u->SendPacketList, p);
+ }
+ }
+ UnlockList(u->SendPacketList);
+
+ if (num >= 1)
+ {
+ SetSockEvent(u->Event);
+ }
+}
+void UdpListenerSendPacket(UDPLISTENER *u, UDPPACKET *packet)
+{
+ LIST *o;
+ // Validate arguments
+ if (u == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+ Add(o, packet);
+
+ UdpListenerSendPackets(u, o);
+
+ ReleaseList(o);
+}
+
+// Creating a UDP listener
+UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param)
+{
+ UDPLISTENER *u;
+ // Validate arguments
+ if (recv_proc == NULL)
+ {
+ return NULL;
+ }
+
+ u = ZeroMalloc(sizeof(UDPLISTENER));
+
+ u->Param = param;
+
+ u->PortList = NewList(NULL);
+ u->Event = NewSockEvent();
+
+ u->RecvProc = recv_proc;
+ u->SendPacketList = NewList(NULL);
+
+ u->Interrupts = NewInterruptManager();
+
+ u->Thread = NewThread(UdpListenerThread, u);
+
+ return u;
+}
+
+// Release the UDP listener
+void FreeUdpListener(UDPLISTENER *u)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ u->Halt = true;
+ SetSockEvent(u->Event);
+
+ WaitThread(u->Thread, INFINITE);
+ ReleaseThread(u->Thread);
+ ReleaseSockEvent(u->Event);
+
+ ReleaseIntList(u->PortList);
+
+ for (i = 0;i < LIST_NUM(u->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(u->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(u->SendPacketList);
+
+ FreeInterruptManager(u->Interrupts);
+
+ Free(u);
+}
+
+// Add the UDP port
+void AddPortToUdpListener(UDPLISTENER *u, UINT port)
+{
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ AddIntDistinct(u->PortList, port);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Get the port list
+UINT GetUdpListenerPortList(UDPLISTENER *u, UINT **port_list)
+{
+ UINT num_ports;
+ // Validate arguments
+ if (u == NULL || port_list == NULL)
+ {
+ return 0;
+ }
+
+ LockList(u->PortList);
+ {
+ UINT *ports;
+ UINT i;
+
+ num_ports = LIST_NUM(u->PortList);
+ ports = ZeroMalloc(sizeof(UINT) * num_ports);
+
+ for (i = 0;i < num_ports;i++)
+ {
+ ports[i] = *((UINT *)(LIST_DATA(u->PortList, i)));
+ }
+
+ *port_list = ports;
+ }
+ UnlockList(u->PortList);
+
+ return num_ports;
+}
+
+// Dekete all the UDP ports
+void DeleteAllPortFromUdpListener(UDPLISTENER *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ UINT num_ports = LIST_NUM(u->PortList);
+ UINT *ports = ZeroMalloc(sizeof(UINT) * num_ports);
+ UINT i;
+
+ for (i = 0;i < num_ports;i++)
+ {
+ ports[i] = *((UINT *)(LIST_DATA(u->PortList, i)));
+ }
+
+ for (i = 0;i < num_ports;i++)
+ {
+ UINT port = ports[i];
+
+ DelInt(u->PortList, port);
+ }
+
+ Free(ports);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Delete the UDP port
+void DeletePortFromUdpListener(UDPLISTENER *u, UINT port)
+{
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ DelInt(u->PortList, port);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Sort function of the interrupt management list
+int CmpInterruptManagerTickList(void *p1, void *p2)
+{
+ UINT64 *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *(UINT64 **)p1;
+ v2 = *(UINT64 **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ if (*v1 > *v2)
+ {
+ return 1;
+ }
+ else if (*v1 < *v2)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Initialization of the interrupt management
+INTERRUPT_MANAGER *NewInterruptManager()
+{
+ INTERRUPT_MANAGER *m = ZeroMalloc(sizeof(INTERRUPT_MANAGER));
+
+ m->TickList = NewList(CmpInterruptManagerTickList);
+
+ return m;
+}
+
+// Release of the interrupt management
+void FreeInterruptManager(INTERRUPT_MANAGER *m)
+{
+ UINT i;
+ // Validate arguments
+ if (m == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(m->TickList);i++)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, i);
+
+ Free(v);
+ }
+
+ ReleaseList(m->TickList);
+
+ Free(m);
+}
+
+// Add a number to the interrupt management
+void AddInterrupt(INTERRUPT_MANAGER *m, UINT64 tick)
+{
+ // Validate arguments
+ if (tick == 0)
+ {
+ return;
+ }
+
+ LockList(m->TickList);
+ {
+ if (Search(m->TickList, &tick) == NULL)
+ {
+ Insert(m->TickList, Clone(&tick, sizeof(UINT64)));
+ }
+ }
+ UnlockList(m->TickList);
+}
+
+// Get the interval to the next calling
+UINT GetNextIntervalForInterrupt(INTERRUPT_MANAGER *m)
+{
+ UINT ret = INFINITE;
+ UINT i;
+ LIST *o = NULL;
+ UINT64 now = Tick64();
+ // Validate arguments
+ if (m == NULL)
+ {
+ return 0;
+ }
+
+ LockList(m->TickList);
+ {
+ // Remove entries older than now already
+ for (i = 0;i < LIST_NUM(m->TickList);i++)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, i);
+
+ if (now >= *v)
+ {
+ ret = 0;
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, v);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *v = LIST_DATA(o, i);
+
+ Free(v);
+
+ Delete(m->TickList, v);
+ }
+
+ if (o != NULL)
+ {
+ ReleaseList(o);
+ }
+
+ if (ret == INFINITE)
+ {
+ if (LIST_NUM(m->TickList) >= 1)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, 0);
+
+ ret = (UINT)(*v - now);
+ }
+ }
+ }
+ UnlockList(m->TickList);
+
+ return ret;
+}
+
+// Let that the listening socket for the reverse socket to accept the new socket
+void InjectNewReverseSocketToAccept(SOCK *listen_sock, SOCK *s, IP *client_ip, UINT client_port)
+{
+ bool ok = false;
+ // Validate arguments
+ if (listen_sock == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockQueue(listen_sock->ReverseAcceptQueue);
+ {
+ if (listen_sock->CancelAccept == false && listen_sock->Disconnecting == false)
+ {
+ InsertQueue(listen_sock->ReverseAcceptQueue, s);
+
+ ok = true;
+
+ s->ServerMode = true;
+ s->IsReverseAcceptedSocket = true;
+
+ Copy(&s->RemoteIP, client_ip, sizeof(IP));
+ s->RemotePort = client_port;
+ }
+ }
+ UnlockQueue(listen_sock->ReverseAcceptQueue);
+
+ if (ok == false)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+ else
+ {
+ Set(listen_sock->ReverseAcceptEvent);
+ }
+}
+
+// Create a listening socket for the reverse socket
+SOCK *ListenReverse()
+{
+ SOCK *s = NewSock();
+
+ s->Type = SOCK_REVERSE_LISTEN;
+ s->ListenMode = true;
+ s->ReverseAcceptQueue = NewQueue();
+ s->ReverseAcceptEvent = NewEvent();
+ s->Connected = true;
+
+ return s;
+}
+
+// Accept on the reverse socket
+SOCK *AcceptReverse(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_REVERSE_LISTEN || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ SOCK *ret;
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ LockQueue(s->ReverseAcceptQueue);
+ {
+ ret = GetNext(s->ReverseAcceptQueue);
+ }
+ UnlockQueue(s->ReverseAcceptQueue);
+
+ if (ret != NULL)
+ {
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_AZURE);
+
+ return ret;
+ }
+
+ Wait(s->ReverseAcceptEvent, INFINITE);
+ }
+}
+
+// Start listening on the in-process socket
+SOCK *ListenInProc()
+{
+ SOCK *s = NewSock();
+
+ s->Type = SOCK_INPROC;
+ s->ListenMode = true;
+ s->InProcAcceptQueue = NewQueue();
+ s->InProcAcceptEvent = NewEvent();
+ s->Connected = true;
+
+ return s;
+}
+
+// Accept at the in-process socket
+SOCK *AcceptInProc(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_INPROC || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ SOCK *ret;
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ LockQueue(s->InProcAcceptQueue);
+ {
+ ret = GetNext(s->InProcAcceptQueue);
+ }
+ UnlockQueue(s->InProcAcceptQueue);
+
+ if (ret != NULL)
+ {
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_INPROC);
+
+ return ret;
+ }
+
+ Wait(s->InProcAcceptEvent, INFINITE);
+ }
+}
+
+// Connect by the in-process socket
+SOCK *ConnectInProc(SOCK *listen_sock, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ SOCK *ss, *sc;
+ bool ok = false;
+ // Validate arguments
+ if (listen_sock == NULL || listen_sock->Type != SOCK_INPROC || listen_sock->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ NewSocketPair(&sc, &ss, client_ip, client_port, server_ip, server_port);
+
+ LockQueue(listen_sock->InProcAcceptQueue);
+ {
+ if (listen_sock->CancelAccept == false && listen_sock->Disconnecting == false)
+ {
+ InsertQueue(listen_sock->InProcAcceptQueue, ss);
+
+ ok = true;
+ }
+ }
+ UnlockQueue(listen_sock->InProcAcceptQueue);
+
+ if (ok == false)
+ {
+ ReleaseSock(ss);
+ ReleaseSock(sc);
+ return NULL;
+ }
+
+ Set(listen_sock->InProcAcceptEvent);
+
+ return sc;
+}
+
+// Creating a new socket pair
+void NewSocketPair(SOCK **client, SOCK **server, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ IP iptmp;
+ TUBE *t1, *t2;
+ SOCK *sc, *ss;
+ SOCK_EVENT *e1, *e2;
+ // Validate arguments
+ if (client == NULL || server == NULL)
+ {
+ return;
+ }
+
+ SetIP(&iptmp, 127, 0, 0, 1);
+ if (client_ip == NULL)
+ {
+ client_ip = &iptmp;
+ }
+ if (server_ip == NULL)
+ {
+ server_ip = &iptmp;
+ }
+
+ // Creating a tube
+ NewTubePair(&t1, &t2, 0); // t1: C -> S, t2: S -> C
+
+ // Creating a socket event
+ e1 = NewSockEvent();
+ e2 = NewSockEvent();
+
+ SetTubeSockEvent(t1, e1);
+ SetTubeSockEvent(t2, e2);
+
+ sc = NewInProcSocket(t1, t2);
+ ss = NewInProcSocket(t2, t1);
+
+ Copy(&sc->LocalIP, client_ip, sizeof(IP));
+ sc->LocalPort = client_port;
+ Copy(&sc->RemoteIP, server_ip, sizeof(IP));
+ sc->RemotePort = server_port;
+
+ Copy(&ss->LocalIP, server_ip, sizeof(IP));
+ ss->LocalPort = server_port;
+ Copy(&ss->RemoteIP, client_ip, sizeof(IP));
+ ss->RemotePort = client_port;
+
+ sc->Connected = true;
+ sc->ServerMode = false;
+
+ ss->Connected = true;
+ ss->ServerMode = true;
+
+ SetTimeout(sc, INFINITE);
+ SetTimeout(ss, INFINITE);
+
+ QuerySocketInformation(sc);
+ QuerySocketInformation(ss);
+
+ ReleaseSockEvent(e1);
+ ReleaseSockEvent(e2);
+
+ ReleaseTube(t1);
+ ReleaseTube(t2);
+
+ *client = sc;
+ *server = ss;
+}
+
+// Creating a new in-process socket
+SOCK *NewInProcSocket(TUBE *tube_send, TUBE *tube_recv)
+{
+ SOCK *s;
+ // Validate arguments
+ if (tube_recv == NULL || tube_send == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewSock();
+
+ s->Type = SOCK_INPROC;
+
+ s->SendTube = tube_send;
+ s->RecvTube = tube_recv;
+
+ AddRef(tube_send->Ref);
+ AddRef(tube_recv->Ref);
+
+ s->InProcRecvFifo = NewFifo();
+
+ s->Connected = true;
+
+ return s;
+}
+
+// Transmission process for the in-process socket
+UINT SendInProc(SOCK *sock, void *data, UINT size)
+{
+ if (sock == NULL || sock->Type != SOCK_INPROC || sock->Disconnecting || sock->Connected == false)
+ {
+ return 0;
+ }
+
+ if (IsTubeConnected(sock->SendTube) == false)
+ {
+ return 0;
+ }
+
+ if (TubeSend(sock->SendTube, data, size, NULL) == false)
+ {
+ return 0;
+ }
+
+ return size;
+}
+
+// Receiving process for the in-process socket
+UINT RecvInProc(SOCK *sock, void *data, UINT size)
+{
+ FIFO *f;
+ UINT ret;
+ UINT timeout;
+ UINT64 giveup_time;
+ TUBEDATA *d = NULL;
+ if (sock == NULL || sock->Type != SOCK_INPROC || sock->Disconnecting || sock->Connected == false)
+ {
+ return 0;
+ }
+
+ if (IsTubeConnected(sock->SendTube) == false)
+ {
+ return 0;
+ }
+
+ f = sock->InProcRecvFifo;
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ // If there is data in the FIFO, return it immediately
+ ret = ReadFifo(f, data, size);
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ timeout = GetTimeout(sock);
+
+ giveup_time = Tick64() + (UINT)timeout;
+
+ // When there is no data in the FIFO, read the next data from the tube
+ d = NULL;
+
+ while (true)
+ {
+ UINT64 now = 0;
+ UINT interval;
+
+ if (sock->AsyncMode == false)
+ {
+ now = Tick64();
+
+ if (now >= giveup_time)
+ {
+ break;
+ }
+ }
+
+ d = TubeRecvAsync(sock->RecvTube);
+
+ if (d != NULL)
+ {
+ break;
+ }
+
+ if (IsTubeConnected(sock->RecvTube) == false)
+ {
+ break;
+ }
+
+ if (sock->AsyncMode)
+ {
+ break;
+ }
+
+ interval = (UINT)(giveup_time - now);
+
+ Wait(sock->RecvTube->Event, interval);
+ }
+
+ if (d == NULL)
+ {
+ if (IsTubeConnected(sock->RecvTube) == false)
+ {
+ return 0;
+ }
+
+ if (sock->AsyncMode == false)
+ {
+ // If a timeout occurs in synchronous mode, disconnect ir
+ Disconnect(sock);
+
+ return 0;
+ }
+ else
+ {
+ // If a timeout occurs in asynchronous mode, returns the blocking error
+ return SOCK_LATER;
+ }
+ }
+ else
+ {
+ // If the received data is larger than the requested size, write the rest to FIFO
+ if (d->DataSize > size)
+ {
+ WriteFifo(f, ((UCHAR *)d->Data) + size, d->DataSize - size);
+ ret = size;
+ }
+ else
+ {
+ ret = d->DataSize;
+ }
+
+ Copy(data, d->Data, ret);
+
+ FreeTubeData(d);
+
+ return ret;
+ }
+}
+
+// Wait for the arrival of data on multiple tubes
+void WaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ // Validate arguments
+ if (num != 0 && tubes == NULL)
+ {
+ return;
+ }
+ if (timeout == 0)
+ {
+ return;
+ }
+ if (num == 0)
+ {
+ SleepThread(timeout);
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32WaitForTubes(tubes, num, timeout);
+#else // OS_WIN32
+ UnixWaitForTubes(tubes, num, timeout);
+#endif // OS_WIN32
+}
+
+#ifdef OS_WIN32
+void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ HANDLE array[MAXIMUM_WAIT_OBJECTS];
+ UINT i;
+
+ Zero(array, sizeof(array));
+
+ for (i = 0;i < num;i++)
+ {
+ TUBE *t = tubes[i];
+
+ array[i] = t->Event->pData;
+ }
+
+ if (num == 1)
+ {
+ WaitForSingleObject(array[0], timeout);
+ }
+ else
+ {
+ WaitForMultipleObjects(num, array, false, timeout);
+ }
+}
+#else // OS_WIN32
+void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ int *fds;
+ UINT i;
+ char tmp[MAX_SIZE];
+ bool any_of_tubes_are_readable = false;
+
+ fds = ZeroMalloc(sizeof(int) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ fds[i] = tubes[i]->SockEvent->pipe_read;
+
+ if (tubes[i]->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+
+ if (any_of_tubes_are_readable == false)
+ {
+ UnixSelectInner(num, fds, 0, NULL, timeout);
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ int fd = fds[i];
+ int readret;
+
+ tubes[i]->SockEvent->current_pipe_data = 0;
+
+ do
+ {
+ readret = read(fd, tmp, sizeof(tmp));
+ }
+ while (readret >= 1);
+ }
+
+ Free(fds);
+}
+#endif // OS_WIN32
+
+// Creating a Tube Flush List
+TUBE_FLUSH_LIST *NewTubeFlushList()
+{
+ TUBE_FLUSH_LIST *f = ZeroMalloc(sizeof(TUBE_FLUSH_LIST));
+
+ f->List = NewListFast(NULL);
+
+ return f;
+}
+
+// Release of the Tube Flush List
+void FreeTubeFlushList(TUBE_FLUSH_LIST *f)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->List);i++)
+ {
+ TUBE *t = LIST_DATA(f->List, i);
+
+ ReleaseTube(t);
+ }
+
+ ReleaseList(f->List);
+
+ Free(f);
+}
+
+// Add a Tube to the Tube Flush List
+void AddTubeToFlushList(TUBE_FLUSH_LIST *f, TUBE *t)
+{
+ // Validate arguments
+ if (f == NULL || t == NULL)
+ {
+ return;
+ }
+
+ if (t->IsInFlushList)
+ {
+ return;
+ }
+
+ if (IsInList(f->List, t) == false)
+ {
+ Add(f->List, t);
+
+ AddRef(t->Ref);
+
+ t->IsInFlushList = true;
+ }
+}
+
+// Flush the all tubes in the Tube Flush List
+void FlushTubeFlushList(TUBE_FLUSH_LIST *f)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->List);i++)
+ {
+ TUBE *t = LIST_DATA(f->List, i);
+
+ TubeFlush(t);
+ t->IsInFlushList = false;
+
+ ReleaseTube(t);
+ }
+
+ DeleteAll(f->List);
+}
+
+// The server receives a PACK from the client
+PACK *HttpServerRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ UINT num_noop = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+START:
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ goto BAD_REQUEST;
+ }
+
+ if (StrCmpi(h->Method, "POST") != 0 ||
+ StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
+ StrCmpi(h->Version, "HTTP/1.1") != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > HTTP_PACK_MAX_SIZE)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ // Determine whether it's a NOOP
+ if (PackGetInt(p, "noop") != 0)
+ {
+ Debug("recv: noop\n");
+ FreePack(p);
+
+ p = PackError(0);
+ PackAddInt(p, "noop", 1);
+ if (HttpServerSend(s, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+
+ FreePack(p);
+
+ num_noop++;
+
+ if (num_noop > MAX_NOOP_PER_SESSION)
+ {
+ return NULL;
+ }
+
+ goto START;
+ }
+
+ return p;
+
+BAD_REQUEST:
+ // Return an error
+
+
+ return NULL;
+}
+
+// Store the error value into PACK
+PACK *PackError(UINT error)
+{
+ PACK *p;
+
+ p = NewPack();
+ PackAddInt(p, "error", error);
+
+ return p;
+}
+
+// Get the error value from PACK
+UINT GetErrorFromPack(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetInt(p, "error");
+}
+
+// Client receives a PACK from the server
+PACK *HttpClientRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
+ StrCmpi(h->Target, "200") != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > MAX_PACK_SIZE)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ return p;
+}
+
+// Create an entry to PACK for the dummy
+void CreateDummyValue(PACK *p)
+{
+ UINT size;
+ UCHAR *buf;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ size = Rand32() % HTTP_PACK_RAND_SIZE_MAX;
+ buf = Malloc(size);
+ Rand(buf, size);
+
+ PackAddData(p, "pencore", buf, size);
+
+ Free(buf);
+}
+
+// Client send a PACK to the server
+bool HttpClientSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Server sends a PACK to the client
+bool HttpServerSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("HTTP/1.1", "200", "OK");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Replace unsafe characters in target
+void ReplaceUnsafeCharInTarget(char *target){
+ UINT i;
+ for(i = 0; target[i] ; i++) {
+ if(target[i] == '<')
+ target[i] = '(';
+ else if(target[i] == '>')
+ target[i] = ')';
+ }
+}
+
+// Sending the 501 Not Implemented error
+bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_501_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // METHOD
+ ReplaceStri(str, str_size, str, "$METHOD$", method);
+
+ // VERSION
+ ReplaceStri(str, str_size, str, "$VERSION$", version);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 404 Not Found error
+bool HttpSendNotFound(SOCK *s, char *target)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_404_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 500 Server Error
+bool HttpSendServerError(SOCK *s, char *target)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "500", "Server Error");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_500_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_500_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 403 Forbidden error
+bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_403_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Get the date and time string for the HTTP header
+void GetHttpDateStr(char *str, UINT size, UINT64 t)
+{
+ SYSTEMTIME s;
+ static char *wday[] =
+ {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+ };
+ static char *month[] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
+ "Nov", "Dec",
+ };
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ UINT64ToSystem(&s, t);
+
+ Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
+ wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
+ s.wHour, s.wMinute, s.wSecond);
+}
+
+// Get the Content-Length from the HTTP header
+UINT GetContentLength(HTTP_HEADER *header)
+{
+ UINT ret;
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return 0;
+ }
+
+ v = GetHttpValue(header, "Content-Length");
+ if (v == NULL)
+ {
+ return 0;
+ }
+
+ ret = ToInt(v->Data);
+
+ return ret;
+}
+
+// Send the data in the HTTP
+bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
+{
+ char *header_str;
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (s == NULL || header == NULL || (post_size != 0 && post_data == NULL))
+ {
+ return false;
+ }
+
+ // Check whether the Content-Lentgh exists?
+ if (GetHttpValue(header, "Content-Length") == NULL)
+ {
+ char tmp[MAX_SIZE];
+ // Add because it does not exist
+ ToStr(tmp, post_size);
+ AddHttpValue(header, NewHttpValue("Content-Length", tmp));
+ }
+
+ // Convert the header to string
+ header_str = HttpHeaderToStr(header);
+ if (header_str == NULL)
+ {
+ return false;
+ }
+ b = NewBuf();
+ WriteBuf(b, header_str, StrLen(header_str));
+ Free(header_str);
+
+ // Append the data
+ WriteBuf(b, post_data, post_size);
+
+ // Send
+ ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert a HTTP header to a string
+char *HttpHeaderToStr(HTTP_HEADER *header)
+{
+ BUF *b;
+ char *tmp;
+ UINT i;
+ char *s;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return NULL;
+ }
+
+ tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
+ b = NewBuf();
+
+ // Header
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s %s %s\r\n", header->Method, header->Target, header->Version);
+ WriteBuf(b, tmp, StrLen(tmp));
+
+ // Value
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s: %s\r\n", v->Name, v->Data);
+ WriteBuf(b, tmp, StrLen(tmp));
+ }
+
+ // Trailing newline
+ WriteBuf(b, "\r\n", 2);
+ s = Malloc(b->Size + 1);
+ Copy(s, b->Buf, b->Size);
+ s[b->Size] = 0;
+
+ FreeBuf(b);
+ Free(tmp);
+
+ return s;
+}
+
+// Send the HTTP header
+bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
+{
+ char *str;
+ bool ret;
+ // Validate arguments
+ if (s == NULL || header == NULL)
+ {
+ return false;
+ }
+
+ // Convert to string
+ str = HttpHeaderToStr(header);
+
+ // Transmission
+ ret = SendAll(s, str, StrLen(str), s->SecureMode);
+
+ Free(str);
+
+ return ret;
+}
+
+// Receive an HTTP header
+HTTP_HEADER *RecvHttpHeader(SOCK *s)
+{
+ TOKEN_LIST *token = NULL;
+ char *str = NULL;
+ HTTP_HEADER *header = NULL;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // Get the first line
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Split into tokens
+ token = ParseToken(str, " ");
+ if (token->NumTokens < 3)
+ {
+ goto LABEL_ERROR;
+ }
+
+ Free(str);
+ str = NULL;
+
+ // Creating a header object
+ header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
+
+ if (StrCmpi(header->Version, "HTTP/0.9") == 0)
+ {
+ // The header ends with this line
+ FreeToken(token);
+ return header;
+ }
+
+ // Get the subsequent lines
+ while (true)
+ {
+ UINT pos;
+ HTTP_VALUE *v;
+ char *value_name, *value_data;
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+ Trim(str);
+
+ if (StrLen(str) == 0)
+ {
+ // End of header
+ Free(str);
+ str = NULL;
+ break;
+ }
+
+ // Get the position of the colon
+ pos = SearchStr(str, ":", 0);
+ if (pos == INFINITE)
+ {
+ // The colon does not exist
+ goto LABEL_ERROR;
+ }
+ if ((pos + 1) >= StrLen(str))
+ {
+ // There is no data
+ goto LABEL_ERROR;
+ }
+
+ // Divide into the name and the data
+ value_name = Malloc(pos + 1);
+ Copy(value_name, str, pos);
+ value_name[pos] = 0;
+ value_data = &str[pos + 1];
+
+ v = NewHttpValue(value_name, value_data);
+ if (v == NULL)
+ {
+ Free(value_name);
+ goto LABEL_ERROR;
+ }
+
+ Free(value_name);
+
+ AddHttpValue(header, v);
+ Free(str);
+ }
+
+ FreeToken(token);
+
+ return header;
+
+LABEL_ERROR:
+ // Memory release
+ if (token)
+ {
+ FreeToken(token);
+ }
+ if (str)
+ {
+ Free(str);
+ }
+ if (header)
+ {
+ FreeHttpHeader(header);
+ }
+ return NULL;
+}
+
+// Receive a line
+char *RecvLine(SOCK *s, UINT max_size)
+{
+ BUF *b;
+ char c;
+ char *str;
+ // Validate arguments
+ if (s == NULL || max_size == 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ while (true)
+ {
+ UCHAR *buf;
+ if (RecvAll(s, &c, sizeof(c), s->SecureMode) == false)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ WriteBuf(b, &c, sizeof(c));
+ buf = (UCHAR *)b->Buf;
+ if (b->Size > max_size)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\n')
+ {
+ b->Size--;
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\r')
+ {
+ b->Size--;
+ }
+ }
+ str = Malloc(b->Size + 1);
+ Copy(str, b->Buf, b->Size);
+ str[b->Size] = 0;
+ FreeBuf(b);
+
+ return str;
+ }
+ }
+ }
+}
+
+// Creating a new HTTP value
+HTTP_VALUE *NewHttpValue(char *name, char *data)
+{
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(HTTP_VALUE));
+
+ v->Name = CopyStr(name);
+ v->Data = CopyStr(data);
+
+ Trim(v->Name);
+ Trim(v->Data);
+
+ return v;
+}
+
+// Look for the HTTP value from the HTTP header
+HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
+{
+ HTTP_VALUE *v, t;
+ // Validate arguments
+ if (header == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ t.Name = name;
+ v = Search(header->ValueList, &t);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ return v;
+}
+
+// Add a HTTP value to the HTTP header
+void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
+{
+ // Validate arguments
+ if (header == NULL || value == NULL)
+ {
+ return;
+ }
+
+ if (LIST_NUM(header->ValueList) < HTTP_HEADER_MAX_LINES)
+ {
+ Insert(header->ValueList, value);
+ }
+ else
+ {
+ FreeHttpValue(value);
+ }
+}
+
+// Create an HTTP header
+HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
+{
+ return NewHttpHeaderEx(method, target, version, false);
+}
+HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort)
+{
+ HTTP_HEADER *header;
+ // Validate arguments
+ if (method == NULL || target == NULL || version == NULL)
+ {
+ return NULL;
+ }
+
+ header = ZeroMalloc(sizeof(HTTP_HEADER));
+
+ header->Method = CopyStr(method);
+ header->Target = CopyStr(target);
+ header->Version = CopyStr(version);
+ header->ValueList = NewListFast(no_sort ? NULL : CompareHttpValue);
+
+ return header;
+}
+
+// Comparison function of the HTTP value
+int CompareHttpValue(void *p1, void *p2)
+{
+ HTTP_VALUE *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(HTTP_VALUE **)p1;
+ v2 = *(HTTP_VALUE **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// Release the HTTP value
+void FreeHttpValue(HTTP_VALUE *value)
+{
+ // Validate arguments
+ if (value == NULL)
+ {
+ return;
+ }
+
+ Free(value->Data);
+ Free(value->Name);
+
+ Free(value);
+}
+
+// Release the HTTP header
+void FreeHttpHeader(HTTP_HEADER *header)
+{
+ UINT i;
+ HTTP_VALUE **values;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return;
+ }
+
+ Free(header->Method);
+ Free(header->Target);
+ Free(header->Version);
+
+ values = ToArray(header->ValueList);
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ FreeHttpValue(values[i]);
+ }
+ Free(values);
+
+ ReleaseList(header->ValueList);
+
+ Free(header);
+}
+
+// Receive a PACK
+PACK *RecvPack(SOCK *s)
+{
+ PACK *p;
+ BUF *b;
+ void *data;
+ UINT sz;
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+ sz = Endian32(sz);
+ if (sz > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+ data = MallocEx(sz, true);
+ if (RecvAll(s, data, sz, s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, sz);
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+ Free(data);
+
+ return p;
+}
+
+// Receive a PACK (with checking the hash)
+PACK *RecvPackWithHash(SOCK *s)
+{
+ PACK *p;
+ BUF *b;
+ void *data;
+ UINT sz;
+ UCHAR hash1[SHA1_SIZE];
+ UCHAR hash2[SHA1_SIZE];
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+ sz = Endian32(sz);
+ if (sz > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+ data = MallocEx(sz, true);
+ if (RecvAll(s, data, sz, s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ HashSha1(hash1, data, sz);
+ if (RecvAll(s, hash2, sizeof(hash2), s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ if (Cmp(hash1, hash2, SHA1_SIZE) != 0)
+ {
+ Free(data);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, sz);
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+ Free(data);
+
+ return p;
+}
+
+// Send a PACK
+bool SendPack(SOCK *s, PACK *p)
+{
+ BUF *b;
+ UINT sz;
+ // Validate arguments
+ if (s == NULL || p == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ b = PackToBuf(p);
+ sz = Endian32(b->Size);
+
+ SendAdd(s, &sz, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return SendNow(s, s->SecureMode);
+}
+
+// Send a Pack (with adding a hash)
+bool SendPackWithHash(SOCK *s, PACK *p)
+{
+ BUF *b;
+ UINT sz;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ b = PackToBuf(p);
+ sz = Endian32(b->Size);
+
+ SendAdd(s, &sz, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+ HashSha1(hash, b->Buf, b->Size);
+ SendAdd(s, hash, sizeof(hash));
+
+ FreeBuf(b);
+
+ return SendNow(s, s->SecureMode);
+}
+
+// Get SNI name from the data that has arrived to the TCP connection before accepting an SSL connection
+bool GetSniNameFromPreSslConnection(SOCK *s, char *sni, UINT sni_size)
+{
+ UCHAR tmp[1500];
+ UINT size;
+ // Validate arguments
+ if (s == NULL || sni == NULL)
+ {
+ return false;
+ }
+
+ size = Peek(s, tmp, sizeof(tmp));
+ if (size == 0)
+ {
+ return false;
+ }
+
+ return GetSniNameFromSslPacket(tmp, size, sni, sni_size);
+}
+
+// Get SNI name from the SSL packet
+bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size)
+{
+ BUF *buf;
+ bool ret = false;
+ UCHAR content_type;
+ USHORT version;
+ USHORT handshake_length;
+
+ // Validate arguments
+ if (packet_buf == NULL || packet_size == 0)
+ {
+ return false;
+ }
+
+ buf = NewBufFromMemory(packet_buf, packet_size);
+
+ if (ReadBuf(buf, &content_type, sizeof(UCHAR)) == sizeof(UCHAR) &&
+ ReadBuf(buf, &version, sizeof(USHORT)) == sizeof(USHORT) &&
+ ReadBuf(buf, &handshake_length, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ version = Endian16(version);
+ handshake_length = Endian16(handshake_length);
+
+ if (version >= 0x0301)
+ {
+ UCHAR *handshake_data = Malloc(handshake_length);
+
+ if (ReadBuf(buf, handshake_data, handshake_length) == handshake_length)
+ {
+ BUF *buf2 = NewBufFromMemory(handshake_data, handshake_length);
+ USHORT handshake_type;
+ USHORT handshake_length_2;
+
+ if (ReadBuf(buf2, &handshake_type, sizeof(USHORT)) == sizeof(USHORT) &&
+ ReadBuf(buf2, &handshake_length_2, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ handshake_type = Endian16(handshake_type);
+ handshake_length_2 = Endian16(handshake_length_2);
+
+ if (handshake_type == 0x0100 && handshake_length_2 <= (handshake_length - 4))
+ {
+ USHORT version2;
+
+ if (ReadBuf(buf2, &version2, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ version2 = Endian16(version2);
+
+ if (version2 >= 0x0301)
+ {
+ UCHAR rand[32];
+
+ if (ReadBuf(buf2, rand, sizeof(rand)) == sizeof(rand))
+ {
+ UCHAR session_id_len;
+
+ if (ReadBuf(buf2, &session_id_len, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (ReadBuf(buf2, NULL, session_id_len) == session_id_len)
+ {
+ USHORT cipher_len;
+
+ if (ReadBuf(buf2, &cipher_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ cipher_len = Endian16(cipher_len);
+
+ if (ReadBuf(buf2, NULL, cipher_len) == cipher_len)
+ {
+ UCHAR comps_len;
+
+ if (ReadBuf(buf2, &comps_len, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (ReadBuf(buf2, NULL, comps_len) == comps_len)
+ {
+ USHORT ext_length;
+
+ if (ReadBuf(buf2, &ext_length, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ UCHAR *ext_buf;
+
+ ext_length = Endian16(ext_length);
+
+ ext_buf = Malloc(ext_length);
+
+ if (ReadBuf(buf2, ext_buf, ext_length) == ext_length)
+ {
+ BUF *ebuf = NewBufFromMemory(ext_buf, ext_length);
+
+ while (ret == false)
+ {
+ USHORT type;
+ USHORT data_len;
+ UCHAR *data;
+
+ if (ReadBuf(ebuf, &type, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ break;
+ }
+
+ if (ReadBuf(ebuf, &data_len, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ break;
+ }
+
+ type = Endian16(type);
+ data_len = Endian16(data_len);
+
+ data = Malloc(data_len);
+
+ if (ReadBuf(ebuf, data, data_len) != data_len)
+ {
+ Free(data);
+ break;
+ }
+
+ if (type == 0x0000)
+ {
+ BUF *dbuf = NewBufFromMemory(data, data_len);
+
+ USHORT total_len;
+
+ if (ReadBuf(dbuf, &total_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ UCHAR c;
+ total_len = Endian16(total_len);
+
+ if (ReadBuf(dbuf, &c, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (c == 0)
+ {
+ USHORT name_len;
+
+ if (ReadBuf(dbuf, &name_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ char *name_buf;
+ name_len = Endian16(name_len);
+
+ name_buf = ZeroMalloc(name_len + 1);
+
+ if (ReadBuf(dbuf, name_buf, name_len) == name_len)
+ {
+ ret = true;
+
+ StrCpy(sni, sni_size, name_buf);
+ }
+
+ Free(name_buf);
+ }
+ }
+ }
+ }
+
+ FreeBuf(dbuf);
+ }
+
+ Free(data);
+ }
+
+ FreeBuf(ebuf);
+ }
+
+ Free(ext_buf);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeBuf(buf2);
+ }
+
+ Free(handshake_data);
+ }
+ }
+
+ FreeBuf(buf);
+
+ if (ret)
+ {
+ Trim(sni);
+
+ if (IsEmptyStr(sni))
+ {
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h
new file mode 100644
index 00000000..20be8619
--- /dev/null
+++ b/src/Mayaqua/Network.h
@@ -0,0 +1,1582 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Network.h
+// Header of Network.c
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+// Dynamic Value
+struct DYN_VALUE
+{
+ char Name[256]; // Name
+ UINT64 Value; // Value
+};
+
+#define DYN64(id, default_value) ( (UINT64)GetDynValueOrDefaultSafe ( #id , (UINT64)( default_value )))
+#define DYN32(id, default_value) (UINT)DYN64(id, (UINT)default_value)
+
+#define MAX_HOST_NAME_LEN 255 // Maximum length of the host name
+
+#define TIMEOUT_GETIP 2300
+
+#define TIMEOUT_INFINITE (0x7fffffff)
+#define TIMEOUT_TCP_PORT_CHECK (10 * 1000)
+#define TIMEOUT_SSL_CONNECT (15 * 1000)
+
+#define TIMEOUT_HOSTNAME (500)
+#define TIMEOUT_NETBIOS_HOSTNAME (100)
+#define EXPIRES_HOSTNAME (10 * 60 * 1000)
+
+#define SOCKET_BUFFER_SIZE 0x10000000
+
+#define IPV6_DUMMY_FOR_IPV4 0xFEFFFFDF
+
+#define UDPLISTENER_CHECK_INTERVAL 1000ULL
+#define UDPLISTENER_WAIT_INTERVAL 1234
+
+#define UDP_MAX_MSG_SIZE_DEFAULT 65507
+
+#define MAX_NUM_IGNORE_ERRORS 1024
+
+// Private IP list file
+#define PRIVATE_IP_TXT_FILENAME "@private_ip.txt"
+
+// Start range of the random UDP port
+#define RAND_UDP_PORT_START 5000
+#define RAND_UDP_PORT_END 65530
+#define RAND_UDP_PORT_DEFAULT_NUM_RETRY 64
+
+// Special Port
+#define MAKE_SPECIAL_PORT(p) (UINT)((UINT)0x10000 | (UINT)(p))
+#define IS_SPECIAL_PORT(p) (MAKEBOOL((p) & (UINT)0x10000))
+#define GET_SPECIAL_PORT(p) (UINT)((UINT)(p) & (UINT)0xffff)
+
+// Random R-UDP port ID
+#define RAND_PORT_ID_SERVER_LISTEN 1
+
+// UDP buffer size
+#define UDP_MAX_BUFFER_SIZE 11911168
+
+// Expiration of the cache acquired from the IP address list of the host
+#define HOST_IP_ADDRESS_LIST_CACHE (5 * 1000)
+
+// IP address
+struct IP
+{
+ UCHAR addr[4]; // IPv4 address, (meaning that 223.255.255.254 = IPv6)
+ UCHAR ipv6_addr[16]; // IPv6 address
+ UINT ipv6_scope_id; // IPv6 scope ID
+};
+
+// Size when comparing the IP structures only in the address part
+#define SIZE_OF_IP_FOR_ADDR (sizeof(UCHAR) * 20)
+
+// Compare the IP address part
+#define CmpIpAddr(ip1, ip2) (Cmp((ip1), (ip2), SIZE_OF_IP_FOR_ADDR))
+
+// IPv6 address (different format)
+struct IPV6_ADDR
+{
+ UCHAR Value[16]; // Value
+} GCC_PACKED;
+
+// IPv6 Address Types
+#define IPV6_ADDR_UNICAST 1 // Unicast
+#define IPV6_ADDR_LOCAL_UNICAST 2 // Local unicast
+#define IPV6_ADDR_GLOBAL_UNICAST 4 // Global Unicast
+#define IPV6_ADDR_MULTICAST 8 // Multicast
+#define IPV6_ADDR_ALL_NODE_MULTICAST 16 // All-nodes multicast
+#define IPV6_ADDR_ALL_ROUTER_MULTICAST 32 // All routers multicast
+#define IPV6_ADDR_SOLICIATION_MULTICAST 64 // Solicited-node multicast
+#define IPV6_ADDR_ZERO 128 // All zeros
+#define IPV6_ADDR_LOOPBACK 256 // Loop-back
+
+
+// DNS cache list
+struct DNSCACHE
+{
+ char *HostName;
+ IP IpAddress;
+};
+
+// Client list
+struct IP_CLIENT
+{
+ IP IpAddress; // IP address
+ UINT NumConnections; // The number of connections
+};
+
+// Socket event
+struct SOCK_EVENT
+{
+ REF *ref; // Reference counter
+#ifdef OS_WIN32
+ void *hEvent; // Pointer to a Win32 event handle
+#else // OS_WIN32
+ LIST *SockList; // Socket list
+ int pipe_read, pipe_write; // Pipe
+ UINT current_pipe_data; // Amount of data in the current pipe
+#endif // OS_WIN32
+};
+
+// Type of socket
+#define SOCK_TCP 1
+#define SOCK_UDP 2
+#define SOCK_INPROC 3
+#define SOCK_RUDP_LISTEN 5
+#define SOCK_REVERSE_LISTEN 6
+
+// Socket
+struct SOCK
+{
+ REF *ref; // Reference counter
+ LOCK *lock; // Lock
+ LOCK *ssl_lock; // Lock related to the SSL
+ LOCK *disconnect_lock; // Disconnection lock
+ SOCKET socket; // Socket number
+ SSL *ssl; // SSL object
+ struct ssl_ctx_st *ssl_ctx; // SSL_CTX
+ char SniHostname[256]; // SNI host name
+ UINT Type; // Type of socket
+ bool Connected; // Connecting flag
+ bool ServerMode; // Server mode
+ bool AsyncMode; // Asynchronous mode
+ bool SecureMode; // SSL communication mode
+ bool ListenMode; // In listening
+ BUF *SendBuf; // Transmission buffer
+ bool IpClientAdded; // Whether it has been added to the list IP_CLIENT
+ bool LocalOnly; // Only local
+ bool EnableConditionalAccept; // Conditional Accept is Enabled
+ IP RemoteIP; // IP address of the remote host
+ IP LocalIP; // IP address of the local host
+ char *RemoteHostname; // Remote host name
+ UINT RemotePort; // Port number of the remote side
+ UINT LocalPort; // Port number of the local side
+ UINT64 SendSize; // Total size of the sent data
+ UINT64 RecvSize; // Total size of received data
+ UINT64 SendNum; // Number of sent data blocks
+ UINT64 RecvNum; // Number of received data blocks
+ X *RemoteX; // Certificate of the remote host
+ X *LocalX; // Certificate of the local host
+ char *CipherName; // Cipher algorithm name
+ char *WaitToUseCipher; // Set the algorithm name to want to use
+ bool IgnoreRecvErr; // Whether the RecvFrom error is ignorable
+ bool IgnoreSendErr; // Whether the SendTo error is ignorable
+ UINT TimeOut; // Time-out value
+ SOCK_EVENT *SockEvent; // Associated socket-event
+ bool CancelAccept; // Cancel flag of the Accept
+ bool AcceptCanceled; // Flag which shows canceling of the Accept
+ bool WriteBlocked; // Previous write is blocked
+ bool NoNeedToRead; // Is not required to read
+ bool Disconnecting; // Disconnecting
+ bool UdpBroadcast; // UDP broadcast mode
+ void *Param; // Any parameters
+ bool IPv6; // IPv6
+ bool IsRawSocket; // Whether it is a raw socket
+ UINT RawSocketIPProtocol; // IP protocol number if it's a raw socket
+ TUBE *SendTube; // Tube for transmission
+ TUBE *RecvTube; // Tube for reception
+ QUEUE *InProcAcceptQueue; // Accept queue of the in-process socket
+ EVENT *InProcAcceptEvent; // Accept event of the in-process socket
+ FIFO *InProcRecvFifo; // Receive FIFO of the in-process socket
+ UINT UdpMaxMsgSize; // Maximum transmitting and receiving size at a time on UDP
+ int CurrentTos; // Current ToS value
+ bool IsTtlSupported; // Whether the TTL value is supported
+ UINT CurrentTtl; // Current TTL value
+ RUDP_STACK *R_UDP_Stack; // R-UDP stack
+ char UnderlayProtocol[64]; // Underlying protocol
+ QUEUE *ReverseAcceptQueue; // Accept queue for the reverse socket
+ EVENT *ReverseAcceptEvent; // Accept event for the reverse socket
+ bool IsReverseAcceptedSocket; // Whether it is a reverse socket
+ IP Reverse_MyServerGlobalIp; // Self global IP address when using the reverse socket
+ UINT Reverse_MyServerPort; // Self port number when using the reverse socket
+
+ void *hAcceptEvent; // Event for Accept
+
+ // R-UDP socket related
+ bool IsRUDPSocket; // Whether this is R-UDP socket
+ TUBE *BulkSendTube; // Tube for Bulk send
+ TUBE *BulkRecvTube; // Tube for Bulk receive
+ SHARED_BUFFER *BulkSendKey; // Bulk send key
+ SHARED_BUFFER *BulkRecvKey; // Bulk receive key
+ UINT RUDP_OptimizedMss; // Optimal MSS value
+
+#ifdef OS_UNIX
+ pthread_t CallingThread; // Thread that is calling the system call
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ void *hEvent; // Event for asynchronous mode
+#endif // OS_WIN32
+};
+
+// Underlying protocol description string of socket
+#define SOCK_UNDERLAY_NATIVE_V6 "Standard TCP/IP (IPv6)"
+#define SOCK_UNDERLAY_NATIVE_V4 "Standard TCP/IP (IPv4)"
+#define SOCK_UNDERLAY_NAT_T "VPN over UDP with NAT-T (IPv4)"
+#define SOCK_UNDERLAY_DNS "VPN over DNS (IPv4)"
+#define SOCK_UNDERLAY_ICMP "VPN over ICMP (IPv4)"
+#define SOCK_UNDERLAY_INPROC "In-Process Pipe"
+#define SOCK_UNDERLAY_INPROC_EX "Legacy VPN - %s"
+#define SOCK_UNDERLAY_AZURE "TCP/IP via VPN Azure (IPv4)"
+
+// Constant of the return value
+#define SOCK_LATER (0xffffffff) // In blocking
+
+// Socket Set
+#define MAX_SOCKSET_NUM 60 // Number of sockets that can be stored in a socket set
+struct SOCKSET
+{
+ UINT NumSocket; // The number of sockets
+ SOCK *Sock[MAX_SOCKSET_NUM]; // Array of pointers to the socket
+};
+
+// Cancel object
+struct CANCEL
+{
+ REF *ref; // Reference counter
+ bool SpecialFlag; // Special flag (associated to the event which is generated by Win32 driver)
+#ifdef OS_WIN32
+ void *hEvent; // Pointer to a Win32 event handle
+#else // OS_WIN32
+ int pipe_read, pipe_write; // Pipe
+#endif // OS_WIN32
+};
+
+// Routing table entry
+struct ROUTE_ENTRY
+{
+ IP DestIP;
+ IP DestMask;
+ IP GatewayIP;
+ bool LocalRouting;
+ bool PPPConnection;
+ UINT Metric;
+ UINT OldIfMetric;
+ UINT InterfaceID;
+ UINT64 InnerScore;
+};
+
+// Routing table
+struct ROUTE_TABLE
+{
+ UINT NumEntry;
+ UINT HashedValue;
+ ROUTE_ENTRY **Entry;
+};
+
+// ICMP response result
+struct ICMP_RESULT
+{
+ bool Ok; // Whether a correct response returned
+ bool Timeout; // Whether a time-out is occurred
+ UCHAR Type; // Message type
+ UCHAR Code; // Message code
+ UCHAR Ttl; // TTL
+ UCHAR *Data; // Data body
+ UINT DataSize; // Data size
+ UINT Rtt; // Round Trip Time
+ IP IpAddress; // IP address
+};
+
+
+// Host name cache list
+typedef struct HOSTCACHE
+{
+ UINT64 Expires; // Expiration
+ IP IpAddress; // IP address
+ char HostName[256]; // Host name
+} HOSTCACHE;
+
+// NETBIOS name requests
+typedef struct NBTREQUEST
+{
+ USHORT TransactionId;
+ USHORT Flags;
+ USHORT NumQuestions;
+ USHORT AnswerRRs;
+ USHORT AuthorityRRs;
+ USHORT AdditionalRRs;
+ UCHAR Query[38];
+} NBTREQUEST;
+
+// NETBIOS name response
+typedef struct NBTRESPONSE
+{
+ USHORT TransactionId;
+ USHORT Flags;
+ USHORT NumQuestions;
+ USHORT AnswerRRs;
+ USHORT AuthorityRRs;
+ USHORT AdditionalRRs;
+ UCHAR Response[61];
+} NBTRESPONSE;
+
+// Socket list
+typedef struct SOCKLIST
+{
+ LIST *SockList;
+} SOCKLIST;
+
+
+// Parameters for timeout thread for Solaris
+typedef struct SOCKET_TIMEOUT_PARAM{
+ SOCK *sock;
+ CANCEL *cancel;
+ THREAD *thread;
+ bool unblocked;
+} SOCKET_TIMEOUT_PARAM;
+
+// Parameters for GetIP thread
+struct GETIP_THREAD_PARAM
+{
+ REF *Ref;
+ char HostName[MAX_PATH];
+ bool IPv6;
+ UINT Timeout;
+ IP Ip;
+ bool Ok;
+};
+
+// Parameters for the IP address release thread
+struct WIN32_RELEASEADDRESS_THREAD_PARAM
+{
+ REF *Ref;
+ char Guid[MAX_SIZE];
+ UINT Timeout;
+ bool Ok;
+ bool Renew;
+};
+
+// TCP table entry
+typedef struct TCPTABLE
+{
+ UINT Status;
+ IP LocalIP;
+ UINT LocalPort;
+ IP RemoteIP;
+ UINT RemotePort;
+ UINT ProcessId;
+} TCPTABLE;
+
+// State of TCP
+#define TCP_STATE_CLOSED 1
+#define TCP_STATE_LISTEN 2
+#define TCP_STATE_SYN_SENT 3
+#define TCP_STATE_SYN_RCVD 4
+#define TCP_STATE_ESTAB 5
+#define TCP_STATE_FIN_WAIT1 6
+#define TCP_STATE_FIN_WAIT2 7
+#define TCP_STATE_CLOSE_WAIT 8
+#define TCP_STATE_CLOSING 9
+#define TCP_STATE_LAST_ACK 10
+#define TCP_STATE_TIME_WAIT 11
+#define TCP_STATE_DELETE_TCB 12
+
+// Routing table changing notification
+struct ROUTE_CHANGE
+{
+ ROUTE_CHANGE_DATA *Data;
+};
+
+// Tube flush list
+struct TUBE_FLUSH_LIST
+{
+ LIST *List; // List
+};
+
+// Tube
+struct TUBE
+{
+ REF *Ref; // Reference counter
+ LOCK *Lock; // Lock
+ QUEUE *Queue; // Packet queue
+ EVENT *Event; // Event
+ SOCK_EVENT *SockEvent; // SockEvent
+ UINT SizeOfHeader; // Header size
+ TUBEPAIR_DATA *TubePairData; // Tube pair data
+ UINT IndexInTubePair; // Number in the tube pair
+ bool IsInFlushList; // Whether it is registered in the Tube Flush List
+ void *Param1, *Param2, *Param3;
+ UINT IntParam1, IntParam2, IntParam3;
+};
+
+// Data that is to send and to receive in the tube
+struct TUBEDATA
+{
+ void *Data; // Body of data
+ UINT DataSize; // The size of the data
+ void *Header; // The body of the header
+ UINT HeaderSize; // Size of the header
+};
+
+// Tube pair data
+struct TUBEPAIR_DATA
+{
+ bool IsDisconnected; // Disconnection flag
+ REF *Ref; // Reference counter
+ LOCK *Lock; // Lock
+ EVENT *Event1, *Event2; // Event
+ SOCK_EVENT *SockEvent1, *SockEvent2; // SockEvent
+};
+
+// UDP listener socket entry
+struct UDPLISTENER_SOCK
+{
+ IP IpAddress; // IP address
+ UINT Port; // Port number
+ SOCK *Sock; // Socket
+ bool HasError; // Whether an error occurs
+ bool Mark; // Mark
+ bool ErrorDebugDisplayed; // Whether the error has been displayed
+ UINT64 NextMyIpAndPortPollTick; // Time to check the self IP address and port number next
+ IP PublicIpAddress; // Global IP address
+ UINT PublicPort; // Global port number
+};
+
+// UDP packet
+struct UDPPACKET
+{
+ IP SrcIP; // Source IP address
+ IP DstIP; // Destination IP address
+ UINT SrcPort; // Source port
+ UINT DestPort; // Destination port
+ UINT Size; // Data size
+ void *Data; // Data body
+ UINT Type; // Type
+};
+
+// UDP listener packet receipt notification procedure
+typedef void (UDPLISTENER_RECV_PROC)(UDPLISTENER *u, LIST *packet_list);
+
+// UDP listener
+struct UDPLISTENER
+{
+ bool Halt; // Halting flag
+ SOCK_EVENT *Event; // Event
+ THREAD *Thread; // Thread
+ LIST *PortList; // Port list
+ LIST *SockList; // Socket list
+ UINT64 LastCheckTick; // Time which the socket list was checked last
+ UDPLISTENER_RECV_PROC *RecvProc; // Receive procedure
+ LIST *SendPacketList; // Transmission packet list
+ void *Param; // Parameters
+ INTERRUPT_MANAGER *Interrupts; // Interrupt manager
+ bool HostIPAddressListChanged; // IP address list of the host has changed
+ bool IsEspRawPortOpened; // Whether the raw port opens
+ bool PollMyIpAndPort; // Examine whether the global IP and the port number of its own
+ QUERYIPTHREAD *GetNatTIpThread; // NAT-T IP address acquisition thread
+};
+
+#define QUERYIPTHREAD_INTERVAL_LAST_OK (3 * 60 * 60 * 1000)
+#define QUERYIPTHREAD_INTERVAL_LAST_NG (30 * 1000)
+
+// IP address acquisition thread
+struct QUERYIPTHREAD
+{
+ THREAD *Thread; // Thread
+ EVENT *HaltEvent; // Halting event
+ bool Halt; // Halting flag
+ LOCK *Lock; // Lock
+ IP Ip; // Get the IP address
+ char Hostname[MAX_SIZE]; // Host name
+ UINT IntervalLastOk; // Interval if last was OK
+ UINT IntervalLastNg; // Interval if last was NG
+};
+
+// Interrupt management
+struct INTERRUPT_MANAGER
+{
+ LIST *TickList; // Time list
+};
+
+// SSL BIO
+struct SSL_BIO
+{
+ BIO *bio; // BIO
+ FIFO *SendFifo; // Transmission FIFO
+ FIFO *RecvFifo; // Reception FIFO
+ bool IsDisconnected; // Disconnected
+ bool NoFree; // Not to release the BIO
+};
+
+// SSL pipe
+struct SSL_PIPE
+{
+ bool ServerMode; // Whether it's in the server mode
+ bool IsDisconnected; // Disconnected
+ SSL *ssl; // SSL object
+ struct ssl_ctx_st *ssl_ctx; // SSL_CTX
+ SSL_BIO *SslInOut; // I/O BIO for the data in the SSL tunnel
+ SSL_BIO *RawIn, *RawOut; // Input and output BIO of the data flowing through the physical network
+};
+
+// IP address block list
+struct IPBLOCK
+{
+ IP Ip; // IP address
+ IP Mask; // Subnet mask
+};
+
+
+// R-UDP related constants
+#define RUDP_RESEND_TIMER 200 // Retransmission timer (initial value)
+#define RUDP_RESEND_TIMER_MAX 4792 // Retransmission timer (maximum value)
+#define RUDP_KEEPALIVE_INTERVAL_MIN 2500 // Transmission interval of Keep Alive (minimum)
+#define RUDP_KEEPALIVE_INTERVAL_MAX 4792 // Transmission interval of Keep Alive (maximum)
+#define RUDP_TIMEOUT 12000 // Time-out of R-UDP communication
+#define RUDP_DIRECT_CONNECT_TIMEOUT 5000 // R-UDP direct connection time-out
+#define RUDP_MAX_SEGMENT_SIZE 512 // Maximum segment size
+// Maximum R-UDP packet size
+#define RUDP_MAX_PACKET_SIZE (RUDP_MAX_SEGMENT_SIZE + sizeof(UINT64) * RUDP_MAX_NUM_ACK + SHA1_SIZE * 2 + sizeof(UINT64) * 4 + sizeof(UINT) + 255)
+#define RUDP_MAX_NUM_ACK 64 // Maximum number of ACKs
+#define RUDP_LOOP_WAIT_INTERVAL_S 1234 // Waiting time in the thread main loop (in server side)
+#define RUDP_LOOP_WAIT_INTERVAL_C 100 // Waiting time in the thread main loop (in client side)
+#define RUDP_MAX_FIFO_SIZE (1600 * 1600) // The maximum FIFO buffer size
+
+// Interval for sending ICMP Echo from the client side when R-UDP used in ICMP mode
+#define RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN 1000
+#define RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX 3000
+
+// R-UDP error code
+#define RUDP_ERROR_OK 0 // Success
+#define RUDP_ERROR_UNKNOWN 1 // Unknown Error
+#define RUDP_ERROR_TIMEOUT 2 // Time-out
+#define RUDP_ERROR_NAT_T_GETIP_FAILED 3 // IP address acquisition failure of NAT-T server
+#define RUDP_ERROR_NAT_T_NO_RESPONSE 4 // There is no response from the NAT-T server
+#define RUDP_ERROR_NAT_T_TWO_OR_MORE 5 // There are two or more hosts on the same destination IP address
+#define RUDP_ERROR_NAT_T_NOT_FOUND 6 // Host does not exist at the specified IP address
+#define RUDP_ERROR_USER_CANCELED 7 // Cancel by the user
+
+// R-UDP segment
+struct RUDP_SEGMENT
+{
+ UINT64 SeqNo; // Sequence number
+ UINT Size; // Size
+ UCHAR Data[RUDP_MAX_SEGMENT_SIZE]; // Data
+ UINT64 NextSendTick; // Next transmission time
+ UINT NumSent; // Number of times sent
+};
+
+// Status of R-UDP session
+#define RUDP_SESSION_STATUS_CONNECT_SENT 0 // Connection request sent
+#define RUDP_SESSION_STATUS_ESTABLISHED 1 // Connection established
+
+// Quota
+#define RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP DYN32(RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP, 1000) // The number of R-UDP sessions per an IP address
+#define RUDP_QUOTA_MAX_NUM_SESSIONS DYN32(RUDP_QUOTA_MAX_NUM_SESSIONS, 30000) // Limit of the Number of sessions
+
+// Range of the sequence numbers of bulk packet
+#define RUDP_BULK_SEQ_NO_RANGE 16384ULL
+#define RUDP_BULK_MAX_RECV_PKTS_IN_QUEUE 8192
+
+// R-UDP session
+struct RUDP_SESSION
+{
+ UINT Status; // Status
+ bool ServerMode; // Whether it's in the server mode
+ bool DisconnectFlag; // Disconnection flag
+ bool DisconnectedByYou; // Disconnected from opponent
+ bool UseHMac;
+ IP MyIp; // IP address of itself
+ UINT MyPort; // Port number of itself
+ IP YourIp; // Opponent IP address
+ UINT YourPort; // Opponent port number
+ LIST *SendSegmentList; // Transmission segment list
+ LIST *RecvSegmentList; // Received segments list
+ LIST *ReplyAckList; // List of ACKs in response
+ SOCK *TcpSock; // Corresponding TCP socket
+ UINT64 LastSentTick; // Time which the data has been sent last
+ UINT64 LastRecvTick; // Time which the data has been received last
+ UCHAR Key_Init[SHA1_SIZE]; // Initial key
+ UCHAR Key_Send[SHA1_SIZE]; // Key that is used to send
+ UCHAR Key_Recv[SHA1_SIZE]; // Key that is used to receive
+ UCHAR Magic_KeepAliveRequest[SHA1_SIZE]; // The magic number for the KeepAlive request
+ UCHAR Magic_KeepAliveResponse[SHA1_SIZE]; // The magic number for KeepAlive response
+ UINT64 Magic_Disconnect; // Disconnection Signal
+ UINT64 NextSendSeqNo; // Transmission sequence number to be used next
+ UINT64 LastRecvCompleteSeqNo; // Sequence number of receiving complete
+ // (This indicates all segments which have sequence number up to this number are received completely)
+ UCHAR NextIv[SHA1_SIZE]; // IV value to be used next
+ UINT NextKeepAliveInterval; // Interval value of KeepAlive to be used next
+ FIFO *RecvFifo; // Reception FIFO
+ FIFO *SendFifo; // Transmission FIFO
+ UINT64 YourTick; // The largest value among received Tick from the opponent
+ UINT64 LatestRecvMyTick; // Value of the last tick among the received tick values
+ UINT64 LatestRecvMyTick2; // Variable for confirming whether LatestRecvMyTick2 changes
+ UINT CurrentRtt; // Current RTT value
+
+ UINT Icmp_Type; // Number of Type to be used in the ICMP
+ USHORT Dns_TranId; // Value of transaction ID used in DNS
+ UINT64 Client_Icmp_NextSendEchoRequest; // Time to send the next Echo Request in the ICMP
+ SHARED_BUFFER *BulkSendKey; // Bulk send key
+ SHARED_BUFFER *BulkRecvKey; // Bulk receive key
+ UCHAR BulkNextIv[SHA1_SIZE]; // Next IV to the bulk send
+ UINT64 BulkNextSeqNo; // Next SEQ NO to the bulk send
+ bool FlushBulkSendTube; // Flag to be Flush the bulk send Tube
+ UINT64 BulkRecvSeqNoMax; // Highest sequence number received
+};
+
+// NAT Traversal Server Information
+#define UDP_NAT_T_SERVER_TAG "x%c.x%c.x%c.x%c.servers.nat-traversal.softether-network.net."
+#define UDP_NAT_T_SERVER_TAG_ALT "x%c.x%c.x%c.x%c.servers.nat-traversal.uxcom.jp."
+#define UDP_NAT_T_PORT 5004
+
+// Related to processing to get the IP address of the NAT-T server
+#define UDP_NAT_T_GET_IP_INTERVAL DYN32(UDP_NAT_T_GET_IP_INTERVAL, (5 * 1000)) // IP address acquisition interval of NAT-T server (before success)
+#define UDP_NAT_T_GET_IP_INTERVAL_AFTER DYN32(UDP_NAT_T_GET_IP_INTERVAL_AFTER, (5 * 60 * 1000)) // IP address acquisition interval of NAT-T server (after success)
+
+// Related to process to get the private IP address of itself with making a TCP connection to the NAT-T server
+#define UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER "get-my-ip.nat-traversal.softether-network.net."
+#define UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER_ALT "get-my-ip.nat-traversal.uxcom.jp."
+
+#define UDP_NAT_T_PORT_FOR_TCP_1 992
+#define UDP_NAT_T_PORT_FOR_TCP_2 80
+#define UDP_NAT_T_PORT_FOR_TCP_3 443
+
+#define UDP_NAT_TRAVERSAL_VERSION 1
+
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL, (15 * 60 * 1000)) // Polling interval (before success)
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN, (30 * 60 * 1000)) // Polling interval (after success)
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX, (60 * 60 * 1000)) // Polling interval (after success)
+#define UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT DYN32(UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT, (5 * 1000)) // TCP connection time-out
+
+// About token acquisition from the NAT-T server
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_1 DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_1, (5 * 1000)) // Token acquisition interval from the NAT-T server (If not acquired)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX, 20)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN, (20 * 60 * 1000)) // Token acquisition interval minimum value from the NAT-T server (If token have been obtained)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX, (30 * 60 * 1000)) // Token acquisition interval maximum value from the NAT-T server (If token have been obtained)
+
+// The Register interval for NAT-T server
+#define UDP_NAT_T_REGISTER_INTERVAL_INITIAL DYN32(UDP_NAT_T_REGISTER_INTERVAL_INITIAL, (5 * 1000)) // Transmission interval when the Register is not completed
+#define UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX, 20)
+#define UDP_NAT_T_REGISTER_INTERVAL_MIN DYN32(UDP_NAT_T_REGISTER_INTERVAL_MIN, (220 * 1000)) // Minimum value of the Register interval
+#define UDP_NAT_T_REGISTER_INTERVAL_MAX DYN32(UDP_NAT_T_REGISTER_INTERVAL_MAX, (240 * 1000)) // Maximum value of the Register interval
+
+// Interval for checking whether the port number or the IP address is changed
+#define UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN DYN32(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, (24 * 1000))
+#define UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX DYN32(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX, (28 * 1000))
+
+// The Connect Request interval for NAT-T server
+#define UDP_NAT_T_CONNECT_INTERVAL DYN32(UDP_NAT_T_CONNECT_INTERVAL, 200)
+
+// Polling interval for its own IP information acquisition to the NAT-T server in regular communication between the client and the server
+#define UDP_NAT_T_INTERVAL_MIN DYN32(UDP_NAT_T_INTERVAL_MIN, (5 * 60 * 1000))
+#define UDP_NAT_T_INTERVAL_MAX DYN32(UDP_NAT_T_INTERVAL_MAX, (10 * 60 * 1000))
+#define UDP_NAT_T_INTERVAL_INITIAL DYN32(UDP_NAT_T_INTERVAL_INITIAL, (3 * 1000))
+#define UDP_NAT_T_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_INTERVAL_FAIL_MAX, 60)
+
+// R-UDP stack callback function definition
+typedef void (RUDP_STACK_INTERRUPTS_PROC)(RUDP_STACK *r);
+typedef bool (RUDP_STACK_RPC_RECV_PROC)(RUDP_STACK *r, UDPPACKET *p);
+
+// ICMP protocol number
+#define IP_PROTO_ICMPV4 0x01 // ICMPv4 protocol
+#define IP_PROTO_ICMPV6 0x3a // ICMPv6 protocol
+
+// R-UDP protocol
+#define RUDP_PROTOCOL_UDP 0 // UDP
+#define RUDP_PROTOCOL_ICMP 1 // ICMP
+#define RUDP_PROTOCOL_DNS 2 // DNS
+
+// Minimum time to wait for a trial to connect by ICMP and DNS in case failing to connect by TCP
+#define SOCK_CONNECT_WAIT_FOR_ICMP_AND_DNS_AT_LEAST 5000
+
+// R-UDP stack
+struct RUDP_STACK
+{
+ bool ServerMode; // Whether it's in the server mode
+ char SvcName[MAX_SIZE]; // Service name
+ UCHAR SvcNameHash[SHA1_SIZE]; // Hash of the service name
+ bool Halt; // Halting flag
+ void *Param; // Parameters that can be used by developers
+ UINT64 Now; // Current time
+ EVENT *HaltEvent; // Halting event
+ INTERRUPT_MANAGER *Interrupt; // Interrupt manager
+ LIST *SessionList; // Session List
+ SOCK *UdpSock; // UDP socket
+ UINT Port; // Port number
+ UINT Protocol; // Protocol
+ SOCK_EVENT *SockEvent; // Socket event
+ THREAD *Thread; // Thread
+ LOCK *Lock; // Lock
+ RUDP_STACK_INTERRUPTS_PROC *ProcInterrupts; // Interrupt notification callback
+ RUDP_STACK_RPC_RECV_PROC *ProcRpcRecv; // RPC reception notification callback
+ THREAD *IpQueryThread; // NAT-T server IP inquiry thread
+ UCHAR TmpBuf[65536]; // Temporary buffer
+ LIST *SendPacketList; // Transmission UDP packet list
+ EVENT *NewSockConnectEvent; // Event to inform that a new socket is connected
+ QUEUE *NewSockQueue; // Queue of new socket
+ UINT64 TotalPhysicalReceived; // Physical amount of data received
+ UINT64 TotalLogicalReceived; // Logical amount of data received
+ UINT64 TotalPhysicalSent; // Physical amount of data transmitted
+ UINT64 TotalLogicalSent; // Logical amount of data transmitted
+ char CurrentRegisterHostname[MAX_SIZE]; // The host name of the the current destination of registration
+
+ // NAT-T server related
+ bool NoNatTRegister; // Flag not to register with the NAT-T server
+ UINT64 NatT_TranId; // Transaction ID is used to communicate with the NAT-T server
+ IP NatT_IP; // IP address of the NAT-T server
+ IP NatT_IP_Safe; // IP address of the NAT-T server (thread-safe)
+ IP My_Private_IP; // Private IP address of itself
+ IP My_Private_IP_Safe; // Private IP address of itself (thread-safe)
+ UINT64 NatT_GetTokenNextTick; // Time to get the next token
+ UINT NatT_GetTokenFailNum; // Token acquisition failure times
+ char NatT_Token[MAX_SIZE]; // Token needed to communicate with NAT-T Server
+ bool NatT_Token_Ok; // Flag of whether it have a valid token
+ UINT64 NatT_RegisterNextTick; // Time to register next
+ UINT NatT_RegisterFailNum; // The number of Register failures
+ bool NatT_Register_Ok; // Is a successful registration
+ char NatT_Registered_IPAndPort[128]; // IP address and port number at the time of registration success
+ UINT64 NatT_NextNatStatusCheckTick; // Time to check the NAT state next
+ UINT LastDDnsFqdnHash; // DNS FQDN hash value when last checked
+ volatile UINT *NatTGlobalUdpPort; // NAT-T global UDP port
+ UCHAR RandPortId; // Random UDP port ID
+
+ // For Client
+ bool TargetIpAndPortInited; // The target IP address and the port number are initialized
+ IP TargetIp; // Target IP address
+ UINT TargetPort; // Target port number
+ EVENT *TargetConnectedEvent; // Event to be set when the connection to the target is successful
+ SOCK *TargetConnectedSock; // Connected socket
+ bool ClientInitiated; // Flag to indicate that the connection is initiated
+ bool DoNotSetTargetConnectedSock; // Flag indicating that it should not set the TargetConnectedSock
+ USHORT Client_IcmpId, Client_IcmpSeqNo; // Sequence number and ICMP ID that is randomly generated on the client side
+};
+
+// Data for the thread for concurrent connection attempts for the R-UDP and TCP
+struct CONNECT_TCP_RUDP_PARAM
+{
+ IP Ip;
+ UINT Port;
+ UINT Timeout;
+ char Hostname[MAX_SIZE];
+ bool *CancelFlag;
+ UINT NatT_ErrorCode;
+ char SvcName[MAX_SIZE];
+ char HintStr[MAX_SIZE];
+ char TargetHostname[MAX_SIZE];
+ SOCK *Result_Nat_T_Sock;
+ SOCK *Result_Tcp_Sock;
+ bool Finished;
+ bool Ok;
+ UINT64 FinishedTick;
+ EVENT *FinishEvent;
+ UINT RUdpProtocol;
+ UINT Delay;
+ bool Tcp_TryStartSsl;
+ bool Tcp_SslNoTls;
+ LOCK *CancelLock;
+ SOCK *CancelDisconnectSock;
+};
+
+#define SSL_DEFAULT_CONNECT_TIMEOUT (15 * 1000) // SSL default timeout
+
+// Header for TCP Pair
+struct TCP_PAIR_HEADER
+{
+ bool EnableHMac;
+};
+
+// The constants for file query by using UDP
+#define UDP_FILE_QUERY_RETRY_INTERVAL 100 // Retry interval
+#define UDP_FILE_QUERY_DST_PORT 5004 // Destination UDP port number
+#define UDP_FILE_QUERY_MAGIC_NUMBER "{5E465695-7923-4CCD-9B51-44444BE1E758}" // Magic number
+#define UDP_FILE_QUERY_BFLETS_TXT_FILENAME "|BFletsUdpList.txt" // Text file name of the IPv6 node list
+
+// The constant for DNS proxy for the B FLETs
+#define BFLETS_DNS_PROXY_PORT 443
+#define BFLETS_DNS_PROXY_PATH "/ddns/queryhost.aspx"
+#define BFLETS_DNS_PROXY_CERT_HASH "EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3"
+#define BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F 500 // Timeout when searching for the server by UDP
+#define BFLETS_DNS_PROXY_TIMEOUT_FOR_QUERY 3000 // Timeout for the response from the proxy DNS server
+
+// FLET'S Hikar-Next (East) DNS proxy host name
+#define FLETS_NGN_EAST_DNS_PROXY_HOSTNAME "senet.aoi.flets-east.jp"
+#define FLETS_NGN_WEST_DNS_PROXY_HOSTNAME "senet.p-ns.flets-west.jp"
+#define FLETS_NGN_DNS_QUERY_TIMEOUT 1000 // FLET'S Hikar-Next host name query timeout
+
+// Detection result of the type of FLET'S line
+#define FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE 1 // NTT East B-FLETs
+#define FLETS_DETECT_TYPE_EAST_NGN_PRIVATE 2 // Wrapping in network of NTT East NGN
+#define FLETS_DETECT_TYPE_WEST_NGN_PRIVATE 4 // Wrapping in network of NTT West NGN
+
+// NIC adapter entry
+struct NIC_ENTRY
+{
+ char IfName[MAX_SIZE];
+ UCHAR MacAddress[6];
+};
+
+
+// HTTP value
+struct HTTP_VALUE
+{
+ char *Name; // Name
+ char *Data; // Data
+};
+
+// HTTP header
+struct HTTP_HEADER
+{
+ char *Method; // Method
+ char *Target; // Target
+ char *Version; // Version
+ LIST *ValueList; // Value list
+};
+
+// HTTPS server / client related string constant
+#define DEFAULT_USER_AGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
+#define DEFAULT_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-powerpoint, application/vnd.ms-excel, */*"
+#define DEFAULT_ENCODING "gzip, deflate"
+#define HTTP_CONTENT_TYPE "text/html; charset=iso-8859-1"
+#define HTTP_CONTENT_TYPE2 "application/octet-stream"
+#define HTTP_CONTENT_TYPE3 "image/jpeg"
+#define HTTP_CONTENT_TYPE4 "text/html"
+#define HTTP_CONTENT_TYPE5 "message/rfc822"
+#define HTTP_KEEP_ALIVE "timeout=15; max=19"
+#define HTTP_VPN_TARGET "/vpnsvc/vpn.cgi"
+#define HTTP_VPN_TARGET2 "/vpnsvc/connect.cgi"
+#define HTTP_VPN_TARGET_POSTDATA "VPNCONNECT"
+#define HTTP_SAITAMA "/saitama.jpg"
+#define HTTP_PICTURES "/picture"
+// Maximum size of a single line in the HTTP header
+#define HTTP_HEADER_LINE_MAX_SIZE 4096
+// Maximum number of lines in the HTTP header
+#define HTTP_HEADER_MAX_LINES 128
+// Maximum size of the random number to be included in the PACK
+#define HTTP_PACK_RAND_SIZE_MAX 1000
+// Maximum PACK size in the HTTP
+#define HTTP_PACK_MAX_SIZE 65536
+
+
+
+
+
+int GetCurrentTimezone();
+
+bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size);
+bool GetSniNameFromPreSslConnection(SOCK *s, char *sni, UINT sni_size);
+
+bool IsUseDnsProxy();
+bool IsUseAlternativeHostname();
+
+#ifdef OS_WIN32
+int GetCurrentTimezoneWin32();
+#endif // OS_WIN32
+
+HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name);
+void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value);
+HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version);
+HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort);
+int CompareHttpValue(void *p1, void *p2);
+void FreeHttpValue(HTTP_VALUE *value);
+void FreeHttpHeader(HTTP_HEADER *header);
+
+bool SendPack(SOCK *s, PACK *p);
+PACK *RecvPack(SOCK *s);
+PACK *RecvPackWithHash(SOCK *s);
+bool SendPackWithHash(SOCK *s, PACK *p);
+
+UINT GetErrorFromPack(PACK *p);
+PACK *PackError(UINT error);
+
+void CreateDummyValue(PACK *p);
+
+HTTP_VALUE *NewHttpValue(char *name, char *data);
+char *RecvLine(SOCK *s, UINT max_size);
+HTTP_HEADER *RecvHttpHeader(SOCK *s);
+bool SendHttpHeader(SOCK *s, HTTP_HEADER *header);
+char *HttpHeaderToStr(HTTP_HEADER *header);
+bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size);
+UINT GetContentLength(HTTP_HEADER *header);
+void GetHttpDateStr(char *str, UINT size, UINT64 t);
+bool HttpSendForbidden(SOCK *s, char *target, char *server_id);
+bool HttpSendNotFound(SOCK *s, char *target);
+bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version);
+bool HttpServerSend(SOCK *s, PACK *p);
+bool HttpClientSend(SOCK *s, PACK *p);
+PACK *HttpServerRecv(SOCK *s);
+PACK *HttpClientRecv(SOCK *s);
+
+bool HttpSendServerError(SOCK *s, char *target);
+
+bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname);
+bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel);
+BUF *QueryFileByUdpForJapanBFlets(UINT timeout, bool *cancel);
+BUF *QueryFileByIPv6Udp(LIST *ip_list, UINT timeout, bool *cancel);
+UINT DetectFletsType();
+
+void ListenTcpForPopupFirewallDialog();
+
+bool DetectIsServerSoftEtherVPN(SOCK *s);
+void ConnectThreadForTcp(THREAD *thread, void *param);
+void ConnectThreadForRUDP(THREAD *thread, void *param);
+void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
+SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
+RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode);
+RUDP_STACK *NewRUDP(bool server_mode, char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, SOCK *sock, SOCK_EVENT *sock_event, bool server_no_natt_register, bool over_dns_mode, IP *client_target_ip, volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+void FreeRUDP(RUDP_STACK *r);
+void RUDPMainThread(THREAD *thread, void *param);
+void RUDPRecvProc(RUDP_STACK *r, UDPPACKET *p);
+void RUDPInterruptProc(RUDP_STACK *r);
+void RUDPIpQueryThread(THREAD *thread, void *param);
+void RUDPSendPacket(RUDP_STACK *r, IP *dest_ip, UINT dest_port, void *data, UINT size, UINT icmp_type);
+void GetCurrentMachineIpProcessHash(void *hash);
+void GetCurrentMachineIpProcessHashInternal(void *hash);
+int RUDPCompareSessionList(void *p1, void *p2);
+RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port, UCHAR *init_key);
+void RUDPFreeSession(RUDP_SESSION *se);
+int RUDPCompareSegmentList(void *p1, void *p2);
+RUDP_SESSION *RUDPSearchSession(RUDP_STACK *r, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port);
+void RUDPSendSegmentNow(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq_no, void *data, UINT size);
+void RUDPSendSegment(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT size);
+bool RUDPProcessRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+void RUDPProcessAck(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq);
+void RUDPProcessAck2(RUDP_STACK *r, RUDP_SESSION *se, UINT64 max_seq);
+void RUDPProcessRecvPayload(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq, void *payload_data, UINT payload_size);
+void RUDPInitSock(RUDP_STACK *r, RUDP_SESSION *se);
+void RUDPDisconnectSession(RUDP_STACK *r, RUDP_SESSION *se, bool disconnected_by_you);
+UINT64 RUDPGetCurrentSendingMinSeqNo(RUDP_SESSION *se);
+UINT64 RUDPGetCurrentSendingMaxSeqNo(RUDP_SESSION *se);
+SOCK *ListenRUDP(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode);
+SOCK *ListenRUDPEx(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+SOCK *AcceptRUDP(SOCK *s);
+void *InitWaitUntilHostIPAddressChanged();
+void FreeWaitUntilHostIPAddressChanged(void *p);
+void WaitUntilHostIPAddressChanged(void *p, EVENT *event, UINT timeout, UINT ip_check_interval);
+UINT GetHostIPAddressHash32();
+bool GetMyPrivateIP(IP *ip);
+UINT GenRandInterval(UINT min, UINT max);
+void RUDPProcess_NatT_Recv(RUDP_STACK *r, UDPPACKET *udp);
+void RUDPDo_NatT_Interrupt(RUDP_STACK *r);
+void RUDPGetRegisterHostNameByIP(char *dst, UINT size, IP *ip);
+bool RUDPParseIPAndPortStr(void *data, UINT data_size, IP *ip, UINT *port);
+void ParseNtUsername(char *src_username, char *dst_username, UINT dst_username_size, char *dst_domain, UINT dst_domain_size, bool do_not_parse_atmark);
+void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size);
+bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+UINT RUDPCalcBestMssForBulk(RUDP_STACK *r, RUDP_SESSION *se);
+bool IsIPLocalHostOrMySelf(IP *ip);
+UINT RUDPGetRandPortNumber(UCHAR rand_port_id);
+
+bool GetBestLocalIpForTarget(IP *local_ip, IP *target_ip);
+SOCK *NewUDP4ForSpecificIp(IP *target_ip, UINT port);
+
+#ifdef OS_WIN32
+
+// Function prototype for Win32
+void Win32InitSocketLibrary();
+void Win32FreeSocketLibrary();
+void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void Win32InitAsyncSocket(SOCK *sock);
+void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+void Win32FreeAsyncSocket(SOCK *sock);
+void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row);
+void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry);
+int Win32CompareRouteEntryByMetric(void *p1, void *p2);
+ROUTE_TABLE *Win32GetRouteTable();
+bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists);
+void Win32DeleteRouteEntry(ROUTE_ENTRY *e);
+void Win32UINTToIP(IP *ip, UINT i);
+UINT Win32IPToUINT(IP *ip);
+UINT Win32GetVLanInterfaceID(char *instance_name);
+char **Win32EnumVLan(char *tag_name);
+void Win32Cancel(CANCEL *c);
+void Win32CleanupCancel(CANCEL *c);
+CANCEL *Win32NewCancel();
+SOCK_EVENT *Win32NewSockEvent();
+void Win32SetSockEvent(SOCK_EVENT *event);
+void Win32CleanupSockEvent(SOCK_EVENT *event);
+bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout);
+bool Win32GetDefaultDns(IP *ip, char *domain, UINT size);
+bool Win32GetDnsSuffix(char *domain, UINT size);
+void Win32RenewDhcp();
+void Win32RenewDhcp9x(UINT if_id);
+void Win32ReleaseDhcp9x(UINT if_id, bool wait);
+void Win32FlushDnsCache();
+int CompareIpAdapterIndexMap(void *p1, void *p2);
+LIST *Win32GetTcpTableList();
+LIST *Win32GetTcpTableListByGetExtendedTcpTable();
+LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();
+LIST *Win32GetTcpTableListByGetTcpTable();
+ROUTE_CHANGE *Win32NewRouteChange();
+void Win32FreeRouteChange(ROUTE_CHANGE *r);
+bool Win32IsRouteChanged(ROUTE_CHANGE *r);
+bool Win32GetAdapterFromGuid(void *a, char *guid);
+SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6);
+
+bool Win32ReleaseAddress(void *a);
+bool Win32ReleaseAddressByGuid(char *guid);
+bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout);
+void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param);
+void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p);
+bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew);
+bool Win32RenewAddress(void *a);
+bool Win32RenewAddressByGuid(char *guid);
+bool Win32RenewAddressByGuidEx(char *guid, UINT timeout);
+
+
+#else // OS_WIN32
+
+// Function prototype for UNIX
+void UnixInitSocketLibrary();
+void UnixFreeSocketLibrary();
+void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void UnixInitAsyncSocket(SOCK *sock);
+void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+void UnixFreeAsyncSocket(SOCK *sock);
+void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row);
+void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry);
+int UnixCompareRouteEntryByMetric(void *p1, void *p2);
+ROUTE_TABLE *UnixGetRouteTable();
+bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists);
+void UnixDeleteRouteEntry(ROUTE_ENTRY *e);
+UINT UnixGetVLanInterfaceID(char *instance_name);
+char **UnixEnumVLan(char *tag_name);
+void UnixCancel(CANCEL *c);
+void UnixCleanupCancel(CANCEL *c);
+CANCEL *UnixNewCancel();
+SOCK_EVENT *UnixNewSockEvent();
+void UnixSetSockEvent(SOCK_EVENT *event);
+void UnixCleanupSockEvent(SOCK_EVENT *event);
+bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout);
+bool UnixGetDefaultDns(IP *ip);
+void UnixRenewDhcp();
+void UnixNewPipe(int *pipe_read, int *pipe_write);
+void UnixWritePipe(int pipe_write);
+void UnixDeletePipe(int p1, int p2);
+void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout);
+void UnixSetSocketNonBlockingMode(int fd, bool nonblock);
+
+#endif // OS_WIN32
+
+// Function prototype
+void InitNetwork();
+void FreeNetwork();
+void InitDnsCache();
+void FreeDnsCache();
+void LockDnsCache();
+void UnlockDnsCache();
+int CompareDnsCache(void *p1, void *p2);
+void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6);
+void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6);
+DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6);
+bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6);
+void NewDnsCache(char *hostname, IP *ip);
+DNSCACHE *FindDnsCache(char *hostname);
+bool QueryDnsCache(IP *ip, char *hostname);
+void InAddrToIP(IP *ip, struct in_addr *addr);
+void InAddrToIP6(IP *ip, struct in6_addr *addr);
+void IPToInAddr(struct in_addr *addr, IP *ip);
+void IPToInAddr6(struct in6_addr *addr, IP *ip);
+bool StrToIP(IP *ip, char *str);
+UINT StrToIP32(char *str);
+bool UniStrToIP(IP *ip, wchar_t *str);
+UINT UniStrToIP32(wchar_t *str);
+void IPToStr(char *str, UINT size, IP *ip);
+void IPToStr4(char *str, UINT size, IP *ip);
+void IPToStr32(char *str, UINT size, UINT ip);
+void IPToStr128(char *str, UINT size, UCHAR *ip_bytes);
+void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes);
+void IPToUniStr(wchar_t *str, UINT size, IP *ip);
+void IPToUniStr32(wchar_t *str, UINT size, UINT ip);
+bool GetIPEx(IP *ip, char *hostname, bool ipv6);
+bool GetIP46(IP *ip4, IP *ip6, char *hostname);
+bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel);
+bool GetIP46Any4(IP *ip, char *hostname);
+bool GetIP46Any6(IP *ip, char *hostname);
+bool GetIP(IP *ip, char *hostname);
+bool GetIP4(IP *ip, char *hostname);
+bool GetIP6(IP *ip, char *hostname);
+bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel);
+bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel);
+bool GetIP4Ex6Ex(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel);
+bool GetIP4Ex6Ex2(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns);
+void GetIP4Ex6ExThread(THREAD *t, void *param);
+void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p);
+void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p);
+bool GetIP4Inner(IP *ip, char *hostname);
+bool GetIP6Inner(IP *ip, char *hostname);
+bool GetHostNameInner(char *hostname, UINT size, IP *ip);
+bool GetHostNameInner6(char *hostname, UINT size, IP *ip);
+bool GetHostName(char *hostname, UINT size, IP *ip);
+void GetHostNameThread(THREAD *t, void *p);
+void GetMachineName(char *name, UINT size);
+void GetMachineNameEx(char *name, UINT size, bool no_load_hosts);
+bool GetMachineNameFromHosts(char *name, UINT size);
+void GetMachineIp(IP *ip);
+void GetMachineHostName(char *name, UINT size);
+void UINTToIP(IP *ip, UINT value);
+UINT IPToUINT(IP *ip);
+SOCK *NewSock();
+void ReleaseSock(SOCK *s);
+void CleanupSock(SOCK *s);
+SOCK *Connect(char *hostname, UINT port);
+SOCK *ConnectEx(char *hostname, UINT port, UINT timeout);
+SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag);
+SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, bool no_get_hostname);
+SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag);
+void SetSocketSendRecvBufferSize(SOCKET s, UINT size);
+UINT GetSocketBufferSize(SOCKET s, bool send);
+bool SetSocketBufferSize(SOCKET s, bool send, UINT size);
+UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size);
+void InitUdpSocketBufferSize(SOCKET s);
+void QuerySocketInformation(SOCK *sock);
+bool SetTtl(SOCK *sock, UINT ttl);
+void Disconnect(SOCK *sock);
+SOCK *Listen(UINT port);
+SOCK *ListenEx(UINT port, bool local_only);
+SOCK *ListenEx2(UINT port, bool local_only, bool enable_ca);
+SOCK *Listen6(UINT port);
+SOCK *ListenEx6(UINT port, bool local_only);
+SOCK *ListenEx62(UINT port, bool local_only, bool enable_ca);
+SOCK *Accept(SOCK *sock);
+SOCK *Accept6(SOCK *sock);
+UINT Send(SOCK *sock, void *data, UINT size, bool secure);
+UINT Recv(SOCK *sock, void *data, UINT size, bool secure);
+UINT Peek(SOCK *sock, void *data, UINT size);
+void SetNoNeedToRead(SOCK *sock);
+UINT SecureSend(SOCK *sock, void *data, UINT size);
+UINT SecureRecv(SOCK *sock, void *data, UINT size);
+bool StartSSL(SOCK *sock, X *x, K *priv);
+bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls, UINT ssl_timeout, char *sni_hostname);
+bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x);
+void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx);
+bool SendAll(SOCK *sock, void *data, UINT size, bool secure);
+void SendAdd(SOCK *sock, void *data, UINT size);
+bool SendNow(SOCK *sock, int secure);
+bool RecvAll(SOCK *sock, void *data, UINT size, bool secure);
+bool RecvAllEx(SOCK *sock, void **data_new_ptr, UINT size, bool secure);
+void InitSockSet(SOCKSET *set);
+void AddSockSet(SOCKSET *set, SOCK *sock);
+CANCEL *NewCancel();
+CANCEL *NewCancelSpecial(void *hEvent);
+void ReleaseCancel(CANCEL *c);
+void CleanupCancel(CANCEL *c);
+void Cancel(CANCEL *c);
+void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void SetWantToUseCipher(SOCK *sock, char *name);
+void InitAsyncSocket(SOCK *sock);
+SOCK *NewUDP(UINT port);
+SOCK *NewUDPEx(UINT port, bool ipv6);
+SOCK *NewUDPEx2(UINT port, bool ipv6, IP *ip);
+SOCK *NewUDPEx3(UINT port, IP *ip);
+SOCK *NewUDP4(UINT port, IP *ip);
+SOCK *NewUDP6(UINT port, IP *ip);
+SOCK *NewUDPEx2Rand(bool ipv6, IP *ip, void *rand_seed, UINT rand_seed_size, UINT num_retry);
+SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR rand_port_id);
+UINT NewRandPortByMachineAndExePath(UINT start_port, UINT end_port, UINT additional_int);
+void DisableUDPChecksum(SOCK *s);
+UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size);
+UINT SendToEx(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast);
+UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size);
+UINT SendTo6Ex(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast);
+UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size);
+UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size);
+void SetTimeout(SOCK *sock, UINT timeout);
+UINT GetTimeout(SOCK *sock);
+bool CheckTCPPort(char *hostname, UINT port);
+bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout);
+void CheckTCPPortThread(THREAD *thread, void *param);
+ROUTE_TABLE *GetRouteTable();
+void FreeRouteTable(ROUTE_TABLE *t);
+bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists);
+bool AddRouteEntry(ROUTE_ENTRY *e);
+void DeleteRouteEntry(ROUTE_ENTRY *e);
+char **EnumVLan(char *tag_name);
+void FreeEnumVLan(char **s);
+UINT GetVLanInterfaceID(char *tag_name);
+ROUTE_ENTRY *GetBestRouteEntry(IP *ip);
+ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id);
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip);
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id);
+void FreeRouteEntry(ROUTE_ENTRY *e);
+void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+SOCK_EVENT *NewSockEvent();
+void SetSockEvent(SOCK_EVENT *event);
+void CleanupSockEvent(SOCK_EVENT *event);
+bool WaitSockEvent(SOCK_EVENT *event, UINT timeout);
+void ReleaseSockEvent(SOCK_EVENT *event);
+void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4);
+UINT SetIP32(UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4);
+bool GetDefaultDns(IP *ip);
+bool GetDomainName(char *name, UINT size);
+bool UnixGetDomainName(char *name, UINT size);
+void RenewDhcp();
+void AcceptInit(SOCK *s);
+bool CheckCipherListName(char *name);
+TOKEN_LIST *GetCipherList();
+COUNTER *GetNumTcpConnectionsCounter();
+void InitWaitThread();
+void FreeWaitThread();
+void AddWaitThread(THREAD *t);
+void DelWaitThread(THREAD *t);
+void InitHostCache();
+void FreeHostCache();
+int CompareHostCache(void *p1, void *p2);
+void AddHostCache(IP *ip, char *hostname);
+bool GetHostCache(char *hostname, UINT size, IP *ip);
+bool IsSubnetMask(IP *ip);
+bool IsSubnetMask4(IP *ip);
+bool IsSubnetMask32(UINT ip);
+bool IsNetworkAddress(IP *ip, IP *mask);
+bool IsNetworkAddress4(IP *ip, IP *mask);
+bool IsNetworkAddress32(UINT ip, UINT mask);
+bool IsHostIPAddress4(IP *ip);
+bool IsHostIPAddress32(UINT ip);
+bool IsZeroIp(IP *ip);
+bool IsZeroIP(IP *ip);
+bool IsZeroIP6Addr(IPV6_ADDR *addr);
+UINT IntToSubnetMask32(UINT i);
+void IntToSubnetMask4(IP *ip, UINT i);
+bool GetNetBiosName(char *name, UINT size, IP *ip);
+bool NormalizeMacAddress(char *dst, UINT size, char *src);
+SOCKLIST *NewSockList();
+void AddSockList(SOCKLIST *sl, SOCK *s);
+void DelSockList(SOCKLIST *sl, SOCK *s);
+void StopSockList(SOCKLIST *sl);
+void FreeSockList(SOCKLIST *sl);
+bool IsIPv6Supported();
+void SetSockTos(SOCK *s, int tos);
+void SetSockHighPriority(SOCK *s, bool flag);
+void InitIpClientList();
+void FreeIpClientList();
+int CompareIpClientList(void *p1, void *p2);
+void AddIpClient(IP *ip);
+void DelIpClient(IP *ip);
+IP_CLIENT *SearchIpClient(IP *ip);
+UINT GetNumIpClient(IP *ip);
+void SetLinuxArpFilter();
+LIST *GetTcpTableList();
+void FreeTcpTableList(LIST *o);
+int CompareTcpTable(void *p1, void *p2);
+void PrintTcpTableList(LIST *o);
+TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port);
+UINT GetTcpProcessIdFromSocket(SOCK *s);
+UINT GetTcpProcessIdFromSocketReverse(SOCK *s);
+bool CanGetTcpProcessId();
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag);
+void EnableNetworkNameCache();
+void DisableNetworkNameCache();
+bool IsNetworkNameCacheEnabled();
+ROUTE_CHANGE *NewRouteChange();
+void FreeRouteChange(ROUTE_CHANGE *r);
+bool IsRouteChanged(ROUTE_CHANGE *r);
+void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e);
+void DebugPrintRoute(ROUTE_ENTRY *e);
+void DebugPrintRouteTable(ROUTE_TABLE *r);
+bool IsIPv6LocalNetworkAddress(IP *ip);
+
+void SocketTimeoutThread(THREAD *t, void *param);
+SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock);
+void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp);
+
+void CopyIP(IP *dst, IP *src);
+bool CheckSubnetLength6(UINT i);
+bool IsIP6(IP *ip);
+bool IsIP4(IP *ip);
+bool IsSameIPVer(IP *ip1, IP *ip2);
+void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr);
+bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip);
+void SetIP6(IP *ip, UCHAR *value);
+void GetLocalHostIP6(IP *ip);
+void GetLocalHostIP4(IP *ip);
+bool IsLocalHostIP6(IP *ip);
+bool IsLocalHostIP4(IP *ip);
+bool IsLocalHostIP(IP *ip);
+void ZeroIP6(IP *ip);
+void ZeroIP4(IP *ip);
+bool CheckIPItemStr6(char *str);
+void IPItemStrToChars6(UCHAR *chars, char *str);
+bool StrToIP6(IP *ip, char *str);
+bool StrToIP6Addr(IPV6_ADDR *ip, char *str);
+void IPToStr6(char *str, UINT size, IP *ip);
+void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr);
+void IPToStr6Array(char *str, UINT size, UCHAR *bytes);
+void IPToStr6Inner(char *str, IP *ip);
+void IntToSubnetMask6(IP *ip, UINT i);
+void IPNot6(IP *dst, IP *a);
+void IPOr6(IP *dst, IP *a, IP *b);
+void IPAnd6(IP *dst, IP *a, IP *b);
+void GetAllRouterMulticastAddress6(IP *ip);
+void GetAllNodeMulticaseAddress6(IP *ip);
+void GetLoopbackAddress6(IP *ip);
+void GetAllFilledAddress6(IP *ip);
+UINT GetIPAddrType6(IP *ip);
+UINT GetIPv6AddrType(IPV6_ADDR *addr);
+void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip);
+void GetSoliciationMulticastAddr6(IP *dst, IP *src);
+bool CheckUnicastAddress(IP *ip);
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet);
+bool IsNetworkAddress6(IP *ip, IP *subnet);
+void GetHostAddress6(IP *dst, IP *ip, IP *subnet);
+void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet);
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet);
+bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet);
+bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet);
+void GenerateEui64Address6(UCHAR *dst, UCHAR *mac);
+void GenerateEui64LocalAddress(IP *a, UCHAR *mac);
+void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac);
+bool IsSubnetMask6(IP *a);
+UINT SubnetMaskToInt(IP *a);
+UINT SubnetMaskToInt6(IP *a);
+UINT SubnetMaskToInt4(IP *a);
+bool IsStrIPv6Address(char *str);
+void IPNot4(IP *dst, IP *a);
+void IPOr4(IP *dst, IP *a, IP *b);
+void IPAnd4(IP *dst, IP *a, IP *b);
+bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet);
+
+bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask);
+bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask);
+bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask);
+bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask);
+bool ParseIpAndMask6(char *src, IP *ip, IP *mask);
+bool ParseIpAndMask46(char *src, IP *ip, IP *mask);
+bool IsIpStr4(char *str);
+bool IsIpStr6(char *str);
+bool IsIpMask6(char *str);
+bool IsIpStr46(char *str);
+bool StrToMask4(IP *mask, char *str);
+bool StrToMask6(IP *mask, char *str);
+bool StrToMask6Addr(IPV6_ADDR *mask, char *str);
+bool StrToMask46(IP *mask, char *str, bool ipv6);
+void MaskToStr(char *str, UINT size, IP *mask);
+void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address);
+void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask);
+void MaskToStr32(char *str, UINT size, UINT mask);
+void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address);
+void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address);
+
+TUBEDATA *NewTubeData(void *data, UINT size, void *header, UINT header_size);
+void FreeTubeData(TUBEDATA *d);
+TUBE *NewTube(UINT size_of_header);
+void ReleaseTube(TUBE *t);
+void CleanupTube(TUBE *t);
+bool TubeSend(TUBE *t, void *data, UINT size, void *header);
+bool TubeSendEx(TUBE *t, void *data, UINT size, void *header, bool no_flush);
+bool TubeSendEx2(TUBE *t, void *data, UINT size, void *header, bool no_flush, UINT max_num_in_queue);
+void TubeFlush(TUBE *t);
+void TubeFlushEx(TUBE *t, bool force);
+TUBEDATA *TubeRecvAsync(TUBE *t);
+TUBEDATA *TubeRecvSync(TUBE *t, UINT timeout);
+TUBEPAIR_DATA *NewTubePairData();
+void ReleaseTubePairData(TUBEPAIR_DATA *d);
+void CleanupTubePairData(TUBEPAIR_DATA *d);
+void NewTubePair(TUBE **t1, TUBE **t2, UINT size_of_header);
+void TubeDisconnect(TUBE *t);
+bool IsTubeConnected(TUBE *t);
+void SetTubeSockEvent(TUBE *t, SOCK_EVENT *e);
+SOCK_EVENT *GetTubeSockEvent(TUBE *t);
+
+TUBE_FLUSH_LIST *NewTubeFlushList();
+void FreeTubeFlushList(TUBE_FLUSH_LIST *f);
+void AddTubeToFlushList(TUBE_FLUSH_LIST *f, TUBE *t);
+void FlushTubeFlushList(TUBE_FLUSH_LIST *f);
+
+LIST *GetHostIPAddressListInternal();
+LIST *GetHostIPAddressList();
+LIST *CloneIPAddressList(LIST *o);
+bool IsMyIPAddress(IP *ip);
+void FreeHostIPAddressList(LIST *o);
+void AddHostIPAddressToList(LIST *o, IP *ip);
+int CmpIpAddressList(void *p1, void *p2);
+
+UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param);
+void UdpListenerThread(THREAD *thread, void *param);
+void UdpListenerGetPublicPortList(UDPLISTENER *u, char *dst, UINT size);
+void FreeUdpListener(UDPLISTENER *u);
+void AddPortToUdpListener(UDPLISTENER *u, UINT port);
+void DeletePortFromUdpListener(UDPLISTENER *u, UINT port);
+void DeleteAllPortFromUdpListener(UDPLISTENER *u);
+UINT GetUdpListenerPortList(UDPLISTENER *u, UINT **port_list);
+void UdpListenerSendPackets(UDPLISTENER *u, LIST *packet_list);
+void UdpListenerSendPacket(UDPLISTENER *u, UDPPACKET *packet);
+UDPPACKET *NewUdpPacket(IP *src_ip, UINT src_port, IP *dst_ip, UINT dst_port, void *data, UINT size);
+void FreeUdpPacket(UDPPACKET *p);
+UDPLISTENER_SOCK *DetermineUdpSocketForSending(UDPLISTENER *u, UDPPACKET *p);
+bool IsUdpPortOpened(UDPLISTENER *u, IP *server_ip, UINT port);
+
+INTERRUPT_MANAGER *NewInterruptManager();
+void FreeInterruptManager(INTERRUPT_MANAGER *m);
+void AddInterrupt(INTERRUPT_MANAGER *m, UINT64 tick);
+UINT GetNextIntervalForInterrupt(INTERRUPT_MANAGER *m);
+
+void NewSocketPair(SOCK **client, SOCK **server, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+SOCK *NewInProcSocket(TUBE *tube_send, TUBE *tube_recv);
+SOCK *ListenInProc();
+SOCK *AcceptInProc(SOCK *s);
+SOCK *ConnectInProc(SOCK *listen_sock, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+UINT SendInProc(SOCK *sock, void *data, UINT size);
+UINT RecvInProc(SOCK *sock, void *data, UINT size);
+void WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+
+SOCK *ListenReverse();
+SOCK *AcceptReverse(SOCK *s);
+void InjectNewReverseSocketToAccept(SOCK *listen_sock, SOCK *s, IP *client_ip, UINT client_port);
+
+bool NewTcpPair(SOCK **s1, SOCK **s2);
+SOCK *ListenAnyPortEx(bool local_only);
+SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca);
+
+bool IsIcmpApiSupported();
+ICMP_RESULT *IcmpApiEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+void IcmpApiFreeResult(ICMP_RESULT *ret);
+
+#ifdef OS_WIN32
+void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+#else // OS_WIN32
+void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+#endif // OS_WIN32
+
+SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh);
+void FreeSslPipe(SSL_PIPE *s);
+bool SyncSslPipe(SSL_PIPE *s);
+
+SSL_BIO *NewSslBioMem();
+SSL_BIO *NewSslBioSsl();
+void FreeSslBio(SSL_BIO *b);
+bool SslBioSync(SSL_BIO *b, bool sync_send, bool sync_recv);
+
+void SetCurrentGlobalIP(IP *ip, bool ipv6);
+bool GetCurrentGlobalIP(IP *ip, bool ipv6);
+void GetCurrentGlobalIPGuess(IP *ip, bool ipv6);
+
+bool IsIPPrivate(IP *ip);
+bool IsIPMyHost(IP *ip);
+void LoadPrivateIPFile();
+bool IsOnPrivateIPFile(UINT ip);
+void FreePrivateIPFile();
+
+LIST *GetNicList();
+void FreeNicList(LIST *o);
+bool IsMacAddressLocal(void *addr);
+bool IsMacAddressLocalInner(LIST *o, void *addr);
+bool IsMacAddressLocalFast(void *addr);
+void RefreshLocalMacAddressList();
+
+struct ssl_ctx_st *NewSSLCtx();
+void FreeSSLCtx(struct ssl_ctx_st *ctx);
+
+void SetCurrentDDnsFqdn(char *name);
+void GetCurrentDDnsFqdn(char *name, UINT size);
+UINT GetCurrentDDnsFqdnHash();
+
+void GetSimpleHostname(char *hostname, UINT hostname_size, char *fqdn);
+
+void DisableRDUPServerGlobally();
+void DisableRUDPRegisterGlobally();
+void SetNatTLowPriority();
+
+void QueryIpThreadMain(THREAD *thread, void *param);
+QUERYIPTHREAD *NewQueryIpThread(char *hostname, UINT interval_last_ok, UINT interval_last_ng);
+bool GetQueryIpThreadResult(QUERYIPTHREAD *t, IP *ip);
+void FreeQueryIpThread(QUERYIPTHREAD *t);
+
+
+bool IsIpInStrList(IP *ip, char *ip_list);
+bool IsInStrByStrList(char *str, char *str_list);
+
+#ifdef OS_WIN32
+LIST *Win32GetNicList();
+#endif // OS_WIN32
+
+
+void InitDynList();
+void FreeDynList();
+void AddDynList(BUF *b);
+void ExtractAndApplyDynList(PACK *p);
+void SetDynListValue(char *name, UINT64 value);
+UINT64 GetDynValue(char *name);
+UINT64 GetDynValueOrDefault(char *name, UINT64 default_value, UINT64 min_value, UINT64 max_value);
+UINT64 GetDynValueOrDefaultSafe(char *name, UINT64 default_value);
+
+
+#endif // NETWORK_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/OS.c b/src/Mayaqua/OS.c
new file mode 100644
index 00000000..66042798
--- /dev/null
+++ b/src/Mayaqua/OS.c
@@ -0,0 +1,527 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// OS.c
+// Operating system dependent code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+#undef Lock
+#undef Unlock
+
+// Dispatch table
+static OS_DISPATCH_TABLE *os = NULL;
+
+// Convert OS type to a string
+char *OsTypeToStr(UINT type)
+{
+ switch (type)
+ {
+ case 0:
+ return "Unsupported OS by SoftEther VPN\0\n";
+ case OSTYPE_WINDOWS_95:
+ return "Windows 95\0\n";
+ case OSTYPE_WINDOWS_98:
+ return "Windows 98\0\n";
+ case OSTYPE_WINDOWS_ME:
+ return "Windows Millennium Edition\0\n";
+ case OSTYPE_WINDOWS_UNKNOWN:
+ return "Windows 9x Unknown Version\0\n";
+ case OSTYPE_WINDOWS_NT_4_WORKSTATION:
+ return "Windows NT 4.0 Workstation\0\n";
+ case OSTYPE_WINDOWS_NT_4_SERVER:
+ return "Windows NT 4.0 Server\0\n";
+ case OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE:
+ return "Windows NT 4.0 Server, Enterprise Edition\0\n";
+ case OSTYPE_WINDOWS_NT_4_BACKOFFICE:
+ return "BackOffice Server 4.5\0\n";
+ case OSTYPE_WINDOWS_NT_4_SMS:
+ return "Small Business Server 4.5\0\n";
+ case OSTYPE_WINDOWS_2000_PROFESSIONAL:
+ return "Windows 2000 Professional\0\n";
+ case OSTYPE_WINDOWS_2000_SERVER:
+ return "Windows 2000 Server\0\n";
+ case OSTYPE_WINDOWS_2000_ADVANCED_SERVER:
+ return "Windows 2000 Advanced Server\0\n";
+ case OSTYPE_WINDOWS_2000_DATACENTER_SERVER:
+ return "Windows 2000 Datacenter Server\0\n";
+ case OSTYPE_WINDOWS_2000_BACKOFFICE:
+ return "BackOffice Server 2000\0\n";
+ case OSTYPE_WINDOWS_2000_SBS:
+ return "Small Business Server 2000\0\n";
+ case OSTYPE_WINDOWS_XP_HOME:
+ return "Windows XP Home Edition\0\n";
+ case OSTYPE_WINDOWS_XP_PROFESSIONAL:
+ return "Windows XP Professional\0\n";
+ case OSTYPE_WINDOWS_2003_WEB:
+ return "Windows Server 2003 Web Edition\0\n";
+ case OSTYPE_WINDOWS_2003_STANDARD:
+ return "Windows Server 2003 Standard Edition\0\n";
+ case OSTYPE_WINDOWS_2003_ENTERPRISE:
+ return "Windows Server 2003 Enterprise Edition\0\n";
+ case OSTYPE_WINDOWS_2003_DATACENTER:
+ return "Windows Server 2003 Datacenter Edition\0\n";
+ case OSTYPE_WINDOWS_2003_BACKOFFICE:
+ return "BackOffice Server 2003\0\n";
+ case OSTYPE_WINDOWS_2003_SBS:
+ return "Small Business Server 2003\0\n";
+ case OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL:
+ return "Windows Vista\0\n";
+ case OSTYPE_WINDOWS_LONGHORN_SERVER:
+ return "Windows Server 2008\0\n";
+ case OSTYPE_WINDOWS_7:
+ return "Windows 7\0\n";
+ case OSTYPE_WINDOWS_SERVER_2008_R2:
+ return "Windows Server 2008 R2\0\n";
+ case OSTYPE_WINDOWS_8:
+ return "Windows 8\0\n";
+ case OSTYPE_WINDOWS_SERVER_8:
+ return "Windows Server 2012\0\n";
+ case OSTYPE_WINDOWS_81:
+ return "Windows 8.1\0\n";
+ case OSTYPE_WINDOWS_SERVER_81:
+ return "Windows Server 2012 R2\0\n";
+ case OSTYPE_WINDOWS_9:
+ return "Windows 8.2 or later\0\n";
+ case OSTYPE_WINDOWS_SERVER_9:
+ return "Windows Server 8.2 or later\0\n";
+ case OSTYPE_UNIX_UNKNOWN:
+ return "UNIX System\0\n";
+ case OSTYPE_LINUX:
+ return "Linux\0\n";
+ case OSTYPE_SOLARIS:
+ return "Sun Solaris\0\n";
+ case OSTYPE_CYGWIN:
+ return "Gnu Cygwin\0\n";
+ case OSTYPE_BSD:
+ return "BSD System\0\n";
+ case OSTYPE_MACOS_X:
+ return "Mac OS X\0\n";
+ }
+
+ return "Unknown OS";
+}
+
+// Initialization
+void OSInit()
+{
+ // Get the dispatch table
+#ifdef OS_WIN32
+ os = Win32GetDispatchTable();
+#else // OS_WIN32
+ os = UnixGetDispatchTable();
+#endif // OS_WIN32
+
+ // Calling the OS-specific initialization function
+ os->Init();
+}
+
+// Release
+void OSFree()
+{
+ os->Free();
+}
+
+// Get the memory information
+void OSGetMemInfo(MEMINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ os->GetMemInfo(info);
+}
+
+// Yield
+void OSYield()
+{
+ os->Yield();
+}
+
+// Start a Single instance
+void *OSNewSingleInstance(char *instance_name)
+{
+ return os->NewSingleInstance(instance_name);
+}
+
+void OSFreeSingleInstance(void *data)
+{
+ os->FreeSingleInstance(data);
+}
+
+// Raise the priority
+void OSSetHighPriority()
+{
+ os->SetHighPriority();
+}
+
+// Restore the priority
+void OSRestorePriority()
+{
+ os->RestorePriority();
+}
+
+// Get the product ID
+char* OSGetProductId()
+{
+ return os->GetProductId();
+}
+
+// Check whether the OS is supported
+bool OSIsSupportedOs()
+{
+ return os->IsSupportedOs();
+}
+
+// Getting OS information
+void OSGetOsInfo(OS_INFO *info)
+{
+ os->GetOsInfo(info);
+}
+
+// Show an alert
+void OSAlert(char *msg, char *caption)
+{
+ os->Alert(msg, caption);
+}
+void OSAlertW(wchar_t *msg, wchar_t *caption)
+{
+ os->AlertW(msg, caption);
+}
+
+// Run a process
+bool OSRun(char *filename, char *arg, bool hide, bool wait)
+{
+ return os->Run(filename, arg, hide, wait);
+}
+bool OSRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ return os->RunW(filename, arg, hide, wait);
+}
+
+// Get the Thread ID
+UINT OSThreadId()
+{
+ return os->ThreadId();
+}
+
+// Rename
+bool OSFileRename(char *old_name, char *new_name)
+{
+ return os->FileRename(old_name, new_name);
+}
+bool OSFileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ return os->FileRenameW(old_name, new_name);
+}
+
+// Get the file size
+UINT64 OSFileSize(void *pData)
+{
+ return os->FileSize(pData);
+}
+
+// Seek the file
+bool OSFileSeek(void *pData, UINT mode, int offset)
+{
+ return os->FileSeek(pData, mode, offset);
+}
+
+// Delete the file
+bool OSFileDelete(char *name)
+{
+ return os->FileDelete(name);
+}
+bool OSFileDeleteW(wchar_t *name)
+{
+ return os->FileDeleteW(name);
+}
+
+// Create a directory
+bool OSMakeDir(char *name)
+{
+ return os->MakeDir(name);
+}
+bool OSMakeDirW(wchar_t *name)
+{
+ return os->MakeDirW(name);
+}
+
+// Delete the directory
+bool OSDeleteDir(char *name)
+{
+ return os->DeleteDir(name);
+}
+bool OSDeleteDirW(wchar_t *name)
+{
+ return os->DeleteDirW(name);
+}
+
+// Open the file
+void *OSFileOpen(char *name, bool write_mode, bool read_lock)
+{
+ return os->FileOpen(name, write_mode, read_lock);
+}
+void *OSFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ return os->FileOpenW(name, write_mode, read_lock);
+}
+
+// Create a file
+void *OSFileCreate(char *name)
+{
+ return os->FileCreate(name);
+}
+void *OSFileCreateW(wchar_t *name)
+{
+ return os->FileCreateW(name);
+}
+
+// Write to a file
+bool OSFileWrite(void *pData, void *buf, UINT size)
+{
+ return os->FileWrite(pData, buf, size);
+}
+
+// Read from a file
+bool OSFileRead(void *pData, void *buf, UINT size)
+{
+ return os->FileRead(pData, buf, size);
+}
+
+// Close the file
+void OSFileClose(void *pData, bool no_flush)
+{
+ os->FileClose(pData, no_flush);
+}
+
+// Flush to the file
+void OSFileFlush(void *pData)
+{
+ os->FileFlush(pData);
+}
+
+// Get the call stack
+CALLSTACK_DATA *OSGetCallStack()
+{
+ return os->GetCallStack();
+}
+
+// Get the symbol information
+bool OSGetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ return os->GetCallStackSymbolInfo(s);
+}
+
+// Wait for the termination of the thread
+bool OSWaitThread(THREAD *t)
+{
+ return os->WaitThread(t);
+}
+
+// Release of thread
+void OSFreeThread(THREAD *t)
+{
+ os->FreeThread(t);
+}
+
+// Thread initialization
+bool OSInitThread(THREAD *t)
+{
+ return os->InitThread(t);
+}
+
+// Memory allocation
+void *OSMemoryAlloc(UINT size)
+{
+ return os->MemoryAlloc(size);
+}
+
+// Memory reallocation
+void *OSMemoryReAlloc(void *addr, UINT size)
+{
+ return os->MemoryReAlloc(addr, size);
+}
+
+// Memory release
+void OSMemoryFree(void *addr)
+{
+ os->MemoryFree(addr);
+}
+
+// Get the system timer
+UINT OSGetTick()
+{
+ return os->GetTick();
+}
+
+// Get the System Time
+void OSGetSystemTime(SYSTEMTIME *system_time)
+{
+ os->GetSystemTime(system_time);
+}
+
+// 32bit increment
+void OSInc32(UINT *value)
+{
+ os->Inc32(value);
+}
+
+// 32bit decrement
+void OSDec32(UINT *value)
+{
+ os->Dec32(value);
+}
+
+// Sleep the thread
+void OSSleep(UINT time)
+{
+ os->Sleep(time);
+}
+
+// Create a Lock
+LOCK *OSNewLock()
+{
+ return os->NewLock();
+}
+
+// Lock
+bool OSLock(LOCK *lock)
+{
+ return os->Lock(lock);
+}
+
+// Unlock
+void OSUnlock(LOCK *lock)
+{
+ os->Unlock(lock);
+}
+
+// Delete the lock
+void OSDeleteLock(LOCK *lock)
+{
+ os->DeleteLock(lock);
+}
+
+// Event initialization
+void OSInitEvent(EVENT *event)
+{
+ os->InitEvent(event);
+}
+
+// Set event
+void OSSetEvent(EVENT *event)
+{
+ os->SetEvent(event);
+}
+
+// Reset event
+void OSResetEvent(EVENT *event)
+{
+ os->ResetEvent(event);
+}
+
+// Wait for event
+bool OSWaitEvent(EVENT *event, UINT timeout)
+{
+ return os->WaitEvent(event, timeout);
+}
+
+// Release of the event
+void OSFreeEvent(EVENT *event)
+{
+ os->FreeEvent(event);
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/OS.h b/src/Mayaqua/OS.h
new file mode 100644
index 00000000..0dc0a31e
--- /dev/null
+++ b/src/Mayaqua/OS.h
@@ -0,0 +1,220 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// OS.h
+// Header of OS.c
+
+#ifndef OS_H
+#define OS_H
+
+// Function prototype
+char *OsTypeToStr(UINT type);
+
+void OSInit();
+void OSFree();
+void *OSMemoryAlloc(UINT size);
+void *OSMemoryReAlloc(void *addr, UINT size);
+void OSMemoryFree(void *addr);
+UINT OSGetTick();
+void OSGetSystemTime(SYSTEMTIME *system_time);
+void OSInc32(UINT *value);
+void OSDec32(UINT *value);
+void OSSleep(UINT time);
+LOCK *OSNewLock();
+bool OSLock(LOCK *lock);
+void OSUnlock(LOCK *lock);
+void OSDeleteLock(LOCK *lock);
+void OSInitEvent(EVENT *event);
+void OSSetEvent(EVENT *event);
+void OSResetEvent(EVENT *event);
+bool OSWaitEvent(EVENT *event, UINT timeout);
+void OSFreeEvent(EVENT *event);
+bool OSWaitThread(THREAD *t);
+void OSFreeThread(THREAD *t);
+bool OSInitThread(THREAD *t);
+void *OSFileOpen(char *name, bool write_mode, bool read_lock);
+void *OSFileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *OSFileCreate(char *name);
+void *OSFileCreateW(wchar_t *name);
+bool OSFileWrite(void *pData, void *buf, UINT size);
+bool OSFileRead(void *pData, void *buf, UINT size);
+void OSFileClose(void *pData, bool no_flush);
+void OSFileFlush(void *pData);
+UINT64 OSFileSize(void *pData);
+bool OSFileSeek(void *pData, UINT mode, int offset);
+bool OSFileDelete(char *name);
+bool OSFileDeleteW(wchar_t *name);
+bool OSMakeDir(char *name);
+bool OSMakeDirW(wchar_t *name);
+bool OSDeleteDir(char *name);
+bool OSDeleteDirW(wchar_t *name);
+CALLSTACK_DATA *OSGetCallStack();
+bool OSGetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool OSFileRename(char *old_name, char *new_name);
+bool OSFileRenameW(wchar_t *old_name, wchar_t *new_name);
+UINT OSThreadId();
+bool OSRun(char *filename, char *arg, bool hide, bool wait);
+bool OSRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+bool OSIsSupportedOs();
+void OSGetOsInfo(OS_INFO *info);
+void OSAlert(char *msg, char *caption);
+void OSAlertW(wchar_t *msg, wchar_t *caption);
+char* OSGetProductId();
+void OSSetHighPriority();
+void OSRestorePriority();
+void *OSNewSingleInstance(char *instance_name);
+void OSFreeSingleInstance(void *data);
+void OSGetMemInfo(MEMINFO *info);
+void OSYield();
+
+// Dispatch table
+typedef struct OS_DISPATCH_TABLE
+{
+ void (*Init)();
+ void (*Free)();
+ void *(*MemoryAlloc)(UINT size);
+ void *(*MemoryReAlloc)(void *addr, UINT size);
+ void (*MemoryFree)(void *addr);
+ UINT (*GetTick)();
+ void (*GetSystemTime)(SYSTEMTIME *system_time);
+ void (*Inc32)(UINT *value);
+ void (*Dec32)(UINT *value);
+ void (*Sleep)(UINT time);
+ LOCK *(*NewLock)();
+ bool (*Lock)(LOCK *lock);
+ void (*Unlock)(LOCK *lock);
+ void (*DeleteLock)(LOCK *lock);
+ void (*InitEvent)(EVENT *event);
+ void (*SetEvent)(EVENT *event);
+ void (*ResetEvent)(EVENT *event);
+ bool (*WaitEvent)(EVENT *event, UINT timeout);
+ void (*FreeEvent)(EVENT *event);
+ bool (*WaitThread)(THREAD *t);
+ void (*FreeThread)(THREAD *t);
+ bool (*InitThread)(THREAD *t);
+ UINT (*ThreadId)();
+ void *(*FileOpen)(char *name, bool write_mode, bool read_lock);
+ void *(*FileOpenW)(wchar_t *name, bool write_mode, bool read_lock);
+ void *(*FileCreate)(char *name);
+ void *(*FileCreateW)(wchar_t *name);
+ bool (*FileWrite)(void *pData, void *buf, UINT size);
+ bool (*FileRead)(void *pData, void *buf, UINT size);
+ void (*FileClose)(void *pData, bool no_flush);
+ void (*FileFlush)(void *pData);
+ UINT64 (*FileSize)(void *pData);
+ bool (*FileSeek)(void *pData, UINT mode, int offset);
+ bool (*FileDelete)(char *name);
+ bool (*FileDeleteW)(wchar_t *name);
+ bool (*MakeDir)(char *name);
+ bool (*MakeDirW)(wchar_t *name);
+ bool (*DeleteDir)(char *name);
+ bool (*DeleteDirW)(wchar_t *name);
+ CALLSTACK_DATA *(*GetCallStack)();
+ bool (*GetCallStackSymbolInfo)(CALLSTACK_DATA *s);
+ bool (*FileRename)(char *old_name, char *new_name);
+ bool (*FileRenameW)(wchar_t *old_name, wchar_t *new_name);
+ bool (*Run)(char *filename, char *arg, bool hide, bool wait);
+ bool (*RunW)(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+ bool (*IsSupportedOs)();
+ void (*GetOsInfo)(OS_INFO *info);
+ void (*Alert)(char *msg, char *caption);
+ void (*AlertW)(wchar_t *msg, wchar_t *caption);
+ char *(*GetProductId)();
+ void (*SetHighPriority)();
+ void (*RestorePriority)();
+ void *(*NewSingleInstance)(char *instance_name);
+ void (*FreeSingleInstance)(void *data);
+ void (*GetMemInfo)(MEMINFO *info);
+ void (*Yield)();
+} OS_DISPATCH_TABLE;
+
+// Include the OS-specific header
+#ifdef OS_WIN32
+#include <Mayaqua/Win32.h>
+#else //OS_WIN32
+#include <Mayaqua/Unix.h>
+#endif // OS_WIN32
+
+#endif // OS_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Object.c b/src/Mayaqua/Object.c
new file mode 100644
index 00000000..b4a7bc0b
--- /dev/null
+++ b/src/Mayaqua/Object.c
@@ -0,0 +1,596 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Object.c
+// Object management code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Thread to try to lock
+void CheckDeadLockThread(THREAD *t, void *param)
+{
+ DEADCHECK *c = (DEADCHECK *)param;
+
+ if (t == NULL || c == NULL)
+ {
+ return;
+ }
+
+ NoticeThreadInit(t);
+
+ Lock(c->Lock);
+ Unlock(c->Lock);
+ c->Unlocked = true;
+}
+
+// Deadlock Detection
+void CheckDeadLock(LOCK *lock, UINT timeout, char *name)
+{
+ DEADCHECK c;
+ THREAD *t;
+ char msg[MAX_PATH];
+
+ if (lock == NULL)
+ {
+ return;
+ }
+ if (name == NULL)
+ {
+ name = "Unknown";
+ }
+
+ Format(msg, sizeof(msg), "error: CheckDeadLock() Failed: %s\n", name);
+
+ Zero(&c, sizeof(c));
+ c.Lock = lock;
+ c.Timeout = timeout;
+ c.Unlocked = false;
+
+ t = NewThread(CheckDeadLockThread, &c);
+ WaitThreadInit(t);
+ if (WaitThread(t, timeout) == false)
+ {
+ if (c.Unlocked == false)
+ {
+ // Deadlock occured
+ AbortExitEx(msg);
+ }
+ else
+ {
+ WaitThread(t, INFINITE);
+ }
+ }
+
+ ReleaseThread(t);
+}
+
+// Create a lock object
+LOCK *NewLockMain()
+{
+ LOCK *lock;
+ UINT retry = 0;
+
+ while (true)
+ {
+ if ((retry++) > OBJECT_ALLOC__MAX_RETRY)
+ {
+ AbortExitEx("error: OSNewLock() failed.\n\n");
+ }
+ lock = OSNewLock();
+ if (lock != NULL)
+ {
+ break;
+ }
+ SleepThread(OBJECT_ALLOC_FAIL_SLEEP_TIME);
+ }
+
+ return lock;
+}
+LOCK *NewLock()
+{
+ LOCK *lock = NewLockMain();
+
+ // KS
+ KS_INC(KS_NEWLOCK_COUNT);
+ KS_INC(KS_CURRENT_LOCK_COUNT);
+
+ return lock;
+}
+
+// Delete the lock object
+void DeleteLock(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_DELETELOCK_COUNT);
+ KS_DEC(KS_CURRENT_LOCK_COUNT);
+
+ OSDeleteLock(lock);
+}
+
+// Lock
+bool LockInner(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_LOCK_COUNT);
+ KS_INC(KS_CURRENT_LOCKED_COUNT);
+
+ return OSLock(lock);
+}
+
+// Unlock
+void UnlockInner(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_UNLOCK_COUNT);
+ KS_DEC(KS_CURRENT_LOCKED_COUNT);
+
+ OSUnlock(lock);
+}
+
+// Creating a counter
+COUNTER *NewCounter()
+{
+ COUNTER *c;
+
+ // Memory allocation
+ c = Malloc(sizeof(COUNTER));
+
+ // Initialization
+ c->Ready = true;
+ c->c = 0;
+
+ // Lock created
+ c->lock = NewLock();
+
+ // KS
+ KS_INC(KS_NEW_COUNTER_COUNT);
+
+ return c;
+}
+
+// Delete the counter
+void DeleteCounter(COUNTER *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_DELETE_COUNTER_COUNT);
+ KS_SUB(KS_CURRENT_COUNT, c->c);
+
+ DeleteLock(c->lock);
+ Free(c);
+}
+
+// Get the count value
+UINT Count(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = c->c;
+ }
+ }
+ Unlock(c->lock);
+
+ return ret;
+}
+
+// Increment
+UINT Inc(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ c->c++;
+ ret = c->c;
+ }
+ }
+ Unlock(c->lock);
+
+ // KS
+ KS_INC(KS_INC_COUNT);
+ KS_INC(KS_CURRENT_COUNT);
+
+ return ret;
+}
+
+// Decrement
+UINT Dec(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ if (c->c != 0)
+ {
+ c->c--;
+ ret = c->c;
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+ }
+ Unlock(c->lock);
+
+ // KS
+ KS_INC(KS_DEC_COUNT);
+ KS_DEC(KS_CURRENT_COUNT);
+
+ return ret;
+}
+
+
+// Release of the reference counter
+UINT Release(REF *ref)
+{
+ UINT c;
+ // Validate arguments
+ if (ref == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_RELEASE_COUNT);
+ KS_DEC(KS_CURRENT_REFED_COUNT);
+
+ c = Dec(ref->c);
+ if (c == 0)
+ {
+ // KS
+ KS_DEC(KS_CURRENT_REF_COUNT);
+ KS_INC(KS_FREEREF_COUNT);
+
+ DeleteCounter(ref->c);
+ ref->c = 0;
+ Free(ref);
+ }
+ return c;
+}
+
+// Increase of the reference counter
+UINT AddRef(REF *ref)
+{
+ UINT c;
+ // Validate arguments
+ if (ref == NULL)
+ {
+ return 0;
+ }
+
+ c = Inc(ref->c);
+
+ // KS
+ KS_INC(KS_ADDREF_COUNT);
+ KS_INC(KS_CURRENT_REFED_COUNT);
+
+ return c;
+}
+
+// Create a reference counter
+REF *NewRef()
+{
+ REF *ref;
+
+ // Memory allocation
+ ref = Malloc(sizeof(REF));
+
+ // Create a Counter
+ ref->c = NewCounter();
+
+ // Increment only once
+ Inc(ref->c);
+
+ // KS
+ KS_INC(KS_NEWREF_COUNT);
+ KS_INC(KS_CURRENT_REF_COUNT);
+ KS_INC(KS_ADDREF_COUNT);
+ KS_INC(KS_CURRENT_REFED_COUNT);
+
+ return ref;
+}
+
+// Creating an event object
+EVENT *NewEvent()
+{
+ // Memory allocation
+ EVENT *e = Malloc(sizeof(EVENT));
+
+ // Reference counter
+ e->ref = NewRef();
+
+ // Event initialization
+ OSInitEvent(e);
+
+ // KS
+ KS_INC(KS_NEWEVENT_COUNT);
+
+ return e;
+}
+
+// Release of the event
+void ReleaseEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (Release(e->ref) == 0)
+ {
+ CleanupEvent(e);
+ }
+}
+
+// Delete the event
+void CleanupEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Release event
+ OSFreeEvent(e);
+
+ // Memory release
+ Free(e);
+
+ // KS
+ KS_INC(KS_FREEEVENT_COUNT);
+}
+
+// Set event
+void Set(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ OSSetEvent(e);
+}
+
+// Wait for event
+bool Wait(EVENT *e, UINT timeout)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_WAIT_COUNT);
+
+ return OSWaitEvent(e, timeout);
+}
+
+// Wait for a event until the cancel flag becomes true
+bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel)
+{
+ bool dummy_bool = false;
+ UINT64 start, giveup;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_bool;
+ }
+
+ start = Tick64();
+
+ if (timeout == INFINITE || timeout == 0x7FFFFFFF)
+ {
+ giveup = 0;
+ }
+ else
+ {
+ giveup = start + (UINT64)timeout;
+ }
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval_to_giveup = (UINT)(giveup - now);
+ if (giveup == 0)
+ {
+ interval_to_giveup = INFINITE;
+ }
+ else
+ {
+ if (now >= giveup)
+ {
+ // Time-out occurs
+ return false;
+ }
+ }
+
+ interval_to_giveup = MIN(interval_to_giveup, 25);
+
+ if (*cancel)
+ {
+ // Cancel flag is set to true. Time-out occurs
+ return false;
+ }
+
+ if (e != NULL)
+ {
+ if (Wait(e, interval_to_giveup))
+ {
+ // Event is set
+ return true;
+ }
+ }
+ else
+ {
+ SleepThread(interval_to_giveup);
+ }
+ }
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Object.h b/src/Mayaqua/Object.h
new file mode 100644
index 00000000..d5f90694
--- /dev/null
+++ b/src/Mayaqua/Object.h
@@ -0,0 +1,189 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Object.h
+// Header of Object.c
+
+#ifndef OBJECT_H
+#define OBJECT_H
+
+
+// Constants
+#define OBJECT_ALLOC_FAIL_SLEEP_TIME 150
+#define OBJECT_ALLOC__MAX_RETRY 30
+
+// Lock object
+struct LOCK
+{
+ void *pData;
+ BOOL Ready;
+#ifdef OS_UNIX
+ UINT thread_id;
+ UINT locked_count;
+#endif // OS_UNIX
+#ifdef _DEBUG
+ char *FileName;
+ UINT Line;
+ UINT ThreadId;
+#endif // _DEBUG
+};
+
+// Counter object
+struct COUNTER
+{
+ LOCK *lock;
+ UINT c;
+ bool Ready;
+};
+
+// Reference counter
+struct REF
+{
+ COUNTER *c;
+};
+
+// Event object
+struct EVENT
+{
+ REF *ref;
+ void *pData;
+};
+
+// Deadlock detection
+struct DEADCHECK
+{
+ LOCK *Lock;
+ UINT Timeout;
+ bool Unlocked;
+};
+
+
+// Lock function
+#ifndef _DEBUG
+
+#define Lock(lock) LockInner((lock))
+#define Unlock(lock) UnlockInner((lock))
+
+#else // _DEBUG
+
+#define Lock(lock) \
+ { \
+ LockInner(lock); \
+ if (lock != NULL) { lock->FileName = __FILE__; lock->Line = __LINE__; lock->ThreadId = ThreadId();} \
+ }
+
+#define Unlock(lock) \
+ { \
+ if (lock != NULL) { lock->FileName = NULL; lock->Line = 0; lock->ThreadId = 0;} \
+ UnlockInner(lock); \
+ }
+
+#endif // _DEBUG
+
+
+// Function prototype
+LOCK *NewLock();
+LOCK *NewLockMain();
+void DeleteLock(LOCK *lock);
+COUNTER *NewCounter();
+void UnlockInner(LOCK *lock);
+bool LockInner(LOCK *lock);
+void DeleteCounter(COUNTER *c);
+UINT Count(COUNTER *c);
+UINT Inc(COUNTER *c);
+UINT Dec(COUNTER *c);
+UINT Release(REF *ref);
+UINT AddRef(REF *ref);
+REF *NewRef();
+EVENT *NewEvent();
+void ReleaseEvent(EVENT *e);
+void CleanupEvent(EVENT *e);
+void Set(EVENT *e);
+bool Wait(EVENT *e, UINT timeout);
+bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel);
+void CheckDeadLock(LOCK *lock, UINT timeout, char *name);
+void CheckDeadLockThread(THREAD *t, void *param);
+
+#endif // OBJECT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Pack.c b/src/Mayaqua/Pack.c
new file mode 100644
index 00000000..a72c71a4
--- /dev/null
+++ b/src/Mayaqua/Pack.c
@@ -0,0 +1,1671 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Pack.c
+// Data package code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Get a list of the element names in the PACK
+TOKEN_LIST *GetPackElementNames(PACK *p)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+
+ ret->NumTokens = LIST_NUM(p->elements);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ELEMENT *e = LIST_DATA(p->elements, i);
+
+ ret->Token[i] = CopyStr(e->name);
+ }
+
+ return ret;
+}
+
+// Convert the BUF to a PACK
+PACK *BufToPack(BUF *b)
+{
+ PACK *p;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ if (ReadPack(b, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+
+ return p;
+}
+
+// Convert the PACK to the BUF
+BUF *PackToBuf(PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WritePack(b, p);
+
+ return b;
+}
+
+// Read the PACK
+bool ReadPack(BUF *b, PACK *p)
+{
+ UINT i, num;
+ // Validate arguments
+ if (b == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ // The number of ELEMENTs
+ num = ReadBufInt(b);
+ if (num > MAX_ELEMENT_NUM)
+ {
+ // Number exceeds
+ return false;
+ }
+
+ // Read the ELEMENT
+ for (i = 0;i < num;i++)
+ {
+ ELEMENT *e;
+ e = ReadElement(b);
+ if (AddElement(p, e) == false)
+ {
+ // Adding error
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Write down the PACK
+void WritePack(BUF *b, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // The number of ELEMENTs
+ WriteBufInt(b, LIST_NUM(p->elements));
+
+ // Write the ELEMENT
+ for (i = 0;i < LIST_NUM(p->elements);i++)
+ {
+ ELEMENT *e = LIST_DATA(p->elements, i);
+ WriteElement(b, e);
+ }
+}
+
+// Read the ELEMENT
+ELEMENT *ReadElement(BUF *b)
+{
+ UINT i;
+ char name[MAX_ELEMENT_NAME_LEN + 1];
+ UINT type, num_value;
+ VALUE **values;
+ ELEMENT *e;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Name
+ if (ReadBufStr(b, name, sizeof(name)) == false)
+ {
+ return NULL;
+ }
+
+ // Type of item
+ type = ReadBufInt(b);
+
+ // Number of items
+ num_value = ReadBufInt(b);
+ if (num_value > MAX_VALUE_NUM)
+ {
+ // Number exceeds
+ return NULL;
+ }
+
+ // VALUE
+ values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);
+ for (i = 0;i < num_value;i++)
+ {
+ values[i] = ReadValue(b, type);
+ }
+
+ // Create a ELEMENT
+ e = NewElement(name, type, num_value, values);
+
+ Free(values);
+
+ return e;
+}
+
+// Write the ELEMENT
+void WriteElement(BUF *b, ELEMENT *e)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || e == NULL)
+ {
+ return;
+ }
+
+ // Name
+ WriteBufStr(b, e->name);
+ // Type of item
+ WriteBufInt(b, e->type);
+ // Number of items
+ WriteBufInt(b, e->num_value);
+ // VALUE
+ for (i = 0;i < e->num_value;i++)
+ {
+ VALUE *v = e->values[i];
+ WriteValue(b, v, e->type);
+ }
+}
+
+// Read the VALUE
+VALUE *ReadValue(BUF *b, UINT type)
+{
+ UINT len;
+ BYTE *u;
+ void *data;
+ char *str;
+ wchar_t *unistr;
+ UINT unistr_size;
+ UINT size;
+ UINT u_size;
+ VALUE *v = NULL;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Data item
+ switch (type)
+ {
+ case VALUE_INT: // Integer
+ v = NewIntValue(ReadBufInt(b));
+ break;
+ case VALUE_INT64:
+ v = NewInt64Value(ReadBufInt64(b));
+ break;
+ case VALUE_DATA: // Data
+ size = ReadBufInt(b);
+ if (size > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ data = Malloc(size);
+ if (ReadBuf(b, data, size) != size)
+ {
+ // Read failure
+ Free(data);
+ break;
+ }
+ v = NewDataValue(data, size);
+ Free(data);
+ break;
+ case VALUE_STR: // ANSI string
+ len = ReadBufInt(b);
+ if ((len + 1) > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ str = Malloc(len + 1);
+ // String body
+ if (ReadBuf(b, str, len) != len)
+ {
+ // Read failure
+ Free(str);
+ break;
+ }
+ str[len] = 0;
+ v = NewStrValue(str);
+ Free(str);
+ break;
+ case VALUE_UNISTR: // Unicode string
+ u_size = ReadBufInt(b);
+ if (u_size > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ // Reading an UTF-8 string
+ u = ZeroMalloc(u_size + 1);
+ if (ReadBuf(b, u, u_size) != u_size)
+ {
+ // Read failure
+ Free(u);
+ break;
+ }
+ // Convert to a Unicode string
+ unistr_size = CalcUtf8ToUni(u, u_size);
+ if (unistr_size == 0)
+ {
+ Free(u);
+ break;
+ }
+ unistr = Malloc(unistr_size);
+ Utf8ToUni(unistr, unistr_size, u, u_size);
+ Free(u);
+ v = NewUniStrValue(unistr);
+ Free(unistr);
+ break;
+ }
+
+ return v;
+}
+
+// Write the VALUE
+void WriteValue(BUF *b, VALUE *v, UINT type)
+{
+ UINT len;
+ BYTE *u;
+ UINT u_size;
+ // Validate arguments
+ if (b == NULL || v == NULL)
+ {
+ return;
+ }
+
+ // Data item
+ switch (type)
+ {
+ case VALUE_INT: // Integer
+ WriteBufInt(b, v->IntValue);
+ break;
+ case VALUE_INT64: // 64 bit integer
+ WriteBufInt64(b, v->Int64Value);
+ break;
+ case VALUE_DATA: // Data
+ // Size
+ WriteBufInt(b, v->Size);
+ // Body
+ WriteBuf(b, v->Data, v->Size);
+ break;
+ case VALUE_STR: // ANSI string
+ len = StrLen(v->Str);
+ // Length
+ WriteBufInt(b, len);
+ // String body
+ WriteBuf(b, v->Str, len);
+ break;
+ case VALUE_UNISTR: // Unicode string
+ // Convert to UTF-8
+ u_size = CalcUniToUtf8(v->UniStr) + 1;
+ u = ZeroMalloc(u_size);
+ UniToUtf8(u, u_size, v->UniStr);
+ // Size
+ WriteBufInt(b, u_size);
+ // UTF-8 string body
+ WriteBuf(b, u, u_size);
+ Free(u);
+ break;
+ }
+}
+
+// Get data size
+UINT GetDataValueSize(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (e->values == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->Size;
+}
+
+// Get the data
+void *GetDataValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+ if (e->values == NULL)
+ {
+ return NULL;
+ }
+ if (index >= e->num_value)
+ {
+ return NULL;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->Data;
+}
+
+// Get the Unicode string type
+wchar_t *GetUniStrValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->UniStr;
+}
+
+// Get the ANSI string type
+char *GetStrValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->Str;
+}
+
+// Get the 64 bit integer value
+UINT64 GetInt64Value(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->Int64Value;
+}
+
+// Get the integer value
+UINT GetIntValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->IntValue;
+}
+
+// Function of sort for PACK
+int ComparePackName(void *p1, void *p2)
+{
+ ELEMENT *o1, *o2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(ELEMENT **)p1;
+ o2 = *(ELEMENT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(o1->name, o2->name);
+}
+
+// Delete the VALUE
+void FreeValue(VALUE *v, UINT type)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ switch (type)
+ {
+ case VALUE_INT:
+ case VALUE_INT64:
+ break;
+ case VALUE_DATA:
+ Free(v->Data);
+ break;
+ case VALUE_STR:
+ Free(v->Str);
+ break;
+ case VALUE_UNISTR:
+ Free(v->UniStr);
+ break;
+ }
+
+ // Memory release
+ Free(v);
+}
+
+// Create a VALUE of Unicode String type
+VALUE *NewUniStrValue(wchar_t *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // String copy
+ v->Size = UniStrSize(str);
+ v->UniStr = Malloc(v->Size);
+ UniStrCpy(v->UniStr, v->Size, str);
+
+ UniTrim(v->UniStr);
+
+ return v;
+}
+
+// Creation of the VALUE of ANSI string type
+VALUE *NewStrValue(char *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // String copy
+ v->Size = StrLen(str) + 1;
+ v->Str = Malloc(v->Size);
+ StrCpy(v->Str, v->Size, str);
+
+ Trim(v->Str);
+
+ return v;
+}
+
+// Create the VALUE of the data type
+VALUE *NewDataValue(void *data, UINT size)
+{
+ VALUE *v;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // Data copy
+ v->Size = size;
+ v->Data = Malloc(v->Size);
+ Copy(v->Data, data, size);
+
+ return v;
+}
+
+// Create the VALUE of 64 bit integer type
+VALUE *NewInt64Value(UINT64 i)
+{
+ VALUE *v;
+
+ v = Malloc(sizeof(VALUE));
+ v->Int64Value = i;
+ v->Size = sizeof(UINT64);
+
+ return v;
+}
+
+// Create the VALUE of integer type
+VALUE *NewIntValue(UINT i)
+{
+ VALUE *v;
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+ v->IntValue = i;
+ v->Size = sizeof(UINT);
+
+ return v;
+}
+
+// Delete the ELEMENT
+void FreeElement(ELEMENT *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < e->num_value;i++)
+ {
+ FreeValue(e->values[i], e->type);
+ }
+ Free(e->values);
+
+ Free(e);
+}
+
+// Create a ELEMENT
+ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values)
+{
+ ELEMENT *e;
+ UINT i;
+ // Validate arguments
+ if (name == NULL || num_value == 0 || values == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ e = Malloc(sizeof(ELEMENT));
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = num_value;
+ e->type = type;
+
+ // Copy of the pointer list to the element
+ e->values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);
+ for (i = 0;i < e->num_value;i++)
+ {
+ e->values[i] = values[i];
+ }
+
+ return e;
+}
+
+// Search and retrieve a ELEMENT from the PACK
+ELEMENT *GetElement(PACK *p, char *name, UINT type)
+{
+ ELEMENT t;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ // Search
+ StrCpy(t.name, sizeof(t.name), name);
+ e = Search(p->elements, &t);
+
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ // Type checking
+ if (type != INFINITE)
+ {
+ if (e->type != type)
+ {
+ return NULL;
+ }
+ }
+
+ return e;
+}
+
+// Remove the ELEMENT from the PACK
+void DelElement(PACK *p, char *name)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ e = GetElement(p, name, INFINITE);
+ if (e != NULL)
+ {
+ Delete(p->elements, e);
+
+ FreeElement(e);
+ }
+}
+
+// Add an ELEMENT to the PACK
+bool AddElement(PACK *p, ELEMENT *e)
+{
+ // Validate arguments
+ if (p == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ // Size Check
+ if (LIST_NUM(p->elements) >= MAX_ELEMENT_NUM)
+ {
+ // Can not add any more
+ FreeElement(e);
+ return false;
+ }
+
+ // Check whether there is another item which have same name
+ if (GetElement(p, e->name, INFINITE))
+ {
+ // Exists
+ FreeElement(e);
+ return false;
+ }
+
+ if (e->num_value == 0)
+ {
+ // VALUE without any items can not be added
+ FreeElement(e);
+ return false;
+ }
+
+ // Adding
+ Add(p->elements, e);
+ return true;
+}
+
+// Release of the PACK object
+void FreePack(PACK *p)
+{
+ UINT i;
+ ELEMENT **elements;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ elements = ToArray(p->elements);
+ for (i = 0;i < LIST_NUM(p->elements);i++)
+ {
+ FreeElement(elements[i]);
+ }
+ Free(elements);
+
+ ReleaseList(p->elements);
+ Free(p);
+}
+
+// Create a PACK object
+PACK *NewPack()
+{
+ PACK *p;
+
+ // Memory allocation
+ p = MallocEx(sizeof(PACK), true);
+
+ // Creating a List
+ p->elements = NewListFast(ComparePackName);
+
+ return p;
+}
+
+// Get the K from the PACK
+K *PackGetK(PACK *p, char *name)
+{
+ K *k;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ k = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+
+ return k;
+}
+
+// Get the X from the PACK
+X *PackGetX(PACK *p, char *name)
+{
+ X *x;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ x = BufToX(b, false);
+ FreeBuf(b);
+
+ return x;
+}
+
+// Add the K to the PACK
+void PackAddK(PACK *p, char *name, K *k)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL || k == NULL)
+ {
+ return;
+ }
+
+ b = KToBuf(k, false, NULL);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// Add an X into the PACK
+void PackAddX(PACK *p, char *name, X *x)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL || x == NULL)
+ {
+ return;
+ }
+
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// Get a buffer from the PACK
+BUF *PackGetBuf(PACK *p, char *name)
+{
+ return PackGetBufEx(p, name, 0);
+}
+BUF *PackGetBufEx(PACK *p, char *name, UINT index)
+{
+ UINT size;
+ void *tmp;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ size = PackGetDataSizeEx(p, name, index);
+ tmp = MallocEx(size, true);
+ if (PackGetDataEx(p, name, tmp, index) == false)
+ {
+ Free(tmp);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ SeekBuf(b, 0, 0);
+
+ Free(tmp);
+
+ return b;
+}
+
+// Get the data from the PACK
+bool PackGetData(PACK *p, char *name, void *data)
+{
+ return PackGetDataEx(p, name, data, 0);
+}
+bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+bool PackGetData2(PACK *p, char *name, void *data, UINT size)
+{
+ return PackGetDataEx2(p, name, data, size, 0);
+}
+bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ if (GetDataValueSize(e, index) != size)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+
+// Get the data size from the PACK
+UINT PackGetDataSize(PACK *p, char *name)
+{
+ return PackGetDataSizeEx(p, name, 0);
+}
+UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetDataValueSize(e, index);
+}
+
+// Get an integer from the PACK
+UINT64 PackGetInt64(PACK *p, char *name)
+{
+ return PackGetInt64Ex(p, name, 0);
+}
+UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT64);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetInt64Value(e, index);
+}
+
+// Get the index number from the PACK
+UINT PackGetIndexCount(PACK *p, char *name)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, INFINITE);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return e->num_value;
+}
+
+// Get the number from the PACK
+UINT PackGetNum(PACK *p, char *name)
+{
+ return MIN(PackGetInt(p, name), 65536);
+}
+
+// Get a bool type from the PACK
+bool PackGetBool(PACK *p, char *name)
+{
+ return PackGetInt(p, name) == 0 ? false : true;
+}
+bool PackGetBoolEx(PACK *p, char *name, UINT index)
+{
+ return PackGetIntEx(p, name, index) == 0 ? false : true;
+}
+
+// Add a bool type into the PACK
+void PackAddBool(PACK *p, char *name, bool b)
+{
+ PackAddInt(p, name, b ? 1 : 0);
+}
+void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
+{
+ PackAddIntEx(p, name, b ? 1 : 0, index, total);
+}
+
+// Add the IPV6_ADDR to the PACK
+void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
+}
+void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ PackAddIp6AddrEx(p, name, addr, 0, 1);
+}
+
+// Get an IPV6_ADDR from the PACK
+bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
+}
+bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ return PackGetIp6AddrEx(p, name, addr, 0);
+}
+
+// Add the IP to the PACK
+void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
+{
+ IP ip;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip, ip32);
+
+ PackAddIpEx(p, name, &ip, index, total);
+}
+void PackAddIp32(PACK *p, char *name, UINT ip32)
+{
+ PackAddIp32Ex(p, name, ip32, 0, 1);
+}
+void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
+{
+ UINT i;
+ bool b = false;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (p == NULL || name == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ b = IsIP6(ip);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ PackAddBoolEx(p, tmp, b, index, total);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ if (b)
+ {
+ PackAddDataEx(p, tmp, ip->ipv6_addr, sizeof(ip->ipv6_addr), index, total);
+ }
+ else
+ {
+ UCHAR dummy[16];
+
+ Zero(dummy, sizeof(dummy));
+
+ PackAddDataEx(p, tmp, dummy, sizeof(dummy), index, total);
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ if (b)
+ {
+ PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
+ }
+ else
+ {
+ PackAddIntEx(p, tmp, 0, index, total);
+ }
+
+ i = IPToUINT(ip);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ PackAddIntEx(p, name, i, index, total);
+}
+void PackAddIp(PACK *p, char *name, IP *ip)
+{
+ PackAddIpEx(p, name, ip, 0, 1);
+}
+
+// Get an IP from the PACK
+UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
+{
+ IP ip;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ if (PackGetIpEx(p, name, &ip, index) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&ip);
+}
+UINT PackGetIp32(PACK *p, char *name)
+{
+ return PackGetIp32Ex(p, name, 0);
+}
+bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
+{
+ UINT i;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (p == NULL || ip == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ if (PackGetBoolEx(p, tmp, index))
+ {
+ UCHAR data[16];
+ UINT scope_id;
+
+ Zero(data, sizeof(data));
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ PackGetDataEx2(p, tmp, data, sizeof(data), index);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ scope_id = PackGetIntEx(p, tmp, index);
+
+ SetIP6(ip, data);
+ ip->ipv6_scope_id = scope_id;
+ }
+ else
+ {
+ if (GetElement(p, name, VALUE_INT) == NULL)
+ {
+ Zero(ip, sizeof(IP));
+ return false;
+ }
+
+ i = PackGetIntEx(p, name, index);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ UINTToIP(ip, i);
+ }
+
+ return true;
+}
+bool PackGetIp(PACK *p, char *name, IP *ip)
+{
+ return PackGetIpEx(p, name, ip, 0);
+}
+
+// Get an integer from the PACK
+UINT PackGetInt(PACK *p, char *name)
+{
+ return PackGetIntEx(p, name, 0);
+}
+UINT PackGetIntEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetIntValue(e, index);
+}
+
+// Get an Unicode string from the PACK
+bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
+{
+ return PackGetUniStrEx(p, name, unistr, size, 0);
+}
+bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL || size == 0)
+ {
+ return false;
+ }
+
+ unistr[0] = 0;
+
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(unistr, size, GetUniStrValue(e, index));
+ return true;
+}
+
+// Compare strings in the PACK
+bool PackCmpStr(PACK *p, char *name, char *str)
+{
+ char tmp[MAX_SIZE];
+
+ if (PackGetStr(p, name, tmp, sizeof(tmp)) == false)
+ {
+ return false;
+ }
+
+ if (StrCmpi(tmp, str) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get a string from the PACK
+bool PackGetStr(PACK *p, char *name, char *str, UINT size)
+{
+ return PackGetStrEx(p, name, str, size, 0);
+}
+bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ e = GetElement(p, name, VALUE_STR);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(str, size, GetStrValue(e, index));
+ return true;
+}
+
+// Add the buffer to the PACK (array)
+void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || b == NULL || total == 0)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, b->Buf, b->Size, index, total);
+}
+
+// Add the data to the PACK (array)
+void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || data == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ e = GetElement(p, name, VALUE_DATA);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_DATA);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_DATA;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add the buffer to the PACK
+void PackAddBuf(PACK *p, char *name, BUF *b)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || b == NULL)
+ {
+ return;
+ }
+
+ PackAddData(p, name, b->Buf, b->Size);
+}
+
+// Add the data to the PACK
+void PackAddData(PACK *p, char *name, void *data, UINT size)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || data == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ AddElement(p, NewElement(name, VALUE_DATA, 1, &v));
+}
+
+// Add a 64 bit integer (array) to the PACK
+void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ e = GetElement(p, name, VALUE_INT64);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT64);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT64;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add an integer to the PACK (array)
+void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ e = GetElement(p, name, VALUE_INT);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a 64 bit integer to the PACK
+void PackAddInt64(PACK *p, char *name, UINT64 i)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ AddElement(p, NewElement(name, VALUE_INT64, 1, &v));
+}
+
+// Add the number of items to the PACK
+void PackAddNum(PACK *p, char *name, UINT num)
+{
+ PackAddInt(p, name, num);
+}
+
+// Add an integer to the PACK
+void PackAddInt(PACK *p, char *name, UINT i)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ AddElement(p, NewElement(name, VALUE_INT, 1, &v));
+}
+
+// Add a Unicode string (array) to the PACK
+void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_UNISTR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_UNISTR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a Unicode string to the PACK
+void PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ AddElement(p, NewElement(name, VALUE_UNISTR, 1, &v));
+}
+
+// Add a string to the PACK (array)
+void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ e = GetElement(p, name, VALUE_STR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_STR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_STR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a string to the PACK
+void PackAddStr(PACK *p, char *name, char *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ AddElement(p, NewElement(name, VALUE_STR, 1, &v));
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Pack.h b/src/Mayaqua/Pack.h
new file mode 100644
index 00000000..5cd70d26
--- /dev/null
+++ b/src/Mayaqua/Pack.h
@@ -0,0 +1,234 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Pack.h
+// Header of Pack.c
+
+#ifndef PACK_H
+#define PACK_H
+
+// Constant
+#ifdef CPU_64
+
+#define MAX_VALUE_SIZE (384 * 1024 * 1024) // Maximum Data size that can be stored in a single VALUE
+#define MAX_VALUE_NUM 262144 // Maximum VALUE number that can be stored in a single ELEMENT
+#define MAX_ELEMENT_NAME_LEN 63 // The length of the name that can be attached to the ELEMENT
+#define MAX_ELEMENT_NUM 262144 // Maximum ELEMENT number that can be stored in a single PACK
+#define MAX_PACK_SIZE (512 * 1024 * 1024) // Maximum size of a serialized PACK
+
+#else // CPU_64
+
+#define MAX_VALUE_SIZE (96 * 1024 * 1024) // Maximum Data size that can be stored in a single VALUE
+#define MAX_VALUE_NUM 65536 // Maximum VALUE number that can be stored in a single ELEMENT
+#define MAX_ELEMENT_NAME_LEN 63 // The length of the name that can be attached to the ELEMENT
+#define MAX_ELEMENT_NUM 131072 // Maximum ELEMENT number that can be stored in a single PACK
+#define MAX_PACK_SIZE (128 * 1024 * 1024) // Maximum size of a serialized PACK
+
+#endif // CPU_64
+
+// Type of VALUE
+#define VALUE_INT 0 // Integer type
+#define VALUE_DATA 1 // Data type
+#define VALUE_STR 2 // ANSI string type
+#define VALUE_UNISTR 3 // Unicode string type
+#define VALUE_INT64 4 // 64 bit integer type
+
+// The number of allowable NOOP
+#define MAX_NOOP_PER_SESSION 30
+
+// VALUE object
+struct VALUE
+{
+ UINT Size; // Size
+ UINT IntValue; // Integer value
+ void *Data; // Data
+ char *Str; // ANSI string
+ wchar_t *UniStr; // Unicode strings
+ UINT64 Int64Value; // 64 bit integer type
+};
+
+// ELEMENT object
+struct ELEMENT
+{
+ char name[MAX_ELEMENT_NAME_LEN + 1]; // Element name
+ UINT num_value; // Number of values (>=1)
+ UINT type; // Type
+ VALUE **values; // List of pointers to the value
+};
+
+// PACK object
+struct PACK
+{
+ LIST *elements; // Element list
+};
+
+
+// Function prototype
+PACK *NewPack();
+bool AddElement(PACK *p, ELEMENT *e);
+void DelElement(PACK *p, char *name);
+ELEMENT *GetElement(PACK *p, char *name, UINT type);
+void FreePack(PACK *p);
+ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values);
+VALUE *NewIntValue(UINT i);
+VALUE *NewDataValue(void *data, UINT size);
+VALUE *NewStrValue(char *str);
+VALUE *NewUniStrValue(wchar_t *str);
+void FreeValue(VALUE *v, UINT type);
+int ComparePackName(void *p1, void *p2);
+void FreeElement(ELEMENT *e);
+UINT GetValueNum(ELEMENT *e);
+UINT GetIntValue(ELEMENT *e, UINT index);
+UINT64 GetInt64Value(ELEMENT *e, UINT index);
+char *GetStrValue(ELEMENT *e, UINT index);
+wchar_t *GetUniStrValue(ELEMENT *e, UINT index);
+UINT GetDataValueSize(ELEMENT *e, UINT index);
+void *GetDataValue(ELEMENT *e, UINT index);
+BUF *PackToBuf(PACK *p);
+void WritePack(BUF *b, PACK *p);
+void WriteElement(BUF *b, ELEMENT *e);
+void WriteValue(BUF *b, VALUE *v, UINT type);
+PACK *BufToPack(BUF *b);
+bool ReadPack(BUF *b, PACK *p);
+ELEMENT *ReadElement(BUF *b);
+VALUE *ReadValue(BUF *b, UINT type);
+void Bit160ToStr(char *str, UCHAR *data);
+void Bit128ToStr(char *str, UCHAR *data);
+VALUE *NewInt64Value(UINT64 i);
+TOKEN_LIST *GetPackElementNames(PACK *p);
+
+X *PackGetX(PACK *p, char *name);
+K *PackGetK(PACK *p, char *name);
+void PackAddX(PACK *p, char *name, X *x);
+void PackAddK(PACK *p, char *name, K *k);
+void PackAddStr(PACK *p, char *name, char *str);
+void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total);
+void PackAddUniStr(PACK *p, char *name, wchar_t *unistr);
+void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total);
+void PackAddInt(PACK *p, char *name, UINT i);
+void PackAddNum(PACK *p, char *name, UINT num);
+void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total);
+void PackAddInt64(PACK *p, char *name, UINT64 i);
+void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total);
+void PackAddData(PACK *p, char *name, void *data, UINT size);
+void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total);
+void PackAddBuf(PACK *p, char *name, BUF *b);
+void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total);
+bool PackGetStr(PACK *p, char *name, char *str, UINT size);
+bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index);
+bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size);
+bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index);
+bool PackCmpStr(PACK *p, char *name, char *str);
+UINT PackGetIndexCount(PACK *p, char *name);
+UINT PackGetInt(PACK *p, char *name);
+UINT PackGetNum(PACK *p, char *name);
+UINT PackGetIntEx(PACK *p, char *name, UINT index);
+UINT64 PackGetInt64(PACK *p, char *name);
+UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index);
+UINT PackGetDataSizeEx(PACK *p, char *name, UINT index);
+UINT PackGetDataSize(PACK *p, char *name);
+bool PackGetData(PACK *p, char *name, void *data);
+bool PackGetDataEx(PACK *p, char *name, void *data, UINT index);
+BUF *PackGetBuf(PACK *p, char *name);
+BUF *PackGetBufEx(PACK *p, char *name, UINT index);
+bool PackGetBool(PACK *p, char *name);
+void PackAddBool(PACK *p, char *name, bool b);
+void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total);
+bool PackGetBoolEx(PACK *p, char *name, UINT index);
+void PackAddIp(PACK *p, char *name, IP *ip);
+void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total);
+bool PackGetIp(PACK *p, char *name, IP *ip);
+bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index);
+UINT PackGetIp32(PACK *p, char *name);
+UINT PackGetIp32Ex(PACK *p, char *name, UINT index);
+void PackAddIp32(PACK *p, char *name, UINT ip32);
+void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total);
+void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total);
+bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index);
+void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr);
+bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr);
+bool PackGetData2(PACK *p, char *name, void *data, UINT size);
+bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index);
+
+#endif // PACK_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Secure.c b/src/Mayaqua/Secure.c
new file mode 100644
index 00000000..e970062f
--- /dev/null
+++ b/src/Mayaqua/Secure.c
@@ -0,0 +1,2197 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Secure.c
+// Security token management module
+
+#include <GlobalConst.h>
+
+#define SECURE_C
+#define ENCRYPT_C
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Mayaqua/cryptoki.h>
+
+
+#define MAX_OBJ 1024 // Maximum number of objects in the hardware (assumed)
+
+#define A_SIZE(a, i) (a[(i)].ulValueLen)
+#define A_SET(a, i, value, size) (a[i].pValue = value;a[i].ulValueLen = size;)
+
+#ifdef OS_WIN32
+// Code for Win32
+
+// DLL reading for Win32
+HINSTANCE Win32SecureLoadLibraryEx(char *dllname, DWORD flags)
+{
+ char tmp1[MAX_PATH];
+ char tmp2[MAX_PATH];
+ char tmp3[MAX_PATH];
+ HINSTANCE h;
+ // Validate arguments
+ if (dllname == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp1, sizeof(tmp1), "%s\\%s", MsGetSystem32Dir(), dllname);
+ Format(tmp2, sizeof(tmp2), "%s\\JPKI\\%s", MsGetProgramFilesDir(), dllname);
+ Format(tmp3, sizeof(tmp3), "%s\\LGWAN\\%s", MsGetProgramFilesDir(), dllname);
+
+ h = LoadLibraryEx(dllname, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp1, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp2, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp3, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ return NULL;
+}
+
+// Examine whether the specified device is installed
+bool Win32IsDeviceSupported(SECURE_DEVICE *dev)
+{
+ HINSTANCE hInst;
+ // Validate arguments
+ if (dev == NULL)
+ {
+ return false;
+ }
+
+ // Check whether the DLL is readable
+ hInst = Win32SecureLoadLibraryEx(dev->ModuleName, DONT_RESOLVE_DLL_REFERENCES);
+ if (hInst == NULL)
+ {
+ return false;
+ }
+
+ FreeLibrary(hInst);
+
+ return true;
+}
+
+// Load the device module
+bool Win32LoadSecModule(SECURE *sec)
+{
+ SEC_DATA_WIN32 *w;
+ HINSTANCE hInst;
+ CK_FUNCTION_LIST_PTR api = NULL;
+ CK_RV (*get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+
+ if (sec->Dev->Id == 9)
+ {
+ char username[MAX_SIZE];
+ DWORD size;
+ // Because the device driver of Juki-Net needs the contents
+ // of the Software\JPKI registry key on HKLU of SYSTEM,
+ // if there is no key, copy the key from the value of other user
+// if (MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "Name") == false ||
+// MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "RWType") == false)
+ size = sizeof(username);
+ GetUserName(username, &size);
+ if (StrCmpi(username, "System") == 0)
+ {
+ TOKEN_LIST *t = MsRegEnumKey(REG_USERS, NULL);
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char tmp[MAX_PATH];
+
+ if (StrCmpi(t->Token[i], ".DEFAULT") != 0 && StrCmpi(t->Token[i], "S-1-5-18") != 0)
+ {
+ Format(tmp, sizeof(tmp), "%s\\Software\\JPKI", t->Token[i]);
+
+ if (MsRegIsValue(REG_USERS, tmp, "Name") && MsRegIsValue(REG_USERS, tmp, "RWType"))
+ {
+ char *name = MsRegReadStr(REG_USERS, tmp, "Name");
+ char *port = MsRegReadStr(REG_USERS, tmp, "Port");
+ UINT type = MsRegReadInt(REG_USERS, tmp, "RWType");
+
+ MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Name", name);
+ MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Port", port);
+ MsRegWriteInt(REG_CURRENT_USER, "Software\\JPKI", "RWType", type);
+
+ Free(name);
+ Free(port);
+ break;
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+ }
+ }
+
+ // Load the Library
+ hInst = Win32SecureLoadLibraryEx(sec->Dev->ModuleName, 0);
+ if (hInst == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ // Get the API
+ get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
+ GetProcAddress(hInst, "C_GetFunctionList");
+
+ if (get_function_list == NULL)
+ {
+ // Failure
+ FreeLibrary(hInst);
+ return false;
+ }
+
+ get_function_list(&api);
+ if (api == NULL)
+ {
+ // Failure
+ FreeLibrary(hInst);
+ return false;
+ }
+
+ sec->Data = ZeroMalloc(sizeof(SEC_DATA_WIN32));
+ w = sec->Data;
+
+ w->hInst = hInst;
+ sec->Api = api;
+
+ return true;
+}
+
+// Unload the device module
+void Win32FreeSecModule(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Data == NULL)
+ {
+ return;
+ }
+
+ // Unload
+ FreeLibrary(sec->Data->hInst);
+ Free(sec->Data);
+
+ sec->Data = NULL;
+}
+
+#endif // OS_WIN32
+
+
+// Whether the specified device is a JPKI
+bool IsJPKI(bool id)
+{
+ if (id == 9 || id == 13)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Sign with the private key which is specified by the name in the secure device
+bool SignSec(SECURE *sec, char *name, void *dst, void *src, UINT size)
+{
+ SEC_OBJ *obj;
+ UINT ret;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL || dst == NULL || src == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ obj = FindSecObject(sec, name, SEC_K);
+ if (obj == NULL)
+ {
+ return false;
+ }
+
+ ret = SignSecByObject(sec, obj, dst, src, size);
+
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Sign with the private key of the secure device
+bool SignSecByObject(SECURE *sec, SEC_OBJ *obj, void *dst, void *src, UINT size)
+{
+ CK_MECHANISM mechanism = {CKM_RSA_PKCS, NULL, 0};
+ UINT ret;
+ UCHAR hash[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (obj == NULL || dst == NULL || src == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (obj->Type != SEC_K)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ // Hash
+ HashForSign(hash, sizeof(hash), src, size);
+
+ // Signature initialization
+ ret = sec->Api->C_SignInit(sec->SessionId, &mechanism, obj->Object);
+ if (ret != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("C_SignInit Error: 0x%x\n", ret);
+ return false;
+ }
+
+ // Perform Signing
+ size = 128;
+ ret = sec->Api->C_Sign(sec->SessionId, hash, sizeof(hash), dst, &size);
+ if (ret != CKR_OK || size != 128)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("C_Sign Error: 0x%x\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+// Changing the PIN code
+bool ChangePin(SECURE *sec, char *old_pin, char *new_pin)
+{
+ // Validate arguments
+ if (sec == NULL || old_pin == NULL || new_pin == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (sec->IsReadOnly)
+ {
+ sec->Error = SEC_ERROR_OPEN_SESSION;
+ return false;
+ }
+
+ // Change then PIN
+ if (sec->Api->C_SetPIN(sec->SessionId, old_pin, StrLen(old_pin),
+ new_pin, StrLen(new_pin)) != CKR_OK)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write the private key object
+bool WriteSecKey(SECURE *sec, bool private_obj, char *name, K *k)
+{
+ UINT key_type = CKK_RSA;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT obj_class = CKO_PRIVATE_KEY;
+ UINT object;
+ UINT ret;
+ BUF *b;
+ RSA *rsa;
+ UCHAR modules[MAX_SIZE], pub[MAX_SIZE], pri[MAX_SIZE], prime1[MAX_SIZE], prime2[MAX_SIZE];
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_MODULUS, modules, 0}, // 0
+ {CKA_PUBLIC_EXPONENT, pub, 0}, // 1
+ {CKA_PRIVATE_EXPONENT, pri, 0}, // 2
+ {CKA_PRIME_1, prime1, 0}, // 3
+ {CKA_PRIME_2, prime2, 0}, // 4
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_KEY_TYPE, &key_type, sizeof(key_type)},
+ {CKA_DERIVE, &b_false, sizeof(b_false)},
+ {CKA_SUBJECT, name, StrLen(name)},
+ {CKA_SENSITIVE, &b_true, sizeof(b_true)},
+ {CKA_DECRYPT, &b_true, sizeof(b_true)},
+ {CKA_SIGN, &b_true, sizeof(b_true)},
+ {CKA_SIGN_RECOVER, &b_false, sizeof(b_false)},
+ {CKA_EXTRACTABLE, &b_false, sizeof(b_false)},
+ {CKA_MODIFIABLE, &b_false, sizeof(b_false)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL || k == NULL || k->private_key == false)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && private_obj)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Numeric data generation
+ rsa = k->pkey->pkey.rsa;
+ if (rsa == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ b = BigNumToBuf(rsa->n);
+ ReadBuf(b, modules, sizeof(modules));
+ A_SIZE(a, 0) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->e);
+ ReadBuf(b, pub, sizeof(pub));
+ A_SIZE(a, 1) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->d);
+ ReadBuf(b, pri, sizeof(pri));
+ A_SIZE(a, 2) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->p);
+ ReadBuf(b, prime1, sizeof(prime1));
+ A_SIZE(a, 3) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->q);
+ ReadBuf(b, prime2, sizeof(prime2));
+ A_SIZE(a, 4) = b->Size;
+ FreeBuf(b);
+
+ // Delete the old key if it exists
+ if (CheckSecObject(sec, name, SEC_K))
+ {
+ DeleteSecKey(sec, name);
+ }
+
+ // Creating
+ if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("ret: 0x%x\n", ret);
+ return false;
+ }
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Read the certificate object by specifying the name
+X *ReadSecCert(SECURE *sec, char *name)
+{
+ SEC_OBJ *obj;
+ X *x;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+
+ // Search
+ obj = FindSecObject(sec, name, SEC_X);
+ if (obj == NULL)
+ {
+ return false;
+ }
+
+ // Acquisition
+ x = ReadSecCertFromObject(sec, obj);
+
+ FreeSecObject(obj);
+
+ return x;
+}
+
+// Read the certificate object
+X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj)
+{
+ UINT size;
+ X *x;
+ UCHAR value[4096];
+ BUF *b;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_VALUE, value, sizeof(value)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (obj->Type != SEC_X)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ // Acquisition
+ if (sec->Api->C_GetAttributeValue(
+ sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return 0;
+ }
+
+ size = A_SIZE(get, 0);
+
+ // Conversion
+ b = NewBuf();
+ WriteBuf(b, value, size);
+ SeekBuf(b, 0, 0);
+
+ x = BufToX(b, false);
+ if (x == NULL)
+ {
+ sec->Error = SEC_ERROR_INVALID_CERT;
+ }
+
+ FreeBuf(b);
+
+ return x;
+}
+
+// Write the certificate object
+bool WriteSecCert(SECURE *sec, bool private_obj, char *name, X *x)
+{
+ UINT obj_class = CKO_CERTIFICATE;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT cert_type = CKC_X_509;
+ CK_DATE start_date, end_date;
+ UCHAR subject[MAX_SIZE];
+ UCHAR issuer[MAX_SIZE];
+ wchar_t w_subject[MAX_SIZE];
+ wchar_t w_issuer[MAX_SIZE];
+ UCHAR serial_number[MAX_SIZE];
+ UCHAR value[4096];
+ UINT ret;
+ BUF *b;
+ UINT object;
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_SUBJECT, subject, 0}, // 0
+ {CKA_ISSUER, issuer, 0}, // 1
+ {CKA_SERIAL_NUMBER, serial_number, 0}, // 2
+ {CKA_VALUE, value, 0}, // 3
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)},
+#if 0 // Don't use these because some tokens fail
+ {CKA_START_DATE, &start_date, sizeof(start_date)},
+ {CKA_END_DATE, &end_date, sizeof(end_date)},
+#endif
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && private_obj)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Copy the certificate to the buffer
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ sec->Error = SEC_ERROR_INVALID_CERT;
+ return false;
+ }
+ if (b->Size > sizeof(value))
+ {
+ // Size is too large
+ FreeBuf(b);
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return false;
+ }
+ Copy(value, b->Buf, b->Size);
+ A_SIZE(a, 3) = b->Size;
+ FreeBuf(b);
+
+ // Store the Subject and the Issuer by encoding into UTF-8
+ GetPrintNameFromName(w_subject, sizeof(w_subject), x->subject_name);
+ UniToUtf8(subject, sizeof(subject), w_subject);
+ A_SIZE(a, 0) = StrLen(subject);
+ if (x->root_cert == false)
+ {
+ GetPrintNameFromName(w_issuer, sizeof(w_issuer), x->issuer_name);
+ UniToUtf8(issuer, sizeof(issuer), w_issuer);
+ A_SIZE(a, 1) = StrLen(issuer);
+ }
+
+ // Copy the serial number
+ Copy(serial_number, x->serial->data, MIN(x->serial->size, sizeof(serial_number)));
+ A_SIZE(a, 2) = MIN(x->serial->size, sizeof(serial_number));
+
+ // Expiration date information
+ UINT64ToCkDate(&start_date, SystemToLocal64(x->notBefore));
+ UINT64ToCkDate(&end_date, SystemToLocal64(x->notAfter));
+
+ // Remove objects which have the same name
+ if (CheckSecObject(sec, name, SEC_X))
+ {
+ DeleteSecCert(sec, name);
+ }
+
+ // Creating
+ if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("Error: 0x%02x\n", ret);
+ return false;
+ }
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Delete the private key object
+bool DeleteSecKey(SECURE *sec, char *name)
+{
+ return DeleteSecObjectByName(sec, name, SEC_K);
+}
+
+// Delete the certificate object
+bool DeleteSecCert(SECURE *sec, char *name)
+{
+ return DeleteSecObjectByName(sec, name, SEC_X);
+}
+
+// Convert the the CK_DATE to the 64 bit time
+UINT64 CkDateToUINT64(struct CK_DATE *ck_date)
+{
+ SYSTEMTIME st;
+ char year[32], month[32], day[32];
+ // Validate arguments
+ if (ck_date == NULL)
+ {
+ return 0;
+ }
+
+ Zero(year, sizeof(year));
+ Zero(month, sizeof(month));
+ Zero(day, sizeof(day));
+
+ Copy(year, ck_date->year, 4);
+ Copy(month, ck_date->month, 2);
+ Copy(day, ck_date->day, 2);
+
+ st.wYear = ToInt(year);
+ st.wMonth = ToInt(month);
+ st.wDay = ToInt(day);
+
+ return SystemToUINT64(&st);
+}
+
+// Convert the 64 bit time to the CK_DATE
+void UINT64ToCkDate(void *p_ck_date, UINT64 time64)
+{
+ SYSTEMTIME st;
+ char year[32], month[32], day[32];
+ struct CK_DATE *ck_date = (CK_DATE *)p_ck_date;
+ // Validate arguments
+ if (ck_date == NULL)
+ {
+ return;
+ }
+
+ UINT64ToSystem(&st, time64);
+
+ Format(year, sizeof(year), "%04u", st.wYear);
+ Format(month, sizeof(month), "%04u", st.wMonth);
+ Format(day, sizeof(day), "%04u", st.wDay);
+
+ Zero(ck_date, sizeof(CK_DATE));
+
+ Copy(ck_date->year, year, 4);
+ Copy(ck_date->month, month, 2);
+ Copy(ck_date->day, day, 2);
+}
+
+// Delete the object by specifying the name
+bool DeleteSecObjectByName(SECURE *sec, char *name, UINT type)
+{
+ bool ret;
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+
+ // Get the Object
+ obj = FindSecObject(sec, name, type);
+ if (obj == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ // Delete the Object
+ ret = DeleteSecObject(sec, obj);
+
+ // Memory release
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Delete the Data
+bool DeleteSecData(SECURE *sec, char *name)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ return DeleteSecObjectByName(sec, name, SEC_DATA);
+}
+
+// Delete the secure object
+bool DeleteSecObject(SECURE *sec, SEC_OBJ *obj)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (obj == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Delete the Object
+ if (sec->Api->C_DestroyObject(sec->SessionId, obj->Object) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return false;
+ }
+
+ // Clear the Cache
+ DeleteSecObjFromEnumCache(sec, obj->Name, obj->Type);
+
+ return true;
+}
+
+// Remove the object which have the specified name from the cache
+void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type)
+{
+ UINT i;
+ // Validate arguments
+ if (sec == NULL || name == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(sec->EnumCache);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(sec->EnumCache, i);
+
+ if (StrCmpi(obj->Name, name) == 0)
+ {
+ if (obj->Type == type)
+ {
+ Delete(sec->EnumCache, obj);
+ FreeSecObject(obj);
+ break;
+ }
+ }
+ }
+}
+
+// Read by searching a secure object by name
+int ReadSecData(SECURE *sec, char *name, void *data, UINT size)
+{
+ UINT ret = 0;
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL || name == NULL || data == NULL)
+ {
+ return 0;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ // Read
+ obj = FindSecObject(sec, name, SEC_DATA);
+ if (obj == NULL)
+ {
+ // Not found
+ return 0;
+ }
+
+ // Read
+ ret = ReadSecDataFromObject(sec, obj, data, size);
+
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Clear the cache
+void EraseEnumSecObjectCache(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ FreeEnumSecObject(sec->EnumCache);
+ sec->EnumCache = NULL;
+}
+
+// Check for the existence of a secure object
+bool CheckSecObject(SECURE *sec, char *name, UINT type)
+{
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ obj = FindSecObject(sec, name, type);
+
+ if (obj == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ FreeSecObject(obj);
+ return true;
+ }
+}
+
+// Cloning a secure object structure
+SEC_OBJ *CloneSecObject(SEC_OBJ *obj)
+{
+ SEC_OBJ *ret;
+ // Validate arguments
+ if (obj == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(SEC_OBJ));
+ ret->Name = CopyStr(obj->Name);
+ ret->Object = obj->Object;
+ ret->Private = obj->Private;
+ ret->Type = obj->Type;
+
+ return ret;
+}
+
+// Search a secure object by the name
+SEC_OBJ *FindSecObject(SECURE *sec, char *name, UINT type)
+{
+ LIST *o;
+ UINT i;
+ SEC_OBJ *ret = NULL;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return NULL;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ // Enumeration
+ o = EnumSecObject(sec);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ if (obj->Type == type || type == INFINITE)
+ {
+ if (StrCmpi(obj->Name, name) == 0)
+ {
+ ret = CloneSecObject(obj);
+ break;
+ }
+ }
+ }
+ FreeEnumSecObject(o);
+
+ if (ret == NULL)
+ {
+ sec->Error = SEC_ERROR_OBJ_NOT_FOUND;
+ }
+
+ return ret;
+}
+
+// Reading a secure object
+int ReadSecDataFromObject(SECURE *sec, SEC_OBJ *obj, void *data, UINT size)
+{
+ UCHAR buf[MAX_SEC_DATA_SIZE];
+ UINT i;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_VALUE, buf, sizeof(buf)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return 0;
+ }
+ if (obj == NULL || data == NULL || size == 0)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return 0;
+ }
+ if (obj->Type != SEC_DATA)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return 0;
+ }
+
+ // Acquisition
+ if (sec->Api->C_GetAttributeValue(
+ sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return 0;
+ }
+
+ // Return the result
+ i = get[0].ulValueLen;
+ if (i > MAX_SEC_DATA_SIZE || i > size)
+ {
+ // Data is too large
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return 0;
+ }
+
+ // Memory copy
+ Copy(data, buf, i);
+
+ return i;
+}
+
+// Release of enumeration results of the secure object
+void FreeEnumSecObject(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ FreeSecObject(obj);
+ }
+
+ ReleaseList(o);
+}
+
+// Release the secure object
+void FreeSecObject(SEC_OBJ *obj)
+{
+ // Validate arguments
+ if (obj == NULL)
+ {
+ return;
+ }
+
+ Free(obj->Name);
+ Free(obj);
+}
+
+// Clone the secure object enumeration results
+LIST *CloneEnumSecObject(LIST *o)
+{
+ LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ Add(ret, CloneSecObject(obj));
+ }
+
+ return ret;
+}
+
+// Enumeration of the secure objects
+LIST *EnumSecObject(SECURE *sec)
+{
+ CK_BBOOL b_true = true, b_false = false;
+ UINT objects[MAX_OBJ];
+ UINT i;
+ UINT ret;
+ LIST *o;
+ CK_ATTRIBUTE dummy[1];
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ };
+ UINT num_objects = MAX_OBJ;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return NULL;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return NULL;
+ }
+
+ Zero(dummy, sizeof(dummy));
+
+ // If there is a cache, return it
+ if (sec->EnumCache != NULL)
+ {
+ return CloneEnumSecObject(sec->EnumCache);
+ }
+
+ // Enumerate
+// if (sec->Dev->Id != 2 && sec->Dev->Id != 14)
+// {
+ // Normal tokens
+ ret = sec->Api->C_FindObjectsInit(sec->SessionId, a, sizeof(a) / sizeof(a[0]));
+// }
+// else
+// {
+ // ePass and SafeSign
+// ret = sec->Api->C_FindObjectsInit(sec->SessionId, dummy, 0);
+// }
+
+ if (ret != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return NULL;
+ }
+ if (sec->Api->C_FindObjects(sec->SessionId, objects, sizeof(objects) / sizeof(objects[0]), &num_objects) != CKR_OK)
+ {
+ sec->Api->C_FindObjectsFinal(sec->SessionId);
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return NULL;
+ }
+ sec->Api->C_FindObjectsFinal(sec->SessionId);
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < num_objects;i++)
+ {
+ char label[MAX_SIZE];
+ UINT obj_class = 0;
+ bool priv = false;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_LABEL, label, sizeof(label) - 1},
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_PRIVATE, &priv, sizeof(priv)},
+ };
+
+ Zero(label, sizeof(label));
+
+ if (sec->Api->C_GetAttributeValue(sec->SessionId, objects[i],
+ get, sizeof(get) / sizeof(get[0])) == CKR_OK)
+ {
+ UINT type = INFINITE;
+
+ switch (obj_class)
+ {
+ case CKO_DATA:
+ // Data
+ type = SEC_DATA;
+ break;
+
+ case CKO_CERTIFICATE:
+ // Certificate
+ type = SEC_X;
+ break;
+
+ case CKO_PUBLIC_KEY:
+ // Public key
+ type = SEC_P;
+ break;
+
+ case CKO_PRIVATE_KEY:
+ // Secret key
+ type = SEC_K;
+ break;
+ }
+
+ if (type != INFINITE)
+ {
+ SEC_OBJ *obj = ZeroMalloc(sizeof(SEC_OBJ));
+
+ obj->Type = type;
+ obj->Object = objects[i];
+ obj->Private = (priv == false) ? false : true;
+ EnSafeStr(label, '?');
+ TruncateCharFromStr(label, '?');
+ obj->Name = CopyStr(label);
+
+ Add(o, obj);
+ }
+ }
+ }
+
+ // Creating a cache
+ sec->EnumCache = CloneEnumSecObject(o);
+
+ return o;
+}
+
+// Write the data
+bool WriteSecData(SECURE *sec, bool private_obj, char *name, void *data, UINT size)
+{
+ UINT object_class = CKO_DATA;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT object;
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_CLASS, &object_class, sizeof(object_class)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_VALUE, data, size},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (private_obj && sec->LoginFlag == false)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (name == NULL || data == NULL || size == 0)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (size > MAX_SEC_DATA_SIZE)
+ {
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return false;
+ }
+
+ // Delete any objects with the same name
+ if (CheckSecObject(sec, name, SEC_DATA))
+ {
+ DeleteSecData(sec, name);
+ }
+
+ // Object creation
+ if (sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return false;
+ }
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Add the information of the newly created object to the cache
+void AddSecObjToEnumCache(SECURE *sec, char *name, UINT type, bool private_obj, UINT object)
+{
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL || name == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ obj = ZeroMalloc(sizeof(SEC_OBJ));
+ obj->Name = CopyStr(name);
+ obj->Object = object;
+ obj->Private = private_obj;
+ obj->Type = type;
+
+ Add(sec->EnumCache, obj);
+}
+
+// Display the token information
+void PrintSecInfo(SECURE *sec)
+{
+ SEC_INFO *s;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ s = sec->Info;
+ if (s == NULL)
+ {
+ Print("No Token Info.\n");
+ return;
+ }
+
+ Print(
+ " Label: %S\n"
+ " ManufacturerId: %S\n"
+ " Model: %S\n"
+ " SerialNumber: %S\n"
+ " MaxSession: %u\n"
+ " MaxRWSession: %u\n"
+ " MinPinLen: %u\n"
+ " MaxPinLen: %u\n"
+ " TotalPublicMemory: %u\n"
+ " FreePublicMemory: %u\n"
+ " TotalPrivateMemory: %u\n"
+ " FreePrivateMemory: %u\n"
+ " HardwareVersion: %s\n"
+ " FirmwareVersion: %s\n",
+ s->Label, s->ManufacturerId, s->Model, s->SerialNumber,
+ s->MaxSession, s->MaxRWSession, s->MinPinLen, s->MaxPinLen,
+ s->TotalPublicMemory, s->FreePublicMemory, s->TotalPrivateMemory,
+ s->FreePrivateMemory, s->HardwareVersion, s->FirmwareVersion
+ );
+}
+
+// Get the token information
+void GetSecInfo(SECURE *sec)
+{
+ CK_TOKEN_INFO token_info;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Info != NULL)
+ {
+ return;
+ }
+
+ // Acquisition
+ Zero(&token_info, sizeof(token_info));
+ if (sec->Api->C_GetTokenInfo(sec->SlotIdList[sec->SessionSlotNumber], &token_info) != CKR_OK)
+ {
+ // Failure
+ return;
+ }
+
+ sec->Info = TokenInfoToSecInfo(&token_info);
+}
+
+// Release the token information
+void FreeSecInfo(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Info == NULL)
+ {
+ return;
+ }
+
+ FreeSecInfoMemory(sec->Info);
+ sec->Info = NULL;
+}
+
+// Convert the token information to the SEC_INFO
+SEC_INFO *TokenInfoToSecInfo(void *p_t)
+{
+ SEC_INFO *s;
+ char buf[MAX_SIZE];
+ CK_TOKEN_INFO *t = (CK_TOKEN_INFO *)p_t;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(SEC_INFO));
+
+ // Label
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->label, sizeof(t->label));
+ s->Label = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->Label, 0, buf, 0);
+
+ // ManufacturerId
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->manufacturerID, sizeof(t->manufacturerID));
+ s->ManufacturerId = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->ManufacturerId, 0, buf, 0);
+
+ // Model
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->model, sizeof(t->model));
+ s->Model = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->Model, 0, buf, 0);
+
+ // SerialNumber
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->serialNumber, sizeof(t->serialNumber));
+ s->SerialNumber = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->SerialNumber, 0, buf, 0);
+
+ // Numeric value
+ s->MaxSession = t->ulMaxSessionCount;
+ s->MaxRWSession = t->ulMaxRwSessionCount;
+ s->MinPinLen = t->ulMinPinLen;
+ s->MaxPinLen = t->ulMaxPinLen;
+ s->TotalPublicMemory = t->ulTotalPublicMemory;
+ s->FreePublicMemory = t->ulFreePublicMemory;
+ s->TotalPrivateMemory = t->ulTotalPrivateMemory;
+ s->FreePrivateMemory = t->ulFreePrivateMemory;
+
+ // Hardware version
+ Format(buf, sizeof(buf), "%u.%02u", t->hardwareVersion.major, t->hardwareVersion.minor);
+ s->HardwareVersion = CopyStr(buf);
+
+ // Firmware version
+ Format(buf, sizeof(buf), "%u.%02u", t->firmwareVersion.major, t->firmwareVersion.minor);
+ s->FirmwareVersion = CopyStr(buf);
+
+ return s;
+}
+
+// Release the memory of the SEC_INFO
+void FreeSecInfoMemory(SEC_INFO *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Free(s->Label);
+ Free(s->ManufacturerId);
+ Free(s->Model);
+ Free(s->SerialNumber);
+ Free(s->HardwareVersion);
+ Free(s->FirmwareVersion);
+ Free(s);
+}
+
+// Log-out
+void LogoutSec(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->LoginFlag == false)
+ {
+ return;
+ }
+
+ // Log-out
+ sec->Api->C_Logout(sec->SessionId);
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ sec->LoginFlag = false;
+}
+
+// Log-in
+bool LoginSec(SECURE *sec, char *pin)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+
+ }
+ if (sec->LoginFlag)
+ {
+ sec->Error = SEC_ERROR_ALREADY_LOGIN;
+ return false;
+ }
+ if (pin == NULL)
+ {
+ sec->Error = SEC_ERROR_NO_PIN_STR;
+ return false;
+ }
+
+ // Log-in
+ if (sec->Api->C_Login(sec->SessionId, CKU_USER, pin, StrLen(pin)) != CKR_OK)
+ {
+ // Login failure
+ sec->Error = SEC_ERROR_BAD_PIN_CODE;
+ return false;
+ }
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+
+ sec->LoginFlag = true;
+
+ return true;
+}
+
+// Close the session
+void CloseSecSession(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->SessionCreated == false)
+ {
+ return;
+ }
+
+ // Close the session
+ sec->Api->C_CloseSession(sec->SessionId);
+
+ sec->SessionCreated = false;
+ sec->SessionId = 0;
+ sec->SessionSlotNumber = 0;
+
+ FreeSecInfo(sec);
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+}
+
+// Open the session
+bool OpenSecSession(SECURE *sec, UINT slot_number)
+{
+ UINT err = 0;
+ UINT session;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated)
+ {
+ // Already been created
+ sec->Error = SEC_ERROR_SESSION_EXISTS;
+ return false;
+ }
+ if (slot_number >= sec->NumSlot)
+ {
+ // Slot number is invalid
+ sec->Error = SEC_ERROR_INVALID_SLOT_NUMBER;
+ return false;
+ }
+
+ // Create a session
+ if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)
+ {
+ // Failed to initialize session in read / write mode
+ // Read-only mode?
+ if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],
+ CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)
+ {
+ // Failure to create
+ sec->Error = SEC_ERROR_OPEN_SESSION;
+ return false;
+ }
+ else
+ {
+ sec->IsReadOnly = true;
+ }
+ }
+
+ sec->SessionCreated = true;
+ sec->SessionId = session;
+ sec->SessionSlotNumber = slot_number;
+
+ // Get the token information
+ GetSecInfo(sec);
+
+ return true;
+}
+
+// Close the secure device
+void CloseSec(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Release the token information
+ FreeSecInfo(sec);
+
+ // Release of the slot list memory
+ if (sec->SlotIdList != NULL)
+ {
+ Free(sec->SlotIdList);
+ sec->SlotIdList = NULL;
+ }
+
+ // Unload the module
+ FreeSecModule(sec);
+
+ // Memory release
+ DeleteLock(sec->lock);
+ Free(sec);
+}
+
+// Open a secure device
+SECURE *OpenSec(UINT id)
+{
+ SECURE_DEVICE *dev = GetSecureDevice(id);
+ SECURE *sec;
+ UINT err;
+
+ if (dev == NULL)
+ {
+ return NULL;
+ }
+
+ sec = ZeroMalloc(sizeof(SECURE));
+
+ sec->lock = NewLock();
+ sec->Error = SEC_ERROR_NOERROR;
+ sec->Dev = dev;
+
+ // Get whether it's a ePass or not
+ if (SearchStrEx(dev->DeviceName, "epass", 0, false) != INFINITE)
+ {
+ sec->IsEPass1000 = true;
+ }
+
+ // Load the module
+ if (LoadSecModule(sec) == false)
+ {
+ CloseSec(sec);
+ return NULL;
+ }
+
+ // Get the slot list
+ sec->NumSlot = 0;
+ if ((err = sec->Api->C_GetSlotList(true, NULL, &sec->NumSlot)) != CKR_OK || sec->NumSlot == 0)
+ {
+ // Failure
+ FreeSecModule(sec);
+ CloseSec(sec);
+ return NULL;
+ }
+
+ sec->SlotIdList = (UINT *)ZeroMalloc(sizeof(UINT *) * sec->NumSlot);
+
+ if (sec->Api->C_GetSlotList(TRUE, sec->SlotIdList, &sec->NumSlot) != CKR_OK)
+ {
+ // Failure
+ Free(sec->SlotIdList);
+ sec->SlotIdList = NULL;
+ FreeSecModule(sec);
+ CloseSec(sec);
+ return NULL;
+ }
+
+ return sec;
+}
+
+// Load the module of the secure device
+bool LoadSecModule(SECURE *sec)
+{
+ bool ret = false;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ ret = Win32LoadSecModule(sec);
+#endif // OS_WIN32
+
+ // Initialization
+ if (sec->Api->C_Initialize(NULL) != CKR_OK)
+ {
+ // Initialization Failed
+ FreeSecModule(sec);
+ return false;
+ }
+
+ sec->Initialized = true;
+
+ return ret;
+}
+
+// Unload the module of the secure device
+void FreeSecModule(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ if (sec->Initialized)
+ {
+ // Release because it is initialized
+ sec->Api->C_Finalize(NULL);
+ sec->Initialized = false;
+ }
+
+#ifdef OS_WIN32
+ Win32FreeSecModule(sec);
+#endif // OS_WIN32
+
+}
+
+
+// Get a secure device
+SECURE_DEVICE *GetSecureDevice(UINT id)
+{
+ UINT i;
+
+ if (id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(SecureDeviceList);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);
+
+ if (dev->Id == id)
+ {
+ return dev;
+ }
+ }
+
+ return NULL;
+}
+
+// Confirm the ID of the secure device
+bool CheckSecureDeviceId(UINT id)
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(SecureDeviceList);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);
+
+ if (dev->Id == id)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get a list of supported devices
+LIST *GetSecureDeviceList()
+{
+ return GetSupportedDeviceList();
+}
+
+// Get a list of supported devices
+LIST *GetSupportedDeviceList()
+{
+ // Increase the reference count
+ AddRef(SecureDeviceList->ref);
+
+ return SecureDeviceList;
+}
+
+// Examine whether the specified device is installed and available
+bool IsDeviceSupported(SECURE_DEVICE *dev)
+{
+ bool b = false;
+#ifdef OS_WIN32
+ b = Win32IsDeviceSupported(dev);
+#endif // OS_WIN32
+ return b;
+}
+
+// Initialization of the secure device list
+void InitSecureDeviceList()
+{
+ UINT i, num_supported_list;
+ SecureDeviceList = NewList(NULL);
+
+ num_supported_list = sizeof(SupportedList) / sizeof(SECURE_DEVICE);
+ for (i = 0; i < num_supported_list;i++)
+ {
+ SECURE_DEVICE *dev = &SupportedList[i];
+
+ // Support Checking
+ if (IsDeviceSupported(dev))
+ {
+ // Add the device to the list because it is supported
+ Add(SecureDeviceList, dev);
+ }
+ }
+}
+
+// Test main procedure
+void TestSecMain(SECURE *sec)
+{
+ char *test_str = CEDAR_PRODUCT_STR " VPN";
+ K *public_key, *private_key;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ Print("test_str: \"%s\"\n", test_str);
+
+ Print("Writing Data...\n");
+ if (WriteSecData(sec, true, "test_str", test_str, StrLen(test_str)) == false)
+ {
+ Print("WriteSecData() Failed.\n");
+ }
+ else
+ {
+ char data[MAX_SIZE];
+ Zero(data, sizeof(data));
+ Print("Reading Data...\n");
+ if (ReadSecData(sec, "test_str", data, sizeof(data)) == false)
+ {
+ Print("ReadSecData() Failed.\n");
+ }
+ else
+ {
+ Print("test_str: \"%s\"\n", data);
+ }
+ Print("Deleting Data...\n");
+ DeleteSecData(sec, "test_str");
+ }
+
+ Print("Generating Key...\n");
+ if (RsaGen(&private_key, &public_key, 1024) == false)
+ {
+ Print("RsaGen() Failed.\n");
+ }
+ else
+ {
+ X *cert;
+ NAME *name;
+ X_SERIAL *serial;
+ UINT num = 0x11220000;
+
+ Print("Creating Cert...\n");
+ serial = NewXSerial(&num, sizeof(UINT));
+ name = NewName(L"Test", L"Test", L"Test", L"JP", L"Test", L"Test");
+ cert = NewRootX(public_key, private_key, name, 365, NULL);
+ FreeXSerial(serial);
+ if (cert == NULL)
+ {
+ Print("NewRootX() Failed.\n");
+ }
+ else
+ {
+ Print("Writing Cert...\n");
+ DeleteSecData(sec, "test_cer");
+ if (WriteSecCert(sec, true, "test_cer", cert) == false)
+ {
+ Print("WriteSecCert() Failed.\n");
+ }
+ else
+ {
+ X *x;
+ Print("Reading Cert...\n");
+ x = ReadSecCert(sec, "test_cer");
+ if (x == NULL)
+ {
+ Print("ReadSecCert() Failed.\n");
+ }
+ else
+ {
+ Print("Checking two Certs... ");
+ if (CompareX(x, cert) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ }
+ FreeX(x);
+ }
+ if (cert != NULL)
+ {
+ X *x;
+ XToFile(cert, "cert_tmp.cer", true);
+ x = FileToX("cert_tmp.cer");
+ if (CompareX(x, cert) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("Writing Private Key...\n");
+ DeleteSecKey(sec, "test_key");
+ if (WriteSecKey(sec, true, "test_key", private_key) == false)
+ {
+ Print("WriteSecKey() Failed.\n");
+ }
+ else
+ {
+ UCHAR sign_cpu[128];
+ UCHAR sign_sec[128];
+ K *pub = GetKFromX(cert);
+ Print("Ok.\n");
+ Print("Signing Data by CPU...\n");
+ if (RsaSign(sign_cpu, test_str, StrLen(test_str), private_key) == false)
+ {
+ Print("RsaSign() Failed.\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("sign_cpu: ");
+ PrintBin(sign_cpu, sizeof(sign_cpu));
+ Print("Signing Data by %s..\n", sec->Dev->DeviceName);
+ if (SignSec(sec, "test_key", sign_sec, test_str, StrLen(test_str)) == false)
+ {
+ Print("SignSec() Failed.\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("sign_sec: ");
+ PrintBin(sign_sec, sizeof(sign_sec));
+ Print("Compare...");
+ if (Cmp(sign_sec, sign_cpu, sizeof(sign_cpu)) == 0)
+ {
+ Print("Ok.\n");
+ Print("Verify...");
+ if (RsaVerify(test_str, StrLen(test_str),
+ sign_sec, pub) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ }
+ }
+ else
+ {
+ Print("[DIFFIRENT]\n");
+ }
+ }
+ }
+ Print("Deleting test_key...\n");
+// DeleteSecKey(sec, "test_key");
+ FreeK(pub);
+ }
+ }
+ FreeX(x);
+ }
+ }
+ Print("Deleting Cert..\n");
+// DeleteSecCert(sec, "test_cer");
+ FreeX(cert);
+ }
+ FreeName(name);
+ FreeK(private_key);
+ FreeK(public_key);
+ }
+}
+
+// Test the security device
+void TestSec()
+{
+ UINT i;
+ LIST *secure_device_list;
+ Print("Secure Device Test Program\n"
+ "Copyright (c) SoftEther Corporation. All Rights Reserved.\n\n");
+
+ // Get the secure device list
+ secure_device_list = GetSecureDeviceList();
+ if (secure_device_list != NULL)
+ {
+ UINT use_device_id;
+ char tmp[MAX_SIZE];
+ Print("--- Secure Device List ---\n");
+ for (i = 0;i < LIST_NUM(secure_device_list);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(secure_device_list, i);
+ Print("%2u - %s\n", dev->Id, dev->DeviceName);
+ }
+ Print("\n");
+ Print("Device ID >");
+ GetLine(tmp, sizeof(tmp));
+ use_device_id = ToInt(tmp);
+ if (use_device_id == 0)
+ {
+ Print("Canceled.\n");
+ }
+ else
+ {
+ SECURE *sec = OpenSec(use_device_id);
+ Print("Opening Device...\n");
+ if (sec == NULL)
+ {
+ Print("OpenSec() Failed.\n");
+ }
+ else
+ {
+ Print("Opening Session...\n");
+ if (OpenSecSession(sec, 0) == false)
+ {
+ Print("OpenSecSession() Failed.\n");
+ }
+ else
+ {
+ while (true)
+ {
+ char pin[MAX_SIZE];
+ Print("PIN Code >");
+ GetLine(pin, sizeof(pin));
+ Trim(pin);
+ if (StrLen(pin) == 0)
+ {
+ Print("Canceled.\n");
+ break;
+ }
+ else
+ {
+ Print("Login...\n");
+ if (LoginSec(sec, pin))
+ {
+ TestSecMain(sec);
+ Print("Logout...\n");
+ LogoutSec(sec);
+ break;
+ }
+ else
+ {
+ Print("Login Failed. Please Try Again.\n");
+ }
+ }
+ }
+ Print("Closing Session...\n");
+ CloseSecSession(sec);
+ }
+ Print("Closing Device...\n");
+ CloseSec(sec);
+ }
+ }
+ ReleaseList(secure_device_list);
+ }
+ else
+ {
+ Print("GetSecureDeviceList() Error.\n");
+ }
+}
+
+// Release of the secure device list
+void FreeSecureDeviceList()
+{
+ ReleaseList(SecureDeviceList);
+}
+
+// Initialization of the security token module
+void InitSecure()
+{
+ // Initialization of the secure device list
+ InitSecureDeviceList();
+}
+
+// Release of the security token module
+void FreeSecure()
+{
+ // Release of the secure device list
+ FreeSecureDeviceList();
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Secure.h b/src/Mayaqua/Secure.h
new file mode 100644
index 00000000..f9fd0fdd
--- /dev/null
+++ b/src/Mayaqua/Secure.h
@@ -0,0 +1,297 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Secure.h
+// Header of Secure.c
+
+#ifndef SECURE_H
+#define SECURE_H
+
+// Constant
+#define MAX_SEC_DATA_SIZE 4096
+
+// Type declaration related to PKCS#11
+#ifndef SECURE_C
+typedef struct CK_FUNCTION_LIST *CK_FUNCTION_LIST_PTR;
+typedef struct SEC_DATA_WIN32 SEC_DATA_WIN32;
+typedef struct CK_TOKEN_INFO CK_TOKEN_INFO;
+typedef struct CK_DATE CK_DATE;
+#endif // SECURE_C
+
+// Secure device
+struct SECURE_DEVICE
+{
+ UINT Id; // Device ID
+ UINT Type; // Type
+ char *DeviceName; // Device name
+ char *Manufacturer; // Manufacturer
+ char *ModuleName; // Module name
+};
+
+// Type of secure device
+#define SECURE_IC_CARD 0 // IC card
+#define SECURE_USB_TOKEN 1 // USB token
+
+// Secure device information
+struct SEC_INFO
+{
+ wchar_t *Label; // Label
+ wchar_t *ManufacturerId; // Vendor ID
+ wchar_t *Model; // Model
+ wchar_t *SerialNumber; // Serial number
+ UINT MaxSession; // Maximum number of sessions
+ UINT MaxRWSession; // Maximum Number of R/W sessions
+ UINT MinPinLen; // Minimum length of the PIN string
+ UINT MaxPinLen; // Maximum length of the PIN string
+ UINT TotalPublicMemory; // Total memory capacity (Public)
+ UINT FreePublicMemory; // Free memory capacity (Public)
+ UINT TotalPrivateMemory; // Total memory capacity (Private)
+ UINT FreePrivateMemory; // Free memory capacity (Private)
+ char *HardwareVersion; // Hardware version
+ char *FirmwareVersion; // Firmware version
+};
+
+// Secure device structure
+struct SECURE
+{
+ LOCK *lock; // Lock
+ SECURE_DEVICE *Dev; // Device Information
+ UINT Error; // The error that last occurred
+ struct CK_FUNCTION_LIST *Api; // API
+ bool Initialized; // Initialization flag
+ UINT NumSlot; // The number of slots
+ UINT *SlotIdList; // Slot ID list
+ bool SessionCreated; // Session creation flags
+ UINT SessionId; // Session ID
+ UINT SessionSlotNumber; // Slot ID of the session
+ bool LoginFlag; // Logged-in flag
+ SEC_INFO *Info; // Token information
+ LIST *EnumCache; // Enumeration cache
+
+ // Attribute value for the different behavior for each driver
+ bool IsEPass1000; // ePass 1000
+ bool IsReadOnly; // Read-only mode
+
+#ifdef OS_WIN32
+ struct SEC_DATA_WIN32 *Data; // Data
+#endif // OS_WIN32
+};
+
+// Secure device object structure
+struct SEC_OBJ
+{
+ UINT Type; // Type of object
+ UINT Object; // Object handle
+ bool Private; // Private flag
+ char *Name; // Name
+};
+
+#define SEC_ERROR_NOERROR 0 // No Error
+#define SEC_ERROR_INVALID_SLOT_NUMBER 1 // Slot number is invalid
+#define SEC_ERROR_OPEN_SESSION 2 // Session creation failure
+#define SEC_ERROR_SESSION_EXISTS 3 // The session already exists
+#define SEC_ERROR_NO_PIN_STR 4 // PIN string is not specified
+#define SEC_ERROR_ALREADY_LOGIN 5 // Already logged in
+#define SEC_ERROR_BAD_PIN_CODE 6 // PIN code is invalid
+#define SEC_ERROR_NO_SESSION 7 // There is no session
+#define SEC_ERROR_DATA_TOO_BIG 8 // Data is too large
+#define SEC_ERROR_NOT_LOGIN 9 // Not logged in
+#define SEC_ERROR_BAD_PARAMETER 10 // Invalid Parameters
+#define SEC_ERROR_HARDWARE_ERROR 11 // Hardware error
+#define SEC_ERROR_OBJ_NOT_FOUND 12 // Object is not found
+#define SEC_ERROR_INVALID_CERT 13 // The certificate is invalid
+
+
+#define SEC_DATA 0 // Data
+#define SEC_X 1 // Certificate
+#define SEC_K 2 // Secret key
+#define SEC_P 3 // Public key
+
+
+
+// Function prototype
+void InitSecure();
+void FreeSecure();
+void InitSecureDeviceList();
+void FreeSecureDeviceList();
+bool IsDeviceSupported(SECURE_DEVICE *dev);
+LIST *GetSupportedDeviceList();
+LIST *GetSecureDeviceList();
+bool CheckSecureDeviceId(UINT id);
+SECURE_DEVICE *GetSecureDevice(UINT id);
+SECURE *OpenSec(UINT id);
+void CloseSec(SECURE *sec);
+bool OpenSecSession(SECURE *sec, UINT slot_number);
+void CloseSecSession(SECURE *sec);
+bool LoginSec(SECURE *sec, char *pin);
+void LogoutSec(SECURE *sec);
+void PrintSecInfo(SECURE *sec);
+LIST *EnumSecObject(SECURE *sec);
+void FreeSecObject(SEC_OBJ *obj);
+void FreeEnumSecObject(LIST *o);
+SEC_OBJ *FindSecObject(SECURE *sec, char *name, UINT type);
+bool CheckSecObject(SECURE *sec, char *name, UINT type);
+bool DeleteSecObjectByName(SECURE *sec, char *name, UINT type);
+SEC_OBJ *CloneSecObject(SEC_OBJ *obj);
+LIST *CloneEnumSecObject(LIST *o);
+void EraseEnumSecObjectCache(SECURE *sec);
+void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type);
+void AddSecObjToEnumCache(SECURE *sec, char *name, UINT type, bool private_obj, UINT object);
+bool WriteSecData(SECURE *sec, bool private_obj, char *name, void *data, UINT size);
+int ReadSecDataFromObject(SECURE *sec, SEC_OBJ *obj, void *data, UINT size);
+int ReadSecData(SECURE *sec, char *name, void *data, UINT size);
+bool DeleteSecObject(SECURE *sec, SEC_OBJ *obj);
+bool DeleteSecData(SECURE *sec, char *name);
+void UINT64ToCkDate(void *p_ck_date, UINT64 time64);
+bool WriteSecCert(SECURE *sec, bool private_obj, char *name, X *x);
+bool DeleteSecCert(SECURE *sec, char *name);
+X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj);
+X *ReadSecCert(SECURE *sec, char *name);
+bool WriteSecKey(SECURE *sec, bool private_obj, char *name, K *k);
+bool DeleteSecKey(SECURE *sec, char *name);
+bool SignSecByObject(SECURE *sec, SEC_OBJ *obj, void *dst, void *src, UINT size);
+bool SignSec(SECURE *sec, char *name, void *dst, void *src, UINT size);
+bool ChangePin(SECURE *sec, char *old_pin, char *new_pin);
+void TestSec();
+void TestSecMain(SECURE *sec);
+bool IsJPKI(bool id);
+
+bool LoadSecModule(SECURE *sec);
+void FreeSecModule(SECURE *sec);
+void GetSecInfo(SECURE *sec);
+void FreeSecInfo(SECURE *sec);
+SEC_INFO *TokenInfoToSecInfo(void *p_t);
+void FreeSecInfoMemory(SEC_INFO *s);
+
+#ifdef OS_WIN32
+
+bool Win32IsDeviceSupported(SECURE_DEVICE *dev);
+bool Win32LoadSecModule(SECURE *sec);
+void Win32FreeSecModule(SECURE *sec);
+
+#endif // OS_WIN32
+
+
+#ifdef SECURE_C
+// Internal data structure
+// The list of supported secure devices
+static LIST *SecureDeviceList = NULL;
+
+// Supported hardware list
+SECURE_DEVICE SupportedList[] =
+{
+ {1, SECURE_IC_CARD, "Standard-9 IC Card", "Dai Nippon Printing", "DNPS9P11.DLL"},
+ {2, SECURE_USB_TOKEN, "ePass 1000", "Feitian Technologies", "EP1PK111.DLL"},
+ {3, SECURE_IC_CARD, "DNP Felica", "Dai Nippon Printing", "DNPFP11.DLL"},
+ {4, SECURE_USB_TOKEN, "eToken", "Aladdin", "ETPKCS11.DLL"},
+ {5, SECURE_IC_CARD, "Standard-9 IC Card", "Fujitsu", "F3EZSCL2.DLL"},
+ {6, SECURE_IC_CARD, "ASECard", "Athena", "ASEPKCS.DLL"},
+ {7, SECURE_IC_CARD, "Gemplus IC Card", "Gemplus", "PK2PRIV.DLL"},
+ {8, SECURE_IC_CARD, "1-Wire & iButton", "DALLAS SEMICONDUCTOR", "DSPKCS.DLL"},
+ {9, SECURE_IC_CARD, "JPKI IC Card", "Japanese Government", "JPKIPKCS11.DLL"},
+ {10, SECURE_IC_CARD, "LGWAN IC Card", "Japanese Government", "P11STD9.DLL"},
+ {11, SECURE_IC_CARD, "LGWAN IC Card", "Japanese Government", "P11STD9A.DLL"},
+ {12, SECURE_USB_TOKEN, "iKey 1000", "Rainbow Technologies", "K1PK112.DLL"},
+ {13, SECURE_IC_CARD, "JPKI IC Card #2", "Japanese Government", "libmusclepkcs11.dll"},
+ {14, SECURE_USB_TOKEN, "SafeSign", "A.E.T.", "aetpkss1.dll"},
+ {15, SECURE_USB_TOKEN, "LOCK STAR-PKI", "Logicaltech Co.,LTD", "LTPKCS11.dll"},
+ {16, SECURE_USB_TOKEN, "ePass 2000", "Feitian Technologies", "ep2pk11.dll"},
+ {17, SECURE_IC_CARD, "myuToken", "iCanal Inc.", "icardmodpk.dll"},
+ {18, SECURE_IC_CARD, "Gemalto .NET", "Gemalto", "gtop11dotnet.dll"},
+ {19, SECURE_IC_CARD, "Gemalto .NET 64bit", "Gemalto", "gtop11dotnet64.dll"},
+};
+
+#ifdef OS_WIN32
+
+// Win32 internal data
+typedef struct SEC_DATA_WIN32
+{
+ HINSTANCE hInst;
+} SEC_DATA_WIN32;
+
+#endif // OS_WIN32
+
+#endif // SECURE_C
+
+#endif // SECURE_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Str.c b/src/Mayaqua/Str.c
new file mode 100644
index 00000000..a85edaf9
--- /dev/null
+++ b/src/Mayaqua/Str.c
@@ -0,0 +1,3391 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Str.c
+// String processing routine
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Locking for call the token handling function
+LOCK *token_lock = NULL;
+static char *default_spliter = " ,\t\r\n";
+
+typedef struct BYTESTR
+{
+ UINT64 base_value;
+ char *string;
+} BYTESTR;
+
+static BYTESTR bytestr[] =
+{
+ {0, "PBytes"},
+ {0, "TBytes"},
+ {0, "GBytes"},
+ {0, "MBytes"},
+ {0, "KBytes"},
+ {0, "Bytes"},
+};
+
+// Change the case of the string by the bit array
+void SetStrCaseAccordingToBits(char *str, UINT bits)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (bits & 0x01)
+ {
+ c = ToUpper(c);
+ }
+ else
+ {
+ c = ToLower(c);
+ }
+
+ str[i] = c;
+
+ bits = bits / 2;
+ }
+}
+
+// Normalize the integer list string
+void NormalizeIntListStr(char *dst, UINT dst_size, char *src, bool sorted, char *separate_str)
+{
+ LIST *o;
+
+ o = StrToIntList(src, sorted);
+
+ IntListToStr(dst, dst_size, o, separate_str);
+
+ ReleaseIntList(o);
+}
+
+// Convert the string to an integer list
+LIST *StrToIntList(char *str, bool sorted)
+{
+ LIST *o;
+ TOKEN_LIST *t;
+
+ o = NewIntList(sorted);
+
+ t = ParseTokenWithoutNullStr(str, " ,/;\t");
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (IsEmptyStr(s) == false)
+ {
+ if (IsNum(s))
+ {
+ InsertIntDistinct(o, ToInt(s));
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return o;
+}
+
+// Convert an integer list to a string
+void IntListToStr(char *str, UINT str_size, LIST *o, char *separate_str)
+{
+ UINT i;
+ ClearStr(str, str_size);
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+ if (IsEmptyStr(separate_str))
+ {
+ separate_str = ", ";
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT *v = LIST_DATA(o, i);
+
+ ToStr(tmp, *v);
+
+ StrCat(str, str_size, tmp);
+
+ if (i != (LIST_NUM(o) - 1))
+ {
+ StrCat(str, str_size, separate_str);
+ }
+ }
+}
+
+// Initialize the string
+void ClearStr(char *str, UINT str_size)
+{
+ StrCpy(str, str_size, "");
+}
+
+// Search for the ASCII string in the binary data sequence
+UINT SearchAsciiInBinary(void *data, UINT size, char *str, bool case_sensitive)
+{
+ UINT ret = INFINITE;
+ char *tmp;
+ // Validate arguments
+ if (data == NULL || size == 0 || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ tmp = ZeroMalloc(size + 1);
+ Copy(tmp, data, size);
+
+ ret = SearchStrEx(tmp, str, 0, case_sensitive);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the HEX string to a 64 bit integer
+UINT64 HexToInt64(char *str)
+{
+ UINT len, i;
+ UINT64 ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ {
+ str += 2;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+ {
+ ret = ret * 16ULL + (UINT64)HexTo4Bit(c);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Convert the HEX string to a 32 bit integer
+UINT HexToInt(char *str)
+{
+ UINT len, i;
+ UINT ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ {
+ str += 2;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+ {
+ ret = ret * 16 + (UINT)HexTo4Bit(c);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Convert a 64 bit integer to a HEX
+void ToHex64(char *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT64)16);
+ value = value / (UINT)16;
+ tmp[wp++] = FourBitToHex(a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Convert a 32 bit integer into HEX
+void ToHex(char *str, UINT value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT)16);
+ value = value / (UINT)16;
+ tmp[wp++] = FourBitToHex(a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Converts a 4 bit value to hexadecimal string
+char FourBitToHex(UINT value)
+{
+ value = value % 16;
+
+ if (value <= 9)
+ {
+ return '0' + value;
+ }
+ else
+ {
+ return 'a' + (value - 10);
+ }
+}
+
+// Convert a hexadecimal string to a 4 bit integer
+UINT HexTo4Bit(char c)
+{
+ if ('0' <= c && c <= '9')
+ {
+ return c - '0';
+ }
+ else if ('a' <= c && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else if ('A' <= c && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Get a standard token delimiter
+char *DefaultTokenSplitChars()
+{
+ return " ,\t\r\n";
+}
+
+// Check whether the specified character is in the string
+bool IsCharInStr(char *str, char c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Cut out the token from the string (not ignore the blanks between delimiters)
+TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars)
+{
+ LIST *o;
+ UINT i, len;
+ BUF *b;
+ char zero = 0;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+ if (split_chars == NULL)
+ {
+ split_chars = DefaultTokenSplitChars();
+ }
+
+ b = NewBuf();
+ o = NewListFast(NULL);
+
+ len = StrLen(str);
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = str[i];
+ bool flag = IsCharInStr(split_chars, c);
+
+ if (c == '\0')
+ {
+ flag = true;
+ }
+
+ if (flag == false)
+ {
+ WriteBuf(b, &c, sizeof(char));
+ }
+ else
+ {
+ WriteBuf(b, &zero, sizeof(char));
+
+ Insert(o, CopyStr((char *)b->Buf));
+ ClearBuf(b);
+ }
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+ FreeBuf(b);
+
+ return t;
+}
+
+// Check whether the string contains at least one of the specified tokens
+bool InStrList(char *target_str, char *tokens, char *splitter, bool case_sensitive)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (target_str == NULL || tokens == NULL || splitter == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(tokens, splitter);
+
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (InStrEx(target_str, t->Token[i], case_sensitive))
+ {
+ ret = true;
+// printf("%s\n", t->Token[i]);
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return ret;
+}
+
+// Confirm whether the specified string is in the token list
+bool IsStrInStrTokenList(char *str_list, char *str, char *split_chars, bool case_sensitive)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (str_list == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(str_list, split_chars);
+
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if ((case_sensitive == false) && (StrCmpi(t->Token[i], str) == 0))
+ {
+ ret = true;
+ }
+ if ((case_sensitive) && (StrCmp(t->Token[i], str) == 0))
+ {
+ ret = true;
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return ret;
+}
+
+// Cut out the token from string (Ignore blanks between delimiters)
+TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars)
+{
+ LIST *o;
+ UINT i, len;
+ bool last_flag;
+ BUF *b;
+ char zero = 0;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+ if (split_chars == NULL)
+ {
+ split_chars = DefaultTokenSplitChars();
+ }
+
+ b = NewBuf();
+ o = NewListFast(NULL);
+
+ len = StrLen(str);
+ last_flag = false;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = str[i];
+ bool flag = IsCharInStr(split_chars, c);
+
+ if (c == '\0')
+ {
+ flag = true;
+ }
+
+ if (flag == false)
+ {
+ WriteBuf(b, &c, sizeof(char));
+ }
+ else
+ {
+ if (last_flag == false)
+ {
+ WriteBuf(b, &zero, sizeof(char));
+
+ if ((StrLen((char *)b->Buf)) != 0)
+ {
+ Insert(o, CopyStr((char *)b->Buf));
+ }
+ ClearBuf(b);
+ }
+ }
+
+ last_flag = flag;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+ FreeBuf(b);
+
+ return t;
+}
+
+// Check whether the string is included
+bool InStr(char *str, char *keyword)
+{
+ return InStrEx(str, keyword, false);
+}
+bool InStrEx(char *str, char *keyword, bool case_sensitive)
+{
+ // Validate arguments
+ if (IsEmptyStr(str) || IsEmptyStr(keyword))
+ {
+ return false;
+ }
+
+ if (SearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get a value from the INI
+UINT IniIntValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return ToInt(e->Value);
+}
+UINT64 IniInt64Value(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return ToInt64(e->Value);
+}
+char *IniStrValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return "";
+ }
+
+ return e->Value;
+}
+wchar_t *IniUniStrValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return L"";
+ }
+
+ return e->UnicodeValue;
+}
+
+// Check whether the specified value is in the INI
+bool IniHasValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ e = GetIniEntry(o, key);
+
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Release the INI
+void FreeIni(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ INI_ENTRY *e = LIST_DATA(o, i);
+
+ Free(e->Key);
+ Free(e->Value);
+ Free(e->UnicodeValue);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Get an entry in the INI file
+INI_ENTRY *GetIniEntry(LIST *o, char *key)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ INI_ENTRY *e = LIST_DATA(o, i);
+
+ if (StrCmpi(e->Key, key) == 0)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Read an INI file
+LIST *ReadIni(BUF *b)
+{
+ LIST *o;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ SeekBuf(b, 0, 0);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#") == false &&
+ StartWith(line, "//") == false &&
+ StartWith(line, ";") == false)
+ {
+ char *key, *value;
+ UINT size = StrLen(line) + 1;
+
+ key = ZeroMalloc(size);
+ value = ZeroMalloc(size);
+
+ if (GetKeyAndValue(line, key, size, value, size, NULL))
+ {
+ UINT uni_size;
+ INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));
+ e->Key = CopyStr(key);
+ e->Value = CopyStr(value);
+
+ uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value));
+ e->UnicodeValue = ZeroMalloc(uni_size);
+ Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value));
+
+ Add(o, e);
+ }
+
+ Free(key);
+ Free(value);
+ }
+ }
+
+ Free(line);
+ }
+
+ return o;
+}
+
+// Check whether the specified character is a delimiter
+bool IsSplitChar(char c, char *split_str)
+{
+ UINT i, len;
+ char c_upper = ToUpper(c);
+ if (split_str == NULL)
+ {
+ split_str = default_spliter;
+ }
+
+ len = StrLen(split_str);
+
+ for (i = 0;i < len;i++)
+ {
+ if (ToUpper(split_str[i]) == c_upper)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get the keys and the value from the string
+bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str)
+{
+ UINT mode = 0;
+ UINT wp1 = 0, wp2 = 0;
+ UINT i, len;
+ char *key_tmp, *value_tmp;
+ bool ret = false;
+ if (split_str == NULL)
+ {
+ split_str = default_spliter;
+ }
+
+ len = StrLen(str);
+
+ key_tmp = ZeroMalloc(len + 1);
+ value_tmp = ZeroMalloc(len + 1);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ mode = 1;
+ key_tmp[wp1] = c;
+ wp1++;
+ }
+ break;
+
+ case 1:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ key_tmp[wp1] = c;
+ wp1++;
+ }
+ else
+ {
+ mode = 2;
+ }
+ break;
+
+ case 2:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ mode = 3;
+ value_tmp[wp2] = c;
+ wp2++;
+ }
+ break;
+
+ case 3:
+ value_tmp[wp2] = c;
+ wp2++;
+ break;
+ }
+ }
+
+ if (mode != 0)
+ {
+ ret = true;
+ StrCpy(key, key_size, key_tmp);
+ StrCpy(value, value_size, value_tmp);
+ }
+
+ Free(key_tmp);
+ Free(value_tmp);
+
+ return ret;
+}
+
+// Generate a sequence of specified character
+char *MakeCharArray(char c, UINT count)
+{
+ UINT i;
+ char *ret = Malloc(count + 1);
+
+ for (i = 0;i < count;i++)
+ {
+ ret[i] = c;
+ }
+
+ ret[count] = 0;
+
+ return ret;
+}
+void MakeCharArray2(char *str, char c, UINT count)
+{
+ UINT i;
+
+ for (i = 0;i < count;i++)
+ {
+ str[i] = c;
+ }
+
+ str[count] = 0;
+}
+
+// Get the width of the specified string
+UINT StrWidth(char *str)
+{
+ wchar_t *s;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ s = CopyStrToUni(str);
+ ret = UniStrWidth(s);
+ Free(s);
+
+ return ret;
+}
+
+// Check whether the specified string is all uppercase
+bool IsAllUpperStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z'))
+ {
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Normalize the line breaks
+char *NormalizeCrlf(char *str)
+{
+ char *ret;
+ UINT ret_size, i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ ret_size = sizeof(char) * (len + 32) * 2;
+ ret = Malloc(ret_size);
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ switch (c)
+ {
+ case '\r':
+ if (str[i + 1] == '\n')
+ {
+ i++;
+ }
+ ret[wp++] = '\r';
+ ret[wp++] = '\n';
+ break;
+
+ case '\n':
+ ret[wp++] = '\r';
+ ret[wp++] = '\n';
+ break;
+
+ default:
+ ret[wp++] = c;
+ break;
+ }
+ }
+
+ ret[wp++] = 0;
+
+ return ret;
+}
+
+// Remove duplications from the token list
+TOKEN_LIST *UniqueToken(TOKEN_LIST *t)
+{
+ UINT i, num, j, n;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ num = 0;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ bool exists = false;
+
+ for (j = 0;j < i;j++)
+ {
+ if (StrCmpi(t->Token[j], t->Token[i]) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ num++;
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(sizeof(char *) * num);
+ ret->NumTokens = num;
+
+ n = 0;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ bool exists = false;
+
+ for (j = 0;j < i;j++)
+ {
+ if (StrCmpi(t->Token[j], t->Token[i]) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ ret->Token[n++] = CopyStr(t->Token[i]);
+ }
+ }
+
+ return ret;
+}
+
+// Convert a value to a byte string (by 1,000)
+void ToStrByte1000(char *str, UINT size, UINT64 v)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Warning measures in gcc
+ bytestr[0].base_value = 1000000000UL;
+ bytestr[0].base_value *= 1000UL;
+ bytestr[0].base_value *= 1000UL;
+ bytestr[1].base_value = 1000000000UL;
+ bytestr[1].base_value *= 1000UL;
+ bytestr[2].base_value = 1000000000UL;
+ bytestr[3].base_value = 1000000UL;
+ bytestr[4].base_value = 1000UL;
+ bytestr[5].base_value = 0UL;
+
+ for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
+ {
+ BYTESTR *b = &bytestr[i];
+
+ if ((v * 11UL) / 10UL >= b->base_value)
+ {
+ if (b->base_value != 0)
+ {
+ double d = (double)v / (double)b->base_value;
+ Format(str, size, "%.2f %s", d, b->string);
+ }
+ else
+ {
+ Format(str, size, "%I64u %s", v, b->string);
+ }
+
+ break;
+ }
+ }
+}
+
+// Convert a value to a byte string
+void ToStrByte(char *str, UINT size, UINT64 v)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Warning measures in gcc
+ bytestr[0].base_value = 1073741824UL;
+ bytestr[0].base_value *= 1024UL;
+ bytestr[0].base_value *= 1024UL;
+ bytestr[1].base_value = 1073741824UL;
+ bytestr[1].base_value *= 1024UL;
+ bytestr[2].base_value = 1073741824UL;
+ bytestr[3].base_value = 1048576UL;
+ bytestr[4].base_value = 1024UL;
+ bytestr[5].base_value = 0UL;
+
+ for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
+ {
+ BYTESTR *b = &bytestr[i];
+
+ if ((v * 11UL) / 10UL >= b->base_value)
+ {
+ if (b->base_value != 0)
+ {
+ double d = (double)v / (double)b->base_value;
+ Format(str, size, "%.2f %s", d, b->string);
+ }
+ else
+ {
+ Format(str, size, "%I64u %s", v, b->string);
+ }
+
+ break;
+ }
+ }
+}
+
+// Convert the number to a string, and separate it with commas by three orders of magnitude
+void ToStr3(char *str, UINT size, UINT64 v)
+{
+ char tmp[128];
+ char tmp2[128];
+ UINT i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr64(tmp, v);
+
+ wp = 0;
+ len = StrLen(tmp);
+
+ for (i = len - 1;((int)i) >= 0;i--)
+ {
+ tmp2[wp++] = tmp[i];
+ }
+ tmp2[wp++] = 0;
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ if (i != 0 && (i % 3) == 0)
+ {
+ tmp[wp++] = ',';
+ }
+ tmp[wp++] = tmp2[i];
+ }
+ tmp[wp++] = 0;
+ wp = 0;
+ len = StrLen(tmp);
+
+ for (i = len - 1;((int)i) >= 0;i--)
+ {
+ tmp2[wp++] = tmp[i];
+ }
+ tmp2[wp++] = 0;
+
+ StrCpy(str, size, tmp2);
+}
+
+// Convert the MAC address to a string
+void MacToStr(char *str, UINT size, UCHAR *mac_address)
+{
+ // Validate arguments
+ if (str == NULL || mac_address == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02X-%02X-%02X-%02X-%02X-%02X",
+ mac_address[0],
+ mac_address[1],
+ mac_address[2],
+ mac_address[3],
+ mac_address[4],
+ mac_address[5]);
+}
+
+// Examine whether the string is empty
+bool IsEmptyStr(char *str)
+{
+ char *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return true;
+ }
+
+ s = CopyStr(str);
+ Trim(s);
+
+ if (StrLen(s) == 0)
+ {
+ Free(s);
+ return true;
+ }
+ else
+ {
+ Free(s);
+ return false;
+ }
+}
+
+// Convert the token list to a string list
+LIST *TokenListToList(TOKEN_LIST *t)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ Insert(o, CopyStr(t->Token[i]));
+ }
+
+ return o;
+}
+
+// Convert a string list to a token list
+TOKEN_LIST *ListToTokenList(LIST *o)
+{
+ UINT i;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = CopyStr(LIST_DATA(o, i));
+ }
+
+ return t;
+}
+
+// Free the string list
+void FreeStrList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ Free(s);
+ }
+
+ ReleaseList(o);
+}
+
+// Convert the string list to a string
+BUF *StrListToStr(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ char c;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ WriteBuf(b, s, StrLen(s) + 1);
+ }
+
+ c = 0;
+ WriteBuf(b, &c, 1);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert a (NULL delimited) string to a list
+LIST *StrToStrList(char *str, UINT size)
+{
+ LIST *o;
+ char *tmp;
+ UINT tmp_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ i = 0;
+ while (true)
+ {
+ if (i >= size)
+ {
+ break;
+ }
+ if (*str == 0)
+ {
+ break;
+ }
+
+ tmp_size = StrSize(str);
+ tmp = ZeroMalloc(tmp_size);
+ StrCpy(tmp, tmp_size, str);
+ Add(o, tmp);
+ str += StrLen(str) + 1;
+ i++;
+ }
+
+ return o;
+}
+
+// Check whether the specified string is a number
+bool IsNum(char *str)
+{
+ char c;
+ UINT i, len;
+ UINT n = 0;
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (StrLen(tmp) == 0)
+ {
+ return false;
+ }
+
+ t = ParseToken(tmp, " ");
+
+ if (t->NumTokens >= 1)
+ {
+ StrCpy(tmp, sizeof(tmp), t->Token[0]);
+ }
+
+ FreeToken(t);
+
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ bool b = false;
+ c = tmp[i];
+ if (('0' <= c && c <= '9') || (c == '+') || (c == '-') || (c == ','))
+ {
+ b = true;
+ }
+
+ if (b == false)
+ {
+ return false;
+ }
+ }
+
+ for (i = 0;i < len;i++)
+ {
+ c = tmp[i];
+ if (c == '-')
+ {
+ n++;
+ }
+ }
+ if (n >= 2)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Empty token list
+TOKEN_LIST *NullToken()
+{
+ TOKEN_LIST *ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Copy the token list
+TOKEN_LIST *CopyToken(TOKEN_LIST *src)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Parse the command line
+TOKEN_LIST *ParseCmdLine(char *str)
+{
+ TOKEN_LIST *t;
+ LIST *o;
+ UINT i, len, wp, mode;
+ char c;
+ char *tmp;
+ bool ignore_space = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ // There is no token
+ return NullToken();
+ }
+
+ o = NewListFast(NULL);
+ tmp = Malloc(StrSize(str) + 32);
+
+ wp = 0;
+ mode = 0;
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ // Mode to discover the next token
+ if (c == ' ' || c == '\t')
+ {
+ // Advance to the next character
+ }
+ else
+ {
+ // Start of the token
+ if (c == '\"')
+ {
+ if (str[i + 1] == '\"')
+ {
+ // Regard "" as a single "
+ tmp[wp++] = '\"';
+ i++;
+ }
+ else
+ {
+ // Enable the ignoring space flag for a single "
+ ignore_space = true;
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+
+ mode = 1;
+ }
+ break;
+
+ case 1:
+ if (ignore_space == false && (c == ' ' || c == '\t'))
+ {
+ // End of the token
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, CopyStr(tmp));
+ mode = 0;
+ }
+ else
+ {
+ if (c == '\"')
+ {
+ if (str[i + 1] == '\"')
+ {
+ // Regard "" as a single "
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ if (ignore_space == false)
+ {
+ // Enable the ignoring space flag for a single "
+ ignore_space = true;
+ }
+ else
+ {
+ // Disable the space ignore flag
+ ignore_space = false;
+ }
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+ break;
+ }
+ }
+
+ if (wp != 0)
+ {
+ tmp[wp++] = 0;
+ Insert(o, CopyStr(tmp));
+ }
+
+ Free(tmp);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Convert a 64-bit integer to a string
+void ToStr64(char *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT64)10);
+ value = value / (UINT64)10;
+ tmp[wp++] = (char)('0' + a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Convert a string to a 64-bit integer
+UINT64 ToInt64(char *str)
+{
+ UINT len, i;
+ UINT64 ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+ if (c != ',')
+ {
+ if ('0' <= c && c <= '9')
+ {
+ ret = ret * (UINT64)10 + (UINT64)(c - '0');
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Check whether the str ends with the key
+bool EndWith(char *str, char *key)
+{
+ UINT str_len;
+ UINT key_len;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = StrLen(str);
+ key_len = StrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+
+ if (StrCmpi(str + (str_len - key_len), key) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Check whether the str starts with the key
+bool StartWith(char *str, char *key)
+{
+ UINT str_len;
+ UINT key_len;
+ char *tmp;
+ bool ret;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = StrLen(str);
+ key_len = StrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+ if (str_len == 0 || key_len == 0)
+ {
+ return false;
+ }
+ tmp = CopyStr(str);
+ tmp[key_len] = 0;
+
+ if (StrCmpi(tmp, key) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the binary data
+void PrintBin(void *data, UINT size)
+{
+ char *tmp;
+ UINT i;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ i = size * 3 + 1;
+ tmp = Malloc(i);
+ BinToStrEx(tmp, i, data, size);
+ Print("%s\n", tmp);
+ Free(tmp);
+}
+
+// Convert the string to a MAC address
+bool StrToMac(UCHAR *mac_address, char *str)
+{
+ BUF *b;
+ // Validate arguments
+ if (mac_address == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = StrToBin(str);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size != 6)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ Copy(mac_address, b->Buf, 6);
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Convert a hexadecimal string to a binary data
+BUF *StrToBin(char *str)
+{
+ BUF *b;
+ UINT len, i;
+ char tmp[3];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp[0] = 0;
+ b = NewBuf();
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+ c = ToUpper(c);
+ if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))
+ {
+ if (tmp[0] == 0)
+ {
+ tmp[0] = c;
+ tmp[1] = 0;
+ }
+ else if (tmp[1] == 0)
+ {
+ UCHAR data;
+ char tmp2[64];
+ tmp[1] = c;
+ tmp[2] = 0;
+ StrCpy(tmp2, sizeof(tmp2), "0x");
+ StrCat(tmp2, sizeof(tmp2), tmp);
+ data = (UCHAR)strtoul(tmp2, NULL, 0);
+ WriteBuf(b, &data, 1);
+ Zero(tmp, sizeof(tmp));
+ }
+ }
+ else if (c == ' ' || c == ',' || c == '-' || c == ':')
+ {
+ // Do Nothing
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return b;
+}
+
+// Convert the binary data to a hexadecimal string (with space)
+void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 3 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ Format(&tmp[i * 3], 0, "%02X ", buf[i]);
+ }
+ Trim(tmp);
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 3 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char);
+ }
+ if (StrLen(tmp) >= 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == padding_char)
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+// Convert the binary data to a string, and copy it
+char *CopyBinToStrEx(void *data, UINT data_size)
+{
+ char *ret;
+ UINT size;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ size = data_size * 3 + 1;
+ ret = ZeroMalloc(size);
+
+ BinToStrEx(ret, size, data, data_size);
+
+ return ret;
+}
+char *CopyBinToStr(void *data, UINT data_size)
+{
+ char *ret;
+ UINT size;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ size = data_size * 2 + 1;
+ ret = ZeroMalloc(size);
+
+ BinToStr(ret, size, data, data_size);
+
+ return ret;
+}
+
+// Convert the binary data to a hexadecimal string
+void BinToStr(char *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ if (str != NULL)
+ {
+ str[0] = 0;
+ }
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 2 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ sprintf(&tmp[i * 2], "%02X", buf[i]);
+ }
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ if (str != NULL)
+ {
+ str[0] = 0;
+ }
+ return;
+ }
+
+ tmp_size = (data_size * 2 + 4) * sizeof(wchar_t);
+ tmp = ZeroMalloc(tmp_size);
+
+ BinToStr(tmp, tmp_size, data, data_size);
+
+ StrToUni(str, str_size, tmp);
+
+ Free(tmp);
+}
+
+// Convert a 160-bit sequence into a string
+void Bit160ToStr(char *str, UCHAR *data)
+{
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Format(str, 0,
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
+ data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19]);
+}
+
+// Make a string from a 128-bit sequence
+void Bit128ToStr(char *str, UCHAR *data)
+{
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Format(str, 0,
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
+ data[10], data[11], data[12], data[13], data[14], data[15]);
+}
+
+// Copy a string
+char *CopyStr(char *str)
+{
+ UINT len;
+ char *dst;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ dst = Malloc(len + 1);
+ StrCpy(dst, len + 1, str);
+ return dst;
+}
+
+// Check whether the string is safe
+bool IsSafeStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (IsSafeChar(str[i]) == false)
+ {
+ return false;
+ }
+ }
+ if (str[0] == ' ')
+ {
+ return false;
+ }
+ if (len != 0)
+ {
+ if (str[len - 1] == ' ')
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the character can be displayed
+bool IsPrintableAsciiChar(char c)
+{
+ UCHAR uc = (UCHAR)c;
+ if (uc <= 31)
+ {
+ return false;
+ }
+ if (uc >= 127)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Check whether the string that can be displayed
+bool IsPrintableAsciiStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (IsPrintableAsciiChar(c) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Convert a string to a displayable string
+void EnPrintableAsciiStr(char *str, char replace)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (IsPrintableAsciiChar(c) == false)
+ {
+ str[i] = replace;
+ }
+ }
+}
+
+// Check whether the character is safe
+bool IsSafeChar(char c)
+{
+ UINT i, len;
+ char *check_str =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ " ()-_#%&.";
+
+ len = StrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Remove the specified character from a string
+void TruncateCharFromStr(char *str, char replace)
+{
+ char *src,*dst;
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ src = dst = str;
+
+ while(*src != '\0')
+ {
+ if(*src != replace)
+ {
+ *dst = *src;
+ dst++;
+ }
+ src++;
+ }
+ *dst = *src;
+
+ //BUF *b = NewBuf();
+ //UINT i, len;
+ //char zero = 0;
+
+ //len = StrLen(str);
+ //for (i = 0;i < len;i++)
+ //{
+ // char c = str[i];
+
+ // if (c != replace)
+ // {
+ // WriteBuf(b, &c, 1);
+ // }
+ //}
+
+ //if (b->Size == 0)
+ //{
+ // char c = '_';
+ // WriteBuf(b, &c, 1);
+ //}
+
+ //WriteBuf(b, &zero, 1);
+
+ //StrCpy(str, 0, b->Buf);
+
+ //FreeBuf(b);
+}
+
+// Replace the unsafe characters
+void EnSafeStr(char *str, char replace)
+{
+ if (str == NULL)
+ {
+ return;
+ }
+
+ while(*str != '\0')
+ {
+ if(IsSafeChar(*str) == false)
+ {
+ *str = replace;
+ }
+ str++;
+ }
+}
+
+// Operation check of string library
+bool CheckStringLibrary()
+{
+ wchar_t *compare_str = L"TEST_TEST_123_123456789012345";
+ char *teststr = "TEST";
+ wchar_t *testunistr = L"TEST";
+ wchar_t tmp[64];
+ UINT i1 = 123;
+ UINT64 i2 = 123456789012345ULL;
+
+ UniFormat(tmp, sizeof(tmp), L"%S_%s_%u_%I64u", teststr, testunistr,
+ i1, i2);
+
+ if (UniStrCmpi(tmp, compare_str) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Initialize the string library
+void InitStringLibrary()
+{
+ // Create a lock for token
+ token_lock = NewLock();
+
+ // Initialization of the International Library
+ InitInternational();
+
+ // Operation check
+ if (CheckStringLibrary() == false)
+ {
+#ifdef OS_WIN32
+ Alert("String Library Init Failed.\r\nPlease check your locale settings.", NULL);
+#else // OS_WIN32
+ Alert("String Library Init Failed.\r\nPlease check your locale settings and iconv() libraries.", NULL);
+#endif // OS_WIN32
+ exit(0);
+ }
+}
+
+// Release of the string library
+void FreeStringLibrary()
+{
+ // Release of the International Library
+ FreeInternational();
+
+ // Release of the lock for token
+ DeleteLock(token_lock);
+ token_lock = NULL;
+}
+
+// String replaceing (case insensitive)
+UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
+{
+ return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
+}
+
+// String replaceing (case sensitive)
+UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
+{
+ return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
+}
+
+// String replaceing
+UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
+{
+ UINT i, j, num;
+ UINT len_string, len_old, len_new;
+ UINT len_ret;
+ UINT wp;
+ char *ret;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = StrLen(string);
+ len_old = StrLen(old_keyword);
+ len_new = StrLen(new_keyword);
+
+ // Calculate the final string length
+ len_ret = CalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
+ // Memory allocation
+ ret = Malloc(len_ret + 1);
+ ret[len_ret] = '\0';
+
+ // Search and Replace
+ i = 0;
+ j = 0;
+ num = 0;
+ wp = 0;
+ while (true)
+ {
+ i = SearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ Copy(ret + wp, string + j, len_string - j);
+ wp += len_string - j;
+ break;
+ }
+ num++;
+ Copy(ret + wp, string + j, i - j);
+ wp += i - j;
+ Copy(ret + wp, new_keyword, len_new);
+ wp += len_new;
+ i += len_old;
+ j = i;
+ }
+
+ // Copy of the search results
+ StrCpy(dst, size, ret);
+
+ // Memory release
+ Free(ret);
+
+ return num;
+}
+
+// Calculate the length of the result of string replacement
+UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
+{
+ UINT i, num;
+ UINT len_string, len_old, len_new;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = StrLen(string);
+ len_old = StrLen(old_keyword);
+ len_new = StrLen(new_keyword);
+
+ if (len_old == len_new)
+ {
+ return len_string;
+ }
+
+ // Search
+ num = 0;
+ i = 0;
+ while (true)
+ {
+ i = SearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ break;
+ }
+ i += len_old;
+ num++;
+ }
+
+ // Calculation
+ return len_string + len_new * num - len_old * num;
+}
+
+// Search for a string (distinguish between upper / lower case)
+UINT SearchStr(char *string, char *keyword, UINT start)
+{
+ return SearchStrEx(string, keyword, start, true);
+}
+
+// Search for a string (Don't distinguish between upper / lower case)
+UINT SearchStri(char *string, char *keyword, UINT start)
+{
+ return SearchStrEx(string, keyword, start, false);
+}
+
+// Examine whether the string contains the specified character
+bool InChar(char *string, char c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (string == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(string);
+
+ for (i = 0;i < len;i++)
+ {
+ if (string[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Return the position of the first found keyword in the string
+// (Found at first character: returns 0, Not found: returns INFINITE)
+UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive)
+{
+ UINT len_string, len_keyword;
+ UINT i;
+ char *cmp_string, *cmp_keyword;
+ bool found;
+ // Validate arguments
+ if (string == NULL || keyword == NULL)
+ {
+ return INFINITE;
+ }
+
+ // Get the length of string
+ len_string = StrLen(string);
+ if (len_string <= start)
+ {
+ // Value of start is invalid
+ return INFINITE;
+ }
+
+ // Get the length of the keyword
+ len_keyword = StrLen(keyword);
+ if (len_keyword == 0)
+ {
+ // There is no keyword in the string
+ return INFINITE;
+ }
+
+ if ((len_string - start) < len_keyword)
+ {
+ // The keyword is longer than the string
+ return INFINITE;
+ }
+
+ if (case_sensitive)
+ {
+ cmp_string = string;
+ cmp_keyword = keyword;
+ }
+ else
+ {
+ cmp_string = Malloc(len_string + 1);
+ StrCpy(cmp_string, len_string + 1, string);
+ cmp_keyword = Malloc(len_keyword + 1);
+ StrCpy(cmp_keyword, len_keyword + 1, keyword);
+ StrUpper(cmp_string);
+ StrUpper(cmp_keyword);
+ }
+
+ // Search
+ found = false;
+ for (i = start;i < (len_string - len_keyword + 1);i++)
+ {
+ // Compare
+ if (!strncmp(&cmp_string[i], cmp_keyword, len_keyword))
+ {
+ // Found
+ found = true;
+ break;
+ }
+ }
+
+ if (case_sensitive == false)
+ {
+ // Memory release
+ Free(cmp_keyword);
+ Free(cmp_string);
+ }
+
+ if (found == false)
+ {
+ return INFINITE;
+ }
+ return i;
+}
+
+// Determine whether the specified character is in the token list
+bool IsInToken(TOKEN_LIST *t, char *str)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (StrCmpi(t->Token[i], str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Release of the token list
+void FreeToken(TOKEN_LIST *tokens)
+{
+ UINT i;
+ if (tokens == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < tokens->NumTokens;i++)
+ {
+ if (tokens->Token[i] != 0)
+ {
+ Free(tokens->Token[i]);
+ }
+ }
+ Free(tokens->Token);
+ Free(tokens);
+}
+
+// Parse the token
+TOKEN_LIST *ParseToken(char *src, char *separator)
+{
+ TOKEN_LIST *ret;
+ char *tmp;
+ char *str1, *str2;
+ UINT len;
+ UINT num;
+ if (src == NULL)
+ {
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+ if (separator == NULL)
+ {
+ separator = " ,\t\r\n";
+ }
+ len = StrLen(src);
+ str1 = Malloc(len + 1);
+ str2 = Malloc(len + 1);
+ StrCpy(str1, 0, src);
+ StrCpy(str2, 0, src);
+
+ Lock(token_lock);
+ {
+ tmp = strtok(str1, separator);
+ num = 0;
+ while (tmp != NULL)
+ {
+ num++;
+ tmp = strtok(NULL, separator);
+ }
+ ret = Malloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = (char **)Malloc(sizeof(char *) * num);
+ num = 0;
+ tmp = strtok(str2, separator);
+ while (tmp != NULL)
+ {
+ ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1);
+ StrCpy(ret->Token[num], 0, tmp);
+ num++;
+ tmp = strtok(NULL, separator);
+ }
+ }
+ Unlock(token_lock);
+
+ Free(str1);
+ Free(str2);
+ return ret;
+}
+
+// Get a line from standard input
+bool GetLine(char *str, UINT size)
+{
+ bool ret;
+ wchar_t *unistr;
+ UINT unistr_size = (size + 1) * sizeof(wchar_t);
+
+ unistr = Malloc(unistr_size);
+
+ ret = UniGetLine(unistr, unistr_size);
+
+ UniToStr(str, size, unistr);
+
+ Free(unistr);
+
+ return ret;
+}
+
+// Remove '\r' and '\n' at the end
+void TrimCrlf(char *str)
+{
+ UINT len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (str[len - 1] == '\n')
+ {
+ if (len >= 2 && str[len - 2] == '\r')
+ {
+ str[len - 2] = 0;
+ }
+ str[len - 1] = 0;
+ }
+ else if (str[len - 1] == '\r')
+ {
+ str[len - 1] = 0;
+ }
+}
+
+// Remove white spaces of the both side of the string
+void Trim(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Trim on the left side
+ TrimLeft(str);
+
+ // Trim on the right side
+ TrimRight(str);
+}
+
+// Remove white spaces on the right side of the string
+void TrimRight(char *str)
+{
+ char *buf, *tmp;
+ UINT len, i, wp, wp2;
+ BOOL flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[len - 1] != ' ' && str[len - 1] != '\t')
+ {
+ return;
+ }
+
+ buf = Malloc(len + 1);
+ tmp = Malloc(len + 1);
+ flag = FALSE;
+ wp = 0;
+ wp2 = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != ' ' && str[i] != '\t')
+ {
+ Copy(buf + wp, tmp, wp2);
+ wp += wp2;
+ wp2 = 0;
+ buf[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp2++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ StrCpy(str, 0, buf);
+ Free(buf);
+ Free(tmp);
+}
+
+// Remove white spaces from the left side of the string
+void TrimLeft(char *str)
+{
+ char *buf;
+ UINT len, i, wp;
+ BOOL flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[0] != ' ' && str[0] != '\t')
+ {
+ return;
+ }
+
+ buf = Malloc(len + 1);
+ flag = FALSE;
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != ' ' && str[i] != '\t')
+ {
+ flag = TRUE;
+ }
+ if (flag)
+ {
+ buf[wp++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ StrCpy(str, 0, buf);
+ Free(buf);
+}
+
+// Convert an integer to a hexadecimal string (8-digit fixed)
+void ToStrx8(char *str, UINT i)
+{
+ sprintf(str, "0x%08x", i);
+}
+
+// Convert an integer to a hexadecimal string
+void ToStrx(char *str, UINT i)
+{
+ sprintf(str, "0x%02x", i);
+}
+
+// Convert a signed integer to a string
+void ToStri(char *str, int i)
+{
+ sprintf(str, "%i", i);
+}
+
+// Convert an integer to a string
+void ToStr(char *str, UINT i)
+{
+ sprintf(str, "%u", i);
+}
+
+// Convert the string to a signed integer
+int ToInti(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return (int)ToInt(str);
+}
+
+// Convert a string to a Boolean value
+bool ToBool(char *str)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ if (ToInt(tmp) != 0)
+ {
+ return true;
+ }
+
+ if (StartWith("true", tmp))
+ {
+ return true;
+ }
+
+ if (StartWith("yes", tmp))
+ {
+ return true;
+ }
+
+ if (StartWith(tmp, "true"))
+ {
+ return true;
+ }
+
+ if (StartWith(tmp, "yes"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Convert a string to an integer
+UINT ToInt(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // Ignore the octal literal
+ while (true)
+ {
+ if (*str != '0')
+ {
+ break;
+ }
+ if ((*(str + 1) == 'x') || (*(str + 1) == 'X'))
+ {
+ break;
+ }
+ str++;
+ }
+
+ return (UINT)strtoul(str, NULL, 0);
+}
+
+// Replace a format string for 64-bit integer
+char *ReplaceFormatStringFor64(char *fmt)
+{
+ char *tmp;
+ char *ret;
+ UINT tmp_size;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = StrSize(fmt) * 2;
+ tmp = ZeroMalloc(tmp_size);
+
+#ifdef OS_WIN32
+ ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false);
+#else // OS_WIN32
+ ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false);
+#endif // OS_WIN32
+
+ ret = CopyStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the string on the screen
+void PrintStr(char *str)
+{
+ wchar_t *unistr = NULL;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_UNIX
+ fputs(str, stdout);
+#else // OS_UNIX
+ unistr = CopyStrToUni(str);
+ UniPrintStr(unistr);
+ Free(unistr);
+#endif // OS_UNIX
+}
+
+// Display a string with arguments
+void PrintArgs(char *fmt, va_list args)
+{
+ wchar_t *ret;
+ wchar_t *fmt_wchar;
+ char *tmp;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ fmt_wchar = CopyStrToUni(fmt);
+ ret = InternalFormatArgs(fmt_wchar, args, true);
+
+ tmp = CopyUniToStr(ret);
+ PrintStr(tmp);
+ Free(tmp);
+
+ Free(ret);
+ Free(fmt_wchar);
+}
+
+// Display a string
+void Print(char *fmt, ...)
+{
+ va_list args;
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ PrintArgs(fmt, args);
+ va_end(args);
+}
+
+// Display a debug string with arguments
+void DebugArgs(char *fmt, va_list args)
+{
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ PrintArgs(fmt, args);
+}
+
+// Display a debug string
+void Debug(char *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+
+ DebugArgs(fmt, args);
+
+ va_end(args);
+}
+
+// Format the string, and return the result
+char *CopyFormat(char *fmt, ...)
+{
+ char *buf;
+ char *ret;
+ UINT size;
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(StrSize(fmt) * 10, MAX_SIZE * 10);
+ buf = Malloc(size);
+
+ va_start(args, fmt);
+ FormatArgs(buf, size, fmt, args);
+
+ ret = CopyStr(buf);
+ Free(buf);
+
+ va_end(args);
+ return ret;
+}
+
+// Format the string
+void Format(char *buf, UINT size, char *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ FormatArgs(buf, size, fmt, args);
+ va_end(args);
+}
+
+// Format the string (argument list)
+void FormatArgs(char *buf, UINT size, char *fmt, va_list args)
+{
+ wchar_t *tag;
+ wchar_t *ret;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ tag = CopyStrToUni(fmt);
+ ret = InternalFormatArgs(tag, args, true);
+
+ UniToStr(buf, size, ret);
+ Free(ret);
+ Free(tag);
+}
+
+// Compare the strings in case-insensitive mode
+int StrCmpi(char *str1, char *str2)
+{
+ UINT i;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ // String comparison
+ i = 0;
+ while (true)
+ {
+ char c1, c2;
+ c1 = ToUpper(str1[i]);
+ c2 = ToUpper(str2[i]);
+ if (c1 > c2)
+ {
+ return 1;
+ }
+ else if (c1 < c2)
+ {
+ return -1;
+ }
+ if (str1[i] == 0 || str2[i] == 0)
+ {
+ return 0;
+ }
+ i++;
+ }
+}
+
+// Compare the string
+int StrCmp(char *str1, char *str2)
+{
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ return strcmp(str1, str2);
+}
+
+// Uncapitalize the string
+void StrLower(char *str)
+{
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = ToLower(str[i]);
+ }
+}
+
+// Capitalize the string
+void StrUpper(char *str)
+{
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = ToUpper(str[i]);
+ }
+}
+
+// Uncapitalize a character
+char ToLower(char c)
+{
+ if ('A' <= c && c <= 'Z')
+ {
+ c += 'z' - 'Z';
+ }
+ return c;
+}
+
+// Capitalize a character
+char ToUpper(char c)
+{
+ if ('a' <= c && c <= 'z')
+ {
+ c += 'Z' - 'z';
+ }
+ return c;
+}
+
+// Combine the string
+UINT StrCat(char *dst, UINT size, char *src)
+{
+ UINT len1, len2, len_test;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_STRCAT_COUNT);
+
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x7fffffff;
+ }
+
+ len1 = StrLen(dst);
+ len2 = StrLen(src);
+ len_test = len1 + len2 + 1;
+ if (len_test > size)
+ {
+ if (len2 <= (len_test - size))
+ {
+ return 0;
+ }
+ len2 -= len_test - size;
+ }
+ Copy(dst + len1, src, len2);
+ dst[len1 + len2] = 0;
+
+ return len1 + len2;
+}
+UINT StrCatLeft(char *dst, UINT size, char *src)
+{
+ char *s;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ s = CopyStr(dst);
+ StrCpy(dst, size, src);
+ StrCat(dst, size, s);
+
+ Free(s);
+
+ return StrLen(dst);
+}
+
+// Copy a string
+UINT StrCpy(char *dst, UINT size, char *src)
+{
+ UINT len;
+ // Validate arguments
+ if (dst == src)
+ {
+ return StrLen(src);
+ }
+ if (dst == NULL || src == NULL)
+ {
+ if (src == NULL && dst != NULL)
+ {
+ if (size >= 1)
+ {
+ dst[0] = '\0';
+ }
+ }
+ return 0;
+ }
+ if (size == 1)
+ {
+ dst[0] = '\0';
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x7fffffff;
+ }
+
+ // Check the length
+ len = StrLen(src);
+ if (len <= (size - 1))
+ {
+ Copy(dst, src, len + 1);
+ }
+ else
+ {
+ len = size - 1;
+ Copy(dst, src, len);
+ dst[len] = '\0';
+ }
+
+ // KS
+ KS_INC(KS_STRCPY_COUNT);
+
+ return len;
+}
+
+// Check whether the string buffer is within the specified size
+bool StrCheckSize(char *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ return StrCheckLen(str, size - 1);
+}
+
+// Make sure that the string is within the specified length
+bool StrCheckLen(char *str, UINT len)
+{
+ UINT count = 0;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_STRCHECK_COUNT);
+
+ for (i = 0;;i++)
+ {
+ if (str[i] == '\0')
+ {
+ return true;
+ }
+ count++;
+ if (count > len)
+ {
+ return false;
+ }
+ }
+}
+
+// Get the memory size needed to store the string
+UINT StrSize(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return StrLen(str) + 1;
+}
+
+// Get the length of the string
+UINT StrLen(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_STRLEN_COUNT);
+
+ return (UINT)strlen(str);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Str.h b/src/Mayaqua/Str.h
new file mode 100644
index 00000000..bff89011
--- /dev/null
+++ b/src/Mayaqua/Str.h
@@ -0,0 +1,228 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Str.h
+// Header of Str.c
+
+#ifndef STR_H
+#define STR_H
+
+// String token
+struct TOKEN_LIST
+{
+ UINT NumTokens;
+ char **Token;
+};
+
+// INI_ENTRY
+struct INI_ENTRY
+{
+ char *Key;
+ char *Value;
+ wchar_t *UnicodeValue;
+};
+
+// Function prototype
+UINT StrLen(char *str);
+UINT StrSize(char *str);
+bool StrCheckLen(char *str, UINT len);
+bool StrCheckSize(char *str, UINT size);
+UINT StrCpy(char *dst, UINT size, char *src);
+UINT StrCat(char *dst, UINT size, char *src);
+UINT StrCatLeft(char *dst, UINT size, char *src);
+char ToLower(char c);
+char ToUpper(char c);
+void StrUpper(char *str);
+void StrLower(char *str);
+int StrCmp(char *str1, char *str2);
+int StrCmpi(char *str1, char *str2);
+void FormatArgs(char *buf, UINT size, char *fmt, va_list args);
+void Format(char *buf, UINT size, char *fmt, ...);
+char *CopyFormat(char *fmt, ...);
+void Print(char *fmt, ...);
+void PrintArgs(char *fmt, va_list args);
+void PrintStr(char *str);
+void Debug(char *fmt, ...);
+void DebugArgs(char *fmt, va_list args);
+UINT ToInt(char *str);
+bool ToBool(char *str);
+int ToInti(char *str);
+void ToStr(char *str, UINT i);
+void ToStri(char *str, int i);
+void ToStrx(char *str, UINT i);
+void ToStrx8(char *str, UINT i);
+void TrimCrlf(char *str);
+void Trim(char *str);
+void TrimRight(char *str);
+void TrimLeft(char *str);
+bool GetLine(char *str, UINT size);
+void FreeToken(TOKEN_LIST *tokens);
+bool IsInToken(TOKEN_LIST *t, char *str);
+TOKEN_LIST *ParseToken(char *src, char *separator);
+void InitStringLibrary();
+void FreeStringLibrary();
+bool CheckStringLibrary();
+bool InChar(char *string, char c);
+UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive);
+UINT SearchStri(char *string, char *keyword, UINT start);
+UINT SearchStr(char *string, char *keyword, UINT start);
+UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive);
+UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive);
+UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword);
+UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword);
+bool IsPrintableAsciiChar(char c);
+bool IsPrintableAsciiStr(char *str);
+void EnPrintableAsciiStr(char *str, char replace);
+bool IsSafeChar(char c);
+bool IsSafeStr(char *str);
+void EnSafeStr(char *str, char replace);
+void TruncateCharFromStr(char *str, char replace);
+char *CopyStr(char *str);
+void BinToStr(char *str, UINT str_size, void *data, UINT data_size);
+void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size);
+void PrintBin(void *data, UINT size);
+bool StartWith(char *str, char *key);
+bool EndWith(char *str, char *key);
+UINT64 ToInt64(char *str);
+void ToStr64(char *str, UINT64 value);
+char *ReplaceFormatStringFor64(char *fmt);
+TOKEN_LIST *ParseCmdLine(char *str);
+TOKEN_LIST *CopyToken(TOKEN_LIST *src);
+TOKEN_LIST *NullToken();
+bool IsNum(char *str);
+LIST *StrToStrList(char *str, UINT size);
+BUF *StrListToStr(LIST *o);
+void FreeStrList(LIST *o);
+TOKEN_LIST *ListToTokenList(LIST *o);
+LIST *TokenListToList(TOKEN_LIST *t);
+bool IsEmptyStr(char *str);
+void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size);
+void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char);
+char *CopyBinToStrEx(void *data, UINT data_size);
+char *CopyBinToStr(void *data, UINT data_size);
+BUF *StrToBin(char *str);
+void MacToStr(char *str, UINT size, UCHAR *mac_address);
+void ToStr3(char *str, UINT size, UINT64 v);
+void ToStrByte(char *str, UINT size, UINT64 v);
+void ToStrByte1000(char *str, UINT size, UINT64 v);
+TOKEN_LIST *UniqueToken(TOKEN_LIST *t);
+char *NormalizeCrlf(char *str);
+bool IsAllUpperStr(char *str);
+UINT StrWidth(char *str);
+char *MakeCharArray(char c, UINT count);
+void MakeCharArray2(char *str, char c, UINT count);
+bool StrToMac(UCHAR *mac_address, char *str);
+bool IsSplitChar(char c, char *split_str);
+bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str);
+LIST *ReadIni(BUF *b);
+INI_ENTRY *GetIniEntry(LIST *o, char *key);
+void FreeIni(LIST *o);
+UINT IniIntValue(LIST *o, char *key);
+UINT64 IniInt64Value(LIST *o, char *key);
+char *IniStrValue(LIST *o, char *key);
+wchar_t *IniUniStrValue(LIST *o, char *key);
+bool IniHasValue(LIST *o, char *key);
+bool InStr(char *str, char *keyword);
+bool InStrEx(char *str, char *keyword, bool case_sensitive);
+bool InStrList(char *target_str, char *tokens, char *splitter, bool case_sensitive);
+TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars);
+TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars);
+char *DefaultTokenSplitChars();
+bool IsCharInStr(char *str, char c);
+UINT HexTo4Bit(char c);
+char FourBitToHex(UINT value);
+void ToHex(char *str, UINT value);
+void ToHex64(char *str, UINT64 value);
+UINT HexToInt(char *str);
+UINT64 HexToInt64(char *str);
+UINT SearchAsciiInBinary(void *data, UINT size, char *str, bool case_sensitive);
+bool IsStrInStrTokenList(char *str_list, char *str, char *split_chars, bool case_sensitive);
+void IntListToStr(char *str, UINT str_size, LIST *o, char *separate_str);
+LIST *StrToIntList(char *str, bool sorted);
+void NormalizeIntListStr(char *dst, UINT dst_size, char *src, bool sorted, char *separate_str);
+void ClearStr(char *str, UINT str_size);
+void SetStrCaseAccordingToBits(char *str, UINT bits);
+
+#endif // STR_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Table.c b/src/Mayaqua/Table.c
new file mode 100644
index 00000000..6cc3282b
--- /dev/null
+++ b/src/Mayaqua/Table.c
@@ -0,0 +1,1473 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Table.c
+// Read and management routines for string table
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// List of TABLE
+static LIST *TableList = NULL;
+static wchar_t old_table_name[MAX_SIZE] = {0}; // Old table name
+static LANGLIST current_lang = {0};
+static LANGLIST current_os_lang = {0};
+
+// Initialization of string table routine
+void InitTable()
+{
+ LIST *o;
+ char tmp[MAX_SIZE];
+ LANGLIST *e = NULL;
+ LANGLIST *os_lang = NULL;
+ char table_name[MAX_SIZE];
+ if (MayaquaIsMinimalMode())
+ {
+ // Not to load in case of minimum mode
+ return;
+ }
+
+ o = LoadLangList();
+ if (o == NULL)
+ {
+LABEL_FATAL_ERROR:
+ Alert("Fatal Error: The file \"hamcore.se2\" is missing or broken.\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)", NULL);
+ exit(-1);
+ return;
+ }
+
+ // Read the lang.config
+ if (LoadLangConfigCurrentDir(tmp, sizeof(tmp)))
+ {
+ e = GetBestLangByName(o, tmp);
+ }
+
+ os_lang = GetBestLangForCurrentEnvironment(o);
+
+ if (e == NULL)
+ {
+ e = os_lang;
+ }
+
+ if (e == NULL)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+
+ SaveLangConfigCurrentDir(e->Name);
+
+ Copy(&current_lang, e, sizeof(LANGLIST));
+ Copy(&current_os_lang, os_lang, sizeof(LANGLIST));
+
+ current_lang.LangList = current_lang.LcidList = NULL;
+ current_os_lang.LangList = current_os_lang.LcidList = NULL;
+
+ // Read the corresponding string table
+ Format(table_name, sizeof(table_name), "|strtable_%s.stb", current_lang.Name);
+ if (LoadTable(table_name) == false)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+
+ FreeLangList(o);
+}
+
+// Get the language of the current OS
+void GetCurrentOsLang(LANGLIST *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Copy(e, &current_os_lang, sizeof(LANGLIST));
+}
+
+// Get the language ID of the current OS
+UINT GetCurrentOsLangId()
+{
+ LANGLIST e;
+
+ Zero(&e, sizeof(e));
+
+ GetCurrentOsLang(&e);
+
+ return e.Id;
+}
+
+// Get the current language
+void GetCurrentLang(LANGLIST *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Copy(e, &current_lang, sizeof(LANGLIST));
+}
+
+// Get the current language ID
+UINT GetCurrentLangId()
+{
+ LANGLIST e;
+
+ Zero(&e, sizeof(e));
+
+ GetCurrentLang(&e);
+
+ return e.Id;
+}
+
+// Write to the lang.config file in the current directory
+bool SaveLangConfigCurrentDir(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return SaveLangConfig(LANG_CONFIG_FILENAME, str);
+}
+
+// Write to the lang.config file
+bool SaveLangConfig(wchar_t *filename, char *str)
+{
+ BUF *b;
+ LIST *o;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ // Read the template
+ b = ReadDump(LANG_CONFIG_TEMPLETE);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, b->Size, 0);
+
+ o = LoadLangList();
+ if (o != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ AppendBufStr(b, "# Available Language IDs are:\r\n");
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ UniFormat(tmp, sizeof(tmp), L"# %S: %s (%s)\r\n",
+ e->Name, e->TitleEnglish, e->TitleLocal);
+
+ AppendBufUtf8(b, tmp);
+ }
+
+ AppendBufStr(b, "\r\n\r\n# Specify a Language ID here.\r\n");
+ AppendBufStr(b, str);
+ AppendBufStr(b, "\r\n\r\n");
+
+ FreeLangList(o);
+ }
+
+ ret = DumpBufW(b, filename);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read the lang.config file in the current directory
+bool LoadLangConfigCurrentDir(char *str, UINT str_size)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return LoadLangConfig(LANG_CONFIG_FILENAME, str, str_size);
+}
+
+// Read the lang.config file
+bool LoadLangConfig(wchar_t *filename, char *str, UINT str_size)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (filename == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#") == false && StartWith(line, "//") == false && StartWith(line, ";") == false &&
+ InStr(line, "#") == false)
+ {
+ StrCpy(str, str_size, line);
+ ret = true;
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Choose the language from the ID
+LANGLIST *GetLangById(LIST *o, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (e->Id == id)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Choice the best language for the current environment
+LANGLIST *GetBestLangForCurrentEnvironment(LIST *o)
+{
+ LANGLIST *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ ret = GetBestLangByLcid(o, MsGetUserLocaleId());
+#else // OS_WIN32
+ if (true)
+ {
+ char lang[MAX_SIZE];
+
+ if (GetEnv("LANG", lang, sizeof(lang)))
+ {
+ ret = GetBestLangByLangStr(o, lang);
+ }
+ else
+ {
+ ret = GetBestLangByLangStr(o, "C");
+ }
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Search for the best language from LANG string of UNIX
+LANGLIST *GetBestLangByLangStr(LIST *o, char *str)
+{
+ UINT i;
+ LANGLIST *ret;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(e->LangList);j++)
+ {
+ char *v = LIST_DATA(e->LangList, j);
+
+ if (StrCmpi(v, str) == 0)
+ {
+ return e;
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(e->LangList);j++)
+ {
+ char *v = LIST_DATA(e->LangList, j);
+
+ if (StartWith(str, v) || StartWith(v, str))
+ {
+ return e;
+ }
+ }
+ }
+
+ ret = GetBestLangByName(o, "en");
+
+ return ret;
+}
+
+// Search for the best language from LCID
+LANGLIST *GetBestLangByLcid(LIST *o, UINT lcid)
+{
+ LANGLIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (IsIntInList(e->LcidList, lcid))
+ {
+ return e;
+ }
+ }
+
+ ret = GetBestLangByName(o, "en");
+
+ return ret;
+}
+
+// Search for the best language from the name
+LANGLIST *GetBestLangByName(LIST *o, char *name)
+{
+ UINT i;
+ LANGLIST *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (StrCmpi(e->Name, name) == 0)
+ {
+ ret = e;
+ break;
+ }
+ }
+
+ if (ret != NULL)
+ {
+ return ret;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (StartWith(e->Name, name) || StartWith(name, e->Name))
+ {
+ ret = e;
+ break;
+ }
+ }
+
+ if (ret != NULL)
+ {
+ return ret;
+ }
+
+ return ret;
+}
+
+// Release the language list
+void FreeLangList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ FreeStrList(e->LangList);
+ ReleaseIntList(e->LcidList);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Read the language list
+LIST *LoadLangList()
+{
+ LIST *o = NewListFast(NULL);
+ char *filename = LANGLIST_FILENAME;
+ BUF *b;
+
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false && StartWith(line, "#") == false)
+ {
+ TOKEN_LIST *t = ParseToken(line, "\t ");
+ if (t != NULL)
+ {
+ if (t->NumTokens == 6)
+ {
+ LANGLIST *e = ZeroMalloc(sizeof(LANGLIST));
+ TOKEN_LIST *t2;
+
+ e->Id = ToInt(t->Token[0]);
+ StrCpy(e->Name, sizeof(e->Name), t->Token[1]);
+ Utf8ToUni(e->TitleEnglish, sizeof(e->TitleEnglish), t->Token[2], StrLen(t->Token[2]));
+ Utf8ToUni(e->TitleLocal, sizeof(e->TitleLocal), t->Token[3], StrLen(t->Token[3]));
+
+ UniReplaceStrEx(e->TitleEnglish, sizeof(e->TitleEnglish), e->TitleEnglish,
+ L"_", L" ", true);
+
+ UniReplaceStrEx(e->TitleLocal, sizeof(e->TitleLocal), e->TitleLocal,
+ L"_", L" ", true);
+
+ e->LcidList = NewIntList(false);
+
+ t2 = ParseToken(t->Token[4], ",");
+ if (t2 != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t2->NumTokens;i++)
+ {
+ UINT id = ToInt(t2->Token[i]);
+
+ AddIntDistinct(e->LcidList, id);
+ }
+
+ FreeToken(t2);
+ }
+
+ e->LangList = NewListFast(NULL);
+
+ t2 = ParseToken(t->Token[5], ",");
+ if (t2 != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t2->NumTokens;i++)
+ {
+ Add(e->LangList, CopyStr(t2->Token[i]));
+ }
+
+ FreeToken(t2);
+ }
+
+ Add(o, e);
+ }
+
+ FreeToken(t);
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+
+ return o;
+}
+
+// Get an error string in Unicode
+wchar_t *GetUniErrorStr(UINT err)
+{
+ wchar_t *ret;
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "ERR_%u", err);
+
+ ret = GetTableUniStr(name);
+ if (UniStrLen(ret) != 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return _UU("ERR_UNKNOWN");
+ }
+}
+
+// Get an error string
+char *GetErrorStr(UINT err)
+{
+ char *ret;
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "ERR_%u", err);
+
+ ret = GetTableStr(name);
+ if (StrLen(ret) != 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return _SS("ERR_UNKNOWN");
+ }
+}
+
+// Load the integer value from the table
+UINT GetTableInt(char *name)
+{
+ char *str;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ str = GetTableStr(name);
+ return ToInt(str);
+}
+
+// Load a Unicode string from the table
+wchar_t *GetTableUniStr(char *name)
+{
+ TABLE *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+// Debug("%s: ************\n", name);
+ return L"";
+ }
+
+ // Search
+ t = FindTable(name);
+ if (t == NULL)
+ {
+ //Debug("%s: UNICODE STRING NOT FOUND\n", name);
+ return L"";
+ }
+
+ return t->unistr;
+}
+
+// Load the string from the table
+char *GetTableStr(char *name)
+{
+ TABLE *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return "";
+ }
+
+#ifdef OS_WIN32
+ if (StrCmpi(name, "DEFAULT_FONT") == 0)
+ {
+ if (_II("LANG") == 2)
+ {
+ UINT os_type = GetOsType();
+ if (OS_IS_WINDOWS_9X(os_type) ||
+ GET_KETA(os_type, 100) <= 4)
+ {
+ // Use the SimSun font in Windows 9x, Windows NT 4.0, Windows 2000, Windows XP, and Windows Server 2003
+ return "SimSun";
+ }
+ }
+ }
+#endif // OS_WIN32
+
+ // Search
+ t = FindTable(name);
+ if (t == NULL)
+ {
+ //Debug("%s: ANSI STRING NOT FOUND\n", name);
+ return "";
+ }
+
+ return t->str;
+}
+
+// Get the string name that begins with the specified name
+TOKEN_LIST *GetTableNameStartWith(char *str)
+{
+ UINT i;
+ UINT len;
+ LIST *o;
+ TOKEN_LIST *t;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ StrUpper(tmp);
+
+ len = StrLen(tmp);
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(TableList);i++)
+ {
+ TABLE *t = LIST_DATA(TableList, i);
+ UINT len2 = StrLen(t->name);
+
+ if (len2 >= len)
+ {
+ if (Cmp(t->name, tmp, len) == 0)
+ {
+ Insert(o, CopyStr(t->name));
+ }
+ }
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Search the table
+TABLE *FindTable(char *name)
+{
+ TABLE *t, tt;
+ // Validate arguments
+ if (name == NULL || TableList == NULL)
+ {
+ return NULL;
+ }
+
+ tt.name = CopyStr(name);
+ t = Search(TableList, &tt);
+ Free(tt.name);
+
+ return t;
+}
+
+// A function that compares the table name
+int CmpTableName(void *p1, void *p2)
+{
+ TABLE *t1, *t2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ t1 = *(TABLE **)p1;
+ t2 = *(TABLE **)p2;
+ if (t1 == NULL || t2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(t1->name, t2->name);
+}
+
+// Interpret a line
+TABLE *ParseTableLine(char *line, char *prefix, UINT prefix_size, LIST *replace_list)
+{
+ UINT i, len;
+ UINT len_name;
+ UINT string_start;
+ char *name;
+ char *name2;
+ UINT name2_size;
+ wchar_t *unistr;
+ char *str;
+ UINT unistr_size, str_size;
+ TABLE *t;
+ // Validate arguments
+ if (line == NULL || prefix == NULL)
+ {
+ return NULL;
+ }
+ TrimLeft(line);
+
+ // No line
+ len = StrLen(line);
+ if (len == 0)
+ {
+ return NULL;
+ }
+
+ // Comment
+ if (line[0] == '#' || (line[0] == '/' && line[1] == '/'))
+ {
+ return NULL;
+ }
+
+ // Search to the end position of the name
+ len_name = 0;
+ for (i = 0;;i++)
+ {
+ if (line[i] == 0)
+ {
+ // There is only one token
+ return NULL;
+ }
+ if (line[i] == ' ' || line[i] == '\t')
+ {
+ break;
+ }
+ len_name++;
+ }
+
+ name = Malloc(len_name + 1);
+ StrCpy(name, len_name + 1, line);
+
+ string_start = len_name;
+ for (i = len_name;i < len;i++)
+ {
+ if (line[i] != ' ' && line[i] != '\t')
+ {
+ break;
+ }
+ string_start++;
+ }
+ if (i == len)
+ {
+ Free(name);
+ return NULL;
+ }
+
+ // Unescape
+ UnescapeStr(&line[string_start]);
+
+ // Convert to Unicode
+ unistr_size = CalcUtf8ToUni(&line[string_start], StrLen(&line[string_start]));
+ if (unistr_size == 0)
+ {
+ Free(name);
+ return NULL;
+ }
+ unistr = Malloc(unistr_size);
+ Utf8ToUni(unistr, unistr_size, &line[string_start], StrLen(&line[string_start]));
+
+ if (UniInChar(unistr, L'$'))
+ {
+ // Replace the replacement string
+ wchar_t *tmp;
+ UINT tmp_size = (UniStrSize(unistr) + 1024) * 2;
+ UINT i;
+
+ tmp = Malloc(tmp_size);
+
+ UniStrCpy(tmp, tmp_size, unistr);
+
+ for (i = 0; i < LIST_NUM(replace_list);i++)
+ {
+ TABLE *r = LIST_DATA(replace_list, i);
+
+ UniReplaceStrEx(tmp, tmp_size, tmp, (wchar_t *)r->name, r->unistr, false);
+ }
+
+ unistr = CopyUniStr(tmp);
+
+ Free(tmp);
+ }
+
+ // Convert to ANSI
+ str_size = CalcUniToStr(unistr);
+ if (str_size == 0)
+ {
+ str_size = 1;
+ str = Malloc(1);
+ str[0] = 0;
+ }
+ else
+ {
+ str = Malloc(str_size);
+ UniToStr(str, str_size, unistr);
+ }
+
+ if (StrCmpi(name, "PREFIX") == 0)
+ {
+ // Prefix is specified
+ StrCpy(prefix, prefix_size, str);
+ Trim(prefix);
+
+ if (StrCmpi(prefix, "$") == 0 || StrCmpi(prefix, "NULL") == 0)
+ {
+ prefix[0] = 0;
+ }
+
+ Free(name);
+ Free(str);
+ Free(unistr);
+
+ return NULL;
+ }
+
+ name2_size = StrLen(name) + StrLen(prefix) + 2;
+ name2 = ZeroMalloc(name2_size);
+
+ if (prefix[0] != 0)
+ {
+ StrCat(name2, name2_size, prefix);
+ StrCat(name2, name2_size, "@");
+ }
+
+ StrCat(name2, name2_size, name);
+
+ Free(name);
+
+ // Create a TABLE
+ t = Malloc(sizeof(TABLE));
+ StrUpper(name2);
+ t->name = name2;
+ t->str = str;
+ t->unistr = unistr;
+
+ return t;
+}
+
+// Unescape the string
+void UnescapeStr(char *src)
+{
+ UINT i, len, wp;
+ char *tmp;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(src);
+ tmp = Malloc(len + 1);
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (src[i] == '\\')
+ {
+ i++;
+ switch (src[i])
+ {
+ case 0:
+ goto FINISH;
+ case '\\':
+ tmp[wp++] = '\\';
+ break;
+ case ' ':
+ tmp[wp++] = ' ';
+ break;
+ case 'n':
+ case 'N':
+ tmp[wp++] = '\n';
+ break;
+ case 'r':
+ case 'R':
+ tmp[wp++] = '\r';
+ break;
+ case 't':
+ case 'T':
+ tmp[wp++] = '\t';
+ break;
+ }
+ }
+ else
+ {
+ tmp[wp++] = src[i];
+ }
+ }
+FINISH:
+ tmp[wp++] = 0;
+ StrCpy(src, 0, tmp);
+ Free(tmp);
+}
+
+// Release the table
+void FreeTable()
+{
+ UINT i, num;
+ TABLE **tables;
+ if (TableList == NULL)
+ {
+ return;
+ }
+
+ TrackingDisable();
+
+ num = LIST_NUM(TableList);
+ tables = ToArray(TableList);
+ for (i = 0;i < num;i++)
+ {
+ TABLE *t = tables[i];
+ Free(t->name);
+ Free(t->str);
+ Free(t->unistr);
+ Free(t);
+ }
+ ReleaseList(TableList);
+ TableList = NULL;
+ Free(tables);
+
+ Zero(old_table_name, sizeof(old_table_name));
+
+ TrackingEnable();
+}
+
+// Read a string table from the buffer
+bool LoadTableFromBuf(BUF *b)
+{
+ char *tmp;
+ char prefix[MAX_SIZE];
+ LIST *replace_list = NULL;
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ // If the table already exists, delete it
+ FreeTable();
+
+ // Create a list
+ TableList = NewList(CmpTableName);
+
+ Zero(prefix, sizeof(prefix));
+
+ replace_list = NewListFast(NULL);
+
+ // Read the contents of the buffer line by line
+ while (true)
+ {
+ TABLE *t;
+ bool ok = true;
+
+ tmp = CfgReadNextLine(b);
+ if (tmp == NULL)
+ {
+ break;
+ }
+
+ if (tmp[0] == '$')
+ {
+ char key[128];
+ char value[MAX_SIZE];
+ if (GetKeyAndValue(tmp, key, sizeof(key), value, sizeof(value), " \t"))
+ {
+ if (StartWith(key, "$") && EndWith(key, "$") && StrLen(key) >= 3)
+ {
+ TABLE *t;
+ wchar_t univalue[MAX_SIZE];
+ wchar_t uniname[MAX_SIZE];
+
+ t = ZeroMalloc(sizeof(TABLE));
+
+ Zero(univalue, sizeof(univalue));
+ Utf8ToUni(univalue, sizeof(univalue), value, StrLen(value));
+
+ StrToUni(uniname, sizeof(uniname), key);
+
+ t->name = (char *)CopyUniStr(uniname);
+ t->unistr = CopyUniStr(univalue);
+
+ Add(replace_list, t);
+
+ // Found a replacement definition
+ ok = false;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ t = ParseTableLine(tmp, prefix, sizeof(prefix), replace_list);
+ if (t != NULL)
+ {
+ // Register
+ Insert(TableList, t);
+ }
+ }
+
+ Free(tmp);
+ }
+
+ for (i = 0;i < LIST_NUM(replace_list);i++)
+ {
+ TABLE *t = LIST_DATA(replace_list, i);
+
+ Free(t->name);
+ Free(t->str);
+ Free(t->unistr);
+
+ Free(t);
+ }
+
+ ReleaseList(replace_list);
+
+ return true;
+}
+
+// Generate the Unicode string cache file name
+void GenerateUnicodeCacheFileName(wchar_t *name, UINT size, wchar_t *strfilename, UINT strfilesize, UCHAR *filehash)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t hashstr[64];
+ wchar_t hashtemp[MAX_SIZE];
+ wchar_t exe[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL || strfilename == NULL || filehash == NULL)
+ {
+ return;
+ }
+
+ GetExeDirW(exe, sizeof(exe));
+ UniStrCpy(hashtemp, sizeof(hashtemp), strfilename);
+ BinToStrW(tmp, sizeof(tmp), filehash, MD5_SIZE);
+ UniStrCat(hashtemp, sizeof(hashtemp), tmp);
+ UniStrCat(hashtemp, sizeof(hashtemp), exe);
+ UniStrLower(hashtemp);
+
+ Hash(hash, hashtemp, UniStrLen(hashtemp) * sizeof(wchar_t), true);
+ BinToStrW(hashstr, sizeof(hashstr), hash, 4);
+ UniFormat(tmp, sizeof(tmp), UNICODE_CACHE_FILE, hashstr);
+ UniStrLower(tmp);
+
+#ifndef OS_WIN32
+ UniStrCpy(exe, sizeof(exe), L"/tmp");
+#else // OS_WIN32
+ StrToUni(exe, sizeof(exe), MsGetTempDir());
+#endif // OS_WIN32
+
+ UniFormat(name, size, L"%s/%s", exe, tmp);
+ NormalizePathW(name, size, name);
+}
+
+// Save the Unicode cache
+void SaveUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash)
+{
+ UNICODE_CACHE c;
+ BUF *b;
+ UINT i;
+ IO *io;
+ wchar_t name[MAX_PATH];
+ UCHAR binhash[MD5_SIZE];
+ // Validate arguments
+ if (strfilename == NULL || hash == NULL)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+ UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename);
+ c.StrFileSize = strfilesize;
+ GetMachineName(c.MachineName, sizeof(c.MachineName));
+ c.OsType = GetOsInfo()->OsType;
+ Copy(c.hash, hash, MD5_SIZE);
+
+#ifdef OS_UNIX
+ GetCurrentCharSet(c.CharSet, sizeof(c.CharSet));
+#else // OS_UNIX
+ {
+ UINT id = MsGetThreadLocale();
+ Copy(c.CharSet, &id, sizeof(id));
+ }
+#endif // OS_UNIX
+
+ b = NewBuf();
+ WriteBuf(b, &c, sizeof(c));
+
+ WriteBufInt(b, LIST_NUM(TableList));
+ for (i = 0;i < LIST_NUM(TableList);i++)
+ {
+ TABLE *t = LIST_DATA(TableList, i);
+ WriteBufInt(b, StrLen(t->name));
+ WriteBuf(b, t->name, StrLen(t->name));
+ WriteBufInt(b, StrLen(t->str));
+ WriteBuf(b, t->str, StrLen(t->str));
+ WriteBufInt(b, UniStrLen(t->unistr));
+ WriteBuf(b, t->unistr, UniStrLen(t->unistr) * sizeof(wchar_t));
+ }
+
+ Hash(binhash, b->Buf, b->Size, false);
+ WriteBuf(b, binhash, MD5_SIZE);
+
+ GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash);
+
+ io = FileCreateW(name);
+ if (io != NULL)
+ {
+ SeekBuf(b, 0, 0);
+ BufToFile(io, b);
+ FileClose(io);
+ }
+
+ FreeBuf(b);
+}
+
+// Reading the Unicode cache
+bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash)
+{
+ UNICODE_CACHE c, t;
+ BUF *b;
+ UINT i, num;
+ IO *io;
+ wchar_t name[MAX_PATH];
+ UCHAR binhash[MD5_SIZE];
+ UCHAR binhash_2[MD5_SIZE];
+ // Validate arguments
+ if (strfilename == NULL || hash == NULL)
+ {
+ return false;
+ }
+
+ GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash);
+
+ io = FileOpenW(name, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ b = FileToBuf(io);
+ if (b == NULL)
+ {
+ FileClose(io);
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+ FileClose(io);
+
+ Hash(binhash, b->Buf, b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0, false);
+ Copy(binhash_2, ((UCHAR *)b->Buf) + (b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0), MD5_SIZE);
+ if (Cmp(binhash, binhash_2, MD5_SIZE) != 0)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ Zero(&c, sizeof(c));
+ UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename);
+ c.StrFileSize = strfilesize;
+ DisableNetworkNameCache();
+ GetMachineName(c.MachineName, sizeof(c.MachineName));
+ EnableNetworkNameCache();
+ c.OsType = GetOsInfo()->OsType;
+ Copy(c.hash, hash, MD5_SIZE);
+
+#ifdef OS_UNIX
+ GetCurrentCharSet(c.CharSet, sizeof(c.CharSet));
+#else // OS_UNIX
+ {
+ UINT id = MsGetThreadLocale();
+ Copy(c.CharSet, &id, sizeof(id));
+ }
+#endif // OS_UNIX
+
+ Zero(&t, sizeof(t));
+ ReadBuf(b, &t, sizeof(t));
+
+ if (Cmp(&c, &t, sizeof(UNICODE_CACHE)) != 0)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ num = ReadBufInt(b);
+
+ FreeTable();
+ TableList = NewList(CmpTableName);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT len;
+ TABLE *t = ZeroMalloc(sizeof(TABLE));
+
+ len = ReadBufInt(b);
+ t->name = ZeroMalloc(len + 1);
+ ReadBuf(b, t->name, len);
+
+ len = ReadBufInt(b);
+ t->str = ZeroMalloc(len + 1);
+ ReadBuf(b, t->str, len);
+
+ len = ReadBufInt(b);
+ t->unistr = ZeroMalloc((len + 1) * sizeof(wchar_t));
+ ReadBuf(b, t->unistr, len * sizeof(wchar_t));
+
+ Add(TableList, t);
+ }
+
+ FreeBuf(b);
+
+ Sort(TableList);
+
+ return true;
+}
+
+// Read the string table
+bool LoadTableMain(wchar_t *filename)
+{
+ BUF *b;
+ UINT64 t1, t2;
+ UCHAR hash[MD5_SIZE];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ if (MayaquaIsMinimalMode())
+ {
+ return true;
+ }
+
+ if (UniStrCmpi(old_table_name, filename) == 0)
+ {
+ // Already loaded
+ return true;
+ }
+
+ t1 = Tick64();
+
+ // Open the file
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ char tmp[MAX_SIZE];
+ StrCpy(tmp, sizeof(tmp), "Error: Can't read string tables (file not found).\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)");
+ Alert(tmp, NULL);
+ exit(-1);
+ return false;
+ }
+
+ Hash(hash, b->Buf, b->Size, false);
+
+ if (LoadUnicodeCache(filename, b->Size, hash) == false)
+ {
+ if (LoadTableFromBuf(b) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ SaveUnicodeCache(filename, b->Size, hash);
+
+ Debug("Unicode Source: strtable.stb\n");
+ }
+ else
+ {
+ Debug("Unicode Source: unicode_cache\n");
+ }
+
+ FreeBuf(b);
+
+ SetLocale(_UU("DEFAULE_LOCALE"));
+
+ UniStrCpy(old_table_name, sizeof(old_table_name), filename);
+
+ t2 = Tick64();
+
+ if (StrCmpi(_SS("STRTABLE_ID"), STRTABLE_ID) != 0)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "Error: Can't read string tables (invalid version: '%s'!='%s').\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)",
+ _SS("STRTABLE_ID"), STRTABLE_ID);
+ Alert(tmp, NULL);
+ exit(-1);
+ return false;
+ }
+
+ Debug("Unicode File Read Cost: %u (%u Lines)\n", (UINT)(t2 - t1), LIST_NUM(TableList));
+
+ return true;
+}
+bool LoadTable(char *filename)
+{
+ wchar_t *filename_a = CopyStrToUni(filename);
+ bool ret = LoadTableW(filename_a);
+
+ Free(filename_a);
+
+ return ret;
+}
+bool LoadTableW(wchar_t *filename)
+{
+ bool ret;
+ BUF *b;
+ wchar_t replace_name[MAX_PATH];
+
+ Zero(replace_name, sizeof(replace_name));
+
+ TrackingDisable();
+
+ b = ReadDump("@table_name.txt");
+ if (b != NULL)
+ {
+ char *s = CfgReadNextLine(b);
+ if (s != NULL)
+ {
+ if (IsEmptyStr(s) == false)
+ {
+ StrToUni(replace_name, sizeof(replace_name), s);
+ filename = replace_name;
+ }
+
+ Free(s);
+ }
+ FreeBuf(b);
+ }
+
+ ret = LoadTableMain(filename);
+
+ TrackingEnable();
+
+ return ret;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Table.h b/src/Mayaqua/Table.h
new file mode 100644
index 00000000..b7a0e64d
--- /dev/null
+++ b/src/Mayaqua/Table.h
@@ -0,0 +1,186 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Table.h
+// Header of Table.c
+
+#ifndef TABLE_H
+#define TABLE_H
+
+#define UNICODE_CACHE_FILE L".unicode_cache_%s.dat"
+
+#define LANGLIST_FILENAME "|languages.txt"
+#define LANG_CONFIG_FILENAME L"@lang.config"
+#define LANG_CONFIG_TEMPLETE "|lang.config"
+
+// Language constant
+#define SE_LANG_JAPANESE 0 // Japanese
+#define SE_LANG_ENGLISH 1 // English
+#define SE_LANG_CHINESE_ZH 2 // Simplified Chinese
+
+
+// String table
+struct TABLE
+{
+ char *name;
+ char *str;
+ wchar_t *unistr;
+};
+
+// Unicode cache structure
+typedef struct UNICODE_CACHE
+{
+ char StrFileName[256]; // String file name
+ UINT StrFileSize; // String file size
+ char MachineName[256]; // Machine name
+ UINT OsType; // OS type
+ UCHAR hash[MD5_SIZE]; // Hash
+ UCHAR CharSet[64]; // Type of character code
+} UNICODE_CACHE;
+
+// Macro
+#define _SS(name) (GetTableStr((char *)(name)))
+#define _UU(name) (GetTableUniStr((char *)(name)))
+#define _II(name) (GetTableInt((char *)(name)))
+#define _E(name) (GetUniErrorStr((UINT)(name)))
+#define _EA(name) (GetErrorStr((UINT)(name)))
+#define _GETLANG() (_II("LANG"))
+
+// Language list
+struct LANGLIST
+{
+ UINT Id; // Number
+ char Name[32]; // Identifier
+ wchar_t TitleEnglish[128]; // English notation
+ wchar_t TitleLocal[128]; // Local notation
+ LIST *LcidList; // Windows LCID list
+ LIST *LangList; // UNIX LANG environment variable list
+};
+
+
+// Function prototype
+bool LoadTable(char *filename);
+bool LoadTableW(wchar_t *filename);
+bool LoadTableMain(wchar_t *filename);
+bool LoadTableFromBuf(BUF *b);
+void FreeTable();
+TABLE *ParseTableLine(char *line, char *prefix, UINT prefix_size, LIST *replace_list);
+void UnescapeStr(char *src);
+int CmpTableName(void *p1, void *p2);
+TABLE *FindTable(char *name);
+TOKEN_LIST *GetTableNameStartWith(char *str);
+char *GetTableStr(char *name);
+wchar_t *GetTableUniStr(char *name);
+char *GetErrorStr(UINT err);
+wchar_t *GetUniErrorStr(UINT err);
+UINT GetTableInt(char *name);
+void GenerateUnicodeCacheFileName(wchar_t *name, UINT size, wchar_t *strfilename, UINT strfilesize, UCHAR *filehash);
+void SaveUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash);
+bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash);
+void InitTable();
+
+LIST *LoadLangList();
+void FreeLangList(LIST *o);
+
+LANGLIST *GetBestLangByName(LIST *o, char *name);
+LANGLIST *GetBestLangByLcid(LIST *o, UINT lcid);
+LANGLIST *GetBestLangByLangStr(LIST *o, char *str);
+LANGLIST *GetBestLangForCurrentEnvironment(LIST *o);
+LANGLIST *GetLangById(LIST *o, UINT id);
+
+bool LoadLangConfig(wchar_t *filename, char *str, UINT str_size);
+bool LoadLangConfigCurrentDir(char *str, UINT str_size);
+bool SaveLangConfig(wchar_t *filename, char *str);
+bool SaveLangConfigCurrentDir(char *str);
+
+void GetCurrentLang(LANGLIST *e);
+UINT GetCurrentLangId();
+
+void GetCurrentOsLang(LANGLIST *e);
+UINT GetCurrentOsLangId();
+
+#endif // TABLE_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TcpIp.c b/src/Mayaqua/TcpIp.c
new file mode 100644
index 00000000..4bb63c9b
--- /dev/null
+++ b/src/Mayaqua/TcpIp.c
@@ -0,0 +1,3802 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// TcpIp.c
+// Utility module for TCP/IP packet processing
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+
+// Send an ICMP Echo
+ICMP_RESULT *IcmpEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ if (IsIcmpApiSupported())
+ {
+ return IcmpApiEchoSend(dest_ip, ttl, data, size, timeout);
+ }
+ else
+ {
+ return IcmpEchoSendBySocket(dest_ip, ttl, data, size, timeout);
+ }
+}
+
+// Release the memory for the ICMP response
+void IcmpFreeResult(ICMP_RESULT *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ IcmpApiFreeResult(r);
+}
+
+// Parse the ICMP reply packet received from the socket
+ICMP_RESULT *IcmpParseResult(IP *dest_ip, USHORT src_id, USHORT src_seqno, UCHAR *recv_buffer, UINT recv_buffer_size)
+{
+ ICMP_RESULT *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || recv_buffer == NULL || recv_buffer_size == 0)
+ {
+ return NULL;
+ }
+
+ i = recv_buffer_size;
+
+ if (true)
+ {
+ UINT ip_header_size = GetIpHeaderSize(recv_buffer, i);
+ if (ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ IPV4_HEADER *ipv4 = (IPV4_HEADER *)recv_buffer;
+ if ((IPV4_GET_VERSION(ipv4) == 4) && (ipv4->Protocol == IP_PROTO_ICMPV4))
+ {
+ UINT ip_total_len = (UINT)Endian16(ipv4->TotalLength);
+
+ if ((ip_total_len >= sizeof(IPV4_HEADER)) && (ip_total_len <= i))
+ {
+ UINT icmp_packet_size = ip_total_len - ip_header_size;
+ ICMP_HEADER *icmp = (ICMP_HEADER *)(recv_buffer + ip_header_size);
+
+ if (icmp_packet_size >= sizeof(ICMP_HEADER))
+ {
+ USHORT chksum = icmp->Checksum;
+ USHORT chksum2;
+ icmp->Checksum = 0;
+
+ chksum2 = IpChecksum(icmp, icmp_packet_size);
+
+ if (chksum2 == chksum)
+ {
+ if (icmp->Type == ICMP_TYPE_ECHO_RESPONSE)
+ {
+ ICMP_ECHO *echo = (ICMP_ECHO *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER));
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ if (Endian16(echo->Identifier) == src_id && (src_seqno == 0 || Endian16(echo->SeqNo) == src_seqno))
+ {
+ IP ip;
+
+ UINTToIP(&ip, ipv4->SrcIP);
+
+ // Received the correct Echo response
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Ok = true;
+ ret->Ttl = ipv4->TimeToLive;
+ ret->DataSize = icmp_packet_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ ret->Data = Clone(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
+ ret->DataSize);
+ Copy(&ret->IpAddress, &ip, sizeof(IP));
+ }
+ }
+ }
+ else if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
+ {
+ // Ignore because an Echo request should not arrive
+ }
+ else
+ {
+ // If an error is returned, compare to the copy of
+ // the ICMP packet last sent
+ IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(recv_buffer + ip_header_size + 4 + sizeof(ICMP_HEADER));
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + 4 + sizeof(IPV4_HEADER)))
+ {
+ UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, icmp_packet_size - 4 - sizeof(ICMP_HEADER));
+ if (orig_ipv4_header_size >= sizeof(IPV4_HEADER))
+ {
+ if ((IPV4_GET_VERSION(orig_ipv4) == 4) && (orig_ipv4->Protocol == IP_PROTO_ICMPV4))
+ {
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ ICMP_HEADER *orig_icmp = (ICMP_HEADER *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size);
+ ICMP_ECHO *orig_echo = (ICMP_ECHO *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size + sizeof(ICMP_HEADER));
+
+ if (orig_icmp->Type == ICMP_TYPE_ECHO_REQUEST && orig_echo->Identifier == Endian16(src_id) && (src_seqno == 0 || orig_echo->SeqNo == Endian16(src_seqno)))
+ {
+ IP ip;
+
+ UINTToIP(&ip, ipv4->SrcIP);
+
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Type = icmp->Type;
+ ret->Code = icmp->Code;
+ ret->Ttl = ipv4->TimeToLive;
+ ret->DataSize = icmp_packet_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ ret->Data = Clone(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
+ ret->DataSize);
+ Copy(&ret->IpAddress, &ip, sizeof(IP));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Send the ICMP Echo (by a socket)
+ICMP_RESULT *IcmpEchoSendBySocket(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+ SOCK *s;
+ ICMP_RESULT *ret = NULL;
+ USHORT id;
+ USHORT seq;
+ UINT64 sent_tick;
+ UINT64 recv_tick;
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
+ if (s != NULL)
+ {
+ // Construction of the ICMP packet
+ UCHAR *send_buffer;
+ UINT send_buffer_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + size;
+ ICMP_HEADER *send_icmp_header;
+ ICMP_ECHO *send_icmp_echo;
+ UINT i;
+
+ id = Rand16();
+ if (id == 0)
+ {
+ id = 1;
+ }
+
+ seq = Rand16();
+ if (seq == 0)
+ {
+ seq = 1;
+ }
+
+ send_buffer = ZeroMalloc(send_buffer_size);
+
+ send_icmp_header = (ICMP_HEADER *)send_buffer;
+ send_icmp_header->Type = ICMP_TYPE_ECHO_REQUEST;
+
+ send_icmp_echo = (ICMP_ECHO *)(send_buffer + sizeof(ICMP_HEADER));
+ send_icmp_echo->Identifier = Endian16(id);
+ send_icmp_echo->SeqNo = Endian16(seq);
+
+ Copy(send_buffer + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), data, size);
+
+ send_icmp_header->Checksum = IpChecksum(send_buffer, send_buffer_size);
+
+ // Send an ICMP
+ SetTtl(s, ttl);
+ sent_tick = TickHighres64();
+ i = SendTo(s, dest_ip, MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), send_buffer, send_buffer_size);
+
+ if (i != 0 && i != INFINITE)
+ {
+ // ICMP response received
+ INTERRUPT_MANAGER *interrupt = NewInterruptManager();
+ UINT64 giveup_time = Tick64() + (UINT64)timeout;
+ UINT recv_buffer_size = (sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + size + 64) * 2;
+ UCHAR *recv_buffer = Malloc(recv_buffer_size);
+
+ AddInterrupt(interrupt, giveup_time);
+
+ while (true)
+ {
+ UINT interval = GetNextIntervalForInterrupt(interrupt);
+ IP src_ip;
+ UINT src_port;
+ SOCKSET set;
+
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+
+ Select(&set, interval, NULL, NULL);
+
+ while (true)
+ {
+ Zero(recv_buffer, recv_buffer_size);
+ i = RecvFrom(s, &src_ip, &src_port, recv_buffer, recv_buffer_size);
+ recv_tick = TickHighres64();
+
+ if (i != 0 && i != SOCK_LATER)
+ {
+ ret = IcmpParseResult(dest_ip, id, seq, recv_buffer, i);
+
+ if (ret != NULL)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (interval == 0)
+ {
+ break;
+ }
+
+ if (ret != NULL)
+ {
+ break;
+ }
+ }
+
+ FreeInterruptManager(interrupt);
+
+ Free(recv_buffer);
+
+ if (ret == NULL)
+ {
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Timeout = true;
+ }
+ }
+
+ Free(send_buffer);
+ ReleaseSock(s);
+ }
+
+ return ret;
+}
+
+// Get whether the packet is a DHCP packet associated with the specified MAC address
+bool IsDhcpPacketForSpecificMac(UCHAR *data, UINT size, UCHAR *mac_address)
+{
+ USHORT *us;
+ IPV4_HEADER *ip;
+ UDP_HEADER *udp;
+ UINT ip_header_size;
+ bool is_send = false, is_recv = false;
+ // Validate arguments
+ if (data == NULL || mac_address == NULL || IsZero(mac_address, 6))
+ {
+ return false;
+ }
+
+ // Whether the src or the dest matches
+ if (size < 14)
+ {
+ return false;
+ }
+
+ // Destination MAC address
+ if (Cmp(data, mac_address, 6) == 0)
+ {
+ is_recv = true;
+ }
+ size -= 6;
+ data += 6;
+
+ // Source MAC address
+ if (Cmp(data, mac_address, 6) == 0)
+ {
+ is_send = true;
+ }
+ size -= 6;
+ data += 6;
+
+ if (is_send == false && is_recv == false)
+ {
+ return false;
+ }
+ if (is_send && is_recv)
+ {
+ return false;
+ }
+
+ // TPID
+ us = (USHORT *)data;
+ size -= 2;
+ data += 2;
+
+ if (READ_USHORT(us) != MAC_PROTO_IPV4)
+ {
+ // Other than IPv4
+ return false;
+ }
+
+ // IP header
+ ip_header_size = GetIpHeaderSize(data, size);
+ if (ip_header_size == 0)
+ {
+ // IPv4 header analysis failure
+ return false;
+ }
+
+ ip = (IPV4_HEADER *)data;
+ data += ip_header_size;
+ size -= ip_header_size;
+
+ if (ip->Protocol != IP_PROTO_UDP)
+ {
+ // Not an UDP packet
+ return false;
+ }
+
+ // UDP header
+ if (size < sizeof(UDP_HEADER))
+ {
+ return false;
+ }
+ udp = (UDP_HEADER *)data;
+ data += sizeof(UDP_HEADER);
+ size -= sizeof(UDP_HEADER);
+
+ if (is_send)
+ {
+ // Detect whether it's a DHCP Request packet
+ if (Endian16(udp->DstPort) == 67)
+ {
+ Debug("IsDhcpPacketForSpecificMac: DHCP Request Packet is Detected.\n");
+ return true;
+ }
+ }
+ else if (is_recv)
+ {
+ // Detect whether it's a DHCP Response packet
+ if (Endian16(udp->SrcPort) == 67)
+ {
+ Debug("IsDhcpPacketForSpecificMac: DHCP Response Packet is Detected.\n");
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Adjust the MSS of the TCP in the IP packet (L2)
+bool AdjustTcpMssL2(UCHAR *src, UINT src_size, UINT mss, USHORT tag_vlan_tpid)
+{
+ MAC_HEADER *mac;
+ USHORT proto;
+ // Validate arguments
+ if (src == NULL || src_size == 0 || mss == 0)
+ {
+ return false;
+ }
+ if (tag_vlan_tpid == 0)
+ {
+ tag_vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ if (src_size < sizeof(MAC_HEADER))
+ {
+ return false;
+ }
+
+ mac = (MAC_HEADER *)src;
+
+ src += sizeof(MAC_HEADER);
+ src_size -= sizeof(MAC_HEADER);
+
+ proto = Endian16(mac->Protocol);
+
+ if (proto == MAC_PROTO_IPV4 || proto == MAC_PROTO_IPV6)
+ {
+ // Ordinary IPv4 / IPv6 packet
+ return AdjustTcpMssL3(src, src_size, mss);
+ }
+ else if (proto == tag_vlan_tpid)
+ {
+ // IPv4 / IPv6 packets in the VLAN tag
+ if (src_size < 4)
+ {
+ return false;
+ }
+
+ src += 2;
+ src_size -= 2;
+
+ proto = READ_USHORT(src);
+
+ if (proto == MAC_PROTO_IPV4 || proto == MAC_PROTO_IPV6)
+ {
+ if (mss >= 5)
+ {
+ mss -= 4;
+
+ src += 2;
+ src_size -= 2;
+
+ return AdjustTcpMssL3(src, src_size, mss);
+ }
+ }
+ }
+
+ return false;
+}
+
+// Get an IP header size
+UINT GetIpHeaderSize(UCHAR *src, UINT src_size)
+{
+ UCHAR ip_ver;
+ TCP_HEADER *tcp = NULL;
+ UINT tcp_size = 0;
+ IPV4_HEADER *ip = NULL;
+ IPV6_HEADER *ip6 = NULL;
+ // Validate arguments
+ if (src == NULL || src_size == 0)
+ {
+ return 0;
+ }
+
+ // Get the IP version number
+ ip_ver = (src[0] >> 4) & 0x0f;
+
+ if (ip_ver == 4)
+ {
+ // IPv4
+ UINT ip_header_size;
+ if (src_size < sizeof(IPV4_HEADER))
+ {
+ // No IPv4 header
+ return 0;
+ }
+
+ ip = (IPV4_HEADER *)src;
+
+ ip_header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ if (ip_header_size < sizeof(IPV4_HEADER))
+ {
+ // Header size is invalid
+ return 0;
+ }
+
+ if (src_size < ip_header_size)
+ {
+ // No IPv4 header
+ return 0;
+ }
+
+ return ip_header_size;
+ }
+ else if (ip_ver == 6)
+ {
+ // IPv6
+ IPV6_HEADER_PACKET_INFO v6;
+
+ if (ParsePacketIPv6Header(&v6, src, src_size) == false)
+ {
+ // IPv6 analysis failure
+ return 0;
+ }
+
+ ip6 = v6.IPv6Header;
+ if (ip6 == NULL)
+ {
+ return 0;
+ }
+
+ if (src_size < v6.TotalHeaderSize)
+ {
+ // No header data
+ return 0;
+ }
+
+ return v6.TotalHeaderSize;
+ }
+ else
+ {
+ // Invalid
+ return 0;
+ }
+}
+
+// Adjust the MSS of TCP in the IP packet (L3)
+bool AdjustTcpMssL3(UCHAR *src, UINT src_size, UINT mss)
+{
+ UCHAR ip_ver;
+ TCP_HEADER *tcp = NULL;
+ UINT tcp_size = 0;
+ UINT tcp_header_size;
+ UCHAR *options;
+ UINT options_size;
+ IPV4_HEADER *ip = NULL;
+ IPV6_HEADER *ip6 = NULL;
+ // Validate arguments
+ if (src == NULL || src_size == 0 || mss == 0)
+ {
+ return false;
+ }
+
+ // Get the IP version number
+ ip_ver = (src[0] >> 4) & 0x0f;
+
+ if (ip_ver == 4)
+ {
+ UINT ip_header_size;
+ // IPv4
+ if (src_size < sizeof(IPV4_HEADER))
+ {
+ // No IPv4 header
+ return false;
+ }
+
+ ip = (IPV4_HEADER *)src;
+
+ if (ip->Protocol != IP_PROTO_TCP)
+ {
+ // Non-TCP
+ return false;
+ }
+
+ if (IPV4_GET_OFFSET(ip) != 0)
+ {
+ // It is the second or later packet of fragmented packet
+ return false;
+ }
+
+ if (IPV4_GET_FLAGS(ip) & 0x01)
+ {
+ // Fragmented packet
+ return false;
+ }
+
+ ip_header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ if (ip_header_size < sizeof(IPV4_HEADER))
+ {
+ // Header size is invalid
+ return false;
+ }
+
+ if (src_size < ip_header_size)
+ {
+ // No IPv4 header
+ return false;
+ }
+
+ src += ip_header_size;
+ src_size -= ip_header_size;
+
+ if (src_size < sizeof(TCP_HEADER))
+ {
+ // No TCP header
+ return false;
+ }
+
+ tcp = (TCP_HEADER *)src;
+ tcp_size = src_size;
+ }
+ else if (ip_ver == 6)
+ {
+ // IPv6
+ IPV6_HEADER_PACKET_INFO v6;
+
+ if (ParsePacketIPv6Header(&v6, src, src_size) == false)
+ {
+ // IPv6 analysis failure
+ return false;
+ }
+
+ ip6 = v6.IPv6Header;
+ if (ip6 == NULL)
+ {
+ return false;
+ }
+
+ if (v6.Protocol != IP_PROTO_TCP)
+ {
+ // Non-TCP
+ return false;
+ }
+
+ if (v6.IsFragment)
+ {
+ // It is the second or later packet of fragmented packet
+ return false;
+ }
+
+ if (v6.FragmentHeader != NULL)
+ {
+ if (IPV6_GET_FLAGS(v6.FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS)
+ {
+ // Fragmented packet
+ return false;
+ }
+ }
+
+ tcp = (TCP_HEADER *)v6.Payload;
+ tcp_size = v6.PayloadSize;
+ }
+ else
+ {
+ // This isn't either IPv4, IPv6
+ return false;
+ }
+
+ // Processing of the TCP header
+ if (tcp == NULL || tcp_size < sizeof(TCP_HEADER))
+ {
+ return false;
+ }
+
+ tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ if (tcp_header_size < sizeof(TCP_HEADER))
+ {
+ // TCP header size is invalid
+ return false;
+ }
+
+ if (tcp_size < tcp_header_size)
+ {
+ // Packet length shortage
+ return false;
+ }
+
+ if (((tcp->Flag & TCP_SYN) == false) ||
+ ((tcp->Flag & TCP_RST) ||
+ (tcp->Flag & TCP_PSH) ||
+ (tcp->Flag & TCP_URG)))
+ {
+ // Not a SYN packet
+ return false;
+ }
+
+ // Get the option field
+ options = ((UCHAR *)tcp) + sizeof(TCP_HEADER);
+ options_size = tcp_header_size - sizeof(TCP_HEADER);
+
+ if (ip6 != NULL)
+ {
+ // Reduce MSS by 20 since an IP header for IPv6 is 20 bytes larger than IPv4
+ if (mss >= 20)
+ {
+ mss -= 20;
+ }
+ }
+
+ // MSS should be at least 64
+ mss = MAX(mss, 64);
+
+ if (options_size >= 4 && options[0] == 0x02 && options[1] == 0x04)
+ {
+ // MSS option of TCP is added
+ USHORT current_mss = READ_USHORT(((UCHAR *)options) + 2);
+
+ if (current_mss <= mss)
+ {
+ // if the value of the MSS is smaller than the specified size
+ // from the beginning, it doesn't need to be rewritten
+ return false;
+ }
+ else
+ {
+ WRITE_USHORT(((UCHAR *)options) + 2, mss);
+
+ // Clear the checksum
+ tcp->Checksum = 0;
+
+ if (ip != NULL)
+ {
+ // Calculate the TCPv4 checksum
+ tcp->Checksum = CalcChecksumForIPv4(ip->SrcIP, ip->DstIP, IP_PROTO_TCP, tcp, tcp_size, 0);
+ }
+ else
+ {
+ // Calculate the TCPv6 checksum
+ tcp->Checksum = CalcChecksumForIPv6(&ip6->SrcAddress, &ip6->DestAddress,
+ IP_PROTO_TCP, tcp, tcp_size, 0);
+ }
+
+ return true;
+ }
+ }
+ else
+ {
+ // MSS option of TCP is not added
+ return false;
+ }
+}
+
+
+// Parse the DHCPv4 packet
+DHCPV4_DATA *ParseDHCPv4Data(PKT *pkt)
+{
+ DHCPV4_DATA *d;
+ UCHAR *data;
+ UINT size;
+ UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
+ bool ok = false;
+ DHCP_OPTION *o;
+ // Validate arguments
+ if (pkt == NULL)
+ {
+ return NULL;
+ }
+ if (pkt->TypeL3 != L3_IPV4 || pkt->TypeL4 != L4_UDP || pkt->TypeL7 != L7_DHCPV4)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(DHCPV4_DATA));
+ d->Size = (UINT)(pkt->PacketSize - (((UCHAR *)pkt->L7.PointerL7) - ((UCHAR *)pkt->PacketData)));
+ d->Data = Clone(pkt->L7.PointerL7, d->Size);
+
+ if (d->Size < sizeof(DHCPV4_HEADER))
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Header
+ d->Header = (DHCPV4_HEADER *)d->Data;
+
+ data = d->Data;
+ size = d->Size;
+
+ // Search for the Magic Cookie
+ ok = false;
+ while (size >= 5)
+ {
+ if (Cmp(data, &magic_cookie, 4) == 0)
+ {
+ // Found
+ data += 4;
+ size -= 4;
+ ok = true;
+ break;
+ }
+
+ data++;
+ size--;
+ }
+
+ if (ok == false)
+ {
+ // Magic Cookie not found
+ goto LABEL_ERROR;
+ }
+
+ // Parse the DHCP Options
+ d->OptionData = data;
+ d->OptionSize = size;
+
+ d->OptionList = ParseDhcpOptions(data, size);
+ if (d->OptionList == NULL)
+ {
+ // Parsing failure
+ goto LABEL_ERROR;
+ }
+
+ UINTToIP(&d->SrcIP, pkt->L3.IPv4Header->SrcIP);
+ UINTToIP(&d->DestIP, pkt->L3.IPv4Header->DstIP);
+
+ d->SrcPort = Endian16(pkt->L4.UDPHeader->SrcPort);
+ d->DestPort = Endian16(pkt->L4.UDPHeader->DstPort);
+
+ o = GetDhcpOption(d->OptionList, DHCP_ID_MESSAGE_TYPE);
+ if (o == NULL || o->Size != 1)
+ {
+ goto LABEL_ERROR;
+ }
+
+ d->OpCode = *((UCHAR *)o->Data);
+
+ d->ParsedOptionList = ParseDhcpOptionList(d->OptionData, d->OptionSize);
+
+ if (d->ParsedOptionList == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (d->ParsedOptionList->ServerAddress == 0)
+ {
+ d->ParsedOptionList->ServerAddress = d->Header->ServerIP;
+ }
+
+ d->ParsedOptionList->ClientAddress = d->Header->YourIP;
+
+ return d;
+
+LABEL_ERROR:
+ FreeDHCPv4Data(d);
+ return NULL;
+}
+
+// Release the DHCPv4 packet
+void FreeDHCPv4Data(DHCPV4_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ FreeDhcpOptions(d->OptionList);
+ Free(d->Data);
+
+ Free(d->ParsedOptionList);
+
+ Free(d);
+}
+
+// Embed a VLAN tag to the packet
+void VLanInsertTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid)
+{
+ UINT dest_size;
+ UCHAR *dest_data;
+ UINT src_size;
+ UCHAR *src_data;
+ USHORT vlan_ushort = Endian16(((USHORT)vlan_id) & 0xFFF);
+ USHORT vlan_tpid_ushort;
+ // Validate arguments
+ if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
+ *packet_size < 14 || vlan_id == 0)
+ {
+ return;
+ }
+ if (vlan_tpid == 0)
+ {
+ vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_tpid_ushort = Endian16((USHORT)vlan_tpid);
+
+ src_size = *packet_size;
+ src_data = (UCHAR *)(*packet_data);
+
+ dest_size = src_size + 4;
+ dest_data = Malloc(dest_size);
+
+ Copy(&dest_data[12], &vlan_tpid_ushort, sizeof(USHORT));
+ Copy(&dest_data[14], &vlan_ushort, sizeof(USHORT));
+
+ Copy(&dest_data[0], &src_data[0], 12);
+ Copy(&dest_data[16], &src_data[12], src_size - 12);
+
+ *packet_size = dest_size;
+ *packet_data = dest_data;
+
+ Free(src_data);
+}
+
+// Remove the VLAN tag from the packet
+bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid)
+{
+ bool has_vlan_tag = false;
+ UCHAR *src_data;
+ UINT src_size;
+ USHORT vlan_tpid_ushort;
+ UCHAR *vlan_tpid_uchar;
+ // Validate arguments
+ if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
+ *packet_size < 14)
+ {
+ return false;
+ }
+
+ if (vlan_tpid == 0)
+ {
+ vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_tpid_ushort = Endian16((USHORT)vlan_tpid);
+ vlan_tpid_uchar = (UCHAR *)(&vlan_tpid_ushort);
+
+ src_data = (UCHAR *)(*packet_data);
+ src_size = *packet_size;
+
+ if (src_data[12] == vlan_tpid_uchar[0] && src_data[13] == vlan_tpid_uchar[1])
+ {
+ if (src_size >= 18)
+ {
+ USHORT vlan_ushort;
+
+ vlan_ushort = READ_USHORT(&src_data[14]);
+ vlan_ushort = vlan_ushort & 0xFFF;
+
+ if (vlan_id == 0 || (vlan_ushort == vlan_id))
+ {
+ UINT dest_size = src_size - 4;
+ UINT i;
+
+ for (i = 12;i < dest_size;i++)
+ {
+ src_data[i] = src_data[i + 4];
+ }
+
+ *packet_size = dest_size;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Sending of an ICMPv6 packet
+BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id)
+{
+ ICMP_HEADER *icmp;
+ void *data_buf;
+ BUF *ret;
+ // Validate arguments
+ if (src_ip == NULL || dest_ip == NULL || data == NULL)
+ {
+ return NULL;
+ }
+
+ // Assembe the header
+ icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
+ data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
+ Copy(data_buf, data, size);
+
+ icmp->Type = type;
+ icmp->Code = code;
+ icmp->Checksum = CalcChecksumForIPv6(src_ip, dest_ip, IP_PROTO_ICMPV6, icmp,
+ sizeof(ICMP_HEADER) + size, 0);
+
+ ret = BuildIPv6(dest_ip, src_ip, id, IP_PROTO_ICMPV6, hop_limit, icmp,
+ sizeof(ICMP_HEADER) + size);
+
+ Free(icmp);
+
+ return ret;
+}
+
+// Build an ICMPv6 Neighbor Solicitation packet
+BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id)
+{
+ ICMPV6_OPTION_LIST opt;
+ ICMPV6_OPTION_LINK_LAYER link;
+ ICMPV6_NEIGHBOR_SOLICIATION_HEADER header;
+ BUF *b;
+ BUF *b2;
+ BUF *ret;
+ // Validate arguments
+ if (src_ip == NULL || target_ip == NULL || my_mac_address == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&link, sizeof(link));
+ Copy(link.Address, my_mac_address, 6);
+
+ Zero(&opt, sizeof(opt));
+ opt.SourceLinkLayer = &link;
+
+ b = BuildICMPv6Options(&opt);
+
+ Zero(&header, sizeof(header));
+ Copy(&header.TargetAddress, target_ip, sizeof(IPV6_ADDR));
+
+ b2 = NewBuf();
+
+ WriteBuf(b2, &header, sizeof(header));
+ WriteBufBuf(b2, b);
+
+ ret = BuildICMPv6(src_ip, target_ip, 255,
+ ICMPV6_TYPE_NEIGHBOR_SOLICIATION, 0, b2->Buf, b2->Size, id);
+
+ FreeBuf(b);
+ FreeBuf(b2);
+
+ return ret;
+}
+
+// Get the next header number from the queue
+UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
+{
+ UINT *p;
+ UCHAR v;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return IPV6_HEADER_NONE;
+ }
+
+ p = (UINT *)GetNext(q);
+ v = (UCHAR)(*p);
+ Free(p);
+
+ return v;
+}
+
+// Add an IPv6 extension header option (variable length)
+void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size)
+{
+ IPV6_OPTION_HEADER *h;
+ UINT total_size;
+ // Validate arguments
+ if (b == NULL || opt == NULL)
+ {
+ return;
+ }
+
+ total_size = size;
+ if ((total_size % 8) != 0)
+ {
+ total_size = ((total_size / 8) + 1) * 8;
+ }
+
+ h = ZeroMalloc(total_size);
+ Copy(h, opt, size);
+ h->Size = (total_size / 8) - 1;
+ h->NextHeader = next_header;
+
+ WriteBuf(b, h, total_size);
+
+ Free(h);
+}
+
+// Build an IPv6 packet
+BUF *BuildIPv6(IPV6_ADDR *dest_ip, IPV6_ADDR *src_ip, UINT id, UCHAR protocol, UCHAR hop_limit, void *data,
+ UINT size)
+{
+ IPV6_HEADER_PACKET_INFO info;
+ IPV6_HEADER ip_header;
+ BUF *buf;
+ UINT size_for_headers;
+ // Validate arguments
+ if (dest_ip == NULL || src_ip == NULL || data == NULL)
+ {
+ return NULL;
+ }
+ if (hop_limit == 0)
+ {
+ hop_limit = 255;
+ }
+
+ // IPv6 header
+ Zero(&ip_header, sizeof(ip_header));
+ IPV6_SET_VERSION(&ip_header, 6);
+ ip_header.HopLimit = hop_limit;
+ Copy(&ip_header.SrcAddress, src_ip, sizeof(IPV6_ADDR));
+ Copy(&ip_header.DestAddress, dest_ip, sizeof(IPV6_ADDR));
+
+ // Arrangement of the packet header information
+ Zero(&info, sizeof(info));
+ info.IPv6Header = &ip_header;
+ info.Protocol = protocol;
+ info.Payload = data;
+ info.PayloadSize = size;
+
+ buf = BuildIPv6PacketHeader(&info, &size_for_headers);
+ if (buf == NULL)
+ {
+ return NULL;
+ }
+
+ return buf;
+}
+
+// Build the IPv6 packet header section
+BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload)
+{
+ BUF *b;
+ QUEUE *q;
+ UINT bbp = 0;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ q = NewQueueFast();
+
+ // Create the list of options headers
+ if (info->HopHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_HOP);
+ }
+ if (info->EndPointHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_ENDPOINT);
+ }
+ if (info->RoutingHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_ROUTING);
+ }
+ if (info->FragmentHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_FRAGMENT);
+ }
+ InsertQueueInt(q, info->Protocol);
+
+ // IPv6 header
+ info->IPv6Header->NextHeader = IPv6GetNextHeaderFromQueue(q);
+ WriteBuf(b, info->IPv6Header, sizeof(IPV6_HEADER));
+
+ // Hop-by-hop option header
+ if (info->HopHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->HopHeader,
+ IPv6GetNextHeaderFromQueue(q), info->HopHeaderSize);
+ }
+
+ // End point option header
+ if (info->EndPointHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->EndPointHeader,
+ IPv6GetNextHeaderFromQueue(q), info->EndPointHeaderSize);
+ }
+
+ // Routing header
+ if (info->RoutingHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->RoutingHeader,
+ IPv6GetNextHeaderFromQueue(q), info->RoutingHeaderSize);
+ }
+
+ // Fragment header
+ if (info->FragmentHeader != NULL)
+ {
+ info->FragmentHeader->NextHeader = IPv6GetNextHeaderFromQueue(q);
+ WriteBuf(b, info->FragmentHeader, sizeof(IPV6_FRAGMENT_HEADER));
+ }
+
+ bbp = b->Size;
+ if (info->FragmentHeader == NULL)
+ {
+ bbp += sizeof(IPV6_FRAGMENT_HEADER);
+ }
+
+ // Payload
+ if (info->Protocol != IPV6_HEADER_NONE)
+ {
+ WriteBuf(b, info->Payload, info->PayloadSize);
+ }
+
+ ReleaseQueue(q);
+
+ SeekBuf(b, 0, 0);
+
+ // Payload length
+ ((IPV6_HEADER *)b->Buf)->PayloadLength = Endian16(b->Size - (USHORT)sizeof(IPV6_HEADER));
+
+ if (bytes_before_payload != NULL)
+ {
+ // Calculate the length just before the payload
+ // (by assuming fragment header is always included)
+ *bytes_before_payload = bbp;
+ }
+
+ return b;
+}
+
+// Build the option values of an ICMPv6 packet
+void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total_size)
+{
+ UINT packet_size;
+ UCHAR *packet;
+ ICMPV6_OPTION *opt;
+ // Validate arguments
+ if (b == NULL || header_pointer == NULL)
+ {
+ return;
+ }
+
+ packet_size = ((total_size + 7) / 8) * 8;
+ packet = ZeroMalloc(packet_size);
+
+ Copy(packet, header_pointer, total_size);
+ opt = (ICMPV6_OPTION *)packet;
+ opt->Length = (UCHAR)(packet_size / 8);
+ opt->Type = type;
+
+ WriteBuf(b, packet, packet_size);
+
+ Free(packet);
+}
+
+// Build the options of the ICMPv6 packet
+BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o)
+{
+ BUF *b;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ if (o->SourceLinkLayer != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER, o->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ }
+ if (o->TargetLinkLayer != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER, o->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ }
+ if (o->Prefix != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
+ }
+ if (o->Mtu != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_MTU, o->Mtu, sizeof(ICMPV6_OPTION_MTU));
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Checksum calculation (IPv4)
+USHORT CalcChecksumForIPv4(UINT src_ip, UINT dst_ip, UCHAR protocol, void *data, UINT size, UINT real_size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ IPV4_PSEUDO_HEADER *ph;
+ USHORT ret;
+ bool use_free = false;
+ UCHAR tmp_buffer[1600];
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ if (real_size == 0)
+ {
+ real_size = size;
+ }
+
+ if (real_size == INFINITE)
+ {
+ real_size = 0;
+ }
+
+ tmp_size = size + sizeof(IPV4_PSEUDO_HEADER);
+
+ if (tmp_size > sizeof(tmp_buffer))
+ {
+ tmp = Malloc(tmp_size);
+
+ use_free = true;
+ }
+ else
+ {
+ tmp = tmp_buffer;
+ }
+
+ ph = (IPV4_PSEUDO_HEADER *)tmp;
+ ph->SrcIP = src_ip;
+ ph->DstIP = dst_ip;
+ ph->PacketLength = Endian16(real_size);
+ ph->Protocol = protocol;
+ ph->Reserved = 0;
+
+ if (size >= 1)
+ {
+ Copy(((UCHAR *)tmp) + sizeof(IPV4_PSEUDO_HEADER), data, size);
+ }
+
+ ret = IpChecksum(tmp, tmp_size);
+
+ if (use_free)
+ {
+ Free(tmp);
+ }
+
+ return ret;
+}
+
+// Checksum calculation (IPv6)
+USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size, UINT real_size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ IPV6_PSEUDO_HEADER *ph;
+ USHORT ret;
+ bool use_free = false;
+ UCHAR tmp_buffer[256];
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ if (real_size == 0)
+ {
+ real_size = size;
+ }
+
+ if (real_size == INFINITE)
+ {
+ real_size = 0;
+ }
+
+ tmp_size = size + sizeof(IPV6_PSEUDO_HEADER);
+
+ if (tmp_size > sizeof(tmp_buffer))
+ {
+ tmp = Malloc(tmp_size);
+
+ use_free = true;
+ }
+ else
+ {
+ tmp = tmp_buffer;
+ }
+
+ ph = (IPV6_PSEUDO_HEADER *)tmp;
+ Zero(ph, sizeof(IPV6_PSEUDO_HEADER));
+ Copy(&ph->SrcAddress, src_ip, sizeof(IPV6_ADDR));
+ Copy(&ph->DestAddress, dest_ip, sizeof(IPV6_ADDR));
+ ph->UpperLayerPacketSize = Endian32(real_size);
+ ph->NextHeader = protocol;
+
+ Copy(((UCHAR *)tmp) + sizeof(IPV6_PSEUDO_HEADER), data, size);
+
+ ret = IpChecksum(tmp, tmp_size);
+
+ if (use_free)
+ {
+ Free(tmp);
+ }
+
+ return ret;
+}
+
+// Release the cloned packet
+void FreeClonePacket(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p->IPv6HeaderPacketInfo.IPv6Header);
+ Free(p->IPv6HeaderPacketInfo.HopHeader);
+ Free(p->IPv6HeaderPacketInfo.EndPointHeader);
+ Free(p->IPv6HeaderPacketInfo.RoutingHeader);
+ Free(p->IPv6HeaderPacketInfo.FragmentHeader);
+ Free(p->IPv6HeaderPacketInfo.Payload);
+ Free(p->ICMPv6HeaderPacketInfo.Data);
+ Free(p->ICMPv6HeaderPacketInfo.EchoData);
+ Free(p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer);
+ FreeCloneICMPv6Options(&p->ICMPv6HeaderPacketInfo.OptionList);
+ Free(p->L3.PointerL3);
+ Free(p->L4.PointerL4);
+ Free(p->L7.PointerL7);
+ Free(p->PacketData);
+ Free(p->MacHeader);
+ Free(p->HttpLog);
+ Free(p);
+}
+
+// Copy the packet header
+PKT *ClonePacket(PKT *p, bool copy_data)
+{
+ PKT *ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMallocFast(sizeof(PKT));
+ ret->PacketSize = p->PacketSize;
+
+ // Copy of the MAC header
+ ret->MacHeader = MallocFast(sizeof(MAC_HEADER));
+ Copy(ret->MacHeader, p->MacHeader, sizeof(MAC_HEADER));
+
+ // Copy of the MAC flag
+ ret->BroadcastPacket = p->BroadcastPacket;
+ ret->InvalidSourcePacket = p->InvalidSourcePacket;
+
+ // Copy of the IPv6 related structure
+ Copy(&ret->IPv6HeaderPacketInfo, &p->IPv6HeaderPacketInfo, sizeof(IPV6_HEADER_PACKET_INFO));
+ Copy(&ret->ICMPv6HeaderPacketInfo, &p->ICMPv6HeaderPacketInfo, sizeof(ICMPV6_HEADER_INFO));
+
+ // Layer 3
+ ret->TypeL3 = p->TypeL3;
+ switch (ret->TypeL3)
+ {
+ case L3_ARPV4:
+ // ARP packet
+ ret->L3.ARPv4Header = MallocFast(sizeof(ARPV4_HEADER));
+ Copy(ret->L3.ARPv4Header, p->L3.ARPv4Header, sizeof(ARPV4_HEADER));
+ break;
+
+ case L3_IPV4:
+ // IPv4 packet
+ ret->L3.IPv4Header = MallocFast(sizeof(IPV4_HEADER));
+ Copy(ret->L3.IPv4Header, p->L3.IPv4Header, sizeof(IPV4_HEADER));
+ break;
+
+ case L3_IPV6:
+ // IPv6 packet
+ ret->L3.IPv6Header = MallocFast(sizeof(IPV6_HEADER));
+ Copy(ret->L3.IPv6Header, p->L3.IPv6Header, sizeof(IPV6_HEADER));
+
+ ret->IPv6HeaderPacketInfo.IPv6Header = Clone(p->IPv6HeaderPacketInfo.IPv6Header,
+ sizeof(IPV6_HEADER));
+
+ ret->IPv6HeaderPacketInfo.HopHeader = Clone(p->IPv6HeaderPacketInfo.HopHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.EndPointHeader = Clone(p->IPv6HeaderPacketInfo.EndPointHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.RoutingHeader = Clone(p->IPv6HeaderPacketInfo.RoutingHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.FragmentHeader = Clone(p->IPv6HeaderPacketInfo.FragmentHeader,
+ sizeof(IPV6_FRAGMENT_HEADER));
+
+ ret->IPv6HeaderPacketInfo.Payload = Clone(p->IPv6HeaderPacketInfo.Payload,
+ p->IPv6HeaderPacketInfo.PayloadSize);
+ break;
+ }
+
+ // Layer 4
+ ret->TypeL4 = p->TypeL4;
+ switch (ret->TypeL4)
+ {
+ case L4_ICMPV4:
+ // ICMPv4 packet
+ ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
+ Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
+ break;
+
+ case L4_ICMPV6:
+ // ICMPv6 packet
+ ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
+ Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
+
+ ret->ICMPv6HeaderPacketInfo.Data = Clone(p->ICMPv6HeaderPacketInfo.Data,
+ p->ICMPv6HeaderPacketInfo.DataSize);
+
+ ret->ICMPv6HeaderPacketInfo.EchoData = Clone(p->ICMPv6HeaderPacketInfo.EchoData,
+ p->ICMPv6HeaderPacketInfo.EchoDataSize);
+
+ switch (ret->ICMPv6HeaderPacketInfo.Type)
+ {
+ case ICMPV6_TYPE_ECHO_REQUEST:
+ case ICMPV6_TYPE_ECHO_RESPONSE:
+ break;
+
+ case ICMPV6_TYPE_ROUTER_SOLICIATION:
+ ret->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader,
+ sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER));
+ break;
+
+ case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
+ ret->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader,
+ sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER));
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
+ ret->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader,
+ sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER));
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
+ ret->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader,
+ sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER));
+ break;
+ }
+
+ CloneICMPv6Options(&ret->ICMPv6HeaderPacketInfo.OptionList,
+ &p->ICMPv6HeaderPacketInfo.OptionList);
+ break;
+
+ case L4_TCP:
+ // TCP packet
+ ret->L4.TCPHeader = MallocFast(sizeof(TCP_HEADER));
+ Copy(ret->L4.TCPHeader, p->L4.TCPHeader, sizeof(TCP_HEADER));
+ break;
+
+ case L4_UDP:
+ // UDP packet
+ ret->L4.UDPHeader = MallocFast(sizeof(UDP_HEADER));
+ Copy(ret->L4.UDPHeader, p->L4.UDPHeader, sizeof(UDP_HEADER));
+ break;
+ }
+
+ // Layer 7
+ ret->TypeL7 = p->TypeL7;
+ switch (ret->TypeL7)
+ {
+ case L7_DHCPV4:
+ // DHCP packet
+ ret->L7.DHCPv4Header = MallocFast(sizeof(DHCPV4_HEADER));
+ Copy(ret->L7.DHCPv4Header, p->L7.DHCPv4Header, sizeof(DHCPV4_HEADER));
+ break;
+
+ case L7_IKECONN:
+ // IKE packet
+ ret->L7.IkeHeader = MallocFast(sizeof(IKE_HEADER));
+ Copy(ret->L7.IkeHeader, p->L7.IkeHeader, sizeof(IKE_HEADER));
+ break;
+ }
+
+ // Address data
+ ret->MacAddressSrc = ret->MacHeader->SrcAddress;
+ ret->MacAddressDest = ret->MacHeader->DestAddress;
+
+ if (copy_data)
+ {
+ // Copy also the packet body
+ ret->PacketData = MallocFast(p->PacketSize);
+ Copy(ret->PacketData, p->PacketData, p->PacketSize);
+ }
+
+ if (p->HttpLog != NULL)
+ {
+ ret->HttpLog = Clone(p->HttpLog, sizeof(HTTPLOG));
+ }
+
+ return ret;
+}
+
+// Parse the contents of the packet
+PKT *ParsePacket(UCHAR *buf, UINT size)
+{
+ return ParsePacketEx(buf, size, false);
+}
+PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3)
+{
+ return ParsePacketEx2(buf, size, no_l3, 0);
+}
+PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id)
+{
+ return ParsePacketEx3(buf, size, no_l3, vlan_type_id, true);
+}
+PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address)
+{
+ return ParsePacketEx4(buf, size, no_l3, vlan_type_id, bridge_id_as_mac_address, false, false);
+}
+PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum)
+{
+ PKT *p;
+ USHORT vlan_type_id_16;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ if (vlan_type_id == 0)
+ {
+ vlan_type_id = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_type_id_16 = Endian16((USHORT)vlan_type_id);
+
+ p = ZeroMallocFast(sizeof(PKT));
+
+ p->VlanTypeID = vlan_type_id;
+
+ // If there is garbage after the payload in IPv4 and IPv6 packets, eliminate it
+ if (size >= 24)
+ {
+ if (buf[12] == 0x08 && buf[13] == 0x00)
+ {
+ USHORT ip_total_size2 = READ_USHORT(&buf[16]);
+ UINT mac_packet_size;
+
+ if (ip_total_size2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_total_size2 + 14;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[12] == 0x86 && buf[13] == 0xdd)
+ {
+ USHORT ip_payload_size_2 = READ_USHORT(&buf[18]);
+ UINT mac_packet_size;
+
+ if (ip_payload_size_2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_payload_size_2 + 14 + 40;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[12] == ((UCHAR *)&vlan_type_id_16)[0] && buf[13] == ((UCHAR *)&vlan_type_id_16)[1])
+ {
+ if (buf[16] == 0x08 && buf[17] == 0x00)
+ {
+ USHORT ip_total_size2 = READ_USHORT(&buf[20]);
+ UINT mac_packet_size;
+
+ if (ip_total_size2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_total_size2 + 14 + 4;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[16] == 0x86 && buf[17] == 0xdd)
+ {
+ USHORT ip_payload_size_2 = READ_USHORT(&buf[22]);
+ UINT mac_packet_size;
+
+ if (ip_payload_size_2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_payload_size_2 + 14 + 40 + 4;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ }
+ }
+
+ // Do parse
+ if (ParsePacketL2Ex(p, buf, size, no_l3) == false)
+ {
+ // Parsing failure
+ FreePacket(p);
+ return NULL;
+ }
+
+ p->PacketData = buf;
+ p->PacketSize = size;
+
+ p->MacAddressSrc = p->MacHeader->SrcAddress;
+ p->MacAddressDest = p->MacHeader->DestAddress;
+
+ if (bridge_id_as_mac_address)
+ {
+ if (p->TypeL3 == L3_BPDU)
+ {
+ if (p->L3.BpduHeader != NULL)
+ {
+ p->MacAddressSrc = p->L3.BpduHeader->BridgeMacAddress;
+ }
+ }
+ }
+
+ if (no_http == false)
+ {
+ USHORT port_raw = Endian16(80);
+
+ // Analyze if the packet is a part of HTTP
+ if ((p->TypeL3 == L3_IPV4 || p->TypeL3 == L3_IPV6) && p->TypeL4 == L4_TCP)
+ {
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+ if (tcp->DstPort == port_raw)
+ {
+ if (tcp != NULL && (!((tcp->Flag & TCP_SYN) || (tcp->Flag & TCP_RST) || (tcp->Flag & TCP_FIN))))
+ {
+ if (p->PayloadSize >= 1)
+ {
+ p->HttpLog = ParseHttpAccessLog(p);
+ }
+ }
+ }
+ }
+ }
+
+ if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
+ {
+ // Get the DHCP opcode
+ DHCPV4_DATA *d = ParseDHCPv4Data(p);
+
+ if (d != NULL)
+ {
+ p->DhcpOpCode = d->OpCode;
+
+ FreeDHCPv4Data(d);
+ }
+ }
+
+ if (correct_checksum)
+ {
+ // Correct the checksum of the UDP, IP and TCP
+ CorrectChecksum(p);
+ }
+
+ // Parsing success
+ return p;
+}
+
+// Correct the checksum (store the correct value in the header by recalculating the checksum which is by off-load processing)
+void CorrectChecksum(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->TypeL3 == L3_IPV4)
+ {
+ IPV4_HEADER *v4 = p->L3.IPv4Header;
+
+ if (v4 != NULL)
+ {
+ if (v4->Checksum == 0x0000)
+ {
+ v4->Checksum = IpChecksum(v4, IPV4_GET_HEADER_LEN(v4) * 4);
+ }
+
+ if (p->TypeL4 == L4_TCP)
+ {
+ // Recalculate the TCP checksum
+ if (IPV4_GET_OFFSET(v4) == 0 && (IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // TCP checksuming doesn't target fragmented IP packets
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ if (tcp != NULL)
+ {
+ USHORT tcp_offloading_checksum1 = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_TCP, NULL, 0, p->IPv4PayloadSize);
+ USHORT tcp_offloading_checksum2 = ~tcp_offloading_checksum1;
+
+ if (tcp->Checksum == 0 || tcp->Checksum == tcp_offloading_checksum1 || tcp->Checksum == tcp_offloading_checksum2)
+ {
+ tcp->Checksum = 0;
+ tcp->Checksum = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_TCP, tcp, p->IPv4PayloadSize, 0);
+ }
+ }
+ }
+ }
+
+ if (p->TypeL4 == L4_UDP)
+ {
+ // Recalculation of the UDP checksum
+ if (IPV4_GET_OFFSET(v4) == 0 || (IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // If it is not divided, or it is divided but it is the first fragment of the UDP packet
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ if (udp != NULL && udp->Checksum != 0)
+ {
+ USHORT udp_len = Endian16(udp->PacketLength);
+ USHORT udp_offloading_checksum1 = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_UDP, NULL, 0, udp_len);
+ USHORT udp_offloading_checksum2 = ~udp_offloading_checksum1;
+
+ if (udp->Checksum == udp_offloading_checksum1 || udp->Checksum == udp_offloading_checksum2)
+ {
+ udp->Checksum = 0;
+
+ if ((IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // Calculate the checksum correctly based on the data in case of a non-fragmented packet
+ udp->Checksum = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_UDP, udp, udp_len, 0);
+ }
+ else
+ {
+ // In case of the first fragment of the packet, set the checksum to 0
+ // because there isn't entire data of the packet
+ udp->Checksum = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (p->TypeL3 == L3_IPV6)
+ {
+ IPV6_HEADER *v6 = p->L3.IPv6Header;
+ IPV6_HEADER_PACKET_INFO *v6info = &p->IPv6HeaderPacketInfo;
+
+ if (v6 != NULL)
+ {
+ if (p->TypeL4 == L4_TCP)
+ {
+ // Recalculate the TCP checksum
+ if (v6info->IsFragment == false)
+ {
+ if (v6info->FragmentHeader == NULL || ((IPV6_GET_FLAGS(v6info->FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS) == 0))
+ {
+ // TCP checksuming doesn't target fragmented packets
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ if (tcp != NULL)
+ {
+ UINT tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ USHORT tcp_offloading_checksum1 = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_TCP, NULL, 0, v6info->PayloadSize);
+ USHORT tcp_offloading_checksum2 = ~tcp_offloading_checksum1;
+
+ if (tcp->Checksum == 0 || tcp->Checksum == tcp_offloading_checksum1 || tcp->Checksum == tcp_offloading_checksum2)
+ {
+ tcp->Checksum = 0;
+ tcp->Checksum = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_TCP, tcp, v6info->PayloadSize, 0);
+ }
+ }
+ }
+ }
+ }
+ else if (p->TypeL4 == L4_UDP)
+ {
+ // Recalculation of the UDP checksum
+ if (v6info->IsFragment == false)
+ {
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ if (udp != NULL && udp->Checksum != 0)
+ {
+ USHORT udp_len = Endian16(udp->PacketLength);
+ USHORT udp_offloading_checksum1 = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_UDP, NULL, 0, udp_len);
+ USHORT udp_offloading_checksum2 = ~udp_offloading_checksum1;
+
+ if (udp->Checksum == 0 || udp->Checksum == udp_offloading_checksum1 || udp->Checksum == udp_offloading_checksum2)
+ {
+ udp->Checksum = 0;
+
+ if (v6info->FragmentHeader == NULL || ((IPV6_GET_FLAGS(v6info->FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS) == 0))
+ {
+ // If the packet is not fragmented, recalculate the checksum
+ udp->Checksum = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_UDP, udp, udp_len, 0);
+ }
+ else
+ {
+ // Don't do (can't do) anything in the case of fragmented packet
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// Parse the HTTP access log
+HTTPLOG *ParseHttpAccessLog(PKT *pkt)
+{
+ HTTPLOG h;
+ UCHAR *buf;
+ UINT size;
+ BUF *b;
+ char *line1;
+ bool ok = false;
+ // Validate arguments
+ if (pkt == NULL)
+ {
+ return NULL;
+ }
+
+ buf = pkt->Payload;
+ size = pkt->PayloadSize;
+
+ if (size <= 5)
+ {
+ return NULL;
+ }
+
+ // Check whether it starts with the HTTP-specific string
+ if (CmpCaseIgnore(buf, "GET ", 4) != 0 &&
+ CmpCaseIgnore(buf, "HEAD ", 5) != 0 &&
+ CmpCaseIgnore(buf, "POST ", 5) != 0)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+
+ h.Port = Endian16(pkt->L4.TCPHeader->DstPort);
+
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBuf(b, 0, 0);
+
+ line1 = CfgReadNextLine(b);
+
+ if (line1 != NULL)
+ {
+ TOKEN_LIST *tokens = ParseToken(line1, " \t");
+ if (tokens != NULL)
+ {
+ if (tokens->NumTokens == 3)
+ {
+ StrCpy(h.Method, sizeof(h.Hostname), tokens->Token[0]);
+ Trim(h.Method);
+
+ StrCpy(h.Path, sizeof(h.Path), tokens->Token[1]);
+ Trim(h.Path);
+
+ StrCpy(h.Protocol, sizeof(h.Protocol), tokens->Token[2]);
+ Trim(h.Protocol);
+
+ StrUpper(h.Method);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ UINT i;
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ i = SearchStr(line, ":", 0);
+ if (i != INFINITE && i < (MAX_SIZE / 2))
+ {
+ char name[MAX_SIZE];
+ char value[MAX_SIZE];
+
+ StrCpy(name, sizeof(name), line);
+ name[i] = 0;
+ Trim(name);
+
+ StrCpy(value, sizeof(value), line + i + 1);
+ Trim(value);
+
+ if (StrCmpi(name, "host") == 0)
+ {
+ StrCpy(h.Hostname, sizeof(h.Hostname), value);
+ }
+ else if (StrCmpi(name, "referer") == 0)
+ {
+ StrCpy(h.Referer, sizeof(h.Referer), value);
+ }
+ else if (StrCmpi(name, "user-agent") == 0)
+ {
+ StrCpy(h.UserAgent, sizeof(h.UserAgent), value);
+ }
+ }
+
+ Free(line);
+ }
+
+ if (IsEmptyStr(h.Hostname) == false)
+ {
+ ok = true;
+ }
+ }
+ FreeToken(tokens);
+ }
+ }
+
+ Free(line1);
+ FreeBuf(b);
+
+ if (ok)
+ {
+ return Clone(&h, sizeof(h));
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+// Layer-2 parsing
+bool ParsePacketL2(PKT *p, UCHAR *buf, UINT size)
+{
+ return ParsePacketL2Ex(p, buf, size, false);
+}
+bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
+{
+ UINT i;
+ bool b1, b2;
+ USHORT type_id_16;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(MAC_HEADER))
+ {
+ return false;
+ }
+
+ // MAC header
+ p->MacHeader = (MAC_HEADER *)buf;
+
+ buf += sizeof(MAC_HEADER);
+ size -= sizeof(MAC_HEADER);
+
+ // Analysis of the MAC header
+ p->BroadcastPacket = true;
+ b1 = true;
+ b2 = true;
+ for (i = 0;i < 6;i++)
+ {
+ if (p->MacHeader->DestAddress[i] != 0xff)
+ {
+ p->BroadcastPacket = false;
+ }
+ if (p->MacHeader->SrcAddress[i] != 0xff)
+ {
+ b1 = false;
+ }
+ if (p->MacHeader->SrcAddress[i] != 0x00)
+ {
+ b2 = false;
+ }
+ }
+ if (b1 || b2 || (Cmp(p->MacHeader->SrcAddress, p->MacHeader->DestAddress, 6) == 0))
+ {
+ p->InvalidSourcePacket = true;
+ }
+ else
+ {
+ p->InvalidSourcePacket = false;
+ }
+
+ if (p->MacHeader->DestAddress[0] & 0x01)
+ {
+ p->BroadcastPacket = true;
+ }
+
+ // Parse L3 packet
+ type_id_16 = Endian16(p->MacHeader->Protocol);
+
+ if (type_id_16 > 1500)
+ {
+ // Ordinary Ethernet frame
+ switch (type_id_16)
+ {
+ case MAC_PROTO_ARPV4: // ARPv4
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketARPv4(p, buf, size);
+
+ case MAC_PROTO_IPV4: // IPv4
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketIPv4(p, buf, size);
+
+ case MAC_PROTO_IPV6: // IPv6
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketIPv6(p, buf, size);
+
+ default: // Unknown
+ if (type_id_16 == p->VlanTypeID)
+ {
+ // VLAN
+ return ParsePacketTAGVLAN(p, buf, size);
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // Old IEEE 802.3 frame (payload length of the packet is written in the header)
+ // (It has been used in the BPDU, etc.)
+ UINT length = (UINT)type_id_16;
+ LLC_HEADER *llc;
+
+ // Check whether the length is remaining
+ if (size < length || size < sizeof(LLC_HEADER))
+ {
+ return true;
+ }
+
+ // Read an LLC header
+ llc = (LLC_HEADER *)buf;
+ buf += sizeof(LLC_HEADER);
+ size -= sizeof(LLC_HEADER);
+
+ // Determine the protocol by the value of DSAP and SSAP
+ if (llc->Dsap == LLC_DSAP_BPDU && llc->Ssap == LLC_SSAP_BPDU)
+ {
+ // This is a BPDU (Spanning Tree)
+ return ParsePacketBPDU(p, buf, size);
+ }
+ else
+ {
+ // Unknown protocol
+ return true;
+ }
+ }
+}
+
+// TAG VLAN parsing
+bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size)
+{
+ USHORT vlan_ushort;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(TAGVLAN_HEADER))
+ {
+ return false;
+ }
+
+ // TAG VLAN header
+ p->L3.TagVlanHeader = (TAGVLAN_HEADER *)buf;
+ p->TypeL3 = L3_TAGVLAN;
+
+ buf += sizeof(TAGVLAN_HEADER);
+ size -= sizeof(TAGVLAN_HEADER);
+
+ vlan_ushort = READ_USHORT(p->L3.TagVlanHeader->Data);
+ vlan_ushort = vlan_ushort & 0xFFF;
+
+ p->VlanId = vlan_ushort;
+
+ return true;
+}
+
+// BPDU Parsing
+bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(BPDU_HEADER))
+ {
+ return true;
+ }
+
+ // BPDU header
+ p->L3.BpduHeader = (BPDU_HEADER *)buf;
+ p->TypeL3 = L3_BPDU;
+
+ buf += sizeof(BPDU_HEADER);
+ size -= sizeof(BPDU_HEADER);
+
+ return true;
+}
+
+// ARPv4 Parsing
+bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(ARPV4_HEADER))
+ {
+ return false;
+ }
+
+ // ARPv4 header
+ p->L3.ARPv4Header = (ARPV4_HEADER *)buf;
+ p->TypeL3 = L3_ARPV4;
+
+ buf += sizeof(ARPV4_HEADER);
+ size -= sizeof(ARPV4_HEADER);
+
+ return true;
+}
+
+// Analysis of the IPv6 extension header
+bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size)
+{
+ bool ret = false;
+ IPV6_OPTION_HEADER *option_header;
+ UINT option_header_size;
+ UCHAR next_header_2 = IPV6_HEADER_NONE;
+ // Validate arguments
+ if (info == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ info->IsFragment = false;
+
+ while (true)
+ {
+ if (size > 8)
+ {
+ next_header_2 = *((UCHAR *)buf);
+ }
+
+ switch (next_header)
+ {
+ case IPV6_HEADER_HOP:
+ case IPV6_HEADER_ENDPOINT:
+ case IPV6_HEADER_ROUTING:
+ // Variable-length header
+ if (size < 8)
+ {
+ return false;
+ }
+
+ option_header = (IPV6_OPTION_HEADER *)buf;
+ option_header_size = (option_header->Size + 1) * 8;
+ if (size < option_header_size)
+ {
+ return false;
+ }
+
+ switch (next_header)
+ {
+ case IPV6_HEADER_HOP:
+ info->HopHeader = (IPV6_OPTION_HEADER *)buf;
+ info->HopHeaderSize = option_header_size;
+ break;
+
+ case IPV6_HEADER_ENDPOINT:
+ info->EndPointHeader = (IPV6_OPTION_HEADER *)buf;
+ info->EndPointHeaderSize = option_header_size;
+ break;
+
+ case IPV6_HEADER_ROUTING:
+ info->RoutingHeader = (IPV6_OPTION_HEADER *)buf;
+ info->RoutingHeaderSize = option_header_size;
+ break;
+ }
+
+ buf += option_header_size;
+ size -= option_header_size;
+ break;
+
+ case IPV6_HEADER_FRAGMENT:
+ // Fragment header (fixed length)
+ if (size < sizeof(IPV6_FRAGMENT_HEADER))
+ {
+ return false;
+ }
+
+ info->FragmentHeader = (IPV6_FRAGMENT_HEADER *)buf;
+
+ if (IPV6_GET_FRAGMENT_OFFSET(info->FragmentHeader) != 0)
+ {
+ info->IsFragment = true;
+ }
+
+ buf += sizeof(IPV6_FRAGMENT_HEADER);
+ size -= sizeof(IPV6_FRAGMENT_HEADER);
+ break;
+
+ default:
+ // Considered that the payload follows
+ if (next_header != IPV6_HEADER_NONE)
+ {
+ info->Payload = buf;
+ info->PayloadSize = size;
+ }
+ else
+ {
+ info->Payload = NULL;
+ info->PayloadSize = 0;
+ }
+ info->Protocol = next_header;
+ return true;
+ }
+
+ next_header = next_header_2;
+ }
+}
+
+// Analysis of the IPv6 header
+bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (info == NULL || buf == NULL)
+ {
+ Zero(info, sizeof(IPV6_HEADER_PACKET_INFO));
+ return false;
+ }
+
+ Zero(info, sizeof(IPV6_HEADER_PACKET_INFO));
+
+ // IPv6 header
+ if (size < sizeof(IPV6_HEADER))
+ {
+ // Invalid size
+ return false;
+ }
+
+ info->IPv6Header = (IPV6_HEADER *)buf;
+ buf += sizeof(IPV6_HEADER);
+ size -= sizeof(IPV6_HEADER);
+
+ if (IPV6_GET_VERSION(info->IPv6Header) != 6)
+ {
+ // Invalid version
+ return false;
+ }
+
+ // Analysis of the extension header
+ if (ParseIPv6ExtHeader(info, info->IPv6Header->NextHeader, buf, size) == false)
+ {
+ return false;
+ }
+
+ // Record the header size
+ if (info->Payload != NULL)
+ {
+ info->TotalHeaderSize = (UINT)((UINT64)(info->Payload) - (UINT64)(info->IPv6Header));
+ }
+
+ return true;
+}
+
+// Analyse the options of ICMPv6 packet
+bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(o, sizeof(ICMPV6_OPTION_LIST));
+
+ // Read the header part
+ while (true)
+ {
+ ICMPV6_OPTION *option_header;
+ UINT header_total_size;
+ UCHAR *header_pointer;
+ if (size < sizeof(ICMPV6_OPTION))
+ {
+ // Size shortage
+ return true;
+ }
+
+ option_header = (ICMPV6_OPTION *)buf;
+ // Calculate the entire header size
+ header_total_size = option_header->Length * 8;
+ if (header_total_size == 0)
+ {
+ // The size is zero
+ return true;
+ }
+ if (size < header_total_size)
+ {
+ // Size shortage
+ return true;
+ }
+
+ header_pointer = buf;
+ buf += header_total_size;
+ size -= header_total_size;
+
+ switch (option_header->Type)
+ {
+ case ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER:
+ case ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER:
+ // Source or target link-layer option
+ if (header_total_size >= sizeof(ICMPV6_OPTION_LINK_LAYER))
+ {
+ if (option_header->Type == ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER)
+ {
+ o->SourceLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
+ }
+ else
+ {
+ o->TargetLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
+ }
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ return false;
+ }
+ break;
+
+ case ICMPV6_OPTION_TYPE_PREFIX:
+ // Prefix Information
+ if (header_total_size >= sizeof(ICMPV6_OPTION_PREFIX))
+ {
+ o->Prefix = (ICMPV6_OPTION_PREFIX *)header_pointer;
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ }
+ break;
+
+ case ICMPV6_OPTION_TYPE_MTU:
+ // MTU
+ if (header_total_size >= sizeof(ICMPV6_OPTION_MTU))
+ {
+ o->Mtu = (ICMPV6_OPTION_MTU *)header_pointer;
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ }
+ break;
+ }
+ }
+}
+
+// ICMPv6 parsing
+bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size)
+{
+ ICMPV6_HEADER_INFO icmp_info;
+ ICMP_HEADER *icmp;
+ ICMP_ECHO *echo;
+ UINT msg_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(&icmp_info, sizeof(icmp_info));
+
+ if (size < sizeof(ICMP_HEADER))
+ {
+ return false;
+ }
+
+ icmp = (ICMP_HEADER *)buf;
+ p->L4.ICMPHeader = icmp;
+
+ msg_size = size - sizeof(ICMP_HEADER);
+
+ icmp_info.Type = icmp->Type;
+ icmp_info.Code = icmp->Code;
+ icmp_info.Data = ((UCHAR *)buf) + sizeof(ICMP_HEADER);
+ icmp_info.DataSize = msg_size;
+
+ switch (icmp_info.Type)
+ {
+ case ICMPV6_TYPE_ECHO_REQUEST:
+ case ICMPV6_TYPE_ECHO_RESPONSE:
+ // ICMP Echo Request / Response
+ if (icmp_info.DataSize < sizeof(ICMP_ECHO))
+ {
+ return false;
+ }
+
+ echo = (ICMP_ECHO *)icmp_info.Data;
+
+ icmp_info.EchoHeader.Identifier = Endian16(echo->Identifier);
+ icmp_info.EchoHeader.SeqNo = Endian16(echo->SeqNo);
+ icmp_info.EchoData = (UCHAR *)echo + sizeof(ICMP_ECHO);
+ icmp_info.EchoDataSize = icmp_info.DataSize - sizeof(ICMP_ECHO);
+
+ break;
+
+ case ICMPV6_TYPE_ROUTER_SOLICIATION:
+ // Router Solicitation
+ if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.RouterSoliciationHeader =
+ (ICMPV6_ROUTER_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
+ // Router Advertisement
+ if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.RouterAdvertisementHeader =
+ (ICMPV6_ROUTER_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
+ // Neighbor Solicitation
+ if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.NeighborSoliciationHeader =
+ (ICMPV6_NEIGHBOR_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
+ // Neighbor Advertisement
+ if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.NeighborAdvertisementHeader =
+ (ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+ }
+
+ p->TypeL4 = L4_ICMPV6;
+ Copy(&p->ICMPv6HeaderPacketInfo, &icmp_info, sizeof(ICMPV6_HEADER_INFO));
+
+ return true;
+}
+
+// Release of the ICMPv6 options
+void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Free(o->SourceLinkLayer);
+ Free(o->TargetLinkLayer);
+ Free(o->Prefix);
+ Free(o->Mtu);
+}
+
+// Clone of the ICMPv6 options
+void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ Zero(dst, sizeof(ICMPV6_OPTION_LIST));
+
+ dst->SourceLinkLayer = Clone(src->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ dst->TargetLinkLayer = Clone(src->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ dst->Prefix = Clone(src->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
+ dst->Mtu = Clone(src->Mtu, sizeof(ICMPV6_OPTION_MTU));
+}
+
+// IPv6 parsing
+bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ if (ParsePacketIPv6Header(&p->IPv6HeaderPacketInfo, buf, size) == false)
+ {
+ return false;
+ }
+
+ p->TypeL3 = L3_IPV6;
+ p->L3.IPv6Header = p->IPv6HeaderPacketInfo.IPv6Header;
+
+ if (p->IPv6HeaderPacketInfo.Payload == NULL)
+ {
+ // No payload
+ return true;
+ }
+
+ buf = p->IPv6HeaderPacketInfo.Payload;
+ size = p->IPv6HeaderPacketInfo.PayloadSize;
+
+ if (p->IPv6HeaderPacketInfo.IsFragment)
+ {
+ // This is a fragmented packet. Quit interpreting
+ p->TypeL4 = L4_FRAGMENT;
+ return true;
+ }
+
+ // Parse a L4 packet
+ switch (p->IPv6HeaderPacketInfo.Protocol)
+ {
+ case IP_PROTO_ICMPV6: // ICMPv6
+ if (ParseICMPv6(p, buf, size) == false)
+ {
+ // Returns true also if it fails to parse ICMPv6
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+
+ case IP_PROTO_TCP: // TCP
+ return ParseTCP(p, buf, size);
+
+ case IP_PROTO_UDP: // UDP
+ return ParseUDP(p, buf, size);
+
+ default: // Unknown
+ return true;
+ }
+
+ return true;
+}
+
+// Parse the IPv4 by adding a dummy MAC header
+PKT *ParsePacketIPv4WithDummyMacHeader(UCHAR *buf, UINT size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = size + 14;
+ tmp = Malloc(tmp_size);
+ Zero(tmp, 12);
+ WRITE_USHORT(tmp + 12, MAC_PROTO_IPV4);
+ Copy(tmp + 14, buf, size);
+
+ return ParsePacket(tmp, tmp_size);
+}
+
+// IPv4 parsing
+bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ UINT header_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(IPV4_HEADER))
+ {
+ return false;
+ }
+
+ // IPv4 header
+ p->L3.IPv4Header = (IPV4_HEADER *)buf;
+ p->TypeL3 = L3_IPV4;
+
+ // Check the header
+ header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
+ if (header_size < sizeof(IPV4_HEADER) || size < header_size)
+ {
+ // Header size is invalid
+ p->L3.IPv4Header = NULL;
+ p->TypeL3= L3_UNKNOWN;
+ return true;
+ }
+
+ buf += header_size;
+ size -= header_size;
+
+ p->IPv4PayloadSize = MIN(size, Endian16(p->L3.IPv4Header->TotalLength) - header_size);
+ if (Endian16(p->L3.IPv4Header->TotalLength) < header_size)
+ {
+ p->IPv4PayloadSize = 0;
+ }
+
+ p->IPv4PayloadData = buf;
+
+ if (IPV4_GET_OFFSET(p->L3.IPv4Header) != 0)
+ {
+ // Quit analysing since this is fragmented
+ p->TypeL4 = L4_FRAGMENT;
+ return true;
+ }
+
+ // Parse a L4 packet
+ switch (p->L3.IPv4Header->Protocol)
+ {
+ case IP_PROTO_ICMPV4: // ICMPv4
+ return ParseICMPv4(p, buf, size);
+
+ case IP_PROTO_UDP: // UDP
+ return ParseUDP(p, buf, size);
+
+ case IP_PROTO_TCP: // TCP
+ return ParseTCP(p, buf, size);
+
+ default: // Unknown
+ return true;
+ }
+}
+
+// ICMPv4 parsing
+bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(ICMP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // ICMPv4 header
+ p->L4.ICMPHeader = (ICMP_HEADER *)buf;
+ p->TypeL4 = L4_ICMPV4;
+
+ buf += sizeof(ICMP_HEADER);
+ size -= sizeof(ICMP_HEADER);
+
+ return true;
+}
+
+// TCP parsing
+bool ParseTCP(PKT *p, UCHAR *buf, UINT size)
+{
+ UINT header_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(TCP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // TCP header
+ p->L4.TCPHeader = (TCP_HEADER *)buf;
+ p->TypeL4 = L4_TCP;
+
+ // Check the header size
+ header_size = TCP_GET_HEADER_SIZE(p->L4.TCPHeader) * 4;
+ if (header_size < sizeof(TCP_HEADER) || size < header_size)
+ {
+ // Header size is invalid
+ p->L4.TCPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+ return true;
+ }
+
+ buf += header_size;
+ size -= header_size;
+
+ p->Payload = buf;
+ p->PayloadSize = size;
+
+ return true;
+}
+
+// UDP parsing
+bool ParseUDP(PKT *p, UCHAR *buf, UINT size)
+{
+ USHORT src_port, dst_port;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(UDP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // UDP header
+ p->L4.UDPHeader = (UDP_HEADER *)buf;
+ p->TypeL4 = L4_UDP;
+
+ buf += sizeof(UDP_HEADER);
+ size -= sizeof(UDP_HEADER);
+
+ p->Payload = buf;
+ p->PayloadSize = size;
+
+ // Check the port number
+ src_port = Endian16(p->L4.UDPHeader->SrcPort);
+ dst_port = Endian16(p->L4.UDPHeader->DstPort);
+
+ if ((src_port == 67 && dst_port == 68) ||
+ (src_port == 68 && dst_port == 67))
+ {
+ if (p->TypeL3 == L3_IPV4)
+ {
+ // A DHCP packet is found
+ ParseDHCPv4(p, buf, size);
+
+ return true;
+ }
+ }
+
+ if (src_port == 500 || dst_port == 500 || src_port == 4500 || dst_port == 4500)
+ {
+ if (p->PayloadSize >= sizeof(IKE_HEADER))
+ {
+ IKE_HEADER *ike_header = (IKE_HEADER *)p->Payload;
+
+ if (ike_header->InitiatorCookie != 0 && ike_header->ResponderCookie == 0 &&
+ (ike_header->ExchangeType == IKE_EXCHANGE_TYPE_MAIN ||
+ ike_header->ExchangeType == IKE_EXCHANGE_TYPE_AGGRESSIVE))
+ {
+ // the IKE connection request packet is found
+ p->TypeL7 = L7_IKECONN;
+ p->L7.IkeHeader = ike_header;
+ return true;
+ }
+ }
+ }
+
+ // Determine whether it's an OpenVPN UDP packet
+ if (size == 14)
+ {
+ if (buf[0] == 0x38)
+ {
+ if (IsZero(buf + 9, 5))
+ {
+ if (IsZero(buf + 1, 8) == false)
+ {
+ // An OpenVPN connection request packet is found
+ p->TypeL7 = L7_OPENVPNCONN;
+ return true;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// DHCPv4 parsing
+void ParseDHCPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return;
+ }
+
+ // Check the size
+ if (size < sizeof(DHCPV4_HEADER))
+ {
+ // Size is invalid
+ return;
+ }
+
+ // DHCPv4 header
+ p->L7.DHCPv4Header = (DHCPV4_HEADER *)buf;
+ p->TypeL7 = L7_DHCPV4;
+}
+
+// Release the memory of the packet
+void FreePacket(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->MacHeader != NULL)
+ {
+ switch (p->TypeL3)
+ {
+ case L3_IPV4:
+ FreePacketIPv4(p);
+ break;
+
+ case L3_ARPV4:
+ FreePacketARPv4(p);
+ break;
+
+ case L3_TAGVLAN:
+ FreePacketTagVlan(p);
+ break;
+ }
+ }
+
+ if (p->HttpLog != NULL)
+ {
+ Free(p->HttpLog);
+ }
+
+ Free(p);
+}
+
+// Release the memory of the packet with data
+void FreePacketWithData(PKT *p)
+{
+ void *data;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ data = p->PacketData;
+
+ FreePacket(p);
+
+ Free(data);
+}
+
+// Release the memory for the IPv4 packet
+void FreePacketIPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ switch (p->TypeL4)
+ {
+ case L4_ICMPV4:
+ FreePacketICMPv4(p);
+ break;
+
+ case L4_TCP:
+ FreePacketTCPv4(p);
+ break;
+
+ case L4_UDP:
+ FreePacketUDPv4(p);
+ break;
+ }
+
+ p->L3.IPv4Header = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory for the tagged VLAN packet
+void FreePacketTagVlan(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L3.TagVlanHeader = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory for the ARPv4 packet
+void FreePacketARPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L3.ARPv4Header = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory of the UDPv4 packet
+void FreePacketUDPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ switch (p->TypeL7)
+ {
+ case L7_DHCPV4:
+ FreePacketDHCPv4(p);
+ break;
+ }
+
+ p->L4.UDPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the TCPv4 packet
+void FreePacketTCPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L4.TCPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the ICMPv4 packet
+void FreePacketICMPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L4.ICMPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the DHCPv4 packet
+void FreePacketDHCPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L7.DHCPv4Header = NULL;
+ p->TypeL7 = L7_UNKNOWN;
+}
+
+
+// Confirm the checksum of the IP header
+bool IpCheckChecksum(IPV4_HEADER *ip)
+{
+ UINT header_size;
+ USHORT checksum_original, checksum_calc;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ checksum_original = ip->Checksum;
+ ip->Checksum = 0;
+ checksum_calc = IpChecksum(ip, header_size);
+ ip->Checksum = checksum_original;
+
+ if (checksum_original == checksum_calc)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Calculate the checksum
+USHORT IpChecksum(void *buf, UINT size)
+{
+ int sum = 0;
+ USHORT *addr = (USHORT *)buf;
+ int len = (int)size;
+ USHORT *w = addr;
+ int nleft = len;
+ USHORT answer = 0;
+
+ while (nleft > 1)
+ {
+ USHORT ww = 0;
+ Copy(&ww, w++, sizeof(USHORT));
+ sum += ww;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *(UCHAR *)(&answer) = *(UCHAR *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ answer = ~sum;
+
+ return answer;
+}
+
+// Convert a DHCP option list into a buffer
+BUF *BuildDhcpOptionsBuf(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ UCHAR id;
+ UCHAR sz;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *d = LIST_DATA(o, i);
+ id = (UCHAR)d->Id;
+ sz = (UCHAR)d->Size;
+ WriteBuf(b, &id, 1);
+ WriteBuf(b, &sz, 1);
+ WriteBuf(b, d->Data, d->Size);
+ }
+
+ id = 0xff;
+ WriteBuf(b, &id, 1);
+
+ return b;
+}
+
+// Convert a DHCP option list to the DHCP option
+LIST *BuildDhcpOption(DHCP_OPTION_LIST *opt)
+{
+ LIST *o;
+ UCHAR opcode;
+ BUF *dns_buf;
+ // Validate arguments
+ if (opt == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ // Op-code
+ opcode = (UCHAR)opt->Opcode;
+ Add(o, NewDhcpOption(DHCP_ID_MESSAGE_TYPE, &opcode, sizeof(opcode)));
+ Add(o, NewDhcpOption(DHCP_ID_SERVER_ADDRESS, &opt->ServerAddress, sizeof(opt->ServerAddress)));
+
+ if (opt->LeaseTime != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_LEASE_TIME, &opt->LeaseTime, sizeof(opt->LeaseTime)));
+ }
+
+ if (StrLen(opt->DomainName) != 0 && opt->DnsServer != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_DOMAIN_NAME, opt->DomainName, StrLen(opt->DomainName)));
+ }
+ if (opt->SubnetMask != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_SUBNET_MASK, &opt->SubnetMask, sizeof(opt->SubnetMask)));
+ }
+ if (opt->Gateway != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_GATEWAY_ADDR, &opt->Gateway, sizeof(opt->Gateway)));
+ }
+
+ dns_buf = NewBuf();
+
+ if (opt->DnsServer != 0)
+ {
+ WriteBuf(dns_buf, &opt->DnsServer, sizeof(opt->DnsServer));
+ }
+ if (opt->DnsServer2 != 0)
+ {
+ WriteBuf(dns_buf, &opt->DnsServer2, sizeof(opt->DnsServer2));
+ }
+
+ if (dns_buf->Size >= 1)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_DNS_ADDR, dns_buf->Buf, dns_buf->Size));
+ }
+
+ FreeBuf(dns_buf);
+
+ return o;
+}
+
+// Create a new DHCP option item
+DHCP_OPTION *NewDhcpOption(UINT id, void *data, UINT size)
+{
+ DHCP_OPTION *ret;
+ if (size != 0 && data == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(DHCP_OPTION));
+ ret->Data = ZeroMalloc(size);
+ Copy(ret->Data, data, size);
+ ret->Size = (UCHAR)size;
+ ret->Id = (UCHAR)id;
+
+ return ret;
+}
+
+// Parse a DHCP options list
+DHCP_OPTION_LIST *ParseDhcpOptionList(void *data, UINT size)
+{
+ DHCP_OPTION_LIST *ret;
+ LIST *o;
+ DHCP_OPTION *a;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ // Parse the list
+ o = ParseDhcpOptions(data, size);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(DHCP_OPTION_LIST));
+
+ // Get the opcode
+ a = GetDhcpOption(o, DHCP_ID_MESSAGE_TYPE);
+ if (a != NULL)
+ {
+ if (a->Size == 1)
+ {
+ ret->Opcode = *((UCHAR *)a->Data);
+ }
+ }
+
+ switch (ret->Opcode)
+ {
+ case DHCP_DISCOVER:
+ case DHCP_REQUEST:
+ // Parse this more finely because this is client requests
+ // Requested IP address
+ a = GetDhcpOption(o, DHCP_ID_REQUEST_IP_ADDRESS);
+ if (a != NULL && a->Size == 4)
+ {
+ Copy(&ret->RequestedIp, a->Data, 4);
+ }
+ // Host name
+ a = GetDhcpOption(o, DHCP_ID_HOST_NAME);
+ if (a != NULL)
+ {
+ if (a->Size > 1)
+ {
+ Copy(ret->Hostname, a->Data, MIN(a->Size, sizeof(ret->Hostname) - 1));
+ }
+ }
+ break;
+
+ case DHCP_OFFER:
+ case DHCP_ACK:
+ // Subnet mask
+ a = GetDhcpOption(o, DHCP_ID_SUBNET_MASK);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->SubnetMask, a->Data, 4);
+ }
+
+ // Lease time
+ a = GetDhcpOption(o, DHCP_ID_LEASE_TIME);
+ if (a != NULL && a->Size == 4)
+ {
+ ret->LeaseTime = READ_UINT(a->Data);
+ }
+
+ // Server IP address
+ a = GetDhcpOption(o, DHCP_ID_SERVER_ADDRESS);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->ServerAddress, a->Data, 4);
+ }
+
+ // Domain name
+ a = GetDhcpOption(o, DHCP_ID_DOMAIN_NAME);
+ if (a != NULL && a->Size >= 1)
+ {
+ Zero(ret->DomainName, sizeof(ret->DomainName));
+ Copy(ret->DomainName, a->Data, MIN(a->Size, sizeof(ret->DomainName) - 1));
+ }
+
+ // Gateway
+ a = GetDhcpOption(o, DHCP_ID_GATEWAY_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->Gateway, a->Data, 4);
+ }
+
+ // DNS server
+ a = GetDhcpOption(o, DHCP_ID_DNS_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->DnsServer, a->Data, 4);
+
+ if (a->Size >= 8)
+ {
+ Copy(&ret->DnsServer2, ((UCHAR *)a->Data) + 4, 4);
+ }
+ }
+
+ // WINS server
+ a = GetDhcpOption(o, DHCP_ID_WINS_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->WinsServer, a->Data, 4);
+
+ if (a->Size >= 8)
+ {
+ Copy(&ret->WinsServer2, ((UCHAR *)a->Data) + 4, 4);
+ }
+ }
+
+ break;
+ }
+
+ // Release the list
+ FreeDhcpOptions(o);
+
+ return ret;
+}
+
+// Finding a DHCP option
+DHCP_OPTION *GetDhcpOption(LIST *o, UINT id)
+{
+ UINT i;
+ DHCP_OPTION *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *opt = LIST_DATA(o, i);
+ if (opt->Id == id)
+ {
+ ret = opt;
+ }
+ }
+
+ return ret;
+}
+
+// Release the DHCP option
+void FreeDhcpOptions(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *opt = LIST_DATA(o, i);
+ Free(opt->Data);
+ Free(opt);
+ }
+
+ ReleaseList(o);
+}
+
+// Parse the DHCP Options
+LIST *ParseDhcpOptions(void *data, UINT size)
+{
+ BUF *b;
+ LIST *o;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ o = NewListFast(NULL);
+
+ while (true)
+ {
+ UCHAR c = 0;
+ UCHAR sz = 0;
+ DHCP_OPTION *opt;
+ if (ReadBuf(b, &c, 1) != 1)
+ {
+ break;
+ }
+ if (c == 0xff)
+ {
+ break;
+ }
+ if (ReadBuf(b, &sz, 1) != 1)
+ {
+ break;
+ }
+
+ opt = ZeroMalloc(sizeof(DHCP_OPTION));
+ opt->Id = (UINT)c;
+ opt->Size = (UINT)sz;
+ opt->Data = ZeroMalloc((UINT)sz);
+ ReadBuf(b, opt->Data, sz);
+ Add(o, opt);
+ }
+
+ FreeBuf(b);
+
+ return o;
+}
+
+// Rewrite the DHCP message data in the requested IPv4 packet appropriately
+BUF *DhcpModifyIPv4(DHCP_MODIFY_OPTION *m, void *data, UINT size)
+{
+ PKT *p;
+ BUF *ret = NULL;
+ // Validate arguments
+ if (m == NULL || data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ p = ParsePacketEx4(data, size, false, 0, false, false, false);
+
+ if (p != NULL && p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
+ {
+ BUF *new_buf = DhcpModify(m, p->Payload, p->PayloadSize);
+
+ if (new_buf != NULL)
+ {
+ ret = NewBuf();
+
+ WriteBuf(ret, p->PacketData, p->PacketSize - p->PayloadSize);
+ WriteBuf(ret, new_buf->Buf, new_buf->Size);
+
+ FreeBuf(new_buf);
+ }
+ }
+
+ FreePacket(p);
+
+ if (ret != NULL)
+ {
+ PKT *p = ParsePacketEx4(ret->Buf, ret->Size, false, 0, false, false, false);
+
+ if (p != NULL)
+ {
+ // Recalculation of the UDP checksum
+ if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP)
+ {
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ udp->Checksum = 0;
+ udp->Checksum = CalcChecksumForIPv4(p->L3.IPv4Header->SrcIP,
+ p->L3.IPv4Header->DstIP,
+ IP_PROTO_UDP,
+ udp,
+ p->PacketSize - (UINT)(((UCHAR *)udp) - ((UCHAR *)p->PacketData)), 0);
+ }
+
+ FreePacket(p);
+ }
+ }
+
+ return ret;
+}
+
+// Rewrite the DHCP packet appropriately
+BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size)
+{
+ DHCPV4_HEADER *dhcp_header;
+ UCHAR *data_ptr;
+ bool ret_ok = false;
+ BUF *ret = NULL;
+ BUF *opt_buf = NULL;
+ UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
+ bool ok = false;
+ DHCP_OPTION_LIST *opt = NULL;
+ LIST *opt_list = NULL;
+ LIST *opt_list2 = NULL;
+ UINT src_size = size;
+ UINT i;
+ // Validate arguments
+ if (m == NULL || data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ data_ptr = (UCHAR *)data;
+
+ if (size < sizeof(DHCPV4_HEADER))
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ dhcp_header = (DHCPV4_HEADER *)data_ptr;
+ data_ptr += sizeof(DHCPV4_HEADER);
+
+ // Search for a Magic Cookie
+ while (size >= 5)
+ {
+ if (Cmp(data_ptr, &magic_cookie, sizeof(UINT)) == 0)
+ {
+ // Found
+ data_ptr += sizeof(UINT);
+ size -= sizeof(UINT);
+ ok = true;
+ break;
+ }
+
+ data_ptr++;
+ size--;
+ }
+
+ if (ok == false)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, data, (UINT)(data_ptr - ((UCHAR *)data)));
+
+ // Parse the DHCP options list
+ opt = ParseDhcpOptionList(data_ptr, size);
+ if (opt == NULL)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ opt_list = ParseDhcpOptions(data_ptr, size);
+ if (opt_list == NULL)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ // Rebuilding the options list
+ opt_list2 = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(opt_list);i++)
+ {
+ DHCP_OPTION *o = LIST_DATA(opt_list, i);
+ DHCP_OPTION *o2 = NULL;
+ bool ok = true;
+
+ if (m->RemoveDefaultGatewayOnReply)
+ {
+ if (opt->Opcode == DHCP_OFFER || opt->Opcode == DHCP_ACK)
+ {
+ // Remove the default gateway from the DHCP Reply
+ if (o->Id == DHCP_ID_GATEWAY_ADDR)
+ {
+ ok = false;
+ }
+ if (o->Id == DHCP_ID_DNS_ADDR || o->Id == DHCP_ID_WINS_ADDR || o->Id == DHCP_ID_DOMAIN_NAME)
+ {
+ ok = false;
+ }
+ }
+ }
+
+ if (ok && o2 == NULL)
+ {
+ o2 = NewDhcpOption(o->Id, o->Data, o->Size);
+ }
+
+ if (o2 != NULL)
+ {
+ Add(opt_list2, o2);
+ }
+ }
+
+ opt_buf = BuildDhcpOptionsBuf(opt_list2);
+
+ WriteBuf(ret, opt_buf->Buf, opt_buf->Size);
+
+ if (src_size != ret->Size || Cmp(data, ret->Buf, ret->Size) != 0)
+ {
+ // Rewrite if anything changes. Do not rewrite if there is no change
+ ret_ok = true;
+
+ if (ret->Size < DHCP_MIN_SIZE)
+ {
+ // Padding
+ UCHAR *pad_buf;
+ UINT pad_size = DHCP_MIN_SIZE - ret->Size;
+
+ pad_buf = ZeroMalloc(pad_size);
+
+ WriteBuf(ret, pad_buf, pad_size);
+
+ Free(pad_buf);
+ }
+ }
+
+LABEL_CLEANUP:
+ // Memory release
+ if (opt_buf != NULL)
+ {
+ FreeBuf(opt_buf);
+ }
+
+ if (opt != NULL)
+ {
+ Free(opt);
+ }
+
+ if (opt_list != NULL)
+ {
+ FreeDhcpOptions(opt_list);
+ }
+
+ if (opt_list2 != NULL)
+ {
+ FreeDhcpOptions(opt_list2);
+ }
+
+ // Return a value
+ if (ret_ok)
+ {
+ return ret;
+ }
+ else
+ {
+ FreeBuf(ret);
+ return NULL;
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TcpIp.h b/src/Mayaqua/TcpIp.h
new file mode 100644
index 00000000..0740460a
--- /dev/null
+++ b/src/Mayaqua/TcpIp.h
@@ -0,0 +1,876 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// TcpIp.h
+// Header of TcpIp.c
+
+#ifndef TCPIP_H
+#define TCPIP_H
+
+#ifdef OS_WIN32
+#pragma pack(push, 1)
+#endif // OS_WIN32
+
+// MTU when using of the PPPoE
+#define MTU_FOR_PPPOE (1500 - 46)
+
+// MAC header
+struct MAC_HEADER
+{
+ UCHAR DestAddress[6]; // Source MAC address
+ UCHAR SrcAddress[6]; // Destination MAC address
+ USHORT Protocol; // Protocol
+} GCC_PACKED;
+
+// MAC protocol
+#define MAC_PROTO_ARPV4 0x0806 // ARPv4 packet
+#define MAC_PROTO_IPV4 0x0800 // IPv4 packets
+#define MAC_PROTO_IPV6 0x86dd // IPv6 packets
+#define MAC_PROTO_TAGVLAN 0x8100 // Tagged VLAN packets
+
+// LLC header
+struct LLC_HEADER
+{
+ UCHAR Dsap;
+ UCHAR Ssap;
+ UCHAR Ctl;
+} GCC_PACKED;
+
+// The value of the SSAP and the DSAP of the LLC header
+#define LLC_DSAP_BPDU 0x42
+#define LLC_SSAP_BPDU 0x42
+
+// BPDU header
+struct BPDU_HEADER
+{
+ USHORT ProtocolId; // Protocol ID (STP == 0x0000)
+ UCHAR Version; // Version
+ UCHAR Type; // Type
+ UCHAR Flags; // Flag
+ USHORT RootPriority; // Priority of the root bridge
+ UCHAR RootMacAddress[6]; // MAC address of the root bridge
+ UINT RootPathCost; // Path cost to the root bridge
+ USHORT BridgePriority; // Priority of the outgoing bridge
+ UCHAR BridgeMacAddress[6]; // MAC address of the outgoing bridge
+ USHORT BridgePortId; // Port ID of the outgoing bridge
+ USHORT MessageAge; // Expiration date
+ USHORT MaxAge; // Maximum expiration date
+ USHORT HelloTime; // Hello Time
+ USHORT ForwardDelay; // Forward Delay
+} GCC_PACKED;
+
+// ARPv4 header
+struct ARPV4_HEADER
+{
+ USHORT HardwareType; // Hardware type
+ USHORT ProtocolType; // Protocol type
+ UCHAR HardwareSize; // Hardware size
+ UCHAR ProtocolSize; // Protocol size
+ USHORT Operation; // Operation
+ UCHAR SrcAddress[6]; // Source MAC address
+ UINT SrcIP; // Source IP address
+ UCHAR TargetAddress[6]; // Target MAC address
+ UINT TargetIP; // Target IP address
+} GCC_PACKED;
+
+// ARP hardware type
+#define ARP_HARDWARE_TYPE_ETHERNET 0x0001
+
+// ARP operation type
+#define ARP_OPERATION_REQUEST 1
+#define ARP_OPERATION_RESPONSE 2
+
+// Tagged VLAN header
+struct TAGVLAN_HEADER
+{
+ UCHAR Data[2]; // Data
+} GCC_PACKED;
+
+// IPv4 header
+struct IPV4_HEADER
+{
+ UCHAR VersionAndHeaderLength; // Version and header size
+ UCHAR TypeOfService; // Service Type
+ USHORT TotalLength; // Total size
+ USHORT Identification; // Identifier
+ UCHAR FlagsAndFlagmentOffset[2]; // Flag and Fragment offset
+ UCHAR TimeToLive; // TTL
+ UCHAR Protocol; // Protocol
+ USHORT Checksum; // Checksum
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+} GCC_PACKED;
+
+// Macro for IPv4 header operation
+#define IPV4_GET_VERSION(h) (((h)->VersionAndHeaderLength >> 4 & 0x0f))
+#define IPV4_SET_VERSION(h, v) ((h)->VersionAndHeaderLength |= (((v) & 0x0f) << 4))
+#define IPV4_GET_HEADER_LEN(h) ((h)->VersionAndHeaderLength & 0x0f)
+#define IPV4_SET_HEADER_LEN(h, v) ((h)->VersionAndHeaderLength |= ((v) & 0x0f))
+
+// Macro for IPv4 fragment related operation
+#define IPV4_GET_FLAGS(h) (((h)->FlagsAndFlagmentOffset[0] >> 5) & 0x07)
+#define IPV4_SET_FLAGS(h, v) ((h)->FlagsAndFlagmentOffset[0] |= (((v) & 0x07) << 5))
+#define IPV4_GET_OFFSET(h) (((h)->FlagsAndFlagmentOffset[0] & 0x1f) * 256 + ((h)->FlagsAndFlagmentOffset[1]))
+#define IPV4_SET_OFFSET(h, v) {(h)->FlagsAndFlagmentOffset[0] |= (UCHAR)((v) / 256); (h)->FlagsAndFlagmentOffset[1] = (UCHAR)((v) % 256);}
+
+// IPv4 / IPv6 common protocol
+#define IP_PROTO_TCP 0x06 // TCP protocol
+#define IP_PROTO_UDP 0x11 // UDP protocol
+#define IP_PROTO_ESP 50 // ESP protocol
+#define IP_PROTO_ETHERIP 97 // EtherIP protocol
+#define IP_PROTO_L2TPV3 115 // L2TPv3 protocol
+
+
+// UDP header
+struct UDP_HEADER
+{
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ USHORT PacketLength; // Data length
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// UDPv4 pseudo header
+struct UDPV4_PSEUDO_HEADER
+{
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+ UCHAR Reserved; // Unused
+ UCHAR Protocol; // Protocol number
+ USHORT PacketLength1; // UDP data length 1
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ USHORT PacketLength2; // UDP data length 2
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// IPv4 pseudo header
+struct IPV4_PSEUDO_HEADER
+{
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+ UCHAR Reserved; // Unused
+ UCHAR Protocol; // Protocol number
+ USHORT PacketLength; // Packet size
+} GCC_PACKED;
+
+// TCP header
+struct TCP_HEADER
+{
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ UINT SeqNumber; // Sequence number
+ UINT AckNumber; // Acknowledgment number
+ UCHAR HeaderSizeAndReserved; // Header size and Reserved area
+ UCHAR Flag; // Flag
+ USHORT WindowSize; // Window size
+ USHORT Checksum; // Checksum
+ USHORT UrgentPointer; // Urgent Pointer
+} GCC_PACKED;
+
+// TCP macro
+#define TCP_GET_HEADER_SIZE(h) (((h)->HeaderSizeAndReserved >> 4) & 0x0f)
+#define TCP_SET_HEADER_SIZE(h, v) ((h)->HeaderSizeAndReserved = (((v) & 0x0f) << 4))
+
+// TCP flags
+#define TCP_FIN 1
+#define TCP_SYN 2
+#define TCP_RST 4
+#define TCP_PSH 8
+#define TCP_ACK 16
+#define TCP_URG 32
+
+// ICMP header
+struct ICMP_HEADER
+{
+ UCHAR Type; // Type
+ UCHAR Code; // Code
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// ICMP Echo
+struct ICMP_ECHO
+{
+ USHORT Identifier; // ID
+ USHORT SeqNo; // Sequence number
+} GCC_PACKED;
+
+// ICMP message type
+#define ICMP_TYPE_ECHO_REQUEST 8
+#define ICMP_TYPE_ECHO_RESPONSE 0
+#define ICMP_TYPE_DESTINATION_UNREACHABLE 3
+#define ICMP_TYPE_TIME_EXCEEDED 11
+#define ICMP_TYPE_INFORMATION_REQUEST 15
+#define ICMP_TYPE_INFORMATION_REPLY 16
+
+// ICMP message code
+// In case of ICMP_TYPE_DESTINATION_UNREACHABLE
+#define ICMP_CODE_NET_UNREACHABLE 0
+#define ICMP_CODE_HOST_UNREACHABLE 1
+#define ICMP_CODE_PROTOCOL_UNREACHABLE 2
+#define ICMP_CODE_PORT_UNREACHABLE 3
+#define ICMP_CODE_FRAGMENTATION_NEEDED_DF_SET 4
+#define ICMP_CODE_SOURCE_ROUTE_FAILED 5
+
+// In case of TIME_EXCEEDED
+#define ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT 0
+#define ICMP_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEDED 1
+
+// DHCPv4 Header
+struct DHCPV4_HEADER
+{
+ UCHAR OpCode; // Op-code
+ UCHAR HardwareType; // Hardware type
+ UCHAR HardwareAddressSize; // Hardware address size
+ UCHAR Hops; // Number of hops
+ UINT TransactionId; // Transaction ID
+ USHORT Seconds; // Seconds
+ USHORT Flags; // Flag
+ UINT ClientIP; // Client IP address
+ UINT YourIP; // Assigned IP address
+ UINT ServerIP; // Server IP address
+ UINT RelayIP; // Relay IP address
+ UCHAR ClientMacAddress[6]; // Client MAC address
+ UCHAR Padding[10]; // Padding for non-Ethernet
+} GCC_PACKED;
+
+// DNSv4 header
+struct DNSV4_HEADER
+{
+ USHORT TransactionId; // Transaction ID
+ UCHAR Flag1; // Flag 1
+ UCHAR Flag2; // Flag 2
+ USHORT NumQuery; // Number of queries
+ USHORT AnswerRRs; // Answer RR number
+ USHORT AuthorityRRs; // Authority RR number
+ USHORT AdditionalRRs; // Additional RR number
+} GCC_PACKED;
+
+#define DHCP_MAGIC_COOKIE 0x63825363 // Magic Cookie (fixed)
+
+// NetBIOS Datagram header
+struct NBTDG_HEADER
+{
+ UCHAR MessageType;
+ UCHAR MoreFlagments;
+ USHORT DatagramId;
+ UINT SrcIP;
+ USHORT SrcPort;
+ USHORT DatagramLen;
+ USHORT PacketOffset;
+} GCC_PACKED;
+
+// IPv6 packet header information
+struct IPV6_HEADER_PACKET_INFO
+{
+ IPV6_HEADER *IPv6Header; // IPv6 header
+ IPV6_OPTION_HEADER *HopHeader; // Hop-by-hop option header
+ UINT HopHeaderSize; // Hop-by-hop option header size
+ IPV6_OPTION_HEADER *EndPointHeader; // End point option header
+ UINT EndPointHeaderSize; // End point option header size
+ IPV6_OPTION_HEADER *RoutingHeader; // Routing header
+ UINT RoutingHeaderSize; // Routing header size
+ IPV6_FRAGMENT_HEADER *FragmentHeader; // Fragment header
+ void *Payload; // Payload
+ UINT PayloadSize; // Payload size
+ UCHAR Protocol; // Payload protocol
+ bool IsFragment; // Whether it's a fragmented packet
+ UINT TotalHeaderSize; // Total header size
+};
+
+// IPv6 header
+struct IPV6_HEADER
+{
+ UCHAR VersionAndTrafficClass1; // Version Number (4 bit) and Traffic Class 1 (4 bit)
+ UCHAR TrafficClass2AndFlowLabel1; // Traffic Class 2 (4 bit) and Flow Label 1 (4 bit)
+ UCHAR FlowLabel2; // Flow Label 2 (8 bit)
+ UCHAR FlowLabel3; // Flow Label 3 (8 bit)
+ USHORT PayloadLength; // Length of the payload (including extension header)
+ UCHAR NextHeader; // Next header
+ UCHAR HopLimit; // Hop limit
+ IPV6_ADDR SrcAddress; // Source address
+ IPV6_ADDR DestAddress; // Destination address
+} GCC_PACKED;
+
+
+// Macro for IPv6 header operation
+#define IPV6_GET_VERSION(h) (((h)->VersionAndTrafficClass1 >> 4) & 0x0f)
+#define IPV6_SET_VERSION(h, v) ((h)->VersionAndTrafficClass1 = ((h)->VersionAndTrafficClass1 & 0x0f) | ((v) << 4) & 0xf0)
+#define IPV6_GET_TRAFFIC_CLASS(h) ((((h)->VersionAndTrafficClass1 << 4) & 0xf0) | ((h)->TrafficClass2AndFlowLabel1 >> 4) & 0x0f)
+#define IPV6_SET_TRAFFIC_CLASS(h, v) ((h)->VersionAndTrafficClass1 = ((h)->VersionAndTrafficClass1 & 0xf0) | (((v) >> 4) & 0x0f),\
+ (h)->TrafficClass2AndFlowLabel1 = (h)->TrafficClass2AndFlowLabel1 & 0x0f | ((v) << 4) & 0xf0)
+#define IPV6_GET_FLOW_LABEL(h) ((((h)->TrafficClass2AndFlowLabel1 << 16) & 0xf0000) | (((h)->FlowLabel2 << 8) & 0xff00) |\
+ (((h)->FlowLabel3) & 0xff))
+#define IPV6_SET_FLOW_LABEL(h, v) ((h)->TrafficClass2AndFlowLabel1 = ((h)->TrafficClass2AndFlowLabel1 & 0xf0 | ((v) >> 16) & 0x0f),\
+ (h)->FlowLabel2 = ((v) >> 8) & 0xff,\
+ (h)->FlowLabel3 = (v) & 0xff)
+
+
+// Maximum hops of IPv6 (not routing)
+#define IPV6_HOP_MAX 255
+
+// Standard hops of IPv6
+#define IPV6_HOP_DEFAULT 127
+
+// IPv6 header number
+#define IPV6_HEADER_HOP 0 // Hop-by-hop option header
+#define IPV6_HEADER_ENDPOINT 60 // End point option header
+#define IPV6_HEADER_ROUTING 43 // Routing header
+#define IPV6_HEADER_FRAGMENT 44 // Fragment header
+#define IPV6_HEADER_NONE 59 // No Next Header
+
+// IPv6 option header
+// (Used on hop option header, end point option header, routing header)
+struct IPV6_OPTION_HEADER
+{
+ UCHAR NextHeader; // Next header
+ UCHAR Size; // Header size (/8)
+} GCC_PACKED;
+
+// IPv6 fragment header
+// (fragment impossible part is until just before the routing header
+// or hop-by-hop option header or first extended header or payload)
+struct IPV6_FRAGMENT_HEADER
+{
+ UCHAR NextHeader; // Next header
+ UCHAR Reserved; // Reserved
+ UCHAR FlagmentOffset1; // Fragment offset 1 (/8, 8 bit)
+ UCHAR FlagmentOffset2AndFlags; // Fragment offset 2 (/8, 5 bit) + Reserved (2 bit) + More flag (1 bit)
+ UINT Identification; // ID
+} GCC_PACKED;
+
+// Macro for IPv6 fragment header operation
+#define IPV6_GET_FRAGMENT_OFFSET(h) (((((h)->FlagmentOffset1) << 5) & 0x1fe0) | (((h)->FlagmentOffset2AndFlags >> 3) & 0x1f))
+#define IPV6_SET_FRAGMENT_OFFSET(h, v) ((h)->FlagmentOffset1 = (v / 32) & 0xff, \
+ ((h)->FlagmentOffset2AndFlags = ((v % 256) << 3) & 0xf8) | ((h)->FlagmentOffset2AndFlags & 0x07))
+#define IPV6_GET_FLAGS(h) ((h)->FlagmentOffset2AndFlags & 0x0f)
+#define IPV6_SET_FLAGS(h, v) ((h)->FlagmentOffset2AndFlags = (((h)->FlagmentOffset2AndFlags & 0xf8) | (v & 0x07)))
+
+// Flag
+#define IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS 0x01 // There are more fragments
+
+// Virtual IPv6 header
+struct IPV6_PSEUDO_HEADER
+{
+ IPV6_ADDR SrcAddress; // Source address
+ IPV6_ADDR DestAddress; // Destination address
+ UINT UpperLayerPacketSize; // Upper layer packet size
+ UCHAR Padding[3]; // Padding
+ UCHAR NextHeader; // Next Header (TCP / UDP)
+} GCC_PACKED;
+
+// ICMPv6 Router Solicitation header
+struct ICMPV6_ROUTER_SOLICIATION_HEADER
+{
+ UINT Reserved; // Reserved
+ // + Option (source link-layer address [optional])
+} GCC_PACKED;
+
+// ICMPv6 Router Advertisement header
+struct ICMPV6_ROUTER_ADVERTISEMENT_HEADER
+{
+ UCHAR CurHopLimit; // Hop limit of the default
+ UCHAR Flags; // Flag (0)
+ USHORT Lifetime; // Lifetime
+ UINT ReachableTime; // 0
+ UINT RetransTimer; // 0
+ // + Option (prefix information [required], MTU [optional])
+} GCC_PACKED;
+
+// ICMPv6 Neighbor Solicitation header
+struct ICMPV6_NEIGHBOR_SOLICIATION_HEADER
+{
+ UINT Reserved; // Reserved
+ IPV6_ADDR TargetAddress; // Target address
+ // + Option (source link-layer address [required])
+} GCC_PACKED;
+
+// ICMPv6 Neighbor Advertisement header
+struct ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER
+{
+ UCHAR Flags; // Flag
+ UCHAR Reserved[3]; // Reserved
+ IPV6_ADDR TargetAddress; // Target address
+ // + Option (target link-layer address)
+} GCC_PACKED;
+
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER 0x80 // Router
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED 0x40 // Solicited flag
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERWRITE 0x20 // Overwrite flag
+
+// ICMPv6 option list
+struct ICMPV6_OPTION_LIST
+{
+ ICMPV6_OPTION_LINK_LAYER *SourceLinkLayer; // Source link-layer address
+ ICMPV6_OPTION_LINK_LAYER *TargetLinkLayer; // Target link-layer address
+ ICMPV6_OPTION_PREFIX *Prefix; // Prefix Information
+ ICMPV6_OPTION_MTU *Mtu; // MTU
+} GCC_PACKED;
+
+// ICMPv6 option
+struct ICMPV6_OPTION
+{
+ UCHAR Type; // Type
+ UCHAR Length; // Length (/8, include type and length)
+} GCC_PACKED;
+
+#define ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER 1 // Source link-layer address
+#define ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER 2 // Target link-layer address
+#define ICMPV6_OPTION_TYPE_PREFIX 3 // Prefix Information
+#define ICMPV6_OPTION_TYPE_MTU 5 // MTU
+
+// ICMPv6 link layer options
+struct ICMPV6_OPTION_LINK_LAYER
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ UCHAR Address[6]; // MAC address
+} GCC_PACKED;
+
+// ICMPv6 prefix information option
+struct ICMPV6_OPTION_PREFIX
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ UCHAR SubnetLength; // Subnet length
+ UCHAR Flags; // Flag
+ UINT ValidLifetime; // Formal lifetime
+ UINT PreferredLifetime; // Preferred lifetime
+ UINT Reserved; // Reserved
+ IPV6_ADDR Prefix; // Prefix address
+} GCC_PACKED;
+
+#define ICMPV6_OPTION_PREFIX_FLAG_ONLINK 0x80 // On link
+#define ICMPV6_OPTION_PREFIX_FLAG_AUTO 0x40 // Automatic
+
+// ICMPv6 MTU option
+struct ICMPV6_OPTION_MTU
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ USHORT Reserved; // Reserved
+ UINT Mtu; // MTU value
+} GCC_PACKED;
+
+
+// IPv6 header information
+struct IPV6_HEADER_INFO
+{
+ bool IsRawIpPacket;
+ USHORT Size;
+ UINT Id;
+ UCHAR Protocol;
+ UCHAR HopLimit;
+ IPV6_ADDR SrcIpAddress;
+ IPV6_ADDR DestIpAddress;
+ bool UnicastForMe;
+ bool UnicastForRouting;
+ bool UnicastForRoutingWithProxyNdp;
+ bool IsBroadcast;
+ UINT TypeL4;
+};
+
+// ICMPv6 header information
+struct ICMPV6_HEADER_INFO
+{
+ UCHAR Type;
+ UCHAR Code;
+ USHORT DataSize;
+ void *Data;
+ ICMP_ECHO EchoHeader;
+ void *EchoData;
+ UINT EchoDataSize;
+
+ union
+ {
+ // Meaning is determined by the value of the Type
+ ICMPV6_ROUTER_SOLICIATION_HEADER *RouterSoliciationHeader;
+ ICMPV6_ROUTER_ADVERTISEMENT_HEADER *RouterAdvertisementHeader;
+ ICMPV6_NEIGHBOR_SOLICIATION_HEADER *NeighborSoliciationHeader;
+ ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *NeighborAdvertisementHeader;
+ void *HeaderPointer;
+ } Headers;
+
+ ICMPV6_OPTION_LIST OptionList;
+};
+
+// The Type value of ICMPv6
+#define ICMPV6_TYPE_ECHO_REQUEST 128 // ICMPv6 Echo request
+#define ICMPV6_TYPE_ECHO_RESPONSE 129 // ICMPv6 Echo response
+#define ICMPV6_TYPE_ROUTER_SOLICIATION 133 // Router Solicitation
+#define ICMPV6_TYPE_ROUTER_ADVERTISEMENT 134 // Router Advertisement
+#define ICMPV6_TYPE_NEIGHBOR_SOLICIATION 135 // Neighbor Solicitation
+#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 136 // Neighbor Advertisement
+
+// Minimum DHCP packet size
+#define DHCP_MIN_SIZE 300
+
+// Constants about DHCP
+#define DHCP_ID_MESSAGE_TYPE 0x35
+#define DHCP_ID_REQUEST_IP_ADDRESS 0x32
+#define DHCP_ID_HOST_NAME 0x0c
+#define DHCP_ID_SERVER_ADDRESS 0x36
+#define DHCP_ID_LEASE_TIME 0x33
+#define DHCP_ID_DOMAIN_NAME 0x0f
+#define DHCP_ID_SUBNET_MASK 0x01
+#define DHCP_ID_GATEWAY_ADDR 0x03
+#define DHCP_ID_DNS_ADDR 0x06
+#define DHCP_ID_WINS_ADDR 0x2C
+#define DHCP_ID_CLIENT_ID 0x3d
+#define DHCP_ID_VENDOR_ID 0x3c
+#define DHCP_ID_REQ_PARAM_LIST 0x37
+
+// DHCP client action
+#define DHCP_DISCOVER 1
+#define DHCP_REQUEST 3
+#define DHCP_RELEASE 7
+#define DHCP_INFORM 8
+
+// DHCP server action
+#define DHCP_OFFER 2
+#define DHCP_DECLINE 4
+#define DHCP_ACK 5
+#define DHCP_NACK 6
+
+// HTTPLOG data structure
+struct HTTPLOG
+{
+ char Method[32]; // Method
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+ char Path[MAX_SIZE]; // Path
+ char Protocol[64]; // Protocol
+ char UserAgent[MAX_SIZE]; // User Agent value
+ char Referer[MAX_SIZE]; // Referer
+};
+
+// Packet
+struct PKT
+{
+ UCHAR *PacketData; // Packet data body
+ UINT PacketSize; // Packet size
+ MAC_HEADER *MacHeader; // MAC header
+ UCHAR *MacAddressSrc; // Source MAC address
+ UCHAR *MacAddressDest; // Destination MAC address
+ bool BroadcastPacket; // Broadcast packet
+ bool InvalidSourcePacket; // Packet with an invalid source address
+ bool AccessChecked; // Packets that pass was confirmed by the access list
+ UINT VlanTypeID; // TypeID of the tagged VLAN (usually 0x8100)
+ UINT VlanId; // VLAN ID
+ UINT Delay; // Delay
+ UINT Jitter; // Jitter
+ UINT Loss; // Packet loss
+ UINT64 DelayedForwardTick; // Sending time in case of delayed
+ struct SESSION *DelayedSrcSession; // Source session
+ UINT TypeL3; // Layer-3 packet classification
+ IPV6_HEADER_PACKET_INFO IPv6HeaderPacketInfo; // IPv6 packet header information (only for TypeL3 == L3_IPV6)
+ ICMPV6_HEADER_INFO ICMPv6HeaderPacketInfo; // ICMPv6 header information (Only for TypeL4 == L4_ICMPV6)
+ UINT DhcpOpCode; // DHCP opcode
+ union
+ {
+ IPV4_HEADER *IPv4Header; // IPv4 header
+ ARPV4_HEADER *ARPv4Header; // ARPv4 header
+ IPV6_HEADER *IPv6Header; // IPv6 header
+ TAGVLAN_HEADER *TagVlanHeader; // Tag header
+ BPDU_HEADER *BpduHeader; // BPDU header
+ void *PointerL3;
+ } L3;
+ UINT TypeL4; // Layer-4 packet classification
+ UINT IPv4PayloadSize; // IPv4 payload size
+ void *IPv4PayloadData; // IPv4 payload data
+ union
+ {
+ UDP_HEADER *UDPHeader; // UDP header
+ TCP_HEADER *TCPHeader; // TCP header
+ ICMP_HEADER *ICMPHeader; // ICMP header
+ void *PointerL4;
+ } L4;
+ UINT TypeL7; // Layer-7 packet classification
+ union
+ {
+ DHCPV4_HEADER *DHCPv4Header; // DHCPv4 header
+ IKE_HEADER *IkeHeader; // IKE header
+ void *PointerL7;
+ } L7;
+ UCHAR *Payload; // Pointer to the payload of TCP or UDP
+ UINT PayloadSize; // Payload size
+ struct HTTPLOG *HttpLog; // HTTP log
+} GCC_PACKED;
+
+// Layer-3 packet classification
+#define L3_UNKNOWN 0 // Unknown
+#define L3_ARPV4 1 // ARPv4 packet
+#define L3_IPV4 2 // IPv4 packet
+#define L3_TAGVLAN 3 // Tagged VLAN packet
+#define L3_BPDU 4 // BPDU packet
+#define L3_IPV6 5 // IPv6 packet
+
+// Layer-4 packet classification
+#define L4_UNKNOWN 0 // Unknown
+#define L4_UDP 1 // UDPv4 packet
+#define L4_TCP 2 // TCPv4 packet
+#define L4_ICMPV4 3 // ICMPv4 packet
+#define L4_ICMPV6 4 // ICMPv6 packet
+#define L4_FRAGMENT 5 // Fragment packet
+
+// Layer-7 packet classification
+#define L7_UNKNOWN 0 // Unknown
+#define L7_DHCPV4 1 // DHCPv4 packet
+#define L7_IKECONN 2 // IKE connection request packet
+#define L7_OPENVPNCONN 3 // OpenVPN connection request packet
+
+
+// IKE header
+struct IKE_HEADER
+{
+ UINT64 InitiatorCookie; // Initiator cookie
+ UINT64 ResponderCookie; // Responder cookie
+ UCHAR NextPayload; // Next payload
+ UCHAR Version; // Version
+ UCHAR ExchangeType; // Exchange type
+ UCHAR Flag; // Flag
+ UINT MessageId; // Message ID
+ UINT MessageSize; // Message size
+} GCC_PACKED;
+
+// IKE exchange type
+#define IKE_EXCHANGE_TYPE_MAIN 2 // Main mode
+#define IKE_EXCHANGE_TYPE_AGGRESSIVE 4 // Aggressive mode
+#define IKE_EXCHANGE_TYPE_INFORMATION 5 // Information exchange
+#define IKE_EXCHANGE_TYPE_QUICK 32 // Quick mode
+
+// DHCPv4 data
+struct DHCPV4_DATA
+{
+ UCHAR *Data;
+ UINT Size;
+ IP SrcIP;
+ UINT SrcPort;
+ IP DestIP;
+ UINT DestPort;
+ UINT OpCode;
+
+ UCHAR *OptionData;
+ UINT OptionSize;
+
+ DHCPV4_HEADER *Header;
+ LIST *OptionList;
+
+ struct DHCP_OPTION_LIST *ParsedOptionList;
+};
+// DHCP Option
+struct DHCP_OPTION
+{
+ UINT Id; // ID
+ UINT Size; // Size
+ void *Data; // Data
+};
+
+// DHCP option list
+struct DHCP_OPTION_LIST
+{
+ // Common Item
+ UINT Opcode; // DHCP opcode
+
+ // Client request
+ UINT RequestedIp; // Requested IP address
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+
+ // Server response
+ UINT ClientAddress; // Client address
+ UINT ServerAddress; // DHCP server address
+ UINT LeaseTime; // Lease time
+ char DomainName[MAX_HOST_NAME_LEN + 1]; // Domain name
+ UINT SubnetMask; // Subnet mask
+ UINT Gateway; // Gateway address
+ UINT DnsServer; // DNS server address 1
+ UINT DnsServer2; // DNS server address 2
+ UINT WinsServer; // WINS server address 1
+ UINT WinsServer2; // WINS server address 2
+};
+
+// Modification option in the DHCP packet
+struct DHCP_MODIFY_OPTION
+{
+ bool RemoveDefaultGatewayOnReply; // Remove the default gateway from the DHCP Reply
+};
+
+// Special IP address
+#define SPECIAL_IPV4_ADDR_LLMNR_DEST 0xE00000FC // 224.0.0.252
+
+// Special port
+#define SPECIAL_UDP_PORT_LLMNR 5355 // LLMNR
+#define SPECIAL_UDP_PORT_NBTNS 137 // NetBIOS Name Service
+#define SPECIAL_UDP_PORT_NBTDGM 138 // NetBIOS Datagram
+#define SPECIAL_UDP_PORT_WSD 3702 // WS-Discovery
+#define SPECIAL_UDP_PORT_SSDP 1900 // SSDP
+
+
+PKT *ParsePacketIPv4WithDummyMacHeader(UCHAR *buf, UINT size);
+PKT *ParsePacket(UCHAR *buf, UINT size);
+PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3);
+PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id);
+PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address);
+PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum);
+void FreePacket(PKT *p);
+void FreePacketWithData(PKT *p);
+void FreePacketIPv4(PKT *p);
+void FreePacketTagVlan(PKT *p);
+void FreePacketARPv4(PKT *p);
+void FreePacketUDPv4(PKT *p);
+void FreePacketTCPv4(PKT *p);
+void FreePacketICMPv4(PKT *p);
+void FreePacketDHCPv4(PKT *p);
+bool ParsePacketL2(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3);
+bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size);
+bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size);
+bool ParseTCP(PKT *p, UCHAR *buf, UINT size);
+bool ParseUDP(PKT *p, UCHAR *buf, UINT size);
+void ParseDHCPv4(PKT *p, UCHAR *buf, UINT size);
+PKT *ClonePacket(PKT *p, bool copy_data);
+void FreeClonePacket(PKT *p);
+
+void CorrectChecksum(PKT *p);
+
+bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size);
+bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size);
+bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size);
+void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src);
+void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o);
+USHORT CalcChecksumForIPv4(UINT src_ip, UINT dst_ip, UCHAR protocol, void *data, UINT size, UINT real_size);
+USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size, UINT real_size);
+BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o);
+void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total_size);
+BUF *BuildIPv6(IPV6_ADDR *dest_ip, IPV6_ADDR *src_ip, UINT id, UCHAR protocol, UCHAR hop_limit, void *data,
+ UINT size);
+BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload);
+UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q);
+void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size);
+BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id);
+BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id);
+
+bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
+void VLanInsertTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
+
+DHCPV4_DATA *ParseDHCPv4Data(PKT *pkt);
+void FreeDHCPv4Data(DHCPV4_DATA *d);
+
+bool AdjustTcpMssL3(UCHAR *src, UINT src_size, UINT mss);
+bool AdjustTcpMssL2(UCHAR *src, UINT src_size, UINT mss, USHORT tag_vlan_tpid);
+UINT GetIpHeaderSize(UCHAR *src, UINT src_size);
+
+bool IsDhcpPacketForSpecificMac(UCHAR *data, UINT size, UCHAR *mac_address);
+
+ICMP_RESULT *IcmpEchoSendBySocket(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+ICMP_RESULT *IcmpEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+ICMP_RESULT *IcmpParseResult(IP *dest_ip, USHORT src_id, USHORT src_seqno, UCHAR *recv_buffer, UINT recv_buffer_size);
+void IcmpFreeResult(ICMP_RESULT *r);
+
+USHORT IpChecksum(void *buf, UINT size);
+bool IpCheckChecksum(IPV4_HEADER *ip);
+
+LIST *BuildDhcpOption(DHCP_OPTION_LIST *opt);
+DHCP_OPTION *NewDhcpOption(UINT id, void *data, UINT size);
+DHCP_OPTION_LIST *ParseDhcpOptionList(void *data, UINT size);
+DHCP_OPTION *GetDhcpOption(LIST *o, UINT id);
+void FreeDhcpOptions(LIST *o);
+LIST *ParseDhcpOptions(void *data, UINT size);
+BUF *BuildDhcpOptionsBuf(LIST *o);
+HTTPLOG *ParseHttpAccessLog(PKT *pkt);
+
+BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size);
+BUF *DhcpModifyIPv4(DHCP_MODIFY_OPTION *m, void *data, UINT size);
+
+
+
+#ifdef OS_WIN32
+#pragma pack(pop)
+#endif // OS_WIN32
+
+#endif // TCPIP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tick64.c b/src/Mayaqua/Tick64.c
new file mode 100644
index 00000000..91224cdf
--- /dev/null
+++ b/src/Mayaqua/Tick64.c
@@ -0,0 +1,378 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tick64.c
+// 64-bit real-time clock program
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <locale.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static TICK64 *tk64 = NULL;
+static EVENT *halt_tick_event = NULL;
+
+// Get the high-resolution time
+UINT64 TickHighres64()
+{
+ UINT64 ret = 0;
+
+#ifdef OS_WIN32
+
+ ret = (UINT64)(MsGetHiResTimeSpan(MsGetHiResCounter()) * 1000.0f);
+
+#else // OS_WIN32
+
+ return Tick64();
+
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Convert the Tick value to time
+UINT64 Tick64ToTime64(UINT64 tick)
+{
+ UINT64 ret = 0;
+ if (tick == 0)
+ {
+ return 0;
+ }
+ LockList(tk64->AdjustTime);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++)
+ {
+ ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i);
+ if (t->Tick <= tick)
+ {
+ ret = t->Time + (tick - t->Tick);
+ }
+ }
+ }
+ UnlockList(tk64->AdjustTime);
+ if (ret == 0)
+ {
+ ret++;
+ }
+ return ret;
+}
+
+// Convert the Tick value to time
+UINT64 TickToTime(UINT64 tick)
+{
+ return Tick64ToTime64(tick);
+}
+
+// Get the Tick value
+UINT64 Tick64()
+{
+#ifdef OS_WIN32
+ return Win32FastTick64();
+#else // OS_WIN32
+ UINT64 tick64;
+ if (tk64 == NULL)
+ {
+ return 0;
+ }
+ Lock(tk64->TickLock);
+ {
+ tick64 = tk64->Tick;
+ }
+ Unlock(tk64->TickLock);
+ return tick64;
+#endif // OS_WIN32
+}
+
+// Real-time clock measuring thread
+void Tick64Thread(THREAD *thread, void *param)
+{
+ UINT n = 0;
+ bool first = false;
+ bool create_first_entry = true;
+ UINT tick_span;
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+
+ // Raise the priority of the Win32 thread
+ MsSetThreadPriorityRealtime();
+
+ tick_span = TICK64_SPAN_WIN32;
+
+#else // OS_WIN32
+
+ // Raise the priority of a POSIX threads
+ UnixSetThreadPriorityRealtime();
+
+ tick_span = TICK64_SPAN;
+
+#endif // OS_WIN32
+
+ while (true)
+ {
+ UINT tick;
+ UINT64 tick64;
+
+#ifndef OS_WIN32
+ tick = TickRealtime(); // Get the current system clock
+
+ if (tk64->LastTick > tick)
+ {
+ if ((tk64->LastTick - tick) >= (UINT64)0x0fffffff)
+ {
+ // The Tick has gone lap around
+ tk64->RoundCount++;
+ }
+ else
+ {
+ // tick skewed (System administrator might change hardware clock)
+ // Normally, the clock skew appears as sub-seconds error
+ tick = tk64->LastTick;
+ }
+ }
+ tk64->LastTick = tick;
+
+ tick64 = (UINT64)tk64->RoundCount * (UINT64)4294967296LL + (UINT64)tick;
+
+ Lock(tk64->TickLock);
+ {
+ if (tk64->TickStart == 0)
+ {
+ tk64->TickStart = tick64;
+ }
+ tick64 = tk64->Tick = tick64 - tk64->TickStart + (UINT64)1;
+ }
+ Unlock(tk64->TickLock);
+#else // OS_WIN32
+ tick64 = Win32FastTick64();
+ tick = (UINT)tick64;
+#endif // OS_WIN32
+
+ if (create_first_entry)
+ {
+ ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME));
+ t->Tick = tick64;
+ t->Time = SystemTime64();
+ tk64->Tick64WithTime64 = tick64;
+ tk64->Time64 = t->Time;
+ Add(tk64->AdjustTime, t);
+
+ // Notify the completion of the initialization
+ NoticeThreadInit(thread);
+ create_first_entry = false;
+ }
+
+ // Time correction
+ n += tick_span;
+ if (n >= 1000 || first == false)
+ {
+ UINT64 now = SystemTime64();
+
+ if (now < tk64->Time64 ||
+ Diff64((now - tk64->Time64) + tk64->Tick64WithTime64, tick64) >= tick_span)
+ {
+ ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME));
+ LockList(tk64->AdjustTime);
+ {
+ t->Tick = tick64;
+ t->Time = now;
+ Add(tk64->AdjustTime, t);
+ Debug("Adjust Time: Tick = %I64u, Time = %I64u\n",
+ t->Tick, t->Time);
+
+ // To prevent consuming memory infinite on a system that clock is skewd
+ if (LIST_NUM(tk64->AdjustTime) > MAX_ADJUST_TIME)
+ {
+ // Remove the second
+ ADJUST_TIME *t2 = LIST_DATA(tk64->AdjustTime, 1);
+
+ Delete(tk64->AdjustTime, t2);
+
+ Debug("NUM_ADJUST TIME: %u\n", LIST_NUM(tk64->AdjustTime));
+
+ Free(t2);
+ }
+ }
+ UnlockList(tk64->AdjustTime);
+ tk64->Time64 = now;
+ tk64->Tick64WithTime64 = tick64;
+ }
+ first = true;
+ n = 0;
+ }
+
+ if (tk64->Halt)
+ {
+ break;
+ }
+
+#ifdef OS_WIN32
+ Wait(halt_tick_event, tick_span);
+#else // OS_WIN32
+ SleepThread(tick_span);
+#endif // OS_WIN32
+ }
+}
+
+// Get the absolute value of the difference between the two 64 bit integers
+UINT64 Diff64(UINT64 a, UINT64 b)
+{
+ if (a > b)
+ {
+ return a - b;
+ }
+ else
+ {
+ return b - a;
+ }
+}
+
+// Initialization of the Tick64
+void InitTick64()
+{
+ if (tk64 != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ halt_tick_event = NewEvent();
+
+ // Initialize the structure
+ tk64 = ZeroMalloc(sizeof(TICK64));
+ tk64->TickLock = NewLock();
+ tk64->AdjustTime = NewList(NULL);
+
+ // Creating a thread
+ tk64->Thread = NewThread(Tick64Thread, NULL);
+ WaitThreadInit(tk64->Thread);
+}
+
+// Release of the Tick64
+void FreeTick64()
+{
+ UINT i;
+ if (tk64 == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Termination process
+ tk64->Halt = true;
+ Set(halt_tick_event);
+ WaitThread(tk64->Thread, INFINITE);
+ ReleaseThread(tk64->Thread);
+
+ // Releasing process
+ for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++)
+ {
+ ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i);
+ Free(t);
+ }
+ ReleaseList(tk64->AdjustTime);
+ DeleteLock(tk64->TickLock);
+ Free(tk64);
+ tk64 = NULL;
+
+ ReleaseEvent(halt_tick_event);
+ halt_tick_event = NULL;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tick64.h b/src/Mayaqua/Tick64.h
new file mode 100644
index 00000000..8d5b5eed
--- /dev/null
+++ b/src/Mayaqua/Tick64.h
@@ -0,0 +1,134 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tick64.h
+// Header of Tick64.c
+
+#ifndef TICK64_H
+#define TICK64_H
+
+// Maximum number of correction list entries
+#define MAX_ADJUST_TIME 5000
+
+// Correction list entry
+struct ADJUST_TIME
+{
+ UINT64 Tick;
+ UINT64 Time;
+};
+
+// TICK64 structure
+struct TICK64
+{
+ THREAD *Thread;
+ UINT64 Tick;
+ UINT64 TickStart;
+ UINT64 Time64;
+ UINT64 Tick64WithTime64;
+ UINT LastTick;
+ UINT RoundCount;
+ LOCK *TickLock;
+ volatile bool Halt;
+ LIST *AdjustTime;
+};
+
+// Constant
+#define TICK64_SPAN 10 // Measurement interval (Usually less than 10ms)
+#define TICK64_SPAN_WIN32 1000 // Interval of measurement on Win32
+#define TICK64_ADJUST_SPAN 5000 // Correct the clock if it shifts more than this value
+
+// Function prototype
+void InitTick64();
+void FreeTick64();
+void Tick64Thread(THREAD *thread, void *param);
+UINT64 Tick64();
+UINT64 Diff64(UINT64 a, UINT64 b);
+UINT64 Tick64ToTime64(UINT64 tick);
+UINT64 TickToTime(UINT64 tick);
+UINT64 TickHighres64();
+
+#endif // TICK64_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tracking.c b/src/Mayaqua/Tracking.c
new file mode 100644
index 00000000..55bb9284
--- /dev/null
+++ b/src/Mayaqua/Tracking.c
@@ -0,0 +1,975 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tracking.c
+// Object tracking module
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Global variables
+static LOCK *obj_lock;
+static LOCK *obj_id_lock;
+static UINT obj_id;
+static LOCK *cs_lock;
+static bool disable_tracking = false;
+static TRACKING_LIST **hashlist;
+
+static bool do_not_get_callstack;
+
+// Enable the tracking
+void TrackingEnable()
+{
+ disable_tracking = false;
+}
+
+// Disable the tracking
+void TrackingDisable()
+{
+ disable_tracking = true;
+}
+
+// Get whether the tracking is enabled
+bool IsTrackingEnabled()
+{
+ return !disable_tracking;
+}
+
+// Memory debug menu
+void MemoryDebugMenu()
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ char *cmd;
+ Print("Mayaqua Kernel Memory Debug Tools\n"
+ "Copyright (c) SoftEther Corporation. All Rights Reserved.\n\n");
+ g_memcheck = false;
+ while (true)
+ {
+ Print("debug>");
+ GetLine(tmp, sizeof(tmp));
+ t = ParseToken(tmp, " \t");
+ if (t->NumTokens == 0)
+ {
+ FreeToken(t);
+ DebugPrintAllObjects();
+ continue;
+ }
+ cmd = t->Token[0];
+ if (!StrCmpi(cmd, "?"))
+ {
+ DebugPrintCommandList();
+ }
+ else if (!StrCmpi(cmd, "a"))
+ {
+ DebugPrintAllObjects();
+ }
+ else if (!StrCmpi(cmd, "i"))
+ {
+ if (t->NumTokens == 1)
+ {
+ Print("Usage: i <obj_id>\n\n");
+ }
+ else
+ {
+ DebugPrintObjectInfo(ToInt(t->Token[1]));
+ }
+ }
+ else if (!StrCmpi(cmd, "q"))
+ {
+ break;
+ }
+ else if (ToInt(cmd) != 0)
+ {
+ DebugPrintObjectInfo(ToInt(t->Token[0]));
+ }
+ else
+ {
+ Print("Command Not Found,\n\n");
+ }
+ FreeToken(t);
+ }
+ FreeToken(t);
+ g_memcheck = true;
+}
+
+// Sort the objects by chronological order
+int SortObjectView(void *p1, void *p2)
+{
+ TRACKING_OBJECT *o1, *o2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(TRACKING_OBJECT **)p1;
+ o2 = *(TRACKING_OBJECT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ if (o1->Id > o2->Id)
+ {
+ return 1;
+ }
+ else if (o1->Id == o2->Id)
+ {
+ return 0;
+ }
+ return -1;
+}
+
+// Display the information of the object
+void PrintObjectInfo(TRACKING_OBJECT *o)
+{
+ SYSTEMTIME t;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ UINT64ToSystem(&t, o->CreatedDate);
+ GetDateTimeStrMilli(tmp, sizeof(tmp), &t);
+
+ Print(" TRACKING_OBJECT ID: %u\n"
+ " TRACKING_OBJECT TYPE: %s\n"
+ " ADDRESS: 0x%p\n"
+ " TRACKING_OBJECT SIZE: %u bytes\n"
+ " CREATED DATE: %s\n",
+ o->Id, o->Name, UINT64_TO_POINTER(o->Address), o->Size, tmp);
+
+ PrintCallStack(o->CallStack);
+}
+
+// Display the object information
+void DebugPrintObjectInfo(UINT id)
+{
+ UINT i;
+ TRACKING_OBJECT *o;
+
+ // Search
+ o = NULL;
+ LockTrackingList();
+ {
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ if (t->Object->Id == id)
+ {
+ o = t->Object;
+ break;
+ }
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+
+ if (o != NULL)
+ {
+ break;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ if (o == NULL)
+ {
+ // The ID could not be found
+ Print("obj_id %u Not Found.\n\n", id);
+ return;
+ }
+
+ PrintObjectInfo(o);
+ Print("\n");
+}
+
+// Show a Summary of the object
+void PrintObjectList(TRACKING_OBJECT *o)
+{
+ char tmp[MAX_SIZE];
+ SYSTEMTIME t;
+ UINT64ToSystem(&t, o->CreatedDate);
+ GetTimeStrMilli(tmp, sizeof(tmp), &t);
+ TrackGetObjSymbolInfo(o);
+ Print("%-4u - [%-6s] %s 0x%p size=%-5u %11s %u\n",
+ o->Id, o->Name, tmp, UINT64_TO_POINTER(o->Address), o->Size, o->FileName, o->LineNumber);
+}
+
+// Display all the objects
+void DebugPrintAllObjects()
+{
+ UINT i;
+ LIST *view;
+
+ // Creating a List
+ view = NewListFast(SortObjectView);
+ LockTrackingList();
+ {
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ Add(view, t->Object);
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ // Sort
+ Sort(view);
+
+ // Drawing
+ for (i = 0;i < LIST_NUM(view);i++)
+ {
+ TRACKING_OBJECT *o = (TRACKING_OBJECT *)LIST_DATA(view, i);
+ PrintObjectList(o);
+ }
+
+ // Release the list
+ ReleaseList(view);
+
+ Print("\n");
+}
+
+// List of the commands
+void DebugPrintCommandList()
+{
+ Print(
+ "a - All Objects\n"
+ "i - Object Information\n"
+ "? - Help\n"
+ "q - Quit\n\n"
+ );
+}
+
+// Display the usage of the memory
+void PrintMemoryStatus()
+{
+ MEMORY_STATUS s;
+ GetMemoryStatus(&s);
+ Print("MEMORY STATUS:\n"
+ " NUM_OF_MEMORY_BLOCKS: %u\n"
+ " SIZE_OF_TOTAL_MEMORY: %u bytes\n",
+ s.MemoryBlocksNum, s.MemorySize);
+}
+
+// Get the using state of the memory
+void GetMemoryStatus(MEMORY_STATUS *status)
+{
+ UINT i, num, size;
+ // Validate arguments
+ if (status == NULL)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ size = num = 0;
+
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ TRACKING_OBJECT *o = t->Object;
+
+ if (StrCmpi(o->Name, "MEM") == 0)
+ {
+ num++;
+ size += o->Size;
+ }
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ status->MemoryBlocksNum = num;
+ status->MemorySize = size;
+}
+
+// Get the symbol information by the object
+void TrackGetObjSymbolInfo(TRACKING_OBJECT *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (!(o->LineNumber == 0 && o->FileName[0] == 0))
+ {
+ return;
+ }
+
+ if (o->CallStack != NULL)
+ {
+ GetCallStackSymbolInfo(o->CallStack);
+ if (StrLen(o->CallStack->filename) != 0 && o->CallStack->line != 0)
+ {
+ StrCpy(o->FileName, sizeof(o->FileName), o->CallStack->filename);
+ o->LineNumber = o->CallStack->line;
+ }
+ }
+}
+
+// Put a new object into the tracking list
+void TrackNewObj(UINT64 addr, char *name, UINT size)
+{
+ TRACKING_OBJECT *o;
+ UINT new_id;
+ // Validate arguments
+ if (addr == 0 || name == NULL)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ // Generate a new ID
+ OSLock(obj_id_lock);
+ {
+ new_id = ++obj_id;
+ }
+ OSUnlock(obj_id_lock);
+
+ o = OSMemoryAlloc(sizeof(TRACKING_OBJECT));
+ o->Id = new_id;
+ o->Address = addr;
+ o->Name = name;
+ o->Size = size;
+ o->CreatedDate = LocalTime64();
+ o->CallStack = WalkDownCallStack(GetCallStack(), 2);
+
+ o->FileName[0] = 0;
+ o->LineNumber = 0;
+
+ LockTrackingList();
+ {
+ InsertTrackingList(o);
+ }
+ UnlockTrackingList();
+}
+
+// Remove the object from the tracking list
+void TrackDeleteObj(UINT64 addr)
+{
+ TRACKING_OBJECT *o;
+ // Validate arguments
+ if (addr == 0)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ o = SearchTrackingList(addr);
+ if (o == NULL)
+ {
+ UnlockTrackingList();
+
+ if (IsDebug())
+ {
+ printf("TrackDeleteObj: 0x%x is not Object!!\n", (void *)addr);
+ }
+ return;
+ }
+ DeleteTrackingList(o, true);
+ }
+ UnlockTrackingList();
+}
+
+// Change the size of the object being tracked
+void TrackChangeObjSize(UINT64 addr, UINT size, UINT64 new_addr)
+{
+ TRACKING_OBJECT *o;
+ // Validate arguments
+ if (addr == 0)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ o = SearchTrackingList(addr);
+ if (o == NULL)
+ {
+ UnlockTrackingList();
+ return;
+ }
+
+ DeleteTrackingList(o, false);
+
+ o->Size = size;
+ o->Address = new_addr;
+
+ InsertTrackingList(o);
+ }
+ UnlockTrackingList();
+}
+
+// Memory address comparison function
+int CompareTrackingObject(const void *p1, const void *p2)
+{
+ TRACKING_OBJECT *o1, *o2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(TRACKING_OBJECT **)p1;
+ o2 = *(TRACKING_OBJECT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ if (o1->Address > o2->Address)
+ {
+ return 1;
+ }
+ if (o1->Address == o2->Address)
+ {
+ return 0;
+ }
+ return -1;
+}
+
+// Search an object in the tracking list
+TRACKING_OBJECT *SearchTrackingList(UINT64 Address)
+{
+ UINT i;
+ // Validate arguments
+ if (Address == 0)
+ {
+ return NULL;
+ }
+
+ i = TRACKING_HASH(Address);
+
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *tt = hashlist[i];
+
+ while (true)
+ {
+ if (tt->Object->Address == Address)
+ {
+ return tt->Object;
+ }
+
+ tt = tt->Next;
+
+ if (tt == NULL)
+ {
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Remove an object from a tracking list
+void DeleteTrackingList(TRACKING_OBJECT *o, bool free_object_memory)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ i = TRACKING_HASH(o->Address);
+
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *ft = NULL;
+
+ if (hashlist[i]->Object == o)
+ {
+ ft = hashlist[i];
+ hashlist[i] = hashlist[i]->Next;
+ }
+ else
+ {
+ TRACKING_LIST *tt = hashlist[i];
+ TRACKING_LIST *prev = NULL;
+
+ while (true)
+ {
+ if (tt->Object == o)
+ {
+ prev->Next = tt->Next;
+ ft = tt;
+ break;
+ }
+
+ if (tt->Next == NULL)
+ {
+ break;
+ }
+
+ prev = tt;
+ tt = tt->Next;
+ }
+ }
+
+ if (ft != NULL)
+ {
+ OSMemoryFree(ft);
+
+ if (free_object_memory)
+ {
+ FreeCallStack(o->CallStack);
+ OSMemoryFree(o);
+ }
+ }
+ }
+}
+
+// Insert an object into the tracking list
+void InsertTrackingList(TRACKING_OBJECT *o)
+{
+ UINT i;
+ TRACKING_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ t = OSMemoryAlloc(sizeof(TRACKING_LIST));
+ t->Object = o;
+ t->Next = NULL;
+
+ i = TRACKING_HASH(o->Address);
+
+ if (hashlist[i] == NULL)
+ {
+ hashlist[i] = t;
+ }
+ else
+ {
+ TRACKING_LIST *tt = hashlist[i];
+ while (true)
+ {
+ if (tt->Next == NULL)
+ {
+ tt->Next = t;
+ break;
+ }
+
+ tt = tt->Next;
+ }
+ }
+}
+
+// Lock the tracking list
+void LockTrackingList()
+{
+ OSLock(obj_lock);
+}
+
+// Unlock the tracking list
+void UnlockTrackingList()
+{
+ OSUnlock(obj_lock);
+}
+
+// Initialize the tracking
+void InitTracking()
+{
+ UINT i;
+ CALLSTACK_DATA *s;
+
+ // Hash list initialization
+ hashlist = (TRACKING_LIST **)OSMemoryAlloc(sizeof(TRACKING_LIST *) * TRACKING_NUM_ARRAY);
+
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ hashlist[i] = NULL;
+ }
+
+ obj_id = 0;
+
+ // Create a lock
+ obj_lock = OSNewLock();
+ obj_id_lock = OSNewLock();
+ cs_lock = OSNewLock();
+
+ s = GetCallStack();
+ if (s == NULL)
+ {
+ do_not_get_callstack = true;
+ }
+ else
+ {
+ do_not_get_callstack = false;
+ FreeCallStack(s);
+ }
+}
+
+// Release the tracking
+void FreeTracking()
+{
+ UINT i;
+ // Delete the lock
+ OSDeleteLock(obj_lock);
+ OSDeleteLock(obj_id_lock);
+ OSDeleteLock(cs_lock);
+ cs_lock = NULL;
+ obj_id_lock = NULL;
+ obj_lock = NULL;
+
+ // Release all of the elements
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ TRACKING_LIST *t2 = t;
+ TRACKING_OBJECT *o = t->Object;
+
+ FreeCallStack(o->CallStack);
+ OSMemoryFree(o);
+
+ t = t->Next;
+
+ OSMemoryFree(t2);
+
+ if (t == NULL)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Release the list
+ OSMemoryFree(hashlist);
+}
+
+// Show the call stack
+void PrintCallStack(CALLSTACK_DATA *s)
+{
+ char tmp[MAX_SIZE * 2];
+
+ GetCallStackStr(tmp, sizeof(tmp), s);
+ Print("%s", tmp);
+}
+
+// Convert the call stack to a string
+void GetCallStackStr(char *str, UINT size, CALLSTACK_DATA *s)
+{
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ char tmp3[MAX_SIZE];
+ UINT num, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ if (s == NULL)
+ {
+ StrCpy(str, size, "(Unknown)\n");
+ }
+ else
+ {
+ num = 0;
+ str[0] = 0;
+ while (true)
+ {
+ if (s == NULL)
+ {
+ break;
+ }
+
+ GetCallStackSymbolInfo(s);
+
+ if (s->name == NULL)
+ {
+ Format(tmp, sizeof(tmp), "0x%p ---", UINT64_TO_POINTER(s->offset));
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "0x%p %s() + 0x%02x",
+ (void *)s->offset, s->name, UINT64_TO_POINTER(s->disp));
+ }
+ for (i = 0;i < num;i++)
+ {
+ tmp2[i] = ' ';
+ }
+ tmp2[i] = '\0';
+ StrCpy(tmp3, sizeof(tmp3), tmp2);
+ StrCat(tmp3, sizeof(tmp3), tmp);
+ Format(tmp, sizeof(tmp), "%-55s %11s %u\n", tmp3, s->filename, s->line);
+ StrCat(str, size, tmp);
+ num++;
+ s = s->next;
+ }
+ }
+}
+
+// Get the current call stack
+CALLSTACK_DATA *GetCallStack()
+{
+ CALLSTACK_DATA *s;
+ if (do_not_get_callstack)
+ {
+ // Not to get the call stack
+ return NULL;
+ }
+
+ OSLock(cs_lock);
+ {
+ // Get the call stack
+ s = OSGetCallStack();
+ }
+ OSUnlock(cs_lock);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // Descend in the call stack for 3 steps
+ s = WalkDownCallStack(s, 3);
+
+ return s;
+}
+
+// Get the symbol information of the call stack
+bool GetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ bool ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ OSLock(cs_lock);
+ {
+ ret = OSGetCallStackSymbolInfo(s);
+ }
+ OSUnlock(cs_lock);
+
+ return ret;
+}
+
+// Descend in the call stack by a specified number
+CALLSTACK_DATA *WalkDownCallStack(CALLSTACK_DATA *s, UINT num)
+{
+ CALLSTACK_DATA *cs, *tmp;
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ cs = s;
+ i = 0;
+
+ while (true)
+ {
+ if (i >= num)
+ {
+ return cs;
+ }
+ i++;
+ tmp = cs;
+ cs = tmp->next;
+ OSMemoryFree(tmp->name);
+ OSMemoryFree(tmp);
+
+ if (cs == NULL)
+ {
+ return NULL;
+ }
+ }
+}
+
+// Release the call stack
+void FreeCallStack(CALLSTACK_DATA *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ CALLSTACK_DATA *next = s->next;
+ OSMemoryFree(s->name);
+ OSMemoryFree(s);
+ if (next == NULL)
+ {
+ break;
+ }
+ s = next;
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tracking.h b/src/Mayaqua/Tracking.h
new file mode 100644
index 00000000..54cd6d6b
--- /dev/null
+++ b/src/Mayaqua/Tracking.h
@@ -0,0 +1,171 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tracking.h
+// Header of Tracking.c
+
+#ifndef TRACKING_H
+#define TRACKING_H
+
+// The number of array
+#define TRACKING_NUM_ARRAY 1048576
+
+// Hash from an pointer to an array index
+#define TRACKING_HASH(p) (UINT)(((((UINT64)(p)) / (UINT64)(sizeof(void *))) % ((UINT64)TRACKING_NUM_ARRAY)))
+
+// Call stack
+struct CALLSTACK_DATA
+{
+ bool symbol_cache;
+ UINT64 offset, disp;
+ char *name;
+ struct CALLSTACK_DATA *next;
+ char filename[MAX_PATH];
+ UINT line;
+};
+
+// Object
+struct TRACKING_OBJECT
+{
+ UINT Id;
+ char *Name;
+ UINT64 Address;
+ UINT Size;
+ UINT64 CreatedDate;
+ CALLSTACK_DATA *CallStack;
+ char FileName[MAX_PATH];
+ UINT LineNumber;
+};
+
+// Usage of the memory
+struct MEMORY_STATUS
+{
+ UINT MemoryBlocksNum;
+ UINT MemorySize;
+};
+
+// Tracking list
+struct TRACKING_LIST
+{
+ struct TRACKING_LIST *Next;
+ struct TRACKING_OBJECT *Object;
+};
+
+CALLSTACK_DATA *GetCallStack();
+bool GetCallStackSymbolInfo(CALLSTACK_DATA *s);
+void FreeCallStack(CALLSTACK_DATA *s);
+CALLSTACK_DATA *WalkDownCallStack(CALLSTACK_DATA *s, UINT num);
+void GetCallStackStr(char *str, UINT size, CALLSTACK_DATA *s);
+void PrintCallStack(CALLSTACK_DATA *s);
+void InitTracking();
+void FreeTracking();
+int CompareTrackingObject(const void *p1, const void *p2);
+void LockTrackingList();
+void UnlockTrackingList();
+void InsertTrackingList(TRACKING_OBJECT *o);
+void DeleteTrackingList(TRACKING_OBJECT *o, bool free_object_memory);
+TRACKING_OBJECT *SearchTrackingList(UINT64 Address);
+
+void TrackNewObj(UINT64 addr, char *name, UINT size);
+void TrackGetObjSymbolInfo(TRACKING_OBJECT *o);
+void TrackDeleteObj(UINT64 addr);
+void TrackChangeObjSize(UINT64 addr, UINT size, UINT64 new_addr);
+
+void GetMemoryStatus(MEMORY_STATUS *status);
+void PrintMemoryStatus();
+void MemoryDebugMenu();
+int SortObjectView(void *p1, void *p2);
+void DebugPrintAllObjects();
+void DebugPrintCommandList();
+void PrintObjectList(TRACKING_OBJECT *o);
+void PrintObjectInfo(TRACKING_OBJECT *o);
+void DebugPrintObjectInfo(UINT id);
+
+void TrackingEnable();
+void TrackingDisable();
+bool IsTrackingEnabled();
+
+#endif // TRACKING_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TunTap.h b/src/Mayaqua/TunTap.h
new file mode 100644
index 00000000..5db02c06
--- /dev/null
+++ b/src/Mayaqua/TunTap.h
@@ -0,0 +1,306 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// TunTap.h
+// Header file of the TUN / TAP device driver
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#ifndef TUNTAP_H
+#define TUNTAP_H
+
+#ifdef UNIX_LINUX
+
+// -----------------------------------------------------------------
+// Tap header for Linux
+// -----------------------------------------------------------------
+/*
+ * Universal TUN/TAP device driver.
+ * Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * $Id: if_tun.h,v 1.2 2001/10/31 15:27:57 arjanv Exp $
+ */
+
+#ifndef __IF_TUN_H
+#define __IF_TUN_H
+
+/* Uncomment to enable debugging */
+/* #define TUN_DEBUG 1 */
+
+
+
+/* Read queue size */
+#define TUN_READQ_SIZE 10
+
+/* TUN device flags */
+#define TUN_TUN_DEV 0x0001
+#define TUN_TAP_DEV 0x0002
+#define TUN_TYPE_MASK 0x000f
+
+#define TUN_FASYNC 0x0010
+#define TUN_NOCHECKSUM 0x0020
+#define TUN_NO_PI 0x0040
+#define TUN_ONE_QUEUE 0x0080
+#define TUN_PERSIST 0x0100
+
+/* Ioctl defines */
+#define TUNSETNOCSUM _IOW('T', 200, int)
+#define TUNSETDEBUG _IOW('T', 201, int)
+#define TUNSETIFF _IOW('T', 202, int)
+#define TUNSETPERSIST _IOW('T', 203, int)
+#define TUNSETOWNER _IOW('T', 204, int)
+
+/* TUNSETIFF ifr flags */
+#define IFF_TUN 0x0001
+#define IFF_TAP 0x0002
+#define IFF_NO_PI 0x1000
+#define IFF_ONE_QUEUE 0x2000
+
+struct tun_pi {
+ unsigned short flags;
+ unsigned short proto;
+};
+#define TUN_PKT_STRIP 0x0001
+
+#endif /* __IF_TUN_H */
+#else // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+
+// -----------------------------------------------------------------
+// Tap header for Solaris
+// -----------------------------------------------------------------
+/*
+ * Universal TUN/TAP device driver.
+ *
+ * Multithreaded STREAMS tun pseudo device driver.
+ *
+ * Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * $Id: if_tun.h,v 1.4 2000/05/01 12:23:27 maxk Exp $
+ */
+
+#ifndef _SYS_IF_TUN_H
+#define _SYS_IF_TUN_H
+
+#ifdef _KERNEL
+/* Uncomment to enable debuging */
+/* #define TUN_DEBUG 1 */
+
+#ifdef TUN_DEBUG
+#define DBG cmn_err
+#else
+#define DBG( a... )
+#endif
+
+/* PPA structure, one per TUN iface */
+struct tunppa {
+ unsigned int id; /* Iface number */
+ queue_t *rq; /* Control Stream RQ */
+ struct tunstr * p_str; /* Protocol Streams */
+};
+#define TUNMAXPPA 20
+
+/* Stream structure, one per Stream */
+struct tunstr {
+ struct tunstr *s_next; /* next in streams list */
+ struct tunstr *p_next; /* next in ppa list */
+ queue_t *rq; /* pointer to rq */
+
+ struct tunppa *ppa; /* assigned PPA */
+ u_long flags; /* flags */
+ u_long state; /* DL state */
+ u_long sap; /* bound sap */
+ u_long minor; /* minor device number */
+};
+
+/* Flags */
+#define TUN_CONTROL 0x0001
+
+#define TUN_RAW 0x0100
+#define TUN_FAST 0x0200
+
+#define TUN_ALL_PHY 0x0010
+#define TUN_ALL_SAP 0x0020
+#define TUN_ALL_MUL 0x0040
+
+#define SNIFFER(a) ( (a & TUN_ALL_SAP) || (a & TUN_ALL_PHY) )
+
+struct tundladdr {
+ u_short sap;
+};
+#define TUN_ADDR_LEN (sizeof(struct tundladdr))
+
+#define TUN_QUEUE 0
+#define TUN_DROP 1
+
+#endif /* _KERNEL */
+
+/* IOCTL defines */
+#define TUNNEWPPA (('T'<<16) | 0x0001)
+#define TUNSETPPA (('T'<<16) | 0x0002)
+
+#endif /* _SYS_IF_TUN_H */
+
+#else // UNIX_SOLARIS
+
+#ifdef UNIX_BSD
+
+// -----------------------------------------------------------------
+// Tap header for FreeBSD
+// -----------------------------------------------------------------
+/* $NetBSD: if_tun.h,v 1.5 1994/06/29 06:36:27 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
+ * Nottingham University 1987.
+ *
+ * This source may be freely distributed, however I would be interested
+ * in any changes that are made.
+ *
+ * This driver takes packets off the IP i/f and hands them up to a
+ * user process to have its wicked way with. This driver has it's
+ * roots in a similar driver written by Phil Cockcroft (formerly) at
+ * UCL. This driver is based much more on read/write/select mode of
+ * operation though.
+ *
+ * $FreeBSD: src/sys/net/if_tun.h,v 1.17 2000/01/23 01:47:12 brian Exp $
+ */
+
+#ifndef _NET_IF_TUN_H_
+#define _NET_IF_TUN_H_
+
+/* Refer to if_tunvar.h for the softc stuff */
+
+/* Maximum transmit packet size (default) */
+#define TUNMTU 1500
+
+/* Maximum receive packet size (hard limit) */
+#define TUNMRU 16384
+
+struct tuninfo {
+ int baudrate; /* linespeed */
+ short mtu; /* maximum transmission unit */
+ u_char type; /* ethernet, tokenring, etc. */
+ u_char dummy; /* place holder */
+};
+
+/* ioctl's for get/set debug */
+#define TUNSDEBUG _IOW('t', 90, int)
+#define TUNGDEBUG _IOR('t', 89, int)
+#define TUNSIFINFO _IOW('t', 91, struct tuninfo)
+#define TUNGIFINFO _IOR('t', 92, struct tuninfo)
+#define TUNSLMODE _IOW('t', 93, int)
+#define TUNSIFMODE _IOW('t', 94, int)
+#define TUNSIFPID _IO('t', 95)
+#define TUNSIFHEAD _IOW('t', 96, int)
+#define TUNGIFHEAD _IOR('t', 97, int)
+
+#endif /* !_NET_IF_TUN_H_ */
+
+#else // UNIX_BSD
+
+#ifdef UNIX_MACOS
+
+// -----------------------------------------------------------------
+// Tap header For MacOS
+// -----------------------------------------------------------------
+
+#else // UNIX_MACOS
+
+#endif // UNIX_MACOS
+
+#endif // UNIX_BSD
+
+#endif // UNIX_SOLARIS
+
+#endif // UNIX_LINUX
+
+#endif // TUNTAP_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Unix.c b/src/Mayaqua/Unix.c
new file mode 100644
index 00000000..8ee0b9c3
--- /dev/null
+++ b/src/Mayaqua/Unix.c
@@ -0,0 +1,2741 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Unix.c
+// UNIX dependent code
+
+#include <GlobalConst.h>
+
+#ifdef UNIX
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Struct statfs for MacOS X
+#ifdef UNIX_MACOS
+typedef struct fsid { int32_t val[2]; } fsid_t;
+struct statfs {
+ short f_otype; /* TEMPORARY SHADOW COPY OF f_type */
+ short f_oflags; /* TEMPORARY SHADOW COPY OF f_flags */
+ long f_bsize; /* fundamental file system block size */
+ long f_iosize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ fsid_t f_fsid; /* file system id */
+ uid_t f_owner; /* user that mounted the filesystem */
+ short f_reserved1; /* spare for later */
+ short f_type; /* type of filesystem */
+ long f_flags; /* copy of mount exported flags */
+ long f_reserved2[2]; /* reserved for future use */
+ char f_fstypename[15]; /* fs type name */
+ char f_mntonname[90]; /* directory on which mounted */
+ char f_mntfromname[90];/* mounted filesystem */
+};
+#endif // UNIX_MACOS
+
+// Scandir() function for Solaris
+#ifdef UNIX_SOLARIS
+#define scandir local_scandir
+#define alphasort local_alphasort
+
+int local_scandir(const char *dir, struct dirent ***namelist,
+ int (*select)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **))
+{
+ DIR *d;
+ struct dirent *entry;
+ register int i=0;
+ size_t entrysize;
+
+ if ((d=opendir(dir)) == NULL)
+ return(-1);
+
+ *namelist=NULL;
+ while ((entry=readdir(d)) != NULL)
+ {
+ if (select == NULL || (select != NULL && (*select)(entry)))
+ {
+ *namelist=(struct dirent **)realloc((void *)(*namelist),
+ (size_t)((i+1)*sizeof(struct dirent *)));
+ if (*namelist == NULL) return(-1);
+ entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
+ (*namelist)[i]=(struct dirent *)malloc(entrysize);
+ if ((*namelist)[i] == NULL) return(-1);
+ memcpy((*namelist)[i], entry, entrysize);
+ i++;
+ }
+ }
+ if (closedir(d)) return(-1);
+ if (i == 0) return(-1);
+ if (compar != NULL)
+ qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
+
+ return(i);
+}
+
+int local_alphasort(const struct dirent **a, const struct dirent **b)
+{
+ return(strcmp((*a)->d_name, (*b)->d_name));
+}
+
+
+#endif // UNIX_SOLARIS
+
+// Thread data for UNIX
+typedef struct UNIXTHREAD
+{
+ pthread_t thread;
+ bool finished;
+} UNIXTHREAD;
+
+// Thread startup information for UNIX
+typedef struct UNIXTHREADSTARTUPINFO
+{
+ THREAD_PROC *thread_proc;
+ void *param;
+ THREAD *thread;
+} UNIXTHREADSTARTUPINFO;
+
+// Thread function prototype for UNIX
+void *UnixDefaultThreadProc(void *param);
+
+// Current process ID
+static pid_t current_process_id = 0;
+
+// File I/O data for UNIX
+typedef struct UNIXIO
+{
+ int fd;
+ bool write_mode;
+} UNIXIO;
+
+// Lock file data for UNIX
+typedef struct UNIXLOCKFILE
+{
+ char FileName[MAX_SIZE];
+ int fd;
+} UNIXLOCKFILE;
+
+// Event data for UNIX
+typedef struct UNIXEVENT
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ bool signal;
+} UNIXEVENT;
+
+static pthread_mutex_t get_time_lock;
+static pthread_mutex_t malloc_lock;
+static bool high_process = false;
+
+static bool unix_svc_terminate = false;
+static int solaris_sleep_p1 = -1, solaris_sleep_p2 = -1;
+
+// Create a dispatch table
+OS_DISPATCH_TABLE *UnixGetDispatchTable()
+{
+ static OS_DISPATCH_TABLE t =
+ {
+ UnixInit,
+ UnixFree,
+ UnixMemoryAlloc,
+ UnixMemoryReAlloc,
+ UnixMemoryFree,
+ UnixGetTick,
+ UnixGetSystemTime,
+ UnixInc32,
+ UnixDec32,
+ UnixSleep,
+ UnixNewLock,
+ UnixLock,
+ UnixUnlock,
+ UnixDeleteLock,
+ UnixInitEvent,
+ UnixSetEvent,
+ UnixResetEvent,
+ UnixWaitEvent,
+ UnixFreeEvent,
+ UnixWaitThread,
+ UnixFreeThread,
+ UnixInitThread,
+ UnixThreadId,
+ UnixFileOpen,
+ UnixFileOpenW,
+ UnixFileCreate,
+ UnixFileCreateW,
+ UnixFileWrite,
+ UnixFileRead,
+ UnixFileClose,
+ UnixFileFlush,
+ UnixFileSize,
+ UnixFileSeek,
+ UnixFileDelete,
+ UnixFileDeleteW,
+ UnixMakeDir,
+ UnixMakeDirW,
+ UnixDeleteDir,
+ UnixDeleteDirW,
+ UnixGetCallStack,
+ UnixGetCallStackSymbolInfo,
+ UnixFileRename,
+ UnixFileRenameW,
+ UnixRun,
+ UnixRunW,
+ UnixIsSupportedOs,
+ UnixGetOsInfo,
+ UnixAlert,
+ UnixAlertW,
+ UnixGetProductId,
+ UnixSetHighPriority,
+ UnixRestorePriority,
+ UnixNewSingleInstance,
+ UnixFreeSingleInstance,
+ UnixGetMemInfo,
+ UnixYield,
+ };
+
+ return &t;
+}
+
+static void *signal_received_for_ignore(int sig, siginfo_t *info, void *ucontext)
+{
+ return NULL;
+}
+
+// Ignore the signal flew to the thread
+void UnixIgnoreSignalForThread(int sig)
+{
+ struct sigaction sa;
+
+ Zero(&sa, sizeof(sa));
+ sa.sa_handler = NULL;
+ sa.sa_sigaction = signal_received_for_ignore;
+ sa.sa_flags = SA_SIGINFO;
+
+ sigemptyset(&sa.sa_mask);
+
+ sigaction(SIGUSR1, &sa, NULL);
+}
+
+// Disable the off-loading function of the specific Ethernet device
+void UnixDisableInterfaceOffload(char *name)
+{
+#ifdef UNIX_LINUX
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ char *names = "rx tx sg tso ufo gso gro lro rxvlan txvlan ntuple rxhash";
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ t = ParseToken(names, " ");
+
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *a = t->Token[i];
+
+ Format(tmp, sizeof(tmp), "/sbin/ethtool -K %s %s off 2>/dev/null", name, a);
+ FreeToken(UnixExec(tmp));
+ }
+ }
+
+ FreeToken(t);
+#endif // UNIX_LINUX
+}
+
+// Validate whether the UNIX is running in a VM
+bool UnixIsInVmMain()
+{
+ TOKEN_LIST *t = NULL;
+ bool ret = false;
+ char *vm_str_list = "Hypervisor detected,VMware Virtual Platform,VMware Virtual USB,qemu,xen,paravirtualized,virtual hd,virtualhd,virtual pc,virtualpc,kvm,oracle vm,oraclevm,parallels,xvm,bochs";
+
+#ifdef UNIX_LINUX
+ t = UnixExec("/bin/dmesg");
+
+ if (t != NULL)
+ {
+ BUF *b = NewBuf();
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *line = t->Token[i];
+
+ AddBufStr(b, line);
+ AddBufStr(b, " ");
+ }
+
+ WriteBufInt(b, 0);
+
+// printf("%s\n", b->Buf);
+
+ ret = InStrList(b->Buf, vm_str_list, ",", false);
+
+ FreeBuf(b);
+ FreeToken(t);
+ }
+#endif // UNIX_LINUX
+
+ return ret;
+}
+bool UnixIsInVm()
+{
+ static bool is_in_vm_flag = false;
+ static bool is_in_vm_ret = false;
+
+ if (is_in_vm_flag == false)
+ {
+ is_in_vm_ret = UnixIsInVmMain();
+ is_in_vm_flag = true;
+ }
+
+ return is_in_vm_ret;
+}
+
+// Run quietly in the UNIX
+void UnixExecSilent(char *cmd)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (cmd == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), "%s 2>/dev/null", cmd);
+
+ FreeToken(UnixExec(tmp));
+}
+
+// Enable / disable the ESP processing in the kernel
+void UnixSetEnableKernelEspProcessing(bool b)
+{
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // Mac OS X
+ if (b)
+ {
+ UnixExecSilent("/usr/sbin/sysctl -w net.inet.ipsec.esp_port=4500");
+ }
+ else
+ {
+ UnixExecSilent("/usr/sbin/sysctl -w net.inet.ipsec.esp_port=4501");
+ }
+ }
+}
+
+// Run a command and return its result
+TOKEN_LIST *UnixExec(char *cmd)
+{
+ FILE *fp;
+ char tmp[MAX_SIZE];
+ char *ptr;
+ LIST *o;
+ UINT i;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (cmd == NULL)
+ {
+ return NULL;
+ }
+
+ fp = popen(cmd, "r");
+ if (fp == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewList(NULL);
+
+ while (true)
+ {
+ fgets(tmp, sizeof(tmp), fp);
+ if (feof(fp))
+ {
+ break;
+ }
+
+ ptr = strchr(tmp, '\n');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ }
+
+ ptr = strchr(tmp, '\r');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ pclose(fp);
+
+ ret = ListToTokenList(o);
+
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Initialize the Sleep for Solaris
+void UnixInitSolarisSleep()
+{
+ char tmp[MAX_SIZE];
+
+ UnixNewPipe(&solaris_sleep_p1, &solaris_sleep_p2);
+ read(solaris_sleep_p1, tmp, sizeof(tmp));
+}
+
+// Release the Sleep for Solaris
+void UnixFreeSolarisSleep()
+{
+ UnixDeletePipe(solaris_sleep_p1, solaris_sleep_p2);
+ solaris_sleep_p1 = -1;
+ solaris_sleep_p2 = -1;
+}
+
+// Sleep for Solaris
+void UnixSolarisSleep(UINT msec)
+{
+ struct pollfd p;
+
+ memset(&p, 0, sizeof(p));
+ p.fd = solaris_sleep_p1;
+ p.events = POLLIN;
+
+ poll(&p, 1, msec == INFINITE ? -1 : (int)msec);
+}
+
+// Get the free space of the disk
+bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char *path_a = CopyUniToStr(path);
+ bool ret;
+
+ ret = UnixGetDiskFree(path_a, free_size, used_size, total_size);
+
+ Free(path_a);
+
+ return ret;
+}
+bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char tmp[MAX_PATH];
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ while ((ret = UnixGetDiskFreeMain(tmp, free_size, used_size, total_size)) == false)
+ {
+ if (StrCmpi(tmp, "/") == 0)
+ {
+ break;
+ }
+
+ GetDirNameFromFilePath(tmp, sizeof(tmp), tmp);
+ }
+
+ return ret;
+}
+bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+#ifndef USE_STATVFS
+ struct statfs st;
+ char tmp[MAX_PATH];
+ UINT64 v1 = 0, v2 = 0;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ Zero(&st, sizeof(st));
+ if (statfs(tmp, &st) == 0)
+ {
+ v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
+ v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2 - v1;
+ }
+
+ return ret;
+#else // USE_STATVFS
+ struct statvfs st;
+ char tmp[MAX_PATH];
+ UINT64 v1 = 0, v2 = 0;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ Zero(&st, sizeof(st));
+
+ if (statvfs(tmp, &st) == 0)
+ {
+ v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
+ v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2 - v1;
+ }
+
+ return ret;
+#endif // USE_STATVFS
+}
+
+// Directory enumeration
+DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare)
+{
+ char tmp[MAX_PATH];
+ DIRLIST *d;
+ int n;
+ struct dirent **e;
+ LIST *o;
+ // Validate arguments
+ if (dirname == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(compare);
+
+ NormalizePath(tmp, sizeof(tmp), dirname);
+
+ if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] != '/')
+ {
+ StrCat(tmp, sizeof(tmp), "/");
+ }
+
+ e = NULL;
+ n = scandir(tmp, &e, 0, alphasort);
+
+ if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] == '/')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+
+ if (n >= 0 && e != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < (UINT)n;i++)
+ {
+ char *filename = e[i]->d_name;
+
+ if (filename != NULL)
+ {
+ if (StrCmpi(filename, "..") != 0 && StrCmpi(filename, ".") != 0)
+ {
+ char fullpath[MAX_PATH];
+ struct stat st;
+ Format(fullpath, sizeof(fullpath), "%s/%s", tmp, filename);
+
+ Zero(&st, sizeof(st));
+
+ if (stat(fullpath, &st) == 0)
+ {
+ DIRENT *f = ZeroMalloc(sizeof(DIRENT));
+ SYSTEMTIME t;
+
+ f->Folder = S_ISDIR(st.st_mode) ? true : false;
+ f->FileName = CopyStr(filename);
+ f->FileNameW = CopyUtfToUni(f->FileName);
+
+ Zero(&t, sizeof(t));
+ TimeToSystem(&t, st.st_ctime);
+ f->CreateDate = SystemToUINT64(&t);
+
+ Zero(&t, sizeof(t));
+ TimeToSystem(&t, st.st_mtime);
+ f->UpdateDate = SystemToUINT64(&t);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = st.st_size;
+ }
+
+ Add(o, f);
+ }
+ }
+ }
+
+ free(e[i]);
+ }
+
+ free(e);
+ }
+
+ Sort(o);
+
+ d = ZeroMalloc(sizeof(DIRLIST));
+ d->NumFiles = LIST_NUM(o);
+ d->File = ToArray(o);
+
+ ReleaseList(o);
+
+ return d;
+}
+DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ char *dirname_a = CopyUniToUtf(dirname);
+ DIRLIST *ret;
+
+ ret = UnixEnumDirEx(dirname_a, compare);
+
+ Free(dirname_a);
+
+ return ret;
+}
+
+// Check the execute permissions of the specified file
+bool UnixCheckExecAccess(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (access(name, X_OK) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool UnixCheckExecAccessW(wchar_t *name)
+{
+ char *name_a;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ name_a = CopyUniToUtf(name);
+
+ ret = UnixCheckExecAccess(name_a);
+
+ Free(name_a);
+
+ return ret;
+}
+
+// Raise the priority of the thread to highest
+void UnixSetThreadPriorityRealtime()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 255;
+ pthread_setschedparam(pthread_self(), SCHED_RR, &p);
+}
+
+// Lower the priority of the thread
+void UnixSetThreadPriorityLow()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 32;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Raise the priority of the thread
+void UnixSetThreadPriorityHigh()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 127;
+ pthread_setschedparam(pthread_self(), SCHED_RR, &p);
+}
+
+// Set the priority of the thread to idle
+void UnixSetThreadPriorityIdle()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 1;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Restore the priority of the thread to normal
+void UnixRestoreThreadPriority()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 64;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Get the current directory
+void UnixGetCurrentDir(char *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ getcwd(dir, size);
+}
+void UnixGetCurrentDirW(wchar_t *dir, UINT size)
+{
+ char dir_a[MAX_PATH];
+
+ UnixGetCurrentDir(dir_a, sizeof(dir_a));
+
+ UtfToUni(dir, size, dir_a);
+}
+
+// Yield
+void UnixYield()
+{
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(1);
+#else
+ usleep(1000);
+#endif
+}
+
+// Get the memory information
+void UnixGetMemInfo(MEMINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ // I don't know!!
+ Zero(info, sizeof(MEMINFO));
+}
+
+// Release of the single instance
+void UnixFreeSingleInstance(void *data)
+{
+ UNIXLOCKFILE *o;
+ struct flock lock;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ o = (UNIXLOCKFILE *)data;
+
+ Zero(&lock, sizeof(lock));
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+
+ fcntl(o->fd, F_SETLK, &lock);
+ close(o->fd);
+
+ remove(o->FileName);
+
+ Free(data);
+}
+
+// Creating a single instance
+void *UnixNewSingleInstance(char *instance_name)
+{
+ UNIXLOCKFILE *ret;
+ char tmp[MAX_SIZE];
+ char name[MAX_SIZE];
+ char dir[MAX_PATH];
+ int fd;
+ struct flock lock;
+ int mode = S_IRUSR | S_IWUSR;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ GetExeName(tmp, sizeof(tmp));
+ HashInstanceName(tmp, sizeof(tmp), tmp);
+ }
+ else
+ {
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ // File name generation
+ Format(name, sizeof(name), "%s/.%s", dir, tmp);
+
+ fd = open(name, O_WRONLY);
+ if (fd == -1)
+ {
+ fd = creat(name, mode);
+ }
+ if (fd == -1)
+ {
+ Format(tmp, sizeof(tmp), "Unable to create %s.", name);
+ Alert(tmp, NULL);
+ exit(0);
+ return NULL;
+ }
+
+ fchmod(fd, mode);
+ chmod(name, mode);
+
+ Zero(&lock, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+
+ if (fcntl(fd, F_SETLK, &lock) == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ ret = ZeroMalloc(sizeof(UNIXLOCKFILE));
+ ret->fd = fd;
+ StrCpy(ret->FileName, sizeof(ret->FileName), name);
+ return (void *)ret;
+ }
+}
+
+// Raise the priority of the process
+void UnixSetHighPriority()
+{
+ if (high_process == false)
+ {
+ UINT pid = getpid();
+ UINT pgid = getpgid(pid);
+
+ high_process = true;
+ nice(-20);
+
+ setpriority(PRIO_PROCESS, pid, -20);
+ setpriority(PRIO_PGRP, pgid, -20);
+ }
+}
+
+// Restore the priority of the process
+void UnixRestorePriority()
+{
+ if (high_process != false)
+ {
+ high_process = false;
+ nice(20);
+ }
+}
+
+// Get the product ID
+char *UnixGetProductId()
+{
+ return CopyStr("--");
+}
+
+// Display an alert
+void UnixAlertW(wchar_t *msg, wchar_t *caption)
+{
+ char *msg8 = CopyUniToUtf(msg);
+ char *caption8 = CopyUniToUtf(caption);
+
+ UnixAlert(msg8, caption8);
+
+ Free(msg8);
+ Free(caption8);
+}
+void UnixAlert(char *msg, char *caption)
+{
+ char *tag =
+ "-- Alert: %s --\n%s\n";
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR " VPN Kernel";
+ }
+
+ printf(tag, caption, msg);
+}
+
+// Get the information of the current OS
+void UnixGetOsInfo(OS_INFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(info, sizeof(OS_INFO));
+ info->OsType = OSTYPE_UNIX_UNKNOWN;
+
+#ifdef UNIX_SOLARIS
+ info->OsType = OSTYPE_SOLARIS;
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_CYGWIN
+ info->OsType = OSTYPE_CYGWIN;
+#endif // UNIX_CYGWIN
+
+#ifdef UNIX_MACOS
+ info->OsType = OSTYPE_MACOS_X;
+#endif // UNIX_MACOS
+
+#ifdef UNIX_BSD
+ info->OsType = OSTYPE_BSD;
+#endif // UNIX_BSD
+
+#ifdef UNIX_LINUX
+ info->OsType = OSTYPE_LINUX;
+#endif // UNIX_LINUX
+
+ info->OsServicePack = 0;
+
+ if (info->OsType != OSTYPE_LINUX)
+ {
+ info->OsSystemName = CopyStr("UNIX");
+ info->OsProductName = CopyStr("UNIX");
+ }
+ else
+ {
+ info->OsSystemName = CopyStr("Linux");
+ info->OsProductName = CopyStr("Linux");
+ }
+
+ if (info->OsType == OSTYPE_LINUX)
+ {
+ // Get the distribution name on Linux
+ BUF *b;
+ b = ReadDump("/etc/redhat-release");
+ if (b != NULL)
+ {
+ info->OsVersion = CfgReadNextLine(b);
+ info->OsVendorName = CopyStr("Red Hat, Inc.");
+ FreeBuf(b);
+ }
+ else
+ {
+ b = ReadDump("/etc/turbolinux-release");
+ if (b != NULL)
+ {
+ info->OsVersion = CfgReadNextLine(b);
+ info->OsVendorName = CopyStr("Turbolinux, Inc.");
+ FreeBuf(b);
+ }
+ else
+ {
+ info->OsVersion = CopyStr("Unknown Liunx Version");
+ info->OsVendorName = CopyStr("Unknown Vendor");
+ }
+ }
+
+ info->KernelName = CopyStr("Linux Kernel");
+
+ b = ReadDump("/proc/sys/kernel/osrelease");
+ if (b != NULL)
+ {
+ info->KernelVersion = CfgReadNextLine(b);
+ FreeBuf(b);
+ }
+ else
+ {
+ info->KernelVersion = CopyStr("Unknown Version");
+ }
+ }
+ else
+ {
+ // In other cases
+ Free(info->OsProductName);
+ info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
+ info->OsVersion = CopyStr("Unknown Version");
+ info->KernelName = CopyStr(OsTypeToStr(info->OsType));
+ info->KernelVersion = CopyStr("Unknown Version");
+ }
+}
+
+// Examine whether the current OS is supported by the PacketiX VPN Kernel
+bool UnixIsSupportedOs()
+{
+ // Support all UNIX OS which can run PacketiX VPN
+ return true;
+}
+
+// Run a specified command
+bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ char *filename8 = CopyUniToUtf(filename);
+ char *arg8 = CopyUniToUtf(arg);
+ bool ret = UnixRun(filename8, arg8, hide, wait);
+
+ Free(filename8);
+ Free(arg8);
+
+ return ret;
+}
+bool UnixRun(char *filename, char *arg, bool hide, bool wait)
+{
+ TOKEN_LIST *t;
+ UINT ret;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+ if (arg == NULL)
+ {
+ arg = "";
+ }
+
+ // Create a child process
+ ret = fork();
+ if (ret == -1)
+ {
+ // Child process creation failure
+ return false;
+ }
+
+ if (ret == 0)
+ {
+ Print("", filename, arg);
+ // Child process
+ if (hide)
+ {
+ // Close the standard I/O
+ UnixCloseIO();
+ }
+
+ t = ParseToken(arg, " ");
+ if (t == NULL)
+ {
+ AbortExit();
+ }
+ else
+ {
+ char **args;
+ UINT num_args;
+ UINT i;
+ num_args = t->NumTokens + 2;
+ args = ZeroMalloc(sizeof(char *) * num_args);
+ args[0] = filename;
+ for (i = 1;i < num_args - 1;i++)
+ {
+ args[i] = t->Token[i - 1];
+ }
+ execvp(filename, args);
+ AbortExit();
+ }
+ }
+ else
+ {
+ // Parent process
+ pid_t pid = (pid_t)ret;
+
+ if (wait)
+ {
+ int status = 0;
+ // Wait for the termination of the child process
+ if (waitpid(pid, &status, 0) == -1)
+ {
+ return false;
+ }
+
+ if (WEXITSTATUS(status) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+// Initialize the daemon
+void UnixDaemon(bool debug_mode)
+{
+ UINT ret;
+
+ if (debug_mode)
+ {
+ // Debug mode
+ signal(SIGHUP, SIG_IGN);
+ return;
+ }
+
+ ret = fork();
+
+ if (ret == -1)
+ {
+ // Error
+ return;
+ }
+ else if (ret == 0)
+ {
+ // Create a new session for the child process
+ setsid();
+
+ // Close the standard I/O
+ UnixCloseIO();
+
+ // Mute the unwanted signal
+ signal(SIGHUP, SIG_IGN);
+ }
+ else
+ {
+ // Terminate the parent process
+ exit(0);
+ }
+}
+
+// Close the standard I/O
+void UnixCloseIO()
+{
+ static bool close_io_first = false;
+
+ // Execute only once
+ if (close_io_first)
+ {
+ return;
+ }
+ else
+ {
+ close(0);
+ close(1);
+ close(2);
+ open("/dev/null", O_RDWR);
+ dup2(0, 1);
+ dup2(0, 2);
+ close_io_first = false;
+ }
+}
+
+// Change the file name
+bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ char *old_name8 = CopyUniToUtf(old_name);
+ char *new_name8 = CopyUniToUtf(new_name);
+ bool ret = UnixFileRename(old_name8, new_name8);
+
+ Free(old_name8);
+ Free(new_name8);
+
+ return ret;
+}
+bool UnixFileRename(char *old_name, char *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (rename(old_name, new_name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the call stack
+CALLSTACK_DATA *UnixGetCallStack()
+{
+ // This is not supported on non-Win32
+ return NULL;
+}
+
+// Get the symbol information from the call stack
+bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ // This is not supported on non-Win32
+ return false;
+}
+
+// Delete the directory
+bool UnixDeleteDirW(wchar_t *name)
+{
+ char *name8 = CopyUniToUtf(name);
+ bool ret = UnixDeleteDir(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixDeleteDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (rmdir(name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a directory
+bool UnixMakeDirW(wchar_t *name)
+{
+ char *name8 = CopyUniToUtf(name);
+ bool ret = UnixMakeDir(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixMakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (mkdir(name, 0700) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Delete the file
+bool UnixFileDeleteW(wchar_t *name)
+{
+ bool ret;
+ char *name8 = CopyUniToUtf(name);
+
+ ret = UnixFileDelete(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixFileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (remove(name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Seek the file
+bool UnixFileSeek(void *pData, UINT mode, int offset)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+ if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = lseek(p->fd, offset, mode);
+
+ if (ret == -1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the file size
+UINT64 UnixFileSize(void *pData)
+{
+ struct stat st;
+ UNIXIO *p;
+ int r;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+
+ p = (UNIXIO *)pData;
+
+ Zero(&st, sizeof(st));
+ r = fstat(p->fd, &st);
+ if (r != 0)
+ {
+ return 0;
+ }
+
+ return (UINT64)st.st_size;
+}
+
+// Write to the file
+bool UnixFileWrite(void *pData, void *buf, UINT size)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = write(p->fd, buf, size);
+ if (ret != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read from the file
+bool UnixFileRead(void *pData, void *buf, UINT size)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = read(p->fd, buf, size);
+ if (ret != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Flush to the file
+void UnixFileFlush(void *pData)
+{
+ UNIXIO *p;
+ bool write_mode;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (UNIXIO *)pData;
+
+ write_mode = p->write_mode;
+
+ if (write_mode)
+ {
+ fsync(p->fd);
+ }
+}
+
+// Close the file
+void UnixFileClose(void *pData, bool no_flush)
+{
+ UNIXIO *p;
+ bool write_mode;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (UNIXIO *)pData;
+
+ write_mode = p->write_mode;
+
+ if (write_mode && no_flush == false)
+ {
+ fsync(p->fd);
+ }
+
+ close(p->fd);
+
+ UnixMemoryFree(p);
+
+ if (write_mode)
+ {
+ //sync();
+ }
+}
+
+// Create a file
+void *UnixFileCreateW(wchar_t *name)
+{
+ void *ret;
+ char *name8 = CopyUniToUtf(name);
+
+ ret = UnixFileCreate(name8);
+
+ Free(name8);
+
+ return ret;
+}
+void *UnixFileCreate(char *name)
+{
+ UNIXIO *p;
+ int fd;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ fd = creat(name, 0600);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ p = UnixMemoryAlloc(sizeof(UNIXIO));
+ p->fd = fd;
+ p->write_mode = true;
+
+ return (void *)p;
+}
+
+// Open the file
+void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ char *name8 = CopyUniToUtf(name);
+ void *ret;
+
+ ret = UnixFileOpen(name8, write_mode, read_lock);
+
+ Free(name8);
+
+ return ret;
+}
+void *UnixFileOpen(char *name, bool write_mode, bool read_lock)
+{
+ UNIXIO *p;
+ int fd;
+ int mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (write_mode == false)
+ {
+ mode = O_RDONLY;
+ }
+ else
+ {
+ mode = O_RDWR;
+ }
+
+ // Open the file
+ fd = open(name, mode);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ p = UnixMemoryAlloc(sizeof(UNIXIO));
+ p->fd = fd;
+ p->write_mode = write_mode;
+
+ return (void *)p;
+}
+
+// Return the current thread ID
+UINT UnixThreadId()
+{
+ UINT ret;
+
+ ret = (UINT)pthread_self();
+
+ return ret;
+}
+
+// Thread function
+void *UnixDefaultThreadProc(void *param)
+{
+ UNIXTHREAD *ut;
+ UNIXTHREADSTARTUPINFO *info = (UNIXTHREADSTARTUPINFO *)param;
+ if (info == NULL)
+ {
+ return 0;
+ }
+
+ ut = (UNIXTHREAD *)info->thread->pData;
+
+ // Call the thread function
+ info->thread_proc(info->thread, info->param);
+
+ // Set a termination flag
+ ut->finished = true;
+
+ // Release of reference
+ ReleaseThread(info->thread);
+
+ UnixMemoryFree(info);
+
+ FreeOpenSSLThreadState();
+
+ return 0;
+}
+
+// Release of thread
+void UnixFreeThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Free memory
+ UnixMemoryFree(t->pData);
+}
+
+// Wait for the termination of the thread
+bool UnixWaitThread(THREAD *t)
+{
+ UNIXTHREAD *ut;
+ void *retcode = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ ut = (UNIXTHREAD *)t->pData;
+ if (ut == NULL)
+ {
+ return false;
+ }
+
+ pthread_join(ut->thread, &retcode);
+
+ return true;
+}
+
+// Thread initialization
+bool UnixInitThread(THREAD *t)
+{
+ UNIXTHREAD *ut;
+ UNIXTHREADSTARTUPINFO *info;
+ pthread_attr_t attr;
+ // Validate arguments
+ if (t == NULL || t->thread_proc == NULL)
+ {
+ return false;
+ }
+
+ // Thread data creation
+ ut = UnixMemoryAlloc(sizeof(UNIXTHREAD));
+ Zero(ut, sizeof(UNIXTHREAD));
+
+ // Creating the startup information
+ info = UnixMemoryAlloc(sizeof(UNIXTHREADSTARTUPINFO));
+ Zero(info, sizeof(UNIXTHREADSTARTUPINFO));
+ info->param = t->param;
+ info->thread_proc = t->thread_proc;
+ info->thread = t;
+ AddRef(t->ref);
+
+ // Thread creation
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, UNIX_THREAD_STACK_SIZE);
+
+ t->pData = (void *)ut;
+
+ if (pthread_create(&ut->thread, &attr, UnixDefaultThreadProc, info) != 0)
+ {
+ // An error has occured
+ t->pData = NULL;
+ Release(t->ref);
+ UnixMemoryFree(ut);
+ UnixMemoryFree(info);
+ pthread_attr_destroy(&attr);
+ return false;
+ }
+
+ pthread_attr_destroy(&attr);
+
+ return true;
+}
+
+// Release the event
+void UnixFreeEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_cond_destroy(&ue->cond);
+ pthread_mutex_destroy(&ue->mutex);
+
+ UnixMemoryFree(ue);
+}
+
+// Wait for a event
+bool UnixWaitEvent(EVENT *event, UINT timeout)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ struct timeval now;
+ struct timespec to;
+ bool ret;
+ if (ue == NULL)
+ {
+ return false;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ gettimeofday(&now, NULL);
+ to.tv_sec = now.tv_sec + timeout / 1000;
+ to.tv_nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000 * 1000;
+ if ((to.tv_nsec / 1000000000) >= 1)
+ {
+ to.tv_sec += to.tv_nsec / 1000000000;
+ to.tv_nsec = to.tv_nsec % 1000000000;
+ }
+
+ ret = true;
+
+ while (ue->signal == false)
+ {
+ if (timeout != INFINITE)
+ {
+ if (pthread_cond_timedwait(&ue->cond, &ue->mutex, &to))
+ {
+ ret = false;
+ break;
+ }
+ }
+ else
+ {
+ pthread_cond_wait(&ue->cond, &ue->mutex);
+ }
+ }
+ ue->signal = false;
+
+ pthread_mutex_unlock(&ue->mutex);
+
+ return ret;
+}
+
+// Reset the event
+void UnixResetEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ ue->signal = false;
+ pthread_cond_signal(&ue->cond);
+ pthread_mutex_unlock(&ue->mutex);
+}
+
+// Set the event
+void UnixSetEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ ue->signal = true;
+ pthread_cond_signal(&ue->cond);
+ pthread_mutex_unlock(&ue->mutex);
+}
+
+// Initialize the event
+void UnixInitEvent(EVENT *event)
+{
+ UNIXEVENT *ue = UnixMemoryAlloc(sizeof(UNIXEVENT));
+
+ Zero(ue, sizeof(UNIXEVENT));
+
+ pthread_cond_init(&ue->cond, NULL);
+ pthread_mutex_init(&ue->mutex, NULL);
+ ue->signal = false;
+
+ event->pData = (void *)ue;
+}
+
+// Delete the lock
+void UnixDeleteLock(LOCK *lock)
+{
+ pthread_mutex_t *mutex;
+ // Reset Ready flag safely
+ UnixLock(lock);
+ lock->Ready = false;
+ UnixUnlockEx(lock, true);
+
+ // Delete the mutex
+ mutex = (pthread_mutex_t *)lock->pData;
+ pthread_mutex_destroy(mutex);
+
+ // Memory release
+ UnixMemoryFree(mutex);
+ UnixMemoryFree(lock);
+}
+
+// Unlock
+void UnixUnlock(LOCK *lock)
+{
+ UnixUnlockEx(lock, false);
+}
+void UnixUnlockEx(LOCK *lock, bool inner)
+{
+ pthread_mutex_t *mutex;
+ if (lock->Ready == false && inner == false)
+ {
+ // State is invalid
+ return;
+ }
+ mutex = (pthread_mutex_t *)lock->pData;
+
+ if ((--lock->locked_count) > 0)
+ {
+ return;
+ }
+
+ lock->thread_id = INFINITE;
+
+ pthread_mutex_unlock(mutex);
+
+ return;
+}
+
+// Lock
+bool UnixLock(LOCK *lock)
+{
+ pthread_mutex_t *mutex;
+ UINT thread_id = UnixThreadId();
+ if (lock->Ready == false)
+ {
+ // State is invalid
+ return false;
+ }
+
+ if (lock->thread_id == thread_id)
+ {
+ lock->locked_count++;
+ return true;
+ }
+
+ mutex = (pthread_mutex_t *)lock->pData;
+
+ pthread_mutex_lock(mutex);
+
+ lock->thread_id = thread_id;
+ lock->locked_count++;
+
+ return true;
+}
+
+// Creating a new lock
+LOCK *UnixNewLock()
+{
+ pthread_mutex_t *mutex;
+ // Memory allocation
+ LOCK *lock = UnixMemoryAlloc(sizeof(LOCK));
+
+ // Create a mutex
+ mutex = UnixMemoryAlloc(sizeof(pthread_mutex_t));
+
+ // Initialization of the mutex
+ pthread_mutex_init(mutex, NULL);
+
+ lock->pData = (void *)mutex;
+ lock->Ready = true;
+
+ lock->thread_id = INFINITE;
+ lock->locked_count = 0;
+
+ return lock;
+}
+
+// Sleep
+void UnixSleep(UINT time)
+{
+ UINT sec = 0, millisec = 0;
+ // Validate arguments
+ if (time == 0)
+ {
+ return;
+ }
+
+ if (time == INFINITE)
+ {
+ // Wait forever
+ while (true)
+ {
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(time);
+#else
+ sleep(1000000);
+#endif
+ }
+ }
+
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(time);
+#else
+
+ // Prevent overflow
+ sec = time / 1000;
+ millisec = time % 1000;
+
+ if (sec != 0)
+ {
+ sleep(sec);
+ }
+ if (millisec != 0)
+ {
+ usleep(millisec * 1000);
+ }
+#endif
+}
+
+// Decrement
+void UnixDec32(UINT *value)
+{
+ if (value != NULL)
+ {
+ (*value)--;
+ }
+}
+
+// Increment
+void UnixInc32(UINT *value)
+{
+ if (value != NULL)
+ {
+ (*value)++;
+ }
+}
+
+// Get the System Time
+void UnixGetSystemTime(SYSTEMTIME *system_time)
+{
+ time_t now = 0;
+ struct tm tm;
+ struct timeval tv;
+ struct timezone tz;
+ // Validate arguments
+ if (system_time == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&get_time_lock);
+
+ Zero(system_time, sizeof(SYSTEMTIME));
+ Zero(&tv, sizeof(tv));
+ Zero(&tz, sizeof(tz));
+
+ time(&now);
+
+ gmtime_r(&now, &tm);
+
+ TmToSystem(system_time, &tm);
+
+ gettimeofday(&tv, &tz);
+
+ system_time->wMilliseconds = tv.tv_usec / 1000;
+
+ pthread_mutex_unlock(&get_time_lock);
+}
+
+// Get the system timer (64bit)
+UINT64 UnixGetTick64()
+{
+#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
+
+ struct timespec t;
+ UINT64 ret;
+ static bool akirame = false;
+
+ if (akirame)
+ {
+ return TickRealtimeManual();
+ }
+
+ Zero(&t, sizeof(t));
+
+ // Function to get the boot time of the system
+ // Be careful. The Implementation is depend on the system.
+#ifdef CLOCK_HIGHRES
+ clock_gettime(CLOCK_HIGHRES, &t);
+#else // CLOCK_HIGHRES
+#ifdef CLOCK_MONOTONIC
+ clock_gettime(CLOCK_MONOTONIC, &t);
+#else // CLOCK_MONOTONIC
+ clock_gettime(CLOCK_REALTIME, &t);
+#endif // CLOCK_MONOTONIC
+#endif // CLOCK_HIGHRES
+
+ ret = (UINT64)t.tv_sec * 1000LL + (UINT64)t.tv_nsec / 1000000LL;
+
+ if (akirame == false && ret == 0)
+ {
+ ret = TickRealtimeManual();
+ akirame = true;
+ }
+
+ return ret;
+
+#else
+
+ return TickRealtimeManual();
+
+#endif
+}
+
+// Get the system timer
+UINT UnixGetTick()
+{
+ return (UINT)UnixGetTick64();
+}
+
+// Memory allocation
+void *UnixMemoryAlloc(UINT size)
+{
+ void *r;
+ pthread_mutex_lock(&malloc_lock);
+ r = malloc(size);
+ pthread_mutex_unlock(&malloc_lock);
+ return r;
+}
+
+// Reallocation of the memory
+void *UnixMemoryReAlloc(void *addr, UINT size)
+{
+ void *r;
+ pthread_mutex_lock(&malloc_lock);
+ r = realloc(addr, size);
+ pthread_mutex_unlock(&malloc_lock);
+ return r;
+}
+
+// Free the memory
+void UnixMemoryFree(void *addr)
+{
+ pthread_mutex_lock(&malloc_lock);
+ free(addr);
+ pthread_mutex_unlock(&malloc_lock);
+}
+
+// SIGCHLD handler
+void UnixSigChldHandler(int sig)
+{
+ // Recall the zombie processes
+ while (waitpid(-1, NULL, WNOHANG) > 0);
+ signal(SIGCHLD, UnixSigChldHandler);
+}
+
+// Initialize the library for UNIX
+void UnixInit()
+{
+ UNIXIO *o;
+
+ UnixInitSolarisSleep();
+
+ // Global lock
+ pthread_mutex_init(&get_time_lock, NULL);
+ pthread_mutex_init(&malloc_lock, NULL);
+
+ // Get the Process ID
+ current_process_id = getpid();
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, UNIX_MAX_MEMORY);
+#endif // RLIMIT_CORE
+
+#ifdef RLIMIT_DATA
+ UnixSetResourceLimit(RLIMIT_DATA, UNIX_MAX_MEMORY);
+#endif // RLIMIT_DATA
+
+#ifdef RLIMIT_NOFILE
+#ifndef UNIX_MACOS
+ UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD);
+#else // UNIX_MACOS
+ UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD_MACOS);
+#endif // UNIX_MACOS
+#endif // RLIMIT_NOFILE
+
+#ifdef RLIMIT_STACK
+// UnixSetResourceLimit(RLIMIT_STACK, UNIX_MAX_MEMORY);
+#endif // RLIMIT_STACK
+
+#ifdef RLIMIT_RSS
+ UnixSetResourceLimit(RLIMIT_RSS, UNIX_MAX_MEMORY);
+#endif // RLIMIT_RSS
+
+#ifdef RLIMIT_LOCKS
+ UnixSetResourceLimit(RLIMIT_LOCKS, UNIX_MAX_LOCKS);
+#endif // RLIMIT_LOCKS
+
+#ifdef RLIMIT_MEMLOCK
+ UnixSetResourceLimit(RLIMIT_MEMLOCK, UNIX_MAX_MEMORY);
+#endif // RLIMIT_MEMLOCK
+
+#ifdef RLIMIT_NPROC
+ UnixSetResourceLimit(RLIMIT_NPROC, UNIX_MAX_CHILD_PROCESSES);
+#endif // RLIMIT_NPROC
+
+ // Write a value to the threads-max of the proc file system
+ o = UnixFileCreate("/proc/sys/kernel/threads-max");
+ if (o != NULL)
+ {
+ char tmp[128];
+ sprintf(tmp, "%u\n", UNIX_LINUX_MAX_THREADS);
+ UnixFileWrite(o, tmp, strlen(tmp));
+ UnixFileClose(o, false);
+ }
+
+ // Set the signals that is to be ignored
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGALRM, SIG_IGN);
+
+#ifdef UNIX_BSD
+ signal(64, SIG_IGN);
+#endif // UNIX_BSD
+
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif // SIGXFSZ
+
+ // Set a signal handler to salvage the child processes
+ signal(SIGCHLD, UnixSigChldHandler);
+}
+
+// Release the library for UNIX
+void UnixFree()
+{
+ UnixFreeSolarisSleep();
+
+ current_process_id = 0;
+
+ pthread_mutex_destroy(&get_time_lock);
+}
+
+// Adjust the upper limit of resources that may be occupied
+void UnixSetResourceLimit(UINT id, UINT value)
+{
+ struct rlimit t;
+ UINT hard_limit;
+
+ Zero(&t, sizeof(t));
+ getrlimit(id, &t);
+
+ hard_limit = t.rlim_max;
+
+ Zero(&t, sizeof(t));
+ t.rlim_cur = MIN(value, hard_limit);
+ t.rlim_max = hard_limit;
+ setrlimit(id, &t);
+
+ Zero(&t, sizeof(t));
+ t.rlim_cur = value;
+ t.rlim_max = value;
+ setrlimit(id, &t);
+}
+
+// Generate the PID file name
+void UnixGenPidFileName(char *name, UINT size)
+{
+ char exe_name[MAX_PATH];
+ UCHAR hash[MD5_SIZE];
+ char tmp1[64];
+ char dir[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ GetExeName(exe_name, sizeof(exe_name));
+ StrCat(exe_name, sizeof(exe_name), ":pid_hash");
+ StrUpper(exe_name);
+
+ Hash(hash, exe_name, StrLen(exe_name), false);
+ BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
+
+ Format(name, size, "%s/.pid_%s", dir, tmp1);
+}
+
+// Delete the PID file
+void UnixDeletePidFile()
+{
+ char tmp[MAX_PATH];
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+
+ UnixFileDelete(tmp);
+}
+
+// Delete the CTL file
+void UnixDeleteCtlFile()
+{
+ char tmp[MAX_PATH];
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+
+ UnixFileDelete(tmp);
+}
+
+// Generate the CTL file name
+void UnixGenCtlFileName(char *name, UINT size)
+{
+ char exe_name[MAX_PATH];
+ UCHAR hash[MD5_SIZE];
+ char tmp1[64];
+ char dir[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ GetExeName(exe_name, sizeof(exe_name));
+ StrCat(exe_name, sizeof(exe_name), ":pid_hash");
+ StrUpper(exe_name);
+
+ Hash(hash, exe_name, StrLen(exe_name), false);
+ BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
+
+ Format(name, size, "%s/.ctl_%s", dir, tmp1);
+}
+
+// Write the CTL file
+void UnixWriteCtlFile(UINT i)
+{
+ char tmp[MAX_PATH];
+ char tmp2[64];
+ IO *o;
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+ Format(tmp2, sizeof(tmp2), "%u\n", i);
+
+ o = FileCreate(tmp);
+ if (o != NULL)
+ {
+ FileWrite(o, tmp2, StrLen(tmp2));
+ FileClose(o);
+ }
+}
+
+// Write to the PID file
+void UnixWritePidFile(UINT pid)
+{
+ char tmp[MAX_PATH];
+ char tmp2[64];
+ IO *o;
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+ Format(tmp2, sizeof(tmp2), "%u\n", pid);
+
+ o = FileCreate(tmp);
+ if (o != NULL)
+ {
+ FileWrite(o, tmp2, StrLen(tmp2));
+ FileClose(o);
+ }
+}
+
+// Read the PID file
+UINT UnixReadPidFile()
+{
+ char tmp[MAX_PATH];
+ BUF *buf;
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+
+ buf = ReadDump(tmp);
+ if (buf == NULL)
+ {
+ return 0;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
+ FreeBuf(buf);
+
+ return ToInt(tmp);
+}
+
+// Read the CTL file
+UINT UnixReadCtlFile()
+{
+ char tmp[MAX_PATH];
+ BUF *buf;
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+
+ buf = ReadDump(tmp);
+ if (buf == NULL)
+ {
+ return 0;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
+ FreeBuf(buf);
+
+ return ToInt(tmp);
+}
+
+// Get the UID
+UINT UnixGetUID()
+{
+ return (UINT)getuid();
+}
+
+// Start the service
+void UnixStartService(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ char exe[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeName(exe, sizeof(exe));
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ // Examine whether the service has not been started already
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ // Service is already running
+ UniPrint(_UU("UNIX_SVC_ALREADY_START"), svc_title, svc_name);
+ }
+ else
+ {
+ int pid;
+ // Begin to start the service
+ UniPrint(_UU("UNIX_SVC_STARTED"), svc_title);
+ FreeSingleInstance(inst);
+
+ // Create a child process
+ pid = fork();
+ if (pid == -1)
+ {
+ UniPrint(_UU("UNIX_SVC_ERROR_FORK"), svc_title);
+ }
+ else
+ {
+ if (pid == 0)
+ {
+ // Child process
+ char *param = UNIX_SVC_ARG_EXEC_SVC;
+ char **args;
+
+ // Daemonize
+ setsid();
+ UnixCloseIO();
+ signal(SIGHUP, SIG_IGN);
+
+ // Prepare arguments
+ args = ZeroMalloc(sizeof(char *) * 3);
+ args[0] = exe;
+ args[1] = param;
+ args[2] = NULL;
+
+ execvp(exe, args);
+ AbortExit();
+ }
+ else
+ {
+ // Don't write the child process number to the file
+// UnixWritePidFile(pid);
+ }
+ }
+ }
+}
+
+// Stop the Service
+void UnixStopService(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ char exe[MAX_PATH];
+ UINT pid;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeName(exe, sizeof(exe));
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ inst = NewSingleInstance(NULL);
+ pid = UnixReadPidFile();
+ if (inst != NULL || pid == 0)
+ {
+ // Service is not running yet
+ UniPrint(_UU("UNIX_SVC_NOT_STARTED"), svc_title, svc_name);
+ }
+ else
+ {
+ int status;
+
+ // Stop the service
+ UniPrint(_UU("UNIX_SVC_STOPPING"), svc_title);
+
+ // Terminate the process
+ kill(pid, SIGTERM);
+#ifdef UNIX_BSD
+ UnixWriteCtlFile(Rand32());
+#endif // UNIX_BSD
+ if (UnixWaitProcessEx(pid, UNIX_SERVICE_STOP_TIMEOUT_2))
+ {
+ UniPrint(_UU("UNIX_SVC_STOPPED"), svc_title);
+ }
+ else
+ {
+ UniPrint(_UU("UNIX_SVC_STOP_FAILED"), svc_title);
+ }
+ }
+
+ FreeSingleInstance(inst);
+}
+
+// Handler of the stop signal to the process
+void UnixSigTermHandler(int signum)
+{
+ if (signum == SIGTERM)
+ {
+ unix_svc_terminate = true;
+ }
+}
+
+// The thread for stop service
+void UnixStopThread(THREAD *t, void *param)
+{
+ SERVICE_FUNCTION *stop = (SERVICE_FUNCTION *)param;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ stop();
+}
+
+// Execute the main body of the service
+void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ UINT yobi_size = 1024 * 128;
+ void *yobi1, *yobi2;
+ UINT saved_ctl;
+ // Validate arguments
+ if (start == NULL || stop == NULL || name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ UnixWriteCtlFile(Rand32());
+ saved_ctl = UnixReadCtlFile();
+
+ inst = NewSingleInstance(NULL);
+ if (inst != NULL)
+ {
+ THREAD *t;
+
+ yobi1 = ZeroMalloc(yobi_size);
+ yobi2 = ZeroMalloc(yobi_size);
+
+ // Start
+ UnixWritePidFile(getpid());
+
+ start();
+
+ // Starting complete. wait for arriving SIGTERM from another process
+ signal(SIGTERM, &UnixSigTermHandler);
+ while (unix_svc_terminate == false)
+ {
+#ifndef UNIX_BSD
+ pause();
+#else // UNIX_BSD
+ if (UnixReadCtlFile() != saved_ctl)
+ {
+ break;
+ }
+
+ SleepThread(1394);
+#endif // UNIX_BSD
+ }
+
+ // Stop
+ Free(yobi1);
+ t = NewThread(UnixStopThread, stop);
+ if (t == NULL || (WaitThread(t, UNIX_SERVICE_STOP_TIMEOUT_1) == false))
+ {
+ // Terminate forcibly if creation of a halting thread have
+ // failed or timed out
+ Free(yobi2);
+ FreeSingleInstance(inst);
+ UnixDeletePidFile();
+ _exit(0);
+ }
+ ReleaseThread(t);
+
+ // Delete the PID file
+ UnixDeletePidFile();
+
+ // Delete the CTL file
+ UnixDeleteCtlFile();
+
+ FreeSingleInstance(inst);
+
+ Free(yobi2);
+ }
+}
+
+// Get whether the process with the specified pid exists
+bool UnixIsProcess(UINT pid)
+{
+ if (getsid((pid_t)pid) == -1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Wait for the termination of the specified process
+bool UnixWaitProcessEx(UINT pid, UINT timeout)
+{
+ UINT64 start_tick = Tick64();
+ UINT64 end_tick = start_tick + (UINT64)timeout;
+ if (timeout == INFINITE)
+ {
+ end_tick = 0;
+ }
+ while (UnixIsProcess(pid))
+ {
+ if (end_tick != 0)
+ {
+ if (end_tick < Tick64())
+ {
+ return false;
+ }
+ }
+ SleepThread(100);
+ }
+ return true;
+}
+void UnixWaitProcess(UINT pid)
+{
+ UnixWaitProcessEx(pid, INFINITE);
+}
+
+// Description of how to start
+void UnixUsage(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ UniPrint(_UU("UNIX_SVC_HELP"), svc_title, svc_name, svc_name, svc_title, svc_name, svc_title);
+}
+
+// Main function of the UNIX service
+UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ // Validate arguments
+ if (name == NULL || start == NULL || stop == NULL)
+ {
+ return 0;
+ }
+
+ if (argc >= 2 && StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
+ {
+ UINT pid;
+ // Start a child process
+ // Restart if the child process didn't exit properly
+
+RESTART_PROCESS:
+ pid = fork();
+ if ((int)pid != -1)
+ {
+ if (pid == 0)
+ {
+ // Run the main process
+ UnixServiceMain(argc, argv, name, start, stop);
+ }
+ else
+ {
+ int status = 0, ret;
+
+ // Wait for the termination of the child process
+ ret = waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status) == 0)
+ {
+ // Aborted
+ UnixSleep(100);
+ goto RESTART_PROCESS;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Start normally
+ UnixServiceMain(argc, argv, name, start, stop);
+ }
+
+ return 0;
+}
+void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ UINT mode = 0;
+ // Start of the Mayaqua
+ InitMayaqua(false, false, argc, argv);
+
+ if (argc >= 2)
+ {
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_START) == 0)
+ {
+ mode = UNIX_SVC_MODE_START;
+ }
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_STOP) == 0)
+ {
+ mode = UNIX_SVC_MODE_STOP;
+ }
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
+ {
+ mode = UNIX_SVC_MODE_EXEC_SVC;
+ }
+ if (StrCmpi(argv[1], UNIX_ARG_EXIT) == 0)
+ {
+ mode = UNIX_SVC_MODE_EXIT;
+ }
+ }
+
+ switch (mode)
+ {
+ case UNIX_SVC_MODE_EXIT:
+ break;
+
+ case UNIX_SVC_MODE_START:
+ UnixStartService(name);
+ break;
+
+ case UNIX_SVC_MODE_STOP:
+ UnixStopService(name);
+ break;
+
+ case UNIX_SVC_MODE_EXEC_SVC:
+ UnixExecService(name, start, stop);
+ break;
+
+ default:
+ UnixUsage(name);
+ break;
+ }
+
+ // End of the Mayaqua
+ FreeMayaqua();
+
+ return;
+}
+
+#endif // UNIX
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Unix.h b/src/Mayaqua/Unix.h
new file mode 100644
index 00000000..1f881a15
--- /dev/null
+++ b/src/Mayaqua/Unix.h
@@ -0,0 +1,239 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Unix.h
+// Header of Unix.c
+
+#ifdef OS_UNIX
+
+#ifndef UNIX_H
+#define UNIX_H
+
+// Constants
+#define UNIX_THREAD_STACK_SIZE (200 * 1000) // Stack size
+#define UNIX_MAX_CHILD_PROCESSES 2000000 // Maximum number of child processes
+#define UNIX_LINUX_MAX_THREADS 200000000 // Maximum number of threads
+#define UNIX_MAX_LOCKS 65536 // Maximum number of locks
+#define UNIX_MAX_MEMORY (2147483648UL) // Maximum memory capacity
+#define UNIX_MAX_FD (655360) // Maximum number of FDs
+#define UNIX_MAX_FD_MACOS (10000) // Maximum number of FDs (Mac OS X)
+#define MAXIMUM_WAIT_OBJECTS 64 // Maximum number of select
+
+#define UNIX_SERVICE_STOP_TIMEOUT_1 (600 * 1000) // Timeout to stop the service
+#define UNIX_SERVICE_STOP_TIMEOUT_2 (900 * 1000) // Timeout to stop the service (parent process)
+
+
+// Service related
+typedef void (SERVICE_FUNCTION)();
+
+#define SVC_NAME "SVC_%s_NAME"
+#define SVC_TITLE "SVC_%s_TITLE"
+
+#define UNIX_SVC_ARG_START "start"
+#define UNIX_SVC_ARG_STOP "stop"
+#define UNIX_SVC_ARG_EXEC_SVC "execsvc"
+#define UNIX_ARG_EXIT "exit"
+
+#define UNIX_SVC_MODE_START 1
+#define UNIX_SVC_MODE_STOP 2
+#define UNIX_SVC_MODE_EXEC_SVC 3
+#define UNIX_SVC_MODE_EXIT 4
+
+
+// Function prototype
+OS_DISPATCH_TABLE *UnixGetDispatchTable();
+void UnixInit();
+void UnixFree();
+void *UnixMemoryAlloc(UINT size);
+void *UnixMemoryReAlloc(void *addr, UINT size);
+void UnixMemoryFree(void *addr);
+UINT UnixGetTick();
+void UnixGetSystemTime(SYSTEMTIME *system_time);
+void UnixInc32(UINT *value);
+void UnixDec32(UINT *value);
+void UnixSleep(UINT time);
+LOCK *UnixNewLock();
+bool UnixLock(LOCK *lock);
+void UnixUnlock(LOCK *lock);
+void UnixUnlockEx(LOCK *lock, bool inner);
+void UnixDeleteLock(LOCK *lock);
+void UnixInitEvent(EVENT *event);
+void UnixSetEvent(EVENT *event);
+void UnixResetEvent(EVENT *event);
+bool UnixWaitEvent(EVENT *event, UINT timeout);
+void UnixFreeEvent(EVENT *event);
+bool UnixWaitThread(THREAD *t);
+void UnixFreeThread(THREAD *t);
+bool UnixInitThread(THREAD *t);
+UINT UnixThreadId();
+void *UnixFileOpen(char *name, bool write_mode, bool read_lock);
+void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *UnixFileCreate(char *name);
+void *UnixFileCreateW(wchar_t *name);
+bool UnixFileWrite(void *pData, void *buf, UINT size);
+bool UnixFileRead(void *pData, void *buf, UINT size);
+void UnixFileClose(void *pData, bool no_flush);
+void UnixFileFlush(void *pData);
+UINT64 UnixFileSize(void *pData);
+bool UnixFileSeek(void *pData, UINT mode, int offset);
+bool UnixFileDelete(char *name);
+bool UnixFileDeleteW(wchar_t *name);
+bool UnixMakeDir(char *name);
+bool UnixMakeDirW(wchar_t *name);
+bool UnixDeleteDir(char *name);
+bool UnixDeleteDirW(wchar_t *name);
+CALLSTACK_DATA *UnixGetCallStack();
+bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool UnixFileRename(char *old_name, char *new_name);
+bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name);
+bool UnixRun(char *filename, char *arg, bool hide, bool wait);
+bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+bool UnixIsSupportedOs();
+void UnixGetOsInfo(OS_INFO *info);
+void UnixAlert(char *msg, char *caption);
+void UnixAlertW(wchar_t *msg, wchar_t *caption);
+char *UnixGetProductId();
+void UnixSetHighPriority();
+void UnixRestorePriority();
+void *UnixNewSingleInstance(char *instance_name);
+void UnixFreeSingleInstance(void *data);
+void UnixGetMemInfo(MEMINFO *info);
+void UnixYield();
+TOKEN_LIST *UnixExec(char *cmd);
+void UnixExecSilent(char *cmd);
+void UnixDisableInterfaceOffload(char *name);
+void UnixSetEnableKernelEspProcessing(bool b);
+
+void UnixSetThreadPriorityRealtime();
+void UnixSetThreadPriorityLow();
+void UnixSetThreadPriorityHigh();
+void UnixSetThreadPriorityIdle();
+void UnixRestoreThreadPriority();
+void UnixSetResourceLimit(UINT id, UINT value);
+UINT64 UnixGetTick64();
+void UnixSigChldHandler(int sig);
+void UnixCloseIO();
+void UnixDaemon(bool debug_mode);
+void UnixGetCurrentDir(char *dir, UINT size);
+void UnixGetCurrentDirW(wchar_t *dir, UINT size);
+bool UnixCheckExecAccess(char *name);
+bool UnixCheckExecAccessW(wchar_t *name);
+DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare);
+bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+void UnixInitSolarisSleep();
+void UnixFreeSolarisSleep();
+void UnixSolarisSleep(UINT msec);
+
+UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixGenPidFileName(char *name, UINT size);
+void UnixGenCtlFileName(char *name, UINT size);
+void UnixStartService(char *name);
+void UnixStopService(char *name);
+void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixUsage(char *name);
+void UnixWritePidFile(UINT pid);
+void UnixWriteCtlFile(UINT i);
+UINT UnixReadPidFile();
+UINT UnixReadCtlFile();
+bool UnixIsProcess(UINT pid);
+bool UnixWaitProcessEx(UINT pid, UINT timeout);
+void UnixWaitProcess(UINT pid);
+void UnixDeletePidFile();
+void UnixDeleteCtlFile();
+void UnixStopThread(THREAD *t, void *param);
+UINT UnixGetUID();
+void UnixIgnoreSignalForThread(int sig);
+
+bool UnixIsInVmMain();
+bool UnixIsInVm();
+
+
+#endif // UNIX_H
+
+#endif // OS_UNIX
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Win32.c b/src/Mayaqua/Win32.c
new file mode 100644
index 00000000..7e1cc778
--- /dev/null
+++ b/src/Mayaqua/Win32.c
@@ -0,0 +1,3463 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32.c
+// Microsoft Windows dependent code
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <Dbghelp.h>
+#include <commctrl.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static HANDLE heap_handle = NULL;
+static HANDLE hstdout = INVALID_HANDLE_VALUE;
+static HANDLE hstdin = INVALID_HANDLE_VALUE;
+
+// Thread data for Win32
+typedef struct WIN32THREAD
+{
+ HANDLE hThread;
+ DWORD thread_id;
+} WIN32THREAD;
+
+// Thread startup information for Win32
+typedef struct WIN32THREADSTARTUPINFO
+{
+ THREAD_PROC *thread_proc;
+ void *param;
+ THREAD *thread;
+} WIN32THREADSTARTUPINFO;
+
+// Function prototype for Win32
+DWORD CALLBACK Win32DefaultThreadProc(void *param);
+
+// Current process handle
+static HANDLE hCurrentProcessHandle = NULL;
+static CRITICAL_SECTION fasttick_lock;
+static UINT64 start_tick = 0;
+static bool use_heap_api = false;
+static bool win32_is_nt = false;
+
+// File I/O data for Win32
+typedef struct WIN32IO
+{
+ HANDLE hFile;
+ bool WriteMode;
+} WIN32IO;
+
+// Mutex data for Win32
+typedef struct WIN32MUTEX
+{
+ HANDLE hMutex;
+} WIN32MUTEX;
+
+// Set the Thread name
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+// Create a dispatch table
+OS_DISPATCH_TABLE *Win32GetDispatchTable()
+{
+ static OS_DISPATCH_TABLE t =
+ {
+ Win32Init,
+ Win32Free,
+ Win32MemoryAlloc,
+ Win32MemoryReAlloc,
+ Win32MemoryFree,
+ Win32GetTick,
+ Win32GetSystemTime,
+ Win32Inc32,
+ Win32Dec32,
+ Win32Sleep,
+ Win32NewLock,
+ Win32Lock,
+ Win32Unlock,
+ Win32DeleteLock,
+ Win32InitEvent,
+ Win32SetEvent,
+ Win32ResetEvent,
+ Win32WaitEvent,
+ Win32FreeEvent,
+ Win32WaitThread,
+ Win32FreeThread,
+ Win32InitThread,
+ Win32ThreadId,
+ Win32FileOpen,
+ Win32FileOpenW,
+ Win32FileCreate,
+ Win32FileCreateW,
+ Win32FileWrite,
+ Win32FileRead,
+ Win32FileClose,
+ Win32FileFlush,
+ Win32FileSize,
+ Win32FileSeek,
+ Win32FileDelete,
+ Win32FileDeleteW,
+ Win32MakeDir,
+ Win32MakeDirW,
+ Win32DeleteDir,
+ Win32DeleteDirW,
+ Win32GetCallStack,
+ Win32GetCallStackSymbolInfo,
+ Win32FileRename,
+ Win32FileRenameW,
+ Win32Run,
+ Win32RunW,
+ Win32IsSupportedOs,
+ Win32GetOsInfo,
+ Win32Alert,
+ Win32AlertW,
+ Win32GetProductId,
+ Win32SetHighPriority,
+ Win32RestorePriority,
+ Win32NewSingleInstance,
+ Win32FreeSingleInstance,
+ Win32GetMemInfo,
+ Win32Yield,
+ };
+
+ return &t;
+}
+
+// Set the thread name
+void Win32SetThreadName(UINT thread_id, char *name)
+{
+ DWORD ms_vc_exception = 0x406D1388;
+ THREADNAME_INFO t;
+ // Validate arguments
+ if (thread_id == 0 || name == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.dwType = 0x1000;
+ t.szName = name;
+ t.dwThreadID = thread_id;
+ t.dwFlags = 0;
+
+ __try
+ {
+ RaiseException(ms_vc_exception, 0, sizeof(t) / sizeof(ULONG_PTR), (ULONG_PTR *)&t);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+}
+
+// Initialization function of the new thread
+void Win32InitNewThread()
+{
+ static HINSTANCE hDll = NULL;
+ static bool (WINAPI *_SetThreadLocale)(LCID) = NULL;
+
+ if (hDll == NULL)
+ {
+ hDll = LoadLibrary("kernel32.dll");
+
+ _SetThreadLocale =
+ (bool (__stdcall *)(LCID))
+ GetProcAddress(hDll, "SetThreadLocale");
+ }
+
+ if (_SetThreadLocale != NULL)
+ {
+ _SetThreadLocale(LOCALE_USER_DEFAULT);
+ }
+}
+
+// Set the compression flag of the folder
+bool Win32SetFolderCompressW(wchar_t *path, bool compressed)
+{
+ HANDLE h;
+ UINT retsize = 0;
+ USHORT flag;
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *path_a = CopyUniToStr(path);
+ bool ret = Win32SetFolderCompress(path_a, compressed);
+
+ Free(path_a);
+
+ return ret;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), path);
+
+ // Open the folder
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
+
+ if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
+ NULL, 0, &retsize, NULL) == false)
+ {
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+bool Win32SetFolderCompress(char *path, bool compressed)
+{
+ HANDLE h;
+ UINT retsize = 0;
+ USHORT flag;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), path);
+
+ // Open the folder
+ h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
+
+ if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
+ NULL, 0, &retsize, NULL) == false)
+ {
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Get the free space of the disk
+bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT count = 0;
+ UINT i, n, len;
+ ULARGE_INTEGER v1, v2, v3;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *path_a = CopyUniToStr(path);
+
+ ret = Win32GetDiskFree(path_a, free_size, used_size, total_size);
+
+ Free(path_a);
+
+ return ret;
+ }
+
+ Zero(&v1, sizeof(v1));
+ Zero(&v2, sizeof(v2));
+ Zero(&v3, sizeof(v3));
+
+ NormalizePathW(tmp, sizeof(tmp), path);
+
+ // Get the directory name
+ if (UniStartWith(path, L"\\\\"))
+ {
+ count = 4;
+ }
+ else
+ {
+ count = 1;
+ }
+
+ len = UniStrLen(tmp);
+ n = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == L'\\')
+ {
+ n++;
+ if (n >= count)
+ {
+ tmp[i + 1] = 0;
+ break;
+ }
+ }
+ }
+
+ if (GetDiskFreeSpaceExW(tmp, &v1, &v2, &v3))
+ {
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1.QuadPart;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2.QuadPart;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2.QuadPart - v1.QuadPart;
+ }
+
+ return ret;
+}
+bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char tmp[MAX_SIZE];
+ UINT count = 0;
+ UINT i, n, len;
+ ULARGE_INTEGER v1, v2, v3;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ Zero(&v1, sizeof(v1));
+ Zero(&v2, sizeof(v2));
+ Zero(&v3, sizeof(v3));
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ // Get the directory name
+ if (StartWith(path, "\\\\"))
+ {
+ count = 4;
+ }
+ else
+ {
+ count = 1;
+ }
+
+ len = StrLen(tmp);
+ n = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == '\\')
+ {
+ n++;
+ if (n >= count)
+ {
+ tmp[i + 1] = 0;
+ break;
+ }
+ }
+ }
+
+ if (GetDiskFreeSpaceEx(tmp, &v1, &v2, &v3))
+ {
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1.QuadPart;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2.QuadPart;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2.QuadPart - v1.QuadPart;
+ }
+
+ return ret;
+}
+
+// Enumeration of directory
+DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare)
+{
+ DIRLIST *ret;
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+
+ ret = Win32EnumDirExW(dirname_w, compare);
+
+ Free(dirname_w);
+
+ return ret;
+}
+DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ WIN32_FIND_DATAA data_a;
+ WIN32_FIND_DATAW data_w;
+ HANDLE h;
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ wchar_t dirname2[MAX_PATH];
+ LIST *o;
+ DIRLIST *d;
+
+ UniStrCpy(tmp2, sizeof(tmp2), dirname);
+
+ if (UniStrLen(tmp2) >= 1 && tmp[UniStrLen(tmp2) - 1] == L'\\')
+ {
+ tmp2[UniStrLen(tmp2) - 1] = 0;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%s\\*.*", tmp2);
+ NormalizePathW(tmp, sizeof(tmp), tmp);
+ NormalizePathW(dirname2, sizeof(dirname2), tmp2);
+
+ o = NewListFast(compare);
+
+ Zero(&data_a, sizeof(data_a));
+ Zero(&data_w, sizeof(data_w));
+
+ if (IsNt())
+ {
+ h = FindFirstFileW(tmp, &data_w);
+ }
+ else
+ {
+ char *tmp_a = CopyUniToStr(tmp);
+
+ h = FindFirstFileA(tmp_a, &data_a);
+
+ Free(tmp_a);
+ }
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ bool b = true;
+
+ do
+ {
+ if (IsNt() == false)
+ {
+ Zero(&data_w, sizeof(data_w));
+ StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
+ data_w.dwFileAttributes = data_a.dwFileAttributes;
+ data_w.ftCreationTime = data_a.ftCreationTime;
+ data_w.ftLastWriteTime = data_a.ftLastWriteTime;
+ data_w.nFileSizeHigh = data_a.nFileSizeHigh;
+ data_w.nFileSizeLow = data_a.nFileSizeLow;
+ }
+
+ if (UniStrCmpi(data_w.cFileName, L"..") != 0 &&
+ UniStrCmpi(data_w.cFileName, L".") != 0)
+ {
+ DIRENT *f = ZeroMalloc(sizeof(DIRENT));
+ SYSTEMTIME t1, t2;
+ wchar_t fullpath[MAX_SIZE];
+ bool ok = false;
+
+ f->FileNameW = UniCopyStr(data_w.cFileName);
+ f->FileName = CopyUniToStr(f->FileNameW);
+ f->Folder = (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
+
+ CombinePathW(fullpath, sizeof(fullpath), dirname2, f->FileNameW);
+
+ // Attempt to get the file information
+ if (MsIsNt())
+ {
+ HANDLE h = CreateFileW(fullpath, 0,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ BY_HANDLE_FILE_INFORMATION info;
+
+ Zero(&info, sizeof(info));
+
+ if (MsGetFileInformation(h, &info))
+ {
+ Zero(&t1, sizeof(t1));
+ Zero(&t2, sizeof(t2));
+ FileTimeToSystemTime(&info.ftCreationTime, &t1);
+ FileTimeToSystemTime(&info.ftLastWriteTime, &t2);
+ f->CreateDate = SystemToUINT64(&t1);
+ f->UpdateDate = SystemToUINT64(&t2);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = ((UINT64)info.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)info.nFileSizeLow;
+ }
+
+ ok = true;
+ }
+
+ CloseHandle(h);
+ }
+ }
+
+ if (ok == false)
+ {
+ Zero(&t1, sizeof(t1));
+ Zero(&t2, sizeof(t2));
+ FileTimeToSystemTime(&data_w.ftCreationTime, &t1);
+ FileTimeToSystemTime(&data_w.ftLastWriteTime, &t2);
+ f->CreateDate = SystemToUINT64(&t1);
+ f->UpdateDate = SystemToUINT64(&t2);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = ((UINT64)data_w.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)data_w.nFileSizeLow;
+ }
+ }
+
+ Add(o, f);
+ }
+
+ Zero(&data_w, sizeof(data_w));
+ Zero(&data_a, sizeof(data_a));
+
+ if (IsNt())
+ {
+ b = FindNextFileW(h, &data_w);
+ }
+ else
+ {
+ b = FindNextFileA(h, &data_a);
+ }
+ }
+ while (b);
+
+ FindClose(h);
+ }
+
+ Sort(o);
+
+ d = ZeroMalloc(sizeof(DIRLIST));
+ d->NumFiles = LIST_NUM(o);
+ d->File = ToArray(o);
+
+ ReleaseList(o);
+
+ return d;
+}
+
+// Get the EXE file name
+void Win32GetExeNameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ Win32GetExeName(name_a, sizeof(name_a));
+
+ StrToUni(name, size, name_a);
+
+ return;
+ }
+
+ UniStrCpy(name, size, L"");
+
+ GetModuleFileNameW(NULL, name, size);
+}
+void Win32GetExeName(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(name, size, "");
+
+ GetModuleFileName(NULL, name, size);
+}
+
+// Get the current directory
+void Win32GetCurrentDirW(wchar_t *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char dir_a[MAX_PATH];
+
+ Win32GetCurrentDir(dir_a, sizeof(dir_a));
+
+ StrToUni(dir, size, dir_a);
+
+ return;
+ }
+
+ GetCurrentDirectoryW(size, dir);
+}
+void Win32GetCurrentDir(char *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ GetCurrentDirectory(size, dir);
+}
+
+// Yield
+void Win32Yield()
+{
+ Sleep(0);
+}
+
+// Get the memory information
+void Win32GetMemInfo(MEMINFO *info)
+{
+ static HINSTANCE hDll = NULL;
+ static bool (WINAPI *_GlobalMemoryStatusEx)(LPMEMORYSTATUSEX) = NULL;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(info, sizeof(MEMINFO));
+
+ if (hDll == NULL)
+ {
+ hDll = LoadLibrary("kernel32.dll");
+ }
+ if (hDll != NULL)
+ {
+ if (_GlobalMemoryStatusEx == NULL)
+ {
+ _GlobalMemoryStatusEx =
+ (bool (__stdcall *)(LPMEMORYSTATUSEX))GetProcAddress(hDll, "GlobalMemoryStatusEx");
+ }
+ }
+
+
+ if (_GlobalMemoryStatusEx == NULL)
+ {
+ // Old API
+ MEMORYSTATUS st;
+ Zero(&st, sizeof(st));
+ st.dwLength = sizeof(st);
+
+ GlobalMemoryStatus(&st);
+
+ // Amount of the logical memory
+ info->TotalMemory = (UINT64)st.dwTotalPageFile;
+ info->FreeMemory = (UINT64)st.dwAvailPageFile;
+ info->UsedMemory = info->TotalMemory - info->FreeMemory;
+
+ // Amount of the physical memory
+ info->TotalPhys = (UINT64)st.dwTotalPhys;
+ info->FreePhys = (UINT64)st.dwAvailPhys;
+ info->UsedPhys = info->TotalPhys - info->FreePhys;
+ }
+ else
+ {
+ // New API
+ MEMORYSTATUSEX st;
+ Zero(&st, sizeof(st));
+ st.dwLength = sizeof(st);
+
+ _GlobalMemoryStatusEx(&st);
+
+ // Amount of the logical memory
+ info->TotalMemory = st.ullTotalPageFile;
+ info->FreeMemory = st.ullAvailPageFile;
+ info->UsedMemory = info->TotalMemory - info->FreeMemory;
+
+ // Amount of the physical memory
+ info->TotalPhys = st.ullTotalPhys;
+ info->FreePhys = st.ullAvailPhys;
+ info->UsedPhys = info->TotalPhys - info->FreePhys;
+ }
+}
+
+// Creating a single instance
+void *Win32NewSingleInstance(char *instance_name)
+{
+ WIN32MUTEX *ret;
+ char tmp[MAX_SIZE];
+ HANDLE hMutex;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ char exe_path[MAX_PATH];
+ GetModuleFileName(NULL, exe_path, sizeof(exe_path));
+ HashInstanceName(tmp, sizeof(tmp), exe_path);
+ instance_name = tmp;
+ }
+
+ hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, instance_name);
+ if (hMutex != NULL)
+ {
+ CloseHandle(hMutex);
+ return NULL;
+ }
+
+ hMutex = CreateMutex(NULL, FALSE, instance_name);
+ if (hMutex == NULL)
+ {
+ CloseHandle(hMutex);
+ return NULL;
+ }
+
+ ret = Win32MemoryAlloc(sizeof(WIN32MUTEX));
+ ret->hMutex = hMutex;
+
+ return (void *)ret;
+}
+
+// Release the single instance
+void Win32FreeSingleInstance(void *data)
+{
+ WIN32MUTEX *m;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ m = (WIN32MUTEX *)data;
+ ReleaseMutex(m->hMutex);
+ CloseHandle(m->hMutex);
+
+ Win32MemoryFree(m);
+}
+
+// Raise the priority
+void Win32SetHighPriority()
+{
+ SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
+}
+
+// Restore the priority
+void Win32RestorePriority()
+{
+ SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+}
+
+// Get the node information
+char* Win32GetProductId()
+{
+ char *product_id;
+
+ return CopyStr("--");
+
+ // Product ID
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+
+ return product_id;
+}
+
+// Acquisition whether the OS is currently supported
+bool Win32IsSupportedOs()
+{
+ if (Win32GetOsType() == 0)
+ {
+ Win32Alert(
+ CEDAR_PRODUCT_STR " VPN doesn't support this Windows Operating System.\n"
+ CEDAR_PRODUCT_STR " VPN requires " SUPPORTED_WINDOWS_LIST ".\n\n"
+ "Please contact your system administrator.", NULL);
+ return false;
+ }
+
+ return true;
+}
+
+// Show an alert
+void Win32AlertW(wchar_t *msg, wchar_t *caption)
+{
+ char *s;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = L"Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR_W L" VPN Kernel";
+ }
+
+ s = GetCommandLineStr();
+
+ if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
+ {
+ // Hide during the uninstallation in Win9x service mode
+ MessageBoxW(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+
+ Free(s);
+}
+void Win32Alert(char *msg, char *caption)
+{
+ char *s;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR " VPN Kernel";
+ }
+
+ s = GetCommandLineStr();
+
+ if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
+ {
+ // Hide during the uninstallation in Win9x service mode
+ MessageBox(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+
+ Free(s);
+}
+void Win32DebugAlert(char *msg)
+{
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+
+ MessageBox(NULL, msg, "Debug", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+}
+
+// Get the OS information
+void Win32GetOsInfo(OS_INFO *info)
+{
+ UINT type = Win32GetOsType();
+ OSVERSIONINFOEX os;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ Win32GetVersionExInternal((LPOSVERSIONINFOA)&os);
+
+ info->OsType = Win32GetOsType();
+ info->OsServicePack = os.wServicePackMajor;
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ char *s;
+ char *keyname = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+ info->OsSystemName = CopyStr("Windows NT");
+ Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), ", %s", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ if (os.wServicePackMajor != 0)
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), ", Service Pack %u", os.wServicePackMajor);
+ StrCat(tmp, sizeof(tmp), str);
+ }
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "BuildLab"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), " (%s)", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ info->OsVersion = CopyStr(tmp);
+ info->KernelName = CopyStr("NTOS Kernel");
+ Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), " %s", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ info->KernelVersion = CopyStr(tmp);
+ }
+ else
+ {
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+ Format(tmp, sizeof(tmp), "Build %u %s", LOWORD(os.dwBuildNumber), os.szCSDVersion);
+ Trim(tmp);
+ info->OsVersion = CopyStr(tmp);
+ info->OsSystemName = CopyStr("Windows");
+ info->KernelName = CopyStr("Windows 9x Kernel");
+ info->KernelVersion = CopyStr(tmp);
+ }
+
+ info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
+ info->OsVendorName = CopyStr("Microsoft Corporation");
+}
+
+// GetVersionEx API (Ignore the tricky features that have been added to the Windows 8.2 or later)
+bool Win32GetVersionExInternal(void *info)
+{
+ OSVERSIONINFOA os;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (GetVersionExA(&os))
+ {
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ if ((os.dwMajorVersion == 6 && os.dwMinorVersion >= 2) ||
+ (os.dwMajorVersion == 7))
+ {
+ // Windows 8 later
+ return Win32GetVersionExInternalForWindows81orLater(info);
+ }
+ }
+ }
+
+ return GetVersionExA(info);
+}
+
+// GetVersionEx for Windows 8.1 and later
+bool Win32GetVersionExInternalForWindows81orLater(void *info)
+{
+ OSVERSIONINFOEXA *ex = (OSVERSIONINFOEXA *)info;
+ char *str;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA) &&
+ ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA))
+ {
+ return GetVersionExA(info);
+ }
+
+ if (GetVersionExA(info) == false)
+ {
+ return false;
+ }
+
+ str = MsRegReadStrEx2(REG_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+ "CurrentVersion",
+ false, true);
+
+ if (IsEmptyStr(str) == false)
+ {
+ // Is the version string formed as x.y?
+ TOKEN_LIST *t = ParseToken(str, ".");
+
+ if (t != NULL && t->NumTokens == 2)
+ {
+ UINT major = ToInt(t->Token[0]);
+ UINT minor = ToInt(t->Token[1]);
+
+ if (major >= 6)
+ {
+ // Version number acquisition success
+ ex->dwMajorVersion = major;
+ ex->dwMinorVersion = minor;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ Free(str);
+
+ return true;
+}
+
+// Acquisition whether it's a Windows NT
+bool Win32IsNt()
+{
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (GetVersionEx(&os) == FALSE)
+ {
+ // Failure?
+ return false;
+ }
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT
+ return true;
+ }
+
+ // 9x
+ return false;
+}
+
+// Get the OS type
+UINT Win32GetOsType()
+{
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (Win32GetVersionExInternal(&os) == FALSE)
+ {
+ // Failure?
+ return 0;
+ }
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Windows 9x system
+ if (os.dwMajorVersion == 4)
+ {
+ if (os.dwMinorVersion == 0)
+ {
+ return OSTYPE_WINDOWS_95;
+ }
+ else if (os.dwMinorVersion == 10)
+ {
+ return OSTYPE_WINDOWS_98;
+ }
+ else if (os.dwMinorVersion == 90)
+ {
+ return OSTYPE_WINDOWS_ME;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_UNKNOWN;
+ }
+ }
+ else if (os.dwMajorVersion >= 5)
+ {
+ return OSTYPE_WINDOWS_UNKNOWN;
+ }
+ }
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ UINT sp = Win32GetSpVer(os.szCSDVersion);
+ if (os.dwMajorVersion == 4)
+ {
+ if (sp < 6)
+ {
+ // SP6 or earlier
+ return 0;
+ }
+ }
+ if (os.dwMajorVersion < 4)
+ {
+ // NT 3.51 or earlier
+ return 0;
+ }
+ else
+ {
+ OSVERSIONINFOEX os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ Win32GetVersionExInternal((LPOSVERSIONINFOA)&os);
+
+ if (os.dwMajorVersion == 4)
+ {
+ // Windows NT 4.0
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ if ((os.wSuiteMask & VER_SUITE_TERMINAL) || (os.wSuiteMask & VER_SUITE_SINGLEUSERTS))
+ {
+ return OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER;
+ }
+ if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE;
+ }
+ if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_NT_4_BACKOFFICE;
+ }
+ if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_NT_4_SMS;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_NT_4_SERVER;
+ }
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_NT_4_WORKSTATION;
+ }
+ }
+ else if (os.dwMajorVersion == 5)
+ {
+ // Windows 2000, XP, Server 2003
+ if (os.dwMinorVersion == 0)
+ {
+ // Windows 2000
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ // Server
+ if (os.wSuiteMask & VER_SUITE_DATACENTER)
+ {
+ return OSTYPE_WINDOWS_2000_DATACENTER_SERVER;
+ }
+ else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_2000_SBS;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_2000_BACKOFFICE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_2000_ADVANCED_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_2000_SERVER;
+ }
+ }
+ else
+ {
+ // Client
+ return OSTYPE_WINDOWS_2000_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMinorVersion == 1)
+ {
+ // Windows XP
+ if (os.wSuiteMask & VER_SUITE_PERSONAL)
+ {
+ return OSTYPE_WINDOWS_XP_HOME;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_XP_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMinorVersion == 2)
+ {
+ // Windows Server 2003
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ // Server
+ if (os.wSuiteMask & VER_SUITE_DATACENTER)
+ {
+ return OSTYPE_WINDOWS_2003_DATACENTER;
+ }
+ else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_2003_SBS;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_2003_BACKOFFICE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_2003_ENTERPRISE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BLADE)
+ {
+ return OSTYPE_WINDOWS_2003_WEB;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_2003_STANDARD;
+ }
+ }
+ else
+ {
+ // Client (Unknown XP?)
+ return OSTYPE_WINDOWS_XP_PROFESSIONAL;
+ }
+ }
+ else
+ {
+ // Windows Longhorn
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ return OSTYPE_WINDOWS_LONGHORN_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
+ }
+ }
+ }
+ else
+ {
+ if (os.dwMajorVersion == 6 && os.dwMinorVersion == 0)
+ {
+ // Windows Vista, Server 2008
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ return OSTYPE_WINDOWS_LONGHORN_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 1)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 7
+ return OSTYPE_WINDOWS_7;
+ }
+ else
+ {
+ // Windows Server 2008 R2
+ return OSTYPE_WINDOWS_SERVER_2008_R2;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 2)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 8
+ return OSTYPE_WINDOWS_8;
+ }
+ else
+ {
+ // Windows Server 2012
+ return OSTYPE_WINDOWS_SERVER_8;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 3)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 8.1
+ return OSTYPE_WINDOWS_81;
+ }
+ else
+ {
+ // Windows Server 2012 R2
+ return OSTYPE_WINDOWS_SERVER_81;
+ }
+ }
+ else
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 9?
+ return OSTYPE_WINDOWS_9;
+ }
+ else
+ {
+ // Windows Server 9?
+ return OSTYPE_WINDOWS_SERVER_9;
+ }
+ }
+ }
+ }
+ }
+
+ // Can not be determined
+ return 0;
+}
+
+// Get the SP version from the string
+UINT Win32GetSpVer(char *str)
+{
+ UINT ret, i;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ t = ParseToken(str, NULL);
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ ret = ToInt(t->Token[i]);
+ if (ret != 0)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Kill the process
+bool Win32TerminateProcess(void *handle)
+{
+ HANDLE h;
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return false;
+ }
+
+ h = (HANDLE)handle;
+
+ TerminateProcess(h, 0);
+
+ return true;
+}
+
+// Close the process
+void Win32CloseProcess(void *handle)
+{
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ CloseHandle((HANDLE)handle);
+}
+
+// Check whether the specified process is alive
+bool Win32IsProcessAlive(void *handle)
+{
+ HANDLE h;
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return false;
+ }
+
+ h = (HANDLE)handle;
+
+ if (WaitForSingleObject(h, 0) == WAIT_OBJECT_0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Wait for the process termination
+bool Win32WaitProcess(void *h, UINT timeout)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = INFINITE;
+ }
+
+ if (WaitForSingleObject((HANDLE)h, timeout) == WAIT_TIMEOUT)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Run the process and wait for terminate it
+bool Win32RunAndWaitProcess(wchar_t *filename, wchar_t *arg, bool hide, bool disableWow, UINT timeout)
+{
+ UINT process_id = 0;
+ void *p = Win32RunEx3W(filename, arg, hide, &process_id, disableWow);
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return Win32WaitProcess(p, timeout);
+}
+
+// Run the process (return the handle)
+void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ return Win32RunEx2W(filename, arg, hide, NULL);
+}
+void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id)
+{
+ return Win32RunEx3W(filename, arg, hide, process_id, false);
+}
+void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ void *p;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ char *filename_a = CopyUniToStr(filename);
+ char *arg_a = CopyUniToStr(arg);
+ void *ret = Win32RunEx3(filename_a, arg_a, hide, process_id, disableWow);
+
+ Free(filename_a);
+ Free(arg_a);
+
+ return ret;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ if (disableWow)
+ {
+ p = MsDisableWow64FileSystemRedirection();
+ }
+
+ if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+ return NULL;
+ }
+
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+
+ if (process_id != NULL)
+ {
+ *process_id = ret.dwProcessId;
+ }
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+void *Win32RunEx(char *filename, char *arg, bool hide)
+{
+ return Win32RunEx2(filename, arg, hide, NULL);
+}
+void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id)
+{
+ return Win32RunEx3(filename, arg, hide, process_id, false);
+}
+void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow)
+{
+ STARTUPINFO info;
+ PROCESS_INFORMATION ret;
+ char cmdline[MAX_SIZE];
+ char name[MAX_PATH];
+ void *p = NULL;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(name, sizeof(name), filename);
+ Trim(name);
+
+ if (SearchStr(name, "\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "%s", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\"", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ Trim(cmdline);
+
+ if (disableWow)
+ {
+ p = MsDisableWow64FileSystemRedirection();
+ }
+
+ if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+ return NULL;
+ }
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+
+ if (process_id != NULL)
+ {
+ *process_id = ret.dwProcessId;
+ }
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+
+// Start the process
+bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *filename_a = CopyUniToStr(filename);
+ char *arg_a = CopyUniToStr(arg);
+ bool ret;
+
+ ret = Win32Run(filename_a, arg_a, hide, wait);
+
+ Free(filename_a);
+ Free(arg_a);
+
+ return ret;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return false;
+ }
+
+ if (wait)
+ {
+ WaitForSingleObject(ret.hProcess, INFINITE);
+ }
+
+ CloseHandle(ret.hThread);
+ CloseHandle(ret.hProcess);
+
+ return true;
+}
+bool Win32Run(char *filename, char *arg, bool hide, bool wait)
+{
+ STARTUPINFO info;
+ PROCESS_INFORMATION ret;
+ char cmdline[MAX_SIZE];
+ char name[MAX_PATH];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(name, sizeof(name), filename);
+ Trim(name);
+
+ if (SearchStr(name, "\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "%s", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\"", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ Trim(cmdline);
+
+ if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return false;
+ }
+
+ if (wait)
+ {
+ WaitForSingleObject(ret.hProcess, INFINITE);
+ }
+
+ CloseHandle(ret.hThread);
+ CloseHandle(ret.hProcess);
+
+ return true;
+}
+
+// Get the Thread ID
+UINT Win32ThreadId()
+{
+ return GetCurrentThreadId();
+}
+
+// Rename the file
+bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *old_name_a = CopyUniToStr(old_name);
+ char *new_name_a = CopyUniToStr(new_name);
+ bool ret = Win32FileRename(old_name_a, new_name_a);
+
+ Free(old_name_a);
+ Free(new_name_a);
+
+ return ret;
+ }
+
+ // Rename
+ if (MoveFileW(old_name, new_name) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool Win32FileRename(char *old_name, char *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ // Rename
+ if (MoveFile(old_name, new_name) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Getting the name of the directory where the EXE file is in
+void Win32GetExeDirW(wchar_t *name, UINT size)
+{
+ wchar_t exe_path[MAX_SIZE];
+ wchar_t exe_dir[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ Win32GetExeDir(name_a, sizeof(name_a));
+
+ StrToUni(name, size, name_a);
+
+ return;
+ }
+
+ // Get the EXE file name
+ GetModuleFileNameW(NULL, exe_path, sizeof(exe_path));
+
+ // Get the directory name
+ Win32GetDirFromPathW(exe_dir, sizeof(exe_dir), exe_path);
+
+ UniStrCpy(name, size, exe_dir);
+}
+void Win32GetExeDir(char *name, UINT size)
+{
+ char exe_path[MAX_SIZE];
+ char exe_dir[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ // Get the EXE file name
+ GetModuleFileName(NULL, exe_path, sizeof(exe_path));
+
+ // Get the directory name
+ Win32GetDirFromPath(exe_dir, sizeof(exe_dir), exe_path);
+
+ StrCpy(name, size, exe_dir);
+}
+
+// Remove the '\' at the end
+void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t str[MAX_SIZE];
+ int i;
+ if (src)
+ {
+ UniStrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ UniStrCpy(str, sizeof(str), dst);
+ }
+ i = UniStrLen(str);
+ if (str[i - 1] == L'\\')
+ {
+ str[i - 1] = 0;
+ }
+ UniStrCpy(dst, size, str);
+}
+void Win32NukuEn(char *dst, UINT size, char *src)
+{
+ char str[MAX_SIZE];
+ int i;
+ if (src)
+ {
+ StrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ StrCpy(str, sizeof(str), dst);
+ }
+ i = StrLen(str);
+ if (str[i - 1] == '\\')
+ {
+ str[i - 1] = 0;
+ }
+ StrCpy(dst, size, str);
+}
+
+// Get the directory name from path
+void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t str[MAX_SIZE];
+ int i,len;
+ wchar_t c;
+ wchar_t tmp[MAX_SIZE];
+ int wp;
+ if (src)
+ {
+ UniStrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ UniStrCpy(str, sizeof(str), dst);
+ }
+ Win32NukuEnW(str, sizeof(str), NULL);
+ wp = 0;
+ len = UniStrLen(str);
+ dst[0] = 0;
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+ switch (c)
+ {
+ case L'\\':
+ tmp[wp] = 0;
+ wp = 0;
+ UniStrCat(dst, size, tmp);
+ UniStrCat(dst, size, L"\\");
+ break;
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+ Win32NukuEnW(dst, size, NULL);
+}
+void Win32GetDirFromPath(char *dst, UINT size, char *src)
+{
+ char str[MAX_SIZE];
+ int i,len;
+ char c;
+ char tmp[MAX_SIZE];
+ int wp;
+ if (src)
+ {
+ StrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ StrCpy(str, sizeof(str), dst);
+ }
+ Win32NukuEn(str, sizeof(str), NULL);
+ wp = 0;
+ len = StrLen(str);
+ dst[0] = 0;
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+ switch (c)
+ {
+ case '\\':
+ tmp[wp] = 0;
+ wp = 0;
+ StrCat(dst, size, tmp);
+ StrCat(dst, size, "\\");
+ break;
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+ Win32NukuEn(dst, size, NULL);
+}
+
+// Delete the directory
+bool Win32DeleteDirW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *name_a = CopyUniToStr(name);
+ bool ret = Win32DeleteDir(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (RemoveDirectoryW(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+bool Win32DeleteDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (RemoveDirectory(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Create a directory
+bool Win32MakeDirW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *name_a = CopyUniToStr(name);
+ bool ret = Win32MakeDir(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (CreateDirectoryW(name, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool Win32MakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (CreateDirectory(name, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Delete the file
+bool Win32FileDeleteW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileDelete(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (DeleteFileW(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+bool Win32FileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (DeleteFile(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Seek in the file
+bool Win32FileSeek(void *pData, UINT mode, int offset)
+{
+ WIN32IO *p;
+ DWORD ret;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return false;
+ }
+ if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ ret = SetFilePointer(p->hFile, (LONG)offset, NULL, mode);
+ if (ret == INVALID_SET_FILE_POINTER || ret == ERROR_NEGATIVE_SEEK)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Get the file size
+UINT64 Win32FileSize(void *pData)
+{
+ WIN32IO *p;
+ UINT64 ret;
+ DWORD tmp;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+
+ p = (WIN32IO *)pData;
+ tmp = 0;
+ ret = GetFileSize(p->hFile, &tmp);
+ if (ret == (DWORD)-1)
+ {
+ return 0;
+ }
+
+ if (tmp != 0)
+ {
+ ret += (UINT64)tmp * 4294967296ULL;
+ }
+
+ return ret;
+}
+
+// Write to the file
+bool Win32FileWrite(void *pData, void *buf, UINT size)
+{
+ WIN32IO *p;
+ DWORD write_size;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ if (WriteFile(p->hFile, buf, size, &write_size, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ if (write_size != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read from a file
+bool Win32FileRead(void *pData, void *buf, UINT size)
+{
+ WIN32IO *p;
+ DWORD read_size;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ if (ReadFile(p->hFile, buf, size, &read_size, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ if (read_size != size)
+ {
+ return false;
+ }
+
+ return true;;
+}
+
+// Close the file
+void Win32FileClose(void *pData, bool no_flush)
+{
+ WIN32IO *p;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32IO *)pData;
+ if (p->WriteMode && no_flush == false)
+ {
+ FlushFileBuffers(p->hFile);
+ }
+ CloseHandle(p->hFile);
+ p->hFile = NULL;
+
+ // Memory release
+ Win32MemoryFree(p);
+}
+
+// Get the date of the file
+bool Win32FileGetDate(void *pData, UINT64 *created_time, UINT64 *updated_time, UINT64 *accessed_date)
+{
+ WIN32IO *p;
+ BY_HANDLE_FILE_INFORMATION info;
+ SYSTEMTIME st_create, st_update, st_access;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+
+ Zero(&info, sizeof(info));
+
+ if (GetFileInformationByHandle(p->hFile, &info) == false)
+ {
+ return false;
+ }
+
+ Zero(&st_create, sizeof(st_create));
+ Zero(&st_update, sizeof(st_update));
+ Zero(&st_access, sizeof(st_access));
+
+ FileTimeToSystemTime(&info.ftCreationTime, &st_create);
+ FileTimeToSystemTime(&info.ftLastWriteTime, &st_update);
+ FileTimeToSystemTime(&info.ftLastAccessTime, &st_access);
+
+ if (created_time != NULL)
+ {
+ *created_time = SystemToUINT64(&st_create);
+ }
+
+ if (updated_time != NULL)
+ {
+ *updated_time = SystemToUINT64(&st_update);
+ }
+
+ if (accessed_date != NULL)
+ {
+ *accessed_date = SystemToUINT64(&st_access);
+ }
+
+ return true;
+}
+
+// Set the date of the file
+bool Win32FileSetDate(void *pData, UINT64 created_time, UINT64 updated_time)
+{
+ WIN32IO *p;
+ SYSTEMTIME st_created_time, st_updated_time;
+ FILETIME ft_created_time, ft_updated_time;
+ FILETIME *p_created_time = NULL, *p_updated_time = NULL;
+ // Validate arguments
+ if (pData == NULL || (created_time == 0 && updated_time == 0))
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+
+ Zero(&st_created_time, sizeof(st_created_time));
+ Zero(&st_updated_time, sizeof(st_updated_time));
+
+ if (created_time != 0)
+ {
+ UINT64ToSystem(&st_created_time, created_time);
+
+ SystemTimeToFileTime(&st_created_time, &ft_created_time);
+
+ p_created_time = &ft_created_time;
+ }
+
+ if (updated_time != 0)
+ {
+ UINT64ToSystem(&st_updated_time, updated_time);
+
+ SystemTimeToFileTime(&st_updated_time, &ft_updated_time);
+
+ p_updated_time = &ft_updated_time;
+ }
+
+ return SetFileTime(p->hFile, p_created_time, NULL, p_updated_time);
+}
+
+// Flush to the file
+void Win32FileFlush(void *pData)
+{
+ WIN32IO *p;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32IO *)pData;
+ if (p->WriteMode)
+ {
+ FlushFileBuffers(p->hFile);
+ }
+}
+
+// Open the file
+void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ WIN32IO *p;
+ HANDLE h;
+ DWORD lock_mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ void *ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileOpen(name_a, write_mode, read_lock);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (write_mode)
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ else
+ {
+ if (read_lock == false)
+ {
+ lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ else
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ }
+
+ // Open the file
+ h = CreateFileW(name,
+ (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
+ lock_mode,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ UINT ret = GetLastError();
+ // Failure
+ return NULL;
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = write_mode;
+
+ return (void *)p;
+}
+void *Win32FileOpen(char *name, bool write_mode, bool read_lock)
+{
+ WIN32IO *p;
+ HANDLE h;
+ DWORD lock_mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (write_mode)
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ else
+ {
+ if (read_lock == false)
+ {
+ lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ else
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ }
+
+ // Open the file
+ h = CreateFile(name,
+ (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
+ lock_mode,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ UINT ret = GetLastError();
+ // Failure
+ return NULL;
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = write_mode;
+
+ return (void *)p;
+}
+
+// Create a file
+void *Win32FileCreateW(wchar_t *name)
+{
+ WIN32IO *p;
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ void *ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileCreate(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ // Create a file
+ h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = true;
+
+ return (void *)p;
+}
+void *Win32FileCreate(char *name)
+{
+ WIN32IO *p;
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a file
+ h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = true;
+
+ return (void *)p;
+}
+
+#define SIZE_OF_CALLSTACK_SYM 10000
+#define CALLSTACK_DEPTH 12
+
+// Get the call stack
+CALLSTACK_DATA *Win32GetCallStack()
+{
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ DWORD current_eip32 = 0, current_esp32 = 0, current_ebp32 = 0;
+ UINT64 current_eip = 0, current_esp = 0, current_ebp = 0;
+ STACKFRAME64 sf;
+ CALLSTACK_DATA *cs = NULL, *s;
+
+#ifdef CPU_64
+ CONTEXT context;
+#endif // CPU_64
+
+ bool ret;
+ UINT depth = 0;
+
+#ifndef CPU_64
+ // Register acquisition (32 bit)
+ __asm
+ {
+ mov current_esp32, esp
+ mov current_ebp32, ebp
+ };
+
+ current_eip32 = (DWORD)Win32GetCallStack;
+
+ current_eip = (UINT64)current_eip32;
+ current_esp = (UINT64)current_esp32;
+ current_ebp = (UINT64)current_ebp32;
+#else // CPU_64
+ // Register acquisition (64 bit)
+ Zero(&context, sizeof(context));
+ context.ContextFlags = CONTEXT_FULL;
+ RtlCaptureContext(&context);
+#endif // CPU_64
+
+ Zero(&sf, sizeof(sf));
+
+#ifndef CPU_64
+ sf.AddrPC.Offset = current_eip;
+ sf.AddrStack.Offset = current_esp;
+ sf.AddrFrame.Offset = current_ebp;
+#else // CPU_64
+ sf.AddrPC.Offset = context.Rip;
+ sf.AddrStack.Offset = context.Rsp;
+ sf.AddrFrame.Offset = context.Rsp;
+#endif // CPU_64
+
+ sf.AddrPC.Mode = AddrModeFlat;
+ sf.AddrStack.Mode = AddrModeFlat;
+ sf.AddrFrame.Mode = AddrModeFlat;
+
+ while (true)
+ {
+ DWORD type = IMAGE_FILE_MACHINE_I386;
+
+#ifdef CPU_64
+ type = IMAGE_FILE_MACHINE_AMD64;
+#endif // CPU_64
+
+ if ((depth++) >= CALLSTACK_DEPTH)
+ {
+ break;
+ }
+
+#ifndef CPU_64
+ ret = StackWalk64(type,
+ hCurrentProcessHandle,
+ GetCurrentThread(),
+ &sf,
+ NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
+#else // CPU_64
+ ret = StackWalk64(type,
+ hCurrentProcessHandle,
+ GetCurrentThread(),
+ &sf,
+ &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
+#endif // CPU_64
+ if (ret == false || sf.AddrFrame.Offset == 0)
+ {
+ break;
+ }
+
+ if (cs == NULL)
+ {
+ cs = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
+ s = cs;
+ }
+ else
+ {
+ s->next = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
+ s = s->next;
+ }
+ s->symbol_cache = false;
+ s->next = NULL;
+ s->offset = sf.AddrPC.Offset;
+ s->disp = 0;
+ s->name = NULL;
+ s->line = 0;
+ s->filename[0] = 0;
+ }
+
+ return cs;
+#else // WIN32_NO_DEBUG_HELP_DLL
+ return NULL;
+#endif // WIN32_NO_DEBUG_HELP_DLL
+}
+
+// Get the symbol information from the call stack
+bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+#ifdef WIN32_NO_DEBUG_HELP_DLL
+ return false;
+#else // WIN32_NO_DEBUG_HELP_DLL
+ UINT64 disp;
+ UINT disp32, len;
+ IMAGEHLP_SYMBOL64 *sym;
+ IMAGEHLP_LINE64 line;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->symbol_cache)
+ {
+ return true;
+ }
+
+ sym = OSMemoryAlloc(SIZE_OF_CALLSTACK_SYM);
+ sym->SizeOfStruct = SIZE_OF_CALLSTACK_SYM;
+ sym->MaxNameLength = SIZE_OF_CALLSTACK_SYM - sizeof(IMAGEHLP_SYMBOL64);
+
+ if (SymGetSymFromAddr64(hCurrentProcessHandle, s->offset, &disp, sym))
+ {
+ s->disp = disp;
+ s->name = OSMemoryAlloc((UINT)strlen(sym->Name) + 1);
+ lstrcpy(s->name, sym->Name);
+ }
+ else
+ {
+ s->disp = 0;
+ s->name = NULL;
+ }
+
+ Zero(&line, sizeof(line));
+ line.SizeOfStruct = sizeof(line);
+ if (SymGetLineFromAddr64(hCurrentProcessHandle, s->offset, &disp32, &line))
+ {
+ disp = (UINT64)disp32;
+ s->line = line.LineNumber;
+ lstrcpy(s->filename, line.FileName);
+ Win32GetDirFromPath(tmp, sizeof(tmp), s->filename);
+ len = lstrlen(tmp);
+ lstrcpy(tmp, &s->filename[len + 1]);
+ lstrcpy(s->filename, tmp);
+ }
+ else
+ {
+ s->line = 0;
+ s->filename[0] = 0;
+ }
+
+ OSMemoryFree(sym);
+
+ s->symbol_cache = true;
+
+ return true;
+#endif // WIN32_NO_DEBUG_HELP_DLL
+}
+
+// Default Win32 thread
+DWORD CALLBACK Win32DefaultThreadProc(void *param)
+{
+ WIN32THREADSTARTUPINFO *info = (WIN32THREADSTARTUPINFO *)param;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return 0;
+ }
+
+ Win32InitNewThread();
+
+ CoInitialize(NULL);
+
+ // Call the thread function
+ info->thread_proc(info->thread, info->param);
+
+ // Release the reference
+ ReleaseThread(info->thread);
+
+ Win32MemoryFree(info);
+
+ FreeOpenSSLThreadState();
+
+ CoUninitialize();
+
+ _endthreadex(0);
+ return 0;
+}
+
+// Wait for the termination of the thread
+bool Win32WaitThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ w = (WIN32THREAD *)t->pData;
+ if (w == NULL)
+ {
+ return false;
+ }
+
+ // Wait for the thread event
+ if (WaitForSingleObject(w->hThread, INFINITE) == WAIT_OBJECT_0)
+ {
+ // The thread was signaled
+ return true;
+ }
+
+ // Wait failure (time-out, etc.)
+ return false;
+}
+
+// Release the thread
+void Win32FreeThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+ w = (WIN32THREAD *)t->pData;
+ if (w == NULL)
+ {
+ return;
+ }
+
+ // Close the handle
+ CloseHandle(w->hThread);
+
+ // Memory release
+ Win32MemoryFree(t->pData);
+ t->pData = NULL;
+}
+
+// Thread initialization
+bool Win32InitThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ HANDLE hThread;
+ DWORD thread_id;
+ WIN32THREADSTARTUPINFO *info;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ if (t->thread_proc == NULL)
+ {
+ return false;
+ }
+
+ // Thread data generation
+ w = Win32MemoryAlloc(sizeof(WIN32THREAD));
+
+ // Creating the startup information
+ info = Win32MemoryAlloc(sizeof(WIN32THREADSTARTUPINFO));
+ info->param = t->param;
+ info->thread_proc = t->thread_proc;
+ info->thread = t;
+ AddRef(t->ref);
+
+ // Thread creation
+ t->pData = w;
+ hThread = (HANDLE)_beginthreadex(NULL, 0, Win32DefaultThreadProc, info, 0, &thread_id);
+ if (hThread == NULL)
+ {
+ // Thread creation failure
+ t->pData = NULL;
+ Release(t->ref);
+ Win32MemoryFree(info);
+ Win32MemoryFree(w);
+ return false;
+ }
+
+ // Save the thread information
+ w->hThread = hThread;
+ w->thread_id = thread_id;
+
+ return true;
+}
+
+// Initialize the library for Win32
+void Win32Init()
+{
+ INITCOMMONCONTROLSEX c;
+ OSVERSIONINFO os;
+
+ // Get whether it's in a Windows NT
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT system
+ win32_is_nt = true;
+ }
+ else
+ {
+ // 9x system
+ win32_is_nt = false;
+ }
+
+ // Open the stdout
+ if (hstdout == INVALID_HANDLE_VALUE)
+ {
+ hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+
+ // Open the stdin
+ if (hstdin == INVALID_HANDLE_VALUE)
+ {
+ hstdin = GetStdHandle(STD_INPUT_HANDLE);
+ }
+
+ Win32InitNewThread();
+
+ CoInitialize(NULL);
+
+ InitializeCriticalSection(&fasttick_lock);
+
+#ifdef WIN32_USE_HEAP_API_FOR_MEMORY
+ use_heap_api = true;
+#else // WIN32_USE_HEAP_API_FOR_MEMORY
+ use_heap_api = false;
+#endif // WIN32_USE_HEAP_API_FOR_MEMORY
+
+ if (MayaquaIsDotNetMode())
+ {
+ // If an heap API is called from .NET API, it might crush
+ use_heap_api = false;
+ }
+
+ if (IsNt() == false)
+ {
+ // Do not use the heap related API in Win9x
+ use_heap_api = false;
+ }
+
+ if (use_heap_api)
+ {
+ heap_handle = HeapCreate(0, 0, 0);
+ }
+
+ // Get the process pseudo handle
+ hCurrentProcessHandle = GetCurrentProcess();
+
+ // Initialization of the current directory
+ // Win32InitCurrentDir(); /* Don't do */
+
+ // Initialization of the symbol handler
+ if (IsMemCheck())
+ {
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ SymInitialize(hCurrentProcessHandle, NULL, TRUE);
+#endif // WIN32_NO_DEBUG_HELP_DLL
+ }
+
+ // Initialization of the Common Control
+ Zero(&c, sizeof(INITCOMMONCONTROLSEX));
+ c.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ c.dwICC = ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES |
+ ICC_DATE_CLASSES | ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES |
+ ICC_LISTVIEW_CLASSES | ICC_NATIVEFNTCTL_CLASS |
+ ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS |
+ ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES |
+ ICC_WIN95_CLASSES;
+ InitCommonControlsEx(&c);
+}
+
+// Release the library for Win32
+void Win32Free()
+{
+ // Close the symbol handler
+ if (IsMemCheck())
+ {
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ SymCleanup(hCurrentProcessHandle);
+#endif // WIN32_NO_DEBUG_HELP_DLL
+ }
+
+ if (use_heap_api)
+ {
+ HeapDestroy(heap_handle);
+ heap_handle = NULL;
+ }
+
+ CoUninitialize();
+
+ DeleteCriticalSection(&fasttick_lock);
+}
+
+// Memory allocation
+void *Win32MemoryAlloc(UINT size)
+{
+ if (use_heap_api)
+ {
+ return HeapAlloc(heap_handle, 0, size);
+ }
+ else
+ {
+ return malloc(size);
+ }
+}
+
+// Memory reallocation
+void *Win32MemoryReAlloc(void *addr, UINT size)
+{
+ if (use_heap_api)
+ {
+ return HeapReAlloc(heap_handle, 0, addr, size);
+ }
+ else
+ {
+ return realloc(addr, size);
+ }
+}
+
+// Memory allocation
+void Win32MemoryFree(void *addr)
+{
+ if (use_heap_api)
+ {
+ HeapFree(heap_handle, 0, addr);
+ }
+ else
+ {
+ free(addr);
+ }
+}
+
+// Get the system timer
+UINT Win32GetTick()
+{
+ return (UINT)timeGetTime();
+}
+
+// Get the System Time
+void Win32GetSystemTime(SYSTEMTIME *system_time)
+{
+ // Get the System Time
+ GetSystemTime(system_time);
+}
+
+// Increment of 32bit integer
+void Win32Inc32(UINT *value)
+{
+ InterlockedIncrement(value);
+}
+
+// Decrement of 32bit integer
+void Win32Dec32(UINT *value)
+{
+ InterlockedDecrement(value);
+}
+
+// Sleep the thread
+void Win32Sleep(UINT time)
+{
+ Sleep(time);
+}
+
+// Creating a lock
+LOCK *Win32NewLock()
+{
+ // Memory allocation
+ LOCK *lock = Win32MemoryAlloc(sizeof(LOCK));
+
+ // Allocate a critical section
+ CRITICAL_SECTION *critical_section = Win32MemoryAlloc(sizeof(CRITICAL_SECTION));
+
+ if (lock == NULL || critical_section == NULL)
+ {
+ Win32MemoryFree(lock);
+ Win32MemoryFree(critical_section);
+ return NULL;
+ }
+
+ // Initialize the critical section
+ InitializeCriticalSection(critical_section);
+
+ lock->pData = (void *)critical_section;
+ lock->Ready = true;
+
+ return lock;
+}
+
+// Lock
+bool Win32Lock(LOCK *lock)
+{
+ CRITICAL_SECTION *critical_section;
+ if (lock->Ready == false)
+ {
+ // State is invalid
+ return false;
+ }
+
+ // Enter the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ EnterCriticalSection(critical_section);
+
+ return true;
+}
+
+// Unlock
+void Win32Unlock(LOCK *lock)
+{
+ Win32UnlockEx(lock, false);
+}
+void Win32UnlockEx(LOCK *lock, bool inner)
+{
+ CRITICAL_SECTION *critical_section;
+ if (lock->Ready == false && inner == false)
+ {
+ // State is invalid
+ return;
+ }
+
+ // Leave the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ LeaveCriticalSection(critical_section);
+}
+
+// Delete the lock
+void Win32DeleteLock(LOCK *lock)
+{
+ CRITICAL_SECTION *critical_section;
+ // Reset the Ready flag safely
+ Win32Lock(lock);
+ lock->Ready = false;
+ Win32UnlockEx(lock, true);
+
+ // Delete the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ DeleteCriticalSection(critical_section);
+
+ // Memory release
+ Win32MemoryFree(critical_section);
+ Win32MemoryFree(lock);
+}
+
+// Initialization of the event
+void Win32InitEvent(EVENT *event)
+{
+ // Creating an auto-reset event
+ HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ event->pData = hEvent;
+}
+
+// Set the event
+void Win32SetEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ SetEvent(hEvent);
+}
+
+// Reset the event
+void Win32ResetEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ ResetEvent(hEvent);
+}
+
+// Wait for the event
+bool Win32WaitEvent(EVENT *event, UINT timeout)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ UINT ret;
+ if (hEvent == NULL)
+ {
+ return false;
+ }
+
+ // Wait for an object
+ ret = WaitForSingleObject(hEvent, timeout);
+ if (ret == WAIT_TIMEOUT)
+ {
+ // Time-out
+ return false;
+ }
+ else
+ {
+ // Signaled state
+ return true;
+ }
+}
+
+// Release of the event
+void Win32FreeEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(hEvent);
+}
+
+// Fast getting 64 bit Tick functions for only Win32
+UINT64 Win32FastTick64()
+{
+ static UINT last_tick = 0;
+ static UINT counter = 0;
+ UINT64 ret;
+ UINT tick;
+
+ EnterCriticalSection(&fasttick_lock);
+
+ // Get the current tick value
+ tick = Win32GetTick();
+
+ if (last_tick > tick)
+ {
+ // When the previously acquired tick value is larger than acquired this time,
+ // it can be considered that the counter have gone one around
+
+ counter++;
+ }
+
+ last_tick = tick;
+
+ ret = (UINT64)tick + (UINT64)counter * 4294967296ULL;
+
+ LeaveCriticalSection(&fasttick_lock);
+
+ if (start_tick == 0)
+ {
+ start_tick = ret;
+ ret = 0;
+ }
+ else
+ {
+ ret -= start_tick;
+ }
+
+ return ret + 1;
+}
+
+// Read a string from the console
+bool Win32InputW(wchar_t *str, UINT size)
+{
+ bool ret = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ size = 0x7fffffff;
+ }
+
+ if (str == NULL || size <= sizeof(wchar_t))
+ {
+ if (str != NULL)
+ {
+ Zero(str, size);
+ }
+
+ return Win32InputFromFileW(NULL, 0);
+ }
+
+ if (IsNt())
+ {
+ DWORD read_size = 0;
+
+ if (ReadConsoleW(hstdin, str, (size - sizeof(wchar_t)), &read_size, NULL))
+ {
+ str[read_size] = 0;
+
+ UniTrimCrlf(str);
+
+ ret = true;
+ }
+ else
+ {
+ ret = Win32InputFromFileW(str, size);
+ }
+ }
+ else
+ {
+ DWORD read_size = 0;
+ UINT a_size = size / sizeof(wchar_t) + 16;
+ char *a;
+
+ a = ZeroMalloc(a_size);
+
+ if (ReadConsoleA(hstdin, a, a_size - 1, &read_size, NULL))
+ {
+ a[read_size] = 0;
+
+ StrToUni(str, size, a);
+
+ UniTrimCrlf(str);
+
+ ret = true;
+ }
+ else
+ {
+ ret = Win32InputFromFileW(str, size);
+ }
+
+ Free(a);
+ }
+
+ return ret;
+}
+// Get a line from standard input
+bool Win32InputFromFileW(wchar_t *str, UINT size)
+{
+ char *a;
+ if (str == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ Win32InputFromFileW(tmp, sizeof(tmp));
+ return false;
+ }
+
+ a = Win32InputFromFileLineA();
+ if (a == NULL)
+ {
+ UniStrCpy(str, size, L"");
+ return false;
+ }
+
+ UtfToUni(str, size, a);
+
+ UniTrimCrlf(str);
+
+ Free(a);
+
+ return true;
+}
+char *Win32InputFromFileLineA()
+{
+ BUF *b = NewBuf();
+ char zero = 0;
+ char *ret = NULL;
+ bool ok = true;
+
+ while (true)
+ {
+ char c;
+ UINT read_size = 0;
+
+ if (ReadFile(hstdin, &c, 1, &read_size, NULL) == false)
+ {
+ ok = false;
+ break;
+ }
+ if (read_size != 1)
+ {
+ ok = false;
+ break;
+ }
+
+ WriteBuf(b, &c, 1);
+
+ if (c == 10)
+ {
+ break;
+ }
+ }
+
+ WriteBuf(b, &zero, 1);
+
+ if (ok)
+ {
+ ret = CopyStr(b->Buf);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Print the string to the console
+void Win32PrintW(wchar_t *str)
+{
+ DWORD write_size = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ if (IsNt())
+ {
+ if (WriteConsoleW(hstdout, str, UniStrLen(str), &write_size, NULL) == false)
+ {
+ Win32PrintToFileW(str);
+ }
+ }
+ else
+ {
+ char *ansi_str = CopyUniToStr(str);
+
+ if (WriteConsoleA(hstdout, ansi_str, StrLen(ansi_str), &write_size, NULL) == false)
+ {
+ Win32PrintToFileW(str);
+ }
+
+ Free(ansi_str);
+ }
+}
+void Win32PrintToFileW(wchar_t *str)
+{
+ char *utf;
+ DWORD size = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ utf = CopyUniToUtf(str);
+
+ WriteFile(hstdout, utf, StrLen(utf), &size, NULL);
+
+ Free(utf);
+}
+
+
+#endif // WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Win32.h b/src/Mayaqua/Win32.h
new file mode 100644
index 00000000..8a0f9617
--- /dev/null
+++ b/src/Mayaqua/Win32.h
@@ -0,0 +1,204 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32.h
+// Header of Win32.c
+
+#ifdef OS_WIN32
+
+#ifndef WIN32_H
+#define WIN32_H
+
+// Function prototype
+OS_DISPATCH_TABLE *Win32GetDispatchTable();
+
+void Win32Init();
+void Win32Free();
+void *Win32MemoryAlloc(UINT size);
+void *Win32MemoryReAlloc(void *addr, UINT size);
+void Win32MemoryFree(void *addr);
+UINT Win32GetTick();
+void Win32GetSystemTime(SYSTEMTIME *system_time);
+void Win32Inc32(UINT *value);
+void Win32Dec32(UINT *value);
+void Win32Sleep(UINT time);
+LOCK *Win32NewLock();
+bool Win32Lock(LOCK *lock);
+void Win32Unlock(LOCK *lock);
+void Win32DeleteLock(LOCK *lock);
+void Win32InitEvent(EVENT *event);
+void Win32SetEvent(EVENT *event);
+void Win32ResetEvent(EVENT *event);
+bool Win32WaitEvent(EVENT *event, UINT timeout);
+void Win32FreeEvent(EVENT *event);
+bool Win32WaitThread(THREAD *t);
+void Win32FreeThread(THREAD *t);
+bool Win32InitThread(THREAD *t);
+UINT Win32ThreadId();
+void *Win32FileOpen(char *name, bool write_mode, bool read_lock);
+void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *Win32FileCreate(char *name);
+void *Win32FileCreateW(wchar_t *name);
+bool Win32FileWrite(void *pData, void *buf, UINT size);
+bool Win32FileRead(void *pData, void *buf, UINT size);
+bool Win32FileSetDate(void *pData, UINT64 created_time, UINT64 updated_time);
+bool Win32FileGetDate(void *pData, UINT64 *created_time, UINT64 *updated_time, UINT64 *accessed_date);
+void Win32FileClose(void *pData, bool no_flush);
+void Win32FileFlush(void *pData);
+UINT64 Win32FileSize(void *pData);
+bool Win32FileSeek(void *pData, UINT mode, int offset);
+bool Win32FileDelete(char *name);
+bool Win32FileDeleteW(wchar_t *name);
+bool Win32MakeDir(char *name);
+bool Win32MakeDirW(wchar_t *name);
+bool Win32DeleteDir(char *name);
+bool Win32DeleteDirW(wchar_t *name);
+CALLSTACK_DATA *Win32GetCallStack();
+bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool Win32FileRename(char *old_name, char *new_name);
+bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name);
+bool Win32Run(char *filename, char *arg, bool hide, bool wait);
+bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+void *Win32RunEx(char *filename, char *arg, bool hide);
+void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id);
+void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow);
+void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide);
+void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id);
+void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow);
+bool Win32WaitProcess(void *h, UINT timeout);
+bool Win32RunAndWaitProcess(wchar_t *filename, wchar_t *arg, bool hide, bool disableWow, UINT timeout);
+bool Win32IsProcessAlive(void *handle);
+bool Win32TerminateProcess(void *handle);
+void Win32CloseProcess(void *handle);
+bool Win32IsSupportedOs();
+void Win32GetOsInfo(OS_INFO *info);
+void Win32Alert(char *msg, char *caption);
+void Win32AlertW(wchar_t *msg, wchar_t *caption);
+void Win32DebugAlert(char *msg);
+char* Win32GetProductId();
+void Win32SetHighPriority();
+void Win32RestorePriority();
+void *Win32NewSingleInstance(char *instance_name);
+void Win32FreeSingleInstance(void *data);
+void Win32GetMemInfo(MEMINFO *info);
+void Win32Yield();
+
+void Win32UnlockEx(LOCK *lock, bool inner);
+UINT Win32GetOsType();
+UINT Win32GetSpVer(char *str);
+UINT Win32GetOsSpVer();
+void Win32NukuEn(char *dst, UINT size, char *src);
+void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src);
+void Win32GetDirFromPath(char *dst, UINT size, char *src);
+void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src);
+void Win32GetExeDir(char *name, UINT size);
+void Win32GetExeDirW(wchar_t *name, UINT size);
+void Win32GetCurrentDir(char *dir, UINT size);
+void Win32GetCurrentDirW(wchar_t *dir, UINT size);
+void Win32GetExeName(char *name, UINT size);
+void Win32GetExeNameW(wchar_t *name, UINT size);
+DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare);
+bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool Win32SetFolderCompress(char *path, bool compressed);
+bool Win32SetFolderCompressW(wchar_t *path, bool compressed);
+UINT64 Win32FastTick64();
+void Win32InitNewThread();
+bool Win32IsNt();
+bool Win32InputW(wchar_t *str, UINT size);
+bool Win32InputFromFileW(wchar_t *str, UINT size);
+char *Win32InputFromFileLineA();
+void Win32PrintW(wchar_t *str);
+void Win32PrintToFileW(wchar_t *str);
+bool Win32GetVersionExInternal(void *info);
+bool Win32GetVersionExInternalForWindows81orLater(void *info);
+
+void Win32SetThreadName(UINT thread_id, char *name);
+
+#endif // WIN32_H
+
+#endif // OS_WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/cryptoki.h b/src/Mayaqua/cryptoki.h
new file mode 100644
index 00000000..7d85ca80
--- /dev/null
+++ b/src/Mayaqua/cryptoki.h
@@ -0,0 +1,66 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef ___CRYPTOKI_H_INC___
+#define ___CRYPTOKI_H_INC___
+
+#pragma pack(push, cryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do
+ * not define it in applications.
+ */
+#ifdef CRYPTOKI_EXPORTS
+/* Specified that the function is an exported DLL entry point. */
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+#include "pkcs11.h"
+
+#pragma pack(pop, cryptoki)
+
+#endif /* ___CRYPTOKI_H_INC___ */
diff --git a/src/Mayaqua/intelaes/iaesni.h b/src/Mayaqua/intelaes/iaesni.h
new file mode 100644
index 00000000..b71a223a
--- /dev/null
+++ b/src/Mayaqua/intelaes/iaesni.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+
+#ifndef _IAESNI_H__
+#define _IAESNI_H__
+
+#include <stdlib.h>
+
+#define AES_INSTRCTIONS_CPUID_BIT (1<<25)
+
+//indicates input param
+#define _AES_IN
+
+//indicates output param
+#define _AES_OUT
+
+//indicates input/output param - based on context
+#define _AES_INOUT
+
+//typedef unsigned char UCHAR;
+
+
+/*#ifndef bool
+#define bool BOOL
+#endif*/
+//test if the processor actually supports the above functions
+//executing one the functions below without processor support will cause UD fault
+//bool check_for_aes_instructions(void);
+#if (__cplusplus)
+extern "C" {
+#endif
+int check_for_aes_instructions(void);
+
+#define ROUND_KEYS_UNALIGNED_TESTING
+
+#ifdef __linux__
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+ UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey + 4; \
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+ UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey; \
+
+#endif
+
+#else // if not __linux__
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+ __declspec(align(16)) UCHAR _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey + 4; \
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+ __declspec(align(16)) UCHAR _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey; \
+
+
+#endif
+
+#endif
+
+
+
+// encryption functions
+// plainText is pointer to input stream
+// cipherText is pointer to buffer to be filled with encrypted (cipher text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that encryption is done of full 16 byte blocks
+void intel_AES_enc128(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc192(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc256(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+
+void intel_AES_enc128_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc192_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc256_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+
+// encryption functions
+// cipherText is pointer to encrypted stream
+// plainText is pointer to buffer to be filled with original (plain text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that decryption is done of full 16 byte blocks
+void intel_AES_dec128(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec192(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec256(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+void intel_AES_dec128_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec192_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec256_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+void intel_AES_encdec128_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec192_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec256_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+
+
+#if (__cplusplus)
+}
+#endif
+
+
+#endif
+
+
+
diff --git a/src/Mayaqua/pkcs11.h b/src/Mayaqua/pkcs11.h
new file mode 100644
index 00000000..5afbb7ac
--- /dev/null
+++ b/src/Mayaqua/pkcs11.h
@@ -0,0 +1,299 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/pkcs11f.h b/src/Mayaqua/pkcs11f.h
new file mode 100644
index 00000000..30097535
--- /dev/null
+++ b/src/Mayaqua/pkcs11f.h
@@ -0,0 +1,912 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session
+ * handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen
+ * mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
+ * for pub.
+ * key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
+ * attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
+ * for priv.
+ * key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
+ * attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
+ * key
+ * handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
+ * priv. key
+ * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
diff --git a/src/Mayaqua/pkcs11t.h b/src/Mayaqua/pkcs11t.h
new file mode 100644
index 00000000..7a0f4060
--- /dev/null
+++ b/src/Mayaqua/pkcs11t.h
@@ -0,0 +1,1440 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE !(FALSE)
+#endif
+#endif
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
+#define CKF_HW_SLOT 0x00000004 /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001 /* has random #
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002 /* token is
+ * write-
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#define CKS_RO_PUBLIC_SESSION 0
+#define CKS_RO_USER_FUNCTIONS 1
+#define CKS_RW_PUBLIC_SESSION 2
+#define CKS_RW_USER_FUNCTIONS 3
+#define CKS_RW_SO_FUNCTIONS 4
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002 /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_VENDOR_DEFINED 0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_VENDOR_DEFINED 0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000
+#define CKK_DSA 0x00000001
+#define CKK_DH 0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
+#define CKK_KEA 0x00000005
+
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC2 0x00000011
+#define CKK_RC4 0x00000012
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016
+#define CKK_CAST3 0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018
+#define CKK_CAST128 0x00000018
+#define CKK_RC5 0x00000019
+#define CKK_IDEA 0x0000001A
+#define CKK_SKIPJACK 0x0000001B
+#define CKK_BATON 0x0000001C
+#define CKK_JUNIPER 0x0000001D
+#define CKK_CDMF 0x0000001E
+#define CKK_AES 0x0000001F
+
+#define CKK_VENDOR_DEFINED 0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000
+#define CKA_TOKEN 0x00000001
+#define CKA_PRIVATE 0x00000002
+#define CKA_LABEL 0x00000003
+#define CKA_APPLICATION 0x00000010
+#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
+#define CKA_CERTIFICATE_TYPE 0x00000080
+#define CKA_ISSUER 0x00000081
+#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_SUBJECT 0x00000101
+#define CKA_ID 0x00000102
+#define CKA_SENSITIVE 0x00000103
+#define CKA_ENCRYPT 0x00000104
+#define CKA_DECRYPT 0x00000105
+#define CKA_WRAP 0x00000106
+#define CKA_UNWRAP 0x00000107
+#define CKA_SIGN 0x00000108
+#define CKA_SIGN_RECOVER 0x00000109
+#define CKA_VERIFY 0x0000010A
+#define CKA_VERIFY_RECOVER 0x0000010B
+#define CKA_DERIVE 0x0000010C
+#define CKA_START_DATE 0x00000110
+#define CKA_END_DATE 0x00000111
+#define CKA_MODULUS 0x00000120
+#define CKA_MODULUS_BITS 0x00000121
+#define CKA_PUBLIC_EXPONENT 0x00000122
+#define CKA_PRIVATE_EXPONENT 0x00000123
+#define CKA_PRIME_1 0x00000124
+#define CKA_PRIME_2 0x00000125
+#define CKA_EXPONENT_1 0x00000126
+#define CKA_EXPONENT_2 0x00000127
+#define CKA_COEFFICIENT 0x00000128
+#define CKA_PRIME 0x00000130
+#define CKA_SUBPRIME 0x00000131
+#define CKA_BASE 0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUBPRIME_BITS 0x00000134
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS 0x00000160
+#define CKA_VALUE_LEN 0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162
+#define CKA_LOCAL 0x00000163
+#define CKA_NEVER_EXTRACTABLE 0x00000164
+#define CKA_ALWAYS_SENSITIVE 0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
+
+#define CKA_MODIFIABLE 0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180
+#define CKA_EC_PARAMS 0x00000180
+
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_SECONDARY_AUTH 0x00000200
+#define CKA_AUTH_PIN_FLAGS 0x00000201
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
+
+#define CKA_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
+#define CKM_RSA_PKCS 0x00000001
+#define CKM_RSA_9796 0x00000002
+#define CKM_RSA_X_509 0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004
+#define CKM_MD5_RSA_PKCS 0x00000005
+#define CKM_SHA1_RSA_PKCS 0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+#define CKM_RSA_PKCS_PSS 0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010
+#define CKM_DSA 0x00000011
+#define CKM_DSA_SHA1 0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
+#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
+#define CKM_RC2_KEY_GEN 0x00000100
+#define CKM_RC2_ECB 0x00000101
+#define CKM_RC2_CBC 0x00000102
+#define CKM_RC2_MAC 0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104
+#define CKM_RC2_CBC_PAD 0x00000105
+
+#define CKM_RC4_KEY_GEN 0x00000110
+#define CKM_RC4 0x00000111
+#define CKM_DES_KEY_GEN 0x00000120
+#define CKM_DES_ECB 0x00000121
+#define CKM_DES_CBC 0x00000122
+#define CKM_DES_MAC 0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124
+#define CKM_DES_CBC_PAD 0x00000125
+
+#define CKM_DES2_KEY_GEN 0x00000130
+#define CKM_DES3_KEY_GEN 0x00000131
+#define CKM_DES3_ECB 0x00000132
+#define CKM_DES3_CBC 0x00000133
+#define CKM_DES3_MAC 0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135
+#define CKM_DES3_CBC_PAD 0x00000136
+#define CKM_CDMF_KEY_GEN 0x00000140
+#define CKM_CDMF_ECB 0x00000141
+#define CKM_CDMF_CBC 0x00000142
+#define CKM_CDMF_MAC 0x00000143
+#define CKM_CDMF_MAC_GENERAL 0x00000144
+#define CKM_CDMF_CBC_PAD 0x00000145
+
+#define CKM_MD2 0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201
+#define CKM_MD2_HMAC_GENERAL 0x00000202
+
+#define CKM_MD5 0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211
+#define CKM_MD5_HMAC_GENERAL 0x00000212
+
+#define CKM_SHA_1 0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300
+#define CKM_CAST_ECB 0x00000301
+#define CKM_CAST_CBC 0x00000302
+#define CKM_CAST_MAC 0x00000303
+#define CKM_CAST_MAC_GENERAL 0x00000304
+#define CKM_CAST_CBC_PAD 0x00000305
+#define CKM_CAST3_KEY_GEN 0x00000310
+#define CKM_CAST3_ECB 0x00000311
+#define CKM_CAST3_CBC 0x00000312
+#define CKM_CAST3_MAC 0x00000313
+#define CKM_CAST3_MAC_GENERAL 0x00000314
+#define CKM_CAST3_CBC_PAD 0x00000315
+#define CKM_CAST5_KEY_GEN 0x00000320
+#define CKM_CAST128_KEY_GEN 0x00000320
+#define CKM_CAST5_ECB 0x00000321
+#define CKM_CAST128_ECB 0x00000321
+#define CKM_CAST5_CBC 0x00000322
+#define CKM_CAST128_CBC 0x00000322
+#define CKM_CAST5_MAC 0x00000323
+#define CKM_CAST128_MAC 0x00000323
+#define CKM_CAST5_MAC_GENERAL 0x00000324
+#define CKM_CAST128_MAC_GENERAL 0x00000324
+#define CKM_CAST5_CBC_PAD 0x00000325
+#define CKM_CAST128_CBC_PAD 0x00000325
+#define CKM_RC5_KEY_GEN 0x00000330
+#define CKM_RC5_ECB 0x00000331
+#define CKM_RC5_CBC 0x00000332
+#define CKM_RC5_MAC 0x00000333
+#define CKM_RC5_MAC_GENERAL 0x00000334
+#define CKM_RC5_CBC_PAD 0x00000335
+#define CKM_IDEA_KEY_GEN 0x00000340
+#define CKM_IDEA_ECB 0x00000341
+#define CKM_IDEA_CBC 0x00000342
+#define CKM_IDEA_MAC 0x00000343
+#define CKM_IDEA_MAC_GENERAL 0x00000344
+#define CKM_IDEA_CBC_PAD 0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
+#define CKM_XOR_BASE_AND_DATA 0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
+#define CKM_SSL3_MD5_MAC 0x00000380
+#define CKM_SSL3_SHA1_MAC 0x00000381
+#define CKM_MD5_KEY_DERIVATION 0x00000390
+#define CKM_MD2_KEY_DERIVATION 0x00000391
+#define CKM_SHA1_KEY_DERIVATION 0x00000392
+#define CKM_PBE_MD2_DES_CBC 0x000003A0
+#define CKM_PBE_MD5_DES_CBC 0x000003A1
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
+#define CKM_PBE_SHA1_RC4_128 0x000003A6
+#define CKM_PBE_SHA1_RC4_40 0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
+#define CKM_KEY_WRAP_LYNKS 0x00000400
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000
+#define CKM_SKIPJACK_ECB64 0x00001001
+#define CKM_SKIPJACK_CBC64 0x00001002
+#define CKM_SKIPJACK_OFB64 0x00001003
+#define CKM_SKIPJACK_CFB64 0x00001004
+#define CKM_SKIPJACK_CFB32 0x00001005
+#define CKM_SKIPJACK_CFB16 0x00001006
+#define CKM_SKIPJACK_CFB8 0x00001007
+#define CKM_SKIPJACK_WRAP 0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
+#define CKM_SKIPJACK_RELAYX 0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010
+#define CKM_KEA_KEY_DERIVE 0x00001011
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020
+#define CKM_BATON_KEY_GEN 0x00001030
+#define CKM_BATON_ECB128 0x00001031
+#define CKM_BATON_ECB96 0x00001032
+#define CKM_BATON_CBC128 0x00001033
+#define CKM_BATON_COUNTER 0x00001034
+#define CKM_BATON_SHUFFLE 0x00001035
+#define CKM_BATON_WRAP 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
+
+#define CKM_ECDSA 0x00001041
+#define CKM_ECDSA_SHA1 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
+#define CKM_ECMQV_DERIVE 0x00001052
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060
+#define CKM_JUNIPER_ECB128 0x00001061
+#define CKM_JUNIPER_CBC128 0x00001062
+#define CKM_JUNIPER_COUNTER 0x00001063
+#define CKM_JUNIPER_SHUFFLE 0x00001064
+#define CKM_JUNIPER_WRAP 0x00001065
+#define CKM_FASTHASH 0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080
+#define CKM_AES_ECB 0x00001081
+#define CKM_AES_CBC 0x00001082
+#define CKM_AES_MAC 0x00001083
+#define CKM_AES_MAC_GENERAL 0x00001084
+#define CKM_AES_CBC_PAD 0x00001085
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+
+#define CKM_VENDOR_DEFINED 0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001 /* performed by HW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100
+#define CKF_DECRYPT 0x00000200
+#define CKF_DIGEST 0x00000400
+#define CKF_SIGN 0x00000800
+#define CKF_SIGN_RECOVER 0x00001000
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000
+#define CKF_GENERATE 0x00008000
+#define CKF_GENERATE_KEY_PAIR 0x00010000
+#define CKF_WRAP 0x00020000
+#define CKF_UNWRAP 0x00040000
+#define CKF_DERIVE 0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
+
+#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000
+#define CKR_CANCEL 0x00000001
+#define CKR_HOST_MEMORY 0x00000002
+#define CKR_SLOT_ID_INVALID 0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005
+#define CKR_FUNCTION_FAILED 0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007
+#define CKR_NO_EVENT 0x00000008
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009
+#define CKR_CANT_LOCK 0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
+#define CKR_DATA_INVALID 0x00000020
+#define CKR_DATA_LEN_RANGE 0x00000021
+#define CKR_DEVICE_ERROR 0x00000030
+#define CKR_DEVICE_MEMORY 0x00000031
+#define CKR_DEVICE_REMOVED 0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
+#define CKR_FUNCTION_CANCELED 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064
+#define CKR_KEY_CHANGED 0x00000065
+#define CKR_KEY_NEEDED 0x00000066
+#define CKR_KEY_INDIGESTIBLE 0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069
+#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+
+#define CKR_MECHANISM_INVALID 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082
+#define CKR_OPERATION_ACTIVE 0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
+#define CKR_PIN_INCORRECT 0x000000A0
+#define CKR_PIN_INVALID 0x000000A1
+#define CKR_PIN_LEN_RANGE 0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3
+#define CKR_PIN_LOCKED 0x000000A4
+
+#define CKR_SESSION_CLOSED 0x000000B0
+#define CKR_SESSION_COUNT 0x000000B1
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
+#define CKR_SESSION_READ_ONLY 0x000000B5
+#define CKR_SESSION_EXISTS 0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
+
+#define CKR_SIGNATURE_INVALID 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
+#define CKR_USER_NOT_LOGGED_IN 0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
+#define CKR_USER_TYPE_INVALID 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
+#define CKR_USER_TOO_MANY_TYPES 0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150
+#define CKR_SAVED_STATE_INVALID 0x00000160
+#define CKR_INFORMATION_SENSITIVE 0x00000170
+#define CKR_STATE_UNSAVEABLE 0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
+#define CKR_MUTEX_BAD 0x000001A0
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1
+
+#define CKR_VENDOR_DEFINED 0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK 0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+#define CKG_MGF1_SHA1 0x00000001
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF 0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined: */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF_ASN1 0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/aes.h b/src/Mayaqua/win32_inc/openssl/aes.h
new file mode 100644
index 00000000..07ece721
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/aes.h
@@ -0,0 +1,148 @@
+/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef HEADER_AES_H
+#define HEADER_AES_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_AES
+#error AES is disabled.
+#endif
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+/* Because array size can't be a const in C, the following two are macros.
+ Both sizes are in bytes. */
+#define AES_MAXNR 14
+#define AES_BLOCK_SIZE 16
+
+#ifdef OPENSSL_FIPS
+#define FIPS_AES_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+struct aes_key_st {
+#ifdef AES_LONG
+ unsigned long rd_key[4 *(AES_MAXNR + 1)];
+#else
+ unsigned int rd_key[4 *(AES_MAXNR + 1)];
+#endif
+ int rounds;
+};
+typedef struct aes_key_st AES_KEY;
+
+const char *AES_options(void);
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+
+void AES_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void AES_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key, const int enc);
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfbr_encrypt_block(const unsigned char *in,unsigned char *out,
+ const int nbits,const AES_KEY *key,
+ unsigned char *ivec,const int enc);
+void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num);
+void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char ivec[AES_BLOCK_SIZE],
+ unsigned char ecount_buf[AES_BLOCK_SIZE],
+ unsigned int *num);
+
+/* For IGE, see also http://www.links.org/files/openssl-ige.pdf */
+/* NB: the IV is _two_ blocks long */
+void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+/* NB: the IV is _four_ blocks long */
+void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ const AES_KEY *key2, const unsigned char *ivec,
+ const int enc);
+
+int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
+ unsigned char *out,
+ const unsigned char *in, unsigned int inlen);
+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
+ unsigned char *out,
+ const unsigned char *in, unsigned int inlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !HEADER_AES_H */
diff --git a/src/Mayaqua/win32_inc/openssl/asn1.h b/src/Mayaqua/win32_inc/openssl/asn1.h
new file mode 100644
index 00000000..ba064087
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1.h
@@ -0,0 +1,1332 @@
+/* crypto/asn1/asn1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_H
+#define HEADER_ASN1_H
+
+#include <time.h>
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+
+#include <openssl/symhacks.h>
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define V_ASN1_UNIVERSAL 0x00
+#define V_ASN1_APPLICATION 0x40
+#define V_ASN1_CONTEXT_SPECIFIC 0x80
+#define V_ASN1_PRIVATE 0xc0
+
+#define V_ASN1_CONSTRUCTED 0x20
+#define V_ASN1_PRIMITIVE_TAG 0x1f
+#define V_ASN1_PRIMATIVE_TAG 0x1f
+
+#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */
+#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */
+#define V_ASN1_ANY -4 /* used in ASN1 template code */
+
+#define V_ASN1_NEG 0x100 /* negative flag */
+
+#define V_ASN1_UNDEF -1
+#define V_ASN1_EOC 0
+#define V_ASN1_BOOLEAN 1 /**/
+#define V_ASN1_INTEGER 2
+#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG)
+#define V_ASN1_BIT_STRING 3
+#define V_ASN1_OCTET_STRING 4
+#define V_ASN1_NULL 5
+#define V_ASN1_OBJECT 6
+#define V_ASN1_OBJECT_DESCRIPTOR 7
+#define V_ASN1_EXTERNAL 8
+#define V_ASN1_REAL 9
+#define V_ASN1_ENUMERATED 10
+#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG)
+#define V_ASN1_UTF8STRING 12
+#define V_ASN1_SEQUENCE 16
+#define V_ASN1_SET 17
+#define V_ASN1_NUMERICSTRING 18 /**/
+#define V_ASN1_PRINTABLESTRING 19
+#define V_ASN1_T61STRING 20
+#define V_ASN1_TELETEXSTRING 20 /* alias */
+#define V_ASN1_VIDEOTEXSTRING 21 /**/
+#define V_ASN1_IA5STRING 22
+#define V_ASN1_UTCTIME 23
+#define V_ASN1_GENERALIZEDTIME 24 /**/
+#define V_ASN1_GRAPHICSTRING 25 /**/
+#define V_ASN1_ISO64STRING 26 /**/
+#define V_ASN1_VISIBLESTRING 26 /* alias */
+#define V_ASN1_GENERALSTRING 27 /**/
+#define V_ASN1_UNIVERSALSTRING 28 /**/
+#define V_ASN1_BMPSTRING 30
+
+/* For use with d2i_ASN1_type_bytes() */
+#define B_ASN1_NUMERICSTRING 0x0001
+#define B_ASN1_PRINTABLESTRING 0x0002
+#define B_ASN1_T61STRING 0x0004
+#define B_ASN1_TELETEXSTRING 0x0004
+#define B_ASN1_VIDEOTEXSTRING 0x0008
+#define B_ASN1_IA5STRING 0x0010
+#define B_ASN1_GRAPHICSTRING 0x0020
+#define B_ASN1_ISO64STRING 0x0040
+#define B_ASN1_VISIBLESTRING 0x0040
+#define B_ASN1_GENERALSTRING 0x0080
+#define B_ASN1_UNIVERSALSTRING 0x0100
+#define B_ASN1_OCTET_STRING 0x0200
+#define B_ASN1_BIT_STRING 0x0400
+#define B_ASN1_BMPSTRING 0x0800
+#define B_ASN1_UNKNOWN 0x1000
+#define B_ASN1_UTF8STRING 0x2000
+#define B_ASN1_UTCTIME 0x4000
+#define B_ASN1_GENERALIZEDTIME 0x8000
+#define B_ASN1_SEQUENCE 0x10000
+
+/* For use with ASN1_mbstring_copy() */
+#define MBSTRING_FLAG 0x1000
+#define MBSTRING_UTF8 (MBSTRING_FLAG)
+#define MBSTRING_ASC (MBSTRING_FLAG|1)
+#define MBSTRING_BMP (MBSTRING_FLAG|2)
+#define MBSTRING_UNIV (MBSTRING_FLAG|4)
+
+#define SMIME_OLDMIME 0x400
+#define SMIME_CRLFEOL 0x800
+#define SMIME_STREAM 0x1000
+
+struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
+
+#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
+#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
+
+/* We MUST make sure that, except for constness, asn1_ctx_st and
+ asn1_const_ctx are exactly the same. Fortunately, as soon as
+ the old ASN1 parsing macros are gone, we can throw this away
+ as well... */
+typedef struct asn1_ctx_st
+ {
+ unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ unsigned char *max; /* largest value of p allowed */
+ unsigned char *q;/* temporary variable */
+ unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_CTX;
+
+typedef struct asn1_const_ctx_st
+ {
+ const unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ const unsigned char *max; /* largest value of p allowed */
+ const unsigned char *q;/* temporary variable */
+ const unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_const_CTX;
+
+/* These are used internally in the ASN1_OBJECT to keep track of
+ * whether the names and data need to be free()ed */
+#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */
+#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */
+#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */
+#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */
+typedef struct asn1_object_st
+ {
+ const char *sn,*ln;
+ int nid;
+ int length;
+ unsigned char *data;
+ int flags; /* Should we free this one */
+ } ASN1_OBJECT;
+
+#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
+/* This indicates that the ASN1_STRING is not a real value but just a place
+ * holder for the location where indefinite length constructed data should
+ * be inserted in the memory buffer
+ */
+#define ASN1_STRING_FLAG_NDEF 0x010
+
+/* This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been
+ * accessed. The flag will be reset when content has been written to it.
+ */
+#define ASN1_STRING_FLAG_CONT 0x020
+
+/* This is the base type that holds just about everything :-) */
+typedef struct asn1_string_st
+ {
+ int length;
+ int type;
+ unsigned char *data;
+ /* The value of the following field depends on the type being
+ * held. It is mostly being used for BIT_STRING so if the
+ * input data has a non-zero 'unused bits' value, it will be
+ * handled correctly */
+ long flags;
+ } ASN1_STRING;
+
+/* ASN1_ENCODING structure: this is used to save the received
+ * encoding of an ASN1 type. This is useful to get round
+ * problems with invalid encodings which can break signatures.
+ */
+
+typedef struct ASN1_ENCODING_st
+ {
+ unsigned char *enc; /* DER encoding */
+ long len; /* Length of encoding */
+ int modified; /* set to 1 if 'enc' is invalid */
+ } ASN1_ENCODING;
+
+/* Used with ASN1 LONG type: if a long is set to this it is omitted */
+#define ASN1_LONG_UNDEF 0x7fffffffL
+
+#define STABLE_FLAGS_MALLOC 0x01
+#define STABLE_NO_MASK 0x02
+#define DIRSTRING_TYPE \
+ (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
+#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
+
+typedef struct asn1_string_table_st {
+ int nid;
+ long minsize;
+ long maxsize;
+ unsigned long mask;
+ unsigned long flags;
+} ASN1_STRING_TABLE;
+
+DECLARE_STACK_OF(ASN1_STRING_TABLE)
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+#define ub_name 32768
+#define ub_common_name 64
+#define ub_locality_name 128
+#define ub_state_name 128
+#define ub_organization_name 64
+#define ub_organization_unit_name 64
+#define ub_title 64
+#define ub_email_address 128
+
+/* Declarations for template structures: for full definitions
+ * see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
+
+#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+ type *d2i_##name(type **a, const unsigned char **in, long len); \
+ int i2d_##name(type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(itname)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+ type *d2i_##name(type **a, const unsigned char **in, long len); \
+ int i2d_##name(const type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(name)
+
+#define DECLARE_ASN1_NDEF_FUNCTION(name) \
+ int i2d_##name##_NDEF(name *a, unsigned char **out);
+
+#define DECLARE_ASN1_FUNCTIONS_const(name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ type *name##_new(void); \
+ void name##_free(type *a);
+
+#define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+#define I2D_OF(type) int (*)(type *,unsigned char **)
+#define I2D_OF_const(type) int (*)(const type *,unsigned char **)
+
+#define CHECKED_D2I_OF(type, d2i) \
+ ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+#define CHECKED_I2D_OF(type, i2d) \
+ ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+#define CHECKED_NEW_OF(type, xnew) \
+ ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+#define CHECKED_PTR_OF(type, p) \
+ ((void*) (1 ? p : (type*)0))
+#define CHECKED_PPTR_OF(type, p) \
+ ((void**) (1 ? p : (type**)0))
+#define CHECKED_PTR_OF_TO_CHAR(type, p) \
+ ((char*) (1 ? p : (type*)0))
+
+#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
+#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+TYPEDEF_D2I2D_OF(void);
+
+/* The following macros and typedefs allow an ASN1_ITEM
+ * to be embedded in a structure and referenced. Since
+ * the ASN1_ITEM pointers need to be globally accessible
+ * (possibly from shared libraries) they may exist in
+ * different forms. On platforms that support it the
+ * ASN1_ITEM structure itself will be globally exported.
+ * Other platforms will export a function that returns
+ * an ASN1_ITEM pointer.
+ *
+ * To handle both cases transparently the macros below
+ * should be used instead of hard coding an ASN1_ITEM
+ * pointer in a structure.
+ *
+ * The structure will look like this:
+ *
+ * typedef struct SOMETHING_st {
+ * ...
+ * ASN1_ITEM_EXP *iptr;
+ * ...
+ * } SOMETHING;
+ *
+ * It would be initialised as e.g.:
+ *
+ * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
+ *
+ * and the actual pointer extracted with:
+ *
+ * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
+ *
+ * Finally an ASN1_ITEM pointer can be extracted from an
+ * appropriate reference with: ASN1_ITEM_rptr(X509). This
+ * would be used when a function takes an ASN1_ITEM * argument.
+ *
+ */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM ASN1_ITEM_EXP;
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr)
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (&(iptr##_it))
+
+#define ASN1_ITEM_rptr(ref) (&(ref##_it))
+
+#define DECLARE_ASN1_ITEM(name) \
+ OPENSSL_EXTERN const ASN1_ITEM name##_it;
+
+#else
+
+/* Platforms that can't easily handle shared global variables are declared
+ * as functions returning ASN1_ITEM pointers.
+ */
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM * ASN1_ITEM_EXP(void);
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr())
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (iptr##_it)
+
+#define ASN1_ITEM_rptr(ref) (ref##_it())
+
+#define DECLARE_ASN1_ITEM(name) \
+ const ASN1_ITEM * name##_it(void);
+
+#endif
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/* These determine which characters to escape:
+ * RFC2253 special characters, control characters and
+ * MSB set characters
+ */
+
+#define ASN1_STRFLGS_ESC_2253 1
+#define ASN1_STRFLGS_ESC_CTRL 2
+#define ASN1_STRFLGS_ESC_MSB 4
+
+
+/* This flag determines how we do escaping: normally
+ * RC2253 backslash only, set this to use backslash and
+ * quote.
+ */
+
+#define ASN1_STRFLGS_ESC_QUOTE 8
+
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+#define CHARTYPE_PRINTABLESTRING 0x10
+/* Character needs escaping if it is the first character */
+#define CHARTYPE_FIRST_ESC_2253 0x20
+/* Character needs escaping if it is the last character */
+#define CHARTYPE_LAST_ESC_2253 0x40
+
+/* NB the internal flags are safely reused below by flags
+ * handled at the top level.
+ */
+
+/* If this is set we convert all character strings
+ * to UTF8 first
+ */
+
+#define ASN1_STRFLGS_UTF8_CONVERT 0x10
+
+/* If this is set we don't attempt to interpret content:
+ * just assume all strings are 1 byte per character. This
+ * will produce some pretty odd looking output!
+ */
+
+#define ASN1_STRFLGS_IGNORE_TYPE 0x20
+
+/* If this is set we include the string type in the output */
+#define ASN1_STRFLGS_SHOW_TYPE 0x40
+
+/* This determines which strings to display and which to
+ * 'dump' (hex dump of content octets or DER encoding). We can
+ * only dump non character strings or everything. If we
+ * don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to
+ * the usual escaping options.
+ */
+
+#define ASN1_STRFLGS_DUMP_ALL 0x80
+#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100
+
+/* These determine what 'dumping' does, we can dump the
+ * content octets or the DER encoding: both use the
+ * RFC2253 #XXXXX notation.
+ */
+
+#define ASN1_STRFLGS_DUMP_DER 0x200
+
+/* All the string flags consistent with RFC2253,
+ * escaping control characters isn't essential in
+ * RFC2253 but it is advisable anyway.
+ */
+
+#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \
+ ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ ASN1_STRFLGS_UTF8_CONVERT | \
+ ASN1_STRFLGS_DUMP_UNKNOWN | \
+ ASN1_STRFLGS_DUMP_DER)
+
+DECLARE_STACK_OF(ASN1_INTEGER)
+DECLARE_ASN1_SET_OF(ASN1_INTEGER)
+
+DECLARE_STACK_OF(ASN1_GENERALSTRING)
+
+typedef struct asn1_type_st
+ {
+ int type;
+ union {
+ char *ptr;
+ ASN1_BOOLEAN boolean;
+ ASN1_STRING * asn1_string;
+ ASN1_OBJECT * object;
+ ASN1_INTEGER * integer;
+ ASN1_ENUMERATED * enumerated;
+ ASN1_BIT_STRING * bit_string;
+ ASN1_OCTET_STRING * octet_string;
+ ASN1_PRINTABLESTRING * printablestring;
+ ASN1_T61STRING * t61string;
+ ASN1_IA5STRING * ia5string;
+ ASN1_GENERALSTRING * generalstring;
+ ASN1_BMPSTRING * bmpstring;
+ ASN1_UNIVERSALSTRING * universalstring;
+ ASN1_UTCTIME * utctime;
+ ASN1_GENERALIZEDTIME * generalizedtime;
+ ASN1_VISIBLESTRING * visiblestring;
+ ASN1_UTF8STRING * utf8string;
+ /* set and sequence are left complete and still
+ * contain the set or sequence bytes */
+ ASN1_STRING * set;
+ ASN1_STRING * sequence;
+ ASN1_VALUE * asn1_value;
+ } value;
+ } ASN1_TYPE;
+
+DECLARE_STACK_OF(ASN1_TYPE)
+DECLARE_ASN1_SET_OF(ASN1_TYPE)
+
+typedef struct asn1_method_st
+ {
+ i2d_of_void *i2d;
+ d2i_of_void *d2i;
+ void *(*create)(void);
+ void (*destroy)(void *);
+ } ASN1_METHOD;
+
+/* This is used when parsing some Netscape objects */
+typedef struct asn1_header_st
+ {
+ ASN1_OCTET_STRING *header;
+ void *data;
+ ASN1_METHOD *meth;
+ } ASN1_HEADER;
+
+/* This is used to contain a list of bit names */
+typedef struct BIT_STRING_BITNAME_st {
+ int bitnum;
+ const char *lname;
+ const char *sname;
+} BIT_STRING_BITNAME;
+
+
+#define M_ASN1_STRING_length(x) ((x)->length)
+#define M_ASN1_STRING_length_set(x, n) ((x)->length = (n))
+#define M_ASN1_STRING_type(x) ((x)->type)
+#define M_ASN1_STRING_data(x) ((x)->data)
+
+/* Macros for string operations */
+#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_BIT_STRING)
+#define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\
+ ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+
+#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\
+ ASN1_STRING_type_new(V_ASN1_INTEGER)
+#define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\
+ ASN1_STRING_type_new(V_ASN1_ENUMERATED)
+#define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_OCTET_STRING)
+#define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\
+ ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+#define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b)
+#define M_i2d_ASN1_OCTET_STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
+ V_ASN1_UNIVERSAL)
+
+#define B_ASN1_TIME \
+ B_ASN1_UTCTIME | \
+ B_ASN1_GENERALIZEDTIME
+
+#define B_ASN1_PRINTABLE \
+ B_ASN1_NUMERICSTRING| \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_T61STRING| \
+ B_ASN1_IA5STRING| \
+ B_ASN1_BIT_STRING| \
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING|\
+ B_ASN1_SEQUENCE|\
+ B_ASN1_UNKNOWN
+
+#define B_ASN1_DIRECTORYSTRING \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_TELETEXSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_UTF8STRING
+
+#define B_ASN1_DISPLAYTEXT \
+ B_ASN1_IA5STRING| \
+ B_ASN1_VISIBLESTRING| \
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING
+
+#define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLE(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_PRINTABLE)
+
+#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DIRECTORYSTRING(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DIRECTORYSTRING)
+
+#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DISPLAYTEXT(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DISPLAYTEXT)
+
+#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
+ (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
+
+#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\
+ ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_T61STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_T61STRING(a,pp,l) \
+ (ASN1_T61STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
+
+#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\
+ ASN1_STRING_type_new(V_ASN1_IA5STRING)
+#define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_IA5STRING_dup(a) \
+ (ASN1_IA5STRING *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_i2d_ASN1_IA5STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_IA5STRING(a,pp,l) \
+ (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
+ B_ASN1_IA5STRING)
+
+#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME)
+#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\
+ (ASN1_STRING *)a)
+
+#define M_ASN1_TIME_new() (ASN1_TIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_TIME_dup(a) (ASN1_TIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
+#define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_GENERALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
+ (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
+
+#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
+#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
+ (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
+
+#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_BMPSTRING)
+#define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_BMPSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_BMPSTRING(a,pp,l) \
+ (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
+
+#define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_VISIBLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
+ (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
+
+#define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\
+ ASN1_STRING_type_new(V_ASN1_UTF8STRING)
+#define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UTF8STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UTF8STRING(a,pp,l) \
+ (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
+
+ /* for the is_set parameter to i2d_ASN1_SET */
+#define IS_SEQUENCE 0
+#define IS_SET 1
+
+DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+int ASN1_TYPE_get(ASN1_TYPE *a);
+void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+
+ASN1_OBJECT * ASN1_OBJECT_new(void );
+void ASN1_OBJECT_free(ASN1_OBJECT *a);
+int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp);
+ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+
+DECLARE_ASN1_ITEM(ASN1_OBJECT)
+
+DECLARE_STACK_OF(ASN1_OBJECT)
+DECLARE_ASN1_SET_OF(ASN1_OBJECT)
+
+ASN1_STRING * ASN1_STRING_new(void);
+void ASN1_STRING_free(ASN1_STRING *a);
+ASN1_STRING * ASN1_STRING_dup(ASN1_STRING *a);
+ASN1_STRING * ASN1_STRING_type_new(int type );
+int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
+ /* Since this is used to store all sorts of things, via macros, for now, make
+ its data void * */
+int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
+int ASN1_STRING_length(ASN1_STRING *x);
+void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+int ASN1_STRING_type(ASN1_STRING *x);
+unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
+ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp,
+ long length);
+int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d,
+ int length );
+int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
+
+#ifndef OPENSSL_NO_BIO
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+ BIT_STRING_BITNAME *tbl, int indent);
+#endif
+int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl);
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
+ BIT_STRING_BITNAME *tbl);
+
+int i2d_ASN1_BOOLEAN(int a,unsigned char **pp);
+int d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp);
+ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+ long length);
+ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+ long length);
+ASN1_INTEGER * ASN1_INTEGER_dup(ASN1_INTEGER *x);
+int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+int ASN1_UTCTIME_check(ASN1_UTCTIME *a);
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t);
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+#if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
+#endif
+
+int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *a);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t);
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *a);
+int ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *a, ASN1_OCTET_STRING *b);
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, int len);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t);
+int ASN1_TIME_check(ASN1_TIME *t);
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
+
+int i2d_ASN1_SET(STACK *a, unsigned char **pp,
+ i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
+STACK * d2i_ASN1_SET(STACK **a, const unsigned char **pp, long length,
+ d2i_of_void *d2i, void (*free_func)(void *),
+ int ex_tag, int ex_class);
+
+#ifndef OPENSSL_NO_BIO
+int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
+int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size);
+int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
+int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size);
+int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
+int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size);
+int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
+#endif
+int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
+
+int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num);
+ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len,
+ const char *sn, const char *ln);
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+long ASN1_INTEGER_get(ASN1_INTEGER *a);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai);
+BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn);
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
+BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
+ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
+ long length, int Ptag, int Pclass);
+unsigned long ASN1_tag2bit(int tag);
+/* type is one or more of the B_ASN1_ values. */
+ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp,
+ long length,int type);
+
+/* PARSING */
+int asn1_Finish(ASN1_CTX *c);
+int asn1_const_Finish(ASN1_const_CTX *c);
+
+/* SPECIALS */
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+ int *pclass, long omax);
+int ASN1_check_infinite_end(unsigned char **p,long len);
+int ASN1_const_check_infinite_end(const unsigned char **p,long len);
+void ASN1_put_object(unsigned char **pp, int constructed, int length,
+ int tag, int xclass);
+int ASN1_put_eoc(unsigned char **pp);
+int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+
+#define ASN1_dup_of(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF_TO_CHAR(type, x)))
+
+#define ASN1_dup_of_const(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF_TO_CHAR(const type, x)))
+
+void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+ ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
+#ifndef OPENSSL_NO_FP_API
+void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
+
+#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
+
+#define ASN1_i2d_fp_of(type,i2d,out,x) \
+ (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(type, x)))
+
+#define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+ (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
+#endif
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
+
+#ifndef OPENSSL_NO_BIO
+void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
+
+#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x);
+
+#define ASN1_i2d_bio_of(type,i2d,out,x) \
+ (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(type, x)))
+
+#define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+ (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
+int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
+int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
+int ASN1_TIME_print(BIO *fp,ASN1_TIME *a);
+int ASN1_STRING_print(BIO *bp,ASN1_STRING *v);
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
+int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
+int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
+#endif
+const char *ASN1_tag2str(int tag);
+
+/* Used to load and write netscape format cert/key */
+int i2d_ASN1_HEADER(ASN1_HEADER *a,unsigned char **pp);
+ASN1_HEADER *d2i_ASN1_HEADER(ASN1_HEADER **a,const unsigned char **pp, long length);
+ASN1_HEADER *ASN1_HEADER_new(void );
+void ASN1_HEADER_free(ASN1_HEADER *a);
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+/* Not used that much at this point, except for the first two */
+ASN1_METHOD *X509_asn1_meth(void);
+ASN1_METHOD *RSAPrivateKey_asn1_meth(void);
+ASN1_METHOD *ASN1_IA5STRING_asn1_meth(void);
+ASN1_METHOD *ASN1_BIT_STRING_asn1_meth(void);
+
+int ASN1_TYPE_set_octetstring(ASN1_TYPE *a,
+ unsigned char *data, int len);
+int ASN1_TYPE_get_octetstring(ASN1_TYPE *a,
+ unsigned char *data, int max_len);
+int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
+ unsigned char *data, int len);
+int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a,long *num,
+ unsigned char *data, int max_len);
+
+STACK *ASN1_seq_unpack(const unsigned char *buf, int len,
+ d2i_of_void *d2i, void (*free_func)(void *));
+unsigned char *ASN1_seq_pack(STACK *safes, i2d_of_void *i2d,
+ unsigned char **buf, int *len );
+void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
+void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
+ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
+ ASN1_OCTET_STRING **oct);
+
+#define ASN1_pack_string_of(type,obj,i2d,oct) \
+ (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
+ CHECKED_I2D_OF(type, i2d), \
+ oct))
+
+ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
+
+void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(const char *p);
+unsigned long ASN1_STRING_get_default_mask(void);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask);
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask,
+ long minsize, long maxsize);
+
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+ const unsigned char *in, int inlen, int inform, int nid);
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it);
+int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+
+void ASN1_add_oid_module(void);
+
+ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
+ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
+
+typedef int asn1_output_data_fn(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+ const ASN1_ITEM *it);
+
+int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs,
+ asn1_output_data_fn *data_fn,
+ const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ASN1_strings(void);
+
+/* Error codes for the ASN1 functions. */
+
+/* Function codes. */
+#define ASN1_F_A2D_ASN1_OBJECT 100
+#define ASN1_F_A2I_ASN1_ENUMERATED 101
+#define ASN1_F_A2I_ASN1_INTEGER 102
+#define ASN1_F_A2I_ASN1_STRING 103
+#define ASN1_F_APPEND_EXP 176
+#define ASN1_F_ASN1_BIT_STRING_SET_BIT 183
+#define ASN1_F_ASN1_CB 177
+#define ASN1_F_ASN1_CHECK_TLEN 104
+#define ASN1_F_ASN1_COLLATE_PRIMITIVE 105
+#define ASN1_F_ASN1_COLLECT 106
+#define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108
+#define ASN1_F_ASN1_D2I_FP 109
+#define ASN1_F_ASN1_D2I_READ_BIO 107
+#define ASN1_F_ASN1_DIGEST 184
+#define ASN1_F_ASN1_DO_ADB 110
+#define ASN1_F_ASN1_DUP 111
+#define ASN1_F_ASN1_ENUMERATED_SET 112
+#define ASN1_F_ASN1_ENUMERATED_TO_BN 113
+#define ASN1_F_ASN1_EX_C2I 204
+#define ASN1_F_ASN1_FIND_END 190
+#define ASN1_F_ASN1_GENERALIZEDTIME_SET 185
+#define ASN1_F_ASN1_GENERATE_V3 178
+#define ASN1_F_ASN1_GET_OBJECT 114
+#define ASN1_F_ASN1_HEADER_NEW 115
+#define ASN1_F_ASN1_I2D_BIO 116
+#define ASN1_F_ASN1_I2D_FP 117
+#define ASN1_F_ASN1_INTEGER_SET 118
+#define ASN1_F_ASN1_INTEGER_TO_BN 119
+#define ASN1_F_ASN1_ITEM_D2I_FP 206
+#define ASN1_F_ASN1_ITEM_DUP 191
+#define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW 121
+#define ASN1_F_ASN1_ITEM_EX_D2I 120
+#define ASN1_F_ASN1_ITEM_I2D_BIO 192
+#define ASN1_F_ASN1_ITEM_I2D_FP 193
+#define ASN1_F_ASN1_ITEM_PACK 198
+#define ASN1_F_ASN1_ITEM_SIGN 195
+#define ASN1_F_ASN1_ITEM_UNPACK 199
+#define ASN1_F_ASN1_ITEM_VERIFY 197
+#define ASN1_F_ASN1_MBSTRING_NCOPY 122
+#define ASN1_F_ASN1_OBJECT_NEW 123
+#define ASN1_F_ASN1_OUTPUT_DATA 207
+#define ASN1_F_ASN1_PACK_STRING 124
+#define ASN1_F_ASN1_PCTX_NEW 205
+#define ASN1_F_ASN1_PKCS5_PBE_SET 125
+#define ASN1_F_ASN1_SEQ_PACK 126
+#define ASN1_F_ASN1_SEQ_UNPACK 127
+#define ASN1_F_ASN1_SIGN 128
+#define ASN1_F_ASN1_STR2TYPE 179
+#define ASN1_F_ASN1_STRING_SET 186
+#define ASN1_F_ASN1_STRING_TABLE_ADD 129
+#define ASN1_F_ASN1_STRING_TYPE_NEW 130
+#define ASN1_F_ASN1_TEMPLATE_EX_D2I 132
+#define ASN1_F_ASN1_TEMPLATE_NEW 133
+#define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131
+#define ASN1_F_ASN1_TIME_SET 175
+#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134
+#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135
+#define ASN1_F_ASN1_UNPACK_STRING 136
+#define ASN1_F_ASN1_UTCTIME_SET 187
+#define ASN1_F_ASN1_VERIFY 137
+#define ASN1_F_B64_READ_ASN1 208
+#define ASN1_F_B64_WRITE_ASN1 209
+#define ASN1_F_BITSTR_CB 180
+#define ASN1_F_BN_TO_ASN1_ENUMERATED 138
+#define ASN1_F_BN_TO_ASN1_INTEGER 139
+#define ASN1_F_C2I_ASN1_BIT_STRING 189
+#define ASN1_F_C2I_ASN1_INTEGER 194
+#define ASN1_F_C2I_ASN1_OBJECT 196
+#define ASN1_F_COLLECT_DATA 140
+#define ASN1_F_D2I_ASN1_BIT_STRING 141
+#define ASN1_F_D2I_ASN1_BOOLEAN 142
+#define ASN1_F_D2I_ASN1_BYTES 143
+#define ASN1_F_D2I_ASN1_GENERALIZEDTIME 144
+#define ASN1_F_D2I_ASN1_HEADER 145
+#define ASN1_F_D2I_ASN1_INTEGER 146
+#define ASN1_F_D2I_ASN1_OBJECT 147
+#define ASN1_F_D2I_ASN1_SET 148
+#define ASN1_F_D2I_ASN1_TYPE_BYTES 149
+#define ASN1_F_D2I_ASN1_UINTEGER 150
+#define ASN1_F_D2I_ASN1_UTCTIME 151
+#define ASN1_F_D2I_NETSCAPE_RSA 152
+#define ASN1_F_D2I_NETSCAPE_RSA_2 153
+#define ASN1_F_D2I_PRIVATEKEY 154
+#define ASN1_F_D2I_PUBLICKEY 155
+#define ASN1_F_D2I_RSA_NET 200
+#define ASN1_F_D2I_RSA_NET_2 201
+#define ASN1_F_D2I_X509 156
+#define ASN1_F_D2I_X509_CINF 157
+#define ASN1_F_D2I_X509_PKEY 159
+#define ASN1_F_I2D_ASN1_SET 188
+#define ASN1_F_I2D_ASN1_TIME 160
+#define ASN1_F_I2D_DSA_PUBKEY 161
+#define ASN1_F_I2D_EC_PUBKEY 181
+#define ASN1_F_I2D_PRIVATEKEY 163
+#define ASN1_F_I2D_PUBLICKEY 164
+#define ASN1_F_I2D_RSA_NET 162
+#define ASN1_F_I2D_RSA_PUBKEY 165
+#define ASN1_F_LONG_C2I 166
+#define ASN1_F_OID_MODULE_INIT 174
+#define ASN1_F_PARSE_TAGGING 182
+#define ASN1_F_PKCS5_PBE2_SET 167
+#define ASN1_F_PKCS5_PBE_SET 202
+#define ASN1_F_SMIME_READ_ASN1 210
+#define ASN1_F_SMIME_TEXT 211
+#define ASN1_F_X509_CINF_NEW 168
+#define ASN1_F_X509_CRL_ADD0_REVOKED 169
+#define ASN1_F_X509_INFO_NEW 170
+#define ASN1_F_X509_NAME_ENCODE 203
+#define ASN1_F_X509_NAME_EX_D2I 158
+#define ASN1_F_X509_NAME_EX_NEW 171
+#define ASN1_F_X509_NEW 172
+#define ASN1_F_X509_PKEY_NEW 173
+
+/* Reason codes. */
+#define ASN1_R_ADDING_OBJECT 171
+#define ASN1_R_ASN1_PARSE_ERROR 198
+#define ASN1_R_ASN1_SIG_PARSE_ERROR 199
+#define ASN1_R_AUX_ERROR 100
+#define ASN1_R_BAD_CLASS 101
+#define ASN1_R_BAD_OBJECT_HEADER 102
+#define ASN1_R_BAD_PASSWORD_READ 103
+#define ASN1_R_BAD_TAG 104
+#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 210
+#define ASN1_R_BN_LIB 105
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
+#define ASN1_R_BUFFER_TOO_SMALL 107
+#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108
+#define ASN1_R_DATA_IS_WRONG 109
+#define ASN1_R_DECODE_ERROR 110
+#define ASN1_R_DECODING_ERROR 111
+#define ASN1_R_DEPTH_EXCEEDED 174
+#define ASN1_R_ENCODE_ERROR 112
+#define ASN1_R_ERROR_GETTING_TIME 173
+#define ASN1_R_ERROR_LOADING_SECTION 172
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT 113
+#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114
+#define ASN1_R_EXPECTING_AN_INTEGER 115
+#define ASN1_R_EXPECTING_AN_OBJECT 116
+#define ASN1_R_EXPECTING_A_BOOLEAN 117
+#define ASN1_R_EXPECTING_A_TIME 118
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
+#define ASN1_R_FIELD_MISSING 121
+#define ASN1_R_FIRST_NUM_TOO_LARGE 122
+#define ASN1_R_HEADER_TOO_LONG 123
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
+#define ASN1_R_ILLEGAL_BOOLEAN 176
+#define ASN1_R_ILLEGAL_CHARACTERS 124
+#define ASN1_R_ILLEGAL_FORMAT 177
+#define ASN1_R_ILLEGAL_HEX 178
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179
+#define ASN1_R_ILLEGAL_INTEGER 180
+#define ASN1_R_ILLEGAL_NESTED_TAGGING 181
+#define ASN1_R_ILLEGAL_NULL 125
+#define ASN1_R_ILLEGAL_NULL_VALUE 182
+#define ASN1_R_ILLEGAL_OBJECT 183
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY 126
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170
+#define ASN1_R_ILLEGAL_TAGGED_ANY 127
+#define ASN1_R_ILLEGAL_TIME_VALUE 184
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
+#define ASN1_R_INVALID_BMPSTRING_LENGTH 129
+#define ASN1_R_INVALID_DIGIT 130
+#define ASN1_R_INVALID_MIME_TYPE 200
+#define ASN1_R_INVALID_MODIFIER 186
+#define ASN1_R_INVALID_NUMBER 187
+#define ASN1_R_INVALID_OBJECT_ENCODING 212
+#define ASN1_R_INVALID_SEPARATOR 131
+#define ASN1_R_INVALID_TIME_FORMAT 132
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
+#define ASN1_R_INVALID_UTF8STRING 134
+#define ASN1_R_IV_TOO_LARGE 135
+#define ASN1_R_LENGTH_ERROR 136
+#define ASN1_R_LIST_ERROR 188
+#define ASN1_R_MIME_NO_CONTENT_TYPE 201
+#define ASN1_R_MIME_PARSE_ERROR 202
+#define ASN1_R_MIME_SIG_PARSE_ERROR 203
+#define ASN1_R_MISSING_EOC 137
+#define ASN1_R_MISSING_SECOND_NUMBER 138
+#define ASN1_R_MISSING_VALUE 189
+#define ASN1_R_MSTRING_NOT_UNIVERSAL 139
+#define ASN1_R_MSTRING_WRONG_TAG 140
+#define ASN1_R_NESTED_ASN1_STRING 197
+#define ASN1_R_NON_HEX_CHARACTERS 141
+#define ASN1_R_NOT_ASCII_FORMAT 190
+#define ASN1_R_NOT_ENOUGH_DATA 142
+#define ASN1_R_NO_CONTENT_TYPE 204
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE 205
+#define ASN1_R_NO_MULTIPART_BOUNDARY 206
+#define ASN1_R_NO_SIG_CONTENT_TYPE 207
+#define ASN1_R_NULL_IS_WRONG_LENGTH 144
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
+#define ASN1_R_ODD_NUMBER_OF_CHARS 145
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE 147
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
+#define ASN1_R_SHORT_LINE 150
+#define ASN1_R_SIG_INVALID_MIME_TYPE 208
+#define ASN1_R_STREAMING_NOT_SUPPORTED 209
+#define ASN1_R_STRING_TOO_LONG 151
+#define ASN1_R_STRING_TOO_SHORT 152
+#define ASN1_R_TAG_VALUE_TOO_HIGH 153
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
+#define ASN1_R_TIME_NOT_ASCII_FORMAT 193
+#define ASN1_R_TOO_LONG 155
+#define ASN1_R_TYPE_NOT_CONSTRUCTED 156
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158
+#define ASN1_R_UNEXPECTED_EOC 159
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 211
+#define ASN1_R_UNKNOWN_FORMAT 160
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
+#define ASN1_R_UNKNOWN_OBJECT_TYPE 162
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163
+#define ASN1_R_UNKNOWN_TAG 194
+#define ASN1_R_UNKOWN_FORMAT 195
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164
+#define ASN1_R_UNSUPPORTED_CIPHER 165
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
+#define ASN1_R_UNSUPPORTED_TYPE 196
+#define ASN1_R_WRONG_TAG 168
+#define ASN1_R_WRONG_TYPE 169
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/asn1_mac.h b/src/Mayaqua/win32_inc/openssl/asn1_mac.h
new file mode 100644
index 00000000..1ac54cf1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1_mac.h
@@ -0,0 +1,571 @@
+/* crypto/asn1/asn1_mac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_MAC_H
+#define HEADER_ASN1_MAC_H
+
+#include <openssl/asn1.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB ERR_LIB_ASN1
+#endif
+
+#define ASN1_MAC_H_err(f,r,line) \
+ ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
+
+#define M_ASN1_D2I_vars(a,type,func) \
+ ASN1_const_CTX c; \
+ type ret=NULL; \
+ \
+ c.pp=(const unsigned char **)pp; \
+ c.q= *(const unsigned char **)pp; \
+ c.error=ERR_R_NESTED_ASN1_ERROR; \
+ if ((a == NULL) || ((*a) == NULL)) \
+ { if ((ret=(type)func()) == NULL) \
+ { c.line=__LINE__; goto err; } } \
+ else ret=(*a);
+
+#define M_ASN1_D2I_Init() \
+ c.p= *(const unsigned char **)pp; \
+ c.max=(length == 0)?0:(c.p+length);
+
+#define M_ASN1_D2I_Finish_2(a) \
+ if (!asn1_const_Finish(&c)) \
+ { c.line=__LINE__; goto err; } \
+ *(const unsigned char **)pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret);
+
+#define M_ASN1_D2I_Finish(a,func,e) \
+ M_ASN1_D2I_Finish_2(a); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_start_sequence() \
+ if (!asn1_GetSequence(&c,&length)) \
+ { c.line=__LINE__; goto err; }
+/* Begin reading ASN1 without a surrounding sequence */
+#define M_ASN1_D2I_begin() \
+ c.slen = length;
+
+/* End reading ASN1 with no check on length */
+#define M_ASN1_D2I_Finish_nolen(a, func, e) \
+ *pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_end_sequence() \
+ (((c.inf&1) == 0)?(c.slen <= 0): \
+ (c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get(b, func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get_x(type,b,func) \
+ c.q=c.p; \
+ if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) < 0) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_opt(b,func,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+ == (V_ASN1_UNIVERSAL|(type)))) \
+ { \
+ M_ASN1_D2I_get(b,func); \
+ }
+
+#define M_ASN1_D2I_get_imp(b,func, type) \
+ M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+ c.slen-=(c.p-c.q);\
+ M_ASN1_next_prev=_tmp;
+
+#define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
+ (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
+ { \
+ unsigned char _tmp = M_ASN1_next; \
+ M_ASN1_D2I_get_imp(b,func, type);\
+ }
+
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set(b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq(r,func,free_func); }
+
+#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+ (void (*)())free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+ free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_set_strings(r,func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
+ if ((c.slen != 0L) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (func(&(r),&c.p,Tlen) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+ (void (*)())free_func, \
+ b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+ free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+/* New macros */
+#define M_ASN1_New_Malloc(ret,type) \
+ if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
+ { c.line=__LINE__; goto err2; }
+
+#define M_ASN1_New(arg,func) \
+ if (((arg)=func()) == NULL) return(NULL)
+
+#define M_ASN1_New_Error(a) \
+/* err: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
+ return(NULL);*/ \
+ err2: ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
+ return(NULL)
+
+
+/* BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately,
+ some macros that use ASN1_const_CTX still insist on writing in the input
+ stream. ARGH! ARGH! ARGH! Let's get rid of this macro package.
+ Please? -- Richard Levitte */
+#define M_ASN1_next (*((unsigned char *)(c.p)))
+#define M_ASN1_next_prev (*((unsigned char *)(c.q)))
+
+/*************************************************/
+
+#define M_ASN1_I2D_vars(a) int r=0,ret=0; \
+ unsigned char *p; \
+ if (a == NULL) return(0)
+
+/* Length Macros */
+#define M_ASN1_I2D_len(a,f) ret+=f(a,NULL)
+#define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f)
+
+#define M_ASN1_I2D_len_SET(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SET_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+ V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SEQUENCE(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
+ if (a != NULL)\
+ { \
+ v=f(a,NULL); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+ V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+/* Put Macros */
+#define M_ASN1_I2D_put(a,f) f(a,&p)
+
+#define M_ASN1_I2D_put_IMP_opt(a,f,t) \
+ if (a != NULL) \
+ { \
+ unsigned char *q=p; \
+ f(a,&p); \
+ *q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
+ }
+
+#define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
+ V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_SET_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
+ if (a != NULL) \
+ { \
+ ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
+ f(a,&p); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_seq_total() \
+ r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
+ if (pp == NULL) return(r); \
+ p= *pp; \
+ ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_I2D_INF_seq_start(tag,ctx) \
+ *(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
+ *(p++)=0x80
+
+#define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
+
+#define M_ASN1_I2D_finish() *pp=p; \
+ return(r);
+
+int asn1_GetSequence(ASN1_const_CTX *c, long *length);
+void asn1_add_error(const unsigned char *address,int offset);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/asn1t.h b/src/Mayaqua/win32_inc/openssl/asn1t.h
new file mode 100644
index 00000000..bc361156
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1t.h
@@ -0,0 +1,893 @@
+/* asn1t.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ASN1T_H
+#define HEADER_ASN1T_H
+
+#include <stddef.h>
+#include <openssl/e_os2.h>
+#include <openssl/asn1.h>
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+ OPENSSL_GLOBAL const ASN1_ITEM itname##_it = {
+
+#define ASN1_ITEM_end(itname) \
+ };
+
+#else
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr()))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+ const ASN1_ITEM * itname##_it(void) \
+ { \
+ static const ASN1_ITEM local_it = {
+
+#define ASN1_ITEM_end(itname) \
+ }; \
+ return &local_it; \
+ }
+
+#endif
+
+
+/* Macros to aid ASN1 template writing */
+
+#define ASN1_ITEM_TEMPLATE(tname) \
+ static const ASN1_TEMPLATE tname##_item_tt
+
+#define ASN1_ITEM_TEMPLATE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_PRIMITIVE,\
+ -1,\
+ &tname##_item_tt,\
+ 0,\
+ NULL,\
+ 0,\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+
+/* This is a ASN1 type which just embeds a template */
+
+/* This pair helps declare a SEQUENCE. We can do:
+ *
+ * ASN1_SEQUENCE(stname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END(stname)
+ *
+ * This will produce an ASN1_ITEM called stname_it
+ * for a structure called stname.
+ *
+ * If you want the same structure but a different
+ * name then use:
+ *
+ * ASN1_SEQUENCE(itname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END_name(stname, itname)
+ *
+ * This will create an item called itname_it using
+ * a structure called stname.
+ */
+
+#define ASN1_SEQUENCE(tname) \
+ static const ASN1_TEMPLATE tname##_seq_tt[]
+
+#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
+
+#define ASN1_SEQUENCE_END_name(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_NDEF_SEQUENCE(tname) \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+ ASN1_SEQUENCE_cb(tname, cb)
+
+#define ASN1_SEQUENCE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_ref(tname, cb, lck) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_enc(tname, enc, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(tname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
+
+#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_ref(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+
+/* This pair helps declare a CHOICE type. We can do:
+ *
+ * ASN1_CHOICE(chname) = {
+ * ... CHOICE options ...
+ * ASN1_CHOICE_END(chname)
+ *
+ * This will produce an ASN1_ITEM called chname_it
+ * for a structure called chname. The structure
+ * definition must look like this:
+ * typedef struct {
+ * int type;
+ * union {
+ * ASN1_SOMETHING *opt1;
+ * ASN1_SOMEOTHER *opt2;
+ * } value;
+ * } chname;
+ *
+ * the name of the selector must be 'type'.
+ * to use an alternative selector name use the
+ * ASN1_CHOICE_END_selector() version.
+ */
+
+#define ASN1_CHOICE(tname) \
+ static const ASN1_TEMPLATE tname##_ch_tt[]
+
+#define ASN1_CHOICE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+ ASN1_CHOICE(tname)
+
+#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
+
+#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
+
+#define ASN1_CHOICE_END_selector(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_CHOICE_END_cb(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+/* This helps with the template wrapper form of ASN1_ITEM */
+
+#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
+ (flags), (tag), 0,\
+ #name, ASN1_ITEM_ref(type) }
+
+/* These help with SEQUENCE or CHOICE components */
+
+/* used to declare other types */
+
+#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
+ (flags), (tag), offsetof(stname, field),\
+ #field, ASN1_ITEM_ref(type) }
+
+/* used when the structure is combined with the parent */
+
+#define ASN1_EX_COMBINE(flags, tag, type) { \
+ (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) }
+
+/* implicit and explicit helper macros */
+
+#define ASN1_IMP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type)
+
+#define ASN1_EXP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type)
+
+/* Any defined by macros: the field used is in the table itself */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#else
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
+#endif
+/* Plain simple type */
+#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
+
+/* OPTIONAL simple type */
+#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* IMPLICIT tagged simple type */
+#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
+
+/* IMPLICIT tagged OPTIONAL simple type */
+#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* Same as above but EXPLICIT */
+
+#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
+#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* SEQUENCE OF type */
+#define ASN1_SEQUENCE_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
+
+/* OPTIONAL SEQUENCE OF */
+#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Same as above but for SET OF */
+
+#define ASN1_SET_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
+
+#define ASN1_SET_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
+
+#define ASN1_IMP_SET_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_EXP_SET_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+/* EXPLICIT using indefinite length constructed form */
+#define ASN1_NDEF_EXP(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
+/* EXPLICIT OPTIONAL using indefinite length constructed form */
+#define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
+
+/* Macros for the ASN1_ADB structure */
+
+#define ASN1_ADB(name) \
+ static const ASN1_ADB_TABLE name##_adbtbl[]
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+ ;\
+ static const ASN1_ADB name##_adb = {\
+ flags,\
+ offsetof(name, field),\
+ app_table,\
+ name##_adbtbl,\
+ sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+ def,\
+ none\
+ }
+
+#else
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+ ;\
+ static const ASN1_ITEM *name##_adb(void) \
+ { \
+ static const ASN1_ADB internal_adb = \
+ {\
+ flags,\
+ offsetof(name, field),\
+ app_table,\
+ name##_adbtbl,\
+ sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+ def,\
+ none\
+ }; \
+ return (const ASN1_ITEM *) &internal_adb; \
+ } \
+ void dummy_function(void)
+
+#endif
+
+#define ADB_ENTRY(val, template) {val, template}
+
+#define ASN1_ADB_TEMPLATE(name) \
+ static const ASN1_TEMPLATE name##_tt
+
+/* This is the ASN1 template structure that defines
+ * a wrapper round the actual type. It determines the
+ * actual position of the field in the value structure,
+ * various flags such as OPTIONAL and the field name.
+ */
+
+struct ASN1_TEMPLATE_st {
+unsigned long flags; /* Various flags */
+long tag; /* tag, not used if no tagging */
+unsigned long offset; /* Offset of this field in structure */
+#ifndef NO_ASN1_FIELD_NAMES
+const char *field_name; /* Field name */
+#endif
+ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */
+};
+
+/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
+
+#define ASN1_TEMPLATE_item(t) (t->item_ptr)
+#define ASN1_TEMPLATE_adb(t) (t->item_ptr)
+
+typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
+typedef struct ASN1_ADB_st ASN1_ADB;
+
+struct ASN1_ADB_st {
+ unsigned long flags; /* Various flags */
+ unsigned long offset; /* Offset of selector field */
+ STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
+ const ASN1_ADB_TABLE *tbl; /* Table of possible types */
+ long tblcount; /* Number of entries in tbl */
+ const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
+ const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+ long value; /* NID for an object or value for an int */
+ const ASN1_TEMPLATE tt; /* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+#define ASN1_TFLG_OPTIONAL (0x1)
+
+/* Field is a SET OF */
+#define ASN1_TFLG_SET_OF (0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
+
+/* Special case: this refers to a SET OF that
+ * will be sorted into DER order when encoded *and*
+ * the corresponding STACK will be modified to match
+ * the new order.
+ */
+#define ASN1_TFLG_SET_ORDER (0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+#define ASN1_TFLG_SK_MASK (0x3 << 1)
+
+/* These flags mean the tag should be taken from the
+ * tag field. If EXPLICIT then the underlying type
+ * is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+#define ASN1_TFLG_IMPTAG (0x1 << 3)
+
+
+/* EXPLICIT tagging, inner tag from underlying type */
+#define ASN1_TFLG_EXPTAG (0x2 << 3)
+
+#define ASN1_TFLG_TAG_MASK (0x3 << 3)
+
+/* context specific IMPLICIT */
+#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
+
+/* context specific EXPLICIT */
+#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
+
+/* If tagging is in force these determine the
+ * type of tag to use. Otherwise the tag is
+ * determined by the underlying type. These
+ * values reflect the actual octet format.
+ */
+
+/* Universal tag */
+#define ASN1_TFLG_UNIVERSAL (0x0<<6)
+/* Application tag */
+#define ASN1_TFLG_APPLICATION (0x1<<6)
+/* Context specific tag */
+#define ASN1_TFLG_CONTEXT (0x2<<6)
+/* Private tag */
+#define ASN1_TFLG_PRIVATE (0x3<<6)
+
+#define ASN1_TFLG_TAG_CLASS (0x3<<6)
+
+/* These are for ANY DEFINED BY type. In this case
+ * the 'item' field points to an ASN1_ADB structure
+ * which contains a table of values to decode the
+ * relevant type
+ */
+
+#define ASN1_TFLG_ADB_MASK (0x3<<8)
+
+#define ASN1_TFLG_ADB_OID (0x1<<8)
+
+#define ASN1_TFLG_ADB_INT (0x1<<9)
+
+/* This flag means a parent structure is passed
+ * instead of the field: this is useful is a
+ * SEQUENCE is being combined with a CHOICE for
+ * example. Since this means the structure and
+ * item name will differ we need to use the
+ * ASN1_CHOICE_END_name() macro for example.
+ */
+
+#define ASN1_TFLG_COMBINE (0x1<<10)
+
+/* This flag when present in a SEQUENCE OF, SET OF
+ * or EXPLICIT causes indefinite length constructed
+ * encoding to be used if required.
+ */
+
+#define ASN1_TFLG_NDEF (0x1<<11)
+
+/* This is the actual ASN1 item itself */
+
+struct ASN1_ITEM_st {
+char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */
+long utype; /* underlying type */
+const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */
+long tcount; /* Number of templates if SEQUENCE or CHOICE */
+const void *funcs; /* functions that handle this type */
+long size; /* Structure size (usually)*/
+#ifndef NO_ASN1_FIELD_NAMES
+const char *sname; /* Structure name */
+#endif
+};
+
+/* These are values for the itype field and
+ * determine how the type is interpreted.
+ *
+ * For PRIMITIVE types the underlying type
+ * determines the behaviour if items is NULL.
+ *
+ * Otherwise templates must contain a single
+ * template and the type is treated in the
+ * same way as the type specified in the template.
+ *
+ * For SEQUENCE types the templates field points
+ * to the members, the size field is the
+ * structure size.
+ *
+ * For CHOICE types the templates field points
+ * to each possible member (typically a union)
+ * and the 'size' field is the offset of the
+ * selector.
+ *
+ * The 'funcs' field is used for application
+ * specific functions.
+ *
+ * For COMPAT types the funcs field gives a
+ * set of functions that handle this type, this
+ * supports the old d2i, i2d convention.
+ *
+ * The EXTERN type uses a new style d2i/i2d.
+ * The new style should be used where possible
+ * because it avoids things like the d2i IMPLICIT
+ * hack.
+ *
+ * MSTRING is a multiple string type, it is used
+ * for a CHOICE of character strings where the
+ * actual strings all occupy an ASN1_STRING
+ * structure. In this case the 'utype' field
+ * has a special meaning, it is used as a mask
+ * of acceptable types using the B_ASN1 constants.
+ *
+ * NDEF_SEQUENCE is the same as SEQUENCE except
+ * that it will use indefinite length constructed
+ * encoding if requested.
+ *
+ */
+
+#define ASN1_ITYPE_PRIMITIVE 0x0
+
+#define ASN1_ITYPE_SEQUENCE 0x1
+
+#define ASN1_ITYPE_CHOICE 0x2
+
+#define ASN1_ITYPE_COMPAT 0x3
+
+#define ASN1_ITYPE_EXTERN 0x4
+
+#define ASN1_ITYPE_MSTRING 0x5
+
+#define ASN1_ITYPE_NDEF_SEQUENCE 0x6
+
+/* Cache for ASN1 tag and length, so we
+ * don't keep re-reading it for things
+ * like CHOICE
+ */
+
+struct ASN1_TLC_st{
+ char valid; /* Values below are valid */
+ int ret; /* return value */
+ long plen; /* length */
+ int ptag; /* class value */
+ int pclass; /* class value */
+ int hdrlen; /* header length */
+};
+
+/* Typedefs for ASN1 function pointers */
+
+typedef ASN1_VALUE * ASN1_new_func(void);
+typedef void ASN1_free_func(ASN1_VALUE *a);
+typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length);
+typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in);
+
+typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+typedef struct ASN1_COMPAT_FUNCS_st {
+ ASN1_new_func *asn1_new;
+ ASN1_free_func *asn1_free;
+ ASN1_d2i_func *asn1_d2i;
+ ASN1_i2d_func *asn1_i2d;
+} ASN1_COMPAT_FUNCS;
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+ void *app_data;
+ ASN1_ex_new_func *asn1_ex_new;
+ ASN1_ex_free_func *asn1_ex_free;
+ ASN1_ex_free_func *asn1_ex_clear;
+ ASN1_ex_d2i *asn1_ex_d2i;
+ ASN1_ex_i2d *asn1_ex_i2d;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+ void *app_data;
+ unsigned long flags;
+ ASN1_ex_new_func *prim_new;
+ ASN1_ex_free_func *prim_free;
+ ASN1_ex_free_func *prim_clear;
+ ASN1_primitive_c2i *prim_c2i;
+ ASN1_primitive_i2c *prim_i2c;
+} ASN1_PRIMITIVE_FUNCS;
+
+/* This is the ASN1_AUX structure: it handles various
+ * miscellaneous requirements. For example the use of
+ * reference counts and an informational callback.
+ *
+ * The "informational callback" is called at various
+ * points during the ASN1 encoding and decoding. It can
+ * be used to provide minor customisation of the structures
+ * used. This is most useful where the supplied routines
+ * *almost* do the right thing but need some extra help
+ * at a few points. If the callback returns zero then
+ * it is assumed a fatal error has occurred and the
+ * main operation should be abandoned.
+ *
+ * If major changes in the default behaviour are required
+ * then an external type is more appropriate.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it);
+
+typedef struct ASN1_AUX_st {
+ void *app_data;
+ int flags;
+ int ref_offset; /* Offset of reference value */
+ int ref_lock; /* Lock type to use */
+ ASN1_aux_cb *asn1_cb;
+ int enc_offset; /* Offset of ASN1_ENCODING structure */
+} ASN1_AUX;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+#define ASN1_AFLG_REFCOUNT 1
+/* Save the encoding of structure (useful for signatures) */
+#define ASN1_AFLG_ENCODING 2
+/* The Sequence length is invalid */
+#define ASN1_AFLG_BROKEN 4
+
+/* operation values for asn1_cb */
+
+#define ASN1_OP_NEW_PRE 0
+#define ASN1_OP_NEW_POST 1
+#define ASN1_OP_FREE_PRE 2
+#define ASN1_OP_FREE_POST 3
+#define ASN1_OP_D2I_PRE 4
+#define ASN1_OP_D2I_POST 5
+#define ASN1_OP_I2D_PRE 6
+#define ASN1_OP_I2D_POST 7
+
+/* Macro to implement a primitive type */
+#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement an ASN1_ITEM in terms of old style funcs */
+
+#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
+
+#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
+ static const ASN1_COMPAT_FUNCS sname##_ff = { \
+ (ASN1_new_func *)sname##_new, \
+ (ASN1_free_func *)sname##_free, \
+ (ASN1_d2i_func *)d2i_##sname, \
+ (ASN1_i2d_func *)i2d_##sname, \
+ }; \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_COMPAT, \
+ tag, \
+ NULL, \
+ 0, \
+ &sname##_ff, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_EXTERN, \
+ tag, \
+ NULL, \
+ 0, \
+ &fptrs, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+/* Macro to implement standard functions in terms of ASN1_ITEM structures */
+
+#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
+ IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
+ stname *fname##_new(void) \
+ { \
+ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+ } \
+ void fname##_free(stname *a) \
+ { \
+ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+ }
+
+#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+ } \
+ int i2d_##fname(stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+ }
+
+#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
+ int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
+ }
+
+/* This includes evil casts to remove const: they will go away when full
+ * ASN1 constification is done.
+ */
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+ } \
+ int i2d_##fname(const stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+ }
+
+#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
+ stname * stname##_dup(stname *x) \
+ { \
+ return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+ }
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
+ IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+
+DECLARE_STACK_OF(ASN1_VALUE)
+
+/* Functions used internally by the ASN1 code */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt);
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it);
+
+ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr);
+
+int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+
+void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/bio.h b/src/Mayaqua/win32_inc/openssl/bio.h
new file mode 100644
index 00000000..dabd7862
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/bio.h
@@ -0,0 +1,791 @@
+/* crypto/bio/bio.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BIO_H
+#define HEADER_BIO_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+# include <stdio.h>
+#endif
+#include <stdarg.h>
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These are the 'types' of BIOs */
+#define BIO_TYPE_NONE 0
+#define BIO_TYPE_MEM (1|0x0400)
+#define BIO_TYPE_FILE (2|0x0400)
+
+#define BIO_TYPE_FD (4|0x0400|0x0100)
+#define BIO_TYPE_SOCKET (5|0x0400|0x0100)
+#define BIO_TYPE_NULL (6|0x0400)
+#define BIO_TYPE_SSL (7|0x0200)
+#define BIO_TYPE_MD (8|0x0200) /* passive filter */
+#define BIO_TYPE_BUFFER (9|0x0200) /* filter */
+#define BIO_TYPE_CIPHER (10|0x0200) /* filter */
+#define BIO_TYPE_BASE64 (11|0x0200) /* filter */
+#define BIO_TYPE_CONNECT (12|0x0400|0x0100) /* socket - connect */
+#define BIO_TYPE_ACCEPT (13|0x0400|0x0100) /* socket for accept */
+#define BIO_TYPE_PROXY_CLIENT (14|0x0200) /* client proxy BIO */
+#define BIO_TYPE_PROXY_SERVER (15|0x0200) /* server proxy BIO */
+#define BIO_TYPE_NBIO_TEST (16|0x0200) /* server proxy BIO */
+#define BIO_TYPE_NULL_FILTER (17|0x0200)
+#define BIO_TYPE_BER (18|0x0200) /* BER -> bin filter */
+#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
+#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
+#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
+#define BIO_TYPE_COMP (23|0x0200) /* filter */
+
+#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */
+#define BIO_TYPE_FILTER 0x0200
+#define BIO_TYPE_SOURCE_SINK 0x0400
+
+/* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
+ * BIO_set_fp(in,stdin,BIO_NOCLOSE); */
+#define BIO_NOCLOSE 0x00
+#define BIO_CLOSE 0x01
+
+/* These are used in the following macros and are passed to
+ * BIO_ctrl() */
+#define BIO_CTRL_RESET 1 /* opt - rewind/zero etc */
+#define BIO_CTRL_EOF 2 /* opt - are we at the eof */
+#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */
+#define BIO_CTRL_SET 4 /* man - set the 'IO' type */
+#define BIO_CTRL_GET 5 /* man - get the 'IO' type */
+#define BIO_CTRL_PUSH 6 /* opt - internal, used to signify change */
+#define BIO_CTRL_POP 7 /* opt - internal, used to signify change */
+#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */
+#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */
+#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */
+#define BIO_CTRL_FLUSH 11 /* opt - 'flush' buffered output */
+#define BIO_CTRL_DUP 12 /* man - extra stuff for 'duped' BIO */
+#define BIO_CTRL_WPENDING 13 /* opt - number of bytes still to write */
+/* callback is int cb(BIO *bio,state,ret); */
+#define BIO_CTRL_SET_CALLBACK 14 /* opt - set callback function */
+#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */
+
+#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */
+
+/* dgram BIO stuff */
+#define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */
+#define BIO_CTRL_DGRAM_SET_CONNECTED 32 /* allow for an externally
+ * connected socket to be
+ * passed in */
+#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */
+#define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */
+
+#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38 /* I/O operation tiemd out */
+
+/* #ifdef IP_MTU_DISCOVER */
+#define BIO_CTRL_DGRAM_MTU_DISCOVER 39 /* set DF bit on egress packets */
+/* #endif */
+
+#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */
+#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
+#define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */
+#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for
+ * MTU. want to use this
+ * if asking the kernel
+ * fails */
+
+#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU
+ * was exceed in the
+ * previous write
+ * operation */
+
+#define BIO_CTRL_DGRAM_GET_PEER 46
+#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */
+
+#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to
+ * adjust socket timeouts */
+
+/* modifiers */
+#define BIO_FP_READ 0x02
+#define BIO_FP_WRITE 0x04
+#define BIO_FP_APPEND 0x08
+#define BIO_FP_TEXT 0x10
+
+#define BIO_FLAGS_READ 0x01
+#define BIO_FLAGS_WRITE 0x02
+#define BIO_FLAGS_IO_SPECIAL 0x04
+#define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+#define BIO_FLAGS_SHOULD_RETRY 0x08
+#ifndef BIO_FLAGS_UPLINK
+/* "UPLINK" flag denotes file descriptors provided by application.
+ It defaults to 0, as most platforms don't require UPLINK interface. */
+#define BIO_FLAGS_UPLINK 0
+#endif
+
+/* Used in BIO_gethostbyname() */
+#define BIO_GHBN_CTRL_HITS 1
+#define BIO_GHBN_CTRL_MISSES 2
+#define BIO_GHBN_CTRL_CACHE_SIZE 3
+#define BIO_GHBN_CTRL_GET_ENTRY 4
+#define BIO_GHBN_CTRL_FLUSH 5
+
+/* Mostly used in the SSL BIO */
+/* Not used anymore
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20
+ * #define BIO_FLAGS_PROTOCOL_STARTUP 0x40
+ */
+
+#define BIO_FLAGS_BASE64_NO_NL 0x100
+
+/* This is used with memory BIOs: it means we shouldn't free up or change the
+ * data in any way.
+ */
+#define BIO_FLAGS_MEM_RDONLY 0x200
+
+typedef struct bio_st BIO;
+
+void BIO_set_flags(BIO *b, int flags);
+int BIO_test_flags(const BIO *b, int flags);
+void BIO_clear_flags(BIO *b, int flags);
+
+#define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
+#define BIO_set_retry_special(b) \
+ BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_read(b) \
+ BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_write(b) \
+ BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+#define BIO_clear_retry_flags(b) \
+ BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_get_retry_flags(b) \
+ BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+/* These should be used by the application to tell why we should retry */
+#define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ)
+#define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE)
+#define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
+#define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS)
+#define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
+
+/* The next three are used in conjunction with the
+ * BIO_should_io_special() condition. After this returns true,
+ * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO
+ * stack and return the 'reason' for the special and the offending BIO.
+ * Given a BIO, BIO_get_retry_reason(bio) will return the code. */
+/* Returned from the SSL bio when the certificate retrieval code had an error */
+#define BIO_RR_SSL_X509_LOOKUP 0x01
+/* Returned from the connect BIO when a connect would have blocked */
+#define BIO_RR_CONNECT 0x02
+/* Returned from the accept BIO when an accept would have blocked */
+#define BIO_RR_ACCEPT 0x03
+
+/* These are passed by the BIO callback */
+#define BIO_CB_FREE 0x01
+#define BIO_CB_READ 0x02
+#define BIO_CB_WRITE 0x03
+#define BIO_CB_PUTS 0x04
+#define BIO_CB_GETS 0x05
+#define BIO_CB_CTRL 0x06
+
+/* The callback is called before and after the underling operation,
+ * The BIO_CB_RETURN flag indicates if it is after the call */
+#define BIO_CB_RETURN 0x80
+#define BIO_CB_return(a) ((a)|BIO_CB_RETURN))
+#define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN))
+#define BIO_cb_post(a) ((a)&BIO_CB_RETURN)
+
+long (*BIO_get_callback(const BIO *b)) (struct bio_st *,int,const char *,int, long,long);
+void BIO_set_callback(BIO *b,
+ long (*callback)(struct bio_st *,int,const char *,int, long,long));
+char *BIO_get_callback_arg(const BIO *b);
+void BIO_set_callback_arg(BIO *b, char *arg);
+
+const char * BIO_method_name(const BIO *b);
+int BIO_method_type(const BIO *b);
+
+typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long);
+
+#ifndef OPENSSL_SYS_WIN16
+typedef struct bio_method_st
+ {
+ int type;
+ const char *name;
+ int (*bwrite)(BIO *, const char *, int);
+ int (*bread)(BIO *, char *, int);
+ int (*bputs)(BIO *, const char *);
+ int (*bgets)(BIO *, char *, int);
+ long (*ctrl)(BIO *, int, long, void *);
+ int (*create)(BIO *);
+ int (*destroy)(BIO *);
+ long (*callback_ctrl)(BIO *, int, bio_info_cb *);
+ } BIO_METHOD;
+#else
+typedef struct bio_method_st
+ {
+ int type;
+ const char *name;
+ int (_far *bwrite)();
+ int (_far *bread)();
+ int (_far *bputs)();
+ int (_far *bgets)();
+ long (_far *ctrl)();
+ int (_far *create)();
+ int (_far *destroy)();
+ long (_far *callback_ctrl)();
+ } BIO_METHOD;
+#endif
+
+struct bio_st
+ {
+ BIO_METHOD *method;
+ /* bio, mode, argp, argi, argl, ret */
+ long (*callback)(struct bio_st *,int,const char *,int, long,long);
+ char *cb_arg; /* first argument for the callback */
+
+ int init;
+ int shutdown;
+ int flags; /* extra storage */
+ int retry_reason;
+ int num;
+ void *ptr;
+ struct bio_st *next_bio; /* used by filter BIOs */
+ struct bio_st *prev_bio; /* used by filter BIOs */
+ int references;
+ unsigned long num_read;
+ unsigned long num_write;
+
+ CRYPTO_EX_DATA ex_data;
+ };
+
+DECLARE_STACK_OF(BIO)
+
+typedef struct bio_f_buffer_ctx_struct
+ {
+ /* Buffers are setup like this:
+ *
+ * <---------------------- size ----------------------->
+ * +---------------------------------------------------+
+ * | consumed | remaining | free space |
+ * +---------------------------------------------------+
+ * <-- off --><------- len ------->
+ */
+
+ /* BIO *bio; */ /* this is now in the BIO struct */
+ int ibuf_size; /* how big is the input buffer */
+ int obuf_size; /* how big is the output buffer */
+
+ char *ibuf; /* the char array */
+ int ibuf_len; /* how many bytes are in it */
+ int ibuf_off; /* write/read offset */
+
+ char *obuf; /* the char array */
+ int obuf_len; /* how many bytes are in it */
+ int obuf_off; /* write/read offset */
+ } BIO_F_BUFFER_CTX;
+
+/* connect BIO stuff */
+#define BIO_CONN_S_BEFORE 1
+#define BIO_CONN_S_GET_IP 2
+#define BIO_CONN_S_GET_PORT 3
+#define BIO_CONN_S_CREATE_SOCKET 4
+#define BIO_CONN_S_CONNECT 5
+#define BIO_CONN_S_OK 6
+#define BIO_CONN_S_BLOCKED_CONNECT 7
+#define BIO_CONN_S_NBIO 8
+/*#define BIO_CONN_get_param_hostname BIO_ctrl */
+
+#define BIO_C_SET_CONNECT 100
+#define BIO_C_DO_STATE_MACHINE 101
+#define BIO_C_SET_NBIO 102
+#define BIO_C_SET_PROXY_PARAM 103
+#define BIO_C_SET_FD 104
+#define BIO_C_GET_FD 105
+#define BIO_C_SET_FILE_PTR 106
+#define BIO_C_GET_FILE_PTR 107
+#define BIO_C_SET_FILENAME 108
+#define BIO_C_SET_SSL 109
+#define BIO_C_GET_SSL 110
+#define BIO_C_SET_MD 111
+#define BIO_C_GET_MD 112
+#define BIO_C_GET_CIPHER_STATUS 113
+#define BIO_C_SET_BUF_MEM 114
+#define BIO_C_GET_BUF_MEM_PTR 115
+#define BIO_C_GET_BUFF_NUM_LINES 116
+#define BIO_C_SET_BUFF_SIZE 117
+#define BIO_C_SET_ACCEPT 118
+#define BIO_C_SSL_MODE 119
+#define BIO_C_GET_MD_CTX 120
+#define BIO_C_GET_PROXY_PARAM 121
+#define BIO_C_SET_BUFF_READ_DATA 122 /* data to read first */
+#define BIO_C_GET_CONNECT 123
+#define BIO_C_GET_ACCEPT 124
+#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125
+#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126
+#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
+#define BIO_C_FILE_SEEK 128
+#define BIO_C_GET_CIPHER_CTX 129
+#define BIO_C_SET_BUF_MEM_EOF_RETURN 130/*return end of input value*/
+#define BIO_C_SET_BIND_MODE 131
+#define BIO_C_GET_BIND_MODE 132
+#define BIO_C_FILE_TELL 133
+#define BIO_C_GET_SOCKS 134
+#define BIO_C_SET_SOCKS 135
+
+#define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */
+#define BIO_C_GET_WRITE_BUF_SIZE 137
+#define BIO_C_MAKE_BIO_PAIR 138
+#define BIO_C_DESTROY_BIO_PAIR 139
+#define BIO_C_GET_WRITE_GUARANTEE 140
+#define BIO_C_GET_READ_REQUEST 141
+#define BIO_C_SHUTDOWN_WR 142
+#define BIO_C_NREAD0 143
+#define BIO_C_NREAD 144
+#define BIO_C_NWRITE0 145
+#define BIO_C_NWRITE 146
+#define BIO_C_RESET_READ_REQUEST 147
+#define BIO_C_SET_MD_CTX 148
+
+
+#define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
+#define BIO_get_app_data(s) BIO_get_ex_data(s,0)
+
+/* BIO_s_connect() and BIO_s_socks4a_connect() */
+#define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name)
+#define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
+#define BIO_set_conn_ip(b,ip) BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
+#define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port)
+#define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
+#define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
+#define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
+#define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0)
+
+
+#define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
+
+/* BIO_s_accept_socket() */
+#define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
+#define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
+/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
+#define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?(void *)"a":NULL)
+#define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio)
+
+#define BIO_BIND_NORMAL 0
+#define BIO_BIND_REUSEADDR_IF_UNUSED 1
+#define BIO_BIND_REUSEADDR 2
+#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+
+#define BIO_do_connect(b) BIO_do_handshake(b)
+#define BIO_do_accept(b) BIO_do_handshake(b)
+#define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
+
+/* BIO_s_proxy_client() */
+#define BIO_set_url(b,url) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url))
+#define BIO_set_proxies(b,p) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p))
+/* BIO_set_nbio(b,n) */
+#define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s))
+/* BIO *BIO_get_filter_bio(BIO *bio); */
+#define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)()))
+#define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk)
+#define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool)
+
+#define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp)
+#define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p))
+#define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
+#define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+
+#define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
+#define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+
+#define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
+#define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+
+#define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+#define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
+/* name is cast to lose const, but might be better to route through a function
+ so we can do it safely */
+#ifdef CONST_STRICT
+/* If you are wondering why this isn't defined, its because CONST_STRICT is
+ * purely a compile-time kludge to allow const to be checked.
+ */
+int BIO_read_filename(BIO *b,const char *name);
+#else
+#define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ,(char *)name)
+#endif
+#define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_WRITE,name)
+#define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_APPEND,name)
+#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
+
+/* WARNING WARNING, this ups the reference count on the read bio of the
+ * SSL structure. This is because the ssl read BIO is now pointed to by
+ * the next_bio field in the bio. So when you free the BIO, make sure
+ * you are doing a BIO_free_all() to catch the underlying BIO. */
+#define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl)
+#define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp)
+#define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
+#define BIO_set_ssl_renegotiate_bytes(b,num) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL);
+#define BIO_get_num_renegotiates(b) \
+ BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL);
+#define BIO_set_ssl_renegotiate_timeout(b,seconds) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL);
+
+/* defined in evp.h */
+/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */
+
+#define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+#define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm)
+#define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp)
+#define BIO_set_mem_eof_return(b,v) \
+ BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
+
+/* For the BIO_f_buffer() type */
+#define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
+#define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
+#define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
+#define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
+#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
+
+/* Don't use the next one unless you know what you are doing :-) */
+#define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
+
+#define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
+#define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
+#define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
+#define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
+#define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+#define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
+/* ...pending macros have inappropriate return type */
+size_t BIO_ctrl_pending(BIO *b);
+size_t BIO_ctrl_wpending(BIO *b);
+#define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
+#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
+ cbp)
+#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
+
+/* For the BIO_f_buffer() type */
+#define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
+
+/* For BIO_s_bio() */
+#define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
+#define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
+#define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
+/* macros with inappropriate type -- but ...pending macros use int too: */
+#define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
+#define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
+size_t BIO_ctrl_get_write_guarantee(BIO *b);
+size_t BIO_ctrl_get_read_request(BIO *b);
+int BIO_ctrl_reset_read_request(BIO *b);
+
+/* ctrl macros for dgram */
+#define BIO_ctrl_dgram_connect(b,peer) \
+ (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer)
+#define BIO_ctrl_set_connected(b, state, peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer)
+#define BIO_dgram_recv_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
+#define BIO_dgram_send_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
+#define BIO_dgram_get_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer)
+#define BIO_dgram_set_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+
+/* These two aren't currently implemented */
+/* int BIO_get_ex_num(BIO *bio); */
+/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */
+int BIO_set_ex_data(BIO *bio,int idx,void *data);
+void *BIO_get_ex_data(BIO *bio,int idx);
+int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+unsigned long BIO_number_read(BIO *bio);
+unsigned long BIO_number_written(BIO *bio);
+
+# ifndef OPENSSL_NO_FP_API
+# if defined(OPENSSL_SYS_WIN16) && defined(_WINDLL)
+BIO_METHOD *BIO_s_file_internal(void);
+BIO *BIO_new_file_internal(char *filename, char *mode);
+BIO *BIO_new_fp_internal(FILE *stream, int close_flag);
+# define BIO_s_file BIO_s_file_internal
+# define BIO_new_file BIO_new_file_internal
+# define BIO_new_fp BIO_new_fp_internal
+# else /* FP_API */
+BIO_METHOD *BIO_s_file(void );
+BIO *BIO_new_file(const char *filename, const char *mode);
+BIO *BIO_new_fp(FILE *stream, int close_flag);
+# define BIO_s_file_internal BIO_s_file
+# define BIO_new_file_internal BIO_new_file
+# define BIO_new_fp_internal BIO_s_file
+# endif /* FP_API */
+# endif
+BIO * BIO_new(BIO_METHOD *type);
+int BIO_set(BIO *a,BIO_METHOD *type);
+int BIO_free(BIO *a);
+void BIO_vfree(BIO *a);
+int BIO_read(BIO *b, void *data, int len);
+int BIO_gets(BIO *bp,char *buf, int size);
+int BIO_write(BIO *b, const void *data, int len);
+int BIO_puts(BIO *bp,const char *buf);
+int BIO_indent(BIO *b,int indent,int max);
+long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg);
+long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long));
+char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg);
+long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg);
+BIO * BIO_push(BIO *b,BIO *append);
+BIO * BIO_pop(BIO *b);
+void BIO_free_all(BIO *a);
+BIO * BIO_find_type(BIO *b,int bio_type);
+BIO * BIO_next(BIO *b);
+BIO * BIO_get_retry_BIO(BIO *bio, int *reason);
+int BIO_get_retry_reason(BIO *bio);
+BIO * BIO_dup_chain(BIO *in);
+
+int BIO_nread0(BIO *bio, char **buf);
+int BIO_nread(BIO *bio, char **buf, int num);
+int BIO_nwrite0(BIO *bio, char **buf);
+int BIO_nwrite(BIO *bio, char **buf, int num);
+
+#ifndef OPENSSL_SYS_WIN16
+long BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+ long argl,long ret);
+#else
+long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+ long argl,long ret);
+#endif
+
+BIO_METHOD *BIO_s_mem(void);
+BIO *BIO_new_mem_buf(void *buf, int len);
+BIO_METHOD *BIO_s_socket(void);
+BIO_METHOD *BIO_s_connect(void);
+BIO_METHOD *BIO_s_accept(void);
+BIO_METHOD *BIO_s_fd(void);
+#ifndef OPENSSL_SYS_OS2
+BIO_METHOD *BIO_s_log(void);
+#endif
+BIO_METHOD *BIO_s_bio(void);
+BIO_METHOD *BIO_s_null(void);
+BIO_METHOD *BIO_f_null(void);
+BIO_METHOD *BIO_f_buffer(void);
+#ifdef OPENSSL_SYS_VMS
+BIO_METHOD *BIO_f_linebuffer(void);
+#endif
+BIO_METHOD *BIO_f_nbio_test(void);
+#ifndef OPENSSL_NO_DGRAM
+BIO_METHOD *BIO_s_datagram(void);
+#endif
+
+/* BIO_METHOD *BIO_f_ber(void); */
+
+int BIO_sock_should_retry(int i);
+int BIO_sock_non_fatal_error(int error);
+int BIO_dgram_non_fatal_error(int error);
+
+int BIO_fd_should_retry(int i);
+int BIO_fd_non_fatal_error(int error);
+int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
+ void *u, const char *s, int len);
+int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
+ void *u, const char *s, int len, int indent);
+int BIO_dump(BIO *b,const char *bytes,int len);
+int BIO_dump_indent(BIO *b,const char *bytes,int len,int indent);
+#ifndef OPENSSL_NO_FP_API
+int BIO_dump_fp(FILE *fp, const char *s, int len);
+int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
+#endif
+struct hostent *BIO_gethostbyname(const char *name);
+/* We might want a thread-safe interface too:
+ * struct hostent *BIO_gethostbyname_r(const char *name,
+ * struct hostent *result, void *buffer, size_t buflen);
+ * or something similar (caller allocates a struct hostent,
+ * pointed to by "result", and additional buffer space for the various
+ * substructures; if the buffer does not suffice, NULL is returned
+ * and an appropriate error code is set).
+ */
+int BIO_sock_error(int sock);
+int BIO_socket_ioctl(int fd, long type, void *arg);
+int BIO_socket_nbio(int fd,int mode);
+int BIO_get_port(const char *str, unsigned short *port_ptr);
+int BIO_get_host_ip(const char *str, unsigned char *ip);
+int BIO_get_accept_socket(char *host_port,int mode);
+int BIO_accept(int sock,char **ip_port);
+int BIO_sock_init(void );
+void BIO_sock_cleanup(void);
+int BIO_set_tcp_ndelay(int sock,int turn_on);
+
+BIO *BIO_new_socket(int sock, int close_flag);
+BIO *BIO_new_dgram(int fd, int close_flag);
+BIO *BIO_new_fd(int fd, int close_flag);
+BIO *BIO_new_connect(char *host_port);
+BIO *BIO_new_accept(char *host_port);
+
+int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
+ BIO **bio2, size_t writebuf2);
+/* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
+ * Otherwise returns 0 and sets *bio1 and *bio2 to NULL.
+ * Size 0 uses default value.
+ */
+
+void BIO_copy_next_retry(BIO *b);
+
+/*long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);*/
+
+#ifdef __GNUC__
+# define __bio_h__attr__ __attribute__
+#else
+# define __bio_h__attr__(x)
+#endif
+int BIO_printf(BIO *bio, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__,2,3)));
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+ __bio_h__attr__((__format__(__printf__,2,0)));
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__,3,4)));
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+ __bio_h__attr__((__format__(__printf__,3,0)));
+#undef __bio_h__attr__
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BIO_strings(void);
+
+/* Error codes for the BIO functions. */
+
+/* Function codes. */
+#define BIO_F_ACPT_STATE 100
+#define BIO_F_BIO_ACCEPT 101
+#define BIO_F_BIO_BER_GET_HEADER 102
+#define BIO_F_BIO_CALLBACK_CTRL 131
+#define BIO_F_BIO_CTRL 103
+#define BIO_F_BIO_GETHOSTBYNAME 120
+#define BIO_F_BIO_GETS 104
+#define BIO_F_BIO_GET_ACCEPT_SOCKET 105
+#define BIO_F_BIO_GET_HOST_IP 106
+#define BIO_F_BIO_GET_PORT 107
+#define BIO_F_BIO_MAKE_PAIR 121
+#define BIO_F_BIO_NEW 108
+#define BIO_F_BIO_NEW_FILE 109
+#define BIO_F_BIO_NEW_MEM_BUF 126
+#define BIO_F_BIO_NREAD 123
+#define BIO_F_BIO_NREAD0 124
+#define BIO_F_BIO_NWRITE 125
+#define BIO_F_BIO_NWRITE0 122
+#define BIO_F_BIO_PUTS 110
+#define BIO_F_BIO_READ 111
+#define BIO_F_BIO_SOCK_INIT 112
+#define BIO_F_BIO_WRITE 113
+#define BIO_F_BUFFER_CTRL 114
+#define BIO_F_CONN_CTRL 127
+#define BIO_F_CONN_STATE 115
+#define BIO_F_FILE_CTRL 116
+#define BIO_F_FILE_READ 130
+#define BIO_F_LINEBUFFER_CTRL 129
+#define BIO_F_MEM_READ 128
+#define BIO_F_MEM_WRITE 117
+#define BIO_F_SSL_NEW 118
+#define BIO_F_WSASTARTUP 119
+
+/* Reason codes. */
+#define BIO_R_ACCEPT_ERROR 100
+#define BIO_R_BAD_FOPEN_MODE 101
+#define BIO_R_BAD_HOSTNAME_LOOKUP 102
+#define BIO_R_BROKEN_PIPE 124
+#define BIO_R_CONNECT_ERROR 103
+#define BIO_R_EOF_ON_MEMORY_BIO 127
+#define BIO_R_ERROR_SETTING_NBIO 104
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET 106
+#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
+#define BIO_R_INVALID_ARGUMENT 125
+#define BIO_R_INVALID_IP_ADDRESS 108
+#define BIO_R_IN_USE 123
+#define BIO_R_KEEPALIVE 109
+#define BIO_R_NBIO_CONNECT_ERROR 110
+#define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111
+#define BIO_R_NO_HOSTNAME_SPECIFIED 112
+#define BIO_R_NO_PORT_DEFINED 113
+#define BIO_R_NO_PORT_SPECIFIED 114
+#define BIO_R_NO_SUCH_FILE 128
+#define BIO_R_NULL_PARAMETER 115
+#define BIO_R_TAG_MISMATCH 116
+#define BIO_R_UNABLE_TO_BIND_SOCKET 117
+#define BIO_R_UNABLE_TO_CREATE_SOCKET 118
+#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
+#define BIO_R_UNINITIALIZED 120
+#define BIO_R_UNSUPPORTED_METHOD 121
+#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
+#define BIO_R_WSASTARTUP 122
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/blowfish.h b/src/Mayaqua/win32_inc/openssl/blowfish.h
new file mode 100644
index 00000000..832a97dd
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/blowfish.h
@@ -0,0 +1,129 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+#define HEADER_BLOWFISH_H
+
+#include <openssl/e_os2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_BF
+#error BF is disabled.
+#endif
+
+#define BF_ENCRYPT 1
+#define BF_DECRYPT 0
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define BF_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define BF_LONG unsigned long
+#define BF_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define BF_LONG unsigned int
+#endif
+
+#define BF_ROUNDS 16
+#define BF_BLOCK 8
+
+typedef struct bf_key_st
+ {
+ BF_LONG P[BF_ROUNDS+2];
+ BF_LONG S[4*256];
+ } BF_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+#endif
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+
+void BF_encrypt(BF_LONG *data,const BF_KEY *key);
+void BF_decrypt(BF_LONG *data,const BF_KEY *key);
+
+void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ const BF_KEY *key, int enc);
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int enc);
+void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int *num);
+const char *BF_options(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/bn.h b/src/Mayaqua/win32_inc/openssl/bn.h
new file mode 100644
index 00000000..dd9cd3eb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/bn.h
@@ -0,0 +1,855 @@
+/* crypto/bn/bn.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_BN_H
+#define HEADER_BN_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h> /* FILE */
+#endif
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These preprocessor symbols control various aspects of the bignum headers and
+ * library code. They're not defined by any "normal" configuration, as they are
+ * intended for development and testing purposes. NB: defining all three can be
+ * useful for debugging application code as well as openssl itself.
+ *
+ * BN_DEBUG - turn on various debugging alterations to the bignum code
+ * BN_DEBUG_RAND - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. You must also define BN_DEBUG.
+ */
+/* #define BN_DEBUG */
+/* #define BN_DEBUG_RAND */
+
+#define BN_MUL_COMBA
+#define BN_SQR_COMBA
+#define BN_RECURSION
+
+/* This next option uses the C libraries (2 word)/(1 word) function.
+ * If it is not defined, I use my C version (which is slower).
+ * The reason for this flag is that when the particular C compiler
+ * library routine is used, and the library is linked with a different
+ * compiler, the library is missing. This mostly happens when the
+ * library is built with gcc and then linked using normal cc. This would
+ * be a common occurrence because gcc normally produces code that is
+ * 2 times faster than system compilers for the big number stuff.
+ * For machines with only one compiler (or shared libraries), this should
+ * be on. Again this in only really a problem on machines
+ * using "long long's", are 32bit, and are not using my assembler code. */
+#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \
+ defined(OPENSSL_SYS_WIN32) || defined(linux)
+# ifndef BN_DIV2W
+# define BN_DIV2W
+# endif
+#endif
+
+/* assuming long is 64bit - this is the DEC Alpha
+ * unsigned long long is only 64 bits :-(, don't define
+ * BN_LLONG for the DEC Alpha */
+#ifdef SIXTY_FOUR_BIT_LONG
+#define BN_ULLONG unsigned long long
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
+#define BN_MASK2 (0xffffffffffffffffL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000L)
+#define BN_MASK2h1 (0xffffffff80000000L)
+#define BN_TBIT (0x8000000000000000L)
+#define BN_DEC_CONV (10000000000000000000UL)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%019lu"
+#define BN_DEC_NUM 19
+#endif
+
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevant
+ * assembler code :-). Do NOT define BN_LLONG.
+ */
+#ifdef SIXTY_FOUR_BIT
+#undef BN_LLONG
+#undef BN_ULLONG
+#define BN_ULONG unsigned long long
+#define BN_LONG long long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK2 (0xffffffffffffffffLL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000LL)
+#define BN_MASK2h1 (0xffffffff80000000LL)
+#define BN_TBIT (0x8000000000000000LL)
+#define BN_DEC_CONV (10000000000000000000ULL)
+#define BN_DEC_FMT1 "%llu"
+#define BN_DEC_FMT2 "%019llu"
+#define BN_DEC_NUM 19
+#endif
+
+#ifdef THIRTY_TWO_BIT
+#ifdef BN_LLONG
+# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
+# define BN_ULLONG unsigned __int64
+# else
+# define BN_ULLONG unsigned long long
+# endif
+#endif
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 64
+#define BN_BYTES 4
+#define BN_BITS2 32
+#define BN_BITS4 16
+#ifdef OPENSSL_SYS_WIN32
+/* VC++ doesn't like the LL suffix */
+#define BN_MASK (0xffffffffffffffffL)
+#else
+#define BN_MASK (0xffffffffffffffffLL)
+#endif
+#define BN_MASK2 (0xffffffffL)
+#define BN_MASK2l (0xffff)
+#define BN_MASK2h1 (0xffff8000L)
+#define BN_MASK2h (0xffff0000L)
+#define BN_TBIT (0x80000000L)
+#define BN_DEC_CONV (1000000000L)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%09lu"
+#define BN_DEC_NUM 9
+#endif
+
+#ifdef SIXTEEN_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned long
+#define BN_ULONG unsigned short
+#define BN_LONG short
+#define BN_BITS 32
+#define BN_BYTES 2
+#define BN_BITS2 16
+#define BN_BITS4 8
+#define BN_MASK (0xffffffff)
+#define BN_MASK2 (0xffff)
+#define BN_MASK2l (0xff)
+#define BN_MASK2h1 (0xff80)
+#define BN_MASK2h (0xff00)
+#define BN_TBIT (0x8000)
+#define BN_DEC_CONV (100000)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%05u"
+#define BN_DEC_NUM 5
+#endif
+
+#ifdef EIGHT_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned short
+#define BN_ULONG unsigned char
+#define BN_LONG char
+#define BN_BITS 16
+#define BN_BYTES 1
+#define BN_BITS2 8
+#define BN_BITS4 4
+#define BN_MASK (0xffff)
+#define BN_MASK2 (0xff)
+#define BN_MASK2l (0xf)
+#define BN_MASK2h1 (0xf8)
+#define BN_MASK2h (0xf0)
+#define BN_TBIT (0x80)
+#define BN_DEC_CONV (100)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%02u"
+#define BN_DEC_NUM 2
+#endif
+
+#define BN_DEFAULT_BITS 1280
+
+#define BN_FLG_MALLOCED 0x01
+#define BN_FLG_STATIC_DATA 0x02
+#define BN_FLG_CONSTTIME 0x04 /* avoid leaking exponent information through timing,
+ * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime,
+ * BN_div() will call BN_div_no_branch,
+ * BN_mod_inverse() will call BN_mod_inverse_no_branch.
+ */
+
+#ifndef OPENSSL_NO_DEPRECATED
+#define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME /* deprecated name for the flag */
+ /* avoid leaking exponent information through timings
+ * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#define BN_FLG_FREE 0x8000 /* used for debuging */
+#endif
+#define BN_set_flags(b,n) ((b)->flags|=(n))
+#define BN_get_flags(b,n) ((b)->flags&(n))
+
+/* get a clone of a BIGNUM with changed flags, for *temporary* use only
+ * (the two BIGNUMs cannot not be used in parallel!) */
+#define BN_with_flags(dest,b,n) ((dest)->d=(b)->d, \
+ (dest)->top=(b)->top, \
+ (dest)->dmax=(b)->dmax, \
+ (dest)->neg=(b)->neg, \
+ (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \
+ | ((b)->flags & ~BN_FLG_MALLOCED) \
+ | BN_FLG_STATIC_DATA \
+ | (n)))
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct bignum_st BIGNUM;
+/* Used for temp variables (declaration hidden in bn_lcl.h) */
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+#endif
+
+struct bignum_st
+ {
+ BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
+ int top; /* Index of last used d +1. */
+ /* The next are internal book keeping for bn_expand. */
+ int dmax; /* Size of the d array. */
+ int neg; /* one if the number is negative */
+ int flags;
+ };
+
+/* Used for montgomery multiplication */
+struct bn_mont_ctx_st
+ {
+ int ri; /* number of bits in R */
+ BIGNUM RR; /* used to convert to montgomery form */
+ BIGNUM N; /* The modulus */
+ BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
+ * (Ni is only stored for bignum algorithm) */
+#if 0
+ /* OpenSSL 0.9.9 preview: */
+ BN_ULONG n0[2];/* least significant word(s) of Ni */
+#else
+ BN_ULONG n0; /* least significant word of Ni */
+#endif
+ int flags;
+ };
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+struct bn_recp_ctx_st
+ {
+ BIGNUM N; /* the divisor */
+ BIGNUM Nr; /* the reciprocal */
+ int num_bits;
+ int shift;
+ int flags;
+ };
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st
+ {
+ unsigned int ver; /* To handle binary (in)compatibility */
+ void *arg; /* callback-specific data */
+ union
+ {
+ /* if(ver==1) - handles old style callbacks */
+ void (*cb_1)(int, int, void *);
+ /* if(ver==2) - new callback style */
+ int (*cb_2)(int, int, BN_GENCB *);
+ } cb;
+ };
+/* Wrapper function to make using BN_GENCB easier, */
+int BN_GENCB_call(BN_GENCB *cb, int a, int b);
+/* Macro to populate a BN_GENCB structure with an "old"-style callback */
+#define BN_GENCB_set_old(gencb, callback, cb_arg) { \
+ BN_GENCB *tmp_gencb = (gencb); \
+ tmp_gencb->ver = 1; \
+ tmp_gencb->arg = (cb_arg); \
+ tmp_gencb->cb.cb_1 = (callback); }
+/* Macro to populate a BN_GENCB structure with a "new"-style callback */
+#define BN_GENCB_set(gencb, callback, cb_arg) { \
+ BN_GENCB *tmp_gencb = (gencb); \
+ tmp_gencb->ver = 2; \
+ tmp_gencb->arg = (cb_arg); \
+ tmp_gencb->cb.cb_2 = (callback); }
+
+#define BN_prime_checks 0 /* default: select number of iterations
+ based on the size of the number */
+
+/* number of Miller-Rabin iterations for an error rate of less than 2^-80
+ * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
+ * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
+ * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
+ * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
+#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
+ (b) >= 850 ? 3 : \
+ (b) >= 650 ? 4 : \
+ (b) >= 550 ? 5 : \
+ (b) >= 450 ? 6 : \
+ (b) >= 400 ? 7 : \
+ (b) >= 350 ? 8 : \
+ (b) >= 300 ? 9 : \
+ (b) >= 250 ? 12 : \
+ (b) >= 200 ? 15 : \
+ (b) >= 150 ? 18 : \
+ /* b >= 100 */ 27)
+
+#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
+
+/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */
+#define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \
+ (((w) == 0) && ((a)->top == 0)))
+#define BN_is_zero(a) ((a)->top == 0)
+#define BN_is_one(a) (BN_abs_is_word((a),1) && !(a)->neg)
+#define BN_is_word(a,w) (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg))
+#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1))
+
+#define BN_one(a) (BN_set_word((a),1))
+#define BN_zero_ex(a) \
+ do { \
+ BIGNUM *_tmp_bn = (a); \
+ _tmp_bn->top = 0; \
+ _tmp_bn->neg = 0; \
+ } while(0)
+#ifdef OPENSSL_NO_DEPRECATED
+#define BN_zero(a) BN_zero_ex(a)
+#else
+#define BN_zero(a) (BN_set_word((a),0))
+#endif
+
+const BIGNUM *BN_value_one(void);
+char * BN_options(void);
+BN_CTX *BN_CTX_new(void);
+#ifndef OPENSSL_NO_DEPRECATED
+void BN_CTX_init(BN_CTX *c);
+#endif
+void BN_CTX_free(BN_CTX *c);
+void BN_CTX_start(BN_CTX *ctx);
+BIGNUM *BN_CTX_get(BN_CTX *ctx);
+void BN_CTX_end(BN_CTX *ctx);
+int BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_num_bits(const BIGNUM *a);
+int BN_num_bits_word(BN_ULONG);
+BIGNUM *BN_new(void);
+void BN_init(BIGNUM *);
+void BN_clear_free(BIGNUM *a);
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+void BN_swap(BIGNUM *a, BIGNUM *b);
+BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
+int BN_bn2bin(const BIGNUM *a, unsigned char *to);
+BIGNUM *BN_mpi2bn(const unsigned char *s,int len,BIGNUM *ret);
+int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
+/** BN_set_negative sets sign of a BIGNUM
+ * \param b pointer to the BIGNUM object
+ * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise
+ */
+void BN_set_negative(BIGNUM *b, int n);
+/** BN_is_negative returns 1 if the BIGNUM is negative
+ * \param a pointer to the BIGNUM object
+ * \return 1 if a < 0 and 0 otherwise
+ */
+#define BN_is_negative(a) ((a)->neg != 0)
+
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+ BN_CTX *ctx);
+#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);
+
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int BN_mul_word(BIGNUM *a, BN_ULONG w);
+int BN_add_word(BIGNUM *a, BN_ULONG w);
+int BN_sub_word(BIGNUM *a, BN_ULONG w);
+int BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(const BIGNUM *a);
+
+int BN_cmp(const BIGNUM *a, const BIGNUM *b);
+void BN_free(BIGNUM *a);
+int BN_is_bit_set(const BIGNUM *a, int n);
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_lshift1(BIGNUM *r, const BIGNUM *a);
+int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,BN_CTX *ctx);
+
+int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont);
+int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
+ const BIGNUM *a2, const BIGNUM *p2,const BIGNUM *m,
+ BN_CTX *ctx,BN_MONT_CTX *m_ctx);
+int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+
+int BN_mask_bits(BIGNUM *a,int n);
+#ifndef OPENSSL_NO_FP_API
+int BN_print_fp(FILE *fp, const BIGNUM *a);
+#endif
+#ifdef HEADER_BIO_H
+int BN_print(BIO *fp, const BIGNUM *a);
+#else
+int BN_print(void *fp, const BIGNUM *a);
+#endif
+int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
+int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_rshift1(BIGNUM *r, const BIGNUM *a);
+void BN_clear(BIGNUM *a);
+BIGNUM *BN_dup(const BIGNUM *a);
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+int BN_set_bit(BIGNUM *a, int n);
+int BN_clear_bit(BIGNUM *a, int n);
+char * BN_bn2hex(const BIGNUM *a);
+char * BN_bn2dec(const BIGNUM *a);
+int BN_hex2bn(BIGNUM **a, const char *str);
+int BN_dec2bn(BIGNUM **a, const char *str);
+int BN_gcd(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx);
+int BN_kronecker(const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); /* returns -2 for error */
+BIGNUM *BN_mod_inverse(BIGNUM *ret,
+ const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_mod_sqrt(BIGNUM *ret,
+ const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+
+/* Deprecated versions */
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
+ const BIGNUM *add, const BIGNUM *rem,
+ void (*callback)(int,int,void *),void *cb_arg);
+int BN_is_prime(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),
+ BN_CTX *ctx,void *cb_arg);
+int BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
+ int do_trial_division);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* Newer versions */
+int BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add,
+ const BIGNUM *rem, BN_GENCB *cb);
+int BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+int BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb);
+
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+ const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+ const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+ BIGNUM *Xp1, BIGNUM *Xp2,
+ const BIGNUM *Xp,
+ const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
+
+BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
+ BN_MONT_CTX *mont, BN_CTX *ctx);
+#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\
+ (r),(a),&((mont)->RR),(mont),(ctx))
+int BN_from_montgomery(BIGNUM *r,const BIGNUM *a,
+ BN_MONT_CTX *mont, BN_CTX *ctx);
+void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
+ const BIGNUM *mod, BN_CTX *ctx);
+
+/* BN_BLINDING flags */
+#define BN_BLINDING_NO_UPDATE 0x00000001
+#define BN_BLINDING_NO_RECREATE 0x00000002
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
+void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
+void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
+ const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx,
+ int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
+ BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DEPRECATED
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+#endif
+
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx);
+int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+ BN_RECP_CTX *recp,BN_CTX *ctx);
+int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx);
+int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
+ BN_RECP_CTX *recp, BN_CTX *ctx);
+
+/* Functions for arithmetic over binary polynomials represented by BIGNUMs.
+ *
+ * The BIGNUM::neg property of BIGNUMs representing binary polynomials is
+ * ignored.
+ *
+ * Note that input arguments are not const so that their bit arrays can
+ * be expanded to the appropriate size if needed.
+ */
+
+int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); /*r = a + b*/
+#define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
+int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); /*r=a mod p*/
+int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a * b) mod p */
+int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r = (a * a) mod p */
+int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p,
+ BN_CTX *ctx); /* r = (1 / b) mod p */
+int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a / b) mod p */
+int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a ^ b) mod p */
+int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r = sqrt(a) mod p */
+int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r^2 + r = a mod p */
+#define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
+/* Some functions allow for representation of the irreducible polynomials
+ * as an unsigned int[], say p. The irreducible f(t) is then of the form:
+ * t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]);
+ /* r = a mod p */
+int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a * b) mod p */
+int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[],
+ BN_CTX *ctx); /* r = (a * a) mod p */
+int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const unsigned int p[],
+ BN_CTX *ctx); /* r = (1 / b) mod p */
+int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a / b) mod p */
+int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a ^ b) mod p */
+int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
+ const unsigned int p[], BN_CTX *ctx); /* r = sqrt(a) mod p */
+int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
+ const unsigned int p[], BN_CTX *ctx); /* r^2 + r = a mod p */
+int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
+int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
+
+/* faster mod functions for the 'NIST primes'
+ * 0 <= a < p^2 */
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+const BIGNUM *BN_get0_nist_prime_192(void);
+const BIGNUM *BN_get0_nist_prime_224(void);
+const BIGNUM *BN_get0_nist_prime_256(void);
+const BIGNUM *BN_get0_nist_prime_384(void);
+const BIGNUM *BN_get0_nist_prime_521(void);
+
+/* library internal functions */
+
+#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
+ (a):bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2))
+#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
+BIGNUM *bn_expand2(BIGNUM *a, int words);
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */
+#endif
+
+/* Bignum consistency macros
+ * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
+ * bignum data after direct manipulations on the data. There is also an
+ * "internal" macro, bn_check_top(), for verifying that there are no leading
+ * zeroes. Unfortunately, some auditing is required due to the fact that
+ * bn_fix_top() has become an overabused duct-tape because bignum data is
+ * occasionally passed around in an inconsistent state. So the following
+ * changes have been made to sort this out;
+ * - bn_fix_top()s implementation has been moved to bn_correct_top()
+ * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
+ * bn_check_top() is as before.
+ * - if BN_DEBUG *is* defined;
+ * - bn_check_top() tries to pollute unused words even if the bignum 'top' is
+ * consistent. (ed: only if BN_DEBUG_RAND is defined)
+ * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
+ * The idea is to have debug builds flag up inconsistent bignums when they
+ * occur. If that occurs in a bn_fix_top(), we examine the code in question; if
+ * the use of bn_fix_top() was appropriate (ie. it follows directly after code
+ * that manipulates the bignum) it is converted to bn_correct_top(), and if it
+ * was not appropriate, we convert it permanently to bn_check_top() and track
+ * down the cause of the bug. Eventually, no internal code should be using the
+ * bn_fix_top() macro. External applications and libraries should try this with
+ * their own code too, both in terms of building against the openssl headers
+ * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
+ * defined. This not only improves external code, it provides more test
+ * coverage for openssl's own code.
+ */
+
+#ifdef BN_DEBUG
+
+/* We only need assert() when debugging */
+#include <assert.h>
+
+#ifdef BN_DEBUG_RAND
+/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
+#ifndef RAND_pseudo_bytes
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+#define BN_DEBUG_TRIX
+#endif
+#define bn_pollute(a) \
+ do { \
+ const BIGNUM *_bnum1 = (a); \
+ if(_bnum1->top < _bnum1->dmax) { \
+ unsigned char _tmp_char; \
+ /* We cast away const without the compiler knowing, any \
+ * *genuinely* constant variables that aren't mutable \
+ * wouldn't be constructed with top!=dmax. */ \
+ BN_ULONG *_not_const; \
+ memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \
+ RAND_pseudo_bytes(&_tmp_char, 1); \
+ memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \
+ (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \
+ } \
+ } while(0)
+#ifdef BN_DEBUG_TRIX
+#undef RAND_pseudo_bytes
+#endif
+#else
+#define bn_pollute(a)
+#endif
+#define bn_check_top(a) \
+ do { \
+ const BIGNUM *_bnum2 = (a); \
+ if (_bnum2 != NULL) { \
+ assert((_bnum2->top == 0) || \
+ (_bnum2->d[_bnum2->top - 1] != 0)); \
+ bn_pollute(_bnum2); \
+ } \
+ } while(0)
+
+#define bn_fix_top(a) bn_check_top(a)
+
+#else /* !BN_DEBUG */
+
+#define bn_pollute(a)
+#define bn_check_top(a)
+#define bn_fix_top(a) bn_correct_top(a)
+
+#endif
+
+#define bn_correct_top(a) \
+ { \
+ BN_ULONG *ftl; \
+ if ((a)->top > 0) \
+ { \
+ for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+ if (*(ftl--)) break; \
+ } \
+ bn_pollute(a); \
+ }
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+
+/* Primes from RFC 2409 */
+BIGNUM *get_rfc2409_prime_768(BIGNUM *bn);
+BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn);
+
+/* Primes from RFC 3526 */
+BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BN_strings(void);
+
+/* Error codes for the BN functions. */
+
+/* Function codes. */
+#define BN_F_BNRAND 127
+#define BN_F_BN_BLINDING_CONVERT_EX 100
+#define BN_F_BN_BLINDING_CREATE_PARAM 128
+#define BN_F_BN_BLINDING_INVERT_EX 101
+#define BN_F_BN_BLINDING_NEW 102
+#define BN_F_BN_BLINDING_UPDATE 103
+#define BN_F_BN_BN2DEC 104
+#define BN_F_BN_BN2HEX 105
+#define BN_F_BN_CTX_GET 116
+#define BN_F_BN_CTX_NEW 106
+#define BN_F_BN_CTX_START 129
+#define BN_F_BN_DIV 107
+#define BN_F_BN_DIV_NO_BRANCH 138
+#define BN_F_BN_DIV_RECP 130
+#define BN_F_BN_EXP 123
+#define BN_F_BN_EXPAND2 108
+#define BN_F_BN_EXPAND_INTERNAL 120
+#define BN_F_BN_GF2M_MOD 131
+#define BN_F_BN_GF2M_MOD_EXP 132
+#define BN_F_BN_GF2M_MOD_MUL 133
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135
+#define BN_F_BN_GF2M_MOD_SQR 136
+#define BN_F_BN_GF2M_MOD_SQRT 137
+#define BN_F_BN_MOD_EXP2_MONT 118
+#define BN_F_BN_MOD_EXP_MONT 109
+#define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124
+#define BN_F_BN_MOD_EXP_MONT_WORD 117
+#define BN_F_BN_MOD_EXP_RECP 125
+#define BN_F_BN_MOD_EXP_SIMPLE 126
+#define BN_F_BN_MOD_INVERSE 110
+#define BN_F_BN_MOD_INVERSE_NO_BRANCH 139
+#define BN_F_BN_MOD_LSHIFT_QUICK 119
+#define BN_F_BN_MOD_MUL_RECIPROCAL 111
+#define BN_F_BN_MOD_SQRT 121
+#define BN_F_BN_MPI2BN 112
+#define BN_F_BN_NEW 113
+#define BN_F_BN_RAND 114
+#define BN_F_BN_RAND_RANGE 122
+#define BN_F_BN_USUB 115
+
+/* Reason codes. */
+#define BN_R_ARG2_LT_ARG3 100
+#define BN_R_BAD_RECIPROCAL 101
+#define BN_R_BIGNUM_TOO_LONG 114
+#define BN_R_CALLED_WITH_EVEN_MODULUS 102
+#define BN_R_DIV_BY_ZERO 103
+#define BN_R_ENCODING_ERROR 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105
+#define BN_R_INPUT_NOT_REDUCED 110
+#define BN_R_INVALID_LENGTH 106
+#define BN_R_INVALID_RANGE 115
+#define BN_R_NOT_A_SQUARE 111
+#define BN_R_NOT_INITIALIZED 107
+#define BN_R_NO_INVERSE 108
+#define BN_R_NO_SOLUTION 116
+#define BN_R_P_IS_NOT_PRIME 112
+#define BN_R_TOO_MANY_ITERATIONS 113
+#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/buffer.h b/src/Mayaqua/win32_inc/openssl/buffer.h
new file mode 100644
index 00000000..e3f394cb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/buffer.h
@@ -0,0 +1,118 @@
+/* crypto/buffer/buffer.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BUFFER_H
+#define HEADER_BUFFER_H
+
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+#if !defined(NO_SYS_TYPES_H)
+#include <sys/types.h>
+#endif
+
+/* Already declared in ossl_typ.h */
+/* typedef struct buf_mem_st BUF_MEM; */
+
+struct buf_mem_st
+ {
+ int length; /* current number of bytes */
+ char *data;
+ int max; /* size of buffer */
+ };
+
+BUF_MEM *BUF_MEM_new(void);
+void BUF_MEM_free(BUF_MEM *a);
+int BUF_MEM_grow(BUF_MEM *str, int len);
+int BUF_MEM_grow_clean(BUF_MEM *str, int len);
+char * BUF_strdup(const char *str);
+char * BUF_strndup(const char *str, size_t siz);
+void * BUF_memdup(const void *data, size_t siz);
+
+/* safe string functions */
+size_t BUF_strlcpy(char *dst,const char *src,size_t siz);
+size_t BUF_strlcat(char *dst,const char *src,size_t siz);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BUF_strings(void);
+
+/* Error codes for the BUF functions. */
+
+/* Function codes. */
+#define BUF_F_BUF_MEMDUP 103
+#define BUF_F_BUF_MEM_GROW 100
+#define BUF_F_BUF_MEM_GROW_CLEAN 105
+#define BUF_F_BUF_MEM_NEW 101
+#define BUF_F_BUF_STRDUP 102
+#define BUF_F_BUF_STRNDUP 104
+
+/* Reason codes. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/cast.h b/src/Mayaqua/win32_inc/openssl/cast.h
new file mode 100644
index 00000000..fd1bc9cf
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/cast.h
@@ -0,0 +1,107 @@
+/* crypto/cast/cast.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CAST_H
+#define HEADER_CAST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_CAST
+#error CAST is disabled.
+#endif
+
+#define CAST_ENCRYPT 1
+#define CAST_DECRYPT 0
+
+#define CAST_LONG unsigned long
+
+#define CAST_BLOCK 8
+#define CAST_KEY_LENGTH 16
+
+typedef struct cast_key_st
+ {
+ CAST_LONG data[32];
+ int short_key; /* Use reduced rounds for short key */
+ } CAST_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+#endif
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, const CAST_KEY *key,
+ int enc);
+void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const CAST_KEY *ks, unsigned char *iv, int enc);
+void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, const CAST_KEY *schedule, unsigned char *ivec,
+ int *num, int enc);
+void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, const CAST_KEY *schedule, unsigned char *ivec,
+ int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/comp.h b/src/Mayaqua/win32_inc/openssl/comp.h
new file mode 100644
index 00000000..15ad4f24
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/comp.h
@@ -0,0 +1,80 @@
+
+#ifndef HEADER_COMP_H
+#define HEADER_COMP_H
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct comp_ctx_st COMP_CTX;
+
+typedef struct comp_method_st
+ {
+ int type; /* NID for compression library */
+ const char *name; /* A text string to identify the library */
+ int (*init)(COMP_CTX *ctx);
+ void (*finish)(COMP_CTX *ctx);
+ int (*compress)(COMP_CTX *ctx,
+ unsigned char *out, unsigned int olen,
+ unsigned char *in, unsigned int ilen);
+ int (*expand)(COMP_CTX *ctx,
+ unsigned char *out, unsigned int olen,
+ unsigned char *in, unsigned int ilen);
+ /* The following two do NOTHING, but are kept for backward compatibility */
+ long (*ctrl)(void);
+ long (*callback_ctrl)(void);
+ } COMP_METHOD;
+
+struct comp_ctx_st
+ {
+ COMP_METHOD *meth;
+ unsigned long compress_in;
+ unsigned long compress_out;
+ unsigned long expand_in;
+ unsigned long expand_out;
+
+ CRYPTO_EX_DATA ex_data;
+ };
+
+
+COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
+void COMP_CTX_free(COMP_CTX *ctx);
+int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen,
+ unsigned char *in, int ilen);
+int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
+ unsigned char *in, int ilen);
+COMP_METHOD *COMP_rle(void );
+COMP_METHOD *COMP_zlib(void );
+void COMP_zlib_cleanup(void);
+
+#ifdef HEADER_BIO_H
+#ifdef ZLIB
+BIO_METHOD *BIO_f_zlib(void);
+#endif
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_COMP_strings(void);
+
+/* Error codes for the COMP functions. */
+
+/* Function codes. */
+#define COMP_F_BIO_ZLIB_FLUSH 99
+#define COMP_F_BIO_ZLIB_NEW 100
+#define COMP_F_BIO_ZLIB_READ 101
+#define COMP_F_BIO_ZLIB_WRITE 102
+
+/* Reason codes. */
+#define COMP_R_ZLIB_DEFLATE_ERROR 99
+#define COMP_R_ZLIB_INFLATE_ERROR 100
+#define COMP_R_ZLIB_NOT_SUPPORTED 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/conf.h b/src/Mayaqua/win32_inc/openssl/conf.h
new file mode 100644
index 00000000..5ae4b90d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/conf.h
@@ -0,0 +1,254 @@
+/* crypto/conf/conf.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONF_H
+#define HEADER_CONF_H
+
+#include <openssl/bio.h>
+#include <openssl/lhash.h>
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+#include <openssl/e_os2.h>
+
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+ {
+ char *section;
+ char *name;
+ char *value;
+ } CONF_VALUE;
+
+DECLARE_STACK_OF(CONF_VALUE)
+DECLARE_STACK_OF(CONF_MODULE)
+DECLARE_STACK_OF(CONF_IMODULE)
+
+struct conf_st;
+struct conf_method_st;
+typedef struct conf_method_st CONF_METHOD;
+
+struct conf_method_st
+ {
+ const char *name;
+ CONF *(*create)(CONF_METHOD *meth);
+ int (*init)(CONF *conf);
+ int (*destroy)(CONF *conf);
+ int (*destroy_data)(CONF *conf);
+ int (*load_bio)(CONF *conf, BIO *bp, long *eline);
+ int (*dump)(const CONF *conf, BIO *bp);
+ int (*is_number)(const CONF *conf, char c);
+ int (*to_int)(const CONF *conf, char c);
+ int (*load)(CONF *conf, const char *name, long *eline);
+ };
+
+/* Module definitions */
+
+typedef struct conf_imodule_st CONF_IMODULE;
+typedef struct conf_module_st CONF_MODULE;
+
+/* DSO module function typedefs */
+typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf);
+typedef void conf_finish_func(CONF_IMODULE *md);
+
+#define CONF_MFLAGS_IGNORE_ERRORS 0x1
+#define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2
+#define CONF_MFLAGS_SILENT 0x4
+#define CONF_MFLAGS_NO_DSO 0x8
+#define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
+#define CONF_MFLAGS_DEFAULT_SECTION 0x20
+
+int CONF_set_default_method(CONF_METHOD *meth);
+void CONF_set_nconf(CONF *conf,LHASH *hash);
+LHASH *CONF_load(LHASH *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline);
+#endif
+LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section);
+char *CONF_get_string(LHASH *conf,const char *group,const char *name);
+long CONF_get_number(LHASH *conf,const char *group,const char *name);
+void CONF_free(LHASH *conf);
+int CONF_dump_fp(LHASH *conf, FILE *out);
+int CONF_dump_bio(LHASH *conf, BIO *out);
+
+void OPENSSL_config(const char *config_name);
+void OPENSSL_no_config(void);
+
+/* New conf code. The semantics are different from the functions above.
+ If that wasn't the case, the above functions would have been replaced */
+
+struct conf_st
+ {
+ CONF_METHOD *meth;
+ void *meth_data;
+ LHASH *data;
+ };
+
+CONF *NCONF_new(CONF_METHOD *meth);
+CONF_METHOD *NCONF_default(void);
+CONF_METHOD *NCONF_WIN32(void);
+#if 0 /* Just to give you an idea of what I have in mind */
+CONF_METHOD *NCONF_XML(void);
+#endif
+void NCONF_free(CONF *conf);
+void NCONF_free_data(CONF *conf);
+
+int NCONF_load(CONF *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+int NCONF_load_fp(CONF *conf, FILE *fp,long *eline);
+#endif
+int NCONF_load_bio(CONF *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section);
+char *NCONF_get_string(const CONF *conf,const char *group,const char *name);
+int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
+ long *result);
+int NCONF_dump_fp(const CONF *conf, FILE *out);
+int NCONF_dump_bio(const CONF *conf, BIO *out);
+
+#if 0 /* The following function has no error checking,
+ and should therefore be avoided */
+long NCONF_get_number(CONF *conf,char *group,char *name);
+#else
+#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
+#endif
+
+/* Module functions */
+
+int CONF_modules_load(const CONF *cnf, const char *appname,
+ unsigned long flags);
+int CONF_modules_load_file(const char *filename, const char *appname,
+ unsigned long flags);
+void CONF_modules_unload(int all);
+void CONF_modules_finish(void);
+void CONF_modules_free(void);
+int CONF_module_add(const char *name, conf_init_func *ifunc,
+ conf_finish_func *ffunc);
+
+const char *CONF_imodule_get_name(const CONF_IMODULE *md);
+const char *CONF_imodule_get_value(const CONF_IMODULE *md);
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
+void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
+void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
+void *CONF_module_get_usr_data(CONF_MODULE *pmod);
+void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
+
+char *CONF_get1_default_config_file(void);
+
+int CONF_parse_list(const char *list, int sep, int nospc,
+ int (*list_cb)(const char *elem, int len, void *usr), void *arg);
+
+void OPENSSL_load_builtin_modules(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CONF_strings(void);
+
+/* Error codes for the CONF functions. */
+
+/* Function codes. */
+#define CONF_F_CONF_DUMP_FP 104
+#define CONF_F_CONF_LOAD 100
+#define CONF_F_CONF_LOAD_BIO 102
+#define CONF_F_CONF_LOAD_FP 103
+#define CONF_F_CONF_MODULES_LOAD 116
+#define CONF_F_DEF_LOAD 120
+#define CONF_F_DEF_LOAD_BIO 121
+#define CONF_F_MODULE_INIT 115
+#define CONF_F_MODULE_LOAD_DSO 117
+#define CONF_F_MODULE_RUN 118
+#define CONF_F_NCONF_DUMP_BIO 105
+#define CONF_F_NCONF_DUMP_FP 106
+#define CONF_F_NCONF_GET_NUMBER 107
+#define CONF_F_NCONF_GET_NUMBER_E 112
+#define CONF_F_NCONF_GET_SECTION 108
+#define CONF_F_NCONF_GET_STRING 109
+#define CONF_F_NCONF_LOAD 113
+#define CONF_F_NCONF_LOAD_BIO 110
+#define CONF_F_NCONF_LOAD_FP 114
+#define CONF_F_NCONF_NEW 111
+#define CONF_F_STR_COPY 101
+
+/* Reason codes. */
+#define CONF_R_ERROR_LOADING_DSO 110
+#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100
+#define CONF_R_MISSING_EQUAL_SIGN 101
+#define CONF_R_MISSING_FINISH_FUNCTION 111
+#define CONF_R_MISSING_INIT_FUNCTION 112
+#define CONF_R_MODULE_INITIALIZATION_ERROR 109
+#define CONF_R_NO_CLOSE_BRACE 102
+#define CONF_R_NO_CONF 105
+#define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106
+#define CONF_R_NO_SECTION 107
+#define CONF_R_NO_SUCH_FILE 114
+#define CONF_R_NO_VALUE 108
+#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103
+#define CONF_R_UNKNOWN_MODULE_NAME 113
+#define CONF_R_VARIABLE_HAS_NO_VALUE 104
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/conf_api.h b/src/Mayaqua/win32_inc/openssl/conf_api.h
new file mode 100644
index 00000000..8e7d5d50
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/conf_api.h
@@ -0,0 +1,89 @@
+/* conf_api.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONF_API_H
+#define HEADER_CONF_API_H
+
+#include <openssl/lhash.h>
+#include <openssl/conf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Up until OpenSSL 0.9.5a, this was new_section */
+CONF_VALUE *_CONF_new_section(CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was get_section */
+CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
+STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
+ const char *section);
+
+int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value);
+char *_CONF_get_string(const CONF *conf, const char *section,
+ const char *name);
+long _CONF_get_number(const CONF *conf, const char *section, const char *name);
+
+int _CONF_new_data(CONF *conf);
+void _CONF_free_data(CONF *conf);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/crypto.h b/src/Mayaqua/win32_inc/openssl/crypto.h
new file mode 100644
index 00000000..60ad49b3
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/crypto.h
@@ -0,0 +1,619 @@
+/* crypto/crypto.h */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#include <stdlib.h>
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#endif
+
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+#include <openssl/opensslv.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
+/* Resolve problems on some operating systems with symbol names that clash
+ one way or another */
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Backward compatibility to SSLeay */
+/* This is more to be used to check the correct DLL is being used
+ * in the MS world. */
+#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
+#define SSLEAY_VERSION 0
+/* #define SSLEAY_OPTIONS 1 no longer supported */
+#define SSLEAY_CFLAGS 2
+#define SSLEAY_BUILT_ON 3
+#define SSLEAY_PLATFORM 4
+#define SSLEAY_DIR 5
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Called when a new object is created */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+/* Called when an object is free()ed */
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+/* Called when we need to dup an object */
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
+ int idx, long argl, void *argp);
+#endif
+
+/* A generic structure to pass assorted data in a expandable way */
+typedef struct openssl_item_st
+ {
+ int code;
+ void *value; /* Not used for flag attributes */
+ size_t value_size; /* Max size of value for output, length for input */
+ size_t *value_length; /* Returned length of value for output */
+ } OPENSSL_ITEM;
+
+
+/* When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock
+ * names in cryptlib.c
+ */
+
+#define CRYPTO_LOCK_ERR 1
+#define CRYPTO_LOCK_EX_DATA 2
+#define CRYPTO_LOCK_X509 3
+#define CRYPTO_LOCK_X509_INFO 4
+#define CRYPTO_LOCK_X509_PKEY 5
+#define CRYPTO_LOCK_X509_CRL 6
+#define CRYPTO_LOCK_X509_REQ 7
+#define CRYPTO_LOCK_DSA 8
+#define CRYPTO_LOCK_RSA 9
+#define CRYPTO_LOCK_EVP_PKEY 10
+#define CRYPTO_LOCK_X509_STORE 11
+#define CRYPTO_LOCK_SSL_CTX 12
+#define CRYPTO_LOCK_SSL_CERT 13
+#define CRYPTO_LOCK_SSL_SESSION 14
+#define CRYPTO_LOCK_SSL_SESS_CERT 15
+#define CRYPTO_LOCK_SSL 16
+#define CRYPTO_LOCK_SSL_METHOD 17
+#define CRYPTO_LOCK_RAND 18
+#define CRYPTO_LOCK_RAND2 19
+#define CRYPTO_LOCK_MALLOC 20
+#define CRYPTO_LOCK_BIO 21
+#define CRYPTO_LOCK_GETHOSTBYNAME 22
+#define CRYPTO_LOCK_GETSERVBYNAME 23
+#define CRYPTO_LOCK_READDIR 24
+#define CRYPTO_LOCK_RSA_BLINDING 25
+#define CRYPTO_LOCK_DH 26
+#define CRYPTO_LOCK_MALLOC2 27
+#define CRYPTO_LOCK_DSO 28
+#define CRYPTO_LOCK_DYNLOCK 29
+#define CRYPTO_LOCK_ENGINE 30
+#define CRYPTO_LOCK_UI 31
+#define CRYPTO_LOCK_ECDSA 32
+#define CRYPTO_LOCK_EC 33
+#define CRYPTO_LOCK_ECDH 34
+#define CRYPTO_LOCK_BN 35
+#define CRYPTO_LOCK_EC_PRE_COMP 36
+#define CRYPTO_LOCK_STORE 37
+#define CRYPTO_LOCK_COMP 38
+#ifndef OPENSSL_FIPS
+#define CRYPTO_NUM_LOCKS 39
+#else
+#define CRYPTO_LOCK_FIPS 39
+#define CRYPTO_LOCK_FIPS2 40
+#define CRYPTO_NUM_LOCKS 41
+#endif
+
+#define CRYPTO_LOCK 1
+#define CRYPTO_UNLOCK 2
+#define CRYPTO_READ 4
+#define CRYPTO_WRITE 8
+
+#ifndef OPENSSL_NO_LOCKING
+#ifndef CRYPTO_w_lock
+#define CRYPTO_w_lock(type) \
+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_w_unlock(type) \
+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_r_lock(type) \
+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_r_unlock(type) \
+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_add(addr,amount,type) \
+ CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
+#endif
+#else
+#define CRYPTO_w_lock(a)
+#define CRYPTO_w_unlock(a)
+#define CRYPTO_r_lock(a)
+#define CRYPTO_r_unlock(a)
+#define CRYPTO_add(a,b,c) ((*(a))+=(b))
+#endif
+
+/* Some applications as well as some parts of OpenSSL need to allocate
+ and deallocate locks in a dynamic fashion. The following typedef
+ makes this possible in a type-safe manner. */
+/* struct CRYPTO_dynlock_value has to be defined by the application. */
+typedef struct
+ {
+ int references;
+ struct CRYPTO_dynlock_value *data;
+ } CRYPTO_dynlock;
+
+
+/* The following can be used to detect memory leaks in the SSLeay library.
+ * It used, it turns on malloc checking */
+
+#define CRYPTO_MEM_CHECK_OFF 0x0 /* an enume */
+#define CRYPTO_MEM_CHECK_ON 0x1 /* a bit */
+#define CRYPTO_MEM_CHECK_ENABLE 0x2 /* a bit */
+#define CRYPTO_MEM_CHECK_DISABLE 0x3 /* an enume */
+
+/* The following are bit values to turn on or off options connected to the
+ * malloc checking functionality */
+
+/* Adds time to the memory checking information */
+#define V_CRYPTO_MDEBUG_TIME 0x1 /* a bit */
+/* Adds thread number to the memory checking information */
+#define V_CRYPTO_MDEBUG_THREAD 0x2 /* a bit */
+
+#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD)
+
+
+/* predec of the BIO type */
+typedef struct bio_st BIO_dummy;
+
+struct crypto_ex_data_st
+ {
+ STACK *sk;
+ int dummy; /* gcc is screwing up this data structure :-( */
+ };
+
+/* This stuff is basically class callback functions
+ * The current classes are SSL_CTX, SSL, SSL_SESSION, and a few more */
+
+typedef struct crypto_ex_data_func_st
+ {
+ long argl; /* Arbitary long */
+ void *argp; /* Arbitary void * */
+ CRYPTO_EX_new *new_func;
+ CRYPTO_EX_free *free_func;
+ CRYPTO_EX_dup *dup_func;
+ } CRYPTO_EX_DATA_FUNCS;
+
+DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
+
+/* Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA
+ * entry.
+ */
+
+#define CRYPTO_EX_INDEX_BIO 0
+#define CRYPTO_EX_INDEX_SSL 1
+#define CRYPTO_EX_INDEX_SSL_CTX 2
+#define CRYPTO_EX_INDEX_SSL_SESSION 3
+#define CRYPTO_EX_INDEX_X509_STORE 4
+#define CRYPTO_EX_INDEX_X509_STORE_CTX 5
+#define CRYPTO_EX_INDEX_RSA 6
+#define CRYPTO_EX_INDEX_DSA 7
+#define CRYPTO_EX_INDEX_DH 8
+#define CRYPTO_EX_INDEX_ENGINE 9
+#define CRYPTO_EX_INDEX_X509 10
+#define CRYPTO_EX_INDEX_UI 11
+#define CRYPTO_EX_INDEX_ECDSA 12
+#define CRYPTO_EX_INDEX_ECDH 13
+#define CRYPTO_EX_INDEX_COMP 14
+#define CRYPTO_EX_INDEX_STORE 15
+
+/* Dynamically assigned indexes start from this value (don't use directly, use
+ * via CRYPTO_ex_data_new_class). */
+#define CRYPTO_EX_INDEX_USER 100
+
+
+/* This is the default callbacks, but we can have others as well:
+ * this is needed in Win32 where the application malloc and the
+ * library malloc may not be the same.
+ */
+#define CRYPTO_malloc_init() CRYPTO_set_mem_functions(\
+ malloc, realloc, free)
+
+#if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD
+# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */
+# define CRYPTO_MDEBUG
+# endif
+#endif
+
+/* Set standard debugging functions (not done by default
+ * unless CRYPTO_MDEBUG is defined) */
+void CRYPTO_malloc_debug_init(void);
+
+int CRYPTO_mem_ctrl(int mode);
+int CRYPTO_is_mem_check_on(void);
+
+/* for applications */
+#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
+#define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
+
+/* for library-internal use */
+#define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
+#define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
+#define is_MemCheck_on() CRYPTO_is_mem_check_on()
+
+#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
+#define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__)
+#define OPENSSL_realloc(addr,num) \
+ CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_realloc_clean(addr,old_num,num) \
+ CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
+#define OPENSSL_remalloc(addr,num) \
+ CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_freeFunc CRYPTO_free
+#define OPENSSL_free(addr) CRYPTO_free(addr)
+
+#define OPENSSL_malloc_locked(num) \
+ CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
+#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+
+
+const char *SSLeay_version(int type);
+unsigned long SSLeay(void);
+
+int OPENSSL_issetugid(void);
+
+/* An opaque type representing an implementation of "ex_data" support */
+typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL;
+/* Return an opaque pointer to the current "ex_data" implementation */
+const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void);
+/* Sets the "ex_data" implementation to be used (if it's not too late) */
+int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i);
+/* Get a new "ex_data" class, and return the corresponding "class_index" */
+int CRYPTO_ex_data_new_class(void);
+/* Within a given class, get/register a new index */
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+/* Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a given
+ * class (invokes whatever per-class callbacks are applicable) */
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+ CRYPTO_EX_DATA *from);
+void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+/* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular index
+ * (relative to the class type involved) */
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad,int idx);
+/* This function cleans up all "ex_data" state. It mustn't be called under
+ * potential race-conditions. */
+void CRYPTO_cleanup_all_ex_data(void);
+
+int CRYPTO_get_new_lockid(char *name);
+
+int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */
+void CRYPTO_lock(int mode, int type,const char *file,int line);
+void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
+ const char *file,int line));
+void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
+ int line);
+void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
+ const char *file, int line));
+int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
+ const char *file,int line);
+void CRYPTO_set_id_callback(unsigned long (*func)(void));
+unsigned long (*CRYPTO_get_id_callback(void))(void);
+unsigned long CRYPTO_thread_id(void);
+const char *CRYPTO_get_lock_name(int type);
+int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
+ int line);
+
+void int_CRYPTO_set_do_dynlock_callback(
+ void (*do_dynlock_cb)(int mode, int type, const char *file, int line));
+
+int CRYPTO_get_new_dynlockid(void);
+void CRYPTO_destroy_dynlockid(int i);
+struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i);
+void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, int line));
+void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line));
+void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, const char *file, int line));
+struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(const char *file,int line);
+void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, struct CRYPTO_dynlock_value *l, const char *file,int line);
+void (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, const char *file,int line);
+
+/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions --
+ * call the latter last if you need different functions */
+int CRYPTO_set_mem_functions(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *));
+int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*free_func)(void *));
+int CRYPTO_set_mem_ex_functions(void *(*m)(size_t,const char *,int),
+ void *(*r)(void *,size_t,const char *,int),
+ void (*f)(void *));
+int CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t,const char *,int),
+ void (*free_func)(void *));
+int CRYPTO_set_mem_debug_functions(void (*m)(void *,int,const char *,int,int),
+ void (*r)(void *,void *,int,const char *,int,int),
+ void (*f)(void *,int),
+ void (*so)(long),
+ long (*go)(void));
+void CRYPTO_set_mem_info_functions(
+ int (*push_info_fn)(const char *info, const char *file, int line),
+ int (*pop_info_fn)(void),
+ int (*remove_all_info_fn)(void));
+void CRYPTO_get_mem_functions(void *(**m)(size_t),void *(**r)(void *, size_t), void (**f)(void *));
+void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *));
+void CRYPTO_get_mem_ex_functions(void *(**m)(size_t,const char *,int),
+ void *(**r)(void *, size_t,const char *,int),
+ void (**f)(void *));
+void CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t,const char *,int),
+ void (**f)(void *));
+void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int),
+ void (**r)(void *,void *,int,const char *,int,int),
+ void (**f)(void *,int),
+ void (**so)(long),
+ long (**go)(void));
+
+void *CRYPTO_malloc_locked(int num, const char *file, int line);
+void CRYPTO_free_locked(void *);
+void *CRYPTO_malloc(int num, const char *file, int line);
+char *CRYPTO_strdup(const char *str, const char *file, int line);
+void CRYPTO_free(void *);
+void *CRYPTO_realloc(void *addr,int num, const char *file, int line);
+void *CRYPTO_realloc_clean(void *addr,int old_num,int num,const char *file,
+ int line);
+void *CRYPTO_remalloc(void *addr,int num, const char *file, int line);
+
+void OPENSSL_cleanse(void *ptr, size_t len);
+
+void CRYPTO_set_mem_debug_options(long bits);
+long CRYPTO_get_mem_debug_options(void);
+
+#define CRYPTO_push_info(info) \
+ CRYPTO_push_info_(info, __FILE__, __LINE__);
+int CRYPTO_push_info_(const char *info, const char *file, int line);
+int CRYPTO_pop_info(void);
+int CRYPTO_remove_all_info(void);
+
+
+/* Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro;
+ * used as default in CRYPTO_MDEBUG compilations): */
+/* The last argument has the following significance:
+ *
+ * 0: called before the actual memory allocation has taken place
+ * 1: called after the actual memory allocation has taken place
+ */
+void CRYPTO_dbg_malloc(void *addr,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_realloc(void *addr1,void *addr2,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_free(void *addr,int before_p);
+/* Tell the debugging code about options. By default, the following values
+ * apply:
+ *
+ * 0: Clear all options.
+ * V_CRYPTO_MDEBUG_TIME (1): Set the "Show Time" option.
+ * V_CRYPTO_MDEBUG_THREAD (2): Set the "Show Thread Number" option.
+ * V_CRYPTO_MDEBUG_ALL (3): 1 + 2
+ */
+void CRYPTO_dbg_set_options(long bits);
+long CRYPTO_dbg_get_options(void);
+
+int CRYPTO_dbg_push_info(const char *info, const char *file, int line);
+int CRYPTO_dbg_pop_info(void);
+int CRYPTO_dbg_remove_all_info(void);
+
+#ifndef OPENSSL_NO_FP_API
+void CRYPTO_mem_leaks_fp(FILE *);
+#endif
+void CRYPTO_mem_leaks(struct bio_st *bio);
+/* unsigned long order, char *file, int line, int num_bytes, char *addr */
+typedef void *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *);
+void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+
+/* die if we have to */
+void OpenSSLDie(const char *file,int line,const char *assertion);
+#define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
+
+unsigned long *OPENSSL_ia32cap_loc(void);
+#define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+int OPENSSL_isservice(void);
+
+#ifdef OPENSSL_FIPS
+#define FIPS_ERROR_IGNORED(alg) OpenSSLDie(__FILE__, __LINE__, \
+ alg " previous FIPS forbidden algorithm error ignored");
+
+#define FIPS_BAD_ABORT(alg) OpenSSLDie(__FILE__, __LINE__, \
+ #alg " Algorithm forbidden in FIPS mode");
+
+#ifdef OPENSSL_FIPS_STRICT
+#define FIPS_BAD_ALGORITHM(alg) FIPS_BAD_ABORT(alg)
+#else
+#define FIPS_BAD_ALGORITHM(alg) \
+ { \
+ FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); \
+ ERR_add_error_data(2, "Algorithm=", #alg); \
+ return 0; \
+ }
+#endif
+
+/* Low level digest API blocking macro */
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+ int alg##_Init(alg##_CTX *c) \
+ { \
+ if (FIPS_mode()) \
+ FIPS_BAD_ALGORITHM(alg) \
+ return private_##alg##_Init(c); \
+ } \
+ int private_##alg##_Init(alg##_CTX *c)
+
+/* For ciphers the API often varies from cipher to cipher and each needs to
+ * be treated as a special case. Variable key length ciphers (Blowfish, RC4,
+ * CAST) however are very similar and can use a blocking macro.
+ */
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+ void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data) \
+ { \
+ if (FIPS_mode()) \
+ FIPS_BAD_ABORT(alg) \
+ private_##alg##_set_key(key, len, data); \
+ } \
+ void private_##alg##_set_key(alg##_KEY *key, int len, \
+ const unsigned char *data)
+
+#else
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+ void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data)
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+ int alg##_Init(alg##_CTX *c)
+
+#endif /* def OPENSSL_FIPS */
+
+#define OPENSSL_HAVE_INIT 1
+void OPENSSL_init(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CRYPTO_strings(void);
+
+/* Error codes for the CRYPTO functions. */
+
+/* Function codes. */
+#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100
+#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103
+#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101
+#define CRYPTO_F_CRYPTO_SET_EX_DATA 102
+#define CRYPTO_F_DEF_ADD_INDEX 104
+#define CRYPTO_F_DEF_GET_CLASS 105
+#define CRYPTO_F_INT_DUP_EX_DATA 106
+#define CRYPTO_F_INT_FREE_EX_DATA 107
+#define CRYPTO_F_INT_NEW_EX_DATA 108
+
+/* Reason codes. */
+#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/des.h b/src/Mayaqua/win32_inc/openssl/des.h
new file mode 100644
index 00000000..bd10b944
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/des.h
@@ -0,0 +1,245 @@
+/* crypto/des/des.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_NEW_DES_H
+#define HEADER_NEW_DES_H
+
+#include <openssl/e_os2.h> /* OPENSSL_EXTERN, OPENSSL_NO_DES,
+ DES_LONG (via openssl/opensslconf.h */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char DES_cblock[8];
+typedef /* const */ unsigned char const_DES_cblock[8];
+/* With "const", gcc 2.8.1 on Solaris thinks that DES_cblock *
+ * and const_DES_cblock * are incompatible pointer types. */
+
+typedef struct DES_ks
+ {
+ union
+ {
+ DES_cblock cblock;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ DES_LONG deslong[2];
+ } ks[16];
+ } DES_key_schedule;
+
+#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
+# ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT
+# define OPENSSL_ENABLE_OLD_DES_SUPPORT
+# endif
+#endif
+
+#ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT
+# include <openssl/des_old.h>
+#endif
+
+#define DES_KEY_SZ (sizeof(DES_cblock))
+#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
+
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#define DES_CBC_MODE 0
+#define DES_PCBC_MODE 1
+
+#define DES_ecb2_encrypt(i,o,k1,k2,e) \
+ DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+OPENSSL_DECLARE_GLOBAL(int,DES_check_key); /* defaults to false */
+#define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key)
+OPENSSL_DECLARE_GLOBAL(int,DES_rw_mode); /* defaults to DES_PCBC_MODE */
+#define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode)
+
+const char *DES_options(void);
+void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3, int enc);
+DES_LONG DES_cbc_cksum(const unsigned char *input,DES_cblock *output,
+ long length,DES_key_schedule *schedule,
+ const_DES_cblock *ivec);
+/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */
+void DES_cbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_xcbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ const_DES_cblock *inw,const_DES_cblock *outw,int enc);
+void DES_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_ecb_encrypt(const_DES_cblock *input,DES_cblock *output,
+ DES_key_schedule *ks,int enc);
+
+/* This is the DES encryption function that gets called by just about
+ every other DES routine in the library. You should not use this
+ function except to implement 'modes' of DES. I say this because the
+ functions that call this routine do the conversion from 'char *' to
+ long, and this needs to be done to make sure 'non-aligned' memory
+ access do not occur. The characters are loaded 'little endian'.
+ Data is a pointer to 2 unsigned long's and ks is the
+ DES_key_schedule to use. enc, is non zero specifies encryption,
+ zero if decryption. */
+void DES_encrypt1(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+/* This functions is the same as DES_encrypt1() except that the DES
+ initial permutation (IP) and final permutation (FP) have been left
+ out. As for DES_encrypt1(), you should not use this function.
+ It is used by the routines in the library that implement triple DES.
+ IP() DES_encrypt2() DES_encrypt2() DES_encrypt2() FP() is the same
+ as DES_encrypt1() DES_encrypt1() DES_encrypt1() except faster :-). */
+void DES_encrypt2(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
+ DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
+ DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3,DES_cblock *ivec,int enc);
+void DES_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out,
+ long length,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3,
+ DES_cblock *ivec1,DES_cblock *ivec2,
+ int enc);
+void DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out,
+ long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int *num,int enc);
+void DES_ede3_cfb_encrypt(const unsigned char *in,unsigned char *out,
+ int numbits,long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int enc);
+void DES_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out,
+ long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int *num);
+#if 0
+void DES_xwhite_in2out(const_DES_cblock *DES_key,const_DES_cblock *in_white,
+ DES_cblock *out_white);
+#endif
+
+int DES_enc_read(int fd,void *buf,int len,DES_key_schedule *sched,
+ DES_cblock *iv);
+int DES_enc_write(int fd,const void *buf,int len,DES_key_schedule *sched,
+ DES_cblock *iv);
+char *DES_fcrypt(const char *buf,const char *salt, char *ret);
+char *DES_crypt(const char *buf,const char *salt);
+void DES_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec);
+void DES_pcbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+DES_LONG DES_quad_cksum(const unsigned char *input,DES_cblock output[],
+ long length,int out_count,DES_cblock *seed);
+int DES_random_key(DES_cblock *ret);
+void DES_set_odd_parity(DES_cblock *key);
+int DES_check_key_parity(const_DES_cblock *key);
+int DES_is_weak_key(const_DES_cblock *key);
+/* DES_set_key (= set_key = DES_key_sched = key_sched) calls
+ * DES_set_key_checked if global variable DES_check_key is set,
+ * DES_set_key_unchecked otherwise. */
+int DES_set_key(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_key_sched(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_set_key_checked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_set_key_unchecked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_string_to_key(const char *str,DES_cblock *key);
+void DES_string_to_2keys(const char *str,DES_cblock *key1,DES_cblock *key2);
+void DES_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+ DES_key_schedule *schedule,DES_cblock *ivec,int *num,
+ int enc);
+void DES_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+ DES_key_schedule *schedule,DES_cblock *ivec,int *num);
+
+int DES_read_password(DES_cblock *key, const char *prompt, int verify);
+int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2, const char *prompt,
+ int verify);
+
+#define DES_fixup_key_parity DES_set_odd_parity
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/des_old.h b/src/Mayaqua/win32_inc/openssl/des_old.h
new file mode 100644
index 00000000..833899fc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/des_old.h
@@ -0,0 +1,446 @@
+/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * The function names in here are deprecated and are only present to
+ * provide an interface compatible with openssl 0.9.6 and older as
+ * well as libdes. OpenSSL now provides functions where "des_" has
+ * been replaced with "DES_" in the names, to make it possible to
+ * make incompatible changes that are needed for C type security and
+ * other stuff.
+ *
+ * This include files has two compatibility modes:
+ *
+ * - If OPENSSL_DES_LIBDES_COMPATIBILITY is defined, you get an API
+ * that is compatible with libdes and SSLeay.
+ * - If OPENSSL_DES_LIBDES_COMPATIBILITY isn't defined, you get an
+ * API that is compatible with OpenSSL 0.9.5x to 0.9.6x.
+ *
+ * Note that these modes break earlier snapshots of OpenSSL, where
+ * libdes compatibility was the only available mode or (later on) the
+ * prefered compatibility mode. However, after much consideration
+ * (and more or less violent discussions with external parties), it
+ * was concluded that OpenSSL should be compatible with earlier versions
+ * of itself before anything else. Also, in all honesty, libdes is
+ * an old beast that shouldn't really be used any more.
+ *
+ * Please consider starting to use the DES_ functions rather than the
+ * des_ ones. The des_ functions will disappear completely before
+ * OpenSSL 1.0!
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DES_H
+#define HEADER_DES_H
+
+#include <openssl/e_os2.h> /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifndef HEADER_NEW_DES_H
+#error You must include des.h, not des_old.h directly.
+#endif
+
+#ifdef _KERBEROS_DES_H
+#error <openssl/des_old.h> replaces <kerberos/des.h>.
+#endif
+
+#include <openssl/symhacks.h>
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _
+#undef _
+#endif
+
+typedef unsigned char _ossl_old_des_cblock[8];
+typedef struct _ossl_old_des_ks_struct
+ {
+ union {
+ _ossl_old_des_cblock _;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ DES_LONG pad[2];
+ } ks;
+ } _ossl_old_des_key_schedule[16];
+
+#ifndef OPENSSL_DES_LIBDES_COMPATIBILITY
+#define des_cblock DES_cblock
+#define const_des_cblock const_DES_cblock
+#define des_key_schedule DES_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+ DES_ecb3_encrypt((i),(o),&(k1),&(k2),&(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+ DES_ede3_cbc_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(e))
+#define des_ede3_cbcm_encrypt(i,o,l,k1,k2,k3,iv1,iv2,e)\
+ DES_ede3_cbcm_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv1),(iv2),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+ DES_ede3_cfb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+ DES_ede3_ofb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n))
+#define des_options()\
+ DES_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+ DES_cbc_cksum((i),(o),(l),&(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+ DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+ DES_ncbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+ DES_xcbc_encrypt((i),(o),(l),&(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+ DES_cfb_encrypt((i),(o),(n),(l),&(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+ DES_ecb_encrypt((i),(o),&(k),(e))
+#define des_encrypt1(d,k,e)\
+ DES_encrypt1((d),&(k),(e))
+#define des_encrypt2(d,k,e)\
+ DES_encrypt2((d),&(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+ DES_encrypt3((d),&(k1),&(k2),&(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+ DES_decrypt3((d),&(k1),&(k2),&(k3))
+#define des_xwhite_in2out(k,i,o)\
+ DES_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+ DES_enc_read((f),(b),(l),&(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+ DES_enc_write((f),(b),(l),&(k),(iv))
+#define des_fcrypt(b,s,r)\
+ DES_fcrypt((b),(s),(r))
+#if 0
+#define des_crypt(b,s)\
+ DES_crypt((b),(s))
+#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
+#define crypt(b,s)\
+ DES_crypt((b),(s))
+#endif
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+ DES_ofb_encrypt((i),(o),(n),(l),&(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+ DES_pcbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+ DES_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+ _ossl_096_des_random_seed((k))
+#define des_random_key(r)\
+ DES_random_key((r))
+#define des_read_password(k,p,v) \
+ DES_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+ DES_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+ DES_set_odd_parity((k))
+#define des_check_key_parity(k)\
+ DES_check_key_parity((k))
+#define des_is_weak_key(k)\
+ DES_is_weak_key((k))
+#define des_set_key(k,ks)\
+ DES_set_key((k),&(ks))
+#define des_key_sched(k,ks)\
+ DES_key_sched((k),&(ks))
+#define des_set_key_checked(k,ks)\
+ DES_set_key_checked((k),&(ks))
+#define des_set_key_unchecked(k,ks)\
+ DES_set_key_unchecked((k),&(ks))
+#define des_string_to_key(s,k)\
+ DES_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+ DES_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+ DES_cfb64_encrypt((i),(o),(l),&(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+ DES_ofb64_encrypt((i),(o),(l),&(ks),(iv),(n))
+
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#else /* libdes compatibility */
+/* Map all symbol names to _ossl_old_des_* form, so we avoid all
+ clashes with libdes */
+#define des_cblock _ossl_old_des_cblock
+#define des_key_schedule _ossl_old_des_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+ _ossl_old_des_ecb3_encrypt((i),(o),(k1),(k2),(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+ _ossl_old_des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+ _ossl_old_des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+ _ossl_old_des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n))
+#define des_options()\
+ _ossl_old_des_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+ _ossl_old_des_cbc_cksum((i),(o),(l),(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_cbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_ncbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+ _ossl_old_des_xcbc_encrypt((i),(o),(l),(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+ _ossl_old_des_cfb_encrypt((i),(o),(n),(l),(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+ _ossl_old_des_ecb_encrypt((i),(o),(k),(e))
+#define des_encrypt(d,k,e)\
+ _ossl_old_des_encrypt((d),(k),(e))
+#define des_encrypt2(d,k,e)\
+ _ossl_old_des_encrypt2((d),(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+ _ossl_old_des_encrypt3((d),(k1),(k2),(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+ _ossl_old_des_decrypt3((d),(k1),(k2),(k3))
+#define des_xwhite_in2out(k,i,o)\
+ _ossl_old_des_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+ _ossl_old_des_enc_read((f),(b),(l),(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+ _ossl_old_des_enc_write((f),(b),(l),(k),(iv))
+#define des_fcrypt(b,s,r)\
+ _ossl_old_des_fcrypt((b),(s),(r))
+#define des_crypt(b,s)\
+ _ossl_old_des_crypt((b),(s))
+#if 0
+#define crypt(b,s)\
+ _ossl_old_crypt((b),(s))
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+ _ossl_old_des_ofb_encrypt((i),(o),(n),(l),(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_pcbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+ _ossl_old_des_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+ _ossl_old_des_random_seed((k))
+#define des_random_key(r)\
+ _ossl_old_des_random_key((r))
+#define des_read_password(k,p,v) \
+ _ossl_old_des_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+ _ossl_old_des_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+ _ossl_old_des_set_odd_parity((k))
+#define des_is_weak_key(k)\
+ _ossl_old_des_is_weak_key((k))
+#define des_set_key(k,ks)\
+ _ossl_old_des_set_key((k),(ks))
+#define des_key_sched(k,ks)\
+ _ossl_old_des_key_sched((k),(ks))
+#define des_string_to_key(s,k)\
+ _ossl_old_des_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+ _ossl_old_des_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+ _ossl_old_des_cfb64_encrypt((i),(o),(l),(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+ _ossl_old_des_ofb64_encrypt((i),(o),(l),(ks),(iv),(n))
+
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#endif
+
+const char *_ossl_old_des_options(void);
+void _ossl_old_des_ecb3_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ _ossl_old_des_key_schedule ks1,_ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, int enc);
+DES_LONG _ossl_old_des_cbc_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_cbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ncbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_xcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,
+ _ossl_old_des_cblock *inw,_ossl_old_des_cblock *outw,int enc);
+void _ossl_old_des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,
+ long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ecb_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ _ossl_old_des_key_schedule ks,int enc);
+void _ossl_old_des_encrypt(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt2(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+ _ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_decrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+ _ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_ede3_cbc_encrypt(_ossl_old_des_cblock *input, _ossl_old_des_cblock *output,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num);
+#if 0
+void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), _ossl_old_des_cblock (*in_white),
+ _ossl_old_des_cblock (*out_white));
+#endif
+
+int _ossl_old_des_enc_read(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+ _ossl_old_des_cblock *iv);
+int _ossl_old_des_enc_write(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+ _ossl_old_des_cblock *iv);
+char *_ossl_old_des_fcrypt(const char *buf,const char *salt, char *ret);
+char *_ossl_old_des_crypt(const char *buf,const char *salt);
+#if !defined(PERL5) && !defined(NeXT)
+char *_ossl_old_crypt(const char *buf,const char *salt);
+#endif
+void _ossl_old_des_ofb_encrypt(unsigned char *in,unsigned char *out,
+ int numbits,long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_pcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+DES_LONG _ossl_old_des_quad_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ long length,int out_count,_ossl_old_des_cblock *seed);
+void _ossl_old_des_random_seed(_ossl_old_des_cblock key);
+void _ossl_old_des_random_key(_ossl_old_des_cblock ret);
+int _ossl_old_des_read_password(_ossl_old_des_cblock *key,const char *prompt,int verify);
+int _ossl_old_des_read_2passwords(_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2,
+ const char *prompt,int verify);
+void _ossl_old_des_set_odd_parity(_ossl_old_des_cblock *key);
+int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key);
+int _ossl_old_des_set_key(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+int _ossl_old_des_key_sched(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+void _ossl_old_des_string_to_key(char *str,_ossl_old_des_cblock *key);
+void _ossl_old_des_string_to_2keys(char *str,_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2);
+void _ossl_old_des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ _ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ _ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num);
+
+void _ossl_096_des_random_seed(des_cblock *key);
+
+/* The following definitions provide compatibility with the MIT Kerberos
+ * library. The _ossl_old_des_key_schedule structure is not binary compatible. */
+
+#define _KERBEROS_DES_H
+
+#define KRBDES_ENCRYPT DES_ENCRYPT
+#define KRBDES_DECRYPT DES_DECRYPT
+
+#ifdef KERBEROS
+# define ENCRYPT DES_ENCRYPT
+# define DECRYPT DES_DECRYPT
+#endif
+
+#ifndef NCOMPAT
+# define C_Block des_cblock
+# define Key_schedule des_key_schedule
+# define KEY_SZ DES_KEY_SZ
+# define string_to_key des_string_to_key
+# define read_pw_string des_read_pw_string
+# define random_key des_random_key
+# define pcbc_encrypt des_pcbc_encrypt
+# define set_key des_set_key
+# define key_sched des_key_sched
+# define ecb_encrypt des_ecb_encrypt
+# define cbc_encrypt des_cbc_encrypt
+# define ncbc_encrypt des_ncbc_encrypt
+# define xcbc_encrypt des_xcbc_encrypt
+# define cbc_cksum des_cbc_cksum
+# define quad_cksum des_quad_cksum
+# define check_parity des_check_key_parity
+#endif
+
+#define des_fixup_key_parity DES_fixup_key_parity
+
+#ifdef __cplusplus
+}
+#endif
+
+/* for DES_read_pw_string et al */
+#include <openssl/ui_compat.h>
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dh.h b/src/Mayaqua/win32_inc/openssl/dh.h
new file mode 100644
index 00000000..18d787f9
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dh.h
@@ -0,0 +1,245 @@
+/* crypto/dh/dh.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DH_H
+#define HEADER_DH_H
+
+#include <openssl/e_os2.h>
+
+#ifdef OPENSSL_NO_DH
+#error DH is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifndef OPENSSL_DH_MAX_MODULUS_BITS
+# define OPENSSL_DH_MAX_MODULUS_BITS 10000
+#endif
+
+#define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
+
+#define DH_FLAG_CACHE_MONT_P 0x01
+#define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dh_st DH; */
+/* typedef struct dh_method DH_METHOD; */
+
+struct dh_method
+ {
+ const char *name;
+ /* Methods here */
+ int (*generate_key)(DH *dh);
+ int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+ int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+
+ int (*init)(DH *dh);
+ int (*finish)(DH *dh);
+ int flags;
+ char *app_data;
+ /* If this is non-NULL, it will be used to generate parameters */
+ int (*generate_params)(DH *dh, int prime_len, int generator, BN_GENCB *cb);
+ };
+
+struct dh_st
+ {
+ /* This first argument is used to pick up errors when
+ * a DH is passed instead of a EVP_PKEY */
+ int pad;
+ int version;
+ BIGNUM *p;
+ BIGNUM *g;
+ long length; /* optional */
+ BIGNUM *pub_key; /* g^x */
+ BIGNUM *priv_key; /* x */
+
+ int flags;
+ BN_MONT_CTX *method_mont_p;
+ /* Place holders if we want to do X9.42 DH */
+ BIGNUM *q;
+ BIGNUM *j;
+ unsigned char *seed;
+ int seedlen;
+ BIGNUM *counter;
+
+ int references;
+ CRYPTO_EX_DATA ex_data;
+ const DH_METHOD *meth;
+ ENGINE *engine;
+ };
+
+#define DH_GENERATOR_2 2
+/* #define DH_GENERATOR_3 3 */
+#define DH_GENERATOR_5 5
+
+/* DH_check error codes */
+#define DH_CHECK_P_NOT_PRIME 0x01
+#define DH_CHECK_P_NOT_SAFE_PRIME 0x02
+#define DH_UNABLE_TO_CHECK_GENERATOR 0x04
+#define DH_NOT_SUITABLE_GENERATOR 0x08
+
+/* DH_check_pub_key error codes */
+#define DH_CHECK_PUBKEY_TOO_SMALL 0x01
+#define DH_CHECK_PUBKEY_TOO_LARGE 0x02
+
+/* primes p where (p-1)/2 is prime too are called "safe"; we define
+ this for backward compatibility: */
+#define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME
+
+#define DHparams_dup(x) ASN1_dup_of_const(DH,i2d_DHparams,d2i_DHparams,x)
+#define d2i_DHparams_fp(fp,x) (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+ (char *(*)())d2i_DHparams,(fp),(unsigned char **)(x))
+#define i2d_DHparams_fp(fp,x) ASN1_i2d_fp(i2d_DHparams,(fp), \
+ (unsigned char *)(x))
+#define d2i_DHparams_bio(bp,x) ASN1_d2i_bio_of(DH,DH_new,d2i_DHparams,bp,x)
+#define i2d_DHparams_bio(bp,x) ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x)
+
+const DH_METHOD *DH_OpenSSL(void);
+
+#ifdef OPENSSL_FIPS
+DH * FIPS_dh_new(void);
+void FIPS_dh_free(DH *dh);
+#endif
+
+void DH_set_default_method(const DH_METHOD *meth);
+const DH_METHOD *DH_get_default_method(void);
+int DH_set_method(DH *dh, const DH_METHOD *meth);
+DH *DH_new_method(ENGINE *engine);
+
+DH * DH_new(void);
+void DH_free(DH *dh);
+int DH_up_ref(DH *dh);
+int DH_size(const DH *dh);
+int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DH_set_ex_data(DH *d, int idx, void *arg);
+void *DH_get_ex_data(DH *d, int idx);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DH * DH_generate_parameters(int prime_len,int generator,
+ void (*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DH_generate_parameters_ex(DH *dh, int prime_len,int generator, BN_GENCB *cb);
+
+int DH_check(const DH *dh,int *codes);
+int DH_check_pub_key(const DH *dh,const BIGNUM *pub_key, int *codes);
+int DH_generate_key(DH *dh);
+int DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+DH * d2i_DHparams(DH **a,const unsigned char **pp, long length);
+int i2d_DHparams(const DH *a,unsigned char **pp);
+#ifndef OPENSSL_NO_FP_API
+int DHparams_print_fp(FILE *fp, const DH *x);
+#endif
+#ifndef OPENSSL_NO_BIO
+int DHparams_print(BIO *bp, const DH *x);
+#else
+int DHparams_print(char *bp, const DH *x);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DH_strings(void);
+
+/* Error codes for the DH functions. */
+
+/* Function codes. */
+#define DH_F_COMPUTE_KEY 102
+#define DH_F_DHPARAMS_PRINT 100
+#define DH_F_DHPARAMS_PRINT_FP 101
+#define DH_F_DH_BUILTIN_GENPARAMS 106
+#define DH_F_DH_COMPUTE_KEY 107
+#define DH_F_DH_GENERATE_KEY 108
+#define DH_F_DH_GENERATE_PARAMETERS 109
+#define DH_F_DH_NEW_METHOD 105
+#define DH_F_GENERATE_KEY 103
+#define DH_F_GENERATE_PARAMETERS 104
+
+/* Reason codes. */
+#define DH_R_BAD_GENERATOR 101
+#define DH_R_INVALID_PUBKEY 102
+#define DH_R_KEY_SIZE_TOO_SMALL 104
+#define DH_R_MODULUS_TOO_LARGE 103
+#define DH_R_NO_PRIVATE_VALUE 100
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dsa.h b/src/Mayaqua/win32_inc/openssl/dsa.h
new file mode 100644
index 00000000..a826ffe5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dsa.h
@@ -0,0 +1,324 @@
+/* crypto/dsa/dsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. He basically did the
+ * work and I have just tweaked them a little to fit into my
+ * stylistic vision for SSLeay :-) */
+
+#ifndef HEADER_DSA_H
+#define HEADER_DSA_H
+
+#include <openssl/e_os2.h>
+
+#ifdef OPENSSL_NO_DSA
+#error DSA is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/ossl_typ.h>
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+#endif
+#endif
+
+#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+#endif
+
+#define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024
+
+#define DSA_FLAG_CACHE_MONT_P 0x01
+#define DSA_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DSA
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+
+/* If this flag is set the DSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define DSA_FLAG_FIPS_METHOD 0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define DSA_FLAG_NON_FIPS_ALLOW 0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_DSA_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dsa_st DSA; */
+/* typedef struct dsa_method DSA_METHOD; */
+
+typedef struct DSA_SIG_st
+ {
+ BIGNUM *r;
+ BIGNUM *s;
+ } DSA_SIG;
+
+struct dsa_method
+ {
+ const char *name;
+ DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa);
+ int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp);
+ int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+ int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
+ BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *in_mont);
+ int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+ int (*init)(DSA *dsa);
+ int (*finish)(DSA *dsa);
+ int flags;
+ char *app_data;
+ /* If this is non-NULL, it is used to generate DSA parameters */
+ int (*dsa_paramgen)(DSA *dsa, int bits,
+ unsigned char *seed, int seed_len,
+ int *counter_ret, unsigned long *h_ret,
+ BN_GENCB *cb);
+ /* If this is non-NULL, it is used to generate DSA keys */
+ int (*dsa_keygen)(DSA *dsa);
+ };
+
+struct dsa_st
+ {
+ /* This first variable is used to pick up errors where
+ * a DSA is passed instead of of a EVP_PKEY */
+ int pad;
+ long version;
+ int write_params;
+ BIGNUM *p;
+ BIGNUM *q; /* == 20 */
+ BIGNUM *g;
+
+ BIGNUM *pub_key; /* y public key */
+ BIGNUM *priv_key; /* x private key */
+
+ BIGNUM *kinv; /* Signing pre-calc */
+ BIGNUM *r; /* Signing pre-calc */
+
+ int flags;
+ /* Normally used to cache montgomery values */
+ BN_MONT_CTX *method_mont_p;
+ int references;
+ CRYPTO_EX_DATA ex_data;
+ const DSA_METHOD *meth;
+ /* functional reference if 'meth' is ENGINE-provided */
+ ENGINE *engine;
+ };
+
+#define DSAparams_dup(x) ASN1_dup_of_const(DSA,i2d_DSAparams,d2i_DSAparams,x)
+#define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
+ (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x))
+#define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \
+ (unsigned char *)(x))
+#define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x)
+#define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x)
+
+
+DSA_SIG * DSA_SIG_new(void);
+void DSA_SIG_free(DSA_SIG *a);
+int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp);
+DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length);
+
+DSA_SIG * DSA_do_sign(const unsigned char *dgst,int dlen,DSA *dsa);
+int DSA_do_verify(const unsigned char *dgst,int dgst_len,
+ DSA_SIG *sig,DSA *dsa);
+
+const DSA_METHOD *DSA_OpenSSL(void);
+
+void DSA_set_default_method(const DSA_METHOD *);
+const DSA_METHOD *DSA_get_default_method(void);
+int DSA_set_method(DSA *dsa, const DSA_METHOD *);
+
+#ifdef OPENSSL_FIPS
+DSA * FIPS_dsa_new(void);
+void FIPS_dsa_free (DSA *r);
+#endif
+
+DSA * DSA_new(void);
+DSA * DSA_new_method(ENGINE *engine);
+void DSA_free (DSA *r);
+/* "up" the DSA object's reference count */
+int DSA_up_ref(DSA *r);
+int DSA_size(const DSA *);
+ /* next 4 return -1 on error */
+int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp);
+int DSA_sign(int type,const unsigned char *dgst,int dlen,
+ unsigned char *sig, unsigned int *siglen, DSA *dsa);
+int DSA_verify(int type,const unsigned char *dgst,int dgst_len,
+ const unsigned char *sigbuf, int siglen, DSA *dsa);
+int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DSA_set_ex_data(DSA *d, int idx, void *arg);
+void *DSA_get_ex_data(DSA *d, int idx);
+
+DSA * d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
+DSA * d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
+DSA * d2i_DSAparams(DSA **a, const unsigned char **pp, long length);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DSA * DSA_generate_parameters(int bits,
+ unsigned char *seed,int seed_len,
+ int *counter_ret, unsigned long *h_ret,void
+ (*callback)(int, int, void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DSA_generate_parameters_ex(DSA *dsa, int bits,
+ unsigned char *seed,int seed_len,
+ int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+int DSA_generate_key(DSA *a);
+int i2d_DSAPublicKey(const DSA *a, unsigned char **pp);
+int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+int i2d_DSAparams(const DSA *a,unsigned char **pp);
+
+#ifndef OPENSSL_NO_BIO
+int DSAparams_print(BIO *bp, const DSA *x);
+int DSA_print(BIO *bp, const DSA *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int DSAparams_print_fp(FILE *fp, const DSA *x);
+int DSA_print_fp(FILE *bp, const DSA *x, int off);
+#endif
+
+#define DSS_prime_checks 50
+/* Primality test according to FIPS PUB 186[-1], Appendix 2.1:
+ * 50 rounds of Rabin-Miller */
+#define DSA_is_prime(n, callback, cb_arg) \
+ BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
+
+#ifndef OPENSSL_NO_DH
+/* Convert DSA structure (key or just parameters) into DH structure
+ * (be careful to avoid small subgroup attacks when using this!) */
+DH *DSA_dup_DH(const DSA *r);
+#endif
+
+#ifdef OPENSSL_FIPS
+int FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig);
+int FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSA_strings(void);
+
+/* Error codes for the DSA functions. */
+
+/* Function codes. */
+#define DSA_F_D2I_DSA_SIG 110
+#define DSA_F_DSAPARAMS_PRINT 100
+#define DSA_F_DSAPARAMS_PRINT_FP 101
+#define DSA_F_DSA_BUILTIN_KEYGEN 119
+#define DSA_F_DSA_BUILTIN_PARAMGEN 118
+#define DSA_F_DSA_DO_SIGN 112
+#define DSA_F_DSA_DO_VERIFY 113
+#define DSA_F_DSA_GENERATE_PARAMETERS 117
+#define DSA_F_DSA_NEW_METHOD 103
+#define DSA_F_DSA_PRINT 104
+#define DSA_F_DSA_PRINT_FP 105
+#define DSA_F_DSA_SET_DEFAULT_METHOD 115
+#define DSA_F_DSA_SET_METHOD 116
+#define DSA_F_DSA_SIGN 106
+#define DSA_F_DSA_SIGN_SETUP 107
+#define DSA_F_DSA_SIG_NEW 109
+#define DSA_F_DSA_VERIFY 108
+#define DSA_F_I2D_DSA_SIG 111
+#define DSA_F_SIG_CB 114
+
+/* Reason codes. */
+#define DSA_R_BAD_Q_VALUE 102
+#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100
+#define DSA_R_KEY_SIZE_TOO_SMALL 106
+#define DSA_R_MISSING_PARAMETERS 101
+#define DSA_R_MODULUS_TOO_LARGE 103
+#define DSA_R_NON_FIPS_METHOD 104
+#define DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 105
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dso.h b/src/Mayaqua/win32_inc/openssl/dso.h
new file mode 100644
index 00000000..18362319
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dso.h
@@ -0,0 +1,368 @@
+/* dso.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DSO_H
+#define HEADER_DSO_H
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These values are used as commands to DSO_ctrl() */
+#define DSO_CTRL_GET_FLAGS 1
+#define DSO_CTRL_SET_FLAGS 2
+#define DSO_CTRL_OR_FLAGS 3
+
+/* By default, DSO_load() will translate the provided filename into a form
+ * typical for the platform (more specifically the DSO_METHOD) using the
+ * dso_name_converter function of the method. Eg. win32 will transform "blah"
+ * into "blah.dll", and dlfcn will transform it into "libblah.so". The
+ * behaviour can be overriden by setting the name_converter callback in the DSO
+ * object (using DSO_set_name_converter()). This callback could even utilise
+ * the DSO_METHOD's converter too if it only wants to override behaviour for
+ * one or two possible DSO methods. However, the following flag can be set in a
+ * DSO to prevent *any* native name-translation at all - eg. if the caller has
+ * prompted the user for a path to a driver library so the filename should be
+ * interpreted as-is. */
+#define DSO_FLAG_NO_NAME_TRANSLATION 0x01
+/* An extra flag to give if only the extension should be added as
+ * translation. This is obviously only of importance on Unix and
+ * other operating systems where the translation also may prefix
+ * the name with something, like 'lib', and ignored everywhere else.
+ * This flag is also ignored if DSO_FLAG_NO_NAME_TRANSLATION is used
+ * at the same time. */
+#define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02
+
+/* The following flag controls the translation of symbol names to upper
+ * case. This is currently only being implemented for OpenVMS.
+ */
+#define DSO_FLAG_UPCASE_SYMBOL 0x10
+
+/* This flag loads the library with public symbols.
+ * Meaning: The exported symbols of this library are public
+ * to all libraries loaded after this library.
+ * At the moment only implemented in unix.
+ */
+#define DSO_FLAG_GLOBAL_SYMBOLS 0x20
+
+
+typedef void (*DSO_FUNC_TYPE)(void);
+
+typedef struct dso_st DSO;
+
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that transform filenames. They are passed a DSO structure pointer
+ * (or NULL if they are to be used independantly of a DSO object) and a
+ * filename to transform. They should either return NULL (if there is an error
+ * condition) or a newly allocated string containing the transformed form that
+ * the caller will need to free with OPENSSL_free() when done. */
+typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *);
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that merge two file specifications. They are passed a
+ * DSO structure pointer (or NULL if they are to be used independantly of
+ * a DSO object) and two file specifications to merge. They should
+ * either return NULL (if there is an error condition) or a newly allocated
+ * string containing the result of merging that the caller will need
+ * to free with OPENSSL_free() when done.
+ * Here, merging means that bits and pieces are taken from each of the
+ * file specifications and added together in whatever fashion that is
+ * sensible for the DSO method in question. The only rule that really
+ * applies is that if the two specification contain pieces of the same
+ * type, the copy from the first string takes priority. One could see
+ * it as the first specification is the one given by the user and the
+ * second being a bunch of defaults to add on if they're missing in the
+ * first. */
+typedef char* (*DSO_MERGER_FUNC)(DSO *, const char *, const char *);
+
+typedef struct dso_meth_st
+ {
+ const char *name;
+ /* Loads a shared library, NB: new DSO_METHODs must ensure that a
+ * successful load populates the loaded_filename field, and likewise a
+ * successful unload OPENSSL_frees and NULLs it out. */
+ int (*dso_load)(DSO *dso);
+ /* Unloads a shared library */
+ int (*dso_unload)(DSO *dso);
+ /* Binds a variable */
+ void *(*dso_bind_var)(DSO *dso, const char *symname);
+ /* Binds a function - assumes a return type of DSO_FUNC_TYPE.
+ * This should be cast to the real function prototype by the
+ * caller. Platforms that don't have compatible representations
+ * for different prototypes (this is possible within ANSI C)
+ * are highly unlikely to have shared libraries at all, let
+ * alone a DSO_METHOD implemented for them. */
+ DSO_FUNC_TYPE (*dso_bind_func)(DSO *dso, const char *symname);
+
+/* I don't think this would actually be used in any circumstances. */
+#if 0
+ /* Unbinds a variable */
+ int (*dso_unbind_var)(DSO *dso, char *symname, void *symptr);
+ /* Unbinds a function */
+ int (*dso_unbind_func)(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
+#endif
+ /* The generic (yuck) "ctrl()" function. NB: Negative return
+ * values (rather than zero) indicate errors. */
+ long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg);
+ /* The default DSO_METHOD-specific function for converting filenames to
+ * a canonical native form. */
+ DSO_NAME_CONVERTER_FUNC dso_name_converter;
+ /* The default DSO_METHOD-specific function for converting filenames to
+ * a canonical native form. */
+ DSO_MERGER_FUNC dso_merger;
+
+ /* [De]Initialisation handlers. */
+ int (*init)(DSO *dso);
+ int (*finish)(DSO *dso);
+ } DSO_METHOD;
+
+/**********************************************************************/
+/* The low-level handle type used to refer to a loaded shared library */
+
+struct dso_st
+ {
+ DSO_METHOD *meth;
+ /* Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS
+ * doesn't use anything but will need to cache the filename
+ * for use in the dso_bind handler. All in all, let each
+ * method control its own destiny. "Handles" and such go in
+ * a STACK. */
+ STACK *meth_data;
+ int references;
+ int flags;
+ /* For use by applications etc ... use this for your bits'n'pieces,
+ * don't touch meth_data! */
+ CRYPTO_EX_DATA ex_data;
+ /* If this callback function pointer is set to non-NULL, then it will
+ * be used in DSO_load() in place of meth->dso_name_converter. NB: This
+ * should normally set using DSO_set_name_converter(). */
+ DSO_NAME_CONVERTER_FUNC name_converter;
+ /* If this callback function pointer is set to non-NULL, then it will
+ * be used in DSO_load() in place of meth->dso_merger. NB: This
+ * should normally set using DSO_set_merger(). */
+ DSO_MERGER_FUNC merger;
+ /* This is populated with (a copy of) the platform-independant
+ * filename used for this DSO. */
+ char *filename;
+ /* This is populated with (a copy of) the translated filename by which
+ * the DSO was actually loaded. It is NULL iff the DSO is not currently
+ * loaded. NB: This is here because the filename translation process
+ * may involve a callback being invoked more than once not only to
+ * convert to a platform-specific form, but also to try different
+ * filenames in the process of trying to perform a load. As such, this
+ * variable can be used to indicate (a) whether this DSO structure
+ * corresponds to a loaded library or not, and (b) the filename with
+ * which it was actually loaded. */
+ char *loaded_filename;
+ };
+
+
+DSO * DSO_new(void);
+DSO * DSO_new_method(DSO_METHOD *method);
+int DSO_free(DSO *dso);
+int DSO_flags(DSO *dso);
+int DSO_up_ref(DSO *dso);
+long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg);
+
+/* This function sets the DSO's name_converter callback. If it is non-NULL,
+ * then it will be used instead of the associated DSO_METHOD's function. If
+ * oldcb is non-NULL then it is set to the function pointer value being
+ * replaced. Return value is non-zero for success. */
+int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
+ DSO_NAME_CONVERTER_FUNC *oldcb);
+/* These functions can be used to get/set the platform-independant filename
+ * used for a DSO. NB: set will fail if the DSO is already loaded. */
+const char *DSO_get_filename(DSO *dso);
+int DSO_set_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's name_converter callback to translate a
+ * filename, or if the callback isn't set it will instead use the DSO_METHOD's
+ * converter. If "filename" is NULL, the "filename" in the DSO itself will be
+ * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is
+ * simply duplicated. NB: This function is usually called from within a
+ * DSO_METHOD during the processing of a DSO_load() call, and is exposed so that
+ * caller-created DSO_METHODs can do the same thing. A non-NULL return value
+ * will need to be OPENSSL_free()'d. */
+char *DSO_convert_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's merger callback to merge two file
+ * specifications, or if the callback isn't set it will instead use the
+ * DSO_METHOD's merger. A non-NULL return value will need to be
+ * OPENSSL_free()'d. */
+char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2);
+/* If the DSO is currently loaded, this returns the filename that it was loaded
+ * under, otherwise it returns NULL. So it is also useful as a test as to
+ * whether the DSO is currently loaded. NB: This will not necessarily return
+ * the same value as DSO_convert_filename(dso, dso->filename), because the
+ * DSO_METHOD's load function may have tried a variety of filenames (with
+ * and/or without the aid of the converters) before settling on the one it
+ * actually loaded. */
+const char *DSO_get_loaded_filename(DSO *dso);
+
+void DSO_set_default_method(DSO_METHOD *meth);
+DSO_METHOD *DSO_get_default_method(void);
+DSO_METHOD *DSO_get_method(DSO *dso);
+DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth);
+
+/* The all-singing all-dancing load function, you normally pass NULL
+ * for the first and third parameters. Use DSO_up and DSO_free for
+ * subsequent reference count handling. Any flags passed in will be set
+ * in the constructed DSO after its init() function but before the
+ * load operation. If 'dso' is non-NULL, 'flags' is ignored. */
+DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags);
+
+/* This function binds to a variable inside a shared library. */
+void *DSO_bind_var(DSO *dso, const char *symname);
+
+/* This function binds to a function inside a shared library. */
+DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname);
+
+/* This method is the default, but will beg, borrow, or steal whatever
+ * method should be the default on any particular platform (including
+ * DSO_METH_null() if necessary). */
+DSO_METHOD *DSO_METHOD_openssl(void);
+
+/* This method is defined for all platforms - if a platform has no
+ * DSO support then this will be the only method! */
+DSO_METHOD *DSO_METHOD_null(void);
+
+/* If DSO_DLFCN is defined, the standard dlfcn.h-style functions
+ * (dlopen, dlclose, dlsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dlfcn(void);
+
+/* If DSO_DL is defined, the standard dl.h-style functions (shl_load,
+ * shl_unload, shl_findsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dl(void);
+
+/* If WIN32 is defined, use DLLs. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_win32(void);
+
+/* If VMS is defined, use shared images. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_vms(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSO_strings(void);
+
+/* Error codes for the DSO functions. */
+
+/* Function codes. */
+#define DSO_F_DLFCN_BIND_FUNC 100
+#define DSO_F_DLFCN_BIND_VAR 101
+#define DSO_F_DLFCN_LOAD 102
+#define DSO_F_DLFCN_MERGER 130
+#define DSO_F_DLFCN_NAME_CONVERTER 123
+#define DSO_F_DLFCN_UNLOAD 103
+#define DSO_F_DL_BIND_FUNC 104
+#define DSO_F_DL_BIND_VAR 105
+#define DSO_F_DL_LOAD 106
+#define DSO_F_DL_MERGER 131
+#define DSO_F_DL_NAME_CONVERTER 124
+#define DSO_F_DL_UNLOAD 107
+#define DSO_F_DSO_BIND_FUNC 108
+#define DSO_F_DSO_BIND_VAR 109
+#define DSO_F_DSO_CONVERT_FILENAME 126
+#define DSO_F_DSO_CTRL 110
+#define DSO_F_DSO_FREE 111
+#define DSO_F_DSO_GET_FILENAME 127
+#define DSO_F_DSO_GET_LOADED_FILENAME 128
+#define DSO_F_DSO_LOAD 112
+#define DSO_F_DSO_MERGE 132
+#define DSO_F_DSO_NEW_METHOD 113
+#define DSO_F_DSO_SET_FILENAME 129
+#define DSO_F_DSO_SET_NAME_CONVERTER 122
+#define DSO_F_DSO_UP_REF 114
+#define DSO_F_VMS_BIND_SYM 115
+#define DSO_F_VMS_LOAD 116
+#define DSO_F_VMS_MERGER 133
+#define DSO_F_VMS_UNLOAD 117
+#define DSO_F_WIN32_BIND_FUNC 118
+#define DSO_F_WIN32_BIND_VAR 119
+#define DSO_F_WIN32_JOINER 135
+#define DSO_F_WIN32_LOAD 120
+#define DSO_F_WIN32_MERGER 134
+#define DSO_F_WIN32_NAME_CONVERTER 125
+#define DSO_F_WIN32_SPLITTER 136
+#define DSO_F_WIN32_UNLOAD 121
+
+/* Reason codes. */
+#define DSO_R_CTRL_FAILED 100
+#define DSO_R_DSO_ALREADY_LOADED 110
+#define DSO_R_EMPTY_FILE_STRUCTURE 113
+#define DSO_R_FAILURE 114
+#define DSO_R_FILENAME_TOO_BIG 101
+#define DSO_R_FINISH_FAILED 102
+#define DSO_R_INCORRECT_FILE_SYNTAX 115
+#define DSO_R_LOAD_FAILED 103
+#define DSO_R_NAME_TRANSLATION_FAILED 109
+#define DSO_R_NO_FILENAME 111
+#define DSO_R_NO_FILE_SPECIFICATION 116
+#define DSO_R_NULL_HANDLE 104
+#define DSO_R_SET_FILENAME_FAILED 112
+#define DSO_R_STACK_ERROR 105
+#define DSO_R_SYM_FAILURE 106
+#define DSO_R_UNLOAD_FAILED 107
+#define DSO_R_UNSUPPORTED 108
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dtls1.h b/src/Mayaqua/win32_inc/openssl/dtls1.h
new file mode 100644
index 00000000..d196356b
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dtls1.h
@@ -0,0 +1,265 @@
+/* ssl/dtls1.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DTLS1_H
+#define HEADER_DTLS1_H
+
+#include <openssl/buffer.h>
+#include <openssl/pqueue.h>
+#ifdef OPENSSL_SYS_VMS
+#include <resource.h>
+#include <sys/timeb.h>
+#endif
+#ifdef OPENSSL_SYS_WIN32
+/* Needed for struct timeval */
+#include <winsock.h>
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
+#include <sys/timeval.h>
+#else
+#include <sys/time.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DTLS1_VERSION 0xFEFF
+#define DTLS1_BAD_VER 0x0100
+
+#if 0
+/* this alert description is not specified anywhere... */
+#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
+#endif
+
+/* lengths of messages */
+#define DTLS1_COOKIE_LENGTH 256
+
+#define DTLS1_RT_HEADER_LENGTH 13
+
+#define DTLS1_HM_HEADER_LENGTH 12
+
+#define DTLS1_HM_BAD_FRAGMENT -2
+#define DTLS1_HM_FRAGMENT_RETRY -3
+
+#define DTLS1_CCS_HEADER_LENGTH 1
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#define DTLS1_AL_HEADER_LENGTH 7
+#else
+#define DTLS1_AL_HEADER_LENGTH 2
+#endif
+
+
+typedef struct dtls1_bitmap_st
+ {
+ PQ_64BIT map;
+ unsigned long length; /* sizeof the bitmap in bits */
+ PQ_64BIT max_seq_num; /* max record number seen so far */
+ } DTLS1_BITMAP;
+
+struct dtls1_retransmit_state
+ {
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ const EVP_MD *write_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *compress; /* compression */
+#else
+ char *compress;
+#endif
+ SSL_SESSION *session;
+ unsigned short epoch;
+ };
+
+struct hm_header_st
+ {
+ unsigned char type;
+ unsigned long msg_len;
+ unsigned short seq;
+ unsigned long frag_off;
+ unsigned long frag_len;
+ unsigned int is_ccs;
+ struct dtls1_retransmit_state saved_retransmit_state;
+ };
+
+struct ccs_header_st
+ {
+ unsigned char type;
+ unsigned short seq;
+ };
+
+struct dtls1_timeout_st
+ {
+ /* Number of read timeouts so far */
+ unsigned int read_timeouts;
+
+ /* Number of write timeouts so far */
+ unsigned int write_timeouts;
+
+ /* Number of alerts received so far */
+ unsigned int num_alerts;
+ };
+
+typedef struct record_pqueue_st
+ {
+ unsigned short epoch;
+ pqueue q;
+ } record_pqueue;
+
+typedef struct hm_fragment_st
+ {
+ struct hm_header_st msg_header;
+ unsigned char *fragment;
+ unsigned char *reassembly;
+ } hm_fragment;
+
+typedef struct dtls1_state_st
+ {
+ unsigned int send_cookie;
+ unsigned char cookie[DTLS1_COOKIE_LENGTH];
+ unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+ unsigned int cookie_len;
+
+ /*
+ * The current data and handshake epoch. This is initially
+ * undefined, and starts at zero once the initial handshake is
+ * completed
+ */
+ unsigned short r_epoch;
+ unsigned short w_epoch;
+
+ /* records being received in the current epoch */
+ DTLS1_BITMAP bitmap;
+
+ /* renegotiation starts a new set of sequence numbers */
+ DTLS1_BITMAP next_bitmap;
+
+ /* handshake message numbers */
+ unsigned short handshake_write_seq;
+ unsigned short next_handshake_write_seq;
+
+ unsigned short handshake_read_seq;
+
+ /* save last sequence number for retransmissions */
+ unsigned char last_write_sequence[8];
+
+ /* Received handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+
+ /* Buffered handshake messages */
+ pqueue buffered_messages;
+
+ /* Buffered (sent) handshake records */
+ pqueue sent_messages;
+
+ /* Buffered application records.
+ * Only for records between CCS and Finished
+ * to prevent either protocol violation or
+ * unnecessary message loss.
+ */
+ record_pqueue buffered_app_data;
+
+ /* Is set when listening for new connections with dtls1_listen() */
+ unsigned int listen;
+
+ unsigned int mtu; /* max DTLS packet size */
+
+ struct hm_header_st w_msg_hdr;
+ struct hm_header_st r_msg_hdr;
+
+ struct dtls1_timeout_st timeout;
+
+ /* Indicates when the last handshake msg sent will timeout */
+ struct timeval next_timeout;
+
+ /* Timeout duration */
+ unsigned short timeout_duration;
+
+ /* storage for Alert/Handshake protocol data received but not
+ * yet processed by ssl3_read_bytes: */
+ unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+ unsigned int handshake_fragment_len;
+
+ unsigned int retransmitting;
+ unsigned int change_cipher_spec_ok;
+
+ } DTLS1_STATE;
+
+typedef struct dtls1_record_data_st
+ {
+ unsigned char *packet;
+ unsigned int packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+ } DTLS1_RECORD_DATA;
+
+
+/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
+#define DTLS1_TMO_READ_COUNT 2
+#define DTLS1_TMO_WRITE_COUNT 2
+
+#define DTLS1_TMO_ALERT_COUNT 12
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/e_os2.h b/src/Mayaqua/win32_inc/openssl/e_os2.h
new file mode 100644
index 00000000..79bfe248
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/e_os2.h
@@ -0,0 +1,279 @@
+/* e_os2.h */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifndef HEADER_E_OS2_H
+#define HEADER_E_OS2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************
+ * Detect operating systems. This probably needs completing.
+ * The result is that at least one OPENSSL_SYS_os macro should be defined.
+ * However, if none is defined, Unix is assumed.
+ **/
+
+#define OPENSSL_SYS_UNIX
+
+/* ----------------------- Macintosh, before MacOS X ----------------------- */
+#if defined(__MWERKS__) && defined(macintosh) || defined(OPENSSL_SYSNAME_MAC)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MACINTOSH_CLASSIC
+#endif
+
+/* ----------------------- NetWare ----------------------------------------- */
+#if defined(NETWARE) || defined(OPENSSL_SYSNAME_NETWARE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_NETWARE
+#endif
+
+/* ---------------------- Microsoft operating systems ---------------------- */
+
+/* Note that MSDOS actually denotes 32-bit environments running on top of
+ MS-DOS, such as DJGPP one. */
+#if defined(OPENSSL_SYSNAME_MSDOS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MSDOS
+#endif
+
+/* For 32 bit environment, there seems to be the CygWin environment and then
+ all the others that try to do the same thing Microsoft does... */
+#if defined(OPENSSL_SYSNAME_UWIN)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32_UWIN
+#else
+# if defined(__CYGWIN32__) || defined(OPENSSL_SYSNAME_CYGWIN32)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32_CYGWIN
+# else
+# if defined(_WIN32) || defined(OPENSSL_SYSNAME_WIN32)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32
+# endif
+# if defined(OPENSSL_SYSNAME_WINNT)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINNT
+# endif
+# if defined(OPENSSL_SYSNAME_WINCE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINCE
+# endif
+# endif
+#endif
+
+/* Anything that tries to look like Microsoft is "Windows" */
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_SYS_MSDOS
+# define OPENSSL_SYS_MSDOS
+# endif
+#endif
+
+/* DLL settings. This part is a bit tough, because it's up to the application
+ implementor how he or she will link the application, so it requires some
+ macro to be used. */
+#ifdef OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_OPT_WINDLL
+# if defined(_WINDLL) /* This is used when building OpenSSL to indicate that
+ DLL linkage should be used */
+# define OPENSSL_OPT_WINDLL
+# endif
+# endif
+#endif
+
+/* -------------------------------- OpenVMS -------------------------------- */
+#if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYSNAME_VMS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_VMS
+# if defined(__DECC)
+# define OPENSSL_SYS_VMS_DECC
+# elif defined(__DECCXX)
+# define OPENSSL_SYS_VMS_DECC
+# define OPENSSL_SYS_VMS_DECCXX
+# else
+# define OPENSSL_SYS_VMS_NODECC
+# endif
+#endif
+
+/* --------------------------------- OS/2 ---------------------------------- */
+#if defined(__EMX__) || defined(__OS2__)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_OS2
+#endif
+
+/* --------------------------------- Unix ---------------------------------- */
+#ifdef OPENSSL_SYS_UNIX
+# if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX)
+# define OPENSSL_SYS_LINUX
+# endif
+# ifdef OPENSSL_SYSNAME_MPE
+# define OPENSSL_SYS_MPE
+# endif
+# ifdef OPENSSL_SYSNAME_SNI
+# define OPENSSL_SYS_SNI
+# endif
+# ifdef OPENSSL_SYSNAME_ULTRASPARC
+# define OPENSSL_SYS_ULTRASPARC
+# endif
+# ifdef OPENSSL_SYSNAME_NEWS4
+# define OPENSSL_SYS_NEWS4
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX
+# define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX_RHAPSODY
+# define OPENSSL_SYS_MACOSX_RHAPSODY
+# define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_SUNOS
+# define OPENSSL_SYS_SUNOS
+#endif
+# if defined(_CRAY) || defined(OPENSSL_SYSNAME_CRAY)
+# define OPENSSL_SYS_CRAY
+# endif
+# if defined(_AIX) || defined(OPENSSL_SYSNAME_AIX)
+# define OPENSSL_SYS_AIX
+# endif
+#endif
+
+/* --------------------------------- VOS ----------------------------------- */
+#ifdef OPENSSL_SYSNAME_VOS
+# define OPENSSL_SYS_VOS
+#endif
+
+/* ------------------------------- VxWorks --------------------------------- */
+#ifdef OPENSSL_SYSNAME_VXWORKS
+# define OPENSSL_SYS_VXWORKS
+#endif
+
+/**
+ * That's it for OS-specific stuff
+ *****************************************************************************/
+
+
+/* Specials for I/O an exit */
+#ifdef OPENSSL_SYS_MSDOS
+# define OPENSSL_UNISTD_IO <io.h>
+# define OPENSSL_DECLARE_EXIT extern void exit(int);
+#else
+# define OPENSSL_UNISTD_IO OPENSSL_UNISTD
+# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */
+#endif
+
+/* Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, to define and declare
+ certain global symbols that, with some compilers under VMS, have to be
+ defined and declared explicitely with globaldef and globalref.
+ Definitions of OPENSSL_EXPORT and OPENSSL_IMPORT, to define and declare
+ DLL exports and imports for compilers under Win32. These are a little
+ more complicated to use. Basically, for any library that exports some
+ global variables, the following code must be present in the header file
+ that declares them, before OPENSSL_EXTERN is used:
+
+ #ifdef SOME_BUILD_FLAG_MACRO
+ # undef OPENSSL_EXTERN
+ # define OPENSSL_EXTERN OPENSSL_EXPORT
+ #endif
+
+ The default is to have OPENSSL_EXPORT, OPENSSL_IMPORT and OPENSSL_GLOBAL
+ have some generally sensible values, and for OPENSSL_EXTERN to have the
+ value OPENSSL_IMPORT.
+*/
+
+#if defined(OPENSSL_SYS_VMS_NODECC)
+# define OPENSSL_EXPORT globalref
+# define OPENSSL_IMPORT globalref
+# define OPENSSL_GLOBAL globaldef
+#elif defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL)
+# define OPENSSL_EXPORT extern __declspec(dllexport)
+# define OPENSSL_IMPORT extern __declspec(dllimport)
+# define OPENSSL_GLOBAL
+#else
+# define OPENSSL_EXPORT extern
+# define OPENSSL_IMPORT extern
+# define OPENSSL_GLOBAL
+#endif
+#define OPENSSL_EXTERN OPENSSL_IMPORT
+
+/* Macros to allow global variables to be reached through function calls when
+ required (if a shared library version requvres it, for example.
+ The way it's done allows definitions like this:
+
+ // in foobar.c
+ OPENSSL_IMPLEMENT_GLOBAL(int,foobar) = 0;
+ // in foobar.h
+ OPENSSL_DECLARE_GLOBAL(int,foobar);
+ #define foobar OPENSSL_GLOBAL_REF(foobar)
+*/
+#ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name) \
+ extern type _hide_##name; \
+ type *_shadow_##name(void) { return &_hide_##name; } \
+ static type _hide_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
+# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
+#else
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name) OPENSSL_GLOBAL type _shadow_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
+# define OPENSSL_GLOBAL_REF(name) _shadow_##name
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ebcdic.h b/src/Mayaqua/win32_inc/openssl/ebcdic.h
new file mode 100644
index 00000000..0941c8be
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ebcdic.h
@@ -0,0 +1,19 @@
+/* crypto/ebcdic.h */
+
+#ifndef HEADER_EBCDIC_H
+#define HEADER_EBCDIC_H
+
+#include <sys/types.h>
+
+/* Avoid name clashes with other applications */
+#define os_toascii _openssl_os_toascii
+#define os_toebcdic _openssl_os_toebcdic
+#define ebcdic2ascii _openssl_ebcdic2ascii
+#define ascii2ebcdic _openssl_ascii2ebcdic
+
+extern const unsigned char os_toascii[256];
+extern const unsigned char os_toebcdic[256];
+void *ebcdic2ascii(void *dest, const void *srce, size_t count);
+void *ascii2ebcdic(void *dest, const void *srce, size_t count);
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ec.h b/src/Mayaqua/win32_inc/openssl/ec.h
new file mode 100644
index 00000000..b29901a4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ec.h
@@ -0,0 +1,526 @@
+/* crypto/ec/ec.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_EC_H
+#define HEADER_EC_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_EC
+#error EC is disabled.
+#endif
+
+#include <openssl/asn1.h>
+#include <openssl/symhacks.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#elif defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+
+#ifndef OPENSSL_ECC_MAX_FIELD_BITS
+# define OPENSSL_ECC_MAX_FIELD_BITS 661
+#endif
+
+typedef enum {
+ /* values as defined in X9.62 (ECDSA) and elsewhere */
+ POINT_CONVERSION_COMPRESSED = 2,
+ POINT_CONVERSION_UNCOMPRESSED = 4,
+ POINT_CONVERSION_HYBRID = 6
+} point_conversion_form_t;
+
+
+typedef struct ec_method_st EC_METHOD;
+
+typedef struct ec_group_st
+ /*
+ EC_METHOD *meth;
+ -- field definition
+ -- curve coefficients
+ -- optional generator with associated information (order, cofactor)
+ -- optional extra data (precomputed table for fast computation of multiples of generator)
+ -- ASN1 stuff
+ */
+ EC_GROUP;
+
+typedef struct ec_point_st EC_POINT;
+
+
+/* EC_METHODs for curves over GF(p).
+ * EC_GFp_simple_method provides the basis for the optimized methods.
+ */
+const EC_METHOD *EC_GFp_simple_method(void);
+const EC_METHOD *EC_GFp_mont_method(void);
+const EC_METHOD *EC_GFp_nist_method(void);
+
+/* EC_METHOD for curves over GF(2^m).
+ */
+const EC_METHOD *EC_GF2m_simple_method(void);
+
+
+EC_GROUP *EC_GROUP_new(const EC_METHOD *);
+void EC_GROUP_free(EC_GROUP *);
+void EC_GROUP_clear_free(EC_GROUP *);
+int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *);
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *);
+
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *);
+int EC_METHOD_get_field_type(const EC_METHOD *);
+
+int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *);
+int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *);
+int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
+
+void EC_GROUP_set_curve_name(EC_GROUP *, int nid);
+int EC_GROUP_get_curve_name(const EC_GROUP *);
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *, int flag);
+int EC_GROUP_get_asn1_flag(const EC_GROUP *);
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
+size_t EC_GROUP_get_seed_len(const EC_GROUP *);
+size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+
+int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+int EC_GROUP_set_curve_GF2m(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+
+/* returns the number of bits needed to represent a field element */
+int EC_GROUP_get_degree(const EC_GROUP *);
+
+/* EC_GROUP_check() returns 1 if 'group' defines a valid group, 0 otherwise */
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+/* EC_GROUP_check_discriminant() returns 1 if the discriminant of the
+ * elliptic curve is not zero, 0 otherwise */
+int EC_GROUP_check_discriminant(const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_cmp() returns 0 if both groups are equal and 1 otherwise */
+int EC_GROUP_cmp(const EC_GROUP *, const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
+ * after choosing an appropriate EC_METHOD */
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+
+/* EC_GROUP_new_by_curve_name() creates a EC_GROUP structure
+ * specified by a curve name (in form of a NID) */
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+/* handling of internal curves */
+typedef struct {
+ int nid;
+ const char *comment;
+ } EC_builtin_curve;
+/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number
+ * of all available curves or zero if a error occurred.
+ * In case r ist not zero nitems EC_builtin_curve structures
+ * are filled with the data of the first nitems internal groups */
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+
+
+/* EC_POINT functions */
+
+EC_POINT *EC_POINT_new(const EC_GROUP *);
+void EC_POINT_free(EC_POINT *);
+void EC_POINT_clear_free(EC_POINT *);
+int EC_POINT_copy(EC_POINT *, const EC_POINT *);
+EC_POINT *EC_POINT_dup(const EC_POINT *, const EC_GROUP *);
+
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *);
+
+int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit, BN_CTX *);
+
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit, BN_CTX *);
+
+size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *);
+int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *,
+ const unsigned char *buf, size_t len, BN_CTX *);
+
+/* other interfaces to point2oct/oct2point: */
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form, BIGNUM *, BN_CTX *);
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
+ EC_POINT *, BN_CTX *);
+char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form, BN_CTX *);
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
+ EC_POINT *, BN_CTX *);
+
+int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+
+int EC_POINT_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int EC_POINT_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int EC_POINT_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+
+int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+
+
+int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *);
+int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *);
+
+/* EC_GROUP_precompute_mult() stores multiples of generator for faster point multiplication */
+int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *);
+/* EC_GROUP_have_precompute_mult() reports whether such precomputation has been done */
+int EC_GROUP_have_precompute_mult(const EC_GROUP *);
+
+
+
+/* ASN1 stuff */
+
+/* EC_GROUP_get_basis_type() returns the NID of the basis type
+ * used to represent the field elements */
+int EC_GROUP_get_basis_type(const EC_GROUP *);
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
+ unsigned int *k2, unsigned int *k3);
+
+#define OPENSSL_EC_NAMED_CURVE 0x001
+
+typedef struct ecpk_parameters_st ECPKPARAMETERS;
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
+int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
+
+#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
+#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
+#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
+ (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
+#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
+ (unsigned char *)(x))
+
+#ifndef OPENSSL_NO_BIO
+int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
+#endif
+
+/* the EC_KEY stuff */
+typedef struct ec_key_st EC_KEY;
+
+/* some values for the encoding_flag */
+#define EC_PKEY_NO_PARAMETERS 0x001
+#define EC_PKEY_NO_PUBKEY 0x002
+
+EC_KEY *EC_KEY_new(void);
+EC_KEY *EC_KEY_new_by_curve_name(int nid);
+void EC_KEY_free(EC_KEY *);
+EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *);
+EC_KEY *EC_KEY_dup(const EC_KEY *);
+
+int EC_KEY_up_ref(EC_KEY *);
+
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *);
+int EC_KEY_set_group(EC_KEY *, const EC_GROUP *);
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *);
+int EC_KEY_set_private_key(EC_KEY *, const BIGNUM *);
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *);
+int EC_KEY_set_public_key(EC_KEY *, const EC_POINT *);
+unsigned EC_KEY_get_enc_flags(const EC_KEY *);
+void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
+void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
+/* functions to set/get method specific data */
+void *EC_KEY_get_key_method_data(EC_KEY *,
+ void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
+ void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+/* wrapper functions for the underlying EC_GROUP object */
+void EC_KEY_set_asn1_flag(EC_KEY *, int);
+int EC_KEY_precompute_mult(EC_KEY *, BN_CTX *ctx);
+
+/* EC_KEY_generate_key() creates a ec private (public) key */
+int EC_KEY_generate_key(EC_KEY *);
+/* EC_KEY_check_key() */
+int EC_KEY_check_key(const EC_KEY *);
+
+/* de- and encoding functions for SEC1 ECPrivateKey */
+EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC parameters */
+EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECParameters(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC public key
+ * (octet string, not DER -- hence 'o2i' and 'i2o') */
+EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len);
+int i2o_ECPublicKey(EC_KEY *a, unsigned char **out);
+
+#ifndef OPENSSL_NO_BIO
+int ECParameters_print(BIO *bp, const EC_KEY *x);
+int EC_KEY_print(BIO *bp, const EC_KEY *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int ECParameters_print_fp(FILE *fp, const EC_KEY *x);
+int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off);
+#endif
+
+#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
+
+#ifndef __cplusplus
+#if defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+# endif
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EC_strings(void);
+
+/* Error codes for the EC functions. */
+
+/* Function codes. */
+#define EC_F_COMPUTE_WNAF 143
+#define EC_F_D2I_ECPARAMETERS 144
+#define EC_F_D2I_ECPKPARAMETERS 145
+#define EC_F_D2I_ECPRIVATEKEY 146
+#define EC_F_ECPARAMETERS_PRINT 147
+#define EC_F_ECPARAMETERS_PRINT_FP 148
+#define EC_F_ECPKPARAMETERS_PRINT 149
+#define EC_F_ECPKPARAMETERS_PRINT_FP 150
+#define EC_F_ECP_NIST_MOD_192 203
+#define EC_F_ECP_NIST_MOD_224 204
+#define EC_F_ECP_NIST_MOD_256 205
+#define EC_F_ECP_NIST_MOD_521 206
+#define EC_F_EC_ASN1_GROUP2CURVE 153
+#define EC_F_EC_ASN1_GROUP2FIELDID 154
+#define EC_F_EC_ASN1_GROUP2PARAMETERS 155
+#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156
+#define EC_F_EC_ASN1_PARAMETERS2GROUP 157
+#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158
+#define EC_F_EC_EX_DATA_SET_DATA 211
+#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
+#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
+#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
+#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
+#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
+#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
+#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
+#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
+#define EC_F_EC_GFP_MONT_FIELD_DECODE 133
+#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134
+#define EC_F_EC_GFP_MONT_FIELD_MUL 131
+#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209
+#define EC_F_EC_GFP_MONT_FIELD_SQR 132
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
+#define EC_F_EC_GFP_NIST_FIELD_MUL 200
+#define EC_F_EC_GFP_NIST_FIELD_SQR 201
+#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
+#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101
+#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102
+#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104
+#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
+#define EC_F_EC_GROUP_CHECK 170
+#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171
+#define EC_F_EC_GROUP_COPY 106
+#define EC_F_EC_GROUP_GET0_GENERATOR 139
+#define EC_F_EC_GROUP_GET_COFACTOR 140
+#define EC_F_EC_GROUP_GET_CURVE_GF2M 172
+#define EC_F_EC_GROUP_GET_CURVE_GFP 130
+#define EC_F_EC_GROUP_GET_DEGREE 173
+#define EC_F_EC_GROUP_GET_ORDER 141
+#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193
+#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194
+#define EC_F_EC_GROUP_NEW 108
+#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174
+#define EC_F_EC_GROUP_NEW_FROM_DATA 175
+#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142
+#define EC_F_EC_GROUP_SET_CURVE_GF2M 176
+#define EC_F_EC_GROUP_SET_CURVE_GFP 109
+#define EC_F_EC_GROUP_SET_EXTRA_DATA 110
+#define EC_F_EC_GROUP_SET_GENERATOR 111
+#define EC_F_EC_KEY_CHECK_KEY 177
+#define EC_F_EC_KEY_COPY 178
+#define EC_F_EC_KEY_GENERATE_KEY 179
+#define EC_F_EC_KEY_NEW 182
+#define EC_F_EC_KEY_PRINT 180
+#define EC_F_EC_KEY_PRINT_FP 181
+#define EC_F_EC_POINTS_MAKE_AFFINE 136
+#define EC_F_EC_POINTS_MUL 138
+#define EC_F_EC_POINT_ADD 112
+#define EC_F_EC_POINT_CMP 113
+#define EC_F_EC_POINT_COPY 114
+#define EC_F_EC_POINT_DBL 115
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116
+#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117
+#define EC_F_EC_POINT_INVERT 210
+#define EC_F_EC_POINT_IS_AT_INFINITY 118
+#define EC_F_EC_POINT_IS_ON_CURVE 119
+#define EC_F_EC_POINT_MAKE_AFFINE 120
+#define EC_F_EC_POINT_MUL 184
+#define EC_F_EC_POINT_NEW 121
+#define EC_F_EC_POINT_OCT2POINT 122
+#define EC_F_EC_POINT_POINT2OCT 123
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125
+#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
+#define EC_F_EC_POINT_SET_TO_INFINITY 127
+#define EC_F_EC_PRE_COMP_DUP 207
+#define EC_F_EC_PRE_COMP_NEW 196
+#define EC_F_EC_WNAF_MUL 187
+#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
+#define EC_F_I2D_ECPARAMETERS 190
+#define EC_F_I2D_ECPKPARAMETERS 191
+#define EC_F_I2D_ECPRIVATEKEY 192
+#define EC_F_I2O_ECPUBLICKEY 151
+#define EC_F_O2I_ECPUBLICKEY 152
+
+/* Reason codes. */
+#define EC_R_ASN1_ERROR 115
+#define EC_R_ASN1_UNKNOWN_FIELD 116
+#define EC_R_BUFFER_TOO_SMALL 100
+#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
+#define EC_R_DISCRIMINANT_IS_ZERO 118
+#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
+#define EC_R_FIELD_TOO_LARGE 138
+#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
+#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
+#define EC_R_INCOMPATIBLE_OBJECTS 101
+#define EC_R_INVALID_ARGUMENT 112
+#define EC_R_INVALID_COMPRESSED_POINT 110
+#define EC_R_INVALID_COMPRESSION_BIT 109
+#define EC_R_INVALID_ENCODING 102
+#define EC_R_INVALID_FIELD 103
+#define EC_R_INVALID_FORM 104
+#define EC_R_INVALID_GROUP_ORDER 122
+#define EC_R_INVALID_PENTANOMIAL_BASIS 132
+#define EC_R_INVALID_PRIVATE_KEY 123
+#define EC_R_INVALID_TRINOMIAL_BASIS 137
+#define EC_R_MISSING_PARAMETERS 124
+#define EC_R_MISSING_PRIVATE_KEY 125
+#define EC_R_NOT_A_NIST_PRIME 135
+#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136
+#define EC_R_NOT_IMPLEMENTED 126
+#define EC_R_NOT_INITIALIZED 111
+#define EC_R_NO_FIELD_MOD 133
+#define EC_R_PASSED_NULL_PARAMETER 134
+#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
+#define EC_R_POINT_AT_INFINITY 106
+#define EC_R_POINT_IS_NOT_ON_CURVE 107
+#define EC_R_SLOT_FULL 108
+#define EC_R_UNDEFINED_GENERATOR 113
+#define EC_R_UNDEFINED_ORDER 128
+#define EC_R_UNKNOWN_GROUP 129
+#define EC_R_UNKNOWN_ORDER 114
+#define EC_R_UNSUPPORTED_FIELD 131
+#define EC_R_WRONG_ORDER 130
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ecdh.h b/src/Mayaqua/win32_inc/openssl/ecdh.h
new file mode 100644
index 00000000..c2c00b8a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ecdh.h
@@ -0,0 +1,123 @@
+/* crypto/ecdh/ecdh.h */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH software is originally written by Douglas Stebila of
+ * Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDH_H
+#define HEADER_ECDH_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ECDH
+#error ECDH is disabled.
+#endif
+
+#include <openssl/ec.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const ECDH_METHOD *ECDH_OpenSSL(void);
+
+void ECDH_set_default_method(const ECDH_METHOD *);
+const ECDH_METHOD *ECDH_get_default_method(void);
+int ECDH_set_method(EC_KEY *, const ECDH_METHOD *);
+
+int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
+ void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
+
+int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+ *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDH_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDH_strings(void);
+
+/* Error codes for the ECDH functions. */
+
+/* Function codes. */
+#define ECDH_F_ECDH_COMPUTE_KEY 100
+#define ECDH_F_ECDH_DATA_NEW_METHOD 101
+
+/* Reason codes. */
+#define ECDH_R_KDF_FAILED 102
+#define ECDH_R_NO_PRIVATE_VALUE 100
+#define ECDH_R_POINT_ARITHMETIC_FAILURE 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ecdsa.h b/src/Mayaqua/win32_inc/openssl/ecdsa.h
new file mode 100644
index 00000000..294e2ba7
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ecdsa.h
@@ -0,0 +1,271 @@
+/* crypto/ecdsa/ecdsa.h */
+/**
+ * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions
+ * \author Written by Nils Larsch for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDSA_H
+#define HEADER_ECDSA_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ECDSA
+#error ECDSA is disabled.
+#endif
+
+#include <openssl/ec.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ECDSA_SIG_st
+ {
+ BIGNUM *r;
+ BIGNUM *s;
+ } ECDSA_SIG;
+
+/** ECDSA_SIG *ECDSA_SIG_new(void)
+ * allocates and initialize a ECDSA_SIG structure
+ * \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_SIG_new(void);
+
+/** ECDSA_SIG_free
+ * frees a ECDSA_SIG structure
+ * \param a pointer to the ECDSA_SIG structure
+ */
+void ECDSA_SIG_free(ECDSA_SIG *a);
+
+/** i2d_ECDSA_SIG
+ * DER encode content of ECDSA_SIG object (note: this function modifies *pp
+ * (*pp += length of the DER encoded signature)).
+ * \param a pointer to the ECDSA_SIG object
+ * \param pp pointer to a unsigned char pointer for the output or NULL
+ * \return the length of the DER encoded ECDSA_SIG object or 0
+ */
+int i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **pp);
+
+/** d2i_ECDSA_SIG
+ * decodes a DER encoded ECDSA signature (note: this function changes *pp
+ * (*pp += len)).
+ * \param v pointer to ECDSA_SIG pointer (may be NULL)
+ * \param pp buffer with the DER encoded signature
+ * \param len bufferlength
+ * \return pointer to the decoded ECDSA_SIG structure (or NULL)
+ */
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long len);
+
+/** ECDSA_do_sign
+ * computes the ECDSA signature of the given hash value using
+ * the supplied private key and returns the created signature.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,int dgst_len,EC_KEY *eckey);
+
+/** ECDSA_do_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see
+ * ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
+ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_do_verify
+ * verifies that the supplied signature is a valid ECDSA
+ * signature of the supplied hash value using the supplied public key.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param sig pointer to the ECDSA_SIG structure
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY* eckey);
+
+const ECDSA_METHOD *ECDSA_OpenSSL(void);
+
+/** ECDSA_set_default_method
+ * sets the default ECDSA method
+ * \param meth the new default ECDSA_METHOD
+ */
+void ECDSA_set_default_method(const ECDSA_METHOD *meth);
+
+/** ECDSA_get_default_method
+ * returns the default ECDSA method
+ * \return pointer to ECDSA_METHOD structure containing the default method
+ */
+const ECDSA_METHOD *ECDSA_get_default_method(void);
+
+/** ECDSA_set_method
+ * sets method to be used for the ECDSA operations
+ * \param eckey pointer to the EC_KEY object
+ * \param meth pointer to the new method
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth);
+
+/** ECDSA_size
+ * returns the maximum length of the DER encoded signature
+ * \param eckey pointer to a EC_KEY object
+ * \return numbers of bytes required for the DER encoded signature
+ */
+int ECDSA_size(const EC_KEY *eckey);
+
+/** ECDSA_sign_setup
+ * precompute parts of the signing operation.
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \param ctx pointer to a BN_CTX object (may be NULL)
+ * \param kinv pointer to a BIGNUM pointer for the inverse of k
+ * \param rp pointer to a BIGNUM pointer for x coordinate of k * generator
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
+ BIGNUM **rp);
+
+/** ECDSA_sign
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+
+
+/** ECDSA_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see
+ * ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv,
+ const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_verify
+ * verifies that the given signature is valid ECDSA signature
+ * of the supplied hash value using the specified public key.
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value
+ * \param dgstlen length of the hash value
+ * \param sig pointer to the DER encoded signature
+ * \param siglen length of the DER encoded signature
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
+ const unsigned char *sig, int siglen, EC_KEY *eckey);
+
+/* the standard ex_data functions */
+int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+ *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDSA_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDSA_strings(void);
+
+/* Error codes for the ECDSA functions. */
+
+/* Function codes. */
+#define ECDSA_F_ECDSA_DATA_NEW_METHOD 100
+#define ECDSA_F_ECDSA_DO_SIGN 101
+#define ECDSA_F_ECDSA_DO_VERIFY 102
+#define ECDSA_F_ECDSA_SIGN_SETUP 103
+
+/* Reason codes. */
+#define ECDSA_R_BAD_SIGNATURE 100
+#define ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 101
+#define ECDSA_R_ERR_EC_LIB 102
+#define ECDSA_R_MISSING_PARAMETERS 103
+#define ECDSA_R_NEED_NEW_SETUP_VALUES 106
+#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104
+#define ECDSA_R_SIGNATURE_MALLOC_FAILED 105
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/engine.h b/src/Mayaqua/win32_inc/openssl/engine.h
new file mode 100644
index 00000000..a64e92e1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/engine.h
@@ -0,0 +1,804 @@
+/* openssl/engine.h */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_H
+#define HEADER_ENGINE_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ENGINE
+#error ENGINE is disabled.
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/rand.h>
+#include <openssl/store.h>
+#include <openssl/ui.h>
+#include <openssl/err.h>
+#endif
+
+#include <openssl/x509.h>
+
+#include <openssl/ossl_typ.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These flags are used to control combinations of algorithm (methods)
+ * by bitwise "OR"ing. */
+#define ENGINE_METHOD_RSA (unsigned int)0x0001
+#define ENGINE_METHOD_DSA (unsigned int)0x0002
+#define ENGINE_METHOD_DH (unsigned int)0x0004
+#define ENGINE_METHOD_RAND (unsigned int)0x0008
+#define ENGINE_METHOD_ECDH (unsigned int)0x0010
+#define ENGINE_METHOD_ECDSA (unsigned int)0x0020
+#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
+#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
+#define ENGINE_METHOD_STORE (unsigned int)0x0100
+/* Obvious all-or-nothing cases. */
+#define ENGINE_METHOD_ALL (unsigned int)0xFFFF
+#define ENGINE_METHOD_NONE (unsigned int)0x0000
+
+/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
+ * internally to control registration of ENGINE implementations, and can be set
+ * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
+ * initialise registered ENGINEs if they are not already initialised. */
+#define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001
+
+/* ENGINE flags that can be set by ENGINE_set_flags(). */
+/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */
+
+/* This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles these
+ * control commands on behalf of the ENGINE using their "cmd_defns" data. */
+#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
+
+/* This flag is for ENGINEs who return new duplicate structures when found via
+ * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl()
+ * commands are called in sequence as part of some stateful process like
+ * key-generation setup and execution), it can set this flag - then each attempt
+ * to obtain the ENGINE will result in it being copied into a new structure.
+ * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments
+ * the existing ENGINE's structural reference count. */
+#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004
+
+/* ENGINEs can support their own command types, and these flags are used in
+ * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each
+ * command expects. Currently only numeric and string input is supported. If a
+ * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options,
+ * then it is regarded as an "internal" control command - and not for use in
+ * config setting situations. As such, they're not available to the
+ * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to
+ * this list of 'command types' should be reflected carefully in
+ * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
+/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to
+ * ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
+/* Indicates that the control command takes *no* input. Ie. the control command
+ * is unparameterised. */
+#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
+/* Indicates that the control command is internal. This control command won't
+ * be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
+ * function. */
+#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008
+
+/* NB: These 3 control commands are deprecated and should not be used. ENGINEs
+ * relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate the
+ * same functionality to their own ENGINE-specific control functions that can be
+ * "discovered" by calling applications. The fact these control commands
+ * wouldn't be "executable" (ie. usable by text-based config) doesn't change the
+ * fact that application code can find and use them without requiring per-ENGINE
+ * hacking. */
+
+/* These flags are used to tell the ctrl function what should be done.
+ * All command numbers are shared between all engines, even if some don't
+ * make sense to some engines. In such a case, they do nothing but return
+ * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */
+#define ENGINE_CTRL_SET_LOGSTREAM 1
+#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2
+#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any
+ handles/connections etc. */
+#define ENGINE_CTRL_SET_USER_INTERFACE 4 /* Alternative to callback */
+#define ENGINE_CTRL_SET_CALLBACK_DATA 5 /* User-specific data, used
+ when calling the password
+ callback and the user
+ interface */
+#define ENGINE_CTRL_LOAD_CONFIGURATION 6 /* Load a configuration, given
+ a string that represents a
+ file name or so */
+#define ENGINE_CTRL_LOAD_SECTION 7 /* Load data from a given
+ section in the already loaded
+ configuration */
+
+/* These control commands allow an application to deal with an arbitrary engine
+ * in a dynamic way. Warn: Negative return values indicate errors FOR THESE
+ * COMMANDS because zero is used to indicate 'end-of-list'. Other commands,
+ * including ENGINE-specific command types, return zero for an error.
+ *
+ * An ENGINE can choose to implement these ctrl functions, and can internally
+ * manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the
+ * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns
+ * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl()
+ * handler need only implement its own commands - the above "meta" commands will
+ * be taken care of. */
+
+/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then
+ * all the remaining control commands will return failure, so it is worth
+ * checking this first if the caller is trying to "discover" the engine's
+ * capabilities and doesn't want errors generated unnecessarily. */
+#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
+/* Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported. */
+#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
+/* The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more. */
+#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
+/* The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it. */
+#define ENGINE_CTRL_GET_CMD_FROM_NAME 13
+/* The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the NAME_LEN
+ * case, the return value is the length of the command name (not counting a
+ * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer
+ * large enough, and it will be populated with the name of the command (WITH a
+ * trailing EOL). */
+#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
+#define ENGINE_CTRL_GET_NAME_FROM_CMD 15
+/* The next two are similar but give a "short description" of a command. */
+#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
+#define ENGINE_CTRL_GET_DESC_FROM_CMD 17
+/* With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects. */
+#define ENGINE_CTRL_GET_CMD_FLAGS 18
+
+/* ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */
+#define ENGINE_CMD_BASE 200
+
+/* NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before these
+ * are removed. */
+
+/* Flags specific to the nCipher "chil" engine */
+#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
+ /* Depending on the value of the (long)i argument, this sets or
+ * unsets the SimpleForkCheck flag in the CHIL API to enable or
+ * disable checking and workarounds for applications that fork().
+ */
+#define ENGINE_CTRL_CHIL_NO_LOCKING 101
+ /* This prevents the initialisation function from providing mutex
+ * callbacks to the nCipher library. */
+
+/* If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its
+ * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries
+ * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that
+ * supports the stated commands (ie. the "cmd_num" entries as described by the
+ * array). NB: The array must be ordered in increasing order of cmd_num.
+ * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set
+ * to zero and/or cmd_name set to NULL. */
+typedef struct ENGINE_CMD_DEFN_st
+ {
+ unsigned int cmd_num; /* The command number */
+ const char *cmd_name; /* The command name itself */
+ const char *cmd_desc; /* A short description of the command */
+ unsigned int cmd_flags; /* The input the command expects */
+ } ENGINE_CMD_DEFN;
+
+/* Generic function pointer */
+typedef int (*ENGINE_GEN_FUNC_PTR)(void);
+/* Generic function pointer taking no arguments */
+typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
+/* Specific control function pointer */
+typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void));
+/* Generic load_key function pointer */
+typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+ UI_METHOD *ui_method, void *callback_data);
+typedef int (*ENGINE_SSL_CLIENT_CERT_PTR)(ENGINE *, SSL *ssl,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
+ STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
+/* These callback types are for an ENGINE's handler for cipher and digest logic.
+ * These handlers have these prototypes;
+ * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+ * Looking at how to implement these handlers in the case of cipher support, if
+ * the framework wants the EVP_CIPHER for 'nid', it will call;
+ * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure)
+ * If the framework wants a list of supported 'nid's, it will call;
+ * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error)
+ */
+/* Returns to a pointer to the array of supported cipher 'nid's. If the second
+ * parameter is non-NULL it is set to the size of the returned array. */
+typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, const int **, int);
+typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int);
+
+/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE
+ * structures where the pointers have a "structural reference". This means that
+ * their reference is to allowed access to the structure but it does not imply
+ * that the structure is functional. To simply increment or decrement the
+ * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not
+ * required when iterating using ENGINE_get_next as it will automatically
+ * decrement the structural reference count of the "current" ENGINE and
+ * increment the structural reference count of the ENGINE it returns (unless it
+ * is NULL). */
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void);
+ENGINE *ENGINE_get_last(void);
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e);
+ENGINE *ENGINE_get_prev(ENGINE *e);
+/* Add another "ENGINE" type into the array. */
+int ENGINE_add(ENGINE *e);
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e);
+/* Retrieve an engine from the list by its unique "id" value. */
+ENGINE *ENGINE_by_id(const char *id);
+/* Add all the built-in engines. */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+#ifndef OPENSSL_NO_STATIC_ENGINE
+void ENGINE_load_4758cca(void);
+void ENGINE_load_aep(void);
+void ENGINE_load_atalla(void);
+void ENGINE_load_chil(void);
+void ENGINE_load_cswift(void);
+#ifndef OPENSSL_NO_GMP
+void ENGINE_load_gmp(void);
+#endif
+void ENGINE_load_nuron(void);
+void ENGINE_load_sureware(void);
+void ENGINE_load_ubsec(void);
+#endif
+void ENGINE_load_cryptodev(void);
+void ENGINE_load_padlock(void);
+void ENGINE_load_builtin_engines(void);
+#ifdef OPENSSL_SYS_WIN32
+#ifndef OPENSSL_NO_CAPIENG
+void ENGINE_load_capi(void);
+#endif
+#endif
+
+/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+ * "registry" handling. */
+unsigned int ENGINE_get_table_flags(void);
+void ENGINE_set_table_flags(unsigned int flags);
+
+/* Manage registration of ENGINEs per "table". For each type, there are 3
+ * functions;
+ * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one)
+ * ENGINE_unregister_***(e) - unregister the implementation from 'e'
+ * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
+ * Cleanup is automatically registered from each table when required, so
+ * ENGINE_cleanup() will reverse any "register" operations. */
+
+int ENGINE_register_RSA(ENGINE *e);
+void ENGINE_unregister_RSA(ENGINE *e);
+void ENGINE_register_all_RSA(void);
+
+int ENGINE_register_DSA(ENGINE *e);
+void ENGINE_unregister_DSA(ENGINE *e);
+void ENGINE_register_all_DSA(void);
+
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
+int ENGINE_register_ECDSA(ENGINE *e);
+void ENGINE_unregister_ECDSA(ENGINE *e);
+void ENGINE_register_all_ECDSA(void);
+
+int ENGINE_register_DH(ENGINE *e);
+void ENGINE_unregister_DH(ENGINE *e);
+void ENGINE_register_all_DH(void);
+
+int ENGINE_register_RAND(ENGINE *e);
+void ENGINE_unregister_RAND(ENGINE *e);
+void ENGINE_register_all_RAND(void);
+
+int ENGINE_register_STORE(ENGINE *e);
+void ENGINE_unregister_STORE(ENGINE *e);
+void ENGINE_register_all_STORE(void);
+
+int ENGINE_register_ciphers(ENGINE *e);
+void ENGINE_unregister_ciphers(ENGINE *e);
+void ENGINE_register_all_ciphers(void);
+
+int ENGINE_register_digests(ENGINE *e);
+void ENGINE_unregister_digests(ENGINE *e);
+void ENGINE_register_all_digests(void);
+
+/* These functions register all support from the above categories. Note, use of
+ * these functions can result in static linkage of code your application may not
+ * need. If you only need a subset of functionality, consider using more
+ * selective initialisation. */
+int ENGINE_register_complete(ENGINE *e);
+int ENGINE_register_all_complete(void);
+
+/* Send parametrised control commands to the engine. The possibilities to send
+ * down an integer, a pointer to data or a function pointer are provided. Any of
+ * the parameters may or may not be NULL, depending on the command number. In
+ * actuality, this function only requires a structural (rather than functional)
+ * reference to an engine, but many control commands may require the engine be
+ * functional. The caller should be aware of trying commands that require an
+ * operational ENGINE, and only use functional references in such situations. */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+
+/* This function tests if an ENGINE-specific command is usable as a "setting".
+ * Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/* This function works like ENGINE_ctrl() with the exception of taking a
+ * command name instead of a command number, and can handle optional commands.
+ * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to
+ * use the cmd_name and cmd_optional. */
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f)(void), int cmd_optional);
+
+/* This function passes a command-name and argument to an ENGINE. The cmd_name
+ * is converted to a command number and the control command is called using
+ * 'arg' as an argument (unless the ENGINE doesn't support such a command, in
+ * which case no control command is called). The command is checked for input
+ * flags, and if necessary the argument will be converted to a numeric value. If
+ * cmd_optional is non-zero, then if the ENGINE doesn't support the given
+ * cmd_name the return value will be success anyway. This function is intended
+ * for applications to use so that users (or config files) can supply
+ * engine-specific config data to the ENGINE at run-time to control behaviour of
+ * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl()
+ * functions that return data, deal with binary data, or that are otherwise
+ * supposed to be used directly through ENGINE_ctrl() in application code. Any
+ * "return" data from an ENGINE_ctrl() operation in this function will be lost -
+ * the return value is interpreted as failure if the return value is zero,
+ * success otherwise, and this function returns a boolean value as a result. In
+ * other words, vendors of 'ENGINE'-enabled devices should write ENGINE
+ * implementations with parameterisations that work in this scheme, so that
+ * compliant ENGINE-based applications can work consistently with the same
+ * configuration for the same ENGINE-enabled devices, across applications. */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional);
+
+/* These functions are useful for manufacturing new ENGINE structures. They
+ * don't address reference counting at all - one uses them to populate an ENGINE
+ * structure with personalised implementations of things prior to using it
+ * directly or adding it to the builtin ENGINE list in OpenSSL. These are also
+ * here so that the ENGINE structure doesn't have to be exposed and break binary
+ * compatibility! */
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+int ENGINE_up_ref(ENGINE *e);
+int ENGINE_set_id(ENGINE *e, const char *id);
+int ENGINE_set_name(ENGINE *e, const char *name);
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+ ENGINE_SSL_CLIENT_CERT_PTR loadssl_f);
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+int ENGINE_set_flags(ENGINE *e, int flags);
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+/* These functions allow control over any per-structure ENGINE data. */
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+
+/* This function cleans up anything that needs it. Eg. the ENGINE_add() function
+ * automatically ensures the list cleanup function is registered to be called
+ * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure
+ * ENGINE_cleanup() will clean up after them. */
+void ENGINE_cleanup(void);
+
+/* These return values from within the ENGINE structure. These can be useful
+ * with functional references as well as structural references - it depends
+ * which you obtained. Using the result for functional purposes if you only
+ * obtained a structural reference may be problematic! */
+const char *ENGINE_get_id(const ENGINE *e);
+const char *ENGINE_get_name(const ENGINE *e);
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e);
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
+int ENGINE_get_flags(const ENGINE *e);
+
+/* FUNCTIONAL functions. These functions deal with ENGINE structures
+ * that have (or will) be initialised for use. Broadly speaking, the
+ * structural functions are useful for iterating the list of available
+ * engine types, creating new engine types, and other "list" operations.
+ * These functions actually deal with ENGINEs that are to be used. As
+ * such these functions can fail (if applicable) when particular
+ * engines are unavailable - eg. if a hardware accelerator is not
+ * attached or not functioning correctly. Each ENGINE has 2 reference
+ * counts; structural and functional. Every time a functional reference
+ * is obtained or released, a corresponding structural reference is
+ * automatically obtained or released too. */
+
+/* Initialise a engine type for use (or up its reference count if it's
+ * already in use). This will fail if the engine is not currently
+ * operational and cannot initialise. */
+int ENGINE_init(ENGINE *e);
+/* Free a functional reference to a engine type. This does not require
+ * a corresponding call to ENGINE_free as it also releases a structural
+ * reference. */
+int ENGINE_finish(ENGINE *e);
+
+/* The following functions handle keys that are stored in some secondary
+ * location, handled by the engine. The storage may be on a card or
+ * whatever. */
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+ STACK_OF(X509) **pother,
+ UI_METHOD *ui_method, void *callback_data);
+
+/* This returns a pointer for the current ENGINE structure that
+ * is (by default) performing any RSA operations. The value returned
+ * is an incremented reference, so it should be free'd (ENGINE_finish)
+ * before it is discarded. */
+ENGINE *ENGINE_get_default_RSA(void);
+/* Same for the other "methods" */
+ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
+ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_DH(void);
+ENGINE *ENGINE_get_default_RAND(void);
+/* These functions can be used to get a functional reference to perform
+ * ciphering or digesting corresponding to "nid". */
+ENGINE *ENGINE_get_cipher_engine(int nid);
+ENGINE *ENGINE_get_digest_engine(int nid);
+
+/* This sets a new default ENGINE structure for performing RSA
+ * operations. If the result is non-zero (success) then the ENGINE
+ * structure will have had its reference count up'd so the caller
+ * should still free their own reference 'e'. */
+int ENGINE_set_default_RSA(ENGINE *e);
+int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+/* Same for the other "methods" */
+int ENGINE_set_default_DSA(ENGINE *e);
+int ENGINE_set_default_ECDH(ENGINE *e);
+int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_DH(ENGINE *e);
+int ENGINE_set_default_RAND(ENGINE *e);
+int ENGINE_set_default_ciphers(ENGINE *e);
+int ENGINE_set_default_digests(ENGINE *e);
+
+/* The combination "set" - the flags are bitwise "OR"d from the
+ * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
+ * function, this function can result in unnecessary static linkage. If your
+ * application requires only specific functionality, consider using more
+ * selective functions. */
+int ENGINE_set_default(ENGINE *e, unsigned int flags);
+
+void ENGINE_add_conf_module(void);
+
+/* Deprecated functions ... */
+/* int ENGINE_clear_defaults(void); */
+
+/**************************/
+/* DYNAMIC ENGINE SUPPORT */
+/**************************/
+
+/* Binary/behaviour compatibility levels */
+#define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000
+/* Binary versions older than this are too old for us (whether we're a loader or
+ * a loadee) */
+#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000
+
+/* When compiling an ENGINE entirely as an external shared library, loadable by
+ * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
+ * type provides the calling application's (or library's) error functionality
+ * and memory management function pointers to the loaded library. These should
+ * be used/set in the loaded library code so that the loading application's
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
+typedef void *(*dyn_MEM_malloc_cb)(size_t);
+typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
+typedef void (*dyn_MEM_free_cb)(void *);
+typedef struct st_dynamic_MEM_fns {
+ dyn_MEM_malloc_cb malloc_cb;
+ dyn_MEM_realloc_cb realloc_cb;
+ dyn_MEM_free_cb free_cb;
+ } dynamic_MEM_fns;
+/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use
+ * these types so we (and any other dependant code) can simplify a bit?? */
+typedef void (*dyn_lock_locking_cb)(int,int,const char *,int);
+typedef int (*dyn_lock_add_lock_cb)(int*,int,int,const char *,int);
+typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)(
+ const char *,int);
+typedef void (*dyn_dynlock_lock_cb)(int,struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef struct st_dynamic_LOCK_fns {
+ dyn_lock_locking_cb lock_locking_cb;
+ dyn_lock_add_lock_cb lock_add_lock_cb;
+ dyn_dynlock_create_cb dynlock_create_cb;
+ dyn_dynlock_lock_cb dynlock_lock_cb;
+ dyn_dynlock_destroy_cb dynlock_destroy_cb;
+ } dynamic_LOCK_fns;
+/* The top-level structure */
+typedef struct st_dynamic_fns {
+ void *static_state;
+ const ERR_FNS *err_fns;
+ const CRYPTO_EX_DATA_IMPL *ex_data_fns;
+ dynamic_MEM_fns mem_fns;
+ dynamic_LOCK_fns lock_fns;
+ } dynamic_fns;
+
+/* The version checking function should be of this prototype. NB: The
+ * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code.
+ * If this function returns zero, it indicates a (potential) version
+ * incompatibility and the loaded library doesn't believe it can proceed.
+ * Otherwise, the returned value is the (latest) version supported by the
+ * loading library. The loader may still decide that the loaded code's version
+ * is unsatisfactory and could veto the load. The function is expected to
+ * be implemented with the symbol name "v_check", and a default implementation
+ * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */
+typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version);
+#define IMPLEMENT_DYNAMIC_CHECK_FN() \
+ OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
+ if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
+ return 0; }
+
+/* This function is passed the ENGINE structure to initialise with its own
+ * function and command settings. It should not adjust the structural or
+ * functional reference counts. If this function returns zero, (a) the load will
+ * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the
+ * structure, and (c) the shared library will be unloaded. So implementations
+ * should do their own internal cleanup in failure circumstances otherwise they
+ * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that
+ * the loader is looking for. If this is NULL, the shared library can choose to
+ * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared
+ * library must initialise only an ENGINE matching the passed 'id'. The function
+ * is expected to be implemented with the symbol name "bind_engine". A standard
+ * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where
+ * the parameter 'fn' is a callback function that populates the ENGINE structure
+ * and returns an int value (zero for failure). 'fn' should have prototype;
+ * [static] int fn(ENGINE *e, const char *id); */
+typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
+ const dynamic_fns *fns);
+#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+ OPENSSL_EXPORT \
+ int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+ if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
+ if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
+ fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
+ return 0; \
+ CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \
+ CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \
+ CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \
+ CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \
+ CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \
+ if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
+ return 0; \
+ if(!ERR_set_implementation(fns->err_fns)) return 0; \
+ skip_cbs: \
+ if(!fn(e,id)) return 0; \
+ return 1; }
+
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+#if defined(__OpenBSD__) || defined(__FreeBSD__)
+void ENGINE_setup_bsd_cryptodev(void);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ENGINE_strings(void);
+
+/* Error codes for the ENGINE functions. */
+
+/* Function codes. */
+#define ENGINE_F_DYNAMIC_CTRL 180
+#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181
+#define ENGINE_F_DYNAMIC_LOAD 182
+#define ENGINE_F_DYNAMIC_SET_DATA_CTX 183
+#define ENGINE_F_ENGINE_ADD 105
+#define ENGINE_F_ENGINE_BY_ID 106
+#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
+#define ENGINE_F_ENGINE_CTRL 142
+#define ENGINE_F_ENGINE_CTRL_CMD 178
+#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171
+#define ENGINE_F_ENGINE_FINISH 107
+#define ENGINE_F_ENGINE_FREE_UTIL 108
+#define ENGINE_F_ENGINE_GET_CIPHER 185
+#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177
+#define ENGINE_F_ENGINE_GET_DIGEST 186
+#define ENGINE_F_ENGINE_GET_NEXT 115
+#define ENGINE_F_ENGINE_GET_PREV 116
+#define ENGINE_F_ENGINE_INIT 119
+#define ENGINE_F_ENGINE_LIST_ADD 120
+#define ENGINE_F_ENGINE_LIST_REMOVE 121
+#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150
+#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151
+#define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 192
+#define ENGINE_F_ENGINE_NEW 122
+#define ENGINE_F_ENGINE_REMOVE 123
+#define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189
+#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126
+#define ENGINE_F_ENGINE_SET_ID 129
+#define ENGINE_F_ENGINE_SET_NAME 130
+#define ENGINE_F_ENGINE_TABLE_REGISTER 184
+#define ENGINE_F_ENGINE_UNLOAD_KEY 152
+#define ENGINE_F_ENGINE_UNLOCKED_FINISH 191
+#define ENGINE_F_ENGINE_UP_REF 190
+#define ENGINE_F_INT_CTRL_HELPER 172
+#define ENGINE_F_INT_ENGINE_CONFIGURE 188
+#define ENGINE_F_INT_ENGINE_MODULE_INIT 187
+#define ENGINE_F_LOG_MESSAGE 141
+
+/* Reason codes. */
+#define ENGINE_R_ALREADY_LOADED 100
+#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133
+#define ENGINE_R_CMD_NOT_EXECUTABLE 134
+#define ENGINE_R_COMMAND_TAKES_INPUT 135
+#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136
+#define ENGINE_R_CONFLICTING_ENGINE_ID 103
+#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119
+#define ENGINE_R_DH_NOT_IMPLEMENTED 139
+#define ENGINE_R_DSA_NOT_IMPLEMENTED 140
+#define ENGINE_R_DSO_FAILURE 104
+#define ENGINE_R_DSO_NOT_FOUND 132
+#define ENGINE_R_ENGINES_SECTION_ERROR 148
+#define ENGINE_R_ENGINE_CONFIGURATION_ERROR 101
+#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105
+#define ENGINE_R_ENGINE_SECTION_ERROR 149
+#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128
+#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129
+#define ENGINE_R_FINISH_FAILED 106
+#define ENGINE_R_GET_HANDLE_FAILED 107
+#define ENGINE_R_ID_OR_NAME_MISSING 108
+#define ENGINE_R_INIT_FAILED 109
+#define ENGINE_R_INTERNAL_LIST_ERROR 110
+#define ENGINE_R_INVALID_ARGUMENT 143
+#define ENGINE_R_INVALID_CMD_NAME 137
+#define ENGINE_R_INVALID_CMD_NUMBER 138
+#define ENGINE_R_INVALID_INIT_VALUE 151
+#define ENGINE_R_INVALID_STRING 150
+#define ENGINE_R_NOT_INITIALISED 117
+#define ENGINE_R_NOT_LOADED 112
+#define ENGINE_R_NO_CONTROL_FUNCTION 120
+#define ENGINE_R_NO_INDEX 144
+#define ENGINE_R_NO_LOAD_FUNCTION 125
+#define ENGINE_R_NO_REFERENCE 130
+#define ENGINE_R_NO_SUCH_ENGINE 116
+#define ENGINE_R_NO_UNLOAD_FUNCTION 126
+#define ENGINE_R_PROVIDE_PARAMETERS 113
+#define ENGINE_R_RSA_NOT_IMPLEMENTED 141
+#define ENGINE_R_UNIMPLEMENTED_CIPHER 146
+#define ENGINE_R_UNIMPLEMENTED_DIGEST 147
+#define ENGINE_R_VERSION_INCOMPATIBILITY 145
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/err.h b/src/Mayaqua/win32_inc/openssl/err.h
new file mode 100644
index 00000000..1b9f733e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/err.h
@@ -0,0 +1,330 @@
+/* crypto/err/err.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ERR_H
+#define HEADER_ERR_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_LHASH
+#include <openssl/lhash.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSSL_NO_ERR
+#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e)
+#else
+#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0)
+#endif
+
+#include <errno.h>
+
+#define ERR_TXT_MALLOCED 0x01
+#define ERR_TXT_STRING 0x02
+
+#define ERR_FLAG_MARK 0x01
+
+#define ERR_NUM_ERRORS 16
+typedef struct err_state_st
+ {
+ unsigned long pid;
+ int err_flags[ERR_NUM_ERRORS];
+ unsigned long err_buffer[ERR_NUM_ERRORS];
+ char *err_data[ERR_NUM_ERRORS];
+ int err_data_flags[ERR_NUM_ERRORS];
+ const char *err_file[ERR_NUM_ERRORS];
+ int err_line[ERR_NUM_ERRORS];
+ int top,bottom;
+ } ERR_STATE;
+
+/* library */
+#define ERR_LIB_NONE 1
+#define ERR_LIB_SYS 2
+#define ERR_LIB_BN 3
+#define ERR_LIB_RSA 4
+#define ERR_LIB_DH 5
+#define ERR_LIB_EVP 6
+#define ERR_LIB_BUF 7
+#define ERR_LIB_OBJ 8
+#define ERR_LIB_PEM 9
+#define ERR_LIB_DSA 10
+#define ERR_LIB_X509 11
+/* #define ERR_LIB_METH 12 */
+#define ERR_LIB_ASN1 13
+#define ERR_LIB_CONF 14
+#define ERR_LIB_CRYPTO 15
+#define ERR_LIB_EC 16
+#define ERR_LIB_SSL 20
+/* #define ERR_LIB_SSL23 21 */
+/* #define ERR_LIB_SSL2 22 */
+/* #define ERR_LIB_SSL3 23 */
+/* #define ERR_LIB_RSAREF 30 */
+/* #define ERR_LIB_PROXY 31 */
+#define ERR_LIB_BIO 32
+#define ERR_LIB_PKCS7 33
+#define ERR_LIB_X509V3 34
+#define ERR_LIB_PKCS12 35
+#define ERR_LIB_RAND 36
+#define ERR_LIB_DSO 37
+#define ERR_LIB_ENGINE 38
+#define ERR_LIB_OCSP 39
+#define ERR_LIB_UI 40
+#define ERR_LIB_COMP 41
+#define ERR_LIB_ECDSA 42
+#define ERR_LIB_ECDH 43
+#define ERR_LIB_STORE 44
+#define ERR_LIB_FIPS 45
+#define ERR_LIB_CMS 46
+#define ERR_LIB_JPAKE 47
+
+#define ERR_LIB_USER 128
+
+#define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__)
+#define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__)
+#define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__)
+#define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__)
+#define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__)
+#define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__)
+#define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__)
+#define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__)
+#define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__)
+#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__)
+#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__)
+#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__)
+#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__)
+#define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__)
+#define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__)
+#define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__)
+#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__)
+#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__)
+#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__)
+#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__)
+#define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__)
+#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__)
+#define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__)
+#define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__)
+#define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__)
+#define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
+#define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
+#define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
+#define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__)
+#define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
+#define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
+
+/* Borland C seems too stupid to be able to shift and do longs in
+ * the pre-processor :-( */
+#define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)*0x1000000)| \
+ ((((unsigned long)f)&0xfffL)*0x1000)| \
+ ((((unsigned long)r)&0xfffL)))
+#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL)
+#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL)
+#define ERR_GET_REASON(l) (int)((l)&0xfffL)
+#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL)
+
+
+/* OS functions */
+#define SYS_F_FOPEN 1
+#define SYS_F_CONNECT 2
+#define SYS_F_GETSERVBYNAME 3
+#define SYS_F_SOCKET 4
+#define SYS_F_IOCTLSOCKET 5
+#define SYS_F_BIND 6
+#define SYS_F_LISTEN 7
+#define SYS_F_ACCEPT 8
+#define SYS_F_WSASTARTUP 9 /* Winsock stuff */
+#define SYS_F_OPENDIR 10
+#define SYS_F_FREAD 11
+
+
+/* reasons */
+#define ERR_R_SYS_LIB ERR_LIB_SYS /* 2 */
+#define ERR_R_BN_LIB ERR_LIB_BN /* 3 */
+#define ERR_R_RSA_LIB ERR_LIB_RSA /* 4 */
+#define ERR_R_DH_LIB ERR_LIB_DH /* 5 */
+#define ERR_R_EVP_LIB ERR_LIB_EVP /* 6 */
+#define ERR_R_BUF_LIB ERR_LIB_BUF /* 7 */
+#define ERR_R_OBJ_LIB ERR_LIB_OBJ /* 8 */
+#define ERR_R_PEM_LIB ERR_LIB_PEM /* 9 */
+#define ERR_R_DSA_LIB ERR_LIB_DSA /* 10 */
+#define ERR_R_X509_LIB ERR_LIB_X509 /* 11 */
+#define ERR_R_ASN1_LIB ERR_LIB_ASN1 /* 13 */
+#define ERR_R_CONF_LIB ERR_LIB_CONF /* 14 */
+#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO /* 15 */
+#define ERR_R_EC_LIB ERR_LIB_EC /* 16 */
+#define ERR_R_SSL_LIB ERR_LIB_SSL /* 20 */
+#define ERR_R_BIO_LIB ERR_LIB_BIO /* 32 */
+#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 /* 33 */
+#define ERR_R_X509V3_LIB ERR_LIB_X509V3 /* 34 */
+#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 /* 35 */
+#define ERR_R_RAND_LIB ERR_LIB_RAND /* 36 */
+#define ERR_R_DSO_LIB ERR_LIB_DSO /* 37 */
+#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE /* 38 */
+#define ERR_R_OCSP_LIB ERR_LIB_OCSP /* 39 */
+#define ERR_R_UI_LIB ERR_LIB_UI /* 40 */
+#define ERR_R_COMP_LIB ERR_LIB_COMP /* 41 */
+#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA /* 42 */
+#define ERR_R_ECDH_LIB ERR_LIB_ECDH /* 43 */
+#define ERR_R_STORE_LIB ERR_LIB_STORE /* 44 */
+
+#define ERR_R_NESTED_ASN1_ERROR 58
+#define ERR_R_BAD_ASN1_OBJECT_HEADER 59
+#define ERR_R_BAD_GET_ASN1_OBJECT_CALL 60
+#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE 61
+#define ERR_R_ASN1_LENGTH_MISMATCH 62
+#define ERR_R_MISSING_ASN1_EOS 63
+
+/* fatal error */
+#define ERR_R_FATAL 64
+#define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL)
+#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL)
+#define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL)
+#define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL)
+#define ERR_R_DISABLED (5|ERR_R_FATAL)
+
+/* 99 is the maximum possible ERR_R_... code, higher values
+ * are reserved for the individual libraries */
+
+
+typedef struct ERR_string_data_st
+ {
+ unsigned long error;
+ const char *string;
+ } ERR_STRING_DATA;
+
+void ERR_put_error(int lib, int func,int reason,const char *file,int line);
+void ERR_set_error_data(char *data,int flags);
+
+unsigned long ERR_get_error(void);
+unsigned long ERR_get_error_line(const char **file,int *line);
+unsigned long ERR_get_error_line_data(const char **file,int *line,
+ const char **data, int *flags);
+unsigned long ERR_peek_error(void);
+unsigned long ERR_peek_error_line(const char **file,int *line);
+unsigned long ERR_peek_error_line_data(const char **file,int *line,
+ const char **data,int *flags);
+unsigned long ERR_peek_last_error(void);
+unsigned long ERR_peek_last_error_line(const char **file,int *line);
+unsigned long ERR_peek_last_error_line_data(const char **file,int *line,
+ const char **data,int *flags);
+void ERR_clear_error(void );
+char *ERR_error_string(unsigned long e,char *buf);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+const char *ERR_lib_error_string(unsigned long e);
+const char *ERR_func_error_string(unsigned long e);
+const char *ERR_reason_error_string(unsigned long e);
+void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u);
+#ifndef OPENSSL_NO_FP_API
+void ERR_print_errors_fp(FILE *fp);
+#endif
+#ifndef OPENSSL_NO_BIO
+void ERR_print_errors(BIO *bp);
+void ERR_add_error_data(int num, ...);
+#endif
+void ERR_load_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_unload_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_load_ERR_strings(void);
+void ERR_load_crypto_strings(void);
+void ERR_free_strings(void);
+
+void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+ERR_STATE *ERR_get_state(void);
+
+#ifndef OPENSSL_NO_LHASH
+LHASH *ERR_get_string_table(void);
+LHASH *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH **hash);
+#endif
+
+int ERR_get_next_error_library(void);
+
+int ERR_set_mark(void);
+int ERR_pop_to_mark(void);
+
+#ifdef OPENSSL_FIPS
+void int_ERR_set_state_func(ERR_STATE *(*get_func)(void),
+ void (*remove_func)(unsigned long pid));
+void int_ERR_lib_init(void);
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct st_ERR_FNS ERR_FNS; */
+/* An application can use this function and provide the return value to loaded
+ * modules that should use the application's ERR state/functionality */
+const ERR_FNS *ERR_get_implementation(void);
+/* A loaded module should call this function prior to any ERR operations using
+ * the application's "ERR_FNS". */
+int ERR_set_implementation(const ERR_FNS *fns);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/evp.h b/src/Mayaqua/win32_inc/openssl/evp.h
new file mode 100644
index 00000000..ac9ebede
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/evp.h
@@ -0,0 +1,1059 @@
+/* crypto/evp/evp.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ENVELOPE_H
+#define HEADER_ENVELOPE_H
+
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# include <openssl/opensslconf.h>
+#else
+# define OPENSSL_ALGORITHM_DEFINES
+# include <openssl/opensslconf.h>
+# undef OPENSSL_ALGORITHM_DEFINES
+#endif
+
+#include <openssl/ossl_typ.h>
+
+#include <openssl/symhacks.h>
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+/*
+#define EVP_RC2_KEY_SIZE 16
+#define EVP_RC4_KEY_SIZE 16
+#define EVP_BLOWFISH_KEY_SIZE 16
+#define EVP_CAST5_KEY_SIZE 16
+#define EVP_RC5_32_12_16_KEY_SIZE 16
+*/
+#define EVP_MAX_MD_SIZE 64 /* longest known is SHA512 */
+#define EVP_MAX_KEY_LENGTH 32
+#define EVP_MAX_IV_LENGTH 16
+#define EVP_MAX_BLOCK_LENGTH 32
+
+#define PKCS5_SALT_LEN 8
+/* Default PKCS#5 iteration count */
+#define PKCS5_DEFAULT_ITER 2048
+
+#include <openssl/objects.h>
+
+#define EVP_PK_RSA 0x0001
+#define EVP_PK_DSA 0x0002
+#define EVP_PK_DH 0x0004
+#define EVP_PK_EC 0x0008
+#define EVP_PKT_SIGN 0x0010
+#define EVP_PKT_ENC 0x0020
+#define EVP_PKT_EXCH 0x0040
+#define EVP_PKS_RSA 0x0100
+#define EVP_PKS_DSA 0x0200
+#define EVP_PKS_EC 0x0400
+#define EVP_PKT_EXP 0x1000 /* <= 512 bit key */
+
+#define EVP_PKEY_NONE NID_undef
+#define EVP_PKEY_RSA NID_rsaEncryption
+#define EVP_PKEY_RSA2 NID_rsa
+#define EVP_PKEY_DSA NID_dsa
+#define EVP_PKEY_DSA1 NID_dsa_2
+#define EVP_PKEY_DSA2 NID_dsaWithSHA
+#define EVP_PKEY_DSA3 NID_dsaWithSHA1
+#define EVP_PKEY_DSA4 NID_dsaWithSHA1_2
+#define EVP_PKEY_DH NID_dhKeyAgreement
+#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Type needs to be a bit field
+ * Sub-type needs to be for variations on the method, as in, can it do
+ * arbitrary encryption.... */
+struct evp_pkey_st
+ {
+ int type;
+ int save_type;
+ int references;
+ union {
+ char *ptr;
+#ifndef OPENSSL_NO_RSA
+ struct rsa_st *rsa; /* RSA */
+#endif
+#ifndef OPENSSL_NO_DSA
+ struct dsa_st *dsa; /* DSA */
+#endif
+#ifndef OPENSSL_NO_DH
+ struct dh_st *dh; /* DH */
+#endif
+#ifndef OPENSSL_NO_EC
+ struct ec_key_st *ec; /* ECC */
+#endif
+ } pkey;
+ int save_parameters;
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+ } /* EVP_PKEY */;
+
+#define EVP_PKEY_MO_SIGN 0x0001
+#define EVP_PKEY_MO_VERIFY 0x0002
+#define EVP_PKEY_MO_ENCRYPT 0x0004
+#define EVP_PKEY_MO_DECRYPT 0x0008
+
+#if 0
+/* This structure is required to tie the message digest and signing together.
+ * The lookup can be done by md/pkey_method, oid, oid/pkey_method, or
+ * oid, md and pkey.
+ * This is required because for various smart-card perform the digest and
+ * signing/verification on-board. To handle this case, the specific
+ * EVP_MD and EVP_PKEY_METHODs need to be closely associated.
+ * When a PKEY is created, it will have a EVP_PKEY_METHOD associated with it.
+ * This can either be software or a token to provide the required low level
+ * routines.
+ */
+typedef struct evp_pkey_md_st
+ {
+ int oid;
+ EVP_MD *md;
+ EVP_PKEY_METHOD *pkey;
+ } EVP_PKEY_MD;
+
+#define EVP_rsa_md2() \
+ EVP_PKEY_MD_add(NID_md2WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_md2())
+#define EVP_rsa_md5() \
+ EVP_PKEY_MD_add(NID_md5WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_md5())
+#define EVP_rsa_sha0() \
+ EVP_PKEY_MD_add(NID_shaWithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_sha())
+#define EVP_rsa_sha1() \
+ EVP_PKEY_MD_add(NID_sha1WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_sha1())
+#define EVP_rsa_ripemd160() \
+ EVP_PKEY_MD_add(NID_ripemd160WithRSA,\
+ EVP_rsa_pkcs1(),EVP_ripemd160())
+#define EVP_rsa_mdc2() \
+ EVP_PKEY_MD_add(NID_mdc2WithRSA,\
+ EVP_rsa_octet_string(),EVP_mdc2())
+#define EVP_dsa_sha() \
+ EVP_PKEY_MD_add(NID_dsaWithSHA,\
+ EVP_dsa(),EVP_sha())
+#define EVP_dsa_sha1() \
+ EVP_PKEY_MD_add(NID_dsaWithSHA1,\
+ EVP_dsa(),EVP_sha1())
+
+typedef struct evp_pkey_method_st
+ {
+ char *name;
+ int flags;
+ int type; /* RSA, DSA, an SSLeay specific constant */
+ int oid; /* For the pub-key type */
+ int encrypt_oid; /* pub/priv key encryption */
+
+ int (*sign)();
+ int (*verify)();
+ struct {
+ int (*set)(); /* get and/or set the underlying type */
+ int (*get)();
+ int (*encrypt)();
+ int (*decrypt)();
+ int (*i2d)();
+ int (*d2i)();
+ int (*dup)();
+ } pub,priv;
+ int (*set_asn1_parameters)();
+ int (*get_asn1_parameters)();
+ } EVP_PKEY_METHOD;
+#endif
+
+#ifndef EVP_MD
+struct env_md_st
+ {
+ int type;
+ int pkey_type;
+ int md_size;
+ unsigned long flags;
+ int (*init)(EVP_MD_CTX *ctx);
+ int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
+ int (*final)(EVP_MD_CTX *ctx,unsigned char *md);
+ int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);
+ int (*cleanup)(EVP_MD_CTX *ctx);
+
+ /* FIXME: prototype these some day */
+ int (*sign)(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, void *key);
+ int (*verify)(int type, const unsigned char *m, unsigned int m_length,
+ const unsigned char *sigbuf, unsigned int siglen,
+ void *key);
+ int required_pkey_type[5]; /*EVP_PKEY_xxx */
+ int block_size;
+ int ctx_size; /* how big does the ctx->md_data need to be */
+ } /* EVP_MD */;
+
+typedef int evp_sign_method(int type,const unsigned char *m,
+ unsigned int m_length,unsigned char *sigret,
+ unsigned int *siglen, void *key);
+typedef int evp_verify_method(int type,const unsigned char *m,
+ unsigned int m_length,const unsigned char *sigbuf,
+ unsigned int siglen, void *key);
+
+typedef struct
+ {
+ EVP_MD_CTX *mctx;
+ void *key;
+ } EVP_MD_SVCTX;
+
+#define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single
+ * block */
+
+#define EVP_MD_FLAG_FIPS 0x0400 /* Note if suitable for use in FIPS mode */
+
+#define EVP_MD_FLAG_SVCTX 0x0800 /* pass EVP_MD_SVCTX to sign/verify */
+
+#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0}
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_DSA_method (evp_sign_method *)DSA_sign, \
+ (evp_verify_method *)DSA_verify, \
+ {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \
+ EVP_PKEY_DSA4,0}
+#else
+#define EVP_PKEY_DSA_method EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#define EVP_PKEY_ECDSA_method (evp_sign_method *)ECDSA_sign, \
+ (evp_verify_method *)ECDSA_verify, \
+ {EVP_PKEY_EC,0,0,0}
+#else
+#define EVP_PKEY_ECDSA_method EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_RSA_method (evp_sign_method *)RSA_sign, \
+ (evp_verify_method *)RSA_verify, \
+ {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \
+ (evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \
+ (evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \
+ {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#else
+#define EVP_PKEY_RSA_method EVP_PKEY_NULL_method
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method
+#endif
+
+#endif /* !EVP_MD */
+
+struct env_md_ctx_st
+ {
+ const EVP_MD *digest;
+ ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */
+ unsigned long flags;
+ void *md_data;
+ } /* EVP_MD_CTX */;
+
+/* values for EVP_MD_CTX flags */
+
+#define EVP_MD_CTX_FLAG_ONESHOT 0x0001 /* digest update will be called
+ * once only */
+#define EVP_MD_CTX_FLAG_CLEANED 0x0002 /* context has already been
+ * cleaned */
+#define EVP_MD_CTX_FLAG_REUSE 0x0004 /* Don't free up ctx->md_data
+ * in EVP_MD_CTX_cleanup */
+#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008 /* Allow use of non FIPS digest
+ * in FIPS mode */
+
+#define EVP_MD_CTX_FLAG_PAD_MASK 0xF0 /* RSA mode to use */
+#define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00 /* PKCS#1 v1.5 mode */
+#define EVP_MD_CTX_FLAG_PAD_X931 0x10 /* X9.31 mode */
+#define EVP_MD_CTX_FLAG_PAD_PSS 0x20 /* PSS mode */
+#define M_EVP_MD_CTX_FLAG_PSS_SALT(ctx) \
+ ((ctx->flags>>16) &0xFFFF) /* seed length */
+#define EVP_MD_CTX_FLAG_PSS_MDLEN 0xFFFF /* salt len same as digest */
+#define EVP_MD_CTX_FLAG_PSS_MREC 0xFFFE /* salt max or auto recovered */
+
+struct evp_cipher_st
+ {
+ int nid;
+ int block_size;
+ int key_len; /* Default value for variable length ciphers */
+ int iv_len;
+ unsigned long flags; /* Various flags */
+ int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc); /* init key */
+ int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */
+ int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */
+ int ctx_size; /* how big ctx->cipher_data needs to be */
+ int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */
+ int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */
+ int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */
+ void *app_data; /* Application data */
+ } /* EVP_CIPHER */;
+
+/* Values for cipher flags */
+
+/* Modes for ciphers */
+
+#define EVP_CIPH_STREAM_CIPHER 0x0
+#define EVP_CIPH_ECB_MODE 0x1
+#define EVP_CIPH_CBC_MODE 0x2
+#define EVP_CIPH_CFB_MODE 0x3
+#define EVP_CIPH_OFB_MODE 0x4
+#define EVP_CIPH_MODE 0x7
+/* Set if variable length cipher */
+#define EVP_CIPH_VARIABLE_LENGTH 0x8
+/* Set if the iv handling should be done by the cipher itself */
+#define EVP_CIPH_CUSTOM_IV 0x10
+/* Set if the cipher's init() function should be called if key is NULL */
+#define EVP_CIPH_ALWAYS_CALL_INIT 0x20
+/* Call ctrl() to init cipher parameters */
+#define EVP_CIPH_CTRL_INIT 0x40
+/* Don't use standard key length function */
+#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80
+/* Don't use standard block padding */
+#define EVP_CIPH_NO_PADDING 0x100
+/* cipher handles random key generation */
+#define EVP_CIPH_RAND_KEY 0x200
+/* Note if suitable for use in FIPS mode */
+#define EVP_CIPH_FLAG_FIPS 0x400
+/* Allow non FIPS cipher in FIPS mode */
+#define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x800
+/* Allow use default ASN1 get/set iv */
+#define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000
+/* Buffer length in bits not bytes: CFB1 mode only */
+#define EVP_CIPH_FLAG_LENGTH_BITS 0x2000
+
+/* ctrl() values */
+
+#define EVP_CTRL_INIT 0x0
+#define EVP_CTRL_SET_KEY_LENGTH 0x1
+#define EVP_CTRL_GET_RC2_KEY_BITS 0x2
+#define EVP_CTRL_SET_RC2_KEY_BITS 0x3
+#define EVP_CTRL_GET_RC5_ROUNDS 0x4
+#define EVP_CTRL_SET_RC5_ROUNDS 0x5
+#define EVP_CTRL_RAND_KEY 0x6
+
+typedef struct evp_cipher_info_st
+ {
+ const EVP_CIPHER *cipher;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ } EVP_CIPHER_INFO;
+
+struct evp_cipher_ctx_st
+ {
+ const EVP_CIPHER *cipher;
+ ENGINE *engine; /* functional reference if 'cipher' is ENGINE-provided */
+ int encrypt; /* encrypt or decrypt */
+ int buf_len; /* number we have left */
+
+ unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */
+ unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */
+ unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */
+ int num; /* used by cfb/ofb mode */
+
+ void *app_data; /* application stuff */
+ int key_len; /* May change for variable length cipher */
+ unsigned long flags; /* Various flags */
+ void *cipher_data; /* per EVP data */
+ int final_used;
+ int block_mask;
+ unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */
+ } /* EVP_CIPHER_CTX */;
+
+typedef struct evp_Encode_Ctx_st
+ {
+ int num; /* number saved in a partial encode/decode */
+ int length; /* The length is either the output line length
+ * (in input bytes) or the shortest input line
+ * length that is ok. Once decoding begins,
+ * the length is adjusted up each time a longer
+ * line is decoded */
+ unsigned char enc_data[80]; /* data to encode */
+ int line_num; /* number read on current line */
+ int expect_nl;
+ } EVP_ENCODE_CTX;
+
+/* Password based encryption function */
+typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de);
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+ (char *)(rsa))
+#endif
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+ (char *)(dsa))
+#endif
+
+#ifndef OPENSSL_NO_DH
+#define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
+ (char *)(dh))
+#endif
+
+#ifndef OPENSSL_NO_EC
+#define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
+ (char *)(eckey))
+#endif
+
+/* Add some extra combinations */
+#define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
+#define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
+#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
+#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
+
+/* Macros to reduce FIPS dependencies: do NOT use in applications */
+#define M_EVP_MD_size(e) ((e)->md_size)
+#define M_EVP_MD_block_size(e) ((e)->block_size)
+#define M_EVP_MD_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+#define M_EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs))
+#define M_EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs))
+#define M_EVP_MD_type(e) ((e)->type)
+#define M_EVP_MD_CTX_type(e) M_EVP_MD_type(M_EVP_MD_CTX_md(e))
+#define M_EVP_MD_CTX_md(e) ((e)->digest)
+
+#define M_EVP_CIPHER_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+
+int EVP_MD_type(const EVP_MD *md);
+#define EVP_MD_nid(e) EVP_MD_type(e)
+#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e))
+int EVP_MD_pkey_type(const EVP_MD *md);
+int EVP_MD_size(const EVP_MD *md);
+int EVP_MD_block_size(const EVP_MD *md);
+
+const EVP_MD * EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+#define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e))
+
+int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
+int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
+int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
+unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
+
+const EVP_CIPHER * EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
+void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
+#define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
+unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+#define EVP_CIPHER_CTX_mode(e) (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE)
+
+#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80)
+#define EVP_DECODE_LENGTH(l) ((l+3)/4*3+80)
+
+#define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
+#define EVP_SignInit(a,b) EVP_DigestInit(a,b)
+#define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
+#define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
+#define EVP_VerifyInit(a,b) EVP_DigestInit(a,b)
+#define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
+#define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e)
+#define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e)
+
+#ifdef CONST_STRICT
+void BIO_set_md(BIO *,const EVP_MD *md);
+#else
+# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md)
+#endif
+#define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
+#define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
+#define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp)
+#define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
+#define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
+
+int EVP_Cipher(EVP_CIPHER_CTX *c,
+ unsigned char *out,
+ const unsigned char *in,
+ unsigned int inl);
+
+#define EVP_add_cipher_alias(n,alias) \
+ OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_add_digest_alias(n,alias) \
+ OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_delete_cipher_alias(alias) \
+ OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
+#define EVP_delete_digest_alias(alias) \
+ OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in);
+void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
+void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
+int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,int flags);
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
+int EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
+ size_t cnt);
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+int EVP_Digest(const void *data, size_t count,
+ unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl);
+
+int EVP_MD_CTX_copy(EVP_MD_CTX *out,const EVP_MD_CTX *in);
+int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+int EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+
+int EVP_read_pw_string(char *buf,int length,const char *prompt,int verify);
+void EVP_set_pw_prompt(const char *prompt);
+char * EVP_get_pw_prompt(void);
+
+int EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,
+ const unsigned char *salt, const unsigned char *data,
+ int datal, int count, unsigned char *key,unsigned char *iv);
+
+void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
+void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
+int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx,int flags);
+
+int EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key,const unsigned char *iv,
+ int enc);
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key,const unsigned char *iv,
+ int enc);
+int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s,
+ EVP_PKEY *pkey);
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx,const unsigned char *sigbuf,
+ unsigned int siglen,EVP_PKEY *pkey);
+
+int EVP_OpenInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type,
+ const unsigned char *ek, int ekl, const unsigned char *iv,
+ EVP_PKEY *priv);
+int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+ unsigned char **ek, int *ekl, unsigned char *iv,
+ EVP_PKEY **pubk, int npubk);
+int EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl);
+
+void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
+void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+ const unsigned char *in,int inl);
+void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);
+int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+ const unsigned char *in, int inl);
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
+ char *out, int *outl);
+int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
+int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_md(void);
+BIO_METHOD *BIO_f_base64(void);
+BIO_METHOD *BIO_f_cipher(void);
+BIO_METHOD *BIO_f_reliable(void);
+void BIO_set_cipher(BIO *b,const EVP_CIPHER *c,const unsigned char *k,
+ const unsigned char *i, int enc);
+#endif
+
+const EVP_MD *EVP_md_null(void);
+#ifndef OPENSSL_NO_MD2
+const EVP_MD *EVP_md2(void);
+#endif
+#ifndef OPENSSL_NO_MD4
+const EVP_MD *EVP_md4(void);
+#endif
+#ifndef OPENSSL_NO_MD5
+const EVP_MD *EVP_md5(void);
+#endif
+#ifndef OPENSSL_NO_SHA
+const EVP_MD *EVP_sha(void);
+const EVP_MD *EVP_sha1(void);
+const EVP_MD *EVP_dss(void);
+const EVP_MD *EVP_dss1(void);
+const EVP_MD *EVP_ecdsa(void);
+#endif
+#ifndef OPENSSL_NO_SHA256
+const EVP_MD *EVP_sha224(void);
+const EVP_MD *EVP_sha256(void);
+#endif
+#ifndef OPENSSL_NO_SHA512
+const EVP_MD *EVP_sha384(void);
+const EVP_MD *EVP_sha512(void);
+#endif
+#ifndef OPENSSL_NO_MDC2
+const EVP_MD *EVP_mdc2(void);
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+const EVP_MD *EVP_ripemd160(void);
+#endif
+const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */
+#ifndef OPENSSL_NO_DES
+const EVP_CIPHER *EVP_des_ecb(void);
+const EVP_CIPHER *EVP_des_ede(void);
+const EVP_CIPHER *EVP_des_ede3(void);
+const EVP_CIPHER *EVP_des_ede_ecb(void);
+const EVP_CIPHER *EVP_des_ede3_ecb(void);
+const EVP_CIPHER *EVP_des_cfb64(void);
+# define EVP_des_cfb EVP_des_cfb64
+const EVP_CIPHER *EVP_des_cfb1(void);
+const EVP_CIPHER *EVP_des_cfb8(void);
+const EVP_CIPHER *EVP_des_ede_cfb64(void);
+# define EVP_des_ede_cfb EVP_des_ede_cfb64
+#if 0
+const EVP_CIPHER *EVP_des_ede_cfb1(void);
+const EVP_CIPHER *EVP_des_ede_cfb8(void);
+#endif
+const EVP_CIPHER *EVP_des_ede3_cfb64(void);
+# define EVP_des_ede3_cfb EVP_des_ede3_cfb64
+const EVP_CIPHER *EVP_des_ede3_cfb1(void);
+const EVP_CIPHER *EVP_des_ede3_cfb8(void);
+const EVP_CIPHER *EVP_des_ofb(void);
+const EVP_CIPHER *EVP_des_ede_ofb(void);
+const EVP_CIPHER *EVP_des_ede3_ofb(void);
+const EVP_CIPHER *EVP_des_cbc(void);
+const EVP_CIPHER *EVP_des_ede_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_desx_cbc(void);
+/* This should now be supported through the dev_crypto ENGINE. But also, why are
+ * rc4 and md5 declarations made here inside a "NO_DES" precompiler branch? */
+#if 0
+# ifdef OPENSSL_OPENBSD_DEV_CRYPTO
+const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_dev_crypto_rc4(void);
+const EVP_MD *EVP_dev_crypto_md5(void);
+# endif
+#endif
+#endif
+#ifndef OPENSSL_NO_RC4
+const EVP_CIPHER *EVP_rc4(void);
+const EVP_CIPHER *EVP_rc4_40(void);
+#endif
+#ifndef OPENSSL_NO_IDEA
+const EVP_CIPHER *EVP_idea_ecb(void);
+const EVP_CIPHER *EVP_idea_cfb64(void);
+# define EVP_idea_cfb EVP_idea_cfb64
+const EVP_CIPHER *EVP_idea_ofb(void);
+const EVP_CIPHER *EVP_idea_cbc(void);
+#endif
+#ifndef OPENSSL_NO_RC2
+const EVP_CIPHER *EVP_rc2_ecb(void);
+const EVP_CIPHER *EVP_rc2_cbc(void);
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+const EVP_CIPHER *EVP_rc2_64_cbc(void);
+const EVP_CIPHER *EVP_rc2_cfb64(void);
+# define EVP_rc2_cfb EVP_rc2_cfb64
+const EVP_CIPHER *EVP_rc2_ofb(void);
+#endif
+#ifndef OPENSSL_NO_BF
+const EVP_CIPHER *EVP_bf_ecb(void);
+const EVP_CIPHER *EVP_bf_cbc(void);
+const EVP_CIPHER *EVP_bf_cfb64(void);
+# define EVP_bf_cfb EVP_bf_cfb64
+const EVP_CIPHER *EVP_bf_ofb(void);
+#endif
+#ifndef OPENSSL_NO_CAST
+const EVP_CIPHER *EVP_cast5_ecb(void);
+const EVP_CIPHER *EVP_cast5_cbc(void);
+const EVP_CIPHER *EVP_cast5_cfb64(void);
+# define EVP_cast5_cfb EVP_cast5_cfb64
+const EVP_CIPHER *EVP_cast5_ofb(void);
+#endif
+#ifndef OPENSSL_NO_RC5
+const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
+# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
+const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
+#endif
+#ifndef OPENSSL_NO_AES
+const EVP_CIPHER *EVP_aes_128_ecb(void);
+const EVP_CIPHER *EVP_aes_128_cbc(void);
+const EVP_CIPHER *EVP_aes_128_cfb1(void);
+const EVP_CIPHER *EVP_aes_128_cfb8(void);
+const EVP_CIPHER *EVP_aes_128_cfb128(void);
+# define EVP_aes_128_cfb EVP_aes_128_cfb128
+const EVP_CIPHER *EVP_aes_128_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_128_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_192_ecb(void);
+const EVP_CIPHER *EVP_aes_192_cbc(void);
+const EVP_CIPHER *EVP_aes_192_cfb1(void);
+const EVP_CIPHER *EVP_aes_192_cfb8(void);
+const EVP_CIPHER *EVP_aes_192_cfb128(void);
+# define EVP_aes_192_cfb EVP_aes_192_cfb128
+const EVP_CIPHER *EVP_aes_192_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_192_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_256_ecb(void);
+const EVP_CIPHER *EVP_aes_256_cbc(void);
+const EVP_CIPHER *EVP_aes_256_cfb1(void);
+const EVP_CIPHER *EVP_aes_256_cfb8(void);
+const EVP_CIPHER *EVP_aes_256_cfb128(void);
+# define EVP_aes_256_cfb EVP_aes_256_cfb128
+const EVP_CIPHER *EVP_aes_256_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_256_ctr(void);
+#endif
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+const EVP_CIPHER *EVP_camellia_128_ecb(void);
+const EVP_CIPHER *EVP_camellia_128_cbc(void);
+const EVP_CIPHER *EVP_camellia_128_cfb1(void);
+const EVP_CIPHER *EVP_camellia_128_cfb8(void);
+const EVP_CIPHER *EVP_camellia_128_cfb128(void);
+# define EVP_camellia_128_cfb EVP_camellia_128_cfb128
+const EVP_CIPHER *EVP_camellia_128_ofb(void);
+const EVP_CIPHER *EVP_camellia_192_ecb(void);
+const EVP_CIPHER *EVP_camellia_192_cbc(void);
+const EVP_CIPHER *EVP_camellia_192_cfb1(void);
+const EVP_CIPHER *EVP_camellia_192_cfb8(void);
+const EVP_CIPHER *EVP_camellia_192_cfb128(void);
+# define EVP_camellia_192_cfb EVP_camellia_192_cfb128
+const EVP_CIPHER *EVP_camellia_192_ofb(void);
+const EVP_CIPHER *EVP_camellia_256_ecb(void);
+const EVP_CIPHER *EVP_camellia_256_cbc(void);
+const EVP_CIPHER *EVP_camellia_256_cfb1(void);
+const EVP_CIPHER *EVP_camellia_256_cfb8(void);
+const EVP_CIPHER *EVP_camellia_256_cfb128(void);
+# define EVP_camellia_256_cfb EVP_camellia_256_cfb128
+const EVP_CIPHER *EVP_camellia_256_ofb(void);
+#endif
+
+#ifndef OPENSSL_NO_SEED
+const EVP_CIPHER *EVP_seed_ecb(void);
+const EVP_CIPHER *EVP_seed_cbc(void);
+const EVP_CIPHER *EVP_seed_cfb128(void);
+# define EVP_seed_cfb EVP_seed_cfb128
+const EVP_CIPHER *EVP_seed_ofb(void);
+#endif
+
+void OPENSSL_add_all_algorithms_noconf(void);
+void OPENSSL_add_all_algorithms_conf(void);
+
+#ifdef OPENSSL_LOAD_CONF
+#define OpenSSL_add_all_algorithms() \
+ OPENSSL_add_all_algorithms_conf()
+#else
+#define OpenSSL_add_all_algorithms() \
+ OPENSSL_add_all_algorithms_noconf()
+#endif
+
+void OpenSSL_add_all_ciphers(void);
+void OpenSSL_add_all_digests(void);
+#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
+#define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers()
+#define SSLeay_add_all_digests() OpenSSL_add_all_digests()
+
+int EVP_add_cipher(const EVP_CIPHER *cipher);
+int EVP_add_digest(const EVP_MD *digest);
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
+const EVP_MD *EVP_get_digestbyname(const char *name);
+void EVP_cleanup(void);
+
+int EVP_PKEY_decrypt(unsigned char *dec_key,
+ const unsigned char *enc_key,int enc_key_len,
+ EVP_PKEY *private_key);
+int EVP_PKEY_encrypt(unsigned char *enc_key,
+ const unsigned char *key,int key_len,
+ EVP_PKEY *pub_key);
+int EVP_PKEY_type(int type);
+int EVP_PKEY_bits(EVP_PKEY *pkey);
+int EVP_PKEY_size(EVP_PKEY *pkey);
+int EVP_PKEY_assign(EVP_PKEY *pkey,int type,char *key);
+
+#ifndef OPENSSL_NO_RSA
+struct rsa_st;
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,struct rsa_st *key);
+struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DSA
+struct dsa_st;
+int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,struct dsa_st *key);
+struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DH
+struct dh_st;
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey,struct dh_st *key);
+struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_EC
+struct ec_key_st;
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey,struct ec_key_st *key);
+struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+#endif
+
+EVP_PKEY * EVP_PKEY_new(void);
+void EVP_PKEY_free(EVP_PKEY *pkey);
+
+EVP_PKEY * d2i_PublicKey(int type,EVP_PKEY **a, const unsigned char **pp,
+ long length);
+int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+
+EVP_PKEY * d2i_PrivateKey(int type,EVP_PKEY **a, const unsigned char **pp,
+ long length);
+EVP_PKEY * d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+ long length);
+int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+
+int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode);
+int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_CIPHER_type(const EVP_CIPHER *ctx);
+
+/* calls methods */
+int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
+/* These are used by EVP_CIPHER methods */
+int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+
+/* PKCS5 password based encryption */
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+ int en_de);
+int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+ const unsigned char *salt, int saltlen, int iter,
+ int keylen, unsigned char *out);
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+ int en_de);
+
+void PKCS5_PBE_add(void);
+
+int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+ EVP_PBE_KEYGEN *keygen);
+void EVP_PBE_cleanup(void);
+
+#ifdef OPENSSL_FIPS
+#ifndef OPENSSL_NO_ENGINE
+void int_EVP_MD_set_engine_callbacks(
+ int (*eng_md_init)(ENGINE *impl),
+ int (*eng_md_fin)(ENGINE *impl),
+ int (*eng_md_evp)
+ (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl));
+void int_EVP_MD_init_engine_callbacks(void);
+void int_EVP_CIPHER_set_engine_callbacks(
+ int (*eng_ciph_fin)(ENGINE *impl),
+ int (*eng_ciph_evp)
+ (EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl));
+void int_EVP_CIPHER_init_engine_callbacks(void);
+#endif
+#endif
+
+void EVP_add_alg_module(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EVP_strings(void);
+
+/* Error codes for the EVP functions. */
+
+/* Function codes. */
+#define EVP_F_AES_INIT_KEY 133
+#define EVP_F_ALG_MODULE_INIT 138
+#define EVP_F_CAMELLIA_INIT_KEY 159
+#define EVP_F_D2I_PKEY 100
+#define EVP_F_DO_EVP_ENC_ENGINE 140
+#define EVP_F_DO_EVP_ENC_ENGINE_FULL 141
+#define EVP_F_DO_EVP_MD_ENGINE 139
+#define EVP_F_DO_EVP_MD_ENGINE_FULL 142
+#define EVP_F_DSAPKEY2PKCS8 134
+#define EVP_F_DSA_PKEY2PKCS8 135
+#define EVP_F_ECDSA_PKEY2PKCS8 129
+#define EVP_F_ECKEY_PKEY2PKCS8 132
+#define EVP_F_EVP_CIPHERINIT 137
+#define EVP_F_EVP_CIPHERINIT_EX 123
+#define EVP_F_EVP_CIPHER_CTX_CTRL 124
+#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122
+#define EVP_F_EVP_DECRYPTFINAL_EX 101
+#define EVP_F_EVP_DIGESTINIT 136
+#define EVP_F_EVP_DIGESTINIT_EX 128
+#define EVP_F_EVP_ENCRYPTFINAL_EX 127
+#define EVP_F_EVP_MD_CTX_COPY_EX 110
+#define EVP_F_EVP_OPENINIT 102
+#define EVP_F_EVP_PBE_ALG_ADD 115
+#define EVP_F_EVP_PBE_CIPHERINIT 116
+#define EVP_F_EVP_PKCS82PKEY 111
+#define EVP_F_EVP_PKEY2PKCS8_BROKEN 113
+#define EVP_F_EVP_PKEY_COPY_PARAMETERS 103
+#define EVP_F_EVP_PKEY_DECRYPT 104
+#define EVP_F_EVP_PKEY_ENCRYPT 105
+#define EVP_F_EVP_PKEY_GET1_DH 119
+#define EVP_F_EVP_PKEY_GET1_DSA 120
+#define EVP_F_EVP_PKEY_GET1_ECDSA 130
+#define EVP_F_EVP_PKEY_GET1_EC_KEY 131
+#define EVP_F_EVP_PKEY_GET1_RSA 121
+#define EVP_F_EVP_PKEY_NEW 106
+#define EVP_F_EVP_RIJNDAEL 126
+#define EVP_F_EVP_SIGNFINAL 107
+#define EVP_F_EVP_VERIFYFINAL 108
+#define EVP_F_PKCS5_PBE_KEYIVGEN 117
+#define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118
+#define EVP_F_PKCS8_SET_BROKEN 112
+#define EVP_F_RC2_MAGIC_TO_METH 109
+#define EVP_F_RC5_CTRL 125
+
+/* Reason codes. */
+#define EVP_R_AES_KEY_SETUP_FAILED 143
+#define EVP_R_ASN1_LIB 140
+#define EVP_R_BAD_BLOCK_LENGTH 136
+#define EVP_R_BAD_DECRYPT 100
+#define EVP_R_BAD_KEY_LENGTH 137
+#define EVP_R_BN_DECODE_ERROR 112
+#define EVP_R_BN_PUBKEY_ERROR 113
+#define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157
+#define EVP_R_CIPHER_PARAMETER_ERROR 122
+#define EVP_R_CTRL_NOT_IMPLEMENTED 132
+#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133
+#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138
+#define EVP_R_DECODE_ERROR 114
+#define EVP_R_DIFFERENT_KEY_TYPES 101
+#define EVP_R_DISABLED_FOR_FIPS 144
+#define EVP_R_ENCODE_ERROR 115
+#define EVP_R_ERROR_LOADING_SECTION 145
+#define EVP_R_ERROR_SETTING_FIPS_MODE 146
+#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119
+#define EVP_R_EXPECTING_AN_RSA_KEY 127
+#define EVP_R_EXPECTING_A_DH_KEY 128
+#define EVP_R_EXPECTING_A_DSA_KEY 129
+#define EVP_R_EXPECTING_A_ECDSA_KEY 141
+#define EVP_R_EXPECTING_A_EC_KEY 142
+#define EVP_R_FIPS_MODE_NOT_SUPPORTED 147
+#define EVP_R_INITIALIZATION_ERROR 134
+#define EVP_R_INPUT_NOT_INITIALIZED 111
+#define EVP_R_INVALID_FIPS_MODE 148
+#define EVP_R_INVALID_KEY_LENGTH 130
+#define EVP_R_IV_TOO_LARGE 102
+#define EVP_R_KEYGEN_FAILURE 120
+#define EVP_R_MISSING_PARAMETERS 103
+#define EVP_R_NO_CIPHER_SET 131
+#define EVP_R_NO_DIGEST_SET 139
+#define EVP_R_NO_DSA_PARAMETERS 116
+#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104
+#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105
+#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE 117
+#define EVP_R_PUBLIC_KEY_NOT_RSA 106
+#define EVP_R_UNKNOWN_OPTION 149
+#define EVP_R_UNKNOWN_PBE_ALGORITHM 121
+#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135
+#define EVP_R_UNSUPPORTED_CIPHER 107
+#define EVP_R_UNSUPPORTED_KEYLENGTH 123
+#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124
+#define EVP_R_UNSUPPORTED_KEY_SIZE 108
+#define EVP_R_UNSUPPORTED_PRF 125
+#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118
+#define EVP_R_UNSUPPORTED_SALT_TYPE 126
+#define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE 110
+#define EVP_R_SEED_KEY_SETUP_FAILED 162
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/fips.h b/src/Mayaqua/win32_inc/openssl/fips.h
new file mode 100644
index 00000000..3af03253
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/fips.h
@@ -0,0 +1,126 @@
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_FIPS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Note that these are defined in crypto/cryptlib.c so they're
+ * available even without -lfips.
+ */
+struct dsa_st;
+
+int FIPS_mode_set(int onoff,const char *path);
+void FIPS_allow_md5(int onoff);
+int FIPS_md5_allowed(void);
+int FIPS_selftest_failed(void);
+int FIPS_dsa_check(struct dsa_st *dsa);
+void FIPS_corrupt_sha1(void);
+int FIPS_selftest_sha1(void);
+void FIPS_corrupt_aes(void);
+int FIPS_selftest_aes(void);
+void FIPS_corrupt_des(void);
+int FIPS_selftest_des(void);
+void FIPS_corrupt_rsa(void);
+int FIPS_selftest_rsa(void);
+void FIPS_corrupt_dsa(void);
+int FIPS_selftest_dsa(void);
+
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_FIPS_strings(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_FIPS_strings(void);
+
+/* Error codes for the FIPS functions. */
+
+/* Function codes. */
+#define FIPS_F_DSA_DO_SIGN 111
+#define FIPS_F_DSA_DO_VERIFY 112
+#define FIPS_F_DSA_GENERATE_PARAMETERS 110
+#define FIPS_F_FIPS_CHECK_DSA 116
+#define FIPS_F_FIPS_CHECK_EXE 106
+#define FIPS_F_FIPS_CHECK_RSA 115
+#define FIPS_F_FIPS_DSA_CHECK 102
+#define FIPS_F_FIPS_MODE_SET 105
+#define FIPS_F_FIPS_SELFTEST_AES 104
+#define FIPS_F_FIPS_SELFTEST_DES 107
+#define FIPS_F_FIPS_SELFTEST_DSA 109
+#define FIPS_F_FIPS_SELFTEST_RSA 108
+#define FIPS_F_FIPS_SELFTEST_SHA1 103
+#define FIPS_F_HASH_FINAL 100
+#define FIPS_F_DH_GENERATE_PARAMETERS 117
+#define FIPS_F_RSA_EAY_PUBLIC_ENCRYPT 114
+#define FIPS_F_RSA_GENERATE_KEY 113
+#define FIPS_F_SSLEAY_RAND_BYTES 101
+
+/* Reason codes. */
+#define FIPS_R_CANNOT_READ_EXE 103
+#define FIPS_R_CANNOT_READ_EXE_DIGEST 104
+#define FIPS_R_EXE_DIGEST_DOES_NOT_MATCH 105
+#define FIPS_R_FIPS_MODE_ALREADY_SET 102
+#define FIPS_R_FIPS_SELFTEST_FAILED 106
+#define FIPS_R_NON_FIPS_METHOD 100
+#define FIPS_R_PAIRWISE_TEST_FAILED 107
+#define FIPS_R_SELFTEST_FAILED 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/fips_rand.h b/src/Mayaqua/win32_inc/openssl/fips_rand.h
new file mode 100644
index 00000000..07a925d4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/fips_rand.h
@@ -0,0 +1,74 @@
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef HEADER_FIPS_RAND_H
+#define HEADER_FIPS_RAND_H
+
+#include "des.h"
+
+#ifdef OPENSSL_FIPS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void FIPS_set_prng_key(const unsigned char k1[8],const unsigned char k2[8]);
+void FIPS_test_mode(int test,const unsigned char faketime[8]);
+void FIPS_rand_seed(const void *buf, FIPS_RAND_SIZE_T num);
+/* NB: this returns true if _partially_ seeded */
+int FIPS_rand_seeded(void);
+
+RAND_METHOD *FIPS_rand_method(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/hmac.h b/src/Mayaqua/win32_inc/openssl/hmac.h
new file mode 100644
index 00000000..4bbf8b57
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/hmac.h
@@ -0,0 +1,109 @@
+/* crypto/hmac/hmac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#ifndef HEADER_HMAC_H
+#define HEADER_HMAC_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_HMAC
+#error HMAC is disabled.
+#endif
+
+#include <openssl/evp.h>
+
+#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct hmac_ctx_st
+ {
+ const EVP_MD *md;
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX i_ctx;
+ EVP_MD_CTX o_ctx;
+ unsigned int key_length;
+ unsigned char key[HMAC_MAX_MD_CBLOCK];
+ } HMAC_CTX;
+
+#define HMAC_size(e) (EVP_MD_size((e)->md))
+
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) /* deprecated */
+
+void HMAC_Init(HMAC_CTX *ctx, const void *key, int len,
+ const EVP_MD *md); /* deprecated */
+void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ const EVP_MD *md, ENGINE *impl);
+void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+ const unsigned char *d, size_t n, unsigned char *md,
+ unsigned int *md_len);
+
+void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/idea.h b/src/Mayaqua/win32_inc/openssl/idea.h
new file mode 100644
index 00000000..f52d21fa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/idea.h
@@ -0,0 +1,103 @@
+/* crypto/idea/idea.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_IDEA_H
+#define HEADER_IDEA_H
+
+#include <openssl/opensslconf.h> /* IDEA_INT, OPENSSL_NO_IDEA */
+
+#ifdef OPENSSL_NO_IDEA
+#error IDEA is disabled.
+#endif
+
+#define IDEA_ENCRYPT 1
+#define IDEA_DECRYPT 0
+
+#define IDEA_BLOCK 8
+#define IDEA_KEY_LENGTH 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct idea_key_st
+ {
+ IDEA_INT data[9][6];
+ } IDEA_KEY_SCHEDULE;
+
+const char *idea_options(void);
+void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ IDEA_KEY_SCHEDULE *ks);
+#ifdef OPENSSL_FIPS
+void private_idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+#endif
+void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+void idea_set_decrypt_key(const IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
+void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc);
+void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+ int *num,int enc);
+void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num);
+void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/krb5_asn.h b/src/Mayaqua/win32_inc/openssl/krb5_asn.h
new file mode 100644
index 00000000..fa08967f
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/krb5_asn.h
@@ -0,0 +1,256 @@
+/* krb5_asn.h */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project,
+** using ocsp/{*.h,*asn*.c} as a starting point
+*/
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_KRB5_ASN_H
+#define HEADER_KRB5_ASN_H
+
+/*
+#include <krb5.h>
+*/
+#include <openssl/safestack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ASN.1 from Kerberos RFC 1510
+*/
+
+/* EncryptedData ::= SEQUENCE {
+** etype[0] INTEGER, -- EncryptionType
+** kvno[1] INTEGER OPTIONAL,
+** cipher[2] OCTET STRING -- ciphertext
+** }
+*/
+typedef struct krb5_encdata_st
+ {
+ ASN1_INTEGER *etype;
+ ASN1_INTEGER *kvno;
+ ASN1_OCTET_STRING *cipher;
+ } KRB5_ENCDATA;
+
+DECLARE_STACK_OF(KRB5_ENCDATA)
+
+/* PrincipalName ::= SEQUENCE {
+** name-type[0] INTEGER,
+** name-string[1] SEQUENCE OF GeneralString
+** }
+*/
+typedef struct krb5_princname_st
+ {
+ ASN1_INTEGER *nametype;
+ STACK_OF(ASN1_GENERALSTRING) *namestring;
+ } KRB5_PRINCNAME;
+
+DECLARE_STACK_OF(KRB5_PRINCNAME)
+
+
+/* Ticket ::= [APPLICATION 1] SEQUENCE {
+** tkt-vno[0] INTEGER,
+** realm[1] Realm,
+** sname[2] PrincipalName,
+** enc-part[3] EncryptedData
+** }
+*/
+typedef struct krb5_tktbody_st
+ {
+ ASN1_INTEGER *tktvno;
+ ASN1_GENERALSTRING *realm;
+ KRB5_PRINCNAME *sname;
+ KRB5_ENCDATA *encdata;
+ } KRB5_TKTBODY;
+
+typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET;
+DECLARE_STACK_OF(KRB5_TKTBODY)
+
+
+/* AP-REQ ::= [APPLICATION 14] SEQUENCE {
+** pvno[0] INTEGER,
+** msg-type[1] INTEGER,
+** ap-options[2] APOptions,
+** ticket[3] Ticket,
+** authenticator[4] EncryptedData
+** }
+**
+** APOptions ::= BIT STRING {
+** reserved(0), use-session-key(1), mutual-required(2) }
+*/
+typedef struct krb5_ap_req_st
+ {
+ ASN1_INTEGER *pvno;
+ ASN1_INTEGER *msgtype;
+ ASN1_BIT_STRING *apoptions;
+ KRB5_TICKET *ticket;
+ KRB5_ENCDATA *authenticator;
+ } KRB5_APREQBODY;
+
+typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ;
+DECLARE_STACK_OF(KRB5_APREQBODY)
+
+
+/* Authenticator Stuff */
+
+
+/* Checksum ::= SEQUENCE {
+** cksumtype[0] INTEGER,
+** checksum[1] OCTET STRING
+** }
+*/
+typedef struct krb5_checksum_st
+ {
+ ASN1_INTEGER *ctype;
+ ASN1_OCTET_STRING *checksum;
+ } KRB5_CHECKSUM;
+
+DECLARE_STACK_OF(KRB5_CHECKSUM)
+
+
+/* EncryptionKey ::= SEQUENCE {
+** keytype[0] INTEGER,
+** keyvalue[1] OCTET STRING
+** }
+*/
+typedef struct krb5_encryptionkey_st
+ {
+ ASN1_INTEGER *ktype;
+ ASN1_OCTET_STRING *keyvalue;
+ } KRB5_ENCKEY;
+
+DECLARE_STACK_OF(KRB5_ENCKEY)
+
+
+/* AuthorizationData ::= SEQUENCE OF SEQUENCE {
+** ad-type[0] INTEGER,
+** ad-data[1] OCTET STRING
+** }
+*/
+typedef struct krb5_authorization_st
+ {
+ ASN1_INTEGER *adtype;
+ ASN1_OCTET_STRING *addata;
+ } KRB5_AUTHDATA;
+
+DECLARE_STACK_OF(KRB5_AUTHDATA)
+
+
+/* -- Unencrypted authenticator
+** Authenticator ::= [APPLICATION 2] SEQUENCE {
+** authenticator-vno[0] INTEGER,
+** crealm[1] Realm,
+** cname[2] PrincipalName,
+** cksum[3] Checksum OPTIONAL,
+** cusec[4] INTEGER,
+** ctime[5] KerberosTime,
+** subkey[6] EncryptionKey OPTIONAL,
+** seq-number[7] INTEGER OPTIONAL,
+** authorization-data[8] AuthorizationData OPTIONAL
+** }
+*/
+typedef struct krb5_authenticator_st
+ {
+ ASN1_INTEGER *avno;
+ ASN1_GENERALSTRING *crealm;
+ KRB5_PRINCNAME *cname;
+ KRB5_CHECKSUM *cksum;
+ ASN1_INTEGER *cusec;
+ ASN1_GENERALIZEDTIME *ctime;
+ KRB5_ENCKEY *subkey;
+ ASN1_INTEGER *seqnum;
+ KRB5_AUTHDATA *authorization;
+ } KRB5_AUTHENTBODY;
+
+typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT;
+DECLARE_STACK_OF(KRB5_AUTHENTBODY)
+
+
+/* DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) =
+** type *name##_new(void);
+** void name##_free(type *a);
+** DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) =
+** DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) =
+** type *d2i_##name(type **a, const unsigned char **in, long len);
+** int i2d_##name(type *a, unsigned char **out);
+** DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it
+*/
+
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME)
+DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_TICKET)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQ)
+
+DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM)
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT)
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/kssl.h b/src/Mayaqua/win32_inc/openssl/kssl.h
new file mode 100644
index 00000000..c84820f5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/kssl.h
@@ -0,0 +1,179 @@
+/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+** 19990701 VRS Started.
+*/
+
+#ifndef KSSL_H
+#define KSSL_H
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_KRB5
+
+#include <stdio.h>
+#include <ctype.h>
+#include <krb5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Depending on which KRB5 implementation used, some types from
+** the other may be missing. Resolve that here and now
+*/
+#ifdef KRB5_HEIMDAL
+typedef unsigned char krb5_octet;
+#define FAR
+#else
+
+#ifndef FAR
+#define FAR
+#endif
+
+#endif
+
+/* Uncomment this to debug kssl problems or
+** to trace usage of the Kerberos session key
+**
+** #define KSSL_DEBUG
+*/
+
+#ifndef KRB5SVC
+#define KRB5SVC "host"
+#endif
+
+#ifndef KRB5KEYTAB
+#define KRB5KEYTAB "/etc/krb5.keytab"
+#endif
+
+#ifndef KRB5SENDAUTH
+#define KRB5SENDAUTH 1
+#endif
+
+#ifndef KRB5CHECKAUTH
+#define KRB5CHECKAUTH 1
+#endif
+
+#ifndef KSSL_CLOCKSKEW
+#define KSSL_CLOCKSKEW 300;
+#endif
+
+#define KSSL_ERR_MAX 255
+typedef struct kssl_err_st {
+ int reason;
+ char text[KSSL_ERR_MAX+1];
+ } KSSL_ERR;
+
+
+/* Context for passing
+** (1) Kerberos session key to SSL, and
+** (2) Config data between application and SSL lib
+*/
+typedef struct kssl_ctx_st
+ {
+ /* used by: disposition: */
+ char *service_name; /* C,S default ok (kssl) */
+ char *service_host; /* C input, REQUIRED */
+ char *client_princ; /* S output from krb5 ticket */
+ char *keytab_file; /* S NULL (/etc/krb5.keytab) */
+ char *cred_cache; /* C NULL (default) */
+ krb5_enctype enctype;
+ int length;
+ krb5_octet FAR *key;
+ } KSSL_CTX;
+
+#define KSSL_CLIENT 1
+#define KSSL_SERVER 2
+#define KSSL_SERVICE 3
+#define KSSL_KEYTAB 4
+
+#define KSSL_CTX_OK 0
+#define KSSL_CTX_ERR 1
+#define KSSL_NOMEM 2
+
+/* Public (for use by applications that use OpenSSL with Kerberos 5 support */
+krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text);
+KSSL_CTX *kssl_ctx_new(void);
+KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx);
+void kssl_ctx_show(KSSL_CTX *kssl_ctx);
+krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+ krb5_data *realm, krb5_data *entity, int nentities);
+krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data **enc_tktp,
+ krb5_data *authenp, KSSL_ERR *kssl_err);
+krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, krb5_data *indata,
+ krb5_ticket_times *ttimes, KSSL_ERR *kssl_err);
+krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session);
+void kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text);
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data);
+krb5_error_code kssl_build_principal_2(krb5_context context,
+ krb5_principal *princ, int rlen, const char *realm,
+ int slen, const char *svc, int hlen, const char *host);
+krb5_error_code kssl_validate_times(krb5_timestamp atime,
+ krb5_ticket_times *ttimes);
+krb5_error_code kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp,
+ krb5_timestamp *atimep, KSSL_ERR *kssl_err);
+unsigned char *kssl_skip_confound(krb5_enctype enctype, unsigned char *authn);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* OPENSSL_NO_KRB5 */
+#endif /* KSSL_H */
diff --git a/src/Mayaqua/win32_inc/openssl/lhash.h b/src/Mayaqua/win32_inc/openssl/lhash.h
new file mode 100644
index 00000000..d0b1daf6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/lhash.h
@@ -0,0 +1,200 @@
+/* crypto/lhash/lhash.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+
+#ifndef HEADER_LHASH_H
+#define HEADER_LHASH_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct lhash_node_st
+ {
+ void *data;
+ struct lhash_node_st *next;
+#ifndef OPENSSL_NO_HASH_COMP
+ unsigned long hash;
+#endif
+ } LHASH_NODE;
+
+typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *);
+typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *);
+typedef void (*LHASH_DOALL_FN_TYPE)(void *);
+typedef void (*LHASH_DOALL_ARG_FN_TYPE)(void *, void *);
+
+/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks.
+ * This way, callbacks can be provided to LHASH structures without function
+ * pointer casting and the macro-defined callbacks provide per-variable casting
+ * before deferring to the underlying type-specific callbacks. NB: It is
+ * possible to place a "static" in front of both the DECLARE and IMPLEMENT
+ * macros if the functions are strictly internal. */
+
+/* First: "hash" functions */
+#define DECLARE_LHASH_HASH_FN(f_name,o_type) \
+ unsigned long f_name##_LHASH_HASH(const void *);
+#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \
+ unsigned long f_name##_LHASH_HASH(const void *arg) { \
+ o_type a = (o_type)arg; \
+ return f_name(a); }
+#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH
+
+/* Second: "compare" functions */
+#define DECLARE_LHASH_COMP_FN(f_name,o_type) \
+ int f_name##_LHASH_COMP(const void *, const void *);
+#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \
+ int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+ o_type a = (o_type)arg1; \
+ o_type b = (o_type)arg2; \
+ return f_name(a,b); }
+#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
+
+/* Third: "doall" functions */
+#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \
+ void f_name##_LHASH_DOALL(void *);
+#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \
+ void f_name##_LHASH_DOALL(void *arg) { \
+ o_type a = (o_type)arg; \
+ f_name(a); }
+#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL
+
+/* Fourth: "doall_arg" functions */
+#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+ void f_name##_LHASH_DOALL_ARG(void *, void *);
+#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+ void f_name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+ o_type a = (o_type)arg1; \
+ a_type b = (a_type)arg2; \
+ f_name(a,b); }
+#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG
+
+typedef struct lhash_st
+ {
+ LHASH_NODE **b;
+ LHASH_COMP_FN_TYPE comp;
+ LHASH_HASH_FN_TYPE hash;
+ unsigned int num_nodes;
+ unsigned int num_alloc_nodes;
+ unsigned int p;
+ unsigned int pmax;
+ unsigned long up_load; /* load times 256 */
+ unsigned long down_load; /* load times 256 */
+ unsigned long num_items;
+
+ unsigned long num_expands;
+ unsigned long num_expand_reallocs;
+ unsigned long num_contracts;
+ unsigned long num_contract_reallocs;
+ unsigned long num_hash_calls;
+ unsigned long num_comp_calls;
+ unsigned long num_insert;
+ unsigned long num_replace;
+ unsigned long num_delete;
+ unsigned long num_no_delete;
+ unsigned long num_retrieve;
+ unsigned long num_retrieve_miss;
+ unsigned long num_hash_comps;
+
+ int error;
+ } LHASH;
+
+#define LH_LOAD_MULT 256
+
+/* Indicates a malloc() error in the last call, this is only bad
+ * in lh_insert(). */
+#define lh_error(lh) ((lh)->error)
+
+LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
+void lh_free(LHASH *lh);
+void *lh_insert(LHASH *lh, void *data);
+void *lh_delete(LHASH *lh, const void *data);
+void *lh_retrieve(LHASH *lh, const void *data);
+void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func);
+void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
+unsigned long lh_strhash(const char *c);
+unsigned long lh_num_items(const LHASH *lh);
+
+#ifndef OPENSSL_NO_FP_API
+void lh_stats(const LHASH *lh, FILE *out);
+void lh_node_stats(const LHASH *lh, FILE *out);
+void lh_node_usage_stats(const LHASH *lh, FILE *out);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+void lh_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_usage_stats_bio(const LHASH *lh, BIO *out);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/md2.h b/src/Mayaqua/win32_inc/openssl/md2.h
new file mode 100644
index 00000000..f06843e1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md2.h
@@ -0,0 +1,95 @@
+/* crypto/md/md2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD2_H
+#define HEADER_MD2_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_MD2, MD2_INT */
+#ifdef OPENSSL_NO_MD2
+#error MD2 is disabled.
+#endif
+#include <stddef.h>
+
+#define MD2_DIGEST_LENGTH 16
+#define MD2_BLOCK 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct MD2state_st
+ {
+ unsigned int num;
+ unsigned char data[MD2_BLOCK];
+ MD2_INT cksm[MD2_BLOCK];
+ MD2_INT state[MD2_BLOCK];
+ } MD2_CTX;
+
+const char *MD2_options(void);
+#ifdef OPENSSL_FIPS
+int private_MD2_Init(MD2_CTX *c);
+#endif
+int MD2_Init(MD2_CTX *c);
+int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len);
+int MD2_Final(unsigned char *md, MD2_CTX *c);
+unsigned char *MD2(const unsigned char *d, size_t n,unsigned char *md);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/md4.h b/src/Mayaqua/win32_inc/openssl/md4.h
new file mode 100644
index 00000000..b316d87d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md4.h
@@ -0,0 +1,120 @@
+/* crypto/md4/md4.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD4_H
+#define HEADER_MD4_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD4
+#error MD4 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD4_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD4_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD4_LONG unsigned long
+#define MD4_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define MD4_LONG unsigned int
+#endif
+
+#define MD4_CBLOCK 64
+#define MD4_LBLOCK (MD4_CBLOCK/4)
+#define MD4_DIGEST_LENGTH 16
+
+typedef struct MD4state_st
+ {
+ MD4_LONG A,B,C,D;
+ MD4_LONG Nl,Nh;
+ MD4_LONG data[MD4_LBLOCK];
+ unsigned int num;
+ } MD4_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MD4_Init(MD4_CTX *c);
+#endif
+int MD4_Init(MD4_CTX *c);
+int MD4_Update(MD4_CTX *c, const void *data, size_t len);
+int MD4_Final(unsigned char *md, MD4_CTX *c);
+unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md);
+void MD4_Transform(MD4_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/md5.h b/src/Mayaqua/win32_inc/openssl/md5.h
new file mode 100644
index 00000000..f84cc762
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md5.h
@@ -0,0 +1,120 @@
+/* crypto/md5/md5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD5_H
+#define HEADER_MD5_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD5
+#error MD5 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD5_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD5_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD5_LONG unsigned long
+#define MD5_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define MD5_LONG unsigned int
+#endif
+
+#define MD5_CBLOCK 64
+#define MD5_LBLOCK (MD5_CBLOCK/4)
+#define MD5_DIGEST_LENGTH 16
+
+typedef struct MD5state_st
+ {
+ MD5_LONG A,B,C,D;
+ MD5_LONG Nl,Nh;
+ MD5_LONG data[MD5_LBLOCK];
+ unsigned int num;
+ } MD5_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MD5_Init(MD5_CTX *c);
+#endif
+int MD5_Init(MD5_CTX *c);
+int MD5_Update(MD5_CTX *c, const void *data, size_t len);
+int MD5_Final(unsigned char *md, MD5_CTX *c);
+unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
+void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/mdc2.h b/src/Mayaqua/win32_inc/openssl/mdc2.h
new file mode 100644
index 00000000..48320c42
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/mdc2.h
@@ -0,0 +1,98 @@
+/* crypto/mdc2/mdc2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MDC2_H
+#define HEADER_MDC2_H
+
+#include <openssl/des.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MDC2
+#error MDC2 is disabled.
+#endif
+
+#define MDC2_BLOCK 8
+#define MDC2_DIGEST_LENGTH 16
+
+typedef struct mdc2_ctx_st
+ {
+ int num;
+ unsigned char data[MDC2_BLOCK];
+ DES_cblock h,hh;
+ int pad_type; /* either 1 or 2, default 1 */
+ } MDC2_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MDC2_Init(MDC2_CTX *c);
+#endif
+int MDC2_Init(MDC2_CTX *c);
+int MDC2_Update(MDC2_CTX *c, const unsigned char *data, unsigned long len);
+int MDC2_Final(unsigned char *md, MDC2_CTX *c);
+unsigned char *MDC2(const unsigned char *d, unsigned long n,
+ unsigned char *md);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/Mayaqua/win32_inc/openssl/obj_mac.h b/src/Mayaqua/win32_inc/openssl/obj_mac.h
new file mode 100644
index 00000000..b402e896
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/obj_mac.h
@@ -0,0 +1,3914 @@
+/* crypto/objects/obj_mac.h */
+
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num obj_mac.h
+ */
+
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_itu_t "ITU-T"
+#define LN_itu_t "itu-t"
+#define NID_itu_t 645
+#define OBJ_itu_t 0L
+
+#define NID_ccitt 404
+#define OBJ_ccitt OBJ_itu_t
+
+#define SN_iso "ISO"
+#define LN_iso "iso"
+#define NID_iso 181
+#define OBJ_iso 1L
+
+#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t "joint-iso-itu-t"
+#define NID_joint_iso_itu_t 646
+#define OBJ_joint_iso_itu_t 2L
+
+#define NID_joint_iso_ccitt 393
+#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t
+
+#define SN_member_body "member-body"
+#define LN_member_body "ISO Member Body"
+#define NID_member_body 182
+#define OBJ_member_body OBJ_iso,2L
+
+#define SN_identified_organization "identified-organization"
+#define NID_identified_organization 676
+#define OBJ_identified_organization OBJ_iso,3L
+
+#define SN_hmac_md5 "HMAC-MD5"
+#define LN_hmac_md5 "hmac-md5"
+#define NID_hmac_md5 780
+#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
+
+#define SN_hmac_sha1 "HMAC-SHA1"
+#define LN_hmac_sha1 "hmac-sha1"
+#define NID_hmac_sha1 781
+#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
+
+#define SN_certicom_arc "certicom-arc"
+#define NID_certicom_arc 677
+#define OBJ_certicom_arc OBJ_identified_organization,132L
+
+#define SN_international_organizations "international-organizations"
+#define LN_international_organizations "International Organizations"
+#define NID_international_organizations 647
+#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L
+
+#define SN_wap "wap"
+#define NID_wap 678
+#define OBJ_wap OBJ_international_organizations,43L
+
+#define SN_wap_wsg "wap-wsg"
+#define NID_wap_wsg 679
+#define OBJ_wap_wsg OBJ_wap,1L
+
+#define SN_selected_attribute_types "selected-attribute-types"
+#define LN_selected_attribute_types "Selected Attribute Types"
+#define NID_selected_attribute_types 394
+#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L
+
+#define SN_clearance "clearance"
+#define NID_clearance 395
+#define OBJ_clearance OBJ_selected_attribute_types,55L
+
+#define SN_ISO_US "ISO-US"
+#define LN_ISO_US "ISO US Member Body"
+#define NID_ISO_US 183
+#define OBJ_ISO_US OBJ_member_body,840L
+
+#define SN_X9_57 "X9-57"
+#define LN_X9_57 "X9.57"
+#define NID_X9_57 184
+#define OBJ_X9_57 OBJ_ISO_US,10040L
+
+#define SN_X9cm "X9cm"
+#define LN_X9cm "X9.57 CM ?"
+#define NID_X9cm 185
+#define OBJ_X9cm OBJ_X9_57,4L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa OBJ_X9cm,1L
+
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 OBJ_X9cm,3L
+
+#define SN_ansi_X9_62 "ansi-X9-62"
+#define LN_ansi_X9_62 "ANSI X9.62"
+#define NID_ansi_X9_62 405
+#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L
+
+#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L
+
+#define SN_X9_62_prime_field "prime-field"
+#define NID_X9_62_prime_field 406
+#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L
+
+#define SN_X9_62_characteristic_two_field "characteristic-two-field"
+#define NID_X9_62_characteristic_two_field 407
+#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L
+
+#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis 680
+#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L
+
+#define SN_X9_62_onBasis "onBasis"
+#define NID_X9_62_onBasis 681
+#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L
+
+#define SN_X9_62_tpBasis "tpBasis"
+#define NID_X9_62_tpBasis 682
+#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L
+
+#define SN_X9_62_ppBasis "ppBasis"
+#define NID_X9_62_ppBasis 683
+#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L
+
+#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L
+
+#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey 408
+#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L
+
+#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L
+
+#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L
+
+#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
+#define NID_X9_62_c2pnb163v1 684
+#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L
+
+#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
+#define NID_X9_62_c2pnb163v2 685
+#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L
+
+#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
+#define NID_X9_62_c2pnb163v3 686
+#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L
+
+#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
+#define NID_X9_62_c2pnb176v1 687
+#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L
+
+#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
+#define NID_X9_62_c2tnb191v1 688
+#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L
+
+#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
+#define NID_X9_62_c2tnb191v2 689
+#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L
+
+#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
+#define NID_X9_62_c2tnb191v3 690
+#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L
+
+#define SN_X9_62_c2onb191v4 "c2onb191v4"
+#define NID_X9_62_c2onb191v4 691
+#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L
+
+#define SN_X9_62_c2onb191v5 "c2onb191v5"
+#define NID_X9_62_c2onb191v5 692
+#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L
+
+#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
+#define NID_X9_62_c2pnb208w1 693
+#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L
+
+#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
+#define NID_X9_62_c2tnb239v1 694
+#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L
+
+#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
+#define NID_X9_62_c2tnb239v2 695
+#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L
+
+#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
+#define NID_X9_62_c2tnb239v3 696
+#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L
+
+#define SN_X9_62_c2onb239v4 "c2onb239v4"
+#define NID_X9_62_c2onb239v4 697
+#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L
+
+#define SN_X9_62_c2onb239v5 "c2onb239v5"
+#define NID_X9_62_c2onb239v5 698
+#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L
+
+#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
+#define NID_X9_62_c2pnb272w1 699
+#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L
+
+#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
+#define NID_X9_62_c2pnb304w1 700
+#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L
+
+#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
+#define NID_X9_62_c2tnb359v1 701
+#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L
+
+#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
+#define NID_X9_62_c2pnb368w1 702
+#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L
+
+#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
+#define NID_X9_62_c2tnb431r1 703
+#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L
+
+#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L
+
+#define SN_X9_62_prime192v1 "prime192v1"
+#define NID_X9_62_prime192v1 409
+#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L
+
+#define SN_X9_62_prime192v2 "prime192v2"
+#define NID_X9_62_prime192v2 410
+#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L
+
+#define SN_X9_62_prime192v3 "prime192v3"
+#define NID_X9_62_prime192v3 411
+#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L
+
+#define SN_X9_62_prime239v1 "prime239v1"
+#define NID_X9_62_prime239v1 412
+#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L
+
+#define SN_X9_62_prime239v2 "prime239v2"
+#define NID_X9_62_prime239v2 413
+#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L
+
+#define SN_X9_62_prime239v3 "prime239v3"
+#define NID_X9_62_prime239v3 414
+#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L
+
+#define SN_X9_62_prime256v1 "prime256v1"
+#define NID_X9_62_prime256v1 415
+#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L
+
+#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L
+
+#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1 416
+#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L
+
+#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
+#define NID_ecdsa_with_Recommended 791
+#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L
+
+#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
+#define NID_ecdsa_with_Specified 792
+#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L
+
+#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
+#define NID_ecdsa_with_SHA224 793
+#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L
+
+#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
+#define NID_ecdsa_with_SHA256 794
+#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L
+
+#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
+#define NID_ecdsa_with_SHA384 795
+#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L
+
+#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
+#define NID_ecdsa_with_SHA512 796
+#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L
+
+#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L
+
+#define SN_secp112r1 "secp112r1"
+#define NID_secp112r1 704
+#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
+
+#define SN_secp112r2 "secp112r2"
+#define NID_secp112r2 705
+#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
+
+#define SN_secp128r1 "secp128r1"
+#define NID_secp128r1 706
+#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
+
+#define SN_secp128r2 "secp128r2"
+#define NID_secp128r2 707
+#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
+
+#define SN_secp160k1 "secp160k1"
+#define NID_secp160k1 708
+#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
+
+#define SN_secp160r1 "secp160r1"
+#define NID_secp160r1 709
+#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
+
+#define SN_secp160r2 "secp160r2"
+#define NID_secp160r2 710
+#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
+
+#define SN_secp192k1 "secp192k1"
+#define NID_secp192k1 711
+#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
+
+#define SN_secp224k1 "secp224k1"
+#define NID_secp224k1 712
+#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
+
+#define SN_secp224r1 "secp224r1"
+#define NID_secp224r1 713
+#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
+
+#define SN_secp256k1 "secp256k1"
+#define NID_secp256k1 714
+#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
+
+#define SN_secp384r1 "secp384r1"
+#define NID_secp384r1 715
+#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
+
+#define SN_secp521r1 "secp521r1"
+#define NID_secp521r1 716
+#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
+
+#define SN_sect113r1 "sect113r1"
+#define NID_sect113r1 717
+#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
+
+#define SN_sect113r2 "sect113r2"
+#define NID_sect113r2 718
+#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
+
+#define SN_sect131r1 "sect131r1"
+#define NID_sect131r1 719
+#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
+
+#define SN_sect131r2 "sect131r2"
+#define NID_sect131r2 720
+#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
+
+#define SN_sect163k1 "sect163k1"
+#define NID_sect163k1 721
+#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
+
+#define SN_sect163r1 "sect163r1"
+#define NID_sect163r1 722
+#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
+
+#define SN_sect163r2 "sect163r2"
+#define NID_sect163r2 723
+#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
+
+#define SN_sect193r1 "sect193r1"
+#define NID_sect193r1 724
+#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
+
+#define SN_sect193r2 "sect193r2"
+#define NID_sect193r2 725
+#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
+
+#define SN_sect233k1 "sect233k1"
+#define NID_sect233k1 726
+#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
+
+#define SN_sect233r1 "sect233r1"
+#define NID_sect233r1 727
+#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
+
+#define SN_sect239k1 "sect239k1"
+#define NID_sect239k1 728
+#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
+
+#define SN_sect283k1 "sect283k1"
+#define NID_sect283k1 729
+#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
+
+#define SN_sect283r1 "sect283r1"
+#define NID_sect283r1 730
+#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
+
+#define SN_sect409k1 "sect409k1"
+#define NID_sect409k1 731
+#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
+
+#define SN_sect409r1 "sect409r1"
+#define NID_sect409r1 732
+#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
+
+#define SN_sect571k1 "sect571k1"
+#define NID_sect571k1 733
+#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
+
+#define SN_sect571r1 "sect571r1"
+#define NID_sect571r1 734
+#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
+
+#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L
+
+#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1 735
+#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L
+
+#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3 736
+#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L
+
+#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4 737
+#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L
+
+#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5 738
+#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L
+
+#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6 739
+#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L
+
+#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7 740
+#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L
+
+#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8 741
+#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L
+
+#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9 742
+#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L
+
+#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10 743
+#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L
+
+#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11 744
+#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L
+
+#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12 745
+#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L
+
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L
+
+#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC "password based MAC"
+#define NID_id_PasswordBasedMAC 782
+#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L
+
+#define SN_id_DHBasedMac "id-DHBasedMac"
+#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac 783
+#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L
+
+#define SN_rsadsi "rsadsi"
+#define LN_rsadsi "RSA Data Security, Inc."
+#define NID_rsadsi 1
+#define OBJ_rsadsi OBJ_ISO_US,113549L
+
+#define SN_pkcs "pkcs"
+#define LN_pkcs "RSA Data Security, Inc. PKCS"
+#define NID_pkcs 2
+#define OBJ_pkcs OBJ_rsadsi,1L
+
+#define SN_pkcs1 "pkcs1"
+#define NID_pkcs1 186
+#define OBJ_pkcs1 OBJ_pkcs,1L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption OBJ_pkcs1,1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L
+
+#define SN_md4WithRSAEncryption "RSA-MD4"
+#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption 396
+#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L
+
+#define SN_sha256WithRSAEncryption "RSA-SHA256"
+#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption 668
+#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L
+
+#define SN_sha384WithRSAEncryption "RSA-SHA384"
+#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption 669
+#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L
+
+#define SN_sha512WithRSAEncryption "RSA-SHA512"
+#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption 670
+#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L
+
+#define SN_sha224WithRSAEncryption "RSA-SHA224"
+#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption 671
+#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L
+
+#define SN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
+
+#define SN_pkcs5 "pkcs5"
+#define NID_pkcs5 187
+#define OBJ_pkcs5 OBJ_pkcs,5L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L
+
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L
+
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 OBJ_pkcs5,12L
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 OBJ_pkcs5,13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 OBJ_pkcs5,14L
+
+#define SN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 OBJ_pkcs,7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
+
+#define SN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 OBJ_pkcs,9L
+
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
+
+#define SN_ext_req "extReq"
+#define LN_ext_req "Extension Request"
+#define NID_ext_req 172
+#define OBJ_ext_req OBJ_pkcs9,14L
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
+
+#define SN_SMIME "SMIME"
+#define LN_SMIME "S/MIME"
+#define NID_SMIME 188
+#define OBJ_SMIME OBJ_pkcs9,16L
+
+#define SN_id_smime_mod "id-smime-mod"
+#define NID_id_smime_mod 189
+#define OBJ_id_smime_mod OBJ_SMIME,0L
+
+#define SN_id_smime_ct "id-smime-ct"
+#define NID_id_smime_ct 190
+#define OBJ_id_smime_ct OBJ_SMIME,1L
+
+#define SN_id_smime_aa "id-smime-aa"
+#define NID_id_smime_aa 191
+#define OBJ_id_smime_aa OBJ_SMIME,2L
+
+#define SN_id_smime_alg "id-smime-alg"
+#define NID_id_smime_alg 192
+#define OBJ_id_smime_alg OBJ_SMIME,3L
+
+#define SN_id_smime_cd "id-smime-cd"
+#define NID_id_smime_cd 193
+#define OBJ_id_smime_cd OBJ_SMIME,4L
+
+#define SN_id_smime_spq "id-smime-spq"
+#define NID_id_smime_spq 194
+#define OBJ_id_smime_spq OBJ_SMIME,5L
+
+#define SN_id_smime_cti "id-smime-cti"
+#define NID_id_smime_cti 195
+#define OBJ_id_smime_cti OBJ_SMIME,6L
+
+#define SN_id_smime_mod_cms "id-smime-mod-cms"
+#define NID_id_smime_mod_cms 196
+#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
+
+#define SN_id_smime_mod_ess "id-smime-mod-ess"
+#define NID_id_smime_mod_ess 197
+#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L
+
+#define SN_id_smime_mod_oid "id-smime-mod-oid"
+#define NID_id_smime_mod_oid 198
+#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L
+
+#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3 199
+#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L
+
+#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88 200
+#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L
+
+#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97 201
+#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88 202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97 203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L
+
+#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt 204
+#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L
+
+#define SN_id_smime_ct_authData "id-smime-ct-authData"
+#define NID_id_smime_ct_authData 205
+#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L
+
+#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert 206
+#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L
+
+#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo 207
+#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L
+
+#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo 208
+#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L
+
+#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo 209
+#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L
+
+#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData 210
+#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L
+
+#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData 211
+#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L
+
+#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
+#define NID_id_smime_ct_compressedData 786
+#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L
+
+#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF 787
+#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
+
+#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest 212
+#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
+
+#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel 213
+#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L
+
+#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory 214
+#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L
+
+#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint 215
+#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L
+
+#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest 216
+#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L
+
+#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType 217
+#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L
+
+#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier 218
+#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L
+
+#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue 219
+#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L
+
+#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels 220
+#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L
+
+#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference 221
+#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L
+
+#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref 222
+#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L
+
+#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate 223
+#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L
+
+#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts 224
+#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L
+
+#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken 225
+#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L
+
+#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId 226
+#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L
+
+#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType 227
+#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L
+
+#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation 228
+#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L
+
+#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr 229
+#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L
+
+#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert 230
+#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L
+
+#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp 231
+#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L
+
+#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs 232
+#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L
+
+#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs 233
+#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L
+
+#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues 234
+#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L
+
+#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues 235
+#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L
+
+#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp 236
+#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp 237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp 238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L
+
+#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType 239
+#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L
+
+#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc 240
+#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L
+
+#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES 241
+#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L
+
+#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2 242
+#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L
+
+#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap 243
+#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L
+
+#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap 244
+#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L
+
+#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH 245
+#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L
+
+#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap 246
+#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L
+
+#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap 247
+#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L
+
+#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap 248
+#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
+
+#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri 249
+#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L
+
+#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice 250
+#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin 251
+#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt 252
+#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery 253
+#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L
+
+#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender 254
+#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L
+
+#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval 255
+#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L
+
+#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation 256
+#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName OBJ_pkcs9,20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID OBJ_pkcs9,21L
+
+#define SN_ms_csp_name "CSPName"
+#define LN_ms_csp_name "Microsoft CSP Name"
+#define NID_ms_csp_name 417
+#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L
+
+#define SN_LocalKeySet "LocalKeySet"
+#define LN_LocalKeySet "Microsoft Local Key set"
+#define NID_LocalKeySet 856
+#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L
+
+#define OBJ_certTypes OBJ_pkcs9,22L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate OBJ_certTypes,1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate OBJ_certTypes,2L
+
+#define OBJ_crlTypes OBJ_pkcs9,23L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl OBJ_crlTypes,1L
+
+#define OBJ_pkcs12 OBJ_pkcs,12L
+
+#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L
+
+#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L
+
+#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag OBJ_pkcs12_BagIds,1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag OBJ_pkcs12_BagIds,3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag OBJ_pkcs12_BagIds,4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag OBJ_pkcs12_BagIds,5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 OBJ_rsadsi,2L,2L
+
+#define SN_md4 "MD4"
+#define LN_md4 "md4"
+#define NID_md4 257
+#define OBJ_md4 OBJ_rsadsi,2L,4L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 OBJ_rsadsi,2L,5L
+
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+#define NID_md5_sha1 114
+
+#define LN_hmacWithMD5 "hmacWithMD5"
+#define NID_hmacWithMD5 797
+#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+
+#define LN_hmacWithSHA224 "hmacWithSHA224"
+#define NID_hmacWithSHA224 798
+#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
+
+#define LN_hmacWithSHA256 "hmacWithSHA256"
+#define NID_hmacWithSHA256 799
+#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L
+
+#define LN_hmacWithSHA384 "hmacWithSHA384"
+#define NID_hmacWithSHA384 800
+#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L
+
+#define LN_hmacWithSHA512 "hmacWithSHA512"
+#define NID_hmacWithSHA512 801
+#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 OBJ_rsadsi,3L,4L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
+
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_ms_ext_req "msExtReq"
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+#define SN_ms_smartcard_login "msSmartcardLogin"
+#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login 648
+#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
+
+#define SN_ms_upn "msUPN"
+#define LN_ms_upn "Microsoft Universal Principal Name"
+#define NID_ms_upn 649
+#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_pkix_mod "id-pkix-mod"
+#define NID_id_pkix_mod 258
+#define OBJ_id_pkix_mod OBJ_id_pkix,0L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe OBJ_id_pkix,1L
+
+#define SN_id_qt "id-qt"
+#define NID_id_qt 259
+#define OBJ_id_qt OBJ_id_pkix,2L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp OBJ_id_pkix,3L
+
+#define SN_id_it "id-it"
+#define NID_id_it 260
+#define OBJ_id_it OBJ_id_pkix,4L
+
+#define SN_id_pkip "id-pkip"
+#define NID_id_pkip 261
+#define OBJ_id_pkip OBJ_id_pkix,5L
+
+#define SN_id_alg "id-alg"
+#define NID_id_alg 262
+#define OBJ_id_alg OBJ_id_pkix,6L
+
+#define SN_id_cmc "id-cmc"
+#define NID_id_cmc 263
+#define OBJ_id_cmc OBJ_id_pkix,7L
+
+#define SN_id_on "id-on"
+#define NID_id_on 264
+#define OBJ_id_on OBJ_id_pkix,8L
+
+#define SN_id_pda "id-pda"
+#define NID_id_pda 265
+#define OBJ_id_pda OBJ_id_pkix,9L
+
+#define SN_id_aca "id-aca"
+#define NID_id_aca 266
+#define OBJ_id_aca OBJ_id_pkix,10L
+
+#define SN_id_qcs "id-qcs"
+#define NID_id_qcs 267
+#define OBJ_id_qcs OBJ_id_pkix,11L
+
+#define SN_id_cct "id-cct"
+#define NID_id_cct 268
+#define OBJ_id_cct OBJ_id_pkix,12L
+
+#define SN_id_ppl "id-ppl"
+#define NID_id_ppl 662
+#define OBJ_id_ppl OBJ_id_pkix,21L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad OBJ_id_pkix,48L
+
+#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88 269
+#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L
+
+#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88 270
+#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L
+
+#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93 271
+#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L
+
+#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93 272
+#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L
+
+#define SN_id_mod_crmf "id-mod-crmf"
+#define NID_id_mod_crmf 273
+#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L
+
+#define SN_id_mod_cmc "id-mod-cmc"
+#define NID_id_mod_cmc 274
+#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L
+
+#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88 275
+#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L
+
+#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93 276
+#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L
+
+#define SN_id_mod_cmp "id-mod-cmp"
+#define NID_id_mod_cmp 277
+#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L
+
+#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88 278
+#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L
+
+#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93 279
+#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L
+
+#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert 280
+#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L
+
+#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol 281
+#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L
+
+#define SN_id_mod_ocsp "id-mod-ocsp"
+#define NID_id_mod_ocsp 282
+#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L
+
+#define SN_id_mod_dvcs "id-mod-dvcs"
+#define NID_id_mod_dvcs 283
+#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L
+
+#define SN_id_mod_cmp2000 "id-mod-cmp2000"
+#define NID_id_mod_cmp2000 284
+#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access OBJ_id_pe,1L
+
+#define SN_biometricInfo "biometricInfo"
+#define LN_biometricInfo "Biometric Info"
+#define NID_biometricInfo 285
+#define OBJ_biometricInfo OBJ_id_pe,2L
+
+#define SN_qcStatements "qcStatements"
+#define NID_qcStatements 286
+#define OBJ_qcStatements OBJ_id_pe,3L
+
+#define SN_ac_auditEntity "ac-auditEntity"
+#define NID_ac_auditEntity 287
+#define OBJ_ac_auditEntity OBJ_id_pe,4L
+
+#define SN_ac_targeting "ac-targeting"
+#define NID_ac_targeting 288
+#define OBJ_ac_targeting OBJ_id_pe,5L
+
+#define SN_aaControls "aaControls"
+#define NID_aaControls 289
+#define OBJ_aaControls OBJ_id_pe,6L
+
+#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock 290
+#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L
+
+#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum 291
+#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L
+
+#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier 292
+#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L
+
+#define SN_ac_proxying "ac-proxying"
+#define NID_ac_proxying 397
+#define OBJ_ac_proxying OBJ_id_pe,10L
+
+#define SN_sinfo_access "subjectInfoAccess"
+#define LN_sinfo_access "Subject Information Access"
+#define NID_sinfo_access 398
+#define OBJ_sinfo_access OBJ_id_pe,11L
+
+#define SN_proxyCertInfo "proxyCertInfo"
+#define LN_proxyCertInfo "Proxy Certificate Information"
+#define NID_proxyCertInfo 663
+#define OBJ_proxyCertInfo OBJ_id_pe,14L
+
+#define SN_id_qt_cps "id-qt-cps"
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps OBJ_id_qt,1L
+
+#define SN_id_qt_unotice "id-qt-unotice"
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice OBJ_id_qt,2L
+
+#define SN_textNotice "textNotice"
+#define NID_textNotice 293
+#define OBJ_textNotice OBJ_id_qt,3L
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth OBJ_id_kp,1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth OBJ_id_kp,2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign OBJ_id_kp,3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect OBJ_id_kp,4L
+
+#define SN_ipsecEndSystem "ipsecEndSystem"
+#define LN_ipsecEndSystem "IPSec End System"
+#define NID_ipsecEndSystem 294
+#define OBJ_ipsecEndSystem OBJ_id_kp,5L
+
+#define SN_ipsecTunnel "ipsecTunnel"
+#define LN_ipsecTunnel "IPSec Tunnel"
+#define NID_ipsecTunnel 295
+#define OBJ_ipsecTunnel OBJ_id_kp,6L
+
+#define SN_ipsecUser "ipsecUser"
+#define LN_ipsecUser "IPSec User"
+#define NID_ipsecUser 296
+#define OBJ_ipsecUser OBJ_id_kp,7L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp OBJ_id_kp,8L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign OBJ_id_kp,9L
+
+#define SN_dvcs "DVCS"
+#define LN_dvcs "dvcs"
+#define NID_dvcs 297
+#define OBJ_dvcs OBJ_id_kp,10L
+
+#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert 298
+#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
+
+#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes 299
+#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L
+
+#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes 300
+#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L
+
+#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg 301
+#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L
+
+#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo 302
+#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L
+
+#define SN_id_it_currentCRL "id-it-currentCRL"
+#define NID_id_it_currentCRL 303
+#define OBJ_id_it_currentCRL OBJ_id_it,6L
+
+#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs 304
+#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L
+
+#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest 305
+#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L
+
+#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse 306
+#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L
+
+#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq 307
+#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L
+
+#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep 308
+#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L
+
+#define SN_id_it_revPassphrase "id-it-revPassphrase"
+#define NID_id_it_revPassphrase 309
+#define OBJ_id_it_revPassphrase OBJ_id_it,12L
+
+#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm 310
+#define OBJ_id_it_implicitConfirm OBJ_id_it,13L
+
+#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime 311
+#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L
+
+#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage 312
+#define OBJ_id_it_origPKIMessage OBJ_id_it,15L
+
+#define SN_id_it_suppLangTags "id-it-suppLangTags"
+#define NID_id_it_suppLangTags 784
+#define OBJ_id_it_suppLangTags OBJ_id_it,16L
+
+#define SN_id_regCtrl "id-regCtrl"
+#define NID_id_regCtrl 313
+#define OBJ_id_regCtrl OBJ_id_pkip,1L
+
+#define SN_id_regInfo "id-regInfo"
+#define NID_id_regInfo 314
+#define OBJ_id_regInfo OBJ_id_pkip,2L
+
+#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken 315
+#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L
+
+#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator 316
+#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L
+
+#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo 317
+#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L
+
+#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions 318
+#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L
+
+#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID 319
+#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L
+
+#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey 320
+#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L
+
+#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs 321
+#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L
+
+#define SN_id_regInfo_certReq "id-regInfo-certReq"
+#define NID_id_regInfo_certReq 322
+#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L
+
+#define SN_id_alg_des40 "id-alg-des40"
+#define NID_id_alg_des40 323
+#define OBJ_id_alg_des40 OBJ_id_alg,1L
+
+#define SN_id_alg_noSignature "id-alg-noSignature"
+#define NID_id_alg_noSignature 324
+#define OBJ_id_alg_noSignature OBJ_id_alg,2L
+
+#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1 325
+#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L
+
+#define SN_id_alg_dh_pop "id-alg-dh-pop"
+#define NID_id_alg_dh_pop 326
+#define OBJ_id_alg_dh_pop OBJ_id_alg,4L
+
+#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo 327
+#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L
+
+#define SN_id_cmc_identification "id-cmc-identification"
+#define NID_id_cmc_identification 328
+#define OBJ_id_cmc_identification OBJ_id_cmc,2L
+
+#define SN_id_cmc_identityProof "id-cmc-identityProof"
+#define NID_id_cmc_identityProof 329
+#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L
+
+#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn 330
+#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L
+
+#define SN_id_cmc_transactionId "id-cmc-transactionId"
+#define NID_id_cmc_transactionId 331
+#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L
+
+#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce 332
+#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L
+
+#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce 333
+#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L
+
+#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions 334
+#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L
+
+#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP 335
+#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L
+
+#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP 336
+#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L
+
+#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness 337
+#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L
+
+#define SN_id_cmc_getCert "id-cmc-getCert"
+#define NID_id_cmc_getCert 338
+#define OBJ_id_cmc_getCert OBJ_id_cmc,15L
+
+#define SN_id_cmc_getCRL "id-cmc-getCRL"
+#define NID_id_cmc_getCRL 339
+#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L
+
+#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest 340
+#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L
+
+#define SN_id_cmc_regInfo "id-cmc-regInfo"
+#define NID_id_cmc_regInfo 341
+#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L
+
+#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo 342
+#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L
+
+#define SN_id_cmc_queryPending "id-cmc-queryPending"
+#define NID_id_cmc_queryPending 343
+#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L
+
+#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom 344
+#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L
+
+#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness 345
+#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L
+
+#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance 346
+#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L
+
+#define SN_id_on_personalData "id-on-personalData"
+#define NID_id_on_personalData 347
+#define OBJ_id_on_personalData OBJ_id_on,1L
+
+#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
+#define LN_id_on_permanentIdentifier "Permanent Identifier"
+#define NID_id_on_permanentIdentifier 858
+#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
+
+#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth 348
+#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
+
+#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth 349
+#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L
+
+#define SN_id_pda_gender "id-pda-gender"
+#define NID_id_pda_gender 351
+#define OBJ_id_pda_gender OBJ_id_pda,3L
+
+#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship 352
+#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L
+
+#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence 353
+#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L
+
+#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo 354
+#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L
+
+#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity 355
+#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L
+
+#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity 356
+#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L
+
+#define SN_id_aca_group "id-aca-group"
+#define NID_id_aca_group 357
+#define OBJ_id_aca_group OBJ_id_aca,4L
+
+#define SN_id_aca_role "id-aca-role"
+#define NID_id_aca_role 358
+#define OBJ_id_aca_role OBJ_id_aca,5L
+
+#define SN_id_aca_encAttrs "id-aca-encAttrs"
+#define NID_id_aca_encAttrs 399
+#define OBJ_id_aca_encAttrs OBJ_id_aca,6L
+
+#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1 359
+#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
+
+#define SN_id_cct_crs "id-cct-crs"
+#define NID_id_cct_crs 360
+#define OBJ_id_cct_crs OBJ_id_cct,1L
+
+#define SN_id_cct_PKIData "id-cct-PKIData"
+#define NID_id_cct_PKIData 361
+#define OBJ_id_cct_PKIData OBJ_id_cct,2L
+
+#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse 362
+#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L
+
+#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage "Any language"
+#define NID_id_ppl_anyLanguage 664
+#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L
+
+#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll "Inherit all"
+#define NID_id_ppl_inheritAll 665
+#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L
+
+#define SN_Independent "id-ppl-independent"
+#define LN_Independent "Independent"
+#define NID_Independent 667
+#define OBJ_Independent OBJ_id_ppl,2L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers OBJ_id_ad,2L
+
+#define SN_ad_timeStamping "ad_timestamping"
+#define LN_ad_timeStamping "AD Time Stamping"
+#define NID_ad_timeStamping 363
+#define OBJ_ad_timeStamping OBJ_id_ad,3L
+
+#define SN_ad_dvcs "AD_DVCS"
+#define LN_ad_dvcs "ad dvcs"
+#define NID_ad_dvcs 364
+#define OBJ_ad_dvcs OBJ_id_ad,4L
+
+#define SN_caRepository "caRepository"
+#define LN_caRepository "CA Repository"
+#define NID_caRepository 785
+#define OBJ_caRepository OBJ_id_ad,5L
+
+#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
+
+#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic 365
+#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L
+
+#define SN_id_pkix_OCSP_Nonce "Nonce"
+#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce 366
+#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L
+
+#define SN_id_pkix_OCSP_CrlID "CrlID"
+#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID 367
+#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L
+
+#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses 368
+#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L
+
+#define SN_id_pkix_OCSP_noCheck "noCheck"
+#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck 369
+#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L
+
+#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff 370
+#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L
+
+#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator 371
+#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L
+
+#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus 372
+#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L
+
+#define SN_id_pkix_OCSP_valid "valid"
+#define NID_id_pkix_OCSP_valid 373
+#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L
+
+#define SN_id_pkix_OCSP_path "path"
+#define NID_id_pkix_OCSP_path 374
+#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L
+
+#define SN_id_pkix_OCSP_trustRoot "trustRoot"
+#define LN_id_pkix_OCSP_trustRoot "Trust Root"
+#define NID_id_pkix_OCSP_trustRoot 375
+#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L
+
+#define SN_algorithm "algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 376
+#define OBJ_algorithm 1L,3L,14L,3L,2L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA OBJ_algorithm,3L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb OBJ_algorithm,6L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+#define OBJ_des_cbc OBJ_algorithm,7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 OBJ_algorithm,8L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+#define OBJ_des_cfb64 OBJ_algorithm,9L
+
+#define SN_rsaSignature "rsaSignature"
+#define NID_rsaSignature 377
+#define OBJ_rsaSignature OBJ_algorithm,11L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 OBJ_algorithm,12L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA OBJ_algorithm,13L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
+
+#define SN_des_ede_ecb "DES-EDE"
+#define LN_des_ede_ecb "des-ede"
+#define NID_des_ede_ecb 32
+#define OBJ_des_ede_ecb OBJ_algorithm,17L
+
+#define SN_des_ede3_ecb "DES-EDE3"
+#define LN_des_ede3_ecb "des-ede3"
+#define NID_des_ede3_ecb 33
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha OBJ_algorithm,18L
+
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 OBJ_algorithm,26L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA OBJ_algorithm,29L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
+
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
+
+#define SN_X500 "X500"
+#define LN_X500 "directory services (X.500)"
+#define NID_X500 11
+#define OBJ_X500 2L,5L
+
+#define SN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 OBJ_X500,4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName OBJ_X509,3L
+
+#define SN_surname "SN"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname OBJ_X509,4L
+
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber OBJ_X509,5L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName OBJ_X509,6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName OBJ_X509,7L
+
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName OBJ_X509,8L
+
+#define SN_streetAddress "street"
+#define LN_streetAddress "streetAddress"
+#define NID_streetAddress 660
+#define OBJ_streetAddress OBJ_X509,9L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName OBJ_X509,10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName OBJ_X509,11L
+
+#define SN_title "title"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title OBJ_X509,12L
+
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description OBJ_X509,13L
+
+#define LN_searchGuide "searchGuide"
+#define NID_searchGuide 859
+#define OBJ_searchGuide OBJ_X509,14L
+
+#define LN_businessCategory "businessCategory"
+#define NID_businessCategory 860
+#define OBJ_businessCategory OBJ_X509,15L
+
+#define LN_postalAddress "postalAddress"
+#define NID_postalAddress 861
+#define OBJ_postalAddress OBJ_X509,16L
+
+#define LN_postalCode "postalCode"
+#define NID_postalCode 661
+#define OBJ_postalCode OBJ_X509,17L
+
+#define LN_postOfficeBox "postOfficeBox"
+#define NID_postOfficeBox 862
+#define OBJ_postOfficeBox OBJ_X509,18L
+
+#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
+#define NID_physicalDeliveryOfficeName 863
+#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L
+
+#define LN_telephoneNumber "telephoneNumber"
+#define NID_telephoneNumber 864
+#define OBJ_telephoneNumber OBJ_X509,20L
+
+#define LN_telexNumber "telexNumber"
+#define NID_telexNumber 865
+#define OBJ_telexNumber OBJ_X509,21L
+
+#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
+#define NID_teletexTerminalIdentifier 866
+#define OBJ_teletexTerminalIdentifier OBJ_X509,22L
+
+#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
+#define NID_facsimileTelephoneNumber 867
+#define OBJ_facsimileTelephoneNumber OBJ_X509,23L
+
+#define LN_x121Address "x121Address"
+#define NID_x121Address 868
+#define OBJ_x121Address OBJ_X509,24L
+
+#define LN_internationaliSDNNumber "internationaliSDNNumber"
+#define NID_internationaliSDNNumber 869
+#define OBJ_internationaliSDNNumber OBJ_X509,25L
+
+#define LN_registeredAddress "registeredAddress"
+#define NID_registeredAddress 870
+#define OBJ_registeredAddress OBJ_X509,26L
+
+#define LN_destinationIndicator "destinationIndicator"
+#define NID_destinationIndicator 871
+#define OBJ_destinationIndicator OBJ_X509,27L
+
+#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
+#define NID_preferredDeliveryMethod 872
+#define OBJ_preferredDeliveryMethod OBJ_X509,28L
+
+#define LN_presentationAddress "presentationAddress"
+#define NID_presentationAddress 873
+#define OBJ_presentationAddress OBJ_X509,29L
+
+#define LN_supportedApplicationContext "supportedApplicationContext"
+#define NID_supportedApplicationContext 874
+#define OBJ_supportedApplicationContext OBJ_X509,30L
+
+#define SN_member "member"
+#define NID_member 875
+#define OBJ_member OBJ_X509,31L
+
+#define SN_owner "owner"
+#define NID_owner 876
+#define OBJ_owner OBJ_X509,32L
+
+#define LN_roleOccupant "roleOccupant"
+#define NID_roleOccupant 877
+#define OBJ_roleOccupant OBJ_X509,33L
+
+#define SN_seeAlso "seeAlso"
+#define NID_seeAlso 878
+#define OBJ_seeAlso OBJ_X509,34L
+
+#define LN_userPassword "userPassword"
+#define NID_userPassword 879
+#define OBJ_userPassword OBJ_X509,35L
+
+#define LN_userCertificate "userCertificate"
+#define NID_userCertificate 880
+#define OBJ_userCertificate OBJ_X509,36L
+
+#define LN_cACertificate "cACertificate"
+#define NID_cACertificate 881
+#define OBJ_cACertificate OBJ_X509,37L
+
+#define LN_authorityRevocationList "authorityRevocationList"
+#define NID_authorityRevocationList 882
+#define OBJ_authorityRevocationList OBJ_X509,38L
+
+#define LN_certificateRevocationList "certificateRevocationList"
+#define NID_certificateRevocationList 883
+#define OBJ_certificateRevocationList OBJ_X509,39L
+
+#define LN_crossCertificatePair "crossCertificatePair"
+#define NID_crossCertificatePair 884
+#define OBJ_crossCertificatePair OBJ_X509,40L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name OBJ_X509,41L
+
+#define SN_givenName "GN"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName OBJ_X509,42L
+
+#define SN_initials "initials"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials OBJ_X509,43L
+
+#define LN_generationQualifier "generationQualifier"
+#define NID_generationQualifier 509
+#define OBJ_generationQualifier OBJ_X509,44L
+
+#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier 503
+#define OBJ_x500UniqueIdentifier OBJ_X509,45L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier OBJ_X509,46L
+
+#define LN_enhancedSearchGuide "enhancedSearchGuide"
+#define NID_enhancedSearchGuide 885
+#define OBJ_enhancedSearchGuide OBJ_X509,47L
+
+#define LN_protocolInformation "protocolInformation"
+#define NID_protocolInformation 886
+#define OBJ_protocolInformation OBJ_X509,48L
+
+#define LN_distinguishedName "distinguishedName"
+#define NID_distinguishedName 887
+#define OBJ_distinguishedName OBJ_X509,49L
+
+#define LN_uniqueMember "uniqueMember"
+#define NID_uniqueMember 888
+#define OBJ_uniqueMember OBJ_X509,50L
+
+#define LN_houseIdentifier "houseIdentifier"
+#define NID_houseIdentifier 889
+#define OBJ_houseIdentifier OBJ_X509,51L
+
+#define LN_supportedAlgorithms "supportedAlgorithms"
+#define NID_supportedAlgorithms 890
+#define OBJ_supportedAlgorithms OBJ_X509,52L
+
+#define LN_deltaRevocationList "deltaRevocationList"
+#define NID_deltaRevocationList 891
+#define OBJ_deltaRevocationList OBJ_X509,53L
+
+#define SN_dmdName "dmdName"
+#define NID_dmdName 892
+#define OBJ_dmdName OBJ_X509,54L
+
+#define LN_pseudonym "pseudonym"
+#define NID_pseudonym 510
+#define OBJ_pseudonym OBJ_X509,65L
+
+#define SN_role "role"
+#define LN_role "role"
+#define NID_role 400
+#define OBJ_role OBJ_X509,72L
+
+#define SN_X500algorithms "X500algorithms"
+#define LN_X500algorithms "directory services - algorithms"
+#define NID_X500algorithms 378
+#define OBJ_X500algorithms OBJ_X500,8L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa OBJ_X500algorithms,1L,1L
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2WithRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 OBJ_X500algorithms,3L,101L
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce OBJ_X500,29L
+
+#define SN_subject_directory_attributes "subjectDirectoryAttributes"
+#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes 769
+#define OBJ_subject_directory_attributes OBJ_id_ce,9L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier OBJ_id_ce,14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage OBJ_id_ce,15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period OBJ_id_ce,16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name OBJ_id_ce,17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name OBJ_id_ce,18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints OBJ_id_ce,19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number OBJ_id_ce,20L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "X509v3 CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason OBJ_id_ce,21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date OBJ_id_ce,24L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl OBJ_id_ce,27L
+
+#define SN_issuing_distribution_point "issuingDistributionPoint"
+#define LN_issuing_distribution_point "X509v3 Issuing Distrubution Point"
+#define NID_issuing_distribution_point 770
+#define OBJ_issuing_distribution_point OBJ_id_ce,28L
+
+#define SN_certificate_issuer "certificateIssuer"
+#define LN_certificate_issuer "X509v3 Certificate Issuer"
+#define NID_certificate_issuer 771
+#define OBJ_certificate_issuer OBJ_id_ce,29L
+
+#define SN_name_constraints "nameConstraints"
+#define LN_name_constraints "X509v3 Name Constraints"
+#define NID_name_constraints 666
+#define OBJ_name_constraints OBJ_id_ce,30L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points OBJ_id_ce,31L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies OBJ_id_ce,32L
+
+#define SN_any_policy "anyPolicy"
+#define LN_any_policy "X509v3 Any Policy"
+#define NID_any_policy 746
+#define OBJ_any_policy OBJ_certificate_policies,0L
+
+#define SN_policy_mappings "policyMappings"
+#define LN_policy_mappings "X509v3 Policy Mappings"
+#define NID_policy_mappings 747
+#define OBJ_policy_mappings OBJ_id_ce,33L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier OBJ_id_ce,35L
+
+#define SN_policy_constraints "policyConstraints"
+#define LN_policy_constraints "X509v3 Policy Constraints"
+#define NID_policy_constraints 401
+#define OBJ_policy_constraints OBJ_id_ce,36L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage OBJ_id_ce,37L
+
+#define SN_freshest_crl "freshestCRL"
+#define LN_freshest_crl "X509v3 Freshest CRL"
+#define NID_freshest_crl 857
+#define OBJ_freshest_crl OBJ_id_ce,46L
+
+#define SN_inhibit_any_policy "inhibitAnyPolicy"
+#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy 748
+#define OBJ_inhibit_any_policy OBJ_id_ce,54L
+
+#define SN_target_information "targetInformation"
+#define LN_target_information "X509v3 AC Targeting"
+#define NID_target_information 402
+#define OBJ_target_information OBJ_id_ce,55L
+
+#define SN_no_rev_avail "noRevAvail"
+#define LN_no_rev_avail "X509v3 No Revocation Available"
+#define NID_no_rev_avail 403
+#define OBJ_no_rev_avail OBJ_id_ce,56L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension OBJ_netscape,1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type OBJ_netscape,2L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc OBJ_netscape,4L,1L
+
+#define SN_org "ORG"
+#define LN_org "org"
+#define NID_org 379
+#define OBJ_org OBJ_iso,3L
+
+#define SN_dod "DOD"
+#define LN_dod "dod"
+#define NID_dod 380
+#define OBJ_dod OBJ_org,6L
+
+#define SN_iana "IANA"
+#define LN_iana "iana"
+#define NID_iana 381
+#define OBJ_iana OBJ_dod,1L
+
+#define OBJ_internet OBJ_iana
+
+#define SN_Directory "directory"
+#define LN_Directory "Directory"
+#define NID_Directory 382
+#define OBJ_Directory OBJ_internet,1L
+
+#define SN_Management "mgmt"
+#define LN_Management "Management"
+#define NID_Management 383
+#define OBJ_Management OBJ_internet,2L
+
+#define SN_Experimental "experimental"
+#define LN_Experimental "Experimental"
+#define NID_Experimental 384
+#define OBJ_Experimental OBJ_internet,3L
+
+#define SN_Private "private"
+#define LN_Private "Private"
+#define NID_Private 385
+#define OBJ_Private OBJ_internet,4L
+
+#define SN_Security "security"
+#define LN_Security "Security"
+#define NID_Security 386
+#define OBJ_Security OBJ_internet,5L
+
+#define SN_SNMPv2 "snmpv2"
+#define LN_SNMPv2 "SNMPv2"
+#define NID_SNMPv2 387
+#define OBJ_SNMPv2 OBJ_internet,6L
+
+#define LN_Mail "Mail"
+#define NID_Mail 388
+#define OBJ_Mail OBJ_internet,7L
+
+#define SN_Enterprises "enterprises"
+#define LN_Enterprises "Enterprises"
+#define NID_Enterprises 389
+#define OBJ_Enterprises OBJ_Private,1L
+
+#define SN_dcObject "dcobject"
+#define LN_dcObject "dcObject"
+#define NID_dcObject 390
+#define OBJ_dcObject OBJ_Enterprises,1466L,344L
+
+#define SN_mime_mhs "mime-mhs"
+#define LN_mime_mhs "MIME MHS"
+#define NID_mime_mhs 504
+#define OBJ_mime_mhs OBJ_Mail,1L
+
+#define SN_mime_mhs_headings "mime-mhs-headings"
+#define LN_mime_mhs_headings "mime-mhs-headings"
+#define NID_mime_mhs_headings 505
+#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L
+
+#define SN_mime_mhs_bodies "mime-mhs-bodies"
+#define LN_mime_mhs_bodies "mime-mhs-bodies"
+#define NID_mime_mhs_bodies 506
+#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L
+
+#define SN_id_hex_partial_message "id-hex-partial-message"
+#define LN_id_hex_partial_message "id-hex-partial-message"
+#define NID_id_hex_partial_message 507
+#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L
+
+#define SN_id_hex_multipart_message "id-hex-multipart-message"
+#define LN_id_hex_multipart_message "id-hex-multipart-message"
+#define NID_id_hex_multipart_message 508
+#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L
+
+#define SN_rle_compression "RLE"
+#define LN_rle_compression "run length compression"
+#define NID_rle_compression 124
+#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression OBJ_id_smime_alg,8L
+
+#define OBJ_csor 2L,16L,840L,1L,101L,3L
+
+#define OBJ_nistAlgorithms OBJ_csor,4L
+
+#define OBJ_aes OBJ_nistAlgorithms,1L
+
+#define SN_aes_128_ecb "AES-128-ECB"
+#define LN_aes_128_ecb "aes-128-ecb"
+#define NID_aes_128_ecb 418
+#define OBJ_aes_128_ecb OBJ_aes,1L
+
+#define SN_aes_128_cbc "AES-128-CBC"
+#define LN_aes_128_cbc "aes-128-cbc"
+#define NID_aes_128_cbc 419
+#define OBJ_aes_128_cbc OBJ_aes,2L
+
+#define SN_aes_128_ofb128 "AES-128-OFB"
+#define LN_aes_128_ofb128 "aes-128-ofb"
+#define NID_aes_128_ofb128 420
+#define OBJ_aes_128_ofb128 OBJ_aes,3L
+
+#define SN_aes_128_cfb128 "AES-128-CFB"
+#define LN_aes_128_cfb128 "aes-128-cfb"
+#define NID_aes_128_cfb128 421
+#define OBJ_aes_128_cfb128 OBJ_aes,4L
+
+#define SN_aes_192_ecb "AES-192-ECB"
+#define LN_aes_192_ecb "aes-192-ecb"
+#define NID_aes_192_ecb 422
+#define OBJ_aes_192_ecb OBJ_aes,21L
+
+#define SN_aes_192_cbc "AES-192-CBC"
+#define LN_aes_192_cbc "aes-192-cbc"
+#define NID_aes_192_cbc 423
+#define OBJ_aes_192_cbc OBJ_aes,22L
+
+#define SN_aes_192_ofb128 "AES-192-OFB"
+#define LN_aes_192_ofb128 "aes-192-ofb"
+#define NID_aes_192_ofb128 424
+#define OBJ_aes_192_ofb128 OBJ_aes,23L
+
+#define SN_aes_192_cfb128 "AES-192-CFB"
+#define LN_aes_192_cfb128 "aes-192-cfb"
+#define NID_aes_192_cfb128 425
+#define OBJ_aes_192_cfb128 OBJ_aes,24L
+
+#define SN_aes_256_ecb "AES-256-ECB"
+#define LN_aes_256_ecb "aes-256-ecb"
+#define NID_aes_256_ecb 426
+#define OBJ_aes_256_ecb OBJ_aes,41L
+
+#define SN_aes_256_cbc "AES-256-CBC"
+#define LN_aes_256_cbc "aes-256-cbc"
+#define NID_aes_256_cbc 427
+#define OBJ_aes_256_cbc OBJ_aes,42L
+
+#define SN_aes_256_ofb128 "AES-256-OFB"
+#define LN_aes_256_ofb128 "aes-256-ofb"
+#define NID_aes_256_ofb128 428
+#define OBJ_aes_256_ofb128 OBJ_aes,43L
+
+#define SN_aes_256_cfb128 "AES-256-CFB"
+#define LN_aes_256_cfb128 "aes-256-cfb"
+#define NID_aes_256_cfb128 429
+#define OBJ_aes_256_cfb128 OBJ_aes,44L
+
+#define SN_aes_128_cfb1 "AES-128-CFB1"
+#define LN_aes_128_cfb1 "aes-128-cfb1"
+#define NID_aes_128_cfb1 650
+
+#define SN_aes_192_cfb1 "AES-192-CFB1"
+#define LN_aes_192_cfb1 "aes-192-cfb1"
+#define NID_aes_192_cfb1 651
+
+#define SN_aes_256_cfb1 "AES-256-CFB1"
+#define LN_aes_256_cfb1 "aes-256-cfb1"
+#define NID_aes_256_cfb1 652
+
+#define SN_aes_128_cfb8 "AES-128-CFB8"
+#define LN_aes_128_cfb8 "aes-128-cfb8"
+#define NID_aes_128_cfb8 653
+
+#define SN_aes_192_cfb8 "AES-192-CFB8"
+#define LN_aes_192_cfb8 "aes-192-cfb8"
+#define NID_aes_192_cfb8 654
+
+#define SN_aes_256_cfb8 "AES-256-CFB8"
+#define LN_aes_256_cfb8 "aes-256-cfb8"
+#define NID_aes_256_cfb8 655
+
+#define SN_des_cfb1 "DES-CFB1"
+#define LN_des_cfb1 "des-cfb1"
+#define NID_des_cfb1 656
+
+#define SN_des_cfb8 "DES-CFB8"
+#define LN_des_cfb8 "des-cfb8"
+#define NID_des_cfb8 657
+
+#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1 "des-ede3-cfb1"
+#define NID_des_ede3_cfb1 658
+
+#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8 "des-ede3-cfb8"
+#define NID_des_ede3_cfb8 659
+
+#define SN_id_aes128_wrap "id-aes128-wrap"
+#define NID_id_aes128_wrap 788
+#define OBJ_id_aes128_wrap OBJ_aes,5L
+
+#define SN_id_aes192_wrap "id-aes192-wrap"
+#define NID_id_aes192_wrap 789
+#define OBJ_id_aes192_wrap OBJ_aes,25L
+
+#define SN_id_aes256_wrap "id-aes256-wrap"
+#define NID_id_aes256_wrap 790
+#define OBJ_id_aes256_wrap OBJ_aes,45L
+
+#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L
+
+#define SN_sha256 "SHA256"
+#define LN_sha256 "sha256"
+#define NID_sha256 672
+#define OBJ_sha256 OBJ_nist_hashalgs,1L
+
+#define SN_sha384 "SHA384"
+#define LN_sha384 "sha384"
+#define NID_sha384 673
+#define OBJ_sha384 OBJ_nist_hashalgs,2L
+
+#define SN_sha512 "SHA512"
+#define LN_sha512 "sha512"
+#define NID_sha512 674
+#define OBJ_sha512 OBJ_nist_hashalgs,3L
+
+#define SN_sha224 "SHA224"
+#define LN_sha224 "sha224"
+#define NID_sha224 675
+#define OBJ_sha224 OBJ_nist_hashalgs,4L
+
+#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
+
+#define SN_dsa_with_SHA224 "dsa_with_SHA224"
+#define NID_dsa_with_SHA224 802
+#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
+
+#define SN_dsa_with_SHA256 "dsa_with_SHA256"
+#define NID_dsa_with_SHA256 803
+#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
+
+#define SN_hold_instruction_code "holdInstructionCode"
+#define LN_hold_instruction_code "Hold Instruction Code"
+#define NID_hold_instruction_code 430
+#define OBJ_hold_instruction_code OBJ_id_ce,23L
+
+#define OBJ_holdInstruction OBJ_X9_57,2L
+
+#define SN_hold_instruction_none "holdInstructionNone"
+#define LN_hold_instruction_none "Hold Instruction None"
+#define NID_hold_instruction_none 431
+#define OBJ_hold_instruction_none OBJ_holdInstruction,1L
+
+#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer 432
+#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L
+
+#define SN_hold_instruction_reject "holdInstructionReject"
+#define LN_hold_instruction_reject "Hold Instruction Reject"
+#define NID_hold_instruction_reject 433
+#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L
+
+#define SN_data "data"
+#define NID_data 434
+#define OBJ_data OBJ_itu_t,9L
+
+#define SN_pss "pss"
+#define NID_pss 435
+#define OBJ_pss OBJ_data,2342L
+
+#define SN_ucl "ucl"
+#define NID_ucl 436
+#define OBJ_ucl OBJ_pss,19200300L
+
+#define SN_pilot "pilot"
+#define NID_pilot 437
+#define OBJ_pilot OBJ_ucl,100L
+
+#define LN_pilotAttributeType "pilotAttributeType"
+#define NID_pilotAttributeType 438
+#define OBJ_pilotAttributeType OBJ_pilot,1L
+
+#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax 439
+#define OBJ_pilotAttributeSyntax OBJ_pilot,3L
+
+#define LN_pilotObjectClass "pilotObjectClass"
+#define NID_pilotObjectClass 440
+#define OBJ_pilotObjectClass OBJ_pilot,4L
+
+#define LN_pilotGroups "pilotGroups"
+#define NID_pilotGroups 441
+#define OBJ_pilotGroups OBJ_pilot,10L
+
+#define LN_iA5StringSyntax "iA5StringSyntax"
+#define NID_iA5StringSyntax 442
+#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L
+
+#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax 443
+#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L
+
+#define LN_pilotObject "pilotObject"
+#define NID_pilotObject 444
+#define OBJ_pilotObject OBJ_pilotObjectClass,3L
+
+#define LN_pilotPerson "pilotPerson"
+#define NID_pilotPerson 445
+#define OBJ_pilotPerson OBJ_pilotObjectClass,4L
+
+#define SN_account "account"
+#define NID_account 446
+#define OBJ_account OBJ_pilotObjectClass,5L
+
+#define SN_document "document"
+#define NID_document 447
+#define OBJ_document OBJ_pilotObjectClass,6L
+
+#define SN_room "room"
+#define NID_room 448
+#define OBJ_room OBJ_pilotObjectClass,7L
+
+#define LN_documentSeries "documentSeries"
+#define NID_documentSeries 449
+#define OBJ_documentSeries OBJ_pilotObjectClass,9L
+
+#define SN_Domain "domain"
+#define LN_Domain "Domain"
+#define NID_Domain 392
+#define OBJ_Domain OBJ_pilotObjectClass,13L
+
+#define LN_rFC822localPart "rFC822localPart"
+#define NID_rFC822localPart 450
+#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L
+
+#define LN_dNSDomain "dNSDomain"
+#define NID_dNSDomain 451
+#define OBJ_dNSDomain OBJ_pilotObjectClass,15L
+
+#define LN_domainRelatedObject "domainRelatedObject"
+#define NID_domainRelatedObject 452
+#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L
+
+#define LN_friendlyCountry "friendlyCountry"
+#define NID_friendlyCountry 453
+#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L
+
+#define LN_simpleSecurityObject "simpleSecurityObject"
+#define NID_simpleSecurityObject 454
+#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L
+
+#define LN_pilotOrganization "pilotOrganization"
+#define NID_pilotOrganization 455
+#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L
+
+#define LN_pilotDSA "pilotDSA"
+#define NID_pilotDSA 456
+#define OBJ_pilotDSA OBJ_pilotObjectClass,21L
+
+#define LN_qualityLabelledData "qualityLabelledData"
+#define NID_qualityLabelledData 457
+#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L
+
+#define SN_userId "UID"
+#define LN_userId "userId"
+#define NID_userId 458
+#define OBJ_userId OBJ_pilotAttributeType,1L
+
+#define LN_textEncodedORAddress "textEncodedORAddress"
+#define NID_textEncodedORAddress 459
+#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L
+
+#define SN_rfc822Mailbox "mail"
+#define LN_rfc822Mailbox "rfc822Mailbox"
+#define NID_rfc822Mailbox 460
+#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L
+
+#define SN_info "info"
+#define NID_info 461
+#define OBJ_info OBJ_pilotAttributeType,4L
+
+#define LN_favouriteDrink "favouriteDrink"
+#define NID_favouriteDrink 462
+#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L
+
+#define LN_roomNumber "roomNumber"
+#define NID_roomNumber 463
+#define OBJ_roomNumber OBJ_pilotAttributeType,6L
+
+#define SN_photo "photo"
+#define NID_photo 464
+#define OBJ_photo OBJ_pilotAttributeType,7L
+
+#define LN_userClass "userClass"
+#define NID_userClass 465
+#define OBJ_userClass OBJ_pilotAttributeType,8L
+
+#define SN_host "host"
+#define NID_host 466
+#define OBJ_host OBJ_pilotAttributeType,9L
+
+#define SN_manager "manager"
+#define NID_manager 467
+#define OBJ_manager OBJ_pilotAttributeType,10L
+
+#define LN_documentIdentifier "documentIdentifier"
+#define NID_documentIdentifier 468
+#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L
+
+#define LN_documentTitle "documentTitle"
+#define NID_documentTitle 469
+#define OBJ_documentTitle OBJ_pilotAttributeType,12L
+
+#define LN_documentVersion "documentVersion"
+#define NID_documentVersion 470
+#define OBJ_documentVersion OBJ_pilotAttributeType,13L
+
+#define LN_documentAuthor "documentAuthor"
+#define NID_documentAuthor 471
+#define OBJ_documentAuthor OBJ_pilotAttributeType,14L
+
+#define LN_documentLocation "documentLocation"
+#define NID_documentLocation 472
+#define OBJ_documentLocation OBJ_pilotAttributeType,15L
+
+#define LN_homeTelephoneNumber "homeTelephoneNumber"
+#define NID_homeTelephoneNumber 473
+#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L
+
+#define SN_secretary "secretary"
+#define NID_secretary 474
+#define OBJ_secretary OBJ_pilotAttributeType,21L
+
+#define LN_otherMailbox "otherMailbox"
+#define NID_otherMailbox 475
+#define OBJ_otherMailbox OBJ_pilotAttributeType,22L
+
+#define LN_lastModifiedTime "lastModifiedTime"
+#define NID_lastModifiedTime 476
+#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L
+
+#define LN_lastModifiedBy "lastModifiedBy"
+#define NID_lastModifiedBy 477
+#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L
+
+#define SN_domainComponent "DC"
+#define LN_domainComponent "domainComponent"
+#define NID_domainComponent 391
+#define OBJ_domainComponent OBJ_pilotAttributeType,25L
+
+#define LN_aRecord "aRecord"
+#define NID_aRecord 478
+#define OBJ_aRecord OBJ_pilotAttributeType,26L
+
+#define LN_pilotAttributeType27 "pilotAttributeType27"
+#define NID_pilotAttributeType27 479
+#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L
+
+#define LN_mXRecord "mXRecord"
+#define NID_mXRecord 480
+#define OBJ_mXRecord OBJ_pilotAttributeType,28L
+
+#define LN_nSRecord "nSRecord"
+#define NID_nSRecord 481
+#define OBJ_nSRecord OBJ_pilotAttributeType,29L
+
+#define LN_sOARecord "sOARecord"
+#define NID_sOARecord 482
+#define OBJ_sOARecord OBJ_pilotAttributeType,30L
+
+#define LN_cNAMERecord "cNAMERecord"
+#define NID_cNAMERecord 483
+#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L
+
+#define LN_associatedDomain "associatedDomain"
+#define NID_associatedDomain 484
+#define OBJ_associatedDomain OBJ_pilotAttributeType,37L
+
+#define LN_associatedName "associatedName"
+#define NID_associatedName 485
+#define OBJ_associatedName OBJ_pilotAttributeType,38L
+
+#define LN_homePostalAddress "homePostalAddress"
+#define NID_homePostalAddress 486
+#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L
+
+#define LN_personalTitle "personalTitle"
+#define NID_personalTitle 487
+#define OBJ_personalTitle OBJ_pilotAttributeType,40L
+
+#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber 488
+#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L
+
+#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber 489
+#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L
+
+#define LN_friendlyCountryName "friendlyCountryName"
+#define NID_friendlyCountryName 490
+#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L
+
+#define LN_organizationalStatus "organizationalStatus"
+#define NID_organizationalStatus 491
+#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L
+
+#define LN_janetMailbox "janetMailbox"
+#define NID_janetMailbox 492
+#define OBJ_janetMailbox OBJ_pilotAttributeType,46L
+
+#define LN_mailPreferenceOption "mailPreferenceOption"
+#define NID_mailPreferenceOption 493
+#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L
+
+#define LN_buildingName "buildingName"
+#define NID_buildingName 494
+#define OBJ_buildingName OBJ_pilotAttributeType,48L
+
+#define LN_dSAQuality "dSAQuality"
+#define NID_dSAQuality 495
+#define OBJ_dSAQuality OBJ_pilotAttributeType,49L
+
+#define LN_singleLevelQuality "singleLevelQuality"
+#define NID_singleLevelQuality 496
+#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L
+
+#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality 497
+#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L
+
+#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality 498
+#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L
+
+#define LN_personalSignature "personalSignature"
+#define NID_personalSignature 499
+#define OBJ_personalSignature OBJ_pilotAttributeType,53L
+
+#define LN_dITRedirect "dITRedirect"
+#define NID_dITRedirect 500
+#define OBJ_dITRedirect OBJ_pilotAttributeType,54L
+
+#define SN_audio "audio"
+#define NID_audio 501
+#define OBJ_audio OBJ_pilotAttributeType,55L
+
+#define LN_documentPublisher "documentPublisher"
+#define NID_documentPublisher 502
+#define OBJ_documentPublisher OBJ_pilotAttributeType,56L
+
+#define SN_id_set "id-set"
+#define LN_id_set "Secure Electronic Transactions"
+#define NID_id_set 512
+#define OBJ_id_set OBJ_international_organizations,42L
+
+#define SN_set_ctype "set-ctype"
+#define LN_set_ctype "content types"
+#define NID_set_ctype 513
+#define OBJ_set_ctype OBJ_id_set,0L
+
+#define SN_set_msgExt "set-msgExt"
+#define LN_set_msgExt "message extensions"
+#define NID_set_msgExt 514
+#define OBJ_set_msgExt OBJ_id_set,1L
+
+#define SN_set_attr "set-attr"
+#define NID_set_attr 515
+#define OBJ_set_attr OBJ_id_set,3L
+
+#define SN_set_policy "set-policy"
+#define NID_set_policy 516
+#define OBJ_set_policy OBJ_id_set,5L
+
+#define SN_set_certExt "set-certExt"
+#define LN_set_certExt "certificate extensions"
+#define NID_set_certExt 517
+#define OBJ_set_certExt OBJ_id_set,7L
+
+#define SN_set_brand "set-brand"
+#define NID_set_brand 518
+#define OBJ_set_brand OBJ_id_set,8L
+
+#define SN_setct_PANData "setct-PANData"
+#define NID_setct_PANData 519
+#define OBJ_setct_PANData OBJ_set_ctype,0L
+
+#define SN_setct_PANToken "setct-PANToken"
+#define NID_setct_PANToken 520
+#define OBJ_setct_PANToken OBJ_set_ctype,1L
+
+#define SN_setct_PANOnly "setct-PANOnly"
+#define NID_setct_PANOnly 521
+#define OBJ_setct_PANOnly OBJ_set_ctype,2L
+
+#define SN_setct_OIData "setct-OIData"
+#define NID_setct_OIData 522
+#define OBJ_setct_OIData OBJ_set_ctype,3L
+
+#define SN_setct_PI "setct-PI"
+#define NID_setct_PI 523
+#define OBJ_setct_PI OBJ_set_ctype,4L
+
+#define SN_setct_PIData "setct-PIData"
+#define NID_setct_PIData 524
+#define OBJ_setct_PIData OBJ_set_ctype,5L
+
+#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned 525
+#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L
+
+#define SN_setct_HODInput "setct-HODInput"
+#define NID_setct_HODInput 526
+#define OBJ_setct_HODInput OBJ_set_ctype,7L
+
+#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage 527
+#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L
+
+#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage 528
+#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L
+
+#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage 529
+#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L
+
+#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq 530
+#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L
+
+#define SN_setct_PInitResData "setct-PInitResData"
+#define NID_setct_PInitResData 531
+#define OBJ_setct_PInitResData OBJ_set_ctype,12L
+
+#define SN_setct_PI_TBS "setct-PI-TBS"
+#define NID_setct_PI_TBS 532
+#define OBJ_setct_PI_TBS OBJ_set_ctype,13L
+
+#define SN_setct_PResData "setct-PResData"
+#define NID_setct_PResData 533
+#define OBJ_setct_PResData OBJ_set_ctype,14L
+
+#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS 534
+#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L
+
+#define SN_setct_AuthResTBS "setct-AuthResTBS"
+#define NID_setct_AuthResTBS 535
+#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L
+
+#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX 536
+#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L
+
+#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS 537
+#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L
+
+#define SN_setct_CapTokenData "setct-CapTokenData"
+#define NID_setct_CapTokenData 538
+#define OBJ_setct_CapTokenData OBJ_set_ctype,20L
+
+#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS 539
+#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L
+
+#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg 540
+#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L
+
+#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS 541
+#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L
+
+#define SN_setct_AuthRevResData "setct-AuthRevResData"
+#define NID_setct_AuthRevResData 542
+#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L
+
+#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS 543
+#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L
+
+#define SN_setct_CapReqTBS "setct-CapReqTBS"
+#define NID_setct_CapReqTBS 544
+#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L
+
+#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX 545
+#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L
+
+#define SN_setct_CapResData "setct-CapResData"
+#define NID_setct_CapResData 546
+#define OBJ_setct_CapResData OBJ_set_ctype,28L
+
+#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS 547
+#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L
+
+#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX 548
+#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L
+
+#define SN_setct_CapRevResData "setct-CapRevResData"
+#define NID_setct_CapRevResData 549
+#define OBJ_setct_CapRevResData OBJ_set_ctype,31L
+
+#define SN_setct_CredReqTBS "setct-CredReqTBS"
+#define NID_setct_CredReqTBS 550
+#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L
+
+#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX 551
+#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L
+
+#define SN_setct_CredResData "setct-CredResData"
+#define NID_setct_CredResData 552
+#define OBJ_setct_CredResData OBJ_set_ctype,34L
+
+#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS 553
+#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L
+
+#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX 554
+#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L
+
+#define SN_setct_CredRevResData "setct-CredRevResData"
+#define NID_setct_CredRevResData 555
+#define OBJ_setct_CredRevResData OBJ_set_ctype,37L
+
+#define SN_setct_PCertReqData "setct-PCertReqData"
+#define NID_setct_PCertReqData 556
+#define OBJ_setct_PCertReqData OBJ_set_ctype,38L
+
+#define SN_setct_PCertResTBS "setct-PCertResTBS"
+#define NID_setct_PCertResTBS 557
+#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L
+
+#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData 558
+#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L
+
+#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData 559
+#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L
+
+#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS 560
+#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L
+
+#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS 561
+#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L
+
+#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS 562
+#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L
+
+#define SN_setct_CertReqData "setct-CertReqData"
+#define NID_setct_CertReqData 563
+#define OBJ_setct_CertReqData OBJ_set_ctype,45L
+
+#define SN_setct_CertReqTBS "setct-CertReqTBS"
+#define NID_setct_CertReqTBS 564
+#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L
+
+#define SN_setct_CertResData "setct-CertResData"
+#define NID_setct_CertResData 565
+#define OBJ_setct_CertResData OBJ_set_ctype,47L
+
+#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS 566
+#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L
+
+#define SN_setct_ErrorTBS "setct-ErrorTBS"
+#define NID_setct_ErrorTBS 567
+#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L
+
+#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE 568
+#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L
+
+#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE 569
+#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L
+
+#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE 570
+#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L
+
+#define SN_setct_AuthResTBE "setct-AuthResTBE"
+#define NID_setct_AuthResTBE 571
+#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L
+
+#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX 572
+#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L
+
+#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE 573
+#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L
+
+#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE 574
+#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L
+
+#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX 575
+#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L
+
+#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE 576
+#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L
+
+#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE 577
+#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L
+
+#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE 578
+#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L
+
+#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB 579
+#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L
+
+#define SN_setct_CapReqTBE "setct-CapReqTBE"
+#define NID_setct_CapReqTBE 580
+#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L
+
+#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX 581
+#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L
+
+#define SN_setct_CapResTBE "setct-CapResTBE"
+#define NID_setct_CapResTBE 582
+#define OBJ_setct_CapResTBE OBJ_set_ctype,64L
+
+#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE 583
+#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L
+
+#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX 584
+#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L
+
+#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE 585
+#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L
+
+#define SN_setct_CredReqTBE "setct-CredReqTBE"
+#define NID_setct_CredReqTBE 586
+#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L
+
+#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX 587
+#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L
+
+#define SN_setct_CredResTBE "setct-CredResTBE"
+#define NID_setct_CredResTBE 588
+#define OBJ_setct_CredResTBE OBJ_set_ctype,70L
+
+#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE 589
+#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L
+
+#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX 590
+#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L
+
+#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE 591
+#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L
+
+#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE 592
+#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L
+
+#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE 593
+#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L
+
+#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE 594
+#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L
+
+#define SN_setct_CertReqTBE "setct-CertReqTBE"
+#define NID_setct_CertReqTBE 595
+#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L
+
+#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX 596
+#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L
+
+#define SN_setct_CertResTBE "setct-CertResTBE"
+#define NID_setct_CertResTBE 597
+#define OBJ_setct_CertResTBE OBJ_set_ctype,79L
+
+#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS 598
+#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L
+
+#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS 599
+#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L
+
+#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS 600
+#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L
+
+#define SN_setext_genCrypt "setext-genCrypt"
+#define LN_setext_genCrypt "generic cryptogram"
+#define NID_setext_genCrypt 601
+#define OBJ_setext_genCrypt OBJ_set_msgExt,1L
+
+#define SN_setext_miAuth "setext-miAuth"
+#define LN_setext_miAuth "merchant initiated auth"
+#define NID_setext_miAuth 602
+#define OBJ_setext_miAuth OBJ_set_msgExt,3L
+
+#define SN_setext_pinSecure "setext-pinSecure"
+#define NID_setext_pinSecure 603
+#define OBJ_setext_pinSecure OBJ_set_msgExt,4L
+
+#define SN_setext_pinAny "setext-pinAny"
+#define NID_setext_pinAny 604
+#define OBJ_setext_pinAny OBJ_set_msgExt,5L
+
+#define SN_setext_track2 "setext-track2"
+#define NID_setext_track2 605
+#define OBJ_setext_track2 OBJ_set_msgExt,7L
+
+#define SN_setext_cv "setext-cv"
+#define LN_setext_cv "additional verification"
+#define NID_setext_cv 606
+#define OBJ_setext_cv OBJ_set_msgExt,8L
+
+#define SN_set_policy_root "set-policy-root"
+#define NID_set_policy_root 607
+#define OBJ_set_policy_root OBJ_set_policy,0L
+
+#define SN_setCext_hashedRoot "setCext-hashedRoot"
+#define NID_setCext_hashedRoot 608
+#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L
+
+#define SN_setCext_certType "setCext-certType"
+#define NID_setCext_certType 609
+#define OBJ_setCext_certType OBJ_set_certExt,1L
+
+#define SN_setCext_merchData "setCext-merchData"
+#define NID_setCext_merchData 610
+#define OBJ_setCext_merchData OBJ_set_certExt,2L
+
+#define SN_setCext_cCertRequired "setCext-cCertRequired"
+#define NID_setCext_cCertRequired 611
+#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L
+
+#define SN_setCext_tunneling "setCext-tunneling"
+#define NID_setCext_tunneling 612
+#define OBJ_setCext_tunneling OBJ_set_certExt,4L
+
+#define SN_setCext_setExt "setCext-setExt"
+#define NID_setCext_setExt 613
+#define OBJ_setCext_setExt OBJ_set_certExt,5L
+
+#define SN_setCext_setQualf "setCext-setQualf"
+#define NID_setCext_setQualf 614
+#define OBJ_setCext_setQualf OBJ_set_certExt,6L
+
+#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities 615
+#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L
+
+#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier 616
+#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L
+
+#define SN_setCext_Track2Data "setCext-Track2Data"
+#define NID_setCext_Track2Data 617
+#define OBJ_setCext_Track2Data OBJ_set_certExt,9L
+
+#define SN_setCext_TokenType "setCext-TokenType"
+#define NID_setCext_TokenType 618
+#define OBJ_setCext_TokenType OBJ_set_certExt,10L
+
+#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities 619
+#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L
+
+#define SN_setAttr_Cert "setAttr-Cert"
+#define NID_setAttr_Cert 620
+#define OBJ_setAttr_Cert OBJ_set_attr,0L
+
+#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap "payment gateway capabilities"
+#define NID_setAttr_PGWYcap 621
+#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L
+
+#define SN_setAttr_TokenType "setAttr-TokenType"
+#define NID_setAttr_TokenType 622
+#define OBJ_setAttr_TokenType OBJ_set_attr,2L
+
+#define SN_setAttr_IssCap "setAttr-IssCap"
+#define LN_setAttr_IssCap "issuer capabilities"
+#define NID_setAttr_IssCap 623
+#define OBJ_setAttr_IssCap OBJ_set_attr,3L
+
+#define SN_set_rootKeyThumb "set-rootKeyThumb"
+#define NID_set_rootKeyThumb 624
+#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L
+
+#define SN_set_addPolicy "set-addPolicy"
+#define NID_set_addPolicy 625
+#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L
+
+#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV 626
+#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L
+
+#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime 627
+#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L
+
+#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM 628
+#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L
+
+#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2 629
+#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L
+
+#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig 630
+#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L
+
+#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm "generate cryptogram"
+#define NID_setAttr_GenCryptgrm 631
+#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L
+
+#define SN_setAttr_T2Enc "setAttr-T2Enc"
+#define LN_setAttr_T2Enc "encrypted track 2"
+#define NID_setAttr_T2Enc 632
+#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L
+
+#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt "cleartext track 2"
+#define NID_setAttr_T2cleartxt 633
+#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L
+
+#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig "ICC or token signature"
+#define NID_setAttr_TokICCsig 634
+#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L
+
+#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig "secure device signature"
+#define NID_setAttr_SecDevSig 635
+#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L
+
+#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA 636
+#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L
+
+#define SN_set_brand_Diners "set-brand-Diners"
+#define NID_set_brand_Diners 637
+#define OBJ_set_brand_Diners OBJ_set_brand,30L
+
+#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress 638
+#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L
+
+#define SN_set_brand_JCB "set-brand-JCB"
+#define NID_set_brand_JCB 639
+#define OBJ_set_brand_JCB OBJ_set_brand,35L
+
+#define SN_set_brand_Visa "set-brand-Visa"
+#define NID_set_brand_Visa 640
+#define OBJ_set_brand_Visa OBJ_set_brand,4L
+
+#define SN_set_brand_MasterCard "set-brand-MasterCard"
+#define NID_set_brand_MasterCard 641
+#define OBJ_set_brand_MasterCard OBJ_set_brand,5L
+
+#define SN_set_brand_Novus "set-brand-Novus"
+#define NID_set_brand_Novus 642
+#define OBJ_set_brand_Novus OBJ_set_brand,6011L
+
+#define SN_des_cdmf "DES-CDMF"
+#define LN_des_cdmf "des-cdmf"
+#define NID_des_cdmf 643
+#define OBJ_des_cdmf OBJ_rsadsi,3L,10L
+
+#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET 644
+#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L
+
+#define SN_ipsec3 "Oakley-EC2N-3"
+#define LN_ipsec3 "ipsec3"
+#define NID_ipsec3 749
+
+#define SN_ipsec4 "Oakley-EC2N-4"
+#define LN_ipsec4 "ipsec4"
+#define NID_ipsec4 750
+
+#define SN_whirlpool "whirlpool"
+#define NID_whirlpool 804
+#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L
+
+#define SN_cryptopro "cryptopro"
+#define NID_cryptopro 805
+#define OBJ_cryptopro OBJ_member_body,643L,2L,2L
+
+#define SN_cryptocom "cryptocom"
+#define NID_cryptocom 806
+#define OBJ_cryptocom OBJ_member_body,643L,2L,9L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001"
+#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001"
+#define NID_id_GostR3411_94_with_GostR3410_2001 807
+#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
+#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94"
+#define NID_id_GostR3411_94_with_GostR3410_94 808
+#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L
+
+#define SN_id_GostR3411_94 "md_gost94"
+#define LN_id_GostR3411_94 "GOST R 34.11-94"
+#define NID_id_GostR3411_94 809
+#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L
+
+#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
+#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
+#define NID_id_HMACGostR3411_94 810
+#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L
+
+#define SN_id_GostR3410_2001 "gost2001"
+#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
+#define NID_id_GostR3410_2001 811
+#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L
+
+#define SN_id_GostR3410_94 "gost94"
+#define LN_id_GostR3410_94 "GOST R 34.10-94"
+#define NID_id_GostR3410_94 812
+#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L
+
+#define SN_id_Gost28147_89 "gost89"
+#define LN_id_Gost28147_89 "GOST 28147-89"
+#define NID_id_Gost28147_89 813
+#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L
+
+#define SN_gost89_cnt "gost89-cnt"
+#define NID_gost89_cnt 814
+
+#define SN_id_Gost28147_89_MAC "gost-mac"
+#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
+#define NID_id_Gost28147_89_MAC 815
+#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L
+
+#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
+#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
+#define NID_id_GostR3411_94_prf 816
+#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L
+
+#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
+#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
+#define NID_id_GostR3410_2001DH 817
+#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L
+
+#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
+#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
+#define NID_id_GostR3410_94DH 818
+#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L
+
+#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing"
+#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
+#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L
+
+#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
+#define NID_id_Gost28147_89_None_KeyMeshing 820
+#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L
+
+#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
+#define NID_id_GostR3411_94_TestParamSet 821
+#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L
+
+#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
+#define NID_id_GostR3411_94_CryptoProParamSet 822
+#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L
+
+#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
+#define NID_id_Gost28147_89_TestParamSet 823
+#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L
+
+#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
+#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L
+
+#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
+#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L
+
+#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
+#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L
+
+#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
+#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L
+
+#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
+#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L
+
+#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
+#define NID_id_GostR3410_94_TestParamSet 831
+#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L
+
+#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
+#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
+#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L
+
+#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
+#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L
+
+#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
+#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L
+
+#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
+#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L
+
+#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
+#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
+#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L
+
+#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
+#define NID_id_GostR3410_2001_TestParamSet 839
+#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
+#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L
+
+#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
+#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L
+
+#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
+#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
+#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
+#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L
+
+#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
+#define NID_id_GostR3410_94_a 845
+#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L
+
+#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
+#define NID_id_GostR3410_94_aBis 846
+#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L
+
+#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
+#define NID_id_GostR3410_94_b 847
+#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L
+
+#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
+#define NID_id_GostR3410_94_bBis 848
+#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L
+
+#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
+#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
+#define NID_id_Gost28147_89_cc 849
+#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L
+
+#define SN_id_GostR3410_94_cc "gost94cc"
+#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
+#define NID_id_GostR3410_94_cc 850
+#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L
+
+#define SN_id_GostR3410_2001_cc "gost2001cc"
+#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
+#define NID_id_GostR3410_2001_cc 851
+#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L
+
+#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc"
+#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
+#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc"
+#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
+#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L
+
+#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
+#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom"
+#define NID_id_GostR3410_2001_ParamSet_cc 854
+#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L
+
+#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc "camellia-128-cbc"
+#define NID_camellia_128_cbc 751
+#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L
+
+#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc "camellia-192-cbc"
+#define NID_camellia_192_cbc 752
+#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L
+
+#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc "camellia-256-cbc"
+#define NID_camellia_256_cbc 753
+#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L
+
+#define OBJ_ntt_ds 0L,3L,4401L,5L
+
+#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L
+
+#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb "camellia-128-ecb"
+#define NID_camellia_128_ecb 754
+#define OBJ_camellia_128_ecb OBJ_camellia,1L
+
+#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128 "camellia-128-ofb"
+#define NID_camellia_128_ofb128 766
+#define OBJ_camellia_128_ofb128 OBJ_camellia,3L
+
+#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128 "camellia-128-cfb"
+#define NID_camellia_128_cfb128 757
+#define OBJ_camellia_128_cfb128 OBJ_camellia,4L
+
+#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb "camellia-192-ecb"
+#define NID_camellia_192_ecb 755
+#define OBJ_camellia_192_ecb OBJ_camellia,21L
+
+#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128 "camellia-192-ofb"
+#define NID_camellia_192_ofb128 767
+#define OBJ_camellia_192_ofb128 OBJ_camellia,23L
+
+#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128 "camellia-192-cfb"
+#define NID_camellia_192_cfb128 758
+#define OBJ_camellia_192_cfb128 OBJ_camellia,24L
+
+#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb "camellia-256-ecb"
+#define NID_camellia_256_ecb 756
+#define OBJ_camellia_256_ecb OBJ_camellia,41L
+
+#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128 "camellia-256-ofb"
+#define NID_camellia_256_ofb128 768
+#define OBJ_camellia_256_ofb128 OBJ_camellia,43L
+
+#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128 "camellia-256-cfb"
+#define NID_camellia_256_cfb128 759
+#define OBJ_camellia_256_cfb128 OBJ_camellia,44L
+
+#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1 "camellia-128-cfb1"
+#define NID_camellia_128_cfb1 760
+
+#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1 "camellia-192-cfb1"
+#define NID_camellia_192_cfb1 761
+
+#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1 "camellia-256-cfb1"
+#define NID_camellia_256_cfb1 762
+
+#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8 "camellia-128-cfb8"
+#define NID_camellia_128_cfb8 763
+
+#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8 "camellia-192-cfb8"
+#define NID_camellia_192_cfb8 764
+
+#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8 "camellia-256-cfb8"
+#define NID_camellia_256_cfb8 765
+
+#define SN_kisa "KISA"
+#define LN_kisa "kisa"
+#define NID_kisa 773
+#define OBJ_kisa OBJ_member_body,410L,200004L
+
+#define SN_seed_ecb "SEED-ECB"
+#define LN_seed_ecb "seed-ecb"
+#define NID_seed_ecb 776
+#define OBJ_seed_ecb OBJ_kisa,1L,3L
+
+#define SN_seed_cbc "SEED-CBC"
+#define LN_seed_cbc "seed-cbc"
+#define NID_seed_cbc 777
+#define OBJ_seed_cbc OBJ_kisa,1L,4L
+
+#define SN_seed_cfb128 "SEED-CFB"
+#define LN_seed_cfb128 "seed-cfb"
+#define NID_seed_cfb128 779
+#define OBJ_seed_cfb128 OBJ_kisa,1L,5L
+
+#define SN_seed_ofb128 "SEED-OFB"
+#define LN_seed_ofb128 "seed-ofb"
+#define NID_seed_ofb128 778
+#define OBJ_seed_ofb128 OBJ_kisa,1L,6L
+
+#define SN_hmac "HMAC"
+#define LN_hmac "hmac"
+#define NID_hmac 855
+
diff --git a/src/Mayaqua/win32_inc/openssl/objects.h b/src/Mayaqua/win32_inc/openssl/objects.h
new file mode 100644
index 00000000..77008942
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/objects.h
@@ -0,0 +1,1049 @@
+/* crypto/objects/objects.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_OBJECTS_H
+#define HEADER_OBJECTS_H
+
+#define USE_OBJ_MAC
+
+#ifdef USE_OBJ_MAC
+#include <openssl/obj_mac.h>
+#else
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_Algorithm "Algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 38
+#define OBJ_algorithm 1L,3L,14L,3L,2L
+
+#define LN_rsadsi "rsadsi"
+#define NID_rsadsi 1
+#define OBJ_rsadsi 1L,2L,840L,113549L
+
+#define LN_pkcs "pkcs"
+#define NID_pkcs 2
+#define OBJ_pkcs OBJ_rsadsi,1L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 OBJ_rsadsi,2L,2L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 OBJ_rsadsi,2L,5L
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 OBJ_rsadsi,3L,4L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption OBJ_pkcs,1L,1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption OBJ_pkcs,1L,2L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption OBJ_pkcs,1L,4L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs,5L,1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs,5L,3L
+
+#define LN_X500 "X500"
+#define NID_X500 11
+#define OBJ_X500 2L,5L
+
+#define LN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 OBJ_X500,4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName OBJ_X509,3L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName OBJ_X509,6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName OBJ_X509,7L
+
+/* Postal Address? PA */
+
+/* should be "ST" (rfc1327) but MS uses 'S' */
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName OBJ_X509,8L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName OBJ_X509,10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName OBJ_X509,11L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa OBJ_X500,8L,1L,1L
+
+#define LN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 OBJ_pkcs,7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
+
+#define LN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb OBJ_algorithm,6L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+/* IV + num */
+#define OBJ_des_cfb64 OBJ_algorithm,9L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+/* IV */
+#define OBJ_des_cbc OBJ_algorithm,7L
+
+#define SN_des_ede "DES-EDE"
+#define LN_des_ede "des-ede"
+#define NID_des_ede 32
+/* ?? */
+#define OBJ_des_ede OBJ_algorithm,17L
+
+#define SN_des_ede3 "DES-EDE3"
+#define LN_des_ede3 "des-ede3"
+#define NID_des_ede3 33
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha OBJ_algorithm,18L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 OBJ_algorithm,8L
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define LN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 OBJ_pkcs,9L
+
+#define SN_pkcs9_emailAddress "Email"
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension OBJ_netscape,1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type OBJ_netscape,2L
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+/* I'm not sure about the object ID */
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 OBJ_algorithm,26L
+/* 28 Jun 1996 - eay */
+/* #define OBJ_sha1 1L,3L,14L,2L,26L,05L <- wrong */
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption OBJ_pkcs,1L,5L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA OBJ_algorithm,13L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 OBJ_algorithm,12L
+
+/* proposed by microsoft to RSA */
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs,5L,11L
+
+/* proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now
+ * defined explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something
+ * completely different.
+ */
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 OBJ_pkcs,5L,12L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */
+#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce 2L,5L,29L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier OBJ_id_ce,14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage OBJ_id_ce,15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period OBJ_id_ce,16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name OBJ_id_ce,17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name OBJ_id_ce,18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints OBJ_id_ce,19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number OBJ_id_ce,20L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies OBJ_id_ce,32L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier OBJ_id_ce,35L
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 2L,5L,8L,3L,101L
+/* An alternative? 1L,3L,14L,3L,2L,19L */
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2withRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA 2L,5L,8L,3L,100L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_givenName "G"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName OBJ_X509,42L
+
+#define SN_surname "S"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname OBJ_X509,4L
+
+#define SN_initials "I"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials OBJ_X509,43L
+
+#define SN_uniqueIdentifier "UID"
+#define LN_uniqueIdentifier "uniqueIdentifier"
+#define NID_uniqueIdentifier 102
+#define OBJ_uniqueIdentifier OBJ_X509,45L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points OBJ_id_ce,31L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA OBJ_algorithm,3L
+
+#define SN_serialNumber "SN"
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber OBJ_X509,5L
+
+#define SN_title "T"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title OBJ_X509,12L
+
+#define SN_description "D"
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description OBJ_X509,13L
+
+/* CAST5 is CAST-128, I'm just sticking with the documentation */
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc 1L,2L,840L,113533L,7L,66L,10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC 1L,2L,840L,113533L,7L,66L,12L
+
+/* This is one sun will soon be using :-(
+ * id-dsa-with-sha1 ID ::= {
+ * iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 }
+ */
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 1L,2L,840L,10040L,4L,3L
+
+#define NID_md5_sha1 114
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA OBJ_algorithm,29L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa 1L,2L,840L,10040L,4L,1L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
+
+/* The name should actually be rsaSignatureWithripemd160, but I'm going
+ * to continue using the convention I'm using with the other ciphers */
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+
+/* Taken from rfc2040
+ * RC5_CBC_Parameters ::= SEQUENCE {
+ * version INTEGER (v1_0(16)),
+ * rounds INTEGER (8..127),
+ * blockSizeInBits INTEGER (64, 128),
+ * iv OCTET STRING OPTIONAL
+ * }
+ */
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_rle_compression "RLE"
+#define LN_rle_compression "run length compression"
+#define NID_rle_compression 124
+#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression 1L,1L,1L,1L,666L,2L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage OBJ_id_ce,37
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp OBJ_id_pkix,3L
+
+/* PKIX extended key usage OIDs */
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth OBJ_id_kp,1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth OBJ_id_kp,2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign OBJ_id_kp,3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect OBJ_id_kp,4L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp OBJ_id_kp,8L
+
+/* Additional extended key usage OIDs: Microsoft */
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+/* Additional usage: Netscape */
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc OBJ_netscape,4L,1L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl OBJ_id_ce,27L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason OBJ_id_ce,21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date OBJ_id_ce,24L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
+
+/* PKCS12 and related OBJECT IDENTIFIERS */
+
+#define OBJ_pkcs12 OBJ_pkcs,12L
+#define OBJ_pkcs12_pbeids OBJ_pkcs12, 1
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids, 1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids, 2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids, 5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids, 6L
+
+#define OBJ_pkcs12_Version1 OBJ_pkcs12, 10L
+
+#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1, 1L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag OBJ_pkcs12_BagIds, 1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds, 2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag OBJ_pkcs12_BagIds, 3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag OBJ_pkcs12_BagIds, 4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag OBJ_pkcs12_BagIds, 5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag OBJ_pkcs12_BagIds, 6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName OBJ_pkcs9, 20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID OBJ_pkcs9, 21L
+
+#define OBJ_certTypes OBJ_pkcs9, 22L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate OBJ_certTypes, 1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate OBJ_certTypes, 2L
+
+#define OBJ_crlTypes OBJ_pkcs9, 23L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl OBJ_crlTypes, 1L
+
+/* PKCS#5 v2 OIDs */
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 OBJ_pkcs,5L,13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 OBJ_pkcs,5L,14L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+
+/* Policy Qualifier Ids */
+
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define SN_id_qt_cps "id-qt-cps"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps OBJ_id_pkix,2L,1L
+
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define SN_id_qt_unotice "id-qt-unotice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice OBJ_id_pkix,2L,2L
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs,5L,4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs,5L,6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs,5L,10L
+
+/* Extension request OIDs */
+
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define SN_ms_ext_req "msExtReq"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define LN_ext_req "Extension Request"
+#define SN_ext_req "extReq"
+#define NID_ext_req 172
+#define OBJ_ext_req OBJ_pkcs9,14L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name OBJ_X509,41L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier OBJ_X509,46L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe OBJ_id_pkix,1L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad OBJ_id_pkix,48L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access OBJ_id_pe,1L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers OBJ_id_ad,2L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign OBJ_id_kp,9L
+#endif /* USE_OBJ_MAC */
+
+#include <openssl/bio.h>
+#include <openssl/asn1.h>
+
+#define OBJ_NAME_TYPE_UNDEF 0x00
+#define OBJ_NAME_TYPE_MD_METH 0x01
+#define OBJ_NAME_TYPE_CIPHER_METH 0x02
+#define OBJ_NAME_TYPE_PKEY_METH 0x03
+#define OBJ_NAME_TYPE_COMP_METH 0x04
+#define OBJ_NAME_TYPE_NUM 0x05
+
+#define OBJ_NAME_ALIAS 0x8000
+
+#define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01
+#define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct obj_name_st
+ {
+ int type;
+ int alias;
+ const char *name;
+ const char *data;
+ } OBJ_NAME;
+
+#define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c)
+
+
+int OBJ_NAME_init(void);
+int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
+ int (*cmp_func)(const char *, const char *),
+ void (*free_func)(const char *, int, const char *));
+const char *OBJ_NAME_get(const char *name,int type);
+int OBJ_NAME_add(const char *name,int type,const char *data);
+int OBJ_NAME_remove(const char *name,int type);
+void OBJ_NAME_cleanup(int type); /* -1 for everything */
+void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),
+ void *arg);
+void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
+ void *arg);
+
+ASN1_OBJECT * OBJ_dup(const ASN1_OBJECT *o);
+ASN1_OBJECT * OBJ_nid2obj(int n);
+const char * OBJ_nid2ln(int n);
+const char * OBJ_nid2sn(int n);
+int OBJ_obj2nid(const ASN1_OBJECT *o);
+ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name);
+int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
+int OBJ_txt2nid(const char *s);
+int OBJ_ln2nid(const char *s);
+int OBJ_sn2nid(const char *s);
+int OBJ_cmp(const ASN1_OBJECT *a,const ASN1_OBJECT *b);
+const char * OBJ_bsearch(const char *key,const char *base,int num,int size,
+ int (*cmp)(const void *, const void *));
+const char * OBJ_bsearch_ex(const char *key,const char *base,int num,
+ int size, int (*cmp)(const void *, const void *), int flags);
+
+int OBJ_new_nid(int num);
+int OBJ_add_object(const ASN1_OBJECT *obj);
+int OBJ_create(const char *oid,const char *sn,const char *ln);
+void OBJ_cleanup(void );
+int OBJ_create_objects(BIO *in);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OBJ_strings(void);
+
+/* Error codes for the OBJ functions. */
+
+/* Function codes. */
+#define OBJ_F_OBJ_ADD_OBJECT 105
+#define OBJ_F_OBJ_CREATE 100
+#define OBJ_F_OBJ_DUP 101
+#define OBJ_F_OBJ_NAME_NEW_INDEX 106
+#define OBJ_F_OBJ_NID2LN 102
+#define OBJ_F_OBJ_NID2OBJ 103
+#define OBJ_F_OBJ_NID2SN 104
+
+/* Reason codes. */
+#define OBJ_R_MALLOC_FAILURE 100
+#define OBJ_R_UNKNOWN_NID 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ocsp.h b/src/Mayaqua/win32_inc/openssl/ocsp.h
new file mode 100644
index 00000000..a9b7160a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ocsp.h
@@ -0,0 +1,623 @@
+/* ocsp.h */
+/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
+ * project. */
+
+/* History:
+ This file was transfered to Richard Levitte from CertCo by Kathy
+ Weinhold in mid-spring 2000 to be included in OpenSSL or released
+ as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OCSP_H
+#define HEADER_OCSP_H
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Various flags and values */
+
+#define OCSP_DEFAULT_NONCE_LENGTH 16
+
+#define OCSP_NOCERTS 0x1
+#define OCSP_NOINTERN 0x2
+#define OCSP_NOSIGS 0x4
+#define OCSP_NOCHAIN 0x8
+#define OCSP_NOVERIFY 0x10
+#define OCSP_NOEXPLICIT 0x20
+#define OCSP_NOCASIGN 0x40
+#define OCSP_NODELEGATED 0x80
+#define OCSP_NOCHECKS 0x100
+#define OCSP_TRUSTOTHER 0x200
+#define OCSP_RESPID_KEY 0x400
+#define OCSP_NOTIME 0x800
+
+/* CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields)
+ * serialNumber CertificateSerialNumber }
+ */
+typedef struct ocsp_cert_id_st
+ {
+ X509_ALGOR *hashAlgorithm;
+ ASN1_OCTET_STRING *issuerNameHash;
+ ASN1_OCTET_STRING *issuerKeyHash;
+ ASN1_INTEGER *serialNumber;
+ } OCSP_CERTID;
+
+DECLARE_STACK_OF(OCSP_CERTID)
+
+/* Request ::= SEQUENCE {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_one_request_st
+ {
+ OCSP_CERTID *reqCert;
+ STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+ } OCSP_ONEREQ;
+
+DECLARE_STACK_OF(OCSP_ONEREQ)
+DECLARE_ASN1_SET_OF(OCSP_ONEREQ)
+
+
+/* TBSRequest ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList SEQUENCE OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_req_info_st
+ {
+ ASN1_INTEGER *version;
+ GENERAL_NAME *requestorName;
+ STACK_OF(OCSP_ONEREQ) *requestList;
+ STACK_OF(X509_EXTENSION) *requestExtensions;
+ } OCSP_REQINFO;
+
+/* Signature ::= SEQUENCE {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+typedef struct ocsp_signature_st
+ {
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+ } OCSP_SIGNATURE;
+
+/* OCSPRequest ::= SEQUENCE {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ */
+typedef struct ocsp_request_st
+ {
+ OCSP_REQINFO *tbsRequest;
+ OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
+ } OCSP_REQUEST;
+
+/* OCSPResponseStatus ::= ENUMERATED {
+ * successful (0), --Response has valid confirmations
+ * malformedRequest (1), --Illegal confirmation request
+ * internalError (2), --Internal error in issuer
+ * tryLater (3), --Try again later
+ * --(4) is not used
+ * sigRequired (5), --Must sign the request
+ * unauthorized (6) --Request unauthorized
+ * }
+ */
+#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
+#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1
+#define OCSP_RESPONSE_STATUS_INTERNALERROR 2
+#define OCSP_RESPONSE_STATUS_TRYLATER 3
+#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5
+#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6
+
+/* ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ */
+typedef struct ocsp_resp_bytes_st
+ {
+ ASN1_OBJECT *responseType;
+ ASN1_OCTET_STRING *response;
+ } OCSP_RESPBYTES;
+
+/* OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+struct ocsp_response_st
+ {
+ ASN1_ENUMERATED *responseStatus;
+ OCSP_RESPBYTES *responseBytes;
+ };
+
+/* ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ */
+#define V_OCSP_RESPID_NAME 0
+#define V_OCSP_RESPID_KEY 1
+struct ocsp_responder_id_st
+ {
+ int type;
+ union {
+ X509_NAME* byName;
+ ASN1_OCTET_STRING *byKey;
+ } value;
+ };
+
+DECLARE_STACK_OF(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+
+/* KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ * --(excluding the tag and length fields)
+ */
+
+/* RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ */
+typedef struct ocsp_revoked_info_st
+ {
+ ASN1_GENERALIZEDTIME *revocationTime;
+ ASN1_ENUMERATED *revocationReason;
+ } OCSP_REVOKEDINFO;
+
+/* CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ */
+#define V_OCSP_CERTSTATUS_GOOD 0
+#define V_OCSP_CERTSTATUS_REVOKED 1
+#define V_OCSP_CERTSTATUS_UNKNOWN 2
+typedef struct ocsp_cert_status_st
+ {
+ int type;
+ union {
+ ASN1_NULL *good;
+ OCSP_REVOKEDINFO *revoked;
+ ASN1_NULL *unknown;
+ } value;
+ } OCSP_CERTSTATUS;
+
+/* SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_single_response_st
+ {
+ OCSP_CERTID *certId;
+ OCSP_CERTSTATUS *certStatus;
+ ASN1_GENERALIZEDTIME *thisUpdate;
+ ASN1_GENERALIZEDTIME *nextUpdate;
+ STACK_OF(X509_EXTENSION) *singleExtensions;
+ } OCSP_SINGLERESP;
+
+DECLARE_STACK_OF(OCSP_SINGLERESP)
+DECLARE_ASN1_SET_OF(OCSP_SINGLERESP)
+
+/* ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_response_data_st
+ {
+ ASN1_INTEGER *version;
+ OCSP_RESPID *responderId;
+ ASN1_GENERALIZEDTIME *producedAt;
+ STACK_OF(OCSP_SINGLERESP) *responses;
+ STACK_OF(X509_EXTENSION) *responseExtensions;
+ } OCSP_RESPDATA;
+
+/* BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+ /* Note 1:
+ The value for "signature" is specified in the OCSP rfc2560 as follows:
+ "The value for the signature SHALL be computed on the hash of the DER
+ encoding ResponseData." This means that you must hash the DER-encoded
+ tbsResponseData, and then run it through a crypto-signing function, which
+ will (at least w/RSA) do a hash-'n'-private-encrypt operation. This seems
+ a bit odd, but that's the spec. Also note that the data structures do not
+ leave anywhere to independently specify the algorithm used for the initial
+ hash. So, we look at the signature-specification algorithm, and try to do
+ something intelligent. -- Kathy Weinhold, CertCo */
+ /* Note 2:
+ It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open
+ for interpretation. I've done tests against another responder, and found
+ that it doesn't do the double hashing that the RFC seems to say one
+ should. Therefore, all relevant functions take a flag saying which
+ variant should be used. -- Richard Levitte, OpenSSL team and CeloCom */
+typedef struct ocsp_basic_response_st
+ {
+ OCSP_RESPDATA *tbsResponseData;
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+ } OCSP_BASICRESP;
+
+/*
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8) }
+ */
+#define OCSP_REVOKED_STATUS_NOSTATUS -1
+#define OCSP_REVOKED_STATUS_UNSPECIFIED 0
+#define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1
+#define OCSP_REVOKED_STATUS_CACOMPROMISE 2
+#define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3
+#define OCSP_REVOKED_STATUS_SUPERSEDED 4
+#define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5
+#define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6
+#define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8
+
+/* CrlID ::= SEQUENCE {
+ * crlUrl [0] EXPLICIT IA5String OPTIONAL,
+ * crlNum [1] EXPLICIT INTEGER OPTIONAL,
+ * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
+ */
+typedef struct ocsp_crl_id_st
+ {
+ ASN1_IA5STRING *crlUrl;
+ ASN1_INTEGER *crlNum;
+ ASN1_GENERALIZEDTIME *crlTime;
+ } OCSP_CRLID;
+
+/* ServiceLocator ::= SEQUENCE {
+ * issuer Name,
+ * locator AuthorityInfoAccessSyntax OPTIONAL }
+ */
+typedef struct ocsp_service_locator_st
+ {
+ X509_NAME* issuer;
+ STACK_OF(ACCESS_DESCRIPTION) *locator;
+ } OCSP_SERVICELOC;
+
+#define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
+#define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
+
+#define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
+
+#define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
+
+#define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL)
+
+#define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
+ (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL)
+
+#define PEM_write_bio_OCSP_REQUEST(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
+ bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_OCSP_RESPONSE(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
+ bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
+
+#define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
+
+#define OCSP_REQUEST_sign(o,pkey,md) \
+ ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ o->optionalSignature->signatureAlgorithm,NULL,\
+ o->optionalSignature->signature,o->tbsRequest,pkey,md)
+
+#define OCSP_BASICRESP_sign(o,pkey,md,d) \
+ ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\
+ o->signature,o->tbsResponseData,pkey,md)
+
+#define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ a->optionalSignature->signatureAlgorithm,\
+ a->optionalSignature->signature,a->tbsRequest,r)
+
+#define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+ a->signatureAlgorithm,a->signature,a->tbsResponseData,r)
+
+#define ASN1_BIT_STRING_digest(data,type,md,len) \
+ ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
+
+#define OCSP_CERTID_dup(cid) ASN1_dup_of(OCSP_CERTID,i2d_OCSP_CERTID,d2i_OCSP_CERTID,cid)
+
+#define OCSP_CERTSTATUS_dup(cs)\
+ (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
+ (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
+ int maxline);
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+
+OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
+ X509_NAME *issuerName,
+ ASN1_BIT_STRING* issuerKey,
+ ASN1_INTEGER *serialNumber);
+
+OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
+
+int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
+int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
+int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
+int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
+
+int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
+int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
+
+int OCSP_request_sign(OCSP_REQUEST *req,
+ X509 *signer,
+ EVP_PKEY *key,
+ const EVP_MD *dgst,
+ STACK_OF(X509) *certs,
+ unsigned long flags);
+
+int OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+
+int OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
+int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
+ int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
+ ASN1_GENERALIZEDTIME *nextupd,
+ long sec, long maxsec);
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags);
+
+int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl);
+
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+
+int OCSP_request_onereq_count(OCSP_REQUEST *req);
+OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
+OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
+int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+ ASN1_OCTET_STRING **pikeyHash,
+ ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
+ OCSP_CERTID *cid,
+ int status, int reason,
+ ASN1_TIME *revtime,
+ ASN1_TIME *thisupd, ASN1_TIME *nextupd);
+int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
+int OCSP_basic_sign(OCSP_BASICRESP *brsp,
+ X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+ STACK_OF(X509) *certs, unsigned long flags);
+
+ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
+ void *data, STACK_OF(ASN1_OBJECT) *sk);
+#define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
+ ASN1_STRING_encode(s, CHECKED_I2D_OF(type, i2d), data, sk)
+
+X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);
+
+X509_EXTENSION *OCSP_accept_responses_new(char **oids);
+
+X509_EXTENSION *OCSP_archive_cutoff_new(char* tim);
+
+X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls);
+
+int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
+int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
+int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
+X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
+void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx);
+int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
+int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
+int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
+X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
+void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
+int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
+int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
+int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
+X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
+void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx);
+int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
+int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
+X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
+void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx);
+int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
+
+DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
+DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
+DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
+DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
+
+char *OCSP_response_status_str(long s);
+char *OCSP_cert_status_str(long s);
+char *OCSP_crl_reason_str(long s);
+
+int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
+int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags);
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+ X509_STORE *st, unsigned long flags);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OCSP_strings(void);
+
+/* Error codes for the OCSP functions. */
+
+/* Function codes. */
+#define OCSP_F_ASN1_STRING_ENCODE 100
+#define OCSP_F_D2I_OCSP_NONCE 102
+#define OCSP_F_OCSP_BASIC_ADD1_STATUS 103
+#define OCSP_F_OCSP_BASIC_SIGN 104
+#define OCSP_F_OCSP_BASIC_VERIFY 105
+#define OCSP_F_OCSP_CERT_ID_NEW 101
+#define OCSP_F_OCSP_CHECK_DELEGATED 106
+#define OCSP_F_OCSP_CHECK_IDS 107
+#define OCSP_F_OCSP_CHECK_ISSUER 108
+#define OCSP_F_OCSP_CHECK_VALIDITY 115
+#define OCSP_F_OCSP_MATCH_ISSUERID 109
+#define OCSP_F_OCSP_PARSE_URL 114
+#define OCSP_F_OCSP_REQUEST_SIGN 110
+#define OCSP_F_OCSP_REQUEST_VERIFY 116
+#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111
+#define OCSP_F_OCSP_SENDREQ_BIO 112
+#define OCSP_F_PARSE_HTTP_LINE1 117
+#define OCSP_F_REQUEST_VERIFY 113
+
+/* Reason codes. */
+#define OCSP_R_BAD_DATA 100
+#define OCSP_R_CERTIFICATE_VERIFY_ERROR 101
+#define OCSP_R_DIGEST_ERR 102
+#define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122
+#define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123
+#define OCSP_R_ERROR_PARSING_URL 121
+#define OCSP_R_MISSING_OCSPSIGNING_USAGE 103
+#define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124
+#define OCSP_R_NOT_BASIC_RESPONSE 104
+#define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105
+#define OCSP_R_NO_CONTENT 106
+#define OCSP_R_NO_PUBLIC_KEY 107
+#define OCSP_R_NO_RESPONSE_DATA 108
+#define OCSP_R_NO_REVOKED_TIME 109
+#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110
+#define OCSP_R_REQUEST_NOT_SIGNED 128
+#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
+#define OCSP_R_ROOT_CA_NOT_TRUSTED 112
+#define OCSP_R_SERVER_READ_ERROR 113
+#define OCSP_R_SERVER_RESPONSE_ERROR 114
+#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115
+#define OCSP_R_SERVER_WRITE_ERROR 116
+#define OCSP_R_SIGNATURE_FAILURE 117
+#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118
+#define OCSP_R_STATUS_EXPIRED 125
+#define OCSP_R_STATUS_NOT_YET_VALID 126
+#define OCSP_R_STATUS_TOO_OLD 127
+#define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119
+#define OCSP_R_UNKNOWN_NID 120
+#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/opensslconf.h b/src/Mayaqua/win32_inc/openssl/opensslconf.h
new file mode 100644
index 00000000..48e4adf6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/opensslconf.h
@@ -0,0 +1,259 @@
+/* opensslconf.h */
+/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+
+/* OpenSSL was configured with the following options: */
+/*#ifndef OPENSSL_SYSNAME_WIN32
+# define OPENSSL_SYSNAME_WIN32
+#endif*/
+#ifndef OPENSSL_DOING_MAKEDEPEND
+
+
+#ifndef OPENSSL_NO_CAMELLIA
+# define OPENSSL_NO_CAMELLIA
+#endif
+#ifndef OPENSSL_NO_CAPIENG
+# define OPENSSL_NO_CAPIENG
+#endif
+#ifndef OPENSSL_NO_CMS
+# define OPENSSL_NO_CMS
+#endif
+#ifndef OPENSSL_NO_GMP
+# define OPENSSL_NO_GMP
+#endif
+#ifndef OPENSSL_NO_JPAKE
+# define OPENSSL_NO_JPAKE
+#endif
+#ifndef OPENSSL_NO_KRB5
+# define OPENSSL_NO_KRB5
+#endif
+#ifndef OPENSSL_NO_MDC2
+# define OPENSSL_NO_MDC2
+#endif
+#ifndef OPENSSL_NO_RC5
+# define OPENSSL_NO_RC5
+#endif
+#ifndef OPENSSL_NO_RFC3779
+# define OPENSSL_NO_RFC3779
+#endif
+#ifndef OPENSSL_NO_SEED
+# define OPENSSL_NO_SEED
+#endif
+
+#endif /* OPENSSL_DOING_MAKEDEPEND */
+
+#ifndef OPENSSL_THREADS
+# define OPENSSL_THREADS
+#endif
+
+/* The OPENSSL_NO_* macros are also defined as NO_* if the application
+ asks for it. This is a transient feature that is provided for those
+ who haven't had the time to do the appropriate changes in their
+ applications. */
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# if defined(OPENSSL_NO_CAMELLIA) && !defined(NO_CAMELLIA)
+# define NO_CAMELLIA
+# endif
+# if defined(OPENSSL_NO_CAPIENG) && !defined(NO_CAPIENG)
+# define NO_CAPIENG
+# endif
+# if defined(OPENSSL_NO_CMS) && !defined(NO_CMS)
+# define NO_CMS
+# endif
+# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP)
+# define NO_GMP
+# endif
+# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE)
+# define NO_JPAKE
+# endif
+# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5)
+# define NO_KRB5
+# endif
+# if defined(OPENSSL_NO_MDC2) && !defined(NO_MDC2)
+# define NO_MDC2
+# endif
+# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5)
+# define NO_RC5
+# endif
+# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779)
+# define NO_RFC3779
+# endif
+# if defined(OPENSSL_NO_SEED) && !defined(NO_SEED)
+# define NO_SEED
+# endif
+#endif
+
+/* crypto/opensslconf.h.in */
+
+#ifdef OPENSSL_DOING_MAKEDEPEND
+
+/* Include any symbols here that have to be explicitly set to enable a feature
+ * that should be visible to makedepend.
+ *
+ * [Our "make depend" doesn't actually look at this, we use actual build settings
+ * instead; we want to make it easy to remove subdirectories with disabled algorithms.]
+ */
+
+#ifndef OPENSSL_FIPS
+#define OPENSSL_FIPS
+#endif
+
+#endif
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */
+#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
+#define ENGINESDIR "/usr/local/ssl/lib/engines"
+#define OPENSSLDIR "/usr/local/ssl"
+#endif
+#endif
+
+#undef OPENSSL_UNISTD
+#define OPENSSL_UNISTD <unistd.h>
+
+#undef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)
+#define IDEA_INT unsigned int
+#endif
+
+#if defined(HEADER_MD2_H) && !defined(MD2_INT)
+#define MD2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC2_H) && !defined(RC2_INT)
+/* I need to put in a mod for the alpha - eay */
+#define RC2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC4_H)
+#if !defined(RC4_INT)
+/* using int types make the structure larger but make the code faster
+ * on most boxes I have tested - up to %20 faster. */
+/*
+ * I don't know what does "most" mean, but declaring "int" is a must on:
+ * - Intel P6 because partial register stalls are very expensive;
+ * - elder Alpha because it lacks byte load/store instructions;
+ */
+#define RC4_INT unsigned int
+#endif
+#if !defined(RC4_CHUNK)
+/*
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+#undef RC4_CHUNK
+#endif
+#endif
+
+#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG)
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+#define DES_LONG unsigned long
+#endif
+#endif
+
+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
+#define CONFIG_HEADER_BN_H
+#define BN_LLONG
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+/* The prime number generation stuff may not work when
+ * EIGHT_BIT but I don't care since I've only used this mode
+ * for debuging the bignum libraries */
+#undef SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#define THIRTY_TWO_BIT
+#undef SIXTEEN_BIT
+#undef EIGHT_BIT
+#endif
+
+#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+#define CONFIG_HEADER_RC4_LOCL_H
+/* if this is defined data[i] is used instead of *data, this is a %20
+ * speedup on x86 */
+#define RC4_INDEX
+#endif
+
+#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+#define CONFIG_HEADER_BF_LOCL_H
+#undef BF_PTR
+#endif /* HEADER_BF_LOCL_H */
+
+#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+#define CONFIG_HEADER_DES_LOCL_H
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#undef DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units. It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#undef DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#undef DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman <pgut001@cs.auckland.ac.nz>
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+ even newer MIPS CPU's, but at the moment one size fits all for
+ optimization options. Older Sparc's work better with only UNROLL, but
+ there's no way to tell at compile time what it is you're running on */
+
+#if defined( sun ) /* Newer Sparc's */
+# define DES_PTR
+# define DES_RISC1
+# define DES_UNROLL
+#elif defined( __ultrix ) /* Older MIPS */
+# define DES_PTR
+# define DES_RISC2
+# define DES_UNROLL
+#elif defined( __osf1__ ) /* Alpha */
+# define DES_PTR
+# define DES_RISC2
+#elif defined ( _AIX ) /* RS6000 */
+ /* Unknown */
+#elif defined( __hpux ) /* HP-PA */
+ /* Unknown */
+#elif defined( __aux ) /* 68K */
+ /* Unknown */
+#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */
+# define DES_UNROLL
+#elif defined( __sgi ) /* Newer MIPS */
+# define DES_PTR
+# define DES_RISC2
+# define DES_UNROLL
+#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */
+# define DES_PTR
+# define DES_RISC1
+# define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+#endif /* HEADER_DES_LOCL_H */
diff --git a/src/Mayaqua/win32_inc/openssl/opensslv.h b/src/Mayaqua/win32_inc/openssl/opensslv.h
new file mode 100644
index 00000000..39b504b0
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/opensslv.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_OPENSSLV_H
+#define HEADER_OPENSSLV_H
+
+/* Numeric release version identifier:
+ * MNNFFPPS: major minor fix patch status
+ * The status nibble has one of the values 0 for development, 1 to e for betas
+ * 1 to 14, and f for release. The patch level is exactly that.
+ * For example:
+ * 0.9.3-dev 0x00903000
+ * 0.9.3-beta1 0x00903001
+ * 0.9.3-beta2-dev 0x00903002
+ * 0.9.3-beta2 0x00903002 (same as ...beta2-dev)
+ * 0.9.3 0x0090300f
+ * 0.9.3a 0x0090301f
+ * 0.9.4 0x0090400f
+ * 1.2.3z 0x102031af
+ *
+ * For continuity reasons (because 0.9.5 is already out, and is coded
+ * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
+ * part is slightly different, by setting the highest bit. This means
+ * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start
+ * with 0x0090600S...
+ *
+ * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
+ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
+ * major minor fix final patch/beta)
+ */
+#define OPENSSL_VERSION_NUMBER 0x0090818fL
+#ifdef OPENSSL_FIPS
+#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x-fips 10 May 2012"
+#else
+#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x 10 May 2012"
+#endif
+#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
+
+
+/* The macros below are to be used for shared library (.so, .dll, ...)
+ * versioning. That kind of versioning works a bit differently between
+ * operating systems. The most usual scheme is to set a major and a minor
+ * number, and have the runtime loader check that the major number is equal
+ * to what it was at application link time, while the minor number has to
+ * be greater or equal to what it was at application link time. With this
+ * scheme, the version number is usually part of the file name, like this:
+ *
+ * libcrypto.so.0.9
+ *
+ * Some unixen also make a softlink with the major verson number only:
+ *
+ * libcrypto.so.0
+ *
+ * On Tru64 and IRIX 6.x it works a little bit differently. There, the
+ * shared library version is stored in the file, and is actually a series
+ * of versions, separated by colons. The rightmost version present in the
+ * library when linking an application is stored in the application to be
+ * matched at run time. When the application is run, a check is done to
+ * see if the library version stored in the application matches any of the
+ * versions in the version string of the library itself.
+ * This version string can be constructed in any way, depending on what
+ * kind of matching is desired. However, to implement the same scheme as
+ * the one used in the other unixen, all compatible versions, from lowest
+ * to highest, should be part of the string. Consecutive builds would
+ * give the following versions strings:
+ *
+ * 3.0
+ * 3.0:3.1
+ * 3.0:3.1:3.2
+ * 4.0
+ * 4.0:4.1
+ *
+ * Notice how version 4 is completely incompatible with version, and
+ * therefore give the breach you can see.
+ *
+ * There may be other schemes as well that I haven't yet discovered.
+ *
+ * So, here's the way it works here: first of all, the library version
+ * number doesn't need at all to match the overall OpenSSL version.
+ * However, it's nice and more understandable if it actually does.
+ * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
+ * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
+ * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
+ * we need to keep a history of version numbers, which is done in the
+ * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and
+ * should only keep the versions that are binary compatible with the current.
+ */
+#define SHLIB_VERSION_HISTORY ""
+#define SHLIB_VERSION_NUMBER "0.9.8"
+
+
+#endif /* HEADER_OPENSSLV_H */
diff --git a/src/Mayaqua/win32_inc/openssl/ossl_typ.h b/src/Mayaqua/win32_inc/openssl/ossl_typ.h
new file mode 100644
index 00000000..f86374f7
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ossl_typ.h
@@ -0,0 +1,183 @@
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OPENSSL_TYPES_H
+#define HEADER_OPENSSL_TYPES_H
+
+#include <openssl/e_os2.h>
+
+#ifdef NO_ASN1_TYPEDEFS
+#define ASN1_INTEGER ASN1_STRING
+#define ASN1_ENUMERATED ASN1_STRING
+#define ASN1_BIT_STRING ASN1_STRING
+#define ASN1_OCTET_STRING ASN1_STRING
+#define ASN1_PRINTABLESTRING ASN1_STRING
+#define ASN1_T61STRING ASN1_STRING
+#define ASN1_IA5STRING ASN1_STRING
+#define ASN1_UTCTIME ASN1_STRING
+#define ASN1_GENERALIZEDTIME ASN1_STRING
+#define ASN1_TIME ASN1_STRING
+#define ASN1_GENERALSTRING ASN1_STRING
+#define ASN1_UNIVERSALSTRING ASN1_STRING
+#define ASN1_BMPSTRING ASN1_STRING
+#define ASN1_VISIBLESTRING ASN1_STRING
+#define ASN1_UTF8STRING ASN1_STRING
+#define ASN1_BOOLEAN int
+#define ASN1_NULL int
+#else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef X509_CERT_PAIR
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
+#ifdef BIGNUM
+#undef BIGNUM
+#endif
+typedef struct bignum_st BIGNUM;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+
+typedef struct buf_mem_st BUF_MEM;
+
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct env_md_st EVP_MD;
+typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+
+typedef struct dh_st DH;
+typedef struct dh_method DH_METHOD;
+
+typedef struct dsa_st DSA;
+typedef struct dsa_method DSA_METHOD;
+
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+
+typedef struct rand_meth_st RAND_METHOD;
+
+typedef struct ecdh_method ECDH_METHOD;
+typedef struct ecdsa_method ECDSA_METHOD;
+
+typedef struct x509_st X509;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct X509_name_st X509_NAME;
+typedef struct x509_store_st X509_STORE;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+
+typedef struct store_st STORE;
+typedef struct store_method_st STORE_METHOD;
+
+typedef struct ui_st UI;
+typedef struct ui_method_st UI_METHOD;
+
+typedef struct st_ERR_FNS ERR_FNS;
+
+typedef struct engine_st ENGINE;
+
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+
+ /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */
+#define DECLARE_PKCS12_STACK_OF(type) /* Nothing */
+#define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Callback types for crypto.h */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
+ int idx, long argl, void *argp);
+
+typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
+typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_responder_id_st OCSP_RESPID;
+
+#endif /* def HEADER_OPENSSL_TYPES_H */
diff --git a/src/Mayaqua/win32_inc/openssl/pem.h b/src/Mayaqua/win32_inc/openssl/pem.h
new file mode 100644
index 00000000..5881ac3e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pem.h
@@ -0,0 +1,782 @@
+/* crypto/pem/pem.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PEM_H
+#define HEADER_PEM_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_STACK
+#include <openssl/stack.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PEM_BUFSIZE 1024
+
+#define PEM_OBJ_UNDEF 0
+#define PEM_OBJ_X509 1
+#define PEM_OBJ_X509_REQ 2
+#define PEM_OBJ_CRL 3
+#define PEM_OBJ_SSL_SESSION 4
+#define PEM_OBJ_PRIV_KEY 10
+#define PEM_OBJ_PRIV_RSA 11
+#define PEM_OBJ_PRIV_DSA 12
+#define PEM_OBJ_PRIV_DH 13
+#define PEM_OBJ_PUB_RSA 14
+#define PEM_OBJ_PUB_DSA 15
+#define PEM_OBJ_PUB_DH 16
+#define PEM_OBJ_DHPARAMS 17
+#define PEM_OBJ_DSAPARAMS 18
+#define PEM_OBJ_PRIV_RSA_PUBLIC 19
+#define PEM_OBJ_PRIV_ECDSA 20
+#define PEM_OBJ_PUB_ECDSA 21
+#define PEM_OBJ_ECPARAMETERS 22
+
+#define PEM_ERROR 30
+#define PEM_DEK_DES_CBC 40
+#define PEM_DEK_IDEA_CBC 45
+#define PEM_DEK_DES_EDE 50
+#define PEM_DEK_DES_ECB 60
+#define PEM_DEK_RSA 70
+#define PEM_DEK_RSA_MD2 80
+#define PEM_DEK_RSA_MD5 90
+
+#define PEM_MD_MD2 NID_md2
+#define PEM_MD_MD5 NID_md5
+#define PEM_MD_SHA NID_sha
+#define PEM_MD_MD2_RSA NID_md2WithRSAEncryption
+#define PEM_MD_MD5_RSA NID_md5WithRSAEncryption
+#define PEM_MD_SHA_RSA NID_sha1WithRSAEncryption
+
+#define PEM_STRING_X509_OLD "X509 CERTIFICATE"
+#define PEM_STRING_X509 "CERTIFICATE"
+#define PEM_STRING_X509_PAIR "CERTIFICATE PAIR"
+#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
+#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
+#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
+#define PEM_STRING_X509_CRL "X509 CRL"
+#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
+#define PEM_STRING_PUBLIC "PUBLIC KEY"
+#define PEM_STRING_RSA "RSA PRIVATE KEY"
+#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY"
+#define PEM_STRING_DSA "DSA PRIVATE KEY"
+#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY"
+#define PEM_STRING_PKCS7 "PKCS7"
+#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
+#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY"
+#define PEM_STRING_PKCS8INF "PRIVATE KEY"
+#define PEM_STRING_DHPARAMS "DH PARAMETERS"
+#define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS"
+#define PEM_STRING_DSAPARAMS "DSA PARAMETERS"
+#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
+#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
+#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
+#define PEM_STRING_CMS "CMS"
+
+ /* Note that this structure is initialised by PEM_SealInit and cleaned up
+ by PEM_SealFinal (at least for now) */
+typedef struct PEM_Encode_Seal_st
+ {
+ EVP_ENCODE_CTX encode;
+ EVP_MD_CTX md;
+ EVP_CIPHER_CTX cipher;
+ } PEM_ENCODE_SEAL_CTX;
+
+/* enc_type is one off */
+#define PEM_TYPE_ENCRYPTED 10
+#define PEM_TYPE_MIC_ONLY 20
+#define PEM_TYPE_MIC_CLEAR 30
+#define PEM_TYPE_CLEAR 40
+
+typedef struct pem_recip_st
+ {
+ char *name;
+ X509_NAME *dn;
+
+ int cipher;
+ int key_enc;
+ /* char iv[8]; unused and wrong size */
+ } PEM_USER;
+
+typedef struct pem_ctx_st
+ {
+ int type; /* what type of object */
+
+ struct {
+ int version;
+ int mode;
+ } proc_type;
+
+ char *domain;
+
+ struct {
+ int cipher;
+ /* unused, and wrong size
+ unsigned char iv[8]; */
+ } DEK_info;
+
+ PEM_USER *originator;
+
+ int num_recipient;
+ PEM_USER **recipient;
+
+#ifndef OPENSSL_NO_STACK
+ STACK *x509_chain; /* certificate chain */
+#else
+ char *x509_chain; /* certificate chain */
+#endif
+ EVP_MD *md; /* signature type */
+
+ int md_enc; /* is the md encrypted or not? */
+ int md_len; /* length of md_data */
+ char *md_data; /* message digest, could be pkey encrypted */
+
+ EVP_CIPHER *dec; /* date encryption cipher */
+ int key_len; /* key length */
+ unsigned char *key; /* key */
+ /* unused, and wrong size
+ unsigned char iv[8]; */
+
+
+ int data_enc; /* is the data encrypted */
+ int data_len;
+ unsigned char *data;
+ } PEM_CTX;
+
+/* These macros make the PEM_read/PEM_write functions easier to maintain and
+ * write. Now they are all implemented with either:
+ * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...)
+ */
+
+#ifdef OPENSSL_NO_FP_API
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
+
+#else
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
+{ \
+ return (type*)PEM_ASN1_read(CHECKED_D2I_OF(type, d2i_##asn1), \
+ str, fp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u); \
+}
+
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x) \
+{ \
+ return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, const type *x) \
+{ \
+ return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(const type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+ { \
+ return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+ { \
+ return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(const type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#endif
+
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
+{ \
+ return (type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i_##asn1), \
+ str, bp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u); \
+}
+
+#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x) \
+{ \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, const type *x) \
+{ \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(const type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(const type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_fp_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_read_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb(name, type, str, asn1)
+
+/* These are the same except they are for the declarations */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_NO_FP_API)
+
+#define DECLARE_PEM_read_fp(name, type) /**/
+#define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_fp_const(name, type) /**/
+#define DECLARE_PEM_write_cb_fp(name, type) /**/
+
+#else
+
+#define DECLARE_PEM_read_fp(name, type) \
+ type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_fp(name, type) \
+ int PEM_write_##name(FILE *fp, type *x);
+
+#define DECLARE_PEM_write_fp_const(name, type) \
+ int PEM_write_##name(FILE *fp, const type *x);
+
+#define DECLARE_PEM_write_cb_fp(name, type) \
+ int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#define DECLARE_PEM_read_bio(name, type) \
+ type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_bio(name, type) \
+ int PEM_write_bio_##name(BIO *bp, type *x);
+
+#define DECLARE_PEM_write_bio_const(name, type) \
+ int PEM_write_bio_##name(BIO *bp, const type *x);
+
+#define DECLARE_PEM_write_cb_bio(name, type) \
+ int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#else
+
+#define DECLARE_PEM_read_bio(name, type) /**/
+#define DECLARE_PEM_write_bio(name, type) /**/
+#define DECLARE_PEM_write_bio_const(name, type) /**/
+#define DECLARE_PEM_write_cb_bio(name, type) /**/
+
+#endif
+
+#define DECLARE_PEM_write(name, type) \
+ DECLARE_PEM_write_bio(name, type) \
+ DECLARE_PEM_write_fp(name, type)
+
+#define DECLARE_PEM_write_const(name, type) \
+ DECLARE_PEM_write_bio_const(name, type) \
+ DECLARE_PEM_write_fp_const(name, type)
+
+#define DECLARE_PEM_write_cb(name, type) \
+ DECLARE_PEM_write_cb_bio(name, type) \
+ DECLARE_PEM_write_cb_fp(name, type)
+
+#define DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_read_bio(name, type) \
+ DECLARE_PEM_read_fp(name, type)
+
+#define DECLARE_PEM_rw(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write(name, type)
+
+#define DECLARE_PEM_rw_const(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write_const(name, type)
+
+#define DECLARE_PEM_rw_cb(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write_cb(name, type)
+
+#ifdef SSLEAY_MACROS
+
+#define PEM_write_SSL_SESSION(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+ PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_REQ(fp,x) PEM_ASN1_write( \
+ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x, \
+ NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_CRL(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, \
+ fp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp,\
+ (char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_RSAPublicKey(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_RSAPublicKey,\
+ PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp,\
+ (char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_PrivateKey,\
+ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_PKCS7(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_DHparams(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp,\
+ (char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_NETSCAPE_CERT_SEQUENCE(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+ PEM_STRING_X509,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+ (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u)
+#define PEM_read_X509_REQ(fp,x,cb,u) (X509_REQ *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb,u)
+#define PEM_read_X509_CRL(fp,x,cb,u) (X509_CRL *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb,u)
+#define PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u)
+#define PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u)
+#define PEM_read_DSAPrivateKey(fp,x,cb,u) (DSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb,u)
+#define PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \
+ (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u)
+#define PEM_read_PKCS7(fp,x,cb,u) (PKCS7 *)PEM_ASN1_read( \
+ (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb,u)
+#define PEM_read_DHparams(fp,x,cb,u) (DH *)PEM_ASN1_read( \
+ (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb,u)
+
+#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb,u) \
+ (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read( \
+ (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,fp,\
+ (char **)x,cb,u)
+
+#define PEM_write_bio_X509(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_REQ(bp,x) PEM_ASN1_write_bio( \
+ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x, \
+ NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_CRL(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,\
+ bp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_RSAPublicKey(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, \
+ PEM_STRING_RSA_PUBLIC,\
+ bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_PrivateKey,\
+ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_PKCS7(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DHparams(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,\
+ bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DSAparams(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_DSAparams, \
+ PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+ PEM_STRING_X509,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define PEM_read_bio_X509(bp,x,cb,u) (X509 *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb,u)
+#define PEM_read_bio_X509_REQ(bp,x,cb,u) (X509_REQ *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb,u)
+#define PEM_read_bio_X509_CRL(bp,x,cb,u) (X509_CRL *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb,u)
+#define PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u)
+#define PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u)
+#define PEM_read_bio_DSAPrivateKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb,u)
+#define PEM_read_bio_PrivateKey(bp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb,u)
+
+#define PEM_read_bio_PKCS7(bp,x,cb,u) (PKCS7 *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb,u)
+#define PEM_read_bio_DHparams(bp,x,cb,u) (DH *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb,u)
+#define PEM_read_bio_DSAparams(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb,u)
+
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb,u) \
+ (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,bp,\
+ (char **)x,cb,u)
+
+#endif
+
+#if 1
+/* "userdata": new with OpenSSL 0.9.4 */
+typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+#else
+/* OpenSSL 0.9.3, 0.9.3a */
+typedef int pem_password_cb(char *buf, int size, int rwflag);
+#endif
+
+int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
+int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len,
+ pem_password_cb *callback,void *u);
+
+#ifndef OPENSSL_NO_BIO
+int PEM_read_bio(BIO *bp, char **name, char **header,
+ unsigned char **data,long *len);
+int PEM_write_bio(BIO *bp,const char *name,char *hdr,unsigned char *data,
+ long len);
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
+ pem_password_cb *cb, void *u);
+void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp,
+ void **x, pem_password_cb *cb, void *u);
+
+#define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
+ ((type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i), \
+ name, bp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u))
+
+int PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp,char *x,
+ const EVP_CIPHER *enc,unsigned char *kstr,int klen,
+ pem_password_cb *cb, void *u);
+
+#define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr,klen,cb,u) \
+ (PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d), \
+ name, bp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u))
+
+STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
+int PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
+ unsigned char *kstr, int klen, pem_password_cb *cd, void *u);
+#endif
+
+#ifndef OPENSSL_SYS_WIN16
+int PEM_read(FILE *fp, char **name, char **header,
+ unsigned char **data,long *len);
+int PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len);
+void * PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
+ pem_password_cb *cb, void *u);
+int PEM_ASN1_write(i2d_of_void *i2d,const char *name,FILE *fp,
+ char *x,const EVP_CIPHER *enc,unsigned char *kstr,
+ int klen,pem_password_cb *callback, void *u);
+STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u);
+#endif
+
+int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
+ EVP_MD *md_type, unsigned char **ek, int *ekl,
+ unsigned char *iv, EVP_PKEY **pubk, int npubk);
+void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl,
+ unsigned char *in, int inl);
+int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig,int *sigl,
+ unsigned char *out, int *outl, EVP_PKEY *priv);
+
+void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
+void PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt);
+int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
+ unsigned int *siglen, EVP_PKEY *pkey);
+
+int PEM_def_callback(char *buf, int num, int w, void *key);
+void PEM_proc_type(char *buf, int type);
+void PEM_dek_info(char *buf, const char *type, int len, char *str);
+
+#ifndef SSLEAY_MACROS
+
+#include <openssl/symhacks.h>
+
+DECLARE_PEM_rw(X509, X509)
+
+DECLARE_PEM_rw(X509_AUX, X509)
+
+DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR)
+
+DECLARE_PEM_rw(X509_REQ, X509_REQ)
+DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
+
+DECLARE_PEM_rw(X509_CRL, X509_CRL)
+
+DECLARE_PEM_rw(PKCS7, PKCS7)
+
+DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
+
+DECLARE_PEM_rw(PKCS8, X509_SIG)
+
+DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+#ifndef OPENSSL_NO_RSA
+
+DECLARE_PEM_rw_cb(RSAPrivateKey, RSA)
+
+DECLARE_PEM_rw_const(RSAPublicKey, RSA)
+DECLARE_PEM_rw(RSA_PUBKEY, RSA)
+
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+DECLARE_PEM_rw_cb(DSAPrivateKey, DSA)
+
+DECLARE_PEM_rw(DSA_PUBKEY, DSA)
+
+DECLARE_PEM_rw_const(DSAparams, DSA)
+
+#endif
+
+#ifndef OPENSSL_NO_EC
+DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
+DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
+DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
+#endif
+
+#ifndef OPENSSL_NO_DH
+
+DECLARE_PEM_rw_const(DHparams, DH)
+
+#endif
+
+DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
+
+DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+
+int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
+ char *, int, pem_password_cb *, void *);
+int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+
+EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
+ char *kstr,int klen, pem_password_cb *cd, void *u);
+
+#endif /* SSLEAY_MACROS */
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PEM_strings(void);
+
+/* Error codes for the PEM functions. */
+
+/* Function codes. */
+#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120
+#define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121
+#define PEM_F_DO_PK8PKEY 126
+#define PEM_F_DO_PK8PKEY_FP 125
+#define PEM_F_LOAD_IV 101
+#define PEM_F_PEM_ASN1_READ 102
+#define PEM_F_PEM_ASN1_READ_BIO 103
+#define PEM_F_PEM_ASN1_WRITE 104
+#define PEM_F_PEM_ASN1_WRITE_BIO 105
+#define PEM_F_PEM_DEF_CALLBACK 100
+#define PEM_F_PEM_DO_HEADER 106
+#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118
+#define PEM_F_PEM_GET_EVP_CIPHER_INFO 107
+#define PEM_F_PEM_PK8PKEY 119
+#define PEM_F_PEM_READ 108
+#define PEM_F_PEM_READ_BIO 109
+#define PEM_F_PEM_READ_BIO_PRIVATEKEY 123
+#define PEM_F_PEM_READ_PRIVATEKEY 124
+#define PEM_F_PEM_SEALFINAL 110
+#define PEM_F_PEM_SEALINIT 111
+#define PEM_F_PEM_SIGNFINAL 112
+#define PEM_F_PEM_WRITE 113
+#define PEM_F_PEM_WRITE_BIO 114
+#define PEM_F_PEM_X509_INFO_READ 115
+#define PEM_F_PEM_X509_INFO_READ_BIO 116
+#define PEM_F_PEM_X509_INFO_WRITE_BIO 117
+
+/* Reason codes. */
+#define PEM_R_BAD_BASE64_DECODE 100
+#define PEM_R_BAD_DECRYPT 101
+#define PEM_R_BAD_END_LINE 102
+#define PEM_R_BAD_IV_CHARS 103
+#define PEM_R_BAD_PASSWORD_READ 104
+#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
+#define PEM_R_NOT_DEK_INFO 105
+#define PEM_R_NOT_ENCRYPTED 106
+#define PEM_R_NOT_PROC_TYPE 107
+#define PEM_R_NO_START_LINE 108
+#define PEM_R_PROBLEMS_GETTING_PASSWORD 109
+#define PEM_R_PUBLIC_KEY_NO_RSA 110
+#define PEM_R_READ_KEY 111
+#define PEM_R_SHORT_HEADER 112
+#define PEM_R_UNSUPPORTED_CIPHER 113
+#define PEM_R_UNSUPPORTED_ENCRYPTION 114
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pem2.h b/src/Mayaqua/win32_inc/openssl/pem2.h
new file mode 100644
index 00000000..97ba68aa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pem2.h
@@ -0,0 +1,70 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This header only exists to break a circular dependency between pem and err
+ * Ben 30 Jan 1999.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HEADER_PEM_H
+void ERR_load_PEM_strings(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pkcs12.h b/src/Mayaqua/win32_inc/openssl/pkcs12.h
new file mode 100644
index 00000000..3f45ee60
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pkcs12.h
@@ -0,0 +1,338 @@
+/* pkcs12.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PKCS12_H
+#define HEADER_PKCS12_H
+
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKCS12_KEY_ID 1
+#define PKCS12_IV_ID 2
+#define PKCS12_MAC_ID 3
+
+/* Default iteration count */
+#ifndef PKCS12_DEFAULT_ITER
+#define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER
+#endif
+
+#define PKCS12_MAC_KEY_LENGTH 20
+
+#define PKCS12_SALT_LEN 8
+
+/* Uncomment out next line for unicode password and names, otherwise ASCII */
+
+/*#define PBE_UNICODE*/
+
+#ifdef PBE_UNICODE
+#define PKCS12_key_gen PKCS12_key_gen_uni
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni
+#else
+#define PKCS12_key_gen PKCS12_key_gen_asc
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc
+#endif
+
+/* MS key usage constants */
+
+#define KEY_EX 0x10
+#define KEY_SIG 0x80
+
+typedef struct {
+X509_SIG *dinfo;
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter; /* defaults to 1 */
+} PKCS12_MAC_DATA;
+
+typedef struct {
+ASN1_INTEGER *version;
+PKCS12_MAC_DATA *mac;
+PKCS7 *authsafes;
+} PKCS12;
+
+PREDECLARE_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct {
+ASN1_OBJECT *type;
+union {
+ struct pkcs12_bag_st *bag; /* secret, crl and certbag */
+ struct pkcs8_priv_key_info_st *keybag; /* keybag */
+ X509_SIG *shkeybag; /* shrouded key bag */
+ STACK_OF(PKCS12_SAFEBAG) *safes;
+ ASN1_TYPE *other;
+}value;
+STACK_OF(X509_ATTRIBUTE) *attrib;
+} PKCS12_SAFEBAG;
+
+DECLARE_STACK_OF(PKCS12_SAFEBAG)
+DECLARE_ASN1_SET_OF(PKCS12_SAFEBAG)
+DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct pkcs12_bag_st {
+ASN1_OBJECT *type;
+union {
+ ASN1_OCTET_STRING *x509cert;
+ ASN1_OCTET_STRING *x509crl;
+ ASN1_OCTET_STRING *octet;
+ ASN1_IA5STRING *sdsicert;
+ ASN1_TYPE *other; /* Secret or other bag */
+}value;
+} PKCS12_BAGS;
+
+#define PKCS12_ERROR 0
+#define PKCS12_OK 1
+
+/* Compatibility macros */
+
+#define M_PKCS12_x5092certbag PKCS12_x5092certbag
+#define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag
+
+#define M_PKCS12_certbag2x509 PKCS12_certbag2x509
+#define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl
+
+#define M_PKCS12_unpack_p7data PKCS12_unpack_p7data
+#define M_PKCS12_pack_authsafes PKCS12_pack_authsafes
+#define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes
+#define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata
+
+#define M_PKCS12_decrypt_skey PKCS12_decrypt_skey
+#define M_PKCS8_decrypt PKCS8_decrypt
+
+#define M_PKCS12_bag_type(bg) OBJ_obj2nid((bg)->type)
+#define M_PKCS12_cert_bag_type(bg) OBJ_obj2nid((bg)->value.bag->type)
+#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type
+
+#define PKCS12_get_attr(bag, attr_nid) \
+ PKCS12_get_attr_gen(bag->attrib, attr_nid)
+
+#define PKCS8_get_attr(p8, attr_nid) \
+ PKCS12_get_attr_gen(p8->attributes, attr_nid)
+
+#define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0)
+
+
+PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509);
+PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl);
+X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag);
+X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag);
+
+PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1,
+ int nid2);
+PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, const char *pass,
+ int passlen);
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8);
+PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass,
+ int passlen, unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8);
+PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, int passlen);
+
+int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes);
+STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12);
+
+int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen);
+int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name,
+ int namelen);
+int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage);
+ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid);
+char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
+unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass,
+ int passlen, unsigned char *in, int inlen,
+ unsigned char **data, int *datalen, int en_de);
+void * PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen, ASN1_OCTET_STRING *oct, int zbuf);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf);
+PKCS12 *PKCS12_init(int mode);
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type);
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md_type,
+ int en_de);
+int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *mac, unsigned int *maclen);
+int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *md_type);
+int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+ int saltlen, const EVP_MD *md_type);
+#if defined(NETWARE) || defined(OPENSSL_SYS_NETWARE)
+/* Rename these functions to avoid name clashes on NetWare OS */
+unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen);
+char *OPENSSL_uni2asc(unsigned char *uni, int unilen);
+#else
+unsigned char *asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen);
+char *uni2asc(unsigned char *uni, int unilen);
+#endif
+DECLARE_ASN1_FUNCTIONS(PKCS12)
+DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)
+DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG)
+DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS)
+
+DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS)
+DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
+
+void PKCS12_PBE_add(void);
+int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+ STACK_OF(X509) **ca);
+PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
+ STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
+ int mac_iter, int keytype);
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
+ int key_usage, int iter,
+ int key_nid, char *pass);
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, char *pass);
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+
+int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
+int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
+PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
+PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS12_strings(void);
+
+/* Error codes for the PKCS12 functions. */
+
+/* Function codes. */
+#define PKCS12_F_PARSE_BAG 129
+#define PKCS12_F_PARSE_BAGS 103
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME 100
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC 127
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI 102
+#define PKCS12_F_PKCS12_ADD_LOCALKEYID 104
+#define PKCS12_F_PKCS12_CREATE 105
+#define PKCS12_F_PKCS12_GEN_MAC 107
+#define PKCS12_F_PKCS12_INIT 109
+#define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106
+#define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108
+#define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117
+#define PKCS12_F_PKCS12_KEY_GEN_ASC 110
+#define PKCS12_F_PKCS12_KEY_GEN_UNI 111
+#define PKCS12_F_PKCS12_MAKE_KEYBAG 112
+#define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113
+#define PKCS12_F_PKCS12_NEWPASS 128
+#define PKCS12_F_PKCS12_PACK_P7DATA 114
+#define PKCS12_F_PKCS12_PACK_P7ENCDATA 115
+#define PKCS12_F_PKCS12_PARSE 118
+#define PKCS12_F_PKCS12_PBE_CRYPT 119
+#define PKCS12_F_PKCS12_PBE_KEYIVGEN 120
+#define PKCS12_F_PKCS12_SETUP_MAC 122
+#define PKCS12_F_PKCS12_SET_MAC 123
+#define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130
+#define PKCS12_F_PKCS12_UNPACK_P7DATA 131
+#define PKCS12_F_PKCS12_VERIFY_MAC 126
+#define PKCS12_F_PKCS8_ADD_KEYUSAGE 124
+#define PKCS12_F_PKCS8_ENCRYPT 125
+
+/* Reason codes. */
+#define PKCS12_R_CANT_PACK_STRUCTURE 100
+#define PKCS12_R_CONTENT_TYPE_NOT_DATA 121
+#define PKCS12_R_DECODE_ERROR 101
+#define PKCS12_R_ENCODE_ERROR 102
+#define PKCS12_R_ENCRYPT_ERROR 103
+#define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120
+#define PKCS12_R_INVALID_NULL_ARGUMENT 104
+#define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105
+#define PKCS12_R_IV_GEN_ERROR 106
+#define PKCS12_R_KEY_GEN_ERROR 107
+#define PKCS12_R_MAC_ABSENT 108
+#define PKCS12_R_MAC_GENERATION_ERROR 109
+#define PKCS12_R_MAC_SETUP_ERROR 110
+#define PKCS12_R_MAC_STRING_SET_ERROR 111
+#define PKCS12_R_MAC_VERIFY_ERROR 112
+#define PKCS12_R_MAC_VERIFY_FAILURE 113
+#define PKCS12_R_PARSE_ERROR 114
+#define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115
+#define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116
+#define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117
+#define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118
+#define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pkcs7.h b/src/Mayaqua/win32_inc/openssl/pkcs7.h
new file mode 100644
index 00000000..eeb05324
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pkcs7.h
@@ -0,0 +1,464 @@
+/* crypto/pkcs7/pkcs7.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PKCS7_H
+#define HEADER_PKCS7_H
+
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/e_os2.h>
+
+#include <openssl/symhacks.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 thes are defined in wincrypt.h */
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#endif
+
+/*
+Encryption_ID DES-CBC
+Digest_ID MD5
+Digest_Encryption_ID rsaEncryption
+Key_Encryption_ID rsaEncryption
+*/
+
+typedef struct pkcs7_issuer_and_serial_st
+ {
+ X509_NAME *issuer;
+ ASN1_INTEGER *serial;
+ } PKCS7_ISSUER_AND_SERIAL;
+
+typedef struct pkcs7_signer_info_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *digest_alg;
+ STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
+ X509_ALGOR *digest_enc_alg;
+ ASN1_OCTET_STRING *enc_digest;
+ STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
+
+ /* The private key to sign with */
+ EVP_PKEY *pkey;
+ } PKCS7_SIGNER_INFO;
+
+DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO)
+
+typedef struct pkcs7_recip_info_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *key_enc_algor;
+ ASN1_OCTET_STRING *enc_key;
+ X509 *cert; /* get the pub-key from this */
+ } PKCS7_RECIP_INFO;
+
+DECLARE_STACK_OF(PKCS7_RECIP_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO)
+
+typedef struct pkcs7_signed_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+
+ struct pkcs7_st *contents;
+ } PKCS7_SIGNED;
+/* The above structure is very very similar to PKCS7_SIGN_ENVELOPE.
+ * How about merging the two */
+
+typedef struct pkcs7_enc_content_st
+ {
+ ASN1_OBJECT *content_type;
+ X509_ALGOR *algorithm;
+ ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
+ const EVP_CIPHER *cipher;
+ } PKCS7_ENC_CONTENT;
+
+typedef struct pkcs7_enveloped_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+ PKCS7_ENC_CONTENT *enc_data;
+ } PKCS7_ENVELOPE;
+
+typedef struct pkcs7_signedandenveloped_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+
+ PKCS7_ENC_CONTENT *enc_data;
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+ } PKCS7_SIGN_ENVELOPE;
+
+typedef struct pkcs7_digest_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ X509_ALGOR *md; /* md used */
+ struct pkcs7_st *contents;
+ ASN1_OCTET_STRING *digest;
+ } PKCS7_DIGEST;
+
+typedef struct pkcs7_encrypted_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ENC_CONTENT *enc_data;
+ } PKCS7_ENCRYPT;
+
+typedef struct pkcs7_st
+ {
+ /* The following is non NULL if it contains ASN1 encoding of
+ * this structure */
+ unsigned char *asn1;
+ long length;
+
+#define PKCS7_S_HEADER 0
+#define PKCS7_S_BODY 1
+#define PKCS7_S_TAIL 2
+ int state; /* used during processing */
+
+ int detached;
+
+ ASN1_OBJECT *type;
+ /* content as defined by the type */
+ /* all encryption/message digests are applied to the 'contents',
+ * leaving out the 'type' field. */
+ union {
+ char *ptr;
+
+ /* NID_pkcs7_data */
+ ASN1_OCTET_STRING *data;
+
+ /* NID_pkcs7_signed */
+ PKCS7_SIGNED *sign;
+
+ /* NID_pkcs7_enveloped */
+ PKCS7_ENVELOPE *enveloped;
+
+ /* NID_pkcs7_signedAndEnveloped */
+ PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
+
+ /* NID_pkcs7_digest */
+ PKCS7_DIGEST *digest;
+
+ /* NID_pkcs7_encrypted */
+ PKCS7_ENCRYPT *encrypted;
+
+ /* Anything else */
+ ASN1_TYPE *other;
+ } d;
+ } PKCS7;
+
+DECLARE_STACK_OF(PKCS7)
+DECLARE_ASN1_SET_OF(PKCS7)
+DECLARE_PKCS12_STACK_OF(PKCS7)
+
+#define PKCS7_OP_SET_DETACHED_SIGNATURE 1
+#define PKCS7_OP_GET_DETACHED_SIGNATURE 2
+
+#define PKCS7_get_signed_attributes(si) ((si)->auth_attr)
+#define PKCS7_get_attributes(si) ((si)->unauth_attr)
+
+#define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
+#define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+#define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped)
+#define PKCS7_type_is_signedAndEnveloped(a) \
+ (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
+#define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
+
+#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
+
+#define PKCS7_set_detached(p,v) \
+ PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
+#define PKCS7_get_detached(p) \
+ PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
+
+#define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+
+#ifdef SSLEAY_MACROS
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+ (char *)data,md,len)
+#endif
+#endif
+
+/* S/MIME related flags */
+
+#define PKCS7_TEXT 0x1
+#define PKCS7_NOCERTS 0x2
+#define PKCS7_NOSIGS 0x4
+#define PKCS7_NOCHAIN 0x8
+#define PKCS7_NOINTERN 0x10
+#define PKCS7_NOVERIFY 0x20
+#define PKCS7_DETACHED 0x40
+#define PKCS7_BINARY 0x80
+#define PKCS7_NOATTR 0x100
+#define PKCS7_NOSMIMECAP 0x200
+#define PKCS7_NOOLDMIMETYPE 0x400
+#define PKCS7_CRLFEOL 0x800
+#define PKCS7_STREAM 0x1000
+#define PKCS7_NOCRL 0x2000
+
+/* Flags: for compatibility with older code */
+
+#define SMIME_TEXT PKCS7_TEXT
+#define SMIME_NOCERTS PKCS7_NOCERTS
+#define SMIME_NOSIGS PKCS7_NOSIGS
+#define SMIME_NOCHAIN PKCS7_NOCHAIN
+#define SMIME_NOINTERN PKCS7_NOINTERN
+#define SMIME_NOVERIFY PKCS7_NOVERIFY
+#define SMIME_DETACHED PKCS7_DETACHED
+#define SMIME_BINARY PKCS7_BINARY
+#define SMIME_NOATTR PKCS7_NOATTR
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
+
+#ifndef SSLEAY_MACROS
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type,
+ unsigned char *md,unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+PKCS7 *d2i_PKCS7_fp(FILE *fp,PKCS7 **p7);
+int i2d_PKCS7_fp(FILE *fp,PKCS7 *p7);
+#endif
+PKCS7 *PKCS7_dup(PKCS7 *p7);
+PKCS7 *d2i_PKCS7_bio(BIO *bp,PKCS7 **p7);
+int i2d_PKCS7_bio(BIO *bp,PKCS7 *p7);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
+DECLARE_ASN1_FUNCTIONS(PKCS7)
+
+DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
+DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
+
+DECLARE_ASN1_NDEF_FUNCTION(PKCS7)
+
+long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg);
+
+int PKCS7_set_type(PKCS7 *p7, int type);
+int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other);
+int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data);
+int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
+ const EVP_MD *dgst);
+int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i);
+int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
+int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
+int PKCS7_content_new(PKCS7 *p7, int nid);
+int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
+ BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
+ X509 *x509);
+
+BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
+int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert);
+
+
+PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
+ EVP_PKEY *pkey, const EVP_MD *dgst);
+X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
+STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
+
+PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
+int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
+int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
+int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
+
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si,int nid,int type,
+ void *data);
+int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+ void *value);
+ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
+int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
+ STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk);
+
+
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags);
+int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
+ BIO *indata, BIO *out, int flags);
+STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+ int flags);
+int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags);
+
+int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
+ STACK_OF(X509_ALGOR) *cap);
+STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si);
+int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg);
+
+int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS7_strings(void);
+
+/* Error codes for the PKCS7 functions. */
+
+/* Function codes. */
+#define PKCS7_F_B64_READ_PKCS7 120
+#define PKCS7_F_B64_WRITE_PKCS7 121
+#define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118
+#define PKCS7_F_PKCS7_ADD_CERTIFICATE 100
+#define PKCS7_F_PKCS7_ADD_CRL 101
+#define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102
+#define PKCS7_F_PKCS7_ADD_SIGNER 103
+#define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125
+#define PKCS7_F_PKCS7_CTRL 104
+#define PKCS7_F_PKCS7_DATADECODE 112
+#define PKCS7_F_PKCS7_DATAFINAL 128
+#define PKCS7_F_PKCS7_DATAINIT 105
+#define PKCS7_F_PKCS7_DATASIGN 106
+#define PKCS7_F_PKCS7_DATAVERIFY 107
+#define PKCS7_F_PKCS7_DECRYPT 114
+#define PKCS7_F_PKCS7_ENCRYPT 115
+#define PKCS7_F_PKCS7_FIND_DIGEST 127
+#define PKCS7_F_PKCS7_GET0_SIGNERS 124
+#define PKCS7_F_PKCS7_SET_CIPHER 108
+#define PKCS7_F_PKCS7_SET_CONTENT 109
+#define PKCS7_F_PKCS7_SET_DIGEST 126
+#define PKCS7_F_PKCS7_SET_TYPE 110
+#define PKCS7_F_PKCS7_SIGN 116
+#define PKCS7_F_PKCS7_SIGNATUREVERIFY 113
+#define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119
+#define PKCS7_F_PKCS7_VERIFY 117
+#define PKCS7_F_SMIME_READ_PKCS7 122
+#define PKCS7_F_SMIME_TEXT 123
+
+/* Reason codes. */
+#define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117
+#define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144
+#define PKCS7_R_CIPHER_NOT_INITIALIZED 116
+#define PKCS7_R_CONTENT_AND_DATA_PRESENT 118
+#define PKCS7_R_DECODE_ERROR 130
+#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100
+#define PKCS7_R_DECRYPT_ERROR 119
+#define PKCS7_R_DIGEST_FAILURE 101
+#define PKCS7_R_ERROR_ADDING_RECIPIENT 120
+#define PKCS7_R_ERROR_SETTING_CIPHER 121
+#define PKCS7_R_INVALID_MIME_TYPE 131
+#define PKCS7_R_INVALID_NULL_POINTER 143
+#define PKCS7_R_MIME_NO_CONTENT_TYPE 132
+#define PKCS7_R_MIME_PARSE_ERROR 133
+#define PKCS7_R_MIME_SIG_PARSE_ERROR 134
+#define PKCS7_R_MISSING_CERIPEND_INFO 103
+#define PKCS7_R_NO_CONTENT 122
+#define PKCS7_R_NO_CONTENT_TYPE 135
+#define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136
+#define PKCS7_R_NO_MULTIPART_BOUNDARY 137
+#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115
+#define PKCS7_R_NO_RECIPIENT_MATCHES_KEY 146
+#define PKCS7_R_NO_SIGNATURES_ON_DATA 123
+#define PKCS7_R_NO_SIGNERS 142
+#define PKCS7_R_NO_SIG_CONTENT_TYPE 138
+#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104
+#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124
+#define PKCS7_R_PKCS7_DATAFINAL 126
+#define PKCS7_R_PKCS7_DATAFINAL_ERROR 125
+#define PKCS7_R_PKCS7_DATASIGN 145
+#define PKCS7_R_PKCS7_PARSE_ERROR 139
+#define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140
+#define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127
+#define PKCS7_R_SIGNATURE_FAILURE 105
+#define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128
+#define PKCS7_R_SIG_INVALID_MIME_TYPE 141
+#define PKCS7_R_SMIME_TEXT_ERROR 129
+#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106
+#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107
+#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108
+#define PKCS7_R_UNKNOWN_DIGEST_TYPE 109
+#define PKCS7_R_UNKNOWN_OPERATION 110
+#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111
+#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112
+#define PKCS7_R_WRONG_CONTENT_TYPE 113
+#define PKCS7_R_WRONG_PKCS7_TYPE 114
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pq_compat.h b/src/Mayaqua/win32_inc/openssl/pq_compat.h
new file mode 100644
index 00000000..27a585fb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pq_compat.h
@@ -0,0 +1,152 @@
+/* crypto/pqueue/pqueue_compat.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PQ_COMPAT_H
+#define HEADER_PQ_COMPAT_H
+
+#include <openssl/opensslconf.h>
+#include <openssl/bn.h>
+
+/*
+ * The purpose of this header file is for supporting 64-bit integer
+ * manipulation on 32-bit (and lower) machines. Currently the only
+ * such environment is VMS, Utrix and those with smaller default integer
+ * sizes than 32 bits. For all such environment, we fall back to using
+ * BIGNUM. We may need to fine tune the conditions for systems that
+ * are incorrectly configured.
+ *
+ * The only clients of this code are (1) pqueue for priority, and
+ * (2) DTLS, for sequence number manipulation.
+ */
+
+#if (defined(THIRTY_TWO_BIT) && !defined(BN_LLONG)) || defined(SIXTEEN_BIT) || defined(EIGHT_BIT)
+
+#define PQ_64BIT_IS_INTEGER 0
+#define PQ_64BIT_IS_BIGNUM 1
+
+#define PQ_64BIT BIGNUM
+#define PQ_64BIT_CTX BN_CTX
+
+#define pq_64bit_init(x) BN_init(x)
+#define pq_64bit_free(x) BN_free(x)
+
+#define pq_64bit_ctx_new(ctx) BN_CTX_new()
+#define pq_64bit_ctx_free(x) BN_CTX_free(x)
+
+#define pq_64bit_assign(x, y) BN_copy(x, y)
+#define pq_64bit_assign_word(x, y) BN_set_word(x, y)
+#define pq_64bit_gt(x, y) BN_ucmp(x, y) >= 1 ? 1 : 0
+#define pq_64bit_eq(x, y) BN_ucmp(x, y) == 0 ? 1 : 0
+#define pq_64bit_add_word(x, w) BN_add_word(x, w)
+#define pq_64bit_sub(r, x, y) BN_sub(r, x, y)
+#define pq_64bit_sub_word(x, w) BN_sub_word(x, w)
+#define pq_64bit_mod(r, x, n, ctx) BN_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(bn, bytes, len) BN_bin2bn(bytes, len, bn)
+#define pq_64bit_num2bin(bn, bytes) BN_bn2bin(bn, bytes)
+#define pq_64bit_get_word(x) BN_get_word(x)
+#define pq_64bit_is_bit_set(x, offset) BN_is_bit_set(x, offset)
+#define pq_64bit_lshift(r, x, shift) BN_lshift(r, x, shift)
+#define pq_64bit_set_bit(x, num) BN_set_bit(x, num)
+#define pq_64bit_get_length(x) BN_num_bits((x))
+
+#else
+
+#define PQ_64BIT_IS_INTEGER 1
+#define PQ_64BIT_IS_BIGNUM 0
+
+#if defined(SIXTY_FOUR_BIT)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%lld"
+#elif defined(SIXTY_FOUR_BIT_LONG)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%ld"
+#elif defined(THIRTY_TWO_BIT)
+#define PQ_64BIT BN_ULLONG
+#define PQ_64BIT_PRINT "%lld"
+#endif
+
+#define PQ_64BIT_CTX void
+
+#define pq_64bit_init(x)
+#define pq_64bit_free(x)
+#define pq_64bit_ctx_new(ctx) (ctx)
+#define pq_64bit_ctx_free(x)
+
+#define pq_64bit_assign(x, y) (*(x) = *(y))
+#define pq_64bit_assign_word(x, y) (*(x) = y)
+#define pq_64bit_gt(x, y) (*(x) > *(y))
+#define pq_64bit_eq(x, y) (*(x) == *(y))
+#define pq_64bit_add_word(x, w) (*(x) = (*(x) + (w)))
+#define pq_64bit_sub(r, x, y) (*(r) = (*(x) - *(y)))
+#define pq_64bit_sub_word(x, w) (*(x) = (*(x) - (w)))
+#define pq_64bit_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(num, bytes, len) bytes_to_long_long(bytes, num)
+#define pq_64bit_num2bin(num, bytes) long_long_to_bytes(num, bytes)
+#define pq_64bit_get_word(x) *(x)
+#define pq_64bit_lshift(r, x, shift) (*(r) = (*(x) << (shift)))
+#define pq_64bit_set_bit(x, num) do { \
+ PQ_64BIT mask = 1; \
+ mask = mask << (num); \
+ *(x) |= mask; \
+ } while(0)
+#endif /* OPENSSL_SYS_VMS */
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pqueue.h b/src/Mayaqua/win32_inc/openssl/pqueue.h
new file mode 100644
index 00000000..12b607dc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pqueue.h
@@ -0,0 +1,96 @@
+/* crypto/pqueue/pqueue.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PQUEUE_H
+#define HEADER_PQUEUE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/pq_compat.h>
+
+typedef struct _pqueue *pqueue;
+
+typedef struct _pitem
+ {
+ PQ_64BIT priority;
+ void *data;
+ struct _pitem *next;
+ } pitem;
+
+typedef struct _pitem *piterator;
+
+pitem *pitem_new(PQ_64BIT priority, void *data);
+void pitem_free(pitem *item);
+
+pqueue pqueue_new(void);
+void pqueue_free(pqueue pq);
+
+pitem *pqueue_insert(pqueue pq, pitem *item);
+pitem *pqueue_peek(pqueue pq);
+pitem *pqueue_pop(pqueue pq);
+pitem *pqueue_find(pqueue pq, PQ_64BIT priority);
+pitem *pqueue_iterator(pqueue pq);
+pitem *pqueue_next(piterator *iter);
+
+void pqueue_print(pqueue pq);
+int pqueue_size(pqueue pq);
+
+#endif /* ! HEADER_PQUEUE_H */
diff --git a/src/Mayaqua/win32_inc/openssl/rand.h b/src/Mayaqua/win32_inc/openssl/rand.h
new file mode 100644
index 00000000..07aabc07
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rand.h
@@ -0,0 +1,167 @@
+/* crypto/rand/rand.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RAND_H
+#define HEADER_RAND_H
+
+#include <stdlib.h>
+#include <openssl/ossl_typ.h>
+#include <openssl/e_os2.h>
+
+#if defined(OPENSSL_SYS_WINDOWS)
+#include <windows.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_RAND_SIZE_T int
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct rand_meth_st RAND_METHOD; */
+
+struct rand_meth_st
+ {
+ void (*seed)(const void *buf, int num);
+ int (*bytes)(unsigned char *buf, int num);
+ void (*cleanup)(void);
+ void (*add)(const void *buf, int num, double entropy);
+ int (*pseudorand)(unsigned char *buf, int num);
+ int (*status)(void);
+ };
+
+#ifdef BN_DEBUG
+extern int rand_predictable;
+#endif
+
+int RAND_set_rand_method(const RAND_METHOD *meth);
+const RAND_METHOD *RAND_get_rand_method(void);
+#ifndef OPENSSL_NO_ENGINE
+int RAND_set_rand_engine(ENGINE *engine);
+#endif
+RAND_METHOD *RAND_SSLeay(void);
+void RAND_cleanup(void );
+int RAND_bytes(unsigned char *buf,int num);
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+void RAND_seed(const void *buf,int num);
+void RAND_add(const void *buf,int num,double entropy);
+int RAND_load_file(const char *file,long max_bytes);
+int RAND_write_file(const char *file);
+const char *RAND_file_name(char *file,size_t num);
+int RAND_status(void);
+int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes);
+int RAND_egd(const char *path);
+int RAND_egd_bytes(const char *path,int bytes);
+int RAND_poll(void);
+#ifndef OPENSSL_NO_ENGINE
+#ifdef OPENSSL_FIPS
+void int_RAND_init_engine_callbacks(void);
+void int_RAND_set_callbacks(
+ int (*set_rand_func)(const RAND_METHOD *meth,
+ const RAND_METHOD **pmeth),
+ const RAND_METHOD *(*get_rand_func)(const RAND_METHOD **pmeth));
+#endif
+#endif
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+
+void RAND_screen(void);
+int RAND_event(UINT, WPARAM, LPARAM);
+
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RAND_strings(void);
+
+/* Error codes for the RAND functions. */
+
+/* Function codes. */
+#define RAND_F_ENG_RAND_GET_RAND_METHOD 108
+#define RAND_F_FIPS_RAND 103
+#define RAND_F_FIPS_RAND_BYTES 102
+#define RAND_F_FIPS_RAND_GET_RAND_METHOD 109
+#define RAND_F_FIPS_RAND_SET_DT 106
+#define RAND_F_FIPS_SET_DT 104
+#define RAND_F_FIPS_SET_PRNG_SEED 107
+#define RAND_F_FIPS_SET_TEST_MODE 105
+#define RAND_F_RAND_GET_RAND_METHOD 101
+#define RAND_F_SSLEAY_RAND_BYTES 100
+
+/* Reason codes. */
+#define RAND_R_NON_FIPS_METHOD 105
+#define RAND_R_NOT_IN_TEST_MODE 106
+#define RAND_R_NO_KEY_SET 107
+#define RAND_R_PRNG_ASKING_FOR_TOO_MUCH 101
+#define RAND_R_PRNG_ERROR 108
+#define RAND_R_PRNG_KEYED 109
+#define RAND_R_PRNG_NOT_REKEYED 102
+#define RAND_R_PRNG_NOT_RESEEDED 103
+#define RAND_R_PRNG_NOT_SEEDED 100
+#define RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY 110
+#define RAND_R_PRNG_STUCK 104
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc2.h b/src/Mayaqua/win32_inc/openssl/rc2.h
new file mode 100644
index 00000000..cf0876e3
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc2.h
@@ -0,0 +1,103 @@
+/* crypto/rc2/rc2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC2_H
+#define HEADER_RC2_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_RC2, RC2_INT */
+#ifdef OPENSSL_NO_RC2
+#error RC2 is disabled.
+#endif
+
+#define RC2_ENCRYPT 1
+#define RC2_DECRYPT 0
+
+#define RC2_BLOCK 8
+#define RC2_KEY_LENGTH 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc2_key_st
+ {
+ RC2_INT data[64];
+ } RC2_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+#endif
+void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+void RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key,
+ int enc);
+void RC2_encrypt(unsigned long *data,RC2_KEY *key);
+void RC2_decrypt(unsigned long *data,RC2_KEY *key);
+void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ RC2_KEY *ks, unsigned char *iv, int enc);
+void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC2_KEY *schedule, unsigned char *ivec,
+ int *num, int enc);
+void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC2_KEY *schedule, unsigned char *ivec,
+ int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc4.h b/src/Mayaqua/win32_inc/openssl/rc4.h
new file mode 100644
index 00000000..f598804b
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc4.h
@@ -0,0 +1,90 @@
+/* crypto/rc4/rc4.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC4_H
+#define HEADER_RC4_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_RC4, RC4_INT */
+#ifdef OPENSSL_NO_RC4
+#error RC4 is disabled.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc4_key_st
+ {
+ RC4_INT x,y;
+ RC4_INT data[256];
+ } RC4_KEY;
+
+
+const char *RC4_options(void);
+#ifdef OPENSSL_FIPS
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+#endif
+void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
+ unsigned char *outdata);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc5.h b/src/Mayaqua/win32_inc/openssl/rc5.h
new file mode 100644
index 00000000..ea227272
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc5.h
@@ -0,0 +1,120 @@
+/* crypto/rc5/rc5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC5_H
+#define HEADER_RC5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RC5
+#error RC5 is disabled.
+#endif
+
+#define RC5_ENCRYPT 1
+#define RC5_DECRYPT 0
+
+/* 32 bit. For Alpha, things may get weird */
+#define RC5_32_INT unsigned long
+
+#define RC5_32_BLOCK 8
+#define RC5_32_KEY_LENGTH 16 /* This is a default, max is 255 */
+
+/* This are the only values supported. Tweak the code if you want more
+ * The most supported modes will be
+ * RC5-32/12/16
+ * RC5-32/16/8
+ */
+#define RC5_8_ROUNDS 8
+#define RC5_12_ROUNDS 12
+#define RC5_16_ROUNDS 16
+
+typedef struct rc5_key_st
+ {
+ /* Number of rounds */
+ int rounds;
+ RC5_32_INT data[2*(RC5_16_ROUNDS+1)];
+ } RC5_32_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+ int rounds);
+#endif
+void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+ int rounds);
+void RC5_32_ecb_encrypt(const unsigned char *in,unsigned char *out,RC5_32_KEY *key,
+ int enc);
+void RC5_32_encrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_decrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *ks, unsigned char *iv,
+ int enc);
+void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num, int enc);
+void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ripemd.h b/src/Mayaqua/win32_inc/openssl/ripemd.h
new file mode 100644
index 00000000..af7eca59
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ripemd.h
@@ -0,0 +1,106 @@
+/* crypto/ripemd/ripemd.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RIPEMD_H
+#define HEADER_RIPEMD_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RIPEMD
+#error RIPEMD is disabled.
+#endif
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define RIPEMD160_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define RIPEMD160_LONG unsigned long
+#define RIPEMD160_LONG_LOG2 3
+#else
+#define RIPEMD160_LONG unsigned int
+#endif
+
+#define RIPEMD160_CBLOCK 64
+#define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
+#define RIPEMD160_DIGEST_LENGTH 20
+
+typedef struct RIPEMD160state_st
+ {
+ RIPEMD160_LONG A,B,C,D,E;
+ RIPEMD160_LONG Nl,Nh;
+ RIPEMD160_LONG data[RIPEMD160_LBLOCK];
+ unsigned int num;
+ } RIPEMD160_CTX;
+#ifdef OPENSSL_FIPS
+int private_RIPEMD160_Init(RIPEMD160_CTX *c);
+#endif
+int RIPEMD160_Init(RIPEMD160_CTX *c);
+int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len);
+int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
+unsigned char *RIPEMD160(const unsigned char *d, size_t n,
+ unsigned char *md);
+void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rsa.h b/src/Mayaqua/win32_inc/openssl/rsa.h
new file mode 100644
index 00000000..8e5e1b8d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rsa.h
@@ -0,0 +1,496 @@
+/* crypto/rsa/rsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RSA_H
+#define HEADER_RSA_H
+
+#include <openssl/asn1.h>
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef OPENSSL_NO_RSA
+#error RSA is disabled.
+#endif
+
+/* If this flag is set the RSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define RSA_FLAG_FIPS_METHOD 0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define RSA_FLAG_NON_FIPS_ALLOW 0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_RSA_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct rsa_st RSA; */
+/* typedef struct rsa_meth_st RSA_METHOD; */
+
+struct rsa_meth_st
+ {
+ const char *name;
+ int (*rsa_pub_enc)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_pub_dec)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_priv_enc)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_priv_dec)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa,BN_CTX *ctx); /* Can be null */
+ int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+ int (*init)(RSA *rsa); /* called at new */
+ int (*finish)(RSA *rsa); /* called at free */
+ int flags; /* RSA_METHOD_FLAG_* things */
+ char *app_data; /* may be needed! */
+/* New sign and verify functions: some libraries don't allow arbitrary data
+ * to be signed/verified: this allows them to be used. Note: for this to work
+ * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used
+ * RSA_sign(), RSA_verify() should be used instead. Note: for backwards
+ * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER
+ * option is set in 'flags'.
+ */
+ int (*rsa_sign)(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+ int (*rsa_verify)(int dtype,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
+/* If this callback is NULL, the builtin software RSA key-gen will be used. This
+ * is for behavioural compatibility whilst the code gets rewired, but one day
+ * it would be nice to assume there are no such things as "builtin software"
+ * implementations. */
+ int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+ };
+
+struct rsa_st
+ {
+ /* The first parameter is used to pickup errors where
+ * this is passed instead of aEVP_PKEY, it is set to 0 */
+ int pad;
+ long version;
+ const RSA_METHOD *meth;
+ /* functional reference if 'meth' is ENGINE-provided */
+ ENGINE *engine;
+ BIGNUM *n;
+ BIGNUM *e;
+ BIGNUM *d;
+ BIGNUM *p;
+ BIGNUM *q;
+ BIGNUM *dmp1;
+ BIGNUM *dmq1;
+ BIGNUM *iqmp;
+ /* be careful using this if the RSA structure is shared */
+ CRYPTO_EX_DATA ex_data;
+ int references;
+ int flags;
+
+ /* Used to cache montgomery values */
+ BN_MONT_CTX *_method_mod_n;
+ BN_MONT_CTX *_method_mod_p;
+ BN_MONT_CTX *_method_mod_q;
+
+ /* all BIGNUM values are actually in the following data, if it is not
+ * NULL */
+ char *bignum_data;
+ BN_BLINDING *blinding;
+ BN_BLINDING *mt_blinding;
+ };
+
+#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
+# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
+#endif
+
+#define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
+
+#ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
+# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
+#endif
+#ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */
+#endif
+
+#define RSA_3 0x3L
+#define RSA_F4 0x10001L
+
+#define RSA_METHOD_FLAG_NO_CHECK 0x0001 /* don't check pub/private match */
+
+#define RSA_FLAG_CACHE_PUBLIC 0x0002
+#define RSA_FLAG_CACHE_PRIVATE 0x0004
+#define RSA_FLAG_BLINDING 0x0008
+#define RSA_FLAG_THREAD_SAFE 0x0010
+/* This flag means the private key operations will be handled by rsa_mod_exp
+ * and that they do not depend on the private key components being present:
+ * for example a key stored in external hardware. Without this flag bn_mod_exp
+ * gets called when private key components are absent.
+ */
+#define RSA_FLAG_EXT_PKEY 0x0020
+
+/* This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions.
+ */
+#define RSA_FLAG_SIGN_VER 0x0040
+
+#define RSA_FLAG_NO_BLINDING 0x0080 /* new with 0.9.6j and 0.9.7b; the built-in
+ * RSA implementation now uses blinding by
+ * default (ignoring RSA_FLAG_BLINDING),
+ * but other engines might not need it
+ */
+#define RSA_FLAG_NO_CONSTTIME 0x0100 /* new with 0.9.8f; the built-in RSA
+ * implementation now uses constant time
+ * operations by default in private key operations,
+ * e.g., constant time modular exponentiation,
+ * modular inverse without leaking branches,
+ * division without leaking branches. This
+ * flag disables these constant time
+ * operations and results in faster RSA
+ * private key operations.
+ */
+#ifndef OPENSSL_NO_DEPRECATED
+#define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME /* deprecated name for the flag*/
+ /* new with 0.9.7h; the built-in RSA
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+#endif
+
+
+#define RSA_PKCS1_PADDING 1
+#define RSA_SSLV23_PADDING 2
+#define RSA_NO_PADDING 3
+#define RSA_PKCS1_OAEP_PADDING 4
+#define RSA_X931_PADDING 5
+
+#define RSA_PKCS1_PADDING_SIZE 11
+
+#define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg)
+#define RSA_get_app_data(s) RSA_get_ex_data(s,0)
+
+RSA * RSA_new(void);
+RSA * RSA_new_method(ENGINE *engine);
+int RSA_size(const RSA *);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+RSA * RSA_generate_key(int bits, unsigned long e,void
+ (*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+ const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+ const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+ const BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BN_GENCB *cb);
+
+int RSA_check_key(const RSA *);
+ /* next 4 return -1 on error */
+int RSA_public_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_private_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_public_decrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_private_decrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+void RSA_free (RSA *r);
+/* "up" the RSA object's reference count */
+int RSA_up_ref(RSA *r);
+
+int RSA_flags(const RSA *r);
+
+#ifdef OPENSSL_FIPS
+RSA *FIPS_rsa_new(void);
+void FIPS_rsa_free(RSA *r);
+#endif
+
+void RSA_set_default_method(const RSA_METHOD *meth);
+const RSA_METHOD *RSA_get_default_method(void);
+const RSA_METHOD *RSA_get_method(const RSA *rsa);
+int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
+
+/* This function needs the memory locking malloc callbacks to be installed */
+int RSA_memory_lock(RSA *r);
+
+/* these are the actual SSLeay RSA functions */
+const RSA_METHOD *RSA_PKCS1_SSLeay(void);
+
+const RSA_METHOD *RSA_null_method(void);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
+
+#ifndef OPENSSL_NO_FP_API
+int RSA_print_fp(FILE *fp, const RSA *r,int offset);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int RSA_print(BIO *bp, const RSA *r,int offset);
+#endif
+
+#ifndef OPENSSL_NO_RC4
+int i2d_RSA_NET(const RSA *a, unsigned char **pp,
+ int (*cb)(char *buf, int len, const char *prompt, int verify),
+ int sgckey);
+RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
+ int (*cb)(char *buf, int len, const char *prompt, int verify),
+ int sgckey);
+
+int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
+ int (*cb)(char *buf, int len, const char *prompt,
+ int verify));
+RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
+ int (*cb)(char *buf, int len, const char *prompt,
+ int verify));
+#endif
+
+/* The following 2 functions sign and verify a X509_SIG ASN1 object
+ * inside PKCS#1 padded RSA encryption */
+int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+/* The following 2 function sign and verify a ASN1_OCTET_STRING
+ * object inside PKCS#1 padded RSA encryption */
+int RSA_sign_ASN1_OCTET_STRING(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify_ASN1_OCTET_STRING(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
+void RSA_blinding_off(RSA *rsa);
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+
+int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_PKCS1_type_2(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int PKCS1_MGF1(unsigned char *mask, long len,
+ const unsigned char *seed, long seedlen, const EVP_MD *dgst);
+int RSA_padding_add_PKCS1_OAEP(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,
+ const unsigned char *p,int pl);
+int RSA_padding_check_PKCS1_OAEP(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len,
+ const unsigned char *p,int pl);
+int RSA_padding_add_SSLv23(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_SSLv23(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_none(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_none(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_X931(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_X931(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_X931_hash_id(int nid);
+
+int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
+ const EVP_MD *Hash, const unsigned char *EM, int sLen);
+int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
+ const unsigned char *mHash,
+ const EVP_MD *Hash, int sLen);
+
+int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int RSA_set_ex_data(RSA *r,int idx,void *arg);
+void *RSA_get_ex_data(const RSA *r, int idx);
+
+RSA *RSAPublicKey_dup(RSA *rsa);
+RSA *RSAPrivateKey_dup(RSA *rsa);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RSA_strings(void);
+
+/* Error codes for the RSA functions. */
+
+/* Function codes. */
+#define RSA_F_FIPS_RSA_SIGN 140
+#define RSA_F_FIPS_RSA_VERIFY 141
+#define RSA_F_MEMORY_LOCK 100
+#define RSA_F_RSA_BUILTIN_KEYGEN 129
+#define RSA_F_RSA_CHECK_KEY 123
+#define RSA_F_RSA_EAY_PRIVATE_DECRYPT 101
+#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 102
+#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103
+#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104
+#define RSA_F_RSA_GENERATE_KEY 105
+#define RSA_F_RSA_MEMORY_LOCK 130
+#define RSA_F_RSA_NEW_METHOD 106
+#define RSA_F_RSA_NULL 124
+#define RSA_F_RSA_NULL_MOD_EXP 131
+#define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132
+#define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133
+#define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134
+#define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135
+#define RSA_F_RSA_PADDING_ADD_NONE 107
+#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121
+#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109
+#define RSA_F_RSA_PADDING_ADD_SSLV23 110
+#define RSA_F_RSA_PADDING_ADD_X931 127
+#define RSA_F_RSA_PADDING_CHECK_NONE 111
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113
+#define RSA_F_RSA_PADDING_CHECK_SSLV23 114
+#define RSA_F_RSA_PADDING_CHECK_X931 128
+#define RSA_F_RSA_PRINT 115
+#define RSA_F_RSA_PRINT_FP 116
+#define RSA_F_RSA_PRIVATE_ENCRYPT 137
+#define RSA_F_RSA_PUBLIC_DECRYPT 138
+#define RSA_F_RSA_SETUP_BLINDING 136
+#define RSA_F_RSA_SET_DEFAULT_METHOD 139
+#define RSA_F_RSA_SET_METHOD 142
+#define RSA_F_RSA_SIGN 117
+#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118
+#define RSA_F_RSA_VERIFY 119
+#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120
+#define RSA_F_RSA_VERIFY_PKCS1_PSS 126
+
+/* Reason codes. */
+#define RSA_R_ALGORITHM_MISMATCH 100
+#define RSA_R_BAD_E_VALUE 101
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102
+#define RSA_R_BAD_PAD_BYTE_COUNT 103
+#define RSA_R_BAD_SIGNATURE 104
+#define RSA_R_BLOCK_TYPE_IS_NOT_01 106
+#define RSA_R_BLOCK_TYPE_IS_NOT_02 107
+#define RSA_R_DATA_GREATER_THAN_MOD_LEN 108
+#define RSA_R_DATA_TOO_LARGE 109
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132
+#define RSA_R_DATA_TOO_SMALL 111
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112
+#define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124
+#define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1 123
+#define RSA_R_FIRST_OCTET_INVALID 133
+#define RSA_R_INVALID_HEADER 137
+#define RSA_R_INVALID_MESSAGE_LENGTH 131
+#define RSA_R_INVALID_PADDING 138
+#define RSA_R_INVALID_TRAILER 139
+#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
+#define RSA_R_KEY_SIZE_TOO_SMALL 120
+#define RSA_R_LAST_OCTET_INVALID 134
+#define RSA_R_MODULUS_TOO_LARGE 105
+#define RSA_R_NON_FIPS_METHOD 141
+#define RSA_R_NO_PUBLIC_EXPONENT 140
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
+#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
+#define RSA_R_OAEP_DECODING_ERROR 121
+#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 142
+#define RSA_R_PADDING_CHECK_FAILED 114
+#define RSA_R_P_NOT_PRIME 128
+#define RSA_R_Q_NOT_PRIME 129
+#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130
+#define RSA_R_SLEN_CHECK_FAILED 136
+#define RSA_R_SLEN_RECOVERY_FAILED 135
+#define RSA_R_SSLV3_ROLLBACK_ATTACK 115
+#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE 117
+#define RSA_R_UNKNOWN_PADDING_TYPE 118
+#define RSA_R_WRONG_SIGNATURE_LENGTH 119
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/safestack.h b/src/Mayaqua/win32_inc/openssl/safestack.h
new file mode 100644
index 00000000..54c82031
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/safestack.h
@@ -0,0 +1,1986 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SAFESTACK_H
+#define HEADER_SAFESTACK_H
+
+#include <openssl/stack.h>
+
+#ifdef DEBUG_SAFESTACK
+
+#ifndef CHECKED_PTR_OF
+#define CHECKED_PTR_OF(type, p) \
+ ((void*) (1 ? p : (type*)0))
+#endif
+
+#define CHECKED_SK_FREE_FUNC(type, p) \
+ ((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))
+
+#define CHECKED_SK_CMP_FUNC(type, p) \
+ ((int (*)(const char * const *, const char * const *)) \
+ ((1 ? p : (int (*)(const type * const *, const type * const *))0)))
+
+#define STACK_OF(type) struct stack_st_##type
+#define PREDECLARE_STACK_OF(type) STACK_OF(type);
+
+#define DECLARE_STACK_OF(type) \
+STACK_OF(type) \
+ { \
+ STACK stack; \
+ };
+
+#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/
+
+/* SKM_sk_... stack macros are internal to safestack.h:
+ * never use them directly, use sk_<type>_... instead */
+#define SKM_sk_new(type, cmp) \
+ ((STACK_OF(type) *)sk_new(CHECKED_SK_CMP_FUNC(type, cmp)))
+#define SKM_sk_new_null(type) \
+ ((STACK_OF(type) *)sk_new_null())
+#define SKM_sk_free(type, st) \
+ sk_free(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_num(type, st) \
+ sk_num(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_value(type, st,i) \
+ ((type *)sk_value(CHECKED_PTR_OF(STACK_OF(type), st), i))
+#define SKM_sk_set(type, st,i,val) \
+ sk_set(CHECKED_PTR_OF(STACK_OF(type), st), i, CHECKED_PTR_OF(type, val))
+#define SKM_sk_zero(type, st) \
+ sk_zero(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_push(type, st,val) \
+ sk_push(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_unshift(type, st,val) \
+ sk_unshift(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_find(type, st,val) \
+ sk_find(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_delete(type, st,i) \
+ (type *)sk_delete(CHECKED_PTR_OF(STACK_OF(type), st), i)
+#define SKM_sk_delete_ptr(type, st,ptr) \
+ (type *)sk_delete_ptr(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, ptr))
+#define SKM_sk_insert(type, st,val,i) \
+ sk_insert(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val), i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+ ((int (*)(const type * const *,const type * const *)) \
+ sk_set_cmp_func(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_CMP_FUNC(type, cmp)))
+#define SKM_sk_dup(type, st) \
+ (STACK_OF(type) *)sk_dup(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_pop_free(type, st,free_func) \
+ sk_pop_free(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_FREE_FUNC(type, free_func))
+#define SKM_sk_shift(type, st) \
+ (type *)sk_shift(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_pop(type, st) \
+ (type *)sk_pop(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_sort(type, st) \
+ sk_sort(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_is_sorted(type, st) \
+ sk_is_sorted(CHECKED_PTR_OF(STACK_OF(type), st))
+
+#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ (STACK_OF(type) *)d2i_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type)*, st), \
+ pp, length, \
+ CHECKED_D2I_OF(type, d2i_func), \
+ CHECKED_SK_FREE_FUNC(type, free_func), \
+ ex_tag, ex_class)
+
+#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ i2d_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type), st), pp, \
+ CHECKED_I2D_OF(type, i2d_func), \
+ ex_tag, ex_class, is_set)
+
+#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+ ASN1_seq_pack(CHECKED_PTR_OF(STACK_OF(type), st), \
+ CHECKED_I2D_OF(type, i2d_func), buf, len)
+
+#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+ (STACK_OF(type) *)ASN1_seq_unpack(buf, len, CHECKED_D2I_OF(type, d2i_func), CHECKED_SK_FREE_FUNC(type, free_func))
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ (STACK_OF(type) *)PKCS12_decrypt_d2i(algor, \
+ CHECKED_D2I_OF(type, d2i_func), \
+ CHECKED_SK_FREE_FUNC(type, free_func), \
+ pass, passlen, oct, seq)
+
+#else
+
+#define STACK_OF(type) STACK
+#define PREDECLARE_STACK_OF(type) /* nada */
+#define DECLARE_STACK_OF(type) /* nada */
+#define IMPLEMENT_STACK_OF(type) /* nada */
+
+#define SKM_sk_new(type, cmp) \
+ sk_new((int (*)(const char * const *, const char * const *))(cmp))
+#define SKM_sk_new_null(type) \
+ sk_new_null()
+#define SKM_sk_free(type, st) \
+ sk_free(st)
+#define SKM_sk_num(type, st) \
+ sk_num(st)
+#define SKM_sk_value(type, st,i) \
+ ((type *)sk_value(st, i))
+#define SKM_sk_set(type, st,i,val) \
+ ((type *)sk_set(st, i,(char *)val))
+#define SKM_sk_zero(type, st) \
+ sk_zero(st)
+#define SKM_sk_push(type, st,val) \
+ sk_push(st, (char *)val)
+#define SKM_sk_unshift(type, st,val) \
+ sk_unshift(st, (char *)val)
+#define SKM_sk_find(type, st,val) \
+ sk_find(st, (char *)val)
+#define SKM_sk_delete(type, st,i) \
+ ((type *)sk_delete(st, i))
+#define SKM_sk_delete_ptr(type, st,ptr) \
+ ((type *)sk_delete_ptr(st,(char *)ptr))
+#define SKM_sk_insert(type, st,val,i) \
+ sk_insert(st, (char *)val, i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+ ((int (*)(const type * const *,const type * const *)) \
+ sk_set_cmp_func(st, (int (*)(const char * const *, const char * const *))(cmp)))
+#define SKM_sk_dup(type, st) \
+ sk_dup(st)
+#define SKM_sk_pop_free(type, st,free_func) \
+ sk_pop_free(st, (void (*)(void *))free_func)
+#define SKM_sk_shift(type, st) \
+ ((type *)sk_shift(st))
+#define SKM_sk_pop(type, st) \
+ ((type *)sk_pop(st))
+#define SKM_sk_sort(type, st) \
+ sk_sort(st)
+#define SKM_sk_is_sorted(type, st) \
+ sk_is_sorted(st)
+
+#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ d2i_ASN1_SET(st,pp,length, (void *(*)(void ** ,const unsigned char ** ,long))d2i_func, (void (*)(void *))free_func, ex_tag,ex_class)
+#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ i2d_ASN1_SET(st,pp,(int (*)(void *, unsigned char **))i2d_func,ex_tag,ex_class,is_set)
+
+#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+ ASN1_seq_pack(st, (int (*)(void *, unsigned char **))i2d_func, buf, len)
+#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+ ASN1_seq_unpack(buf,len,(void *(*)(void **,const unsigned char **,long))d2i_func, (void(*)(void *))free_func)
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ ((STACK *)PKCS12_decrypt_d2i(algor,(char *(*)())d2i_func, (void(*)(void *))free_func,pass,passlen,oct,seq))
+
+#endif
+
+/* This block of defines is updated by util/mkstack.pl, please do not touch! */
+#define sk_ACCESS_DESCRIPTION_new(st) SKM_sk_new(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION)
+#define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val))
+#define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find_ex(st, val) SKM_sk_find_ex(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr))
+#define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i))
+#define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp))
+#define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st)
+#define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func))
+#define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st))
+
+#define sk_ASIdOrRange_new(st) SKM_sk_new(ASIdOrRange, (st))
+#define sk_ASIdOrRange_new_null() SKM_sk_new_null(ASIdOrRange)
+#define sk_ASIdOrRange_free(st) SKM_sk_free(ASIdOrRange, (st))
+#define sk_ASIdOrRange_num(st) SKM_sk_num(ASIdOrRange, (st))
+#define sk_ASIdOrRange_value(st, i) SKM_sk_value(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_set(st, i, val) SKM_sk_set(ASIdOrRange, (st), (i), (val))
+#define sk_ASIdOrRange_zero(st) SKM_sk_zero(ASIdOrRange, (st))
+#define sk_ASIdOrRange_push(st, val) SKM_sk_push(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_unshift(st, val) SKM_sk_unshift(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find(st, val) SKM_sk_find(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find_ex(st, val) SKM_sk_find_ex(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_delete(st, i) SKM_sk_delete(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASIdOrRange, (st), (ptr))
+#define sk_ASIdOrRange_insert(st, val, i) SKM_sk_insert(ASIdOrRange, (st), (val), (i))
+#define sk_ASIdOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASIdOrRange, (st), (cmp))
+#define sk_ASIdOrRange_dup(st) SKM_sk_dup(ASIdOrRange, st)
+#define sk_ASIdOrRange_pop_free(st, free_func) SKM_sk_pop_free(ASIdOrRange, (st), (free_func))
+#define sk_ASIdOrRange_shift(st) SKM_sk_shift(ASIdOrRange, (st))
+#define sk_ASIdOrRange_pop(st) SKM_sk_pop(ASIdOrRange, (st))
+#define sk_ASIdOrRange_sort(st) SKM_sk_sort(ASIdOrRange, (st))
+#define sk_ASIdOrRange_is_sorted(st) SKM_sk_is_sorted(ASIdOrRange, (st))
+
+#define sk_ASN1_GENERALSTRING_new(st) SKM_sk_new(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING)
+#define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val))
+#define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find_ex(st, val) SKM_sk_find_ex(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr))
+#define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i))
+#define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp))
+#define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st)
+#define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func))
+#define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st))
+
+#define sk_ASN1_INTEGER_new(st) SKM_sk_new(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER)
+#define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val))
+#define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find_ex(st, val) SKM_sk_find_ex(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr))
+#define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i))
+#define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp))
+#define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st)
+#define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func))
+#define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st))
+
+#define sk_ASN1_OBJECT_new(st) SKM_sk_new(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT)
+#define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val))
+#define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find_ex(st, val) SKM_sk_find_ex(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr))
+#define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i))
+#define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp))
+#define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st)
+#define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func))
+#define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st))
+
+#define sk_ASN1_STRING_TABLE_new(st) SKM_sk_new(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE)
+#define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val))
+#define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find_ex(st, val) SKM_sk_find_ex(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr))
+#define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i))
+#define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp))
+#define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st)
+#define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func))
+#define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st))
+
+#define sk_ASN1_TYPE_new(st) SKM_sk_new(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE)
+#define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val))
+#define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find_ex(st, val) SKM_sk_find_ex(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr))
+#define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i))
+#define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp))
+#define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st)
+#define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func))
+#define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st))
+
+#define sk_ASN1_VALUE_new(st) SKM_sk_new(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE)
+#define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val))
+#define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find_ex(st, val) SKM_sk_find_ex(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr))
+#define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i))
+#define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp))
+#define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st)
+#define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func))
+#define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st))
+
+#define sk_BIO_new(st) SKM_sk_new(BIO, (st))
+#define sk_BIO_new_null() SKM_sk_new_null(BIO)
+#define sk_BIO_free(st) SKM_sk_free(BIO, (st))
+#define sk_BIO_num(st) SKM_sk_num(BIO, (st))
+#define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i))
+#define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val))
+#define sk_BIO_zero(st) SKM_sk_zero(BIO, (st))
+#define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val))
+#define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val))
+#define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val))
+#define sk_BIO_find_ex(st, val) SKM_sk_find_ex(BIO, (st), (val))
+#define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i))
+#define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr))
+#define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i))
+#define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp))
+#define sk_BIO_dup(st) SKM_sk_dup(BIO, st)
+#define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func))
+#define sk_BIO_shift(st) SKM_sk_shift(BIO, (st))
+#define sk_BIO_pop(st) SKM_sk_pop(BIO, (st))
+#define sk_BIO_sort(st) SKM_sk_sort(BIO, (st))
+#define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st))
+
+#define sk_CMS_CertificateChoices_new(st) SKM_sk_new(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices)
+#define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i))
+#define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val))
+#define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_find(st, val) SKM_sk_find(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_find_ex(st, val) SKM_sk_find_ex(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_delete(st, i) SKM_sk_delete(CMS_CertificateChoices, (st), (i))
+#define sk_CMS_CertificateChoices_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_CertificateChoices, (st), (ptr))
+#define sk_CMS_CertificateChoices_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i))
+#define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp))
+#define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(CMS_CertificateChoices, st)
+#define sk_CMS_CertificateChoices_pop_free(st, free_func) SKM_sk_pop_free(CMS_CertificateChoices, (st), (free_func))
+#define sk_CMS_CertificateChoices_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st))
+
+#define sk_CMS_RecipientInfo_new(st) SKM_sk_new(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo)
+#define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i))
+#define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val))
+#define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_find(st, val) SKM_sk_find(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_delete(st, i) SKM_sk_delete(CMS_RecipientInfo, (st), (i))
+#define sk_CMS_RecipientInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientInfo, (st), (ptr))
+#define sk_CMS_RecipientInfo_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i))
+#define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp))
+#define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(CMS_RecipientInfo, st)
+#define sk_CMS_RecipientInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientInfo, (st), (free_func))
+#define sk_CMS_RecipientInfo_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st))
+
+#define sk_CMS_RevocationInfoChoice_new(st) SKM_sk_new(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice)
+#define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i))
+#define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val))
+#define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_find(st, val) SKM_sk_find(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_find_ex(st, val) SKM_sk_find_ex(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_delete(st, i) SKM_sk_delete(CMS_RevocationInfoChoice, (st), (i))
+#define sk_CMS_RevocationInfoChoice_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RevocationInfoChoice, (st), (ptr))
+#define sk_CMS_RevocationInfoChoice_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i))
+#define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp))
+#define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(CMS_RevocationInfoChoice, st)
+#define sk_CMS_RevocationInfoChoice_pop_free(st, free_func) SKM_sk_pop_free(CMS_RevocationInfoChoice, (st), (free_func))
+#define sk_CMS_RevocationInfoChoice_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st))
+
+#define sk_CMS_SignerInfo_new(st) SKM_sk_new(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo)
+#define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i))
+#define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val))
+#define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_find(st, val) SKM_sk_find(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_find_ex(st, val) SKM_sk_find_ex(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_delete(st, i) SKM_sk_delete(CMS_SignerInfo, (st), (i))
+#define sk_CMS_SignerInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_SignerInfo, (st), (ptr))
+#define sk_CMS_SignerInfo_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i))
+#define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp))
+#define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(CMS_SignerInfo, st)
+#define sk_CMS_SignerInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_SignerInfo, (st), (free_func))
+#define sk_CMS_SignerInfo_shift(st) SKM_sk_shift(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st))
+
+#define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE)
+#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val))
+#define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find_ex(st, val) SKM_sk_find_ex(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr))
+#define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i))
+#define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp))
+#define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st)
+#define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func))
+#define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st))
+
+#define sk_CONF_MODULE_new(st) SKM_sk_new(CONF_MODULE, (st))
+#define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE)
+#define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st))
+#define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st))
+#define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val))
+#define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st))
+#define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find_ex(st, val) SKM_sk_find_ex(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr))
+#define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i))
+#define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp))
+#define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st)
+#define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func))
+#define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st))
+#define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st))
+#define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st))
+#define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st))
+
+#define sk_CONF_VALUE_new(st) SKM_sk_new(CONF_VALUE, (st))
+#define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE)
+#define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st))
+#define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st))
+#define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val))
+#define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st))
+#define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find_ex(st, val) SKM_sk_find_ex(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr))
+#define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i))
+#define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp))
+#define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st)
+#define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func))
+#define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st))
+#define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st))
+#define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st))
+#define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
+#define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_zero(st) SKM_sk_zero(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_unshift(st, val) SKM_sk_unshift(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find(st, val) SKM_sk_find(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find_ex(st, val) SKM_sk_find_ex(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete(st, i) SKM_sk_delete(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_EX_DATA_FUNCS, (st), (ptr))
+#define sk_CRYPTO_EX_DATA_FUNCS_insert(st, val, i) SKM_sk_insert(CRYPTO_EX_DATA_FUNCS, (st), (val), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_EX_DATA_FUNCS, (st), (cmp))
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(st) SKM_sk_dup(CRYPTO_EX_DATA_FUNCS, st)
+#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func))
+#define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(st) SKM_sk_is_sorted(CRYPTO_EX_DATA_FUNCS, (st))
+
+#define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock)
+#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val))
+#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find_ex(st, val) SKM_sk_find_ex(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr))
+#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i))
+#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp))
+#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st)
+#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func))
+#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st))
+
+#define sk_DIST_POINT_new(st) SKM_sk_new(DIST_POINT, (st))
+#define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT)
+#define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st))
+#define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st))
+#define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val))
+#define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st))
+#define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find_ex(st, val) SKM_sk_find_ex(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr))
+#define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i))
+#define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp))
+#define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st)
+#define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func))
+#define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st))
+#define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st))
+#define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st))
+#define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st))
+
+#define sk_ENGINE_new(st) SKM_sk_new(ENGINE, (st))
+#define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE)
+#define sk_ENGINE_free(st) SKM_sk_free(ENGINE, (st))
+#define sk_ENGINE_num(st) SKM_sk_num(ENGINE, (st))
+#define sk_ENGINE_value(st, i) SKM_sk_value(ENGINE, (st), (i))
+#define sk_ENGINE_set(st, i, val) SKM_sk_set(ENGINE, (st), (i), (val))
+#define sk_ENGINE_zero(st) SKM_sk_zero(ENGINE, (st))
+#define sk_ENGINE_push(st, val) SKM_sk_push(ENGINE, (st), (val))
+#define sk_ENGINE_unshift(st, val) SKM_sk_unshift(ENGINE, (st), (val))
+#define sk_ENGINE_find(st, val) SKM_sk_find(ENGINE, (st), (val))
+#define sk_ENGINE_find_ex(st, val) SKM_sk_find_ex(ENGINE, (st), (val))
+#define sk_ENGINE_delete(st, i) SKM_sk_delete(ENGINE, (st), (i))
+#define sk_ENGINE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE, (st), (ptr))
+#define sk_ENGINE_insert(st, val, i) SKM_sk_insert(ENGINE, (st), (val), (i))
+#define sk_ENGINE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE, (st), (cmp))
+#define sk_ENGINE_dup(st) SKM_sk_dup(ENGINE, st)
+#define sk_ENGINE_pop_free(st, free_func) SKM_sk_pop_free(ENGINE, (st), (free_func))
+#define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st))
+#define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st))
+#define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st))
+#define sk_ENGINE_is_sorted(st) SKM_sk_is_sorted(ENGINE, (st))
+
+#define sk_ENGINE_CLEANUP_ITEM_new(st) SKM_sk_new(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM)
+#define sk_ENGINE_CLEANUP_ITEM_free(st) SKM_sk_free(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_num(st) SKM_sk_num(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_value(st, i) SKM_sk_value(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set(st, i, val) SKM_sk_set(ENGINE_CLEANUP_ITEM, (st), (i), (val))
+#define sk_ENGINE_CLEANUP_ITEM_zero(st) SKM_sk_zero(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_push(st, val) SKM_sk_push(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_unshift(st, val) SKM_sk_unshift(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find(st, val) SKM_sk_find(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find_ex(st, val) SKM_sk_find_ex(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_delete(st, i) SKM_sk_delete(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE_CLEANUP_ITEM, (st), (ptr))
+#define sk_ENGINE_CLEANUP_ITEM_insert(st, val, i) SKM_sk_insert(ENGINE_CLEANUP_ITEM, (st), (val), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE_CLEANUP_ITEM, (st), (cmp))
+#define sk_ENGINE_CLEANUP_ITEM_dup(st) SKM_sk_dup(ENGINE_CLEANUP_ITEM, st)
+#define sk_ENGINE_CLEANUP_ITEM_pop_free(st, free_func) SKM_sk_pop_free(ENGINE_CLEANUP_ITEM, (st), (free_func))
+#define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_is_sorted(st) SKM_sk_is_sorted(ENGINE_CLEANUP_ITEM, (st))
+
+#define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME)
+#define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val))
+#define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr))
+#define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i))
+#define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp))
+#define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st)
+#define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func))
+#define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st))
+
+#define sk_GENERAL_NAMES_new(st) SKM_sk_new(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_new_null() SKM_sk_new_null(GENERAL_NAMES)
+#define sk_GENERAL_NAMES_free(st) SKM_sk_free(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_num(st) SKM_sk_num(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_value(st, i) SKM_sk_value(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_set(st, i, val) SKM_sk_set(GENERAL_NAMES, (st), (i), (val))
+#define sk_GENERAL_NAMES_zero(st) SKM_sk_zero(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_push(st, val) SKM_sk_push(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_unshift(st, val) SKM_sk_unshift(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find(st, val) SKM_sk_find(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_delete(st, i) SKM_sk_delete(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAMES, (st), (ptr))
+#define sk_GENERAL_NAMES_insert(st, val, i) SKM_sk_insert(GENERAL_NAMES, (st), (val), (i))
+#define sk_GENERAL_NAMES_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAMES, (st), (cmp))
+#define sk_GENERAL_NAMES_dup(st) SKM_sk_dup(GENERAL_NAMES, st)
+#define sk_GENERAL_NAMES_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAMES, (st), (free_func))
+#define sk_GENERAL_NAMES_shift(st) SKM_sk_shift(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_pop(st) SKM_sk_pop(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_sort(st) SKM_sk_sort(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAMES, (st))
+
+#define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
+#define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val))
+#define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find_ex(st, val) SKM_sk_find_ex(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr))
+#define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i))
+#define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp))
+#define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st)
+#define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func))
+#define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st))
+
+#define sk_IPAddressFamily_new(st) SKM_sk_new(IPAddressFamily, (st))
+#define sk_IPAddressFamily_new_null() SKM_sk_new_null(IPAddressFamily)
+#define sk_IPAddressFamily_free(st) SKM_sk_free(IPAddressFamily, (st))
+#define sk_IPAddressFamily_num(st) SKM_sk_num(IPAddressFamily, (st))
+#define sk_IPAddressFamily_value(st, i) SKM_sk_value(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_set(st, i, val) SKM_sk_set(IPAddressFamily, (st), (i), (val))
+#define sk_IPAddressFamily_zero(st) SKM_sk_zero(IPAddressFamily, (st))
+#define sk_IPAddressFamily_push(st, val) SKM_sk_push(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_unshift(st, val) SKM_sk_unshift(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find(st, val) SKM_sk_find(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find_ex(st, val) SKM_sk_find_ex(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_delete(st, i) SKM_sk_delete(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressFamily, (st), (ptr))
+#define sk_IPAddressFamily_insert(st, val, i) SKM_sk_insert(IPAddressFamily, (st), (val), (i))
+#define sk_IPAddressFamily_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressFamily, (st), (cmp))
+#define sk_IPAddressFamily_dup(st) SKM_sk_dup(IPAddressFamily, st)
+#define sk_IPAddressFamily_pop_free(st, free_func) SKM_sk_pop_free(IPAddressFamily, (st), (free_func))
+#define sk_IPAddressFamily_shift(st) SKM_sk_shift(IPAddressFamily, (st))
+#define sk_IPAddressFamily_pop(st) SKM_sk_pop(IPAddressFamily, (st))
+#define sk_IPAddressFamily_sort(st) SKM_sk_sort(IPAddressFamily, (st))
+#define sk_IPAddressFamily_is_sorted(st) SKM_sk_is_sorted(IPAddressFamily, (st))
+
+#define sk_IPAddressOrRange_new(st) SKM_sk_new(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_new_null() SKM_sk_new_null(IPAddressOrRange)
+#define sk_IPAddressOrRange_free(st) SKM_sk_free(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_num(st) SKM_sk_num(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_value(st, i) SKM_sk_value(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_set(st, i, val) SKM_sk_set(IPAddressOrRange, (st), (i), (val))
+#define sk_IPAddressOrRange_zero(st) SKM_sk_zero(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_push(st, val) SKM_sk_push(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_unshift(st, val) SKM_sk_unshift(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find(st, val) SKM_sk_find(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find_ex(st, val) SKM_sk_find_ex(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_delete(st, i) SKM_sk_delete(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressOrRange, (st), (ptr))
+#define sk_IPAddressOrRange_insert(st, val, i) SKM_sk_insert(IPAddressOrRange, (st), (val), (i))
+#define sk_IPAddressOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressOrRange, (st), (cmp))
+#define sk_IPAddressOrRange_dup(st) SKM_sk_dup(IPAddressOrRange, st)
+#define sk_IPAddressOrRange_pop_free(st, free_func) SKM_sk_pop_free(IPAddressOrRange, (st), (free_func))
+#define sk_IPAddressOrRange_shift(st) SKM_sk_shift(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_pop(st) SKM_sk_pop(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_sort(st) SKM_sk_sort(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_is_sorted(st) SKM_sk_is_sorted(IPAddressOrRange, (st))
+
+#define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY)
+#define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_num(st) SKM_sk_num(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_value(st, i) SKM_sk_value(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_set(st, i, val) SKM_sk_set(KRB5_APREQBODY, (st), (i), (val))
+#define sk_KRB5_APREQBODY_zero(st) SKM_sk_zero(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_push(st, val) SKM_sk_push(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_unshift(st, val) SKM_sk_unshift(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find(st, val) SKM_sk_find(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_delete(st, i) SKM_sk_delete(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_APREQBODY, (st), (ptr))
+#define sk_KRB5_APREQBODY_insert(st, val, i) SKM_sk_insert(KRB5_APREQBODY, (st), (val), (i))
+#define sk_KRB5_APREQBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_APREQBODY, (st), (cmp))
+#define sk_KRB5_APREQBODY_dup(st) SKM_sk_dup(KRB5_APREQBODY, st)
+#define sk_KRB5_APREQBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_APREQBODY, (st), (free_func))
+#define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_APREQBODY, (st))
+
+#define sk_KRB5_AUTHDATA_new(st) SKM_sk_new(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA)
+#define sk_KRB5_AUTHDATA_free(st) SKM_sk_free(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_num(st) SKM_sk_num(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_value(st, i) SKM_sk_value(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_set(st, i, val) SKM_sk_set(KRB5_AUTHDATA, (st), (i), (val))
+#define sk_KRB5_AUTHDATA_zero(st) SKM_sk_zero(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_push(st, val) SKM_sk_push(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_unshift(st, val) SKM_sk_unshift(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find(st, val) SKM_sk_find(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_delete(st, i) SKM_sk_delete(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHDATA, (st), (ptr))
+#define sk_KRB5_AUTHDATA_insert(st, val, i) SKM_sk_insert(KRB5_AUTHDATA, (st), (val), (i))
+#define sk_KRB5_AUTHDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHDATA, (st), (cmp))
+#define sk_KRB5_AUTHDATA_dup(st) SKM_sk_dup(KRB5_AUTHDATA, st)
+#define sk_KRB5_AUTHDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHDATA, (st), (free_func))
+#define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHDATA, (st))
+
+#define sk_KRB5_AUTHENTBODY_new(st) SKM_sk_new(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY)
+#define sk_KRB5_AUTHENTBODY_free(st) SKM_sk_free(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_num(st) SKM_sk_num(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_value(st, i) SKM_sk_value(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_set(st, i, val) SKM_sk_set(KRB5_AUTHENTBODY, (st), (i), (val))
+#define sk_KRB5_AUTHENTBODY_zero(st) SKM_sk_zero(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_push(st, val) SKM_sk_push(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_unshift(st, val) SKM_sk_unshift(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find(st, val) SKM_sk_find(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_delete(st, i) SKM_sk_delete(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHENTBODY, (st), (ptr))
+#define sk_KRB5_AUTHENTBODY_insert(st, val, i) SKM_sk_insert(KRB5_AUTHENTBODY, (st), (val), (i))
+#define sk_KRB5_AUTHENTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHENTBODY, (st), (cmp))
+#define sk_KRB5_AUTHENTBODY_dup(st) SKM_sk_dup(KRB5_AUTHENTBODY, st)
+#define sk_KRB5_AUTHENTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHENTBODY, (st), (free_func))
+#define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHENTBODY, (st))
+
+#define sk_KRB5_CHECKSUM_new(st) SKM_sk_new(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM)
+#define sk_KRB5_CHECKSUM_free(st) SKM_sk_free(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_num(st) SKM_sk_num(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_value(st, i) SKM_sk_value(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_set(st, i, val) SKM_sk_set(KRB5_CHECKSUM, (st), (i), (val))
+#define sk_KRB5_CHECKSUM_zero(st) SKM_sk_zero(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_push(st, val) SKM_sk_push(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_unshift(st, val) SKM_sk_unshift(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find(st, val) SKM_sk_find(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find_ex(st, val) SKM_sk_find_ex(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_delete(st, i) SKM_sk_delete(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_CHECKSUM, (st), (ptr))
+#define sk_KRB5_CHECKSUM_insert(st, val, i) SKM_sk_insert(KRB5_CHECKSUM, (st), (val), (i))
+#define sk_KRB5_CHECKSUM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_CHECKSUM, (st), (cmp))
+#define sk_KRB5_CHECKSUM_dup(st) SKM_sk_dup(KRB5_CHECKSUM, st)
+#define sk_KRB5_CHECKSUM_pop_free(st, free_func) SKM_sk_pop_free(KRB5_CHECKSUM, (st), (free_func))
+#define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_is_sorted(st) SKM_sk_is_sorted(KRB5_CHECKSUM, (st))
+
+#define sk_KRB5_ENCDATA_new(st) SKM_sk_new(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA)
+#define sk_KRB5_ENCDATA_free(st) SKM_sk_free(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_num(st) SKM_sk_num(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_value(st, i) SKM_sk_value(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_set(st, i, val) SKM_sk_set(KRB5_ENCDATA, (st), (i), (val))
+#define sk_KRB5_ENCDATA_zero(st) SKM_sk_zero(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_push(st, val) SKM_sk_push(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_unshift(st, val) SKM_sk_unshift(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find(st, val) SKM_sk_find(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_delete(st, i) SKM_sk_delete(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCDATA, (st), (ptr))
+#define sk_KRB5_ENCDATA_insert(st, val, i) SKM_sk_insert(KRB5_ENCDATA, (st), (val), (i))
+#define sk_KRB5_ENCDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCDATA, (st), (cmp))
+#define sk_KRB5_ENCDATA_dup(st) SKM_sk_dup(KRB5_ENCDATA, st)
+#define sk_KRB5_ENCDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCDATA, (st), (free_func))
+#define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCDATA, (st))
+
+#define sk_KRB5_ENCKEY_new(st) SKM_sk_new(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY)
+#define sk_KRB5_ENCKEY_free(st) SKM_sk_free(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_num(st) SKM_sk_num(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_value(st, i) SKM_sk_value(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_set(st, i, val) SKM_sk_set(KRB5_ENCKEY, (st), (i), (val))
+#define sk_KRB5_ENCKEY_zero(st) SKM_sk_zero(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_push(st, val) SKM_sk_push(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_unshift(st, val) SKM_sk_unshift(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find(st, val) SKM_sk_find(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_delete(st, i) SKM_sk_delete(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCKEY, (st), (ptr))
+#define sk_KRB5_ENCKEY_insert(st, val, i) SKM_sk_insert(KRB5_ENCKEY, (st), (val), (i))
+#define sk_KRB5_ENCKEY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCKEY, (st), (cmp))
+#define sk_KRB5_ENCKEY_dup(st) SKM_sk_dup(KRB5_ENCKEY, st)
+#define sk_KRB5_ENCKEY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCKEY, (st), (free_func))
+#define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCKEY, (st))
+
+#define sk_KRB5_PRINCNAME_new(st) SKM_sk_new(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME)
+#define sk_KRB5_PRINCNAME_free(st) SKM_sk_free(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_num(st) SKM_sk_num(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_value(st, i) SKM_sk_value(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_set(st, i, val) SKM_sk_set(KRB5_PRINCNAME, (st), (i), (val))
+#define sk_KRB5_PRINCNAME_zero(st) SKM_sk_zero(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_push(st, val) SKM_sk_push(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_unshift(st, val) SKM_sk_unshift(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find(st, val) SKM_sk_find(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find_ex(st, val) SKM_sk_find_ex(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_delete(st, i) SKM_sk_delete(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_PRINCNAME, (st), (ptr))
+#define sk_KRB5_PRINCNAME_insert(st, val, i) SKM_sk_insert(KRB5_PRINCNAME, (st), (val), (i))
+#define sk_KRB5_PRINCNAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_PRINCNAME, (st), (cmp))
+#define sk_KRB5_PRINCNAME_dup(st) SKM_sk_dup(KRB5_PRINCNAME, st)
+#define sk_KRB5_PRINCNAME_pop_free(st, free_func) SKM_sk_pop_free(KRB5_PRINCNAME, (st), (free_func))
+#define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_is_sorted(st) SKM_sk_is_sorted(KRB5_PRINCNAME, (st))
+
+#define sk_KRB5_TKTBODY_new(st) SKM_sk_new(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY)
+#define sk_KRB5_TKTBODY_free(st) SKM_sk_free(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_num(st) SKM_sk_num(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_value(st, i) SKM_sk_value(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_set(st, i, val) SKM_sk_set(KRB5_TKTBODY, (st), (i), (val))
+#define sk_KRB5_TKTBODY_zero(st) SKM_sk_zero(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_push(st, val) SKM_sk_push(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_unshift(st, val) SKM_sk_unshift(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find(st, val) SKM_sk_find(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_delete(st, i) SKM_sk_delete(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_TKTBODY, (st), (ptr))
+#define sk_KRB5_TKTBODY_insert(st, val, i) SKM_sk_insert(KRB5_TKTBODY, (st), (val), (i))
+#define sk_KRB5_TKTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_TKTBODY, (st), (cmp))
+#define sk_KRB5_TKTBODY_dup(st) SKM_sk_dup(KRB5_TKTBODY, st)
+#define sk_KRB5_TKTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_TKTBODY, (st), (free_func))
+#define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_TKTBODY, (st))
+
+#define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st))
+#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER)
+#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st))
+#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st))
+#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val))
+#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st))
+#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr))
+#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i))
+#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp))
+#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st)
+#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func))
+#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st))
+#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st))
+#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
+#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
+
+#define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
+#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
+#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st))
+#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st))
+#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val))
+#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st))
+#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr))
+#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i))
+#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp))
+#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st)
+#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func))
+#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st))
+#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st))
+#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st))
+#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st))
+
+#define sk_NAME_FUNCS_new(st) SKM_sk_new(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS)
+#define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val))
+#define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find_ex(st, val) SKM_sk_find_ex(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr))
+#define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i))
+#define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp))
+#define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st)
+#define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func))
+#define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st))
+
+#define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID)
+#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val))
+#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find_ex(st, val) SKM_sk_find_ex(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr))
+#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i))
+#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp))
+#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st)
+#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func))
+#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st))
+
+#define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ)
+#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val))
+#define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find_ex(st, val) SKM_sk_find_ex(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr))
+#define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i))
+#define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp))
+#define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st)
+#define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func))
+#define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st))
+
+#define sk_OCSP_RESPID_new(st) SKM_sk_new(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_new_null() SKM_sk_new_null(OCSP_RESPID)
+#define sk_OCSP_RESPID_free(st) SKM_sk_free(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_num(st) SKM_sk_num(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_value(st, i) SKM_sk_value(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_set(st, i, val) SKM_sk_set(OCSP_RESPID, (st), (i), (val))
+#define sk_OCSP_RESPID_zero(st) SKM_sk_zero(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_push(st, val) SKM_sk_push(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_unshift(st, val) SKM_sk_unshift(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find(st, val) SKM_sk_find(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find_ex(st, val) SKM_sk_find_ex(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_delete(st, i) SKM_sk_delete(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_RESPID, (st), (ptr))
+#define sk_OCSP_RESPID_insert(st, val, i) SKM_sk_insert(OCSP_RESPID, (st), (val), (i))
+#define sk_OCSP_RESPID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_RESPID, (st), (cmp))
+#define sk_OCSP_RESPID_dup(st) SKM_sk_dup(OCSP_RESPID, st)
+#define sk_OCSP_RESPID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_RESPID, (st), (free_func))
+#define sk_OCSP_RESPID_shift(st) SKM_sk_shift(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_pop(st) SKM_sk_pop(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_sort(st) SKM_sk_sort(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_is_sorted(st) SKM_sk_is_sorted(OCSP_RESPID, (st))
+
+#define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP)
+#define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val))
+#define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find_ex(st, val) SKM_sk_find_ex(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr))
+#define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i))
+#define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp))
+#define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st)
+#define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func))
+#define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st))
+
+#define sk_PKCS12_SAFEBAG_new(st) SKM_sk_new(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG)
+#define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val))
+#define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find_ex(st, val) SKM_sk_find_ex(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr))
+#define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i))
+#define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp))
+#define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st)
+#define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func))
+#define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st))
+
+#define sk_PKCS7_new(st) SKM_sk_new(PKCS7, (st))
+#define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7)
+#define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st))
+#define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st))
+#define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i))
+#define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val))
+#define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st))
+#define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val))
+#define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val))
+#define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val))
+#define sk_PKCS7_find_ex(st, val) SKM_sk_find_ex(PKCS7, (st), (val))
+#define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i))
+#define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr))
+#define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i))
+#define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp))
+#define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st)
+#define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func))
+#define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st))
+#define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st))
+#define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st))
+#define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st))
+
+#define sk_PKCS7_RECIP_INFO_new(st) SKM_sk_new(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO)
+#define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val))
+#define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr))
+#define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i))
+#define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp))
+#define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st)
+#define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func))
+#define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st))
+
+#define sk_PKCS7_SIGNER_INFO_new(st) SKM_sk_new(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO)
+#define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val))
+#define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr))
+#define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i))
+#define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp))
+#define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st)
+#define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func))
+#define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st))
+
+#define sk_POLICYINFO_new(st) SKM_sk_new(POLICYINFO, (st))
+#define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO)
+#define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st))
+#define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st))
+#define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val))
+#define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st))
+#define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find_ex(st, val) SKM_sk_find_ex(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr))
+#define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i))
+#define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp))
+#define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st)
+#define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func))
+#define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st))
+#define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st))
+#define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st))
+#define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st))
+
+#define sk_POLICYQUALINFO_new(st) SKM_sk_new(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO)
+#define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val))
+#define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find_ex(st, val) SKM_sk_find_ex(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr))
+#define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i))
+#define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp))
+#define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st)
+#define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func))
+#define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st))
+
+#define sk_POLICY_MAPPING_new(st) SKM_sk_new(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING)
+#define sk_POLICY_MAPPING_free(st) SKM_sk_free(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_num(st) SKM_sk_num(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_value(st, i) SKM_sk_value(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_set(st, i, val) SKM_sk_set(POLICY_MAPPING, (st), (i), (val))
+#define sk_POLICY_MAPPING_zero(st) SKM_sk_zero(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_push(st, val) SKM_sk_push(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_unshift(st, val) SKM_sk_unshift(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find(st, val) SKM_sk_find(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find_ex(st, val) SKM_sk_find_ex(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_delete(st, i) SKM_sk_delete(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICY_MAPPING, (st), (ptr))
+#define sk_POLICY_MAPPING_insert(st, val, i) SKM_sk_insert(POLICY_MAPPING, (st), (val), (i))
+#define sk_POLICY_MAPPING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICY_MAPPING, (st), (cmp))
+#define sk_POLICY_MAPPING_dup(st) SKM_sk_dup(POLICY_MAPPING, st)
+#define sk_POLICY_MAPPING_pop_free(st, free_func) SKM_sk_pop_free(POLICY_MAPPING, (st), (free_func))
+#define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st))
+
+#define sk_SSL_CIPHER_new(st) SKM_sk_new(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER)
+#define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val))
+#define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find_ex(st, val) SKM_sk_find_ex(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr))
+#define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i))
+#define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp))
+#define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st)
+#define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func))
+#define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st))
+
+#define sk_SSL_COMP_new(st) SKM_sk_new(SSL_COMP, (st))
+#define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP)
+#define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st))
+#define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st))
+#define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val))
+#define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st))
+#define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find_ex(st, val) SKM_sk_find_ex(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr))
+#define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i))
+#define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp))
+#define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st)
+#define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func))
+#define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st))
+#define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st))
+#define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st))
+#define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st))
+
+#define sk_STORE_OBJECT_new(st) SKM_sk_new(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT)
+#define sk_STORE_OBJECT_free(st) SKM_sk_free(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_num(st) SKM_sk_num(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_value(st, i) SKM_sk_value(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_set(st, i, val) SKM_sk_set(STORE_OBJECT, (st), (i), (val))
+#define sk_STORE_OBJECT_zero(st) SKM_sk_zero(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_push(st, val) SKM_sk_push(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_unshift(st, val) SKM_sk_unshift(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find(st, val) SKM_sk_find(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find_ex(st, val) SKM_sk_find_ex(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_delete(st, i) SKM_sk_delete(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_OBJECT, (st), (ptr))
+#define sk_STORE_OBJECT_insert(st, val, i) SKM_sk_insert(STORE_OBJECT, (st), (val), (i))
+#define sk_STORE_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_OBJECT, (st), (cmp))
+#define sk_STORE_OBJECT_dup(st) SKM_sk_dup(STORE_OBJECT, st)
+#define sk_STORE_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(STORE_OBJECT, (st), (free_func))
+#define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st))
+
+#define sk_SXNETID_new(st) SKM_sk_new(SXNETID, (st))
+#define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID)
+#define sk_SXNETID_free(st) SKM_sk_free(SXNETID, (st))
+#define sk_SXNETID_num(st) SKM_sk_num(SXNETID, (st))
+#define sk_SXNETID_value(st, i) SKM_sk_value(SXNETID, (st), (i))
+#define sk_SXNETID_set(st, i, val) SKM_sk_set(SXNETID, (st), (i), (val))
+#define sk_SXNETID_zero(st) SKM_sk_zero(SXNETID, (st))
+#define sk_SXNETID_push(st, val) SKM_sk_push(SXNETID, (st), (val))
+#define sk_SXNETID_unshift(st, val) SKM_sk_unshift(SXNETID, (st), (val))
+#define sk_SXNETID_find(st, val) SKM_sk_find(SXNETID, (st), (val))
+#define sk_SXNETID_find_ex(st, val) SKM_sk_find_ex(SXNETID, (st), (val))
+#define sk_SXNETID_delete(st, i) SKM_sk_delete(SXNETID, (st), (i))
+#define sk_SXNETID_delete_ptr(st, ptr) SKM_sk_delete_ptr(SXNETID, (st), (ptr))
+#define sk_SXNETID_insert(st, val, i) SKM_sk_insert(SXNETID, (st), (val), (i))
+#define sk_SXNETID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SXNETID, (st), (cmp))
+#define sk_SXNETID_dup(st) SKM_sk_dup(SXNETID, st)
+#define sk_SXNETID_pop_free(st, free_func) SKM_sk_pop_free(SXNETID, (st), (free_func))
+#define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st))
+#define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st))
+#define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st))
+#define sk_SXNETID_is_sorted(st) SKM_sk_is_sorted(SXNETID, (st))
+
+#define sk_UI_STRING_new(st) SKM_sk_new(UI_STRING, (st))
+#define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING)
+#define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st))
+#define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st))
+#define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i))
+#define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val))
+#define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st))
+#define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val))
+#define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val))
+#define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val))
+#define sk_UI_STRING_find_ex(st, val) SKM_sk_find_ex(UI_STRING, (st), (val))
+#define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i))
+#define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr))
+#define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i))
+#define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp))
+#define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st)
+#define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func))
+#define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st))
+#define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st))
+#define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st))
+#define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st))
+
+#define sk_X509_new(st) SKM_sk_new(X509, (st))
+#define sk_X509_new_null() SKM_sk_new_null(X509)
+#define sk_X509_free(st) SKM_sk_free(X509, (st))
+#define sk_X509_num(st) SKM_sk_num(X509, (st))
+#define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i))
+#define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val))
+#define sk_X509_zero(st) SKM_sk_zero(X509, (st))
+#define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val))
+#define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val))
+#define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val))
+#define sk_X509_find_ex(st, val) SKM_sk_find_ex(X509, (st), (val))
+#define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i))
+#define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr))
+#define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i))
+#define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp))
+#define sk_X509_dup(st) SKM_sk_dup(X509, st)
+#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func))
+#define sk_X509_shift(st) SKM_sk_shift(X509, (st))
+#define sk_X509_pop(st) SKM_sk_pop(X509, (st))
+#define sk_X509_sort(st) SKM_sk_sort(X509, (st))
+#define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st))
+
+#define sk_X509V3_EXT_METHOD_new(st) SKM_sk_new(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD)
+#define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val))
+#define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find_ex(st, val) SKM_sk_find_ex(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr))
+#define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i))
+#define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp))
+#define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st)
+#define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func))
+#define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st))
+
+#define sk_X509_ALGOR_new(st) SKM_sk_new(X509_ALGOR, (st))
+#define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR)
+#define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st))
+#define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st))
+#define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val))
+#define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st))
+#define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find_ex(st, val) SKM_sk_find_ex(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr))
+#define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i))
+#define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp))
+#define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st)
+#define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func))
+#define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st))
+#define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st))
+#define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st))
+#define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st))
+
+#define sk_X509_ATTRIBUTE_new(st) SKM_sk_new(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE)
+#define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val))
+#define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find_ex(st, val) SKM_sk_find_ex(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr))
+#define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i))
+#define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp))
+#define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st)
+#define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func))
+#define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st))
+
+#define sk_X509_CRL_new(st) SKM_sk_new(X509_CRL, (st))
+#define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL)
+#define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st))
+#define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st))
+#define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i))
+#define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val))
+#define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st))
+#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val))
+#define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val))
+#define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val))
+#define sk_X509_CRL_find_ex(st, val) SKM_sk_find_ex(X509_CRL, (st), (val))
+#define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i))
+#define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr))
+#define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i))
+#define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp))
+#define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st)
+#define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func))
+#define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st))
+#define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st))
+#define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st))
+#define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st))
+
+#define sk_X509_EXTENSION_new(st) SKM_sk_new(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION)
+#define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val))
+#define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find_ex(st, val) SKM_sk_find_ex(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr))
+#define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i))
+#define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp))
+#define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st)
+#define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func))
+#define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st))
+
+#define sk_X509_INFO_new(st) SKM_sk_new(X509_INFO, (st))
+#define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO)
+#define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st))
+#define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st))
+#define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i))
+#define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val))
+#define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st))
+#define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val))
+#define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val))
+#define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val))
+#define sk_X509_INFO_find_ex(st, val) SKM_sk_find_ex(X509_INFO, (st), (val))
+#define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i))
+#define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr))
+#define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i))
+#define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp))
+#define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st)
+#define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func))
+#define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st))
+#define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st))
+#define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st))
+#define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st))
+
+#define sk_X509_LOOKUP_new(st) SKM_sk_new(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP)
+#define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val))
+#define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find_ex(st, val) SKM_sk_find_ex(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr))
+#define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i))
+#define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp))
+#define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st)
+#define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func))
+#define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st))
+
+#define sk_X509_NAME_new(st) SKM_sk_new(X509_NAME, (st))
+#define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME)
+#define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st))
+#define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st))
+#define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i))
+#define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val))
+#define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st))
+#define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val))
+#define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val))
+#define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val))
+#define sk_X509_NAME_find_ex(st, val) SKM_sk_find_ex(X509_NAME, (st), (val))
+#define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i))
+#define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr))
+#define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i))
+#define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp))
+#define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st)
+#define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func))
+#define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st))
+#define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st))
+#define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st))
+#define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st))
+
+#define sk_X509_NAME_ENTRY_new(st) SKM_sk_new(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY)
+#define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val))
+#define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr))
+#define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i))
+#define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp))
+#define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st)
+#define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func))
+#define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st))
+
+#define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st))
+#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT)
+#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st))
+#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st))
+#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val))
+#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st))
+#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find_ex(st, val) SKM_sk_find_ex(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr))
+#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i))
+#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp))
+#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st)
+#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func))
+#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st))
+#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st))
+#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st))
+#define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st))
+
+#define sk_X509_POLICY_DATA_new(st) SKM_sk_new(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA)
+#define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val))
+#define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr))
+#define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i))
+#define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp))
+#define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st)
+#define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func))
+#define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st))
+
+#define sk_X509_POLICY_NODE_new(st) SKM_sk_new(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE)
+#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val))
+#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr))
+#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i))
+#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp))
+#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st)
+#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func))
+#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st))
+
+#define sk_X509_POLICY_REF_new(st) SKM_sk_new(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_new_null() SKM_sk_new_null(X509_POLICY_REF)
+#define sk_X509_POLICY_REF_free(st) SKM_sk_free(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_num(st) SKM_sk_num(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_value(st, i) SKM_sk_value(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_set(st, i, val) SKM_sk_set(X509_POLICY_REF, (st), (i), (val))
+#define sk_X509_POLICY_REF_zero(st) SKM_sk_zero(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_push(st, val) SKM_sk_push(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_unshift(st, val) SKM_sk_unshift(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find(st, val) SKM_sk_find(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_delete(st, i) SKM_sk_delete(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_REF, (st), (ptr))
+#define sk_X509_POLICY_REF_insert(st, val, i) SKM_sk_insert(X509_POLICY_REF, (st), (val), (i))
+#define sk_X509_POLICY_REF_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_REF, (st), (cmp))
+#define sk_X509_POLICY_REF_dup(st) SKM_sk_dup(X509_POLICY_REF, st)
+#define sk_X509_POLICY_REF_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_REF, (st), (free_func))
+#define sk_X509_POLICY_REF_shift(st) SKM_sk_shift(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_pop(st) SKM_sk_pop(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_sort(st) SKM_sk_sort(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_REF, (st))
+
+#define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE)
+#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val))
+#define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find_ex(st, val) SKM_sk_find_ex(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr))
+#define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i))
+#define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp))
+#define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st)
+#define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func))
+#define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st))
+
+#define sk_X509_REVOKED_new(st) SKM_sk_new(X509_REVOKED, (st))
+#define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED)
+#define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st))
+#define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st))
+#define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val))
+#define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st))
+#define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find_ex(st, val) SKM_sk_find_ex(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr))
+#define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i))
+#define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp))
+#define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st)
+#define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func))
+#define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st))
+#define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st))
+#define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st))
+#define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st))
+
+#define sk_X509_TRUST_new(st) SKM_sk_new(X509_TRUST, (st))
+#define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST)
+#define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st))
+#define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st))
+#define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val))
+#define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st))
+#define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find_ex(st, val) SKM_sk_find_ex(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr))
+#define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i))
+#define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp))
+#define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st)
+#define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func))
+#define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st))
+#define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st))
+#define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st))
+#define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st))
+
+#define sk_X509_VERIFY_PARAM_new(st) SKM_sk_new(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM)
+#define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val))
+#define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr))
+#define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i))
+#define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp))
+#define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st)
+#define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func))
+#define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st))
+
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ACCESS_DESCRIPTION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ACCESS_DESCRIPTION(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ACCESS_DESCRIPTION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ACCESS_DESCRIPTION(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ACCESS_DESCRIPTION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_INTEGER(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_INTEGER, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_INTEGER(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_INTEGER, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_INTEGER(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_INTEGER, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_INTEGER(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_INTEGER, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_OBJECT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_OBJECT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_OBJECT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_OBJECT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_OBJECT(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_OBJECT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_OBJECT(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_OBJECT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_TYPE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_TYPE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_TYPE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_TYPE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_TYPE(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_TYPE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_TYPE(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_TYPE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_DIST_POINT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(DIST_POINT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_DIST_POINT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(DIST_POINT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_DIST_POINT(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(DIST_POINT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_DIST_POINT(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(DIST_POINT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_GENERAL_NAME(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(GENERAL_NAME, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_GENERAL_NAME(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(GENERAL_NAME, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_GENERAL_NAME(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(GENERAL_NAME, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_GENERAL_NAME(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(GENERAL_NAME, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_ONEREQ(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(OCSP_ONEREQ, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_OCSP_ONEREQ(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(OCSP_ONEREQ, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_ONEREQ(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(OCSP_ONEREQ, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_ONEREQ(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(OCSP_ONEREQ, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(OCSP_SINGLERESP, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(OCSP_SINGLERESP, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_SINGLERESP(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(OCSP_SINGLERESP, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_SINGLERESP(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(OCSP_SINGLERESP, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS12_SAFEBAG, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS12_SAFEBAG, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS12_SAFEBAG(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS12_SAFEBAG, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS12_SAFEBAG(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS12_SAFEBAG, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7_RECIP_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7_RECIP_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_RECIP_INFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7_RECIP_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_RECIP_INFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7_RECIP_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7_SIGNER_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7_SIGNER_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_SIGNER_INFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7_SIGNER_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_SIGNER_INFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7_SIGNER_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(POLICYINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_POLICYINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(POLICYINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYINFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(POLICYINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYINFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(POLICYINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYQUALINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(POLICYQUALINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_POLICYQUALINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(POLICYQUALINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYQUALINFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(POLICYQUALINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYQUALINFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(POLICYQUALINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_SXNETID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(SXNETID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_SXNETID(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(SXNETID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_SXNETID(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(SXNETID, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_SXNETID(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(SXNETID, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ALGOR(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_ALGOR, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_ALGOR(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_ALGOR, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ALGOR(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_ALGOR, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ALGOR(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_ALGOR, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_ATTRIBUTE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_ATTRIBUTE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ATTRIBUTE(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_ATTRIBUTE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ATTRIBUTE(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_ATTRIBUTE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_CRL(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_CRL, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_CRL(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_CRL, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_CRL(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_CRL, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_CRL(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_CRL, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_EXTENSION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_EXTENSION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_EXTENSION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_EXTENSION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_EXTENSION(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_EXTENSION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_EXTENSION(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_EXTENSION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_NAME_ENTRY, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_NAME_ENTRY, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_NAME_ENTRY(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_NAME_ENTRY, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_NAME_ENTRY(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_NAME_ENTRY, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_REVOKED(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_REVOKED, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_REVOKED(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_REVOKED, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_REVOKED(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_REVOKED, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_REVOKED(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_REVOKED, (buf), (len), (d2i_func), (free_func))
+
+#define PKCS12_decrypt_d2i_PKCS12_SAFEBAG(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ SKM_PKCS12_decrypt_d2i(PKCS12_SAFEBAG, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+
+#define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+/* End of util/mkstack.pl block, you may now edit :-) */
+
+#endif /* !defined HEADER_SAFESTACK_H */
diff --git a/src/Mayaqua/win32_inc/openssl/sha.h b/src/Mayaqua/win32_inc/openssl/sha.h
new file mode 100644
index 00000000..3e9bde9a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/sha.h
@@ -0,0 +1,203 @@
+/* crypto/sha/sha.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1))
+#error SHA is disabled.
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_SHA_SIZE_T size_t
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#else
+#define SHA_LONG unsigned int
+#endif
+
+#define SHA_LBLOCK 16
+#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a
+ * contiguous array of 32 bit
+ * wide big-endian values. */
+#define SHA_LAST_BLOCK (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+typedef struct SHAstate_st
+ {
+ SHA_LONG h0,h1,h2,h3,h4;
+ SHA_LONG Nl,Nh;
+ SHA_LONG data[SHA_LBLOCK];
+ unsigned int num;
+ } SHA_CTX;
+
+#ifndef OPENSSL_NO_SHA0
+#ifdef OPENSSL_FIPS
+int private_SHA_Init(SHA_CTX *c);
+#endif
+int SHA_Init(SHA_CTX *c);
+int SHA_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md);
+void SHA_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifndef OPENSSL_NO_SHA1
+int SHA1_Init(SHA_CTX *c);
+int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA1_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
+void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA256_CBLOCK (SHA_LBLOCK*4) /* SHA-256 treats input data as a
+ * contiguous array of 32 bit
+ * wide big-endian values. */
+#define SHA224_DIGEST_LENGTH 28
+#define SHA256_DIGEST_LENGTH 32
+
+typedef struct SHA256state_st
+ {
+ SHA_LONG h[8];
+ SHA_LONG Nl,Nh;
+ SHA_LONG data[SHA_LBLOCK];
+ unsigned int num,md_len;
+ } SHA256_CTX;
+
+#ifndef OPENSSL_NO_SHA256
+int SHA224_Init(SHA256_CTX *c);
+int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA224(const unsigned char *d, size_t n,unsigned char *md);
+int SHA256_Init(SHA256_CTX *c);
+int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA256_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA256(const unsigned char *d, size_t n,unsigned char *md);
+void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
+#ifndef OPENSSL_NO_SHA512
+/*
+ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64
+ * being exactly 64-bit wide. See Implementation Notes in sha512.c
+ * for further details.
+ */
+#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a
+ * contiguous array of 64 bit
+ * wide big-endian values. */
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+#define SHA_LONG64 unsigned __int64
+#define U64(C) C##UI64
+#elif defined(__arch64__)
+#define SHA_LONG64 unsigned long
+#define U64(C) C##UL
+#else
+#define SHA_LONG64 unsigned long long
+#define U64(C) C##ULL
+#endif
+
+typedef struct SHA512state_st
+ {
+ SHA_LONG64 h[8];
+ SHA_LONG64 Nl,Nh;
+ union {
+ SHA_LONG64 d[SHA_LBLOCK];
+ unsigned char p[SHA512_CBLOCK];
+ } u;
+ unsigned int num,md_len;
+ } SHA512_CTX;
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+int SHA384_Init(SHA512_CTX *c);
+int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA384_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA384(const unsigned char *d, size_t n,unsigned char *md);
+int SHA512_Init(SHA512_CTX *c);
+int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA512_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA512(const unsigned char *d, size_t n,unsigned char *md);
+void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ssl.h b/src/Mayaqua/win32_inc/openssl/ssl.h
new file mode 100644
index 00000000..5071fdd8
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl.h
@@ -0,0 +1,2125 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL_H
+#define HEADER_SSL_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_X509
+#include <openssl/x509.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/buffer.h>
+#endif
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#include <openssl/kssl.h>
+#include <openssl/safestack.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* SSLeay version number for ASN.1 encoding of the session information */
+/* Version 0 - initial version
+ * Version 1 - added the optional peer certificate
+ */
+#define SSL_SESSION_ASN1_VERSION 0x0001
+
+/* text strings for the ciphers */
+#define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5
+#define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5
+#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5
+#define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5
+#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5
+#define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5
+#define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5
+#define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA
+
+/* VRS Additional Kerberos5 entries
+ */
+#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_RC4_128_SHA SSL3_TXT_KRB5_RC4_128_SHA
+#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_TXT_KRB5_RC4_128_MD5 SSL3_TXT_KRB5_RC4_128_MD5
+#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_RC2_40_CBC_SHA SSL3_TXT_KRB5_RC2_40_CBC_SHA
+#define SSL_TXT_KRB5_RC4_40_SHA SSL3_TXT_KRB5_RC4_40_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_RC2_40_CBC_MD5 SSL3_TXT_KRB5_RC2_40_CBC_MD5
+#define SSL_TXT_KRB5_RC4_40_MD5 SSL3_TXT_KRB5_RC4_40_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256
+
+#define SSL_MAX_SSL_SESSION_ID_LENGTH 32
+#define SSL_MAX_SID_CTX_LENGTH 32
+
+#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
+#define SSL_MAX_KEY_ARG_LENGTH 8
+#define SSL_MAX_MASTER_KEY_LENGTH 48
+
+/* These are used to specify which ciphers to use and not to use */
+#define SSL_TXT_LOW "LOW"
+#define SSL_TXT_MEDIUM "MEDIUM"
+#define SSL_TXT_HIGH "HIGH"
+#define SSL_TXT_FIPS "FIPS"
+#define SSL_TXT_kFZA "kFZA"
+#define SSL_TXT_aFZA "aFZA"
+#define SSL_TXT_eFZA "eFZA"
+#define SSL_TXT_FZA "FZA"
+
+#define SSL_TXT_aNULL "aNULL"
+#define SSL_TXT_eNULL "eNULL"
+#define SSL_TXT_NULL "NULL"
+
+#define SSL_TXT_kKRB5 "kKRB5"
+#define SSL_TXT_aKRB5 "aKRB5"
+#define SSL_TXT_KRB5 "KRB5"
+
+#define SSL_TXT_kRSA "kRSA"
+#define SSL_TXT_kDHr "kDHr"
+#define SSL_TXT_kDHd "kDHd"
+#define SSL_TXT_kEDH "kEDH"
+#define SSL_TXT_aRSA "aRSA"
+#define SSL_TXT_aDSS "aDSS"
+#define SSL_TXT_aDH "aDH"
+#define SSL_TXT_DSS "DSS"
+#define SSL_TXT_DH "DH"
+#define SSL_TXT_EDH "EDH"
+#define SSL_TXT_ADH "ADH"
+#define SSL_TXT_RSA "RSA"
+#define SSL_TXT_DES "DES"
+#define SSL_TXT_3DES "3DES"
+#define SSL_TXT_RC4 "RC4"
+#define SSL_TXT_RC2 "RC2"
+#define SSL_TXT_IDEA "IDEA"
+#define SSL_TXT_SEED "SEED"
+#define SSL_TXT_AES "AES"
+#define SSL_TXT_CAMELLIA "CAMELLIA"
+#define SSL_TXT_MD5 "MD5"
+#define SSL_TXT_SHA1 "SHA1"
+#define SSL_TXT_SHA "SHA"
+#define SSL_TXT_EXP "EXP"
+#define SSL_TXT_EXPORT "EXPORT"
+#define SSL_TXT_EXP40 "EXPORT40"
+#define SSL_TXT_EXP56 "EXPORT56"
+#define SSL_TXT_SSLV2 "SSLv2"
+#define SSL_TXT_SSLV3 "SSLv3"
+#define SSL_TXT_TLSV1 "TLSv1"
+#define SSL_TXT_ALL "ALL"
+#define SSL_TXT_ECC "ECCdraft" /* ECC ciphersuites are not yet official */
+
+/*
+ * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
+ * ciphers normally not being used.
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers
+ * without authentication, which would normally disabled by DEFAULT (due
+ * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
+ * will make sure that it is also disabled in the specific selection.
+ * COMPLEMENTOF* identifiers are portable between version, as adjustments
+ * to the default cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed
+ * for DEFAULT.
+ */
+#define SSL_TXT_CMPALL "COMPLEMENTOFALL"
+#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
+
+/* The following cipher list is used by default.
+ * It also is substituted when an application-defined cipher list string
+ * starts with 'DEFAULT'. */
+#define SSL_DEFAULT_CIPHER_LIST "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" /* low priority for RC4 */
+
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
+#define SSL_SENT_SHUTDOWN 1
+#define SSL_RECEIVED_SHUTDOWN 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
+#define OPENSSL_NO_SSL2
+#endif
+
+#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
+#define SSL_FILETYPE_PEM X509_FILETYPE_PEM
+
+/* This is needed to stop compilers complaining about the
+ * 'struct ssl_st *' function parameters used to prototype callbacks
+ * in SSL_CTX. */
+typedef struct ssl_st *ssl_crock_st;
+
+/* used to hold info on the particular ciphers used */
+typedef struct ssl_cipher_st
+ {
+ int valid;
+ const char *name; /* text name */
+ unsigned long id; /* id, 4 bytes, first is version */
+ unsigned long algorithms; /* what ciphers are used */
+ unsigned long algo_strength; /* strength and export flags */
+ unsigned long algorithm2; /* Extra flags */
+ int strength_bits; /* Number of bits really used */
+ int alg_bits; /* Number of bits for algorithm */
+ unsigned long mask; /* used for matching */
+ unsigned long mask_strength; /* also used for matching */
+ } SSL_CIPHER;
+
+DECLARE_STACK_OF(SSL_CIPHER)
+
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+typedef struct ssl_method_st
+ {
+ int version;
+ int (*ssl_new)(SSL *s);
+ void (*ssl_clear)(SSL *s);
+ void (*ssl_free)(SSL *s);
+ int (*ssl_accept)(SSL *s);
+ int (*ssl_connect)(SSL *s);
+ int (*ssl_read)(SSL *s,void *buf,int len);
+ int (*ssl_peek)(SSL *s,void *buf,int len);
+ int (*ssl_write)(SSL *s,const void *buf,int len);
+ int (*ssl_shutdown)(SSL *s);
+ int (*ssl_renegotiate)(SSL *s);
+ int (*ssl_renegotiate_check)(SSL *s);
+ long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
+ max, int *ok);
+ int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,
+ int peek);
+ int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
+ int (*ssl_dispatch_alert)(SSL *s);
+ long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
+ long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
+ SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
+ int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
+ int (*ssl_pending)(const SSL *s);
+ int (*num_ciphers)(void);
+ SSL_CIPHER *(*get_cipher)(unsigned ncipher);
+ struct ssl_method_st *(*get_ssl_method)(int version);
+ long (*get_timeout)(void);
+ struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
+ int (*ssl_version)(void);
+ long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
+ long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
+ } SSL_METHOD;
+
+/* Lets make this into an ASN.1 type structure as follows
+ * SSL_SESSION_ID ::= SEQUENCE {
+ * version INTEGER, -- structure version number
+ * SSLversion INTEGER, -- SSL version number
+ * Cipher OCTET_STRING, -- the 3 byte cipher ID
+ * Session_ID OCTET_STRING, -- the Session ID
+ * Master_key OCTET_STRING, -- the master key
+ * KRB5_principal OCTET_STRING -- optional Kerberos principal
+ * Key_Arg [ 0 ] IMPLICIT OCTET_STRING, -- the optional Key argument
+ * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time
+ * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
+ * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
+ * Session_ID_context [ 4 ] EXPLICIT OCTET_STRING, -- the Session ID context
+ * Verify_result [ 5 ] EXPLICIT INTEGER -- X509_V_... code for `Peer'
+ * Compression [6] IMPLICIT ASN1_OBJECT -- compression OID XXXXX
+ * }
+ * Look in ssl/ssl_asn1.c for more details
+ * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
+ */
+typedef struct ssl_session_st
+ {
+ int ssl_version; /* what ssl version session info is
+ * being kept in here? */
+
+ /* only really used in SSLv2 */
+ unsigned int key_arg_length;
+ unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
+ int master_key_length;
+ unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ /* session_id - valid? */
+ unsigned int session_id_length;
+ unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
+ /* this is used to determine whether the session is being reused in
+ * the appropriate context. It is up to the application to set this,
+ * via SSL_new */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+#ifndef OPENSSL_NO_KRB5
+ unsigned int krb5_client_princ_len;
+ unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
+#endif /* OPENSSL_NO_KRB5 */
+
+ int not_resumable;
+
+ /* The cert is the certificate used to establish this connection */
+ struct sess_cert_st /* SESS_CERT */ *sess_cert;
+
+ /* This is the cert for the other end.
+ * On clients, it will be the same as sess_cert->peer_key->x509
+ * (the latter is not enough as sess_cert is not retained
+ * in the external representation of sessions, see ssl_asn1.c). */
+ X509 *peer;
+ /* when app_verify_callback accepts a session where the peer's certificate
+ * is not ok, we must remember the error for session reuse: */
+ long verify_result; /* only for servers */
+
+ int references;
+ long timeout;
+ long time;
+
+ int compress_meth; /* Need to lookup the method */
+
+ SSL_CIPHER *cipher;
+ unsigned long cipher_id; /* when ASN.1 loaded, this
+ * needs to be used to load
+ * the 'cipher' structure */
+
+ STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+
+ CRYPTO_EX_DATA ex_data; /* application specific data */
+
+ /* These are used to make removal of session-ids more
+ * efficient and to implement a maximum cache size. */
+ struct ssl_session_st *prev,*next;
+#ifndef OPENSSL_NO_TLSEXT
+ char *tlsext_hostname;
+ /* RFC4507 info */
+ unsigned char *tlsext_tick; /* Session ticket */
+ size_t tlsext_ticklen; /* Session ticket length */
+ long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
+#endif
+ } SSL_SESSION;
+
+
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
+/* Allow initial connection to servers that don't support RI */
+#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L
+#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
+#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L /* no effect since 0.9.7h and 0.9.8b */
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
+#define SSL_OP_TLS_D5_BUG 0x00000100L
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
+
+/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
+ * in OpenSSL 0.9.6d. Usually (depending on the application protocol)
+ * the workaround is not needed. Unfortunately some broken SSL/TLS
+ * implementations cannot handle it at all, which is why we include
+ * it in SSL_OP_ALL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L /* added in 0.9.6e */
+
+/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
+ * This used to be 0x000FFFFFL before 0.9.7. */
+#define SSL_OP_ALL 0x00000FFFL
+
+/* DTLS options */
+#define SSL_OP_NO_QUERY_MTU 0x00001000L
+/* Turn on Cookie Exchange (on relevant for servers) */
+#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
+/* Don't use RFC4507 ticket extension */
+#define SSL_OP_NO_TICKET 0x00004000L
+/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client) */
+#define SSL_OP_CISCO_ANYCONNECT 0x00008000L
+
+/* As server, disallow session resumption on renegotiation */
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
+/* Permit unsafe legacy renegotiation */
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
+/* If set, always create a new key when using tmp_ecdh parameters */
+#define SSL_OP_SINGLE_ECDH_USE 0x00080000L
+/* If set, always create a new key when using tmp_dh parameters */
+#define SSL_OP_SINGLE_DH_USE 0x00100000L
+/* Set to always use the tmp_rsa key when doing RSA operations,
+ * even when this violates protocol specs */
+#define SSL_OP_EPHEMERAL_RSA 0x00200000L
+/* Set on servers to choose the cipher according to the server's
+ * preferences */
+#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
+/* If set, a server will allow a client to issue a SSLv3.0 version number
+ * as latest version supported in the premaster secret, even when TLSv1.0
+ * (version 3.1) was announced in the client hello. Normally this is
+ * forbidden to prevent version rollback attacks. */
+#define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
+
+#define SSL_OP_NO_SSLv2 0x01000000L
+#define SSL_OP_NO_SSLv3 0x02000000L
+#define SSL_OP_NO_TLSv1 0x04000000L
+
+/* The next flag deliberately changes the ciphertest, this is a check
+ * for the PKCS#1 attack */
+#define SSL_OP_PKCS1_CHECK_1 0x08000000L
+#define SSL_OP_PKCS1_CHECK_2 0x10000000L
+#define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
+
+
+/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written): */
+#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L
+/* Make it possible to retry SSL_write() with changed buffer location
+ * (buffer contents must stay the same!); this is not the default to avoid
+ * the misconception that non-blocking SSL_write() behaves like
+ * non-blocking write(): */
+#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
+/* Never bother the application with retries if the transport
+ * is blocking: */
+#define SSL_MODE_AUTO_RETRY 0x00000004L
+/* Don't attempt to automatically build certificate chain */
+#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
+
+
+/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
+ * they cannot be used to clear bits. */
+
+#define SSL_CTX_set_options(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_CTX_clear_options(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_CTX_get_options(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
+#define SSL_set_options(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_clear_options(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_get_options(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
+
+#define SSL_CTX_set_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+#define SSL_CTX_clear_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_CTX_get_mode(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
+#define SSL_clear_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_set_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+#define SSL_get_mode(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mtu(ssl, mtu) \
+ SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+
+#define SSL_get_secure_renegotiation_support(ssl) \
+ SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+
+
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
+#else
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
+#endif
+
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20)
+
+/* This callback type is used inside SSL_CTX, SSL, and in the functions that set
+ * them. It is used to override the generation of SSL/TLS session IDs in a
+ * server. Return value should be zero on an error, non-zero to proceed. Also,
+ * callbacks should themselves check if the id they generate is unique otherwise
+ * the SSL handshake will fail with an error - callbacks can do this using the
+ * 'ssl' value they're passed by;
+ * SSL_has_matching_session_id(ssl, id, *id_len)
+ * The length value passed in is set at the maximum size the session ID can be.
+ * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
+ * can alter this length to be less if desired, but under SSLv2 session IDs are
+ * supposed to be fixed at 16 bytes so the id will be padded after the callback
+ * returns in this case. It is also an error for the callback to set the size to
+ * zero. */
+typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
+ unsigned int *id_len);
+
+typedef struct ssl_comp_st
+ {
+ int id;
+ const char *name;
+#ifndef OPENSSL_NO_COMP
+ COMP_METHOD *method;
+#else
+ char *method;
+#endif
+ } SSL_COMP;
+
+DECLARE_STACK_OF(SSL_COMP)
+
+struct ssl_ctx_st
+ {
+ SSL_METHOD *method;
+
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ /* same as above but sorted for lookup */
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+ struct x509_store_st /* X509_STORE */ *cert_store;
+ struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSIONs */
+ /* Most session-ids that will be cached, default is
+ * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
+ unsigned long session_cache_size;
+ struct ssl_session_st *session_cache_head;
+ struct ssl_session_st *session_cache_tail;
+
+ /* This can have one of 2 values, ored together,
+ * SSL_SESS_CACHE_CLIENT,
+ * SSL_SESS_CACHE_SERVER,
+ * Default is SSL_SESSION_CACHE_SERVER, which means only
+ * SSL_accept which cache SSL_SESSIONS. */
+ int session_cache_mode;
+
+ /* If timeout is not 0, it is the default timeout value set
+ * when SSL_new() is called. This has been put in to make
+ * life easier to set things up */
+ long session_timeout;
+
+ /* If this callback is not null, it will be called each
+ * time a session id is added to the cache. If this function
+ * returns 1, it means that the callback will do a
+ * SSL_SESSION_free() when it has finished using it. Otherwise,
+ * on 0, it means the callback has finished with it.
+ * If remove_session_cb is not null, it will be called when
+ * a session-id is removed from the cache. After the call,
+ * OpenSSL will SSL_SESSION_free() it. */
+ int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
+ void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
+ SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
+ unsigned char *data,int len,int *copy);
+
+ struct
+ {
+ int sess_connect; /* SSL new conn - started */
+ int sess_connect_renegotiate;/* SSL reneg - requested */
+ int sess_connect_good; /* SSL new conne/reneg - finished */
+ int sess_accept; /* SSL new accept - started */
+ int sess_accept_renegotiate;/* SSL reneg - requested */
+ int sess_accept_good; /* SSL accept/reneg - finished */
+ int sess_miss; /* session lookup misses */
+ int sess_timeout; /* reuse attempt on timeouted session */
+ int sess_cache_full; /* session removed due to full cache */
+ int sess_hit; /* session reuse actually done */
+ int sess_cb_hit; /* session-id that was not
+ * in the cache was
+ * passed back via the callback. This
+ * indicates that the application is
+ * supplying session-id's from other
+ * processes - spooky :-) */
+ } stats;
+
+ int references;
+
+ /* if defined, these override the X509_verify_cert() calls */
+ int (*app_verify_callback)(X509_STORE_CTX *, void *);
+ void *app_verify_arg;
+ /* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
+ * ('app_verify_callback' was called with just one argument) */
+
+ /* Default password callback. */
+ pem_password_cb *default_passwd_callback;
+
+ /* Default password callback user data. */
+ void *default_passwd_callback_userdata;
+
+ /* get client cert callback */
+ int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+ /* cookie generate callback */
+ int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len);
+
+ /* verify cookie callback */
+ int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie,
+ unsigned int cookie_len);
+
+ CRYPTO_EX_DATA ex_data;
+
+ const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
+ const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
+ const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */
+
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
+
+
+ /* Default values used when no per-SSL value is defined follow */
+
+ void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
+
+ /* what we put in client cert requests */
+ STACK_OF(X509_NAME) *client_CA;
+
+
+ /* Default values to use in SSL structures follow (these are copied by SSL_new) */
+
+ unsigned long options;
+ unsigned long mode;
+ long max_cert_list;
+
+ struct cert_st /* CERT */ *cert;
+ int read_ahead;
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int verify_mode;
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+ int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ X509_VERIFY_PARAM *param;
+
+#if 0
+ int purpose; /* Purpose setting */
+ int trust; /* Trust setting */
+#endif
+
+ int quiet_shutdown;
+
+#ifndef OPENSSL_ENGINE
+ /* Engine to pass requests for client certs to
+ */
+ ENGINE *client_cert_engine;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions servername callback */
+ int (*tlsext_servername_callback)(SSL*, int *, void *);
+ void *tlsext_servername_arg;
+ /* RFC 4507 session ticket keys */
+ unsigned char tlsext_tick_key_name[16];
+ unsigned char tlsext_tick_hmac_key[16];
+ unsigned char tlsext_tick_aes_key[16];
+ /* Callback to support customisation of ticket key setting */
+ int (*tlsext_ticket_key_cb)(SSL *ssl,
+ unsigned char *name, unsigned char *iv,
+ EVP_CIPHER_CTX *ectx,
+ HMAC_CTX *hctx, int enc);
+
+ /* certificate status request info */
+ /* Callback for status request */
+ int (*tlsext_status_cb)(SSL *ssl, void *arg);
+ void *tlsext_status_arg;
+#endif
+
+ };
+
+#define SSL_SESS_CACHE_OFF 0x0000
+#define SSL_SESS_CACHE_CLIENT 0x0001
+#define SSL_SESS_CACHE_SERVER 0x0002
+#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
+/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
+#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
+#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
+#define SSL_SESS_CACHE_NO_INTERNAL \
+ (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
+
+ struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
+#define SSL_CTX_sess_number(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
+#define SSL_CTX_sess_connect(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
+#define SSL_CTX_sess_connect_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
+#define SSL_CTX_sess_connect_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
+#define SSL_CTX_sess_accept_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
+#define SSL_CTX_sess_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
+#define SSL_CTX_sess_cb_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
+#define SSL_CTX_sess_misses(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
+#define SSL_CTX_sess_timeouts(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
+#define SSL_CTX_sess_cache_full(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
+#endif
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
+
+#define SSL_NOTHING 1
+#define SSL_WRITING 2
+#define SSL_READING 3
+#define SSL_X509_LOOKUP 4
+
+/* These will only be used when doing non-blocking IO */
+#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
+#define SSL_want_read(s) (SSL_want(s) == SSL_READING)
+#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
+#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
+
+struct ssl_st
+ {
+ /* protocol version
+ * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
+ */
+ int version;
+ int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
+
+ SSL_METHOD *method; /* SSLv3 */
+
+ /* There are 2 BIO's even though they are normally both the
+ * same. This is so data can be read and written to different
+ * handlers */
+
+#ifndef OPENSSL_NO_BIO
+ BIO *rbio; /* used by SSL_read */
+ BIO *wbio; /* used by SSL_write */
+ BIO *bbio; /* used during session-id reuse to concatenate
+ * messages */
+#else
+ char *rbio; /* used by SSL_read */
+ char *wbio; /* used by SSL_write */
+ char *bbio;
+#endif
+ /* This holds a variable that indicates what we were doing
+ * when a 0 or -1 is returned. This is needed for
+ * non-blocking IO so we know what request needs re-doing when
+ * in SSL_accept or SSL_connect */
+ int rwstate;
+
+ /* true when we are actually in SSL_accept() or SSL_connect() */
+ int in_handshake;
+ int (*handshake_func)(SSL *);
+
+ /* Imagine that here's a boolean member "init" that is
+ * switched as soon as SSL_set_{accept/connect}_state
+ * is called for the first time, so that "state" and
+ * "handshake_func" are properly initialized. But as
+ * handshake_func is == 0 until then, we use this
+ * test instead of an "init" member.
+ */
+
+ int server; /* are we the server side? - mostly used by SSL_clear*/
+
+ int new_session;/* 1 if we are to use a new session.
+ * 2 if we are a server and are inside a handshake
+ * (i.e. not just sending a HelloRequest)
+ * NB: For servers, the 'new' session may actually be a previously
+ * cached session or even the previous session unless
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+ int quiet_shutdown;/* don't send shutdown packets */
+ int shutdown; /* we have shut things down, 0x01 sent, 0x02
+ * for received */
+ int state; /* where we are */
+ int rstate; /* where we are when reading */
+
+ BUF_MEM *init_buf; /* buffer used during init */
+ void *init_msg; /* pointer to handshake message body, set by ssl3_get_message() */
+ int init_num; /* amount read/written */
+ int init_off; /* amount read/written */
+
+ /* used internally to point at a raw packet */
+ unsigned char *packet;
+ unsigned int packet_length;
+
+ struct ssl2_state_st *s2; /* SSLv2 variables */
+ struct ssl3_state_st *s3; /* SSLv3 variables */
+ struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+ int read_ahead; /* Read as many input bytes as possible
+ * (for non-blocking reads) */
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int hit; /* reusing a previous session */
+
+ X509_VERIFY_PARAM *param;
+
+#if 0
+ int purpose; /* Purpose setting */
+ int trust; /* Trust setting */
+#endif
+
+ /* crypto */
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+ /* These are the ones being used, the ones in SSL_SESSION are
+ * the ones to be 'copied' into these ones */
+
+ EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
+ const EVP_MD *read_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *expand; /* uncompress */
+#else
+ char *expand;
+#endif
+
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ const EVP_MD *write_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *compress; /* compression */
+#else
+ char *compress;
+#endif
+
+ /* session info */
+
+ /* client cert? */
+ /* This is used to hold the server certificate used */
+ struct cert_st /* CERT */ *cert;
+
+ /* the session_id_context is used to ensure sessions are only reused
+ * in the appropriate context */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+ /* This can also be in the session once a session is established */
+ SSL_SESSION *session;
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ /* Used in SSL2 and SSL3 */
+ int verify_mode; /* 0 don't care about verify failure.
+ * 1 fail if verify fails */
+ int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+ void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
+
+ int error; /* error bytes to be written */
+ int error_code; /* actual code */
+
+#ifndef OPENSSL_NO_KRB5
+ KSSL_CTX *kssl_ctx; /* Kerberos 5 context */
+#endif /* OPENSSL_NO_KRB5 */
+
+ SSL_CTX *ctx;
+ /* set this flag to 1 and a sleep(1) is put into all SSL_read()
+ * and SSL_write() calls, good for nbio debuging :-) */
+ int debug;
+
+ /* extra application data */
+ long verify_result;
+ CRYPTO_EX_DATA ex_data;
+
+ /* for server side, keep the list of CA_dn we can use */
+ STACK_OF(X509_NAME) *client_CA;
+
+ int references;
+ unsigned long options; /* protocol behaviour */
+ unsigned long mode; /* API behaviour */
+ long max_cert_list;
+ int first_packet;
+ int client_version; /* what was passed, used for
+ * SSLv3/TLS rollback check */
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extension debug callback */
+ void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
+ unsigned char *data, int len,
+ void *arg);
+ void *tlsext_debug_arg;
+ char *tlsext_hostname;
+ int servername_done; /* no further mod of servername
+ 0 : call the servername extension callback.
+ 1 : prepare 2, allow last ack just after in server callback.
+ 2 : don't call servername callback, no ack in server hello
+ */
+ /* certificate status request info */
+ /* Status type or -1 if no status type */
+ int tlsext_status_type;
+ /* Expect OCSP CertificateStatus message */
+ int tlsext_status_expected;
+ /* OCSP status request only */
+ STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+ X509_EXTENSIONS *tlsext_ocsp_exts;
+ /* OCSP response received or to be sent */
+ unsigned char *tlsext_ocsp_resp;
+ int tlsext_ocsp_resplen;
+
+ /* RFC4507 session ticket expected to be received or sent */
+ int tlsext_ticket_expected;
+ SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/ssl2.h>
+#include <openssl/ssl3.h>
+#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
+#include <openssl/dtls1.h> /* Datagram TLS */
+#include <openssl/ssl23.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* compatibility */
+#define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg))
+#define SSL_get_app_data(s) (SSL_get_ex_data(s,0))
+#define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a))
+#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0))
+#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0))
+#define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg))
+
+/* The following are the possible values for ssl->state are are
+ * used to indicate where we are up to in the SSL connection establishment.
+ * The macros that follow are about the only things you should need to use
+ * and even then, only when using non-blocking IO.
+ * It can also be useful to work out where you were when the connection
+ * failed */
+
+#define SSL_ST_CONNECT 0x1000
+#define SSL_ST_ACCEPT 0x2000
+#define SSL_ST_MASK 0x0FFF
+#define SSL_ST_INIT (SSL_ST_CONNECT|SSL_ST_ACCEPT)
+#define SSL_ST_BEFORE 0x4000
+#define SSL_ST_OK 0x03
+#define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT)
+
+#define SSL_CB_LOOP 0x01
+#define SSL_CB_EXIT 0x02
+#define SSL_CB_READ 0x04
+#define SSL_CB_WRITE 0x08
+#define SSL_CB_ALERT 0x4000 /* used in callback */
+#define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ)
+#define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE)
+#define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP)
+#define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT)
+#define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP)
+#define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT)
+#define SSL_CB_HANDSHAKE_START 0x10
+#define SSL_CB_HANDSHAKE_DONE 0x20
+
+/* Is the SSL_connection established? */
+#define SSL_get_state(a) SSL_state(a)
+#define SSL_is_init_finished(a) (SSL_state(a) == SSL_ST_OK)
+#define SSL_in_init(a) (SSL_state(a)&SSL_ST_INIT)
+#define SSL_in_before(a) (SSL_state(a)&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a) (SSL_state(a)&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a) (SSL_state(a)&SSL_ST_ACCEPT)
+
+/* The following 2 states are kept in ssl->rstate when reads fail,
+ * you should not need these */
+#define SSL_ST_READ_HEADER 0xF0
+#define SSL_ST_READ_BODY 0xF1
+#define SSL_ST_READ_DONE 0xF2
+
+/* Obtain latest Finished message
+ * -- that we sent (SSL_get_finished)
+ * -- that we expected from peer (SSL_get_peer_finished).
+ * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
+ * are 'ored' with SSL_VERIFY_PEER if they are desired */
+#define SSL_VERIFY_NONE 0x00
+#define SSL_VERIFY_PEER 0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
+#define SSL_VERIFY_CLIENT_ONCE 0x04
+
+#define OpenSSL_add_ssl_algorithms() SSL_library_init()
+#define SSLeay_add_ssl_algorithms() SSL_library_init()
+
+/* this is for backward compatibility */
+#if 0 /* NEW_SSLEAY */
+#define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
+#define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n)
+#define SSL_add_session(a,b) SSL_CTX_add_session((a),(b))
+#define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b))
+#define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b))
+#endif
+/* More backward compatibility */
+#define SSL_get_cipher(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_cipher_bits(s,np) \
+ SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+#define SSL_get_cipher_version(s) \
+ SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+#define SSL_get_cipher_name(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a) SSL_SESSION_get_time(a)
+#define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b))
+#define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b))
+
+#if 1 /*SSLEAY_MACROS*/
+#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
+#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+ (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) PEM_ASN1_read_bio_of(SSL_SESSION,d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,cb,u)
+#define PEM_write_SSL_SESSION(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+ PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_SSL_SESSION(bp,x) \
+ PEM_ASN1_write_bio_of(SSL_SESSION,i2d_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,NULL,NULL,0,NULL,NULL)
+#endif
+
+#define SSL_AD_REASON_OFFSET 1000
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC /* fatal */
+#define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE/* fatal */
+#define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER /* fatal */
+#define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA /* fatal */
+#define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED /* fatal */
+#define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR /* fatal */
+#define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION/* fatal */
+#define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
+#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */
+#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
+#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+
+#define SSL_ERROR_NONE 0
+#define SSL_ERROR_SSL 1
+#define SSL_ERROR_WANT_READ 2
+#define SSL_ERROR_WANT_WRITE 3
+#define SSL_ERROR_WANT_X509_LOOKUP 4
+#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */
+#define SSL_ERROR_ZERO_RETURN 6
+#define SSL_ERROR_WANT_CONNECT 7
+#define SSL_ERROR_WANT_ACCEPT 8
+
+#define SSL_CTRL_NEED_TMP_RSA 1
+#define SSL_CTRL_SET_TMP_RSA 2
+#define SSL_CTRL_SET_TMP_DH 3
+#define SSL_CTRL_SET_TMP_ECDH 4
+#define SSL_CTRL_SET_TMP_RSA_CB 5
+#define SSL_CTRL_SET_TMP_DH_CB 6
+#define SSL_CTRL_SET_TMP_ECDH_CB 7
+
+#define SSL_CTRL_GET_SESSION_REUSED 8
+#define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9
+#define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12
+#define SSL_CTRL_GET_FLAGS 13
+#define SSL_CTRL_EXTRA_CHAIN_CERT 14
+
+#define SSL_CTRL_SET_MSG_CALLBACK 15
+#define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
+
+/* only applies to datagram connections */
+#define SSL_CTRL_SET_MTU 17
+/* Stats */
+#define SSL_CTRL_SESS_NUMBER 20
+#define SSL_CTRL_SESS_CONNECT 21
+#define SSL_CTRL_SESS_CONNECT_GOOD 22
+#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23
+#define SSL_CTRL_SESS_ACCEPT 24
+#define SSL_CTRL_SESS_ACCEPT_GOOD 25
+#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26
+#define SSL_CTRL_SESS_HIT 27
+#define SSL_CTRL_SESS_CB_HIT 28
+#define SSL_CTRL_SESS_MISSES 29
+#define SSL_CTRL_SESS_TIMEOUTS 30
+#define SSL_CTRL_SESS_CACHE_FULL 31
+#define SSL_CTRL_OPTIONS 32
+#define SSL_CTRL_MODE 33
+
+#define SSL_CTRL_GET_READ_AHEAD 40
+#define SSL_CTRL_SET_READ_AHEAD 41
+#define SSL_CTRL_SET_SESS_CACHE_SIZE 42
+#define SSL_CTRL_GET_SESS_CACHE_SIZE 43
+#define SSL_CTRL_SET_SESS_CACHE_MODE 44
+#define SSL_CTRL_GET_SESS_CACHE_MODE 45
+
+#define SSL_CTRL_GET_MAX_CERT_LIST 50
+#define SSL_CTRL_SET_MAX_CERT_LIST 51
+
+/* see tls1.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+#define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
+#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
+
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
+
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
+#endif
+
+#define DTLS_CTRL_GET_TIMEOUT 73
+#define DTLS_CTRL_HANDLE_TIMEOUT 74
+#define DTLS_CTRL_LISTEN 75
+
+#define SSL_CTRL_GET_RI_SUPPORT 76
+#define SSL_CTRL_CLEAR_OPTIONS 77
+#define SSL_CTRL_CLEAR_MODE 78
+
+#define DTLSv1_get_timeout(ssl, arg) \
+ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
+#define DTLSv1_handle_timeout(ssl) \
+ SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
+#define DTLSv1_listen(ssl, peer) \
+ SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
+
+#define SSL_session_reused(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+#define SSL_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_clear_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_total_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
+
+#define SSL_CTX_need_tmp_RSA(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_CTX_set_tmp_rsa(ctx,rsa) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_CTX_set_tmp_dh(ctx,dh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_need_tmp_RSA(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_set_tmp_ecdh(ssl,ecdh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_CTX_add_extra_chain_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_ssl(void);
+BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
+int BIO_ssl_copy_session_id(BIO *to,BIO *from);
+void BIO_ssl_shutdown(BIO *ssl_bio);
+
+#endif
+
+int SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
+SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
+void SSL_CTX_free(SSL_CTX *);
+long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
+long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
+int SSL_want(const SSL *s);
+int SSL_clear(SSL *s);
+
+void SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
+
+SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+int SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
+char * SSL_CIPHER_get_version(const SSL_CIPHER *c);
+const char * SSL_CIPHER_get_name(const SSL_CIPHER *c);
+
+int SSL_get_fd(const SSL *s);
+int SSL_get_rfd(const SSL *s);
+int SSL_get_wfd(const SSL *s);
+const char * SSL_get_cipher_list(const SSL *s,int n);
+char * SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
+int SSL_get_read_ahead(const SSL * s);
+int SSL_pending(const SSL *s);
+#ifndef OPENSSL_NO_SOCK
+int SSL_set_fd(SSL *s, int fd);
+int SSL_set_rfd(SSL *s, int fd);
+int SSL_set_wfd(SSL *s, int fd);
+#endif
+#ifndef OPENSSL_NO_BIO
+void SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
+BIO * SSL_get_rbio(const SSL *s);
+BIO * SSL_get_wbio(const SSL *s);
+#endif
+int SSL_set_cipher_list(SSL *s, const char *str);
+void SSL_set_read_ahead(SSL *s, int yes);
+int SSL_get_verify_mode(const SSL *s);
+int SSL_get_verify_depth(const SSL *s);
+int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
+void SSL_set_verify(SSL *s, int mode,
+ int (*callback)(int ok,X509_STORE_CTX *ctx));
+void SSL_set_verify_depth(SSL *s, int depth);
+#ifndef OPENSSL_NO_RSA
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+#endif
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
+int SSL_use_certificate(SSL *ssl, X509 *x);
+int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
+int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *file);
+#ifndef OPENSSL_SYS_VMS
+#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *dir);
+#endif
+#endif
+
+#endif
+
+void SSL_load_error_strings(void );
+const char *SSL_state_string(const SSL *s);
+const char *SSL_rstate_string(const SSL *s);
+const char *SSL_state_string_long(const SSL *s);
+const char *SSL_rstate_string_long(const SSL *s);
+long SSL_SESSION_get_time(const SSL_SESSION *s);
+long SSL_SESSION_set_time(SSL_SESSION *s, long t);
+long SSL_SESSION_get_timeout(const SSL_SESSION *s);
+long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+void SSL_copy_session_id(SSL *to,const SSL *from);
+
+SSL_SESSION *SSL_SESSION_new(void);
+unsigned long SSL_SESSION_hash(const SSL_SESSION *a);
+int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+int SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
+#endif
+#ifndef OPENSSL_NO_BIO
+int SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
+#endif
+void SSL_SESSION_free(SSL_SESSION *ses);
+int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
+int SSL_set_session(SSL *to, SSL_SESSION *session);
+int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
+int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
+int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
+int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+ unsigned int id_len);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
+ long length);
+
+#ifdef HEADER_X509_H
+X509 * SSL_get_peer_certificate(const SSL *s);
+#endif
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
+ int (*callback)(int, X509_STORE_CTX *));
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+#endif
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
+ const unsigned char *d, long len);
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
+
+int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+int SSL_check_private_key(const SSL *ctx);
+
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+SSL * SSL_new(SSL_CTX *ctx);
+int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+int SSL_set_purpose(SSL *s, int purpose);
+int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+int SSL_set_trust(SSL *s, int trust);
+
+void SSL_free(SSL *ssl);
+int SSL_accept(SSL *ssl);
+int SSL_connect(SSL *ssl);
+int SSL_read(SSL *ssl,void *buf,int num);
+int SSL_peek(SSL *ssl,void *buf,int num);
+int SSL_write(SSL *ssl,const void *buf,int num);
+long SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+long SSL_callback_ctrl(SSL *, int, void (*)(void));
+long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
+long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+int SSL_get_error(const SSL *s,int ret_code);
+const char *SSL_get_version(const SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
+
+SSL_METHOD *SSLv2_method(void); /* SSLv2 */
+SSL_METHOD *SSLv2_server_method(void); /* SSLv2 */
+SSL_METHOD *SSLv2_client_method(void); /* SSLv2 */
+
+SSL_METHOD *SSLv3_method(void); /* SSLv3 */
+SSL_METHOD *SSLv3_server_method(void); /* SSLv3 */
+SSL_METHOD *SSLv3_client_method(void); /* SSLv3 */
+
+SSL_METHOD *SSLv23_method(void); /* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_server_method(void); /* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_client_method(void); /* SSLv3 but can rollback to v2 */
+
+SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
+SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */
+SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */
+
+SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
+SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */
+SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */
+
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+
+int SSL_do_handshake(SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_pending(SSL *s);
+int SSL_shutdown(SSL *s);
+
+SSL_METHOD *SSL_get_ssl_method(SSL *s);
+int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
+const char *SSL_alert_type_string_long(int value);
+const char *SSL_alert_type_string(int value);
+const char *SSL_alert_desc_string_long(int value);
+const char *SSL_alert_desc_string(int value);
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+int SSL_add_client_CA(SSL *ssl,X509 *x);
+int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
+
+void SSL_set_connect_state(SSL *s);
+void SSL_set_accept_state(SSL *s);
+
+long SSL_get_default_timeout(const SSL *s);
+
+int SSL_library_init(void );
+
+char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
+
+SSL *SSL_dup(SSL *ssl);
+
+X509 *SSL_get_certificate(const SSL *ssl);
+/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl,int mode);
+int SSL_get_quiet_shutdown(const SSL *ssl);
+void SSL_set_shutdown(SSL *ssl,int mode);
+int SSL_get_shutdown(const SSL *ssl);
+int SSL_version(const SSL *ssl);
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath);
+#define SSL_get0_session SSL_get_session /* just peek at pointer */
+SSL_SESSION *SSL_get_session(const SSL *ssl);
+SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
+void SSL_set_info_callback(SSL *ssl,
+ void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
+int SSL_state(const SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl,long v);
+long SSL_get_verify_result(const SSL *ssl);
+
+int SSL_set_ex_data(SSL *ssl,int idx,void *data);
+void *SSL_get_ex_data(const SSL *ssl,int idx);
+int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
+void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
+int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void );
+
+#define SSL_CTX_sess_set_cache_size(ctx,t) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
+#define SSL_CTX_sess_get_cache_size(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
+#define SSL_CTX_set_session_cache_mode(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+#define SSL_CTX_get_session_cache_mode(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
+
+#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
+#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
+#define SSL_CTX_get_read_ahead(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
+#define SSL_CTX_set_read_ahead(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
+#define SSL_CTX_get_max_cert_list(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_CTX_set_max_cert_list(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+#define SSL_get_max_cert_list(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_set_max_cert_list(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+
+ /* NB: the keylength is only applicable when is_export is true */
+#ifndef OPENSSL_NO_RSA
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
+ RSA *(*cb)(SSL *ssl,int is_export,
+ int keylength));
+
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+ RSA *(*cb)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh)(SSL *ssl,int is_export,
+ int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+ DH *(*dh)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+#ifndef OPENSSL_NO_ECDH
+void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
+ EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+ int keylength));
+void SSL_set_tmp_ecdh_callback(SSL *ssl,
+ EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+
+#ifndef OPENSSL_NO_COMP
+const COMP_METHOD *SSL_get_current_compression(SSL *s);
+const COMP_METHOD *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
+#else
+const void *SSL_get_current_compression(SSL *s);
+const void *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const void *comp);
+void *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,void *cm);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_SSL_strings(void);
+
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE 100
+#define SSL_F_CLIENT_FINISHED 167
+#define SSL_F_CLIENT_HELLO 101
+#define SSL_F_CLIENT_MASTER_KEY 102
+#define SSL_F_D2I_SSL_SESSION 103
+#define SSL_F_DO_DTLS1_WRITE 245
+#define SSL_F_DO_SSL3_WRITE 104
+#define SSL_F_DTLS1_ACCEPT 246
+#define SSL_F_DTLS1_ADD_CERT_TO_BUF 280
+#define SSL_F_DTLS1_BUFFER_RECORD 247
+#define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 293
+#define SSL_F_DTLS1_CLIENT_HELLO 248
+#define SSL_F_DTLS1_CONNECT 249
+#define SSL_F_DTLS1_ENC 250
+#define SSL_F_DTLS1_GET_HELLO_VERIFY 251
+#define SSL_F_DTLS1_GET_MESSAGE 252
+#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253
+#define SSL_F_DTLS1_GET_RECORD 254
+#define SSL_F_DTLS1_HANDLE_TIMEOUT 282
+#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277
+#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
+#define SSL_F_DTLS1_PROCESS_RECORD 257
+#define SSL_F_DTLS1_READ_BYTES 258
+#define SSL_F_DTLS1_READ_FAILED 259
+#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST 260
+#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE 261
+#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE 262
+#define SSL_F_DTLS1_SEND_CLIENT_VERIFY 263
+#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 264
+#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE 265
+#define SSL_F_DTLS1_SEND_SERVER_HELLO 266
+#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267
+#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
+#define SSL_F_GET_CLIENT_FINISHED 105
+#define SSL_F_GET_CLIENT_HELLO 106
+#define SSL_F_GET_CLIENT_MASTER_KEY 107
+#define SSL_F_GET_SERVER_FINISHED 108
+#define SSL_F_GET_SERVER_HELLO 109
+#define SSL_F_GET_SERVER_VERIFY 110
+#define SSL_F_I2D_SSL_SESSION 111
+#define SSL_F_READ_N 112
+#define SSL_F_REQUEST_CERTIFICATE 113
+#define SSL_F_SERVER_FINISH 239
+#define SSL_F_SERVER_HELLO 114
+#define SSL_F_SERVER_VERIFY 240
+#define SSL_F_SSL23_ACCEPT 115
+#define SSL_F_SSL23_CLIENT_HELLO 116
+#define SSL_F_SSL23_CONNECT 117
+#define SSL_F_SSL23_GET_CLIENT_HELLO 118
+#define SSL_F_SSL23_GET_SERVER_HELLO 119
+#define SSL_F_SSL23_PEEK 237
+#define SSL_F_SSL23_READ 120
+#define SSL_F_SSL23_WRITE 121
+#define SSL_F_SSL2_ACCEPT 122
+#define SSL_F_SSL2_CONNECT 123
+#define SSL_F_SSL2_ENC_INIT 124
+#define SSL_F_SSL2_GENERATE_KEY_MATERIAL 241
+#define SSL_F_SSL2_PEEK 234
+#define SSL_F_SSL2_READ 125
+#define SSL_F_SSL2_READ_INTERNAL 236
+#define SSL_F_SSL2_SET_CERTIFICATE 126
+#define SSL_F_SSL2_WRITE 127
+#define SSL_F_SSL3_ACCEPT 128
+#define SSL_F_SSL3_ADD_CERT_TO_BUF 281
+#define SSL_F_SSL3_CALLBACK_CTRL 233
+#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129
+#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130
+#define SSL_F_SSL3_CHECK_CLIENT_HELLO 292
+#define SSL_F_SSL3_CLIENT_HELLO 131
+#define SSL_F_SSL3_CONNECT 132
+#define SSL_F_SSL3_CTRL 213
+#define SSL_F_SSL3_CTX_CTRL 133
+#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 279
+#define SSL_F_SSL3_ENC 134
+#define SSL_F_SSL3_GENERATE_KEY_BLOCK 238
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135
+#define SSL_F_SSL3_GET_CERT_STATUS 288
+#define SSL_F_SSL3_GET_CERT_VERIFY 136
+#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137
+#define SSL_F_SSL3_GET_CLIENT_HELLO 138
+#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139
+#define SSL_F_SSL3_GET_FINISHED 140
+#define SSL_F_SSL3_GET_KEY_EXCHANGE 141
+#define SSL_F_SSL3_GET_MESSAGE 142
+#define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283
+#define SSL_F_SSL3_GET_RECORD 143
+#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144
+#define SSL_F_SSL3_GET_SERVER_DONE 145
+#define SSL_F_SSL3_GET_SERVER_HELLO 146
+#define SSL_F_SSL3_NEW_SESSION_TICKET 284
+#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147
+#define SSL_F_SSL3_PEEK 235
+#define SSL_F_SSL3_READ_BYTES 148
+#define SSL_F_SSL3_READ_N 149
+#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150
+#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151
+#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152
+#define SSL_F_SSL3_SEND_CLIENT_VERIFY 153
+#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154
+#define SSL_F_SSL3_SEND_SERVER_HELLO 242
+#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155
+#define SSL_F_SSL3_SETUP_BUFFERS 156
+#define SSL_F_SSL3_SETUP_KEY_BLOCK 157
+#define SSL_F_SSL3_WRITE_BYTES 158
+#define SSL_F_SSL3_WRITE_PENDING 159
+#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 285
+#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 272
+#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215
+#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216
+#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 286
+#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 273
+#define SSL_F_SSL_BAD_METHOD 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161
+#define SSL_F_SSL_CERT_DUP 221
+#define SSL_F_SSL_CERT_INST 222
+#define SSL_F_SSL_CERT_INSTANTIATE 214
+#define SSL_F_SSL_CERT_NEW 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY 163
+#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 274
+#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230
+#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231
+#define SSL_F_SSL_CLEAR 164
+#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165
+#define SSL_F_SSL_CREATE_CIPHER_LIST 166
+#define SSL_F_SSL_CTRL 232
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168
+#define SSL_F_SSL_CTX_NEW 169
+#define SSL_F_SSL_CTX_SET_CIPHER_LIST 269
+#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 278
+#define SSL_F_SSL_CTX_SET_PURPOSE 226
+#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219
+#define SSL_F_SSL_CTX_SET_SSL_VERSION 170
+#define SSL_F_SSL_CTX_SET_TRUST 229
+#define SSL_F_SSL_CTX_USE_CERTIFICATE 171
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179
+#define SSL_F_SSL_DO_HANDSHAKE 180
+#define SSL_F_SSL_GET_NEW_SESSION 181
+#define SSL_F_SSL_GET_PREV_SESSION 217
+#define SSL_F_SSL_GET_SERVER_SEND_CERT 182
+#define SSL_F_SSL_GET_SIGN_PKEY 183
+#define SSL_F_SSL_INIT_WBIO_BUFFER 184
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185
+#define SSL_F_SSL_NEW 186
+#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 287
+#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 290
+#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 289
+#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 291
+#define SSL_F_SSL_PEEK 270
+#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT 275
+#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT 276
+#define SSL_F_SSL_READ 223
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188
+#define SSL_F_SSL_SESSION_NEW 189
+#define SSL_F_SSL_SESSION_PRINT_FP 190
+#define SSL_F_SSL_SESS_CERT_NEW 225
+#define SSL_F_SSL_SET_CERT 191
+#define SSL_F_SSL_SET_CIPHER_LIST 271
+#define SSL_F_SSL_SET_FD 192
+#define SSL_F_SSL_SET_PKEY 193
+#define SSL_F_SSL_SET_PURPOSE 227
+#define SSL_F_SSL_SET_RFD 194
+#define SSL_F_SSL_SET_SESSION 195
+#define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218
+#define SSL_F_SSL_SET_TRUST 228
+#define SSL_F_SSL_SET_WFD 196
+#define SSL_F_SSL_SHUTDOWN 224
+#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION 243
+#define SSL_F_SSL_UNDEFINED_FUNCTION 197
+#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244
+#define SSL_F_SSL_USE_CERTIFICATE 198
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199
+#define SSL_F_SSL_USE_CERTIFICATE_FILE 200
+#define SSL_F_SSL_USE_PRIVATEKEY 201
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203
+#define SSL_F_SSL_USE_RSAPRIVATEKEY 204
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
+#define SSL_F_SSL_VERIFY_CERT_CHAIN 207
+#define SSL_F_SSL_WRITE 208
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
+#define SSL_F_TLS1_ENC 210
+#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
+#define SSL_F_WRITE_PENDING 212
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE 100
+#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
+#define SSL_R_BAD_ALERT_RECORD 101
+#define SSL_R_BAD_AUTHENTICATION_TYPE 102
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
+#define SSL_R_BAD_CHECKSUM 104
+#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106
+#define SSL_R_BAD_DECOMPRESSION 107
+#define SSL_R_BAD_DH_G_LENGTH 108
+#define SSL_R_BAD_DH_PUB_KEY_LENGTH 109
+#define SSL_R_BAD_DH_P_LENGTH 110
+#define SSL_R_BAD_DIGEST_LENGTH 111
+#define SSL_R_BAD_DSA_SIGNATURE 112
+#define SSL_R_BAD_ECC_CERT 304
+#define SSL_R_BAD_ECDSA_SIGNATURE 305
+#define SSL_R_BAD_ECPOINT 306
+#define SSL_R_BAD_HELLO_REQUEST 105
+#define SSL_R_BAD_LENGTH 271
+#define SSL_R_BAD_MAC_DECODE 113
+#define SSL_R_BAD_MESSAGE_TYPE 114
+#define SSL_R_BAD_PACKET_LENGTH 115
+#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116
+#define SSL_R_BAD_RESPONSE_ARGUMENT 117
+#define SSL_R_BAD_RSA_DECRYPT 118
+#define SSL_R_BAD_RSA_ENCRYPT 119
+#define SSL_R_BAD_RSA_E_LENGTH 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH 121
+#define SSL_R_BAD_RSA_SIGNATURE 122
+#define SSL_R_BAD_SIGNATURE 123
+#define SSL_R_BAD_SSL_FILETYPE 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 125
+#define SSL_R_BAD_STATE 126
+#define SSL_R_BAD_WRITE_RETRY 127
+#define SSL_R_BIO_NOT_SET 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129
+#define SSL_R_BN_LIB 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH 131
+#define SSL_R_CA_DN_TOO_LONG 132
+#define SSL_R_CCS_RECEIVED_EARLY 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED 134
+#define SSL_R_CERT_LENGTH_MISMATCH 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR 139
+#define SSL_R_CLIENTHELLO_TLSEXT 157
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140
+#define SSL_R_COMPRESSION_FAILURE 141
+#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307
+#define SSL_R_COMPRESSION_LIBRARY_ERROR 142
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT 143
+#define SSL_R_CONNECTION_TYPE_NOT_SET 144
+#define SSL_R_COOKIE_MISMATCH 308
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145
+#define SSL_R_DATA_LENGTH_TOO_LONG 146
+#define SSL_R_DECRYPTION_FAILED 147
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148
+#define SSL_R_DIGEST_CHECK_FAILED 149
+#define SSL_R_DTLS_MESSAGE_TOO_BIG 318
+#define SSL_R_DUPLICATE_COMPRESSION_ID 309
+#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 310
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150
+#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 282
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE 152
+#define SSL_R_EXTRA_DATA_IN_MESSAGE 153
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154
+#define SSL_R_HTTPS_PROXY_REQUEST 155
+#define SSL_R_HTTP_REQUEST 156
+#define SSL_R_ILLEGAL_PADDING 283
+#define SSL_R_INVALID_CHALLENGE_LENGTH 158
+#define SSL_R_INVALID_COMMAND 280
+#define SSL_R_INVALID_PURPOSE 278
+#define SSL_R_INVALID_STATUS_RESPONSE 316
+#define SSL_R_INVALID_TICKET_KEYS_LENGTH 275
+#define SSL_R_INVALID_TRUST 279
+#define SSL_R_KEY_ARG_TOO_LONG 284
+#define SSL_R_KRB5 285
+#define SSL_R_KRB5_C_CC_PRINC 286
+#define SSL_R_KRB5_C_GET_CRED 287
+#define SSL_R_KRB5_C_INIT 288
+#define SSL_R_KRB5_C_MK_REQ 289
+#define SSL_R_KRB5_S_BAD_TICKET 290
+#define SSL_R_KRB5_S_INIT 291
+#define SSL_R_KRB5_S_RD_REQ 292
+#define SSL_R_KRB5_S_TKT_EXPIRED 293
+#define SSL_R_KRB5_S_TKT_NYV 294
+#define SSL_R_KRB5_S_TKT_SKEW 295
+#define SSL_R_LENGTH_MISMATCH 159
+#define SSL_R_LENGTH_TOO_SHORT 160
+#define SSL_R_LIBRARY_BUG 274
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS 161
+#define SSL_R_MESSAGE_TOO_LONG 296
+#define SSL_R_MISSING_DH_DSA_CERT 162
+#define SSL_R_MISSING_DH_KEY 163
+#define SSL_R_MISSING_DH_RSA_CERT 164
+#define SSL_R_MISSING_DSA_SIGNING_CERT 165
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167
+#define SSL_R_MISSING_RSA_CERTIFICATE 168
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169
+#define SSL_R_MISSING_RSA_SIGNING_CERT 170
+#define SSL_R_MISSING_TMP_DH_KEY 171
+#define SSL_R_MISSING_TMP_ECDH_KEY 311
+#define SSL_R_MISSING_TMP_RSA_KEY 172
+#define SSL_R_MISSING_TMP_RSA_PKEY 173
+#define SSL_R_MISSING_VERIFY_MESSAGE 174
+#define SSL_R_MULTIPLE_SGC_RESTARTS 325
+#define SSL_R_NON_SSLV2_INITIAL_PACKET 175
+#define SSL_R_NO_CERTIFICATES_RETURNED 176
+#define SSL_R_NO_CERTIFICATE_ASSIGNED 177
+#define SSL_R_NO_CERTIFICATE_RETURNED 178
+#define SSL_R_NO_CERTIFICATE_SET 179
+#define SSL_R_NO_CERTIFICATE_SPECIFIED 180
+#define SSL_R_NO_CIPHERS_AVAILABLE 181
+#define SSL_R_NO_CIPHERS_PASSED 182
+#define SSL_R_NO_CIPHERS_SPECIFIED 183
+#define SSL_R_NO_CIPHER_LIST 184
+#define SSL_R_NO_CIPHER_MATCH 185
+#define SSL_R_NO_CLIENT_CERT_METHOD 317
+#define SSL_R_NO_CLIENT_CERT_RECEIVED 186
+#define SSL_R_NO_COMPRESSION_SPECIFIED 187
+#define SSL_R_NO_METHOD_SPECIFIED 188
+#define SSL_R_NO_PRIVATEKEY 189
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190
+#define SSL_R_NO_PROTOCOLS_AVAILABLE 191
+#define SSL_R_NO_PUBLICKEY 192
+#define SSL_R_NO_RENEGOTIATION 319
+#define SSL_R_NO_SHARED_CIPHER 193
+#define SSL_R_NO_VERIFY_CALLBACK 194
+#define SSL_R_NULL_SSL_CTX 195
+#define SSL_R_NULL_SSL_METHOD_PASSED 196
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
+#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297
+#define SSL_R_PACKET_LENGTH_TOO_LONG 198
+#define SSL_R_PARSE_TLSEXT 223
+#define SSL_R_PATH_TOO_LONG 270
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199
+#define SSL_R_PEER_ERROR 200
+#define SSL_R_PEER_ERROR_CERTIFICATE 201
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE 202
+#define SSL_R_PEER_ERROR_NO_CIPHER 203
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206
+#define SSL_R_PROTOCOL_IS_SHUTDOWN 207
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209
+#define SSL_R_PUBLIC_KEY_NOT_RSA 210
+#define SSL_R_READ_BIO_NOT_SET 211
+#define SSL_R_READ_TIMEOUT_EXPIRED 312
+#define SSL_R_READ_WRONG_PACKET_TYPE 212
+#define SSL_R_RECORD_LENGTH_MISMATCH 213
+#define SSL_R_RECORD_TOO_LARGE 214
+#define SSL_R_RECORD_TOO_SMALL 298
+#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 320
+#define SSL_R_RENEGOTIATION_ENCODING_ERR 321
+#define SSL_R_RENEGOTIATION_MISMATCH 322
+#define SSL_R_REQUIRED_CIPHER_MISSING 215
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218
+#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 324
+#define SSL_R_SERVERHELLO_TLSEXT 224
+#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
+#define SSL_R_SHORT_READ 219
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
+#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221
+#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 299
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 225
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 226
+#define SSL_R_SSL3_SESSION_ID_TOO_LONG 300
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228
+#define SSL_R_SSL_HANDSHAKE_FAILURE 229
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230
+#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301
+#define SSL_R_SSL_SESSION_ID_CONFLICT 302
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273
+#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236
+#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS 313
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238
+#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
+#define SSL_R_UNEXPECTED_MESSAGE 244
+#define SSL_R_UNEXPECTED_RECORD 245
+#define SSL_R_UNINITIALIZED 276
+#define SSL_R_UNKNOWN_ALERT_TYPE 246
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247
+#define SSL_R_UNKNOWN_CIPHER_RETURNED 248
+#define SSL_R_UNKNOWN_CIPHER_TYPE 249
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250
+#define SSL_R_UNKNOWN_PKEY_TYPE 251
+#define SSL_R_UNKNOWN_PROTOCOL 252
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253
+#define SSL_R_UNKNOWN_SSL_VERSION 254
+#define SSL_R_UNKNOWN_STATE 255
+#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 323
+#define SSL_R_UNSUPPORTED_CIPHER 256
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257
+#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315
+#define SSL_R_UNSUPPORTED_PROTOCOL 258
+#define SSL_R_UNSUPPORTED_SSL_VERSION 259
+#define SSL_R_UNSUPPORTED_STATUS_TYPE 329
+#define SSL_R_WRITE_BIO_NOT_SET 260
+#define SSL_R_WRONG_CIPHER_RETURNED 261
+#define SSL_R_WRONG_MESSAGE_TYPE 262
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263
+#define SSL_R_WRONG_SIGNATURE_LENGTH 264
+#define SSL_R_WRONG_SIGNATURE_SIZE 265
+#define SSL_R_WRONG_SSL_VERSION 266
+#define SSL_R_WRONG_VERSION_NUMBER 267
+#define SSL_R_X509_LIB 268
+#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ssl2.h b/src/Mayaqua/win32_inc/openssl/ssl2.h
new file mode 100644
index 00000000..c871efec
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl2.h
@@ -0,0 +1,268 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL2_H
+#define HEADER_SSL2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Protocol Version Codes */
+#define SSL2_VERSION 0x0002
+#define SSL2_VERSION_MAJOR 0x00
+#define SSL2_VERSION_MINOR 0x02
+/* #define SSL2_CLIENT_VERSION 0x0002 */
+/* #define SSL2_SERVER_VERSION 0x0002 */
+
+/* Protocol Message Codes */
+#define SSL2_MT_ERROR 0
+#define SSL2_MT_CLIENT_HELLO 1
+#define SSL2_MT_CLIENT_MASTER_KEY 2
+#define SSL2_MT_CLIENT_FINISHED 3
+#define SSL2_MT_SERVER_HELLO 4
+#define SSL2_MT_SERVER_VERIFY 5
+#define SSL2_MT_SERVER_FINISHED 6
+#define SSL2_MT_REQUEST_CERTIFICATE 7
+#define SSL2_MT_CLIENT_CERTIFICATE 8
+
+/* Error Message Codes */
+#define SSL2_PE_UNDEFINED_ERROR 0x0000
+#define SSL2_PE_NO_CIPHER 0x0001
+#define SSL2_PE_NO_CERTIFICATE 0x0002
+#define SSL2_PE_BAD_CERTIFICATE 0x0004
+#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
+
+/* Cipher Kind Values */
+#define SSL2_CK_NULL_WITH_MD5 0x02000000 /* v3 */
+#define SSL2_CK_RC4_128_WITH_MD5 0x02010080
+#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5 0x02020080
+#define SSL2_CK_RC2_128_CBC_WITH_MD5 0x02030080
+#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x02040080
+#define SSL2_CK_IDEA_128_CBC_WITH_MD5 0x02050080
+#define SSL2_CK_DES_64_CBC_WITH_MD5 0x02060040
+#define SSL2_CK_DES_64_CBC_WITH_SHA 0x02060140 /* v3 */
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 0x020700c0
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA 0x020701c0 /* v3 */
+#define SSL2_CK_RC4_64_WITH_MD5 0x02080080 /* MS hack */
+
+#define SSL2_CK_DES_64_CFB64_WITH_MD5_1 0x02ff0800 /* SSLeay */
+#define SSL2_CK_NULL 0x02ff0810 /* SSLeay */
+
+#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1 "DES-CFB-M1"
+#define SSL2_TXT_NULL_WITH_MD5 "NULL-MD5"
+#define SSL2_TXT_RC4_128_WITH_MD5 "RC4-MD5"
+#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 "EXP-RC4-MD5"
+#define SSL2_TXT_RC2_128_CBC_WITH_MD5 "RC2-CBC-MD5"
+#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 "EXP-RC2-CBC-MD5"
+#define SSL2_TXT_IDEA_128_CBC_WITH_MD5 "IDEA-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_MD5 "DES-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_SHA "DES-CBC-SHA"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 "DES-CBC3-MD5"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA "DES-CBC3-SHA"
+#define SSL2_TXT_RC4_64_WITH_MD5 "RC4-64-MD5"
+
+#define SSL2_TXT_NULL "NULL"
+
+/* Flags for the SSL_CIPHER.algorithm2 field */
+#define SSL2_CF_5_BYTE_ENC 0x01
+#define SSL2_CF_8_BYTE_ENC 0x02
+
+/* Certificate Type Codes */
+#define SSL2_CT_X509_CERTIFICATE 0x01
+
+/* Authentication Type Code */
+#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION 0x01
+
+#define SSL2_MAX_SSL_SESSION_ID_LENGTH 32
+
+/* Upper/Lower Bounds */
+#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256
+#ifdef OPENSSL_SYS_MPE
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 29998u
+#else
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u /* 2^15-1 */
+#endif
+#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /* 2^14-1 */
+
+#define SSL2_CHALLENGE_LENGTH 16
+/*#define SSL2_CHALLENGE_LENGTH 32 */
+#define SSL2_MIN_CHALLENGE_LENGTH 16
+#define SSL2_MAX_CHALLENGE_LENGTH 32
+#define SSL2_CONNECTION_ID_LENGTH 16
+#define SSL2_MAX_CONNECTION_ID_LENGTH 16
+#define SSL2_SSL_SESSION_ID_LENGTH 16
+#define SSL2_MAX_CERT_CHALLENGE_LENGTH 32
+#define SSL2_MIN_CERT_CHALLENGE_LENGTH 16
+#define SSL2_MAX_KEY_MATERIAL_LENGTH 24
+
+#ifndef HEADER_SSL_LOCL_H
+#define CERT char
+#endif
+
+typedef struct ssl2_state_st
+ {
+ int three_byte_header;
+ int clear_text; /* clear text */
+ int escape; /* not used in SSLv2 */
+ int ssl2_rollback; /* used if SSLv23 rolled back to SSLv2 */
+
+ /* non-blocking io info, used to make sure the same
+ * args were passwd */
+ unsigned int wnum; /* number of bytes sent so far */
+ int wpend_tot;
+ const unsigned char *wpend_buf;
+
+ int wpend_off; /* offset to data to write */
+ int wpend_len; /* number of bytes passwd to write */
+ int wpend_ret; /* number of bytes to return to caller */
+
+ /* buffer raw data */
+ int rbuf_left;
+ int rbuf_offs;
+ unsigned char *rbuf;
+ unsigned char *wbuf;
+
+ unsigned char *write_ptr;/* used to point to the start due to
+ * 2/3 byte header. */
+
+ unsigned int padding;
+ unsigned int rlength; /* passed to ssl2_enc */
+ int ract_data_length; /* Set when things are encrypted. */
+ unsigned int wlength; /* passed to ssl2_enc */
+ int wact_data_length; /* Set when things are decrypted. */
+ unsigned char *ract_data;
+ unsigned char *wact_data;
+ unsigned char *mac_data;
+
+ unsigned char *read_key;
+ unsigned char *write_key;
+
+ /* Stuff specifically to do with this SSL session */
+ unsigned int challenge_length;
+ unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH];
+ unsigned int conn_id_length;
+ unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
+ unsigned int key_material_length;
+ unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2];
+
+ unsigned long read_sequence;
+ unsigned long write_sequence;
+
+ struct {
+ unsigned int conn_id_length;
+ unsigned int cert_type;
+ unsigned int cert_length;
+ unsigned int csl;
+ unsigned int clear;
+ unsigned int enc;
+ unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+ unsigned int cipher_spec_length;
+ unsigned int session_id_length;
+ unsigned int clen;
+ unsigned int rlen;
+ } tmp;
+ } SSL2_STATE;
+
+/* SSLv2 */
+/* client */
+#define SSL2_ST_SEND_CLIENT_HELLO_A (0x10|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_HELLO_B (0x11|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_A (0x20|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_B (0x21|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A (0x30|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B (0x31|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_A (0x40|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_B (0x41|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A (0x50|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B (0x51|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C (0x52|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D (0x53|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_A (0x60|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_B (0x61|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_A (0x70|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_B (0x71|SSL_ST_CONNECT)
+#define SSL2_ST_CLIENT_START_ENCRYPTION (0x80|SSL_ST_CONNECT)
+#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE (0x90|SSL_ST_CONNECT)
+/* server */
+#define SSL2_ST_GET_CLIENT_HELLO_A (0x10|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_B (0x11|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_C (0x12|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_A (0x20|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_B (0x21|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_A (0x30|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_B (0x31|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_A (0x40|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_B (0x41|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_C (0x42|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_A (0x50|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_B (0x51|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_A (0x60|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_B (0x61|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A (0x70|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B (0x71|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C (0x72|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D (0x73|SSL_ST_ACCEPT)
+#define SSL2_ST_SERVER_START_ENCRYPTION (0x80|SSL_ST_ACCEPT)
+#define SSL2_ST_X509_GET_SERVER_CERTIFICATE (0x90|SSL_ST_ACCEPT)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ssl23.h b/src/Mayaqua/win32_inc/openssl/ssl23.h
new file mode 100644
index 00000000..1a87d8cf
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl23.h
@@ -0,0 +1,83 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL23_H
+#define HEADER_SSL23_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*client */
+/* write to server */
+#define SSL23_ST_CW_CLNT_HELLO_A (0x210|SSL_ST_CONNECT)
+#define SSL23_ST_CW_CLNT_HELLO_B (0x211|SSL_ST_CONNECT)
+/* read from server */
+#define SSL23_ST_CR_SRVR_HELLO_A (0x220|SSL_ST_CONNECT)
+#define SSL23_ST_CR_SRVR_HELLO_B (0x221|SSL_ST_CONNECT)
+
+/* server */
+/* read from client */
+#define SSL23_ST_SR_CLNT_HELLO_A (0x210|SSL_ST_ACCEPT)
+#define SSL23_ST_SR_CLNT_HELLO_B (0x211|SSL_ST_ACCEPT)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ssl3.h b/src/Mayaqua/win32_inc/openssl/ssl3.h
new file mode 100644
index 00000000..d726b4f5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl3.h
@@ -0,0 +1,585 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL3_H
+#define HEADER_SSL3_H
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/pq_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */
+#define SSL3_CK_SCSV 0x030000FF
+
+#define SSL3_CK_RSA_NULL_MD5 0x03000001
+#define SSL3_CK_RSA_NULL_SHA 0x03000002
+#define SSL3_CK_RSA_RC4_40_MD5 0x03000003
+#define SSL3_CK_RSA_RC4_128_MD5 0x03000004
+#define SSL3_CK_RSA_RC4_128_SHA 0x03000005
+#define SSL3_CK_RSA_RC2_40_MD5 0x03000006
+#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007
+#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008
+#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009
+#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A
+
+#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B
+#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C
+#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D
+#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E
+#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F
+#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010
+
+#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011
+#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012
+#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013
+#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014
+#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015
+#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016
+
+#define SSL3_CK_ADH_RC4_40_MD5 0x03000017
+#define SSL3_CK_ADH_RC4_128_MD5 0x03000018
+#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019
+#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A
+#define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B
+
+#define SSL3_CK_FZA_DMS_NULL_SHA 0x0300001C
+#define SSL3_CK_FZA_DMS_FZA_SHA 0x0300001D
+#if 0 /* Because it clashes with KRB5, is never used any more, and is safe
+ to remove according to David Hopwood <david.hopwood@zetnet.co.uk>
+ of the ietf-tls list */
+#define SSL3_CK_FZA_DMS_RC4_SHA 0x0300001E
+#endif
+
+/* VRS Additional Kerberos5 entries
+ */
+#define SSL3_CK_KRB5_DES_64_CBC_SHA 0x0300001E
+#define SSL3_CK_KRB5_DES_192_CBC3_SHA 0x0300001F
+#define SSL3_CK_KRB5_RC4_128_SHA 0x03000020
+#define SSL3_CK_KRB5_IDEA_128_CBC_SHA 0x03000021
+#define SSL3_CK_KRB5_DES_64_CBC_MD5 0x03000022
+#define SSL3_CK_KRB5_DES_192_CBC3_MD5 0x03000023
+#define SSL3_CK_KRB5_RC4_128_MD5 0x03000024
+#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 0x03000025
+
+#define SSL3_CK_KRB5_DES_40_CBC_SHA 0x03000026
+#define SSL3_CK_KRB5_RC2_40_CBC_SHA 0x03000027
+#define SSL3_CK_KRB5_RC4_40_SHA 0x03000028
+#define SSL3_CK_KRB5_DES_40_CBC_MD5 0x03000029
+#define SSL3_CK_KRB5_RC2_40_CBC_MD5 0x0300002A
+#define SSL3_CK_KRB5_RC4_40_MD5 0x0300002B
+
+#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5"
+#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA"
+#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA"
+#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5"
+#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA"
+#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA"
+
+#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5"
+#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5"
+#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA"
+
+#define SSL3_TXT_FZA_DMS_NULL_SHA "FZA-NULL-SHA"
+#define SSL3_TXT_FZA_DMS_FZA_SHA "FZA-FZA-CBC-SHA"
+#define SSL3_TXT_FZA_DMS_RC4_SHA "FZA-RC4-SHA"
+
+#define SSL3_TXT_KRB5_DES_64_CBC_SHA "KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_192_CBC3_SHA "KRB5-DES-CBC3-SHA"
+#define SSL3_TXT_KRB5_RC4_128_SHA "KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA "KRB5-IDEA-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_64_CBC_MD5 "KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_DES_192_CBC3_MD5 "KRB5-DES-CBC3-MD5"
+#define SSL3_TXT_KRB5_RC4_128_MD5 "KRB5-RC4-MD5"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 "KRB5-IDEA-CBC-MD5"
+
+#define SSL3_TXT_KRB5_DES_40_CBC_SHA "EXP-KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_RC2_40_CBC_SHA "EXP-KRB5-RC2-CBC-SHA"
+#define SSL3_TXT_KRB5_RC4_40_SHA "EXP-KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_DES_40_CBC_MD5 "EXP-KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 "EXP-KRB5-RC2-CBC-MD5"
+#define SSL3_TXT_KRB5_RC4_40_MD5 "EXP-KRB5-RC4-MD5"
+
+#define SSL3_SSL_SESSION_ID_LENGTH 32
+#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32
+
+#define SSL3_MASTER_SECRET_SIZE 48
+#define SSL3_RANDOM_SIZE 32
+#define SSL3_SESSION_ID_SIZE 32
+#define SSL3_RT_HEADER_LENGTH 5
+
+/* Due to MS stuffing up, this can change.... */
+#if defined(OPENSSL_SYS_WIN16) || \
+ (defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32))
+#define SSL3_RT_MAX_EXTRA (14000)
+#else
+#define SSL3_RT_MAX_EXTRA (16384)
+#endif
+
+#define SSL3_RT_MAX_PLAIN_LENGTH 16384
+#ifdef OPENSSL_NO_COMP
+#define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH
+#else
+#define SSL3_RT_MAX_COMPRESSED_LENGTH (1024+SSL3_RT_MAX_PLAIN_LENGTH)
+#endif
+#define SSL3_RT_MAX_ENCRYPTED_LENGTH (1024+SSL3_RT_MAX_COMPRESSED_LENGTH)
+#define SSL3_RT_MAX_PACKET_SIZE (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
+#define SSL3_RT_MAX_DATA_SIZE (1024*1024)
+
+#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54"
+#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52"
+
+#define SSL3_VERSION 0x0300
+#define SSL3_VERSION_MAJOR 0x03
+#define SSL3_VERSION_MINOR 0x00
+
+#define SSL3_RT_CHANGE_CIPHER_SPEC 20
+#define SSL3_RT_ALERT 21
+#define SSL3_RT_HANDSHAKE 22
+#define SSL3_RT_APPLICATION_DATA 23
+
+#define SSL3_AL_WARNING 1
+#define SSL3_AL_FATAL 2
+
+#define SSL3_AD_CLOSE_NOTIFY 0
+#define SSL3_AD_UNEXPECTED_MESSAGE 10 /* fatal */
+#define SSL3_AD_BAD_RECORD_MAC 20 /* fatal */
+#define SSL3_AD_DECOMPRESSION_FAILURE 30 /* fatal */
+#define SSL3_AD_HANDSHAKE_FAILURE 40 /* fatal */
+#define SSL3_AD_NO_CERTIFICATE 41
+#define SSL3_AD_BAD_CERTIFICATE 42
+#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43
+#define SSL3_AD_CERTIFICATE_REVOKED 44
+#define SSL3_AD_CERTIFICATE_EXPIRED 45
+#define SSL3_AD_CERTIFICATE_UNKNOWN 46
+#define SSL3_AD_ILLEGAL_PARAMETER 47 /* fatal */
+
+typedef struct ssl3_record_st
+ {
+/*r */ int type; /* type of record */
+/*rw*/ unsigned int length; /* How many bytes available */
+/*r */ unsigned int off; /* read/write offset into 'buf' */
+/*rw*/ unsigned char *data; /* pointer to the record data */
+/*rw*/ unsigned char *input; /* where the decode bytes are */
+/*r */ unsigned char *comp; /* only used with decompression - malloc()ed */
+/*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */
+/*r */ PQ_64BIT seq_num; /* sequence number, needed by DTLS1 */
+ } SSL3_RECORD;
+
+typedef struct ssl3_buffer_st
+ {
+ unsigned char *buf; /* at least SSL3_RT_MAX_PACKET_SIZE bytes,
+ * see ssl3_setup_buffers() */
+ size_t len; /* buffer size */
+ int offset; /* where to 'copy from' */
+ int left; /* how many bytes left */
+ } SSL3_BUFFER;
+
+#define SSL3_CT_RSA_SIGN 1
+#define SSL3_CT_DSS_SIGN 2
+#define SSL3_CT_RSA_FIXED_DH 3
+#define SSL3_CT_DSS_FIXED_DH 4
+#define SSL3_CT_RSA_EPHEMERAL_DH 5
+#define SSL3_CT_DSS_EPHEMERAL_DH 6
+#define SSL3_CT_FORTEZZA_DMS 20
+/* SSL3_CT_NUMBER is used to size arrays and it must be large
+ * enough to contain all of the cert types defined either for
+ * SSLv3 and TLSv1.
+ */
+#define SSL3_CT_NUMBER 7
+
+
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002
+#define SSL3_FLAGS_POP_BUFFER 0x0004
+#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
+
+/* SSL3_FLAGS_SGC_RESTART_DONE is set when we
+ * restart a handshake because of MS SGC and so prevents us
+ * from restarting the handshake in a loop. It's reset on a
+ * renegotiation, so effectively limits the client to one restart
+ * per negotiation. This limits the possibility of a DDoS
+ * attack where the client handshakes in a loop using SGC to
+ * restart. Servers which permit renegotiation can still be
+ * effected, but we can't prevent that.
+ */
+#define SSL3_FLAGS_SGC_RESTART_DONE 0x0040
+
+typedef struct ssl3_state_st
+ {
+ long flags;
+ int delay_buf_pop_ret;
+
+ unsigned char read_sequence[8];
+ unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+ unsigned char write_sequence[8];
+ unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+
+ unsigned char server_random[SSL3_RANDOM_SIZE];
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+
+ /* flags for countermeasure against known-IV weakness */
+ int need_empty_fragments;
+ int empty_fragment_done;
+
+ SSL3_BUFFER rbuf; /* read IO goes into here */
+ SSL3_BUFFER wbuf; /* write IO goes into here */
+
+ SSL3_RECORD rrec; /* each decoded record goes in here */
+ SSL3_RECORD wrec; /* goes out from here */
+
+ /* storage for Alert/Handshake protocol data received but not
+ * yet processed by ssl3_read_bytes: */
+ unsigned char alert_fragment[2];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[4];
+ unsigned int handshake_fragment_len;
+
+ /* partial write - check the numbers match */
+ unsigned int wnum; /* number of bytes sent so far */
+ int wpend_tot; /* number bytes written */
+ int wpend_type;
+ int wpend_ret; /* number of bytes submitted */
+ const unsigned char *wpend_buf;
+
+ /* used during startup, digest all incoming/outgoing packets */
+ EVP_MD_CTX finish_dgst1;
+ EVP_MD_CTX finish_dgst2;
+
+ /* this is set whenerver we see a change_cipher_spec message
+ * come in when we are not looking for one */
+ int change_cipher_spec;
+
+ int warn_alert;
+ int fatal_alert;
+ /* we allow one fatal and one warning alert to be outstanding,
+ * send close alert via the warning alert */
+ int alert_dispatch;
+ unsigned char send_alert[2];
+
+ /* This flag is set when we should renegotiate ASAP, basically when
+ * there is no more data in the read or write buffers */
+ int renegotiate;
+ int total_renegotiations;
+ int num_renegotiations;
+
+ int in_read_app_data;
+
+ struct {
+ /* actually only needs to be 16+20 */
+ unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];
+
+ /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+ unsigned char finish_md[EVP_MAX_MD_SIZE*2];
+ int finish_md_len;
+ unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2];
+ int peer_finish_md_len;
+
+ unsigned long message_size;
+ int message_type;
+
+ /* used to hold the new cipher we are going to use */
+ SSL_CIPHER *new_cipher;
+#ifndef OPENSSL_NO_DH
+ DH *dh;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+ EC_KEY *ecdh; /* holds short lived ECDH key */
+#endif
+
+ /* used when SSL_ST_FLUSH_DATA is entered */
+ int next_state;
+
+ int reuse_message;
+
+ /* used for certificate requests */
+ int cert_req;
+ int ctype_num;
+ char ctype[SSL3_CT_NUMBER];
+ STACK_OF(X509_NAME) *ca_names;
+
+ int use_rsa_tmp;
+
+ int key_block_length;
+ unsigned char *key_block;
+
+ const EVP_CIPHER *new_sym_enc;
+ const EVP_MD *new_hash;
+#ifndef OPENSSL_NO_COMP
+ const SSL_COMP *new_compression;
+#else
+ char *new_compression;
+#endif
+ int cert_request;
+ } tmp;
+
+ /* Connection binding to prevent renegotiation attacks */
+ unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_client_finished_len;
+ unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_server_finished_len;
+ int send_connection_binding; /* TODOEKR */
+ } SSL3_STATE;
+
+
+/* SSLv3 */
+/*client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_B (0x141|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_A (0x150|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_C (0x172|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_D (0x173|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_A (0x180|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_B (0x181|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_A (0x190|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_CHANGE_A (0x1C0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_A (0x1E0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_B (0x1E1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_A (0x1F0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_B (0x1F1|SSL_ST_CONNECT)
+
+/* server */
+/* extra state */
+#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT)
+/* read from client */
+/* Do not change the number values, they do matter */
+#define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT)
+/* write to client */
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_A (0x130|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_B (0x131|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_A (0x140|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_B (0x141|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_A (0x150|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_B (0x151|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_A (0x160|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_B (0x161|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_A (0x170|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_B (0x171|SSL_ST_ACCEPT)
+/* read from client */
+#define SSL3_ST_SR_CERT_A (0x180|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_B (0x181|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_A (0x190|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_B (0x191|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT)
+/* write to client */
+#define SSL3_ST_SW_CHANGE_A (0x1D0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_A (0x1F0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_A (0x200|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_B (0x201|SSL_ST_ACCEPT)
+
+#define SSL3_MT_HELLO_REQUEST 0
+#define SSL3_MT_CLIENT_HELLO 1
+#define SSL3_MT_SERVER_HELLO 2
+#define SSL3_MT_NEWSESSION_TICKET 4
+#define SSL3_MT_CERTIFICATE 11
+#define SSL3_MT_SERVER_KEY_EXCHANGE 12
+#define SSL3_MT_CERTIFICATE_REQUEST 13
+#define SSL3_MT_SERVER_DONE 14
+#define SSL3_MT_CERTIFICATE_VERIFY 15
+#define SSL3_MT_CLIENT_KEY_EXCHANGE 16
+#define SSL3_MT_FINISHED 20
+#define SSL3_MT_CERTIFICATE_STATUS 22
+#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
+
+
+#define SSL3_MT_CCS 1
+
+/* These are used when changing over to a new cipher */
+#define SSL3_CC_READ 0x01
+#define SSL3_CC_WRITE 0x02
+#define SSL3_CC_CLIENT 0x10
+#define SSL3_CC_SERVER 0x20
+#define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE)
+#define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/stack.h b/src/Mayaqua/win32_inc/openssl/stack.h
new file mode 100644
index 00000000..7f3b13d2
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/stack.h
@@ -0,0 +1,109 @@
+/* crypto/stack/stack.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_STACK_H
+#define HEADER_STACK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct stack_st
+ {
+ int num;
+ char **data;
+ int sorted;
+
+ int num_alloc;
+ int (*comp)(const char * const *, const char * const *);
+ } STACK;
+
+#define M_sk_num(sk) ((sk) ? (sk)->num:-1)
+#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL)
+
+int sk_num(const STACK *);
+char *sk_value(const STACK *, int);
+
+char *sk_set(STACK *, int, char *);
+
+STACK *sk_new(int (*cmp)(const char * const *, const char * const *));
+STACK *sk_new_null(void);
+void sk_free(STACK *);
+void sk_pop_free(STACK *st, void (*func)(void *));
+int sk_insert(STACK *sk,char *data,int where);
+char *sk_delete(STACK *st,int loc);
+char *sk_delete_ptr(STACK *st, char *p);
+int sk_find(STACK *st,char *data);
+int sk_find_ex(STACK *st,char *data);
+int sk_push(STACK *st,char *data);
+int sk_unshift(STACK *st,char *data);
+char *sk_shift(STACK *st);
+char *sk_pop(STACK *st);
+void sk_zero(STACK *st);
+int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *,
+ const char * const *)))
+ (const char * const *, const char * const *);
+STACK *sk_dup(STACK *st);
+void sk_sort(STACK *st);
+int sk_is_sorted(const STACK *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/store.h b/src/Mayaqua/win32_inc/openssl/store.h
new file mode 100644
index 00000000..9665d0d4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/store.h
@@ -0,0 +1,554 @@
+/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_STORE_H
+#define HEADER_STORE_H
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct store_st STORE; */
+/* typedef struct store_method_st STORE_METHOD; */
+
+
+/* All the following functions return 0, a negative number or NULL on error.
+ When everything is fine, they return a positive value or a non-NULL
+ pointer, all depending on their purpose. */
+
+/* Creators and destructor. */
+STORE *STORE_new_method(const STORE_METHOD *method);
+STORE *STORE_new_engine(ENGINE *engine);
+void STORE_free(STORE *ui);
+
+
+/* Give a user interface parametrised control commands. This can be used to
+ send down an integer, a data pointer or a function pointer, as well as
+ be used to get information from a STORE. */
+int STORE_ctrl(STORE *store, int cmd, long i, void *p, void (*f)(void));
+
+/* A control to set the directory with keys and certificates. Used by the
+ built-in directory level method. */
+#define STORE_CTRL_SET_DIRECTORY 0x0001
+/* A control to set a file to load. Used by the built-in file level method. */
+#define STORE_CTRL_SET_FILE 0x0002
+/* A control to set a configuration file to load. Can be used by any method
+ that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_FILE 0x0003
+/* A control to set a the section of the loaded configuration file. Can be
+ used by any method that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_SECTION 0x0004
+
+
+/* Some methods may use extra data */
+#define STORE_set_app_data(s,arg) STORE_set_ex_data(s,0,arg)
+#define STORE_get_app_data(s) STORE_get_ex_data(s,0)
+int STORE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int STORE_set_ex_data(STORE *r,int idx,void *arg);
+void *STORE_get_ex_data(STORE *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+const STORE_METHOD *STORE_get_method(STORE *store);
+const STORE_METHOD *STORE_set_method(STORE *store, const STORE_METHOD *meth);
+
+/* The standard OpenSSL methods. */
+/* This is the in-memory method. It does everything except revoking and updating,
+ and is of course volatile. It's used by other methods that have an in-memory
+ cache. */
+const STORE_METHOD *STORE_Memory(void);
+#if 0 /* Not yet implemented */
+/* This is the directory store. It does everything except revoking and updating,
+ and uses STORE_Memory() to cache things in memory. */
+const STORE_METHOD *STORE_Directory(void);
+/* This is the file store. It does everything except revoking and updating,
+ and uses STORE_Memory() to cache things in memory. Certificates are added
+ to it with the store operation, and it will only get cached certificates. */
+const STORE_METHOD *STORE_File(void);
+#endif
+
+/* Store functions take a type code for the type of data they should store
+ or fetch */
+typedef enum STORE_object_types
+ {
+ STORE_OBJECT_TYPE_X509_CERTIFICATE= 0x01, /* X509 * */
+ STORE_OBJECT_TYPE_X509_CRL= 0x02, /* X509_CRL * */
+ STORE_OBJECT_TYPE_PRIVATE_KEY= 0x03, /* EVP_PKEY * */
+ STORE_OBJECT_TYPE_PUBLIC_KEY= 0x04, /* EVP_PKEY * */
+ STORE_OBJECT_TYPE_NUMBER= 0x05, /* BIGNUM * */
+ STORE_OBJECT_TYPE_ARBITRARY= 0x06, /* BUF_MEM * */
+ STORE_OBJECT_TYPE_NUM= 0x06 /* The amount of known
+ object types */
+ } STORE_OBJECT_TYPES;
+/* List of text strings corresponding to the object types. */
+extern const char * const STORE_object_type_string[STORE_OBJECT_TYPE_NUM+1];
+
+/* Some store functions take a parameter list. Those parameters come with
+ one of the following codes. The comments following the codes below indicate
+ what type the value should be a pointer to. */
+typedef enum STORE_params
+ {
+ STORE_PARAM_EVP_TYPE= 0x01, /* int */
+ STORE_PARAM_BITS= 0x02, /* size_t */
+ STORE_PARAM_KEY_PARAMETERS= 0x03, /* ??? */
+ STORE_PARAM_KEY_NO_PARAMETERS= 0x04, /* N/A */
+ STORE_PARAM_AUTH_PASSPHRASE= 0x05, /* char * */
+ STORE_PARAM_AUTH_KRB5_TICKET= 0x06, /* void * */
+ STORE_PARAM_TYPE_NUM= 0x06 /* The amount of known
+ parameter types */
+ } STORE_PARAM_TYPES;
+/* Parameter value sizes. -1 means unknown, anything else is the required size. */
+extern const int STORE_param_sizes[STORE_PARAM_TYPE_NUM+1];
+
+/* Store functions take attribute lists. Those attributes come with codes.
+ The comments following the codes below indicate what type the value should
+ be a pointer to. */
+typedef enum STORE_attribs
+ {
+ STORE_ATTR_END= 0x00,
+ STORE_ATTR_FRIENDLYNAME= 0x01, /* C string */
+ STORE_ATTR_KEYID= 0x02, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUERKEYID= 0x03, /* 160 bit string (SHA1) */
+ STORE_ATTR_SUBJECTKEYID= 0x04, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUERSERIALHASH= 0x05, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUER= 0x06, /* X509_NAME * */
+ STORE_ATTR_SERIAL= 0x07, /* BIGNUM * */
+ STORE_ATTR_SUBJECT= 0x08, /* X509_NAME * */
+ STORE_ATTR_CERTHASH= 0x09, /* 160 bit string (SHA1) */
+ STORE_ATTR_EMAIL= 0x0a, /* C string */
+ STORE_ATTR_FILENAME= 0x0b, /* C string */
+ STORE_ATTR_TYPE_NUM= 0x0b, /* The amount of known
+ attribute types */
+ STORE_ATTR_OR= 0xff /* This is a special
+ separator, which
+ expresses the OR
+ operation. */
+ } STORE_ATTR_TYPES;
+/* Attribute value sizes. -1 means unknown, anything else is the required size. */
+extern const int STORE_attr_sizes[STORE_ATTR_TYPE_NUM+1];
+
+typedef enum STORE_certificate_status
+ {
+ STORE_X509_VALID= 0x00,
+ STORE_X509_EXPIRED= 0x01,
+ STORE_X509_SUSPENDED= 0x02,
+ STORE_X509_REVOKED= 0x03
+ } STORE_CERTIFICATE_STATUS;
+
+/* Engine store functions will return a structure that contains all the necessary
+ * information, including revokation status for certificates. This is really not
+ * needed for application authors, as the ENGINE framework functions will extract
+ * the OpenSSL-specific information when at all possible. However, for engine
+ * authors, it's crucial to know this structure. */
+typedef struct STORE_OBJECT_st
+ {
+ STORE_OBJECT_TYPES type;
+ union
+ {
+ struct
+ {
+ STORE_CERTIFICATE_STATUS status;
+ X509 *certificate;
+ } x509;
+ X509_CRL *crl;
+ EVP_PKEY *key;
+ BIGNUM *number;
+ BUF_MEM *arbitrary;
+ } data;
+ } STORE_OBJECT;
+DECLARE_STACK_OF(STORE_OBJECT)
+STORE_OBJECT *STORE_OBJECT_new(void);
+void STORE_OBJECT_free(STORE_OBJECT *data);
+
+
+
+/* The following functions handle the storage. They return 0, a negative number
+ or NULL on error, anything else on success. */
+X509 *STORE_get_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_certificate(STORE *e, X509 *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_certificate(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_certificate_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509 *STORE_list_certificate_next(STORE *e, void *handle);
+int STORE_list_certificate_end(STORE *e, void *handle);
+int STORE_list_certificate_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_generate_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_get_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_private_key(STORE *e, EVP_PKEY *data,
+ OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+int STORE_modify_private_key(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_private_key_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_private_key_next(STORE *e, void *handle);
+int STORE_list_private_key_end(STORE *e, void *handle);
+int STORE_list_private_key_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_get_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_public_key(STORE *e, EVP_PKEY *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_public_key(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_public_key_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_public_key_next(STORE *e, void *handle);
+int STORE_list_public_key_end(STORE *e, void *handle);
+int STORE_list_public_key_endp(STORE *e, void *handle);
+X509_CRL *STORE_generate_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_get_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_crl(STORE *e, X509_CRL *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_crl(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_delete_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_crl_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_list_crl_next(STORE *e, void *handle);
+int STORE_list_crl_end(STORE *e, void *handle);
+int STORE_list_crl_endp(STORE *e, void *handle);
+int STORE_store_number(STORE *e, BIGNUM *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_number(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BIGNUM *STORE_get_number(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_number(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_arbitrary(STORE *e, BUF_MEM *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_arbitrary(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BUF_MEM *STORE_get_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+
+
+/* Create and manipulate methods */
+STORE_METHOD *STORE_create_method(char *name);
+void STORE_destroy_method(STORE_METHOD *store_method);
+
+/* These callback types are use for store handlers */
+typedef int (*STORE_INITIALISE_FUNC_PTR)(STORE *);
+typedef void (*STORE_CLEANUP_FUNC_PTR)(STORE *);
+typedef STORE_OBJECT *(*STORE_GENERATE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_GET_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef void *(*STORE_START_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_NEXT_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_END_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_HANDLE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_STORE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, STORE_OBJECT *data, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_MODIFY_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_GENERIC_FUNC_PTR)(STORE *, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_CTRL_FUNC_PTR)(STORE *, int cmd, long l, void *p, void (*f)(void));
+
+int STORE_method_set_initialise_function(STORE_METHOD *sm, STORE_INITIALISE_FUNC_PTR init_f);
+int STORE_method_set_cleanup_function(STORE_METHOD *sm, STORE_CLEANUP_FUNC_PTR clean_f);
+int STORE_method_set_generate_function(STORE_METHOD *sm, STORE_GENERATE_OBJECT_FUNC_PTR generate_f);
+int STORE_method_set_get_function(STORE_METHOD *sm, STORE_GET_OBJECT_FUNC_PTR get_f);
+int STORE_method_set_store_function(STORE_METHOD *sm, STORE_STORE_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_modify_function(STORE_METHOD *sm, STORE_MODIFY_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_revoke_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR revoke_f);
+int STORE_method_set_delete_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR delete_f);
+int STORE_method_set_list_start_function(STORE_METHOD *sm, STORE_START_OBJECT_FUNC_PTR list_start_f);
+int STORE_method_set_list_next_function(STORE_METHOD *sm, STORE_NEXT_OBJECT_FUNC_PTR list_next_f);
+int STORE_method_set_list_end_function(STORE_METHOD *sm, STORE_END_OBJECT_FUNC_PTR list_end_f);
+int STORE_method_set_update_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_lock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_unlock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_ctrl_function(STORE_METHOD *sm, STORE_CTRL_FUNC_PTR ctrl_f);
+
+STORE_INITIALISE_FUNC_PTR STORE_method_get_initialise_function(STORE_METHOD *sm);
+STORE_CLEANUP_FUNC_PTR STORE_method_get_cleanup_function(STORE_METHOD *sm);
+STORE_GENERATE_OBJECT_FUNC_PTR STORE_method_get_generate_function(STORE_METHOD *sm);
+STORE_GET_OBJECT_FUNC_PTR STORE_method_get_get_function(STORE_METHOD *sm);
+STORE_STORE_OBJECT_FUNC_PTR STORE_method_get_store_function(STORE_METHOD *sm);
+STORE_MODIFY_OBJECT_FUNC_PTR STORE_method_get_modify_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_revoke_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_delete_function(STORE_METHOD *sm);
+STORE_START_OBJECT_FUNC_PTR STORE_method_get_list_start_function(STORE_METHOD *sm);
+STORE_NEXT_OBJECT_FUNC_PTR STORE_method_get_list_next_function(STORE_METHOD *sm);
+STORE_END_OBJECT_FUNC_PTR STORE_method_get_list_end_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_update_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_lock_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_unlock_store_function(STORE_METHOD *sm);
+STORE_CTRL_FUNC_PTR STORE_method_get_ctrl_function(STORE_METHOD *sm);
+
+/* Method helper structures and functions. */
+
+/* This structure is the result of parsing through the information in a list
+ of OPENSSL_ITEMs. It stores all the necessary information in a structured
+ way.*/
+typedef struct STORE_attr_info_st STORE_ATTR_INFO;
+
+/* Parse a list of OPENSSL_ITEMs and return a pointer to a STORE_ATTR_INFO.
+ Note that we do this in the list form, since the list of OPENSSL_ITEMs can
+ come in blocks separated with STORE_ATTR_OR. Note that the value returned
+ by STORE_parse_attrs_next() must be freed with STORE_ATTR_INFO_free(). */
+void *STORE_parse_attrs_start(OPENSSL_ITEM *attributes);
+STORE_ATTR_INFO *STORE_parse_attrs_next(void *handle);
+int STORE_parse_attrs_end(void *handle);
+int STORE_parse_attrs_endp(void *handle);
+
+/* Creator and destructor */
+STORE_ATTR_INFO *STORE_ATTR_INFO_new(void);
+int STORE_ATTR_INFO_free(STORE_ATTR_INFO *attrs);
+
+/* Manipulators */
+char *STORE_ATTR_INFO_get0_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+unsigned char *STORE_ATTR_INFO_get0_sha1str(STORE_ATTR_INFO *attrs,
+ STORE_ATTR_TYPES code);
+X509_NAME *STORE_ATTR_INFO_get0_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+BIGNUM *STORE_ATTR_INFO_get0_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+int STORE_ATTR_INFO_set_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_set_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_set_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ X509_NAME *dn);
+int STORE_ATTR_INFO_set_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ BIGNUM *number);
+int STORE_ATTR_INFO_modify_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_modify_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_modify_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ X509_NAME *dn);
+int STORE_ATTR_INFO_modify_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ BIGNUM *number);
+
+/* Compare on basis of a bit pattern formed by the STORE_ATTR_TYPES values
+ in each contained attribute. */
+int STORE_ATTR_INFO_compare(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a is within the range of attributes
+ set in b. */
+int STORE_ATTR_INFO_in_range(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a are also set in b. */
+int STORE_ATTR_INFO_in(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Same as STORE_ATTR_INFO_in(), but also checks the attribute values. */
+int STORE_ATTR_INFO_in_ex(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_STORE_strings(void);
+
+/* Error codes for the STORE functions. */
+
+/* Function codes. */
+#define STORE_F_MEM_DELETE 134
+#define STORE_F_MEM_GENERATE 135
+#define STORE_F_MEM_LIST_END 168
+#define STORE_F_MEM_LIST_NEXT 136
+#define STORE_F_MEM_LIST_START 137
+#define STORE_F_MEM_MODIFY 169
+#define STORE_F_MEM_STORE 138
+#define STORE_F_STORE_ATTR_INFO_GET0_CSTR 139
+#define STORE_F_STORE_ATTR_INFO_GET0_DN 140
+#define STORE_F_STORE_ATTR_INFO_GET0_NUMBER 141
+#define STORE_F_STORE_ATTR_INFO_GET0_SHA1STR 142
+#define STORE_F_STORE_ATTR_INFO_MODIFY_CSTR 143
+#define STORE_F_STORE_ATTR_INFO_MODIFY_DN 144
+#define STORE_F_STORE_ATTR_INFO_MODIFY_NUMBER 145
+#define STORE_F_STORE_ATTR_INFO_MODIFY_SHA1STR 146
+#define STORE_F_STORE_ATTR_INFO_SET_CSTR 147
+#define STORE_F_STORE_ATTR_INFO_SET_DN 148
+#define STORE_F_STORE_ATTR_INFO_SET_NUMBER 149
+#define STORE_F_STORE_ATTR_INFO_SET_SHA1STR 150
+#define STORE_F_STORE_CERTIFICATE 170
+#define STORE_F_STORE_CTRL 161
+#define STORE_F_STORE_DELETE_ARBITRARY 158
+#define STORE_F_STORE_DELETE_CERTIFICATE 102
+#define STORE_F_STORE_DELETE_CRL 103
+#define STORE_F_STORE_DELETE_NUMBER 104
+#define STORE_F_STORE_DELETE_PRIVATE_KEY 105
+#define STORE_F_STORE_DELETE_PUBLIC_KEY 106
+#define STORE_F_STORE_GENERATE_CRL 107
+#define STORE_F_STORE_GENERATE_KEY 108
+#define STORE_F_STORE_GET_ARBITRARY 159
+#define STORE_F_STORE_GET_CERTIFICATE 109
+#define STORE_F_STORE_GET_CRL 110
+#define STORE_F_STORE_GET_NUMBER 111
+#define STORE_F_STORE_GET_PRIVATE_KEY 112
+#define STORE_F_STORE_GET_PUBLIC_KEY 113
+#define STORE_F_STORE_LIST_CERTIFICATE_END 114
+#define STORE_F_STORE_LIST_CERTIFICATE_ENDP 153
+#define STORE_F_STORE_LIST_CERTIFICATE_NEXT 115
+#define STORE_F_STORE_LIST_CERTIFICATE_START 116
+#define STORE_F_STORE_LIST_CRL_END 117
+#define STORE_F_STORE_LIST_CRL_ENDP 154
+#define STORE_F_STORE_LIST_CRL_NEXT 118
+#define STORE_F_STORE_LIST_CRL_START 119
+#define STORE_F_STORE_LIST_PRIVATE_KEY_END 120
+#define STORE_F_STORE_LIST_PRIVATE_KEY_ENDP 155
+#define STORE_F_STORE_LIST_PRIVATE_KEY_NEXT 121
+#define STORE_F_STORE_LIST_PRIVATE_KEY_START 122
+#define STORE_F_STORE_LIST_PUBLIC_KEY_END 123
+#define STORE_F_STORE_LIST_PUBLIC_KEY_ENDP 156
+#define STORE_F_STORE_LIST_PUBLIC_KEY_NEXT 124
+#define STORE_F_STORE_LIST_PUBLIC_KEY_START 125
+#define STORE_F_STORE_MODIFY_ARBITRARY 162
+#define STORE_F_STORE_MODIFY_CERTIFICATE 163
+#define STORE_F_STORE_MODIFY_CRL 164
+#define STORE_F_STORE_MODIFY_NUMBER 165
+#define STORE_F_STORE_MODIFY_PRIVATE_KEY 166
+#define STORE_F_STORE_MODIFY_PUBLIC_KEY 167
+#define STORE_F_STORE_NEW_ENGINE 133
+#define STORE_F_STORE_NEW_METHOD 132
+#define STORE_F_STORE_PARSE_ATTRS_END 151
+#define STORE_F_STORE_PARSE_ATTRS_ENDP 172
+#define STORE_F_STORE_PARSE_ATTRS_NEXT 152
+#define STORE_F_STORE_PARSE_ATTRS_START 171
+#define STORE_F_STORE_REVOKE_CERTIFICATE 129
+#define STORE_F_STORE_REVOKE_PRIVATE_KEY 130
+#define STORE_F_STORE_REVOKE_PUBLIC_KEY 131
+#define STORE_F_STORE_STORE_ARBITRARY 157
+#define STORE_F_STORE_STORE_CERTIFICATE 100
+#define STORE_F_STORE_STORE_CRL 101
+#define STORE_F_STORE_STORE_NUMBER 126
+#define STORE_F_STORE_STORE_PRIVATE_KEY 127
+#define STORE_F_STORE_STORE_PUBLIC_KEY 128
+
+/* Reason codes. */
+#define STORE_R_ALREADY_HAS_A_VALUE 127
+#define STORE_R_FAILED_DELETING_ARBITRARY 132
+#define STORE_R_FAILED_DELETING_CERTIFICATE 100
+#define STORE_R_FAILED_DELETING_KEY 101
+#define STORE_R_FAILED_DELETING_NUMBER 102
+#define STORE_R_FAILED_GENERATING_CRL 103
+#define STORE_R_FAILED_GENERATING_KEY 104
+#define STORE_R_FAILED_GETTING_ARBITRARY 133
+#define STORE_R_FAILED_GETTING_CERTIFICATE 105
+#define STORE_R_FAILED_GETTING_KEY 106
+#define STORE_R_FAILED_GETTING_NUMBER 107
+#define STORE_R_FAILED_LISTING_CERTIFICATES 108
+#define STORE_R_FAILED_LISTING_KEYS 109
+#define STORE_R_FAILED_MODIFYING_ARBITRARY 138
+#define STORE_R_FAILED_MODIFYING_CERTIFICATE 139
+#define STORE_R_FAILED_MODIFYING_CRL 140
+#define STORE_R_FAILED_MODIFYING_NUMBER 141
+#define STORE_R_FAILED_MODIFYING_PRIVATE_KEY 142
+#define STORE_R_FAILED_MODIFYING_PUBLIC_KEY 143
+#define STORE_R_FAILED_REVOKING_CERTIFICATE 110
+#define STORE_R_FAILED_REVOKING_KEY 111
+#define STORE_R_FAILED_STORING_ARBITRARY 134
+#define STORE_R_FAILED_STORING_CERTIFICATE 112
+#define STORE_R_FAILED_STORING_KEY 113
+#define STORE_R_FAILED_STORING_NUMBER 114
+#define STORE_R_NOT_IMPLEMENTED 128
+#define STORE_R_NO_CONTROL_FUNCTION 144
+#define STORE_R_NO_DELETE_ARBITRARY_FUNCTION 135
+#define STORE_R_NO_DELETE_NUMBER_FUNCTION 115
+#define STORE_R_NO_DELETE_OBJECT_FUNCTION 116
+#define STORE_R_NO_GENERATE_CRL_FUNCTION 117
+#define STORE_R_NO_GENERATE_OBJECT_FUNCTION 118
+#define STORE_R_NO_GET_OBJECT_ARBITRARY_FUNCTION 136
+#define STORE_R_NO_GET_OBJECT_FUNCTION 119
+#define STORE_R_NO_GET_OBJECT_NUMBER_FUNCTION 120
+#define STORE_R_NO_LIST_OBJECT_ENDP_FUNCTION 131
+#define STORE_R_NO_LIST_OBJECT_END_FUNCTION 121
+#define STORE_R_NO_LIST_OBJECT_NEXT_FUNCTION 122
+#define STORE_R_NO_LIST_OBJECT_START_FUNCTION 123
+#define STORE_R_NO_MODIFY_OBJECT_FUNCTION 145
+#define STORE_R_NO_REVOKE_OBJECT_FUNCTION 124
+#define STORE_R_NO_STORE 129
+#define STORE_R_NO_STORE_OBJECT_ARBITRARY_FUNCTION 137
+#define STORE_R_NO_STORE_OBJECT_FUNCTION 125
+#define STORE_R_NO_STORE_OBJECT_NUMBER_FUNCTION 126
+#define STORE_R_NO_VALUE 130
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/symhacks.h b/src/Mayaqua/win32_inc/openssl/symhacks.h
new file mode 100644
index 00000000..d101333e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/symhacks.h
@@ -0,0 +1,429 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SYMHACKS_H
+#define HEADER_SYMHACKS_H
+
+#include <openssl/e_os2.h>
+
+/* Hacks to solve the problem with linkers incapable of handling very long
+ symbol names. In the case of VMS, the limit is 31 characters on VMS for
+ VAX. */
+/* Note that this affects util/libeay.num and util/ssleay.num... you may
+ change those manually, but that's not recommended, as those files are
+ controlled centrally and updated on Unix, and the central definition
+ may disagree with yours, which in turn may come with shareable library
+ incompatibilities. */
+#ifdef OPENSSL_SYS_VMS
+
+/* Hack a long name in crypto/cryptlib.c */
+#undef int_CRYPTO_set_do_dynlock_callback
+#define int_CRYPTO_set_do_dynlock_callback int_CRYPTO_set_do_dynlock_cb
+
+/* Hack a long name in crypto/ex_data.c */
+#undef CRYPTO_get_ex_data_implementation
+#define CRYPTO_get_ex_data_implementation CRYPTO_get_ex_data_impl
+#undef CRYPTO_set_ex_data_implementation
+#define CRYPTO_set_ex_data_implementation CRYPTO_set_ex_data_impl
+
+/* Hack a long name in crypto/asn1/a_mbstr.c */
+#undef ASN1_STRING_set_default_mask_asc
+#define ASN1_STRING_set_default_mask_asc ASN1_STRING_set_def_mask_asc
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO i2d_ASN1_SET_OF_PKCS7_SIGINF
+#undef d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO d2i_ASN1_SET_OF_PKCS7_SIGINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO i2d_ASN1_SET_OF_PKCS7_RECINF
+#undef d2i_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO d2i_ASN1_SET_OF_PKCS7_RECINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) */
+#undef i2d_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION i2d_ASN1_SET_OF_ACC_DESC
+#undef d2i_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION d2i_ASN1_SET_OF_ACC_DESC
+#endif
+
+/* Hack the names created with DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE) */
+#undef PEM_read_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_NETSCAPE_CERT_SEQUENCE PEM_read_NS_CERT_SEQ
+#undef PEM_write_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_NETSCAPE_CERT_SEQUENCE PEM_write_NS_CERT_SEQ
+#undef PEM_read_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE PEM_read_bio_NS_CERT_SEQ
+#undef PEM_write_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE PEM_write_bio_NS_CERT_SEQ
+#undef PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE PEM_write_cb_bio_NS_CERT_SEQ
+
+/* Hack the names created with DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO) */
+#undef PEM_read_PKCS8_PRIV_KEY_INFO
+#define PEM_read_PKCS8_PRIV_KEY_INFO PEM_read_P8_PRIV_KEY_INFO
+#undef PEM_write_PKCS8_PRIV_KEY_INFO
+#define PEM_write_PKCS8_PRIV_KEY_INFO PEM_write_P8_PRIV_KEY_INFO
+#undef PEM_read_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_read_bio_PKCS8_PRIV_KEY_INFO PEM_read_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_bio_PKCS8_PRIV_KEY_INFO PEM_write_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO PEM_wrt_cb_bio_P8_PRIV_KEY_INFO
+
+/* Hack other PEM names */
+#undef PEM_write_bio_PKCS8PrivateKey_nid
+#define PEM_write_bio_PKCS8PrivateKey_nid PEM_write_bio_PKCS8PrivKey_nid
+
+/* Hack some long X509 names */
+#undef X509_REVOKED_get_ext_by_critical
+#define X509_REVOKED_get_ext_by_critical X509_REVOKED_get_ext_by_critic
+#undef X509_policy_tree_get0_user_policies
+#define X509_policy_tree_get0_user_policies X509_pcy_tree_get0_usr_policies
+#undef X509_policy_node_get0_qualifiers
+#define X509_policy_node_get0_qualifiers X509_pcy_node_get0_qualifiers
+#undef X509_STORE_CTX_get_explicit_policy
+#define X509_STORE_CTX_get_explicit_policy X509_STORE_CTX_get_expl_policy
+#undef X509_STORE_CTX_get0_current_issuer
+#define X509_STORE_CTX_get0_current_issuer X509_STORE_CTX_get0_cur_issuer
+
+/* Hack some long CRYPTO names */
+#undef CRYPTO_set_dynlock_destroy_callback
+#define CRYPTO_set_dynlock_destroy_callback CRYPTO_set_dynlock_destroy_cb
+#undef CRYPTO_set_dynlock_create_callback
+#define CRYPTO_set_dynlock_create_callback CRYPTO_set_dynlock_create_cb
+#undef CRYPTO_set_dynlock_lock_callback
+#define CRYPTO_set_dynlock_lock_callback CRYPTO_set_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_lock_callback
+#define CRYPTO_get_dynlock_lock_callback CRYPTO_get_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_destroy_callback
+#define CRYPTO_get_dynlock_destroy_callback CRYPTO_get_dynlock_destroy_cb
+#undef CRYPTO_get_dynlock_create_callback
+#define CRYPTO_get_dynlock_create_callback CRYPTO_get_dynlock_create_cb
+#undef CRYPTO_set_locked_mem_ex_functions
+#define CRYPTO_set_locked_mem_ex_functions CRYPTO_set_locked_mem_ex_funcs
+#undef CRYPTO_get_locked_mem_ex_functions
+#define CRYPTO_get_locked_mem_ex_functions CRYPTO_get_locked_mem_ex_funcs
+
+/* Hack some long SSL names */
+#undef SSL_CTX_set_default_verify_paths
+#define SSL_CTX_set_default_verify_paths SSL_CTX_set_def_verify_paths
+#undef SSL_get_ex_data_X509_STORE_CTX_idx
+#define SSL_get_ex_data_X509_STORE_CTX_idx SSL_get_ex_d_X509_STORE_CTX_idx
+#undef SSL_add_file_cert_subjects_to_stack
+#define SSL_add_file_cert_subjects_to_stack SSL_add_file_cert_subjs_to_stk
+#undef SSL_add_dir_cert_subjects_to_stack
+#define SSL_add_dir_cert_subjects_to_stack SSL_add_dir_cert_subjs_to_stk
+#undef SSL_CTX_use_certificate_chain_file
+#define SSL_CTX_use_certificate_chain_file SSL_CTX_use_cert_chain_file
+#undef SSL_CTX_set_cert_verify_callback
+#define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_cb
+#undef SSL_CTX_set_default_passwd_cb_userdata
+#define SSL_CTX_set_default_passwd_cb_userdata SSL_CTX_set_def_passwd_cb_ud
+#undef SSL_COMP_get_compression_methods
+#define SSL_COMP_get_compression_methods SSL_COMP_get_compress_methods
+
+#undef ssl_add_clienthello_renegotiate_ext
+#define ssl_add_clienthello_renegotiate_ext ssl_add_clienthello_reneg_ext
+#undef ssl_add_serverhello_renegotiate_ext
+#define ssl_add_serverhello_renegotiate_ext ssl_add_serverhello_reneg_ext
+#undef ssl_parse_clienthello_renegotiate_ext
+#define ssl_parse_clienthello_renegotiate_ext ssl_parse_clienthello_reneg_ext
+#undef ssl_parse_serverhello_renegotiate_ext
+#define ssl_parse_serverhello_renegotiate_ext ssl_parse_serverhello_reneg_ext
+
+/* Hack some long ENGINE names */
+#undef ENGINE_get_default_BN_mod_exp_crt
+#define ENGINE_get_default_BN_mod_exp_crt ENGINE_get_def_BN_mod_exp_crt
+#undef ENGINE_set_default_BN_mod_exp_crt
+#define ENGINE_set_default_BN_mod_exp_crt ENGINE_set_def_BN_mod_exp_crt
+#undef ENGINE_set_load_privkey_function
+#define ENGINE_set_load_privkey_function ENGINE_set_load_privkey_fn
+#undef ENGINE_get_load_privkey_function
+#define ENGINE_get_load_privkey_function ENGINE_get_load_privkey_fn
+#undef ENGINE_set_load_ssl_client_cert_function
+#define ENGINE_set_load_ssl_client_cert_function \
+ ENGINE_set_ld_ssl_clnt_cert_fn
+#undef ENGINE_get_ssl_client_cert_function
+#define ENGINE_get_ssl_client_cert_function ENGINE_get_ssl_client_cert_fn
+
+/* Hack some long OCSP names */
+#undef OCSP_REQUEST_get_ext_by_critical
+#define OCSP_REQUEST_get_ext_by_critical OCSP_REQUEST_get_ext_by_crit
+#undef OCSP_BASICRESP_get_ext_by_critical
+#define OCSP_BASICRESP_get_ext_by_critical OCSP_BASICRESP_get_ext_by_crit
+#undef OCSP_SINGLERESP_get_ext_by_critical
+#define OCSP_SINGLERESP_get_ext_by_critical OCSP_SINGLERESP_get_ext_by_crit
+
+/* Hack some long DES names */
+#undef _ossl_old_des_ede3_cfb64_encrypt
+#define _ossl_old_des_ede3_cfb64_encrypt _ossl_odes_ede3_cfb64_encrypt
+#undef _ossl_old_des_ede3_ofb64_encrypt
+#define _ossl_old_des_ede3_ofb64_encrypt _ossl_odes_ede3_ofb64_encrypt
+
+/* Hack some long EVP names */
+#undef OPENSSL_add_all_algorithms_noconf
+#define OPENSSL_add_all_algorithms_noconf OPENSSL_add_all_algo_noconf
+#undef OPENSSL_add_all_algorithms_conf
+#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algo_conf
+
+/* Hack some long EC names */
+#undef EC_GROUP_set_point_conversion_form
+#define EC_GROUP_set_point_conversion_form EC_GROUP_set_point_conv_form
+#undef EC_GROUP_get_point_conversion_form
+#define EC_GROUP_get_point_conversion_form EC_GROUP_get_point_conv_form
+#undef EC_GROUP_clear_free_all_extra_data
+#define EC_GROUP_clear_free_all_extra_data EC_GROUP_clr_free_all_xtra_data
+#undef EC_POINT_set_Jprojective_coordinates_GFp
+#define EC_POINT_set_Jprojective_coordinates_GFp \
+ EC_POINT_set_Jproj_coords_GFp
+#undef EC_POINT_get_Jprojective_coordinates_GFp
+#define EC_POINT_get_Jprojective_coordinates_GFp \
+ EC_POINT_get_Jproj_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GFp
+#define EC_POINT_set_affine_coordinates_GFp EC_POINT_set_affine_coords_GFp
+#undef EC_POINT_get_affine_coordinates_GFp
+#define EC_POINT_get_affine_coordinates_GFp EC_POINT_get_affine_coords_GFp
+#undef EC_POINT_set_compressed_coordinates_GFp
+#define EC_POINT_set_compressed_coordinates_GFp EC_POINT_set_compr_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GF2m
+#define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coords_GF2m
+#undef EC_POINT_get_affine_coordinates_GF2m
+#define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coords_GF2m
+#undef EC_POINT_set_compressed_coordinates_GF2m
+#define EC_POINT_set_compressed_coordinates_GF2m \
+ EC_POINT_set_compr_coords_GF2m
+#undef ec_GF2m_simple_group_clear_finish
+#define ec_GF2m_simple_group_clear_finish ec_GF2m_simple_grp_clr_finish
+#undef ec_GF2m_simple_group_check_discriminant
+#define ec_GF2m_simple_group_check_discriminant ec_GF2m_simple_grp_chk_discrim
+#undef ec_GF2m_simple_point_clear_finish
+#define ec_GF2m_simple_point_clear_finish ec_GF2m_simple_pt_clr_finish
+#undef ec_GF2m_simple_point_set_to_infinity
+#define ec_GF2m_simple_point_set_to_infinity ec_GF2m_simple_pt_set_to_inf
+#undef ec_GF2m_simple_points_make_affine
+#define ec_GF2m_simple_points_make_affine ec_GF2m_simple_pts_make_affine
+#undef ec_GF2m_simple_point_set_affine_coordinates
+#define ec_GF2m_simple_point_set_affine_coordinates \
+ ec_GF2m_smp_pt_set_af_coords
+#undef ec_GF2m_simple_point_get_affine_coordinates
+#define ec_GF2m_simple_point_get_affine_coordinates \
+ ec_GF2m_smp_pt_get_af_coords
+#undef ec_GF2m_simple_set_compressed_coordinates
+#define ec_GF2m_simple_set_compressed_coordinates \
+ ec_GF2m_smp_set_compr_coords
+#undef ec_GFp_simple_group_set_curve_GFp
+#define ec_GFp_simple_group_set_curve_GFp ec_GFp_simple_grp_set_curve_GFp
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_group_clear_finish
+#define ec_GFp_simple_group_clear_finish ec_GFp_simple_grp_clear_finish
+#undef ec_GFp_simple_group_set_generator
+#define ec_GFp_simple_group_set_generator ec_GFp_simple_grp_set_generator
+#undef ec_GFp_simple_group_get0_generator
+#define ec_GFp_simple_group_get0_generator ec_GFp_simple_grp_gt0_generator
+#undef ec_GFp_simple_group_get_cofactor
+#define ec_GFp_simple_group_get_cofactor ec_GFp_simple_grp_get_cofactor
+#undef ec_GFp_simple_point_clear_finish
+#define ec_GFp_simple_point_clear_finish ec_GFp_simple_pt_clear_finish
+#undef ec_GFp_simple_point_set_to_infinity
+#define ec_GFp_simple_point_set_to_infinity ec_GFp_simple_pt_set_to_inf
+#undef ec_GFp_simple_points_make_affine
+#define ec_GFp_simple_points_make_affine ec_GFp_simple_pts_make_affine
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_set_Jprojective_coordinates_GFp
+#define ec_GFp_simple_set_Jprojective_coordinates_GFp \
+ ec_GFp_smp_set_Jproj_coords_GFp
+#undef ec_GFp_simple_get_Jprojective_coordinates_GFp
+#define ec_GFp_simple_get_Jprojective_coordinates_GFp \
+ ec_GFp_smp_get_Jproj_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates_GFp
+#define ec_GFp_simple_point_set_affine_coordinates_GFp \
+ ec_GFp_smp_pt_set_af_coords_GFp
+#undef ec_GFp_simple_point_get_affine_coordinates_GFp
+#define ec_GFp_simple_point_get_affine_coordinates_GFp \
+ ec_GFp_smp_pt_get_af_coords_GFp
+#undef ec_GFp_simple_set_compressed_coordinates_GFp
+#define ec_GFp_simple_set_compressed_coordinates_GFp \
+ ec_GFp_smp_set_compr_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates
+#define ec_GFp_simple_point_set_affine_coordinates \
+ ec_GFp_smp_pt_set_af_coords
+#undef ec_GFp_simple_point_get_affine_coordinates
+#define ec_GFp_simple_point_get_affine_coordinates \
+ ec_GFp_smp_pt_get_af_coords
+#undef ec_GFp_simple_set_compressed_coordinates
+#define ec_GFp_simple_set_compressed_coordinates \
+ ec_GFp_smp_set_compr_coords
+#undef ec_GFp_simple_group_check_discriminant
+#define ec_GFp_simple_group_check_discriminant ec_GFp_simple_grp_chk_discrim
+
+/* Hack som long STORE names */
+#undef STORE_method_set_initialise_function
+#define STORE_method_set_initialise_function STORE_meth_set_initialise_fn
+#undef STORE_method_set_cleanup_function
+#define STORE_method_set_cleanup_function STORE_meth_set_cleanup_fn
+#undef STORE_method_set_generate_function
+#define STORE_method_set_generate_function STORE_meth_set_generate_fn
+#undef STORE_method_set_modify_function
+#define STORE_method_set_modify_function STORE_meth_set_modify_fn
+#undef STORE_method_set_revoke_function
+#define STORE_method_set_revoke_function STORE_meth_set_revoke_fn
+#undef STORE_method_set_delete_function
+#define STORE_method_set_delete_function STORE_meth_set_delete_fn
+#undef STORE_method_set_list_start_function
+#define STORE_method_set_list_start_function STORE_meth_set_list_start_fn
+#undef STORE_method_set_list_next_function
+#define STORE_method_set_list_next_function STORE_meth_set_list_next_fn
+#undef STORE_method_set_list_end_function
+#define STORE_method_set_list_end_function STORE_meth_set_list_end_fn
+#undef STORE_method_set_update_store_function
+#define STORE_method_set_update_store_function STORE_meth_set_update_store_fn
+#undef STORE_method_set_lock_store_function
+#define STORE_method_set_lock_store_function STORE_meth_set_lock_store_fn
+#undef STORE_method_set_unlock_store_function
+#define STORE_method_set_unlock_store_function STORE_meth_set_unlock_store_fn
+#undef STORE_method_get_initialise_function
+#define STORE_method_get_initialise_function STORE_meth_get_initialise_fn
+#undef STORE_method_get_cleanup_function
+#define STORE_method_get_cleanup_function STORE_meth_get_cleanup_fn
+#undef STORE_method_get_generate_function
+#define STORE_method_get_generate_function STORE_meth_get_generate_fn
+#undef STORE_method_get_modify_function
+#define STORE_method_get_modify_function STORE_meth_get_modify_fn
+#undef STORE_method_get_revoke_function
+#define STORE_method_get_revoke_function STORE_meth_get_revoke_fn
+#undef STORE_method_get_delete_function
+#define STORE_method_get_delete_function STORE_meth_get_delete_fn
+#undef STORE_method_get_list_start_function
+#define STORE_method_get_list_start_function STORE_meth_get_list_start_fn
+#undef STORE_method_get_list_next_function
+#define STORE_method_get_list_next_function STORE_meth_get_list_next_fn
+#undef STORE_method_get_list_end_function
+#define STORE_method_get_list_end_function STORE_meth_get_list_end_fn
+#undef STORE_method_get_update_store_function
+#define STORE_method_get_update_store_function STORE_meth_get_update_store_fn
+#undef STORE_method_get_lock_store_function
+#define STORE_method_get_lock_store_function STORE_meth_get_lock_store_fn
+#undef STORE_method_get_unlock_store_function
+#define STORE_method_get_unlock_store_function STORE_meth_get_unlock_store_fn
+
+/* Hack some long CMS names */
+#undef CMS_RecipientInfo_ktri_get0_algs
+#define CMS_RecipientInfo_ktri_get0_algs CMS_RecipInfo_ktri_get0_algs
+#undef CMS_RecipientInfo_ktri_get0_signer_id
+#define CMS_RecipientInfo_ktri_get0_signer_id CMS_RecipInfo_ktri_get0_sigr_id
+#undef CMS_OtherRevocationInfoFormat_it
+#define CMS_OtherRevocationInfoFormat_it CMS_OtherRevocInfoFormat_it
+#undef CMS_KeyAgreeRecipientIdentifier_it
+#define CMS_KeyAgreeRecipientIdentifier_it CMS_KeyAgreeRecipIdentifier_it
+#undef CMS_OriginatorIdentifierOrKey_it
+#define CMS_OriginatorIdentifierOrKey_it CMS_OriginatorIdOrKey_it
+#undef cms_SignerIdentifier_get0_signer_id
+#define cms_SignerIdentifier_get0_signer_id cms_SignerId_get0_signer_id
+
+/* Hack some long DTLS1 names */
+#undef dtls1_retransmit_buffered_messages
+#define dtls1_retransmit_buffered_messages dtls1_retransmit_buffered_msgs
+
+#endif /* defined OPENSSL_SYS_VMS */
+
+
+/* Case insensiteve linking causes problems.... */
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2)
+#undef ERR_load_CRYPTO_strings
+#define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings
+#undef OCSP_crlID_new
+#define OCSP_crlID_new OCSP_crlID2_new
+
+#undef d2i_ECPARAMETERS
+#define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS
+#undef i2d_ECPARAMETERS
+#define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS
+#undef d2i_ECPKPARAMETERS
+#define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS
+#undef i2d_ECPKPARAMETERS
+#define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS
+
+/* These functions do not seem to exist! However, I'm paranoid...
+ Original command in x509v3.h:
+ These functions are being redefined in another directory,
+ and clash when the linker is case-insensitive, so let's
+ hide them a little, by giving them an extra 'o' at the
+ beginning of the name... */
+#undef X509v3_cleanup_extensions
+#define X509v3_cleanup_extensions oX509v3_cleanup_extensions
+#undef X509v3_add_extension
+#define X509v3_add_extension oX509v3_add_extension
+#undef X509v3_add_netscape_extensions
+#define X509v3_add_netscape_extensions oX509v3_add_netscape_extensions
+#undef X509v3_add_standard_extensions
+#define X509v3_add_standard_extensions oX509v3_add_standard_extensions
+
+
+#endif
+
+
+#endif /* ! defined HEADER_VMS_IDHACKS_H */
+/* This one clashes with CMS_data_create */
+#undef cms_Data_create
+#define cms_Data_create priv_cms_Data_create
diff --git a/src/Mayaqua/win32_inc/openssl/tls1.h b/src/Mayaqua/win32_inc/openssl/tls1.h
new file mode 100644
index 00000000..3ae5bfc4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/tls1.h
@@ -0,0 +1,410 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_TLS1_H
+#define HEADER_TLS1_H
+
+#include <openssl/buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0
+
+#define TLS1_VERSION 0x0301
+#define TLS1_VERSION_MAJOR 0x03
+#define TLS1_VERSION_MINOR 0x01
+
+#define TLS1_AD_DECRYPTION_FAILED 21
+#define TLS1_AD_RECORD_OVERFLOW 22
+#define TLS1_AD_UNKNOWN_CA 48 /* fatal */
+#define TLS1_AD_ACCESS_DENIED 49 /* fatal */
+#define TLS1_AD_DECODE_ERROR 50 /* fatal */
+#define TLS1_AD_DECRYPT_ERROR 51
+#define TLS1_AD_EXPORT_RESTRICTION 60 /* fatal */
+#define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */
+#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
+#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */
+#define TLS1_AD_USER_CANCELLED 90
+#define TLS1_AD_NO_RENEGOTIATION 100
+/* codes 110-114 are from RFC3546 */
+#define TLS1_AD_UNSUPPORTED_EXTENSION 110
+#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
+#define TLS1_AD_UNRECOGNIZED_NAME 112
+#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
+#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+
+/* ExtensionType values from RFC 3546 */
+#define TLSEXT_TYPE_server_name 0
+#define TLSEXT_TYPE_max_fragment_length 1
+#define TLSEXT_TYPE_client_certificate_url 2
+#define TLSEXT_TYPE_trusted_ca_keys 3
+#define TLSEXT_TYPE_truncated_hmac 4
+#define TLSEXT_TYPE_status_request 5
+#define TLSEXT_TYPE_elliptic_curves 10
+#define TLSEXT_TYPE_ec_point_formats 11
+#define TLSEXT_TYPE_session_ticket 35
+
+/* Temporary extension type */
+#define TLSEXT_TYPE_renegotiate 0xff01
+
+/* NameType value from RFC 3546 */
+#define TLSEXT_NAMETYPE_host_name 0
+/* status request value from RFC 3546 */
+#define TLSEXT_STATUSTYPE_ocsp 1
+
+#ifndef OPENSSL_NO_TLSEXT
+
+#define TLSEXT_MAXLEN_host_name 255
+
+const char *SSL_get_servername(const SSL *s, const int type) ;
+int SSL_get_servername_type(const SSL *s) ;
+
+#define SSL_set_tlsext_host_name(s,name) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
+
+#define SSL_set_tlsext_debug_callback(ssl, cb) \
+SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
+
+#define SSL_set_tlsext_debug_arg(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
+
+#define SSL_set_tlsext_status_type(ssl, type) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
+
+#define SSL_get_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
+
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
+
+#define SSL_TLSEXT_ERR_OK 0
+#define SSL_TLSEXT_ERR_ALERT_WARNING 1
+#define SSL_TLSEXT_ERR_ALERT_FATAL 2
+#define SSL_TLSEXT_ERR_NOACK 3
+
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
+
+#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+
+#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb)
+
+#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \
+SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg)
+
+#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+
+#endif
+
+/* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
+ * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
+ * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably
+ * shouldn't. */
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061
+#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065
+#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066
+
+/* AES ciphersuites from RFC3268 */
+
+#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F
+#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030
+#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031
+#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032
+#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033
+#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034
+
+#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035
+#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036
+#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037
+#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038
+#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039
+#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045
+#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046
+
+#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088
+#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096
+#define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097
+#define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098
+#define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099
+#define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A
+#define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */
+#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001
+#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002
+#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005
+
+#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006
+#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007
+#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A
+
+#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B
+#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C
+#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D
+#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E
+#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F
+
+#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010
+#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011
+#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014
+
+#define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015
+#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016
+#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017
+#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018
+#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019
+
+/* XXX
+ * Inconsistency alert:
+ * The OpenSSL names of ciphers with ephemeral DH here include the string
+ * "DHE", while elsewhere it has always been "EDH".
+ * (The alias for the list of all such ciphers also is "EDH".)
+ * The specifications speak of "EDH"; maybe we should allow both forms
+ * for everything. */
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DHE-DSS-DES-CBC-SHA"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA"
+
+/* AES ciphersuites from RFC3268 */
+#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA"
+#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA"
+
+#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA"
+#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA"
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */
+#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA"
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA"
+
+#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA"
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA"
+#define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA"
+#define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA"
+#define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA"
+
+#define TLS_CT_RSA_SIGN 1
+#define TLS_CT_DSS_SIGN 2
+#define TLS_CT_RSA_FIXED_DH 3
+#define TLS_CT_DSS_FIXED_DH 4
+#define TLS_CT_ECDSA_SIGN 64
+#define TLS_CT_RSA_FIXED_ECDH 65
+#define TLS_CT_ECDSA_FIXED_ECDH 66
+#define TLS_CT_NUMBER 7
+
+#define TLS1_FINISH_MAC_LENGTH 12
+
+#define TLS_MD_MAX_CONST_SIZE 20
+#define TLS_MD_CLIENT_FINISH_CONST "client finished"
+#define TLS_MD_CLIENT_FINISH_CONST_SIZE 15
+#define TLS_MD_SERVER_FINISH_CONST "server finished"
+#define TLS_MD_SERVER_FINISH_CONST_SIZE 15
+#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_KEY_EXPANSION_CONST "key expansion"
+#define TLS_MD_KEY_EXPANSION_CONST_SIZE 13
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key"
+#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_IV_BLOCK_CONST "IV block"
+#define TLS_MD_IV_BLOCK_CONST_SIZE 8
+#define TLS_MD_MASTER_SECRET_CONST "master secret"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE 13
+
+#ifdef CHARSET_EBCDIC
+#undef TLS_MD_CLIENT_FINISH_CONST
+#define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*client finished*/
+#undef TLS_MD_SERVER_FINISH_CONST
+#define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*server finished*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/
+#undef TLS_MD_KEY_EXPANSION_CONST
+#define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" /*key expansion*/
+#undef TLS_MD_CLIENT_WRITE_KEY_CONST
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*client write key*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/
+#undef TLS_MD_IV_BLOCK_CONST
+#define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" /*IV block*/
+#undef TLS_MD_MASTER_SECRET_CONST
+#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
diff --git a/src/Mayaqua/win32_inc/openssl/tmdiff.h b/src/Mayaqua/win32_inc/openssl/tmdiff.h
new file mode 100644
index 00000000..6ed309e6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/tmdiff.h
@@ -0,0 +1,93 @@
+/* crypto/tmdiff.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+/* ... erm yeah, "dynamic hash tables" you say?
+ *
+ * And what would dynamic hash tables have to do with any of this code *now*?
+ * AFAICS, this code is only referenced by crypto/bn/exp.c which is an unused
+ * file that I doubt compiles any more. speed.c is the only thing that could
+ * use this (and it has nothing to do with hash tables), yet it instead has its
+ * own duplication of all this stuff and looks, if anything, more complete. See
+ * the corresponding note in apps/speed.c.
+ * The Bemused - Geoff
+ */
+
+#ifndef HEADER_TMDIFF_H
+#define HEADER_TMDIFF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ms_tm MS_TM;
+
+MS_TM *ms_time_new(void );
+void ms_time_free(MS_TM *a);
+void ms_time_get(MS_TM *a);
+double ms_time_diff(MS_TM *start, MS_TM *end);
+int ms_time_cmp(const MS_TM *ap, const MS_TM *bp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/txt_db.h b/src/Mayaqua/win32_inc/openssl/txt_db.h
new file mode 100644
index 00000000..a767e455
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/txt_db.h
@@ -0,0 +1,109 @@
+/* crypto/txt_db/txt_db.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_TXT_DB_H
+#define HEADER_TXT_DB_H
+
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/lhash.h>
+
+#define DB_ERROR_OK 0
+#define DB_ERROR_MALLOC 1
+#define DB_ERROR_INDEX_CLASH 2
+#define DB_ERROR_INDEX_OUT_OF_RANGE 3
+#define DB_ERROR_NO_INDEX 4
+#define DB_ERROR_INSERT_INDEX_CLASH 5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct txt_db_st
+ {
+ int num_fields;
+ STACK /* char ** */ *data;
+ LHASH **index;
+ int (**qual)(char **);
+ long error;
+ long arg1;
+ long arg2;
+ char **arg_row;
+ } TXT_DB;
+
+#ifndef OPENSSL_NO_BIO
+TXT_DB *TXT_DB_read(BIO *in, int num);
+long TXT_DB_write(BIO *out, TXT_DB *db);
+#else
+TXT_DB *TXT_DB_read(char *in, int num);
+long TXT_DB_write(char *out, TXT_DB *db);
+#endif
+int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(char **),
+ LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp);
+void TXT_DB_free(TXT_DB *db);
+char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value);
+int TXT_DB_insert(TXT_DB *db,char **value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ui.h b/src/Mayaqua/win32_inc/openssl/ui.h
new file mode 100644
index 00000000..5570e0d1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ui.h
@@ -0,0 +1,381 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_H
+#define HEADER_UI_H
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/crypto.h>
+#endif
+#include <openssl/safestack.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct ui_st UI; */
+/* typedef struct ui_method_st UI_METHOD; */
+
+
+/* All the following functions return -1 or NULL on error and in some cases
+ (UI_process()) -2 if interrupted or in some other way cancelled.
+ When everything is fine, they return 0, a positive value or a non-NULL
+ pointer, all depending on their purpose. */
+
+/* Creators and destructor. */
+UI *UI_new(void);
+UI *UI_new_method(const UI_METHOD *method);
+void UI_free(UI *ui);
+
+/* The following functions are used to add strings to be printed and prompt
+ strings to prompt for data. The names are UI_{add,dup}_<function>_string
+ and UI_{add,dup}_input_boolean.
+
+ UI_{add,dup}_<function>_string have the following meanings:
+ add add a text or prompt string. The pointers given to these
+ functions are used verbatim, no copying is done.
+ dup make a copy of the text or prompt string, then add the copy
+ to the collection of strings in the user interface.
+ <function>
+ The function is a name for the functionality that the given
+ string shall be used for. It can be one of:
+ input use the string as data prompt.
+ verify use the string as verification prompt. This
+ is used to verify a previous input.
+ info use the string for informational output.
+ error use the string for error output.
+ Honestly, there's currently no difference between info and error for the
+ moment.
+
+ UI_{add,dup}_input_boolean have the same semantics for "add" and "dup",
+ and are typically used when one wants to prompt for a yes/no response.
+
+
+ All of the functions in this group take a UI and a prompt string.
+ The string input and verify addition functions also take a flag argument,
+ a buffer for the result to end up with, a minimum input size and a maximum
+ input size (the result buffer MUST be large enough to be able to contain
+ the maximum number of characters). Additionally, the verify addition
+ functions takes another buffer to compare the result against.
+ The boolean input functions take an action description string (which should
+ be safe to ignore if the expected user action is obvious, for example with
+ a dialog box with an OK button and a Cancel button), a string of acceptable
+ characters to mean OK and to mean Cancel. The two last strings are checked
+ to make sure they don't have common characters. Additionally, the same
+ flag argument as for the string input is taken, as well as a result buffer.
+ The result buffer is required to be at least one byte long. Depending on
+ the answer, the first character from the OK or the Cancel character strings
+ will be stored in the first byte of the result buffer. No NUL will be
+ added, so the result is *not* a string.
+
+ On success, the all return an index of the added information. That index
+ is usefull when retrieving results with UI_get0_result(). */
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_add_info_string(UI *ui, const char *text);
+int UI_dup_info_string(UI *ui, const char *text);
+int UI_add_error_string(UI *ui, const char *text);
+int UI_dup_error_string(UI *ui, const char *text);
+
+/* These are the possible flags. They can be or'ed together. */
+/* Use to have echoing of input */
+#define UI_INPUT_FLAG_ECHO 0x01
+/* Use a default password. Where that password is found is completely
+ up to the application, it might for example be in the user data set
+ with UI_add_user_data(). It is not recommended to have more than
+ one input in each UI being marked with this flag, or the application
+ might get confused. */
+#define UI_INPUT_FLAG_DEFAULT_PWD 0x02
+
+/* The user of these routines may want to define flags of their own. The core
+ UI won't look at those, but will pass them on to the method routines. They
+ must use higher bits so they don't get confused with the UI bits above.
+ UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good
+ example of use is this:
+
+ #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE)
+
+*/
+#define UI_INPUT_FLAG_USER_BASE 16
+
+
+/* The following function helps construct a prompt. object_desc is a
+ textual short description of the object, for example "pass phrase",
+ and object_name is the name of the object (might be a card name or
+ a file name.
+ The returned string shall always be allocated on the heap with
+ OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
+
+ If the ui_method doesn't contain a pointer to a user-defined prompt
+ constructor, a default string is built, looking like this:
+
+ "Enter {object_desc} for {object_name}:"
+
+ So, if object_desc has the value "pass phrase" and object_name has
+ the value "foo.key", the resulting string is:
+
+ "Enter pass phrase for foo.key:"
+*/
+char *UI_construct_prompt(UI *ui_method,
+ const char *object_desc, const char *object_name);
+
+
+/* The following function is used to store a pointer to user-specific data.
+ Any previous such pointer will be returned and replaced.
+
+ For callback purposes, this function makes a lot more sense than using
+ ex_data, since the latter requires that different parts of OpenSSL or
+ applications share the same ex_data index.
+
+ Note that the UI_OpenSSL() method completely ignores the user data.
+ Other methods may not, however. */
+void *UI_add_user_data(UI *ui, void *user_data);
+/* We need a user data retrieving function as well. */
+void *UI_get0_user_data(UI *ui);
+
+/* Return the result associated with a prompt given with the index i. */
+const char *UI_get0_result(UI *ui, int i);
+
+/* When all strings have been added, process the whole thing. */
+int UI_process(UI *ui);
+
+/* Give a user interface parametrised control commands. This can be used to
+ send down an integer, a data pointer or a function pointer, as well as
+ be used to get information from a UI. */
+int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void));
+
+/* The commands */
+/* Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the
+ OpenSSL error stack before printing any info or added error messages and
+ before any prompting. */
+#define UI_CTRL_PRINT_ERRORS 1
+/* Check if a UI_process() is possible to do again with the same instance of
+ a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0
+ if not. */
+#define UI_CTRL_IS_REDOABLE 2
+
+
+/* Some methods may use extra data */
+#define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg)
+#define UI_get_app_data(s) UI_get_ex_data(s,0)
+int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int UI_set_ex_data(UI *r,int idx,void *arg);
+void *UI_get_ex_data(UI *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+void UI_set_default_method(const UI_METHOD *meth);
+const UI_METHOD *UI_get_default_method(void);
+const UI_METHOD *UI_get_method(UI *ui);
+const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth);
+
+/* The method with all the built-in thingies */
+UI_METHOD *UI_OpenSSL(void);
+
+
+/* ---------- For method writers ---------- */
+/* A method contains a number of functions that implement the low level
+ of the User Interface. The functions are:
+
+ an opener This function starts a session, maybe by opening
+ a channel to a tty, or by opening a window.
+ a writer This function is called to write a given string,
+ maybe to the tty, maybe as a field label in a
+ window.
+ a flusher This function is called to flush everything that
+ has been output so far. It can be used to actually
+ display a dialog box after it has been built.
+ a reader This function is called to read a given prompt,
+ maybe from the tty, maybe from a field in a
+ window. Note that it's called wth all string
+ structures, not only the prompt ones, so it must
+ check such things itself.
+ a closer This function closes the session, maybe by closing
+ the channel to the tty, or closing the window.
+
+ All these functions are expected to return:
+
+ 0 on error.
+ 1 on success.
+ -1 on out-of-band events, for example if some prompting has
+ been canceled (by pressing Ctrl-C, for example). This is
+ only checked when returned by the flusher or the reader.
+
+ The way this is used, the opener is first called, then the writer for all
+ strings, then the flusher, then the reader for all strings and finally the
+ closer. Note that if you want to prompt from a terminal or other command
+ line interface, the best is to have the reader also write the prompts
+ instead of having the writer do it. If you want to prompt from a dialog
+ box, the writer can be used to build up the contents of the box, and the
+ flusher to actually display the box and run the event loop until all data
+ has been given, after which the reader only grabs the given data and puts
+ them back into the UI strings.
+
+ All method functions take a UI as argument. Additionally, the writer and
+ the reader take a UI_STRING.
+*/
+
+/* The UI_STRING type is the data structure that contains all the needed info
+ about a string or a prompt, including test data for a verification prompt.
+*/
+DECLARE_STACK_OF(UI_STRING)
+typedef struct ui_string_st UI_STRING;
+
+/* The different types of strings that are currently supported.
+ This is only needed by method authors. */
+enum UI_string_types
+ {
+ UIT_NONE=0,
+ UIT_PROMPT, /* Prompt for a string */
+ UIT_VERIFY, /* Prompt for a string and verify */
+ UIT_BOOLEAN, /* Prompt for a yes/no response */
+ UIT_INFO, /* Send info to the user */
+ UIT_ERROR /* Send an error message to the user */
+ };
+
+/* Create and manipulate methods */
+UI_METHOD *UI_create_method(char *name);
+void UI_destroy_method(UI_METHOD *ui_method);
+int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui));
+int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis));
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui));
+int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis));
+int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui));
+int (*UI_method_get_opener(UI_METHOD *method))(UI*);
+int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_flusher(UI_METHOD *method))(UI*);
+int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_closer(UI_METHOD *method))(UI*);
+
+/* The following functions are helpers for method writers to access relevant
+ data from a UI_STRING. */
+
+/* Return type of the UI_STRING */
+enum UI_string_types UI_get_string_type(UI_STRING *uis);
+/* Return input flags of the UI_STRING */
+int UI_get_input_flags(UI_STRING *uis);
+/* Return the actual string to output (the prompt, info or error) */
+const char *UI_get0_output_string(UI_STRING *uis);
+/* Return the optional action string to output (the boolean promtp instruction) */
+const char *UI_get0_action_string(UI_STRING *uis);
+/* Return the result of a prompt */
+const char *UI_get0_result_string(UI_STRING *uis);
+/* Return the string to test the result against. Only useful with verifies. */
+const char *UI_get0_test_string(UI_STRING *uis);
+/* Return the required minimum size of the result */
+int UI_get_result_minsize(UI_STRING *uis);
+/* Return the required maximum size of the result */
+int UI_get_result_maxsize(UI_STRING *uis);
+/* Set the result of a UI_STRING. */
+int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+
+
+/* A couple of popular utility functions */
+int UI_UTIL_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_UI_strings(void);
+
+/* Error codes for the UI functions. */
+
+/* Function codes. */
+#define UI_F_GENERAL_ALLOCATE_BOOLEAN 108
+#define UI_F_GENERAL_ALLOCATE_PROMPT 109
+#define UI_F_GENERAL_ALLOCATE_STRING 100
+#define UI_F_UI_CTRL 111
+#define UI_F_UI_DUP_ERROR_STRING 101
+#define UI_F_UI_DUP_INFO_STRING 102
+#define UI_F_UI_DUP_INPUT_BOOLEAN 110
+#define UI_F_UI_DUP_INPUT_STRING 103
+#define UI_F_UI_DUP_VERIFY_STRING 106
+#define UI_F_UI_GET0_RESULT 107
+#define UI_F_UI_NEW_METHOD 104
+#define UI_F_UI_SET_RESULT 105
+
+/* Reason codes. */
+#define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104
+#define UI_R_INDEX_TOO_LARGE 102
+#define UI_R_INDEX_TOO_SMALL 103
+#define UI_R_NO_RESULT_BUFFER 105
+#define UI_R_RESULT_TOO_LARGE 100
+#define UI_R_RESULT_TOO_SMALL 101
+#define UI_R_UNKNOWN_CONTROL_COMMAND 106
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ui_compat.h b/src/Mayaqua/win32_inc/openssl/ui_compat.h
new file mode 100644
index 00000000..0209438d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ui_compat.h
@@ -0,0 +1,83 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_COMPAT_H
+#define HEADER_UI_COMPAT_H
+
+#include <openssl/opensslconf.h>
+#include <openssl/ui.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following functions were previously part of the DES section,
+ and are provided here for backward compatibility reasons. */
+
+#define des_read_pw_string(b,l,p,v) \
+ _ossl_old_des_read_pw_string((b),(l),(p),(v))
+#define des_read_pw(b,bf,s,p,v) \
+ _ossl_old_des_read_pw((b),(bf),(s),(p),(v))
+
+int _ossl_old_des_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int _ossl_old_des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/x509.h b/src/Mayaqua/win32_inc/openssl/x509.h
new file mode 100644
index 00000000..30ebe555
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509.h
@@ -0,0 +1,1357 @@
+/* crypto/x509/x509.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_X509_H
+#define HEADER_X509_H
+
+#include <openssl/e_os2.h>
+#include <openssl/symhacks.h>
+#ifndef OPENSSL_NO_BUFFER
+#include <openssl/buffer.h>
+#endif
+#ifndef OPENSSL_NO_EVP
+#include <openssl/evp.h>
+#endif
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/asn1.h>
+#include <openssl/safestack.h>
+
+#ifndef OPENSSL_NO_EC
+#include <openssl/ec.h>
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#endif
+
+#ifndef OPENSSL_NO_SHA
+#include <openssl/sha.h>
+#endif
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 these are defined in wincrypt.h */
+#undef X509_NAME
+#undef X509_CERT_PAIR
+#undef X509_EXTENSIONS
+#endif
+
+#define X509_FILETYPE_PEM 1
+#define X509_FILETYPE_ASN1 2
+#define X509_FILETYPE_DEFAULT 3
+
+#define X509v3_KU_DIGITAL_SIGNATURE 0x0080
+#define X509v3_KU_NON_REPUDIATION 0x0040
+#define X509v3_KU_KEY_ENCIPHERMENT 0x0020
+#define X509v3_KU_DATA_ENCIPHERMENT 0x0010
+#define X509v3_KU_KEY_AGREEMENT 0x0008
+#define X509v3_KU_KEY_CERT_SIGN 0x0004
+#define X509v3_KU_CRL_SIGN 0x0002
+#define X509v3_KU_ENCIPHER_ONLY 0x0001
+#define X509v3_KU_DECIPHER_ONLY 0x8000
+#define X509v3_KU_UNDEF 0xffff
+
+typedef struct X509_objects_st
+ {
+ int nid;
+ int (*a2i)(void);
+ int (*i2a)(void);
+ } X509_OBJECTS;
+
+struct X509_algor_st
+ {
+ ASN1_OBJECT *algorithm;
+ ASN1_TYPE *parameter;
+ } /* X509_ALGOR */;
+
+DECLARE_ASN1_SET_OF(X509_ALGOR)
+
+typedef STACK_OF(X509_ALGOR) X509_ALGORS;
+
+typedef struct X509_val_st
+ {
+ ASN1_TIME *notBefore;
+ ASN1_TIME *notAfter;
+ } X509_VAL;
+
+typedef struct X509_pubkey_st
+ {
+ X509_ALGOR *algor;
+ ASN1_BIT_STRING *public_key;
+ EVP_PKEY *pkey;
+ } X509_PUBKEY;
+
+typedef struct X509_sig_st
+ {
+ X509_ALGOR *algor;
+ ASN1_OCTET_STRING *digest;
+ } X509_SIG;
+
+typedef struct X509_name_entry_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_STRING *value;
+ int set;
+ int size; /* temp variable */
+ } X509_NAME_ENTRY;
+
+DECLARE_STACK_OF(X509_NAME_ENTRY)
+DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
+
+/* we always keep X509_NAMEs in 2 forms. */
+struct X509_name_st
+ {
+ STACK_OF(X509_NAME_ENTRY) *entries;
+ int modified; /* true if 'bytes' needs to be built */
+#ifndef OPENSSL_NO_BUFFER
+ BUF_MEM *bytes;
+#else
+ char *bytes;
+#endif
+ unsigned long hash; /* Keep the hash around for lookups */
+ } /* X509_NAME */;
+
+DECLARE_STACK_OF(X509_NAME)
+
+#define X509_EX_V_NETSCAPE_HACK 0x8000
+#define X509_EX_V_INIT 0x0001
+typedef struct X509_extension_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_BOOLEAN critical;
+ ASN1_OCTET_STRING *value;
+ } X509_EXTENSION;
+
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+
+DECLARE_STACK_OF(X509_EXTENSION)
+DECLARE_ASN1_SET_OF(X509_EXTENSION)
+
+/* a sequence of these are used */
+typedef struct x509_attributes_st
+ {
+ ASN1_OBJECT *object;
+ int single; /* 0 for a set, 1 for a single item (which is wrong) */
+ union {
+ char *ptr;
+/* 0 */ STACK_OF(ASN1_TYPE) *set;
+/* 1 */ ASN1_TYPE *single;
+ } value;
+ } X509_ATTRIBUTE;
+
+DECLARE_STACK_OF(X509_ATTRIBUTE)
+DECLARE_ASN1_SET_OF(X509_ATTRIBUTE)
+
+
+typedef struct X509_req_info_st
+ {
+ ASN1_ENCODING enc;
+ ASN1_INTEGER *version;
+ X509_NAME *subject;
+ X509_PUBKEY *pubkey;
+ /* d=2 hl=2 l= 0 cons: cont: 00 */
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+ } X509_REQ_INFO;
+
+typedef struct X509_req_st
+ {
+ X509_REQ_INFO *req_info;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int references;
+ } X509_REQ;
+
+typedef struct x509_cinf_st
+ {
+ ASN1_INTEGER *version; /* [ 0 ] default of v1 */
+ ASN1_INTEGER *serialNumber;
+ X509_ALGOR *signature;
+ X509_NAME *issuer;
+ X509_VAL *validity;
+ X509_NAME *subject;
+ X509_PUBKEY *key;
+ ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */
+ ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */
+ STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */
+ ASN1_ENCODING enc;
+ } X509_CINF;
+
+/* This stuff is certificate "auxiliary info"
+ * it contains details which are useful in certificate
+ * stores and databases. When used this is tagged onto
+ * the end of the certificate itself
+ */
+
+typedef struct x509_cert_aux_st
+ {
+ STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */
+ STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */
+ ASN1_UTF8STRING *alias; /* "friendly name" */
+ ASN1_OCTET_STRING *keyid; /* key id of private key */
+ STACK_OF(X509_ALGOR) *other; /* other unspecified info */
+ } X509_CERT_AUX;
+
+struct x509_st
+ {
+ X509_CINF *cert_info;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int valid;
+ int references;
+ char *name;
+ CRYPTO_EX_DATA ex_data;
+ /* These contain copies of various extension values */
+ long ex_pathlen;
+ long ex_pcpathlen;
+ unsigned long ex_flags;
+ unsigned long ex_kusage;
+ unsigned long ex_xkusage;
+ unsigned long ex_nscert;
+ ASN1_OCTET_STRING *skid;
+ struct AUTHORITY_KEYID_st *akid;
+ X509_POLICY_CACHE *policy_cache;
+#ifndef OPENSSL_NO_RFC3779
+ STACK_OF(IPAddressFamily) *rfc3779_addr;
+ struct ASIdentifiers_st *rfc3779_asid;
+#endif
+#ifndef OPENSSL_NO_SHA
+ unsigned char sha1_hash[SHA_DIGEST_LENGTH];
+#endif
+ X509_CERT_AUX *aux;
+ } /* X509 */;
+
+DECLARE_STACK_OF(X509)
+DECLARE_ASN1_SET_OF(X509)
+
+/* This is used for a table of trust checking functions */
+
+typedef struct x509_trust_st {
+ int trust;
+ int flags;
+ int (*check_trust)(struct x509_trust_st *, X509 *, int);
+ char *name;
+ int arg1;
+ void *arg2;
+} X509_TRUST;
+
+DECLARE_STACK_OF(X509_TRUST)
+
+typedef struct x509_cert_pair_st {
+ X509 *forward;
+ X509 *reverse;
+} X509_CERT_PAIR;
+
+/* standard trust ids */
+
+#define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */
+
+#define X509_TRUST_COMPAT 1
+#define X509_TRUST_SSL_CLIENT 2
+#define X509_TRUST_SSL_SERVER 3
+#define X509_TRUST_EMAIL 4
+#define X509_TRUST_OBJECT_SIGN 5
+#define X509_TRUST_OCSP_SIGN 6
+#define X509_TRUST_OCSP_REQUEST 7
+
+/* Keep these up to date! */
+#define X509_TRUST_MIN 1
+#define X509_TRUST_MAX 7
+
+
+/* trust_flags values */
+#define X509_TRUST_DYNAMIC 1
+#define X509_TRUST_DYNAMIC_NAME 2
+
+/* check_trust return codes */
+
+#define X509_TRUST_TRUSTED 1
+#define X509_TRUST_REJECTED 2
+#define X509_TRUST_UNTRUSTED 3
+
+/* Flags for X509_print_ex() */
+
+#define X509_FLAG_COMPAT 0
+#define X509_FLAG_NO_HEADER 1L
+#define X509_FLAG_NO_VERSION (1L << 1)
+#define X509_FLAG_NO_SERIAL (1L << 2)
+#define X509_FLAG_NO_SIGNAME (1L << 3)
+#define X509_FLAG_NO_ISSUER (1L << 4)
+#define X509_FLAG_NO_VALIDITY (1L << 5)
+#define X509_FLAG_NO_SUBJECT (1L << 6)
+#define X509_FLAG_NO_PUBKEY (1L << 7)
+#define X509_FLAG_NO_EXTENSIONS (1L << 8)
+#define X509_FLAG_NO_SIGDUMP (1L << 9)
+#define X509_FLAG_NO_AUX (1L << 10)
+#define X509_FLAG_NO_ATTRIBUTES (1L << 11)
+
+/* Flags specific to X509_NAME_print_ex() */
+
+/* The field separator information */
+
+#define XN_FLAG_SEP_MASK (0xf << 16)
+
+#define XN_FLAG_COMPAT 0 /* Traditional SSLeay: use old X509_NAME_print */
+#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) /* RFC2253 ,+ */
+#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) /* ,+ spaced: more readable */
+#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) /* ;+ spaced */
+#define XN_FLAG_SEP_MULTILINE (4 << 16) /* One line per field */
+
+#define XN_FLAG_DN_REV (1 << 20) /* Reverse DN order */
+
+/* How the field name is shown */
+
+#define XN_FLAG_FN_MASK (0x3 << 21)
+
+#define XN_FLAG_FN_SN 0 /* Object short name */
+#define XN_FLAG_FN_LN (1 << 21) /* Object long name */
+#define XN_FLAG_FN_OID (2 << 21) /* Always use OIDs */
+#define XN_FLAG_FN_NONE (3 << 21) /* No field names */
+
+#define XN_FLAG_SPC_EQ (1 << 23) /* Put spaces round '=' */
+
+/* This determines if we dump fields we don't recognise:
+ * RFC2253 requires this.
+ */
+
+#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
+
+#define XN_FLAG_FN_ALIGN (1 << 25) /* Align field names to 20 characters */
+
+/* Complete set of RFC2253 flags */
+
+#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \
+ XN_FLAG_SEP_COMMA_PLUS | \
+ XN_FLAG_DN_REV | \
+ XN_FLAG_FN_SN | \
+ XN_FLAG_DUMP_UNKNOWN_FIELDS)
+
+/* readable oneline form */
+
+#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \
+ ASN1_STRFLGS_ESC_QUOTE | \
+ XN_FLAG_SEP_CPLUS_SPC | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_SN)
+
+/* readable multiline form */
+
+#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ XN_FLAG_SEP_MULTILINE | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_LN | \
+ XN_FLAG_FN_ALIGN)
+
+typedef struct X509_revoked_st
+ {
+ ASN1_INTEGER *serialNumber;
+ ASN1_TIME *revocationDate;
+ STACK_OF(X509_EXTENSION) /* optional */ *extensions;
+ int sequence; /* load sequence */
+ } X509_REVOKED;
+
+DECLARE_STACK_OF(X509_REVOKED)
+DECLARE_ASN1_SET_OF(X509_REVOKED)
+
+typedef struct X509_crl_info_st
+ {
+ ASN1_INTEGER *version;
+ X509_ALGOR *sig_alg;
+ X509_NAME *issuer;
+ ASN1_TIME *lastUpdate;
+ ASN1_TIME *nextUpdate;
+ STACK_OF(X509_REVOKED) *revoked;
+ STACK_OF(X509_EXTENSION) /* [0] */ *extensions;
+ ASN1_ENCODING enc;
+ } X509_CRL_INFO;
+
+struct X509_crl_st
+ {
+ /* actual signature */
+ X509_CRL_INFO *crl;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int references;
+ } /* X509_CRL */;
+
+DECLARE_STACK_OF(X509_CRL)
+DECLARE_ASN1_SET_OF(X509_CRL)
+
+typedef struct private_key_st
+ {
+ int version;
+ /* The PKCS#8 data types */
+ X509_ALGOR *enc_algor;
+ ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */
+
+ /* When decrypted, the following will not be NULL */
+ EVP_PKEY *dec_pkey;
+
+ /* used to encrypt and decrypt */
+ int key_length;
+ char *key_data;
+ int key_free; /* true if we should auto free key_data */
+
+ /* expanded version of 'enc_algor' */
+ EVP_CIPHER_INFO cipher;
+
+ int references;
+ } X509_PKEY;
+
+#ifndef OPENSSL_NO_EVP
+typedef struct X509_info_st
+ {
+ X509 *x509;
+ X509_CRL *crl;
+ X509_PKEY *x_pkey;
+
+ EVP_CIPHER_INFO enc_cipher;
+ int enc_len;
+ char *enc_data;
+
+ int references;
+ } X509_INFO;
+
+DECLARE_STACK_OF(X509_INFO)
+#endif
+
+/* The next 2 structures and their 8 routines were sent to me by
+ * Pat Richard <patr@x509.com> and are used to manipulate
+ * Netscapes spki structures - useful if you are writing a CA web page
+ */
+typedef struct Netscape_spkac_st
+ {
+ X509_PUBKEY *pubkey;
+ ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */
+ } NETSCAPE_SPKAC;
+
+typedef struct Netscape_spki_st
+ {
+ NETSCAPE_SPKAC *spkac; /* signed public key and challenge */
+ X509_ALGOR *sig_algor;
+ ASN1_BIT_STRING *signature;
+ } NETSCAPE_SPKI;
+
+/* Netscape certificate sequence structure */
+typedef struct Netscape_certificate_sequence
+ {
+ ASN1_OBJECT *type;
+ STACK_OF(X509) *certs;
+ } NETSCAPE_CERT_SEQUENCE;
+
+/* Unused (and iv length is wrong)
+typedef struct CBCParameter_st
+ {
+ unsigned char iv[8];
+ } CBC_PARAM;
+*/
+
+/* Password based encryption structure */
+
+typedef struct PBEPARAM_st {
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter;
+} PBEPARAM;
+
+/* Password based encryption V2 structures */
+
+typedef struct PBE2PARAM_st {
+X509_ALGOR *keyfunc;
+X509_ALGOR *encryption;
+} PBE2PARAM;
+
+typedef struct PBKDF2PARAM_st {
+ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */
+ASN1_INTEGER *iter;
+ASN1_INTEGER *keylength;
+X509_ALGOR *prf;
+} PBKDF2PARAM;
+
+
+/* PKCS#8 private key info structure */
+
+typedef struct pkcs8_priv_key_info_st
+ {
+ int broken; /* Flag for various broken formats */
+#define PKCS8_OK 0
+#define PKCS8_NO_OCTET 1
+#define PKCS8_EMBEDDED_PARAM 2
+#define PKCS8_NS_DB 3
+ ASN1_INTEGER *version;
+ X509_ALGOR *pkeyalg;
+ ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
+ STACK_OF(X509_ATTRIBUTE) *attributes;
+ } PKCS8_PRIV_KEY_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/x509_vfy.h>
+#include <openssl/pkcs7.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SSLEAY_MACROS
+#define X509_verify(a,r) ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg,\
+ a->signature,(char *)a->cert_info,r)
+#define X509_REQ_verify(a,r) ASN1_verify((int (*)())i2d_X509_REQ_INFO, \
+ a->sig_alg,a->signature,(char *)a->req_info,r)
+#define X509_CRL_verify(a,r) ASN1_verify((int (*)())i2d_X509_CRL_INFO, \
+ a->sig_alg, a->signature,(char *)a->crl,r)
+
+#define X509_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_CINF, x->cert_info->signature, \
+ x->sig_alg, x->signature, (char *)x->cert_info,pkey,md)
+#define X509_REQ_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, \
+ x->signature, (char *)x->req_info,pkey,md)
+#define X509_CRL_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_CRL_INFO,x->crl->sig_alg,x->sig_alg, \
+ x->signature, (char *)x->crl,pkey,md)
+#define NETSCAPE_SPKI_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_NETSCAPE_SPKAC, x->sig_algor,NULL, \
+ x->signature, (char *)x->spkac,pkey,md)
+
+#define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
+ (char *(*)())d2i_X509,(char *)x509)
+#define X509_ATTRIBUTE_dup(xa) (X509_ATTRIBUTE *)ASN1_dup(\
+ (int (*)())i2d_X509_ATTRIBUTE, \
+ (char *(*)())d2i_X509_ATTRIBUTE,(char *)xa)
+#define X509_EXTENSION_dup(ex) (X509_EXTENSION *)ASN1_dup( \
+ (int (*)())i2d_X509_EXTENSION, \
+ (char *(*)())d2i_X509_EXTENSION,(char *)ex)
+#define d2i_X509_fp(fp,x509) (X509 *)ASN1_d2i_fp((char *(*)())X509_new, \
+ (char *(*)())d2i_X509, (fp),(unsigned char **)(x509))
+#define i2d_X509_fp(fp,x509) ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509)
+#define d2i_X509_bio(bp,x509) (X509 *)ASN1_d2i_bio((char *(*)())X509_new, \
+ (char *(*)())d2i_X509, (bp),(unsigned char **)(x509))
+#define i2d_X509_bio(bp,x509) ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509)
+
+#define X509_CRL_dup(crl) (X509_CRL *)ASN1_dup((int (*)())i2d_X509_CRL, \
+ (char *(*)())d2i_X509_CRL,(char *)crl)
+#define d2i_X509_CRL_fp(fp,crl) (X509_CRL *)ASN1_d2i_fp((char *(*)()) \
+ X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp),\
+ (unsigned char **)(crl))
+#define i2d_X509_CRL_fp(fp,crl) ASN1_i2d_fp(i2d_X509_CRL,fp,\
+ (unsigned char *)crl)
+#define d2i_X509_CRL_bio(bp,crl) (X509_CRL *)ASN1_d2i_bio((char *(*)()) \
+ X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp),\
+ (unsigned char **)(crl))
+#define i2d_X509_CRL_bio(bp,crl) ASN1_i2d_bio(i2d_X509_CRL,bp,\
+ (unsigned char *)crl)
+
+#define PKCS7_dup(p7) (PKCS7 *)ASN1_dup((int (*)())i2d_PKCS7, \
+ (char *(*)())d2i_PKCS7,(char *)p7)
+#define d2i_PKCS7_fp(fp,p7) (PKCS7 *)ASN1_d2i_fp((char *(*)()) \
+ PKCS7_new,(char *(*)())d2i_PKCS7, (fp),\
+ (unsigned char **)(p7))
+#define i2d_PKCS7_fp(fp,p7) ASN1_i2d_fp(i2d_PKCS7,fp,\
+ (unsigned char *)p7)
+#define d2i_PKCS7_bio(bp,p7) (PKCS7 *)ASN1_d2i_bio((char *(*)()) \
+ PKCS7_new,(char *(*)())d2i_PKCS7, (bp),\
+ (unsigned char **)(p7))
+#define i2d_PKCS7_bio(bp,p7) ASN1_i2d_bio(i2d_PKCS7,bp,\
+ (unsigned char *)p7)
+
+#define X509_REQ_dup(req) (X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, \
+ (char *(*)())d2i_X509_REQ,(char *)req)
+#define d2i_X509_REQ_fp(fp,req) (X509_REQ *)ASN1_d2i_fp((char *(*)())\
+ X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp),\
+ (unsigned char **)(req))
+#define i2d_X509_REQ_fp(fp,req) ASN1_i2d_fp(i2d_X509_REQ,fp,\
+ (unsigned char *)req)
+#define d2i_X509_REQ_bio(bp,req) (X509_REQ *)ASN1_d2i_bio((char *(*)())\
+ X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp),\
+ (unsigned char **)(req))
+#define i2d_X509_REQ_bio(bp,req) ASN1_i2d_bio(i2d_X509_REQ,bp,\
+ (unsigned char *)req)
+
+#define RSAPublicKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPublicKey, \
+ (char *(*)())d2i_RSAPublicKey,(char *)rsa)
+#define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey, \
+ (char *(*)())d2i_RSAPrivateKey,(char *)rsa)
+
+#define d2i_RSAPrivateKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPrivateKey,fp, \
+ (unsigned char *)rsa)
+#define d2i_RSAPrivateKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPrivateKey,bp, \
+ (unsigned char *)rsa)
+
+#define d2i_RSAPublicKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPublicKey, (fp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPublicKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPublicKey,fp, \
+ (unsigned char *)rsa)
+#define d2i_RSAPublicKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPublicKey, (bp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPublicKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPublicKey,bp, \
+ (unsigned char *)rsa)
+
+#define d2i_DSAPrivateKey_fp(fp,dsa) (DSA *)ASN1_d2i_fp((char *(*)())\
+ DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), \
+ (unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_fp(fp,dsa) ASN1_i2d_fp(i2d_DSAPrivateKey,fp, \
+ (unsigned char *)dsa)
+#define d2i_DSAPrivateKey_bio(bp,dsa) (DSA *)ASN1_d2i_bio((char *(*)())\
+ DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), \
+ (unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_bio(bp,dsa) ASN1_i2d_bio(i2d_DSAPrivateKey,bp, \
+ (unsigned char *)dsa)
+
+#define d2i_ECPrivateKey_fp(fp,ecdsa) (EC_KEY *)ASN1_d2i_fp((char *(*)())\
+ EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (fp), \
+ (unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_fp(fp,ecdsa) ASN1_i2d_fp(i2d_ECPrivateKey,fp, \
+ (unsigned char *)ecdsa)
+#define d2i_ECPrivateKey_bio(bp,ecdsa) (EC_KEY *)ASN1_d2i_bio((char *(*)())\
+ EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (bp), \
+ (unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_bio(bp,ecdsa) ASN1_i2d_bio(i2d_ECPrivateKey,bp, \
+ (unsigned char *)ecdsa)
+
+#define X509_ALGOR_dup(xn) (X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,\
+ (char *(*)())d2i_X509_ALGOR,(char *)xn)
+
+#define X509_NAME_dup(xn) (X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, \
+ (char *(*)())d2i_X509_NAME,(char *)xn)
+#define X509_NAME_ENTRY_dup(ne) (X509_NAME_ENTRY *)ASN1_dup( \
+ (int (*)())i2d_X509_NAME_ENTRY, \
+ (char *(*)())d2i_X509_NAME_ENTRY,\
+ (char *)ne)
+
+#define X509_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len)
+#define X509_NAME_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len)
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+ (char *)data,md,len)
+#endif
+#endif
+
+#define X509_EXT_PACK_UNKNOWN 1
+#define X509_EXT_PACK_STRING 2
+
+#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version)
+/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */
+#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+#define X509_extract_key(x) X509_get_pubkey(x) /*****/
+#define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version)
+#define X509_REQ_get_subject_name(x) ((x)->req_info->subject)
+#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a)
+#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b))
+#define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm))
+
+#define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version)
+#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate)
+#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate)
+#define X509_CRL_get_issuer(x) ((x)->crl->issuer)
+#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked)
+
+/* This one is only used so that a binary form can output, as in
+ * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */
+#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key)
+
+
+const char *X509_verify_cert_error_string(long n);
+
+#ifndef SSLEAY_MACROS
+#ifndef OPENSSL_NO_EVP
+int X509_verify(X509 *a, EVP_PKEY *r);
+
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
+
+NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len);
+char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
+int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
+
+int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+
+int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
+
+int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509 *d2i_X509_fp(FILE *fp, X509 **x509);
+int i2d_X509_fp(FILE *fp,X509 *x509);
+X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl);
+int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req);
+int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa);
+int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
+int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
+int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
+int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
+int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8);
+int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
+int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+X509 *d2i_X509_bio(BIO *bp,X509 **x509);
+int i2d_X509_bio(BIO *bp,X509 *x509);
+X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl);
+int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req);
+int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa);
+int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
+int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
+int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
+int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
+int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8);
+int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
+int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
+#endif
+
+X509 *X509_dup(X509 *x509);
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
+X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
+X509_CRL *X509_CRL_dup(X509_CRL *crl);
+X509_REQ *X509_REQ_dup(X509_REQ *req);
+X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+ X509_ALGOR *algor);
+
+X509_NAME *X509_NAME_dup(X509_NAME *xn);
+X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+
+#endif /* !SSLEAY_MACROS */
+
+int X509_cmp_time(ASN1_TIME *s, time_t *t);
+int X509_cmp_current_time(ASN1_TIME *s);
+ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+const char * X509_get_default_cert_area(void );
+const char * X509_get_default_cert_dir(void );
+const char * X509_get_default_cert_file(void );
+const char * X509_get_default_cert_dir_env(void );
+const char * X509_get_default_cert_file_env(void );
+const char * X509_get_default_private_dir(void );
+
+X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
+
+DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+DECLARE_ASN1_FUNCTIONS(X509_VAL)
+
+DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+
+int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key);
+int X509_get_pubkey_parameters(EVP_PKEY *pkey,
+ STACK_OF(X509) *chain);
+int i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp);
+EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp,
+ long length);
+#ifndef OPENSSL_NO_RSA
+int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp);
+RSA * d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp,
+ long length);
+#endif
+#ifndef OPENSSL_NO_DSA
+int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp);
+DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp,
+ long length);
+#endif
+#ifndef OPENSSL_NO_EC
+int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp);
+EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp,
+ long length);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(X509_SIG)
+DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_REQ)
+
+DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
+
+DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME)
+
+int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+
+DECLARE_ASN1_FUNCTIONS(X509)
+DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int X509_set_ex_data(X509 *r, int idx, void *arg);
+void *X509_get_ex_data(X509 *r, int idx);
+int i2d_X509_AUX(X509 *a,unsigned char **pp);
+X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
+
+int X509_alias_set1(X509 *x, unsigned char *name, int len);
+int X509_keyid_set1(X509 *x, unsigned char *id, int len);
+unsigned char * X509_alias_get0(X509 *x, int *len);
+unsigned char * X509_keyid_get0(X509 *x, int *len);
+int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
+int X509_TRUST_set(int *t, int trust);
+int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
+int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
+void X509_trust_clear(X509 *x);
+void X509_reject_clear(X509 *x);
+
+DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_CRL)
+
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+
+X509_PKEY * X509_PKEY_new(void );
+void X509_PKEY_free(X509_PKEY *a);
+int i2d_X509_PKEY(X509_PKEY *a,unsigned char **pp);
+X509_PKEY * d2i_X509_PKEY(X509_PKEY **a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
+
+#ifndef OPENSSL_NO_EVP
+X509_INFO * X509_INFO_new(void);
+void X509_INFO_free(X509_INFO *a);
+char * X509_NAME_oneline(X509_NAME *a,char *buf,int size);
+
+int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature,char *data,EVP_PKEY *pkey);
+
+int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data,
+ unsigned char *md,unsigned int *len);
+
+int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ char *data,EVP_PKEY *pkey, const EVP_MD *type);
+
+int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+ unsigned char *md,unsigned int *len);
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature,
+ void *data, EVP_PKEY *pkey, const EVP_MD *type);
+#endif
+
+int X509_set_version(X509 *x,long version);
+int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+ASN1_INTEGER * X509_get_serialNumber(X509 *x);
+int X509_set_issuer_name(X509 *x, X509_NAME *name);
+X509_NAME * X509_get_issuer_name(X509 *a);
+int X509_set_subject_name(X509 *x, X509_NAME *name);
+X509_NAME * X509_get_subject_name(X509 *a);
+int X509_set_notBefore(X509 *x, ASN1_TIME *tm);
+int X509_set_notAfter(X509 *x, ASN1_TIME *tm);
+int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
+EVP_PKEY * X509_get_pubkey(X509 *x);
+ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
+int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
+
+int X509_REQ_set_version(X509_REQ *x,long version);
+int X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name);
+int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
+EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req);
+int X509_REQ_extension_nid(int nid);
+int * X509_REQ_get_extension_nids(void);
+void X509_REQ_set_extension_nids(int *nids);
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
+ int nid);
+int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
+int X509_REQ_get_attr_count(const X509_REQ *req);
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+ int lastpos);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+int X509_CRL_set_version(X509_CRL *x, long version);
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+int X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_sort(X509_CRL *crl);
+
+int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
+int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+
+int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
+
+int X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
+
+int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_and_serial_hash(X509 *a);
+
+int X509_issuer_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_name_hash(X509 *a);
+
+int X509_subject_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_subject_name_hash(X509 *x);
+
+int X509_cmp(const X509 *a, const X509 *b);
+int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
+unsigned long X509_NAME_hash(X509_NAME *x);
+
+int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
+#ifndef OPENSSL_NO_FP_API
+int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int X509_print_fp(FILE *bp,X509 *x);
+int X509_CRL_print_fp(FILE *bp,X509_CRL *x);
+int X509_REQ_print_fp(FILE *bp,X509_REQ *req);
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int X509_NAME_print(BIO *bp, X509_NAME *name, int obase);
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags);
+int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int X509_print(BIO *bp,X509 *x);
+int X509_ocspid_print(BIO *bp,X509 *x);
+int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent);
+int X509_CRL_print(BIO *bp,X509_CRL *x);
+int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag);
+int X509_REQ_print(BIO *bp,X509_REQ *req);
+#endif
+
+int X509_NAME_entry_count(X509_NAME *name);
+int X509_NAME_get_text_by_NID(X509_NAME *name, int nid,
+ char *buf,int len);
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
+ char *buf,int len);
+
+/* NOTE: you should be passsing -1, not 0 as lastpos. The functions that use
+ * lastpos, search after that position on. */
+int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos);
+int X509_NAME_get_index_by_OBJ(X509_NAME *name,ASN1_OBJECT *obj,
+ int lastpos);
+X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
+X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
+int X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
+ int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+ unsigned char *bytes, int len, int loc, int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+ const char *field, int type, const unsigned char *bytes, int len);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type,unsigned char *bytes, int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
+ const unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
+ ASN1_OBJECT *obj, int type,const unsigned char *bytes,
+ int len);
+int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne,
+ ASN1_OBJECT *obj);
+int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+ const unsigned char *bytes, int len);
+ASN1_OBJECT * X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne);
+ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne);
+
+int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
+int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
+ int nid, int lastpos);
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
+ ASN1_OBJECT *obj,int lastpos);
+int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
+ int crit, int lastpos);
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
+STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+ X509_EXTENSION *ex, int loc);
+
+int X509_get_ext_count(X509 *x);
+int X509_get_ext_by_NID(X509 *x, int nid, int lastpos);
+int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos);
+int X509_get_ext_by_critical(X509 *x, int crit, int lastpos);
+X509_EXTENSION *X509_get_ext(X509 *x, int loc);
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx);
+int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_CRL_get_ext_count(X509_CRL *x);
+int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos);
+int X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos);
+int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos);
+X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc);
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
+int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
+void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx);
+int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_REVOKED_get_ext_count(X509_REVOKED *x);
+int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos);
+int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos);
+int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos);
+X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc);
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
+int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
+void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx);
+int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+ int nid, int crit, ASN1_OCTET_STRING *data);
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+ ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data);
+int X509_EXTENSION_set_object(X509_EXTENSION *ex,ASN1_OBJECT *obj);
+int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
+int X509_EXTENSION_set_data(X509_EXTENSION *ex,
+ ASN1_OCTET_STRING *data);
+ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex);
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
+int X509_EXTENSION_get_critical(X509_EXTENSION *ex);
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos);
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+ ASN1_OBJECT *obj, int lastpos, int type);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+ const ASN1_OBJECT *obj, int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+ const char *atrname, int type, const unsigned char *bytes, int len);
+int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+ int atrtype, void *data);
+int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr);
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
+
+int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
+int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
+ int lastpos);
+int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
+X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
+int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
+int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+int X509_verify_cert(X509_STORE_CTX *ctx);
+
+/* lookup a cert from a X509 STACK */
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name,
+ ASN1_INTEGER *serial);
+X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen);
+
+/* PKCS#8 utilities */
+
+DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
+PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
+
+int X509_check_trust(X509 *x, int id, int flags);
+int X509_TRUST_get_count(void);
+X509_TRUST * X509_TRUST_get0(int idx);
+int X509_TRUST_get_by_id(int id);
+int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+ char *name, int arg1, void *arg2);
+void X509_TRUST_cleanup(void);
+int X509_TRUST_get_flags(X509_TRUST *xp);
+char *X509_TRUST_get0_name(X509_TRUST *xp);
+int X509_TRUST_get_trust(X509_TRUST *xp);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509_strings(void);
+
+/* Error codes for the X509 functions. */
+
+/* Function codes. */
+#define X509_F_ADD_CERT_DIR 100
+#define X509_F_BY_FILE_CTRL 101
+#define X509_F_CHECK_POLICY 145
+#define X509_F_DIR_CTRL 102
+#define X509_F_GET_CERT_BY_SUBJECT 103
+#define X509_F_NETSCAPE_SPKI_B64_DECODE 129
+#define X509_F_NETSCAPE_SPKI_B64_ENCODE 130
+#define X509_F_X509AT_ADD1_ATTR 135
+#define X509_F_X509V3_ADD_EXT 104
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140
+#define X509_F_X509_ATTRIBUTE_GET0_DATA 139
+#define X509_F_X509_ATTRIBUTE_SET1_DATA 138
+#define X509_F_X509_CHECK_PRIVATE_KEY 128
+#define X509_F_X509_CRL_PRINT_FP 147
+#define X509_F_X509_EXTENSION_CREATE_BY_NID 108
+#define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109
+#define X509_F_X509_GET_PUBKEY_PARAMETERS 110
+#define X509_F_X509_LOAD_CERT_CRL_FILE 132
+#define X509_F_X509_LOAD_CERT_FILE 111
+#define X509_F_X509_LOAD_CRL_FILE 112
+#define X509_F_X509_NAME_ADD_ENTRY 113
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131
+#define X509_F_X509_NAME_ENTRY_SET_OBJECT 115
+#define X509_F_X509_NAME_ONELINE 116
+#define X509_F_X509_NAME_PRINT 117
+#define X509_F_X509_PRINT_EX_FP 118
+#define X509_F_X509_PUBKEY_GET 119
+#define X509_F_X509_PUBKEY_SET 120
+#define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144
+#define X509_F_X509_REQ_PRINT_EX 121
+#define X509_F_X509_REQ_PRINT_FP 122
+#define X509_F_X509_REQ_TO_X509 123
+#define X509_F_X509_STORE_ADD_CERT 124
+#define X509_F_X509_STORE_ADD_CRL 125
+#define X509_F_X509_STORE_CTX_GET1_ISSUER 146
+#define X509_F_X509_STORE_CTX_INIT 143
+#define X509_F_X509_STORE_CTX_NEW 142
+#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134
+#define X509_F_X509_TO_X509_REQ 126
+#define X509_F_X509_TRUST_ADD 133
+#define X509_F_X509_TRUST_SET 141
+#define X509_F_X509_VERIFY_CERT 127
+
+/* Reason codes. */
+#define X509_R_BAD_X509_FILETYPE 100
+#define X509_R_BASE64_DECODE_ERROR 118
+#define X509_R_CANT_CHECK_DH_KEY 114
+#define X509_R_CERT_ALREADY_IN_HASH_TABLE 101
+#define X509_R_ERR_ASN1_LIB 102
+#define X509_R_INVALID_DIRECTORY 113
+#define X509_R_INVALID_FIELD_NAME 119
+#define X509_R_INVALID_TRUST 123
+#define X509_R_KEY_TYPE_MISMATCH 115
+#define X509_R_KEY_VALUES_MISMATCH 116
+#define X509_R_LOADING_CERT_DIR 103
+#define X509_R_LOADING_DEFAULTS 104
+#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105
+#define X509_R_SHOULD_RETRY 106
+#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107
+#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108
+#define X509_R_UNKNOWN_KEY_TYPE 117
+#define X509_R_UNKNOWN_NID 109
+#define X509_R_UNKNOWN_PURPOSE_ID 121
+#define X509_R_UNKNOWN_TRUST_ID 120
+#define X509_R_UNSUPPORTED_ALGORITHM 111
+#define X509_R_WRONG_LOOKUP_TYPE 112
+#define X509_R_WRONG_TYPE 122
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/x509_vfy.h b/src/Mayaqua/win32_inc/openssl/x509_vfy.h
new file mode 100644
index 00000000..921dd0aa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509_vfy.h
@@ -0,0 +1,534 @@
+/* crypto/x509/x509_vfy.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_X509_H
+#include <openssl/x509.h>
+/* openssl/x509.h ends up #include-ing this file at about the only
+ * appropriate moment. */
+#endif
+
+#ifndef HEADER_X509_VFY_H
+#define HEADER_X509_VFY_H
+
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_LHASH
+#include <openssl/lhash.h>
+#endif
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Outer object */
+typedef struct x509_hash_dir_st
+ {
+ int num_dirs;
+ char **dirs;
+ int *dirs_type;
+ int num_dirs_alloced;
+ } X509_HASH_DIR_CTX;
+
+typedef struct x509_file_st
+ {
+ int num_paths; /* number of paths to files or directories */
+ int num_alloced;
+ char **paths; /* the list of paths or directories */
+ int *path_type;
+ } X509_CERT_FILE_CTX;
+
+/*******************************/
+/*
+SSL_CTX -> X509_STORE
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+
+SSL -> X509_STORE_CTX
+ ->X509_STORE
+
+The X509_STORE holds the tables etc for verification stuff.
+A X509_STORE_CTX is used while validating a single certificate.
+The X509_STORE has X509_LOOKUPs for looking up certs.
+The X509_STORE then calls a function to actually verify the
+certificate chain.
+*/
+
+#define X509_LU_RETRY -1
+#define X509_LU_FAIL 0
+#define X509_LU_X509 1
+#define X509_LU_CRL 2
+#define X509_LU_PKEY 3
+
+typedef struct x509_object_st
+ {
+ /* one of the above types */
+ int type;
+ union {
+ char *ptr;
+ X509 *x509;
+ X509_CRL *crl;
+ EVP_PKEY *pkey;
+ } data;
+ } X509_OBJECT;
+
+typedef struct x509_lookup_st X509_LOOKUP;
+
+DECLARE_STACK_OF(X509_LOOKUP)
+DECLARE_STACK_OF(X509_OBJECT)
+
+/* This is a static that defines the function interface */
+typedef struct x509_lookup_method_st
+ {
+ const char *name;
+ int (*new_item)(X509_LOOKUP *ctx);
+ void (*free)(X509_LOOKUP *ctx);
+ int (*init)(X509_LOOKUP *ctx);
+ int (*shutdown)(X509_LOOKUP *ctx);
+ int (*ctrl)(X509_LOOKUP *ctx,int cmd,const char *argc,long argl,
+ char **ret);
+ int (*get_by_subject)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+ int (*get_by_issuer_serial)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+ ASN1_INTEGER *serial,X509_OBJECT *ret);
+ int (*get_by_fingerprint)(X509_LOOKUP *ctx,int type,
+ unsigned char *bytes,int len,
+ X509_OBJECT *ret);
+ int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len,
+ X509_OBJECT *ret);
+ } X509_LOOKUP_METHOD;
+
+/* This structure hold all parameters associated with a verify operation
+ * by including an X509_VERIFY_PARAM structure in related structures the
+ * parameters used can be customized
+ */
+
+typedef struct X509_VERIFY_PARAM_st
+ {
+ char *name;
+ time_t check_time; /* Time to use */
+ unsigned long inh_flags; /* Inheritance flags */
+ unsigned long flags; /* Various verify flags */
+ int purpose; /* purpose to check untrusted certificates */
+ int trust; /* trust setting to check */
+ int depth; /* Verify depth */
+ STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */
+ } X509_VERIFY_PARAM;
+
+DECLARE_STACK_OF(X509_VERIFY_PARAM)
+
+/* This is used to hold everything. It is used for all certificate
+ * validation. Once we have a certificate chain, the 'verify'
+ * function is then called to actually check the cert chain. */
+struct x509_store_st
+ {
+ /* The following is a cache of trusted certs */
+ int cache; /* if true, stash any hits */
+ STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */
+
+ /* These are external lookup methods */
+ STACK_OF(X509_LOOKUP) *get_cert_methods;
+
+ X509_VERIFY_PARAM *param;
+
+ /* Callbacks for various operations */
+ int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */
+ int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */
+ int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */
+ int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+ int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+ int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+ int (*cleanup)(X509_STORE_CTX *ctx);
+
+ CRYPTO_EX_DATA ex_data;
+ int references;
+ } /* X509_STORE */;
+
+int X509_STORE_set_depth(X509_STORE *store, int depth);
+
+#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func))
+#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func))
+
+/* This is the functions plus an instance of the local variables. */
+struct x509_lookup_st
+ {
+ int init; /* have we been started */
+ int skip; /* don't use us. */
+ X509_LOOKUP_METHOD *method; /* the functions */
+ char *method_data; /* method data */
+
+ X509_STORE *store_ctx; /* who owns us */
+ } /* X509_LOOKUP */;
+
+/* This is a used when verifying cert chains. Since the
+ * gathering of the cert chain can take some time (and have to be
+ * 'retried', this needs to be kept and passed around. */
+struct x509_store_ctx_st /* X509_STORE_CTX */
+ {
+ X509_STORE *ctx;
+ int current_method; /* used when looking up certs */
+
+ /* The following are set by the caller */
+ X509 *cert; /* The cert to check */
+ STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */
+ STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */
+
+ X509_VERIFY_PARAM *param;
+ void *other_ctx; /* Other info for use with get_issuer() */
+
+ /* Callbacks for various operations */
+ int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */
+ int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */
+ int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */
+ int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+ int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+ int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+ int (*check_policy)(X509_STORE_CTX *ctx);
+ int (*cleanup)(X509_STORE_CTX *ctx);
+
+ /* The following is built up */
+ int valid; /* if 0, rebuild chain */
+ int last_untrusted; /* index of last untrusted cert */
+ STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */
+ X509_POLICY_TREE *tree; /* Valid policy tree */
+
+ int explicit_policy; /* Require explicit policy value */
+
+ /* When something goes wrong, this is why */
+ int error_depth;
+ int error;
+ X509 *current_cert;
+ X509 *current_issuer; /* cert currently being tested as valid issuer */
+ X509_CRL *current_crl; /* current CRL */
+
+ CRYPTO_EX_DATA ex_data;
+ } /* X509_STORE_CTX */;
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
+
+#define X509_STORE_CTX_set_app_data(ctx,data) \
+ X509_STORE_CTX_set_ex_data(ctx,0,data)
+#define X509_STORE_CTX_get_app_data(ctx) \
+ X509_STORE_CTX_get_ex_data(ctx,0)
+
+#define X509_L_FILE_LOAD 1
+#define X509_L_ADD_DIR 2
+
+#define X509_LOOKUP_load_file(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
+
+#define X509_LOOKUP_add_dir(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
+
+#define X509_V_OK 0
+/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+
+#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
+#define X509_V_ERR_UNABLE_TO_GET_CRL 3
+#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4
+#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5
+#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
+#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
+#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
+#define X509_V_ERR_CERT_NOT_YET_VALID 9
+#define X509_V_ERR_CERT_HAS_EXPIRED 10
+#define X509_V_ERR_CRL_NOT_YET_VALID 11
+#define X509_V_ERR_CRL_HAS_EXPIRED 12
+#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13
+#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14
+#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15
+#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16
+#define X509_V_ERR_OUT_OF_MEM 17
+#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18
+#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19
+#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20
+#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
+#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
+#define X509_V_ERR_CERT_REVOKED 23
+#define X509_V_ERR_INVALID_CA 24
+#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
+#define X509_V_ERR_INVALID_PURPOSE 26
+#define X509_V_ERR_CERT_UNTRUSTED 27
+#define X509_V_ERR_CERT_REJECTED 28
+/* These are 'informational' when looking for issuer cert */
+#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29
+#define X509_V_ERR_AKID_SKID_MISMATCH 30
+#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31
+#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
+
+#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
+#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
+#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
+#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
+#define X509_V_ERR_INVALID_NON_CA 37
+#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
+#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
+#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
+
+#define X509_V_ERR_INVALID_EXTENSION 41
+#define X509_V_ERR_INVALID_POLICY_EXTENSION 42
+#define X509_V_ERR_NO_EXPLICIT_POLICY 43
+
+#define X509_V_ERR_UNNESTED_RESOURCE 44
+
+/* The application is not happy */
+#define X509_V_ERR_APPLICATION_VERIFICATION 50
+
+/* Certificate verify flags */
+
+/* Send issuer+subject checks to verify_cb */
+#define X509_V_FLAG_CB_ISSUER_CHECK 0x1
+/* Use check time instead of current time */
+#define X509_V_FLAG_USE_CHECK_TIME 0x2
+/* Lookup CRLs */
+#define X509_V_FLAG_CRL_CHECK 0x4
+/* Lookup CRLs for whole chain */
+#define X509_V_FLAG_CRL_CHECK_ALL 0x8
+/* Ignore unhandled critical extensions */
+#define X509_V_FLAG_IGNORE_CRITICAL 0x10
+/* Disable workarounds for broken certificates */
+#define X509_V_FLAG_X509_STRICT 0x20
+/* Enable proxy certificate validation */
+#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
+/* Enable policy checking */
+#define X509_V_FLAG_POLICY_CHECK 0x80
+/* Policy variable require-explicit-policy */
+#define X509_V_FLAG_EXPLICIT_POLICY 0x100
+/* Policy variable inhibit-any-policy */
+#define X509_V_FLAG_INHIBIT_ANY 0x200
+/* Policy variable inhibit-policy-mapping */
+#define X509_V_FLAG_INHIBIT_MAP 0x400
+/* Notify callback that policy is OK */
+#define X509_V_FLAG_NOTIFY_POLICY 0x800
+
+/* Check selfsigned CA signature */
+#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
+
+#define X509_VP_FLAG_DEFAULT 0x1
+#define X509_VP_FLAG_OVERWRITE 0x2
+#define X509_VP_FLAG_RESET_FLAGS 0x4
+#define X509_VP_FLAG_LOCKED 0x8
+#define X509_VP_FLAG_ONCE 0x10
+
+/* Internal use: mask of policy related options */
+#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
+ | X509_V_FLAG_EXPLICIT_POLICY \
+ | X509_V_FLAG_INHIBIT_ANY \
+ | X509_V_FLAG_INHIBIT_MAP)
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
+void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+void X509_OBJECT_free_contents(X509_OBJECT *a);
+X509_STORE *X509_STORE_new(void );
+void X509_STORE_free(X509_STORE *v);
+
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
+int X509_STORE_set_trust(X509_STORE *ctx, int trust);
+int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+
+X509_STORE_CTX *X509_STORE_CTX_new(void);
+
+int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
+ X509 *x509, STACK_OF(X509) *chain);
+void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
+
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
+
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+
+#ifndef OPENSSL_NO_STDIO
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+#endif
+
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
+void X509_LOOKUP_free(X509_LOOKUP *ctx);
+int X509_LOOKUP_init(X509_LOOKUP *ctx);
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ X509_OBJECT *ret);
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ ASN1_INTEGER *serial, X509_OBJECT *ret);
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+ unsigned char *bytes, int len, X509_OBJECT *ret);
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str,
+ int len, X509_OBJECT *ret);
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
+
+#ifndef OPENSSL_NO_STDIO
+int X509_STORE_load_locations (X509_STORE *ctx,
+ const char *file, const char *dir);
+int X509_STORE_set_default_paths(X509_STORE *ctx);
+#endif
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data);
+void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
+int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
+void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+ int purpose, int trust);
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+ time_t t);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *));
+
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx);
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
+int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
+
+/* X509_VERIFY_PARAM functions */
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags);
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags);
+unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
+void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+ ASN1_OBJECT *policy);
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies);
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
+
+int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
+void X509_VERIFY_PARAM_table_cleanup(void);
+
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ unsigned int flags);
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree);
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
+X509_POLICY_LEVEL *
+ X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i);
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
+
+X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i);
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
+
+STACK_OF(POLICYQUALINFO) *
+ X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
+const X509_POLICY_NODE *
+ X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/x509v3.h b/src/Mayaqua/win32_inc/openssl/x509v3.h
new file mode 100644
index 00000000..c34bd6dc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509v3.h
@@ -0,0 +1,922 @@
+/* x509v3.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_X509V3_H
+#define HEADER_X509V3_H
+
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/conf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward reference */
+struct v3_ext_method;
+struct v3_ext_ctx;
+
+/* Useful typedefs */
+
+typedef void * (*X509V3_EXT_NEW)(void);
+typedef void (*X509V3_EXT_FREE)(void *);
+typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long);
+typedef int (*X509V3_EXT_I2D)(void *, unsigned char **);
+typedef STACK_OF(CONF_VALUE) * (*X509V3_EXT_I2V)(struct v3_ext_method *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
+typedef void * (*X509V3_EXT_V2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, STACK_OF(CONF_VALUE) *values);
+typedef char * (*X509V3_EXT_I2S)(struct v3_ext_method *method, void *ext);
+typedef void * (*X509V3_EXT_S2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R)(struct v3_ext_method *method, void *ext, BIO *out, int indent);
+typedef void * (*X509V3_EXT_R2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+
+/* V3 extension structure */
+
+struct v3_ext_method {
+int ext_nid;
+int ext_flags;
+/* If this is set the following four fields are ignored */
+ASN1_ITEM_EXP *it;
+/* Old style ASN1 calls */
+X509V3_EXT_NEW ext_new;
+X509V3_EXT_FREE ext_free;
+X509V3_EXT_D2I d2i;
+X509V3_EXT_I2D i2d;
+
+/* The following pair is used for string extensions */
+X509V3_EXT_I2S i2s;
+X509V3_EXT_S2I s2i;
+
+/* The following pair is used for multi-valued extensions */
+X509V3_EXT_I2V i2v;
+X509V3_EXT_V2I v2i;
+
+/* The following are used for raw extensions */
+X509V3_EXT_I2R i2r;
+X509V3_EXT_R2I r2i;
+
+void *usr_data; /* Any extension specific data */
+};
+
+typedef struct X509V3_CONF_METHOD_st {
+char * (*get_string)(void *db, char *section, char *value);
+STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section);
+void (*free_string)(void *db, char * string);
+void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section);
+} X509V3_CONF_METHOD;
+
+/* Context specific info */
+struct v3_ext_ctx {
+#define CTX_TEST 0x1
+int flags;
+X509 *issuer_cert;
+X509 *subject_cert;
+X509_REQ *subject_req;
+X509_CRL *crl;
+X509V3_CONF_METHOD *db_meth;
+void *db;
+/* Maybe more here */
+};
+
+typedef struct v3_ext_method X509V3_EXT_METHOD;
+
+DECLARE_STACK_OF(X509V3_EXT_METHOD)
+
+/* ext_flags values */
+#define X509V3_EXT_DYNAMIC 0x1
+#define X509V3_EXT_CTX_DEP 0x2
+#define X509V3_EXT_MULTILINE 0x4
+
+typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
+
+typedef struct BASIC_CONSTRAINTS_st {
+int ca;
+ASN1_INTEGER *pathlen;
+} BASIC_CONSTRAINTS;
+
+
+typedef struct PKEY_USAGE_PERIOD_st {
+ASN1_GENERALIZEDTIME *notBefore;
+ASN1_GENERALIZEDTIME *notAfter;
+} PKEY_USAGE_PERIOD;
+
+typedef struct otherName_st {
+ASN1_OBJECT *type_id;
+ASN1_TYPE *value;
+} OTHERNAME;
+
+typedef struct EDIPartyName_st {
+ ASN1_STRING *nameAssigner;
+ ASN1_STRING *partyName;
+} EDIPARTYNAME;
+
+typedef struct GENERAL_NAME_st {
+
+#define GEN_OTHERNAME 0
+#define GEN_EMAIL 1
+#define GEN_DNS 2
+#define GEN_X400 3
+#define GEN_DIRNAME 4
+#define GEN_EDIPARTY 5
+#define GEN_URI 6
+#define GEN_IPADD 7
+#define GEN_RID 8
+
+int type;
+union {
+ char *ptr;
+ OTHERNAME *otherName; /* otherName */
+ ASN1_IA5STRING *rfc822Name;
+ ASN1_IA5STRING *dNSName;
+ ASN1_TYPE *x400Address;
+ X509_NAME *directoryName;
+ EDIPARTYNAME *ediPartyName;
+ ASN1_IA5STRING *uniformResourceIdentifier;
+ ASN1_OCTET_STRING *iPAddress;
+ ASN1_OBJECT *registeredID;
+
+ /* Old names */
+ ASN1_OCTET_STRING *ip; /* iPAddress */
+ X509_NAME *dirn; /* dirn */
+ ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */
+ ASN1_OBJECT *rid; /* registeredID */
+ ASN1_TYPE *other; /* x400Address */
+} d;
+} GENERAL_NAME;
+
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+
+typedef struct ACCESS_DESCRIPTION_st {
+ ASN1_OBJECT *method;
+ GENERAL_NAME *location;
+} ACCESS_DESCRIPTION;
+
+typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
+
+typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
+
+DECLARE_STACK_OF(GENERAL_NAME)
+DECLARE_ASN1_SET_OF(GENERAL_NAME)
+
+DECLARE_STACK_OF(ACCESS_DESCRIPTION)
+DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION)
+
+typedef struct DIST_POINT_NAME_st {
+int type;
+union {
+ GENERAL_NAMES *fullname;
+ STACK_OF(X509_NAME_ENTRY) *relativename;
+} name;
+} DIST_POINT_NAME;
+
+typedef struct DIST_POINT_st {
+DIST_POINT_NAME *distpoint;
+ASN1_BIT_STRING *reasons;
+GENERAL_NAMES *CRLissuer;
+} DIST_POINT;
+
+typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
+
+DECLARE_STACK_OF(DIST_POINT)
+DECLARE_ASN1_SET_OF(DIST_POINT)
+
+typedef struct AUTHORITY_KEYID_st {
+ASN1_OCTET_STRING *keyid;
+GENERAL_NAMES *issuer;
+ASN1_INTEGER *serial;
+} AUTHORITY_KEYID;
+
+/* Strong extranet structures */
+
+typedef struct SXNET_ID_st {
+ ASN1_INTEGER *zone;
+ ASN1_OCTET_STRING *user;
+} SXNETID;
+
+DECLARE_STACK_OF(SXNETID)
+DECLARE_ASN1_SET_OF(SXNETID)
+
+typedef struct SXNET_st {
+ ASN1_INTEGER *version;
+ STACK_OF(SXNETID) *ids;
+} SXNET;
+
+typedef struct NOTICEREF_st {
+ ASN1_STRING *organization;
+ STACK_OF(ASN1_INTEGER) *noticenos;
+} NOTICEREF;
+
+typedef struct USERNOTICE_st {
+ NOTICEREF *noticeref;
+ ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct POLICYQUALINFO_st {
+ ASN1_OBJECT *pqualid;
+ union {
+ ASN1_IA5STRING *cpsuri;
+ USERNOTICE *usernotice;
+ ASN1_TYPE *other;
+ } d;
+} POLICYQUALINFO;
+
+DECLARE_STACK_OF(POLICYQUALINFO)
+DECLARE_ASN1_SET_OF(POLICYQUALINFO)
+
+typedef struct POLICYINFO_st {
+ ASN1_OBJECT *policyid;
+ STACK_OF(POLICYQUALINFO) *qualifiers;
+} POLICYINFO;
+
+typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
+
+DECLARE_STACK_OF(POLICYINFO)
+DECLARE_ASN1_SET_OF(POLICYINFO)
+
+typedef struct POLICY_MAPPING_st {
+ ASN1_OBJECT *issuerDomainPolicy;
+ ASN1_OBJECT *subjectDomainPolicy;
+} POLICY_MAPPING;
+
+DECLARE_STACK_OF(POLICY_MAPPING)
+
+typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
+
+typedef struct GENERAL_SUBTREE_st {
+ GENERAL_NAME *base;
+ ASN1_INTEGER *minimum;
+ ASN1_INTEGER *maximum;
+} GENERAL_SUBTREE;
+
+DECLARE_STACK_OF(GENERAL_SUBTREE)
+
+typedef struct NAME_CONSTRAINTS_st {
+ STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
+ STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
+} NAME_CONSTRAINTS;
+
+typedef struct POLICY_CONSTRAINTS_st {
+ ASN1_INTEGER *requireExplicitPolicy;
+ ASN1_INTEGER *inhibitPolicyMapping;
+} POLICY_CONSTRAINTS;
+
+/* Proxy certificate structures, see RFC 3820 */
+typedef struct PROXY_POLICY_st
+ {
+ ASN1_OBJECT *policyLanguage;
+ ASN1_OCTET_STRING *policy;
+ } PROXY_POLICY;
+
+typedef struct PROXY_CERT_INFO_EXTENSION_st
+ {
+ ASN1_INTEGER *pcPathLengthConstraint;
+ PROXY_POLICY *proxyPolicy;
+ } PROXY_CERT_INFO_EXTENSION;
+
+DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+
+
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
+",name:", val->name, ",value:", val->value);
+
+#define X509V3_set_ctx_test(ctx) \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
+#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
+
+#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
+ 0,0,0,0, \
+ 0,0, \
+ (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
+ (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
+ NULL, NULL, \
+ table}
+
+#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
+ 0,0,0,0, \
+ (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
+ (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
+ 0,0,0,0, \
+ NULL}
+
+#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+
+/* X509_PURPOSE stuff */
+
+#define EXFLAG_BCONS 0x1
+#define EXFLAG_KUSAGE 0x2
+#define EXFLAG_XKUSAGE 0x4
+#define EXFLAG_NSCERT 0x8
+
+#define EXFLAG_CA 0x10
+/* Really self issued not necessarily self signed */
+#define EXFLAG_SI 0x20
+#define EXFLAG_SS 0x20
+#define EXFLAG_V1 0x40
+#define EXFLAG_INVALID 0x80
+#define EXFLAG_SET 0x100
+#define EXFLAG_CRITICAL 0x200
+#define EXFLAG_PROXY 0x400
+
+#define EXFLAG_INVALID_POLICY 0x800
+
+#define KU_DIGITAL_SIGNATURE 0x0080
+#define KU_NON_REPUDIATION 0x0040
+#define KU_KEY_ENCIPHERMENT 0x0020
+#define KU_DATA_ENCIPHERMENT 0x0010
+#define KU_KEY_AGREEMENT 0x0008
+#define KU_KEY_CERT_SIGN 0x0004
+#define KU_CRL_SIGN 0x0002
+#define KU_ENCIPHER_ONLY 0x0001
+#define KU_DECIPHER_ONLY 0x8000
+
+#define NS_SSL_CLIENT 0x80
+#define NS_SSL_SERVER 0x40
+#define NS_SMIME 0x20
+#define NS_OBJSIGN 0x10
+#define NS_SSL_CA 0x04
+#define NS_SMIME_CA 0x02
+#define NS_OBJSIGN_CA 0x01
+#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
+
+#define XKU_SSL_SERVER 0x1
+#define XKU_SSL_CLIENT 0x2
+#define XKU_SMIME 0x4
+#define XKU_CODE_SIGN 0x8
+#define XKU_SGC 0x10
+#define XKU_OCSP_SIGN 0x20
+#define XKU_TIMESTAMP 0x40
+#define XKU_DVCS 0x80
+
+#define X509_PURPOSE_DYNAMIC 0x1
+#define X509_PURPOSE_DYNAMIC_NAME 0x2
+
+typedef struct x509_purpose_st {
+ int purpose;
+ int trust; /* Default trust ID */
+ int flags;
+ int (*check_purpose)(const struct x509_purpose_st *,
+ const X509 *, int);
+ char *name;
+ char *sname;
+ void *usr_data;
+} X509_PURPOSE;
+
+#define X509_PURPOSE_SSL_CLIENT 1
+#define X509_PURPOSE_SSL_SERVER 2
+#define X509_PURPOSE_NS_SSL_SERVER 3
+#define X509_PURPOSE_SMIME_SIGN 4
+#define X509_PURPOSE_SMIME_ENCRYPT 5
+#define X509_PURPOSE_CRL_SIGN 6
+#define X509_PURPOSE_ANY 7
+#define X509_PURPOSE_OCSP_HELPER 8
+
+#define X509_PURPOSE_MIN 1
+#define X509_PURPOSE_MAX 8
+
+/* Flags for X509V3_EXT_print() */
+
+#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
+/* Return error for unknown extensions */
+#define X509V3_EXT_DEFAULT 0
+/* Print error for unknown extensions */
+#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
+/* ASN1 parse unknown extensions */
+#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
+/* BIO_dump unknown extensions */
+#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+
+/* Flags for X509V3_add1_i2d */
+
+#define X509V3_ADD_OP_MASK 0xfL
+#define X509V3_ADD_DEFAULT 0L
+#define X509V3_ADD_APPEND 1L
+#define X509V3_ADD_REPLACE 2L
+#define X509V3_ADD_REPLACE_EXISTING 3L
+#define X509V3_ADD_KEEP_EXISTING 4L
+#define X509V3_ADD_DELETE 5L
+#define X509V3_ADD_SILENT 0x10
+
+DECLARE_STACK_OF(X509_PURPOSE)
+
+DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+DECLARE_ASN1_FUNCTIONS(SXNET)
+DECLARE_ASN1_FUNCTIONS(SXNETID)
+
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen);
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen);
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen);
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone);
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
+
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
+
+DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
+
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *extlist);
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret);
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist);
+GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+DECLARE_ASN1_FUNCTIONS(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5);
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
+
+DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a);
+
+DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+
+DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+
+DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+DECLARE_ASN1_ITEM(POLICY_MAPPING)
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
+
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
+
+#ifdef HEADER_CONF_H
+GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
+void X509V3_conf_free(CONF_VALUE *val);
+
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
+int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint);
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash);
+#endif
+
+char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section);
+STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section);
+void X509V3_string_free(X509V3_CTX *ctx, char *str);
+void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+ X509_REQ *req, X509_CRL *crl, int flags);
+
+int X509V3_add_value(const char *name, const char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
+ STACK_OF(CONF_VALUE) **extlist);
+char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint);
+ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value);
+char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
+int X509V3_EXT_add_alias(int nid_to, int nid_from);
+void X509V3_EXT_cleanup(void);
+
+X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
+X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
+int X509V3_add_standard_extensions(void);
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
+void *X509V3_EXT_d2i(X509_EXTENSION *ext);
+void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+
+
+X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
+int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags);
+
+char *hex_to_string(unsigned char *buffer, long len);
+unsigned char *string_to_hex(char *str, long *len);
+int name_cmp(const char *name, const char *cmp);
+
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml);
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
+int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+
+int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
+
+int X509_check_ca(X509 *x);
+int X509_check_purpose(X509 *x, int id, int ca);
+int X509_supported_extension(X509_EXTENSION *ex);
+int X509_PURPOSE_set(int *p, int purpose);
+int X509_check_issued(X509 *issuer, X509 *subject);
+int X509_PURPOSE_get_count(void);
+X509_PURPOSE * X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_by_sname(char *sname);
+int X509_PURPOSE_get_by_id(int id);
+int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck)(const X509_PURPOSE *, const X509 *, int),
+ char *name, char *sname, void *arg);
+char *X509_PURPOSE_get0_name(X509_PURPOSE *xp);
+char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp);
+int X509_PURPOSE_get_trust(X509_PURPOSE *xp);
+void X509_PURPOSE_cleanup(void);
+int X509_PURPOSE_get_id(X509_PURPOSE *);
+
+STACK *X509_get1_email(X509 *x);
+STACK *X509_REQ_get1_email(X509_REQ *x);
+void X509_email_free(STACK *sk);
+STACK *X509_get1_ocsp(X509 *x);
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
+int a2i_ipadd(unsigned char *ipout, const char *ipasc);
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+ unsigned long chtype);
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
+
+#ifndef OPENSSL_NO_RFC3779
+
+typedef struct ASRange_st {
+ ASN1_INTEGER *min, *max;
+} ASRange;
+
+#define ASIdOrRange_id 0
+#define ASIdOrRange_range 1
+
+typedef struct ASIdOrRange_st {
+ int type;
+ union {
+ ASN1_INTEGER *id;
+ ASRange *range;
+ } u;
+} ASIdOrRange;
+
+typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
+DECLARE_STACK_OF(ASIdOrRange)
+
+#define ASIdentifierChoice_inherit 0
+#define ASIdentifierChoice_asIdsOrRanges 1
+
+typedef struct ASIdentifierChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ ASIdOrRanges *asIdsOrRanges;
+ } u;
+} ASIdentifierChoice;
+
+typedef struct ASIdentifiers_st {
+ ASIdentifierChoice *asnum, *rdi;
+} ASIdentifiers;
+
+DECLARE_ASN1_FUNCTIONS(ASRange)
+DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
+DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
+DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
+
+
+typedef struct IPAddressRange_st {
+ ASN1_BIT_STRING *min, *max;
+} IPAddressRange;
+
+#define IPAddressOrRange_addressPrefix 0
+#define IPAddressOrRange_addressRange 1
+
+typedef struct IPAddressOrRange_st {
+ int type;
+ union {
+ ASN1_BIT_STRING *addressPrefix;
+ IPAddressRange *addressRange;
+ } u;
+} IPAddressOrRange;
+
+typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
+DECLARE_STACK_OF(IPAddressOrRange)
+
+#define IPAddressChoice_inherit 0
+#define IPAddressChoice_addressesOrRanges 1
+
+typedef struct IPAddressChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ IPAddressOrRanges *addressesOrRanges;
+ } u;
+} IPAddressChoice;
+
+typedef struct IPAddressFamily_st {
+ ASN1_OCTET_STRING *addressFamily;
+ IPAddressChoice *ipAddressChoice;
+} IPAddressFamily;
+
+typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
+DECLARE_STACK_OF(IPAddressFamily)
+
+DECLARE_ASN1_FUNCTIONS(IPAddressRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
+DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
+
+/*
+ * API tag for elements of the ASIdentifer SEQUENCE.
+ */
+#define V3_ASID_ASNUM 0
+#define V3_ASID_RDI 1
+
+/*
+ * AFI values, assigned by IANA. It'd be nice to make the AFI
+ * handling code totally generic, but there are too many little things
+ * that would need to be defined for other address families for it to
+ * be worth the trouble.
+ */
+#define IANA_AFI_IPV4 1
+#define IANA_AFI_IPV6 2
+
+/*
+ * Utilities to construct and extract values from RFC3779 extensions,
+ * since some of the encodings (particularly for IP address prefixes
+ * and ranges) are a bit tedious to work with directly.
+ */
+int v3_asid_add_inherit(ASIdentifiers *asid, int which);
+int v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
+ ASN1_INTEGER *min, ASN1_INTEGER *max);
+int v3_addr_add_inherit(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi);
+int v3_addr_add_prefix(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *a, const int prefixlen);
+int v3_addr_add_range(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *min, unsigned char *max);
+unsigned v3_addr_get_afi(const IPAddressFamily *f);
+int v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
+ unsigned char *min, unsigned char *max,
+ const int length);
+
+/*
+ * Canonical forms.
+ */
+int v3_asid_is_canonical(ASIdentifiers *asid);
+int v3_addr_is_canonical(IPAddrBlocks *addr);
+int v3_asid_canonize(ASIdentifiers *asid);
+int v3_addr_canonize(IPAddrBlocks *addr);
+
+/*
+ * Tests for inheritance and containment.
+ */
+int v3_asid_inherits(ASIdentifiers *asid);
+int v3_addr_inherits(IPAddrBlocks *addr);
+int v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
+int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
+
+/*
+ * Check whether RFC 3779 extensions nest properly in chains.
+ */
+int v3_asid_validate_path(X509_STORE_CTX *);
+int v3_addr_validate_path(X509_STORE_CTX *);
+int v3_asid_validate_resource_set(STACK_OF(X509) *chain,
+ ASIdentifiers *ext,
+ int allow_inheritance);
+int v3_addr_validate_resource_set(STACK_OF(X509) *chain,
+ IPAddrBlocks *ext,
+ int allow_inheritance);
+
+#endif /* OPENSSL_NO_RFC3779 */
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509V3_strings(void);
+
+/* Error codes for the X509V3 functions. */
+
+/* Function codes. */
+#define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 156
+#define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 157
+#define X509V3_F_COPY_EMAIL 122
+#define X509V3_F_COPY_ISSUER 123
+#define X509V3_F_DO_DIRNAME 144
+#define X509V3_F_DO_EXT_CONF 124
+#define X509V3_F_DO_EXT_I2D 135
+#define X509V3_F_DO_EXT_NCONF 151
+#define X509V3_F_DO_I2V_NAME_CONSTRAINTS 148
+#define X509V3_F_HEX_TO_STRING 111
+#define X509V3_F_I2S_ASN1_ENUMERATED 121
+#define X509V3_F_I2S_ASN1_IA5STRING 149
+#define X509V3_F_I2S_ASN1_INTEGER 120
+#define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138
+#define X509V3_F_NOTICE_SECTION 132
+#define X509V3_F_NREF_NOS 133
+#define X509V3_F_POLICY_SECTION 131
+#define X509V3_F_PROCESS_PCI_VALUE 150
+#define X509V3_F_R2I_CERTPOL 130
+#define X509V3_F_R2I_PCI 155
+#define X509V3_F_S2I_ASN1_IA5STRING 100
+#define X509V3_F_S2I_ASN1_INTEGER 108
+#define X509V3_F_S2I_ASN1_OCTET_STRING 112
+#define X509V3_F_S2I_ASN1_SKEY_ID 114
+#define X509V3_F_S2I_SKEY_ID 115
+#define X509V3_F_STRING_TO_HEX 113
+#define X509V3_F_SXNET_ADD_ID_ASC 125
+#define X509V3_F_SXNET_ADD_ID_INTEGER 126
+#define X509V3_F_SXNET_ADD_ID_ULONG 127
+#define X509V3_F_SXNET_GET_ID_ASC 128
+#define X509V3_F_SXNET_GET_ID_ULONG 129
+#define X509V3_F_V2I_ASIDENTIFIERS 158
+#define X509V3_F_V2I_ASN1_BIT_STRING 101
+#define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139
+#define X509V3_F_V2I_AUTHORITY_KEYID 119
+#define X509V3_F_V2I_BASIC_CONSTRAINTS 102
+#define X509V3_F_V2I_CRLD 134
+#define X509V3_F_V2I_EXTENDED_KEY_USAGE 103
+#define X509V3_F_V2I_GENERAL_NAMES 118
+#define X509V3_F_V2I_GENERAL_NAME_EX 117
+#define X509V3_F_V2I_IPADDRBLOCKS 159
+#define X509V3_F_V2I_ISSUER_ALT 153
+#define X509V3_F_V2I_NAME_CONSTRAINTS 147
+#define X509V3_F_V2I_POLICY_CONSTRAINTS 146
+#define X509V3_F_V2I_POLICY_MAPPINGS 145
+#define X509V3_F_V2I_SUBJECT_ALT 154
+#define X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL 160
+#define X509V3_F_V3_GENERIC_EXTENSION 116
+#define X509V3_F_X509V3_ADD1_I2D 140
+#define X509V3_F_X509V3_ADD_VALUE 105
+#define X509V3_F_X509V3_EXT_ADD 104
+#define X509V3_F_X509V3_EXT_ADD_ALIAS 106
+#define X509V3_F_X509V3_EXT_CONF 107
+#define X509V3_F_X509V3_EXT_I2D 136
+#define X509V3_F_X509V3_EXT_NCONF 152
+#define X509V3_F_X509V3_GET_SECTION 142
+#define X509V3_F_X509V3_GET_STRING 143
+#define X509V3_F_X509V3_GET_VALUE_BOOL 110
+#define X509V3_F_X509V3_PARSE_LIST 109
+#define X509V3_F_X509_PURPOSE_ADD 137
+#define X509V3_F_X509_PURPOSE_SET 141
+
+/* Reason codes. */
+#define X509V3_R_BAD_IP_ADDRESS 118
+#define X509V3_R_BAD_OBJECT 119
+#define X509V3_R_BN_DEC2BN_ERROR 100
+#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101
+#define X509V3_R_DIRNAME_ERROR 149
+#define X509V3_R_DUPLICATE_ZONE_ID 133
+#define X509V3_R_ERROR_CONVERTING_ZONE 131
+#define X509V3_R_ERROR_CREATING_EXTENSION 144
+#define X509V3_R_ERROR_IN_EXTENSION 128
+#define X509V3_R_EXPECTED_A_SECTION_NAME 137
+#define X509V3_R_EXTENSION_EXISTS 145
+#define X509V3_R_EXTENSION_NAME_ERROR 115
+#define X509V3_R_EXTENSION_NOT_FOUND 102
+#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103
+#define X509V3_R_EXTENSION_VALUE_ERROR 116
+#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151
+#define X509V3_R_ILLEGAL_HEX_DIGIT 113
+#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152
+#define X509V3_R_INVALID_ASNUMBER 160
+#define X509V3_R_INVALID_ASRANGE 161
+#define X509V3_R_INVALID_BOOLEAN_STRING 104
+#define X509V3_R_INVALID_EXTENSION_STRING 105
+#define X509V3_R_INVALID_INHERITANCE 162
+#define X509V3_R_INVALID_IPADDRESS 163
+#define X509V3_R_INVALID_NAME 106
+#define X509V3_R_INVALID_NULL_ARGUMENT 107
+#define X509V3_R_INVALID_NULL_NAME 108
+#define X509V3_R_INVALID_NULL_VALUE 109
+#define X509V3_R_INVALID_NUMBER 140
+#define X509V3_R_INVALID_NUMBERS 141
+#define X509V3_R_INVALID_OBJECT_IDENTIFIER 110
+#define X509V3_R_INVALID_OPTION 138
+#define X509V3_R_INVALID_POLICY_IDENTIFIER 134
+#define X509V3_R_INVALID_PROXY_POLICY_SETTING 153
+#define X509V3_R_INVALID_PURPOSE 146
+#define X509V3_R_INVALID_SAFI 164
+#define X509V3_R_INVALID_SECTION 135
+#define X509V3_R_INVALID_SYNTAX 143
+#define X509V3_R_ISSUER_DECODE_ERROR 126
+#define X509V3_R_MISSING_VALUE 124
+#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142
+#define X509V3_R_NO_CONFIG_DATABASE 136
+#define X509V3_R_NO_ISSUER_CERTIFICATE 121
+#define X509V3_R_NO_ISSUER_DETAILS 127
+#define X509V3_R_NO_POLICY_IDENTIFIER 139
+#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154
+#define X509V3_R_NO_PUBLIC_KEY 114
+#define X509V3_R_NO_SUBJECT_DETAILS 125
+#define X509V3_R_ODD_NUMBER_OF_DIGITS 112
+#define X509V3_R_OPERATION_NOT_DEFINED 148
+#define X509V3_R_OTHERNAME_ERROR 147
+#define X509V3_R_POLICY_LANGUAGE_ALREADTY_DEFINED 155
+#define X509V3_R_POLICY_PATH_LENGTH 156
+#define X509V3_R_POLICY_PATH_LENGTH_ALREADTY_DEFINED 157
+#define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED 158
+#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159
+#define X509V3_R_SECTION_NOT_FOUND 150
+#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122
+#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123
+#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111
+#define X509V3_R_UNKNOWN_EXTENSION 129
+#define X509V3_R_UNKNOWN_EXTENSION_NAME 130
+#define X509V3_R_UNKNOWN_OPTION 120
+#define X509V3_R_UNSUPPORTED_OPTION 117
+#define X509V3_R_USER_TOO_LONG 132
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/zlib/zconf.h b/src/Mayaqua/zlib/zconf.h
new file mode 100644
index 00000000..e3b0c962
--- /dev/null
+++ b/src/Mayaqua/zlib/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/src/Mayaqua/zlib/zlib.h b/src/Mayaqua/zlib/zlib.h
new file mode 100644
index 00000000..62d0e467
--- /dev/null
+++ b/src/Mayaqua/zlib/zlib.h
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/src/Neo/NDIS5.c b/src/Neo/NDIS5.c
new file mode 100644
index 00000000..1ba85c7c
--- /dev/null
+++ b/src/Neo/NDIS5.c
@@ -0,0 +1,1704 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NDIS5.c
+// Description: Windows NDIS 5.0 Routine
+
+#include <GlobalConst.h>
+
+#define NEO_DEVICE_DRIVER
+
+#include "Neo.h"
+
+static UINT max_speed = NEO_MAX_SPEED_DEFAULT;
+static bool keep_link = false;
+
+BOOLEAN
+PsGetVersion(
+ PULONG MajorVersion OPTIONAL,
+ PULONG MinorVersion OPTIONAL,
+ PULONG BuildNumber OPTIONAL,
+ PUNICODE_STRING CSDVersion OPTIONAL
+ );
+
+// Memory related
+static NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+NDIS_HANDLE ndis_wrapper_handle = NULL;
+
+// Whether Windows 8
+bool g_is_win8 = false;
+
+// Win32 driver entry point
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
+{
+ NDIS_MINIPORT_CHARACTERISTICS miniport;
+ ULONG os_major_ver = 0, os_minor_ver = 0;
+
+ // Initialize the Neo library
+ if (NeoInit() == FALSE)
+ {
+ // Initialization Failed
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ g_is_win8 = false;
+
+#ifndef NDIS30_MINIPORT
+ // Get the OS version
+ PsGetVersion(&os_major_ver, &os_minor_ver, NULL, NULL);
+
+ if (os_major_ver >= 7 || (os_major_ver == 6 && os_minor_ver >= 2))
+ {
+ // Windows 8
+ g_is_win8 = true;
+ }
+#endif // NDIS30_MINIPORT
+
+ // Initialize the NDIS wrapper
+ NdisMInitializeWrapper(&ctx->NdisWrapper, DriverObject, RegistryPath, NULL);
+ ndis_wrapper_handle = ctx->NdisWrapper;
+
+ // Register a NDIS miniport driver
+ NeoZero(&miniport, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
+ miniport.MajorNdisVersion = NEO_NDIS_MAJOR_VERSION;
+ miniport.MinorNdisVersion = NEO_NDIS_MINOR_VERSION;
+
+ // Register the handler
+ miniport.InitializeHandler = NeoNdisInit;
+ miniport.HaltHandler = NeoNdisHalt;
+ miniport.QueryInformationHandler = NeoNdisQuery;
+ miniport.ResetHandler = NeoNdisReset;
+ miniport.SetInformationHandler = NeoNdisSet;
+
+#ifndef NDIS30_MINIPORT
+ miniport.SendPacketsHandler = NeoNdisSendPackets;
+#else // NDIS30_MINIPORT
+ miniport.SendHandler = NULL;
+#endif // NDIS30_MINIPORT
+
+ if (NG(NdisMRegisterMiniport(ctx->NdisWrapper, &miniport, sizeof(NDIS_MINIPORT_CHARACTERISTICS))))
+ {
+ // Registration failure
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Initialization success
+ return STATUS_SUCCESS;
+}
+
+// Initialization handler of adapter
+NDIS_STATUS NeoNdisInit(NDIS_STATUS *OpenErrorStatus,
+ UINT *SelectedMediumIndex,
+ NDIS_MEDIUM *MediumArray,
+ UINT MediumArraySize,
+ NDIS_HANDLE MiniportAdapterHandle,
+ NDIS_HANDLE WrapperConfigurationContext)
+{
+ BOOL media_check;
+ UINT i;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if (ctx->NdisWrapper == NULL)
+ {
+ ctx->NdisWrapper = ndis_wrapper_handle;
+ }
+
+ // Prevention of multiple start
+ if (ctx->Initing != FALSE)
+ {
+ // Multiple started
+ return NDIS_STATUS_FAILURE;
+ }
+ ctx->Initing = TRUE;
+
+ // Examine whether it has already been initialized
+ if (ctx->Inited != FALSE)
+ {
+ // Driver is started on another instance already.
+ // PacketiX VPN driver can start only one instance per one service.
+ // User can start multiple drivers with different instance ID
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Current value of the packet filter
+ ctx->CurrentPacketFilter = NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
+
+ // Examine whether the Ethernet is available
+ media_check = FALSE;
+ for (i = 0;i < MediumArraySize;i++)
+ {
+ if (MediumArray[i] == NEO_MEDIA)
+ {
+ media_check = TRUE;
+ break;
+ }
+ }
+ if (media_check == FALSE)
+ {
+ // Ethernet is unavailable
+ ctx->Initing = FALSE;
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Media number to use
+ *SelectedMediumIndex = i;
+
+ // Initialize the adapter information
+ ctx->NdisMiniport = MiniportAdapterHandle;
+ ctx->NdisConfig = WrapperConfigurationContext;
+ ctx->NdisContext = ctx;
+ ctx->HardwareStatus = NdisHardwareStatusReady;
+ ctx->Halting = FALSE;
+ ctx->Connected = ctx->ConnectedOld = FALSE;
+
+ if (keep_link == false)
+ {
+ ctx->ConnectedForce = TRUE;
+ }
+
+ // Read the information from the registry
+ if (NeoLoadRegistory() == FALSE)
+ {
+ // Failure
+ ctx->Initing = FALSE;
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Register the device attributes
+
+ if (g_is_win8 == false)
+ {
+ NdisMSetAttributes(ctx->NdisMiniport, ctx->NdisContext, FALSE, NdisInterfaceInternal);
+ }
+ else
+ {
+ NdisMSetAttributesEx(ctx->NdisMiniport, ctx->NdisContext, 16,
+ NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
+ NdisInterfaceInternal);
+ }
+
+ // Initialize the received packet array
+ NeoInitPacketArray();
+
+ // Initialize the control device
+ NeoInitControlDevice();
+
+ // Start the adapter
+ NeoStartAdapter();
+
+ // Flag setting
+ ctx->Initing = FALSE;
+ ctx->Inited = TRUE;
+
+ // Notify the connection state
+ NeoSetConnectState(FALSE);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Open the device
+BOOL NeoNdisOnOpen(IRP *irp, IO_STACK_LOCATION *stack)
+{
+ char name[MAX_SIZE];
+
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Opened != FALSE)
+ {
+ // Another client is connected already
+ return FALSE;
+ }
+ ctx->Opened = TRUE;
+
+ // Initialize the event name
+ sprintf(name, NDIS_NEO_EVENT_NAME, ctx->HardwareID);
+
+ // Register a Event
+#ifndef WIN9X
+ ctx->Event = NeoNewEvent(name);
+ if (ctx->Event == NULL)
+ {
+ ctx->Opened = FALSE;
+ return FALSE;
+ }
+#endif // WIN9X
+
+ // Set the connection state
+ NeoSetConnectState(TRUE);
+
+ return TRUE;
+}
+
+// Close the device
+BOOL NeoNdisOnClose(IRP *irp, IO_STACK_LOCATION *stack)
+{
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Opened == FALSE)
+ {
+ // Client is not connected
+ return FALSE;
+ }
+ ctx->Opened = FALSE;
+
+ // Release the event
+ NeoFreeEvent(ctx->Event);
+ ctx->Event = NULL;
+
+ // Release all packets
+ NeoClearPacketQueue();
+
+ NeoSetConnectState(FALSE);
+
+ return TRUE;
+}
+
+// Crash
+void NeoNdisCrash()
+{
+ NEO_QUEUE *q;
+ q = (NEO_QUEUE *)0xACACACAC;
+ q->Size = 128;
+ NeoCopy(q->Buf, "ABCDEFG", 8);
+}
+
+// Dispatch table for control
+NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
+{
+ NTSTATUS status;
+ IO_STACK_LOCATION *stack;
+ void *buf;
+ BOOL ok;
+ status = STATUS_SUCCESS;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Get the IRP stack
+ stack = IoGetCurrentIrpStackLocation(Irp);
+
+ // Initialize the number of bytes
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ buf = Irp->UserBuffer;
+
+ if (ctx->Halting != FALSE)
+ {
+ // Device driver is terminating
+ Irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Branch to each operation
+ switch (stack->MajorFunction)
+ {
+ case IRP_MJ_CREATE:
+ // Device is opened
+ if (NeoNdisOnOpen(Irp, stack) == FALSE)
+ {
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case IRP_MJ_CLOSE:
+ // Device is closed
+ if (NeoNdisOnClose(Irp, stack) == FALSE)
+ {
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case IRP_MJ_READ:
+#ifndef WIN9X
+ // Read (Reading of the received packet)
+ ok = false;
+ if (buf != NULL)
+ {
+ if (ctx->Opened && ctx->Inited)
+ {
+ if (stack->Parameters.Read.Length == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Address check
+ MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ if (NeoIsKernelAddress(buf) == FALSE)
+ {
+ // Read
+ NeoRead(buf);
+ Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE;
+ ok = true;
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ if (ok == FALSE)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+#endif // WIN9X
+ break;
+
+ case IRP_MJ_WRITE:
+#ifndef WIN9X
+ // Write (Writing of a transmission packet)
+ ok = false;
+ if (buf != NULL)
+ {
+ if (ctx->Opened && ctx->Inited)
+ {
+ if (stack->Parameters.Write.Length == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Address check
+ MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
+ }
+
+ if (NeoIsKernelAddress(buf) == FALSE)
+ {
+ // Write
+ NeoWrite(buf);
+ Irp->IoStatus.Information = stack->Parameters.Write.Length;
+ ok = true;
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ if (ok == FALSE)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+#endif // WIN9X
+ case IRP_MJ_DEVICE_CONTROL:
+#ifdef WIN9X
+ // IO Control
+ switch (stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case NEO_IOCTL_SET_EVENT:
+ // Specify a event
+ if (Irp->AssociatedIrp.SystemBuffer == NULL ||
+ stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(DWORD))
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ DWORD value = *((DWORD *)Irp->AssociatedIrp.SystemBuffer);
+ ctx->Event = NeoCreateWin9xEvent(value);
+ Irp->IoStatus.Information = sizeof(DWORD);
+ }
+ break;
+
+ case NEO_IOCTL_PUT_PACKET:
+ // Write a packet
+ ok = false;
+ buf = Irp->AssociatedIrp.SystemBuffer;
+ if (buf != NULL)
+ {
+ if (stack->Parameters.DeviceIoControl.InputBufferLength == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Write
+ NeoWrite(buf);
+ Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE;
+ ok = true;
+ }
+ }
+
+ if (ok == false)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case NEO_IOCTL_GET_PACKET:
+ // Get the packet
+ ok = false;
+ buf = Irp->AssociatedIrp.SystemBuffer;
+ if (buf != NULL)
+ {
+ if (stack->Parameters.DeviceIoControl.OutputBufferLength == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Read
+ NeoRead(buf);
+ Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE;
+ ok = true;
+ }
+ }
+
+ if (ok == false)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+#endif // WIN9X
+ break;
+ }
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+}
+
+// Initialize the control device
+void NeoInitControlDevice()
+{
+ char name_kernel[MAX_SIZE];
+ char name_win32[MAX_SIZE];
+ UNICODE *unicode_kernel, *unicode_win32;
+ DEVICE_OBJECT *control_device_object;
+ NDIS_HANDLE ndis_control_handle;
+
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ // Initialize the dispatch table
+ NeoZero(ctx->DispatchTable, sizeof(PDRIVER_DISPATCH) * IRP_MJ_MAXIMUM_FUNCTION);
+
+ // Register the handler
+ ctx->DispatchTable[IRP_MJ_CREATE] =
+ ctx->DispatchTable[IRP_MJ_CLOSE] =
+ ctx->DispatchTable[IRP_MJ_READ] =
+ ctx->DispatchTable[IRP_MJ_WRITE] =
+ ctx->DispatchTable[IRP_MJ_DEVICE_CONTROL] = NeoNdisDispatch;
+ ctx->Opened = FALSE;
+
+ // Generate the device name
+ sprintf(name_kernel, NDIS_NEO_DEVICE_NAME, ctx->HardwareID);
+ unicode_kernel = NewUnicode(name_kernel);
+ sprintf(name_win32, NDIS_NEO_DEVICE_NAME_WIN32, ctx->HardwareID);
+ unicode_win32 = NewUnicode(name_win32);
+
+ // Register the Device
+ NdisMRegisterDevice(ctx->NdisWrapper, GetUnicode(unicode_kernel),
+ GetUnicode(unicode_win32), ctx->DispatchTable,
+ &control_device_object,
+ &ndis_control_handle);
+
+ ctx->NdisControlDevice = control_device_object;
+ ctx->NdisControl = ndis_control_handle;
+
+ // Initialize the display name
+ if (strlen(ctx->HardwareID) > 11)
+ {
+ sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw + 11);
+ }
+ else
+ {
+ sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw);
+ }
+}
+
+// Release the control device
+void NeoFreeControlDevice()
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ if (ctx->Opened != FALSE)
+ {
+ // Delete the event
+ NeoSet(ctx->Event);
+ NeoFreeEvent(ctx->Event);
+ ctx->Event = NULL;
+ ctx->Opened = FALSE;
+ }
+ // Delet the device
+ NdisMDeregisterDevice(ctx->NdisControl);
+}
+
+
+// Read the information from the registry
+BOOL NeoLoadRegistory()
+{
+ void *buf;
+ NDIS_STATUS ret;
+ UINT size;
+ NDIS_HANDLE config;
+ NDIS_CONFIGURATION_PARAMETER *param;
+ UNICODE *name;
+ ANSI_STRING ansi;
+ UNICODE_STRING *unicode;
+ UINT speed;
+ BOOL keep;
+
+ // Get the config handle
+ NdisOpenConfiguration(&ret, &config, ctx->NdisConfig);
+ if (NG(ret))
+ {
+ // Failure
+ return FALSE;
+ }
+
+ // Read the MAC address
+ NdisReadNetworkAddress(&ret, &buf, &size, config);
+ if (NG(ret))
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+
+ // Copy the MAC address
+ if (size != NEO_MAC_ADDRESS_SIZE)
+ {
+ // Invalid size
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ NeoCopy(ctx->MacAddress, buf, NEO_MAC_ADDRESS_SIZE);
+
+ if (ctx->MacAddress[0] == 0x00 &&
+ ctx->MacAddress[1] == 0x00 &&
+ ctx->MacAddress[2] == 0x01 &&
+ ctx->MacAddress[3] == 0x00 &&
+ ctx->MacAddress[4] == 0x00 &&
+ ctx->MacAddress[5] == 0x01)
+ {
+ // Special MAC address
+ UINT ptr32 = (UINT)((UINT64)ctx);
+
+ ctx->MacAddress[0] = 0x00;
+ ctx->MacAddress[1] = 0xAD;
+ ctx->MacAddress[2] = ((UCHAR *)(&ptr32))[0];
+ ctx->MacAddress[3] = ((UCHAR *)(&ptr32))[1];
+ ctx->MacAddress[4] = ((UCHAR *)(&ptr32))[2];
+ ctx->MacAddress[5] = ((UCHAR *)(&ptr32))[3];
+ }
+
+ // Initialize the key name of the device name
+ name = NewUnicode("MatchingDeviceId");
+
+ // Read the hardware ID
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterString);
+ FreeUnicode(name);
+ if (NG(ret))
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ // Type checking
+ if (param->ParameterType != NdisParameterString)
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ unicode = &param->ParameterData.StringData;
+
+ // Prepare a buffer for ANSI string
+ NeoZero(&ansi, sizeof(ANSI_STRING));
+ ansi.MaximumLength = MAX_SIZE - 1;
+ ansi.Buffer = NeoZeroMalloc(MAX_SIZE);
+
+ // Convert to ANSI string
+ NdisUnicodeStringToAnsiString(&ansi, unicode);
+ // Copy
+ strcpy(ctx->HardwareID, ansi.Buffer);
+ strcpy(ctx->HardwareID_Raw, ctx->HardwareID);
+ // Convert to upper case
+ _strupr(ctx->HardwareID);
+ // Release the memory
+ NeoFree(ansi.Buffer);
+
+ // Read the bit rate
+ name = NewUnicode("MaxSpeed");
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
+ FreeUnicode(name);
+
+ if (NG(ret) || param->ParameterType != NdisParameterInteger)
+ {
+ speed = NEO_MAX_SPEED_DEFAULT;
+ }
+ else
+ {
+ speed = param->ParameterData.IntegerData * 10000;
+ }
+
+ max_speed = speed;
+
+ // Read the link keeping flag
+ name = NewUnicode("KeepLink");
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
+ FreeUnicode(name);
+
+ if (NG(ret) || param->ParameterType != NdisParameterInteger)
+ {
+ keep = false;
+ }
+ else
+ {
+ keep = (param->ParameterData.IntegerData == 0 ? false : true);
+ }
+
+ keep_link = keep;
+
+ // Close the Config handle
+ NdisCloseConfiguration(config);
+
+ return TRUE;
+}
+
+// Stop handler of adapter
+NDIS_STATUS NeoNdisHalt(NDIS_HANDLE MiniportAdapterContext)
+{
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if (ctx->Halting != FALSE)
+ {
+ // That has already been stopped
+ return NDIS_STATUS_SUCCESS;
+ }
+ ctx->Halting = TRUE;
+
+ // Stop the adapter
+ NeoStopAdapter();
+
+ // Release the packet array
+ NeoFreePacketArray();
+
+ // Delete the control device
+ NeoFreeControlDevice();
+
+ // Complete to stop
+ ctx->Initing = ctx->Inited = FALSE;
+ ctx->Connected = ctx->ConnectedForce = ctx->ConnectedOld = FALSE;
+ ctx->Halting = FALSE;
+
+ // Shutdown of Neo
+ NeoShutdown();
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Reset handler of adapter
+NDIS_STATUS NeoNdisReset(BOOLEAN *AddressingReset, NDIS_HANDLE MiniportAdapterContext)
+{
+ NdisMResetComplete(ctx->NdisMiniport, NDIS_STATUS_SUCCESS, FALSE);
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Information acquisition handler of adapter
+NDIS_STATUS NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesWritten,
+ ULONG *BytesNeeded)
+{
+ NDIS_MEDIUM media;
+ void *buf;
+ UINT value32;
+ USHORT value16;
+ UINT size;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Initialization
+ size = sizeof(UINT);
+ value32 = value16 = 0;
+ buf = &value32;
+
+ // Branch processing
+ switch (Oid)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+ // Return a list of supported OID
+ buf = SupportedOids;
+ size = sizeof(SupportedOids);
+ break;
+
+ case OID_GEN_MAC_OPTIONS:
+ // Ethernet option
+ value32 = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK;
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+ // Hardware state
+ buf = &ctx->HardwareStatus;
+ size = sizeof(NDIS_HARDWARE_STATUS);
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ // Type of media
+ media = NdisMedium802_3;
+ buf = &media;
+ size = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ // Available look-ahead size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ // Maximum frame size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ break;
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ // Maximum packet size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE;
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ // Buffer size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE * NEO_MAX_PACKET_EXCHANGE;
+ break;
+
+ case OID_GEN_LINK_SPEED:
+ // Communication speed
+ value32 = max_speed;
+ break;
+
+ case OID_GEN_VENDOR_ID:
+ // Vendor ID
+ NeoCopy(&value32, ctx->MacAddress, 3);
+ value32 &= 0xFFFFFF00;
+ value32 |= 0x01;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+ // Hardware ID
+ buf = ctx->HardwarePrintableID;
+ size = (UINT)strlen(ctx->HardwarePrintableID) + 1;
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+ // Driver version
+ value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
+ buf = &value16;
+ size = sizeof(USHORT);
+ break;
+
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+ // Vendor driver version
+ value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
+ buf = &value16;
+ size = sizeof(USHORT);
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ // MAC address
+ buf = ctx->MacAddress;
+ size = NEO_MAC_ADDRESS_SIZE;
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ // Number of multicast
+ value32 = NEO_MAX_MULTICASE;
+ break;
+
+ case OID_GEN_MAXIMUM_SEND_PACKETS:
+ // Number of packets that can be sent at a time
+ value32 = NEO_MAX_PACKET_EXCHANGE;
+ break;
+
+ case OID_GEN_XMIT_OK:
+ // Number of packets sent
+ value32 = ctx->Status.NumPacketSend;
+ break;
+
+ case OID_GEN_RCV_OK:
+ // Number of received packets
+ value32 = ctx->Status.NumPacketRecv;
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ // Number of transmission error packets
+ value32 = ctx->Status.NumPacketSendError;
+ break;
+
+ case OID_GEN_RCV_ERROR:
+ // Number of error packets received
+ value32 = ctx->Status.NumPacketRecvError;
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+ // Number of reception buffer shortage occurrences
+ value32 = ctx->Status.NumPacketRecvNoBuffer;
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ // Number of errors
+ value32 = 0;
+ break;
+
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ // Cable connection state
+ NeoCheckConnectState();
+ if (keep_link == false)
+ {
+ value32 = ctx->Connected ? NdisMediaStateConnected : NdisMediaStateDisconnected;
+ }
+ else
+ {
+ value32 = NdisMediaStateConnected;
+ }
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ // Number of collisions
+ value32 = 0;
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ // Current settings of the packet filter
+ value32 = ctx->CurrentPacketFilter;
+ break;
+
+/* case OID_GEN_PROTOCOL_OPTIONS:
+ // Current value of the protocol option
+ value32 = ctx->CurrentProtocolOptions;
+ break;*/
+
+ default:
+ // Unknown OID
+ *BytesWritten = 0;
+ return NDIS_STATUS_INVALID_OID;
+ }
+
+ if (size > InformationBufferLength)
+ {
+ // Undersize
+ *BytesNeeded = size;
+ *BytesWritten = 0;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ // Data copy
+ NeoCopy(InformationBuffer, buf, size);
+ *BytesWritten = size;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Set the cable connection state
+void NeoSetConnectState(BOOL connected)
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+ ctx->Connected = connected;
+ NeoCheckConnectState();
+}
+
+// Check the cable connection state
+void NeoCheckConnectState()
+{
+ if (ctx == NULL || ctx->NdisMiniport == NULL)
+ {
+ return;
+ }
+
+ if (keep_link == false)
+ {
+ if (ctx->ConnectedOld != ctx->Connected || ctx->ConnectedForce)
+ {
+ ctx->ConnectedForce = FALSE;
+ ctx->ConnectedOld = ctx->Connected;
+ if (ctx->Halting == FALSE)
+ {
+ NdisMIndicateStatus(ctx->NdisMiniport,
+ ctx->Connected ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT,
+ 0, 0);
+ NdisMIndicateStatusComplete(ctx->NdisMiniport);
+ }
+ }
+ }
+ else
+ {
+ if (ctx->ConnectedForce)
+ {
+ ctx->ConnectedForce = false;
+
+ if (ctx->Halting == FALSE)
+ {
+ NdisMIndicateStatus(ctx->NdisMiniport,
+ NDIS_STATUS_MEDIA_CONNECT,
+ 0, 0);
+ NdisMIndicateStatusComplete(ctx->NdisMiniport);
+ }
+ }
+ }
+}
+
+// Information setting handler of adapter
+NDIS_STATUS NeoNdisSet(
+ NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesRead,
+ ULONG *BytesNeeded)
+{
+ if (ctx == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Initialization
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ // Branch processing
+ switch (Oid)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ /* Packet filter */
+ if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ ctx->CurrentPacketFilter = *((UINT *)InformationBuffer);
+ return NDIS_STATUS_SUCCESS;
+
+// case OID_GEN_PROTOCOL_OPTIONS:
+ /* Current protocol option value */
+/* if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ ctx->CurrentProtocolOptions = *((UINT *)InformationBuffer);
+ return NDIS_STATUS_SUCCESS;*/
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ /* Look ahead */
+ if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ return NDIS_STATUS_SUCCESS;
+
+ case OID_802_3_MULTICAST_LIST:
+ // Multicast list
+ *BytesRead = InformationBufferLength;
+
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ return NDIS_STATUS_INVALID_OID;
+}
+
+// NDIS 3.0 packet send handler
+NDIS_STATUS NeoNdisSend(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_PACKET *Packet, UINT Flags)
+{
+ NDIS_PACKET *PacketArray[1];
+ PacketArray[0] = Packet;
+ NeoNdisSendPackets(MiniportAdapterContext, PacketArray, 1);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Packet send handler
+void NeoNdisSendPackets(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_PACKET **PacketArray,
+ UINT NumberOfPackets)
+{
+ UCHAR *Buf,*BufCopy;
+ PNDIS_BUFFER Buffer;
+ UCHAR *Tmp;
+ UINT PacketLength;
+ UINT CurrentLength;
+ UINT i;
+
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ // Update the connection state
+ NeoCheckConnectState();
+
+ if (NumberOfPackets == 0)
+ {
+ // The number of packets is 0
+ return;
+ }
+
+ if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE)
+ {
+ // Device is stopped
+ return;
+ }
+
+ // Operation of the packet queue
+ NeoLockPacketQueue();
+ {
+ if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE)
+ {
+ // Device is stopped
+ NeoUnlockPacketQueue();
+ return;
+ }
+
+ // Place the packet in the queue in order
+ for (i = 0;i < NumberOfPackets;i++)
+ {
+ // Get a packet
+ NdisQueryPacket(PacketArray[i], NULL, NULL, &Buffer, &PacketLength);
+
+ // Extract the packet.
+ // Memory allocated here is used for the queue and is released at the time of releasing the queue.
+ Buf = NeoMalloc(PacketLength);
+ BufCopy = Buf;
+ while (Buffer)
+ {
+ NdisQueryBuffer(Buffer, &Tmp, &CurrentLength);
+ if (CurrentLength == 0)
+ {
+ // Complete
+ break;
+ }
+ NeoCopy(BufCopy, Tmp, CurrentLength);
+ BufCopy += CurrentLength;
+ NdisGetNextBuffer(Buffer, &Buffer);
+ }
+ // Process this packet
+ if (PacketLength > NEO_MIN_PACKET_SIZE)
+ {
+ if (PacketLength > NEO_MAX_PACKET_SIZE)
+ {
+ // Packet is too large
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE);
+
+ if (g_is_win8)
+ {
+ NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_FAILURE);
+ }
+
+ ctx->Status.NumPacketSendError++;
+ NeoFree(Buf);
+ }
+ else
+ {
+ // Insert the packet into the queue
+ NeoInsertQueue(Buf, PacketLength);
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
+
+ if (g_is_win8)
+ {
+ NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS);
+ }
+
+ ctx->Status.NumPacketSend++;
+ }
+ }
+ else
+ {
+ // Release if the packet doesn't contain data
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
+
+ if (g_is_win8)
+ {
+ NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS);
+ }
+
+ NeoFree(Buf);
+ }
+ }
+ }
+ NeoUnlockPacketQueue();
+
+ // Reception event
+ NeoSet(ctx->Event);
+}
+
+// Stop check of packet transmission
+BOOL NeoNdisSendPacketsHaltCheck(NDIS_PACKET **PacketArray, UINT NumberOfPackets)
+{
+ UINT i;
+
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Halting != FALSE || ctx->Opened == FALSE)
+ {
+ // Finishing
+ for (i = 0;i < NumberOfPackets;i++)
+ {
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE);
+
+ if (g_is_win8)
+ {
+ NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS);
+ }
+
+ ctx->Status.NumPacketSendError++;
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// Initialize the packet array
+void NeoInitPacketArray()
+{
+ UINT i;
+ // Create a packet buffer
+ for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
+ {
+ ctx->PacketBuffer[i] = NeoNewPacketBuffer();
+ // Store in the array
+ ctx->PacketBufferArray[i] = ctx->PacketBuffer[i]->NdisPacket;
+ }
+}
+
+// Release the packet array
+void NeoFreePacketArray()
+{
+ UINT i;
+ for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
+ {
+ NeoFreePacketBuffer(ctx->PacketBuffer[i]);
+ ctx->PacketBuffer[i] = NULL;
+ ctx->PacketBufferArray[i] = NULL;
+ }
+}
+
+// Release the packet buffer
+void NeoFreePacketBuffer(PACKET_BUFFER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Detach the buffer from the packet
+ NdisUnchainBufferAtFront(p->NdisPacket, &p->NdisBuffer);
+ // Release the packet
+ NdisFreePacket(p->NdisPacket);
+ // Release the packet pool
+ NdisFreePacketPool(p->PacketPool);
+ // Release the buffer
+ NdisFreeBuffer(p->NdisBuffer);
+ // Release the memory
+ NeoFree(p->Buf);
+ // Release the buffer pool
+ NdisFreeBufferPool(p->BufferPool);
+ // Release the memory
+ NeoFree(p);
+}
+
+// Create a packet buffer
+PACKET_BUFFER *NeoNewPacketBuffer()
+{
+ PACKET_BUFFER *p;
+ NDIS_STATUS ret;
+
+ // Memory allocation
+ p = NeoZeroMalloc(sizeof(PACKET_BUFFER));
+ // Memory allocation for packet
+ p->Buf = NeoMalloc(NEO_MAX_PACKET_SIZE);
+ // Allocate the buffer pool
+ NdisAllocateBufferPool(&ret, &p->BufferPool, 1);
+ // Allocate the buffer
+ NdisAllocateBuffer(&ret, &p->NdisBuffer, p->BufferPool, p->Buf, NEO_MAX_PACKET_SIZE);
+ // Secure the packet pool
+ NdisAllocatePacketPool(&ret, &p->PacketPool, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET);
+ // Secure the packet
+ NdisAllocatePacket(&ret, &p->NdisPacket, p->PacketPool);
+ NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE);
+ // Attach the buffer to the packet
+ NdisChainBufferAtFront(p->NdisPacket, p->NdisBuffer);
+
+ return p;
+}
+
+// Check whether the specified address is kernel memory
+BOOL NeoIsKernelAddress(void *addr)
+{
+#if 0
+ if ((ULONG)addr >= (ULONG)0x80000000)
+ {
+ // Kernel memory
+ return TRUE;
+ }
+#endif // CPU_64
+ // User memory
+ return FALSE;
+}
+
+// Reset the event
+void NeoReset(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+#ifndef WIN9X
+ KeResetEvent(event->event);
+#else // WIN9X
+ if (event->win32_event != 0)
+ {
+ DWORD h = event->win32_event;
+ _asm mov eax, h;
+ VxDCall(_VWIN32_ResetWin32Event);
+ }
+#endif // WIN9X
+}
+
+// Set the event
+void NeoSet(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+#ifndef WIN9X
+ KeSetEvent(event->event, 0, FALSE);
+#else // WIN9X
+ if (event->win32_event != 0)
+ {
+ DWORD h = event->win32_event;
+ _asm mov eax, h;
+ VxDCall(_VWIN32_SetWin32Event);
+ }
+#endif // WIN9X
+}
+
+// Release the event
+void NeoFreeEvent(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+#ifdef WIN9X
+ if (0)
+ {
+ if (event->win32_event != 0)
+ {
+ DWORD h = event->win32_event;
+ _asm mov eax, h;
+ VxDCall(_VWIN32_CloseVxDHandle);
+ }
+ }
+#endif WIN9X
+
+ ZwClose(event->event_handle);
+
+ // Release the memory
+ NeoFree(event);
+}
+
+// Create a new event
+#ifndef WIN9X
+NEO_EVENT *NeoNewEvent(char *name)
+{
+ UNICODE *unicode_name;
+ NEO_EVENT *event;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert the name to Unicode
+ unicode_name = NewUnicode(name);
+ if (unicode_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ event = NeoZeroMalloc(sizeof(NEO_EVENT));
+ if (event == NULL)
+ {
+ FreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Create an Event
+ event->event = IoCreateNotificationEvent(GetUnicode(unicode_name), &event->event_handle);
+ if (event->event == NULL)
+ {
+ NeoFree(event);
+ FreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Initialize the event
+ KeInitializeEvent(event->event, NotificationEvent, FALSE);
+ KeClearEvent(event->event);
+
+ // Release a string
+ FreeUnicode(unicode_name);
+
+ return event;
+}
+#else // WIN9X
+NEO_EVENT *NeoCreateWin9xEvent(DWORD h)
+{
+ NEO_EVENT *event;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ event = NeoZeroMalloc(sizeof(NEO_EVENT));
+ if (event == NULL)
+ {
+ return NULL;
+ }
+
+ event->win32_event = h;
+
+ return event;
+}
+#endif // WIN9X
+
+// Get the Unicode string
+NDIS_STRING *GetUnicode(UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ return &u->String;
+}
+
+// Release the Unicode strings
+void FreeUnicode(UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ // Release a string
+ NdisFreeString(u->String);
+
+ // Release the memory
+ NeoFree(u);
+}
+
+// Create a new Unicode string
+UNICODE *NewUnicode(char *str)
+{
+ UNICODE *u;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = NeoZeroMalloc(sizeof(UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ // String initialization
+ _NdisInitializeString(&u->String, str);
+
+ return u;
+}
+
+// Release the lock
+void NeoFreeLock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisFreeSpinLock(spin_lock);
+
+ // Release the memory
+ NeoFree(lock);
+}
+
+// Unlock
+void NeoUnlock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisReleaseSpinLock(spin_lock);
+}
+
+// Lock
+void NeoLock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisAcquireSpinLock(spin_lock);
+}
+
+// Create a new lock
+NEO_LOCK *NeoNewLock()
+{
+ NDIS_SPIN_LOCK *spin_lock;
+
+ // Memory allocation
+ NEO_LOCK *lock = NeoZeroMalloc(sizeof(NEO_LOCK));
+ if (lock == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize spin lock
+ spin_lock = &lock->spin_lock;
+
+ NdisAllocateSpinLock(spin_lock);
+
+ return lock;
+}
+
+// Memory copy
+void NeoCopy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Copy
+ NdisMoveMemory(dst, src, size);
+}
+
+// Memory clear
+void NeoZero(void *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Clear
+ NdisZeroMemory(dst, size);
+}
+
+// Clear to zero by memory allocation
+void *NeoZeroMalloc(UINT size)
+{
+ void *p = NeoMalloc(size);
+ if (p == NULL)
+ {
+ // Memory allocation failure
+ return NULL;
+ }
+ // Clear to zero
+ NeoZero(p, size);
+ return p;
+}
+
+// Memory allocation
+void *NeoMalloc(UINT size)
+{
+ NDIS_STATUS r;
+ void *p;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ // Allocate the non-paged memory
+ r = NdisAllocateMemoryWithTag(&p, size, 0);
+
+ if (NG(r))
+ {
+ return NULL;
+ }
+ return p;
+}
+
+// Release the memory
+void NeoFree(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the memory
+ NdisFreeMemory(p, 0, 0);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo/NDIS5.h b/src/Neo/NDIS5.h
new file mode 100644
index 00000000..6e2139da
--- /dev/null
+++ b/src/Neo/NDIS5.h
@@ -0,0 +1,269 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NDIS5.h
+// Header of NDIS5.c
+
+#ifndef NDIS5_H
+#define NDIS5_H
+
+// Win32 DDK related
+#ifndef CPU_64
+#define _X86_
+#else // CPU_64
+#ifndef NEO_IA64
+#define _AMD64_
+#define AMD64
+#else // NEO_IA64
+#define _IA64_
+#define IA64
+#endif // NEO_IA64
+#endif // CPU_64
+#define NDIS_MINIPORT_DRIVER
+#ifndef WIN9X
+// Windows 2000 or later: NDIS 5.0
+#define NDIS50_MINIPORT
+#define NEO_NDIS_MAJOR_VERSION 5
+#define NEO_NDIS_MINOR_VERSION 0
+#else // WIN9X
+// Windows 9x: NDIS 4.0
+#define NDIS40_MINIPORT
+#define NEO_NDIS_MAJOR_VERSION 4
+#define NEO_NDIS_MINOR_VERSION 0
+#define BINARY_COMPATIBLE 1
+#endif // WIN9X
+#define NDIS_WDM 1
+
+#ifndef WIN9X
+#include <wdm.h>
+#include <ndis.h>
+#include <stdio.h>
+#include <string.h>
+#else // WIN9X
+#include <basedef.h>
+#define _LARGE_INTEGER DUMMY__LARGE_INTEGER
+#define LARGE_INTEGER DUMMY_LARGE_INTEGER
+#define PLARGE_INTEGER DUMMY_PLARGE_INTEGER
+#define _ULARGE_INTEGER DUMMY__ULARGE_INTEGER
+#define ULARGE_INTEGER DUMMY_ULARGE_INTEGER
+#define PULARGE_INTEGER DUMMY_PULARGE_INTEGER
+#define PSZ DUMMY_PSZ
+#include <ndis.h>
+#include <vmm.h>
+#include <vwin32.h>
+#include <stdio.h>
+#include <string.h>
+#undef _LARGE_INTEGER
+#undef LARGE_INTEGER
+#undef PLARGE_INTEGER
+#undef _ULARGE_INTEGER
+#undef ULARGE_INTEGER
+#undef PULARGE_INTEGER
+#undef PSZ
+#endif // WIN9X
+
+// Error checking macro
+#define OK(val) (val == STATUS_SUCCESS)
+#define NG(val) (!OK(val))
+
+// Constant
+static UINT SupportedOids[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_VENDOR_DRIVER_VERSION,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+ OID_802_3_MULTICAST_LIST,
+ //OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAXIMUM_SEND_PACKETS
+ };
+#define NEO_MEDIA NdisMedium802_3
+#define MAX_MULTICAST 32
+
+#define MAX_PATH 260
+#define MAX_SIZE 512
+#define STD_SIZE 512
+
+
+// Macro
+#define _NdisInitializeString(Destination,Source) \
+{\
+ PNDIS_STRING _D = (Destination);\
+ UCHAR *_S = (Source);\
+ WCHAR *_P;\
+ _D->Length = (USHORT)((strlen(_S)) * sizeof(WCHAR));\
+ _D->MaximumLength = _D->Length + sizeof(WCHAR);\
+ NdisAllocateMemoryWithTag((PVOID *)&(_D->Buffer), _D->MaximumLength, 0);\
+ _P = _D->Buffer;\
+ while(*_S != '\0'){\
+ *_P = (WCHAR)(*_S);\
+ _S++;\
+ _P++;\
+ }\
+ *_P = UNICODE_NULL;\
+}
+
+
+// Unicode string
+typedef struct _UNICODE
+{
+ UNICODE_STRING String;
+} UNICODE;
+
+typedef struct _PACKET_BUFFER PACKET_BUFFER;
+
+// Function prototype
+UNICODE *NewUnicode(char *str);
+void FreeUnicode(UNICODE *u);
+NDIS_STRING *GetUnicode(UNICODE *u);
+PACKET_BUFFER *NeoNewPacketBuffer();
+void NeoFreePacketBuffer(PACKET_BUFFER *p);
+void NeoInitPacketArray();
+void NeoFreePacketArray();
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath);
+NDIS_STATUS NeoNdisInit(NDIS_STATUS *OpenErrorStatus,
+ UINT *SelectedMediumIndex,
+ NDIS_MEDIUM *MediumArray,
+ UINT MediumArraySize,
+ NDIS_HANDLE MiniportAdapterHandle,
+ NDIS_HANDLE WrapperConfigurationContext);
+NDIS_STATUS NeoNdisHalt(NDIS_HANDLE MiniportAdapterContext);
+NDIS_STATUS NeoNdisReset(BOOLEAN *AddressingReset, NDIS_HANDLE MiniportAdapterContext);
+NDIS_STATUS NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesWritten,
+ ULONG *BytesNeeded);
+NDIS_STATUS NeoNdisSet(
+ NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesRead,
+ ULONG *BytesNeeded);
+void NeoNdisSendPackets(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_PACKET **PacketArray,
+ UINT NumberOfPackets);
+NDIS_STATUS NeoNdisSend(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_PACKET *Packet, UINT Flags);
+BOOL NeoNdisSendPacketsHaltCheck(NDIS_PACKET **PacketArray, UINT NumberOfPackets);
+BOOL NeoLoadRegistory();
+void NeoInitControlDevice();
+void NeoFreeControlDevice();
+NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp);
+void NeoCheckConnectState();
+void NeoSetConnectState(BOOL connected);
+BOOL NeoNdisOnOpen(IRP *irp, IO_STACK_LOCATION *stack);
+BOOL NeoNdisOnClose(IRP *irp, IO_STACK_LOCATION *stack);
+
+#endif // NDIS5_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo/Neo.c b/src/Neo/Neo.c
new file mode 100644
index 00000000..4b4a754a
--- /dev/null
+++ b/src/Neo/Neo.c
@@ -0,0 +1,442 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Neo.c
+// Driver main program
+
+#include <GlobalConst.h>
+
+#define NEO_DEVICE_DRIVER
+
+#include "Neo.h"
+
+// Whether Win8
+extern bool g_is_win8;
+
+// Neo driver context
+static NEO_CTX static_ctx;
+NEO_CTX *ctx = &static_ctx;
+
+// Read the packet data from the transmit packet queue
+void NeoRead(void *buf)
+{
+ NEO_QUEUE *q;
+ UINT num;
+ BOOL left;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Copy the packets one by one from the queue
+ num = 0;
+ left = TRUE;
+ NeoLockPacketQueue();
+ {
+ while (TRUE)
+ {
+ if (num >= NEO_MAX_PACKET_EXCHANGE)
+ {
+ if (ctx->PacketQueue == NULL)
+ {
+ left = FALSE;
+ }
+ break;
+ }
+ q = NeoGetNextQueue();
+ if (q == NULL)
+ {
+ left = FALSE;
+ break;
+ }
+ NEO_SIZE_OF_PACKET(buf, num) = q->Size;
+ NeoCopy(NEO_ADDR_OF_PACKET(buf, num), q->Buf, q->Size);
+ num++;
+ NeoFreeQueue(q);
+ }
+ }
+ NeoUnlockPacketQueue();
+
+ NEO_NUM_PACKET(buf) = num;
+ NEO_LEFT_FLAG(buf) = left;
+
+ if (left == FALSE)
+ {
+ NeoReset(ctx->Event);
+ }
+ else
+ {
+ NeoSet(ctx->Event);
+ }
+
+ return;
+}
+
+// Process the received packet
+void NeoWrite(void *buf)
+{
+ UINT num, i, size;
+ void *packet_buf;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Number of packets
+ num = NEO_NUM_PACKET(buf);
+ if (num > NEO_MAX_PACKET_EXCHANGE)
+ {
+ // Number of packets is too many
+ return;
+ }
+ if (num == 0)
+ {
+ // No packet
+ return;
+ }
+
+ if (ctx->Halting != FALSE)
+ {
+ // Halting
+ return;
+ }
+
+ if (ctx->Opened == FALSE)
+ {
+ // Not connected
+ return;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ PACKET_BUFFER *p = ctx->PacketBuffer[i];
+
+ size = NEO_SIZE_OF_PACKET(buf, i);
+ if (size > NEO_MAX_PACKET_SIZE)
+ {
+ size = NEO_MAX_PACKET_SIZE;
+ }
+ if (size < NEO_PACKET_HEADER_SIZE)
+ {
+ size = NEO_PACKET_HEADER_SIZE;
+ }
+
+ packet_buf = NEO_ADDR_OF_PACKET(buf, i);
+
+ // Buffer copy
+ NeoCopy(p->Buf, packet_buf, size);
+
+ if (g_is_win8 == false)
+ {
+ // Adjust the buffer size
+ NdisAdjustBufferLength(p->NdisBuffer, size);
+ // Set the packet information
+ NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES);
+ NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE);
+ }
+ else
+ {
+ NdisMEthIndicateReceive(ctx->NdisMiniport, ctx,
+ p->Buf, NEO_PACKET_HEADER_SIZE,
+ ((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE,
+ size - NEO_PACKET_HEADER_SIZE);
+ NdisMEthIndicateReceiveComplete(ctx->NdisMiniport);
+ }
+ }
+
+ // Notify that packets have received
+ ctx->Status.NumPacketRecv += num;
+
+ if (g_is_win8 == false)
+ {
+ NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num);
+ }
+}
+
+// Get the number of queue items
+UINT NeoGetNumQueue()
+{
+ return ctx->NumPacketQueue;
+}
+
+// Insert the queue
+void NeoInsertQueue(void *buf, UINT size)
+{
+ NEO_QUEUE *p;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Prevent the packet accumulation in large quantities in the queue
+ if (ctx->NumPacketQueue > NEO_MAX_PACKET_QUEUED)
+ {
+ NeoFree(buf);
+ return;
+ }
+
+ // Create a queue
+ p = NeoMalloc(sizeof(NEO_QUEUE));
+ p->Next = NULL;
+ p->Size = size;
+ p->Buf = buf;
+
+ // Append to the queue
+ if (ctx->PacketQueue == NULL)
+ {
+ ctx->PacketQueue = p;
+ }
+ else
+ {
+ NEO_QUEUE *q = ctx->Tail;
+ q->Next = p;
+ }
+
+ ctx->Tail = p;
+
+ ctx->NumPacketQueue++;
+}
+
+// Get the next queued item
+NEO_QUEUE *NeoGetNextQueue()
+{
+ NEO_QUEUE *q;
+ if (ctx->PacketQueue == NULL)
+ {
+ // No item queued
+ return NULL;
+ }
+
+ // Get the next queued item
+ q = ctx->PacketQueue;
+ ctx->PacketQueue = ctx->PacketQueue->Next;
+ q->Next = NULL;
+ ctx->NumPacketQueue--;
+
+ if (ctx->PacketQueue == NULL)
+ {
+ ctx->Tail = NULL;
+ }
+
+ return q;
+}
+
+// Release the buffer queue
+void NeoFreeQueue(NEO_QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+ NeoFree(q->Buf);
+ NeoFree(q);
+}
+
+// Lock the packet queue
+void NeoLockPacketQueue()
+{
+ NeoLock(ctx->PacketQueueLock);
+}
+
+// Unlock the packet queue
+void NeoUnlockPacketQueue()
+{
+ NeoUnlock(ctx->PacketQueueLock);
+}
+
+// Initialize the packet queue
+void NeoInitPacketQueue()
+{
+ // Create a lock
+ ctx->PacketQueueLock = NeoNewLock();
+ // Initialize the packet queue
+ ctx->PacketQueue = NULL;
+ ctx->NumPacketQueue = 0;
+ ctx->Tail = NULL;
+}
+
+// Delete all the packets from the packet queue
+void NeoClearPacketQueue()
+{
+ // Release the memory of the packet queue
+ NeoLock(ctx->PacketQueueLock);
+ {
+ NEO_QUEUE *q = ctx->PacketQueue;
+ NEO_QUEUE *qn;
+ while (q != NULL)
+ {
+ qn = q->Next;
+ NeoFree(q->Buf);
+ NeoFree(q);
+ q = qn;
+ }
+ ctx->PacketQueue = NULL;
+ ctx->Tail = NULL;
+ ctx->NumPacketQueue = 0;
+ }
+ NeoUnlock(ctx->PacketQueueLock);
+}
+
+// Release the packet queue
+void NeoFreePacketQueue()
+{
+ // Delete all packets
+ NeoClearPacketQueue();
+
+ // Delete the lock
+ NeoFreeLock(ctx->PacketQueueLock);
+ ctx->PacketQueueLock = NULL;
+}
+
+// Start the adapter
+void NeoStartAdapter()
+{
+ // Initialize the packet queue
+ NeoInitPacketQueue();
+}
+
+// Stop the adapter
+void NeoStopAdapter()
+{
+ // Delete the packet queue
+ NeoFreePacketQueue();
+}
+
+// Initialization
+BOOL NeoInit()
+{
+ // Initialize the context
+ NeoZero(ctx, sizeof(NEO_CTX));
+
+ // Initialize the status information
+ NeoNewStatus(&ctx->Status);
+
+ return TRUE;
+}
+
+// Shutdown
+void NeoShutdown()
+{
+ if (ctx == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Relaese the status information
+ NeoFreeStatus(&ctx->Status);
+
+ NeoZero(ctx, sizeof(NEO_CTX));
+}
+
+// Create a status information
+void NeoNewStatus(NEO_STATUS *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory initialization
+ NeoZero(s, sizeof(NEO_STATUS));
+}
+
+// Release the status information
+void NeoFreeStatus(NEO_STATUS *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory initialization
+ NeoZero(s, sizeof(NEO_STATUS));
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo/Neo.h b/src/Neo/Neo.h
new file mode 100644
index 00000000..9ec21a2e
--- /dev/null
+++ b/src/Neo/Neo.h
@@ -0,0 +1,313 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Neo.h
+// Header of Neo.c
+
+#ifndef NEO_H
+#define NEO_H
+
+
+// Identification string (NDIS)
+#define NDIS_NEO_HARDWARE_ID "VPN Client Adapter - %s"
+#define NDIS_NEO_DEVICE_NAME "\\Device\\NEO_%s_DEVICE"
+#define NDIS_NEO_DEVICE_NAME_WIN32 "\\DosDevices\\NEO_%s_DEVICE"
+#define NDIS_NEO_DEVICE_FILE_NAME "\\\\.\\NEO_NEOADAPTER_%s_DEVICE"
+#define NDIS_NEO_EVENT_NAME "\\BaseNamedObjects\\NEO_EVENT_%s"
+#define NDIS_NEO_EVENT_NAME_WIN32 "Global\\NEO_EVENT_NEOADAPTER_%s"
+
+// Constant
+#define NEO_MAX_PACKET_SIZE 1560
+#define NEO_MAX_PACKET_SIZE_ANNOUNCE 1514
+#define NEO_MIN_PACKET_SIZE 14
+#define NEO_PACKET_HEADER_SIZE 14
+#define NEO_MAX_FRAME_SIZE (NEO_MAX_PACKET_SIZE - NEO_MIN_PACKET_SIZE)
+#define NEO_MAX_SPEED_DEFAULT 1000000
+#define NEO_MAC_ADDRESS_SIZE 6
+#define NEO_MAX_MULTICASE 32
+
+
+// IOCTL constant
+#define NEO_IOCTL_SET_EVENT CTL_CODE(0x8000, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define NEO_IOCTL_PUT_PACKET CTL_CODE(0x8000, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define NEO_IOCTL_GET_PACKET CTL_CODE(0x8000, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+// Packet data exchange related
+#define NEO_MAX_PACKET_EXCHANGE 256 // Number of packets that can be exchanged at a time
+#define NEO_MAX_PACKET_QUEUED 4096 // Maximum number of packets that can be queued
+#define NEO_EX_SIZEOF_NUM_PACKET 4 // Packet count data (UINT)
+#define NEO_EX_SIZEOF_LENGTH_PACKET 4 // Length data of the packet data (UINT)
+#define NEO_EX_SIZEOF_LEFT_FLAG 4 // Flag to indicate that the packet is still
+#define NEO_EX_SIZEOF_ONE_PACKET 1600 // Data area occupied by a packet data
+#define NEO_EXCHANGE_BUFFER_SIZE (NEO_EX_SIZEOF_NUM_PACKET + NEO_EX_SIZEOF_LEFT_FLAG + \
+ (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET) * (NEO_MAX_PACKET_EXCHANGE + 1))
+#define NEO_NUM_PACKET(buf) (*((UINT *)((UCHAR *)buf + 0)))
+#define NEO_SIZE_OF_PACKET(buf, i) (*((UINT *)((UCHAR *)buf + NEO_EX_SIZEOF_NUM_PACKET + \
+ (i * (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET)))))
+#define NEO_ADDR_OF_PACKET(buf, i) (((UINT *)((UCHAR *)buf + NEO_EX_SIZEOF_NUM_PACKET + \
+ NEO_EX_SIZEOF_LENGTH_PACKET + \
+ (i * (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET)))))
+#define NEO_LEFT_FLAG(buf) NEO_SIZE_OF_PACKET(buf, NEO_MAX_PACKET_EXCHANGE)
+
+
+
+// Definitions needed to compile as a device driver
+#ifdef NEO_DEVICE_DRIVER
+
+// OS determination
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX / Linux
+#endif
+
+
+// Type declaration
+#ifndef WINDOWS_H_INCLUDED
+#ifndef WIN9X
+typedef unsigned long BOOL;
+#endif // WIN9X
+#define TRUE 1
+#define FALSE 0
+#endif
+typedef unsigned long bool;
+#define true 1
+#define false 0
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef signed char CHAR;
+typedef unsigned long DWORD;
+#define INFINITE 0xFFFFFFFF
+
+#define LESS(a, max_value) ((a) < (max_value) ? (a) : (max_value))
+#define MORE(a, min_value) ((a) > (min_value) ? (a) : (min_value))
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+
+#ifdef OS_WIN32
+// NDIS 5.0 related
+#include "NDIS5.h"
+#endif // OS_WIN32
+
+// Lock
+typedef struct _NEO_LOCK
+{
+#ifdef OS_WIN32
+ NDIS_SPIN_LOCK spin_lock;
+#endif
+} NEO_LOCK;
+
+// Event
+typedef struct _NEO_EVENT
+{
+#ifdef OS_WIN32
+#ifndef WIN9X
+ KEVENT *event;
+ HANDLE event_handle;
+#else // WIN9X
+ DWORD win32_event;
+#endif // WIN9X
+#endif
+} NEO_EVENT;
+
+// Packet queue
+typedef struct _NEO_QUEUE
+{
+ struct _NEO_QUEUE *Next;
+ UINT Size;
+ void *Buf;
+} NEO_QUEUE;
+
+// Status
+typedef struct _NEO_STATUS
+{
+ UINT NumPacketSend;
+ UINT NumPacketRecv;
+ UINT NumPacketSendError;
+ UINT NumPacketRecvError;
+ UINT NumPacketRecvNoBuffer;
+} NEO_STATUS;
+
+// NDIS packet buffer
+typedef struct _PACKET_BUFFER
+{
+ void *Buf; // Buffer
+ NDIS_PACKET *NdisPacket; // NDIS packet
+ NDIS_BUFFER *NdisBuffer; // NDIS packet buffer
+ NDIS_HANDLE PacketPool; // Packet pool
+ NDIS_HANDLE BufferPool; // Buffer pool
+} PACKET_BUFFER;
+
+// Context
+typedef struct _NEO_CTX
+{
+ NEO_EVENT *Event; // Packet reception notification event
+ BOOL Opened; // Flag of whether opened
+ BOOL Inited; // Initialization flag
+ BOOL Initing; // Starting-up flag
+ volatile BOOL Halting; // Halting flag
+ BYTE MacAddress[6]; // MAC address
+ BYTE padding[2]; // padding
+ NEO_QUEUE *PacketQueue; // Transmission packet queue
+ NEO_QUEUE *Tail; // Tail of the transmission packet queue
+ UINT NumPacketQueue; // Number of queued packet
+ NEO_LOCK *PacketQueueLock; // Transmission packet queue lock
+ NEO_STATUS Status; // Status
+ UINT CurrentPacketFilter; // Current packet filter value
+ UINT CurrentProtocolOptions; // Current protocol option value
+ BOOL Connected, ConnectedOld; // Cable connection state
+ BOOL ConnectedForce; // Connection state forcibly notification
+#ifdef OS_WIN32
+ NDIS_HANDLE NdisWrapper; // NDIS wrapper handle
+ NDIS_HANDLE NdisControl; // NDIS control handle
+ NDIS_HANDLE NdisMiniport; // NDIS miniport handle
+ NDIS_HANDLE NdisContext; // NDIS context handle
+ NDIS_HANDLE NdisConfig; // NDIS Config handle
+ DEVICE_OBJECT *NdisControlDevice; // NDIS control device
+ PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION];
+ PACKET_BUFFER *PacketBuffer[NEO_MAX_PACKET_EXCHANGE]; // NDIS packet buffer
+ NDIS_PACKET *PacketBufferArray[NEO_MAX_PACKET_EXCHANGE]; // NDIS packet buffer array
+ NDIS_HARDWARE_STATUS HardwareStatus; // Hardware state
+ char HardwareID[MAX_SIZE]; // Hardware ID
+ char HardwareID_Raw[MAX_SIZE]; // Original hardware ID
+ char HardwarePrintableID[MAX_SIZE]; // Hardware ID (for display)
+#endif
+} NEO_CTX;
+
+extern NEO_CTX *ctx;
+
+
+// Neo.c routine
+void NeoNewStatus(NEO_STATUS *s);
+void NeoFreeStatus(NEO_STATUS *s);
+BOOL NeoInit();
+void NeoShutdown();
+void NeoInitPacketQueue();
+void NeoFreePacketQueue();
+void NeoClearPacketQueue();
+void NeoLockPacketQueue();
+void NeoUnlockPacketQueue();
+NEO_QUEUE *NeoGetNextQueue();
+void NeoFreeQueue(NEO_QUEUE *q);
+void NeoInsertQueue(void *buf, UINT size);
+UINT NeoGetNumQueue();
+void NeoStartAdapter();
+void NeoStopAdapter();
+void NeoRead(void *buf);
+void NeoWrite(void *buf);
+
+// Common routine (platform dependent)
+void *NeoMalloc(UINT size);
+void *NeoZeroMalloc(UINT size);
+void NeoFree(void *p);
+void NeoCopy(void *dst, void *src, UINT size);
+void NeoZero(void *dst, UINT size);
+NEO_LOCK *NeoNewLock();
+void NeoLock(NEO_LOCK *lock);
+void NeoUnlock(NEO_LOCK *lock);
+void NeoFreeLock(NEO_LOCK *lock);
+NEO_EVENT *NeoNewEvent(char *name);
+NEO_EVENT *NeoCreateWin9xEvent(DWORD h);
+void NeoFreeEvent(NEO_EVENT *event);
+void NeoSet(NEO_EVENT *event);
+void NeoReset(NEO_EVENT *event);
+BOOL NeoIsKernelAddress(void *addr);
+
+#endif // NEO_DEVICE_DRIVER
+
+
+#endif // NEO_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo/Neo.rc b/src/Neo/Neo.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/Neo/Neo.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/Neo/Neo.vcproj b/src/Neo/Neo.vcproj
new file mode 100644
index 00000000..d44fa47f
--- /dev/null
+++ b/src/Neo/Neo.vcproj
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Neo"
+ ProjectGUID="{D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}"
+ RootNamespace="Neo"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\wnet\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib wdmsec.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\vpn_driver.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\wnet\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib wdmsec.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\vpn_driver_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\NDIS5.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Neo.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\NDIS5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Neo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Neo.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Neo/resource.h b/src/Neo/resource.h
new file mode 100644
index 00000000..1fdda11a
--- /dev/null
+++ b/src/Neo/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Neo.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo6/NDIS6.c b/src/Neo6/NDIS6.c
new file mode 100644
index 00000000..bb9e8b35
--- /dev/null
+++ b/src/Neo6/NDIS6.c
@@ -0,0 +1,1745 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NDIS6.c
+// Windows NDIS 6.2 Routine
+
+#include <GlobalConst.h>
+
+#define NEO_DEVICE_DRIVER
+
+#include "Neo6.h"
+
+static UINT64 max_speed = NEO_MAX_SPEED_DEFAULT;
+static bool keep_link = false;
+
+BOOLEAN
+PsGetVersion(
+ PULONG MajorVersion OPTIONAL,
+ PULONG MinorVersion OPTIONAL,
+ PULONG BuildNumber OPTIONAL,
+ PUNICODE_STRING CSDVersion OPTIONAL
+ );
+
+// Memory related
+static NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+NDIS_HANDLE ndis_miniport_driver_handle = NULL;
+
+// Flag for whether Windows 8
+bool g_is_win8 = false;
+
+// Win32 driver entry point
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
+{
+ NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniport;
+ ULONG os_major_ver = 0, os_minor_ver = 0;
+ NDIS_STATUS ret;
+
+ // Initialize the Neo library
+ if (NeoInit() == FALSE)
+ {
+ // Initialization Failed
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ g_is_win8 = false;
+
+ // Get the OS version
+ PsGetVersion(&os_major_ver, &os_minor_ver, NULL, NULL);
+
+ if (os_major_ver >= 7 || (os_major_ver == 6 && os_minor_ver >= 2))
+ {
+ // Windows 8
+ g_is_win8 = true;
+ }
+
+ // Register a NDIS miniport driver
+ NeoZero(&miniport, sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS));
+
+ miniport.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
+ miniport.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
+ miniport.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
+
+ miniport.MajorNdisVersion = NEO_NDIS_MAJOR_VERSION;
+ miniport.MinorNdisVersion = NEO_NDIS_MINOR_VERSION;
+
+ // Register the handler
+ miniport.InitializeHandlerEx = NeoNdisInitEx;
+ miniport.HaltHandlerEx = NeoNdisHaltEx;
+ miniport.OidRequestHandler = NeoNdisOidRequest;
+ miniport.ResetHandlerEx = NeoNdisResetEx;
+ miniport.CheckForHangHandlerEx = NeoNdisCheckForHangEx;
+ miniport.UnloadHandler = NeoNdisDriverUnload;
+ miniport.SendNetBufferListsHandler = NeoNdisSendNetBufferLists;
+
+ miniport.SetOptionsHandler = NeoNdisSetOptions;
+ miniport.PauseHandler = NeoNdisPause;
+ miniport.RestartHandler = NeoNdisRestart;
+ miniport.ReturnNetBufferListsHandler = NeoNdisReturnNetBufferLists;
+ miniport.CancelSendHandler = NeoNdisCancelSend;
+ miniport.DevicePnPEventNotifyHandler = NeoNdisDevicePnPEventNotify;
+ miniport.ShutdownHandlerEx = NeoNdisShutdownEx;
+ miniport.CancelOidRequestHandler = NeoNdisCancelOidRequest;
+
+ ret = NdisMRegisterMiniportDriver(DriverObject, RegistryPath,
+ NULL, &miniport, &ndis_miniport_driver_handle);
+
+ if (NG(ret))
+ {
+ // Registration failure
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Initialization success
+ return STATUS_SUCCESS;
+}
+
+NDIS_STATUS NeoNdisSetOptions(NDIS_HANDLE NdisDriverHandle, NDIS_HANDLE DriverContext)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+
+NDIS_STATUS NeoNdisPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+
+NDIS_STATUS NeoNdisRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+
+void NeoNdisReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags)
+{
+}
+
+void NeoNdisCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId)
+{
+}
+
+void NeoNdisDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext, PNET_DEVICE_PNP_EVENT NetDevicePnPEvent)
+{
+}
+
+void NeoNdisShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownAction)
+{
+}
+
+void NeoNdisCancelOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId)
+{
+}
+
+// Initialization handler of adapter
+NDIS_STATUS NeoNdisInitEx(NDIS_HANDLE MiniportAdapterHandle,
+ NDIS_HANDLE MiniportDriverContext,
+ PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)
+{
+ NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES attr;
+ NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gen;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if (ctx->NdisMiniportDriverHandle == NULL)
+ {
+ ctx->NdisMiniportDriverHandle = ndis_miniport_driver_handle;
+ }
+
+ // Prevention of multiple start
+ if (ctx->Initing != FALSE)
+ {
+ // Multiple started
+ return NDIS_STATUS_FAILURE;
+ }
+ ctx->Initing = TRUE;
+
+ // Examine whether it has already been initialized
+ if (ctx->Inited != FALSE)
+ {
+ // Driver is started on another instance already.
+ // VPN driver can start only one instance per one service.
+ // User can start multiple drivers with different instance ID
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Current value of the packet filter
+ ctx->CurrentPacketFilter = NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
+
+ // Initialize the adapter information
+ ctx->NdisMiniport = MiniportAdapterHandle;
+ ctx->NdisContext = ctx;
+ ctx->HardwareStatus = NdisHardwareStatusReady;
+ ctx->Halting = FALSE;
+ ctx->Connected = ctx->ConnectedOld = FALSE;
+
+ if (keep_link == false)
+ {
+ ctx->ConnectedForce = TRUE;
+ }
+
+ // Read the information from the registry
+ if (NeoLoadRegistory() == FALSE)
+ {
+ // Failure
+ ctx->Initing = FALSE;
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Register the device attributes
+ NeoZero(&attr, sizeof(attr));
+ attr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+ attr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+ attr.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+ attr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
+ attr.InterfaceType = NdisInterfaceInternal;
+ attr.MiniportAdapterContext = ctx->NdisContext;
+
+ NdisMSetMiniportAttributes(ctx->NdisMiniport, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&attr);
+
+ NeoZero(&gen, sizeof(gen));
+ gen.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+ gen.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
+ gen.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
+ gen.MediaType = NdisMedium802_3;
+ gen.PhysicalMediumType = NdisPhysicalMedium802_3;
+ gen.MtuSize = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ gen.MaxXmitLinkSpeed = gen.MaxRcvLinkSpeed = max_speed;
+ gen.RcvLinkSpeed = gen.XmitLinkSpeed = max_speed;
+ gen.MediaConnectState = MediaConnectStateDisconnected;
+ gen.LookaheadSize = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ gen.MacOptions = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK;
+ gen.SupportedPacketFilters = NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
+ gen.MaxMulticastListSize = NEO_MAX_MULTICASE;
+ gen.MacAddressLength = NEO_MAC_ADDRESS_SIZE;
+ NeoCopy(gen.PermanentMacAddress, ctx->MacAddress, NEO_MAC_ADDRESS_SIZE);
+ NeoCopy(gen.CurrentMacAddress, ctx->MacAddress, NEO_MAC_ADDRESS_SIZE);
+ gen.AccessType = NET_IF_ACCESS_BROADCAST;
+ gen.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
+ gen.ConnectionType = NET_IF_CONNECTION_DEDICATED;
+ gen.IfType = IF_TYPE_ETHERNET_CSMACD;
+ gen.IfConnectorPresent = TRUE;
+ gen.SupportedStatistics =
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |
+ NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
+ gen.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
+ gen.AutoNegotiationFlags = NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED |
+ NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED |
+ NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED |
+ NDIS_LINK_STATE_PAUSE_FUNCTIONS_AUTO_NEGOTIATED;
+ gen.SupportedOidList = SupportedOids;
+ gen.SupportedOidListLength = sizeof(SupportedOids);
+
+ NdisMSetMiniportAttributes(ctx->NdisMiniport, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gen);
+
+ // Initialize the received packet array
+ NeoInitPacketArray();
+
+ // Initialize the control device
+ NeoInitControlDevice();
+
+ // Start the adapter
+ NeoStartAdapter();
+
+ // Flag setting
+ ctx->Initing = FALSE;
+ ctx->Inited = TRUE;
+
+ // Notify the connection state
+ NeoSetConnectState(FALSE);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Open the device
+BOOL NeoNdisOnOpen(IRP *irp, IO_STACK_LOCATION *stack)
+{
+ char name[MAX_SIZE];
+
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Opened != FALSE)
+ {
+ // Another client is connected already
+ return FALSE;
+ }
+ ctx->Opened = TRUE;
+
+ // Initialize the event name
+ sprintf(name, NDIS_NEO_EVENT_NAME, ctx->HardwareID);
+
+ // Register a Event
+ ctx->Event = NeoNewEvent(name);
+ if (ctx->Event == NULL)
+ {
+ ctx->Opened = FALSE;
+ return FALSE;
+ }
+
+ // Set the connection state
+ NeoSetConnectState(TRUE);
+
+ return TRUE;
+}
+
+// Close the device
+BOOL NeoNdisOnClose(IRP *irp, IO_STACK_LOCATION *stack)
+{
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Opened == FALSE)
+ {
+ // Client is not connected
+ return FALSE;
+ }
+ ctx->Opened = FALSE;
+
+ // Release the event
+ NeoFreeEvent(ctx->Event);
+ ctx->Event = NULL;
+
+ // Release all packets
+ NeoClearPacketQueue();
+
+ NeoSetConnectState(FALSE);
+
+ return TRUE;
+}
+
+// Crash 2
+void NeoNdisCrash2(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+// Crash
+void NeoNdisCrash()
+{
+ NEO_QUEUE *q;
+ q = (NEO_QUEUE *)0xACACACAC;
+ q->Size = 128;
+ NeoCopy(q->Buf, "ABCDEFG", 8);
+}
+
+// Dispatch table for control
+NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
+{
+ NTSTATUS status;
+ IO_STACK_LOCATION *stack;
+ void *buf;
+ BOOL ok;
+ status = STATUS_SUCCESS;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Get the IRP stack
+ stack = IoGetCurrentIrpStackLocation(Irp);
+
+ // Initialize the number of bytes
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ buf = Irp->UserBuffer;
+
+ if (ctx->Halting != FALSE)
+ {
+ // Device driver is terminating
+ Irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Branch to each operation
+ switch (stack->MajorFunction)
+ {
+ case IRP_MJ_CREATE:
+ // Device is opened
+ if (NeoNdisOnOpen(Irp, stack) == FALSE)
+ {
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case IRP_MJ_CLOSE:
+ // Device is closed
+ if (NeoNdisOnClose(Irp, stack) == FALSE)
+ {
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case IRP_MJ_READ:
+ // Read (Reading of the received packet)
+ ok = false;
+ if (buf != NULL)
+ {
+ if (ctx->Opened && ctx->Inited)
+ {
+ if (stack->Parameters.Read.Length == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Address check
+ MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ if (NeoIsKernelAddress(buf) == FALSE)
+ {
+ // Read
+ NeoRead(buf);
+ Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE;
+ ok = true;
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ if (ok == FALSE)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case IRP_MJ_WRITE:
+ // Write (Writing of a transmission packet)
+ ok = false;
+ if (buf != NULL)
+ {
+ if (ctx->Opened && ctx->Inited)
+ {
+ if (stack->Parameters.Write.Length == NEO_EXCHANGE_BUFFER_SIZE)
+ {
+ // Address check
+ MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
+ }
+
+ if (NeoIsKernelAddress(buf) == FALSE)
+ {
+ // Write
+ NeoWrite(buf);
+ Irp->IoStatus.Information = stack->Parameters.Write.Length;
+ ok = true;
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ if (ok == FALSE)
+ {
+ // An error occurred
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+}
+
+// Initialize the control device
+void NeoInitControlDevice()
+{
+ char name_kernel[MAX_SIZE];
+ char name_win32[MAX_SIZE];
+ UNICODE *unicode_kernel, *unicode_win32;
+ DEVICE_OBJECT *control_device_object;
+ NDIS_HANDLE ndis_control_handle;
+ NDIS_DEVICE_OBJECT_ATTRIBUTES t;
+
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ // Initialize the dispatch table
+ NeoZero(ctx->DispatchTable, sizeof(PDRIVER_DISPATCH) * IRP_MJ_MAXIMUM_FUNCTION);
+
+ // Register the handler
+ ctx->DispatchTable[IRP_MJ_CREATE] =
+ ctx->DispatchTable[IRP_MJ_CLOSE] =
+ ctx->DispatchTable[IRP_MJ_READ] =
+ ctx->DispatchTable[IRP_MJ_WRITE] =
+ ctx->DispatchTable[IRP_MJ_DEVICE_CONTROL] = NeoNdisDispatch;
+ ctx->Opened = FALSE;
+
+ // Generate the device name
+ sprintf(name_kernel, NDIS_NEO_DEVICE_NAME, ctx->HardwareID);
+ unicode_kernel = NewUnicode(name_kernel);
+ sprintf(name_win32, NDIS_NEO_DEVICE_NAME_WIN32, ctx->HardwareID);
+ unicode_win32 = NewUnicode(name_win32);
+
+ // Register the device
+ NeoZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
+ t.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
+ t.Header.Size = NDIS_SIZEOF_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
+ t.DeviceName = GetUnicode(unicode_kernel);
+ t.SymbolicName = GetUnicode(unicode_win32);
+ t.MajorFunctions = ctx->DispatchTable;
+
+ NdisRegisterDeviceEx(ndis_miniport_driver_handle, &t,
+ &control_device_object,
+ &ndis_control_handle);
+
+ ctx->NdisControlDevice = control_device_object;
+ ctx->NdisControl = ndis_control_handle;
+
+ // Initialize the display name
+ if (strlen(ctx->HardwareID) > 11)
+ {
+ sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw + 11);
+ }
+ else
+ {
+ sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw);
+ }
+}
+
+// Release the control device
+void NeoFreeControlDevice()
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ if (ctx->Opened != FALSE)
+ {
+ // Delete the event
+ NeoSet(ctx->Event);
+ NeoFreeEvent(ctx->Event);
+ ctx->Event = NULL;
+ ctx->Opened = FALSE;
+ }
+
+ // Delete the device
+ NdisDeregisterDeviceEx(ctx->NdisControl);
+}
+
+
+// Read the information from the registry
+BOOL NeoLoadRegistory()
+{
+ void *buf;
+ NDIS_STATUS ret;
+ UINT size;
+ NDIS_HANDLE config;
+ NDIS_CONFIGURATION_PARAMETER *param;
+ UNICODE *name;
+ ANSI_STRING ansi;
+ UNICODE_STRING *unicode;
+ UINT64 speed;
+ BOOL keep;
+ NDIS_CONFIGURATION_OBJECT config_obj;
+
+ // Get the Config handle
+ NeoZero(&config_obj, sizeof(config_obj));
+ config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+ config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+ config_obj.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+ config_obj.NdisHandle = ctx->NdisMiniport;
+
+ ret = NdisOpenConfigurationEx(&config_obj, &config);
+ if (NG(ret))
+ {
+ // Failure
+ return FALSE;
+ }
+
+ // Read the MAC address
+ NdisReadNetworkAddress(&ret, &buf, &size, config);
+ if (NG(ret))
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+
+ // Copy the MAC address
+ if (size != NEO_MAC_ADDRESS_SIZE)
+ {
+ // Invalid size
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ NeoCopy(ctx->MacAddress, buf, NEO_MAC_ADDRESS_SIZE);
+
+ if (ctx->MacAddress[0] == 0x00 &&
+ ctx->MacAddress[1] == 0x00 &&
+ ctx->MacAddress[2] == 0x01 &&
+ ctx->MacAddress[3] == 0x00 &&
+ ctx->MacAddress[4] == 0x00 &&
+ ctx->MacAddress[5] == 0x01)
+ {
+ // Special MAC address
+ UINT ptr32 = (UINT)((UINT64)ctx);
+
+ ctx->MacAddress[0] = 0x00;
+ ctx->MacAddress[1] = 0xAD;
+ ctx->MacAddress[2] = ((UCHAR *)(&ptr32))[0];
+ ctx->MacAddress[3] = ((UCHAR *)(&ptr32))[1];
+ ctx->MacAddress[4] = ((UCHAR *)(&ptr32))[2];
+ ctx->MacAddress[5] = ((UCHAR *)(&ptr32))[3];
+ }
+
+ // Initialize the key name of the device name
+ name = NewUnicode("MatchingDeviceId");
+
+ // Read the hardware ID
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterString);
+ FreeUnicode(name);
+ if (NG(ret))
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ // Type checking
+ if (param->ParameterType != NdisParameterString)
+ {
+ // Failure
+ NdisCloseConfiguration(config);
+ return FALSE;
+ }
+ unicode = &param->ParameterData.StringData;
+
+ // Prepare a buffer for ANSI string
+ NeoZero(&ansi, sizeof(ANSI_STRING));
+ ansi.MaximumLength = MAX_SIZE - 1;
+ ansi.Buffer = NeoZeroMalloc(MAX_SIZE);
+
+ // Convert to ANSI string
+ NdisUnicodeStringToAnsiString(&ansi, unicode);
+ // Copy
+ strcpy(ctx->HardwareID, ansi.Buffer);
+ strcpy(ctx->HardwareID_Raw, ctx->HardwareID);
+ // Convert to upper case
+ _strupr(ctx->HardwareID);
+ // Release the memory
+ NeoFree(ansi.Buffer);
+
+ // Read the bit rate
+ name = NewUnicode("MaxSpeed");
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
+ FreeUnicode(name);
+
+ if (NG(ret) || param->ParameterType != NdisParameterInteger)
+ {
+ speed = NEO_MAX_SPEED_DEFAULT;
+ }
+ else
+ {
+ speed = (UINT64)param->ParameterData.IntegerData * 1000000ULL;
+ }
+
+ max_speed = speed;
+
+ // Read the link keeping flag
+ name = NewUnicode("KeepLink");
+ NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
+ FreeUnicode(name);
+
+ if (NG(ret) || param->ParameterType != NdisParameterInteger)
+ {
+ keep = false;
+ }
+ else
+ {
+ keep = (param->ParameterData.IntegerData == 0 ? false : true);
+ }
+
+ keep_link = keep;
+
+ // Close the config handle
+ NdisCloseConfiguration(config);
+
+ return TRUE;
+}
+
+// Unload the driver
+VOID NeoNdisDriverUnload(PDRIVER_OBJECT DriverObject)
+{
+ NdisMDeregisterMiniportDriver(ndis_miniport_driver_handle);
+}
+
+// Stop handler of adapter
+void NeoNdisHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction)
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ if (ctx->Halting != FALSE)
+ {
+ // That has already been stopped
+ return;
+ }
+ ctx->Halting = TRUE;
+
+ // Stop the adapter
+ NeoStopAdapter();
+
+ // Release the packet array
+ NeoFreePacketArray();
+
+ // Delete the control device
+ NeoFreeControlDevice();
+
+ // Complete to stop
+ ctx->Initing = ctx->Inited = FALSE;
+ ctx->Connected = ctx->ConnectedForce = ctx->ConnectedOld = FALSE;
+ ctx->Halting = FALSE;
+
+ // Shutdown of Neo
+ NeoShutdown();
+}
+
+// Reset handler of adapter
+NDIS_STATUS NeoNdisResetEx(NDIS_HANDLE MiniportAdapterContext, PBOOLEAN AddressingReset)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Hang-up check handler of adapter
+BOOLEAN NeoNdisCheckForHangEx(NDIS_HANDLE MiniportAdapterContext)
+{
+ return FALSE;
+}
+
+// OID request handler
+NDIS_STATUS NeoNdisOidRequest(NDIS_HANDLE MiniportAdapterContext,
+ PNDIS_OID_REQUEST OidRequest)
+{
+ NDIS_STATUS ret = STATUS_UNSUCCESSFUL;
+ ULONG dummy = 0;
+
+ switch (OidRequest->RequestType)
+ {
+ case NdisRequestQueryInformation:
+ case NdisRequestQueryStatistics:
+ ret = NeoNdisQuery(MiniportAdapterContext,
+ OidRequest->DATA.QUERY_INFORMATION.Oid,
+ OidRequest->DATA.QUERY_INFORMATION.InformationBuffer,
+ OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
+ &OidRequest->DATA.QUERY_INFORMATION.BytesWritten,
+ &OidRequest->DATA.QUERY_INFORMATION.BytesNeeded);
+ break;
+
+ case NdisRequestSetInformation:
+ ret = NeoNdisSet(MiniportAdapterContext,
+ OidRequest->DATA.SET_INFORMATION.Oid,
+ OidRequest->DATA.SET_INFORMATION.InformationBuffer,
+ OidRequest->DATA.SET_INFORMATION.InformationBufferLength,
+ &dummy,
+ &OidRequest->DATA.SET_INFORMATION.BytesNeeded);
+ break;
+
+ default:
+ ret = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ return ret;
+}
+
+
+// Information acquisition handler of adapter
+NDIS_STATUS NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesWritten,
+ ULONG *BytesNeeded)
+{
+ NDIS_MEDIUM media;
+ void *buf;
+ UINT value32;
+ USHORT value16;
+ UINT size;
+ NDIS_STATISTICS_INFO stat;
+ NDIS_INTERRUPT_MODERATION_PARAMETERS intp;
+
+ if (ctx == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Initialization
+ size = sizeof(UINT);
+ value32 = value16 = 0;
+ buf = &value32;
+
+ // Branch processing
+ switch (Oid)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+ // Return a list of supported OID
+ buf = SupportedOids;
+ size = sizeof(SupportedOids);
+ break;
+
+ case OID_GEN_MAC_OPTIONS:
+ // Ethernet option
+ value32 = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK;
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+ // Hardware state
+ buf = &ctx->HardwareStatus;
+ size = sizeof(NDIS_HARDWARE_STATUS);
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ // Type of media
+ media = NdisMedium802_3;
+ buf = &media;
+ size = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ // Read-ahead available size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ // Maximum frame size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
+ break;
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ // Maximum packet size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE;
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ // Buffer size
+ value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE * NEO_MAX_PACKET_EXCHANGE;
+ break;
+
+ case OID_GEN_LINK_SPEED:
+ // Communication speed
+ value32 = (UINT)(max_speed / 100);
+ break;
+
+ case OID_GEN_VENDOR_ID:
+ // Vendor ID
+ NeoCopy(&value32, ctx->MacAddress, 3);
+ value32 &= 0xFFFFFF00;
+ value32 |= 0x01;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+ // Hardware ID
+ buf = ctx->HardwarePrintableID;
+ size = (UINT)strlen(ctx->HardwarePrintableID) + 1;
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+ // Driver version
+ value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
+ buf = &value16;
+ size = sizeof(USHORT);
+ break;
+
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+ // Vendor driver version
+ value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
+ buf = &value16;
+ size = sizeof(USHORT);
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ // MAC address
+ buf = ctx->MacAddress;
+ size = NEO_MAC_ADDRESS_SIZE;
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ // Number of multicast
+ value32 = NEO_MAX_MULTICASE;
+ break;
+
+ case OID_GEN_MAXIMUM_SEND_PACKETS:
+ // Number of packets that can be sent at a time
+ value32 = NEO_MAX_PACKET_EXCHANGE;
+ break;
+
+ case OID_GEN_XMIT_OK:
+ // Number of packets sent
+ value32 = ctx->Status.NumPacketSend;
+ break;
+
+ case OID_GEN_RCV_OK:
+ // Number of received packets
+ value32 = ctx->Status.NumPacketRecv;
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ // Number of transmission error packets
+ value32 = ctx->Status.NumPacketSendError;
+ break;
+
+ case OID_GEN_RCV_ERROR:
+ // Number of error packets received
+ value32 = ctx->Status.NumPacketRecvError;
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+ // Number of reception buffer shortage occurrences
+ value32 = ctx->Status.NumPacketRecvNoBuffer;
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ // Number of errors
+ value32 = 0;
+ break;
+
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ // Cable connection state
+ NeoCheckConnectState();
+ if (keep_link == false)
+ {
+ value32 = ctx->Connected ? NdisMediaStateConnected : NdisMediaStateDisconnected;
+ }
+ else
+ {
+ value32 = NdisMediaStateConnected;
+ }
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ // Number of collisions
+ value32 = 0;
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ // Current settings of the packet filter
+ value32 = ctx->CurrentPacketFilter;
+ break;
+
+/* case OID_GEN_PROTOCOL_OPTIONS:
+ // Current value of the protocol option
+ value32 = ctx->CurrentProtocolOptions;
+ break;*/
+
+ case OID_GEN_STATISTICS:
+ // Statistics (NDIS 6.0)
+ NeoZero(&stat, sizeof(stat));
+ buf = &stat;
+ size = sizeof(stat);
+
+ stat.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ stat.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
+ stat.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
+ stat.SupportedStatistics =
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |
+ NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
+
+ stat.ifInErrors = ctx->Status.Int64NumRecvError;
+ stat.ifHCInOctets = ctx->Status.Int64BytesRecvTotal;
+ stat.ifHCInUcastPkts = ctx->Status.Int64NumRecvUnicast;
+ stat.ifHCInBroadcastPkts = ctx->Status.Int64NumRecvBroadcast;
+ stat.ifHCOutOctets = ctx->Status.Int64BytesSendTotal;
+ stat.ifHCOutUcastPkts = ctx->Status.Int64NumSendUnicast;
+ stat.ifHCOutBroadcastPkts = ctx->Status.Int64NumSendBroadcast;
+ stat.ifOutErrors = ctx->Status.Int64NumSendError;
+ stat.ifHCInUcastOctets = ctx->Status.Int64BytesRecvUnicast;
+ stat.ifHCInBroadcastOctets = ctx->Status.Int64BytesRecvBroadcast;
+ stat.ifHCOutUcastOctets = ctx->Status.Int64BytesSendUnicast;
+ stat.ifHCOutBroadcastOctets = ctx->Status.Int64BytesSendBroadcast;
+ break;
+
+ case OID_GEN_INTERRUPT_MODERATION:
+ // Interrupt Moderation (NDIS 6.0)
+ NeoZero(&intp, sizeof(intp));
+ buf = &intp;
+ size = sizeof(intp);
+
+ intp.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ intp.Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+ intp.Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+ intp.InterruptModeration = NdisInterruptModerationNotSupported;
+ break;
+
+ default:
+ // Unknown OID
+ *BytesWritten = 0;
+ return NDIS_STATUS_INVALID_OID;
+ }
+
+ if (size > InformationBufferLength)
+ {
+ // Undersize
+ *BytesNeeded = size;
+ *BytesWritten = 0;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ // Data copy
+ NeoCopy(InformationBuffer, buf, size);
+ *BytesWritten = size;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// Set the cable connection state
+void NeoSetConnectState(BOOL connected)
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+ ctx->Connected = connected;
+ NeoCheckConnectState();
+}
+
+// Check the cable connection state
+void NeoCheckConnectState()
+{
+ NDIS_STATUS_INDICATION t;
+ NDIS_LINK_STATE state;
+ if (ctx == NULL || ctx->NdisMiniport == NULL)
+ {
+ return;
+ }
+
+ NeoZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+ t.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+ t.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
+
+ t.SourceHandle = ctx->NdisMiniport;
+
+ NeoZero(&state, sizeof(state));
+ state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ state.Header.Revision = NDIS_LINK_STATE_REVISION_1;
+ state.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
+
+ state.MediaDuplexState = NdisPauseFunctionsSendAndReceive;
+ state.XmitLinkSpeed = state.RcvLinkSpeed = max_speed;
+ state.PauseFunctions = NdisPauseFunctionsUnsupported;
+
+ t.StatusCode = NDIS_STATUS_LINK_STATE;
+ t.StatusBuffer = &state;
+ t.StatusBufferSize = sizeof(NDIS_LINK_STATE);
+
+ if (keep_link == false)
+ {
+ if (ctx->ConnectedOld != ctx->Connected || ctx->ConnectedForce)
+ {
+ ctx->ConnectedForce = FALSE;
+ ctx->ConnectedOld = ctx->Connected;
+ if (ctx->Halting == FALSE)
+ {
+ state.MediaConnectState = ctx->Connected ? MediaConnectStateConnected : MediaConnectStateDisconnected;
+ NdisMIndicateStatusEx(ctx->NdisMiniport, &t);
+ }
+ }
+ }
+ else
+ {
+ if (ctx->ConnectedForce)
+ {
+ ctx->ConnectedForce = false;
+
+ if (ctx->Halting == FALSE)
+ {
+ state.MediaConnectState = MediaConnectStateConnected;
+ NdisMIndicateStatusEx(ctx->NdisMiniport, &t);
+ }
+ }
+ }
+}
+
+// Information setting handler of adapter
+NDIS_STATUS NeoNdisSet(
+ NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesRead,
+ ULONG *BytesNeeded)
+{
+ if (ctx == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Initialization
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ // Branch processing
+ switch (Oid)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ /* Packet filter */
+ if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ ctx->CurrentPacketFilter = *((UINT *)InformationBuffer);
+ return NDIS_STATUS_SUCCESS;
+
+// case OID_GEN_PROTOCOL_OPTIONS:
+ /* Current protocol option value */
+/* if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ ctx->CurrentProtocolOptions = *((UINT *)InformationBuffer);
+ return NDIS_STATUS_SUCCESS;*/
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ /* Look ahead */
+ if (InformationBufferLength != 4)
+ {
+ *BytesNeeded = 4;
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+ *BytesRead = 4;
+ return NDIS_STATUS_SUCCESS;
+
+ case OID_GEN_LINK_PARAMETERS:
+ // NDIS 6.0 Link setting
+ *BytesRead = InformationBufferLength;
+ return NDIS_STATUS_SUCCESS;
+
+ case OID_802_3_MULTICAST_LIST:
+ // Multicast list
+ *BytesRead = InformationBufferLength;
+
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ return NDIS_STATUS_INVALID_OID;
+}
+
+// Packet send handler
+void NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext,
+ NET_BUFFER_LIST *NetBufferLists,
+ NDIS_PORT_NUMBER PortNumber,
+ ULONG SendFlags)
+{
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ // Update the connection state
+ NeoCheckConnectState();
+
+ if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE)
+ {
+ // Device is stopped
+ return;
+ }
+
+ // Operation of the packet queue
+ NeoLockPacketQueue();
+ {
+ NET_BUFFER_LIST *nbl;
+ if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE)
+ {
+ // Device is stopped
+ NeoUnlockPacketQueue();
+ return;
+ }
+
+ nbl = NetBufferLists;
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ while (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ if (size >= NEO_MIN_PACKET_SIZE && size <= NEO_MAX_PACKET_SIZE)
+ {
+ UCHAR *buf = NeoMalloc(size);
+ void *ptr;
+
+ ptr = NdisGetDataBuffer(nb, size, buf, 1, 0);
+
+ if (ptr == NULL)
+ {
+ ctx->Status.NumPacketSendError++;
+ ctx->Status.Int64NumSendError++;
+ NeoFree(buf);
+ }
+ else
+ {
+ if (ptr != buf)
+ {
+ NeoCopy(buf, ptr, size);
+ }
+
+ NeoInsertQueue(buf, size);
+ ctx->Status.NumPacketSend++;
+
+ if (buf[0] & 0x40)
+ {
+ ctx->Status.Int64NumSendBroadcast++;
+ ctx->Status.Int64BytesSendBroadcast += (UINT64)size;
+ }
+ else
+ {
+ ctx->Status.Int64NumSendUnicast++;
+ ctx->Status.Int64BytesSendUnicast += (UINT64)size;
+ }
+
+ ctx->Status.Int64BytesSendTotal += (UINT64)size;
+ }
+ }
+ else
+ {
+ ctx->Status.NumPacketSendError++;
+ ctx->Status.Int64NumSendError++;
+ }
+
+ nb = NET_BUFFER_NEXT_NB(nb);
+ }
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ }
+ }
+
+ NeoUnlockPacketQueue();
+
+ // Notify the transmission completion
+ NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, NDIS_STATUS_SUCCESS);
+
+ // Reception event
+ NeoSet(ctx->Event);
+}
+
+// Stop check of packet transmission
+BOOL NeoNdisSendPacketsHaltCheck(NET_BUFFER_LIST *NetBufferLists)
+{
+ if (ctx == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ctx->Halting != FALSE || ctx->Opened == FALSE)
+ {
+ // Halting
+ NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, NDIS_STATUS_FAILURE);
+
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// Initialize the packet array
+void NeoInitPacketArray()
+{
+ UINT i;
+ // Create a packet buffer
+ for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
+ {
+ ctx->PacketBuffer[i] = NeoNewPacketBuffer();
+ }
+}
+
+// Release the packet array
+void NeoFreePacketArray()
+{
+ UINT i;
+ for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
+ {
+ NeoFreePacketBuffer(ctx->PacketBuffer[i]);
+ ctx->PacketBuffer[i] = NULL;
+ }
+}
+
+// Release the packet buffer
+void NeoFreePacketBuffer(PACKET_BUFFER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the NET_BUFFER_LIST
+ NdisFreeNetBufferList(p->NetBufferList);
+ // Release the NET_BUFFER_LIST pool
+ NdisFreeNetBufferListPool(p->NetBufferListPool);
+ // Release the memory
+ NeoFree(p);
+}
+
+// Create a packet buffer
+PACKET_BUFFER *NeoNewPacketBuffer()
+{
+ PACKET_BUFFER *p;
+ NET_BUFFER_LIST_POOL_PARAMETERS p1;
+
+ // Memory allocation
+ p = NeoZeroMalloc(sizeof(PACKET_BUFFER));
+
+ // Create a NET_BUFFER_LIST pool
+ NeoZero(&p1, sizeof(p1));
+ p1.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ p1.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+ p1.fAllocateNetBuffer = TRUE;
+ p1.DataSize = NEO_MAX_PACKET_SIZE;
+ p->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p1);
+
+ // Create a NET_BUFFER_LIST
+ p->NetBufferList = NdisAllocateNetBufferList(p->NetBufferListPool, 0, 0);
+
+ return p;
+}
+
+// Check whether the specified address is kernel memory
+BOOL NeoIsKernelAddress(void *addr)
+{
+#if 0
+ if ((ULONG)addr >= (ULONG)0x80000000)
+ {
+ // Kernel memory
+ return TRUE;
+ }
+#endif // CPU_64
+ // User memory
+ return FALSE;
+}
+
+// Reset the event
+void NeoReset(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeResetEvent(event->event);
+}
+
+// Set the event
+void NeoSet(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeSetEvent(event->event, 0, FALSE);
+}
+
+// Release the event
+void NeoFreeEvent(NEO_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ ZwClose(event->event_handle);
+
+ // Release the memory
+ NeoFree(event);
+}
+
+// Create a new event
+NEO_EVENT *NeoNewEvent(char *name)
+{
+ UNICODE *unicode_name;
+ NEO_EVENT *event;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert the name to Unicode
+ unicode_name = NewUnicode(name);
+ if (unicode_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ event = NeoZeroMalloc(sizeof(NEO_EVENT));
+ if (event == NULL)
+ {
+ FreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Create an Event
+ event->event = IoCreateNotificationEvent(GetUnicode(unicode_name), &event->event_handle);
+ if (event->event == NULL)
+ {
+ NeoFree(event);
+ FreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Initialize the event
+ KeInitializeEvent(event->event, NotificationEvent, FALSE);
+ KeClearEvent(event->event);
+
+ // Release a string
+ FreeUnicode(unicode_name);
+
+ return event;
+}
+
+// Get the Unicode string
+NDIS_STRING *GetUnicode(UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ return &u->String;
+}
+
+// Release the Unicode strings
+void FreeUnicode(UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ // Release a string
+ NdisFreeString(u->String);
+
+ // Release the memory
+ NeoFree(u);
+}
+
+// Create a new Unicode string
+UNICODE *NewUnicode(char *str)
+{
+ UNICODE *u;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = NeoZeroMalloc(sizeof(UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ // String initialization
+ NdisInitializeString(&u->String, str);
+
+ return u;
+}
+
+// Release the lock
+void NeoFreeLock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisFreeSpinLock(spin_lock);
+
+ // Release the memory
+ NeoFree(lock);
+}
+
+// Unlock
+void NeoUnlock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisReleaseSpinLock(spin_lock);
+}
+
+// Lock
+void NeoLock(NEO_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisAcquireSpinLock(spin_lock);
+}
+
+// Creating a new lock
+NEO_LOCK *NeoNewLock()
+{
+ NDIS_SPIN_LOCK *spin_lock;
+
+ // Memory allocation
+ NEO_LOCK *lock = NeoZeroMalloc(sizeof(NEO_LOCK));
+ if (lock == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize spin lock
+ spin_lock = &lock->spin_lock;
+
+ NdisAllocateSpinLock(spin_lock);
+
+ return lock;
+}
+
+// Memory copy
+void NeoCopy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Copy
+ NdisMoveMemory(dst, src, size);
+}
+
+// Memory clear
+void NeoZero(void *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Clear
+ NdisZeroMemory(dst, size);
+}
+
+// Clear to zero by memory allocation
+void *NeoZeroMalloc(UINT size)
+{
+ void *p = NeoMalloc(size);
+ if (p == NULL)
+ {
+ // Memory allocation failure
+ return NULL;
+ }
+ // Clear to zero
+ NeoZero(p, size);
+ return p;
+}
+
+// Memory allocation
+void *NeoMalloc(UINT size)
+{
+ NDIS_STATUS r;
+ void *p;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ // Allocate the non-paged memory
+ r = NdisAllocateMemoryWithTag(&p, size, 0);
+
+ if (NG(r))
+ {
+ return NULL;
+ }
+ return p;
+}
+
+// Release the memory
+void NeoFree(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the memory
+ NdisFreeMemory(p, 0, 0);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo6/NDIS6.h b/src/Neo6/NDIS6.h
new file mode 100644
index 00000000..cacf8e22
--- /dev/null
+++ b/src/Neo6/NDIS6.h
@@ -0,0 +1,239 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// NDIS6.h
+// Header of NDIS6.c
+
+#ifndef NDIS5_H
+#define NDIS5_H
+
+// Win32 DDK related
+#ifndef CPU_64
+#define _X86_
+#else // CPU_64
+#ifndef NEO_IA64
+#define _AMD64_
+#define AMD64
+#else // NEO_IA64
+#define _IA64_
+#define IA64
+#endif // NEO_IA64
+#endif // CPU_64
+#define NDIS_MINIPORT_DRIVER
+// NDIS 6.2
+#define NDIS620_MINIPORT
+#define NDIS_SUPPORT_NDIS61 1
+#define NDIS_SUPPORT_NDIS620 1
+#define NEO_NDIS_MAJOR_VERSION 6
+#define NEO_NDIS_MINOR_VERSION 20
+#define NDIS_WDM 1
+
+#include <wdm.h>
+#include <ndis.h>
+#include <stdio.h>
+#include <string.h>
+
+// Error checking macro
+#define OK(val) ((val) == STATUS_SUCCESS)
+#define NG(val) (!OK(val))
+
+// Constant
+static UINT SupportedOids[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_VENDOR_DRIVER_VERSION,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+ OID_802_3_MULTICAST_LIST,
+ //OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAXIMUM_SEND_PACKETS,
+ OID_GEN_STATISTICS,
+ OID_GEN_INTERRUPT_MODERATION,
+ OID_GEN_LINK_PARAMETERS,
+ };
+#define NEO_MEDIA NdisMedium802_3
+#define MAX_MULTICAST 32
+
+#define MAX_PATH 260
+#define MAX_SIZE 512
+#define STD_SIZE 512
+
+
+
+// Unicode string
+typedef struct _UNICODE
+{
+ UNICODE_STRING String;
+} UNICODE;
+
+typedef struct _PACKET_BUFFER PACKET_BUFFER;
+
+// Function prototype
+UNICODE *NewUnicode(char *str);
+void FreeUnicode(UNICODE *u);
+NDIS_STRING *GetUnicode(UNICODE *u);
+PACKET_BUFFER *NeoNewPacketBuffer();
+void NeoFreePacketBuffer(PACKET_BUFFER *p);
+void NeoInitPacketArray();
+void NeoFreePacketArray();
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath);
+NDIS_STATUS NeoNdisInitEx(NDIS_HANDLE MiniportAdapterHandle,
+ NDIS_HANDLE MiniportDriverContext,
+ PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters);
+void NeoNdisHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction);
+VOID NeoNdisDriverUnload(PDRIVER_OBJECT DriverObject);
+NDIS_STATUS NeoNdisResetEx(NDIS_HANDLE MiniportAdapterContext, PBOOLEAN AddressingReset);
+BOOLEAN NeoNdisCheckForHangEx(NDIS_HANDLE MiniportAdapterContext);
+NDIS_STATUS NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesWritten,
+ ULONG *BytesNeeded);
+NDIS_STATUS NeoNdisSet(
+ NDIS_HANDLE MiniportAdapterContext,
+ NDIS_OID Oid,
+ void *InformationBuffer,
+ ULONG InformationBufferLength,
+ ULONG *BytesRead,
+ ULONG *BytesNeeded);
+NDIS_STATUS NeoNdisOidRequest(NDIS_HANDLE MiniportAdapterContext,
+ PNDIS_OID_REQUEST OidRequest);
+void NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext,
+ NET_BUFFER_LIST *NetBufferLists,
+ NDIS_PORT_NUMBER PortNumber,
+ ULONG SendFlags);
+BOOL NeoNdisSendPacketsHaltCheck(NET_BUFFER_LIST *NetBufferLists);
+BOOL NeoLoadRegistory();
+void NeoInitControlDevice();
+void NeoFreeControlDevice();
+NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp);
+void NeoCheckConnectState();
+void NeoSetConnectState(BOOL connected);
+BOOL NeoNdisOnOpen(IRP *irp, IO_STACK_LOCATION *stack);
+BOOL NeoNdisOnClose(IRP *irp, IO_STACK_LOCATION *stack);
+void NeoNdisCrash();
+void NeoNdisCrash2();
+
+NDIS_STATUS NeoNdisSetOptions(NDIS_HANDLE NdisDriverHandle, NDIS_HANDLE DriverContext);
+NDIS_STATUS NeoNdisPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters);
+NDIS_STATUS NeoNdisRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters);
+void NeoNdisReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags);
+void NeoNdisCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId);
+void NeoNdisDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext, PNET_DEVICE_PNP_EVENT NetDevicePnPEvent);
+void NeoNdisShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownAction);
+void NeoNdisCancelOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId);
+
+// NeoNdisCrash2(__LINE__, __LINE__, __LINE__, __LINE__);
+
+
+#endif // NDIS5_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo6/Neo6.c b/src/Neo6/Neo6.c
new file mode 100644
index 00000000..aec85662
--- /dev/null
+++ b/src/Neo6/Neo6.c
@@ -0,0 +1,499 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Neo6.c
+// Driver Main Program
+
+#include <GlobalConst.h>
+
+#define NEO_DEVICE_DRIVER
+
+#include "Neo6.h"
+
+// Whether Win8
+extern bool g_is_win8;
+
+// Neo driver context
+static NEO_CTX static_ctx;
+NEO_CTX *ctx = &static_ctx;
+
+// Read the packet data from the transmit packet queue
+void NeoRead(void *buf)
+{
+ NEO_QUEUE *q;
+ UINT num;
+ BOOL left;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Copy the packets one by one from the queue
+ num = 0;
+ left = TRUE;
+ NeoLockPacketQueue();
+ {
+ while (TRUE)
+ {
+ if (num >= NEO_MAX_PACKET_EXCHANGE)
+ {
+ if (ctx->PacketQueue == NULL)
+ {
+ left = FALSE;
+ }
+ break;
+ }
+ q = NeoGetNextQueue();
+ if (q == NULL)
+ {
+ left = FALSE;
+ break;
+ }
+ NEO_SIZE_OF_PACKET(buf, num) = q->Size;
+ NeoCopy(NEO_ADDR_OF_PACKET(buf, num), q->Buf, q->Size);
+ num++;
+ NeoFreeQueue(q);
+ }
+ }
+ NeoUnlockPacketQueue();
+
+ NEO_NUM_PACKET(buf) = num;
+ NEO_LEFT_FLAG(buf) = left;
+
+ if (left == FALSE)
+ {
+ NeoReset(ctx->Event);
+ }
+ else
+ {
+ NeoSet(ctx->Event);
+ }
+
+ return;
+}
+
+// Process the received packet
+void NeoWrite(void *buf)
+{
+ UINT num, i, size;
+ UCHAR *packet_buf;
+ NET_BUFFER_LIST *nbl_chain = NULL;
+ NET_BUFFER_LIST *nbl_tail = NULL;
+ UINT num_nbl_chain = 0;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Number of packets
+ num = NEO_NUM_PACKET(buf);
+ if (num > NEO_MAX_PACKET_EXCHANGE)
+ {
+ // Number of packets is too many
+ return;
+ }
+ if (num == 0)
+ {
+ // No packet
+ return;
+ }
+
+ if (ctx->Halting != FALSE)
+ {
+ // Stopping
+ return;
+ }
+
+ if (ctx->Opened == FALSE)
+ {
+ // Not connected
+ return;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ PACKET_BUFFER *p = ctx->PacketBuffer[i];
+ void *dst;
+ NET_BUFFER_LIST *nbl = ctx->PacketBuffer[i]->NetBufferList;
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ nbl->SourceHandle = ctx->NdisMiniport;
+
+ NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
+
+ size = NEO_SIZE_OF_PACKET(buf, i);
+ if (size > NEO_MAX_PACKET_SIZE)
+ {
+ size = NEO_MAX_PACKET_SIZE;
+ }
+ if (size < NEO_PACKET_HEADER_SIZE)
+ {
+ size = NEO_PACKET_HEADER_SIZE;
+ }
+
+ packet_buf = (UCHAR *)(NEO_ADDR_OF_PACKET(buf, i));
+
+ if (OK(NdisRetreatNetBufferDataStart(nb, size, 0, NULL)))
+ {
+ // Buffer copy
+ dst = NdisGetDataBuffer(nb,
+ size,
+ NULL,
+ 1,
+ 0);
+
+ if (dst != NULL)
+ {
+ NeoCopy(dst, packet_buf, size);
+
+ if (nbl_chain == NULL)
+ {
+ nbl_chain = nbl;
+ }
+
+ if (nbl_tail != NULL)
+ {
+ NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
+ }
+
+ nbl_tail = nbl;
+
+ num_nbl_chain++;
+ }
+ }
+
+ nbl->Status = NDIS_STATUS_RESOURCES;
+
+ ctx->Status.Int64BytesRecvTotal += (UINT64)size;
+
+ if (packet_buf[0] & 0x40)
+ {
+ ctx->Status.Int64NumRecvBroadcast++;
+ ctx->Status.Int64BytesRecvBroadcast += (UINT64)size;
+ }
+ else
+ {
+ ctx->Status.Int64NumRecvUnicast++;
+ ctx->Status.Int64BytesRecvUnicast += (UINT64)size;
+ }
+ }
+
+ if (nbl_chain == NULL)
+ {
+ return;
+ }
+
+ // Notify that it has received
+ ctx->Status.NumPacketRecv += num_nbl_chain;
+
+ NdisMIndicateReceiveNetBufferLists(ctx->NdisMiniport,
+ nbl_chain, 0, num_nbl_chain, NDIS_RECEIVE_FLAGS_RESOURCES);
+
+ if (true)
+ {
+ // Restore the packet buffer
+ NET_BUFFER_LIST *nbl = nbl_chain;
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ if (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ NdisAdvanceNetBufferDataStart(nb, size, false, NULL);
+ }
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ }
+ }
+}
+
+// Get the number of queue items
+UINT NeoGetNumQueue()
+{
+ return ctx->NumPacketQueue;
+}
+
+// Insert the queue
+void NeoInsertQueue(void *buf, UINT size)
+{
+ NEO_QUEUE *p;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Prevent the packet accumulation in large quantities in the queue
+ if (ctx->NumPacketQueue > NEO_MAX_PACKET_QUEUED)
+ {
+ NeoFree(buf);
+ return;
+ }
+
+ // Create a queue
+ p = NeoMalloc(sizeof(NEO_QUEUE));
+ p->Next = NULL;
+ p->Size = size;
+ p->Buf = buf;
+
+ // Append to the queue
+ if (ctx->PacketQueue == NULL)
+ {
+ ctx->PacketQueue = p;
+ }
+ else
+ {
+ NEO_QUEUE *q = ctx->Tail;
+ q->Next = p;
+ }
+
+ ctx->Tail = p;
+
+ ctx->NumPacketQueue++;
+}
+
+// Get the next queued item
+NEO_QUEUE *NeoGetNextQueue()
+{
+ NEO_QUEUE *q;
+ if (ctx->PacketQueue == NULL)
+ {
+ // Empty queue
+ return NULL;
+ }
+
+ // Get the next queued item
+ q = ctx->PacketQueue;
+ ctx->PacketQueue = ctx->PacketQueue->Next;
+ q->Next = NULL;
+ ctx->NumPacketQueue--;
+
+ if (ctx->PacketQueue == NULL)
+ {
+ ctx->Tail = NULL;
+ }
+
+ return q;
+}
+
+// Release the buffer of the queue
+void NeoFreeQueue(NEO_QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+ NeoFree(q->Buf);
+ NeoFree(q);
+}
+
+// Lock the packet queue
+void NeoLockPacketQueue()
+{
+ NeoLock(ctx->PacketQueueLock);
+}
+
+// Unlock the packet queue
+void NeoUnlockPacketQueue()
+{
+ NeoUnlock(ctx->PacketQueueLock);
+}
+
+// Initialize the packet queue
+void NeoInitPacketQueue()
+{
+ // Create a lock
+ ctx->PacketQueueLock = NeoNewLock();
+ // Initialize the packet queue
+ ctx->PacketQueue = NULL;
+ ctx->NumPacketQueue = 0;
+ ctx->Tail = NULL;
+}
+
+// Delete all the packets from the packet queue
+void NeoClearPacketQueue()
+{
+ // Release the memory of the packet queue
+ NeoLock(ctx->PacketQueueLock);
+ {
+ NEO_QUEUE *q = ctx->PacketQueue;
+ NEO_QUEUE *qn;
+ while (q != NULL)
+ {
+ qn = q->Next;
+ NeoFree(q->Buf);
+ NeoFree(q);
+ q = qn;
+ }
+ ctx->PacketQueue = NULL;
+ ctx->Tail = NULL;
+ ctx->NumPacketQueue = 0;
+ }
+ NeoUnlock(ctx->PacketQueueLock);
+}
+
+// Release the packet queue
+void NeoFreePacketQueue()
+{
+ // Delete all packets
+ NeoClearPacketQueue();
+
+ // Delete the lock
+ NeoFreeLock(ctx->PacketQueueLock);
+ ctx->PacketQueueLock = NULL;
+}
+
+// Start the adapter
+void NeoStartAdapter()
+{
+ // Initialize the packet queue
+ NeoInitPacketQueue();
+}
+
+// Stop the adapter
+void NeoStopAdapter()
+{
+ // Delete the packet queue
+ NeoFreePacketQueue();
+}
+
+// Initialization
+BOOL NeoInit()
+{
+ // Initialize the context
+ NeoZero(ctx, sizeof(NEO_CTX));
+
+ // Initialize the status information
+ NeoNewStatus(&ctx->Status);
+
+ return TRUE;
+}
+
+// Shutdown
+void NeoShutdown()
+{
+ if (ctx == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Relaese the status information
+ NeoFreeStatus(&ctx->Status);
+
+ NeoZero(ctx, sizeof(NEO_CTX));
+}
+
+// Create a status information
+void NeoNewStatus(NEO_STATUS *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory initialization
+ NeoZero(s, sizeof(NEO_STATUS));
+}
+
+// Release the status information
+void NeoFreeStatus(NEO_STATUS *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory initialization
+ NeoZero(s, sizeof(NEO_STATUS));
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo6/Neo6.h b/src/Neo6/Neo6.h
new file mode 100644
index 00000000..3a5b6feb
--- /dev/null
+++ b/src/Neo6/Neo6.h
@@ -0,0 +1,320 @@
+// SoftEther VPN Source Code
+// Kernel Device Driver
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Neo6.h
+// Header of Neo6.c
+
+#ifndef NEO_H
+#define NEO_H
+
+
+// Identification string (NDIS)
+#define NDIS_NEO_HARDWARE_ID "VPN Client Adapter - %s"
+#define NDIS_NEO_DEVICE_NAME "\\Device\\NEO_%s_DEVICE"
+#define NDIS_NEO_DEVICE_NAME_WIN32 "\\DosDevices\\NEO_%s_DEVICE"
+#define NDIS_NEO_DEVICE_FILE_NAME "\\\\.\\NEO_NEOADAPTER_%s_DEVICE"
+#define NDIS_NEO_EVENT_NAME "\\BaseNamedObjects\\NEO_EVENT_%s"
+#define NDIS_NEO_EVENT_NAME_WIN32 "Global\\NEO_EVENT_NEOADAPTER_%s"
+
+// Constant
+#define NEO_MAX_PACKET_SIZE 1560
+#define NEO_MAX_PACKET_SIZE_ANNOUNCE 1514
+#define NEO_MIN_PACKET_SIZE 14
+#define NEO_PACKET_HEADER_SIZE 14
+#define NEO_MAX_FRAME_SIZE (NEO_MAX_PACKET_SIZE - NEO_MIN_PACKET_SIZE)
+#define NEO_MAX_SPEED_DEFAULT 100000000ULL
+#define NEO_MAC_ADDRESS_SIZE 6
+#define NEO_MAX_MULTICASE 32
+
+
+// IOCTL constant
+#define NEO_IOCTL_SET_EVENT CTL_CODE(0x8000, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define NEO_IOCTL_PUT_PACKET CTL_CODE(0x8000, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define NEO_IOCTL_GET_PACKET CTL_CODE(0x8000, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+// Packet data exchange related
+#define NEO_MAX_PACKET_EXCHANGE 256 // Number of packets that can be exchanged at a time
+#define NEO_MAX_PACKET_QUEUED 4096 // Maximum number of packets that can be queued
+#define NEO_EX_SIZEOF_NUM_PACKET 4 // Packet count data (UINT)
+#define NEO_EX_SIZEOF_LENGTH_PACKET 4 // Length data of the packet data (UINT)
+#define NEO_EX_SIZEOF_LEFT_FLAG 4 // Flag to indicate that the packet is still
+#define NEO_EX_SIZEOF_ONE_PACKET 1600 // Data area occupied by a packet data
+#define NEO_EXCHANGE_BUFFER_SIZE (NEO_EX_SIZEOF_NUM_PACKET + NEO_EX_SIZEOF_LEFT_FLAG + \
+ (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET) * (NEO_MAX_PACKET_EXCHANGE + 1))
+#define NEO_NUM_PACKET(buf) (*((UINT *)((UCHAR *)buf + 0)))
+#define NEO_SIZE_OF_PACKET(buf, i) (*((UINT *)((UCHAR *)buf + NEO_EX_SIZEOF_NUM_PACKET + \
+ (i * (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET)))))
+#define NEO_ADDR_OF_PACKET(buf, i) (((UINT *)((UCHAR *)buf + NEO_EX_SIZEOF_NUM_PACKET + \
+ NEO_EX_SIZEOF_LENGTH_PACKET + \
+ (i * (NEO_EX_SIZEOF_LENGTH_PACKET + NEO_EX_SIZEOF_ONE_PACKET)))))
+#define NEO_LEFT_FLAG(buf) NEO_SIZE_OF_PACKET(buf, NEO_MAX_PACKET_EXCHANGE)
+
+
+
+// Definitions needed to compile as a device driver
+#ifdef NEO_DEVICE_DRIVER
+
+// OS decision
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX / Linux
+#endif
+
+
+// Type declaration
+#ifndef WINDOWS_H_INCLUDED
+#ifndef WIN9X
+typedef unsigned long BOOL;
+#endif // WIN9X
+#define TRUE 1
+#define FALSE 0
+#endif
+typedef unsigned long bool;
+#define true 1
+#define false 0
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef signed char CHAR;
+typedef unsigned long DWORD;
+#define INFINITE 0xFFFFFFFF
+
+#define LESS(a, max_value) ((a) < (max_value) ? (a) : (max_value))
+#define MORE(a, min_value) ((a) > (min_value) ? (a) : (min_value))
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+
+#ifdef OS_WIN32
+// NDIS 5.0 related
+#include "NDIS6.h"
+#endif // OS_WIN32
+
+// Lock
+typedef struct _NEO_LOCK
+{
+#ifdef OS_WIN32
+ NDIS_SPIN_LOCK spin_lock;
+#endif
+} NEO_LOCK;
+
+// Event
+typedef struct _NEO_EVENT
+{
+#ifdef OS_WIN32
+#ifndef WIN9X
+ KEVENT *event;
+ HANDLE event_handle;
+#else // WIN9X
+ DWORD win32_event;
+#endif // WIN9X
+#endif
+} NEO_EVENT;
+
+// Packet queue
+typedef struct _NEO_QUEUE
+{
+ struct _NEO_QUEUE *Next;
+ UINT Size;
+ void *Buf;
+} NEO_QUEUE;
+
+// Status
+typedef struct _NEO_STATUS
+{
+ UINT NumPacketSend;
+ UINT NumPacketRecv;
+ UINT NumPacketSendError;
+ UINT NumPacketRecvError;
+ UINT NumPacketRecvNoBuffer;
+ UINT64 Int64NumRecvError; // ifInErrors, OID_GEN_RCV_ERROR
+ UINT64 Int64BytesRecvTotal; // ifHCInOctets, OID_GEN_BYTES_RCV
+ UINT64 Int64NumRecvUnicast; // ifHCInUcastPkts, OID_GEN_DIRECTED_FRAMES_RCV
+ UINT64 Int64NumRecvBroadcast; // ifHCInBroadcastPkts, OID_GEN_BROADCAST_FRAMES_RCV
+ UINT64 Int64BytesSendTotal; // ifHCOutOctets, OID_GEN_BYTES_XMIT
+ UINT64 Int64NumSendUnicast; // ifHCOutUcastPkts, OID_GEN_DIRECTED_FRAMES_XMIT
+ UINT64 Int64NumSendBroadcast; // ifHCOutBroadcastPkts, OID_GEN_BROADCAST_FRAMES_XMIT
+ UINT64 Int64NumSendError; // ifOutErrors, OID_GEN_XMIT_ERROR
+ UINT64 Int64BytesRecvUnicast; // ifHCInUcastOctets, OID_GEN_DIRECTED_BYTES_RCV
+ UINT64 Int64BytesRecvBroadcast; // ifHCInBroadcastOctets, OID_GEN_BROADCAST_BYTES_RCV
+ UINT64 Int64BytesSendUnicast; // ifHCOutUcastOctets, OID_GEN_DIRECTED_BYTES_XMIT
+ UINT64 Int64BytesSendBroadcast; // ifHCOutBroadcastOctets, OID_GEN_BROADCAST_BYTES_XMIT
+} NEO_STATUS;
+
+// NDIS packet buffer
+typedef struct _PACKET_BUFFER
+{
+ NDIS_HANDLE NetBufferListPool; // NET_BUFFER_LIST Pool
+ NET_BUFFER_LIST *NetBufferList; // NET_BUFFER_LIST
+} PACKET_BUFFER;
+
+// Context
+typedef struct _NEO_CTX
+{
+ NEO_EVENT *Event; // Packet reception notification event
+ BOOL Opened; // Flag of whether opened
+ BOOL Inited; // Initialization flag
+ BOOL Initing; // Starting-up flag
+ volatile BOOL Halting; // Stopping flag
+ BYTE MacAddress[6]; // MAC address
+ BYTE padding[2]; // padding
+ NEO_QUEUE *PacketQueue; // Transmit packet queue
+ NEO_QUEUE *Tail; // Tail of the transmission packet queue
+ UINT NumPacketQueue; // Number of queued packet
+ NEO_LOCK *PacketQueueLock; // Transmit packet queue lock
+ NEO_STATUS Status; // Status
+ UINT CurrentPacketFilter; // Current packet filter value
+ UINT CurrentProtocolOptions; // Current protocol option value
+ BOOL Connected, ConnectedOld; // Cable connection state
+ BOOL ConnectedForce; // Connection state forcibly notification
+#ifdef OS_WIN32
+ NDIS_HANDLE NdisMiniportDriverHandle; // NDIS miniport driver handle
+ NDIS_HANDLE NdisControl; // NDIS control handle
+ NDIS_HANDLE NdisMiniport; // NDIS miniport handle
+ NDIS_HANDLE NdisContext; // NDIS context handle
+ DEVICE_OBJECT *NdisControlDevice; // NDIS control device
+ PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION];
+ PACKET_BUFFER *PacketBuffer[NEO_MAX_PACKET_EXCHANGE]; // NDIS packet buffer
+ NDIS_HARDWARE_STATUS HardwareStatus; // Hardware state
+ char HardwareID[MAX_SIZE]; // Hardware ID
+ char HardwareID_Raw[MAX_SIZE]; // Original hardware ID
+ char HardwarePrintableID[MAX_SIZE]; // Hardware ID (for display)
+#endif
+} NEO_CTX;
+
+extern NEO_CTX *ctx;
+
+
+// Neo.c routine
+void NeoNewStatus(NEO_STATUS *s);
+void NeoFreeStatus(NEO_STATUS *s);
+BOOL NeoInit();
+void NeoShutdown();
+void NeoInitPacketQueue();
+void NeoFreePacketQueue();
+void NeoClearPacketQueue();
+void NeoLockPacketQueue();
+void NeoUnlockPacketQueue();
+NEO_QUEUE *NeoGetNextQueue();
+void NeoFreeQueue(NEO_QUEUE *q);
+void NeoInsertQueue(void *buf, UINT size);
+UINT NeoGetNumQueue();
+void NeoStartAdapter();
+void NeoStopAdapter();
+void NeoRead(void *buf);
+void NeoWrite(void *buf);
+
+// Common routine (platform dependent)
+void *NeoMalloc(UINT size);
+void *NeoZeroMalloc(UINT size);
+void NeoFree(void *p);
+void NeoCopy(void *dst, void *src, UINT size);
+void NeoZero(void *dst, UINT size);
+NEO_LOCK *NeoNewLock();
+void NeoLock(NEO_LOCK *lock);
+void NeoUnlock(NEO_LOCK *lock);
+void NeoFreeLock(NEO_LOCK *lock);
+NEO_EVENT *NeoNewEvent(char *name);
+NEO_EVENT *NeoCreateWin9xEvent(DWORD h);
+void NeoFreeEvent(NEO_EVENT *event);
+void NeoSet(NEO_EVENT *event);
+void NeoReset(NEO_EVENT *event);
+BOOL NeoIsKernelAddress(void *addr);
+
+#endif // NEO_DEVICE_DRIVER
+
+
+#endif // NEO_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Neo6/Neo6.rc b/src/Neo6/Neo6.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/Neo6/Neo6.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/Neo6/Neo6.vcproj b/src/Neo6/Neo6.vcproj
new file mode 100644
index 00000000..b828ed30
--- /dev/null
+++ b/src/Neo6/Neo6.vcproj
@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Neo6"
+ ProjectGUID="{F7679B65-2FEC-469A-8BAC-B07BF4439422}"
+ RootNamespace="Neo6"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\vpn_driver6.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateWin8InfFiles x86&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\vpn_driver6_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateWin8InfFiles x64&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\NDIS6.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Neo6.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\NDIS6.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Neo6.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Neo6.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Neo6/resource.h b/src/Neo6/resource.h
new file mode 100644
index 00000000..1fdda11a
--- /dev/null
+++ b/src/Neo6/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Neo.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/PenCore/AboutBox.bmp b/src/PenCore/AboutBox.bmp
new file mode 100644
index 00000000..f92482d5
--- /dev/null
+++ b/src/PenCore/AboutBox.bmp
Binary files differ
diff --git a/src/PenCore/Azure.bmp b/src/PenCore/Azure.bmp
new file mode 100644
index 00000000..629d4941
--- /dev/null
+++ b/src/PenCore/Azure.bmp
Binary files differ
diff --git a/src/PenCore/Azure.ico b/src/PenCore/Azure.ico
new file mode 100644
index 00000000..715052c5
--- /dev/null
+++ b/src/PenCore/Azure.ico
Binary files differ
diff --git a/src/PenCore/AzureCn.bmp b/src/PenCore/AzureCn.bmp
new file mode 100644
index 00000000..55662ef4
--- /dev/null
+++ b/src/PenCore/AzureCn.bmp
Binary files differ
diff --git a/src/PenCore/AzureJa.bmp b/src/PenCore/AzureJa.bmp
new file mode 100644
index 00000000..30494fa1
--- /dev/null
+++ b/src/PenCore/AzureJa.bmp
Binary files differ
diff --git a/src/PenCore/BMP_UT.bmp b/src/PenCore/BMP_UT.bmp
new file mode 100644
index 00000000..6ca755e4
--- /dev/null
+++ b/src/PenCore/BMP_UT.bmp
Binary files differ
diff --git a/src/PenCore/Bridge.ico b/src/PenCore/Bridge.ico
new file mode 100644
index 00000000..451a0547
--- /dev/null
+++ b/src/PenCore/Bridge.ico
Binary files differ
diff --git a/src/PenCore/Cascade.ico b/src/PenCore/Cascade.ico
new file mode 100644
index 00000000..3a1ecd1a
--- /dev/null
+++ b/src/PenCore/Cascade.ico
Binary files differ
diff --git a/src/PenCore/CascadeOffline.ico b/src/PenCore/CascadeOffline.ico
new file mode 100644
index 00000000..87eab55d
--- /dev/null
+++ b/src/PenCore/CascadeOffline.ico
Binary files differ
diff --git a/src/PenCore/CascadeOffline2.ico b/src/PenCore/CascadeOffline2.ico
new file mode 100644
index 00000000..21c76273
--- /dev/null
+++ b/src/PenCore/CascadeOffline2.ico
Binary files differ
diff --git a/src/PenCore/Cert.ico b/src/PenCore/Cert.ico
new file mode 100644
index 00000000..3cdb1f88
--- /dev/null
+++ b/src/PenCore/Cert.ico
Binary files differ
diff --git a/src/PenCore/CertX.ico b/src/PenCore/CertX.ico
new file mode 100644
index 00000000..37f5694b
--- /dev/null
+++ b/src/PenCore/CertX.ico
Binary files differ
diff --git a/src/PenCore/ClientBanner.bmp b/src/PenCore/ClientBanner.bmp
new file mode 100644
index 00000000..c62bb73a
--- /dev/null
+++ b/src/PenCore/ClientBanner.bmp
Binary files differ
diff --git a/src/PenCore/Coins.bmp b/src/PenCore/Coins.bmp
new file mode 100644
index 00000000..8ea1e773
--- /dev/null
+++ b/src/PenCore/Coins.bmp
Binary files differ
diff --git a/src/PenCore/DDNS.ico b/src/PenCore/DDNS.ico
new file mode 100644
index 00000000..b81cd02c
--- /dev/null
+++ b/src/PenCore/DDNS.ico
Binary files differ
diff --git a/src/PenCore/DateTime.ico b/src/PenCore/DateTime.ico
new file mode 100644
index 00000000..343f9def
--- /dev/null
+++ b/src/PenCore/DateTime.ico
Binary files differ
diff --git a/src/PenCore/Discard.ico b/src/PenCore/Discard.ico
new file mode 100644
index 00000000..e6a9db41
--- /dev/null
+++ b/src/PenCore/Discard.ico
Binary files differ
diff --git a/src/PenCore/DiscardDisable.ico b/src/PenCore/DiscardDisable.ico
new file mode 100644
index 00000000..40b0c76d
--- /dev/null
+++ b/src/PenCore/DiscardDisable.ico
Binary files differ
diff --git a/src/PenCore/Display.ico b/src/PenCore/Display.ico
new file mode 100644
index 00000000..b4aa5cd0
--- /dev/null
+++ b/src/PenCore/Display.ico
Binary files differ
diff --git a/src/PenCore/Dummy.bin b/src/PenCore/Dummy.bin
new file mode 100644
index 00000000..9ed54232
--- /dev/null
+++ b/src/PenCore/Dummy.bin
@@ -0,0 +1 @@
+ABCDE
diff --git a/src/PenCore/EasyInstaller.ico b/src/PenCore/EasyInstaller.ico
new file mode 100644
index 00000000..82cb8494
--- /dev/null
+++ b/src/PenCore/EasyInstaller.ico
Binary files differ
diff --git a/src/PenCore/EtherIP.bmp b/src/PenCore/EtherIP.bmp
new file mode 100644
index 00000000..f39fa2b9
--- /dev/null
+++ b/src/PenCore/EtherIP.bmp
Binary files differ
diff --git a/src/PenCore/Farm.ico b/src/PenCore/Farm.ico
new file mode 100644
index 00000000..cdc6b790
--- /dev/null
+++ b/src/PenCore/Farm.ico
Binary files differ
diff --git a/src/PenCore/Group.ico b/src/PenCore/Group.ico
new file mode 100644
index 00000000..e5fec032
--- /dev/null
+++ b/src/PenCore/Group.ico
Binary files differ
diff --git a/src/PenCore/GroupDeny.ico b/src/PenCore/GroupDeny.ico
new file mode 100644
index 00000000..7de261f8
--- /dev/null
+++ b/src/PenCore/GroupDeny.ico
Binary files differ
diff --git a/src/PenCore/Hub.ico b/src/PenCore/Hub.ico
new file mode 100644
index 00000000..104533f3
--- /dev/null
+++ b/src/PenCore/Hub.ico
Binary files differ
diff --git a/src/PenCore/Hub_Offline.ico b/src/PenCore/Hub_Offline.ico
new file mode 100644
index 00000000..7568c212
--- /dev/null
+++ b/src/PenCore/Hub_Offline.ico
Binary files differ
diff --git a/src/PenCore/IPsec.ico b/src/PenCore/IPsec.ico
new file mode 100644
index 00000000..b67a69bd
--- /dev/null
+++ b/src/PenCore/IPsec.ico
Binary files differ
diff --git a/src/PenCore/IX2015.bmp b/src/PenCore/IX2015.bmp
new file mode 100644
index 00000000..e6b20efa
--- /dev/null
+++ b/src/PenCore/IX2015.bmp
Binary files differ
diff --git a/src/PenCore/Ibaraki.bmp b/src/PenCore/Ibaraki.bmp
new file mode 100644
index 00000000..8f49c8f1
--- /dev/null
+++ b/src/PenCore/Ibaraki.bmp
Binary files differ
diff --git a/src/PenCore/Information.ico b/src/PenCore/Information.ico
new file mode 100644
index 00000000..986e5fb4
--- /dev/null
+++ b/src/PenCore/Information.ico
Binary files differ
diff --git a/src/PenCore/Installer.ico b/src/PenCore/Installer.ico
new file mode 100644
index 00000000..b274e4c6
--- /dev/null
+++ b/src/PenCore/Installer.ico
Binary files differ
diff --git a/src/PenCore/Internet.ico b/src/PenCore/Internet.ico
new file mode 100644
index 00000000..cb20c031
--- /dev/null
+++ b/src/PenCore/Internet.ico
Binary files differ
diff --git a/src/PenCore/InternetX.ico b/src/PenCore/InternetX.ico
new file mode 100644
index 00000000..10a67272
--- /dev/null
+++ b/src/PenCore/InternetX.ico
Binary files differ
diff --git a/src/PenCore/Key.ico b/src/PenCore/Key.ico
new file mode 100644
index 00000000..2f6720a0
--- /dev/null
+++ b/src/PenCore/Key.ico
Binary files differ
diff --git a/src/PenCore/L2TP.bmp b/src/PenCore/L2TP.bmp
new file mode 100644
index 00000000..51943599
--- /dev/null
+++ b/src/PenCore/L2TP.bmp
Binary files differ
diff --git a/src/PenCore/LANG_CHINESE.ico b/src/PenCore/LANG_CHINESE.ico
new file mode 100644
index 00000000..baf7f344
--- /dev/null
+++ b/src/PenCore/LANG_CHINESE.ico
Binary files differ
diff --git a/src/PenCore/LANG_ENGLISH.ico b/src/PenCore/LANG_ENGLISH.ico
new file mode 100644
index 00000000..2be60b03
--- /dev/null
+++ b/src/PenCore/LANG_ENGLISH.ico
Binary files differ
diff --git a/src/PenCore/LANG_JAPANESE.ico b/src/PenCore/LANG_JAPANESE.ico
new file mode 100644
index 00000000..ddaad545
--- /dev/null
+++ b/src/PenCore/LANG_JAPANESE.ico
Binary files differ
diff --git a/src/PenCore/Language.ico b/src/PenCore/Language.ico
new file mode 100644
index 00000000..6a0c116b
--- /dev/null
+++ b/src/PenCore/Language.ico
Binary files differ
diff --git a/src/PenCore/License.ico b/src/PenCore/License.ico
new file mode 100644
index 00000000..4f9dcb94
--- /dev/null
+++ b/src/PenCore/License.ico
Binary files differ
diff --git a/src/PenCore/Link.ico b/src/PenCore/Link.ico
new file mode 100644
index 00000000..8124b793
--- /dev/null
+++ b/src/PenCore/Link.ico
Binary files differ
diff --git a/src/PenCore/Link2.ico b/src/PenCore/Link2.ico
new file mode 100644
index 00000000..2594aca2
--- /dev/null
+++ b/src/PenCore/Link2.ico
Binary files differ
diff --git a/src/PenCore/Log.ico b/src/PenCore/Log.ico
new file mode 100644
index 00000000..2ff6f914
--- /dev/null
+++ b/src/PenCore/Log.ico
Binary files differ
diff --git a/src/PenCore/Log2.ico b/src/PenCore/Log2.ico
new file mode 100644
index 00000000..7eaa770b
--- /dev/null
+++ b/src/PenCore/Log2.ico
Binary files differ
diff --git a/src/PenCore/Machine.ico b/src/PenCore/Machine.ico
new file mode 100644
index 00000000..ed34d0a6
--- /dev/null
+++ b/src/PenCore/Machine.ico
Binary files differ
diff --git a/src/PenCore/ManagerLogo.bmp b/src/PenCore/ManagerLogo.bmp
new file mode 100644
index 00000000..db9ecb5c
--- /dev/null
+++ b/src/PenCore/ManagerLogo.bmp
Binary files differ
diff --git a/src/PenCore/Memory.ico b/src/PenCore/Memory.ico
new file mode 100644
index 00000000..75d3c4aa
--- /dev/null
+++ b/src/PenCore/Memory.ico
Binary files differ
diff --git a/src/PenCore/NIC.ico b/src/PenCore/NIC.ico
new file mode 100644
index 00000000..0310b265
--- /dev/null
+++ b/src/PenCore/NIC.ico
Binary files differ
diff --git a/src/PenCore/NIC_Offline.ico b/src/PenCore/NIC_Offline.ico
new file mode 100644
index 00000000..45dfa17b
--- /dev/null
+++ b/src/PenCore/NIC_Offline.ico
Binary files differ
diff --git a/src/PenCore/New.ico b/src/PenCore/New.ico
new file mode 100644
index 00000000..ed15c92e
--- /dev/null
+++ b/src/PenCore/New.ico
Binary files differ
diff --git a/src/PenCore/Null.ico b/src/PenCore/Null.ico
new file mode 100644
index 00000000..d9d34d00
--- /dev/null
+++ b/src/PenCore/Null.ico
Binary files differ
diff --git a/src/PenCore/OpenVPN.bmp b/src/PenCore/OpenVPN.bmp
new file mode 100644
index 00000000..dfd5ae5e
--- /dev/null
+++ b/src/PenCore/OpenVPN.bmp
Binary files differ
diff --git a/src/PenCore/OpenVPN.ico b/src/PenCore/OpenVPN.ico
new file mode 100644
index 00000000..8d2821fc
--- /dev/null
+++ b/src/PenCore/OpenVPN.ico
Binary files differ
diff --git a/src/PenCore/PKCS12.ico b/src/PenCore/PKCS12.ico
new file mode 100644
index 00000000..0aaa5f7f
--- /dev/null
+++ b/src/PenCore/PKCS12.ico
Binary files differ
diff --git a/src/PenCore/Pass.ico b/src/PenCore/Pass.ico
new file mode 100644
index 00000000..2e050244
--- /dev/null
+++ b/src/PenCore/Pass.ico
Binary files differ
diff --git a/src/PenCore/PassDisable.ico b/src/PenCore/PassDisable.ico
new file mode 100644
index 00000000..eecd64ed
--- /dev/null
+++ b/src/PenCore/PassDisable.ico
Binary files differ
diff --git a/src/PenCore/PenCore.c b/src/PenCore/PenCore.c
new file mode 100644
index 00000000..d500df75
--- /dev/null
+++ b/src/PenCore/PenCore.c
@@ -0,0 +1,8 @@
+void DllMainCRTStartup()
+{
+}
+
+void PenKawaKuwaKuwa()
+{
+}
+
diff --git a/src/PenCore/PenCore.def b/src/PenCore/PenCore.def
new file mode 100644
index 00000000..f2db98e4
--- /dev/null
+++ b/src/PenCore/PenCore.def
@@ -0,0 +1,2 @@
+EXPORTS
+PenKawaKuwaKuwa \ No newline at end of file
diff --git a/src/PenCore/PenCore.rc b/src/PenCore/PenCore.rc
new file mode 100644
index 00000000..0f1e4d76
--- /dev/null
+++ b/src/PenCore/PenCore.rc
@@ -0,0 +1,4890 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ D_SECURE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 299
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 193
+ END
+
+ D_PKCSUTIL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 292
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 287
+ END
+
+ D_PASSPHRASE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 232
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 84
+ END
+
+ D_NM_CONNECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 264
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 51
+ END
+
+ D_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 207
+ END
+
+ D_STATUS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 208
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 59
+ END
+
+ D_CERT, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 264
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 384
+ END
+
+ D_CHECKCERT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 294
+ END
+
+ D_CONNECTERROR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 206
+ END
+
+ D_CM_LOGIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 268
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 127
+ END
+
+ D_CM_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 251
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 240
+ END
+
+ D_CONNECTION_STATUS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 284
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 261
+ END
+
+ D_CM_POLICY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 296
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 296
+ END
+
+ D_CM_ACCOUNT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 370
+ END
+
+ D_CM_PROXY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 248
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 146
+ END
+
+ D_CM_DETAIL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 427
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 357
+ END
+
+ D_CM_NEW_VLAN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 108
+ END
+
+ D_CM_TRUST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 328
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 221
+ END
+
+ D_CM_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 270
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 179
+ END
+
+ D_CM_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 295
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 391
+ END
+
+ D_ABOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 326
+ BOTTOMMARGIN, 354
+ HORZGUIDE, 315
+ END
+
+ D_REMOTE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 268
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 168
+ END
+
+ D_CM_DESKTOP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 363
+ VERTGUIDE, 31
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 217
+ END
+
+ D_CM_CHANGE_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 241
+ END
+
+ D_SM_MAIN, DIALOG
+ BEGIN
+ RIGHTMARGIN, 274
+ END
+
+ D_SM_EDIT_SETTING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 428
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 300
+ END
+
+ D_SM_SERVER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 432
+ TOPMARGIN, 7
+ END
+
+ D_SM_STATUS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 328
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 285
+ END
+
+ D_SM_EDIT_HUB, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 424
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 325
+ END
+
+ D_SM_CREATE_LISTENER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 154
+ END
+
+ D_SM_SSL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 456
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 358
+ END
+
+ D_SM_SAVE_KEY_PAIR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 288
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 341
+ END
+
+ D_SM_CONNECTION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 311
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 265
+ END
+
+ D_SM_FARM, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 381
+ END
+
+ D_SM_FARM_MEMBER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 408
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 258
+ END
+
+ D_SM_CHANGE_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 243
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 105
+ END
+
+ D_SM_HUB, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 396
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 351
+ END
+
+ D_SM_USER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 447
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 274
+ END
+
+ D_SM_EDIT_USER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 448
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 345
+ END
+
+ D_SM_POLICY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 443
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 334
+ END
+
+ D_SM_GROUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 327
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 275
+ END
+
+ D_SM_EDIT_GROUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 291
+ END
+
+ D_SM_ACCESS_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 315
+ END
+
+ D_SM_EDIT_ACCESS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 452
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 404
+ HORZGUIDE, 7
+ END
+
+ D_SM_RADIUS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 317
+ END
+
+ D_SM_LINK, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 416
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 306
+ END
+
+ D_SM_LOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 272
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 382
+ END
+
+ D_SM_CA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 328
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 220
+ END
+
+ D_SM_SESSION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 446
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 355
+ END
+
+ D_SM_MAC, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 330
+ END
+
+ D_SM_IP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 330
+ END
+
+ D_SM_CREATE_CERT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 294
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 364
+ END
+
+ D_NM_LOGIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 268
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 127
+ END
+
+ D_SPEEDMETER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 312
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 288
+ END
+
+ D_NM_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 344
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 373
+ END
+
+ D_NM_OPTION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 412
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 300
+ END
+
+ D_NM_NAT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 330
+ END
+
+ D_NM_DHCP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 444
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 330
+ END
+
+ D_NM_CHANGE_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 243
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 105
+ END
+
+ D_SM_SNAT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 348
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 311
+ END
+
+ D_SM_BRIDGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 360
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 373
+ END
+
+ D_WIN9X_REBOOT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 232
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 97
+ END
+
+ D_DEFAULT1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 83
+ END
+
+ D_EM_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 328
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 204
+ END
+
+ D_EM_ADD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 272
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 340
+ END
+
+ D_EM_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 243
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 105
+ END
+
+ D_SM_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 376
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 361
+ END
+
+ D_SM_ADMIN_OPTION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 303
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 352
+ END
+
+ D_SM_AO_VALUE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 199
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 73
+ END
+
+ D_SM_L3, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 284
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 291
+ END
+
+ D_SM_L3_ADD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 227
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 98
+ END
+
+ D_SM_L3_SW, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 291
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 367
+ END
+
+ D_SM_L3_SW_IF, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 282
+ END
+
+ D_SM_L3_SW_TABLE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 255
+ END
+
+ D_CM_SELECT_SECURE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 288
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 243
+ END
+
+ D_CM_SECURE_MANAGER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 288
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 260
+ END
+
+ D_CM_SECURE_TYPE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 188
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 119
+ END
+
+ D_STRING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 259
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 115
+ END
+
+ D_SM_SELECT_KEYPAIR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 194
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 276
+ END
+
+ D_CM_LOAD_X, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 232
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 202
+ END
+
+ D_CM_SECURE_PIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 256
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 214
+ END
+
+ D_SM_CRL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 328
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 220
+ END
+
+ D_SM_EDIT_CRL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 344
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 358
+ END
+
+ D_SM_AC_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 302
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 223
+ END
+
+ D_SM_AC, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 303
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 304
+ END
+
+ D_SM_LOG_FILE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 391
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 333
+ END
+
+ D_SM_READ_LOG_FILE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 280
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 104
+ END
+
+ D_SM_SAVE_LOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 264
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 75
+ END
+
+ D_TCP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 324
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 309
+ END
+
+ D_TCP_MSG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 240
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 200
+ END
+
+ D_CM_PKCSEULA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 260
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+
+ D_CM_KAKUSHI, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 358
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 266
+ END
+
+ D_CM_TRAFFIC, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 388
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 353
+ END
+
+ D_CM_TRAFFIC_RUN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 352
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 295
+ END
+
+ D_CM_TRAFFIC_RESULT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 323
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 221
+ END
+
+ D_SM_LICENSE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 420
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 360
+ END
+
+ D_SM_LICENSE_ADD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 352
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 260
+ END
+
+ D_FREEINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 235
+ END
+
+ D_EM_LICENSE_ADD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 352
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 260
+ END
+
+ D_EM_LICENSE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 420
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 355
+ END
+
+ D_EM_REMOTE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 268
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 168
+ END
+
+ D_CM_SETTING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 332
+ END
+
+ D_SM_SETUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 440
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 357
+ END
+
+ D_SM_SETUP_HUB, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 222
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 94
+ END
+
+ D_SM_SETUP_STEP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 322
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 344
+ END
+
+ D_CPU64_WARNING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 292
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 172
+ END
+
+ D_ONCEMSG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 181
+ END
+
+ D_CONNECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 182
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 72
+ END
+
+ D_SM_SIMULATION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 274
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 252
+ END
+
+ D_SM_EDIT_ACCESS_V6, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 452
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 404
+ HORZGUIDE, 7
+ END
+
+ D_SM_VLAN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 308
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 320
+ END
+
+ D_SM_MSG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 268
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 316
+ END
+
+ D_NICINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 214
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 100
+ END
+
+ D_SM_IPSEC, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 416
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 352
+ END
+
+ D_SM_ETHERIP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 404
+ VERTGUIDE, 326
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 278
+ END
+
+ D_SM_ETHERIP_ID, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 260
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 258
+ END
+
+ D_SM_OPENVPN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 420
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 380
+ END
+
+ D_SM_DDNS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 408
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 328
+ END
+
+ D_SM_SPECIALLISTENER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 350
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 366
+ END
+
+ D_SM_REDIRECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 351
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 356
+ END
+
+ D_SW_TEST1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_DUMMY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 83
+ END
+
+ D_SW_TEST2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 168
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 92
+ END
+
+ D_SW_DEFAULT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_WELCOME, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_MODE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ END
+
+ D_SW_NOT_ADMIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_COMPONENTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_EULA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_WARNING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_DIR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_READY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_PERFORM, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_ERROR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_FINISH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_UNINST1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_LANG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_EASY1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_EASY2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_WEB1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_SW_WEB2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 175
+ END
+
+ D_UPDATE_NOTICE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 232
+ END
+
+ D_UPDATE_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 300
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 148
+ END
+
+ D_SM_VMBRIDGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 304
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 308
+ END
+
+ D_SM_AZURE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 404
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 364
+ END
+
+ D_SM_PROXY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 220
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 160
+ END
+
+ D_VGC_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 439
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 347
+ END
+
+ D_VGC_PROTOCOL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 274
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 166
+ END
+
+ D_VGS_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 363
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 356
+ END
+
+ D_VGS_OPTION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 348
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 338
+ END
+
+ D_VGS_WARNING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 342
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 284
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+D_SECURE DIALOGEX 0, 0, 307, 201
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_SECURE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 107,S_IMAGE,"Static",SS_BITMAP,7,7,81,63
+ LTEXT "@S_TITLE",S_TITLE,99,7,166,19
+ LTEXT "%s",S_INSERT_SECURE,99,30,200,19
+ CONTROL "@S_DEVICE_INFO",S_DEVICE_INFO,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,106,70,173,26
+ GROUPBOX "@IDS_STATIC1",IDS_STATIC1,99,55,189,45
+ EDITTEXT E_PIN,106,118,180,13,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "@S_WARNING",S_WARNING,106,137,176,28
+ DEFPUSHBUTTON "@IDOK",IDOK,186,175,54,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,245,175,54,18
+ CONTROL "",A_PROGRESS,"SysAnimate32",ACS_TRANSPARENT | WS_TABSTOP,110,116,120,18,WS_EX_TRANSPARENT
+ LTEXT "S_STATUS",S_STATUS,106,136,193,20,NOT WS_VISIBLE
+ RTEXT "@S_PIN_CODE",S_PIN_CODE,40,119,64,12
+ LTEXT "-- SOFTWARE TITLE --",S_SOFTWARE_TITLE,7,180,177,13
+ CONTROL ICO_SESSION_BRIDGE,S_IMAGE2,"Static",SS_BITMAP,7,7,81,63
+ CONTROL ICO_TRAY4,S_IMAGE_TSUKUBA,"Static",SS_BITMAP,7,7,81,63
+END
+
+D_PKCSUTIL DIALOGEX 0, 0, 299, 294
+STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_PKCSUTIL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,30,7,263,20
+ LTEXT "@STATIC1",IDC_STATIC,31,39,245,39
+ GROUPBOX "@STATIC2",IDC_STATIC,31,89,241,86
+ LTEXT "@STATIC3",IDC_STATIC,38,101,227,36
+ PUSHBUTTON "@B_WRITE",B_WRITE,199,146,65,19
+ GROUPBOX "@STATIC4",IDC_STATIC,31,183,241,64
+ LTEXT "@STATIC5",IDC_STATIC,38,195,227,19
+ PUSHBUTTON "@B_ERASE",B_ERASE,199,219,65,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,212,269,80,18
+ LTEXT "@S_COPYRIGHT",S_COPYRIGHT,7,256,195,31
+END
+
+D_PASSPHRASE DIALOGEX 0, 0, 239, 91
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_PASSPHRASE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,28,7,194,29
+ RTEXT "@STATIC2",IDC_STATIC,7,44,55,11
+ EDITTEXT E_PASSPHRASE,67,42,156,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,126,66,50,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,182,66,50,18
+END
+
+D_NM_CONNECT DIALOGEX 0, 0, 271, 58
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "@D_NM_CONNECT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_ROUTER,IDC_STATIC,7,16,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,23,231,28
+END
+
+D_PASSWORD DIALOGEX 0, 0, 259, 214
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,14,221,29
+ GROUPBOX "@STATIC1",IDC_STATIC,21,46,209,102
+ RTEXT "@STATIC2",IDC_STATIC,32,65,60,12
+ COMBOBOX C_TYPE,99,63,108,56,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@STATIC3",IDC_STATIC,32,87,60,11
+ EDITTEXT E_USERNAME,99,85,108,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,32,109,60,11
+ EDITTEXT E_PASSWORD,99,107,108,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "@R_NO_SAVE_PASSWORD",R_NO_SAVE_PASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,99,127,120,10
+ LTEXT "@S_COUNTDOWN",S_COUNTDOWN,21,152,207,15
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER,21,170,209,9
+ DEFPUSHBUTTON "@IDOK",IDOK,133,190,50,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,189,190,63,17
+END
+
+D_STATUS DIALOGEX 0, 0, 215, 66
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_STATUS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@S_STATUS",S_STATUS,31,7,177,32
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,81,43,50,16
+END
+
+D_CERT DIALOGEX 0, 0, 271, 391
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CERT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,6,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,32,7,232,17
+ GROUPBOX "@STATIC1",IDC_STATIC,6,33,258,68
+ RTEXT "@STATIC2",IDC_STATIC,41,49,39,10
+ EDITTEXT E_SUBJECT,85,49,164,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@STATIC3",IDC_STATIC,41,64,39,11
+ EDITTEXT E_ISSUER,85,64,164,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@STATIC4",IDC_STATIC,41,79,39,10
+ EDITTEXT E_EXPIRES,85,79,128,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ GROUPBOX "@STATIC5",IDC_STATIC,6,109,258,180
+ CONTROL "",L_CERTINFO,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,21,129,229,97
+ GROUPBOX "@STATIC6",IDC_STATIC1,6,295,258,64
+ ICON ICO_CERT,S_CERT_ICON,22,313,20,20
+ LTEXT "@S_PARENT",S_PARENT,46,316,150,20
+ PUSHBUTTON "",B_PARENT,220,309,29,26,BS_ICON
+ CTEXT "@S_PARENT_BUTTON_STR",S_PARENT_BUTTON_STR,205,341,55,10
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,214,367,50,17
+ ICON ICO_WARNING,S_WARNING_ICON,22,314,20,20
+ EDITTEXT E_DETAIL,21,231,228,49,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY | WS_VSCROLL
+ PUSHBUTTON "@B_SAVE",B_SAVE,128,367,76,17
+END
+
+D_CHECKCERT DIALOGEX 0, 0, 251, 301
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_CHECKCERT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_WARNING,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,7,211,35
+ GROUPBOX "@STATIC1",IDC_STATIC,7,48,237,198
+ LTEXT "@STATIC2",IDC_STATIC,14,61,222,26
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,17,97,20,20
+ LTEXT "@S_MSG1",S_MSG1,42,97,193,26
+ RTEXT "@STATIC3",IDC_STATIC,14,124,69,12
+ EDITTEXT E_SUBJECT,88,124,149,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@STATIC4",IDC_STATIC,15,139,68,11
+ EDITTEXT E_ISSUER,88,139,149,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@STATIC5",IDC_STATIC,15,154,68,11
+ EDITTEXT E_EXPIRES,88,154,149,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "@B_SHOW",B_SHOW,158,201,76,17
+ LTEXT "@STATIC9",IDC_STATIC,7,247,237,29
+ RTEXT "@STATIC6",IDC_STATIC,16,169,67,10
+ EDITTEXT E_MD5,88,169,148,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@STATIC7",IDC_STATIC,14,185,69,12
+ EDITTEXT E_SHA1,88,185,148,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ DEFPUSHBUTTON "@IDOK",IDOK,38,277,80,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,127,277,80,17
+ LTEXT "@STATIC8",IDC_STATIC,15,223,221,19
+END
+
+D_CONNECTERROR DIALOGEX 0, 0, 251, 213
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_CONNECTERROR"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_OFFLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,213,24
+ EDITTEXT E_ERROR,31,32,197,74,ES_MULTILINE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER
+ LTEXT "@S_COUNTDOWN",S_COUNTDOWN,23,124,207,23
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER,23,150,209,9
+ DEFPUSHBUTTON "@IDOK",IDOK,125,189,50,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,181,189,63,17
+ LTEXT "---",S_RETRYINFO,23,110,207,13
+ CONTROL "@R_HIDE",R_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,164,214,19
+END
+
+D_CM_LOGIN DIALOGEX 0, 0, 275, 134
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_LOGIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,237,34
+ RTEXT "@STATIC1",IDC_STATIC,33,70,49,12
+ EDITTEXT E_PASSWORD,87,68,141,12,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "@STATIC2",IDC_STATIC,26,47,222,50
+ DEFPUSHBUTTON "@IDOK",IDOK,158,111,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,216,111,52,16
+END
+
+D_CM_MAIN DIALOGEX 0, 0, 258, 247
+STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "PacketiX VPN Main Window"
+MENU M_MAIN
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL "",L_ACCOUNT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,7,7,244,143
+ CONTROL "",L_VLAN,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,154,244,86
+END
+
+D_CONNECTION_STATUS DIALOGEX 0, 0, 291, 268
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CONNECTION_STATUS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TOWER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,28,7,256,26
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,39,277,199
+ PUSHBUTTON "@B_POLICY",B_POLICY,7,244,73,17
+ PUSHBUTTON "@B_SERVER_CERT",B_SERVER_CERT,88,244,65,17
+ PUSHBUTTON "@B_CLIENT_CERT",B_CLIENT_CERT,161,244,65,17
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,234,244,50,17
+END
+
+D_CM_POLICY DIALOGEX 0, 0, 303, 303
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_POLICY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,34,14,262,19
+ CONTROL "",L_POLICY,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,39,289,180
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,246,279,50,17
+ EDITTEXT S_DESCRIPTION,7,223,289,52,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+END
+
+D_CM_ACCOUNT DIALOGEX 0, 0, 451, 377
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_ACCOUNT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",S_STATIC1,29,7,186,27
+ RTEXT "@S_ACCOUNT_NAME",S_ACCOUNT_NAME,7,38,61,12
+ EDITTEXT E_ACCOUNT_NAME,72,36,126,12,ES_AUTOHSCROLL
+ GROUPBOX "@STATIC2",S_STATIC2,7,51,206,104
+ ICON ICO_VPNSERVER,IDC_STATIC,14,65,20,20
+ LTEXT "@STATIC3",S_STATIC3,40,65,166,29
+ RTEXT "@STATIC4",S_STATIC4,14,101,54,10
+ EDITTEXT E_HOSTNAME,72,99,126,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC5",S_STATIC5,14,119,54,10
+ COMBOBOX C_PORT,72,115,81,48,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@STATIC6",S_STATIC66,159,119,46,11
+ RTEXT "@STATIC7",S_STATIC7,14,137,54,10
+ COMBOBOX C_HUBNAME,72,133,126,72,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "@STATIC8",IDC_STATIC,7,161,206,108
+ ICON ICO_TOWER,IDC_STATIC,14,175,20,20
+ LTEXT "@STATIC9",IDC_STATIC,40,175,163,19
+ PUSHBUTTON "@B_IE",B_IE,74,185,114,17
+ RTEXT "@STATIC10",IDC_STATIC,14,205,54,10
+ CONTROL "@R_DIRECT_TCP",R_DIRECT_TCP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,72,203,135,11
+ CONTROL "@R_HTTPS",R_HTTPS,"Button",BS_AUTORADIOBUTTON,72,215,135,11
+ CONTROL "@R_SOCKS",R_SOCKS,"Button",BS_AUTORADIOBUTTON,72,227,135,11
+ PUSHBUTTON "@B_PROXY_CONFIG",B_PROXY_CONFIG,74,243,114,17
+ GROUPBOX "@STATIC11",S_STATIC11,7,275,206,80
+ ICON ICO_CERT,IDC_STATIC,14,287,20,20
+ CONTROL "@R_CHECK_CERT",R_CHECK_CERT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,291,133,10
+ PUSHBUTTON "@B_TRUST",B_TRUST,41,307,157,17
+ PUSHBUTTON "@B_SERVER_CERT",B_SERVER_CERT,41,329,77,17
+ PUSHBUTTON "@B_VIEW_SERVER_CERT",B_VIEW_SERVER_CERT,123,329,75,17
+ CONTROL "@R_HIDE",R_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,360,148,10
+ CONTROL "@R_HIDE2",R_HIDE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158,360,132,10
+ CONTROL "",L_VLAN,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,233,21,200,76
+ GROUPBOX "@S_VLAN_GROUP",S_VLAN_GROUP,224,7,220,102
+ LTEXT "@S_POLICY_1",S_POLICY_1,258,21,163,28,NOT WS_VISIBLE
+ PUSHBUTTON "@B_POLICY",B_POLICY,343,53,77,17,NOT WS_VISIBLE
+ ICON ICO_CASCADE,S_POLICY_2,233,21,20,20,NOT WS_VISIBLE
+ GROUPBOX "@STATIC12",IDC_STATIC,223,115,221,126
+ ICON ICO_KEY,IDC_STATIC,230,127,20,20
+ LTEXT "@STATIC15",IDC_STATIC,251,127,185,20
+ RTEXT "@STATIC13",IDC_STATIC,237,153,48,10
+ COMBOBOX C_TYPE,289,151,126,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_USERNAME",S_USERNAME,230,172,54,10
+ EDITTEXT E_USERNAME,289,170,126,12,ES_AUTOHSCROLL
+ RTEXT "@S_PASSWORD",S_PASSWORD,230,189,54,10,NOT WS_VISIBLE
+ ICON ICO_CERT,S_CERT,248,185,20,20
+ LTEXT "@S_CERT_INFO",S_CERT_INFO,272,187,160,28
+ EDITTEXT E_PASSWORD,289,187,126,12,ES_PASSWORD | ES_AUTOHSCROLL | NOT WS_VISIBLE
+ CTEXT "@S_CHANGE_PASSWORD",S_CHANGE_PASSWORD,244,203,187,11
+ PUSHBUTTON "VIEW_CLIENT_CERT",B_VIEW_CLIENT_CERT,246,215,90,17
+ PUSHBUTTON "@B_REGIST_CLIENT_CERT",B_REGIST_CLIENT_CERT,341,215,90,17
+ PUSHBUTTON "@B_CHANGE_PASSWORD",B_CHANGE_PASSWORD,341,215,90,17
+ GROUPBOX "@STATIC14",IDC_STATIC,223,248,221,100
+ ICON ICO_MACHINE,IDC_STATIC,230,262,20,20
+ CONTROL "@R_RETRY",R_RETRY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,253,263,184,10
+ RTEXT "@S_RETRY_NUM_1",S_RETRY_NUM_1,253,279,61,10
+ EDITTEXT E_RETRY_NUM,318,277,41,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_RETRY_NUM_2",S_RETRY_NUM_2,364,279,73,9
+ RTEXT "@S_RETRY_SPAN_1",S_RETRY_SPAN_1,228,295,86,10
+ EDITTEXT E_RETRY_SPAN,318,293,41,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_RETRY_SPAN_2",S_RETRY_SPAN_2,364,295,72,10
+ CONTROL "@R_INFINITE",R_INFINITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,266,310,171,10
+ CONTROL "@R_NOTLS1",R_NOTLS1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,253,327,87,10
+ PUSHBUTTON "@B_DETAIL",B_DETAIL,344,324,87,17
+ DEFPUSHBUTTON "@IDOK",IDOK,308,351,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,380,351,64,19
+ CONTROL 178,S_ROUTER_LOGO,"Static",SS_BITMAP | NOT WS_VISIBLE,358,7,86,103
+END
+
+D_CM_PROXY DIALOGEX 0, 0, 255, 153
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_PROXY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TOWER,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,26,7,222,29
+ RTEXT "@STATIC2",IDC_STATIC,7,45,74,10
+ EDITTEXT E_HOSTNAME,85,43,126,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC3",IDC_STATIC,7,63,74,9
+ COMBOBOX C_PORT,85,59,48,48,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@STATIC4",IDC_STATIC,7,82,74,11
+ EDITTEXT E_USERNAME,85,80,99,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC5",IDC_STATIC,7,101,74,10
+ EDITTEXT E_PASSWORD,85,99,99,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,115,129,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,184,129,64,17
+ LTEXT "@STATIC6",IDC_STATIC,191,82,57,13
+ LTEXT "@STATIC7",IDC_STATIC,191,101,57,12
+END
+
+D_CM_DETAIL DIALOGEX 0, 0, 435, 365
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_DETAIL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,18,21
+ LTEXT "@STATIC1",IDC_STATIC,33,7,394,23
+ GROUPBOX "@STATIC2",S_STATIC2,7,38,205,319
+ ICON ICO_NIC_ONLINE,IDC_STATIC,15,52,18,21
+ LTEXT "@STATIC3",S_STATIC3,39,52,167,28
+ LTEXT "@STATIC4",S_STATIC4,15,84,130,10
+ COMBOBOX C_NUM_TCP,39,97,33,110,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@STATIC5",S_STATIC5,78,100,125,10
+ LTEXT "@STATIC6",S_STATIC6,39,115,165,18
+ LTEXT "@STATIC7",S_STATIC7,15,138,130,10
+ RTEXT "@STATIC8",S_STATIC8,15,153,106,10
+ EDITTEXT E_INTERVAL,125,151,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC9",S_STATIC9,169,153,38,9
+ CONTROL "@R_USE_DISCONNECT",R_USE_DISCONNECT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,39,171,160,18
+ RTEXT "@STATIC10",S_STATIC10,15,194,105,9
+ EDITTEXT E_DISCONNECT_SPAN,125,192,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC11",S_STATIC11,169,194,40,10
+ LTEXT "@STATIC12",S_STATIC12,15,213,190,78
+ CONTROL "@R_USE_HALF_CONNECTION",R_USE_HALF_CONNECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,294,160,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,311,190,35
+ LTEXT "@STATIC19",S_STATIC19,18,317,184,19
+ CONTROL "@R_DISABLE_QOS",R_DISABLE_QOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,339,161,11
+ GROUPBOX "@STATIC13",S_STATIC133,222,38,205,142
+ ICON ICO_KEY,IDC_STATIC,230,47,18,21
+ LTEXT "@STATIC14",IDC_STATIC,254,47,167,37
+ CONTROL "@R_USE_ENCRYPT",R_USE_ENCRYPT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,87,160,10
+ ICON ICO_VPN,IDC_STATIC,230,104,18,21
+ LTEXT "@S_UDPACCEL",IDC_STATIC,254,104,167,34
+ CONTROL "@R_USE_COMPRESS",R_USE_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,141,160,10
+ CONTROL "@R_DISABLE_UDP",R_DISABLE_UDP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,161,160,10
+ GROUPBOX "@STATIC16",IDC_STATIC,222,185,205,73
+ LTEXT "@S_MODE",S_MODE,254,198,166,19
+ CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,223,166,10
+ CONTROL "@R_MONITOR",R_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,240,166,10
+ GROUPBOX "@STATIC17",IDC_STATIC,222,263,205,34
+ CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,278,181,10
+ ICON ICO_WARNING,S_WARNING_ICON,223,305,18,21
+ LTEXT "@STATIC18",IDC_STATIC,247,305,180,30
+ DEFPUSHBUTTON "@IDOK",IDOK,294,340,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,363,340,64,17
+ ICON ICO_SWITCH,IDC_STATIC,230,198,18,21
+END
+
+D_CM_NEW_VLAN DIALOGEX 0, 0, 251, 115
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_NEW_VLAN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,18,21
+ LTEXT "@S_INFO",S_INFO,32,10,212,27
+ RTEXT "@STATIC1",IDC_STATIC,7,45,93,10
+ EDITTEXT E_NAME,105,43,120,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,112,91,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,180,91,64,17
+ LTEXT "@S_WIN8",S_WIN8,7,65,237,24,NOT WS_VISIBLE
+END
+
+D_CM_TRUST DIALOGEX 0, 0, 335, 228
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_TRUST"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,295,44
+ CONTROL "",L_CERT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP,7,52,321,142
+ PUSHBUTTON "@B_IMPORT",B_IMPORT,7,204,55,17
+ PUSHBUTTON "@B_EXPORT",B_EXPORT,66,204,54,17
+ DEFPUSHBUTTON "@IDOK",IDOK,187,204,62,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,255,204,73,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,126,204,54,17
+END
+
+D_CM_PASSWORD DIALOGEX 0, 0, 277, 186
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,29,7,241,37
+ GROUPBOX "@STATIC1",IDC_STATIC,26,47,222,103
+ CONTROL "@R_USE_PASSWORD",R_USE_PASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,64,190,10
+ CONTROL "@R_REMOTE_ONLY",R_REMOTE_ONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,81,190,10
+ RTEXT "@IDC_STATIC1",IDC_STATIC1,33,104,49,10
+ EDITTEXT E_PASSWORD,87,102,141,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@IDC_STATIC2",IDC_STATIC2,33,124,49,10
+ EDITTEXT E_PASSWORD2,87,122,141,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,158,163,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,218,163,52,16
+END
+
+D_CM_CONFIG DIALOGEX 0, 0, 303, 399
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_CONFIG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,32,7,263,19
+ GROUPBOX "@STATIC2",IDC_STATIC,7,40,288,94
+ ICON ICO_VPN,IDC_STATIC,14,54,20,20
+ LTEXT "@STATIC3",IDC_STATIC,41,55,246,17
+ CONTROL "@R_ALLOW_REMOTE_CONFIG",R_ALLOW_REMOTE_CONFIG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,81,232,12
+ LTEXT "@S_WARNING",S_WARNING,41,94,246,38
+ GROUPBOX "@STATIC7",IDC_STATIC,7,141,288,162
+ ICON ICO_INTERNET,IDC_STATIC,14,155,20,20
+ LTEXT "@STATIC4",IDC_STATIC,41,156,246,29
+ CONTROL "@R_USE_KEEP_CONNECT",R_USE_KEEP_CONNECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,187,232,12
+ RTEXT "@S_HOSTNAME",S_HOSTNAME,16,207,63,10
+ EDITTEXT E_HOSTNAME,82,205,139,12,ES_AUTOHSCROLL
+ RTEXT "@S_PORT",S_PORT,16,227,63,10
+ EDITTEXT E_PORT,82,225,36,12,ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "@S_INTERVAL",S_INTERVAL,131,227,63,11
+ EDITTEXT E_INTERVAL,197,225,36,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_INTERVAL2",S_INTERVAL2,239,227,47,10
+ RTEXT "@S_PROTOCOL",S_PROTOCOL,16,247,63,10
+ CONTROL "@R_TCP",R_TCP,"Button",BS_AUTORADIOBUTTON,85,247,74,10
+ CONTROL "@R_UDP",R_UDP,"Button",BS_AUTORADIOBUTTON,171,247,75,10
+ LTEXT "@S_INFO",S_INFO,41,265,246,36
+ ICON ICO_INFORMATION,S_INFO2,14,260,20,20
+ DEFPUSHBUTTON "@IDOK",IDOK,162,374,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,231,374,64,17
+ GROUPBOX "@STATIC5",IDC_STATIC,7,311,288,54
+ CONTROL "@R_ALPHA",R_ALPHA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,332,105,12
+ EDITTEXT E_ALPHA_VALUE,150,331,27,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "%",IDC_STATIC,185,333,8,11
+ LTEXT "@STATIC6",IDC_STATIC,43,349,243,9
+ ICON ICO_SETUP,S_INFO3,14,329,20,20
+END
+
+D_ABOUT DIALOGEX 0, 0, 333, 361
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_ABOUT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,250,339,76,18
+ CONTROL 224,S_LOGO,"Static",SS_BITMAP,7,6,319,76
+ LTEXT "@S_INFO1",S_INFO1,7,83,319,17
+ LTEXT "@S_INFO2",S_INFO2,7,101,319,39
+ LTEXT "@S_INFO4",S_INFO4,7,143,319,61
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,211,319,1
+ LTEXT "@S_INFO3",S_INFO3,7,217,319,98
+ PUSHBUTTON "@B_EULA",B_EULA,7,315,74,18
+ PUSHBUTTON "@B_IMPORTANT",B_IMPORTANT,88,315,74,18
+ PUSHBUTTON "@B_LEGAL",B_LEGAL,169,315,74,18
+ PUSHBUTTON "Lan&guage Settings",B_LANGUAGE,250,315,75,18
+ PUSHBUTTON "@B_WEB",B_WEB,7,339,130,18
+ PUSHBUTTON "@B_UPDATE_CONFIG",B_UPDATE_CONFIG,142,339,96,18
+END
+
+D_REMOTE DIALOGEX 0, 0, 275, 175
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_REMOTE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TEST,S_ICON,7,7,20,20
+ LTEXT "S_TITLE",S_TITLE,31,7,237,64
+ GROUPBOX "@STATIC1",-1,26,78,222,61
+ CONTROL "@R_LOCAL",R_LOCAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,40,92,200,17
+ RTEXT "@S_HOSTNAME",S_HOSTNAME,28,115,54,12
+ DEFPUSHBUTTON "@IDOK",IDOK,158,152,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,216,152,52,16
+ COMBOBOX C_HOSTNAME,86,113,150,106,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+END
+
+D_CM_DESKTOP DIALOGEX 0, 0, 370, 224
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_DESKTOP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_DISPLAY,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,31,14,332,26
+ LTEXT "@S_WARNING",S_WARNING,31,41,332,23
+ LTEXT "",S_MSG_1,31,65,332,31
+ LTEXT "",S_MSG_2,31,99,332,32
+ LTEXT "",S_MSG_3,31,135,332,44
+ LTEXT "@S_INFO",S_INFO,31,183,332,16
+ DEFPUSHBUTTON "@IDOK",IDOK,253,201,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,311,201,52,16
+END
+
+D_CM_CHANGE_PASSWORD DIALOGEX 0, 0, 259, 248
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_CM_CHANGE_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,14,221,29
+ GROUPBOX "@STATIC1",IDC_STATIC,21,46,209,148
+ RTEXT "@STATIC2",IDC_STATIC,32,65,60,11
+ EDITTEXT E_HUBNAME,99,63,108,12,ES_AUTOHSCROLL | WS_DISABLED
+ RTEXT "@STATIC3",IDC_STATIC,32,87,60,11
+ EDITTEXT E_USERNAME,99,85,108,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,32,109,60,11
+ EDITTEXT E_OLD_PASSWORD,99,107,108,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC5",IDC_STATIC,31,131,60,9
+ EDITTEXT E_NEW_PASSWORD1,99,129,108,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC6",IDC_STATIC,31,151,60,19
+ EDITTEXT E_NEW_PASSWORD2,99,151,108,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,120,224,63,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,189,224,63,17
+ LTEXT "@S_STATIC",S_STATIC,21,199,231,18
+END
+
+D_SM_MAIN DIALOGEX 0, 0, 275, 361
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_SM_MAIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 141,IDC_STATIC,"Static",SS_BITMAP,0,0,275,53
+ GROUPBOX "@STATIC1",IDC_STATIC,6,63,261,218
+ ICON ICO_VPNSERVER,IDC_STATIC,14,79,20,20
+ LTEXT "@STATIC2",IDC_STATIC,41,79,218,33
+ CONTROL "",L_SETTING,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,15,113,242,111
+ PUSHBUTTON "@B_NEW_SETTING",B_NEW_SETTING,15,231,76,16
+ PUSHBUTTON "@B_EDIT_SETTING",B_EDIT_SETTING,98,231,76,16
+ PUSHBUTTON "@B_DELETE",B_DELETE,181,231,76,16
+ PUSHBUTTON "@IDOK",IDOK,181,254,76,19
+ ICON ICO_CERT,IDC_STATIC,147,288,20,20
+ PUSHBUTTON "@B_CERT_TOOL",B_CERT_TOOL,171,290,86,16
+ ICON ICO_SECURE,IDC_STATIC,45,311,20,20
+ PUSHBUTTON "@B_SECURE_MANAGER",B_SECURE_MANAGER,67,314,96,16
+ PUSHBUTTON "@B_SELECT_SECURE",B_SELECT_SECURE,171,314,86,16
+ PUSHBUTTON "@B_ABOUT",B_ABOUT,14,337,76,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,98,337,159,16
+END
+
+D_SM_EDIT_SETTING DIALOGEX 0, 0, 435, 307
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_SETTING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,32,15,396,12
+ RTEXT "@STATIC2",IDC_STATIC,7,33,61,11
+ EDITTEXT E_ACCOUNT_NAME,72,31,126,12,ES_AUTOHSCROLL
+ GROUPBOX "@STATIC3",IDC_STATIC,7,51,206,101
+ ICON ICO_VPNSERVER,IDC_STATIC,14,65,20,20
+ LTEXT "@STATIC4",IDC_STATIC,40,65,166,29
+ RTEXT "@STATIC5",IDC_STATIC,14,101,54,12
+ EDITTEXT E_HOSTNAME,72,99,126,12,ES_AUTOHSCROLL
+ CONTROL "@R_LOCALHOST",R_LOCALHOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,72,115,122,10
+ RTEXT "@STATIC6",IDC_STATIC,14,133,54,12
+ COMBOBOX C_PORT,72,129,81,48,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@STATIC7",IDC_STATIC,159,133,46,11
+ GROUPBOX "@STATIC8",IDC_STATIC,7,169,206,108
+ ICON ICO_TOWER,IDC_STATIC,14,183,20,20
+ LTEXT "@STATIC9",IDC_STATIC,40,183,163,19
+ RTEXT "@STATIC10",IDC_STATIC,14,213,54,11
+ CONTROL "@R_DIRECT_TCP",R_DIRECT_TCP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,72,211,135,11
+ CONTROL "@R_HTTPS",R_HTTPS,"Button",BS_AUTORADIOBUTTON,72,223,135,11
+ CONTROL "@R_SOCKS",R_SOCKS,"Button",BS_AUTORADIOBUTTON,72,235,135,11
+ PUSHBUTTON "@B_PROXY_CONFIG",B_PROXY_CONFIG,74,251,114,17
+ GROUPBOX "@STATIC11",IDC_STATIC,222,51,206,225
+ ICON ICO_USER_ADMIN,IDC_STATIC,229,65,20,20
+ LTEXT "@STATIC12",IDC_STATIC,255,65,165,94
+ CONTROL "@R_SERVER_ADMIN",R_SERVER_ADMIN,"Button",BS_AUTORADIOBUTTON,239,162,82,13
+ CONTROL "@R_HUB_ADMIN",R_HUB_ADMIN,"Button",BS_AUTORADIOBUTTON,324,162,85,13
+ RTEXT "@S_HUBNAME",S_HUBNAME,224,189,61,14
+ COMBOBOX C_HUBNAME,288,185,126,90,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ ICON ICO_KEY,IDC_STATIC,230,217,20,20
+ LTEXT "@STATIC13",IDC_STATIC,251,220,177,18
+ RTEXT "@S_PASSWORD",S_PASSWORD,227,243,60,10
+ EDITTEXT E_PASSWORD,289,241,126,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "@R_NO_SAVE",R_NO_SAVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,290,261,127,10
+ DEFPUSHBUTTON "@IDOK",IDOK,291,281,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,364,281,64,19
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,233,209,183,1
+END
+
+D_SM_SERVER DIALOGEX 0, 0, 439, 367
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SERVER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_VPNSERVER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,322,25
+ CONTROL "",L_HUB,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,14,33,410,112
+ DEFPUSHBUTTON "@IDOK",IDOK,14,151,84,18
+ PUSHBUTTON "@B_ONLINE",B_ONLINE,101,151,48,18
+ PUSHBUTTON "@B_OFFLINE",B_OFFLINE,153,151,47,18
+ PUSHBUTTON "@B_HUB_STATUS",B_HUB_STATUS,203,151,54,18
+ PUSHBUTTON "@B_CREATE",B_CREATE,261,151,70,18
+ PUSHBUTTON "@B_EDIT",B_EDIT,334,151,48,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,385,151,39,18
+ GROUPBOX "@STATIC1",IDC_STATIC,7,174,176,123
+ LTEXT "@STATIC2",IDC_STATIC,14,187,108,10
+ CONTROL "",L_LISTENER,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,14,202,109,88
+ PUSHBUTTON "@B_CREATE_LISTENER",B_CREATE_LISTENER,128,199,48,18
+ PUSHBUTTON "@B_DELETE_LISTENER",B_DELETE_LISTENER,128,223,48,18
+ PUSHBUTTON "@B_START",B_START,128,247,48,18
+ PUSHBUTTON "@B_STOP",B_STOP,128,271,48,18
+ GROUPBOX "@STATIC3",IDC_STATIC,187,174,245,123
+ ICON ICO_KEY,IDC_STATIC,194,189,20,20
+ PUSHBUTTON "@B_SSL",B_SSL,218,191,100,18
+ ICON ICO_TOWER,IDC_STATIC,194,214,20,20
+ PUSHBUTTON "@B_STATUS",B_STATUS,218,217,100,18
+ ICON ICO_VPNSERVER,IDC_STATIC,194,240,20,20
+ PUSHBUTTON "@B_INFO",B_INFO,218,241,100,24,BS_MULTILINE
+ ICON ICO_CERT,S_LICENSE,194,270,20,20
+ PUSHBUTTON "@B_LICENSE",B_LICENSE,218,272,100,18
+ ICON ICO_FARM,IDC_STATIC,323,190,20,20
+ PUSHBUTTON "@B_FARM",B_FARM,344,190,81,18,BS_MULTILINE
+ ICON ICO_INTERNET,IDC_STATIC,323,217,20,20
+ PUSHBUTTON "@B_FARM_STATUS",B_FARM_STATUS,344,217,81,18,BS_MULTILINE
+ ICON ICO_PROTOCOL,IDC_STATIC,323,240,20,20
+ PUSHBUTTON "@B_CONNECTION",B_CONNECTION,344,241,81,24,BS_MULTILINE
+ ICON ICO_MACHINE,IDC_STATIC,323,270,20,20
+ PUSHBUTTON "@B_CONFIG",B_CONFIG,344,272,81,18
+ ICON ICO_BRIDGE,IDC_STATIC,7,301,20,20
+ PUSHBUTTON "@B_BRIDGE",B_BRIDGE,28,304,71,18
+ ICON ICO_SWITCH,IDC_STATIC,108,301,20,20
+ PUSHBUTTON "@B_L3",B_L3,129,304,74,18
+ ICON ICO_IPSEC,IDC_STATIC,206,301,20,20
+ PUSHBUTTON "@B_IPSEC",B_IPSEC,227,304,77,18
+ ICON ICO_OPENVPN,IDC_STATIC,310,302,20,20
+ PUSHBUTTON "@B_OPENVPN",B_OPENVPN,334,304,97,18
+ ICON ICO_DISPLAY,IDC_STATIC,7,327,20,20
+ PUSHBUTTON "@B_DDNS",B_DDNS,28,329,71,18
+ RTEXT "@S_DDNS",S_DDNS,0,354,75,10
+ EDITTEXT E_DDNS_HOST,78,352,114,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ CTEXT "@S_BETA",S_BETA,193,274,126,17
+ PUSHBUTTON "@B_AZURE",B_AZURE,129,329,74,18
+ RTEXT "@S_AZURE",S_AZURE,196,354,65,10
+ EDITTEXT E_AZURE_HOST,266,352,126,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ ICON ICO_RESEARCH,S_ICO_VPNGATE,206,327,20,20
+ PUSHBUTTON "@B_VPNGATE",B_VPNGATE,227,329,77,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,307,329,71,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,381,329,50,18
+ ICON ICO_AZURE,IDC_STATIC,108,328,20,20
+END
+
+D_SM_STATUS DIALOGEX 0, 0, 335, 292
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_STATUS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INFORMATION,S_ICON,7,7,18,21
+ LTEXT "S_TITLE",S_TITLE,30,7,298,29
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,39,321,219
+ DEFPUSHBUTTON "@IDOK",IDOK,177,267,80,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,265,267,63,18
+END
+
+D_SM_EDIT_HUB DIALOGEX 0, 0, 431, 333
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_HUB"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_HUB,IDC_STATIC,7,7,18,21
+ RTEXT "@STATIC1",IDC_STATIC,31,18,54,14
+ EDITTEXT E_HUBNAME,90,16,115,12,ES_AUTOHSCROLL
+ GROUPBOX "@STATIC2",IDC_STATIC,7,34,205,87
+ ICON ICO_KEY,IDC_STATIC,16,46,18,21
+ LTEXT "@S_BOLD",S_BOLD,42,48,151,10
+ RTEXT "@STATIC3",IDC_STATIC,38,63,46,11
+ EDITTEXT E_PASSWORD1,90,61,114,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,29,80,56,12
+ EDITTEXT E_PASSWORD2,90,78,114,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "@R_NO_ENUM",R_NO_ENUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,96,161,23
+ GROUPBOX "@STATIC7",IDC_STATIC,7,126,205,48
+ ICON ICO_HUB_OFFLINE,IDC_STATIC,15,140,18,21
+ LTEXT "@STATIC8",IDC_STATIC,42,140,140,13
+ CONTROL "@R_ONLINE",R_ONLINE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,46,154,56,10
+ CONTROL "@R_OFFLINE",R_OFFLINE,"Button",BS_AUTORADIOBUTTON,118,154,62,10
+ GROUPBOX "@STATIC5",IDC_STATIC,7,181,205,144
+ ICON ICO_MACHINE,IDC_STATIC,16,191,18,21
+ CONTROL "@R_LIMIT_MAX_SESSION",R_LIMIT_MAX_SESSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,191,159,13
+ RTEXT "@S_MAX_SESSION_1",S_MAX_SESSION_1,42,207,86,11
+ EDITTEXT E_MAX_SESSION,135,205,32,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_MAX_SESSION_2",S_MAX_SESSION_2,174,207,29,11
+ LTEXT "@STATIC6",IDC_STATIC,42,219,160,26
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,15,257,190,1
+ ICON ICO_LINK2,S_AO_4,16,265,18,21
+ LTEXT "@STATIC10",S_STATIC,42,267,160,26
+ PUSHBUTTON "@B_EXTOPTION",B_EXTOPTION,76,295,128,19
+ GROUPBOX "@STATIC9",IDC_STATIC,219,34,205,67
+ ICON ICO_FARM,IDC_STATIC,227,48,18,21
+ LTEXT "@S_FARM_INFO",S_FARM_INFO,253,49,163,26
+ CONTROL "@R_STATIC",R_STATIC,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,254,78,81,10
+ CONTROL "@R_DYNAMIC",R_DYNAMIC,"Button",BS_AUTORADIOBUTTON,337,78,83,10
+ GROUPBOX "@S_AO_1",S_AO_1,219,105,205,61
+ ICON ICO_USER_ADMIN,S_AO_2,227,117,18,21
+ LTEXT "@S_AO_3",S_AO_3,252,117,164,19
+ PUSHBUTTON "@B_ADMINOPTION",B_ADMINOPTION,313,139,102,19
+ GROUPBOX "@S_ACL_3",S_ACL_3,219,170,205,63
+ ICON ICO_INTERNET,S_ACL_2,227,184,18,21
+ LTEXT "@S_ACL",S_ACL,252,184,164,18
+ PUSHBUTTON "@B_ACL",B_ACL,313,205,102,19
+ GROUPBOX "@S_MSG_1",S_MSG_1,219,237,205,63
+ ICON ICO_LOG2,S_MSG_4,227,251,18,21
+ LTEXT "@S_MSG_2",S_MSG_2,252,251,164,18
+ PUSHBUTTON "@B_MSG",B_MSG,313,273,102,19
+ DEFPUSHBUTTON "@IDOK",IDOK,291,306,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,360,306,64,19
+END
+
+D_SM_CREATE_LISTENER DIALOGEX 0, 0, 270, 161
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CREATE_LISTENER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PROTOCOL,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,14,230,36
+ LTEXT "@STATIC2",IDC_STATIC,33,85,230,48
+ ICON ICO_INFORMATION,IDC_STATIC,7,86,20,20
+ RTEXT "@STATIC3",IDC_STATIC,39,60,55,10
+ EDITTEXT E_PORT,98,58,35,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ DEFPUSHBUTTON "@IDOK",IDOK,126,135,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,199,135,64,19
+ LTEXT "@STATIC4",IDC_STATIC,137,60,107,9
+END
+
+D_SM_SSL DIALOGEX 0, 0, 463, 365
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SSL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@STATIC1",IDC_STATIC,7,7,449,20
+ GROUPBOX "@STATIC2",IDC_STATIC,7,28,218,77
+ ICON ICO_KEY,IDC_STATIC,14,41,20,20
+ LTEXT "@STATIC3",IDC_STATIC,39,43,179,38
+ RTEXT "@STATIC4",IDC_STATIC,15,87,84,13
+ COMBOBOX C_CIPHER,106,84,110,93,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "@STATIC6",IDC_STATIC,7,109,218,124
+ ICON ICO_SERVER_CERT,IDC_STATIC,14,124,20,20
+ LTEXT "@STATIC7",IDC_STATIC,39,126,178,17
+ GROUPBOX "@STATIC10",IDC_STATIC,38,147,179,53
+ LTEXT "CERT_INFO",S_CERT_INFO,50,159,162,33
+ PUSHBUTTON "@B_REGENERATE",B_REGENERATE,12,205,47,18
+ PUSHBUTTON "@B_IMPORT",B_IMPORT,61,205,47,18
+ PUSHBUTTON "@B_EXPORT",B_EXPORT,110,205,47,18
+ PUSHBUTTON "@B_VIEW",B_VIEW,159,205,56,18
+ GROUPBOX "@STATIC12",IDC_STATIC,7,237,218,101
+ ICON ICO_LOG2,IDC_STATIC,14,249,20,20
+ LTEXT "@STATIC13",IDC_STATIC,35,249,184,28
+ COMBOBOX C_SYSLOG,16,281,199,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@STATIC14",S_01,15,304,84,11
+ EDITTEXT E_SYSLOG_HOSTNAME,102,302,113,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC15",S_02,15,322,84,13
+ EDITTEXT E_SYSLOG_PORT,102,320,32,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ GROUPBOX "@STATIC8",IDC_STATIC,230,28,223,169
+ ICON ICO_INTERNET,IDC_STATIC,233,42,20,20
+ LTEXT "@STATIC9",IDC_STATIC,256,38,179,49
+ CONTROL "@R_USE_KEEP_CONNECT",R_USE_KEEP_CONNECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,255,87,172,12
+ RTEXT "@S_HOSTNAME",S_HOSTNAME,244,107,50,11
+ EDITTEXT E_HOSTNAME,297,105,139,12,ES_AUTOHSCROLL
+ RTEXT "@S_PORT",S_PORT,246,127,48,11
+ EDITTEXT E_PORT,297,125,27,12,ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "@S_INTERVAL",S_INTERVAL,326,127,59,11
+ EDITTEXT E_INTERVAL,387,125,36,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_INTERVAL2",S_INTERVAL2,426,127,21,11
+ RTEXT "@S_PROTOCOL",S_PROTOCOL,238,147,48,11
+ CONTROL "@R_TCP",R_TCP,"Button",BS_AUTORADIOBUTTON,292,147,72,10
+ CONTROL "@R_UDP",R_UDP,"Button",BS_AUTORADIOBUTTON,369,147,76,10
+ ICON ICO_INFORMATION,S_INFO2,233,161,20,20
+ LTEXT "@S_INFO",S_INFO,256,165,194,26
+ GROUPBOX "@STATIC11",IDC_STATIC,230,202,226,61
+ LTEXT "@S_INFO4",S_INFO4,237,213,210,19
+ ICON ICO_USER_ADMIN,IDC_STATIC,322,235,20,20
+ PUSHBUTTON "@B_PASSWORD",B_PASSWORD,347,237,98,18
+ GROUPBOX "@S_OVER_FUNCS",IDC_STATIC,230,268,226,64
+ LTEXT "@S_INFO5",S_INFO5,236,282,210,26
+ ICON ICO_SPECIALLISTENER,IDC_STATIC,322,306,20,20
+ PUSHBUTTON "@B_SPECIALLISTENER",B_SPECIALLISTENER,346,308,98,18
+ PUSHBUTTON "@B_UPDATE_CONFIG",B_UPDATE_CONFIG,230,339,85,19
+ DEFPUSHBUTTON "@IDOK",IDOK,321,339,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,392,339,64,19
+END
+
+D_SM_SAVE_KEY_PAIR DIALOGEX 0, 0, 295, 348
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SAVE_KEY_PAIR"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@STATIC1",IDC_STATIC,7,7,281,17
+ GROUPBOX "@STATIC2",IDC_STATIC,7,27,281,195
+ CONTROL "@R_X509_AND_KEY",R_X509_AND_KEY,"Button",BS_AUTORADIOBUTTON,14,39,249,10
+ CONTROL "@R_PKCS12",R_PKCS12,"Button",BS_AUTORADIOBUTTON,14,81,249,10
+ CONTROL "@R_SECURE",R_SECURE,"Button",BS_AUTORADIOBUTTON,14,127,249,10
+ ICON ICO_CERT,IDC_STATIC,26,50,20,20
+ LTEXT "@STATIC3",IDC_STATIC,51,51,218,28
+ ICON ICO_PKCS12,IDC_STATIC,26,98,20,20
+ LTEXT "@STATIC4",IDC_STATIC,51,98,224,28
+ ICON ICO_SECURE,IDC_STATIC,26,141,20,20
+ LTEXT "@STATIC5",IDC_STATIC,51,144,224,19
+ PUSHBUTTON "@B_SELECT",B_SELECT,50,168,110,20
+ GROUPBOX "@S_PASS3",S_PASS3,7,227,281,90
+ ICON ICO_KEY,IDC_STATIC,14,241,20,20
+ LTEXT "@S_PASS4",S_PASS4,39,242,242,20
+ CONTROL "@R_USE_PASS",R_USE_PASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,38,265,144,10
+ RTEXT "@S_PASS1",S_PASS1,31,280,56,12
+ EDITTEXT E_PASS1,94,279,158,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@S_PASS2",S_PASS2,31,299,56,12
+ EDITTEXT E_PASS2,94,297,158,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,150,322,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,224,322,64,19
+ LTEXT "",S_INFO,52,190,227,26
+ PUSHBUTTON "@B_SECURE_MANAGER",B_SECURE_MANAGER,169,168,110,20,NOT WS_VISIBLE
+END
+
+D_SM_CONNECTION DIALOGEX 0, 0, 318, 272
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CONNECTION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PROTOCOL,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,32,7,279,21
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,304,201
+ DEFPUSHBUTTON "@IDOK",IDOK,7,247,99,18
+ PUSHBUTTON "@B_DISCONNECT",B_DISCONNECT,113,247,49,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,169,247,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,258,247,51,18
+END
+
+D_SM_FARM DIALOGEX 0, 0, 259, 388
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_FARM"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_FARM,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,33,7,219,18
+ LTEXT "@STATIC1",IDC_STATIC,7,36,245,22
+ RTEXT "@STATIC2",IDC_STATIC,7,60,69,10
+ LTEXT "--",S_CURRENT,82,58,154,16
+ GROUPBOX "@STATIC3",IDC_STATIC,7,76,245,242
+ CONTROL "@R_STANDALONE",R_STANDALONE,"Button",BS_AUTORADIOBUTTON,14,86,180,10
+ CONTROL "@R_CONTROLLER",R_CONTROLLER,"Button",BS_AUTORADIOBUTTON,14,101,119,10
+ CONTROL "@R_MEMBER",R_MEMBER,"Button",BS_AUTORADIOBUTTON,14,117,117,10
+ GROUPBOX "@STATIC4",IDC_STATIC,25,153,220,157
+ ICON ICO_PROTOCOL,IDC_STATIC,32,168,18,21
+ RTEXT "@S_IP_1",S_IP_1,59,169,59,10
+ CONTROL "",E_IP,"SysIPAddress32",WS_TABSTOP,122,166,75,13
+ LTEXT "@S_IP_2",S_IP_2,74,183,164,29
+ RTEXT "@S_PORT_1",S_PORT_1,59,218,59,11
+ EDITTEXT E_PORT,122,216,117,12,ES_AUTOHSCROLL
+ RTEXT "@S_PORT_2",S_PORT_2,62,232,179,11
+ RTEXT "@S_CONTROLLER",S_CONTROLLER,55,245,63,20
+ EDITTEXT E_CONTROLLER,122,248,85,12,ES_AUTOHSCROLL
+ RTEXT "@S_CONTROLLER_PORT",S_CONTROLLER_PORT,59,266,59,18
+ EDITTEXT E_CONTROLLER_PORT,122,268,39,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_PORT_3",S_PORT_3,165,271,59,10
+ RTEXT "@S_PASSWORD",S_PASSWORD,27,293,92,12
+ EDITTEXT E_PASSWORD,122,290,117,12,ES_PASSWORD | ES_AUTOHSCROLL
+ ICON ICO_WARNING,IDC_STATIC,7,322,18,21
+ LTEXT "@STATIC5",IDC_STATIC,32,322,220,37
+ DEFPUSHBUTTON "@IDOK",IDOK,115,362,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,188,362,64,19
+ RTEXT "@S_1",S_1,14,138,104,10
+ EDITTEXT E_WEIGHT,122,136,34,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_2",S_2,161,138,71,12
+ CONTROL "@R_CONTROLLER_ONLY",R_CONTROLLER_ONLY,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,146,100,98,35
+END
+
+D_SM_FARM_MEMBER DIALOGEX 0, 0, 415, 265
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_FARM_MEMBER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_FARM,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,32,7,376,22
+ CONTROL "",L_FARM_MEMBER,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,34,401,198
+ DEFPUSHBUTTON "@IDOK",IDOK,7,240,122,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,268,240,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,357,240,51,18
+ PUSHBUTTON "@B_CERT",B_CERT,132,240,93,18
+END
+
+D_SM_CHANGE_PASSWORD DIALOGEX 0, 0, 250, 112
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CHANGE_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_USER_ADMIN,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,212,20
+ RTEXT "@STATIC1",IDC_STATIC,7,41,65,11
+ EDITTEXT E_PASSWORD1,78,39,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC2",IDC_STATIC,7,60,65,11
+ EDITTEXT E_PASSWORD2,78,58,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,106,86,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,179,86,64,19
+END
+
+D_SM_HUB DIALOGEX 0, 0, 403, 359
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_HUB"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_TITLE",S_TITLE,7,7,176,19,SS_WORDELLIPSIS
+ GROUPBOX "@STATIC1",IDC_STATIC,7,29,173,145
+ ICON ICO_USER,IDC_STATIC,14,38,20,20
+ PUSHBUTTON "@B_USER",B_USER,38,40,104,17
+ LTEXT "@S_USER",S_USER,38,61,132,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,75,156,1
+ ICON ICO_GROUP,IDC_STATIC,14,82,20,20
+ PUSHBUTTON "@B_GROUP",B_GROUP,38,84,104,17
+ LTEXT "@S_GROUP",S_GROUP,38,106,132,12
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,120,156,1
+ ICON ICO_PASS,IDC_STATIC,14,127,20,20
+ PUSHBUTTON "@B_ACCESS",B_ACCESS,38,129,104,17
+ LTEXT "@S_ACCESS",S_ACCESS,38,151,132,20
+ GROUPBOX "@STATIC2",IDC_STATIC,7,181,173,170
+ ICON ICO_HUB,IDC_STATIC,14,193,20,20
+ PUSHBUTTON "@B_PROPERTY",B_PROPERTY,38,193,104,17
+ LTEXT "@S_PROPERTY",S_PROPERTY,40,213,137,17
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,231,156,1
+ ICON ICO_TOWER,IDC_STATIC,14,237,20,20
+ PUSHBUTTON "@B_RADIUS",B_RADIUS,38,239,104,17
+ LTEXT "@S_RADIUS",S_RADIUS,38,260,132,27
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,288,156,1
+ ICON ICO_CASCADE,IDC_STATIC,14,297,20,20
+ PUSHBUTTON "@B_LINK",B_LINK,38,299,104,17
+ LTEXT "@S_LINK",S_LINK,38,320,132,26
+ GROUPBOX "@STATIC3",IDC_STATIC,188,7,208,167
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,194,21,191,125
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,303,150,82,18
+ GROUPBOX "@STATIC4",IDC_STATIC,187,178,209,130
+ ICON ICO_LOG2,IDC_STATIC,192,188,20,20
+ PUSHBUTTON "@B_LOG",B_LOG,216,188,100,17
+ PUSHBUTTON "@B_LOG_FILE",B_LOG_FILE,321,188,63,17
+ LTEXT "@S_LOG",S_LOG,216,209,173,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,192,221,193,1
+ ICON ICO_SERVER_CERT,IDC_STATIC,192,224,20,20
+ PUSHBUTTON "@B_CA",B_CA,216,226,100,17
+ PUSHBUTTON "@B_CRL",B_CRL,321,226,63,17
+ LTEXT "@S_CA",S_CA,216,244,170,17
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,193,261,193,1
+ ICON ICO_ROUTER,IDC_STATIC,192,263,20,20
+ PUSHBUTTON "@B_SNAT",B_SNAT,215,266,169,17
+ LTEXT "@S_SNAT",S_SNAT,215,286,170,18
+ GROUPBOX "@STATIC5",IDC_STATIC,187,311,140,40
+ ICON ICO_VPN,IDC_STATIC,194,323,20,20
+ PUSHBUTTON "@B_SESSION",B_SESSION,221,327,100,17,BS_MULTILINE
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,336,333,60,18
+END
+
+D_SM_USER DIALOGEX 0, 0, 454, 281
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_USER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_USER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,416,15
+ CONTROL "",L_USER,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,32,440,218
+ DEFPUSHBUTTON "@IDOK",IDOK,83,257,65,17
+ PUSHBUTTON "@B_CREATE",B_CREATE,13,257,65,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,226,257,65,17
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,297,257,81,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,382,257,65,17
+ PUSHBUTTON "@B_STATUS",B_STATUS,153,257,68,17
+END
+
+D_SM_EDIT_USER DIALOGEX 0, 0, 455, 352
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_USER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_USER,IDC_STATIC,7,7,20,20
+ RTEXT "@IDC_STATIC1",IDC_STATIC1,31,16,44,10
+ EDITTEXT E_USERNAME,80,14,154,12,ES_AUTOHSCROLL
+ RTEXT "@IDC_STATIC3",IDC_STATIC3,7,35,68,10
+ EDITTEXT E_REALNAME,80,33,154,12,ES_AUTOHSCROLL
+ RTEXT "@IDC_STATIC4",IDC_STATIC4,7,55,68,9
+ EDITTEXT E_NOTE,80,53,154,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,71,226,1
+ ICON ICO_GROUP,IDC_STATIC,7,79,20,20
+ RTEXT "@IDC_STATIC5",IDC_STATIC5,31,82,44,24
+ EDITTEXT E_GROUP,80,84,80,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_GROUP",B_GROUP,164,80,70,18
+ ICON ICO_DATETIME,IDC_STATIC,7,105,20,20
+ CONTROL "@R_EXPIRES",R_EXPIRES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,106,161,10
+ CONTROL "",E_EXPIRES_DATE,"SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,48,121,75,15
+ CONTROL "",E_EXPIRES_TIME,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP,131,121,67,15
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,143,227,1
+ RTEXT "@IDC_STATIC6",IDC_STATIC6,7,151,68,11
+ CONTROL "",L_AUTH,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,80,150,120,76
+ GROUPBOX "@S_RADIUS_3",S_RADIUS_3,7,232,229,87
+ ICON ICO_TOWER,IDC_STATIC,14,244,20,20
+ LTEXT "@S_RADIUS_1",S_RADIUS_1,35,246,195,27
+ CONTROL "@R_SET_RADIUS_USERNAME",R_SET_RADIUS_USERNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,276,184,10
+ RTEXT "@S_RADIUS_2",S_RADIUS_2,11,292,113,13
+ EDITTEXT E_RADIUS_USERNAME,127,290,101,12,ES_AUTOHSCROLL
+ GROUPBOX "@S_POLICY_1",S_POLICY_1,242,7,206,40
+ ICON ICO_MACHINE,IDC_STATIC,249,19,20,20
+ CONTROL "@R_POLICY",R_POLICY,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,281,19,83,21
+ PUSHBUTTON "@B_POLICY",B_POLICY,367,21,73,18
+ GROUPBOX "@S_PASSWORD_1",S_PASSWORD_1,242,56,206,53
+ ICON ICO_KEY,IDC_STATIC,249,70,20,20
+ RTEXT "@S_PASSWORD_2",S_PASSWORD_2,275,74,70,10
+ EDITTEXT E_PASSWORD1,348,72,92,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@S_PASSWORD_3",S_PASSWORD_3,270,92,75,10
+ EDITTEXT E_PASSWORD2,348,90,92,12,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "@S_USER_CERT_1",S_USER_CERT_1,242,114,206,82
+ ICON ICO_CERT,IDC_STATIC,249,126,20,20
+ LTEXT "S_CERT_INFO\r\nS_CERT_INFO\r\nS_CERT_INFO\r\nS_CERT_INFO",S_CERT_INFO,272,128,176,40
+ PUSHBUTTON "@B_LOAD_CERT",B_LOAD_CERT,248,170,57,18
+ PUSHBUTTON "@B_VIEW_CERT",B_VIEW_CERT,308,170,58,18
+ PUSHBUTTON "@B_CREATE",B_CREATE,369,170,75,18
+ GROUPBOX "@S_ROOT_CERT_1",S_ROOT_CERT_1,242,197,206,122
+ ICON ICO_SERVER_CERT,IDC_STATIC,249,214,20,20
+ LTEXT "@S_ROOT_CERT_2",S_ROOT_CERT_2,272,210,168,31
+ CONTROL "@R_CN",R_CN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,257,240,184,10
+ EDITTEXT E_CN,267,254,174,12,ES_AUTOHSCROLL
+ CONTROL "@R_SERIAL",R_SERIAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,257,272,184,10
+ EDITTEXT E_SERIAL,267,286,174,12,ES_AUTOHSCROLL
+ RTEXT "@S_ROOT_CERT_3",S_ROOT_CERT_3,267,303,170,11
+ DEFPUSHBUTTON "@IDOK",IDOK,311,326,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,384,326,64,19
+ LTEXT "@S_HINT",S_HINT,7,322,299,30
+END
+
+D_SM_POLICY DIALOGEX 0, 0, 450, 341
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_POLICY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,20,20
+ LTEXT "S_TITLE",S_TITLE,30,7,281,19
+ CONTROL "",L_POLICY,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,33,257,269
+ GROUPBOX "@STATIC1",IDC_STATIC,270,30,173,274
+ LTEXT "S_POLICY_TITLE S_POLICY_TITLE S_POLICY_TITLE S_POLICY_TITLE ",S_POLICY_TITLE,278,45,158,30
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,277,80,159,1
+ EDITTEXT E_POLICY_DESCRIPTION,277,99,157,56,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+ LTEXT "@S_BOLD",S_BOLD,277,86,114,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,277,165,158,1
+ LTEXT "@S_BOLD2",S_BOLD2,277,173,114,11
+ CONTROL "@R_ENABLE",R_ENABLE,"Button",BS_AUTORADIOBUTTON,284,189,149,14
+ CONTROL "@R_DISABLE",R_DISABLE,"Button",BS_AUTORADIOBUTTON,284,208,149,14
+ CONTROL "@R_DEFINE",R_DEFINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,284,191,151,11
+ EDITTEXT E_VALUE,293,207,74,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "S_TANI",S_TANI,371,209,64,12
+ LTEXT "S_LIMIT",S_LIMIT,294,227,142,34
+ DEFPUSHBUTTON "@IDOK",IDOK,306,315,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,379,315,64,19
+END
+
+D_SM_GROUP DIALOGEX 0, 0, 334, 282
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_GROUP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_GROUP,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,31,7,252,18
+ CONTROL "",L_GROUP,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,32,320,218
+ PUSHBUTTON "@B_CREATE",B_CREATE,8,258,51,17
+ DEFPUSHBUTTON "@IDOK",IDOK,64,258,36,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,105,258,40,17
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,150,258,69,17
+ PUSHBUTTON "@B_USER",B_USER,224,258,51,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,280,258,47,17
+END
+
+D_SM_EDIT_GROUP DIALOGEX 0, 0, 243, 298
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_GROUP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_GROUP,IDC_STATIC,7,7,20,20
+ RTEXT "@IDC_STATIC1",IDC_STATIC1,31,16,44,12
+ EDITTEXT E_GROUPNAME,80,14,154,12,ES_AUTOHSCROLL
+ RTEXT "@IDC_STATIC3",IDC_STATIC3,7,35,68,12
+ EDITTEXT E_REALNAME,80,33,154,12,ES_AUTOHSCROLL
+ RTEXT "@IDC_STATIC4",IDC_STATIC4,7,55,68,12
+ EDITTEXT E_NOTE,80,53,154,12,ES_AUTOHSCROLL
+ GROUPBOX "@S_POLICY_1",S_POLICY_1,7,76,229,40
+ ICON ICO_MACHINE,IDC_STATIC,14,88,20,20
+ CONTROL "@R_POLICY",R_POLICY,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,40,87,104,21
+ PUSHBUTTON "@B_POLICY",B_POLICY,154,90,73,18
+ GROUPBOX "@S_POLICY_2",S_POLICY_2,7,123,229,144
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,14,138,213,118
+ DEFPUSHBUTTON "@IDOK",IDOK,98,272,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,172,272,64,19
+END
+
+D_SM_ACCESS_LIST DIALOGEX 0, 0, 451, 322
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_ACCESS_LIST"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PASS,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,7,411,23
+ CONTROL "",L_ACCESS_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,34,364,257
+ PUSHBUTTON "@B_ADD",B_ADD,376,33,68,18
+ PUSHBUTTON "@B_ADD_V6",B_ADD_V6,376,55,68,18
+ DEFPUSHBUTTON "@IDOK",IDOK,376,77,68,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,376,99,68,18
+ PUSHBUTTON "@B_CLONE",B_CLONE,376,138,68,18
+ PUSHBUTTON "@B_ENABLE",B_ENABLE,376,178,68,18
+ PUSHBUTTON "@B_DISABLE",B_DISABLE,376,200,68,18
+ LTEXT "@STATIC1",IDC_STATIC,377,238,67,28
+ PUSHBUTTON "@B_SAVE",B_SAVE,376,272,68,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,376,297,68,18
+ ICON ICO_INFORMATION,IDC_STATIC,7,294,20,20
+ LTEXT "@STATIC2",IDC_STATIC,28,295,340,20
+END
+
+D_SM_EDIT_ACCESS DIALOGEX 0, 0, 459, 411
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_ACCESS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PASS,S_ICON,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,421,19
+ GROUPBOX "@STATIC2",IDC_STATIC,7,34,217,71
+ RTEXT "@STATIC3",IDC_STATIC,14,51,71,11
+ EDITTEXT E_NOTE,91,49,115,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,14,69,71,9
+ CONTROL "@R_PASS",R_PASS,"Button",BS_AUTORADIOBUTTON,91,64,47,18
+ CONTROL "@R_DISCARD",R_DISCARD,"Button",BS_AUTORADIOBUTTON,142,64,51,18
+ RTEXT "@STATIC5",IDC_STATIC,14,88,71,10
+ EDITTEXT E_PRIORITY,91,86,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC6",IDC_STATIC,134,85,73,18
+ GROUPBOX "@STATIC11",S_STATIC11,7,108,217,112
+ ICON ICO_USER,IDC_STATIC,11,119,20,20
+ LTEXT "@STATIC12",S_STATIC12,34,121,177,28
+ RTEXT "@STATIC13",S_STATIC13,12,155,73,12
+ EDITTEXT E_USERNAME1,89,153,84,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_USER1",B_USER1,179,151,41,18
+ RTEXT "@STATIC14",S_STATIC14,13,178,72,12
+ EDITTEXT E_USERNAME2,89,176,84,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_USER2",B_USER2,179,174,41,18
+ LTEXT "@STATIC15",S_STATIC15,56,195,156,22
+ GROUPBOX "@STATIC16",IDC_STATIC,7,223,217,152
+ RTEXT "@S_CHECK_SRC_MAC",S_CHECK_SRC_MAC,14,235,71,10
+ CONTROL "@R_CHECK_SRC_MAC",R_CHECK_SRC_MAC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,233,121,10
+ RTEXT "@S_SRC_MAC",S_SRC_MAC,14,250,108,10
+ EDITTEXT E_SRC_MAC,128,248,78,12,ES_AUTOHSCROLL
+ RTEXT "@S_SRC_MAC_MASK",S_SRC_MAC_MASK,14,267,108,10
+ EDITTEXT E_SRC_MAC_MASK,128,265,78,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,18,283,193,1
+ RTEXT "@S_CHECK_DST_MAC",S_CHECK_DST_MAC,13,289,71,10
+ CONTROL "@R_CHECK_DST_MAC",R_CHECK_DST_MAC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,287,121,10
+ RTEXT "@S_DST_MAC",S_DST_MAC,14,304,108,10
+ EDITTEXT E_DST_MAC,128,302,78,12,ES_AUTOHSCROLL
+ RTEXT "@S_DST_MAC_MASK",S_DST_MAC_MASK,14,322,108,10
+ EDITTEXT E_DST_MAC_MASK,128,320,78,12,ES_AUTOHSCROLL
+ LTEXT "@S_MAC_NOTE",S_MAC_NOTE,18,337,197,30
+ GROUPBOX "@STATIC7",IDC_STATIC,232,34,220,211
+ RTEXT "@S_ACCESS_SRC_ALL",S_ACCESS_SRC_ALL,237,50,71,10
+ CONTROL "@R_SRC_ALL",R_SRC_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,311,48,121,10
+ RTEXT "@S_SRC_IP_1",S_SRC_IP_1,237,64,108,10
+ CONTROL "",E_SRC_IP,"SysIPAddress32",WS_TABSTOP,349,62,75,13
+ RTEXT "@S_SRC_IP_2",S_SRC_IP_2,237,82,108,9
+ CONTROL "",E_SRC_MASK,"SysIPAddress32",WS_TABSTOP,349,80,75,13
+ RTEXT "@S_SRC_IP_3",S_SRC_IP_3,237,102,195,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,118,208,1
+ RTEXT "@S_ACCESS_DST_ALL",S_ACCESS_DST_ALL,237,128,71,10
+ CONTROL "@R_DST_ALL",R_DST_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,311,126,121,10
+ RTEXT "@S_IP_DST_1",S_IP_DST_1,237,142,108,10
+ CONTROL "",E_DST_IP,"SysIPAddress32",WS_TABSTOP,349,140,75,13
+ RTEXT "@S_IP_DST_2",S_IP_DST_2,237,160,108,10
+ CONTROL "",E_DST_MASK,"SysIPAddress32",WS_TABSTOP,349,158,75,13
+ RTEXT "@S_IP_DST_3",S_IP_DST_3,237,178,197,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,196,208,1
+ RTEXT "@STATIC9",IDC_STATIC,237,206,71,12
+ COMBOBOX C_PROTOCOL,313,204,110,87,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_PROTOID",S_PROTOID,237,226,71,10
+ EDITTEXT E_IP_PROTO,313,224,37,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ GROUPBOX "@STATIC10",IDC_STATIC,232,247,220,129
+ LTEXT "@S_TCP_1",S_TCP_1,318,259,31,10
+ LTEXT "@S_TCP_2",S_TCP_2,370,259,31,10
+ RTEXT "@S_TCP_3",S_TCP_3,234,273,71,10
+ EDITTEXT E_SRC_PORT_1,311,271,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "-",S_TCP_4,356,273,8,8
+ EDITTEXT E_SRC_PORT_2,365,271,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "@S_TCP_5",S_TCP_5,234,291,71,10
+ EDITTEXT E_DST_PORT_1,311,289,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "-",S_TCP_6,356,291,8,8
+ EDITTEXT E_DST_PORT_2,365,289,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_TCP_7",S_TCP_7,240,308,204,25
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,340,208,1
+ CONTROL "@R_CHECK_TCP_STATE",R_CHECK_TCP_STATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,346,158,10
+ CONTROL "@R_ESTABLISHED",R_ESTABLISHED,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,268,360,71,10
+ CONTROL "@R_UNESTABLISHED",R_UNESTABLISHED,"Button",BS_AUTORADIOBUTTON,351,360,80,10
+ CONTROL "@R_REDIRECT",R_REDIRECT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,383,113,21
+ PUSHBUTTON "@B_REDIRECT",B_REDIRECT,122,385,78,19
+ PUSHBUTTON "@B_SIMULATION",B_SIMULATION,207,385,103,19
+ DEFPUSHBUTTON "@IDOK",IDOK,320,385,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,388,385,64,19
+END
+
+D_SM_RADIUS DIALOGEX 0, 0, 283, 324
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_RADIUS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TOWER,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,30,7,236,29
+ GROUPBOX "@STATIC1",IDC_STATIC,7,46,269,200
+ CONTROL "@R_USE_RADIUS",R_USE_RADIUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,61,255,14
+ RTEXT "@S_RADIUS_1",S_RADIUS_1,14,81,95,18
+ EDITTEXT E_HOSTNAME,115,84,154,12,ES_AUTOHSCROLL
+ RTEXT "@S_RADIUS_2",S_RADIUS_2,14,119,95,13
+ EDITTEXT E_PORT,115,117,41,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_RADIUS3",S_RADIUS3,162,119,106,13
+ RTEXT "@S_RADIUS_4",S_RADIUS_4,14,139,95,11
+ EDITTEXT E_SECRET1,115,137,154,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@S_RADIUS_5",S_RADIUS_5,14,158,95,11
+ EDITTEXT E_SECRET2,115,156,154,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@S_RADIUS_8",S_RADIUS_8,14,176,95,11
+ EDITTEXT E_RADIUS_RETRY_INTERVAL,115,174,41,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_RADIUS_7",S_RADIUS_7,163,177,106,18
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,199,255,1
+ ICON ICO_INFORMATION,IDC_STATIC,14,205,18,21
+ LTEXT "@S_RADIUS_6",S_RADIUS_6,38,205,231,31
+ ICON ICO_LINK,IDC_STATIC,14,247,18,21
+ LTEXT "@STATIC2",IDC_STATIC,38,251,230,37
+ DEFPUSHBUTTON "@IDOK",IDOK,139,298,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,212,298,64,19
+ LTEXT "@S_RADIUS_9",S_RADIUS_9,116,99,152,11
+END
+
+D_SM_LINK DIALOGEX 0, 0, 423, 313
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_LINK"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CASCADE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,29,7,387,19
+ GROUPBOX "@STATIC2",IDC_STATIC,26,29,357,49
+ ICON ICO_WARNING,IDC_STATIC,31,41,20,20
+ LTEXT "@STATIC3",IDC_STATIC,54,40,324,28
+ CONTROL "",L_LINK,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,7,87,409,192
+ PUSHBUTTON "@B_CREATE",B_CREATE,12,289,52,17
+ PUSHBUTTON "@B_EDIT",B_EDIT,68,289,40,17
+ PUSHBUTTON "@B_ONLINE",B_ONLINE,112,289,44,17
+ PUSHBUTTON "@B_OFFLINE",B_OFFLINE,160,289,44,17
+ DEFPUSHBUTTON "@IDOK",IDOK,208,289,41,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,253,289,41,17
+ PUSHBUTTON "@B_RENAME",B_RENAME,298,289,60,17
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,398,48,18,17,NOT WS_VISIBLE
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,373,289,43,17
+END
+
+D_SM_LOG DIALOGEX 0, 0, 279, 389
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_LOG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_LOG2,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,30,7,242,28
+ GROUPBOX "@STATIC1",IDC_STATIC,7,46,265,58
+ ICON ICO_MACHINE,IDC_STATIC,14,59,20,20
+ CONTROL "@B_SEC",B_SEC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,60,225,10
+ RTEXT "@S_SEC",S_SEC,39,76,98,11
+ COMBOBOX C_SEC_SWITCH,142,73,121,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "@STATIC2",IDC_STATIC,7,111,265,210
+ ICON ICO_NIC_ONLINE,IDC_STATIC,14,125,20,20
+ CONTROL "@B_PACKET",B_PACKET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,125,225,10
+ RTEXT "@S_PACKET",S_PACKET,39,141,98,11
+ COMBOBOX C_PACKET_SWITCH,142,139,121,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_PACKET_0",S_PACKET_0,19,169,58,11
+ CONTROL "@B_PACKET_0_0",B_PACKET_0_0,"Button",BS_AUTORADIOBUTTON,82,167,45,10
+ CONTROL "@B_PACKET_0_1",B_PACKET_0_1,"Button",BS_AUTORADIOBUTTON,128,167,52,10
+ CONTROL "@B_PACKET_0_2",B_PACKET_0_2,"Button",BS_AUTORADIOBUTTON,181,167,78,10
+ RTEXT "@S_PACKET_1",S_PACKET_1,19,185,58,11
+ CONTROL "@B_PACKET_1_0",B_PACKET_1_0,"Button",BS_AUTORADIOBUTTON,82,184,45,10
+ CONTROL "@B_PACKET_1_1",B_PACKET_1_1,"Button",BS_AUTORADIOBUTTON,128,184,52,10
+ CONTROL "@B_PACKET_1_2",B_PACKET_1_2,"Button",BS_AUTORADIOBUTTON,181,184,78,10
+ RTEXT "@S_PACKET_2",S_PACKET_2,19,202,58,12
+ CONTROL "@B_PACKET_2_0",B_PACKET_2_0,"Button",BS_AUTORADIOBUTTON,82,201,45,10
+ CONTROL "@B_PACKET_2_1",B_PACKET_2_1,"Button",BS_AUTORADIOBUTTON,128,201,52,10
+ CONTROL "@B_PACKET_2_2",B_PACKET_2_2,"Button",BS_AUTORADIOBUTTON,181,201,78,10
+ RTEXT "@S_PACKET_3",S_PACKET_3,19,219,58,10
+ CONTROL "@B_PACKET_3_0",B_PACKET_3_0,"Button",BS_AUTORADIOBUTTON,82,218,44,10
+ CONTROL "@B_PACKET_3_1",B_PACKET_3_1,"Button",BS_AUTORADIOBUTTON,128,218,52,10
+ CONTROL "@B_PACKET_3_2",B_PACKET_3_2,"Button",BS_AUTORADIOBUTTON,181,218,78,10
+ RTEXT "@S_PACKET_4",S_PACKET_4,19,235,58,11
+ CONTROL "@B_PACKET_4_0",B_PACKET_4_0,"Button",BS_AUTORADIOBUTTON,82,235,45,10
+ CONTROL "@B_PACKET_4_1",B_PACKET_4_1,"Button",BS_AUTORADIOBUTTON,128,235,52,10
+ CONTROL "@B_PACKET_4_2",B_PACKET_4_2,"Button",BS_AUTORADIOBUTTON,181,235,78,10
+ RTEXT "@S_PACKET_5",S_PACKET_5,19,252,58,11
+ CONTROL "@B_PACKET_5_0",B_PACKET_5_0,"Button",BS_AUTORADIOBUTTON,82,252,45,10
+ CONTROL "@B_PACKET_5_1",B_PACKET_5_1,"Button",BS_AUTORADIOBUTTON,128,252,52,10
+ CONTROL "@B_PACKET_5_2",B_PACKET_5_2,"Button",BS_AUTORADIOBUTTON,181,252,78,10
+ RTEXT "@S_PACKET_6",S_PACKET_6,19,269,58,10
+ CONTROL "@B_PACKET_6_0",B_PACKET_6_0,"Button",BS_AUTORADIOBUTTON,82,269,45,10
+ CONTROL "@B_PACKET_6_1",B_PACKET_6_1,"Button",BS_AUTORADIOBUTTON,128,269,52,10
+ CONTROL "@B_PACKET_6_2",B_PACKET_6_2,"Button",BS_AUTORADIOBUTTON,181,269,78,10
+ RTEXT "@S_PACKET_7",S_PACKET_7,19,284,58,19
+ CONTROL "@B_PACKET_7_0",B_PACKET_7_0,"Button",BS_AUTORADIOBUTTON,82,285,45,10
+ CONTROL "@B_PACKET_7_1",B_PACKET_7_1,"Button",BS_AUTORADIOBUTTON,128,286,53,10
+ CONTROL "@B_PACKET_7_2",B_PACKET_7_2,"Button",BS_AUTORADIOBUTTON,181,286,78,10
+ DEFPUSHBUTTON "@IDOK",IDOK,135,363,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,208,363,64,19
+ ICON ICO_WARNING,IDC_STATIC,7,328,20,20
+ LTEXT "@STATIC3",IDC_STATIC,29,327,243,35
+END
+
+D_SM_CA DIALOGEX 0, 0, 335, 228
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_CERT,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,295,35
+ CONTROL "",L_CERT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP,7,50,321,144
+ PUSHBUTTON "@B_IMPORT",B_IMPORT,81,203,55,17
+ DEFPUSHBUTTON "@IDOK",IDOK,203,203,62,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,273,203,55,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,142,203,54,17
+END
+
+D_SM_SESSION DIALOGEX 0, 0, 453, 362
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SESSION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_VPN,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,35,7,411,19
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,439,222
+ GROUPBOX "@STATIC1",IDC_STATIC,7,263,434,43
+ DEFPUSHBUTTON "@IDOK",IDOK,13,277,81,18
+ PUSHBUTTON "@B_DISCONNECT",B_DISCONNECT,100,277,47,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,152,277,71,18
+ PUSHBUTTON "@B_SESSION_MAC_TABLE",B_SESSION_MAC_TABLE,231,277,99,18
+ PUSHBUTTON "@B_SESSION_IP_TABLE",B_SESSION_IP_TABLE,337,277,90,18
+ GROUPBOX "@STATIC2",IDC_STATIC,7,312,245,43
+ ICON ICO_NIC_ONLINE,IDC_STATIC,14,324,18,21
+ PUSHBUTTON "@B_MAC_TABLE",B_MAC_TABLE,39,326,92,18
+ ICON ICO_PROTOCOL,IDC_STATIC,133,323,18,21
+ PUSHBUTTON "@B_IP_TABLE",B_IP_TABLE,160,326,85,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,387,337,59,18
+ ICON ICO_FARM,S_FARM_INFO_1,260,310,18,21,NOT WS_VISIBLE
+ LTEXT "@S_FARM_INFO_2",S_FARM_INFO_2,281,309,165,24,NOT WS_VISIBLE
+END
+
+D_SM_MAC DIALOGEX 0, 0, 451, 337
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_MAC"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,35,7,409,21
+ CONTROL "",L_TABLE,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,437,265
+ PUSHBUTTON "@B_DELETE",B_DELETE,201,312,93,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,301,312,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,393,312,51,18
+END
+
+D_SM_IP DIALOGEX 0, 0, 451, 337
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_IP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PROTOCOL,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,35,7,409,21
+ CONTROL "",L_TABLE,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,437,265
+ PUSHBUTTON "@B_DELETE",B_DELETE,201,312,93,18
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,301,312,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,393,312,51,18
+END
+
+D_SM_CREATE_CERT DIALOGEX 0, 0, 301, 371
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CREATE_CERT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,263,21
+ RTEXT "@STATIC2",IDC_STATIC,7,39,69,13
+ CONTROL "@R_ROOT_CERT",R_ROOT_CERT,"Button",BS_AUTORADIOBUTTON,81,37,187,10
+ CONTROL "@R_SIGNED_CERT",R_SIGNED_CERT,"Button",BS_AUTORADIOBUTTON,81,53,189,10
+ RTEXT "@S_LOAD_1",S_LOAD_1,7,75,69,19
+ PUSHBUTTON "@B_LOAD",B_LOAD,81,75,102,18
+ LTEXT "@S_LOAD_2",S_LOAD_2,81,97,206,36
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,137,287,20
+ RTEXT "@S_LOAD_3",S_LOAD_3,7,146,69,12
+ EDITTEXT E_CN,81,144,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_4",S_LOAD_4,7,163,69,11
+ EDITTEXT E_O,81,161,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_5",S_LOAD_5,7,181,69,12
+ EDITTEXT E_OU,81,179,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_6",S_LOAD_6,7,200,69,11
+ EDITTEXT E_C,81,198,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_7",S_LOAD_7,7,217,69,11
+ EDITTEXT E_ST,81,215,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_8",S_LOAD_8,7,235,69,10
+ EDITTEXT E_L,81,233,205,12,ES_AUTOHSCROLL
+ RTEXT "@S_LOAD_11",S_LOAD_11,7,253,69,19
+ EDITTEXT E_SERIAL,81,251,205,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,273,286,1
+ RTEXT "@S_LOAD_9",S_LOAD_9,7,286,69,11
+ EDITTEXT E_EXPIRE,81,284,36,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_LOAD_10",S_LOAD_10,121,286,28,11
+ RTEXT "@S_LOAD_12",S_LOAD_12,157,286,51,11
+ COMBOBOX C_BITS,210,281,48,131,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "bits",S_LOAD_13,263,286,28,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,304,285,1
+ ICON ICO_INFORMATION,IDC_STATIC,7,313,20,20
+ LTEXT "@STATIC3",IDC_STATIC,30,315,264,29
+ DEFPUSHBUTTON "@IDOK",IDOK,157,345,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,230,345,64,19
+END
+
+D_NM_LOGIN DIALOGEX 0, 0, 275, 134
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_LOGIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,237,34
+ RTEXT "@STATIC1",IDC_STATIC,33,70,49,12
+ EDITTEXT E_PASSWORD,87,68,141,12,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "@STATIC2",IDC_STATIC,26,47,222,50
+ DEFPUSHBUTTON "@IDOK",IDOK,158,111,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,216,111,52,16
+END
+
+D_SPEEDMETER DIALOGEX 0, 0, 319, 295
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SPEEDMETER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,14,281,12
+ COMBOBOX E_LIST,32,30,215,141,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "@STATIC2",IDC_STATIC,7,56,305,232
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,19,73,276,203
+ PUSHBUTTON "@STATIC3",B_REFRESH,254,29,50,16
+END
+
+D_NM_MAIN DIALOGEX 0, 0, 351, 380
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_MAIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 176,IDC_STATIC,"Static",SS_BITMAP,7,7,338,103
+ GROUPBOX "@STATIC1",IDC_STATIC,7,112,337,85
+ ICON ICO_VPNSERVER,IDC_STATIC,14,123,20,20
+ LTEXT "@STATIC2",IDC_STATIC,38,126,297,20
+ PUSHBUTTON "@B_SETTING",B_SETTING,44,148,111,17
+ PUSHBUTTON "@B_CONNECT",B_CONNECT,164,148,61,17
+ PUSHBUTTON "@B_DISCONNECT",B_DISCONNECT,234,148,61,17
+ ICON ICO_INTERNET,IDC_STATIC,15,169,20,20
+ LTEXT "",S_STATUS,39,176,298,15,SS_WORDELLIPSIS
+ GROUPBOX "@STATIC3",IDC_STATIC,7,203,337,62
+ ICON ICO_ROUTER,IDC_STATIC,15,215,20,20
+ LTEXT "@STATIC4",IDC_STATIC,38,218,297,14
+ PUSHBUTTON "@B_OPTION",B_OPTION,113,238,120,17
+ GROUPBOX "@STATIC5",IDC_STATIC,7,267,337,83
+ ICON ICO_MACHINE,IDC_STATIC,14,278,20,20
+ LTEXT "@STATIC6",IDC_STATIC,38,280,297,14
+ PUSHBUTTON "@B_NAT",B_NAT,75,298,97,17
+ PUSHBUTTON "@B_DHCP",B_DHCP,186,298,97,17
+ PUSHBUTTON "@B_STATUS",B_STATUS,75,322,97,17
+ PUSHBUTTON "@B_INFO",B_INFO,186,322,97,17
+ PUSHBUTTON "@B_PASSWORD",B_PASSWORD,7,356,97,17
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,109,356,71,17
+ PUSHBUTTON "@B_ABOUT",B_ABOUT,192,356,71,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,279,356,65,17
+END
+
+D_NM_OPTION DIALOGEX 0, 0, 419, 307
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_OPTION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_ROUTER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,29,11,357,19
+ GROUPBOX "@STATIC1",IDC_STATIC,7,40,199,83
+ ICON ICO_NIC_ONLINE,IDC_STATIC,14,55,20,20
+ RTEXT "@STATIC2",IDC_STATIC,39,60,59,12
+ EDITTEXT E_MAC,102,59,81,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC3",IDC_STATIC,39,81,59,11
+ CONTROL "",E_IP,"SysIPAddress32",WS_TABSTOP,102,79,75,13
+ RTEXT "@STATIC4",IDC_STATIC,39,102,59,10
+ CONTROL "",E_MASK,"SysIPAddress32",WS_TABSTOP,102,100,75,13
+ GROUPBOX "@STATIC5",IDC_STATIC,7,130,199,89
+ CONTROL "@R_USE_NAT",R_USE_NAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,146,157,10
+ RTEXT "@STATIC6",IDC_STATIC,39,162,59,11
+ EDITTEXT E_MTU,102,160,39,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC7",IDC_STATIC,145,162,52,10
+ RTEXT "@STATIC8",IDC_STATIC,10,180,88,10
+ EDITTEXT E_TCP,102,178,39,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC9",IDC_STATIC,145,180,47,10
+ RTEXT "@STATIC10",IDC_STATIC,10,198,88,11
+ EDITTEXT E_UDP,102,196,39,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC11",IDC_STATIC,145,198,51,10
+ CONTROL "@R_SAVE_LOG",R_SAVE_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,255,190,10
+ GROUPBOX "@STATIC12",IDC_STATIC,211,40,201,228
+ CONTROL "@R_USE_DHCP",R_USE_DHCP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,218,56,161,10
+ RTEXT "@STATIC13",IDC_STATIC,218,74,84,11
+ CONTROL "",E_DHCP_START,"SysIPAddress32",WS_TABSTOP,306,72,75,13
+ LTEXT "@STATIC14",IDC_STATIC,384,74,24,11
+ CONTROL "",E_DHCP_END,"SysIPAddress32",WS_TABSTOP,306,92,75,13
+ LTEXT "@STATIC15",IDC_STATIC,384,94,26,10
+ RTEXT "@STATIC16",IDC_STATIC,218,114,84,11
+ CONTROL "",E_DHCP_MASK,"SysIPAddress32",WS_TABSTOP,306,112,75,13
+ RTEXT "@STATIC17",IDC_STATIC,218,136,84,10
+ EDITTEXT E_EXPIRES,306,134,39,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC18",IDC_STATIC,349,136,54,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,218,154,185,1
+ LTEXT "@STATIC19",IDC_STATIC,218,163,184,14
+ RTEXT "@STATIC20",IDC_STATIC,218,182,84,20
+ CONTROL "",E_GATEWAY,"SysIPAddress32",WS_TABSTOP,306,183,75,13
+ RTEXT "@STATIC21",IDC_STATIC,213,207,89,14
+ CONTROL "",E_DNS,"SysIPAddress32",WS_TABSTOP,306,205,75,13
+ RTEXT "@STATIC23",IDC_STATIC,213,228,89,13
+ CONTROL "",E_DNS2,"SysIPAddress32",WS_TABSTOP,306,226,75,13
+ RTEXT "@STATIC22",IDC_STATIC,218,249,84,12
+ EDITTEXT E_DOMAIN,306,247,98,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,274,281,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,348,281,64,19
+END
+
+D_NM_NAT DIALOGEX 0, 0, 451, 337
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_NAT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PROTOCOL,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,35,7,409,21
+ CONTROL "",L_TABLE,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,437,265
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,301,312,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,393,312,51,18
+END
+
+D_NM_DHCP DIALOGEX 0, 0, 451, 337
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_DHCP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INTERNET,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,35,7,409,21
+ CONTROL "",L_TABLE,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,37,437,265
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,301,312,82,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,393,312,51,18
+END
+
+D_NM_CHANGE_PASSWORD DIALOGEX 0, 0, 250, 112
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_NM_CHANGE_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_USER_ADMIN,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,212,29
+ RTEXT "@STATIC1",IDC_STATIC,7,41,65,10
+ EDITTEXT E_PASSWORD1,78,39,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC2",IDC_STATIC,7,60,65,10
+ EDITTEXT E_PASSWORD2,78,58,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,106,86,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,179,86,64,19
+END
+
+D_SM_SNAT DIALOGEX 0, 0, 355, 318
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SNAT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_ROUTER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,317,26
+ GROUPBOX "@STATIC1",IDC_STATIC,7,37,341,96
+ ICON ICO_WARNING,IDC_STATIC,14,53,20,20
+ LTEXT "@S_WARNING",S_WARNING,39,53,301,22
+ LTEXT "@S_WARNING2",S_WARNING2,39,81,301,45
+ GROUPBOX "@STATIC2",IDC_STATIC,7,137,341,76
+ LTEXT "@STATIC3",IDC_STATIC,15,151,325,12
+ PUSHBUTTON "@B_ENABLE",B_ENABLE,19,167,102,18
+ PUSHBUTTON "@B_DISABLE",B_DISABLE,125,167,102,18
+ PUSHBUTTON "@B_CONFIG",B_CONFIG,232,167,102,18
+ LTEXT "@STATIC4",IDC_STATIC,15,191,325,18
+ GROUPBOX "@STATIC5",IDC_STATIC,7,217,341,65
+ ICON ICO_INFORMATION,IDC_STATIC,14,231,20,20
+ LTEXT "@STATIC6",IDC_STATIC,43,235,230,14
+ PUSHBUTTON "@B_NAT",B_NAT,17,255,100,18
+ PUSHBUTTON "@B_DHCP",B_DHCP,122,255,100,18
+ PUSHBUTTON "@B_STATUS",B_STATUS,226,255,112,18
+ CONTROL 179,S_TSUKUBA1,"Static",SS_BITMAP | NOT WS_VISIBLE,644,-9,68,26
+ LTEXT "@S_TSUKUBA2",S_TSUKUBA2,78,293,204,18,NOT WS_VISIBLE
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,288,293,60,18
+END
+
+D_SM_BRIDGE DIALOGEX 0, 0, 367, 380
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_BRIDGE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_BRIDGE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,327,43
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,55,353,99
+ PUSHBUTTON "@B_VLAN",B_VLAN,7,159,130,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,267,159,93,17
+ GROUPBOX "@STATIC2",IDC_STATIC,7,181,353,158
+ ICON ICO_HUB,IDC_STATIC,16,195,20,20
+ LTEXT "@STATIC3",IDC_STATIC,40,197,310,10
+ RTEXT "@STATIC4",IDC_STATIC,40,213,53,10
+ COMBOBOX E_HUBNAME,100,211,250,96,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,22,229,328,1
+ LTEXT "@STATIC5",S_STATIC5,14,236,54,12
+ CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTORADIOBUTTON,73,235,274,10
+ CONTROL "@R_TAP",R_TAP,"Button",BS_AUTORADIOBUTTON,73,249,275,10
+ ICON ICO_NIC_ONLINE,S_ICON,14,263,20,20
+ LTEXT "--INFO--",S_INFO,38,262,311,12
+ RTEXT "@S_ETH_1",S_ETH_1,38,279,53,11
+ COMBOBOX E_NICNAME,100,276,251,96,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_TAP_1",S_TAP_1,14,295,77,10
+ EDITTEXT E_TAPNAME,99,294,81,12,ES_AUTOHSCROLL
+ LTEXT "@S_TAP_2",S_TAP_2,183,296,80,10
+ LTEXT "@STATIC6",IDC_STATIC,14,308,236,29
+ DEFPUSHBUTTON "@IDOK",IDOK,258,314,91,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,301,345,59,18
+ LTEXT "@STATIC7",IDC_STATIC,7,345,286,28
+END
+
+D_WIN9X_REBOOT DIALOGEX 0, 0, 239, 104
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
+EXSTYLE WS_EX_TOPMOST
+CAPTION "@D_WIN9X_REBOOT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,32,7,200,52
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER,7,65,225,12
+ CTEXT "-- COUNTER --",S_INFO,7,82,225,15
+END
+
+D_DEFAULT1 DIALOGEX 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "PacketiX VPN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+END
+
+D_EM_MAIN DIALOGEX 0, 0, 335, 211
+STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_MAIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,-1,7,7,20,20
+ LTEXT "@STATIC1",-1,31,7,297,43
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,55,321,120
+ PUSHBUTTON "@B_PASSWORD",B_PASSWORD,7,186,60,18
+ PUSHBUTTON "@B_LICENSE",B_LICENSE,72,186,50,18
+ PUSHBUTTON "@B_ADD",B_ADD,127,186,47,18
+ DEFPUSHBUTTON "@IDOK",IDOK,178,186,47,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,229,186,47,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,281,186,47,18
+END
+
+D_EM_ADD DIALOGEX 0, 0, 279, 347
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_ADD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ GROUPBOX "@STATIC1",-1,7,7,265,59
+ ICON ICO_NIC_ONLINE,-1,14,21,20,20
+ COMBOBOX C_DEVICE,37,26,226,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "@R_PROMISCUS",R_PROMISCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,38,44,223,12
+ GROUPBOX "@STATIC2",-1,7,81,265,200
+ ICON ICO_USER_ADMIN,-1,14,94,20,20
+ RTEXT "@S_PACKET",S_PACKET,39,101,98,10
+ COMBOBOX C_PACKET_SWITCH,142,99,121,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_PACKET_0",S_PACKET_0,14,129,58,12
+ CONTROL "@B_PACKET_0_0",B_PACKET_0_0,"Button",BS_AUTORADIOBUTTON,79,127,42,10
+ CONTROL "@B_PACKET_0_1",B_PACKET_0_1,"Button",BS_AUTORADIOBUTTON,125,127,57,10
+ CONTROL "@B_PACKET_0_2",B_PACKET_0_2,"Button",BS_AUTORADIOBUTTON,187,127,66,10
+ RTEXT "@S_PACKET_1",S_PACKET_1,14,147,58,11
+ CONTROL "@B_PACKET_1_0",B_PACKET_1_0,"Button",BS_AUTORADIOBUTTON,79,145,42,10
+ CONTROL "@B_PACKET_1_1",B_PACKET_1_1,"Button",BS_AUTORADIOBUTTON,125,145,57,10
+ CONTROL "@B_PACKET_1_2",B_PACKET_1_2,"Button",BS_AUTORADIOBUTTON,187,145,66,10
+ RTEXT "@S_PACKET_2",S_PACKET_2,14,165,58,12
+ CONTROL "@B_PACKET_2_0",B_PACKET_2_0,"Button",BS_AUTORADIOBUTTON,79,163,42,10
+ CONTROL "@B_PACKET_2_1",B_PACKET_2_1,"Button",BS_AUTORADIOBUTTON,125,163,57,10
+ CONTROL "@B_PACKET_2_2",B_PACKET_2_2,"Button",BS_AUTORADIOBUTTON,187,163,66,10
+ RTEXT "@S_PACKET_3",S_PACKET_3,14,181,58,11
+ CONTROL "@B_PACKET_3_0",B_PACKET_3_0,"Button",BS_AUTORADIOBUTTON,79,179,42,10
+ CONTROL "@B_PACKET_3_1",B_PACKET_3_1,"Button",BS_AUTORADIOBUTTON,125,179,57,10
+ CONTROL "@B_PACKET_3_2",B_PACKET_3_2,"Button",BS_AUTORADIOBUTTON,187,179,66,10
+ RTEXT "@S_PACKET_4",S_PACKET_4,14,199,58,10
+ CONTROL "@B_PACKET_4_0",B_PACKET_4_0,"Button",BS_AUTORADIOBUTTON,79,197,42,10
+ CONTROL "@B_PACKET_4_1",B_PACKET_4_1,"Button",BS_AUTORADIOBUTTON,125,197,57,10
+ CONTROL "@B_PACKET_4_2",B_PACKET_4_2,"Button",BS_AUTORADIOBUTTON,187,197,66,10
+ RTEXT "@S_PACKET_5",S_PACKET_5,14,217,58,12
+ CONTROL "@B_PACKET_5_0",B_PACKET_5_0,"Button",BS_AUTORADIOBUTTON,79,215,42,10
+ CONTROL "@B_PACKET_5_1",B_PACKET_5_1,"Button",BS_AUTORADIOBUTTON,125,215,57,10
+ CONTROL "@B_PACKET_5_2",B_PACKET_5_2,"Button",BS_AUTORADIOBUTTON,187,215,66,10
+ RTEXT "@S_PACKET_6",S_PACKET_6,14,231,58,10
+ CONTROL "@B_PACKET_6_0",B_PACKET_6_0,"Button",BS_AUTORADIOBUTTON,79,231,42,10
+ CONTROL "@B_PACKET_6_1",B_PACKET_6_1,"Button",BS_AUTORADIOBUTTON,125,231,57,10
+ CONTROL "@B_PACKET_6_2",B_PACKET_6_2,"Button",BS_AUTORADIOBUTTON,187,231,66,10
+ RTEXT "@S_PACKET_7",S_PACKET_7,14,247,58,19
+ CONTROL "@B_PACKET_7_0",B_PACKET_7_0,"Button",BS_AUTORADIOBUTTON,79,249,42,10
+ CONTROL "@B_PACKET_7_1",B_PACKET_7_1,"Button",BS_AUTORADIOBUTTON,125,249,57,10
+ CONTROL "@B_PACKET_7_2",B_PACKET_7_2,"Button",BS_AUTORADIOBUTTON,187,249,66,10
+ DEFPUSHBUTTON "@IDOK",IDOK,135,321,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,208,321,64,19
+ ICON ICO_WARNING,-1,7,288,20,20
+ LTEXT "@STATIC3",-1,29,287,243,28
+END
+
+D_EM_PASSWORD DIALOGEX 0, 0, 250, 112
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_PASSWORD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,212,20
+ RTEXT "@STATIC1",IDC_STATIC,7,41,65,11
+ EDITTEXT E_PASSWORD1,78,39,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC2",IDC_STATIC,7,60,65,11
+ EDITTEXT E_PASSWORD2,78,58,130,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,106,86,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,179,86,64,19
+END
+
+D_SM_CONFIG DIALOGEX 0, 0, 383, 368
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CONFIG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,20,20
+ LTEXT "@IDC_INFO",IDC_INFO,36,12,340,24
+ EDITTEXT E_CONFIG,7,44,369,257,ES_MULTILINE | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+ PUSHBUTTON "@B_FACTORY",B_FACTORY,7,342,112,19
+ PUSHBUTTON "@B_EXPORT",B_EXPORT,127,342,74,19
+ PUSHBUTTON "@B_IMPORT",B_IMPORT,206,342,112,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,323,342,53,19
+ ICON ICO_WARNING,IDC_STATIC,7,307,20,20
+ LTEXT "@STATIC1",IDC_STATIC,30,303,346,38
+END
+
+D_SM_ADMIN_OPTION DIALOGEX 0, 0, 310, 359
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_ADMIN_OPTION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_USER_ADMIN,S_ICON,7,7,20,20
+ LTEXT "@S_INFO",S_INFO,31,15,272,17
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,37,224,158
+ PUSHBUTTON "@B_EDIT",B_EDIT,239,37,64,17
+ PUSHBUTTON "@B_ADD",B_ADD,239,111,64,17,NOT WS_VISIBLE
+ PUSHBUTTON "@B_DELETE",B_DELETE,239,140,64,17,NOT WS_VISIBLE
+ LTEXT "@S_BOLD",S_BOLD,7,198,223,8
+ EDITTEXT E_HELP,7,209,296,44,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+ ICON ICO_INFORMATION,IDC_STATIC,7,257,20,20
+ LTEXT "@STATIC1",S_STATIC1,31,259,272,18
+ LTEXT "@STATIC2",S_STATIC2,31,277,272,55
+ DEFPUSHBUTTON "@IDOK",IDOK,182,335,56,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,247,335,56,17
+END
+
+D_SM_AO_VALUE DIALOGEX 0, 0, 206, 80
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_AO_VALUE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ RTEXT "@STATIC1",IDC_STATIC,7,17,37,11
+ COMBOBOX C_NAME,47,15,145,168,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@STATIC2",IDC_STATIC,7,37,37,10
+ EDITTEXT E_VALUE,47,35,67,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC3",IDC_STATIC,118,37,37,13
+ DEFPUSHBUTTON "@IDOK",IDOK,80,57,56,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,143,57,56,16
+END
+
+D_SM_L3 DIALOGEX 0, 0, 291, 298
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_L3"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,253,22
+ ICON ICO_WARNING,IDC_STATIC,11,49,20,20
+ LTEXT "@STATIC2",IDC_STATIC,35,45,244,58
+ GROUPBOX "@STATIC3",IDC_STATIC,7,35,277,71
+ LTEXT "@S_BOLD",S_BOLD,7,114,183,12
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,129,277,113
+ PUSHBUTTON "@B_ADD",B_ADD,7,248,48,18
+ PUSHBUTTON "@B_START",B_START,64,248,48,18
+ PUSHBUTTON "@B_STOP",B_STOP,121,248,48,18
+ DEFPUSHBUTTON "@IDOK",IDOK,178,248,48,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,235,248,48,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,226,273,58,18
+END
+
+D_SM_L3_ADD DIALOGEX 0, 0, 234, 105
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_L3_ADD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,32,7,195,50
+ RTEXT "@STATIC2",IDC_STATIC,7,60,35,12
+ EDITTEXT E_NAME,46,58,173,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,99,81,61,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,166,81,61,17
+END
+
+D_SM_L3_SW DIALOGEX 0, 0, 298, 374
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_L3_SW"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH_OFFLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,260,20
+ LTEXT "@STATIC2",IDC_STATIC,31,27,260,55
+ LTEXT "@S_BOLD1",S_BOLD1,7,82,183,12
+ CONTROL "",L_IF,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,95,284,94
+ PUSHBUTTON "@B_ADD_IF",B_ADD_IF,46,195,119,18
+ PUSHBUTTON "@B_DEL_IF",B_DEL_IF,170,195,121,18
+ LTEXT "@S_BOLD2",S_BOLD2,7,218,183,12
+ CONTROL "",L_TABLE,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,232,284,88
+ PUSHBUTTON "@B_ADD_TABLE",B_ADD_TABLE,46,323,119,18
+ PUSHBUTTON "@B_DEL_TABLE",B_DEL_TABLE,170,323,121,18
+ PUSHBUTTON "@B_START",B_START,7,349,58,18
+ PUSHBUTTON "@B_STOP",B_STOP,72,349,58,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,233,349,58,18
+END
+
+D_SM_L3_SW_IF DIALOGEX 0, 0, 259, 289
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_L3_SW_IF"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,219,55
+ GROUPBOX "@STATIC2",IDC_STATIC,7,68,245,62
+ ICON ICO_HUB,IDC_STATIC,12,82,20,20
+ LTEXT "@STATIC3",IDC_STATIC,35,83,210,18
+ RTEXT "@STATIC4",IDC_STATIC,26,107,53,11
+ COMBOBOX E_HUBNAME,86,105,159,150,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "@STATIC5",IDC_STATIC,7,135,245,118
+ ICON ICO_PROTOCOL,IDC_STATIC,12,152,20,20
+ LTEXT "@STATIC6",IDC_STATIC,35,147,210,59
+ RTEXT "@S_SRC_IP_1",S_SRC_IP_1,31,212,51,11
+ CONTROL "",E_IP,"SysIPAddress32",WS_TABSTOP,86,210,75,13
+ RTEXT "@S_SRC_IP_2",S_SRC_IP_2,15,230,67,11
+ CONTROL "",E_MASK,"SysIPAddress32",WS_TABSTOP,86,228,75,13
+ DEFPUSHBUTTON "@IDOK",IDOK,115,263,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,188,263,64,19
+END
+
+D_SM_L3_SW_TABLE DIALOGEX 0, 0, 259, 262
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_L3_SW_TABLE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,219,57
+ GROUPBOX "@STATIC2",IDC_STATIC,7,65,245,158
+ ICON ICO_PROTOCOL,IDC_STATIC,12,82,20,20
+ LTEXT "@STATIC3",IDC_STATIC,35,78,210,60
+ RTEXT "@S_SRC_IP_1",S_SRC_IP_1,15,142,67,11
+ CONTROL "",E_NETWORK,"SysIPAddress32",WS_TABSTOP,86,140,75,13
+ RTEXT "@S_SRC_IP_2",S_SRC_IP_2,15,160,67,10
+ CONTROL "",E_MASK,"SysIPAddress32",WS_TABSTOP,86,158,75,13
+ RTEXT "@S_SRC_IP_3",S_SRC_IP_3,15,178,67,11
+ CONTROL "",E_GATEWAY,"SysIPAddress32",WS_TABSTOP,86,176,75,13
+ RTEXT "@S_SRC_IP_4",S_SRC_IP_4,15,196,67,11
+ EDITTEXT E_METRIC,86,194,40,14,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC4",IDC_STATIC,166,165,79,54
+ DEFPUSHBUTTON "@IDOK",IDOK,115,236,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,188,236,64,19
+END
+
+D_CM_SELECT_SECURE DIALOGEX 0, 0, 295, 250
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_SELECT_SECURE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SECURE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,257,78
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,90,281,126
+ DEFPUSHBUTTON "@IDOK",IDOK,154,226,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,224,226,64,17
+END
+
+D_CM_SECURE_MANAGER DIALOGEX 0, 0, 295, 267
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_SECURE_MANAGER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SECURE,IDC_STATIC,7,7,20,20
+ LTEXT "@S_INFO",S_INFO,31,7,257,27
+ LTEXT "@B_BOLD",B_BOLD,7,43,141,13
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,58,187,202
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,198,57,90,17
+ PUSHBUTTON "@B_IMPORT",B_IMPORT,198,80,90,17
+ PUSHBUTTON "@B_EXPORT",B_EXPORT,198,103,90,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,198,126,90,17
+ PUSHBUTTON "@B_NEW_CERT",B_NEW_CERT,198,149,90,29,BS_MULTILINE
+ ICON ICO_KEY,IDC_STATIC,199,214,20,20
+ PUSHBUTTON "@B_PIN",B_PIN,220,215,68,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,198,243,90,17
+END
+
+D_CM_SECURE_TYPE DIALOGEX 0, 0, 195, 126
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_SECURE_TYPE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@STATIC",IDC_STATIC,7,7,149,20
+ CONTROL "@R_CERT",R_CERT,"Button",BS_AUTORADIOBUTTON,28,35,46,10
+ CONTROL "@R_KEY",R_KEY,"Button",BS_AUTORADIOBUTTON,28,57,45,10
+ CONTROL "@R_DATA",R_DATA,"Button",BS_AUTORADIOBUTTON,28,79,61,10
+ DEFPUSHBUTTON "@IDOK",IDOK,51,102,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,124,102,64,17
+END
+
+D_STRING DIALOGEX 0, 0, 266, 122
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_STRING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON "",S_ICON,7,6,18,21
+ LTEXT "[INFO]",S_INFO,30,6,229,61
+ EDITTEXT E_STRING,30,69,221,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,144,98,55,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,204,98,55,17
+END
+
+D_SM_SELECT_KEYPAIR DIALOGEX 0, 0, 201, 283
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SELECT_KEYPAIR"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SECURE,-1,7,7,18,21
+ LTEXT "@S_INFO",S_INFO,31,7,163,33
+ CONTROL "",L_CERT,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,56,187,83
+ LTEXT "@B_BOLD1",B_BOLD1,7,43,187,11
+ DEFPUSHBUTTON "@IDOK",IDOK,61,257,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,130,257,64,19
+ CONTROL "",L_KEY,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,162,187,83
+ LTEXT "@B_BOLD2",B_BOLD2,7,149,187,11
+END
+
+D_CM_LOAD_X DIALOGEX 0, 0, 239, 209
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_LOAD_X"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@STATIC1",IDC_STATIC,7,7,225,15
+ CONTROL "@R_FROM_FILE",R_FROM_FILE,"Button",BS_AUTORADIOBUTTON,14,27,133,10
+ CONTROL "@R_FROM_SECURE",R_FROM_SECURE,"Button",BS_AUTORADIOBUTTON,14,85,138,10
+ ICON ICO_CERT,IDC_STATIC,25,45,20,20
+ LTEXT "@S_FILE",S_FILE,50,48,182,26
+ ICON ICO_SECURE,IDC_STATIC,25,104,20,20
+ LTEXT "@S_CERT",S_CERT,50,106,182,26
+ PUSHBUTTON "@B_SELECT",B_SELECT,50,131,110,20
+ LTEXT "",S_INFO,45,155,187,26
+ DEFPUSHBUTTON "@IDOK",IDOK,122,184,52,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,180,184,52,18
+END
+
+D_CM_SECURE_PIN DIALOGEX 0, 0, 263, 221
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_SECURE_PIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,30,7,227,40
+ RTEXT "@STATIC2",IDC_STATIC,7,55,70,10
+ EDITTEXT E_PIN1,81,53,144,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC3",IDC_STATIC,7,75,70,10
+ EDITTEXT E_PIN2,81,73,144,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,7,95,70,10
+ EDITTEXT E_PIN3,81,93,144,12,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "@STATIC5",IDC_STATIC,7,119,249,49
+ ICON ICO_WARNING,IDC_STATIC,14,133,20,20
+ LTEXT "@STATIC6",IDC_STATIC,40,133,208,19
+ LTEXT "@STATIC7",IDC_STATIC,7,177,249,10
+ DEFPUSHBUTTON "@IDOK",IDOK,123,197,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,192,197,64,17
+END
+
+D_SM_CRL DIALOGEX 0, 0, 335, 228
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_CRL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT_X,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,295,35
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP,7,50,321,144
+ PUSHBUTTON "@B_ADD",B_ADD,85,203,55,17
+ DEFPUSHBUTTON "@IDOK",IDOK,209,203,58,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,273,203,55,17
+ PUSHBUTTON "@B_DELETE",B_DELETE,147,203,54,17
+END
+
+D_SM_EDIT_CRL DIALOGEX 0, 0, 351, 365
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_CRL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT_X,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,313,35
+ LTEXT "@S_BOLD",S_BOLD,7,44,337,13
+ GROUPBOX "@STATIC2",IDC_STATIC,7,58,337,121
+ CONTROL "@R_CN",R_CN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,70,76,10
+ EDITTEXT E_CN,96,69,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_O",R_O,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,87,60,10
+ EDITTEXT E_O,96,86,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_OU",R_OU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,103,80,10
+ EDITTEXT E_OU,96,104,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_C",R_C,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,123,53,10
+ EDITTEXT E_C,96,122,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_ST",R_ST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,141,62,10
+ EDITTEXT E_ST,96,140,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_L",R_L,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,160,51,10
+ EDITTEXT E_L,96,158,241,12,ES_AUTOHSCROLL
+ GROUPBOX "@STATIC3",IDC_STATIC,7,183,337,95
+ CONTROL "@R_SERI",R_SERI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,197,85,10
+ EDITTEXT E_SERI,96,195,241,12,ES_AUTOHSCROLL
+ CONTROL "@R_MD5_HASH",R_MD5_HASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,214,125,10
+ EDITTEXT E_MD5_HASH,142,211,195,12,ES_AUTOHSCROLL
+ CONTROL "@R_SHA1_HASH",R_SHA1_HASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,231,124,10
+ EDITTEXT E_SHA1_HASH,142,229,195,12,ES_AUTOHSCROLL
+ ICON ICO_INFORMATION,IDC_STATIC,15,246,20,20
+ LTEXT "@STATIC4",IDC_STATIC,39,248,298,27
+ GROUPBOX "@STATIC5",IDC_STATIC,7,283,337,52
+ LTEXT "@STATIC6",IDC_STATIC,39,295,216,35
+ ICON ICO_CERT,IDC_STATIC,14,295,20,20
+ PUSHBUTTON "@B_LOAD",B_LOAD,257,297,79,18
+ DEFPUSHBUTTON "@IDOK",IDOK,225,342,56,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,288,342,56,16
+END
+
+D_SM_AC_LIST DIALOGEX 0, 0, 309, 230
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_AC_LIST"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INTERNET,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,7,269,26
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,38,222,158
+ PUSHBUTTON "@B_ADD",B_ADD,234,39,68,18
+ DEFPUSHBUTTON "@IDOK",IDOK,234,61,68,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,234,83,68,18
+ PUSHBUTTON "@B_SAVE",B_SAVE,234,178,68,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,234,205,68,18
+ LTEXT "@STATIC1",IDC_STATIC,235,110,67,28
+ ICON ICO_INFORMATION,IDC_STATIC,7,202,20,20
+ LTEXT "@STATIC2",IDC_STATIC,28,203,205,20
+END
+
+D_SM_AC DIALOGEX 0, 0, 310, 311
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_AC"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INTERNET,S_ICON,7,6,18,21
+ LTEXT "@STATIC1",IDC_STATIC,33,6,270,29
+ GROUPBOX "@STATIC2",IDC_STATIC,7,38,296,130
+ LTEXT "@STATIC3",IDC_STATIC,14,52,281,12
+ CONTROL "IPv&4",R_IPV4,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,110,68,38,10
+ CONTROL "IPv&6",R_IPV6,"Button",BS_AUTORADIOBUTTON,155,68,91,10
+ RTEXT "@STATIC9",IDC_STATIC,14,69,87,12
+ CONTROL "@R_SINGLE",R_SINGLE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,21,87,274,13
+ CONTROL "@R_MASKED",R_MASKED,"Button",BS_AUTORADIOBUTTON,21,105,275,13
+ RTEXT "@STATIC4",IDC_STATIC,21,126,80,11
+ CONTROL "",E_IP,"SysIPAddress32",WS_TABSTOP,110,123,81,13
+ RTEXT "@S_MASK",S_MASK,21,146,80,11
+ CONTROL "",E_MASK,"SysIPAddress32",WS_TABSTOP,110,144,81,13
+ GROUPBOX "@STATIC5",IDC_STATIC,7,182,296,37
+ CONTROL "@R_PASS",R_PASS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,21,198,87,10
+ CONTROL "@R_DENY",R_DENY,"Button",BS_AUTORADIOBUTTON,112,198,91,10
+ GROUPBOX "@STATIC6",IDC_STATIC,7,227,296,53
+ RTEXT "@STATIC7",IDC_STATIC,16,249,47,11
+ EDITTEXT E_PRIORITY,69,247,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC8",IDC_STATIC,112,249,181,13
+ DEFPUSHBUTTON "@IDOK",IDOK,168,285,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,239,285,64,19
+ EDITTEXT E_IPV6,110,123,186,13,ES_AUTOHSCROLL
+ EDITTEXT E_MASKV6,110,143,186,13,ES_AUTOHSCROLL
+END
+
+D_SM_LOG_FILE DIALOGEX 0, 0, 398, 340
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_LOG_FILE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_LOG2,IDC_STATIC,7,7,18,21
+ LTEXT "@STATIC1",IDC_STATIC,26,7,365,37
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP,7,49,384,257
+ DEFPUSHBUTTON "@IDOK",IDOK,7,314,80,19
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,99,314,80,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,311,314,80,19
+END
+
+D_SM_READ_LOG_FILE DIALOGEX 0, 0, 287, 111
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_READ_LOG_FILE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_INFO2",S_INFO2,7,7,273,31
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER | WS_TABSTOP,7,40,273,14
+ CTEXT "--",S_INFO,7,61,273,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,102,86,83,18
+END
+
+D_SM_SAVE_LOG DIALOGEX 0, 0, 271, 82
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SAVE_LOG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_LOG2,IDC_STATIC,7,7,18,21
+ LTEXT "@S_INFO",S_INFO,27,7,237,36
+ DEFPUSHBUTTON "@IDOK",IDOK,58,58,65,17
+ PUSHBUTTON "@B_SAVE",B_SAVE,129,58,65,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,199,58,65,17
+END
+
+D_TCP DIALOGEX 0, 0, 331, 316
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_TCP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SETUP,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,33,7,269,53
+ LTEXT "@STATIC2",IDC_STATIC,33,64,269,34
+ GROUPBOX "@STATIC3",IDC_STATIC,33,101,269,151
+ ICON ICO_PROTOCOL,IDC_STATIC,40,110,20,20
+ LTEXT "@STATIC4",IDC_STATIC,65,112,174,11
+ CONTROL "@R_RECV_DISABLE",R_RECV_DISABLE,"Button",BS_AUTORADIOBUTTON,73,123,175,10
+ CONTROL "@R_RECV_ENABLE",R_RECV_ENABLE,"Button",BS_AUTORADIOBUTTON,73,138,183,10
+ EDITTEXT E_RECV,84,153,48,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_RECV",S_RECV,137,155,33,11
+ PUSHBUTTON "@B_RECV",B_RECV,177,149,67,17
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,54,177,194,1
+ LTEXT "@STATIC5",IDC_STATIC,65,184,115,8
+ CONTROL "@R_SEND_DISABLE",R_SEND_DISABLE,"Button",BS_AUTORADIOBUTTON,73,198,166,10
+ CONTROL "@R_SEND_ENABLE",R_SEND_ENABLE,"Button",BS_AUTORADIOBUTTON,73,213,172,10
+ EDITTEXT E_SEND,84,229,48,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_SEND",S_SEND,137,231,33,11
+ PUSHBUTTON "@B_SEND",B_SEND,177,225,66,17
+ ICON ICO_WARNING,IDC_STATIC,16,258,20,20
+ LTEXT "@STATIC6",IDC_STATIC,42,259,270,29
+ PUSHBUTTON "@B_DELETE",B_DELETE,7,290,170,19
+ DEFPUSHBUTTON "@IDOK",IDOK,188,290,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,260,290,64,19
+END
+
+D_TCP_MSG DIALOGEX 0, 0, 247, 207
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "@D_TCP_MSG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SETUP,IDC_STATIC,7,7,18,21
+ LTEXT "@STATIC1",IDC_STATIC,31,7,209,50
+ ICON ICO_WARNING,IDC_STATIC,7,171,18,21
+ LTEXT "@STATIC2",IDC_STATIC,32,171,208,37
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,162,233,1
+ CONTROL "@R_OPTIMIZE",R_OPTIMIZE,"Button",BS_AUTORADIOBUTTON,31,62,209,16
+ CONTROL "@R_MANUAL",R_MANUAL,"Button",BS_AUTORADIOBUTTON,31,85,209,15
+ CONTROL "@R_NO",R_NO,"Button",BS_AUTORADIOBUTTON,31,107,209,16
+ DEFPUSHBUTTON "@IDOK",IDOK,174,134,66,18
+ PUSHBUTTON "@IDOK3",IDOK3,105,134,66,18,WS_DISABLED
+END
+
+D_CM_PKCSEULA DIALOGEX 0, 0, 267, 158
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_PKCSEULA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INFORMATION,IDC_STATIC,7,7,20,20
+ LTEXT "@S_INFO_1",S_INFO_1,32,7,228,27
+ LTEXT "@S_INFO_2",S_INFO_2,32,41,228,58
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,31,103,229,1
+ LTEXT "@S_INFO_3",S_INFO_3,32,110,228,18
+ DEFPUSHBUTTON "@IDOK",IDOK,146,134,55,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,205,134,55,17
+END
+
+D_CM_KAKUSHI DIALOGEX 0, 0, 365, 273
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,19,57,18,21
+ LTEXT "STRING HERE !!",S_INFO,56,61,302,132
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER,7,201,351,16
+END
+
+D_CM_TRAFFIC DIALOGEX 0, 0, 395, 360
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_TRAFFIC"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,30,7,342,39
+ LTEXT "@STATIC2",IDC_STATIC,30,46,342,32
+ GROUPBOX "@S_1",S_1,30,74,342,254
+ LTEXT "@S_3",S_3,61,86,301,14
+ CONTROL "@R_SERVER",R_SERVER,"Button",BS_AUTORADIOBUTTON,109,99,72,10
+ CONTROL "@R_CLIENT",R_CLIENT,"Button",BS_AUTORADIOBUTTON,196,99,72,10
+ ICON ICO_TOWER,IDC_STATIC,38,85,20,20
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,41,114,319,1
+ ICON ICO_PROTOCOL,IDC_STATIC,38,119,20,20
+ LTEXT "@S_4",S_4,61,120,301,29
+ RTEXT "@S_5",S_5,34,152,117,10
+ COMBOBOX C_HOST,157,149,147,121,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_6",S_6,35,170,116,11
+ COMBOBOX C_PORT,157,168,40,121,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@S_7",S_7,202,170,51,10
+ LTEXT "@S_8",S_8,61,184,301,14
+ GROUPBOX "@S_9",S_9,68,199,287,56
+ CONTROL "@R_DOWNLOAD",R_DOWNLOAD,"Button",BS_AUTORADIOBUTTON,75,210,256,10
+ CONTROL "@R_UPLOAD",R_UPLOAD,"Button",BS_AUTORADIOBUTTON,75,225,256,10
+ CONTROL "@R_FULL",R_FULL,"Button",BS_AUTORADIOBUTTON,75,240,256,10
+ GROUPBOX "@S_10",S_10,68,258,287,62
+ RTEXT "@S_11",S_11,75,272,168,9
+ COMBOBOX C_NUM,246,269,40,110,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_12",S_12,75,289,168,10
+ EDITTEXT E_SPAN,246,287,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_13",S_13,289,288,58,10
+ CONTROL "@R_ETHERNET",R_ETHERNET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,304,165,10
+ CONTROL "@R_DOUBLE",R_DOUBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,247,304,105,10
+ LTEXT "@S_14",S_14,289,271,54,10
+ DEFPUSHBUTTON "@IDOK",IDOK,255,336,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,323,336,64,17
+ LTEXT "@S_15",S_15,7,329,244,24
+END
+
+D_CM_TRAFFIC_RUN DIALOGEX 0, 0, 359, 302
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_TRAFFIC_RUN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH,IDC_STATIC,7,7,20,20
+ LTEXT "@S_INFO",S_INFO,30,7,322,25
+ EDITTEXT E_EDIT,7,35,345,207,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+ LTEXT "@STATIC1",IDC_STATIC,7,274,274,21
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,288,278,64,17
+END
+
+D_CM_TRAFFIC_RESULT DIALOGEX 0, 0, 330, 228
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_TRAFFIC_RESULT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SWITCH,IDC_STATIC,7,7,18,21
+ LTEXT "@STATIC1",IDC_STATIC,29,7,220,20
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,35,316,164
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,259,204,64,17
+END
+
+D_SM_LICENSE DIALOGEX 0, 0, 427, 367
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_LICENSE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,389,29
+ LTEXT "@S_BOLD",S_BOLD,7,39,159,12
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,54,413,80
+ PUSHBUTTON "@B_OBTAIN",B_OBTAIN,7,141,109,19
+ LTEXT "@STATIC2",IDC_STATIC,7,167,141,28
+ PUSHBUTTON "@B_ADD",B_ADD,162,141,105,19
+ PUSHBUTTON "@B_DEL",B_DEL,273,141,48,19
+ DEFPUSHBUTTON "@IDOK",IDOK,327,141,93,19
+ LTEXT "@STATIC3",IDC_STATIC,163,167,257,29
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,197,411,1
+ LTEXT "@S_BOLD2",S_BOLD2,7,203,198,12
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,219,346,141
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,360,342,60,18
+END
+
+D_SM_LICENSE_ADD DIALOGEX 0, 0, 359, 268
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_LICENSE_ADD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_INFO",S_INFO,33,6,319,26
+ LTEXT "@STATIC1",IDC_STATIC,33,28,319,73
+ GROUPBOX "@STATIC2",IDC_STATIC,21,101,320,81
+ LTEXT "@STATIC3",IDC_STATIC,31,120,301,20
+ EDITTEXT B_KEY1,30,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY2,83,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY3,135,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY4,187,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY5,239,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY6,291,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ CTEXT "-",IDC_STATIC,74,150,8,8
+ CTEXT "-",IDC_STATIC,126,150,8,8
+ CTEXT "-",IDC_STATIC,178,150,8,8
+ CTEXT "-",IDC_STATIC,230,150,8,8
+ CTEXT "-",IDC_STATIC,282,150,8,8
+ LTEXT "@B_INFO2",B_INFO2,35,195,317,42
+ ICON ICO_WARNING,IDC_STATIC,13,196,20,20
+ DEFPUSHBUTTON "@IDOK",IDOK,229,242,58,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,294,242,58,18
+END
+
+D_FREEINFO DIALOGEX 0, 0, 323, 242
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_FREEINFO"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INFORMATION,IDC_STATIC,7,7,18,21
+ LTEXT "@S_INFO_1",S_INFO_1,32,7,284,34
+ LTEXT "@S_INFO_2",S_INFO_2,7,45,309,35
+ LTEXT "@S_INFO_3",S_INFO_3,14,85,302,29
+ LTEXT "@S_INFO_4",S_INFO_4,7,118,309,98
+ CONTROL "@B_HIDE",B_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,218,148,17
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,257,218,59,17
+END
+
+D_EM_LICENSE_ADD DIALOGEX 0, 0, 359, 268
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_LICENSE_ADD"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_INFO",S_INFO,33,7,319,26
+ LTEXT "@STATIC1",IDC_STATIC,33,36,319,57
+ GROUPBOX "@STATIC2",IDC_STATIC,21,101,320,81
+ LTEXT "@STATIC3",IDC_STATIC,31,120,301,20
+ EDITTEXT B_KEY1,30,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY2,83,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY3,135,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY4,187,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY5,239,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ EDITTEXT B_KEY6,291,145,43,17,ES_UPPERCASE | ES_AUTOHSCROLL
+ CTEXT "-",IDC_STATIC,74,150,8,8
+ CTEXT "-",IDC_STATIC,126,150,8,8
+ CTEXT "-",IDC_STATIC,178,150,8,8
+ CTEXT "-",IDC_STATIC,230,150,8,8
+ CTEXT "-",IDC_STATIC,282,150,8,8
+ LTEXT "@B_INFO2",B_INFO2,35,195,317,42
+ ICON ICO_WARNING,IDC_STATIC,13,196,20,20
+ DEFPUSHBUTTON "@IDOK",IDOK,229,242,58,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,294,242,58,18
+END
+
+D_EM_LICENSE DIALOGEX 0, 0, 427, 362
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_LICENSE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_CERT,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,389,29
+ LTEXT "@S_BOLD",S_BOLD,7,39,159,12
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,54,413,158
+ PUSHBUTTON "@B_OBTAIN",B_OBTAIN,7,218,82,19
+ LTEXT "@STATIC2",IDC_STATIC,7,243,141,28
+ PUSHBUTTON "@B_ADD",B_ADD,162,218,105,19
+ PUSHBUTTON "@B_DEL",B_DEL,273,218,48,19
+ DEFPUSHBUTTON "@IDOK",IDOK,327,218,93,19
+ LTEXT "@STATIC3",IDC_STATIC,163,243,257,21
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,274,413,1
+ LTEXT "@S_BOLD2",S_BOLD2,7,279,198,12
+ CONTROL "",L_STATUS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,291,306,64
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,356,337,64,18
+END
+
+D_EM_REMOTE DIALOGEX 0, 0, 275, 175
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_EM_REMOTE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TEST,S_ICON,7,7,20,20
+ LTEXT "S_TITLE",S_TITLE,31,7,237,64
+ GROUPBOX "@STATIC1",-1,26,78,222,61
+ CONTROL "@R_LOCAL",R_LOCAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,40,92,200,17
+ RTEXT "@S_HOSTNAME",S_HOSTNAME,33,115,49,11
+ COMBOBOX C_HOSTNAME,86,113,150,106,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "@B_ABOUT",B_ABOUT,14,152,50,16
+ DEFPUSHBUTTON "@IDOK",IDOK,158,152,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,216,152,52,16
+END
+
+D_CM_SETTING DIALOGEX 0, 0, 283, 339
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_SETTING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_VPN,IDC_STATIC,7,7,18,21
+ LTEXT "@STATIC1",IDC_STATIC,33,7,243,23
+ CONTROL "@R_NORMAL",R_NORMAL,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,15,39,201,10
+ CONTROL "@R_EASY",R_EASY,"Button",BS_AUTORADIOBUTTON,15,86,201,10
+ LTEXT "@STATIC2",IDC_STATIC,25,56,250,28
+ LTEXT "@STATIC3",IDC_STATIC,25,101,250,30
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,136,269,1
+ LTEXT "@STATIC4",IDC_STATIC,26,146,250,35
+ CONTROL "@R_LOCK",R_LOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,185,135,10
+ LTEXT "@S_PASSWORD1",S_PASSWORD1,26,200,250,19
+ RTEXT "@S_PASSWORD2",S_PASSWORD2,26,227,50,12
+ EDITTEXT E_PASSWORD1,81,225,140,12,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "@S_PASSWORD3",S_PASSWORD3,26,245,50,11
+ EDITTEXT E_PASSWORD2,81,243,140,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "",S_VGS1,"Static",SS_ETCHEDHORZ,7,267,268,1
+ ICON ICO_RESEARCH,S_VGS3,7,275,18,21
+ LTEXT "@S_VGS2",S_VGS2,33,277,186,11
+ PUSHBUTTON "@B_VGS",B_VGS,32,291,97,17
+ DEFPUSHBUTTON "@IDOK",IDOK,143,315,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,212,315,64,17
+END
+
+D_CM_EASY DIALOGEX 0, 0, 307, 261
+STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CM_EASY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL ICO_TRAY1,IDC_STATIC,"Static",SS_BITMAP,0,0,308,53
+ LTEXT "@S_TITLE",S_TITLE,32,61,267,19
+ ICON ICO_VPN,IDC_STATIC,7,60,20,20
+ CONTROL "",L_ACCOUNT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_EDITLABELS | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,103,293,95
+ PUSHBUTTON "--BUTTON--",IDOK,92,203,123,24
+ LTEXT "--INFO--",S_INFO,12,85,288,16
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,232,294,1
+ PUSHBUTTON "@B_MODE",B_MODE,7,237,84,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,247,237,53,18
+ PUSHBUTTON "@B_STATUS",B_STATUS,216,206,84,18
+ PUSHBUTTON "@B_VGC",B_VGC,112,237,84,18
+END
+
+D_SM_SETUP DIALOGEX 0, 0, 447, 364
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CLIENTEDGE
+CAPTION "@D_SM_SETUP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SETUP,IDC_STATIC,7,7,18,21
+ LTEXT "@S_TITLE",S_TITLE,31,7,409,19
+ LTEXT "@IDC_STATIC_1",IDC_STATIC,7,31,433,27
+ LTEXT "@S_BOLD",S_BOLD,7,60,433,24
+ CONTROL "@C_REMOTE",C_REMOTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,84,226,13
+ CONTROL ICO_TRAY3,IDC_STATIC,"Static",SS_BITMAP,291,86,70,72
+ LTEXT "@S_REMOTE_1",S_REMOTE_1,22,101,262,51
+ CONTROL ICO_TRAY2,IDC_STATIC,"Static",SS_BITMAP,291,176,149,91
+ CONTROL "@C_SITE",C_SITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,170,244,13
+ LTEXT "@S_SITE_1",S_SITE_1,22,188,262,46
+ LTEXT "@S_SITE_2",S_SITE_2,22,237,228,11
+ CONTROL "@C_CENTER",C_CENTER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,29,252,255,12
+ CONTROL "@C_EDGE",C_EDGE,"Button",BS_AUTORADIOBUTTON,29,267,252,12
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,163,426,1
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,284,426,1
+ CONTROL "@C_OTHER",C_OTHER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,291,244,13
+ LTEXT "@S_OTHER",S_OTHER,22,309,418,25
+ DEFPUSHBUTTON "@IDOK",IDOK,322,340,57,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,383,340,57,17
+ LTEXT "--INFO--",S_INFO,7,336,310,21
+END
+
+D_SM_SETUP_HUB DIALOGEX 0, 0, 229, 101
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SETUP_HUB"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_HUB,IDC_STATIC,7,7,20,20
+ LTEXT "@IDC_STATIC_1",IDC_STATIC,31,7,191,29
+ RTEXT "@IDC_STATIC_2",IDC_STATIC,7,47,62,13
+ EDITTEXT E_HUBNAME,74,45,140,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "@IDOK",IDOK,89,75,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,157,75,64,19
+END
+
+D_SM_SETUP_STEP DIALOGEX 0, 0, 329, 351
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CLIENTEDGE
+CAPTION "@D_SM_SETUP_STEP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,7,7,20,20,WS_TABSTOP
+ LTEXT "@IDC_STATIC_1",IDC_STATIC,29,7,293,23
+ LTEXT "@S_1_1",S_1_1,7,45,315,13
+ ICON ICO_USER,IDC_STATIC,14,63,20,20
+ LTEXT "@S_1_2",S_1_2,37,63,285,33
+ PUSHBUTTON "@B_USER",B_USER,37,99,87,17
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,38,315,1
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,126,315,1
+ LTEXT "@S_2_1",S_2_1,7,137,315,13
+ ICON ICO_CASCADE,IDC_STATIC,14,151,20,20
+ LTEXT "@S_2_2",S_2_2,37,152,285,33
+ PUSHBUTTON "@B_CASCADE",B_CASCADE,37,189,155,17
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,215,315,1
+ LTEXT "@S_3_1",S_3_1,7,227,315,13
+ ICON ICO_NIC_ONLINE,S_ICON,14,242,20,20
+ LTEXT "@S_3_2",S_3_2,37,243,285,38
+ COMBOBOX C_DEVICE,37,283,285,163,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,307,314,1
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,263,326,59,18
+ LTEXT "@IDC_STATIC_8",IDC_STATIC,14,318,245,26
+ PUSHBUTTON "@B_SECURENAT",B_SECURENAT,37,282,155,17
+END
+
+D_CPU64_WARNING DIALOGEX 0, 0, 299, 180
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST
+CAPTION "@D_CPU64_WARNING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_WARNING,IDC_STATIC,7,7,18,21
+ LTEXT "@S_BOLD",S_BOLD,29,7,263,29
+ LTEXT "@S_INFO",S_INFO,29,41,263,107
+ DEFPUSHBUTTON "@IDOK",IDOK,119,155,61,17
+END
+
+D_ONCEMSG DIALOGEX 0, 0, 251, 188
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_ONCEMSG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ EDITTEXT E_TEXT,7,7,237,140,ES_MULTILINE | ES_READONLY | WS_VSCROLL
+ CONTROL "@C_DONTSHOWAGAIN",C_DONTSHOWAGAIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,149,237,12
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,94,164,64,17
+END
+
+D_CONNECT DIALOGEX 0, 0, 189, 79
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_CONNECT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "String",S_INFO,30,9,152,27
+ ICON ICO_TEST,S_ICON,7,7,20,20
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,69,56,50,16
+ CONTROL "",IDC_PROGRESS1,"msctls_progress32",0x0,7,41,175,10
+END
+
+D_SM_SIMULATION DIALOGEX 0, 0, 281, 259
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SIMULATION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_FARM,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,30,7,244,60
+ GROUPBOX "@STATIC2",IDC_STATIC,7,73,267,148
+ CONTROL "@C_DELAY",C_DELAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,88,248,11
+ RTEXT "@S_DELAY",S_DELAY,14,108,122,15
+ EDITTEXT E_DELAY,139,106,51,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_DELAY2",S_DELAY2,194,108,73,16
+ CONTROL "@C_JITTER",C_JITTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,131,248,11
+ RTEXT "@S_JITTER",S_JITTER,14,151,122,16
+ EDITTEXT E_JITTER,139,149,51,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_JITTER2",S_JITTER2,194,151,73,16
+ CONTROL "@C_LOSS",C_LOSS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,175,248,11
+ RTEXT "@S_LOSS",S_LOSS,14,195,122,15
+ EDITTEXT E_LOSS,139,193,51,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_LOSS2",S_LOSS2,194,195,73,16
+ DEFPUSHBUTTON "@IDOK",IDOK,142,233,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,210,233,64,19
+END
+
+D_SM_EDIT_ACCESS_V6 DIALOGEX 0, 0, 459, 411
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_EDIT_ACCESS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_PASS,S_ICON,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,31,7,421,19
+ GROUPBOX "@STATIC2",IDC_STATIC,7,34,217,71
+ RTEXT "@STATIC3",IDC_STATIC,14,51,71,11
+ EDITTEXT E_NOTE,91,49,115,12,ES_AUTOHSCROLL
+ RTEXT "@STATIC4",IDC_STATIC,14,69,71,9
+ CONTROL "@R_PASS",R_PASS,"Button",BS_AUTORADIOBUTTON,91,64,47,18
+ CONTROL "@R_DISCARD",R_DISCARD,"Button",BS_AUTORADIOBUTTON,142,64,51,18
+ RTEXT "@STATIC5",IDC_STATIC,14,88,71,10
+ EDITTEXT E_PRIORITY,91,86,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@STATIC6",IDC_STATIC,134,85,73,18
+ GROUPBOX "@STATIC11",S_STATIC11,7,108,217,112
+ ICON ICO_USER,IDC_STATIC,11,119,20,20
+ LTEXT "@STATIC12",S_STATIC12,34,121,177,28
+ RTEXT "@STATIC13",S_STATIC13,12,155,73,12
+ EDITTEXT E_USERNAME1,89,153,84,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_USER1",B_USER1,179,151,41,18
+ RTEXT "@STATIC14",S_STATIC14,13,178,72,12
+ EDITTEXT E_USERNAME2,89,176,84,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_USER2",B_USER2,179,174,41,18
+ LTEXT "@STATIC15",S_STATIC15,56,196,156,21
+ GROUPBOX "@STATIC16",IDC_STATIC,7,223,217,152
+ RTEXT "@S_CHECK_SRC_MAC",S_CHECK_SRC_MAC,14,235,71,10
+ CONTROL "@R_CHECK_SRC_MAC",R_CHECK_SRC_MAC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,233,121,10
+ RTEXT "@S_SRC_MAC",S_SRC_MAC,14,250,108,10
+ EDITTEXT E_SRC_MAC,128,248,78,12,ES_AUTOHSCROLL
+ RTEXT "@S_SRC_MAC_MASK",S_SRC_MAC_MASK,14,267,108,10
+ EDITTEXT E_SRC_MAC_MASK,128,265,78,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,18,283,193,1
+ RTEXT "@S_CHECK_DST_MAC",S_CHECK_DST_MAC,13,289,71,10
+ CONTROL "@R_CHECK_DST_MAC",R_CHECK_DST_MAC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,287,121,10
+ RTEXT "@S_DST_MAC",S_DST_MAC,14,304,108,10
+ EDITTEXT E_DST_MAC,128,302,78,12,ES_AUTOHSCROLL
+ RTEXT "@S_DST_MAC_MASK",S_DST_MAC_MASK,14,322,108,10
+ EDITTEXT E_DST_MAC_MASK,128,320,78,12,ES_AUTOHSCROLL
+ LTEXT "@S_MAC_NOTE",S_MAC_NOTE,18,337,197,30
+ GROUPBOX "@STATIC7",IDC_STATIC,232,34,220,211
+ RTEXT "@S_ACCESS_SRC_ALL",S_ACCESS_SRC_ALL,237,50,71,10
+ CONTROL "@R_SRC_ALL",R_SRC_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,311,48,121,10
+ RTEXT "@S_SRC_IP_1_V6",S_SRC_IP_1,237,64,54,10
+ EDITTEXT E_SRC_IP_V6,298,62,147,12,ES_AUTOHSCROLL
+ RTEXT "@S_SRC_IP_2",S_SRC_IP_2,237,82,54,9
+ EDITTEXT E_SRC_MASK_V6,298,80,147,12,ES_AUTOHSCROLL
+ RTEXT "@S_SRC_IP_3_V6",S_SRC_IP_3,237,102,208,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,118,208,1
+ RTEXT "@S_ACCESS_DST_ALL",S_ACCESS_DST_ALL,237,128,71,10
+ CONTROL "@R_DST_ALL",R_DST_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,311,126,121,10
+ RTEXT "@S_IP_DST_1_V6",S_IP_DST_1,237,142,54,10
+ EDITTEXT E_DST_IP_V6,298,140,147,12,ES_AUTOHSCROLL
+ RTEXT "@S_IP_DST_2",S_IP_DST_2,237,160,54,10
+ EDITTEXT E_DST_MASK_V6,298,158,146,12,ES_AUTOHSCROLL
+ RTEXT "@S_IP_DST_3_V6",S_IP_DST_3,237,178,207,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,196,208,1
+ RTEXT "@STATIC9",IDC_STATIC,237,206,71,12
+ COMBOBOX C_PROTOCOL,313,204,110,87,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S_PROTOID",S_PROTOID,237,226,71,10
+ EDITTEXT E_IP_PROTO,313,224,37,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ GROUPBOX "@STATIC10",IDC_STATIC,232,247,220,129
+ LTEXT "@S_TCP_1",S_TCP_1,318,259,31,10
+ LTEXT "@S_TCP_2",S_TCP_2,370,259,31,10
+ RTEXT "@S_TCP_3",S_TCP_3,234,273,71,10
+ EDITTEXT E_SRC_PORT_1,311,271,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "-",S_TCP_4,356,273,8,8
+ EDITTEXT E_SRC_PORT_2,365,271,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "@S_TCP_5",S_TCP_5,234,291,71,10
+ EDITTEXT E_DST_PORT_1,311,289,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "-",S_TCP_6,356,291,8,8
+ EDITTEXT E_DST_PORT_2,365,289,38,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "@S_TCP_7",S_TCP_7,240,308,204,25
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,238,340,208,1
+ CONTROL "@R_CHECK_TCP_STATE",R_CHECK_TCP_STATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,346,158,10
+ CONTROL "@R_ESTABLISHED",R_ESTABLISHED,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,268,360,71,10
+ CONTROL "@R_UNESTABLISHED",R_UNESTABLISHED,"Button",BS_AUTORADIOBUTTON,351,360,80,10
+ CONTROL "@R_REDIRECT",R_REDIRECT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,383,113,21
+ PUSHBUTTON "@B_REDIRECT",B_REDIRECT,122,385,78,19
+ PUSHBUTTON "@B_SIMULATION",B_SIMULATION,207,385,103,19
+ DEFPUSHBUTTON "@IDOK",IDOK,320,385,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,388,385,64,19
+END
+
+D_SM_VLAN DIALOGEX 0, 0, 315, 327
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_VLAN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_ONLINE,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC1",IDC_STATIC,29,7,279,61
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,69,301,84
+ PUSHBUTTON "@B_ENABLE",B_ENABLE,7,160,209,18
+ PUSHBUTTON "@B_DISABLE",B_DISABLE,223,160,85,18
+ GROUPBOX "@STATIC2",IDC_STATIC,7,187,301,109
+ ICON ICO_INFORMATION,IDC_STATIC,14,200,20,20
+ LTEXT "@S_WARNING",S_WARNING,38,200,262,27
+ LTEXT "@S_WARNING2",S_WARNING2,38,230,262,60
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,249,302,59,18
+END
+
+D_SM_MSG DIALOGEX 0, 0, 275, 323
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_MSG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_LOG2,S_ACL_5,7,7,20,20
+ LTEXT "@S_MSG_2",S_MSG_2,31,7,237,36
+ CONTROL "@C_USEMSG",C_USEMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,51,253,15
+ EDITTEXT E_TEXT,20,72,237,140,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
+ GROUPBOX "@STATIC1",IDC_STATIC,7,217,261,71
+ ICON ICO_INFORMATION,IDC_STATIC,14,230,20,20
+ LTEXT "@S_INFO",S_INFO,39,232,222,52
+ DEFPUSHBUTTON "@IDOK",IDOK,131,297,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,203,297,64,19
+END
+
+D_NICINFO DIALOGEX 0, 0, 221, 107
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "@D_NICINFO"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_NIC_OFFLINE,S_ICON,7,7,18,21
+ LTEXT "Status1",S_STATUS1,31,12,183,17
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,84,84,50,16
+ LTEXT "Status2",S_STATUS2,31,32,183,37
+ CONTROL "",P_BAR,"msctls_progress32",0x0,7,71,207,8
+END
+
+D_SM_IPSEC DIALOGEX 0, 0, 423, 359
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_IPSEC"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_TITLE",S_TITLE,31,7,385,18
+ LTEXT "@S_3",S_3,31,26,385,26
+ ICON ICO_IPSEC,IDC_STATIC,7,7,20,20
+ GROUPBOX "@S01",IDC_STATIC,7,56,409,165
+ LTEXT "@S02",IDC_STATIC,14,68,267,26
+ CONTROL 197,IDC_STATIC,"Static",SS_BITMAP,288,66,121,38
+ CONTROL "@R_L2TP_OVER_IPSEC",R_L2TP_OVER_IPSEC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,96,269,10
+ LTEXT "@S03",IDC_STATIC,31,111,286,15
+ CONTROL "@R_L2TP_RAW",R_L2TP_RAW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,130,269,10
+ LTEXT "@S04",IDC_STATIC,31,146,378,14
+ RTEXT "@S_1",S_1,16,200,270,14
+ COMBOBOX L_HUBNAME,291,197,114,148,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@S_2",S_2,48,167,361,26
+ GROUPBOX "@S05",IDC_STATIC,7,227,409,56
+ LTEXT "@S06",IDC_STATIC,16,238,294,19
+ CONTROL 195,IDC_STATIC,"Static",SS_BITMAP,314,236,94,43,WS_EX_STATICEDGE
+ CONTROL "@R_ETHERIP",R_ETHERIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,262,184,10
+ PUSHBUTTON "@B_DETAIL",B_DETAIL,204,259,103,17
+ GROUPBOX "@S07",IDC_STATIC,7,291,261,59
+ RTEXT "@S_PSK",S_PSK,14,306,78,14
+ EDITTEXT E_SECRET,98,302,159,15,ES_AUTOHSCROLL
+ LTEXT "@S_PSK2",S_PSK2,14,326,248,19
+ DEFPUSHBUTTON "@IDOK",IDOK,307,336,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,364,336,52,16
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,160,395,1
+ ICON ICO_INFORMATION,IDC_STATIC,24,164,20,20
+ CONTROL 227,IDC_STATIC,"Static",SS_BITMAP,318,104,90,38
+END
+
+D_SM_ETHERIP DIALOGEX 0, 0, 411, 285
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_ETHERIP"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_MACHINE,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,198,18
+ LTEXT "@S01",IDC_STATIC,7,38,221,47
+ LTEXT "@S02",IDC_STATIC,7,87,222,33
+ LTEXT "@S_BOLD",S_BOLD,7,126,222,11
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,140,311,138
+ CONTROL 202,IDC_STATIC,"Static",SS_BITMAP,233,7,171,125,WS_EX_DLGMODALFRAME
+ PUSHBUTTON "@B_ADD",B_ADD,326,155,78,18
+ DEFPUSHBUTTON "@IDOK",IDOK,326,176,78,18
+ PUSHBUTTON "@B_DELETE",B_DELETE,326,198,78,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,326,260,78,18
+ RTEXT "@S03",IDC_STATIC,320,135,84,10,NOT WS_VISIBLE
+END
+
+D_SM_ETHERIP_ID DIALOGEX 0, 0, 267, 265
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_ETHERIP_ID"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_KEY,IDC_STATIC,7,7,20,20
+ LTEXT "@S01",IDC_STATIC,29,7,231,35
+ RTEXT "@S02",IDC_STATIC,7,47,76,14
+ EDITTEXT E_ID,88,45,153,12,ES_AUTOHSCROLL
+ RTEXT "@S03",IDC_STATIC,7,128,76,12
+ COMBOBOX L_HUBNAME,88,125,153,148,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "@S04",IDC_STATIC,7,150,76,14
+ EDITTEXT E_USERNAME,88,148,153,12,ES_AUTOHSCROLL
+ RTEXT "@S05",IDC_STATIC,7,172,76,16
+ EDITTEXT E_PASSWORD,88,170,153,12,ES_PASSWORD | ES_AUTOHSCROLL
+ ICON ICO_INFORMATION,IDC_STATIC,7,197,20,20
+ LTEXT "@S06",IDC_STATIC,30,198,230,38
+ DEFPUSHBUTTON "@IDOK",IDOK,151,242,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,208,242,52,16
+ LTEXT "@S07",IDC_STATIC,88,60,154,64
+END
+
+D_SM_OPENVPN DIALOGEX 0, 0, 427, 387
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_OPENVPN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_OPENVPN,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,32,8,385,18
+ GROUPBOX "@S_13",IDC_STATIC,8,31,409,201
+ LTEXT "@S_1",IDC_STATIC,15,43,195,43
+ CONTROL 205,IDC_STATIC,"Static",SS_BITMAP,217,41,194,87
+ CONTROL "@R_OPENVPN",R_OPENVPN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,88,194,10
+ LTEXT "@S_UDP",S_UDP,25,102,186,10
+ EDITTEXT E_UDP,25,113,127,15,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_DEFAULT",B_DEFAULT,159,112,52,17
+ LTEXT "@S_UDP2",S_UDP2,26,133,383,28
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,14,162,395,1
+ LTEXT "@S_TOOL",S_TOOL,15,168,392,14
+ LTEXT "@S_TOOL2",S_TOOL2,24,184,385,25
+ PUSHBUTTON "@B_CONFIG",B_CONFIG,120,207,189,17
+ GROUPBOX "@S_2",IDC_STATIC,7,236,409,114
+ LTEXT "@S_3",IDC_STATIC,14,248,195,43
+ CONTROL 206,IDC_STATIC,"Static",SS_BITMAP,215,245,194,99
+ CONTROL "@R_SSTP",R_SSTP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,295,194,10
+ LTEXT "@S_SSTP",S_SSTP,21,310,188,38
+ LTEXT "@S_4",IDC_STATIC,7,353,186,27
+ PUSHBUTTON "@B_IPSEC",B_IPSEC,195,363,93,17
+ DEFPUSHBUTTON "@IDOK",IDOK,311,364,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,368,364,52,16
+END
+
+D_SM_DDNS DIALOGEX 0, 0, 415, 335
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_DDNS"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_DISPLAY,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,31,7,377,18
+ LTEXT "@S_BOLD",S_BOLD,7,37,401,13
+ LTEXT "@S_1",IDC_STATIC,7,55,401,32
+ LTEXT "@S_22",IDC_STATIC,7,89,401,34
+ LTEXT "@S_3",IDC_STATIC,7,125,401,25
+ GROUPBOX "@S_4",IDC_STATIC,7,153,194,123
+ LTEXT "@S_STATUS3",S_STATUS3,14,170,182,11
+ EDITTEXT E_HOST,17,184,155,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "@B_HINT",B_HINT,174,181,24,17
+ LTEXT "@S_STATUS4",S_STATUS4,14,205,171,11
+ EDITTEXT E_IPV4,17,217,172,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "@S_STATUS5",S_STATUS5,14,239,171,10
+ EDITTEXT E_IPV6,17,251,172,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ GROUPBOX "@S_5",IDC_STATIC,206,153,202,123
+ LTEXT "@S_STATUS6",S_STATUS6,212,170,189,11
+ EDITTEXT E_NEWHOST,215,184,86,15,ES_AUTOHSCROLL
+ LTEXT "",S_SUFFIX,303,186,98,12
+ LTEXT "@S_STATUS7",S_STATUS7,219,201,182,34
+ DEFPUSHBUTTON "@IDOK",IDOK,218,237,119,18
+ PUSHBUTTON "@B_RESTORE",B_RESTORE,341,237,60,18
+ ICON ICO_INFORMATION,IDC_STATIC,7,282,20,20
+ LTEXT "@S_2",S_2,30,281,378,25
+ PUSHBUTTON "@B_DISABLE",B_DISABLE,7,310,145,18
+ PUSHBUTTON "@B_PROXY",B_PROXY,218,310,110,18
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,335,310,73,18
+END
+
+D_SM_SPECIALLISTENER DIALOGEX 0, 0, 357, 373
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_SPECIALLISTENER"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SPECIALLISTENER,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,32,8,260,18
+ CONTROL 208,IDC_STATIC,"Static",SS_BITMAP,36,131,286,185
+ GROUPBOX "@S_1",S_1,7,36,343,92
+ LTEXT "@S_2",IDC_STATIC,14,50,329,36
+ CONTROL "@R_OVER_ICMP",R_OVER_ICMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,86,272,14
+ CONTROL "@R_OVER_DNS",R_OVER_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,106,272,13
+ DEFPUSHBUTTON "@IDOK",IDOK,241,350,52,16
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,298,350,52,16
+ LTEXT "@S_3",IDC_STATIC,7,352,224,20
+ LTEXT "@S_4",IDC_STATIC,7,321,343,27
+END
+
+D_SM_REDIRECT DIALOGEX 0, 0, 358, 363
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_REDIRECT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INTERNET,IDC_STATIC,7,7,20,20
+ LTEXT "@S_1",IDC_STATIC,31,7,320,53
+ GROUPBOX "@S_2",IDC_STATIC,7,63,344,111
+ RTEXT "@S_BOLD2",S_BOLD2,10,82,71,11
+ EDITTEXT E_URL,86,78,257,17,ES_AUTOHSCROLL
+ RTEXT "@S_3",IDC_STATIC,14,103,52,12
+ RTEXT "@S_4",IDC_STATIC,23,118,102,13
+ EDITTEXT E_SAMPLE1,128,117,215,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ RTEXT "@S_5",IDC_STATIC,23,136,102,14
+ EDITTEXT E_SAMPLE2,128,135,215,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "@B_HINT",B_HINT,197,150,146,19
+ GROUPBOX "@S_6",IDC_STATIC,7,182,344,148
+ ICON ICO_WARNING,IDC_STATIC,11,195,20,20
+ LTEXT "@S_BOLD",S_BOLD,35,197,308,20
+ LTEXT "@S_7",IDC_STATIC,35,224,308,20
+ LTEXT "@S_8",IDC_STATIC,35,249,308,12
+ LTEXT "@S_9",IDC_STATIC,35,267,308,26
+ LTEXT "@S_10",IDC_STATIC,35,293,308,33
+ DEFPUSHBUTTON "@IDOK",IDOK,219,337,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,287,337,64,19
+ LTEXT "@S_11",IDC_STATIC,15,151,175,21
+END
+
+D_SW_TEST1 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "AAA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ PUSHBUTTON "Button1",IDC_BUTTON1,266,128,50,14
+ LTEXT "HAMNEKO",IDC_STATIC,36,6,50,12
+ PUSHBUTTON "Button2",IDC_BUTTON2,266,145,50,14
+ PUSHBUTTON "Button3",IDC_BUTTON3,266,108,50,14
+ PUSHBUTTON "Button4",IDC_BUTTON4,266,161,50,14
+ ICON ICO_INSTALLER,IDC_STATIC,7,6,18,21
+END
+
+D_DUMMY DIALOGEX 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dummy"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ PUSHBUTTON "B_WIZ_NEXT",B_WIZ_NEXT,7,6,50,14
+ PUSHBUTTON "B_WIZ_PREV",B_WIZ_PREV,7,23,50,14
+END
+
+D_SW_TEST2 DIALOGEX 0, 0, 175, 99
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Testkko"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ PUSHBUTTON "Button1",IDC_BUTTON1,7,7,50,14
+ LTEXT "Hanyu",IDC_STATIC,26,44,50,12
+ PUSHBUTTON "Button2",IDC_BUTTON2,118,7,50,14
+ PUSHBUTTON "Button3",IDC_BUTTON3,7,78,50,14
+ PUSHBUTTON "Button4",IDC_BUTTON4,118,78,50,14
+END
+
+D_SW_DEFAULT DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_DEFAULT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+END
+
+D_SW_WELCOME DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_WELCOME"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INSTALLER,IDC_STATIC,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_WELCOME",S_WELCOME,39,22,277,50
+ LTEXT "@S_TITLE",S_TITLE,39,6,277,11
+ CONTROL 223,IDC_STATIC,"Static",SS_BITMAP,54,74,245,107
+END
+
+D_SW_MODE DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_MODE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL "@R_SYSTEM",R_SYSTEM,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,56,75,242,12
+ CONTROL "@R_USER",R_USER,"Button",BS_AUTORADIOBUTTON,56,122,242,12
+ LTEXT "@S_1",IDC_STATIC,68,91,241,27
+ LTEXT "@S_USER",S_USER,68,137,241,27
+ ICON ICO_TOWER,IDC_STATIC,20,75,20,20
+ ICON ICO_USER,IDC_STATIC,20,122,20,20
+ LTEXT "@S_2",IDC_STATIC,7,6,309,63
+ ICON ICO_TEST,S_UAC,42,75,20,20
+END
+
+D_SW_NOT_ADMIN DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_NOT_ADMIN"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INFORMATION,IDC_STATIC,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_INFO",S_INFO,39,6,277,55
+ LTEXT "@S_INFO6",S_INFO6,39,162,277,13
+ LTEXT "@S_INFO2",S_INFO2,39,72,277,32
+END
+
+D_SW_COMPONENTS DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_DEFAULT"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,4,309,98
+ LTEXT "INFO",S_TITLE,7,114,309,16
+ LTEXT "Static",S_DESCRIPTION,44,135,272,44
+ ICON ICO_TEST,S_ICON,19,134,18,21
+END
+
+D_SW_EULA DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_EULA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_1",IDC_STATIC,7,2,309,12,WS_TABSTOP
+ EDITTEXT E_TEXT,7,19,309,139,ES_MULTILINE | ES_READONLY | WS_VSCROLL
+ CONTROL "@B_AGREE",B_AGREE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,168,297,12
+END
+
+D_SW_WARNING DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_WARNING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_1",IDC_STATIC,22,2,294,19,WS_TABSTOP
+ EDITTEXT E_TEXT,7,27,309,141,ES_MULTILINE | ES_READONLY | WS_VSCROLL
+ ICON ICO_INFORMATION,IDC_STATIC,0,0,20,20
+END
+
+D_SW_DIR DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_DIR"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TEST,S_ICON,2,1,20,20,WS_TABSTOP
+ LTEXT "@S_INFO",S_INFO,29,6,287,21
+ CONTROL "dest_dir",R_DEFAULT,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,33,30,283,12
+ CONTROL "@R_CUSTOM",R_CUSTOM,"Button",BS_AUTORADIOBUTTON,33,47,283,12
+ RTEXT "@S_DEST",S_DEST,7,69,72,12
+ EDITTEXT E_DIR,82,67,179,12,ES_AUTOHSCROLL
+ PUSHBUTTON "@B_BROWSE",B_BROWSE,269,65,46,15
+ CONTROL "@R_SHOWCUSTOM",R_SHOWCUSTOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,105,283,10
+ CONTROL "@R_FOR_SYSTEM",R_FOR_SYSTEM,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,46,122,263,10
+ CONTROL "@R_FOR_USER",R_FOR_USER,"Button",BS_AUTORADIOBUTTON,46,137,263,10
+ ICON ICO_WARNING,S_WARNING2,36,154,20,20
+ LTEXT "@S_WARNING",S_WARNING,60,155,256,26
+END
+
+D_SW_READY DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_READY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INSTALLER,S_ICON,2,1,20,20,WS_TABSTOP
+ LTEXT "@S_INFO",S_INFO,29,6,287,21
+ LTEXT "@S_INFO7",S_INFO7,29,29,287,21
+END
+
+D_SW_PERFORM DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_PERFORM"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TEST,S_ICON,0,76,20,20
+ CONTROL "",IDC_PROGRESS1,"msctls_progress32",0x0,7,142,309,15
+ LTEXT "@S_INFO",S_INFO,32,77,284,22
+ LTEXT "STATUS",S_STATUS,7,116,309,24
+ CONTROL 224,IDC_STATIC,"Static",SS_BITMAP,3,0,319,76
+END
+
+D_SW_ERROR DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_ERROR"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_STOP,S_ICON,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_INFO",S_INFO,38,6,278,104
+END
+
+D_SW_FINISH DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_FINISH"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TEST,S_ICON,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_INFO",S_INFO,38,6,278,75
+ CONTROL "RUN_TEXT",B_RUN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,86,271,14
+ LTEXT "@S_INFO8",S_INFO8,65,132,251,48
+ ICON ICO_GROUP,S_ICON2,43,130,18,21,WS_TABSTOP
+END
+
+D_SW_UNINST1 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_UNINST1"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INSTALLER,-1,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_WELCOME",S_WELCOME,39,26,277,55
+ LTEXT "@S_TITLE",S_TITLE,39,6,277,11
+END
+
+D_SW_LANG1 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "D_SW_LANG1"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,65,309,69
+ ICON ICO_LANGUAGE,IDC_STATIC,7,0,20,20
+ CONTROL 218,IDC_STATIC,"Static",SS_BITMAP,57,0,113,24
+ CONTROL 216,IDC_STATIC,"Static",SS_BITMAP,7,27,307,35
+ CONTROL 217,IDC_STATIC,"Static",SS_BITMAP,7,136,307,35
+ EDITTEXT E_CURRENT,173,4,143,17,ES_CENTER | ES_AUTOHSCROLL | ES_READONLY
+END
+
+D_SW_EASY1 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_EASY1"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_EASYINSTALLER,IDC_STATIC,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_WELCOME",S_WELCOME,39,31,277,36
+ LTEXT "@S_TITLE",S_TITLE,39,6,277,11
+ LTEXT "@S_WELCOME2",S_WELCOME2,39,72,277,36
+ LTEXT "@S_WELCOME3",S_WELCOME3,39,114,277,36
+END
+
+D_SW_EASY2 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_EASY2"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SETUP,IDC_STATIC,7,6,18,21,WS_TABSTOP
+ LTEXT "@S_BOLD1",S_BOLD1,35,6,281,13
+ LTEXT "@S_1",S_1,44,26,272,32
+ RTEXT "@S_18",S_18,7,61,79,13
+ EDITTEXT E_SETTING,88,59,177,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "@B_BROWSE_SETTING",B_BROWSE_SETTING,270,57,46,15
+ CONTROL "@B_DELETE_SENSITIVE",B_DELETE_SENSITIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,77,227,12
+ LTEXT "@S_BOLD2",S_BOLD2,35,95,281,13
+ LTEXT "@S_3",S_3,44,115,272,25
+ RTEXT "@S_19",S_19,7,148,79,13
+ EDITTEXT E_OUT,88,146,177,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "@B_BROWSE_OUT",B_BROWSE_OUT,270,144,46,15
+ CONTROL "@B_EASYMODE",B_EASYMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,163,227,12
+END
+
+D_SW_WEB1 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_WEB1"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_INTERNET,IDC_STATIC,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_WELCOME",S_WELCOME,39,31,277,36
+ LTEXT "@S_TITLE",S_TITLE,39,6,277,11
+ LTEXT "@S_WELCOME2",S_WELCOME2,39,72,277,36
+ LTEXT "@S_WELCOME3",S_WELCOME3,39,114,277,36
+END
+
+D_SW_WEB2 DIALOGEX 0, 0, 323, 181
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SW_WEB2"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_SETUP,IDC_STATIC,7,6,20,20,WS_TABSTOP
+ LTEXT "@S_BOLD1",S_BOLD1,35,6,281,13
+ LTEXT "@S_1",S_1,44,26,272,32
+ RTEXT "@S_18",S_18,7,61,79,13
+ EDITTEXT E_SETTING,88,59,177,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "@B_BROWSE_SETTING",B_BROWSE_SETTING,270,57,46,15
+ CONTROL "@B_DELETE_SENSITIVE",B_DELETE_SENSITIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,77,227,12
+ LTEXT "@S_BOLD2",S_BOLD2,35,95,281,13
+ LTEXT "@S_3",S_3,44,115,272,25
+ RTEXT "@S_19",S_19,7,148,79,13
+ EDITTEXT E_OUT,88,146,177,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "@B_BROWSE_OUT",B_BROWSE_OUT,270,144,46,15
+ CONTROL "@B_EASYMODE",B_EASYMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,163,227,12
+END
+
+D_UPDATE_NOTICE DIALOGEX 0, 0, 259, 239
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST
+CAPTION "@D_UPDATE_NOTICE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 225,IDC_STATIC,"Static",SS_BITMAP | WS_TABSTOP,2,2,254,79
+ DEFPUSHBUTTON "@IDOK",IDOK,7,213,117,19
+ PUSHBUTTON "@B_CONFIG",B_CONFIG,162,112,90,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,135,213,117,19
+ LTEXT "@S_INFO",S_INFO,7,82,245,28
+ RTEXT "@S_PRODUCT",S_PRODUCT,7,141,77,17
+ LTEXT "TITLE",S_PRODUCT_STR,90,139,162,18
+ RTEXT "@S_CURRENT",S_CURRENT,7,164,77,18
+ LTEXT "@S_CURRENT_STR",S_CURRENT_STR,90,162,162,18
+ RTEXT "@S_LATEST",S_LATEST,7,188,77,18
+ LTEXT "@S_LATEST_STR",S_LATEST_STR,90,186,162,19
+END
+
+D_UPDATE_CONFIG DIALOGEX 0, 0, 307, 155
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST
+CAPTION "@D_UPDATE_CONFIG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_INFO",S_INFO,7,32,293,54
+ LTEXT "@S_TITLE",S_TITLE,7,7,293,24
+ CONTROL "@S_ENABLE",S_ENABLE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,48,94,157,13
+ CONTROL "@S_DISBLE",S_DISBLE,"Button",BS_AUTORADIOBUTTON,48,113,157,13
+ ICON ICO_MACHINE,IDC_STATIC,16,93,20,20
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,236,131,64,17
+END
+
+D_SM_VMBRIDGE DIALOGEX 0, 0, 311, 315
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_VMBRIDGE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 228,IDC_STATIC,"Static",SS_BITMAP,12,76,286,85
+ ICON ICO_NIC_ONLINE,IDC_STATIC,6,5,18,21
+ LTEXT "@S_TITLE",S_TITLE,32,7,272,22
+ LTEXT "@S_1",IDC_STATIC,7,31,297,27
+ LTEXT "@S_2",IDC_STATIC,14,168,282,105
+ GROUPBOX "@S_BOLD",S_BOLD,7,61,297,219
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,248,290,56,18
+END
+
+D_SM_AZURE DIALOGEX 0, 0, 411, 371
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_AZURE"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL 229,S_BMP_EN,"Static",SS_BITMAP,7,0,397,201
+ LTEXT "@S_TITLE",S_TITLE,7,207,397,18
+ LTEXT "@S_1",IDC_STATIC,7,227,397,27
+ LTEXT "@S_2",IDC_STATIC,7,254,397,27
+ LTEXT "@S_3",IDC_STATIC,30,281,374,24
+ GROUPBOX "@B_BOLD",B_BOLD,7,309,112,55
+ CONTROL "@R_ENABLE",R_ENABLE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,319,102,14
+ CONTROL "@R_DISABLE",R_DISABLE,"Button",BS_AUTORADIOBUTTON,13,347,101,14
+ GROUPBOX "@S_HOSTNAME_BORDER",S_HOSTNAME_BORDER,123,309,204,55
+ LTEXT "@S_HOSTNAME_INFO",S_HOSTNAME_INFO,129,321,191,22
+ EDITTEXT E_HOST,129,345,118,15,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "@B_CHANGE",B_CHANGE,252,343,67,17
+ PUSHBUTTON "@B_WEB",B_WEB,332,305,72,35,BS_MULTILINE
+ DEFPUSHBUTTON "@IDCANCEL",IDCANCEL,331,346,73,18
+ CONTROL 230,S_BMP_JA,"Static",SS_BITMAP,7,0,397,201
+ ICON ICO_AZURE,IDC_STATIC,7,280,20,20
+ LTEXT "STATUS_STRING",S_STATUS,22,336,95,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,204,415,1
+ CONTROL 232,S_BMP_CN,"Static",SS_BITMAP,7,0,397,201
+END
+
+D_SM_PROXY DIALOGEX 0, 0, 227, 167
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_SM_PROXY"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_TOWER,IDC_STATIC,7,7,20,20
+ LTEXT "@STATIC9",IDC_STATIC,33,7,187,19
+ RTEXT "@STATIC10",IDC_STATIC,7,46,54,11
+ CONTROL "@R_DIRECT_TCP",R_DIRECT_TCP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,65,44,135,11
+ CONTROL "@R_HTTPS",R_HTTPS,"Button",BS_AUTORADIOBUTTON,65,56,135,11
+ CONTROL "@R_SOCKS",R_SOCKS,"Button",BS_AUTORADIOBUTTON,65,68,135,11
+ PUSHBUTTON "@B_PROXY_CONFIG",B_PROXY_CONFIG,67,92,114,17
+ DEFPUSHBUTTON "@IDOK",IDOK,87,143,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,156,143,64,17
+END
+
+D_VGC_LIST DIALOGEX 0, 0, 446, 354
+STYLE DS_SETFONT | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "@D_VGC_LIST"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_RESEARCH,IDC_STATIC,7,9,20,20
+ LTEXT "@S_TITLE",S_TITLE,30,7,186,17
+ LTEXT "@S_INFO1",S_INFO1,30,28,331,25
+ LTEXT "STATIC",S_BOLD,8,65,352,11
+ CONTROL "",L_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,7,80,432,211
+ DEFPUSHBUTTON "@IDOK",IDOK,276,321,163,25
+ PUSHBUTTON "@B_PROXY",B_PROXY,7,320,62,18
+ RTEXT "@S_VLAN",S_VLAN,69,324,81,15
+ COMBOBOX C_VLAN,153,322,87,101,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "@B_WEB",B_WEB,369,22,70,26,BS_MULTILINE
+ PUSHBUTTON "@B_REFRESH",B_REFRESH,369,55,70,18
+ CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE,372,62,63,10
+ LTEXT "@S_REFRESH",S_REFRESH,375,51,71,9,NOT WS_VISIBLE
+ LTEXT "Implemented as a plug-in for SoftEther VPN. (c) VPN Gate Project at University of Tsukuba, Japan.",S_COPYRIGHT,7,343,268,8
+ CONTROL 240,S_TSUKUBA,"Static",SS_BITMAP,397,3,44,15
+ RTEXT "@S_RESEARCH",S_RESEARCH,219,6,174,12
+ LTEXT "@S_INFO9",S_INFO9,7,294,432,26
+END
+
+D_VGC_PROTOCOL DIALOGEX 0, 0, 283, 173
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_VGC_PROTOCOL"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "@S_TITLE",S_TITLE,34,7,240,33
+ LTEXT "@S_INFO",S_INFO,34,45,240,43
+ CONTROL "@R_TCP",R_TCP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,50,93,198,17
+ CONTROL "@R_UDP",R_UDP,"Button",BS_AUTORADIOBUTTON,50,113,198,17
+ DEFPUSHBUTTON "@IDOK",IDOK,136,147,64,19
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,204,147,64,19
+ ICON ICO_SERVER_ONLINE,IDC_STATIC,7,7,20,20
+END
+
+D_VGS_CONFIG DIALOGEX 0, 0, 370, 363
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_VGS_CONFIG"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ CONTROL "@R_ENABLE",R_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,265,330,15
+ CONTROL 238,S_VPNGATEJA,"Static",SS_BITMAP,0,0,370,158
+ ICON ICO_RESEARCH,IDC_STATIC,7,167,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,170,195,17
+ LTEXT "@S_INFO1",S_INFO1,33,191,330,36
+ LTEXT "@S_INFO9",S_INFO9,33,228,330,36
+ ICON ICO_INFORMATION,IDC_STATIC,42,286,20,20
+ LTEXT "@S_WARNING",S_WARNING,66,286,297,52
+ PUSHBUTTON "@B_OPTION",B_OPTION,7,339,137,17
+ DEFPUSHBUTTON "@IDOK",IDOK,230,339,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,299,339,64,17
+ PUSHBUTTON "@B_WEB",B_WEB,228,168,135,17
+ CONTROL 237,S_VPNGATEEN,"Static",SS_BITMAP,0,0,370,158
+END
+
+D_VGS_OPTION DIALOGEX 0, 0, 355, 345
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_VGS_OPTION"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_RESEARCH,IDC_STATIC,7,7,20,20
+ LTEXT "@S_TITLE",S_TITLE,33,7,315,22
+ GROUPBOX "@S_2",S_2,7,35,341,149
+ LTEXT "@S_1",S_1,41,48,293,34
+ RTEXT "@S_3",S_3,14,87,114,11
+ EDITTEXT E_OWNER,132,85,150,12,ES_AUTOHSCROLL
+ LTEXT "@S_19",S_19,287,87,56,12
+ RTEXT "@S_20",S_20,14,104,114,18
+ EDITTEXT E_ABUSE,132,109,150,12,ES_AUTOHSCROLL
+ LTEXT "@S_21",S_21,287,111,59,15
+ ICON ICO_GROUP,IDC_STATIC,14,47,20,20
+ RTEXT "@S_22",S_22,14,129,114,31
+ EDITTEXT E_MSG,132,128,207,31,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
+ LTEXT "@S_23",S_23,132,163,208,18
+ GROUPBOX "@S_24",S_24,7,187,341,130
+ ICON ICO_MACHINE,IDC_STATIC,14,201,20,20
+ CONTROL "@R_LOG",R_LOG,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,46,202,293,10
+ CONTROL "@R_2WEEKS",R_2WEEKS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,56,219,284,10
+ CONTROL "@R_PERMANENT",R_PERMANENT,"Button",BS_AUTORADIOBUTTON,56,234,284,10
+ CONTROL "@R_L2TP",R_L2TP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,46,253,293,10
+ LTEXT "@S_25",S_25,55,269,285,12
+ PUSHBUTTON "@B_MESSAGE",B_MESSAGE,45,286,268,17
+ DEFPUSHBUTTON "@IDOK",IDOK,215,321,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,284,321,64,17
+END
+
+D_VGS_WARNING DIALOGEX 0, 0, 349, 291
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@D_VGS_WARNING"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON ICO_POLICE,IDC_STATIC,7,7,20,20
+ LTEXT "@S1",S1,32,41,310,32
+ LTEXT "@S2",S2,32,75,310,46
+ LTEXT "@S3",S3,32,121,310,34
+ LTEXT "@S4",S4,32,156,310,27
+ LTEXT "@S5",S5,32,185,310,55
+ CONTROL "@R_NEVER",R_NEVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,246,297,13
+ PUSHBUTTON "@B_WEB",B_WEB,7,267,123,17
+ DEFPUSHBUTTON "@IDOK",IDOK,209,267,64,17
+ PUSHBUTTON "@IDCANCEL",IDCANCEL,278,267,64,17
+ LTEXT "@S_BOLD",S_BOLD,32,7,310,31
+ ICON ICO_RESEARCH,IDC_STATIC,7,185,20,20
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+ICO_TEST ICON "Test.ico"
+ICO_KEY ICON "Key.ico"
+ICO_CERT ICON "Cert.ico"
+ICO_SERVER_ONLINE ICON "Server.ico"
+ICO_WARNING ICON "Warning.ico"
+ICO_NULL ICON "Null.ico"
+ICO_TOWER ICON "Tower.ico"
+ICO_VPN ICON "VPN.ico"
+ICO_VPNSERVER ICON "VPNSvr.ico"
+ICO_NIC_ONLINE ICON "NIC.ico"
+ICO_SETUP ICON "Setup.ico"
+ICO_MACHINE ICON "Machine.ico"
+ICO_HUB ICON "Hub.ico"
+ICO_VLAN ICON "VLan.ico"
+ICO_SERVER_OFFLINE ICON "Server_Offline.ico"
+ICO_NIC_OFFLINE ICON "NIC_Offline.ico"
+ICO_INFORMATION ICON "Information.ico"
+ICO_STOP ICON "Stop.ico"
+ICO_SERVER_DELETE ICON "Server_Delete.ico"
+ICO_SERVER_ONLINE_EX ICON "Server_Online_Ex.ico"
+ICO_SERVER_OFFLINE_EX ICON "Server_Offline_Ex.ico"
+ICO_INTERNET ICON "Internet.ico"
+ICO_DISPLAY ICON "Display.ico"
+ICO_GROUP ICON "Group.ico"
+ICO_USER ICON "User.ico"
+ICO_USER_ADMIN ICON "UserAdmin.ico"
+ICO_HUB_OFFLINE ICON "Hub_Offline.ico"
+ICO_FARM ICON "Farm.ico"
+ICO_X ICON "X.ico"
+ICO_PROTOCOL ICON "Protocol.ico"
+ICO_PROTOCOL_X ICON "Protocol2.ico"
+ICO_DISCARD ICON "Discard.ico"
+ICO_PASS ICON "Pass.ico"
+ICO_PROTOCOL_OFFLINE ICON "ProtocolOffline.ico"
+ICO_MEMORY ICON "Memory.ico"
+ICO_PKCS12 ICON "PKCS12.ico"
+ICO_SERVER_CERT ICON "ServerCert.ico"
+ICO_LINK ICON "Link.ico"
+ICO_PENGUIN ICON "Penguin.ico"
+ICO_LINK2 ICON "Link2.ico"
+ICO_CASCADE ICON "Cascade.ico"
+ICO_USER_DENY ICON "UserDeny.ico"
+ICO_GROUP_DENY ICON "GroupDeny.ico"
+ICO_LOG ICON "Log.ico"
+ICO_LOG2 ICON "Log2.ico"
+ICO_DATETIME ICON "DateTime.ico"
+ICO_NEW ICON "New.ico"
+ICO_PASS_DISABLE ICON "PassDisable.ico"
+ICO_DISCARD_DISABLE ICON "DiscardDisable.ico"
+ICO_CASCADE_ERROR ICON "CascadeOffline.ico"
+ICO_CASCADE_OFFLINE ICON "CascadeOffline2.ico"
+ICO_PROTOCOL_DHCP ICON "ProtocolDhcp.ico"
+ICO_ROUTER ICON "Router.ico"
+ICO_BRIDGE ICON "Bridge.ico"
+ICO_SWITCH ICON "Switch.ico"
+ICO_SWITCH_OFFLINE ICON "SwitchOffline.ico"
+ICO_SECURE ICON "Secure.ico"
+ICO_CERT_X ICON "CertX.ico"
+ICO_INTERNET_X ICON "InternetX.ico"
+ICO_LICENSE ICON "License.ico"
+ICO_SESSION_BRIDGE ICON "SessionBridge.ico"
+ICO_SESSION_MONITOR ICON "SessionMonitor.ico"
+ICO_TRAY1 ICON "Tray1.ico"
+ICO_TRAY2 ICON "Tray2.ico"
+ICO_TRAY3 ICON "Tray3.ico"
+ICO_TRAY4 ICON "Tray4.ico"
+ICO_TRAY0 ICON "Tray0.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+BMP_TEST BITMAP "Test.bmp"
+BMP_SECURE BITMAP "Secure.bmp"
+BMP_SECURE2 BITMAP "Secure2.bmp"
+BMP_MANAGER_LOGO BITMAP "ManagerLogo.bmp"
+BMP_ROUTER_BANNER BITMAP "RouterBanner.bmp"
+BMP_ROUTER_LOGO BITMAP "RouterLogo.bmp"
+BMP_COINS BITMAP "Coins.bmp"
+BMP_SECURE3 BITMAP "Secure3.bmp"
+BMP_CLIENT_BANNER BITMAP "ClientBanner.bmp"
+BMP_SETUP_2 BITMAP "setup_2.bmp"
+BMP_SETUP_1 BITMAP "setup_1.bmp"
+BMP_TSUKUBA BITMAP "Tsukuba.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AVI
+//
+
+AVI_PROGRESS AVI "Progress.avi"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+M_MAIN MENU
+BEGIN
+ POPUP "@CMD_TOP_CONNECT"
+ BEGIN
+ MENUITEM "@CMD_CONNECT", CMD_CONNECT
+ MENUITEM "@CMD_STATUS", CMD_STATUS
+ MENUITEM "@CMD_DISCONNECT", CMD_DISCONNECT
+ MENUITEM "@CMD_DISCONNECT_ALL", CMD_DISCONNECT_ALL
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_RECENT", CMD_RECENT
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_NEW", CMD_NEW
+ MENUITEM "@CMD_CLONE", CMD_CLONE
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_SHORTCUT", CMD_SHORTCUT
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_EXPORT_ACCOUNT", CMD_EXPORT_ACCOUNT
+ MENUITEM "@CMD_IMPORT_ACCOUNT", CMD_IMPORT_ACCOUNT
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_STARTUP", CMD_STARTUP
+ MENUITEM "@CMD_NOSTARTUP", CMD_NOSTARTUP
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_RENAME", CMD_RENAME
+ MENUITEM "@CMD_DELETE", CMD_DELETE
+ MENUITEM "@CMD_PROPERTY", CMD_PROPERTY
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_TRAYICON", CMD_TRAYICON
+ MENUITEM "@CMD_EXIT", CMD_EXIT
+ MENUITEM "@CMD_QUIT", CMD_QUIT
+ END
+ POPUP "@CMD_TOP_EDIT"
+ BEGIN
+ MENUITEM "@CMD_SELECT_ALL", CMD_SELECT_ALL
+ MENUITEM "@CMD_SWITCH_SELECT", CMD_SWITCH_SELECT
+ END
+ POPUP "@CMD_TOP_VIEW"
+ BEGIN
+ MENUITEM "@CMD_STATUSBAR", CMD_STATUSBAR
+ MENUITEM "@CMD_TRAYICON", CMD_TRAYICON
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_SHOWPORT", CMD_SHOWPORT
+ MENUITEM "@CMD_VISTASTYLE", CMD_VISTASTYLE
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_ICON", CMD_ICON
+ MENUITEM "@CMD_DETAIL", CMD_DETAIL
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_GRID", CMD_GRID
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_REFRESH", CMD_REFRESH
+ END
+ POPUP "@CMD_TOP_VLAN"
+ BEGIN
+ MENUITEM "@CMD_NEW_VLAN", CMD_NEW_VLAN
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_ENABLE_VLAN", CMD_ENABLE_VLAN
+ MENUITEM "@CMD_DISABLE_VLAN", CMD_DISABLE_VLAN
+ MENUITEM "@CMD_DELETE_VLAN", CMD_DELETE_VLAN
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_REINSTALL", CMD_REINSTALL
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_WINNET", CMD_WINNET
+ END
+ POPUP "@CMD_TOP_SECURE"
+ BEGIN
+ MENUITEM "@CMD_SECURE_MANAGER", CMD_SECURE_MANAGER
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_SECURE_SELECT", CMD_SECURE_SELECT
+ END
+ POPUP "@CMD_TOP_TOOL"
+ BEGIN
+ MENUITEM "@CMD_PASSWORD", CMD_PASSWORD
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_TRUST", CMD_TRUST
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_NETIF", CMD_NETIF
+ MENUITEM "@CMD_MMCSS", CMD_MMCSS
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_TRAFFIC", CMD_TRAFFIC
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_CM_SETTING", CMD_CM_SETTING
+ MENUITEM "@CMD_LANGUAGE", CMD_LANGUAGE
+ MENUITEM "@CMD_OPTION", CMD_OPTION
+ END
+ POPUP "@CMD_TOP_HELP"
+ BEGIN
+ MENUITEM "@CMD_ABOUT", CMD_ABOUT
+ END
+END
+
+M_VOICE_BACKUP MENU
+BEGIN
+ POPUP "@CMD_TOP_VOICE"
+ BEGIN
+ MENUITEM "@CMD_VOIDE_NONE", CMD_VOIDE_NONE
+ MENUITEM SEPARATOR
+ MENUITEM "@CMD_VOICE_NORMAL", CMD_VOICE_NORMAL
+ MENUITEM "@CMD_VOICE_ODD", CMD_VOICE_ODD
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// BIN
+//
+
+BIN_WINPCAP BIN "Dummy.bin"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+ICO_IPSEC ICON "IPsec.ico"
+ICO_DDNS ICON "DDNS.ico"
+ICO_OPENVPN ICON "OpenVPN.ico"
+ICO_SPECIALLISTENER ICON "SpecialListener.ico"
+ICO_INSTALLER ICON "Installer.ico"
+ICO_LANGUAGE ICON "Language.ico"
+ICO_LANG_CHINESE ICON "LANG_CHINESE.ico"
+ICO_LANG_ENGLISH ICON "LANG_ENGLISH.ico"
+ICO_LANG_JAPANESE ICON "LANG_JAPANESE.ico"
+ICO_EASYINSTALLER ICON "EasyInstaller.ico"
+ICO_AZURE ICON "Azure.ico"
+ICO_ZURUHAM ICON "ZuruHam.ico"
+ICO_ZURUKKO ICON "Zurukko.ico"
+ICO_RESEARCH ICON "Research.ico"
+ICO_POLICE ICON "Police.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+BMP_ETHERIP BITMAP "EtherIP.bmp"
+BMP_L2TP BITMAP "L2TP.bmp"
+BMP_IX2015 BITMAP "IX2015.bmp"
+BMP_OPENVPN BITMAP "OpenVPN.bmp"
+BMP_SSTP BITMAP "SSTP.bmp"
+BMP_SPECIALLISTENER BITMAP "SpecialListener.bmp"
+BMP_SELOGO49x49 BITMAP "SELOGO49x49.bmp"
+BMP_UT BITMAP "BMP_UT.bmp"
+BMP_SW_LANG_1 BITMAP "SW_LANG_1.bmp"
+BMP_SW_LANG_2 BITMAP "SW_LANG_2.bmp"
+BMP_SW_LANG_3 BITMAP "SW_LANG_3.bmp"
+BMP_VPNSERVER_FIGURE BITMAP "VPNServerFigure.bmp"
+BMP_ABOUTBOX BITMAP "AboutBox.bmp"
+BMP_UPDATE BITMAP "Update.bmp"
+BMP_IBARAKI BITMAP "Ibaraki.bmp"
+BMP_WINPC BITMAP "WinPC.bmp"
+BMP_VMBRIDGE BITMAP "VMBridge.bmp"
+BMP_AZURE BITMAP "Azure.bmp"
+BMP_AZURE_JA BITMAP "AzureJa.bmp"
+BMP_AZURE_CN BITMAP "AzureCn.bmp"
+BMP_VPNGATEBANNER BITMAP "VPNGateBanner.bmp"
+BMP_ZURUKKO BITMAP "Zurukko.bmp"
+BMP_VPNGATEEN BITMAP "VPNGateEN.bmp"
+BMP_VPNGATEJA BITMAP "VPNGateJA.bmp"
+BMP_UNIVTSUKUBA BITMAP "UnivTsukuba.bmp"
+#endif // English resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/PenCore/PenCore.vcproj b/src/PenCore/PenCore.vcproj
new file mode 100644
index 00000000..902f786d
--- /dev/null
+++ b/src/PenCore/PenCore.vcproj
@@ -0,0 +1,667 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="PenCore"
+ ProjectGUID="{AF16335D-DBC2-4879-9E9A-89E2A61A4B30}"
+ RootNamespace="PenCore"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\PenCore.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\PenCore.c"
+ >
+ </File>
+ <File
+ RelativePath=".\PenCore.def"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\AboutBox.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Azure.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Azure.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureCn.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\AzureJa.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\bitmap1.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\BMP_SW_TSUKUBA.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\BMP_UT.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Bridge.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Cascade.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\CascadeOffline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\CascadeOffline2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Cert.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\CertX.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ClientBanner.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Coins.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\DateTime.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\DDNS.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Discard.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\DiscardDisable.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Display.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Dummy.bin"
+ >
+ </File>
+ <File
+ RelativePath=".\EasyInstaller.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\EtherIP.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Farm.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Group.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\GroupDeny.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Hub.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Hub_Offline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Ibaraki.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Information.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Installer.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Internet.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\InternetX.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\IPsec.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\IX2015.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Key.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\L2TP.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\LANG_CHINESE.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\LANG_ENGLISH.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\LANG_JAPANESE.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Language.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\License.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Link.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Link2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Log.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Log2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Machine.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ManagerLogo.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Memory.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\New.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\NIC.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\NIC_Offline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Null.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\OpenVPN.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\OpenVPN.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Pass.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\PassDisable.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\PenCore.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\Penguin.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\PKCS12.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Police.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Progress.avi"
+ >
+ </File>
+ <File
+ RelativePath=".\Protocol.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Protocol2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ProtocolDhcp.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ProtocolOffline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Research.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Router.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\RouterBanner.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\RouterLogo.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure2.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure3.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SELOGO49x49.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Server.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Server_Delete.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Server_Offline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Server_Offline_Ex.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Server_Online_Ex.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ServerCert.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\SessionBridge.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\SessionMonitor.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Setup.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\setup_1.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\setup_2.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SpecialListener.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SpecialListener.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\SplashClient.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SplashLogger.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SplashManager.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SplashRouter.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SSTP.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Stop.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\SW_LANG_1.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SW_LANG_2.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SW_LANG_3.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\SW_SPLASH.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Switch.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\SwitchOffline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Test.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Test.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tower.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tray0.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tray1.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tray2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tray3.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tray4.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Tsukuba.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\UnivTsukuba.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Update.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\User.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\UserAdmin.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\UserDeny.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\VLan.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\VMBridge.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VPN.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNGateBanner.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNGateEN.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNGateJA.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNServerFigure.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNSvr.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Warning.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\WinPC.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\X.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\ZuruHam.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Zurukko.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\Zurukko.ico"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/PenCore/Penguin.ico b/src/PenCore/Penguin.ico
new file mode 100644
index 00000000..6488df97
--- /dev/null
+++ b/src/PenCore/Penguin.ico
Binary files differ
diff --git a/src/PenCore/Police.ico b/src/PenCore/Police.ico
new file mode 100644
index 00000000..f674ea39
--- /dev/null
+++ b/src/PenCore/Police.ico
Binary files differ
diff --git a/src/PenCore/Progress.avi b/src/PenCore/Progress.avi
new file mode 100644
index 00000000..aeba7ad0
--- /dev/null
+++ b/src/PenCore/Progress.avi
Binary files differ
diff --git a/src/PenCore/Protocol.ico b/src/PenCore/Protocol.ico
new file mode 100644
index 00000000..48236516
--- /dev/null
+++ b/src/PenCore/Protocol.ico
Binary files differ
diff --git a/src/PenCore/Protocol2.ico b/src/PenCore/Protocol2.ico
new file mode 100644
index 00000000..61abfdd3
--- /dev/null
+++ b/src/PenCore/Protocol2.ico
Binary files differ
diff --git a/src/PenCore/ProtocolDhcp.ico b/src/PenCore/ProtocolDhcp.ico
new file mode 100644
index 00000000..ce5d1fff
--- /dev/null
+++ b/src/PenCore/ProtocolDhcp.ico
Binary files differ
diff --git a/src/PenCore/ProtocolOffline.ico b/src/PenCore/ProtocolOffline.ico
new file mode 100644
index 00000000..384d5bc5
--- /dev/null
+++ b/src/PenCore/ProtocolOffline.ico
Binary files differ
diff --git a/src/PenCore/Research.ico b/src/PenCore/Research.ico
new file mode 100644
index 00000000..c2ef4443
--- /dev/null
+++ b/src/PenCore/Research.ico
Binary files differ
diff --git a/src/PenCore/Router.ico b/src/PenCore/Router.ico
new file mode 100644
index 00000000..bf724fd4
--- /dev/null
+++ b/src/PenCore/Router.ico
Binary files differ
diff --git a/src/PenCore/RouterBanner.bmp b/src/PenCore/RouterBanner.bmp
new file mode 100644
index 00000000..6d425eff
--- /dev/null
+++ b/src/PenCore/RouterBanner.bmp
Binary files differ
diff --git a/src/PenCore/RouterLogo.bmp b/src/PenCore/RouterLogo.bmp
new file mode 100644
index 00000000..11ebb202
--- /dev/null
+++ b/src/PenCore/RouterLogo.bmp
Binary files differ
diff --git a/src/PenCore/SELOGO49x49.bmp b/src/PenCore/SELOGO49x49.bmp
new file mode 100644
index 00000000..116b0321
--- /dev/null
+++ b/src/PenCore/SELOGO49x49.bmp
Binary files differ
diff --git a/src/PenCore/SSTP.bmp b/src/PenCore/SSTP.bmp
new file mode 100644
index 00000000..d1edbbad
--- /dev/null
+++ b/src/PenCore/SSTP.bmp
Binary files differ
diff --git a/src/PenCore/SW_LANG_1.bmp b/src/PenCore/SW_LANG_1.bmp
new file mode 100644
index 00000000..e2dceeac
--- /dev/null
+++ b/src/PenCore/SW_LANG_1.bmp
Binary files differ
diff --git a/src/PenCore/SW_LANG_2.bmp b/src/PenCore/SW_LANG_2.bmp
new file mode 100644
index 00000000..530c2f82
--- /dev/null
+++ b/src/PenCore/SW_LANG_2.bmp
Binary files differ
diff --git a/src/PenCore/SW_LANG_3.bmp b/src/PenCore/SW_LANG_3.bmp
new file mode 100644
index 00000000..9ce7e771
--- /dev/null
+++ b/src/PenCore/SW_LANG_3.bmp
Binary files differ
diff --git a/src/PenCore/Secure.bmp b/src/PenCore/Secure.bmp
new file mode 100644
index 00000000..eb2ce802
--- /dev/null
+++ b/src/PenCore/Secure.bmp
Binary files differ
diff --git a/src/PenCore/Secure.ico b/src/PenCore/Secure.ico
new file mode 100644
index 00000000..f08f16d7
--- /dev/null
+++ b/src/PenCore/Secure.ico
Binary files differ
diff --git a/src/PenCore/Secure2.bmp b/src/PenCore/Secure2.bmp
new file mode 100644
index 00000000..94e22e42
--- /dev/null
+++ b/src/PenCore/Secure2.bmp
Binary files differ
diff --git a/src/PenCore/Secure3.bmp b/src/PenCore/Secure3.bmp
new file mode 100644
index 00000000..80119bcb
--- /dev/null
+++ b/src/PenCore/Secure3.bmp
Binary files differ
diff --git a/src/PenCore/Server.ico b/src/PenCore/Server.ico
new file mode 100644
index 00000000..b569c128
--- /dev/null
+++ b/src/PenCore/Server.ico
Binary files differ
diff --git a/src/PenCore/ServerCert.ico b/src/PenCore/ServerCert.ico
new file mode 100644
index 00000000..7e1a55ab
--- /dev/null
+++ b/src/PenCore/ServerCert.ico
Binary files differ
diff --git a/src/PenCore/Server_Delete.ico b/src/PenCore/Server_Delete.ico
new file mode 100644
index 00000000..40047291
--- /dev/null
+++ b/src/PenCore/Server_Delete.ico
Binary files differ
diff --git a/src/PenCore/Server_Offline.ico b/src/PenCore/Server_Offline.ico
new file mode 100644
index 00000000..eb4cbd15
--- /dev/null
+++ b/src/PenCore/Server_Offline.ico
Binary files differ
diff --git a/src/PenCore/Server_Offline_Ex.ico b/src/PenCore/Server_Offline_Ex.ico
new file mode 100644
index 00000000..44a77fda
--- /dev/null
+++ b/src/PenCore/Server_Offline_Ex.ico
Binary files differ
diff --git a/src/PenCore/Server_Online_Ex.ico b/src/PenCore/Server_Online_Ex.ico
new file mode 100644
index 00000000..6398b153
--- /dev/null
+++ b/src/PenCore/Server_Online_Ex.ico
Binary files differ
diff --git a/src/PenCore/SessionBridge.ico b/src/PenCore/SessionBridge.ico
new file mode 100644
index 00000000..a59218a5
--- /dev/null
+++ b/src/PenCore/SessionBridge.ico
Binary files differ
diff --git a/src/PenCore/SessionMonitor.ico b/src/PenCore/SessionMonitor.ico
new file mode 100644
index 00000000..7ee8fc55
--- /dev/null
+++ b/src/PenCore/SessionMonitor.ico
Binary files differ
diff --git a/src/PenCore/Setup.ico b/src/PenCore/Setup.ico
new file mode 100644
index 00000000..2cf9d172
--- /dev/null
+++ b/src/PenCore/Setup.ico
Binary files differ
diff --git a/src/PenCore/SpecialListener.bmp b/src/PenCore/SpecialListener.bmp
new file mode 100644
index 00000000..402e3925
--- /dev/null
+++ b/src/PenCore/SpecialListener.bmp
Binary files differ
diff --git a/src/PenCore/SpecialListener.ico b/src/PenCore/SpecialListener.ico
new file mode 100644
index 00000000..59115bae
--- /dev/null
+++ b/src/PenCore/SpecialListener.ico
Binary files differ
diff --git a/src/PenCore/Stop.ico b/src/PenCore/Stop.ico
new file mode 100644
index 00000000..8717bb17
--- /dev/null
+++ b/src/PenCore/Stop.ico
Binary files differ
diff --git a/src/PenCore/Switch.ico b/src/PenCore/Switch.ico
new file mode 100644
index 00000000..13e323b0
--- /dev/null
+++ b/src/PenCore/Switch.ico
Binary files differ
diff --git a/src/PenCore/SwitchOffline.ico b/src/PenCore/SwitchOffline.ico
new file mode 100644
index 00000000..73160211
--- /dev/null
+++ b/src/PenCore/SwitchOffline.ico
Binary files differ
diff --git a/src/PenCore/Test.bmp b/src/PenCore/Test.bmp
new file mode 100644
index 00000000..dacf8ffe
--- /dev/null
+++ b/src/PenCore/Test.bmp
Binary files differ
diff --git a/src/PenCore/Test.ico b/src/PenCore/Test.ico
new file mode 100644
index 00000000..3d732232
--- /dev/null
+++ b/src/PenCore/Test.ico
Binary files differ
diff --git a/src/PenCore/Thumbs.db b/src/PenCore/Thumbs.db
new file mode 100644
index 00000000..a9137666
--- /dev/null
+++ b/src/PenCore/Thumbs.db
Binary files differ
diff --git a/src/PenCore/Tower.ico b/src/PenCore/Tower.ico
new file mode 100644
index 00000000..a2f8ab33
--- /dev/null
+++ b/src/PenCore/Tower.ico
Binary files differ
diff --git a/src/PenCore/Tray0.ico b/src/PenCore/Tray0.ico
new file mode 100644
index 00000000..9ccaa63c
--- /dev/null
+++ b/src/PenCore/Tray0.ico
Binary files differ
diff --git a/src/PenCore/Tray1.ico b/src/PenCore/Tray1.ico
new file mode 100644
index 00000000..21058beb
--- /dev/null
+++ b/src/PenCore/Tray1.ico
Binary files differ
diff --git a/src/PenCore/Tray2.ico b/src/PenCore/Tray2.ico
new file mode 100644
index 00000000..d2e10b9c
--- /dev/null
+++ b/src/PenCore/Tray2.ico
Binary files differ
diff --git a/src/PenCore/Tray3.ico b/src/PenCore/Tray3.ico
new file mode 100644
index 00000000..52c7d115
--- /dev/null
+++ b/src/PenCore/Tray3.ico
Binary files differ
diff --git a/src/PenCore/Tray4.ico b/src/PenCore/Tray4.ico
new file mode 100644
index 00000000..6e8984b4
--- /dev/null
+++ b/src/PenCore/Tray4.ico
Binary files differ
diff --git a/src/PenCore/Tsukuba.bmp b/src/PenCore/Tsukuba.bmp
new file mode 100644
index 00000000..866cb151
--- /dev/null
+++ b/src/PenCore/Tsukuba.bmp
Binary files differ
diff --git a/src/PenCore/UnivTsukuba.bmp b/src/PenCore/UnivTsukuba.bmp
new file mode 100644
index 00000000..6977dc50
--- /dev/null
+++ b/src/PenCore/UnivTsukuba.bmp
Binary files differ
diff --git a/src/PenCore/Update.bmp b/src/PenCore/Update.bmp
new file mode 100644
index 00000000..a3be31b9
--- /dev/null
+++ b/src/PenCore/Update.bmp
Binary files differ
diff --git a/src/PenCore/User.ico b/src/PenCore/User.ico
new file mode 100644
index 00000000..596b225c
--- /dev/null
+++ b/src/PenCore/User.ico
Binary files differ
diff --git a/src/PenCore/UserAdmin.ico b/src/PenCore/UserAdmin.ico
new file mode 100644
index 00000000..8d2125fd
--- /dev/null
+++ b/src/PenCore/UserAdmin.ico
Binary files differ
diff --git a/src/PenCore/UserDeny.ico b/src/PenCore/UserDeny.ico
new file mode 100644
index 00000000..cd2e0543
--- /dev/null
+++ b/src/PenCore/UserDeny.ico
Binary files differ
diff --git a/src/PenCore/VLan.ico b/src/PenCore/VLan.ico
new file mode 100644
index 00000000..95194765
--- /dev/null
+++ b/src/PenCore/VLan.ico
Binary files differ
diff --git a/src/PenCore/VMBridge.bmp b/src/PenCore/VMBridge.bmp
new file mode 100644
index 00000000..819beffd
--- /dev/null
+++ b/src/PenCore/VMBridge.bmp
Binary files differ
diff --git a/src/PenCore/VPN.ico b/src/PenCore/VPN.ico
new file mode 100644
index 00000000..b366131e
--- /dev/null
+++ b/src/PenCore/VPN.ico
Binary files differ
diff --git a/src/PenCore/VPNGateBanner.bmp b/src/PenCore/VPNGateBanner.bmp
new file mode 100644
index 00000000..b72619c0
--- /dev/null
+++ b/src/PenCore/VPNGateBanner.bmp
Binary files differ
diff --git a/src/PenCore/VPNGateEN.bmp b/src/PenCore/VPNGateEN.bmp
new file mode 100644
index 00000000..a2ce6134
--- /dev/null
+++ b/src/PenCore/VPNGateEN.bmp
Binary files differ
diff --git a/src/PenCore/VPNGateJA.bmp b/src/PenCore/VPNGateJA.bmp
new file mode 100644
index 00000000..123ce1ac
--- /dev/null
+++ b/src/PenCore/VPNGateJA.bmp
Binary files differ
diff --git a/src/PenCore/VPNServerFigure.bmp b/src/PenCore/VPNServerFigure.bmp
new file mode 100644
index 00000000..7fe53d26
--- /dev/null
+++ b/src/PenCore/VPNServerFigure.bmp
Binary files differ
diff --git a/src/PenCore/VPNSvr.ico b/src/PenCore/VPNSvr.ico
new file mode 100644
index 00000000..9585574a
--- /dev/null
+++ b/src/PenCore/VPNSvr.ico
Binary files differ
diff --git a/src/PenCore/Warning.ico b/src/PenCore/Warning.ico
new file mode 100644
index 00000000..067b22bf
--- /dev/null
+++ b/src/PenCore/Warning.ico
Binary files differ
diff --git a/src/PenCore/WinPC.bmp b/src/PenCore/WinPC.bmp
new file mode 100644
index 00000000..9a11ec61
--- /dev/null
+++ b/src/PenCore/WinPC.bmp
Binary files differ
diff --git a/src/PenCore/X.ico b/src/PenCore/X.ico
new file mode 100644
index 00000000..1cecee79
--- /dev/null
+++ b/src/PenCore/X.ico
Binary files differ
diff --git a/src/PenCore/ZuruHam.ico b/src/PenCore/ZuruHam.ico
new file mode 100644
index 00000000..22cd5b03
--- /dev/null
+++ b/src/PenCore/ZuruHam.ico
Binary files differ
diff --git a/src/PenCore/Zurukko.bmp b/src/PenCore/Zurukko.bmp
new file mode 100644
index 00000000..4cabe31a
--- /dev/null
+++ b/src/PenCore/Zurukko.bmp
Binary files differ
diff --git a/src/PenCore/Zurukko.ico b/src/PenCore/Zurukko.ico
new file mode 100644
index 00000000..a7d62316
--- /dev/null
+++ b/src/PenCore/Zurukko.ico
Binary files differ
diff --git a/src/PenCore/resource.h b/src/PenCore/resource.h
new file mode 100644
index 00000000..040eff0d
--- /dev/null
+++ b/src/PenCore/resource.h
@@ -0,0 +1,1204 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PenCore.rc
+//
+#define IDOK3 2
+#define B_POLICY 3
+#define B_SAVE 3
+#define B_ABOUT 3
+#define B_OFFLINE 3
+#define IDOK2 3
+#define IDCANCEL3 3
+#define B_WEB 3
+#define B_SIMULATION 3
+#define B_RESTORE 3
+#define B_MESSAGE 3
+#define B_HUB_STATUS 4
+#define IDCANCEL2 4
+#define B_SECURE_MANAGER 4
+#define B_REDIRECT 4
+#define B_EULA 4
+#define DLG_SECURE 5
+#define D_SECURE 5
+#define B_CLIENT_CERT 5
+#define B_CREATE 5
+#define B_SELECT_SECURE 5
+#define B_IMPORTANT 5
+#define B_CREATE_LISTENER 6
+#define B_CERT_TOOL 6
+#define B_LEGAL 6
+#define B_DELETE_LISTENER 7
+#define B_LEGAL2 7
+#define B_UPDATE_CONFIG 7
+#define B_START 8
+#define B_LEGAL3 8
+#define B_LANGUAGE 8
+#define B_STOP 9
+#define B_EDIT 10
+#define S_STATUSBAR 101
+#define ICO_TEST 103
+#define BMP_TEST 104
+#define ICO_KEY 105
+#define BMP_SECURE 106
+#define BMP_SECURE2 107
+#define AVI_PROGRESS 108
+#define ICO_CERT 109
+#define D_PKCSUTIL 110
+#define D_PASSPHRASE 111
+#define D_DEFAULT 112
+#define D_SPEEDMETER 112
+#define D_PASSWORD 113
+#define ICO_SERVER_ONLINE 113
+#define D_STATUS 114
+#define D_CERT 115
+#define D_CHECKCERT 116
+#define ICO_WARNING 117
+#define D_CONNECTERROR 117
+#define ICO_NULL 118
+#define D_CM_LOGIN 118
+#define D_CM_MAIN 119
+#define ICO_TOWER 119
+#define ICO_VPN 120
+#define D_CONNECTION_STATUS 120
+#define ICO_VPNSERVER 121
+#define D_CM_POLICY 121
+#define D_CM_ACCOUNT 122
+#define ICO_NIC_ONLINE 123
+#define D_CM_PROXY 123
+#define ICO_SETUP 124
+#define D_CM_DETAIL 124
+#define ICO_MACHINE 125
+#define D_CM_NEW_VLAN 125
+#define D_CM_TRUST 126
+#define D_CM_PASSWORD 127
+#define ICO_HUB 128
+#define D_CM_CONFIG 128
+#define ICO_VLAN 129
+#define D_ABOUT 129
+#define ICO_SERVER_OFFLINE 130
+#define M_MAIN 130
+#define D_REMOTE 130
+#define ICO_NIC_OFFLINE 131
+#define D_CM_DESKTOP 131
+#define D_CM_CHANGE_PASSWORD 132
+#define ICO_INFORMATION 133
+#define D_SM_MAIN 133
+#define ICO_STOP 134
+#define D_SM_EDIT_SETTING 134
+#define ICO_SERVER_DELETE 135
+#define D_SM_SERVER 135
+#define ICO_SERVER_ONLINE_EX 136
+#define D_SM_STATUS 136
+#define ICO_SERVER_OFFLINE_EX 137
+#define D_SM_EDIT_HUB 137
+#define ICO_INTERNET 138
+#define D_SM_CREATE_LISTENER 138
+#define ICO_DISPLAY 139
+#define D_SM_SSL 139
+#define D_SM_SAVE_KEY_PAIR 140
+#define BMP_MANAGER_LOGO 141
+#define D_SM_CONNECTION 141
+#define D_SM_FARM 142
+#define ICO_GROUP 143
+#define D_SM_FARM_MEMBER 143
+#define ICO_USER 144
+#define D_SM_CHANGE_PASSWORD 144
+#define ICO_USER_ADMIN 145
+#define D_SM_HUB 145
+#define ICO_HUB_OFFLINE 146
+#define D_SM_USER 146
+#define ICO_FARM 147
+#define D_SM_EDIT_USER 147
+#define D_SM_POLICY 148
+#define D_SM_GROUP 149
+#define ICO_X 150
+#define D_SM_EDIT_GROUP 150
+#define ICO_PROTOCOL 151
+#define D_SM_ACCESS_LIST 151
+#define ICO_PROTOCOL_X 152
+#define D_SM_EDIT_ACCESS 152
+#define ICO_DISCARD 153
+#define D_SM_RADIUS 153
+#define ICO_PASS 154
+#define D_SM_LINK 154
+#define ICO_PROTOCOL_OFFLINE 155
+#define D_SM_LOG 155
+#define ICO_MEMORY 156
+#define D_SM_CA 156
+#define ICO_PKCS12 157
+#define D_SM_SESSION 157
+#define ICO_SERVER_CERT 158
+#define D_SM_MAC 158
+#define D_SM_IP 159
+#define ICO_LINK 160
+#define D_SM_CREATE_CERT 160
+#define ICO_PENGUIN 161
+#define D_NM_LOGIN 161
+#define ICO_LINK2 162
+#define ICO_CASCADE 163
+#define ICO_USER1 164
+#define ICO_USER_DENY 164
+#define ICO_GROUP_DENY 165
+#define ICO_LOG 166
+#define ICO_LOG2 167
+#define ICO_DATETIME 168
+#define ICO_NEW 169
+#define ICO_PASS_DISABLE 170
+#define ICO_DISCARD_DISABLE 171
+#define ICO_CASCADE_ERROR 172
+#define ICO_CASCADE_OFFLINE 173
+#define ICO_PROTOCOL_DHCP 174
+#define ICO_ROUTER 175
+#define BMP_ROUTER_BANNER 176
+#define BMP_ROUTER_LOGO 178
+#define BMP_COINS 179
+#define ICO_BRIDGE 180
+#define BIN_WINPCAP 181
+#define ICO_SWITCH 182
+#define ICO_SWITCH_OFFLINE 183
+#define ICO_SECURE 184
+#define ICO_CERT_X 185
+#define ICO_INTERNET_X 186
+#define ICO_LICENSE 187
+#define ICO_SESSION_BRIDGE 188
+#define BMP_SECURE3 188
+#define ICO_VPN1 189
+#define ICO_SESSION_MONITOR 189
+#define ICO_TRAY1 190
+#define BMP_CLIENT_BANNER 190
+#define ICO_TRAY2 191
+#define BMP_SETUP_2 191
+#define ICO_TRAY3 192
+#define BMP_SETUP_1 192
+#define ICO_TRAY4 193
+#define BMP_TSUKUBA 193
+#define ICO_VPN2 194
+#define ICO_TRAY0 194
+#define IDR_MENU1 194
+#define M_VOICE_BACKUP 194
+#define BMP_ETHERIP 195
+#define BMP_L2TP 197
+#define ICO_IPSEC 201
+#define BMP_IX2015 202
+#define ICO_DDNS 203
+#define ICO_OPENVPN 204
+#define BMP_OPENVPN 205
+#define BMP_SSTP 206
+#define ICO_SPECIALLISTENER 207
+#define BMP_SPECIALLISTENER 208
+#define ICO_INSTALLER 209
+#define BMP_SELOGO49x49 211
+#define ICO_LANGUAGE 215
+#define BMP_SW_LANG_1 216
+#define BMP_SW_LANG_2 217
+#define BMP_SW_LANG_3 218
+#define ICO_LANG_CHINESE 219
+#define ICO_LANG_ENGLISH 220
+#define ICO_LANG_JAPANESE 221
+#define ICO_EASYINSTALLER 222
+#define BMP_VPNSERVER_FIGURE 223
+#define BMP_ABOUTBOX 224
+#define BMP_UPDATE 225
+#define BMP_IBARAKI 226
+#define IDB_BITMAP1 227
+#define BMP_WINPC 227
+#define BMP_VMBRIDGE 228
+#define BMP_AZURE 229
+#define BMP_AZURE_JA 230
+#define ICO_AZURE 231
+#define IDB_BITMAP2 232
+#define BMP_AZURE_CN 232
+#define ICO_ZURUHAM 233
+#define IDI_ICON2 234
+#define ICO_ZURUKKO 234
+#define BMP_VPNGATEBANNER 235
+#define BMP_ZURUKKO 236
+#define BMP_VPNGATEEN 237
+#define BMP_VPNGATEJA 238
+#define ICO_RESEARCH 239
+#define BMP_UNIVTSUKUBA 240
+#define ICO_POLICE 241
+#define S_TITLE 1007
+#define S_INSERT_SECURE 1008
+#define S_TITLE2 1008
+#define S_STATIC 1008
+#define S_RESEARCH 1008
+#define S_DEVICE_INFO 1009
+#define E_PIN 1010
+#define IDS_STATIC1 1012
+#define S_WARNING 1013
+#define A_PROGRESS 1014
+#define S_MSG_1 1014
+#define S_WARNING2 1014
+#define S_STATUS 1015
+#define S_MSG_2 1015
+#define S_PIN_CODE 1016
+#define S_MSG_3 1016
+#define S_STATUS3 1016
+#define S_SOFTWARE_TITLE 1017
+#define S_STATUS4 1017
+#define B_WRITE 1018
+#define S_STATUS6 1018
+#define B_ERASE 1019
+#define S_STATUS5 1019
+#define S_COPYRIGHT 1020
+#define S_SUFFIX 1020
+#define E_PASSPHRASE 1021
+#define S_STATUS7 1021
+#define E_USERNAME 1023
+#define C_TYPE 1024
+#define E_HUBNAME 1024
+#define E_REALNAME 1024
+#define P_PROGRESS 1025
+#define E_NOTE 1025
+#define E_NICNAME 1025
+#define E_GROUP 1026
+#define E_PRIORITY 1026
+#define E_PASSWORD 1027
+#define E_CN 1027
+#define E_SRC_IP_V6 1027
+#define S_COUNTDOWN 1028
+#define E_PASSWORD2 1028
+#define E_SRC_PORT_1 1028
+#define E_O 1028
+#define S_RETRYINFO 1029
+#define E_RADIUS_USERNAME 1029
+#define E_SRC_PORT_2 1029
+#define E_OU 1029
+#define E_SUBJECT 1030
+#define E_DST_PORT_1 1030
+#define E_C 1030
+#define E_ISSUER 1031
+#define E_DST_PORT_2 1031
+#define E_ST 1031
+#define E_EXPIRES 1032
+#define E_L 1032
+#define E_SRC_PORT_3 1032
+#define E_IP_PROTO 1032
+#define L_CERTINFO 1033
+#define E_MD5 1033
+#define E_EXPIRES_TIME 1033
+#define E_EXPIRE 1033
+#define E_SERI 1033
+#define E_DST_MAC 1033
+#define S_PARENT 1034
+#define E_DOMAIN 1034
+#define E_MD5_HASH 1034
+#define E_SRC_MAC 1034
+#define B_PARENT 1035
+#define E_SHA1 1035
+#define E_SHA1_HASH 1035
+#define E_SRC_MAC_MASK 1035
+#define E_DST_MAC_MASK 1036
+#define S_WARNING_ICON 1037
+#define E_SRC_MASK_V6 1037
+#define S_CERT_ICON 1038
+#define E_DST_IP_V6 1038
+#define S_PARENT_BUTTON_STR 1039
+#define E_DST_MASK_V6 1039
+#define E_DETAIL 1040
+#define B_SHOW 1041
+#define S_MSG1 1043
+#define E_ERROR 1044
+#define L_ACCOUNT 1047
+#define L_VLAN 1048
+#define L_STATUS 1048
+#define S_DESCRIPTION 1051
+#define L_POLICY 1052
+#define E_ACCOUNT_NAME 1053
+#define E_HOSTNAME 1054
+#define E_RETRY_NUM 1055
+#define E_SECRET1 1055
+#define E_SECRET2 1056
+#define R_DIRECT_TCP 1057
+#define R_HTTPS 1059
+#define R_SOCKS 1060
+#define S_USERNAME 1062
+#define E_RETRY_SPAN 1065
+#define C_HUBNAME 1066
+#define S_PASSWORD 1067
+#define S_CERT 1068
+#define S_CONTROLLER_PORT 1068
+#define B_REGIST_CLIENT_CERT 1069
+#define S_CERT_INFO 1070
+#define R_RETRY 1071
+#define R_INFINITE 1072
+#define R_USE_ENCRYPT 1072
+#define B_DETAIL 1073
+#define R_USE_COMPRESS 1073
+#define R_CHECK_CERT 1074
+#define R_USE_COMPRESS2 1074
+#define R_DISABLE_UDP 1074
+#define B_CONFIG_L2 1074
+#define B_VIEW_CLIENT_CERT 1075
+#define C_NUM_TCP 1075
+#define B_TRUST 1076
+#define E_INTERVAL 1076
+#define B_PROXY_CONFIG 1077
+#define B_SERVER_CERT 1078
+#define B_VIEW_SERVER_CERT 1079
+#define R_USE_HALF_CONNECTION 1080
+#define C_PORT 1080
+#define S_STATIC13 1080
+#define R_USE_DISCONNECT 1081
+#define S_RETRY_NUM_1 1081
+#define S_RETRY_NUM_2 1082
+#define S_RETRY_SPAN_1 1083
+#define E_DISCONNECT_SPAN 1083
+#define S_RETRY_SPAN_2 1084
+#define R_NO_ROUTING 1084
+#define E_NAME 1085
+#define B_CHANGE_PASSWORD 1085
+#define L_CERT 1086
+#define S_CHANGE_PASSWORD 1086
+#define B_IMPORT 1087
+#define B_PROXY_CONFIG2 1087
+#define B_IE 1087
+#define B_EXPORT 1088
+#define IDC_STATIC1 1088
+#define R_R_NOTLS1 1088
+#define R_NOTLS1 1088
+#define R_USE_PASSWORD 1089
+#define IDC_STATIC3 1089
+#define B_IMPORT2 1089
+#define B_REGENERATE 1089
+#define B_FACTORY 1089
+#define R_REMOTE_ONLY 1090
+#define IDC_STATIC4 1090
+#define B_DELETE 1091
+#define IDC_STATIC2 1091
+#define R_ALLOW_REMOTE_CONFIG 1092
+#define B_REFRESH 1092
+#define IDC_STATIC5 1092
+#define B_DELETE2 1092
+#define B_ETH_VLAN 1092
+#define B_VLAN 1092
+#define R_USE_KEEP_CONNECT 1093
+#define B_CERT 1093
+#define IDC_STATIC6 1093
+#define B_SESSION_IP_TABLE 1093
+#define B_NEW_CERT 1093
+#define B_RENAME 1093
+#define S_HOSTNAME 1094
+#define B_REFRESH2 1094
+#define B_BRIDGE 1094
+#define B_PIN 1094
+#define R_ALPHA 1095
+#define B_SESSION_MAC_TABLE 1095
+#define B_PASSWORD2 1095
+#define B_L3 1095
+#define R_TCP 1096
+#define B_MAC_TABLE 1096
+#define B_IPSEC 1096
+#define S_INFO 1097
+#define B_OPENVPN 1097
+#define B_DEFAULT 1097
+#define S_PORT 1098
+#define B_BRIDGE2 1098
+#define B_DDNS 1098
+#define S_INFO7 1098
+#define E_PORT 1099
+#define B_AZURE 1099
+#define S_INFO8 1099
+#define S_INTERVAL 1100
+#define E_CONTROLLER 1100
+#define B_IP_TABLE 1100
+#define E_PORT2 1100
+#define E_RADIUS_RETRY_INTERVAL 1100
+#define S_INFO6 1100
+#define B_VPNGATE 1100
+#define S_INFO2 1101
+#define S_INTERVAL2 1102
+#define R_LOCAL 1102
+#define S_PROTOCOL 1103
+#define C_HOSTNAME 1103
+#define R_UDP 1104
+#define S_ICON 1104
+#define E_ALPHA_VALUE 1105
+#define S_INFO4 1105
+#define S_ICON2 1105
+#define S_INFO3 1106
+#define E_OLD_PASSWORD 1106
+#define E_NEW_PASSWORD1 1107
+#define S_INFO5 1107
+#define E_NEW_PASSWORD2 1108
+#define L_SETTING 1109
+#define B_NEW_SETTING 1110
+#define B_EDIT_SETTING 1111
+#define R_SERVER_ADMIN 1111
+#define B_DELETE_SETTING 1112
+#define R_NO_SAVE 1112
+#define B_MODE 1112
+#define R_HUB_ADMIN 1113
+#define B_MODE2 1113
+#define B_VGC 1113
+#define S_HUBNAME 1114
+#define E_MAX_SESSION 1115
+#define R_LOCALHOST 1116
+#define L_HUB 1118
+#define L_LISTENER 1120
+#define B_SSL 1121
+#define B_STATUS 1123
+#define E_PASSWORD1 1123
+#define B_INFO 1124
+#define R_LIMIT_MAX_SESSION 1124
+#define B_FARM 1125
+#define S_MAX_SESSION_1 1125
+#define B_INFO2 1125
+#define S_MAX_SESSION_2 1126
+#define B_CONNECTION 1126
+#define R_ONLINE 1127
+#define B_FARM_STATUS 1127
+#define R_OFFLINE 1128
+#define S_BOLD 1129
+#define S_FARM_INFO 1130
+#define S_BOLD2 1130
+#define R_STATIC 1131
+#define R_DYNAMIC 1132
+#define C_CIPHER 1132
+#define S_AO_3 1133
+#define S_ACL 1134
+#define B_VIEW 1136
+#define R_PKCS12 1136
+#define R_USE_PASS 1137
+#define E_PASS1 1138
+#define E_PASS2 1139
+#define R_X509_AND_KEY 1140
+#define S_PASS1 1141
+#define S_PASS2 1142
+#define B_DISCONNECT 1143
+#define R_SECURE 1143
+#define L_LIST 1144
+#define S_CURRENT 1145
+#define L_KEY 1145
+#define R_STANDALONE 1146
+#define R_CONTROLLER 1147
+#define R_MEMBER 1148
+#define S_PORT_2 1151
+#define S_PORT_1 1152
+#define S_IP_1 1153
+#define E_IP 1154
+#define S_SRC_MAC_ALL 1154
+#define S_CHECK_SRC_MAC 1154
+#define S_IP_2 1155
+#define E_SRC_MASK 1155
+#define E_MASK 1155
+#define S_CONTROLLER 1156
+#define E_DST_IP 1156
+#define E_DHCP_START 1156
+#define E_CONTROLLER_PORT 1157
+#define E_DST_MASK 1157
+#define E_DHCP_END 1157
+#define S_PORT_3 1158
+#define E_DHCP_MASK 1158
+#define L_FARM_MEMBER 1159
+#define E_GATEWAY 1159
+#define B_USER 1160
+#define E_DNS 1160
+#define B_GROUP 1161
+#define B_CASCADE 1161
+#define E_DNS2 1161
+#define S_USER 1162
+#define B_USER2 1162
+#define S_GROUP 1163
+#define B_SECURENAT 1163
+#define B_ACCESS 1164
+#define S_LINK 1165
+#define S_RADIUS 1166
+#define L_USER 1167
+#define S_RADIUS2 1167
+#define S_CA 1167
+#define B_PROPERTY 1168
+#define B_RADIUS 1169
+#define B_LINK 1170
+#define S_PASSWORD_2 1170
+#define B_SESSION 1171
+#define S_PASSWORD_3 1171
+#define B_LOG 1172
+#define B_LOAD_CERT 1172
+#define B_RADIUS2 1173
+#define B_VIEW_CERT 1173
+#define B_CA 1173
+#define R_CN 1174
+#define B_SNAT 1174
+#define R_SERIAL 1175
+#define S_SNAT 1175
+#define R_O 1175
+#define R_SET_RADIUS_USERNAME 1176
+#define B_CRL 1176
+#define R_OU 1176
+#define S_RADIUS_2 1177
+#define R_C 1177
+#define B_LOG_FILE 1177
+#define R_POLICY 1178
+#define S_RADIUS_4 1178
+#define R_ST 1178
+#define S_RADIUS_5 1179
+#define R_L 1179
+#define R_EXPIRES 1180
+#define R_SERI 1180
+#define S_RADIUS_7 1180
+#define R_MD5_HASH 1181
+#define S_RADIUS_9 1181
+#define R_SHA1_HASH 1182
+#define L_AUTH 1183
+#define S_RADIUS_8 1183
+#define S_RADIUS_1 1184
+#define S_RADIUS_3 1185
+#define S_POLICY_1 1186
+#define S_PASSWORD_1 1187
+#define S_POLICY_2 1187
+#define S_ROOT_CERT_1 1188
+#define S_ROOT_CERT_2 1189
+#define S_ROOT_CERT_3 1190
+#define S_USER_CERT_1 1191
+#define S_RADIUS_10 1192
+#define S_HINT 1192
+#define E_EXPIRES_DATE 1193
+#define S_POLICY_TITLE 1194
+#define E_POLICY_DESCRIPTION 1195
+#define R_ENABLE 1196
+#define R_DISABLE 1197
+#define R_DEFINE 1198
+#define E_VALUE 1199
+#define S_TANI 1200
+#define S_LIMIT 1201
+#define L_GROUP 1202
+#define E_GROUPNAME 1203
+#define B_ADD 1205
+#define L_ACCESS_LIST 1206
+#define B_DEL_IF 1206
+#define B_ADD_TABLE 1207
+#define B_ADD_V6 1207
+#define R_PASS 1208
+#define B_DEL_TABLE 1208
+#define B_DEL 1208
+#define R_DISCARD 1209
+#define R_DENY 1209
+#define R_SRC_ALL 1210
+#define B_OBTAIN 1210
+#define R_IPV4 1210
+#define R_DST_ALL 1211
+#define R_IPV6 1211
+#define C_PROTOCOL 1212
+#define E_USERNAME1 1213
+#define E_USERNAME2 1214
+#define S_SRC_IP_1 1215
+#define S_SRC_IP_2 1216
+#define S_SRC_IP_3 1217
+#define E_SRC_IP 1218
+#define S_SRC_IP_4 1218
+#define S_IP_DST_1 1219
+#define S_IP_DST_2 1220
+#define S_IP_DST_3 1221
+#define S_TCP_1 1222
+#define S_TCP_2 1223
+#define S_TCP_3 1224
+#define S_TCP_4 1225
+#define S_TCP_5 1226
+#define S_TCP_6 1227
+#define S_TCP_7 1228
+#define B_USER1 1229
+#define S_SRC_MAC 1230
+#define R_USE_RADIUS 1231
+#define R_SRC_MAC_ALL 1231
+#define R_CHECK_SRC_MAC 1231
+#define S_DST_MAC 1232
+#define S_RADIUS3 1233
+#define R_DST_MAC_ALL 1233
+#define R_CHECK_DST_MAC 1233
+#define S_RADIUS_6 1234
+#define S_SRC_MAC_MASK 1234
+#define S_LOG 1235
+#define S_DST_MAC_MASK 1235
+#define S_MAC_NOTE 1236
+#define L_LINK 1237
+#define E_SERIAL 1238
+#define S_VLAN_GROUP 1238
+#define B_SEC 1240
+#define S_SEC 1241
+#define C_SEC_SWITCH 1242
+#define B_PACKET 1243
+#define S_PACKET 1244
+#define C_PACKET_SWITCH 1245
+#define S_PACKET_0 1246
+#define S_PACKET_1 1247
+#define B_PACKET_0_0 1248
+#define B_PACKET_1_0 1249
+#define S_FARM_INFO_1 1249
+#define B_PACKET_0_1 1250
+#define S_FARM_INFO_2 1250
+#define B_PACKET_1_1 1251
+#define L_TABLE 1251
+#define B_PACKET_0_2 1252
+#define R_ROOT_CERT 1252
+#define B_PACKET_1_2 1253
+#define R_SIGNED_CERT 1253
+#define S_PACKET_2 1254
+#define B_LOAD 1254
+#define B_PACKET_2_0 1255
+#define S_LOAD_1 1255
+#define B_PACKET_2_1 1256
+#define S_LOAD_2 1256
+#define B_PACKET_2_2 1257
+#define S_LOAD_3 1257
+#define S_LOAD_4 1258
+#define S_LOAD_5 1259
+#define S_STATIC_S 1259
+#define S_ACCESS 1259
+#define S_LOAD_6 1260
+#define S_VERSION 1260
+#define S_LOAD_7 1261
+#define S_LOGO 1261
+#define S_PACKET_3 1262
+#define S_LOAD_8 1262
+#define S_VERSION2 1262
+#define B_PACKET_3_0 1263
+#define S_LOAD_9 1263
+#define S_BUILD 1263
+#define B_PACKET_3_1 1264
+#define S_LOAD_10 1264
+#define B_PACKET_3_2 1265
+#define S_LOAD_11 1265
+#define B_SETTING 1265
+#define S_PACKET_4 1266
+#define B_CONNECT 1266
+#define S_ACCOUNT_NAME 1266
+#define S_LOAD_12 1266
+#define B_PACKET_4_0 1267
+#define S_ROUTER_LOGO 1267
+#define S_LOAD_13 1267
+#define B_PACKET_4_1 1268
+#define B_OPTION 1268
+#define E_MAC 1268
+#define B_PACKET_4_2 1269
+#define B_NAT 1269
+#define R_USE_NAT 1269
+#define S_PACKET_5 1270
+#define E_MTU 1270
+#define B_PACKET_5_0 1271
+#define B_DHCP 1271
+#define E_TCP 1271
+#define B_PACKET_5_1 1272
+#define E_UDP 1272
+#define B_PACKET_5_2 1273
+#define R_USE_DHCP 1273
+#define S_PACKET_6 1274
+#define R_SAVE_LOG 1274
+#define B_PACKET_6_0 1275
+#define R_HIDE 1275
+#define B_PACKET_6_1 1276
+#define S_PROPERTY 1276
+#define R_HIDE2 1276
+#define B_PACKET_6_2 1277
+#define B_ENABLE 1277
+#define S_PACKET_7 1278
+#define B_DISABLE 1278
+#define B_PACKET_7_0 1279
+#define B_CONFIG 1279
+#define B_CLONE 1279
+#define B_DISABLE2 1279
+#define B_PROXY 1279
+#define B_PACKET_7_1 1280
+#define S_TSUKUBA1 1280
+#define B_LICENSE 1280
+#define B_PACKET_7_2 1281
+#define S_TSUKUBA2 1281
+#define IDC_CHECK1 1285
+#define R_NO_SAVE_PASSWORD 1285
+#define R_PROMISCUS 1285
+#define R_NO_ENUM 1285
+#define R_ETHERNET 1285
+#define R_CONTROLLER_ONLY 1285
+#define B_HIDE 1285
+#define R_DISABLE_QOS 1285
+#define R_LOCK 1285
+#define C_REMOTE 1285
+#define C_DONTSHOWAGAIN 1285
+#define R_CHECK_TCP_STATE 1285
+#define C_DELAY 1285
+#define C_USEMSG 1285
+#define R_L2TP_OVER_IPSEC 1285
+#define B_AGREE 1285
+#define R_SHOWCUSTOM 1285
+#define B_RUN 1285
+#define B_DELETE_SENSITIVE 1285
+#define R_LOG 1285
+#define R_DOUBLE 1286
+#define C_SITE 1286
+#define C_JITTER 1286
+#define R_REDIRECT 1286
+#define R_L2TP 1286
+#define E_LIST 1287
+#define C_OTHER 1287
+#define C_LOSS 1287
+#define R_L2TP_RAW 1287
+#define B_EASYMODE 1287
+#define R_ETHERIP 1288
+#define R_BRIDGE 1289
+#define R_TAP 1290
+#define R_MONITOR 1290
+#define E_TAPNAME 1291
+#define S_ETH_1 1292
+#define S_TAP_1 1293
+#define S_TAP_2 1294
+#define S_VHUB_BRIDGE 1295
+#define C_DEVICE 1296
+#define IDC_INFO 1297
+#define E_CONFIG 1298
+#define B_ADMINOPTION 1300
+#define S_AO_1 1301
+#define S_AO_2 1302
+#define S_ACL_3 1303
+#define S_ACL_2 1304
+#define B_ACL 1305
+#define B_ACL2 1306
+#define B_EXTOPTION 1306
+#define S_AO_4 1307
+#define B_MSG 1308
+#define C_NAME 1309
+#define S_ACL_5 1310
+#define L_IF 1311
+#define S_BOLD1 1313
+#define B_ADD_IF 1314
+#define E_NETWORK 1315
+#define E_METRIC 1316
+#define B_BOLD 1317
+#define R_CERT 1319
+#define R_KEY 1320
+#define E_STRING 1320
+#define R_DATA 1321
+#define B_BOLD1 1321
+#define B_BOLD2 1322
+#define R_FROM_FILE 1322
+#define R_FROM_SECURE 1323
+#define B_SELECT 1324
+#define S_FILE 1325
+#define S_PASS3 1326
+#define S_PASS4 1327
+#define E_PIN1 1328
+#define E_PIN2 1329
+#define E_PIN3 1330
+#define R_SINGLE 1331
+#define R_MASKED 1332
+#define S_MASK 1333
+#define S_MODE 1336
+#define B_PASSWORD 1339
+#define R_RECV_DISABLE 1340
+#define B_PASSWORD3 1340
+#define B_SPECIALLISTENER 1340
+#define R_RECV_ENABLE 1341
+#define E_RECV 1342
+#define S_RECV 1343
+#define B_RECV 1344
+#define R_SEND_DISABLE 1345
+#define R_SEND_ENABLE 1346
+#define E_SEND 1347
+#define R_OPTIMIZE 1347
+#define S_SEND 1348
+#define R_MANUAL 1348
+#define B_SEND 1349
+#define R_NO 1349
+#define S_IMAGE 1351
+#define S_IMAGE2 1352
+#define S_INFO_1 1352
+#define S_INFO_2 1353
+#define S_IMAGE3 1353
+#define S_IMAGE_TSUKUBA 1353
+#define S_INFO_3 1354
+#define S_INFO_4 1355
+#define S_PROTOID 1356
+#define S_1 1359
+#define S_18 1360
+#define S_3 1361
+#define R_SERVER 1362
+#define S_19 1362
+#define R_CLIENT 1363
+#define S_20 1363
+#define S_4 1364
+#define S_21 1364
+#define S_5 1365
+#define S_23 1365
+#define C_HOST 1366
+#define S_22 1366
+#define S_6 1367
+#define S_25 1367
+#define S_8 1368
+#define S_9 1369
+#define S_7 1370
+#define R_DOWNLOAD 1371
+#define R_UPLOAD 1372
+#define R_FULL 1373
+#define S_10 1374
+#define S_11 1375
+#define C_NUM 1376
+#define S_12 1377
+#define E_SPAN 1378
+#define S_13 1379
+#define E_EDIT 1379
+#define S_14 1380
+#define IDC_EDIT1 1380
+#define E_WEIGHT 1380
+#define B_KEY1 1380
+#define E_SYSLOG_HOSTNAME 1380
+#define E_TEXT 1380
+#define E_DELAY 1380
+#define E_IPV6 1380
+#define E_SECRET 1380
+#define E_ID 1380
+#define E_DDNS_HOST 1380
+#define E_SAMPLE1 1380
+#define E_CURRENT 1380
+#define E_OWNER 1380
+#define S_15 1381
+#define S_2 1381
+#define E_SYSLOG_PORT 1381
+#define E_JITTER 1381
+#define E_IPV7 1381
+#define E_MASKV6 1381
+#define E_SAMPLE2 1381
+#define E_DDNS_HOST2 1381
+#define E_AZURE_HOST 1381
+#define E_LOSS 1382
+#define S_16 1382
+#define E_URL 1382
+#define E_ABUSE 1382
+#define S_17 1383
+#define E_MSG 1383
+#define S_24 1384
+#define ABOUT 1387
+#define C_SYSLOG 1388
+#define B_KEY2 1389
+#define S_01 1389
+#define B_KEY3 1390
+#define S_02 1390
+#define B_KEY4 1391
+#define R_EASY 1391
+#define B_KEY5 1392
+#define R_NORMAL 1392
+#define B_KEY6 1393
+#define S_PASSWORD1 1393
+#define S_PASSWORD2 1394
+#define S_PASSWORD3 1395
+#define S_STATIC3 1397
+#define S_STATIC4 1398
+#define S_STATIC5 1399
+#define S_STATIC7 1400
+#define S_STATIC66 1401
+#define S_STATIC2 1402
+#define S_STATIC11 1403
+#define S_STATIC1 1404
+#define S_STATIC6 1405
+#define S_STATIC8 1406
+#define S_STATIC9 1407
+#define S_STATIC10 1408
+#define S_STATIC12 1409
+#define S_STATIC19 1410
+#define S_STATIC133 1411
+#define S_REMOTE_1 1413
+#define S_SITE_1 1414
+#define S_SITE_2 1415
+#define C_CENTER 1416
+#define C_EDGE 1417
+#define S_OTHER 1418
+#define S_1_1 1421
+#define S_1_2 1422
+#define S_2_1 1423
+#define S_2_2 1424
+#define S_3_1 1425
+#define S_3_2 1426
+#define IDC_COMBO1 1427
+#define C_BITS 1427
+#define R_NEVER 1427
+#define IDC_BUTTON1 1428
+#define BMP_UT 1428
+#define S_LICENSE 1429
+#define IDC_BUTTON2 1429
+#define S_BETA 1430
+#define IDC_BUTTON3 1430
+#define S_DST_MAC_ALL 1431
+#define S_CHECK_DST_MAC 1431
+#define IDC_BUTTON4 1431
+#define S_ACCESS_DST_ALL 1432
+#define S_ACCESS_SRC_ALL 1433
+#define IDC_RADIO1 1434
+#define R_ESTABLISHED 1434
+#define R_SYSTEM 1434
+#define R_DEFAULT 1434
+#define S_ENABLE 1434
+#define R_2WEEKS 1434
+#define IDC_RADIO2 1435
+#define R_UNESTABLISHED 1435
+#define R_USER 1435
+#define R_CUSTOM 1435
+#define S_DISBLE 1435
+#define R_PERMANENT 1435
+#define R_FOR_SYSTEM 1436
+#define IDC_NETADDRESS1 1437
+#define R_FOR_USER 1437
+#define IDC_PROGRESS1 1438
+#define E_HELP 1440
+#define S_DELAY 1441
+#define S_DELAY2 1442
+#define S_JITTER 1443
+#define S_JITTER2 1444
+#define S_LOSS 1445
+#define S_LOSS2 1446
+#define S_STATIC14 1448
+#define S_STATIC15 1449
+#define S_MSG_4 1450
+#define S_STATUS1 1451
+#define S_STATUS2 1452
+#define P_BAR 1453
+#define L_HUBNAME 1454
+#define S_PSK 1455
+#define S_PSK2 1456
+#define S_WIN8 1457
+#define R_OPENVPN 1458
+#define S_UDP 1459
+#define S_UDP2 1460
+#define S_TOOL 1461
+#define S_TOOL2 1462
+#define R_SSTP 1463
+#define B_CONFIG_L3 1464
+#define S_SSTP 1465
+#define E_HOST 1466
+#define E_IPV4 1467
+#define E_NEWHOST 1468
+#define B_NSLOOKUP 1469
+#define B_HINT 1470
+#define S_DDNS 1470
+#define R_OVER_ICMP 1471
+#define S_AZURE 1471
+#define R_OVER_ICMP2 1472
+#define R_OVER_DNS 1472
+#define B_WIZ_NEXT 1472
+#define B_WIZ_NEXT2 1473
+#define B_WIZ_PREV 1473
+#define S_ACK 1473
+#define S_WELCOME 1474
+#define S_ACK2 1475
+#define S_WELCOME2 1475
+#define S_WELCOME3 1476
+#define E_DIR 1479
+#define B_BROWSE 1480
+#define S_DEST 1481
+#define B_BROWSE_OUT 1481
+#define S_UAC 1482
+#define E_SETTING 1483
+#define E_OUT 1484
+#define B_BROWSE_SETTING 1485
+#define S_INFO1 1486
+#define S_PRODUCT 1487
+#define S_INFO9 1487
+#define S_PRODUCT_STR 1488
+#define S_CURRENT_STR 1490
+#define S_LATEST 1491
+#define S_LATEST_STR 1492
+#define S_BMP_EN 1494
+#define S_BMP_JA 1495
+#define B_CHANGE 1496
+#define S_HOSTNAME_BORDER 1497
+#define S_HOSTNAME_INFO 1498
+#define S_BMP_CN 1499
+#define S_REFRESH 1499
+#define S_VLAN 1500
+#define C_VLAN 1502
+#define S_VPNGATEJA 1504
+#define S_ICO_VPNGATE 1505
+#define S_VPNGATEJA2 1505
+#define S_VPNGATEEN 1505
+#define S1 1506
+#define S2 1507
+#define S3 1508
+#define S4 1509
+#define S5 1510
+#define S_VGS1 1511
+#define S_VGS2 1512
+#define B_VGS 1513
+#define S_VGS3 1514
+#define S_TSUKUBA 1515
+#define B_ONLINE 1655
+#define D_NM_CONNECT 1998
+#define D_NM_MAIN 1999
+#define D_NM_OPTION 2000
+#define D_NM_NAT 2001
+#define D_NM_DHCP 2002
+#define D_NM_CHANGE_PASSWORD 2003
+#define D_SM_SNAT 2004
+#define D_SM_BRIDGE 2005
+#define D_WIN9X_REBOOT 2006
+#define D_DEFAULT1 2007
+#define D_EM_MAIN 2008
+#define D_EM_ADD 2009
+#define D_EM_PASSWORD 2010
+#define D_SM_CONFIG 2011
+#define D_SM_ADMIN_OPTION 2012
+#define D_SM_AO_VALUE 2013
+#define D_SM_L3 2014
+#define D_SM_L3_ADD 2015
+#define D_SM_L3_SW 2016
+#define D_SM_L3_SW_IF 2017
+#define D_SM_L3_SW_TABLE 2018
+#define D_CM_SELECT_SECURE 2019
+#define D_CM_SECURE_MANAGER 2020
+#define D_CM_SECURE_TYPE 2021
+#define D_STRING 2022
+#define D_SM_SELECT_KEYPAIR 2023
+#define D_CM_LOAD_X 2024
+#define D_CM_SECURE_PIN 2025
+#define D_SM_CRL 2026
+#define D_SM_EDIT_CRL 2027
+#define D_SM_AC_LIST 2028
+#define D_SM_AC 2029
+#define D_SM_LOG_FILE 2030
+#define D_SM_READ_LOG_FILE 2031
+#define D_SM_SAVE_LOG 2032
+#define D_TCP 2033
+#define D_TCP_MSG 2034
+#define D_CM_PKCSEULA 2035
+#define D_CM_KAKUSHI 2036
+#define D_CM_TRAFFIC 2037
+#define D_CM_TRAFFIC_RUN 2038
+#define D_CM_TRAFFIC_RESULT 2039
+#define D_SM_LICENSE 2040
+#define D_SM_LICENSE_ADD 2041
+#define D_FREEEDITION 2042
+#define D_FREEINFO 2042
+#define D_EM_LICENSE_ADD 2043
+#define D_EM_LICENSE 2044
+#define D_EM_REMOTE 2045
+#define D_CM_SETTING 2046
+#define D_CM_EASY 2047
+#define D_SM_SETUP 2048
+#define D_SM_SETUP_HUB 2049
+#define D_SM_SETUP_STEP 2050
+#define D_DEFAULT2 2051
+#define D_CPU64_WARNING 2051
+#define D_ONCEMSG 2052
+#define D_CONNECT 2053
+#define D_SM_SIMULATION 2054
+#define D_SM_EDIT_ACCESS1 2055
+#define D_SM_EDIT_ACCESS_V6 2055
+#define D_SM_VLAN 2056
+#define D_SM_MSG 2057
+#define D_NICSTATUS 2058
+#define D_NICINFO 2058
+#define D_SM_IPSEC 2059
+#define D_SM_ETHERIP 2060
+#define D_SM_ETHERIP_ID 2061
+#define D_SM_OPENVPN 2062
+#define D_DDNS 2063
+#define D_SM_DDNS 2063
+#define D_SM_SPECIALLISTENER 2064
+#define D_SM_REDIRECT 2065
+#define D_SW_TEST1 2066
+#define D_DUMMY 2067
+#define D_SW_TEST2 2068
+#define D_SW_DEFAULT 2069
+#define D_SW_WELCOME 2070
+#define D_SW_MODE 2071
+#define D_SW_NOT_ADMIN 2072
+#define D_SW_COMPONENTS 2073
+#define D_SW_EULA 2074
+#define D_SW_WARNING 2075
+#define D_SW_DIR 2076
+#define D_SW_READY 2077
+#define D_SW_PERFORM 2078
+#define D_SW_ERROR 2079
+#define D_SW_ERROR1 2080
+#define D_SW_FINISH 2080
+#define D_SW_WELCOME1 2081
+#define D_SW_UNINST1 2081
+#define D_SW_LANG1 2082
+#define D_SW_EASY1 2083
+#define D_SW_EASY2 2084
+#define D_SW_WEB1 2085
+#define D_SW_EASY4 2086
+#define D_SW_WEB2 2086
+#define D_UPDATE_NOTICE 2087
+#define D_UPDATE_CONFIG 2088
+#define D_SM_VMBRIDGE 2089
+#define D_SM_AZURE 2090
+#define D_SM_PROXY 2091
+#define D_VGC_LIST 2092
+#define D_VGC_PROTOCOL 2093
+#define D_VGS_CONFIG 2094
+#define D_VGS_OPTION 2095
+#define D_VGS_WARNING 2096
+#define ID_Menu40011 40011
+#define CMD_CONNECT 40020
+#define CMD_STATUS 40021
+#define CMD_DISCONNECT 40022
+#define CMD_NEW 40023
+#define CMD_CLONE 40024
+#define CMD_STARTUP 40025
+#define CMD_NOSTARTUP 40026
+#define CMD_PROPERTY 40028
+#define CMD_EXIT 40029
+#define CMD_SWITCH_SELECT 40031
+#define CMD_SELECT_ALL 40032
+#define CMD_TOOLBAR 40033
+#define CMD_STATUSBAR 40034
+#define CMD_ICON 40035
+#define CMD_DETAIL 40036
+#define CMD_REFRESH 40037
+#define CMD_PASSWORD 40038
+#define CMD_ABOUT 40040
+#define CMD_DELETE_VLAN 40045
+#define CMD_NEW_VLAN 40046
+#define CMD_REINSTALL 40050
+#define CMD_PROPERTY_VLAN 40052
+#define CMD_DISABLE_VLAN 40054
+#define CMD_ENABLE_VLAN 40056
+#define CMD_RENAME 40059
+#define CMD_DELETE 40061
+#define CMD_GRID 40062
+#define CMD_ 40063
+#define CMD_TRUST 40065
+#define CMD_DISCONNECT_ALL 40067
+#define CMD_VOICE_NORMAL 40072
+#define CMD_VOIDE_NONE 40073
+#define CMD_VOICE_ODD 40074
+#define CMD_EXPORT_ACCOUNT 40075
+#define CMD_IMPORT_ACCOUNT 40078
+#define CMD_SHORTCUT 40079
+#define ID_40080 40080
+#define ID_40082 40082
+#define CMD_SECURE_MANAGER 40083
+#define CMD_SECURE_SELECT 40084
+#define CMD_QUIT 40086
+#define CMD_NETIF 40088
+#define CMD_TCPIP 40089
+#define CMD_TRAFFIC 40090
+#define CMD_OPTION 40092
+#define ID__40093 40093
+#define CMD_CM_SETTING 40094
+#define CMD_MMCSS 40095
+#define CMD_TRAYICON 40096
+#define ID__ 40097
+#define CMD_WINNET 40098
+#define ID__40099 40099
+#define CMD_VISTASTYLE 40100
+#define ID__40101 40101
+#define CMD_SHOWPORT 40102
+#define ID__40103 40103
+#define CMD_RECENT 40104
+#define ID__40105 40105
+#define ID__40106 40106
+#define CMD_LANGUAGE 40107
+#define ID_VPNGATE40108 40108
+#define ID__40109 40109
+#define CMD_VGS 40110
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 242
+#define _APS_NEXT_COMMAND_VALUE 40111
+#define _APS_NEXT_CONTROL_VALUE 1516
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/src/PenCore/setup_1.bmp b/src/PenCore/setup_1.bmp
new file mode 100644
index 00000000..988f8c65
--- /dev/null
+++ b/src/PenCore/setup_1.bmp
Binary files differ
diff --git a/src/PenCore/setup_2.bmp b/src/PenCore/setup_2.bmp
new file mode 100644
index 00000000..98d791b2
--- /dev/null
+++ b/src/PenCore/setup_2.bmp
Binary files differ
diff --git a/src/README b/src/README
new file mode 100644
index 00000000..df623ce6
--- /dev/null
+++ b/src/README
@@ -0,0 +1,189 @@
+SoftEther VPN - An Open-Source Cross-platform Multi-protocol VPN Program
+http://www.softether.org/
+
+We use GitHub as the primary official SoftEther VPN repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+Source code packages (.zip and .tar.gz) and binary files are also available:
+http://www.softether-download.com/
+
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2
+as published by the Free Software Foundation.
+
+SoftEther VPN ("SoftEther" means "Software Ethernet") is one of the
+world's most powerful and easy-to-use multi-protocol VPN software.
+
+SoftEther VPN runs on Windows, Linux, Mac, FreeBSD and Solaris.
+
+SoftEther VPN supports most of widely-used VPN protocols
+including SSL-VPN, OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 and EtherIP
+by the single SoftEther VPN Server program.
+
+More details on http://www.softether.org/.
+
+
+SOFTETHER VPN ADVANTAGES
+------------------------
+
+- Supporting all popular VPN protocols by the single VPN server:
+ SSL-VPN (HTTPS)
+ OpenVPN
+ IPsec
+ L2TP
+ MS-SSTP
+ L2TPv3
+ EtherIP
+- Free and open-source software.
+- Easy to establish both remote-access and site-to-site VPN.
+- SSL-VPN Tunneling on HTTPS to pass through NATs and firewalls.
+- Revolutionary VPN over ICMP and VPN over DNS features.
+- Resistance to highly-restricted firewall.
+- Ethernet-bridging (L2) and IP-routing (L3) over VPN.
+- Embedded dynamic-DNS and NAT-traversal so that no static nor
+ fixed IP address is required.
+- AES 256-bit and RSA 4096-bit encryptions.
+- Sufficient security features such as logging and firewall inner
+ VPN tunnel.
+- 1Gbps-class high-speed throughput performance with low memory and
+ CPU usage.
+- Windows, Linux, Mac, Android, iPhone, iPad and Windows Phone are
+ supported.
+- The OpenVPN clone function supports legacy OpenVPN clients.
+- IPv4 / IPv6 dual-stack.
+- The VPN server runs on Windows, Linux, FreeBSD, Solaris and Mac OS X.
+- Configure All settings on GUI.
+- Multi-languages (English, Japanese and Simplified-Chinese).
+- More details at http://www.softether.org/.
+
+
+GETTING STARTED
+---------------
+
+Visit the SoftEther VPN Project official web site at first:
+ http://www.softether.org/
+
+If you are not a developer, it is recommended to download the binary
+installers from:
+ http://www.softether-download.com/
+
+To build from the source,
+see "BUILD_UNIX.TXT" or "BUILD_WINDOWS.TXT" files.
+
+
+HOW TO DOWNLOAD THE LATEST SOURCE CODE PACKAGE
+----------------------------------------------
+
+Go to http://www.softether-download.com/ and you can find the latest
+source-code package file in both .ZIP and .TAR.GZ format.
+
+This is the easiest way to obtain the source code of SoftEther VPN.
+
+
+HOW TO GET THE LATEST SOURCE CODE TREE FOR DEVELOPERS
+-----------------------------------------------------
+
+If you are an open-source developer, visit our GitHub repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+You can download the up-to-date source-code tree of SoftEther VPN
+from GitHub. You may make your own fork project from our project.
+
+The download and build instruction is following:
+
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+$ cd SoftEtherVPN
+$ make
+$ make install
+
+
+TO CIRCUMVENT YOUR GOVERNMENT'S FIREWALL RESTRICTION
+----------------------------------------------------
+
+Because SoftEther VPN is overly strong tool to build a VPN tunnel,
+some censorship governments want to block your access to the source code
+of SoftEther VPN, by abusing their censorship firewalls.
+
+To circumvent your censor's unjust restriction,
+SoftEther VPN Project distributes the up-to-date source-code
+on all the following open-source repositories:
+
+ - GitHub
+ https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+ - SourceForge
+ https://sourceforge.net/projects/softethervpn/
+
+ - Google Code
+ https://code.google.com/p/softether/
+
+
+To fetch the source code from GitHub:
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+
+To fetch the source code from SourceForge:
+$ git clone http://git.code.sf.net/p/softethervpn/code
+ - or -
+$ git clone git://git.code.sf.net/p/softethervpn/code
+
+To fetch the source code from Google Code:
+$ git clone https://code.google.com/p/softether/
+
+We hope that you can reach one of the above URLs at least!
+
+
+DEAR SECURITY EXPERTS
+---------------------
+
+If you find a bug or a security vulnerability please kindly inform us
+about the problem immediately so that we can fix the security problem
+to protect a lot of users around the world as soon as possible.
+
+Our e-mail address for security reports is:
+softether-vpn-security [at] softether.org
+
+Please note that the above e-mail address is not a technical support
+inquiry address. If you need technical assistance, please visit
+http://www.softether.org/ and ask your question on the users forum.
+
+
+DISCLAIMER
+----------
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+COUNTRIES MIGHT BE RESTRICTED.
+
+
+ADVERTISEMENT
+-------------
+
+SoftEther VPN is developed by SoftEther VPN Project at University of Tsukuba.
+Department of Computer Science has dozens of overly-enthusiastic geeks.
+Join us: http://www.tsukuba.ac.jp/english/admission/
+
diff --git a/src/README.TXT b/src/README.TXT
new file mode 100644
index 00000000..df623ce6
--- /dev/null
+++ b/src/README.TXT
@@ -0,0 +1,189 @@
+SoftEther VPN - An Open-Source Cross-platform Multi-protocol VPN Program
+http://www.softether.org/
+
+We use GitHub as the primary official SoftEther VPN repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+Source code packages (.zip and .tar.gz) and binary files are also available:
+http://www.softether-download.com/
+
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2
+as published by the Free Software Foundation.
+
+SoftEther VPN ("SoftEther" means "Software Ethernet") is one of the
+world's most powerful and easy-to-use multi-protocol VPN software.
+
+SoftEther VPN runs on Windows, Linux, Mac, FreeBSD and Solaris.
+
+SoftEther VPN supports most of widely-used VPN protocols
+including SSL-VPN, OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 and EtherIP
+by the single SoftEther VPN Server program.
+
+More details on http://www.softether.org/.
+
+
+SOFTETHER VPN ADVANTAGES
+------------------------
+
+- Supporting all popular VPN protocols by the single VPN server:
+ SSL-VPN (HTTPS)
+ OpenVPN
+ IPsec
+ L2TP
+ MS-SSTP
+ L2TPv3
+ EtherIP
+- Free and open-source software.
+- Easy to establish both remote-access and site-to-site VPN.
+- SSL-VPN Tunneling on HTTPS to pass through NATs and firewalls.
+- Revolutionary VPN over ICMP and VPN over DNS features.
+- Resistance to highly-restricted firewall.
+- Ethernet-bridging (L2) and IP-routing (L3) over VPN.
+- Embedded dynamic-DNS and NAT-traversal so that no static nor
+ fixed IP address is required.
+- AES 256-bit and RSA 4096-bit encryptions.
+- Sufficient security features such as logging and firewall inner
+ VPN tunnel.
+- 1Gbps-class high-speed throughput performance with low memory and
+ CPU usage.
+- Windows, Linux, Mac, Android, iPhone, iPad and Windows Phone are
+ supported.
+- The OpenVPN clone function supports legacy OpenVPN clients.
+- IPv4 / IPv6 dual-stack.
+- The VPN server runs on Windows, Linux, FreeBSD, Solaris and Mac OS X.
+- Configure All settings on GUI.
+- Multi-languages (English, Japanese and Simplified-Chinese).
+- More details at http://www.softether.org/.
+
+
+GETTING STARTED
+---------------
+
+Visit the SoftEther VPN Project official web site at first:
+ http://www.softether.org/
+
+If you are not a developer, it is recommended to download the binary
+installers from:
+ http://www.softether-download.com/
+
+To build from the source,
+see "BUILD_UNIX.TXT" or "BUILD_WINDOWS.TXT" files.
+
+
+HOW TO DOWNLOAD THE LATEST SOURCE CODE PACKAGE
+----------------------------------------------
+
+Go to http://www.softether-download.com/ and you can find the latest
+source-code package file in both .ZIP and .TAR.GZ format.
+
+This is the easiest way to obtain the source code of SoftEther VPN.
+
+
+HOW TO GET THE LATEST SOURCE CODE TREE FOR DEVELOPERS
+-----------------------------------------------------
+
+If you are an open-source developer, visit our GitHub repository:
+https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+You can download the up-to-date source-code tree of SoftEther VPN
+from GitHub. You may make your own fork project from our project.
+
+The download and build instruction is following:
+
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+$ cd SoftEtherVPN
+$ make
+$ make install
+
+
+TO CIRCUMVENT YOUR GOVERNMENT'S FIREWALL RESTRICTION
+----------------------------------------------------
+
+Because SoftEther VPN is overly strong tool to build a VPN tunnel,
+some censorship governments want to block your access to the source code
+of SoftEther VPN, by abusing their censorship firewalls.
+
+To circumvent your censor's unjust restriction,
+SoftEther VPN Project distributes the up-to-date source-code
+on all the following open-source repositories:
+
+ - GitHub
+ https://github.com/SoftEtherVPN/SoftEtherVPN/
+
+ - SourceForge
+ https://sourceforge.net/projects/softethervpn/
+
+ - Google Code
+ https://code.google.com/p/softether/
+
+
+To fetch the source code from GitHub:
+$ git clone https://github.com/SoftEtherVPN/SoftEtherVPN.git
+
+To fetch the source code from SourceForge:
+$ git clone http://git.code.sf.net/p/softethervpn/code
+ - or -
+$ git clone git://git.code.sf.net/p/softethervpn/code
+
+To fetch the source code from Google Code:
+$ git clone https://code.google.com/p/softether/
+
+We hope that you can reach one of the above URLs at least!
+
+
+DEAR SECURITY EXPERTS
+---------------------
+
+If you find a bug or a security vulnerability please kindly inform us
+about the problem immediately so that we can fix the security problem
+to protect a lot of users around the world as soon as possible.
+
+Our e-mail address for security reports is:
+softether-vpn-security [at] softether.org
+
+Please note that the above e-mail address is not a technical support
+inquiry address. If you need technical assistance, please visit
+http://www.softether.org/ and ask your question on the users forum.
+
+
+DISCLAIMER
+----------
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+COUNTRIES MIGHT BE RESTRICTED.
+
+
+ADVERTISEMENT
+-------------
+
+SoftEther VPN is developed by SoftEther VPN Project at University of Tsukuba.
+Department of Computer Science has dozens of overly-enthusiastic geeks.
+Join us: http://www.tsukuba.ac.jp/english/admission/
+
diff --git a/src/SEVPN.sln b/src/SEVPN.sln
new file mode 100644
index 00000000..9e48f540
--- /dev/null
+++ b/src/SEVPN.sln
@@ -0,0 +1,377 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{C17FED94-2864-4C4A-8A8F-80555FEEB5E3}"
+ ProjectSection(SolutionItems) = preProject
+ GlobalConst.h = GlobalConst.h
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bin", "bin", "{140CBADC-7522-4B52-B06A-A4781A9C9DF2}"
+ ProjectSection(SolutionItems) = preProject
+ bin\custom.ini = bin\custom.ini
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hamcore", "hamcore", "{234994FD-5966-4CFE-AC38-960DE089FBED}"
+ ProjectSection(SolutionItems) = preProject
+ bin\hamcore\lang.config = bin\hamcore\lang.config
+ bin\hamcore\languages.txt = bin\hamcore\languages.txt
+ bin\hamcore\SeLow_x64.inf = bin\hamcore\SeLow_x64.inf
+ bin\hamcore\SeLow_x86.inf = bin\hamcore\SeLow_x86.inf
+ bin\hamcore\strtable_cn.stb = bin\hamcore\strtable_cn.stb
+ bin\hamcore\strtable_en.stb = bin\hamcore\strtable_en.stb
+ bin\hamcore\time.htm = bin\hamcore\time.htm
+ bin\hamcore\vpn16.exe = bin\hamcore\vpn16.exe
+ bin\hamcore\vpn_driver.inf = bin\hamcore\vpn_driver.inf
+ bin\hamcore\vpn_driver_9x.inf = bin\hamcore\vpn_driver_9x.inf
+ bin\hamcore\vpn_driver_x64.inf = bin\hamcore\vpn_driver_x64.inf
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildFiles", "BuildFiles", "{ECFF92D4-8F03-4DDF-ACEF-9A68589BC282}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{90A585CD-2B00-47F3-8F65-FE091B154AB3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win32_Debug", "Win32_Debug", "{979EF6E9-A263-4E9B-964C-DE72344DFB13}"
+ ProjectSection(SolutionItems) = preProject
+ BuildFiles\Library\Win32_Debug\libeay32.lib = BuildFiles\Library\Win32_Debug\libeay32.lib
+ BuildFiles\Library\Win32_Debug\ssleay32.lib = BuildFiles\Library\Win32_Debug\ssleay32.lib
+ BuildFiles\Library\Win32_Debug\zlib.lib = BuildFiles\Library\Win32_Debug\zlib.lib
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win32_Release", "Win32_Release", "{7DE9E590-6189-4570-A451-2584E655A539}"
+ ProjectSection(SolutionItems) = preProject
+ BuildFiles\Library\Win32_Release\libeay32.lib = BuildFiles\Library\Win32_Release\libeay32.lib
+ BuildFiles\Library\Win32_Release\ssleay32.lib = BuildFiles\Library\Win32_Release\ssleay32.lib
+ BuildFiles\Library\Win32_Release\zlib.lib = BuildFiles\Library\Win32_Release\zlib.lib
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x64_Debug", "x64_Debug", "{696A5B66-04A7-4CE8-A31C-E05026846B5C}"
+ ProjectSection(SolutionItems) = preProject
+ BuildFiles\Library\x64_Debug\libeay32.lib = BuildFiles\Library\x64_Debug\libeay32.lib
+ BuildFiles\Library\x64_Debug\ssleay32.lib = BuildFiles\Library\x64_Debug\ssleay32.lib
+ BuildFiles\Library\x64_Debug\zlib.lib = BuildFiles\Library\x64_Debug\zlib.lib
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x64_Release", "x64_Release", "{1AFACDF7-7ECE-42D3-A3BD-563025F247D7}"
+ ProjectSection(SolutionItems) = preProject
+ BuildFiles\Library\x64_Release\libeay32.lib = BuildFiles\Library\x64_Release\libeay32.lib
+ BuildFiles\Library\x64_Release\ssleay32.lib = BuildFiles\Library\x64_Release\ssleay32.lib
+ BuildFiles\Library\x64_Release\zlib.lib = BuildFiles\Library\x64_Release\zlib.lib
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Neo", "Neo\Neo.vcproj", "{D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "See", "See\See.vcproj", "{D817977C-481C-4575-B229-DD2896EDF6C9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeeDll", "SeeDll\SeeDll.vcproj", "{B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D817977C-481C-4575-B229-DD2896EDF6C9} = {D817977C-481C-4575-B229-DD2896EDF6C9}
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ {94CA5DD2-1543-42F6-9F96-EE7694DDC837} = {94CA5DD2-1543-42F6-9F96-EE7694DDC837}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PenCore", "PenCore\PenCore.vcproj", "{AF16335D-DBC2-4879-9E9A-89E2A61A4B30}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mayaqua", "Mayaqua\Mayaqua.vcproj", "{70486335-7814-40E2-A561-BBCB6025F5C9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cedar", "Cedar\Cedar.vcproj", "{2928D768-DEC3-40D3-8E51-26E364497C9B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {70486335-7814-40E2-A561-BBCB6025F5C9} = {70486335-7814-40E2-A561-BBCB6025F5C9}
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30} = {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422} = {F7679B65-2FEC-469A-8BAC-B07BF4439422}
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69} = {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}
+ {717B8D7F-9C93-4713-9A23-8CE70A31FD39} = {717B8D7F-9C93-4713-9A23-8CE70A31FD39}
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ham", "Ham\Ham.vcproj", "{1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF} = {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpncmd", "vpncmd\vpncmd.vcproj", "{83438AC3-5329-4337-89BC-5B69EBAE4B6E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpncmdsys", "vpncmdsys\vpncmdsys.vcproj", "{78CD48D9-0B4B-43B1-A1D1-E079362B6864}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnbrand", "vpnbrand\vpnbrand.vcproj", "{ABAB0B91-91DD-4FF4-9773-18B37A820B9F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnbridge", "vpnbridge\vpnbridge.vcproj", "{BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF} = {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpncmgr", "vpncmgr\vpncmgr.vcproj", "{92B04960-1AA9-4A7A-B75C-1403046F25B3}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnclient", "vpnclient\vpnclient.vcproj", "{D7216F25-434B-45D3-BA48-6772AF997C84}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF} = {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnserver", "vpnserver\vpnserver.vcproj", "{7CF21BD6-659F-449C-91CB-CE52AABAD22D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF} = {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnsmgr", "vpnsmgr\vpnsmgr.vcproj", "{A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF} = {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utility", "Utility", "{F5F7EE7B-3207-4ACD-804B-1423BCB25285}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildUtil", "BuildUtil\BuildUtil.csproj", "{384815C3-333C-4CEC-9DCD-B6AB2602EBB9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpndrvinst", "vpndrvinst\vpndrvinst.vcproj", "{CF2B20BF-9799-40EF-A987-9E4C25E68E1C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpninstall", "vpninstall\vpninstall.vcproj", "{F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnweb", "vpnweb\vpnweb.vcproj", "{1F58A797-A861-4256-9262-CE97B923016B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Wfp", "Wfp\Wfp.vcproj", "{717B8D7F-9C93-4713-9A23-8CE70A31FD39}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpnsetup", "vpnsetup\vpnsetup.vcproj", "{58FEB572-E43A-439E-9A2C-E19DE3CB1401}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Neo6", "Neo6\Neo6.vcproj", "{F7679B65-2FEC-469A-8BAC-B07BF4439422}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F} = {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeLow", "SeLow\SeLow.vcproj", "{94CA5DD2-1543-42F6-9F96-EE7694DDC837}"
+ ProjectSection(ProjectDependencies) = postProject
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9} = {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VGate", "VGate\VGate.vcproj", "{DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2928D768-DEC3-40D3-8E51-26E364497C9B} = {2928D768-DEC3-40D3-8E51-26E364497C9B}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}.Debug|Win32.ActiveCfg = Release|Win32
+ {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}.Debug|x64.ActiveCfg = Release|x64
+ {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}.Release|Win32.ActiveCfg = Release|Win32
+ {D302D5D9-A3B7-4D2E-98BF-3BB305BAE43F}.Release|x64.ActiveCfg = Release|x64
+ {D817977C-481C-4575-B229-DD2896EDF6C9}.Debug|Win32.ActiveCfg = Release|Win32
+ {D817977C-481C-4575-B229-DD2896EDF6C9}.Debug|x64.ActiveCfg = Release|x64
+ {D817977C-481C-4575-B229-DD2896EDF6C9}.Release|Win32.ActiveCfg = Release|Win32
+ {D817977C-481C-4575-B229-DD2896EDF6C9}.Release|x64.ActiveCfg = Release|x64
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Debug|Win32.ActiveCfg = Release|Win32
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Debug|Win32.Build.0 = Release|Win32
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Debug|x64.ActiveCfg = Release|x64
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Debug|x64.Build.0 = Release|x64
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Release|Win32.ActiveCfg = Release|Win32
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Release|Win32.Build.0 = Release|Win32
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Release|x64.ActiveCfg = Release|x64
+ {B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}.Release|x64.Build.0 = Release|x64
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Debug|Win32.ActiveCfg = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Debug|Win32.Build.0 = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Debug|x64.ActiveCfg = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Debug|x64.Build.0 = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Release|Win32.ActiveCfg = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Release|Win32.Build.0 = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Release|x64.ActiveCfg = Release|Win32
+ {AF16335D-DBC2-4879-9E9A-89E2A61A4B30}.Release|x64.Build.0 = Release|Win32
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Debug|Win32.Build.0 = Debug|Win32
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Debug|x64.ActiveCfg = Debug|x64
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Debug|x64.Build.0 = Debug|x64
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Release|Win32.ActiveCfg = Release|Win32
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Release|Win32.Build.0 = Release|Win32
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Release|x64.ActiveCfg = Release|x64
+ {70486335-7814-40E2-A561-BBCB6025F5C9}.Release|x64.Build.0 = Release|x64
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Debug|Win32.Build.0 = Debug|Win32
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Debug|x64.ActiveCfg = Debug|x64
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Debug|x64.Build.0 = Debug|x64
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Release|Win32.ActiveCfg = Release|Win32
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Release|Win32.Build.0 = Release|Win32
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Release|x64.ActiveCfg = Release|x64
+ {2928D768-DEC3-40D3-8E51-26E364497C9B}.Release|x64.Build.0 = Release|x64
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Debug|Win32.Build.0 = Debug|Win32
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Debug|x64.ActiveCfg = Debug|x64
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Debug|x64.Build.0 = Debug|x64
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Release|Win32.ActiveCfg = Release|Win32
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Release|Win32.Build.0 = Release|Win32
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Release|x64.ActiveCfg = Release|x64
+ {1ED5782B-1734-4FC6-AA9E-F7181CDBA8A7}.Release|x64.Build.0 = Release|x64
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Debug|Win32.Build.0 = Debug|Win32
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Debug|x64.ActiveCfg = Debug|x64
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Debug|x64.Build.0 = Debug|x64
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Release|Win32.ActiveCfg = Release|Win32
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Release|Win32.Build.0 = Release|Win32
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Release|x64.ActiveCfg = Release|x64
+ {83438AC3-5329-4337-89BC-5B69EBAE4B6E}.Release|x64.Build.0 = Release|x64
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Debug|Win32.ActiveCfg = Release|Win32
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Debug|Win32.Build.0 = Release|Win32
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Debug|x64.ActiveCfg = Release|x64
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Debug|x64.Build.0 = Release|x64
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Release|Win32.ActiveCfg = Release|Win32
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Release|Win32.Build.0 = Release|Win32
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Release|x64.ActiveCfg = Release|x64
+ {78CD48D9-0B4B-43B1-A1D1-E079362B6864}.Release|x64.Build.0 = Release|x64
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Debug|Win32.Build.0 = Debug|Win32
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Debug|x64.ActiveCfg = Debug|x64
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Debug|x64.Build.0 = Debug|x64
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Release|Win32.ActiveCfg = Release|Win32
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Release|Win32.Build.0 = Release|Win32
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Release|x64.ActiveCfg = Release|x64
+ {ABAB0B91-91DD-4FF4-9773-18B37A820B9F}.Release|x64.Build.0 = Release|x64
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Debug|Win32.Build.0 = Debug|Win32
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Debug|x64.ActiveCfg = Debug|x64
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Debug|x64.Build.0 = Debug|x64
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Release|Win32.ActiveCfg = Release|Win32
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Release|Win32.Build.0 = Release|Win32
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Release|x64.ActiveCfg = Release|x64
+ {BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}.Release|x64.Build.0 = Release|x64
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Debug|Win32.Build.0 = Debug|Win32
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Debug|x64.ActiveCfg = Debug|x64
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Debug|x64.Build.0 = Debug|x64
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Release|Win32.ActiveCfg = Release|Win32
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Release|Win32.Build.0 = Release|Win32
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Release|x64.ActiveCfg = Release|x64
+ {92B04960-1AA9-4A7A-B75C-1403046F25B3}.Release|x64.Build.0 = Release|x64
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Debug|Win32.Build.0 = Debug|Win32
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Debug|x64.ActiveCfg = Debug|x64
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Debug|x64.Build.0 = Debug|x64
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Release|Win32.ActiveCfg = Release|Win32
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Release|Win32.Build.0 = Release|Win32
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Release|x64.ActiveCfg = Release|x64
+ {D7216F25-434B-45D3-BA48-6772AF997C84}.Release|x64.Build.0 = Release|x64
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Debug|Win32.Build.0 = Debug|Win32
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Debug|x64.ActiveCfg = Debug|x64
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Debug|x64.Build.0 = Debug|x64
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Release|Win32.ActiveCfg = Release|Win32
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Release|Win32.Build.0 = Release|Win32
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Release|x64.ActiveCfg = Release|x64
+ {7CF21BD6-659F-449C-91CB-CE52AABAD22D}.Release|x64.Build.0 = Release|x64
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Debug|Win32.Build.0 = Debug|Win32
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Debug|x64.ActiveCfg = Debug|x64
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Debug|x64.Build.0 = Debug|x64
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Release|Win32.ActiveCfg = Release|Win32
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Release|Win32.Build.0 = Release|Win32
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Release|x64.ActiveCfg = Release|x64
+ {A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}.Release|x64.Build.0 = Release|x64
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Debug|Win32.Build.0 = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Debug|x64.Build.0 = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Release|Win32.ActiveCfg = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Release|Win32.Build.0 = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Release|x64.ActiveCfg = Debug|Any CPU
+ {384815C3-333C-4CEC-9DCD-B6AB2602EBB9}.Release|x64.Build.0 = Debug|Any CPU
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Debug|Win32.ActiveCfg = Release|Win32
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Debug|Win32.Build.0 = Release|Win32
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Debug|x64.ActiveCfg = Release|x64
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Debug|x64.Build.0 = Release|x64
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Release|Win32.ActiveCfg = Release|Win32
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Release|Win32.Build.0 = Release|Win32
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Release|x64.ActiveCfg = Release|x64
+ {CF2B20BF-9799-40EF-A987-9E4C25E68E1C}.Release|x64.Build.0 = Release|x64
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Debug|Win32.Build.0 = Debug|Win32
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Debug|x64.ActiveCfg = Debug|Win32
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Release|Win32.ActiveCfg = Release|Win32
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Release|Win32.Build.0 = Release|Win32
+ {F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}.Release|x64.ActiveCfg = Release|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Debug|Win32.Build.0 = Debug|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Debug|x64.ActiveCfg = Debug|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Release|Win32.ActiveCfg = Release|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Release|Win32.Build.0 = Release|Win32
+ {1F58A797-A861-4256-9262-CE97B923016B}.Release|x64.ActiveCfg = Release|Win32
+ {717B8D7F-9C93-4713-9A23-8CE70A31FD39}.Debug|Win32.ActiveCfg = Release|Win32
+ {717B8D7F-9C93-4713-9A23-8CE70A31FD39}.Debug|x64.ActiveCfg = Release|x64
+ {717B8D7F-9C93-4713-9A23-8CE70A31FD39}.Release|Win32.ActiveCfg = Release|Win32
+ {717B8D7F-9C93-4713-9A23-8CE70A31FD39}.Release|x64.ActiveCfg = Release|x64
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Debug|Win32.ActiveCfg = Debug|Win32
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Debug|Win32.Build.0 = Debug|Win32
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Debug|x64.ActiveCfg = Debug|x64
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Debug|x64.Build.0 = Debug|x64
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Release|Win32.ActiveCfg = Release|Win32
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Release|Win32.Build.0 = Release|Win32
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Release|x64.ActiveCfg = Release|x64
+ {58FEB572-E43A-439E-9A2C-E19DE3CB1401}.Release|x64.Build.0 = Release|x64
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422}.Debug|Win32.ActiveCfg = Release|Win32
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422}.Debug|x64.ActiveCfg = Release|x64
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422}.Release|Win32.ActiveCfg = Release|Win32
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422}.Release|x64.ActiveCfg = Release|x64
+ {94CA5DD2-1543-42F6-9F96-EE7694DDC837}.Debug|Win32.ActiveCfg = Release|Win32
+ {94CA5DD2-1543-42F6-9F96-EE7694DDC837}.Debug|x64.ActiveCfg = Release|x64
+ {94CA5DD2-1543-42F6-9F96-EE7694DDC837}.Release|Win32.ActiveCfg = Release|Win32
+ {94CA5DD2-1543-42F6-9F96-EE7694DDC837}.Release|x64.ActiveCfg = Release|x64
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}.Debug|x64.ActiveCfg = Debug|x64
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}.Release|Win32.ActiveCfg = Release|Win32
+ {DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}.Release|x64.ActiveCfg = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {140CBADC-7522-4B52-B06A-A4781A9C9DF2} = {C17FED94-2864-4C4A-8A8F-80555FEEB5E3}
+ {ECFF92D4-8F03-4DDF-ACEF-9A68589BC282} = {C17FED94-2864-4C4A-8A8F-80555FEEB5E3}
+ {234994FD-5966-4CFE-AC38-960DE089FBED} = {140CBADC-7522-4B52-B06A-A4781A9C9DF2}
+ {90A585CD-2B00-47F3-8F65-FE091B154AB3} = {ECFF92D4-8F03-4DDF-ACEF-9A68589BC282}
+ {F5F7EE7B-3207-4ACD-804B-1423BCB25285} = {ECFF92D4-8F03-4DDF-ACEF-9A68589BC282}
+ {979EF6E9-A263-4E9B-964C-DE72344DFB13} = {90A585CD-2B00-47F3-8F65-FE091B154AB3}
+ {7DE9E590-6189-4570-A451-2584E655A539} = {90A585CD-2B00-47F3-8F65-FE091B154AB3}
+ {696A5B66-04A7-4CE8-A31C-E05026846B5C} = {90A585CD-2B00-47F3-8F65-FE091B154AB3}
+ {1AFACDF7-7ECE-42D3-A3BD-563025F247D7} = {90A585CD-2B00-47F3-8F65-FE091B154AB3}
+ EndGlobalSection
+EndGlobal
diff --git a/src/SeLow/SeLow.c b/src/SeLow/SeLow.c
new file mode 100644
index 00000000..439fbd25
--- /dev/null
+++ b/src/SeLow/SeLow.c
@@ -0,0 +1,2104 @@
+// SoftEther VPN Source Code
+// SeLow: SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLow.c
+// SeLow Device Driver
+
+#include <GlobalConst.h>
+
+#define SELOW_DEVICE_DRIVER
+
+#include "SeLow.h"
+
+static SL_CTX sl_ctx = {0};
+static SL_CTX *sl = &sl_ctx;
+
+// Win32 driver entry point
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path)
+{
+ NDIS_PROTOCOL_DRIVER_CHARACTERISTICS t;
+ NDIS_STATUS ret = NDIS_STATUS_FAILURE;
+ SL_UNICODE *protocol_name = NULL;
+ NDIS_HANDLE protocol_handle = NULL;
+ SL_CTX *sl_ctx = NULL;
+ DEVICE_OBJECT *device_object = NULL;
+
+ SlZero(sl, sizeof(SL_CTX));
+
+ // Register the NDIS protocol
+ protocol_name = SlNewUnicode(SL_PROTOCOL_NAME);
+ if (protocol_name == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ SlZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS;
+ t.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2;
+ t.Header.Size = NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2;
+ t.MajorNdisVersion = 6;
+ t.MinorNdisVersion = 20;
+ t.Name = protocol_name->String;
+
+ t.BindAdapterHandlerEx = SlNdisBindAdapterExProc;
+ t.UnbindAdapterHandlerEx = SlNdisUnbindAdapterExProc;
+ t.OpenAdapterCompleteHandlerEx = SlNdisOpenAdapterCompleteExProc;
+ t.CloseAdapterCompleteHandlerEx = SlNdisCloseAdapterCompleteExProc;
+ t.NetPnPEventHandler = SlNdisNetPnPEventProc;
+ t.UninstallHandler = SlNdisUninstallProc;
+ t.OidRequestCompleteHandler = SlNdisOidRequestCompleteProc;
+ t.StatusHandlerEx = SlNdisStatusExProc;
+ t.ReceiveNetBufferListsHandler = SlNdisReceiveNetBufferListsProc;
+ t.SendNetBufferListsCompleteHandler = SlNdisSendNetBufferListsCompleteProc;
+
+ // Create an adapters list
+ sl->DriverObject = driver_object;
+ sl->AdapterList = SlNewList();
+
+ ret = NdisRegisterProtocolDriver(NULL, &t, &protocol_handle);
+
+ if (NG(ret))
+ {
+ protocol_handle = NULL;
+ goto LABEL_CLEANUP;
+ }
+
+ SlZero(driver_object->MajorFunction, sizeof(driver_object->MajorFunction));
+ driver_object->MajorFunction[IRP_MJ_CREATE] = SlDeviceOpenProc;
+ driver_object->MajorFunction[IRP_MJ_CLOSE] = SlDeviceCloseProc;
+ driver_object->MajorFunction[IRP_MJ_READ] = SlDeviceReadProc;
+ driver_object->MajorFunction[IRP_MJ_WRITE] = SlDeviceWriteProc;
+ driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SlDeviceIoControlProc;
+ driver_object->DriverUnload = SlUnloadProc;
+
+ // Initialize the SL context
+ sl->ProtocolHandle = protocol_handle;
+
+ // Create a basic device
+ sl->BasicDevice = SlNewDevice(SL_BASIC_DEVICE_NAME, SL_BASIC_DEVICE_NAME_SYMBOLIC);
+ if (sl->BasicDevice == NULL)
+ {
+ ret = NDIS_STATUS_FAILURE;
+ goto LABEL_CLEANUP;
+ }
+ sl->BasicDevice->IsBasicDevice = true;
+
+LABEL_CLEANUP:
+
+ SlFreeUnicode(protocol_name);
+
+ if (NG(ret))
+ {
+ SlUnloadProc(driver_object);
+ }
+
+ return ret;
+}
+
+// Unloading procedure of the device driver
+void SlUnloadProc(DRIVER_OBJECT *driver_object)
+{
+ // Release the protocol
+ if (sl->ProtocolHandle != NULL)
+ {
+ NdisDeregisterProtocolDriver(sl->ProtocolHandle);
+ sl->ProtocolHandle = NULL;
+ }
+
+ // Release the basic device
+ SlFreeDevice(sl->BasicDevice);
+
+ // Release the adapter list
+ SlFreeList(sl->AdapterList);
+
+ // Initialize the SL context
+ SlZero(sl, sizeof(SL_CTX));
+}
+
+// Delete a device
+void SlFreeDevice(SL_DEVICE *dev)
+{
+ NTSTATUS r;
+ // Validate arguments
+ if (dev == NULL)
+ {
+ return;
+ }
+
+ r = IoDeleteSymbolicLink(&dev->SymbolicLinkName->String);
+ if (NG(r))
+ {
+ // May fail due to a bug in Windows Kernel
+ }
+
+ IoDeleteDevice(dev->DeviceObject);
+
+ SlFreeUnicode(dev->DeviceName);
+ SlFreeUnicode(dev->SymbolicLinkName);
+
+ SlFreeLock(dev->OpenCloseLock);
+
+ SlFree(dev);
+}
+
+// Create a new device
+SL_DEVICE *SlNewDevice(char *device_name, char *symbolic_link_name)
+{
+ SL_UNICODE *u_device_name = SlNewUnicode(device_name);
+ SL_UNICODE *u_sym_name = SlNewUnicode(symbolic_link_name);
+
+ SL_DEVICE *ret = SlNewDeviceUnicode(u_device_name, u_sym_name);
+
+ if (ret == NULL)
+ {
+ SlFreeUnicode(u_device_name);
+ SlFreeUnicode(u_sym_name);
+ }
+
+ return ret;
+}
+SL_DEVICE *SlNewDeviceUnicode(SL_UNICODE *u_device_name, SL_UNICODE *u_sym_name)
+{
+ SL_DEVICE *ret = NULL;
+ DEVICE_OBJECT *dev_obj = NULL;
+ NTSTATUS r;
+ SL_UNICODE *sddl;
+
+ sddl = SlNewUnicode("D:P(A;;GA;;;SY)(A;;GA;;;BA)");
+
+ /*r = IoCreateDevice(sl->DriverObject, sizeof(SL_DEVICE *),
+ &u_device_name->String, FILE_DEVICE_TRANSPORT, 0, false, &dev_obj);*/
+
+ r = IoCreateDeviceSecure(sl->DriverObject, sizeof(SL_DEVICE *),
+ &u_device_name->String, FILE_DEVICE_TRANSPORT, 0, false, SlGetUnicode(sddl),
+ NULL, &dev_obj);
+
+ SlFreeUnicode(sddl);
+
+ if (NG(r))
+ {
+ dev_obj = NULL;
+ goto LABEL_CLEANUP;
+ }
+
+ r = IoCreateSymbolicLink(&u_sym_name->String, &u_device_name->String);
+ if (NG(r))
+ {
+ // May fail due to a bug in Windows Kernel
+ }
+
+ ret = SlZeroMalloc(sizeof(SL_DEVICE));
+ if (ret == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ ret->DeviceObject = dev_obj;
+ ret->DeviceName = u_device_name;
+ ret->SymbolicLinkName = u_sym_name;
+ *((SL_DEVICE **)dev_obj->DeviceExtension) = ret;
+
+ dev_obj->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ ret->OpenCloseLock = SlNewLock();
+
+LABEL_CLEANUP:
+ if (ret == NULL)
+ {
+ if (dev_obj != NULL)
+ {
+ IoDeleteDevice(dev_obj);
+ }
+ }
+
+ return ret;
+}
+
+// Device is opened
+NTSTATUS SlDeviceOpenProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Basic device
+ ret = STATUS_SUCCESS;
+ }
+ else
+ {
+ bool set_promisc = false;
+ volatile UINT *num_pending_oid_requests = NULL;
+ UINT64 v;
+ char event_name[SL_EVENT_NAME_SIZE];
+ char event_name_win32[SL_EVENT_NAME_SIZE];
+ SL_EVENT *event_object = NULL;
+ LARGE_INTEGER count;
+ LARGE_INTEGER freq;
+
+ count = KeQueryPerformanceCounter(&freq);
+
+ InterlockedIncrement(&sl->IntCounter1);
+
+ // Create a new event object
+ v = (UINT64)device_object + (UINT64)(++sl->IntCounter1) + *((UINT64 *)(&count));
+ sprintf(event_name, SL_EVENT_NAME, (UINT)v, (UINT)(v >> 32) + sl->IntCounter1);
+ sprintf(event_name_win32, SL_EVENT_NAME_WIN32, (UINT)v, (UINT)(v >> 32) + sl->IntCounter1);
+ event_object = SlNewEvent(event_name);
+
+ SlLock(dev->OpenCloseLock);
+ {
+ // Add to the opened file list
+ SlLockList(dev->FileList);
+ {
+ if (dev->Halting == false && dev->Adapter != NULL && dev->Adapter->Ready && dev->Adapter->Halt == false)
+ {
+ // Adapter device
+ SL_FILE *f = SlZeroMalloc(sizeof(SL_FILE));
+ NET_BUFFER_LIST_POOL_PARAMETERS p;
+
+ f->Device = dev;
+ f->Adapter = dev->Adapter;
+ f->FileObject = irp_stack->FileObject;
+
+ irp_stack->FileObject->FsContext = f;
+
+ SlAdd(dev->FileList, f);
+
+ ret = STATUS_SUCCESS;
+ set_promisc = true;
+
+ // Event
+ f->Event = event_object;
+ event_object = NULL;
+ strcpy(f->EventNameWin32, event_name_win32);
+
+ // Create a lock
+ f->RecvLock = SlNewLock();
+
+ // Create a NET_BUFFER_LIST pool
+ SlZero(&p, sizeof(p));
+ p.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ p.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+ p.fAllocateNetBuffer = true;
+ p.ContextSize = 32;
+ p.DataSize = SL_MAX_PACKET_SIZE;
+
+ f->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p);
+
+ num_pending_oid_requests = &dev->Adapter->NumPendingOidRequests;
+ }
+ }
+ SlUnlockList(dev->FileList);
+ }
+ SlUnlock(dev->OpenCloseLock);
+
+ if (event_object != NULL)
+ {
+ SlFreeEvent(event_object);
+ }
+
+ if (set_promisc)
+ {
+ // Enable promiscuous mode
+ UINT filter = NDIS_PACKET_TYPE_PROMISCUOUS;
+ SlSendOidRequest(dev->Adapter, true, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter));
+
+ // Wait until the number of OID requests being processed becomes 0
+ while ((*num_pending_oid_requests) != 0)
+ {
+ SlSleep(50);
+ }
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Send an OID request to the device
+void SlSendOidRequest(SL_ADAPTER *a, bool set, NDIS_OID oid, void *data, UINT size)
+{
+ NDIS_OID_REQUEST *t;
+ NDIS_STATUS ret;
+ // Validate arguments
+ if (a == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (a->Halt == false)
+ {
+ bool ok = false;
+
+ t = SlZeroMalloc(sizeof(NDIS_OID_REQUEST));
+
+ t->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
+ t->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
+ t->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
+
+ if (set == false)
+ {
+ t->RequestType = NdisRequestQueryInformation;
+ t->DATA.QUERY_INFORMATION.Oid = oid;
+ t->DATA.QUERY_INFORMATION.InformationBuffer = data;
+ t->DATA.QUERY_INFORMATION.InformationBufferLength = size;
+ }
+ else
+ {
+ t->RequestType = NdisRequestSetInformation;
+ t->DATA.SET_INFORMATION.Oid = oid;
+ t->DATA.SET_INFORMATION.InformationBuffer = SlClone(data, size);
+ t->DATA.SET_INFORMATION.InformationBufferLength = size;
+ }
+
+ SlLock(a->Lock);
+ {
+ if (a->AdapterHandle != NULL && a->Halt == false)
+ {
+ InterlockedIncrement(&a->NumPendingOidRequests);
+ ok = true;
+ }
+ }
+ SlUnlock(a->Lock);
+
+ if (ok)
+ {
+ ret = NdisOidRequest(a->AdapterHandle, t);
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ InterlockedDecrement(&a->NumPendingOidRequests);
+ if (set)
+ {
+ SlFree(t->DATA.SET_INFORMATION.InformationBuffer);
+ }
+ SlFree(t);
+ }
+ }
+ else
+ {
+ if (set)
+ {
+ SlFree(t->DATA.SET_INFORMATION.InformationBuffer);
+ }
+ SlFree(t);
+ }
+ }
+}
+
+// Device is closed
+NTSTATUS SlDeviceCloseProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Basic device
+ ret = STATUS_SUCCESS;
+ }
+ else
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (f != NULL)
+ {
+ bool clear_filter = false;
+
+ // Wait until the number of packet being sent becomes the zero
+ while (true)
+ {
+ if (f->NumSendingPacketets == 0)
+ {
+ break;
+ }
+
+ SlSleep(50);
+ }
+
+ SlLock(dev->OpenCloseLock);
+ {
+ // Delete the file from the list
+ SlLockList(dev->FileList);
+ {
+ SlDelete(dev->FileList, f);
+
+ if (SL_LIST_NUM(dev->FileList) == 0)
+ {
+ // Clear the filter when all files are closed
+ clear_filter = true;
+ }
+ }
+ SlUnlockList(dev->FileList);
+
+ if (dev->Adapter->Halt)
+ {
+ clear_filter = false;
+ }
+
+ if (clear_filter)
+ {
+ InterlockedIncrement(&dev->Adapter->NumPendingOidRequests);
+ }
+ }
+ SlUnlock(dev->OpenCloseLock);
+
+ if (clear_filter)
+ {
+ // Clear the filter when all files are closed
+ UINT filter = 0;
+ SlSendOidRequest(dev->Adapter, true, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter));
+ InterlockedDecrement(&dev->Adapter->NumPendingOidRequests);
+ }
+
+ // Release the event
+ SlFreeEvent(f->Event);
+
+ // Release the receive queue
+ if (true)
+ {
+ SL_PACKET *p = f->RecvPacketHead;
+
+ while (p != NULL)
+ {
+ SL_PACKET *p_next = p->Next;
+
+ SlFree(p);
+
+ p = p_next;
+ }
+ }
+
+ // Release the NET_BUFFER_LIST pool
+ NdisFreeNetBufferListPool(f->NetBufferListPool);
+
+ // Release the lock
+ SlFreeLock(f->RecvLock);
+
+ SlFree(f);
+
+ ret = STATUS_SUCCESS;
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Read procedure of the device
+NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ UINT ret_size = 0;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Return the adapter list in the case of basic device
+ if (irp_stack->Parameters.Read.Length >= sizeof(SL_ADAPTER_INFO_LIST))
+ {
+ SL_ADAPTER_INFO_LIST *dst = irp->UserBuffer;
+
+ if (dst != NULL)
+ {
+ MDL *mdl;
+
+ mdl = IoAllocateMdl(dst, irp_stack->Parameters.Read.Length, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ SlZero(dst, sizeof(SL_ADAPTER_INFO_LIST));
+
+ dst->Signature = SL_SIGNATURE;
+ dst->SeLowVersion = SL_VER;
+ dst->EnumCompleted = sl->IsEnumCompleted ? 8 : 1;
+
+ SlLockList(sl->AdapterList);
+ {
+ UINT i;
+
+ dst->NumAdapters = MIN(SL_LIST_NUM(sl->AdapterList), SL_MAX_ADAPTER_INFO_LIST_ENTRY);
+
+ for (i = 0;i < dst->NumAdapters;i++)
+ {
+ SL_ADAPTER *a = SL_LIST_DATA(sl->AdapterList, i);
+ SL_ADAPTER_INFO *d = &dst->Adapters[i];
+
+ d->MtuSize = a->MtuSize;
+ SlCopy(d->MacAddress, a->MacAddress, 6);
+ SlCopy(d->AdapterId, a->AdapterId, sizeof(a->AdapterId));
+ strcpy(d->FriendlyName, a->FriendlyName);
+ }
+ }
+ SlUnlockList(sl->AdapterList);
+
+ ret_size = sizeof(SL_ADAPTER_INFO);
+ ret = STATUS_SUCCESS;
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (irp_stack->Parameters.Read.Length == SL_EXCHANGE_BUFFER_SIZE)
+ {
+ UCHAR *buf = irp->UserBuffer;
+
+ if (dev->Halting || f->Adapter->Halt || buf == NULL)
+ {
+ // Halting
+ }
+ else
+ {
+ UINT num = 0;
+ bool left = true;
+ MDL *mdl;
+
+ mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ // Lock the receive queue
+ SlLock(f->RecvLock);
+ {
+ while (true)
+ {
+ SL_PACKET *q;
+ if (num >= SL_MAX_PACKET_EXCHANGE)
+ {
+ if (f->RecvPacketHead == NULL)
+ {
+ left = false;
+ }
+ break;
+ }
+ q = f->RecvPacketHead;
+ if (q != NULL)
+ {
+ f->RecvPacketHead = f->RecvPacketHead->Next;
+ q->Next = NULL;
+ f->NumRecvPackets--;
+
+ if (f->RecvPacketHead == NULL)
+ {
+ f->RecvPacketTail = NULL;
+ }
+ }
+ else
+ {
+ left = false;
+ break;
+ }
+ SL_SIZE_OF_PACKET(buf, num) = q->Size;
+ SlCopy(SL_ADDR_OF_PACKET(buf, num), q->Data, q->Size);
+ num++;
+ SlFree(q);
+ }
+ }
+ SlUnlock(f->RecvLock);
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+
+ SL_NUM_PACKET(buf) = num;
+ SL_LEFT_FLAG(buf) = left;
+
+ if (left == false)
+ {
+ SlReset(f->Event);
+ }
+ else
+ {
+ SlSet(f->Event);
+ }
+
+ ret = STATUS_SUCCESS;
+ ret_size = SL_EXCHANGE_BUFFER_SIZE;
+ }
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ irp->IoStatus.Information = ret_size;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Write procedure of the device
+NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+ UINT ret_size = 0;
+
+ if (dev->IsBasicDevice == false)
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (irp_stack->Parameters.Write.Length == SL_EXCHANGE_BUFFER_SIZE)
+ {
+ UCHAR *buf = irp->UserBuffer;
+
+ if (dev->Halting || dev->Adapter->Halt || buf == NULL)
+ {
+ // Halting
+ }
+ else
+ {
+ // Write the packet
+ MDL *mdl;
+ UINT num = SL_NUM_PACKET(buf);
+
+ mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
+ }
+
+ ret = true;
+ ret_size = SL_EXCHANGE_BUFFER_SIZE;
+
+ if (num >= 1 && num <= SL_MAX_PACKET_EXCHANGE)
+ {
+ UINT i, j;
+ NET_BUFFER_LIST *nbl_head = NULL;
+ NET_BUFFER_LIST *nbl_tail = NULL;
+ UINT num_packets = 0;
+ NDIS_HANDLE adapter_handle = NULL;
+
+ SlLock(f->Adapter->Lock);
+
+ if (f->Adapter->NumPendingSendPackets <= SL_MAX_PACKET_QUEUED)
+ {
+ // Admit to send only if the number of packets being transmitted does not exceed the specified limit
+ adapter_handle = f->Adapter->AdapterHandle;
+ }
+
+ if (adapter_handle != NULL)
+ {
+ // Lock the file list which opens the same adapter
+ SlLockList(dev->FileList);
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Lock the receive queue of other file lists
+ SlLock(other->RecvLock);
+
+ other->SetEventFlag = false;
+ }
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ UINT packet_size = SL_SIZE_OF_PACKET(buf, i);
+ UCHAR *packet_buf;
+ NET_BUFFER_LIST *nbl = NULL;
+ bool ok = false;
+
+ if (packet_size > SL_MAX_PACKET_SIZE)
+ {
+ packet_size = SL_MAX_PACKET_SIZE;
+ }
+ else if (packet_size < SL_PACKET_HEADER_SIZE)
+ {
+ packet_size = SL_PACKET_HEADER_SIZE;
+ }
+
+ packet_buf = (UCHAR *)SL_ADDR_OF_PACKET(buf, i);
+
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Insert into the receive queue of the other file lists
+ if (other->NumRecvPackets < SL_MAX_PACKET_QUEUED)
+ {
+ SL_PACKET *q = SlMalloc(sizeof(SL_PACKET));
+
+ SlCopy(q->Data, packet_buf, packet_size);
+ q->Size = packet_size;
+ q->Next = NULL;
+
+ if (other->RecvPacketHead == NULL)
+ {
+ other->RecvPacketHead = q;
+ }
+ else
+ {
+ other->RecvPacketTail->Next = q;
+ }
+
+ other->RecvPacketTail = q;
+
+ other->NumRecvPackets++;
+
+ other->SetEventFlag = true;
+ }
+ }
+ }
+
+ // Allocate a new NET_BUFFER_LIST
+ if (f->NetBufferListPool != NULL)
+ {
+ nbl = NdisAllocateNetBufferList(f->NetBufferListPool, 16, 0);
+
+ if (nbl != NULL)
+ {
+ nbl->SourceHandle = adapter_handle;
+ }
+ }
+
+ if (nbl != NULL)
+ {
+ // Get the NET_BUFFER from the NET_BUFFER_LIST
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
+
+ if (nb != NULL && OK(NdisRetreatNetBufferDataStart(nb, packet_size, 0, NULL)))
+ {
+ // Buffer copy
+ UCHAR *dst = NdisGetDataBuffer(nb, packet_size, NULL, 1, 0);
+
+ if (dst != NULL)
+ {
+ SlCopy(dst, packet_buf, packet_size);
+
+ ok = true;
+ }
+ else
+ {
+ NdisAdvanceNetBufferDataStart(nb, packet_size, false, NULL);
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ if (nbl != NULL)
+ {
+ NdisFreeNetBufferList(nbl);
+ }
+ }
+ else
+ {
+ if (nbl_head == NULL)
+ {
+ nbl_head = nbl;
+ }
+
+ if (nbl_tail != NULL)
+ {
+ NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
+ }
+
+ nbl_tail = nbl;
+
+ *((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl)) = f;
+
+ num_packets++;
+ }
+ }
+
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Release the receive queue of other file lists
+ SlUnlock(other->RecvLock);
+
+ // Set an event
+ if (other->SetEventFlag)
+ {
+ SlSet(other->Event);
+ }
+ }
+ }
+ SlUnlockList(dev->FileList);
+
+ if (nbl_head != NULL)
+ {
+ InterlockedExchangeAdd(&f->NumSendingPacketets, num_packets);
+ InterlockedExchangeAdd(&f->Adapter->NumPendingSendPackets, num_packets);
+
+ SlUnlock(f->Adapter->Lock);
+
+ NdisSendNetBufferLists(adapter_handle, nbl_head, 0, 0);
+ }
+ else
+ {
+ SlUnlock(f->Adapter->Lock);
+ }
+ }
+ else
+ {
+ SlUnlock(f->Adapter->Lock);
+ }
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+
+ irp->IoStatus.Information = ret_size;
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// IOCTL procedure of the device
+NTSTATUS SlDeviceIoControlProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+ UINT ret_size = 0;
+
+ if (dev->IsBasicDevice == false)
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ switch (irp_stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case SL_IOCTL_GET_EVENT_NAME:
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(SL_IOCTL_EVENT_NAME))
+ {
+ SL_IOCTL_EVENT_NAME *t = irp->UserBuffer;
+
+ if (t != NULL)
+ {
+ strcpy(t->EventNameWin32, f->EventNameWin32);
+
+ ret_size = sizeof(SL_IOCTL_EVENT_NAME);
+
+ ret = STATUS_SUCCESS;
+ }
+ }
+ break;
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ irp->IoStatus.Information = ret_size;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// NDIS bind notification procedure
+NDIS_STATUS SlNdisBindAdapterExProc(NDIS_HANDLE protocol_driver_context, NDIS_HANDLE bind_context, NDIS_BIND_PARAMETERS *bind_parameters)
+{
+ NDIS_STATUS ret = NDIS_STATUS_FAILURE;
+
+ InterlockedIncrement(&sl->NumBoundAdapters);
+
+ // Check the attributes of the adapter, and process only adapter which should be bound to
+ if (bind_parameters->MediaType == NdisMedium802_3 &&
+ bind_parameters->MacAddressLength == 6 &&
+// (bind_parameters->PhysicalMediumType == NdisPhysicalMedium802_3 || bind_parameters->PhysicalMediumType == 0) &&
+ bind_parameters->AccessType == NET_IF_ACCESS_BROADCAST &&
+ bind_parameters->DirectionType == NET_IF_DIRECTION_SENDRECEIVE &&
+ bind_parameters->ConnectionType == NET_IF_CONNECTION_DEDICATED)
+ {
+ // Open the adapter
+ NDIS_OPEN_PARAMETERS t;
+ NDIS_MEDIUM medium_array = {NdisMedium802_3};
+ SL_ADAPTER *a;
+ wchar_t adapter_id_tag[] = SL_ADAPTER_ID_PREFIX_W;
+
+ SlZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_OPEN_PARAMETERS;
+ t.Header.Revision = NDIS_OPEN_PARAMETERS_REVISION_1;
+ t.Header.Size = NDIS_SIZEOF_OPEN_PARAMETERS_REVSION_1;
+
+ t.AdapterName = bind_parameters->AdapterName;
+ t.MediumArray = &medium_array;
+ t.MediumArraySize = 1;
+ t.SelectedMediumIndex = &sl->DummyInt;
+ t.FrameTypeArray = NULL;
+ t.FrameTypeArraySize = 0;
+
+ a = SlZeroMalloc(sizeof(SL_ADAPTER));
+
+ a->Lock = SlNewLock();
+ a->AdapterName = SlNewUnicodeFromUnicodeString(bind_parameters->AdapterName);
+
+ SlCopy(a->AdapterId, a->AdapterName->String.Buffer, MIN(sizeof(a->AdapterId) - sizeof(wchar_t), a->AdapterName->String.Length));
+ SlCopy(a->AdapterId, adapter_id_tag, sizeof(adapter_id_tag) - sizeof(wchar_t));
+
+ SlCopy(a->MacAddress, bind_parameters->CurrentMacAddress, 6);
+ SlCopy(&a->BindParamCopy, bind_parameters, sizeof(NDIS_BIND_PARAMETERS));
+ a->BindingContext = bind_context;
+ a->MtuSize = bind_parameters->MtuSize;
+
+ a->IsOpenPending = true;
+
+ ret = NdisOpenAdapterEx(sl->ProtocolHandle, a, &t, bind_context, &a->AdapterHandle);
+ a->AdapterHandle2 = a->AdapterHandle;
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ a->IsOpenPending = false;
+ SlNdisOpenAdapterCompleteExProc(a, ret);
+ }
+ }
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ if (ret != NDIS_STATUS_SUCCESS)
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+ }
+
+ return ret;
+}
+
+// Open success notification procedure of NDIS adapter
+void SlNdisOpenAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS status)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ bool is_pending = a->IsOpenPending;
+ NDIS_HANDLE binding_context = a->BindingContext;
+
+ if (OK(status))
+ {
+ // Create an adapter device
+ SL_UNICODE *device_name = SlNewUnicode(SL_ADAPTER_DEVICE_NAME);
+ SL_UNICODE *symbolic_name = SlNewUnicode(SL_ADAPTER_DEVICE_NAME_SYMBOLIC);
+ SL_DEVICE *dev;
+
+ // Create a device name
+ SlCopy(device_name->String.Buffer + 8, a->AdapterId, sizeof(wchar_t) * 46);
+ SlCopy(symbolic_name->String.Buffer + 19, a->AdapterId, sizeof(wchar_t) * 46);
+
+ dev = SlNewDeviceUnicode(device_name, symbolic_name);
+
+ if (dev == NULL)
+ {
+ // Device creation failed
+ SlFreeUnicode(device_name);
+ SlFreeUnicode(symbolic_name);
+ }
+ else
+ {
+ // Create a file list
+ dev->FileList = SlNewList();
+ }
+ if (dev != NULL)
+ {
+ // Get the display name
+ SlSendOidRequest(a, false, OID_GEN_VENDOR_DESCRIPTION, a->FriendlyName,
+ sizeof(a->FriendlyName) - 1);
+
+ dev->Adapter = a;
+ a->Device = dev;
+
+ // Add this adapter to the adapter list
+ SlLockList(sl->AdapterList);
+ {
+ SlAdd(sl->AdapterList, a);
+ }
+ SlUnlockList(sl->AdapterList);
+ }
+ }
+ else
+ {
+ // Discard the adapter handle
+ a->AdapterHandle = NULL;
+
+ // Release the SL_ADAPTER
+ SlFreeAdapter(a);
+
+ a = NULL;
+ }
+
+ if (is_pending)
+ {
+ NdisCompleteBindAdapterEx(binding_context, status);
+ }
+
+ if (a != NULL)
+ {
+ a->Ready = true;
+ }
+
+ if (is_pending)
+ {
+ if (NG(status))
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+ }
+}
+
+// Release the SL_ADAPTER
+void SlFreeAdapter(SL_ADAPTER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ SlFreeUnicode(a->AdapterName);
+
+ SlFreeLock(a->Lock);
+
+ SlFree(a);
+}
+
+// NDIS unbind notification procedure
+NDIS_STATUS SlNdisUnbindAdapterExProc(NDIS_HANDLE unbind_context, NDIS_HANDLE protocol_binding_context)
+{
+ NDIS_STATUS ret;
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ UINT j;
+ NDIS_HANDLE adapter_handle = NULL;
+
+ if (a->Halt)
+ {
+ //SL_WHERE;
+ }
+
+ adapter_handle = a->AdapterHandle;
+ a->Halt = true;
+ if (a->Device != NULL)
+ {
+ a->Device->Halting = true;
+ }
+ a->AdapterHandle = NULL;
+
+ SlLock(a->Lock);
+ {
+ }
+ SlUnlock(a->Lock);
+
+ a->UnbindContext = unbind_context;
+ a->IsClosePending = true;
+
+ // Delete the adapter from the adapter list
+ SlLockList(sl->AdapterList);
+ {
+ SlDelete(sl->AdapterList, a);
+ }
+ SlUnlockList(sl->AdapterList);
+
+ for (j = 0;j < 32;j++)
+ {
+ // Wait until the number of OID requests of being processed by this adapter becomes zero
+ while (true)
+ {
+ UINT num;
+
+ num = a->NumPendingOidRequests;
+
+ if (num == 0)
+ {
+ break;
+ }
+ else
+ {
+ j = 0;
+ }
+
+ //SlSleep(50);
+ }
+
+ // Wait until the number of packets this adapter is transmitting becomes zero
+ while (true)
+ {
+ UINT num;
+
+ num = a->NumPendingSendPackets;
+
+ if (num == 0)
+ {
+ break;
+ }
+ else
+ {
+ j = 0;
+ }
+
+ //SlSleep(50);
+ }
+
+ }
+
+ ret = NdisCloseAdapterEx(adapter_handle);
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ a->IsClosePending = false;
+ SlNdisCloseAdapterCompleteExProc(a);
+
+ ret = NDIS_STATUS_SUCCESS;
+
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+
+ return ret;
+}
+
+// Close success notification procedure of NDIS adapter
+void SlNdisCloseAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ NDIS_HANDLE unbind_context = a->UnbindContext;
+ bool is_pending = a->IsClosePending;
+ UINT j;
+
+ if (is_pending)
+ {
+ NdisCompleteUnbindAdapterEx(unbind_context);
+ }
+
+ for (j = 0;j < 32;j++)
+ {
+ if (a->Device != NULL)
+ {
+ a->Device->Halting = true;
+
+ // Wait until the number of file handles that are associated with this device becomes zero
+ while (true)
+ {
+ UINT num_files = 0;
+
+ SlLock(a->Device->OpenCloseLock);
+ {
+ SlLockList(a->Device->FileList);
+ {
+ UINT i;
+ num_files = SL_LIST_NUM(a->Device->FileList);
+
+ for (i = 0;i < num_files;i++)
+ {
+ // Hit the associated event
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ if (f->FinalWakeUp == false)
+ {
+ SlSet(f->Event);
+ f->FinalWakeUp = true;
+ }
+ }
+ }
+ SlUnlockList(a->Device->FileList);
+ }
+ SlUnlock(a->Device->OpenCloseLock);
+
+ if (num_files == 0)
+ {
+ break;
+ }
+
+ SlSleep(50);
+ }
+ }
+ }
+
+ // Release the device
+ if (a->Device != NULL)
+ {
+ // Delete the file list
+ SlFreeList(a->Device->FileList);
+
+ SlFreeDevice(a->Device);
+ a->Device = NULL;
+ }
+
+ // Release the SL_ADAPTER
+ SlFreeAdapter(a);
+
+ if (is_pending)
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+}
+
+// NDIS PnP notification procedure
+NDIS_STATUS SlNdisNetPnPEventProc(NDIS_HANDLE protocol_binding_context, NET_PNP_EVENT_NOTIFICATION *net_pnp_event)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+
+ if (net_pnp_event != NULL)
+ {
+ if (net_pnp_event->NetPnPEvent.NetEvent == NetEventBindsComplete)
+ {
+ sl->IsEnumCompleted = true;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// NDIS uninstall procedure
+void SlNdisUninstallProc(void)
+{
+}
+
+// NDIS OID request completion notification procedure
+void SlNdisOidRequestCompleteProc(NDIS_HANDLE protocol_binding_context, NDIS_OID_REQUEST *oid_request, NDIS_STATUS status)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ bool no_not_free = false;
+
+ // Check the results
+ if (oid_request->RequestType == NdisRequestQueryInformation)
+ {
+ if (oid_request->DATA.QUERY_INFORMATION.Oid == OID_GEN_VENDOR_DESCRIPTION)
+ {
+ no_not_free = true;
+ }
+ }
+
+ // Release the memory
+ if (no_not_free == false)
+ {
+ SlFree(oid_request->DATA.SET_INFORMATION.InformationBuffer);
+ }
+
+ SlFree(oid_request);
+
+ // Counter subtraction
+ InterlockedDecrement(&a->NumPendingOidRequests);
+}
+
+// NDIS status notification procedure
+void SlNdisStatusExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS_INDICATION *status_indication)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+}
+
+// NDIS packet reception notification procedure
+void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists,
+ NDIS_PORT_NUMBER port_number, ULONG NumberOfNetBufferLists,
+ ULONG receive_flags)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ UINT i;
+ UINT return_flags = 0;
+ NET_BUFFER_LIST *nbl;
+ UCHAR *tmp_buffer;
+ UINT tmp_size;
+
+ if (net_buffer_lists == NULL || NumberOfNetBufferLists == 0)
+ {
+ return;
+ }
+
+ if (a->AdapterHandle2 == NULL)
+ {
+ a->AdapterHandle2 = a->AdapterHandle;
+ }
+
+ if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(receive_flags))
+ {
+ NDIS_SET_RETURN_FLAG(return_flags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
+ }
+
+ if (a->Halt || a->Device == NULL || a->Device->Halting || a->Ready == false || a->AdapterHandle == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ tmp_buffer = a->TmpBuffer;
+ tmp_size = sizeof(a->TmpBuffer);
+
+ nbl = net_buffer_lists;
+
+ SlLockList(a->Device->FileList);
+ {
+ if (a->Halt == false)
+ {
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ // Lock the receive queue
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ SlLock(f->RecvLock);
+ }
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+ bool is_vlan = false;
+ UCHAR vlan_tag[2];
+
+ if (NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo) != 0)
+ {
+ NDIS_NET_BUFFER_LIST_8021Q_INFO qinfo;
+ qinfo.Value = NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo);
+ if (qinfo.TagHeader.VlanId != 0)
+ {
+ USHORT tag_us;
+ is_vlan = true;
+
+ tag_us = (qinfo.TagHeader.UserPriority & 0x07 << 13) |
+ (qinfo.TagHeader.CanonicalFormatId & 0x01 << 12) |
+ (qinfo.TagHeader.VlanId & 0x0FFF);
+
+ vlan_tag[0] = ((UCHAR *)(&tag_us))[1];
+ vlan_tag[1] = ((UCHAR *)(&tag_us))[0];
+ }
+ }
+
+ while (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ if (size >= 14 && size <= tmp_size && size <= (UINT)((is_vlan == false) ? SL_MAX_PACKET_SIZE : (SL_MAX_PACKET_SIZE - 4)))
+ {
+ UCHAR *ptr = NdisGetDataBuffer(nb, size, tmp_buffer, 1, 0);
+
+ if (ptr != NULL)
+ {
+ // Insert the queue to all waiting files
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ if (f->NumRecvPackets < SL_MAX_PACKET_QUEUED)
+ {
+ SL_PACKET *q = SlMalloc(sizeof(SL_PACKET));
+
+ if (is_vlan == false)
+ {
+ // Normal packet
+ SlCopy(q->Data, ptr, size);
+ q->Size = size;
+ }
+ else
+ {
+ // Insert a tag in the case of IEEE802.1Q packet
+ SlCopy(q->Data, ptr, 12);
+ q->Data[12] = 0x81;
+ q->Data[13] = 0x00;
+ SlCopy(&q->Data[14], vlan_tag, 2);
+ SlCopy(&q->Data[16], &ptr[12], size - 12);
+
+ q->Size = size + 4;
+ }
+
+ q->Next = NULL;
+
+ if (f->RecvPacketHead == NULL)
+ {
+ f->RecvPacketHead = q;
+ }
+ else
+ {
+ f->RecvPacketTail->Next = q;
+ }
+
+ f->RecvPacketTail = q;
+
+ f->NumRecvPackets++;
+ }
+ }
+ }
+ }
+
+ nb = NET_BUFFER_NEXT_NB(nb);
+ }
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ }
+
+ // Hit the event
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ // Unlock the receive queue
+ SlUnlock(f->RecvLock);
+
+ SlSet(f->Event);
+ }
+ }
+ }
+ SlUnlockList(a->Device->FileList);
+
+LABEL_CLEANUP:
+
+ if (NDIS_TEST_RECEIVE_CAN_PEND(receive_flags))
+ {
+ NdisReturnNetBufferLists(a->AdapterHandle2, net_buffer_lists, return_flags);
+ }
+}
+
+// NDIS packet transmission completion notification procedure
+void SlNdisSendNetBufferListsCompleteProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists,
+ ULONG send_complete_flags)
+{
+ NET_BUFFER_LIST *nbl;
+
+ nbl = net_buffer_lists;
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER_LIST *current_nbl = nbl;
+ SL_FILE *f;
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ if (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ NdisAdvanceNetBufferDataStart(nb, size, false, NULL);
+ }
+
+ // Get a file context
+ f = *((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl));
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ NET_BUFFER_LIST_NEXT_NBL(current_nbl) = NULL;
+
+ // Release the NET_BUFFER_LIST
+ NdisFreeNetBufferList(current_nbl);
+
+ // Reduce the number of packets being sent by 1
+ InterlockedExchangeAdd(&f->NumSendingPacketets, (LONG)-1);
+ InterlockedExchangeAdd(&f->Adapter->NumPendingSendPackets, (LONG)-1);
+ }
+}
+
+// Crash
+void SlCrash(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+// Memory allocation
+void *SlMalloc(UINT size)
+{
+ NDIS_STATUS r;
+ void *p;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ // Allocate the non-paged memory
+ r = NdisAllocateMemoryWithTag(&p, size, 0);
+
+ if (NG(r))
+ {
+ return NULL;
+ }
+
+ return p;
+}
+
+// Clear to zero by allocating the memory
+void *SlZeroMalloc(UINT size)
+{
+ void *p = SlMalloc(size);
+ if (p == NULL)
+ {
+ // Memory allocation failure
+ return NULL;
+ }
+
+ // Clear to zero
+ SlZero(p, size);
+
+ return p;
+}
+
+// Release the memory
+void SlFree(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the memory
+ NdisFreeMemory(p, 0, 0);
+}
+
+// Memory zero clear
+void SlZero(void *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Clear
+ NdisZeroMemory(dst, size);
+}
+
+// Copy memory
+void SlCopy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Copy
+ NdisMoveMemory(dst, src, size);
+}
+
+// Create a lock
+SL_LOCK *SlNewLock()
+{
+ NDIS_SPIN_LOCK *spin_lock;
+
+ // Memory allocation
+ SL_LOCK *lock = SlZeroMalloc(sizeof(SL_LOCK));
+ if (lock == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize spin lock
+ spin_lock = &lock->spin_lock;
+
+ NdisAllocateSpinLock(spin_lock);
+
+ return lock;
+}
+
+// Lock
+void SlLock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisAcquireSpinLock(spin_lock);
+}
+
+// Unlock
+void SlUnlock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisReleaseSpinLock(spin_lock);
+}
+
+// Release the lock
+void SlFreeLock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisFreeSpinLock(spin_lock);
+
+ // Release the memory
+ SlFree(lock);
+}
+
+// Create an event
+SL_EVENT *SlNewEvent(char *name)
+{
+ SL_UNICODE *unicode_name;
+ SL_EVENT *event;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert to Unicode name
+ unicode_name = SlNewUnicode(name);
+ if (unicode_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ event = SlZeroMalloc(sizeof(SL_EVENT));
+ if (event == NULL)
+ {
+ SlFreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Create an event
+ event->event = IoCreateNotificationEvent(SlGetUnicode(unicode_name), &event->event_handle);
+ if (event->event == NULL)
+ {
+ SlFree(event);
+ SlFreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Initialize the event
+ KeInitializeEvent(event->event, NotificationEvent, FALSE);
+ KeClearEvent(event->event);
+
+ // Release the string
+ SlFreeUnicode(unicode_name);
+
+ return event;
+}
+
+// Release the event
+void SlFreeEvent(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ ZwClose(event->event_handle);
+
+ // Release the memory
+ SlFree(event);
+}
+
+// Set the event
+void SlSet(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeSetEvent(event->event, 0, FALSE);
+}
+
+// Reset the event
+void SlReset(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeResetEvent(event->event);
+}
+
+// Create by copying the Unicode
+SL_UNICODE *SlNewUnicodeFromUnicodeString(UNICODE_STRING *src)
+{
+ SL_UNICODE *u;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = SlZeroMalloc(sizeof(SL_UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ u->String.Length = u->String.MaximumLength = src->Length;
+
+ u->String.Buffer = SlZeroMalloc(src->Length);
+ SlCopy(u->String.Buffer, src->Buffer, src->Length);
+
+ return u;
+}
+
+// Create a Unicode
+SL_UNICODE *SlNewUnicode(char *str)
+{
+ SL_UNICODE *u;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = SlZeroMalloc(sizeof(SL_UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ // String initialization
+ NdisInitializeString(&u->String, str);
+
+ return u;
+}
+
+// Release the Unicode
+void SlFreeUnicode(SL_UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ // Release the string
+ NdisFreeString(u->String);
+
+ // Release the memory
+ SlFree(u);
+}
+
+// Get an Unicode
+NDIS_STRING *SlGetUnicode(SL_UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ return &u->String;
+}
+
+// Create a packet buffer
+SL_PACKET_BUFFER *SlNewPacketBuffer()
+{
+ SL_PACKET_BUFFER *p;
+ NET_BUFFER_LIST_POOL_PARAMETERS p1;
+
+ // Memory allocation
+ p = SlZeroMalloc(sizeof(SL_PACKET_BUFFER));
+
+ // Create a NET_BUFFER_LIST pool
+ SlZero(&p1, sizeof(p1));
+ p1.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ p1.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+ p1.fAllocateNetBuffer = TRUE;
+ p1.DataSize = SL_MAX_PACKET_SIZE;
+
+ p->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p1);
+
+ // Create a NET_BUFFER_LIST
+ p->NetBufferList = NdisAllocateNetBufferList(p->NetBufferListPool, 0, 0);
+
+ return p;
+}
+
+// Release the packet buffer
+void SlFreePacketBuffer(SL_PACKET_BUFFER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the NET_BUFFER_LIST
+ NdisFreeNetBufferList(p->NetBufferList);
+
+ // Release the NET_BUFFER_LIST pool
+ NdisFreeNetBufferListPool(p->NetBufferListPool);
+
+ // Release the memory
+ SlFree(p);
+}
+
+// Create a list
+SL_LIST *SlNewList()
+{
+ SL_LIST *o;
+
+ o = (SL_LIST *)SlZeroMalloc(sizeof(SL_LIST));
+
+ o->lock = SlNewLock();
+
+ o->num_item = 0;
+ o->num_reserved = SL_INIT_NUM_RESERVED;
+
+ o->p = (void **)SlZeroMalloc(sizeof(void *) * o->num_reserved);
+
+ return o;
+}
+
+// Add an element to the list
+void SlAdd(SL_LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = o->num_item;
+ o->num_item++;
+
+ if (o->num_item > o->num_reserved)
+ {
+ UINT old_num_reserved = o->num_reserved;
+ void *p_old = o->p;
+
+ o->num_reserved = o->num_reserved * 2;
+
+ o->p = SlZeroMalloc(sizeof(void *) * o->num_reserved);
+ SlCopy(o->p, p_old, sizeof(void *) * old_num_reserved);
+ SlFree(p_old);
+ }
+
+ o->p[i] = p;
+}
+
+// Delete the element from the list
+bool SlDelete(SL_LIST *o, void *p)
+{
+ UINT i, n;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < o->num_item;i++)
+ {
+ if (o->p[i] == p)
+ {
+ break;
+ }
+ }
+ if (i == o->num_item)
+ {
+ return false;
+ }
+
+ n = i;
+ for (i = n;i < (o->num_item - 1);i++)
+ {
+ o->p[i] = o->p[i + 1];
+ }
+ o->num_item--;
+
+ return true;
+}
+
+// Delete all elements from the list
+void SlDeleteAll(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->num_item = 0;
+}
+
+// Lock the list
+void SlLockList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlLock(o->lock);
+}
+
+// Unlock the list
+void SlUnlockList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlUnlock(o->lock);
+}
+
+// Release the list
+void SlFreeList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlFree(o->p);
+ SlFreeLock(o->lock);
+
+ SlFree(o);
+}
+
+// Clone the memory
+void *SlClone(void *p, UINT size)
+{
+ void *ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = SlMalloc(size);
+ SlCopy(ret, p, size);
+
+ return ret;
+}
+
+
+// Sleep
+void SlSleep(int milliSeconds)
+{
+ PKTIMER timer = SlMalloc(sizeof(KTIMER));
+ LARGE_INTEGER duetime;
+
+ duetime.QuadPart = (__int64)milliSeconds * -10000;
+ KeInitializeTimerEx(timer, NotificationTimer);
+ KeSetTimerEx(timer, duetime, 0, NULL);
+
+ KeWaitForSingleObject(timer, Executive, KernelMode, FALSE, NULL);
+
+ SlFree(timer);
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/SeLow.h b/src/SeLow/SeLow.h
new file mode 100644
index 00000000..40b6f922
--- /dev/null
+++ b/src/SeLow/SeLow.h
@@ -0,0 +1,361 @@
+// SoftEther VPN Source Code
+// SeLow - SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLow.h
+// Header of SeLow.c
+
+#ifndef SELOW_H
+#define SELOW_H
+
+// Win32 DDK related
+#ifndef CPU_64
+#define _X86_
+#else // CPU_64
+#ifndef NEO_IA64
+#define _AMD64_
+#define AMD64
+#else // NEO_IA64
+#define _IA64_
+#define IA64
+#endif // NEO_IA64
+#endif // CPU_64
+#define NDIS_MINIPORT_DRIVER
+// NDIS 6.2
+#define NDIS620_MINIPORT
+#define NDIS_SUPPORT_NDIS61 1
+#define NDIS_SUPPORT_NDIS620 1
+#define NEO_NDIS_MAJOR_VERSION 6
+#define NEO_NDIS_MINOR_VERSION 20
+#define NDIS_WDM 1
+
+#include <wdm.h>
+#include <wdmsec.h>
+#include <ndis.h>
+#include <stdio.h>
+#include <string.h>
+
+// OS determination
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX / Linux
+#endif
+
+
+// Type declaration
+#ifndef WINDOWS_H_INCLUDED
+#ifndef WIN9X
+typedef unsigned long BOOL;
+#endif // WIN9X
+#define TRUE 1
+#define FALSE 0
+#endif
+typedef unsigned long bool;
+#define true 1
+#define false 0
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef signed char CHAR;
+typedef unsigned long DWORD;
+#define INFINITE 0xFFFFFFFF
+
+#define LESS(a, max_value) ((a) < (max_value) ? (a) : (max_value))
+#define MORE(a, min_value) ((a) > (min_value) ? (a) : (min_value))
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+
+// Error checking macro
+#define OK(val) ((val) == STATUS_SUCCESS)
+#define NG(val) (!OK(val))
+
+#define MAX_PATH 260
+#define MAX_SIZE 512
+#define STD_SIZE 512
+
+#define SL_WHERE SlCrash(__LINE__, __LINE__, __LINE__, __LINE__)
+#define SL_CRUSH(x) SlCrash(__LINE__, (UINT)(x), (UINT)(x), (UINT)(x))
+
+// Common header
+#include "SeLowCommon.h"
+
+
+//// Utility data structure
+
+// Lock
+typedef struct SL_LOCK
+{
+ NDIS_SPIN_LOCK spin_lock;
+} SL_LOCK;
+
+// Event
+typedef struct SL_EVENT
+{
+ KEVENT *event;
+ HANDLE event_handle;
+} SL_EVENT;
+
+// Unicode string
+typedef struct SL_UNICODE
+{
+ UNICODE_STRING String;
+} SL_UNICODE;
+
+// NDIS packet buffer
+typedef struct SL_PACKET_BUFFER
+{
+ NDIS_HANDLE NetBufferListPool; // NET_BUFFER_LIST Pool
+ NET_BUFFER_LIST *NetBufferList; // NET_BUFFER_LIST
+} SL_PACKET_BUFFER;
+
+// List
+typedef struct SL_LIST
+{
+ UINT num_item, num_reserved;
+ void **p;
+ SL_LOCK *lock;
+} SL_LIST;
+
+#define SL_LIST_DATA(o, i) (((o) != NULL) ? ((o)->p[(i)]) : NULL)
+#define SL_LIST_NUM(o) (((o) != NULL) ? (o)->num_item : 0)
+#define SL_INIT_NUM_RESERVED 32
+
+//// SL data structure
+
+// Packet queue
+typedef struct SL_PACKET
+{
+ UCHAR Data[SL_MAX_PACKET_SIZE]; // Data
+ UINT Size; // Size
+
+ struct SL_PACKET *Next; // Next packet
+} SL_PACKET;
+
+// File context
+typedef struct SL_FILE
+{
+ struct SL_DEVICE *Device; // Device
+ struct SL_ADAPTER *Adapter; // Adapter
+ FILE_OBJECT *FileObject; // File object
+ SL_EVENT *Event; // Event
+ char EventNameWin32[SL_EVENT_NAME_SIZE]; // Win32 event name
+
+ SL_LOCK *RecvLock; // Receive lock
+ SL_PACKET *RecvPacketHead; // Head of the received packet
+ SL_PACKET *RecvPacketTail; // Tail of the received packet
+ UINT NumRecvPackets; // Number of items of the received packet queue
+ NDIS_HANDLE NetBufferListPool; // NET_BUFFER_LIST Pool
+ volatile UINT NumSendingPacketets; // Number of packets being transmitted
+ bool SetEventFlag; // Flag to set an event
+ bool FinalWakeUp;
+} SL_FILE;
+
+// Device context
+typedef struct SL_DEVICE
+{
+ DEVICE_OBJECT *DeviceObject; // Device object
+ SL_UNICODE *DeviceName; // Device name
+ SL_UNICODE *SymbolicLinkName; // Symbolic link name
+ volatile bool Halting; // Halting
+
+ bool IsBasicDevice; // Whether basic device
+ struct SL_ADAPTER *Adapter; // Adapter
+
+ SL_LIST *FileList; // File List
+ SL_LOCK *OpenCloseLock; // Open / Close lock of the device
+} SL_DEVICE;
+
+// Adapter context
+typedef struct SL_ADAPTER
+{
+ volatile bool Halt; // Halt flag
+ volatile bool Ready; // Ready flag
+ SL_UNICODE *AdapterName; // Adapter name
+ NDIS_BIND_PARAMETERS BindParamCopy; // Copy of the bind parameters
+ UCHAR MacAddress[6]; // MAC address
+ UINT MtuSize; // MTU size
+ wchar_t AdapterId[SL_ADAPTER_ID_LEN]; // Adapter ID
+ volatile bool IsOpenPending; // Whether Open is Pending
+ volatile bool IsClosePending; // Whether Close is Pending
+ NDIS_HANDLE BindingContext; // Binding context
+ NDIS_HANDLE AdapterHandle; // Handle of the adapter
+ NDIS_HANDLE AdapterHandle2; // Handle of the adapter (receive-only)
+ NDIS_HANDLE UnbindContext; // Unbind context
+ SL_LOCK *Lock; // Lock object
+ volatile UINT NumPendingOidRequests; // Number of running OID requests
+ volatile UINT NumPendingSendPackets; // Number of packets being transmitted
+ UCHAR TmpBuffer[SL_MAX_PACKET_SIZE]; // Temporally buffer size
+ char FriendlyName[256]; // Adapter name
+
+ SL_DEVICE *Device; // Handle of the device
+} SL_ADAPTER;
+
+// SL context
+typedef struct SL_CTX
+{
+ DRIVER_OBJECT *DriverObject; // Driver object
+ NDIS_HANDLE ProtocolHandle; // NDIS protocol handle
+ SL_DEVICE *BasicDevice; // Basic device
+ SL_LIST *AdapterList; // Adapter list
+
+ volatile UINT IntCounter1;
+ UINT DummyInt;
+ volatile bool IsEnumCompleted; // Enumeration completion flag
+ volatile UINT NumBoundAdapters;
+} SL_CTX;
+
+
+//// SL function
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path);
+
+NTSTATUS SlDeviceOpenProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceCloseProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceIoControlProc(DEVICE_OBJECT *device_object, IRP *irp);
+
+void SlUnloadProc(DRIVER_OBJECT *driver_object);
+
+NDIS_STATUS SlNdisBindAdapterExProc(NDIS_HANDLE protocol_driver_context, NDIS_HANDLE bind_context, NDIS_BIND_PARAMETERS *bind_parameters);
+NDIS_STATUS SlNdisUnbindAdapterExProc(NDIS_HANDLE unbind_context, NDIS_HANDLE protocol_binding_context);
+void SlNdisOpenAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS status);
+void SlNdisCloseAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context);
+NDIS_STATUS SlNdisNetPnPEventProc(NDIS_HANDLE protocol_binding_context, NET_PNP_EVENT_NOTIFICATION *net_pnp_event);
+void SlNdisUninstallProc(void);
+void SlNdisOidRequestCompleteProc(NDIS_HANDLE protocol_binding_context, NDIS_OID_REQUEST *oid_request, NDIS_STATUS status);
+void SlNdisStatusExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS_INDICATION *status_indication);
+void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists, NDIS_PORT_NUMBER port_number, ULONG NumberOfNetBufferLists, ULONG receive_flags);
+void SlNdisSendNetBufferListsCompleteProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists, ULONG send_complete_flags);
+
+SL_DEVICE *SlNewDevice(char *device_name, char *symbolic_link_name);
+SL_DEVICE *SlNewDeviceUnicode(SL_UNICODE *u_device_name, SL_UNICODE *u_sym_name);
+void SlFreeDevice(SL_DEVICE *dev);
+void SlFreeAdapter(SL_ADAPTER *a);
+
+void SlSendOidRequest(SL_ADAPTER *a, bool set, NDIS_OID oid, void *data, UINT size);
+
+//// Utility function
+void *SlMalloc(UINT size);
+void *SlZeroMalloc(UINT size);
+void SlFree(void *p);
+void SlCopy(void *dst, void *src, UINT size);
+void SlZero(void *dst, UINT size);
+SL_LOCK *SlNewLock();
+void SlLock(SL_LOCK *lock);
+void SlUnlock(SL_LOCK *lock);
+void SlFreeLock(SL_LOCK *lock);
+SL_EVENT *SlNewEvent(char *name);
+void SlFreeEvent(SL_EVENT *event);
+void SlSet(SL_EVENT *event);
+void SlReset(SL_EVENT *event);
+SL_UNICODE *SlNewUnicode(char *str);
+SL_UNICODE *SlNewUnicodeFromUnicodeString(UNICODE_STRING *src);
+void SlFreeUnicode(SL_UNICODE *u);
+NDIS_STRING *SlGetUnicode(SL_UNICODE *u);
+SL_PACKET_BUFFER *SlNewPacketBuffer();
+void SlFreePacketBuffer(SL_PACKET_BUFFER *p);
+void SlCrash(UINT a, UINT b, UINT c, UINT d);
+SL_LIST *SlNewList();
+void SlAdd(SL_LIST *o, void *p);
+bool SlDelete(SL_LIST *o, void *p);
+void SlDeleteAll(SL_LIST *o);
+void SlLockList(SL_LIST *o);
+void SlUnlockList(SL_LIST *o);
+void SlFreeList(SL_LIST *o);
+void *SlClone(void *p, UINT size);
+void SlSleep(int milliSeconds);
+
+
+
+
+#endif // SELOW_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/SeLow.rc b/src/SeLow/SeLow.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/SeLow/SeLow.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/SeLow/SeLow.vcproj b/src/SeLow/SeLow.vcproj
new file mode 100644
index 00000000..a7719953
--- /dev/null
+++ b/src/SeLow/SeLow.vcproj
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="SeLow"
+ ProjectGUID="{94CA5DD2-1543-42F6-9F96-EE7694DDC837}"
+ RootNamespace="SeLow"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="bufferoverflowK.lib wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\SeLow_x86.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignSeLowInfFiles x86&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="bufferoverflowK.lib wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\SeLow_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignSeLowInfFiles x64&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\SeLow.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLow.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLowCommon.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\SeLow.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/SeLow/SeLowCommon.h b/src/SeLow/SeLowCommon.h
new file mode 100644
index 00000000..7edfefbb
--- /dev/null
+++ b/src/SeLow/SeLowCommon.h
@@ -0,0 +1,175 @@
+// SoftEther VPN Source Code
+// SeLow - SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLowCommon.h
+// Common Header for Kernel Mode / User Mode
+
+//// Version number
+// Change this number every time functions are added or modified on the driver.
+// As long as this number does not change, installation of SeLow during the update
+// installation of the VPN Server / VPN Client / VPN Bridge is skipped.
+#define SL_VER 42
+
+// Constants
+#define SL_MAX_PACKET_SIZE 1560
+#define SL_MAX_PACKET_SIZE_ANNOUNCE 1514
+#define SL_MIN_PACKET_SIZE 14
+#define SL_PACKET_HEADER_SIZE 14
+#define SL_MAX_FRAME_SIZE (SL_MAX_PACKET_SIZE - SL_MIN_PACKET_SIZE)
+
+#define SL_PROTOCOL_NAME "SeLow"
+#define SL_EVENT_NAME_SIZE 128
+
+#define SL_ENUM_COMPLETE_GIVEUP_TICK (15 * 1000)
+
+// IOCTL
+#define SL_IOCTL_GET_EVENT_NAME CTL_CODE(0x8000, 1, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+// IOCTL data structure
+typedef struct SL_IOCTL_EVENT_NAME
+{
+ char EventNameWin32[SL_EVENT_NAME_SIZE]; // Event name
+} SL_IOCTL_EVENT_NAME;
+
+// Device ID
+#define SL_BASIC_DEVICE_NAME "\\Device\\SELOW_BASIC_DEVICE"
+#define SL_BASIC_DEVICE_NAME_SYMBOLIC "\\DosDevices\\Global\\SELOW_BASIC_DEVICE"
+#define SL_BASIC_DEVICE_FILENAME_WIN32 "\\\\.\\SELOW_BASIC_DEVICE"
+#define SL_ADAPTER_ID_PREFIX "SELOW_A_"
+#define SL_ADAPTER_ID_PREFIX_W L"SELOW_A_"
+#define SL_ADAPTER_DEVICE_NAME "\\Device\\SELOW_A_{00000000-0000-0000-0000-000000000000}"
+#define SL_ADAPTER_DEVICE_NAME_SYMBOLIC "\\DosDevices\\Global\\SELOW_A_{00000000-0000-0000-0000-000000000000}"
+#define SL_ADAPTER_DEVICE_FILENAME_WIN32 "\\\\.\\%s"
+
+// Event name
+#define SL_EVENT_NAME "\\BaseNamedObjects\\SELOW_EVENT_%u_%u"
+#define SL_EVENT_NAME_WIN32 "Global\\SELOW_EVENT_%u_%u"
+
+// Registry key
+#define SL_REG_KEY_NAME "SYSTEM\\CurrentControlSet\\services\\SeLow"
+#define SL_REG_VER_VALUE "SlVersion"
+
+// Adapter data
+#define SL_ADAPTER_ID_LEN 64
+typedef struct SL_ADAPTER_INFO
+{
+ wchar_t AdapterId[SL_ADAPTER_ID_LEN]; // Adapter ID
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding1[2];
+ UINT MtuSize; // MTU size
+ char FriendlyName[256]; // Display name
+ UCHAR Reserved[256]; // Reserved area
+} SL_ADAPTER_INFO;
+
+#define SL_MAX_ADAPTER_INFO_LIST_ENTRY 256
+#define SL_SIGNATURE 0xDEADBEEF
+
+typedef struct SL_ADAPTER_INFO_LIST
+{
+ UINT Signature; // Signature
+ UINT SeLowVersion; // Version of SeLow
+ UINT EnumCompleted; // Enumeration completion flag
+ UINT NumAdapters; // The total number of adapter
+ SL_ADAPTER_INFO Adapters[SL_MAX_ADAPTER_INFO_LIST_ENTRY]; // Array of adapter
+} SL_ADAPTER_INFO_LIST;
+
+
+// Packet data exchange related
+#define SL_MAX_PACKET_EXCHANGE 256 // Number of packets that can be exchanged at a time
+#define SL_MAX_PACKET_QUEUED 4096 // Maximum number of packets that can be queued
+#define SL_EX_SIZEOF_NUM_PACKET 4 // Packet count data (UINT)
+#define SL_EX_SIZEOF_LENGTH_PACKET 4 // Length data of the packet data (UINT)
+#define SL_EX_SIZEOF_LEFT_FLAG 4 // Flag to indicate that the packet is left
+#define SL_EX_SIZEOF_ONE_PACKET 1600 // Data area occupied by a packet data
+#define SL_EXCHANGE_BUFFER_SIZE (SL_EX_SIZEOF_NUM_PACKET + SL_EX_SIZEOF_LEFT_FLAG + \
+ (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET) * (SL_MAX_PACKET_EXCHANGE + 1))
+#define SL_NUM_PACKET(buf) (*((UINT *)((UCHAR *)buf + 0)))
+#define SL_SIZE_OF_PACKET(buf, i) (*((UINT *)((UCHAR *)buf + SL_EX_SIZEOF_NUM_PACKET + \
+ (i * (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET)))))
+#define SL_ADDR_OF_PACKET(buf, i) (((UINT *)((UCHAR *)buf + SL_EX_SIZEOF_NUM_PACKET + \
+ SL_EX_SIZEOF_LENGTH_PACKET + \
+ (i * (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET)))))
+#define SL_LEFT_FLAG(buf) SL_SIZE_OF_PACKET(buf, SL_MAX_PACKET_EXCHANGE)
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/resource.h b/src/SeLow/resource.h
new file mode 100644
index 00000000..1fdda11a
--- /dev/null
+++ b/src/SeLow/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Neo.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/See/DEBUG.H b/src/See/DEBUG.H
new file mode 100644
index 00000000..ef8174d4
--- /dev/null
+++ b/src/See/DEBUG.H
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
+
+
+#if DBG
+
+#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
+extern ULONG PacketDebugFlag;
+
+#define PACKET_DEBUG_LOUD 0x00000001 // debugging info
+#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+
+#define PACKET_DEBUG_INIT 0x00000100 // init debugging info
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
+#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_LOUD(A)
+
+#endif
+
+#endif /*#define __DEBUG_INCLUDE*/
diff --git a/src/See/Devioctl.h b/src/See/Devioctl.h
new file mode 100644
index 00000000..af8784bf
--- /dev/null
+++ b/src/See/Devioctl.h
@@ -0,0 +1,90 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+ Copyright (c) 1992-1993 Microsoft Corporation
+ Module Name:
+ devioctl.h
+ Revision History:
+ -- */
+// begin_winioctl
+#ifndef _DEVIOCTL_
+#define _DEVIOCTL_
+// begin_ntddk begin_nthal begin_ntifs
+//
+// Define the various device type values. Note that values used by Microsoft
+// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
+// by customers.
+//
+#define DEVICE_TYPE ULONG
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+//
+// Macro definition for defining IOCTL and FSCTL function control codes. Note
+// that function codes 0-2047 are reserved for Microsoft Corporation, and
+// 2048-4095 are reserved for customers.
+//
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+//
+// Define the method codes for how buffers are passed for I/O and FS controls
+//
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+//
+// Define the access check value for any access
+//
+//
+// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+// constants *MUST* always be in sync.
+//
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+// end_ntddk end_nthal end_ntifs
+#endif // _DEVIOCTL_
+// end_winioctl
diff --git a/src/See/Ntddndis.h b/src/See/Ntddndis.h
new file mode 100644
index 00000000..0b629806
--- /dev/null
+++ b/src/See/Ntddndis.h
@@ -0,0 +1,1400 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+ Copyright (c) 1990-1993 Microsoft Corporation
+ Module Name:
+ ntddndis.h
+ Abstract:
+ This is the include file that defines all constants and types for
+ accessing the Network driver interface device.
+ Author:
+ Steve Wood (stevewo) 27-May-1990
+ Revision History:
+ Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0.
+ Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures
+ Kyle Brandon (kyleb) 09/24/96 added general co ndis oids.
+ -- */
+#ifndef _NTDDNDIS_
+#define _NTDDNDIS_
+//
+// Device Name - this string is the name of the device. It is the name
+// that should be passed to NtOpenFile when accessing the device.
+//
+// Note: For devices that support multiple units, it should be suffixed
+// with the Ascii representation of the unit number.
+//
+#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN"
+//
+// NtDeviceIoControlFile IoControlCode values for this device.
+//
+// Warning: Remember that the low two bits of the code specify how the
+// buffers are passed to the driver!
+//
+#define _NDIS_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED )
+#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED )
+#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED )
+#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED )
+#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED )
+#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT )
+//
+// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for
+// this device.
+//
+//
+// This is the type of an NDIS OID value.
+//
+typedef ULONG NDIS_OID, *PNDIS_OID;
+//
+// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed
+// together (no padding is required since statistics all have
+// four or eight bytes of data).
+//
+typedef struct _NDIS_STATISTICS_VALUE {
+ NDIS_OID Oid;
+ ULONG DataLength;
+ UCHAR Data[1]; // variable length
+
+} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE;
+
+//
+// Structure used by TRANSLATE_NAME IOCTL
+//
+typedef struct _NET_PNP_ID {
+ ULONG ClassId;
+ ULONG Token;
+} NET_PNP_ID, *PNET_PNP_ID;
+
+typedef struct _NET_PNP_TRANSLATE_LIST {
+ ULONG BytesNeeded;
+ NET_PNP_ID IdArray[ANYSIZE_ARRAY];
+} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST;
+
+//
+// Structure used to define a self-contained variable data structure
+//
+typedef struct _NDIS_VAR_DATA_DESC {
+ USHORT Length; // # of octects of data
+
+ USHORT MaximumLength; // # of octects available
+
+ LONG Offset; // Offset of data relative to the descriptor
+
+} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC;
+
+//
+// Object Identifiers used by NdisRequest Query/Set Information
+//
+//
+// General Objects
+//
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+//
+// These are connection-oriented general OIDs.
+// These replace the above OIDs for connection-oriented media.
+//
+#define OID_GEN_CO_SUPPORTED_LIST 0x00010101
+#define OID_GEN_CO_HARDWARE_STATUS 0x00010102
+#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_CO_MEDIA_IN_USE 0x00010104
+#define OID_GEN_CO_LINK_SPEED 0x00010105
+#define OID_GEN_CO_VENDOR_ID 0x00010106
+#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
+#define OID_GEN_CO_DRIVER_VERSION 0x00010108
+#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
+#define OID_GEN_CO_MAC_OPTIONS 0x0001010A
+#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
+#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
+#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
+#define OID_GEN_CO_GET_TIME_CAPS 0x00010201
+#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202
+//
+// These are connection-oriented statistics OIDs.
+//
+#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101
+#define OID_GEN_CO_RCV_PDUS_OK 0x00020102
+#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
+#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
+#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
+#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201
+#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
+#define OID_GEN_CO_BYTES_XMIT 0x00020203
+#define OID_GEN_CO_BYTES_RCV 0x00020204
+#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
+#define OID_GEN_CO_NETCARD_LOAD 0x00020206
+//
+// These are objects for Connection-oriented media call-managers and are not
+// valid for ndis drivers. Under construction.
+//
+#define OID_CO_ADD_PVC 0xFF000001
+#define OID_CO_DELETE_PVC 0xFF000002
+#define OID_CO_GET_CALL_INFORMATION 0xFF000003
+#define OID_CO_ADD_ADDRESS 0xFF000004
+#define OID_CO_DELETE_ADDRESS 0xFF000005
+#define OID_CO_GET_ADDRESSES 0xFF000006
+#define OID_CO_ADDRESS_CHANGE 0xFF000007
+#define OID_CO_SIGNALING_ENABLED 0xFF000008
+#define OID_CO_SIGNALING_DISABLED 0xFF000009
+//
+// 802.3 Objects (Ethernet)
+//
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+//
+//
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+//
+// 802.5 Objects (Token-Ring)
+//
+#define OID_802_5_PERMANENT_ADDRESS 0x02010101
+#define OID_802_5_CURRENT_ADDRESS 0x02010102
+#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103
+#define OID_802_5_CURRENT_GROUP 0x02010104
+#define OID_802_5_LAST_OPEN_STATUS 0x02010105
+#define OID_802_5_CURRENT_RING_STATUS 0x02010106
+#define OID_802_5_CURRENT_RING_STATE 0x02010107
+#define OID_802_5_LINE_ERRORS 0x02020101
+#define OID_802_5_LOST_FRAMES 0x02020102
+#define OID_802_5_BURST_ERRORS 0x02020201
+#define OID_802_5_AC_ERRORS 0x02020202
+#define OID_802_5_ABORT_DELIMETERS 0x02020203
+#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204
+#define OID_802_5_FREQUENCY_ERRORS 0x02020205
+#define OID_802_5_TOKEN_ERRORS 0x02020206
+#define OID_802_5_INTERNAL_ERRORS 0x02020207
+//
+// FDDI Objects
+//
+#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101
+#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102
+#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103
+#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104
+#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105
+#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106
+#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107
+#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108
+#define OID_FDDI_ATTACHMENT_TYPE 0x03020101
+#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102
+#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103
+#define OID_FDDI_FRAME_ERRORS 0x03020104
+#define OID_FDDI_FRAMES_LOST 0x03020105
+#define OID_FDDI_RING_MGT_STATE 0x03020106
+#define OID_FDDI_LCT_FAILURES 0x03020107
+#define OID_FDDI_LEM_REJECTS 0x03020108
+#define OID_FDDI_LCONNECTION_STATE 0x03020109
+#define OID_FDDI_SMT_STATION_ID 0x03030201
+#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202
+#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203
+#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204
+#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205
+#define OID_FDDI_SMT_USER_DATA 0x03030206
+#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207
+#define OID_FDDI_SMT_MAC_CT 0x03030208
+#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209
+#define OID_FDDI_SMT_MASTER_CT 0x0303020A
+#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B
+#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C
+#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D
+#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E
+#define OID_FDDI_SMT_T_NOTIFY 0x0303020F
+#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210
+#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211
+#define OID_FDDI_SMT_PORT_INDEXES 0x03030212
+#define OID_FDDI_SMT_MAC_INDEXES 0x03030213
+#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214
+#define OID_FDDI_SMT_ECM_STATE 0x03030215
+#define OID_FDDI_SMT_CF_STATE 0x03030216
+#define OID_FDDI_SMT_HOLD_STATE 0x03030217
+#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218
+#define OID_FDDI_SMT_STATION_STATUS 0x03030219
+#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A
+#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B
+#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C
+#define OID_FDDI_SMT_SET_COUNT 0x0303021D
+#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E
+#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F
+#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220
+#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221
+#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222
+#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223
+#define OID_FDDI_MAC_CURRENT_PATH 0x03030224
+#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225
+#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226
+#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227
+#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228
+#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229
+#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A
+#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B
+#define OID_FDDI_MAC_INDEX 0x0303022C
+#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D
+#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E
+#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F
+#define OID_FDDI_MAC_T_REQ 0x03030230
+#define OID_FDDI_MAC_T_NEG 0x03030231
+#define OID_FDDI_MAC_T_MAX 0x03030232
+#define OID_FDDI_MAC_TVX_VALUE 0x03030233
+#define OID_FDDI_MAC_T_PRI0 0x03030234
+#define OID_FDDI_MAC_T_PRI1 0x03030235
+#define OID_FDDI_MAC_T_PRI2 0x03030236
+#define OID_FDDI_MAC_T_PRI3 0x03030237
+#define OID_FDDI_MAC_T_PRI4 0x03030238
+#define OID_FDDI_MAC_T_PRI5 0x03030239
+#define OID_FDDI_MAC_T_PRI6 0x0303023A
+#define OID_FDDI_MAC_FRAME_CT 0x0303023B
+#define OID_FDDI_MAC_COPIED_CT 0x0303023C
+#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D
+#define OID_FDDI_MAC_TOKEN_CT 0x0303023E
+#define OID_FDDI_MAC_ERROR_CT 0x0303023F
+#define OID_FDDI_MAC_LOST_CT 0x03030240
+#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241
+#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242
+#define OID_FDDI_MAC_LATE_CT 0x03030243
+#define OID_FDDI_MAC_RING_OP_CT 0x03030244
+#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245
+#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246
+#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247
+#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248
+#define OID_FDDI_MAC_RMT_STATE 0x03030249
+#define OID_FDDI_MAC_DA_FLAG 0x0303024A
+#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B
+#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C
+#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D
+#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E
+#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F
+#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250
+#define OID_FDDI_PATH_INDEX 0x03030251
+#define OID_FDDI_PATH_RING_LATENCY 0x03030252
+#define OID_FDDI_PATH_TRACE_STATUS 0x03030253
+#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254
+#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255
+#define OID_FDDI_PATH_CONFIGURATION 0x03030256
+#define OID_FDDI_PATH_T_R_MODE 0x03030257
+#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258
+#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259
+#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A
+#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B
+#define OID_FDDI_PORT_MY_TYPE 0x0303025C
+#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D
+#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E
+#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F
+#define OID_FDDI_PORT_CURRENT_PATH 0x03030260
+#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261
+#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262
+#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263
+#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264
+#define OID_FDDI_PORT_PMD_CLASS 0x03030265
+#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266
+#define OID_FDDI_PORT_INDEX 0x03030267
+#define OID_FDDI_PORT_MAINT_LS 0x03030268
+#define OID_FDDI_PORT_BS_FLAG 0x03030269
+#define OID_FDDI_PORT_PC_LS 0x0303026A
+#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B
+#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C
+#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D
+#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E
+#define OID_FDDI_PORT_LEM_CT 0x0303026F
+#define OID_FDDI_PORT_LER_CUTOFF 0x03030270
+#define OID_FDDI_PORT_LER_ALARM 0x03030271
+#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272
+#define OID_FDDI_PORT_PCM_STATE 0x03030273
+#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274
+#define OID_FDDI_PORT_LER_FLAG 0x03030275
+#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276
+#define OID_FDDI_SMT_STATION_ACTION 0x03030277
+#define OID_FDDI_PORT_ACTION 0x03030278
+#define OID_FDDI_IF_DESCR 0x03030279
+#define OID_FDDI_IF_TYPE 0x0303027A
+#define OID_FDDI_IF_MTU 0x0303027B
+#define OID_FDDI_IF_SPEED 0x0303027C
+#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D
+#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E
+#define OID_FDDI_IF_OPER_STATUS 0x0303027F
+#define OID_FDDI_IF_LAST_CHANGE 0x03030280
+#define OID_FDDI_IF_IN_OCTETS 0x03030281
+#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282
+#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283
+#define OID_FDDI_IF_IN_DISCARDS 0x03030284
+#define OID_FDDI_IF_IN_ERRORS 0x03030285
+#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286
+#define OID_FDDI_IF_OUT_OCTETS 0x03030287
+#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288
+#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289
+#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A
+#define OID_FDDI_IF_OUT_ERRORS 0x0303028B
+#define OID_FDDI_IF_OUT_QLEN 0x0303028C
+#define OID_FDDI_IF_SPECIFIC 0x0303028D
+//
+// WAN objects
+//
+#define OID_WAN_PERMANENT_ADDRESS 0x04010101
+#define OID_WAN_CURRENT_ADDRESS 0x04010102
+#define OID_WAN_QUALITY_OF_SERVICE 0x04010103
+#define OID_WAN_PROTOCOL_TYPE 0x04010104
+#define OID_WAN_MEDIUM_SUBTYPE 0x04010105
+#define OID_WAN_HEADER_FORMAT 0x04010106
+#define OID_WAN_GET_INFO 0x04010107
+#define OID_WAN_SET_LINK_INFO 0x04010108
+#define OID_WAN_GET_LINK_INFO 0x04010109
+#define OID_WAN_LINE_COUNT 0x0401010A
+#define OID_WAN_GET_BRIDGE_INFO 0x0401020A
+#define OID_WAN_SET_BRIDGE_INFO 0x0401020B
+#define OID_WAN_GET_COMP_INFO 0x0401020C
+#define OID_WAN_SET_COMP_INFO 0x0401020D
+#define OID_WAN_GET_STATS_INFO 0x0401020E
+//
+// LocalTalk objects
+//
+#define OID_LTALK_CURRENT_NODE_ID 0x05010102
+#define OID_LTALK_IN_BROADCASTS 0x05020101
+#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102
+#define OID_LTALK_OUT_NO_HANDLERS 0x05020201
+#define OID_LTALK_COLLISIONS 0x05020202
+#define OID_LTALK_DEFERS 0x05020203
+#define OID_LTALK_NO_DATA_ERRORS 0x05020204
+#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205
+#define OID_LTALK_FCS_ERRORS 0x05020206
+//
+// Arcnet objects
+//
+#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101
+#define OID_ARCNET_CURRENT_ADDRESS 0x06010102
+#define OID_ARCNET_RECONFIGURATIONS 0x06020201
+//
+// TAPI objects
+//
+#define OID_TAPI_ACCEPT 0x07030101
+#define OID_TAPI_ANSWER 0x07030102
+#define OID_TAPI_CLOSE 0x07030103
+#define OID_TAPI_CLOSE_CALL 0x07030104
+#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105
+#define OID_TAPI_CONFIG_DIALOG 0x07030106
+#define OID_TAPI_DEV_SPECIFIC 0x07030107
+#define OID_TAPI_DIAL 0x07030108
+#define OID_TAPI_DROP 0x07030109
+#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A
+#define OID_TAPI_GET_ADDRESS_ID 0x0703010B
+#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C
+#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D
+#define OID_TAPI_GET_CALL_INFO 0x0703010E
+#define OID_TAPI_GET_CALL_STATUS 0x0703010F
+#define OID_TAPI_GET_DEV_CAPS 0x07030110
+#define OID_TAPI_GET_DEV_CONFIG 0x07030111
+#define OID_TAPI_GET_EXTENSION_ID 0x07030112
+#define OID_TAPI_GET_ID 0x07030113
+#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114
+#define OID_TAPI_MAKE_CALL 0x07030115
+#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116
+#define OID_TAPI_OPEN 0x07030117
+#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118
+#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119
+#define OID_TAPI_SECURE_CALL 0x0703011A
+#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B
+#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C
+#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D
+#define OID_TAPI_SET_CALL_PARAMS 0x0703011E
+#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F
+#define OID_TAPI_SET_DEV_CONFIG 0x07030120
+#define OID_TAPI_SET_MEDIA_MODE 0x07030121
+#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122
+//
+// ATM Connection Oriented Ndis
+//
+#define OID_ATM_SUPPORTED_VC_RATES 0x08010101
+#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102
+#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103
+#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104
+#define OID_ATM_MAX_ACTIVE_VCS 0x08010105
+#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106
+#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107
+#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108
+#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109
+#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A
+#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B
+#define OID_ATM_SIGNALING_VPIVCI 0x08010201
+#define OID_ATM_ASSIGNED_VPI 0x08010202
+#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203
+#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204
+#define OID_ATM_ILMI_VPIVCI 0x08010205
+#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206
+#define OID_ATM_GET_NEAREST_FLOW 0x08010207
+#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208
+//
+// ATM specific statistics OIDs.
+//
+#define OID_ATM_RCV_CELLS_OK 0x08020101
+#define OID_ATM_XMIT_CELLS_OK 0x08020102
+#define OID_ATM_RCV_CELLS_DROPPED 0x08020103
+#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201
+#define OID_ATM_CELLS_HEC_ERROR 0x08020202
+#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203
+//
+// PCCA (Wireless) object
+//
+//
+// All WirelessWAN devices must support the following OIDs
+//
+#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101
+#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102
+#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103
+#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104
+#define OID_WW_GEN_INDICATION_REQUEST 0x09010105
+#define OID_WW_GEN_DEVICE_INFO 0x09010106
+#define OID_WW_GEN_OPERATION_MODE 0x09010107
+#define OID_WW_GEN_LOCK_STATUS 0x09010108
+#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109
+#define OID_WW_GEN_NETWORK_ID 0x0901010A
+#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B
+#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C
+#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D
+#define OID_WW_GEN_BASESTATION_ID 0x0901010E
+#define OID_WW_GEN_CHANNEL_ID 0x0901010F
+#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110
+#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111
+#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112
+#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113
+#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114
+#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115
+#define OID_WW_GEN_LATENCY 0x09010116
+#define OID_WW_GEN_BATTERY_LEVEL 0x09010117
+#define OID_WW_GEN_EXTERNAL_POWER 0x09010118
+//
+// Network Dependent OIDs - Mobitex:
+//
+#define OID_WW_MBX_SUBADDR 0x09050101
+// OID 0x09050102 is reserved and may not be used
+#define OID_WW_MBX_FLEXLIST 0x09050103
+#define OID_WW_MBX_GROUPLIST 0x09050104
+#define OID_WW_MBX_TRAFFIC_AREA 0x09050105
+#define OID_WW_MBX_LIVE_DIE 0x09050106
+#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107
+//
+// Network Dependent OIDs - Pinpoint:
+//
+#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101
+#define OID_WW_PIN_LAST_LOCATION 0x09090102
+#define OID_WW_PIN_LOC_FIX 0x09090103
+//
+// Network Dependent - CDPD:
+//
+#define OID_WW_CDPD_SPNI 0x090D0101
+#define OID_WW_CDPD_WASI 0x090D0102
+#define OID_WW_CDPD_AREA_COLOR 0x090D0103
+#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104
+#define OID_WW_CDPD_EID 0x090D0105
+#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106
+#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107
+#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108
+#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109
+#define OID_WW_CDPD_NEI 0x090D010A
+#define OID_WW_CDPD_NEI_STATE 0x090D010B
+#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C
+#define OID_WW_CDPD_SLEEP_MODE 0x090D010D
+#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E
+#define OID_WW_CDPD_TEI 0x090D010F
+#define OID_WW_CDPD_RSSI 0x090D0110
+//
+// Network Dependent - Ardis:
+//
+#define OID_WW_ARD_SNDCP 0x09110101
+#define OID_WW_ARD_TMLY_MSG 0x09110102
+#define OID_WW_ARD_DATAGRAM 0x09110103
+//
+// Network Dependent - DataTac:
+//
+#define OID_WW_TAC_COMPRESSION 0x09150101
+#define OID_WW_TAC_SET_CONFIG 0x09150102
+#define OID_WW_TAC_GET_STATUS 0x09150103
+#define OID_WW_TAC_USER_HEADER 0x09150104
+//
+// Network Dependent - Metricom:
+//
+#define OID_WW_MET_FUNCTION 0x09190101
+//
+// IRDA objects
+//
+#define OID_IRDA_RECEIVING 0x0A010100
+#define OID_IRDA_TURNAROUND_TIME 0x0A010101
+#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102
+#define OID_IRDA_LINK_SPEED 0x0A010103
+#define OID_IRDA_MEDIA_BUSY 0x0A010104
+#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200
+#define OID_IRDA_RATE_SNIFF 0x0A010201
+#define OID_IRDA_UNICAST_LIST 0x0A010202
+#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203
+#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204
+#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205
+//
+// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/
+// OID_GEN_MEDIA_IN_USE).
+//
+typedef enum _NDIS_MEDIUM {
+ NdisMedium802_3,
+ NdisMedium802_5,
+ NdisMediumFddi,
+ NdisMediumWan,
+ NdisMediumLocalTalk,
+ NdisMediumDix, // defined for convenience, not a real medium
+ NdisMediumArcnetRaw,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMediumWirelessWan,
+ NdisMediumIrda,
+ NdisMediumMax // Not a real medium, defined as an upper-bound
+} NDIS_MEDIUM, *PNDIS_MEDIUM;
+
+//
+// Hardware status codes (OID_GEN_HARDWARE_STATUS).
+//
+typedef enum _NDIS_HARDWARE_STATUS {
+ NdisHardwareStatusReady,
+ NdisHardwareStatusInitializing,
+ NdisHardwareStatusReset,
+ NdisHardwareStatusClosing,
+ NdisHardwareStatusNotReady
+} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS;
+
+//
+// this is the type passed in the OID_GEN_GET_TIME_CAPS request
+//
+typedef struct _GEN_GET_TIME_CAPS {
+ ULONG Flags; // Bits defined below
+
+ ULONG ClockPrecision;
+} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS;
+
+#define READABLE_LOCAL_CLOCK 0x000000001
+#define CLOCK_NETWORK_DERIVED 0x000000002
+#define CLOCK_PRECISION 0x000000004
+#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008
+#define TIMED_SEND_CAPABLE 0x000000010
+#define TIME_STAMP_CAPABLE 0x000000020
+//
+//
+// this is the type passed in the OID_GEN_GET_NETCARD_TIME request
+//
+typedef struct _GEN_GET_NETCARD_TIME {
+ ULONG ReadTime;
+} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME;
+
+//
+// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE).
+//
+typedef enum _NDIS_FDDI_ATTACHMENT_TYPE {
+ NdisFddiTypeIsolated = 1,
+ NdisFddiTypeLocalA,
+ NdisFddiTypeLocalB,
+ NdisFddiTypeLocalAB,
+ NdisFddiTypeLocalS,
+ NdisFddiTypeWrapA,
+ NdisFddiTypeWrapB,
+ NdisFddiTypeWrapAB,
+ NdisFddiTypeWrapS,
+ NdisFddiTypeCWrapA,
+ NdisFddiTypeCWrapB,
+ NdisFddiTypeCWrapS,
+ NdisFddiTypeThrough
+} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE;
+
+//
+// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE).
+//
+typedef enum _NDIS_FDDI_RING_MGT_STATE {
+ NdisFddiRingIsolated = 1,
+ NdisFddiRingNonOperational,
+ NdisFddiRingOperational,
+ NdisFddiRingDetect,
+ NdisFddiRingNonOperationalDup,
+ NdisFddiRingOperationalDup,
+ NdisFddiRingDirected,
+ NdisFddiRingTrace
+} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE;
+
+//
+// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE).
+//
+typedef enum _NDIS_FDDI_LCONNECTION_STATE {
+ NdisFddiStateOff = 1,
+ NdisFddiStateBreak,
+ NdisFddiStateTrace,
+ NdisFddiStateConnect,
+ NdisFddiStateNext,
+ NdisFddiStateSignal,
+ NdisFddiStateJoin,
+ NdisFddiStateVerify,
+ NdisFddiStateActive,
+ NdisFddiStateMaintenance
+} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE;
+
+//
+// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE).
+//
+typedef enum _NDIS_WAN_MEDIUM_SUBTYPE {
+ NdisWanMediumHub,
+ NdisWanMediumX_25,
+ NdisWanMediumIsdn,
+ NdisWanMediumSerial,
+ NdisWanMediumFrameRelay,
+ NdisWanMediumAtm,
+ NdisWanMediumSonet,
+ NdisWanMediumSW56K
+} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE;
+
+//
+// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT).
+//
+typedef enum _NDIS_WAN_HEADER_FORMAT {
+ NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID
+ NdisWanHeaderEthernet // emulation of ethernet header
+} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT;
+
+//
+// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE).
+//
+typedef enum _NDIS_WAN_QUALITY {
+ NdisWanRaw,
+ NdisWanErrorControl,
+ NdisWanReliable
+} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY;
+
+//
+// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE).
+//
+typedef enum _NDIS_802_5_RING_STATE {
+ NdisRingStateOpened = 1,
+ NdisRingStateClosed,
+ NdisRingStateOpening,
+ NdisRingStateClosing,
+ NdisRingStateOpenFailure,
+ NdisRingStateRingFailure
+} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE;
+
+//
+// Defines the state of the LAN media
+//
+typedef enum _NDIS_MEDIA_STATE {
+ NdisMediaStateConnected,
+ NdisMediaStateDisconnected
+} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority
+//
+typedef ULONG Priority_802_3; // 0-7 priority levels
+//
+// The following structure is used to query OID_GEN_CO_LINK_SPEED and
+// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current
+// link speed of the adapter. The second will return the minimum link speed
+// the adapter is capable of.
+//
+
+typedef struct _NDIS_CO_LINK_SPEED {
+ ULONG Outbound;
+ ULONG Inbound;
+} NDIS_CO_LINK_SPEED,
+
+*PNDIS_CO_LINK_SPEED;
+//
+// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).
+//
+#define NDIS_PACKET_TYPE_DIRECTED 0x0001
+#define NDIS_PACKET_TYPE_MULTICAST 0x0002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
+#define NDIS_PACKET_TYPE_BROADCAST 0x0008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
+#define NDIS_PACKET_TYPE_SMT 0x0040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000
+#define NDIS_PACKET_TYPE_GROUP 0x1000
+//
+// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS).
+//
+#define NDIS_RING_SIGNAL_LOSS 0x00008000
+#define NDIS_RING_HARD_ERROR 0x00004000
+#define NDIS_RING_SOFT_ERROR 0x00002000
+#define NDIS_RING_TRANSMIT_BEACON 0x00001000
+#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800
+#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400
+#define NDIS_RING_REMOVE_RECEIVED 0x00000200
+#define NDIS_RING_COUNTER_OVERFLOW 0x00000100
+#define NDIS_RING_SINGLE_STATION 0x00000080
+#define NDIS_RING_RING_RECOVERY 0x00000040
+//
+// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS).
+//
+#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001
+#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002
+#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004
+//
+// Ndis MAC option bits (OID_GEN_MAC_OPTIONS).
+//
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+//
+// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS.
+//
+#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001
+#ifdef IRDA
+//
+// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo
+// This is the per-packet info specified on a per-packet basis
+//
+typedef struct _NDIS_IRDA_PACKET_INFO {
+ UINT ExtraBOFs;
+ UINT MinTurnAroundTime;
+} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO;
+
+#endif
+#ifdef WIRELESS_WAN
+//
+// Wireless WAN structure definitions
+//
+//
+// currently defined Wireless network subtypes
+//
+typedef enum _NDIS_WW_NETWORK_TYPE {
+ NdisWWGeneric,
+ NdisWWMobitex,
+ NdisWWPinpoint,
+ NdisWWCDPD,
+ NdisWWArdis,
+ NdisWWDataTAC,
+ NdisWWMetricom,
+ NdisWWGSM,
+ NdisWWCDMA,
+ NdisWWTDMA,
+ NdisWWAMPS,
+ NdisWWInmarsat,
+ NdisWWpACT
+} NDIS_WW_NETWORK_TYPE;
+
+//
+// currently defined header formats
+//
+typedef enum _NDIS_WW_HEADER_FORMAT {
+ NdisWWDIXEthernetFrames,
+ NdisWWMPAKFrames,
+ NdisWWRDLAPFrames,
+ NdisWWMDC4800Frames
+} NDIS_WW_HEADER_FORMAT;
+
+//
+// currently defined encryption types
+//
+typedef enum _NDIS_WW_ENCRYPTION_TYPE {
+ NdisWWUnknownEncryption = -1,
+ NdisWWNoEncryption,
+ NdisWWDefaultEncryption
+} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE;
+
+//
+// OID_WW_GEN_INDICATION_REQUEST
+//
+typedef struct _NDIS_WW_INDICATION_REQUEST {
+ NDIS_OID Oid; // IN
+
+ UINT uIndicationFlag; // IN
+
+ UINT uApplicationToken; // IN OUT
+
+ HANDLE hIndicationHandle; // IN OUT
+
+ INT iPollingInterval; // IN OUT
+
+ NDIS_VAR_DATA_DESC InitialValue; // IN OUT
+
+ NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication
+
+ NDIS_VAR_DATA_DESC TriggerValue; // IN
+
+} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST;
+
+#define OID_INDICATION_REQUEST_ENABLE 0x0000
+#define OID_INDICATION_REQUEST_CANCEL 0x0001
+//
+// OID_WW_GEN_DEVICE_INFO
+//
+typedef struct _WW_DEVICE_INFO {
+ NDIS_VAR_DATA_DESC Manufacturer;
+ NDIS_VAR_DATA_DESC ModelNum;
+ NDIS_VAR_DATA_DESC SWVersionNum;
+ NDIS_VAR_DATA_DESC SerialNum;
+} WW_DEVICE_INFO, *PWW_DEVICE_INFO;
+
+//
+// OID_WW_GEN_OPERATION_MODE
+//
+typedef INT WW_OPERATION_MODE; // 0 = Normal mode
+ // 1 = Power saving mode
+ // -1 = mode unknown
+//
+// OID_WW_GEN_LOCK_STATUS
+//
+
+typedef INT WW_LOCK_STATUS; // 0 = unlocked
+ // 1 = locked
+ // -1 = unknown lock status
+//
+// OID_WW_GEN_DISABLE_TRANSMITTER
+//
+
+typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled
+ // 1 = transmitter disabled
+ // -1 = unknown value
+//
+// OID_WW_GEN_NETWORK_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID;
+//
+// OID_WW_GEN_PERMANENT_ADDRESS
+//
+typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS;
+//
+// OID_WW_GEN_CURRENT_ADDRESS
+//
+typedef struct _WW_CURRENT_ADDRESS {
+ NDIS_WW_HEADER_FORMAT Format;
+ NDIS_VAR_DATA_DESC Address;
+} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS;
+
+//
+// OID_WW_GEN_SUSPEND_DRIVER
+//
+typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational
+ // 1 = driver suspended
+//
+// OID_WW_GEN_BASESTATION_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID;
+//
+// OID_WW_GEN_CHANNEL_ID
+//
+typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID;
+//
+// OID_WW_GEN_ENCRYPTION_STATE
+//
+typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled
+ // 1 = if encryption is enabled
+//
+// OID_WW_GEN_CHANNEL_QUALITY
+//
+
+typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact,
+ // 1-100 = Quality of Channel (100 is highest quality).
+ // -1 = channel quality is unknown
+//
+// OID_WW_GEN_REGISTRATION_STATUS
+//
+
+typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied
+ // 1 = Registration pending
+ // 2 = Registered
+ // -1 = unknown registration status
+//
+// OID_WW_GEN_RADIO_LINK_SPEED
+//
+
+typedef UINT WW_RADIO_LINK_SPEED; // Bits per second.
+//
+// OID_WW_GEN_LATENCY
+//
+
+typedef UINT WW_LATENCY; // milliseconds
+//
+// OID_WW_GEN_BATTERY_LEVEL
+//
+
+typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage
+ // (100=fully charged)
+ // -1 = unknown battery level.
+//
+// OID_WW_GEN_EXTERNAL_POWER
+//
+
+typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected
+ // 1 = external power connected
+ // -1 = unknown
+//
+// OID_WW_MET_FUNCTION
+//
+
+typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION;
+//
+// OID_WW_TAC_COMPRESSION
+//
+typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression
+ // is being used.
+//
+// OID_WW_TAC_SET_CONFIG
+//
+
+typedef struct _WW_TAC_SETCONFIG {
+ NDIS_VAR_DATA_DESC RCV_MODE;
+ NDIS_VAR_DATA_DESC TX_CONTROL;
+ NDIS_VAR_DATA_DESC RX_CONTROL;
+ NDIS_VAR_DATA_DESC FLOW_CONTROL;
+ NDIS_VAR_DATA_DESC RESET_CNF;
+ NDIS_VAR_DATA_DESC READ_CNF;
+} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG;
+
+//
+// OID_WW_TAC_GET_STATUS
+//
+typedef struct _WW_TAC_GETSTATUS {
+ BOOLEAN Action; // Set = Execute command.
+
+ NDIS_VAR_DATA_DESC Command;
+ NDIS_VAR_DATA_DESC Option;
+ NDIS_VAR_DATA_DESC Response; // The response to the requested command
+ // - max. length of string is 256 octets.
+
+} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS;
+
+//
+// OID_WW_TAC_USER_HEADER
+//
+typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets.
+//
+// OID_WW_ARD_SNDCP
+//
+
+typedef struct _WW_ARD_SNDCP {
+ NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported.
+
+ INT BlockSize; // The block size used for SNDCP
+
+ INT Window; // The window size used in SNDCP
+
+} WW_ARD_SNDCP, *PWW_ARD_SNDCP;
+
+//
+// OID_WW_ARD_TMLY_MSG
+//
+typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel.
+//
+// OID_WW_ARD_DATAGRAM
+//
+
+typedef struct _WW_ARD_DATAGRAM {
+ BOOLEAN LoadLevel; // Byte that contains the load level info.
+
+ INT SessionTime; // Datagram session time remaining.
+
+ NDIS_VAR_DATA_DESC HostAddr; // Host address.
+
+ NDIS_VAR_DATA_DESC THostAddr; // Test host address.
+
+} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM;
+
+//
+// OID_WW_CDPD_SPNI
+//
+typedef struct _WW_CDPD_SPNI {
+ UINT SPNI[10]; //10 16-bit service provider network IDs
+
+ INT OperatingMode; // 0 = ignore SPNI,
+ // 1 = require SPNI from list,
+ // 2 = prefer SPNI from list.
+ // 3 = exclude SPNI from list.
+
+} WW_CDPD_SPNI, *PWW_CDPD_SPNI;
+
+//
+// OID_WW_CDPD_WASI
+//
+typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID {
+ UINT WASI[10]; //10 16-bit wide area service IDs
+
+ INT OperatingMode; // 0 = ignore WASI,
+ // 1 = Require WASI from list,
+ // 2 = prefer WASI from list
+ // 3 = exclude WASI from list.
+
+} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID;
+
+//
+// OID_WW_CDPD_AREA_COLOR
+//
+typedef INT WW_CDPD_AREA_COLOR;
+//
+// OID_WW_CDPD_TX_POWER_LEVEL
+//
+typedef UINT WW_CDPD_TX_POWER_LEVEL;
+//
+// OID_WW_CDPD_EID
+//
+typedef NDIS_VAR_DATA_DESC WW_CDPD_EID;
+//
+// OID_WW_CDPD_HEADER_COMPRESSION
+//
+typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression,
+ // 1 = always compress headers,
+ // 2 = compress headers if MD-IS does
+ // -1 = unknown
+//
+// OID_WW_CDPD_DATA_COMPRESSION
+//
+
+typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression,
+ // 1 = data compression enabled
+ // -1 = unknown
+//
+// OID_WW_CDPD_CHANNEL_SELECT
+//
+
+typedef struct _WW_CDPD_CHANNEL_SELECT {
+ UINT ChannelID; // channel number
+
+ UINT fixedDuration; // duration in seconds
+
+} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT;
+
+//
+// OID_WW_CDPD_CHANNEL_STATE
+//
+typedef enum _WW_CDPD_CHANNEL_STATE {
+ CDPDChannelNotAvail,
+ CDPDChannelScanning,
+ CDPDChannelInitAcquired,
+ CDPDChannelAcquired,
+ CDPDChannelSleeping,
+ CDPDChannelWaking,
+ CDPDChannelCSDialing,
+ CDPDChannelCSRedial,
+ CDPDChannelCSAnswering,
+ CDPDChannelCSConnected,
+ CDPDChannelCSSuspended
+} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE;
+
+//
+// OID_WW_CDPD_NEI
+//
+typedef enum _WW_CDPD_NEI_FORMAT {
+ CDPDNeiIPv4,
+ CDPDNeiCLNP,
+ CDPDNeiIPv6
+} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT;
+typedef enum _WW_CDPD_NEI_TYPE {
+ CDPDNeiIndividual,
+ CDPDNeiMulticast,
+ CDPDNeiBroadcast
+} WW_CDPD_NEI_TYPE;
+typedef struct _WW_CDPD_NEI {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_FORMAT NeiFormat;
+ WW_CDPD_NEI_TYPE NeiType;
+ WORD NeiGmid; // group member identifier, only
+ // meaningful if NeiType ==
+ // CDPDNeiMulticast
+
+ NDIS_VAR_DATA_DESC NeiAddress;
+} WW_CDPD_NEI;
+
+//
+// OID_WW_CDPD_NEI_STATE
+//
+typedef enum _WW_CDPD_NEI_STATE {
+ CDPDUnknown,
+ CDPDRegistered,
+ CDPDDeregistered
+} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE;
+typedef enum _WW_CDPD_NEI_SUB_STATE {
+ CDPDPending, // Registration pending
+ CDPDNoReason, // Registration denied - no reason given
+ CDPDMDISNotCapable, // Registration denied - MD-IS not capable of
+ // handling M-ES at this time
+ CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to
+ // use this subnetwork
+ CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient
+ // authentication credentials
+ CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported
+ // authentication credentials
+ CDPDUsageExceeded, // Registration denied - NEI has exceeded usage
+ // limitations
+ CDPDDeniedThisNetwork // Registration denied on this network, service
+ // may be obtained on alternate Service Provider
+ // network
+} WW_CDPD_NEI_SUB_STATE;
+typedef struct _WW_CDPD_NEI_REG_STATE {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_STATE NeiState;
+ WW_CDPD_NEI_SUB_STATE NeiSubState;
+} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE;
+
+//
+// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER
+//
+typedef struct _WW_CDPD_SERVICE_PROVIDER_ID {
+ UINT SPI[10]; //10 16-bit service provider IDs
+
+ INT OperatingMode; // 0 = ignore SPI,
+ // 1 = require SPI from list,
+ // 2 = prefer SPI from list.
+ // 3 = exclude SPI from list.
+
+} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID;
+
+//
+// OID_WW_CDPD_SLEEP_MODE
+//
+typedef INT WW_CDPD_SLEEP_MODE;
+//
+// OID_WW_CDPD_TEI
+//
+typedef ULONG WW_CDPD_TEI;
+//
+// OID_WW_CDPD_CIRCUIT_SWITCHED
+//
+typedef struct _WW_CDPD_CIRCUIT_SWITCHED {
+ INT service_preference; // -1 = unknown,
+ // 0 = always use packet switched CDPD,
+ // 1 = always use CS CDPD via AMPS,
+ // 2 = always use CS CDPD via PSTN,
+ // 3 = use circuit switched via AMPS only
+ // when packet switched is not available.
+ // 4 = use packet switched only when circuit
+ // switched via AMPS is not available.
+ // 5 = device manuf. defined service
+ // preference.
+ // 6 = device manuf. defined service
+ // preference.
+
+ INT service_status; // -1 = unknown,
+ // 0 = packet switched CDPD,
+ // 1 = circuit switched CDPD via AMPS,
+ // 2 = circuit switched CDPD via PSTN.
+
+ INT connect_rate; // CS connection bit rate (bits per second).
+ // 0 = no active connection,
+ // -1 = unknown
+ // Dial code last used to dial.
+
+ NDIS_VAR_DATA_DESC dial_code[20];
+
+ UINT sid; // Current AMPS system ID
+
+ INT a_b_side_selection; // -1 = unknown,
+ // 0 = no AMPS service
+ // 1 = AMPS "A" side channels selected
+ // 2 = AMPS "B" side channels selected
+
+ INT AMPS_channel; // -1= unknown
+ // 0 = no AMPS service.
+ // 1-1023 = AMPS channel number in use
+
+ UINT action; // 0 = no action
+ // 1 = suspend (hangup)
+ // 2 = dial
+
+ // Default dial code for CS CDPD service
+ // encoded as specified in the CS CDPD
+ // implementor guidelines.
+ NDIS_VAR_DATA_DESC default_dial[20];
+
+ // Number for the CS CDPD network to call
+ // back the mobile, encoded as specified in
+ // the CS CDPD implementor guidelines.
+ NDIS_VAR_DATA_DESC call_back[20];
+
+ UINT sid_list[10]; // List of 10 16-bit preferred AMPS
+ // system IDs for CS CDPD.
+
+ UINT inactivity_timer; // Wait time after last data before dropping
+ // call.
+ // 0-65535 = inactivity time limit (seconds).
+
+ UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED;
+typedef UINT WW_CDPD_RSSI;
+//
+// OID_WW_PIN_LOC_AUTHORIZE
+//
+typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized
+ // 1 = authorized
+ // -1 = unknown
+//
+// OID_WW_PIN_LAST_LOCATION
+// OID_WW_PIN_LOC_FIX
+//
+
+typedef struct _WW_PIN_LOCATION {
+ INT Latitude; // Latitude in hundredths of a second
+
+ INT Longitude; // Longitude in hundredths of a second
+
+ INT Altitude; // Altitude in feet
+
+ INT FixTime; // Time of the location fix, since midnight, local time (of the
+ // current day), in tenths of a second
+
+ INT NetTime; // Current local network time of the current day, since midnight,
+ // in tenths of a second
+
+ INT LocQuality; // 0-100 = location quality
+
+ INT LatReg; // Latitude registration offset, in hundredths of a second
+
+ INT LongReg; // Longitude registration offset, in hundredths of a second
+
+ INT GMTOffset; // Offset in minutes of the local time zone from GMT
+
+} WW_PIN_LOCATION, *PWW_PIN_LOCATION;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox
+//
+typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag
+//
+// OID_WW_MBX_SUBADDR
+//
+
+typedef struct _WW_MBX_PMAN {
+ BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN
+
+ UINT MAN;
+ UCHAR PASSWORD[8]; // Password should be null for Logout and indications.
+ // Maximum length of password is 8 chars.
+
+} WW_MBX_PMAN, *PWW_MBX_PMAN;
+
+//
+// OID_WW_MBX_FLEXLIST
+//
+typedef struct _WW_MBX_FLEXLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[7]; // List of MANs.
+
+} WW_MBX_FLEXLIST;
+
+//
+// OID_WW_MBX_GROUPLIST
+//
+typedef struct _WW_MBX_GROUPLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[15]; // List of MANs.
+
+} WW_MBX_GROUPLIST;
+
+//
+// OID_WW_MBX_TRAFFIC_AREA
+//
+typedef enum _WW_MBX_TRAFFIC_AREA {
+ unknown_traffic_area, // The driver has no information about the current traffic area.
+ in_traffic_area, // Mobile unit has entered a subscribed traffic area.
+ in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized.
+ unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized.
+} WW_MBX_TRAFFIC_AREA;
+
+//
+// OID_WW_MBX_LIVE_DIE
+//
+typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received
+ // 1 = LIVE last received
+ // -1 = unknown
+//
+// OID_WW_MBX_TEMP_DEFAULTLIST
+//
+
+typedef struct _WW_MBX_CHANNEL_PAIR {
+ UINT Mobile_Tx;
+ UINT Mobile_Rx;
+} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR;
+typedef struct _WW_MBX_TEMPDEFAULTLIST {
+ UINT Length;
+ WW_MBX_CHANNEL_PAIR ChannelPair[1];
+} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST;
+
+#endif // WIRELESS_WAN
+#endif // _NTDDNDIS_
diff --git a/src/See/Ntddpack.h b/src/See/Ntddpack.h
new file mode 100644
index 00000000..30945c1e
--- /dev/null
+++ b/src/See/Ntddpack.h
@@ -0,0 +1,26 @@
+
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+#include "devioctl.h"
+/*#include <packon.h> */
+struct _PACKET_OID_DATA {
+ ULONG Oid;
+ ULONG Length;
+ UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL 0x8000
+#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/src/See/Openclos.c b/src/See/Openclos.c
new file mode 100644
index 00000000..adb9bf22
--- /dev/null
+++ b/src/See/Openclos.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "debug.h"
+#include "packet.h"
+
+static NDIS_MEDIUM MediumArray[] = {
+ NdisMedium802_3,
+// NdisMediumWan,
+ NdisMediumFddi,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMedium802_5
+};
+
+#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
+
+ULONG NamedEventsCounter=0;
+
+//Itoa. Replaces the buggy RtlIntegerToUnicodeString
+void PacketItoa(UINT n,PUCHAR buf){
+int i;
+
+ for(i=0;i<20;i+=2){
+ buf[18-i]=(n%10)+48;
+ buf[19-i]=0;
+ n/=10;
+ }
+
+}
+
+/// Global start time. Used as an absolute reference for timestamp conversion.
+struct time_conv G_Start_Time = {
+ 0,
+ {0, 0},
+};
+
+UINT n_Opened_Instances = 0;
+
+NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+
+ PDEVICE_EXTENSION DeviceExtension;
+
+ POPEN_INSTANCE Open;
+
+ PIO_STACK_LOCATION IrpSp;
+
+ NDIS_STATUS Status;
+ NDIS_STATUS ErrorStatus;
+ UINT i;
+ PCHAR EvName;
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ // allocate some memory for the open structure
+ Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
+
+ if (Open==NULL) {
+ // no memory
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Open,
+ sizeof(OPEN_INSTANCE)
+ );
+
+
+ EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\SEE0000000000"), '1OWA');
+
+ if (EvName==NULL) {
+ // no memory
+ ExFreePool(Open);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // Save or open here
+ IrpSp->FileObject->FsContext=Open;
+
+ Open->DeviceExtension=DeviceExtension;
+
+
+ // Save the Irp here for the completeion routine to retrieve
+ Open->OpenCloseIrp=Irp;
+
+ // Allocate a packet pool for our xmit and receive packets
+ NdisAllocatePacketPool(
+ &Status,
+ &Open->PacketPool,
+ TRANSMIT_PACKETS,
+ sizeof(PACKET_RESERVED));
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
+
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ RtlCopyBytes(EvName,L"\\BaseNamedObjects\\SEE0000000000",sizeof(L"\\BaseNamedObjects\\SEE0000000000"));
+
+ //Create the string containing the name of the read event
+ RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
+
+ PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
+
+ InterlockedIncrement(&NamedEventsCounter);
+
+ IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
+
+ //allocate the event objects
+ Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
+ if(Open->ReadEvent==NULL){
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
+ KeClearEvent(Open->ReadEvent);
+ NdisInitializeEvent(&Open->WriteEvent);
+ NdisInitializeEvent(&Open->IOEvent);
+ NdisInitializeEvent(&Open->DumpEvent);
+ NdisAllocateSpinLock(&Open->MachineLock);
+ NdisAllocateSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+
+ // list to hold irp's want to reset the adapter
+ InitializeListHead(&Open->ResetIrpList);
+
+
+ // Initialize the request list
+ KeInitializeSpinLock(&Open->RequestSpinLock);
+ InitializeListHead(&Open->RequestList);
+
+ // Initializes the extended memory of the NPF machine
+ Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
+ if((Open->mem_ex.buffer) == NULL)
+ {
+ // no memory
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
+ RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
+
+ //
+ // Initialize the open instance
+ //
+// Open->BufSize = 0;
+// Open->Buffer = NULL;
+// Open->Bhead = 0;
+// Open->Btail = 0;
+// (INT)Open->BLastByte = -1;
+// Open->Dropped = 0; //reset the dropped packets counter
+// Open->Received = 0; //reset the received packets counter
+// Open->Accepted = 0; //reset the accepted packets counter
+ Open->bpfprogram = NULL; //reset the filter
+ Open->mode = MODE_CAPT;
+ Open->Nbytes.QuadPart = 0;
+ Open->Npackets.QuadPart = 0;
+ Open->Nwrites = 1;
+ Open->Multiple_Write_Counter = 0;
+ Open->MinToCopy = 0;
+ Open->TimeOut.QuadPart = (LONGLONG)1;
+ Open->Bound = TRUE;
+ Open->DumpFileName.Buffer = NULL;
+ Open->DumpFileHandle = NULL;
+ Open->tme.active = TME_NONE_ACTIVE;
+ Open->DumpLimitReached = FALSE;
+ Open->MaxFrameSize = 0;
+ Open->WriterSN=0;
+ Open->ReaderSN=0;
+ Open->Size=0;
+
+
+
+ //allocate the spinlock for the statistic counters
+ NdisAllocateSpinLock(&Open->CountersLock);
+
+ //allocate the spinlock for the buffer pointers
+ // NdisAllocateSpinLock(&Open->BufLock);
+
+ //
+ // link up the request stored in our open block
+ //
+ for (i=0;i<MAX_REQUESTS;i++) {
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &Open->Requests[i].ListElement,
+ &Open->RequestSpinLock);
+
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ //
+ // Try to open the MAC
+ //
+ IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
+
+ NdisOpenAdapter(
+ &Status,
+ &ErrorStatus,
+ &Open->AdapterHandle,
+ &Open->Medium,
+ MediumArray,
+ NUM_NDIS_MEDIA,
+ DeviceExtension->NdisProtocolHandle,
+ Open,
+ &DeviceExtension->AdapterName,
+ 0,
+ NULL);
+
+ IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus)
+{
+
+ PIRP Irp;
+ POPEN_INSTANCE Open;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST MaxSizeReq;
+ NDIS_STATUS ReqStatus;
+
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ //
+ // get the open irp
+ //
+ Irp=Open->OpenCloseIrp;
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+
+ ZwClose(Open->ReadEventHandle);
+
+
+ ExFreePool(Open);
+ }
+ else {
+ NdisAcquireSpinLock(&Opened_Instances_Lock);
+ n_Opened_Instances++;
+ NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+ IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+ // Get the absolute value of the system boot time.
+ // This is used for timestamp conversion.
+ TIME_SYNCHRONIZE(&G_Start_Time);
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
+
+ if (RequestListEntry == NULL)
+ {
+
+ Open->MaxFrameSize = 1560; // Assume Ethernet
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+ }
+
+ MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
+ MaxSizeReq->Irp = Irp;
+ MaxSizeReq->Internal = TRUE;
+
+
+ MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
+
+
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
+
+ // submit the request
+ NdisRequest(
+ &ReqStatus,
+ Open->AdapterHandle,
+ &MaxSizeReq->Request);
+
+
+ if (ReqStatus != NDIS_STATUS_PENDING) {
+ NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
+ }
+
+ return;
+
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+
+ POPEN_INSTANCE Open;
+ NDIS_STATUS Status;
+ PIO_STACK_LOCATION IrpSp;
+ LARGE_INTEGER ThreadDelay;
+
+ IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Open=IrpSp->FileObject->FsContext;
+
+ // Reset the buffer size. This tells the dump thread to stop.
+// Open->BufSize = 0;
+
+ if( Open->Bound == FALSE){
+
+ NdisWaitEvent(&Open->IOEvent,10000);
+
+ // Free the filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+#endif
+
+ //free the buffer
+// Open->BufSize=0;
+// if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
+
+ if (Open->Size > 0)
+ ExFreePool(Open->CpuData[0].Buffer);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ // Free the string with the name of the dump file
+ if(Open->DumpFileName.Buffer!=NULL)
+ ExFreePool(Open->DumpFileName.Buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+ ExFreePool(Open);
+
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return(STATUS_SUCCESS);
+ }
+
+ // Unfreeze the consumer
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ // Save the IRP
+ Open->OpenCloseIrp = Irp;
+
+ IoMarkIrpPending(Irp);
+
+ // If this instance is in dump mode, complete the dump and close the file
+ if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
+
+ NTSTATUS wres;
+
+ ThreadDelay.QuadPart = -50000000;
+ // Wait the completion of the thread
+ wres = KeWaitForSingleObject(Open->DumpThreadObject,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ &ThreadDelay);
+
+ ObDereferenceObject(Open->DumpThreadObject);
+
+
+ // Flush and close the dump file
+ NPF_CloseDumpFile(Open);
+ }
+
+ // Destroy the read Event
+ ZwClose(Open->ReadEventHandle);
+
+ // Close the adapter
+ NdisCloseAdapter(
+ &Status,
+ Open->AdapterHandle
+ );
+
+ if (Status != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ Status
+ );
+ return STATUS_SUCCESS;
+
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ // free the allocated structures only if the instance is still bound to the adapter
+ if(Open->Bound == TRUE){
+
+ // Free the filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+#endif // __NPF_x86__
+
+ //free the buffer
+// Open->BufSize = 0;
+// if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
+
+ if (Open->Size > 0)
+ ExFreePool(Open->CpuData[0].Buffer);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ Irp=Open->OpenCloseIrp;
+
+ // Free the string with the name of the dump file
+ if(Open->DumpFileName.Buffer!=NULL)
+ ExFreePool(Open->DumpFileName.Buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+ ExFreePool(Open);
+
+ // Complete the request only if the instance is still bound to the adapter
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ else
+ NdisSetEvent(&Open->IOEvent);
+
+ // Decrease the counter of open instances
+ NdisAcquireSpinLock(&Opened_Instances_Lock);
+ n_Opened_Instances--;
+ NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+ IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+ if(n_Opened_Instances == 0){
+ // Force a synchronization at the next NPF_Open().
+ // This hopefully avoids the synchronization issues caused by hibernation or standby.
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+ }
+
+ return;
+
+}
+//-------------------------------------------------------------------
+
+#ifdef NDIS50
+NDIS_STATUS
+NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
+{
+ IF_LOUD(DbgPrint("NPF: PowerChange\n");)
+
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+
+ TIME_SYNCHRONIZE(&G_Start_Time);
+
+ return STATUS_SUCCESS;
+}
+#endif
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ )
+{
+ IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ )
+{
+ POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
+ NDIS_STATUS lStatus;
+
+ IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
+
+ // Reset the buffer size. This tells the dump thread to stop.
+// Open->BufSize=0;
+
+ NdisResetEvent(&Open->IOEvent);
+
+ // This open instance is no more bound to the adapter, set Bound to False
+ InterlockedExchange( (PLONG) &Open->Bound, FALSE );
+
+ // Awake a possible pending read on this instance
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ // If this instance is in dump mode, complete the dump and close the file
+ if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
+ NPF_CloseDumpFile(Open);
+
+ // Destroy the read Event
+ ZwClose(Open->ReadEventHandle);
+
+ // close the adapter
+ NdisCloseAdapter(
+ &lStatus,
+ Open->AdapterHandle
+ );
+
+ if (lStatus != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ lStatus
+ );
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+
+ }
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ PLIST_ENTRY ResetListEntry;
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+
+ //
+ // remove the reset IRP from the list
+ //
+ ResetListEntry=ExInterlockedRemoveHeadList(
+ &Open->ResetIrpList,
+ &Open->RequestSpinLock
+ );
+
+#if DBG
+ if (ResetListEntry == NULL) {
+ DbgBreakPoint();
+ return;
+ }
+#endif
+
+ Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
+
+ return;
+
+}
diff --git a/src/See/Packet.c b/src/See/Packet.c
new file mode 100644
index 00000000..a3718aae
--- /dev/null
+++ b/src/See/Packet.c
@@ -0,0 +1,1607 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "ntddpack.h"
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "win_bpf_filter_init.h"
+
+#if DBG
+// Declare the global debug flag for this driver.
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+
+#endif
+
+PDEVICE_EXTENSION GlobalDeviceExtension;
+
+//
+// Global strings
+//
+NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("SEE_");
+NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
+NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
+NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
+NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
+
+/// Global variable that points to the names of the bound adapters
+WCHAR* bindP = NULL;
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+extern NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+ULONG NCpu = 1;
+
+ULONG TimestampMode;
+UINT g_SendPacketFlags = 0;
+
+
+// Crush now
+void Crush(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x3f000000 + a, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+//
+// Packet Driver's entry routine.
+//
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
+ PDEVICE_OBJECT DeviceObject = NULL;
+ PDEVICE_EXTENSION DeviceExtension = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS ErrorCode = STATUS_SUCCESS;
+ NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
+ ULONG DevicesCreated=0;
+ NDIS_HANDLE NdisProtocolHandle;
+ WCHAR* bindT;
+ PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
+ UNICODE_STRING macName;
+ ULONG OsMajorVersion, OsMinorVersion;
+
+ PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
+ //
+ // Define the correct flag to skip the loopback packets, according to the OS
+ //
+ if((OsMajorVersion == 5) && (OsMinorVersion == 0))
+ {
+ // Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
+ }
+ else
+ {
+ // Windows XP, 2003 and follwing want only NDIS_FLAGS_DONT_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK;
+ }
+
+ if (((OsMajorVersion == 6) && (OsMinorVersion >= 1)) || (OsMajorVersion >= 7))
+ {
+ // Use KeQueryActiveProcessors to get the number of CPUs in Windows 7 or later
+ KAFFINITY cpus = KeQueryActiveProcessors();
+ NCpu = 0;
+
+ while (cpus)
+ {
+ if (cpus % 2)
+ {
+ NCpu++;
+ }
+
+ cpus = cpus / 2;
+ }
+ }
+ else
+ {
+ // Use NdisSystemProcessorCount in Windows Vista or earlier
+ NCpu = NdisSystemProcessorCount();
+ }
+
+
+ ReadTimeStampModeFromRegistry(RegistryPath);
+
+ IF_LOUD(DbgPrint("%ws",RegistryPath->Buffer);)
+
+ IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
+
+ RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+#ifdef NDIS50
+ ProtocolChar.MajorNdisVersion = 5;
+#else
+ ProtocolChar.MajorNdisVersion = 3;
+#endif
+ ProtocolChar.MinorNdisVersion = 0;
+ ProtocolChar.Reserved = 0;
+ ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
+ ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+ ProtocolChar.SendCompleteHandler = NPF_SendComplete;
+ ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+ ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
+ ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
+ ProtocolChar.ReceiveHandler = NPF_tap;
+ ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
+ ProtocolChar.StatusHandler = NPF_Status;
+ ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
+#ifdef NDIS50
+ ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
+ ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
+ ProtocolChar.PnPEventHandler = NPF_PowerChange;
+ ProtocolChar.ReceivePacketHandler = NULL;
+#endif
+ ProtocolChar.Name = ProtoName;
+
+ NdisRegisterProtocol(
+ &Status,
+ &NdisProtocolHandle,
+ &ProtocolChar,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
+
+ return Status;
+
+ }
+
+ NdisAllocateSpinLock(&Opened_Instances_Lock);
+
+ // Set up the device driver entry points.
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
+ DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
+ DriverObject->DriverUnload = NPF_Unload;
+
+ bindP = getAdaptersList();
+
+ if (bindP == NULL)
+ {
+ IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
+
+ tcpBindingsP = getTcpBindings();
+
+ if (tcpBindingsP == NULL)
+ {
+ IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
+ goto RegistryError;
+ }
+
+ bindP = (WCHAR*)tcpBindingsP;
+ bindT = (WCHAR*)(tcpBindingsP->Data);
+
+ }
+ else
+ {
+ bindT = bindP;
+ }
+
+ for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR))
+ {
+ RtlInitUnicodeString(&macName, bindT);
+ createDevice(DriverObject, &macName, NdisProtocolHandle);
+ }
+
+ return STATUS_SUCCESS;
+
+RegistryError:
+
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ Status=STATUS_UNSUCCESSFUL;
+
+ return(Status);
+
+}
+
+//-------------------------------------------------------------------
+
+PWCHAR getAdaptersList(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UINT BufPos=0;
+ UINT BufLen=4096;
+
+
+ PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
+
+ if (DeviceNames == NULL) {
+ IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&objAttrs, &AdapterListKey,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else { //OK
+
+ ULONG resultLength;
+ CHAR AdapInfo[1024];
+ UINT i=0;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
+
+ // Scan the list of the devices
+ while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
+ {
+ WCHAR ExportKeyName [512];
+ PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
+ UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+ PWCHAR LinkageKeyPrefix = L"\\Linkage";
+ UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
+ NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
+ PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
+ UNICODE_STRING AdapterKeyName;
+ HANDLE ExportKeyHandle;
+
+ RtlCopyMemory(ExportKeyName,
+ ExportKeyPrefix,
+ ExportKeyPrefixSize);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
+ tInfo->Name,
+ tInfo->NameLength+2);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
+ LinkageKeyPrefix,
+ LinkageKeyPrefixSize);
+
+ IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
+
+ RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
+
+ InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
+ i++;
+ continue;
+ }
+
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
+ }
+ else{
+ IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
+ if( BufPos + valueInfoP->DataLength > BufLen ) {
+ // double the buffer size
+ PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
+ << 1, '0PWA');
+ if( DeviceNames2 ) {
+ RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
+ BufLen <<= 1;
+ ExFreePool(DeviceNames);
+ DeviceNames = DeviceNames2;
+ }
+ }
+ if( BufPos + valueInfoP->DataLength < BufLen ) {
+ RtlCopyMemory((PCHAR)DeviceNames+BufPos,
+ valueInfoP->Data,
+ valueInfoP->DataLength);
+ BufPos+=valueInfoP->DataLength-2;
+ }
+ }
+
+ ExFreePool(valueInfoP);
+ }
+ else {
+ IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
+ }
+
+ }
+
+ // terminate the buffer
+ DeviceNames[BufPos/2]=0;
+ DeviceNames[BufPos/2+1]=0;
+
+ ZwClose (ExportKeyHandle);
+ i++;
+
+ }
+
+ ZwClose (keyHandle);
+
+ }
+ if(BufPos==0){
+ ExFreePool(DeviceNames);
+ return NULL;
+ }
+ return DeviceNames;
+}
+
+//-------------------------------------------------------------------
+
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+
+ InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else {
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
+
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
+ (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
+
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
+ }
+ else if (valueInfoLength != resultLength) {
+ IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
+ "but previous len = %u\n",
+ resultLength, valueInfoLength);)
+ }
+ else if (valueInfoP->Type != REG_MULTI_SZ) {
+ IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
+ valueInfoP->Type);)
+ }
+ else { // It's OK
+#if DBG
+ ULONG i;
+ WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
+ IF_LOUD(DbgPrint("\n\nBind value:\n");)
+ for (i = 0; *dataP != UNICODE_NULL; i++) {
+ UNICODE_STRING macName;
+ RtlInitUnicodeString(&macName, dataP);
+ IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
+ dataP +=
+ (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+ }
+#endif // DBG
+ result = valueInfoP;
+ }
+ }
+ }
+ ZwClose(keyHandle);
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------
+
+BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT devObjP;
+ UNICODE_STRING deviceName;
+ UNICODE_STRING deviceSymLink;
+
+ IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
+ if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
+ devicePrefix.Length) < devicePrefix.Length)
+ {
+ return FALSE;
+ }
+
+ deviceName.Length = 0;
+ deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
+ deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
+
+ if (deviceName.Buffer == NULL)
+ return FALSE;
+
+ deviceSymLink.Length = 0;
+ deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
+ + symbolicLinkPrefix.Length
+ + NPF_Prefix.Length
+ + sizeof(UNICODE_NULL));
+
+ deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
+
+ if (deviceSymLink.Buffer == NULL)
+ {
+ ExFreePool(deviceName.Buffer);
+ return FALSE;
+ }
+
+ RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
+ RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
+ RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
+
+ status = IoCreateDevice(adriverObjectP,
+ sizeof(DEVICE_EXTENSION),
+ &deviceName,
+ FILE_DEVICE_TRANSPORT,
+ 0,
+ FALSE,
+ &devObjP);
+
+ if (NT_SUCCESS(status))
+ {
+ PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
+ IF_LOUD(DbgPrint("Device created successfully\n"););
+
+ devObjP->Flags |= DO_DIRECT_IO;
+ RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
+ devExtP->NdisProtocolHandle=aProtoHandle;
+
+ IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
+
+ if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ devExtP->ExportString = NULL;
+
+ return FALSE;
+ }
+
+ IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
+
+ devExtP->ExportString = deviceSymLink.Buffer;
+
+ ExFreePool(deviceName.Buffer);
+
+ return TRUE;
+ }
+
+ else
+ {
+ IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ return FALSE;
+ }
+}
+//-------------------------------------------------------------------
+
+VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT OldDeviceObject;
+ PDEVICE_EXTENSION DeviceExtension;
+
+ NDIS_HANDLE NdisProtocolHandle = NULL;
+ NDIS_STATUS Status;
+
+ NDIS_STRING SymLink;
+
+ IF_LOUD(DbgPrint("NPF: Unload\n"););
+
+ DeviceObject = DriverObject->DeviceObject;
+
+ while (DeviceObject != NULL) {
+ OldDeviceObject = DeviceObject;
+
+ DeviceObject = DeviceObject->NextDevice;
+
+ DeviceExtension = OldDeviceObject->DeviceExtension;
+
+ NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
+
+ IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
+ DeviceExtension->AdapterName.Buffer,
+ NdisProtocolHandle,
+ DeviceObject,
+ OldDeviceObject););
+
+ if (DeviceExtension->ExportString)
+ {
+ RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
+
+ IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
+
+ IoDeleteSymbolicLink(&SymLink);
+ ExFreePool(DeviceExtension->ExportString);
+ }
+
+ IoDeleteDevice(OldDeviceObject);
+ }
+
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ // Free the adapters names
+ ExFreePool( bindP );
+}
+
+#define SET_FAILURE_BUFFER_SMALL() do{\
+ Information = 0; \
+ Status = STATUS_BUFFER_TOO_SMALL; \
+} while(FALSE)
+
+#define SET_RESULT_SUCCESS(__a__) do{\
+ Information = __a__; \
+ Status = STATUS_SUCCESS; \
+} while(FALSE)
+
+#define SET_FAILURE_INVALID_REQUEST() do{\
+ Information = 0; \
+ Status = STATUS_INVALID_DEVICE_REQUEST; \
+} while(FALSE)
+
+#define SET_FAILURE_UNSUCCESSFUL() do{\
+ Information = 0; \
+ Status = STATUS_UNSUCCESSFUL; \
+} while(FALSE)
+
+#define SET_FAILURE_NOMEM() do{\
+ Information = 0; \
+ Status = STATUS_INSUFFICIENT_RESOURCES; \
+} while(FALSE)
+
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST pRequest;
+ ULONG FunctionCode;
+ NDIS_STATUS Status;
+ UINT i;
+ PUCHAR tpointer;
+ ULONG dim,timeout;
+ PUCHAR prog;
+ PPACKET_OID_DATA OidData;
+ ULONG mode;
+// PWSTR DumpNameBuff;
+ PUCHAR TmpBPFProgram;
+ INT WriteRes;
+ BOOLEAN SyncWrite = FALSE;
+// struct bpf_insn *initprogram;
+ ULONG insns;
+ ULONG cnt;
+ BOOLEAN IsExtendedFilter=FALSE;
+
+ BOOLEAN Flag;
+ PUINT pStats;
+ ULONG Information = 0;
+
+ IF_LOUD(DbgPrint("NPF: IoControl\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+ Open=IrpSp->FileObject->FsContext;
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
+
+ switch (FunctionCode){
+
+ case BIOCGSTATS: //function to get the capture stats
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(UINT)){
+ EXIT_FAILURE(0);
+ }
+
+ pStats = (PUINT)(Irp->UserBuffer);
+
+ pStats[3] = 0;
+ pStats[0] = 0;
+ pStats[1] = 0;
+ pStats[2] = 0; // Not yet supported
+
+ for(i = 0 ; i < NCpu ; i++)
+ {
+
+ pStats[3] += Open->CpuData[i].Accepted;
+ pStats[0] += Open->CpuData[i].Received;
+ pStats[1] += Open->CpuData[i].Dropped;
+ pStats[2] += 0; // Not yet supported
+ }
+ EXIT_SUCCESS(4*sizeof(UINT));
+
+ break;
+
+ case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
+ EXIT_FAILURE(0);
+ }
+
+ RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
+
+ EXIT_SUCCESS(26);
+
+ break;
+
+ case BIOCSENDPACKETSSYNC:
+
+ SyncWrite = TRUE;
+
+ case BIOCSENDPACKETSNOSYNC:
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ if(Open->WriteInProgress)
+ {
+ // Another write operation is currently in progress
+ EXIT_FAILURE(0);
+ }
+ else
+ {
+ Open->WriteInProgress = TRUE;
+ }
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ WriteRes = NPF_BufferedWrite(Irp,
+ (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+ SyncWrite);
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ if( WriteRes != -1)
+ {
+ EXIT_SUCCESS(WriteRes);
+ }
+
+ EXIT_FAILURE(WriteRes);
+
+ break;
+
+ case BIOCSETF:
+
+ Open->SkipProcessing = 1;
+
+ do
+ {
+ Flag = FALSE;
+ for(i = 0; i < NCpu ; i++)
+ if (Open->CpuData[i].Processing == 1)
+ Flag = TRUE;
+ }
+ while(Flag); //BUSY FORM WAITING...
+
+
+ // Free the previous buffer if it was present
+ if(Open->bpfprogram != NULL){
+ TmpBPFProgram = Open->bpfprogram;
+ Open->bpfprogram = NULL;
+ ExFreePool(TmpBPFProgram);
+ }
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ if (Open->Filter != NULL)
+ {
+ JIT_BPF_Filter *OldFilter=Open->Filter;
+ Open->Filter=NULL;
+ BPF_Destroy_JIT_Filter(OldFilter);
+ }
+#endif // __NPF_x86__
+
+ // Get the pointer to the new program
+ prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
+
+ if(prog==NULL)
+ {
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+ insns = (IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
+
+ //count the number of operative instructions
+ for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
+
+ IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
+
+#ifdef __NPF_x86__
+ if ( cnt != insns && insns != cnt+1 && ((struct bpf_insn*)prog)[cnt].code == BPF_SEPARATION )
+ {
+ IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
+
+ IsExtendedFilter=TRUE;
+
+ initprogram=&((struct bpf_insn*)prog)[cnt+1];
+
+ if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
+ {
+
+ IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
+
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+ }
+#else //x86-64 and IA64
+ if ( cnt != insns)
+ {
+ IF_LOUD(DbgPrint("Error installing the BPF filter. The filter contains TME extensions,"
+ " not supported on 64bit platforms.\n");)
+
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+
+#endif
+
+ //the NPF processor has been initialized, we have to validate the operative instructions
+ insns = cnt;
+
+ //NOTE: the validation code checks for TME instructions, and fails if a TME instruction is
+ //encountered on 64 bit machines
+ if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
+ {
+ IF_LOUD(DbgPrint("Error validating program");)
+ //FIXME: the machine has been initialized(?), but the operative code is wrong.
+ //we have to reset the machine!
+ //something like: reallocate the mem_ex, and reset the tme_core
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+ // Allocate the memory to contain the new filter program
+ // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
+ TmpBPFProgram = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
+ if (TmpBPFProgram == NULL)
+ {
+ IF_LOUD(DbgPrint("Error - No memory for filter");)
+ // no memory
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+ //copy the program in the new buffer
+ RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
+ Open->bpfprogram=TmpBPFProgram;
+
+ //
+ // At the moment the JIT compiler works on x86 (32 bit) only
+ //
+#ifdef __NPF_x86__
+ // Create the new JIT filter function
+ if(!IsExtendedFilter)
+ if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL)
+ {
+ IF_LOUD(DbgPrint("Error jittering filter");)
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+#endif
+
+ //return
+ for (i = 0 ; i < NCpu ; i++)
+ {
+ Open->CpuData[i].C=0;
+ Open->CpuData[i].P=0;
+ Open->CpuData[i].Free = Open->Size;
+ Open->CpuData[i].Accepted=0;
+ Open->CpuData[i].Dropped=0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ Open->ReaderSN=0;
+ Open->WriterSN=0;
+
+ Open->SkipProcessing = 0;
+ EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ break;
+
+ case BIOCSMODE: //set the capture mode
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ if (mode & MODE_DUMP)
+ {
+ EXIT_FAILURE(0);
+ }
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ if(mode == MODE_CAPT)
+ {
+ Open->mode = MODE_CAPT;
+
+ EXIT_SUCCESS(0);
+ }
+ else if (mode == MODE_MON)
+ {
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ Open->mode = MODE_MON;
+ EXIT_SUCCESS(0);
+#else // _NPF_x86__
+ EXIT_FAILURE(0);
+#endif // __NPF_x86__
+
+ }
+ else{
+ if(mode & MODE_STAT){
+ Open->mode = MODE_STAT;
+ NdisAcquireSpinLock(&Open->CountersLock);
+ Open->Nbytes.QuadPart = 0;
+ Open->Npackets.QuadPart = 0;
+ NdisReleaseSpinLock(&Open->CountersLock);
+
+ if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;
+
+ }
+
+ if(mode & MODE_DUMP){
+
+ Open->mode |= MODE_DUMP;
+// Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
+
+ }
+ EXIT_SUCCESS(0);
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+
+ case BIOCSETDUMPFILENAME:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if(Open->mode & MODE_DUMP)
+ {
+
+ // Close current dump file
+ if(Open->DumpFileHandle != NULL)
+ {
+ NPF_CloseDumpFile(Open);
+ Open->DumpFileHandle = NULL;
+ }
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
+ EXIT_FAILURE(0);
+ }
+
+ // Allocate the buffer that will contain the string
+ DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
+ if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
+ IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
+ EXIT_FAILURE(0);
+ }
+
+ // Copy the buffer
+ RtlCopyBytes((PVOID)DumpNameBuff,
+ Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
+ ((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
+
+ // Create the unicode string
+ RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
+
+ IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
+ Open->DumpFileName.Buffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+ // Try to create the file
+ if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
+ NT_SUCCESS( NPF_StartDump(Open)))
+ {
+ EXIT_SUCCESS(0);
+ }
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+#endif // #if 0
+ case BIOCSETDUMPLIMITS:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+ Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
+
+ IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
+
+ EXIT_SUCCESS(0);
+
+ break;
+
+#endif // #if 0
+
+ case BIOCISDUMPENDED:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+ EXIT_SUCCESS(4);
+
+ break;
+
+#endif // #if 0
+
+ case BIOCSETBUFFERSIZE:
+
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ // Get the number of bytes to allocate
+ dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ Open->SkipProcessing = 1;
+
+ do
+ {
+ Flag = FALSE;
+ for(i=0;i<NCpu;i++)
+ if (Open->CpuData[i].Processing == 1)
+ Flag = TRUE;
+ }
+ while(Flag); //BUSY FORM WAITING...
+
+ if (dim / NCpu < sizeof(struct PacketHeader))
+ dim = 0;
+ else
+ {
+ tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
+ if (tpointer==NULL)
+ {
+ // no memory
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+ }
+
+ if (Open->CpuData[0].Buffer != NULL)
+ ExFreePool(Open->CpuData[0].Buffer);
+
+ for (i = 0 ; i < NCpu ; i++)
+ {
+ if (dim > 0)
+ Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/NCpu)*i;
+ else
+ Open->CpuData[i].Buffer = NULL;
+ Open->CpuData[i].Free = dim/NCpu;
+ Open->CpuData[i].P = 0;
+ Open->CpuData[i].C = 0;
+ Open->CpuData[i].Accepted = 0;
+ Open->CpuData[i].Dropped = 0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ Open->ReaderSN=0;
+ Open->WriterSN=0;
+
+ Open->Size = dim/NCpu;
+
+ Open->SkipProcessing = 0;
+ EXIT_SUCCESS(dim);
+
+ break;
+
+ case BIOCSRTIMEOUT: //set the timeout on the read calls
+
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+ if(timeout == (ULONG)-1)
+ Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
+ else
+ {
+ Open->TimeOut.QuadPart = (LONGLONG)timeout;
+ Open->TimeOut.QuadPart *= 10000;
+ Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;
+ }
+
+ IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
+ EXIT_SUCCESS(timeout);
+
+ break;
+
+ case BIOCSWRITEREP: //set the writes repetition number
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ EXIT_SUCCESS(Open->Nwrites);
+
+ break;
+
+ case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/NCpu; //An hack to make the NCPU-buffers behave like a larger one
+
+ EXIT_SUCCESS(Open->MinToCopy);
+
+ break;
+
+ case IOCTL_PROTOCOL_RESET:
+
+ IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
+
+ IoMarkIrpPending(Irp);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
+ NdisReset(&Status,Open->AdapterHandle);
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
+ NPF_ResetComplete(Open,Status);
+ }
+
+ break;
+
+
+ case BIOCSETOID:
+ case BIOCQUERYOID:
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
+ if (RequestListEntry == NULL)
+ {
+ EXIT_FAILURE(0);
+ }
+
+ pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
+ pRequest->Irp = Irp;
+ pRequest->Internal = FALSE;
+
+
+ //
+ // See if it is an Ndis request
+ //
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
+
+ IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
+
+ //
+ // The buffer is valid
+ //
+ if (FunctionCode == BIOCSETOID){
+
+ pRequest->Request.RequestType=NdisRequestSetInformation;
+ pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
+
+
+ }
+ else{
+
+ pRequest->Request.RequestType=NdisRequestQueryInformation;
+ pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
+
+ }
+
+ NdisResetEvent(&Open->IOEvent);
+ //
+ // submit the request
+ //
+ NdisRequest(
+ &Status,
+ Open->AdapterHandle,
+ &pRequest->Request
+ );
+
+ } else {
+ //
+ // buffer too small
+ //
+ Status=NDIS_STATUS_FAILURE;
+ pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
+ pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
+
+ }
+
+ if (Status != NDIS_STATUS_PENDING) {
+ IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
+
+ NPF_RequestComplete(Open, &pRequest->Request, Status);
+ return Status;
+
+ }
+
+ NdisWaitEvent(&Open->IOEvent, 5000);
+
+ return(Open->IOStatus);
+
+ break;
+
+ case BIOCISETLOBBEH:
+
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+#ifdef __NPF_NT4__
+
+ // NT4 doesn't support loopback inhibition / activation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+
+#else //not __NPF_NT4__
+ //
+ // win2000/xp/2003/vista
+ //
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 1)
+ {
+ Open->SkipSentPackets = TRUE;
+
+ //
+ // Reset the capture buffers, since they could contain loopbacked packets
+ //
+
+// NPF_ResetBufferContents(Open);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ }
+ else
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 2)
+ {
+ Open->SkipSentPackets = FALSE;
+
+ SET_RESULT_SUCCESS(0);
+ break;
+ }
+ else
+ {
+ // Unknown operation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+#endif // !__NPF_NT4__
+ break;
+
+
+
+ default:
+
+ EXIT_FAILURE(0);
+ }
+
+ if (FunctionCode == BIOCISETLOBBEH)
+ {
+ Irp->IoStatus.Information = Information;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ )
+
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PIRP Irp;
+ PINTERNAL_REQUEST pRequest;
+ UINT FunctionCode;
+// KIRQL OldIrq;
+
+ PPACKET_OID_DATA OidData;
+
+ IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
+ Irp=pRequest->Irp;
+
+ if(pRequest->Internal == TRUE){
+
+ // Put the request in the list of the free ones
+ ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+
+ if(Status != NDIS_STATUS_SUCCESS)
+ Open->MaxFrameSize = 1560; // Assume Ethernet
+
+ // We always return success, because the adapter has been already opened
+ Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return;
+ }
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if (FunctionCode == BIOCSETOID) {
+
+ OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
+
+ } else {
+
+ if (FunctionCode == BIOCQUERYOID) {
+
+ OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
+
+ IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
+ }
+
+ }
+
+ Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
+
+ IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &pRequest->ListElement,
+ &Open->RequestSpinLock);
+
+ Irp->IoStatus.Status = Status;
+
+ Open->IOStatus = Status;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // Unlock the caller
+ NdisSetEvent(&Open->IOEvent);
+
+ return;
+
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_StatusComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+{
+ NTSTATUS Status;
+
+ RTL_QUERY_REGISTRY_TABLE ParamTable[4];
+
+ PWSTR Bind = L"Bind";
+ PWSTR Export = L"Export";
+ PWSTR Parameters = L"Parameters";
+ PWSTR Linkage = L"Linkage";
+
+ PWCHAR Path;
+
+
+
+ Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
+
+ if (Path == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Path,
+ RegistryPath->Length+sizeof(WCHAR)
+ );
+
+ RtlCopyMemory(
+ Path,
+ RegistryPath->Buffer,
+ RegistryPath->Length
+ );
+
+ IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
+
+ RtlZeroMemory(
+ ParamTable,
+ sizeof(ParamTable)
+ );
+
+
+
+ //
+ // change to the linkage key
+ //
+
+ ParamTable[0].QueryRoutine = NULL;
+ ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ ParamTable[0].Name = Linkage;
+
+
+ //
+ // Get the name of the mac driver we should bind to
+ //
+
+ ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[1].Name = Bind;
+ ParamTable[1].EntryContext = (PVOID)MacDriverName;
+ ParamTable[1].DefaultType = REG_MULTI_SZ;
+
+ //
+ // Get the name that we should use for the driver object
+ //
+
+ ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[2].Name = Export;
+ ParamTable[2].EntryContext = (PVOID)PacketDriverName;
+ ParamTable[2].DefaultType = REG_MULTI_SZ;
+
+
+ Status=RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ Path,
+ ParamTable,
+ NULL,
+ NULL
+ );
+
+
+ ExFreePool(Path);
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+
+{
+
+ PUCHAR Buffer;
+
+ IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
+
+ if (ValueType != REG_MULTI_SZ) {
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ }
+
+ Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
+
+ if (Buffer==NULL) {
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ RtlCopyMemory(
+ Buffer,
+ ValueData,
+ ValueLength
+ );
+
+ *((PUCHAR *)EntryContext)=Buffer;
+
+ return STATUS_SUCCESS;
+
+}
diff --git a/src/See/Packet.h b/src/See/Packet.h
new file mode 100644
index 00000000..f75ed1d9
--- /dev/null
+++ b/src/See/Packet.h
@@ -0,0 +1,954 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#ifdef __NPF_x86__
+#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
+#include "jitter.h"
+#endif
+
+
+#include "win_bpf.h"
+
+#define MAX_REQUESTS 256 ///< Maximum number of simultaneous IOCTL requests.
+
+#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
+ ///< even multiple of Packet_ALIGNMENT.
+/***************************/
+/* IOCTLs */
+/***************************/
+
+/*!
+ \brief IOCTL code: set kernel buffer size.
+
+ This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
+ When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one
+ and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently
+ buffered packets are lost.
+*/
+#define BIOCSETBUFFERSIZE 9592
+
+/*!
+ \brief IOCTL code: set packet filtering program.
+
+ This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the
+ bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE,
+ the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the
+ OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to
+ every incoming packet. This command also empties the circular buffer used by current instance
+ to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
+*/
+#define BIOCSETF 9030
+
+/*!
+ \brief IOCTL code: get the capture stats
+
+ This command returns to the application the number of packets received and the number of packets dropped by
+ an instance of the driver.
+*/
+#define BIOCGSTATS 9031
+
+/*!
+ \brief IOCTL code: set the read timeout
+
+ This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define BIOCSRTIMEOUT 7416
+
+/*!
+ \brief IOCTL code: set working mode
+
+ This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
+ buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
+ statistical mode or #MODE_DUMP for dump mode.
+*/
+#define BIOCSMODE 7412
+
+/*!
+ \brief IOCTL code: set number of physical repetions of every packet written by the app
+
+ Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites
+ member, and is used to implement the 'multiple write' feature of the driver.
+*/
+#define BIOCSWRITEREP 7413
+
+/*!
+ \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
+
+ This command sets the OPEN_INSTANCE::MinToCopy member.
+*/
+#define BIOCSMINTOCOPY 7414
+
+/*!
+ \brief IOCTL code: set an OID value
+
+ This IOCTL is used to perform an OID set operation on the NIC driver.
+*/
+#define BIOCSETOID 2147483648
+
+/*!
+ \brief IOCTL code: get an OID value
+
+ This IOCTL is used to perform an OID get operation on the NIC driver.
+*/
+#define BIOCQUERYOID 2147483652
+#define BIOCISETLOBBEH 7410
+/*!
+ \brief IOCTL code: set the name of a the file used by kernel dump mode
+
+ This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
+ The dump thread uses it to copy the content of the circular buffer to file.
+ If a file was already opened, the driver closes it before opening the new one.
+*/
+#define BIOCSETDUMPFILENAME 9029
+
+/*!
+ \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
+
+ Command used by the application to retrieve the name of the global event associated with a NPF instance.
+ The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
+*/
+#define BIOCGEVNAME 7415
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as
+ possible. The NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSNOSYNC 9032
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets
+ are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
+ packet. NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSSYNC 9033
+
+/*!
+ \brief IOCTL code: Set the dump file limits.
+
+ This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
+ driver works in dump mode.
+*/
+#define BIOCSETDUMPLIMITS 9034
+
+/*!
+ \brief IOCTL code: Get the status of the kernel dump process.
+
+ This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
+ (amount of bytes or number of packets) has been reached.
+*/
+#define BIOCISDUMPENDED 7411
+
+// Working modes
+#define MODE_CAPT 0x0 ///< Capture working mode
+#define MODE_STAT 0x1 ///< Statistical working mode
+#define MODE_MON 0x2 ///< Kernel monitoring mode
+#define MODE_DUMP 0x10 ///< Kernel dump working mode
+
+
+#define IMMEDIATE 1 ///< Immediate timeout. Forces a read call to return immediately.
+
+
+// The following definitions are used to provide compatibility
+// of the dump files with the ones of libpcap
+#define TCPDUMP_MAGIC 0xa1b2c3d4 ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MAJOR 2 ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MINOR 4 ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+
+/*!
+ \brief Header of a libpcap dump file.
+
+ Used when a driver instance is set in dump mode to create a libpcap-compatible file.
+*/
+struct packet_file_header
+{
+ UINT magic; ///< Libpcap magic number
+ USHORT version_major; ///< Libpcap major version
+ USHORT version_minor; ///< Libpcap minor version
+ UINT thiszone; ///< Gmt to local correction
+ UINT sigfigs; ///< Accuracy of timestamps
+ UINT snaplen; ///< Length of the max saved portion of each packet
+ UINT linktype; ///< Data link type (DLT_*). See win_bpf.h for details.
+};
+
+/*!
+ \brief Header associated to a packet in the driver's buffer when the driver is in dump mode.
+ Similar to the bpf_hdr structure, but simpler.
+*/
+struct sf_pkthdr {
+ struct timeval ts; ///< time stamp
+ UINT caplen; ///< Length of captured portion. The captured portion can be different from
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+/*!
+ \brief Stores an OID request.
+
+ This structure is used by the driver to perform OID query or set operations on the underlying NIC driver.
+ The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level
+ applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure.
+ This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _INTERNAL_REQUEST {
+ LIST_ENTRY ListElement; ///< Used to handle lists of requests.
+ PIRP Irp; ///< Irp that performed the request
+ BOOLEAN Internal; ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
+ NDIS_REQUEST Request; ///< The structure with the actual request, that will be passed to NdisRequest().
+} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
+
+/*!
+ \brief Contains a NDIS packet.
+
+ The driver uses this structure to wrap a NDIS_PACKET structure.
+ This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _PACKET_RESERVED {
+ LIST_ENTRY ListElement; ///< Used to handle lists of packets.
+ PIRP Irp; ///< Irp that performed the request
+ PMDL pMdl; ///< MDL mapping the buffer of the packet.
+ BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
+ ///< after a call to NdisSend().
+ ULONG Cpu; ///< The CPU on which the packet was pulled out of the linked list of free packets
+} PACKET_RESERVED, *PPACKET_RESERVED;
+
+#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
+
+/*!
+ \brief Port device extension.
+
+ Structure containing some data relative to every adapter on which NPF is bound.
+*/
+typedef struct _DEVICE_EXTENSION {
+ NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF.
+ NDIS_STRING AdapterName; ///< Name of the adapter.
+ PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
+ ///< to open this adapter through WinPcap.
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*!
+ \brief Kernel buffer of each CPU.
+
+ Structure containing the kernel buffer (and other CPU related fields) used to capture packets.
+*/
+typedef struct __CPU_Private_Data
+{
+ ULONG P; ///< Zero-based index of the producer in the buffer. It indicates the first free byte to be written.
+ ULONG C; ///< Zero-based index of the consumer in the buffer. It indicates the first free byte to be read.
+ ULONG Free; ///< Number of the free bytes in the buffer
+ PUCHAR Buffer; ///< Pointer to the kernel buffer used to capture packets.
+ ULONG Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
+ ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
+ ///< ones that reach the application.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Received; ///< Number of packets received by current instance from its opening, i.e. number of
+ ///< packet received by the network adapter since the beginning of the
+ ///< capture/monitoring/dump session.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
+ ///< is dropped if there is no more space to store it in the circular buffer that the
+ ///< driver associates to current instance.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Processing; ///< Flag. If set to 1, it indicates that the tap is processing a packet on the CPU this structure is referring to.
+ PMDL TransferMdl1; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
+ PMDL TransferMdl2; ///< Second MDL used to map the portion of the buffer that will contain an incoming packet.
+ ULONG NewP; ///< Used by NdisTransferData() (when we call NdisTransferData, p index must be updated only in the TransferDataComplete.
+}
+ CpuPrivateData;
+
+
+/*!
+ \brief Contains the state of a running instance of the NPF driver.
+
+ This is the most important structure of NPF: it is used by almost all the functions of the driver. An
+ _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
+ to the driver.
+*/
+typedef struct _OPEN_INSTANCE
+{
+ PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
+ ///< the instance is bound.
+ NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
+ UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
+ ///< documentation of NdisOpenAdapter in the MS DDK for details.
+ NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
+ PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the
+ ///< callbacks of NDIS.
+ KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
+ LIST_ENTRY RequestList; ///< List of pending OID requests.
+ LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
+ INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
+ PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
+ PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
+ HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait.
+ UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait.
+ ///< The event is created with a name, so it can be used at user level to know when it
+ ///< is possible to access the driver without being blocked. This fiels stores the name
+ ///< that and is used by the BIOCGEVNAME IOCTL call.
+ PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
+ ///< This code is used only in particular situations (for example when the packet received
+ ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
+ ///< the filtering routine created by the JIT compiler and pointed by the next field
+ ///< is used. See \ref NPF for details on the filtering process.
+#ifdef __NPF_x86__
+ JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
+ ///< See BPF_jitter() for details.
+#endif
+ UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
+ ///< BIOCSMINTOCOPY IOCTL.
+ LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
+ ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
+
+ int mode; ///< Working mode of the driver. See PacketSetMode() for details.
+ LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
+ LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
+ NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
+ UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
+ ///< explanation
+ ULONG Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
+ NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
+ BOOLEAN WriteInProgress; ///< True if a write is currently in progress. NPF currently allows a single wite on
+ ///< the same open instance.
+ NDIS_SPIN_LOCK WriteLock; ///< SpinLock that protects the WriteInProgress variable.
+ NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
+ NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
+ BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
+ ///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
+ HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
+ PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
+ PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
+ HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
+ NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
+ LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
+ UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
+ UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
+ ///< will be closed. A value of 0 means unlimited size.
+ UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
+ ///< packets is reached the dump will be closed. A value of 0 means unlimited number of
+ ///< packets.
+ BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
+ ///< reached.
+ MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
+ TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
+ NDIS_SPIN_LOCK MachineLock; ///< SpinLock that protects the mem_ex buffer
+ UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
+ ///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
+ CpuPrivateData CpuData[1024]; ///< Pool of kernel buffer structures, one for each CPU.
+ ULONG ReaderSN; ///< Sequence number of the next packet to be read from the pool of kernel buffers.
+ ULONG WriterSN; ///< Sequence number of the next packet to be written in the pool of kernel buffers.
+ ///< These two sequence numbers are unique for each capture instance.
+ ULONG Size; ///< Size of each kernel buffer contained in the CpuData field.
+ ULONG SkipProcessing; ///< Flag. When set to 1, the tap discards each packet. It is set to 1 by the IOCTLs that modify
+ ///< some "sensible" fields of the Open structure (e.g. they reallocate the pool of kernel buffers,
+ ///< or change the filter program
+ BOOLEAN SkipSentPackets;
+
+}
+OPEN_INSTANCE, *POPEN_INSTANCE;
+
+/*!
+ \brief Structure prepended to each packet in the kernel buffer pool.
+
+ Each packet in one of the kernel buffers is prepended by this header. It encapsulates the bpf_header,
+ which will be passed to user level programs, as well as the sequence number of the packet, set by the producer (the tap function),
+ and used by the consumer (the read function) to "reorder" the packets contained in the various kernel buffers.
+*/
+struct PacketHeader
+{
+ ULONG SN; ///< Sequence number of the packet.
+ struct bpf_hdr header; ///< bpf header, created by the tap, and copied unmodified to user level programs.
+};
+
+extern UINT g_SendPacketFlags;
+#define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x400 ///< This is an undocumented flag for NdisSetPacketFlags() that allows to disable loopback reception.
+
+#define TRANSMIT_PACKETS 2048 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
+ ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
+
+
+/// Macro used in the I/O routines to return the control to user-mode with a success status.
+#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_SUCCESS;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_SUCCESS;\
+
+/// Macro used in the I/O routines to return the control to user-mode with a failure status.
+#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_UNSUCCESSFUL;\
+
+/**
+ * @}
+ */
+
+
+/***************************/
+/* Prototypes */
+/***************************/
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+
+/*!
+ \brief The initialization routine of the driver.
+ \param DriverObject The driver object of NPF created by the system.
+ \param RegistryPath The registry path containing the keys related to the driver.
+ \return A string containing a list of network adapters.
+
+ DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
+ by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
+ performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
+ callbacks, creates the devices, defines NPF as a protocol inside NDIS.
+*/
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Returns the list of the MACs available on the system.
+ \return A string containing a list of network adapters.
+
+ The list of adapters is retrieved from the
+ SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
+ NPF tries to create its bindings from this list. In this way it is possible to be loaded
+ and unloaded dynamically without passing from the control panel.
+*/
+PWCHAR getAdaptersList(VOID);
+
+/*!
+ \brief Returns the MACs that bind to TCP/IP.
+ \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
+
+ If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
+*/
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
+
+/*!
+ \brief Creates a device for a given MAC.
+ \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
+ \param amacNameP The name of the network interface that the device will point.
+ \param aProtoHandle NDIS protocol handle of NPF.
+ \return If the function succeeds, the return value is nonzero.
+
+ NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
+ information about the original device. In this way, when the user opens the new device, NPF will be able to
+ determine the correct adapter to use.
+*/
+BOOLEAN createDevice(
+ IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP,
+ NDIS_HANDLE aProtoHandle);
+
+/*!
+ \brief Opens a new instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS when a new instance of the driver is opened, i.e. when a user application
+ performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
+ and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the
+ adapter with a call to NdisOpenAdapter.
+*/
+NTSTATUS
+NPF_Open(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the opening of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the opening operation performed by NDIS.
+ \param OpenErrorStatus not used by NPF.
+
+ Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an open operation that was previously started by NPF_Open().
+*/
+VOID
+NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ );
+
+/*!
+ \brief Closes an instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called when a running instance of the driver is closed by the user with a CloseHandle().
+ It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
+ instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
+*/
+NTSTATUS
+NPF_Close(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the closing of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the close operation performed by NDIS.
+
+ Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished a close operation that was previously started by NPF_Close().
+*/
+VOID
+NPF_CloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback invoked by NDIS when a packet arrives from the network.
+ \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
+ the NPF instance to which the packets are destined.
+ \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
+ This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
+ \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
+ \param HeaderBufferSize Size in bytes of the header.
+ \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
+ data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
+ since only a portion can be available at this time. The remaining portion can be obtained with the
+ NdisTransferData() NDIS function.
+ \param LookaheadBufferSize Size in bytes of the lookahead buffer.
+ \param PacketSize Total size of the incoming packet, excluded the header.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of
+ the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in
+ statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
+ along with the filtering ones, that is executed for every incoming packet, therefore it is carefully
+ optimized.
+*/
+NDIS_STATUS
+NPF_tap(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,
+ IN UINT HeaderBufferSize,
+ IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,
+ IN UINT PacketSize
+ );
+
+/*!
+ \brief Ends the transfer of a packet.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
+ \param Status Status of the transfer operation.
+ \param BytesTransferred Amount of bytes transferred.
+
+ Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
+*/
+VOID
+NPF_TransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ );
+
+/*!
+ \brief Callback function that signals the end of a packet reception.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+
+ does nothing in NPF
+*/
+VOID
+NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Handles the IOCTL calls.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
+ using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
+ The following commands are recognized:
+ - #BIOCSETBUFFERSIZE
+ - #BIOCSETF
+ - #BIOCGSTATS
+ - #BIOCSRTIMEOUT
+ - #BIOCSMODE
+ - #BIOCSWRITEREP
+ - #BIOCSMINTOCOPY
+ - #BIOCSETOID
+ - #BIOCQUERYOID
+ - #BIOCSETDUMPFILENAME
+ - #BIOCGEVNAME
+ - #BIOCSENDPACKETSSYNC
+ - #BIOCSENDPACKETSNOSYNC
+*/
+NTSTATUS
+NPF_IoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+
+/*!
+ \brief Ends an OID request.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the completed OID request.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl().
+*/
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST pRequest,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Writes a raw packet to the network.
+ \param DeviceObject Pointer to the device object on which the user wrote the packet.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
+ be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
+ delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
+ associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
+ packet can be sent for performance reasons.
+*/
+NTSTATUS
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+/*!
+ \brief Writes a buffer of raw packets to the network.
+ \param Irp Pointer to the IRP containing the user request.
+ \param UserBuff Pointer to the buffer containing the packets to send.
+ \param UserBuffSize Size of the buffer with the packets.
+ \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+ error occurred during the send. The error can be caused by an adapter problem or by an
+ inconsistent/bogus user buffer.
+
+ This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
+ The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
+ sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
+ When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
+ This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
+ of some microseconds (depending on the precision of the performance counter of the machine).
+ If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
+*/
+
+INT NPF_BufferedWrite(IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN sync);
+
+/*!
+ \brief Waits the completion of all the sends performed by NPF_BufferedWrite.
+
+ \param Open Pointer to open context structure
+
+ Used by NPF_BufferedWrite to wait the completion of all the sends before returning the control to the user.
+*/
+VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open);
+
+/*!
+ \brief Ends a send operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_Write().
+*/
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Ends a reset of the adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET
+ command.
+*/
+VOID
+NPF_ResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+/*!
+ \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
+VOID
+NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Function called by the OS when NPF is unloaded.
+ \param DriverObject The driver object of NPF created by the system.
+
+ This is the last function executed when the driver is unloaded from the system. It frees global resources,
+ delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
+ service (from control panel or with a console 'net stop npf').
+*/
+VOID
+NPF_Unload(IN PDRIVER_OBJECT DriverObject);
+
+
+/*!
+ \brief Function that serves the user's reads.
+ \param DeviceObject Pointer to the device used by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
+ kernel buffer to the user buffer associated with Irp.
+ First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance.
+ - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
+ NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
+ user is not blocking.
+ - If the buffer contains less than MinToCopy bytes, the application's request isn't
+ satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net
+ or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
+ - If the instance is in statistical mode or in dump mode, the application's request is blocked until the
+ timeout kept in OPEN_INSTANCE::TimeOut expires.
+*/
+NTSTATUS
+NPF_Read(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver
+ is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+/*!
+ \brief Callback for NDIS BindAdapterHandler. Not used by NPF.
+
+ Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
+*/
+VOID NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ );
+
+/*!
+ \brief Callback for NDIS UnbindAdapterHandler.
+ \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
+ \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
+
+ Function called by NDIS when a new adapter is removed from the machine without shutting it down.
+ NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
+ associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
+ is in dump mode.
+*/
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ );
+
+
+/*!
+ \brief Creates the file that will receive the packets when the driver is in dump mode.
+ \param Open The NPF instance that opens the file.
+ \param fileName Pointer to a UNICODE string containing the name of the file.
+ \param append Boolean value that specifies if the data must be appended to the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
+
+/*!
+ \brief Starts dump to file.
+ \param Open The NPF instance that opens the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function performs two operations. First, it writes the libpcap header at the beginning of the file.
+ Second, it starts the thread that asynchronously dumps the network data to the file.
+*/
+NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
+
+/*!
+ \brief The dump thread.
+ \param Open The NPF instance that creates the thread.
+
+ This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
+ priority than the TAP.
+*/
+VOID NPF_DumpThread(PVOID Open);
+
+/*!
+ \brief Saves the content of the packet buffer to the file associated with current instance.
+ \param Open The NPF instance that creates the thread.
+
+ Used by NPF_DumpThread() and NPF_CloseDumpFile().
+*/
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
+
+/*!
+ \brief Writes a block of packets on the dump file.
+ \param FileObject The file object that will receive the packets.
+ \param Offset The offset in the file where the packets will be put.
+ \param Length The amount of bytes to write.
+ \param Mdl MDL mapping the memory buffer that will be written to disk.
+ \param IoStatusBlock Used by the function to return the status of the operation.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
+ of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
+*/
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock);
+
+
+
+/*!
+ \brief Closes the dump file associated with an instance of the driver.
+ \param Open The NPF instance that closes the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
+
+/*!
+ \brief Returns the amount of bytes present in the packet buffer.
+ \param Open The NPF instance that closes the file.
+*/
+UINT GetBuffOccupation(POPEN_INSTANCE Open);
+
+/*!
+ \brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
+
+ \param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig
+ events.
+ \param pNetPnPEvent Pointer to the PnP event
+
+ If there is a power state change, the driver is forced to resynchronize the global timer.
+ This hopefully avoids the synchronization issues caused by hibernation or standby.
+ This function is excluded from the NT4 driver, where PnP is not supported
+*/
+#ifdef NDIS50
+NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /*main ifndef/define*/
diff --git a/src/See/Packet32.h b/src/See/Packet32.h
new file mode 100644
index 00000000..8c2c8c4a
--- /dev/null
+++ b/src/See/Packet32.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup packetapi
+ * @{
+ */
+
+/** @defgroup packet32h Packet.dll definitions and data structures
+ * Packet32.h contains the data structures and the definitions used by packet.dll.
+ * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
+ * by the applications that use the functions of this library
+ * @{
+ */
+
+#ifndef __PACKET32
+#define __PACKET32
+
+#include <winsock2.h>
+#include "devioctl.h"
+#ifdef HAVE_DAG_API
+#include <dagc.h>
+#endif /* HAVE_DAG_API */
+
+// Working modes
+#define PACKET_MODE_CAPT 0x0 ///< Capture mode
+#define PACKET_MODE_STAT 0x1 ///< Statistical mode
+#define PACKET_MODE_MON 0x2 ///< Monitoring mode
+#define PACKET_MODE_DUMP 0x10 ///< Dump mode
+#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
+
+// ioctls
+#define FILE_DEVICE_PROTOCOL 0x8000
+
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size.
+#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program.
+#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats.
+#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout.
+#define pBIOCSMODE 7412 ///< IOCTL code: set working mode.
+#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app.
+#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call.
+#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value.
+#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value.
+#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only.
+#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only.
+#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode.
+#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer.
+#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets.
+#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets.
+#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function.
+#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function.
+
+#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only.
+
+
+/// Alignment macro. Defines the alignment size.
+#define Packet_ALIGNMENT sizeof(int)
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
+
+
+#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent
+
+/*!
+ \brief Network type structure.
+
+ This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
+*/
+typedef struct NetType
+{
+ UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
+ ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
+}NetType;
+
+
+//some definitions stolen from libpcap
+
+#ifndef BPF_MAJOR_VERSION
+
+/*!
+ \brief A BPF pseudo-assembly program.
+
+ The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
+*/
+struct bpf_program
+{
+ UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
+ struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
+};
+
+/*!
+ \brief A single BPF pseudo-instruction.
+
+ bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
+*/
+struct bpf_insn
+{
+ USHORT code; ///< Instruction type and addressing mode.
+ UCHAR jt; ///< Jump if true
+ UCHAR jf; ///< Jump if false
+ int k; ///< Generic field used for various purposes.
+};
+
+/*!
+ \brief Structure that contains a couple of statistics values on the current capture.
+
+ It is used by packet.dll to return statistics about a capture session.
+*/
+struct bpf_stat
+{
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*!
+ \brief Packet header.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+struct bpf_hdr
+{
+ struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
+ ///< It is stored in a TimeVal structure.
+ UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
+ ///< from the original packet, because it is possible (with a proper filter)
+ ///< to instruct the driver to capture only a portion of the packets.
+ UINT bh_datalen; ///< Original length of packet
+ USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
+ ///< a padding could be added between the end of this structure and the packet
+ ///< data for performance reasons. This filed can be used to retrieve the actual data
+ ///< of the packet.
+};
+
+/*!
+ \brief Dump packet header.
+
+ This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
+ It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
+ packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
+*/
+struct dump_bpf_hdr{
+ struct timeval ts; ///< Time stamp of the packet
+ UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+
+#endif
+
+#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
+#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
+#define NMAX_PACKET 65535
+
+/*!
+ \brief Addresses of a network adapter.
+
+ This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
+ an adapter.
+*/
+typedef struct npf_if_addr {
+ struct sockaddr_storage IPAddress; ///< IP address.
+ struct sockaddr_storage SubnetMask; ///< Netmask for that address.
+ struct sockaddr_storage Broadcast; ///< Broadcast address.
+}npf_if_addr;
+
+
+#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
+#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
+#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+
+
+typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+
+#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
+#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter
+#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
+#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
+#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
+
+/*!
+ \brief Contains comprehensive information about a network adapter.
+
+ This structure is filled with all the accessory information that the user can need about an adapter installed
+ on his system.
+*/
+typedef struct _ADAPTER_INFO
+{
+ struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list.
+ CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter.
+ CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter
+ UINT MacAddressLen; ///< Length of the link layer address.
+ UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address.
+ NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter.
+ INT NNetworkAddresses; ///< Number of network layer addresses of this adapter.
+ npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter.
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+}
+ADAPTER_INFO, *PADAPTER_INFO;
+
+/*!
+ \brief Describes an opened network adapter.
+
+ This structure is the most important for the functioning of packet.dll, but the great part of its fields
+ should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
+*/
+typedef struct _ADAPTER {
+ HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
+ CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
+ int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
+ ///< on the wire.
+ HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
+ ///< It can be passed to standard Win32 functions (like WaitForSingleObject
+ ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
+ ///< data. It is particularly useful in GUI applications that need to wait
+ ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
+ ///< function can be used to define the minimum amount of data in the kernel buffer
+ ///< that will cause the event to be signalled.
+
+ UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
+ ///< ReadEvent will be signaled, also if no packets were captured
+ CHAR Name[ADAPTER_NAME_LENGTH];
+ PWAN_ADAPTER pWanAdapter;
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+#ifdef HAVE_DAG_API
+ dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
+ PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
+ struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
+ unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
+ DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
+#endif // HAVE_DAG_API
+} ADAPTER, *LPADAPTER;
+
+/*!
+ \brief Structure that contains a group of packets coming from the driver.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+typedef struct _PACKET {
+ HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
+ OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
+ PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
+ ///< details about the organization of the data in this buffer
+ UINT Length; ///< Length of the buffer
+ DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
+ ///< received by the last call to PacketReceivePacket()
+ BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
+} PACKET, *LPPACKET;
+
+/*!
+ \brief Structure containing an OID request.
+
+ It is used by the PacketRequest() function to send an OID to the interface card driver.
+ It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
+ the list of the multicast groups defined on it, and so on.
+*/
+struct _PACKET_OID_DATA {
+ ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+ ///< for a complete list of valid codes.
+ ULONG Length; ///< Length of the data field
+ UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
+ ///< from the adapter.
+};
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+
+#if _DBG
+#define ODS(_x) OutputDebugString(TEXT(_x))
+#define ODSEx(_x, _y)
+#else
+#ifdef _DEBUG_TO_FILE
+/*!
+ \brief Macro to print a debug string. The behavior differs depending on the debug level
+*/
+#define ODS(_x) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, "%s", _x); \
+ fclose(f); \
+}
+/*!
+ \brief Macro to print debug data with the printf convention. The behavior differs depending on
+ the debug level
+*/
+#define ODSEx(_x, _y) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, _x, _y); \
+ fclose(f); \
+}
+
+
+
+LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
+#else
+#define ODS(_x)
+#define ODSEx(_x, _y)
+#endif
+#endif
+
+/* We load dinamically the dag library in order link it only when it's present on the system */
+#ifdef HAVE_DAG_API
+typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll
+typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll
+#endif // HAVE_DAG_API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @}
+ */
+
+// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent
+// opening of firewire adapters
+#define FIREWIRE_SUBSTR L"1394"
+
+void PacketPopulateAdaptersInfoList();
+PWCHAR SChar2WChar(PCHAR string);
+PCHAR WChar2SChar(PWCHAR string);
+BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen);
+PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName);
+BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName);
+BOOLEAN IsFireWire(TCHAR *AdapterDesc);
+
+
+//---------------------------------------------------------------------------
+// EXPORTED FUNCTIONS
+//---------------------------------------------------------------------------
+
+PCHAR PacketGetVersion();
+PCHAR PacketGetDriverVersion();
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
+INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
+BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
+LPPACKET PacketAllocatePacket(void);
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
+VOID PacketFreePacket(LPPACKET lpPacket);
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
+BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
+BOOL PacketStopDriver();
+VOID PacketCloseAdapter(LPADAPTER lpAdapter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__PACKET32
diff --git a/src/See/Read.c b/src/See/Read.c
new file mode 100644
index 00000000..03df5c0d
--- /dev/null
+++ b/src/See/Read.c
@@ -0,0 +1,938 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include <stdarg.h>
+#include "ntddk.h"
+#include <ntiologc.h>
+#include <ndis.h>
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+#include "tme.h"
+#include "time_calls.h"
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+extern ULONG NCpu; //from packet.c
+
+NTSTATUS NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PUCHAR packp;
+ PUCHAR CurrBuff;
+ struct bpf_hdr *header;
+// PUCHAR UserPointer;
+// ULONG bytecopy;
+ ULONG copied,count,current_cpu,plen,increment,ToCopy,available;
+ CpuPrivateData *LocalData;
+ ULONG i;
+ ULONG Occupation;
+
+ IF_LOUD(DbgPrint("NPF: Read\n");)
+
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE )
+ {
+ // The Network adapter has been removed or diasabled
+ EXIT_FAILURE(0);
+ }
+
+ if (Open->Size == 0)
+ {
+ EXIT_FAILURE(0);
+ }
+
+ if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
+ // this instance is in dump mode, but the dump file has still not been opened
+ EXIT_FAILURE(0);
+ }
+
+ Occupation=0;
+
+ for(i=0;i<NCpu;i++)
+ Occupation += (Open->Size - Open->CpuData[i].Free);
+
+ //See if the buffer is full enough to be copied
+ if( Occupation <= Open->MinToCopy*NCpu || Open->mode & MODE_DUMP )
+ {
+ //wait until some packets arrive or the timeout expires
+ if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+ KeWaitForSingleObject(Open->ReadEvent,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+ KeClearEvent(Open->ReadEvent);
+
+ if(Open->mode & MODE_STAT)
+ { //this capture instance is in statistics mode
+#ifdef NDIS50
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ //fill the bpf header for this packet
+ header=(struct bpf_hdr*)CurrBuff;
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+ if(Open->mode & MODE_DUMP){
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+ header->bh_caplen=24;
+ header->bh_datalen=24;
+ Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+ }
+ else{
+ header->bh_caplen=16;
+ header->bh_datalen=16;
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+ Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+ }
+
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+
+ //reset the countetrs
+ NdisAcquireSpinLock( &Open->CountersLock );
+ Open->Npackets.QuadPart=0;
+ Open->Nbytes.QuadPart=0;
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+ }
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ PTME_DATA data;
+ ULONG cnt;
+ ULONG block_size;
+ PUCHAR tmp;
+
+#ifdef NDIS50
+ UserPointer=MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ header=(struct bpf_hdr*)UserPointer;
+
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+
+
+ //moves user memory pointer
+ UserPointer+=sizeof(struct bpf_hdr);
+
+ //calculus of data to be copied
+ //if the user buffer is smaller than data to be copied,
+ //only some data will be copied
+ data=&Open->tme.block_data[Open->tme.active_read];
+
+ if (data->last_read.tv_sec!=0)
+ data->last_read=header->bh_tstamp;
+
+
+ bytecopy=data->block_size*data->filled_blocks;
+
+ if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
+ bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
+ else
+ bytecopy=data->filled_blocks;
+
+ tmp=data->shared_memory_base_address;
+ block_size=data->block_size;
+
+ for (cnt=0;cnt<bytecopy;cnt++)
+ {
+ NdisAcquireSpinLock(&Open->MachineLock);
+ RtlCopyMemory(UserPointer,tmp,block_size);
+ NdisReleaseSpinLock(&Open->MachineLock);
+ tmp+=block_size;
+ UserPointer+=block_size;
+ }
+
+ bytecopy*=block_size;
+
+ header->bh_caplen=bytecopy;
+ header->bh_datalen=header->bh_caplen;
+
+ EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+ }
+
+ Occupation=0;
+
+ for(i=0;i<NCpu;i++)
+ Occupation += (Open->Size - Open->CpuData[i].Free);
+
+
+ if ( Occupation == 0 || Open->mode & MODE_DUMP)
+ // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+ // We must awake the application, returning an empty buffer.
+ {
+ EXIT_SUCCESS(0);
+ }
+
+ #else // not __NPF_x86__ , so x86-64 or IA64
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ EXIT_FAILURE(0);
+ }
+ #endif // __NPF_x86__
+
+ }
+
+
+
+//------------------------------------------------------------------------------
+ copied=0;
+ count=0;
+ current_cpu=0;
+ available = IrpSp->Parameters.Read.Length;
+#ifdef NDIS50
+ packp=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+
+ KeClearEvent(Open->ReadEvent);
+
+ while (count < NCpu) //round robin on the CPUs, if count = NCpu there are no packets left to be copied
+ {
+ if (available == copied)
+ {
+ EXIT_SUCCESS(copied);
+ }
+
+ LocalData = &Open->CpuData[current_cpu];
+
+ if (LocalData->Free < Open->Size)
+ { //there are some packets in the selected (aka LocalData) buffer
+ struct PacketHeader *Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->C);
+
+ if ( Header->SN == Open->ReaderSN)
+ { //check if it the next one to be copied
+ plen = Header->header.bh_caplen;
+ if (plen + sizeof (struct bpf_hdr) > available - copied)
+ { //if the packet does not fit into the user buffer, we've ended copying packets
+ EXIT_SUCCESS(copied);
+ }
+
+// FIX_TIMESTAMPS(&Header->header.bh_tstamp);
+
+ *((struct bpf_hdr*)(&packp[copied]))=Header->header;
+
+ copied += sizeof(struct bpf_hdr);
+ LocalData->C += sizeof(struct PacketHeader);
+
+ if (LocalData->C == Open->Size)
+ LocalData->C = 0;
+
+ if (Open->Size - LocalData->C < plen)
+ {
+ //the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
+ ToCopy = Open->Size - LocalData->C;
+ RtlCopyMemory(packp + copied,LocalData->Buffer + LocalData->C,ToCopy);
+ RtlCopyMemory(packp + copied + ToCopy,LocalData->Buffer,plen-ToCopy);
+ LocalData->C = plen-ToCopy;
+ }
+ else
+ {
+ //the packet is not fragmented
+ RtlCopyMemory(packp + copied ,LocalData->Buffer + LocalData->C ,plen);
+ LocalData->C += plen;
+ // if (c==size) inutile, contemplato nell "header atomico"
+ // c=0;
+ }
+
+ Open->ReaderSN++;
+ copied+=Packet_WORDALIGN(plen);
+
+ increment = plen + sizeof(struct PacketHeader);
+ if ( Open->Size - LocalData->C < sizeof(struct PacketHeader))
+ { //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
+ //so the producer (--> the consumer) skips to the beginning of the buffer
+ increment += Open->Size-LocalData->C;
+ LocalData->C=0;
+ }
+ InterlockedExchangeAdd(&Open->CpuData[current_cpu].Free,increment);
+ count=0;
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%NCpu;
+ count++;
+ }
+
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%NCpu;
+ count++;
+ }
+ }
+
+ {EXIT_SUCCESS(copied);}
+
+//------------------------------------------------------------------------------
+
+}
+
+extern void *test_addr;
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookaheadBuffer,
+ IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+ POPEN_INSTANCE Open;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status;
+ UINT BytesTransfered;
+ PMDL pMdl1,pMdl2;
+ UINT fres;
+
+ CpuPrivateData *LocalData;
+ ULONG Cpu;
+ struct PacketHeader *Header;
+ ULONG ToCopy;
+ ULONG increment;
+ ULONG i;
+// BOOLEAN ShouldReleaseMachineLock;
+
+ IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+ IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n",
+ HeaderBufferSize,
+ LookaheadBuffer,
+ LookaheadBufferSize,
+ PacketSize);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ if (Open->SkipProcessing == 1) //some IoCtl is modifying some shared structure, we must drop the packet.
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ Cpu = KeGetCurrentProcessorNumber();
+ LocalData = &Open->CpuData[Cpu];
+
+ LocalData->Processing = 1; //this tells the Ioctls that we are processing a packet, they cannot modify anything
+ //until ALL the Cpu have terminated their processing (aka, set their LocalData->processing to 0)
+ LocalData->Received++;
+ IF_LOUD(DbgPrint("Received on CPU %d \t%d\n",Cpu,LocalData->Received);)
+// Open->Received++; // Number of packets received by filter ++
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if (Open->mode == MODE_MON)
+ {
+ ShouldReleaseMachineLock = TRUE;
+ NdisAcquireSpinLock(&Open->MachineLock);
+ }
+ else
+ ShouldReleaseMachineLock = FALSE;
+#endif
+
+ //
+ //Check if the lookahead buffer follows the mac header.
+ //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+ //executed on the packet.
+ //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+ //things like this) bpf_filter_with_2_buffers() is executed.
+ //
+ if((UINT)((PUCHAR)LookaheadBuffer-(PUCHAR)HeaderBuffer) != HeaderBufferSize)
+ fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ LookaheadBuffer,
+ HeaderBufferSize,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+
+ else
+//
+// the jit filter is available on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+
+ if(Open->Filter != NULL)
+ {
+ if (Open->bpfprogram != NULL)
+ {
+ fres=Open->Filter->Function(HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+ }
+ else
+ fres = -1;
+ }
+ else
+#endif //__NPF_x86__
+ fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if (ShouldReleaseMachineLock)
+ NdisReleaseSpinLock(&Open->MachineLock);
+#endif
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if(Open->mode==MODE_MON)
+ // we are in monitor mode
+ {
+ if (fres==1)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ }
+#endif
+
+ if(fres==0)
+ {
+ // Packet not accepted by the filter, ignore it.
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ //if the filter returns -1 the whole packet must be accepted
+ if(fres==-1 || fres > PacketSize+HeaderBufferSize)
+ fres = PacketSize+HeaderBufferSize;
+
+ if(Open->mode & MODE_STAT)
+ {
+ // we are in statistics mode
+ NdisAcquireSpinLock( &Open->CountersLock );
+
+ Open->Npackets.QuadPart++;
+
+ if(PacketSize+HeaderBufferSize<60)
+ Open->Nbytes.QuadPart+=60;
+ else
+ Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+ // add preamble+SFD+FCS to the packet
+ // these values must be considered because are not part of the packet received from NDIS
+ Open->Nbytes.QuadPart+=12;
+
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ if(!(Open->mode & MODE_DUMP))
+ {
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ if(Open->Size == 0)
+ {
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if(Open->mode & MODE_DUMP && Open->MaxDumpPacks)
+ {
+ ULONG Accepted=0;
+ for(i=0;i<NCpu;i++)
+ Accepted+=Open->CpuData[i].Accepted;
+
+ if( Accepted > Open->MaxDumpPacks)
+ {
+ // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+ Open->DumpLimitReached = TRUE; // This stops the thread
+ // Awake the dump thread
+ NdisSetEvent(&Open->DumpEvent);
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ //////////////////////////////COPIA.C//////////////////////////////////////////77
+
+ if (fres + sizeof(struct PacketHeader) > LocalData->Free)
+ {
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if (LocalData->TransferMdl1 != NULL)
+ {
+ //if TransferMdl is not NULL, there is some TransferData pending (i.e. not having called TransferDataComplete, yet)
+ //in order to avoid buffer corruption, we drop the packet
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+
+ if (LookaheadBufferSize + HeaderBufferSize >= fres)
+ {
+ //we do not need to call NdisTransferData, either because we need only the HeaderBuffer, or because the LookaheadBuffer
+ //contains what we need
+
+
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ LocalData->P +=sizeof(struct PacketHeader);
+ if (LocalData->P == Open->Size)
+ LocalData->P = 0;
+
+ if ( fres <= HeaderBufferSize || (UINT)( (PUCHAR)LookaheadBuffer - (PUCHAR)HeaderBuffer ) == HeaderBufferSize )
+ {
+ //we can consider the buffer contiguous, either because we use only the data
+ //present in the HeaderBuffer, or because HeaderBuffer and LookaheadBuffer are contiguous
+ // ;-))))))
+
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies!!
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P,HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0 , (PUCHAR)HeaderBuffer + ToCopy, fres - ToCopy);
+ LocalData->P = fres-ToCopy;
+ }
+ else
+ {
+ //the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
+ // ;-)))))) only ONE copy
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, fres);
+ LocalData->P += fres;
+ }
+ }
+ else
+ {
+ //HeaderBuffer and LookAhead buffer are NOT contiguous,
+ //AND, we need some bytes from the LookaheadBuffer, too
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ if (Open->Size - LocalData->P >= HeaderBufferSize)
+ {
+ //HeaderBuffer is NOT fragmented
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+
+ if (LocalData->P == Open->Size)
+ {
+ //the fragmentation of the packet in the buffer is the same fragmentation
+ //in HeaderBuffer+LookaheadBuffer
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ else
+ {
+ //LookAheadBuffer is fragmented, two copies
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, ToCopy);
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer+ ToCopy, fres - HeaderBufferSize - ToCopy);
+ LocalData->P = fres - HeaderBufferSize - ToCopy;
+ }
+ }
+ else
+ {
+ //HeaderBuffer is fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies to copy the HeaderBuffer
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, ToCopy);
+ LocalData->P = 0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->P = HeaderBufferSize - ToCopy;
+
+ //only one copy to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres- HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+ else
+ {
+ //the packet won't be fragmented in the destination buffer (aka, it won't skip the buffer boundary)
+ //two copies, the former to copy the HeaderBuffer, the latter to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader)) //we check that the available, AND contiguous, space in the buffer will fit
+ { //the NewHeader structure, at least, otherwise we skip the producer
+ increment += Open->Size-LocalData->P; //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else
+ {
+ IF_LOUD(DbgPrint("TransferData!!\n");)
+ //ndisTransferData required
+ LocalData->NewP = LocalData->P;
+
+ LocalData->NewP +=sizeof(struct PacketHeader);
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+
+ //first of all, surely the header must be copied
+ if (Open->Size-LocalData->NewP >= HeaderBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, HeaderBufferSize);
+ LocalData->NewP += HeaderBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->NewP = HeaderBufferSize - ToCopy;
+ }
+
+ //then we copy the Lookahead buffer
+
+ if (Open->Size-LocalData->NewP >= LookaheadBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, LookaheadBufferSize);
+ LocalData->NewP += LookaheadBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer + ToCopy, LookaheadBufferSize - ToCopy);
+ LocalData->NewP = LookaheadBufferSize - ToCopy;
+ }
+
+ //Now we must prepare the buffer(s) for the NdisTransferData
+ if ((Open->Size - LocalData->NewP) >= (fres - HeaderBufferSize - LookaheadBufferSize))
+ {
+ //only 1 buffer
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ pMdl2=NULL;
+ LocalData->NewP += fres - HeaderBufferSize - LookaheadBufferSize;
+
+
+ }
+ else
+ {
+ //2 buffers
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ Open->Size - LocalData->NewP,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ pMdl2 = IoAllocateMdl(
+ LocalData->Buffer + 0,
+ fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP),
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl2 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl2\n");)
+ IoFreeMdl(pMdl1);
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ LocalData->NewP = fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP);
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ MmBuildMdlForNonPagedPool(pMdl2);
+ }
+
+
+ NdisAllocatePacket(&Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+ IoFreeMdl(pMdl1);
+ if (pMdl2 != NULL)
+ IoFreeMdl(pMdl2);
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if (pMdl2 != NULL)
+ NdisChainBufferAtFront(pPacket,pMdl2);
+
+ NdisChainBufferAtFront(pPacket,pMdl1);
+
+ RESERVED(pPacket)->Cpu = Cpu;
+
+ LocalData->TransferMdl1 = pMdl1;
+ LocalData->TransferMdl2 = pMdl2;
+
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ NdisTransferData(
+ &Status,
+ Open->AdapterHandle,
+ MacReceiveContext,
+ LookaheadBufferSize,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ pPacket,
+ &BytesTransfered);
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ IF_LOUD(DbgPrint("NdisTransferData, not pending!\n");)
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+
+ IoFreeMdl(pMdl1);
+ if ( pMdl2 != NULL )
+ IoFreeMdl(pMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ LocalData->P = LocalData->NewP;
+
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else
+ {
+ DbgPrint("NdisTransferData, pending!\n");
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+ POPEN_INSTANCE Open;
+ ULONG Cpu;
+ CpuPrivateData *LocalData;
+ struct PacketHeader* Header;
+ ULONG increment;
+
+ IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ Cpu = RESERVED(pPacket)->Cpu;
+
+ LocalData = &Open->CpuData[Cpu];
+
+ IoFreeMdl(LocalData->TransferMdl1);
+ if ( LocalData->TransferMdl2 != NULL )
+ IoFreeMdl(LocalData->TransferMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ //the packet has been successfully copied to the kernel buffer, we can prepend it with the PacketHeader,
+ //and obtain the sequence number and the timestamp
+
+ LocalData->Accepted++;
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ LocalData->P = LocalData->NewP;
+
+ increment = Header->header.bh_caplen + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+ LocalData->Processing = 0;
+
+// Unfreeze the consumer
+ if(Open->Size - LocalData->Free > Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+ IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+ return;
+}
diff --git a/src/See/See.rc b/src/See/See.rc
new file mode 100644
index 00000000..5c275264
--- /dev/null
+++ b/src/See/See.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource1.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource1.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/See/See.vcproj b/src/See/See.vcproj
new file mode 100644
index 00000000..f5254e95
--- /dev/null
+++ b/src/See/See.vcproj
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="See"
+ ProjectGUID="{D817977C-481C-4575-B229-DD2896EDF6C9}"
+ RootNamespace="See"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;WIN_NT_DRIVER;_X86_=1;NDIS50;NTKERNEL"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB"
+ AdditionalDependencies="ntoskrnl.lib hal.lib wmilib.lib ndis.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\see.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ StackReserveSize="262144"
+ StackCommitSize="4096"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;WIN_NT_DRIVER;NDIS50;WIN32_EXT;__NPF_AMD64__;_AMD64_;AMD64;_WIN64;NTKERNEL;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996;4334"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB"
+ AdditionalDependencies="ntoskrnl.lib hal.lib wmilib.lib ndis.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\see_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ StackReserveSize="262144"
+ StackCommitSize="4096"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\bucket_lookup.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\count_packets.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\dump.c"
+ >
+ </File>
+ <File
+ RelativePath=".\functions.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\jitter.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\normal_lookup.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Openclos.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Read.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcp_session.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\tme.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter.c"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter_init.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Write.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\bucket_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\count_packets.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dagc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\DEBUG.H"
+ >
+ </File>
+ <File
+ RelativePath=".\Devioctl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\functions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\jitter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\memory_t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\normal_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddndis.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tcp_session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\time_calls.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tme.h"
+ >
+ </File>
+ <File
+ RelativePath=".\valid_insns.h"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter_init.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\See.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/See/Write.c b/src/See/Write.c
new file mode 100644
index 00000000..a2f1244b
--- /dev/null
+++ b/src/See/Write.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "debug.h"
+#include "packet.h"
+
+
+void *test_addr = NULL;
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ UINT i;
+ NDIS_STATUS Status;
+
+ IF_LOUD(DbgPrint("NPF_Write\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE )
+ {
+ // The Network adapter was removed.
+ EXIT_FAILURE(0);
+ }
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ if(Open->WriteInProgress)
+ {
+ // Another write operation is currently in progress
+ NdisReleaseSpinLock(&Open->WriteLock);
+ EXIT_FAILURE(0);
+ }
+ else
+ {
+ Open->WriteInProgress = TRUE;
+ }
+
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ IF_LOUD(DbgPrint("Max frame size = %d, packet size = %d\n", Open->MaxFrameSize, IrpSp->Parameters.Write.Length);)
+
+
+ if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
+ Open->MaxFrameSize == 0/* || // Check that the MaxFrameSize is correctly initialized
+ IrpSp->Parameters.Write.Length > Open->MaxFrameSize*/) // Check that the fame size is smaller that the MTU
+ {
+ IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
+
+ EXIT_FAILURE(0);
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ Open->Multiple_Write_Counter=Open->Nwrites;
+
+ NdisResetEvent(&Open->WriteEvent);
+
+
+ for(i=0;i<Open->Nwrites;i++){
+
+ // Try to get a packet from our list of free ones
+ NdisAllocatePacket(
+ &Status,
+ &pPacket,
+ Open->PacketPool
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ // No free packets
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if(Open->SkipSentPackets)
+ {
+ NdisSetPacketFlags(
+ pPacket,
+ g_SendPacketFlags);
+ }
+
+ // The packet hasn't a buffer that needs not to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
+
+ // Save the IRP associated with the packet
+ RESERVED(pPacket)->Irp=Irp;
+
+ // Attach the writes buffer to the packet
+ NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
+
+ test_addr = MmGetMdlVirtualAddress(Irp->MdlAddress);
+
+ // Call the MAC
+ NdisSend(
+ &Status,
+ Open->AdapterHandle,
+ pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+
+ }
+
+ if(i%100==99){
+ NdisWaitEvent(&Open->WriteEvent,1000);
+ NdisResetEvent(&Open->WriteEvent);
+ }
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+INT
+NPF_BufferedWrite(
+ IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN Sync)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status;
+ struct sf_pkthdr *winpcap_hdr;
+ PMDL TmpMdl;
+ PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
+
+ IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE ){
+ // The Network adapter was removed.
+ return 0;
+ }
+
+ // Sanity check on the user buffer
+ if(UserBuff == NULL)
+ {
+ return 0;
+ }
+
+ // Check that the MaxFrameSize is correctly initialized
+ if(Open->MaxFrameSize == 0)
+ {
+ IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
+
+ return 0;
+ }
+
+ // Reset the event used to synchronize packet allocation
+ NdisResetEvent(&Open->WriteEvent);
+
+ // Reset the pending packets counter
+ Open->Multiple_Write_Counter = 0;
+
+ // Start from the first packet
+ winpcap_hdr = (struct sf_pkthdr*)UserBuff;
+
+ // Chech the consistency of the user buffer
+ if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
+
+ return -1;
+ }
+
+ //
+ // Main loop: send the buffer to the wire
+ //
+ while(TRUE)
+ {
+
+ if(winpcap_hdr->caplen ==0/* || winpcap_hdr->caplen > Open->MaxFrameSize*/)
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ return -1;
+ }
+
+ // Allocate an MDL to map the packet data
+ TmpMdl = IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
+ winpcap_hdr->caplen,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (TmpMdl == NULL)
+ {
+ // Unable to map the memory: packet lost
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
+
+ return -1;
+ }
+
+ MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
+
+ // Allocate a packet from our free list
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ // No more free packets
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
+
+ NdisResetEvent(&Open->WriteEvent);
+
+ NdisWaitEvent(&Open->WriteEvent, 1000);
+
+ // Try again to allocate a packet
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ // Second failure, report an error
+ IoFreeMdl(TmpMdl);
+ return -1;
+ }
+
+// IoFreeMdl(TmpMdl);
+// return (PCHAR)winpcap_hdr - UserBuff;
+ }
+
+ if(Open->SkipSentPackets)
+ {
+ NdisSetPacketFlags(
+ pPacket,
+ g_SendPacketFlags);
+ }
+
+ // The packet has a buffer that needs to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
+
+ TmpMdl->Next = NULL;
+
+ // Attach the MDL to the packet
+ NdisChainBufferAtFront(pPacket, TmpMdl);
+
+ // Increment the number of pending sends
+ InterlockedIncrement(&Open->Multiple_Write_Counter);
+
+ // Call the MAC
+ NdisSend( &Status, Open->AdapterHandle, pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+ }
+
+ // Step to the next packet in the buffer
+ (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
+
+ // Check if the end of the user buffer has been reached
+ if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
+
+ // Wait the completion of pending sends
+ NPF_WaitEndOfBufferedWrite(Open);
+
+ return (INT)((PCHAR)winpcap_hdr - UserBuff);
+ }
+
+ }
+
+ return (INT)((PCHAR)winpcap_hdr - UserBuff);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open)
+{
+ UINT i;
+
+ NdisResetEvent(&Open->WriteEvent);
+
+ for(i=0; Open->Multiple_Write_Counter > 0 && i < TRANSMIT_PACKETS; i++)
+ {
+ NdisWaitEvent(&Open->WriteEvent, 100);
+ NdisResetEvent(&Open->WriteEvent);
+ }
+
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ )
+
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION irpSp;
+ POPEN_INSTANCE Open;
+ PMDL TmpMdl;
+
+ IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ if( RESERVED(pPacket)->FreeBufAfterWrite )
+ {
+ //
+ // Packet sent by NPF_BufferedWrite()
+ //
+
+
+ // Free the MDL associated with the packet
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+
+ IoFreeMdl(TmpMdl);
+
+ // recyle the packet
+ // NdisReinitializePacket(pPacket);
+
+ NdisFreePacket(pPacket);
+
+ // Increment the number of pending sends
+ InterlockedDecrement(&Open->Multiple_Write_Counter);
+
+ NdisSetEvent(&Open->WriteEvent);
+
+ return;
+ }
+ else
+ {
+ //
+ // Packet sent by NPF_Write()
+ //
+
+ if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
+ NdisSetEvent(&Open->WriteEvent);
+
+ Open->Multiple_Write_Counter--;
+
+ if(Open->Multiple_Write_Counter == 0){
+ // Release the buffer and awake the application
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+
+ // Complete the request
+ Irp=RESERVED(pPacket)->Irp;
+ irpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+ NdisReleaseSpinLock(&Open->WriteLock);
+ }
+
+ // Put the packet back on the free list
+ NdisFreePacket(pPacket);
+
+ return;
+ }
+
+}
diff --git a/src/See/bucket_lookup.c b/src/See/bucket_lookup.c
new file mode 100644
index 00000000..569ce163
--- /dev/null
+++ b/src/See/bucket_lookup.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include "tme.h"
+#include "bucket_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/bucket_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/bucket_lookup.h>
+#endif
+
+#endif
+
+
+
+/* the key is represented by the initial and final value */
+/* of the bucket. At the moment bucket_lookup is able to */
+/* manage values of 16, 32 bits. */
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 value;
+ uint32 i,j;
+ int found=-1;
+ uint32 blocks;
+ uint32 block_size;
+ uint8 *temp;
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ /*32 bit values*/
+ blocks=data->filled_blocks-1;
+ block_size=data->block_size;
+ i=blocks/2; /*relative shift*/
+ j=i;
+ temp=data->shared_memory_base_address+block_size;
+
+ if (data->key_len==2)
+ {
+ value=SW_ULONG_AT(key,0);
+
+ if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_ULONG_AT(temp+block_size*j,0)>value)
+ if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
+ found=-2;
+ else
+ j-=i;
+ else
+ if (SW_ULONG_AT(temp+block_size*j,4)<value)
+ if (SW_ULONG_AT(temp+block_size*j,0)>value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+ if (found<0)
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ COPY_MEMORY(key,temp+block_size*found,8);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
+
+ return TME_TRUE;
+ }
+ else
+ {
+ value=SW_USHORT_AT(key,0);
+
+ if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_USHORT_AT(temp+block_size*j,0)>value)
+ if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
+ found=-2;
+ else
+ j-=i;
+ else
+ if (SW_USHORT_AT(temp+block_size*j,2)<value)
+ if (SW_USHORT_AT(temp+block_size*j,0)>value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+
+ if (found<0)
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
+
+ COPY_MEMORY(key,temp+block_size*found,4);
+
+ return TME_TRUE;
+ }
+
+}
+
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ RECORD *records=(RECORD*)data->lut_base_address;
+
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ if(data->key_len==2)
+ {
+ uint32 start,stop;
+ uint8 *tmp;
+
+ start=SW_ULONG_AT(key,0);
+ stop=SW_ULONG_AT(key,4);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_ULONG_AT(tmp,4)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
+
+ COPY_MEMORY(tmp,key,8);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+8),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+ else
+ {
+ uint16 start,stop;
+ uint8 *tmp;
+
+ start=SW_USHORT_AT(key,0);
+ stop=SW_USHORT_AT(key,2);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_USHORT_AT(tmp,2)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
+
+ COPY_MEMORY(tmp,key,4);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+4),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+}
diff --git a/src/See/bucket_lookup.h b/src/See/bucket_lookup.h
new file mode 100644
index 00000000..d8700b54
--- /dev/null
+++ b/src/See/bucket_lookup.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define BUCKET_LOOKUP_INSERT 0x00000011
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define BUCKET_LOOKUP 0x00000010
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+
+#endif
diff --git a/src/See/count_packets.c b/src/See/count_packets.c
new file mode 100644
index 00000000..9e69241d
--- /dev/null
+++ b/src/See/count_packets.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include "tme.h"
+#include "count_packets.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/count_packets.h>
+#else
+#include <tme/tme.h>
+#include <tme/count_packets.h>
+#endif
+
+#endif
+
+
+
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+{
+
+ c_p_data *counters=(c_p_data*)(block+data->key_len*4);
+
+ counters->bytes+=pkt_size;
+ counters->packets++;
+
+ return TME_SUCCESS;
+
+}
diff --git a/src/See/count_packets.h b/src/See/count_packets.h
new file mode 100644
index 00000000..9853bda3
--- /dev/null
+++ b/src/See/count_packets.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+typedef struct __c_p_data
+{
+ struct timeval timestamp;
+ uint64 packets;
+ uint64 bytes;
+}
+ c_p_data;
+
+#define COUNT_PACKETS 0x00000000
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
+
diff --git a/src/See/dagc.h b/src/See/dagc.h
new file mode 100644
index 00000000..6162c4a3
--- /dev/null
+++ b/src/See/dagc.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define DAGC_ERRBUF_SIZE 512
+#define FILEBUFSIZE 65536
+#define MAXDAGCARDS 32
+
+#ifndef _WIN32
+
+typedef long long long_long;
+typedef long long ull_t;
+#define TRUE 1
+#define devicestring "/dev/dag%d"
+#define dagc_sleepms(_MS) usleep(_MS * 1000)
+#else /* _WIN32 */
+
+typedef LONGLONG long_long;
+typedef ULONGLONG ull_t;
+#define dagc_sleepms(_MS) Sleep(_MS)
+#define devicestring "\\\\.\\dag%d"
+
+#endif /* _WIN32 */
+
+#define MIN_DAG_SNAPLEN 12
+#define MAX_DAG_SNAPLEN 2040
+
+#define erffilestring "erffile://"
+
+
+#define ATM_SNAPLEN 48
+/* Size of ATM payload */
+#define ATM_WLEN(h) ATM_SNAPLEN
+#define ATM_SLEN(h) ATM_SNAPLEN
+
+/* Size Ethernet payload */
+#define ETHERNET_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define ETHERNET_SLEN(h, b) min(ETHERNET_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size - 2)
+
+/* Size of HDLC payload */
+#define HDLC_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define HDLC_SLEN(h, b) min(HDLC_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size)
+
+/* Flags for dagc_open */
+#define DAGC_OPEN_SHARED 1
+#define DAGC_OPEN_EXCLUSIVE 2
+
+#define TYPE_LEGACY 0
+#define TYPE_HDLC_POS 1
+#define TYPE_ETH 2
+#define TYPE_ATM 3
+#define TYPE_AAL5 4
+
+/*
+ * Card statistics.
+ */
+typedef struct dagc_stats_t
+{
+ ull_t received; /* (NOT IMPLEMENTED) total number of frames received by the DAG */
+ ull_t dropped; /* number of frames dropped for buffer full */
+ ull_t captured; /* (NOT IMPLEMENTED) number of frames that actually reach the
+ application, i.e that are not filtered or dropped */
+} dagc_stats_t;
+
+/*
+ * Descriptor of an open session.
+ * Note: the dagc_t descriptor is completely opaque to the application. It can be compared
+ * to a file descriptor.
+ */
+typedef struct dagc dagc_t;
+
+/*
+ * Card description.
+ */
+typedef struct dagc_if_t
+{
+ struct dagc_if_t *next;
+ char *name; /* pointer to a string to pass to dagc_open*/
+ char *description; /* human-understandable description (e.g. Endace 3.5e Fast
+ Ethernet Card) */
+} dagc_if_t;
+
+
+
+/*
+ * returns a string with last dagc lib error
+ */
+#define dagc_getlasterror(dagcfd) dagcfd->errbuf
+
+/*
+ * returns a linked list with the cards available on the systems. For every card, it scans the
+ * card type and converts it to a human-understandable string, in order to provide a description
+ * useful for example when a system has more than one card
+ */
+int dagc_finddevs (dagc_if_t **alldevsp, char *ebuf);
+
+
+/*
+ * frees the card list.
+ */
+void dagc_freedevs (dagc_if_t *alldevsp);
+
+
+/*
+ * Opens a card (or a file) for capture. Snaplen is the portion of packet delivered to the
+ * application, flags can contain specific settings (for example promisc mode??), minbufsize
+ * is the smallest buffer that the API can provide to the application (to limit CPU waste
+ * with several small buffers under moderated network throughputs)
+ */
+dagc_t* dagc_open(const char *source, unsigned flags, char *ebuf);
+
+/*
+ * Sets the snaplen of a card
+ * Returns -1 on failure. On success, the actual snaplen is returned (snap len has to be a multiple of 4
+ * with DAG cards).
+ */
+int dagc_setsnaplen(dagc_t *dagcfd, unsigned snaplen);
+
+/*
+ * closes a capture instance
+ */
+void dagc_close(dagc_t *dagcfd);
+
+
+/*
+ * returns the linktype of a card
+ */
+int dagc_getlinktype(dagc_t *dagcfd);
+
+
+/*
+ * returns the link speed of the adapter, in MB/s.
+ * If the link speed of the card is unknown, -1 is returned.
+ * XXX NOTE: Currently, there is no consistent way to get linkspeed querying the card.
+ * As a consequence, we determine this value statically from the card model. For cards that can run at
+ * different speeds, we report only the *maximum* speed.
+ */
+int dagc_getlinkspeed(dagc_t *dagcfd);
+
+
+/*
+ * Returns the length of the CRC checksum that the card associates with any packet in the hole. This
+ * information will be used to understand the actual length of the packet on the wire.
+ * Note: this information is not provided consistently by DAG cards, so we gather it from an environment
+ * variable in Unix and from a registry key in Windows.
+ */
+unsigned dagc_getfcslen(dagc_t *dagcfd);
+
+/*
+ * provides a buffer with the new packets (from the board or from the file) and its size.
+ * On success, the return value is 0. If an error has occurred, the return value is -1.
+ * If EOF has reached, the return value is -2. Note that this function always returns
+ * immediately, eventually with an empty buffer, so it is possible to have a success (0)
+ * return value and bufsize = 0.
+ */
+int dagc_receive(dagc_t *dagcfd, u_char **buffer, u_int *bufsize);
+
+
+/*
+ * returns nonzero if any data is available from dagcfd, -1 if an error occurred. Waits until almost the time
+ * specified by timeout has past or any data is available. If timeout=0, returns immediately.
+ * If timeout=NULL, blocks until a packet arrives.
+ */
+int dagc_wait(dagc_t *dagcfd, struct timeval *timeout);
+
+
+/*
+ * returns statistics about current capture session
+ */
+int dagc_stats(dagc_t *dagcfd, dagc_stats_t *ps);
+
+
+/*
+ * Opens a dump file to store the data of this capture.
+ * Returns 0 on success.
+ * NOTE: currently, dagc_dumpfile_open, dagc_dumpfile_close and dagc_dump are simply wrappers
+ * for open, close and write. However, if the programmer uses these functions, he is more protected
+ * against file format changes (for example if the file format will have an header in the future).
+ * Moreover, assuming that the user knows the file format is a bad practice: providing
+ * simple simple save functionality is more intutive and user-friendly.
+ */
+int dagc_dumpfile_open(dagc_t *dagcfd, char* name);
+
+
+/*
+ * Closes a dump file
+ */
+int dagc_dumpfile_close(dagc_t *dagcfd);
+
+
+/*
+ * Writes a buffer of packets to a dump file
+ * Returns 0 on success.
+ */
+int dagc_dump(dagc_t *dagcfd, u_char *buffer, u_int bufsize);
diff --git a/src/See/dump.c b/src/See/dump.c
new file mode 100644
index 00000000..e60aa6cb
--- /dev/null
+++ b/src/See/dump.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#include "debug.h"
+#include "packet.h"
+
+#include "win_bpf.h"
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
+{
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PWCHAR PathPrefix;
+ USHORT PathLen;
+ UNICODE_STRING FullFileName;
+ ULONG FullFileNameLength;
+ PDEVICE_OBJECT fsdDevice;
+
+ IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+ if(fileName->Buffer[0] == L'\\' &&
+ fileName->Buffer[1] == L'?' &&
+ fileName->Buffer[2] == L'?' &&
+ fileName->Buffer[3] == L'\\'
+ ){
+ PathLen = 0;
+ }
+ else{
+ PathPrefix = L"\\??\\";
+ PathLen = 8;
+ }
+
+ // Insert the correct path prefix.
+ FullFileNameLength = PathLen + fileName->MaximumLength;
+
+ FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ FullFileNameLength,
+ '0DWA');
+
+ if (FullFileName.Buffer == NULL) {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return ntStatus;
+ }
+
+ FullFileName.Length = PathLen;
+ FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+
+ if(PathLen)
+ RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+
+ RtlAppendUnicodeStringToString (&FullFileName, fileName);
+
+ IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+
+ InitializeObjectAttributes ( &ObjectAttributes,
+ &FullFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ // Create the dump file
+ ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+
+ ExFreePool(FullFileName.Buffer);
+ Open->DumpFileHandle=NULL;
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ ExFreePool(FullFileName.Buffer);
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+ FILE_WRITE_ACCESS,
+ *IoFileObjectType,
+ KernelMode,
+ &Open->DumpFileObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+ IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+ return ntStatus;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+ NTSTATUS ntStatus;
+ struct packet_file_header hdr;
+ IO_STATUS_BLOCK IoStatus;
+
+ IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+ // Init the file header
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+ hdr.thiszone = 0; /*Currently not set*/
+ hdr.snaplen = 1514;
+ hdr.sigfigs = 0;
+
+ // Detect the medium type
+ switch (Open->Medium){
+
+ case NdisMediumWan:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMediumFddi:
+ hdr.linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ hdr.linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnet878_2:
+ hdr.linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ hdr.linktype = DLT_ATM_RFC1483;
+ break;
+
+ default:
+ hdr.linktype = DLT_EN10MB;
+ }
+
+ // Write the header.
+ // We can use ZwWriteFile because we are in the context of the application
+ ntStatus = ZwWriteFile(Open->DumpFileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ &hdr,
+ sizeof(hdr),
+ NULL,
+ NULL );
+
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ Open->DumpOffset.QuadPart=24;
+
+ ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ (ACCESS_MASK)0L,
+ 0,
+ 0,
+ NPF_DumpThread,
+ Open);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ KernelMode,
+ &Open->DumpThreadObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+
+ return ntStatus;
+
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+// ULONG FrozenNic;
+
+ IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);)
+
+ while(TRUE){
+
+ // Wait until some packets arrive or the timeout expires
+ NdisWaitEvent(&Open->DumpEvent, 5000);
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
+
+ if(Open->DumpLimitReached ||
+ Open->Size==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
+ // small for any capture. In both cases it is better to end the dump
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+ IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ NdisResetEvent(&Open->DumpEvent);
+
+ // Write the content of the buffer to the file
+ if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ }
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+#if 0
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte=Open->BLastByte;
+
+ IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+ // Get the address of the buffer
+ CurrBuff=Open->Buffer;
+ //
+ // Fill the application buffer
+ //
+ if( Ttail < Thead )
+ {
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /*+ GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(TRUE){
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = TLastByte-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != TLastByte-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+ Open->BLastByte=Ttail;
+ Open->Bhead=0;
+ }
+
+ if( Ttail > Thead ){
+
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /* +GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(Thead + SizeToDump < Ttail){
+
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = Ttail-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != Ttail-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(Ttail-Thead);
+ Open->Bhead=Ttail;
+
+ }
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+#if 0
+ IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+ IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+ // Consistency check
+ if(Open->DumpFileHandle == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+ ZwClose( Open->DumpFileHandle );
+
+ ObDereferenceObject(Open->DumpFileObject);
+/*
+ if(Open->DumpLimitReached == TRUE)
+ // Limit already reached: don't save the rest of the buffer.
+ return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+ NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+ // Flush the buffer to file
+ NPF_SaveCurrentBuffer(Open);
+
+ // Close The file
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+
+ Open->DumpFileHandle = NULL;
+
+ ObDereferenceObject(Open->DumpFileObject);
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+
+ // Copy the status information back into the "user" IOSB
+ *Irp->UserIosb = Irp->IoStatus;
+
+ // Wake up the mainline code
+ KeSetEvent(Irp->UserEvent, 0, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PIRP irp;
+ KEVENT event;
+ PIO_STACK_LOCATION ioStackLocation;
+ PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
+
+ // Set up the event we'll use
+ KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+
+ // Allocate and build the IRP we'll be sending to the FSD
+ irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
+
+ if (!irp) {
+ // Allocation failed, presumably due to memory allocation failure
+ IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoStatusBlock->Information = 0;
+
+ return;
+ }
+
+ irp->MdlAddress = Mdl;
+ irp->UserEvent = &event;
+ irp->UserIosb = IoStatusBlock;
+ irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ irp->Tail.Overlay.OriginalFileObject= FileObject;
+ irp->RequestorMode = KernelMode;
+
+ // Indicate that this is a WRITE operation
+ irp->Flags = IRP_WRITE_OPERATION;
+
+ // Set up the next I/O stack location
+ ioStackLocation = IoGetNextIrpStackLocation(irp);
+ ioStackLocation->MajorFunction = IRP_MJ_WRITE;
+ ioStackLocation->MinorFunction = 0;
+ ioStackLocation->DeviceObject = fsdDevice;
+ ioStackLocation->FileObject = FileObject;
+ IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
+ ioStackLocation->Parameters.Write.Length = Length;
+ ioStackLocation->Parameters.Write.ByteOffset = *Offset;
+
+
+ // Send it on. Ignore the return code
+ (void) IoCallDriver(fsdDevice, irp);
+
+ // Wait for the I/O to complete.
+ KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
+
+ // Free the IRP now that we are done with it
+ IoFreeIrp(irp);
+
+ return;
+
+}
diff --git a/src/See/functions.c b/src/See/functions.c
new file mode 100644
index 00000000..e6817343
--- /dev/null
+++ b/src/See/functions.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include "tme.h"
+#include "functions.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/bpf.h>
+#include <net/tme/functions.h>
+#else
+#include <tme/tme.h>
+#include <bpf.h>
+#include <tme/functions.h>
+#endif
+
+#endif
+
+
+
+lut_fcn lut_fcn_mapper(uint32 index)
+{
+
+ switch (index)
+ {
+ case NORMAL_LUT_W_INSERT:
+ return (lut_fcn) normal_lut_w_insert;
+
+ case NORMAL_LUT_WO_INSERT:
+ return (lut_fcn) normal_lut_wo_insert;
+
+ case BUCKET_LOOKUP:
+ return (lut_fcn) bucket_lookup;
+
+ case BUCKET_LOOKUP_INSERT:
+ return (lut_fcn) bucket_lookup_insert;
+
+ default:
+ return NULL;
+ }
+
+ return NULL;
+
+}
+
+exec_fcn exec_fcn_mapper(uint32 index)
+{
+ switch (index)
+ {
+ case COUNT_PACKETS:
+ return (exec_fcn) count_packets;
+
+ case TCP_SESSION:
+ return (exec_fcn) tcp_session;
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
diff --git a/src/See/functions.h b/src/See/functions.h
new file mode 100644
index 00000000..9715ce10
--- /dev/null
+++ b/src/See/functions.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+/*function mappers */
+
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+/* lookup functions */
+
+#ifdef WIN32
+#include "bucket_lookup.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/bucket_lookup.h>
+#include <net/tme/normal_lookup.h>
+#endif
+
+/* execution functions */
+
+#ifdef WIN32
+#include "count_packets.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/count_packets.h>
+#include <ne/tme/tcp_session.h>
+#endif
+
+#endif
diff --git a/src/See/jitter.c b/src/See/jitter.c
new file mode 100644
index 00000000..b3bf8cb4
--- /dev/null
+++ b/src/See/jitter.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "packet.h"
+#include "win_bpf.h"
+#include "jitter.h"
+
+//
+// emit routine to update the jump table
+//
+void emit_lenght(binary_stream *stream, ULONG value, UINT len)
+{
+ (stream->refs)[stream->bpf_pc]+=len;
+ stream->cur_ip+=len;
+}
+
+//
+// emit routine to output the actual binary code
+//
+void emit_code(binary_stream *stream, ULONG value, UINT len)
+{
+
+ switch (len){
+
+ case 1:
+ stream->ibuf[stream->cur_ip]=(UCHAR)value;
+ stream->cur_ip++;
+ break;
+
+ case 2:
+ *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
+ stream->cur_ip+=2;
+ break;
+
+ case 4:
+ *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
+ stream->cur_ip+=4;
+ break;
+
+ default:;
+
+ }
+
+ return;
+
+}
+
+//
+// Function that does the real stuff
+//
+BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
+{
+ struct bpf_insn *ins;
+ UINT i, pass;
+ binary_stream stream;
+
+ //NOTE: do not modify the name of this variable, as it's used by the macros to emit code.
+ emit_func emitm;
+
+
+ // Allocate the reference table for the jumps
+#ifdef NTKERNEL
+ stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
+#else
+ stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
+#endif
+ if(stream.refs==NULL)
+ {
+ return NULL;
+ }
+
+ // Reset the reference table
+ for(i=0; i< nins + 1; i++)
+ stream.refs[i]=0;
+
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+
+ // the first pass will emit the lengths of the instructions
+ // to create the reference table
+ emitm=emit_lenght;
+
+ for(pass=0;;){
+
+ ins = prog;
+
+ /* create the procedure header */
+ PUSH(EBP)
+ MOVrd(EBP,ESP)
+ PUSH(EBX)
+ PUSH(ECX)
+ PUSH(EDX)
+ PUSH(ESI)
+ PUSH(EDI)
+ MOVodd(EBX, EBP, 8)
+
+ for(i=0;i<nins;i++){
+
+ stream.bpf_pc++;
+
+ switch (ins->code) {
+
+ default:
+
+ return NULL;
+
+ case BPF_RET|BPF_K:
+
+ MOVid(EAX,ins->k)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_RET|BPF_A:
+
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_LD|BPF_W|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0) //this can be optimized with xor eax,eax
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+
+ MOVodd(EAX, EBP, 0xc)
+
+ break;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+
+ MOVodd(EDX, EBP, 0xc)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EDX,0)
+ MOVobb(DL,EBX,ECX)
+ ANDib(DL, 0xf)
+ SHLib(EDX, 2)
+
+ break;
+
+ case BPF_LD|BPF_IMM:
+
+ MOVid(EAX,ins->k)
+
+ break;
+
+ case BPF_LDX|BPF_IMM:
+
+ MOVid(EDX,ins->k)
+
+ break;
+
+ case BPF_LD|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EAX, ECX, ESI)
+
+ break;
+
+ case BPF_LDX|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EDX, ECX, ESI)
+
+ break;
+
+ case BPF_ST:
+
+ // XXX: this command and the following could be optimized if the previous
+ // instruction was already of this type
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EAX)
+
+ break;
+
+ case BPF_STX:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EDX)
+ break;
+
+ case BPF_JMP|BPF_JA:
+
+ JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+
+ MOVrd(ECX,EAX)
+ ANDid(ECX,ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+
+ MOVrd(ECX,EAX)
+ ANDrd(ECX,EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+
+ ADDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+
+ SUBrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+
+ MOVrd(ECX,EDX)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+
+ CMPid(EDX, 0)
+ JNEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ DIVrd(ECX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+
+ ANDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+
+ ORrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHL_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHR_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+
+ ADD_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+
+ SUB_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,ins->k)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ MOVid(ESI,ins->k)
+ DIVrd(ESI)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+
+ ANDid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+
+ ORid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+
+ SHLib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+
+ SHRib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_NEG:
+
+ NEGd(EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TAX:
+
+ MOVrd(EDX,EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TXA:
+
+ MOVrd(EAX,EDX)
+
+ break;
+
+
+
+ }
+
+ ins++;
+ }
+
+ pass++;
+ if(pass == 2) break;
+
+#ifdef NTKERNEL
+ stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA');
+#else
+ stream.ibuf=(CHAR*)malloc(stream.cur_ip);
+#endif
+ if(stream.ibuf==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return NULL;
+ }
+
+ // modify the reference table to contain the offsets and not the lengths of the instructions
+ for(i=1; i< nins + 1; i++)
+ stream.refs[i]+=stream.refs[i-1];
+
+ // Reset the counters
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+ // the second pass creates the actual code
+ emitm=emit_code;
+
+ }
+
+ // the reference table is needed only during compilation, now we can free it
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return (BPF_filter_function)stream.ibuf;
+
+}
+
+
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
+{
+ JIT_BPF_Filter *Filter;
+
+
+ // Allocate the filter structure
+#ifdef NTKERNEL
+ Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA');
+#else
+ Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
+#endif
+ if(Filter==NULL)
+ {
+ return NULL;
+ }
+
+ // Allocate the filter's memory
+#ifdef NTKERNEL
+ Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA');
+#else
+ Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
+#endif
+ if(Filter->mem==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter);
+#else
+ free(Filter);
+#endif
+ return NULL;
+ }
+
+ // Create the binary
+ if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter);
+#endif
+ return NULL;
+ }
+
+ return Filter;
+
+}
+
+//////////////////////////////////////////////////////////////
+
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
+
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter->Function);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter->Function);
+ free(Filter);
+#endif
+
+}
diff --git a/src/See/jitter.h b/src/See/jitter.h
new file mode 100644
index 00000000..82edea74
--- /dev/null
+++ b/src/See/jitter.h
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+//
+// Registers
+//
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+
+#define AX 0
+#define CX 1
+#define DX 2
+#define BX 3
+#define SP 4
+#define BP 5
+#define SI 6
+#define DI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+
+/*! \brief A stream of X86 binary code.*/
+typedef struct binary_stream{
+ INT cur_ip; ///< Current X86 instruction pointer.
+ INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
+ PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
+ PUINT refs; ///< Jumps reference table.
+}binary_stream;
+
+
+/*! \brief Prototype of a filtering function created by the jitter.
+
+ The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
+ is not among the parameters, because it is hardwired in the function.
+*/
+typedef UINT (__cdecl *BPF_filter_function)( PVOID *, ULONG, UINT);
+
+/*! \brief Prototype of the emit functions.
+
+ Different emit functions are used to create the reference table and to generate the actual filtering code.
+ This allows to have simpler instruction macros.
+ The first parameter is the stream that will receive the data. The secon one is a variable containing
+ the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
+ or a work at a time.
+*/
+typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
+
+/*! \brief Structure describing a x86 filtering program created by the jitter.*/
+typedef struct JIT_BPF_Filter{
+ BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
+ PINT mem;
+}
+JIT_BPF_Filter;
+
+
+
+
+/**************************/
+/* X86 INSTRUCTION MACROS */
+/**************************/
+
+/// mov r32,i32
+#define MOVid(r32, i32) \
+ emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
+
+/// mov dr32,sr32
+#define MOVrd(dr32, sr32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// mov dr32,sr32[off]
+#define MOVodd(dr32, sr32, off) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// mov dr32,sr32[or32]
+#define MOVobd(dr32, sr32, or32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr16,sr32[or32]
+#define MOVobw(dr32, sr32, or32) \
+ emitm(&stream, 0x66, 1); \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr8,sr32[or32]
+#define MOVobb(dr8, sr32, or32) \
+ emitm(&stream, 0x8a, 1); \
+ emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov [dr32][or32],sr32
+#define MOVomd(dr32, or32, sr32) \
+ emitm(&stream, 0x89, 1); \
+ emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
+
+/// bswap dr32
+#define BSWAP(dr32) \
+ emitm(&stream, 0xf, 1); \
+ emitm(&stream, 0x19 << 3 | dr32 , 1);
+
+/// xchg al,ah
+#define SWAP_AX() \
+ emitm(&stream, 0x86, 1); \
+ emitm(&stream, 0xc4 , 1);
+
+/// push r32
+#define PUSH(r32) \
+ emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
+
+/// pop r32
+#define POP(r32) \
+ emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
+
+/// ret
+#define RET() \
+ emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
+
+/// add dr32,sr32
+#define ADDrd(dr32, sr32) \
+ emitm(&stream, 0x03, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// add eax,i32
+#define ADD_EAXi(i32) \
+ emitm(&stream, 0x05, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i32
+#define ADDid(r32, i32) \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i8
+#define ADDib(r32, i8) \
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i8, 1);
+
+/// sub dr32,sr32
+#define SUBrd(dr32, sr32) \
+ emitm(&stream, 0x2b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// sub eax,i32
+#define SUB_EAXi(i32) \
+ emitm(&stream, 0x2d, 1);\
+ emitm(&stream, i32, 4);
+
+/// mul r32
+#define MULrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
+
+/// div r32
+#define DIVrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
+
+/// and r8,i8
+#define ANDib(r8, i8) \
+ emitm(&stream, 0x80, 1);\
+ emitm(&stream, 7 << 5 | r8, 1);\
+ emitm(&stream, i8, 1);
+
+/// and r32,i32
+#define ANDid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x25, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 7 << 5 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// and dr32,sr32
+#define ANDrd(dr32, sr32) \
+ emitm(&stream, 0x23, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or dr32,sr32
+#define ORrd(dr32, sr32) \
+ emitm(&stream, 0x0b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or r32,i32
+#define ORid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x0d, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 25 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// shl r32,i8
+#define SHLib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shl dr32,cl
+#define SHL_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
+
+/// shr r32,i8
+#define SHRib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shr dr32,cl
+#define SHR_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
+
+/// neg r32
+#define NEGd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 27 << 3 | r32 & 0x7, 1);
+
+/// cmp dr32,sr32[off]
+#define CMPodd(dr32, sr32, off) \
+ emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// cmp dr32,sr32
+#define CMPrd(dr32, sr32) \
+ emitm(&stream, 0x3b, 1); \
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// cmp dr32,i32
+#define CMPid(dr32, i32) \
+ if (dr32 == EAX){ \
+ emitm(&stream, 0x3d, 1); \
+ emitm(&stream, i32, 4);} \
+ else{ \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
+ emitm(&stream, i32, 4);}
+
+/// jne off32
+#define JNEb(off8) \
+ emitm(&stream, 0x75, 1);\
+ emitm(&stream, off8, 1);
+
+/// je off32
+#define JE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x84, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off32
+#define JLE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8e, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off8
+#define JLEb(off8) \
+ emitm(&stream, 0x7e, 1);\
+ emitm(&stream, off8, 1);
+
+/// ja off32
+#define JA(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x87, 1);\
+ emitm(&stream, off32, 4);
+
+/// jae off32
+#define JAE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, off32, 4);
+
+/// jg off32
+#define JG(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8f, 1);\
+ emitm(&stream, off32, 4);
+
+/// jge off32
+#define JGE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8d, 1);\
+ emitm(&stream, off32, 4);
+
+/// jmp off32
+#define JMP(off32) \
+ emitm(&stream, 0xe9, 1);\
+ emitm(&stream, off32, 4);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**************************/
+/* Prototypes */
+/**************************/
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+/*!
+ \brief BPF jitter, builds an x86 function from a BPF program.
+ \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
+ \param nins Number of instructions of the input filter.
+ \return The JIT_BPF_Filter structure containing the x86 filtering binary.
+
+ BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
+ calling BPFtoX86().
+*/
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
+
+/*!
+ \brief Translates a set of BPF instructions in a set of x86 ones.
+ \param ins Pointer to the BPF instructions that will be translated into x86 code.
+ \param nins Number of instructions to translate.
+ \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
+ \return The x86 filtering function.
+
+ This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
+ through the instruction macros defined in jitter.h it is able to create an function directly executable
+ by NPF.
+*/
+BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
+/*!
+ \brief Deletes a filtering function that was previously created by BPF_jitter().
+ \param Filter The filter to destroy.
+
+ This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
+*/
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/src/See/memory_t.h b/src/See/memory_t.h
new file mode 100644
index 00000000..ab3c85db
--- /dev/null
+++ b/src/See/memory_t.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define uint8 UCHAR
+#define int8 CHAR
+#define uint16 USHORT
+#define int16 SHORT
+#define uint32 ULONG
+#define int32 LONG
+#define uint64 ULONGLONG
+#define int64 LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+ uint8 *buffer;
+ uint32 size;
+} MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ { \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
+ if ((dest)!=NULL) \
+ RtlZeroMemory((dest),sizeof(type)*(amount)); \
+ }
+
+#define FREE_MEMORY(dest) ExFreePool(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+#else
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+
+#define FREE_MEMORY(dest) GlobalFree(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+
+#endif /*WIN_NT_DRIVER*/
+
+
+
+#endif
+
diff --git a/src/See/normal_lookup.c b/src/See/normal_lookup.c
new file mode 100644
index 00000000..24adb62e
--- /dev/null
+++ b/src/See/normal_lookup.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include "tme.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/normal_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/normal_lookup.h>
+#endif
+
+#endif
+
+
+/* lookup in the table, seen as an hash */
+/* if not found, inserts an element */
+/* returns TME_TRUE if the entry is found or created, */
+/* returns TME_FALSE if no more blocks are available */
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; i<key_len;i++)
+ shrinked_key^=key32[i];
+ /*the first index in the table is calculated*/
+ index=shrinked_key % data->lut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*creation of a new entry*/
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ {
+ /*no more free blocks*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ /*offset=absolute pointer to the block associated*/
+ /*with the newly created entry*/
+ offset=data->shared_memory_base_address+
+ data->block_size*data->filled_blocks;
+
+ /*copy the key in the block*/
+ COPY_MEMORY(offset,key32,key_len*4);
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ /*assign the block relative offset to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
+
+ data->filled_blocks++;
+
+ /*assign the exec function ID to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ data->filled_entries++;
+
+ data->last_found=(uint8*)&records[index];
+
+ return TME_TRUE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+
+ if (i==key_len)
+ {
+ /*key in the block matches the one provided, right entry*/
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /* wrong entry, rehashing */
+ if (IS_DELETABLE(offset+key_len*4,data))
+ {
+ ZERO_MEMORY(offset,data->block_size);
+ COPY_MEMORY(offset,key32,key_len*4);
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+ }
+
+ /* nothing found, last found= out of lut */
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
+
+/* lookup in the table, seen as an hash */
+/* if not found, returns out of count entry index */
+/* returns TME_TRUE if the entry is found */
+/* returns TME_FALSE if the entry is not found */
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; i<key_len;i++)
+ shrinked_key^=key32[i];
+ /*the first index in the table is calculated*/
+ index=shrinked_key % data->lut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*out of table, insertion is not allowed*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+
+ if (i==key_len)
+ {
+ /*key in the block matches the one provided, right entry*/
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /*wrong entry, rehashing*/
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+
+ /*nothing found, last found= out of lut*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
diff --git a/src/See/normal_lookup.h b/src/See/normal_lookup.h
new file mode 100644
index 00000000..45ac4fd1
--- /dev/null
+++ b/src/See/normal_lookup.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define NORMAL_LUT_W_INSERT 0x00000000
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define NORMAL_LUT_WO_INSERT 0x00000001
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define DUMMY_INSERT 1234
+
+#endif
diff --git a/src/See/resource.h b/src/See/resource.h
new file mode 100644
index 00000000..a8d305ad
--- /dev/null
+++ b/src/See/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by NPF.RC
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/See/resource1.h b/src/See/resource1.h
new file mode 100644
index 00000000..abd60c4b
--- /dev/null
+++ b/src/See/resource1.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by See.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/See/tcp_session.c b/src/See/tcp_session.c
new file mode 100644
index 00000000..cce97465
--- /dev/null
+++ b/src/See/tcp_session.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include "tme.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/tcp_session.h>
+#else
+#include <tme/tme.h>
+#include <tme/tcp_session.h>
+#endif
+
+#endif
+
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+
+{
+
+ uint32 next_status;
+ uint32 direction=ULONG_AT(mem_data,12);
+ uint8 flags=mem_ex->buffer[25];
+ tcp_data *session=(tcp_data*)(block+data->key_len*4);
+
+ session->last_timestamp=session->timestamp_block;
+ session->timestamp_block.tv_sec=0x7fffffff;
+
+ if (direction==session->direction)
+ {
+ session->pkts_cln_to_srv++;
+ session->bytes_cln_to_srv+=pkt_size;
+ }
+ else
+ {
+ session->pkts_srv_to_cln++;
+ session->bytes_srv_to_cln+=pkt_size;
+ }
+ /* we use only thes four flags, we don't need PSH or URG */
+ flags&=(ACK|FIN|SYN|RST);
+
+ switch (session->status)
+ {
+ case ERROR_TCP:
+ next_status=ERROR_TCP;
+ break;
+
+ case UNKNOWN:
+ if (flags==SYN)
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
+ {
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_RCV;
+ session->syn_timestamp=session->last_timestamp;
+
+ session->direction=direction;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ }
+ else
+ next_status=UNKNOWN;
+ break;
+
+ case SYN_RCV:
+ if ((flags&RST)&&(direction!=session->direction))
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if ((flags==SYN)&&(direction==session->direction))
+ { /* two syns... */
+ next_status=SYN_RCV;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ break;
+ }
+
+ if ((flags==(SYN|ACK))&&(direction!=session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_ACK_RCV;
+
+ session->syn_ack_timestamp=session->last_timestamp;
+
+ session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ session->ack_cln=session->seq_n_0_cln+1;
+ }
+ else
+ {
+ next_status=ERROR_TCP;
+ }
+ break;
+
+ case SYN_ACK_RCV:
+ if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
+ {
+ next_status=CLOSED_RST;
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
+ break;
+ }
+
+ if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=ESTABLISHED;
+ session->ack_srv=session->seq_n_0_srv+1;
+ break;
+ }
+ if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
+ {
+ next_status=SYN_ACK_RCV;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+
+ case ESTABLISHED:
+ if (flags&SYN)
+ {
+ if ((flags&ACK)&&
+ (direction!=session->direction)&&
+ ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
+ )
+ { /* SYN_ACK duplicato */
+ next_status=ESTABLISHED;
+ break;
+ }
+
+ if ((!(flags&ACK))&&
+ (direction==session->direction)&&
+ (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
+ (ULONG_AT(mem_ex->buffer,20)==0)
+ )
+ { /* syn duplicato */
+ next_status=ESTABLISHED;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ if (flags&ACK)
+ if (direction==session->direction)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_srv<MAX_WINDOW)
+ session->ack_srv=new_ack;
+ }
+ else
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_cln<MAX_WINDOW)
+ session->ack_cln=new_ack;
+ }
+ if (flags&RST)
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if (flags&FIN)
+ if (direction==session->direction)
+ { /* an hack to make all things work */
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_CLN_RCV;
+ break;
+ }
+ else
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_SRV_RCV;
+ break;
+ }
+ next_status=ESTABLISHED;
+ break;
+
+ case CLOSED_RST:
+ next_status=CLOSED_RST;
+ break;
+
+ case FIN_SRV_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_SRV_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction!=session->direction)
+ if ((new_ack-session->ack_cln)<MAX_WINDOW)
+ session->ack_cln=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction==session->direction))
+ {
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case FIN_CLN_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_CLN_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction==session->direction)
+ if (new_ack-session->ack_srv<MAX_WINDOW)
+ session->ack_srv=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction!=session->direction))
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case CLOSED_FIN:
+ next_status=CLOSED_FIN;
+ break;
+ default:
+ next_status=ERROR_TCP;
+
+ }
+
+ session->status=next_status;
+
+ if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
+ session->timestamp_block=session->last_timestamp;
+
+ return TME_SUCCESS;
+}
diff --git a/src/See/tcp_session.h b/src/See/tcp_session.h
new file mode 100644
index 00000000..33aa99e1
--- /dev/null
+++ b/src/See/tcp_session.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define UNKNOWN 0
+#define SYN_RCV 1
+#define SYN_ACK_RCV 2
+#define ESTABLISHED 3
+#define CLOSED_RST 4
+#define FIN_CLN_RCV 5
+#define FIN_SRV_RCV 6
+#define CLOSED_FIN 7
+#define ERROR_TCP 8
+#define FIRST_IS_CLN 0
+#define FIRST_IS_SRV 0xffffffff
+#define FIN_CLN 1
+#define FIN_SRV 2
+
+#define MAX_WINDOW 65536
+
+typedef struct __tcp_data
+{
+ struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
+ struct timeval syn_timestamp;
+ struct timeval last_timestamp;
+ struct timeval syn_ack_timestamp;
+ uint32 direction;
+ uint32 seq_n_0_srv;
+ uint32 seq_n_0_cln;
+ uint32 ack_srv; /* acknowledge of (data sent by server) */
+ uint32 ack_cln; /* acknowledge of (data sent by client) */
+ uint32 status;
+ uint32 pkts_cln_to_srv;
+ uint32 pkts_srv_to_cln;
+ uint32 bytes_srv_to_cln;
+ uint32 bytes_cln_to_srv;
+ uint32 close_state;
+}
+ tcp_data;
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+#define TCP_SESSION 0x00000800
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
diff --git a/src/See/time_calls.h b/src/See/time_calls.h
new file mode 100644
index 00000000..8f02f48f
--- /dev/null
+++ b/src/See/time_calls.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+#include "ndis.h"
+
+#define DEFAULT_TIMESTAMPMODE 0
+
+#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
+#define TIMESTAMPMODE_QUERYSYSTEMTIME 2
+#define TIMESTAMPMODE_RDTSC 3
+
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
+
+#define TIMESTAMPMODE_REGKEY L"TimestampMode"
+
+extern ULONG TimestampMode;
+extern ULONG NCpu;
+
+/*!
+ \brief A microsecond precise timestamp.
+
+ included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
+*/
+
+struct timeval {
+ long tv_sec; ///< seconds
+ long tv_usec; ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv
+{
+ ULONGLONG reference;
+ struct timeval start[32];
+};
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+// data->start.tv_sec = 0;
+// data->start.tv_usec = 0;
+}
+
+
+__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
+{
+ ULONG NewLength;
+ PWSTR NullTerminatedString;
+ RTL_QUERY_REGISTRY_TABLE Queries[2];
+ ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
+
+ NewLength = RegistryPath->Length/2;
+
+ NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));
+
+ if (NullTerminatedString != NULL)
+ {
+ RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
+
+ NullTerminatedString[NewLength]=0;
+
+ RtlZeroMemory(Queries, sizeof(Queries));
+
+ Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Queries[0].Name = TIMESTAMPMODE_REGKEY;
+ Queries[0].EntryContext = &TimestampMode;
+ Queries[0].DefaultType = REG_DWORD;
+ Queries[0].DefaultData = &DefaultTimestampMode;
+ Queries[0].DefaultLength = sizeof(ULONG);
+
+ if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
+ {
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+ }
+
+ RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY, REG_DWORD, &TimestampMode,sizeof(ULONG));
+ ExFreePool(NullTerminatedString);
+ }
+ else
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+}
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+/* KeQueryPerformanceCounter TimeStamps */
+__inline void SynchronizeOnCpu(struct timeval *start)
+{
+// struct timeval *start = (struct timeval*)Data;
+
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ // get the absolute value of the system boot time.
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+
+ start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+
+ start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+ start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (start->tv_usec < 0)
+ {
+ start->tv_sec --;
+ start->tv_usec += 1000000;
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef __NPF_x86__
+/*RDTSC timestamps */
+/* callers must be at IRQL=PASSIVE_LEVEL*/
+__inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+
+ i.QuadPart=-3500000;
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ KeLowerIrql(old);
+
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+ KeLowerIrql(old);
+
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000)
+ {
+ delta/=16;
+ delta2/=16;
+ }
+
+ reference=delta*(start_freq.QuadPart)/delta2;
+
+ data->reference=reference/1000;
+
+ if (reference%1000>500)
+ data->reference++;
+
+ data->reference*=1000;
+
+ reference=data->reference;
+
+ KeQuerySystemTime(&system_time);
+
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+
+ system_time.QuadPart-=116444736000000000;
+
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+
+ if (tmp.tv_usec<0)
+ {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+
+ data->start[0] = tmp;
+
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+#endif //__NPF_x86__
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ ULONG NumberOfCpus, i;
+ KAFFINITY AffinityMask;
+
+ if (data->reference != 0)
+ return;
+
+ NumberOfCpus = NCpu;
+
+ if ( TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ for (i = 0 ; i < NumberOfCpus ; i++ )
+ {
+ AffinityMask = (1 << i);
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ SynchronizeOnCpu(&(data->start[i]));
+ }
+ AffinityMask = 0xFFFFFFFF;
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ data->reference = 1;
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ //do nothing
+ data->reference = 1;
+ }
+ else
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ TimeSynchronizeRDTSC(data);
+ }
+ else
+#endif // __NPF_x86__
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ SynchronizeOnCpu(data->start);
+ data->reference = 1;
+ }
+ return;
+}
+
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+ ULONG CurrentCpu;
+ static struct timeval old_ts={0,0};
+
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ //actually this code is ok only if we are guaranteed that no thread scheduling will take place.
+ CurrentCpu = KeGetCurrentProcessorNumber();
+
+ dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
+ dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
+ {
+ if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec && old_ts.tv_usec > dst->tv_usec) )
+ *dst = old_ts;
+
+ else
+ old_ts = *dst;
+ }
+ }
+ else
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ dst->tv_sec = data->start[0].tv_sec + tmp;
+ dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef __NPF_x86__
+__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
+{
+
+ ULONGLONG tmp;
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ if (data->reference==0)
+ {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+
+ dst->tv_sec+=data->start[0].tv_sec;
+
+ dst->tv_usec+=data->start[0].tv_usec;
+
+ if (dst->tv_usec>=1000000)
+ {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+
+
+}
+#endif //__NPF_x86__
+
+__inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER SystemTime;
+
+ KeQuerySystemTime(&SystemTime);
+
+ dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+ dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+}
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+
+#if 0
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ GetTimeRDTSC(dst,data);
+ }
+ else
+#endif
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ GetTimeQST(dst,data);
+ }
+ else
+ {
+ GetTimeKQPC(dst,data);
+ }
+#endif
+}
+
+
+#else /*WIN_NT_DRIVER*/
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start[0]=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+ *dst=data->start[0];
+}
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif /*_time_calls*/
diff --git a/src/See/tme.c b/src/See/tme.c
new file mode 100644
index 00000000..1e1a6d87
--- /dev/null
+++ b/src/See/tme.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "tme.h"
+
+/* resizes extended memory */
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
+{
+ uint8 *tmp;
+
+ if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
+ return TME_ERROR; /* awfully never reached!!!! */
+
+ tmp=mem_ex->buffer;
+ mem_ex->buffer=NULL;
+ FREE_MEMORY(tmp);
+
+ ALLOCATE_MEMORY(tmp,uint8,size);
+ if (tmp==NULL)
+ return TME_ERROR; /* no memory */
+
+ mem_ex->size=size;
+ mem_ex->buffer=tmp;
+ return TME_SUCCESS;
+
+}
+
+/* activates a block of the TME */
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+
+}
+
+/* simply inserts default values in a TME block */
+/* it DOESN'T initialize the block in the core!! */
+/* FIXME default values are defined at compile time, */
+/* it will be useful to store them in the registry */
+uint32 init_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ TME_DATA *data;
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&(tme->block_data[block]);
+ tme->working=block;
+
+ ZERO_MEMORY(data,sizeof(TME_DATA));
+
+ /* entries in LUT */
+ data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
+ /* blocks */
+ data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
+ /* block size */
+ data->block_size=TME_BLOCK_SIZE_DEFAULT;
+ /* lookup function */
+ data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
+ /* rehashing value */
+ data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
+ /* out lut function */
+ data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
+ /* default function */
+ data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
+ /* extra segment size */
+ data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
+
+
+ data->enable_deletion=FALSE;
+ data->last_read.tv_sec=0;
+ data->last_read.tv_usec=0;
+ return TME_SUCCESS;
+
+}
+/* it validates a TME block and */
+/* (on OK) inserts the block in the core */
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
+{
+ uint32 required_memory;
+ uint8 *base=mem_ex_offset+mem_ex->buffer;
+ TME_DATA *data;
+
+ /* FIXME soluzione un po' posticcia... */
+ if (mem_ex_offset==0)
+ return TME_ERROR;
+
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&tme->block_data[block];
+
+ if (data->lut_entries==0)
+ return TME_ERROR;
+
+ if (data->key_len==0)
+ return TME_ERROR;
+
+ if (data->shared_memory_blocks==0)
+ return TME_ERROR;
+
+ if (data->block_size==0)
+ return TME_ERROR;
+
+ /* checks if the lookup function is valid */
+ if (data->lookup_code==NULL)
+ return TME_ERROR;
+
+ /* checks if the out lut exec function is valid */
+ if (exec_fcn_mapper(data->out_lut_exec)==NULL)
+ return TME_ERROR;
+
+ /* checks if the default exec function is valid */
+ if (exec_fcn_mapper(data->default_exec)==NULL)
+ return TME_ERROR;
+
+ /* let's calculate memory needed */
+ required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
+ required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
+ required_memory+=data->extra_segment_size; /*extra segment*/
+
+ if (required_memory>(mem_ex->size-mem_ex_offset))
+ return TME_ERROR; /*not enough memory*/
+
+ /* the TME block can be initialized */
+ ZERO_MEMORY(base,required_memory);
+
+ data->lut_base_address=base;
+
+ data->shared_memory_base_address=
+ data->lut_base_address+
+ data->lut_entries*sizeof(RECORD);
+
+ data->extra_segment_base_address=
+ data->shared_memory_base_address+
+ data->block_size*data->shared_memory_blocks;
+ data->filled_blocks=1;
+ VALIDATE(tme->validated_blocks,block);
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
+{
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_FALSE;
+
+ return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
+{
+
+ exec_fcn tmp;
+ TME_DATA *data;
+ uint8 *block;
+ uint8 *mem_data;
+
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_ERROR;
+
+ data=&tme->block_data[tme->active];
+
+ if (data->last_found==NULL)
+ { /*out lut exec */
+ tmp=exec_fcn_mapper(data->out_lut_exec);
+ block=data->shared_memory_base_address;
+ }
+ else
+ { /*checks if last_found is valid */
+ if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
+ return TME_ERROR;
+ else
+ {
+ tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
+ if (tmp==NULL)
+ return TME_ERROR;
+ block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
+ if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
+ return TME_ERROR;
+ }
+ }
+
+ if (offset>=mem_ex->size)
+ return TME_ERROR;
+
+ mem_data=mem_ex->buffer+offset;
+
+ return tmp(block,pkt_size,data,mem_ex,mem_data);
+}
+
+/*resets all the TME core*/
+uint32 reset_tme(TME_CORE *tme)
+{
+ if (tme==NULL)
+ return TME_ERROR;
+ ZERO_MEMORY(tme, sizeof(TME_CORE));
+ return TME_SUCCESS;
+}
+
+/* returns a register value of the active TME block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
+{
+ switch(rgstr)
+ {
+ case TME_LUT_ENTRIES:
+ *rval=data->lut_entries;
+ return TME_SUCCESS;
+ case TME_MAX_FILL_STATE:
+ *rval=data->max_fill_state;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ *rval=data->rehashing_value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ *rval=data->key_len;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ *rval=data->shared_memory_blocks;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ *rval=data->filled_entries;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ *rval=data->block_size;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ *rval=data->extra_segment_size;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ *rval=data->filled_blocks;
+ return TME_SUCCESS;
+ case TME_DEFAULT_EXEC:
+ *rval=data->default_exec;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ *rval=data->out_lut_exec;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BASE_ADDRESS:
+ *rval=data->shared_memory_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LUT_BASE_ADDRESS:
+ *rval=data->lut_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_BASE_ADDRESS:
+ *rval=data->extra_segment_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LAST_FOUND_BLOCK:
+ if (data->last_found==NULL)
+ *rval=0;
+ else
+ *rval=data->last_found-mem_ex->buffer;
+ return TME_SUCCESS;
+
+ default:
+ return TME_ERROR;
+ }
+}
+
+/* sets a register value in the active block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
+{ /* very very very dangerous!!!!!!!!!!! */
+ lut_fcn tmp;
+ switch(rgstr)
+ {
+ case TME_MAX_FILL_STATE:
+ data->max_fill_state=value;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ data->rehashing_value=value;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ data->filled_entries=value;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ if (value<=data->shared_memory_blocks)
+ {
+ data->filled_blocks=value;
+ return TME_SUCCESS;
+ }
+ else
+ return TME_ERROR;
+ case TME_DEFAULT_EXEC:
+ data->default_exec=value;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ data->out_lut_exec=value;
+ return TME_SUCCESS;
+ case TME_LOOKUP_CODE:
+ tmp=lut_fcn_mapper(value);
+ if (tmp==NULL)
+ return TME_ERROR;
+ else
+ data->lookup_code=tmp;
+ return TME_SUCCESS;
+ default:
+ break;
+ }
+
+ if (init)
+ switch (rgstr)
+ {
+
+ case TME_LUT_ENTRIES:
+ data->lut_entries=value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ data->key_len=value;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ data->shared_memory_blocks=value;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ data->block_size=value;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ data->extra_segment_size=value;
+ return TME_SUCCESS;
+ default:
+ return TME_ERROR;
+ }
+ else
+ return TME_ERROR;
+
+}
+
+/* chooses the TME block for read */
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active_read=block;
+ return TME_SUCCESS;
+
+}
+
+/* chooses if the autodeletion must be used */
+uint32 set_autodeletion(TME_DATA *data, uint32 value)
+{
+ if (value==0) /* no autodeletion */
+ data->enable_deletion=FALSE;
+ else
+ data->enable_deletion=TRUE;
+
+ return TME_SUCCESS;
+}
diff --git a/src/See/tme.h b/src/See/tme.h
new file mode 100644
index 00000000..eb8d4b12
--- /dev/null
+++ b/src/See/tme.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+#include "ndis.h"
+#else
+#include <windows.h>
+#endif /*WIN_NT_DRIVER*/
+
+#include "memory_t.h"
+#include "time_calls.h"
+
+
+/* error codes */
+#define TME_ERROR 0
+#define TME_SUCCESS 1
+#define TME_TRUE 2
+#define TME_FALSE 3
+
+/* some constants */
+#define DEFAULT_MEM_EX_SIZE 65536
+#define MAX_TME_DATA_BLOCKS 4
+#define TME_NONE_ACTIVE 0xffffffff
+#define DELTA_READ 2 /* secs */
+
+#define TME_LUT_ENTRIES 0x00000000
+#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
+#define TME_REHASHING_VALUE 0x00000002
+#define TME_KEY_LEN 0x00000003
+#define TME_SHARED_MEMORY_BLOCKS 0x00000004
+#define TME_FILLED_ENTRIES 0x00000005
+#define TME_BLOCK_SIZE 0x00000006
+#define TME_EXTRA_SEGMENT_SIZE 0x00000007
+#define TME_LOOKUP_CODE 0x00000008
+#define TME_OUT_LUT_EXEC 0x00000009
+#define TME_FILLED_BLOCKS 0x0000000a
+#define TME_DEFAULT_EXEC 0x0000000b
+#define TME_LUT_BASE_ADDRESS 0x0000000c
+#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
+#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
+#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
+#define TME_LAST_FOUND_BLOCK 0x00000010
+/* TME default values */
+#define TME_LUT_ENTRIES_DEFAULT 32007
+#define TME_REHASHING_VALUE_DEFAULT 1
+#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
+#define TME_BLOCK_SIZE_DEFAULT 64
+#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
+#define TME_LOOKUP_CODE_DEFAULT 0
+#define TME_OUT_LUT_EXEC_DEFAULT 0
+#define TME_DEFAULT_EXEC_DEFAULT 0
+#define TME_MAX_FILL_STATE_DEFAULT 15000
+
+#define IS_VALIDATED(src,index) (src&(1<<index))
+
+#define VALIDATE(src,index) src|=(1<<index);
+
+
+#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
+
+/* TME callback prototypes */
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+ uint32 block;
+ uint32 exec_fcn;
+}
+ RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+ uint32 lut_entries;
+ uint32 max_fill_state;
+ uint32 rehashing_value;
+ uint32 key_len;
+ uint32 shared_memory_blocks;
+ uint32 filled_entries;
+ uint32 block_size;
+ uint32 extra_segment_size;
+ uint32 filled_blocks;
+ lut_fcn lookup_code;
+ uint32 default_exec;
+ uint32 out_lut_exec;
+ uint8 *lut_base_address;
+ uint8 *shared_memory_base_address;
+ uint8 *extra_segment_base_address;
+ struct timeval last_read;
+ uint32 enable_deletion;
+ uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+ uint32 working;
+ uint32 active;
+ uint32 validated_blocks;
+ TME_DATA block_data[MAX_TME_DATA_BLOCKS];
+ uint32 active_read;
+
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+ struct timeval *ts=(struct timeval*)timestamp;
+
+ if (data->enable_deletion==FALSE)
+ return FALSE;
+ if (data->filled_entries<data->max_fill_state)
+ return FALSE;
+ if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
diff --git a/src/See/valid_insns.h b/src/See/valid_insns.h
new file mode 100644
index 00000000..f0361021
--- /dev/null
+++ b/src/See/valid_insns.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+u_short valid_instructions[]=
+ {
+ BPF_RET|BPF_K,
+ BPF_RET|BPF_A,
+ BPF_LD|BPF_IMM,
+ BPF_LDX|BPF_IMM,
+ BPF_LD|BPF_MEM,
+ BPF_LDX|BPF_MEM,
+
+#ifdef __NPF_x86__
+ BPF_LD|BPF_MEM_EX_IMM|BPF_B,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_H,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_W,
+ BPF_LD|BPF_MEM_EX_IND|BPF_B,
+ BPF_LD|BPF_MEM_EX_IND|BPF_H,
+ BPF_LD|BPF_MEM_EX_IND|BPF_W,
+#endif
+ BPF_LD|BPF_W|BPF_ABS,
+ BPF_LD|BPF_H|BPF_ABS,
+ BPF_LD|BPF_B|BPF_ABS,
+ BPF_LDX|BPF_W|BPF_ABS,
+ BPF_LDX|BPF_H|BPF_ABS,
+ BPF_LDX|BPF_B|BPF_ABS,
+ BPF_LD|BPF_W|BPF_LEN,
+ BPF_LDX|BPF_W|BPF_LEN,
+ BPF_LD|BPF_W|BPF_IND,
+ BPF_LD|BPF_H|BPF_IND,
+ BPF_LD|BPF_B|BPF_IND,
+ BPF_LDX|BPF_MSH|BPF_B,
+ BPF_ST,
+ BPF_STX,
+
+#ifdef __NPF_x86__
+ BPF_ST|BPF_MEM_EX_IMM|BPF_B,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_B,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_W,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_W,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_H,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_H,
+ BPF_ST|BPF_MEM_EX_IND|BPF_B,
+ BPF_ST|BPF_MEM_EX_IND|BPF_W,
+ BPF_ST|BPF_MEM_EX_IND|BPF_H,
+#endif
+
+ BPF_JMP|BPF_JA,
+ BPF_JMP|BPF_JGT|BPF_K,
+ BPF_JMP|BPF_JGE|BPF_K,
+ BPF_JMP|BPF_JEQ|BPF_K,
+ BPF_JMP|BPF_JSET|BPF_K,
+ BPF_JMP|BPF_JGT|BPF_X,
+ BPF_JMP|BPF_JGE|BPF_X,
+ BPF_JMP|BPF_JEQ|BPF_X,
+ BPF_JMP|BPF_JSET|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_X,
+ BPF_ALU|BPF_SUB|BPF_X,
+ BPF_ALU|BPF_MUL|BPF_X,
+ BPF_ALU|BPF_DIV|BPF_X,
+ BPF_ALU|BPF_AND|BPF_X,
+ BPF_ALU|BPF_OR|BPF_X,
+ BPF_ALU|BPF_LSH|BPF_X,
+ BPF_ALU|BPF_RSH|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_K,
+ BPF_ALU|BPF_SUB|BPF_K,
+ BPF_ALU|BPF_MUL|BPF_K,
+ BPF_ALU|BPF_DIV|BPF_K,
+ BPF_ALU|BPF_AND|BPF_K,
+ BPF_ALU|BPF_OR|BPF_K,
+ BPF_ALU|BPF_LSH|BPF_K,
+ BPF_ALU|BPF_RSH|BPF_K,
+ BPF_ALU|BPF_NEG,
+ BPF_MISC|BPF_TAX,
+ BPF_MISC|BPF_TXA,
+
+#ifdef __NPF_x86__
+ BPF_MISC|BPF_TME|BPF_LOOKUP,
+ BPF_MISC|BPF_TME|BPF_EXECUTE,
+ BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
+ BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
+ BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
+#endif
+
+ };
+
+#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
diff --git a/src/See/win_bpf.h b/src/See/win_bpf.h
new file mode 100644
index 00000000..8ca879f5
--- /dev/null
+++ b/src/See/win_bpf.h
@@ -0,0 +1,417 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /usr/cvsroot_private/winpcap/packetNtx/driver/win_bpf.h,v 1.2.2.1 2005/12/02 22:12:58 gianlucav Exp $ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef WIN_NT_DRIVER
+#include <ndis.h>
+#endif
+
+
+#include "tme.h"
+#include "time_calls.h"
+
+typedef UCHAR u_char;
+typedef USHORT u_short;
+
+#ifdef WIN_NT_DRIVER
+typedef ULONG u_int;
+#endif
+
+typedef LONG bpf_int32;
+typedef ULONG bpf_u_int32;
+typedef ULONG u_int32;
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a <net/bpf.h> should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+#define DLT_RAW 12 /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * This value is defined by NetBSD; other platforms should refrain from
+ * using it for other purposes, so that NetBSD savefiles with a link
+ * type of 50 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+/*
+ * Reserved for future use.
+ * Do not pick other numerical value for these unless you have also
+ * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
+ * which will arrange that capture files for these DLT_ types have
+ * the same "network" value on all platforms, regardless of what
+ * value is chosen for their DLT_ type (thus allowing captures made
+ * on one platform to be read on other platforms, even if the two
+ * platforms don't use the same numerical values for all DLT_ types).
+ */
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 for any purpose.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/* TME instructions */
+#define BPF_TME 0x08
+
+#define BPF_LOOKUP 0x90
+#define BPF_EXECUTE 0xa0
+#define BPF_INIT 0xb0
+#define BPF_VALIDATE 0xc0
+#define BPF_SET_ACTIVE 0xd0
+#define BPF_RESET 0xe0
+#define BPF_SET_MEMORY 0x80
+#define BPF_GET_REGISTER_VALUE 0x70
+#define BPF_SET_REGISTER_VALUE 0x60
+#define BPF_SET_WORKING 0x50
+#define BPF_SET_ACTIVE_READ 0x40
+#define BPF_SET_AUTODELETION 0x30
+#define BPF_SEPARATION 0xff
+
+#define BPF_MEM_EX_IMM 0xc0
+#define BPF_MEM_EX_IND 0xe0
+/*used for ST */
+#define BPF_MEM_EX 0xc0
+
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*!
+ \brief Validates a filtering program arriving from the user-level app.
+ \param f The filter.
+ \param len Its length, in pseudo instructions.
+ \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
+ \return true if f is a valid filter program..
+
+ The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
+ crash the system.
+ This function returns true if f is a valid filter program. The constraints are that each jump be forward and
+ to a valid code. The code must terminate with either an accept or reject.
+*/
+int32 bpf_validate(struct bpf_insn *f,int32 len, uint32 mem_ex_size);
+
+/*!
+ \brief The filtering pseudo-machine interpreter.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the packet on which the filter will be executed.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ \note this function is not used in normal situations, because the jitter creates a native filtering function
+ that is faster than the interpreter.
+*/
+u_int bpf_filter(register struct bpf_insn *pc,
+ register UCHAR *p,
+ u_int wirelen,
+ register u_int buflen ,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme ,
+ struct time_conv *time_ref);
+
+/*!
+ \brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(),
+ but works correctly also if the MAC header and the data of the packet are in two different buffers.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the MAC header of the packet.
+ \param pd Pointer to a memory buffer containing the data of the packet.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
+*/
+u_int bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+ register u_char *p,
+ register u_char *pd,
+ register int headersize,
+ u_int wirelen,
+ register u_int buflen,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme,
+ struct time_conv *time_ref);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/See/win_bpf_filter.c b/src/See/win_bpf_filter.c
new file mode 100644
index 00000000..8ebb82f5
--- /dev/null
+++ b/src/See/win_bpf_filter.c
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifndef WIN_NT_DRIVER
+#include <windows.h>
+#else
+#include <ndis.h>
+#endif
+
+#include "win_bpf.h"
+
+#include "debug.h"
+
+#include "valid_insns.h"
+
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+
+
+u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+
+{
+ register u_int32 A, X;
+ register int k;
+ //u_int32 j,tmp;
+ //u_short tmp2;
+
+ int32 mem[BPF_MEMWORDS];
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+#endif //__NPF_x86__
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+/* END STORE INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+ /* END TME INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ }
+ }
+}
+
+//-------------------------------------------------------------------
+
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ register u_char *pd;
+ register int headersize;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+{
+ register u_int32 A, X;
+ register int k;
+ int32 mem[BPF_MEMWORDS];
+// u_int32 j,tmp;
+// u_short tmp2;
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + 4 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize){
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen)
+ {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k + 1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k +(int) sizeof(char) <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + 2 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k +1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if((int)(pc->k) <= headersize)
+ X = (p[pc->k] & 0xf) << 2;
+ else
+ X = (pd[(pc->k)-headersize] & 0xf) << 2;
+
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+ /* END LD NO PACKET INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+ /* END STORE INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+ /* END TME INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ }
+ }
+}
+
+int32
+bpf_validate(f, len,mem_ex_size)
+ struct bpf_insn *f;
+ int32 len;
+ uint32 mem_ex_size;
+{
+ register uint32 i, from;
+ register int32 j;
+ register struct bpf_insn *p;
+ int32 flag;
+
+ if (len < 1)
+ return 0;
+
+ for (i = 0; i < (uint32)len; ++i) {
+ p = &f[i];
+
+ IF_LOUD(DbgPrint("Validating program");)
+
+ flag=0;
+ for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
+ if (p->code==valid_instructions[j])
+ flag=1;
+ if (flag==0)
+ return 0;
+
+ IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
+
+ switch (BPF_CLASS(p->code)) {
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong LD memory locations");)
+ break;
+ case BPF_ST:
+ case BPF_STX:
+#ifdef __NPF_x86__
+ if ((p->code &BPF_MEM_EX_IMM) == BPF_MEM_EX_IMM)
+ {
+ /*
+ * Check if key stores use valid addresses
+ */
+ switch (BPF_SIZE(p->code)) {
+
+ case BPF_W:
+ if (p->k+3 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_H:
+ if (p->k+1 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_B:
+ if (p->k >= mem_ex_size)
+ return 0;
+ break;
+ }
+ }
+ else
+#endif //__NPF_x86__
+ {
+ if ((p->code & BPF_MEM_EX_IND) != BPF_MEM_EX_IND)
+ {
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ }
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong ST memory locations");)
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
+ return 0;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+ if (from + p->k < from || from + p->k >= (uint32)len)
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= (uint32)len || from + p->jf >= (uint32)len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ return 0;
+ }
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/src/See/win_bpf_filter_init.c b/src/See/win_bpf_filter_init.c
new file mode 100644
index 00000000..7703a106
--- /dev/null
+++ b/src/See/win_bpf_filter_init.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "tme.h"
+#include "win_bpf.h"
+
+/*
+ * Initialize the filter machine
+ */
+uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
+{
+ register uint32 A, X;
+ int32 mem[BPF_MEMWORDS];
+ register int32 k;
+ uint32 *tmp;
+ uint16 *tmp2;
+ uint32 j;
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (uint32)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ return 0;
+
+/* RET INSTRUCTIONS */
+ case BPF_RET|BPF_K:
+ return (uint32)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (uint32)A;
+/* END RET INSTRUCTIONS */
+
+/* LD NO PACKET INSTRUCTIONS */
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp2=(uint16*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp=(uint32*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, X
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, X
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END STORE INSTRUCTIONS */
+
+/* JUMP INSTRUCTIONS */
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+/* END JUMP INSTRUCTIONS */
+
+/* ARITHMETIC INSTRUCTIONS */
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int32)A = -((int32)A);
+ continue;
+/* ARITHMETIC INSTRUCTIONS */
+
+/* MISC INSTRUCTIONS */
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+/* END MISC INSTRUCTIONS */
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_INIT:
+ if (init_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_VALIDATE:
+ if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
+ if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+ case BPF_MISC|BPF_TME|BPF_SET_WORKING:
+ if (pc->k>=MAX_TME_DATA_BLOCKS)
+ return 0;
+ tme->working=pc->k;
+ continue;
+
+
+
+ case BPF_MISC|BPF_TME|BPF_RESET:
+ if (reset_tme(tme)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
+ set_autodeletion(&tme->block_data[tme->working],pc->k);
+ continue;
+
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
diff --git a/src/See/win_bpf_filter_init.h b/src/See/win_bpf_filter_init.h
new file mode 100644
index 00000000..c1ad028b
--- /dev/null
+++ b/src/See/win_bpf_filter_init.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __FILTER_INIT
+#define __FILTER_INIT
+
+#include "tme.h"
+
+#define INIT_OK 1
+#define INIT_ERROR 0
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/SeeDll/AdInfo.c b/src/SeeDll/AdInfo.c
new file mode 100644
index 00000000..c0dbbc7e
--- /dev/null
+++ b/src/SeeDll/AdInfo.c
@@ -0,0 +1,1410 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <GlobalConst.h>
+
+/*
+ This file contains the support functions used by packet.dll to retrieve information about installed
+ adapters, like
+
+ - the adapter list
+ - the device associated to any adapter and the description of the adapter
+ - physical parameters like the linkspeed or the link layer type
+ - the IP and link layer addresses */
+
+#define UNICODE 1
+
+#include <stdio.h>
+#include <packet32.h>
+
+#if 0
+#include "WanPacket/WanPacket.h"
+#endif
+
+#define _WINNT4
+
+#include <windows.h>
+#include <windowsx.h>
+#include <Iphlpapi.h>
+#include <IPIfCons.h>
+#include <stdio.h>
+
+#include <ntddndis.h>
+
+
+LPADAPTER PacketOpenAdapterNPF(PCHAR AdapterName);
+BOOL PacketAddFakeNdisWanAdapter();
+
+PADAPTER_INFO AdaptersInfoList = NULL; ///< Head of the adapter information list. This list is populated when packet.dll is linked by the application.
+HANDLE AdaptersInfoMutex; ///< Mutex that protects the adapter information list. NOTE: every API that takes an ADAPTER_INFO as parameter assumes that it has been called with the mutex acquired.
+
+#define FAKE_NDISWAN_ADAPTER_NAME "\\Device\\SEE_GenericDialupAdapter" ///< Name of a fake ndiswan adapter that is always available on 2000/XP/2003, used to capture NCP/LCP packets
+#define FAKE_NDISWAN_ADAPTER_DESCRIPTION "Generic dialup adapter" ///< Description of a fake ndiswan adapter that is always available on 2000/XP/2003, used to capture NCP/LCP packets
+
+extern FARPROC GetAdaptersAddressesPointer;
+
+#ifdef HAVE_DAG_API
+extern dagc_open_handler p_dagc_open;
+extern dagc_close_handler p_dagc_close;
+extern dagc_getlinktype_handler p_dagc_getlinktype;
+extern dagc_getlinkspeed_handler p_dagc_getlinkspeed;
+extern dagc_finddevs_handler p_dagc_finddevs;
+extern dagc_freedevs_handler p_dagc_freedevs;
+#endif /* HAVE_DAG_API */
+
+/// Title of error windows
+TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
+
+ULONG inet_addrU(const WCHAR *cp);
+
+/*!
+ \brief Gets the link layer of an adapter, querying the registry.
+ \param AdapterObject Handle to an open adapter.
+ \param type Pointer to a NetType structure that will be filled by the function.
+ \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
+
+ This function retrieves from the registry the link layer and the speed (in bps) of an opened adapter.
+ These values are copied in the NetType structure provided by the user.
+ The LinkType field of the type parameter can have one of the following values:
+
+ - NdisMedium802_3: Ethernet (802.3)
+ - NdisMediumWan: WAN
+ - NdisMedium802_5: Token Ring (802.5)
+ - NdisMediumFddi: FDDI
+ - NdisMediumAtm: ATM
+ - NdisMediumArcnet878_2: ARCNET (878.2)
+*/
+BOOLEAN PacketGetLinkLayerFromRegistry(LPADAPTER AdapterObject, NetType *type)
+{
+ BOOLEAN Status;
+ ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
+ PPACKET_OID_DATA OidData;
+
+ OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
+ if (OidData == NULL) {
+ ODS("PacketGetLinkLayerFromRegistry failed\n");
+ return FALSE;
+ }
+ //get the link-layer type
+ OidData->Oid = OID_GEN_MEDIA_IN_USE;
+ OidData->Length = sizeof (ULONG);
+ Status = PacketRequest(AdapterObject,FALSE,OidData);
+ type->LinkType=*((UINT*)OidData->Data);
+
+ //get the link-layer speed
+ OidData->Oid = OID_GEN_LINK_SPEED;
+ OidData->Length = sizeof (ULONG);
+ Status = PacketRequest(AdapterObject,FALSE,OidData);
+ type->LinkSpeed=*((UINT*)OidData->Data)*100;
+ GlobalFreePtr (OidData);
+
+ ODSEx("Media:%d\n",type->LinkType);
+ ODSEx("Speed=%d\n",type->LinkSpeed);
+
+ return Status;
+}
+
+
+/*!
+ \brief Scan the registry to retrieve the IP addresses of an adapter.
+ \param AdapterName String that contains the name of the adapter.
+ \param buffer A user allocated array of npf_if_addr that will be filled by the function.
+ \param NEntries Size of the array (in npf_if_addr).
+ \return If the function succeeds, the return value is nonzero.
+
+ This function grabs from the registry information like the IP addresses, the netmasks
+ and the broadcast addresses of an interface. The buffer passed by the user is filled with
+ npf_if_addr structures, each of which contains the data for a single address. If the buffer
+ is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
+ if you want only the first address.
+*/
+BOOLEAN PacketGetAddressesFromRegistry(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
+{
+ char *AdapterNameA;
+ WCHAR *AdapterNameU;
+ WCHAR *ifname;
+ HKEY SystemKey;
+ HKEY InterfaceKey;
+ HKEY ParametersKey;
+ HKEY TcpIpKey;
+ HKEY UnderTcpKey;
+ LONG status;
+ WCHAR String[1024+1];
+ DWORD RegType;
+ ULONG BufLen;
+ DWORD DHCPEnabled;
+ struct sockaddr_in *TmpAddr, *TmpBroad;
+ LONG naddrs,nmasks,StringPos;
+ DWORD ZeroBroadcast;
+
+ AdapterNameA = (char*)AdapterName;
+ if(AdapterNameA[1] != 0) { //ASCII
+ AdapterNameU = SChar2WChar(AdapterNameA);
+ AdapterName = AdapterNameU;
+ } else { //Unicode
+ AdapterNameU = NULL;
+ }
+ ifname = wcsrchr(AdapterName, '\\');
+ if (ifname == NULL)
+ ifname = AdapterName;
+ else
+ ifname++;
+ if (wcsncmp(ifname, L"SEE_", 4) == 0)
+ ifname += 4;
+
+ if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"), 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
+ {
+ status = RegOpenKeyEx(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+ }
+ else
+ {
+
+ // Query the registry key with the interface's adresses
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SYSTEM\\CurrentControlSet\\Services"),0,KEY_READ,&SystemKey);
+ if (status != ERROR_SUCCESS)
+ goto fail;
+ status = RegOpenKeyEx(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(SystemKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+ RegCloseKey(SystemKey);
+ status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(InterfaceKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+ RegCloseKey(InterfaceKey);
+ status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(ParametersKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+ RegCloseKey(ParametersKey);
+ BufLen = sizeof String;
+ }
+
+ BufLen = 4;
+ /* Try to detect if the interface has a zero broadcast addr */
+ status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen);
+ if (status != ERROR_SUCCESS)
+ ZeroBroadcast=0;
+
+ BufLen = 4;
+ /* See if DHCP is used by this system */
+ status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
+ if (status != ERROR_SUCCESS)
+ DHCPEnabled=0;
+
+
+ /* Retrieve the adrresses */
+ if(DHCPEnabled){
+
+ BufLen = sizeof String;
+ // Open the key with the addresses
+ status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ // scan the key to obtain the addresses
+ StringPos = 0;
+ for(naddrs = 0;naddrs <* NEntries;naddrs++){
+ TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
+
+ if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
+ TmpAddr->sin_family = AF_INET;
+
+ TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
+ TmpBroad->sin_family = AF_INET;
+ if(ZeroBroadcast==0)
+ TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
+ else
+ TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
+
+ while(*(String + StringPos) != 0)StringPos++;
+ StringPos++;
+
+ if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
+ break;
+ }
+ else break;
+ }
+
+ BufLen = sizeof String;
+ // Open the key with the netmasks
+ status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ // scan the key to obtain the masks
+ StringPos = 0;
+ for(nmasks = 0;nmasks < *NEntries;nmasks++){
+ TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
+
+ if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
+ TmpAddr->sin_family = AF_INET;
+
+ while(*(String + StringPos) != 0)StringPos++;
+ StringPos++;
+
+ if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
+ break;
+ }
+ else break;
+ }
+
+ // The number of masks MUST be equal to the number of adresses
+ if(nmasks != naddrs){
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ }
+ else{
+
+ BufLen = sizeof String;
+ // Open the key with the addresses
+ status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ // scan the key to obtain the addresses
+ StringPos = 0;
+ for(naddrs = 0;naddrs < *NEntries;naddrs++){
+ TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
+
+ if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
+ TmpAddr->sin_family = AF_INET;
+
+ TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
+ TmpBroad->sin_family = AF_INET;
+ if(ZeroBroadcast==0)
+ TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
+ else
+ TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
+
+ while(*(String + StringPos) != 0)StringPos++;
+ StringPos++;
+
+ if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
+ break;
+ }
+ else break;
+ }
+
+ BufLen = sizeof String;
+ // Open the key with the netmasks
+ status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
+ if (status != ERROR_SUCCESS) {
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ // scan the key to obtain the masks
+ StringPos = 0;
+ for(nmasks = 0;nmasks <* NEntries;nmasks++){
+ TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
+
+ if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
+ TmpAddr->sin_family = AF_INET;
+
+ while(*(String + StringPos) != 0)StringPos++;
+ StringPos++;
+
+ if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
+ break;
+ }
+ else break;
+ }
+
+ // The number of masks MUST be equal to the number of adresses
+ if(nmasks != naddrs){
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+ goto fail;
+ }
+
+ }
+
+ *NEntries = naddrs + 1;
+
+ RegCloseKey(TcpIpKey);
+ RegCloseKey(UnderTcpKey);
+
+ if (status != ERROR_SUCCESS) {
+ goto fail;
+ }
+
+
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ return TRUE;
+
+fail:
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ return FALSE;
+}
+
+/*!
+ \brief Adds the IPv6 addresses of an adapter to the ADAPTER_INFO structure that describes it.
+ \param AdInfo Pointer to the ADAPTER_INFO structure that keeps the information about the adapter.
+ \return If the function succeeds, the function returns TRUE.
+
+ \note the structure pointed by AdInfo must be initialized the an properly filled. In particular, AdInfo->Name
+ must be a valid capture device name.
+ \note uses the GetAdaptersAddresses() Ip Helper API function, so it works only on systems where IP Helper API
+ provides it (WinXP and successive).
+ \note we suppose that we are called after having acquired the AdaptersInfoMutex mutex
+*/
+#ifndef _WINNT4
+BOOLEAN PacketAddIP6Addresses(PADAPTER_INFO AdInfo)
+{
+ ULONG BufLen;
+ PIP_ADAPTER_ADDRESSES AdBuffer, TmpAddr;
+ PCHAR OrName;
+ PIP_ADAPTER_UNICAST_ADDRESS UnicastAddr;
+ struct sockaddr_storage *Addr;
+ INT AddrLen;
+
+ ODS("PacketAddIP6Addresses\n");
+
+ if(GetAdaptersAddressesPointer == NULL) return TRUE; // GetAdaptersAddresses() not present on this system,
+ // return immediately.
+
+ if(GetAdaptersAddressesPointer(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST| GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, NULL, &BufLen) != ERROR_BUFFER_OVERFLOW)
+ {
+ ODS("PacketAddIP6Addresses: GetAdaptersAddresses Failed\n");
+ return FALSE;
+ }
+
+ ODS("PacketAddIP6Addresses, retrieved needed storage for the call\n");
+
+ AdBuffer = GlobalAllocPtr(GMEM_MOVEABLE, BufLen);
+ if (AdBuffer == NULL) {
+ ODS("PacketAddIP6Addresses: GlobalAlloc Failed\n");
+ return FALSE;
+ }
+
+ if(GetAdaptersAddressesPointer(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST| GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, AdBuffer, &BufLen) != ERROR_SUCCESS)
+ {
+ ODS("PacketGetIP6AddressesIPH: GetAdaptersAddresses Failed\n");
+ GlobalFreePtr(AdBuffer);
+ return FALSE;
+ }
+
+ ODS("PacketAddIP6Addresses, retrieved addresses\n");
+
+ //
+ // Scan the list of adddresses obtained from the IP helper API
+ //
+ for(TmpAddr = AdBuffer; TmpAddr != NULL; TmpAddr = TmpAddr->Next)
+ {
+ OrName = AdInfo->Name + sizeof("\\device\\see_") - 1;
+
+ ODS("PacketAddIP6Addresses, external loop\n");
+ if(strcmp(TmpAddr->AdapterName, OrName) == 0)
+ {
+ // Found a corresponding adapter, scan its address list
+ for(UnicastAddr = TmpAddr->FirstUnicastAddress; UnicastAddr != NULL; UnicastAddr = UnicastAddr->Next)
+ {
+ ODS("PacketAddIP6Addresses, internal loop\n");
+
+ AddrLen = UnicastAddr->Address.iSockaddrLength;
+ Addr = (struct sockaddr_storage *)UnicastAddr->Address.lpSockaddr;
+ if(Addr->ss_family == AF_INET6)
+ {
+ // Be sure not to overflow the addresses buffer of this adapter
+ if(AdInfo->NNetworkAddresses >= MAX_NETWORK_ADDRESSES)
+ {
+ GlobalFreePtr(AdBuffer);
+ return FALSE;
+ }
+
+ memcpy(&(AdInfo->NetworkAddresses[AdInfo->NNetworkAddresses].IPAddress), Addr, AddrLen);
+ memset(&(AdInfo->NetworkAddresses[AdInfo->NNetworkAddresses].SubnetMask), 0, sizeof(struct sockaddr_storage));
+ memset(&(AdInfo->NetworkAddresses[AdInfo->NNetworkAddresses].Broadcast), 0, sizeof(struct sockaddr_storage));
+ AdInfo->NNetworkAddresses ++;
+ }
+ }
+ }
+ }
+
+ ODS("PacketAddIP6Addresses, finished parsing the addresses\n");
+
+ GlobalFreePtr(AdBuffer);
+
+ return TRUE;
+}
+#endif // _WINNT4
+
+/*!
+ \brief Check if a string contains the "1394" substring
+
+ We prevent opening of firewire adapters since they have non standard behaviors that can cause
+ problems with winpcap
+
+ \param AdapterDesc NULL-terminated ASCII string with the adapter's description
+ \return TRUE if the input string contains "1394"
+*/
+BOOLEAN IsFireWire(TCHAR *AdapterDesc)
+{
+ if(wcsstr(AdapterDesc, FIREWIRE_SUBSTR) != NULL)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*!
+ \brief Adds an entry to the adapter description list, gathering its values from the IP Helper API.
+ \param IphAd PIP_ADAPTER_INFO IP Helper API structure containing the parameters of the adapter that must be added to the list.
+ \return If the function succeeds, the return value is TRUE.
+ \note we suppose that we are called after having acquired the AdaptersInfoMutex mutex
+*/
+#ifndef _WINNT4
+BOOLEAN AddAdapterIPH(PIP_ADAPTER_INFO IphAd)
+{
+ PIP_ADAPTER_INFO AdList = NULL;
+ ULONG OutBufLen=0;
+ PADAPTER_INFO TmpAdInfo, SAdInfo;
+ PIP_ADDR_STRING TmpAddrStr;
+ UINT i;
+ struct sockaddr_in *TmpAddr;
+ CHAR TName[256];
+ LPADAPTER adapter;
+ PWCHAR UAdName;
+
+
+ // Create the NPF device name from the original device name
+ strcpy(TName, "\\Device\\SEE_");
+ _snprintf(TName + 12, ADAPTER_NAME_LENGTH - 12, "%s", IphAd->AdapterName);
+
+ // Scan the adapters list to see if this one is already present
+ for(SAdInfo = AdaptersInfoList; SAdInfo != NULL; SAdInfo = SAdInfo->Next)
+ {
+ if(strcmp(TName, SAdInfo->Name) == 0)
+ {
+ ODS("PacketGetAdaptersIPH: Adapter already present in the list\n");
+ goto SkipAd;
+ }
+ }
+
+ if(IphAd->Type == IF_TYPE_PPP || IphAd->Type == IF_TYPE_SLIP)
+ {
+ if (!WanPacketTestAdapter())
+ goto SkipAd;
+ }
+ else
+ {
+ //convert the string to unicode, as OpenAdapterNPF accepts unicode strings, only.
+ UAdName = SChar2WChar(TName);
+ if (UAdName == NULL)
+ {
+ ODS("AddAdapterIPH: unable to convert an ASCII string to UNICODE\n");
+ goto SkipAd;
+ }
+
+ adapter = PacketOpenAdapterNPF((PCHAR)UAdName);
+ GlobalFreePtr(UAdName);
+
+ if(adapter == NULL)
+ {
+ // We are not able to open this adapter. Skip to the next one.
+ ODS("PacketGetAdaptersIPH: unable to open the adapter\n");
+ goto SkipAd;
+ }
+ else
+ {
+ PacketCloseAdapter(adapter);
+ }
+ }
+
+ //
+ // Adapter valid and not yet present in the list. Allocate the ADAPTER_INFO structure
+ //
+ TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));
+ if (TmpAdInfo == NULL) {
+ ODS("PacketGetAdaptersIPH: GlobalAlloc Failed\n");
+ return FALSE;
+ }
+
+ // Copy the device name
+ strcpy(TmpAdInfo->Name, TName);
+
+ // Copy the description
+ _snprintf(TmpAdInfo->Description, ADAPTER_DESC_LENGTH, "%s", IphAd->Description);
+
+ // Copy the MAC address
+ TmpAdInfo->MacAddressLen = IphAd->AddressLength;
+
+ memcpy(TmpAdInfo->MacAddress,
+ IphAd->Address,
+ (MAX_MAC_ADDR_LENGTH<MAX_ADAPTER_ADDRESS_LENGTH)? MAX_MAC_ADDR_LENGTH:MAX_ADAPTER_ADDRESS_LENGTH);
+
+ // Calculate the number of IP addresses of this interface
+ for(TmpAddrStr = &IphAd->IpAddressList, i = 0; TmpAddrStr != NULL; TmpAddrStr = TmpAddrStr->Next, i++)
+ {
+
+ }
+
+ TmpAdInfo->NetworkAddresses = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_NETWORK_ADDRESSES * sizeof(npf_if_addr));
+ if (TmpAdInfo->NetworkAddresses == NULL) {
+ ODS("PacketGetAdaptersIPH: GlobalAlloc Failed\n");
+ GlobalFreePtr(TmpAdInfo);
+ return FALSE;
+ }
+
+ // Scan the addresses, convert them to addrinfo structures and put each of them in the list
+ for(TmpAddrStr = &IphAd->IpAddressList, i = 0; TmpAddrStr != NULL; TmpAddrStr = TmpAddrStr->Next)
+ {
+ TmpAddr = (struct sockaddr_in *)&(TmpAdInfo->NetworkAddresses[i].IPAddress);
+ if((TmpAddr->sin_addr.S_un.S_addr = inet_addr(TmpAddrStr->IpAddress.String))!= INADDR_NONE)
+ {
+ TmpAddr->sin_family = AF_INET;
+ TmpAddr = (struct sockaddr_in *)&(TmpAdInfo->NetworkAddresses[i].SubnetMask);
+ TmpAddr->sin_addr.S_un.S_addr = inet_addr(TmpAddrStr->IpMask.String);
+ TmpAddr->sin_family = AF_INET;
+ TmpAddr = (struct sockaddr_in *)&(TmpAdInfo->NetworkAddresses[i].Broadcast);
+ TmpAddr->sin_addr.S_un.S_addr = 0xffffffff; // Consider 255.255.255.255 as broadcast address since IP Helper API doesn't provide information about it
+ TmpAddr->sin_family = AF_INET;
+ i++;
+ }
+ }
+
+ TmpAdInfo->NNetworkAddresses = i;
+
+ // Now Add IPv6 Addresses
+ PacketAddIP6Addresses(TmpAdInfo);
+
+ if(IphAd->Type == IF_TYPE_PPP || IphAd->Type == IF_TYPE_SLIP)
+ {
+ // NdisWan adapter
+ TmpAdInfo->Flags = INFO_FLAG_NDISWAN_ADAPTER;
+ }
+
+ // Update the AdaptersInfo list
+ TmpAdInfo->Next = AdaptersInfoList;
+ AdaptersInfoList = TmpAdInfo;
+
+SkipAd:
+
+ return TRUE;
+}
+#endif // _WINNT4
+
+
+/*!
+ \brief Updates the list of the adapters querying the IP Helper API.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function populates the list of adapter descriptions, retrieving the information from a query to
+ the IP Helper API. The IP Helper API is used as a support of the standard registry query method to obtain
+ adapter information, so PacketGetAdaptersIPH() add only information about the adapters that were not
+ found by PacketGetAdapters().
+*/
+#ifndef _WINNT4
+BOOLEAN PacketGetAdaptersIPH()
+{
+ PIP_ADAPTER_INFO AdList = NULL;
+ PIP_ADAPTER_INFO TmpAd;
+ ULONG OutBufLen=0;
+
+ ODS("PacketGetAdaptersIPH\n");
+
+ // Find the size of the buffer filled by GetAdaptersInfo
+ if(GetAdaptersInfo(AdList, &OutBufLen) == ERROR_NOT_SUPPORTED)
+ {
+ ODS("IP Helper API not supported on this system!\n");
+ return FALSE;
+ }
+
+ ODS("PacketGetAdaptersIPH: retrieved needed bytes for IPH\n");
+
+ // Allocate the buffer
+ AdList = GlobalAllocPtr(GMEM_MOVEABLE, OutBufLen);
+ if (AdList == NULL) {
+ ODS("PacketGetAdaptersIPH: GlobalAlloc Failed\n");
+ return FALSE;
+ }
+
+ // Retrieve the adapters information using the IP helper API
+ GetAdaptersInfo(AdList, &OutBufLen);
+
+ ODS("PacketGetAdaptersIPH: retrieved list from IPH\n");
+
+ // Scan the list of adapters obtained from the IP helper API, create a new ADAPTER_INFO
+ // structure for every new adapter and put it in our global list
+ for(TmpAd = AdList; TmpAd != NULL; TmpAd = TmpAd->Next)
+ {
+ AddAdapterIPH(TmpAd);
+ }
+
+ GlobalFreePtr(AdList);
+
+ return TRUE;
+}
+#endif // _WINNT4
+
+
+/*!
+ \brief Adds an entry to the adapter description list.
+ \param AdName Name of the adapter to add
+ \return If the function succeeds, the return value is nonzero.
+
+ Used by PacketGetAdapters(). Queries the registry to fill the PADAPTER_INFO describing the new adapter.
+*/
+BOOLEAN AddAdapter(PCHAR AdName, UINT flags)
+{
+ //this function should acquire the AdaptersInfoMutex, since it's NOT called with an ADAPTER_INFO as parameter
+ DWORD RegKeySize=0;
+ LONG Status;
+ LPADAPTER adapter;
+ PPACKET_OID_DATA OidData;
+ int i=0;
+ PADAPTER_INFO TmpAdInfo;
+ PADAPTER_INFO TAdInfo;
+ PWCHAR UAdName;
+
+ ODS("AddAdapter\n");
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+
+ for(TAdInfo = AdaptersInfoList; TAdInfo != NULL; TAdInfo = TAdInfo->Next)
+ {
+ if(strcmp(AdName, TAdInfo->Name) == 0)
+ {
+ ODS("AddAdapter: Adapter already present in the list\n");
+ ReleaseMutex(AdaptersInfoMutex);
+ return TRUE;
+ }
+ }
+
+ UAdName = SChar2WChar(AdName);
+
+ //here we could have released the mutex, but what happens if two threads try to add the same adapter?
+ //The adapter would be duplicated on the linked list
+
+ if(flags != INFO_FLAG_DONT_EXPORT)
+ {
+
+ // Try to Open the adapter
+ adapter = PacketOpenAdapterNPF((PCHAR)UAdName);
+
+ GlobalFreePtr(UAdName);
+
+ if(adapter == NULL)
+ {
+ // We are not able to open this adapter. Skip to the next one.
+ ReleaseMutex(AdaptersInfoMutex);
+ return FALSE;
+ }
+
+ // Allocate a buffer to get the vendor description from the driver
+ OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,512);
+ if (OidData == NULL)
+ {
+ ODS("AddAdapter: GlobalAlloc Failed\n");
+ PacketCloseAdapter(adapter);
+ ReleaseMutex(AdaptersInfoMutex);
+ return FALSE;
+ }
+ }
+
+ //
+ // PacketOpenAdapter was succesful. Consider this a valid adapter and allocate an entry for it
+ // In the adapter list
+ //
+
+ TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));
+ if (TmpAdInfo == NULL)
+ {
+ ODS("AddAdapter: GlobalAlloc Failed\n");
+ GlobalFreePtr(OidData);
+ PacketCloseAdapter(adapter);
+ ReleaseMutex(AdaptersInfoMutex);
+ return FALSE;
+ }
+
+ // Copy the device name
+ strcpy(TmpAdInfo->Name, AdName);
+
+ if(flags != INFO_FLAG_DONT_EXPORT)
+ {
+ // Retrieve the adapter description querying the NIC driver
+ OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
+ OidData->Length = 256;
+ ZeroMemory(OidData->Data, 256);
+
+ Status = PacketRequest(adapter, FALSE, OidData);
+
+ if(Status==0 || ((char*)OidData->Data)[0]==0)
+ {
+ ODS("AddAdapter: unable to get a valid adapter description from the NIC driver\n");
+ }
+
+ ODSEx("Adapter Description=%s\n\n",OidData->Data);
+
+ // Copy the description
+ strcpy(TmpAdInfo->Description, OidData->Data);
+
+ PacketGetLinkLayerFromRegistry(adapter, &(TmpAdInfo->LinkLayer));
+
+ // Retrieve the adapter MAC address querying the NIC driver
+ OidData->Oid = OID_802_3_CURRENT_ADDRESS; // XXX At the moment only Ethernet is supported.
+ // Waiting a patch to support other Link Layers
+ OidData->Length = 256;
+ ZeroMemory(OidData->Data, 256);
+
+ Status = PacketRequest(adapter, FALSE, OidData);
+ if(Status)
+ {
+ memcpy(TmpAdInfo->MacAddress, OidData->Data, 6);
+ TmpAdInfo->MacAddressLen = 6;
+ }
+ else
+ {
+ memset(TmpAdInfo->MacAddress, 0, 6);
+ TmpAdInfo->MacAddressLen = 0;
+ }
+
+ // Retrieve IP addresses
+ TmpAdInfo->NetworkAddresses = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_NETWORK_ADDRESSES * sizeof(npf_if_addr));
+ if (TmpAdInfo->NetworkAddresses == NULL) {
+ ODS("AddAdapter: GlobalAlloc Failed\n");
+ PacketCloseAdapter(adapter);
+ GlobalFreePtr(OidData);
+ GlobalFreePtr(TmpAdInfo);
+ ReleaseMutex(AdaptersInfoMutex);
+ return FALSE;
+ }
+
+ TmpAdInfo->NNetworkAddresses = MAX_NETWORK_ADDRESSES;
+ if(!PacketGetAddressesFromRegistry((LPTSTR)TmpAdInfo->Name, TmpAdInfo->NetworkAddresses, &TmpAdInfo->NNetworkAddresses))
+ {
+#ifndef _WINNT4
+ // Try to see if the interface has some IPv6 addresses
+ TmpAdInfo->NNetworkAddresses = 0; // We have no addresses because PacketGetAddressesFromRegistry() failed
+
+ if(!PacketAddIP6Addresses(TmpAdInfo))
+ {
+#endif // _WINNT4
+ GlobalFreePtr(TmpAdInfo->NetworkAddresses);
+ TmpAdInfo->NetworkAddresses = NULL;
+ TmpAdInfo->NNetworkAddresses = 0;
+#ifndef _WINNT4
+ }
+#endif // _WINNT4
+ }
+
+#ifndef _WINNT4
+ // Now Add IPv6 Addresses
+ PacketAddIP6Addresses(TmpAdInfo);
+#endif // _WINNT4
+
+ TmpAdInfo->Flags = INFO_FLAG_NDIS_ADAPTER; // NdisWan adapters are not exported by the NPF driver,
+ // therefore it's impossible to see them here
+
+ // Free storage
+ PacketCloseAdapter(adapter);
+ GlobalFreePtr(OidData);
+ }
+ else
+ {
+ // Write in the flags that this adapter is firewire
+ // This will block it in all successive calls
+ TmpAdInfo->Flags = INFO_FLAG_DONT_EXPORT;
+ }
+
+ // Update the AdaptersInfo list
+ TmpAdInfo->Next = AdaptersInfoList;
+ AdaptersInfoList = TmpAdInfo;
+
+ ReleaseMutex(AdaptersInfoMutex);
+ return TRUE;
+}
+
+
+/*!
+ \brief Updates the list of the adapters querying the registry.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function populates the list of adapter descriptions, retrieving the information from the registry.
+*/
+BOOLEAN PacketGetAdapters()
+{
+ HKEY LinkageKey,AdapKey, OneAdapKey;
+ DWORD RegKeySize=0;
+ LONG Status;
+ ULONG Result;
+ INT i=0,k;
+ DWORD dim;
+ DWORD RegType;
+ WCHAR TName[256];
+ CHAR TAName[256];
+ TCHAR AdapName[256];
+ PTSTR BpStr;
+ UINT FireWireFlag;
+
+ ODS("PacketGetAdapters\n");
+
+ Status=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
+ 0,
+ KEY_READ,
+ &AdapKey);
+
+ if ( Status != ERROR_SUCCESS ){
+ ODS("PacketGetAdapters: RegOpenKeyEx ( Class\\{networkclassguid} ) Failed\n");
+ goto nt4;
+ }
+
+ i=0;
+
+ ODS("PacketGetAdapters: Cycling through the adapters:\n");
+
+ //
+ // Cycle through the entries inside the {4D36E972-E325-11CE-BFC1-08002BE10318} key
+ // To get the names of the adapters
+ //
+ while((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS)
+ {
+ i++;
+ ODSEx(" %d) ", i);
+ FireWireFlag = 0;
+
+ //
+ // Get the adapter name from the registry key
+ //
+ Status=RegOpenKeyEx(AdapKey, AdapName, 0, KEY_READ, &OneAdapKey);
+ if ( Status != ERROR_SUCCESS )
+ {
+ ODS("PacketGetAdapters: RegOpenKeyEx ( OneAdapKey ) Failed\n");
+ continue;
+ }
+
+ //
+ //
+ // Check if this is a FireWire adapter, looking for "1394" in its ComponentId string.
+ // We prevent listing FireWire adapters because winpcap can open them, but their interface
+ // with the OS is broken and they can cause blue screens.
+ //
+ dim = sizeof(TName);
+ Status = RegQueryValueEx(OneAdapKey,
+ L"ComponentId",
+ NULL,
+ NULL,
+ (PBYTE)TName,
+ &dim);
+
+ if(Status == ERROR_SUCCESS)
+ {
+ if(IsFireWire(TName))
+ {
+ FireWireFlag = INFO_FLAG_DONT_EXPORT;
+ }
+ }
+
+ Status=RegOpenKeyEx(OneAdapKey, L"Linkage", 0, KEY_READ, &LinkageKey);
+ if (Status != ERROR_SUCCESS)
+ {
+ RegCloseKey(OneAdapKey);
+ ODS("PacketGetAdapters: RegOpenKeyEx ( LinkageKey ) Failed\n");
+ continue;
+ }
+
+ dim = sizeof(TName);
+ Status=RegQueryValueEx(LinkageKey,
+ L"Export",
+ NULL,
+ NULL,
+ (PBYTE)TName,
+ &dim);
+
+ if(Status != ERROR_SUCCESS)
+ {
+ RegCloseKey(OneAdapKey);
+ RegCloseKey(LinkageKey);
+ ODS("Name = SKIPPED (error reading the key)\n");
+ continue;
+ }
+
+ // Conver to ASCII
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ TName, // wide-character string
+ -1, // number of chars in string
+ TAName + sizeof("\\Device\\SEE_") - sizeof("\\Device\\"), // buffer for new string
+ sizeof(TAName) - sizeof("\\Device\\SEE_") + sizeof("\\Device\\"), // size of buffer
+ NULL,
+ NULL);
+
+ // Put the \Device\NPF_ string at the beginning of the name
+ memcpy(TAName, "\\Device\\SEE_", sizeof("\\Device\\SEE_") - 1);
+
+ // If the adapter is valid, add it to the list.
+ AddAdapter(TAName, FireWireFlag);
+
+ RegCloseKey(OneAdapKey);
+ RegCloseKey(LinkageKey);
+
+ } // while enum reg keys
+
+ RegCloseKey(AdapKey);
+
+nt4:
+ //
+ // no adapters were found under {4D36E972-E325-11CE-BFC1-08002BE10318}. This means with great probability
+ // that we are under Windows NT 4, so we try to look under the tcpip bindings.
+ //
+
+ ODS("Adapters not found under SYSTEM\\CurrentControlSet\\Control\\Class. Using the TCP/IP bindings.\n");
+
+ Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage"),
+ 0,
+ KEY_READ,
+ &LinkageKey);
+
+ if (Status == ERROR_SUCCESS)
+ {
+ // Retrieve the length of th binde key
+ Status=RegQueryValueEx(LinkageKey,
+ TEXT("bind"),
+ NULL,
+ &RegType,
+ NULL,
+ &RegKeySize);
+
+ // Allocate the buffer
+ BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
+
+ if (BpStr == NULL)
+ {
+ return FALSE;
+ }
+
+ // Query the key again to get its content
+ Status = RegQueryValueEx(LinkageKey,
+ TEXT("bind"),
+ NULL,
+ &RegType,
+ (LPBYTE)BpStr,
+ &RegKeySize);
+
+ RegCloseKey(LinkageKey);
+
+ // Scan the buffer with the device names
+ for(i = 0;;)
+ {
+ if((k = _snprintf(TAName + sizeof("\\Device\\SEE_") - sizeof("\\Device\\"), sizeof(TAName), "%S", BpStr + i)) == 0)
+ break;
+
+ // Put the \Device\NPF_ string at the beginning of the name
+ memcpy(TAName, "\\Device\\SEE_", sizeof("\\Device\\SEE_") - 1);
+
+ // If the adapter is valid, add it to the list.
+ AddAdapter(TAName, 0);
+
+ i += k + 1;
+ }
+
+ GlobalFreePtr(BpStr);
+ }
+
+ else{
+#ifdef _WINNT4
+ return FALSE;
+#endif
+ }
+
+ return TRUE;
+}
+
+#ifdef HAVE_DAG_API
+/*!
+ \brief Add a dag adapter to the adapters info list, gathering information from the dagc API
+ \param name Name of the adapter.
+ \param description description of the adapter.
+ \return If the function succeeds, the return value is nonzero.
+*/
+BOOLEAN PacketAddAdapterDag(PCHAR name, PCHAR description, BOOLEAN IsAFile)
+{
+ //this function should acquire the AdaptersInfoMutex, since it's NOT called with an ADAPTER_INFO as parameter
+ CHAR ebuf[DAGC_ERRBUF_SIZE];
+ PADAPTER_INFO TmpAdInfo;
+ dagc_t *dagfd;
+
+ //XXX what about checking if the adapter already exists???
+
+ //
+ // Allocate a descriptor for this adapter
+ //
+ //here we do not acquire the mutex, since we are not touching the list, yet.
+ TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));
+ if (TmpAdInfo == NULL)
+ {
+ ODS("PacketAddAdapterDag: GlobalAlloc Failed\n");
+ return FALSE;
+ }
+
+ // Copy the device name and description
+ _snprintf(TmpAdInfo->Name,
+ sizeof(TmpAdInfo->Name),
+ "%s",
+ name);
+
+ _snprintf(TmpAdInfo->Description,
+ sizeof(TmpAdInfo->Description),
+ "%s",
+ description);
+
+ if(IsAFile)
+ TmpAdInfo->Flags = INFO_FLAG_DAG_FILE;
+ else
+ TmpAdInfo->Flags = INFO_FLAG_DAG_CARD;
+
+ if(p_dagc_open)
+ dagfd = p_dagc_open(name, 0, ebuf);
+ else
+ dagfd = NULL;
+
+ if(!dagfd)
+ {
+ GlobalFreePtr(TmpAdInfo);
+ return FALSE;
+ }
+
+ TmpAdInfo->LinkLayer.LinkType = p_dagc_getlinktype(dagfd);
+
+ switch(p_dagc_getlinktype(dagfd))
+ {
+ case TYPE_HDLC_POS:
+ TmpAdInfo->LinkLayer.LinkType = NdisMediumCHDLC; // Note: custom linktype, NDIS doesn't provide an equivalent
+ break;
+ case -TYPE_HDLC_POS:
+ TmpAdInfo->LinkLayer.LinkType = NdisMediumPPPSerial; // Note: custom linktype, NDIS doesn't provide an equivalent
+ break;
+ case TYPE_ETH:
+ TmpAdInfo->LinkLayer.LinkType = NdisMedium802_3;
+ break;
+ case TYPE_ATM:
+ TmpAdInfo->LinkLayer.LinkType = NdisMediumAtm;
+ break;
+ default:
+ TmpAdInfo->LinkLayer.LinkType = NdisMediumNull; // Note: custom linktype, NDIS doesn't provide an equivalent
+ break;
+ }
+
+ TmpAdInfo->LinkLayer.LinkSpeed = (p_dagc_getlinkspeed(dagfd) == -1)?
+ 100000000: // Unknown speed, default to 100Mbit
+ p_dagc_getlinkspeed(dagfd) * 1000000;
+
+ p_dagc_close(dagfd);
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+
+ // Update the AdaptersInfo list
+ TmpAdInfo->Next = AdaptersInfoList;
+ AdaptersInfoList = TmpAdInfo;
+
+ ReleaseMutex(AdaptersInfoMutex);
+
+ return TRUE;
+}
+
+/*!
+ \brief Updates the list of the adapters using the DAGC API.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function populates the list of adapter descriptions, looking for DAG cards on the system.
+*/
+BOOLEAN PacketGetAdaptersDag()
+{
+ CHAR ebuf[DAGC_ERRBUF_SIZE];
+ dagc_if_t *devs = NULL, *tmpdevs;
+ UINT i;
+
+ if(p_dagc_finddevs(&devs, ebuf))
+ // No dag cards found on this system
+ return FALSE;
+ else
+ {
+ for(tmpdevs = devs, i=0; tmpdevs != NULL; tmpdevs = tmpdevs->next)
+ {
+ PacketAddAdapterDag(tmpdevs->name, tmpdevs->description, FALSE);
+ }
+ }
+
+ p_dagc_freedevs(devs);
+
+ return TRUE;
+}
+#endif // HAVE_DAG_API
+
+/*!
+\brief Find the information about an adapter scanning the global ADAPTER_INFO list.
+ \param AdapterName Name of the adapter whose information has to be retrieved.
+ \return If the function succeeds, the return value is non-null.
+*/
+PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName)
+{
+ //this function should NOT acquire the AdaptersInfoMutex, since it does return an ADAPTER_INFO structure
+ PADAPTER_INFO TAdInfo;
+
+ if (AdaptersInfoList == NULL)
+ PacketPopulateAdaptersInfoList();
+
+ TAdInfo = AdaptersInfoList;
+
+ while(TAdInfo != NULL)
+ {
+ if(strcmp(TAdInfo->Name, AdapterName) == 0) break;
+
+ TAdInfo = TAdInfo->Next;
+ }
+
+ return TAdInfo;
+}
+
+
+
+/*!
+ \brief Updates information about an adapter in the global ADAPTER_INFO list.
+ \param AdapterName Name of the adapter whose information has to be retrieved.
+ \return If the function succeeds, the return value is TRUE. A false value means that the adapter is no
+ more valid or that it is disconnected.
+*/
+BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName)
+{
+ //this function should acquire the AdaptersInfoMutex, since it's NOT called with an ADAPTER_INFO as parameter
+ PADAPTER_INFO TAdInfo, PrevAdInfo;
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+
+ PrevAdInfo = TAdInfo = AdaptersInfoList;
+
+ //
+ // If an entry for this adapter is present in the list, we destroy it
+ //
+ while(TAdInfo != NULL)
+ {
+ if(strcmp(TAdInfo->Name, AdapterName) == 0)
+ {
+ if (strcmp(AdapterName, FAKE_NDISWAN_ADAPTER_NAME) == 0)
+ {
+ ReleaseMutex(AdaptersInfoMutex);
+ return TRUE;
+ }
+
+ if(TAdInfo == AdaptersInfoList)
+ {
+ AdaptersInfoList = TAdInfo->Next;
+ }
+ else
+ {
+ PrevAdInfo->Next = TAdInfo->Next;
+ }
+
+ if (TAdInfo->NetworkAddresses != NULL)
+ GlobalFreePtr(TAdInfo->NetworkAddresses);
+ GlobalFreePtr(TAdInfo);
+
+ break;
+ }
+
+ PrevAdInfo = TAdInfo;
+
+ TAdInfo = TAdInfo->Next;
+ }
+
+ ReleaseMutex(AdaptersInfoMutex);
+
+ //
+ // Now obtain the information about this adapter
+ //
+ if(AddAdapter(AdapterName, 0) == TRUE)
+ return TRUE;
+#ifndef _WINNT4
+ //
+ // Not a tradiditonal adapter, but possibly a Wan or DAG interface
+ // Gather all the available adapters from IPH API and dagc API
+ //
+ PacketGetAdaptersIPH();
+ PacketAddFakeNdisWanAdapter();
+#ifdef HAVE_DAG_API
+ if(p_dagc_open == NULL)
+ return TRUE; // dagc.dll not present on this system.
+ else
+ PacketGetAdaptersDag();
+#endif // HAVE_DAG_API
+
+#endif // _WINNT4
+
+ // Adapter not found
+ return TRUE;
+}
+
+/*!
+ \brief Populates the list of the adapters.
+
+ This function populates the list of adapter descriptions, invoking first PacketGetAdapters() and then
+ PacketGetAdaptersIPH().
+*/
+void PacketPopulateAdaptersInfoList()
+{
+ //this function should acquire the AdaptersInfoMutex, since it's NOT called with an ADAPTER_INFO as parameter
+ PADAPTER_INFO TAdInfo;
+ PVOID Mem1, Mem2;
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+
+ if(AdaptersInfoList)
+ {
+ // Free the old list
+ TAdInfo = AdaptersInfoList;
+ while(TAdInfo != NULL)
+ {
+ Mem1 = TAdInfo->NetworkAddresses;
+ Mem2 = TAdInfo;
+
+ TAdInfo = TAdInfo->Next;
+
+ if (Mem1 != NULL)
+ GlobalFreePtr(Mem1);
+ GlobalFreePtr(Mem2);
+ }
+
+ AdaptersInfoList = NULL;
+ }
+
+ //
+ // Fill the new list
+ //
+ if(!PacketGetAdapters())
+ {
+ // No info about adapters in the registry.
+ ODS("PacketPopulateAdaptersInfoList: registry scan for adapters failed!\n");
+ }
+#ifndef _WINNT4
+ if(!PacketGetAdaptersIPH())
+ {
+ // IP Helper API not present. We are under WinNT 4 or TCP/IP is not installed
+ ODS("PacketPopulateAdaptersInfoList: failed to get adapters from the IP Helper API!\n");
+ }
+
+ if (!PacketAddFakeNdisWanAdapter())
+ {
+ ODS("PacketPopulateAdaptersInfoList: adding fake NdisWan adapter failed.\n");
+ }
+
+#ifdef HAVE_DAG_API
+ if(p_dagc_open == NULL)
+ {} // dagc.dll not present on this system.
+ else
+ {
+ if(!PacketGetAdaptersDag())
+ {
+ // No info about adapters in the registry.
+ ODS("PacketPopulateAdaptersInfoList: lookup of dag cards failed!\n");
+ }
+ }
+#endif // HAVE_DAG_API
+
+#endif // _WINNT4
+
+ ReleaseMutex(AdaptersInfoMutex);
+}
+
+#ifndef _WINNT4
+
+BOOL PacketAddFakeNdisWanAdapter()
+{
+ //this function should acquire the AdaptersInfoMutex, since it's NOT called with an ADAPTER_INFO as parameter
+ PADAPTER_INFO TmpAdInfo, SAdInfo;
+
+ // Scan the adapters list to see if this one is already present
+
+ if (!WanPacketTestAdapter())
+ {
+ ODS("Cannot add the adapter, since it cannot be opened.");
+ //the adapter cannot be opened, we do not list it, but we return t
+ return FALSE;
+ }
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+
+ for(SAdInfo = AdaptersInfoList; SAdInfo != NULL; SAdInfo = SAdInfo->Next)
+ {
+ if(strcmp(FAKE_NDISWAN_ADAPTER_NAME, SAdInfo->Name) == 0)
+ {
+ ODS("PacketAddFakeNdisWanAdapter: Adapter already present in the list\n");
+ ReleaseMutex(AdaptersInfoMutex);
+ return TRUE;
+ }
+ }
+
+ TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));
+ if (TmpAdInfo == NULL)
+ {
+ ODS("PacketAddFakeNdisWanAdapter: GlobalAlloc Failed\n");
+ ReleaseMutex(AdaptersInfoMutex);
+ return FALSE;
+ }
+
+ strcpy(TmpAdInfo->Name, FAKE_NDISWAN_ADAPTER_NAME);
+ strcpy(TmpAdInfo->Description, FAKE_NDISWAN_ADAPTER_DESCRIPTION);
+ TmpAdInfo->LinkLayer.LinkType = NdisMedium802_3;
+ TmpAdInfo->LinkLayer.LinkSpeed = 10 * 1000 * 1000; //we emulate a fake 10MBit Ethernet
+ TmpAdInfo->Flags = INFO_FLAG_NDISWAN_ADAPTER;
+ memset(TmpAdInfo->MacAddress,'0',6);
+ TmpAdInfo->MacAddressLen = 6;
+ TmpAdInfo->NetworkAddresses = NULL;
+ TmpAdInfo->NNetworkAddresses = 0;
+
+ TmpAdInfo->Next = AdaptersInfoList;
+ AdaptersInfoList = TmpAdInfo;
+ ReleaseMutex(AdaptersInfoMutex);
+
+ return TRUE;
+}
+
+#endif
diff --git a/src/SeeDll/Devioctl.h b/src/SeeDll/Devioctl.h
new file mode 100644
index 00000000..af8784bf
--- /dev/null
+++ b/src/SeeDll/Devioctl.h
@@ -0,0 +1,90 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+ Copyright (c) 1992-1993 Microsoft Corporation
+ Module Name:
+ devioctl.h
+ Revision History:
+ -- */
+// begin_winioctl
+#ifndef _DEVIOCTL_
+#define _DEVIOCTL_
+// begin_ntddk begin_nthal begin_ntifs
+//
+// Define the various device type values. Note that values used by Microsoft
+// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
+// by customers.
+//
+#define DEVICE_TYPE ULONG
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+//
+// Macro definition for defining IOCTL and FSCTL function control codes. Note
+// that function codes 0-2047 are reserved for Microsoft Corporation, and
+// 2048-4095 are reserved for customers.
+//
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+//
+// Define the method codes for how buffers are passed for I/O and FS controls
+//
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+//
+// Define the access check value for any access
+//
+//
+// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+// constants *MUST* always be in sync.
+//
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+// end_ntddk end_nthal end_ntifs
+#endif // _DEVIOCTL_
+// end_winioctl
diff --git a/src/SeeDll/Ntddndis.h b/src/SeeDll/Ntddndis.h
new file mode 100644
index 00000000..0b629806
--- /dev/null
+++ b/src/SeeDll/Ntddndis.h
@@ -0,0 +1,1400 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+ Copyright (c) 1990-1993 Microsoft Corporation
+ Module Name:
+ ntddndis.h
+ Abstract:
+ This is the include file that defines all constants and types for
+ accessing the Network driver interface device.
+ Author:
+ Steve Wood (stevewo) 27-May-1990
+ Revision History:
+ Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0.
+ Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures
+ Kyle Brandon (kyleb) 09/24/96 added general co ndis oids.
+ -- */
+#ifndef _NTDDNDIS_
+#define _NTDDNDIS_
+//
+// Device Name - this string is the name of the device. It is the name
+// that should be passed to NtOpenFile when accessing the device.
+//
+// Note: For devices that support multiple units, it should be suffixed
+// with the Ascii representation of the unit number.
+//
+#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN"
+//
+// NtDeviceIoControlFile IoControlCode values for this device.
+//
+// Warning: Remember that the low two bits of the code specify how the
+// buffers are passed to the driver!
+//
+#define _NDIS_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED )
+#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED )
+#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED )
+#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED )
+#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED )
+#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT )
+//
+// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for
+// this device.
+//
+//
+// This is the type of an NDIS OID value.
+//
+typedef ULONG NDIS_OID, *PNDIS_OID;
+//
+// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed
+// together (no padding is required since statistics all have
+// four or eight bytes of data).
+//
+typedef struct _NDIS_STATISTICS_VALUE {
+ NDIS_OID Oid;
+ ULONG DataLength;
+ UCHAR Data[1]; // variable length
+
+} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE;
+
+//
+// Structure used by TRANSLATE_NAME IOCTL
+//
+typedef struct _NET_PNP_ID {
+ ULONG ClassId;
+ ULONG Token;
+} NET_PNP_ID, *PNET_PNP_ID;
+
+typedef struct _NET_PNP_TRANSLATE_LIST {
+ ULONG BytesNeeded;
+ NET_PNP_ID IdArray[ANYSIZE_ARRAY];
+} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST;
+
+//
+// Structure used to define a self-contained variable data structure
+//
+typedef struct _NDIS_VAR_DATA_DESC {
+ USHORT Length; // # of octects of data
+
+ USHORT MaximumLength; // # of octects available
+
+ LONG Offset; // Offset of data relative to the descriptor
+
+} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC;
+
+//
+// Object Identifiers used by NdisRequest Query/Set Information
+//
+//
+// General Objects
+//
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+//
+// These are connection-oriented general OIDs.
+// These replace the above OIDs for connection-oriented media.
+//
+#define OID_GEN_CO_SUPPORTED_LIST 0x00010101
+#define OID_GEN_CO_HARDWARE_STATUS 0x00010102
+#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_CO_MEDIA_IN_USE 0x00010104
+#define OID_GEN_CO_LINK_SPEED 0x00010105
+#define OID_GEN_CO_VENDOR_ID 0x00010106
+#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
+#define OID_GEN_CO_DRIVER_VERSION 0x00010108
+#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
+#define OID_GEN_CO_MAC_OPTIONS 0x0001010A
+#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
+#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
+#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
+#define OID_GEN_CO_GET_TIME_CAPS 0x00010201
+#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202
+//
+// These are connection-oriented statistics OIDs.
+//
+#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101
+#define OID_GEN_CO_RCV_PDUS_OK 0x00020102
+#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
+#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
+#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
+#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201
+#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
+#define OID_GEN_CO_BYTES_XMIT 0x00020203
+#define OID_GEN_CO_BYTES_RCV 0x00020204
+#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
+#define OID_GEN_CO_NETCARD_LOAD 0x00020206
+//
+// These are objects for Connection-oriented media call-managers and are not
+// valid for ndis drivers. Under construction.
+//
+#define OID_CO_ADD_PVC 0xFF000001
+#define OID_CO_DELETE_PVC 0xFF000002
+#define OID_CO_GET_CALL_INFORMATION 0xFF000003
+#define OID_CO_ADD_ADDRESS 0xFF000004
+#define OID_CO_DELETE_ADDRESS 0xFF000005
+#define OID_CO_GET_ADDRESSES 0xFF000006
+#define OID_CO_ADDRESS_CHANGE 0xFF000007
+#define OID_CO_SIGNALING_ENABLED 0xFF000008
+#define OID_CO_SIGNALING_DISABLED 0xFF000009
+//
+// 802.3 Objects (Ethernet)
+//
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+//
+//
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+//
+// 802.5 Objects (Token-Ring)
+//
+#define OID_802_5_PERMANENT_ADDRESS 0x02010101
+#define OID_802_5_CURRENT_ADDRESS 0x02010102
+#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103
+#define OID_802_5_CURRENT_GROUP 0x02010104
+#define OID_802_5_LAST_OPEN_STATUS 0x02010105
+#define OID_802_5_CURRENT_RING_STATUS 0x02010106
+#define OID_802_5_CURRENT_RING_STATE 0x02010107
+#define OID_802_5_LINE_ERRORS 0x02020101
+#define OID_802_5_LOST_FRAMES 0x02020102
+#define OID_802_5_BURST_ERRORS 0x02020201
+#define OID_802_5_AC_ERRORS 0x02020202
+#define OID_802_5_ABORT_DELIMETERS 0x02020203
+#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204
+#define OID_802_5_FREQUENCY_ERRORS 0x02020205
+#define OID_802_5_TOKEN_ERRORS 0x02020206
+#define OID_802_5_INTERNAL_ERRORS 0x02020207
+//
+// FDDI Objects
+//
+#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101
+#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102
+#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103
+#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104
+#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105
+#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106
+#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107
+#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108
+#define OID_FDDI_ATTACHMENT_TYPE 0x03020101
+#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102
+#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103
+#define OID_FDDI_FRAME_ERRORS 0x03020104
+#define OID_FDDI_FRAMES_LOST 0x03020105
+#define OID_FDDI_RING_MGT_STATE 0x03020106
+#define OID_FDDI_LCT_FAILURES 0x03020107
+#define OID_FDDI_LEM_REJECTS 0x03020108
+#define OID_FDDI_LCONNECTION_STATE 0x03020109
+#define OID_FDDI_SMT_STATION_ID 0x03030201
+#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202
+#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203
+#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204
+#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205
+#define OID_FDDI_SMT_USER_DATA 0x03030206
+#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207
+#define OID_FDDI_SMT_MAC_CT 0x03030208
+#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209
+#define OID_FDDI_SMT_MASTER_CT 0x0303020A
+#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B
+#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C
+#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D
+#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E
+#define OID_FDDI_SMT_T_NOTIFY 0x0303020F
+#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210
+#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211
+#define OID_FDDI_SMT_PORT_INDEXES 0x03030212
+#define OID_FDDI_SMT_MAC_INDEXES 0x03030213
+#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214
+#define OID_FDDI_SMT_ECM_STATE 0x03030215
+#define OID_FDDI_SMT_CF_STATE 0x03030216
+#define OID_FDDI_SMT_HOLD_STATE 0x03030217
+#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218
+#define OID_FDDI_SMT_STATION_STATUS 0x03030219
+#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A
+#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B
+#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C
+#define OID_FDDI_SMT_SET_COUNT 0x0303021D
+#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E
+#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F
+#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220
+#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221
+#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222
+#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223
+#define OID_FDDI_MAC_CURRENT_PATH 0x03030224
+#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225
+#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226
+#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227
+#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228
+#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229
+#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A
+#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B
+#define OID_FDDI_MAC_INDEX 0x0303022C
+#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D
+#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E
+#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F
+#define OID_FDDI_MAC_T_REQ 0x03030230
+#define OID_FDDI_MAC_T_NEG 0x03030231
+#define OID_FDDI_MAC_T_MAX 0x03030232
+#define OID_FDDI_MAC_TVX_VALUE 0x03030233
+#define OID_FDDI_MAC_T_PRI0 0x03030234
+#define OID_FDDI_MAC_T_PRI1 0x03030235
+#define OID_FDDI_MAC_T_PRI2 0x03030236
+#define OID_FDDI_MAC_T_PRI3 0x03030237
+#define OID_FDDI_MAC_T_PRI4 0x03030238
+#define OID_FDDI_MAC_T_PRI5 0x03030239
+#define OID_FDDI_MAC_T_PRI6 0x0303023A
+#define OID_FDDI_MAC_FRAME_CT 0x0303023B
+#define OID_FDDI_MAC_COPIED_CT 0x0303023C
+#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D
+#define OID_FDDI_MAC_TOKEN_CT 0x0303023E
+#define OID_FDDI_MAC_ERROR_CT 0x0303023F
+#define OID_FDDI_MAC_LOST_CT 0x03030240
+#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241
+#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242
+#define OID_FDDI_MAC_LATE_CT 0x03030243
+#define OID_FDDI_MAC_RING_OP_CT 0x03030244
+#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245
+#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246
+#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247
+#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248
+#define OID_FDDI_MAC_RMT_STATE 0x03030249
+#define OID_FDDI_MAC_DA_FLAG 0x0303024A
+#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B
+#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C
+#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D
+#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E
+#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F
+#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250
+#define OID_FDDI_PATH_INDEX 0x03030251
+#define OID_FDDI_PATH_RING_LATENCY 0x03030252
+#define OID_FDDI_PATH_TRACE_STATUS 0x03030253
+#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254
+#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255
+#define OID_FDDI_PATH_CONFIGURATION 0x03030256
+#define OID_FDDI_PATH_T_R_MODE 0x03030257
+#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258
+#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259
+#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A
+#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B
+#define OID_FDDI_PORT_MY_TYPE 0x0303025C
+#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D
+#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E
+#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F
+#define OID_FDDI_PORT_CURRENT_PATH 0x03030260
+#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261
+#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262
+#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263
+#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264
+#define OID_FDDI_PORT_PMD_CLASS 0x03030265
+#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266
+#define OID_FDDI_PORT_INDEX 0x03030267
+#define OID_FDDI_PORT_MAINT_LS 0x03030268
+#define OID_FDDI_PORT_BS_FLAG 0x03030269
+#define OID_FDDI_PORT_PC_LS 0x0303026A
+#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B
+#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C
+#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D
+#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E
+#define OID_FDDI_PORT_LEM_CT 0x0303026F
+#define OID_FDDI_PORT_LER_CUTOFF 0x03030270
+#define OID_FDDI_PORT_LER_ALARM 0x03030271
+#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272
+#define OID_FDDI_PORT_PCM_STATE 0x03030273
+#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274
+#define OID_FDDI_PORT_LER_FLAG 0x03030275
+#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276
+#define OID_FDDI_SMT_STATION_ACTION 0x03030277
+#define OID_FDDI_PORT_ACTION 0x03030278
+#define OID_FDDI_IF_DESCR 0x03030279
+#define OID_FDDI_IF_TYPE 0x0303027A
+#define OID_FDDI_IF_MTU 0x0303027B
+#define OID_FDDI_IF_SPEED 0x0303027C
+#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D
+#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E
+#define OID_FDDI_IF_OPER_STATUS 0x0303027F
+#define OID_FDDI_IF_LAST_CHANGE 0x03030280
+#define OID_FDDI_IF_IN_OCTETS 0x03030281
+#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282
+#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283
+#define OID_FDDI_IF_IN_DISCARDS 0x03030284
+#define OID_FDDI_IF_IN_ERRORS 0x03030285
+#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286
+#define OID_FDDI_IF_OUT_OCTETS 0x03030287
+#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288
+#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289
+#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A
+#define OID_FDDI_IF_OUT_ERRORS 0x0303028B
+#define OID_FDDI_IF_OUT_QLEN 0x0303028C
+#define OID_FDDI_IF_SPECIFIC 0x0303028D
+//
+// WAN objects
+//
+#define OID_WAN_PERMANENT_ADDRESS 0x04010101
+#define OID_WAN_CURRENT_ADDRESS 0x04010102
+#define OID_WAN_QUALITY_OF_SERVICE 0x04010103
+#define OID_WAN_PROTOCOL_TYPE 0x04010104
+#define OID_WAN_MEDIUM_SUBTYPE 0x04010105
+#define OID_WAN_HEADER_FORMAT 0x04010106
+#define OID_WAN_GET_INFO 0x04010107
+#define OID_WAN_SET_LINK_INFO 0x04010108
+#define OID_WAN_GET_LINK_INFO 0x04010109
+#define OID_WAN_LINE_COUNT 0x0401010A
+#define OID_WAN_GET_BRIDGE_INFO 0x0401020A
+#define OID_WAN_SET_BRIDGE_INFO 0x0401020B
+#define OID_WAN_GET_COMP_INFO 0x0401020C
+#define OID_WAN_SET_COMP_INFO 0x0401020D
+#define OID_WAN_GET_STATS_INFO 0x0401020E
+//
+// LocalTalk objects
+//
+#define OID_LTALK_CURRENT_NODE_ID 0x05010102
+#define OID_LTALK_IN_BROADCASTS 0x05020101
+#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102
+#define OID_LTALK_OUT_NO_HANDLERS 0x05020201
+#define OID_LTALK_COLLISIONS 0x05020202
+#define OID_LTALK_DEFERS 0x05020203
+#define OID_LTALK_NO_DATA_ERRORS 0x05020204
+#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205
+#define OID_LTALK_FCS_ERRORS 0x05020206
+//
+// Arcnet objects
+//
+#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101
+#define OID_ARCNET_CURRENT_ADDRESS 0x06010102
+#define OID_ARCNET_RECONFIGURATIONS 0x06020201
+//
+// TAPI objects
+//
+#define OID_TAPI_ACCEPT 0x07030101
+#define OID_TAPI_ANSWER 0x07030102
+#define OID_TAPI_CLOSE 0x07030103
+#define OID_TAPI_CLOSE_CALL 0x07030104
+#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105
+#define OID_TAPI_CONFIG_DIALOG 0x07030106
+#define OID_TAPI_DEV_SPECIFIC 0x07030107
+#define OID_TAPI_DIAL 0x07030108
+#define OID_TAPI_DROP 0x07030109
+#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A
+#define OID_TAPI_GET_ADDRESS_ID 0x0703010B
+#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C
+#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D
+#define OID_TAPI_GET_CALL_INFO 0x0703010E
+#define OID_TAPI_GET_CALL_STATUS 0x0703010F
+#define OID_TAPI_GET_DEV_CAPS 0x07030110
+#define OID_TAPI_GET_DEV_CONFIG 0x07030111
+#define OID_TAPI_GET_EXTENSION_ID 0x07030112
+#define OID_TAPI_GET_ID 0x07030113
+#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114
+#define OID_TAPI_MAKE_CALL 0x07030115
+#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116
+#define OID_TAPI_OPEN 0x07030117
+#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118
+#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119
+#define OID_TAPI_SECURE_CALL 0x0703011A
+#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B
+#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C
+#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D
+#define OID_TAPI_SET_CALL_PARAMS 0x0703011E
+#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F
+#define OID_TAPI_SET_DEV_CONFIG 0x07030120
+#define OID_TAPI_SET_MEDIA_MODE 0x07030121
+#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122
+//
+// ATM Connection Oriented Ndis
+//
+#define OID_ATM_SUPPORTED_VC_RATES 0x08010101
+#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102
+#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103
+#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104
+#define OID_ATM_MAX_ACTIVE_VCS 0x08010105
+#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106
+#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107
+#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108
+#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109
+#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A
+#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B
+#define OID_ATM_SIGNALING_VPIVCI 0x08010201
+#define OID_ATM_ASSIGNED_VPI 0x08010202
+#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203
+#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204
+#define OID_ATM_ILMI_VPIVCI 0x08010205
+#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206
+#define OID_ATM_GET_NEAREST_FLOW 0x08010207
+#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208
+//
+// ATM specific statistics OIDs.
+//
+#define OID_ATM_RCV_CELLS_OK 0x08020101
+#define OID_ATM_XMIT_CELLS_OK 0x08020102
+#define OID_ATM_RCV_CELLS_DROPPED 0x08020103
+#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201
+#define OID_ATM_CELLS_HEC_ERROR 0x08020202
+#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203
+//
+// PCCA (Wireless) object
+//
+//
+// All WirelessWAN devices must support the following OIDs
+//
+#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101
+#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102
+#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103
+#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104
+#define OID_WW_GEN_INDICATION_REQUEST 0x09010105
+#define OID_WW_GEN_DEVICE_INFO 0x09010106
+#define OID_WW_GEN_OPERATION_MODE 0x09010107
+#define OID_WW_GEN_LOCK_STATUS 0x09010108
+#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109
+#define OID_WW_GEN_NETWORK_ID 0x0901010A
+#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B
+#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C
+#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D
+#define OID_WW_GEN_BASESTATION_ID 0x0901010E
+#define OID_WW_GEN_CHANNEL_ID 0x0901010F
+#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110
+#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111
+#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112
+#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113
+#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114
+#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115
+#define OID_WW_GEN_LATENCY 0x09010116
+#define OID_WW_GEN_BATTERY_LEVEL 0x09010117
+#define OID_WW_GEN_EXTERNAL_POWER 0x09010118
+//
+// Network Dependent OIDs - Mobitex:
+//
+#define OID_WW_MBX_SUBADDR 0x09050101
+// OID 0x09050102 is reserved and may not be used
+#define OID_WW_MBX_FLEXLIST 0x09050103
+#define OID_WW_MBX_GROUPLIST 0x09050104
+#define OID_WW_MBX_TRAFFIC_AREA 0x09050105
+#define OID_WW_MBX_LIVE_DIE 0x09050106
+#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107
+//
+// Network Dependent OIDs - Pinpoint:
+//
+#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101
+#define OID_WW_PIN_LAST_LOCATION 0x09090102
+#define OID_WW_PIN_LOC_FIX 0x09090103
+//
+// Network Dependent - CDPD:
+//
+#define OID_WW_CDPD_SPNI 0x090D0101
+#define OID_WW_CDPD_WASI 0x090D0102
+#define OID_WW_CDPD_AREA_COLOR 0x090D0103
+#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104
+#define OID_WW_CDPD_EID 0x090D0105
+#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106
+#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107
+#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108
+#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109
+#define OID_WW_CDPD_NEI 0x090D010A
+#define OID_WW_CDPD_NEI_STATE 0x090D010B
+#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C
+#define OID_WW_CDPD_SLEEP_MODE 0x090D010D
+#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E
+#define OID_WW_CDPD_TEI 0x090D010F
+#define OID_WW_CDPD_RSSI 0x090D0110
+//
+// Network Dependent - Ardis:
+//
+#define OID_WW_ARD_SNDCP 0x09110101
+#define OID_WW_ARD_TMLY_MSG 0x09110102
+#define OID_WW_ARD_DATAGRAM 0x09110103
+//
+// Network Dependent - DataTac:
+//
+#define OID_WW_TAC_COMPRESSION 0x09150101
+#define OID_WW_TAC_SET_CONFIG 0x09150102
+#define OID_WW_TAC_GET_STATUS 0x09150103
+#define OID_WW_TAC_USER_HEADER 0x09150104
+//
+// Network Dependent - Metricom:
+//
+#define OID_WW_MET_FUNCTION 0x09190101
+//
+// IRDA objects
+//
+#define OID_IRDA_RECEIVING 0x0A010100
+#define OID_IRDA_TURNAROUND_TIME 0x0A010101
+#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102
+#define OID_IRDA_LINK_SPEED 0x0A010103
+#define OID_IRDA_MEDIA_BUSY 0x0A010104
+#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200
+#define OID_IRDA_RATE_SNIFF 0x0A010201
+#define OID_IRDA_UNICAST_LIST 0x0A010202
+#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203
+#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204
+#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205
+//
+// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/
+// OID_GEN_MEDIA_IN_USE).
+//
+typedef enum _NDIS_MEDIUM {
+ NdisMedium802_3,
+ NdisMedium802_5,
+ NdisMediumFddi,
+ NdisMediumWan,
+ NdisMediumLocalTalk,
+ NdisMediumDix, // defined for convenience, not a real medium
+ NdisMediumArcnetRaw,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMediumWirelessWan,
+ NdisMediumIrda,
+ NdisMediumMax // Not a real medium, defined as an upper-bound
+} NDIS_MEDIUM, *PNDIS_MEDIUM;
+
+//
+// Hardware status codes (OID_GEN_HARDWARE_STATUS).
+//
+typedef enum _NDIS_HARDWARE_STATUS {
+ NdisHardwareStatusReady,
+ NdisHardwareStatusInitializing,
+ NdisHardwareStatusReset,
+ NdisHardwareStatusClosing,
+ NdisHardwareStatusNotReady
+} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS;
+
+//
+// this is the type passed in the OID_GEN_GET_TIME_CAPS request
+//
+typedef struct _GEN_GET_TIME_CAPS {
+ ULONG Flags; // Bits defined below
+
+ ULONG ClockPrecision;
+} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS;
+
+#define READABLE_LOCAL_CLOCK 0x000000001
+#define CLOCK_NETWORK_DERIVED 0x000000002
+#define CLOCK_PRECISION 0x000000004
+#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008
+#define TIMED_SEND_CAPABLE 0x000000010
+#define TIME_STAMP_CAPABLE 0x000000020
+//
+//
+// this is the type passed in the OID_GEN_GET_NETCARD_TIME request
+//
+typedef struct _GEN_GET_NETCARD_TIME {
+ ULONG ReadTime;
+} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME;
+
+//
+// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE).
+//
+typedef enum _NDIS_FDDI_ATTACHMENT_TYPE {
+ NdisFddiTypeIsolated = 1,
+ NdisFddiTypeLocalA,
+ NdisFddiTypeLocalB,
+ NdisFddiTypeLocalAB,
+ NdisFddiTypeLocalS,
+ NdisFddiTypeWrapA,
+ NdisFddiTypeWrapB,
+ NdisFddiTypeWrapAB,
+ NdisFddiTypeWrapS,
+ NdisFddiTypeCWrapA,
+ NdisFddiTypeCWrapB,
+ NdisFddiTypeCWrapS,
+ NdisFddiTypeThrough
+} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE;
+
+//
+// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE).
+//
+typedef enum _NDIS_FDDI_RING_MGT_STATE {
+ NdisFddiRingIsolated = 1,
+ NdisFddiRingNonOperational,
+ NdisFddiRingOperational,
+ NdisFddiRingDetect,
+ NdisFddiRingNonOperationalDup,
+ NdisFddiRingOperationalDup,
+ NdisFddiRingDirected,
+ NdisFddiRingTrace
+} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE;
+
+//
+// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE).
+//
+typedef enum _NDIS_FDDI_LCONNECTION_STATE {
+ NdisFddiStateOff = 1,
+ NdisFddiStateBreak,
+ NdisFddiStateTrace,
+ NdisFddiStateConnect,
+ NdisFddiStateNext,
+ NdisFddiStateSignal,
+ NdisFddiStateJoin,
+ NdisFddiStateVerify,
+ NdisFddiStateActive,
+ NdisFddiStateMaintenance
+} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE;
+
+//
+// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE).
+//
+typedef enum _NDIS_WAN_MEDIUM_SUBTYPE {
+ NdisWanMediumHub,
+ NdisWanMediumX_25,
+ NdisWanMediumIsdn,
+ NdisWanMediumSerial,
+ NdisWanMediumFrameRelay,
+ NdisWanMediumAtm,
+ NdisWanMediumSonet,
+ NdisWanMediumSW56K
+} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE;
+
+//
+// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT).
+//
+typedef enum _NDIS_WAN_HEADER_FORMAT {
+ NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID
+ NdisWanHeaderEthernet // emulation of ethernet header
+} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT;
+
+//
+// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE).
+//
+typedef enum _NDIS_WAN_QUALITY {
+ NdisWanRaw,
+ NdisWanErrorControl,
+ NdisWanReliable
+} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY;
+
+//
+// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE).
+//
+typedef enum _NDIS_802_5_RING_STATE {
+ NdisRingStateOpened = 1,
+ NdisRingStateClosed,
+ NdisRingStateOpening,
+ NdisRingStateClosing,
+ NdisRingStateOpenFailure,
+ NdisRingStateRingFailure
+} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE;
+
+//
+// Defines the state of the LAN media
+//
+typedef enum _NDIS_MEDIA_STATE {
+ NdisMediaStateConnected,
+ NdisMediaStateDisconnected
+} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority
+//
+typedef ULONG Priority_802_3; // 0-7 priority levels
+//
+// The following structure is used to query OID_GEN_CO_LINK_SPEED and
+// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current
+// link speed of the adapter. The second will return the minimum link speed
+// the adapter is capable of.
+//
+
+typedef struct _NDIS_CO_LINK_SPEED {
+ ULONG Outbound;
+ ULONG Inbound;
+} NDIS_CO_LINK_SPEED,
+
+*PNDIS_CO_LINK_SPEED;
+//
+// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).
+//
+#define NDIS_PACKET_TYPE_DIRECTED 0x0001
+#define NDIS_PACKET_TYPE_MULTICAST 0x0002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
+#define NDIS_PACKET_TYPE_BROADCAST 0x0008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
+#define NDIS_PACKET_TYPE_SMT 0x0040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000
+#define NDIS_PACKET_TYPE_GROUP 0x1000
+//
+// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS).
+//
+#define NDIS_RING_SIGNAL_LOSS 0x00008000
+#define NDIS_RING_HARD_ERROR 0x00004000
+#define NDIS_RING_SOFT_ERROR 0x00002000
+#define NDIS_RING_TRANSMIT_BEACON 0x00001000
+#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800
+#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400
+#define NDIS_RING_REMOVE_RECEIVED 0x00000200
+#define NDIS_RING_COUNTER_OVERFLOW 0x00000100
+#define NDIS_RING_SINGLE_STATION 0x00000080
+#define NDIS_RING_RING_RECOVERY 0x00000040
+//
+// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS).
+//
+#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001
+#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002
+#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004
+//
+// Ndis MAC option bits (OID_GEN_MAC_OPTIONS).
+//
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+//
+// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS.
+//
+#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001
+#ifdef IRDA
+//
+// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo
+// This is the per-packet info specified on a per-packet basis
+//
+typedef struct _NDIS_IRDA_PACKET_INFO {
+ UINT ExtraBOFs;
+ UINT MinTurnAroundTime;
+} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO;
+
+#endif
+#ifdef WIRELESS_WAN
+//
+// Wireless WAN structure definitions
+//
+//
+// currently defined Wireless network subtypes
+//
+typedef enum _NDIS_WW_NETWORK_TYPE {
+ NdisWWGeneric,
+ NdisWWMobitex,
+ NdisWWPinpoint,
+ NdisWWCDPD,
+ NdisWWArdis,
+ NdisWWDataTAC,
+ NdisWWMetricom,
+ NdisWWGSM,
+ NdisWWCDMA,
+ NdisWWTDMA,
+ NdisWWAMPS,
+ NdisWWInmarsat,
+ NdisWWpACT
+} NDIS_WW_NETWORK_TYPE;
+
+//
+// currently defined header formats
+//
+typedef enum _NDIS_WW_HEADER_FORMAT {
+ NdisWWDIXEthernetFrames,
+ NdisWWMPAKFrames,
+ NdisWWRDLAPFrames,
+ NdisWWMDC4800Frames
+} NDIS_WW_HEADER_FORMAT;
+
+//
+// currently defined encryption types
+//
+typedef enum _NDIS_WW_ENCRYPTION_TYPE {
+ NdisWWUnknownEncryption = -1,
+ NdisWWNoEncryption,
+ NdisWWDefaultEncryption
+} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE;
+
+//
+// OID_WW_GEN_INDICATION_REQUEST
+//
+typedef struct _NDIS_WW_INDICATION_REQUEST {
+ NDIS_OID Oid; // IN
+
+ UINT uIndicationFlag; // IN
+
+ UINT uApplicationToken; // IN OUT
+
+ HANDLE hIndicationHandle; // IN OUT
+
+ INT iPollingInterval; // IN OUT
+
+ NDIS_VAR_DATA_DESC InitialValue; // IN OUT
+
+ NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication
+
+ NDIS_VAR_DATA_DESC TriggerValue; // IN
+
+} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST;
+
+#define OID_INDICATION_REQUEST_ENABLE 0x0000
+#define OID_INDICATION_REQUEST_CANCEL 0x0001
+//
+// OID_WW_GEN_DEVICE_INFO
+//
+typedef struct _WW_DEVICE_INFO {
+ NDIS_VAR_DATA_DESC Manufacturer;
+ NDIS_VAR_DATA_DESC ModelNum;
+ NDIS_VAR_DATA_DESC SWVersionNum;
+ NDIS_VAR_DATA_DESC SerialNum;
+} WW_DEVICE_INFO, *PWW_DEVICE_INFO;
+
+//
+// OID_WW_GEN_OPERATION_MODE
+//
+typedef INT WW_OPERATION_MODE; // 0 = Normal mode
+ // 1 = Power saving mode
+ // -1 = mode unknown
+//
+// OID_WW_GEN_LOCK_STATUS
+//
+
+typedef INT WW_LOCK_STATUS; // 0 = unlocked
+ // 1 = locked
+ // -1 = unknown lock status
+//
+// OID_WW_GEN_DISABLE_TRANSMITTER
+//
+
+typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled
+ // 1 = transmitter disabled
+ // -1 = unknown value
+//
+// OID_WW_GEN_NETWORK_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID;
+//
+// OID_WW_GEN_PERMANENT_ADDRESS
+//
+typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS;
+//
+// OID_WW_GEN_CURRENT_ADDRESS
+//
+typedef struct _WW_CURRENT_ADDRESS {
+ NDIS_WW_HEADER_FORMAT Format;
+ NDIS_VAR_DATA_DESC Address;
+} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS;
+
+//
+// OID_WW_GEN_SUSPEND_DRIVER
+//
+typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational
+ // 1 = driver suspended
+//
+// OID_WW_GEN_BASESTATION_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID;
+//
+// OID_WW_GEN_CHANNEL_ID
+//
+typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID;
+//
+// OID_WW_GEN_ENCRYPTION_STATE
+//
+typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled
+ // 1 = if encryption is enabled
+//
+// OID_WW_GEN_CHANNEL_QUALITY
+//
+
+typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact,
+ // 1-100 = Quality of Channel (100 is highest quality).
+ // -1 = channel quality is unknown
+//
+// OID_WW_GEN_REGISTRATION_STATUS
+//
+
+typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied
+ // 1 = Registration pending
+ // 2 = Registered
+ // -1 = unknown registration status
+//
+// OID_WW_GEN_RADIO_LINK_SPEED
+//
+
+typedef UINT WW_RADIO_LINK_SPEED; // Bits per second.
+//
+// OID_WW_GEN_LATENCY
+//
+
+typedef UINT WW_LATENCY; // milliseconds
+//
+// OID_WW_GEN_BATTERY_LEVEL
+//
+
+typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage
+ // (100=fully charged)
+ // -1 = unknown battery level.
+//
+// OID_WW_GEN_EXTERNAL_POWER
+//
+
+typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected
+ // 1 = external power connected
+ // -1 = unknown
+//
+// OID_WW_MET_FUNCTION
+//
+
+typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION;
+//
+// OID_WW_TAC_COMPRESSION
+//
+typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression
+ // is being used.
+//
+// OID_WW_TAC_SET_CONFIG
+//
+
+typedef struct _WW_TAC_SETCONFIG {
+ NDIS_VAR_DATA_DESC RCV_MODE;
+ NDIS_VAR_DATA_DESC TX_CONTROL;
+ NDIS_VAR_DATA_DESC RX_CONTROL;
+ NDIS_VAR_DATA_DESC FLOW_CONTROL;
+ NDIS_VAR_DATA_DESC RESET_CNF;
+ NDIS_VAR_DATA_DESC READ_CNF;
+} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG;
+
+//
+// OID_WW_TAC_GET_STATUS
+//
+typedef struct _WW_TAC_GETSTATUS {
+ BOOLEAN Action; // Set = Execute command.
+
+ NDIS_VAR_DATA_DESC Command;
+ NDIS_VAR_DATA_DESC Option;
+ NDIS_VAR_DATA_DESC Response; // The response to the requested command
+ // - max. length of string is 256 octets.
+
+} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS;
+
+//
+// OID_WW_TAC_USER_HEADER
+//
+typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets.
+//
+// OID_WW_ARD_SNDCP
+//
+
+typedef struct _WW_ARD_SNDCP {
+ NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported.
+
+ INT BlockSize; // The block size used for SNDCP
+
+ INT Window; // The window size used in SNDCP
+
+} WW_ARD_SNDCP, *PWW_ARD_SNDCP;
+
+//
+// OID_WW_ARD_TMLY_MSG
+//
+typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel.
+//
+// OID_WW_ARD_DATAGRAM
+//
+
+typedef struct _WW_ARD_DATAGRAM {
+ BOOLEAN LoadLevel; // Byte that contains the load level info.
+
+ INT SessionTime; // Datagram session time remaining.
+
+ NDIS_VAR_DATA_DESC HostAddr; // Host address.
+
+ NDIS_VAR_DATA_DESC THostAddr; // Test host address.
+
+} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM;
+
+//
+// OID_WW_CDPD_SPNI
+//
+typedef struct _WW_CDPD_SPNI {
+ UINT SPNI[10]; //10 16-bit service provider network IDs
+
+ INT OperatingMode; // 0 = ignore SPNI,
+ // 1 = require SPNI from list,
+ // 2 = prefer SPNI from list.
+ // 3 = exclude SPNI from list.
+
+} WW_CDPD_SPNI, *PWW_CDPD_SPNI;
+
+//
+// OID_WW_CDPD_WASI
+//
+typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID {
+ UINT WASI[10]; //10 16-bit wide area service IDs
+
+ INT OperatingMode; // 0 = ignore WASI,
+ // 1 = Require WASI from list,
+ // 2 = prefer WASI from list
+ // 3 = exclude WASI from list.
+
+} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID;
+
+//
+// OID_WW_CDPD_AREA_COLOR
+//
+typedef INT WW_CDPD_AREA_COLOR;
+//
+// OID_WW_CDPD_TX_POWER_LEVEL
+//
+typedef UINT WW_CDPD_TX_POWER_LEVEL;
+//
+// OID_WW_CDPD_EID
+//
+typedef NDIS_VAR_DATA_DESC WW_CDPD_EID;
+//
+// OID_WW_CDPD_HEADER_COMPRESSION
+//
+typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression,
+ // 1 = always compress headers,
+ // 2 = compress headers if MD-IS does
+ // -1 = unknown
+//
+// OID_WW_CDPD_DATA_COMPRESSION
+//
+
+typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression,
+ // 1 = data compression enabled
+ // -1 = unknown
+//
+// OID_WW_CDPD_CHANNEL_SELECT
+//
+
+typedef struct _WW_CDPD_CHANNEL_SELECT {
+ UINT ChannelID; // channel number
+
+ UINT fixedDuration; // duration in seconds
+
+} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT;
+
+//
+// OID_WW_CDPD_CHANNEL_STATE
+//
+typedef enum _WW_CDPD_CHANNEL_STATE {
+ CDPDChannelNotAvail,
+ CDPDChannelScanning,
+ CDPDChannelInitAcquired,
+ CDPDChannelAcquired,
+ CDPDChannelSleeping,
+ CDPDChannelWaking,
+ CDPDChannelCSDialing,
+ CDPDChannelCSRedial,
+ CDPDChannelCSAnswering,
+ CDPDChannelCSConnected,
+ CDPDChannelCSSuspended
+} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE;
+
+//
+// OID_WW_CDPD_NEI
+//
+typedef enum _WW_CDPD_NEI_FORMAT {
+ CDPDNeiIPv4,
+ CDPDNeiCLNP,
+ CDPDNeiIPv6
+} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT;
+typedef enum _WW_CDPD_NEI_TYPE {
+ CDPDNeiIndividual,
+ CDPDNeiMulticast,
+ CDPDNeiBroadcast
+} WW_CDPD_NEI_TYPE;
+typedef struct _WW_CDPD_NEI {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_FORMAT NeiFormat;
+ WW_CDPD_NEI_TYPE NeiType;
+ WORD NeiGmid; // group member identifier, only
+ // meaningful if NeiType ==
+ // CDPDNeiMulticast
+
+ NDIS_VAR_DATA_DESC NeiAddress;
+} WW_CDPD_NEI;
+
+//
+// OID_WW_CDPD_NEI_STATE
+//
+typedef enum _WW_CDPD_NEI_STATE {
+ CDPDUnknown,
+ CDPDRegistered,
+ CDPDDeregistered
+} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE;
+typedef enum _WW_CDPD_NEI_SUB_STATE {
+ CDPDPending, // Registration pending
+ CDPDNoReason, // Registration denied - no reason given
+ CDPDMDISNotCapable, // Registration denied - MD-IS not capable of
+ // handling M-ES at this time
+ CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to
+ // use this subnetwork
+ CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient
+ // authentication credentials
+ CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported
+ // authentication credentials
+ CDPDUsageExceeded, // Registration denied - NEI has exceeded usage
+ // limitations
+ CDPDDeniedThisNetwork // Registration denied on this network, service
+ // may be obtained on alternate Service Provider
+ // network
+} WW_CDPD_NEI_SUB_STATE;
+typedef struct _WW_CDPD_NEI_REG_STATE {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_STATE NeiState;
+ WW_CDPD_NEI_SUB_STATE NeiSubState;
+} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE;
+
+//
+// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER
+//
+typedef struct _WW_CDPD_SERVICE_PROVIDER_ID {
+ UINT SPI[10]; //10 16-bit service provider IDs
+
+ INT OperatingMode; // 0 = ignore SPI,
+ // 1 = require SPI from list,
+ // 2 = prefer SPI from list.
+ // 3 = exclude SPI from list.
+
+} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID;
+
+//
+// OID_WW_CDPD_SLEEP_MODE
+//
+typedef INT WW_CDPD_SLEEP_MODE;
+//
+// OID_WW_CDPD_TEI
+//
+typedef ULONG WW_CDPD_TEI;
+//
+// OID_WW_CDPD_CIRCUIT_SWITCHED
+//
+typedef struct _WW_CDPD_CIRCUIT_SWITCHED {
+ INT service_preference; // -1 = unknown,
+ // 0 = always use packet switched CDPD,
+ // 1 = always use CS CDPD via AMPS,
+ // 2 = always use CS CDPD via PSTN,
+ // 3 = use circuit switched via AMPS only
+ // when packet switched is not available.
+ // 4 = use packet switched only when circuit
+ // switched via AMPS is not available.
+ // 5 = device manuf. defined service
+ // preference.
+ // 6 = device manuf. defined service
+ // preference.
+
+ INT service_status; // -1 = unknown,
+ // 0 = packet switched CDPD,
+ // 1 = circuit switched CDPD via AMPS,
+ // 2 = circuit switched CDPD via PSTN.
+
+ INT connect_rate; // CS connection bit rate (bits per second).
+ // 0 = no active connection,
+ // -1 = unknown
+ // Dial code last used to dial.
+
+ NDIS_VAR_DATA_DESC dial_code[20];
+
+ UINT sid; // Current AMPS system ID
+
+ INT a_b_side_selection; // -1 = unknown,
+ // 0 = no AMPS service
+ // 1 = AMPS "A" side channels selected
+ // 2 = AMPS "B" side channels selected
+
+ INT AMPS_channel; // -1= unknown
+ // 0 = no AMPS service.
+ // 1-1023 = AMPS channel number in use
+
+ UINT action; // 0 = no action
+ // 1 = suspend (hangup)
+ // 2 = dial
+
+ // Default dial code for CS CDPD service
+ // encoded as specified in the CS CDPD
+ // implementor guidelines.
+ NDIS_VAR_DATA_DESC default_dial[20];
+
+ // Number for the CS CDPD network to call
+ // back the mobile, encoded as specified in
+ // the CS CDPD implementor guidelines.
+ NDIS_VAR_DATA_DESC call_back[20];
+
+ UINT sid_list[10]; // List of 10 16-bit preferred AMPS
+ // system IDs for CS CDPD.
+
+ UINT inactivity_timer; // Wait time after last data before dropping
+ // call.
+ // 0-65535 = inactivity time limit (seconds).
+
+ UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED;
+typedef UINT WW_CDPD_RSSI;
+//
+// OID_WW_PIN_LOC_AUTHORIZE
+//
+typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized
+ // 1 = authorized
+ // -1 = unknown
+//
+// OID_WW_PIN_LAST_LOCATION
+// OID_WW_PIN_LOC_FIX
+//
+
+typedef struct _WW_PIN_LOCATION {
+ INT Latitude; // Latitude in hundredths of a second
+
+ INT Longitude; // Longitude in hundredths of a second
+
+ INT Altitude; // Altitude in feet
+
+ INT FixTime; // Time of the location fix, since midnight, local time (of the
+ // current day), in tenths of a second
+
+ INT NetTime; // Current local network time of the current day, since midnight,
+ // in tenths of a second
+
+ INT LocQuality; // 0-100 = location quality
+
+ INT LatReg; // Latitude registration offset, in hundredths of a second
+
+ INT LongReg; // Longitude registration offset, in hundredths of a second
+
+ INT GMTOffset; // Offset in minutes of the local time zone from GMT
+
+} WW_PIN_LOCATION, *PWW_PIN_LOCATION;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox
+//
+typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag
+//
+// OID_WW_MBX_SUBADDR
+//
+
+typedef struct _WW_MBX_PMAN {
+ BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN
+
+ UINT MAN;
+ UCHAR PASSWORD[8]; // Password should be null for Logout and indications.
+ // Maximum length of password is 8 chars.
+
+} WW_MBX_PMAN, *PWW_MBX_PMAN;
+
+//
+// OID_WW_MBX_FLEXLIST
+//
+typedef struct _WW_MBX_FLEXLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[7]; // List of MANs.
+
+} WW_MBX_FLEXLIST;
+
+//
+// OID_WW_MBX_GROUPLIST
+//
+typedef struct _WW_MBX_GROUPLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[15]; // List of MANs.
+
+} WW_MBX_GROUPLIST;
+
+//
+// OID_WW_MBX_TRAFFIC_AREA
+//
+typedef enum _WW_MBX_TRAFFIC_AREA {
+ unknown_traffic_area, // The driver has no information about the current traffic area.
+ in_traffic_area, // Mobile unit has entered a subscribed traffic area.
+ in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized.
+ unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized.
+} WW_MBX_TRAFFIC_AREA;
+
+//
+// OID_WW_MBX_LIVE_DIE
+//
+typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received
+ // 1 = LIVE last received
+ // -1 = unknown
+//
+// OID_WW_MBX_TEMP_DEFAULTLIST
+//
+
+typedef struct _WW_MBX_CHANNEL_PAIR {
+ UINT Mobile_Tx;
+ UINT Mobile_Rx;
+} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR;
+typedef struct _WW_MBX_TEMPDEFAULTLIST {
+ UINT Length;
+ WW_MBX_CHANNEL_PAIR ChannelPair[1];
+} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST;
+
+#endif // WIRELESS_WAN
+#endif // _NTDDNDIS_
diff --git a/src/SeeDll/Ntddpack.h b/src/SeeDll/Ntddpack.h
new file mode 100644
index 00000000..30945c1e
--- /dev/null
+++ b/src/SeeDll/Ntddpack.h
@@ -0,0 +1,26 @@
+
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+#include "devioctl.h"
+/*#include <packon.h> */
+struct _PACKET_OID_DATA {
+ ULONG Oid;
+ ULONG Length;
+ UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL 0x8000
+#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/src/SeeDll/Packet32.c b/src/SeeDll/Packet32.c
new file mode 100644
index 00000000..e2647ec2
--- /dev/null
+++ b/src/SeeDll/Packet32.c
@@ -0,0 +1,2302 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <GlobalConst.h>
+
+#define UNICODE 1
+
+#include <stdio.h>
+#include <packet32.h>
+
+#if 0
+#include "WanPacket/WanPacket.h"
+#endif
+
+#define _WINNT4
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <Iphlpapi.h>
+#include <IPIfCons.h>
+
+#include <ntddndis.h>
+
+
+/// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
+char PacketLibraryVersion[64];
+/// Current NPF.sys Version. It can be retrieved directly or through the PacketGetVersion() function.
+char PacketDriverVersion[64];
+
+LPCTSTR NPFServiceName = TEXT("SEE");
+LPCTSTR NPFServiceDesc = TEXT("SoftEther Ethernet Layer Driver");
+LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\CurrentControlSet\\Services\\SEE");
+LPCTSTR NPFDriverPath = TEXT("system32\\drivers\\see.sys");
+
+extern PADAPTER_INFO AdaptersInfoList;
+extern HANDLE AdaptersInfoMutex;
+#ifndef _WINNT4
+typedef VOID (*GAAHandler)(
+ ULONG,
+ DWORD,
+ PVOID,
+ PIP_ADAPTER_ADDRESSES,
+ PULONG);
+GAAHandler GetAdaptersAddressesPointer = NULL;
+#endif // _WINNT4
+
+#ifdef HAVE_DAG_API
+/* We load dinamically the dag library in order link it only when it's present on the system */
+dagc_open_handler p_dagc_open = NULL;
+dagc_close_handler p_dagc_close = NULL;
+dagc_getlinktype_handler p_dagc_getlinktype = NULL;
+dagc_getlinkspeed_handler p_dagc_getlinkspeed = NULL;
+dagc_getfcslen_handler p_dagc_getfcslen = NULL;
+dagc_receive_handler p_dagc_receive = NULL;
+dagc_wait_handler p_dagc_wait = NULL;
+dagc_stats_handler p_dagc_stats = NULL;
+dagc_setsnaplen_handler p_dagc_setsnaplen = NULL;
+dagc_finddevs_handler p_dagc_finddevs = NULL;
+dagc_freedevs_handler p_dagc_freedevs = NULL;
+#endif /* HAVE_DAG_API */
+
+BOOLEAN PacketAddAdapterDag(PCHAR name, PCHAR description, BOOLEAN IsAFile);
+
+//---------------------------------------------------------------------------
+
+/*!
+ \brief The main dll function.
+*/
+
+BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
+{
+ BOOLEAN Status=TRUE;
+ HMODULE IPHMod;
+ PADAPTER_INFO NewAdInfo;
+#ifdef HAVE_DAG_API
+ HMODULE DagcLib;
+#endif // HAVE_DAG_API
+
+ switch(Reason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ ODS("************Packet32: DllMain************\n");
+
+#ifdef _DEBUG_TO_FILE
+ // dump a bunch of registry keys useful for debug to file
+ PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
+ "adapters.reg");
+ PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip",
+ "tcpip.reg");
+ PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\SEE",
+ "npf.reg");
+ PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services",
+ "services.reg");
+#endif
+
+ // Create the mutex that will protect the adapter information list
+ AdaptersInfoMutex = CreateMutex(NULL, FALSE, NULL);
+
+ //
+ // Retrieve packet.dll version information from the file
+ //
+ PacketGetFileVersion(TEXT("see.dll"), PacketLibraryVersion, sizeof(PacketLibraryVersion));
+
+ //
+ // Retrieve NPF.sys version information from the file
+ //
+ PacketGetFileVersion(TEXT("drivers\\see.sys"), PacketDriverVersion, sizeof(PacketDriverVersion));
+
+ //
+ // Locate GetAdaptersAddresses dinamically since it is not present in Win2k
+ //
+ IPHMod = GetModuleHandle(TEXT("Iphlpapi"));
+
+#ifndef _WINNT4
+ GetAdaptersAddressesPointer = (GAAHandler) GetProcAddress(IPHMod ,"GetAdaptersAddresses");
+#endif // _WINNT4
+
+#ifdef HAVE_DAG_API
+ /* We load dinamically the dag library in order link it only when it's present on the system */
+ if((DagcLib = LoadLibrary(TEXT("dagc.dll"))) == NULL)
+ {
+ // Report the error but go on
+ ODS("dag capture library not found on this system\n");
+ break;
+ }
+
+ p_dagc_open = (dagc_open_handler) GetProcAddress(DagcLib, "dagc_open");
+ p_dagc_close = (dagc_close_handler) GetProcAddress(DagcLib, "dagc_close");
+ p_dagc_setsnaplen = (dagc_setsnaplen_handler) GetProcAddress(DagcLib, "dagc_setsnaplen");
+ p_dagc_getlinktype = (dagc_getlinktype_handler) GetProcAddress(DagcLib, "dagc_getlinktype");
+ p_dagc_getlinkspeed = (dagc_getlinkspeed_handler) GetProcAddress(DagcLib, "dagc_getlinkspeed");
+ p_dagc_getfcslen = (dagc_getfcslen_handler) GetProcAddress(DagcLib, "dagc_getfcslen");
+ p_dagc_receive = (dagc_receive_handler) GetProcAddress(DagcLib, "dagc_receive");
+ p_dagc_wait = (dagc_wait_handler) GetProcAddress(DagcLib, "dagc_wait");
+ p_dagc_stats = (dagc_stats_handler) GetProcAddress(DagcLib, "dagc_stats");
+ p_dagc_finddevs = (dagc_finddevs_handler) GetProcAddress(DagcLib, "dagc_finddevs");
+ p_dagc_freedevs = (dagc_freedevs_handler) GetProcAddress(DagcLib, "dagc_freedevs");
+
+#endif /* HAVE_DAG_API */
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ CloseHandle(AdaptersInfoMutex);
+
+ AdaptersInfoList;
+
+ while(AdaptersInfoList != NULL)
+ {
+
+ NewAdInfo = AdaptersInfoList->Next;
+ if (AdaptersInfoList->NetworkAddresses != NULL)
+ GlobalFreePtr(AdaptersInfoList->NetworkAddresses);
+ GlobalFreePtr(AdaptersInfoList);
+
+ AdaptersInfoList = NewAdInfo;
+ }
+
+
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+/*!
+ \brief Convert a Unicode dotted-quad to a 32-bit IP address.
+ \param cp A string containing the address.
+ \return the converted 32-bit numeric address.
+
+ Doesn't check to make sure the address is valid.
+*/
+
+ULONG inet_addrU(const WCHAR *cp)
+{
+ ULONG val, part;
+ WCHAR c;
+ int i;
+
+ val = 0;
+ for (i = 0; i < 4; i++) {
+ part = 0;
+ while ((c = *cp++) != '\0' && c != '.') {
+ if (c < '0' || c > '9')
+ return -1;
+ part = part*10 + (c - '0');
+ }
+ if (part > 255)
+ return -1;
+ val = val | (part << i*8);
+ if (i == 3) {
+ if (c != '\0')
+ return -1; // extra gunk at end of string
+ } else {
+ if (c == '\0')
+ return -1; // string ends early
+ }
+ }
+ return val;
+}
+
+/*!
+ \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
+ \param string The string to convert.
+ \return The converted string.
+*/
+
+PWCHAR SChar2WChar(PCHAR string)
+{
+ PWCHAR TmpStr;
+ TmpStr = (WCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, (strlen(string)+2)*sizeof(WCHAR));
+
+ MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, ((int)strlen(string)+2));
+
+ return TmpStr;
+}
+
+/*!
+ \brief Converts an UNICODE string to ASCII. Uses the WideCharToMultiByte() system function.
+ \param string The string to convert.
+ \return The converted string.
+*/
+
+PCHAR WChar2SChar(PWCHAR string)
+{
+ PCHAR TmpStr;
+ TmpStr = (CHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, (wcslen(string)+2));
+
+ // Conver to ASCII
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ string,
+ -1,
+ TmpStr,
+ ((int)wcslen(string)+2), // size of buffer
+ NULL,
+ NULL);
+
+ return TmpStr;
+}
+
+/*!
+ \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
+ \param AdapterObject Handle to the service control manager.
+ \return If the function succeeds, the return value is nonzero.
+
+ The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
+ without performing a copy. This function tries to increase the size of that buffer.
+*/
+
+BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
+{
+ BOOLEAN Status;
+ ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
+ PPACKET_OID_DATA OidData;
+
+ OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
+ if (OidData == NULL) {
+ ODS("PacketSetMaxLookaheadsize failed\n");
+ return FALSE;
+ }
+
+ //set the size of the lookahead buffer to the maximum available by the the NIC driver
+ OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
+ OidData->Length=sizeof(ULONG);
+ Status=PacketRequest(AdapterObject,FALSE,OidData);
+ OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
+ Status=PacketRequest(AdapterObject,TRUE,OidData);
+ GlobalFreePtr(OidData);
+ return Status;
+}
+
+/*!
+ \brief Retrieves the event associated in the driver with a capture instance and stores it in an
+ _ADAPTER structure.
+ \param AdapterObject Handle to the service control manager.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
+ call and set it in the _ADAPTER structure pointed by AdapterObject.
+*/
+
+BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
+{
+ DWORD BytesReturned;
+ TCHAR EventName[39];
+
+ if (LOWORD(GetVersion()) == 4)
+ {
+ // retrieve the name of the shared event from the driver without the "Global\\" prefix
+ if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE)
+ return FALSE;
+
+ EventName[BytesReturned/sizeof(TCHAR)]=0; // terminate the string
+ }
+ else
+ {
+ // this tells the terminal service to retrieve the event from the global namespace
+ wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
+ // retrieve the name of the shared event from the driver with the "Global\\" prefix
+ if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName + 7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE)
+ return FALSE;
+
+ EventName[BytesReturned/sizeof(TCHAR) + 7]=0; // terminate the string
+ }
+
+ // open the shared event
+ AdapterObject->ReadEvent=CreateEvent(NULL,
+ TRUE,
+ FALSE,
+ EventName);
+
+ if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
+ ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
+ return FALSE;
+ }
+
+ AdapterObject->ReadTimeOut=0;
+
+ return TRUE;
+}
+
+/*!
+ \brief Installs the NPF device driver.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function installs the driver's service in the system using the CreateService function.
+*/
+
+BOOL PacketInstallDriver()
+{
+ BOOL result = FALSE;
+ ULONG err = 0;
+ SC_HANDLE svcHandle;
+ SC_HANDLE scmHandle;
+ ODS("PacketInstallDriver\n");
+
+ scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+ if(scmHandle == NULL)
+ return FALSE;
+
+ svcHandle = CreateService(scmHandle,
+ NPFServiceName,
+ NPFServiceDesc,
+ SERVICE_ALL_ACCESS,
+ SERVICE_KERNEL_DRIVER,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL,
+ NPFDriverPath,
+ NULL, NULL, NULL, NULL, NULL);
+ if (svcHandle == NULL)
+ {
+ err = GetLastError();
+ if (err == ERROR_SERVICE_EXISTS)
+ {
+ //npf.sys already existed
+ err = 0;
+ result = TRUE;
+ }
+ }
+ else
+ {
+ //Created service for npf.sys
+ result = TRUE;
+ }
+
+ if (svcHandle != NULL)
+ CloseServiceHandle(svcHandle);
+
+ if(result == FALSE)
+ {
+ ODSEx("PacketInstallDriver failed, Error=%d\n",err);
+ }
+
+ CloseServiceHandle(scmHandle);
+ SetLastError(err);
+ return result;
+
+}
+
+/*!
+ \brief Dumps a registry key to disk in text format. Uses regedit.
+ \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
+ \param FileName Name of the file that will contain the dump.
+ \return If the function succeeds, the return value is nonzero.
+
+ For debugging purposes, we use this function to obtain some registry keys from the user's machine.
+*/
+
+#ifdef _DEBUG_TO_FILE
+
+LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
+{
+ CHAR Command[256];
+
+ strcpy(Command, "regedit /e ");
+ strcat(Command, FileName);
+ strcat(Command, " ");
+ strcat(Command, KeyName);
+
+ /// Let regedit do the dirt work for us
+ system(Command);
+
+ return TRUE;
+}
+#endif
+
+/*!
+ \brief Returns the version of a dll or exe file
+ \param FileName Name of the file whose version has to be retrieved.
+ \param VersionBuff Buffer that will contain the string with the file version.
+ \param VersionBuffLen Length of the buffer poited by VersionBuff.
+ \return If the function succeeds, the return value is TRUE.
+
+ \note uses the GetFileVersionInfoSize() and GetFileVersionInfo() WIN32 API functions
+*/
+BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen)
+{
+ DWORD dwVerInfoSize; // Size of version information block
+ DWORD dwVerHnd=0; // An 'ignored' parameter, always '0'
+ LPSTR lpstrVffInfo;
+ UINT cbTranslate, dwBytes;
+ TCHAR SubBlock[64];
+ PVOID lpBuffer;
+ PCHAR TmpStr;
+
+ // Structure used to store enumerated languages and code pages.
+ struct LANGANDCODEPAGE {
+ WORD wLanguage;
+ WORD wCodePage;
+ } *lpTranslate;
+
+ ODS("PacketGetFileVersion\n");
+
+ // Now lets dive in and pull out the version information:
+ dwVerInfoSize = GetFileVersionInfoSize(FileName, &dwVerHnd);
+ if (dwVerInfoSize)
+ {
+ lpstrVffInfo = GlobalAllocPtr(GMEM_MOVEABLE, dwVerInfoSize);
+ if (lpstrVffInfo == NULL)
+ {
+ ODS("PacketGetFileVersion: failed to allocate memory\n");
+ return FALSE;
+ }
+
+ if(!GetFileVersionInfo(FileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo))
+ {
+ ODS("PacketGetFileVersion: failed to call GetFileVersionInfo\n");
+ GlobalFreePtr(lpstrVffInfo);
+ return FALSE;
+ }
+
+ // Read the list of languages and code pages.
+ if(!VerQueryValue(lpstrVffInfo, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
+ {
+ ODS("PacketGetFileVersion: failed to call VerQueryValue\n");
+ GlobalFreePtr(lpstrVffInfo);
+ return FALSE;
+ }
+
+ // Create the file version string for the first (i.e. the only one) language.
+ wsprintf( SubBlock,
+ TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
+ (*lpTranslate).wLanguage,
+ (*lpTranslate).wCodePage);
+
+ // Retrieve the file version string for the language.
+ if(!VerQueryValue(lpstrVffInfo, SubBlock, &lpBuffer, &dwBytes))
+ {
+ ODS("PacketGetFileVersion: failed to call VerQueryValue\n");
+ GlobalFreePtr(lpstrVffInfo);
+ return FALSE;
+ }
+
+ // Convert to ASCII
+ TmpStr = WChar2SChar(lpBuffer);
+
+ if(strlen(TmpStr) >= VersionBuffLen)
+ {
+ ODS("PacketGetFileVersion: Input buffer too small\n");
+ GlobalFreePtr(lpstrVffInfo);
+ GlobalFreePtr(TmpStr);
+ return FALSE;
+ }
+
+ strcpy(VersionBuff, TmpStr);
+
+ GlobalFreePtr(lpstrVffInfo);
+ GlobalFreePtr(TmpStr);
+
+ }
+ else
+ {
+ ODSEx("PacketGetFileVersion: failed to call GetFileVersionInfoSize, LastError = %d\n", GetLastError());
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+/*!
+ \brief Opens an adapter using the NPF device driver.
+ \param AdapterName A string containing the name of the device to open.
+ \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
+ otherwise the return value is NULL.
+
+ \note internal function used by PacketOpenAdapter() and AddAdapter()
+*/
+LPADAPTER PacketOpenAdapterNPF(PCHAR AdapterName)
+{
+ LPADAPTER lpAdapter;
+ BOOLEAN Result;
+ DWORD error;
+ SC_HANDLE svcHandle = NULL;
+ SC_HANDLE scmHandle = NULL;
+ LONG KeyRes;
+ HKEY PathKey;
+ SERVICE_STATUS SStat;
+ BOOLEAN QuerySStat;
+ WCHAR SymbolicLink[128];
+
+ ODS("PacketOpenAdapterNPF\n");
+
+ scmHandle = OpenSCManager(NULL, NULL, GENERIC_READ);
+
+ if(scmHandle == NULL)
+ {
+ error = GetLastError();
+ ODSEx("OpenSCManager failed! LastError=%d\n", error);
+ }
+ else
+ {
+ // check if the NPF registry key is already present
+ // this means that the driver is already installed and that we don't need to call PacketInstallDriver
+ KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ NPFRegistryLocation,
+ 0,
+ KEY_READ,
+ &PathKey);
+
+ if(KeyRes != ERROR_SUCCESS)
+ {
+ Result = PacketInstallDriver();
+ }
+ else
+ {
+ Result = TRUE;
+ RegCloseKey(PathKey);
+ }
+
+ Result = FALSE;
+ svcHandle = OpenService(scmHandle, NPFServiceName, GENERIC_READ);
+ if (svcHandle != NULL)
+ {
+ Result = TRUE;
+
+ CloseServiceHandle(svcHandle);
+ }
+
+ if (Result)
+ {
+
+ svcHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS );
+ if (svcHandle != NULL)
+ {
+ QuerySStat = QueryServiceStatus(svcHandle, &SStat);
+
+#if defined(_DBG) || defined(_DEBUG_TO_FILE)
+ switch (SStat.dwCurrentState)
+ {
+ case SERVICE_CONTINUE_PENDING:
+ ODS("The status of the driver is: SERVICE_CONTINUE_PENDING\n");
+ break;
+ case SERVICE_PAUSE_PENDING:
+ ODS("The status of the driver is: SERVICE_PAUSE_PENDING\n");
+ break;
+ case SERVICE_PAUSED:
+ ODS("The status of the driver is: SERVICE_PAUSED\n");
+ break;
+ case SERVICE_RUNNING:
+ ODS("The status of the driver is: SERVICE_RUNNING\n");
+ break;
+ case SERVICE_START_PENDING:
+ ODS("The status of the driver is: SERVICE_START_PENDING\n");
+ break;
+ case SERVICE_STOP_PENDING:
+ ODS("The status of the driver is: SERVICE_STOP_PENDING\n");
+ break;
+ case SERVICE_STOPPED:
+ ODS("The status of the driver is: SERVICE_STOPPED\n");
+ break;
+
+ default:
+ ODS("The status of the driver is: unknown\n");
+ break;
+ }
+#endif
+
+ if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING)
+ {
+ ODS("Calling startservice\n");
+ if (StartService(svcHandle, 0, NULL)==0)
+ {
+ error = GetLastError();
+ if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS)
+ {
+ SetLastError(error);
+ if (scmHandle != NULL)
+ CloseServiceHandle(scmHandle);
+ error = GetLastError();
+ ODSEx("PacketOpenAdapterNPF: StartService failed, LastError=%d\n",error);
+ SetLastError(error);
+ return NULL;
+ }
+ }
+ }
+
+ CloseServiceHandle( svcHandle );
+ svcHandle = NULL;
+
+ }
+ else
+ {
+ error = GetLastError();
+ ODSEx("OpenService failed! Error=%d", error);
+ SetLastError(error);
+ }
+ }
+ else
+ {
+ if (KeyRes == FALSE)
+ Result = PacketInstallDriver();
+ else
+ Result = TRUE;
+
+ if (Result) {
+
+ svcHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
+ if (svcHandle != NULL)
+ {
+
+ QuerySStat = QueryServiceStatus(svcHandle, &SStat);
+
+#if defined(_DBG) || defined(_DEBUG_TO_FILE)
+ switch (SStat.dwCurrentState)
+ {
+ case SERVICE_CONTINUE_PENDING:
+ ODS("The status of the driver is: SERVICE_CONTINUE_PENDING\n");
+ break;
+ case SERVICE_PAUSE_PENDING:
+ ODS("The status of the driver is: SERVICE_PAUSE_PENDING\n");
+ break;
+ case SERVICE_PAUSED:
+ ODS("The status of the driver is: SERVICE_PAUSED\n");
+ break;
+ case SERVICE_RUNNING:
+ ODS("The status of the driver is: SERVICE_RUNNING\n");
+ break;
+ case SERVICE_START_PENDING:
+ ODS("The status of the driver is: SERVICE_START_PENDING\n");
+ break;
+ case SERVICE_STOP_PENDING:
+ ODS("The status of the driver is: SERVICE_STOP_PENDING\n");
+ break;
+ case SERVICE_STOPPED:
+ ODS("The status of the driver is: SERVICE_STOPPED\n");
+ break;
+
+ default:
+ ODS("The status of the driver is: unknown\n");
+ break;
+ }
+#endif
+
+ if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
+
+ ODS("Calling startservice\n");
+
+ if (StartService(svcHandle, 0, NULL)==0){
+ error = GetLastError();
+ if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
+ if (scmHandle != NULL) CloseServiceHandle(scmHandle);
+ ODSEx("PacketOpenAdapterNPF: StartService failed, LastError=%d\n",error);
+ SetLastError(error);
+ return NULL;
+ }
+ }
+ }
+
+ CloseServiceHandle( svcHandle );
+ svcHandle = NULL;
+
+ }
+ else{
+ error = GetLastError();
+ ODSEx("OpenService failed! LastError=%d", error);
+ SetLastError(error);
+ }
+ }
+ }
+ }
+
+ if (scmHandle != NULL) CloseServiceHandle(scmHandle);
+
+ lpAdapter=(LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER));
+ if (lpAdapter==NULL)
+ {
+ ODS("PacketOpenAdapterNPF: GlobalAlloc Failed\n");
+ error=GetLastError();
+ //set the error to the one on which we failed
+ SetLastError(error);
+ ODS("PacketOpenAdapterNPF: Failed to allocate the adapter structure\n");
+ return NULL;
+ }
+ lpAdapter->NumWrites=1;
+
+ if (LOWORD(GetVersion()) == 4)
+ wsprintf(SymbolicLink,TEXT("\\\\.\\%s"),&AdapterName[16]);
+ else
+ wsprintf(SymbolicLink,TEXT("\\\\.\\Global\\%s"),&AdapterName[16]);
+
+ // Copy only the bytes that fit in the adapter structure.
+ // Note that lpAdapter->SymbolicLink is present for backward compatibility but will
+ // never be used by the apps
+ memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
+
+ //try if it is possible to open the adapter immediately
+ lpAdapter->hFile=CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,
+ 0,NULL,OPEN_EXISTING,0,0);
+
+ if (lpAdapter->hFile != INVALID_HANDLE_VALUE)
+ {
+
+ if(PacketSetReadEvt(lpAdapter)==FALSE){
+ error=GetLastError();
+ ODS("PacketOpenAdapterNPF: Unable to open the read event\n");
+ GlobalFreePtr(lpAdapter);
+ //set the error to the one on which we failed
+ SetLastError(error);
+ ODSEx("PacketOpenAdapterNPF: PacketSetReadEvt failed, LastError=%d\n",error);
+ return NULL;
+ }
+
+ PacketSetMaxLookaheadsize(lpAdapter);
+
+ _snprintf(lpAdapter->Name, ADAPTER_NAME_LENGTH, "%S", AdapterName);
+
+ return lpAdapter;
+ }
+
+
+ error=GetLastError();
+ GlobalFreePtr(lpAdapter);
+ //set the error to the one on which we failed
+ ODSEx("PacketOpenAdapterNPF: CreateFile failed, LastError= %d\n",error);
+ SetLastError(error);
+ return NULL;
+}
+
+/*!
+ \brief Opens an adapter using the DAG capture API.
+ \param AdapterName A string containing the name of the device to open.
+ \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
+ otherwise the return value is NULL.
+
+ \note internal function used by PacketOpenAdapter()
+*/
+#ifdef HAVE_DAG_API
+LPADAPTER PacketOpenAdapterDAG(PCHAR AdapterName, BOOLEAN IsAFile)
+{
+ CHAR DagEbuf[DAGC_ERRBUF_SIZE];
+ LPADAPTER lpAdapter;
+ LONG status;
+ HKEY dagkey;
+ DWORD lptype;
+ DWORD fpc;
+ DWORD lpcbdata = sizeof(fpc);
+ WCHAR keyname[512];
+ PWCHAR tsn;
+
+
+ lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ sizeof(ADAPTER));
+ if (lpAdapter == NULL)
+ {
+ return NULL;
+ }
+
+ if(IsAFile)
+ {
+ // We must add an entry to the adapter description list, otherwise many function will not
+ // be able to work
+ if(!PacketAddAdapterDag(AdapterName, "DAG file", IsAFile))
+ {
+ GlobalFreePtr(lpAdapter);
+ return NULL;
+ }
+
+ // Flag that this is a DAG file
+ lpAdapter->Flags = INFO_FLAG_DAG_FILE;
+ }
+ else
+ {
+ // Flag that this is a DAG card
+ lpAdapter->Flags = INFO_FLAG_DAG_CARD;
+ }
+
+ //
+ // See if the user is asking for fast capture with this device
+ //
+
+ lpAdapter->DagFastProcess = FALSE;
+
+ tsn = (strstr(strlwr((char*)AdapterName), "dag") != NULL)?
+ SChar2WChar(strstr(strlwr((char*)AdapterName), "dag")):
+ L"";
+
+ _snwprintf(keyname, sizeof(keyname), L"%s\\CardParams\\%ws",
+ L"SYSTEM\\CurrentControlSet\\Services\\DAG",
+ tsn);
+
+ GlobalFreePtr(tsn);
+
+ do
+ {
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0 , KEY_READ, &dagkey);
+ if(status != ERROR_SUCCESS)
+ break;
+
+ status = RegQueryValueEx(dagkey,
+ L"FastCap",
+ NULL,
+ &lptype,
+ (char*)&fpc,
+ &lpcbdata);
+
+ if(status == ERROR_SUCCESS)
+ lpAdapter->DagFastProcess = fpc;
+
+ RegCloseKey(dagkey);
+ }
+ while(FALSE);
+
+ //
+ // Open the card
+ //
+ lpAdapter->pDagCard = p_dagc_open(AdapterName,
+ 0,
+ DagEbuf);
+
+ if(lpAdapter->pDagCard == NULL)
+ {
+ GlobalFreePtr(lpAdapter);
+ return NULL;
+ }
+
+ lpAdapter->DagFcsLen = p_dagc_getfcslen(lpAdapter->pDagCard);
+
+ _snprintf(lpAdapter->Name, ADAPTER_NAME_LENGTH, "%s", AdapterName);
+
+ // XXX we could create the read event here
+
+ return lpAdapter;
+}
+#endif // HAVE_DAG_API
+
+//---------------------------------------------------------------------------
+// PUBLIC API
+//---------------------------------------------------------------------------
+
+/** @ingroup packetapi
+ * @{
+ */
+
+/** @defgroup packet32 Packet.dll exported functions and variables
+ * @{
+ */
+
+/*!
+ \brief Return a string with the dll version.
+ \return A char pointer to the version of the library.
+*/
+PCHAR PacketGetVersion()
+{
+ return PacketLibraryVersion;
+}
+
+/*!
+ \brief Return a string with the version of the NPF.sys device driver.
+ \return A char pointer to the version of the driver.
+*/
+PCHAR PacketGetDriverVersion()
+{
+ return PacketDriverVersion;
+}
+
+/*!
+ \brief Stops and unloads the WinPcap device driver.
+ \return If the function succeeds, the return value is nonzero, otherwise it is zero.
+
+ This function can be used to unload the driver from memory when the application no more needs it.
+ Note that the driver is physically stopped and unloaded only when all the files on its devices
+ are closed, i.e. when all the applications that use WinPcap close all their adapters.
+*/
+BOOL PacketStopDriver()
+{
+ SC_HANDLE scmHandle;
+ SC_HANDLE schService;
+ BOOL ret;
+ SERVICE_STATUS serviceStatus;
+
+ scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+ if(scmHandle != NULL){
+
+ schService = OpenService (scmHandle,
+ NPFServiceName,
+ SERVICE_ALL_ACCESS
+ );
+
+ if (schService != NULL)
+ {
+
+ ret = ControlService (schService,
+ SERVICE_CONTROL_STOP,
+ &serviceStatus
+ );
+ if (!ret)
+ {
+ }
+
+ CloseServiceHandle (schService);
+
+ CloseServiceHandle(scmHandle);
+
+ return ret;
+ }
+ }
+
+ return FALSE;
+}
+
+/*!
+ \brief Opens an adapter.
+ \param AdapterName A string containing the name of the device to open.
+ Use the PacketGetAdapterNames() function to retrieve the list of available devices.
+ \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
+ otherwise the return value is NULL.
+*/
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName)
+{
+ LPADAPTER lpAdapter;
+ WCHAR *AdapterNameU;
+ SC_HANDLE svcHandle = NULL;
+ PCHAR AdapterNameA = NULL;
+#ifndef _WINNT4
+ PADAPTER_INFO TAdInfo;
+#endif // _WINNT4
+ ODSEx("PacketOpenAdapter: trying to open the adapter=%s\n",AdapterName)
+
+ if(AdapterName[1]!=0)
+ {
+ //
+ // ASCII
+ //
+
+ AdapterNameU = SChar2WChar(AdapterName);
+ AdapterNameA = AdapterName;
+ AdapterName = (PCHAR)AdapterNameU;
+ }
+ else
+ {
+ //
+ // Unicode
+ //
+ AdapterNameU = NULL;
+ AdapterNameA = WChar2SChar((PWCHAR)AdapterName);
+ }
+
+#ifndef _WINNT4
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+ // Find the PADAPTER_INFO structure associated with this adapter
+ TAdInfo = PacketFindAdInfo(AdapterNameA);
+ if(TAdInfo == NULL)
+ {
+ PacketUpdateAdInfo(AdapterNameA);
+ TAdInfo = PacketFindAdInfo(AdapterNameA);
+ if(TAdInfo == NULL)
+ {
+
+ //can be an ERF file?
+ lpAdapter = PacketOpenAdapterDAG(AdapterNameA, TRUE);
+
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ else
+ GlobalFreePtr(AdapterNameA);
+
+ ReleaseMutex(AdaptersInfoMutex);
+ if (lpAdapter == NULL)
+ SetLastError(ERROR_BAD_UNIT); //this is the best we can do....
+ return lpAdapter;
+ }
+ }
+
+ //
+ // Check adapter type
+ //
+ if(TAdInfo->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ //
+ // Not a standard NDIS adapter, we must have specific handling
+ //
+
+ if(TAdInfo->Flags & INFO_FLAG_NDISWAN_ADAPTER)
+ {
+ //
+ // This is a wan adapter. Open it using the netmon API
+ //
+ lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ sizeof(ADAPTER));
+ if (lpAdapter == NULL)
+ {
+ if (AdapterNameU != NULL) GlobalFreePtr(AdapterNameU);
+ else GlobalFreePtr(AdapterNameA);
+ ReleaseMutex(AdaptersInfoMutex);
+ SetLastError(ERROR_BAD_UNIT);
+ return NULL;
+ }
+
+ // Backup flags for future usage
+ lpAdapter->Flags = TAdInfo->Flags;
+
+ // Open the adapter
+ lpAdapter->pWanAdapter = WanPacketOpenAdapter();
+ if (lpAdapter->pWanAdapter == NULL)
+ {
+ if (AdapterNameU != NULL) GlobalFreePtr(AdapterNameU);
+ else GlobalFreePtr(AdapterNameA);
+
+ GlobalFreePtr(lpAdapter);
+ ReleaseMutex(AdaptersInfoMutex);
+ SetLastError(ERROR_BAD_UNIT);
+ return NULL;
+ }
+
+ _snprintf(lpAdapter->Name, ADAPTER_NAME_LENGTH, "%s", AdapterNameA);
+
+ lpAdapter->ReadEvent = WanPacketGetReadEvent(lpAdapter->pWanAdapter);
+
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ else
+ GlobalFreePtr(AdapterNameA);
+
+ ReleaseMutex(AdaptersInfoMutex);
+ return lpAdapter;
+ }
+ else
+ if(TAdInfo->Flags & INFO_FLAG_DAG_CARD)
+ {
+ //
+ // This is a Dag card. Open it using the dagc API
+ //
+ lpAdapter = PacketOpenAdapterDAG(AdapterNameA, FALSE);
+
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ else
+ GlobalFreePtr(AdapterNameA);
+
+ ReleaseMutex(AdaptersInfoMutex);
+ if (lpAdapter == NULL)
+ SetLastError(ERROR_BAD_UNIT);
+ return lpAdapter;
+ }
+ else
+ if(TAdInfo->Flags == INFO_FLAG_DONT_EXPORT)
+ {
+ //
+ // The adapter is flagged as not exported, probably because it's broken
+ // or incompatible with WinPcap. We end here with an error.
+ //
+ ODSEx("The user openend the adapter %s which is flagged as not exported", AdapterNameA);
+ if (AdapterNameU != NULL) GlobalFreePtr(AdapterNameU);
+ else GlobalFreePtr(AdapterNameA);
+ ReleaseMutex(AdaptersInfoMutex);
+ SetLastError(ERROR_BAD_UNIT);
+ return NULL;
+ }
+ }
+
+ ReleaseMutex(AdaptersInfoMutex);
+
+#endif // _WINNT4
+
+ lpAdapter = PacketOpenAdapterNPF(AdapterName);
+
+ if (AdapterNameU != NULL)
+ GlobalFreePtr(AdapterNameU);
+ else
+ GlobalFreePtr(AdapterNameA);
+
+ return lpAdapter;
+}
+
+/*!
+ \brief Closes an adapter.
+ \param lpAdapter the pointer to the adapter to close.
+
+ PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
+*/
+VOID PacketCloseAdapter(LPADAPTER lpAdapter)
+{
+ if(!lpAdapter)
+ {
+ ODS("PacketCloseAdapter: attempt to close a NULL adapter\n");
+ return;
+ }
+
+#ifndef _WINNT4
+ if(lpAdapter->pWanAdapter != NULL)
+ {
+ WanPacketCloseAdapter(lpAdapter->pWanAdapter);
+ GlobalFreePtr(lpAdapter);
+ return;
+ }
+#ifdef HAVE_DAG_API
+ else
+ if(lpAdapter->pDagCard != NULL)
+ {
+ if(lpAdapter->Flags & INFO_FLAG_DAG_FILE & ~INFO_FLAG_DAG_CARD)
+ {
+ // This is a file. We must remove the entry in the adapter description list
+ PacketUpdateAdInfo(lpAdapter->Name);
+ }
+ p_dagc_close(lpAdapter->pDagCard);
+ }
+#endif // HAVE_DAG_API
+#endif // _WINNT4
+
+ CloseHandle(lpAdapter->hFile);
+ SetEvent(lpAdapter->ReadEvent);
+ CloseHandle(lpAdapter->ReadEvent);
+ GlobalFreePtr(lpAdapter);
+}
+
+/*!
+ \brief Allocates a _PACKET structure.
+ \return On succeess, the return value is the pointer to a _PACKET structure otherwise the
+ return value is NULL.
+
+ The structure returned will be passed to the PacketReceivePacket() function to receive the
+ packets from the driver.
+
+ \warning The Buffer field of the _PACKET structure is not set by this function.
+ The buffer \b must be allocated by the application, and associated to the PACKET structure
+ with a call to PacketInitPacket.
+*/
+LPPACKET PacketAllocatePacket(void)
+{
+
+ LPPACKET lpPacket;
+ lpPacket=(LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
+ if (lpPacket==NULL)
+ {
+ ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
+ return NULL;
+ }
+ return lpPacket;
+}
+
+/*!
+ \brief Frees a _PACKET structure.
+ \param lpPacket The structure to free.
+
+ \warning the user-allocated buffer associated with the _PACKET structure is not deallocated
+ by this function and \b must be explicitly deallocated by the programmer.
+
+*/
+VOID PacketFreePacket(LPPACKET lpPacket)
+
+{
+ GlobalFreePtr(lpPacket);
+}
+
+/*!
+ \brief Initializes a _PACKET structure.
+ \param lpPacket The structure to initialize.
+ \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
+ \param Length the length of the buffer. This is the maximum buffer size that will be
+ transferred from the driver to the application using a single read.
+
+ \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
+ influence the performance of the capture process, since this buffer will contain the packets received
+ from the the driver. The driver is able to return several packets using a single read call
+ (see the PacketReceivePacket() function for details), and the number of packets transferable to the
+ application in a call is limited only by the size of the buffer associated with the PACKET structure
+ passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
+ decrease the number of system calls, reducing the impcat of the capture process on the processor.
+*/
+
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
+
+{
+ lpPacket->Buffer = Buffer;
+ lpPacket->Length = Length;
+ lpPacket->ulBytesReceived = 0;
+ lpPacket->bIoComplete = FALSE;
+}
+
+/*!
+ \brief Read data (packets or statistics) from the NPF driver.
+ \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
+ the data is received.
+ \param lpPacket Pointer to a PACKET structure that will contain the data.
+ \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
+ older applications.
+ \return If the function succeeds, the return value is nonzero.
+
+ The data received with this function can be a group of packets or a static on the network traffic,
+ depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
+ function. Give a look at that function if you are interested in the format used to return statistics
+ values, here only the normal capture mode will be described.
+
+ The number of packets received with this function is variable. It depends on the number of packets
+ currently stored in the driver buffer, on the size of these packets and on the size of the buffer
+ associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
+ packets to the application.
+
+ \image html encoding.gif "method used to encode the packets"
+
+ Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
+ that structure is updated with the amount of data copied in the buffer. Each packet has a header
+ consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
+ is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
+ and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
+
+ Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
+ in the developer's pack, or in the pcap_read() function of wpcap.
+*/
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
+{
+ BOOLEAN res;
+
+#ifndef _WINNT4
+
+ if (AdapterObject->pWanAdapter != NULL)
+ {
+ lpPacket->ulBytesReceived = WanPacketReceivePacket(AdapterObject->pWanAdapter, lpPacket->Buffer, lpPacket->Length);
+ return TRUE;
+ }
+#ifdef HAVE_DAG_API
+ else
+ if(AdapterObject->pDagCard != NULL)
+ {
+
+ p_dagc_wait(AdapterObject->pDagCard, &AdapterObject->DagReadTimeout);
+
+ if(p_dagc_receive(AdapterObject->pDagCard, &AdapterObject->DagBuffer, &lpPacket->ulBytesReceived) == 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+#endif // HAVE_DAG_API
+#endif // _WINNT4
+
+ if((int)AdapterObject->ReadTimeOut != -1)
+ WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
+
+ res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
+
+ return res;
+}
+
+/*!
+ \brief Sends one (or more) copies of a packet to the network.
+ \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
+ send the packets.
+ \param lpPacket Pointer to a PACKET structure with the packet to send.
+ \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
+ older applications.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
+ will have to include the protocol headers, since the packet is sent to the network 'as is'.
+ The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
+ added by the network interface.
+
+ The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
+ it is possible to change the number of times a single write must be repeated. The default is 1,
+ i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
+ greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
+ the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
+ high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
+ to obtain high network loads.
+ The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
+ to send a buffer with multiple packets.
+
+ \note The ability to write multiple packets is currently present only in the Windows NTx version of the
+ packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
+ that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
+ compared to the one of WindowsNTx.
+*/
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
+{
+ DWORD BytesTransfered;
+
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketSendPacket: packet sending not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
+}
+
+
+/*!
+ \brief Sends a buffer of packets to the network.
+ \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
+ send the packets.
+ \param PacketBuff Pointer to buffer with the packets to send.
+ \param Size Size of the buffer pointed by the PacketBuff argument.
+ \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
+ fast as possible
+ \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+ error occurred during the send. The error can be caused by a driver/adapter problem or by an
+ inconsistent/bogus packet buffer.
+
+ This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
+ number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
+ by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
+ 'Raw packets' means that the sending application will have to include the protocol headers, since every packet
+ is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be
+ transparently added by the network interface.
+
+ \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
+ buffered in the kernel driver, so the number of context switches is reduced.
+
+ \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
+ This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
+ (depending on the precision of the performance counter of the machine). Such a precision cannot be reached
+ sending the packets separately with PacketSendPacket().
+*/
+INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
+{
+ BOOLEAN Res;
+ DWORD BytesTransfered, TotBytesTransfered=0;
+ DWORD last_total = 0;
+ struct timeval BufStartTime;
+ //LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq;
+ UINT num_count = 0;
+
+
+ ODS("PacketSendPackets");
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketSendPackets: packet sending not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ // Obtain starting timestamp of the buffer
+ BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
+ BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
+
+ // Retrieve the reference time counters
+// QueryPerformanceCounter(&StartTicks);
+// QueryPerformanceFrequency(&TimeFreq);
+
+// CurTicks.QuadPart = StartTicks.QuadPart;
+
+ do{
+ // Send the data to the driver
+ Res = DeviceIoControl(AdapterObject->hFile,
+ (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
+ (PCHAR)PacketBuff + TotBytesTransfered,
+ Size - TotBytesTransfered,
+ NULL,
+ 0,
+ &BytesTransfered,
+ NULL);
+
+ TotBytesTransfered += BytesTransfered;
+
+ // Exit from the loop on termination or error
+ if(TotBytesTransfered >= Size || Res != TRUE)
+ break;
+
+ if (last_total != TotBytesTransfered)
+ {
+ num_count = 0;
+ last_total = TotBytesTransfered;
+ }
+
+ num_count++;
+
+ if (num_count >= 100000)
+ {
+ // Fatal Error: Infinite Loop
+ return 0x7FFFFFFF;
+ }
+
+ // calculate the time interval to wait before sending the next packet
+ /*TargetTicks.QuadPart = StartTicks.QuadPart +
+ (LONGLONG)
+ ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
+ (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
+ (TimeFreq.QuadPart) / 1000000;
+
+ // Wait until the time interval has elapsed
+ while( CurTicks.QuadPart <= TargetTicks.QuadPart )
+ QueryPerformanceCounter(&CurTicks);*/
+
+ }
+ while(TRUE);
+
+ return TotBytesTransfered;
+}
+
+/*!
+ \brief Defines the minimum amount of data that will be received in a read.
+ \param AdapterObject Pointer to an _ADAPTER structure
+ \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
+ release a read on this adapter.
+ \return If the function succeeds, the return value is nonzero.
+
+ In presence of a large value for nbytes, the kernel waits for the arrival of several packets before
+ copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
+ i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value
+ means that the kernel will copy the packets as soon as the application is ready to receive them. This is
+ suggested for real time applications (like, for example, a bridge) that need the better responsiveness from
+ the kernel.
+
+ \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer
+ this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
+*/
+
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
+{
+ DWORD BytesReturned;
+
+#ifndef _WINNT4
+ if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
+ return WanPacketSetMinToCopy(AdapterObject->pWanAdapter, nbytes);
+#ifdef HAVE_DAG_API
+ else
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ // No mintocopy with DAGs
+ return TRUE;
+#endif // HAVE_DAG_API
+#endif // _WINNT4
+
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets the working mode of an adapter.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param mode The new working mode of the adapter.
+ \return If the function succeeds, the return value is nonzero.
+
+ The device driver of WinPcap has 4 working modes:
+ - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
+ to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
+ - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
+ precise intervals, statics values on the network traffic. The interval between the statistic samples is
+ by default 1 second but it can be set to any other value (with a 1 ms precision) with the
+ PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
+ mode is shown in the following figure:<p>
+ \image html stats.gif "data structure returned by statistical mode"
+ Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter
+ previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are
+ encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a
+ very low impact on system performance compared to capture mode.
+ - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
+ method is much faster than saving the packets after having captured them. No data is returned
+ by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
+ this filter are dumped to disk.
+ - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap
+ format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the
+ network traffic and on the amount of data saved to file, in a way similar to statistical mode.
+ The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in
+ the following figure:<p>
+ \image html dump.gif "data structure returned by statistical dump mode"
+ Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the
+ effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are
+ dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly
+ by wpcap.
+ Look at the NetMeter example in the
+ WinPcap developer's pack to see how to use statistics mode.
+*/
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
+{
+ DWORD BytesReturned;
+
+#ifndef _WINNT4
+ if (AdapterObject->pWanAdapter != NULL)
+ return WanPacketSetMode(AdapterObject->pWanAdapter, mode);
+#endif // _WINNT4
+
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param name the file name, in ASCII or UNICODE.
+ \param len the length of the buffer containing the name, in bytes.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function defines the file name that the driver will open to store the packets on disk when
+ it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
+ called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
+ If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver
+ closes the old file and opens the new one.
+*/
+
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
+{
+ DWORD BytesReturned;
+ WCHAR *FileName;
+ BOOLEAN res;
+ WCHAR NameWithPath[1024];
+ int TStrLen;
+ WCHAR *NamePos;
+
+#ifndef _WINNT4
+ if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketSetDumpName: not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
+ FileName=SChar2WChar(name);
+ len*=2;
+ }
+ else { //Unicode
+ FileName=name;
+ }
+
+ TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
+
+ len=TStrLen*2+2; //add the terminating null character
+
+ // Try to catch malformed strings
+ if(len>2048){
+ if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
+ return FALSE;
+ }
+
+ res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
+ free(FileName);
+ return res;
+}
+
+/*!
+ \brief Set the dump mode limits.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
+ \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
+ \return If the function succeeds, the return value is nonzero.
+
+ This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
+ is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
+ very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
+ the first of the two is reached.
+
+ \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush
+ correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
+*/
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
+{
+ DWORD BytesReturned;
+ UINT valbuff[2];
+
+#ifndef _WINNT4
+ if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketSetDumpLimits: not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ valbuff[0] = maxfilesize;
+ valbuff[1] = maxnpacks;
+
+ return DeviceIoControl(AdapterObject->hFile,
+ pBIOCSETDUMPLIMITS,
+ valbuff,
+ sizeof valbuff,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL);
+}
+
+/*!
+ \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
+ \return TRUE if the dump is ended, FALSE otherwise.
+
+ PacketIsDumpEnded() informs the user about the limits that were set with a previous call to
+ PacketSetDumpLimits().
+
+ \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits
+ (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
+ block the application on this call forever.
+*/
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
+{
+ DWORD BytesReturned;
+ int IsDumpEnded;
+ BOOLEAN res;
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketIsDumpEnded: not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ if(sync)
+ WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
+
+ res = DeviceIoControl(AdapterObject->hFile,
+ pBIOCISDUMPENDED,
+ NULL,
+ 0,
+ &IsDumpEnded,
+ 4,
+ &BytesReturned,
+ NULL);
+
+ if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
+
+ return (BOOLEAN)IsDumpEnded;
+}
+
+/*!
+ \brief Returns the notification event associated with the read calls on an adapter.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \return The handle of the event that the driver signals when some data is available in the kernel buffer.
+
+ The event returned by this function is signaled by the driver if:
+ - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal
+ than the one set with the PacketSetMinToCopy() function is received from the network.
+ - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
+ but the the timeout set with the PacketSetReadTimeout() function has elapsed.
+ - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the
+ PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
+
+ In every case, a call to PacketReceivePacket() will return immediately.
+ The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects)
+ to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that
+ need to wait concurrently on several events.
+
+*/
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
+{
+ return AdapterObject->ReadEvent;
+}
+
+/*!
+ \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param nwrites Number of copies of a packet that will be physically sent by the interface.
+ \return If the function succeeds, the return value is nonzero.
+
+ See PacketSendPacket() for details.
+*/
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
+{
+ DWORD BytesReturned;
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ ODS("PacketSetNumWrites: not allowed on wan adapters\n");
+ return FALSE;
+ }
+#endif // _WINNT4
+
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets the timeout after which a read on an adapter returns.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on
+ the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver.
+ Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
+ A timeout of -1 causes PacketReceivePacket() to always return immediately.
+ \return If the function succeeds, the return value is nonzero.
+
+ \note This function works also if the adapter is working in statistics mode, and can be used to set the
+ time interval between two statistic reports.
+*/
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
+{
+ DWORD BytesReturned;
+ int DriverTimeOut=-1;
+
+#ifndef _WINNT4
+ if (AdapterObject->pWanAdapter != NULL)
+ return WanPacketSetReadTimeout(AdapterObject->pWanAdapter,timeout);
+#endif // _WINNT4
+
+ AdapterObject->ReadTimeOut=timeout;
+
+#ifdef HAVE_DAG_API
+ // Under DAG, we simply store the timeout value and then
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ {
+ if(timeout == 1)
+ {
+ // tell DAG card to return immediately
+ AdapterObject->DagReadTimeout.tv_sec = 0;
+ AdapterObject->DagReadTimeout.tv_usec = 0;
+ }
+ else
+ if(timeout == 1)
+ {
+ // tell the DAG card to wait forvever
+ AdapterObject->DagReadTimeout.tv_sec = -1;
+ AdapterObject->DagReadTimeout.tv_usec = -1;
+ }
+ else
+ {
+ // Set the timeout for the DAG card
+ AdapterObject->DagReadTimeout.tv_sec = timeout / 1000;
+ AdapterObject->DagReadTimeout.tv_usec = (timeout * 1000) % 1000000;
+ }
+
+ return TRUE;
+ }
+#endif // HAVE_DAG_API
+
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets the size of the kernel-level buffer associated with a capture.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param dim New size of the buffer, in \b kilobytes.
+ \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to
+ allocate the new buffer.
+
+ When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are
+ lost.
+
+ Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
+ An adequate buffer in the driver is able to keep the packets while the application is busy, compensating
+ the delays of the application and avoiding the loss of packets during bursts or high network activity.
+ The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to
+ set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
+*/
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
+{
+ DWORD BytesReturned;
+
+#ifndef _WINNT4
+ if (AdapterObject->pWanAdapter != NULL)
+ return WanPacketSetBufferSize(AdapterObject->pWanAdapter, dim);
+#ifdef HAVE_DAG_API
+ else
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ // We can't change DAG buffers
+ return TRUE;
+#endif // HAVE_DAG_API
+
+#endif // _WINNT4
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets a kernel-level packet filter.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param fp Pointer to a filtering program that will be associated with this capture or monitoring
+ instance and that will be executed on every incoming packet.
+ \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs
+ or if the filter program is not accepted after a safeness check by the driver. The driver performs
+ the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
+ conformat filters.
+
+ This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a
+ set of bpf_insn instructions.
+
+ A filter can be automatically created by using the pcap_compile() function of wpcap. This function
+ converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at
+ http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but
+ you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd
+ flags to obtain the pseudocode.
+
+*/
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject, struct bpf_program *fp)
+{
+ DWORD BytesReturned;
+
+#ifndef _WINNT4
+ if (AdapterObject->pWanAdapter != NULL)
+ return WanPacketSetBpfFilter(AdapterObject->pWanAdapter, (PUCHAR)fp->bf_insns, fp->bf_len * sizeof(struct bpf_insn));
+#ifdef HAVE_DAG_API
+ else
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ // Delegate the filtering to higher layers since it's too expensive here
+ return TRUE;
+#endif // HAVE_DAG_API
+#endif // _WINNT4
+
+ return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
+}
+
+/*!
+ \brief Sets the snap len on the adapters that allow it.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param snaplen Desired snap len for this capture.
+ \return If the function succeeds, the return value is nonzero and specifies the actual snaplen that
+ the card is using. If the function fails or if the card does't allow to set sna length, the return
+ value is 0.
+
+ The snap len is the amount of packet that is actually captured by the interface and received by the
+ application. Some interfaces allow to capture only a portion of any packet for performance reasons.
+
+ \note: the return value can be different from the snaplen parameter, for example some boards round the
+ snaplen to 4 bytes.
+*/
+INT PacketSetSnapLen(LPADAPTER AdapterObject, int snaplen)
+{
+
+#ifdef HAVE_DAG_API
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ return p_dagc_setsnaplen(AdapterObject->pDagCard, snaplen);
+ else
+#endif // HAVE_DAG_API
+ return 0;
+}
+
+/*!
+ \brief Returns a couple of statistic values about the current capture session.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
+ \return If the function succeeds, the return value is nonzero.
+
+ With this function, the programmer can know the value of two internal variables of the driver:
+
+ - the number of packets that have been received by the adapter AdapterObject, starting at the
+ time in which it was opened with PacketOpenAdapter.
+ - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
+ buffer associated with the adapter is full.
+*/
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
+{
+ BOOLEAN Res;
+ DWORD BytesReturned;
+ struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
+
+#ifndef _WINNT4
+#ifdef HAVE_DAG_API
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ {
+ dagc_stats_t DagStats;
+
+ // Note: DAG cards are currently very limited from the statistics reporting point of view,
+ // so most of the values returned by dagc_stats() are zero at the moment
+ if(p_dagc_stats(AdapterObject->pDagCard, &DagStats) == 0)
+ {
+ // XXX: Only copy the dropped packets for now, since the received counter is not supported by
+ // DAGS at the moment
+
+ s->bs_recv = (ULONG)DagStats.received;
+ s->bs_drop = (ULONG)DagStats.dropped;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else
+#endif // HAVE_DAG_API
+ if ( AdapterObject->pWanAdapter != NULL)
+ Res = WanPacketGetStats(AdapterObject->pWanAdapter, (PVOID)&tmpstat);
+ else
+#endif // _WINNT4
+
+ Res = DeviceIoControl(AdapterObject->hFile,
+ pBIOCGSTATS,
+ NULL,
+ 0,
+ &tmpstat,
+ sizeof(struct bpf_stat),
+ &BytesReturned,
+ NULL);
+
+
+ // Copy only the first two values retrieved from the driver
+ s->bs_recv = tmpstat.bs_recv;
+ s->bs_drop = tmpstat.bs_drop;
+
+ return Res;
+}
+
+/*!
+ \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
+ \return If the function succeeds, the return value is nonzero.
+
+ With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
+
+ - the number of drops by interface (not yet supported, always 0).
+ - the number of packets that reached the application, i.e that were accepted by the kernel filter and
+ that fitted in the kernel buffer.
+*/
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
+{
+ BOOLEAN Res;
+ DWORD BytesReturned;
+ struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
+
+#ifndef _WINNT4
+#ifdef HAVE_DAG_API
+ if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
+ {
+ dagc_stats_t DagStats;
+
+ // Note: DAG cards are currently very limited from the statistics reporting point of view,
+ // so most of the values returned by dagc_stats() are zero at the moment
+ p_dagc_stats(AdapterObject->pDagCard, &DagStats);
+ s->bs_recv = (ULONG)DagStats.received;
+ s->bs_drop = (ULONG)DagStats.dropped;
+ s->ps_ifdrop = 0;
+ s->bs_capt = (ULONG)DagStats.captured;
+ }
+#endif // HAVE_DAG_API
+ if(AdapterObject->pWanAdapter != NULL)
+ Res = WanPacketGetStats(AdapterObject->pWanAdapter, (PVOID)&tmpstat);
+ else
+#endif // _WINNT4
+
+ Res = DeviceIoControl(AdapterObject->hFile,
+ pBIOCGSTATS,
+ NULL,
+ 0,
+ &tmpstat,
+ sizeof(struct bpf_stat),
+ &BytesReturned,
+ NULL);
+
+ s->bs_recv = tmpstat.bs_recv;
+ s->bs_drop = tmpstat.bs_drop;
+ s->ps_ifdrop = tmpstat.ps_ifdrop;
+ s->bs_capt = tmpstat.bs_capt;
+
+ return Res;
+}
+
+/*!
+ \brief Performs a query/set operation on an internal variable of the network card driver.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
+ \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
+ \return If the function succeeds, the return value is nonzero.
+
+ \note not all the network adapters implement all the query/set functions. There is a set of mandatory
+ OID functions that is granted to be present on all the adapters, and a set of facultative functions, not
+ provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a
+ facultative function, be careful to enclose it in an if statement to check the result.
+*/
+BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData)
+{
+ DWORD BytesReturned;
+ BOOLEAN Result;
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ return FALSE;
+#endif // _WINNT4
+
+ Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? (DWORD)pBIOCSETOID : (DWORD)pBIOCQUERYOID,
+ OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
+ sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);
+
+ // output some debug info
+ ODSEx("PacketRequest, OID=%d ", OidData->Oid);
+ ODSEx("Length=%d ", OidData->Length);
+ ODSEx("Set=%d ", Set);
+ ODSEx("Res=%d\n", Result);
+
+ return Result;
+}
+
+/*!
+ \brief Sets a hardware filter on the incoming packets.
+ \param AdapterObject Pointer to an _ADAPTER structure.
+ \param Filter The identifier of the filter.
+ \return If the function succeeds, the return value is nonzero.
+
+ The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
+ device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
+
+ - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter.
+ - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted.
+ - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted.
+ - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted.
+ - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted.
+ - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST
+*/
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter)
+{
+ BOOLEAN Status;
+ ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
+ PPACKET_OID_DATA OidData;
+
+#ifndef _WINNT4
+ if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ return TRUE;
+#endif // _WINNT4
+
+ OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
+ if (OidData == NULL) {
+ ODS("PacketSetHwFilter: GlobalAlloc Failed\n");
+ return FALSE;
+ }
+ OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
+ OidData->Length=sizeof(ULONG);
+ *((PULONG)OidData->Data)=Filter;
+ Status=PacketRequest(AdapterObject,TRUE,OidData);
+ GlobalFreePtr(OidData);
+ return Status;
+}
+
+/*!
+ \brief Retrieve the list of available network adapters and their description.
+ \param pStr User allocated string that will be filled with the names of the adapters.
+ \param BufferSize Length of the buffer pointed by pStr. If the function fails, this variable contains the
+ number of bytes that are needed to contain the adapter list.
+ \return If the function succeeds, the return value is nonzero. If the return value is zero, BufferSize contains
+ the number of bytes that are needed to contain the adapter list.
+
+ Usually, this is the first function that should be used to communicate with the driver.
+ It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>.
+ After the names of the adapters, pStr contains a string that describes each of them.
+
+ After a call to PacketGetAdapterNames pStr contains, in succession:
+ - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
+ - a double "\0"
+ - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number
+ of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
+ so on.
+ - a double "\0".
+*/
+
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize)
+{
+ PADAPTER_INFO TAdInfo;
+ ULONG SizeNeeded = 1;
+ ULONG SizeNames = 1;
+ ULONG SizeDesc;
+ ULONG OffDescriptions;
+
+ ODSEx("PacketGetAdapterNames: BufferSize=%d\n", *BufferSize);
+
+ //
+ // Create the adapter information list
+ //
+ PacketPopulateAdaptersInfoList();
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+ if(!AdaptersInfoList)
+ {
+ ReleaseMutex(AdaptersInfoMutex);
+ *BufferSize = 0;
+ return FALSE; // No adapters to return
+ }
+
+ //
+ // First scan of the list to calculate the offsets and check the sizes
+ //
+ for(TAdInfo = AdaptersInfoList; TAdInfo != NULL; TAdInfo = TAdInfo->Next)
+ {
+ if(TAdInfo->Flags != INFO_FLAG_DONT_EXPORT)
+ {
+ // Update the size variables
+ SizeNeeded += (int)strlen(TAdInfo->Name) + (int)strlen(TAdInfo->Description) + 2;
+ SizeNames += (int)strlen(TAdInfo->Name) + 1;
+ }
+ }
+
+ // Check that we don't overflow the buffer.
+ // Note: 2 is the number of additional separators needed inside the list
+ if(SizeNeeded + 2 >= *BufferSize || pStr == NULL)
+ {
+ ReleaseMutex(AdaptersInfoMutex);
+
+ ODS("PacketGetAdapterNames: input buffer too small\n");
+ *BufferSize = SizeNeeded + 4; // Report the required size
+ return FALSE;
+ }
+
+ OffDescriptions = SizeNames;
+
+ //
+ // Second scan of the list to copy the information
+ //
+ for(TAdInfo = AdaptersInfoList, SizeNames = 0, SizeDesc = 0; TAdInfo != NULL; TAdInfo = TAdInfo->Next)
+ {
+ if(TAdInfo->Flags != INFO_FLAG_DONT_EXPORT)
+ {
+ // Copy the data
+ strcpy(((PCHAR)pStr) + SizeNames, TAdInfo->Name);
+ strcpy(((PCHAR)pStr) + OffDescriptions + SizeDesc, TAdInfo->Description);
+
+ // Update the size variables
+ SizeNames += (int)strlen(TAdInfo->Name) + 1;
+ SizeDesc += (int)strlen(TAdInfo->Description) + 1;
+ }
+ }
+
+ // Separate the two lists
+ ((PCHAR)pStr)[SizeNames] = 0;
+
+ // End the list with a further \0
+ ((PCHAR)pStr)[SizeNeeded] = 0;
+
+
+ ReleaseMutex(AdaptersInfoMutex);
+ return TRUE;
+}
+
+/*!
+ \brief Returns comprehensive information the addresses of an adapter.
+ \param AdapterName String that contains the name of the adapter.
+ \param buffer A user allocated array of npf_if_addr that will be filled by the function.
+ \param NEntries Size of the array (in npf_if_addr).
+ \return If the function succeeds, the return value is nonzero.
+
+ This function grabs from the registry information like the IP addresses, the netmasks
+ and the broadcast addresses of an interface. The buffer passed by the user is filled with
+ npf_if_addr structures, each of which contains the data for a single address. If the buffer
+ is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
+ if you want only the first address.
+*/
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries)
+{
+ PADAPTER_INFO TAdInfo;
+ PCHAR Tname;
+ BOOLEAN Res, FreeBuff;
+
+ ODS("PacketGetNetInfo\n");
+
+ // Provide conversion for backward compatibility
+ if(AdapterName[1] != 0)
+ { //ASCII
+ Tname = AdapterName;
+ FreeBuff = FALSE;
+ }
+ else
+ {
+ Tname = WChar2SChar((PWCHAR)AdapterName);
+ FreeBuff = TRUE;
+ }
+
+ //
+ // Update the information about this adapter
+ //
+ if(!PacketUpdateAdInfo(Tname))
+ {
+ ODS("PacketGetNetInfo: Adapter not found\n");
+ if(FreeBuff)GlobalFreePtr(Tname);
+ return FALSE;
+ }
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+ // Find the PADAPTER_INFO structure associated with this adapter
+ TAdInfo = PacketFindAdInfo(Tname);
+
+ if(TAdInfo != NULL)
+ {
+ *NEntries = (TAdInfo->NNetworkAddresses < *NEntries)? TAdInfo->NNetworkAddresses: *NEntries;
+ //TODO what if nentries = 0?
+ if (*NEntries > 0)
+ memcpy(buffer, TAdInfo->NetworkAddresses, *NEntries * sizeof(npf_if_addr));
+ Res = TRUE;
+ }
+ else
+ {
+ ODS("PacketGetNetInfo: Adapter not found\n");
+ Res = FALSE;
+ }
+
+ ReleaseMutex(AdaptersInfoMutex);
+
+ if(FreeBuff)GlobalFreePtr(Tname);
+
+ return Res;
+}
+
+/*!
+ \brief Returns information about the MAC type of an adapter.
+ \param AdapterObject The adapter on which information is needed.
+ \param type Pointer to a NetType structure that will be filled by the function.
+ \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
+
+ This function return the link layer and the speed (in bps) of an opened adapter.
+ The LinkType field of the type parameter can have one of the following values:
+
+ - NdisMedium802_3: Ethernet (802.3)
+ - NdisMediumWan: WAN
+ - NdisMedium802_5: Token Ring (802.5)
+ - NdisMediumFddi: FDDI
+ - NdisMediumAtm: ATM
+ - NdisMediumArcnet878_2: ARCNET (878.2)
+*/
+BOOLEAN PacketGetNetType(LPADAPTER AdapterObject, NetType *type)
+{
+ PADAPTER_INFO TAdInfo;
+ BOOLEAN ret;
+ ODS("PacketGetNetType\n");
+
+ WaitForSingleObject(AdaptersInfoMutex, INFINITE);
+ // Find the PADAPTER_INFO structure associated with this adapter
+ TAdInfo = PacketFindAdInfo(AdapterObject->Name);
+
+ if(TAdInfo != NULL)
+ {
+ // Copy the data
+ memcpy(type, &(TAdInfo->LinkLayer), sizeof(struct NetType));
+ ret = TRUE;
+ }
+ else
+ {
+ ODS("PacketGetNetType: Adapter not found\n");
+ ret = FALSE;
+ }
+
+ ReleaseMutex(AdaptersInfoMutex);
+
+ return ret;
+}
+
+/* @} */
+BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior)
+{
+ DWORD BytesReturned;
+ BOOLEAN result;
+
+ if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
+ {
+ return FALSE;
+ }
+
+
+ result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
+ pBIOCISETLOBBEH,
+ &LoopbackBehavior,
+ sizeof(UINT),
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL);
+
+ return result;
+}
+
diff --git a/src/SeeDll/Packet32.h b/src/SeeDll/Packet32.h
new file mode 100644
index 00000000..b5cd1cf9
--- /dev/null
+++ b/src/SeeDll/Packet32.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup packetapi
+ * @{
+ */
+
+/** @defgroup packet32h Packet.dll definitions and data structures
+ * Packet32.h contains the data structures and the definitions used by packet.dll.
+ * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
+ * by the applications that use the functions of this library
+ * @{
+ */
+
+#ifndef __PACKET32
+#define __PACKET32
+
+#include <winsock2.h>
+#include "devioctl.h"
+#ifdef HAVE_DAG_API
+#include <dagc.h>
+#endif /* HAVE_DAG_API */
+
+// Working modes
+#define PACKET_MODE_CAPT 0x0 ///< Capture mode
+#define PACKET_MODE_STAT 0x1 ///< Statistical mode
+#define PACKET_MODE_MON 0x2 ///< Monitoring mode
+#define PACKET_MODE_DUMP 0x10 ///< Dump mode
+#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
+
+// ioctls
+#define FILE_DEVICE_PROTOCOL 0x8000
+
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size.
+#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program.
+#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats.
+#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout.
+#define pBIOCSMODE 7412 ///< IOCTL code: set working mode.
+#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app.
+#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call.
+#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value.
+#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value.
+#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only.
+#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only.
+#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode.
+#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer.
+#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets.
+#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets.
+#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function.
+#define pBIOCISETLOBBEH 7410
+#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function.
+
+#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only.
+
+
+/// Alignment macro. Defines the alignment size.
+#define Packet_ALIGNMENT sizeof(int)
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
+
+
+#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent
+
+/*!
+ \brief Network type structure.
+
+ This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
+*/
+typedef struct NetType
+{
+ UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
+ ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
+}NetType;
+
+
+//some definitions stolen from libpcap
+
+#ifndef BPF_MAJOR_VERSION
+
+/*!
+ \brief A BPF pseudo-assembly program.
+
+ The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
+*/
+struct bpf_program
+{
+ UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
+ struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
+};
+
+/*!
+ \brief A single BPF pseudo-instruction.
+
+ bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
+*/
+struct bpf_insn
+{
+ USHORT code; ///< Instruction type and addressing mode.
+ UCHAR jt; ///< Jump if true
+ UCHAR jf; ///< Jump if false
+ int k; ///< Generic field used for various purposes.
+};
+
+/*!
+ \brief Structure that contains a couple of statistics values on the current capture.
+
+ It is used by packet.dll to return statistics about a capture session.
+*/
+struct bpf_stat
+{
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*!
+ \brief Packet header.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+struct bpf_hdr
+{
+ struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
+ ///< It is stored in a TimeVal structure.
+ UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
+ ///< from the original packet, because it is possible (with a proper filter)
+ ///< to instruct the driver to capture only a portion of the packets.
+ UINT bh_datalen; ///< Original length of packet
+ USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
+ ///< a padding could be added between the end of this structure and the packet
+ ///< data for performance reasons. This filed can be used to retrieve the actual data
+ ///< of the packet.
+};
+
+/*!
+ \brief Dump packet header.
+
+ This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
+ It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
+ packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
+*/
+struct dump_bpf_hdr{
+ struct timeval ts; ///< Time stamp of the packet
+ UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+
+#endif
+
+#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
+#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
+#define NMAX_PACKET 65535
+
+/*!
+ \brief Addresses of a network adapter.
+
+ This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
+ an adapter.
+*/
+typedef struct npf_if_addr {
+ struct sockaddr_storage IPAddress; ///< IP address.
+ struct sockaddr_storage SubnetMask; ///< Netmask for that address.
+ struct sockaddr_storage Broadcast; ///< Broadcast address.
+}npf_if_addr;
+
+
+#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
+#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
+#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+
+
+typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+
+#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
+#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter
+#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
+#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
+#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
+
+/*!
+ \brief Contains comprehensive information about a network adapter.
+
+ This structure is filled with all the accessory information that the user can need about an adapter installed
+ on his system.
+*/
+typedef struct _ADAPTER_INFO
+{
+ struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list.
+ CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter.
+ CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter
+ UINT MacAddressLen; ///< Length of the link layer address.
+ UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address.
+ NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter.
+ INT NNetworkAddresses; ///< Number of network layer addresses of this adapter.
+ npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter.
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+}
+ADAPTER_INFO, *PADAPTER_INFO;
+
+/*!
+ \brief Describes an opened network adapter.
+
+ This structure is the most important for the functioning of packet.dll, but the great part of its fields
+ should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
+*/
+typedef struct _ADAPTER {
+ HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
+ CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
+ int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
+ ///< on the wire.
+ HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
+ ///< It can be passed to standard Win32 functions (like WaitForSingleObject
+ ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
+ ///< data. It is particularly useful in GUI applications that need to wait
+ ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
+ ///< function can be used to define the minimum amount of data in the kernel buffer
+ ///< that will cause the event to be signalled.
+
+ UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
+ ///< ReadEvent will be signaled, also if no packets were captured
+ CHAR Name[ADAPTER_NAME_LENGTH];
+ PWAN_ADAPTER pWanAdapter;
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+#ifdef HAVE_DAG_API
+ dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
+ PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
+ struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
+ unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
+ DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
+#endif // HAVE_DAG_API
+} ADAPTER, *LPADAPTER;
+
+/*!
+ \brief Structure that contains a group of packets coming from the driver.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+typedef struct _PACKET {
+ HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
+ OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
+ PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
+ ///< details about the organization of the data in this buffer
+ UINT Length; ///< Length of the buffer
+ DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
+ ///< received by the last call to PacketReceivePacket()
+ BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
+} PACKET, *LPPACKET;
+
+/*!
+ \brief Structure containing an OID request.
+
+ It is used by the PacketRequest() function to send an OID to the interface card driver.
+ It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
+ the list of the multicast groups defined on it, and so on.
+*/
+struct _PACKET_OID_DATA {
+ ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+ ///< for a complete list of valid codes.
+ ULONG Length; ///< Length of the data field
+ UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
+ ///< from the adapter.
+};
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+
+#if _DBG
+#define ODS(_x) OutputDebugString(TEXT(_x))
+#define ODSEx(_x, _y)
+#else
+#ifdef _DEBUG_TO_FILE
+/*!
+ \brief Macro to print a debug string. The behavior differs depending on the debug level
+*/
+#define ODS(_x) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, "%s", _x); \
+ fclose(f); \
+}
+/*!
+ \brief Macro to print debug data with the printf convention. The behavior differs depending on
+ the debug level
+*/
+#define ODSEx(_x, _y) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, _x, _y); \
+ fclose(f); \
+}
+
+
+
+LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
+#else
+#define ODS(_x)
+#define ODSEx(_x, _y)
+#endif
+#endif
+
+/* We load dinamically the dag library in order link it only when it's present on the system */
+#ifdef HAVE_DAG_API
+typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll
+typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll
+#endif // HAVE_DAG_API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @}
+ */
+
+// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent
+// opening of firewire adapters
+#define FIREWIRE_SUBSTR L"1394"
+
+void PacketPopulateAdaptersInfoList();
+PWCHAR SChar2WChar(PCHAR string);
+PCHAR WChar2SChar(PWCHAR string);
+BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen);
+PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName);
+BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName);
+BOOLEAN IsFireWire(TCHAR *AdapterDesc);
+
+
+//---------------------------------------------------------------------------
+// EXPORTED FUNCTIONS
+//---------------------------------------------------------------------------
+
+PCHAR PacketGetVersion();
+PCHAR PacketGetDriverVersion();
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
+INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
+BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
+LPPACKET PacketAllocatePacket(void);
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
+VOID PacketFreePacket(LPPACKET lpPacket);
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
+BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
+BOOL PacketStopDriver();
+VOID PacketCloseAdapter(LPADAPTER lpAdapter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__PACKET32
diff --git a/src/SeeDll/SeeDll.rc b/src/SeeDll/SeeDll.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/SeeDll/SeeDll.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/SeeDll/SeeDll.vcproj b/src/SeeDll/SeeDll.vcproj
new file mode 100644
index 00000000..eee9e345
--- /dev/null
+++ b/src/SeeDll/SeeDll.vcproj
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="SeeDll"
+ ProjectGUID="{B75C0F74-0FE6-4BD4-8E54-F8383C58CB69}"
+ RootNamespace="SeeDll"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_USE_32BIT_TIME_T;PCDDLL_EXPORTS"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\see.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ ModuleDefinitionFile="See_$(PlatformName).def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PCDDLL_EXPORTS;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\see_x64.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ ModuleDefinitionFile="See_$(PlatformName).def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\AdInfo.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet32.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\dagc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Devioctl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddndis.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\SeeDll.rc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\See_Win32.def"
+ >
+ </File>
+ <File
+ RelativePath=".\See_x64.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/SeeDll/See_Win32.def b/src/SeeDll/See_Win32.def
new file mode 100644
index 00000000..4c5c64f8
--- /dev/null
+++ b/src/SeeDll/See_Win32.def
@@ -0,0 +1,34 @@
+LIBRARY see
+
+EXPORTS
+ PacketLibraryVersion
+ PacketGetVersion
+ PacketGetDriverVersion
+ PacketOpenAdapter
+ PacketSendPacket
+ PacketSendPackets
+ PacketAllocatePacket
+ PacketInitPacket
+ PacketFreePacket
+ PacketReceivePacket
+ PacketCloseAdapter
+ PacketSetHwFilter
+ PacketGetAdapterNames
+ PacketRequest
+ PacketSetBuff
+ PacketSetBpf
+ PacketSetSnapLen
+ PacketGetStats
+ PacketGetStatsEx
+ PacketGetNetType
+ PacketSetReadTimeout
+ PacketSetMode
+ PacketSetNumWrites
+ PacketGetNetInfoEx
+ PacketSetMinToCopy
+ PacketGetReadEvent
+ PacketStopDriver
+ PacketSetDumpName
+ PacketSetDumpLimits
+ PacketIsDumpEnded
+ PacketSetLoopbackBehavior
diff --git a/src/SeeDll/See_x64.def b/src/SeeDll/See_x64.def
new file mode 100644
index 00000000..5f30a5fd
--- /dev/null
+++ b/src/SeeDll/See_x64.def
@@ -0,0 +1,34 @@
+LIBRARY see_x64
+
+EXPORTS
+ PacketLibraryVersion
+ PacketGetVersion
+ PacketGetDriverVersion
+ PacketOpenAdapter
+ PacketSendPacket
+ PacketSendPackets
+ PacketAllocatePacket
+ PacketInitPacket
+ PacketFreePacket
+ PacketReceivePacket
+ PacketCloseAdapter
+ PacketSetHwFilter
+ PacketGetAdapterNames
+ PacketRequest
+ PacketSetBuff
+ PacketSetBpf
+ PacketSetSnapLen
+ PacketGetStats
+ PacketGetStatsEx
+ PacketGetNetType
+ PacketSetReadTimeout
+ PacketSetMode
+ PacketSetNumWrites
+ PacketGetNetInfoEx
+ PacketSetMinToCopy
+ PacketGetReadEvent
+ PacketStopDriver
+ PacketSetDumpName
+ PacketSetDumpLimits
+ PacketIsDumpEnded
+ PacketSetLoopbackBehavior
diff --git a/src/SeeDll/dagc.h b/src/SeeDll/dagc.h
new file mode 100644
index 00000000..6162c4a3
--- /dev/null
+++ b/src/SeeDll/dagc.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define DAGC_ERRBUF_SIZE 512
+#define FILEBUFSIZE 65536
+#define MAXDAGCARDS 32
+
+#ifndef _WIN32
+
+typedef long long long_long;
+typedef long long ull_t;
+#define TRUE 1
+#define devicestring "/dev/dag%d"
+#define dagc_sleepms(_MS) usleep(_MS * 1000)
+#else /* _WIN32 */
+
+typedef LONGLONG long_long;
+typedef ULONGLONG ull_t;
+#define dagc_sleepms(_MS) Sleep(_MS)
+#define devicestring "\\\\.\\dag%d"
+
+#endif /* _WIN32 */
+
+#define MIN_DAG_SNAPLEN 12
+#define MAX_DAG_SNAPLEN 2040
+
+#define erffilestring "erffile://"
+
+
+#define ATM_SNAPLEN 48
+/* Size of ATM payload */
+#define ATM_WLEN(h) ATM_SNAPLEN
+#define ATM_SLEN(h) ATM_SNAPLEN
+
+/* Size Ethernet payload */
+#define ETHERNET_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define ETHERNET_SLEN(h, b) min(ETHERNET_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size - 2)
+
+/* Size of HDLC payload */
+#define HDLC_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define HDLC_SLEN(h, b) min(HDLC_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size)
+
+/* Flags for dagc_open */
+#define DAGC_OPEN_SHARED 1
+#define DAGC_OPEN_EXCLUSIVE 2
+
+#define TYPE_LEGACY 0
+#define TYPE_HDLC_POS 1
+#define TYPE_ETH 2
+#define TYPE_ATM 3
+#define TYPE_AAL5 4
+
+/*
+ * Card statistics.
+ */
+typedef struct dagc_stats_t
+{
+ ull_t received; /* (NOT IMPLEMENTED) total number of frames received by the DAG */
+ ull_t dropped; /* number of frames dropped for buffer full */
+ ull_t captured; /* (NOT IMPLEMENTED) number of frames that actually reach the
+ application, i.e that are not filtered or dropped */
+} dagc_stats_t;
+
+/*
+ * Descriptor of an open session.
+ * Note: the dagc_t descriptor is completely opaque to the application. It can be compared
+ * to a file descriptor.
+ */
+typedef struct dagc dagc_t;
+
+/*
+ * Card description.
+ */
+typedef struct dagc_if_t
+{
+ struct dagc_if_t *next;
+ char *name; /* pointer to a string to pass to dagc_open*/
+ char *description; /* human-understandable description (e.g. Endace 3.5e Fast
+ Ethernet Card) */
+} dagc_if_t;
+
+
+
+/*
+ * returns a string with last dagc lib error
+ */
+#define dagc_getlasterror(dagcfd) dagcfd->errbuf
+
+/*
+ * returns a linked list with the cards available on the systems. For every card, it scans the
+ * card type and converts it to a human-understandable string, in order to provide a description
+ * useful for example when a system has more than one card
+ */
+int dagc_finddevs (dagc_if_t **alldevsp, char *ebuf);
+
+
+/*
+ * frees the card list.
+ */
+void dagc_freedevs (dagc_if_t *alldevsp);
+
+
+/*
+ * Opens a card (or a file) for capture. Snaplen is the portion of packet delivered to the
+ * application, flags can contain specific settings (for example promisc mode??), minbufsize
+ * is the smallest buffer that the API can provide to the application (to limit CPU waste
+ * with several small buffers under moderated network throughputs)
+ */
+dagc_t* dagc_open(const char *source, unsigned flags, char *ebuf);
+
+/*
+ * Sets the snaplen of a card
+ * Returns -1 on failure. On success, the actual snaplen is returned (snap len has to be a multiple of 4
+ * with DAG cards).
+ */
+int dagc_setsnaplen(dagc_t *dagcfd, unsigned snaplen);
+
+/*
+ * closes a capture instance
+ */
+void dagc_close(dagc_t *dagcfd);
+
+
+/*
+ * returns the linktype of a card
+ */
+int dagc_getlinktype(dagc_t *dagcfd);
+
+
+/*
+ * returns the link speed of the adapter, in MB/s.
+ * If the link speed of the card is unknown, -1 is returned.
+ * XXX NOTE: Currently, there is no consistent way to get linkspeed querying the card.
+ * As a consequence, we determine this value statically from the card model. For cards that can run at
+ * different speeds, we report only the *maximum* speed.
+ */
+int dagc_getlinkspeed(dagc_t *dagcfd);
+
+
+/*
+ * Returns the length of the CRC checksum that the card associates with any packet in the hole. This
+ * information will be used to understand the actual length of the packet on the wire.
+ * Note: this information is not provided consistently by DAG cards, so we gather it from an environment
+ * variable in Unix and from a registry key in Windows.
+ */
+unsigned dagc_getfcslen(dagc_t *dagcfd);
+
+/*
+ * provides a buffer with the new packets (from the board or from the file) and its size.
+ * On success, the return value is 0. If an error has occurred, the return value is -1.
+ * If EOF has reached, the return value is -2. Note that this function always returns
+ * immediately, eventually with an empty buffer, so it is possible to have a success (0)
+ * return value and bufsize = 0.
+ */
+int dagc_receive(dagc_t *dagcfd, u_char **buffer, u_int *bufsize);
+
+
+/*
+ * returns nonzero if any data is available from dagcfd, -1 if an error occurred. Waits until almost the time
+ * specified by timeout has past or any data is available. If timeout=0, returns immediately.
+ * If timeout=NULL, blocks until a packet arrives.
+ */
+int dagc_wait(dagc_t *dagcfd, struct timeval *timeout);
+
+
+/*
+ * returns statistics about current capture session
+ */
+int dagc_stats(dagc_t *dagcfd, dagc_stats_t *ps);
+
+
+/*
+ * Opens a dump file to store the data of this capture.
+ * Returns 0 on success.
+ * NOTE: currently, dagc_dumpfile_open, dagc_dumpfile_close and dagc_dump are simply wrappers
+ * for open, close and write. However, if the programmer uses these functions, he is more protected
+ * against file format changes (for example if the file format will have an header in the future).
+ * Moreover, assuming that the user knows the file format is a bad practice: providing
+ * simple simple save functionality is more intutive and user-friendly.
+ */
+int dagc_dumpfile_open(dagc_t *dagcfd, char* name);
+
+
+/*
+ * Closes a dump file
+ */
+int dagc_dumpfile_close(dagc_t *dagcfd);
+
+
+/*
+ * Writes a buffer of packets to a dump file
+ * Returns 0 on success.
+ */
+int dagc_dump(dagc_t *dagcfd, u_char *buffer, u_int bufsize);
diff --git a/src/SeeDll/resource.h b/src/SeeDll/resource.h
new file mode 100644
index 00000000..6e86a4b6
--- /dev/null
+++ b/src/SeeDll/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SeeDll.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/VGate/VGate.c b/src/VGate/VGate.c
new file mode 100644
index 00000000..ba7c7aa8
--- /dev/null
+++ b/src/VGate/VGate.c
@@ -0,0 +1,109 @@
+// VPN Gate Source Code
+//
+// Copyright (c) VPN Gate Academic Project, University of Tsukuba.
+// All Rights Reserved.
+//
+// http://www.vpngate.net/
+//
+// VGate.c
+// Main source
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include <VGate/VGateCommon.h>
+#include <VGate/VGate.h>
+
+
+
+// DLL initialization
+struct VGATE_FUNCTIONS *LoadPluginDll()
+{
+ return NULL;
+}
+
+// Release the DLL
+void FreePluginDll(struct VGATE_FUNCTIONS *funcs)
+{
+}
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/VGate/VGate.h b/src/VGate/VGate.h
new file mode 100644
index 00000000..195e8f8a
--- /dev/null
+++ b/src/VGate/VGate.h
@@ -0,0 +1,89 @@
+// VPN Gate Source Code
+//
+// Copyright (c) VPN Gate Academic Project, University of Tsukuba.
+// All Rights Reserved.
+//
+// http://www.vpngate.net/
+//
+// VGate.h
+// Main header
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#ifndef VGATE_H
+#define VGATE_H
+
+
+#endif // VGATE_H
+
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/VGate/VGate.rc b/src/VGate/VGate.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/VGate/VGate.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/VGate/VGate.vcproj b/src/VGate/VGate.vcproj
new file mode 100644
index 00000000..ccaf4161
--- /dev/null
+++ b/src/VGate/VGate.vcproj
@@ -0,0 +1,472 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="VGate"
+ ProjectGUID="{DB2A0C4F-D685-41DD-91BA-06E9EEA381CF}"
+ RootNamespace="VGate"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_USE_32BIT_TIME_T;PCDDLL_EXPORTS"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ OmitDefaultLibName="false"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot; /RC:ver_vg.rc"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\VpnGatePlugin_x86.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ ModuleDefinitionFile="VGate_$(PlatformName).def"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PCDDLL_EXPORTS;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot; /RC:ver_vg.rc"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\VpnGatePlugin_x64.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ ModuleDefinitionFile="VGate_$(PlatformName).def"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_USE_32BIT_TIME_T;PCDDLL_EXPORTS"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot; /RC:ver_vg.rc"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\VpnGatePlugin_x86.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ ModuleDefinitionFile="VGate_$(PlatformName).def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="0"
+ EnableCOMDATFolding="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PCDDLL_EXPORTS;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot; /RC:ver_vg.rc"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="Version.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\VpnGatePlugin_x64.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ ModuleDefinitionFile="VGate_$(PlatformName).def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="0"
+ EnableCOMDATFolding="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\VGate.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VGate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VGateCommon.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\VGate.rc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\VGate_Win32.def"
+ >
+ </File>
+ <File
+ RelativePath=".\VGate_x64.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/VGate/VGateCommon.h b/src/VGate/VGateCommon.h
new file mode 100644
index 00000000..19dce4d3
--- /dev/null
+++ b/src/VGate/VGateCommon.h
@@ -0,0 +1,8 @@
+#ifndef VGATECOMMON_H
+#define VGATECOMMON_H
+
+
+
+#endif // VGATECOMMON_H
+
+
diff --git a/src/VGate/VGate_Win32.def b/src/VGate/VGate_Win32.def
new file mode 100644
index 00000000..b75f28ab
--- /dev/null
+++ b/src/VGate/VGate_Win32.def
@@ -0,0 +1,7 @@
+LIBRARY VpnGatePlugin_x86
+
+EXPORTS
+ LoadPluginDll
+ FreePluginDll
+
+
diff --git a/src/VGate/VGate_x64.def b/src/VGate/VGate_x64.def
new file mode 100644
index 00000000..88607b28
--- /dev/null
+++ b/src/VGate/VGate_x64.def
@@ -0,0 +1,5 @@
+LIBRARY VpnGatePlugin_x64
+
+EXPORTS
+ LoadPluginDll
+ FreePluginDll
diff --git a/src/VGate/resource.h b/src/VGate/resource.h
new file mode 100644
index 00000000..8adbac7c
--- /dev/null
+++ b/src/VGate/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// MicrosoftVisual C++ generated include file.
+// Used by VGate.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Wfp/Wfp.c b/src/Wfp/Wfp.c
new file mode 100644
index 00000000..5ef8c1d3
--- /dev/null
+++ b/src/Wfp/Wfp.c
@@ -0,0 +1,1282 @@
+// SoftEther VPN Source Code
+// Windows Filtering Platform Callout Driver for Capturing IPsec Packets on Windows Vista / 7 / Server 2008
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Wfp.c
+// WFP Callout Driver
+
+#include <GlobalConst.h>
+
+#define WFP_DEVICE_DRIVER
+
+#include "WfpInner.h"
+#include "Wfp.h"
+
+static WFP_CTX *wfp = NULL;
+
+// Dispatch function
+NTSTATUS DriverDispatch(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ NTSTATUS ret = STATUS_SUCCESS;
+ IO_STACK_LOCATION *stack;
+ void *buf;
+ bool ok;
+ // Validate arguments
+ if (wfp == NULL || device_object == NULL || irp == NULL || wfp->Halting)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Get the IRP stack
+ stack = IoGetCurrentIrpStackLocation(irp);
+
+ // Initialize the number of bytes
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_SUCCESS;
+
+ buf = irp->UserBuffer;
+
+ if (wfp->Halting != FALSE)
+ {
+ // Device driver is terminating
+ irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ok = false;
+
+ // Branch to each operation
+ switch (stack->MajorFunction)
+ {
+ case IRP_MJ_CREATE: // Open
+ ok = true;
+ break;
+
+ case IRP_MJ_CLOSE: // Close
+ ok = true;
+ break;
+
+ case IRP_MJ_READ: // Read
+ ResetEvent(wfp->Event);
+ break;
+
+ case IRP_MJ_WRITE: // Write
+ if ((stack->Parameters.Write.Length % sizeof(WFP_LOCAL_IP)) == 0)
+ {
+ UINT size = MIN(WFP_MAX_LOCAL_IP_COUNT * sizeof(WFP_LOCAL_IP), stack->Parameters.Write.Length);
+ UCHAR *copied_buf = Malloc(size);
+ UCHAR *old_buf;
+ Copy(copied_buf, buf, size);
+
+ SpinLock(wfp->LocalIPListLock);
+ {
+ old_buf = wfp->LocalIPListData;
+ wfp->LocalIPListData = copied_buf;
+ wfp->LocalIPListSize = size;
+ }
+ SpinUnlock(wfp->LocalIPListLock);
+
+ if (old_buf != NULL)
+ {
+ Free(old_buf);
+ }
+ }
+ irp->IoStatus.Information = stack->Parameters.Write.Length;
+ ok = true;
+ break;
+ }
+
+ if (ok == false)
+ {
+ irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ ret = STATUS_UNSUCCESSFUL;
+ }
+
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Function to finish the insertion of the packet
+void NTAPI CalloutInjectionCompleted(void *context, NET_BUFFER_LIST *net_buffer_list, BOOLEAN dispatch_level)
+{
+ WFP_INJECTED_PACKET_CONTEXT *ctx = (WFP_INJECTED_PACKET_CONTEXT *)context;
+
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ FreeInjectionCtx(ctx);
+}
+
+// Release the injection data
+void FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT *ctx)
+{
+ // Validate arguments
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ if (ctx->CurrentNetBuffer != NULL)
+ {
+ Copy(ctx->CurrentNetBuffer, &ctx->OriginalNetBufferData, sizeof(NET_BUFFER));
+ }
+
+ if (ctx->AllocatedNetBufferList != NULL)
+ {
+ FwpsFreeCloneNetBufferList0(ctx->AllocatedNetBufferList, 0);
+ }
+
+ if (ctx->AllocatedMdl != NULL)
+ {
+ NdisFreeMdl(ctx->AllocatedMdl);
+ }
+
+ if (ctx->AllocatedMemory != NULL)
+ {
+ Free(ctx->AllocatedMemory);
+ }
+
+ Free(ctx);
+}
+
+// Calculate the checksum
+USHORT IpChecksum(void *buf, UINT size)
+{
+ int sum = 0;
+ USHORT *addr = (USHORT *)buf;
+ int len = (int)size;
+ USHORT *w = addr;
+ int nleft = len;
+ USHORT answer = 0;
+
+ while (nleft > 1)
+ {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *(UCHAR *)(&answer) = *(UCHAR *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ answer = ~sum;
+
+ return answer;
+}
+
+// Modify the IPsec ESP packet
+UCHAR *ModificationOfIPsecESPPacket(UCHAR *ip_packet, UINT ip_packet_size, UINT ip_header_size, UINT *dst_size_ptr, bool isv6)
+{
+ UINT ip_and_udp_header_size = ip_header_size + sizeof(WFP_UDP_HEADER);
+ UINT udp_packet_size;
+ UINT udp_payload_size;
+ UINT dst_udp_payload_size;
+ WFP_UDP_HEADER *src_udp;
+ WFP_UDP_HEADER *dst_udp;
+ UCHAR *src_udp_payload;
+ UCHAR *dst_data;
+ UINT dst_size;
+ // Validate arguments
+ if (ip_packet == NULL || ip_packet == 0 || ip_header_size == 0 || dst_size_ptr == NULL)
+ {
+ return NULL;
+ }
+
+ if (ip_packet_size <= ip_and_udp_header_size)
+ {
+ // There is no UDP header
+ return NULL;
+ }
+
+ // Get the UDP header
+ src_udp = (WFP_UDP_HEADER *)(ip_packet + ip_header_size);
+ udp_packet_size = Endian16(src_udp->PacketLength);
+ if (udp_packet_size < sizeof(WFP_UDP_HEADER))
+ {
+ // There is no UDP payload
+ return NULL;
+ }
+
+ // Get the UDP payload size
+ udp_payload_size = udp_packet_size - sizeof(WFP_UDP_HEADER);
+
+ if (ip_packet_size < (ip_and_udp_header_size + udp_payload_size))
+ {
+ // There is no UDP payload
+ return NULL;
+ }
+
+ // Get the UDP payload
+ src_udp_payload = ip_packet + ip_and_udp_header_size;
+
+ if (udp_payload_size < sizeof(UINT))
+ {
+ // The size of the UDP payload is less than 5 bytes
+ return NULL;
+ }
+
+ dst_udp_payload_size = udp_payload_size + sizeof(UINT) * 3;
+ if ((dst_udp_payload_size + sizeof(WFP_UDP_HEADER)) > 0xffff)
+ {
+ // UDP payload size overflows the 16bit
+ return NULL;
+ }
+
+ // Build a new packet
+ dst_size = ip_and_udp_header_size + sizeof(UINT) * 3 + udp_payload_size;
+ if (dst_size > 0xffff)
+ {
+ // IP total size overflows the 16bit
+ return NULL;
+ }
+
+ dst_data = Malloc(dst_size);
+ if (dst_data == NULL)
+ {
+ // Memory allocation failure
+ return NULL;
+ }
+
+ // Copy the IP header + UDP header
+ Copy(dst_data, ip_packet, ip_and_udp_header_size);
+
+ // Copy the original payload
+ Copy(dst_data + ip_and_udp_header_size + sizeof(UINT) * 3, src_udp_payload, udp_payload_size);
+
+ // Insert a tag
+ *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 0)) = 0;
+ *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 1)) = WFP_ESP_PACKET_TAG_1;
+ *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 2)) = WFP_ESP_PACKET_TAG_2;
+
+ // Adjust the new IP header
+ if (isv6 == false)
+ {
+ WFP_IPV4_HEADER *ip = (WFP_IPV4_HEADER *)dst_data;
+
+ ip->TotalLength = Endian16(dst_size);
+ ip->Checksum = 0;
+ ip->Checksum = IpChecksum(ip, ip_header_size);
+ }
+ else
+ {
+ WFP_IPV6_HEADER *ip = (WFP_IPV6_HEADER *)dst_data;
+
+ ip->PayloadLength = Endian16(dst_size);
+ }
+
+ // Adjust the new UDP header
+ dst_udp = (WFP_UDP_HEADER *)(dst_data + ip_header_size);
+ dst_udp->Checksum = 0;
+ dst_udp->PacketLength = Endian16((USHORT)(dst_udp_payload_size + sizeof(WFP_UDP_HEADER)));
+
+ *dst_size_ptr = dst_size;
+ return dst_data;
+}
+
+// Insert the packet into the stack
+bool InjectPacket(HANDLE hInjection, NET_BUFFER_LIST *nbl, UCHAR *dst_data, UINT dst_size, const FWPS_INCOMING_VALUES0* inFixedValues, const FWPS_INCOMING_METADATA_VALUES0* inMetaValues)
+{
+ WFP_INJECTED_PACKET_CONTEXT *ctx;
+ bool block = false;
+ // Validate arguments
+ if (hInjection == NULL || nbl == NULL || dst_data == NULL || dst_size == 0 || inMetaValues == NULL || inFixedValues == NULL)
+ {
+ return false;
+ }
+
+ ctx = ZeroMalloc(sizeof(WFP_INJECTED_PACKET_CONTEXT));
+
+ if (ctx != NULL)
+ {
+ // Generate a modified packet
+ ctx->AllocatedMemory = dst_data;
+
+ if (dst_data != NULL)
+ {
+ NET_BUFFER_LIST *net_buffer_list;
+ NTSTATUS ret;
+
+ // Clone the original NET_BUFFER_LIST
+ ret = FwpsAllocateCloneNetBufferList0(nbl, NULL, NULL, 0, &net_buffer_list);
+
+ if (OK(ret) && net_buffer_list != NULL)
+ {
+ NET_BUFFER *net_buffer = NET_BUFFER_LIST_FIRST_NB(net_buffer_list);
+
+ ctx->AllocatedNetBufferList = net_buffer_list;
+ ctx->CurrentNetBuffer = net_buffer;
+
+ if (net_buffer != NULL)
+ {
+ MDL *mdl = NdisAllocateMdl(wfp->hNdis, dst_data, dst_size);
+ if (mdl != NULL)
+ {
+ NTSTATUS ret;
+
+ ctx->AllocatedMdl = mdl;
+
+ Copy(&ctx->OriginalNetBufferData, net_buffer, sizeof(NET_BUFFER));
+
+ NET_BUFFER_FIRST_MDL(net_buffer) = mdl;
+ NET_BUFFER_DATA_LENGTH(net_buffer) = dst_size;
+ NET_BUFFER_DATA_OFFSET(net_buffer) = 0;
+ NET_BUFFER_CURRENT_MDL(net_buffer) = mdl;
+ NET_BUFFER_CURRENT_MDL_OFFSET(net_buffer) = 0;
+
+ // Insert packets of receiving direction
+ ret = FwpsInjectNetworkReceiveAsync0(hInjection, NULL,
+ 0,
+ (inMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_COMPARTMENT_ID ? inMetaValues->compartmentId : UNSPECIFIED_COMPARTMENT_ID),
+ inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_INTERFACE_INDEX].value.uint32,
+ inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_SUB_INTERFACE_INDEX].value.uint32,
+ net_buffer_list,
+ CalloutInjectionCompleted,
+ (HANDLE)ctx);
+
+ if (NG(ret))
+ {
+ //CRUSH_WHERE;
+ }
+ else
+ {
+ block = true;
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+
+ if (block == false)
+ {
+ FreeInjectionCtx(ctx);
+ }
+ }
+
+ return block;
+}
+
+// Function to be notified of arriving packet
+void NTAPI CalloutClassify(const FWPS_INCOMING_VALUES0* inFixedValues,
+ const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
+ void* layerData,
+ const FWPS_FILTER0* filter,
+ UINT64 flowContext,
+ FWPS_CLASSIFY_OUT0* classifyOut)
+{
+ NET_BUFFER_LIST *nbl = layerData;
+ FWPS_PACKET_INJECTION_STATE injecton_state;
+ bool block = false;
+ HANDLE hInjection = NULL;
+ UINT ip_header_len = 0;
+ bool isv6 = false;
+
+ if (wfp->Halting || nbl == NULL)
+ {
+ classifyOut->actionType = FWP_ACTION_CONTINUE;
+ return;
+ }
+
+ switch (inFixedValues->layerId)
+ {
+ case FWPS_LAYER_INBOUND_IPPACKET_V4:
+ hInjection = wfp->hInjectionIPv4;
+ ip_header_len = sizeof(WFP_IPV4_HEADER);
+ break;
+
+ case FWPS_LAYER_INBOUND_IPPACKET_V6:
+ hInjection = wfp->hInjectionIPv6;
+ ip_header_len = sizeof(WFP_IPV6_HEADER);
+ isv6 = true;
+ break;
+ }
+
+ if (hInjection != NULL)
+ {
+ injecton_state = FwpsQueryPacketInjectionState0(hInjection, nbl, NULL);
+
+ if (injecton_state == FWPS_PACKET_INJECTED_BY_SELF || injecton_state == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
+ {
+ //SetEvent(wfp->Event);
+ classifyOut->actionType = FWP_ACTION_CONTINUE; // continue
+ return;
+ }
+
+ if (nbl != NULL && NET_BUFFER_LIST_NEXT_NBL(nbl) == NULL)
+ {
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ if (nb != NULL && NET_BUFFER_NEXT_NB(nb) == NULL)
+ {
+ if (OK(NdisRetreatNetBufferDataStart(nb, inMetaValues->ipHeaderSize, 0, NULL)))
+ {
+ WFP_IPV4_HEADER *ipv4;
+ WFP_IPV6_HEADER *ipv6;
+ UCHAR *alloc_buf = Malloc(ip_header_len);
+
+ ipv4 = NdisGetDataBuffer(nb, ip_header_len, alloc_buf, 1, 0);
+ ipv6 = (WFP_IPV6_HEADER *)ipv4;
+
+ if (ipv4 != NULL)
+ {
+ if ((isv6 == false && ipv4->Protocol == WFP_ESP_RAW_PROTOCOL_ID))
+ {
+ if (IsIPv4AddressInList(&ipv4->DstIP))
+ {
+ UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
+ UCHAR *src_data = Malloc(src_size);
+
+ if (src_data != NULL)
+ {
+ UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
+
+ if (src_ptr != NULL)
+ {
+ UINT dst_size = src_size;
+ UCHAR *dst_data = Malloc(dst_size);
+
+ if (dst_data != NULL)
+ {
+ WFP_IPV4_HEADER *ipv4;
+
+ Copy(dst_data, src_ptr, dst_size);
+ ipv4 = (WFP_IPV4_HEADER *)dst_data;
+
+ ipv4->Protocol = WFP_ESP_RAW_PROTOCOL_ID_DST;
+ ipv4->Checksum = 0;
+ ipv4->Checksum = IpChecksum(ipv4, inMetaValues->ipHeaderSize);
+
+ block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
+ }
+ }
+
+ Free(src_data);
+ }
+ }
+ }
+ else if ((isv6 && ipv6->NextHeader == WFP_ESP_RAW_PROTOCOL_ID))
+ {
+ if (IsIPv6AddressInList(&ipv6->DestAddress))
+ {
+ UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
+ UCHAR *src_data = Malloc(src_size);
+
+ if (src_data != NULL)
+ {
+ UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
+
+ if (src_ptr != NULL)
+ {
+ UINT dst_size = src_size;
+ UCHAR *dst_data = Malloc(dst_size);
+
+ if (dst_data != NULL)
+ {
+ WFP_IPV6_HEADER *ipv6;
+
+ Copy(dst_data, src_ptr, dst_size);
+ ipv6 = (WFP_IPV6_HEADER *)dst_data;
+
+ ipv6->NextHeader = WFP_ESP_RAW_PROTOCOL_ID_DST;
+
+ block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
+ }
+ }
+
+ Free(src_data);
+ }
+ }
+ }
+
+ if ((isv6 == false && ipv4->Protocol == WFP_IP_PROTO_UDP) ||
+ (isv6 && ipv6->NextHeader == WFP_IP_PROTO_UDP))
+ {
+ UINT ip_and_udp_header_len = inMetaValues->ipHeaderSize + sizeof(WFP_UDP_HEADER);
+ UCHAR *ptr;
+ UCHAR *alloc_buf = Malloc(ip_and_udp_header_len);
+
+ ptr = NdisGetDataBuffer(nb, ip_and_udp_header_len, alloc_buf, 1, 0);
+ if (ptr != NULL)
+ {
+ WFP_UDP_HEADER *udp = (WFP_UDP_HEADER *)(ptr + inMetaValues->ipHeaderSize);
+
+ if (Endian16(udp->DstPort) == 4500)
+ {
+ if ((isv6 == false && IsIPv4AddressInList(&ipv4->DstIP)) ||
+ (isv6 && IsIPv6AddressInList(&ipv6->DestAddress)))
+ {
+ UINT packet_size = NET_BUFFER_DATA_LENGTH(nb);
+ UCHAR *packet_buf_allocated = Malloc(packet_size);
+ UCHAR *packet_data = NdisGetDataBuffer(nb, packet_size, packet_buf_allocated, 1, 0);
+
+ if (packet_data != NULL)
+ {
+ UCHAR *udp_payload = packet_data + ip_and_udp_header_len;
+ UINT udp_payload_size = packet_size - ip_and_udp_header_len;
+
+ if (udp_payload_size >= 4)
+ {
+ UINT *i = (UINT *)udp_payload;
+ if (*i != 0)
+ {
+ // Generate a modified packet
+ UINT dst_size;
+ UCHAR *dst_data = ModificationOfIPsecESPPacket(packet_data, packet_size,
+ inMetaValues->ipHeaderSize, &dst_size, isv6);
+
+ block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
+ }
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+
+ Free(packet_buf_allocated);
+ }
+ }
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+
+ Free(alloc_buf);
+ }
+ }
+
+ Free(alloc_buf);
+
+ NdisAdvanceNetBufferDataStart(nb, inMetaValues->ipHeaderSize, false, NULL);
+ }
+ else
+ {
+ //CRUSH_WHERE;
+ }
+
+ nb = NET_BUFFER_NEXT_NB(nb);
+ }
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ }
+ }
+
+ classifyOut->actionType = FWP_ACTION_CONTINUE;
+
+ if (block)
+ {
+ // Block the packet
+ classifyOut->actionType = FWP_ACTION_BLOCK;
+ classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
+ classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
+ //SetEvent(wfp->Event);
+ }
+}
+
+// Function to receive notification from the WFP
+NTSTATUS NTAPI CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,
+ const GUID* filterKey, FWPS_FILTER0* filter)
+{
+ //Crush(1,0,0,0);
+ return 0;
+}
+
+// Scan whether the specified IP address is in the local IP address list
+bool IsIPAddressInList(struct WFP_LOCAL_IP *ip)
+{
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ SpinLock(wfp->LocalIPListLock);
+ {
+ if (wfp->LocalIPListData != NULL)
+ {
+ UINT num = wfp->LocalIPListSize / sizeof(WFP_LOCAL_IP);
+ WFP_LOCAL_IP *o = (WFP_LOCAL_IP *)wfp->LocalIPListData;
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ if (Cmp(&o[i], ip, sizeof(WFP_LOCAL_IP)) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+ SpinUnlock(wfp->LocalIPListLock);
+
+ return ret;
+}
+bool IsIPv4AddressInList(void *addr)
+{
+ WFP_LOCAL_IP ip;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip, sizeof(ip));
+ ip.IpVersion = 4;
+ Copy(ip.IpAddress.IPv4Address, addr, 4);
+
+ return IsIPAddressInList(&ip);
+}
+bool IsIPv6AddressInList(void *addr)
+{
+ WFP_LOCAL_IP ip;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip, sizeof(ip));
+ ip.IpVersion = 6;
+ Copy(ip.IpAddress.IPv6Address, addr, 16);
+
+ return IsIPAddressInList(&ip);
+}
+
+// Win32 driver entry point
+NTSTATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path)
+{
+ NTSTATUS ret;
+ FWPM_SESSION0 t;
+
+ if (wfp != NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ wfp = ZeroMalloc(sizeof(WFP_CTX));
+
+ RtlInitUnicodeString(&wfp->DeviceName, WFP_DEVICE_NAME);
+ RtlInitUnicodeString(&wfp->DeviceNameWin32, WFP_DEVICE_NAME_WIN32);
+ // Create a device
+ ret = IoCreateDevice(driver_object, 0, &wfp->DeviceName, FILE_DEVICE_NETWORK, 0, false, &wfp->DeviceObject);
+ if (NG(ret))
+ {
+ return ret;
+ }
+
+ // Open the NDIS handle
+ wfp->hNdis = NdisAllocateGenericObject(driver_object, MEMPOOL_TAG, 0);
+ if (wfp->hNdis == NULL)
+ {
+ DriverUnload(driver_object);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Create a symbolic device for Win32
+ ret = IoCreateSymbolicLink(&wfp->DeviceNameWin32, &wfp->DeviceName);
+ if (NG(ret))
+ {
+ DriverUnload(driver_object);
+ return ret;
+ }
+
+ driver_object->DriverUnload = DriverUnload;
+
+ // Create an Event
+ wfp->Event = NewEvent(WFP_EVENT_NAME);
+ if (wfp->Event == NULL)
+ {
+ DriverUnload(driver_object);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Open the WFP engine
+ Zero(&t, sizeof(t));
+ t.flags = FWPM_SESSION_FLAG_DYNAMIC;
+ ret = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &t, &wfp->hEngine);
+ if (NG(ret))
+ {
+ DriverUnload(driver_object);
+ return ret;
+ }
+ else
+ {
+ // Register itself as a Callout Driver
+ FWPS_CALLOUT0 s;
+// FWPM_CALLOUT0 callout;
+
+ Zero(&s, sizeof(s));
+ s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
+ s.classifyFn = CalloutClassify;
+ s.notifyFn = CalloutNotify;
+
+ ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv4);
+ if (NG(ret))
+ {
+ DriverUnload(driver_object);
+ return ret;
+ }
+
+ Zero(&s, sizeof(s));
+ s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
+ s.classifyFn = CalloutClassify;
+ s.notifyFn = CalloutNotify;
+
+ ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv6);
+ if (NG(ret))
+ {
+ DriverUnload(driver_object);
+ return ret;
+ }
+
+ /*// Create the Callout Driver (IPv4)
+ Zero(&callout, sizeof(callout));
+ callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
+ callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V4;
+ callout.displayData.name = WFP_DRIVER_TITLE_V4;
+ ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv4);
+
+ // Create the Callout Driver (IPv6)
+ Zero(&callout, sizeof(callout));
+ callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
+ callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V6;
+ callout.displayData.name = WFP_DRIVER_TITLE_V6;
+ ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv6);*/
+
+ // Create an injection handle
+ FwpsInjectionHandleCreate0(AF_INET, FWPS_INJECTION_TYPE_NETWORK, &wfp->hInjectionIPv4);
+ if (NG(ret))
+ {
+ wfp->hInjectionIPv4 = NULL;
+ }
+ ret = FwpsInjectionHandleCreate0(AF_INET6, FWPS_INJECTION_TYPE_NETWORK,&wfp->hInjectionIPv6);
+ if (NG(ret))
+ {
+ wfp->hInjectionIPv6 = NULL;
+ }
+ }
+
+ // Create a lock
+ wfp->LocalIPListLock = NewSpinLock();
+
+ // Specify a service function
+ driver_object->MajorFunction[IRP_MJ_CREATE] =
+ driver_object->MajorFunction[IRP_MJ_CLOSE] =
+ driver_object->MajorFunction[IRP_MJ_READ] =
+ driver_object->MajorFunction[IRP_MJ_WRITE] = DriverDispatch;
+
+ return STATUS_SUCCESS;
+}
+
+// Unload the driver
+void DriverUnload(DRIVER_OBJECT *driver_object)
+{
+ // Validate arguments
+ if (wfp == NULL || driver_object == NULL)
+ {
+ return;
+ }
+
+ wfp->Halting = true;
+
+ // Delete the lock
+ FreeSpinLock(wfp->LocalIPListLock);
+
+ // Delete the injection handle
+ if (wfp->hInjectionIPv4 != NULL)
+ {
+ FwpsInjectionHandleDestroy0(wfp->hInjectionIPv4);
+ }
+ if (wfp->hInjectionIPv6 != NULL)
+ {
+ FwpsInjectionHandleDestroy0(wfp->hInjectionIPv6);
+ }
+
+ // Delete the Callout Object
+ if (wfp->hEngine != NULL)
+ {
+ //FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V4);
+ //FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V6);
+ }
+
+ if (wfp->CalloutIdIPv4 != 0)
+ {
+ // Delete the registration of Callout Driver (IPv4)
+ FwpsCalloutUnregisterById0(wfp->CalloutIdIPv4);
+ }
+
+ if (wfp->CalloutIdIPv6 != 0)
+ {
+ // Delete the registration of Callout Driver (IPv6)
+ FwpsCalloutUnregisterById0(wfp->CalloutIdIPv6);
+ }
+
+ FreeEvent(wfp->Event);
+
+ IoDeleteSymbolicLink(&wfp->DeviceNameWin32);
+
+ if (wfp->DeviceObject != NULL)
+ {
+ IoDeleteDevice(wfp->DeviceObject);
+ }
+
+ if (wfp->hEngine != NULL)
+ {
+ FwpmEngineClose0(wfp->hEngine);
+ }
+
+ if (wfp->LocalIPListData != NULL)
+ {
+ Free(wfp->LocalIPListData);
+ }
+
+ // Close the NDIS handle
+ if (wfp->hNdis != NULL)
+ {
+ NdisFreeGenericObject(wfp->hNdis);
+ }
+
+ Free(wfp);
+
+ wfp = NULL;
+}
+
+// Create an Event
+EVENT *NewEvent(wchar_t *name)
+{
+ EVENT *e;
+ KEVENT *ke;
+ HANDLE h;
+ UNICODE_STRING name_str;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ RtlInitUnicodeString(&name_str, name);
+
+ ke = IoCreateNotificationEvent(&name_str, &h);
+ if (ke == NULL)
+ {
+ return NULL;
+ }
+
+ KeInitializeEvent(ke, NotificationEvent, false);
+ KeClearEvent(ke);
+
+ e = ZeroMalloc(sizeof(EVENT));
+
+ e->EventObj = ke;
+ e->Handle = h;
+
+ return e;
+}
+
+// Delete the event
+void FreeEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ ZwClose(e->Handle);
+
+ Free(e);
+}
+
+// Set the event
+void SetEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ KeSetEvent(e->EventObj, 0, false);
+}
+
+// Reset the event
+void ResetEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ KeResetEvent(e->EventObj);
+}
+
+// Allocate the memory
+void *Malloc(UINT size)
+{
+ void *p;
+
+ p = ExAllocatePoolWithTag(NonPagedPool, size + sizeof(UINT), MEMPOOL_TAG);
+ *((UINT *)p) = size;
+
+ return ((UCHAR *)p) + sizeof(UINT);
+}
+void *ZeroMalloc(UINT size)
+{
+ void *p = Malloc(size);
+ Zero(p, size);
+ return p;
+}
+
+// Change the memory block size
+void *ReAlloc(void *p, UINT size)
+{
+ void *ret;
+ UINT oldsize;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = Malloc(size);
+ if (ret == NULL)
+ {
+ Free(p);
+ return NULL;
+ }
+
+ oldsize = GetMemSize(p);
+
+ Copy(ret, p, MIN(size, oldsize));
+
+ Free(p);
+
+ return ret;
+}
+
+// Copy memory
+void Copy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0)
+ {
+ return;
+ }
+
+ memcpy(dst, src, size);
+}
+
+// Get the memory block size
+UINT GetMemSize(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return *(UINT *)(((UCHAR *)p) - sizeof(UINT));
+}
+
+// Release the memory
+void Free(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p = ((UCHAR *)p) - sizeof(UINT);
+
+ ExFreePoolWithTag(p, MEMPOOL_TAG);
+}
+
+// Clear the memory to zero
+void Zero(void *p, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || size == 0)
+ {
+ return;
+ }
+
+ memset(p, 0, size);
+}
+
+// Comparison of memory
+UINT Cmp(void *p1, void *p2, UINT size)
+{
+ UCHAR *c1 = (UCHAR *)p1;
+ UCHAR *c2 = (UCHAR *)p2;
+ UINT i;
+
+ for (i = 0;i < size;i++)
+ {
+ if (c1[i] != c2[i])
+ {
+ if (c1[i] > c2[i])
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Create a spin lock
+SPINLOCK *NewSpinLock()
+{
+ SPINLOCK *s = ZeroMalloc(sizeof(SPINLOCK));
+
+ KeInitializeSpinLock(&s->SpinLock);
+
+ return s;
+}
+
+// Lock
+void SpinLock(SPINLOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ KeAcquireSpinLock(&s->SpinLock, &s->OldIrql);
+}
+
+// Unlock
+void SpinUnlock(SPINLOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ KeReleaseSpinLock(&s->SpinLock, s->OldIrql);
+}
+
+// Release the spin lock
+void FreeSpinLock(SPINLOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Free(s);
+}
+
+// Sleep
+void Sleep(int milliSeconds)
+{
+ PKTIMER timer = ZeroMalloc(sizeof(KTIMER));
+ LARGE_INTEGER duetime;
+
+ duetime.QuadPart = (__int64)milliSeconds * -10000;
+ KeInitializeTimerEx(timer, NotificationTimer);
+ KeSetTimerEx(timer, duetime, 0, NULL);
+
+ KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL);
+
+ Free(timer);
+}
+
+// 16-bit swap
+USHORT Swap16(USHORT value)
+{
+ USHORT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 32-bit swap
+UINT Swap32(UINT value)
+{
+ UINT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 64-bit swap
+UINT64 Swap64(UINT64 value)
+{
+ UINT64 r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[7];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[6];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[5];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[4];
+ ((BYTE *)&r)[4] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[5] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[6] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[7] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// Endian conversion 16bit
+USHORT Endian16(USHORT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap16(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 32bit
+UINT Endian32(UINT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap32(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 64bit
+UINT64 Endian64(UINT64 src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap64(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Crash
+void Crush(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Wfp/Wfp.h b/src/Wfp/Wfp.h
new file mode 100644
index 00000000..1178433a
--- /dev/null
+++ b/src/Wfp/Wfp.h
@@ -0,0 +1,126 @@
+// SoftEther VPN Source Code
+// Windows Filtering Platform Callout Driver for Capturing IPsec Packets on Windows Vista / 7 / Server 2008
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Wfp.h
+// Header File for WFP Callout Driver
+
+#ifndef WFP_H
+#define WFP_H
+
+// Identify string
+#define WFP_DEVICE_NAME L"\\Device\\PXWFP_DEVICE"
+#define WFP_DEVICE_NAME_WIN32 L"\\DosDevices\\PXWFP_DEVICE"
+#define WFP_DEVICE_FILE_NAME "\\\\.\\PXWFP_DEVICE"
+#define WFP_EVENT_NAME L"\\BaseNamedObjects\\PXWFP_EVENT"
+#define WFP_EVENT_NAME_WIN32 "Global\\PXWFP_EVENT"
+
+// PXWFP Callout Driver
+// {4E6F16C5-C266-440a-9382-22E7B1AA4411}
+DEFINE_GUID(GUID_WFP_CALLOUT_DRIVER_V4,
+ 0x4e6f16c5, 0xc266, 0x440a, 0x93, 0x82, 0x22, 0xe7, 0xb1, 0xaa, 0x44, 0x11);
+// {CAE3EC1F-E2F9-4b07-B910-1467E223E55E}
+DEFINE_GUID(GUID_WFP_CALLOUT_DRIVER_V6,
+ 0xcae3ec1f, 0xe2f9, 0x4b07, 0xb9, 0x10, 0x14, 0x67, 0xe2, 0x23, 0xe5, 0x5e);
+
+// PXWFP Filter for IPsec
+// {4FB80D9C-B3D3-433c-B707-9D6EDE3A9493}
+//DEFINE_GUID(GUID_WFP_FILTER,
+// 0x4fb80d9c, 0xb3d3, 0x433c, 0xb7, 0x7, 0x9d, 0x6e, 0xde, 0x3a, 0x94, 0x94);
+
+// WFP local IP address
+typedef struct WFP_LOCAL_IP
+{
+ UINT IpVersion;
+ UINT Padding;
+ union
+ {
+ UCHAR IPv4Address[4];
+ UCHAR IPv6Address[16];
+ } IpAddress;
+} WFP_LOCAL_IP;
+
+
+#endif // WFP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Wfp/Wfp.rc b/src/Wfp/Wfp.rc
new file mode 100644
index 00000000..5c275264
--- /dev/null
+++ b/src/Wfp/Wfp.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource1.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource1.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/Wfp/Wfp.vcproj b/src/Wfp/Wfp.vcproj
new file mode 100644
index 00000000..0f325a5f
--- /dev/null
+++ b/src/Wfp/Wfp.vcproj
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Wfp"
+ ProjectGUID="{717B8D7F-9C93-4713-9A23-8CE70A31FD39}"
+ RootNamespace="Wfp"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;WFP_EXPORTS;VPN_SPEED"
+ GeneratePreprocessedFile="0"
+ KeepComments="false"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/driver /subsystem:native,6.00 /FULLBUILD /align:0x80 /osversion:6.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\wlh\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\pxwfp_x86.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wlh\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;WFP_EXPORTS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="1"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:6.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\wlh\stub512.com"
+ AdditionalDependencies="wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\pxwfp_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wlh\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Wfp.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Wfp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WfpInner.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Wfp.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Wfp/WfpInner.h b/src/Wfp/WfpInner.h
new file mode 100644
index 00000000..ca555fc6
--- /dev/null
+++ b/src/Wfp/WfpInner.h
@@ -0,0 +1,315 @@
+// SoftEther VPN Source Code
+// Windows Filtering Platform Callout Driver for Capturing IPsec Packets on Windows Vista / 7 / Server 2008
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// WfpInner.h
+// Header File for WFP Callout Driver
+
+#ifndef WFPINNER_H
+#define WFPINNER_H
+
+// Win32 DDK related
+#ifndef CPU_64
+#define _X86_
+#define i386
+#else // CPU_64
+#define _AMD64_
+#define AMD64
+#define x64
+#endif // CPU_64
+
+#define STD_CALL
+#define CONDITION_HANDLING 1
+#define NT_UP 1
+#define NT_INST 0
+#define _NT1X_ 100
+#define _WIN32_WINNT 0x0600
+#define WINNT 1
+#define WINVER 0x0600
+#define _WIN32_IE 0x0700
+#define WIN32_LEAN_AND_MEAN 1
+#define DEVL 1
+#define __BUILDMACHINE__ WinDDK
+#define FPO 0
+#define BINARY_COMPATIBLE 0
+#define NT
+#define NDIS60 1
+#define NDIS_SUPPORT_NDIS6 1
+#define NTDDI_VERSION 0x06000100
+
+#define KMDF_MAJOR_VERSION_STRING 01
+#define KMDF_MINOR_VERSION_STRING 009
+
+#include <ntddk.h>
+#include <fwpsk.h>
+#include <fwpmk.h>
+#include <ndis.h>
+#include <ws2ipdef.h>
+#include <in6addr.h>
+#include <ip2string.h>
+#include <stdio.h>
+#include <string.h>
+#define INITGUID
+#include <guiddef.h>
+
+#define TRUE 1
+#define FALSE 0
+typedef unsigned long bool;
+#define true 1
+#define false 0
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef signed char CHAR;
+typedef unsigned long DWORD;
+#define INFINITE 0xFFFFFFFF
+
+#define LESS(a, max_value) ((a) < (max_value) ? (a) : (max_value))
+#define MORE(a, min_value) ((a) > (min_value) ? (a) : (min_value))
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+// Error checking macro
+#define OK(val) (val == STATUS_SUCCESS)
+#define NG(val) (!OK(val))
+#define CRUSH_WHERE //Crush(0xaaaaaaaa, __LINE__, __LINE__, __LINE__)
+
+// Constants
+#define MEMPOOL_TAG 'wpfx'
+#define WFP_MAX_LOCAL_IP_COUNT 4096
+
+// Tag constant
+#define WFP_ESP_PACKET_TAG_1 0x19841117
+#define WFP_ESP_PACKET_TAG_2 0x1accafe1
+
+// ESP protocol number
+#define WFP_ESP_RAW_PROTOCOL_ID 50
+#define WFP_ESP_RAW_PROTOCOL_ID_DST 52
+
+// Event
+typedef struct EVENT
+{
+ KEVENT *EventObj;
+ HANDLE Handle;
+} EVENT;
+
+// Spin lock
+typedef struct SPINLOCK
+{
+ KSPIN_LOCK SpinLock;
+ KIRQL OldIrql;
+} SPINLOCK;
+
+// Instance data
+typedef struct WFP_CTX
+{
+ DEVICE_OBJECT *DeviceObject;
+ UNICODE_STRING DeviceName;
+ UNICODE_STRING DeviceNameWin32;
+ EVENT *Event;
+ HANDLE hEngine;
+ bool Halting;
+ UINT CalloutIdIPv4;
+ UINT CalloutIdIPv6;
+ UINT CalloutObjIdIPv4;
+ UINT CalloutObjIdIPv6;
+ SPINLOCK *LocalIPListLock;
+ UCHAR *LocalIPListData;
+ UINT LocalIPListSize;
+ HANDLE hInjectionIPv4, hInjectionIPv6;
+ NDIS_HANDLE hNdis;
+} WFP_CTX;
+
+#pragma pack(push, 1)
+
+#define WFP_IP_PROTO_UDP 0x11 // UDP protocol
+
+// IPv4 header
+typedef struct WFP_IPV4_HEADER
+{
+ UCHAR VersionAndHeaderLength; // Version and header size
+ UCHAR TypeOfService; // Service Type
+ USHORT TotalLength; // Total size
+ USHORT Identification; // Identifier
+ UCHAR FlagsAndFlagmentOffset[2]; // The flag and fragment offset
+ UCHAR TimeToLive; // TTL
+ UCHAR Protocol; // Protocol
+ USHORT Checksum; // Checksum
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+} WFP_IPV4_HEADER;
+
+// IPv6 header
+typedef struct WFP_IPV6_HEADER
+{
+ UCHAR VersionAndTrafficClass1; // Version Number (4 bit) and Traffic Class 1 (4 bit)
+ UCHAR TrafficClass2AndFlowLabel1; // Traffic Class 2 (4 bit) and Flow Label 1 (4 bit)
+ UCHAR FlowLabel2; // Flow Label 2 (8 bit)
+ UCHAR FlowLabel3; // Flow Label 3 (8 bit)
+ USHORT PayloadLength; // Length of the payload (including extension header)
+ UCHAR NextHeader; // The next header
+ UCHAR HopLimit; // Hop limit
+ UCHAR SrcAddress[16]; // Source address
+ UCHAR DestAddress[16]; // Destination address
+} WFP_IPV6_HEADER;
+
+// UDP header
+typedef struct WFP_UDP_HEADER
+{
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ USHORT PacketLength; // Data length
+ USHORT Checksum; // Checksum
+} WFP_UDP_HEADER;
+
+// Context of injected packet
+typedef struct WFP_INJECTED_PACKET_CONTEXT
+{
+ NET_BUFFER OriginalNetBufferData; // Data of the original NET_BUFFER
+ NET_BUFFER *CurrentNetBuffer; // Pointer of the current NET_BUFFER
+ NET_BUFFER_LIST *AllocatedNetBufferList; // Newly allocated NET_BUFFER_LIST
+ MDL *AllocatedMdl; // MDL that newly allocated
+ void *AllocatedMemory; // Newly allocated memory
+} WFP_INJECTED_PACKET_CONTEXT;
+
+
+#pragma pack(pop)
+
+
+// Function prototype
+NTSTATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path);
+void DriverUnload(DRIVER_OBJECT *driver_object);
+NTSTATUS DriverDispatch(DEVICE_OBJECT *device_object, IRP *irp);
+
+void NTAPI CalloutClassify(const FWPS_INCOMING_VALUES0* inFixedValues,
+ const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
+ void* layerData,
+ const FWPS_FILTER0* filter,
+ UINT64 flowContext,
+ FWPS_CLASSIFY_OUT0* classifyOut);
+NTSTATUS NTAPI CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,
+ const GUID* filterKey, FWPS_FILTER0* filter);
+bool IsIPAddressInList(struct WFP_LOCAL_IP *ip);
+bool IsIPv4AddressInList(void *addr);
+bool IsIPv6AddressInList(void *addr);
+void FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT *ctx);
+UCHAR *ModificationOfIPsecESPPacket(UCHAR *ip_packet, UINT ip_packet_size, UINT ip_header_size, UINT *dst_size_ptr, bool isv6);
+USHORT IpChecksum(void *buf, UINT size);
+bool InjectPacket(HANDLE hInjection, NET_BUFFER_LIST *nbl, UCHAR *dst_data, UINT dst_size, const FWPS_INCOMING_VALUES0* inFixedValues, const FWPS_INCOMING_METADATA_VALUES0* inMetaValues);
+
+void *Malloc(UINT size);
+void *ZeroMalloc(UINT size);
+void Free(void *p);
+void *ReAlloc(void *p, UINT size);
+void Copy(void *dst, void *src, UINT size);
+UINT GetMemSize(void *p);
+void Zero(void *p, UINT size);
+UINT Cmp(void *p1, void *p2, UINT size);
+SPINLOCK *NewSpinLock();
+void SpinLock(SPINLOCK *s);
+void SpinUnlock(SPINLOCK *s);
+void FreeSpinLock(SPINLOCK *s);
+EVENT *NewEvent(wchar_t *name);
+void FreeEvent(EVENT *e);
+void SetEvent(EVENT *e);
+void ResetEvent(EVENT *e);
+void Sleep(int milliSeconds);
+USHORT Swap16(USHORT value);
+UINT Swap32(UINT value);
+UINT64 Swap64(UINT64 value);
+USHORT Endian16(USHORT src);
+UINT Endian32(UINT src);
+UINT64 Endian64(UINT64 src);
+
+void Crush();
+
+
+#endif // WFPINNER_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Wfp/resource1.h b/src/Wfp/resource1.h
new file mode 100644
index 00000000..744b77bb
--- /dev/null
+++ b/src/Wfp/resource1.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Wfp.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/bin/BuiltHamcoreFiles/unix/hamcore.se2 b/src/bin/BuiltHamcoreFiles/unix/hamcore.se2
new file mode 100644
index 00000000..b3231a54
--- /dev/null
+++ b/src/bin/BuiltHamcoreFiles/unix/hamcore.se2
Binary files differ
diff --git a/src/bin/hamcore/SeLow_x64.inf b/src/bin/hamcore/SeLow_x64.inf
new file mode 100644
index 00000000..d626d9c4
--- /dev/null
+++ b/src/bin/hamcore/SeLow_x64.inf
@@ -0,0 +1,65 @@
+; SeLow - SoftEther Lightweight Ethernet Low Driver
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = NetTrans
+ClassGUID = {4D36E975-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = $MONTH$/$DAY$/$YEAR$, $VER_MAJOR$.$VER_MINOR$.0.$VER_BUILD$
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SoftEther.NTamd64]
+%SeLow_DisplayName% = SeLow_Install, SeLow
+
+[SeLow_Install]
+Characteristics = 0x4080
+AddReg = SeLow_Install_Ndi
+CopyFiles = SeLow_CopyFiles
+
+[SeLow_Install_Ndi]
+HKR, Ndi, Service, , "SeLow"
+HKR, Ndi, HelpText, , %SeLow_Description%
+HKR, Ndi\Interfaces, UpperRange, , noupper
+HKR, Ndi\Interfaces, LowerRange, , "ndis5,ndis4"
+
+[SeLow_Install.Services]
+AddService = SeLow, , SeLow_Service_Install
+
+[SeLow_Service_Install]
+DisplayName = %SeLow_DisplayName%
+Description = %SeLow_Description%
+ServiceType = 1
+StartType = 1
+ErrorControl = 1
+ServiceBinary = %12%\SeLow_x64.sys
+LoadOrderGroup = PNP_TDI
+
+[SeLow_Install.Remove.Services]
+DelService = SeLow, 0x200
+
+[SourceDisksNames]
+1 = %DiskDescription%, "", ,
+
+[SourceDisksFiles]
+SeLow_x64.sys = 1
+
+[DestinationDirs]
+SeLow_CopyFiles = 12
+
+[SeLow_CopyFiles]
+SeLow_x64.sys, , , 2
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "SoftEther Lightweight Network Protocol Install Disk"
+SeLow_DisplayName = "SoftEther Lightweight Network Protocol"
+SeLow_Description = "A lightweight helper kernel-mode module for PacketiX VPN / SoftEther VPN."
+
+
+
+
diff --git a/src/bin/hamcore/SeLow_x64.sys b/src/bin/hamcore/SeLow_x64.sys
new file mode 100644
index 00000000..fc8b0710
--- /dev/null
+++ b/src/bin/hamcore/SeLow_x64.sys
Binary files differ
diff --git a/src/bin/hamcore/SeLow_x86.inf b/src/bin/hamcore/SeLow_x86.inf
new file mode 100644
index 00000000..d8384b07
--- /dev/null
+++ b/src/bin/hamcore/SeLow_x86.inf
@@ -0,0 +1,65 @@
+; SeLow - SoftEther Lightweight Ethernet Low Driver
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = NetTrans
+ClassGUID = {4D36E975-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = $MONTH$/$DAY$/$YEAR$, $VER_MAJOR$.$VER_MINOR$.0.$VER_BUILD$
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTx86
+
+[SoftEther.NTx86]
+%SeLow_DisplayName% = SeLow_Install, SeLow
+
+[SeLow_Install]
+Characteristics = 0x4080
+AddReg = SeLow_Install_Ndi
+CopyFiles = SeLow_CopyFiles
+
+[SeLow_Install_Ndi]
+HKR, Ndi, Service, , "SeLow"
+HKR, Ndi, HelpText, , %SeLow_Description%
+HKR, Ndi\Interfaces, UpperRange, , noupper
+HKR, Ndi\Interfaces, LowerRange, , "ndis5,ndis4"
+
+[SeLow_Install.Services]
+AddService = SeLow, , SeLow_Service_Install
+
+[SeLow_Service_Install]
+DisplayName = %SeLow_DisplayName%
+Description = %SeLow_Description%
+ServiceType = 1
+StartType = 1
+ErrorControl = 1
+ServiceBinary = %12%\SeLow_x86.sys
+LoadOrderGroup = PNP_TDI
+
+[SeLow_Install.Remove.Services]
+DelService = SeLow, 0x200
+
+[SourceDisksNames]
+1 = %DiskDescription%, "", ,
+
+[SourceDisksFiles]
+SeLow_x86.sys = 1
+
+[DestinationDirs]
+SeLow_CopyFiles = 12
+
+[SeLow_CopyFiles]
+SeLow_x86.sys, , , 2
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "SoftEther Lightweight Network Protocol Install Disk"
+SeLow_DisplayName = "SoftEther Lightweight Network Protocol"
+SeLow_Description = "A lightweight helper kernel-mode module for PacketiX VPN / SoftEther VPN."
+
+
+
+
diff --git a/src/bin/hamcore/SeLow_x86.sys b/src/bin/hamcore/SeLow_x86.sys
new file mode 100644
index 00000000..e9856768
--- /dev/null
+++ b/src/bin/hamcore/SeLow_x86.sys
Binary files differ
diff --git a/src/bin/hamcore/backup_dir_readme.txt b/src/bin/hamcore/backup_dir_readme.txt
new file mode 100644
index 00000000..b9c5bd7f
--- /dev/null
+++ b/src/bin/hamcore/backup_dir_readme.txt
@@ -0,0 +1,10 @@
+======================================================================
+
+ About Backup Folder
+
+======================================================================
+
+Here are auto backups of configuration files.
+
+You can delete there files to make free space on the disk drive.
+
diff --git a/src/bin/hamcore/egg1.exe b/src/bin/hamcore/egg1.exe
new file mode 100644
index 00000000..98b8121a
--- /dev/null
+++ b/src/bin/hamcore/egg1.exe
Binary files differ
diff --git a/src/bin/hamcore/egg2.exe b/src/bin/hamcore/egg2.exe
new file mode 100644
index 00000000..98170dfd
--- /dev/null
+++ b/src/bin/hamcore/egg2.exe
Binary files differ
diff --git a/src/bin/hamcore/egg3.exe b/src/bin/hamcore/egg3.exe
new file mode 100644
index 00000000..c52758b1
--- /dev/null
+++ b/src/bin/hamcore/egg3.exe
Binary files differ
diff --git a/src/bin/hamcore/empty.config b/src/bin/hamcore/empty.config
new file mode 100644
index 00000000..0ae49aa2
--- /dev/null
+++ b/src/bin/hamcore/empty.config
@@ -0,0 +1,3 @@
+# VPN Default Empty Config File
+
+
diff --git a/src/bin/hamcore/empty_sevpnclient.config b/src/bin/hamcore/empty_sevpnclient.config
new file mode 100644
index 00000000..43aed949
--- /dev/null
+++ b/src/bin/hamcore/empty_sevpnclient.config
@@ -0,0 +1,77 @@
+# Software Configuration File
+#
+# You can edit this file when the program is not working.
+#
+declare root
+{
+ bool DontSavePassword false
+ byte EncryptedPassword +WzqGYrR3VYXrAhKPZLGEHcIwO8=
+ bool PasswordRemoteOnly false
+ string UserAgent Mozilla/4.0$20(compatible;$20MSIE$206.0;$20Windows$20NT$205.1;$20.NET$20CLR$201.1.4322)
+ uint UseSecureDeviceId 0
+
+ declare AccountDatabase
+ {
+ declare Account0
+ {
+ bool CheckServerCert false
+ uint64 CreateDateTime 1275214393898
+ uint64 LastConnectDateTime 0
+ bool StartupAccount false
+ uint64 UpdateDateTime 1275214393898
+
+ declare ClientAuth
+ {
+ uint AuthType 0
+ string Username public
+ }
+ declare ClientOption
+ {
+ string AccountName Public$20VPN$20&$20NAT$20in$20Japan$20(Sample)
+ uint AdditionalConnectionInterval 1
+ uint ConnectionDisconnectSpan 0
+ string DeviceName TEST
+ bool DisableQoS true
+ bool HalfConnection false
+ bool HideNicInfoWindow false
+ bool HideStatusWindow false
+ string Hostname public.softether.com
+ string HubName PUBLIC
+ uint MaxConnection 2
+ bool NoRoutingTracking false
+ bool NoTls1 false
+ uint NumRetry 4294967295
+ uint Port 443
+ uint PortUDP 0
+ string ProxyName $
+ byte ProxyPassword $
+ uint ProxyPort 0
+ uint ProxyType 0
+ string ProxyUsername $
+ bool RequireBridgeRoutingMode false
+ bool RequireMonitorMode false
+ uint RetryInterval 15
+ bool UseCompress false
+ bool UseEncrypt true
+ }
+ }
+ }
+ declare ClientManagerSetting
+ {
+ bool EasyMode false
+ bool LockMode false
+ }
+ declare Config
+ {
+ bool AllowRemoteConfig false
+ uint64 AutoDeleteCheckDiskFreeSpaceMin 104857600
+ string KeepConnectHost keepalive.softether.org
+ uint KeepConnectInterval 50
+ uint KeepConnectPort 80
+ uint KeepConnectProtocol 1
+ bool UseKeepConnect false
+ }
+ declare RootCA
+ {
+ }
+}
diff --git a/src/bin/hamcore/eula.txt b/src/bin/hamcore/eula.txt
new file mode 100644
index 00000000..ad9a8d33
--- /dev/null
+++ b/src/bin/hamcore/eula.txt
@@ -0,0 +1,444 @@
+SoftEther VPN Server, Client and Bridge are free software, and released as open-source. You can redistribute them and/or modify them under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.
+
+Copyright (c) 2012-2014 Daiyuu Nobori.
+Copyright (c) 2012-2014 SoftEther Project at University of Tsukuba, Japan.
+Copyright (c) 2012-2014 SoftEther Corporation.
+All Rights Reserved.
+http://www.softether.org/
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License version 2 along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+Neither the name of SoftEther nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+
+USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER COUNTRIES MIGHT BE RESTRICTED.
+
+THE FOLLOWING GPLV2 CONDITIONS APPLY ON ALL SOFTETHER VPN PROGRAMS WHICH ARE DEVELOPED BY SOFTETHER VPN PROJECT.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+Note that the above copyright notices and use conditions do not apply on the software components listed in below which are included in this Software. When you use or distribute Software with including these libraries, you have to follow the conditions of these libraries.
+
+These library's copyright notices and conditions are following;
+
+-------------------
+
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas of Cornell University.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above) ; and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, distribute with modifications, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must display the following acknowledgement: "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES
+
+SoftEther provides source codes of some GPL/LGPL/other libraries listed above on its web server. Anyone can download, use and re-distribute them under individual licenses which are contained on each archive file, available from the following URL:
+http://uploader.softether.co.jp/src/
+
diff --git a/src/bin/hamcore/inf/selow_x64/SeLow_x64.inf b/src/bin/hamcore/inf/selow_x64/SeLow_x64.inf
new file mode 100644
index 00000000..c28d6397
--- /dev/null
+++ b/src/bin/hamcore/inf/selow_x64/SeLow_x64.inf
@@ -0,0 +1,70 @@
+; SeLow - SoftEther Lightweight Ethernet Low Driver
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = NetTrans
+ClassGUID = {4D36E975-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_selow.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SoftEther.NTamd64]
+%SeLow_DisplayName% = SeLow_Install, SeLow
+
+[SeLow_Install]
+Characteristics = 0x4080
+AddReg = SeLow_Install_Ndi
+CopyFiles = SeLow_CopyFiles
+
+[SeLow_Install_Ndi]
+HKR, Ndi, Service, , "SeLow"
+HKR, Ndi, HelpText, , %SeLow_Description%
+HKR, Ndi\Interfaces, UpperRange, , noupper
+HKR, Ndi\Interfaces, LowerRange, , "ndis5,ndis4"
+
+[SeLow_Install.Services]
+AddService = SeLow, , SeLow_Service_Install
+
+[SeLow_Service_Install]
+DisplayName = %SeLow_DisplayName%
+Description = %SeLow_Description%
+ServiceType = 1
+StartType = 1
+ErrorControl = 1
+ServiceBinary = %12%\SeLow_x64.sys
+LoadOrderGroup = PNP_TDI
+
+[SeLow_Install.Remove.Services]
+DelService = SeLow, 0x200
+
+[SourceDisksNames]
+1 = %DiskDescription%, "", ,
+
+[SourceDisksFiles]
+SeLow_x64.sys = 1
+
+[DestinationDirs]
+SeLow_CopyFiles = 12
+
+[SeLow_CopyFiles]
+SeLow_x64.sys, , , 2
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "SoftEther Lightweight Network Protocol Install Disk"
+SeLow_DisplayName = "SoftEther Lightweight Network Protocol"
+SeLow_Description = "A lightweight helper kernel-mode module for PacketiX VPN / SoftEther VPN."
+
+
+
+
+
+; Auto Generated 20140104_181831.858
+
diff --git a/src/bin/hamcore/inf/selow_x64/inf.cat b/src/bin/hamcore/inf/selow_x64/inf.cat
new file mode 100644
index 00000000..a98da97e
--- /dev/null
+++ b/src/bin/hamcore/inf/selow_x64/inf.cat
Binary files differ
diff --git a/src/bin/hamcore/inf/selow_x86/SeLow_x86.inf b/src/bin/hamcore/inf/selow_x86/SeLow_x86.inf
new file mode 100644
index 00000000..17efd5d5
--- /dev/null
+++ b/src/bin/hamcore/inf/selow_x86/SeLow_x86.inf
@@ -0,0 +1,70 @@
+; SeLow - SoftEther Lightweight Ethernet Low Driver
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = NetTrans
+ClassGUID = {4D36E975-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_selow.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTx86
+
+[SoftEther.NTx86]
+%SeLow_DisplayName% = SeLow_Install, SeLow
+
+[SeLow_Install]
+Characteristics = 0x4080
+AddReg = SeLow_Install_Ndi
+CopyFiles = SeLow_CopyFiles
+
+[SeLow_Install_Ndi]
+HKR, Ndi, Service, , "SeLow"
+HKR, Ndi, HelpText, , %SeLow_Description%
+HKR, Ndi\Interfaces, UpperRange, , noupper
+HKR, Ndi\Interfaces, LowerRange, , "ndis5,ndis4"
+
+[SeLow_Install.Services]
+AddService = SeLow, , SeLow_Service_Install
+
+[SeLow_Service_Install]
+DisplayName = %SeLow_DisplayName%
+Description = %SeLow_Description%
+ServiceType = 1
+StartType = 1
+ErrorControl = 1
+ServiceBinary = %12%\SeLow_x86.sys
+LoadOrderGroup = PNP_TDI
+
+[SeLow_Install.Remove.Services]
+DelService = SeLow, 0x200
+
+[SourceDisksNames]
+1 = %DiskDescription%, "", ,
+
+[SourceDisksFiles]
+SeLow_x86.sys = 1
+
+[DestinationDirs]
+SeLow_CopyFiles = 12
+
+[SeLow_CopyFiles]
+SeLow_x86.sys, , , 2
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "SoftEther Lightweight Network Protocol Install Disk"
+SeLow_DisplayName = "SoftEther Lightweight Network Protocol"
+SeLow_Description = "A lightweight helper kernel-mode module for PacketiX VPN / SoftEther VPN."
+
+
+
+
+
+; Auto Generated 20140104_181657.418
+
diff --git a/src/bin/hamcore/inf/selow_x86/inf.cat b/src/bin/hamcore/inf/selow_x86/inf.cat
new file mode 100644
index 00000000..072a6ccd
--- /dev/null
+++ b/src/bin/hamcore/inf/selow_x86/inf.cat
Binary files differ
diff --git a/src/bin/hamcore/inf/x64/INF_VPN.inf b/src/bin/hamcore/inf/x64/INF_VPN.inf
new file mode 100644
index 00000000..a57f3bdf
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN"
+Neo.Service.DispName = "VPN Client Device Driver - VPN"
+Neo.Service.Desc = "VPN Client Adapter - VPN"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN10.inf b/src/bin/hamcore/inf/x64/INF_VPN10.inf
new file mode 100644
index 00000000..52ae9483
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN10.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN10.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN10.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN10.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN10
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN10"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN10.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN10"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN10.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN10.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN10"
+Neo.Service.DispName = "VPN Client Device Driver - VPN10"
+Neo.Service.Desc = "VPN Client Adapter - VPN10"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN10"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN100.inf b/src/bin/hamcore/inf/x64/INF_VPN100.inf
new file mode 100644
index 00000000..bec74d2d
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN100.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN100.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN100.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN100.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN100
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN100"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN100.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN100"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN100.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN100.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN100"
+Neo.Service.DispName = "VPN Client Device Driver - VPN100"
+Neo.Service.Desc = "VPN Client Adapter - VPN100"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN100"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN101.inf b/src/bin/hamcore/inf/x64/INF_VPN101.inf
new file mode 100644
index 00000000..2a863b06
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN101.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN101.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN101.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN101.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN101
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN101"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN101.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN101"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN101.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN101.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN101"
+Neo.Service.DispName = "VPN Client Device Driver - VPN101"
+Neo.Service.Desc = "VPN Client Adapter - VPN101"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN101"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN102.inf b/src/bin/hamcore/inf/x64/INF_VPN102.inf
new file mode 100644
index 00000000..1279b1a5
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN102.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN102.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN102.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN102.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN102
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN102"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN102.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN102"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN102.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN102.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN102"
+Neo.Service.DispName = "VPN Client Device Driver - VPN102"
+Neo.Service.Desc = "VPN Client Adapter - VPN102"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN102"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN103.inf b/src/bin/hamcore/inf/x64/INF_VPN103.inf
new file mode 100644
index 00000000..d1452caa
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN103.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN103.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN103.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN103.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN103
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN103"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN103.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN103"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN103.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN103.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN103"
+Neo.Service.DispName = "VPN Client Device Driver - VPN103"
+Neo.Service.Desc = "VPN Client Adapter - VPN103"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN103"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN104.inf b/src/bin/hamcore/inf/x64/INF_VPN104.inf
new file mode 100644
index 00000000..1bc3383b
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN104.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN104.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN104.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN104.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN104
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN104"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN104.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN104"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN104.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN104.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN104"
+Neo.Service.DispName = "VPN Client Device Driver - VPN104"
+Neo.Service.Desc = "VPN Client Adapter - VPN104"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN104"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN105.inf b/src/bin/hamcore/inf/x64/INF_VPN105.inf
new file mode 100644
index 00000000..312ad9e3
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN105.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN105.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN105.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN105.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN105
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN105"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN105.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN105"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN105.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN105.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN105"
+Neo.Service.DispName = "VPN Client Device Driver - VPN105"
+Neo.Service.Desc = "VPN Client Adapter - VPN105"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN105"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN106.inf b/src/bin/hamcore/inf/x64/INF_VPN106.inf
new file mode 100644
index 00000000..c017b961
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN106.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN106.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN106.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN106.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN106
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN106"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN106.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN106"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN106.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN106.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN106"
+Neo.Service.DispName = "VPN Client Device Driver - VPN106"
+Neo.Service.Desc = "VPN Client Adapter - VPN106"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN106"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN107.inf b/src/bin/hamcore/inf/x64/INF_VPN107.inf
new file mode 100644
index 00000000..c92e0b6c
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN107.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN107.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN107.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN107.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN107
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN107"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN107.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN107"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN107.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN107.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN107"
+Neo.Service.DispName = "VPN Client Device Driver - VPN107"
+Neo.Service.Desc = "VPN Client Adapter - VPN107"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN107"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN108.inf b/src/bin/hamcore/inf/x64/INF_VPN108.inf
new file mode 100644
index 00000000..bf7cbddc
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN108.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN108.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN108.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN108.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN108
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN108"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN108.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN108"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN108.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN108.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN108"
+Neo.Service.DispName = "VPN Client Device Driver - VPN108"
+Neo.Service.Desc = "VPN Client Adapter - VPN108"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN108"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN109.inf b/src/bin/hamcore/inf/x64/INF_VPN109.inf
new file mode 100644
index 00000000..9bef4034
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN109.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN109.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN109.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN109.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN109
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN109"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN109.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN109"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN109.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN109.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN109"
+Neo.Service.DispName = "VPN Client Device Driver - VPN109"
+Neo.Service.Desc = "VPN Client Adapter - VPN109"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN109"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN11.inf b/src/bin/hamcore/inf/x64/INF_VPN11.inf
new file mode 100644
index 00000000..ef3392cc
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN11.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN11.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN11.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN11.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN11
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN11"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN11.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN11"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN11.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN11.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN11"
+Neo.Service.DispName = "VPN Client Device Driver - VPN11"
+Neo.Service.Desc = "VPN Client Adapter - VPN11"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN11"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN110.inf b/src/bin/hamcore/inf/x64/INF_VPN110.inf
new file mode 100644
index 00000000..653fb0b7
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN110.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN110.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN110.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN110.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN110
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN110"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN110.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN110"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN110.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN110.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN110"
+Neo.Service.DispName = "VPN Client Device Driver - VPN110"
+Neo.Service.Desc = "VPN Client Adapter - VPN110"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN110"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN111.inf b/src/bin/hamcore/inf/x64/INF_VPN111.inf
new file mode 100644
index 00000000..2a37c007
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN111.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN111.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN111.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN111.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN111
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN111"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN111.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN111"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN111.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN111.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN111"
+Neo.Service.DispName = "VPN Client Device Driver - VPN111"
+Neo.Service.Desc = "VPN Client Adapter - VPN111"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN111"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN112.inf b/src/bin/hamcore/inf/x64/INF_VPN112.inf
new file mode 100644
index 00000000..e40f9ef8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN112.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN112.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN112.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN112.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN112
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN112"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN112.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN112"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN112.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN112.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN112"
+Neo.Service.DispName = "VPN Client Device Driver - VPN112"
+Neo.Service.Desc = "VPN Client Adapter - VPN112"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN112"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN113.inf b/src/bin/hamcore/inf/x64/INF_VPN113.inf
new file mode 100644
index 00000000..86e365d7
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN113.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN113.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN113.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN113.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN113
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN113"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN113.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN113"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN113.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN113.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN113"
+Neo.Service.DispName = "VPN Client Device Driver - VPN113"
+Neo.Service.Desc = "VPN Client Adapter - VPN113"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN113"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN114.inf b/src/bin/hamcore/inf/x64/INF_VPN114.inf
new file mode 100644
index 00000000..0da197c3
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN114.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN114.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN114.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN114.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN114
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN114"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN114.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN114"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN114.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN114.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN114"
+Neo.Service.DispName = "VPN Client Device Driver - VPN114"
+Neo.Service.Desc = "VPN Client Adapter - VPN114"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN114"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN115.inf b/src/bin/hamcore/inf/x64/INF_VPN115.inf
new file mode 100644
index 00000000..e3b9a1b9
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN115.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN115.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN115.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN115.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN115
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN115"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN115.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN115"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN115.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN115.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN115"
+Neo.Service.DispName = "VPN Client Device Driver - VPN115"
+Neo.Service.Desc = "VPN Client Adapter - VPN115"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN115"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN116.inf b/src/bin/hamcore/inf/x64/INF_VPN116.inf
new file mode 100644
index 00000000..3d88e41b
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN116.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN116.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN116.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN116.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN116
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN116"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN116.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN116"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN116.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN116.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN116"
+Neo.Service.DispName = "VPN Client Device Driver - VPN116"
+Neo.Service.Desc = "VPN Client Adapter - VPN116"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN116"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN117.inf b/src/bin/hamcore/inf/x64/INF_VPN117.inf
new file mode 100644
index 00000000..4ca29be8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN117.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN117.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN117.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN117.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN117
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN117"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN117.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN117"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN117.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN117.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN117"
+Neo.Service.DispName = "VPN Client Device Driver - VPN117"
+Neo.Service.Desc = "VPN Client Adapter - VPN117"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN117"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN118.inf b/src/bin/hamcore/inf/x64/INF_VPN118.inf
new file mode 100644
index 00000000..7907fd01
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN118.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN118.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN118.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN118.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN118
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN118"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN118.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN118"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN118.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN118.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN118"
+Neo.Service.DispName = "VPN Client Device Driver - VPN118"
+Neo.Service.Desc = "VPN Client Adapter - VPN118"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN118"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN119.inf b/src/bin/hamcore/inf/x64/INF_VPN119.inf
new file mode 100644
index 00000000..6482d249
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN119.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN119.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN119.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN119.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN119
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN119"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN119.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN119"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN119.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN119.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN119"
+Neo.Service.DispName = "VPN Client Device Driver - VPN119"
+Neo.Service.Desc = "VPN Client Adapter - VPN119"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN119"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN12.inf b/src/bin/hamcore/inf/x64/INF_VPN12.inf
new file mode 100644
index 00000000..71d66b70
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN12.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN12.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN12.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN12.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN12
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN12"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN12.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN12"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN12.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN12.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN12"
+Neo.Service.DispName = "VPN Client Device Driver - VPN12"
+Neo.Service.Desc = "VPN Client Adapter - VPN12"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN12"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN120.inf b/src/bin/hamcore/inf/x64/INF_VPN120.inf
new file mode 100644
index 00000000..1e131a0a
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN120.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN120.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN120.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN120.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN120
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN120"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN120.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN120"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN120.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN120.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN120"
+Neo.Service.DispName = "VPN Client Device Driver - VPN120"
+Neo.Service.Desc = "VPN Client Adapter - VPN120"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN120"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN121.inf b/src/bin/hamcore/inf/x64/INF_VPN121.inf
new file mode 100644
index 00000000..23c83a69
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN121.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN121.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN121.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN121.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN121
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN121"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN121.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN121"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN121.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN121.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN121"
+Neo.Service.DispName = "VPN Client Device Driver - VPN121"
+Neo.Service.Desc = "VPN Client Adapter - VPN121"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN121"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN122.inf b/src/bin/hamcore/inf/x64/INF_VPN122.inf
new file mode 100644
index 00000000..be26755e
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN122.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN122.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN122.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN122.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN122
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN122"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN122.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN122"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN122.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN122.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN122"
+Neo.Service.DispName = "VPN Client Device Driver - VPN122"
+Neo.Service.Desc = "VPN Client Adapter - VPN122"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN122"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN123.inf b/src/bin/hamcore/inf/x64/INF_VPN123.inf
new file mode 100644
index 00000000..845e7833
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN123.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN123.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN123.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN123.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN123
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN123"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN123.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN123"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN123.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN123.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN123"
+Neo.Service.DispName = "VPN Client Device Driver - VPN123"
+Neo.Service.Desc = "VPN Client Adapter - VPN123"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN123"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN124.inf b/src/bin/hamcore/inf/x64/INF_VPN124.inf
new file mode 100644
index 00000000..c09d7d12
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN124.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN124.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN124.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN124.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN124
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN124"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN124.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN124"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN124.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN124.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN124"
+Neo.Service.DispName = "VPN Client Device Driver - VPN124"
+Neo.Service.Desc = "VPN Client Adapter - VPN124"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN124"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN125.inf b/src/bin/hamcore/inf/x64/INF_VPN125.inf
new file mode 100644
index 00000000..34aac2a3
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN125.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN125.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN125.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN125.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN125
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN125"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN125.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN125"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN125.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN125.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN125"
+Neo.Service.DispName = "VPN Client Device Driver - VPN125"
+Neo.Service.Desc = "VPN Client Adapter - VPN125"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN125"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN126.inf b/src/bin/hamcore/inf/x64/INF_VPN126.inf
new file mode 100644
index 00000000..d68ef0d8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN126.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN126.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN126.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN126.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN126
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN126"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN126.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN126"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN126.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN126.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN126"
+Neo.Service.DispName = "VPN Client Device Driver - VPN126"
+Neo.Service.Desc = "VPN Client Adapter - VPN126"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN126"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN127.inf b/src/bin/hamcore/inf/x64/INF_VPN127.inf
new file mode 100644
index 00000000..83248c72
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN127.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN127.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN127.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN127.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN127
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN127"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN127.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN127"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN127.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN127.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN127"
+Neo.Service.DispName = "VPN Client Device Driver - VPN127"
+Neo.Service.Desc = "VPN Client Adapter - VPN127"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN127"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN13.inf b/src/bin/hamcore/inf/x64/INF_VPN13.inf
new file mode 100644
index 00000000..89e7440c
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN13.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN13.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN13.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN13.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN13
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN13"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN13.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN13"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN13.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN13.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN13"
+Neo.Service.DispName = "VPN Client Device Driver - VPN13"
+Neo.Service.Desc = "VPN Client Adapter - VPN13"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN13"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN14.inf b/src/bin/hamcore/inf/x64/INF_VPN14.inf
new file mode 100644
index 00000000..8bdd6b7e
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN14.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN14.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN14.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN14.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN14
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN14"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN14.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN14"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN14.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN14.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN14"
+Neo.Service.DispName = "VPN Client Device Driver - VPN14"
+Neo.Service.Desc = "VPN Client Adapter - VPN14"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN14"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN15.inf b/src/bin/hamcore/inf/x64/INF_VPN15.inf
new file mode 100644
index 00000000..1e1a6b73
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN15.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN15.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN15.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN15.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN15
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN15"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN15.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN15"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN15.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN15.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN15"
+Neo.Service.DispName = "VPN Client Device Driver - VPN15"
+Neo.Service.Desc = "VPN Client Adapter - VPN15"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN15"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN16.inf b/src/bin/hamcore/inf/x64/INF_VPN16.inf
new file mode 100644
index 00000000..f3707f27
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN16.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN16.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN16.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN16.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN16
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN16"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN16.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN16"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN16.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN16.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN16"
+Neo.Service.DispName = "VPN Client Device Driver - VPN16"
+Neo.Service.Desc = "VPN Client Adapter - VPN16"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN16"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN17.inf b/src/bin/hamcore/inf/x64/INF_VPN17.inf
new file mode 100644
index 00000000..1d69d286
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN17.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN17.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN17.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN17.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN17
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN17"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN17.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN17"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN17.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN17.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN17"
+Neo.Service.DispName = "VPN Client Device Driver - VPN17"
+Neo.Service.Desc = "VPN Client Adapter - VPN17"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN17"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN18.inf b/src/bin/hamcore/inf/x64/INF_VPN18.inf
new file mode 100644
index 00000000..8046f2eb
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN18.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN18.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN18.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN18.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN18
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN18"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN18.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN18"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN18.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN18.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN18"
+Neo.Service.DispName = "VPN Client Device Driver - VPN18"
+Neo.Service.Desc = "VPN Client Adapter - VPN18"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN18"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN19.inf b/src/bin/hamcore/inf/x64/INF_VPN19.inf
new file mode 100644
index 00000000..fd510fc6
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN19.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN19.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN19.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN19.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN19
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN19"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN19.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN19"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN19.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN19.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN19"
+Neo.Service.DispName = "VPN Client Device Driver - VPN19"
+Neo.Service.Desc = "VPN Client Adapter - VPN19"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN19"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN2.inf b/src/bin/hamcore/inf/x64/INF_VPN2.inf
new file mode 100644
index 00000000..7ef036b2
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN2.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN2.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN2.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN2.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN2
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN2"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN2.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN2"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN2.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN2.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN2"
+Neo.Service.DispName = "VPN Client Device Driver - VPN2"
+Neo.Service.Desc = "VPN Client Adapter - VPN2"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN2"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN20.inf b/src/bin/hamcore/inf/x64/INF_VPN20.inf
new file mode 100644
index 00000000..80f4e0c0
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN20.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN20.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN20.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN20.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN20
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN20"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN20.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN20"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN20.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN20.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN20"
+Neo.Service.DispName = "VPN Client Device Driver - VPN20"
+Neo.Service.Desc = "VPN Client Adapter - VPN20"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN20"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN21.inf b/src/bin/hamcore/inf/x64/INF_VPN21.inf
new file mode 100644
index 00000000..70995f60
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN21.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN21.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN21.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN21.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN21
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN21"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN21.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN21"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN21.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN21.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN21"
+Neo.Service.DispName = "VPN Client Device Driver - VPN21"
+Neo.Service.Desc = "VPN Client Adapter - VPN21"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN21"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN22.inf b/src/bin/hamcore/inf/x64/INF_VPN22.inf
new file mode 100644
index 00000000..f6420f14
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN22.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN22.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN22.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN22.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN22
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN22"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN22.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN22"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN22.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN22.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN22"
+Neo.Service.DispName = "VPN Client Device Driver - VPN22"
+Neo.Service.Desc = "VPN Client Adapter - VPN22"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN22"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN23.inf b/src/bin/hamcore/inf/x64/INF_VPN23.inf
new file mode 100644
index 00000000..0430bc36
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN23.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN23.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN23.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN23.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN23
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN23"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN23.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN23"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN23.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN23.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN23"
+Neo.Service.DispName = "VPN Client Device Driver - VPN23"
+Neo.Service.Desc = "VPN Client Adapter - VPN23"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN23"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN24.inf b/src/bin/hamcore/inf/x64/INF_VPN24.inf
new file mode 100644
index 00000000..81d7fb77
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN24.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN24.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN24.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN24.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN24
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN24"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN24.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN24"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN24.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN24.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN24"
+Neo.Service.DispName = "VPN Client Device Driver - VPN24"
+Neo.Service.Desc = "VPN Client Adapter - VPN24"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN24"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN25.inf b/src/bin/hamcore/inf/x64/INF_VPN25.inf
new file mode 100644
index 00000000..28e791a3
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN25.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN25.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN25.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN25.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN25
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN25"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN25.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN25"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN25.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN25.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN25"
+Neo.Service.DispName = "VPN Client Device Driver - VPN25"
+Neo.Service.Desc = "VPN Client Adapter - VPN25"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN25"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN26.inf b/src/bin/hamcore/inf/x64/INF_VPN26.inf
new file mode 100644
index 00000000..2c5a5b61
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN26.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN26.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN26.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN26.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN26
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN26"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN26.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN26"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN26.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN26.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN26"
+Neo.Service.DispName = "VPN Client Device Driver - VPN26"
+Neo.Service.Desc = "VPN Client Adapter - VPN26"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN26"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN27.inf b/src/bin/hamcore/inf/x64/INF_VPN27.inf
new file mode 100644
index 00000000..e76cc4d4
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN27.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN27.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN27.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN27.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN27
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN27"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN27.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN27"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN27.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN27.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN27"
+Neo.Service.DispName = "VPN Client Device Driver - VPN27"
+Neo.Service.Desc = "VPN Client Adapter - VPN27"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN27"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN28.inf b/src/bin/hamcore/inf/x64/INF_VPN28.inf
new file mode 100644
index 00000000..25eab7e5
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN28.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN28.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN28.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN28.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN28
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN28"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN28.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN28"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN28.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN28.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN28"
+Neo.Service.DispName = "VPN Client Device Driver - VPN28"
+Neo.Service.Desc = "VPN Client Adapter - VPN28"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN28"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN29.inf b/src/bin/hamcore/inf/x64/INF_VPN29.inf
new file mode 100644
index 00000000..dab42168
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN29.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN29.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN29.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN29.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN29
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN29"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN29.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN29"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN29.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN29.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN29"
+Neo.Service.DispName = "VPN Client Device Driver - VPN29"
+Neo.Service.Desc = "VPN Client Adapter - VPN29"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN29"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN3.inf b/src/bin/hamcore/inf/x64/INF_VPN3.inf
new file mode 100644
index 00000000..171f2260
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN3.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN3.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN3.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN3.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN3
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN3"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN3.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN3"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN3.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN3.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN3"
+Neo.Service.DispName = "VPN Client Device Driver - VPN3"
+Neo.Service.Desc = "VPN Client Adapter - VPN3"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN3"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN30.inf b/src/bin/hamcore/inf/x64/INF_VPN30.inf
new file mode 100644
index 00000000..a9606293
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN30.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN30.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN30.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN30.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN30
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN30"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN30.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN30"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN30.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN30.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN30"
+Neo.Service.DispName = "VPN Client Device Driver - VPN30"
+Neo.Service.Desc = "VPN Client Adapter - VPN30"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN30"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN31.inf b/src/bin/hamcore/inf/x64/INF_VPN31.inf
new file mode 100644
index 00000000..fe607ce1
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN31.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN31.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN31.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN31.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN31
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN31"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN31.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN31"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN31.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN31.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN31"
+Neo.Service.DispName = "VPN Client Device Driver - VPN31"
+Neo.Service.Desc = "VPN Client Adapter - VPN31"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN31"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN32.inf b/src/bin/hamcore/inf/x64/INF_VPN32.inf
new file mode 100644
index 00000000..88e3dfd7
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN32.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN32.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN32.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN32.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN32
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN32"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN32.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN32"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN32.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN32.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN32"
+Neo.Service.DispName = "VPN Client Device Driver - VPN32"
+Neo.Service.Desc = "VPN Client Adapter - VPN32"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN32"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN33.inf b/src/bin/hamcore/inf/x64/INF_VPN33.inf
new file mode 100644
index 00000000..e0e74249
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN33.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN33.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN33.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN33.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN33
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN33"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN33.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN33"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN33.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN33.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN33"
+Neo.Service.DispName = "VPN Client Device Driver - VPN33"
+Neo.Service.Desc = "VPN Client Adapter - VPN33"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN33"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN34.inf b/src/bin/hamcore/inf/x64/INF_VPN34.inf
new file mode 100644
index 00000000..787e567a
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN34.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN34.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN34.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN34.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN34
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN34"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN34.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN34"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN34.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN34.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN34"
+Neo.Service.DispName = "VPN Client Device Driver - VPN34"
+Neo.Service.Desc = "VPN Client Adapter - VPN34"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN34"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN35.inf b/src/bin/hamcore/inf/x64/INF_VPN35.inf
new file mode 100644
index 00000000..f98060a1
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN35.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN35.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN35.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN35.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN35
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN35"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN35.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN35"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN35.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN35.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN35"
+Neo.Service.DispName = "VPN Client Device Driver - VPN35"
+Neo.Service.Desc = "VPN Client Adapter - VPN35"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN35"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN36.inf b/src/bin/hamcore/inf/x64/INF_VPN36.inf
new file mode 100644
index 00000000..8c671337
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN36.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN36.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN36.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN36.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN36
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN36"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN36.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN36"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN36.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN36.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN36"
+Neo.Service.DispName = "VPN Client Device Driver - VPN36"
+Neo.Service.Desc = "VPN Client Adapter - VPN36"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN36"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN37.inf b/src/bin/hamcore/inf/x64/INF_VPN37.inf
new file mode 100644
index 00000000..a26bb5f4
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN37.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN37.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN37.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN37.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN37
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN37"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN37.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN37"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN37.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN37.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN37"
+Neo.Service.DispName = "VPN Client Device Driver - VPN37"
+Neo.Service.Desc = "VPN Client Adapter - VPN37"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN37"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN38.inf b/src/bin/hamcore/inf/x64/INF_VPN38.inf
new file mode 100644
index 00000000..6e7f60bc
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN38.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN38.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN38.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN38.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN38
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN38"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN38.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN38"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN38.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN38.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN38"
+Neo.Service.DispName = "VPN Client Device Driver - VPN38"
+Neo.Service.Desc = "VPN Client Adapter - VPN38"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN38"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN39.inf b/src/bin/hamcore/inf/x64/INF_VPN39.inf
new file mode 100644
index 00000000..32317aab
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN39.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN39.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN39.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN39.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN39
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN39"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN39.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN39"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN39.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN39.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN39"
+Neo.Service.DispName = "VPN Client Device Driver - VPN39"
+Neo.Service.Desc = "VPN Client Adapter - VPN39"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN39"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN4.inf b/src/bin/hamcore/inf/x64/INF_VPN4.inf
new file mode 100644
index 00000000..2b69c84c
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN4.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN4.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN4.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN4.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN4
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN4"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN4.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN4"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN4.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN4.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN4"
+Neo.Service.DispName = "VPN Client Device Driver - VPN4"
+Neo.Service.Desc = "VPN Client Adapter - VPN4"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN4"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN40.inf b/src/bin/hamcore/inf/x64/INF_VPN40.inf
new file mode 100644
index 00000000..2b1b1e53
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN40.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN40.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN40.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN40.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN40
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN40"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN40.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN40"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN40.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN40.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN40"
+Neo.Service.DispName = "VPN Client Device Driver - VPN40"
+Neo.Service.Desc = "VPN Client Adapter - VPN40"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN40"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN41.inf b/src/bin/hamcore/inf/x64/INF_VPN41.inf
new file mode 100644
index 00000000..795b9384
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN41.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN41.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN41.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN41.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN41
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN41"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN41.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN41"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN41.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN41.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN41"
+Neo.Service.DispName = "VPN Client Device Driver - VPN41"
+Neo.Service.Desc = "VPN Client Adapter - VPN41"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN41"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN42.inf b/src/bin/hamcore/inf/x64/INF_VPN42.inf
new file mode 100644
index 00000000..f4de324d
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN42.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN42.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN42.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN42.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN42
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN42"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN42.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN42"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN42.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN42.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN42"
+Neo.Service.DispName = "VPN Client Device Driver - VPN42"
+Neo.Service.Desc = "VPN Client Adapter - VPN42"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN42"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN43.inf b/src/bin/hamcore/inf/x64/INF_VPN43.inf
new file mode 100644
index 00000000..606cde78
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN43.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN43.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN43.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN43.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN43
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN43"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN43.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN43"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN43.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN43.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN43"
+Neo.Service.DispName = "VPN Client Device Driver - VPN43"
+Neo.Service.Desc = "VPN Client Adapter - VPN43"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN43"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN44.inf b/src/bin/hamcore/inf/x64/INF_VPN44.inf
new file mode 100644
index 00000000..8444d497
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN44.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN44.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN44.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN44.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN44
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN44"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN44.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN44"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN44.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN44.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN44"
+Neo.Service.DispName = "VPN Client Device Driver - VPN44"
+Neo.Service.Desc = "VPN Client Adapter - VPN44"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN44"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN45.inf b/src/bin/hamcore/inf/x64/INF_VPN45.inf
new file mode 100644
index 00000000..428077df
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN45.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN45.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN45.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN45.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN45
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN45"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN45.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN45"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN45.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN45.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN45"
+Neo.Service.DispName = "VPN Client Device Driver - VPN45"
+Neo.Service.Desc = "VPN Client Adapter - VPN45"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN45"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN46.inf b/src/bin/hamcore/inf/x64/INF_VPN46.inf
new file mode 100644
index 00000000..55ef2d7a
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN46.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN46.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN46.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN46.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN46
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN46"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN46.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN46"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN46.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN46.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN46"
+Neo.Service.DispName = "VPN Client Device Driver - VPN46"
+Neo.Service.Desc = "VPN Client Adapter - VPN46"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN46"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN47.inf b/src/bin/hamcore/inf/x64/INF_VPN47.inf
new file mode 100644
index 00000000..a6f35c3e
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN47.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN47.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN47.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN47.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN47
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN47"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN47.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN47"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN47.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN47.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN47"
+Neo.Service.DispName = "VPN Client Device Driver - VPN47"
+Neo.Service.Desc = "VPN Client Adapter - VPN47"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN47"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN48.inf b/src/bin/hamcore/inf/x64/INF_VPN48.inf
new file mode 100644
index 00000000..cd4d7f38
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN48.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN48.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN48.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN48.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN48
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN48"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN48.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN48"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN48.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN48.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN48"
+Neo.Service.DispName = "VPN Client Device Driver - VPN48"
+Neo.Service.Desc = "VPN Client Adapter - VPN48"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN48"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN49.inf b/src/bin/hamcore/inf/x64/INF_VPN49.inf
new file mode 100644
index 00000000..c9efe104
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN49.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN49.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN49.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN49.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN49
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN49"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN49.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN49"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN49.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN49.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN49"
+Neo.Service.DispName = "VPN Client Device Driver - VPN49"
+Neo.Service.Desc = "VPN Client Adapter - VPN49"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN49"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN5.inf b/src/bin/hamcore/inf/x64/INF_VPN5.inf
new file mode 100644
index 00000000..bed1d995
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN5.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN5.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN5.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN5.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN5
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN5"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN5.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN5"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN5.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN5.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN5"
+Neo.Service.DispName = "VPN Client Device Driver - VPN5"
+Neo.Service.Desc = "VPN Client Adapter - VPN5"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN5"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN50.inf b/src/bin/hamcore/inf/x64/INF_VPN50.inf
new file mode 100644
index 00000000..70b5b3ba
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN50.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN50.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN50.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN50.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN50
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN50"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN50.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN50"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN50.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN50.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN50"
+Neo.Service.DispName = "VPN Client Device Driver - VPN50"
+Neo.Service.Desc = "VPN Client Adapter - VPN50"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN50"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN51.inf b/src/bin/hamcore/inf/x64/INF_VPN51.inf
new file mode 100644
index 00000000..3c5f5142
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN51.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN51.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN51.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN51.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN51
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN51"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN51.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN51"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN51.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN51.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN51"
+Neo.Service.DispName = "VPN Client Device Driver - VPN51"
+Neo.Service.Desc = "VPN Client Adapter - VPN51"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN51"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN52.inf b/src/bin/hamcore/inf/x64/INF_VPN52.inf
new file mode 100644
index 00000000..78bee581
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN52.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN52.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN52.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN52.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN52
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN52"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN52.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN52"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN52.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN52.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN52"
+Neo.Service.DispName = "VPN Client Device Driver - VPN52"
+Neo.Service.Desc = "VPN Client Adapter - VPN52"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN52"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN53.inf b/src/bin/hamcore/inf/x64/INF_VPN53.inf
new file mode 100644
index 00000000..bc5a2b27
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN53.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN53.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN53.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN53.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN53
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN53"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN53.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN53"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN53.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN53.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN53"
+Neo.Service.DispName = "VPN Client Device Driver - VPN53"
+Neo.Service.Desc = "VPN Client Adapter - VPN53"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN53"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN54.inf b/src/bin/hamcore/inf/x64/INF_VPN54.inf
new file mode 100644
index 00000000..8ee9aeba
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN54.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN54.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN54.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN54.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN54
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN54"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN54.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN54"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN54.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN54.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN54"
+Neo.Service.DispName = "VPN Client Device Driver - VPN54"
+Neo.Service.Desc = "VPN Client Adapter - VPN54"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN54"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN55.inf b/src/bin/hamcore/inf/x64/INF_VPN55.inf
new file mode 100644
index 00000000..10d7025d
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN55.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN55.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN55.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN55.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN55
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN55"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN55.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN55"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN55.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN55.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN55"
+Neo.Service.DispName = "VPN Client Device Driver - VPN55"
+Neo.Service.Desc = "VPN Client Adapter - VPN55"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN55"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN56.inf b/src/bin/hamcore/inf/x64/INF_VPN56.inf
new file mode 100644
index 00000000..6b366ecc
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN56.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN56.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN56.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN56.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN56
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN56"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN56.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN56"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN56.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN56.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN56"
+Neo.Service.DispName = "VPN Client Device Driver - VPN56"
+Neo.Service.Desc = "VPN Client Adapter - VPN56"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN56"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN57.inf b/src/bin/hamcore/inf/x64/INF_VPN57.inf
new file mode 100644
index 00000000..1f9486d6
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN57.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN57.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN57.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN57.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN57
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN57"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN57.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN57"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN57.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN57.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN57"
+Neo.Service.DispName = "VPN Client Device Driver - VPN57"
+Neo.Service.Desc = "VPN Client Adapter - VPN57"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN57"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN58.inf b/src/bin/hamcore/inf/x64/INF_VPN58.inf
new file mode 100644
index 00000000..134b8706
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN58.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN58.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN58.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN58.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN58
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN58"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN58.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN58"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN58.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN58.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN58"
+Neo.Service.DispName = "VPN Client Device Driver - VPN58"
+Neo.Service.Desc = "VPN Client Adapter - VPN58"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN58"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN59.inf b/src/bin/hamcore/inf/x64/INF_VPN59.inf
new file mode 100644
index 00000000..6dbc950c
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN59.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN59.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN59.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN59.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN59
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN59"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN59.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN59"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN59.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN59.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN59"
+Neo.Service.DispName = "VPN Client Device Driver - VPN59"
+Neo.Service.Desc = "VPN Client Adapter - VPN59"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN59"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN6.inf b/src/bin/hamcore/inf/x64/INF_VPN6.inf
new file mode 100644
index 00000000..ea3c8dd2
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN6.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN6.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN6.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN6.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN6
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN6"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN6.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN6"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN6.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN6.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN6"
+Neo.Service.DispName = "VPN Client Device Driver - VPN6"
+Neo.Service.Desc = "VPN Client Adapter - VPN6"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN6"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN60.inf b/src/bin/hamcore/inf/x64/INF_VPN60.inf
new file mode 100644
index 00000000..3a6f57fb
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN60.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN60.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN60.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN60.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN60
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN60"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN60.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN60"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN60.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN60.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN60"
+Neo.Service.DispName = "VPN Client Device Driver - VPN60"
+Neo.Service.Desc = "VPN Client Adapter - VPN60"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN60"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN61.inf b/src/bin/hamcore/inf/x64/INF_VPN61.inf
new file mode 100644
index 00000000..f449da11
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN61.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN61.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN61.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN61.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN61
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN61"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN61.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN61"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN61.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN61.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN61"
+Neo.Service.DispName = "VPN Client Device Driver - VPN61"
+Neo.Service.Desc = "VPN Client Adapter - VPN61"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN61"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN62.inf b/src/bin/hamcore/inf/x64/INF_VPN62.inf
new file mode 100644
index 00000000..af64efd9
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN62.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN62.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN62.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN62.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN62
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN62"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN62.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN62"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN62.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN62.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN62"
+Neo.Service.DispName = "VPN Client Device Driver - VPN62"
+Neo.Service.Desc = "VPN Client Adapter - VPN62"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN62"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN63.inf b/src/bin/hamcore/inf/x64/INF_VPN63.inf
new file mode 100644
index 00000000..61003c87
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN63.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN63.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN63.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN63.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN63
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN63"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN63.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN63"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN63.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN63.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN63"
+Neo.Service.DispName = "VPN Client Device Driver - VPN63"
+Neo.Service.Desc = "VPN Client Adapter - VPN63"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN63"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN64.inf b/src/bin/hamcore/inf/x64/INF_VPN64.inf
new file mode 100644
index 00000000..0cbbb026
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN64.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN64.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN64.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN64.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN64
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN64"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN64.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN64"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN64.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN64.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN64"
+Neo.Service.DispName = "VPN Client Device Driver - VPN64"
+Neo.Service.Desc = "VPN Client Adapter - VPN64"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN64"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN65.inf b/src/bin/hamcore/inf/x64/INF_VPN65.inf
new file mode 100644
index 00000000..d964f291
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN65.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN65.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN65.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN65.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN65
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN65"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN65.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN65"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN65.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN65.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN65"
+Neo.Service.DispName = "VPN Client Device Driver - VPN65"
+Neo.Service.Desc = "VPN Client Adapter - VPN65"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN65"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN66.inf b/src/bin/hamcore/inf/x64/INF_VPN66.inf
new file mode 100644
index 00000000..bdefa0b1
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN66.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN66.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN66.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN66.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN66
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN66"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN66.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN66"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN66.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN66.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN66"
+Neo.Service.DispName = "VPN Client Device Driver - VPN66"
+Neo.Service.Desc = "VPN Client Adapter - VPN66"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN66"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN67.inf b/src/bin/hamcore/inf/x64/INF_VPN67.inf
new file mode 100644
index 00000000..7c04ab21
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN67.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN67.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN67.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN67.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN67
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN67"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN67.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN67"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN67.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN67.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN67"
+Neo.Service.DispName = "VPN Client Device Driver - VPN67"
+Neo.Service.Desc = "VPN Client Adapter - VPN67"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN67"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN68.inf b/src/bin/hamcore/inf/x64/INF_VPN68.inf
new file mode 100644
index 00000000..b8399a1f
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN68.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN68.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN68.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN68.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN68
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN68"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN68.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN68"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN68.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN68.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN68"
+Neo.Service.DispName = "VPN Client Device Driver - VPN68"
+Neo.Service.Desc = "VPN Client Adapter - VPN68"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN68"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN69.inf b/src/bin/hamcore/inf/x64/INF_VPN69.inf
new file mode 100644
index 00000000..fe6e62c8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN69.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN69.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN69.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN69.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN69
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN69"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN69.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN69"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN69.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN69.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN69"
+Neo.Service.DispName = "VPN Client Device Driver - VPN69"
+Neo.Service.Desc = "VPN Client Adapter - VPN69"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN69"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN7.inf b/src/bin/hamcore/inf/x64/INF_VPN7.inf
new file mode 100644
index 00000000..ebd49170
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN7.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN7.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN7.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN7.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN7
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN7"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN7.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN7"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN7.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN7.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN7"
+Neo.Service.DispName = "VPN Client Device Driver - VPN7"
+Neo.Service.Desc = "VPN Client Adapter - VPN7"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN7"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN70.inf b/src/bin/hamcore/inf/x64/INF_VPN70.inf
new file mode 100644
index 00000000..eef4a312
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN70.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN70.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN70.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN70.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN70
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN70"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN70.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN70"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN70.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN70.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN70"
+Neo.Service.DispName = "VPN Client Device Driver - VPN70"
+Neo.Service.Desc = "VPN Client Adapter - VPN70"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN70"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN71.inf b/src/bin/hamcore/inf/x64/INF_VPN71.inf
new file mode 100644
index 00000000..faba0678
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN71.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN71.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN71.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN71.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN71
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN71"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN71.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN71"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN71.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN71.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN71"
+Neo.Service.DispName = "VPN Client Device Driver - VPN71"
+Neo.Service.Desc = "VPN Client Adapter - VPN71"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN71"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN72.inf b/src/bin/hamcore/inf/x64/INF_VPN72.inf
new file mode 100644
index 00000000..b1c0a0fb
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN72.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN72.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN72.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN72.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN72
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN72"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN72.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN72"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN72.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN72.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN72"
+Neo.Service.DispName = "VPN Client Device Driver - VPN72"
+Neo.Service.Desc = "VPN Client Adapter - VPN72"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN72"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN73.inf b/src/bin/hamcore/inf/x64/INF_VPN73.inf
new file mode 100644
index 00000000..f5cbdc0b
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN73.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN73.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN73.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN73.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN73
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN73"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN73.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN73"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN73.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN73.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN73"
+Neo.Service.DispName = "VPN Client Device Driver - VPN73"
+Neo.Service.Desc = "VPN Client Adapter - VPN73"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN73"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN74.inf b/src/bin/hamcore/inf/x64/INF_VPN74.inf
new file mode 100644
index 00000000..0835ef75
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN74.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN74.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN74.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN74.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN74
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN74"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN74.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN74"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN74.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN74.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN74"
+Neo.Service.DispName = "VPN Client Device Driver - VPN74"
+Neo.Service.Desc = "VPN Client Adapter - VPN74"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN74"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN75.inf b/src/bin/hamcore/inf/x64/INF_VPN75.inf
new file mode 100644
index 00000000..63b4da79
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN75.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN75.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN75.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN75.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN75
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN75"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN75.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN75"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN75.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN75.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN75"
+Neo.Service.DispName = "VPN Client Device Driver - VPN75"
+Neo.Service.Desc = "VPN Client Adapter - VPN75"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN75"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN76.inf b/src/bin/hamcore/inf/x64/INF_VPN76.inf
new file mode 100644
index 00000000..fa12a196
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN76.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN76.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN76.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN76.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN76
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN76"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN76.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN76"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN76.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN76.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN76"
+Neo.Service.DispName = "VPN Client Device Driver - VPN76"
+Neo.Service.Desc = "VPN Client Adapter - VPN76"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN76"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN77.inf b/src/bin/hamcore/inf/x64/INF_VPN77.inf
new file mode 100644
index 00000000..4899e01b
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN77.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN77.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN77.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN77.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN77
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN77"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN77.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN77"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN77.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN77.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN77"
+Neo.Service.DispName = "VPN Client Device Driver - VPN77"
+Neo.Service.Desc = "VPN Client Adapter - VPN77"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN77"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN78.inf b/src/bin/hamcore/inf/x64/INF_VPN78.inf
new file mode 100644
index 00000000..c19dbba6
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN78.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN78.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN78.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN78.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN78
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN78"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN78.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN78"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN78.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN78.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN78"
+Neo.Service.DispName = "VPN Client Device Driver - VPN78"
+Neo.Service.Desc = "VPN Client Adapter - VPN78"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN78"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN79.inf b/src/bin/hamcore/inf/x64/INF_VPN79.inf
new file mode 100644
index 00000000..8906cbed
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN79.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN79.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN79.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN79.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN79
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN79"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN79.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN79"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN79.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN79.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN79"
+Neo.Service.DispName = "VPN Client Device Driver - VPN79"
+Neo.Service.Desc = "VPN Client Adapter - VPN79"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN79"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN8.inf b/src/bin/hamcore/inf/x64/INF_VPN8.inf
new file mode 100644
index 00000000..c08e63a9
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN8.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN8.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN8.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN8.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN8
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN8"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN8.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN8"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN8.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN8.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN8"
+Neo.Service.DispName = "VPN Client Device Driver - VPN8"
+Neo.Service.Desc = "VPN Client Adapter - VPN8"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN8"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN80.inf b/src/bin/hamcore/inf/x64/INF_VPN80.inf
new file mode 100644
index 00000000..b5728f7e
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN80.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN80.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN80.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN80.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN80
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN80"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN80.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN80"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN80.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN80.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN80"
+Neo.Service.DispName = "VPN Client Device Driver - VPN80"
+Neo.Service.Desc = "VPN Client Adapter - VPN80"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN80"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN81.inf b/src/bin/hamcore/inf/x64/INF_VPN81.inf
new file mode 100644
index 00000000..159e5f7f
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN81.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN81.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN81.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN81.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN81
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN81"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN81.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN81"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN81.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN81.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN81"
+Neo.Service.DispName = "VPN Client Device Driver - VPN81"
+Neo.Service.Desc = "VPN Client Adapter - VPN81"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN81"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN82.inf b/src/bin/hamcore/inf/x64/INF_VPN82.inf
new file mode 100644
index 00000000..733084dc
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN82.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN82.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN82.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN82.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN82
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN82"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN82.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN82"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN82.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN82.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN82"
+Neo.Service.DispName = "VPN Client Device Driver - VPN82"
+Neo.Service.Desc = "VPN Client Adapter - VPN82"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN82"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN83.inf b/src/bin/hamcore/inf/x64/INF_VPN83.inf
new file mode 100644
index 00000000..0563577f
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN83.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN83.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN83.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN83.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN83
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN83"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN83.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN83"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN83.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN83.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN83"
+Neo.Service.DispName = "VPN Client Device Driver - VPN83"
+Neo.Service.Desc = "VPN Client Adapter - VPN83"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN83"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN84.inf b/src/bin/hamcore/inf/x64/INF_VPN84.inf
new file mode 100644
index 00000000..98c220c8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN84.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN84.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN84.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN84.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN84
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN84"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN84.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN84"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN84.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN84.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN84"
+Neo.Service.DispName = "VPN Client Device Driver - VPN84"
+Neo.Service.Desc = "VPN Client Adapter - VPN84"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN84"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN85.inf b/src/bin/hamcore/inf/x64/INF_VPN85.inf
new file mode 100644
index 00000000..6669ac65
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN85.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN85.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN85.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN85.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN85
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN85"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN85.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN85"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN85.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN85.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN85"
+Neo.Service.DispName = "VPN Client Device Driver - VPN85"
+Neo.Service.Desc = "VPN Client Adapter - VPN85"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN85"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN86.inf b/src/bin/hamcore/inf/x64/INF_VPN86.inf
new file mode 100644
index 00000000..c4d3daf8
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN86.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN86.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN86.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN86.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN86
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN86"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN86.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN86"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN86.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN86.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN86"
+Neo.Service.DispName = "VPN Client Device Driver - VPN86"
+Neo.Service.Desc = "VPN Client Adapter - VPN86"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN86"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN87.inf b/src/bin/hamcore/inf/x64/INF_VPN87.inf
new file mode 100644
index 00000000..6a6a79e5
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN87.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN87.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN87.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN87.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN87
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN87"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN87.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN87"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN87.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN87.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN87"
+Neo.Service.DispName = "VPN Client Device Driver - VPN87"
+Neo.Service.Desc = "VPN Client Adapter - VPN87"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN87"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN88.inf b/src/bin/hamcore/inf/x64/INF_VPN88.inf
new file mode 100644
index 00000000..39f811c3
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN88.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN88.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN88.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN88.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN88
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN88"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN88.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN88"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN88.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN88.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN88"
+Neo.Service.DispName = "VPN Client Device Driver - VPN88"
+Neo.Service.Desc = "VPN Client Adapter - VPN88"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN88"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN89.inf b/src/bin/hamcore/inf/x64/INF_VPN89.inf
new file mode 100644
index 00000000..51a27d41
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN89.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN89.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN89.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN89.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN89
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN89"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN89.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN89"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN89.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN89.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN89"
+Neo.Service.DispName = "VPN Client Device Driver - VPN89"
+Neo.Service.Desc = "VPN Client Adapter - VPN89"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN89"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN9.inf b/src/bin/hamcore/inf/x64/INF_VPN9.inf
new file mode 100644
index 00000000..94fc032e
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN9.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN9.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN9.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN9.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN9
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN9"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN9.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN9"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN9.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN9.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN9"
+Neo.Service.DispName = "VPN Client Device Driver - VPN9"
+Neo.Service.Desc = "VPN Client Adapter - VPN9"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN9"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN90.inf b/src/bin/hamcore/inf/x64/INF_VPN90.inf
new file mode 100644
index 00000000..943f493c
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN90.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN90.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN90.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN90.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN90
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN90"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN90.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN90"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN90.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN90.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN90"
+Neo.Service.DispName = "VPN Client Device Driver - VPN90"
+Neo.Service.Desc = "VPN Client Adapter - VPN90"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN90"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN91.inf b/src/bin/hamcore/inf/x64/INF_VPN91.inf
new file mode 100644
index 00000000..31903d22
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN91.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN91.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN91.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN91.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN91
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN91"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN91.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN91"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN91.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN91.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN91"
+Neo.Service.DispName = "VPN Client Device Driver - VPN91"
+Neo.Service.Desc = "VPN Client Adapter - VPN91"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN91"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN92.inf b/src/bin/hamcore/inf/x64/INF_VPN92.inf
new file mode 100644
index 00000000..0884fb4b
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN92.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN92.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN92.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN92.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN92
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN92"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN92.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN92"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN92.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN92.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN92"
+Neo.Service.DispName = "VPN Client Device Driver - VPN92"
+Neo.Service.Desc = "VPN Client Adapter - VPN92"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN92"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN93.inf b/src/bin/hamcore/inf/x64/INF_VPN93.inf
new file mode 100644
index 00000000..bdffef42
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN93.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN93.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN93.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN93.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN93
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN93"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN93.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN93"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN93.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN93.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN93"
+Neo.Service.DispName = "VPN Client Device Driver - VPN93"
+Neo.Service.Desc = "VPN Client Adapter - VPN93"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN93"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN94.inf b/src/bin/hamcore/inf/x64/INF_VPN94.inf
new file mode 100644
index 00000000..451e50df
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN94.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN94.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN94.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN94.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN94
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN94"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN94.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN94"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN94.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN94.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN94"
+Neo.Service.DispName = "VPN Client Device Driver - VPN94"
+Neo.Service.Desc = "VPN Client Adapter - VPN94"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN94"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN95.inf b/src/bin/hamcore/inf/x64/INF_VPN95.inf
new file mode 100644
index 00000000..6588e6cd
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN95.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN95.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN95.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN95.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN95
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN95"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN95.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN95"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN95.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN95.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN95"
+Neo.Service.DispName = "VPN Client Device Driver - VPN95"
+Neo.Service.Desc = "VPN Client Adapter - VPN95"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN95"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN96.inf b/src/bin/hamcore/inf/x64/INF_VPN96.inf
new file mode 100644
index 00000000..f722a2ba
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN96.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN96.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN96.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN96.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN96
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN96"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN96.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN96"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN96.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN96.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN96"
+Neo.Service.DispName = "VPN Client Device Driver - VPN96"
+Neo.Service.Desc = "VPN Client Adapter - VPN96"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN96"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN97.inf b/src/bin/hamcore/inf/x64/INF_VPN97.inf
new file mode 100644
index 00000000..c130a603
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN97.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN97.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN97.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN97.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN97
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN97"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN97.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN97"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN97.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN97.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN97"
+Neo.Service.DispName = "VPN Client Device Driver - VPN97"
+Neo.Service.Desc = "VPN Client Adapter - VPN97"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN97"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN98.inf b/src/bin/hamcore/inf/x64/INF_VPN98.inf
new file mode 100644
index 00000000..4d6b3866
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN98.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN98.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN98.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN98.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN98
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN98"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN98.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN98"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN98.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN98.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN98"
+Neo.Service.DispName = "VPN Client Device Driver - VPN98"
+Neo.Service.Desc = "VPN Client Adapter - VPN98"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN98"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/INF_VPN99.inf b/src/bin/hamcore/inf/x64/INF_VPN99.inf
new file mode 100644
index 00000000..34e417f6
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/INF_VPN99.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN99.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN99.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN99.sys, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN99
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN99"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN99.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN99"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN99.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN99.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN99"
+Neo.Service.DispName = "VPN Client Device Driver - VPN99"
+Neo.Service.Desc = "VPN Client Adapter - VPN99"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN99"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x64/inf.cat b/src/bin/hamcore/inf/x64/inf.cat
new file mode 100644
index 00000000..ba9317ba
--- /dev/null
+++ b/src/bin/hamcore/inf/x64/inf.cat
Binary files differ
diff --git a/src/bin/hamcore/inf/x86/INF_VPN.inf b/src/bin/hamcore/inf/x86/INF_VPN.inf
new file mode 100644
index 00000000..1d0e25ea
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN"
+Neo.Service.DispName = "VPN Client Device Driver - VPN"
+Neo.Service.Desc = "VPN Client Adapter - VPN"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN10.inf b/src/bin/hamcore/inf/x86/INF_VPN10.inf
new file mode 100644
index 00000000..d1bce86d
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN10.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN10.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN10.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN10.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN10
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN10"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN10.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN10"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN10.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN10.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN10"
+Neo.Service.DispName = "VPN Client Device Driver - VPN10"
+Neo.Service.Desc = "VPN Client Adapter - VPN10"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN10"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN100.inf b/src/bin/hamcore/inf/x86/INF_VPN100.inf
new file mode 100644
index 00000000..63588c1b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN100.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN100.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN100.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN100.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN100
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN100"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN100.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN100"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN100.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN100.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN100"
+Neo.Service.DispName = "VPN Client Device Driver - VPN100"
+Neo.Service.Desc = "VPN Client Adapter - VPN100"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN100"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN101.inf b/src/bin/hamcore/inf/x86/INF_VPN101.inf
new file mode 100644
index 00000000..b43fa01b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN101.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN101.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN101.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN101.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN101
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN101"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN101.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN101"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN101.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN101.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN101"
+Neo.Service.DispName = "VPN Client Device Driver - VPN101"
+Neo.Service.Desc = "VPN Client Adapter - VPN101"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN101"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN102.inf b/src/bin/hamcore/inf/x86/INF_VPN102.inf
new file mode 100644
index 00000000..ae84696a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN102.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN102.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN102.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN102.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN102
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN102"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN102.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN102"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN102.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN102.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN102"
+Neo.Service.DispName = "VPN Client Device Driver - VPN102"
+Neo.Service.Desc = "VPN Client Adapter - VPN102"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN102"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN103.inf b/src/bin/hamcore/inf/x86/INF_VPN103.inf
new file mode 100644
index 00000000..ad2589f8
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN103.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN103.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN103.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN103.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN103
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN103"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN103.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN103"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN103.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN103.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN103"
+Neo.Service.DispName = "VPN Client Device Driver - VPN103"
+Neo.Service.Desc = "VPN Client Adapter - VPN103"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN103"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN104.inf b/src/bin/hamcore/inf/x86/INF_VPN104.inf
new file mode 100644
index 00000000..85cde04a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN104.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN104.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN104.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN104.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN104
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN104"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN104.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN104"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN104.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN104.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN104"
+Neo.Service.DispName = "VPN Client Device Driver - VPN104"
+Neo.Service.Desc = "VPN Client Adapter - VPN104"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN104"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN105.inf b/src/bin/hamcore/inf/x86/INF_VPN105.inf
new file mode 100644
index 00000000..31142251
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN105.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN105.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN105.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN105.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN105
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN105"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN105.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN105"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN105.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN105.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN105"
+Neo.Service.DispName = "VPN Client Device Driver - VPN105"
+Neo.Service.Desc = "VPN Client Adapter - VPN105"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN105"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN106.inf b/src/bin/hamcore/inf/x86/INF_VPN106.inf
new file mode 100644
index 00000000..1671be64
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN106.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN106.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN106.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN106.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN106
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN106"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN106.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN106"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN106.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN106.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN106"
+Neo.Service.DispName = "VPN Client Device Driver - VPN106"
+Neo.Service.Desc = "VPN Client Adapter - VPN106"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN106"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN107.inf b/src/bin/hamcore/inf/x86/INF_VPN107.inf
new file mode 100644
index 00000000..167aa857
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN107.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN107.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN107.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN107.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN107
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN107"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN107.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN107"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN107.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN107.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN107"
+Neo.Service.DispName = "VPN Client Device Driver - VPN107"
+Neo.Service.Desc = "VPN Client Adapter - VPN107"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN107"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN108.inf b/src/bin/hamcore/inf/x86/INF_VPN108.inf
new file mode 100644
index 00000000..59d63a5e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN108.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN108.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN108.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN108.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN108
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN108"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN108.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN108"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN108.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN108.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN108"
+Neo.Service.DispName = "VPN Client Device Driver - VPN108"
+Neo.Service.Desc = "VPN Client Adapter - VPN108"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN108"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN109.inf b/src/bin/hamcore/inf/x86/INF_VPN109.inf
new file mode 100644
index 00000000..6549e6ad
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN109.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN109.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN109.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN109.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN109
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN109"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN109.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN109"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN109.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN109.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN109"
+Neo.Service.DispName = "VPN Client Device Driver - VPN109"
+Neo.Service.Desc = "VPN Client Adapter - VPN109"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN109"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN11.inf b/src/bin/hamcore/inf/x86/INF_VPN11.inf
new file mode 100644
index 00000000..675df209
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN11.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN11.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN11.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN11.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN11
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN11"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN11.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN11"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN11.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN11.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN11"
+Neo.Service.DispName = "VPN Client Device Driver - VPN11"
+Neo.Service.Desc = "VPN Client Adapter - VPN11"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN11"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN110.inf b/src/bin/hamcore/inf/x86/INF_VPN110.inf
new file mode 100644
index 00000000..7eb6bbb0
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN110.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN110.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN110.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN110.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN110
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN110"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN110.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN110"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN110.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN110.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN110"
+Neo.Service.DispName = "VPN Client Device Driver - VPN110"
+Neo.Service.Desc = "VPN Client Adapter - VPN110"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN110"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN111.inf b/src/bin/hamcore/inf/x86/INF_VPN111.inf
new file mode 100644
index 00000000..da959730
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN111.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN111.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN111.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN111.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN111
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN111"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN111.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN111"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN111.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN111.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN111"
+Neo.Service.DispName = "VPN Client Device Driver - VPN111"
+Neo.Service.Desc = "VPN Client Adapter - VPN111"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN111"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN112.inf b/src/bin/hamcore/inf/x86/INF_VPN112.inf
new file mode 100644
index 00000000..80dc2d4e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN112.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN112.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN112.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN112.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN112
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN112"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN112.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN112"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN112.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN112.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN112"
+Neo.Service.DispName = "VPN Client Device Driver - VPN112"
+Neo.Service.Desc = "VPN Client Adapter - VPN112"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN112"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN113.inf b/src/bin/hamcore/inf/x86/INF_VPN113.inf
new file mode 100644
index 00000000..878b341a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN113.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN113.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN113.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN113.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN113
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN113"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN113.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN113"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN113.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN113.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN113"
+Neo.Service.DispName = "VPN Client Device Driver - VPN113"
+Neo.Service.Desc = "VPN Client Adapter - VPN113"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN113"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN114.inf b/src/bin/hamcore/inf/x86/INF_VPN114.inf
new file mode 100644
index 00000000..e8748149
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN114.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN114.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN114.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN114.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN114
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN114"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN114.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN114"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN114.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN114.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN114"
+Neo.Service.DispName = "VPN Client Device Driver - VPN114"
+Neo.Service.Desc = "VPN Client Adapter - VPN114"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN114"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN115.inf b/src/bin/hamcore/inf/x86/INF_VPN115.inf
new file mode 100644
index 00000000..73fad6c6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN115.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN115.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN115.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN115.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN115
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN115"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN115.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN115"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN115.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN115.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN115"
+Neo.Service.DispName = "VPN Client Device Driver - VPN115"
+Neo.Service.Desc = "VPN Client Adapter - VPN115"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN115"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN116.inf b/src/bin/hamcore/inf/x86/INF_VPN116.inf
new file mode 100644
index 00000000..41624c29
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN116.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN116.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN116.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN116.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN116
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN116"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN116.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN116"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN116.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN116.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN116"
+Neo.Service.DispName = "VPN Client Device Driver - VPN116"
+Neo.Service.Desc = "VPN Client Adapter - VPN116"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN116"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN117.inf b/src/bin/hamcore/inf/x86/INF_VPN117.inf
new file mode 100644
index 00000000..bfc619d5
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN117.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN117.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN117.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN117.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN117
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN117"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN117.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN117"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN117.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN117.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN117"
+Neo.Service.DispName = "VPN Client Device Driver - VPN117"
+Neo.Service.Desc = "VPN Client Adapter - VPN117"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN117"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN118.inf b/src/bin/hamcore/inf/x86/INF_VPN118.inf
new file mode 100644
index 00000000..ac37a376
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN118.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN118.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN118.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN118.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN118
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN118"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN118.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN118"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN118.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN118.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN118"
+Neo.Service.DispName = "VPN Client Device Driver - VPN118"
+Neo.Service.Desc = "VPN Client Adapter - VPN118"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN118"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN119.inf b/src/bin/hamcore/inf/x86/INF_VPN119.inf
new file mode 100644
index 00000000..c99c9e9c
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN119.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN119.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN119.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN119.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN119
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN119"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN119.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN119"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN119.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN119.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN119"
+Neo.Service.DispName = "VPN Client Device Driver - VPN119"
+Neo.Service.Desc = "VPN Client Adapter - VPN119"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN119"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN12.inf b/src/bin/hamcore/inf/x86/INF_VPN12.inf
new file mode 100644
index 00000000..b10573ea
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN12.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN12.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN12.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN12.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN12
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN12"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN12.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN12"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN12.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN12.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN12"
+Neo.Service.DispName = "VPN Client Device Driver - VPN12"
+Neo.Service.Desc = "VPN Client Adapter - VPN12"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN12"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN120.inf b/src/bin/hamcore/inf/x86/INF_VPN120.inf
new file mode 100644
index 00000000..2671a95d
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN120.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN120.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN120.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN120.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN120
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN120"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN120.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN120"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN120.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN120.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN120"
+Neo.Service.DispName = "VPN Client Device Driver - VPN120"
+Neo.Service.Desc = "VPN Client Adapter - VPN120"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN120"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN121.inf b/src/bin/hamcore/inf/x86/INF_VPN121.inf
new file mode 100644
index 00000000..f1ed369d
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN121.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN121.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN121.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN121.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN121
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN121"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN121.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN121"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN121.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN121.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN121"
+Neo.Service.DispName = "VPN Client Device Driver - VPN121"
+Neo.Service.Desc = "VPN Client Adapter - VPN121"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN121"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN122.inf b/src/bin/hamcore/inf/x86/INF_VPN122.inf
new file mode 100644
index 00000000..4f07c685
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN122.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN122.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN122.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN122.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN122
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN122"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN122.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN122"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN122.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN122.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN122"
+Neo.Service.DispName = "VPN Client Device Driver - VPN122"
+Neo.Service.Desc = "VPN Client Adapter - VPN122"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN122"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN123.inf b/src/bin/hamcore/inf/x86/INF_VPN123.inf
new file mode 100644
index 00000000..97914dbe
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN123.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN123.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN123.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN123.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN123
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN123"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN123.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN123"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN123.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN123.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN123"
+Neo.Service.DispName = "VPN Client Device Driver - VPN123"
+Neo.Service.Desc = "VPN Client Adapter - VPN123"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN123"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN124.inf b/src/bin/hamcore/inf/x86/INF_VPN124.inf
new file mode 100644
index 00000000..6f25063e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN124.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN124.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN124.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN124.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN124
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN124"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN124.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN124"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN124.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN124.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN124"
+Neo.Service.DispName = "VPN Client Device Driver - VPN124"
+Neo.Service.Desc = "VPN Client Adapter - VPN124"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN124"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN125.inf b/src/bin/hamcore/inf/x86/INF_VPN125.inf
new file mode 100644
index 00000000..a066f937
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN125.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN125.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN125.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN125.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN125
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN125"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN125.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN125"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN125.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN125.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN125"
+Neo.Service.DispName = "VPN Client Device Driver - VPN125"
+Neo.Service.Desc = "VPN Client Adapter - VPN125"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN125"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN126.inf b/src/bin/hamcore/inf/x86/INF_VPN126.inf
new file mode 100644
index 00000000..2e184d20
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN126.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN126.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN126.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN126.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN126
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN126"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN126.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN126"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN126.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN126.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN126"
+Neo.Service.DispName = "VPN Client Device Driver - VPN126"
+Neo.Service.Desc = "VPN Client Adapter - VPN126"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN126"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN127.inf b/src/bin/hamcore/inf/x86/INF_VPN127.inf
new file mode 100644
index 00000000..e4f2dde1
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN127.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN127.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN127.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN127.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN127
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN127"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN127.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN127"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN127.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN127.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN127"
+Neo.Service.DispName = "VPN Client Device Driver - VPN127"
+Neo.Service.Desc = "VPN Client Adapter - VPN127"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN127"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN13.inf b/src/bin/hamcore/inf/x86/INF_VPN13.inf
new file mode 100644
index 00000000..5786598a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN13.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN13.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN13.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN13.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN13
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN13"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN13.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN13"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN13.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN13.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN13"
+Neo.Service.DispName = "VPN Client Device Driver - VPN13"
+Neo.Service.Desc = "VPN Client Adapter - VPN13"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN13"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN14.inf b/src/bin/hamcore/inf/x86/INF_VPN14.inf
new file mode 100644
index 00000000..e248a65b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN14.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN14.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN14.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN14.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN14
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN14"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN14.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN14"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN14.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN14.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN14"
+Neo.Service.DispName = "VPN Client Device Driver - VPN14"
+Neo.Service.Desc = "VPN Client Adapter - VPN14"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN14"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN15.inf b/src/bin/hamcore/inf/x86/INF_VPN15.inf
new file mode 100644
index 00000000..ef291478
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN15.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN15.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN15.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN15.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN15
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN15"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN15.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN15"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN15.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN15.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN15"
+Neo.Service.DispName = "VPN Client Device Driver - VPN15"
+Neo.Service.Desc = "VPN Client Adapter - VPN15"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN15"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN16.inf b/src/bin/hamcore/inf/x86/INF_VPN16.inf
new file mode 100644
index 00000000..228dd419
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN16.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN16.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN16.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN16.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN16
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN16"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN16.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN16"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN16.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN16.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN16"
+Neo.Service.DispName = "VPN Client Device Driver - VPN16"
+Neo.Service.Desc = "VPN Client Adapter - VPN16"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN16"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN17.inf b/src/bin/hamcore/inf/x86/INF_VPN17.inf
new file mode 100644
index 00000000..5ce57122
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN17.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN17.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN17.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN17.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN17
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN17"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN17.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN17"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN17.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN17.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN17"
+Neo.Service.DispName = "VPN Client Device Driver - VPN17"
+Neo.Service.Desc = "VPN Client Adapter - VPN17"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN17"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN18.inf b/src/bin/hamcore/inf/x86/INF_VPN18.inf
new file mode 100644
index 00000000..d683b623
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN18.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN18.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN18.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN18.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN18
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN18"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN18.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN18"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN18.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN18.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN18"
+Neo.Service.DispName = "VPN Client Device Driver - VPN18"
+Neo.Service.Desc = "VPN Client Adapter - VPN18"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN18"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN19.inf b/src/bin/hamcore/inf/x86/INF_VPN19.inf
new file mode 100644
index 00000000..2062598e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN19.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN19.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN19.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN19.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN19
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN19"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN19.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN19"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN19.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN19.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN19"
+Neo.Service.DispName = "VPN Client Device Driver - VPN19"
+Neo.Service.Desc = "VPN Client Adapter - VPN19"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN19"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN2.inf b/src/bin/hamcore/inf/x86/INF_VPN2.inf
new file mode 100644
index 00000000..3d9c7d32
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN2.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN2.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN2.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN2.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN2
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN2"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN2.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN2"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN2.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN2.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN2"
+Neo.Service.DispName = "VPN Client Device Driver - VPN2"
+Neo.Service.Desc = "VPN Client Adapter - VPN2"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN2"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN20.inf b/src/bin/hamcore/inf/x86/INF_VPN20.inf
new file mode 100644
index 00000000..61af4fa7
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN20.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN20.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN20.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN20.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN20
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN20"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN20.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN20"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN20.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN20.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN20"
+Neo.Service.DispName = "VPN Client Device Driver - VPN20"
+Neo.Service.Desc = "VPN Client Adapter - VPN20"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN20"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN21.inf b/src/bin/hamcore/inf/x86/INF_VPN21.inf
new file mode 100644
index 00000000..4da81b6a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN21.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN21.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN21.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN21.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN21
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN21"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN21.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN21"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN21.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN21.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN21"
+Neo.Service.DispName = "VPN Client Device Driver - VPN21"
+Neo.Service.Desc = "VPN Client Adapter - VPN21"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN21"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN22.inf b/src/bin/hamcore/inf/x86/INF_VPN22.inf
new file mode 100644
index 00000000..a879f6db
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN22.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN22.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN22.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN22.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN22
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN22"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN22.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN22"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN22.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN22.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN22"
+Neo.Service.DispName = "VPN Client Device Driver - VPN22"
+Neo.Service.Desc = "VPN Client Adapter - VPN22"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN22"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN23.inf b/src/bin/hamcore/inf/x86/INF_VPN23.inf
new file mode 100644
index 00000000..526f68af
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN23.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN23.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN23.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN23.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN23
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN23"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN23.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN23"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN23.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN23.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN23"
+Neo.Service.DispName = "VPN Client Device Driver - VPN23"
+Neo.Service.Desc = "VPN Client Adapter - VPN23"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN23"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN24.inf b/src/bin/hamcore/inf/x86/INF_VPN24.inf
new file mode 100644
index 00000000..721459f6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN24.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN24.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN24.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN24.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN24
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN24"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN24.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN24"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN24.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN24.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN24"
+Neo.Service.DispName = "VPN Client Device Driver - VPN24"
+Neo.Service.Desc = "VPN Client Adapter - VPN24"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN24"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN25.inf b/src/bin/hamcore/inf/x86/INF_VPN25.inf
new file mode 100644
index 00000000..70fb577b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN25.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN25.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN25.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN25.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN25
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN25"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN25.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN25"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN25.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN25.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN25"
+Neo.Service.DispName = "VPN Client Device Driver - VPN25"
+Neo.Service.Desc = "VPN Client Adapter - VPN25"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN25"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN26.inf b/src/bin/hamcore/inf/x86/INF_VPN26.inf
new file mode 100644
index 00000000..54f16908
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN26.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN26.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN26.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN26.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN26
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN26"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN26.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN26"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN26.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN26.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN26"
+Neo.Service.DispName = "VPN Client Device Driver - VPN26"
+Neo.Service.Desc = "VPN Client Adapter - VPN26"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN26"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN27.inf b/src/bin/hamcore/inf/x86/INF_VPN27.inf
new file mode 100644
index 00000000..6da94965
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN27.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN27.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN27.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN27.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN27
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN27"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN27.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN27"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN27.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN27.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN27"
+Neo.Service.DispName = "VPN Client Device Driver - VPN27"
+Neo.Service.Desc = "VPN Client Adapter - VPN27"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN27"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN28.inf b/src/bin/hamcore/inf/x86/INF_VPN28.inf
new file mode 100644
index 00000000..2d0f7657
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN28.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN28.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN28.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN28.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN28
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN28"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN28.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN28"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN28.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN28.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN28"
+Neo.Service.DispName = "VPN Client Device Driver - VPN28"
+Neo.Service.Desc = "VPN Client Adapter - VPN28"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN28"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN29.inf b/src/bin/hamcore/inf/x86/INF_VPN29.inf
new file mode 100644
index 00000000..8da46dd5
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN29.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN29.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN29.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN29.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN29
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN29"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN29.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN29"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN29.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN29.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN29"
+Neo.Service.DispName = "VPN Client Device Driver - VPN29"
+Neo.Service.Desc = "VPN Client Adapter - VPN29"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN29"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN3.inf b/src/bin/hamcore/inf/x86/INF_VPN3.inf
new file mode 100644
index 00000000..41591cdb
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN3.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN3.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN3.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN3.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN3
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN3"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN3.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN3"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN3.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN3.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN3"
+Neo.Service.DispName = "VPN Client Device Driver - VPN3"
+Neo.Service.Desc = "VPN Client Adapter - VPN3"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN3"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN30.inf b/src/bin/hamcore/inf/x86/INF_VPN30.inf
new file mode 100644
index 00000000..2152d86b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN30.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN30.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN30.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN30.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN30
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN30"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN30.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN30"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN30.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN30.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN30"
+Neo.Service.DispName = "VPN Client Device Driver - VPN30"
+Neo.Service.Desc = "VPN Client Adapter - VPN30"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN30"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN31.inf b/src/bin/hamcore/inf/x86/INF_VPN31.inf
new file mode 100644
index 00000000..c87cf7f5
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN31.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN31.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN31.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN31.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN31
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN31"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN31.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN31"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN31.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN31.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN31"
+Neo.Service.DispName = "VPN Client Device Driver - VPN31"
+Neo.Service.Desc = "VPN Client Adapter - VPN31"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN31"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN32.inf b/src/bin/hamcore/inf/x86/INF_VPN32.inf
new file mode 100644
index 00000000..d6a8509c
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN32.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN32.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN32.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN32.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN32
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN32"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN32.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN32"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN32.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN32.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN32"
+Neo.Service.DispName = "VPN Client Device Driver - VPN32"
+Neo.Service.Desc = "VPN Client Adapter - VPN32"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN32"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN33.inf b/src/bin/hamcore/inf/x86/INF_VPN33.inf
new file mode 100644
index 00000000..9289d1ab
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN33.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN33.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN33.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN33.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN33
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN33"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN33.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN33"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN33.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN33.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN33"
+Neo.Service.DispName = "VPN Client Device Driver - VPN33"
+Neo.Service.Desc = "VPN Client Adapter - VPN33"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN33"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN34.inf b/src/bin/hamcore/inf/x86/INF_VPN34.inf
new file mode 100644
index 00000000..6d7dd4d1
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN34.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN34.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN34.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN34.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN34
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN34"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN34.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN34"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN34.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN34.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN34"
+Neo.Service.DispName = "VPN Client Device Driver - VPN34"
+Neo.Service.Desc = "VPN Client Adapter - VPN34"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN34"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN35.inf b/src/bin/hamcore/inf/x86/INF_VPN35.inf
new file mode 100644
index 00000000..dc0ee1a8
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN35.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN35.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN35.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN35.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN35
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN35"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN35.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN35"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN35.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN35.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN35"
+Neo.Service.DispName = "VPN Client Device Driver - VPN35"
+Neo.Service.Desc = "VPN Client Adapter - VPN35"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN35"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN36.inf b/src/bin/hamcore/inf/x86/INF_VPN36.inf
new file mode 100644
index 00000000..938521e8
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN36.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN36.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN36.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN36.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN36
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN36"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN36.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN36"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN36.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN36.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN36"
+Neo.Service.DispName = "VPN Client Device Driver - VPN36"
+Neo.Service.Desc = "VPN Client Adapter - VPN36"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN36"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN37.inf b/src/bin/hamcore/inf/x86/INF_VPN37.inf
new file mode 100644
index 00000000..b3c52a7e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN37.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN37.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN37.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN37.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN37
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN37"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN37.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN37"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN37.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN37.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN37"
+Neo.Service.DispName = "VPN Client Device Driver - VPN37"
+Neo.Service.Desc = "VPN Client Adapter - VPN37"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN37"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN38.inf b/src/bin/hamcore/inf/x86/INF_VPN38.inf
new file mode 100644
index 00000000..71dbad9f
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN38.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN38.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN38.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN38.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN38
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN38"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN38.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN38"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN38.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN38.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN38"
+Neo.Service.DispName = "VPN Client Device Driver - VPN38"
+Neo.Service.Desc = "VPN Client Adapter - VPN38"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN38"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN39.inf b/src/bin/hamcore/inf/x86/INF_VPN39.inf
new file mode 100644
index 00000000..ce278cbc
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN39.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN39.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN39.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN39.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN39
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN39"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN39.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN39"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN39.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN39.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN39"
+Neo.Service.DispName = "VPN Client Device Driver - VPN39"
+Neo.Service.Desc = "VPN Client Adapter - VPN39"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN39"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN4.inf b/src/bin/hamcore/inf/x86/INF_VPN4.inf
new file mode 100644
index 00000000..c6560298
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN4.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN4.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN4.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN4.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN4
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN4"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN4.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN4"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN4.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN4.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN4"
+Neo.Service.DispName = "VPN Client Device Driver - VPN4"
+Neo.Service.Desc = "VPN Client Adapter - VPN4"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN4"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN40.inf b/src/bin/hamcore/inf/x86/INF_VPN40.inf
new file mode 100644
index 00000000..bfeb3040
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN40.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN40.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN40.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN40.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN40
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN40"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN40.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN40"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN40.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN40.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN40"
+Neo.Service.DispName = "VPN Client Device Driver - VPN40"
+Neo.Service.Desc = "VPN Client Adapter - VPN40"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN40"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN41.inf b/src/bin/hamcore/inf/x86/INF_VPN41.inf
new file mode 100644
index 00000000..81aee50b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN41.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN41.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN41.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN41.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN41
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN41"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN41.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN41"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN41.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN41.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN41"
+Neo.Service.DispName = "VPN Client Device Driver - VPN41"
+Neo.Service.Desc = "VPN Client Adapter - VPN41"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN41"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN42.inf b/src/bin/hamcore/inf/x86/INF_VPN42.inf
new file mode 100644
index 00000000..c77acc79
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN42.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN42.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN42.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN42.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN42
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN42"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN42.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN42"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN42.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN42.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN42"
+Neo.Service.DispName = "VPN Client Device Driver - VPN42"
+Neo.Service.Desc = "VPN Client Adapter - VPN42"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN42"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN43.inf b/src/bin/hamcore/inf/x86/INF_VPN43.inf
new file mode 100644
index 00000000..34e914ec
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN43.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN43.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN43.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN43.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN43
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN43"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN43.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN43"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN43.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN43.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN43"
+Neo.Service.DispName = "VPN Client Device Driver - VPN43"
+Neo.Service.Desc = "VPN Client Adapter - VPN43"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN43"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN44.inf b/src/bin/hamcore/inf/x86/INF_VPN44.inf
new file mode 100644
index 00000000..511ebf58
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN44.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN44.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN44.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN44.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN44
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN44"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN44.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN44"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN44.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN44.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN44"
+Neo.Service.DispName = "VPN Client Device Driver - VPN44"
+Neo.Service.Desc = "VPN Client Adapter - VPN44"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN44"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN45.inf b/src/bin/hamcore/inf/x86/INF_VPN45.inf
new file mode 100644
index 00000000..0aef6dd4
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN45.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN45.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN45.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN45.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN45
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN45"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN45.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN45"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN45.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN45.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN45"
+Neo.Service.DispName = "VPN Client Device Driver - VPN45"
+Neo.Service.Desc = "VPN Client Adapter - VPN45"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN45"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN46.inf b/src/bin/hamcore/inf/x86/INF_VPN46.inf
new file mode 100644
index 00000000..9fa07090
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN46.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN46.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN46.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN46.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN46
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN46"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN46.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN46"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN46.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN46.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN46"
+Neo.Service.DispName = "VPN Client Device Driver - VPN46"
+Neo.Service.Desc = "VPN Client Adapter - VPN46"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN46"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN47.inf b/src/bin/hamcore/inf/x86/INF_VPN47.inf
new file mode 100644
index 00000000..127988e6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN47.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN47.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN47.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN47.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN47
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN47"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN47.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN47"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN47.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN47.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN47"
+Neo.Service.DispName = "VPN Client Device Driver - VPN47"
+Neo.Service.Desc = "VPN Client Adapter - VPN47"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN47"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN48.inf b/src/bin/hamcore/inf/x86/INF_VPN48.inf
new file mode 100644
index 00000000..8ff0b724
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN48.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN48.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN48.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN48.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN48
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN48"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN48.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN48"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN48.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN48.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN48"
+Neo.Service.DispName = "VPN Client Device Driver - VPN48"
+Neo.Service.Desc = "VPN Client Adapter - VPN48"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN48"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN49.inf b/src/bin/hamcore/inf/x86/INF_VPN49.inf
new file mode 100644
index 00000000..18b245dd
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN49.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN49.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN49.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN49.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN49
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN49"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN49.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN49"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN49.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN49.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN49"
+Neo.Service.DispName = "VPN Client Device Driver - VPN49"
+Neo.Service.Desc = "VPN Client Adapter - VPN49"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN49"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN5.inf b/src/bin/hamcore/inf/x86/INF_VPN5.inf
new file mode 100644
index 00000000..6d299ac6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN5.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN5.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN5.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN5.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN5
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN5"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN5.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN5"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN5.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN5.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN5"
+Neo.Service.DispName = "VPN Client Device Driver - VPN5"
+Neo.Service.Desc = "VPN Client Adapter - VPN5"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN5"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN50.inf b/src/bin/hamcore/inf/x86/INF_VPN50.inf
new file mode 100644
index 00000000..d7f45d57
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN50.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN50.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN50.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN50.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN50
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN50"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN50.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN50"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN50.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN50.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN50"
+Neo.Service.DispName = "VPN Client Device Driver - VPN50"
+Neo.Service.Desc = "VPN Client Adapter - VPN50"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN50"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN51.inf b/src/bin/hamcore/inf/x86/INF_VPN51.inf
new file mode 100644
index 00000000..4a2bb221
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN51.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN51.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN51.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN51.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN51
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN51"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN51.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN51"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN51.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN51.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN51"
+Neo.Service.DispName = "VPN Client Device Driver - VPN51"
+Neo.Service.Desc = "VPN Client Adapter - VPN51"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN51"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN52.inf b/src/bin/hamcore/inf/x86/INF_VPN52.inf
new file mode 100644
index 00000000..22256633
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN52.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN52.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN52.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN52.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN52
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN52"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN52.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN52"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN52.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN52.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN52"
+Neo.Service.DispName = "VPN Client Device Driver - VPN52"
+Neo.Service.Desc = "VPN Client Adapter - VPN52"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN52"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN53.inf b/src/bin/hamcore/inf/x86/INF_VPN53.inf
new file mode 100644
index 00000000..36256a05
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN53.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN53.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN53.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN53.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN53
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN53"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN53.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN53"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN53.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN53.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN53"
+Neo.Service.DispName = "VPN Client Device Driver - VPN53"
+Neo.Service.Desc = "VPN Client Adapter - VPN53"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN53"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN54.inf b/src/bin/hamcore/inf/x86/INF_VPN54.inf
new file mode 100644
index 00000000..e8b0b395
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN54.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN54.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN54.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN54.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN54
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN54"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN54.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN54"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN54.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN54.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN54"
+Neo.Service.DispName = "VPN Client Device Driver - VPN54"
+Neo.Service.Desc = "VPN Client Adapter - VPN54"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN54"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN55.inf b/src/bin/hamcore/inf/x86/INF_VPN55.inf
new file mode 100644
index 00000000..bcd6aff3
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN55.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN55.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN55.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN55.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN55
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN55"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN55.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN55"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN55.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN55.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN55"
+Neo.Service.DispName = "VPN Client Device Driver - VPN55"
+Neo.Service.Desc = "VPN Client Adapter - VPN55"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN55"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN56.inf b/src/bin/hamcore/inf/x86/INF_VPN56.inf
new file mode 100644
index 00000000..85d8a99d
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN56.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN56.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN56.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN56.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN56
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN56"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN56.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN56"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN56.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN56.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN56"
+Neo.Service.DispName = "VPN Client Device Driver - VPN56"
+Neo.Service.Desc = "VPN Client Adapter - VPN56"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN56"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN57.inf b/src/bin/hamcore/inf/x86/INF_VPN57.inf
new file mode 100644
index 00000000..6b5d2ed4
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN57.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN57.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN57.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN57.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN57
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN57"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN57.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN57"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN57.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN57.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN57"
+Neo.Service.DispName = "VPN Client Device Driver - VPN57"
+Neo.Service.Desc = "VPN Client Adapter - VPN57"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN57"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN58.inf b/src/bin/hamcore/inf/x86/INF_VPN58.inf
new file mode 100644
index 00000000..8cea6b94
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN58.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN58.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN58.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN58.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN58
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN58"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN58.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN58"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN58.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN58.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN58"
+Neo.Service.DispName = "VPN Client Device Driver - VPN58"
+Neo.Service.Desc = "VPN Client Adapter - VPN58"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN58"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN59.inf b/src/bin/hamcore/inf/x86/INF_VPN59.inf
new file mode 100644
index 00000000..f7199f89
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN59.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN59.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN59.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN59.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN59
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN59"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN59.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN59"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN59.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN59.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN59"
+Neo.Service.DispName = "VPN Client Device Driver - VPN59"
+Neo.Service.Desc = "VPN Client Adapter - VPN59"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN59"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN6.inf b/src/bin/hamcore/inf/x86/INF_VPN6.inf
new file mode 100644
index 00000000..86f54480
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN6.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN6.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN6.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN6.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN6
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN6"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN6.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN6"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN6.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN6.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN6"
+Neo.Service.DispName = "VPN Client Device Driver - VPN6"
+Neo.Service.Desc = "VPN Client Adapter - VPN6"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN6"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN60.inf b/src/bin/hamcore/inf/x86/INF_VPN60.inf
new file mode 100644
index 00000000..ba702d3c
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN60.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN60.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN60.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN60.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN60
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN60"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN60.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN60"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN60.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN60.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN60"
+Neo.Service.DispName = "VPN Client Device Driver - VPN60"
+Neo.Service.Desc = "VPN Client Adapter - VPN60"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN60"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN61.inf b/src/bin/hamcore/inf/x86/INF_VPN61.inf
new file mode 100644
index 00000000..c97c6259
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN61.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN61.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN61.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN61.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN61
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN61"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN61.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN61"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN61.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN61.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN61"
+Neo.Service.DispName = "VPN Client Device Driver - VPN61"
+Neo.Service.Desc = "VPN Client Adapter - VPN61"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN61"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN62.inf b/src/bin/hamcore/inf/x86/INF_VPN62.inf
new file mode 100644
index 00000000..a7b9945c
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN62.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN62.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN62.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN62.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN62
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN62"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN62.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN62"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN62.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN62.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN62"
+Neo.Service.DispName = "VPN Client Device Driver - VPN62"
+Neo.Service.Desc = "VPN Client Adapter - VPN62"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN62"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN63.inf b/src/bin/hamcore/inf/x86/INF_VPN63.inf
new file mode 100644
index 00000000..14d1e426
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN63.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN63.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN63.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN63.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN63
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN63"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN63.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN63"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN63.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN63.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN63"
+Neo.Service.DispName = "VPN Client Device Driver - VPN63"
+Neo.Service.Desc = "VPN Client Adapter - VPN63"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN63"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN64.inf b/src/bin/hamcore/inf/x86/INF_VPN64.inf
new file mode 100644
index 00000000..388a8edc
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN64.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN64.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN64.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN64.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN64
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN64"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN64.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN64"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN64.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN64.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN64"
+Neo.Service.DispName = "VPN Client Device Driver - VPN64"
+Neo.Service.Desc = "VPN Client Adapter - VPN64"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN64"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN65.inf b/src/bin/hamcore/inf/x86/INF_VPN65.inf
new file mode 100644
index 00000000..b0bec056
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN65.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN65.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN65.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN65.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN65
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN65"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN65.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN65"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN65.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN65.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN65"
+Neo.Service.DispName = "VPN Client Device Driver - VPN65"
+Neo.Service.Desc = "VPN Client Adapter - VPN65"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN65"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN66.inf b/src/bin/hamcore/inf/x86/INF_VPN66.inf
new file mode 100644
index 00000000..abf6df36
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN66.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN66.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN66.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN66.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN66
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN66"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN66.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN66"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN66.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN66.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN66"
+Neo.Service.DispName = "VPN Client Device Driver - VPN66"
+Neo.Service.Desc = "VPN Client Adapter - VPN66"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN66"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN67.inf b/src/bin/hamcore/inf/x86/INF_VPN67.inf
new file mode 100644
index 00000000..9f519fd6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN67.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN67.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN67.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN67.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN67
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN67"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN67.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN67"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN67.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN67.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN67"
+Neo.Service.DispName = "VPN Client Device Driver - VPN67"
+Neo.Service.Desc = "VPN Client Adapter - VPN67"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN67"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN68.inf b/src/bin/hamcore/inf/x86/INF_VPN68.inf
new file mode 100644
index 00000000..4cfa090b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN68.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN68.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN68.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN68.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN68
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN68"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN68.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN68"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN68.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN68.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN68"
+Neo.Service.DispName = "VPN Client Device Driver - VPN68"
+Neo.Service.Desc = "VPN Client Adapter - VPN68"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN68"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN69.inf b/src/bin/hamcore/inf/x86/INF_VPN69.inf
new file mode 100644
index 00000000..45754f15
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN69.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN69.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN69.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN69.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN69
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN69"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN69.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN69"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN69.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN69.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN69"
+Neo.Service.DispName = "VPN Client Device Driver - VPN69"
+Neo.Service.Desc = "VPN Client Adapter - VPN69"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN69"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN7.inf b/src/bin/hamcore/inf/x86/INF_VPN7.inf
new file mode 100644
index 00000000..96aa13ab
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN7.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN7.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN7.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN7.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN7
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN7"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN7.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN7"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN7.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN7.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN7"
+Neo.Service.DispName = "VPN Client Device Driver - VPN7"
+Neo.Service.Desc = "VPN Client Adapter - VPN7"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN7"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN70.inf b/src/bin/hamcore/inf/x86/INF_VPN70.inf
new file mode 100644
index 00000000..8ef1cb66
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN70.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN70.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN70.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN70.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN70
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN70"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN70.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN70"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN70.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN70.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN70"
+Neo.Service.DispName = "VPN Client Device Driver - VPN70"
+Neo.Service.Desc = "VPN Client Adapter - VPN70"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN70"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN71.inf b/src/bin/hamcore/inf/x86/INF_VPN71.inf
new file mode 100644
index 00000000..80c453a7
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN71.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN71.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN71.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN71.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN71
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN71"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN71.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN71"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN71.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN71.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN71"
+Neo.Service.DispName = "VPN Client Device Driver - VPN71"
+Neo.Service.Desc = "VPN Client Adapter - VPN71"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN71"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN72.inf b/src/bin/hamcore/inf/x86/INF_VPN72.inf
new file mode 100644
index 00000000..28b28c34
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN72.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN72.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN72.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN72.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN72
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN72"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN72.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN72"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN72.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN72.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN72"
+Neo.Service.DispName = "VPN Client Device Driver - VPN72"
+Neo.Service.Desc = "VPN Client Adapter - VPN72"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN72"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN73.inf b/src/bin/hamcore/inf/x86/INF_VPN73.inf
new file mode 100644
index 00000000..76bec447
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN73.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN73.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN73.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN73.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN73
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN73"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN73.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN73"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN73.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN73.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN73"
+Neo.Service.DispName = "VPN Client Device Driver - VPN73"
+Neo.Service.Desc = "VPN Client Adapter - VPN73"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN73"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN74.inf b/src/bin/hamcore/inf/x86/INF_VPN74.inf
new file mode 100644
index 00000000..233a8de8
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN74.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN74.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN74.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN74.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN74
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN74"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN74.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN74"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN74.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN74.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN74"
+Neo.Service.DispName = "VPN Client Device Driver - VPN74"
+Neo.Service.Desc = "VPN Client Adapter - VPN74"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN74"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN75.inf b/src/bin/hamcore/inf/x86/INF_VPN75.inf
new file mode 100644
index 00000000..269399cb
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN75.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN75.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN75.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN75.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN75
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN75"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN75.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN75"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN75.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN75.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN75"
+Neo.Service.DispName = "VPN Client Device Driver - VPN75"
+Neo.Service.Desc = "VPN Client Adapter - VPN75"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN75"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN76.inf b/src/bin/hamcore/inf/x86/INF_VPN76.inf
new file mode 100644
index 00000000..1f780fa6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN76.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN76.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN76.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN76.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN76
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN76"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN76.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN76"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN76.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN76.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN76"
+Neo.Service.DispName = "VPN Client Device Driver - VPN76"
+Neo.Service.Desc = "VPN Client Adapter - VPN76"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN76"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN77.inf b/src/bin/hamcore/inf/x86/INF_VPN77.inf
new file mode 100644
index 00000000..153530a1
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN77.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN77.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN77.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN77.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN77
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN77"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN77.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN77"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN77.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN77.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN77"
+Neo.Service.DispName = "VPN Client Device Driver - VPN77"
+Neo.Service.Desc = "VPN Client Adapter - VPN77"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN77"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN78.inf b/src/bin/hamcore/inf/x86/INF_VPN78.inf
new file mode 100644
index 00000000..f1481bf9
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN78.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN78.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN78.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN78.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN78
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN78"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN78.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN78"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN78.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN78.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN78"
+Neo.Service.DispName = "VPN Client Device Driver - VPN78"
+Neo.Service.Desc = "VPN Client Adapter - VPN78"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN78"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN79.inf b/src/bin/hamcore/inf/x86/INF_VPN79.inf
new file mode 100644
index 00000000..0e92d447
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN79.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN79.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN79.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN79.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN79
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN79"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN79.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN79"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN79.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN79.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN79"
+Neo.Service.DispName = "VPN Client Device Driver - VPN79"
+Neo.Service.Desc = "VPN Client Adapter - VPN79"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN79"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN8.inf b/src/bin/hamcore/inf/x86/INF_VPN8.inf
new file mode 100644
index 00000000..faf57ad9
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN8.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN8.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN8.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN8.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN8
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN8"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN8.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN8"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN8.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN8.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN8"
+Neo.Service.DispName = "VPN Client Device Driver - VPN8"
+Neo.Service.Desc = "VPN Client Adapter - VPN8"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN8"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN80.inf b/src/bin/hamcore/inf/x86/INF_VPN80.inf
new file mode 100644
index 00000000..b8a1afed
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN80.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN80.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN80.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN80.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN80
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN80"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN80.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN80"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN80.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN80.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN80"
+Neo.Service.DispName = "VPN Client Device Driver - VPN80"
+Neo.Service.Desc = "VPN Client Adapter - VPN80"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN80"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN81.inf b/src/bin/hamcore/inf/x86/INF_VPN81.inf
new file mode 100644
index 00000000..e5f7b9c2
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN81.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN81.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN81.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN81.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN81
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN81"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN81.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN81"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN81.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN81.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN81"
+Neo.Service.DispName = "VPN Client Device Driver - VPN81"
+Neo.Service.Desc = "VPN Client Adapter - VPN81"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN81"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN82.inf b/src/bin/hamcore/inf/x86/INF_VPN82.inf
new file mode 100644
index 00000000..a5bed7a4
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN82.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN82.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN82.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN82.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN82
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN82"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN82.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN82"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN82.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN82.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN82"
+Neo.Service.DispName = "VPN Client Device Driver - VPN82"
+Neo.Service.Desc = "VPN Client Adapter - VPN82"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN82"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN83.inf b/src/bin/hamcore/inf/x86/INF_VPN83.inf
new file mode 100644
index 00000000..f69ca617
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN83.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN83.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN83.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN83.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN83
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN83"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN83.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN83"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN83.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN83.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN83"
+Neo.Service.DispName = "VPN Client Device Driver - VPN83"
+Neo.Service.Desc = "VPN Client Adapter - VPN83"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN83"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN84.inf b/src/bin/hamcore/inf/x86/INF_VPN84.inf
new file mode 100644
index 00000000..d2a9350e
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN84.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN84.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN84.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN84.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN84
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN84"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN84.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN84"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN84.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN84.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN84"
+Neo.Service.DispName = "VPN Client Device Driver - VPN84"
+Neo.Service.Desc = "VPN Client Adapter - VPN84"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN84"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN85.inf b/src/bin/hamcore/inf/x86/INF_VPN85.inf
new file mode 100644
index 00000000..2d7ddbab
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN85.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN85.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN85.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN85.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN85
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN85"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN85.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN85"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN85.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN85.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN85"
+Neo.Service.DispName = "VPN Client Device Driver - VPN85"
+Neo.Service.Desc = "VPN Client Adapter - VPN85"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN85"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN86.inf b/src/bin/hamcore/inf/x86/INF_VPN86.inf
new file mode 100644
index 00000000..7a98f66c
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN86.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN86.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN86.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN86.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN86
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN86"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN86.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN86"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN86.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN86.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN86"
+Neo.Service.DispName = "VPN Client Device Driver - VPN86"
+Neo.Service.Desc = "VPN Client Adapter - VPN86"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN86"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN87.inf b/src/bin/hamcore/inf/x86/INF_VPN87.inf
new file mode 100644
index 00000000..219b50f5
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN87.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN87.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN87.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN87.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN87
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN87"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN87.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN87"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN87.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN87.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN87"
+Neo.Service.DispName = "VPN Client Device Driver - VPN87"
+Neo.Service.Desc = "VPN Client Adapter - VPN87"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN87"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN88.inf b/src/bin/hamcore/inf/x86/INF_VPN88.inf
new file mode 100644
index 00000000..156c6728
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN88.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN88.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN88.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN88.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN88
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN88"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN88.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN88"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN88.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN88.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN88"
+Neo.Service.DispName = "VPN Client Device Driver - VPN88"
+Neo.Service.Desc = "VPN Client Adapter - VPN88"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN88"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN89.inf b/src/bin/hamcore/inf/x86/INF_VPN89.inf
new file mode 100644
index 00000000..79fcf54b
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN89.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN89.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN89.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN89.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN89
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN89"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN89.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN89"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN89.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN89.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN89"
+Neo.Service.DispName = "VPN Client Device Driver - VPN89"
+Neo.Service.Desc = "VPN Client Adapter - VPN89"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN89"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN9.inf b/src/bin/hamcore/inf/x86/INF_VPN9.inf
new file mode 100644
index 00000000..f33037a6
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN9.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN9.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN9.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN9.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN9
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN9"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN9.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN9"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN9.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN9.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN9"
+Neo.Service.DispName = "VPN Client Device Driver - VPN9"
+Neo.Service.Desc = "VPN Client Adapter - VPN9"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN9"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN90.inf b/src/bin/hamcore/inf/x86/INF_VPN90.inf
new file mode 100644
index 00000000..2a05a423
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN90.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN90.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN90.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN90.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN90
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN90"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN90.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN90"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN90.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN90.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN90"
+Neo.Service.DispName = "VPN Client Device Driver - VPN90"
+Neo.Service.Desc = "VPN Client Adapter - VPN90"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN90"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN91.inf b/src/bin/hamcore/inf/x86/INF_VPN91.inf
new file mode 100644
index 00000000..756b8baf
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN91.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN91.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN91.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN91.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN91
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN91"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN91.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN91"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN91.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN91.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN91"
+Neo.Service.DispName = "VPN Client Device Driver - VPN91"
+Neo.Service.Desc = "VPN Client Adapter - VPN91"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN91"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN92.inf b/src/bin/hamcore/inf/x86/INF_VPN92.inf
new file mode 100644
index 00000000..0fbb1bc8
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN92.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN92.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN92.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN92.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN92
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN92"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN92.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN92"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN92.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN92.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN92"
+Neo.Service.DispName = "VPN Client Device Driver - VPN92"
+Neo.Service.Desc = "VPN Client Adapter - VPN92"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN92"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN93.inf b/src/bin/hamcore/inf/x86/INF_VPN93.inf
new file mode 100644
index 00000000..2d9b4e58
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN93.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN93.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN93.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN93.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN93
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN93"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN93.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN93"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN93.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN93.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN93"
+Neo.Service.DispName = "VPN Client Device Driver - VPN93"
+Neo.Service.Desc = "VPN Client Adapter - VPN93"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN93"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN94.inf b/src/bin/hamcore/inf/x86/INF_VPN94.inf
new file mode 100644
index 00000000..5ec3245a
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN94.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN94.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN94.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN94.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN94
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN94"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN94.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN94"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN94.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN94.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN94"
+Neo.Service.DispName = "VPN Client Device Driver - VPN94"
+Neo.Service.Desc = "VPN Client Adapter - VPN94"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN94"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN95.inf b/src/bin/hamcore/inf/x86/INF_VPN95.inf
new file mode 100644
index 00000000..49d3d6ce
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN95.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN95.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN95.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN95.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN95
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN95"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN95.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN95"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN95.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN95.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN95"
+Neo.Service.DispName = "VPN Client Device Driver - VPN95"
+Neo.Service.Desc = "VPN Client Adapter - VPN95"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN95"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN96.inf b/src/bin/hamcore/inf/x86/INF_VPN96.inf
new file mode 100644
index 00000000..1eb042c2
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN96.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN96.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN96.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN96.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN96
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN96"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN96.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN96"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN96.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN96.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN96"
+Neo.Service.DispName = "VPN Client Device Driver - VPN96"
+Neo.Service.Desc = "VPN Client Adapter - VPN96"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN96"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN97.inf b/src/bin/hamcore/inf/x86/INF_VPN97.inf
new file mode 100644
index 00000000..09bf822d
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN97.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN97.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN97.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN97.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN97
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN97"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN97.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN97"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN97.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN97.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN97"
+Neo.Service.DispName = "VPN Client Device Driver - VPN97"
+Neo.Service.Desc = "VPN Client Adapter - VPN97"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN97"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN98.inf b/src/bin/hamcore/inf/x86/INF_VPN98.inf
new file mode 100644
index 00000000..cf9be902
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN98.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN98.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN98.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN98.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN98
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN98"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN98.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN98"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN98.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN98.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN98"
+Neo.Service.DispName = "VPN Client Device Driver - VPN98"
+Neo.Service.Desc = "VPN Client Adapter - VPN98"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN98"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/INF_VPN99.inf b/src/bin/hamcore/inf/x86/INF_VPN99.inf
new file mode 100644
index 00000000..7c100324
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/INF_VPN99.inf
@@ -0,0 +1,109 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = 01/04/2014, 4.3.0.9407
+
+CatalogFile.NT = inf_VPN99.cat
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+Neo_VPN99.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+Neo_VPN99.sys, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_VPN99
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_VPN99"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , Neo_VPN99.sys
+HKR, NDIS, LogDriverName, , "Neo_VPN99"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\Neo_VPN99.sys
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_VPN99.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_VPN99"
+Neo.Service.DispName = "VPN Client Device Driver - VPN99"
+Neo.Service.Desc = "VPN Client Adapter - VPN99"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - VPN99"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "000001000001"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/inf/x86/inf.cat b/src/bin/hamcore/inf/x86/inf.cat
new file mode 100644
index 00000000..995b0ced
--- /dev/null
+++ b/src/bin/hamcore/inf/x86/inf.cat
Binary files differ
diff --git a/src/bin/hamcore/install_src.dat b/src/bin/hamcore/install_src.dat
new file mode 100644
index 00000000..92781ffa
--- /dev/null
+++ b/src/bin/hamcore/install_src.dat
@@ -0,0 +1 @@
+“c’†I \ No newline at end of file
diff --git a/src/bin/hamcore/lang.config b/src/bin/hamcore/lang.config
new file mode 100644
index 00000000..aae41653
--- /dev/null
+++ b/src/bin/hamcore/lang.config
@@ -0,0 +1,17 @@
+# PacketiX VPN / SoftEther VPN Language Setting File
+#
+# Specify your preferred Language ID on this setting file.
+# The text messages will be displayed in the specified language.
+#
+# Please note that you must restart a program to apply the modification of
+# this setting-file.
+#
+# Only one line is acceptable. Any other lines are ignored.
+#
+# The change of this file will effect after the next execution of a program.
+#
+# Note for UNIX / Linux Users:
+# You have to set the LANG environment variable if you want to display
+# non-English characters. If no LANG environment is set, any multi-byte
+# characters (i.e. Japanese or Chinese) will not be displayed correctly.
+#
diff --git a/src/bin/hamcore/languages.txt b/src/bin/hamcore/languages.txt
new file mode 100644
index 00000000..7cd121a1
--- /dev/null
+++ b/src/bin/hamcore/languages.txt
@@ -0,0 +1,8 @@
+# PacketiX VPN / SoftEther VPN Language List File
+# Copyright (c) SoftEther Corporation. All Rights Reserved
+
+# ç•ªå· è­˜åˆ¥å­ è‹±èªžè¡¨è¨˜ ローカル表記 Windowsãƒ­ã‚±ãƒ¼ãƒ«ç•ªå· UNIXロケール文字一覧
+0 ja Japanese 日本語 1041 ja,jp,sjis,shift_jis,euc
+1 en English English 1033 en,us,c
+2 cn Simplified_Chinese 简体中文 2052,4100,1028,3076,5124 zh,cn,tw,hkg,mac,sg,chi
+
diff --git a/src/bin/hamcore/legal.txt b/src/bin/hamcore/legal.txt
new file mode 100644
index 00000000..89add663
--- /dev/null
+++ b/src/bin/hamcore/legal.txt
@@ -0,0 +1,323 @@
+BitVisor(R) VPN Client Module (IPsec Driver):
+Copyright (c) 2007, 2008 University of Tsukuba.
+Copyright (C) 2007, 2008 National Institute of Information and Communications Technology.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the University of Tsukuba nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+Microsoft(R) C Runtime Library:
+(c) 2007 Microsoft Corporation. All Rights Reserved.
+
+-------------------
+
+RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki):
+
+License to copy and use this software is granted provided that it is identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing this software.
+
+License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing the derived work.
+
+RSA Security Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind.
+
+-------------------
+
+WinPcap:
+Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the Politecnico di Torino nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libedit:
+Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by Christos Zoulas of Cornell University.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------
+
+libiconv:
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such.
+
+ Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above) ; and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
+
+ 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+-------------------
+
+ncurses:
+Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, distribute with modifications, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.
+
+-------------------
+
+OpenSSL:
+OpenSSL License
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com).
+
+Original SSLeay License
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.
+
+This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software must display the following acknowledgement: "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.]
+
+-------------------
+
+zlib:
+Acknowledgments:
+ The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here.
+
+Copyright notice:
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions.
+
+-------------------
+
+Intel AESNI Sample Library:
+
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Issue Date: Aug 6, 2010
+
+-------------------
+
+NOTES WRITTEN BY SOFTETHER CORPORATION
+
+Note for users of non-Windows version of PacketiX VPN: The enumerated bundle of License Agreements above are copies of original License Agreements of each library programs which PacketiX VPN uses. PacketiX VPN is not a delivered work from these libraries. PacketiX VPN is a separated work from the libraries, but it may call functions of the libraries (whether or not PacketiX VPN calls such functions are depended on the user's intention to link them or not on user's side computer). While some libraries indicate GPL or LGPL as a condition to re-distribute, PacketiX VPN is not license under GPL nor LGPL. Therefore, we took special care not to make PacketiX VPN become delivered works of any GPL or LGPL libraries. In order to achieve that, both PacketiX VPN and GPL/LGPL libraries are distributed with isolated forms (means that any program files of PacketiX VPN are not bound nor linked to any GPL/LGPL libraries). If a user of PacketiX VPN wants to link GPL/LGPL libraries by their own decisions, operations and responsibilities, he may do that on his computer. However, if a delivered work under copyright law is created as a result of such an operation, such a delivered work must not re-distributed to other people, because it may violate GPL/LGPL libraries' conditions.
+
+Note for users of Windows version of PacketiX VPN: For technical reason, the above texts are exactly same as a file which is also contained on the non-Windows version of PacketiX VPN. Actually, the Windows version of PacketiX VPN has no relations to any GPL/LGPL libraries enumerated above.
+
+SoftEther Corporation provides source codes of some GPL/LGPL/other libraries listed above on its web server. Anyone can download, use and re-distribute them under individual licenses which are contained on each archive file, available from the following URL:
+http://uploader.softether.co.jp/src/
+
diff --git a/src/bin/hamcore/openvpn_readme.pdf b/src/bin/hamcore/openvpn_readme.pdf
new file mode 100644
index 00000000..45c250a8
--- /dev/null
+++ b/src/bin/hamcore/openvpn_readme.pdf
Binary files differ
diff --git a/src/bin/hamcore/openvpn_readme.txt b/src/bin/hamcore/openvpn_readme.txt
new file mode 100644
index 00000000..350c8cb7
--- /dev/null
+++ b/src/bin/hamcore/openvpn_readme.txt
@@ -0,0 +1,292 @@
+======================================================================
+
+ How to Use the Auto-Generated OpenVPN Configuration Samples
+ OpenVPN 用ã®è‡ªå‹•ç”Ÿæˆã•ã‚ŒãŸè¨­å®šã‚µãƒ³ãƒ—ルファイルã®ä½¿ã„æ–¹
+ 如何使用自动生æˆçš„ OpenVPN é…置案例
+
+======================================================================
+
+This document is written in English, Japanese and Simplified-Chinese.
+ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯è‹±èªžã€æ—¥æœ¬èªžã€ä¸­å›½èªž (簡体字) ã§è¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
+本文档是英语,日语和简体中文。
+
+
+*****************************
+*** ***
+*** English ***
+*** ***
+*****************************
+
+
+How to Use the Auto-Generated OpenVPN Configuration Samples
+<< !! READ IT CAREFULLY BEFORE YOU USE !! >>
+
+
+* 1. About Files
+When you open the ZIP archive, the following files with the
+structured-directory will be expanded.
+Extract there files including sub-directory structure toward any destination
+directory, and use parts according to your necessary.
+
+< The Configuration File for L3 (IP Routing) >
+ openvpn_remote_access_l3.ovpn
+
+< The Configuration File for L2 (Ethernet Bridging) >
+ openvpn_site_to_site_bridge_l2.ovpn
+
+The extension ".ovpn" means a configuration file. You can specify the
+configuration file into OpenVPN to initiate a VPN connection.
+
+
+* 2. How Different between L3 and L2?
+Use L3 (IP Routing) if you want to install OpenVPN on the normal computer (for
+example, a lap top PC), and make it connect to PacketiX VPN Server or SoftEther
+VPN Server for the purpose of establishing a "Remote-Access VPN Connection" .
+In this case, the IP address will be assigned on the virtual network adapter
+of OpenVPN automatically when the OpenVPN will connect to the Virtual HUB on
+the VPN Server successfully and request an IP address and other network
+parameters (e.g. DNS server address).
+
+In other hand, if you want to build a "Site-to-Site VPN Connection" ,
+use L2 (Ethernet Bridging) for OpenVPN on the computer which is set up on the
+remote place for bridging. No IP-specific treatment will be done. All Ethernet
+packets (MAC frames) will exchanged transparently between two or more sites.
+Any computers or network equipments (e.g. routers) will be able to communicate
+to other sites mutually.
+
+VPN Server will treat a virtual VPN session from L3-mode OpenVPN as
+a "VPN Client" session.
+VPN Server will treat a virtual VPN session from L2-mode OpenVPN as
+a "VPN Bridge" session.
+
+
+* 3. How to Specify the Username and Password?
+The prompt of username and password will be shown when you try to use this
+configuration. You have to enter the same username and password which has
+already been defined on the Virtual HUB of VPN Server.
+
+Please note that you have to create an user on the Virtual HUB in advance.
+
+If there are two or more Virtual HUBs on the VPN Server, you have to specify
+the username as:
+
+ "Username@Virtual-HUB-Name"
+
+or:
+
+ "Virtual-HUB-Name\Username"
+
+to choose which Virtual HUB to be connected. You can also choose which
+Virtual HUB should be elected as a "Default HUB" when the specification of
+the name of Virtual HUB will be omitted.
+
+Please be advised that you can make OpenVPN to enter the username and password
+automatically without showing a prompt. How to do it is described on the
+OpenVPN manual.
+
+
+* 4. About Protocol and Port Number
+Both TCP and UDP are available to connect to the VPN Server by OpenVPN.
+
+If you use TCP, the port number is same as any of the "TCP Listener Port" on
+the VPN Server which is originally defined in order to accept inbound
+TCP-based VPN Client session.
+
+If you use UDP, the port number must be one of UDP ports which are defined on
+the VPN Server configuration in advance. Do not confuse between TCP and UDP
+since they are not concerned mutually.
+
+You can also specify the proxy-server address if the connection should be
+relayed by the proxy-server. Specify it on the configuration file.
+
+
+* 5. Closing
+OpenVPN is independent software from PacketiX VPN / SoftEther VPN.
+It is an open-source application which was developer by third-party.
+Refer to http://openvpn.net/ if you need more how to use OpenVPN.
+
+
+
+*****************************
+*** ***
+*** Japanese (日本語) ***
+*** ***
+*****************************
+
+OpenVPN 用ã®è‡ªå‹•ç”Ÿæˆã•ã‚ŒãŸè¨­å®šã‚µãƒ³ãƒ—ルファイルã®ä½¿ã„æ–¹
+<< !! 使用å‰ã«å¿…ãšãŠèª­ã¿ãã ã•ã„ !! >>
+
+
+* 1. ファイル構æˆ
+ZIP ファイルを開ãã¨ã€ä»¥ä¸‹ã®ã‚ˆã†ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªæ§‹é€ ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒå‡ºåŠ›ã•ã‚Œã¾ã™ã€‚
+ã“れらã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ã™ã¹ã¦ã‚µãƒ–フォルダã”ã¨ä»»æ„ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å±•é–‹ã—ã€å¿…è¦ãª
+ファイルをãŠä½¿ã„ãã ã•ã„。
+
+< L3 (IP ルーティング) 用ã®æŽ¥ç¶šè¨­å®š >
+ openvpn_remote_access_l3.ovpn
+
+< L2 (Ethernet ブリッジ) 用ã®æŽ¥ç¶šè¨­å®š >
+ openvpn_site_to_site_bridge_l2.ovpn
+
+æ‹¡å¼µå­ãŒ .ovpn ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒæŽ¥ç¶šè¨­å®šã®æœ¬ä½“ã§ã™ã€‚ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ OpenVPN
+プログラムã«æŒ‡å®šã—㦠OpenVPN 接続を始動ã—ã¦ãã ã•ã„。
+
+
+* 2. L3 㨠L2 ã®é•ã„
+普通ã®ã‚³ãƒ³ãƒ”ュータ (ラップトップ PC ãªã©) ã« OpenVPN をインストールã—ã€
+ãã®ã‚³ãƒ³ãƒ”ュータを PacketiX VPN Server / SoftEther VPN Server ã«
+リモートアクセス VPN 接続ã™ã‚‹å ´åˆã¯ã€L3 (IP ルーティング) 用ã®æŽ¥ç¶šè¨­å®š
+を使用ã—ã¦ãã ã•ã„。ã“ã®å ´åˆã¯ã€æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã‚’試行ã—ã€
+仮想 HUB ã®ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã‹ã‚‰ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ DHCP サーãƒãƒ¼ã‹ã‚‰
+IP アドレスã®å–得を試ã¿ã€å–å¾—ã«æˆåŠŸã—㟠IP アドレスや DNS サーãƒãƒ¼ãªã©
+ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æƒ…å ±ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ PC ã®ä»®æƒ³ LAN カードã«è‡ªå‹•çš„ã«å‰²å½“ã¦ã‚‰ã‚Œ
+ã¾ã™ã€‚
+
+一方ã€æ‹ ç‚¹é–“接続 VPN を構築ã™ã‚‹å ´åˆã¯ã€é éš”拠点ã«è¨­ç½®ã™ã‚‹ VPN ブリッジ用
+ã®ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã•ã›ã‚‹ OpenVPN ã«ã¯ L2 (Ethernet ブリッジ) 用ã®
+接続設定を使用ã—ã¦ãã ã•ã„。ã“ã®å ´åˆã¯ã€IP ã«ç‰¹åŒ–ã—ãŸå‡¦ç†ã¯ä¸€åˆ‡è¡Œã‚ã‚Œã¾
+ã›ã‚“。ã™ã¹ã¦ã® Ethernet パケット (MAC フレーム) ãŒæ‹ ç‚¹é–“ã§ç›¸äº’ã«é€éŽçš„ã«
+交æ›ã•ã‚Œã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚両方ã®æ‹ ç‚¹ã® Ethernet セグメントã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹
+ã™ã¹ã¦ã®ã‚³ãƒ³ãƒ”ュータやルータãªã©ã®é€šä¿¡æ©Ÿå™¨åŒå£«ã¯è‡ªç”±ã«é€šä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã‚‹
+よã†ã«ãªã‚Šã¾ã™ã€‚
+
+L3 モードã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€VPN Server ã¯ãã®æŽ¥ç¶šã‚’「VPN Clientã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢
+ã‹ã‚‰ã®æŽ¥ç¶šã¨åŒä¸€ã®ã‚‚ã®ã¨è¦‹ãªã—ãŸæŒ¯ã‚‹èˆžã„ã‚’ã—ã¾ã™ã€‚
+
+L2 モードã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€VPN Server ã¯ãã®æŽ¥ç¶šã‚’「VPN Bridgeã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢
+ã‹ã‚‰ã®æŽ¥ç¶šã¨åŒä¸€ã®ã‚‚ã®ã¨è¦‹ãªã—ãŸæŒ¯ã‚‹èˆžã„ã‚’ã—ã¾ã™ã€‚
+
+
+* 3. 接続時ã«æŒ‡å®šã™ã‚‹ã¹ãユーザーåã¨ãƒ‘スワードã«ã¤ã„ã¦
+ã“ã®ã‚µãƒ³ãƒ—ル設定ファイルを用ã„㦠VPN Server ã«æŽ¥ç¶šã—よã†ã¨ã™ã‚‹ã¨ã€
+ユーザーåã¨ãƒ‘スワードã®å…¥åŠ›ãŒè¦æ±‚ã•ã‚Œã¾ã™ã€‚ã“ã“ã§å…¥åŠ›ã™ã¹ãユーザーåã¨
+パスワードã¯ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ä»®æƒ³ HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーåã¨
+パスワードã¨åŒä¸€ã®ã‚‚ã®ã§ã™ã€‚
+
+OpenVPN ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã«ã¯ã€ã‚らã‹ã˜ã‚仮想 HUB ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’登録ã—ã¦
+ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+ãªãŠã€VPN Server ã« 2 個以上ã®ä»®æƒ³ HUB ãŒè¨­ç½®ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼å
+ã®æŒ‡å®šæ–¹æ³•ã¨ã—ã¦ã€
+
+ "ユーザーå@仮想 HUB å"
+
+ã‚ã‚‹ã„ã¯
+
+ "仮想 HUB å\ユーザーå"
+
+ã®ã‚ˆã†ã«æŒ‡å®šã—ã¦ãã ã•ã„。
+ã“ã®å ´åˆã«ãŠã„ã¦ã€ä»®æƒ³ HUB åã‚’çœç•¥ã—ãŸå ´åˆã«æ¨™æº–ã§é¸æŠžã•ã‚Œã‚‹ã¹ãデフォルト
+ã®ä»®æƒ³ HUB ã‚’ã‚らã‹ã˜ã‚ VPN Server å´ã®è¨­å®šã«ãŠã„ã¦æŒ‡å®šã—ã¦ãŠãã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚
+
+ユーザーåã¨ãƒ‘スワードã®å…¥åŠ›ã‚’毎回行ã†ã“ã¨ãŒå›°é›£ãªå ´åˆã¯ã€ä»£ã‚ã‚Šã«
+設定ファイルãŠã‚ˆã³å¤–部テキストファイルã«ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを記載ã—ã¦è‡ªå‹•çš„
+ã«å…¥åŠ›ã•ã›ã‚‹ã‚ˆã†ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ãã®ãŸã‚ã®æ–¹æ³•ã¯ OpenVPN ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚’
+å‚ç…§ã—ã¦ãã ã•ã„。
+
+
+* 4. プロトコルやãƒãƒ¼ãƒˆç•ªå·ã«ã¤ã„ã¦
+接続先㮠VPN Server ã«å¯¾ã—ã¦é€šä¿¡ã‚’è¡Œã†ãŸã‚ã®ãƒ—ロトコルã«ã¯ TCP 㨠UDP ãŒã‚ã‚Šã€
+ã©ã¡ã‚‰ã‚‚利用å¯èƒ½ã§ã™ã€‚
+
+TCP を利用ã™ã‚‹å ´åˆã¯ã€ãƒãƒ¼ãƒˆç•ªå·ã¯ VPN Server ãŒæ­£è¦ã® VPN Client ソフトウェア
+ã«å¯¾ã—ã¦ã‚µãƒ¼ãƒ“スをæä¾›ã™ã‚‹ãŸã‚ã® TCP リスナãƒãƒ¼ãƒˆã¨åŒä¸€ã§ã™ã€‚ã‚‚ã—リスナãƒãƒ¼ãƒˆ
+ãŒè¤‡æ•°å®šç¾©ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ã„ãšã‚Œã®ãƒªã‚¹ãƒŠãƒãƒ¼ãƒˆã«ã‚‚ OpenVPN プロトコルã§æŽ¥ç¶š
+ã§ãã¾ã™ã€‚
+
+UDP を利用ã™ã‚‹å ´åˆã¯ã€ãƒãƒ¼ãƒˆç•ªå·ã¯ã‚らã‹ã˜ã‚ VPN Server å´ã§æŒ‡å®šã•ã‚Œã¦ã„ã‚‹
+UDP ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚TCP 㨠UDP ã®ãƒãƒ¼ãƒˆç•ªå·ã¯äº’ã„ã«ç„¡é–¢ä¿‚
+ã§ã™ã®ã§ã€æ··ä¹±ã—ãªã„よã†ã«ã—ã¦ãã ã•ã„。
+
+TCP を利用ã™ã‚‹å ´åˆã§ãƒ—ロキシサーãƒãƒ¼ã‚’利用ã™ã‚‹å ´åˆã¯ã€ãã®ãŸã‚ã®è¨­å®šã‚’設定
+ファイルã«è¿½åŠ ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+
+* 5. 最後ã«
+OpenVPN 㯠PacketiX VPN / SoftEther VPN ã¨ã¯ç‹¬ç«‹ã—ãŸã€ã‚µãƒ¼ãƒ‰ãƒ‘ーティã«ã‚ˆã£ã¦
+開発ã•ã‚ŒãŸã‚ªãƒ¼ãƒ—ンソースã®ãƒ—ログラムã§ã™ã€‚OpenVPN ã®ä½¿ã„æ–¹ã«ã¤ã„ã¦ã¯ã€
+http://openvpn.net/ ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+
+
+
+*****************************
+*** ***
+*** Chinese (简体中文) ***
+*** ***
+*****************************
+
+如何使用自动生æˆçš„ OpenVPN é…置案例
+<< !! 使用å‰è¯·ä»”细阅读 !! >>
+
+
+* 1. 关于文件
+当您打开 ZIP 压缩包, 以下文件结构目录将被展现。
+解压缩这些文件, 包括å­ç›®å½•ç»“构到任何目的地目录, 并使用你需è¦çš„部分。
+
+< The Configuration File for L3 (IP Routing) >
+ openvpn_remote_access_l3.ovpn
+
+< The Configuration File for L2 (Ethernet Bridging) >
+ openvpn_site_to_site_bridge_l2.ovpn
+
+扩展å ".ovpn" 表示一个é…置文件。您å¯ä»¥æŒ‡å®šé…置文件到 OpenVPN æ¥å‘起一个
+VPN 连接。
+
+
+* 2. L3 å’Œ L2 之间有什么ä¸åŒ ?
+如果你想在普通电脑上安装 OpenVPN (例如, 笔记本电脑), 使用 L3 (IP 路由)
+并使其连接到 PacketiX VPN æœåŠ¡å™¨æˆ– SoftEther VPN æœåŠ¡å™¨ä»¥å»ºç«‹ "远程访问
+VPN 连接" 的目的。
+在这ç§æƒ…况下, 当 OpenVPN æˆåŠŸè¿žæŽ¥åˆ° VPN æœåŠ¡å™¨çš„虚拟 HUB 并请求一个 IP
+地å€å’Œå…¶ä»–网络å‚æ•° (如 DNS æœåŠ¡å™¨åœ°å€) æ—¶,
+IP 地å€å°†è¢«è‡ªåŠ¨åˆ†é…到 OpenVPN 的虚拟网å¡ä¸Šã€‚
+
+å¦ä¸€æ–¹é¢, 如果你想建立一个 "站点到站点的 VPN 连接" , 在远程地点è¦å»ºç«‹æ¡¥æŽ¥çš„
+é‚£å°ç”µè„‘上使用 OpenVPN L2 (以太网桥)。
+ä¸éœ€è¦è¿›è¡Œå…·ä½“çš„ IP æ“作。所有的以太网数æ®åŒ… (MAC 帧) 将在两个或多个站点之
+é—´é€æ˜Žåœ°äº¤æ¢ã€‚
+任何电脑或网络设备 (如路由器) 能够与其他站点相互通信。
+
+VPN æœåŠ¡å™¨å°†æŠŠ OpenVPN L3 模å¼çš„虚拟 VPN 会è¯å½“作一个 "VPN 客户端" 会è¯ã€‚
+VPN æœåŠ¡å™¨å°†æŠŠ OpenVPN L2 模å¼çš„虚拟 VPN 会è¯å½“作一个 "VPNæ¡¥" 会è¯ã€‚
+
+
+* 3. 如何指定用户åå’Œå¯†ç  ?
+当您å°è¯•ä½¿ç”¨æ­¤é…置时, 会出现输入用户å和密ç çš„æ示。
+您应输入已在 VPN æœåŠ¡å™¨çš„虚拟 HUB 上定义好的ã€ç›¸åŒçš„用户å和密ç ã€‚
+
+请注æ„, 您必须æå‰åœ¨è™šæ‹Ÿ HUB 上创建一个用户。
+
+如果在 VPN æœåŠ¡å™¨ä¸Šæœ‰ä¸¤ä¸ªæˆ–多个虚拟 HUB, 你应指定用户å为:
+
+ "Username@Virtual-HUB-Name"
+
+或:
+
+ "Virtual-HUB-Name\Username"
+
+选择è¦è¿žæŽ¥çš„虚拟 HUB。当虚拟 HUB çš„å称å‚数被çœç•¥æ—¶, 您也å¯ä»¥é€‰æ‹©ä½œä¸º
+"默认 HUB" 的虚拟 HUB。
+
+请注æ„, 您å¯ä»¥ä½¿ OpenVPN 自动输入用户å和密ç , 而ä¸æ˜¾ç¤ºæ示信æ¯ã€‚
+如何åšåˆ°è¿™ä¸€ç‚¹, 在 OpenVPN 手册中有æ述。
+
+
+* 4. 关于å议和端å£å·
+通过 OpenVPN,TCP å’Œ UDP 都å¯ä»¥è¿žæŽ¥åˆ° VPN æœåŠ¡å™¨ã€‚
+
+如果您使用 TCP, 端å£å·ä¸Žä¸ºäº†æŽ¥å—入站的ã€åŸºäºŽ TCP çš„ã€VPN 客户端会è¯è€Œåœ¨
+VPN æœåŠ¡å™¨ä¸Šæœ€åˆå®šä¹‰å¥½çš„任一 "TCP 侦å¬ç«¯å£" 相åŒã€‚
+
+如果您使用 UDP, 端å£å·å¿…须是预先在 VPN æœåŠ¡å™¨é…置时定义好的 UDP 端å£ä¹‹ä¸€ã€‚
+ä¸è¦æ··æ·† TCP å’Œ UDP, 因为它们是互ä¸ç›¸å…³çš„。
+
+如果连接需è¦é€šè¿‡ä»£ç†æœåŠ¡å™¨ä¸­è½¬, 您还å¯ä»¥æŒ‡å®šä»£ç†æœåŠ¡å™¨åœ°å€ã€‚在é…置文件中
+指定。
+
+
+* 5. 结æŸ
+OpenVPN 对于 PacketiX VPN / SoftEther VPN 是一个独立软件。
+它是一个开æºåº”用程åº, 由第三方开å‘。
+如果你想知é“如何使用 OpenVPN 的更多信æ¯, 请å‚考 http://openvpn.net/ 。
+
diff --git a/src/bin/hamcore/openvpn_sample.ovpn b/src/bin/hamcore/openvpn_sample.ovpn
new file mode 100644
index 00000000..63cc5b85
--- /dev/null
+++ b/src/bin/hamcore/openvpn_sample.ovpn
@@ -0,0 +1,137 @@
+###############################################################################
+# OpenVPN 2.0 Sample Configuration File
+# for PacketiX VPN / SoftEther VPN Server
+#
+# !!! AUTO-GENERATED BY SOFTETHER VPN SERVER MANAGEMENT TOOL !!!
+#
+# !!! YOU HAVE TO REVIEW IT BEFORE USE AND MODIFY IT AS NECESSARY !!!
+#
+# This configuration file is auto-generated. You might use this config file
+# in order to connect to the PacketiX VPN / SoftEther VPN Server.
+# However, before you try it, you should review the descriptions of the file
+# to determine the necessity to modify to suitable for your real environment.
+# If necessary, you have to modify a little adequately on the file.
+# For example, the IP address or the hostname as a destination VPN Server
+# should be confirmed.
+#
+# Note that to use OpenVPN 2.0, you have to put the certification file of
+# the destination VPN Server on the OpenVPN Client computer when you use this
+# config file. Please refer the below descriptions carefully.
+
+
+###############################################################################
+# Specify the type of the layer of the VPN connection.
+#
+# To connect to the VPN Server as a "Remote-Access VPN Client PC",
+# specify 'dev tun'. (Layer-3 IP Routing Mode)
+#
+# To connect to the VPN Server as a bridging equipment of "Site-to-Site VPN",
+# specify 'dev tap'. (Layer-2 Ethernet Bridgine Mode)
+
+dev $TAG_TUN_TAP$
+
+
+###############################################################################
+# Specify the underlying protocol beyond the Internet.
+# Note that this setting must be correspond with the listening setting on
+# the VPN Server.
+#
+# Specify either 'proto tcp' or 'proto udp'.
+
+proto $TAG_PROTO$
+
+
+###############################################################################
+# The destination hostname / IP address, and port number of
+# the target VPN Server.
+#
+# You have to specify as 'remote <HOSTNAME> <PORT>'. You can also
+# specify the IP address instead of the hostname.
+#
+# Note that the auto-generated below hostname are a "auto-detected
+# IP address" of the VPN Server. You have to confirm the correctness
+# beforehand.
+#
+# When you want to connect to the VPN Server by using TCP protocol,
+# the port number of the destination TCP port should be same as one of
+# the available TCP listeners on the VPN Server.
+#
+# When you use UDP protocol, the port number must same as the configuration
+# setting of "OpenVPN Server Compatible Function" on the VPN Server.
+
+$TAG_BEFORE_REMOTE$remote $TAG_HOSTNAME$ $TAG_PORT$
+
+
+###############################################################################
+# The HTTP/HTTPS proxy setting.
+#
+# Only if you have to use the Internet via a proxy, uncomment the below
+# two lines and specify the proxy address and the port number.
+# In the case of using proxy-authentication, refer the OpenVPN manual.
+
+;http-proxy-retry
+;http-proxy [proxy server] [proxy port]
+
+
+###############################################################################
+# The encryption and authentication algorithm.
+#
+# Default setting is good. Modify it as you prefer.
+# When you specify an unsupported algorithm, the error will occur.
+#
+# The supported algorithms are as follows:
+# cipher: [NULL-CIPHER] NULL AES-128-CBC AES-192-CBC AES-256-CBC BF-CBC
+# CAST-CBC CAST5-CBC DES-CBC DES-EDE-CBC DES-EDE3-CBC DESX-CBC
+# RC2-40-CBC RC2-64-CBC RC2-CBC
+# auth: SHA SHA1 MD5 MD4 RMD160
+
+cipher AES-128-CBC
+auth SHA1
+
+
+###############################################################################
+# Other parameters necessary to connect to the VPN Server.
+#
+# It is not recommended to modify it unless you have a particular need.
+
+resolv-retry infinite
+nobind
+persist-key
+persist-tun
+client
+verb 3
+auth-user-pass
+
+
+###############################################################################
+# The certificate file of the destination VPN Server.
+#
+# The CA certificate file is embedded in the inline format.
+# You can replace this CA contents if necessary.
+# Please note that if the server certificate is not a self-signed, you have to
+# specify the signer's root certificate (CA) here.
+
+<ca>
+$CA$
+</ca>
+
+
+###############################################################################
+# The client certificate file (dummy).
+#
+# In some implementations of OpenVPN Client software
+# (for example: OpenVPN Client for iOS),
+# a pair of client certificate and private key must be included on the
+# configuration file due to the limitation of the client.
+# So this sample configuration file has a dummy pair of client certificate
+# and private key as follows.
+
+<cert>
+$CERT$
+</cert>
+
+<key>
+$KEY$
+</key>
+
+
diff --git a/src/bin/hamcore/pxwfp_x64.sys b/src/bin/hamcore/pxwfp_x64.sys
new file mode 100644
index 00000000..f9b47c61
--- /dev/null
+++ b/src/bin/hamcore/pxwfp_x64.sys
Binary files differ
diff --git a/src/bin/hamcore/pxwfp_x86.sys b/src/bin/hamcore/pxwfp_x86.sys
new file mode 100644
index 00000000..a40ac4a0
--- /dev/null
+++ b/src/bin/hamcore/pxwfp_x86.sys
Binary files differ
diff --git a/src/bin/hamcore/see.sys b/src/bin/hamcore/see.sys
new file mode 100644
index 00000000..1e822e8f
--- /dev/null
+++ b/src/bin/hamcore/see.sys
Binary files differ
diff --git a/src/bin/hamcore/see_x64.sys b/src/bin/hamcore/see_x64.sys
new file mode 100644
index 00000000..46ad55d2
--- /dev/null
+++ b/src/bin/hamcore/see_x64.sys
Binary files differ
diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb
new file mode 100644
index 00000000..73fb41df
--- /dev/null
+++ b/src/bin/hamcore/strtable_cn.stb
@@ -0,0 +1,7088 @@
+# SoftEther VPN String Table
+# Copyright (c) SoftEther VPN Project. All Rights Reserved.
+#
+# http://www.softether.co.jp/
+
+
+###########################################################################
+# #
+# 软件内的消æ¯ç­‰çš„å­—ç¬¦ä¸²æ•°æ® #
+# (对è¯æ¡†èµ„æºå­—符串以外) #
+# #
+###########################################################################
+
+
+
+# 环境å‚æ•°
+DEFAULT_FONT SimSun
+DEFAULT_FONT_HIGHDPI Microsoft YaHei
+DEFAULT_FONT_2 SimSun
+DEFAULT_FONT_SIZE 9
+DEFAULE_LOCALE å¹´ 月 æ—¥ 点 分 秒 星期日 星期一 星期二 星期三 星期四 星期五 星期六 天 å°æ—¶ 分 秒 (æ— )
+
+
+# 语言
+# (0: 日语, 1: 英语, 2: 中文)
+LANG 2
+LANGSTR Simplified_Chinese
+
+STRTABLE_ID SE_VPN_20121007
+
+CM_JAPANESE_ONLY_OLD_STARTUP %s\\SoftEther VPN Client 2.0 タスクトレイ.lnk
+
+
+# 软件信æ¯
+PRODUCT_NAME_VPN_CLI SoftEther VPN Client
+PRODUCT_NAME_VPN_CMGR SoftEther VPN Client 管ç†å™¨
+PRODUCT_NAME_VPN_SVR SoftEther VPN Server
+PRODUCT_NAME_VPN_BRIDGE SoftEther VPN Bridge
+PRODUCT_NAME_VPN_SMGR SoftEther VPN Server 管ç†å™¨
+PRODUCT_NAME_ELOGSVC SoftEther EtherLogger Beta Edition
+PRODUCT_NAME_ELOGMGR SoftEther EtherLogger Manager Beta Edition
+
+
+# BRANDED_C_TO_S Branded_VPN
+# BRANDED_C_FROM_S Branded_VPN
+
+# CLIENT_ID 123
+
+# Family Name for Software Update Check
+PRODUCT_FAMILY_NAME SoftEther
+
+# 产å“ä¿¡æ¯
+SE_COMPANY_URL https://selinks.org/?se
+SE_VPNAZURE_URL https://selinks.org/?vpnazure
+
+# 共通字符串
+COMMON_UNKNOWN (未知)
+
+
+# å议错误字符串
+ERR_UNKNOWN å‘生未知的错误。
+ERR_0 没有任何错误。
+ERR_1 æœåŠ¡å™¨è¿žæŽ¥å¤±è´¥ã€‚请检查网络连接,确ä¿ç›®æ ‡æœåŠ¡å™¨åœ°å€å’Œç«¯å£æ­£ç¡®ã€‚
+ERR_2 å议错误。目标æœåŠ¡å™¨è¿”回错误。
+ERR_3 连接中断。
+ERR_4 å议错误。
+ERR_5 éž SoftEther VPN 软件客户端已连接到该端å£ã€‚
+ERR_6 命令被用户å–消。
+ERR_7 æœåŠ¡å™¨æ‹’ç»æŒ‡å®šçš„认è¯æ–¹å¼ã€‚
+ERR_8 指定的虚拟 HUB 在该æœåŠ¡å™¨ä¸Šä¸å­˜åœ¨ã€‚
+ERR_9 用户身份验è¯å¤±è´¥ã€‚
+ERR_10 指定的虚拟 HUB ç›®å‰å·²åœæ­¢ã€‚等待一段时间,然åŽé‡æ–°è¿žæŽ¥ã€‚
+ERR_11 VPN 会è¯å·²åˆ é™¤ã€‚å¯èƒ½æ˜¯ä»Žå®¢æˆ·ç«¯åˆ° VPN Server 的连接被断开或管ç†å‘˜ä¸­æ–­äº†æ­¤ä¼šè¯ã€‚
+ERR_12 访问被拒ç»ã€‚
+ERR_13 VPN 通信会è¯è¶…时。有å¯èƒ½æ˜¯ä»Žå®¢æˆ·ç«¯è¿žæŽ¥åˆ° VPN Server 的连接已断开。
+ERR_14 åè®®å·æ— æ•ˆã€‚
+ERR_15 过多的 TCP/IP 连接。
+ERR_16 连接到目标æœåŠ¡å™¨æˆ–虚拟 HUB 的会è¯å¤ªå¤šã€‚
+ERR_17 连接到代ç†æœåŠ¡å™¨å¤±è´¥ã€‚
+ERR_18 代ç†æœåŠ¡å™¨é”™è¯¯ã€‚
+ERR_19 代ç†æœåŠ¡å™¨ç”¨æˆ·èº«ä»½éªŒè¯å¤±è´¥ã€‚
+ERR_20 ç”±åŒä¸€ç”¨æˆ·å‘起的连接会è¯è¿‡å¤šã€‚其他用户å¯èƒ½è¢«ä½œä¸ºåŒä¸€ç”¨æˆ·è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB。
+ERR_21 VPN Server 的软件许å¯å‘生错误。请与 VPN Server 的管ç†å‘˜è”系。
+ERR_22 无法访问虚拟网络适é…器的设备驱动程åºã€‚检查虚拟网络适é…器安装并确ä¿å®ƒä¸æ˜¯ç¦ç”¨ã€‚
+ERR_23 å‘生内部错误。
+ERR_24 访问智能å¡æˆ– USB 硬件令牌设备失败。
+ERR_25 PIN ç é”™è¯¯ã€‚
+ERR_26 在智能å¡æˆ– USB 硬件令牌设备上找ä¸åˆ°æŒ‡å®šçš„è¯ä¹¦ã€‚
+ERR_27 在智能å¡æˆ– USB 硬件令牌设备上找ä¸åˆ°æŒ‡å®šçš„密钥。
+ERR_28 对智能å¡æˆ– USB 硬件令牌设备的写æ“作失败。
+ERR_29 找ä¸åˆ°å¯¹è±¡ã€‚
+ERR_30 指定å称的虚拟网络适é…器已存在。请指定一个ä¸åŒçš„å称。
+ERR_31 虚拟网络适é…器的设备驱动程åºå®‰è£…失败。
+ERR_32 您ä¸èƒ½ä½¿ç”¨è™šæ‹Ÿç½‘络适é…器设备的指定å称。
+ERR_33 ä¸æ”¯æŒçš„。
+ERR_34 指定å称的 VPN 连接设置已存在。
+ERR_35 指定的 VPN 连接设置当å‰å·²è¿žæŽ¥ã€‚
+ERR_36 指定的 VPN 连接设置ä¸å­˜åœ¨ã€‚
+ERR_37 指定的 VPN 连接设置未连接。
+ERR_38 无效的å‚数。
+ERR_39 智能å¡æˆ– USB 硬件令牌设备错误。
+ERR_40 智能å¡æˆ– USB 硬件令牌认è¯è¢«é€‰ä¸­ï¼Œä½†è¦è¿›è¡Œè®¤è¯çš„设备没有被选中。请从连接管ç†å™¨çš„“智能å¡â€ èœå•è¿›è¡Œé€‰æ‹©ã€‚
+ERR_41 至少有一个 VPN 连接设置正在被指定的虚拟网络适é…器使用。\r\n请删除当å‰æ­£åœ¨ä½¿ç”¨æŒ‡å®šè™šæ‹Ÿç½‘络适é…器的 VPN 连接设置,或为此 VPN 连接设置指定å¦ä¸€ä¸ªè™šæ‹Ÿç½‘络适é…器。
+ERR_42 找ä¸åˆ°æŒ‡å®šçš„ VPN 连接设置所使用的虚拟网络适é…器。\r\nç¡®ä¿æ­¤è™šæ‹Ÿç½‘络适é…器存在。å¦å¤–,请确ä¿è™šæ‹Ÿç½‘络适é…器设备没有被ç¦ç”¨ã€‚\r\n\r\n如果你解决ä¸äº†æ­¤é—®é¢˜ï¼Œå¯ä»¥æ›´æ”¹ VPN 连接设置使用的虚拟网络适é…器,或者创建一个新的åŒå虚拟网络适é…器。
+ERR_43 由指定的 VPN 连接设置使用的虚拟网络适é…器当å‰è¢«å¦ä¸€ä¸ª VPN 连接设置所å ç”¨ã€‚\r\n如果有å¦ä¸€ä¸ª VPN 连接设置正在使用åŒä¸€ä¸ªè™šæ‹Ÿç½‘络适é…器,需断开 VPN 连接设置。
+ERR_44 由指定的 VPN 连接设置使用的虚拟网络适é…器已ç¦ç”¨ã€‚\r\n在使用此 VPN 连接设置å‰ï¼Œè¯·å¯ç”¨è™šæ‹Ÿç½‘络适é…器。
+ERR_45 指定值无效。
+ERR_46 连接目标ä¸æ˜¯ç¾¤é›†æŽ§åˆ¶å™¨ã€‚
+ERR_47 å°è¯•è¿žæŽ¥ã€‚
+ERR_48 连接群集控制器失败。
+ERR_49 群集控制器无法分é…一个新的会è¯åˆ°ç¾¤é›†ä¸Šã€‚
+ERR_50 无法管ç†ç¾¤é›†æˆå‘˜æœåŠ¡å™¨çš„虚拟 HUB。
+ERR_51 用于连接的用户密ç æ˜¯ç©ºçš„,所以远程连接被ç¦æ­¢ã€‚如果使用空密ç ï¼Œåªè¢«å…许连接 VPN Server 的本地主机(127.0.0.1)。
+ERR_52 没有足够的æƒé™ã€‚
+ERR_53 找ä¸åˆ°æŒ‡å®šçš„监å¬å™¨ã€‚
+ERR_54 指定监å¬ç«¯å£å·å·²ç»å­˜åœ¨ã€‚
+ERR_55 è¿™ä¸æ˜¯ä¸€ä¸ªç¾¤é›†æˆå‘˜æœåŠ¡å™¨ã€‚
+ERR_56 ä¸æ”¯æŒæŒ‡å®šçš„加密算法å。
+ERR_57 具有指定å称的虚拟 HUB å·²ç»å­˜åœ¨äºŽæœåŠ¡å™¨ä¸Šã€‚
+ERR_58 已存在过多虚拟 HUB。请删除过期的虚拟 HUB 以释放资æºï¼Œä¾›æ–°çš„虚拟 HUB 使用。
+ERR_59 具有指定å称的级è”å·²ç»å­˜åœ¨ã€‚
+ERR_60 群集的æœåŠ¡å™¨ä¸Šä¸èƒ½åˆ›å»ºçº§è”。
+ERR_61 指定的级è”处于脱机状æ€ã€‚
+ERR_62 访问列表过多。
+ERR_63 用户过多。
+ERR_64 组过多。
+ERR_65 指定的组ä¸å­˜åœ¨ã€‚
+ERR_66 虚拟 HUB 上已存在指定å称的用户。
+ERR_67 虚拟 HUB 上已存在指定å称的群。
+ERR_68 具有指定å称的用户在æœåŠ¡å™¨ä¸Šå·²å­˜åœ¨ï¼Œä½†èº«ä»½éªŒè¯ç±»åž‹ä¸æ˜¯å¯†ç éªŒè¯ã€‚无法更改密ç ã€‚
+ERR_69 用户å或旧密ç è¾“å…¥ä¸æ­£ç¡®ã€‚请注æ„密ç æœ‰å¤§å°å†™åŒºåˆ†ã€‚
+ERR_70 埼玉。
+ERR_71 因应日本ç»æµŽäº§ä¸šçœå‘½ä»¤ï¼ŒSoftEther æš‚åœå½“å‰é…å‘。
+ERR_72 因应 IPA 命令,SoftEther æš‚åœå½“å‰é…å‘。
+ERR_73 无法断开级è”会è¯ã€‚è¦åˆ é™¤ä¼šè¯ï¼Œè¯·åœæ­¢çº§è”。
+ERR_74 VPN Server 的连接设置未完æˆã€‚è¯·å…ˆå®Œæˆ VPN 连接设置。
+ERR_75 虚拟专用网 VPN Server 连接已ç»å¼€å§‹ã€‚
+ERR_76 未连接到 VPN Server。
+ERR_77 指定的 X509 è¯ä¹¦æ–‡ä»¶ä¸åŒ…å« RSA 1024 bit,1536 bit,2048 bit,3072 bit ä½æˆ– 4096 bit 的公共密钥。SoftEther VPN è½¯ä»¶ä»…æ”¯æŒ RSA 1024 bit,1536 bit,2048 bit,3072 bit ä½æˆ– 4096 bit è¯ä¹¦ã€‚
+ERR_78 无法断开 SecureNAT 会è¯ã€‚è¦åˆ é™¤ä¼šè¯ï¼Œè¯·åœæ­¢ SecureNAT 功能。
+ERR_79 无法在群集环境中å¯ç”¨ SecureNAT。
+ERR_80 SecureNAT 未开始工作。
+ERR_81 至 VPN Server çš„ VPN 连接会è¯è¢«ç½‘络管ç†å‘˜å®‰è£…的防ç«å¢™è®¾å¤‡ä¸­æ–­ã€‚请è”络网络管ç†å‘˜ä»¥èŽ·å–进一步信æ¯ã€‚
+ERR_82 无法断开本地网桥会è¯ã€‚è¦åˆ é™¤ä¼šè¯ï¼Œè¯·åœæ­¢æœ¬åœ°ç½‘桥。
+ERR_83 本地网桥未开始工作。
+ERR_84 目标 VPN Server 无法使用本地网桥。å‚考在线帮助或其他文档以获å–在指定 VPN Server 上使用本地网桥的设置方法。
+ERR_85 无法信任目标æœåŠ¡å™¨æ供的è¯ä¹¦ã€‚始终验è¯æœåŠ¡å™¨è¯ä¹¦åœ¨ VPN 连接设置中被å¯ç”¨ã€‚请注册一个å¯ä¿¡ä»»çš„æ ¹è¯ä¹¦æˆ–注册一个å•ç‹¬çš„è¯ä¹¦ã€‚
+ERR_86 目标æœåŠ¡å™¨çš„产å“代ç ä¸æ­£ç¡®ã€‚无法从此客户端连接。
+ERR_87 客户端和æœåŠ¡ç«¯è½¯ä»¶ç‰ˆæœ¬ä¸åŒã€‚请更新软件。
+ERR_88 无法添加æ•èŽ·è®¾å¤‡ã€‚很å¯èƒ½åŒä¸€æ•èŽ·è®¾å¤‡å·²ç»æ³¨å†Œã€‚
+ERR_89 无法从该客户端连接到目标æœåŠ¡å™¨ã€‚一个特殊客户端软件是必需的。
+ERR_90 指定æ•èŽ·è®¾å¤‡æœªæ³¨å†Œã€‚
+ERR_91 无法断开虚拟 3 层交æ¢æœºä¼šè¯ã€‚è¦åˆ é™¤ä¼šè¯ï¼Œè¯·åœæ­¢è™šæ‹Ÿ 3 层交æ¢æœºã€‚
+ERR_92 具有指定å称的虚拟 3 层交æ¢æœºå·²å­˜åœ¨ã€‚指定一个ä¸åŒçš„å称。
+ERR_93 找ä¸åˆ°æŒ‡å®šçš„虚拟 3 层交æ¢æœºã€‚
+ERR_94 指定的å称无效。检查å称是å¦æœ‰ä¸èƒ½ä½¿ç”¨çš„字符
+ERR_95 无法添加虚拟 3 层接å£ã€‚
+ERR_96 无法删除虚拟 3 层接å£ã€‚
+ERR_97 与指定虚拟 3 层交æ¢æŽ¥å£çš„目标虚拟 HUB 连接的虚拟 3 层接å£å·²åœ¨è™šæ‹Ÿ 3 层交æ¢æœºä¸­å­˜åœ¨ã€‚ä¸èƒ½åœ¨åŒä¸€ä¸ªè™šæ‹Ÿ 3 层交æ¢æœºä¸­å®šä¹‰è¶…过一个连接到åŒä¸€ä¸ªè™šæ‹Ÿ HUB 的虚拟 3 层接å£ã€‚
+ERR_98 无法添加路由表项。
+ERR_99 无法删除路由表项。
+ERR_100 指定的路由表项已存在。
+ERR_101 客户端和æœåŠ¡å™¨çš„时钟彼此ä¸åŒæ­¥ã€‚检查时间设置。
+ERR_102 无法å¯åŠ¨æ­¤è™šæ‹Ÿ 3 层交æ¢æœºã€‚ è¦å¯åŠ¨è™šæ‹Ÿ 3 层交æ¢æœºï¼Œå¿…须在虚拟 3 层交æ¢æœºå®šä¹‰è‡³å°‘一个虚拟接å£ã€‚
+ERR_103 目标 VPN Server 没有足够的客户端连接许å¯è¯ã€‚请与æœåŠ¡å™¨ç®¡ç†å‘˜è”系。
+ERR_104 目标 VPN Server 没有足够的网桥许å¯è¯ã€‚请与æœåŠ¡å™¨ç®¡ç†å‘˜è”系。
+ERR_105 由于目å‰çš„技术问题,目标 VPN Server 没有收到连接。请ç¨å€™ï¼Œæˆ–与 VPN Server 管ç†å‘˜è”系,è¦æ±‚进行æœåŠ¡å™¨æ—¥å¿—文件检查。
+ERR_106 目标 VPN Server çš„è¯ä¹¦å·²è¿‡æœŸã€‚请与 VPN Server 管ç†å‘˜è”系。
+ERR_107 监测模å¼è¦æ±‚了一个连接。但是,连接用户的安全策略ä¸å…许监察模å¼ã€‚
+ERR_108 网桥 / 路由模å¼è¦æ±‚了一个连接。但是,连接用户的安全策略ä¸å…许网桥 / 路由模å¼ã€‚
+ERR_109 一个æ¥è‡ªå®¢æˆ·ç«¯ IP 地å€çš„连接被虚拟 HUB çš„æº IP é™åˆ¶åˆ—表拒ç»ã€‚
+ERR_110 项目数过多。
+ERR_111 内存ä¸è¶³ã€‚
+ERR_112 指定的对象已存在。指定的对象已存在。
+ERR_113 å‘生致命的错误。很å¯èƒ½æ˜¯è¯¥ç¨‹åºçš„æ“作无法继续。
+ERR_114 目标 VPN Server 已检测到软件许å¯è¯é”™è¯¯ã€‚连接被拒ç»ã€‚请与 VPN Server 管ç†å‘˜è”系。
+ERR_115 通过 Internet 连接到 SoftEther å…¬å¸æ供的一个é‡è¦æœåŠ¡å™¨çš„目标 VPN Server 无法验è¯è®¸å¯è¯ã€‚请ç¨å€™ï¼Œæˆ–与 VPN Server 管ç†å‘˜è”系,è¦æ±‚检查æœåŠ¡å™¨æ—¥å¿—文件和检查æœåŠ¡å™¨æœ¬èº«çš„ Internet 连接状æ€ã€‚
+ERR_116 客户端的软件许å¯è¯é”™è¯¯ã€‚连接被拒ç»ã€‚
+ERR_117 命令或文件åä¸æ­£ç¡®
+ERR_118 许å¯è¯å¯†é’¥ä¸æ­£ç¡®
+ERR_119 VPN Server 上没有注册有效的产å“许å¯è¯ã€‚请与 VPN Server 管ç†å‘˜è”系。
+ERR_120 VPN Server 作为群集è¿è¡Œæ‰€éœ€è¦çš„许å¯è¯æœªæ³¨å†Œã€‚请与 VPN Server 的管ç†å‘˜ã€‚
+ERR_121 VPN 连接设置已使用“Web 安装程åºåˆ›å»ºå·¥å…·åŒ…â€æˆ–“简å•å®‰è£…程åºåˆ›å»ºå·¥å…·åŒ…â€å®‰è£…。目标æœåŠ¡å™¨ç‰ˆæœ¬ä¸æ”¯æŒæ”¯æŒ SoftEther VPN çš„ 2.0 管ç†åŒ…。请与系统管ç†å‘˜æˆ–安装程åºåˆ›å»ºè€…è”系。
+ERR_122 与 VPN Server SDK for .NET,它åªèƒ½è¿žæŽ¥åˆ° SoftEther VPN Server ç‰ˆæœ¬ï¼Œæ”¯æŒ SoftEther VPN çš„ 2.0 管ç†åŒ…。 VPN Server 的目标ä¸æ˜¯ä¸€ä¸ªç‰ˆæœ¬ï¼Œæ”¯æŒ SoftEther VPN çš„ 2.0 管ç†åŒ…。与系统管ç†å‘˜è”系。
+ERR_123 试用版软件在目标æœåŠ¡å™¨ä¸Šå·²è¿‡æœŸã€‚è”ç³»æœåŠ¡å™¨çš„系统管ç†å‘˜ä»¥ä¸‹è½½æ–°çš„测试版或从 http://www.softether.com/ 下载完整版本。
+
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã‹ã‚‰ -----
+ERR_124 至 VPN Server çš„ VPN 连接在æœåŠ¡å™¨ç«¯è¢«æ‹’ç»ã€‚
+ERR_125 至 VPN Server çš„ VPN 连接在客户端被拒ç»ã€‚
+ERR_126 因为一段时期已ç»è¿‡åŽ»ï¼Œå®‰å…¨ç­–略强制执行自动断开了 VPN 会è¯ã€‚如果你想继续,请å†æ¬¡è¿žæŽ¥ã€‚
+ERR_127 VPN Server 需è¦ç‰¹æ®Šç‰ˆæœ¬çš„ VPN Client 软件。请咨询您的管ç†å‘˜ã€‚
+ERR_128 注册用户对象的数é‡è¶…过了 VPN Server 上产å“许å¯è¯å…许的最大数é‡ã€‚您ä¸èƒ½å†æ·»åŠ ç”¨æˆ·å¯¹è±¡äº†ï¼Œé™¤éžä½ åˆ é™¤æ—§çš„用户或å‡çº§åˆ°äº§å“的更高版本。
+ERR_129 认购åˆåŒåœ¨ VPN Server çš„ã€è¿™ä¸ªç‰ˆæœ¬çš„ã€å‘布日期å‰å·²ç»åˆ°æœŸã€‚客户在此认购åˆåŒæœŸå†…被授æƒä½¿ç”¨ VPN Server的版本,。客户应延长认购期。客户也能“é™çº§â€ VPN Server 的版本,至认购结æŸå‰å‘布的è€ç‰ˆæœ¬ã€‚如果您想é™çº§ç‰ˆæœ¬ï¼Œæ—§ç‰ˆæœ¬åœ¨ http://www.softether.com/
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã¾ã§ -----
+ERR_130 试用许å¯è¯å¯†é’¥æ怕ä¸èƒ½é¢‘ç¹åœ°è¢«ç›¸åŒçš„客户获å–。请考虑购买的正å¼ç‰ˆã€‚
+ERR_131 几个在åŒä¸€ IP 地å€çš„ VPN Server。您å¯ä»¥æŒ‡å®šç›®æ ‡æœåŠ¡å™¨çš„ç§æœ‰ IP 地å€æˆ–具体的主机åï¼Œå¦‚â€œå…¨çƒ IP 地å€æˆ–主机å/192.168.x.xâ€ã€‚如果æœåŠ¡å™¨ç«¯ä½¿ç”¨ NAT,é…ç½® NAT 为打开ã€è½¬å‘或转让相应的端å£ã€‚
+ERR_132 åŠ¨æ€ DNS æœåŠ¡çš„密钥与他人é‡å¤ã€‚密钥将被自动é‡ç½®ã€‚
+ERR_133 æŒ‡å®šçš„åŠ¨æ€ DNS 主机å已被使用。请更改主机å。
+ERR_134 æŒ‡å®šçš„åŠ¨æ€ DNS 主机å有一个无效的字符。请更改主机å。
+ERR_135 æŒ‡å®šçš„åŠ¨æ€ DNS 主机å的长度太长。主机å必须等于或少于 31 个字æ¯ã€‚
+ERR_136 æœªæŒ‡å®šåŠ¨æ€ DNS 主机å。
+ERR_137 æŒ‡å®šçš„åŠ¨æ€ DNS 主机å的长度太长。主机å必须是等于或大于 3 个字æ¯ã€‚
+ERR_138 在虚拟 HUB 上指定的用户的密ç ã€åœ¨ä½¿ç”¨ MS-CHAP v2 验è¯ä¹‹å‰ï¼Œå¿…é¡»é‡ç½®ã€‚请让 VPN Server 的管ç†å‘˜ï¼Œé€šè¿‡ 4.0 或更高版本的 VPN Server 管ç†å™¨æˆ– vpncmd é‡è®¾å¯†ç ã€‚或者,您自己å¯ä»¥é€šè¿‡ VPN Client 更改密ç ã€‚
+ERR_139 åŠ¨æ€ DNS æœåŠ¡å™¨çš„连接被中断。
+ERR_140 无法åˆå§‹åŒ– ICMP(PING)å议。 VPN Server 的进程å¯èƒ½ä»¥æ™®é€šç”¨æˆ·æƒé™åœ¨è¿è¡Œã€‚在这ç§æƒ…况下, VPN Server 作为系统æœåŠ¡è¿è¡Œã€‚ (在 Linux / UNIX,以 root æƒé™è¿è¡Œ)。
+ERR_141 无法打开 DNS ç«¯å£ 53。请确认没有其他的 DNS æœåŠ¡å™¨ç¨‹åº(例如,BIND 或 Microsoft DNS æœåŠ¡å™¨)在åŒä¸€å°è®¡ç®—机上。如果有冲çªçš„æœåŠ¡ï¼Œåœæ­¢ä»–们。或在 Linux/ UNIX çš„ root æƒé™è¿è¡Œ VPN Server 的进程。
+ERR_142 OpenVPN Server 功能未å¯ç”¨ã€‚
+ERR_143 è¯ä¹¦éªŒè¯åŠŸèƒ½å’Œå¤–部æœåŠ¡å™¨éªŒè¯åŠŸèƒ½å°šæœªåœ¨ SoftEther VPN çš„å¼€æºç‰ˆæœ¬ä¸Šå®žæ–½ã€‚å¯ä»¥é€‰æ‹©åŒ¿å身份验è¯æˆ–密ç éªŒè¯æ¥ä»£æ›¿ã€‚
+ERR_144 ä¸å¯æŽ¥å—çš„æ“作。使用 VPN Gate 控制é¢æ¿æ›´æ”¹ VPN Gate 中继æœåŠ¡å™¨è®¾ç½®ã€‚
+ERR_145 ä¸å¯æŽ¥å—çš„æ“作。使用 VPN Gate 实用工具修改 VPN Gate 公共 VPN 中继æœåŠ¡å™¨çš„连接设置。
+ERR_146 VPN Gate æœåŠ¡è¿è¡Œåœ¨ VPN 客户端程åºå†…。在此å±å¹•ä¸Šï¼Œä½ ä¸èƒ½åœæ­¢ VPN Gate æœåŠ¡ã€‚使用 VPN 客户端管ç†å™¨æ¥å¯ç”¨æˆ–ç¦ç”¨ VPN Gate æœåŠ¡ã€‚
+ERR_147 ä¸æ”¯æŒæ­¤åŠŸèƒ½ã€‚它尚未在 SoftEther VPN çš„å¼€æºç‰ˆæœ¬ä¸Šå®žæ–½ã€‚
+
+
+#关于许å¯è¯
+LICENSE_INFO_URL https://selinks.org/?new_license
+LICENSE_SUPPORT_URL https://selinks.org/?q=license_info&id=%s
+LICENSE_STATUS_OK 有效
+LICENSE_STATUS_EXPIRED 已过期
+LICENSE_STATUS_ID_DIFF æœåŠ¡å™¨ ID ä¸ä¸€è‡´
+LICENSE_STATUS_DUP é‡å¤
+LICENSE_STATUS_INSUFFICIENT 需è¦å…¶ä»–许å¯è¯
+LICENSE_STATUS_COMPETITION 与其他许å¯è¯çš„竞争
+LICENSE_STATUS_NONSENSE 当å‰ç‰ˆæœ¬æ— æ„义
+LICENSE_STATUS_CPU CPU 类型ä¸å…¼å®¹
+LICENSE_STATUS_OTHERERROR 未知错误
+
+
+#关于TCP最优化
+TCPOPT_NOT_SUPPORTED TCP 通讯设定最优化实用程åºï¼Œè¿™ä¸ªæ“作系统ä¸èƒ½ä½¿ç”¨ã€‚
+TCPOPT_NOT_ADMIN 没有管ç†æƒé™çš„用户ä¸èƒ½ä½¿ç”¨ TCP å议优化工具。
+
+
+# Windows Vista / Windows 7 / Windows 8 优化
+VISTA_MMCSS_MSG 你想优化 Windows Vista / Windows 7 / Windows 8 用于使用 VPN 进行多媒体文件的播放å—? (如: 视频ã€éŸ³é¢‘å’Œæµåª’体)
+VISTA_MMCSS_MSG_2 Windows Vista / Windows 7 / Windows 8 çš„ VPN 优化已ç»å®Œæˆã€‚\r\n你想进行远程优化é…ç½®å—?
+VISTA_MMCSS_MSG_3 您ä¸èƒ½åœ¨å½“å‰çŽ¯å¢ƒä¸‹è¿›è¡Œä¼˜åŒ–。
+VISTA_MMCSS_MSG_4 您必须具有管ç†å‘˜æƒé™æ‰å¯ä½¿ç”¨æ­¤åŠŸèƒ½ã€‚\r\n请注æ„,在 Windows Vista / Windows 7 / Windows 8 中,您应该使用“以管ç†å‘˜èº«ä»½è¿è¡Œâ€æ‰§è¡Œç¨‹åºã€‚
+VISTA_MMCSS_MSG_5 优化完æˆã€‚
+VISTA_MMCSS_MSG_6 优化é…置被删除。
+
+
+# 关于PKCS 实用程åº
+PKCS_UTIL_TITLE PKCS#12 写入实用程åº
+PKCS_UTIL_SAVEDLG_TITLE 选择你è¦å†™å…¥åˆ° USB 令牌中的 PKCS#12 文件
+PKCS_UTIL_READ_ERROR 无法读å–文件: "%s"。
+PKCS_UTIL_WRITE_OK_MSG 文件 %s 已写入到 USB 硬件令牌中。
+PKCS_UTIL_DELETE_OK_MSG PKCS#12 è¯ä¹¦æ•°æ®å·²ä»Ž USB 硬件令牌中删除。
+PKCS_UTIL_SECA_FILENAME seca_p12
+PKCS_MAKE_SURE 写入 USB 令牌的 PKCS#12 è¯ä¹¦æ•°æ®å°†è¢«åˆ é™¤ã€‚\r\n一旦数æ®è¢«åˆ é™¤ï¼Œå°†æ— æ³•æ¢å¤ã€‚\r\r\n\r\r\n你想继续å—?
+PKCS_UTIL_BAD_FILE 指定的文件ä¸èƒ½è¯†åˆ«ä¸º PKCS#12 文件。
+
+
+# 关于共通对è¯æ¡†
+DLG_ALL_FILES 所有文件(*.*)|*.*
+DLG_CERT_FILES X509 è¯ä¹¦æ–‡ä»¶ (*.CER;*.CRT)|*.cer;*.crt|所有文件 (*.*)|*.*
+DLG_KEY_FILTER 密钥文件 (*.KEY;*.PEM)|*.key;*.pem|所有文件 (*.*)|*.*
+DLG_PKCS12_FILTER PKCS#12 文件(*.P12;*.PFX)|*.p12;*.pfx|所有文件 (*.*)|*.*
+DLG_CERT_OR_P12_FILTER X509 è¯ä¹¦æˆ– PKCS#12 文件(*.CER;*.CRT;*.P12;*.PFX)|*.cer;*.crt;*.p12;*.pfx|X509 è¯ä¹¦æ–‡ä»¶(*.CER;*.CRT)|*.cer;*.crt|PKCS#12 文件(*.P12;*.PFX)|*.p12;*.pfx|所有文件 (*.*)|*.*
+DLG_CONFIG_FILES 设置文件 (*.CONFIG)|*.config|所有文件 (*.*)|*.*
+DLG_KEY_OR_P12_FILTER 密钥文件或 PKCS#12 文件 (*.KEY;*.PEM;*.P12;*.PFX)|*.key;*.pem;*.p12;*.pfx|密钥文件 (*.KEY;*.PEM)|*.key;*.pem|PKCS#12 文件(*.P12;*.PFX)|*.p12;*.pfx|所有文件 (*.*)|*.*
+DLG_ZIP_FILER ZIP 文件(*.ZIP)|*.zip|所有文件(*.*)|*.*
+DLG_OPEN_CERT 请选择è¯ä¹¦æ–‡ä»¶
+DLG_OPEN_KEY 请选择密钥文件
+DLG_OPEN_KEY_WITH_CERT 请选择相应的密钥文件
+DLG_OPEN_FILE_ERROR 无法读å–指定文件 "%S"。
+DLG_OPEN_FILE_ERROR_W 无法读å–指定文件 "%s"。
+DLG_BAD_P12 文件 "%S" ä¸æ˜¯æœ‰æ•ˆçš„ PKCS#12 è¯ä¹¦æ–‡ä»¶ã€‚
+DLG_BAD_P12_W 文件 "%s" ä¸æ˜¯æœ‰æ•ˆçš„ PKCS#12 è¯ä¹¦æ–‡ä»¶ã€‚
+DLG_BAD_X509 文件 "%S" ä¸æ˜¯æœ‰æ•ˆçš„ X509 è¯ä¹¦æ–‡ä»¶ã€‚
+DLG_BAD_X509_W 文件 "%s" ä¸æ˜¯æœ‰æ•ˆçš„ X509 è¯ä¹¦æ–‡ä»¶ã€‚
+DLG_BAD_KEY 文件 "%S" ä¸æ˜¯æœ‰æ•ˆçš„ RSA 密钥文件。
+DLG_BAD_KEY_W 文件 "%s" ä¸æ˜¯æœ‰æ•ˆçš„ RSA 密钥文件。
+DLG_BAD_SIGNATURE 密钥无法与指定è¯ä¹¦ä¸­çš„公钥相对应。\r\n请æä¾›å¯å¯¹åº”的密钥。
+DLG_SAVE_CERT 请指定ä¿å­˜è¯ä¹¦çš„文件å
+DLG_SAVE_KEY 请指定ä¿å­˜å¯†é’¥çš„文件å
+DLG_SAVE_P12 请指定ä¿å­˜è¯ä¹¦å’Œå¯†é’¥çš„文件å
+DLG_SAVE_FILE 文件ä¿å­˜ä¸º
+DLG_SAVE_OPENVPN_CONFIG 指定一个文件åä¿å­˜ ZIP æ–‡ä»¶ï¼ŒåŒ…å« OpenVPN 的设置
+DLG_CERT_SAVE_OK è¯ä¹¦ä¿å­˜æˆåŠŸã€‚
+DLG_CERT_SAVE_ERROR è¯ä¹¦æ— æ³•ä¿å­˜ã€‚
+DLG_KEY_SAVE_OK 密钥ä¿å­˜æˆåŠŸã€‚
+DLG_KEY_SAVE_ERROR 密钥无法ä¿å­˜ã€‚
+DLG_KEY_PAIR_SAVE_OK è¯ä¹¦å’Œå¯†é’¥ä¿å­˜æˆåŠŸã€‚
+DLG_KEY_PAIR_SAVE_ERROR 无法ä¿å­˜çš„è¯ä¹¦å’Œä¸ªäººå¯†é’¥ã€‚
+DLG_REBOOT_INFO 计算机将被在 %u 秒åŽé‡æ–°å¯åŠ¨ã€‚
+DLG_REBOOT_INFO_2 é‡æ–°å¯åŠ¨...
+DLG_REBOOT_ERROR 计算机é‡æ–°å¯åŠ¨å¤±è´¥ã€‚\r\n\r\n请手动é‡æ–°å¯åŠ¨è®¡ç®—机。
+DLG_SAVE_CONFIG 指定一个文件åä¿å­˜é…ç½®
+DLG_OPEN_CONFIG 指定é…置文件导入
+DLG_STRING_DEFTITLE 输入字符串
+DLG_STRING_DEFINFO 请输入字符串。
+DLG_ABOUT_LEGAL 法律公告
+DLG_UPDATE_DATE \ (Released on %S)
+DLG_UPDATE_HINT 按 OK 查看网页æµè§ˆå™¨æœ€æ–°æ›´æ–°çš„ä¿¡æ¯ã€‚\r\n\r\n您必须手动下载并安装更新。如果你想在其他电脑上更新软件,您必须登录到计算机通过远程桌é¢æˆ– SSH 进行下载和更新。
+
+
+# 关于竞争进程
+BAD_PROCESS_TITLE 有关 %S 的警告
+BAD_PROCESS_MESSAGE 在此计算机上è¿è¡Œçš„软件 "%S" 会产生问题。\r\n\r\n"%S" 问题å¯èƒ½ä¼šå¯¼è‡´ VPN 通信ä¸ç¨³å®šå’Œé”™è¯¯ã€‚\r\n\r\n如果由于 VPN 与 "%S" çš„å…±åŒä½¿ç”¨è€Œå¯¼è‡´ VPN ä¸ç¨³å®šï¼Œè¯·åœæ­¢æˆ–å¸è½½ "%S"。(请注æ„,在æŸäº›æƒ…况下,由于软件的性质,å³ä½¿ä½ åœæ­¢è¯¥è½¯ä»¶ï¼Œä½†é—®é¢˜ä»ä¼šä¿ç•™åœ¨è®¡ç®—机上。) \r\n
+
+
+# 关于硬件令牌
+SEC_SMART_CARD 智能å¡
+SEC_USB_TOKEN USB 令牌
+SEC_INIT_MSG_1 将智能å¡æ’入智能å¡é˜…读器中,并输入 PIN ç ã€‚
+SEC_INIT_MSG_2 å°† USB 硬件令牌与计算机的 USB 端å£ç›¸è¿žï¼Œè¾“å…¥ PIN ç ã€‚
+SEC_OPENING å¼€å¯è®¾å¤‡...
+SEC_CLOSING 关闭设备...
+SEC_OPEN_SESSION å¼€å¯å®‰å…¨ä¼šè¯...
+SEC_CLOSE_SESSION 关闭安全会è¯...
+SEC_LOGIN 登录令牌...
+SEC_LOGOUT 登出令牌...
+SEC_INIT_BATCH å¯åŠ¨æ‰¹å¤„ç†...
+SEC_READ_DATA 读å–æ•°æ®...
+SEC_WRITE_DATA 写入数æ®...
+SEC_READ_CERT 读å–è¯ä¹¦...
+SEC_WRITE_CERT 写入è¯ä¹¦...
+SEC_DELETE 删除对象...
+SEC_SIGN 密匙处ç†æ•°å­—ç­¾å...
+SEC_WRITE_KEY 写入密匙...
+SEC_ENUM 枚举对象...
+SEC_FINISHED æ“作完æˆã€‚
+SEC_ERROR_INVALID_ID 指定的安全设备 (设备 %u) 无效。
+SEC_ERROR_OPEN_DEVICE 无法打开设备 %S,请确ä¿è¯¥è®¾å¤‡è¿žæŽ¥åˆ°è®¡ç®—机上。
+SEC_ERROR_OPEN_DEVICEEX 无法打开设备 %S,请确ä¿è¯¥è®¾å¤‡è¿žæŽ¥åˆ°è®¡ç®—机上。\r\n\r\n如果使用公钥基础设施 (PKI) 特殊客户端软件,则需è¦åœ¨â€œPKI 实用工具†(从“开始â€èœå•é€‰æ‹©) 中,选择智能å¡è®¾å¤‡ã€‚
+SEC_ERROR_OPEN_SESSION 无法在设备 %S 中å¯åŠ¨å®‰å…¨ä¼šè¯ã€‚请确ä¿é€‰æ‹©æ­£ç¡®çš„设备。
+SEC_ERROR_LOGIN 输入的 PIN ç é”™è¯¯ã€‚
+SEC_ERROR_NOT_FOUND_1 智能å¡ä¸­ä¸å­˜åœ¨æŒ‡å®šçš„对象。确ä¿æ’入正确的智能å¡ã€‚
+SEC_ERROR_NOT_FOUND_2 USB 硬件令牌中ä¸å­˜åœ¨æŒ‡å®šçš„对象。确ä¿è¿žæŽ¥æ­£ç¡®çš„ USB 硬件令牌。
+SEC_ERROR_SIGN_1 智能å¡ä¸­ä¸å­˜åœ¨å¯†é’¥æˆ–æ•°å­—ç­¾åæ“作失败。确ä¿æ’入正确的智能å¡ã€‚
+SEC_ERROR_SIGN_2 USB 硬件令牌中ä¸å­˜åœ¨å¯†é’¥æˆ–æ•°å­—ç­¾åæ“作失败。确ä¿è¿žæŽ¥æ­£ç¡®çš„ USB 硬件令牌。
+SEC_ERROR_WRITE_1 无法在智能å¡ä¸­å†™å…¥å¯¹è±¡ã€‚智能å¡ä¸­å¯èƒ½æ²¡æœ‰è¶³å¤Ÿçš„存储空间。
+SEC_ERROR_WRITE_2 无法在 USB 硬件令牌中写入对象。USB 硬件令牌中å¯èƒ½æ²¡æœ‰è¶³å¤Ÿçš„存储空间。
+SEC_ERROR_ENUM 对令牌中的存储对象枚举失败。
+SEC_ERROR_DELETE 对指定对象删除失败。å¯èƒ½æŒ‡å®šå¯¹è±¡åœ¨å†…存中ä¸å­˜åœ¨ã€‚
+SEC_COLUMN1 设备å称
+SEC_COLUMN2 ç§ç±»
+SEC_COLUMN3 制造商
+SEC_COLUMN4 DLL å
+SEC_INVALID_ID 指定的智能å¡è®¾å¤‡ä¸å­˜åœ¨ã€‚请é‡æ–°é€‰æ‹©æ™ºèƒ½å¡ç§ç±»ã€‚
+SEC_MGR_COLUMN1 å称
+SEC_MGR_COLUMN2 ç§ç±»
+SEC_MGR_COLUMN3 ç§æœ‰
+SEC_TYPE_DATA æ•°æ®
+SEC_TYPE_CERT è¯ä¹¦
+SEC_TYPE_KEY 密钥
+SEC_TYPE_PUB 公钥
+SEC_YES 是
+SEC_NO å¦
+SEC_NONE æ— 
+SEC_IMPORT_DATA 选择你想导入的数æ®
+SEC_IMPORT_CERT 选择你è¦å¯¼å…¥çš„è¯ä¹¦
+SEC_IMPORT_KEY 选择你è¦å¯¼å…¥çš„密钥
+SEC_READ_FAILED 选择你è¦å¯¼å…¥çš„è¯ä¹¦ã€‚
+SEC_DATA_TOO_BIG 指定数æ®å¤ªå¤§ã€‚大于 %u 个字节的数æ®æ— æ³•å†™å…¥æ™ºèƒ½å¡ã€‚
+SEC_OBJECT_NAME_TITLE æ’入对象的å称
+SEC_OBJECT_NAME_INFO 指定写入新智能å¡çš„对象å称。您å¯ä»¥æŒ‡å®šä¸åŒ…括字æ¯æ•°å­—字符åŒå­—节字符和特殊对象的å称。\r\n警告: 如果å¡ä¸Šå·²æœ‰åŒä¸€ç±»åž‹ç›¸åŒå称的对象,该对象将被覆盖。
+SEC_DELETE_MSG 选定的对象将从智能å¡ä¸­åˆ é™¤ã€‚\r\nä½ è¦è¿™æ ·åšå—?
+SEC_OBJECT_IMPORT_OK 对象被写入智能å¡ã€‚
+SEC_OBJECT_EXPORT_OK 从智能å¡ä¸­è¯»å–çš„æ•°æ®å·²è¢«ä¿å­˜ã€‚
+SEC_NEW_CERT_IMPORT_OK 新创建的è¯ä¹¦å·²è¢«å†™å…¥æ™ºèƒ½å¡ã€‚
+SEC_CURRENT_DEVICE 当å‰é€‰ä¸­è®¾å¤‡ %S。
+SEC_CURRENT_NO_DEVICE 选择è¦ä½¿ç”¨çš„智能å¡ã€‚
+SEC_NO_SECURE_DEVICE 系统中没有安装与 SoftEther VPN 兼容的智能å¡æˆ–硬件安全å£ä»¤è®¾å¤‡ã€‚\r\n\r\nè¦ä½¿ç”¨æ™ºèƒ½å¡æˆ–硬件å£ä»¤ï¼Œéœ€è¦åœ¨ Windows 中安装 PKCS#11 兼容设备驱动。并且, SoftEther VPN 需è¦æ”¯æŒæ­¤è®¾å¤‡ç±»åž‹ã€‚\r\n请确定已安装系统兼容设备驱动。\r\n请在 SoftEther 有é™å…¬å¸ç½‘站上查阅 SoftEther VPN 兼容设备列表。而且,将软件更新到最新版本也有助于增大设备兼容范围。
+SEC_PIN_DEVICE_OPEN_ERR 无法连接设备 "%S"。请确ä¿ç¡¬ä»¶æ­£ç¡®è¿žæŽ¥ã€‚
+SEC_PIN_CURRENT_BAD 当å‰çš„ PIN ç æ˜¯ä¸æ­£ç¡®çš„。
+SEC_PIN_CHANGE_FAILED 更改 PIN ç å¤±è´¥ã€‚
+SEC_PIN_OK PIN ç å·²å˜æ›´ã€‚
+
+
+# TCP 连接会è¯
+CONNECTDLG_CAPTION 连接中...
+CONNECTDLG_MESSAGE 连接到æœåŠ¡å™¨ "%S" (TCP 端å£: %u)...
+CONNECTDLG_CANCELING å–消连接。请ç¨å€™...
+
+
+# NIC ä¿¡æ¯ä¼šè¯
+NICINFO_1 已连接到 VPN Server。
+NICINFO_1_1 在 VPN 上的 DHCP æœåŠ¡å™¨è¯·æ±‚一个 IP 地å€ã€‚
+NICINFO_1_2 决定在 VPN 中使用的 IP 地å€ã€‚
+
+NICINFO_2 VPN 会è¯å·²å»ºç«‹ã€‚
+NICINFO_2_1 分é…çš„ IP 地å€æ˜¯ %S。
+
+NICINFO_3 VPN 会è¯å·²å»ºç«‹ã€‚
+NICINFO_3_1 该 IP 地å€æ˜¯ %S å·²å¯ä»¥ä½¿ç”¨ã€‚
+
+
+#关于登录时密ç è¾“入对è¯æ¡†
+PW_RETRYCOUNT 如果没有输入,%u 秒åŽè‡ªåŠ¨é‡æ–°è¿žæŽ¥...
+PW_LOGIN_DLG_TITLE 登录
+PW_TYPE_0 匿å身份验è¯
+PW_TYPE_1 标准密ç éªŒè¯
+PW_TYPE_2 RADIUS 或 NT 域验è¯
+PW_TYPE_3 客户端è¯ä¹¦è®¤è¯
+PW_TYPE_4 智能å¡èº«ä»½éªŒè¯
+
+PW_MSG_PROXY 代ç†æœåŠ¡å™¨ %S 用户身份验è¯å¤±è´¥ã€‚请é‡æ–°è¾“入正确的用户å和密ç ã€‚
+PW_TYPE_PROXY 代ç†æœåŠ¡å™¨è®¤è¯
+
+
+#关于 VPN 连接状æ€
+STATUS_1 åˆå§‹åŒ–中...
+STATUS_2 通过代ç†æœåŠ¡å™¨ %S 连接到 VPN Server "%S"...
+STATUS_3 在代ç†æœåŠ¡å™¨ %S 上进行用户身份验è¯...
+STATUS_4 连接到 VPN Server "%S" ...
+STATUS_5 验è¯æœåŠ¡å™¨è¯ä¹¦...
+STATUS_6 用户身份验è¯...
+STATUS_7 建立 VPN 会è¯...
+STATUS_8 连接到群集 VPN Server ...
+STATUS_9 VPN 会è¯å·²å»ºç«‹ã€‚
+
+
+#关于è¯ä¹¦å¯¹è¯
+CERT_NOT_FOUND 没有在å¯ä¿¡ä»»è¯ä¹¦åˆ—表上找到ç»è¯ä¹¦é¢å‘机构é¢å‘çš„è¯ä¹¦ã€‚
+CERT_ROOT 这是一个根è¯ä¹¦ (自签åçš„è¯ä¹¦)。
+CERT_LV_C1 区域
+CERT_LV_C2 值
+CERT_SERIAL åºåˆ—å·
+CERT_ISSUER å‘行者
+CERT_SUBJECT 主题
+CERT_NOT_BEFORE 有效期自
+CERT_NOT_AFTER 有效期至
+CERT_BITS æ•°ä½
+CERT_PUBLIC_KEY 公钥
+CERT_DIGEST_MD5 æ‘˜è¦ (MD5)
+CERT_DIGEST_SHA1 æ‘˜è¦ (SHA-1)
+CERT_NO_SERIAL 没有åºåˆ—å·
+CERT_BITS_FORMAT %u bits
+
+
+#关于è¯ä¹¦è®¤è¯å¯¹è¯æ¡†
+CC_DANGEROUS_MSG 之å‰ä¿å­˜çš„与此æœåŠ¡å™¨(%S)建立 VPN 连接的æœåŠ¡å™¨è¯ä¹¦ï¼Œä¸ŽæœåŠ¡å™¨æ供的当å‰æœåŠ¡å™¨è¯ä¹¦ä¸åŒ¹é…。\r\n以å‰çš„摘è¦å€¼(MD5): %S\r\n以å‰çš„摘è¦å€¼(SHA1): %S\r\ni当å‰çš„摘è¦å€¼(MD5): %S\r\n当å‰æ‘˜è¦å€¼(SHA-1): %S\r\n\r\nå¯èƒ½æ˜¯æœåŠ¡å™¨ç®¡ç†å‘˜åœ¨ VPN Server 端更改了è¯ä¹¦ã€‚然而,也有å¯èƒ½æ˜¯ä¸­é—´äººæ”»å‡»ï¼Œå¦‚å‘生欺骗攻击。\r\n强烈建议您å‘您å‘您想连接的 VPN Server 管ç†å‘˜è¿›è¡Œè¯¦ç»†ä¿¡æ¯å’¨è¯¢ã€‚
+CC_WARNING_MSG 您是å¦æƒ³è®©æ‚¨å½“å‰è¿žæŽ¥ä½¿ç”¨çš„è¯ä¹¦ï¼Œåœ¨ä¸‹æ¬¡è¿žæŽ¥åˆ° %s 自动信任å—?\r\n\r\n摘è¦å€¼(SHA-1): %S\r\n摘è¦å€¼(MD5): %S\r\n\r\n如对此æœåŠ¡å™¨è¯ä¹¦çš„真实性有疑问,请通过一稳妥而安全的渠é“,与æœåŠ¡å™¨æ‰€æœ‰è€…进行è”系,并列举上述摘è¦å€¼ä»¥è¿›è¡Œç¡®è®¤ã€‚\r\n\r\nå•å‡»â€œæ˜¯â€ï¼Œåˆ™ä¸‹æ¬¡è¿žæŽ¥æ—¶ï¼Œè‹¥æœåŠ¡å™¨æ供相åŒè¯ä¹¦åˆ™è‡ªåŠ¨ä¿¡ä»»ã€‚\r\nå•å‡»â€œå¦â€ï¼Œåˆ™ä¸‹æ¬¡è¿žæŽ¥åˆ°æ­¤æœåŠ¡å™¨æ—¶ï¼Œå†æ¬¡æ˜¾ç¤ºæ­¤è­¦å‘Šã€‚\r\nå•å‡»â€œå–消â€ï¼Œè¿”回安全警告窗å£ã€‚\r\n\r\n注æ„: 此设置å¯æŒ‰é€ä¸ªè´¦æˆ·æƒ…况进行修改。您å¯ä»¥ä½¿ç”¨ VPN Client 客户端管ç†å™¨å†…的账户属性进行设置。
+
+
+# 关于 Windows 版本的错误
+WINVER_TITLE 有关 Windows 版本的警告
+WINVER_ERROR_FORMAT Windows %s 的版本和补ä¸åŒ…是“%Sâ€ã€‚\r\n\r\Windows %s 最新支æŒçš„版本和补ä¸åŒ…如下:\r\n%S \r\n因为 Windows 在 %s 的版本比%sæ”¯æŒ Windows 的版本还è¦æ–°ï¼Œå¯èƒ½ä¼šå‘生æ„想ä¸åˆ°çš„麻烦或兼容问题。\r\n为了é¿å…出现问题,建议以获å–并安装 %s 最新的更新\r\nå¯ä»¥ç»§ç»­ä½¿ç”¨å½“å‰æœªæ›´æ–°çš„版本,但ä¸å»ºè®®è¿™æ ·åšã€‚\r\n\r\n如果你是管ç†å‘˜ï¼Œä½ å¯ä»¥å…费下载 %s 的最新更新补ä¸ï¼Œä»Ž http://selinks.org/ 网站。\r\n\r\n如果您ä¸æ˜¯ç®¡ç†å‘˜ï¼Œä½ åº”该将此消æ¯é€šçŸ¥ VPN Server 的管ç†å‘˜ã€‚\r\n\r\n----- MSG%04u%02u -----\r\n\r\n
+WINVER_ERROR_VPNSERVER 在目标计算机上的 VPN Server
+WINVER_ERROR_VPNBRIDGE 在目标计算机上的 VPN Bridge
+WINVER_ERROR_VPNCLIENT 在本地计算机上的 VPN Client
+WINVER_ERROR_PC_LOCAL 此本地计算机
+WINVER_ERROR_PC_REMOTE 远程æœåŠ¡å™¨
+
+
+# å¼€æºç‰ˆæœ¬çš„警告
+OSS_MSG 欢迎æ¥åˆ° SoftEther VPN æœåŠ¡å™¨å­¦æœ¯ç‰ˆ !\r\n\r\næ­¤ VPN æœåŠ¡å™¨ä½œä¸ºæ—¥æœ¬ç­‘波大学的一个学术研究由å…费软件开å‘çš„ï¼Œä¸”ç”±ï¼Œå¼€æº (GPL) SoftEther 项目 (http://www.softether.org/) 为公众利益å…è´¹å‘布的。\r\n\r\nSoftEther VPN 软件是作为筑波大学和 SoftEther å…¬å¸ä¹‹é—´çš„è”åˆç ”究åˆåŒçš„一部分而å‘布给公众的。SoftEther VPN 软件的开å‘å’Œå‘布仅为学术研究目的。因此,对 SoftEther VPN 软件ä¸æ供支æŒæœåŠ¡ï¼Œå³ä½¿å®ƒåŒ…å«é”™è¯¯æˆ–æ¼æ´žã€‚用户将对使用 SoftEther VPN 的结果承担责任。 SoftEther VPN çš„å¼€å‘者和å‘行者都将永远ä¸ä¼šä¸ºä»»ä½•åŽæžœæˆ–æŸå¤±æ‰¿æ‹…责任。\r\n\r\n在您åŒæ„上述å¯ç¤ºåŽï¼Œä½¿ç”¨ SoftEther VPN æœåŠ¡å™¨äº«å— VPN 通信。\r\n\r\n对于 SoftEther VPN 的更多细节,请å‚阅 http://www.softether.org/ 。\r\n\r\n
+
+
+
+#虚拟 HUB 管ç†é€‰é¡¹
+HUB_AO_CLICK 选择一个项目,查看这里的æ述。
+HUB_AO_UNKNOWN 该项目的æ述没有被å‘现。请å‚阅文件,或从该项目的å称推测项目的æ„æ€å’Œç›®çš„。
+HUB_AO_allow_hub_admin_change_option 这是一个特殊项目。如果你å¯ç”¨(设置为1)这个选项,那么ä¸ä½† VPN Server çš„å…¨çƒç®¡ç†å‘˜ï¼Œè€Œä¸”虚拟 HUB 的管ç†å‘˜ï¼Œéƒ½å°†è¢«ä»–自己准予修改虚拟 HUB 管ç†é€‰é¡¹ã€‚
+HUB_AO_deny_hub_admin_change_ext_option 如果你å¯ç”¨(设置为1)这个选项,虚拟 HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä¿®æ”¹åœ¨è™šæ‹Ÿ HUB 扩展选项上的任何值,那么åªæœ‰ VPN Server çš„å…¨çƒç®¡ç†å‘˜å¯ä»¥å¯¹å…¶è¿›è¡Œä¿®æ”¹ã€‚
+HUB_AO_no_delay_jitter_packet_loss 如果您将此选项设置为éžé›¶å€¼ï¼Œåœ¨è®¿é—®åˆ—表æ¡ç›®ä¸­çš„延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失的所有å‚数将被忽略,å³ä½¿è¿™äº›å‚数是在管ç†å‘˜æ·»åŠ æ–°çš„访问列表æ¡ç›®æ—¶è®¾ç½®çš„。因此,延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失的生æˆå‡½æ•°å®žé™…中将被ç¦ç”¨ã€‚由于延迟生æˆå‡½æ•°æœ‰æ—¶ä¼šè®© CPU å’Œ RAM 产生高负载é‡ï¼Œç”±å¤šä¸ªç”¨æˆ·å…±äº«çš„一个虚拟 HUB 上应该å¯ç”¨æ­¤é€‰é¡¹ã€‚
+HUB_AO_max_users 如果您将此选项设置为éžé›¶å€¼ï¼Œåœ¨è™šæ‹Ÿ HUB 上用户对象注册的最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ï¼Œé‚£ä¹ˆç”¨æˆ·å¯¹è±¡çš„æ•°é‡å¦‚果大于这个值则ä¸èƒ½è¢«æ·»åŠ ã€‚
+HUB_AO_max_multilogins_per_user 如果您将此选项设置为éžé›¶å€¼ï¼Œæ¯ä¸€ä¸ªå•ç‹¬çš„用户对象的 VPN 会è¯çš„最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ï¼Œé‚£ä¹ˆå•ç‹¬ç”¨æˆ·å¯¹è±¡çš„ VPN 会è¯çš„æ•°é‡å¦‚果大于这个值则ä¸èƒ½è¢«å»ºç«‹ã€‚
+HUB_AO_max_groups 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨è™šæ‹Ÿ HUB 上的组对象的最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ï¼Œæ›´å¤šçš„组将ä¸è¢«å…许注册。
+HUB_AO_max_accesslists 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨è™šæ‹Ÿ HUB 上的访问列表æ¡ç›®çš„最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ï¼Œæ›´å¤šæ¡ç›®å°†ä¸è¢«å…许注册。
+HUB_AO_max_sessions_client_bridge_apply åªæœ‰å½“该值被设置为éžé›¶å€¼ï¼Œmax_sessions_client å’Œ max_sessions_bridge 值将被应用。
+HUB_AO_max_sessions 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆ VPN 会è¯çš„最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ã€‚
+HUB_AO_max_sessions_client 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆ VPN Client 会è¯çš„最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ã€‚没有更多的 VPN Client 会è¯å°†è¢«å…许建立。此选项åªæœ‰å½“ max_sessions_client_bridge_apply 选项被设置为éžé›¶å€¼æ—¶æœ‰æ•ˆã€‚
+HUB_AO_max_sessions_bridge 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆ VPN Bridge 会è¯çš„最大数é‡å°†è¢«é™åˆ¶åœ¨è¿™ä¸ªå€¼ã€‚没有更多的 VPN Bridge 会è¯å°†è¢«å…许建立。此选项åªæœ‰å½“ max_sessions_client_bridge_apply 选项被设置为éžé›¶å€¼æ—¶æœ‰æ•ˆã€‚
+HUB_AO_max_bitrates_download 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨è™šæ‹Ÿ HUB 上的所有 VPN 会è¯å°†è¢«å¼ºåˆ¶æœ‰ä¸€ä¸ªå®‰å…¨ç­–略设置,å³â€œä¸‹è½½å¸¦å®½â€å€¼è¢«è®¾ç½®ä¸ºè¿™ä¸ªå€¼ã€‚这将é™åˆ¶æ¯ä¸ª VPN 会è¯çš„下载通信速度。例如,如果该值设置为 1000000,然åŽåœ¨è™šæ‹Ÿ HUB 上的æ¯ä¸ª VPN 会è¯çš„下载带宽将被é™åˆ¶ä¸º1Mbps。
+HUB_AO_max_bitrates_upload 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨è™šæ‹Ÿ HUB 上的所有 VPN 会è¯å°†è¢«å¼ºåˆ¶æœ‰ä¸€ä¸ªå®‰å…¨ç­–略设置,å³â€œä¸‹è½½å¸¦å®½â€å€¼è¢«è®¾ç½®ä¸ºè¿™ä¸ªå€¼ã€‚这将é™åˆ¶æ¯ä¸ª VPN 会è¯çš„上传通信速度。例如,如果该值设置为 1000000,然åŽåœ¨è™šæ‹Ÿ HUB 上的æ¯ä¸ª VPN 会è¯çš„上传带宽将被é™åˆ¶ä¸º1Mbps。
+HUB_AO_deny_empty_password 如果您将此选项设置为éžé›¶å€¼ï¼Œæ²¡æœ‰ç”¨æˆ·å¯¹è±¡èƒ½å¤Ÿæœ‰ä¸€ä¸ªç©ºå¯†ç ã€‚一个空密ç çš„用户将被ç¦æ­¢è¿žæŽ¥ VPN 会è¯ã€‚ (例外:从本地的 VPN 连接将被å…许,å³ä½¿å¯†ç ä¸ºç©º)。
+HUB_AO_deny_bridge 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆä»»ä½•åœ¨ç½‘桥模å¼ä¸‹çš„ VPN 会è¯å°†ä¸ä¼šè¢«å‡†è®¸å»ºç«‹ï¼Œä¸ç®¡ç”¨æˆ·çŽ°æœ‰çš„安全策略的设置。为了桥接的目的,没有人能够连接到虚拟 HUB 。
+HUB_AO_deny_routing 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆä»»ä½•åœ¨è·¯ç”±æ¨¡å¼ä¸‹çš„ VPN 会è¯å°†ä¸ä¼šè¢«å‡†è®¸å»ºç«‹ï¼Œä¸ç®¡ç”¨æˆ·çŽ°æœ‰çš„安全策略的设置。为了路由的目的,没有人能够连接到虚拟 HUB 。
+HUB_AO_deny_qos 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸€ä¸ª VPN 会è¯å°†è¢«å¼ºåˆ¶æ‰§è¡Œç¦ç”¨ QoS 功能,ä¸ç®¡ç”¨æˆ·çŽ°æœ‰çš„安全策略的设置。
+HUB_AO_deny_change_user_password 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨è™šæ‹Ÿ HUB 上的任何用户将被ç¦æ­¢é€šè¿‡ VPN Client 的密ç æ›´æ”¹åŠŸèƒ½ä¿®æ”¹å…¶å¯†ç ã€‚
+HUB_AO_no_change_users 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ·»åŠ ã€ç¼–辑或删除用户。
+HUB_AO_no_change_groups 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ·»åŠ ã€ç¼–辑或删除组。
+HUB_AO_no_securenat 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢å¯ç”¨æˆ–ç¦ç”¨ SecureNAT 功能。
+HUB_AO_no_securenat_enablenat 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢å¯ç”¨æˆ–ç¦ç”¨åœ¨ SecureNAT 功能中的虚拟 NAT 功能。
+HUB_AO_no_securenat_enabledhcp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢å¯ç”¨æˆ–ç¦ç”¨åœ¨ SecureNAT 功能中的虚拟 USB 功能。
+HUB_AO_no_cascade 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ·»åŠ ã€ç¼–辑ã€åˆ é™¤æˆ–更改级è”连接的在线状æ€ã€‚
+HUB_AO_no_online 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹ç¦»çº¿çš„虚拟 HUB 为在线状æ€ã€‚
+HUB_AO_no_offline 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹åœ¨çº¿çš„虚拟 HUB 为离线状æ€ã€‚
+HUB_AO_no_change_log_config 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹æ—¥å¿—功能的设置。
+HUB_AO_no_disconnect_session 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ–­å¼€ä¸€ä¸ªç‰¹å®šçš„ VPN 会è¯ã€‚
+HUB_AO_no_delete_iptable 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä»Ž IP 地å€è¡¨æ•°æ®åº“中删除一个特定的 IP 地å€ã€‚
+HUB_AO_no_delete_mactable 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä»Ž MAC 地å€è¡¨æ•°æ®åº“中删除一个特定的 MAC 地å€ã€‚
+HUB_AO_no_enum_session 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢åˆ—举在虚拟 HUB 上的会è¯ã€‚
+HUB_AO_no_query_session 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æŒ‡å®šä¼šè¯ï¼Œå¹¶èŽ·å¾—会è¯çš„ä¿¡æ¯ã€‚
+HUB_AO_no_change_admin_password 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹è™šæ‹Ÿ HUB 的管ç†å‘˜å¯†ç ã€‚
+HUB_AO_no_change_log_switch_type 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹åœ¨è™šæ‹Ÿ HUB 日志功能设置中的日志转æ¢è®¾ç½®ã€‚
+HUB_AO_no_change_access_list 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä¿®æ”¹è™šæ‹Ÿ HUB 的访问列表。
+HUB_AO_no_change_access_control_list 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä¿®æ”¹è™šæ‹Ÿ HUB çš„æº IP 地å€é™åˆ¶åˆ—表。
+HUB_AO_no_change_cert_list 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä¿®æ”¹è™šæ‹Ÿ HUB çš„å¯ä¿¡è¯ä¹¦æŽˆæƒåˆ—表。
+HUB_AO_no_change_crl_list 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢ä¿®æ”¹è™šæ‹Ÿ HUB çš„è¯ä¹¦å–消列表。
+HUB_AO_no_read_log_file 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢è¿œç¨‹åˆ—举或下载虚拟 HUB 的日志文件。
+HUB_AO_no_change_msg 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æ›´æ”¹å½“一个 VPN Client 连接到虚拟 HUB 时应该被显示的消æ¯ã€‚
+HUB_AO_no_access_list_include_file 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 的管ç†å‘˜å°†è¢«ç¦æ­¢æŒ‡å®šâ€œåŒ…括:â€æˆ–“排除:â€æŒ‡ä»¤ä½œä¸ºåœ¨è™šæ‹Ÿ HUB 上的访问列表æ¡ç›®çš„æºæˆ–目标用户字段。
+
+
+# 虚拟 HUB 扩展选项
+HUB_AO_NoAddressPollingIPv4 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ä¸æ‰§è¡Œåœ¨ HUB 上的 IPv4 地å€è¡¨å’Œ MAC 地å€è¡¨çš„ç»´æŠ¤ï¼Œé€šè¿‡æ¯ 5 秒å‘é€ ARP æ•°æ®åŒ…,以检查 IPv4 设备ä¿æŒæ´»è·ƒçŠ¶æ€ã€‚其结果,一个特定的期间(从 1 至 10 分钟)过去以åŽï¼Œåœ¨æ²¡æœ‰é€šä¿¡æ´»åŠ¨é€šè¿‡è™šæ‹Ÿ HUB 的情况下,å³ä½¿ä»ç„¶æ´»è·ƒç€ï¼Œåœ¨ IPv4 地å€è¡¨å’Œ MAC 地å€è¡¨ä¸­çš„ IPv4 设备å¯èƒ½ä¼šè¢«åˆ é™¤ã€‚此选项å¯ä»¥æ¶ˆé™¤å¤§é‡çš„广播数æ®åŒ…,但一些 IPv4 相关的安全策略将无法有效工作。
+HUB_AO_NoAddressPollingIPv6 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ä¸æ‰§è¡Œåœ¨ HUB 上的 IPv6 地å€è¡¨å’Œ MAC 地å€è¡¨çš„ç»´æŠ¤ï¼Œé€šè¿‡æ¯ 5 秒å‘é€ ICMPv6 æ•°æ®åŒ…,以检查 IPv6 设备ä¿æŒæ´»è·ƒçŠ¶æ€ã€‚其结果,一个特定的期间(从 1 至 10 分钟)过去以åŽï¼Œåœ¨æ²¡æœ‰é€šä¿¡æ´»åŠ¨é€šè¿‡è™šæ‹Ÿ HUB 的情况下,å³ä½¿ä»ç„¶æ´»è·ƒç€ï¼Œåœ¨ IPv6 地å€è¡¨å’Œ MAC 地å€è¡¨ä¸­çš„ IPv6 设备å¯èƒ½ä¼šè¢«åˆ é™¤ã€‚此选项å¯ä»¥æ¶ˆé™¤å¤§é‡çš„广播数æ®åŒ…,但一些 IPv6 相关的安全策略将无法有效工作。
+HUB_AO_NoIpTable 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ä¸ä¼šåˆ›å»ºå’Œç»´æŠ¤å†…部 IP 地å€è¡¨ã€‚此选项å¯ä»¥æ¶ˆé™¤ CPU å’Œ RAM 的使用é‡ï¼Œä½†ä¸€äº› IP 相关的安全策略将无法有效工作。
+HUB_AO_NoMacAddressLog 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè¿™è¡¨æ˜Žä»»ä½•ä¸€ä¸ªæ–°çš„ MAC 地å€æ³¨å†Œåˆ°è™šæ‹Ÿ HUB 上 MAC 地å€è¡¨çš„日志,将ä¸ä¼šè¢«è®°å½•åˆ°å®‰å…¨æ—¥å¿—中。
+HUB_AO_ManageOnlyPrivateIP 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB çš„ IPv4 地å€è¡¨å°†åªåŒ…å«ç§æœ‰ IPv4 地å€ã€‚由于这个原因,ç§æœ‰ IPv4 地å€æ˜¯ï¼š10.0.0.0 /8,172.16.0.0/12,192.168.0.0/16 å’Œ 169.254.0.0/16。任何其他的 IPv4 地å€å°†ä¸ä¼šè¢«æ·»åŠ åˆ°è¡¨å†…。
+HUB_AO_ManageOnlyLocalUnicastIPv6 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB çš„ IPv6 地å€è¡¨å°†åªåŒ…å«æœ¬åœ°å•æ’­ IPv6 地å€ã€‚由于这个原因,ç§æœ‰ IPv6 地å€æ˜¯ï¼šfe80:: / 10。任何其他的 IPv6 地å€å°†ä¸ä¼šè¢«æ·»åŠ åˆ°è¡¨å†…。
+HUB_AO_DisableIPParsing 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ç¦ç”¨åœ¨æ‰€æœ‰ä»¥å¤ªç½‘æ•°æ®åŒ…里的 IP 包头的内部解æžå‡½æ•°ã€‚此选项å¯ä»¥æ¶ˆé™¤ CPU å’Œ RAM 的使用é‡ï¼Œä½†æ˜¯è™šæ‹Ÿ HUB å°†ä¸ä¼šæ‰§è¡Œå†…部 IP 地å€è¡¨çš„建设和维护,一些 IP 相关的安全策略将无法有效工作。
+HUB_AO_YieldAfterStorePacket 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨æ•°æ®åŒ…的存储-转å‘进程åŽï¼Œè™šæ‹Ÿ HUB 设置 CPU 为空闲状æ€ã€‚è¿™å¯èƒ½å¯¼è‡´äº†è‰¯å¥½çš„效果,使数æ®åŒ…的延迟更短,但是线程关è”转æ¢çš„计数将增加,性能å¯èƒ½ä¸‹é™ã€‚
+HUB_AO_FilterPPPoE 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 丢弃所有的 PPPoE(PPP over Ethernet)æ•°æ®åŒ…。当建立两个或多个局域网之间的网桥时,方便分开æ¯ä¸ªç«™ç‚¹çš„ PPPoE 网段。
+HUB_AO_FilterOSPF 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 丢弃所有 OSPF (Open Shortest Path First) æ•°æ®åŒ…。
+HUB_AO_FilterIPv4 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 丢弃所有的 IPv4 å’Œ ARP æ•°æ®åŒ…。
+HUB_AO_FilterIPv6 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 丢弃所有的 IPv6 æ•°æ®åŒ…。
+HUB_AO_FilterNonIP 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB ä¸¢å¼ƒæ‰€æœ‰éž IP æ•°æ®åŒ…(éž IPv4ã€ARP 或 IPv6 æ•°æ®åŒ…)。顺便说一å¥ï¼Œä»»ä½•é€šè¿‡è™šæ‹Ÿ HUB 的带标签的 VLAN 将被视为éžIPæ•°æ®åŒ…。
+HUB_AO_FilterBPDU 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 丢弃所有 BPDU (Bridge Protocol Data Unit) æ•°æ®åŒ…。
+HUB_AO_NoIPv6DefaultRouterInRAWhenIPv6 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 上的所有的 VPN 会è¯å°†ä¼šå¯ç”¨â€œæ— åœ¨IPv6 RA(物ç†IPv6)上的默认路由器â€å®‰å…¨ç­–略。当 VPN Client / VPN Bridge å’Œ VPN Server 之间的物ç†é€šä¿¡å议是IPv6时,任何在路由生命周期为éžé›¶å€¼çš„IPv6 RA(路由器广告)æ•°æ®åŒ…将设置为零值。这有效的é¿å…了通过 VPN Client å°è¯•ä½¿ç”¨è¿œç«¯çš„IPv6路由器作为其本地IPv6路由器而导致的IPv6路由混乱的å¯æ€•è¡Œä¸ºã€‚
+HUB_AO_NoLookBPDUBridgeId 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 将忽略在一个 BPDU (Bridge Protocol Data Unit) æ•°æ®åŒ…é‡Œçš„æº MAC 地å€å­—段。这个值是éžå¸¸å…ˆè¿›çš„。请ä¸è¦ä¿®æ”¹å®ƒï¼Œé™¤éžä½ æ˜¯è¶…特殊的计算机网络专家。
+HUB_AO_NoManageVlanId 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ä¸ä¼šä½¿ç”¨åœ¨ MAC 地å€è¡¨ä¸­çš„ VLAN ID。任何有标签的VLANæ•°æ®åŒ…中的 VLAN ID 将被忽略。
+HUB_AO_VlanTypeId 以å进制指定的 VLAN 标签的以太网类型 ID (TPID)。默认值是 33024 (å六进制 0x8100)。此值是éžå¸¸å…ˆè¿›çš„。请ä¸è¦ä¿®æ”¹å®ƒï¼Œé™¤éžä½ æ˜¯è¶…特殊的计算机网络专家。
+HUB_AO_FixForDLinkBPDU 如果您将此选项设置为éžé›¶å€¼ï¼ŒFixForDLinkBPDU 选项将å¯åŠ¨ã€‚此值是éžå¸¸å…ˆè¿›çš„。请ä¸è¦ä¿®æ”¹å®ƒï¼Œé™¤éžä½ æ˜¯è¶…特殊的计算机网络专家。
+HUB_AO_NoIPv4PacketLog 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆç»è¿‡è™šæ‹Ÿ HUB çš„ IPv4 æ•°æ®åŒ…å°†ä¸è¢«è®°å½•ã€‚
+HUB_AO_NoIPv6PacketLog 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆç»è¿‡è™šæ‹Ÿ HUB çš„ IPv6 æ•°æ®åŒ…å°†ä¸è¢«è®°å½•ã€‚
+HUB_AO_NoSpinLockForPacketDelay 如果您将此选项设置为éžé›¶å€¼ï¼Œå½“æ•°æ®åŒ…延迟生æˆå‡½æ•°åº”用于数æ®åŒ…时,那么 VPN Server å°†ä¸ä½¿ç”¨è‡ªæ—‹é”机制æ¥æ¨¡ä»¿æ•°æ®åŒ…的延迟。相å,æ“作系统的计时器中断将被采纳。这会é™ä½Ž CPU 的时间,但产生延迟的解æžåº¦å°†ä¼šæ¶åŒ–。
+HUB_AO_BroadcastStormDetectionThreshold 指定临界值æ¯ç§’检测广播风暴。当从一个特定 VPN 会è¯çš„广播数æ®åŒ…æ•°é‡è¶…过了这个临界值时,数æ®åŒ…将被视为广播风暴,会被过滤。默认值(零值)为 32。
+HUB_AO_ClientMinimumRequiredBuild 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 将拒ç»ä»Žç‰ˆæœ¬å·ä½ŽäºŽè¿™ä¸ªå€¼çš„ã€VPN Client 的任何访问。
+HUB_AO_RequiredClientId 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 将拒ç»ä»Žæ²¡æœ‰åµŒå…¥â€œå®¢æˆ·ç«¯IDâ€å€¼åœ¨è½¯ä»¶ä¸­çš„ã€VPN Client 的任何访问。
+HUB_AO_AdjustTcpMssValue 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 将调整所有 TCP/IP æ•°æ®åŒ…的包头的 MSS(最大报文段长度)值,且ä¸è¶…过此值。
+HUB_AO_DisableAdjustTcpMss 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB 上的 MSS (最大报文段长度)选项将被ç¦ç”¨ã€‚å³ä½¿ AdjustTcpMssValue 选项是指定的,或一个 VPN 会è¯æ˜¯ç”± IPsec / L2TP / EtherIP / L2TPv3 æœåŠ¡å™¨åŠŸèƒ½åˆ›å»ºçš„,MSS 的调节将被ç¦ç”¨ã€‚
+HUB_AO_NoDhcpPacketLogOutsideHub 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB å°†ä¸è®°å½•éžå…³è”çš„ DHCP æ•°æ®åŒ…çš„æ•°æ®åŒ…日志。“éžå…³è” DHCP æ•°æ®åŒ…â€æ˜¯åœ¨è™šæ‹Ÿ HUB 上ä¸å—任何 VPN 会è¯çº¦æŸçš„ DHCP æ•°æ®åŒ…。
+HUB_AO_DisableHttpParsing 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB ä¸ä¼šåœ¨æ‰€æœ‰ HTTP æ•°æ®åŒ…è¿›è¡Œè§£æž HTTP 包头。这会é™ä½Ž CPU å’Œ RAM 的使用,但是 HTTP 访问日志将ä¸ä¼šè¢«è®°å½•ã€‚
+HUB_AO_DisableUdpAcceleration 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ‰€æœ‰ UDP 加速功能在虚拟 HUB 的所有 VPN 会è¯å°†è¢«ç¦ç”¨ã€‚
+HUB_AO_DisableUdpFilterForLocalBridgeNic 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆè™šæ‹Ÿ HUB ç¦ç”¨æ•…障预防过滤功能,æ¥è¿‡æ»¤å¯èƒ½ä¼šå¯¼è‡´ç½‘络ä¸ç¨³å®šçš„ DHCP æ•°æ®åŒ…。默认情况下,本地桥接å£æœ‰æ—¶ä¼šå°è¯•ä»Žè¿œç«¯ DHCP æœåŠ¡å™¨èŽ·å–一个 IP 地å€ï¼Œä½†æ˜¯è¿™æ ·çš„行为在路由表中会无é™å¾ªçŽ¯ã€‚过滤功能å¯é¿å…这样的问题。此选项å¯ä»¥ç¦ç”¨è¿‡æ»¤åŠŸèƒ½ã€‚
+HUB_AO_ApplyIPv4AccessListOnArpPacket 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆ IPv4 访问列表æ¡ç›®å°†ä¸ä»…被应用在 IPv4 æ•°æ®åŒ…,而且还在 ARP æ•°æ®åŒ…。这样方便过滤ä¸å¿…è¦çš„ã€å¯èƒ½ä¼šå¸¦æ¥éº»çƒ¦çš„ ARP æ•°æ®åŒ…。
+HUB_AO_RemoveDefGwOnDhcpForLocalhost 如果您将此选项设置为éžé›¶å€¼ï¼Œå½“本地主机上的一个 VPN Client 连接到虚拟 HUB ,并试图从虚拟 HUB 网段的 DHCP æœåŠ¡å™¨èŽ·å–一个 IP 地å€ï¼Œç›¸åº”çš„ DHCP å“应数æ®åŒ…将被丢弃。它å¯ä»¥é˜²æ­¢æ„想ä¸åˆ°çš„æ•°æ®åŒ…路由的无é™å¾ªçŽ¯ã€‚
+HUB_AO_SecureNAT_MaxTcpSessionsPerIp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸ª IP 状æ€çš„ TCP 连接数(ä¸æ˜¯ SYN_SENT)将被é™åˆ¶ä¸ºæ­¤å€¼ã€‚
+HUB_AO_SecureNAT_MaxTcpSynSentPerIp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸ª IP 状æ€çš„ TCP 连接数(是 SYN_SENT)将被é™åˆ¶ä¸ºæ­¤å€¼ã€‚
+HUB_AO_SecureNAT_MaxUdpSessionsPerIp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸ª IP 状æ€çš„ UDP 会è¯æ•°å°†è¢«é™åˆ¶ä¸ºæ­¤å€¼ã€‚
+HUB_AO_SecureNAT_MaxDnsSessionsPerIp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸ªéž SYN_SENT çŠ¶æ€ IP çš„ DNS 会è¯æ•°å°†è¢«é™åˆ¶ä¸ºæ­¤å€¼ã€‚
+HUB_AO_SecureNAT_MaxIcmpSessionsPerIp 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆæ¯ä¸ªéž SYN_SENT çŠ¶æ€ IP çš„ ICMP 会è¯æ•°å°†è¢«é™åˆ¶ä¸ºæ­¤å€¼ã€‚
+HUB_AO_AccessListIncludeFileCacheLifetime 指定以秒为周期ä¿å­˜å¤–部用户列表文件的缓存,此文件是以“include:â€æˆ–“exclude:â€æ ¼å¼ä½œä¸ºå®ƒçš„用户åçš„ã€è®¿é—®åˆ—表æ¡ç›®ã€‚
+HUB_AO_DisableKernelModeSecureNAT 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨ SecureNAT åŠŸèƒ½ä¸Šçš„å†…æ ¸æ¨¡å¼ NAT 功能将被ç¦ç”¨ã€‚å†…æ ¸æ¨¡å¼ NAT 是加速SecureNAT 虚拟 NAT åŠŸèƒ½è¡¨çŽ°çš„ä¸€ä¸ªåŠŸèƒ½ã€‚å†…æ ¸æ¨¡å¼ NAT åªæœ‰å½“ VPN æœåŠ¡å™¨è¿›ç¨‹ä»¥ç³»ç»Ÿæƒé™ï¼ˆå³æ ¹ï¼Œç³»ç»Ÿæˆ–管ç†å‘˜æƒ…况下)正在è¿è¡Œæ—¶ï¼Œå¯ä»¥å·¥ä½œã€‚å¦‚æžœå†…æ ¸æ¨¡å¼ NAT 引起一些错误的æ“作,使用此选项æ¥ç¦ç”¨å®ƒã€‚
+HUB_AO_DisableUserModeSecureNAT 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨ SecureNAT åŠŸèƒ½ä¸Šçš„ç”¨æˆ·æ¨¡å¼ NAT 功能将被ç¦ç”¨ã€‚ç”¨æˆ·æ¨¡å¼ NAT 是一个使 NAT å¯ä»¥ä½œä¸ºæ™®é€šç”¨æˆ·æƒé™è¿è¡Œçš„功能。
+HUB_AO_DisableCheckMacOnLocalBridge 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆ MAC 地å€é‡å¤æ£€æŸ¥åœ¨æœ¬åœ°æ¡¥åŠŸèƒ½ä¸Šå°†è¢«ç¦ç”¨ã€‚一些网络适é…器有å射传出的数æ®åŒ…å‘虚拟 HUB 的问题。虚拟 HUB 自动检测这样的é‡å¤ï¼Œå¹¶ä¸¢å¼ƒå®ƒä»¬ã€‚å¯ç”¨æ­¤æ ‡å¿—æ¥ç¦ç”¨æ£€æµ‹ï¼Œå¹¶ä¸¢å¼ƒã€‚
+HUB_AO_DisableCorrectIpOffloadChecksum 如果您将此选项设置为éžé›¶å€¼ï¼Œé‚£ä¹ˆåœ¨æœ¬åœ°æ¡¥åŠŸèƒ½ä¸Šæ£€æŸ¥å’Œçº æ­£ IP 校验和值。有些有 IPã€TCP 或 UDP 包头的校验和å¸è½½å¼•æ“Žçš„网络适é…器,以ä¸å®Œæ•´çš„校验和值传输数æ®åŒ…。这样的数æ®åŒ…ä¸èƒ½è¢«æŽ¥æ”¶ç«¯æ­£ç¡®å¯¹å¾…。所以本地桥检测到这样的数æ®åŒ…,并纠正了它的校验和字段。å¯ç”¨æ­¤æ ‡å¿—æ¥ç¦ç”¨è¿™ç§çº æ­£ã€‚
+HUB_AO_BroadcastLimiterStrictMode If you set this option to non-zero value, then the broadcast-storm detection algorithm will compare either source or destination IP address of each packet. If any of the two fields matches, the packet will be recorded on the short-term history of broadcast-storm detection state machine.
+
+#关于失败连接对è¯æ¡†
+ERRDLG_ERRMSG 错误(é”™è¯¯ä»£ç  %u) :\r\n\r\n%s\r\n
+ERRDLG_RETRYCOUNT %u 秒åŽå°†è‡ªåŠ¨è¿›è¡Œé‡æ–°è¿žæŽ¥...
+ERRDLG_INFORMATION 点击“é‡è¯•â€ï¼Œé‡æ–°è¿›è¡Œè¿žæŽ¥ã€‚
+ERRDLG_RETRY_INFO_1 你想é‡è¯•å—? (%u é‡è¯• / %u 总é‡è¯•)
+ERRDLG_RETRY_INFO_2 你想é‡è¯•å—? (%u é‡è¯• / 总无é™é‡è¯•)
+ERRDLG_DISCONNECTED_MSG VPN Server "%S" 连接已被切断
+ERRDLG_DEVICE_ERROR 与 VPN Server 的连接被中断,因为虚拟网络适é…器 (设备å称: %S) å·²åœæ­¢ã€‚\r\n\r\né”™è¯¯ä»£ç  %u: %s
+
+
+# 关于åè®®
+PROTO_DIRECT_TCP 直接的 TCP/IP 连接
+PROTO_HTTP_PROXY 通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥
+PROTO_SOCKS_PROXY 通过 SOCKS 代ç†æœåŠ¡å™¨è¿žæŽ¥
+PROTO_SSH 通过 SSH æœåŠ¡å™¨è¿žæŽ¥
+PROTO_UNKNOWN 未知åè®®
+
+
+
+# 关于caps(控制字符)
+CAPS_YES 是
+CAPS_NO å¦
+# (标题)
+CT_i_max_packet_size 最大的以太网数æ®åŒ…大å°
+CT_i_max_hubs 最大虚拟 HUB 数
+CT_i_max_user_creation 整个 VPN Server 的最大用户数
+CT_i_max_sessions 最大总会è¯æ•°
+CT_i_max_clients 最大客户端会è¯æ•°
+CT_i_max_bridges 最大网桥会è¯æ•°
+CT_i_max_users_per_hub æ¯è™šæ‹Ÿ HUB 最大用户容é‡
+CT_i_max_groups_per_hub æ¯è™šæ‹Ÿ HUB 最大群容é‡
+CT_i_max_access_lists æ¯è™šæ‹Ÿ HUB 最大访问列表容é‡
+CT_i_max_mac_tables æ¯è™šæ‹Ÿ HUB 最大 MAC 地å€å®¹é‡
+CT_i_max_ip_tables æ¯è™šæ‹Ÿ HUB 最大 IP 地å€å®¹é‡
+CT_i_max_secnat_tables æ¯è™šæ‹Ÿ HUB 最大 SecureNAT 容é‡
+CT_i_max_l3_sw 最大虚拟 3 层交æ¢æœºæ•°
+CT_i_max_l3_if æ¯è™šæ‹Ÿ 3 层交æ¢æœºæœ€å¤§è™šæ‹ŸæŽ¥å£å®¹é‡
+CT_i_max_l3_table æ¯è™šæ‹Ÿ 3 层交æ¢æœºæœ€å¤§è·¯ç”±è¡¨å®¹é‡
+CT_b_bridge 作为 VPN Bridge 软件工作
+CT_b_standalone 独立模å¼
+CT_b_cluster_controller 群集控制器模å¼
+CT_b_cluster_member 群集æˆå‘˜æ¨¡å¼
+CT_b_vpn_client_connect æŽ¥å— VPN Client / Bridge 的连接
+CT_b_local_bridge 支æŒæœ¬åœ°ç½‘æ¡¥
+CT_b_must_install_pcap 未安装数æ®åŒ…æ•èŽ·é©±åŠ¨
+CT_b_tap_supported æ”¯æŒ tun/tap 设备 (仅在 Linux)
+CT_b_support_config_hub 支æŒæ›´æ”¹è™šæ‹Ÿ HUB 设置
+CT_b_support_securenat æ”¯æŒ SecureNAT
+CT_b_virtual_nat_disabled 虚拟 NAT 无效 (仅 DHCP 有效)
+CT_b_support_cascade 支æŒçº§è”连接
+CT_b_support_cascade_cert 支æŒçº§è”连接æœåŠ¡å™¨è®¤è¯
+CT_b_support_config_log 支æŒæ›´æ”¹ä¿å­˜æ—¥å¿—设置
+CT_b_support_autodelete 支æŒè‡ªåŠ¨åˆ é™¤æ—¥å¿—文件
+CT_b_support_radius 支æŒå¤–部认è¯æœåŠ¡å™¨
+CT_b_support_config_rw æ”¯æŒ Config 文件的远程读写
+CT_b_support_hub_admin_option 支æŒè™šæ‹Ÿ HUB 管ç†é€‰é¡¹
+CT_b_support_cascade_client_cert 支æŒçº§è”连接客户è¯ä¹¦
+CT_b_support_hide_hub 支æŒè™šæ‹Ÿ HUB 枚举设定
+CT_b_support_cluster_admin 支æŒå¯¹æ‰€æœ‰ç¾¤é›†æ¨¡å¼çš„综åˆç®¡ç†
+CT_b_support_cluster 支æŒéƒ¨åˆ†ç¾¤é›†æ¨¡å¼çš„è¿è¡Œ
+CT_b_support_cluster_controller 作为群集控制器æ“作
+CT_b_support_layer3 支æŒè™šæ‹Ÿ 3 层交æ¢æœº
+CT_b_support_crl 支æŒè™šæ‹Ÿ HUB 特定è¯ä¹¦åŠé”€åˆ—表
+CT_b_support_ac 支æŒç‰¹æœ‰çš„虚拟 HUB æº IP 地å€é™åˆ¶åˆ—表
+CT_b_support_read_log 支æŒæ—¥å¿—文件的下载
+CT_b_support_rename_cascade 支æŒçº§è”连接åçš„å˜æ›´
+CT_b_support_license 支æŒè®¸å¯è¯ç®¡ç†
+CT_b_support_limit_multilogin 支æŒå¯¹åŒä¸€ç”¨æˆ·å¤šä¸ªç™»å½•çš„é™åˆ¶
+CT_b_support_qos æ”¯æŒ VoIP / QoS 功能
+CT_b_support_syslog 支æŒç³»ç»Ÿæ—¥å¿—å‘é€åŠŸèƒ½
+CT_b_cluster_hub_type_fixed 固定群集虚拟 HUB ç§ç±»
+CT_b_beta_version 测试版 (预å‘布版本)
+CT_b_support_check_mac 支æŒåœ¨è®¿é—®åˆ—表中指定 MAC 地å€
+CT_b_support_check_tcp_state 支æŒæ£€æµ‹ TCP 连接的状æ€è¿‡æ»¤
+CT_b_support_network_connection_name 支æŒèŽ·å–网络å‹å¥½å称
+CT_b_support_radius_retry_interval_and_several_servers 在 RADIUS 身份验è¯é‡Œæ”¯æŒé‡è¯•é—´éš”和多个æœåŠ¡å™¨
+CT_b_support_vlan 在 MAC 地å€è¡¨é‡Œæ”¯æŒå¸¦æ ‡ç­¾çš„ VLAN ID
+CT_b_support_hub_ext_options 支æŒè™šæ‹Ÿ HUB 扩展选项
+CT_b_support_policy_ver_3 支æŒå®‰å…¨ç­–ç•¥ 3.0 版本
+CT_b_support_ipv6_acl æ”¯æŒ IPv6 访问列表
+CT_b_support_ex_acl 支æŒè®¿é—®åˆ—表延时ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失
+CT_b_support_acl_group 支æŒè®¿é—®åˆ—表通过组å调节
+CT_b_support_ipv6_ac æ”¯æŒ IPv6 IP 访问控制列表
+CT_b_support_eth_vlan 支æŒå¸¦æ ‡è®°çš„ VLAN æ•°æ®åŒ…é€æ˜Žæ”¯æŒå·¥å…·
+CT_b_support_msg 支æŒä»Šå¤©æ¶ˆæ¯åŠŸèƒ½
+CT_b_vpn3 æ”¯æŒ 3.0 的功能
+CT_b_vpn4 æ”¯æŒ 4.0 的功能
+CT_b_support_ipsec æ”¯æŒ IPsec / L2TP / EtherIP / L2TPv3 æœåŠ¡å™¨åŠŸèƒ½
+CT_b_support_sstp æ”¯æŒ MS-SSTP VPN Server 功能
+CT_b_support_udp_acceleration æ”¯æŒ UDP 加速功能
+CT_b_support_openvpn æ”¯æŒ OpenVPN Server 功能
+CT_b_support_ddns 支æŒåŠ¨æ€ DNS 客户端功能
+CT_b_support_ddns_proxy æ”¯æŒ DDNS 通过代ç†æœåŠ¡å™¨
+CT_b_support_special_listener æ”¯æŒ VPN over ICMP å’Œ VPN over DNS
+CT_b_support_redirect_url_acl 支æŒè®¿é—®åˆ—表 HTTP URL 改é“
+CT_b_is_in_vm 虚拟机上è¿è¡Œ
+CT_b_support_azure æ”¯æŒ VPN Azure
+CT_b_support_intel_aes æ”¯æŒ Intel CPU AES 加密加速功能 (AES-NI)
+CT_b_using_selow_driver æ”¯æŒ SoftEther Lightweight Kernel-mode Ethernet Driver
+CT_b_support_vgs æ”¯æŒ VPN Gate æœåŠ¡çš„æœåŠ¡å™¨åŠŸèƒ½
+CT_b_support_vgs_in_client VPN Gate æœåŠ¡çš„æœåŠ¡å™¨åŠŸèƒ½ (VPN 客户端集æˆ)
+CT_b_is_softether SoftEther VPN çš„å…费或开æºç‰ˆ
+
+
+#相关策略
+POL_TITLE_STR ç­–ç•¥å
+POL_VALUE_STR 现在值
+POL_TYPE_BOOL å¼€ / å…³
+POL_TYPE_INT æ•´æ•°
+POL_BOOL_ENABLE 有效
+POL_BOOL_DISABLE ï¼
+POL_BOOL_DISABLE_EX ï¼
+POL_INT_ZERO ï¼
+POL_INT_COUNT %u 个
+POL_INT_SEC %u 秒
+POL_INT_BPS %u bps
+POL_INT_VLAN %u
+
+# Ver 2.0
+POL_0 å…许访问
+POL_EX_0 用户定义的这项策略的æƒé™ï¼Œä½¿ VPN 连接到 VPN Server。
+POL_1 DHCP æ•°æ®åŒ…过滤器 (IPv4)
+POL_EX_1 此策略定义的所有会è¯ä¸­çš„ IPv4 çš„ DHCP æ•°æ®åŒ…将被过滤。
+POL_2 ç¦æ­¢ DHCP æœåŠ¡å™¨è¿è¡Œ (IPv4)
+POL_EX_2 连接到有此策略设置的会è¯çš„计算机,将无法æˆä¸º DHCP æœåŠ¡å™¨ï¼Œä¹Ÿæ— æ³•å¯¹ DHCP ç”¨æˆ·åˆ†é… IPv4 / DNS ä¿¡æ¯ã€‚
+POL_3 强制 DHCP åˆ†é… IP åœ°å€ (IPv4)
+POL_EX_3 有此策略设置的会è¯çš„计算机,åªèƒ½ä½¿ç”¨è™šæ‹Ÿç½‘络侧的 DHCP æœåŠ¡å™¨æ供的 IPv4 地å€ã€‚
+POL_4 æ‹’ç»ç½‘æ¡¥è¿è¡Œ
+POL_EX_4 网桥模å¼çš„连接被有此策略设置的用户会è¯æ‹’ç»ã€‚å³ä½¿å½“以太网网桥在客户端被é…置的情况下,通信将是ä¸å¯èƒ½çš„。
+POL_5 æ‹’ç»è·¯ç”±æ“作 (IPv4)
+POL_EX_5 有此策略设置的会è¯å°†æ‹’ç» IPv4 路由。å³ä¾¿ IP 路由器è¿è¡Œåœ¨å®¢æˆ·ç«¯ï¼Œé€šè®¯ä»å°†æ— æ³•å»ºç«‹ã€‚
+POL_6 æ‹’ç» MAC 地å€å¤åˆ¶
+POL_EX_6 有此策略设置的会è¯æ— æ³•ä½¿ç”¨æ­£åœ¨è¢«ä¸åŒä¼šè¯çš„计算机å ç”¨çš„é‡å¤ MAC 地å€ã€‚
+POL_7 æ‹’ç» IP 地å€å¤åˆ¶ (IPv4)
+POL_EX_7 有此策略设置的会è¯æ— æ³•ä½¿ç”¨æ­£åœ¨è¢«ä¸åŒä¼šè¯çš„计算机å ç”¨çš„é‡å¤ IPv4 地å€ã€‚
+POL_8 æ‹’ç»éžçš„ ARP / éž DHCP / éž ICMPv6 广播
+POL_EX_8 有此策略设置的会è¯ä¸å…许在虚拟网络上有 ARP å议,DHCP åè®®ã€ICMPv6 å议广播数æ®åŒ…çš„å‘é€å’ŒæŽ¥æ”¶
+POL_9 éšç§è¿‡æ»¤å™¨æ¨¡å¼
+POL_EX_9 有éšç§è¿‡æ»¤å™¨æ¨¡å¼ç­–略设置的会è¯é—´çš„全部通信将被过滤。
+POL_10 æ‹’ç»ä½œä¸º TCP/IP æœåŠ¡å™¨è¿è¡Œ (IPv4)
+POL_EX_10 有此会è¯ç­–略设置的计算机无法收å¬å’ŒæŽ¥å— IPv4 TCP/IP 连接。
+POL_11 æ— é™åˆ¶çš„广播数é‡
+POL_EX_11 有此会è¯ç­–略设置的计算机,如果在虚拟网络上å‘é€è¶…过一般情况的广播数æ®åŒ…é‡ï¼Œç³»ç»Ÿå°†ä¸åšè‡ªåŠ¨é™åˆ¶ã€‚
+POL_12 å…许监测模å¼
+POL_EX_12 有此策略设置的用户å…许连接到监测模å¼ä¸‹çš„虚拟 HUB 上。监测模å¼ä¸‹çš„会è¯å¯ä»¥ç›‘å¬(tap)所有æµç»æ­¤è™šæ‹Ÿ HUB çš„æ•°æ®åŒ…。
+POL_13 最大的 TCP 连接数
+POL_EX_13 对有此策略设置的会è¯ï¼Œå®ƒè®¾ç½®äº†ç‰©ç† TCP è¿žæŽ¥çš„æœ€å¤§æ•°ç›®ï¼ŒåŒ…æ‹¬åœ¨ä¸€ä¸ªç‰©ç† VPN 会è¯ä¸­ã€‚
+POL_14 超时期é™
+POL_EX_14 对有此策略设置的会è¯ï¼Œå½“ VPN Server å’Œ VPN Client 之间å‘生通信问题时,此设置在中断一个会è¯å‰ç­‰å¾…è¶…æ—¶æœŸé™ (以秒为å•ä½)。
+POL_15 最大 MAC 地å€æ•°
+POL_EX_15 对有此策略设置的会è¯ï¼Œè®¾ç½®æ¯ä¼šè¯æœ€å¤§ MAC 地å€æ•°ã€‚
+POL_16 最大 IP 地å€æ•° (IPv4)
+POL_EX_16 对有此策略设置的会è¯ï¼ŒæŒ‡å®šå•ä¸ªä¼šè¯å¯æ³¨å†Œçš„ IPv4 地å€æ•°ã€‚
+POL_17 上传带宽
+POL_EX_17 对有此策略设置的会è¯ï¼Œé™åˆ¶è™šæ‹Ÿè·¯ç”±å™¨ä¸Šç”±å¤–至内的数æ®æµé‡å¸¦å®½ã€‚
+POL_18 下载带宽
+POL_EX_18 对有此策略设置的会è¯ï¼Œé™åˆ¶è™šæ‹Ÿè·¯ç”±å™¨ä¸Šç”±å†…至外的数æ®æµé‡å¸¦å®½ã€‚
+POL_19 æ‹’ç»æ›´æ”¹å¯†ç 
+POL_EX_19 有此密ç éªŒè¯ç­–略设置的用户将无法在 VPN Client 管ç†å™¨ä¸Šè¿›è¡Œå¯†ç çš„æ›´æ¢ã€‚
+POL_20 最大多é‡ç™»å½•æ•°
+POL_EX_20 有此策略设置的用户无法进行多于设置数的并å‘登录数。 网桥模å¼ä¼šè¯ä¸é€‚用于此策略。此安全策略仅在 VPN Server 3.0 或以上版本,或具有多é‡ç™»å½•é™åˆ¶åŠŸèƒ½çš„ VPN Server 2.0 版上有效。
+POL_21 ç¦æ­¢ VoIP / QoS 功能
+POL_EX_21 有此策略设置的用户,无法在 VPN 连接会è¯ä¸­ä½¿ç”¨VoIP / QoS功能。此安全策略仅在 VPN Server 3.0 或以上版本,或具有 VoIP / QoS 功能的 VPN Server 2.0 版上有效。
+
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã‹ã‚‰ -----
+# Ver 3.0
+POL_22 过滤 RS/RA æ•°æ®åŒ…(IPv6)
+POL_EX_22 此策略定义的会è¯ä¸­æ¶ˆæ¯ç±»åž‹ä¸º 133(路由器请求)或 134(路由器通告)的所有 ICMPv6 æ•°æ®åŒ…将被过滤。因此,IPv6 客户端将无法使用 IPv6 地å€å‰ç¼€è‡ªåŠ¨æ£€æµ‹å’Œ IPv6 默认网关自动检测。
+POL_23 过滤 RA æ•°æ®åŒ…(IPv6)
+POL_EX_23 此策略定义的会è¯ä¸­æ¶ˆæ¯ç±»åž‹ä¸º 134(路由器通告)的所有 ICMPv6 æ•°æ®åŒ…将被过滤。因此,æ¶æ„用户将ä¸èƒ½åœ¨ç½‘络中传播éžæ³•çš„ IPv6 地å€å‰ç¼€æˆ–默认网关广告。
+POL_24 过滤 DHCP æ•°æ®åŒ…(IPv6)
+POL_EX_24 此策略定义的所有会è¯ä¸­çš„ IPv6 çš„ DHCP æ•°æ®åŒ…将被过滤。
+POL_25 ä¸å…许 DHCP æœåŠ¡å™¨è¿è¡Œ(IPv6)
+POL_EX_25 连接到有此策略设置的会è¯çš„计算机将ä¸å…许æˆä¸º DHCP æœåŠ¡å™¨ï¼Œä¹Ÿæ— æ³•å¯¹ DHCP ç”¨æˆ·åˆ†é… IPv6 åœ°å€ / DNS ä¿¡æ¯ã€‚
+POL_26 æ‹’ç»è·¯ç”±æ“作 (IPv6)
+POL_EX_26 有此策略设置的会è¯å°†æ‹’ç» IPv6 路由。å³ä¾¿ IP 路由器è¿è¡Œåœ¨å®¢æˆ·ç«¯ï¼Œé€šè®¯ä»å°†æ— æ³•å»ºç«‹ã€‚
+POL_27 æ‹’ç» IP 地å€å¤åˆ¶ (IPv6)
+POL_EX_27 有此策略设置的会è¯æ— æ³•ä½¿ç”¨æ­£åœ¨è¢«ä¸åŒä¼šè¯çš„计算机å ç”¨çš„å¤åˆ¶çš„ IPv6 地å€ã€‚
+POL_28 æ‹’ç»ä½œä¸º TCP/IP æœåŠ¡å™¨è¿è¡Œ (IPv6)
+POL_EX_28 有此策略设置会è¯çš„计算机ä¸èƒ½æ”¶å¬æˆ–æŽ¥å— IPv6 TCP/IP连接。
+POL_29 最大 IP 地å€æ•° (IPv6)
+POL_EX_29 对有此策略设置的会è¯ï¼ŒæŒ‡å®šå•ä¸ªä¼šè¯å¯æ³¨å†Œçš„ IPv6 地å€æ•°ã€‚
+POL_30 VPN Client ä¸æŽ¥å—密ç ä¿å­˜
+POL_EX_30 对有此策略设置的用户,用户在客户端将ä¸å†èƒ½å¤Ÿä¿å­˜å¯†ç ã€‚用户æ¯æ¬¡è¿žæŽ¥ VPN æ—¶å‡éœ€è¦è¾“入密ç ã€‚这将æ高安全性。如果å¯ç”¨æ­¤ç­–略, VPN Client 2.0 版本将被拒ç»è¿žæŽ¥ã€‚
+POL_31 VPN Client 自动断开
+POL_EX_31 对有此策略设置的用户,在特定的一段时间过去åŽï¼Œç”¨æˆ·çš„ VPN 会è¯å°†è¢«è‡ªåŠ¨æ–­å¼€ã€‚è¿™ç§æƒ…况下将ä¸æ‰§è¡Œè‡ªåŠ¨é‡æ–°è¿žæŽ¥ã€‚这将防止大é‡ä¸æ´»è·ƒçš„ VPN 会è¯ã€‚如果å¯ç”¨æ­¤ç­–略, VPN Client 2.0 版将被拒ç»è¿žæŽ¥ã€‚
+POL_32 过滤所有 IPv4 æ•°æ®åŒ…
+POL_EX_32 对定义此策略会è¯çš„所有 IPv4 å’Œ ARP æ®åŒ…将被过滤。
+POL_33 过滤所有 IPv6 æ•°æ®åŒ…
+POL_EX_33 对定义此策略会è¯çš„所有 IPv6 æ•°æ®åŒ…将被拦截。
+POL_34 è¿‡æ»¤æ‰€æœ‰éž IP æ•°æ®åŒ…
+POL_EX_34 å¯¹å®šä¹‰æ­¤ç­–ç•¥çš„æ‰€æœ‰éž IP æ•°æ®åŒ…å°†è¢«è¿‡æ»¤ã€‚â€œéž IP æ•°æ®åŒ…â€æ„æ€æ˜¯ä¸æ˜¯IPv4, ARP, 也ä¸æ˜¯ IPv6 çš„æ•°æ®åŒ…。所有通过虚拟 HUB 的带标签的 VLAN æ•°æ®åŒ…å°†è¢«è®¤ä¸ºæ˜¯éž IP æ•°æ®åŒ…。
+POL_35 在 IPv6 RA 上的éžé»˜è®¤è·¯ç”±å™¨
+POL_EX_35 对定义此策略的所有 VPN 会è¯ä¸­ï¼Œä»»ä½• IPv6 RA(路由器通告)路由器的寿命为éžé›¶å€¼çš„æ•°æ®åŒ…将设置为零值。这å¯ä»¥æœ‰æ•ˆé¿å… VPN Client å°è¯•ä½¿ç”¨è¿œç«¯çš„ IPv6 路由器作为其本地 IPv6 è·¯ç”±å™¨è€Œé€ æˆ IPv6 路由混乱的å¯æ€•è¡Œä¸ºã€‚
+POL_36 在 IPv6 RA 无默认路由器(ç‰©ç† IPv6)
+POL_EX_36 对定义此策略的所有 VPN 会è¯(åªæœ‰å½“ VPN Client / VPN Bridge å’Œ VPN Server 之间的物ç†é€šä¿¡å议是 IPv6 æ—¶),任何 IPv6 RA(路由器通告)路由器的寿命为éžé›¶å€¼çš„æ•°æ®åŒ…将设置为零值。这å¯ä»¥æœ‰æ•ˆé¿å… VPN Client å°è¯•ä½¿ç”¨è¿œç«¯çš„ IPv6 路由器作为其本地 IPv6 è·¯ç”±å™¨è€Œé€ æˆ IPv6 路由混乱的å¯æ€•è¡Œä¸ºã€‚
+POL_37 VLAN ID (IEEE802.1Q)
+POL_EX_37 您å¯ä»¥æŒ‡å®š VLAN ID 的安全策略。所有的 VPN 会è¯å®šä¹‰äº†æ­¤ç­–略,所有从用户到虚拟 HUB 的以太网数æ®åŒ…将被æ’入一个带 VLAN ID çš„ VLAN 标签(IEEE 802.1Q)。用户还å¯ä»¥æ”¶åˆ°å…·æœ‰ç›¸åŒçš„ VLAN ID çš„ VLAN 标签的数æ®åŒ…。(接收过程会自动删除 VLAN 标签)。带有任何其他 VLAN ID æˆ–éž VLAN æ•°æ®åŒ…的以太网数æ®åŒ…å°†ä¸ä¼šæ”¶åˆ°ã€‚所有没有这个策略定义的 VPN 会è¯å¯ä»¥å‘é€/接收任何类型的以太网数æ®åŒ…,ä¸ç®¡ VLAN 标签,VLAN标签也ä¸ä¼šè¢«è‡ªåŠ¨æ’入或删除。通过虚拟 HUB 的任何带标签的 VLAN æ•°æ®åŒ…å°†è¢«è§†ä¸ºéž IP æ•°æ®åŒ…。因此,带标签的 VLAN æ•°æ®åŒ…ä¸å—制于 IPv4/IPv6 安全策略,访问列表也ä¸å—其他 IPv4/IPv6 特定的深入处ç†ã€‚
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã¾ã§ -----
+
+
+# 关于远程连接对è¯æ¡†
+REMOTE_DEF_CAPTION 远程连接
+REMOTE_DEF_TITLE 指定你è¦è¿›è¡Œè¿œç¨‹è¿žæŽ¥çš„计算机。
+
+
+#关于客户通知æœåŠ¡
+CN_TITLE SoftEther VPN Client
+
+
+# 关于连接管ç†å™¨
+CM_TITLE SoftEther VPN Client 管ç†å™¨
+CM_PW_LOCALMACHINE 本地计算机
+CM_NO_REMOTE VPN Client æœåŠ¡è¿è¡Œåœ¨ %s 上,ä¸å…许远程连接。
+CM_CONNECT_FAILED 无法连接到 %s 上的 VPN Client æœåŠ¡ã€‚\r\n确认 VPN æœåŠ¡å·²å¼€å¯å¹¶æ­£å¸¸è¿è¡Œã€‚
+CM_BAD_PASSWORD 密ç é”™è¯¯ã€‚请é‡æ–°è¾“入密ç ã€‚密ç å¤§å°å†™æ•æ„Ÿã€‚
+CM_NUM_CONN_COUNT VPN 连接中: %u 账户
+CM_CONN_NO 未连接
+CM_PRODUCT_NAME SoftEther VPN Client Build %u
+CM_ACCOUNT_COLUMN_1 VPN 连接设置å称
+CM_ACCOUNT_COLUMN_2 状æ€
+CM_ACCOUNT_COLUMN_3 VPN Server 主机å(地å€)
+CM_ACCOUNT_COLUMN_3_2 虚拟 HUB å称
+CM_ACCOUNT_COLUMN_4 虚拟网络适é…器å
+CM_VLAN_COLUMN_1 虚拟网络适é…器å
+CM_VLAN_COLUMN_2 状æ€
+CM_VLAN_COLUMN_3 MAC 地å€
+CM_VLAN_COLUMN_4 版本
+CM_ACCOUNT_OFFLINE 离线
+CM_ACCOUNT_ONLINE 已连接
+CM_ACCOUNT_CONNECTING 连接中
+CM_VLAN_ENABLED 有效 (å¯ç”¨çš„)
+CM_VLAN_DISABLED 无效 (ä¸å¯ç”¨)
+CM_DELETE_ACCOUNT_MSG VPN 连接设置 "%s" 将删除,你想删除�
+CM_ST_ACCOUNT_NAME VPN 连接设置å
+CM_ST_CONNECTED 会è¯çŠ¶æ€
+CM_ST_CONNECTED_TRUE è¿žæŽ¥å®Œæˆ (会è¯å»ºç«‹)
+CM_ST_CONNECTED_FALSE å°è¯•è¿žæŽ¥
+CM_ST_CONNECTING 连接到 VPN Server 开始
+CM_ST_NEGOTIATION 谈判中
+CM_ST_AUTH 用户身份验è¯ä¸­
+CM_ST_ESTABLISHED 连接已建立
+CM_ST_RETRY é‡è¯•
+CM_ST_IDLE 空闲状æ€
+CM_ST_SERVER_NAME æœåŠ¡å™¨å
+CM_ST_SERVER_PORT 端å£å·
+CM_ST_PORT_TCP TCP ç«¯å£ %u
+CM_ST_SERVER_P_NAME æœåŠ¡ç«¯äº§å“å称
+CM_ST_SERVER_P_VER æœåŠ¡ç«¯ç‰ˆæœ¬
+CM_ST_SERVER_P_BUILD æœåŠ¡ç«¯å†…部标å·
+CM_ST_START_TIME 连接开始时间
+CM_ST_FIRST_ESTAB_TIME 首次会è¯å»ºç«‹æ—¶é—´
+CM_ST_NONE ï¼
+CM_ST_CURR_ESTAB_TIME 当å‰ä¼šè¯å»ºç«‹æ—¶é—´
+CM_ST_NUM_ESTABLISHED 已建立的会è¯æ•°
+CM_ST_NUM_STR %u 次
+CM_ST_HALF_CONNECTION åŠåŒå·¥ TCP 连接模å¼
+CM_ST_HALF_TRUE 是 (åŠåŒå·¥æ¨¡å¼)
+CM_ST_HALF_FALSE å¦ (å…¨åŒå·¥æ¨¡å¼)
+CM_ST_QOS VoIP / QoS 功能
+CM_ST_QOS_TRUE 有效 (在使用过程中)
+CM_ST_QOS_FALSE 无效
+CM_ST_NUM_TCP TCP 连接数
+CM_ST_NUM_TCP_UPLOAD 上行传输 TCP 连接数
+CM_ST_NUM_TCP_DOWNLOAD 下行传输 TCP 连接数
+CM_ST_MAX_TCP TCP 连接最大值
+CM_ST_VLAN_ID VLAN ID
+CM_ST_NO_VLAN ï¼
+CM_ST_USE_ENCRYPT 加密
+CM_ST_USE_ENCRYPT_TRUE å¯ç”¨(算法: %S)
+CM_ST_USE_ENCRYPT_TRUE2 å¯ç”¨
+CM_ST_USE_ENCRYPT_FALSE ç¦ç”¨(无加密)
+CM_ST_USE_COMPRESS 使用压缩
+CM_ST_UDP_ACCEL_ENABLED æ”¯æŒ UDP 加速
+CM_ST_UDP_ACCEL_USING UDP 加速是活跃的
+CM_ST_RUDP TCP over UDP (NAT ç©¿é€)
+CM_ST_UNDERLAY_PROTOCOL 物ç†åº•å±‚åè®®
+CM_ST_COMPRESS_TRUE 是 (%u %%)
+CM_ST_COMPRESS_FALSE å¦ (无压缩)
+CM_ST_SESSION_NAME 会è¯å
+CM_ST_CONNECTION_NAME 连接å
+CM_ST_SESSION_KEY 会è¯å¯†é’¥ (160bit)
+CM_ST_BRIDGE_MODE 网桥 / 路由模å¼
+CM_ST_MONITOR_MODE 监测模å¼
+CM_ST_YES 是
+CM_ST_NO å¦
+CM_ST_SEND_SIZE 输出数æ®é‡
+CM_ST_RECV_SIZE 输入数æ®é‡
+
+CM_ST_SEND_UCAST_NUM ä¼ é€å•æ’­æ•°æ®åŒ…
+CM_ST_SEND_UCAST_SIZE ä¼ é€å•æ’­æ€»é‡
+CM_ST_SEND_BCAST_NUM ä¼ é€å¹¿æ’­æ•°æ®åŒ…
+CM_ST_SEND_BCAST_SIZE ä¼ é€å¹¿æ’­æ€»é‡
+
+CM_ST_RECV_UCAST_NUM 接收å•æ’­æ•°æ®åŒ…
+CM_ST_RECV_UCAST_SIZE 接收å•æ’­æ€»é‡
+CM_ST_RECV_BCAST_NUM 接收广播数æ®åŒ…
+CM_ST_RECV_BCAST_SIZE 接收广播总é‡
+
+CM_ST_NUM_PACKET_STR %S æ•°æ®åŒ…
+CM_ST_SIZE_BYTE_STR %S 字节
+
+CM_NEW_ICON 创建新的 VPN 连接
+CM_VGC_ICON VPN Gate 公共 VPN 中继æœåŠ¡å™¨
+CM_VGC_LINK VPN Gate 学术试验 Web 网站
+CM_ST_TITLE %s 的连接状æ€
+CM_ST_COLUMN_1 项目
+CM_ST_COLUMN_2 状æ€
+CM_NEW_ACCOUNT_NAME_1 新的 VPN 连接
+CM_NEW_ACCOUNT_NAME_2 新的 VPN 连接 (%u)
+CM_ACCOUNT_TITLE_1 新的 VPN 连接设置属性
+CM_ACCOUNT_TITLE_2 %s 的属性
+CM_SERVER_CERT_1 指定特定è¯ä¹¦ç™»å½•(&R)
+CM_SERVER_CERT_2 指定特定è¯ä¹¦åˆ é™¤(&D)
+CM_CLIENT_CERT_1 指定客户端è¯ä¹¦(&C)
+CM_CLIENT_CERT_2 删除客户端è¯ä¹¦(&C)
+CM_CERT_INFO å‘行对象: %s\r\nå‘行人: %s\r\n有效期é™: %s
+CM_NO_CERT 您必须指定一个客户端è¯ä¹¦ç”¨äºŽç”¨æˆ·èº«ä»½éªŒè¯ã€‚
+CM_NO_SECURE 指定智能å¡å†…的客户è¯ä¹¦å’Œä¸ªäººå¯†ç ï¼Œä»¥ç”¨äºŽç”¨æˆ·èº«ä»½éªŒè¯ã€‚
+CM_CERT_SECURE_INFO è¯ä¹¦: "%S"\r\n密钥: "%S"
+CM_SELECT_SECURE_DEVICE 选择智能å¡(&P)
+CM_SELECT_CERT_INCARD 指定è¯ä¹¦åŠå¯†é’¥(&V)
+CM_VIEW_CLIENT_CERT 查看客户端è¯ä¹¦(&V)
+CM_NO_VLAN 在你创建一个新的 VPN 连接设置å‰ï¼Œéœ€è¦åˆ›å»ºä¸€ä¸ªè™šæ‹Ÿç½‘络适é…器。\r\n\r\n你想创建一个虚拟网络适é…器å—?
+CM_NO_VLAN_2 在连接到 VPN Server å‰ï¼Œä½ éœ€è¦åˆ›å»ºä¸€ä¸ªè™šæ‹Ÿç½‘络适é…器。\r\n\r\n你想创建一个虚拟网络适é…器å—?
+CM_VLAN_REMOTE_ERROR 无法远程创建虚拟网络适é…器。\r\n请在有 VPN Client æœåŠ¡çš„本地计算机上å¯åŠ¨ VPN Client 管ç†å™¨ï¼Œå®‰è£…虚拟网络适é…器。
+CM_9X_VLAN_INSTALL 一个新的虚拟网络适é…器现在将被创建。\r\n\r\n创建虚拟网络适é…器åŽï¼Œéœ€è¦é‡æ–°å¯åŠ¨ Windows 系统。\n在虚拟网络适é…器安装进行中,å¯èƒ½ä¼šè¦æ±‚ä½ æ’å…¥ Windows CD-ROM 安装盘。关闭除 VPN Client 管ç†å™¨ç¨‹åºä»¥å¤–的当å‰æ‰€æœ‰çš„è¿è¡Œç¨‹åºï¼Œå‡†å¤‡å¥½ Windows 安装盘,å•å‡»â€œç¡®å®šâ€ã€‚\r\nå•å‡»ç¡®å®šå°†å¼€å§‹è™šæ‹Ÿç½‘络适é…器的安装。安装完æˆåŽï¼ŒWindows 将自动é‡å¯ã€‚
+CM_9X_VLAN_ME_MESSAGE 虚拟网络适é…器已创建。在å•å‡»â€œç¡®å®šâ€åŽï¼Œè®¡ç®—机将自动é‡æ–°å¯åŠ¨ã€‚\r\n\r\n计算机é‡æ–°å¯åŠ¨åŽï¼Œå¯èƒ½ä¼šå‡ºçŽ°å®‰è£…新设备å‘导。\r\n如果该å‘导出现,å•å‡»æ¯ä¸€ä¸ªå±å¹•ä¸Šçš„“下一步“,直到安装完æˆã€‚
+CM_9X_VLAN_UNINSTALL è‹¥è¦åˆ é™¤è™šæ‹Ÿç½‘络适é…器,请从网络属性中删除。 \r\n\r\n你想è¦æ˜¾ç¤ºç½‘络属性窗å£å—?
+CM_PORT_1 8888 (PX-VPN 端å£)
+CM_PORT_2 443 (HTTPS 端å£)
+CM_PORT_3 992 (telnets 端å£)
+CM_PORT_4 5555 (SE-VPN 端å£)
+CM_RETRY_INTERVAL_ERROR 当 VPN 连接断开时,设置é‡æ–°è¿žæŽ¥é—´éš”(至少 5 秒)。
+CM_DELETE_CLIENT_CERT 这将删除已ç»è®¾ç½®çš„客户端è¯ä¹¦ã€‚你确定è¦åˆ é™¤å—?
+CM_DELETE_SERVER_CERT 这将删除已ç»è®¾ç½®çš„æœåŠ¡ç«¯ç‰¹å®šè¯ä¹¦ã€‚你确定è¦åˆ é™¤å—?
+CM_SET_STARTUP VPN 连接设置 "%s" 当å‰è®¾ç½®ä¸ºå¯åŠ¨è¿žæŽ¥è®¾ç½®ã€‚\r\n当下次é‡æ–°å¯åŠ¨è®¡ç®—机åŽï¼Œè´¦æˆ·å°†è¢«è‡ªåŠ¨è¿žæŽ¥ã€‚\r\n(如果你使用的是 Windows,在用户登录到 Windows å‰ï¼Œè‡ªåŠ¨è¿žæŽ¥å°†åœ¨åŽå°æ¨¡å¼ä¸‹å¯åŠ¨ã€‚)
+CM_REMOVE_STARTUP 你希望删除 VPN 设置 "%s" çš„å¯åŠ¨è¿žæŽ¥å±žæ€§å—?
+CM_NO_DISCONNECT_SPAN 请设置 TCP 连接的使用寿命。
+CM_HALF_MSG 当使用åŠåŒå·¥æ¨¡å¼æ—¶ï¼Œè®¾ç½®çš„ TCP 连接数至少是2个。
+CM_TOO_SMALL_INTERVAL 设置建立一个 TCP 连接的时间间隔至少是 1 秒钟
+CM_DELETE_VLAN 这将删除虚拟网络适é…器 "%s"。你确定删除å—?
+CM_COPY_NAME_1 å¤ä»¶ %s
+CM_COPY_NAME_2 å¤ä»¶ (%u) %s
+CM_IMPORT_NAME_1 %s
+CM_IMPORT_NAME_2 %s (%u)
+CM_CERT_COLUMN_1 å‘ç»™
+CM_CERT_COLUMN_2 å‘行人
+CM_CERT_COLUMN_3 有效期é™
+CM_CERT_DELETE_MSG 从列表中删除此è¯ä¹¦?
+CM_PASSWORD_SET 设定的密ç ã€‚
+CM_PASSWORD_REMOVE 设置的密ç è¢«åˆ é™¤ã€‚
+CM_UNDER_CONSTRUCTION 未完æˆçš„。
+CM_CURRENT_ACTIVE VPN 连接设置 "%s" 的设定已ç»ä¿å­˜ï¼Œä½†è¿™ä¸ª VPN 连接设置当å‰æ­£åœ¨çº¿ï¼Œæ–°çš„设置直到下一次连接æ‰èƒ½é€‚用。
+CM_DISCONNECT_ALL 这将断开所有的 %u 个 VPN 连接设置的当å‰è¿žæŽ¥ã€‚\r\n你确定è¦è¿™æ ·åšå—?
+CM_HTTPS_MSG 您已ç»é€‰æ‹©é€šè¿‡ HTTP 代ç†æœåŠ¡å™¨è¿›è¡Œè¿žæŽ¥ã€‚\r\n\r\n平常的 HTTP 代ç†æœåŠ¡å™¨ä¸å…许访问您所选择的 TCP 端å£ã€‚\r\n当 VPN Client 通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥åˆ° VPN Server 时,å¯èƒ½ä¼šé€šè¿‡ä½¿ç”¨ HTTPS (HTTP over SSL) 通信进行连接。\r\n在此情况下,建议您指定 443 (HTTPS 端å£) 最为目标 VPN Server 的端å£å·ã€‚\r\n(如果您指定了一个其它端å£å·ï¼Œå¯èƒ½ä¼šæ— æ³•é€šè¿‡ HTTP 代ç†æœåŠ¡å™¨è¿›è¡Œè¿žæŽ¥ã€‚\r\n确定目标 VPN Server å·²å¯ç”¨ 443 端å£ã€‚) \r\n\r\n如果需è¦è¯¦ç»†ä¿¡æ¯ï¼Œè¯·ä¸Žæ‚¨è®¡åˆ’在连接中ç»è¿‡çš„ HTTP 代ç†æœåŠ¡å™¨çš„系统管ç†å‘˜æˆ–网络管ç†å‘˜è”系。\r\n\r\n您是å¦ç¡®å®šæ”¹å˜ç›®æ ‡ VPN Server 端å£å·ä¸º 443 (HTTPS 端å£)?
+CM_REMOTE_WARNING 您正在ç¦ç”¨è¿œç¨‹ç®¡ç†ã€‚\r\n\r\nå½“å‰ VPN Client 管ç†å™¨æ­£è¿žæŽ¥åˆ°è¿œç¨‹è®¡ç®—机 "%S" 并正在控制它的 VPN Client æœåŠ¡ã€‚\r\n如果ç¦ç”¨è¿œç¨‹ç®¡ç†ï¼Œå°†æ— æ³•ç»§ç»­è¿œç¨‹è¿žæŽ¥è®¡ç®—机 "%S" 并通过 VPN Client 管ç†å™¨å¯¹ VPN Client æœåŠ¡è¿›è¡ŒæŽ§åˆ¶ã€‚\r\n\r\n是å¦ç¡®è®¤ç¦ç”¨è¿œç¨‹ç®¡ç†?
+CM_KEEP_INTERVAL_MSG 设置“数æ®åŒ…å‘é€é—´éš”†为 %u 到 %u 秒。
+CM_REMOTE_TITLE å¯ä»¥ä½¿ç”¨ VPN Client 管ç†å™¨è¿žæŽ¥å¦ä¸€å°è®¡ç®—机并远程管ç†å®ƒçš„ VPN Client æœåŠ¡ã€‚\r\n(注æ„: 远程计算机必须å…许远程管ç†ã€‚)
+CM_DESKTOP_LOCAL_PC 本地计算机
+CM_DESKTOP_REMOTE_PC 计算机 %S
+CM_DESKTOP_MSG_LOCAL_TS 终端æœåŠ¡ (远程桌é¢) 功能
+CM_DESKTOP_MSG_LOCAL_SW 切æ¢ç”¨æˆ·åŠŸèƒ½
+CM_DESKTOP_MSG_LOCAL_1 ç›®å‰ï¼Œ%s 安装在这å°è®¡ç®—机上,æ供了å…许多用户登录的环境。在此情况下,VPN Client 显示的进展状æ€ä¿¡æ¯ï¼Œé”™è¯¯ä¿¡æ¯å’Œå…¶å®ƒä¿¡æ¯å°†è¢«æ˜¾ç¤ºåœ¨â€œæŽ§åˆ¶å°ä¼šè¯â€ä¸­ã€‚
+CM_DESKTOP_MSG_LOCAL_21 â€œä¼šè¯ ID: 0,用户 %sâ€åœ¨è¿™å°è®¡ç®—机被分é…为控制å°è¿›ç¨‹ã€‚但是由于您已ç»åœ¨è¿›ç¨‹ %u ä¸Šå¼€å¯ VPN Client 管ç†å™¨ï¼Œå› æ­¤æ— æ³•æ˜¾ç¤º VPN Client 上进度状æ€æˆ–错误等信æ¯ã€‚
+CM_DESKTOP_MSG_LOCAL_22 ç›®å‰è¿™å°è®¡ç®—机上的控制å°ä¼šè¯â€œä¼šè¯ID: 0â€æ²¡æœ‰è¢«ç™»å½•ã€‚å¹¶ä¸”å› ä¸ºæ‚¨åœ¨ä¼šè¯ %u 上å¯åŠ¨äº† VPN Client 管ç†å™¨ï¼Œå› æ­¤æ— æ³•æ˜¾ç¤º VPN Client 上进度状æ€æˆ–错误等信æ¯ã€‚
+CM_DESKTOP_MSG_LOCAL_31 建议当此计算机的控制å°ä¼šè¯ (会è¯ID: 0,用户 %s) 显示时,在此会è¯ä¸­å¯åŠ¨ VPN Client æœåŠ¡å™¨å¹¶å¯åŠ¨ VPN 连接设置“%sâ€ã€‚由此您将å¯ä»¥å¯åŠ¨è¿žæŽ¥è¿›ç¨‹ï¼Œä½†è¦æ‰¿æ‹…无法检查进度状æ€æˆ–错误信æ¯çš„风险。
+CM_DESKTOP_MSG_LOCAL_32 建议您先注销,然åŽå†ä»Žæœ¬åœ°ç™»å…¥ã€‚è¿è¡Œ VPN Client 管ç†å™¨ä¼šè¯ï¼Œå¹¶å¯åŠ¨ VPN 连接设置“%sâ€ã€‚由此您将å¯ä»¥å¯åŠ¨è¿žæŽ¥è¿›ç¨‹ï¼Œä½†è¦æ‰¿æ‹…无法检查进度状æ€æˆ–错误信æ¯çš„风险。
+CM_DESKTOP_MSG_REMOTE_1 由于您在远程连接到计算机 %S 上的 VPN Client 时执行的动作,您将无法看到 VPN Client 显示的诸如进程状æ€æˆ–错误信æ¯ã€‚
+CM_DESKTOP_MSG_REMOTE_2 è¦æ£€æŸ¥æ‰€æœ‰ VPN Client 显示的进程状æ€ï¼Œé”™è¯¯å’Œå…¶ä»–ä¿¡æ¯ï¼Œæ‚¨å¿…须从计算机 %S æœ¬åœ°ç™»å…¥å¹¶æ˜¾ç¤ºæŽ§åˆ¶ä¼šè¯ (æ¡Œé¢)。
+CM_DESKTOP_MSG_REMOTE_3 建议您直接从本地 (%S) 登入。è¿è¡Œ VPN Client 管ç†å™¨ä¼šè¯ï¼Œå¹¶å¯åŠ¨ VPN 连接设置“%sâ€ã€‚由此您将å¯ä»¥å¯åŠ¨è¿žæŽ¥è¿›ç¨‹ï¼Œä½†è¦æ‰¿æ‹…无法检查进度状æ€æˆ–错误信æ¯çš„风险。
+CM_STOP_INST_VLAN_1 è¦æƒ³åœ¨æ­¤è®¡ç®—机上安装虚拟网络适é…器,您必须在“控制å°ä¼šè¯â€ä¸‹å¯åŠ¨ VPN Client 管ç†å™¨ã€‚\r\n\r\nç›®å‰ï¼Œæ­¤è®¡ç®—机上已安装 %sï¼Œä¸”ç”¨æˆ·å·²ç™»å…¥è¿œç¨‹ä¼šè¯ (会è¯ID: %u) 而ä¸æ˜¯æŽ§åˆ¶å°è¿›ç¨‹ã€‚\r\nè‹¥è¦å®‰è£…虚拟网络适é…器,必须在控制å°ä¼šè¯ (会è¯ID: %u,用户 %s 已登录) 下å¯åŠ¨ VPN Client 管ç†å™¨ã€‚\r\n\r\n首先使用切æ¢ç”¨æˆ·åŠŸèƒ½ä»Žæœ¬åœ°ç™»å…¥åˆ°è®¡ç®—机,或在远程桌é¢ä½¿ç”¨ “/console†论æ®åŠŸèƒ½ï¼Œæˆ–切æ¢è®¡ç®—机的本地控制å°è®¾å¤‡ï¼Œä¹‹åŽå¯åŠ¨ VPN Client 管ç†å™¨ï¼Œå¹¶å®‰è£…虚拟网络适é…器。
+CM_STOP_INST_VLAN_2 è¦æƒ³åœ¨æ­¤è®¡ç®—机上安装虚拟网络适é…器,您必须在“控制å°ä¼šè¯â€ä¸‹å¯åŠ¨ VPN Client 管ç†å™¨ã€‚\r\n\r\nç›®å‰ï¼Œæ­¤è®¡ç®—机上已安装 %sï¼Œä¸”ç”¨æˆ·å·²ç™»å…¥è¿œç¨‹ä¼šè¯ (会è¯ID: %u) 而ä¸æ˜¯æŽ§åˆ¶å°è¿›ç¨‹ã€‚\r\nè‹¥è¦å®‰è£…虚拟网络适é…器,必须在“控制å°ä¼šè¯â€ä¸‹å¯åŠ¨ VPN Client 管ç†å™¨ã€‚\r\n(ç›®å‰ç”¨æˆ·å¹¶æœªç™»å…¥åˆ°æŽ§åˆ¶å°ä¼šè¯ (会è¯ID: 0)。) \r\n\r\n首先使用切æ¢ç”¨æˆ·åŠŸèƒ½ä»Žæœ¬åœ°ç™»å…¥åˆ°è®¡ç®—机,或在远程桌é¢ä½¿ç”¨ “/console†论æ®åŠŸèƒ½ï¼Œæˆ–切æ¢è®¡ç®—机的本地控制å°è®¾å¤‡ï¼Œä¹‹åŽå¯åŠ¨ VPN Client 管ç†å™¨ï¼Œå¹¶å®‰è£…虚拟网络适é…器。
+CM_SHORTCUT_DESKTOP_MSG è‹¥è¦ä½¿ç”¨ VPN 连接设置快æ·æ–¹å¼å¯åŠ¨è¿žæŽ¥ï¼Œæ‚¨å¿…须在“控制å°ä¼šè¯â€ä¸‹è¿è¡Œå¿«æ·æ–¹å¼æ–‡ä»¶ã€‚\r\n\r\nç›®å‰ç”¨æˆ·ä½œä¸ºè¿œç¨‹ä¼šè¯ (会è¯ID: %u) 登入而ä¸æ˜¯æŽ§åˆ¶å°ä¼šè¯ã€‚
+CM_HTTP_PROXY_WARNING 已选择“通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥â€ã€‚\r\n\r\n一般情况下,HTTP æœåŠ¡å™¨åªå…è®¸ä¸¤ç§ TCP 端å£ä½œä¸ºè¿žæŽ¥åˆ°ç›®æ ‡æœåŠ¡å™¨çš„端å£å·: HTTP åè®® (TCP 端å£å· 80) å’Œ HTTPS åè®® (TCP 端å£å· 443)。\r\n(åŒæ ·ï¼Œä¹Ÿæœ‰çš„代ç†æœåŠ¡å™¨æ供更宽泛的 TCP 端å£ä¾›è¿žæŽ¥ä½¿ç”¨ã€‚) \r\n\r\n当通过一å°ç¦ç”¨é™¤ HTTP 端å£æˆ– HTTPS 端å£çš„ HTTP 代ç†æœåŠ¡å™¨å»ºç«‹ VPN 连接时,您必须指定 443 (HTTPS åè®®) 作为目标 VPN Server 的端å£å·ã€‚\r\n\r\nè¦æ£€æŸ¥æ‚¨å½“å‰ä½¿ç”¨çš„ HTTP 代ç†æœåŠ¡å™¨æ˜¯å¦å…许 80 或 443 æ„外的端å£ï¼Œè¯·ä¸Ž HTTP 代ç†æœåŠ¡å™¨çš„管ç†å‘˜è”系。\r\n\r\nç›®å‰ %d 指定为目标 VPN Server 的端å£å·ã€‚您是å¦è¦æ›´æ”¹ç«¯å£å·ä¸º 443 (HTTPS åè®®) ?\r\n(您所连接的 VPN Server çš„ 443 端å£å¿…须被设为监å¬çŠ¶æ€å¹¶ä¸”空闲。) \r\n如果您无法确定,请与系统管ç†å‘˜æˆ–网络管ç†å‘˜è”系。
+CM_PASSWORD_CHANGED 密ç å·²æ›´æ”¹ã€‚
+CM_ACCOUNT_SETTING_FILE VPN 连接设置文件 (*.VPN)|*.vpn|所有文件 (*.*)|*.*
+CM_ACCOUNT_SAVE_TITLE 输入è¦å¯¼å‡ºçš„ VPN 连接设置文件的文件å
+CM_ACCOUNT_OPEN_TITLE 选择è¦å¯¼å…¥çš„ VPN 连接设置文件
+CM_ACCOUNT_FILE_BANNER # VPN Client 连接设置文件\r\n# \r\n# 此文件是使用 VPN Client 管ç†å™¨å¯¼å‡ºçš„。\r\n# 此文件内容å¯ä½¿ç”¨æ–‡æœ¬ç¼–辑器进行编辑。\r\n# 当此文件通过使用客户端连接管ç†å™¨å¯¼å…¥åŽå¯ä»¥ç«‹å³è¢«ä½¿ç”¨ã€‚\r\n\r\n
+CM_FAILED_TO_OPEN_FILE 无法打开文件。
+CM_FAILED_TO_SAVE_FILE 无法ä¿å­˜æ–‡ä»¶ã€‚
+CM_ACCOUNT_PARSE_FAILED 无法从指定文件装载 VPN 连接设置。\r\n请检查文件内容。
+CM_ACCOUNT_MSG_SENSITIVE æ­¤ VPN 连接设置有用户å和密ç ã€‚\r\n您想从导出的设置文件中删除这些æ•æ„Ÿä¿¡æ¯å—?\r\n\r\nå•å‡»â€œæ˜¯â€ä»¥åˆ é™¤æ•æ„Ÿä¿¡æ¯ã€‚\r\n在这ç§æƒ…况下,当他正试图连接到 VPN Server 时,用户需è¦è¾“入用户å和密ç ã€‚\r\n\r\nå•å‡»â€œå¦â€å°†æ•æ„Ÿä¿¡æ¯ç•™åœ¨æ–‡ä»¶å†…。
+CM_SHORTCUT_FILE å¿«æ·æ–¹å¼æ–‡ä»¶|*.lnk
+CM_SHORTCUT_SAVE_TITLE 输入快æ·æ–¹å¼æ–‡ä»¶å。
+CM_SHORTCUT_UNSUPPORTED 该连接的快æ·æ–¹å¼çš„功能ä¸æ”¯æŒæ­¤ VPN Client 的版本。\r\n更新到新版本。
+CM_SHORTCUT_COMMENT 使用 VPN 连接设置“%sâ€ä»¥è¿žæŽ¥åˆ° VPN Server。
+CM_SHORTCUT_ERROR 创建快æ·æ–¹å¼å¤±è´¥ã€‚
+CM_VPN_FILE_CLICKED ä½ è¦å¯¼å…¥çš„ VPN 连接文件?
+CM_VPN_FILE_IMPORT_NG 无法导入 VPN 连接设置文件。由于 VPN Client 设置已被é”定。
+CM_VLAN_INSTALLING 请ç¨å€™...
+CM_SECURE_MUST_LOCAL 因为目å‰æ‚¨å¯¹è¿œç¨‹è®¡ç®—æœºè¿›è¡Œè¿žæŽ¥å¹¶ç®¡ç† VPN Client,因此无法修改智能å¡è®¾ç½®ã€‚
+CM_DETAIL_MODE_LINK_STR 使用级è”,则“通过网桥,路由模å¼è¿žæŽ¥â€å§‹ç»ˆå¯ç”¨ã€‚
+CM_TRAY_INITING VPN Client 管ç†å™¨
+CM_TRAY_NOT_CONNECTED VPN Client 管ç†å™¨\r\n未连接
+CM_TRAY_CONNECTED_0 VPN Client 管ç†å™¨\r\n主动连接到%u个æœåŠ¡å™¨ï¼Œå¹¶å°è¯•è¿žæŽ¥åˆ° %u 个æœåŠ¡å™¨
+CM_TRAY_CONNECTED_1 VPN Client 管ç†å™¨\r\nå°è¯•è¿žæŽ¥åˆ°%u个æœåŠ¡å™¨
+CM_TRAY_CONNECTED_2 VPN Client 管ç†å™¨\r\nçš„ %u 个æœåŠ¡å™¨ä¸­çš„连接
+CM_TRAY_MENU_1_SHOW 显示 VPN Client 管ç†å™¨(&S)
+CM_TRAY_MENU_1_HIDE 关闭 VPN Client 管ç†å™¨(&O)
+CM_TRAY_MENU_2_QUIT 退出 VPN Client 管ç†å™¨ç¨‹åº(&X)
+CM_TRAY_MENU_CONNECT å¯åŠ¨ VPN 连接(&C)
+CM_TRAY_MENU_DISCONNECT 断开 VPN 连接(&D)
+CM_TRAY_MENU_STATUS 查看 VPN 连接状æ€(&I)
+CM_TRAY_MENU_DISCONNECT_ALL 断开所有的 VPN 连接(&A)
+CM_TRAY_MENU_NEW 创建一个新的连接设置(&N)
+CM_TRAY_MENU_RECENT 近使用的 VPN Server(&Y)
+CM_TRAY_MENU_TRAFFIC 网格和通信速度测试工具(&R)
+CM_TRAY_MENU_NETIF 查看网络设备的状æ€(&D)
+CM_TRAY_MENU_ABOUT 关于 VPN Client 管ç†å™¨(&A)
+CM_TRAY_MENU_SETTING å˜æ›´è¿è¡Œæ¨¡å¼(&M)
+CM_TRAY_MENU_CANCEL 关闭此èœå•
+CM_EXIT_MESSAGE 是å¦é€€å‡º VPN Client 管ç†å™¨ç¨‹åº?
+CM_IMPORT_MESSAGE 从文件 "%S" 安装 VPN 连接设置 "%s"。
+CM_VLAN_CREATING 创建一个新的 Windows VPN 虚拟网络适é…器。\r\n\r\n这个过程å¯èƒ½ä¼šèŠ±è´¹å‡ ç§’或超过 1 分钟。 \r\n请ç¨å€™...\r\n\r\n(在虚拟网络适é…器安装过程中,请ä¸è¦æ‰§è¡Œå…¶ä»–æ“作。)
+CM_SETTING_PASSWORD 该设置已被é”定。è¦å–消这些é”定设置,您必须输入密ç ã€‚
+CM_EASY_MODE_NOT_ON_REMOTE 无法连接,因为远程计算机上的 VPN Client 在简易模å¼ä¸‹è¿è¡Œã€‚
+CM_EASY_CONNECT_BUTTON_1 å¯åŠ¨ VPN 连接
+CM_EASY_CONNECT_BUTTON_2 æ–­å¼€(&D)
+CM_EASY_ACCOUNT_WARNING 因为设置已é”定,您åªèƒ½æ›´æ”¹â€œä»£ç†æœåŠ¡å™¨è®¾å®šâ€ï¼Œâ€œç”¨æˆ·éªŒè¯â€å’Œâ€œå·²ä½¿ç”¨çš„虚拟网络适é…器â€ã€‚
+CM_EASY_INFO_1 选择一个 VPN 连接。
+CM_EASY_INFO_2 å•å‡»â€œå¼€å§‹ VPN 连接â€å¯åŠ¨ä¸€ä¸ª VPN 连接。
+CM_EASY_INFO_3 VPN 连接是活跃的。您å¯ä»¥é€šè¿‡ç‚¹å‡»â€œæ–­å¼€â€ç»ˆæ­¢è¿žæŽ¥ã€‚
+CM_EXT_VOICE_MSG 扩展语音å‘导的部分内容è¿è¡Œä¸æ­£å¸¸ã€‚\r\n扩展语音å‘导是å¦æ‰“å¼€?
+CM_EASY_TITLE VPN Client 简易连接管ç†å™¨
+CM_EASY_CONNECTED VPN 连接完æˆã€‚
+CM_EASY_CONNECTING 建立 VPN 连接中...
+CM_PROXY_FROM_IE å½“å‰ Internet Explorer 代ç†è®¾ç½®å·²åŠ è½½ã€‚
+CM_TRAY_ICON_RESTORE 托盘图标已被清除。\r\n\r\nè¦æ¢å¤è¯¥å›¾æ ‡ï¼Œè¯·å¯åŠ¨ VPN Client 管ç†å™¨å¹¶åœ¨æŸ¥çœ‹èœå•ç‚¹å‡»â€œæ˜¾ç¤ºæ‰˜ç›˜å›¾æ ‡â€ã€‚
+CM_WOULDYOULOAD_IE_PROXY ç›®å‰ï¼Œè¿™å°è®¡ç®—机的 Internet Explorer é…置使用代ç†æœåŠ¡å™¨"%S"。\r\n您想在新的 VPN 连接设置中应用当å‰ä»£ç†è®¾ç½®å—?\r\n\r\n点击“是â€ä½¿ç”¨Internet Explorer 的代ç†è®¾ç½®ã€‚\r\n点击“å¦â€ä½¿ç”¨ç›´æŽ¥è¿žæŽ¥è‡³ VPN Server(ä¸æ˜¯ä»£ç†æœåŠ¡å™¨)。\r\n此设置å¯ä»¥åœ¨è¿žæŽ¥è®¾ç½®çš„属性窗å£ã€åœ¨ä»ŠåŽçš„任何时间进行修改。
+CM_MSG_TITLE VPN Server "%S" (虚拟 HUB: "%S")
+CM_JUMPLIST_RCCONNECT 最近使用的连接设置
+CM_VPNGATE_MESSAGE 在 VPN Gate 学术项目网站上有一个公共 VPN 中继æœåŠ¡å™¨åˆ—表。\r\n互è”网上的任何人都å¯ä»¥å»ºç«‹ VPN 连接至任一列表上的 VPN æœåŠ¡å™¨ã€‚无需用户注册。\r\n\r\nVPN Gate ä¸æ˜¯ SoftEther VPN 的一部分。\r\n此图标åªæ供了一个超链接到 http://www.vpngate.net/。\r\n\r\n安装带有 SoftEther VPN Client çš„ VPN Gate Client æ’件。它å¯ç”¨ç®€å•çš„é…置连接到 VPN Gate 的一个公共 VPN 中继æœåŠ¡å™¨ã€‚\r\n\r\n你想访问 http://www.vpngate.net/ (设在日本筑波大学) ?
+
+
+# VPN Gate Service
+VGC_COLUMN_0 DDNS 唯一主机å
+VGC_COLUMN_1 IP åœ°å€ (主机å)
+VGC_COLUMN_2 国家/地区
+VGC_COLUMN_3 è¿è¡Œæ—¶é—´
+VGC_COLUMN_4 VPN 会è¯
+VGC_COLUMN_5 线路速度
+VGC_COLUMN_6 Ping (Google, SE)
+VGC_COLUMN_7 SSL-VPN (TCP)
+VGC_COLUMN_8 UDP 支æŒ
+VGC_COLUMN_9 日志策略
+VGC_COLUMN_10 累积转移
+VGC_COLUMN_11 累计用户
+VGC_COLUMN_12 æ“作员的åå­—
+VGC_COLUMN_13 æ“作员的消æ¯
+VGC_COLUMN_14 总分
+
+VGC_LOG_PERMANENT 永久的
+VGC_LOG_2WEEKS 两周
+VGC_LOG_NONE 无日志
+
+VGC_UPTIME_MIN %u 分钟
+VGC_UPTIME_HOUR %u å°æ—¶
+VGC_UPTIME_DAY %u 天
+VGC_NUM_VPN %u 会è¯
+VGC_NUM_LOGIN %S 登录次数
+
+VGC_UDP_AVAILABLE UDP OK
+
+VGC_LIST_STR_OK 在这个地çƒä¸Šçš„ %S 公共 VPN 中继æœåŠ¡å™¨ ! (更新于 %S)
+VGC_LIST_STR_OK_2 %S æœåŠ¡å™¨ (更新于 %S) - æœåŠ¡å™¨åˆ—表更新失败。如果å†æ¬¡å¤±è´¥ï¼Œè¯·ä¸‹è½½æœ€æ–°çš„ VPN Gate Client。
+VGC_LIST_STR_NG æœåŠ¡å™¨åˆ—表更新失败。如果å†æ¬¡å¤±è´¥ï¼Œè¯·ä¸‹è½½æœ€æ–°çš„ VPN Gate Client。
+VGC_PROXY_MSG 如果您使用的是代ç†æœåŠ¡å™¨ï¼Œæ‚¨å¯èƒ½æ— æ³•ä½¿ç”¨ä¸æ”¯æŒ TCP 443 端å£ã€ä»Žè¿™æ ·çš„代ç†å§”托网络ã€ä½œä¸º "SSL-VPN 连接" çš„ VPN 中继æœåŠ¡å™¨ã€‚
+VGC_PROXY_TITLE 代ç†æœåŠ¡å™¨ç”¨æˆ·çš„注æ„事项
+
+VGS_NO_HUB_YET 为了设置消æ¯ï¼Œé¦–先你得æ交å¯ç”¨ VPN Gate æœåŠ¡ã€‚在å¯ç”¨è¯¥æœåŠ¡åŽï¼Œé‡æ–°æ‰“开此窗å£ï¼Œå¹¶è®¾ç½®æ¶ˆæ¯ã€‚
+
+VGC_TITLE VPN Gate Plug-in Message
+
+VGC_VER_DIFF The version of VPN Gate Client Plug-in is different from SoftEther VPN Client.\r\n\r\n- Current VPN Gate Plug-in: Build %u\r\n- Current SoftEther VPN Client: Build %u\r\n\r\nIt is recommended to download and install VPN Gate Plug-in Build %u. Otherwise, communication errors or list-update errors might be occur. If the VPN Server List updating fails many times, update the VPN Gate Plug-in version.\r\n\r\nThe latest VPN Gate Plug-in is available at http://www.vpngate.net/.\r\n(Use a mirror-site if you cannot visit the above web-site directly.)\r\n\r\n
+
+VGS_STOP VPN Gate Service will stop after you click the OK button.\r\n\r\nAfter VPN Gate Service will be stopped, this computer will never accept new VPN connection requests, however, still-alive VPN Sessions might remain.\r\n (Such VPN sessions sometimes hidden from the enumeration.) \r\n\r\nTo terminate all of still-alive VPN Sessions completely, restart SoftEther VPN Server or SoftEther VPN Client service, or reboot the computer.
+
+VGS_START This will activate the VPN Gate Relay Service function.\r\n\r\nVPN Gate Relay Service function must be activated by your own risk.\r\nSome countries prohibit using of encrypted VPN by laws.\r\nFor more details about VPN Gate Relay Service please visit http://www.vpngate.net/en/join.aspx.\r\n\r\nThe VPN Gate Academic Experiment Service is operated as a research project at the graduate school on University of Tsukuba, Japan. The service is governed under the Japanese laws. Other countries' laws are none of our concerns nor responsibilities.\r\n\r\nBy nature, there are almost 200 countries in the World, with different laws. It is impossible to verify every countries' laws and regulations and make the software comply with all countries' laws in advance to release the software. If a user uses VPN Gate service in a specific country, and damaged by public servants of the authority, the developer of either the service or software will never be liable to recover or compensate such damages or criminal responsibilities.\r\nBy using this software and service, the user must observe all concerned laws and rules with user's own responsibility. The user will be completely liable to any damages and responsibilities which are results of using this software and service, regardless of either inside or outside of Japan's territory.\r\nIf you don't agree nor understand the above warnings, do not use any of VPN Gate Academic Experiment Service functions.
+
+
+
+#关于æœåŠ¡ (Win32)
+SVC_HELP “%s (%S) 的命令行å‚æ•°â€\r\n\r\næ­¤ç¨‹åº (%s) 是一个åŽå°ä»»åŠ¡è¿è¡Œè¿›ç¨‹ã€‚通过指定以下命令行å‚æ•°å¯åŠ¨ç¨‹åºã€‚\r\n\r\n\r\n/install …… 在 Windows 安装 %s æœåŠ¡ (æœåŠ¡å: %S)。之åŽæœåŠ¡è‡ªåŠ¨å¯åŠ¨ã€‚\r\n\r\n/uninstall …… 从 Windows å¸è½½ %s æœåŠ¡ (æœåŠ¡å: %S)。\r\n\r\n/start …… å¯åŠ¨ %s æœåŠ¡ (æœåŠ¡å: %S)。\r\n\r\n/stop …… åœæ­¢ %s æœåŠ¡ (æœåŠ¡å: %S)。\r\n\r\n/test …… å¯åŠ¨ %s 程åºçš„测试模å¼ã€‚(调试用) \r\n\r\n/usermode … å¯åŠ¨ %s 程åºçš„用户模å¼ã€‚(如果å¯ç”¨)\r\n\r\n/usermode_showtray …… 用户模å¼ä¸‹å¯åŠ¨æ—¶ï¼Œæ˜¾ç¤ºä»»åŠ¡æ å›¾æ ‡ã€‚(若之å‰è®¾ä¸ºéšè—)\r\n\r\n/usermode_hidetray …… 用户模å¼ä¸‹å¯åŠ¨æ—¶ï¼Œéšè—任务æ å›¾æ ‡ã€‚\r\n\r\n\r\n注æ„: 除 /test å’Œ /usermode 之外的命令仅在 Windows NT / 2000 / XP / Server 2003 / Vista / Server 2008 / 7 / Server 2008 R2 下有效。
+SVC_NT_ONLY 命令相关的æœåŠ¡ä»…在 Windows NT / 2000 / XP / Server 2003 / Vista / Server 2008 / 7 / Server 2008 R2 下有效。\r\nWindows 98 / Me下无效。
+SVC_ALREADY_INSTALLED "%s" æœåŠ¡ (æœåŠ¡å: %S) å·²ç»å®‰è£…在这å°è®¡ç®—机上。你想å¸è½½å¹¶é‡æ–°å®‰è£…å—?
+SVC_INSTALL_OK "%s" æœåŠ¡ (æœåŠ¡å: %S) å·²æˆåŠŸå®‰è£…完毕。\r\n\r\n(执行路径: %s)\r\n\r\næœåŠ¡å¯åŠ¨å®Œæˆã€‚
+SVC_INSTALL_FAILED "%s" æœåŠ¡ (æœåŠ¡å: %S) 安装失败
+SVC_INSTALL_FAILED_2 "%s" æœåŠ¡ (æœåŠ¡å: %S) å·²æˆåŠŸå®‰è£…完毕。\r\n\r\n(执行路径: %s)\r\n\r\nå°è¯•å¯åŠ¨å¤±è´¥ã€‚
+SVC_NOT_INSTALLED "%s" æœåŠ¡ (æœåŠ¡å: %S) 没有安装在此计算机上。请使用命令行å‚æ•° /install 进行安装。
+SVC_START_OK "%s" æœåŠ¡ (æœåŠ¡å: %S) æˆåŠŸå¯åŠ¨ã€‚
+SVC_START_FAILED "%s" æœåŠ¡ (æœåŠ¡å: %S) 无法å¯åŠ¨ã€‚
+SVR_ALREADY_START "%s" æœåŠ¡ (æœåŠ¡å: %S) å·²å¯åŠ¨ã€‚
+SVC_STOP_OK "%s" æœåŠ¡ (æœåŠ¡å: %S) 被åœæ­¢ã€‚
+SVC_STOP_FAILED åœæ­¢ "%s" æœåŠ¡ (æœåŠ¡å: %S) 失败。
+SVC_ALREADY_STOP "%s" æœåŠ¡ (æœåŠ¡å: %S) 已被åœæ­¢ã€‚
+SVC_UNINSTALL_OK "%s" æœåŠ¡ (æœåŠ¡å: %S) å·²å¸è½½ã€‚
+SVC_UNINSTALL_FAILED "%s" æœåŠ¡ (æœåŠ¡å: %S) 无法å¸è½½ã€‚
+SVC_NOT_FOUND 字符串表中找ä¸åˆ°æœåŠ¡ %S çš„ä¿¡æ¯ã€‚
+SVC_NOT_ADMIN è¦å®‰è£… / å¸è½½ / å¯åŠ¨ / åœæ­¢æœåŠ¡ï¼Œæ‚¨å¿…须在此计算机上有管ç†å‘˜æƒé™ã€‚\r\n\r\n如果您在此计算机上有管ç†å‘˜è´¦æˆ·ï¼Œè¯·ç™»å‡ºåŽä½œä¸ºç®¡ç†å‘˜å†ç™»å…¥ã€‚\r\n如果您ä¸äº†è§£ç®¡ç†å‘˜è´¦æˆ·ï¼Œè¯·ä¸Žç³»ç»Ÿç®¡ç†å‘˜è”系。
+SVC_TEST_MSG æœåŠ¡ "%s" 在测试模å¼ä¸‹å¯åŠ¨ã€‚\r\n\r\nå•å‡»â€œç¡®å®šâ€é€€å‡ºæœåŠ¡ã€‚
+SVC_TRAY_TOOLTIP %S (用户模å¼)
+SVC_TEST_MUTEX å¯æ‰§è¡Œæ–‡ä»¶ %s å·²ç»è¿è¡Œã€‚
+SVC_USERMODE_MUTEX %s çš„å¦ä¸€ä¸ªè¿›ç¨‹å·²ç»è¿è¡Œã€‚
+SVC_SERVICE_MUTEX 由于æœåŠ¡ %S 有已å¯åŠ¨çš„进程 %s,因此æœåŠ¡æ— æ³•å¯åŠ¨
+SVC_USERMODE_MENU_1 éšè—任务æ å›¾æ ‡(&H)
+SVC_USERMODE_MENU_2 退出 %s (&X)
+SVC_HIDE_TRAY_MSG å¯åŠ¨ %S 用户模å¼æ—¶å°†éšè—任务æ å›¾æ ‡ã€‚\r\n从下次 %S å¯åŠ¨å¼€å§‹ï¼Œå›¾æ ‡å°†ä¸ä¼šåœ¨ä»»åŠ¡æ æ˜¾ç¤ºã€‚\r\n退出进程的èœå•ä¹Ÿå°†è¢«éšè—。\r\n\r\n如果è¦åœ¨ Windows98 / Me 下退出进程,使用 Ctrl + Alt + Del 组åˆé”®ç„¶åŽé€‰æ‹©ç»“æŸè¿›ç¨‹ã€‚\r\n当使用其他æ“作系统,请使用任务管ç†å™¨ã€‚\r\n\r\nè¦å†æ¬¡æ˜¾ç¤ºä»»åŠ¡æ å›¾æ ‡ï¼Œåœ¨ç”¨æˆ·æ¨¡å¼ä¸‹æ¬¡å¯åŠ¨æ—¶ï¼Œä½¿ç”¨ /usermode_showtray 选项。
+
+
+#关于æœåŠ¡ (UNIX)
+UNIX_SVC_HELP %S Service Program\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n\n%S Command Usage:\n %S start - Start %S Service.\n %S stop - Stop %S Service if the service is already started.\n\n
+UNIX_SVC_STARTED %S Service Started.\n
+UNIX_SVC_STOPPING Stopping %S Service...\n
+UNIX_SVC_STOPPED %S Service Stopped.\n
+UNIX_SVC_STOP_FAILED %S Service Stop Failed.\n
+UNIX_SVC_ALREADY_START %S Service is already started.\nExecute "%S stop" to stop this service.\n
+UNIX_SVC_NOT_STARTED %S Service is not yet started.\nExecute "%S start" to start this service.\n
+UNIX_SVC_ERROR_FORK Failed to create child process for %S Service.\n
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Client)
+SVC_VPNCLIENT_NAME vpnclient
+SVC_VPNCLIENT_TITLE SoftEther VPN Client
+SVC_VPNCLIENT_DESCRIPT 它为 SoftEther VPN Client 管ç†è™šæ‹Ÿç½‘络适é…器设备驱动和连接æœåŠ¡ã€‚当æœåŠ¡åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机将无法使用 SoftEther VPN Client 连接到 SoftEther VPN Server。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Server)
+SVC_VPNSERVER_NAME vpnserver
+SVC_VPNSERVER_TITLE SoftEther VPN Server
+SVC_VPNSERVER_DESCRIPT å®ƒç®¡ç† SoftEther VPN Server æœåŠ¡è¿›ç¨‹ã€‚SoftEther VPN Server 通过 TCP/IP åè®®æ供高性能 SoftEther VPN Server 功能。当此æœåŠ¡è¢«åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机上的 SoftEther VPN Client 也将åœæ­¢ï¼Œä¸” SoftEther VPN Client 将无法与此计算机建立 VPN 连接。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Bridge)
+SVC_VPNBRIDGE_NAME vpnbridge
+SVC_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_VPNBRIDGE_DESCRIPT å®ƒç®¡ç† SoftEther VPN Bridge æœåŠ¡è¿›ç¨‹ã€‚SoftEther VPN Bridge æ供此计算机连接的网络与远程 SoftEther VPN Server 之间的连接。当此æœåŠ¡è¢«åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机上的 SoftEther VPN Bridge 也将åœæ­¢ï¼Œä¸”无法å†é€šè¿‡ç½‘桥连接进行通信。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Client)
+SVC_SEVPNCLIENT_NAME sevpnclient
+SVC_SEVPNCLIENT_TITLE SoftEther VPN Client
+SVC_SEVPNCLIENT_DESCRIPT 它为 SoftEther VPN Client 管ç†è™šæ‹Ÿç½‘络适é…器设备驱动和连接æœåŠ¡ã€‚当æœåŠ¡åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机将无法使用 SoftEther VPN Client 连接到 SoftEther VPN Server。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Server)
+SVC_SEVPNSERVER_NAME sevpnserver
+SVC_SEVPNSERVER_TITLE SoftEther VPN Server
+SVC_SEVPNSERVER_DESCRIPT å®ƒç®¡ç† SoftEther VPN Server æœåŠ¡è¿›ç¨‹ã€‚SoftEther VPN Server 通过 TCP/IP åè®®æ供高性能 SoftEther VPN Server 功能。当此æœåŠ¡è¢«åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机上的 SoftEther VPN Client 也将åœæ­¢ï¼Œä¸” SoftEther VPN Client 将无法与此计算机建立 VPN 连接。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN Bridge)
+SVC_SEVPNBRIDGE_NAME sevpnbridge
+SVC_SEVPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_SEVPNBRIDGE_DESCRIPT å®ƒç®¡ç† SoftEther VPN Bridge æœåŠ¡è¿›ç¨‹ã€‚SoftEther VPN Bridge æ供此计算机连接的网络与远程 SoftEther VPN Server 之间的连接。当此æœåŠ¡è¢«åœæ­¢æ—¶ï¼Œæ­¤è®¡ç®—机上的 SoftEther VPN Bridge 也将åœæ­¢ï¼Œä¸”无法å†é€šè¿‡ç½‘桥连接进行通信。
+
+
+# æœåŠ¡å®šä¹‰ (SoftEther VPN User-mode Router)
+SVC_VPNROUTER_NAME vpnrouter
+SVC_VPNROUTER_TITLE SoftEther VPN Router
+SVC_VPNROUTER_DESCRIPT 这是用æ¥ç®¡ç† SoftEther VPN 路由器(æœåŠ¡æ¨¡å¼)çš„æœåŠ¡å™¨è¿›ç¨‹ã€‚ SoftEther VPN 的路由器是一个程åºï¼Œå®ƒæ供了一个虚拟 NAT å’Œ DHCP æœåŠ¡å™¨ï¼Œåœ¨ç”¨æˆ·æ¨¡å¼ä¸‹è¿è¡Œï¼Œé€šè¿‡ä½¿ç”¨ç®€å•çš„æ“作,它å¯ä»¥å»ºç«‹ä¸€ä¸ªåœ¨è™šæ‹Ÿ IP ç½‘ç»œå’Œä¸€ä¸ªç‰©ç† IP 网络之间的安全连接。如果此æœåŠ¡è¢«åœæ­¢ï¼Œåœ¨è¿™å°ç”µè„‘上的 SoftEther VPN 路由器将åœæ­¢ï¼Œ SoftEther VPN Client 将无法在这å°ç”µè„‘上使用路由æœåŠ¡ã€‚
+
+
+# サービス定義 (EtherLogger)
+SVC_ELOGSVC_NAME elogsvc
+SVC_ELOGSVC_TITLE SoftEther EtherLogger
+SVC_ELOGSVC_DESCRIPT SoftEther EtherLogger 是一个æ•æ‰ä»Žå±€åŸŸç½‘å¡è¿žæŽ¥åˆ°ç”µè„‘上数æ®æµçš„æœåŠ¡ï¼Œä¿å­˜ç”±ç®¡ç†å‘˜æŒ‡å®šç±»åž‹çš„æ•°æ®åŒ…的包头日志,所有数æ®ä»¥æ–‡æœ¬æ–‡ä»¶æ ¼å¼ã€‚
+
+
+#关于 SoftEther VPN Server 管ç†å™¨
+SM_TITLE SoftEther VPN Server 管ç†å™¨
+SM_LOCALHOST 本地主机 (æ­¤æœåŠ¡å™¨)
+SM_SERVER_BRIDGE_TITLE ç®¡ç† VPN Bridge "%S"
+SM_S_VHUB_BRIDGE 当使用 VPN Bridge 时,管ç†è™šæ‹Ÿ HUB“BRIDGEâ€è¿è¡Œ VPN Bridge 的管ç†ã€‚
+SM_DISCONNECTED 管ç†è¿žæŽ¥å·²æ–­å¼€ã€‚
+SM_MIKAN 未完æˆã€‚
+SM_MAIN_COLUMN_1 设置å称
+SM_MAIN_COLUMN_2 VPN Server 主机å(地å€)
+SM_MAIN_COLUMN_3 æ“作模å¼
+SM_MODE_SERVER 整个 VPN Server
+SM_MODE_HUB %S
+SM_EDIT_CAPTION_1 新的连接设置
+SM_EDIT_CAPTION_2 %s 的编辑
+SM_SETTING_EXISTS 与连接设置 "%s" åŒå的连接设置已ç»æ³¨å†Œã€‚请指定一个ä¸åŒçš„å称。
+SM_SETTING_DELETE_MSG 是å¦ç¡®å®šåˆ é™¤è¿žæŽ¥è®¾ç½® "%s"?
+SM_PASSWORD_TYPE_STR 管ç†è¿žæŽ¥ç”¨å¯†ç 
+SM_HUB_COLUMN_1 虚拟 HUB å
+SM_HUB_COLUMN_2 状æ€
+SM_HUB_COLUMN_3 类型
+SM_HUB_COLUMN_4 用户
+SM_HUB_COLUMN_5 组
+SM_HUB_COLUMN_6 会è¯
+SM_HUB_COLUMN_7 MAC 表
+SM_HUB_COLUMN_8 IP 表
+SM_HUB_COLUMN_9 登录次数
+SM_HUB_COLUMN_10 最åŽç™»å½•æ—¶é—´
+SM_HUB_COLUMN_11 最åŽé€šä¿¡æ—¶é—´
+SM_HUB_ONLINE 在线
+SM_HUB_OFFLINE 离线
+SM_HUB_STANDALONE 独立
+SM_HUB_STATIC é™æ€è™šæ‹Ÿ HUB
+SM_HUB_DYNAMIC 动æ€è™šæ‹Ÿ HUB
+SM_SERVER_STANDALONE 独立æœåŠ¡å™¨
+SM_FARM_CONTROLLER 群集控制器
+SM_FARM_MEMBER 群集æˆå‘˜æœåŠ¡å™¨
+SM_INFORMATION 最新信æ¯
+SM_HUB_STATUS_CAPTION 虚拟 HUB "%s" 状æ€
+SM_HUB_STATUS_HUBNAME 虚拟 HUB å称
+SM_HUB_STATUS_ONLINE 状æ€
+SM_HUB_TYPE 类型
+SM_HUB_NUM_SESSIONS 会è¯æ•°
+SM_HUB_NUM_SESSIONS_CLIENT 会è¯æ•° (客户端)
+SM_HUB_NUM_SESSIONS_BRIDGE 会è¯æ•° (网桥)
+SM_HUB_NUM_ACCESSES 访问列表
+SM_HUB_NUM_USERS 用户数
+SM_HUB_NUM_GROUPS 组数
+SM_HUB_NUM_MAC_TABLES MAC 表数
+SM_HUB_NUM_IP_TABLES IP 表数
+SM_HUB_SECURE_NAT SecureNAT 机能
+SM_HUB_SECURE_NAT_YES 有效
+SM_HUB_SECURE_NAT_NO 无效
+SM_HUB_NUM_LOGIN 登录次数
+SM_HUB_LAST_LOGIN_TIME 最åŽç™»å½•æ—¶é—´
+SM_HUB_LAST_COMM_TIME 最åŽé€šä¿¡æ—¶é—´
+SM_HUB_CREATED_TIME 创建日期
+SM_STATUS_COLUMN_1 项目
+SM_STATUS_COLUMN_2 值
+
+SM_ST_SEND_UCAST_NUM å‘é€å•æ’­æ•°æ®åŒ…
+SM_ST_SEND_UCAST_SIZE å‘é€å•æ’­æ€»é‡
+SM_ST_SEND_BCAST_NUM å‘é€å¹¿æ’­æ•°æ®åŒ…
+SM_ST_SEND_BCAST_SIZE å‘é€å¹¿æ’­æ€»é‡
+
+SM_ST_RECV_UCAST_NUM 接收å•æ’­æ•°æ®åŒ…
+SM_ST_RECV_UCAST_SIZE 接收å•æ’­æ€»é‡
+SM_ST_RECV_BCAST_NUM 接收广播数æ®åŒ…
+SM_ST_RECV_BCAST_SIZE 接收广播总é‡
+
+SM_ST_NUM_PACKET_STR %S æ•°æ®åŒ…
+SM_ST_SIZE_BYTE_STR %S 字节
+
+CM_EDIT_HUB_1 新的虚拟 HUB
+CM_EDIT_HUB_2 %S 的属性
+
+CM_EDIT_HUB_STANDALONE 当å‰ï¼ŒæœåŠ¡å™¨æ­£ä»¥ç‹¬ç«‹æ¨¡å¼è¿è¡Œã€‚而该虚拟 HUB 作为一个独立的 HUB è¿è¡Œã€‚
+CM_EDIT_HUB_TYPE_FIXED 当å‰ï¼ŒæœåŠ¡å™¨æ­£ä»¥ç¾¤é›†æ¨¡å¼è¿è¡Œã€‚如果虚拟 HUB 处于这ç§æ¨¡å¼ï¼ŒåŠ¨æ€å˜åŒ–将无法进行。
+CM_EDIT_HUB_CREATER 一个新的虚拟 HUB "%S" å·²ç»å»ºç«‹
+CM_OFFLINE_MSG ä½ æƒ³åˆ‡æ¢ "%s" 到离线状æ€?\r\n\r\n如果您切æ¢è™šæ‹Ÿ HUB 至离线状æ€ï¼Œå½“å‰è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB 上的所有会è¯å°†æ— æ³•è¿žæŽ¥ã€‚
+CM_DELETE_HUB_MSG 你想删除"%S"å—?\r\n\r\n如果你删除虚拟 HUB,当å‰è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB 的所有会è¯å°†è¢«æ–­å¼€ï¼Œæ–°çš„会è¯å°†æ— æ³•è¿žæŽ¥ã€‚\r\n这还将删除所有 HUB 设置,用户对象,组对象,è¯ä¹¦å’Œçº§è”连接。\r\n\r\n一旦你将虚拟 HUB 删除,将无法æ¢å¤ã€‚\r\n你确定è¦åˆ é™¤å—?
+CM_HUB_DELETED_MSG 虚拟 HUB "%S" 被删除。
+CM_LISTENER_COLUMN_1 端å£å·
+CM_LISTENER_COLUMN_2 状æ€
+CM_LISTENER_TCP_PORT TCP %u
+CM_LISTENER_ONLINE 监å¬ä¸­
+CM_LISTENER_OFFLINE åœæ­¢ä¸­
+CM_LISTENER_ERROR 错误
+CM_DELETE_LISTENER_MSG 监å¬å™¨ (TCP ç«¯å£ %u) 将删除。从现在起,将无法连接到该端å£ã€‚\r\n你确定è¦è¿™æ ·åšå—?
+CM_STOP_LISTENER_MSG 监å¬å™¨ (TCP ç«¯å£ %u) å°†åœæ­¢ã€‚监å¬å™¨å°†æ— æ³•è¿žæŽ¥åˆ°è¯¥ç«¯å£ç›´åˆ°é‡æ–°å¯åŠ¨é™å¬å™¨ã€‚\r\n\r\n你确定å—?
+CM_CLOSE_BUTTON 关闭
+CM_CERT_SET_MSG 设置了新的æœåŠ¡å™¨è¯ä¹¦ã€‚
+CM_SHORTCUT_DISCONNECT å·²ç»è¿žæŽ¥åˆ°æŒ‡å®šçš„目标。 \r\n\r\n你想断开å—?
+
+
+
+SM_SERVER_STATUS æœåŠ¡å™¨çŠ¶æ€
+SM_ST_SERVER_TYPE æœåŠ¡å™¨ç±»åž‹
+SM_ST_NUM_TCP 活跃 TCP æ’å£æ•°
+SM_ST_NUM_TCP_LOCAL 活跃 TCP æ’å£æ•° (æ­¤æœåŠ¡å™¨)
+SM_ST_NUM_TCP_REMOTE 活跃 TCP æ’å£æ•° (其他æˆå‘˜æœåŠ¡å™¨)
+SM_ST_NUM_HUB_TOTAL 虚拟 HUB 数
+SM_ST_NUM_HUB_STATIC é™æ€è™šæ‹Ÿ HUB æ•°
+SM_ST_NUM_HUB_DYNAMIC 动æ€è™šæ‹Ÿ HUB æ•°
+SM_ST_NUM_SESSION_TOTAL 会è¯æ•°
+SM_ST_NUM_SESSION_LOCAL 会è¯æ•° (æ­¤æœåŠ¡å™¨)
+SM_ST_NUM_SESSION_REMOTE 会è¯æ•° (其他æˆå‘˜æœåŠ¡å™¨)
+SM_ST_NUM_MAC_TABLE MAC 地å€è¡¨æ•°
+SM_ST_NUM_IP_TABLE IP 地å€è¡¨æ•°
+SM_ST_NUM_USERS 用户数
+SM_ST_NUM_GROUPS 组数
+SM_ST_CLIENT_LICENSE 使用客户端连接许å¯è¯æ•° (æ­¤æœåŠ¡å™¨)
+SM_ST_BRIDGE_LICENSE 使用网桥连接许å¯è¯æ•° (æ­¤æœåŠ¡å™¨)
+SM_ST_CLIENT_LICENSE_EX 使用客户端连接许å¯è¯æ•° (整个群)
+SM_ST_BRIDGE_LICENSE_EX 使用网桥连接许å¯è¯æ•° (整个群)
+SM_ST_START_TIME æœåŠ¡å™¨å¯åŠ¨æ—¶é—´
+SM_ST_CURRENT_TIME 当å‰æ—¶é—´
+SM_ST_CURRENT_TICK 64 ä½é«˜ç²¾åº¦é€»è¾‘系统时钟
+SM_ST_TOTAL_MEMORY 总逻辑内存空间
+SM_ST_USED_MEMORY 已用逻辑内存空间
+SM_ST_FREE_MEMORY å¯ç”¨é€»è¾‘内存空间
+SM_ST_TOTAL_PHYS 总物ç†å†…存空间
+SM_ST_USED_PHYS 已用的物ç†å†…存空间
+SM_ST_FREE_PHYS å¯ç”¨ç‰©ç†å†…存空间
+SM_ST_RAM_SIZE_KB %S 字节
+SM_INFO_TITLE VPN Server 版本信æ¯
+SM_INFO_PRODUCT_NAME 产å“å称
+SM_INFO_VERSION 版本
+SM_INFO_BUILD 内部标å·
+SM_INFO_HOSTNAME 主机å称
+SM_OS_SYSTEM_NAME æ“作系统类型
+SM_OS_PRODUCT_NAME æ“作系统产å“å称
+SM_OS_SERVICE_PACK æœåŠ¡åŒ…
+SM_OS_SP_TAG Service Pack %u
+SM_OS_VENDER_NAME æ“作系统制造商
+SM_OS_VERSION æ“作系统版本
+SM_OS_KERNEL_NAME æ“作系统内核分类
+SM_OS_KERNEL_VERSION æ“作系统内核版本
+SM_CONNECTION_TYPE_0 客户端
+SM_CONNECTION_TYPE_1 åˆå§‹åŒ–中
+SM_CONNECTION_TYPE_2 登录
+SM_CONNECTION_TYPE_3 追加连接
+SM_CONNECTION_TYPE_4 群集 RPC
+SM_CONNECTION_TYPE_5 管ç†ç”¨ RPC
+SM_CONNECTION_TYPE_6 HUB 枚举 RPC
+SM_CONNECTION_TYPE_7 更改密ç 
+SM_CONNECTION_TYPE_8 MS-SSTP 连接
+SM_CONNECTION_TYPE_9 OpenVPN 连接
+SM_CONN_COLUMN_1 连接å称
+SM_CONN_COLUMN_2 连接æº
+SM_CONN_COLUMN_3 连接开始
+SM_CONN_COLUMN_4 类型
+SM_HOSTNAME_AND_PORT %S:%u
+SM_CONN_DISCONNECT_MSG 连接 %s 将断开。\r\n你确定è¦è¿™ä¹ˆåšå—?
+SM_CONNINFO_CAPTION 连接 %s çš„ä¿¡æ¯
+SM_CONNINFO_NAME 连接å称
+SM_CONNINFO_TYPE 连接类型
+SM_CONNINFO_HOSTNAME æºä¸»æœºå称
+SM_CONNINFO_IP æº IP 地å€
+SM_CONNINFO_PORT æºç«¯å£å· (TCP)
+SM_CONNINFO_TIME 连接开始
+SM_CONNINFO_SERVER_STR æœåŠ¡ç«¯äº§å“å
+SM_CONNINFO_SERVER_VER æœåŠ¡ç«¯ç‰ˆæœ¬
+SM_CONNINFO_SERVER_BUILD æœåŠ¡ç«¯å†…部标å·
+SM_CONNINFO_CLIENT_STR 客户端产å“å
+SM_CONNINFO_CLIENT_VER 客户端版本
+SM_CONNINFO_CLIENT_BUILD 客户端内部标å·
+SM_FARM_REBOOT_MSG ä½ å°†è¦æ›´æ”¹ç¾¤é›†é…置。\r\n\r\n当你更改群集é…置时,所有当å‰ä¸ºç®¡ç†è€Œè¿›è¡Œçš„会è¯å’Œè¿žæŽ¥ (包括此管ç†è¿žæŽ¥) 将断开,æœåŠ¡ç«¯ç¨‹åºå°†é‡æ–°å¯åŠ¨ã€‚\r\n当æœåŠ¡ç«¯ç”¨æˆ·è¾ƒå¤šçš„时候,é‡æ–°å¯åŠ¨éœ€è¦ç”¨ä¸€åˆ†é’Ÿçš„时间。\r\n\r\nå•å‡»â€œç¡®å®šâ€è‡ªåŠ¨æ–­å¼€ä¸ŽæœåŠ¡å™¨çš„连接。è¦ç»§ç»­ç®¡ç†ï¼Œä½ éœ€è¦é‡æ–°è¿žæŽ¥åˆ°æœåŠ¡å™¨ã€‚
+SM_FM_COLUMN_1 类型
+SM_FM_COLUMN_2 连接开始时间
+SM_FM_COLUMN_3 主机å称
+SM_FM_COLUMN_4 点
+SM_FM_COLUMN_5 会è¯æ•°
+SM_FM_COLUMN_6 TCP 连接数
+SM_FM_COLUMN_7 è¿è¡Œ HUB æ•°
+SM_FM_COLUMN_8 使用客户端连接许å¯è¯
+SM_FM_COLUMN_9 使用网桥连接许å¯è¯
+SM_FM_CONTROLLER 控制器
+SM_FM_MEMBER æˆå‘˜
+SM_FMINFO_TYPE æœåŠ¡å™¨ç±»åž‹
+SM_FMINFO_CONNECT_TIME 连接建立时间
+SM_FMINFO_IP IP 地å€
+SM_FMINFO_HOSTNAME 主机å称
+SM_FMINFO_POINT 点
+SM_FMINFO_WEIGHT 性能标准比
+SM_FMINFO_NUM_PORT 公共端å£æ•°
+SM_FMINFO_PORT %u ä¸ªå…¬å…±ç«¯å£ (TCP/IP)
+SM_FMINFO_NUM_HUB è¿è¡Œè™šæ‹Ÿ HUB æ•°
+SM_FMINFO_HUB %u 个虚拟 HUB
+SM_FMINFO_HUB_TAG_1 %S (动æ€)
+SM_FMINFO_HUB_TAG_2 %S (é™æ€)
+SM_FMINFO_NUM_SESSION 会è¯æ•°
+SM_FMINFO_NUN_CONNECTION TCP 连接数
+SM_FMINFO_CAPTION 群集æˆå‘˜æœåŠ¡å™¨çŠ¶æ€
+SM_FC_STATUS_CAPTION 群集控制器连接状æ€
+SM_FC_IP 控制器的 IP 地å€
+SM_FC_PORT 控制器的 TCP/IP 端å£
+SM_FC_STATUS 连接状æ€
+SM_FC_ONLINE 在线
+SM_FC_OFFLINE 离线
+SM_FC_LAST_ERROR 最åŽå‘生的错误
+SM_FC_ERROR_TAG %s (错误代ç : %u)
+SM_FC_START_TIME 连接开始时间
+SM_FC_FIRST_TIME 第一个连接建立时间
+SM_FC_CURRENT_TIME 当å‰è¿žæŽ¥å»ºç«‹æ—¶é—´
+SM_FC_NUM_TRY å°è¯•è¿žæŽ¥æ•°
+SM_FC_NUM_CONNECTED æˆåŠŸè¿žæŽ¥æ•°
+SM_FC_NUM_FAILED 失败的连接数
+SM_FC_NOT_CONNECTED (未连接)
+SM_CHANGE_PASSWORD_1 您输入的密ç ä¸åŒ¹é…。请在“确认â€æ è¾“入与“密ç â€æ ç›¸åŒçš„密ç ã€‚
+SM_CHANGE_PASSWORD_2 您输入了一个空密ç ã€‚是å¦ç»§ç»­?
+SM_CHANGE_PASSWORD_3 密ç å·²æ›´æ”¹ã€‚
+SM_USER_COLUMN_1 用户å
+SM_USER_COLUMN_2 å…¨å
+SM_USER_COLUMN_3 所属组
+SM_USER_COLUMN_4 æè¿°
+SM_USER_COLUMN_5 认è¯æ–¹æ³•
+SM_USER_COLUMN_6 登录回数
+SM_USER_COLUMN_7 上次登录时间
+SM_AUTHTYPE_0 匿å身份验è¯
+SM_AUTHTYPE_1 密ç éªŒè¯
+SM_AUTHTYPE_2 特定è¯ä¹¦è®¤è¯
+SM_AUTHTYPE_3 ç­¾åè¯ä¹¦è®¤è¯
+SM_AUTHTYPE_4 RADIUS 身份验è¯
+SM_AUTHTYPE_5 NT 域认è¯
+SM_NO_GROUP ï¼
+SM_USER_DELETE_MSG 这将删除用户 "%s"。您是å¦ç¡®è®¤è¦è¿™æ ·åš?
+SM_EDIT_USER_CAPTION_1 创建新用户
+SM_EDIT_USER_CAPTION_2 用户 %S 属性
+SM_EDIT_USER_CERT_INFO 用户使用“特定è¯ä¹¦è®¤è¯â€å°†æ ¹æ®æ˜¯å¦ SSL 客户端è¯ä¹¦ä¸Žç”¨æˆ·äº‹å…ˆè®¾ç½®çš„è¯ä¹¦å®Œæ•´åŒ¹é…而被å…许或拒ç»è¿žæŽ¥ã€‚
+SM_EDIT_USER_POL_DLG 用户 %S 的安全策略
+SM_POLICY_DEF_CAPTION 安全策略
+SM_LIMIT_STR 指定一个在 %u 与 %u 之间的整数。
+SM_POLICY_INIT_TITLE 从左边的列表中选择一个策略项目。
+SM_USER_CREEATE_OK 用户 %S 已创建。
+SM_USERINFO_CAPTION 用户 "%S" çš„ä¿¡æ¯
+SM_USERINFO_NAME 用户å
+SM_USERINFO_GROUP 组å
+SM_USERINFO_CREATE 创建日期
+SM_USERINFO_UPDATE 更新日期
+SM_USERINFO_EXPIRE 有效期é™
+SM_USERINFO_NUMLOGIN 登录数
+SM_GROUPLIST_NAME 组å
+SM_GROUPLIST_REALNAME å…¨å
+SM_GROUPLIST_NOTE æè¿°
+SM_GROUPLIST_NUMUSERS 用户数
+SM_EDIT_GROUP_CAPTION_1 创建新组
+SM_EDIT_GROUP_CAPTION_2 组 %S 属性
+SM_GROUP_CREATED 组 %S 已创建。
+SM_GROUP_DELETE_MSG 您是å¦ç¡®å®šåˆ é™¤ç»„ "%S" ?
+SM_GROUP_POLICY_CAPTION 组 %S 的安全策略
+SM_GROUP_MEMBER_STR (仅显示属于组 %S 的用户)
+SM_SELECT_GROUP 选择(&S)
+SM_SELECT_NO_GROUP æ— (&N)
+SM_SELECT_ALT_GROUP 选择一个组(&G)...
+SM_ACCESS_COLUMN_0 ID
+SM_ACCESS_COLUMN_1 行为
+SM_ACCESS_COLUMN_2 状æ€
+SM_ACCESS_COLUMN_3 优先级
+SM_ACCESS_COLUMN_4 备注
+SM_ACCESS_COLUMN_5 目录
+SM_ACCESS_COLUMN_6 唯一 ID
+SM_ACCESS_PASS 通过
+SM_ACCESS_DISCARD èˆå¼ƒ
+SM_ACCESS_ENABLE 有效
+SM_ACCESS_DISABLE 无效
+SM_ACCESS_PROTO_1 所有 IPv4 / IPv6 åè®®
+SM_ACCESS_PROTO_2 6 (TCP/IP åè®®)
+SM_ACCESS_PROTO_3 17 (UDP/IP åè®®)
+SM_ACCESS_PROTO_4 1 (ICMPv4 åè®®)
+SM_ACCESS_PROTO_5 58 (ICMPv6 åè®®)
+SM_ACCESS_PROTO_6 指定 IP åè®®å·
+SM_SELECT_USER 选择(&S)
+SM_SELECT_NO ä¸è¦é€‰æ‹©(&N)
+SM_PLEASE_SELECT 选择用户。
+SM_LINK_COLUMN_1 连接设置å
+SM_LINK_COLUMN_2 状æ€
+SM_LINK_COLUMN_3 建立时间
+SM_LINK_COLUMN_4 目标 VPN Server
+SM_LINK_COLUMN_5 目标虚拟 HUB
+SM_LINK_STATUS_OFFLINE 离线 (å·²åœæ­¢)
+SM_LINK_STATUS_ERROR 错误 %u:%s
+SM_LINK_STATUS_ONLINE 在线 (已建立)
+SM_LINK_POLICY_GROUP 级è”连接设置
+SM_LINK_POLICY_CAPTION 安全策略设置适用于级è”会è¯
+SM_LINK_CONNECTING 连接处ç†ä¸­
+SM_LINK_SAVE_ONLINE 级è”连接设置 "%s" 被改å˜ï¼Œä½†å› ä¸ºçº§è”连接当å‰æ­£åœ¨çº¿ï¼Œæ­¤è®¾ç½®åœ¨ä¸‹æ¬¡è¿žæŽ¥å»ºç«‹å‰ä¸ä¼šç”Ÿæ•ˆã€‚
+SM_LINK_DELETE_MSG 是å¦ç¡®å®šåˆ é™¤çº§è”连接 "%s" ?
+SM_LINK_OFFLINE_MSG ç›®å‰çº§è” "%s" 是活跃的。是å¦è¦æ–­å¼€è¿žæŽ¥?
+SM_LINK_STATUS_CAPTION 级è”连接 "%s" 的连接状æ€
+SM_LOG_SWITCH_0 无切æ¢
+SM_LOG_SWITCH_1 æ¯ç§’切æ¢
+SM_LOG_SWITCH_2 æ¯åˆ†é’Ÿåˆ‡æ¢
+SM_LOG_SWITCH_3 æ¯å°æ—¶åˆ‡æ¢
+SM_LOG_SWITCH_4 æ¯å¤©åˆ‡æ¢
+SM_LOG_SWITCH_5 æ¯æœˆåˆ‡æ¢
+SM_SESS_DISCONNECT_MSG 是å¦ç¡®å®šæ–­å¼€ä¼šè¯ "%S" ?
+SM_SESS_COLUMN_1 会è¯å
+SM_SESS_COLUMN_2 ä½ç½®
+SM_SESS_COLUMN_3 用户å
+SM_SESS_COLUMN_4 æºä¸»æœºå称
+SM_SESS_COLUMN_5 TCP 连接
+SM_SESS_COLUMN_6 传输字节
+SM_SESS_COLUMN_7 传输数æ®åŒ…
+SM_SESS_COLUMN_8 VLAN ID
+SM_SESS_NORMAL 本地会è¯
+SM_SESS_LOCAL 本地会è¯
+SM_SESS_LOCAL_2 %S 上
+SM_SESS_REMOTE %S 上
+SM_SESS_LINK 级è”连接
+SM_SESS_LINK_HOSTNAME 虚拟主机
+SM_SESS_LINK_TCP æ— 
+SM_SESS_SNAT SecureNAT 会è¯
+SM_SESS_SNAT_HOSTNAME 虚拟主机
+SM_SESS_SNAT_TCP æ— 
+SM_SESS_BRIDGE 本地网桥会è¯
+SM_SESS_BRIDGE_HOSTNAME 以太网桥
+SM_SESS_LAYER3_HOSTNAME 虚拟 3 层交æ¢æœº
+SM_SESS_BRIDGE_TCP æ— 
+SM_SESS_STATUS_CAPTION "%S" VPN 会è¯çš„状æ€
+SM_SESS_STATUS_USERNAME 用户å (认è¯)
+SM_SESS_STATUS_REALUSER 用户å (æ•°æ®åº“)
+SM_SESS_STATUS_GROUPNAME 用户組å
+SM_CLIENT_IP æº IP 地å€
+SM_CLIENT_HOSTNAME æºä¸»æœºå称
+SM_NODE_CLIENT_NAME 客户端产å“å称
+SM_NODE_CLIENT_VER 客户端版本
+SM_NODE_CLIENT_BUILD 客户端内部标å·
+SM_NODE_SERVER_NAME æœåŠ¡ç«¯äº§å“å
+SM_NODE_SERVER_VER æœåŠ¡ç«¯ç‰ˆæœ¬
+SM_NODE_SERVER_BUILD æœåŠ¡ç«¯å†…部标å·
+SM_NODE_CLIENT_OS_NAME 客户端æ“作系统å称
+SM_NODE_CLIENT_OS_VER 客户端æ“作系统版本
+SM_NODE_CLIENT_OS_PID 客户端æ“作系统产å“ç¼–å·
+SM_NODE_CLIENT_HOST 客户端主机å
+SM_NODE_CLIENT_IP 客户端 IP 地å€
+SM_NODE_CLIENT_PORT 客户端端å£
+SM_NODE_SERVER_HOST æœåŠ¡å™¨ä¸»æœºå称
+SM_NODE_SERVER_IP æœåŠ¡å™¨ IP 地å€
+SM_NODE_SERVER_PORT æœåŠ¡å™¨ç«¯å£
+SM_NODE_PROXY_HOSTNAME 代ç†ä¸»æœºå称
+SM_NODE_PROXY_IP ä»£ç† IP 地å€
+SM_NODE_PROXY_PORT 代ç†ç«¯å£
+SM_MAC_COLUMN_1 会è¯å
+SM_MAC_COLUMN_2 MAC 地å€
+SM_MAC_COLUMN_3 创建时间
+SM_MAC_COLUMN_4 更新时间
+SM_MAC_COLUMN_5 ä½ç½®
+SM_MAC_COLUMN_1A VLAN ID
+SM_SESSION_FILTER \ (ä»…æ˜¾ç¤ºå±žäºŽä¼šè¯ %S 的项)
+SM_IP_COLUMN_1 会è¯å
+SM_IP_COLUMN_2 IP 地å€
+SM_IP_COLUMN_3 创建时间
+SM_IP_COLUMN_4 更新时间
+SM_IP_COLUMN_5 ä½ç½®
+SM_MAC_IP_DHCP %S (DHCP)
+SM_MACIP_LOCAL 在此æœåŠ¡å™¨ä¸Š
+SM_MACIP_SERVER %S 上
+SM_SNAT_STATUS SecureNAT è¿è¡ŒçŠ¶æ€
+SM_SNAT_NUM_SESSION %u 个会è¯
+SM_SNAT_NUM_CLIENT %u 个客户端
+SM_SNAT_IS_KERNEL å†…æ ¸æ¨¡å¼ NAT 功能是活跃的
+SM_BRIDGE_TOO_OLD_VER 当å‰è¿žæŽ¥çš„ VPN Server 版本ä¸æ”¯æŒæœ¬åœ°ç½‘桥功能。\r\n请更新到最新版本。
+SM_BRIDGE_UNSUPPORTED 当å‰è¿žæŽ¥çš„ VPN Server è¿è¡Œçš„æ“作系统无法使用本地网桥功能。请å‚阅 VPN Server 在线文档以获得支æŒæœ¬åœ°ç½‘桥功能的æ“作系统列表。
+SM_BRIDGE_WPCAP_REMOTE 为在此 VPN Server 上使用本地网桥功能,您必须安装 WinPcap 软件。WinPcap 软件当å‰æ²¡æœ‰åœ¨æœåŠ¡å™¨ä¸Šå®‰è£…。\r\n\r\nè¦è¿›è¡Œ WinPcap 软件的安装,您必须在è¿è¡Œ VPN Server çš„æœåŠ¡å™¨ä¸Šå¯åŠ¨ SoftEther VPN Server 管ç†å™¨ï¼Œç„¶åŽè¿žæŽ¥åˆ°æœ¬æœº (您自己计算机的ä½ç½®),打开本地网桥功能设置窗å£ã€‚\r\n首先退出此管ç†ä¼šè¯ï¼Œç„¶åŽåœ¨æ­¤æœåŠ¡å™¨ä¸Šå¯åŠ¨ SoftEther VPN Server 管ç†å™¨ä¹‹åŽï¼Œè¿žæŽ¥åˆ°æœ¬æœºå¹¶ç»§ç»­è®¾ç½®è¿›ç¨‹ã€‚
+SM_BRIDGE_WPCAP_ROOT 为在此 VPN Server 上使用本地网桥功能,您必须安装 WinPcap 软件。\r\n\r\nè‹¥è¦ç»§ç»­å®‰è£…,您必须以管ç†å‘˜èº«ä»½ç™»å½•åˆ°æ­¤è®¡ç®—机上。\r\n以管ç†å‘˜èº«ä»½ç™»é™†ï¼Œç„¶åŽå†æ¬¡å¯åŠ¨ SoftEther VPN Server 管ç†å™¨ã€‚
+SM_BRIDGE_WPCAP_INSTALL 为在此 VPN Server 上使用本地网桥功能,您必须安装 WinPcap 软件。WinPcap 软件当å‰æ²¡æœ‰åœ¨æœåŠ¡å™¨ä¸Šå®‰è£…。\r\n\r\nWinPcap 是一个与 VPN Server æ†ç»‘在一起的å…费软件。\r\n\r\n请问您是å¦å¼€å§‹å®‰è£… WinPcap ?
+SM_BRIDGE_WPCAP_REBOOT1 WinPcap 安装完æˆåŽï¼Œæ‚¨åœ¨ä½¿ç”¨æœ¬åœ°ç½‘桥功能之å‰å¿…é¡»é‡æ–°å¯åŠ¨è®¡ç®—机。\r\n\r\n在您手动é‡å¯è®¡ç®—机并å¯åŠ¨ VPN Server åŽï¼Œé…置本地网桥功能的设置。
+SM_BRIDGE_WPCAP_REBOOT2 WinPcap 安装完æˆåŽï¼Œæ‚¨åœ¨ä½¿ç”¨æœ¬åœ°ç½‘桥功能之å‰å¿…é¡»é‡æ–°å¯åŠ¨è®¡ç®—机。\r\n\r\né‡æ–°å¯åŠ¨ SoftEther VPN Server 会花费一点时间,但所有当å‰æ­£è¿žæŽ¥åˆ° VPN Server 的会è¯å°†è¢«åˆ‡æ–­\r\n此管ç†ä¼šè¯ä¹Ÿå°†è¢«åˆ‡æ–­ï¼Œæ‰€ä»¥æ‚¨å°†éœ€è¦é‡æ–°è¿žæŽ¥ã€‚\r\n\r\n您是å¦è¦é‡å¯ SoftEther VPN Server æœåŠ¡?
+SM_BRIDGE_RESOURCE 无法加载 WinPcap 的驱动程åºã€‚
+SM_BRIDGE_COLUMN_1 ç¼–å·
+SM_BRIDGE_COLUMN_2 虚拟 HUB å称
+SM_BRIDGE_COLUMN_3 网络适é…器或 tap 设备å称
+SM_BRIDGE_COLUMN_4 状æ€
+SM_BRIDGE_OFFLINE 离线
+SM_BRIDGE_ONLINE è¿è¡Œä¸­
+SM_BRIDGE_ERROR 错误
+SM_BRIDGE_OK 已添加本地网桥连接定义。
+SM_BRIDGE_DELETE 您确定è¦ä»Žè™šæ‹Ÿ HUB "%s" 到设备 "%s" 中删除本地网桥å—?
+SM_BRIDGE_DELETE_OK 本地桥被删除。
+SM_BRIDGE_INTEL 当一个网桥到物ç†ç½‘络适é…器的新的网桥连接建立时,在æŸäº›æƒ…况下 (å–决于网络适é…器类型),å¯èƒ½æ— æ³•åœ¨è™šæ‹Ÿç½‘络上通过网络适é…器的网桥连接进行 TCP/IP 通信。\r\n(è¿™ç§çŽ°è±¡è¢«ç¡®è®¤å‘生在 Intel å’Œ Broadcom 网络适é…器上。)\r\n\r\n\r\n如果é‡åˆ°è¿™ä¸ªé—®é¢˜ï¼Œå¯ä»¥é€šè¿‡é‡å¯ VPN Server / Bridge è¿è¡Œçš„计算机æ¥è¡¥æ•‘。通常情况下通信在计算机é‡å¯åŽå¯ä»¥æ­£å¸¸è¿›è¡Œã€‚\r\n\r\n\r\n此外,很多无线网络适é…器在混æ‚模å¼ä¸‹ä¸ä¼šå“应范æ¾æ•°æ®åŒ…请求,而导致无法使用本地网桥。如果å‘生这ç§æƒ…况,请å°è¯•ä½¿ç”¨å¸¸è§„有线网络适é…器æ¥ä»£æ›¿æ— çº¿ç½‘络适é…器。
+SM_BRIDGE_VPN ä½ è¦è¿žæŽ¥åˆ°æœ¬åœ°ç½‘æ¡¥ "%S"。\r\n\r\n通常情况下,网桥被建立在虚拟 HUB 与特ç†ç½‘å¡ä¹‹é—´ã€‚建立一个到虚拟网络适é…器的本地桥是ä¸å¸¸è§çš„。\r\n请确ä¿è¿™æ˜¯ä½ çš„æ„图。\r\n\r\n你真的è¦ç»§ç»­å—?
+SM_BRIDGE_INFO_1 为网桥目标选择以太网设备 (网络适é…器)
+SM_BRIDGE_INFO_2 输入新创建的 tap 设备的å称
+SM_CONFIG_SAVED é…置文件被ä¿å­˜ã€‚
+SM_CONFIG_SAVE_FAILED 无法ä¿å­˜é…置文件。
+SM_CONFIG_OPEN_FAILED 无法打开指定的文件。
+SM_CONFIG_CONFIRM 这将在 VPN Server 应用指定的é…置文件。VPN Server 将自动é‡å¯å¹¶å°†è£…载新的é…置文件。当å‰è¿žæŽ¥åˆ°æ­¤ VPN Server 上的用户连接将被中断。此管ç†ä¼šè¯ä¹Ÿå°†è¢«åˆ‡æ–­ï¼Œæ‚¨å°†éœ€è¦é‡æ–°è¿žæŽ¥åˆ°æœåŠ¡å™¨ã€‚\r\n\r\n您è¦ç»§ç»­å—?
+SM_CONFIG_WRITE_OK 在æœåŠ¡ç«¯çš„é…置文件被覆盖。
+SM_AO_COLUMN_1 项目
+SM_AO_COLUMN_2 值
+SM_TRUE_OR_FALSE 此项目设置为 0 (false) 或 1 (true)。
+SM_AO_SET_OK 虚拟 HUB 管ç†å‘˜é€‰é¡¹å·²è®¾å®šã€‚
+SM_EXT_OPTION_SET_OK 虚拟 HUB 扩展选项已设定。
+SM_PASSWORD_MSG ç›®å‰æ­¤ VPN Server 没有设定管ç†å‘˜å¯†ç ã€‚建议设定密ç ã€‚\r\n\r\n您是å¦è¦è®¾å®šä¸€ä¸ªæœåŠ¡ç«¯ç®¡ç†å‘˜å¯†ç ?
+SM_L3_SW_COLUMN1 虚拟 3 层交æ¢æœºå称
+SM_L3_SW_COLUMN2 è¿è¡ŒçŠ¶æ€
+SM_L3_SW_COLUMN3 接å£æ•°
+SM_L3_SW_COLUMN4 路由表数
+SM_L3_SW_ST_F_F åœæ­¢
+SM_L3_SW_ST_T_F å¯åŠ¨ (错误)
+SM_L3_SW_ST_T_T 开始 (è¿è¡Œ)
+SM_L3_SW_DEL_MSG 是å¦ç¡®å®šåˆ é™¤è™šæ‹Ÿ 3 层交æ¢æœº "%S" ?
+SM_L3_SW_IF_COLUMN1 IP 地å€
+SM_L3_SW_IF_COLUMN2 å­ç½‘掩ç 
+SM_L3_SW_IF_COLUMN3 虚拟 HUB å称
+SM_L3_SW_TABLE_COLUMN1 网络地å€
+SM_L3_SW_TABLE_COLUMN2 å­ç½‘掩ç 
+SM_L3_SW_TABLE_COLUMN3 网关地å€
+SM_L3_SW_TABLE_COLUMN4 公制
+SM_SECURE_NAT_MSG 您是å¦ç¡®å®šå¯ç”¨ SecureNAT ?\r\n\r\n如果您å¯ç”¨ SecureNAT,带虚拟NAT功能的虚拟路由器将被创建,在虚拟 HUB 中有一个 IP 地å€ã€‚此虚拟路由器将互相影å“,作为一å°è®¡ç®—机或多å°è¿žæŽ¥åˆ°è™šæ‹Ÿç½‘络的计算机组æˆçš„路由器。\r\n\r\n在虚拟NAT中的 SecureNAT å¯ç”¨ä»»ä½•è®¡ç®—机连接到虚拟 HUB,通过 SecureNAT 建立与外部网络的通信。\r\n因此,当 SecureNAT è¿è¡Œåœ¨æ­¤ VPN Server 时,无需使用本地客户端连接这å°è®¡ç®—机的虚拟 HUB。\r\n\r\n\r\n此外,请注æ„如果在从虚拟 HUB 二层网段å¯ä»¥åˆ°è¾¾çš„一个地点,已有一个 DHCP æœåŠ¡å™¨ï¼Œå•å‡»â€œSecureNAT é…ç½®â€ç¦ç”¨ DHCP æœåŠ¡å™¨åŠŸèƒ½ï¼Œå¦åˆ™å°†æœ‰ DHCP 冲çªã€‚\r\n\r\n而且,您å¯ä»¥ç¦ç”¨ NAT 功能,åªä½¿ç”¨ DHCP æœåŠ¡å™¨ï¼Œå¦‚果你想的è¯ã€‚
+SM_CRL_COLUMN_1 è¯ä¹¦æ‘˜è¦
+SM_CRL_DELETE_MSG 这将删除选定的项目。你想这样�
+SM_CRL_EMPTY_MSG 没有项目被选择。\r\n如果您在è¯ä¹¦åŠé”€é¡¹ç›®ä¸­è¿›è¡Œè¿½åŠ ï¼Œæ‰€æœ‰è¯ä¹¦å°†è¢«åˆ¤æ–­ä¸ºéžæ³•ï¼Œä¸”所有è¯ä¹¦è®¤è¯æ¨¡å¼ä¸‹çš„客户端连接将被拒ç»ã€‚\r\n\r\n您是å¦ç¡®è®¤?
+SM_AC_COLUMN_1 ID
+SM_AC_COLUMN_2 优先级
+SM_AC_COLUMN_3 行为
+SM_AC_COLUMN_4 目录
+SM_AC_PASS å…许
+SM_AC_DENY æ‹’ç»
+SM_LOG_FILE_COLUMN_1 日志文件的å称
+SM_LOG_FILE_COLUMN_2 文件大å°
+SM_LOG_FILE_COLUMN_3 更新日期
+SM_LOG_FILE_COLUMN_4 ä½ç½®
+SM_READ_LOG_FILE_INFO_1 请等待,直到处ç†å®Œæ¯•...
+SM_READ_LOG_FILE_INFO_2 %S 处ç†ä¸­ï¼Œ%S 已完æˆ
+SM_READ_LOG_FILE_ERROR 文件没有æˆåŠŸä¸‹è½½ã€‚
+SM_READ_SAVE_DLG_TITLE 指定日志文件的ä¿å­˜ç›®æ ‡æ–‡ä»¶å
+SM_READ_SAVE_DLG_FILTER 日志文件 (*.log)|*.log|所有文件(*.*)|*.*
+SM_READ_SAVE_FAILED 无法ä¿å­˜æ—¥å¿—文件。
+SM_READ_SAVE_TMP_FAILED 无法写入临时文件 "%S"。
+SM_READ_SAVE_OPEN_ERROR 无法打开临时文件 "%S"。 \r\n\r\nå¯èƒ½ .LOG 文件扩展å是ä¸æ˜¯åœ¨ Windows 分é…的文件类型。
+SM_LICENSE_COLUMN_1 ç¼–å·
+SM_LICENSE_COLUMN_2 许å¯è¯å¯†é’¥
+SM_LICENSE_COLUMN_3 许å¯è¯ç±»åž‹å
+SM_LICENSE_COLUMN_4 状æ€
+SM_LICENSE_COLUMN_5 有效期
+SM_LICENSE_COLUMN_6 许å¯è¯ç¼–å·
+SM_LICENSE_COLUMN_7 许å¯è¯ç±»åž‹ ID
+SM_LICENSE_COLUMN_8 æœåŠ¡å™¨ ID
+SM_LICENSE_COLUMN_9 åºåˆ—å·
+SM_LICENSE_INFINITE æ— é™
+SM_LICENSE_NO_EXPIRES 没有到期
+SM_LICENSE_STATUS_EDITION 产å“版本
+SM_LICENSE_STATUS_RELEASE VPN Server çš„å‘布日期
+SM_LICENSE_STATUS_SYSTEM_ID 当å‰æœåŠ¡ç«¯ ID
+SM_LICENSE_STATUS_EXPIRES ç›®å‰äº§å“许å¯çš„有效期
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã‹ã‚‰ -----
+SM_LICENSE_STATUS_SUBSCRIPTION 认购åˆåŒçš„状æ€
+SM_LICENSE_STATUS_SUBSCRIPTION_NONEED 无需认购 (在这个版本ä¸éœ€è¦è®¤è´­å¯†é’¥)
+SM_LICENSE_STATUS_SUBSCRIPTION_NONE 无密钥(需è¦æ·»åŠ è®¤è´­å¯†é’¥)
+SM_LICENSE_STATUS_SUBSCRIPTION_VALID 在认购期内 [直至 %s]
+SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED 认购已过期 [在%s]
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD 版本å…许当å‰åˆåŒ
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR å…è´¹å‡çº§åˆ° %s 以å‰å‘布的所有将æ¥ç‰ˆæœ¬ã€‚
+SM_LICENSE_STATUS_ENTERPRISE ä¼ä¸šåŠŸèƒ½çš„å¯ç”¨æ€§
+SM_LICENSE_STATUS_ENTERPRISE_YES 是 (å¯ç”¨çš„)
+SM_LICENSE_STATUS_ENTERPRISE_NO å¦ (ä¸å¯ç”¨)
+SM_LICENSE_NUM_USER å…许用户对象创建
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã¾ã§ -----
+SM_LICENSE_NUM_CLIENT å…许并å‘客户端
+SM_LICENSE_NUM_BRIDGE å…è®¸å¹¶å‘ Bridge
+SM_NO_LICENSE_COLUMN 注æ„:
+SM_NO_LICENSE 因为没有产å“许å¯è¯æ³¨å†Œï¼Œæ­¤ VPN Server 通信功能无法è¿è¡Œã€‚
+SM_LICENSE_DELETE_MSG 你确定è¦ä»Ž VPN Server 删除选定的许å¯è¯å—?
+SM_SYSLOG_0 ç¦ç”¨ç³»ç»Ÿæ—¥å¿—å‘é€åŠŸèƒ½
+SM_SYSLOG_1 ç»ç”± Syslog å‘é€æœåŠ¡å™¨ç«¯æ—¥å¿—
+SM_SYSLOG_2 ç»ç”± Syslog å‘é€æœåŠ¡å™¨ç«¯å’Œè™šæ‹Ÿ HUB 安全日志
+SM_SYSLOG_3 ç»ç”± Syslog å‘é€æœåŠ¡å™¨ç«¯ï¼Œè™šæ‹Ÿ HUB 安全和数æ®åŒ…日志
+SM_SETUP_INFO_1 点击“下一步â€å¼€å§‹å®‰è£…。如果你想通出安装并手动é…置所有设置,请å•å‡»â€œå…³é—­â€œâ€ã€‚
+SM_SETUP_INFO_2 å•å‡»â€œå…³é—­â€œï¼Œé€šè¿‡ä½ è‡ªå·±æ‰‹åŠ¨é…ç½® VPN Server 的设置。
+SM_SETUP_BRIDGE_ONLY 您当å‰è¿žæŽ¥åˆ° VPN Bridge ,您åªèƒ½ä¸ºâ€œå¤šç‚¹ VPN â€åœ¨æ¯ä¸ªç«™ç‚¹åˆ›å»º VPN Bridge。
+SM_SETUP_BRIDGE_EDGE æ¯ä¸ªç«™ç‚¹çš„ VPN Bridge(&E)
+SM_SETUP_WARNING å½“å‰ VPN Server 或 VPN Bridge 的设置将被åˆå§‹åŒ–。\r\n您是å¦ç¡®å®š?
+SM_SETUP_SELECT 选择以太网设备建立桥接
+SM_SETUP_NO_LICENSE_KEY ç›®å‰æ­¤ SoftEther VPN Server 上没有注册任何一个许å¯è¯ã€‚\r\n\r\n如果è¦ä½œä¸º VPN Server è¿è¡Œ SoftEther VPN Server,您必须输入一个许å¯è¯å¯†é’¥ã€‚\r\n您是å¦è¦æ‰“开许å¯è¯ç®¡ç†å™¨çª—å£? ?\r\n\r\n(作为试用版使用 VPN Server ,您必须从 SoftEther VPN Project 的网站获å–试用密钥。\r\n点击“是â€å¹¶ç‚¹å‡»èŽ·å–或延长许å¯è¯æŒ‰é’®èŽ·å–一个试用密钥。
+
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã‹ã‚‰ -----
+SM_HUBEXT_OPTION_TITLE 虚拟 HUB 扩展选项
+SM_HUBEXT_OPTION_STATIC1 虚拟 HUB 扩展选项å…许您é…置这个虚拟 HUB 的详细å‚数。
+SM_HUBEXT_OPTION_STATIC2 标准,VPN Server 全部管ç†è€…åŠï¼Œè™šæ‹Ÿ HUB 管ç†è€…çš„åŒæ–¹éƒ½ï¼Œèƒ½ç¼–辑虚拟 HUB 高级选项。但,如果虚拟 HUB 管ç†é€‰æ‹©çš„ deny_hub_admin_change_ext_option 被 1 设定,虚拟 HUB 的管ç†è€…,ä¸èƒ½ç¼–辑虚拟 HUB 高级选项。默认情况下, VPN Server çš„å…¨çƒç®¡ç†å‘˜å’Œä¸ªäººè™šæ‹Ÿ HUB 的管ç†å‘˜éƒ½å¯ä»¥ä¿®æ”¹è™šæ‹Ÿ HUB 的扩展选项。\n但是,如果在虚拟 HUB 管ç†é€‰é¡¹çš„ deny_hub_admin_change_ext_option 被设置为 1,个人虚拟 HUB 的管ç†å‘˜å°±ä¸èƒ½ä¿®æ”¹è™šæ‹Ÿ HUB 的扩展选项。(åªèƒ½æŸ¥çœ‹ã€‚)
+SM_VLAN_COLUMN_0 网络适é…器å称
+SM_VLAN_COLUMN_1 驱动程åºç§ç±»
+SM_VLAN_COLUMN_2 驱动程åºæ–‡ä»¶å
+SM_VLAN_COLUMN_3 VLAN é€æ˜Žè®¾ç½®
+SM_VLAN_COLUMN_4 å…¨çƒå”¯ä¸€æ ‡è¯†ç¬¦(GUID)
+SM_VLAN_COLUMN_5 设备实例 ID
+SM_VLAN_YES å¯ç”¨
+SM_VLAN_NO 未å¯ç”¨
+SM_VLAN_MSG_1 Windows 注册表é…ç½®å…许网络适é…器“%Sâ€å‘é€/接收带标签的 VLAN æ•°æ®åŒ…。\r\n\r\n然而,有些网络适é…器,需è¦é¢å¤–的设置,在本地计算机的 Windows“设备管ç†å™¨â€çš„属性里设置å‚æ•°æ¥å¯ç”¨å·¨åž‹å¸§(大于 1,512 字节的以太网帧)。如果你未å¯ç”¨å·¨åž‹å¸§ï¼Œä¸€äº›å¤§åž‹ VLAN æ•°æ®åŒ…将被æ¼æŽ‰ã€‚在大型 VLAN æ•°æ®åŒ…总是消失的情况下,请å¯ç”¨å·¨åž‹å¸§ã€‚(例如,设置最大容é‡ä¸º 4088 字节)。Windows 设备管ç†å™¨å°†å¸®æ‚¨é…置。\r\n\r\næ­¤ VLAN çš„é€æ˜Žè®¾ç½®å·²è¢«å†™å…¥åˆ° Windows 注册表中,但是ä¸èƒ½ä¿è¯ VLAN æ•°æ®åŒ…å¯ä»¥è¢«æœ‰æ•ˆåœ°ä¼ é€ã€‚\r\n如果 VLAN 标记的数æ®åŒ…在此é…ç½®åŽä¼ è¾“失败,请å‚阅网络适é…器“%Sâ€çš„手册进行手动的ã€å……分的é…置。此外,“%Sâ€å¯èƒ½ä¸æ”¯æŒ VLAN é€æ˜Žè®¾ç½®ã€‚在这ç§æƒ…况下,这样的网络适é…器ä¸èƒ½è¢«ç”¨æ¥ä¼ è¾“ VLAN 帧。使用其他产å“。\r\n\r\nè¦åº”用此设置,è¿è¡Œ VPN Server çš„ Windows å¿…é¡»é‡æ–°å¯åŠ¨ã€‚ä¸è¦å¿˜äº†é‡æ–°å¯åŠ¨å®ƒã€‚
+
+SM_VLAN_MSG_2 在网络适é…器“%Sâ€ä¸Šå¯ç”¨äº† VLAN é€æ˜ŽåŠŸèƒ½çš„ Windows 注册表å‚数已从注册表中删除。\r\n\r\n如果你上次åšè¿‡å·¨åž‹å¸§å¯ç”¨è®¾ç½®ï¼Œæ‰‹åŠ¨æ’¤æ¶ˆè¿™ä¸ªå˜åŒ–。\r\n\r\nè¦åº”用此设置,è¿è¡Œ VPN Server çš„ Windows å¿…é¡»é‡æ–°å¯åŠ¨ã€‚ä¸è¦å¿˜äº†é‡æ–°å¯åŠ¨å®ƒã€‚
+
+SM_VLAN_NOTHING æ”¯æŒ VLAN é€æ˜Žè®¾ç½®å·¥å…·çš„电脑上“%Sâ€æ²¡æœ‰ç½‘络适é…器。\r\n\r\n但是,æŸäº›ç½‘络适é…器在默认情况下能够å‘é€ VLAN 标记的数æ®åŒ…,或通过由供应商æ供的特定é…置实用程åºè¢«é…置为执行 VLAN 标记的数æ®åŒ…。\r\通过使用这样的网络适é…器,你必须自己手动é…置这些设置。
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã¾ã§ -----
+SM_SERVER_ADMIN_MSG VPN Server / Bridge "%S"
+SM_ETHERIP_COLUMN_0 ISAKMP Phase 1 ID
+SM_ETHERIP_COLUMN_1 虚拟 HUB å
+SM_ETHERIP_COLUMN_2 用户å
+SM_ETHERIP_ADD_OK 一个新的 EtherIP / L2TPv3 客户端设置已注册。
+SM_IPSEC_SETUP_QUESTION æ­¤ VPN Server 已具有支æŒå…¼å®¹ IPsec / L2TP / EtherIP / L2TPv3 å议的 VPN Client 或 VPN 路由器的新功能。 \r\n\r\n您å¯ä»¥å…许 VPN Server 接å—从智能手机,如 iPhone,iPad,Android,或在 Mac OS X 或 Windows 上的标准 VPN Client 的连接。\r\n\r\n您è¦è®¾ç½® IPsec å—?\r\n(您还å¯ä»¥åœ¨ä»¥åŽä»»ä½•æ—¶é—´é€šè¿‡å•å‡»â€œIPSEC / L2TP设置â€æŒ‰é’®æ¥é…ç½® IPsec 设置。)
+SM_OPENVPN_CONFIG_SAVE_OK åŒ…å« OpenVPN 设置文件的 ZIP 文件“%sâ€ã€‚\r\n\r\n打开 ZIP 文件æå– OpenVPN 的样本é…置文件,å¯ä»¥ç«‹å³è½»æ¾åœ°ä½¿ç”¨ã€‚\r\n您å¯èƒ½éœ€è¦ä¿®æ”¹ä¸€ç‚¹é…置文件。\r\n\r\n对于详细信æ¯ï¼Œè¯·é˜…读 ZIP 文件中的'readme.txt'文件。\r\n\r\n您现在想è¦æ‰“开这个 ZIP 文件å—?
+SM_OPENVPN_CONFIG_SAVE_NG 无法ä¿å­˜ ZIP 文件'%s'。
+SM_OPENVPN_CONFIG_OPEN_NG 无法打开 ZIP 文件'%s'。请手动打开此文件。
+SM_DDNS_IPV4_ERROR 无法通过 IPv4 到达 DDNS æœåŠ¡å™¨ã€‚
+SM_DDNS_IPV6_ERROR 无法通过 IPv6 到达 DDNS æœåŠ¡å™¨ã€‚
+SM_DDNS_FQDN_EMPTY (æ— )
+SM_DDNS_OK_MSG åŠ¨æ€ DNS 主机å:%S%S\r\n\r\n您å¯ä»¥é€šè¿‡æŒ‡å®šä»¥ä¸Š DNS 主机å访问下é¢çš„ IP 地å€ã€‚\r\n\r\nIPv4 地å€ï¼š%s \r\nIPv6 地å€ï¼š%s\r\n\r\n您也å¯ä»¥æŒ‡å®šä¸‹åˆ—主机å的特殊形å¼æ¥æŒ‡å®š IPv4 或 IPv6 作为明确地å€ç±»åž‹ã€‚\r\n\r\n针对 IPv4 的主机å%S.v4%S \r\n针对 IPv6 的主机å:%S.v6%S。
+SM_DDNS_OK_TITLE åŠ¨æ€ DNS 功能
+SM_DDNS_OK_MSG2 åŠ¨æ€ DNS 主机å被更改为'%S'。\r\n\r\nå•å‡»æ示读å–更多的信æ¯ã€‚
+SM_IPSEC_PSK_TOO_LONG 预共享密钥(PSK)有 10 个或更多的字æ¯ã€‚\r\n\r\næ®æŠ¥é“谷歌安å“的几个版本有一个 10 个或更多字æ¯ä½œä¸ºé¢„共享密钥的严é‡æ•…障。\r\nå› æ­¤ 9 个或少于 9 个字æ¯è¢«æŽ¨è作为预共享密钥。\r\n\r\n您è¦ä¿®æ”¹é¢„共享密钥å—?
+SM_ADVANCED_REDIRECT_URL_HINT_TITLE 如何使用高级 HTTP é‡å®šå‘功能
+SM_ADVANCED_REDIRECT_URL_HINT 高级 HTTP é‡å®šå‘(为专家)\r\n\r\n此字符串“<INFO>â€æ˜¯ä¸€ä¸ªå ä½ç¬¦ã€‚它å¯ä»¥åµŒå…¥é‡å®šå‘çš„ URL 中。\r\n\r\n嵌入 URL 示例:\r\nhttp://www.google.com/search?q=<INFO>|secret\r\n\r\n当客户端将被é‡å®šå‘,é‡å®šå‘的实际 URL 目的地将被å–代如下。\r\n\r\n用户å|会è¯ID|IP 地å€|日期和时间|哈希值\r\n\r\n替æ¢åŽç¤ºä¾‹ï¼šzurukko|SID-ZURUKKO-123|219.117.219.154|20131117100354|99707160AFE7A454042B2C47B064112D652452D7\r\n\r\nå„字段的详情æ述如下。\r\n\r\n用户åï¼šå½“å‰ VPN 会è¯çš„用户å将被放置。\r\n\r\n会è¯ID:VPN 会è¯çš„ä¼šè¯ ID 将被放置\r\n\r\n日期和时间:14 ä½æ•°å­—将以'YYYYMMDDHHMMSS’格å¼æ”¾ç½®(时区是 UTC)\r\n\r\n哈希值:代表 20 个字节二进制数æ®çš„一个 40 字符的å六进制字符串。二进制数æ®æ˜¯ SHA-1 哈希函数至临时字符串的结果。在é‡å®šå‘ URL 中“|â€ç¬¦å·åŽï¼Œä¸´æ—¶å­—符串是上述字段的ä½é˜µåˆ—加上秘密字符串的结åˆã€‚(在上é¢çš„例å­ä¸­ï¼Œâ€œç§˜å¯†â€æ˜¯ç§˜å¯†å­—符串)。如果在 URL 中没有“|â€ç¬¦å·ï¼Œæ²¡æœ‰å“ˆå¸Œå€¼å°†è¢«æ·»åŠ ã€‚\r\n\r\n哈希值的目的:秘密字符串如密钥般有效。感谢密钥。在é‡å®šå‘ URL 中接收é‡å®šå‘查询字符串的 CGI 程åºï¼Œå¯ä»¥éªŒè¯åŒ…å«åœ¨ URL 中å‚数的完整性。\r\n
+SM_ADVANCED_REDIRECT_URL_MSG URL 必须以“http://â€æˆ–“https://â€å¼€å§‹
+SM_DISABLE_DDNS_HINT_CAPTION ç¦ç”¨åŠ¨æ€ DNS 功能
+SM_DISABLE_DDNS_HINT ç¦ç”¨åŠ¨æ€ DNS 功能,修改 VPN Server çš„é…置文件。\r\n\r\n此“declare rootâ€æŒ‡ä»¤å…·æœ‰â€œdeclare DDnsClientâ€çš„指令。在该指令中,你å¯ä»¥åˆ‡æ¢â€œbool Disableâ€ä»Žå‡åˆ° true,并é‡æ–°å¯åŠ¨ VPN Server ,然åŽåŠ¨æ€ DNS 功能将被ç¦ç”¨ã€‚\r\n
+SM_REGENERATE_CERT_MSG VPN Server çš„è¯ä¹¦è¢«æ›¿æ¢ä¸ºæ–°çš„。\r\n\r\n这会影å“到被é…ç½®éªŒè¯ VPN Server è¯ä¹¦çš„所有 VPN Client。\r\n您è¦ç»§ç»­å—?
+SM_DDNS_SERVER_CERT_MSG DDNS 主机å更改为“%Sâ€ã€‚\r\n\r\n如果您计划使用 Microsoft SSTP VPN 连接到 VPN Server ,从 Windows Vista 或 Windows 更高版本指定 DDNS 主机å为 VPN Server 的目标,由于安全原因, VPN Server 的目标主机å必须与 VPN Server è¯ä¹¦çš„ CN(Common Name)字段完全匹é…。\r\n\r\n您è¦é‡æ–°ç”Ÿæˆçš„æœåŠ¡å™¨è¯ä¹¦ï¼Œä»¥åŒ¹é… CN 值到“%Sâ€å—?\r\n(å•å‡»â€œå¦â€ç»§ç»­ä½¿ç”¨å½“å‰çš„æœåŠ¡å™¨è¯ä¹¦)。
+SM_DDNS_SERVER_CERT_OK VPN Server çš„ SSL è¯ä¹¦çŽ°åœ¨å·²å†æ¬¡ç”Ÿæˆã€‚\r\n\r\n当你让Microsoft SSTP VPN Client 连接到 VPN Server 时,你应该指定当å‰çš„ DDNS 主机å“%Sâ€ä½œä¸ºç›®æ ‡æœåŠ¡å™¨çš„主机å。\r\n你也必须事先在 Windows 的“å—信任的根è¯ä¹¦â€åˆ—表中添加这个 VPN Server çš„è¯ä¹¦ã€‚\r\n(è¦å®‰è£…æ ¹è¯ä¹¦åˆ° Windows 中,在“è¯ä¹¦â€œçš„å°ç¨‹åºé‡Œæ‰“å¼€ MMC,并导航到“本地计算机â€ã€‚之åŽï¼Œä½ å¯ä»¥å¯¼å…¥è¯ä¹¦åˆ°çš„å—信任的根è¯ä¹¦åˆ—表。\r\详细说明请å‚考 Microsoft 的文档。)\r\n\á¹›\n您è¦ä»¥ X.509 æ ¼å¼ä¿å­˜æ–°çš„ SSL è¯ä¹¦ä½œä¸ºä¸€ä¸ªæ–‡ä»¶å—?
+SM_SETUP_STEP_SECURENAT æ­¤ VPN Server / Bridge å¯èƒ½ä»¥ç”¨æˆ·æ¨¡å¼æˆ–å—其他é™åˆ¶æ­£åœ¨è¿è¡Œï¼Œè™šæ‹Ÿ HUB 和物ç†ç½‘络适é…器ä¸èƒ½æ¡¥æŽ¥åœ¨ä¸€èµ·ã€‚相å,SecureNAT 功能å…许 VPN Client 与物ç†ç½‘络中的其他计算机进行通信。在SecureNAT功能是默认å¯ç”¨çš„。您å¯ä»¥é…置或ç¦ç”¨å®ƒã€‚
+SM_SETUP_STEP_SECURENAT_TITLE 第3步。网桥虚拟 HUB 和物ç†ç½‘络
+SM_UPDATE_CHECK_TITLE_VPNSERVER %S VPN Server (在主机'%S'上)
+SM_UPDATE_CHECK_TITLE_VPNBRIDGE %S VPN Bridge (在主机'%S'上)
+SM_FACTORY_DEFAULT_WARNING 这将在 VPN Server / Bridge 上执行出厂å¤ä½è®¾ç½®ã€‚\r\nå½“å‰ VPN Server / Bridge é…置将被清除,将立å³åº”用åˆå§‹è®¾ç½®ã€‚\r\n在åšå‡ºåŽ‚å¤ä½è®¾ç½®å‰ï¼Œå»ºè®®æ‚¨å¤‡ä»½å½“å‰é…置。\r\n\r\n按 OK 执行出厂å¤ä½è®¾ç½®ã€‚ VPN Server / Bridge å°†é‡æ–°å¯åŠ¨ã€‚当å‰çš„管ç†è¿žæŽ¥å°†è¢«æ–­å¼€ï¼Œæ‰€ä»¥è¯·é‡æ–°è¿žæŽ¥åˆ° VPN Server / Bridge。\r\n\r\n按“å–消â€å–消æ“作。
+SM_FACTORY_DEFAULT_PERFORMED 在æœåŠ¡å™¨ä¸Šæ­£åœ¨æ‰§è¡Œå‡ºåŽ‚å¤ä½æ“作。\r\n\r\n按“确定â€é€€å‡ºå½“å‰ VPN Server 管ç†å™¨çš„会è¯â€œã€‚\r\n退出åŽï¼Œè¯·é‡æ–°å¯åŠ¨ VPN Server 管ç†å™¨å¹¶å†æ¬¡è¿žæŽ¥åˆ° VPN Server。\r\n然åŽä½ ä¼šçœ‹åˆ° VPN Server å¤ä½ã€‚
+SM_AZURE_STATUS_CONNECTED 状æ€: 已连接
+SM_AZURE_STATUS_NOT_CONNECTED 状æ€: 没有连接
+SM_NO_BRIDGE_NICS 无物ç†ç½‘络适é…器ã€é€‚åˆæœ¬åœ°æ¡¥åœ¨ VPN æœåŠ¡å™¨è®¡ç®—机上被å‘现。\r\n为了创建一个本地桥,你必须在计算机上至少安装一个物ç†ç½‘络适é…器。\r\n您ä¸èƒ½ä¸ºæœ¬åœ°æ¡¥ä½¿ç”¨ Wi-Fi 适é…器或 3G 适é…器。\r\n请安装一个兼容有线以太网的物ç†ç½‘络适é…器。\r\n\r\n如果最近安装的网络适é…器没有出现,é‡æ–°å¯åŠ¨è®¡ç®—机。\r\n\r\n如果本地桥无论如何ä¸èƒ½ä½¿ç”¨ï¼Œä½ å¯ä»¥ä½¿ç”¨â€œSecureNAT 功能â€ä»£æ›¿ã€‚\r\n\r\n如果你有一定的原因使用ä¸åŒå¯»å¸¸çš„网络适é…å™¨ï¼ˆå³ Wi-Fi 网络连接适é…器,3G 适é…器或虚拟适é…器),设置“ShowAllInterfacesâ€å˜é‡åœ¨â€œLocalBridgeListâ€æŒ‡ä»¤ä¸ºâ€œtrueâ€ï¼Œç„¶åŽé‡å¯VPNæœåŠ¡å™¨ã€‚然åŽï¼Œè¿™äº›è®¾å¤‡å°†å‡ºçŽ°åœ¨åå•ä¸Šã€‚(仅é™äºŽé«˜çº§ Windows 用户)。
+
+#关于 User-mode 路由器管ç†å·¥å…·
+NM_TITLE 删除
+NM_CONNECT_TITLE 删除
+NM_STATUS_TAG 连接状æ€: %s
+NM_OFFLINE 您没有连接到任何 VPN Server
+NM_CONNECTING VPN Server 连接中
+NM_CONNECTED 已连接到 VPN Server "%S"
+NM_CONNECT_ERROR é”™è¯¯å· %u (%s)
+NM_ACCOUNT_TITLE 删除
+NM_STATUS 用户模å¼è·¯ç”±å™¨çŠ¶æ€
+NM_STATUS_CONNECT 连接状æ€
+NM_STATUS_TCP NAT TCP/IP 会è¯æ•°
+NM_STATUS_UDP NAT UDP/IP 会è¯æ•°
+NM_STATUS_ICMP NAT ICMP 会è¯æ•°
+NM_STATUS_DNS NAT DNS 会è¯æ•°
+NM_STATUS_DHCP 已分é…çš„ DHCP 客户端
+NM_INFO 用户模å¼è·¯ç”±å™¨ä¿¡æ¯
+NM_INFO_PRODUCT_NAME 产å“å称
+NM_INFO_VERSION_STR 版本信æ¯
+NM_INFO_BUILD_INFO 构建信æ¯
+NM_INFO_HOSTNAME 主机å
+NM_NAT_ID ID
+NM_NAT_PROTOCOL åè®®
+NM_NAT_SRC_HOST æºä¸»æœº
+NM_NAT_SRC_PORT æºç«¯å£
+NM_NAT_DST_HOST 目标主机
+NM_NAT_DST_PORT 目标端å£
+NM_NAT_CREATED 会è¯ç”Ÿæˆæ—¶é—´
+NM_NAT_LAST_COMM 最åŽé€šä¿¡æ—¶é—´
+NM_NAT_SIZE 接收 / å‘é€å¤§å°
+NM_NAT_TCP_STATUS TCP 连接状æ€
+NM_NAT_PROTO_TCP TCP/IP
+NM_NAT_PROTO_UDP UDP/IP
+NM_NAT_PROTO_DNS DNS
+NM_NAT_PROTO_ICMP ICMP
+NAT_TCP_CONNECTING 连接中
+NAT_TCP_SEND_RESET 断开中
+NAT_TCP_CONNECTED 已连接
+NAT_TCP_ESTABLISHED è¿è¡Œä¸­
+NAT_TCP_WAIT_DISCONNECT 断开中
+DHCP_DHCP_ID ID
+DHCP_LEASED_TIME 租期开始时间
+DHCP_EXPIRE_TIME 租期到期时间
+DHCP_MAC_ADDRESS MAC 地å€
+DHCP_IP_ADDRESS 分é…çš„ IP
+DHCP_HOSTNAME 客户端主机å
+NM_PASSWORD_MSG 管ç†å‘˜å¯†ç è®¾å®šå®Œæˆã€‚
+
+
+#关于版本信æ¯
+ABOUT_CAPTION 关于 %s
+BETA_EXPIRES 因为目å‰å®‰è£…çš„ SoftEther VPN 软件是测试版,您无法在完整版的更新测试版å‘布åŽç»§ç»­ä½¿ç”¨æ­¤æµ‹è¯•ç‰ˆã€‚\r\n请访问 http://selinks.org/ ä»¥èŽ·å– SoftEther VPN 软件的最新版本。
+
+
+#关于日志ä¿å­˜
+# (通用日志)
+L_YES 是
+L_NO å¦
+L_LINE ------------------------------------------------------
+
+# (æœåŠ¡ç«¯æ—¥å¿—)
+LS_START_UTF8 Log Messages are written with UTF-8 Encoding Format.
+LS_START_1 SoftEther VPN Server å·²å¯åŠ¨ã€‚
+LS_START_2 %S %S
+LS_START_3 %S
+LS_END_1 SoftEther VPN Server 引擎已æˆåŠŸå…³é—­ã€‚
+LS_END_2 æœåŠ¡ç«¯å¼•æ“Žå…³é—­è¿›ç¨‹å·²å¯åŠ¨ã€‚
+LS_STOP_ALL_LISTENER å°†åœæ­¢æ‰€æœ‰ TCP 监å¬å™¨ã€‚
+LS_STOP_ALL_LISTENER_2 å·²åœæ­¢æ‰€æœ‰ TCP 监å¬å™¨ã€‚
+LS_STOP_ALL_HUB 正在åœæ­¢æ‰€æœ‰è™šæ‹Ÿ HUB。
+LS_STOP_ALL_HUB_2 å·²åœæ­¢æ‰€æœ‰è™šæ‹Ÿ HUB。
+LS_STOP_CEDAR 正在关闭 Cedar 通信模å—。
+LS_STOP_CEDAR_2 已关闭 Cedar 通信模å—。
+LS_STOP_FARM_MEMBER 正在断开到群集控制器的连接。
+LS_STOP_FARM_MEMBER_2 已断开到群集控制器的连接。
+LS_STOP_FARM_CONTROL 正在åœæ­¢ç¾¤é›†æŽ§åˆ¶å™¨ã€‚
+LS_STOP_FARM_CONTROL_2 å·²åœæ­¢ç¾¤é›†æŽ§åˆ¶å™¨ã€‚
+LS_ENUM_ETHERNET_1 枚举以太网设备。
+LS_ENUM_ETHERNET_2 设备 %u: "%S"
+LS_LOAD_CONFIG_1 正在装载é…置文件。
+LS_LOAD_CONFIG_2 已装载é…置文件。
+LS_LOAD_CONFIG_3 é…置文件ä¸å­˜åœ¨ï¼Œè¯·å°è¯•ä½¿ç”¨åˆå§‹è®¾ç½®ã€‚
+LS_INIT_SAVE_THREAD 开始自动ä¿å­˜åŽå°ä»»åŠ¡ã€‚自动ä¿å­˜é—´éš”为 %u 秒。您å¯ä»¥åœ¨é…置文件中通过修改 AutoSaveConfigSpan å‚æ•°æ¥ä¿®æ”¹è‡ªåŠ¨ä¿å­˜é—´éš”。
+LS_BAD_CONFIG é…置文件内容éžæ³•ã€‚加载进程被终止。
+LS_LISTENER_START_1 正在å¯åŠ¨ TCP 监å¬å™¨ (ç«¯å£ %u)。
+LS_LISTENER_START_2 å·²å¯åŠ¨ TCP 监å¬å™¨ (ç«¯å£ %u)。现在开始监å¬å®¢æˆ·ç«¯è¿žæŽ¥ã€‚
+LS_LISTENER_START_3 无法为 TCP 监å¬å™¨ (ç«¯å£ %u) 设置端å£ä¸ºç›‘å¬çŠ¶æ€ã€‚请隔一段时间å†å°è¯•ï¼Œç›´åˆ°æˆåŠŸã€‚
+LS_LISTENER_ACCEPT 在 TCP 监å¬å™¨(ç«¯å£ %u)上,客户端 (IP åœ°å€ %S,主机å "%S",端å£å· %u) 的连接已建立。
+LS_LISTENER_DISCONNECT 与客户端 (IP åœ°å€ %S,端å£å· %u) 的连接已断开。
+LS_LISTENER_DOS 已检测到 TCP 监å¬å™¨ä¸Šæœ‰ DoS 攻击(端å£å· %u)ã€‚è¿žæŽ¥æº IP 地å€æ˜¯%S,端å£å·æ˜¯%u。现在将强制断开此连接。
+LS_LISTENER_MAXUEC TCP 监å¬å™¨æ˜¯ä¸´æ—¶æš‚åœæŽ¥å—æ–°çš„ã€å‘内的连接,因为未决的 TCP 连接的数é‡è¶…过了 %u 个。(当å‰å€¼=%u)
+LS_LISTENER_STOP_1 正在åœæ­¢ TCP 监å¬å™¨(ç«¯å£ %u)
+LS_LISTENER_STOP_2 å·²åœæ­¢ TCP 监å¬å™¨(ç«¯å£ %u)
+LS_HUB_START 虚拟 HUB "%S" å·²å¯åŠ¨ã€‚
+LS_HUB_STOP 虚拟 HUB "%S" 已关闭。
+LS_HUB_MAC 虚拟 HUB "%S" çš„ MAC 地å€æ˜¯ "%S"。
+LS_NODE_INFO_TAG 客户端产å“å:"%S",客户端版本:%u,客户端构建å·ï¼š%u,æœåŠ¡ç«¯äº§å“å:"%S",æœåŠ¡ç«¯ç‰ˆæœ¬ï¼š%u,æœåŠ¡ç«¯æž„建å·ï¼š%u,客户端æ“作系统å:"%S",客户端æ“作系统版本:"%S"ï¼Œå®¢æˆ·ç«¯äº§å“ ID:"%S",客户端主机å:"%S",客户端 IP 地å€ï¼š"%S",客户端端å£å·ï¼š%u,æœåŠ¡ç«¯ä¸»æœºå:"%S",æœåŠ¡ç«¯ IP 地å€ï¼š"%S",æœåŠ¡ç«¯ç«¯å£å·ï¼š%u,代ç†ä¸»æœºå:"%S"ï¼Œä»£ç† IP 地å€ï¼š"%S",代ç†ç«¯å£å·ï¼š%u,虚拟 HUB å:"%S",客户端唯一 ID: "%S"
+LS_CONNECTION_START_1 客户端 (IP 地å€ï¼š%S,主机å:"%S",端å£å·ï¼š%u) 的连接 "%S" 已建立。
+LS_CONNECTION_END_1 连接 "%S" 已结æŸã€‚
+LS_SSL_START 连接 "%S" çš„ SSL 通信已å¯åŠ¨ã€‚加密算法å为 "%S"。
+LS_CONNECTION_ERROR 连接 "%S"因原因 "%s" (ä»£ç  %u)已终止。
+LS_FARMMEMBER_NOT_ADMIN 连接 "%S": æœåŠ¡ç«¯æ˜¯ç¾¤é›†æˆå‘˜ï¼Œä½†å®¢æˆ·ç«¯åœ¨éžç®¡ç†å‘˜ (%S) 用户情况下,å°è¯•ç›´æŽ¥ä¸Žè™šæ‹Ÿ HUB "%S" 连接。客户端用户å为 "%S"。访问被拒ç»ã€‚
+LS_HUB_NOT_FOUND 连接 "%S": 客户端正在å°è¯•è¿žæŽ¥çš„虚拟 HUB "%S" 在æœåŠ¡ç«¯ä¸Šä¸å­˜åœ¨ã€‚
+LS_IP_DENIED 连接 "%S": 基于虚拟 HUB ä¸Šå®šä¹‰çš„æº IP 访问é™åˆ¶åˆ—è¡¨ï¼Œå®¢æˆ·ç«¯çš„æº IP åœ°å€ "%S" 被拒ç»ã€‚
+LS_LICENSE_ERROR 连接 "%S": 因为å‘生许å¯è¯ç›¸å…³é”™è¯¯ï¼Œå®¢æˆ·ç«¯æ— æ³•è¿žæŽ¥åˆ°æœåŠ¡ç«¯ã€‚
+LS_BETA_EXPIRES SoftEther VPN Server 测试版已过期。测试版使用期é™å·²åˆ°ã€‚请从 http://selinks.org/ 下载新的测试版或完整版。
+LS_TICKET_1 新的客户端鉴æƒç¥¨è¯å·²å‘布为群集æˆå‘˜ "%S"。虚拟机 HUB "%S",用户å "%S" ("%S"),会è¯å "%S"ï¼Œç¥¨è¯ "%S"。
+LS_TICKET_2 新的客户端鉴æƒç¥¨è¯å·²ä»Žç¾¤é›†æŽ§åˆ¶å™¨æŽ¥æ”¶ã€‚虚拟机 HUB "%S",用户å "%S" ("%S"),会è¯å "%S"ï¼Œç¥¨è¯ "%S"ï¼Œæœ‰æ•ˆæœŸé™ %u 秒。
+LS_ENUM_HUB 连接 "%S": æ­¤æœåŠ¡ç«¯ä¸Šå·²æžšä¸¾ %u 个虚拟 HUB æœåŠ¡å™¨ã€‚
+LS_FARM_ACCEPT_1 连接 "%S": æ­¤æœåŠ¡ç«¯æŽ¥æ”¶åˆ°ä¸€ä¸ªç¾¤é›†æŽ§åˆ¶å™¨è¿žæŽ¥è¯·æ±‚,但此æœåŠ¡ç«¯å¹¶ä¸æ˜¯ç¾¤é›†æŽ§åˆ¶å™¨ã€‚
+LS_FARM_ACCEPT_2 连接 "%S": æ­¤æœåŠ¡ç«¯æŽ¥æ”¶åˆ°ä¸€ä¸ªç¾¤é›†æŽ§åˆ¶å™¨è¿žæŽ¥è¯·æ±‚,但认è¯å¯†ç é”™è¯¯ï¼Œæ‹’ç»è¿žæŽ¥ã€‚
+LS_FARM_ACCEPT_3 连接 "%S": æ­¤æœåŠ¡ç«¯æŽ¥æ”¶åˆ°ä¸€ä¸ªç¾¤é›†æŽ§åˆ¶å™¨è¿žæŽ¥è¯·æ±‚。认è¯æˆåŠŸã€‚
+LS_FARM_SERV_START 到群集æˆå‘˜çš„连接已建立。IP åœ°å€ %S,主机å "%S"。
+LS_FARM_SERV_END 到群集æˆå‘˜ "%S" 的连接已删除。
+LS_FARM_CONNECT_1 到群集æˆå‘˜ "%S" 的连接已å¯åŠ¨ã€‚
+LS_FARM_CONNECT_2 到群集æˆå‘˜ "%S" 的连接被拒ç»ã€‚错误: %s (ä»£ç  %u)
+LS_FARM_CONNECT_3 到群集æˆå‘˜ "%S" çš„ TCP 连接失败。请间隔 %u 秒åŽå†åº¦å°è¯•è¿žæŽ¥ï¼Œç›´åˆ°è¿žæŽ¥æˆåŠŸã€‚
+LS_FARM_DISCONNECT 到群集控制器的连接已åœæ­¢ã€‚
+LS_FARM_START 已连接到群集控制器。已开始群集æˆå‘˜æ“作。VPN Server 是ä¸æ˜¯åœ¨æ—¶é—´è®¸å¯çš„产å“注册,VPN Client 试图连接。
+LS_LICENSE_NOT_VPNSERVER 连接 "%S": 许å¯è¯é”™è¯¯ã€‚VPN Client å°è¯•è¿žæŽ¥æœªæ³¨å†Œäº§å“许å¯è¯çš„ VPN Server。
+LS_LICENSE_NOT_VPNCLUSTER 连接 "%S": 许å¯è¯é”™è¯¯ã€‚æ­¤ VPN Server 上注册的许å¯è¯æ˜¯ç¦æ­¢ä½¿ç”¨å½“å‰ç¾¤é›†åŠŸèƒ½çš„类型,且一个 VPN Client å·²å°è¯•åœ¨ç¾¤é›†æ¨¡å¼ä¸‹è¿žæŽ¥ã€‚您必须é‡å¯ VPN Server。
+LS_LICENSE_VIOLATION 连接 "%S": VPN Server å‘生è¿å许å¯è¯é”™è¯¯ï¼Œä¸æŽ¥å—连接。
+LS_LICENSE_VIOLATION_DETECTED å‘现许å¯è¯è¿å错误,一个ä¸åŒçš„ VPN Server 与此æœåŠ¡ç«¯å…·æœ‰ç›¸åŒçš„æœåŠ¡ç«¯ID "%I64u"。å¯èƒ½æ˜¯åœ¨ç¾¤é›†ä¸­æœ‰ä¸¤ä¸ªæˆ–以上 VPN Server 正在使用相åŒçš„许å¯è¯ã€‚请检查æ¯ä¸€ä¸ª VPN Server 的许å¯è¯ä¿¡æ¯ã€‚
+
+
+# (OpenVPN Logs)
+LO_PREFIX_RAW OpenVPN 模å—:
+LO_PREFIX_SESSION OpenVPN 会è¯%u (%r:%u -> %r:%u):
+LO_PREFIX_CHANNEL OpenVPN 会è¯%u (%r:%u -> %r:%u) é€šé“ %u:
+LO_NEW_CHANNEL 已创创建一个新通é“。
+LO_CHANNEL_ESTABLISHED_NEWKEY 通é“已建立。(触å‘器: Re-key完æˆã€‚)
+LO_OPTION_STR_RECV 接收到的选项字符串:"%S"
+LO_OPTION_STR_SEND å‘é€é€‰é¡¹å­—符串:"%S"
+LO_NEW_SESSION 已创建新的会è¯ã€‚å议:%S
+LO_INITIATE_REKEY re-keying 进程已开始。
+LO_CHANNEL_ESTABLISHED 该通é“æˆä¸ºå·²å»ºç«‹çš„状æ€ã€‚
+LO_PUSH_REPLY 完整字符串回答:"%S"
+LO_CHANNEL_FAILED 无法连接通é“。
+LO_CHANNEL_DISCONNECTED_BY_HUB æ­¤ OpenVPN 的通é“被终止,因为虚拟 HUB 管ç†å‘˜æ–­å¼€äº†æ­¤ VPN 会è¯ã€‚
+LO_DELETE_SESSION 删除会è¯ä¸­ã€‚
+LO_START OpenVPN Server 模å—正在å¯åŠ¨ã€‚
+LO_STOP OpenVPN Server 模å—å·²åœæ­¢ã€‚
+
+
+# (IPsec 日志)
+LI_PREFIX_RAW IPsec 模å—:
+LI_PREFIX_CLIENT IPsec 客户端 %u (%S:%u -> %S:%u):
+LI_PREFIX_IKE IPsec IKE ä¼šè¯ (IKE SA) %u (客户端: %u) (%S:%u -> %S:%u):
+LI_PREFIX_IPSEC IPsec ESP ä¼šè¯ (IPsec SA) %u (客户端: %u) (%S:%u -> %S:%u):
+LI_START IPsec 2.0 版 (ISAKMP/IKEv1) 处ç†æ¨¡å—已开å¯ã€‚
+LI_STOPPING IPsec 2.0 版 (ISAKMP/IKEv1) 处ç†æ¨¡å—现在正在关闭。
+LI_STOP IPsec 2.0 版 (ISAKMP/IKEv1) 处ç†æ¨¡å—已正常关闭。
+LI_NUM_IPSEC_SA 在关机时刻, 余下的 IPsec SA æ•°é‡æ˜¯ %u。
+LI_NUM_IKE_SA 在关机时刻, 余下的 IKE SA æ•°é‡æ˜¯ %u。
+LI_NUM_IKE_CLIENTS 在关机时刻, 余下的 IKE 客户端数é‡æ˜¯ %u。
+LI_L2TP_SERVER_STARTED L2TP æœåŠ¡å™¨æ¨¡å—已开å¯ã€‚
+LI_ETHERIP_SERVER_STARTED EtherIP æœåŠ¡å™¨æ¨¡å—已开å¯ã€‚EtherIP ä¼šè¯ ID: %u
+LI_DELETE_IKE_CLIENT IPsec 客户端对象被删除。
+LI_DELETE_IKE_SA IKE SA 对象被删除。
+LI_DELETE_IPSEC_SA IPsec SA 对象被删除。
+LI_START_QM_FROM_SERVER 快速模å¼å商阶段是从æœåŠ¡å™¨ç«¯è°ƒç”¨ã€‚
+LI_START_QM_FROM_CLIENT 快速模å¼å商阶段是从客户端调用。
+LI_QM_DH_ERROR Diffie-Hellman 算法的计算失败。
+LI_NEW_IKE_CLIENT 新的 IPsec 客户端对象已创建。
+LI_NEW_IKE_SA æ–°çš„ IKE SA 对象 (%s) 已创建。å‘èµ· Cookie: 0x%I64X, å“应 Cookie: 0x%I64X, DH 组: %S, 哈希算法: %S, 加密算法: %S, 加密密钥大å°:%u ä½, 寿命:%u kbytes 或 %u 秒。
+LI_TAG_MAINMODE 主模å¼
+LI_TAG_AGGRESSIVE 积æžæ¨¡å¼
+LI_NEW_IPSEC_SA æ–°çš„ IPsec SA (æ–¹å‘:%s) 已创建。SPI: 为 0x%X, DH 组:%S, 哈希算法: %S, 加密算法: %S, 加密密钥大å°: %u ä½, 寿命: %u kbytes 或 %u 秒。
+LI_TAG_SERVER_TO_CLIENT æœåŠ¡å™¨ -> 客户端
+LI_TAG_CLIENT_TO_SERVER 客户端 -> æœåŠ¡å™¨
+LI_IPSEC_SA_SPI_SET ä¸å›ºå®šçš„ SPI 已修改。SPI 的新值为: 0x%X
+LI_IPSEC_SA_ESTABLISHED æœåŠ¡å™¨å’Œå®¢æˆ·ç«¯ä¹‹é—´çš„ IPsec SA 已建立。
+LI_IKE_SA_ESTABLISHED æœåŠ¡å™¨å’Œå®¢æˆ·ç«¯ä¹‹é—´çš„ IKE SA 已建立。
+LI_IPSEC_NO_TRANSFORM 在从客户端的候选人里, 没有建立 IPsec SA 的适当转æ¢è¢«å‘现。
+LI_IKE_NO_TRANSFORM 在从客户端的候选人里, 没有建立 IKE SA 的适当转æ¢è¢«å‘现。
+LI_IKE_NO_NAT_T 此客户端与 IPSec NAT Traversal (在 IKE NAT Traversal çš„ RFC 3947 å商, 或 draft-ietf-ietf-ipsec-nat-t-ike) ä¸å…¼å®¹, å› æ­¤æœåŠ¡å™¨æ— æ³•æŽ¥å— VPN 连接。
+LI_SET_CLIENT_ID 客户端呈现的客户 ID 是 "%S".
+LI_CLIENT_MERGE 此客户端 (客户端 %u) 与客户端 %u 是相åŒçš„, 因此客户端对象与客户端 %u 是相结åˆçš„。
+LI_CLIENT_UPDATE 此客户端的端å£å·ä¿¡æ¯æ˜¯æ›´æ–°çš„。
+
+
+# (EtherIP日志)
+LE_PREFIX EtherIP / L2TPv3 ä¼šè¯ %u (%S:%u - >%S:%u):
+LE_START_MODULE EtherIP / L2TPv3 模å—已开å¯ã€‚
+LE_STOP EtherIP / L2TPv3 模å—已关闭。
+LE_NO_SETTING 错误: 没有与客户端 ID "%S" 相对应的 EtherIP / L2TPv3 设置。你必须预先在 VPN Server 上注册一个 EtherIP / L2TPv3 设置。
+LE_START_IPC 在 EtherIP / L2TPv3 模å—和虚拟 HUB "%S" 之间的内部连接过程。用户å是 "%S" 。IPv4 TCP MSS (最大网段尺寸) 的值是 %u 字节。
+LE_IPC_CONNECT_ERROR 从 EtherIP / L2TPv3 模å—到虚拟 HUB "%S" 的连接失败。错误: %u: %s
+LE_IPC_CONNECT_OK 从 EtherIP / L2TPv3 模å—到虚拟 HUB "%S" 的连接建立æˆåŠŸã€‚
+LE_RECONNECT 由于 EtherIP / L2TPv3 设置已被修改, 现在内部连接是断开的, 将会自动é‡æ–°è¿žæŽ¥ã€‚
+
+
+# (PPP 日志)
+LP_PREFIX %S%SPPP ä¼šè¯ [%S:%u]:
+LP_CONNECTED 开始新的 PPP ä¼šè¯ (上层åè®®: %S)。PPP 客户端 IP 地å€:%S (主机å: "%S"), PPP 客户端端å£: %u, PPP æœåŠ¡å™¨ IP 地å€:%S, PPP æœåŠ¡å™¨ç«¯å£:%u, 客户端软件: "%S" ,IPv4 TCP MSS (最大网段尺寸): %u 字节
+LP_DISCONNECTED PPP 会è¯å·²æ–­å¼€ã€‚
+LP_PAP_REJECTED VPN 客户端拒ç»ä½¿ç”¨ "PAP" (Password Authentication Protocolã€æ˜Žæ–‡å¯†ç éªŒè¯æ–¹æ³•) 作为认è¯å议。您必须在 VPN å®¢æˆ·ç«¯è®¾ç½®ä¸Šå¼€å¯ PAP。
+LP_PAP_MSCHAPV2_REJECTED VPN 客户端拒ç»ä½¿ç”¨ "PAP" (Password Authentication Protocol, 明文密ç éªŒè¯æ–¹æ³•) å’Œ MS-CHAP v2 å议。您必须在 VPN å®¢æˆ·ç«¯è®¾ç½®ä¸Šå¼€å¯ PAP 或 MS-CHAP v2。
+LP_DISCONNECTED_ABNORMAL PPP å议错误或 PPP 会è¯ä¸­æ–­ã€‚
+LP_NEXT_PROTOCOL_IS_NOT_PAP 收到无效的åè®® (åè®®å·:0x%x)。在这ç§æƒ…况下, åªæœ‰ PAP (密ç éªŒè¯åè®®) 控制数æ®å¯ä»¥è¢«æŽ¥å—。
+LP_PAP_FAILED "PAP" (密ç éªŒè¯åè®®, 明文密ç éªŒè¯æ–¹æ³•) 在用户验è¯è¿‡ç¨‹ä¸­å¤±è´¥ã€‚
+LP_MSCHAPV2_FAILED "MS-CHAP v2" (Microsoft Challenge and Response Protocol Version 2.0) 在用户验è¯è¿‡ç¨‹ä¸­å¤±è´¥ã€‚
+LP_NEXT_PROTOCOL_IS_NOT_IPCP 收到无效åè®® (åè®®å·:0x%x)。在这ç§æƒ…况下, åªæœ‰ IPCP (IP é…ç½®åè®®) 控制数æ®å¯ä»¥è¢«æŽ¥å—。
+LP_DATA_TIMEOUT PPP æ•°æ®ä¼ è¾“超时å‘生。PPP 客户端å¯èƒ½ä¼šä»Žç½‘络上断开。
+LP_CONTROL_TIMEOUT PPP 控制通讯超时å‘生。PPP 客户端没有å“应。
+LP_VPN_SESSION_TERMINATED 因为 VPN 会è¯å·²è¢«ç³»ç»Ÿç®¡ç†å‘˜æ–­å¼€, PPP 会è¯æ–­å¼€ã€‚
+LP_UPPER_PROTOCOL_DISCONNECTED 因为上层åè®® "%S" æ–­å¼€, PPP 会è¯æ–­å¼€ã€‚
+LP_NORMAL_TERMINATE 由于 VPN 客户端的请求, PPP 会è¯æ–­å¼€ã€‚
+LP_IP_ADDRESS_NOT_DETERMIND 虽然 VPN 客户端的 IP 地å€æ˜¯ä¸å›ºå®šçš„, VPN 客户端å°è¯•å‘é€æ•°æ®ã€‚
+LP_DHCP_REQUEST_TRYING 请求 DHCP æœåŠ¡å™¨åˆ†é… IP 地å€ã€‚
+LP_DHCP_REQUEST_OK IP 地å€ä»Ž DHCP æœåŠ¡å™¨è¢«åˆ†é…。客户端 IP 地å€: %S, å­ç½‘掩ç : %S, 默认网关: %S, 域å: "%S", DNS æœåŠ¡å™¨ 1: %S, DNS æœåŠ¡å™¨ 2: %S, WINS æœåŠ¡å™¨ 1: %S, WINS æœåŠ¡å™¨ 2: %S, DHCP æœåŠ¡å™¨ IP 地å€:%S, 租èµå¯¿å‘½: %u 秒
+LP_DHCP_REQUEST_NG å‘ DHCP æœåŠ¡å™¨è¯·æ±‚ IP 地å€å¤±è´¥ã€‚è¦æŽ¥å— PPP 连接, DHCP æœåŠ¡å™¨å¿…须在现有网络上。确ä¿ä»»ä½•ä¸€ä¸ªåœ¨è™šæ‹Ÿ HUB 的以太网段的 DHCP æœåŠ¡å™¨æ˜¯å¯ç”¨çš„。
+LP_DHCP_INFORM_TRYING 请求 DHCP æœåŠ¡å™¨èŽ·å–网络信æ¯, 如å­ç½‘掩ç å’Œé»˜è®¤ç½‘关。
+LP_DHCP_INFORM_OK IP 网络信æ¯ä»Ž DHCP æœåŠ¡å™¨èŽ·å–。å­ç½‘掩ç : %S, 默认网关:%S, 域å: "%S", DNS æœåŠ¡å™¨ 1: %S, DNS æœåŠ¡å™¨ 2: %S, WINS æœåŠ¡å™¨ 1: %S, WINS æœåŠ¡å™¨ 2: %S, DHCP æœåŠ¡å™¨ IP 地å€: %S
+LP_DHCP_INFORM_NG å‘ DHCP æœåŠ¡å™¨è¯·æ±‚一个 IP 网络信æ¯å¤±è´¥ã€‚è¦æŽ¥å— PPP 连接, DHCP æœåŠ¡å™¨å¿…须在现有网络上。确ä¿ä»»ä½•ä¸€ä¸ªåœ¨è™šæ‹Ÿ HUB 的以太网段的 DHCP æœåŠ¡å™¨æ˜¯å¯ç”¨çš„。
+LP_SET_IPV4_PARAM 在 VPN 客户端的 IP 地å€å’Œå…¶ä»– IP 网络信æ¯å·²å»ºç«‹ã€‚客户端 IP 地å€: %S, å­ç½‘掩ç : %S, 默认网关: %S, DNS æœåŠ¡å™¨ 1: %S, DNS æœåŠ¡å™¨ 2: %S, WINS æœåŠ¡å™¨ 1: %S, WINS æœåŠ¡å™¨ 2: %S
+
+
+# (虚拟 HUB 日志)
+LH_ONLINE 虚拟 HUB 现在在线。
+LH_OFFLINE 虚拟 HUB 现在离线。
+LH_CONNECT_CLIENT 连接 "%S" (IP åœ°å€ %S,主机å %S,端å£å· %u,客户端å "%S",版本 %Sï¼Œå†…éƒ¨ç¼–å· %u) æ­£å°è¯•è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB。æ供的认è¯ç±»åž‹æ˜¯ "%s",用户å是 "%S"。
+LH_AUTH_UNKNOWN 未知的认è¯ç±»åž‹
+LH_AUTH_ANONYMOUS 匿å身份验è¯
+LH_AUTH_PASSWORD 密ç éªŒè¯
+LH_AUTH_PLAIN_PASSWORD 外部æœåŠ¡å™¨èº«ä»½éªŒè¯
+LH_AUTH_CERT è¯ä¹¦éªŒè¯
+LH_AUTH_TICKET 票è¯éªŒè¯
+LH_AUTH_RADIUS_NOT_SUPPORT 连接 "%S": 用户 "%S" 身份验è¯æ–¹æ³• RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因为 RADIUS 或 Active Directory (NT 域)ä¸èƒ½ä½¿ç”¨ã€‚连接被拒ç»ã€‚
+LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验è¯æ–¹æ³•è¢«æŒ‡å®šä¸º RADIUS 身份验è¯æˆ– Active Directory èº«ä»½éªŒè¯ (NT 域验è¯)。然而,这样一个外部用户身份验è¯åŠŸèƒ½å°šæœªåœ¨ SoftEther VPN çš„å¼€æºç‰ˆæœ¬ä¸Šå®žæ–½ã€‚该连接将被拒ç»ã€‚
+LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验è¯æ–¹æ³•è¢«æŒ‡å®šä¸ºè¯ä¹¦è®¤è¯ã€‚然而,è¯ä¹¦éªŒè¯åŠŸèƒ½å°šæœªåœ¨ SoftEther VPN çš„å¼€æºç‰ˆæœ¬ä¸Šå®žæ–½ã€‚该连接将被拒ç»ã€‚
+LH_AUTH_OK 连接 "%S": æˆåŠŸè®¤è¯ä¸ºç”¨æˆ· "%S"。
+LH_AUTH_OK_CERT 虚拟 HUB 的安全账户管ç†å™¨å·²ç»ä»Ž VPN Client 接收到如下è¯ä¹¦ï¼Œä¸”接å—了其内容作为当用户 "%S" 登录时的è¯ä¹¦: %s
+LH_AUTH_NG_CERT 虚拟 HUB 的安全账户管ç†å™¨å·²ç»ä»Ž VPN Client 接收到如下è¯ä¹¦ï¼Œä½†æ‹’ç»äº†å…¶å†…容作为当用户 "%S" 登录时的è¯ä¹¦ï¼Œå› ä¸ºæ­¤è¯ä¹¦çš„内容匹é…虚拟 HUB 中注册的废止内容列表: %s
+LH_AUTH_NG 连接 "%S": 用户认è¯å¤±è´¥ã€‚æ供的用户å为 "%S"。
+LH_LOCAL_ONLY 连接 "%S": 远程登录拒ç»ï¼Œå› ä¸ºç”¨æˆ· "%S" 的密ç ä¸ºç©ºã€‚
+LH_POLICY_ACCESS_NG 连接 "%S": 由于安全策略,用户 "%S" æ‹’ç»è®¿é—®ã€‚
+LH_USER_EXPIRES 连接 "%S": 由于有效期é™å·²è¿‡ï¼Œç”¨æˆ· "%S" æ‹’ç»è®¿é—®ã€‚
+LH_CLIENT_VERSION_OLD 连接 "%S": 客户端版本å·ä¸º %u。为了å…许这个连接,客户端版本å·è‡³å°‘应为 %u 或以上。
+LH_CLIENT_ID_REQUIRED 连接 "%S": 客户已ç»ä»Žå®¢æˆ·ç«¯å‘é€çš„ ID 是 %u。然而,此虚拟 HUB çš„ RequiredClientId 值设置为 %u。
+LH_FARM_SELECT_1 连接 "%S": 群集控制器正在确定此客户端的目标群集æˆå‘˜ã€‚
+LH_FARM_SELECT_2 连接 "%S": 群集控制器确定目标群集æˆå‘˜æœåŠ¡å™¨å¤±è´¥ã€‚
+LH_FARM_SELECT_3 连接 "%S": å½“å‰ VPN Server 被确定作为目标群集æˆå‘˜æœåŠ¡å™¨ã€‚请继续接收连接。
+LH_FARM_SELECT_4 连接 "%S": æœåŠ¡ç«¯ "%S" 被确定作为目标群集æˆå‘˜æœåŠ¡å™¨ã€‚正在指示客户端é‡æ–°è¿žæŽ¥åˆ°æ­¤æœåŠ¡ç«¯ã€‚
+LH_MAX_SESSION 连接 "%S": 虚拟 HUB 设置的最大会è¯æ•° (%u) 已到达。无法创建新会è¯ã€‚
+LH_MAX_SESSION_CLIENT 连接 "%S": 虚拟 HUB 设置的最大客户端会è¯æ•° (%u) 已到达。无法创建新会è¯ã€‚
+LH_MAX_SESSION_BRIDGE 连接 "%S": 虚拟 HUB 设置的最大网桥会è¯æ•° (%u) 已到达。无法创建新会è¯ã€‚
+LH_MAX_SESSION_2 连接 "%S": å¯è¢« VPN Server 管ç†çš„的最大会è¯æ•° (%u) 已到达。无法创建新会è¯ã€‚
+LH_NEW_SESSION 连接 "%S": å·²åˆ›å»ºæ–°ä¼šè¯ "%S"。(IP 地å€ï¼š%S,端å£å·ï¼š%u,物ç†åº•å±‚å议:"%S")
+LH_SET_SESSION ä¼šè¯ "%S": 已设置å‚数。最大 TCP 连接数:%u,使用的加密:%s,使用的压缩:%s,使用的åŠåŒå·¥é€šä¿¡ï¼š%s,超时:%u 秒。
+LH_NODE_INFO ä¼šè¯ "%S": VPN Client 详细信æ¯: (%s)
+LH_INVALID_SIGNATURE ä¼šè¯ "%S": 已连接的客户端å‘é€äº†éžæ³•å议数æ®ã€‚无法与客户端建立一般通信。请首先检查客户端到æœåŠ¡ç«¯ä¹‹é—´çš„连接和网络线缆问题,然åŽå†æ£€æŸ¥æ˜¯å¦å®‰è£…有特殊传输数æ®åŒ…é‡å†™è®¾å¤‡ã€‚
+LH_END_SESSION ä¼šè¯ "%S": 会è¯å·²ç»“æŸã€‚统计信æ¯å¦‚下: 总输出数æ®å¤§å°: %I64u 字节,总输入数æ®å¤§å°: %I64u 字节。
+LH_BCAST_STORM ä¼šè¯ "%S": 检测到大é‡å¹¿æ’­æ•°æ®åŒ…。您å¯èƒ½ä¼šæŒ‰ç…§ç­–略废弃数æ®åŒ…ã€‚æº MAC 地å€æ˜¯ %Sï¼Œæº IP 地å€æ˜¯ %S,目标 IP 地å€æ˜¯ %S。广播数æ®åŒ…é‡å¤§äºŽç­‰äºŽ %u æ¯ç§’ (注æ„此信æ¯æ˜¯å¯¹éƒ¨åˆ†æ•°æ®åŒ…进行刻æ¿çš„分æžï¼Œç»“æžœå¯èƒ½ä¸æ­£ç¡®)。
+LH_DHCP_FORCE ä¼šè¯ "%S": æ•°æ®åŒ…被废弃,因为它å°è¯•ä½¿ç”¨éž DHCP æœåŠ¡å™¨åˆ†é…çš„ IP åœ°å€ %S。
+LH_MAC_LIMIT ä¼šè¯ "%S": 试图分é…一个新 MAC åœ°å€ "%S",但是 %u 个 MAC 地å€å·²è¢«åˆ†é…在此æœåŠ¡ä¸Šã€‚æ ¹æ®å®‰å…¨ç­–略,此会è¯è¢«å…许拥有最多 %u 个 MAC 地å€ã€‚æ•°æ®åŒ…被废弃。
+LH_BRIDGE_LIMIT ä¼šè¯ "%S": 试图分é…一个新 MAC åœ°å€ "%S",但是 %u 个 MAC 地å€å·²è¢«åˆ†é…在此æœåŠ¡ä¸Šã€‚æ ¹æ®å®‰å…¨ç­–略,此会è¯è¢«ç¦æ­¢ç½‘桥,因此åªå…许拥有ä¸è¶…过 %u 个 MAC 地å€ã€‚æ•°æ®åŒ…被废弃。
+LH_MAC_REGIST ä¼šè¯ "%S": 已分é…æ–°çš„ MAC 地å€"%S"。
+LH_MAC_REGIST_VLAN ä¼šè¯ "%S": 已分é…æ–°çš„ MAC 地å€"%S" (VLAN ID: %u)。
+LH_IP_LIMIT ä¼šè¯ "%S": 试图分é…一个新 IP åœ°å€ "%S",但是 %u 个 IP 地å€å·²è¢«åˆ†é…在此æœåŠ¡ä¸Šã€‚æ ¹æ®å®‰å…¨ç­–略,此会è¯è¢«å…许拥有最多 %u 个 IP 地å€ã€‚æ•°æ®åŒ…被废弃。
+LH_ROUTING_LIMIT ä¼šè¯ "%S": 试图分é…一个新 IP åœ°å€ "%S",但是 %u 个 IP 地å€å·²è¢«åˆ†é…在此æœåŠ¡ä¸Šã€‚æ ¹æ®å®‰å…¨ç­–略,此会è¯è¢«ç¦æ­¢è·¯ç”±ï¼Œå› æ­¤åªå…许拥有ä¸è¶…过 %u 个 IP 地å€ã€‚æ•°æ®åŒ…被废弃。
+LH_IP_CONFLICT ä¼šè¯ "%S": 试图分é…一个新 IP åœ°å€ "%S",但是此 IP 地å€å·²ç»è¢«å¦ä¸€ä¸ªä¼šè¯ "%S": ( MAC 地å€ï¼š"%S")所使用。此会è¯çš„安全策略ç¦æ­¢å¤åˆ¶å…¶å®ƒä¼šè¯ä½¿ç”¨çš„ IP 地å€ã€‚æ•°æ®åŒ…被废弃。详细信æ¯ï¼šCreatedTime=%I64u, UpdatedTime=%I64u, DhcpAllocated=%u, Now=%I64u
+LH_NO_SERVER ä¼šè¯ "%S": 一个 TCP/IP 连接请求 (从 %S:%u 到 %S:%u) 被建立到此会è¯ï¼Œä½†å› ä¸ºå®‰å…¨ç­–ç•¥ç¦æ­¢ä½œä¸ºæœåŠ¡ç«¯è¿è¡Œï¼Œæ•°æ®åŒ…被废弃。
+LH_NO_DHCP ä¼šè¯ "%S": 此会è¯ä¸Šçš„主机 %S å‘é€äº†ä¸€ä¸ªä½œä¸º DHCP æœåŠ¡å™¨ä¸ºä¸»æœº %S 在其他会è¯ä¸Šåˆ†é… IP 地å€çš„æ•°æ®åŒ…,但此会è¯çš„安全策略ç¦æ­¢ä½œä¸º DHCP æœåŠ¡å™¨è¿è¡Œã€‚æ•°æ®åŒ…被废弃。
+LH_REGIST_DHCP ä¼šè¯ "%S": 此会è¯ä¸Šçš„主机 "%S" (%S) çš„ DHCP æœåŠ¡å™¨ï¼Œä¸ºä»¤ä¸€ä¸ªä¼šè¯ "%S" 上的主机 "%S",分é…了新的 IP åœ°å€ %S。
+LH_BRIDGE_1 ä¼šè¯ "%S": å·²å¯åŠ¨æœ¬åœ°ç½‘桥连接到物ç†ä»¥å¤ªç½‘æŽ¥å£ "%S"。
+LH_BRIDGE_2 ä¼šè¯ "%S": 因为与物ç†ä»¥å¤ªç½‘æŽ¥å£ "%S" 的通信建立失败,åœæ­¢æœ¬åœ°ç½‘桥。
+LH_SET_MTU ä¼šè¯ "%S": 物ç†ä»¥å¤ªç½‘æŽ¥å£ "%S" çš„ MTU 为 %u。å‘é€å’ŒæŽ¥æ”¶æœ‰ %u 字节的以太网数æ®åŒ…是必è¦çš„。MTU 现已更改为 %u。
+LH_SET_MTU_ERROR ä¼šè¯ "%S": 错误: 物ç†ä»¥å¤ªç½‘接å£"%S" çš„ MTU 为 %u。å‘é€å’ŒæŽ¥æ”¶æœ‰ %u 字节的以太网数æ®åŒ…是必è¦çš„ã€‚ç„¶è€Œï¼Œæ”¹å˜ MTU 到%u失败。此物ç†ä»¥å¤ªç½‘接å£æˆ–设备驱动程åºå¯èƒ½æ— æ³•å¤„ç†ä¸€ä¸ªå¤§äºŽ 1,514 字节(有效载è·å¤§å°ï¼š1,500 字节)的以太网数æ®åŒ…。在这样的情况下,大于 1,514 字节的ã€å¸¦æ ‡è®°çš„ VLAN æ•°æ®åŒ…ä¸èƒ½è¢«å‘é€ã€‚你应该将当å‰ç‰©ç†ä»¥å¤ªç½‘适é…器替æ¢ä¸ºæ”¯æŒå·¨åž‹å¸§çš„å¦ä¸€ä¸ªã€‚您也å¯ä»¥å°è¯•æ›´æ–°è®¾å¤‡é©±åŠ¨ç¨‹åºã€‚å¦ä¸€ç§å¯èƒ½çš„方法是在æ“作系统或设备驱动程åºè®¾ç½®é‡Œå¯ç”¨å·¨åž‹å¸§ã€‚
+LH_START_BRIDGE å·²å¯åŠ¨æœ¬åœ°ç½‘桥连接 "%S"ã€‚å·²åˆ›å»ºç½‘æ¡¥ä¼šè¯ "%S"。
+LH_STOP_BRIDGE å·²åœæ­¢æœ¬åœ°ç½‘桥连接 "%S"。
+LH_LINK_START 已建立级è”连接 "%s"。已建立级è”ä¼šè¯ "%S"。
+LH_LINK_STOP å·²åœæ­¢çº§è”连接 "%s"。
+LH_NAT_START å·²å¯åŠ¨ SecureNAT。已创建 SecureNAT ä¼šè¯ "%S"。
+LH_NAT_STOP å·²åœæ­¢ SecureNAT。
+LH_NAT_TCP_SUCCEED å·²æˆåŠŸè¿žæŽ¥åˆ° TCP ä¼šè¯ %u: 主机 "%S (%S)"ï¼Œç«¯å£ %u。
+LH_NAT_TCP_FAILED 连接到 TCP ä¼šè¯ %u: 主机 "%S"ï¼Œç«¯å£ %u 失败。
+LH_NAT_TCP_DELETED 已删除 TCP ä¼šè¯ %u。
+LH_NAT_TCP_CREATED 已创建 TCP ä¼šè¯ %uã€‚è¿žæŽ¥æº %S:%u,连接目标 %S:%u
+LH_NAT_UDP_DELETED 已删除 UDP ä¼šè¯ %u。
+LH_NAT_UDP_CREATED 已创建 UDP ä¼šè¯ %uã€‚è¿žæŽ¥æº %S:%u,连接目标 %S:%u
+LH_NAT_DHCP_CREATED 已建立 DHCP 项 %u。MAC 地å€: %S,IP 地å€: %S,主机å: %S,有效期é™: %u 秒
+LH_CHANGE_PASSWORD_1 连接到虚拟 HUB 的连接 "%S" (IP åœ°å€ %S) 在改å˜å¯†ç æ¨¡å¼ã€‚
+LH_CHANGE_PASSWORD_2 连接 "%S": 改å˜å¯†ç å¤±è´¥ã€‚指定用户 "%S" ä¸å­˜åœ¨ã€‚
+LH_CHANGE_PASSWORD_3 连接 "%S": 改å˜å¯†ç å¤±è´¥ã€‚用户 "%S" 的认è¯ç±»åž‹ä¸æ˜¯å¯†ç è®¤è¯ã€‚
+LH_CHANGE_PASSWORD_4 连接 "%S": 改å˜å¯†ç å¤±è´¥ã€‚用户 "%S" 的旧密ç é”™è¯¯ã€‚
+LH_CHANGE_PASSWORD_5 连接 "%S": 用户 "%S" 的密ç ä¿®æ”¹æˆåŠŸã€‚
+LH_CONNECT_1 正在å¯åŠ¨çº§è”连接 "%s": 连接次数 %u。
+LH_CONNECT_2 级è”连接 "%s" 已建立。会è¯å: "%S"
+LH_CONNECT_ERROR 级è”连接 "%s" 的已断开或连接失败。原因: %s (ä»£ç  %u)
+LH_POLICY_MONITOR_MODE 连接 "%S": 因为“监测模å¼â€æ‰“开监测模å¼å¹¶è¯•å›¾è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB 的请求被用户的安全策略ç¦æ­¢ï¼Œè¿žæŽ¥è¢«æ‹’ç»ã€‚
+LH_POLICY_BRIDGE_MODE 连接 "%S": 因为桥接和路由æ“作打开桥接或路由并试图连接到虚拟 HUB 的请求被用户的安全策略ç¦æ­¢ï¼Œè¿žæŽ¥è¢«æ‹’ç»ã€‚
+LH_NOT_ENOUGH_CLIENT_LICENSE 连接 "%S": 此连接试图使用“客户端连接模å¼â€è¿žæŽ¥åˆ° VPN Server,但因为此æ“作会导致整个æœåŠ¡ç«¯ä¸Šçš„客户端连接数超过已注册的客户端许å¯è¯æ•°ï¼Œå› æ­¤ä¸å¯èƒ½å†æŽ¥æ”¶æ›´å¤šè¿žæŽ¥ã€‚当å‰è¿žæŽ¥è®¸å¯è¯æ•°ä¸è¶³æ—¶ï¼Œæ‚¨å¿…须断开已存在的客户端连接,或增加许å¯è¯æ•°ã€‚在æœåŠ¡ç«¯ç›®å‰ç›®å‰ %u 个已注册的客户端连接许å¯è¯å’Œ %u 个连接。
+LH_NOT_ENOUGH_BRIDGE_LICENSE 连接 "%S": 此连接试图使用“桥接模å¼â€è¿žæŽ¥åˆ° VPN Server,但因为此æ“作会导致整个æœåŠ¡ç«¯ä¸Šçš„桥接数超过已注册的桥接许å¯è¯æ•°ï¼Œå› æ­¤ä¸å¯èƒ½å†æŽ¥æ”¶æ›´å¤šè¿žæŽ¥ã€‚当å‰è¿žæŽ¥è®¸å¯è¯æ•°ä¸è¶³æ—¶ï¼Œæ‚¨å¿…须断开已存在的客户端连接,或增加许å¯è¯æ•°ã€‚在æœåŠ¡ç«¯ç›®å‰ç›®å‰ %u 个已注册的桥接许å¯è¯å’Œ %u 个连接。
+LH_TOO_MANY_MULTILOGINS 连接 "%S": 用户 "%S" å°è¯•ç™»å½•ï¼Œä½†æ­¤ç”¨æˆ·çš„安全策略é™åˆ¶äº†æœ€å¤§å¤šé‡ç™»å½•åˆ° %u 个会è¯ã€‚ç›®å‰æ­¤ç”¨æˆ·ç™»å½•äº† %u 个会è¯ï¼Œå› æ­¤æ— æ³•å»ºç«‹æ–°çš„ VPN 连接。
+LH_TOO_MANY_MULTILOGINS2 连接“%Sâ€ï¼šç”¨æˆ·â€œ%Sâ€ç™»å½•å°è¯•ï¼Œä½† VPN Server 的这个版本,å…è®¸å¤šä¸ªå¹¶å‘ VPN 会è¯çš„最大数é‡è¾¾åˆ°æ¯ç”¨æˆ· %u 会è¯ã€‚ç›®å‰è¿™ä¸ªç”¨æˆ·çš„多个并å‘çš„ VPN 会è¯çš„æ•°é‡æ˜¯ %u,所以大于多个并å‘çš„ VPN 会è¯æ˜¯ä¸è¢«å…许的。如果你想æ¯ç”¨æˆ·æ”¯æŒæ›´å¤šçš„å¤šä¸ªå¹¶å‘ VPN 会è¯ï¼Œè¯·è€ƒè™‘å‡çº§åˆ°ä¸“业版或 VPN Server 的更高版本。
+LH_PACKET_LOG_NO_LOG æ­¤ VPN Server 的版本ä¸æ”¯æŒæ•°æ®åŒ…日志功能。无 IP 地å€æˆ–æ—  TCP / UDP 包头的数æ®å°†è¢«è®°å½•ã€‚在你å‡çº§ VPN Server 版å‡çº§åˆ°ä¸“业版或更高版本åŽï¼Œå„ç§æ•°æ®åŒ…日志将被记录在这个文件中。
+LH_PACKET_LOG_NO_LOG_OSS VPN æœåŠ¡å™¨æ˜¯å¼€æºæˆ–å…费的版本。尚未实施 IP 地å€æˆ– TCP / UDP 包头数æ®è®°å½•åŠŸèƒ½ã€‚这里ä¸è®°å½• IP 地å€ï¼Œä¹Ÿä¸è®°å½• TCP / UDP 包头数æ®ã€‚
+LH_NO_RADIUS_SETTING 用户“%Sâ€è¢«é…置为使用 RADIUS 身份验è¯ã€‚然而,没有 RADIUS 身份验è¯è®¾ç½®ã€‚用户ä¸èƒ½è¿›è¡Œèº«ä»½éªŒè¯ã€‚
+LH_KERNEL_MODE_START æ®æ£€æµ‹ï¼ŒSecureNAT çš„å†…æ ¸æ¨¡å¼ NAT å¯ä»¥åœ¨æŽ¥å£ "%S" 上è¿è¡Œã€‚å†…æ ¸æ¨¡å¼ NAT 开始。 TCPã€UDP å’Œ ICMP NAT 处ç†å°†æ‰§è¡Œä¸Žé«˜æ€§èƒ½é€šè¿‡ä»¥ä¸‹å†…核模å¼ã€‚å†…æ ¸æ¨¡å¼ NAT å‚数:IP 地å€="%r",å­ç½‘掩ç ="%r",默认网关="%r",广播地å€="%r",虚拟 MAC 地å€ï¼š"%S",DHCP æœåŠ¡å™¨åœ°å€ï¼š"%r",DNSæœåŠ¡å™¨åœ°å€ï¼š"%r"
+LH_KERNEL_MODE_STOP SecureNAT 接å£â€œ%Sâ€çš„å†…æ ¸æ¨¡å¼ NAT å·²åœæ­¢ã€‚
+
+
+# (日志管ç†)
+LA_CONNECTED_1 连接 "%S" 使用æœåŠ¡ç«¯ç®¡ç†å‘˜æ¨¡å¼è¿žæŽ¥ã€‚
+LA_CONNECTED_2 连接 "%S" 使用虚拟 HUB 管ç†å‘˜æ¨¡å¼è¿žæŽ¥ã€‚虚拟 HUB å为 "%S"。
+LA_IP_DENIED 连接 "%S" 试图使用管ç†å‘˜æ¨¡å¼ä»Žä¸€ä¸ªè¢« adminip.txt ç¦æ­¢çš„ IP 地å€è¿žæŽ¥ã€‚断开中。
+LA_ERROR 连接 "%S" 无法使用管ç†å‘˜æ¨¡å¼ç™»å½•ã€‚%s (é”™è¯¯ç  %u)
+LA_OK 连接 "%S" æˆåŠŸä½¿ç”¨ç®¡ç†å‘˜æ¨¡å¼ç™»å½•ã€‚
+LA_RPC_START 连接 "%S" 为管ç†å‘˜æ¨¡å¼æˆåŠŸåˆ›å»ºäº†ä¸€ä¸ªè¿œç¨‹ç¨‹åºå‘¼å«ä¼šè¯ "%S"。
+LA_TAG_1 管ç†æ¨¡å¼ "%S":
+LA_TAG_2 管ç†æ¨¡å¼ "%S" (虚拟 HUB "%S"):
+LA_CREATE_LISTENER 已建立新 TCP 监å¬å™¨ (端å£å· %u)。
+LA_DELETE_LISTENER 已删除 TCP 监å¬å™¨ (端å£å· %u)。
+LA_ENABLE_LISTENER å·²å¯ç”¨ TCP 监å¬å™¨ (端å£å· %u)。
+LA_DISABLE_LISTENER å·²ç¦ç”¨ TCP 监å¬å™¨ (端å£å· %u)。
+LA_SET_SERVER_PASSWORD æœåŠ¡ç«¯ç®¡ç†å‘˜å¯†ç è®¾ç½®å®Œæˆã€‚
+LA_SET_FARM_SETTING 群集设置å˜æ›´å®Œæˆã€‚
+LA_SET_SERVER_CERT æœåŠ¡ç«¯è¯ä¹¦è®¾å®šå®Œæˆã€‚
+LA_REGENERATE_SERVER_CERT æœåŠ¡å™¨è¯ä¹¦å†æ¬¡ç”Ÿæˆã€‚æ–° CN:"%S"
+LA_SET_SERVER_CIPHER æœåŠ¡ç«¯çš„新加密算法å设定完æˆã€‚新加密算法为 "%S"。
+LA_CREATE_HUB 已创建新虚拟 HUB "%S"。
+LA_SET_HUB å·²å˜æ›´è™šæ‹Ÿ HUB 设置。
+LA_DELETE_HUB 已删除虚拟 HUB "%S"。
+LA_SET_HUB_RADIUS å·²å˜æ›´è™šæ‹Ÿ HUB 外部 RADIUS 认è¯æœåŠ¡å™¨è®¾ç½®ã€‚
+LA_DISCONNECT_CONN 连接到æœåŠ¡ç«¯çš„客户端连接 "%S" 已被强制断开。
+LA_SET_HUB_ONLINE 虚拟 HUB 现在在线。
+LA_SET_HUB_OFFLINE 虚拟 HUB 现在离线。
+LA_SET_SNAT_OPTION 已设置 SecureNAT 选项。
+LA_ENABLE_SNAT å·²å¯åŠ¨ SecureNAT 功能。
+LA_DISABLE_SNAT å·²ç¦ç”¨ SecureNAT 功能。
+LA_SET_HUB_LOG å·²å˜æ›´æ—¥å¿—ä¿å­˜è®¾ç½®ã€‚
+LA_ADD_CA 已注册信任的根è¯ä¹¦ã€‚
+LA_DELETE_CA 已删除信任的根è¯ä¹¦ã€‚
+LA_CREATE_LINK 已添加级è”连接 "%s"。
+LA_SET_LINK å·²å˜æ›´çº§è”连接 "%s" 设置。
+LA_SET_LINK_ONLINE 级è”连接 "%s" 现在在线。
+LA_SET_LINK_OFFLINE 级è”连接 "%s" 现在离线。
+LA_DELETE_LINK 已删除级è”连接 "%s"。
+LA_RENAME_LINK 级è”连接 "%s" å称已更改 "%s"。
+LA_ADD_ACCESS 已添加访问列表。
+LA_DELETE_ACCESS 已删除访问列表。
+LA_SET_ACCESS_LIST å·²æ›´æ–°è®¿é—®åˆ—è¡¨ã€‚å®Œæˆ %u 个访问列表项设定。
+LA_SET_AC_LIST å·²æ›´æ–°æº IP 地å€é™åˆ¶åˆ—表。已设定 %u 个规则项目。
+LA_CREATE_USER 已创建用户 "%S"。
+LA_SET_USER 已更新用户 "%S" 的设置。
+LA_DELETE_USER 已删除用户 "%S"。
+LA_CREATE_GROUP 已创建组 "%S"。
+LA_SET_GROUP 已更新组 "%S" 的设置。
+LA_DELETE_GROUP 已删除组 "%S"。
+LA_DELETE_SESSION ä¼šè¯ "%S" 被强制断开。
+LA_SET_KEEP 已更新æœåŠ¡ç«¯çš„ Internet 连接维æŒè®¾ç½®ã€‚
+LA_SET_SYSLOG 已更新æœåŠ¡ç«¯çš„ syslog å‘é€åŠŸèƒ½è®¾ç½®ã€‚
+LA_DELETE_BRIDGE 已删除本地桥接定义 "%S" --> "%S"。
+LA_ADD_BRIDGE 已添加本地桥接定义 "%S" --> "%S"。
+LA_REBOOT_SERVER 请é‡æ–°å¯åŠ¨ VPN Server。
+LA_GET_CONFIG 已读å–é…置文件。
+LA_SET_CONFIG 已写入é…置文件。VPN Server é‡å¯ä¸­ã€‚
+LA_SET_HUB_ADMIN_OPTION 已设定虚拟 HUB "%S" 的管ç†é€‰é¡¹ã€‚
+LA_SET_HUB_EXT_OPTION 已设定虚拟 HUB %S" 的虚拟 HUB 扩展选项。
+LA_ADD_L3_SW 虚拟 3 层交æ¢æœº "%S" 已在æœåŠ¡ç«¯ä¸Šåˆ›å»ºã€‚
+LA_DEL_L3_SW 虚拟 3 层交æ¢æœº "%S" 已从æœåŠ¡ç«¯ä¸Šåˆ é™¤ã€‚
+LA_START_L3_SW å·²å¯åŠ¨è™šæ‹Ÿ 3 层交æ¢æœº "%S"。
+LA_STOP_L3_SW å·²åœæ­¢è™šæ‹Ÿ 3 层交æ¢æœº "%S"。
+LA_ADD_L3_IF 虚拟 HUB "%S" 的虚拟接å£å·²è¢«æ·»åŠ åˆ°è™šæ‹Ÿ 3 层交æ¢æœº "%S"。
+LA_DEL_L3_IF 虚拟 HUB "%S" 的虚拟接å£å·²ä»Žè™šæ‹Ÿ 3 层交æ¢æœº "%S" 中删除。
+LA_ADD_L3_TABLE 网络 "%S" 的路由表已被添加到虚拟 3 层交æ¢æœº "%S"。
+LA_DEL_L3_TABLE 网络 "%S" 的路由表已从虚拟 3 层交æ¢æœº "%S" 中删除。
+LA_ADD_CRL è¯ä¹¦è¢«æ·»åŠ åˆ°è¯ä¹¦æ— æ•ˆåˆ—表。
+LA_DEL_CRL è¯ä¹¦å·²åœ¨è¯ä¹¦æ— æ•ˆåˆ—表中被编辑。
+LA_SET_CRL 已编辑无效è¯ä¹¦åˆ—表的已注册的注册项目。
+LA_READ_LOG_FILE 已下载æœåŠ¡ç«¯ "%S" (日志文件 "%S") 上的日志文件。
+LA_ADD_LICENSE_KEY 已注册新的许å¯è¯å¯†é’¥ "%S"。
+LA_DEL_LICENSE_KEY 已删除现存许å¯è¯ (%u å·)。
+LA_SET_IPSEC_CONFIG IPsec æœåŠ¡å™¨è®¾ç½®æ˜¯æ›´æ–°çš„。
+LA_ADD_ETHERIP_ID EtherIP / L2TPv3 æœåŠ¡å™¨è®¾ç½® (ID="%S") 已添加。
+LA_DEL_ETHERIP_ID EtherIP / L2TPv3 æœåŠ¡å™¨ (ID="%S") 设置已删除。
+
+LA_SET_OVPN_SSTP_CONFIG OpenVPN 和 MS-SSTP VPN Server 设置已更新。
+LA_DDNS_HOSTNAME_CHANGED åŠ¨æ€ DNS 功能的主机å已更改为 "%S".
+LA_SET_SPECIAL_LISTENER 特殊监å¬å™¨å¯ç”¨/ç¦ç”¨çŠ¶æ€å·²å˜æ›´ã€‚
+
+
+# (客户端日志)
+LC_START_1 å·²å¯åŠ¨ SoftEther VPN Client 引擎。
+LC_START_2 %S %S
+LC_START_3 %S
+LC_END 已关闭 SoftEther VPN Client 引擎。
+LC_LOAD_CONFIG_1 加载é…置文件。
+LC_LOAD_CONFIG_2 é…置文件已已加载。
+LC_LOAD_CONFIG_3 é…置文件ä¸å­˜åœ¨ã€‚请应用åˆå§‹è®¾ç½®ã€‚
+LC_NEW_ACCOUNT 已建立新 VPN 连接设置 "%s"。
+LC_DELETE_ACCOUNT 已删除 VPN 连接设置 "%s"。
+LC_RENAME_ACCOUNT å·²å˜æ›´ VPN 连接设置å "%s" 为 "%s"。
+LC_CONNECT 已开始 VPN 连接设置 "%s" 的连接处ç†ã€‚
+LC_CONNECT_1 VPN 连接设置 "%s": 第 %u 次连接æ“作开始。
+LC_CONNECT_2 VPN 连接设置 "%s": 连接完æˆã€‚会è¯å: "%S"。
+LC_CONNECT_ERROR VPN 连接设置 "%s": 连接断开或连接失败。原因: %s (ä»£ç  %u)
+LC_DISCONNECT VPN 连接设置 "%s" 断开中。
+LC_CREATE_VLAN 已创建虚拟网络适é…器 "%S"。
+LC_UPDATE_VLAN å·²é‡è£…虚拟网络适é…器 "%S" 驱动。
+LC_DELETE_VLAN 已删除虚拟网络适é…器 "%S"。
+LC_SET_PASSWORD 连接到客户端æœåŠ¡çš„密ç è®¾ç½®å·²å˜æ›´ã€‚
+LC_TAP_NOT_FOUND 无法找到 tun/tap 的 Mac OS X 驱动。请安装 tun/tap 驱动。
+
+#(删除日志)
+LE_START 正在监控目录 "%S"。如果å¯ç”¨ç£ç›˜ç©ºé—´å˜å¾—å°äºŽ %S,此目录和其å­ç›®å½•ä¸‹çš„日志文件和é…置文件的备份文件将按照从旧到新的顺åºè¢«è‡ªåŠ¨åˆ é™¤ã€‚决定何时开始删除的å¯ç”¨ç£ç›˜ç©ºé—´å¤§å°ï¼Œå¯ä»¥åœ¨é…置文件的“AutoDeletCheckDiskFreeSpaceMinâ€é¡¹ç›®ä¸­ä¿®æ”¹ã€‚
+LE_DELETE å¯ç”¨ç£ç›˜ç©ºé—´å·²å°äºŽ %S,因此旧文件 "%S" 被自动删除。决定何时开始删除的å¯ç”¨ç£ç›˜ç©ºé—´å¤§å°ï¼Œå¯ä»¥åœ¨é…置文件的“AutoDeletCheckDiskFreeSpaceMinâ€é¡¹ç›®ä¸­ä¿®æ”¹ã€‚
+LE_NOT_ENOUGH_FREE <<警告>> 如果å¯ç”¨ç£ç›˜ç©ºé—´å°äºŽ %S,将ä¸èƒ½è‡ªåŠ¨åˆ é™¤æ—¥å¿—文件和é…置文件的旧备份文件。我们建议您å³åˆ»ä»Žæ¬¡è®¡ç®—机上手动删除ä¸å¿…è¦çš„文件æ¥æ¢å¤å¯ç”¨ç£ç›˜ç©ºé—´ã€‚当å¯ç”¨ç£ç›˜ç©ºé—´è¿‡å°æ—¶ï¼Œè®¡ç®—机è¿è¡Œå°†è¢«å˜å¾—ä¸ç¨³å®šã€‚
+
+# (三层交æ¢æœºæ—¥å¿—)
+L3_SWITCH_START å·²å¯åŠ¨è™šæ‹Ÿ 3 层交æ¢æœº "%S"。直到此交æ¢æœºä¸Šæ‰€æœ‰æ³¨å†ŒæŽ¥å£çš„虚拟 HUB 都在线åŽï¼Œå®ƒæ‰å¼€å§‹å·¥ä½œã€‚
+L3_SWITCH_ONLINE 虚拟 3 层交æ¢æœº "%S" 所有接å£çš„虚拟 HUB 在线,且虚拟 3 层交æ¢æœºå·²å¼€å§‹è™šæ‹Ÿ 3 层交æ¢å·¥ä½œã€‚
+L3_SWITCH_OFFLINE 虚拟 3 层交æ¢æœº "%S" 上至少有一个接å£çš„虚拟 HUB åœæ­¢å·¥ä½œï¼Œåˆ™è™šæ‹Ÿ 3 层交æ¢æœºåœæ­¢å·¥ä½œã€‚
+L3_SWITCH_STOP 虚拟 3 层交æ¢æœº "%S" 终止。
+
+
+#关于Microsoft.c
+MS_ETHERNET 以太网接å£
+MS_TOKENRING 令牌环接å£
+MS_FDDI FDDI 接å£
+MS_PPP PPP (拨å·æˆ– VPN)
+MS_LOOPBACK 环回接å£
+MS_SLIP SLIP 接å£
+MS_WLAN 无线网络适é…器
+MS_OTHER 未知其它接å£
+MS_NON_OPERATIONAL 无效
+MS_UNREACHABLE 未连接
+MS_DISCONNECTED 未连接
+MS_CONNECTING 连接中
+MS_CONNECTED 已连接
+MS_OPERATIONAL 已连接
+
+
+# 关于网络实用工具
+UT_SM_COLUMN_1 项目å
+UT_SM_COLUMN_2 值
+UT_SM_ST_TITLE 网络适é…器的å称
+UT_SM_ST_GUID å…¨çƒå”¯ä¸€æ ‡è¯†ç¬¦(GUID)
+UT_SM_ST_TYPE 类型
+UT_SM_ST_TYPE2 有线网络适é…器
+UT_SM_ST_STATUS 状æ€
+UT_SM_ST_MTU MTU
+UT_SM_ST_SPEED 链接速度
+UT_SM_ST_ADDRESS 物ç†åœ°å€
+UT_SM_ST_RECV_BYTES 接收的字节数
+UT_SM_ST_RECV_BCASTS 接收广播数æ®åŒ…æ•°
+UT_SM_ST_RECV_UNICASTS 接收å•æ’­åŒ…æ•°
+UT_SM_ST_SEND_BYTES å‘é€å­—节数
+UT_SM_ST_SEND_BCASTS å‘é€å¹¿æ’­æ•°æ®åŒ…æ•°
+UT_SM_ST_SEND_UNICASTS å‘é€å•æ’­åŒ…æ•°
+UT_SM_ST_IP IP åœ°å€ %u
+UT_SM_ST_SUBNET å­ç½‘æŽ©ç  %u
+UT_SM_ST_GATEWAY 网关 %u
+UT_SM_ST_DHCP DHCP æœåŠ¡å™¨
+UT_SM_ST_DHCP_1 租èµå¼€å§‹æ—¥æœŸ
+UT_SM_ST_DHCP_2 租èµåˆ°æœŸæ—¥æœŸ
+UT_SM_ST_WINS_1 WINS æœåŠ¡å™¨ 1
+UT_SM_ST_WINS_2 WINS æœåŠ¡å™¨ 2
+
+
+# 关于以太网记录器管ç†å™¨
+EM_TITLE SoftEther 以太网记录器管ç†å™¨
+EM_REMOTE_TITLE 您å¯ä»¥è¿žæŽ¥å¹¶ç®¡ç† SoftEther 以太网记录器æœåŠ¡ã€‚\r\n输入以太网记录器æœåŠ¡è¿›è¡Œç®¡ç†çš„计算机上è¿è¡Œçš„主机åå’Œ IP 地å€ã€‚您也å¯ä»¥é€šè¿‡ä½¿ç”¨â€œ:â€(冒å·)连接端å£å·ã€‚
+EM_MAIN_COLUMN_1 网络适é…器å
+EM_MAIN_COLUMN_2 状æ€
+EM_MAIN_OK æ“作中
+EM_MAIN_ERROR 错误
+EM_ADD_NEW 添加新æ•èŽ·çš„设备
+EM_ADD_EDIT 编辑æ•æ‰è®¾ç½®
+EM_DELETE_CONFIRM 您确定您è¦åˆ é™¤æ•æ‰è®¾ç½® "%S" å—?
+EM_NO_LICENSE_COLUMN 注æ„:
+EM_NO_LICENSE 因为甚至没有一个产å“许å¯è¯è¢«æ³¨å†Œï¼Œæ­¤ SoftEther 以太网记录器将无法æ“作。
+
+EM_UNSUPPORTED ç¦ç”¨åœ¨æ­¤æ“作系统上正在è¿è¡Œçš„ SoftEther 以太网记录器。对于 SoftEther 以太网记录器å¯ä»¥ä½¿ç”¨çš„列表,请å‚阅 SoftEther 以太网记录器的在线文档。
+EM_WPCAP_REMOTE 为了使用 SoftEther 以太网记录器,你需è¦å®‰è£…WinPcap软件。WinPcap 软件目å‰åœ¨æœåŠ¡å™¨è®¡ç®—机上没有安装。\r\n\r\nè¦ç»§ç»­å®‰è£… WinPcap 软件,你必须开å¯æ­£åœ¨è¿è¡Œ VPN Server çš„é‚£å°æœåŠ¡å™¨è®¡ç®—机上的 SoftEther 以太网记录器管ç†å™¨ï¼Œç„¶åŽå†è¿žæŽ¥åˆ°æœ¬åœ°ä¸»æœº(您自己的计算机的ä½ç½®),会显示本地桥功能设置窗å£ã€‚ \r\nè¦ç»§ç»­ï¼Œé¦–先退出管ç†ä¼šè¯ï¼Œç„¶åŽï¼Œåœ¨æœåŠ¡å™¨è®¡ç®—机上å¯åŠ¨ SoftEther 以太网记录器管ç†å™¨ä¹‹åŽï¼Œè¿žæŽ¥åˆ°æœ¬åœ°ä¸»æœºï¼Œå¹¶ç»§ç»­è®¾ç½®è¿‡ç¨‹ã€‚
+EM_WPCAP_ROOT 为了使用 SoftEther 以太网记录器,你需è¦å®‰è£…WinPcap软件。 \r\n\r\nè¦ç»§ç»­å®‰è£…,您必须具有管ç†å‘˜æƒé™ä½œä¸ºç”¨æˆ·ç™»å½•åˆ°è¿™å°è®¡ç®—机。\r\n作为管ç†å‘˜ç™»å½•ï¼Œé‡æ–°å¯åŠ¨ SoftEther VPN Server 管ç†å™¨ã€‚
+EM_WPCAP_INSTALL 为了使用 SoftEther 以太网记录器,你需è¦å®‰è£…WinPcap软件。WinPcap 软件目å‰åœ¨æœåŠ¡å™¨è®¡ç®—机上没有安装。 \r\n\r\nWinPcap 是一个易于安装的å…费软件,与 VPN Server æ†ç»‘在一起。\r\n\r\n您è¦å¼€å§‹å®‰è£… WinPcap å—?
+EM_WPCAP_REBOOT1 在 WinPcap 安装完æˆåŽï¼Œåœ¨ä½¿ç”¨ SoftEther 以太网记录器å‰ï¼Œä½ å¿…é¡»é‡æ–°å¯åŠ¨è®¡ç®—机。\r\n\r\n在您手动é‡æ–°å¯åŠ¨è®¡ç®—机和 SoftEther 以太网记录器åŽï¼Œé‡æ–°é…置设置。
+EM_WPCAP_REBOOT2 在 WinPcap 安装åŽï¼Œä½ å¿…é¡»é‡æ–°å¯åŠ¨ SoftEther 以太网记录器æœåŠ¡ã€‚ \r\n\r\n它仅需è¦å¾ˆçŸ­çš„时间é‡æ–°å¯åŠ¨ SoftEther 以太网记录器æœåŠ¡ï¼Œä½†æ˜¯æ‰€æœ‰å½“å‰è¿žæŽ¥åˆ° SoftEther 以太网记录器的管ç†ä¼šè¯å°†è¢«æ–­å¼€ã€‚ \r\n此管ç†ä¼šè¯ä¹Ÿå°†è¢«æ–­å¼€ï¼Œå› æ­¤æ‚¨éœ€è¦é‡æ–°è¿žæŽ¥å¹¶ç»§ç»­ã€‚\r\n\r\n您是è¦é‡æ–°å¯åŠ¨ SoftEther 以太网记录器æœåŠ¡å—?
+EM_RESOURCE æ— æ³•è¯»å– WinPcap 驱动
+
+
+###########################################################################
+# #
+# åœ¨è½¯ä»¶æ¡†ä¸­çš„å­—ç¬¦ä¸²æ•°æ® #
+# #
+###########################################################################
+
+
+PREFIX D_SECURE
+CAPTION %s - %S 的访问
+S_TITLE %S 的访问
+S_DEVICE_INFO 设备å称: %S\r\n制造商: %S
+IDS_STATIC1 设备信æ¯
+S_WARNING è¦å°å¿ƒè¾“å…¥ PIN ç ï¼Œå› ä¸ºå¦‚果你错误地输入了几次,设备将被é”定。
+IDOK &OK
+IDCANCEL å–消
+S_PIN_CODE &PIN ç :
+
+
+PREFIX D_PKCSUTIL
+CAPTION PKCS#12 写入工具
+S_TITLE ePass 1000 USB 令牌 PKCS#12 写入工具
+STATIC1 通过使用此工具,您å¯ä»¥å°†æ‚¨é€‰æ‹©çš„ PKCS#12 文件(è¯ä¹¦æ–‡ä»¶)写入 ePass 1000 USB 硬件安全令牌。\r\n\r\n写入è¯ä¹¦æ–‡ä»¶çš„ USB å¯ä»¥ç”¨äºŽ SoftEther VPN 的身份验è¯ã€‚
+STATIC2 写入 PKCS#12 文件
+STATIC3 è¦å°†ä¸€ä¸ªçŽ°æœ‰çš„ PKCS#12 文件写入 USB 令牌,å•å‡»â€œå†™å…¥â€ã€‚\r\n注æ„: 如果 USB 令牌中已ç»å­˜å‚¨äº† SoftEther VPN çš„ PKCS#12 è¯ä¹¦ï¼Œåˆ™å·²å­˜å‚¨çš„文件将被覆盖。
+B_WRITE 写入(&W)
+STATIC4 从 USB 令牌擦除 PKCS#12 è¯ä¹¦ã€‚
+STATIC5 您å¯ä»¥ä»Žå·²å­˜å‚¨ SoftEther VPN PKCS#12 è¯ä¹¦çš„ USB 令牌擦除è¯ä¹¦æ•°æ®ã€‚
+B_ERASE 擦除(&E)
+IDCANCEL 退出工具(&X)
+S_COPYRIGHT Copyright (c) SoftEther VPN Project.\r\nAll Rights Reserved.
+
+
+PREFIX D_PASSPHRASE
+CAPTION ç§äººå¯†é’¥å¯†ç 
+STATIC1 æ­¤ç§äººå¯†é’¥è¢«å¯†ç ä¿æŠ¤ã€‚\r\n\r\n输入密ç æ–¹å¯è¯»å–密钥。
+STATIC2 密ç (&P):
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_NM_CONNECT
+CAPTION 连接到 SoftEther VPN 用户模å¼è·¯ç”±å™¨
+S_TITLE 正在连接 %S ...
+
+
+PREFIX D_PASSWORD
+CAPTION 登录到 %S
+S_TITLE 请输入您的用户å和密ç ä»¥ç™»å½•åˆ°æœåŠ¡ç«¯ "%S"。确定您选择了正确的认è¯ç±»åž‹ã€‚
+STATIC1 输入用户信æ¯(&R):
+STATIC2 账户类型(&T):
+STATIC3 用户å(&N):
+STATIC4 密ç (&P):
+R_NO_SAVE_PASSWORD ä¸ä¿å­˜å¯†ç (&D):
+S_COUNTDOWN %u 秒åŽè‡ªåŠ¨é‡è¿ž...
+IDOK &OK
+IDCANCEL 连接å–消
+
+
+PREFIX D_STATUS
+CAPTION 正在连接 %s ...
+S_STATUS åˆå§‹åŒ–中...
+IDCANCEL å–消
+
+
+PREFIX D_CERT
+CAPTION è¯ä¹¦
+S_TITLE æ­¤è¯ä¹¦çš„ä¿¡æ¯å¦‚下。
+STATIC1 æ­¤è¯ä¹¦çš„基本信æ¯:
+STATIC2 å‘ç»™:
+STATIC3 å‘行人:
+STATIC4 有效期é™:
+STATIC5 æ­¤è¯ä¹¦çš„高级信æ¯:
+STATIC6 签署此è¯ä¹¦çš„当局的è¯ä¹¦ï¼š
+S_PARENT 签署此è¯ä¹¦çš„è¯ä¹¦å½“局的è¯ä¹¦å·²åœ¨å¯ä¿¡è¯ä¹¦åˆ—表上注册。
+S_PARENT_BUTTON_STR 查看è¯ä¹¦(&V)
+IDCANCEL &OK
+B_SAVE ä¿å­˜æ–‡ä»¶(&S)
+
+
+PREFIX D_CHECKCERT
+CAPTION 安全警告 - %s
+S_TITLE 你正在连接到的目标 VPN Server “%Sâ€çš„连接是加密的,但由æœåŠ¡å™¨æ供的æœåŠ¡å™¨è¯ä¹¦çš„å¯ä¿¡åº¦æ˜¯æœªçŸ¥çš„。
+STATIC1 关于æœåŠ¡å™¨è¯ä¹¦
+STATIC2 正在 VPN Server å’Œ VPN Client 之间建立加密通é“(SSL 会è¯)。检查æœåŠ¡å™¨è¯ä¹¦å¯ä»¥éªŒè¯æœåŠ¡å™¨çš„å¯é æ€§ã€‚
+S_MSG1 目标 VPN Server "%S" æ供的æœåŠ¡ç«¯è¯ä¹¦å¦‚下。
+STATIC3 å‘ç»™:
+STATIC4 å‘行人:
+STATIC5 有效期é™:
+B_SHOW 查看è¯ä¹¦(&S)
+STATIC6 摘è¦(MD5):
+STATIC7 摘è¦(SHA-1):
+IDOK æ¢å¤è¿žæŽ¥(&R)
+IDCANCEL å–消连接(&C)
+STATIC8 æ­¤è¯ä¹¦å¯èƒ½æœ‰é—®é¢˜ï¼Œä¾‹å¦‚它ä¸æ˜¯æœ‰å¯ä¿¡ç­¾å‘å•ä½ç­¾å‘,或è¯ä¹¦å·²è¿‡æœŸã€‚
+STATIC9 请确认此è¯ä¹¦å†…容,并决定是å¦è¿žæŽ¥åˆ°æ­¤ VPN Server。å•å‡»â€œå–消连接â€æ¥ä¸­æ­¢è¿žæŽ¥ã€‚
+
+
+PREFIX D_CONNECTERROR
+CAPTION 连接错误 - %s
+S_TITLE 连接到 VPN Server "%S" æ—¶å‘生错误。
+S_COUNTDOWN %u 秒åŽè‡ªåŠ¨é‡è¿ž...
+IDOK é‡è¯•(&R)
+IDCANCEL 连接å–消
+R_HIDE 下次连接时éšè—此窗å£(&H)
+
+
+PREFIX D_CM_LOGIN
+CAPTION è¾“å…¥å¯†ç  - VPN Client 管ç†å™¨
+S_TITLE 您必须输入客户端管ç†å¯†ç æ¥ä½¿ç”¨è¿è¡Œåœ¨ %s 上的 VPN Client。输入客户端管ç†å¯†ç ã€‚
+STATIC1 密ç (&P):
+STATIC2 输入客户端管ç†å¯†ç :
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_CONNECTION_STATUS
+S_TITLE %s VPN 会è¯çš„çŠ¶æ€ (实时)
+B_POLICY 安全策略(&P)...
+B_SERVER_CERT æœåŠ¡ç«¯è¯ä¹¦(&S)
+B_CLIENT_CERT 客户端è¯ä¹¦(&C)
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_CM_POLICY
+CAPTION 安全策略列表
+S_TITLE 为当å‰ä¼šè¯ %s 定义的安全策略
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_CM_ACCOUNT
+STATIC1 请为 VPN Server é…ç½® VPN 连接设置。
+S_ACCOUNT_NAME 连接设置å(&N):
+STATIC2 目标 VPN Server (&B):
+STATIC3 指定目标 VPN Server 上的主机å或 IP 地å€ï¼Œç«¯å£å·å’Œè™šæ‹Ÿ HUB å。
+STATIC4 主机å(&H):
+STATIC5 端å£å·(&P):
+STATIC6 (TCP 端å£)
+STATIC7 虚拟 HUB å(&V):
+STATIC8 中继代ç†æœåŠ¡å™¨(&X):
+STATIC9 您å¯ä»¥é€šè¿‡ä»£ç†æœåŠ¡å™¨è¿žæŽ¥åˆ° VPN Server。
+STATIC10 代ç†ç±»åž‹(&T):
+R_DIRECT_TCP 直接 TCP/IP 连接(无代ç†)(&D)
+R_HTTPS 通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥(&T)
+R_SOCKS 通过 SOCKS 代ç†æœåŠ¡å™¨è¿žæŽ¥(&S)
+B_PROXY_CONFIG 代ç†æœåŠ¡å™¨è®¾ç½®(&R)
+STATIC11 æœåŠ¡ç«¯è¯ä¹¦éªŒè¯é€‰é¡¹(&F):
+R_CHECK_CERT 总是验è¯æœåŠ¡ç«¯è¯ä¹¦(&C)
+B_TRUST 管ç†å¯ä¿¡å‘è¯æœºå…³è¯ä¹¦åˆ—表(&C)
+B_SERVER_CERT 指定特定è¯ä¹¦(&S)
+B_VIEW_SERVER_CERT 查看特定è¯ä¹¦(&V)
+S_VLAN_GROUP 使用虚拟网络适é…器(&L):
+S_POLICY_1 您å¯ä»¥é…置将应用到级è”虚拟 HUB 侧的安全策略。
+B_POLICY 安全策略(&L)
+STATIC12 用户认è¯è®¾ç½®(&A):
+STATIC13 认è¯ç±»åž‹(&T):
+S_USERNAME 用户å(&U):
+S_PASSWORD 密ç (&Y):
+S_CERT_INFO 您必须为用户认è¯æŒ‡å®šä¸€ä¸ªå®¢æˆ·ç«¯è¯ä¹¦ã€‚
+STATIC14 通信的高级设置(&E):
+R_RETRY æ–­å¼€åŽè‡ªåŠ¨é‡è¿ž(&Z)
+S_RETRY_NUM_1 é‡è¿žæ¬¡æ•°(&C):
+S_RETRY_NUM_2 次
+S_RETRY_SPAN_1 é‡è¿žé—´éš”(&K):
+S_RETRY_SPAN_2 秒
+R_INFINITE æ— é™é‡è¿ž(总是ä¿æŒ VPN 在线) (&I)
+R_NOTLS1 ä¸è¦ä½¿ç”¨ TLS &1.0
+B_DETAIL 高级设置(&D)...
+IDOK &OK
+IDCANCEL å–消
+B_CHANGE_PASSWORD å˜æ›´å¯†ç (&P)
+S_CHANGE_PASSWORD 您å¯ä»¥åœ¨ VPN Server 上更改用户密ç ã€‚
+R_HIDE éšè—和错误窗å£(&D)
+R_HIDE2 éšè— IP 地å€å±å¹•(&O)
+STATIC15 请设置连接到 VPN Server 时需è¦çš„用户认è¯ä¿¡æ¯ã€‚
+B_REGIST_CLIENT_CERT 指定客户端è¯ä¹¦(&C)
+B_IE 导入I&E代ç†æœåŠ¡å™¨è®¾ç½®
+
+
+PREFIX D_CM_PROXY
+CAPTION 代ç†æœåŠ¡å™¨è¿žæŽ¥è®¾ç½®
+STATIC1 输入中继代ç†æœåŠ¡å™¨ (HTTP 代ç†æˆ– SOCKS 代ç†) 的主机å,IP 地å€ï¼Œç«¯å£ï¼Œå¦‚果需è¦ï¼Œè¯·è¾“入用户å和密ç ã€‚
+STATIC2 主机å(&H):
+STATIC3 端å£(&A):
+STATIC4 用户å(&U):
+STATIC5 密ç (&P):
+IDOK &OK
+IDCANCEL å–消
+STATIC6 (å¯é€‰)
+STATIC7 (å¯é€‰)
+
+
+PREFIX D_CM_DETAIL
+CAPTION 高级设置
+STATIC1 为系统管ç†å‘˜ï¼Œå’Œåœ¨ç½‘络,通信å议,安全方é¢æœ‰ä¸€å®šäº†è§£çš„用户æ供了å¯é€‰æ‹©çš„设置。å¯ä»¥ç”±æ­¤æ¥è‡ªå®šä¹‰ VPN 通信å议设置。为系统管ç†å‘˜å’Œä¸“家在网络ã€é€šä¿¡å议和安全方é¢æä¾›å¯é€‰è®¾ç½®ã€‚自定义 VPN å议的通信设置。
+STATIC2 VPN 通信的最优化(&T):
+STATIC3 ä½¿ç”¨å¤šä¸ªç‰©ç† TCP 连接èšåˆä¸ºä¸€ä¸ªé€»è¾‘ VPN 连接,以æ高通信åžåé‡ã€‚
+STATIC4 TCP 连接数(&N):
+STATIC5 连接数
+STATIC6 ※ 注æ„: 建议宽带线路开 8 个连接,低速线路开 1 个连接 (例如拨å·)。
+STATIC7 高级设置:
+STATIC8 建立间隔(&S):
+STATIC9 秒
+R_USE_DISCONNECT 设置æ¯ä¸ª TCP 的连接寿命(&A)
+STATIC10 寿命(&P):
+STATIC11 秒
+STATIC12 当使用两个或以上 TCP 连接时,å¯ä»¥ä½¿ç”¨â€œåŠåŒå·¥æ¨¡å¼â€ã€‚åŠåŒå·¥æ¨¡å¼ä¸‹ä¿®å¤æ•°æ®æ–¹å‘,æ¯ä¸ª TCP 连接å¯ä»¥å‘åŒæ–¹ä¼ é€ä¸€åŠçš„æ•°æ®ã€‚例如,当使用 8 个 TCP 连接建立一个 VPN 时,物ç†çš„ VPN 隧é“将是固定的,因此,4 个 TCP 连接专用上传方å‘,而其他 4 个连接专用下载方å‘。
+R_USE_HALF_CONNECTION 使用åŠåŒå·¥æ¨¡å¼(&H)
+STATIC13 加密和压缩(&C):
+STATIC14 通常 VPN 会è¯ä¸ºå®‰å…¨èµ·è§ä¼šè¢«åŠ å¯†ã€‚您也å¯ä»¥ç¦ç”¨åŠ å¯†æ¥æ高åžåé‡ã€‚请注æ„ç¦ç”¨åŠ å¯†æƒ…况下,数æ®åœ¨ç½‘络上是以明文方å¼ä¼ è¾“的。
+R_USE_ENCRYPT 使用 SSL 加密 VPN 会è¯(&E)
+STATIC15 您å¯ä»¥ä½¿ç”¨æ•°æ®åŽ‹ç¼©æ¥ä¿å­˜ VPN 通信带宽。当使用较慢的连接时,如拨å·æˆ–移动连接,å¯ç”¨æ­¤é€‰é¡¹ã€‚
+R_DISABLE_UDP ç¦ç”¨ UDP 加速功能功能(&P)
+R_USE_COMPRESS 使用数æ®åŽ‹ç¼©(&U)
+STATIC16 连接模å¼è®¾ç½®(&M):
+S_MODE 您å¯ä»¥æŒ‡å®šå¦‚下连接模å¼ã€‚(网络管ç†å‘˜é€‰æ‹©ã€‚)
+R_BRIDGE 网桥/路由器模å¼(&B)
+R_MONITOR 监控模å¼(&D)
+STATIC17 其它é…ç½®(&G):
+R_NO_ROUTING ä¸è¦è°ƒæ•´è·¯ç”±è¡¨(&R)
+STATIC18 除éžå¾—到系统管ç†å‘˜çš„åŒæ„,或你有网络和安全方é¢çš„专业知识,请ä¿æŒæ­¤å¯¹è¯æ¡†çš„默认设置。
+STATIC19 VoIP / QoS 功能å¯ä»¥å¤„ç†é«˜ä¼˜å…ˆçº§æ•°æ®åŒ…,如 IP 电è¯æ•°æ®åŒ…(VoIP)å¯ä»¥è¢«ä¼ è¾“的更快。
+R_DISABLE_QOS ç¦ç”¨ VoIP / &QoS 功能
+IDOK &OK
+IDCANCEL å–消
+S_UDPACCEL 您å¯ä»¥ä½¿ç”¨æ•°æ®åŽ‹ç¼©ä»¥èŠ‚çœ VPN 通信带宽。当使用慢速连接时,如拨å·æˆ–移动连接,å¯ç”¨æ­¤é€‰é¡¹ã€‚
+
+
+PREFIX D_CM_NEW_VLAN
+CAPTION 创建新虚拟网络适é…器
+S_INFO 一个新虚拟网络适é…器将被被创建到系统中。\r\n您å¯ä»¥ä¸ºæ­¤è™šæ‹Ÿç½‘络适é…器指定最长ä¸è¶…过 %u 个字æ¯å’Œæ•°å­—çš„å称。
+STATIC1 虚拟网络适é…器å(&N):
+IDOK &OK
+IDCANCEL å–消
+S_WIN8 正在è¿è¡Œçš„æ“作系统是 Windows8。请注明 "VPN" 或 "VPN2" 直到 "VPN127" 作为新的虚拟网络适é…器的å称 (最多 127 个适é…器å¯ä»¥è¢«åˆ›å»º)。
+
+
+PREFIX D_CM_TRUST
+CAPTION 管ç†ä¿¡ä»»çš„è¯ä¹¦ç­¾å‘机构的列表
+STATIC1 您å¯ä»¥åœ¨è¿™é‡Œç®¡ç†è®¤è¯æŽˆæƒ(CA)è¯ä¹¦åˆ—表。\r\n\r\n当连接到 VPN Server 时,您å¯ä»¥ä½¿ç”¨åœ¨æ­¤æ³¨å†Œçš„ CA è¯ä¹¦æ¥éªŒè¯æœåŠ¡ç«¯è¯ä¹¦ã€‚
+B_IMPORT 添加(&A)
+B_EXPORT 导出(&E)
+IDOK 查看è¯ä¹¦(&V)
+IDCANCEL 关闭(&C)
+B_DELETE 删除(&D)
+
+
+PREFIX D_CM_PASSWORD
+CAPTION è®¾ç½®å¯†ç  - VPN Client 管ç†å™¨
+S_TITLE 您å¯ä»¥è®¾ç½®å¯†ç æ¥é™åˆ¶æ­¤ SoftEther VPN Client æœåŠ¡ã€‚\r\n设置密ç åŽï¼Œåœ¨ä¸‹æ¬¡ä½¿ç”¨ VPN Client 连接管ç†å™¨åˆ° SoftEther VPN Client æœåŠ¡æ—¶ï¼Œæ‚¨å°†è¢«è¢«è¦æ±‚输入密ç ã€‚
+STATIC1 设置客户端管ç†å¯†ç :
+R_USE_PASSWORD 使用密ç (&U)
+R_REMOTE_ONLY 仅在远程æ“作时需è¦å¯†ç (&R)
+IDC_STATIC1 密ç (&P):
+IDC_STATIC2 确定(&E):
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_CM_CONFIG
+CAPTION å¯é€‰è®¾ç½®
+STATIC1 您å¯ä»¥æ›´æ”¹ VPN Client 的设置
+STATIC2 远程管ç†(&E)
+STATIC3 您å¯ä»¥é€šè¿‡ä½¿ç”¨ VPN Client 管ç†å™¨è¿œç¨‹æ¨¡å¼ä»Žå¦ä¸€å°è®¡ç®—æœºä¸Šè¿œç¨‹ç®¡ç† VPN Client æœåŠ¡ç¨‹åºã€‚
+R_ALLOW_REMOTE_CONFIG å…许 VPN Client æœåŠ¡çš„远程管ç†(&R)
+S_WARNING 建议您在å…许远程管ç†æ—¶è®¾ç½®å¯†ç ã€‚在èœå•é‡Œé€‰æ‹©â€œå·¥å…·â€ >“设置密ç â€æ¥è®¾ç½®å¯†ç ã€‚
+STATIC4 在通讯闲置一段时间åŽè‡ªåŠ¨æ–­å¼€äº’è”网连接的环境下,å¯ä»¥é€šè¿‡å‘互è”网上任æ„主机å‘é€å‡æ•°æ®åŒ…çš„æ–¹å¼æ¥ä¿æŒäº’è”网连接。
+R_USE_KEEP_CONNECT 使用ä¿æŒ Internet 连接功能(&K)
+S_HOSTNAME 主机å(&H):
+S_PORT 端å£å·(&P):
+S_INTERVAL æ•°æ®åŒ…å‘é€é—´éš”(&I):
+S_INTERVAL2 秒æ¯æ•°æ®åŒ…
+S_PROTOCOL åè®®(&O):
+R_TCP TCP/IP åè®®(&T)
+R_UDP UDP/IP åè®®(&U)
+S_INFO å‘é€çš„ä¿æŒäº’è”网连接的数æ®åŒ…大å°éšæœºï¼Œæ— ä¸ªäººä¿¡æ¯è¢«å‘é€ã€‚
+IDOK &OK
+IDCANCEL å–消
+STATIC5 其它é…ç½®(&O)
+R_ALPHA 用户界é¢é€æ˜Ž(&A)
+STATIC6 ※注æ„:é€æ˜Žè®¾ç½®å°†åœ¨è¿žæŽ¥ç®¡ç†å™¨é‡å¯åŽç”Ÿæ•ˆã€‚
+STATIC7 ä¿æŒäº’è”网连接功能(&K)
+
+
+PREFIX D_ABOUT
+S_INFO1 SoftEther VPN %u.0 (Ver %u.%02u, Build %u)
+S_INFO2 An Open-Source VPN Software for Academic Purpose, under the GPLv2 License.\r\nCopyright (c) 2012-%u SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.\r\nWeb Site: http://www.softether.org/\r\n%S
+S_INFO3 This product includes the following software components:\r\nBitVisor: Copyright (c) 2007, 2008 University of Tsukuba. Copyright (C) 2007, 2008 National Institute of Information and Communications Technology. All rights reserved. / Microsoft(R) C Runtime Library: (c) 2007 Microsoft Corporation. All Rights Reserved. / PKCS #11 Cryptographic Token Interface (Cryptoki): Copyright (c) RSA Security Inc. / WinPcap: Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy). All rights reserved. / libedit: Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved. / libiconv: Copyright (C) 2007 Free Software Foundation, Inc. / ncurses: Copyright (c) 1998-2005, 2006 Free Software Foundation, Inc. / OpenSSL: Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). / zlib: (C) 1995-2004 Jean-loup Gailly and Mark Adler. / Special Thanks to: Software Laboratory, Academic Computing Communication Center, Industrial Liaison and Cooperative Research Center and Professor Yasushi Shinjo in University of Tsukuba, Japan.
+S_INFO4 æ­¤ VPN æœåŠ¡å™¨ä½œä¸ºçš„一个学术研究且由 (http://www.softether.org/) 为公众利益å…è´¹å‘布的。本软件是日本筑波大学 SoftEther 项目下开å‘çš„å…费软件,无任何担ä¿ã€‚å¼€å‘人员ã€ç‰ˆæƒæ‰€æœ‰è€…或分销商在任何情况下对于使用本软件的任何索赔ã€æŸå®³èµ”å¿æˆ–其他情况ä¸æ‰¿æ‹…责任。\r\n\r\nSoftEther VPN 是日本政府的研究和开å‘项目的一项工作,由日本的ç»æµŽã€è´¸æ˜“和工业部资助,由信æ¯åŒ–推进机构管ç†ã€‚
+IDCANCEL &OK
+B_WEB 访问 SoftEther VPN 和网站 (&W)...
+B_EULA 最终用户许å¯
+B_IMPORTANT é‡è¦å¯äº‹
+B_LEGAL 法律å¯äº‹
+B_UPDATE_CONFIG é…置更新
+
+
+PREFIX D_REMOTE
+STATIC1 指定目标计算机主机å或 IP 地å€(&S):
+R_LOCAL 连接到本地计算机 (此窗å£ä¸­æ˜¾ç¤ºçš„计算机) (&L)
+S_HOSTNAME 计算机å(&C):
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_CM_DESKTOP
+CAPTION 连接 - %s
+S_TITLE VPN 连接设置 "%s" 的连接进程å¯åŠ¨ä¸­ã€‚
+S_WARNING VPN Client 会将连接到 VPN Server 过程中的连接状æ€å’Œé”™è¯¯ä¿¡æ¯è¾“出到 %s 的“控制å°è¿›ç¨‹â€çª—å£ã€‚
+S_INFO å¯ä»¥ç»§ç»­è¿žæŽ¥å—?
+IDOK 继续(&C)
+IDCANCEL å–消
+
+
+PREFIX D_CM_CHANGE_PASSWORD
+CAPTION 更改密ç 
+S_TITLE 您å¯ä»¥æ›´æ”¹æœåŠ¡ç«¯ %S 上注册的用户密ç ã€‚
+STATIC1 更改密ç (&P)
+STATIC2 虚拟 HUB å(&H):
+STATIC3 用户å(&U):
+STATIC4 旧密ç (&O):
+STATIC5 新密ç (&N):
+STATIC6 确认新密ç (&C):
+IDOK &OK
+IDCANCEL å–消
+S_STATIC ※注æ„: 如果认è¯ç±»åž‹æ˜¯ RADIUS 或 NT 域认è¯ï¼Œæ‚¨ä¸èƒ½æ›´æ”¹ç”¨æˆ·å¯†ç ã€‚
+
+
+PREFIX D_SM_MAIN
+CAPTION SoftEther VPN Server 管ç†å™¨
+STATIC1 SoftEther VPN Server 连接设置(&S):
+STATIC2 VPN Server 或 VPN Bridge 的连接设置被定义如下。åŒå‡»è¯¥é¡¹ä»¥è¿žæŽ¥åˆ°æœåŠ¡ç«¯ã€‚\r\nè¦æ·»åŠ æ–°è¿žæŽ¥ï¼Œå•å‡»â€œæ–°è®¾ç½®â€ã€‚
+B_NEW_SETTING 新设置(&N)
+B_EDIT_SETTING 编辑设置(&E)
+B_DELETE 删除设置(&D)
+IDOK 连接(&C)
+B_SECURE_MANAGER 智能å¡ç®¡ç†å™¨(&S)...
+B_SELECT_SECURE 选择智能å¡(&M)...
+B_ABOUT 版本信æ¯(&A)...
+IDCANCEL 退出 SoftEther VPN Server 管ç†å™¨(&X)
+B_CERT_TOOL 制作è¯ä¹¦
+
+
+
+PREFIX D_SM_EDIT_SETTING
+STATIC1 请é…ç½®è¦ç®¡ç†çš„ VPN Server 或 VPN Bridge 的连接设置
+STATIC2 设置å(&N):
+STATIC3 目标 VPN Server (&B):
+STATIC4 指定目标 VPN Server 的主机å或 IP 地å€ã€ç«¯å£å·å’Œè™šæ‹Ÿ HUB。
+STATIC5 主机å(&H):
+R_LOCALHOST 连接到本地主机(localhost)(&L)
+STATIC6 端å£å·(&P):
+STATIC7 (TCP 端å£)
+STATIC8 中继代ç†æœåŠ¡å™¨(&X):
+STATIC9 您å¯ä»¥é€šè¿‡ä»£ç†æœåŠ¡å™¨è¿žæŽ¥åˆ° VPN Server。
+STATIC10 代ç†ç±»åž‹(&T):
+R_DIRECT_TCP 直接 TCP/IP 连接 (无代ç†) (&D)
+R_HTTPS 通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥(&T)
+R_SOCKS 通过 SOCKS 代ç†æœåŠ¡å™¨è¿žæŽ¥(&O)
+B_PROXY_CONFIG 代ç†æœåŠ¡å™¨è®¾ç½®(&R)
+STATIC11 选择管ç†æ¨¡å¼å¹¶è¾“入密ç (&M)
+STATIC12 您å¯ä»¥ä½¿ç”¨æœåŠ¡ç«¯ç®¡ç†æ¨¡å¼æˆ–虚拟 HUB 管ç†æ¨¡å¼è¿žæŽ¥åˆ° VPN Server。\r\n\r\næœåŠ¡å™¨ç®¡ç†æ¨¡å¼å…许您管ç†æ•´ä¸ª VPN Server 和所有虚拟 HUB 。\r\n\r\n虚拟 HUB 管ç†æ¨¡å¼å…许您åªèƒ½ç®¡ç†æ‚¨æ‹¥æœ‰æƒé™çš„一个虚拟 HUB 。
+R_SERVER_ADMIN æœåŠ¡ç«¯ç®¡ç†æ¨¡å¼(&S)
+R_HUB_ADMIN 虚拟 HUB 管ç†æ¨¡å¼(&U)
+S_HUBNAME 虚拟 HUB å(&V):
+STATIC13 请输入密ç è¿žæŽ¥ç®¡ç†æ¨¡å¼ã€‚
+S_PASSWORD 密ç (&P):
+R_NO_SAVE ä¸ä¿å­˜ç®¡ç†å¯†ç (&S)
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_SM_SERVER
+CAPTION %s - SoftEther VPN Server 管ç†å™¨
+S_TITLE ç®¡ç† VPN Server "%S"
+S_VHUB_BRIDGE 通过此 VPN Server 托管的虚拟 HUB (&Z):
+IDOK 管ç†è™šæ‹Ÿ HUB (&A)
+B_ONLINE 在线(&O)
+B_OFFLINE 离线(&F)
+B_HUB_STATUS 查看状æ€(&S)
+B_CREATE 创建虚拟 HUB (&C)
+B_EDIT 属性(&E)
+B_DELETE 删除(&D)
+STATIC1 管ç†ç›‘å¬å™¨(&L)
+STATIC2 监å¬å™¨åˆ—表 (TCP/IP 端å£) (&I):
+B_CREATE_LISTENER 创建(&R)
+B_DELETE_LISTENER 删除(&T)
+B_START 开始(&G)
+B_STOP åœæ­¢(&P)
+STATIC3 VPN Server 和网络信æ¯å’Œè®¾ç½®(&N)
+B_SSL 加密与网络(&E)
+B_STATUS 查看æœåŠ¡å™¨çŠ¶æ€(&V)
+B_INFO 关于此 VPN Server çš„ä¿¡æ¯
+B_LICENSE 添加 / 删除许å¯è¯(&L)
+B_FARM 群集é…ç½®(&M)
+B_FARM_STATUS 群集状æ€(&Z)
+B_CONNECTION 显示 TCP/IP \r\n连接列表(&Y)
+B_BRIDGE 本地网桥设置(&B)
+B_L3 3 层交æ¢æœºè®¾ç½®(&3)
+B_CONFIG 编辑设置(&D)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+S_BETA 测试版 (预å‘è¡Œ)
+B_IPSEC IPsec / L&2TP 设置
+B_DDNS åŠ¨æ€ DNS 设置
+S_DDNS å½“å‰ DDNS 主机å:
+B_OPENVPN OpenVPN / MS-SSTP 设置
+B_AZURE VPN Azure 设置
+S_AZURE VPN Azure 主机å:
+B_VPNGATE VPN Gate 设置
+
+
+PREFIX D_SM_STATUS
+IDOK 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_EDIT_HUB
+STATIC1 虚拟 HUB å(&N):
+STATIC2 安全设置(&S):
+S_BOLD 管ç†æ­¤è™šæ‹Ÿ HUB 的密ç 
+STATIC3 密ç (&P):
+STATIC4 确定(&C):
+R_NO_ENUM ä¸è¦å‘匿å用户枚举 (&U)
+STATIC5 虚拟 HUB 选项(&I):
+R_LIMIT_MAX_SESSION 最大 VPN 会è¯æ•°é™åˆ¶(&L)
+S_MAX_SESSION_1 最大会è¯æ•°(&X):
+S_MAX_SESSION_2 会è¯
+STATIC6 (ä¸è®¡ç®—本地桥ã€è™šæ‹Ÿ NAT 或级è”产生的æœåŠ¡ç«¯è™šæ‹Ÿä¼šè¯æ•°)
+STATIC7 虚拟 HUB 状æ€(&J):
+STATIC8 设置虚拟 HUB 状æ€ã€‚
+R_ONLINE 在线(&E)
+R_OFFLINE 离线(&F)
+STATIC9 设置群集(&M):
+S_FARM_INFO 选择群集内虚拟 HUB 类型。
+R_STATIC é™æ€è™šæ‹Ÿ HUB (&A)
+R_DYNAMIC 动æ€è™šæ‹Ÿ HUB (&D)
+S_AO_1 虚拟 HUB 管ç†é€‰é¡¹(&Y):
+S_AO_3 显示并编辑虚拟 HUB 管ç†é€‰é¡¹ã€‚
+B_ADMINOPTION 虚拟 HUB 管ç†é€‰é¡¹(&K)
+S_ACL_3 æº IP 访问é™åˆ¶åˆ—表(&R):
+S_ACL æ ¹æ®å®¢æˆ·ç«¯è®¡ç®—机的 IP 地å€å…许或拒ç»åˆ°æ­¤è™šæ‹Ÿ HUB çš„ VPN 连接。
+B_ACL IP 访问控制列表(&T)
+IDOK &OK
+IDCANCEL å–消
+STATIC10 您å¯ä»¥åœ¨è™šæ‹Ÿ HUB 扩展选项列表中é…置更高级的设置。
+B_EXTOPTION 编辑虚拟 HUB 扩展选项列表(&X)
+S_MSG_1 当客户端连接时,显示信æ¯ã€‚
+S_MSG_2 当 VPN Client 连接到这个虚拟 HUB 时,显示在å±å¹•ä¸Šä¸€ä¸ªç”¨æˆ·ä¿¡æ¯ã€‚
+B_MSG ä¿¡æ¯è®¾ç½®(&M)
+
+
+PREFIX D_SM_CREATE_LISTENER
+CAPTION 创建监å¬å™¨
+STATIC1 您å¯ä»¥ä¸º VPN Server 添加一个 TCP/IP 端å£å·ï¼Œæ¥æŽ¥æ”¶ä»Žå®¢æˆ·ç«¯æ¥çš„连接。\r\n\r\n请指定è¦æ·»åŠ çš„端å£å·ã€‚
+STATIC2 如果端å£å·å·²ç»è¢«å…¶å®ƒæœåŠ¡ç«¯ç¨‹åºä½¿ç”¨ï¼Œåˆ™æ–°ç›‘å¬å™¨çš„状æ€å°†è¢«è¢«æ›´æ”¹ä¸ºé”™è¯¯çŠ¶æ€ã€‚\r\n\r\n此时,请åœæ­¢æ‰“开相åŒç«¯å£çš„其他程åºã€‚
+STATIC3 端å£å·(&P):
+IDOK &OK
+IDCANCEL å–消
+STATIC4 (TCP/IP 端å£)
+
+
+PREFIX D_SM_SSL
+CAPTION 加密和网络设置
+STATIC1 您å¯ä»¥æŸ¥çœ‹æˆ–更改此 VPN Server 上与加密ã€é€šä¿¡å’Œå®‰å…¨ç›¸å…³çš„设置。
+STATIC2 加密算法设置(&A):
+STATIC3 指定与此 VPN Server å’Œ VPN Client 连接中使用的 SSL 加密算法å。此加密算法必须与 SSL 版本 3 相兼容。
+STATIC4 加密算法å(&C):
+STATIC6 æœåŠ¡ç«¯è¯ä¹¦è®¾ç½®(&C):
+STATIC7 指定 X509 è¯ä¹¦å’Œç§é’¥æ交给这å°æœåŠ¡å™¨çš„客户端。
+B_IMPORT 导入(&I)
+B_EXPORT 导出(&X)
+B_VIEW 查看(&V)
+B_REGENERATE æ–°çš„
+STATIC8 ä¿æŒäº’è”网连接活跃ç€(&K):
+STATIC9 在闲置一段时间åŽè‡ªåŠ¨æ–­çº¿çš„环境下,å¯ä»¥é€šè¿‡å‘互è”网上任æ„主机å‘é€å‡æ•°æ®åŒ…çš„æ–¹å¼æ¥ä¿æŒäº’è”网连接。
+STATIC10 æœåŠ¡å™¨è¯ä¹¦:
+R_USE_KEEP_CONNECT 使用并ä¿æŒäº’è”网的连接(&K)
+S_HOSTNAME 主机å(&H):
+S_PORT 端å£å·(&P):
+S_INTERVAL å‘é€é—´éš”(&I):
+S_INTERVAL2 秒
+S_PROTOCOL åè®®(&O):
+R_TCP TCP/IP åè®®(&T)
+R_UDP UDP/IP åè®®(&U)
+S_INFO å‘é€å¹¶ä¿æŒäº’è”网连接的数æ®åŒ…大å°éšæœºï¼Œæ— ä¸ªäººä¿¡æ¯è¢«å‘é€ã€‚
+STATIC11 管ç†å‘˜å¯†ç (&W):
+S_INFO4 您å¯ä»¥ä¿®æ”¹æ‰€æœ‰è™šæ‹Ÿ HUB 和整个 VPN Server 的管ç†å‘˜å¯†ç ã€‚
+B_PASSWORD 更改管ç†å‘˜å¯†ç (&P)
+IDOK &OK
+IDCANCEL å–消
+IDCANCEL2 å–消
+STATIC12 syslog å‘é€åŠŸèƒ½:
+STATIC13 您å¯ä»¥é€šè¿‡ä½¿ç”¨ syslog å议传输整个 VPN Server / Bridge 日志,虚拟 HUB 管ç†æ—¥å¿—或虚拟 HUB æ•°æ®åŒ…日志,而ä¸æ˜¯å†™å…¥æœ¬åœ°ç£ç›˜ã€‚
+STATIC14 syslog æœåŠ¡ç«¯ä¸»æœºå(&S):
+STATIC15 端å£å·(&O):
+S_OVER_FUNCS VPN over ICMP / DNS æœåŠ¡å™¨åŠŸèƒ½
+S_INFO5 您å¯ä»¥å»ºç«‹ä¸€ä¸ªä»…用 ICMP 或 DNS æ•°æ®åŒ…çš„ VPN ,å³ä½¿æœ‰é˜²ç«å¢™æˆ–路由器阻止 TCP/IP 通讯。
+B_SPECIALLISTENER VPN over ICMP / DNS 设置
+B_UPDATE_CONFIG 更新通知设置...(&U)
+
+PREFIX D_SM_SAVE_KEY_PAIR
+CAPTION ä¿å­˜è¯ä¹¦å’Œå¯†é’¥
+STATIC1 请选择ä¿å­˜è¯ä¹¦å’Œå¯†é’¥çš„方法。
+STATIC2 ä¿å­˜æ–¹æ³•(&V):
+R_X509_AND_KEY ä¿å­˜ä¸º X509 è¯ä¹¦ (.CER) 和密钥文件 (.KEY) (&X)
+R_PKCS12 ä¿å­˜ä¸º PKCS#12 文件 (.P12) (&P)
+R_SECURE 写入智能å¡(&S)
+STATIC3 切割æˆä¸¤ä¸ªæ–‡ä»¶ä¿å­˜: 一个标准 Base 64 ç¼–ç è¯ä¹¦æ–‡ä»¶å’Œä¸€ä¸ªå¯†é’¥æ–‡ä»¶ã€‚
+STATIC4 ä¿å­˜ä¸º PKCS#12 (Public Key Cryptography Standard #12) 文件。\r\n您å¯ä»¥å°†è¯ä¹¦å’Œå¯†é’¥ä¿å­˜åˆ°ä¸€ä¸ª PKCS#12 文件中。
+STATIC5 当智能å¡è¿žæŽ¥åˆ°æ­¤è®¡ç®—机时,您å¯ä»¥å‘智能å¡ä¸­å†™å…¥è¯ä¹¦å’Œå¯†é’¥ã€‚
+B_SELECT 选择è¦ä½¿ç”¨çš„智能å¡(&S)...
+S_PASS3 密钥ä¿æŠ¤(&R)
+S_PASS4 当ä¿å­˜å¯†é’¥æ—¶ï¼Œæ‚¨å¯ä»¥è®¾ç½®ä¸€ä¸ªå¯†ç æ¥åŠ å¯†ã€‚您当加载它时,你将被è¦æ±‚输入密ç ã€‚
+R_USE_PASS 设置密ç (&A)
+S_PASS1 密ç (&S):
+S_PASS2 确定(&E):
+IDOK 确定(&O)
+IDCANCEL å–消
+B_SECURE_MANAGER 智能å¡ç®¡ç†å™¨(&M)...
+
+
+PREFIX D_SM_CONNECTION
+CAPTION 连接列表
+S_TITLE æœåŠ¡ç«¯ %S 有如下活跃的连接。注æ„,ä¸åŒ…括作为 VPN 会è¯å·²å»ºç«‹çš„连接。
+IDOK 显示连接信æ¯(&I)
+B_DISCONNECT æ–­å¼€(&D)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_FARM
+CAPTION 群集é…ç½®
+S_TITLE 您å¯ä»¥å˜æ›´ VPN Server "%S" 的群集功能é…置。
+STATIC1 群集功能å¯ä»¥å®žçŽ°è´Ÿè½½å‡è¡¡å’Œæ•…障平衡ä¿æŠ¤æ¥æ†ç»‘多个 VPN Server。
+STATIC2 当å‰æ¨¡å¼:
+STATIC3 群集设置(&T):
+R_STANDALONE 独立æœåŠ¡ç«¯(éžç¾¤é›†) (&S)
+R_CONTROLLER 群集控制器(&C)
+R_MEMBER 群集æˆå‘˜æœåŠ¡å™¨(&M)
+STATIC4 群集æˆå‘˜æœåŠ¡å™¨é…ç½®å‚æ•°(&O):
+S_IP_1 公网 IP 地å€(&I):
+S_IP_2 (当公网 IP 地å€çœç•¥æ—¶ï¼Œå°†ä¼šä½¿ç”¨è¿žæŽ¥ç¾¤é›†æŽ§åˆ¶å™¨æ—¶ä½¿ç”¨çš„ç½‘ç»œæŽ¥å£ IP 地å€ã€‚)
+S_PORT_1 公网端å£åˆ—表(&P):
+S_PORT_2 (多个端å£å·ç”¨ç©ºæ ¼æˆ–逗å·åˆ†éš”。)
+S_CONTROLLER 控制器的主机å或 IP 地å€(&H):
+S_CONTROLLER_PORT 控制器的\r\n端å£å·(&R):
+S_PORT_3 (TCP 端å£)
+S_PASSWORD 管ç†å¯†ç (&P):
+STATIC5 当您修改群集é…置时,VPN Server çš„æœåŠ¡è‡ªåŠ¨é‡å¯ã€‚此时,所有当å‰æ­£åœ¨è¿žæŽ¥çš„会è¯å’Œç®¡ç†ç›¸å…³çš„连接将被断开。
+IDOK &OK
+IDCANCEL å–消
+S_1 群机内的标准比例(&W):
+S_2 (标准: 100)
+R_CONTROLLER_ONLY 仅控制器功能 (本身没有 VPN 会è¯)
+
+
+PREFIX D_SM_FARM_MEMBER
+CAPTION 群集æˆå‘˜åˆ—表
+S_TITLE 当å‰ä¸‹åˆ—群集æˆå‘˜æœåŠ¡ç«¯è¿žæŽ¥åˆ°ç¾¤é›†æŽ§åˆ¶å™¨ %S。
+IDOK 群集æˆå‘˜æœåŠ¡ç«¯ä¿¡æ¯(&I)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+B_CERT 查看æœåŠ¡ç«¯è¯ä¹¦(&C)
+
+
+PREFIX D_SM_CHANGE_PASSWORD
+CAPTION 更改 %S 的管ç†å‘˜å¯†ç 
+S_TITLE 更改æœåŠ¡ç«¯ %S 的管ç†å‘˜å¯†ç ã€‚输入密ç åŽè¯·å•å‡»â€œç¡®å®šâ€ã€‚
+STATIC1 新密ç (&P):
+STATIC2 确认密ç (&C):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_HUB
+CAPTION 管ç†è™šæ‹Ÿ HUB - %S
+S_TITLE 虚拟 HUB "%S"
+STATIC1 管ç†å®‰å…¨æ•°æ®åº“(&D):
+B_USER 管ç†ç”¨æˆ·(&U)
+S_USER 添加,删除或编辑用户账户。
+B_GROUP 管ç†ç»„(&G)
+S_GROUP 添加,删除或编辑组。
+B_ACCESS 管ç†è®¿é—®åˆ—表(&A)
+S_ACCESS 添加或删除访问列表 (æ•°æ®åŒ…过滤规则)。
+STATIC2 虚拟 HUB 设置(&N)
+B_PROPERTY 虚拟 HUB 属性(&P)
+S_PROPERTY é…置此 HUB
+B_RADIUS 认è¯æœåŠ¡ç«¯è®¾ç½®(&E)
+S_RADIUS 使用外部 RADIUS 认è¯æœåŠ¡å™¨ä½œä¸ºç”¨æˆ·è®¤è¯ã€‚
+B_LINK 管ç†çº§è”连接(&C)
+S_LINK 在本地或远程 VPN Server 上建立到 HUB 的级è”连接。
+STATIC3 此虚拟 HUB 当å‰çŠ¶æ€(&R):
+B_REFRESH 刷新(&H)
+STATIC4 其它设置(&O)
+B_LOG 日志ä¿å­˜è®¾ç½®(&L)
+B_LOG_FILE 日志文件列表(&Q)
+S_LOG é…置日志ä¿å­˜åŠŸèƒ½çš„设置。
+B_CA å¯ä¿¡çš„ CA è¯ä¹¦(&T)
+B_CRL 无效è¯ä¹¦(&K)
+S_CA 管ç†å¯ä¿¡çš„ CA è¯ä¹¦ã€‚
+B_SNAT 虚拟 NAT 和虚拟 DHCP æœåŠ¡å™¨(&V)
+S_SNAT SecureNAT 在此虚拟 HUB 上å¯ç”¨ã€‚您å¯ä»¥è¿è¡Œè™šæ‹Ÿ NAT 和虚拟 DHCP。
+STATIC5 VPN 会è¯ç®¡ç†(&I):
+B_SESSION 管ç†ä¼šè¯(&S)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_USER
+CAPTION 管ç†ç”¨æˆ·
+S_TITLE 虚拟 HUB "%S" 有如下用户。
+IDOK 编辑(&E)
+B_CREATE 新建(&C)
+B_DELETE 移除(&D)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+B_STATUS 查看用户信æ¯(&V)
+
+
+PREFIX D_SM_EDIT_USER
+IDC_STATIC1 用户å(&U):
+IDC_STATIC3 å…¨å(&F):
+IDC_STATIC4 说明(&N):
+IDC_STATIC5 组å\r\n(å¯é€‰):
+B_GROUP æµè§ˆç»„(&J)...
+R_EXPIRES 设置此账户有效期é™(&S)
+IDC_STATIC6 验è¯ç±»åž‹(&A):
+S_RADIUS_3 RADIUS 或 NT 域认è¯è®¾ç½®
+S_RADIUS_1 通过密ç çš„登录å°è¯•é€šè¿‡å¤–部 RADIUS æœåŠ¡ç«¯ï¼ŒWindows NT 域控制器或 Active Directory 控制器被验è¯ã€‚
+R_SET_RADIUS_USERNAME 指定认è¯æœåŠ¡å™¨çš„用户å(&K)
+S_RADIUS_2 认è¯æœåŠ¡ç«¯ä¸Šçš„用户å(&W):
+S_POLICY_1 安全策略
+R_POLICY 设置安全策略(&Y)
+B_POLICY 安全策略
+S_PASSWORD_1 密ç è®¤è¯è®¾ç½®
+S_PASSWORD_2 密ç (&P):
+S_PASSWORD_3 确认密ç (&C):
+S_USER_CERT_1 特定è¯ä¹¦è®¤è¯è®¾ç½®
+B_LOAD_CERT 指定è¯ä¹¦(&E)
+B_VIEW_CERT 查看è¯ä¹¦(&V)
+B_CREATE 创建è¯ä¹¦(&W)
+S_ROOT_CERT_1 已签åè¯ä¹¦è®¤è¯è®¾ç½®
+S_ROOT_CERT_2 验è¯å®¢æˆ·ç«¯è¯ä¹¦æ˜¯å¦å·²ç­¾å是基于一份由虚拟 HUB 信任的 CA è¯ä¹¦ã€‚
+R_CN è¯ä¹¦çš„ Common Name (CN) é™åˆ¶å€¼(&B)
+R_SERIAL è¯ä¹¦åºåˆ—å·çš„é™åˆ¶å€¼(&L)
+S_ROOT_CERT_3 ※ 注æ„: 请输入å六进制数值。(例如: 0155ABCDEF)
+S_HINT æ示:使用用户å“*â€(星å·)定义一个用户对象,以接å—ä¸ç¬¦åˆä»»ä½•å·²æ³¨å†Œçš„ã€æ˜Žç¡®çš„ã€ç”¨æˆ·å¯¹è±¡çš„登录å°è¯•ã€‚这样一个特殊的用户将使用外部用户认è¯æœåŠ¡å™¨éªŒè¯ç™»å½•ã€‚
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_SM_POLICY
+STATIC1 已选择策略(&P):
+S_BOLD 此策略的æè¿°(&C):
+S_BOLD2 当å‰å€¼(&V):
+R_ENABLE å¯ç”¨æ­¤ç­–ç•¥(&E)
+R_DISABLE ç¦ç”¨æ­¤ç­–ç•¥(&D)
+R_DEFINE 定义此策略(&F)
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_SM_GROUP
+CAPTION 管ç†ç»„
+S_TITLE 虚拟 HUB "%S" 有如下组
+B_CREATE 新建(&C)
+IDOK 编辑(&E)
+B_DELETE 移除(&R)
+B_REFRESH 刷新(&R)
+B_USER æˆå‘˜åˆ—表(&M)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_EDIT_GROUP
+IDC_STATIC1 组å称(&G):
+IDC_STATIC3 å…¨å(&F):
+IDC_STATIC4 说明(&N):
+S_POLICY_1 安全策略
+R_POLICY 设置此组的安全策略(&Y)
+B_POLICY 安全策略(&M)
+S_POLICY_2 组统计信æ¯
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_SM_ACCESS_LIST
+CAPTION 访问列表
+S_TITLE 虚拟 HUB "%S" 有如下访问列表(æ•°æ®åŒ…过滤规则)。
+B_ADD 新建(IPv&4)
+B_ADD_V6 新建(IPv&6)
+IDOK 编辑(&E)
+B_DELETE 删除(&D)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL å–消(&C)
+STATIC1 较高æƒé™çš„项目出现在列表的上方。
+STATIC2 注æ„: 与访问列表项目ä¸åŒ¹é…çš„ IP æ•°æ®åŒ…å¯ä»¥é€šè¡Œã€‚
+B_CLONE 克隆
+B_ENABLE å¯ç”¨
+B_DISABLE ç¦ç”¨
+
+PREFIX D_SM_EDIT_ACCESS
+CAPTION 编辑访问列表项目
+STATIC1 é…置访问列表设置。此处定义的访问列表将被应用于所有穿过虚拟 HUB çš„ IP æ•°æ®åŒ…。
+STATIC2 基础设置
+STATIC3 备忘(&N):
+STATIC4 行为(&A):
+R_PASS 通过(&P)
+R_DISCARD 废弃(&D)
+STATIC5 优先级(&R):
+STATIC6 (较å°å€¼æœ‰æ›´é«˜ä¼˜å…ˆæƒã€‚)
+STATIC7 IP 包头的过滤选项
+S_ACCESS_SRC_ALL æº IP 地å€:
+R_SRC_ALL 应用到所有æºåœ°å€
+S_SRC_IP_1 IPv4 地å€:
+S_SRC_IP_2 å­ç½‘掩ç :
+S_SRC_IP_3 (255.255.255.255: æ„为å•ä¸ªä¸»æœº)
+S_SRC_IP_1_V6 IPv6 地å€:
+S_SRC_IP_3_V6 (例如: "ffff:ff00::" 或 "/24"。"/128" 仅指该唯一主机)
+S_ACCESS_DST_ALL 目标 IP 地å€:
+R_DST_ALL 应用到所有目标地å€
+S_IP_DST_1 IPv4 地å€:
+S_IP_DST_2 å­ç½‘掩ç :
+S_IP_DST_3 (255.255.255.255: 仅指特定主机)
+S_IP_DST_1_V6 IPv6 地å€:
+S_IP_DST_3_V6 (例如: "ffff:ff00::" 或 "/24"。"/128" 指该唯一主机:)
+STATIC9 å议类型:
+STATIC10 TCP 包头和 UDP 包头的过滤选项
+S_TCP_1 最å°å€¼
+S_TCP_2 最大值
+S_TCP_3 æºç«¯å£å·:
+S_TCP_5 目标端å£å·:
+S_TCP_7 空白端å£å·å­—段匹é…任何端å£ã€‚当已指定的最å°å€¼ä½†æ²¡æŒ‡å®šæœ€å¤§å€¼æ—¶ï¼Œå°†åº”用于åªç¬¦åˆæœ€å°å€¼çš„æ•°æ®åŒ…。
+STATIC11 用户/用户組过滤器选项
+STATIC11_OLD 用户过滤器选项
+STATIC12 此访问列表仅应用于具体的用户 / 用户組å‘出或接收的数æ®åŒ…。
+STATIC12_OLD 此访问列表仅应用于具体的用户å‘出或接收的数æ®åŒ…。
+STATIC13 æºå称:
+B_USER1 æµè§ˆ...
+STATIC14 目标å称:
+B_USER2 æµè§ˆ...
+STATIC15 è‹¥ä¸æŒ‡å®šç”¨æˆ·è¿˜æ˜¯çµ„,请ä¿ç•™è¿™äº›å­—段为空白。
+STATIC15_OLD 若无法指定用户å称,请ä¿æŒæœ¬æ ç›®ç©ºç™½ã€‚
+IDOK &OK
+IDCANCEL å–消
+S_PROTOID 指定 IP åè®®:
+STATIC16 MAC 包头的过滤选项:
+S_CHECK_SRC_MAC æº MAC 地å€:
+R_CHECK_SRC_MAC 应用到任一æºåœ°å€
+S_SRC_MAC MAC 地å€:
+S_SRC_MAC_MASK 掩ç :
+S_CHECK_DST_MAC 目标 MAC 地å€:
+R_CHECK_DST_MAC 应用于任一目标地å€
+B_SIMULATION 延迟和丢包(&D)...
+S_DST_MAC MAC 地å€:
+S_DST_MAC_MASK 掩ç :
+S_MAC_NOTE 您å¯ä»¥ä½¿ç”¨å¸¦æœ‰ä¸¤ç§åˆ†éš”符'-',或 ':',或ä¸å¸¦åˆ†éš”符的å六进制数字。\r\n(FF-FF-FF-FF-FF-FF æ„为指定的主机)
+R_CHECK_TCP_STATE éªŒè¯ TCP 连接状æ€(ä»… TCP æ•°æ®åŒ…)
+R_ESTABLISHED 已建立的数æ®åŒ…
+R_UNESTABLISHED 未建立的数æ®åŒ…
+R_REDIRECT é‡å®šå‘ HTTP 请求至特定 URL
+B_REDIRECT 设置 URL é‡å®šå‘至
+
+PREFIX D_SM_RADIUS
+CAPTION 认è¯æœåŠ¡å™¨è®¾ç½®
+S_TITLE 使用外部的 RADIUS æœåŠ¡å™¨æ¥éªŒè¯åˆ°è™šæ‹Ÿ HUB “%Sâ€çš„登录å°è¯•ã€‚指定一个外部 RADIUS æœåŠ¡å™¨æ¥éªŒè¯ç”¨æˆ·å和密ç ã€‚
+STATIC1 RADIUS æœåŠ¡ç«¯è®¾ç½®(&F):
+R_USE_RADIUS 使用 RADIUS 认è¯(&U)
+S_RADIUS_1 RADIUS æœåŠ¡ç«¯ä¸»æœºå或 IP 地å€(&S):
+S_RADIUS_2 端å£(&P):
+S_RADIUS3 (UDP 端å£)
+S_RADIUS_4 共享秘密(&E):
+S_RADIUS_5 确认共享秘密(&C):
+S_RADIUS_6 RADIUS æœåŠ¡å™¨å¿…须接å—从 VPN Server çš„ IP 地å€æ¥çš„请求。而且,必须å¯ç”¨å¯†ç è®¤è¯åè®®(PAP)。
+S_RADIUS_7 毫秒 (大于 %u, å°äºŽ%u)
+S_RADIUS_8 é‡è¯•é—´éš”(&R):
+S_RADIUS_9 (使用“,â€æˆ–“;â€æ¥åˆ†å¼€å¤šä¸ªä¸»æœºå)
+STATIC2 当使用 Windows NT 域控制器或 Windows Server Active Directory 控制器作为外部认è¯æœåŠ¡å™¨æ—¶ï¼Œæ‚¨å¿…须设置 VPN Server 的计算机加入到域中。使用 NT 域认è¯ï¼Œåœ¨æ­¤ä¸éœ€è¦è¿›è¡Œé…置。
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_SM_LINK
+CAPTION %S 上的级è”连接
+STATIC1 级è”连接å¯ä»¥åœ¨ 2 层以太网将本虚拟 HUB 与å¦å¤–一å°ä½äºŽæœ¬åœ°æˆ–者远程 VPN Server 上的虚拟 HUB 建立链接。
+STATIC2 级è”连接使用å‰
+STATIC3 级è”连接实现了在多个虚拟 HUB 间的二层桥接。但如果连接é…ç½®ä¸æ­£ç¡®ï¼Œå¯èƒ½ä¼šæ— æ„中创建一个无é™å¾ªçŽ¯ã€‚当使用级è”连接功能时,请å°å¿ƒè®¾è®¡ç½‘络拓扑。
+B_CREATE 新建(&C)
+B_EDIT 编辑(&E)
+B_ONLINE 在线(&N)
+B_OFFLINE 离线(&F)
+IDOK 状æ€(&S)
+B_DELETE 删除(&D)
+B_RENAME é‡å‘½å(&A)
+B_REFRESH 刷新(&R)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_LOG
+CAPTION 日志ä¿å­˜è®¾ç½®
+S_TITLE 您å¯ä»¥ä¿å­˜è™šæ‹Ÿ HUB "%S"的安全日志 (如用户登录记录) 和所有ç»è¿‡è™šæ‹Ÿ HUB çš„æ•°æ®åŒ…çš„æ•°æ®åŒ…日志。
+STATIC1 安全日志(&S):
+B_SEC ä¿å­˜å®‰å…¨æ—¥å¿—(&E)
+S_SEC 日志文件切æ¢å‘¨æœŸ(&W):
+STATIC2 æ•°æ®åŒ…日志(&P):
+B_PACKET ä¿å­˜æ•°æ®åŒ…日志(&E)
+S_PACKET 日志文件切æ¢å‘¨æœŸ(&W):
+S_PACKET_0 TCP 连接:
+B_PACKET_0_0 ä¸ä¿å­˜
+B_PACKET_0_1 仅包头
+B_PACKET_0_2 包头和有效载è·
+S_PACKET_1 TCP æ•°æ®åŒ…:
+B_PACKET_1_0 ä¸ä¿å­˜
+B_PACKET_1_1 仅包头
+B_PACKET_1_2 包头和有效载è·
+S_PACKET_2 DHCP æ•°æ®åŒ…:
+B_PACKET_2_0 ä¸ä¿å­˜
+B_PACKET_2_1 仅包头
+B_PACKET_2_2 包头和有效载è·
+S_PACKET_3 UDP æ•°æ®åŒ…:
+B_PACKET_3_0 ä¸ä¿å­˜
+B_PACKET_3_1 仅包头
+B_PACKET_3_2 包头和有效载è·
+S_PACKET_4 ICMP æ•°æ®åŒ…:
+B_PACKET_4_0 ä¸ä¿å­˜
+B_PACKET_4_1 仅包头
+B_PACKET_4_2 包头和有效载è·
+S_PACKET_5 IP æ•°æ®åŒ…:
+B_PACKET_5_0 ä¸ä¿å­˜
+B_PACKET_5_1 仅包头
+B_PACKET_5_2 包头和有效载è·
+S_PACKET_6 ARP æ•°æ®åŒ…:
+B_PACKET_6_0 ä¸ä¿å­˜
+B_PACKET_6_1 仅包头
+B_PACKET_6_2 包头和有效载è·
+S_PACKET_7 以太网\r\næ•°æ®åŒ…:
+B_PACKET_7_0 ä¸ä¿å­˜
+B_PACKET_7_1 仅包头
+B_PACKET_7_2 包头和有效载è·
+IDOK &OK
+IDCANCEL å–消
+STATIC3 ä¿å­˜å¤§é‡æ•°æ®åŒ…日志会给 CPU 和硬盘带æ¥å¾ˆå¤§çš„负担,会导致 HUB 和整个 VPN Server 的性能下é™ã€‚å¯ç”¨æ—¥å¿—记录仅ä¿å­˜å¿…è¦çš„æ•°æ®åŒ…。
+
+PREFIX D_SM_CA
+CAPTION 管ç†å¯ä¿¡çš„ CA è¯ä¹¦
+STATIC1 您å¯ä»¥ç®¡ç†è¢«æ­¤è™šæ‹Ÿ HUB 信任的è¯ä¹¦ç­¾å‘机构(CA)çš„è¯ä¹¦åˆ—表。\r\n\r\n当一个 VPN Client 以已签字的è¯ä¹¦è®¤è¯æ¨¡å¼è¿žæŽ¥æ—¶ï¼Œåˆ—在此处的 CA è¯ä¹¦åˆ—表用于验è¯è¯ä¹¦ã€‚
+B_IMPORT 添加(&A)
+IDOK 查看è¯ä¹¦(&V)
+IDCANCEL 关闭(&C)
+B_DELETE 删除(&D)
+
+
+PREFIX D_SM_SESSION
+CAPTION 管ç†ä¼šè¯- %S
+S_TITLE 虚拟 HUB "%S"当å‰æœ‰ä»¥ä¸‹ VPN 会è¯ã€‚
+STATIC1 会è¯æ“作
+IDOK 会è¯ä¿¡æ¯(&I)
+B_DISCONNECT æ–­å¼€(&D)
+B_REFRESH 刷新(&H)
+B_SESSION_MAC_TABLE 已选会è¯çš„ MAC 表(&M)
+B_SESSION_IP_TABLE 已选会è¯çš„ IP 表(&P)
+STATIC2 其它管ç†ä»»åŠ¡
+B_MAC_TABLE MAC 地å€è¡¨åˆ—表(&A)
+B_IP_TABLE IP 地å€è¡¨åˆ—表(&B)
+IDCANCEL 关闭(&X)
+S_FARM_INFO_2 此处显示的会è¯æ˜¯å½“å‰ç¾¤é›†ä¸Šçš„所有会è¯ã€‚è¦ç®¡ç†å…¶ä»–群集æˆå‘˜æœåŠ¡ç«¯ä¸Šçš„会è¯ï¼Œæ‚¨å¿…须以管ç†å‘˜èº«ä»½è¿žæŽ¥åˆ°é‚£äº›æœåŠ¡å™¨ä¸Šã€‚
+
+
+PREFIX D_SM_MAC
+CAPTION MAC 地å€è¡¨
+S_TITLE 虚拟 HUB "%S" 上的 MAC 地å€è¡¨æ•°æ®åº“有如下æ¡ç›®ã€‚
+B_DELETE 删除选定æ¡ç›®(&D)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_IP
+CAPTION IP 地å€è¡¨
+S_TITLE 虚拟 HUB "%S" 上的 IP 地å€è¡¨æ•°æ®åº“有如下æ¡ç›®ã€‚
+B_DELETE 删除选定æ¡ç›®(&D)
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_CREATE_CERT
+CAPTION 创建新è¯ä¹¦
+STATIC1 您å¯ä»¥è½»æ¾åœ°åˆ›å»ºè‡ªå·±æˆ–其他è¯ä¹¦ç­¾ç½²çš„è¯ä¹¦ã€‚
+STATIC2 è¯ä¹¦ç±»åž‹(&T):
+R_ROOT_CERT æ ¹è¯ä¹¦ (自签åè¯ä¹¦) (&R)
+R_SIGNED_CERT 其他è¯ä¹¦ç­¾åçš„è¯ä¹¦(&S)
+S_LOAD_1 ç­¾å用è¯ä¹¦å’Œå¯†é’¥(&C):
+B_LOAD 载入è¯ä¹¦å’Œå¯†é’¥(&L)
+S_LOAD_2 å•å‡»â€œè½½å…¥è¯ä¹¦å’Œå¯†é’¥â€æ¥æŒ‡å®šä½¿ç”¨ä¸€ä¸ªæ–°è¯ä¹¦ç­¾åçš„ X509 è¯ä¹¦å’Œ RSA 密钥。
+S_LOAD_3 通用å称(CN):
+S_LOAD_4 所属机构(O):
+S_LOAD_5 组织å•ä½(OU):
+S_LOAD_6 国家(C):
+S_LOAD_7 çœ(ST):
+S_LOAD_8 地点(L):
+S_LOAD_11 åºåˆ—å·(&S):\r\n(å六进制)
+S_LOAD_9 有效期至(&E):
+S_LOAD_10 天
+STATIC3 当管ç†å¤§é‡è¯ä¹¦å’Œè®¤è¯è®¤è¯æœºæž„时,请使用å…费软件,如 OpenSSL,或商业 CA(è¯ä¹¦è®¤è¯æœºè´­)软件。
+IDOK &OK
+IDCANCEL å–消
+S_LOAD_12 密ç å¼ºåº¦(&N):
+
+
+PREFIX D_NM_LOGIN
+CAPTION deleted
+S_TITLE deleted
+STATIC1 deleted
+STATIC2 deleted
+IDOK deleted
+IDCANCEL deleted
+
+
+PREFIX D_SPEEDMETER
+CAPTION 网络设备状æ€
+STATIC1 选择网络适é…器:
+STATIC2 实时状æ€(&R)
+STATIC3 刷新(&R)
+
+
+PREFIX D_NM_MAIN
+CAPTION deleted
+STATIC1 deleted
+STATIC2 deleted
+B_SETTING VPN Server 的连接设置(&S)
+B_CONNECT 连接(&C)
+B_DISCONNECT æ–­å¼€(&D)
+STATIC3 用户模å¼è·¯ç”±å™¨çš„æ“作设置
+STATIC4 您å¯ä»¥åœ¨ SoftEther VPN 用户模å¼è·¯ç”±å™¨çš„虚拟网络上设置æ“作。
+B_OPTION 用户模å¼è·¯ç”±å™¨çš„æ“作设置(&O)
+STATIC5 用户模å¼è·¯ç”±å™¨çš„æ“作状æ€
+STATIC6 显示 SoftEther VPN 用户模å¼è·¯ç”±å™¨çš„当å‰æ“作状æ€
+B_NAT 虚拟NAT状æ€(&N)
+B_DHCP 虚拟 DHCP æœåŠ¡å™¨çŠ¶æ€(&H)
+B_STATUS 用户模å¼è·¯ç”±å™¨çŠ¶æ€(&R)
+B_INFO 用户模å¼è·¯ç”±å™¨ä¿¡æ¯(&I)
+B_PASSWORD 管ç†å¯†ç è®¾ç½®(&P)
+B_REFRESH 刷新(&E)
+B_ABOUT 关于(&A)
+IDCANCEL 退出(&X)
+
+
+PREFIX D_NM_OPTION
+CAPTION SecureNAT é…ç½®
+S_TITLE 设置 SecureNAT 虚拟主机如何在虚拟 HUB "%S" 的虚拟网络上进行æ“作。
+STATIC1 虚拟主机网络接å£è®¾ç½®:
+STATIC2 MAC 地å€(&M):
+STATIC3 IP 地å€(&P):
+STATIC4 å­ç½‘掩ç (&S):
+STATIC5 虚拟 NAT 设置:
+R_USE_NAT 使用虚拟 NAT 功能(&A):
+STATIC6 M&TU 值:
+STATIC7 字节
+STATIC8 TCP 会è¯è¶…æ—¶(&C):
+STATIC9 秒
+STATIC10 UDP 会è¯è¶…æ—¶(&U):
+STATIC11 秒
+R_SAVE_LOG ä¿å­˜ NAT 或 DHCP æœåŠ¡å™¨è¿è¡Œè®°å½•åˆ°æ—¥å¿—文件(&L)
+STATIC12 虚拟 DHCP æœåŠ¡å™¨è®¾ç½®:
+R_USE_DHCP 使用虚拟 DHCP æœåŠ¡å™¨åŠŸèƒ½(&N)
+STATIC13 åˆ†é… IP 地å€(&D):
+STATIC14 至
+STATIC15 。
+STATIC16 å­ç½‘掩ç (&B):
+STATIC17 租èµæœŸé™(&E):
+STATIC18 秒
+STATIC19 应用到客户端的选项 (å¯é€‰):
+STATIC20 默认网关\r\n地å€(&F):
+STATIC21 DNS æœåŠ¡å™¨åœ°å€ 1 (&V):
+STATIC22 域å(&W):
+STATIC23 DNS æœåŠ¡å™¨åœ°å€ 2 (&V):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_NM_NAT
+CAPTION 虚拟 NAT 路由上的 NAT 会è¯è¡¨
+S_TITLE 有如下 TCP 或 UDP NAT 表项在 SecureNAT 的虚拟 NAT 路由上。
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_NM_DHCP
+CAPTION 虚拟 DHCP æœåŠ¡å™¨ä¸Šçš„ IP 租èµè¡¨
+S_TITLE SecureNAT 虚拟 DHCP æœåŠ¡å™¨å·²åˆ†é…以下 IP 地å€åˆ°å®¢æˆ·ç«¯ã€‚
+B_REFRESH 刷新(&H)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_NM_CHANGE_PASSWORD
+CAPTION å˜æ›´ %S 的管ç†å‘˜å¯†ç 
+S_TITLE 您å¯ä»¥å˜æ›´ SoftEther VPN 用户模å¼è·¯ç”±(%S) 的管ç†å‘˜å¯†ç ã€‚输入新密ç åŽè¯·å•å‡»â€œç¡®å®šâ€ã€‚
+STATIC1 新密ç (&P):
+STATIC2 确认输入(&C):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_SNAT
+CAPTION 虚拟 NAT 和虚拟 DHCP 功能 (SecureNAT) 设置
+S_TITLE SecureNAT 使你在虚拟 HUB "%S" 的虚拟网络上å¯ä»¥è¿è¡Œä¸€ä¸ªè™šæ‹Ÿ NAT 路由器(IP 伪装)å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ã€‚
+STATIC1 SecureNAT 警告
+S_WARNING SecureNAT 功能建议仅系统管ç†å‘˜æˆ–熟悉网络知识的人员使用。
+S_WARNING2 如果您正确使用 SecureNAT,VPN å¯ä»¥å®žçŽ°å®‰å…¨çš„远程访问。但是如果使用方å¼ä¸æ­£ç¡®ï¼Œå¯èƒ½ä¼šå°†æ•´ä¸ªç½‘络暴露在å±é™©ä¸‹ã€‚任何对网络没有足够了解,或没有网络管ç†å‘˜çš„å…许,请一定ä¸è¦å¯ç”¨ SecureNAT。请å‚阅 VPN Server 的手册或在线文档æ¥èŽ·å– SecureNAT 功能的详细解释。
+STATIC2 å¯ç”¨ / ç¦ç”¨å’Œå˜æ›´ SecureNAT 设置
+STATIC3 您å¯ä»¥å¯ç”¨ / ç¦ç”¨å’Œå˜æ›´æ­¤è™šæ‹Ÿ HUB 上的 SecureNAT 设置。
+B_ENABLE å¯ç”¨ SecureNAT (&E)
+B_DISABLE ç¦ç”¨ SecureNAT (&D)
+B_CONFIG SecureNAT é…ç½®(&C)
+STATIC4 ※注æ„: 当ç¦ç”¨ä¸€ä¸ªè¿è¡Œä¸­çš„ SecureNAT 时,所有通过 SecureNAT 连接的活跃的 TCP å’Œ UDP 会è¯å°†è¢«ç»ˆæ­¢ã€‚
+STATIC5 æŸ¥çœ‹å½“å‰ SecureNAT 状æ€
+STATIC6 您å¯ä»¥æŸ¥çœ‹å½“å‰ SecureNAT è¿è¡ŒçŠ¶æ€ã€‚
+B_NAT 虚拟 NAT 路由器状æ€(&N)
+B_DHCP 虚拟 DHCP æœåŠ¡å™¨çŠ¶æ€(&H)
+B_STATUS 查看 SecureNAT è¿è¡ŒçŠ¶æ€(&S)
+S_TSUKUBA2 SecureNAT 使用了 ç™»å¤§éŠ äºŽ 2004 年在筑波大学第三学群信æ¯å­¦ç³»â€œç‰¹åˆ«ä¿¡æ¯ç ”讨 Iâ€å¼€å‘的技术。
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_SM_BRIDGE
+CAPTION 本地网桥设置
+STATIC1 本地网桥å¯ä»¥å»ºç«‹ä¸€ä¸ªäºŒå±‚桥接æ¥è¿žæŽ¥æœ¬ VPN Server 上的虚拟 HUB 和一个物ç†ä»¥å¤ªç½‘设备(网络适é…器)。;\r\n也å¯ä»¥åˆ›å»ºä¸€ä¸ª tap 设备(虚拟网络接å£)并与虚拟 HUB 间建立一个桥接。(Tap ä»…æ”¯æŒ Linux 版)
+B_DELETE 删除本地网桥(&D)
+STATIC2 新建&新建本地网桥定义(&N):
+STATIC3 选择è¦æ¡¥æŽ¥çš„虚拟 HUB
+STATIC4 虚拟 HUB (&H):
+STATIC5 è¦åˆ›å»ºçš„类型(&T):
+R_BRIDGE 现存物ç†ç½‘络适é…器的桥接(&P)
+R_TAP 新 tap 设备的桥接(&T)
+S_ETH_1 &LAN 适é…器:
+S_TAP_1 æ–° tap 设备å称(&D):
+S_TAP_2 (11 个字符以内)
+STATIC6 ※注æ„: å¯ä»¥ä½¿ç”¨ä»»ä½•æ“作系统的网络适é…器建立桥接,但在高负载环境中,你应该为桥接准备一个专用的网络适é…器。
+IDOK 创建本地桥(&A)
+STATIC7 如果无法显示一个新安装到系统的网路适é…器,é‡å¯ç”µè„‘,并é‡æ–°æ‰“开此窗å£ã€‚
+IDCANCEL 关闭(&X)
+B_VLAN VLAN é€æ˜Žè®¾ç½®å·¥å…·(&G)
+
+
+PREFIX D_WIN9X_REBOOT
+CAPTION VPN Client - 安装虚拟网络适é…器
+STATIC1 VPN Client 虚拟网络适é…器已安装。\r\n需è¦å…³é—­ Windows并é‡å¯è®¡ç®—机。\r\n\r\n计算机将会自动é‡å¯ã€‚如果计算机没有é‡å¯ï¼Œè¯·æ‰‹åŠ¨å¯åŠ¨è®¡ç®—机。
+
+
+PREFIX D_EM_MAIN
+CAPTION SoftEther 以太网记录器管ç†å™¨
+STATIC1 SoftEther 以太网记录器是一个æœåŠ¡ï¼Œå¯ä»¥æ•æ‰æµç»è®¡ç®—机上网络适é…器的数æ®ã€‚而且,å¯ä»¥æ•°æ®åŒ…包头ä¿å­˜ä¸ºç®¡ç†å‘˜æŒ‡å®šç±»åž‹çš„日志文件,所有数æ®ä¿å­˜ä¸ºæ–‡æœ¬æ–‡ä»¶ã€‚\r\n\r\nç›®å‰ï¼Œä¸‹åˆ—æ•æ‰è®¾å¤‡æ­£åœ¨è¿è¡Œä¸­ã€‚
+B_PASSWORD 管ç†å‘˜å¯†ç (&P)
+B_LICENSE 许å¯è¯(&L)
+B_ADD 添加(&A)
+IDOK 编辑(&E)
+B_DELETE 删除(&D)
+IDCANCEL 关闭(&X)
+
+
+PREFIX D_EM_ADD
+STATIC1 用于æ•èŽ·çš„网络适é…器å称(&L):
+R_PROMISCUS æ•èŽ·æ—¶ä¸è¦ä½¿ç”¨æ··æ‚模å¼(&N)
+STATIC2 æ•°æ®åŒ…日志 (&P) :
+S_PACKET 日志文件切æ¢å‘¨æœŸ (&W) :
+S_PACKET_0 TCP 连接日志:
+B_PACKET_0_0 没有ä¿å­˜
+B_PACKET_0_1 仅标头信æ¯
+B_PACKET_0_2 æ•°æ®åŒ…所有内容
+S_PACKET_1 TCP æ•°æ®åŒ…日志:
+B_PACKET_1_0 没有ä¿å­˜
+B_PACKET_1_1 仅标头信æ¯
+B_PACKET_1_2 æ•°æ®åŒ…所有内容
+S_PACKET_2 DHCP æ•°æ®åŒ…日志:
+B_PACKET_2_0 没有ä¿å­˜
+B_PACKET_2_1 仅标头信æ¯
+B_PACKET_2_2 æ•°æ®åŒ…所有内容
+S_PACKET_3 UDP æ•°æ®åŒ…日志:
+B_PACKET_3_0 没有ä¿å­˜
+B_PACKET_3_1 仅标头信æ¯
+B_PACKET_3_2 æ•°æ®åŒ…所有内容
+S_PACKET_4 ICMP æ•°æ®åŒ…日志:
+B_PACKET_4_0 没有ä¿å­˜
+B_PACKET_4_1 仅标头信æ¯
+B_PACKET_4_2 æ•°æ®åŒ…所有内容
+S_PACKET_5 IP æ•°æ®åŒ…日志:
+B_PACKET_5_0 没有ä¿å­˜
+B_PACKET_5_1 仅标头信æ¯
+B_PACKET_5_2 æ•°æ®åŒ…所有内容
+S_PACKET_6 ARP æ•°æ®åŒ…日志:
+B_PACKET_6_0 没有ä¿å­˜
+B_PACKET_6_1 仅标头信æ¯
+B_PACKET_6_2 æ•°æ®åŒ…所有内容
+S_PACKET_7 以太网\r\næ•°æ®åŒ…日志:
+B_PACKET_7_0 没有ä¿å­˜
+B_PACKET_7_1 仅标头信æ¯
+B_PACKET_7_2 æ•°æ®åŒ…所有内容
+IDOK 确定(&O)
+IDCANCEL å–消
+STATIC3 ä¿å­˜å¤§é‡æ•°æ®åŒ…日志会给CPU和硬盘带æ¥æ²‰é‡è´Ÿæ‹…,并且å¯èƒ½å¯¼è‡´ç³»ç»Ÿæ•´ä½“性能下é™ã€‚请é…置设置以使必须的日志被ä¿å­˜ã€‚
+
+
+PREFIX D_EM_PASSWORD
+CAPTION å˜æ›´ç®¡ç†å‘˜å¯†ç 
+S_TITLE 您å¯ä»¥å˜æ›´ç®¡ç†å‘˜å¯†ç ã€‚输入åŽè¯·ç‚¹å‡»â€œç¡®å®šâ€ã€‚
+STATIC1 æ–°å¯†ç  (&P) :
+STATIC2 确认 (&C) :
+IDOK 确定(&O)
+IDCANCEL Cancel
+
+
+PREFIX D_EM_LICENSE
+CAPTION 添加或删除许å¯è¯
+STATIC1 è¦ä½¿ç”¨ SoftEther 以太网记录器,您必须获å–一个有效地许å¯è¯å¹¶æ³¨å†Œè®¸å¯è¯å¯†é’¥ã€‚使用此窗å£ï¼Œæ‚¨å¯ä»¥æ³¨å†Œä¸€ä¸ªæ–°çš„许å¯è¯å¯†é’¥ï¼Œåˆ é™¤ä¸€ä¸ªå·²æ³¨å†Œçš„许å¯è¯å¯†é’¥ï¼Œæ˜¾ç¤ºå½“å‰è®¸å¯è¯åˆ—表和许å¯è¯æ¨¡å¼ã€‚
+S_BOLD 当å‰å·²æ³¨å†Œè®¸å¯è¯åˆ—表 (&L) :
+B_OBTAIN 获å–许å¯è¯ (&O)
+STATIC2 点击“获å–许å¯è¯â€ æ¥æ˜¾ç¤ºä»‹ç»å¦‚何获å–许å¯è¯çš„网站。
+B_ADD 注册新许å¯è¯å¯†é’¥
+B_DEL 删除 (&D)
+IDOK 许å¯è¯ç›¸å…³ä¿¡æ¯ (&I)
+STATIC3 选择一个许å¯è¯ï¼Œç‚¹å‡»â€œè®¸å¯è¯ç›¸å…³ä¿¡æ¯â€ æ¥è¿žæŽ¥åˆ°SoftEther有é™å…¬å¸ç½‘ç«™ (softether.com),æ¥æŸ¥è¯¢è¢«é€‰è®¸å¯è¯çš„相关注册信æ¯ã€‚
+S_BOLD2 å½“å‰ SoftEther 以太网记录器许å¯è¯æ¨¡å¼ (&M) :
+IDCANCEL 关闭 (&X)
+
+
+PREFIX D_EM_LICENSE_ADD
+CAPTION 注册新许å¯è¯å¯†é’¥
+S_INFO 您å¯ä»¥æ³¨å†Œä¸€ä¸ª SoftEther 以太网记录器产å“许å¯è¯å¯†é’¥ã€‚
+STATIC1 许å¯è¯å¯†é’¥ç”±36个字æ¯æ•°å­—字符和连字符组æˆã€‚它是è¯æ˜Žè®¸å¯è¯æ‰€æœ‰æƒçš„关键代ç ã€‚\r\n\r\n当此软件收到一个许å¯è¯è¯ä¹¦æ—¶ï¼Œè®¸å¯è¯å¯†é’¥å°±è¢«æ‰“å°åˆ°æ­¤è®¸å¯è¯è¯ä¹¦ä¸Šäº†ã€‚如果此许å¯è¯æ˜¯åœ¨çº¿è´­ä¹°çš„,则许å¯è¯å¯†é’¥å¯ä»¥é€šè¿‡emailæ供,并在购买页é¢æ˜¾ç¤ºã€‚许å¯è¯å¯†é’¥ä¹Ÿå¯èƒ½é€šè¿‡å…¶ä»–æ–¹å¼é€è¾¾ã€‚如果您ä¸çŸ¥é“许å¯è¯å¯†é’¥ä½ç½®ï¼Œè¯·å‘许å¯è¯å‡ºå”®è€…询问。
+STATIC2 请输入正确的许å¯è¯å¯†é’¥ (&I) :
+STATIC3 æ¯ç»„6字,分组输入许å¯è¯å¯†é’¥ã€‚您ä¸éœ€è¦è¾“入连字符。也å¯ä»¥å¤åˆ¶&&粘贴许å¯è¯å¯†é’¥ã€‚
+B_INFO2 此软件有世界范围的著作æƒä¿æŠ¤ã€‚消费者åªå¯ä»¥åœ¨è®¸å¯è¯å…许范围内å¤åˆ¶å’Œä½¿ç”¨æ­¤è½¯ä»¶ã€‚警告: 使用éžæ³•èŽ·å¾—的许å¯è¯å¯†é’¥ï¼Œæˆ–在多å°æœåŠ¡å™¨ä¸Šä½¿ç”¨ä¸€ä¸ªè®¸å¯è¯ï¼Œæˆ–以éžè®¤è¯çš„æ–¹å¼èŽ·å¾—许å¯è¯ï¼Œä¼šå¯¼è‡´æ°‘事或刑事处罚。
+IDOK 注册 (&R)
+IDCANCEL å–消
+
+PREFIX D_EM_REMOTE
+STATIC1 指定目标计算机的主机å或 IP åœ°å€ (&S) :
+R_LOCAL 连接到本地计算机 (显示在此窗å£çš„计算机) (&L)
+S_HOSTNAME 计算机å称 (&C) :
+IDOK 确定(&O)
+IDCANCEL å–消
+B_ABOUT 版本信æ¯
+
+PREFIX D_SM_CONFIG
+CAPTION 编辑é…置文件
+IDC_INFO VPN Server“%Sâ€çš„当å‰é…置如下。\r\n您å¯ä»¥ç¼–辑此é…置文件的内容并应用到 VPN Server。
+B_EXPORT ä¿å­˜åˆ°æ–‡ä»¶ (&S)
+B_IMPORT 导入文件并应用 (&I)
+IDCANCEL 关闭 (&C)
+STATIC1 您å¯ä»¥ä½¿ç”¨ä»»ä¸€æ–‡æœ¬ç¼–辑器编辑é…置文件。当把已编辑的é…置文件应用到 VPN Server 时, VPN Server 将自动é‡å¯ï¼Œå¹¶æ ¹æ®æ–°çš„é…置文件开始。如果应用一个无效的é…置文件,程åºä¼šæŠ¥é”™ï¼Œå¹¶ä¸”当å‰è®¾ç½®å†…容å¯èƒ½ä¼šä¸¢å¤±ï¼Œæ‰€ä»¥è¯·è°¨æ…Žç¼–辑é…置文件。
+B_FACTORY æ¢å¤å‡ºåŽ‚默认值
+
+PREFIX D_SM_ADMIN_OPTION
+CAPTION 虚拟 HUB 管ç†é€‰é¡¹
+S_INFO 当å‰å·²ä¸ºè™šæ‹Ÿ HUB "%S" 设置如下管ç†é€‰é¡¹ã€‚
+B_ADD 添加值(&A)
+B_EDIT 编辑值(&E)
+B_DELETE 删除值(&D)
+STATIC1 虚拟 HUB 管ç†é€‰é¡¹çš„目的是给在虚拟 HUB 管ç†æ¨¡å¼çš„管ç†å‘˜è®¾ç½®çš„é™åˆ¶ã€‚
+IDOK ä¿å­˜(&S)
+IDCANCEL å–消
+STATIC2 åªæœ‰æ•´ä¸ª VPN Server 的管ç†å‘˜å¯ä»¥ç¼–辑虚拟 HUB 管ç†é€‰é¡¹ã€‚个别虚拟 HUB 的管ç†å‘˜åªèƒ½æŸ¥çœ‹ä½†ä¸èƒ½ä¿®æ”¹ç®¡ç†é€‰é¡¹ã€‚\r\n然而,如果 allow_hub_admin_change_option 被设为"1",那么虚拟 HUB 管ç†å‘˜å°±å¯ä»¥ç¼–辑管ç†é€‰é¡¹ã€‚
+S_BOLD æè¿°:
+
+
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã‹ã‚‰ -----
+PREFIX D_SM_MSG
+CAPTION 设置消æ¯
+S_MSG_2 当一个 VPN Client 接入到虚拟 HUB "%S" 时,您å¯ä»¥è®¾ç½®æ¶ˆæ¯æ˜¾ç¤ºåœ¨ä¸€ä¸ªç”¨æˆ·çš„å±å¹•ä¸Šã€‚è¦æ˜¾ç¤ºä¸€ä¸ªæ¶ˆæ¯ï¼Œè¾“入你想è¦æ˜¾ç¤ºçš„消æ¯ã€‚
+C_USEMSG 显示消æ¯(&M)
+STATIC1 关于消æ¯æ˜¾ç¤ºåŠŸèƒ½
+S_INFO VPN Client 必须是 3.0 或更高版本。\r\n\r\n指定以“http://â€å¼€å¤´çš„一行作为打开默认网站æµè§ˆå™¨çš„消æ¯ï¼Œè€Œä¸æ˜¯ç›´æŽ¥æ˜¾ç¤ºä¸€æ¡æ¶ˆæ¯ã€‚
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_NICINFO
+CAPTION 虚拟网络适é…器 "%S" 状æ€
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_VLAN
+CAPTION VLAN é€æ˜Žè®¾ç½®å·¥å…·
+STATIC1 有些网络适é…器默认ä¸èƒ½ä¼ è¾“标记的 VLAN é€æ˜Žæ•°æ®åŒ…(IEEE802.1Q)。\r\n\r\n如果你使用这样一个网络适é…器æ¥æ¡¥æŽ¥åˆ°è™šæ‹Ÿ HUB 并需è¦äº¤æ¢å¸¦ VLAN 标签的以太网数æ®åŒ…,您必须é…置网络适é…å™¨ï¼Œä½¿å…¶èƒ½å¤Ÿå¤„ç† VLAN é€æ˜Žæ•°æ®åŒ…。
+B_ENABLE é…置已选网络适é…器为 VLAN é€æ˜Ž(&C)
+B_DISABLE 撤消该é…ç½®(&U)
+STATIC2 关于 VLAN é€æ˜Žè®¾ç½®å·¥å…·
+S_WARNING 该工具å¯ä»¥åœ¨è‹±ç‰¹å°”,Broadcom å’Œ Marvell 的网络适é…器中开å¯æˆ–关闭标记 VLAN æ•°æ®åŒ…çš„é€æ˜Žåº¦ã€‚(Windows 仅使用供应商æ供的驱动)。此工具å¯ä»¥å¯ç”¨æˆ–ç¦ç”¨åœ¨ Intel,Broadcom 或 Marvell 网络适é…器中标记的 VLAN æ•°æ®åŒ…çš„é€æ˜Žåº¦ã€‚(仅使用供应商æ供的 Windows 驱动程åº)。
+S_WARNING2 本工具仅支æŒä¸Šè¿°åˆ—表中的网络适é…器。其他网络适é…器ä¸èƒ½ç”¨æ­¤å·¥å…·é…置。。但是未在此列表的其他网络适é…器有å¯èƒ½é»˜è®¤æ”¯æŒæˆ–使用一些é…置支æŒå·²æ ‡è®°çš„ VLAN æ•°æ®åŒ…。。\r\n\r\n这样的网络适é…器必须由系统管ç†å‘˜ç™»å½• Windows é…置。
+IDCANCEL 退出(&X)
+
+
+PREFIX D_SM_SIMULATION
+CAPTION 延迟 / 丢包功能
+STATIC1 通过这个虚拟 HUB 传输时,此功能å¯ä»¥ç”Ÿæˆç¬¦åˆæ­¤è®¿é—®åˆ—表æ¡ç›®æ¡ä»¶çš„æ•°æ®åŒ…的延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。\r\n\r\n此功能方便在桌é¢æˆ–实验室模拟低质的和慢速的互è”网ã€å¹¿åŸŸç½‘或无线连接。例如,你å¯ä»¥ç”¨å®ƒæ¥è¯„估和测试 IP 电è¯(VoIP)。
+STATIC2 产生如下延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失:
+C_DELAY 产生延迟(&D)
+S_DELAY 延迟周期(0 - 10000) :
+S_DELAY2 毫秒 (msecs)
+C_JITTER 产生时基误差(波动)(&J)
+S_JITTER 时基误差比率 (0 - 100) :
+S_JITTER2 百分比(%)
+C_LOSS 产生数æ®åŒ…丢失(&L)
+S_LOSS æ•°æ®åŒ…丢失比率(0 - 100) :
+S_LOSS2 百分比(%)
+IDOK 确定(&O)
+IDCANCEL å–消
+# ----- ä¸å®Œå…¨ç¿»è¨³ã“ã“ã¾ã§ -----
+
+
+PREFIX D_SM_AO_VALUE
+CAPTION å称和值
+STATIC1 å称(&N):
+STATIC2 值(&V):
+STATIC3 (整数值)
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_L3
+CAPTION 虚拟 3 层交æ¢è®¾ç½®
+STATIC1 您å¯ä»¥å®šä¹‰åœ¨æ­¤ VPN Server 上è¿è¡Œçš„两个或多个虚拟 HUB 间的虚拟 3 层交æ¢ï¼Œæ¥å®žçŽ°ä¸åŒ IP 网络之间的路由。
+STATIC2 虚拟 3 层交æ¢åŠŸèƒ½ä»…æ供给网络管ç†å‘˜æˆ–数值网络和 IP 路由人员使用。如果您è¦ä½¿ç”¨å¸¸è§„ VPN 功能,您ä¸éœ€è¦ä½¿ç”¨è™šæ‹Ÿ 3 层交æ¢åŠŸèƒ½ã€‚\r\n\r\n如果使用虚拟 3 层交æ¢åŠŸèƒ½ï¼Œä½¿ç”¨è€…必须有足够的 IP 路由知识。
+STATIC3 关于虚拟 3 层交æ¢åŠŸèƒ½æ³¨æ„事项
+S_BOLD 已定义的虚拟 3 层交æ¢(&S):
+B_ADD 新建(&N)
+B_START 开始(&S)
+B_STOP åœæ­¢(&T)
+IDOK 编辑(&E)
+B_DELETE 删除(&D)
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_L3_ADD
+CAPTION 新虚拟 3 层交æ¢
+STATIC1 创新建一个新的虚拟 3 层交æ¢ï¼Œä¸ºè¾“入一个交æ¢æœºå称。\r\n\r\n此虚拟 3 层交æ¢ä¸èƒ½ä¸Žæ­¤ VPN Server 上的其它虚拟 3 层交æ¢æœ‰é‡å¤çš„å字。
+STATIC2 åå­—(&N):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_L3_SW
+CAPTION 编辑虚拟 3 å±‚äº¤æ¢ "%S"
+STATIC1 您å¯ä»¥ä¸ºä¸€ä¸ªè™šæ‹Ÿ 3 层交æ¢å®šä¹‰å¤šä¸ªè™šæ‹ŸæŽ¥å£å’Œè·¯ç”±è¡¨ã€‚
+STATIC2 当虚拟 HUB è¿è¡Œæ—¶ï¼Œä¸€ä¸ªè™šæ‹ŸæŽ¥å£è¢«å…³è”到虚拟 HUB 上,并作为一个å•ç‹¬çš„ IP 主机è¿è¡Œã€‚当多个虚拟接å£åˆ†åˆ«å±žäºŽä¸åŒè™šæ‹Ÿ HUB 定义的ä¸åŒ IP 网络时,IP 路由将会自动在这些接å£ä¹‹é—´ä½¿ç”¨ã€‚\r\n也å¯ä»¥æ‰‹åŠ¨è®¾ç½®è·¯ç”±è¡¨å’Œå…¶ä»–详细设置。
+S_BOLD1 虚拟接å£(&I):
+B_ADD_IF 新虚拟接å£(&A)
+B_DEL_IF 删除虚拟接å£(&E)
+S_BOLD2 路由表(&T):
+B_ADD_TABLE 添加路由表项(&D)
+B_DEL_TABLE 删除路由表项(&L)
+B_START 开始(&S)
+B_STOP åœæ­¢(&T)
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_L3_SW_IF
+CAPTION 添加虚拟接å£
+STATIC1 对虚拟 3 层交æ¢æœºæ·»åŠ æ–°çš„虚拟接å£ã€‚\r\n\r\n您必须定义虚拟接å£å±žäºŽçš„ IP 网络和接å£æœ¬èº«çš„ IP 地å€ã€‚\r\n请选择或输入该接å£è¦è¿žæŽ¥çš„虚拟 HUB å称。
+STATIC2 虚拟 HUB 连接(&A):
+STATIC3 请选择或输入虚拟接å£è¿žæŽ¥çš„虚拟 HUB å称。
+STATIC4 虚拟 HUB (&H):
+STATIC5 虚拟接å£çš„ IP 地å€å’Œå­ç½‘掩ç :
+STATIC6 虚拟接å£å¿…须在虚拟 HUB 中有一个 IP 地å€ã€‚您也必须指定此 IP 地å€ä»Žå±žçš„ IP 网络的å­ç½‘掩ç ã€‚\r\n\r\n通过虚拟 3 层交æ¢è¿žæŽ¥åˆ°å¤šä¸ªè™šæ‹Ÿ HUB 的路由是基于此处指定的 IP 地å€è¿è¡Œçš„。
+S_SRC_IP_1 IP 地å€(&I):
+S_SRC_IP_2 å­ç½‘掩ç (&S):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_L3_SW_TABLE
+CAPTION 新路由表项
+STATIC1 在虚拟 3 层交æ¢æœºçš„路由表增加一个新的路由表项。\r\n\r\n如果 IP æ•°æ®åŒ…的目标 IP 地å€ä¸å±žäºŽä»»ä½•æœ‰ç€è™šæ‹ŸæŽ¥å£çš„ IP 网络,虚拟 3 层交æ¢æœºçš„ IP 路由引擎将å‚考路由表并且执行路由。
+STATIC2 路由表项的定义:
+STATIC3 虚拟接å£å¿…须在虚拟 HUB 中有一个 IP 地å€ã€‚您也必须指定此 IP 地å€ä»Žå±žçš„ IP 网络的å­ç½‘掩ç ã€‚\r\n\r\n通过多个虚拟 HUB IP 网空间的虚拟 3 层交æ¢æœºæ˜¯åŸºäºŽæ­¤å¤„指定的 IP 地å€è¿è¡Œçš„。
+S_SRC_IP_1 网络地å€(&N):
+S_SRC_IP_2 å­ç½‘掩ç (&S):
+S_SRC_IP_3 网关地å€(&G):
+S_SRC_IP_4 公制值(&M):
+STATIC4 ※注æ„: 指定默认网关,指定网络地å€å’Œå­ç½‘掩ç éƒ½æ˜¯â€œ0.0.0.0“。
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_CM_SELECT_SECURE
+CAPTION 选择智能å¡
+STATIC1 选择智能å¡è®¾å¤‡ä½¿ç”¨ã€‚\r\n\r\n智能å¡çš„ç§ç±»å·²åˆ—在目å‰ä½¿ç”¨ç”µè„‘é©±åŠ¨çš„åˆ—è¡¨ä¸­å¹¶æ”¯æŒ VPN 软件。\r\n如果现在使用的智能å¡ç§ç±»æœªæ˜¾ç¤ºåœ¨æ­¤åˆ—表中,å¯ä»¥é€šè¿‡å‡çº§ VPN 软件到新的版本æ¥å®žçŽ°ã€‚\r\n\r\n注: 如果在安装åŽï¼Œé©±åŠ¨æ²¡æœ‰ç«‹å³æ˜¾ç¤ºå‡ºæ¥ï¼Œé‡å¯ Windows。
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_CM_SECURE_MANAGER
+CAPTION 智能å¡ç®¡ç†å™¨
+S_INFO 当å‰æ™ºèƒ½å¡:\r\n\r\n%S
+B_BOLD 智能å¡ä¸Šå­˜å‚¨çš„对象:
+B_REFRESH 更新对象列表(&R)
+B_IMPORT 导入å¡å†…(&I)...
+B_EXPORT 从å¡ä¸­å¯¼å‡º(&E)...
+B_DELETE 从å¡ä¸­åˆ é™¤(&D)
+B_NEW_CERT 将新è¯ä¹¦å’Œå¯†é’¥å†™å…¥å¡å†…(&N)...
+B_PIN 更改 PIN ç (&C)...
+IDCANCEL 关闭
+
+
+PREFIX D_CM_SECURE_TYPE
+CAPTION 选择对象类型
+STATIC 选择你è¦å¯¼å…¥çš„对象类型
+R_CERT è¯ä¹¦(&C)
+R_KEY 密钥(&K)
+R_DATA æ•°æ®(&D)
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_STRING
+CAPTION VPN 软件
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_SELECT_KEYPAIR
+CAPTION 指定智能å¡è¯ä¹¦
+S_INFO 当å‰é€‰å®šçš„智能å¡:\r\n\r\n%S
+B_BOLD1 选择智能å¡è¯ä¹¦:
+IDOK 确定(&O)
+IDCANCEL å–消
+B_BOLD2 选择相应的密钥:
+
+
+PREFIX D_CM_LOAD_X
+CAPTION 加载è¯ä¹¦
+STATIC1 选择加载è¯ä¹¦çš„æ–¹å¼
+R_FROM_FILE 从文件中加载è¯ä¹¦(&F)
+R_FROM_SECURE 从智能å¡ä¸­åŠ è½½è¯ä¹¦(&S)
+S_FILE 您å¯ä»¥ä»Žå­˜å‚¨è¯ä¹¦æ•°æ®çš„文件中 (扩展å: .cer, .crt, .p12, .pfx) 加载è¯ä¹¦ã€‚
+S_CERT 如果智能å¡ä¸Žè®¡ç®—机连接,您å¯ä»¥ä»Žæ™ºèƒ½å¡ä¸­åŠ è½½è¯ä¹¦ã€‚
+B_SELECT 选择è¦ä½¿ç”¨çš„智能å¡(&S)...
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_CM_SECURE_PIN
+CAPTION 更改 PIN ç 
+STATIC1 您å¯ä»¥æ›´æ”¹æ™ºèƒ½å¡çš„ PINç  (个人识别å·ç )。\r\n\r\n更改 PIN ç ï¼Œæ‚¨éœ€è¦è¾“入当å‰çš„ PIN ç å’Œ 2 次新的 PIN ç ã€‚
+STATIC2 当å‰çš„ PIN ç (&C):
+STATIC3 æ–°çš„ PIN ç (&N):
+STATIC4 确认新的 PIN ç (&E):
+STATIC5 注æ„
+STATIC6 如果您错误地输入几次密ç ï¼Œæ™ºèƒ½å¡å°†ä¸èƒ½ä½¿ç”¨ã€‚
+STATIC7 请æ’入智能å¡å¹¶ä¸”点击“OKâ€ã€‚
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_CRL
+CAPTION 废止è¯ä¹¦åˆ—表
+STATIC1 您å¯ä»¥åœ¨è™šæ‹Ÿ HUB 上管ç†è¯ä¹¦åºŸæ­¢åˆ—表。\r\n\r\n通过添加è¯ä¹¦åˆ°è¯ä¹¦åºŸæ­¢åˆ—表,æ供这些è¯ä¹¦çš„客户端将被拒ç»è¿žæŽ¥åˆ°ä½¿ç”¨è¯ä¹¦è®¤è¯æ¨¡å¼çš„此虚拟 HUB。
+B_ADD 添加(&A)
+IDOK 编辑(&E)
+IDCANCEL 关闭(&C)
+B_DELETE 删除(&D)
+
+
+PREFIX D_SM_EDIT_CRL
+CAPTION 废止è¯ä¹¦
+STATIC1 您å¯ä»¥åœ¨åºŸæ­¢åˆ—表中设置æ¡ç›®çš„内容。\r\n\r\n当一个用户以è¯ä¹¦è®¤è¯æ¨¡å¼è¿žæŽ¥ä¸€ä¸ªè™šæ‹Ÿ HUB 时,并且该è¯ä¹¦ä¸Žè¯ä¹¦åºŸæ­¢åˆ—表中定义的一个或多个的内容相匹é…,这个用户将被拒ç»è¿žæŽ¥ã€‚
+S_BOLD 匹é…项目所有字段的è¯ä¹¦å°†è¢«ç¦ç”¨ã€‚
+STATIC2 è¯ä¹¦å†…容:
+R_CN 通用å称 (CN):
+R_O 所属机构 (O):
+R_OU 组织å•ä½ (OU):
+R_C 国家 (C):
+R_ST çœ (ST):
+R_L 地点 (L):
+STATIC3 è¯ä¹¦å±žæ€§å€¼:
+R_SERI åºåˆ—å· (å六进制):
+R_MD5_HASH MD5 摘è¦å€¼ (以å六进制,128ä½):
+R_SHA1_HASH SHA-1 摘è¦å€¼ (以å六进制,160ä½):
+STATIC4 摘è¦å€¼(哈希值)å¯ä»¥ç²¾ç¡®åœ°è¯†åˆ«ç‰¹å®šçš„è¯ä¹¦ã€‚如果你指定了一个 MD5 或 SHA-1 摘è¦å€¼ï¼Œä½ ä¸éœ€è¦æŒ‡å®šå…¶ä»–项目。
+STATIC5 从è¯ä¹¦æ–‡ä»¶çš„输入值
+STATIC6 如果您è¦ç¦ç”¨ä¸€ä¸ªè¯ä¹¦æ–‡ä»¶ï¼Œæ‚¨å¯ä»¥æ­£ç¡®åœ°æŒ‡å®šè¯ä¹¦ï¼Œå¹¶é€šè¿‡è¾“入那个文件将其添加到无效清å•ã€‚å•å‡»â€œåŠ è½½è¯ä¹¦â€ï¼ŒæŒ‡å®šè¯ä¹¦æ–‡ä»¶çš„内容将被自动输入。
+B_LOAD 加载è¯ä¹¦(&L)...
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_AC_LIST
+CAPTION æº IP 地å€é™åˆ¶åˆ—表
+S_TITLE æ ¹æ®å®¢æˆ·ç«¯è®¡ç®—机的 IP 地å€ï¼Œå…许或拒ç»åˆ°æ­¤è™šæ‹Ÿ HUB "%S" çš„ VPN 连接,您å¯ä»¥è®¾ç½®ä»¥ä¸‹è§„则æ¥å…许或拒ç»è¿žæŽ¥ã€‚
+B_ADD 新规则(&A)
+IDOK 编辑规则(&E)
+B_DELETE 删除规则(&D)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL å–消(&C)
+STATIC1 较高æƒé™çš„项目列在列表的上方。
+STATIC2 如果客户端的 IP 地å€ä¸åŒ¹é…列表中的任何项目,VPN 连接到此虚拟 HUB 将被å…许。
+
+
+PREFIX D_SM_AC
+CAPTION ç¼–è¾‘æº IP 地å€é™åˆ¶åˆ—表的规则æ¡ç›®
+STATIC1 在 IP 地å€è®¿é—®æŽ§åˆ¶åˆ—表中定义一个规则。当客户端试图连接到虚拟 HUB 时,这里设置的值将用于决定是å¦å…许或拒ç»ä»Ž VPN Client 的连接。
+STATIC2 规则的定义
+STATIC3 当客户端的 IP 地å€ä¸Žä¸‹é¢ç›¸åŒ¹é…时应用此规则:
+R_SINGLE å•ä¸€ IP 地å€(&S)
+R_MASKED 多个 IP 地å€(通过 IP 地å€å’ŒæŽ©ç æŒ‡å®š) (&M) :
+STATIC4 地å€(&A):
+S_MASK 网络掩ç (&K):
+STATIC5 行为
+R_PASS å…许 (&P)
+R_DENY æ‹’ç» (&D)
+STATIC6 其他
+STATIC7 优先级(&R):
+STATIC8 (æ•´æ•°: 优先级越高数é‡è¶Šå°)
+STATIC9 IP å议版本:
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_LOG_FILE
+CAPTION 日志文件列表
+STATIC1 您å¯ä»¥ä¸‹è½½å­˜å‚¨åœ¨æœåŠ¡å™¨ä¸Šçš„日志文件。整个 VPN Server 的管ç†å‘˜å…许下载所有虚拟 HUB 日志和æœåŠ¡å™¨æ—¥å¿—记录。虚拟 HUB 管ç†å‘˜å…许下载其管ç†çš„虚拟 HUB 日志文件。
+IDOK 下载(&D)
+B_REFRESH æ›´æ–°(&R)
+IDCANCEL 关闭
+
+
+PREFIX D_SM_READ_LOG_FILE
+CAPTION 下载文件
+S_INFO2 VPN Server "%S" 文件下载中。\r\n请ç¨å€™...
+IDCANCEL åœæ­¢ä¸‹è½½(&S)
+
+
+PREFIX D_SM_SAVE_LOG
+CAPTION 下载的日志文件
+S_INFO 文件 "%S" 已完æˆä¸‹è½½ã€‚\r\n\r\n您å¯ä»¥æ‰“开或ä¿å­˜è¿™ä¸ªæ–‡ä»¶ã€‚
+IDOK 打开(&O)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL å–消
+
+
+PREFIX D_TCP
+CAPTION TCP å议优化工具
+STATIC1 通过优化 Windows TCP/IP 设置,就有å¯èƒ½å¢žåŠ è¿™å°è®¡ç®—机的网络通信åžåé‡ã€‚通过使用这个 TCP å议优化工具,您å¯ä»¥è½»æ¾åœ°é…置最佳优化å‚数的设置。
+STATIC2 Windows çš„å½“å‰ TCP/IP 设置å‚数如下。通过改å˜è¿™äº›å€¼å¯ä»¥ä¼˜åŒ– TCP/IP 设置。通过使用该实用程åºï¼Œä»¥åŽæ‚¨éšæ—¶å¯ä»¥é‡ç½®æ­¤å€¼æˆ–æ¢å¤ä»¥å‰çš„设置。
+STATIC3 TCP/IP 通信设置:
+STATIC4 TCP 接收窗å£ä¸Žå°ºå¯¸(&S):
+R_RECV_DISABLE 使用æ“作系统和默认值(&D)
+R_RECV_ENABLE 设置值如下(&E)
+S_RECV 字节
+B_RECV 默认值(&C)
+STATIC5 TCP å‘é€çª—å£å°ºå¯¸(&R):
+R_SEND_DISABLE 使用æ“作系统和默认值(&I)
+R_SEND_ENABLE 设置值如下(&N)
+S_SEND 字节
+B_SEND 默认值(&O)
+IDOK 确定(&O)
+IDCANCEL å–消
+STATIC6 Windows é‡å¯åŽï¼Œä¸Šè¿°æ›´æ”¹ç”Ÿæ•ˆã€‚更改设置åŽï¼Œæ‚¨ä¸å¿…ç«‹å³é‡å¯è®¡ç®—机,但直到é‡å¯åŽï¼ŒTCP/IP 优化设置æ‰ä¼šç”Ÿæ•ˆã€‚
+B_DELETE ä¸ç”¨æ­¤å·¥å…·ç®¡ç†
+
+
+PREFIX D_TCP_MSG
+CAPTION TCP å议优化
+STATIC1 通过 Windows 优化 TCP/IP 设置,有å¯èƒ½å¢žåŠ è¿™å°ç”µè„‘的网络通信åžåé‡ã€‚您想优化通信设置å—?\r\n\r\n您å¯ä»¥åœ¨æœªæ¥éšæ—¶å¯åŠ¨ TCP å议优化工具,优化通信设置或æ¢å¤åˆ°ä»–们以å‰çš„值。
+STATIC2 当 TCP/IP 设置被更改,Windows é‡å¯åŽï¼Œæ›´æ”¹ç”Ÿæ•ˆã€‚更改设置åŽï¼Œæ‚¨ä¸å¿…ç«‹å³é‡å¯è®¡ç®—机,但直到é‡å¯åŽï¼ŒTCP/IP 优化设置æ‰ä¼šç”Ÿæ•ˆã€‚
+R_OPTIMIZE 自动优化通讯设置(&A)
+R_MANUAL 使用 TCP å议优化工具手动优化(&M)
+R_NO ä¸è¦ä¼˜åŒ–(&D)
+IDOK 下一步(&N) >
+IDOK3 < 上一步(&B)
+
+
+PREFIX D_CM_PKCSEULA
+CAPTION 请注æ„使用智能å¡é©±åŠ¨ç¨‹åº¦
+S_INFO_1 您正在试图访问 "%S" 软件的智能å¡ã€‚
+S_INFO_2 当使用 "%S" 软件时,如果有这个软件和智能å¡çš„使用æ¡ä»¶ï¼Œé‚£ä¹ˆæ‚¨åœ¨ä½¿ç”¨å‰å¿…é¡»åŒæ„这些使用æ¡ä»¶ã€‚\r\n\r\n若需详情请è”ç³» "%S" 软件和智能å¡çš„供应商。
+S_INFO_3 您是å¦åŒæ„上述æ¡ä»¶ï¼Œå¹¶å¸Œæœ›ä½¿ç”¨ "%S" 软件和访问指定的智能å¡?
+IDOK 是(&Y)
+IDCANCEL å¦(&N)
+
+
+PREFIX D_CM_TRAFFIC
+CAPTION 网络通信速度测试工具
+STATIC1 网络æµé‡é€Ÿåº¦æµ‹è¯•å·¥å…·åœ¨ä¸¤å°è®¡ç®—机之间连接 TCP/IP å°½å¯èƒ½å¤§çš„åžåé‡è¿›è¡Œæ•°æ®åŒ…传输,以测é‡å®žé™…网络æµé‡å¯ç”¨é€Ÿåº¦ã€‚此工具ä¸ä»…é™äºŽ VPN 使用,还å¯ä»¥ç”¨äºŽç‰©ç†ç½‘络。
+STATIC2 使用此工具æ¥æµ‹é‡å½“å‰ç½‘络带宽容é‡ã€‚请注æ„,由于两端点 CPU 性能ã€å½“å‰æ­£åœ¨è¿è¡Œçš„其他程åºå’Œç½‘络使用率的波动,获å–的值有时会低于实际的网络处ç†èƒ½åŠ›ã€‚
+S_1 é…ç½®
+S_3 è¿™å°ç”µè„‘的作用是哪一个?
+R_SERVER 测试æœåŠ¡å™¨(&S)
+R_CLIENT 测试客户端(&C)
+S_4 激活测试æœåŠ¡å™¨ï¼ŒæŒ‡å®šä¾¦å¬ç«¯å£å·ã€‚\r\n使用它作为测试客户端,指定目标测试æœåŠ¡å™¨çš„主机å或 IP 地å€å’Œç«¯å£å·ã€‚如果有必è¦ï¼Œé…置以下å¯é€‰è®¾ç½®ã€‚
+S_5 目标测试æœåŠ¡å™¨ä¸»æœºå称(&H):
+S_6 端å£å·(&P):
+S_7 (TCP 端å£)
+S_8 在客户端é…置如下选项。
+S_9 æ•°æ®é€šä¿¡æ–¹å‘
+R_DOWNLOAD 下载 (输入: 从æœåŠ¡å™¨åˆ°å®¢æˆ·ç«¯) (&D)
+R_UPLOAD 上传 (输出: 从客户端到æœåŠ¡å™¨) (&U)
+R_FULL 下载和上传 (å…¨åŒå·¥æ¨¡å¼: 进与出åŒæ—¶è¿›è¡Œ) (&F)
+S_10 高级设置
+S_11 åŒæ—¶å¹¶è¡Œçš„ TCP 连接数(&N):
+S_12 测é‡å‘¨æœŸ (&A):
+S_13 秒
+R_ETHERNET 纠正第二层åžåé‡å‡è®¾ä»¥å¤ªç½‘(&E)
+R_DOUBLE 中继设备模å¼(&B)
+S_14 连接
+IDOK è¿è¡Œ(&R)
+IDCANCEL å–消
+S_15 您还å¯ä»¥ä»Ž vpncmd 命令行管ç†å·¥å…·è¿è¡Œæ­¤å·¥å…·ã€‚ (éž Windows æ“作系统也适用)。
+
+
+PREFIX D_CM_TRAFFIC_RUN
+CAPTION 网络通讯速度测试工具
+S_INFO 网络通讯速度测试工具正在è¿è¡Œã€‚æ“作状æ€å¦‚下。
+STATIC1 è¦ä¸­æ­¢ç½‘络通讯速度测试工具,å•å‡»â€œé€€å‡ºâ€ã€‚
+IDCANCEL 退出(&X)
+
+
+PREFIX D_CM_TRAFFIC_RESULT
+CAPTION 通讯æµé‡æµ‹é‡ç»“æžœ
+STATIC1 通讯æµé‡æµ‹é‡å·²å®Œæˆã€‚结果如下。
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_LICENSE
+CAPTION 添加或删除许å¯è¯
+STATIC1 使用 SoftEther VPN Server å¿…é¡»å–得有效的许å¯è¯å¹¶æ³¨å†Œè®¸å¯è¯å¯†é’¥ã€‚ä½ å¯ä»¥æ³¨å†Œä¸€ä¸ªæ–°çš„许å¯è¯å¯†é’¥ï¼Œåˆ é™¤å·²æ³¨å†Œçš„许å¯è¯å¯†é’¥å¹¶åœ¨æ­¤æ˜¾ç¤ºå½“å‰è®¸å¯è¯åˆ—表和 VPN Server 的许å¯è¯æ¨¡å¼ã€‚
+S_BOLD 当å‰å·²æ³¨å†Œçš„许å¯è¯å¯†é’¥(&L):
+B_OBTAIN 获å–或延长许å¯è¯(&O)
+STATIC2 点击“获å–或延长许å¯è¯â€ä»¥è®¿é—®å°†æ供有关如何获å–许å¯è¯è¯´æ˜Žçš„网站。
+B_ADD 添加一个许å¯è¯å¯†é’¥(&A)
+B_DEL 删除(&D)
+IDOK 许å¯è¯ç›¸å…³ä¿¡æ¯(&I)
+STATIC3 选择一个许å¯è¯ï¼Œç‚¹å‡»â€œè®¸å¯è¯ç›¸å…³ä¿¡æ¯â€æ¥è¿žæŽ¥åˆ° SoftEther 有é™å…¬å¸ç½‘ç«™ (softether.com),æ¥æŸ¥è¯¢è¢«é€‰è®¸å¯è¯çš„相关注册信æ¯ã€‚
+S_BOLD2 当å‰è®¸å¯å’Œ SoftEther VPN Server 模å¼(&M):
+IDCANCEL 退出(&X)
+
+
+PREFIX D_SM_LICENSE_ADD
+CAPTION 添加许å¯è¯å¯†é’¥
+S_INFO 您å¯ä»¥æ³¨å†Œä¸€ä¸ª SoftEther VPN Server 产å“许å¯è¯æˆ–连接许å¯è¯ã€‚
+STATIC1 许å¯è¯å¯†é’¥é•¿åº¦ä¸º 36 å­—æ¯æ•°å­—字符和破折å·ç»„åˆ ( '-' )。他们是è¯æ˜Žä¸€ä¸ªè®¸å¯è¯æ‰€æœ‰æƒçš„关键代ç ã€‚\r\n\r\n当许å¯è¯è¯ä¹¦ä¸Žæ­¤è½¯ä»¶ä¸€èµ·æ”¶åˆ°æ—¶ï¼Œè®¸å¯è¯å¯†é’¥å°åœ¨æ­¤æŽˆæƒè¯ä¹¦ä¸Šã€‚如果本软件的许å¯è¯æ˜¯ç½‘上购买的,许å¯è¯å¯†é’¥æ˜¯ç”±ç”µå­é‚®ä»¶æˆ–购买许å¯è¯çš„网站æ供的。许å¯è¯å¯†é’¥ä¹Ÿå¯ä»¥é€šè¿‡ä¸€äº›å…¶ä»–方法写下æ¥ã€‚如果你ä¸çŸ¥é“的许å¯è¯å¯†é’¥å†™åœ¨å“ªé‡Œï¼Œé—®å–给你许å¯è¯çš„供应商。
+STATIC2 请准确输入许å¯è¯å¯†é’¥(&I):
+STATIC3 分组输入许å¯è¯å¯†é’¥ï¼Œæ¯ç»„6ä½ã€‚您ä¸éœ€è¦è¾“入破折å·ã€‚您也å¯ä»¥å¤åˆ¶ && 粘贴许å¯è¯å¯†é’¥ã€‚
+B_INFO2 此软件å—世界范围的版æƒæ³•ä¿æŠ¤ã€‚消费者åªå¯ä»¥åœ¨è®¸å¯è¯å…许范围内å¤åˆ¶å’Œä½¿ç”¨æ­¤è½¯ä»¶ã€‚使用éžæ³•èŽ·å¾—的许å¯è¯å¯†é’¥ï¼Œæˆ–在多å°æœåŠ¡å™¨ä¸Šä½¿ç”¨ä¸€ä¸ªè®¸å¯è¯ï¼Œæˆ–以éžè®¤è¯çš„æ–¹å¼èŽ·å¾—许å¯è¯ï¼Œä¼šå¯¼è‡´æ°‘事或刑事处罚。
+IDOK 注册(&R)
+IDCANCEL å–消
+
+
+PREFIX D_FREEINFO
+CAPTION SoftEther VPN Server çš„å…费版
+S_INFO_1 感谢您试用 SoftEther VPN Server å…费版。
+S_INFO_2 SoftEther VPN Server è¿è¡Œåœ¨ç›®æ ‡æœåŠ¡å™¨ "%S" 上是å…费版供个人使用。\r\n当使用å…费版时,您å¯ä»¥ä½¿ç”¨æ‰€æœ‰çš„ SoftEther VPN Server 的功能,但用户åè®®ç¦æ­¢ä»¥ä¸‹çš„使用。
+S_INFO_3 通过 VPN Server 的商业目的旅行的通迅中使用。
+S_INFO_4 请注æ„,如果软件基于上述ç¦æ­¢ä½¿ç”¨çš„情况下被使用,这样就è¿å了 SoftEther VPN Server 用户å议。一旦你å–得了 SoftEther VPN Server 的定期产å“许å¯è¯ï¼Œä¸Šè¿°é™åˆ¶å³å¯è§£é™¤ã€‚关于常规产å“版本的详细信æ¯ï¼Œè¯·è®¿é—® www.softether.com。\r\n如果该æœåŠ¡å™¨åœ¨ä¸Šè¿°æ述的情况下被使用,请通过我们的网站 www.softether.com è”系我们。请注æ„: 当连接到 VPN Server çš„å…费版,此窗å£å°†å‡ºçŽ°ã€‚当使用除å…费版以外的其他们版本时,此窗å£ä¸å‡ºçŽ°ã€‚\n\n注æ„: 除了这个通知窗å£ï¼Œå…费版软件和产å“版软件之间没有任何差别。
+B_HIDE 下次éšè—此窗å£(&H)
+IDCANCEL 确定(&O)
+
+
+PREFIX D_CM_SETTING
+CAPTION åˆ‡æ¢ SoftEther VPN Client 工作模å¼
+STATIC1 您å¯ä»¥ä½¿ç”¨ SoftEther VPN Client 的“标准模å¼â€æˆ–“简å•æ¨¡å¼â€ã€‚è¦åˆ‡æ¢åˆ°å¦ä¸€ç§æ¨¡å¼ï¼Œå‹¾é€‰ä¸‹é¢ç›¸åº”çš„å¤é€‰æ¡†ã€‚
+R_NORMAL 标准模å¼(&N)
+R_EASY 简å•æ¨¡å¼(&E)
+STATIC2 当使用“标准模å¼â€æ—¶ï¼Œæ‚¨å¯ä»¥è¿›è¡Œ SoftEther VPN Client 软件æ供的所有æ“作。我们建议一般用户和系统管ç†å‘˜ä½¿ç”¨æ­¤æ¨¡å¼ã€‚
+STATIC3 “简å•æ¨¡å¼â€åªå…许最常用的æ“作,如连接到 VPN Server。我们建议åˆçº§ç”¨æˆ·ä½¿ç”¨è¿™ç§æ¨¡å¼ã€‚
+STATIC4 通过使用设置é”,您å¯ä»¥é€šè¿‡ä½¿ç”¨ä¸€ä¸ªåœ¨ SoftEther VPN Client 注册的连接设置连接到一个 VPN Server ,但这样åšï¼Œæ‚¨æ— æ³•å˜æ›´è¿žæŽ¥è®¾ç½®çš„å‚æ•°ã€åˆ›å»ºä¸€ä¸ªæ–°çš„连接设置或者删除一个连接设置。
+R_LOCK å¯ç”¨è®¾ç½®é”(&L)
+S_PASSWORD1 您å¯ä»¥æŒ‡å®šä¸€ä¸ªå¯†ç ã€‚下次ç¦ç”¨è®¾ç½®é”时将被è¦æ³¨è¾“入该密ç ã€‚
+S_PASSWORD2 密ç (&P):
+S_PASSWORD3 确认(&C):
+IDOK 确定(&O)
+IDCANCEL å–消
+S_VGS2 您å¯ä»¥é…ç½® VPN Gate 学术æœåŠ¡è®¾ç½®ã€‚
+B_VGS VPN 和门户æœåŠ¡è®¾ç½® (&G)...
+
+
+PREFIX D_CM_EASY
+CAPTION SoftEther VPN Client 简易管ç†å™¨
+B_MODE 切æ¢è¿è¡Œæ¨¡å¼(&M)
+IDCANCEL 关闭(&C)
+B_STATUS 查看连接模å¼(&S)
+B_VGC VPN Gate 学术项目
+
+
+PREFIX D_SM_SETUP
+CAPTION SoftEther VPN Server / Bridge 简å•å®‰è£…
+S_TITLE SoftEther VPN Server / Bridge 简å•å®‰è£…
+IDC_STATIC_1 通过使用此安装,您å¯ä»¥ä¸ºä»¥ä¸‹ä½¿ç”¨å’Œç›®çš„è½»æ¾åœ°å®‰è£… SoftEther VPN Server 或 VPN Bridge。退出安装åŽï¼Œæ‚¨å¯ä»¥ä½¿ç”¨ VPN Server 管ç†å™¨è‡ªç”±é…置更高级的设置。
+S_BOLD 选择你è¦æž„建的 VPN Server 类型。å¯ä»¥ä¸€èµ·é€‰æ‹©å¤šç§ç±»åž‹ã€‚
+C_REMOTE 远程访问 VPN Server (&R)
+S_REMOTE_1 远程访问 VPN Server å…许 VPN Client 计算机远程访问现有的以太网段,如公å¸å±€åŸŸç½‘。\n\n连接到 VPN Server 的任何 VPN Client 都能访问到网络,就åƒä»–们直接的ã€ç‰©ç†çš„连接到网络一样。
+C_SITE 站点到站点 VPN Server 或 VPN Bridge(&S)
+S_SITE_1 站点到站点 VPN 是一ç§è¿žæŽ¥ä¸¤ä¸ªæˆ–多个远程以太网的 VPN é…置。\r\næ¯ä¸ªç«™ç‚¹è¿žåœ¨ä¸€èµ·ï¼Œå¹¶ä¸”在二层æˆä¸ºåŒä¸€ç½‘段。这使得æ¯ä¸ªç«™ç‚¹çš„所有计算机åƒæ˜¯åœ¨åŒä¸€ç½‘络中一样å¯ä»¥ç›¸äº’通信。
+S_SITE_2 选择这个 VPN Server 的作用:
+C_CENTER 从其他站点接å—连接 VPN Server (中心) (&C)
+C_EDGE æ¯ä¸ªç«™ç‚¹(站点端)çš„ VPN Server 或 VPN Bridge (&E)
+C_OTHER VPN 的其他高级é…ç½®
+S_OTHER 如果你计划构建具有高级功能的 VPN 系统,如群集功能和虚拟 3 层交æ¢åŠŸèƒ½ï¼Œè¯·é€‰æ‹©æœ¬é¡¹ã€‚
+IDOK 下一步(&N)
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_SETUP_HUB
+CAPTION 简å•å®‰è£…-决定虚拟 HUB å称
+IDC_STATIC_1 您必须至少在 VPN Server 上创建一个虚拟 HUB。以您喜欢的å字命å新的虚拟 HUB。
+IDC_STATIC_2 虚拟 HUB å(&N):
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_SETUP_STEP
+CAPTION VPN 简å•å®‰è£…任务
+IDC_STATIC_1 ä¸ºäº†å®Œæˆ VPN Server / VPN Bridge 的安装,您必须完æˆä»¥ä¸‹ä»»åŠ¡ã€‚
+S_1_1 步骤 1. 创建一个用户æ¥æŽ¥å— VPN 连接。
+S_1_2 当此 VPN Server 接å—远程访问 VPN ,或接å—从其他站点æ¥çš„连接æˆä¸ºä¸­å¤®ç«™ç‚¹åˆ°ç«™ç‚¹ VPN Server æ—¶ï¼Œåˆ›å»ºç”¨æˆ·æŽ¥å— VPN 连接。
+B_USER 创建用户
+S_2_1 步骤 2. 定义一个到目标 VPN Server 的连接
+S_2_2 当此 VPN Server 被安装在一个站点到站点 VPN 的特定的站点(端) 上时,您必须制定接å—连接的中心 VPN Server 的地å€ï¼Œå¹¶å»ºç«‹åˆ°ä¸­å¤® VPN Server 的连接。
+B_CASCADE é…置连接设置(&C)
+S_3_1 3. 设置本地网桥
+S_3_2 对于站点到站点 VPN ,使用本地桥功能连接 VPN 的虚拟以太网段与本地端的物ç†ä»¥å¤ªç½‘段之间的网桥。 选择å¯ä»¥æ供桥接到 VPN 的现有以太网设备(网络适é…器)。
+IDCANCEL 关闭(&C)
+IDC_STATIC_8 一旦必须的设置é…置完毕,å•å‡»â€œå…³é—­â€ã€‚VPN Server / VPN Bridge 的高级管ç†å·¥å…·å°†ä¼šå‡ºçŽ°ã€‚然åŽæ‚¨å¯ä»¥é…置你希望的任何高级设置。
+B_SECURENAT é…ç½® SecureNAT
+
+
+PREFIX D_CPU64_WARNING
+CAPTION SoftEther VPN 64 ä½ç‰ˆæœ¬ä¿¡æ¯
+S_BOLD 当å‰å®‰è£…çš„ SoftEther VPN 软件是 32 ä½ç‰ˆæœ¬ï¼Œä½†æ­£åœ¨è¿è¡Œçš„ Windows æ“作系统是 64 ä½ç‰ˆæœ¬ã€‚
+S_INFO 您å¯ä»¥åœ¨ Windows 64 ä½ç‰ˆæœ¬ä¸Šè¿è¡Œ SoftEther VPN 软件 32 ä½ç‰ˆæœ¬ï¼Œä½†è¿™å°†è¿è¡Œ Windows çš„ 32 ä½æ¨¡æ‹Ÿå™¨ï¼Œå¹¶å¯¼è‡´æ€§èƒ½é™ä½Žã€‚\r\n也有一些功能ä¸æ”¯æŒçš„å¯èƒ½æ€§ã€‚ 我们强烈建议您当在 64 ä½ Windows è¿è¡Œå®ƒæ—¶ï¼Œå®‰è£…并使用 SoftEther VPN 软件的 64 ä½ç‰ˆæœ¬ã€‚\r\n您å¯ä»¥ä»Ž http://selinks.org/ 下载 SoftEther VPN 软件的 64 ä½ç‰ˆæœ¬ã€‚此对è¯æ¡†å°†åœ¨ 30 秒åŽè‡ªåŠ¨å…³é—­ã€‚
+IDOK 确定(&O)
+
+
+PREFIX D_ONCEMSG
+CAPTION TITLE
+C_DONTSHOWAGAIN ä¸å†æ˜¾ç¤ºæ­¤æ¶ˆæ¯(&D)
+IDCANCEL 确定(&O)
+
+
+PREFIX D_CONNECT
+IDCANCEL å–消
+
+
+PREFIX D_SM_IPSEC
+CAPTION IPsec / L2TP / EtherIP / L2TPv3 设置
+S_TITLE IPsec / L2TP / EtherIP / L2TPv3 æœåŠ¡å™¨è®¾ç½®
+S_3 在 VPN Server 上的虚拟 HUB å¯ä»¥æŽ¥å—从兼容 L2TP 的个人电脑, Mac OS X 和智能手机的远程访问 VPN 连接, 也å¯ä»¥æŽ¥å— EtherIP / L2TPv3 站点到站点的 VPN 连接。
+S01 L2TP æœåŠ¡å™¨ (远程访问 VPN Server 功能)
+S02 从智能手机诸如 iPhone, iPad å’Œ Android, 还有从Mac OS X å’Œ Windows 内建的 VPN 客户端的 VPN 连接都是å¯ä»¥æŽ¥å—的。
+R_L2TP_OVER_IPSEC å¯ç”¨ L2TP æœåŠ¡å™¨åŠŸèƒ½ (L2TP over IP&sec)
+S03 使æ¥è‡ª iPhone, iPad, Android, Windows å’Œ Mac OS X çš„ VPN 连接å¯ä»¥æŽ¥å—。
+R_L2TP_RAW å¯ç”¨ L2TP æœåŠ¡å™¨åŠŸèƒ½ (没加密的 RAW L2TP)(&L)
+S04 支æŒä½¿ç”¨ L2TP 而无 IPSec 加密的特殊 VPN 客户端。
+S_1 默认虚拟 HUB 以防é—æ¼ç”¨æˆ·å上的 HUB å称 (&H):
+S_2 用户应指定他们的用户å, 如 "用户å@目标虚拟 HUB å" 连接到此 L2TP æœåŠ¡å™¨ã€‚\r\n如果虚拟 HUB çš„å称被é—æ¼, 以下 HUB 将作为目标被使用。
+S05 EtherIP / L2TPv3 æœåŠ¡å™¨åŠŸèƒ½ (站点到站点 VPN 连接)
+S06 兼容 EtherIP / L2TPv3 over IPsec çš„è·¯ç”±å™¨äº§å“ å¯ä»¥è¿žæŽ¥åˆ° VPN Server 上的虚拟 HUB, 并建立 2 层 (以太网) 桥接。
+R_ETHERIP å¯ç”¨ EtherIP / L2TPv3 over IPsec æœåŠ¡å™¨åŠŸèƒ½(&E)
+B_DETAIL EtherIP / L2TPv3 详细设置(&D)
+S07 IPsec 通用设置(&C)
+S_PSK IPsec 预共享密钥(&P):
+S_PSK2 IPsec 预共享密钥也被称为 "PSKs" 或 "秘钥"。用 8 个 ASCII 字符指定, 并让所有的 VPN 用户都知é“。
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_SM_ETHERIP
+CAPTION EtherIP / L2TPv3 æœåŠ¡å™¨è¯¦ç»†è®¾ç½®
+S_TITLE EtherIP / L2TPv3 æœåŠ¡å™¨è¯¦ç»†è®¾ç½®
+S01 兼容EtherIP / L2TPv3 over IPsec çš„è·¯ç”±å™¨äº§å“ å¯ä»¥è¿žæŽ¥åˆ° VPN Server 上的虚拟 HUB , 并建立 2 层 (以太网) 桥接。例如,æ€ç§‘路由器,NEC IX 系列和 IIJ SEIL 路由器作为兼容的 VPN 路由器, 推è使用。
+S02 ä¸ºäº†æŽ¥å— EtherIP / L2TPv3 åè®®, 定义适当的 EtherIP / L2TPv3 客户端设置, 以事先确定 EtherIP / L2TPv3 兼容路由器的客户端站点。EtherIP / L2TPv3 客户端设置必须有相应的 IPSec Phase 1 ID。
+S_BOLD 在 IPSec Phase 1 ID 和虚拟 HUB 之间的通信表(&T):
+B_ADD 添加(&A)
+IDOK 编辑(&E)
+B_DELETE 删除(&D)
+IDCANCEL 退出(&X)
+
+
+PREFIX D_SM_ETHERIP_ID
+CAPTION EtherIP / L2TPv3 over IPsec 客户端设置
+S01 以下虚拟 HUB 连接设置将仅应用于 当 EtherIP / L2TPv3 over IPsec 客户端试图连接一个与下é¢æŒ‡å®šå€¼å®Œå…¨ç›¸åŒçš„ ISAKMP (IKE) Phase 1 ID çš„ VPN Server 时。
+S02 ISAKMP Phase 1 ID(&I):
+S03 虚拟 HUB(&H):
+S04 用户å(&U):
+S05 密ç (&P):
+S06 注æ„: 用户å和密ç å¿…须与在虚拟 HUB 注册时完全相åŒã€‚EtherIP / L2TPv3 用户将被视为以上述用户信æ¯çš„身份连接虚拟 HUB。
+IDOK 确定(&O)
+IDCANCEL å–消
+S07 (ID 必须与 EtherIP / L2TPv3 客户端的é…ç½® ID 完全相åŒã€‚如果 EtherIP / L2TPv3 客户端使用 IP 地å€ä½œä¸º Phsae 1 ID, 您å¯ä»¥æŒ‡å®š IP 地å€å¹¶ä¸”字符也å¯ä»¥åšä¸º ID。您å¯ä»¥æŒ‡å®š “*†(星å·)作为通é…符æ¥åŒ¹é…任何ä¸åŒ¹é…其他明确规则的客户端。
+
+PREFIX D_SM_OPENVPN
+CAPTION OpenVPN / MS-SSTP 设置
+S_TITLE OpenVPN / MS-SSTP VPN 克隆 Server 功能设置
+S_1 本 VPN Server 具有 OpenVPN 技术责任有é™å…¬å¸çš„ OpenVPN 软件产å“的克隆功能。\r\n\r\n任何 OpenVPN Client 都å¯ä»¥è¿žæŽ¥åˆ°æ­¤ VPN Server。
+R_OPENVPN å¯ç”¨ OpenVPN 克隆 Server 功能(&O)
+S_UDP ç›‘å¬ OpenVPN çš„ UDP 端å£:
+B_DEFAULT æ¢å¤é»˜è®¤å€¼(&D)
+S_UDP2 å¤šé‡ UDP 端å£å¯ä»¥ç”¨ç©ºæ ¼æˆ–者逗å·éš”开的字æ¯æ¥æŒ‡å®šã€‚ \r\nOpenVPN Server 功能也å¯ä»¥åœ¨ TCP 端å£ä¸Šè¿è¡Œã€‚任何在 VPN Server 上被定义为监å¬ç«¯çš„ TCP 端å£éƒ½å¯ä»¥å¹³ç­‰çš„ã€åˆ†åˆ«çš„æŽ¥å— OpenVPN å议。
+S_TOOL OpenVPN Client 的示例文件生æˆå·¥å…·
+S_TOOL2 创建一个 OpenVPN Client é…置是一项艰难的工作。您å¯ä»¥ä½¿ç”¨æ­¤å·¥å…·æ¥ç”Ÿæˆä¸€ä¸ªåˆé€‚çš„ OpenVPN Client é…置文件。生æˆçš„é…置示例文件å¯é©¬ä¸Šåº”用。本æ¥ï¼ŒOpenVPN Client 会è¦æ±‚客户手写一个很难的é…置文件。这个工具就å¯ä»¥å¸®åŠ©æ‚¨åˆ›å»ºä¸€ä¸ªæœ‰ç”¨çš„é…置样本。您所需è¦ä¸º OpenVPN Client 生æˆçš„é…置文件就是点击以下按钮。
+B_CONFIG 为 OpenVPN Client 生æˆé…置样本文件(&C)
+S_2 Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½
+S_3 该 VPN Server 有微软公å¸çš„ Windows Server 2008 / 2012 内建的 MS-SSTP VPN Server 的克隆功能。\r\n在 Windows Vista / 7 / 8 / RT 中内建的 MS-SSTP 客户端能连接此 VPN Client。
+R_SSTP å¼€å¯ &MS-SSTP VPN 克隆 Server 功能
+S_SSTP VPN Server 端 SSL è¯ä¹¦çš„ CN (通用å)值必须与该客户端指定的主机åå»åˆï¼Œå¹¶ä¸”该è¯ä¹¦å¿…须在该客户端的å¯ä¿¡åˆ—表中。详细内容请å‚考微软的文档。
+S_4 指定用户å连接到虚拟 HUB çš„æ–¹å¼ï¼Œå’Œé€šè¿‡ä½¿ç”¨å…‹éš†æœåŠ¡å™¨è¿›è¡Œé»˜è®¤ HUB 的选择规则,与 IPsec æœåŠ¡å™¨åŠŸèƒ½æ˜¯ä¸€æ ·çš„。
+B_IPSEC IPsec æœåŠ¡å™¨é…ç½®(&P)
+S_13 OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½
+IDOK 确定(&O)
+IDCANCEL å–消l
+
+
+PREFIX D_SM_DDNS
+CAPTION åŠ¨æ€ DNS 功能
+S_TITLE åŠ¨æ€ DNS 功能
+S_BOLD æ­¤ VPN Server æœ‰å†…å»ºçš„åŠ¨æ€ DNS 功能
+S_1 æ­¤åŠ¨æ€ DNS 为该 VPN Server 分派了一个唯一的永久的 DNS 主机å。您å¯ä»¥ç”¨æ­¤ä¸»æœºåæ¥æŒ‡å®šæœ¬ VPN Server æ¥è®¾ç½® VPN Client å’Œ VPN Bridge 。您ä¸éœ€è¦æ³¨å†Œå¹¶æŒæœ‰ä¸€ä¸ªåŸŸå。
+S_22 åŒæ—¶ï¼Œå¦‚果你的 ISP 分派给你一个动æ€(ä¸å›ºå®š) IP 地å€,ç›¸åº”çš„åŠ¨æ€ DNS 主机åçš„ IP 地å€ä¹Ÿä¼šè‡ªåŠ¨æ”¹å˜ã€‚它使您在仅使用一个动æ€çš„ IP 地å€çš„情况下ä¿æŒ VPN Server çš„è¿è¡Œã€‚\r\n因此,你ä¸å†éœ€è¦æ¯æœˆèŠ±é’±ä»¥ä¿æŒé™æ€å…¨çƒ IP 地å€ã€‚
+S_3 å¦å¤–,本 VPN Server 版本支æŒ'NAT ç©¿é€'功能。如果 VPN Server 在 NAT 内,并且被分é…了一个ç§æœ‰ IP 地å€ï¼Œåˆ™æ‚¨å¯ä»¥å®Œå…¨ä¸ç”¨äº‹å…ˆå¯¹ NAT 进行任何特殊设置,而从因特网端连接该 VPN Server。
+S_4 当å‰çŠ¶æ€(&S)
+S_STATUS3 分é…çš„åŠ¨æ€ DNS 主机å (&H):
+B_HINT æ示
+S_STATUS4 å…¨çƒ IPv4 地å€(&4):
+S_STATUS5 å…¨çƒ IPv6 地å€(&6):
+S_5 修改设置:
+S_STATUS6 改å˜åŠ¨æ€ DNS 主机å(&C):
+S_STATUS7 主机ååªèƒ½æ˜¯å­—æ¯æ•°å­—和破折å·â€œ-â€ã€‚至少 3 ä½ã€‚\r\n您å¯ä»¥éšæ—¶æ›´æ¢å字。
+IDOK 设置上述主机å(&A)
+B_RESTORE &æ¢å¤
+S_2 如果您没有连接到 IPv6 网络,“ å…¨çƒ IPv6 地å€â€œå°†ä¼šæ˜¾ç¤ºä¸€ä¸ªé”™è¯¯ã€‚\r\n少数国家或地区å¯èƒ½ä¼šç¦æ­¢åŠ¨æ€ DNS æœåŠ¡ã€‚
+IDCANCEL 退出(&X)
+B_DISABLE ç¦ç”¨åŠ¨æ€ DNS 功能(&D)
+B_PROXY 通过代ç†æœåŠ¡å™¨è¿žæŽ¥(&P)...
+
+
+PREFIX D_SM_SPECIALLISTENER
+CAPTION VPN over ICMP / DNS 功能设置
+S_TITLE VPN over ICMP / DNS 功能
+S_1 VPN over ICMP / DNS 功能
+S_2 å³ä½¿æœ‰é˜²ç«å¢™æˆ–者å±è”½ TCP/IP 连接的路由器,您也å¯ä»¥åªç”¨ ICMP 或者 DNS æ•°æ®åŒ…建立一个 VPN。您需è¦äº‹å…ˆå¯ç”¨å¦‚下功能。
+R_OVER_ICMP å¯ç”¨ VPN over ICMP æœåŠ¡å™¨åŠŸèƒ½(&I)
+R_OVER_DNS å¯ç”¨ VPN over DNS æœåŠ¡å™¨åŠŸèƒ½(使用 UDP 53 å·ç«¯å£)(&D)
+IDOK 确定(&O)
+IDCANCEL å–消
+S_3 è¦æ±‚ VPN Client / VPN Bridge 内部版本 4.0 或更高。
+S_4 注æ„:仅在紧急情况下使用此功能。它是当防ç«å¢™æˆ–者路由器é…置错误å±è”½ TCP/IP,但是å´æ²¡æœ‰å±è”½ ICMP 或者 DNS 时,使用是有帮助的。它ä¸æ˜¯ä¸ºé•¿æœŸç¨³å®šä½¿ç”¨ã€‚
+
+PREFIX D_SM_REDIRECT
+CAPTION HTTP URL é‡å®šå‘设置
+S_1 下é¢æŒ‡å®šçš„ URL 将被强制回å¤ç»™å®¢æˆ·ç«¯ï¼Œä½œä¸ºé€šè¿‡æ­¤è™šæ‹Ÿ HUB 匹é…此访问列表æ¡ç›®æ¡ä»¶çš„ TCP 连接请求数æ®åŒ…的回应。\r\n\r\nè¦ä½¿ç”¨æ­¤è®¾ç½®ï¼Œå½“网页æµè§ˆå™¨è¯•å›¾è®¿é—®ç‰¹å®šçš„ IP 地å€æ—¶ï¼Œæ‚¨å¯ä»¥å¼ºè¡Œè®© VPN Client 计算机的网络æµè§ˆå™¨æ˜¾ç¤ºè¯¥æŒ‡å®šç½‘站。
+S_2 指定一个 URL,é‡å®šå‘到
+S_BOLD2 该 URL é‡å®šå‘到(&U):
+S_3 例å­:
+S_4 å•ä¸€ URL é‡å®šå‘:
+S_5 高级 URL é‡å®šå‘:
+B_HINT 高级 URL é‡å®šå‘功能的用途(&U)
+S_6 标题
+S_BOLD 该功能适用于 TCP/IP 专家管ç†å‘˜ã€‚阅读如下说明并å°å¿ƒè®¾ç½®ã€‚
+S_7 在数æ®åŒ…的目标会è¯åŒ¹é…访问列表æ¡ç›®çš„目标用户å或组å的情况下,é‡å®šå‘规则无效。
+S_8 如果匹é…æ¡ä»¶ï¼Œéž TCP æ•°æ®åŒ…é‡å®šå‘规则被忽略,。
+S_9 该é‡å®šå‘规则总是对 HTTP é‡å®šå‘ä¿¡æ¯å›žåº”。(对 80 端å£æ— é™åˆ¶)。如果您åªæƒ³åº”用于 80 端å£ï¼Œåœ¨è®¿é—®åˆ—表æ¡ç›®çš„æ¡ä»¶ä¸­ï¼Œå°†ç›®æ ‡ç«¯å£è®¾ä¸º 80 å³å¯ã€‚
+S_10 如果这个规则é‡å®šå‘的结果是,客户端试图连接这个已é‡æ–°å®šå‘çš„ URL,并且这个新的请求åˆä¸Žè¯¥è§„则å»åˆï¼Œåˆ™é‡å®šå‘结果将会å†æ¬¡å›žå¤è¿™ä¸ªæ–°çš„请求。这样就会形æˆä¸€ä¸ªæ— ç©·çš„é‡å®šå‘循环。
+IDOK 确定(&O)
+IDCANCEL å–消
+S_11 高级é‡å®šå‘功能å¯ä»¥å‘é‡æ–°å®šå‘çš„ CGI æä¾› VPN 会è¯ä¿¡æ¯ã€‚
+
+PREFIX D_SW_WELCOME
+CAPTION D_SW_WELCOME
+S_WELCOME SoftEther VPN 在日本筑波大学开å‘çš„å…费软件。具有终æžå…¼å®¹è®¸å¤šè®¾å¤‡çš„高性能 VPNã€‚æ”¯æŒ Windowsã€Macã€æ™ºèƒ½æ‰‹æœºã€å¹³æ¿ç”µè„‘ (iPhoneã€iPadã€å®‰å“ã€Windows RT) å’Œæ€ç§‘或其他 VPN 路由器。SoftEther VPN ä¹ŸæŽ¥å— OpenVPN å’Œ MS-SSTP VPN 客户端。
+S_TITLE éžå¸¸å¼ºå¤§çš„å¼€æºå…è´¹ VPN 软件。
+
+PREFIX D_SW_MODE
+CAPTION D_SW_MODE
+R_SYSTEM 系统模å¼(推èçš„)(&S)
+R_USER 用户模å¼(&U)
+S_1 正常安装本 VPN 软件。è¦æ±‚管ç†å‘˜æƒé™ã€‚
+S_USER 以普通用户æƒé™å®‰è£…本 VPN 软件。ä¸éœ€è¦ç®¡ç†å‘˜æƒé™ã€‚有些诸如本地桥功能是ä¸èƒ½ä½¿ç”¨çš„。åªæœ‰åœ¨"%s"用户登入 Windows 时,æ‰ä¼šè¿è¡Œæœ¬è½¯ä»¶.
+S_2 SoftEther VPN å¯ä»¥æœ‰ä¸¤ç§æ–¹æ³•å®‰è£…。\r\n\r\n通常请选择系统模å¼ã€‚\r\n\r\n如果您由于一些原因ä¸èƒ½ä½¿ç”¨ç®¡ç†å‘˜æƒé™ï¼Œæ‚¨å¯ä»¥é€‰æ‹©ç”¨æˆ·æ¨¡å¼æ¥ç»§ç»­å®‰è£…。
+
+
+PREFIX D_SW_NOT_ADMIN
+CAPTION D_SW_NOT_ADMIN
+S_INFO 登入 Windows çš„"%s"用户ä¸å…·æœ‰ç®¡ç†å‘˜æƒé™ã€‚\r\n\r\n退出登入 Windows,用有管ç†å‘˜æƒé™çš„用户åé‡æ–°ç™»å…¥ï¼Œå¦‚果想继续安装,请é‡å¯å®‰è£…å‘导。
+S_INFO6 点击完æˆï¼Œé€€å‡ºå®‰è£…å‘导。
+S_INFO2 如果您ä¸èƒ½ä½¿ç”¨ç®¡ç†å‘˜æƒé™ï¼Œæ‚¨å¯ä»¥é€‰æ‹©ç”¨æˆ·æ¨¡å¼å®‰è£…。\r\nè¦ä»¥ç”¨æˆ·æ¨¡å¼å®‰è£…,点击返回。
+
+
+PREFIX D_SW_COMPONENTS
+CAPTION D_SW_COMPONENTS
+
+
+PREFIX D_SW_EULA
+CAPTION D_SW_EULA
+S_1 请您仔细阅读最终用户许å¯å议。
+B_AGREE 我åŒæ„最终用户许å¯å议。
+
+
+PREFIX D_SW_WARNING
+CAPTION D_SW_WARNING
+S_1 SoftEther VPN 软件有超乎想象的ã€å¼ºå¤§çš„通信能力。请在使用å‰ä»”细阅读é‡è¦æ³¨æ„事项。
+
+
+PREFIX D_SW_DIR
+CAPTION D_SW_DIR
+S_INFO 请指定安装 %s 的目录.
+R_CUSTOM 指定目录(&S)
+S_DEST 目录(&D):
+B_BROWSE æµè§ˆ...(&B)...
+R_SHOWCUSTOM 为网络专家使用的高级安装选项(&A)
+R_FOR_SYSTEM 在本电脑的 Windows 系统上安装(&W)
+R_FOR_USER 在用户 "%s" 的环境åªä¸Šå®‰è£…
+S_WARNING 注æ„:这是ä¸æŽ¨è的。用户"%s"退出 Windows åŽï¼Œ%s å°†åœæ­¢ã€‚本地桥功能和 L2TP/IPsec 功能 (æ”¯æŒ Mac 和智能手机)也ä¸èƒ½å†ä½¿ç”¨äº†ã€‚
+
+
+PREFIX D_SW_READY
+CAPTION D_SW_READY
+S_INFO %s 安装已就绪。
+S_INFO7 点击继续执行安装。
+
+
+PREFIX D_SW_PERFORM
+CAPTION D_SW_PERFORM
+S_INFO %s 安装正在进行。\r\n请è€å¿ƒç­‰å¾…...
+S_INFO8 SoftEther VPN 是日本政府的研究和开å‘项目的一项工作,由日本的ç»æµŽã€è´¸æ˜“和工业部资助,由信æ¯åŒ–推进机构管ç†ã€‚
+
+
+PREFIX D_SW_ERROR
+CAPTION D_SW_ERROR
+S_INFO 出现错误,%s 安装中止。\r\n\r\n如果你想继续,请é‡å¯å®‰è£…å‘导。
+
+
+PREFIX D_SW_FINISH
+CAPTION D_SW_FINISH
+S_INFO %s 安装过程已æˆåŠŸå®Œæˆã€‚
+S_INFO8 SoftEther VPN 是日本政府的研究和开å‘项目的一项工作,由日本的ç»æµŽã€è´¸æ˜“和工业部资助,由信æ¯åŒ–推进机构管ç†ã€‚
+
+
+PREFIX D_SW_UNINST1
+CAPTION D_SW_UNINST1
+S_WELCOME 安装å‘导å¯ä»¥ä»Žç”µè„‘中å¸è½½ %s。\r\n\r\n若想开始å¸è½½ï¼Œç‚¹å‡»ä¸‹ä¸€æ­¥
+S_TITLE %s å¸è½½å‘导
+
+
+PREFIX D_SW_EASY1
+CAPTION D_SW_EASY1
+S_WELCOME 在一个ä¼ä¸šé‡Œä¸ºè®¸å¤šè®¡ç®—机安装和设置 VPN Client 是很辛苦的工作。
+S_TITLE 什么是 SoftEther VPN Client 简å•å®‰è£…程åº?
+S_WELCOME2 简å•å®‰è£…程åºåˆ›å»ºå™¨æ˜¯ä¸ºå…¬å¸ç®¡ç†å‘˜ä½¿ç”¨çš„一个工具。您å¯ä»¥é€šè¿‡ä½¿ç”¨ç®€å•å®‰è£…程åºåˆ›å»ºå™¨ç”¨åµŒå…¥çš„æŸä¸ªå…·ä½“ VPN 连接设置æ¥åˆ›å»ºä¸€ä¸ª VPN Client 安装程åºã€‚个人用户还å¯ä»¥å¼€å‘此工具。
+S_WELCOME3 通过使用文件æœåŠ¡å™¨æˆ–者 e-mail,å¯ä»¥å°†ä¸€ä¸ªå·²åˆ›å»ºçš„简å•å®‰è£…程åºåˆ†å‘给公å¸çš„员工。如果用户è¿è¡Œç®€å•å®‰è£…程åºï¼Œ VPN Client 会被安装〠VPN 连接设置会被导入完æˆï¼Œå¹¶ä¸” VPN 连接也会自动å¯åŠ¨ã€‚
+
+
+PREFIX D_SW_EASY2
+CAPTION D_SW_EASY2
+S_BOLD1 指定一个嵌入 VPN 连接设置文件(.vpn)。
+S_1 请指定一个 VPN 连接设置文件 (.vpn)æ¥åµŒå…¥åˆ°ç®€å•å®‰è£…程åºã€‚您å¯ä»¥åœ¨ VPN Client 管ç†å·¥å…·ä¸­ï¼Œåœ¨ç›®æ ‡è¿žæŽ¥è®¾ç½®çš„å³å‡»èœå•ä¸­é€šè¿‡å•å‡»è¾“出 VPN 连接设置æ¥è¾“出设置文件。
+S_18 连接设置(&S):
+B_BROWSE_SETTING æµè§ˆ...(&B)
+B_DELETE_SENSITIVE 在连接设置文件中删除用户å和密ç (&E)
+S_BOLD2 指定一个è¦ç”Ÿæˆçš„ EXE 文件å
+S_3 这工具将会输出一个包å«ç®€å•å®‰è£…工具的 EXE 文件(å¯æ‰§è¡Œæ–‡ä»¶)。请指定è¦ç”Ÿæˆçš„输出文件å。
+S_19 ä¿å­˜ä¸º(&A):
+B_BROWSE_OUT æµè§ˆ...(&B)
+B_EASYMODE 安装时将 VPN Client 管ç†å™¨è®¾ç½®æˆç®€å•æ¨¡å¼(&E)
+
+
+PREFIX D_SW_WEB1
+CAPTION D_SW_WEB1
+S_WELCOME 您å¯ä»¥åˆ›å»ºä¸€ä¸ª SoftEther VPN Client Web 安装工具,并且将它上传到公å¸çš„ Web æœåŠ¡å™¨ã€‚用户打开网页就能自动安装 SoftEther VPN Client,您也å¯ä»¥è®¾ç½®è‡ªåŠ¨è¾“入和快速å¯åŠ¨ä¸€ä¸ªå·²å†…建的 VPN 连接设置。
+S_TITLE SoftEther VPN Web 安装工具是什么?
+S_WELCOME2 已生æˆçš„ Web 安装工具å¯ä»¥å½“åš HTML 文件放在内è”网 Web æœåŠ¡å™¨ä¸Šã€‚如果一个公å¸å‘˜å·¥è¿žæŽ¥åˆ°è¯¥ HTML 文件的 URL 上这个 SoftEther VPN Client 安装工具就会被执行。
+S_WELCOME3 使用 ActiveX 控制。支æŒåœ¨ Windows 2000 或更高版本上的 Internet Explorer 5.0 或更高版本的æµè§ˆå™¨ã€‚ä¸æ”¯æŒå…¶ä»–æµè§ˆå™¨æˆ–更低级的æ“作系统(如 Windows 98) 。
+
+
+PREFIX D_SW_WEB2
+CAPTION D_SW_WEB2
+S_BOLD1 指定一个è¦åµŒå…¥çš„ VPN 连接设置文件(.vpn file)
+S_1 请指定一个è¦åµŒå…¥åˆ° Web 安装工具上的 VPN 连接文件(.vpn) 。您å¯ä»¥åœ¨ VPN Client 管ç†å™¨ä¸Šï¼Œé€šè¿‡åœ¨ç›®æ ‡è¿žæŽ¥è®¾ç½®çš„å³å‡»èœå•ä¸­ç‚¹å‡»è¾“出 VPN 连接设置æ¥è¾“出设置文件。
+S_18 连接设置(&S):
+B_BROWSE_SETTING æµè§ˆâ€¦(&B)
+B_DELETE_SENSITIVE 在连接设置文件中删除用户å和密ç (&E)
+S_BOLD2 指定一个è¦ç”Ÿæˆçš„输出文件å
+S_3 这个工具会输出一个 ZIP 文件 (档案文件)ï¼Œè¯¥æ–‡ä»¶åŒ…å« HTML 文件和一个应该放置在 Web æœåŠ¡å™¨ä¸Šçš„ CAB 文件。请指定生æˆçš„输出文件å。
+S_19 ä¿å­˜ä¸º(&A):
+B_BROWSE_OUT æµè§ˆâ€¦(&B)
+B_EASYMODE 当安装时,将 VPN Client 管ç†å™¨è®¾ç½®æˆç®€å•æ¨¡å¼(&E)
+
+
+PREFIX D_UPDATE_NOTICE
+CAPTION å‡çº§ %s
+IDOK 显示å‡çº§çš„ä¿¡æ¯(&S)
+B_CONFIG 设定å‡çº§(&C)
+IDCANCEL ä¸è¦å†æ˜¾ç¤ºæ­¤ä¿¡æ¯(&D)
+S_INFO 已有 %s 的最新版本。您现在å¯ä»¥ä¸‹è½½å’Œå‡çº§ã€‚
+S_PRODUCT 软件:
+S_CURRENT ç›®å‰çš„版本:
+S_CURRENT_STR Ver %u.%02u.%04u%s
+S_LATEST 最新版本:
+S_LATEST_STR Ver %S%s
+
+
+PREFIX D_UPDATE_CONFIG
+CAPTION å‡çº§æ示的é…ç½®
+S_INFO 当新版本将è¦å‘布时,请定期查询 %s 的新版本和弹出æ示窗å£ã€‚\r\n\r\nHTTPS æ•°æ®åŒ…将会用在本电脑和ä½äºŽæ—¥æœ¬é©»æ³¢çš„ SoftEther å‡çº§æœåŠ¡å™¨ä¹‹é—´ï¼Œç”¨äºŽæŸ¥è¯¢æœ‰æ— å‡çº§ä¿¡æ¯ã€‚个人信æ¯ä¸ä¼šå¤–泄。
+S_TITLE %s å‡çº§ä»¥åŠæ示设置
+S_ENABLE å¯ç”¨å‡çº§æŸ¥è¯¢(&E)
+S_DISBLE ç¦ç”¨å‡çº§æŸ¥è¯¢(&D)
+IDCANCEL 关闭(&C)
+
+
+PREFIX D_SM_VMBRIDGE
+CAPTION 虚拟机本地桥说明
+S_TITLE 在虚拟机上使用本地接功能
+S_1 æ®æ£€æµ‹ï¼ŒVPN æœåŠ¡å™¨å¯èƒ½è¿è¡Œåœ¨ VM(虚拟机)上,如 VMware 或 Hyper-V。请仔细阅读下é¢çš„说明。如果你ä¸ä½¿ç”¨è™šæ‹Ÿæœºï¼Œè¯·å¿½ç•¥æ­¤æ¶ˆæ¯ã€‚
+S_2 一些虚拟机默认ç¦æ­¢ç½‘络适é…器的“混æ‚模å¼â€(Promiscuous Mode / MAC Address Spoofing)。\r\n\r\n如果混æ‚æ¨¡å¼ (Promiscuous Mode / MAC Address Spoofing) 被管ç†ç¦ç”¨ï¼Œåœ¨ VPN æœåŠ¡å™¨çš„虚拟 HUB 与物ç†ç”µè„‘上的物ç†ç½‘络适é…器之间的本地桥功能ä¸èƒ½å¾ˆå¥½åœ°å·¥ä½œã€‚通过使用虚拟机的é…置工具,你应该å…许混æ‚æ¨¡å¼ (Promiscuous Mode / MAC Address Spoofing)。\r\n\r\n有关详细信æ¯ï¼Œè¯·å‚阅您的 VM 文件。如果它是一个共享的虚拟机,且由其他人管ç†ï¼Œè¯·å‘管ç†å‘˜è¯·æ±‚å…许使用你的虚拟机的混æ‚æ¨¡å¼ (Promiscuous Mode / MAC Address Spoofing)。
+S_BOLD 说明
+IDCANCEL 确定(&O)
+
+
+PREFIX D_SM_AZURE
+CAPTION VPN Azure æœåŠ¡è®¾ç½®
+S_TITLE VPN Azure 云 VPN æœåŠ¡ï¼ˆå…费)
+S_1 VPN Azure å¯ä»¥æ›´å®¹æ˜“地建立一个 VPN 会è¯ï¼Œä»Žä½ å®¶é‡Œçš„计算机到你办公室的计算机。当一个 VPN 连接建立了,您å¯ä»¥è®¿é—®æ‚¨å…¬å¸ä¸“用网络上的任何其他æœåŠ¡å™¨ã€‚
+S_2 在办公室的计算机(VPN æœåŠ¡å™¨ï¼‰ä¸Šï¼Œä½ å¹¶ä¸éœ€è¦ä¸€ä¸ªå…¨çƒ IP 地å€ã€‚它å¯ä»¥åœ¨é˜²ç«å¢™æˆ– NAT åŽé¢å·¥ä½œã€‚无需网络管ç†å‘˜çš„é…置。您å¯ä»¥åœ¨æ‚¨çš„家用电脑使用 Windows 内置的 SSTP VPN 客户端。
+S_3 VPN Azure 是一个云 VPN æœåŠ¡ç”± SoftEther å…¬å¸ç»è¥ã€‚ VPN Azure 是å…费的,å¯æ供给任何人。按å³è¾¹çš„按钮å¯ä»¥æŸ¥çœ‹è¯¦ç»†ä¿¡æ¯å’Œå¦‚何使用的说明。
+B_BOLD VPN Azure 设置
+R_ENABLE å¯ç”¨ VPN Azure(&E)
+R_DISABLE ç¦ç”¨ VPN Azure(&D)
+S_HOSTNAME_BORDER å½“å‰ VPN Azure 主机å
+S_HOSTNAME_INFO VPN Azure 主机åä¸ŽåŠ¨æ€ DNS 主机å相åŒï¼Œä½†æ”¹å˜çš„域ååŽç¼€ä¸ºâ€œvpnazure.netâ€ã€‚
+B_CHANGE å˜æ›´ä¸»æœºå(&H)
+B_WEB 如何使用 VPN Azure\r\n(访问网络)
+IDCANCEL 确定(&O)
+
+
+PREFIX D_SM_PROXY
+CAPTION 通过代ç†æœåŠ¡å™¨è¿žæŽ¥
+STATIC9 您å¯ä»¥é€šè¿‡ä»£ç†æœåŠ¡å™¨è¿žæŽ¥
+STATIC10 代表类型:
+R_DIRECT_TCP 直接 TCP/IP 连接(无代ç†)(&D)
+R_HTTPS 通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥(&T)
+R_SOCKS 通过 SOCKS 代ç†æœåŠ¡å™¨è¿žæŽ¥(&K)
+B_PROXY_CONFIG 代ç†æœåŠ¡å™¨è®¾ç½®(&R)
+IDOK 确定(&O)
+IDCANCEL å–消
+
+
+PREFIX D_VGC_LIST
+CAPTION SoftEther VPN 客户端的 VPN Gate 学术试验项目æ’件
+S_TITLE VPN Gate 公共 VPN 中继æœåŠ¡å™¨
+S_INFO1 通过使用 VPN 连接ç»ç”±å…¨ä¸–界志愿者æ供的公共 VPN æœåŠ¡å™¨èŽ·å¾—自由访问互è”网。绕过您的本地故障防ç«å¢™çš„æ•°æ®åŒ…拦截,并安全地éšè—ä½ çš„ IP 地å€ã€‚
+IDOK 连接到 VPN æœåŠ¡å™¨(&C)
+B_PROXY 代ç†è®¾ç½®(&P)
+S_VLAN 虚拟网络适é…器:
+B_WEB VPN Gate 学术\r\n官方网站
+B_REFRESH 刷新列表(&R)
+S_REFRESH 刷新列表...
+S_RESEARCH 日本筑波大学的一个学术项目
+S_INFO9 带有更快线路速度值 (Mbps) å’Œè¾ƒå° Ping 结果的 VPN æœåŠ¡å™¨è®©ä½ æ›´åŠ èˆ’适。如果你使用国外的 VPN æœåŠ¡å™¨ï¼Œæ‚¨å¯ä»¥æµè§ˆä»Žæ‚¨æ‰€åœ¨å›½å®¶æ— æ³•è®¿é—®çš„网站。
+
+
+PREFIX D_VGC_PROTOCOL
+CAPTION 选择 VPN åè®®æ¥è¿žæŽ¥
+S_TITLE 公共 VPN 中继æœåŠ¡å™¨ "%S" (%S) æ”¯æŒ TCP å’Œ UDP 作为 VPN å议。
+S_INFO 选择å爱的 VPN åè®®æ¥ä½¿ç”¨ä»¥è¿žæŽ¥ VPN æœåŠ¡å™¨ "%S" (%S)。一般情况下,TCP å议很容易通过防ç«å¢™ã€‚åªæœ‰å½“ TCP 失败时,å†å°è¯•ä½¿ç”¨ UDP å议。
+R_TCP 使用 &TCP åè®® (Ethernet over HTTPS VPN) (推è)
+R_UDP 使用 &UDP åè®® (Ethernet over UDP VPN)
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_VGS_CONFIG
+CAPTION VPN Gate æœåŠ¡æŽ§åˆ¶é¢æ¿
+R_ENABLE å¯ç”¨ VPN Gate 中继æœåŠ¡å’Œä½œä¸ºå¿—愿者加入 VPN Gate 研究(&E)。
+S_TITLE 加入 VPN Gate 的学术研究项目�
+S_INFO1 VPN Gate 是一个以 "分布å¼çš„公共 VPN 中继æœåŠ¡å™¨" 技术为研究的学术实验,日本筑波大学研究生院è¿ä½œçš„。VPN Gate 客户端用户å¯ä»¥è¿žæŽ¥åˆ° VPN Gate 公共 VPN 中继æœåŠ¡å™¨ä¸Šè¿è¡Œçš„æœåŠ¡ï¼Œå¹¶é€šè¿‡ VPN 中继æœåŠ¡å™¨äº«å—æ— é™åˆ¶çš„上网。
+S_INFO9 当一个 VPN Gate 客户端用户访问互è”网上的æœåŠ¡å™¨ï¼Œæº IP 地å€å°†è¢«æ›¿æ¢ä¸ºä¸­ç»§å…¬å…± VPN æœåŠ¡å™¨çš„ IP 地å€ã€‚因此,VPN Gate 客户端用户将能够顺利地æµè§ˆæµ·å¤–网站,å³ä½¿ç”¨æˆ·çš„本地防ç«å¢™å› æœªçŸ¥åŽŸå› å‘生故障,无法通过这样的访问。
+S_WARNING 如果您选中上述å¤é€‰æ¡†ï¼Œç„¶åŽæŒ‰ OK,VPN Gate 中继æœåŠ¡å°†åœ¨è¿™å°ç”µè„‘上激活。结果,任何 VPN Gate 客户端将能够通过 VPN Gate 中继æœåŠ¡å¯¹äº’è”网进行通信。它是安全的,å³ä½¿ä½ çš„计算机是专用网络 (如ä¼ä¸šç½‘),因为任何ç§æœ‰ IP 地å€çš„访问ä¸ä¼šè¢«å…许ç»ç”± VPN Gate 中继æœåŠ¡é€šè¿‡ã€‚
+B_OPTION VPN Gate æœåŠ¡é€‰é¡¹è®¾ç½®(&O)...
+IDOK &OK
+IDCANCEL å–消
+B_WEB æµè§ˆ http://www.vpngate.net/ ...
+
+
+PREFIX D_VGS_OPTION
+CAPTION VPN Gate æœåŠ¡é€‰é¡¹
+S_TITLE VPN Gate æœåŠ¡é€‰é¡¹
+S_1 è¿™å°è®¡ç®—机将æˆä¸ºä¸€ä¸ªå…¬å…± VPN æœåŠ¡å™¨ã€‚请填写è¿è¥å•†çš„æœåŠ¡å™¨ä¿¡æ¯ã€‚这些信æ¯å°†è¢«å…¬å¸ƒåœ¨ www.vpngate.net çš„åå•ä¸Šå’Œå…¶ä»–相关æœåŠ¡ã€‚è”系地å€ä¹Ÿå°†è¢«ç”¨äºŽä»Ž VPN Gate 学术项目è¿è¥å•†çš„è”系。
+S_2 è¿è¥å•†:
+S_3 æœåŠ¡å™¨çš„è¿è¥å•†(&O):
+S_19 (最多 64 个字æ¯)
+S_20 ä¸è‰¯å†…容举报地å€\r\n(e-mail 地å€ç­‰) (&A):
+S_21 (最多 64 个字æ¯)
+S_22 给用户的消æ¯(&M):\r\n(最多 128 个字æ¯)
+S_23 该消æ¯å°†æ˜¾ç¤ºåœ¨ VPN Gate æœåŠ¡å™¨çš„列表中。输入一个令人愉快的消æ¯ï¼Œè®©ç”¨æˆ·æ„Ÿåˆ°é«˜å…´ã€‚
+S_24 VPN 设置:
+R_LOG ä¿å­˜ VPN æ•°æ®åŒ…日志 (推è) (&S)
+R_2WEEKS 两周åŽè‡ªåŠ¨åˆ é™¤æˆ–存档数æ®åŒ…æ—¥å¿—ç¼–ç  (推è) (&T)
+R_PERMANENT 使数æ®åŒ…日志永久å ç”¨ç£ç›˜ç©ºé—´ (&P)
+R_L2TP å¯ç”¨ L2TP/IPSec VPN æœåŠ¡å™¨åŠŸèƒ½ (推è) (&L)
+S_25 å…许 Mac OS Xã€iPhoneã€iPad å’Œ Android 客户端进行 VPN 连接。
+B_MESSAGE 在 VPN 客户端和å±å¹•ä¸Šå¼¹å‡ºæ‚¨çš„广告消æ¯(&S)...
+IDOK &OK
+IDCANCEL å–消
+
+
+PREFIX D_VGS_WARNING
+CAPTION 在连接 VPN Gate 学术实验å‰çš„注æ„事项
+S1 VPN Gate 学术实验æœåŠ¡æ˜¯ä½œä¸ºæ—¥æœ¬ç­‘波大学研究生院的一个研究项目è¿è¥çš„。该æœåŠ¡å—制于日本法律。其他国家的法律ä¸å—我们关注也ä¸æ‰¿æ‹…责任。
+S2 从本质上讲,在世界上有近 200 个国家,都有ä¸åŒçš„法律。ä¸å¯èƒ½åœ¨è½¯ä»¶å‘布å‰åŽ»éªŒè¯æ¯ä¸€ä¸ªå›½å®¶çš„法律和法规,并使我们的软件符åˆæ‰€æœ‰å›½å®¶çš„法律。如果用户在一个特定的国家使用 VPN Gate æœåŠ¡ï¼ŒæŸå公务人员的æƒåŠ›ï¼ŒæœåŠ¡æˆ–软件的开å‘者将永远ä¸ä¼šè´Ÿè´£æ¢å¤æˆ–è¡¥å¿ç­‰æŸå®³æˆ–刑事责任。
+S3 通过使用本软件和æœåŠ¡ï¼Œç”¨æˆ·æœ‰è‡ªå·±çš„义务必须éµå®ˆæ‰€æœ‰ç›¸å…³çš„法律和规则。用户将完全承担任何æŸå¤±å’Œä½¿ç”¨æœ¬è½¯ä»¶åŠæœåŠ¡å¯¼è‡´çš„责任,无论日本领土以内还是以外。
+S4 如果你ä¸åŒæ„也ä¸ç†è§£ä¸Šè¿°è­¦å‘Šï¼Œä¸è¦ä½¿ç”¨ä»»ä½• VPN Gate 学术实验æœåŠ¡åŠŸèƒ½ã€‚
+S5 注: VPN Gate 仅仅是学术目的的一个研究项目。VPN Gate 是作为 SoftEther VPN 的一个æ’件被开å‘的。然而,VPN Gate çš„æ¯ä¸€éƒ¨åˆ†éƒ½æ˜¯åœ¨ç­‘波大学的这一研究项目被开å‘的。VPN Gate 的任何部分都ä¸æ˜¯ SoftEther å…¬å¸å¼€å‘的。VPN Gate 研究项目ä¸æ˜¯ç”± SoftEther å…¬å¸å¼•å¯¼ã€ç»è¥ï¼ŒæŽ¨å¹¿å’Œä¿è¯çš„。
+R_NEVER 请ä¸è¦å†æ¬¡æ˜¾ç¤ºæ­¤æ¶ˆæ¯(&S)
+B_WEB 访问 VPN Gate 和网站 ...
+IDOK åŒæ„(&A)
+IDCANCEL ä¸åŒæ„(&D)
+S_BOLD 注æ„! ä¸è¦åœ¨ VPN 通讯ç¦æ­¢çš„国家使用 VPN Gate æœåŠ¡ã€‚
+
+
+
+
+###########################################################################
+# #
+#软件èœå•çš„å­—ç¬¦ä¸²æ•°æ® #
+# #
+###########################################################################
+
+
+# 连接管ç†å™¨èœå•
+PREFIX CM_MENU
+#“连接†èœå•
+CMD_TOP_CONNECT 连接(&C)
+CMD_CONNECT 连接(&O)\tEnter
+CMD_STATUS 查看状æ€(&S)...\tCtrl+S
+CMD_DISCONNECT æ–­å¼€(&I)\tCtrl+D
+CMD_DISCONNECT_ALL 断开所有(&A)\tCtrl+I
+CMD_NEW 新 VPN 连接设置(&N)...\tCtrl+N
+CMD_CLONE å¤åˆ¶(&C)\tCtrl+C
+CMD_SHORTCUT 创建 VPN 连接快æ·æ–¹å¼(&H)...
+CMD_EXPORT_ACCOUNT 导出 VPN 连接设置(&X)...
+CMD_IMPORT_ACCOUNT 导入 VPN 连接设置(&P)...
+CMD_STARTUP å¯åŠ¨è¿žæŽ¥è®¾ç½®(&T)\tCtrl+T
+CMD_NOSTARTUP 移除连接设置(&E)
+CMD_RECENT 最近的 VPN Server(&V)
+CMD_RENAME é‡å‘½å(&M)\tF2
+CMD_DELETE 删除(&D)\tDel
+CMD_PROPERTY 属性(&R)...\tAlt+Enter
+CMD_EXIT 关闭连接管ç†å™¨(&O)\tAlt+F4
+CMD_QUIT 退出连接管ç†å™¨ç¨‹åº(&X)\tAlt+Q
+#“编辑†èœå•
+CMD_TOP_EDIT 编辑(&E)
+CMD_SELECT_ALL 全选(&A)\tCtrl+A
+CMD_SWITCH_SELECT 切æ¢é€‰æ‹©(&I)
+#“查看â€èœå•
+CMD_TOP_VIEW 查看(&V)
+CMD_STATUSBAR 显示状æ€æ (&S)
+CMD_VISTASTYLE Windows Vista / Windows 7 / Windows 8 风格(&T)
+CMD_SHOWPORT 在连接列表中显示端å£(&P)
+CMD_TRAYICON 显示任务托盘上的图标(&T)
+CMD_ICON 图标(&I)
+CMD_DETAIL 详细(&D)
+CMD_GRID 显示边框(&G)
+CMD_REFRESH 刷新(&R)\tF5
+#“虚拟局域网†èœå•
+CMD_TOP_VLAN 虚拟适é…器(&L)
+CMD_NEW_VLAN 新建虚拟网络适é…器(&C)...\tCtrl+L
+CMD_ENABLE_VLAN å¯ç”¨è™šæ‹Ÿç½‘络适é…器(&E)\tCtrl+E
+CMD_DISABLE_VLAN ç¦ç”¨è™šæ‹Ÿç½‘络适é…器(&S)\tCtrl+B
+CMD_DELETE_VLAN 删除虚拟网络适é…器(&D)\tDel
+CMD_REINSTALL é‡æ–°å®‰è£…驱动程åº(&U)...\tCtrl+U
+CMD_WINNET 打开&Windows网络连接...\tCtrl+W
+#“连接†èœå•
+CMD_TOP_SECURE 智能å¡(&S)
+CMD_SECURE_MANAGER 智能å¡ç®¡ç†å™¨(&M)...\tCtrl+G
+CMD_SECURE_SELECT 选择一个智能å¡ä½¿ç”¨(&S)...
+#“工具†èœå•
+CMD_TOP_TOOL 工具(&T)
+CMD_PASSWORD 设置密ç (&P)...\tCtrl+P
+CMD_TRUST 管ç†ä¿¡ä»»çš„ CA è¯ä¹¦åˆ—表(&T)\tCtrl+R
+CMD_NETIF 网络设备状æ€(&N)...
+CMD_TCPIP TCP å议优化工具(&O)...
+CMD_MMCSS Windows Vista / Windows 7 / Windows 8 的优化(&V)...
+CMD_TRAFFIC 网络通信速度测试工具(&R)...\tCtrl+Q
+CMD_CM_SETTING 切æ¢è¿è¡Œæ¨¡å¼(&M)...
+CMD_LANGUAGE 语言设置(&L)
+CMD_OPTION 选项(&O)...\tCtrl+O
+#“语音â€èœå•
+CMD_TOP_VOICE 语音(&O)
+CMD_VOIDE_NONE 关闭语音指å—(&D)
+CMD_VOICE_NORMAL 正常语音指å—(&N)
+CMD_VOICE_ODD 扩展语音指å—(&O)
+#“帮助â€èœå•
+CMD_TOP_HELP 帮助(&H)
+CMD_ABOUT 关于(&A)...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+###########################################################################
+# #
+# 命令æç¤ºç¬¦å­—ç¬¦ä¸²æ•°æ® #
+# #
+###########################################################################
+
+PREFIX NULL
+
+# 控制å°ç³»ç»Ÿæ€»è§ˆ
+CON_INFILE_ERROR 错误: 无法打开指定的输入文件 "%s"。
+CON_OUTFILE_ERROR 错误: 无法创建指定的输出文件 "%s"。
+CON_INFILE_START 在文件 "%s" 中写入命令将被使用代替键盘输入。
+CON_OUTFILE_START 该消æ¯è¾“出到控制å°å°†è¢«ä¿å­˜åœ¨æ–‡ä»¶ "%s"。
+CON_USER_CANCEL [EOF]
+CON_UNKNOWN_CMD "%S": 命令未找到。\n您å¯ä»¥ä½¿ç”¨ "HELP" 命令æ¥æŸ¥çœ‹ä¸€ä¸ªå¯ç”¨çš„命令列表。
+CON_AMBIGIOUS_CMD "%S": 命令å称是模糊的。
+CON_AMBIGIOUS_CMD_1 指定的命令å称匹é…以下多个命令:
+CON_AMBIGIOUS_CMD_2 请更严格地é‡æ–°æŒ‡å®šå‘½ä»¤å称。
+CON_INVALID_PARAM å‚æ•° "/%S" 已被指定。使用命令 "%S" 时,ä¸å¯èƒ½æŒ‡å®šæ­¤å‚数。输入 "%S /HELP" æ¥çœ‹è¢«ä½¿ç”¨çš„å‚数清å•ã€‚
+CON_AMBIGIOUS_PARAM "/%S": å‚æ•°å称是ä¸æ˜Žç¡®çš„。
+CON_AMBIGIOUS_PARAM_1 指定的å‚æ•°å称符åˆä»¥ä¸‹ï¼Œè¢«æŒ‡å®šçš„åšä¸ºå‘½ä»¤ "%S" å‚æ•°çš„å‚æ•°:
+CON_AMBIGIOUS_PARAM_2 请更严格地é‡æ–°æŒ‡å®šå‚æ•°å称。
+
+
+# ä¸æ˜Žå‘½ä»¤
+CMD_UNKNOWM 没有这个命令的说明。
+CMD_UNKNOWN_HELP 没有这个命令的详细æ述。如果您想了解更多有关此命令的详细资料,请å‚阅手册或在线文档。
+CMD_UNKNOWN_ARGS 没有命令执行的例å­ã€‚
+CMD_UNKNOWN_PARAM 没有这个å‚数的说明。
+
+
+# 控制å°ç³»ç»Ÿå†…使用的字符串
+CMD_HELP_1 您å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„ %u 命令:
+CMD_HELP_2 å‚考æ¯ä¸ªå‘½ä»¤çš„使用,输入 "命令å称 /?" æ¥æŸ¥çœ‹å¸®åŠ©ã€‚
+CMD_EVAL_MIN_MAX 您必须指定从 %u 到 %u 的整数。
+CMD_PROMPT 输入一个值:
+CMD_EVAL_NOT_EMPTY 规格ä¸èƒ½ä¸ºç©ºç™½ã€‚
+CMD_EVAL_SAFE 该字符串包å«ä¸å¯ç”¨çš„字符。
+CMD_EVAL_INT 您必须指定一个ä¸å°äºŽ 1 的整数。
+CMD_HELP_TITLE 关于命令 "%S" 的帮助
+CMD_HELP_DESCRIPTION [目的]
+CMD_HELP_USAGE [使用方法]
+CMD_HELP_HELP [说明]
+CMD_HELP_ARGS [å‚æ•°]
+CMD_PROPMT_PORT 输入端å£å·:
+CMD_EVAL_PORT 端å£å·æ— æ•ˆã€‚指定一个范围是 1 到 65535 的端å£å·ã€‚
+CMD_CT_STD_COLUMN_1 项目
+CMD_CT_STD_COLUMN_2 价值
+CMD_CT_STD_COLUMN_3 说明
+CMD_PARSE_IP_SUBNET_ERROR_1_6 指定 "IPv6 地å€/å­ç½‘掩ç " æ ¼å¼ã€‚\n通过用冒å·æ¥åˆ†å¼€è¿™åå…­ä½è¿›åˆ¶çš„数值æ¥æŒ‡å®š IPv6 地å€ï¼Œå¦‚如“ 2001:200:0:1::â€ã€‚对于å­ç½‘掩ç ï¼Œæ‚¨å¯ä»¥æŒ‡å®šç”¨å†’å·åˆ†å¼€çš„åå…­ä½è¿›åˆ¶æ•°å€¼ï¼Œå¦‚ “ffff:ffff:ffff:ffff::â€ï¼Œæˆ–者您也å¯ä»¥ç”¨å进制数值指定å­ç½‘掩ç çš„比特长度,如 64。\nè¦æŒ‡å®šä¸€ä¸ªç‹¬ç«‹ä¸»æœºï¼ŒæŒ‡å®šå­ç½‘掩ç ä¸ºâ€œ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffffâ€æˆ– “128â€ã€‚\n(例)\n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/12\n\n
+CMD_PARSE_IP_SUBNET_ERROR_1 指定 "IPv4 地å€/å­ç½‘掩ç " æ ¼å¼ã€‚\n通过用å°æ•°ç‚¹æ¥åˆ†éš”å进制数值æ¥æŒ‡å®š IPv4 地å€ï¼Œå¦‚ “192.168.0.1â€ã€‚对于å­ç½‘掩ç ï¼Œæ‚¨å¯ä»¥é€šè¿‡ä½¿ç”¨å°æ•°ç‚¹åˆ†éš”å进制数值æ¥æ¥æŒ‡å®šï¼Œå¦‚ “255.255.255.0â€ï¼Œæˆ–者您也å¯ä»¥é€šè¿‡ä½¿ç”¨å进制数值æ¥æŒ‡å®šå­ç½‘掩ç çš„比特长度如 24。\nè¦æŒ‡å®šä¸€ä¸ªç‹¬ç«‹ä¸»æœºï¼Œæ‚¨å¯ä»¥æŒ‡å®šå­ç½‘掩ç ä¸º 255.255.255.255 或 32\n(例)\n192.168.0.1/24\n192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+CMD_PARSE_IP_SUBNET_ERROR_2 指定的 IP 地å€ä¸æ˜¯ç½‘络地å€ã€‚
+CMD_PARSE_IP_SUBNET_ERROR_3 指定的 IP 地å€ä¸æ˜¯ç½‘络地å€å‰ç¼€ã€‚
+CMD_EVAL_DATE_TIME_FAILED 日期和时间规格无效。\n日期和时间必须为相åŒçš„æ ¼å¼å¦‚ "2005/10/08 19:30:00",指定 6 个整数代表年/月/æ—¥ å°æ—¶:分钟:秒,用斜线,空格和冒å·åˆ†éš”。年指定为 4 ä½æ•°ã€‚
+CMD_PARSE_IP_MASK_ERROR_1_6 指定 "IPv6 地å€/掩ç " æ ¼å¼ã€‚\n通过用冒å·æ¥åˆ†éš”å六进制的数值æ¥æŒ‡å®š IPv6 地å€ï¼Œå¦‚ “2001:200:0:1::â€ã€‚对于掩ç ï¼Œæ‚¨å¯ä»¥æŒ‡å®šç”±å†’å·åˆ†éš”çš„å六进制的数值,如 ffff:ffff:ffff:ffff::,或者您也å¯ä»¥ç”¨å进制数值æ¥æŒ‡å®šæŽ©ç çš„比特长度如 64。\nè¦æŒ‡å®šä¸€ä¸ªç‹¬ç«‹ä¸»æœºï¼ŒæŒ‡å®šæŽ©ç ä¸º “ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff â€æˆ–“128â€ã€‚\n(例) \n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/12\n\n
+CMD_PARSE_IP_MASK_ERROR_1 指定 "IPv4 地å€/掩ç " æ ¼å¼ã€‚\n通过用å°æ•°ç‚¹æ¥åˆ†éš”å进制数值æ¥æŒ‡å®š IPv4 地å€ï¼Œå¦‚“192.168.0.1â€ã€‚对于掩ç ï¼Œæ‚¨å¯ä»¥æŒ‡å®šç”¨å°æ•°ç‚¹åˆ†éš”çš„å进制数值,如 “255.255.255.0â€ï¼Œæˆ–者您也å¯ä»¥ç”¨å进制值指定掩ç çš„比特长度,如 24。\nè¦æŒ‡å®šä¸€ä¸ªç‹¬ç«‹ä¸»æœºï¼ŒæŒ‡å®šæŽ©ç ä¸º 255.255.255.255 或 32\n(例) \n 192.168.0.1/24\n 192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+
+
+
+# 通用信æ¯
+CMD_MSG_INVALID_HOSTNAME 指定的主机å无效。
+CMD_MSG_OK 命令æˆåŠŸå®Œæˆã€‚
+CMD_MSG_ALLOW å…许
+CMD_MSG_DENY æ‹’ç»
+CMD_MSG_INFINITE æ— é™
+CMD_MSG_ENABLE å¯ç”¨
+CMD_MSG_DISABLE ç¦ç”¨
+CMD_MSG_LOAD_CERT_FAILED 无法读å–指定的 X.509 è¯ä¹¦æ–‡ä»¶ã€‚
+CMD_MSG_SAVE_CERT_FAILED 无法写入 X.509 è¯ä¹¦æ–‡ä»¶ã€‚
+CMD_ACCOUNT_COLUMN_NAME VPN 连接设置å称
+CMD_ACCOUNT_COLUMN_HOSTNAME 目标 VPN Server 主机å
+CMD_ACCOUNT_COLUMN_PORT 目标 VPN Server 端å£å·
+CMD_ACCOUNT_COLUMN_HUBNAME 目标 VPN Server 虚拟 HUB å称
+CMD_ACCOUNT_COLUMN_PROXY_TYPE 代ç†æœåŠ¡å™¨ç±»åž‹
+CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME 代ç†æœåŠ¡å™¨ä¸»æœºå
+CMD_ACCOUNT_COLUMN_PROXY_PORT 代ç†æœåŠ¡å™¨çš„端å£å·
+CMD_ACCOUNT_COLUMN_PROXY_USERNAME 代ç†æœåŠ¡å™¨çš„用户å
+CMD_ACCOUNT_COLUMN_SERVER_CERT_USE 验è¯æœåŠ¡å™¨è¯ä¹¦
+CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME 注册的æœåŠ¡å™¨ä¸ªäººè¯ä¹¦
+CMD_ACCOUNT_COLUMN_DEVICE_NAME 用于连接的设备å
+CMD_ACCOUNT_COLUMN_AUTH_TYPE 验è¯ç±»åž‹
+CMD_ACCOUNT_COLUMN_AUTH_USERNAME 用户å
+CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME 客户端验è¯ä½¿ç”¨è¯ä¹¦
+CMD_ACCOUNT_COLUMN_NUMTCP VPN 通信中使用的 TCP 的连接数
+CMD_ACCOUNT_COLUMN_TCP_INTERVAL 建立æ¯ä¸ª TCP 连接的间隔
+CMD_ACCOUNT_COLUMN_TCP_TTL æ¯ä¸ª TCP 连接的连接周期
+CMD_ACCOUNT_COLUMN_TCP_HALF 使用åŠåŒå·¥æ¨¡å¼
+CMD_ACCOUNT_COLUMN_ENCRYPT 通过 SSL 加密
+CMD_ACCOUNT_COLUMN_COMPRESS æ•°æ®åŽ‹ç¼©
+CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER 通过网桥 / 路由模å¼è¿žæŽ¥
+CMD_ACCOUNT_COLUMN_MONITOR 通过监测模å¼è¿žæŽ¥
+CMD_ACCOUNT_COLUMN_NO_TRACKING ä¸è¦è°ƒæ•´è·¯ç”±è¡¨
+CMD_ACCOUNT_COLUMN_QOS_DISABLE ä¸è¦ä½¿ç”¨ QoS 控制功能
+
+
+# Debugging Information Collecting Tool
+CMD_DEBUG_SOFTNAME 调试信æ¯é‡‡é›†å·¥å…·
+CMD_DEBUG_PRINT 调试信æ¯é‡‡é›†å·¥å…·\r\n\r\n
+CMD_DEBUG_NOT_2000 è¦æ±‚ Windows 2000 或更高版本。
+CMD_DEBUG_NOT_ADMIN 您必须以管ç†å‘˜èº«ä»½ç™»å½• Windows 执行此命令。
+CMD_DEBUG_UAC_FAILED 无法获得管ç†å‘˜æƒé™ã€‚
+CMD_DEBUG_SAVE_TITLE 指定ä¿å­˜æ–‡ä»¶çš„目标路径
+CMD_DEBUG_OK 一个调试信æ¯æ–‡ä»¶è¢«ä¿å­˜ä¸º "%s"。\r\n\r\nå‘é€æ­¤æ–‡ä»¶åˆ°ä½ çš„支æŒäººå‘˜ã€‚\r\n在å‘é€ç»™æ”¯æŒäººå‘˜ä»¥å‰ï¼Œæ‚¨å¿…须验è¯æ­¤æ–‡ä»¶çš„内容。\r\n如果有一些你ä¸æƒ³é€éœ²ç»™å…¶ä»–工作人员的机密信æ¯ï¼Œä½ æœ‰è´£ä»»ç§»é™¤è¿™ä¸ªæ–‡ä»¶ä¸­çš„机密信æ¯ã€‚\r\n\r\n如果你忽略了包å«åœ¨æ­¤æ–‡ä»¶ä¸­çš„机密信æ¯ï¼Œå¹¶ä¸”ä½ åŒæ„将整个文件å‘é€ç»™æ”¯æŒäººå‘˜ï¼Œè¿™æ„味ç€ä½ å·²ç»åŒæ„é€éœ²æ–‡ä»¶ä¸­çš„全部内容给支æŒäººå‘˜ã€‚
+CMD_DEBUG_NG 无法ä¿å­˜è°ƒè¯•ä¿¡æ¯ä¸º "%s"。
+
+
+# 测试命令
+CMD_TEST 执行测试è¿è¡Œã€‚
+CMD_TEST_HELP 这是一个测试命令。执行测试è¿è¡Œã€‚éšç€æµ‹è¯•å‘½ä»¤ï¼Œæ‚¨å¯ä»¥æŒ‡å®šè®¸å¤šå‚数。您å¯ä»¥çœç•¥å‚数的个数。
+CMD_TEST_ARGS Test [/A1:a_str] [/A2:b_str] [/A3:int_value]
+CMD_TEST_A1 指定å‚æ•°æ ¼ A1。这å¯ä»¥è¢«çœç•¥ã€‚
+CMD_TEST_A2 指定å‚æ•° A2。如果忽略,当命令执行时,æ示将显示输入å‚æ•° A2。规格ä¸èƒ½æ˜¯ç©ºç™½ã€‚
+CMD_TEST_A3 指定一个数值。您必须指定一个范围是 1 到 100 之间的整数。指定的整数超出此范围,将导致错误信æ¯æ˜¾ç¤ºã€‚
+CMD_TEST_EVAL_A2 å‚æ•° A2 的规格ä¸èƒ½æ˜¯ç©ºç™½ã€‚
+CMD_IP_EVAL_FAILED IP 地å€æŒ‡å®šä¸æ­£ç¡®ã€‚
+CMD_HOSTPORT_EVAL_FAILED 主机å和端å£å·è§„格无效。\n请使用指定的主机åæ ¼å¼:端å£å· 或 IP 地å€:端å£å·ã€‚
+CMD_PORTLIST_EVAL_FAILED 端å£å·åˆ—表规格无效。\n列表必须至少有一个端å£å·è®¾ç½®ï¼Œä¹Ÿå¯ä»¥è®¾ç½®å¤šä¸ªç«¯å£å·ã€‚当指定多个端å£å·æ—¶ï¼Œä½¿ç”¨é€—å·éš”开,如 "443,992,8888"。
+CMD_PROTOCOL_EVAL_FAILED å议指定ä¸æ­£ç¡®ã€‚å¯ä»¥ä¸ºå议指定 ip, tcp, udp, icmpv4, icmpv6 或å议数字 (0 到 255)。
+CMD_PORT_RANGE_EVAL_FAILED 端å£å·æˆ–端å£å·èŒƒå›´æŒ‡å®šä¸æ­£ç¡®ã€‚如果仅指定一个端å£å·ï¼Œå¿…须使用一个整数æ¥æŒ‡å®šç«¯å£å·ã€‚如果指定多个端å£ï¼Œå¼€å§‹ç«¯å£å·å’Œç»“æŸç«¯å£å·åŠ ä¸€ä¸ªè¿žå­—符æ¥æŒ‡å®šï¼Œå¦‚ "80-443"。
+CMD_TCP_CONNECTION_STATE_EVAL_FAILED TCP 连接状æ€è§„格无效。\n指定 "已设立" 或 "未设立",并且在选择å议时指定 TCP。
+CMD_MAC_ADDRESS_AND_MASK_EVAL_FAILED MAC 地å€å’ŒæŽ©ç è§„格无效。\n使用有分隔符('-' 或 ':')çš„å六进制数字,和没有分隔符。一个例å­æ˜¯ "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-FF"。
+CMD_EXEC_MSG_NAME %S 命令 - %s
+CMD_ID ID
+CMD_FILE_NOT_FOUND 找ä¸åˆ°æŒ‡å®šçš„文件 "%s"。
+CMD_FILE_NAME_EMPTY 文件å没有被指定。
+CMD_SAVECERTPATH ä¿å­˜ X.509 è¯ä¹¦åˆ°æ–‡ä»¶å:
+CMD_SAVECERT_FAILED 无法ä¿å­˜è¯ä¹¦æ–‡ä»¶ã€‚
+CMD_SAVEKEYPATH ä¿å­˜å¯†é’¥åˆ°æ–‡ä»¶å:
+CMD_SAVEKEY_FAILED 无法ä¿å­˜å¯†é’¥æ–‡ä»¶ã€‚
+CMD_SAVEFILE_FAILED 无法ä¿å­˜æ–‡ä»¶ã€‚
+CMD_LOADFILE_FAILED 无法打开文件。
+CMD_LOADCERTPATH 从……文件åè¯»å– X.509 è¯ä¹¦:
+CMD_LOADCERT_FAILED 无法读å–è¯ä¹¦æ–‡ä»¶ã€‚
+CMD_LOADKEYPATH 从文件å……读å–ç§é’¥:
+CMD_LOADKEY_FAILED 无法读å–密钥文件。
+CMD_LOADKEY_ENCRYPTED_1 指定的密钥文件被密ç ä¿æŠ¤ã€‚
+CMD_LOADKEY_ENCRYPTED_2 请输入密ç :
+CMD_LOADKEY_ENCRYPTED_3 密ç ä¸æ­£ç¡®ã€‚
+CMD_KEYPAIR_FAILED X.509 è¯ä¹¦å’Œç§é’¥çš„组åˆæŒ‡å®šä¸æ­£ç¡®ã€‚è¯ä¹¦å’Œä¸Žè¯¥è¯ä¹¦å¯¹åº”çš„ç§é’¥æ˜¯å¿…需的。
+CMD_CERT_NOT_EXISTS è¯ä¹¦æœªç™»è®°ã€‚
+CMD_NO_SETTINGS ï¼
+CMD_DISCONNECTED_MSG \n---Error---\n\n与您正管ç†çš„主机通信会è¯è¢«ä¸­æ–­äº†ã€‚从现在开始,如果您è¿è¡Œä»»ä½•å‘½ä»¤å°†å‡ºçŽ°é”™è¯¯ã€‚\n\n为了é‡æ–°è¿žæŽ¥åˆ°æ‚¨ç®¡ç†çš„主机,首先输入 "EXIT" 的离本开æ示,然åŽé‡æ–°è¿žæŽ¥ã€‚\n\n
+
+
+# VPN CMD 命令
+CMD_VPNCMD SoftEther VPN 命令行管ç†å·¥å…·
+CMD_VPNCMD_HELP “vpncmd â€ç¨‹åºæ˜¯ä¸€ä¸ªå…许您通过使用命令行æ¥ç®¡ç† SoftEther VPN 软件的实用工具。通过使用 vpncmd,您å¯ä»¥è¿žæŽ¥åˆ°è¿è¡Œåœ¨æœ¬åœ°æˆ–远程计算机的 VPN Client,VPN Server 或 VPN Bridge 并管ç†å®ƒä»¬ã€‚此外,通过使用 VPN 工具模å¼ï¼Œæ‚¨å¯ä»¥è°ƒç”¨ç½‘络传输速度测试工具和è¯ä¹¦åˆ›å»ºåŠŸèƒ½ã€‚å³ä½¿ä¸è¿žæŽ¥åˆ° VPN Server 或 VPN Client,vpncmd 也是å¯ä»¥ä½¿ç”¨çš„。\n当使用 vpncmd 时,如果文件å是通过使用 /IN å’Œ /OUT å‚数指定的,该命令就å¯ä»¥æ ¹æ®ä¸€ä¸ªæ–‡ä»¶è¢«æ‰¹é‡æ‰§è¡Œã€‚该文件列举了å¯æ‰§è¡Œå‘½ä»¤çš„文件和执行结果å¯ä»¥è¢«å†™å…¥æ–‡ä»¶ä¸­ã€‚通常,vpncmd å¯åŠ¨åŽå‘½ä»¤æ示符会出现,但是,当用 /IN å‚数指定一个输入文件时,在输入文件的所有行执行完æˆåŽï¼Œè¯¥ç¨‹åºå°†è‡ªåŠ¨ç»ˆæ­¢ã€‚此外,当指定 /CMD å‚æ•°æ¥æ‰§è¡Œä¸€ä¸ªå‘½ä»¤æ—¶ï¼Œåœ¨å‘½ä»¤æ‰§è¡Œå®ŒæˆåŽï¼Œç¨‹åºå°†è‡ªåŠ¨ç»ˆæ­¢ã€‚您ä¸èƒ½åŒæ—¶åˆ»æŒ‡å®š /IN å‚æ•°å’Œ /CMD å‚数。vpncmd 程åºçš„终止代ç å°†æ˜¯æœ€åŽæ‰§è¡Œå‘½ä»¤çš„é”™è¯¯ä»£ç  (在æˆåŠŸæ‰§è¡Œçš„情况下是 0)。在 Windows 环境下,当具有管ç†å‘˜æƒé™çš„用户一次或多次å¯åŠ¨ vpncmd 时,有å¯èƒ½åªéœ€è¾“å…¥ "vpncmd" 到 Windows 命令æ示符或 [è¿è¡Œ...] Windows å¯åŠ¨ vpncmd。为了在 UNIX 系统下得到åŒæ ·çš„结果,您å¯ä»¥æ‰‹åŠ¨è®¾ç½®ï¼ŒPATH 环境是å¯å˜çš„。
+CMD_VPNCMD_ARGS vpncmd [host:port] [/CLIENT|/SERVER|/TOOLS] [/HUB:hub] [/ADMINHUB:adminhub] [/PASSWORD:password] [/IN:infile] [/OUT:outfile] [/CMD commands...]
+CMD_VPNCMD_[host:port] 通过指定格å¼çš„å‚æ•° [主机å:端å£å·],å¯è‡ªåŠ¨è¿žæŽ¥åˆ°ä¸»æœºã€‚如果这是没有指定的,会出现一个æ示让输入连接目的地。当连接到一个 VPN Client,您ä¸èƒ½æŒ‡å®šä¸€ä¸ªç«¯å£å·ã€‚
+CMD_VPNCMD_CLIENT 连接到 VPN 客户åšç®¡ç†ã€‚您ä¸èƒ½æŒ‡å®šå®ƒä¸Ž /SERVER 一起åšã€‚
+CMD_VPNCMD_SERVER 连接到 VPN Server 或 VPN Bridge åšç®¡ç†ã€‚您ä¸èƒ½æŒ‡å®šå®ƒä¸Ž /CLIENT 一起åšã€‚
+CMD_VPNCMD_TOOLS å¯ç”¨ VPN 工具命令。 VPN 工具包括简å•è¯ä¹¦åˆ›å»ºå·¥å…· (MakeCert 命令) 和网络传输速度测试工具 (SpeedTest 命令)。
+CMD_VPNCMD_HUB 当通过 “虚拟 HUB 管ç†æ¨¡å¼â€è¿žæŽ¥åˆ° VPN Server 时,这就指定了该虚拟 HUB å称为 "hub"。如果您指定主机å而ä¸æ˜¯ / HUB å‚数,连接将通过 “æœåŠ¡å™¨ç®¡ç†æ¨¡å¼â€è¿›è¡Œã€‚
+CMD_VPNCMD_ADMINHUB 在连接到 VPN Server åŽï¼Œè¿™å°†æŒ‡å®šè‡ªåŠ¨é€‰æ‹©çš„虚拟 HUB "adminhub" çš„å称。如果已ç»æŒ‡å®š /HUB çš„å‚数,虚拟 HUB 将被自动选定,则本指定就没有必è¦äº†ã€‚
+CMD_VPNCMD_PASSWORD 当连接时,如果需è¦ç®¡ç†å‘˜å¯†ç ï¼ŒæŒ‡å®šå¯†ç  "password"。当没有指定密ç æ—¶ï¼Œæ示输入密ç ä¼šè¢«æ˜¾ç¤ºã€‚
+CMD_VPNCMD_IN 这将指定的文本文件 "infile",其中包å«è¿žæŽ¥å®ŒæˆåŽè‡ªåŠ¨æ‰§è¡Œçš„命令列表。如果指定 /IN å‚数,在文件中所有命令文件都执行完毕åŽï¼Œvpncmd 程åºå°†è‡ªåŠ¨ç»ˆæ­¢ã€‚如果该文件包å«å¤šå­—节字符,编ç å¿…须是 Unicode (UTF-8)。这ä¸èƒ½ä¸Ž /CMD 一起被指定 (如 /CMD 是指定的,/IN 将被忽略)。
+CMD_VPNCMD_OUT 您å¯ä»¥æŒ‡å®šæ–‡æœ¬æ–‡ä»¶ "outfile" 写所有的字符串,如å±å¹•ä¸Šçš„æ示,信æ¯ï¼Œé”™è¯¯å’Œæ‰§è¡Œç»“果。请注æ„,如果指定的文件已ç»å­˜åœ¨ï¼ŒçŽ°æœ‰æ–‡ä»¶çš„内容将被覆盖。输出字符串将用 Unicode (UTF-8) ç¼–ç è¢«è®°å½•ã€‚
+CMD_VPNCMD_CMD 如果å¯é€‰å‘½ä»¤ "commands..." 包å«åœ¨ /CMD 命令之åŽï¼Œè¿žæŽ¥å®ŒæˆåŽæ­¤å‘½ä»¤å°†è¢«æ‰§è¡Œï¼Œæ­¤åŽ vpncmd 程åºå°†ç»ˆæ­¢ã€‚ä¸èƒ½ä¸Ž /IN 一起指定 (如果与 /IN 一起指定,/IN 将被忽略)。在所有其他 vpncmd å‚数之åŽæŒ‡å®š /CMD å‚数。
+CMD_VPNCMD_CSV 您å¯ä»¥é€šè¿‡æŒ‡å®šæœ¬é€‰é¡¹å¯ç”¨ CSV 输出。æ¯ä¸ªå‘½ä»¤çš„结果将会以 CSV å½¢å¼æ‰“å°ã€‚用其他程åºå¤„ç†ç»“果是有用的。
+CMD_VPNCMD_CS_1 通过使用 vpncmd 程åºï¼Œå¯ä»¥å–得以下æˆæžœã€‚\n\n1. VPN Server 或 VPN Bridge 的管ç†ã€‚\n2. VPN Client 的管ç†ã€‚\n3. 使用 VPN 工具 (è¯ä¹¦åˆ›å»ºå’Œç½‘络传输速度测试工具)\n\n
+CMD_VPNCMD_CS_2 选择 1, 2 或 3:
+CMD_VPNCMD_HOST_1 指定的主机å或目标 VPN Server 或 VPN Bridge 正在 è¿è¡Œçš„计算机 IP 地å€ã€‚\n通过以 "主机å:端å£å·" æ ¼å¼æŒ‡å®šï¼Œæ‚¨è¿˜å¯ä»¥æŒ‡å®šç«¯å£å·ã€‚\n(当没有指定端å£å·æ—¶ï¼Œä½¿ç”¨ 443。)\n如果ä¸è¾“入任何内容并按下回车键,将连接到端å£å·ä¸º 443 的本地主机 (è¿™å°ç”µè„‘)。
+CMD_VPNCMD_HOST_2 指定的主机å或正在è¿è¡Œçš„目标 VPN Client 计算机的 IP 地å€ã€‚\n如果ä¸è¾“入任何内容并且按下回车键,将连接到本地主机 (è¿™å°ç”µè„‘)。
+CMD_VPNCMD_HOST_3 目标 IP 地å€çš„主机å:
+CMD_VPNCMD_HUB_1 如果通过虚拟 HUB 管ç†æ¨¡å¼è¿žæŽ¥åˆ°æœåŠ¡å™¨ï¼Œè¯·è¾“入虚拟 HUB çš„å称。\n如果通过æœåŠ¡å™¨ç®¡ç†æ¨¡å¼è¿žæŽ¥ï¼Œæ— é¡»è¾“入任何内容请按回车键。\n
+CMD_VPNCMD_HUB_2 指定虚拟 HUB å称:
+CMD_VPNCMD_ABOUT SoftEther VPN 命令行管ç†å·¥å…· (vpncmd 命令)\n%S\n%S\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n
+CMD_VPNCMD_PASSWORD_1 访问被拒ç»ã€‚å¯èƒ½æ˜¯å¯†ç ä¸æ­£ç¡®ï¼Œæˆ–者是您以ä¸æ­£ç¡®çš„管ç†æ¨¡å¼è¿žæŽ¥ã€‚您å¯ä»¥å°è¯•å†æ¬¡è¾“入密ç ã€‚è¦å–消,请按 Ctrl + D。
+CMD_VPNCMD_PASSWORD_2 密ç :
+CMD_VPNCMD_ERROR å‘生错误。(错误代ç : %u)\n%s
+CMD_VPNCMD_SERVER_CONNECTED 与æœåŠ¡å™¨ "%S" 的连接已建立 (ç«¯å£ %u)。
+CMD_VPNCMD_SERVER_CONNECTED_1 您有整个 VPN Server 的管ç†å‘˜æƒé™ã€‚
+CMD_VPNCMD_SERVER_CONNECTED_2 您在 VPN Server 上有虚拟 HUB "%S" 的管ç†å‘˜æƒé™ã€‚
+CMD_VPNCMD_CLIENT_NO_REMODE 目标 VPN Client æœåŠ¡å™¨ä¸å…许æ¥è‡ªè¿œç¨‹è®¡ç®—机的ä¾æ³•è¡Œæ”¿çš„连接。å¯åŠ¨çš„计算机上è¿è¡Œçš„ VPN Client 并连接到本地主机的命令行管ç†å·¥å…·æˆ– VPN 客户ç»ç†ã€‚
+CMD_VPNCMD_PWPROMPT_0 请输入密ç ã€‚è¦å–消,请按下 Ctrl + D 键。
+CMD_VPNCMD_PWPROMPT_1 å¯†ç  :
+CMD_VPNCMD_PWPROMPT_2 确认输入:
+CMD_VPNCMD_PWPROMPT_3 密ç å’Œç¡®è®¤å¯†ç ä¸åŒ¹é…。请å†è¾“入密ç å’Œç¡®è®¤å¯†ç ã€‚
+CMD_VPNCMD_CLIENT_CONNECTED 连接到 VPN Client "%S"。
+CMD_VPNCMD_TOOLS_CONNECTED VPN 工具已推出。通过输入 "HELP",您å¯ä»¥æŸ¥çœ‹å¯ä½¿ç”¨çš„命令列表。
+
+
+
+
+#######################################################
+# #
+# VPN Server 的管ç†å‘½ä»¤å¦‚下 #
+# #
+#######################################################
+
+
+
+# About 命令
+CMD_About 显示版本信æ¯
+CMD_About_HELP 这显示了此命令行管ç†å·¥å…·çš„版本信æ¯ã€‚版本信æ¯ä¸­åŒ…括了 vpncmd 版本å·ï¼Œå†…部标å·å’Œå†…部标å·ä¿¡æ¯ã€‚
+CMD_About_ARGS About
+
+
+# ServerInfoGet 命令
+CMD_ServerInfoGet 获å–æœåŠ¡å™¨ä¿¡æ¯
+CMD_ServerInfoGet_Help 这使您å¯ä»¥èŽ·å–当å‰è¿žæŽ¥çš„ VPN Server 或 VPN Bridge çš„æœåŠ¡å™¨ä¿¡æ¯ã€‚æœåŠ¡å™¨ä¿¡æ¯ä¸­åŒ…括版本å·ï¼Œå†…部标å·å’Œå†…部标å·ä¿¡æ¯ã€‚您还å¯ä»¥èŽ·å–当å‰æœåŠ¡å™¨è¿è¡Œæ¨¡å¼çš„ä¿¡æ¯å’ŒæœåŠ¡å™¨ä¸Šè¿è¡Œçš„æ“作系统信æ¯ã€‚
+CMD_ServerInfoGet_Args ServerInfoGet
+
+
+# ServerStatusGet 命令
+CMD_ServerStatusGet 获å–当å‰æœåŠ¡å™¨çŠ¶æ€
+CMD_ServerStatusGet_Help 这使您å¯ä»¥å®žæ—¶èŽ·å–当å‰è¿žæŽ¥çš„ VPN Server 或 VPN Bridge 的现状。您å¯ä»¥å¾—到关于数æ®é€šä¿¡å’ŒæœåŠ¡å™¨ä¸Šå­˜åœ¨çš„ä¸åŒç±»åž‹å¯¹è±¡æ•°é‡çš„统计资料。您å¯ä»¥å¾—到当å‰è®¡ç®—机所使用的æ“作系统内存多少的信æ¯ã€‚
+CMD_ServerStatusGet_Args ServerStatusGet
+
+
+# ListenerCreate 命令
+CMD_ListenerCreate 创建新的 TCP 监å¬å™¨
+CMD_ListenerCreate_Help 这使您å¯ä»¥åœ¨æœåŠ¡å™¨ä¸Šåˆ›å»ºä¸€ä¸ªæ–°çš„ TCP 监å¬å™¨ã€‚通过建立 TCP 监å¬å™¨ï¼ŒæœåŠ¡å™¨å¼€å§‹åœ¨æŒ‡å®šçš„ TCP/IP 端å£è¿žæŽ¥ç›‘å¬ã€‚\n已创建的 TCP 监å¬å™¨å¯ä»¥è¢« ListenerDelete 命令删除。\n您还å¯ä»¥å¾—到一个当å‰ä½¿ç”¨ ListenerList 命令登记的 TCP 侦å¬å™¨åˆ—表。\nè¦æ‰§è¡Œè¿™ä¸ªå‘½ä»¤ï¼Œæ‚¨å¿…须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ListenerCreate_Args ListenerCreate [port]
+CMD_ListenerCreate_[port] 使用一个整数,指定新添加的 TCP/IP 监å¬ç«¯å£å·ã€‚您也å¯ä»¥ä½¿ç”¨ä¸€ä¸ªå·²ç»è¢«å…¶ä»–程åºä½¿ç”¨çš„端å£å·; 但 VPN Server 将无法使用,直到该程åºç»“æŸäº†åœ¨ç«¯å£çš„使用。指定一个范围从 1 到 65535 的端å£å·ã€‚
+CMD_ListenerCreate_PortPrompt 新增 TCP/IP 监å¬å™¨ç«¯å£å·:
+
+
+# ListenerDelete 命令
+CMD_ListenerDelete 删除 TCP 监å¬å™¨
+CMD_ListenerDelete_Help è¿™å…许您删除一个在æœåŠ¡å™¨ä¸Šå·²æ³¨å†Œçš„ TCP 侦å¬å™¨ã€‚当 TCP 监å¬å™¨åœ¨è¿è¡ŒçŠ¶æ€ï¼Œå½“è¿è¡Œåœæ­¢æ—¶ï¼Œç›‘å¬å™¨å°†è¢«è‡ªåŠ¨åˆ é™¤ã€‚\n您还å¯ä»¥å¾—到一个当å‰ä½¿ç”¨ ListenerList 命令登记的 TCP 监å¬å™¨åˆ—表。\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ListenerDelete_Args ListenerDelete [port]
+CMD_ListenerDelete_[port] 使用一个整数,指定è¦åˆ é™¤çš„ TCP/IP 监å¬å™¨ç«¯å£å·ã€‚
+CMD_ListenerDelete_PortPrompt TCP/IP 侦å¬å™¨ç«¯å£å·:
+
+
+# ListenerList 命令
+CMD_ListenerList èŽ·å– TCP 监å¬å™¨åˆ—表
+CMD_ListenerList_Help 这使您å¯ä»¥èŽ·å–çš„ TCP 侦å¬å™¨åˆ—表当å‰æœåŠ¡å™¨ä¸Šæ³¨å†Œã€‚您å¯ä»¥èŽ·å–有关å„ç§ TCP 监å¬å™¨çš„è¿è¡ŒçŠ¶æ€æˆ–错误的信æ¯ã€‚\n执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ListenerList_Args 监å¬å™¨åˆ—表
+CMD_ListenerList_Column1 TCP 端å£
+CMD_ListenerList_Column2 状æ€
+
+
+# ListenerEnable 命令
+CMD_ListenerEnable 开始 TCP 监å¬å™¨è¿è¡Œ
+CMD_ListenerEnable_Help 这将å¯åŠ¨åœ¨å½“å‰æœåŠ¡å™¨ä¸Šæ³¨å†Œçš„åœæ­¢ TCP 监å¬å™¨çš„è¿è¡Œã€‚\n您还å¯ä»¥å¾—到一个当å‰ä½¿ç”¨ ListenerList 命令注册的 TCP 监å¬å™¨åˆ—表。\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ListenerEnable_Args ListenerEnable [port]
+CMD_ListenerEnable_[port] 使用一个整数,指定è¦å¯åŠ¨çš„ TCP/IP 监å¬å™¨ç«¯å£å·ã€‚
+CMD_ListenerEnable_PortPrompt å¯åŠ¨ TCP/IP 监å¬å™¨ç«¯å£å·:
+
+
+# ListenerDisable 命令
+CMD_ListenerDisable åœæ­¢ TCP 监å¬å™¨è¿è¡Œ
+CMD_ListenerDisable_Help 这将åœæ­¢åœ¨å½“å‰æœåŠ¡å™¨ä¸Šæ³¨å†Œçš„ TCP 监侦å¬å™¨çš„è¿è¡Œã€‚\n您还å¯ä»¥å¾—到一个当å‰ä½¿ç”¨ ListenerList 命令注册的 TCP 监å¬å™¨åˆ—表。\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ListenerDisable_Args ListenerDisable [port]
+CMD_ListenerDisable_[port] 使用一个整数,指定è¦åœæ­¢çš„ TCP/IP 监å¬å™¨ç«¯å£å·ã€‚
+CMD_ListenerDisable_PortPrompt å¯åŠ¨ TCP/IP 监å¬å™¨ç«¯å£å·:
+
+
+# ServerPasswordSet 命令
+CMD_ServerPasswordSet 设置 VPN Server 管ç†å‘˜å¯†ç 
+CMD_ServerPasswordSet_Help 这将设置 VPN Server 管ç†å‘˜å¯†ç ã€‚您å¯ä»¥æŒ‡å®šå¯†ç ä¸ºä¸€ä¸ªå‚数。如果密ç æ²¡æœ‰æŒ‡å®šï¼Œå°†æ˜¾ç¤ºæ示输入密ç å’Œå¯†ç ç¡®è®¤ã€‚如果指定密ç ä¸ºä¸€ä¸ªå‚数,这个密ç å°†åœ¨å±å¹•ä¸Šæ˜¾ç¤ºçž¬é—´ï¼Œè¿™æž„æˆäº†é£Žé™©ã€‚我们建议尽å¯èƒ½é¿å…指定这个å‚数,使用密ç æ示输入密ç ã€‚\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ServerPasswordSet_Args ServerPasswordSet [password]
+CMD_ServerPasswordSet_[password] 指定一个新的密ç è®¾ç½®ã€‚
+
+
+# ClusterSettingGet 命令
+CMD_ClusterSettingGet 获å–å½“å‰ VPN Server 群集é…ç½®
+CMD_ClusterSettingGet_Help ä½ å¯ä»¥ç”¨å®ƒæ¥èŽ·å–å½“å‰ VPN Server 的群集é…置。\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ClusterSettingGet_Args ClusterSettingGet
+CMD_ClusterSettingGet_Current 当å‰é…ç½®
+CMD_ClusterSettingGet_None (没有设置)
+CMD_ClusterSettingGet_PublicIp 公网 IP 地å€
+CMD_ClusterSettingGet_PublicPorts 公共端å£åˆ—表
+CMD_ClusterSettingGet_Controller 目标控制器
+CMD_ClusterSettingGet_ControllerOnly ä»…é™æŽ§åˆ¶å™¨åŠŸèƒ½
+CMD_ClusterSettingGet_Weight 群集性能标准
+
+
+# ClusterSettingStandalone 命令
+CMD_ClusterSettingStandalone 设置为独立的 VPN Server 类型
+CMD_ClusterSettingStandalone_Help 使用此设置 VPN Server 类型为 [独立æœåŠ¡å™¨]。独立æœåŠ¡å™¨æŒ‡ VPN Server 在当å‰çŠ¶æ€ä¸‹ä¸å±žäºŽä»»ä½•ç¾¤é›†ã€‚当 VPN Server 安装åŽï¼Œé»˜è®¤æƒ…况下为独立的æœåŠ¡å™¨æ¨¡å¼ã€‚除éžä½ æœ‰ç‰¹åˆ«çš„计划æ¥é…置群集,我们建议 VPN Server 以独立模å¼è¿è¡Œã€‚\n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚\n还有,当这个命令执行时,VPN Server 会自动é‡æ–°å¯åŠ¨ã€‚\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚
+CMD_ClusterSettingStandalone_Args ClusterSettingStandalone
+
+
+# ClusterSettingController 命令
+CMD_ClusterSettingController 设置 VPN Server 类型为群集控制器
+CMD_ClusterSettingController_Help 使用此设置 VPN Server 类型为 [群集控制器]。群集控制器是一个群集的所有æˆå‘˜æœåŠ¡å™¨çš„中央电脑,群集环境是由多个 VPN Server æž„æˆã€‚一个群集需è¦ä¸€å°ç”µè„‘æˆä¸ºè¿™ä¸ªè§’色。在åŒä¸€ç¾¤é›†é…置里的其他群集æˆå‘˜æœåŠ¡å™¨ï¼Œæ˜¯é€šè¿‡è¿žæŽ¥åˆ°ç¾¤ä¿¡æŽ§åˆ¶å™¨ä½œä¸ºç¾¤é›†æˆå‘˜å¼€å§‹è¿è¡Œçš„。 \n为了执行这个命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚\n还有,当这个命令执行时刻,VPN Server 会自动é‡æ–°å¯åŠ¨ã€‚\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚
+CMD_ClusterSettingController_Args ClusterSettingController [/WEIGHT:weight] [/ONLY:yes|no]
+CMD_ClusterSettingController_WEIGHT 这设置了这个 VPN Server 的性能标准比值。这是在群集负载平衡中执行的标准值。一般而言,这个值是 100。例如,仅设置一å°æœºå™¨ä¸º 200,而其他æˆå‘˜æœºå™¨ä¸º 100,在负载平衡期间,将调节这å°æœºå™¨æ”¶åˆ°å…¶ä»–æˆå‘˜ä¸¤å€çš„连接数。指定 1 或更高的值。如果此å‚数未指定,将使用 100。
+CMD_ClusterSettingController_ONLY 通过在这里指定 "yes",VPN Server 在群集里仅作为一个控制器è¿è¡Œï¼Œå¹¶æ€»æ˜¯åˆ†é…一般 VPN Client 连接给到自身以外的æˆå‘˜ã€‚此功能用于高负载的环境。如果此å‚数未指定,"no" 将被使用。
+
+
+# ClusterSettingMember 命令
+CMD_ClusterSettingMember VPN Server 类型设置为群集æˆå‘˜
+CMD_ClusterSettingMember_Help 使用此设置 VPN Server 类型,[群集æˆå‘˜æœåŠ¡å™¨]。一个群集æˆå‘˜æœåŠ¡å™¨æ˜¯æˆå‘˜çš„计算机属于群集é…置由多个 VPN Server 与å¦ä¸€ä¸ªä¸­å¿ƒçŽ°æœ‰ç¾¤é›†æŽ§åˆ¶å™¨ã€‚集群æˆå‘˜å¯ä»¥æ ¹æ®éœ€è¦ä»»æ„添加到群集。\n在设置为群集æˆå‘˜æœåŠ¡å™¨çš„ VPN Server,群集控制器管ç†å‘˜è¦ä¸ºæŽ§åˆ¶å™¨çš„ IP 地å€å’Œç«¯å£å·ä½¿ç”¨ï¼Œéœ€è¦çŸ¥é“公共 IP 地å€å’Œå…¬å…±ç«¯å£å· (å¿…è¦æ—¶æœ¬ VPN Server) 和密ç ã€‚\nè¦æ‰§è¡Œè¿™ä¸ªå‘½ä»¤ï¼Œæ‚¨å¿…须拥有 VPN Server 管ç†å‘˜æƒé™ã€‚\nå¦å¤–,在执行此命令,VPN Server 会自动é‡æ–°å¯åŠ¨ã€‚\n此命令ä¸èƒ½è¿è¡Œçš„ VPN Bridge。
+CMD_ClusterSettingMember_Args ClusterSettingMember [server:port] [/IP:ip] [/PORTS:ports] [/PASSWORD:password] [/WEIGHT:weight]
+CMD_ClusterSettingMember_[server:port] 按照 [主机å:端å£å·] çš„å½¢å¼ï¼Œè®¾å®šç›®çš„地群集控制器的主机å,IP 地å€ï¼Œç«¯å£å·ç­‰ã€‚
+CMD_ClusterSettingMember_IP 指定该æœåŠ¡å™¨çš„公用 IP 地å€ã€‚如果ä¸æŒ‡å®šå…¬ç”¨ IP 地å€ï¼Œè¯·è®¾å®š "/IP:none"。当 IP 地å€æ²¡æœ‰æŒ‡å®šï¼Œå°†è‡ªåŠ¨ä½¿ç”¨çš„网络接å£çš„ IP 地å€è¿žæŽ¥åˆ°ç¾¤é›†æŽ§åˆ¶å™¨ã€‚
+CMD_ClusterSettingMember_PORTS 指定æœåŠ¡å™¨çš„公开端å£ä¸€è§ˆã€‚该清å•å¿…须至少有一个公共端å£å·è®¾ç½®ï¼Œä¹Ÿå¯ä»¥è®¾ç½®å¤šä¸ªå…¬å…±ç«¯å£å·ã€‚当指定多个端å£å·ï¼Œä¾‹å¦‚ "/PORTS:443,992,8888" 中间用逗å·åˆ†å¼€ã€‚
+CMD_ClusterSettingMember_PASSWORD 指定连接到目标控制器的密ç ã€‚它与目标控制器管ç†å¯†ç æ˜¯ç›¸åŒçš„。
+CMD_ClusterSettingMember_WEIGHT 这设定了一个表现这个 VPN Server 的标准比率值。这是负载平衡集群中执行的标准值。一般而言,这个值是 100。例如,åªæœ‰ä¸€å°æœºå™¨æ˜¯ 200,而其他æˆå‘˜æ˜¯ 100 个å•ä½ï¼Œå°†è§„范这å°æœºå™¨å¾—到åƒå…¶ä»–许多æˆå‘˜æœŸé—´ä¸¤æ¬¡è¿žæŽ¥è´Ÿè½½å¹³è¡¡ã€‚指定 1 或更高的值。如果此å‚数未指定,将使用 100。
+CMD_ClusterSettingMember_Prompt_IP_1 指定一个公用 IP 地å€ã€‚\n如果你ä¸æŒ‡å®šï¼Œè¯·æŒ‰å›žè½¦é”®ï¼Œä¸éœ€è¦è¾“入任何东西。
+CMD_ClusterSettingMember_Prompt_IP_2 公共 IP 地å€:
+CMD_ClusterSettingMember_Prompt_PORT_1 请指定一个公共端å£å·çš„列表。\n有 2 个或以上指定端å£å·ï¼Œå¦‚例用逗å·åˆ†éš”: "443,992,8888"。
+CMD_ClusterSettingMember_Prompt_PORT_2 公共端å£å·:
+CMD_ClusterSettingMember_Prompt_HOST_1 目标控制器的主机å和端å£å·:
+
+
+# ClusterMemberList 命令
+CMD_ClusterMemberList 获得群集æˆå‘˜åå•
+CMD_ClusterMemberList_Help 使用此命令时,VPN Server 作为群集控制器æ“作获得对相åŒçš„群集群集æˆå‘˜æœåŠ¡å™¨ï¼ŒåŒ…括群集控制器本身的列表。\n若需æ¯ä¸ªæˆå‘˜ï¼Œä¸‹é¢çš„ä¿¡æ¯ä¹Ÿè¢«åˆ—入。 [类型],[连线开始],[主机å],[点],[会期å·ç ],[TCP 连接数],[虚拟的作业站数目],[使用客户端连接许å¯è¯],[使用大桥连接许å¯è¯]。\n此命令ä¸èƒ½è¿è¡Œåœ¨ VPN Bridge。
+CMD_ClusterMemberList_Args ClusterMemberList
+
+
+# ClusterMemberInfoGet 命令
+CMD_ClusterMemberInfoGet 会员信æ¯çš„获å–
+CMD_ClusterMemberInfoGet_Help 当 VPN Server 作为群集控制器æ“作,您就å¯ä»¥é€šè¿‡æŒ‡å®šçš„集的æˆå‘˜æœåŠ¡å™¨ ID 获得在群集æˆå‘˜çš„ä¿¡æ¯ã€‚\n您å¯ä»¥å¾—到有关指定群集æˆå‘˜æœåŠ¡å™¨ä¸Šçš„以下信æ¯: ]æœåŠ¡å™¨ç±»åž‹]ã€],[已建立连接的时间],[IP 地å€],[主机å],[点],[公共端å£åˆ—表],[æ“作中的虚拟 HUB],[第一虚拟 HUB],[会è¯æ•°],[TCP 连接数]。\n此命令ä¸èƒ½è¿è¡Œåœ¨ VPN Bridge。
+CMD_ClusterMemberInfoGet_Args ClusterMemberInfoGet [id]
+CMD_ClusterMemberInfoGet_[id] 指定想获信æ¯çš„å–群集æˆå‘˜çš„ ID。ID 地å€å¯ä»¥åœ¨ ClusterMemberList 中获得。
+CMD_ClusterMemberInfoGet_PROMPT_ID 拟获å–ä¿¡æ¯çš„群集æˆå‘˜ ID:
+
+
+# ClusterMemberCertGet 命令
+CMD_ClusterMemberCertGet 获得群集æˆå‘˜è¯ä¹¦
+CMD_ClusterMemberCertGet_Help 当 VPN Server 作为群集控制器æ“作,您就å¯ä»¥é€šè¿‡æŒ‡å®šçš„群集这些æˆå‘˜æœåŠ¡å™¨çš„ ID 的群集æˆå‘˜æœåŠ¡å™¨èŽ·å–公共 X.509 è¯ä¹¦ã€‚您å¯ä»¥ä¿å­˜ä¸º X.509 æ ¼å¼æ–‡ä»¶ã€‚\n此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚
+CMD_ClusterMemberCertGet_Args ClusterMemberCertGet [id] [/SAVECERT:cert]
+CMD_ClusterMemberCertGet_[id] 指定获å–è¯ä¹¦æ‰€éœ€çš„群集的æˆå‘˜çš„ ID。此 ID å¯ä»¥ç¾¤é›†æˆå‘˜ä½¿ç”¨ ClusterMemberList 中获得。
+CMD_ClusterMemberCertGet_SAVECERT 指定路径以ä¿å­˜æ‚¨èŽ·å¾—çš„è¯ä¹¦ã€‚è¯ä¹¦è¢«ä¿å­˜ä¸º X.509 æ ¼å¼ã€‚
+CMD_ClusterMemberCertGet_PROMPT_ID 获å–è¯ä¹¦çš„集群会员 ID:
+
+# ClusterConnectionStatusGet 命令
+CMD_ClusterConnectionStatusGet 获得群集控制器的连接状æ€çš„ä¿¡æ¯
+CMD_ClusterConnectionStatusGet_Help 使用此命令时,VPN Server 作为群集控制器æ“作æ¥èŽ·å¾—连接状æ€çš„群集控制器。\n您å¯ä»¥å¾—到以下信æ¯: [控制器 IP 地å€],[端å£å·],[连接状æ€],[连线开始时间],[第一个连接æˆç«‹æ—¶é—´],[当å‰è¿žæŽ¥æˆç«‹æ—¶é—´],[的连接å°è¯•æ¬¡æ•°],[æˆåŠŸè¿žæŽ¥æ¬¡æ•°],[连接失败次数]。\n此命令ä¸èƒ½è¿è¡Œåœ¨ VPN Bridge。
+CMD_ClusterConnectionStatusGet_Args ClusterConnectionStatusGet
+
+
+# Debug 命令
+CMD_Debug 执行调试命令
+CMD_Debug_Help 在è¿è¡Œçš„ VPN Server / Bridge 进程上è¿è¡Œè°ƒè¯•å‘½ä»¤ã€‚\n此命令在支æŒäººå‘˜è¯·æ±‚这么åšæ—¶æ‰§è¡Œã€‚\n错误使用此命令,很å¯èƒ½é€ æˆ VPN Server / Bridge è¿è¡Œå´©æºƒã€‚
+CMD_Debug_Args Debug [id] [/ARG:arg]
+CMD_Debug_[id] 指定一个调试命令åºå·ã€‚
+CMD_Debug_ARG 指定一个字符串传递给调试命令。如果该字符串包å«ç©ºæ ¼ï¼Œå¹¶ä¸”整个命令都包å«åœ¨" "内。
+CMD_Debug_Msg1 å‘é€è°ƒè¯•å‘½ä»¤...
+CMD_Debug_Msg2 调试命令已执行。\n结果: \"%S\"
+
+# Crash 命令
+CMD_Crash 出现一个错误的 VPN Server / Bridge 强行终止该进程。
+CMD_Crash_Help 此命令会在 VPN Server / Bridge 的进程中产生一个严é‡çš„错误(内存访问冲çª),从而会导致进程崩溃。于是,在æœåŠ¡æ¨¡å¼ä¸‹çš„ VPN Server / Bridge 将会终止并é‡å¯ã€‚如果 VPN Server 在用户模å¼ä¸‹è¿è¡Œï¼Œè¿›ç¨‹å°†ä¸ä¼šè‡ªåŠ¨é‡å¯ã€‚\n本命令适用于:当 VPN Server / Bridge 处于一个ä¸å¯æ¢å¤çš„错误或者进程无é™å¾ªçŽ¯æ—¶ã€‚此命令将断开所有 VPN Server / Bridge 上的 VPN 会è¯ã€‚所有在 VPN Server / Bridge 内存中未ä¿å­˜çš„设置将会丢失。\n在è¿è¡Œæ­¤å‘½ä»¤å‰ï¼Œè¿è¡Œ"Flush" 命令æ¥æŠŠä¸ç¨³å®šçš„æ•°æ®ä¿å­˜åœ¨é…置文件中。\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server / Bridge 的管ç†å‘˜æƒé™ã€‚
+CMD_Crash_Args Crash [yes]
+CMD_Crash_[yes] 确认请输入 "yes"
+CMD_Crash_Msg å‘é€å´©æºƒå‘½ä»¤ç»™ VPN Server。VPN Server 将会立å³å´©æºƒï¼Œæ‰€ä»¥æ‚¨ä¸å¯èƒ½æ”¶åˆ°æœ¬å‘½ä»¤çš„结果值。此刻以åŽï¼Œvpncmd 将会自动断开 VPN Server 的连接。
+CMD_Crash_Confirm 您确定è¦ä½¿ VPN Server 崩溃?\n如果确定请键入 "yes":
+CMD_Crash_Aborted 崩溃命令中止。
+
+
+# Flush 命令
+CMD_Flush ä¿å­˜ VPN Server / Bridge 全部ä¸ç¨³å®šæ•°æ®åˆ°é…置文件。
+CMD_Flush_Help 通常,ä¸ç¨³å®šè®¾ç½®æ•°æ®ä¼šä¿å­˜åœ¨ VPN Server / Bridge 的内存中。它定期以 vpn_server.config 或者 vpn_bridge.config 刷新硬盘。默认周期是 300 秒(5 分钟)。(周期长度å¯ä»¥åœ¨é…置文件中,通过修改 AutoSaveConfigSpan 进行改å˜ã€‚)æ•°æ®ä¼šåœ¨æ­£å¸¸å…³é—­ VPN Server / Bridge æ—¶ä¿å­˜ã€‚\n执行 Flush 命令使 VPN Server / Bridge ç«‹å³ä¿å­˜è®¾ç½®è‡³æ–‡ä»¶ã€‚此设置数æ®å°†è¢«ä¿å­˜åœ¨æœåŠ¡å™¨è®¡ç®—机的ç£ç›˜é©±åŠ¨ä¸­ã€‚在您没有足够时间正常关闭æœåŠ¡å™¨è¿›ç¨‹çš„情况下,使用 Flush 命令。\n执行此命令,您必须有 VPN Server 管ç†å‘˜æƒé™ã€‚\n执行此命令,您必须有 VPN Server / Bridge 的管ç†å‘˜æƒé™ã€‚
+CMD_Flush_Args Flush
+CMD_Flush_Msg1 从内存到ç£ç›˜å†™å…¥ä¸ç¨³å®šæ•°æ®...\n
+CMD_Flush_Msg2 ä¿å­˜æˆåŠŸã€‚文件大å°æ˜¯ %S 字节。\n
+
+
+# ServerCertGet 命令
+CMD_ServerCertGet 获得 VPN Server çš„ SSL è¯ä¹¦
+CMD_ServerCertGet_Help VPN Server,å–得连接客户机所需的 SSL è¯ä¹¦ã€‚è¯ä¹¦å¯ä»¥ä¿å­˜ä¸º X.509 çš„æ ¼å¼ã€‚
+CMD_ServerCertGet_Args ServerCertGet [cert]
+CMD_ServerCertGet_[cert] 获得的è¯ä¹¦æŒ‡å®šæ–‡ä»¶ä¿å­˜è·¯å¾„,以 X.509 çš„å½¢å¼ä¿å­˜ã€‚
+
+
+# ServerKeyGet 命令
+CMD_ServerKeyGet èŽ·å– VPN Server SSL è¯ä¹¦çš„密钥
+CMD_ServerKeyGet_Help VPN Server,为已连接客户æ供获得è¯ä¹¦çš„密钥。密钥å¯ä»¥å­˜å‚¨ä¸º Base 64 çš„ç¼–ç æ–‡ä»¶ã€‚ \n为了è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜çš„æƒé™ã€‚
+CMD_ServerKeyGet_Args ServerKeyGet [key]
+CMD_ServerKeyGet_[key] 指定文件的路径åæ¥å­˜å‚¨å·²èŽ·å¾—的密钥。将密钥存储为 Base 64 ç¼–ç ã€‚
+
+
+# ServerCertSet 命令
+CMD_ServerCertSet VPN Server çš„ SSL è¯ä¹¦å’Œå¯†é’¥çš„设置
+CMD_ServerCertSet_Help 设置已连接 VPN Server 的客户端所需的 SSL è¯ä¹¦ï¼Œä»¥åŠè·Ÿè¯ä¹¦ç›¸å¯¹åº”的密钥。è¯ä¹¦ä¸º X.509 æ ¼å¼ï¼Œå¯†é’¥ä¸º Base 64 ç¼–ç æ ¼å¼ã€‚\n为了è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦æœ‰ VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_ServerCertSet_Args ServerCertSet [/LOADCERT:cert] [/LOADKEY:key]
+CMD_ServerCertSet_LOADCERT 指定è¦ä½¿ç”¨çš„ X.509 æ ¼å¼çš„è¯ä¹¦æ–‡ä»¶ã€‚
+CMD_ServerCertSet_LOADKEY 指定格å¼ä¸º Base 64 ç¼–ç å¹¶ä¸”与è¯ä¹¦å¯¹åº”的密钥文件。
+
+
+# ServerCipherGet 命令
+CMD_ServerCipherGet èŽ·å– VPN 通信中使用的加密程åº
+CMD_ServerCipherGet_Help 您å¯ä»¥èŽ·å– VPN Server 和客户端之间进行通信时使用的 SSL 加密,电å­ç­¾å等,以åŠåœ¨ VPN Server 上的程åºåˆ—表。
+CMD_ServerCipherGet_Args ServerCipherGet
+CMD_ServerCipherGet_SERVER VPN Server 正在使用的加密程åº:
+CMD_ServerCipherGet_CIPHERS å¯ä»¥ä½¿ç”¨çš„加密程åºä¸€è§ˆè¡¨:
+
+# ServerCipherSet 命令
+CMD_ServerCipherSet 设置 VPN 通讯中使用的加密程åºï¼Œ
+CMD_ServerCipherSet_Help 您å¯ä»¥è®¾ç½® VPN Server 和客户端在通讯中应用的 SSL 加密连接,电å­ç­¾å等应用程åºã€‚\n如果您指定程åºçš„å称,以åŽå’Œ VPN Server 连接的 VPN Client,VPN Bridge 之间的将应用指定程åºï¼Œæ•°æ®å°†è¢«åŠ å¯†ã€‚\nè¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜çš„æƒé™ã€‚
+CMD_ServerCipherSet_Args ServerCipherSet [name]
+CMD_ServerCipherSet_[name] 指定设置加密和数字签å的程åºã€‚å¯ä»¥ä½¿ç”¨çš„程åºä¸€è§ˆï¼Œå¯ä»¥ä»Ž ServerCipherGet 指令中获å–。
+CMD_ServerCipherSet_PROMPT_NAME 指定的加密程åºçš„å称:
+
+
+# KeepEnable 命令
+CMD_KeepEnable å¯åŠ¨ Internet ä¿æŒè¿žæŽ¥åŠŸèƒ½
+CMD_KeepEnable_Help å¯åŠ¨ [互è”网ä¿æŒè¿žæŽ¥åŠŸèƒ½]。å¯åŠ¨æ­¤åŠŸèƒ½åŽï¼Œå¦‚果一段时间没有通信数æ®ï¼Œå¯¼è‡´è¿žæŽ¥å°†è¢«æ–­å¼€æ—¶ï¼Œä¼šè‡ªåŠ¨å‘é€æ•°æ®åŒ…到任何æœåŠ¡å™¨ï¼Œäº’è”网æœåŠ¡å™¨ä¸€å®šçš„间隔,从而å¯ä»¥ä¿æŒè¿žæŽ¥ã€‚\n目标主机å等,å¯ä»¥é€šè¿‡ KeepSet 指令æ¥è®¾ç½®ã€‚\nVPN Server 或 VPN Bridge è¿è¡Œæ­¤å‘½ä»¤æ—¶ï¼Œæ‚¨å¿…须具有管ç†å‘˜çš„æƒé™ã€‚
+CMD_KeepEnable_Args KeepEnable
+
+
+# KeepDisable 命令
+CMD_KeepDisable ç¦ç”¨ä¿æŒäº’è”网连接功能
+CMD_KeepDisable_Help 解除 [ä¿æŒäº’è”网连接功能]。\nVPN Server 或 VPN Bridge è¿è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有管ç†å‘˜æƒé™ã€‚
+CMD_KeepDisable_Args KeepDisable
+
+
+# KeepSet 命令
+CMD_KeepSet 设置 Internet ä¿æŒè¿žæŽ¥åŠŸèƒ½
+CMD_KeepSet_Help 设置 [ä¿æŒäº’è”网连接功能] 的目标主机å。 如果一段时间没有任何通信数æ®ï¼Œè¿žæŽ¥å°†è¢«æ–­å¼€æ—¶ï¼Œä½¿ç”¨ [ä¿æŒäº’è”网连接功能 ] å¯ä»¥ï¼Œè®¾å®šæ—¶é—´å‘ Internet 上的任何æœåŠ¡å™¨å‘é€æ•°æ®åŒ…,从而å¯ä»¥ä¿æŒæ‚¨çš„ Internet 连接。\n在此功能中,å¯ä»¥è®¾ç½®ç›®æ ‡ [主机å],[端å£å·],[æ•°æ®åŒ…å‘é€æ—¶é—´é—´éš”]ï¼Œä»¥åŠ [åè®®]。\nå‘é€çš„æ•°æ®åŒ…为éšæœºå†…容,ä¸ä¼šè®²è®¡ç®—机和个人的识别信æ¯å‘é€ã€‚\nä¿æŒ Internet 连接功能,å¯ä»¥é€šè¿‡ KeepEnable 命令,或使用命令 KeepDisable,实现å¯ç”¨ / ç¦ç”¨ã€‚ä¸å¯ä»¥ç”¨ KeepSet æ¥æ”¹å˜å¯ç”¨ / ç¦ç”¨çš„状æ€ã€‚ \nVPN Server 或 VPN Bridge è¿è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有管ç†å‘˜æƒé™ã€‚
+CMD_KeepSet_Args KeepSet [/HOST:host:port] [/PROTOCOL:tcp|udp] [/INTERVAL:interval]
+CMD_KeepSet_HOST 用 [主机:端å£] çš„æ ¼å¼ï¼Œæ¥è®¾å®šç›®æ ‡ä¸»æœºå或 IP 地å€å’Œç«¯å£å·ã€‚
+CMD_KeepSet_PROTOCOL 设定 tcp 或 udp。
+CMD_KeepSet_INTERVAL 以秒为å•ä½è®¾å®šå‘é€æ•°æ®åŒ…之间的间隔时间。
+CMD_KeepSet_PROMPT_HOST 设定目标主机å或 IP 地å€å’Œç«¯å£å·:
+CMD_KeepSet_PROMPT_PROTOCOL tcp 或 udp:
+CMD_KeepSet_PROMPT_INTERVAL å‘é€æ•°æ®åŒ…时间间隔 (秒):
+CMD_KeepSet_EVAL_TCP_UDP 设定 "tcp" 或 "udp"。
+
+# KeepGet 命令
+CMD_KeepGet 获å–ä¿æŒäº’è”网连接的功能
+CMD_KeepGet_Help èŽ·å– [ä¿æŒäº’è”网连接功能] 的当å‰è®¾ç½®ã€‚å¯ä»¥å¾—到 [主机å],[端å£],[æ•°æ®åŒ…å‘é€æ—¶é—´é—´éš”],和 [åè®®]ï¼Œè¿˜åŒ…æ‹¬å½“å‰ [ä¿æŒäº’è”网连接功能] 是å¦å¯ç”¨çš„当å‰çŠ¶æ€ã€‚
+CMD_KeepGet_Args KeepGet
+CMD_KeepGet_COLUMN_1 主机å
+CMD_KeepGet_COLUMN_2 端å£å·
+CMD_KeepGet_COLUMN_3 æ•°æ®åŒ…å‘é€æ—¶é—´é—´éš” (秒)
+CMD_KeepGet_COLUMN_4 åè®®
+CMD_KeepGet_COLUMN_5 当å‰çŠ¶æ€
+
+
+# SyslogEnable 命令
+CMD_SyslogEnable 设置å‘é€ç³»ç»Ÿæ—¥å¿—功能
+CMD_SyslogEnable_Help 使用 syslog å‘é€ç³»ç»Ÿæ—¥å¿—的使用方法和æœåŠ¡å™¨çš„设置。
+CMD_SyslogEnable_Args SyslogEnable [1|2|3] [/HOST:host:port]
+CMD_SyslogEnable_[1|2|3] 使用 syslog 功能 1 - 3 æ¥è¿›è¡Œè®¾ç½®ã€‚\n1: å‘é€ syslog æœåŠ¡å™¨æ—¥å¿—。\n2: å‘é€æœåŠ¡å™¨å’Œè™šæ‹Ÿ HUB 安全系统日志。\n3: æœåŠ¡å™¨ï¼Œè™šæ‹Ÿ HUB 安全和数æ®åŒ…å‘é€ç³»ç»Ÿæ—¥å¿—记录枢纽。
+CMD_SyslogEnable_HOST 按照 [主机:端å£] çš„å½¢å¼ï¼Œè®¾å®šç³»ç»Ÿæ—¥å¿—æœåŠ¡å™¨ä¸»æœºå或 IP 地å€å’Œç«¯å£å·ã€‚如果çœç•¥ç«¯å£å·ä½¿ç”¨ 514。
+CMD_SyslogEnable_MINMAX 设置 syslog å‘é€åŠŸèƒ½ 1 - 3。
+CMD_SyslogEnable_Prompt_123 系统日志传输功能 (1 - 3):
+CMD_SyslogEnable_Prompt_HOST 指定å‘é€æ—¥å¿—çš„æœåŠ¡å™¨:
+
+
+# SyslogDisable 命令
+CMD_SyslogDisable ç¦ç”¨å‘é€ç³»ç»Ÿæ—¥å¿—的功能
+CMD_SyslogDisable_Help 解除系统日志的传é€åŠŸèƒ½ã€‚
+CMD_SyslogDisable_Args SyslogDisable
+
+
+# SyslogGet 命令
+CMD_SyslogGet å–å¾—å‘é€ç³»ç»Ÿæ—¥å¿—的功能
+CMD_SyslogGet_Help èŽ·å– syslog å‘é€åŠŸèƒ½çš„当å‰è®¾ç½®ã€‚您å¯ä»¥è®¾ç½®ç³»ç»Ÿæ—¥å¿—功能的使用方法,å¯ä»¥èŽ·å– syslog æœåŠ¡å™¨çš„主机å和端å£å·ã€‚
+CMD_SyslogGet_Args SyslogGet
+CMD_SyslogGet_COLUMN_1 设置系统日志å‘é€åŠŸèƒ½
+CMD_SyslogGet_COLUMN_2 å‘é€ç³»ç»Ÿæ—¥å¿—æœåŠ¡å™¨ä¸»æœºå
+CMD_SyslogGet_COLUMN_3 syslog æœåŠ¡å™¨ç«¯å£å·
+
+
+# ConnectionList 命令
+CMD_ConnectionList 获å–与 VPN Server 相连的 TCP 连接一览
+CMD_ConnectionList_Help 现在,先获å–与 VPN Server 连接的 TCP/IP 一览表。但是,VPN 会è¯ä½œä¸º TCP/IP 连接ä¸æ˜¾ç¤ºã€‚VPN 会è¯å»ºç«‹çš„ TCP/IP 连接一览表,何以è¿ç”¨ SessionList 命令获得。\nå¯ä»¥èŽ·å– [连接å称], [原始连接], [连接时间] å’Œ [类型]。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_ConnectionList_Args ConnectionList
+
+
+# ConnectionList 命令
+CMD_ConnectionGet 获å–连接到 VPN Server çš„ TCP ä¿¡æ¯ä¸€è§ˆè¡¨
+CMD_ConnectionGet_Help 获å–与 VPN Server 连接的 TCP/IP 连接的详细信æ¯ã€‚\nå¯ä»¥èŽ·å¾— [连接å],[连接ç§ç±»],[连接主机å],[连接主机 IP],[è”æœºä¸»æœºç«¯å£ TCP],[连接时间],[æœåŠ¡å™¨å“牌],[æœåŠ¡å™¨ç‰ˆæœ¬],[æœåŠ¡å™¨é“­ç‰Œå·],[客户机å“牌],[客户机版本],[客户机铭牌å·] 等信æ¯ã€‚ \nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_ConnectionGet_Args ConnectionGet [name]
+CMD_ConnectionGet_[name] 指定希望获å–ä¿¡æ¯çš„连接å称。所有连接的一览表,å¯ä»¥é€šè¿‡ ConnectionList 命令获得。
+CMD_ConnectionGet_PROMPT_NAME 用以获å–ä¿¡æ¯çš„连接å称:
+
+# ConnectionDisconnect 命令
+CMD_ConnectionDisconnect 断开 VPN Server 和 TCP 的连接
+CMD_ConnectionDisconnect_Help 强制切断 VPN Server 和指定的 TCP/IP 的连接。\nè¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_ConnectionDisconnect_Args ConnectionDisconnect [name]
+CMD_ConnectionDisconnect_[name] 选定希望切断的连接。连接的å称å¯ä»¥ä»Ž ConnectionList 命令中获得。
+CMD_ConnectionDisconnect_PROMPT_NAME 断开连接的å称:
+
+
+# BridgeDeviceList 命令
+CMD_BridgeDeviceList 获å–å¯ä»¥åœ¨å½“地的网桥上使用的 LAN å¡ä¸€è§ˆ
+CMD_BridgeDeviceList_Help 使用当地网桥连接,获å–目标桥中å¯ä»¥ä½¿ç”¨çš„设备 (LAN å¡) 列表。\n在此显示的设备å字,BridgeCreate 命令都å¯ä»¥ä½¿ç”¨ã€‚\n为了è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_BridgeDeviceList_Args BridgeDeviceList
+
+
+# BridgeList 命令
+CMD_BridgeList 获得当地网桥连接列表
+CMD_BridgeList_Help 获å–当地定义的网桥连接列表。\nå¯ä»¥èŽ·å–当地网桥连接的虚拟 HUB å称,目标太网桥连接器件 (LAN å¡) çš„å称,或å¯ä»¥èŽ·å–设备的å称和工作状æ€ã€‚
+CMD_BridgeList_Args BridgeList
+
+
+# BridgeCreate 命令
+CMD_BridgeCreate 创建本地的网桥连接
+CMD_BridgeCreate_Help 在 VPN Server 上创建新的本地网桥连接的。\n当您使用一个本地的网桥,这个虚拟 HUB 和物ç†ä»¥å¤ªç½‘设备 (LAN å¡åœ¨ä¸¤å±‚) 之间å¯ä»¥åˆ›å»ºç½‘桥连接。\n在系统中创建 tap 设备 (虚拟网络接å£),å¯ä»¥ä¸Žè™šæ‹Ÿ HUB 建立连接 (tap è®¾å¤‡ä»…æ”¯æŒ Linux)。\n目的地以太网桥设备 (LAN å¡) å¯ä»¥è¿žæŽ¥åˆ°æ‚¨çš„任何è¿è¡Œçš„ LAN å¡ï¼Œä½†æ˜¯é«˜è´Ÿè·çŽ¯å¢ƒçš„网桥,建议您准备专用的 LAN å¡ã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_BridgeCreate_Args BridgeCreate [hubname] [/DEVICE:device_name] [/TAP:yes|no]
+CMD_BridgeCreate_[hubname] 选定虚拟 HUB 的网桥。虚拟 HUB 列表,å¯ä»¥é€šè¿‡ HubList 命令获得。但是,没有必è¦ä¸€å®šè¦é€‰å®šç›®å‰æ­£åœ¨è¿è¡Œçš„虚拟 HUB,å³ä½¿é€‰å®šç›®å‰æ²¡æœ‰å·¥ä½œï¼Œæˆ–ä¸å­˜åœ¨çš„虚拟å称的 HUB,当它真正工作时,它与虚拟本地网桥就会建立连接。
+CMD_BridgeCreate_DEVICE 设定目标以太网桥设备 (LAN å¡) çš„å称,或 tap 设备的å称。以太网设备åå•ï¼Œå¯ä»¥é€šè¿‡è¿è¡Œ BridgeDeviceList 命令得到。
+CMD_BridgeCreate_TAP 网桥连接局域网,ä¸ä½¿ç”¨ LAN å¡ï¼Œè€Œæ˜¯ä½¿ç”¨ tap 设备时,选定 yes,如果您使用的设备指定 (åªæ”¯æŒ Linux)。如果çœç•¥ï¼Œé»˜è®¤ä¸º no。
+CMD_BridgeCreate_PROMPT_HUBNAME 网桥虚拟 HUB å称:
+CMD_BridgeCreate_PROMPT_DEVICE 目标网桥的设备å称:
+CMD_BridgeCreate_PROMPT_TAP 你想使用 tap è®¾å¤‡å— (yes/no):
+
+
+# BridgeDelete 命令
+CMD_BridgeDelete 删除本地网桥连接
+CMD_BridgeDelete_Help 删除现有的当地网桥连接。当地网桥æ¢è¿žæŽ¥çš„列表,å¯ä»¥é€šè¿‡ BridgeDeviceList 命令得到。\nè¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦æœåŠ¡å™¨ç®¡ç†å‘˜æƒé™ã€‚
+CMD_BridgeDelete_Args BridgeDelete [hubname] [/DEVICE:device_name]
+CMD_BridgeDelete_[hubname] 选定被删除的当地网桥的虚拟 HUB。
+CMD_BridgeDelete_DEVICE 选定被删除的当地的网桥的设备å (LAN å¡çš„å称或 tap 设备的å称)。
+CMD_BridgeDelete_PROMPT_HUBNAME 删除虚拟网桥 HUB çš„å称:
+CMD_BridgeDelete_PROMPT_DEVICE 删除网桥的设备å:
+
+
+# Caps 命令
+CMD_Caps 获得æœåŠ¡å™¨çš„功能性能一览表
+CMD_Caps_Help å–得现在正在连接使用的 VPN Server 的功能和性能的清å•ã€‚\nVPN Server 的功能和性能å–决于æœåŠ¡å™¨çš„版本。指令清å•ä¸­çš„指令也å¯èƒ½å› ä¸ºå¯¹æ–¹çš„æœåŠ¡å™¨çš„功能,而无法工作。因此此命令需调查目标æœåŠ¡å™¨çš„功能。\n如果 VPN Server 的版本比命令行管ç†å·¥å…·çš„版本新,存在ä¸æŽŒæ¡çš„指令时,其内部的字符串 (å˜é‡å),但å¯èƒ½åŽŸåŽŸæœ¬æœ¬çš„表示出æ¥ã€‚
+CMD_Caps_Args Caps
+
+
+# Reboot 命令
+CMD_Reboot VPN Server æœåŠ¡é‡æ–°å¯åŠ¨
+CMD_Reboot_Help VPN Server é‡æ–°å¯åŠ¨è¯¥æœåŠ¡ã€‚\nVPN Server é‡æ–°å¯åŠ¨æœåŠ¡ï¼Œç›®å‰è¿žæŽ¥çš„会è¯å’Œ TCP 连接都将被切断,直é“建立新的连接。\n此命令,VPN Server,åªæ˜¯é‡æ–°å¯åŠ¨æœåŠ¡ç¨‹åºï¼Œè€Œä¸æ˜¯é‡æ–°å¯åŠ¨è®¡ç®—机。这ç§ç®¡ç†çš„连接也会断开,如果需è¦è¯·é‡æ–°å»ºç«‹è¿žæŽ¥ã€‚\n此外,/RESETCONFIG:yes 指定å‚数,并对 VPN Server 的系统内容 (.config) 进行åˆå§‹åŒ–。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server需è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_Reboot_Args Reboot [/RESETCONFIG:yes|no]
+CMD_Reboot_RESETCONFIG 选定 yes,对当å‰çš„ VPN Server 的系统内容 (.config) åˆå§‹åŒ–。请谨慎设置此å‚数。
+
+
+# ConfigGet 命令
+CMD_ConfigGet èŽ·å– VPN Server 当å‰ç³»ç»Ÿé…ç½®
+CMD_ConfigGet_Help èŽ·å– VPN Server å½“å‰ (.config 文件) 系统结构化文本ä¿å­˜çš„文本文件,你å¯ä»¥æ£€ç´¢åˆ° VPN Server 执行这个指令的瞬间状æ€ã€‚\n系统内容的文件,如果ä¸æŒ‡å®šå‚数,会在å±å¹•ä¸Šç›´æŽ¥æ˜¾ç¤ºã€‚如果您指定å‚æ•°ä¿å­˜ï¼Œä¼šä¿å­˜ä¸ºä¸€ä¸ªæŒ‡å®šçš„文件å。\né…置文件å¯ä»¥ä½¿ç”¨æ™®é€šçš„文本编辑器编辑。编辑好的文件è¦å†™å…¥ VPN Server,需执行 ConfigSet 命令。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚
+CMD_ConfigGet_Args ConfigGet [path]
+CMD_ConfigGet_[path] 如果你想ä¿å­˜é…置文件,请指定文件å。如果没有指定,é…置的内容将以画é¢å½¢å¼æ˜¾ç¤ºåœ¨å±å¹•ä¸Šã€‚如果é…置是多字字符的,请转å˜æˆ Unicode (UTF-8) ç¼–ç å­˜å‚¨ã€‚
+CMD_ConfigGet_FILENAME Config å称: "%S", 大å°: %u
+CMD_ConfigGet_FILE_SAVE_FAILED 无法创建指定的文件。
+
+
+# ConfigSet 命令
+CMD_ConfigSet å¾€ VPN Server 上写入系统é…置内容
+CMD_ConfigSet_Help å¾€ VPN Server 上写入系统é…置内容。这样,您选定的系统é…置内容会适用于 VPN Server,VPN Server 程åºä¼šè‡ªåŠ¨é‡å¯ï¼Œæ–°çš„系统é…åŒé…置开始工作。\n对系统管ç†è€…æ¥è¯´ï¼Œè¦è®°å½•æ‰€æœ‰çš„系统é…置的文件是比较困难的。因此建议使用 ConfigGet 命令,先获å–当å‰çš„ VPN Server 的系统é…置内容ä¿å­˜æˆæ–‡ä»¶ï¼Œå†å°†æ­¤æ–‡ä»¶åŠ ä»¥ç¼–辑,然åŽç”¨ ConfigSet 命令写入 VPN Server。\n这个æ“作,需è¦å¯¹ VPN Server 充分的了解,如果写入了ä¸æ­£ç¡®çš„系统é…置信æ¯ï¼Œç³»ç»Ÿå°†å‘生错误,甚至å¯èƒ½ä¸¢å¤±çŽ°åœ¨çš„设置内容。请务必å°å¿ƒæ“作。\næ‰§è¡Œè¿™ä¸ªå‘½ä»¤ï¼Œéœ€è¦ VPN Server 的管ç†å‘˜æƒé™ã€‚
+CMD_ConfigSet_Args ConfigSet [path]
+CMD_ConfigSet_[path] 指定é…置文件的å称。如果文件有多ç§æ–‡å­—,请先å˜åŒ–æˆ Unicode (UTF-8) æ ¼å¼ã€‚
+CMD_ConfigSet_PROMPT_PATH å°†é…置上传到æœåŠ¡å™¨ä¸Šçš„文件路径å称:
+CMD_ConfigSet_FILE_LOAD_FAILED 无法加载指定的文件。
+
+
+# RouterList 命令
+CMD_RouterList 获å–虚拟 3 层交æ¢æœºåˆ—表
+CMD_RouterList_Help 在 VPN Server ä¸ŠèŽ·å– 3 层虚拟交æ¢æœºçš„清å•ã€‚获å–虚拟 3 层交æ¢æœºçš„ [交æ¢æœºå称],[工作状æ€],[接å£æ•°é‡],[路由数目] 等信æ¯ã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚
+CMD_RouterList_Args RouterList
+
+
+# RouterAdd 命令
+CMD_RouterAdd 定义一个新的虚拟 3 层交æ¢æœº
+CMD_RouterAdd_Help 在 VPN Server 上定义一个新的 3 层虚拟交æ¢æœºã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚\n\n[虚拟 3 层交æ¢æœºåŠŸèƒ½çš„说明]\n在这个虚拟 VPN Server 上è¿è¡Œçš„多个虚拟 HUB 之间,å¯ä»¥é€šè¿‡å®šä¹‰çš„虚拟 3 层交æ¢æœºï¼Œå®žçŽ°ä¸åŒ IP 地å€ä¹‹é—´çš„路由。\n\n[虚拟 3 层交æ¢æœºåŠŸèƒ½çš„注æ„事项]\n虚拟 3 层交æ¢æœºåŠŸèƒ½æ˜¯åŸºäºŽå¯¹ç½‘络和 IP 路由熟悉的人或者是网络管ç†å‘˜ä½¿ç”¨çš„。如果您使用正常的 VPN 功能,您没有必è¦ä½¿ç”¨è™šæ‹Ÿ 3 层交æ¢æœºã€‚\n如果您使用虚拟 3 层交æ¢æœºçš„功能,请您务必è¦å分熟悉 IP 路由方é¢çš„知识,并å分清楚您的设置将对网络产生的影å“。
+CMD_RouterAdd_Args RouterAdd [name]
+CMD_RouterAdd_[name] 创建一个新的虚拟 3 层交æ¢æœºçš„å称。新创建的å称与现有的å称是ä¸èƒ½ç›¸åŒã€‚
+CMD_RouterAdd_PROMPT_NAME è¦åˆ›å»ºçš„虚拟 3 层交æ¢æœºçš„å称:
+
+
+# RouterDelete 命令
+CMD_RouterDelete 删除虚拟 3 层交æ¢æœº
+CMD_RouterDelete_Help 删除在 VPN Server 上已定义的 3 层虚拟交æ¢æœºã€‚如果选定的虚拟 3 层交æ¢æœºæ­£åœ¨è¿è¡Œï¼Œå®ƒå°†åœæ­¢å·¥ä½œï¼Œç„¶åŽè‡ªåŠ¨åˆ é™¤ã€‚\n获å–虚拟 3 层交æ¢æœºçš„清å•ï¼Œå¯ä»¥ä½¿ç”¨ RouterList 命令。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚
+CMD_RouterDelete_Args RouterDelete [name]
+CMD_RouterDelete_[name] 选定想è¦åˆ é™¤çš„虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterDelete_PROMPT_NAME 想è¦åˆ é™¤çš„虚拟 3 层交æ¢æœºçš„å称:
+
+
+# RouterStart 命令
+CMD_RouterStart 开始è¿è¡Œè™šæ‹Ÿ 3 层交æ¢æœº
+CMD_RouterStart_Help VPN Server 上已ç»å­˜åœ¨çš„虚拟 3 层交æ¢æœºï¼Œå¦‚果处于åœæ­¢å·¥ä½œå·¥ä½œçŠ¶æ€ï¼Œå°†å¼€å§‹è¿è¡Œã€‚\n获å–当å‰çš„虚拟 3 层交æ¢æœºæ¸…å•ï¼Œå¯ä»¥æ‰§è¡Œ RouterList 命令。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge è¿è¡Œã€‚\n\n[虚拟 3 层交æ¢æœºåŠŸèƒ½çš„说明]\n在这个虚拟 VPN Server 上è¿è¡Œçš„多个虚拟 HUB 之间,å¯ä»¥é€šè¿‡å®šä¹‰çš„虚拟 3 层交æ¢æœºï¼Œå®žçŽ°ä¸åŒ IP 地å€ä¹‹é—´çš„路由。\n\n[虚拟 3 层交æ¢æœºåŠŸèƒ½çš„注æ„事项]\n虚拟 3 层交æ¢æœºåŠŸèƒ½æ˜¯åŸºäºŽå¯¹ç½‘络和 IP 路由熟悉的人或者是网络管ç†å‘˜ä½¿ç”¨çš„。如果您使用正常的 VPN 功能,您没有必è¦ä½¿ç”¨è™šæ‹Ÿ 3 层交æ¢æœºã€‚\n如果您使用虚拟 3 层交æ¢æœºçš„功能,请您务必è¦å分熟悉 IP 路由方é¢çš„知识,并å分清楚您的设置将对网络产生的影å“。
+CMD_RouterStart_Args RouterStart [name]
+CMD_RouterStart_[name] 选定å³å°†å¯åŠ¨çš„虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterStart_PROMPT_NAME å³å°†å¯åŠ¨çš„虚拟 3 层交æ¢æœºçš„å称:
+
+
+# RouterStop 命令
+CMD_RouterStop åœæ­¢è™šæ‹Ÿ 3 层交æ¢æœºçš„è¿è¡Œ
+CMD_RouterStop_Help 在 VPN Server 上已定义的虚拟 3 层交æ¢æœºï¼Œå¦‚果正在è¿è¡Œï¼Œå®ƒå°†åœæ­¢è¿è¡Œã€‚\n想è¦èŽ·å–现有的虚拟 3 层交æ¢æœºæ¸…å•ï¼Œå¯ä»¥è¿è¡Œ RouterList 命令。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚
+CMD_RouterStop_Args RouterStop [name]
+CMD_RouterStop_[name] 选定想è¦åœæ­¢è¿è¡Œçš„虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterStop_PROMPT_NAME 想è¦åœæ­¢è¿è¡Œçš„虚拟 3 层交æ¢æœºå称:
+
+
+# RouterIfList 命令
+CMD_RouterIfList 获å–在虚拟 3 层交æ¢æœºä¸­æ³¨å†Œçš„远程接å£çš„清å•
+CMD_RouterIfList_Help 如果在指定的虚拟 3 层交æ¢æœºä¸Šæœ‰å·²ç»å®šä¹‰çš„虚拟远程接å£ï¼Œæ‚¨å°†ä¼šèŽ·å–一个虚拟接å£åˆ—表。\n在一个虚拟 3 层交æ¢æœºä¸Šï¼Œæ‚¨å¯ä»¥å®šä¹‰å¤šä¸ªè™šæ‹ŸæŽ¥å£å’Œè·¯ç”±è¡¨ã€‚\n虚拟接å£ä¸Žè™šæ‹Ÿ HUB 相互关è”,当虚拟 HUB è¿è¡Œæ—¶ï¼Œè™šæ‹ŸæŽ¥å£å°±åƒä¸€ä¸ªè™šæ‹Ÿ IP 主机在工作。相对于多个 IP 虚拟 HUB,如果定义分属ä¸åŒç½‘络的多个远程接å£æ—¶ï¼ŒIP 路由会自动è¿è¡Œã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚
+CMD_RouterIfList_Args RouterIfList [name]
+CMD_RouterIfList_[name] 选定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterIfList_PROMPT_NAME 虚拟 3 层交æ¢æœºçš„å称:
+
+
+# RouterIfAdd 命令
+CMD_RouterIfAdd 在虚拟 3 层交æ¢æœºä¸Šæ·»åŠ ä¸€ä¸ªè™šæ‹Ÿè¿œç¨‹æŽ¥å£
+CMD_RouterIfAdd_Help 指定的 3 层虚拟交æ¢æœºï¼Œä¸ºå®ƒæ·»åŠ ä¸€ä¸ªåœ¨åŒä¸€ä¸ª VPN Server 上è¿è¡Œçš„虚拟 HUB 的连接虚拟接å£ã€‚\n一个指定的 3 层虚拟交æ¢æœºï¼Œæ‚¨å¯ä»¥å®šä¹‰å¤šä¸ªè™šæ‹ŸæŽ¥å£å’Œè·¯ç”±è¡¨ã€‚\n虚拟接å£ä¸Žè™šæ‹Ÿ HUB 相互关è”,当虚拟 HUB è¿è¡Œæ—¶ï¼Œè™šæ‹ŸæŽ¥å£å°±åƒä¸€ä¸ªè™šæ‹Ÿ IP 主机在工作。相对于多个 IP 虚拟 HUB,如果定义分属ä¸åŒç½‘络的多个远程接å£æ—¶ï¼ŒIP 路由会自动è¿è¡Œã€‚\n虚拟接å£çš„ IP 网络空间,虚拟接å£çš„ IP 地å€å¿…须被定义。\n虚拟接å£å¿…须制定目标连接的虚拟 HUB çš„å称。\n指定虚拟 HUB 时,也å¯é€‰å®šå½“å‰ä¸å­˜åœ¨çš„虚拟 HUB。\n虚拟接å£å¿…须在虚拟 HUB 内有一个 IP 地å€ã€‚此外,还需指定属于该 IP 地å€çš„ IP 网络的å­ç½‘掩ç ã€‚\n设置虚拟 HUB 内几个虚拟空间通过交æ¢æœºçš„路由网,需在指定的 IP 地å€æ“作。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚ \nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œæ“作对象的虚拟 3 层交æ¢æœºå¿…须关闭。如果正在è¿è¡Œä¸­ï¼Œå¯ç”¨ RouterStop 命令让其åœæ­¢ã€‚
+CMD_RouterIfAdd_Args RouterIfAdd [name] [/HUB:hub] [/IP:ip/mask]
+CMD_RouterIfAdd_[name] 指定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterIfAdd_HUB 指定新建虚拟接å£æ‹Ÿè¿žæŽ¥çš„虚拟 HUB å称。虚拟 HUB åå•ï¼Œå¯ä»¥é€šè¿‡ HubList 命令获å–。但是,目å‰æ­£åœ¨è¿è¡Œçš„虚拟 HUB 没有必è¦æŒ‡å®šã€‚如果指定了目å‰æ²¡æœ‰å·¥ä½œï¼Œæˆ–ä¸å­˜åœ¨çš„虚拟 HUB,当它开始虚拟工作时,虚拟 3 层交æ¢æœºå°†è¢«æ¿€æ´»ã€‚
+CMD_RouterIfAdd_IP 按照 [IP 地å€/å­ç½‘掩ç ] çš„æ ¼å¼ï¼Œè®¾å®šæ–°æ·»åŠ çš„接å£çš„çš„ IP 地å€å’Œå­ç½‘掩ç ã€‚IP 地å€ä¸º 192.168.0.1,10 进制,以点区分。å­ç½‘æŽ©ç  255.255.255.0 以点区分,10 进制,也å¯ä»¥è®¾å®šä¸ºå¦‚ 24 这样的字节数用 10 进制æ¥è¡¨ç¤ºã€‚
+CMD_RouterIfAdd_PROMPT_NAME 虚拟 3 层交æ¢æœºçš„å称:
+CMD_RouterIfAdd_PROMPT_HUB 虚拟接å£è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB å称:
+CMD_RouterIfAdd_PROMPT_IP IP 地å€/å­ç½‘掩ç :
+
+
+# RouterIfDel 命令
+CMD_RouterIfDel 删除虚拟 3 层交æ¢æœºçš„虚拟远程接å£
+CMD_RouterIfDel_Help 删除在指定虚拟交æ¢æœºä¸­å·²å®šä¹‰çš„虚拟接å£ã€‚\n对当å‰å®šä¹‰çš„虚拟接å£åˆ—表,å¯ä»¥é€šè¿‡ RouterIfList 命令得到。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œè™šæ‹Ÿ 3 层转化åŠå¿…须在åœæ­¢çŠ¶æ€ã€‚如果ä¸æ˜¯ï¼Œå¯ä»¥é€šè¿‡ RouterStop 指令使其åœæ­¢ã€‚
+CMD_RouterIfDel_Args RouterIfDel [name] [/HUB:hub]
+CMD_RouterIfDel_[name] 指定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterIfDel_HUB 指定虚拟接å£æ‰€è¿žæŽ¥çš„虚拟 HUB çš„å称。
+
+
+# RouterTableList 命令
+CMD_RouterTableList 获å–虚拟 3 层交æ¢æœºçš„路由列表
+CMD_RouterTableList_Help 在指定的虚拟 3 层交æ¢æœºä¸­ï¼Œå¦‚果有路由表已定义,å¯ä»¥èŽ·å–一个路由表的列表。\n虚拟 3 层交æ¢æœºçš„IP 路由引擎,当 IP æ•°æ®åŒ…çš„ IP 地å€ä¸å±žäºŽä»»ä¸€ä¸ªè™šæ‹ŸæŽ¥å£æ—¶ï¼Œå°†å‚照这个路由表。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚
+CMD_RouterTableList_Args RouterTableList [name]
+CMD_RouterTableList_[name] 指定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterTableList_PROMPT_NAME 虚拟 3 层交æ¢æœºçš„å称:
+
+
+# RouterTableAdd 命令
+CMD_RouterTableAdd 添加一个路由表项到虚拟 3 层交æ¢æœº
+CMD_RouterTableAdd_Help 指定新的虚拟 3 层交æ¢æœºçš„路由表并添加一个新的路由表项。\n虚拟 3 层交æ¢æœºæ“作 IP 路由引擎时,IP æ•°æ®åŒ…的目的 IP 地å€ä¸å±žäºŽä»»ä½• IP 接å£æ—¶ï¼Œå¯ä»¥å‚照路由表进行æ“作。\nå‘虚拟 3 层交æ¢æœºä¸­æ·»åŠ çš„路由表项内容必须指定。作为网关,在虚拟 3 层交æ¢æœºçš„虚拟接å£ä¸­ï¼Œæœ‰è‡³å°‘一个属于åŒä¸€ IP 网络的 IP 地å€ç›¸åŒã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤è™šæ‹Ÿ 3 层交æ¢æœºå¿…须处于åœæ­¢å™¢å›½å†…工作状æ€ã€‚如果ä¸åœ¨åœæ­¢çŠ¶æ€ï¼Œå¯ä»¥æ‰§è¡Œ RouterStop 命令令其处于暂åœã€‚
+CMD_RouterTableAdd_Args RouterTableAdd [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableAdd_[name] 指定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterTableAdd_NETWORK 按照 [IP 地å€/å­ç½‘掩ç ] çš„æ ¼å¼ï¼Œè®¾ç½®æ–°æ·»åŠ çš„路由表的网络地å€å’Œå­ç½‘掩ç ã€‚网络地å€ï¼Œå¦‚ 192.168.0.1 çš„æ ¼å¼ï¼Œç”±ç‚¹åˆ†éš”,10 è¿›ä½åˆ¶ã€‚å­ç½‘掩ç å¦‚ 255.255.255.0,用点分隔,10 è¿›ä½åˆ¶ï¼Œæˆ–è€…åƒ 24 这样从开头 10 è¿›ä½è®¾å®šå­—节数。ä½é•¿åº¦å¯ä¸ºå进制数指定的分隔å进制数字。 如 0.0.0.0/0.0.0.0 将格å¼è®¾å®šå¥½ï¼Œé»˜è®¤ä¸ºæ ¹ã€‚
+CMD_RouterTableAdd_GATEWAY 指定网关的 IP 地å€ã€‚
+CMD_RouterTableAdd_METRIC 指定度é‡çš„值。请使用一个以上的整数。
+CMD_RouterTableAdd_PROMPT_NAME 虚拟 3 层交æ¢æœºçš„å称:
+CMD_RouterTableAdd_PROMPT_NETWORK 网络地å€/å­ç½‘掩ç :
+CMD_RouterTableAdd_PROMPT_GATEWAY 网关:
+CMD_RouterTableAdd_PROMPT_METRIC 公制值:
+
+
+# RouterTableDel 命令
+CMD_RouterTableDel 删除虚拟 3 层交æ¢æœºçš„路由表项
+CMD_RouterTableDel_Help 指定在虚拟 3 层交æ¢æœºä¸Šå·²å®šä¹‰çš„路由表项,进行删除。\n已定义的路由表项åå•ï¼Œå¯é€šè¿‡ RouterTableList 命令获å–。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚\nè¦è¿è¡Œæ­¤å‘½ä»¤è¦æ±‚虚拟 3 层转æ¢æœºå¤„于åœæ­¢çŠ¶æ€ã€‚如果没有处于åœæ­¢çŠ¶æ€ï¼Œå¯ä»¥æ‰§è¡Œ RouterStop 命令,让其暂åœã€‚
+CMD_RouterTableDel_Args RouterTableDel [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableDel_[name] 指定虚拟 3 层交æ¢æœºçš„å称。
+CMD_RouterTableDel_NETWORK 按照 [IP 地å€/å­ç½‘掩ç ] çš„æ ¼å¼ï¼Œé€‰å®šæ‹Ÿåˆ é™¤çš„路由表项的网络地å€ã€‚
+CMD_RouterTableDel_GATEWAY 指定网关的 IP 地å€ã€‚
+CMD_RouterTableDel_METRIC 指定度é‡çš„值。请使用一以上整数。
+
+
+# LogFileList 命令
+CMD_LogFileList 获å–日志文件列表
+CMD_LogFileList_Help 您å¯ä»¥å°†ä¿å­˜åœ¨ VPN Server 上,并有æœåŠ¡å™¨è¾“出的日志文件显示æˆä¸€ä¸ªè¾“出列表。通过指定一个文件å,è¿ç”¨ LogFileGet 命令,å¯ä»¥ä¸‹è½½è¯¥æ—¥å¿—文件的内容。\n如果 VPN Server 在管ç†æ¨¡å¼ä¸‹ï¼Œæ‰€æœ‰çš„虚拟 HUB çš„æ•°æ®åŒ…日志,安全日志,VPN Server 日志å…许您查看或下载。\n如果虚拟 HUB 在管ç†æ¨¡å¼ä¸‹ï¼Œå¹¶å¤„于连接状æ€ï¼Œå¯ä»¥æŸ¥çœ‹æˆ–下载该数æ®åŒ…日志和安全日志。
+CMD_LogFileList_Args LogFileList
+CMD_LogFileList_START 正在获å–一个日志文件的列表。这å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´ã€‚请ç¨å€™...
+CMD_LogFileList_NUM_LOGS 共有 %u 个日志文件。
+
+
+# LogFileGet 命令
+CMD_LogFileGet 日志文件下载
+CMD_LogFileGet_Help 下载 VPN Server 上存储的日志文件。è¦ä¸‹è½½æ—¥å¿—文件,先用 LogFileList 命令获å–日志文件列表,然åŽæ‚¨å°±å¯ä»¥æ‰§è¡Œ LogFileGet 命令æ¥ä¸‹è½½ã€‚如果与 VPN Server 连接并处于管ç†æ¨¡å¼ï¼Œæ‰€æœ‰çš„虚拟 HUB çš„æ•°æ®åŒ…日志,安全日志,VPN Server å…许您查看或下载。如果正在连接的虚拟 HUB 处于管ç†æ¨¡å¼ï¼ŒHUB 管ç†çš„虚拟数æ®åŒ…日志,安全日志å¯æŸ¥é˜…,也å¯ä»¥ä¸‹è½½ã€‚\n如果您指定一个作为å‚数作为文件å,下载的日志文件将被ä¿å­˜ä¸ºè¿™ä¸ªæ–‡ä»¶å。如果你ä¸æŒ‡å®šæ–‡ä»¶å°†æ˜¾ç¤ºåœ¨å±å¹•ä¸Šã€‚\n日志文件的大å°æœ‰å¯èƒ½éžå¸¸å·¨å¤§çš„,所以一定è¦å°å¿ƒã€‚
+CMD_LogFileGet_Args LogFileGet [name] [/SERVER:server] [/SAVEPATH:savepath]
+CMD_LogFileGet_[name] 选定è¦ä¸‹è½½çš„日志文件å。è¿è¡Œ LogFileList 命令,å¯ä»¥å¾—到一个日志文件的å称列表。
+CMD_LogFileGet_SERVER 如果您è¦ä»Žç¾¤é›†æŽ§åˆ¶å™¨ä¸­ä¸‹è½½ï¼Œè¯·æŒ‡å®šä¿å­˜æ—¥å¿—文件的æœåŠ¡å™¨å称。è¿è¡Œ LogFileGet 指令å¯ä»¥èŽ·å¾—指定æœåŠ¡å™¨ã€‚
+CMD_LogFileGet_SAVEPATH 如果你想ä¿å­˜ä¸‹è½½çš„日志文件,请指定文件å。如果没有指定,将显示在å±å¹•ä¸Šã€‚
+CMD_LogFileGet_PROMPT_NAME 下载的日志文件å:
+CMD_LogFileGet_START 正在下载日志文件。这å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´ã€‚请ç¨å€™...
+CMD_LogFileGet_FAILED 下载失败。
+CMD_LogFileGet_SAVE_FAILED 无法写入指定的文件。
+CMD_LogFileGet_FILESIZE 日志文件的大å°: %u
+
+
+# HubCreate 命令
+CMD_HubCreate 创建新的虚拟 HUB
+CMD_HubCreate_Help 在 VPN Server 上创建一个新的虚拟 HUB。\n创建的虚拟 HUB 将立å³å¼€å§‹å·¥ä½œã€‚\n当 VPN Server,在一个群集中è¿è¡Œï¼Œæ­¤å‘½ä»¤ä»…对群集控制器有效。新的虚拟 HUB,将作为一个动æ€çš„虚拟 HUB。应用 HubSetStatic 命令也å¯å°†è™šæ‹Ÿ HUB 改为é™æ€çš„。è¦æƒ³èŽ·å–å·²ç»å­˜å‚¨åœ¨ VPN Server 上的 HUB,å¯ä»¥è¿è¡Œ HubList 命令获得列表。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge 和群集管ç†æœåŠ¡å™¨ä¸­ä¸èµ·ä½œç”¨ã€‚\n在群集上创建虚拟群集控制器 HUB 时,请è¿è¡Œ HubCreateStatic 或者 HubCreateDynamic 命令。(对群集控制器æ“作时,HubCreate å’Œ HubCreateDynamic就有相åŒçš„功能)。
+CMD_HubCreate_Args HubCreate [name] [/PASSWORD:password]
+CMD_HubCreate_[name] 指定新创建的枢纽虚拟å称。
+CMD_HubCreate_PASSWORD 如果您设置的虚拟 HUB 需è¦å¯†ç ï¼Œè¯·æŒ‡å®šç®¡ç†å‘˜å¯†ç ã€‚å¦åˆ™ï¼Œä¼šæ示您输入。
+CMD_HubCreate_PROMPT_NAME 新创建的虚拟 HUB çš„åå­—:
+
+
+# HubCreateDynamic 命令
+CMD_HubCreateDynamic 创建一个新的动æ€è™šæ‹Ÿ HUB (集群)
+CMD_HubCreateDynamic_Help 在 VPN Server 上创建新的动æ€è™šæ‹Ÿ HUB。\n创建的虚拟 HUB 将立å³å¼€å§‹å·¥ä½œã€‚\nVPN Server,在一个群集中è¿è¡Œæ—¶ï¼Œæ­¤å‘½ä»¤ä»…对群集控制器有效。新的虚拟 HUBï¼Œå°†ä½œä¸ºä¸€ä¸ªè™šæ‹Ÿçš„åŠ¨æ€ HUB。è¿è¡Œ HubSetStatic 命令å¯ä»¥å°†è™šæ‹Ÿ HUB å¯ä»¥æ”¹ä¸ºé™æ€çš„。è¿è¡Œ HubList 命令å¯ä»¥èŽ·å–当å‰è™šæ‹Ÿ HUB 的列表。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge,群集管ç†å™¨ï¼Œç‹¬ç«‹çš„æœåŠ¡å™¨åœ¨ VPN Server 工作时ä¸èµ·ä½œç”¨ã€‚
+CMD_HubCreateDynamic_Args HubCreateDynamic [name] [/PASSWORD:password]
+CMD_HubCreateDynamic_[name] 指定新创建的虚拟 HUB çš„å称。
+CMD_HubCreateDynamic_PASSWORD 如果您设置虚拟 HUB 管ç†å¯†ç ï¼Œè¯·æŒ‡å®šç®¡ç†å‘˜å¯†ç ã€‚å¦åˆ™ï¼Œä¼šæ示您输入。
+
+
+# HubCreateStatic 命令
+CMD_HubCreateStatic 新创建一个é™æ€è™šæ‹Ÿ HUB (集群用)
+CMD_HubCreateStatic_Help 在 VPN Server 上创建一个新的é™æ€è™šæ‹Ÿ HUB。\n创建的虚拟 HUB 将立å³å¼€å§‹å·¥ä½œã€‚\nVPN Server 在一个群集中è¿è¡Œæ—¶ï¼Œæ­¤å‘½ä»¤ä»…对群集控制器有效。新创建的虚拟 HUBï¼Œä¸ºä¸€ä¸ªè™šæ‹Ÿçš„åŠ¨æ€ HUB。è¿è¡Œ HubSetStatic 命令å¯ä»¥å°†è™šæ‹Ÿ HUB 改为é™æ€çš„。如果想得到已ç»ä¿å­˜åœ¨ VPN Server 上的 HUB 列表,å¯ä»¥è¿è¡Œ HubList 命令。\nè¦è¿è¡Œæ­¤å‘½ä»¤ï¼ŒVPN Server 需è¦ç®¡ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge,群集管ç†å™¨ï¼Œç‹¬ç«‹çš„æœåŠ¡å™¨åœ¨ VPN Server 工作时ä¸èµ·ä½œç”¨ã€‚
+CMD_HubCreateStatic_Args HubCreateStatic [name] [/PASSWORD:password]
+CMD_HubCreateStatic_[name] 指定新创建的虚拟 HUB çš„å称。
+CMD_HubCreateStatic_PASSWORD 如果您设置虚拟 HUB 管ç†å¯†ç ï¼Œè¯·æŒ‡å®šç®¡ç†å‘˜å¯†ç ã€‚å¦åˆ™ï¼Œä¼šæ示您输入。
+
+
+# HubDelete 命令
+CMD_HubDelete 删除虚拟 HUB
+CMD_HubDelete_Help 删除 VPN Server 上现有的虚拟 HUB。\n当您删除虚拟 HUB åŽï¼Œæ‰€æœ‰çš„程åºè¿žæŽ¥å°†æ–­å¼€ï¼Œæ–°çš„程åºå°†ä¸èƒ½ä¸Žå®ƒè¿žæŽ¥ã€‚\n虚拟 HUB 的所有的设置,用户选项,组选项,è¯ä¹¦è®¾ç½®å’Œçº§è”将被删除。\n虚拟 HUB 被删除åŽï¼Œå°†ä¸èƒ½æ¢å¤ã€‚\nè¿è¡Œæ­¤å‘½ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge,群集管ç†å™¨ï¼Œç‹¬ç«‹çš„æœåŠ¡å™¨åœ¨ VPN Server 工作时ä¸èµ·ä½œç”¨ã€‚
+CMD_HubDelete_Args HubDelete [name]
+CMD_HubDelete_[name] 定è¦åˆ é™¤çš„虚拟 HUB å称。
+CMD_HubDelete_PROMPT_NAME 删除的虚拟 HUB å称:
+
+
+# HubSetStatic 命令
+CMD_HubSetStatic 将虚拟 HUB 的类型å˜ä¸ºé™æ€è™šæ‹Ÿåž‹
+CMD_HubSetStatic_Help 使用 VPN Server è¿è¡Œåœ¨ç¾¤é›†ä¸Šæ—¶ï¼Œå°†è™šæ‹Ÿ HUB 类型设定为é™æ€è™šæ‹Ÿ HUB。当虚拟 HUB 类型改å˜æ—¶ï¼Œæ‰€æœ‰çš„程åºè¿žæŽ¥å°†è¢«æš‚时中断。 \n当作为é™æ€è™šæ‹Ÿ HUB 工作时,所有的群集æˆå‘˜çš„æœåŠ¡å™¨ä¸Šï¼Œå°†ç”Ÿæˆè¯¥å称的虚拟 HUB。æ¯ä¸ªå°è¯•è¿žæŽ¥è¿™ä¸ªè™šæ‹Ÿ HUB 的用户,基于å„自æœåŠ¡å™¨çš„è´Ÿè·çŠ¶å†µï¼Œç¡®å®šä¸Žè¿™ä¸ªç¾¤é›†æŸä¸ªæˆå‘˜çš„连接。\né™æ€è™šæ‹Ÿ HUB,举例说,一个ä¼ä¸šä»Žäº’è”网上访问局域网,å…许数åƒæˆ–数以万计的用户远程访问 VPN Server。\nè¦æ‰§è¡Œè¿™ä¸ªå‘½ä»¤ï¼Œæ‚¨å¿…须有 VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge,群集管ç†å™¨ï¼Œç‹¬ç«‹çš„æœåŠ¡å™¨åœ¨ VPN Server 工作时ä¸èµ·ä½œç”¨ã€‚\n此命令ä¸èƒ½ç”¨äºŽæ¯” 5190 æ›´æ–°çš„æœåŠ¡å™¨ã€‚
+CMD_HubSetStatic_Args HubSetStatic [name]
+CMD_HubSetStatic_[name] 选定拟å˜æ›´æˆé™æ€è™šæ‹Ÿ HUB çš„å称。
+CMD_HubChange_PROMPT_NAME å˜æ›´è®¾ç½®çš„虚拟 HUB å称:
+
+
+# HubSetDynamic 命令
+CMD_HubSetDynamic 将虚拟 HUB 的类型å˜ä¸ºåŠ¨æ€è™šæ‹Ÿåž‹
+CMD_HubSetDynamic_Help 使用 VPN Server è¿è¡Œåœ¨ç¾¤é›†ä¸Šæ—¶ï¼Œå°†è™šæ‹Ÿ HUB 类型å˜æ›´ä¸ºåŠ¨æ€ã€‚当虚拟 HUB 类型改å˜æ—¶ï¼Œæ‰€æœ‰çš„程åºè¿žæŽ¥ä¼šæš‚时被中断。\n当该虚拟 HUB 上没有任何æˆå‘˜æ—¶ï¼Œè™šæ‹Ÿ HUB 在任何群集上都ä¸å­˜åœ¨ã€‚当第一个客户端试图连接到动æ€çš„虚拟 HUB 时,负è·æœ€ä½Žçš„æœåŠ¡å™¨å¯åŠ¨ï¼Œæ‰˜ç®¡è™šæ‹Ÿ HUB。当第二个和éšåŽçš„客户端试图连接到åŒä¸€ä¸ªè™šæ‹Ÿ HUB,它们会自动连接到æœåŠ¡å™¨æ‰˜ç®¡çš„虚拟 HUB。当所有的客户都从一个特定的动æ€è™šæ‹Ÿ HUB 断开,æœåŠ¡å™¨ä¸Šå°†ä¸å­˜åœ¨ä»»ä½•å®žä½“。\n动æ€è™šæ‹Ÿ HUB 的应用很广泛,例如,公å¸å†…部æ¯ä¸ªéƒ¨é—¨å®šåº”一个虚拟 HUB,让员工å¯ä»¥è¿žæŽ¥åˆ°è‡ªå·±æ‰€å±žçš„虚拟枢纽部门æ¥æ“作,从而实现集中管ç†ã€‚\nè¦æ‰§è¡Œè¿™ä¸ªå‘½ä»¤ï¼Œæ‚¨å¿…须有 VPN Server 管ç†å‘˜æƒé™ã€‚\n此外,此命令在 VPN Bridge,群集管ç†å™¨ï¼Œç‹¬ç«‹çš„æœåŠ¡å™¨åœ¨ VPN Server 工作时ä¸èµ·ä½œç”¨ã€‚\n此命令ä¸èƒ½ç”¨äºŽæ¯” 5190 æ›´æ–°çš„æœåŠ¡å™¨ã€‚
+CMD_HubSetDynamic_Args HubSetDynamic [name]
+CMD_HubSetDynamic_[name] 指定拟转å˜ä¸ºåŠ¨æ€è™šæ‹Ÿ HUB çš„å称。
+
+
+# HubList 命令
+CMD_HubList 获å–一个虚拟 HUB 列表
+CMD_HubList_Help 在 VPN Server 中获得虚拟 HUB 的清å•ã€‚对于æ¯ä¸€ä¸ªè™šæ‹Ÿ HUB,å¯ä»¥èŽ·å¾— [虚拟 HUB å称],[状æ€],[类型],[用户数é‡],[群数é‡],[访问数é‡],[MAC 目录的数é‡],[IP 目录数],[登陆次数],[上次登录],[最终通信时间]。\n但是,如果处于连接状æ€çš„虚拟 HUB 在管ç†æ¨¡å¼ä¸‹ï¼Œå¯¹äºŽåŒ¿å用户如果设定为ä¸åˆ—举虚拟 HUB,则虚拟 HUB ä¸ä¼šè¢«æ˜¾ç¤ºã€‚如果您连接到æœåŠ¡å™¨çš„管ç†æ¨¡å¼ï¼Œåˆ™æ‰€æœ‰çš„虚拟 HUB 会显示清å•ã€‚\n如果你连接到群集控制器以外的其他群集æˆå‘˜ï¼ŒVPN Server åªæ˜¾ç¤ºè™šæ‹Ÿ HUB 的托管虚拟主机。如果您连接到群集控制器æ¥ç®¡ç†ç¾¤é›†ï¼Œæ‰€æœ‰è™šæ‹Ÿ HUB 将显示。
+CMD_HubList_Args HubList
+
+
+# Hub 命令
+CMD_Hub 选择拟管ç†çš„虚拟 HUB
+CMD_Hub_Help 选择拟管ç†çš„虚拟 HUB。在 VPN Server 中,对目标虚拟 HUB 实行é…置管ç†ä¹‹å‰ï¼Œéœ€è¦ç”¨é€‰æ‹©å‘½ä»¤é€‰å®šè™šæ‹Ÿ HUB。\n当正在连接的 VPN Server 处于管ç†è™šæ‹Ÿ HUB 模å¼æ—¶ï¼Œæ‚¨å¯ä»¥é€‰å®šæ‹Ÿç®¡ç†çš„一个虚拟 HUB,而ä¸å¯ä»¥é€‰æ‹©å…¶ä»–的虚拟 HUB。与正在连接的 VPN Server 处于æœåŠ¡å™¨ç®¡ç†æ¨¡å¼ï¼Œå¯ä»¥å¯¹æ‰€æœ‰çš„虚拟 HUB 进行管ç†ã€‚\n获å–当å‰çš„虚拟 HUB 列表,å¯ä»¥æ‰§è¡Œ HubList 命令。\n在 VPN Bridge 中,åªå¯ä»¥é€‰æ‹©å字中带 "BRIDGE" 的虚拟 HUB。
+CMD_Hub_Args Hub [name]
+CMD_Hub_[name] 选定拟管ç†çš„虚拟 HUB çš„å称。如果您没有指定å‚数,目标虚拟 HUB 的选定将被清除。
+CMD_Hub_Unselected å–消已ç»é€‰å®šçš„虚拟 HUB。
+CMD_Hub_Selected 选择虚拟 HUB "%S"。
+CMD_Hub_Select_Failed /ADMINHUB 在虚拟 HUB 中想è¦é€‰æ‹© "%S" å‘生了以下的错误。
+CMD_Hub_Not_Selected 在è¿è¡Œæ­¤å‘½ä»¤ä¹‹å‰ï¼Œè¿ç”¨ HUB 管ç†å‘½ä»¤é€‰æ‹©ç›®æ ‡ç®¡ç†è™šæ‹Ÿ HUB。
+
+
+# Online 命令
+CMD_Online 虚拟 HUB çš„è”机
+CMD_Online_Help 如果您正在管ç†çš„虚拟 HUB 处于脱机状æ€ï¼Œè¯·è®¾ç½®æˆè”机。处于脱机状æ€çš„虚拟 HUB,ä¸ä¼šæŽ¥å—æ¥è‡ª VPN Client 连接。将虚拟 HUB 设定æˆè”网状æ€ï¼Œä»Žè€Œå¯ä»¥æŽ¥å—用户的虚拟连接并æä¾›æœåŠ¡ã€‚\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在 VPN Server 中的虚拟集群 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_Online_Args Online
+
+
+# Offline 命令
+CMD_Offline 虚拟 HUB 脱机
+CMD_Offline_Help 如果您正在管ç†çš„虚拟 HUB 在线,设置æˆè„±æœºã€‚虚拟 HUB 如果有连接程åºï¼Œå°†å…¨éƒ¨æ–­å¼€ã€‚虚拟 HUB 处于脱机状æ€ï¼Œä¸ä¼šæŽ¥å—æ¥è‡ª VPN Client 连接。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在 VPN Server 中的虚拟集群 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_Offline_Args Offline
+
+
+# SetMaxSession 命令
+CMD_SetMaxSession 设定虚拟 HUB 的最大åŒæ—¶åœ¨çº¿ç”¨æˆ·æ•°é‡
+CMD_SetMaxSession_Help 设定现在正在管ç†çš„虚拟 HUB 的最大åŒæ—¶åœ¨çº¿å®¢æˆ·æ•°é‡ã€‚当超过这个数é‡æ—¶ï¼Œå¦‚果从 VPN Client å’Œ VPN Bridge 连接的时候,超过了最大并å‘会è¯æ•°ï¼Œæ›´å¤šçš„客户将无法连接。最大åŒæ—¶åœ¨çº¿å®¢æˆ·æ•°çš„é™åˆ¶ä¸åŒ…括本地的网桥,虚拟的 NAT,级è”连接等生æˆè¿žæŽ¥ä¸åŒ…括在内。\n设置åŒæ—¶åœ¨çº¿æœ€å¤§æ•°ç›®ï¼Œå¯ä»¥é€šè¿‡è¿è¡Œ OptionsGet 命令获得。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_SetMaxSession_Args SetMaxSession [max_session]
+CMD_SetMaxSession_[max_session] 设置最大åŒæ—¶åœ¨çº¿å®¢æˆ·æ•°ï¼Œä½¿ç”¨æ•´æ•°ã€‚当您指定为 0 时,客户数没有é™åˆ¶ã€‚
+CMD_SetMaxSession_Prompt 最大åŒæ—¶åœ¨çº¿å®¢æˆ·æ•°:
+
+
+# SetHubPassword 命令
+CMD_SetHubPassword 设置虚拟 HUB 的管ç†å¯†ç 
+CMD_SetHubPassword_Help 设置目å‰æ­£åœ¨ç®¡ç†çš„虚拟 HUB 的管ç†å¯†ç ã€‚虚拟 HUB,如果设置了管ç†å¯†ç ï¼Œæ‚¨å¯ä»¥åº”用管ç†å¯†ç ï¼Œè™šæ‹Ÿ HUB,VPN Server 的公用事业,虚拟 HUB 连接,您å¯ä»¥é€šè¿‡æŒ‡å®šä¸€ä¸ªè¿žæŽ¥å¯†ç åœ¨è™šæ‹Ÿ HUB 的管ç†æ¨¡å¼ä¸‹å®žçŽ°è¿žæŽ¥ã€‚此外,通过 VPN Client å’Œ VPN Bridge,用户å用 "Administrator" 通过管ç†å‘˜å¯†ç ï¼Œä¹Ÿå¯ä»¥å®žçŽ°è¿žæŽ¥ã€‚\n此命令,ä¸èƒ½åœ¨ VPN Bridge 中è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_SetHubPassword_Args SetHubPassword [password]
+CMD_SetHubPassword_[password] 设定密ç ã€‚如果您ä¸æŒ‡å®šå°†è¢«æ示输入密ç ã€‚
+
+
+# SetEnumAllow 命令
+CMD_SetEnumAllow 设定虚拟 HUB å…许å‘匿å用户显示。
+CMD_SetEnumAllow_Help å˜æ›´è™šæ‹Ÿ HUB 的控制选项,对于匿å用户,å…许虚拟 HUB 显示。当您设置了此选项,VPN Client 的用户,在 VPN Server åªéœ€è¾“入地å€å³å¯æ˜¾ç¤ºè™šæ‹Ÿ HUB。虚拟 HUB 一创建æˆåŠŸï¼Œå³å¯æ˜¾ç¤ºã€‚此外,如果执行 SetEnumDeny 命令,å¯ä»¥ç¦æ­¢å‘匿å用户显示。虚拟 HUB 是在统计创建时设定å…许显示与å¦ã€‚\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_SetEnumAllow_Args SetEnumAllow
+
+
+# SetEnumDeny 命令
+CMD_SetEnumDeny 设定虚拟 HUB ç¦æ­¢å‘匿å用户显示。
+CMD_SetEnumDeny_Help å˜æ›´è™šæ‹Ÿ HUB 的控制选项,对于匿å用户,ç¦æ­¢è™šæ‹Ÿ HUB 显示。当您设置了此选项,VPN Client 的用户,在 VPN Server 输入检索虚拟 HUB,虚拟 HUB 也ä¸ä¼šæ˜¾ç¤ºã€‚此外,如果执行 SetEnumAllow 命令,å¯ä»¥å…许å‘匿å用户显示。虚拟 HUB 是在统计创建时设定å…许显示与å¦ã€‚\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_SetEnumDeny_Args SetEnumDeny
+
+
+# OptionsGet 命令
+CMD_OptionsGet 获得虚拟 HUB 的设置选项
+CMD_OptionsGet_Help 获å–虚拟 HUB 的选项设置清å•ã€‚虚拟 HUB å…许 / ç¦æ­¢æ˜¾ç¤ºè®¾ç½®ï¼Œæœ€å¤§çš„åŒæ—¶åœ¨çº¿æ•°é‡ï¼Œåœ¨çº¿ / 离线状æ€ï¼Œå’Œé›†ç¾¤è™šæ‹ŸçŽ¯å¢ƒä¸­ HUB 的类型。\n此命令对于一个虚拟集群 HUB ä¸èƒ½è¿è¡Œã€‚
+CMD_OptionsGet_Args OptionsGet
+CMD_OptionsGet_TITLE 虚拟 HUB "%S" 设置选项列表
+CMD_OptionsGet_ENUM 对于匿å用户的虚拟 HUB 的显示
+CMD_OptionsGet_MAXSESSIONS 最大åŒæ—¶åœ¨çº¿å®¢æˆ·æ•°
+CMD_OptionsGet_STATUS 状æ€
+CMD_OptionsGet_TYPE 虚拟 HUB 的类型
+
+
+
+# RadiusServerSet 命令
+CMD_RadiusServerSet 使用在用户认è¯ä¸­ä½¿ç”¨çš„ RADIUS æœåŠ¡å™¨è®¾ç½®
+CMD_RadiusServerSet_Help 接å—用户当å‰ä»¥ RADIUS æœåŠ¡å™¨è®¤è¯æ¨¡å¼ç®¡ç†è™šæ‹Ÿ HUB ,你需指定外部 RADIUS æœåŠ¡å™¨ï¼Œä»¥ç¡®è®¤ç”¨æˆ·å和密ç (您å¯ä»¥æŒ‡å®šå¤šä¸ªä¸»æœºå,并将它们用逗å·æˆ–者分å·éš”å¼€)。\nRadius æœåŠ¡å™¨å¿…须设置为接å—æ¥è‡ª VPN Server IP 地å€çš„请求。此外,密ç è®¤è¯åè®®(PAP)的认è¯å¿…须被å¯ç”¨ã€‚\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚\n此命令在 VPN Server 以集群è¿è¡Œçš„虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_RadiusServerSet_Args RadiusServerSet [server_name:port] [/SECRET:secret] [/RETRY_INTERVAL:interval]
+CMD_RadiusServerSet_[server_name:port] 用 [主机å:端å£å·] çš„æ ¼å¼ï¼ŒæŒ‡å®š RADIUS æœåŠ¡å™¨çš„主机å,IP 地å€å’Œ UDP 端å£å·ã€‚如果çœç•¥ç«¯å£å·åˆ™ç”¨ 1812。您å¯ä»¥æŒ‡å®šå¤šä¸ªä¸»æœºå,并将它们用逗å·æˆ–者分å·éš”开。
+CMD_RadiusServerSet_SECRET 设置与 RADIUS æœåŠ¡å™¨ä¹‹é—´çš„通信 (密ç )。
+CMD_RadiusServerSet_RETRY_INTERVAL 用毫秒指定é‡è¯•é—´éš”。
+CMD_RadiusServerSet_Prompt_Host 使用 RADIUS æœåŠ¡å™¨çš„主机å和端å£å·:
+CMD_RadiusServerSet_Prompt_Secret 共享秘密:
+CMD_RadiusServerSet_Prompt_RetryInterval é‡è¯•é—´éš” (毫秒):
+CMD_RadiusServerSet_EVAL_NUMINTERVAL é‡è¯•é—´éš”为 500 毫秒到 10000 毫秒。
+
+
+# RadiusServerDelete 命令
+CMD_RadiusServerDelete 删除应用于用户认è¯çš„ RADIUS æœåŠ¡å™¨è®¾ç½®
+CMD_RadiusServerDelete_Help ç›®å‰ï¼Œæ­£åœ¨ç®¡ç†çš„虚拟 HUB,用户以 RADIUS æœåŠ¡å™¨è®¤è¯æ¨¡å¼è¿žæŽ¥æ—¶ï¼Œåˆ é™¤å¤–部 RADIUS æœåŠ¡å™¨è®¾å®šï¼Œä½¿æœåŠ¡å™¨ä¸èƒ½éªŒè¯ã€‚ç›®å‰ RADIUS æœåŠ¡å™¨çš„设置,å¯ä»¥è¿è¡Œ RadiusServerGet 命令获得。\n此命令,虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_RadiusServerDelete_Args RadiusServerDelete
+
+
+# RadiusServerGet 命令
+CMD_RadiusServerGet 获å–用于用户认è¯çš„ RADIUS æœåŠ¡å™¨è®¾ç½®
+CMD_RadiusServerGet_Help 用户使用 RADIUS æœåŠ¡å™¨èº«ä»½éªŒè¯æ¨¡å¼è¿žæŽ¥åˆ°çŽ°åœ¨ç®¡ç†çš„虚拟 HUB,您å¯ä»¥èŽ·å– RADIUS æœåŠ¡å™¨çš„当å‰è®¾ç½®ã€‚\n此命令,在虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_RadiusServerGet_Args RadiusServerGet
+CMD_RadiusServerGet_STATUS RADIUS æœåŠ¡å™¨çš„使用
+CMD_RadiusServerGet_HOST RADIUS æœåŠ¡å™¨ä¸»æœºå或 IP 地å€
+CMD_RadiusServerGet_PORT RADIUS æœåŠ¡å™¨çš„端å£å·
+CMD_RadiusServerGet_SECRET 共享秘密
+CMD_RadiusServerGet_RetryInterval é‡è¯•é—´éš” (毫秒)
+
+
+# StatusGet 命令
+CMD_StatusGet 获å–虚拟 HUB 的当å‰çŠ¶å†µ
+CMD_StatusGet_Help 获å–正在管ç†çš„虚拟 HUB 的当å‰çŠ¶å†µï¼Œå¯ä»¥èŽ·å¾—虚拟 HUB çš„ç§ç±»,连接数é‡ï¼Œå„ç§ç›®æ ‡æ•°ï¼Œç™»é™†æ¬¡æ•°ï¼Œæœ€åŽä¸€æ¬¡ç™»é™†æ—¶é—´ï¼Œæœ€ç»ˆè¿žæŽ¥æ—¶é—´ï¼Œé€šä¿¡çš„统计数æ®ç­‰ã€‚
+CMD_StatusGet_Args StatusGet
+
+
+# LogGet 命令
+CMD_LogGet 获å–虚拟 HUB 日志的ä¿å­˜è®¾å®š
+CMD_LogGet_Help 获å–虚拟 HUB 日志的ä¿å­˜è®¾ç½®ã€‚获å–安全日志和数æ®åŒ…日志的ä¿å­˜è®¾å®šï¼Œä¿å­˜å¯¹è±¡ç­‰ä¿¡æ¯ã€‚
+CMD_LogGet_Args LogGet
+CMD_Log_SecurityLog ä¿å­˜å®‰å…¨æ—¥å¿—
+CMD_Log_PacketLog ä¿å­˜æ•°æ®åŒ…日志
+CMD_Log_SwitchType 日志文件的替æ¢å‘¨æœŸ
+CMD_Log_0 TCP 连接日志
+CMD_Log_1 TCP æ•°æ®åŒ…日志
+CMD_Log_2 DHCP 日志
+CMD_Log_3 UDP 日志
+CMD_Log_4 ICMP 日志
+CMD_Log_5 IP 日志
+CMD_Log_6 ARP 日志
+CMD_Log_7 以太网日志
+
+
+# LogEnable 命令
+CMD_LogEnable å¯ç”¨å®‰å…¨æ—¥å¿—或数æ®åŒ…日志
+CMD_LogEnable_Help å¯ç”¨çŽ°åœ¨æ­£åœ¨ç®¡ç†çš„ HUB 的安全日志或数æ®åŒ…日志。\n当å‰çš„设置,å¯ä»¥é€šè¿‡ LogGet 命令获得。
+CMD_LogEnable_Args LogEnable [security|packet]
+CMD_LogEnable_[security|packet] 选择å¯ç”¨æ—¥å¿—文件的类型。选定 "security" 或 "packet"。
+CMD_LogEnable_Prompt 选择安全或数æ®åŒ…:
+CMD_LogEnable_Prompt_Error 选择ä¸æ­£ç¡®ã€‚
+
+
+# LogDisable 命令
+CMD_LogDisable ç¦ç”¨å®‰å…¨æ—¥å¿—或数æ®åŒ…日志
+CMD_LogDisable_Help ç¦æ­¢ä½¿ç”¨çŽ°åœ¨æ­£åœ¨ç®¡ç†çš„ HUB 的安全日志或数æ®åŒ…日志。\n当å‰çš„设置,å¯ä»¥é€šè¿‡ LogGet 命令获得。
+CMD_LogDisable_Args LogDisable [security|packet]
+CMD_LogDisable_[security|packet] 选择ç¦ç”¨æ—¥å¿—文件的类型。选定 "security" 或 "packet"。
+
+
+# LogSwitchSet 命令
+CMD_LogSwitchSet 设定替æ¢æ—¥å¿—文件的周期
+CMD_LogSwitchSet_Help 设定现在管ç†çš„虚拟 HUB 所ä¿å­˜çš„安全日志或数æ®åŒ…日志文件的替æ¢å‘¨æœŸã€‚替æ¢æ—¥å¿—文件的时间是å¯ä»¥è®¾å®šä¸º 1 秒,1 分钟,1 å°æ—¶ï¼Œæ¯å¤©ï¼Œæ¯æœˆï¼Œæ‚¨ä¹Ÿå¯ä»¥è®¾å®šä¸ºä¸æ›¿æ¢ã€‚\n当å‰çš„设置,å¯ä»¥é€šè¿‡ LogGet 命令获得。
+CMD_LogSwitchSet_Args LogSwitchSet [security|packet] [/SWITCH:sec|min|hour|day|month|none]
+CMD_LogSwitchSet_[security|packet] 选择å˜æ›´è®¾å®šçš„日志文件的类型。 选定 "security" 或 "packet"。
+CMD_LogSwitchSet_SWITCH 设置替æ¢å‘¨æœŸã€‚从 sec,min,hour,day,month,none 中选择。
+CMD_LogSwitchSet_Prompt 从 sec,min,hour,day,month,none 中选择:
+
+
+# LogPacketSaveType 命令
+CMD_LogPacketSaveType 设置ä¿å­˜ä¸ºæ•°æ®åŒ…日志文件的数æ®åŒ…ç§ç±»åŠä¿å­˜ã€‚
+CMD_LogPacketSaveType_Help é€é¡¹è®¾å®šä¿å­˜åœ¨åœ¨ç®¡ç†çš„虚拟 HUB 上的,数æ®åŒ…ä¿å­˜å†…容和数æ®åŒ…的类型。数æ®åŒ…类型包括,[TCP 连接日志],[TCP æ•°æ®åŒ…日志],[DHCP æ•°æ®åŒ…记录],[UDP æ•°æ®åŒ…日志],[ICMP æ•°æ®åŒ…日志],[IP æ•°æ®åŒ…日志],[ARP æ•°æ®åŒ…日志],[以太网数æ®åŒ…日志] 等。\nè¦æƒ³èŽ·å–当å‰çš„设置,å¯ä»¥è¿è¡Œ LogGet 命令。
+CMD_LogPacketSaveType_Args LogPacketSaveType [/TYPE:tcpconn|tcpdata|dhcp|udp|icmp|ip|arp|ether] [/SAVE:none|header|full]
+CMD_LogPacketSaveType_TYPE ä¿å­˜å†…容对应的数æ®åŒ…类型,从 tcpconn,tcpdata,dhcp,udp,icmp,ip,arp,ether 中选定。
+CMD_LogPacketSaveType_SAVE 设定日志文件的ä¿å­˜å†…容。从下列选定:\nnone: ä¸ä¿å­˜\nheader: ä»…ä¿å­˜æ ‡é¢˜\nfull: 所有数æ®åŒ…
+CMD_LogPacketSaveType_Prompt_TYPE 选定 tcpconn, tcpdata, dhcp, udp, icmp, ip, arp, ether:
+CMD_LogPacketSaveType_Prompt_SAVE 选定 none, header, full:
+
+
+# CAList 命令
+CMD_CAList 获å–å¯ä»¥ä¿¡ä»»çš„机构é¢å‘è¯ä¹¦çš„列表
+CMD_CAList_Help 管ç†å¯ä»¥ä¿¡ä»»çš„机构é¢å‘çš„è¯ä¹¦ã€‚VPN Client 如果用认è¯æ¨¡å¼è¿žæŽ¥æ—¶ï¼Œå¯ä»¥ç”¨ä¿å­˜çš„è¯ä¹¦æ¥éªŒè¯å…¶æ供的è¯ä¹¦ã€‚\n此命令,在虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CAList_Args CAList
+CMD_CAList_COLUMN_ID ID
+
+
+# CAAdd 命令
+CMD_CAAdd 添加å¯ä»¥ä¿¡ä»»çš„机构é¢å‘çš„è¯ä¹¦
+CMD_CAAdd_Help 在虚拟 HUB 管ç†çš„å¯ä¿¡ä»»çš„è¯ä¹¦é¢å‘机构的è¯ä¹¦åˆ—表中,添加一个新的è¯ä¹¦ã€‚如果客户端使用签å认è¯æ¨¡å¼è¿žæŽ¥ï¼Œç®¡ç†ä¸­çš„è¯ä¹¦å°†ç”¨æ¥è¯†åˆ«å®¢æˆ·çš„è¯ä¹¦ã€‚\nè¦å–得当å‰çš„è¯ä¹¦åˆ—表,å¯ä»¥æ‰§è¡Œ CAList 命令。\nè¦æ·»åŠ ä¸€ä¸ªè¯ä¹¦ï¼Œå¿…须将è¯ä¹¦ä¿å­˜ä¸º X.509 æ ¼å¼ä¿å­˜ã€‚\n此命令,在虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CAAdd_Args CAAdd [path]
+CMD_CAAdd_[path] 指定注册 X.509 è¯ä¹¦çš„文件å。
+CMD_CAAdd_PROMPT_PATH 注册 X.509 è¯ä¹¦æ–‡ä»¶çš„å称:
+
+
+# CADelete 命令
+CMD_CADelete 删除å¯ä»¥ä¿¡ä»»çš„机构é¢å‘çš„è¯ä¹¦
+CMD_CADelete_Help 从正在管ç†çš„å¯ä¿¡ä»»æœºæž„é¢å‘çš„è¯ä¹¦åˆ—表中,删除现有的è¯ä¹¦ã€‚\n如果è¦èŽ·å–当å‰çš„è¯ä¹¦åˆ—表,å¯ä»¥æ‰§è¡Œ CAList 命令。\n此命令,在虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CADelete_Args CADelete [id]
+CMD_CADelete_[id] 指定拟删除的è¯ä¹¦çš„ ID。
+CMD_CADelete_PROMPT_ID 拟删除è¯ä¹¦çš„ ID:
+
+
+# CAGet 命令
+CMD_CAGet 获得å¯ä¿¡ä»»æœºæž„é¢å‘çš„è¯ä¹¦ã€‚
+CMD_CAGet_Help 获å–虚拟 HUB ç›®å‰ç®¡ç†çš„å¯ä¿¡ä»»æœºæž„é¢å¸ƒçš„è¯ä¹¦çš„列表,并将其ä¿å­˜ä¸º X.509 的文件格å¼ã€‚\n此命令,在虚拟 VPN Bridge 中ä¸èƒ½è¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CAGet_Args CAGet [id] [/SAVECERT:path]
+CMD_CAGet_[id] 制定获得è¯ä¹¦çš„ ID。
+CMD_CAGet_SAVECERT 指定文件å以ä¿å­˜èŽ·å–çš„è¯ä¹¦ã€‚
+CMD_CAGet_PROMPT_ID 获得è¯ä¹¦ ID:
+CMD_CAGet_PROMPT_SAVECERT ä¿å­˜æ–‡ä»¶å:
+
+
+# CascadeList 命令
+CMD_CascadeList 获å–级è”接续列表
+CMD_CascadeList_Help 获å–当å‰è™šæ‹Ÿ HUB 上登记的级è”åå•ã€‚\n如果您使用虚拟 HUB 级è”åŒä¸€å°æˆ–å¦ä¸€ä¸ªè™šæ‹Ÿæœºä¸Šçš„ HUB,这两个层å¯ä»¥çº§è”。\n\n[使用级è”的警告]\n如果您使用级è”多个虚拟 HUB å¯ä»¥æž„æˆ 2 层的网桥,如果连接方法错误å¯èƒ½ä¼šå°†è¿žæŽ¥åšæˆç»³çŠ¶ã€‚所以使用级è”功能,一定è¦ç²¾å¿ƒè®¾è®¡ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeList_Args CascadeList
+
+
+# CascadeCreate 命令
+CMD_CascadeCreate 创建一个新的级è”接续
+CMD_CascadeCreate_Help 在当å‰è™šæ‹Ÿ HUB 上创建一个新的级è”接续。\n如果您使用虚拟 HUB 级è”åŒä¸€ä¸ªæˆ–者å¦ä¸€ä¸ªè™šæ‹Ÿ HUB,å¯ä»¥å»ºç«‹çº§è”接续。\nè¦åˆ›å»ºä¸€ä¸ªçº§è”,作为åˆå§‹å‚数,需设定级è”çš„å称,连接的æœåŠ¡å™¨ï¼Œç›®æ ‡ HUB çš„å称和用户å。创建一个新的级è”时,用户身份验è¯ç±»åž‹è¢«åˆå§‹åŒ–为 [匿å认è¯],代ç†æœåŠ¡å™¨å’ŒæœåŠ¡å™¨è¯ä¹¦éªŒè¯æœªè®¾ç½®ã€‚è¦æ›´æ”¹è¿™äº›è®¾ç½®ï¼Œè¯·åœ¨åˆ›å»ºä¸€ä¸ªçº§è”之åŽç”¨ "Cascade" 命å的指令æ¥æ‰§è¡Œã€‚\n\n[使用级è”的警告]\n如果您使用级è”多个虚拟 HUB å¯ä»¥æž„æˆ 2 层的网桥,如果连接方法错误å¯èƒ½ä¼šå°†è¿žæŽ¥åšæˆç»³çŠ¶ã€‚所以使用级è”功能,一定è¦ç²¾å¿ƒè®¾è®¡ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeCreate_Args CascadeCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username]
+CMD_CascadeCreate_[name] 指定新创建级è”çš„å称。
+CMD_CascadeCreate_SERVER 按照 [主机å:端å£å·] çš„æ ¼å¼ï¼Œè®¾ç½® VPN Server 的主机å和端å£å·ï¼Œæ‚¨ä¹Ÿå¯ä»¥æŒ‡å®š IP 地å€ã€‚
+CMD_CascadeCreate_HUB 选定目标 VPN Server 内的虚拟 HUB。
+CMD_CascadeCreate_USERNAME 设定连接到 VPN Server 时所须的用户å认è¯å称。
+CMD_CascadeCreate_Prompt_Name 级è”接续的å称:
+CMD_CascadeCreate_Prompt_Server 目标 VPN Server 的主机å和端å£å·:
+CMD_CascadeCreate_Prompt_Hub 目标虚拟 HUB å称:
+CMD_CascadeCreate_Prompt_Username 连接使用的用户å:
+
+
+# CascadeSet 命令
+CMD_CascadeSet 对级è”连接方的设定
+CMD_CascadeSet_Help 对于虚拟 HUB ç›®å‰ç®¡ç†çš„å·²ç»è¿žæŽ¥çš„级è”,设置连接方的 VPN 主机å和端å£å·ï¼Œè™šæ‹Ÿ HUB å,用户å等。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeSet_Args CascadeSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_CascadeSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeSet_SERVER 按照 [主机å:端å£å·] çš„æ ¼å¼ï¼Œè®¾ç½®è¿žæŽ¥æ–¹ VPN Server 的主机å和端å£å·ã€‚您也å¯ä»¥æŒ‡å®š IP 地å€ã€‚
+CMD_CascadeSet_HUB 设置连接方 VPN Server 内的虚拟 HUB。
+
+
+# CascadeGet 命令
+CMD_CascadeGet 获å–级è”连接的设置
+CMD_CascadeGet_Help 获å–当å‰åœ¨è™šæ‹Ÿ HUB 上注册的级è”的连接设置。\nå¦å¤–,è¦æ”¹å˜çº§è”的连接设置,å¯ä»¥åœ¨æ‚¨åˆ›å»ºä¸€ä¸ªçº§è”åŽä½¿ç”¨ "Cascade" 开头的命令。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeGet_Args CascadeGet [name]
+CMD_CascadeGet_[name] 指定级è”获å–它的连接设置。
+CMD_CascadeGet_Policy [级è”连接的安全策略设置值]
+
+# CascadeDelete 命令
+CMD_CascadeDelete 删除级è”连接
+CMD_CascadeDelete_Help 删除目å‰åœ¨è™šæ‹Ÿ HUB 中注册的级è”连接。如果选定的级è”连接处于è”机状æ€ï¼Œåˆ™å…ˆæ–­å¼€è¿žæŽ¥ï¼Œç„¶åŽåˆ é™¤ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeDelete_Args CascadeDelete [name]
+CMD_CascadeDelete_[name] 指定您想删除的级è”连接的å称。
+
+
+# CascadeUsernameSet 命令
+CMD_CascadeUsernameSet 设置级è”连接的用户å
+CMD_CascadeUsernameSet_Help 选定已在虚拟 HUB 上注册的级è”,设定其用户å,当连接到 VPN Server 时,用此用户åæ¥è¿›è¡Œèº«ä»½éªŒè¯ã€‚\n此外,您å¯ä»¥æŒ‡å®šç”¨æˆ·èº«ä»½éªŒè¯çš„ç§ç±»ï¼Œæˆ–å¯ä»¥æŒ‡å®šæ‰€éœ€çš„å‚数。如果您想更改这些设置,å¯ä»¥è¿è¡Œ CascadeAnonymousSet,CascadePasswordSet,CascadeCertSet 等命令。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeUsernameSet_Args CascadeUsernameSet [name] [/USERNAME:username]
+CMD_CascadeUsernameSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeUsernameSet_USERNAME 级è”连接到 VPN Server 时,指定用户åè¦æ±‚用户进行身份验è¯ã€‚
+CMD_CascadeUsername_Notice 连接身份验è¯ï¼Œæ˜¯åœ¨å¯†ç éªŒè¯ä¸­è®¾ç½®çš„。用户åå˜æ›´ä¹‹åŽï¼Œéœ€è¦ç”¨ CascadePasswordSet 指令é‡æ–°è®¾ç½®å¯†ç ã€‚
+
+
+# CascadeAnonymousSet 命令
+CMD_CascadeAnonymousSet 将级è”连接的用户认è¯ç±»åž‹è®¾ç½®ä¸ºåŒ¿å身份验è¯
+CMD_CascadeAnonymousSet_Help 选定虚拟 HUB 中已ç»æ³¨å†Œçš„级è”,将级è”连接到 VPN Server 所需的用户身份验è¯æ–¹æ³•è®¾å®šä¸ºåŒ¿å身份验è¯ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeAnonymousSet_Args CascadeAnonymousSet [name]
+CMD_CascadeAnonymousSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadePasswordSet 命令
+CMD_CascadePasswordSet 将级è”连接时所需的用户验è¯è®¾ç½®ä¸ºå¯†ç éªŒè¯
+CMD_CascadePasswordSet_Help 选定虚拟 HUB 中已ç»æ³¨å†Œçš„级è”,将级è”连接到 VPN Server 所需的用户身份验è¯æ–¹æ³•è®¾å®šä¸ºå¯†ç éªŒè¯ã€‚密ç éªŒè¯çš„ç§ç±»æŒ‡å®šä¸ºï¼Œ[标准密ç éªŒè¯] å’Œ [RADIUS 或 NT域身份验è¯]。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadePasswordSet_Args CascadePasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_CascadePasswordSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadePasswordSet_PASSWORD 指定密ç éªŒè¯æ‰€ä½¿ç”¨çš„密ç ã€‚å¦åˆ™ï¼Œä¼šæ示您输入密ç ã€‚
+CMD_CascadePasswordSet_TYPE 密ç éªŒè¯çš„类型,指定为 "standard" (标准密ç éªŒè¯),或 "radius" (radius 或 NT 域身份验è¯)。
+CMD_CascadePasswordSet_Prompt_Type 指定 standard 或者 radius:
+CMD_CascadePasswordSet_Type_Invalid 指定 standard 或者 radius 时出错。
+
+
+# CascadeCertSet 命令
+CMD_CascadeCertSet 将级è”连接时所需的用户验è¯è®¾ç½®ä¸ºå®¢æˆ·è¯ä¹¦éªŒè¯
+CMD_CascadeCertSet_Help 选定虚拟 HUB 中已ç»æ³¨å†Œçš„级è”,将级è”连接到 VPN Server 所需的用户身份验è¯æ–¹æ³•è®¾å®šä¸ºå®¢æˆ·è¯ä¹¦éªŒè¯ã€‚è¯ä¹¦åº”为 X.509 è¯ä¹¦æ–‡ä»¶æ ¼å¼ï¼Œå¹¶ä¸”用å˜æ¢ä¸º Base 64 密钥文件编ç ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeCertSet_Args CascadeCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_CascadeCertSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeCertSet_LOADCERT 选定 X.509 è¯ä¹¦å称用æ¥è¿›è¡Œè¯ä¹¦è®¤è¯ã€‚
+CMD_CascadeCertSet_LOADKEY 选定与è¯ä¹¦å¯¹åº”çš„ Base 64 ç¼–ç çš„密钥文件。
+
+
+# CascadeCertGet 命令
+CMD_CascadeCertGet 获å–级è”连接所需的客户端è¯ä¹¦
+CMD_CascadeCertGet_Help 指定当å‰åœ¨è™šæ‹Ÿ HUB 上已注册的级è”接续,如果您使用客户端è¯ä¹¦èº«ä»½éªŒè¯ï¼Œè¯·èŽ·å–è¯ä¹¦ï¼Œä¿å­˜ä¸º X.509 æ ¼å¼ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeCertGet_Args CascadeCertGet [name] [/SAVECERT:cert]
+CMD_CascadeCertGet_[name] 指定级è”å称获å–设置。
+CMD_CascadeCertGet_SAVECERT 获å–è¯ä¹¦æŒ‡å®šæ–‡ä»¶åä¿å­˜ä¸º X.509 æ ¼å¼ã€‚
+CMD_CascadeCertSet_Not_Auth_Cert 指定的级è”连接设置的认è¯æ–¹å¼ä¸æ˜¯è¯ä¹¦è®¤è¯æ¨¡å¼ã€‚
+CMD_CascadeCertSet_Cert_Not_Exists è¯ä¹¦æ²¡æœ‰å­˜å‚¨åœ¨æ‰€æŒ‡å®šçš„级è”连接设置中。
+
+
+# CascadeEncryptEnable 命令
+CMD_CascadeEncryptEnable å¯ç”¨çº§è”通信时加密
+CMD_CascadeEncryptEnable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置通信内容为 SSL 加密。\n通常情况下,和 VPN Server 的通信进行 SSL 加密,以防止窃å¬å’Œç¯¡æ”¹ä¿¡æ¯ã€‚您还å¯ä»¥ç¦ç”¨åŠ å¯†ã€‚如果您ç¦ç”¨åŠ å¯†ï¼Œé€šä¿¡çš„æµé€Ÿå°†æ高,传输数æ®ä»¥æ˜Žæ–‡ä¼ è¾“到网络上。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeEncryptEnable_Args CascadeEncryptEnable [name]
+CMD_CascadeEncryptEnable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeEncryptDisable 命令
+CMD_CascadeEncryptDisable 级è”连接通信时,ç¦ç”¨åŠ å¯†
+CMD_CascadeEncryptDisable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置通信内容为ç¦æ­¢åŠ å¯†ã€‚\n通常情况下,和 VPN Server 的通信进行 SSL 加密,以防止窃å¬å’Œç¯¡æ”¹ä¿¡æ¯ã€‚您还å¯ä»¥ç¦ç”¨åŠ å¯†ã€‚如果您ç¦ç”¨åŠ å¯†ï¼Œé€šä¿¡çš„æµé€Ÿå°†æ高,传输数æ®ä»¥æ˜Žæ–‡ä¼ è¾“到网络上。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeEncryptDisable_Args CascadeEncryptDisable [name]
+CMD_CascadeEncryptDisable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeCompressEnable 命令
+CMD_CascadeCompressEnable å¯ç”¨çº§è”通信是数æ®åŽ‹ç¼©åŠŸèƒ½
+CMD_CascadeCompressEnable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置通信内容为压缩内容。\n压缩é‡æœ€å¤§å¯ä»¥è¾¾åˆ° 80% 。但是,实行压缩,会给客户端和æœåŠ¡å™¨åŒæ–¹çš„ CPU 造æˆå¾ˆé«˜çš„è´Ÿè·ã€‚如果网络速度在 10 Mbps 以上,实施压缩åŽä¼šå‡å°‘传输æµé‡ï¼Œå¯èƒ½ä¼šé€‚å¾—å…¶å。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeCompressEnable_Args CascadeCompressEnable [name]
+CMD_CascadeCompressEnable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeCompressDisable 命令
+CMD_CascadeCompressDisable 级è”通信是数æ®ç¦æ­¢åŽ‹ç¼©åŠŸèƒ½
+CMD_CascadeCompressDisable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置通信内容为ç¦æ­¢åŽ‹ç¼©ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeCompressDisable_Args CascadeCompressDisable [name]
+CMD_CascadeCompressDisable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeProxyNone 命令
+CMD_CascadeProxyNone 将级è”的连接方法设置为直接与 TCP/IP 连接
+CMD_CascadeProxyNone_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置连接方法为 [直接与 TCP/IP 连接],而ä¸é€šè¿‡ä»£ç†æœåŠ¡å™¨ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeProxyNone_Args CascadeProxyNone [name]
+CMD_CascadeProxyNone_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeProxyHttp 命令
+CMD_CascadeProxyHttp 将级è”连接方法设定为通过 HTTP 代ç†æœåŠ¡å™¨
+CMD_CascadeProxyHttp_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置连接方法为,[通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥],然åŽè®¾ç½®è¦é€šè¿‡çš„ HTTP 代ç†æœåŠ¡å™¨çš„主机å和端å£å·ï¼Œç”¨æˆ·åå’Œå¯†ç  (如果需è¦)。\n使用的 HTTP 代ç†æœåŠ¡å™¨ï¼Œå¿…é¡»æœ‰é€‚åˆ HTTPS 通信的连接方å¼ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeProxyHttp_Args CascadeProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxyHttp_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeProxyHttp_SERVER [主机:端å£çš„å½¢å¼],通过指定的 HTTP 代ç†æœåŠ¡å™¨çš„主机å或 IP 地å€å’Œç«¯å£å·ã€‚
+CMD_CascadeProxyHttp_USERNAME 如果连接到 HTTP 代ç†æœåŠ¡å™¨æ—¶éœ€è¦ç”¨æˆ·éªŒè¯ï¼Œåˆ™æŒ‡å®šç”¨æˆ·å。åŒæ—¶è®¾å®šå¯†ç å’Œå‚数。 如果没有设定用户åå’Œå¯†ç  Då‚数,则ä¸éœ€è¦è®¾ç½®ç”¨æˆ·èº«ä»½éªŒè¯ã€‚
+CMD_CascadeProxyHttp_PASSWORD 如果连接到 HTTP 代ç†æœåŠ¡å™¨æ—¶éœ€è¦ç”¨æˆ·éªŒè¯ï¼Œåˆ™æŒ‡å®šå¯†ç ã€‚/USERNAME,å‚æ•°ç­‰åŒæ—¶è®¾å®šã€‚
+CMD_CascadeProxyHttp_Prompt_Server 代ç†æœåŠ¡å™¨ä¸»æœºå和端å£å·:
+
+
+
+# CascadeProxySocks 命令
+CMD_CascadeProxySocks 将级è”连接方法设定为通过 SOCKS 代ç†æœåŠ¡å™¨
+CMD_CascadeProxySocks_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,设置连接方法为 [通过 SOCKS 代ç†æœåŠ¡å™¨],设置 SOCKS8 代ç†æœåŠ¡å™¨çš„主机å和端å£å·ï¼Œç”¨æˆ·åå’Œå¯†ç  (如果需è¦)。\nSOCKS æœåŠ¡å™¨ï¼Œéœ€ä¸Ž SOCKS 第 4 版想匹é…。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeProxySocks_Args CascadeProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxySocks_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeProxySocks_SERVER 按照 [主机å:端å£å·] çš„æ ¼å¼ï¼Œè®¾å®šä»£ç†æœåŠ¡å™¨ä¸»æœºå或 IP 地å€å’Œç«¯å£å·ã€‚
+CMD_CascadeProxySocks_USERNAME 如果连接到 SOCKS 代ç†æœåŠ¡å™¨æ—¶éœ€è¦ç”¨æˆ·éªŒè¯ï¼Œåˆ™æŒ‡å®šç”¨æˆ·å。åŒæ—¶è®¾å®šå¯†ç å’Œå‚数。如果没有设定用户å和密ç å‚数,则ä¸éœ€è¦è®¾ç½®ç”¨æˆ·èº«ä»½éªŒè¯ã€‚
+CMD_CascadeProxySocks_PASSWORD 如果连接到 SOCKS 代ç†æœåŠ¡å™¨æ—¶éœ€è¦ç”¨æˆ·éªŒè¯ï¼Œåˆ™æŒ‡å®šå¯†ç ã€‚/USERNAME,å‚æ•°ç­‰åŒæ—¶è®¾å®šã€‚
+
+
+# CascadeServerCertEnable 命令
+CMD_CascadeServerCertEnable å¯ç”¨çº§è”æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹
+CMD_CascadeServerCertEnable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,验è¯ç›®æ ‡è¿žæŽ¥çš„ VPN çš„æœåŠ¡å™¨æ供的 SSL è¯ä¹¦æ˜¯å¦å¯ä»¥ä¿¡ä»»ã€‚\n如果å¯ç”¨æ­¤é€‰é¡¹ï¼Œéœ€è¦å°†åœ¨ç›®æ ‡æœåŠ¡å™¨çš„è¯ä¹¦äº‹å…ˆé€šè¿‡ CascadeServerCertSet 指令设置到级è”的连接设置中,或者在虚拟 HUB çš„å¯ä¿¡ä»»è¯ä¹¦åˆ—表中,è¿è¡Œ CAAdd 指令,将有æœåŠ¡å™¨çš„ SSL è¯ä¹¦ç½²å的路线è¯ä¹¦æ·»åŠ è¿›åŽ»ã€‚\n当å¯ç”¨æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹æ—¶ï¼Œå¦‚æžœ VPN Server æ供的è¯ä¹¦ä¸å¯ä¿¡ï¼Œè¿žæŽ¥å°†æ–­å¼€ï¼Œå¹¶é‡è¯•ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeServerCertEnable_Args CascadeServerCertEnable [name]
+CMD_CascadeServerCertEnable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeServerCertDisable 命令
+CMD_CascadeServerCertDisable ç¦ç”¨çº§è”æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹
+CMD_CascadeServerCertDisable_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,对于连接方æ供的 SSL è¯ä¹¦ï¼Œä¸éœ€è¦æ£€æŸ¥æ˜¯å¦å¯ä»¥ä¿¡ä»»ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeServerCertDisable_Args CascadeServerCertDisable [name]
+CMD_CascadeServerCertDisable_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeServerCertSet 命令
+CMD_CascadeServerCertSet 设置级è”连接的æœåŠ¡å™¨ç‰¹å®šè¯ä¹¦
+CMD_CascadeServerCertSet_Help 指定已ç»åœ¨å½“å‰è™šæ‹Ÿ HUB 注册的级è”连接,当此连接和 VPN Server 之间通信时,事先将连接方æ供的 SSL è¯ä¹¦æ³¨å†Œã€‚\n如果å¯ç”¨æ­¤é€‰é¡¹ï¼Œéœ€è¦å°†åœ¨ç›®æ ‡æœåŠ¡å™¨çš„è¯ä¹¦äº‹å…ˆé€šè¿‡æŒ‡ä»¤è®¾ç½®åˆ°çº§è”的连接设置中,或者在虚拟 HUB çš„å¯ä¿¡ä»»è¯ä¹¦åˆ—表中,è¿è¡Œ CAAdd 指令,将有æœåŠ¡å™¨çš„ SSL è¯ä¹¦ç½²å的路线è¯ä¹¦æ·»åŠ è¿›åŽ»ã€‚\n当å¯ç”¨æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹æ—¶ï¼Œå¦‚æžœ VPN Server æ供的è¯ä¹¦ä¸å¯ä¿¡ï¼Œè¿žæŽ¥å°†æ–­å¼€ï¼Œå¹¶é‡è¯•ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeServerCertSet_Args CascadeServerCertSet [name] [/LOADCERT:cert]
+CMD_CascadeServerCertSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeServerCertSet_LOADCERT 设定文件åä¿å­˜æœåŠ¡å™¨å›ºæœ‰çš„ X.509 æ ¼å¼çš„è¯ä¹¦ã€‚
+
+
+# CascadeServerCertDelete 命令
+CMD_CascadeServerCertDelete 删除级è”æœåŠ¡å™¨å›ºæœ‰çš„è¯ä¹¦
+CMD_CascadeServerCertDelete_Help 选定当å‰è™šæ‹Ÿ HUB 中已注册的级è”,如果已ç»æ³¨å†Œäº†æœåŠ¡å™¨è¯ä¹¦ï¼Œå°†å…¶åˆ é™¤ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeServerCertDelete_Args CascadeServerCertDelete [name]
+CMD_CascadeServerCertDelete_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+
+
+# CascadeServerCertGet 命令
+CMD_CascadeServerCertGet 获å–级è”连接æœåŠ¡å™¨çš„固有è¯ä¹¦
+CMD_CascadeServerCertGet_Help 选定在当å‰è™šæ‹Ÿ HUB 上已注册的级è”,如果此级è”中已ç»æ³¨å†Œäº†æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦ï¼Œåˆ™èŽ·å¾—该è¯ä¹¦ï¼Œå¹¶ä¿å­˜ä¸º X.509 æ ¼å¼ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeServerCertGet_Args CascadeServerCertGet [name] [/SAVECERT:path]
+CMD_CascadeServerCertGet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeServerCertGet_SAVECERT 指定å称以 X.509 æ ¼å¼ä¿å­˜æœåŠ¡å™¨çš„固有è¯ä¹¦ã€‚
+
+
+# CascadeDetailSet 命令
+CMD_CascadeDetailSet 级è”通信的高级设置
+CMD_CascadeDetailSet_Help 选定在当å‰è™šæ‹Ÿ HUB 上已注册的级è”,设置级è”å’Œ VPN Server 连接通信时使用的 VPN 自定义的通信å议。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeDetailSet_Args CascadeDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:interval] [/TTL:disconnect_span] [/HALF:yes|no] [/NOQOS:yes|no]
+CMD_CascadeDetailSet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadeDetailSet_MAXTCP VPN 通信中使用的 TCP 连接的数é‡ï¼Œç”¨ä»Ž 1 到 32 çš„æ•´æ•°æ¥æŒ‡å®šã€‚å’Œ VPN Server 之间的 VPN æ•°æ®ä¼ è¾“,å¯ä»¥é€šè¿‡ä½¿ç”¨å¤šä¸ª TCP 连接,æ高通信速度。\n注æ„: 如果您使用高速连接到大约使用 8 根,如果是缓慢的拨å·æœåŠ¡å™¨ï¼Œè¯·ä½¿ç”¨ä¸€æ ¹ã€‚
+CMD_CascadeDetailSet_INTERVAL 如果使用多个 TCP 连接进行 VPN 通信时,请设定å„个 TCP 连接之间确立连接秒数。默认值为 1 秒。
+CMD_CascadeDetailSet_TTL 如果您设置æ¯ä¸ª TCP 连接的寿命,从连接到断开用秒表示。0 表示寿命未设置。
+CMD_CascadeDetailSet_HALF 如果å¯åŠ¨åŠåŒå·¥æ¨¡å¼é€‰æ‹© "yes"。使用两根以上的 VPN 连接进行 TCP 通信时,å¯ä»¥ä½¿ç”¨ "åŠåŒå·¥æ¨¡å¼"。å¯åŠ¨åŠåŒå·¥æ¨¡å¼åŽï¼Œæ¯ä¸ª TCP å¯ä»¥å›ºå®šä¸€åŠè¿žæŽ¥å®žçŽ°å•æ–¹å‘çš„æ•°æ®ä¼ è¾“。例如,使用 8 æ ¹ TCP 连接建立 VPN 通信,使用åŠåŒå·¥æ¨¡å¼åŽï¼Œä¼šæœ‰ 4 è·¯ TCP 连接上船数æ®ï¼Œå‰©ä¸‹çš„ 4 路负责下载数æ®ã€‚
+CMD_CascadeDetailSet_NOQOS ç¦ç”¨ VoIP/ QoS 对应功能选择 "yes"。通常选择 "no"。
+CMD_CascadeDetailSet_Eval_MaxTcp TCP 连接请在 1-32 之间选定。
+CMD_CascadeDetailSet_Eval_Interval TCP 连接之间建立连接的间隔请选定为 1 秒以上。
+CMD_CascadeDetailSet_Prompt_MaxTcp 在 VPN 通信中使用的 TCP 连接数:
+CMD_CascadeDetailSet_Prompt_Interval TCP 连接之间建立连接的间隔:
+CMD_CascadeDetailSet_Prompt_TTL æ¯ä¸€ä¸ª TCP 连接的寿命 (如为 0 则表示没有) :
+CMD_CascadeDetailSet_Prompt_HALF 使用åŠåŒå·¥æ¨¡å¼ (yes/no):
+
+
+# CascadePolicySet 命令
+CMD_CascadePolicySet 设置级è”连接的安全åè®®
+CMD_CascadePolicySet_Help 选定当å‰è™šæ‹Ÿ HUB 上已ç»æ³¨å†Œçš„级è”连接,设置级è”连接建立时所适用的安全å议。\n虚拟 HUB 和别的 VPN Server 进行级è”连接时,连接方的虚拟 HUB 中将产生新的级è”,è¿è¡Œæ­¤å‘½ä»¤å¯ä»¥è®¾ç½®çº§è”的安全å议。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadePolicySet_Args [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_CascadePolicySet_[name] 指定级è”å称æ¥æ”¹å˜è®¾ç½®ã€‚
+CMD_CascadePolicySet_NAME 选定è¦æ›´æ”¹è®¾ç½®çš„åè®®å称。å˜æ›´å议的å称和å¯å˜æ›´çš„值,å¯é€šè¿‡è¿è¡Œ PolicyList 命令获得列表。
+CMD_CascadePolicySet_VALUE 设定å议的新值,如果å议是数值,请设定为一个整数。如果是选择型,请选 yes 或 no。 设定的值å¯ä»¥é€šè¿‡è¿è¡ŒPolicyList命令æ¥èŽ·å¾—。
+CMD_CascadePolicySet_PROMPT_POLNAME 更改值得å议的å称:
+CMD_CascadePolicySet_PROMPT_POLVALUE 设置新值:
+CMD_CascadePolicySet_Invalid_Name 指定的åè®®å称 "%S" 是无效的。\n请è¿è¡Œ PolicyList 命令,您å¯ä»¥èŽ·å–设置å议的清å•ã€‚
+CMD_CascadePolicySet_Invalid_Name_For_Cadcade 指定åè®® "%S" 在设置级è”的安全å议时ä¸å¯ç”¨ã€‚
+CMD_CascadePolicySet_Invalid_Range åè®® "%S" 请在 %s 范围内选定。
+
+
+# PolicyList 命令
+CMD_PolicyList 查看安全å议和å¯ä»¥è®¾ç½®çš„值得列表
+CMD_PolicyList_Help 显示 VPN Server 中的用户,群,级è”的安全å议的项目å称,说明,以åŠå¯ä»¥è®¾å®šçš„值的清å•ã€‚\nä¸æŒ‡å®šä»»ä½•å‚æ•°çš„å‰æ下è¿è¡Œ PolicyList 命令,你å¯ä»¥èŽ·å¾—被支æŒçš„安全å议的å称和说明。\n如果用 PolicyList 指令指定å称,您å¯ä»¥èŽ·å¾—关于这个å议的详细说明,åŠå€¼çš„类型和值的范围。
+CMD_PolicyList_Args PolicyList [name]
+CMD_PolicyList_[name] 选定想è¦æ˜¾ç¤ºçš„åè®®å称。如果没有指定,所有的å称和安全åè®®åŠå…¶è¯´æ˜Žå°†è¢«åˆ—表的支æŒã€‚
+CMD_PolicyList_Invalid_Name 无效的安全åè®®å称。
+CMD_PolicyList_Column_1 åè®®å称
+CMD_PolicyList_Column_2 å议的简å•è§£é‡Š
+CMD_PolicyList_Column_3 设置值
+CMD_PolicyList_Help_1 ç­–ç•¥å称
+CMD_PolicyList_Help_2 å议的简å•è¯´æ˜Ž
+CMD_PolicyList_Help_3 [å¯ä»¥è®¾å®šçš„值的范围]
+CMD_PolicyList_Help_4 默认值
+CMD_PolicyList_Help_5 [å议的详细说明
+CMD_PolicyList_Range_Bool 是 (Yes) 或 å¦ (No)
+CMD_PolicyList_Range_Int_1 %s 以上或 %s 以下 (0 ä¸èƒ½è®¾å®š)
+CMD_PolicyList_Range_Int_2 %s 以上或 %s 以下 (但是,没有指定为 0 则没有设置)
+
+
+# CascadeStatusGet 命令
+CMD_CascadeStatusGet 获å–级è”的当å‰çŠ¶æ€
+CMD_CascadeStatusGet_Help 选定在当å‰è™šæ‹Ÿ HUB 上注册的级è”,如果此级è”处于连线状æ€ï¼Œæ‚¨å°†å¯ä»¥èŽ·å¾—它的连接状æ€å’Œå…¶ä»–ä¿¡æ¯ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeStatusGet_Args CascadeStatusGet [name]
+CMD_CascadeStatusGet_[name] 指定级è”å称,以获å–ä¿¡æ¯ã€‚
+
+
+# CascadeRename 命令
+CMD_CascadeRename 更改级è”çš„å称
+CMD_CascadeRename_Help 选定在当å‰è™šæ‹Ÿ HUB 上注册的级è”,改å˜å®ƒçš„连接å称。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeRename_Args CascadeRename [name] [/NEW:new_name]
+CMD_CascadeRename_[name] 指定è¦å˜æ›´çš„级è”的当å‰å称。
+CMD_CascadeRename_NEW 指定å˜æ›´åŽçš„æ–°å称。
+CMD_CascadeRename_PROMPT_OLD ç›®å‰çš„å称:
+CMD_CascadeRename_PROMPT_NEW æ–°å称:
+
+
+
+# CascadeOnline 命令
+CMD_CascadeOnline 设置级è”接续的在线状æ€
+CMD_CascadeOnline_Help 选定在当å‰è™šæ‹Ÿ HUB 上注册的级è”,将级è”的连接状æ€è®¾å®šä¸ºè¿žæŽ¥ã€‚级è”æˆåŠŸè¿žæŽ¥åŽï¼Œå¯ä»¥é€šè¿‡è¿žæŽ¥è®¾å®šè¿žæŽ¥åˆ° VPN Server。处于在线状æ€çš„级è”,除éžè¿è¡Œ CascadeOffline 脱机命令,则 VPN Server 始终ä¿æŒè¿žæŽ¥ã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeOnline_Args CascadeOnline [name]
+CMD_CascadeOnline_[name] 指定级è”å称设定为è”机状æ€ã€‚
+
+
+# CascadeOffline 命令
+CMD_CascadeOffline 将级è”设置为脱机状æ€
+CMD_CascadeOffline_Help 选定在当å‰è™šæ‹Ÿ HUB 上注册的级è”,将级è”的连接状æ€è®¾å®šä¸ºè„±æœºã€‚处于脱机状æ€çš„级è”,除éžè¿è¡Œ CascadeOnline 命令使它连线,å¦åˆ™æ— æ³•è¿žæŽ¥åˆ° VPN Server。\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_CascadeOffline_Args CascadeOffline [name]
+CMD_CascadeOffline_[name] 指定级è”å称设置到脱机状æ€ã€‚
+
+
+# AccessAdd 命令
+CMD_AccessAdd 添加规则到å…许访问列表 (IPv4)
+CMD_AccessAdd_Help 在当å‰è™šæ‹Ÿ HUB 的访问列表中,添加新的规则。\n访问列表指的是虚拟 HUB 中,对æµåŠ¨çš„æ•°æ®åŒ…进行筛选的规则,访问列表中å¯ä»¥ç™»å½•å¤šæ¡è§„则,æ¯æ¡è§„则å¯ä»¥å®šä¹‰ä¼˜å…ˆé¡ºåºã€‚所有的数æ®åŒ…,按照最åˆé€‚用的æ¡ä»¶ï¼Œæˆ–是通过或是销æ¯ã€‚ä¸ç¬¦åˆä»»ä½•è§„则的数æ®åŒ…则将被默许通过。您也å¯ä»¥ä½¿ç”¨AccessAddEx 命令,æ¥ç”Ÿæˆå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_AccessAdd_Args AccessAdd [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE:established|unestablished]
+CMD_AccessAdd_[pass|discard] 确定数æ®åŒ…跟规则æ¡ä»¶ä¸€è‡´æ—¶çš„处ç†ã€‚当您指定 pass æ„为通过,指定 discard,æ„为销æ¯ã€‚
+CMD_AccessAdd_MEMO 选定规则的解释 (备忘录)。
+CMD_AccessAdd_PRIORITY 用 1 以上的整数指定优先顺åºã€‚数字越å°ä¼˜å…ˆçº§è¶Šé«˜ã€‚
+CMD_AccessAdd_SRCIP 作为规则æ¡ä»¶åˆ¶å®šä¸€ä¸ªæº IPv4 地å€ã€‚用点把å进制数值分开的 IP 地å€/掩ç [æ ¼å¼æŒ‡å®šä¸€ä¸ª IPv4 地å€ï¼Œä¾‹å¦‚ 192.168.0.1 掩ç ä¾‹å¦‚ 255.255.255.0 为åè¿›åˆ¶ï¼Œä»¥ç‚¹åˆ†éš”ï¼Œæˆ–è€…åƒ 24 这样从开始设定字节长度,以åè¿›ä½ã€‚如果设定为 0.0.0.0/0.0.0.0 则显示所有主机。
+CMD_AccessAdd_DESTIP 作为规则的æ¡ä»¶å¿…须制定目标 IPv4 地å€ï¼šç”¨ [IP 地å€/掩ç ]æ ¼å¼åˆ¶å®šæ–¹æ³•åŒæŒ‡å®š /SRCIP å‚数类似。
+CMD_AccessAdd_PROTOCOL æ ¹æ®è§„则的æ¡ä»¶ï¼Œéœ€æŒ‡å®šå议类型。IP åè®®å·æˆ–者输入一个å进制数,或者 "tcp" (TCP/IP å议,第 6 å·),"udp" (UDP/IP å议,第 17 å·),"icmpv4" (ICMPv4 å议,第 1 å·),"icmpv6" (ICMPv6 å议,第 58 å·),"ip" (所有的 IP å议,0 å·) æ¥æŒ‡å®šæ‰€æœ‰ IP å议中的关键字。如果选定所有的 IP å议,则选 0。
+CMD_AccessAdd_SRCPORT åè®® TCP/IP 或 UDP/IP 的情况下,作为规则需指定æºç«¯å£å·ã€‚其他的åè®®ä¸éœ€è¦ã€‚如果该å‚数没有指定,则选定所有端å£ã€‚设定方法,例如 "1-1024" (第 1 到 1024),"23" (åªé€‰ç¬¬ 23 åª)。
+CMD_AccessAdd_DESTPORT åè®® TCP/IP 或 UDP/IP 的情况下,作为规则需指定æºç«¯å£å·ã€‚其他的åè®®ä¸éœ€è¦ã€‚制定方法åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAdd_SRCUSERNAME 作为此规则的æ¡ä»¶ï¼Œåªæœ‰è¢«æŒ‡å®šçš„用户 / 用户組å‘é€çš„æ•°æ®åŒ…,æ‰é€‚用与此规则。在这ç§æƒ…况下,需指定用户å / 用户組å。
+CMD_AccessAdd_DESTUSERNAME 作为此规则的æ¡ä»¶ï¼Œåªæœ‰è¢«æŒ‡å®šçš„用户 / 用户組接å—çš„æ•°æ®åŒ…,æ‰é€‚用与此规则。在这ç§æƒ…况下,需指定用户å / 用户組å。
+CMD_AccessAdd_SRCMAC 作为规则的æ¡ä»¶ï¼ŒæŒ‡å®šå‘é€åŽŸ MAC 地å€ã€‚MAC 地å€åƒä¾‹å­ (00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00) 一样地 '-' 或 '/' æ–­å¼€å六进制数写。段è½æ–‡å­—能çœç•¥ã€‚
+CMD_AccessAdd_DESTMAC 作为规则的æ¡ä»¶ï¼ŒæŒ‡å®šåœ°å€ MAC 地å€ã€‚指定方法,/SRCMAC å‚æ•°åŒæ ·ã€‚
+CMD_AccessAdd_TCPSTATE 作为规则的æ¡ä»¶ï¼ŒæŒ‡å®š TCP 连接的状æ€ã€‚ Established 或指定 Unestablished。
+CMD_AccessAdd_Prompt_TYPE 通过或破å:
+CMD_AccessAdd_Prompt_MEMO 规则的解释 (备忘录):
+CMD_AccessAdd_Prompt_PRIORITY 规则的优先顺åº:
+CMD_AccessAdd_Eval_PRIORITY 请用 1 以上的整数指定优先顺åºã€‚
+CMD_AccessAdd_Prompt_SRCIP å‘ä¿¡æ–¹çš„æº IP åœ°å€ (0.0.0.0/0 则代表所有):
+CMD_AccessAdd_Prompt_DESTIP æ”¶ä¿¡æ–¹çš„æº IP åœ°å€ (0.0.0.0/0 则代表所有):
+CMD_AccessAdd_Prompt_PROTOCOL åè®®å·ç æˆ–åè®®å称 (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd_Prompt_SRCPORT æºç«¯å£èŒƒå›´ (ä»…é™ tcp/udp):
+CMD_AccessAdd_Prompt_DESTPORT 目标端å£å·èŒƒå›´ (ä»…é™ tcp/udp):
+CMD_AccessAdd_Prompt_SRCUSERNAME å‘é€ç”¨æˆ·å (若无指定代表全部):
+CMD_AccessAdd_Prompt_DESTUSERNAME 接收用户å (若无指定代表全部):
+CMD_AccessAdd_Prompt_SRCMAC 由于å‘é€åŽŸ MAC 地å€å’Œé¢ç½© (无指定全部):
+CMD_AccessAdd_Prompt_DESTMAC ç”±äºŽåœ°å€ MAC 地å€å’Œé¢ç½© (无指定全部):
+CMD_AccessAdd_Prompt_TCPSTATE TCP è¿žæŽ¥çš„çŠ¶æ€ (Established/Unestablished):
+
+
+# AccessAddEx 命令
+CMD_AccessAddEx 添加扩展访问列表规则 (IPv4:延迟ã€æ—¶åŸºè¯¯å·®/æ•°æ®åŒ…丢失产生)
+CMD_AccessAddEx_Help 在当å‰ç®¡ç†çš„虚拟 HUB 的访问列表中,使用此命令添加新的规则。当数æ®åŒ…ç»ç”±è™šæ‹Ÿ HUB 通过时,你å¯ä»¥è®¾ç½®äº§ç”Ÿå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。\n访问列表是一组文件规则被应用到æµè¿‡è™šæ‹Ÿ HUB çš„æ•°æ®åŒ…。您å¯ä»¥åœ¨ä¸€ä¸ªè®¿é—®åˆ—表中注册多个规则,你也å¯ä»¥å®šä¹‰æ¯ä¸ªè§„则的优先级。检查所有的数æ®åŒ…的规则所指定的æ¡ä»¶ï¼Œåœ¨è®¿é—®åˆ—表中注册的规则,由第一个匹é…的规则根æ®è§„定的æ“作,它们è¦ä¹ˆé€šè¿‡è¦ä¹ˆè¢«ä¸¢å¼ƒã€‚ä¸åŒ¹é…任何规则的数æ®åŒ…暗中å…许通过。您也å¯ä»¥ä½¿ç”¨ AccessAddEx 的命令æ¥ç”Ÿæˆå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚\n在以æˆå‘˜æœåŠ¡å™¨ç¾¤é›†ä¸Šè¿è¡Œçš„ VPN Server 的虚拟 HUB 上,您ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AccessAddEx_Args AccessAddEx [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/TCPSTATE:established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx_[pass|discard] 当一个数æ®åŒ…匹é…此规则æ¡ä»¶æ—¶ï¼Œè¯¥æ“作就已决定了。当通过被指定时,则数æ®åŒ…å…许通过;当丢弃被指定时,数æ®åŒ…被丢弃。如果动作是通过,延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失的设置被应用。
+CMD_AccessAddEx_MEMO 指定此规则的æè¿° (备忘录)。
+CMD_AccessAddEx_PRIORITY 指定 1 或以上的整数作为此规则的优先级。数字越å°ä¼˜å…ˆçº§è¶Šé«˜ã€‚
+CMD_AccessAddEx_SRCIP æŒ‡å®šä¸€ä¸ªæº IPv4 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚用点把å进制数值分开的 [IP 地å€/掩ç ] æ ¼å¼æŒ‡å®šä¸€ä¸ª IPv4 地å€ï¼Œä¾‹å¦‚: 192.168.0.1。对于掩ç ï¼Œæ‚¨æˆ–者å¯ä»¥æŒ‡å®šç”±ç‚¹åˆ†å¼€çš„å进制数值,例如 255.255.255.0 也å¯ä»¥æŒ‡å®šä»Žæ ‡å¤´ç”¨å进制数值的比特长度,如 24。 如果您指定: 0.0.0.0/0.0.0.0 这表示所有主机。
+CMD_AccessAddEx_DESTIP 用 [IP 地å€/掩ç ] æ ¼å¼æŒ‡å®šä¸€ä¸ªç›®çš„ IPv4 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶æŒ‡å®šæ–¹æ³•åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAddEx_PROTOCOL 指定一个å议类型作为一个规则æ¡ä»¶ã€‚使用å进制数值输入 IP åè®®å·ï¼Œæˆ–者指定关键字中的一个 "tcp" (TCP/IP å议,第 6 å·),"udp" (UDP/IP å议,第 17 å·),"icmpv4" (ICMPv4 å议,第 1 å·),"icmpv6" (ICMPv6 å议,第 58 å·)或者, "ip" (所有的 IP å议,0 å·)。指定数字 0,则规则会应用到全部 IP å议。
+CMD_AccessAddEx_SRCPORT 如果已指定的å议是 TCP/IP 或 UDP/IP çš„è¯ï¼ŒæŒ‡å®šç«¯å£å·çš„目的地作为规则æ¡ä»¶ã€‚其他的å议会被忽略。如果该å‚数没有指定,那么规则会应用到所有端å£å·ã€‚当指定时,请使用如下方法: "1-1024" (第 1 到 1024),"23" (ä»…é™ 23)。
+CMD_AccessAddEx_DESTPORT 如果已指定的å议是 TCP/IP 或 UDP/IP çš„è¯ï¼ŒæŒ‡å®šç›®çš„端å£å·çš„目的地作为规则æ¡ä»¶ã€‚其他å议将被忽略。指定方法åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAddEx_SRCUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯å‘é€çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAddEx_DESTUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯æŽ¥æ”¶çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAddEx_SRCMAC 指定目标 MAC 地å€ä½œä¸ºä¸€ä¸ªè§„则。用'-' 或 '/'分隔符和å六进制数字,如 (00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00) æ¥æŒ‡å®š MAC 地å€ã€‚分隔符å¯è·³è¿‡ã€‚
+CMD_AccessAddEx_DESTMAC 指定目标 MAC 地å€ä½œä¸ºä¸€ä¸ªè§„则。指定方法åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAddEx_TCPSTATE 指定 TCP 连接状æ€ä½œä¸ºä¸€ä¸ªè§„则。使用 Established (已建立的)或 Unestablished(未建立的)。
+CMD_AccessAddEx_DELAY 当数æ®åŒ…通过时,设置此数值æ¥ç”Ÿæˆå»¶è¿Ÿã€‚以毫秒æ¥æŒ‡å®šå»¶è¿Ÿçš„时间段。指定 0,æ„为ä¸ä¼šç”Ÿæˆå»¶è¿Ÿã€‚延迟最多为 10000 毫秒ã€
+CMD_AccessAddEx_JITTER 当数æ®åŒ…通过时,设置此数值æ¥ç”Ÿæˆæ—¶åŸºè¯¯å·®ã€‚用 0% 到 100% 之内的范围æ¥æŒ‡å®šæ—¶åŸºè¯¯å·®æ³¢åŠ¨çš„频率。指定 0,æ„为ä¸ä¼šç”Ÿæˆæ—¶åŸºè¯¯å·®ã€‚
+CMD_AccessAddEx_LOSS 当数æ®åŒ…通过时,设置此数值æ¥ç”Ÿæˆæ•°æ®åŒ…丢失。用 0% 到 100% 之内的范围æ¥æŒ‡å®šä¸¢åŒ…的频率。指定 0,æ„为ä¸ä¼šç”Ÿæˆä¸¢åŒ…。
+CMD_AccessAddEx_Prompt_DELAY 生æˆå»¶è¿Ÿ (毫秒: 0 - 10000):
+CMD_AccessAddEx_Prompt_JITTER 生æˆæ—¶åŸºè¯¯å·®çš„波动(百分比: 0 - 100):
+CMD_AccessAddEx_Prompt_LOSS 丢包率 (百分比: 0 - 100):
+CMD_AccessAddEx_Eval_DELAY 最大延迟为 10000
+CMD_AccessAddEx_Eval_JITTER 最大时基误差的波动为 100
+CMD_AccessAddEx_Eval_LOSS 最大丢包率为 100
+
+
+# AccessAdd6 命令
+CMD_AccessAdd6 添加访问列表规则 (IPv6)
+CMD_AccessAdd6_Help 在当å‰ç®¡ç†çš„虚拟 HUB 的访问列表中,使用此命令添加新的规则。\n访问列表是一组文件规则被应用到æµè¿‡è™šæ‹Ÿ HUB çš„æ•°æ®åŒ…。您å¯ä»¥åœ¨ä¸€ä¸ªè®¿é—®åˆ—表中注册多个规则,你也å¯ä»¥å®šä¹‰æ¯ä¸ªè§„则的优先级。检查所有的数æ®åŒ…的规则所指定的æ¡ä»¶ï¼Œåœ¨è®¿é—®åˆ—表中注册的规则,由第一个匹é…的规则根æ®è§„定的æ“作,它们è¦ä¹ˆé€šè¿‡è¦ä¹ˆè¢«ä¸¢å¼ƒã€‚ä¸åŒ¹é…任何规则的数æ®åŒ…暗中å…许通过。您也å¯ä»¥ä½¿ç”¨ AccessAddEx6 的命令æ¥ç”Ÿæˆå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。 \n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚ \n在以æˆå‘˜æœåŠ¡å™¨ç¾¤é›†ä¸Šè¿è¡Œçš„ VPN Server 的虚拟 HUB 上,您ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AccessAdd6_Args AccessAdd6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished]
+CMD_AccessAdd6_[pass|discard] 当一个数æ®åŒ…匹é…此规则æ¡ä»¶æ—¶ï¼Œè¯¥æ“作就已决定了。当通过被指定时,则数æ®åŒ…å…许通过;当丢弃被指定时,数æ®åŒ…被丢弃。
+CMD_AccessAdd6_MEMO 指定此规则的æ述。 (备忘录)。
+CMD_AccessAdd6_PRIORITY 指定1或以上的整数作为此规的优先级。数字越å°ä¼˜å…ˆçº§è¶Šé«˜ã€‚
+CMD_AccessAdd6_SRCIP æŒ‡å®šä¸€ä¸ªæº IPv6 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚使用冒å·åˆ†å‰²å六进制数字的 [IP 地å€/掩ç ] æ ¼å¼æ¥æŒ‡å®š IPv6 地å€ã€‚例如 2001:200:0:1:: 对于掩ç æ¥è®²ï¼Œæ‚¨æˆ–者å¯ä»¥ä½¿ç”¨å†’å·åˆ†éš”åå…­ä½æ•°å€¼çš„æ ¼å¼ï¼Œä¾‹å¦‚ ffff:ffff:ffff:ffff:: 或者您也å¯ä»¥é€šè¿‡ç”¨æ ‡å¤´çš„åè¿›åˆ¶æ•°å€¼åƒ 128,æ¥æŒ‡å®šæ¯”特长度。如果您è¦æŒ‡å®š "::/0",æ„为所有主机。
+CMD_AccessAdd6_DESTIP 用 [IP 地å€/掩ç ] æ ¼å¼æŒ‡å®šä¸€ä¸ªç›®æ ‡ IPv6 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚制定方法åŒæŒ‡å®š/SRCIPå‚数类似。
+CMD_AccessAdd6_PROTOCOL 指定一个å议类型æ¥ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚输入å进制数值的 IP åè®®å·æˆ–者指定一个关键字 "tcp" (TCP/IP å议,第 6 å·),"udp" (UDP/IP å议,第 17 å·),"icmpv4" (ICMPv4 å议,第 1 å·),"icmpv6" (ICMPv6 å议,第 58 å·),"ip" (所有的 IP å议,0 å·)。指定]0[,则规则会应用于所有IPå议。
+CMD_AccessAdd6_SRCPORT 如果指定的å议是 TCP/IP 或 UDP/IP,则指定æºç«¯å£å·ä½œä¸ºè§„则æ¡ä»¶ã€‚其他å议将被忽略。如果该å‚数没有指定,规则将会应用到所有端å£å·ã€‚指定时,请使用如下方法 "1-1024" (第 1 到 1024),"23" (仅是第 23 )。
+CMD_AccessAdd6_DESTPORT 如果指定的å议是 TCP/IP 或 UDP/IP,则指定目标端å£å·ä½œä¸ºè§„则æ¡ä»¶ã€‚其他å议将被忽略。指定方法åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAdd6_SRCUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯å‘é€çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAdd6_DESTUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯æŽ¥æ”¶çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAdd6_SRCMAC 指定目的 MAC 地å€ä½œä¸ºè§„则。用分隔符 "-" 或者 ":" å’Œå六进制的数字,如 00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00 æ¥æŒ‡å®š MAC 地å€ã€‚分隔符å¯ä»¥è·³è¿‡ã€‚
+CMD_AccessAdd6_DESTMAC 指定目标 MAC 地å€ä½œä¸ºä¸€ä¸ªè§„则。方法与指定 /SRCMAC å‚æ•°åŒæ ·ã€‚
+CMD_AccessAdd6_TCPSTATE 指定 TCP 连接状æ€ä½œä¸ºä¸€ä¸ªè§„则。使用 Established 或 Unestablished。
+CMD_AccessAdd6_Prompt_TYPE 通过或丢弃:
+CMD_AccessAdd6_Prompt_MEMO 规则æè¿° (备忘录):
+CMD_AccessAdd6_Prompt_PRIORITY 规则优先级:
+CMD_AccessAdd6_Eval_PRIORITY 请用 1 或以上的整数指定优先顺åºã€‚
+CMD_AccessAdd6_Prompt_SRCIP æº IPv6 åœ°å€ (::/0 则代表所有):
+CMD_AccessAdd6_Prompt_DESTIP 目标 IPv6 åœ°å€ (::/0 则代表所有):
+CMD_AccessAdd6_Prompt_PROTOCOL åè®®å·æˆ–åè®®å称 (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd6_Prompt_SRCPORT æºç«¯å£å·èŒƒå›´ (ä»…é™ tcp/udp):
+CMD_AccessAdd6_Prompt_DESTPORT 目标端å£å·èŒƒå›´ (ä»…é™ tcp/udp):
+CMD_AccessAdd6_Prompt_SRCUSERNAME æºç”¨æˆ·å (若无指定代表全部):
+CMD_AccessAdd6_Prompt_DESTUSERNAME 目的用户å (若无指定代表全部):
+CMD_AccessAdd6_Prompt_SRCMAC æº MAC 地å€å’ŒæŽ©ç  (若无指定代表全部):
+CMD_AccessAdd6_Prompt_DESTMAC 目标 MAC 地å€å’ŒæŽ©ç  (若无指定代表全部):
+CMD_AccessAdd6_Prompt_TCPSTATE TCP è¿žæŽ¥çš„çŠ¶æ€ (Established/Unestablished):
+
+
+# AccessAddEx6 命令
+CMD_AccessAddEx6 添加扩展访问列表规则 (IPv6,生æˆå»¶è¿Ÿï¼Œæ—¶åŸºè¯¯å·®/æ•°æ®åŒ…丢失)
+CMD_AccessAddEx6_Help 在当å‰ç®¡ç†çš„虚拟 HUB 的访问列表中,使用此命令添加新的规则。当数æ®åŒ…ç»ç”±è™šæ‹Ÿ HUB 通过时,你å¯ä»¥è®¾ç½®äº§ç”Ÿå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。\n访问列表是一组文件规则被应用到æµè¿‡è™šæ‹Ÿ HUB çš„æ•°æ®åŒ…。您å¯ä»¥åœ¨ä¸€ä¸ªè®¿é—®åˆ—表中注册多个规则,你也å¯ä»¥å®šä¹‰æ¯ä¸ªè§„则的优先级。检查所有的数æ®åŒ…的规则所指定的æ¡ä»¶ï¼Œåœ¨è®¿é—®åˆ—表中注册的规则,由第一个匹é…的规则根æ®è§„定的æ“作,它们è¦ä¹ˆé€šè¿‡è¦ä¹ˆè¢«ä¸¢å¼ƒã€‚ä¸åŒ¹é…任何规则的数æ®åŒ…暗中å…许通过。您也å¯ä»¥ä½¿ç”¨ AccessAddEx6 的命令æ¥ç”Ÿæˆå»¶è¿Ÿã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失。 \n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚ \n在以æˆå‘˜æœåŠ¡å™¨ç¾¤é›†ä¸Šè¿è¡Œçš„ VPN Server 的虚拟 HUB 上,您ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AccessAddEx6_Args AccessAddEx6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx6_[pass|discard] 如果通过,会产生延迟,抖动和丢包。当一个数æ®åŒ…匹é…此规则æ¡ä»¶æ—¶ï¼Œè¯¥æ“作就已决定了。当通过被指定时,则数æ®åŒ…å…许通过;当丢弃被指定时,数æ®åŒ…被丢弃。如果动作是通过,延迟ã€æ—¶åŸºè¯¯å·®å’Œæ•°æ®åŒ…丢失的设置被应用。
+CMD_AccessAddEx6_MEMO 指定此规则的æè¿°(备忘录)。
+CMD_AccessAddEx6_PRIORITY 指定1或以上的整数作为此规则的优先级。数字越å°ä¼˜å…ˆçº§è¶Šé«˜ã€‚
+CMD_AccessAddEx6_SRCIP æŒ‡å®šä¸€ä¸ªæº IPv6 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚æŒ‡å®šä¸€ä¸ªæº IPv6 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚对于掩ç æ¥è®²ï¼Œæ‚¨æˆ–者å¯ä»¥ä½¿ç”¨å†’å·åˆ†éš”åå…­ä½æ•°å€¼çš„æ ¼å¼ï¼Œä¾‹å¦‚ "ffff:ffff:ffff:ffff::" 或者您也å¯ä»¥é€šè¿‡ç”¨æ ‡å¤´çš„åè¿›åˆ¶æ•°å€¼åƒ "64",æ¥æŒ‡å®šæ¯”特长度。如果您è¦æŒ‡å®š "::/0",æ„为所有主机。
+CMD_AccessAddEx6_DESTIP 用 [IP 地å€/掩ç ] æ ¼å¼æŒ‡å®šä¸€ä¸ªç›®æ ‡ IPv6 地å€ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚指定方法åŒæŒ‡å®š /SRCIP å‚数类似。
+CMD_AccessAddEx6_PROTOCOL 指定一个å议类型æ¥ä½œä¸ºä¸€ä¸ªè§„则æ¡ä»¶ã€‚输入å进制数值的IP åè®®å·æˆ–者指定一个关键字 "tcp" (TCP/IP å议,第 6 å·),"udp" (UDP/IP å议,第 17 å·),"icmpv4" (ICMPv4 å议,第 1 å·),"icmpv6" (ICMPv6 å议,第 58 å·),"ip" (所有的 IP å议,0 å·)。指定 0,则规则会应用于所有 IP å议。
+CMD_AccessAddEx6_SRCPORT 如果已指定的å议是 TCP/IP 或 UDP/IP çš„è¯ï¼ŒæŒ‡å®šç«¯å£å·çš„目的地作为规则æ¡ä»¶ã€‚其他的å议会被忽略。如果该å‚数没有指定,那么规则会应用到所有端å£å·ã€‚当指定时,请使用如下方法: "1-1024" (第 1 到 1024),"23" (ä»…é™ 23)。
+CMD_AccessAddEx6_DESTPORT 如果指定的å议是 TCP/IP 或 UDP/IP çš„è¯ï¼Œåˆ™æŒ‡å®šç›®æ ‡ç«¯å£å·ä½œä¸ºè§„则æ¡ä»¶ã€‚其他å议会被忽略。如果该å‚数没有指定,指定方法åŒæŒ‡å®š /SRCPORT å‚数一样。
+CMD_AccessAddEx6_SRCUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯å‘é€çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAddEx6_DESTUSERNAME 您å¯ä»¥å°†æ­¤è§„则仅用于作为规则æ¡ä»¶è¢«æŒ‡å®šäº†ç”¨æˆ·å的用户会è¯æŽ¥æ”¶çš„æ•°æ®åŒ…。在这ç§æƒ…况下,请指定该用户å。
+CMD_AccessAddEx6_SRCMAC 指定目标 MAC 地å€ä½œä¸ºè§„则。用分隔符]-[或者]:[å’Œå六进制的数字,如 "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00" æ¥æŒ‡å®š MAC 地å€ã€‚分隔符å¯ä»¥è·³è¿‡ã€‚
+CMD_AccessAddEx6_DESTMAC 指定目标 MAC 地å€ä½œä¸ºä¸€ä¸ªè§„则。方法与指定 /SRCMAC å‚æ•°åŒæ ·ã€‚
+CMD_AccessAddEx6_TCPSTATE 指定 TCP连接状æ€ä½œä¸ºä¸€ä¸ªè§„则。使用已建立的(Established) 或未建立的(Unestablished)。
+CMD_AccessAddEx6_DELAY 当数æ®åŒ…通过时,设置本数值æ¥äº§ç”Ÿå»¶è¿Ÿã€‚以毫秒为å•ä½æ¥æŒ‡å®šå»¶è¿Ÿå‘¨æœŸã€‚指定0,æ„为ä¸äº§ç”Ÿå»¶è¿Ÿã€‚延迟最大为 10000 毫秒。
+CMD_AccessAddEx6_JITTER 当数æ®åŒ…通过时,设置本数值æ¥äº§ç”Ÿæ—¶åŸºè¯¯å·®ã€‚当数æ®åŒ…通过时,设置此数值æ¥ç”Ÿæˆæ—¶åŸºè¯¯å·®ã€‚用 0% 到 100% 之内的范围æ¥æŒ‡å®šæ—¶åŸºè¯¯å·®æ³¢åŠ¨çš„频率。指定 0,æ„为ä¸ä¼šç”Ÿæˆæ—¶åŸºè¯¯å·®ã€‚
+CMD_AccessAddEx6_LOSS 当数æ®åŒ…通过时,设置本数值æ¥äº§ç”Ÿæ•°æ®åŒ…丢失。指定 0% 至 100% æ¥ä½œä¸ºä¸¢åŒ…的比率范围。指定 0,æ„为无丢包生æˆã€‚
+CMD_AccessAddEx6_Prompt_DELAY 生æˆå»¶è¿Ÿ (毫秒: 0 - 10000):
+CMD_AccessAddEx6_Prompt_JITTER 生æˆæ—¶åŸºè¯¯å·®çš„波动 (百分比: 0 - 100):
+CMD_AccessAddEx6_Prompt_LOSS 丢包率 (百分比: 0 - 100):
+CMD_AccessAddEx6_Eval_DELAY 最大延迟为 10000
+CMD_AccessAddEx6_Eval_JITTER 最大时基误差波动为 100
+CMD_AccessAddEx6_Eval_LOSS 最大丢包率为 100
+
+
+# AccessList 命令
+CMD_AccessList 获å–访问列表规则
+CMD_AccessList_Help 获å–当å‰è™šæ‹Ÿ HUB 的访问列表中注册的数æ®åŒ…筛选规则一览表。\n访问列表,å³æ˜¯è™šæ‹Ÿ HUB 内对æµåŠ¨çš„æ•°æ®åŒ…进行筛选的规则的集åˆï¼Œè®¿é—®åˆ—表中å¯ä»¥ç™»å½•å¤šæ¡è§„则,æ¯æ¡è§„则å¯ä»¥å®šä¹‰ä¼˜å…ˆé¡ºåºã€‚通过包过滤规则适用英寸访问列表å¯ä»¥æ³¨å†Œä¸€ä¸ªä»¥ä¸Šçš„规则å¯ä»¥å®šä¹‰ä¸€ä¸ªä¼˜å…ˆè€ƒè™‘æ¯ä¸€æ¡è§„则。所有的数æ®åŒ…,按照最åˆé€‚用的æ¡ä»¶ï¼Œæˆ–是通过或是销æ¯ã€‚ä¸ç¬¦åˆä»»ä½•è§„则的数æ®åŒ…则将被默许通过。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_AccessList_Args AccessList
+
+
+# AccessDelete 命令
+CMD_AccessDelete 从访问列表中删除规则
+CMD_AccessDelete_Help 从当å‰è™šæ‹Ÿ HUB 中注册的访问列表中,选定数æ®åŒ…过滤规则并加以删除。\nè¦åˆ é™¤è§„则,需è¦æŒ‡å®šè¯¥è§„则 ID。ID å¯ä»¥è¿è¡Œ AccessList 获得。\nå¦å¤–ä¸åˆ é™¤è€Œæ˜¯æš‚æ—¶ç¦ç”¨çš„规则执行 AccessDisable 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_AccessDelete_Args AccessDelete [id]
+CMD_AccessDelete_[id] 指定è¦åˆ é™¤çš„规则的 ID 或唯一 ID。
+CMD_Access_Prompt_ID 访问列表规则 ID 或唯一 ID:
+
+
+# AccessEnable 命令
+CMD_AccessEnable å¯ç”¨è®¿é—®åˆ—表规则功能
+CMD_AccessEnable_Help 从当å‰è™šæ‹Ÿ HUB 中注册的访问列表中,选定数æ®åŒ…筛选规则并激活。激活的规则用于数æ®åŒ…筛选。\nè¦å¯ç”¨è¯¥è§„则,必须指定它的 ID。您å¯ä»¥ä½¿ç”¨ AccessList å‘½ä»¤èŽ·å– ID。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_AccessEnable_Args AccessEnable [id]
+CMD_AccessEnable_[id] 指定规则的 ID 并激活。
+
+
+# AccessDisable 命令
+CMD_AccessDisable ç¦ç”¨è®¿é—®åˆ—表规则
+CMD_AccessDisable_Help 从当å‰è™šæ‹Ÿ HUB 中注册的访问列表中,选定数æ®åŒ…筛选规则并ç¦ç”¨ã€‚被ç¦ç”¨çš„筛选规则将ä¸ä¼šè¢«ç”¨äºŽæ•°æ®åŒ…筛选。\nè¦ç¦ç”¨çš„规则,规则必须指定的 ID。\nè¦ç¦ç”¨è¯¥è§„则,必须指定它的 ID。您å¯ä»¥ä½¿ç”¨ AccessList å‘½ä»¤èŽ·å– ID。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_AccessDisable_Args AccessDisable [id]
+CMD_AccessDisable_[id] 指定规则的 ID 并ç¦ç”¨ã€‚
+
+
+# UserList 命令
+CMD_UserList 获å–用户列表
+CMD_UserList_Help 获å–当å‰è™šæ‹Ÿ HUB 中注册的安全å¸æˆ·æ•°æ®åº“ä¿¡æ¯ä¸­çš„用户清å•ã€‚\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserList_Args UserList
+
+
+# UserCreate 命令
+CMD_UserCreate 创建用户
+CMD_UserCreate_Help 在当å‰è™šæ‹Ÿ HUB 中注册的安全å¸æˆ·æ•°æ®åº“中创建一个新用户。\n当您创建一个用户,根æ®ç”¨æˆ·ä¿¡æ¯çš„认è¯ï¼ŒVPN Client å¯ä»¥è¿žæŽ¥åˆ°è¿™ä¸ªè™šæ‹Ÿ HUB。\n如果您使用 UserCreate 命令创建一个用户,用户身份验è¯æ–¹æ³•æ˜¯éªŒè¯å¯†ç ï¼Œæ³¨å†Œä¸ºä¸€ä¸ªéšæœºå­—符串作为密ç åˆ†é…。因此,用户ä¸èƒ½ç›´æŽ¥è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB。在创建用户åŽï¼Œåˆ™å¿…é¡»è¿ç”¨ UserPasswordSet 命令,设定指定用户的密ç ã€‚或者使用 UserAnonymousSet 命令,UserCertSet 命令,UserSignedSet 命令,UserRadiusSet 命令,UserNTLMSet 命令æ¥æ”¹å˜ç”¨æˆ·èº«ä»½éªŒè¯æ–¹å¼ã€‚\n除éžçœŸæœ‰ç”¨æˆ·å为 "*" (星å·),å¦åˆ™å½“客户登陆时æ供的用户å与已有用户åä¸ä¸€è‡´çš„情况下,将自动登录为 RADIUS æœåŠ¡å™¨ï¼Œæˆ–者 NT 控制器æ¥éªŒè¯ã€‚\n如果è¦æ›´æ”¹ç”¨æˆ·ä¿¡æ¯ï¼Œå¯ä»¥æ‰§è¡Œ UserSet 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserCreate_Args UserCreate [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserCreate_[name] 指定新创建用户的用户å。
+CMD_UserCreate_GROUP 如果让用户加入一个用户组,请指定组å。如果你让用户ä¸å±žäºŽä»»ä½•ç»„,则设定为 /GROUP:none。
+CMD_UserCreate_REALNAME 指定用户的全å。如果ä¸æŒ‡å®šï¼Œè¯·é€‰ /REALNAME:none。
+CMD_UserCreate_NOTE 指定该用户的说明。å¦åˆ™ï¼Œé€‰æ‹© /NOTE:none。
+CMD_UserCreate_Prompt_NAME 用户å:
+CMD_UserCreate_Prompt_GROUP 加入群组å称:
+CMD_UserCreate_Prompt_REALNAME 用户全å:
+CMD_UserCreate_Prompt_NOTE 用户æè¿°:
+
+
+# UserSet 命令
+CMD_UserSet 更改用户信æ¯
+CMD_UserSet_Help å˜æ›´å½“å‰è™šæ‹Ÿ HUB 中的安全å¸æˆ·æ•°æ®åº“中注册的客户信æ¯ã€‚\nå¯ä»¥æ›´æ”¹çš„ä¿¡æ¯ï¼Œå³ä½¿åˆ›å»ºæ–°ç”¨æˆ·æ‰€éœ€è¦çš„ "组å称","å…¨å" å’Œ "æè¿°" 这三个项目。\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserSet_Args UserSet [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserSet_[name] 指定用户å更改设置。
+CMD_UserSet_GROUP 如果让用户加入一个用户组,请指定组å。如果你让用户ä¸å±žäºŽä»»ä½•ç»„,则设定为 /GROUP:none。
+CMD_UserSet_REALNAME 指定用户的全å。如果ä¸æŒ‡å®šï¼Œè¯·é€‰ /REALNAME:none。
+CMD_UserSet_NOTE 指定该用户的说明。å¦åˆ™ï¼Œé€‰æ‹© /NOTE:none
+
+
+# UserDelete 命令
+CMD_UserDelete 删除用户
+CMD_UserDelete_Help 删除在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册的用户。当你删除一个用户,该用户将无法连接到虚拟 HUB。\n如果您使用 UserPolicySet 命令,å³ä½¿ä¸åˆ é™¤ä¹Ÿå¯æš‚æ—¶ç¦æ­¢ç”¨æˆ·ç™»å½•ã€‚\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserDelete_Args UserDelete [name]
+CMD_UserDelete_[name] 指定用户å将其删除。
+
+
+# UserGet 命令
+CMD_UserGet 获å–用户信æ¯
+CMD_UserGet_Help 获å–在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册用户的登录信æ¯ã€‚\n这个指令å¯ä»¥å¾—到的信æ¯æœ‰ "用户å","å…¨å","æè¿°","组的æˆå‘˜","有效期","安全åè®®","身份验è¯æ–¹æ³•",以åŠéªŒè¯å‚数。\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserGet_Args UserGet [name]
+CMD_UserGet_[name] 指定的用户åæ¥èŽ·å–ä¿¡æ¯ã€‚
+CMD_UserGet_Column_Name 用户å
+CMD_UserGet_Column_RealName å…¨å
+CMD_UserGet_Column_Note æè¿°
+CMD_UserGet_Column_Group 组å称
+CMD_UserGet_Column_Expires 有效期
+CMD_UserGet_Column_AuthType 验è¯æ–¹æ³•
+CMD_UserGet_Column_UserCert 已注册的用户固有的è¯ä¹¦
+CMD_UserGet_Column_RadiusAlias 外部认è¯æœåŠ¡å™¨éªŒè¯ç”¨æˆ·å
+CMD_UserGet_Column_RootCert_CN è¯ä¹¦çš„ CN 值得é™å®š
+CMD_UserGet_Column_RootCert_SERIAL è¯ä¹¦çš„åºåˆ—å·çš„é™å®š
+CMD_UserGet_Policy 该用户设定的安全åè®®
+
+
+# UserAnonymousSet 命令
+CMD_UserAnonymousSet 将用户身份验è¯æ–¹æ³•è®¾ç½®ä¸ºåŒ¿å验è¯
+CMD_UserAnonymousSet_Help 在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册用户的验è¯æ–¹æ³•è®¾å®šä¸º "匿å验è¯"。"匿å验è¯" 的用户连接到 VPN Client HUB 时,ä¸ä¼šæœ‰ä»»ä½•ç”¨æˆ·è®¤è¯å³å¯ä»¥è¿žæŽ¥åˆ° HUB。匿å身份验è¯è®¾ç½®é€‚åˆé‚£äº›å…¬å¼€çš„è°éƒ½å¯ä»¥è¿žæŽ¥çš„ VPN Server。\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserAnonymousSet_Args UserAnonymousSet [name]
+CMD_UserAnonymousSet_[name] 指定用户å更改设置。
+
+
+# UserPasswordSet 命令
+CMD_UserPasswordSet 将用户身份验è¯æ–¹æ³•è®¾ç½®ä¸ºå¯†ç éªŒè¯ï¼Œå¹¶è®¾å®šå¯†ç 
+CMD_UserPasswordSet_Help 在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册用户的验è¯æ–¹æ³•è®¾å®šä¸º "密ç éªŒè¯" 所谓 "密ç éªŒè¯" å³æ‰€æœ‰å®‰å…¨å¸æˆ·æ•°æ®åº“中的用户都设置密ç æ³¨å†Œã€‚当此用户连接虚拟 HUB 时,会æ示输入密ç ï¼Œå¦‚果一致,则å…许连接。\n事实上,由于用户的密ç æ˜¯ç»è¿‡å¤„ç†ä»¥åŽä¿å­˜çš„,因此å³ä½¿åˆ†æžåŽŸå§‹æ料,也ä¸ä¼šåˆ†æžå‡ºå¯†ç ã€‚\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserPasswordSet_Args UserPasswordSet [name] [/PASSWORD:password]
+CMD_UserPasswordSet_[name] 指定用户å更改设置。
+CMD_UserPasswordSet_PASSWORD 指定用户的密ç è®¾ç½®ã€‚如果您ä¸æŒ‡å®šæ­¤å‚数将被æ示输入密ç ã€‚
+
+
+# UserCertSet 命令
+CMD_UserCertSet 将用户身份验è¯æ–¹æ³•è®¾ç½®ä¸ºå›ºæœ‰è¯ä¹¦éªŒè¯ï¼Œå¹¶è®¾å®šè¯ä¹¦
+CMD_UserCertSet_Help 在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册用户的验è¯æ–¹æ³•è®¾å®šä¸º "固有è¯ä¹¦éªŒè¯" 所谓 "固有è¯ä¹¦éªŒè¯" å³æ‰€æœ‰å®‰å…¨å¸æˆ·æ•°æ®åº“中的用户都注册一个 X.509 è¯ä¹¦ã€‚当此用户连接虚拟 HUB 时,æ供的固有è¯ä¹¦ä¸Žç™»è®°è¯ä¹¦ä¸€è‡´ï¼Œæˆ–æŒæœ‰å¯¹åº”è¯ä¹¦çš„密钥,å…许是通过验è¯å®žçŽ°è¿žæŽ¥ã€‚\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserCertSet_Args UserCertSet [name] [/LOADCERT:cert]
+CMD_UserCertSet_[name] 指定的用户å更改设置。
+CMD_UserCertSet_LOADCERT 指定 X.509 è¯ä¹¦æ–‡ä»¶å,这顶用户è¯ä¹¦ã€‚
+
+
+# UserCertGet 命令
+CMD_UserCertGet 获å–注册固有è¯ä¹¦è®¤è¯ç”¨æˆ·çš„è¯ä¹¦
+CMD_UserCertGet_Help 在虚拟 HUB 中的安全å¸æˆ·æ•°æ®åº“中注册用户的 "固有è¯ä¹¦è®¤è¯" 的用户,å–得用户的 X.509 è¯ä¹¦ï¼Œå¹¶ä¿å­˜ã€‚\n如果用户未指定 "固有è¯ä¹¦è®¤è¯",则会å‘生错误。\nè¦èŽ·å¾—用户的åå•ï¼Œè¯·ä½¿ç”¨ UserList 命令。\n此命令,在 VPN Bridge 中ä¸ä¼šè¿è¡Œã€‚\n此命令在集群虚拟 HUB 中ä¸èƒ½è¿è¡Œã€‚
+CMD_UserCertGet_Args UserCertGet [name] [/SAVECERT:cert]
+CMD_UserCertGet_[name] 指定的用户åæ¥æ£€ç´¢ä¿¡æ¯ã€‚
+CMD_UserCertGet_SAVECERT 指定文件åæ¥ä¿å­˜èŽ·å–的用户的 X.509 è¯ä¹¦ã€‚
+CMD_UserCertGet_Not_Cert 或者éžå›ºå®šè¯ä¹¦è®¤è¯ï¼Œæˆ–者为设定为固有è¯ä¹¦éªŒè¯ã€‚
+
+
+# UserSignedSet 命令
+CMD_UserSignedSet 将用户身份验è¯æ–¹æ³•è®¾ç½®ä¸ºå·²ç­¾åè¯æ˜Žä¹¦è®¤è¯
+CMD_UserSignedSet_Help 将已注册在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“的用户认è¯æ–¹æ³•è®¾å®šä¸ºå·²ç­¾å认è¯ä¹¦è®¤è¯ã€‚用户以已签åè¯æ˜Žä¹¦è®¤è¯çš„用户å链接虚拟 HUB 时,用户所æ交的è¯æ˜Žä¹¦ä¼šè¢«éªŒè¯æ˜¯å¦ä¸ºè™šæ‹Ÿ HUB 认å¯çš„è¯æ˜Žæœºæž„çš„è¯æ˜Žä¹¦ä¸€è§ˆä¸­ä»»æ„è¯æ˜Žä¹¦çš„ç­¾å,且客户是å¦æŒæœ‰ä¸Žè¯ä¹¦ç›¸åº”的密钥,用 RSA 算法验è¯å¯ä»¥é“¾æŽ¥çš„认è¯æ³•ã€‚/n还å¯ä»¥è®¾å®šæˆå·²æ³¨å†Œç”¨æˆ·å¸Œæœ›çš„è¯æ˜Žä¹¦çš„通用å (CN) åŠç¼–å·ï¼Œåªæœ‰é€šè¿‡äº†ä¸Šè¿°éªŒè¯çš„è¯æ˜Žä¹¦çš„内容与设定值一致的情况下æ‰èƒ½è®¸å¯é“¾æŽ¥ã€‚/nè¦å–å¾—ç›®å‰æ³¨å†Œç”¨æˆ·ä¸€è§ˆï¼Œè¯·ä½¿ç”¨ç”¨æˆ·åå•æŒ‡ä»¤ã€‚\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚ \n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserSignedSet_Args UserSignedSet [name] [/CN:cn] [/SERIAL:serial]
+CMD_UserSignedSet_[name] 指定更改设定的用户å
+CMD_UserSignedSet_CN 如果指定此å‚数,在验è¯äº†ç”¨æˆ·æ交的è¯æ˜Žä¹¦æ˜¯å¦ç”±å¯ä¿¡èµ–çš„è¯æ˜Žæœºæž„ç­¾ååŽï¼Œè¯¥è¯æ˜Žä¹¦çš„通用å (CN) 的值,与根æ®æ­¤å‚数设定的值相比较,åªæœ‰å–得一致的情况下æ‰å…许链接。指定 "none" 的情况下ä¸è¿›è¡Œç¡®è®¤ã€‚
+CMD_UserSignedSet_SERIAL 如果指定此å‚数,在验è¯äº†ç”¨æˆ·æ交的è¯æ˜Žä¹¦æ˜¯å¦ç”±å¯ä¿¡èµ–çš„è¯æ˜Žæœºæž„ç­¾ååŽï¼Œè¯¥è¯æ˜Žä¹¦çš„åºåˆ—å·çš„值,与根æ®æ­¤å‚数设定的值相比较,åªæœ‰å–得一致的情况下æ‰å…许链接。指定 "none" 的情况下ä¸è¿›è¡Œç¡®è®¤ã€‚
+CMD_UserSignedSet_Prompt_CN é™å®šé€šç”¨å (CN) 的值
+CMD_UserSignedSet_Prompt_SERIAL é™å®šç¼–å·çš„值
+
+
+# UserRadiusSet 命令
+CMD_UserRadiusSet 将用户的认è¯æ–¹æ³•è®¾å®šä¸ºåŠå¾„认è¯
+CMD_UserRadiusSet_Help 将在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“上注册的用户认è¯æ–¹æ³•è®¾ç½®ä¸º "åŠå¾„认è¯"。用户以被åŠå¾„认è¯è®¾ç½®çš„用户å连接虚拟 HUB 时,用户å和用户输入的密ç è¢«å‘é€åˆ°åŠå¾„æœåŠ¡å™¨ï¼ŒåŠå¾„æœåŠ¡å™¨æ£€æŸ¥ç”¨æˆ·å和密ç åŽï¼Œå¦‚过该认è¯æˆåŠŸï¼Œç”¨æˆ·è¢«å…许 VPN 连接。\nè¦ä½¿ç”¨åŠå¾„认è¯ï¼Œéœ€è¦äº‹å…ˆä½¿ç”¨ RadiusServerSet 指令把è¦ä½¿ç”¨çš„åŠå¾„æœåŠ¡å™¨è®¾ç½®ä¸ºè™šæ‹Ÿ HUB。\nè¦èŽ·å¾—ç›®å‰æ³¨å†Œçš„用户列表,请使用 UserList 指令。\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserRadiusSet_Args UserRadiusSet [name] [/ALIAS:alias_name]
+CMD_UserRadiusSet_[name] 指定更改设定的用户å
+CMD_UserRadiusSet_ALIAS 如果此å‚数被设置,å¯ä»¥ä½¿å¯¹åŠå¾„æœåŠ¡å™¨å‘é€çš„用户å与虚拟 HUB 上的用户å是ä¸åŒçš„。如果没有设置,请指定为 /ALIAS:none (使用虚拟 HUB 上的用户å)。用户å是 "*" 的情况下 /ALIAS å‚数被忽略。关于 "*" 用户的æ述,输入 UserCreate /HELP å¯æ˜¾ç¤ºã€‚
+CMD_UserRadiusSet_Prompt_ALIAS 验è¯ç”¨åˆ«å (å¯é€‰)
+
+
+# UserNTLMSet 命令
+CMD_UserNTLMSet 用户身份验è¯æ–¹æ³•è®¾ç½®ä¸º NT 域认è¯
+CMD_UserNTLMSet_Help 将在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“上注册的用户认è¯æ–¹æ³•è®¾ç½®ä¸º "NT 域验è¯"。用户以被 NT 域认è¯è®¾ç½®çš„用户å连接虚拟 HUB 时,用户å和用户输入的密ç è¢«å‘é€åˆ° Windows NT / 2000 / Server 2003 / Server 2008 域控制器或 Active Directory æœåŠ¡å™¨ï¼Œè®¤è¯æœåŠ¡å™¨æ£€æŸ¥ç”¨æˆ·å和密ç åŽï¼Œå¦‚果认è¯æˆåŠŸåŽï¼Œè¯¥ç”¨æˆ·çš„ VPN 连接被å…许。è¦ä½¿ç”¨ NT 域认è¯ï¼ŒVPN Server ä¸è¦åœ¨è¿žæŽ¥åˆ°è¯¥åŸŸçš„ Windows NT 4.0,Windows 2000,Windows XP,Windows Server 2003 å’Œ Windows Server 2008 的任何æ“作系统上è¿è¡Œã€‚详情,请与 VPN Server 管ç†å‘˜å’¨è¯¢ã€‚\nè¦èŽ·å¾—ç›®å‰æ³¨å†Œçš„用户列表,请使用 UserList 指令。\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserNTLMSet_Args UserNTLMSet [name] [/ALIAS:alias_name]
+CMD_UserNTLMSet_[name] 指定更改设定的用户å
+CMD_UserNTLMSet_ALIAS 如果此å‚数被设置,å¯ä»¥ä½¿å¯¹ NT 域或 Active Directory å‘é€çš„用户å与虚拟 HUB 上的用户åä¸åŒã€‚如果没有设置,请指定 /ALIAS:none (使用虚拟 HUB 上的用户å)。用户å是 "*" 的情况下 /ALIAS å‚数被忽略。关于 "*" 用户的æ述,输入 UserCreate /HELP å¯æ˜¾ç¤ºã€‚
+
+
+# UserPolicyRemove 命令
+CMD_UserPolicyRemove 删除用户的安全策略
+CMD_UserPolicyRemove_Help 删除在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“上已注册的用户设置的安全策略设置。被删除安全策略设置的用户,适用该用户所属的组的安全策略设置。如果ä¸å±žäºŽä»»ä½•ç»„,或改组没有设置安全策略,则éµä»Žé»˜è®¤å€¼ (å…许访问: å¯ç”¨ï¼ŒTCP连接数最大值: 32 个,超时时间: 20 秒)。\nè¦èŽ·å¾—ç›®å‰æ³¨å†Œçš„用户列表,请使用 UserList 命令。\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚ \n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserPolicyRemove_Args UserPolicyRemove [name]
+CMD_UserPolicyRemove_[name] 指定更改设定的用户å
+
+
+# UserPolicySet 命令
+CMD_UserPolicySet 设置用户的安全策略
+CMD_UserPolicySet_Help å˜æ›´åœ¨ç›®å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“上已注册的用户设置的安全策略内容。\n当用户未设置安全策略时,设置新的默认安全策略åŽï¼Œæ›´æ”¹è¢«æŒ‡å®šçš„值。\nè¦èŽ·å¾—当å‰å·²æ³¨å†Œçš„用户列表,请使用 UserList 指令。\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserPolicySet_Args UserPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_UserPolicySet_[name] 指定更改设定的用户å
+CMD_UserPolicySet_NAME 指定è¦å˜æ›´å€¼çš„策略的å称。您å¯ä»¥ä½¿ç”¨ PolicyList 命令显示策略å称和å¯è®¾å®šå€¼çš„列表。
+CMD_UserPolicySet_VALUE 指定策略的新值。如果其策略是数值型,指定整数。如果是布尔型,指定 "yes" 或 "no"。å¯ä»¥è®¾å®šçš„类型和值,å¯ä»¥ä½¿ç”¨ PolicyList 指令显示。
+
+
+# UserExpiresSet 命令
+CMD_UserExpiresSet 设置用户的有效期é™
+CMD_UserExpiresSet_Help 设置在目å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“中注册的用户的有效期é™ã€‚有效期é™åˆ°æœŸçš„用户ä¸èƒ½è¿žæŽ¥è™šæ‹Ÿ HUB。\nè¦èŽ·å¾—当å‰å·²æ³¨å†Œçš„用户列表,请使用 UserList 指令。\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n此指令令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_UserExpiresSet_Args UserExpiresSet [name] [/EXPIRES:expires]
+CMD_UserExpiresSet_[name] 指定更改设定的用户å
+CMD_UserExpiresSet_EXPIRES 指定用户有效期é™çš„日期和时间。如 "2005/10/08 19:30:00",以 6 个整数指定年,月,日,时,分,秒,用斜线或冒å·åˆ†éš”。年指定为 4 ä½æ•°ã€‚如果把空格加入到值中,需è¦æŠŠæ•´ä¸ªå€¼ç”¨ "" å›´ä½ã€‚å¯ä»¥æŒ‡å®šæœ¬åœ°æ—¶é—´ (计算机上的命令行管ç†å·¥å…·è¿è¡Œçš„标准时间)。如果指定 /EXPIRES:none,å¯ä»¥è§£é™¤æœ‰æ•ˆæœŸé™ã€‚
+CMD_UserExpiresSet_Prompt_EXPIRES ç”¨æˆ·çš„æœ‰æ•ˆæœŸé™ (没有指定,å³æ²¡æœ‰æœŸé™):
+
+
+# GroupList 命令
+CMD_GroupList 获å–组列表
+CMD_GroupList_Help 获å–在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“中注册的组列表。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupList_Args GroupList
+
+
+# GroupCreate 命令
+CMD_GroupCreate 创建组
+CMD_GroupCreate_Help 在目å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“内建立新组。\n在组内å¯ä»¥ç™»è®°å¤šä¸ªç”¨æˆ·ã€‚è¦åœ¨ç»„内注册用户,使用 GroupJoin 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupCreate_Args GroupCreate [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupCreate_[name] 指定è¦åˆ›å»ºçš„组å。
+CMD_GroupCreate_REALNAME 指定该组的全å。例如,如果组对应于实际的部分或部门å称,指定其å称。如果ä¸æŒ‡å®šçš„情况下,请指定 /REALNAME:none。
+CMD_GroupCreate_NOTE 指定组的æ述。如果ä¸æŒ‡å®šçš„情况下,请指定 /NOTE:none。
+CMD_GroupCreate_Prompt_NAME 组å称:
+CMD_GroupCreate_Prompt_REALNAME 组的全å:
+CMD_GroupCreate_Prompt_NOTE 组æè¿°:
+
+
+# GroupSet 命令
+CMD_GroupSet 设置组信æ¯
+CMD_GroupSet_Help 设置在目å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“中注册的组信æ¯ã€‚\nè¦èŽ·å–当å‰å·²æ³¨å†Œçš„组列表,请使用 GroupList 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupSet_Args GroupSet [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupSet_[name] 指定å˜æ›´è®¾å®šçš„组å。
+CMD_GroupSet_REALNAME 指定该组的全å。例如,如果组对应于实际的部分或部门å称,指定其å称。如果ä¸æŒ‡å®šçš„情况下,请指定 /REALNAME:none。
+CMD_GroupSet_NOTE 指定组的æ述。如果ä¸æŒ‡å®šçš„情况下,请指定 /NOTE:none。
+
+
+# GroupDelete 命令
+CMD_GroupDelete 删除组
+CMD_GroupDelete_Help 删除目å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“中注册的组。\n一旦删除组,该组所属的所有用户将æˆä¸ºæœªåˆ†é…的。\nè¦èŽ·å–当å‰å·²æ³¨å†Œçš„组列表,请使用 GroupList 命令。\n此命令ä¸èƒ½è¿è¡Œçš„ VPN Bridge。\n您ä¸èƒ½æ‰§è¡Œè¿™ä¸ªè™šæ‹Ÿçš„ VPN 作为在群集æˆå‘˜æœåŠ¡å™¨æ“作系统æœåŠ¡å™¨èŠ±é¼“命令。
+CMD_GroupDelete_Args GroupDelete [name]
+CMD_GroupDelete_[name] 指定删除的组å。
+
+
+# GroupGet 命令
+CMD_GroupGet 获得组信æ¯å’Œæ‰€å±žç”¨æˆ·åˆ—表
+CMD_GroupGet_Help 获å–ç›®å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“中注册的组信æ¯å’Œå±žäºŽæ”¹ç»„的用户列表。\nè¦èŽ·å–当å‰å·²æ³¨å†Œçš„组列表,请使用 GroupList 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupGet_Args GroupGet [name]
+CMD_GroupGet_[name] 指定获得信æ¯çš„组å。
+CMD_GroupGet_Column_NAME 组å
+CMD_GroupGet_Column_REALNAME å…¨å
+CMD_GroupGet_Column_NOTE æè¿°
+CMD_GroupGet_Column_POLICY 这个组所设定的安全测略
+CMD_GroupGet_Column_MEMBERS 属于这个组的用户å列表
+
+
+# GroupJoin 命令
+CMD_GroupJoin 用户添加到组
+CMD_GroupJoin_Help 在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®åº“注册的组内,添加安全å¸æˆ·æ•°æ®åº“内的用户。\nç›®å‰æ³¨å†Œçš„用户和组的列表,å¯ä½¿ç”¨ UserList 命令和 GroupList 命令获å–。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupJoin_Args GroupJoin [name] [/USERNAME:username]
+CMD_GroupJoin_[name] 指定è¦æ·»åŠ ç”¨æˆ·çš„组å。
+CMD_GroupJoin_USERNAME 指定往以 name 指定了的组添加的用户å。
+CMD_GroupJoin_Prompt_USERNAME è¦åŠ å…¥ç»„的用户å:
+
+
+# GroupUnjoin 命令
+CMD_GroupUnjoin 从组内删除用户
+CMD_GroupUnjoin_Help 从目å‰ç®¡ç†çš„虚拟 HUB 安全å¸æˆ·æ•°æ®åº“注册的组中,删除指定用户。用户一旦从组中被删除,该用户æˆä¸ºæœªåˆ†é…。\nè¦èŽ·å–当å‰ç»„的用户列表,使用 GroupGet 命令。\nè¦èŽ·å–当å‰å·²æ³¨å†Œçš„组列表,使用 GroupList 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupUnjoin_Args GroupUnjoin [name]
+CMD_GroupUnjoin_[name] 指定è¦ä»Žç»„内删除的用户å。
+CMD_GroupUnjoin_Prompt_name è¦ä»Žç»„内删除的用户å:
+
+
+# GroupPolicyRemove 命令
+CMD_GroupPolicyRemove 删除组的安全策略
+CMD_GroupPolicyRemove_Help 对在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®èƒ¡ä¸­æ³¨å†Œçš„组,删除其被设置的安全策略的设置。对所属的组åŠç”¨æˆ·æœ¬èº«æ²¡æœ‰è¢«è®¾ç½®å®‰å…¨ç­–略的用户,éµç…§é»˜è®¤å€¼ (å…许访问: å¯ç”¨ï¼ŒTCP 连接数的最大值: 32 个,超时时间: 20 秒)。\nè¦èŽ·å¾—当å‰å·²æ³¨å†Œçš„组列表,使用 GroupList 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupPolicyRemove_Args GroupPolicyRemove [name]
+CMD_GroupPolicyRemove_[name] 指定å˜æ›´è®¾å®šçš„组å。
+
+
+# GroupPolicySet 命令
+CMD_GroupPolicySet 设置组的安全策略
+CMD_GroupPolicySet_Help 对在目å‰ç®¡ç†çš„虚拟 HUB 的安全å¸æˆ·æ•°æ®èƒ¡ä¸­æ³¨å†Œçš„组,更改其被设置的安全策略的设置。\n如组尚未设置安全策略,新的默认安全策略设置åŽï¼Œæ›´æ”¹è¢«æŒ‡å®šçš„值。\nè¦èŽ·å¾—当å‰å·²æ³¨å†Œçš„组列表,使用 GroupList 命令。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_GroupPolicySet_Args GroupPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_GroupPolicySet_[name] 指定å˜æ›´è®¾å®šçš„组å。
+CMD_GroupPolicySet_NAME 指定è¦æ›´æ”¹å…¶å€¼çš„ç­–ç•¥å称。您å¯ä»¥ä½¿ç”¨ PolicyList 命令显示的策略å称和å¯ä»¥è®¾ç½®å€¼çš„列表。
+CMD_GroupPolicySet_VALUE 指定一个新的策略值。如果策略是数值型的情况下,指定一个整数。如果是布尔型的情况下,指定 "yes" 或 "no"。å¯ä»¥è®¾å®šç±»åž‹å’Œå€¼ï¼Œå¯ä»¥ä½¿ç”¨ PolicyList 指令显示。
+
+
+# SessionList 命令
+CMD_SessionList 获å–连接会è¯çš„列表
+CMD_SessionList_Help 获å–ç›®å‰ç®¡ç†çš„与虚拟 HUB 连接中的的会è¯åˆ—表。在会è¯åˆ—表中,以下信æ¯å°†æ˜¾ç¤ºä¸ºæ¯ä¸ªè¿žæŽ¥: [会è¯å称],[会è¯åœºæ‰€],[用户å],[连接æºä¸»æœºå称],[TCP 连接],[传输字节数] å’Œ [传输数æ®åŒ…æ•°]。\n如果当å‰è¿žæŽ¥çš„ VPN Server 是群集控制器,管ç†çš„虚拟 HUB 是é™æ€çš„虚拟 HUB,å¯ä»¥å¾—到连接其所有的集群æˆå‘˜çš„该虚拟 HUB 的会è¯åˆ—表的结åˆã€‚\n在其他情况下,åªèƒ½èŽ·å–与目å‰ç®¡ç†çš„ VPN Server 实际连接ç€çš„会è¯åˆ—表。
+CMD_SessionList_Args SessionList
+
+
+# SessionGet 命令
+CMD_SessionGet 获å–会è¯ä¿¡æ¯
+CMD_SessionGet_Help 指定与当目å‰ç®¡ç†çš„虚拟 HUB 连接ç€çš„会è¯ï¼Œå¹¶èŽ·å¾—其会è¯ä¿¡æ¯ã€‚会è¯ä¿¡æ¯åŒ…括以下内容: 连接æºä¸»æœºå和用户å,版本信æ¯ï¼Œæ—¶é—´ä¿¡æ¯ï¼ŒTCP 连接数,通讯å‚数,会è¯å¯†é’¥ï¼Œè¾“入输出的数æ®ç»Ÿè®¡èµ„料,和其他客户端和æœåŠ¡å™¨ä¿¡æ¯ç­‰ã€‚\nè¦èŽ·å¾—当å‰è¿žæŽ¥çš„会è¯åˆ—表,请使用 SessionList 命令。
+CMD_SessionGet_Args SessionGet [name]
+CMD_SessionGet_[name] 指定è¦èŽ·å–ä¿¡æ¯çš„会è¯å称。
+CMD_SessionGet_Prompt_NAME 会è¯å称:
+
+
+# SessionDisconnect 命令
+CMD_SessionDisconnect 断开会è¯
+CMD_SessionDisconnect_Help 指定连接到目å‰ç®¡ç†çš„虚拟 HUB 的会è¯ï¼Œç®¡ç†å‘˜æƒé™ä»¥å¼ºåˆ¶æ–­å¼€å…¶ä¼šè¯ã€‚\n但是,终端的客户端的设置为通信断开åŽçš„自动å¯åŠ¨é‡æ–°è¿žæŽ¥ä¼šè¯çš„情况下,å¯èƒ½å®¢æˆ·ç«¯ä¼šé‡æ–°è¿žæŽ¥ã€‚\nè¦èŽ·å¾—当å‰è¿žæŽ¥ä¼šè¯åˆ—表,请使用 SessionList 命令。
+CMD_SessionDisconnect_Args SessionDisconnect [name]
+CMD_SessionDisconnect_[name] 指定è¦æ–­å¼€çš„会è¯å称。
+
+
+# MacTable 命令
+CMD_MacTable èŽ·å– MAC 地å€è¡¨æ•°æ®åº“
+CMD_MacTable_Help 获å–当å‰ç®¡ç†çš„虚拟 HUB ä¿æŒçš„ MAC 地å€è¡¨çš„æ•°æ®åº“。\nMAC 地å€è¡¨æ•°æ®åº“是虚拟 HUB 需è¦è¿›è¡Œäº¤æ¢ä»¥å¤ªç½‘帧的平å°ï¼Œè™šæ‹Ÿ HUB 基于 MAC 地å€è¡¨çš„æ•°æ®åº“,决定å„个以太网帧排åºç›®æ ‡ä¼šè¯ã€‚MAC 地å€æ•°æ®åº“自动分æžåˆ›å»ºè™šæ‹Ÿ HUB æµåŠ¨çš„通信内容。\n指定的会è¯å称,å¯ä»¥å¾—到与该会è¯æœ‰å…³çš„ MAC 地å€è¡¨é¡¹ã€‚
+CMD_MacTable_Args MacTable [session_name]
+CMD_MacTable_[session_name] 如果指定作为å‚数的会è¯å称,å¯ä»¥åªæ˜¾ç¤ºä¸Žè¯¥ä¼šè¯ç›¸å…³è”çš„ MAC 地å€è¡¨é¡¹ã€‚如果ä¸æŒ‡å®šï¼Œåˆ™æ˜¾ç¤ºæ‰€æœ‰çš„项。
+
+
+# MacDelete 命令
+CMD_MacDelete 删除 MAC 地å€è¡¨é¡¹
+CMD_MacDelete_Help æ“作目å‰ç®¡ç†çš„虚拟 HUB ä¿æŒçš„ MAC 地å€è¡¨æ•°æ®åº“,从数æ®åº“中删除指定的 MAC 地å€é¡¹ã€‚\nè¦èŽ·å–ç›®å‰çš„ MAC 地å€è¡¨æ•°æ®åº“的内容,请使用 MacTable 命令。
+CMD_MacDelete_Args MacDelete [id]
+CMD_MacDelete_[id] 指定è¦åˆ é™¤çš„ MAC 地å€è¡¨é¡¹çš„ ID。
+CMD_MacDelete_Prompt è¦åˆ é™¤çš„ ID:
+
+
+# IpTable 命令
+CMD_IpTable èŽ·å– IP 地å€è¡¨æ•°æ®åº“
+CMD_IpTable_Help ç›®å‰ç®¡ç†çš„虚拟 HUB ä¿æŒçš„ IP 地å€è¡¨çš„æ•°æ®åº“。\nIP 地å€è¡¨æ•°æ®åº“是一个自动分æžç”Ÿæˆé€šä¿¡å†…容的平å°ï¼Œä¸ºä½¿è™šæ‹Ÿ HUB 能够掌æ¡å“ªä¸ªä¼šè¯ä½¿ç”¨çš„是哪个 IP 地å€ï¼Œè¿™æ˜¯ç»å¸¸è¢«ä½¿ç”¨çš„虚拟 HUB 安全策略的引擎。\n指定的会è¯å称,å¯ä»¥èŽ·å–与该会è¯ç›¸å…³è”çš„ IP 地å€è¡¨é¡¹ã€‚
+CMD_IpTable_Args IpTable [session_name]
+CMD_IpTable_[session_name] 指定作为å‚数的会è¯å称,å¯ä»¥åªæ˜¾ç¤ºä¸Žè¯¥ä¼šè¯ç›¸å…³è”çš„ IP 地å€è¡¨é¡¹ã€‚如果ä¸æŒ‡å®šï¼Œåˆ™æ˜¾ç¤ºæ‰€æœ‰çš„项。
+
+
+# IpDelete 命令
+CMD_IpDelete 删除 IP 地å€è¡¨é¡¹
+CMD_IpDelete_Help æ“作目å‰ç®¡ç†çš„虚拟 HUB ä¿æŒçš„ IP 地å€è¡¨æ•°æ®åº“,从数æ®åº“中删除指定的 IP 地å€é¡¹ã€‚\nè¦èŽ·å–ç›®å‰çš„ IP 地å€è¡¨æ•°æ®åº“的内容,请使用 IpTable 命令。
+CMD_IpDelete_Args IpDelete [id]
+CMD_IpDelete_[id] 指定è¦åˆ é™¤çš„ IP 地å€è¡¨é¡¹çš„ ID。
+
+
+# SecureNatEnable 命令
+CMD_SecureNatEnable å¯ç”¨è™šæ‹Ÿ NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能)
+CMD_SecureNatEnable_Help 使在目å‰ç®¡ç†çš„虚拟 HUB 内å¯åŠ¨å¹¶è¿è¡Œè™šæ‹Ÿ NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能)。执行此指令å‰ï¼Œå¿…须先使用 SecureNatHostGet 指令,NatGet 指令和 DhcpGet 指令检查当å‰è™šæ‹Ÿ NAT 功能和 DHCP æœåŠ¡å™¨çš„设置内容。\n一旦å¯ç”¨å®‰å…¨ç½‘络的功能,å¯ä»¥åœ¨è™šæ‹Ÿ HUB 的虚拟网络上使 NAT 路由器 (IP 伪装) å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½è™šæ‹Ÿæ€§çš„è¿è¡Œã€‚\n\n[有关安全网络功能的警告]\n安全网络的功能是é¢å‘系统管ç†å‘˜å’Œå¯¹å…·å¤‡æœ‰å…³ç½‘络的丰富知识的人的功能。\n如果正确使用安全网络功能,å¯èƒ½å®žçŽ°é€šè¿‡ VPN 的安全的远程访问。但是如果错误地使用,å¯èƒ½ä½¿æ•´ä¸ªç½‘络处于å±é™©çŠ¶æ€ã€‚如果ä¸å…·å¤‡å…¨é¢çš„的网络知识,没有得到网络管ç†å‘˜è®¸å¯çš„情况下,请ç¦ç”¨å®‰å…¨ç½‘络功能。关于安全网络功能的详细说明,请å‚阅 VPN Server 的手册和在线文档。\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_SecureNatEnable_Args SecureNatEnable
+
+
+# SecureNatDisable 命令
+CMD_SecureNatDisable ç¦ç”¨è™šæ‹Ÿ NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能)
+CMD_SecureNatDisable_Help 在当å‰ç®¡ç†çš„虚拟 HUB 内ç¦ç”¨è™šæ‹Ÿ NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能)。一旦执行该命令,虚拟 NAT 功能立å³åœæ­¢ï¼Œè™šæ‹Ÿ DHCP æœåŠ¡å™¨åŠŸèƒ½åˆ™åˆ é™¤æŒæœ‰çš„ DHCP 租èµæ•°æ®å¹¶åœæ­¢è¯¥æœåŠ¡ã€‚\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_SecureNatDisable_Args SecureNatDisable
+
+
+# SecureNatStatusGet 命令
+CMD_SecureNatStatusGet 获å–虚拟 NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能) 的工作状æ€
+CMD_SecureNatStatusGet_Help 如果在目å‰ç®¡ç†çš„虚拟 HUB 内æ“作虚拟 NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能),获得其æ“作状æ€ã€‚ \n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_SecureNatStatusGet_Args SecureNatStatusGet
+
+
+# SecureNatHostGet 命令
+CMD_SecureNatHostGet 获å–安全网络功能的虚拟主机的网络接å£è®¾ç½®
+CMD_SecureNatHostGet_Help 在当å‰ç®¡ç†çš„虚拟 HUB 内获å–虚拟 NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能) 中的虚拟主机的网络接å£è®¾ç½®ã€‚\n安全网络功能有一枚在虚拟 HUB 内二级市场中的虚拟 LAN å¡ï¼Œå®ƒè¢«èµ‹äºˆäº† MAC 地å€å’Œ IP 地å€ã€‚这样,连接到åŒä¸€ä¸ªäºŒçº§å¸‚场的其他主机,能够如存在于网络的真实 IP 主机般与安全网络的虚拟主机通信。\n\n[有关安全网络功能的警告]\n安全网络的功能是é¢å‘系统管ç†å‘˜å’Œå¯¹å…·å¤‡æœ‰å…³ç½‘络的丰富知识的人的功能。\n如果正确使用安全网络功能,å¯èƒ½å®žçŽ°é€šè¿‡ VPN 的安全的远程访问。但是如果错误地使用,å¯èƒ½ä½¿æ•´ä¸ªç½‘络处于å±é™©çŠ¶æ€ã€‚如果ä¸å…·å¤‡å…¨é¢çš„的网络知识,没有得到网络管ç†å‘˜è®¸å¯çš„情况下,请ç¦ç”¨å®‰å…¨ç½‘络功能。关于安全网络功能的详细说明,请å‚阅 VPN Server 的手册和在线文档。\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_SecureNatHostGet_Args SecureNatHostGet
+CMD_SecureNatHostGet_Column_MAC MAC 地å€
+CMD_SecureNatHostGet_Column_IP IP 地å€
+CMD_SecureNatHostGet_Column_MASK å­ç½‘掩ç 
+CMD_SecureNatHostGet_Column_LOG ä¿å­˜ NAT å’Œ DHCP æ“作日志
+
+
+# SecureNatHostSet 命令
+CMD_SecureNatHostSet 更改安全网络功能的虚拟主机的网络接å£è®¾ç½®
+CMD_SecureNatHostSet_Help 当å‰ç®¡ç†çš„虚拟 HUB 内,更改和ä¿å­˜è™šæ‹Ÿ NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能) 的设置项目中的虚拟主机网络接å£è®¾ç½®ã€‚\n安全网络功能有一枚在虚拟 HUB 内二级市场中的虚拟 LAN å¡ï¼Œå®ƒè¢«èµ‹äºˆäº† MAC 地å€å’Œ IP 地å€ã€‚这样,连接到åŒä¸€ä¸ªäºŒçº§å¸‚场的其他主机,能够如存在于网络的真实 IP 主机般与安全网络的虚拟主机通信。\n\n[有关安全网络功能的警告]\n安全网络的功能是é¢å‘系统管ç†å‘˜å’Œå¯¹å…·å¤‡æœ‰å…³ç½‘络的丰富知识的人的功能。\n如果正确使用安全网络功能,å¯èƒ½å®žçŽ°é€šè¿‡ VPN 的安全的远程访问。但是如果错误地使用,å¯èƒ½ä½¿æ•´ä¸ªç½‘络处于å±é™©çŠ¶æ€ã€‚如果ä¸å…·å¤‡å…¨é¢çš„的网络知识,没有得到网络管ç†å‘˜è®¸å¯çš„情况下,请ç¦ç”¨å®‰å…¨ç½‘络功能。关于安全网络功能的详细说明,请å‚阅 VPN Server 的手册和在线文档。\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_SecureNatHostSet_Args SecureNatHostSet [/MAC:mac] [/IP:ip] [/MASK:mask]
+CMD_SecureNatHostSet_MAC 指定分é…到虚拟接å£çš„ MAC 地å€ã€‚MAC 地å€ç”¨è¯¸å¦‚ "00-AC-01-23-45-67" 的字符串指定。一但指定 /MAC:none,则ä¸æ›´æ”¹å°†å½“å‰çš„设置。
+CMD_SecureNatHostSet_IP 指定分é…到虚拟接å£çš„ IP 地å€ã€‚一但指定 /IP:none,则ä¸æ›´æ”¹å°†å½“å‰çš„设置。
+CMD_SecureNatHostSet_MASK 指定分é…到虚拟接å£çš„å­ç½‘掩ç ã€‚一但指定 /MASK:none,则ä¸æ›´æ”¹å°†å½“å‰çš„设置。
+CMD_SecureNatHostSet_Prompt_MAC MAC 地å€:
+CMD_SecureNatHostSet_Prompt_IP IP 地å€:
+CMD_SecureNatHostSet_Prompt_MASK å­ç½‘掩ç :
+
+
+# NatGet 命令
+CMD_NatGet 获得安全网络功能的虚拟 NAT 功能的设置
+CMD_NatGet_Help 在当å‰ç®¡ç†çš„虚拟 HUB 内,获得虚拟 NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能) 的设置项目中的虚 NAT 设置。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_NatGet_Args NatGet
+CMD_NatGet_Column_USE 使用虚拟 NAT 功能
+CMD_NetGet_Column_MTU MTU 值
+CMD_NatGet_Column_TCP TCP 会è¯è¶…æ—¶ (秒)
+CMD_NatGet_Column_UDP UDP 会è¯è¶…æ—¶ (秒)
+
+
+# NatEnable 命令
+CMD_NatEnable å¯ç”¨å®‰å…¨ç½‘络功能的虚拟 NAT 功能
+CMD_NatEnable_Help 在目å‰ç®¡ç†çš„虚拟 HUB 内å¯ç”¨è™šæ‹Ÿ NAT 功能。\n如果使用此指令å¯åŠ¨è™šæ‹Ÿ NAT 功能,但 SecureNAT 功能没有工作时,则虚拟的 NAT ä¸å·¥ä½œã€‚è¦å¯åŠ¨ SecureNAT 功能的工作,使用 SecureNatEnable 命令。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_NatEnable_Args NatEnable
+
+
+# NatDisable 命令
+CMD_NatDisable ç¦ç”¨å®‰å…¨ç½‘络功能的虚拟 NAT 功能
+CMD_NatDisable_Help 在目å‰ç®¡ç†çš„虚拟 HUB 内ç¦ç”¨è™šæ‹Ÿ NAT 功能。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_NatDisable_Args NatDisable
+
+
+# NatSet 命令
+CMD_NatSet 更改安全网络功能的虚拟 NAT 功能的设置
+CMD_NatSet_Help 更改目å‰ç®¡ç†çš„虚拟 HUB 内的虚拟的 NAT 设置。虚拟的 NAT 设置的内容包括: MTU 值,TCP 会è¯è¶…时,UDP 会è¯è¶…时。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_NatSet_Args NatSet [/MTU:mtu] [/TCPTIMEOUT:tcp_timeout] [/UDPTIMEOUT:udp_timeout] [/LOG:yes|no]
+CMD_NatSet_MTU 用字节数å•ä½çš„整数设置 MTU (最大å¯è½¬è®©å•ä½çš„大å°)。此值是ä¸åŒ…括虚拟 NAT å‘é€çš„以太网帧的 MAC 头最大有效载è·é•¿åº¦ï¼Œé»˜è®¤å€¼æ˜¯ 1500 字节。
+CMD_NatSet_TCPTIMEOUT 设置虚拟 NAT 中转 TCP 会è¯æ—¶å¦‚æžœæŒç»­å¤šå°‘秒éžé€šä¿¡çŠ¶æ€å³è¶…时并丢弃会è¯ã€‚
+CMD_NatSet_UDPTIMEOUT 设置虚拟 NAT 中转 UDP 会è¯æ—¶å¦‚æžœæŒç»­å¤šå°‘秒éžé€šä¿¡çŠ¶æ€å³è¶…时并丢弃会è¯ã€‚
+CMD_NatSet_LOG 指定是å¦å°†è™šæ‹Ÿ NAT çš„æ“作ä¿å­˜åœ¨è™šæ‹Ÿ HUB 安全日志。指定 "yes" å³ä¿å­˜å®ƒï¼ŒæŒ‡å®š "no" å³ä¸ä¿å­˜ã€‚
+CMD_NatSet_Prompt_MTU MTU 值:
+CMD_NatSet_Prompt_TCPTIMEOUT TCP 会è¯è¶…æ—¶ (秒):
+CMD_NatSet_Prompt_UDPTIMEOUT UDP 会è¯è¶…æ—¶ (秒):
+CMD_NatSet_Prompt_LOG ä¿å­˜æ—¥å¿— (yes/no):
+CMD_NatSet_Eval_MTU 请在从 %d 到 %d 之间设定 MTU 值。
+CMD_NatSet_Eval_TCP 请在从 %d 到 %d 之间设定 TCP 会è¯è¶…时秒数。
+CMD_NatSet_Eval_UDP 请在从 %d 到 %d 之间设定 UDP 会è¯è¶…时秒数。
+
+
+# NatTable 命令
+CMD_NatTable 获得安全网络功能的虚拟 NAT 功能会è¯è¡¨
+CMD_NatTable_Help 虚拟 NAT 功能在目å‰ç®¡ç†çš„虚拟 HUB 内è¿ä½œæ—¶ï¼Œç»ç”±è™šæ‹Ÿ NAT 获å–ç›®å‰é€šä¿¡ä¸­çš„ TCP åŠ UDP 会è¯è¡¨ (NAT 表)。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_NatTable_Args NatTable
+
+
+# DhcpGet 命令
+CMD_DhcpGet 获得安全网络功能的虚拟 DHCP æœåŠ¡å™¨åŠŸèƒ½çš„设置
+CMD_DhcpGet_Help 在当å‰ç®¡ç†çš„虚拟 HUB 内获å–虚拟 NAT å’Œ DHCP æœåŠ¡å™¨åŠŸèƒ½ (安全网络功能) 的设置项目中的虚拟 DHCP æœåŠ¡å™¨è®¾ç½®ã€‚\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_DhcpGet_Args DhcpGet
+CMD_DhcpGet_Column_Log NAT å’Œ DHCP çš„æ“作日志记录
+CMD_DhcpGet_Column_USE 使用虚拟 DHCP 功能
+CMD_DhcpGet_Column_IP1 分å‘地å€èŒƒå›´çš„开始
+CMD_DhcpGet_Column_IP2 分å‘地å€èŒƒå›´çš„结æŸ
+CMD_DhcpGet_Column_MASK å­ç½‘掩ç 
+CMD_DhcpGet_Column_LEASE 租èµæœŸé™ (秒)
+CMD_DhcpGet_Column_GW 默认网关地å€
+CMD_DhcpGet_Column_DNS DNS æœåŠ¡å™¨åœ°å€ 1
+CMD_DhcpGet_Column_DNS2 DNS æœåŠ¡å™¨åœ°å€ 2
+CMD_DhcpGet_Column_DOMAIN 域å
+
+
+# DhcpEnable 命令
+CMD_DhcpEnable å¯åŠ¨å®‰å…¨ç½‘络功能的虚拟 DHCP æœåŠ¡å™¨åŠŸèƒ½
+CMD_DhcpEnable_Help 在当å‰ç®¡ç†çš„虚拟 HUB 内å¯åŠ¨è™šæ‹Ÿ DHCP æœåŠ¡å™¨åŠŸèƒ½ã€‚如果使用此指令å¯åŠ¨è™šæ‹Ÿ DHCP æœåŠ¡å™¨åŠŸèƒ½ä½† SecureNAT 功能ä¸å·¥ä½œçš„情况下,则虚拟 DHCP æœåŠ¡å™¨ä¸å·¥ä½œã€‚è¦å¯åŠ¨ SecureNAT 功能,使用 SecureNatEnable 指令。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_DhcpEnable_Args DhcpEnable
+
+
+# DhcpDisable 命令
+CMD_DhcpDisable ç¦ç”¨å®‰å…¨ç½‘络功能的虚拟 DHCP æœåŠ¡å™¨åŠŸèƒ½
+CMD_DhcpDisable_Help 在目å‰ç®¡ç†çš„虚拟 HUB 内ç¦ç”¨ DHCP æœåŠ¡å™¨ã€‚\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_DhcpDisable_Args DhcpDisable
+
+
+# DhcpSet 命令
+CMD_DhcpSet 更改安全网络功能的虚拟 DHCP æœåŠ¡å™¨åŠŸèƒ½çš„设置
+CMD_DhcpSet_Help 在现在管ç†çš„虚拟 HUB 内,更改虚拟 DHCP æœåŠ¡å™¨çš„设置。虚拟 DHCP æœåŠ¡å™¨è®¾ç½®åŒ…括: åˆ†é… IP 地å€èŒƒå›´ï¼Œå­ç½‘掩ç ï¼Œå‡ºç§ŸæœŸé™ï¼ŒåŠåˆ†é…给客户端的选项值。\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_DhcpSet_Args DhcpSet [/START:start_ip] [/END:end_ip] [/MASK:subnetmask] [/EXPIRE:sec] [/GW:gwip] [/DNS:dns] [/DNS2:dns2] [/DOMAIN:domain] [/LOG:yes|no]
+CMD_DhcpSet_START 指定地å€èŒƒå›´çš„开始点,以分å‘给客户。(例如: 192.168.30.10)
+CMD_DhcpSet_END 指定地å€èŒƒå›´çš„结æŸç‚¹ï¼Œä»¥åˆ†å‘给客户。(例如: 192.168.30.200)
+CMD_DhcpSet_MASK 指定对客户指定的å­ç½‘掩ç ã€‚(例如: 255.255.255.0)
+CMD_DhcpSet_EXPIRE 以秒为å•ä½å¯¹å®¢æˆ·æŒ‡å®šç§Ÿèµ IP 地å€æ—¶çš„有效期é™
+CMD_DhcpSet_GW 指定è¦é€šçŸ¥ç»™å®¢æˆ·ç«¯çš„默认网关的 IP 地å€ã€‚如果è¦ä¸Žå®‰å…¨ç½‘络功能的虚拟 NAT 功能一起å¯åŠ¨å¹¶ä½¿ç”¨æ—¶ï¼Œå¯ä»¥æŒ‡å®šå®‰å…¨ç½‘络的虚拟主机的 IP 地å€ã€‚如果指定 "0" 或 "none",则ä¸å°†é»˜è®¤ç½‘关通知客户。
+CMD_DhcpSet_DNS 指定被通知到客户端的主 DNS æœåŠ¡å™¨çš„ IP 地å€ã€‚当 SecureNAT 功能的虚拟 NAT 功能已ç»å¯ç”¨å¹¶æ­£åœ¨è¿è¡Œæ—¶ï¼Œæ‚¨å¯ä»¥ä¸ºæ­¤æŒ‡å®šä¸€ä¸ª SecureNAT 虚拟主机 IP 地å€ã€‚如果您指定的是 0 或者 none,那么客户端就ä¸ä¼šè¢« DNS æœåŠ¡å™¨åœ°å€é€šçŸ¥ã€‚
+CMD_DhcpSet_DNS2 æŒ‡å®šè¢«é€šçŸ¥åˆ°å®¢æˆ·ç«¯çš„æ¬¡è¦ DNS æœåŠ¡å™¨ IP 地å€ã€‚当 SecureNAT 功能的虚拟 NAT 功能已ç»å¯ç”¨å¹¶æ­£åœ¨è¿è¡Œæ—¶ï¼Œæ‚¨å¯ä»¥ä¸ºæ­¤æŒ‡å®šä¸€ä¸ª SecureNAT 虚拟主机 IP 地å€ã€‚如果您指定的是 0 或者 none,那么客户端就ä¸ä¼šè¢« DNS æœåŠ¡å™¨åœ°å€é€šçŸ¥ã€‚
+CMD_DhcpSet_DOMAIN 指定域å通知客户。如果指定 none,该域åä¸é€šçŸ¥å®¢æˆ·ã€‚
+CMD_DhcpSet_LOG 指定是å¦å°†è™šæ‹Ÿ DHCP æœåŠ¡å™¨è¿è¡Œä¿å­˜ä¸ºå®‰å…¨æ—¥å¿—。指定 "yes" 则ä¿å­˜ã€‚此值与虚拟 NAT 功能的日志ä¿å­˜è®¾ç½®æ˜¯è”动的。
+CMD_DhcpSet_Prompt_START 分å‘地å€èŒƒå›´çš„开始:
+CMD_DhcpSet_Prompt_END 分å‘地å€èŒƒå›´çš„结æŸ:
+CMD_DhcpSet_Prompt_MASK å­ç½‘掩ç :
+CMD_DhcpSet_Prompt_EXPIRE 租èµæœŸé™ (è¡¥):
+CMD_DhcpSet_Prompt_GW 默认网关 (å¯ä»¥ä¸è®¾å®š):
+CMD_DhcpSet_Prompt_DNS DNS æœåŠ¡å™¨ 1 (å¯ä»¥ä¸è®¾å®š):
+CMD_DhcpSet_Prompt_DNS2 DNS æœåŠ¡å™¨ 2 (å¯ä»¥ä¸è®¾å®š):
+CMD_DhcpSet_Prompt_DOMAIN 域å:
+
+
+# DhcpTable 命令
+CMD_DhcpTable 获å–安全网络功能的虚拟 DHCP æœåŠ¡å™¨ç§Ÿçº¦è¡¨æ ¼
+CMD_DhcpTable_Help 在目å‰ç®¡ç†çš„虚拟 HUB 内æ“作 DHCP æœåŠ¡å™¨åŠŸèƒ½æ—¶ï¼ŒèŽ·å–分é…到 DHCP æœåŠ¡å™¨æŒæœ‰çš„客户端的 IP 地å€ç§Ÿçº¦è¡¨ã€‚\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_DhcpTable_Args DhcpTable
+
+
+# AdminOptionList 命令
+CMD_AdminOptionList 获å–虚拟 HUB 管ç†é€‰é¡¹åˆ—表
+CMD_AdminOptionList_Help 获å–ç›®å‰ç®¡ç†çš„虚拟 HUB 设置的虚拟 HUB 管ç†é€‰é¡¹åˆ—表。\nVPN Server 的管ç†å‘˜å§”托å„个虚拟 HUB 的管ç†å‘˜å¯¹è™šæ‹Ÿ HUB 进行管ç†æ—¶ï¼Œä¸ºé™åˆ¶å…¶è®¾ç½®èŒƒå›´ï¼Œä½¿ç”¨è™šæ‹Ÿ HUB 管ç†é€‰é¡¹ã€‚\n能够对虚拟 HUB 管ç†é€‰é¡¹è¿›è¡Œæ·»åŠ ï¼Œç¼–辑,删除的,åªæœ‰æŽŒæ¡ç€æ­¤ VPN Server 全部管ç†æƒé™çš„管ç†å‘˜ã€‚虚拟 HUB 的管ç†å‘˜å¯ä»¥æ˜¾ç¤ºç®¡ç†é€‰é¡¹ï¼Œä½†ä¸èƒ½æ›´æ”¹ã€‚\n然而,allow_hub_admin_change_option 设置为 1 时,虚拟 HUB 的管ç†å‘˜ä¹Ÿå¯ä»¥ç¼–辑管ç†é€‰é¡¹ã€‚\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_AdminOptionList_Args AdminOptionList
+
+
+# AdminOptionSet 命令
+CMD_AdminOptionSet 设置虚拟 HUB 管ç†é€‰é¡¹çš„价值
+CMD_AdminOptionSet_Help å˜æ›´ç›®å‰ç®¡ç†çš„虚拟 HUB 设置的虚拟 HUB 管ç†é€‰é¡¹çš„值。\nVPN Server 的管ç†å‘˜å§”托å„个虚拟 HUB 的管ç†å‘˜å¯¹è™šæ‹Ÿ HUB 进行管ç†æ—¶ï¼Œä¸ºé™åˆ¶å…¶è®¾ç½®èŒƒå›´ï¼Œä½¿ç”¨è™šæ‹Ÿ HUB 管ç†é€‰é¡¹ã€‚\n能够对虚拟 HUB 管ç†é€‰é¡¹è¿›è¡Œæ·»åŠ ï¼Œç¼–辑,删除的,åªæœ‰æŽŒæ¡ç€æ­¤ VPN Server 全部管ç†æƒé™çš„管ç†å‘˜ã€‚虚拟 HUB 的管ç†å‘˜å¯ä»¥æ˜¾ç¤ºç®¡ç†é€‰é¡¹ï¼Œä½†ä¸èƒ½æ›´æ”¹ã€‚\n然而,allow_hub_admin_change_option 设置为 1 时,虚拟 HUB 的管ç†å‘˜ä¹Ÿå¯ä»¥ç¼–辑管ç†é€‰é¡¹ã€‚\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_AdminOptionSet_Args AdminOptionSet [name] [/VALUE:value]
+CMD_AdminOptionSet_[name] 指定更改值的管ç†é€‰é¡¹å。以 AdminOptionList 指令å¯ä»¥èŽ·å–åå•ã€‚
+CMD_AdminOptionSet_VALUE 以整数指定è¦è®¾å®šçš„值。
+CMD_AdminOptionSet_Prompt_name è¦æ›´æ”¹å€¼çš„管ç†é€‰é¡¹å称:
+CMD_AdminOptionSet_Prompt_VALUE 设定值 (整数):
+
+
+# ExtOptionList 命令
+CMD_ExtOptionList 获å–虚拟 HUB 扩展选项列表
+CMD_ExtOptionList_Help 获å–ç›®å‰ç®¡ç†çš„虚拟 HUB 设置的虚拟 HUB 扩展选项列表。\n虚拟 HUB 扩展选项使你å¯ä»¥å¯¹è™šæ‹Ÿ HUB 进行更多的é…置。\默认情况下,VPN Server çš„å…¨çƒç®¡ç†å‘˜å’Œä¸ªäººè™šæ‹Ÿ HUB 的管ç†å‘˜éƒ½å¯ä»¥ä¿®æ”¹è™šæ‹Ÿ HUB 扩展选项。\n但是,如果虚拟 HUB 管ç†é€‰é¡¹ deny_hub_admin_change_ext_option 被设置为 1,个人虚拟 HUB 管ç†å‘˜å°±ä¸èƒ½ä¿®æ”¹è™šæ‹Ÿ HUB 扩展选项。\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_ExtOptionList_Args ExtOptionList
+
+
+# ExtOptionSet 命令
+CMD_ExtOptionSet 设置虚拟 HUB 扩展选项的值
+CMD_ExtOptionSet_Help 使用此命令在当å‰ç®¡ç†çš„虚拟 HUB 的虚拟 HUB 扩展选项列表设置一个值。\n虚拟 HUB 扩展选项使你å¯ä»¥å¯¹è™šæ‹Ÿ HUB 进行更多的é…置。\默认情况下,VPN Server çš„å…¨çƒç®¡ç†å‘˜å’Œä¸ªäººè™šæ‹Ÿ HUB 的管ç†å‘˜éƒ½å¯ä»¥ä¿®æ”¹è™šæ‹Ÿ HUB 扩展选项。\n但是,如果虚拟 HUB 管ç†é€‰é¡¹ deny_hub_admin_change_ext_option 被设置为 1,个人虚拟 HUB 管ç†å‘˜å°±ä¸èƒ½ä¿®æ”¹è™šæ‹Ÿ HUB 扩展选项。\n此命令ä¸èƒ½åœ¨ VPN Bridge 上è¿è¡Œã€‚ \n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_ExtOptionSet_Args ExtOptionSet [name] [/VALUE:value]
+CMD_ExtOptionSet_[name] 指定您è¦æ›´æ”¹å…¶å€¼çš„虚拟 HUB 扩展选项的å称。使用 ExtOptionList 命令,你å¯ä»¥å¾—到一个å称列表。
+CMD_ExtOptionSet_VALUE 以整数指定è¦è®¾å®šçš„值。
+CMD_ExtOptionSet_Prompt_name è¦æ›´æ”¹å€¼çš„扩展选项å称:
+CMD_ExtOptionSet_Prompt_VALUE 设定值 (整数):
+
+
+# CrlList 命令
+CMD_CrlList 获å–无效è¯ä¹¦åå•åˆ—表
+CMD_CrlList_Help 获å–ç›®å‰ç®¡ç†çš„虚拟 HUB 设置的无效è¯ä¹¦åå•åˆ—表。\n一旦è¯ä¹¦æ³¨å†Œåˆ°æ— æ•ˆè¯ä¹¦åˆ—表内,æ交了其è¯ä¹¦çš„客户,将ä¸èƒ½ç”¨è¯ä¹¦è®¤è¯æ¨¡å¼è¿žæŽ¥è™šæ‹Ÿ HUB。\n通常情况下,因为泄æ¼å¯†é’¥æˆ–è¯ä¹¦æŒæœ‰äººçš„æƒé™å¤±æ•ˆæ—¶ï¼Œå°†è¯¥è¯ä¹¦ä½œä¸ºæ— æ•ˆè¯ä¹¦æ³¨å†Œåˆ°è™šæ‹Ÿ HUB,而 VPN 客户欲使用该è¯ä¹¦è¿žæŽ¥è™šæ‹Ÿ HUB 时会被拒ç»ç”¨æˆ·è®¤è¯ï¼Œè¿™ç§æƒ…况下该功能被使用。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_CrlList_Args CrlList
+
+
+# CrlAdd 命令
+CMD_CrlAdd 添加无效的è¯ä¹¦
+CMD_CrlAdd_Help 在目å‰ç®¡ç†çš„虚拟 HUB 设置的无效的è¯ä¹¦åå•ä¸­æ·»åŠ æ–°çš„无效è¯ä¹¦çš„定义。\n用此指令的å‚数指定è¦æ³¨å†Œåˆ°æ— æ•ˆè¯ä¹¦åˆ—表中的内容。用户用è¯ä¹¦è®¤è¯æ¨¡å¼è¿žæŽ¥åˆ°è™šæ‹Ÿ HUB 时,如果其è¯ä¹¦ä¸Žæ— æ•ˆè¯ä¹¦åˆ—表中注册的一æ¡ä»¥ä¸Šçš„内容一致,将拒ç»è¯¥ç”¨æˆ·çš„连接。\n与此指令指定的å‚数定义的所有æ¡ä»¶ç›¸ä¸€è‡´çš„è¯ä¹¦ï¼Œä¼šè¢«åˆ¤æ–­ä¸ºæ— æ•ˆã€‚\nå¯ä»¥è®¾ç½®è¯¥é¡¹ç›®ä¸º:[å称 (CN)],[所属机构 (O)],[组织å•ä½ (OU)],[国家 (C)],[å·ž (ST)],[现地 (L)],[åºå· (å六进制)],[MD5 摘è¦å€¼ (å六进制,128 ä½)],[SHA-1 摘è¦å€¼ (å六进制,160ä½)]。摘è¦å€¼ (哈希值) 的指定,是将è¯æ˜Žä¹¦æŒ‡å®šä¸ºäº‹å®žä¸Šçš„唯一。通常情况下,如果输入 MD5 或 SHA-1摘è¦å€¼ï¼Œå°±ä¸ç”¨è¾“入其他项目。\n此命令用 VPN Bridge ä¸èƒ½è¿è¡Œã€‚\n此命令在群集内作为群集æˆå‘˜æœåŠ¡å™¨æ“作的 VPN Server 的虚拟 HUB 上ä¸èƒ½è¿è¡Œã€‚
+CMD_CrlAdd_Args CrlAdd [/SERIAL:serial] [/MD5:md5] [/SHA1:sha1] [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l]
+CMD_CrlAdd_SERIAL 作为æ¡ä»¶ï¼Œåœ¨è®¾å®šè¯ä¹¦çš„åºåˆ—å· (16 进制) 时,以此此å‚数指定其值。
+CMD_CrlAdd_MD5 作为æ¡ä»¶ï¼Œåœ¨è®¾å®šè¯ä¹¦çš„ MD5 摘è¦å€¼ (å六进制,128 ä½) 时,以此å‚数指定其值。如果ä¸æŒ‡å®š 16 进制 32 个字符 (16 字节) çš„å‚数,则被忽略。
+CMD_CrlAdd_SHA1 作为æ¡ä»¶ï¼Œåœ¨è®¾å®šè¯ä¹¦çš„ SHA-1 摘è¦å€¼çš„æ¡ä»¶ (å六进制,160 ä½) 时,以此å‚数指定其值。如ä¸æŒ‡å®šå六进制 40 个字符 (20 字节) çš„å‚数,则被忽略。
+CMD_CrlAdd_CN 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„å称 (CN) 时,以此å‚数设定其值。
+CMD_CrlAdd_O 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„所属机构 (O) 时,以此å‚数设定其值。
+CMD_CrlAdd_OU 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„组织å•ä½ (OU) 时,以此å‚数设定其值。
+CMD_CrlAdd_C 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„国家 (C) 时,以此å‚数设定其值。
+CMD_CrlAdd_ST 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„å·ž (ST) 时,以此å‚数设定其值。
+CMD_CrlAdd_L 作为æ¡ä»¶ï¼ŒæŒ‡å®šè¯ä¹¦çš„当地 (L) 时,以此å‚数设定其值。
+
+
+# CrlDel 命令
+CMD_CrlDel 删除无效的è¯ä¹¦
+CMD_CrlDel_Help 从目å‰ç®¡ç†çš„虚拟 HUB设置的无效è¯ä¹¦åå•ä¸­æŒ‡å®šå¹¶åˆ é™¤æ— æ•ˆè¯ä¹¦çš„定义。\nç›®å‰æ³¨å†Œçš„无效è¯ä¹¦çš„定义列表,å¯ç”¨ CrlList 指令获å–。\n该指令虚拟专用桥ä¸èƒ½è¿è¡Œã€‚ \n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_CrlDel_Args CrlDel [id]
+CMD_CrlDel_[id] 指定è¦åˆ é™¤çš„无效的è¯ä¹¦çš„定义中的 ID。
+CMD_CrlDel_Prompt_ID 删除 ID:
+
+
+# CrlGet 命令
+CMD_CrlGet 获å–无效的è¯ä¹¦
+CMD_CrlGet_Help 从目å‰ç®¡ç†çš„虚拟 HUB 设置的无效è¯ä¹¦åå•ä¸­æŒ‡å®šæ— æ•ˆè¯ä¹¦çš„定义,获å–其定义的内容。\nç›®å‰æ³¨å†Œçš„无效è¯ä¹¦çš„定义列表,å¯ç”¨ CrlList 指令获å–。\n该指令虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n该指令在作为进群æ“作的 VPN Server 的虚拟æœåŠ¡å™¨ä¸Šä¸èƒ½æ‰§è¡Œã€‚
+CMD_CrlGet_Args CrlGet [id]
+CMD_CrlGet_[id] 指定è¦èŽ·å–的无效的è¯ä¹¦çš„定义中的 ID。
+CMD_CrlGet_Prompt_ID èŽ·å– ID:
+CMD_CrlGet_CN å (CN)
+CMD_CrlGet_O 所属机构 (O)
+CMD_CrlGet_OU 组织å•ä½ (OU)
+CMD_CrlGet_C 国家 (C)
+CMD_CrlGet_ST å·ž (ST)
+CMD_CrlGet_L 本地 (L)
+CMD_CrlGet_SERI åºåˆ—å· (å六进制)
+CMD_CrlGet_MD5_HASH MD5 摘è¦å€¼ (以å六进制,128 ä½)
+CMD_CrlGet_SHA1_HASH SHA-1 摘è¦å€¼ (以å六进制,160 ä½)
+
+
+# AcList 命令
+CMD_AcList 获å–æº IP 地å€è®¿é—®é™åˆ¶åˆ—表的规则项目列表
+CMD_AcList_Help 用本命令æ¥èŽ·å–ç›®å‰ç®¡ç†çš„虚拟 HUB ä¸Šè®¾ç½®çš„æº IP 地å€é™åˆ¶åˆ—表规则的列表。\næ ¹æ®å®¢æˆ·ç«¯ç”µè„‘çš„æº IP 地å€ï¼Œæ‚¨å¯ä»¥å…许或拒ç»å¯¹è¯¥è™šæ‹Ÿ HUB çš„ VPN 连接。å¯ä»¥å®šä¹‰å¤šä¸ªè§„则,设置æ¯ä¸ªè§„则的优先顺åºã€‚优先顺åºæŒ‰ç…§ä»Žé«˜åˆ°ä½Žé¡ºåºï¼Œæ ¹æ®æœ€å…ˆä¸Ž IP 地å€åŒ¹é…的规则è¿è¡Œï¼Œå…许或拒ç»ä»Žå®¢æˆ·ç«¯çš„连接。\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AcList_Args AcList
+
+
+# AcAdd 命令
+CMD_AcAdd 添加规则到 IP 地å€é™åˆ¶åˆ—表(IPv4)
+CMD_AcAdd_Help 在目å‰ç®¡ç†çš„虚拟 HUB 设置的 IP 地å€é™åˆ¶åˆ—表中添加新规则。\n当 VPN Client 试图连接虚拟 HUB 时,在此设置的项目决定å…许或拒ç»æ¥è‡ªè¯¥å®¢æˆ·ç«¯çš„连接。\nä½ å¯ä»¥æŒ‡å®šè§„则项目的内容相匹é…的客户端 IP 地å€ï¼Œæˆ–者 IP 地å€å’Œå­ç½‘掩ç ã€‚如果åªæŒ‡å®š IP 地å€ï¼Œä»…指定一å°ä¸Žè¯¥è§„则相匹é…的计算机;如果指定 IP 网络掩ç åœ°å€å’Œå­ç½‘掩ç åœ°å€ï¼Œè¯¥è§„则匹é…çš„å­ç½‘范围内的所有计算机å‡è¢«æŒ‡å®šã€‚\nå¯ä»¥è®¾ç½®è§„则的优先顺åºã€‚以大于 1 的整数指定优先顺åºï¼Œå€¼è¶Šå°åˆ™ä¼˜å…ˆé¡ºåºè¶Šé«˜ã€‚\nè¦èŽ·å–ç›®å‰æ³¨å†Œçš„æº IP 地å€é™åˆ¶åˆ—表,使用 AcList 命令。\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AcAdd_Args AcAdd [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd_[allow|deny] 设定å…许 ("allow") æˆ–æ‹’ç» ("deny") 与规则相一致的æ¥è‡ªå®¢æˆ·ç«¯çš„连接。
+CMD_AcAdd_PRIORITY 以大于 1 的整数指定该规则的优先顺åºã€‚其值越å°åˆ™ä¼˜å…ˆé¡ºåºè¶Šé«˜ã€‚
+CMD_AcAdd_IP 以 "IP 地å€/掩ç " çš„å½¢å¼æŒ‡å®šå®¢æˆ·ç«¯ IPv4 地å€èŒƒå›´ã€‚IPv4 地å€ä¸º "192.168.0.1" 那样的,指定为用点分隔的å进制数。掩ç ä¸º "255.255.255.0" 那样的,指定为用点分隔的å进制数,å¯ä»¥ç”¨å进制数指定 24 ä½ä»Žå¤´å¼€å§‹çš„比特长度,å¯ä½œä¸ºå进制 10 款规定。è¦æŒ‡å®šä¸€ä¸ªå•ç‹¬çš„ IPv4 主机,指定掩ç ä¸º "32" 或者 "255.255.255.255"
+CMD_AcAdd_Prompt_AD allow 或 deny:
+CMD_AcAdd_Prompt_PRIORITY 优先顺åº:
+CMD_AcAdd_Prompt_IP IPv4 地å€/掩ç :
+CMD_AcAdd_Eval_PRIORITY 优先级请指定 1 或以上的数字。
+
+
+# AcAdd6 命令
+CMD_AcAdd6 æ·»åŠ è§„åˆ™åˆ°æº IP 地å€è®¿é—®é™åˆ¶åˆ—表(IPv6)
+CMD_AcAdd6_Help 在目å‰ç®¡ç†çš„虚拟 HUB 设置的 IP 地å€é™åˆ¶åˆ—表中添加新规则。\n当 VPN Client 试图连接虚拟 HUB 时,在此设置的项目决定å…许或拒ç»æ¥è‡ªè¯¥å®¢æˆ·ç«¯çš„连接。\nä½ å¯ä»¥æŒ‡å®šè§„则项目的内容相匹é…的客户端 IP 地å€ï¼Œæˆ–者 IP 地å€å’Œå­ç½‘掩ç ã€‚如果åªæŒ‡å®š IP 地å€ï¼Œä»…指定一å°ä¸Žè¯¥è§„则相匹é…的计算机;如果指定 IP 网络掩ç åœ°å€å’Œå­ç½‘掩ç åœ°å€ï¼Œè¯¥è§„则匹é…çš„å­ç½‘范围内的所有计算机å‡è¢«æŒ‡å®šã€‚\nå¯ä»¥è®¾ç½®è§„则的优先顺åºã€‚以大于 1 的整数指定优先顺åºï¼Œå€¼è¶Šå°åˆ™ä¼˜å…ˆé¡ºåºè¶Šé«˜ã€‚\nè¦èŽ·å–ç›®å‰æ³¨å†Œçš„æº IP 地å€é™åˆ¶åˆ—表,使用 AcList 命令。\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AcAdd6_Args AcAdd6 [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd6_[allow|deny] 设定å…许 ("allow") æˆ–æ‹’ç» ("deny") 与规则相一致的æ¥è‡ªå®¢æˆ·ç«¯çš„连接。
+CMD_AcAdd6_PRIORITY 以大于 1 的整数指定该规则的优先顺åºã€‚其值越å°åˆ™ä¼˜å…ˆé¡ºåºè¶Šé«˜ã€‚
+CMD_AcAdd6_IP 以 [IP 地å€/掩ç ] çš„å½¢å¼æŒ‡å®šå®¢æˆ·ç«¯ IPv6 地å€èŒƒå›´ã€‚IPv6 地å€ä¸º 2001:200:0:1:: 那样的,指定由冒å·åˆ†éš”çš„å六进制数。掩ç ä¸º ffff:ffff:ffff:ffff:: 那样的,指定由冒å·åˆ†éš”çš„å六进制数,å¯ä»¥ç”¨å进制数指定 64 ä½ä»Žå¤´å¼€å§‹çš„比特长度,å¯ä½œä¸ºå进制 10 款规定。如果设定为 "::/128" 则显示å•ä¸€çš„主机。
+CMD_AcAdd6_Prompt_AD allow 或 deny:
+CMD_AcAdd6_Prompt_PRIORITY 优先顺åº:
+CMD_AcAdd6_Prompt_IP IPv6 地å€/掩ç :
+CMD_AcAdd6_Eval_PRIORITY 优先级请指定 1 或以上的数字。
+
+
+# AcDel 命令
+CMD_AcDel æº IP 地å€é™åˆ¶åˆ—表内的删除规则
+CMD_AcDel_Help 使用本命令删除目å‰ç®¡ç†çš„虚拟 HUB 设置的 IP 地å€é™åˆ¶åˆ—表的规则。\nè¦èŽ·å–ç›®å‰æ³¨å†Œçš„ IP 访问控制列表的规则列表,使用AcList命令。\n该指令虚拟专用桥ä¸èƒ½è¿è¡Œã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_AcDel_Args AcDel [id]
+CMD_AcDel_[id] 指定è¦åˆ é™¤çš„æº IP 地å€é™åˆ¶åˆ—表内的规则的 ID。
+CMD_AcDel_Prompt_ID è¦åˆ é™¤çš„规则的 ID:
+
+
+# LicenseAdd 命令
+CMD_LicenseAdd 注册新的许å¯è¯å¯†é’¥
+CMD_LicenseAdd_Help 在 SoftEther VPN Server 注册新的许å¯è¯å¯†é’¥ã€‚\nè¦ä½¿ç”¨ SoftEther VPN Server,需获å–有效的许å¯è¯ï¼Œå¹¶æ³¨å†Œè®¸å¯è¯å¯†é’¥ã€‚许å¯è¯å¯†é’¥æ˜¯ç”± 36 个字æ¯æ•°å­—字符和连字符 ( '-' ) 组æˆçš„,以è¯æ˜Žè®¸å¯è¯æ‰€æœ‰æƒçš„密钥的代ç ã€‚\n一起获得本软件åŠè®¸å¯è¯è¯ä¹¦æ—¶ï¼Œè®¸å¯è¯å¯†é’¥ä¼šè¢«å°åˆ·åœ¨è®¸å¯è¯è¯ä¹¦ä¸Šã€‚如果在线购买本软件的许å¯è¯æ—¶ï¼Œè®¸å¯è¯å¯†é’¥ä¼šåœ¨è´­ä¹°æ—¶çš„网页画é¢æˆ–邮件中记载。此外,许å¯è¯å¯†é’¥è¿˜å¯èƒ½å…¶ä»–以方法被记载。如有ä¸æ˜Žï¼Œè¯·å’¨è¯¢è®¸å¯è¯çš„销售方。\n\nè¦èŽ·å–ç›®å‰æ³¨å†Œçš„许å¯è¯åˆ—表,使用 LicenseList 指令。\nè¦æ˜¾ç¤ºç›®å‰ VPN Server 的许å¯è¯çŠ¶æ€ï¼Œä½¿ç”¨ LicenseStatus 指令。\nè¦è¿è¡Œæ­¤æŒ‡ä»¤ï¼Œéœ€è¦ VPN Server 的管ç†å‘˜æƒé™ã€‚\n该指令虚拟专用桥ä¸èƒ½è¿è¡Œã€‚
+CMD_LicenseAdd_Args LicenseAdd [key]
+CMD_LicenseAdd_[key] 指定è¦æ³¨å†Œçš„许å¯è¯å¯†é’¥ã€‚36 ä½å­—æ¯æ•°å­—,6 个一组以连字符分隔,进行指定。
+CMD_LicenseAdd_Prompt_Key 许å¯è¯å¯†é’¥:
+
+
+# LicenseDel 命令
+CMD_LicenseDel 删除已注册许å¯
+CMD_LicenseDel_Help 从 SoftEther VPN Server 上目å‰æ³¨å†Œçš„许å¯è¯åå•ä¸­åˆ é™¤æŒ‡å®šçš„许å¯è¯ã€‚\n\nè¦èŽ·å¾—ç›®å‰æ³¨å†Œçš„许å¯è¯åå•ï¼Œä½¿ç”¨ LicenseList 指令。\nè¦æ˜¾ç¤ºç›®å‰çš„ VPN Server 的许å¯è¯çŠ¶æ€ï¼Œä½¿ç”¨ LicenseStatus 指令。\nè¦è¿è¡Œæ­¤æŒ‡ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚
+CMD_LicenseDel_Args LicenseDel [id]
+CMD_LicenseDel_[id] 指定è¦åˆ é™¤çš„的许å¯è¯çš„å·ç ã€‚
+CMD_LicenseDel_Prompt_ID 删除许å¯è¯å·ç :
+
+
+# LicenseList 命令
+CMD_LicenseList 获得已注册许å¯è¯çš„列表
+CMD_LicenseList_Help 在 SoftEther VPN Server 上显示目å‰æ³¨å†Œè®¸å¯è¯çš„许å¯è¯å¯†é’¥ï¼Œè®¸å¯è¯ç±»åž‹ï¼ŒçŠ¶æ€ï¼Œæœ‰æ•ˆæœŸé™ï¼Œè®¸å¯è¯ ID,许å¯è¯ç±»åž‹ ID,æœåŠ¡å™¨ ID å’Œç¼–å· ID 的列表。\n\nè¦æ˜¾ç¤ºç›®å‰çš„ VPN Server 的许å¯è¯çŠ¶æ€ï¼Œä½¿ç”¨ LicenseStatus 指令。\nè¦è¿è¡Œæ­¤æŒ‡ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此命令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚
+CMD_LicenseList_Args LicenseList
+
+
+# LicenseStatus 命令
+CMD_LicenseStatus 获å–ç›®å‰çš„ VPN Server 状æ€
+CMD_LicenseStatus_Help 获å–å¹¶æ˜¾ç¤ºå½“å‰ SoftEther VPN Server 的许å¯è¯çŠ¶æ€ã€‚ \n显示 SoftEther VPN Server ç›®å‰äº§å“版本å称,æœåŠ¡å™¨ ID,产å“许å¯è¯çš„有效期é™ï¼ŒåŠå¯ä»¥åˆ©ç”¨çš„客户端连接许å¯è¯æ•°å’Œæ¡¥è¿žæŽ¥è®¸å¯è¯æ•°ã€‚\n\nè¦è¿è¡Œæ­¤æŒ‡ä»¤ï¼Œéœ€è¦ VPN Server 管ç†å‘˜æƒé™ã€‚\n此指令,虚拟专用桥ä¸èƒ½è¿è¡Œã€‚
+CMD_LicenseStatus_Args LicenseStatus
+
+# SoftEther VPN 4.0 添加的 命令
+# IPsecEnable 命令
+CMD_IPsecEnable å¯ç”¨æˆ–ç¦ç”¨ IPsec VPN Server 功能
+CMD_IPsecEnable_Help 在 SoftEther VPN Server 上å¯ç”¨æˆ–ç¦ç”¨IPsec VPN Server 功能。\n如果您ç¦ç”¨äº†æ­¤åŠŸèƒ½ï¼ŒVPN Server 上的虚拟 HUB 将会接å—从 L2TP 兼容的 PC,Mac OS X 和智能手机的远程 VPN 连接,åŒæ—¶ä¹Ÿä¼šæŽ¥å— EtherIP 站点到站点的 VPN 连接。从智能手机上的 VPN 连接,如iPhoneã€iPad å’Œ Android, 和从 Mac OS X å’Œ Windows 上的本地 VPN Client 的连接也都会接å—。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_IPsecEnable_Args IPsecEnable [/L2TP:yes|no] [/L2TPRAW:yes|no] [/ETHERIP:yes|no] [/PSK:pre-shared-key] [/DEFAULTHUB:default_hub]
+CMD_IPsecEnable_L2TP å¯ç”¨æˆ–ç¦ç”¨ L2TP over IPsec æœåŠ¡å™¨åŠŸèƒ½ã€‚è¦æŽ¥å—æ¥è‡ª iPhone, iPad, Android, Windows 或者 Mac OS X çš„ VPN 连接,请å¯ç”¨æœ¬é€‰é¡¹ã€‚
+CMD_IPsecEnable_L2TPRAW å¯ç”¨æˆ–ç¦ç”¨ L2TP æœåŠ¡å™¨åŠŸèƒ½ (未加密的原始 L2TP).è¦æŽ¥å—特殊 VPN 客æœç«¯ï¼Œè¯·å¯ç”¨æœ¬é€‰é¡¹ã€‚
+CMD_IPsecEnable_ETHERIP å¯ç”¨æˆ–ç¦ç”¨ EtherIP / L2TPv3 over IPsecæœåŠ¡å™¨åŠŸèƒ½(为站点到站点 VPN Server 功能). 兼容 EtherIP over IPsec 的路由器产å“å°±å¯ä»¥è¿žæŽ¥åˆ° VPN Server 上的虚拟 HUB ,并建æˆäºŒå±‚(以太网)网桥。
+CMD_IPsecEnable_PSK 指定 IPsec 预共享密钥。IPsec 预共享密钥通常称为 "PSK" 或者"秘钥"。指定一个 8 ä½æˆ–者å°äºŽ 8 ä½çš„密钥,并且将它分é…ç»™è¦è¿žæŽ¥åˆ°è¯¥ VPN Server 的用户。请注æ„:Google Android 4.0 有一个æ¼æ´ž bug,当预共享密钥是 10 ä½æˆ–以上时,会引å‘æ„外行为。介于这ç§æƒ…况,预共享密钥应该是 9 ä½æˆ–å°äºŽ 9 ä½ã€‚
+CMD_IPsecEnable_DEFAULTHUB 为防止é—æ¼ç”¨æˆ·å上的 HUB å,请指定默认的虚拟 HUB。用户应该指定他们的用户å,如 "用户å@目标虚拟 HUB å" æ¥è¿žæŽ¥æ­¤ L2TP æœåŠ¡å™¨ã€‚如果指定的虚拟 HUB 被é—æ¼ï¼Œé‚£ä¹ˆä¸Šè¿°HUB将会作为目标被使用。
+CMD_IPsecEnable_Prompt_L2TP å¯ç”¨ L2TP over IPsec æœåŠ¡å™¨åŠŸèƒ½(yes / no):
+CMD_IPsecEnable_Prompt_L2TPRAW å¯ç”¨åŽŸå§‹ L2TP æœåŠ¡å™¨åŠŸèƒ½(yes / no):
+CMD_IPsecEnable_Prompt_ETHERIP å¯ç”¨ EtherIP / L2TPv3 over IPsecæœåŠ¡å™¨åŠŸèƒ½(yes / no):
+CMD_IPsecEnable_Prompt_PSK IPsec 的预共享密钥(推è:最多 9 ä½)
+CMD_IPsecEnable_Prompt_DEFAULTHUB 为é¿å…在用户å中é—æ¼ HUB,请默认虚拟 HUB 。
+
+
+# IPsecGet 命令
+CMD_IPsecGet 获得当å‰IPsec VPN Server 设置
+CMD_IPsecGet_Help 获得并显示在 SoftEther VPN Server ä¸Šçš„å½“å‰ IPsec VPN Server 设置。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_IPsecGet_Args IPsecGet
+CMD_IPsecGet_PRINT_L2TP L2TP over IPsec æœåŠ¡å™¨åŠŸèƒ½å·²å¯ç”¨
+CMD_IPsecGet_PRINT_L2TPRAW 原始 L2TP æœåŠ¡å™¨åŠŸèƒ½å·²å¯ç”¨
+CMD_IPsecGet_PRINT_ETHERIP EtherIP / L2TPv3 over IPsec æœåŠ¡å™¨åŠŸèƒ½å·²å¯ç”¨
+CMD_IPsecGet_PRINT_PSK IPsec 预共享密钥字符串
+CMD_IPsecGet_PRINT_DEFAULTHUB 默认虚拟 HUB å
+
+
+# EtherIpClientAdd 命令
+CMD_EtherIpClientAdd 添加新的 EtherIP / L2TPv3 over IPsec 客户端设置æ¥æŽ¥å— EtherIP / L2TPv3 客户端设备
+CMD_EtherIpClientAdd_Help 添加一个新的设置æ¡ç›®å¯ç”¨ EtherIP / L2TPv3 over IPsec æœåŠ¡å™¨åŠŸèƒ½æ¥æŽ¥å—客户端设备。\n为了能够通过EtherIP / L2TPv3 over IPsec æœåŠ¡å™¨åŠŸèƒ½æŽ¥å—æ¥è‡ªè·¯ç”±å™¨çš„连接,您需è¦å®šä¹‰ä¸¤è€…之间的关系表。这两者分别是表示客户端兼容EtherIP / L2TPv3 over IPsec 路由器的IPsec Phase 1 字符串和目标虚拟 HUB çš„å称。\n在您使用 EtherIpClientAdd 命令添加了一个连接定义åŽï¼Œè¿™ä¸ªå®šä¹‰çš„连接设置将会被应用到, EtherIP / L2TPv3 over IPsec 客户端设备的接入请求会è¯ä¸­ã€‚\n用户å和密ç æ¡ç›®å¿…é¡»è¦åœ¨è™šæ‹Ÿ HUB 上注册。一个 EtherIP / L2TPv3 客户端会被认为它使用如上的用户信æ¯çš„身份连接到虚拟 HUB 。n\n为执行此命令,您必须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_EtherIpClientAdd_Args EtherIpClientAdd [ID] [/HUB:hubname] [/USERNAME:username] [/PASSWORD:password]
+CMD_EtherIpClientAdd_[ID] 指定一个 ISAKMP Phase 1 ID。这个 ID 必须与 EtherIP / L2TPv3 客户端的IDé…置完全相åŒã€‚如果. EtherIP 客户端用 IP 地å€ä½œä¸ºPhase 1 ID,您å¯ä»¥æŒ‡å®šåƒ ID 的字符类似的 IP 地å€ã€‚如果您指定 '*' (星å·),它将会是一个与任一ä¸ç¬¦åˆå…¶ä»–具体规则的客户端相符åˆçš„通é…符。
+CMD_EtherIpClientAdd_HUB 指定è¦è¿žæŽ¥çš„虚拟 HUB å称。
+CMD_EtherIpClientAdd_USERNAME 指定连接到目的虚拟 HUB 的用户å。
+CMD_EtherIpClientAdd_PASSWORD 指定连接到目的虚拟 HUB 的密ç ã€‚
+CMD_EtherIpClientAdd_Prompt_ID ISAKMP Phase 1 ID ('*' 是通é…符):
+CMD_EtherIpClientAdd_Prompt_HUB 虚拟 HUB å
+CMD_EtherIpClientAdd_Prompt_USERNAME 登录虚拟 HUB 的用户å
+CMD_EtherIpClientAdd_Prompt_PASSWORD 登录虚拟 HUB 的密ç 
+
+
+# EtherIpClientDelete 命令
+CMD_EtherIpClientDelete 删除一个 EtherIP / L2TPv3 over IPsec 客户端设置
+CMD_EtherIpClientDelete_Help 本命令删除一个通过使用 EtherIP / L2TPv3 over IPsec 功能æ¥æŽ¥å— VPN Client çš„æ¡ç›®ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_EtherIpClientDelete_Args EtherIpClientDelete [ID]
+CMD_EtherIpClientDelete_[ID] 指定一个è¦åˆ é™¤çš„ ISAKMP Phase 1 ID
+CMD_EtherIpClientDelete_Prompt_ID ISAKMP Phase 1 ID:
+
+
+# EtherIpClientList 命令
+CMD_EtherIpClientList èŽ·å¾—å½“å‰ EtherIP / L2TPv3 客户端设备æ¡ç›®å®šä¹‰åˆ—表
+CMD_EtherIpClientList_Help 这个命令会获得和显示通过 EtherIP / L2TPv3 over IPsec 功能æ¥æŽ¥å— VPN Client æ¡ç›®çš„列表。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_EtherIpClientList_Args EtherIpClientList
+
+
+# OpenVpnEnable 命令
+CMD_OpenVpnEnable å¯ç”¨/ç¦ç”¨ OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½
+CMD_OpenVpnEnable_Help 本 VPN Server 有 OpenVPN Technologies, Inc. å…¬å¸ç”Ÿäº§çš„ OpenVPN 软件产å“的克隆功能。任何 OpenVPN Client 都å¯ä»¥è¿žæŽ¥åˆ°æœ¬ VPN Server。\n\n指定用户å连接到虚拟 HUB çš„çš„æ–¹å¼ï¼Œä½¿ç”¨æœ¬å…‹éš†æœåŠ¡å™¨åŠŸèƒ½æ¥ä¸ºé»˜è®¤è™šæ‹Ÿ HUB 的选择规则都与 IPsec æœåŠ¡å™¨åŠŸèƒ½ç›¸åŒã€‚详情,请å‚è§ IPsecEnable 命令的帮助。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_OpenVpnEnable_Args OpenVpnEnable [yes|no] [/PORTS:udp_port_list]
+CMD_OpenVpnEnable_[yes|no] 指定 "yes",å¯ç”¨ OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½ã€‚指定 "no" ç¦ç”¨è¯¥åŠŸèƒ½ã€‚
+CMD_OpenVpnEnable_PORTS 指定UDP端å£ç›‘å¬ OpenVPN 。指定多个 UDP 端å£å¯ä»¥ç”¨ç©ºæ ¼æˆ–者逗å·åˆ†å¼€æ¥å®ƒä»¬ï¼Œä¾‹å¦‚: "1194, 2001, 2010, 2012"。OpenVPN 的默认端å£æ˜¯ UDP 1194。您也å¯ä»¥æŒ‡å®šä»»ä¸€å…¶ä»– UDP 端å£ã€‚
+CMD_OpenVpnEnable_Prompt_[yes|no] å¯ç”¨ OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½ (yes / no):
+CMD_OpenVpnEnable_Prompt_PORTS ç›‘å¬ OpenVPN çš„ UDP 端å£(默认: 1194 /也å¯è®¾ç½®å¤šç«¯å£):
+
+
+# OpenVpnGet 命令
+CMD_OpenVpnGet èŽ·å– OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½çš„当å‰è®¾ç½®
+CMD_OpenVpnGet_Help 获å–并显示 OpenVPN 克隆æœåŠ¡å™¨åŠŸèƒ½çš„当å‰è®¾ç½®ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_OpenVpnGet_Args OpenVpnGet
+CMD_OpenVpnGet_PRINT_Enabled OpenVPN 克隆æœåŠ¡å™¨å·²å¯ç”¨
+CMD_OpenVpnGet_PRINT_Ports UDP 端å£åˆ—表
+
+# OpenVpnMakeConfig 命令
+CMD_OpenVpnMakeConfig ç”Ÿæˆ OpenVPN Client 样本设置文件
+CMD_OpenVpnMakeConfig_Help 原æ¥ï¼ŒOpenVPN Client 会è¦æ±‚用户手写很难的é…置文件。本工具å¯ä»¥å¸®åŠ©æ‚¨åˆ›å»ºä¸€ä¸ªæœ‰ç”¨çš„é…置样本。你所需è¦ç”Ÿæˆçš„ OpenVPN Client é…置文件就是è¿è¡Œæ­¤å‘½ä»¤ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_OpenVpnMakeConfig_Args OpenVpnMakeConfig [ZIP_FileName]
+CMD_OpenVpnMakeConfig_[ZIP_FileName] 指定以 ZIP 压缩格å¼ä¿å­˜çš„输出文件。如果没指定文件åŽç¼€ï¼Œé‚£ä¹ˆ".zip" åŽç¼€å°±ä¼šè¢«æ·»åŠ åœ¨æ–‡ä»¶å上。
+CMD_OpenVpnMakeConfig_Prompt_ZIP 设置文件夹的输出文件å。(ZIP 压缩文件):
+CMD_OpenVpnMakeConfig_OK 样本设置文件被ä¿å­˜ä¸º "%s"。您å¯ä»¥è§£åŽ‹æ­¤æ–‡ä»¶ä»¥èŽ·å–设置文件。\n
+CMD_OpenVpnMakeConfig_ERROR 本样本设置文件ä¸èƒ½ä¿å­˜ä¸º "%s"。该文件å无效。\n
+
+
+# SstpEnable 命令
+CMD_SstpEnable å¯ç”¨/ç¦ç”¨ Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½
+CMD_SstpEnable_Help 本 VPN Server 拥有æ¤å…¥åœ¨å¾®è½¯ Windows Server 2008 / 2012 中的 MS-SSTP VPN Server 的克隆功能。Windows Vista / 7 / 8 / RT 中的标准 MS-SSTP 用户端å¯ä»¥è¿žæŽ¥æœ¬ VPN Server。\n\n[注æ„]\n在 VPN Server 上的 SSL è¯ä¹¦ CN 值必须è¦å’ŒæŒ‡å®šç»™å®¢æˆ·ç«¯çš„主机åå»åˆã€‚并且,该è¯ä¹¦å¿…须在 SSTP VPN Client 的信任列表中。详情请å‚è§å¾®è½¯ç›¸å…³æ–‡ä»¶ã€‚\n您å¯ä»¥ç”¨ç”¨ ServerCertRegenerate 命令æ¥å–ä»£å½“å‰ VPN Server çš„è¯ä¹¦ï¼Œå½¢æˆä¸€ä¸ªæ–°çš„,有 CN 值字段的自我认è¯è¯ä¹¦ã€‚这样的è¯ï¼Œæ‚¨éœ€è¦åœ¨ SSTP VPN Client 注册这样一个新的自我认è¯è¯ä¹¦ä½œä¸ºä¸€ä¸ªå¯ä¿¡ä»»æ ¹è¯ä¹¦ã€‚如果您的确想åšè¿™ä»¶å¤æ‚的事,请考虑购买一个商业æƒå¨æœºæž„çš„ SSL è¯ä¹¦ï¼Œå¦‚ VeriSign 或者 GlobalSign。\n\n指定用户å连接到虚拟 HUB çš„çš„æ–¹å¼ï¼Œä½¿ç”¨æœ¬å…‹éš†æœåŠ¡å™¨åŠŸèƒ½æ¥ä¸ºé»˜è®¤è™šæ‹Ÿ HUB 的选择规则都与 IPsec æœåŠ¡å™¨åŠŸèƒ½ç›¸åŒã€‚详情,请å‚è§ IPsecEnable 命令的帮助。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_SstpEnable_Args SstpEnable [yes|no]
+CMD_SstpEnable_[yes|no] 指定 "yes",å¯ç”¨Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½ã€‚指定 "no" ç¦ç”¨è¯¥åŠŸèƒ½ã€‚
+CMD_SstpEnable_Prompt_[yes|no] å¯ç”¨ SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½(yes/no):
+CMD_SstpEnable_PRINT_Enabled SSTP VPN 克隆æœåŠ¡å™¨å·²ç¦ç”¨
+
+
+# SstpGet 命令
+CMD_SstpGet 获得 Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½çš„当å‰è®¾ç½®
+CMD_SstpGet_Help 获得并显示 Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½çš„当å‰è®¾ç½®ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_SstpGet_Args SstpGet
+
+
+# ServerCertRegenerate 命令
+CMD_ServerCertRegenerate 生æˆä¸€ä¸ªæ–°çš„带有指定 CN (Common Name) 的自签åè¯ä¹¦ï¼Œå¹¶ä¸”在 VPN Server 上注册。
+CMD_ServerCertRegenerate_Help 您å¯ä»¥ä½¿ç”¨æ­¤å‘½ä»¤ï¼Œå°†å½“å‰ VPN Server 上的è¯ä¹¦æ›¿æ¢æˆä¸€ä¸ªæ–°çš„ã€æœ‰ CN (Common Name) 值字段的ã€è‡ªç­¾å­—è¯ä¹¦ã€‚n\n此命令在您想使用 Microsoft SSTP VPN 克隆æœåŠ¡å™¨åŠŸèƒ½æ—¶å¾ˆæ–¹ä¾¿ã€‚因为在 VPN Server 上 SSL è¯ä¹¦çš„ CN 值必须è¦ä¸Ž SSTP VPN Client 指定的主机åå»åˆã€‚\n详情å‚è§ SstpEnable 命令的帮助。\n\n本命令会删除 VPN Server 上现有的 SSL è¯ä¹¦ã€‚è¿™è¦æ±‚事先使用 ServerKeyGet 命令备份当å‰çš„ SSL è¯ä¹¦å’Œå¯†é’¥ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN Server 的虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_ServerCertRegenerate_Args ServerCertRegenerate [CN]
+CMD_ServerCertRegenerate_[CN] 指定一个新è¯ä¹¦è¦ä½¿ç”¨çš„ Common Name(CN)
+CMD_ServerCertRegenerate_Prompt_CN Common Name(CN)值:
+
+
+# VpnOverIcmpDnsEnable 命令
+CMD_VpnOverIcmpDnsEnable å¯ç”¨/ç¦ç”¨ VPN over ICMP / VPN over DNSæœåŠ¡å™¨åŠŸèƒ½
+CMD_VpnOverIcmpDnsEnable_Help å³ä½¿æœ‰é˜²ç«å¢™æˆ–者有å±è”½TCP/IP通信的路由器,您也å¯ä»¥åªç”¨ ICMP 或者 DNS æ•°æ®åŒ…建立一个 VPN 。您需è¦äº‹å…ˆå¯ç”¨å¦‚下功能。\n\n注æ„:本功能仅在紧急情况下使用。它在有防ç«å¢™æˆ–者路由器被错误é…ç½®å±è”½ TCP/IP æ—¶,并且 ICMP å’Œ DNS 都没有被å±è”½çš„情况下å¯ä½¿ç”¨ã€‚它ä¸æ˜¯ä¸ºé•¿æœŸç¨³å®šä½¿ç”¨çš„。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚
+CMD_VpnOverIcmpDnsEnable_Args VpnOverIcmpDnsEnable [/ICMP:yes|no] [/DNS:yes|no]
+CMD_VpnOverIcmpDnsEnable_ICMP 指定 "yes",å¯ç”¨ VPN over ICMP æœåŠ¡å™¨ã€‚指定 "no",ç¦ç”¨ã€‚
+CMD_VpnOverIcmpDnsEnable_DNS 指定 "yes",å¯ç”¨ VPN over DNSæœåŠ¡å™¨ã€‚指定 "no",ç¦ç”¨ã€‚
+CMD_VpnOverIcmpDnsEnable_Prompt_ICMP å¯ç”¨ VPN over ICMPæœåŠ¡å™¨ (yes/no):
+CMD_VpnOverIcmpDnsEnable_Prompt_DNS å¯ç”¨ VPN over DNSæœåŠ¡å™¨ (yes/no):
+
+# VpnOverIcmpDnsGet 命令
+CMD_VpnOverIcmpDnsGet èŽ·å– VPN over ICMP / VPN over DNS 功能的当å‰è®¾ç½®
+CMD_VpnOverIcmpDnsGet_Help 获得并显示 VPN over ICMP / VPN over DNS 功能的当å‰çŠ¶æ€ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚
+CMD_VpnOverIcmpDnsGet_Args VpnOverIcmpDnsGet
+CMD_VpnOverIcmpDnsGet_PRINT_ICMP VPN over ICMP æœåŠ¡å™¨å·²å¼€å¯
+CMD_VpnOverIcmpDnsGet_PRINT_DNS VPN over DNS æœåŠ¡å™¨å·²ç¦ç”¨
+
+
+# DynamicDnsGetStatus 命令
+CMD_DynamicDnsGetStatus æ˜¾ç¤ºåŠ¨æ€ DNS 功能的当å‰çŠ¶æ€
+CMD_DynamicDnsGetStatus_Help èŽ·å¾—å¹¶æ˜¾ç¤ºåŠ¨æ€ DNS 功能的当å‰çŠ¶æ€ã€‚\n\nåŠ¨æ€ DNS 会为本 VPN Server 分é…一个唯一的和永久的 DNS 主机å。您å¯ä»¥åœ¨è®¾ç½® VPN Client å’Œ VPN Bridge 时使用该主机å指定的 VPN Server。您ä¸å¿…注册并且ä¿å­˜åŸŸå。\nåŒæ—¶ï¼Œå¦‚果您的 ISP 分派给您一个动æ€(ä¸ç¨³å®š) IP 地å€ï¼Œæ‚¨çš„åŠ¨æ€ DNS 主机å相应的 IP 地å€ä¹Ÿå°†ä¼šè‡ªåŠ¨æ”¹å˜ã€‚它使您åªç”¨åŠ¨æ€ IP 地å€å°±å¯ä»¥ä¿æŒ VPN Server çš„è¿è¡Œã€‚\r\n因此,您å†ä¹Ÿä¸éœ€è¦ä¸ºäº†ç»´æŒé™æ€å…¨çƒ IP 地å€ï¼Œæ¯æœˆèŠ±è´¹è´¹ç”¨äº†ã€‚\n[注æ„]\nè¦ç¦æ­¢åŠ¨æ€ DNS 功能,修改 VPN Server å’Œé…置文件。\r\n\r\n"declare root" 指令有"declare DDnsClient"指令。在本指令中,那你å¯ä»¥ä»Žé”™è¯¯åˆ°æ­£ç¡®åˆ‡æ¢"bool disable",并é‡å¯ VPN Server ï¼Œè¿™æ ·ï¼ŒåŠ¨æ€ DNS 功能就ç¦ç”¨äº†ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚
+CMD_DynamicDnsGetStatus_Args DynamicDnsGetStatus
+CMD_DynamicDnsGetStatus_PRINT_FQDN 分é…çš„åŠ¨æ€ DNS 主机å (FQDN)
+CMD_DynamicDnsGetStatus_PRINT_HOSTNAME 分é…çš„åŠ¨æ€ DNS 主机å (主机å)
+CMD_DynamicDnsGetStatus_PRINT_SUFFIX DNS åŽç¼€
+CMD_DynamicDnsGetStatus_PRINT_IPv4 å…¨çƒ IPv4 地å€
+CMD_DynamicDnsGetStatus_PRINT_IPv6 å…¨çƒ IPv6 地å€
+
+
+# DynamicDnsSetHostname 命令
+CMD_DynamicDnsSetHostname è®¾ç½®åŠ¨æ€ DNS 主机å
+CMD_DynamicDnsSetHostname_Help 您å¯ä»¥ç”¨æœ¬å‘½ä»¤æ›´æ”¹åŠ¨æ€ DNS 功能分é…的主机å。当å‰åˆ†é…的主机åå¯ä»¥é€šè¿‡ä½¿ç”¨ DynamicDnsGetStatus 命令æ¥æ˜¾ç¤ºã€‚\n\nåŠ¨æ€ DNS 为 VPN Server 分é…了一个唯一的和永久的 DNS 主机å。您å¯ä»¥åœ¨è®¾ç½® VPN Client å’Œ VPN Bridge 时使用该主机å指定的 VPN Server。您ä¸å¿…注册并且ä¿å­˜åŸŸå。\nåŒæ—¶ï¼Œå¦‚果您的 ISP 分派给您一个动æ€(ä¸ç¨³å®š) IP 地å€ï¼Œæ‚¨çš„åŠ¨æ€ DNS 主机å相应的 IP 地å€ä¹Ÿå°†ä¼šè‡ªåŠ¨æ”¹å˜ã€‚它使您åªç”¨åŠ¨æ€ IP 地å€å°±å¯ä»¥ä¿æŒ VPN Server çš„è¿è¡Œã€‚\r\n因此,您å†ä¹Ÿä¸éœ€è¦ä¸ºäº†ç»´æŒé™æ€å…¨çƒ IP 地å€ï¼Œæ¯æœˆèŠ±è´¹è´¹ç”¨äº†ã€‚\n[注æ„]\nè¦ç¦æ­¢åŠ¨æ€ DNS 功能,修改 VPN Server å’Œé…置文件。\r\n\r\n"declare root" 指令有"declare DDnsClient"指令。在本指令中,那你å¯ä»¥ä»Žé”™è¯¯åˆ°æ­£ç¡®åˆ‡æ¢"bool disable",并é‡å¯ VPN Serverï¼Œè¿™æ ·ï¼ŒåŠ¨æ€ DNS 功能就ç¦ç”¨äº†ã€‚\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œæ‚¨å¿…须具有 VPN Server 管ç†å‘˜æƒé™ã€‚\n该命令在 VPN Bridge 上ä¸èƒ½è¿è¡Œã€‚
+CMD_DynamicDnsSetHostname_Args DynamicDnsSetHostname [hostname]
+CMD_DynamicDnsSetHostname_[hostname] 指定新的主机å,主机å长度最短3个字æ¯ï¼Œæœ€é•¿ä¸º 31 个字æ¯ã€‚ä»…é™æ•°å­—和字æ¯ã€‚
+CMD_DynamicDnsSetHostname_Prompt_hostname Dynamic åŠ¨æ€ DNS 主机å (3 – 31 个字æ¯):
+
+
+# VpnAzureGetStatus command
+CMD_VpnAzureGetStatus 显示 VPN Azure 功能的当å‰çŠ¶æ€
+CMD_VpnAzureGetStatus_Help 获å–和显示 VPN Azure 功能的当å‰çŠ¶æ€ã€‚\n\nVPN Azure å¯ä»¥æ›´å®¹æ˜“地从你家里的计算机到你办公室的计算机建立一个VPN会è¯ã€‚当一个 VPN 连接建立了,您å¯ä»¥è®¿é—®æ‚¨å…¬å¸ä¸“用网络上的任何其他æœåŠ¡å™¨ã€‚在办公室的计算机(VPN æœåŠ¡å™¨ï¼‰ä¸Šï¼Œä½ å¹¶ä¸éœ€è¦ä¸€ä¸ªå…¨çƒ IP 地å€ã€‚它å¯ä»¥åœ¨é˜²ç«å¢™æˆ– NAT åŽé¢å·¥ä½œã€‚无需网络管ç†å‘˜çš„é…置。您å¯ä»¥åœ¨æ‚¨çš„家用电脑使用 Windows 内置的 SSTP VPN 客户端。\nVPN Azure 是一个云 VPN æœåŠ¡ç”± SoftEther å…¬å¸ç»è¥ã€‚VPN Azure 是å…费的,å¯æ供给任何人。访问 http://www.vpnazure.net/ 查看详细信æ¯å’Œå¦‚何使用的说明。\n\nVPN Azure 主机åä¸ŽåŠ¨æ€ DNS 设置的主机å相åŒï¼Œä½†æ”¹å˜çš„域ååŽç¼€ä¸ºâ€œvpnazure.netâ€ã€‚è¦æ”¹å˜ä¸»æœºå使用 DynamicDnsSetHostname 命令。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œä½ å¿…须具有VPN æœåŠ¡å™¨ç®¡ç†å‘˜æƒé™ã€‚\n此命令ä¸èƒ½åœ¨ VPN 网桥上è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN æœåŠ¡å™¨çš„虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_VpnAzureGetStatus_Args VpnAzureGetStatus
+CMD_VpnAzureGetStatus_PRINT_ENABLED VPN Azure 功能已å¯ç”¨
+CMD_VpnAzureGetStatus_PRINT_CONNECTED 至 VPN Azure 云æœåŠ¡å™¨çš„连接建立
+CMD_VpnAzureGetStatus_PRINT_HOSTNAME 在 VPN Azure æœåŠ¡ä¸Šçš„本 VPN æœåŠ¡å™¨çš„主机å
+
+
+# VpnAzureSetStatus command
+CMD_VpnAzureSetEnable å¯ç”¨/ç¦ç”¨ VPN Azure 功能
+CMD_VpnAzureSetEnable_Help å¯ç”¨æˆ–ç¦ç”¨ VPN Azure 功能。\n\nVPN Azure å¯ä»¥æ›´å®¹æ˜“地从你家里的计算机到你办公室的计算机建立一个 VPN 会è¯ã€‚当一个 VPN 连接建立了,您å¯ä»¥è®¿é—®æ‚¨å…¬å¸ä¸“用网络上的任何其他æœåŠ¡å™¨ã€‚\n在办公室的计算机(VPN æœåŠ¡å™¨ï¼‰ä¸Šï¼Œä½ å¹¶ä¸éœ€è¦ä¸€ä¸ªå…¨çƒ IP 地å€ã€‚它å¯ä»¥åœ¨é˜²ç«å¢™æˆ– NAT åŽé¢å·¥ä½œã€‚无需网络管ç†å‘˜çš„é…置。您å¯ä»¥åœ¨æ‚¨çš„家用电脑使用 Windows 内置的 SSTP VPN 客户端。\nVPN Azure 是一个云 VPN æœåŠ¡ç”± SoftEther å…¬å¸ç»è¥ã€‚VPN Azure 是å…费的,å¯æ供给任何人。访问 http://www.vpnazure.net/ 查看详细信æ¯å’Œå¦‚何使用的说明。\n\nVPN Azure 主机åä¸ŽåŠ¨æ€ DNS 设置的主机å相åŒï¼Œä½†æ”¹å˜çš„域ååŽç¼€ä¸ºâ€œvpnazure.netâ€ã€‚è¦æ”¹å˜ä¸»æœºå使用 DynamicDnsSetHostname 命令。\n\nè¦æ‰§è¡Œæ­¤å‘½ä»¤ï¼Œä½ å¿…须具有 VPN æœåŠ¡å™¨ç®¡ç†å‘˜æƒé™ã€‚\n此命令ä¸èƒ½åœ¨ VPN 网桥上è¿è¡Œã€‚\n以集群æˆå‘˜è¿è¡Œçš„ VPN æœåŠ¡å™¨çš„虚拟 HUB ä¸èƒ½æ‰§è¡Œæ­¤å‘½ä»¤ã€‚
+CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no]
+CMD_VpnAzureSetEnable_[yes|no] 指定“yesâ€ï¼Œå¯ç”¨ VPN Azure。“noâ€ç¦ç”¨å®ƒã€‚
+CMD_VpnAzureSetEnable_PROMPT å¯ç”¨ VPN Azure (yes/no):
+
+
+
+#######################################################
+# #
+#在这里往下是 VPN Client 用的管ç†å‘½ä»¤ #
+# #
+#######################################################
+
+
+# VersionGet 命令
+CMD_VersionGet èŽ·å– VPN 客户æœåŠ¡çš„版本信æ¯
+CMD_VersionGet_Help 获å–ç›®å‰ç®¡ç†çš„ VPN 客户æœåŠ¡ç¨‹åºçš„版本信æ¯ã€‚
+CMD_VersionGet_Args VersionGet
+CMD_VersionGet_1 产å“å
+CMD_VersionGet_2 版本信æ¯
+CMD_VersionGet_3 建设信æ¯
+CMD_VersionGet_4 进程 ID
+CMD_VersionGet_5 æ“作系统类型
+
+
+# PasswordSet 命令
+CMD_PasswordSet 为连接到 VPN 客户æœåŠ¡çš„密ç çš„设定
+CMD_PasswordSet_Help 对 VPN Client æœåŠ¡ï¼Œä»Žå‘½ä»¤è¡Œç®¡ç†å·¥å…·åŠ VPN Client ç»ç†æ¥è¿›è¡Œè¿žæŽ¥æŽ§åˆ¶æ—¶ï¼Œå¯ä»¥è¦æ±‚输入密ç ã€‚使用此指令,å¯ä»¥è®¾ç½®è¦æ±‚输入的密ç ã€‚\n以åªå¯¹ä»Žè¿œç¨‹ (本地主机以外的电脑) 进行æ“作时è¦æ±‚其输入密ç ã€‚
+CMD_PasswordSet_Args PasswordSet [password] [/REMOTEONLY:yes|no]
+CMD_PasswordSet_[password] 指定è¦è®¾ç½®çš„密ç ã€‚如指定为 "none",å¯ä»¥åˆ é™¤å¯†ç çš„设置。
+CMD_PasswordSet_REMOTEONLY 如果指定 "yes",åªå¯¹ä»Žè¿œç¨‹ (本地主机以外的电脑) 进行æ“作时è¦æ±‚其输入密ç ï¼Œä»Žæœ¬åœ°ä¸»æœºè¿žæŽ¥æ—¶ï¼Œä¸è¦æ±‚密ç ã€‚如果çœç•¥æ­¤å‚数,则视为 "no"。
+
+
+# PasswordGet 命令
+CMD_PasswordGet 获å–为连接到 VPN 客户æœåŠ¡çš„密ç çš„设定
+CMD_PasswordGet_Help 对 VPN Client æœåŠ¡ï¼Œä»Žå‘½ä»¤è¡Œç®¡ç†å·¥å…·åŠ VPN Client ç»ç†æ¥è¿›è¡Œè¿žæŽ¥æŽ§åˆ¶æ—¶ï¼ŒèŽ·å–是å¦è¦æ±‚输入密ç çš„设置。\n而且,对于è¦æ±‚密ç çš„情况下,获å–是å¦è®¾ç½®åªå¯¹ä»Žè¿œç¨‹ (本地主机以外的电脑) 进行æ“作的情况è¦æ±‚输入密ç ã€‚
+CMD_PasswordGet_Args PasswordGet
+CMD_PasswordGet_1 设置密ç 
+CMD_PasswordGet_2 åªéœ€è¦è¿œç¨‹è¿žæŽ¥æ—¶ä½¿ç”¨å¯†ç 
+
+
+# CertList 命令
+CMD_CertList 获å–信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表
+CMD_CertList_Help VPN Client 管ç†ä¿¡ç”¨çš„è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表。已注册的è¯æ˜Žæœºæž„è¯ä¹¦çš„注册列表,用æ¥è¿›è¡Œè¿žæŽ¥ VPN Server 时的验è¯æœåŠ¡å™¨è¯ä¹¦ã€‚
+CMD_CertList_Args CertList
+
+
+# CertAdd 命令
+CMD_CertAdd 添加信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦
+CMD_CertAdd_Help å‘ VPN Client 信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表添加新è¯ä¹¦ã€‚已注册的è¯æ˜Žæœºæž„è¯ä¹¦çš„注册列表,用æ¥è¿›è¡Œè¿žæŽ¥ VPN Server 时的验è¯æœåŠ¡å™¨è¯ä¹¦ã€‚\nè¦èŽ·å–当å‰çš„è¯ä¹¦åˆ—表,使用 CertList 指令。\nè¦æ·»åŠ è¯ä¹¦ï¼Œè¯¥è¯ä¹¦éœ€è¦ä¿å­˜ä¸º X.509 æ ¼å¼çš„文件。
+CMD_CertAdd_Args CertAdd [path]
+CMD_CertAdd_[path] 指定è¦æ³¨å†Œçš„ X.509 è¯ä¹¦çš„文件å。
+
+
+# CertDelete 命令
+CMD_CertDelete 删除信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦
+CMD_CertDelete_Help 从 VPN Client 信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表中删除现有的è¯ä¹¦ã€‚\nè¦èŽ·å–当å‰çš„è¯ä¹¦åˆ—表,使用 CertList 命令。
+CMD_CertDelete_Args CertDelete [id]
+CMD_CertDelete_[id] 指定è¦åˆ é™¤çš„è¯ä¹¦çš„ ID。
+
+
+# CertGet 命令
+CMD_CertGet 获得新任的è¯æ˜Žæœºæž„çš„è¯ä¹¦
+CMD_CertGet_Help èŽ·å– VPN Client 信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表中的现有è¯ä¹¦ï¼Œä»¥ X.509 æ ¼å¼æ–‡ä»¶ä¿å­˜ã€‚
+CMD_CertGet_Args CertGet [id] [/SAVECERT:path]
+CMD_CertGet_[id] 指定è¦èŽ·å–çš„è¯ä¹¦ ID。
+CMD_CertGet_SAVECERT 指定获å–到的è¯ä¹¦çš„ä¿å­˜æ–‡ä»¶å。
+
+
+# SecureList 命令
+CMD_SecureList 获å–å¯ç”¨çš„智能å¡ç§ç±»åˆ—表
+CMD_SecureList_Help VPN Client 显示的被支æŒçš„智能å¡ç±»åž‹çš„列表。\n智能å¡ç±»åž‹çš„列表,目å‰çš„计算机上被安装驱动程åºï¼Œä¸”显示以 VPN 软件支æŒçš„设备列表。\n\n如果没有显示目å‰ä½¿ç”¨çš„智能å¡åž‹ï¼Œæˆ–许å¯ä»¥é€šè¿‡æ›´æ–° VPN 软件至新的版本æ¥ä½¿ç”¨ã€‚
+CMD_SecureList_Args SecureList
+
+
+# SecureSelect 命令
+CMD_SecureSelect 选择è¦ä½¿ç”¨çš„智能å¡ç§ç±»
+CMD_SecureSelect_Help 选择 VPN 客户使用的智能å¡ç±»åž‹ã€‚\nå¯ä»¥ä½¿ç”¨çš„智能å¡ç§ç±»åˆ—表,å¯ç”¨ SecureList 指令获å–。
+CMD_SecureSelect_Args SecureSelect [id]
+CMD_SecureSelect_[id] 指定智能å¡ç§ç±»çš„ ID。
+CMD_SecureSelect_PROMPT_ID 使用的智能å¡ç§ç±»çš„ ID:
+
+
+# SecureGet 命令
+CMD_SecureGet 获å–使用的智能å¡ç§ç±»çš„ ID
+CMD_SecureGet_Help 获å–ä¸ºå½“å‰ VPN 客户的使用而设置的智能å¡ç§ç±»çš„ ID。通过基于此 ID 上的 SecureList 指令的结果,å¯ä»¥èŽ·å–当å‰é€‰æ‹©çš„智能å¡ç±»åž‹ã€‚\n如果当å‰çš„智能å¡æ²¡æœ‰è¢«é€‰æ‹©ï¼ŒID 显示是 0。
+CMD_SecureGet_Args SecureGet
+CMD_SecureGet_Print 当å‰é€‰æ‹©çš„æ™ºèƒ½å¡ ID 是 %u。
+CMD_SecureGet_NoPrint 智能å¡ç›®å‰æ²¡æœ‰è¢«é€‰æ‹©ã€‚
+
+
+# NicCreate 命令
+CMD_NicCreate 新的虚拟 LAN å¡çš„创建
+CMD_NicCreate_Help 将新的虚拟 LAN å¡æ·»åŠ åˆ°ç³»ç»Ÿã€‚å¯ä»¥å¯¹è™šæ‹Ÿ LAN å¡ä»»æ„命å。\n然而,给虚拟 LAN å¡å‘½åæ—¶åªèƒ½ä½¿ç”¨è‹±æ–‡å­—æ¯æ•°å­—,Windows 2000 以上的系统最大å¯è®¾ç½® 31 个字符,Windows 98,98 SE å’Œ ME 系统最大å¯è®¾ç½® 4 个字符。\n调用了 NicCreate 指令时,VPN Client è¿è¡Œçš„æ“作系统,将被安装新的虚拟 LAN å¡è®¾å¤‡é©±åŠ¨ç¨‹åºã€‚\n在此情况下,æ“作系统å¯èƒ½ä¼šæ˜¾ç¤ºå¯¹è¯æ¡†ï¼Œç¡®è®¤æ˜¯å¦è¦å®‰è£…设备驱动程åºã€‚
+CMD_NicCreate_Args NicCreate [name]
+CMD_NicCreate_[name] 指定虚拟 LAN å¡å。
+CMD_NicCreate_PROMPT_NAME 虚拟 LAN å¡å:
+
+
+# NicDelete 命令
+CMD_NicDelete 删除虚拟 LAN å¡
+CMD_NicDelete_Help 从系统中删除现有的虚拟 LAN å¡ã€‚\n当从系统中删除虚拟 LAN å¡ï¼Œä½¿ç”¨æ­¤è™šæ‹Ÿ LAN å¡çš„连接将被中断。\n而且,ä½ä½¿ç”¨è¢«åˆ é™¤çš„虚拟 LAN å¡è€Œè®¾ç½®çš„连接设置,自动更改设置为使用别的虚拟 LAN å¡ã€‚\n当 VPN 客户è¿è¡Œ Windows 2000 以上的æ“纵系统时,此指令å¯ä»¥è¢«ä½¿ç”¨ã€‚
+CMD_NicDelete_Args NicDelete [name]
+CMD_NicDelete_[name] 指定的虚拟 LAN å¡å
+
+
+# NicUpgrade 命令
+CMD_NicUpgrade å‡çº§è™šæ‹Ÿ LAN å¡è®¾å¤‡é©±åŠ¨
+CMD_NicUpgrade_Help 如果现有的虚拟 LAN å¡çš„设备驱动程åºç‰ˆæœ¬å¤ªæ—§ï¼Œåœ¨å½“å‰æ­£åœ¨è¿è¡Œçš„ VPN Client å‡çº§åˆ°åŒåŒ…附带的最新的设备驱动程åºã€‚å³ä½¿ä¸è¿›è¡Œå‡çº§ï¼Œä¹Ÿè¦é‡æ–°å®‰è£…设备驱动程åºã€‚\næ“作系统å¯èƒ½ä¼šæ˜¾ç¤ºå¯¹è¯æ¡†ï¼Œç¡®è®¤æ˜¯å¦è¦å®‰è£…设备驱动程åºã€‚\n此指令,在 VPN Client æ­£è¿è¡Œ Windows 2000 以上的æ“作系统时能够使用。
+CMD_NicUpgrade_Args NicUpgrade [name]
+CMD_NicUpgrade_[name] 指定的虚拟 LAN å¡å
+
+
+# NicGetSetting 命令
+CMD_NicGetSetting 获å–虚拟 LAN å¡çš„设置
+CMD_NicGetSetting_Help 获å–现有的虚拟 LAN å¡çš„ MAC 地å€è®¾ç½®ã€‚\n当 VPN 客户è¿è¡Œ Windows 2000 以上的æ“纵系统时,此指令å¯ä»¥è¢«ä½¿ç”¨ã€‚
+CMD_NicGetSetting_Args NicGetSetting [name]
+CMD_NicGetSetting_[name] 指定虚拟 LAN å¡å
+CMD_NicGetSetting_1 设备å称
+CMD_NicGetSetting_2 状æ€
+CMD_NicGetSetting_3 MAC 地å€
+CMD_NicGetSetting_4 版本
+CMD_NicGetSetting_5 驱动程åºæ–‡ä»¶å
+CMD_NicGetSetting_6 GUID
+
+
+# NicSetSetting 命令
+CMD_NicSetSetting 更改虚拟 LAN å¡è®¾ç½®
+CMD_NicSetSetting_Help 更改现有的虚拟 LAN å¡çš„ MAC 地å€è®¾ç½®ã€‚一旦å¯åŠ¨è¯¥æŒ‡ä»¤ï¼Œç›®å‰è¿è¡Œä¸­çš„虚拟 LAN å¡è®¾å¤‡é©±åŠ¨å°†è¢«é‡æ–°å¯åŠ¨ã€‚\n当 VPN 客户è¿è¡Œ Windows 2000 以上的æ“纵系统时,此指令å¯ä»¥è¢«ä½¿ç”¨ã€‚
+CMD_NicSetSetting_Args NicSetSetting [name] [/MAC:mac]
+CMD_NicSetSetting_[name] 指定虚拟 LAN å¡å
+CMD_NicSetSetting_MAC 指定è¦è®¾ç½®çš„ MAC 地å€ã€‚\nMAC 地å€è¯·ç”¨ 6 字节å六进制字符串指定。\n例如: 00:AC:01:23:45:67 或 00-AC-01-23-45-67
+CMD_NicSetSetting_PROMPT_MAC é…ç½® MAC 地å€:
+
+
+# NicEnable 命令
+CMD_NicEnable å¯ç”¨è™šæ‹Ÿ LAN å¡
+CMD_NicEnable_Help å¯åŠ¨çŽ°æœ‰çš„被ç¦ç”¨çš„虚拟 LAN å¡ã€‚\n当 VPN 客户è¿è¡Œ Windows 2000 以上的æ“纵系统时,此指令å¯ä»¥è¢«ä½¿ç”¨ã€‚
+CMD_NicEnable_Args NicEnable [name]
+CMD_NicEnable_[name] 指定虚拟 LAN å¡çš„å称。
+
+
+# NicDisable 命令
+CMD_NicDisable ç¦ç”¨è™šæ‹Ÿ LAN å¡
+CMD_NicDisable_Help ç¦ç”¨çŽ°æœ‰çš„正使用的虚拟 LAN å¡ã€‚\n当 VPN 客户è¿è¡Œ Windows 2000 以上的æ“纵系统时,此指令å¯ä»¥è¢«ä½¿ç”¨ã€‚
+CMD_NicDisable_Args NicDisable [name]
+CMD_NicDisable_[name] 指定虚拟 LAN å¡çš„å称。
+
+
+# NicList 命令
+CMD_NicList 获å–虚拟 LAN å¡åˆ—表
+CMD_NicList_Help 获å–在当å‰ç³»ç»Ÿæ³¨å†Œçš„虚拟 LAN å¡åˆ—表
+CMD_NicList_Args NicList
+
+
+# AccountList 命令
+CMD_AccountList 获å–连接设置列表
+CMD_AccountList_Help 获å–登录到 VPN Client 的连接设置列表
+CMD_AccountList_Args AccountList
+
+
+# AccountCreate 命令
+CMD_AccountCreate 创建新的连接设置
+CMD_AccountCreate_Help 在 VPN Client 创建新的连接设置。\nè¦åˆ›å»ºè¿žæŽ¥è®¾ç½®ï¼Œä½œä¸ºåˆå§‹å‚数需è¦æŒ‡å®šåŠ åœ¨è¿žæŽ¥è®¾ç½®å称和连接终端的æœåŠ¡å™¨ï¼ŒåŠè¿žæŽ¥ç»ˆç«¯çš„虚拟 HUB,用户å上使用的虚拟 LAN å¡å。创建了新的连接设置时,用户认è¯çš„类型被åˆå§‹è®¾ç½®ä¸º [匿å认è¯],代ç†æœåŠ¡å™¨çš„设置和æœåŠ¡å™¨è¯ä¹¦çš„检查选项ä¸è¢«è®¾ç½®ã€‚è‹¥è¦æ›´æ”¹è¿™äº›è®¾ç½®å’Œå…¶ä»–的详细设置,创建连接设置åŽï¼Œä½¿ç”¨ä»¥ "Account" å字开始的其他指令。
+CMD_AccountCreate_Args AccountCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username] [/NICNAME:nicname]
+CMD_AccountCreate_[name] 指定è¦åˆ›å»ºçš„连接设置å
+CMD_AccountCreate_SERVER 以 [主机å:端å£å·] çš„å½¢å¼æŒ‡å®šç»ˆç«¯ VPN Server 的主机å,端å£å·ã€‚å¯ä»¥é€šè¿‡ IP 地å€è¿›è¡ŒæŒ‡å®šã€‚
+CMD_AccountCreate_HUB 在终端 VPN Server 上指定虚拟 HUB。
+CMD_AccountCreate_USERNAME 指定在连接到终端 VPN Server 时用于用户认è¯çš„用户å。
+CMD_AccountCreate_NICNAME 指定用于连接的虚拟 LAN å¡å。
+CMD_AccountCreate_Prompt_Name 连接设置å:
+CMD_AccountCreate_Prompt_Server 终端 VPN Server 主机å和端å£å·:
+CMD_AccountCreate_Prompt_Hub 终端虚拟 HUB å称:
+CMD_AccountCreate_Prompt_Username 连接用户å:
+CMD_AccountCreate_Prompt_Nicname 使用虚拟 LAN å¡å称:
+
+
+# AccountSet 命令
+CMD_AccountSet 设定连接设置连接终端
+CMD_AccountSet_Help 设置注册在 VPN 客户的连接设置的终端 VPN Server 主机å和端å£å·ï¼Œè™šæ‹Ÿ HUB å,åŠç”¨äºŽè¿žæŽ¥çš„用户å,加在其上使用的虚拟 LAN å¡å。
+CMD_AccountSet_Args AccountSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_AccountSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountSet_SERVER 以 [主机å:端å£å·] çš„å½¢å¼æŒ‡å®šç»ˆç«¯ VPN Server 的主机å,端å£å·ã€‚å¯ä»¥é€šè¿‡ IP 地å€è¿›è¡ŒæŒ‡å®šã€‚
+CMD_AccountSet_HUB 指定终端的 VPN Server 上的虚拟 HUB。
+
+
+# AccountGet 命令
+CMD_AccountGet å–得连接设置的设置
+CMD_AccountGet_Help 获å–注册到 VPN Client 的连接设置的连接设置内容。\n而且,è¦æ”¹å˜è¿žæŽ¥è®¾ç½®çš„连接设置内容,在创建连接设置åŽä½¿ç”¨å…¶ä»–的以 "Account" å开始的的指令。
+CMD_AccountGet_Args AccountGet [name]
+CMD_AccountGet_[name] 指定è¦èŽ·å–的连接设置å。
+
+
+# AccountDelete 命令
+CMD_AccountDelete 删除连接设置
+CMD_AccountDelete_Help 删除注册到 VPN Client 的连接设置。如果指定的连接设置处于在线状æ€ï¼Œå°†ä¼šè‡ªåŠ¨æ–­å¼€è¿žæŽ¥å¹¶åˆ é™¤ã€‚
+CMD_AccountDelete_Args AccountDelete [name]
+CMD_AccountDelete_[name] 指定è¦åˆ é™¤çš„连接设置å。
+
+
+# AccountUsernameSet 命令
+CMD_AccountUsernameSet 设置用于连接的连接设置的用户å
+CMD_AccountUsernameSet_Help 指定注册到 VPN Client 的连接设置,且其连接设置连接到 VPN Server 上时,指定需è¦è¿›è¡Œç”¨æˆ·è®¤è¯çš„用户å。\n而且,在一些情况下有必è¦æŒ‡å®šç”¨æˆ·è®¤è¯çš„ç§ç±»å’Œéœ€è¦çš„å‚数。è¦æ›´æ”¹è¿™äº›ä¿¡æ¯ï¼Œå¯ä»¥ä½¿ç”¨å¦‚下指令: AccountAnonymousSet, AccountPasswordSet, AccountCertSet å’Œ AccountSecureCertSet。
+CMD_AccountUsernameSet_Args AccountUsernameSet [name] [/USERNAME:username]
+CMD_AccountUsernameSet_[name] 指定更改设置的连接设置å。
+CMD_AccountUsernameSet_USERNAME 指定连接设置连接到 VPN Server 上时需è¦è¿›è¡Œç”¨æˆ·è®¤è¯çš„用户å。
+CMD_AccountUsername_Notice è¿™ç§è¿žæŽ¥è®¾ç½®çš„认è¯æ–¹æ³•ï¼Œç›®å‰è¢«è®¾ç½®ä¸ºå¯†ç è®¤è¯ã€‚更改用户ååŽï¼Œå¿…须使用 AccountPasswordSet 指令é‡æ–°è®¾å®šã€‚
+
+
+# AccountAnonymousSet 命令
+CMD_AccountAnonymousSet 设定连接设置的用户认è¯ç§ç±»ä¸ºåŒ¿å认è¯
+CMD_AccountAnonymousSet_Help 指定注册到 VPN Client 的连接设置,把其连接设置连接到 VPN Server 上时的用户认è¯æ–¹æ³•ï¼Œè®¾ç½®ä¸º [匿å认è¯]。
+CMD_AccountAnonymousSet_Args AccountAnonymousSet [name]
+CMD_AccountAnonymousSet_[name] 指定更改设置的连接设置å。
+
+
+# AccountPasswordSet 命令
+CMD_AccountPasswordSet 设定连接设置的用户è¯ç±»åž‹ä¸ºå¯†ç è®¤è¯
+CMD_AccountPasswordSet_Help 指定注册到 VPN Client 的连接设置,把其连接设置连接到 VPN Server 上时的用户认è¯æ–¹æ³•ï¼Œè®¾ç½®ä¸º [密ç è®¤è¯]。指定 [标准密ç è®¤è¯] å’Œ [RADIUS 或 NT 域认è¯] 作为密ç è®¤è¯ç§ç±»ã€‚
+CMD_AccountPasswordSet_Args AccountPasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_AccountPasswordSet_[name] 指定更改设置的连接设置å。
+CMD_AccountPasswordSet_PASSWORD 指定密ç è®¤è¯ä½¿ç”¨çš„密ç ã€‚如果ä¸æŒ‡å®šï¼Œå°†æ˜¾ç¤ºè¾“入密ç çš„æ示。
+CMD_AccountPasswordSet_TYPE 作为密ç è®¤è¯ç±»åž‹ï¼ŒæŒ‡å®š "standard" (标准密ç è®¤è¯) 或 "radius" (RADIUS 或 NT 域认è¯) 的二者之一。
+CMD_AccountPasswordSet_Prompt_Type 指定 standard 或 radius:
+CMD_AccountPasswordSet_Type_Invalid standard 或 radius 的指定是ä¸æ­£ç¡®çš„。
+
+
+# AccountCertSet 命令
+CMD_AccountCertSet 设置连接设置的用户认è¯ç±»åž‹ä¸ºç”¨æˆ·è¯ä¹¦è®¤è¯
+CMD_AccountCertSet_Help 指定注册到 VPN Client 的连接设置,把其连接设置连接到 VPN Server 上时的用户认è¯æ–¹æ³•ï¼Œè®¾ç½®ä¸º [用户è¯ä¹¦è®¤è¯]。作为该è¯ä¹¦ï¼Œå¿…须指定è¯ä¹¦æ–‡ä»¶ä¸º X.509 æ ¼å¼ä¸”ç§é’¥æ–‡ä»¶æ˜¯ Base 64 ç¼–ç ã€‚
+CMD_AccountCertSet_Args AccountCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_AccountCertSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å
+CMD_AccountCertSet_LOADCERT 指定以è¯ä¹¦è®¤è¯æ交的 X.509 æ ¼å¼è¯ä¹¦çš„文件å。
+CMD_AccountCertSet_LOADKEY 指定以对应è¯ä¹¦çš„ Base 64 æ ¼å¼çš„ç¼–ç ç§é’¥æ–‡ä»¶å。
+
+
+# AccountCertGet 命令
+CMD_AccountCertGet 获å–用于连接设置的客户端è¯ä¹¦
+CMD_AccountCertGet_Help 当指定注册到 VPN Client 的连接设置,其连接设置使用使用客户è¯ä¹¦è®¤è¯æ—¶ï¼ŒèŽ·å–作为客户è¯ä¹¦æ出的è¯ä¹¦ï¼Œå¹¶ä¿å­˜è¯¥è¯ä¹¦æ–‡ä»¶ä¸º X.509 æ ¼å¼ã€‚
+CMD_AccountCertGet_Args AccountCertGet [name] [/SAVECERT:cert]
+CMD_AccountCertGet_[name] 指定è¦èŽ·å–设置的连接设置å。
+CMD_AccountCertGet_SAVECERT 指定以 X.509 æ ¼å¼ä¿å­˜èŽ·å–çš„è¯ä¹¦çš„文件å。
+
+
+# AccountEncryptEnable 命令
+CMD_AccountEncryptEnable å¯ç”¨è¿žæŽ¥è®¾ç½®è¿›è¡Œé€šä¿¡çš„加密
+CMD_AccountEncryptEnable_Help 当指定注册到 VPN Client 的连接设置,且其连接设置与 VPN Server 间进行 VPN 连接通信时,将与 VPN Server 间的通信内容以 SSL 设置为加密。\n通常,将与 VPN Server 间的通信以 SSL 加密,是防止信æ¯çš„窃å¬å’Œç¯¡æ”¹ã€‚也å¯ä»¥ç¦ç”¨åŠ å¯†ã€‚当ç¦ç”¨åŠ å¯†æ—¶ï¼Œé€šä¿¡é‡å°†æ‰©å¤§ä½†æ˜¯é€šä¿¡æ•°æ®å°†ä»¥çº¯æ–‡æœ¬æ ¼å¼åœ¨ç½‘络上传输。
+CMD_AccountEncryptEnable_Args AccountEncryptEnable [name]
+CMD_AccountEncryptEnable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountEncryptDisable 命令
+CMD_AccountEncryptDisable ç¦ç”¨è¿žæŽ¥è®¾ç½®è¿›è¡Œé€šä¿¡æ—¶çš„加密
+CMD_AccountEncryptDisable_Help 当指定注册到 VPN Client 的连接设置,且其连接设置与 VPN Server 间进行 VPN 连接通信时,将与 VPN Server 间的通信内容以 SSL 设置为ä¸åŠ å¯†ã€‚\n通常,将与 VPN Server 间的通信以 SSL 加密,是防止信æ¯çš„窃å¬å’Œç¯¡æ”¹ã€‚也å¯ä»¥ç¦ç”¨åŠ å¯†ã€‚当ç¦ç”¨åŠ å¯†æ—¶ï¼Œé€šä¿¡é‡å°†æ‰©å¤§ä½†æ˜¯é€šä¿¡æ•°æ®å°†ä»¥çº¯æ–‡æœ¬æ ¼å¼åœ¨ç½‘络上传输。
+CMD_AccountEncryptDisable_Args AccountEncryptDisable [name]
+CMD_AccountEncryptDisable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountCompressEnable 命令
+CMD_AccountCompressEnable å¯ç”¨è¿žæŽ¥è®¾ç½®è¿›è¡Œé€šä¿¡æ—¶çš„æ•°æ®åŽ‹ç¼©
+CMD_AccountCompressEnable_Help 当指定注册到 VPN Client 的连接设置,且其连接设置与 VPN Server 间进行 VPN 连接通信时,将与 VPN Server 间的通信内容设置为压缩。\n最大å¯ä»¥è¿›è¡Œçº¦ 80% 的压缩。但是,压缩会使客户端åŠæœåŠ¡å™¨åŒæ–¹çš„ CPU 产生较高的负è·ã€‚当线路速度为约 10 Mbps 以上时,压缩å¯èƒ½ä¼šé™ä½Žåžåé‡ï¼Œäº§ç”Ÿåé¢æ•ˆæžœã€‚
+CMD_AccountCompressEnable_Args AccountCompressEnable [name]
+CMD_AccountCompressEnable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountCompressDisable 命令
+CMD_AccountCompressDisable ç¦ç”¨è¿žæŽ¥è®¾ç½®è¿›è¡Œé€šä¿¡æ—¶çš„æ•°æ®åŽ‹ç¼©
+CMD_AccountCompressDisable_Help 当指定注册到 VPN Client 的连接设置,且其连接设置与 VPN Server 间进行 VPN 连接通信时,将与 VPN Server 间的通信内容设置为ä¸åŽ‹ç¼©ã€‚
+CMD_AccountCompressDisable_Args AccountCompressDisable [name]
+CMD_AccountCompressDisable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountProxyNone 命令
+CMD_AccountProxyNone 将连接设置的连接方法直接设置为 TCP/IP 连接
+CMD_AccountProxyNone_Help 当指定注册到 VPN Client 的连接设置,将其连接设置与 VPN Server 间进行 VPN 连接时使用的连接方法设置为 [直接 TCP/IP连接],ä¸é€šè¿‡ä»£ç†æœåŠ¡å™¨ã€‚
+CMD_AccountProxyNone_Args AccountProxyNone [name]
+CMD_AccountProxyNone_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountProxyHttp 命令
+CMD_AccountProxyHttp 将连接设置的连接方法设置为通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥
+CMD_AccountProxyHttp_Help 当指定注册到 VPN Client 的连接设置,将其连接设置与 VPN Server 间进行 VPN 连接时使用的连接方法设置为 [通过 HTTP 代ç†æœåŠ¡å™¨è¿žæŽ¥],指定将通过的 HTTP 代ç†æœåŠ¡å™¨çš„主机å和端å£å·ï¼Œç”¨æˆ·åå’Œå¯†ç  (如果需è¦)。\n通过 HTTP 代ç†æœåŠ¡å™¨ï¼Œå¿…须对应因进行 HTTPS 通信的 CONNECT 方法。
+CMD_AccountProxyHttp_Args AccountProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxyHttp_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountProxyHttp_SERVER 以 [主机å:端å£å·] çš„å½¢å¼ï¼ŒæŒ‡å®šé€šè¿‡ HTTP 代ç†æœåŠ¡å™¨çš„主机å或 IP 地å€å’Œç«¯å£å·ã€‚
+CMD_AccountProxyHttp_USERNAME 如果因为连接通过 HTTP 代ç†æœåŠ¡å™¨è€Œéœ€è¦ç”¨æˆ·è®¤è¯æ—¶ï¼ŒæŒ‡å®šç”¨æˆ·å。与此åŒæ—¶ä¹ŸæŒ‡å®š /PASSWORD å‚数。/USERNAME å’Œ /PASSWORD å‚数没有被指定时,ä¸è®¾ç½®ç”¨æˆ·èº«ä»½éªŒè¯æ•°æ®ã€‚
+CMD_AccountProxyHttp_PASSWORD 如果因为连接通过 HTTP 代ç†æœåŠ¡å™¨è€Œéœ€è¦ç”¨æˆ·è®¤è¯æ—¶ï¼ŒæŒ‡å®šå¯†ç ã€‚与 /USERNAME å‚数一起指定。
+CMD_AccountProxyHttp_Prompt_Server 代ç†æœåŠ¡å™¨ä¸»æœºå和端å£å·:
+
+
+
+# AccountProxySocks 命令
+CMD_AccountProxySocks 将连接设置的连接方法设置为通过 SOCKS 代ç†æœåŠ¡å™¨è¿žæŽ¥
+CMD_AccountProxySocks_Help 当指定注册到 VPN Client 的连接设置,将其连接设置与 VPN Server 间进行 VPN 连接时使用的连接方法设置为 [通过 SOCKS æœåŠ¡å™¨è¿žæŽ¥],并指定è¦é€šè¿‡çš„ SOCKS 代ç†æœåŠ¡å™¨çš„主机å和端å£å·ï¼Œç”¨æˆ·åå’Œå¯†ç  (如果需è¦)。\n通过 SOCKS æœåŠ¡å™¨ï¼Œå¿…须对应 SOCKS 版本 4。
+CMD_AccountProxySocks_Args AccountProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxySocks_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountProxySocks_SERVER 以 [主机å:端å£å·] å½¢å¼ï¼ŒæŒ‡å®šè¦é€šè¿‡çš„ SOCKS 代ç†æœåŠ¡å™¨ä¸»æœºå或 IP 地å€å’Œç«¯å£å·ã€‚
+CMD_AccountProxySocks_USERNAME 如果因为连接通过 SOCKS 代ç†æœåŠ¡å™¨è€Œéœ€è¦ç”¨æˆ·è®¤è¯æ—¶ï¼ŒæŒ‡å®šç”¨æˆ·å。与此åŒæ—¶ä¹ŸæŒ‡å®š /PASSWORD å‚数。/USERNAME å’Œ /PASSWORD å‚数没有被指定时,ä¸è®¾ç½®ç”¨æˆ·èº«ä»½éªŒè¯æ•°æ®ã€‚
+CMD_AccountProxySocks_PASSWORD 如果因为连接通过 SOCKS 代ç†æœåŠ¡å™¨è€Œéœ€è¦ç”¨æˆ·è®¤è¯æ—¶ï¼ŒæŒ‡å®šå¯†ç ã€‚与 /USERNAME å‚数一起指定。
+
+
+# AccountServerCertEnable 命令
+CMD_AccountServerCertEnable å¯ç”¨è¿žæŽ¥è®¾ç½®æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹
+CMD_AccountServerCertEnable_Help 指定注册到 VPN Client 的连接设置,其连接设置连接到 VPN Server 时,å¯åŠ¨æ£€æŸ¥è¿žæŽ¥ç»ˆç«¯çš„ VPN Server æ交的 SSL è¯ä¹¦æ˜¯å¦å¯ä¿¡çš„选项。\n如果å¯ç”¨æ­¤é€‰é¡¹ï¼Œå¯ä»¥é¢„先将连接目标æœåŠ¡å™¨çš„ SSL è¯ä¹¦ä»¥ AccountServerCertSet 指令ä¿å­˜åœ¨è¿žæŽ¥è®¾ç½®çš„设置内,或建议将æœåŠ¡å™¨çš„ SSL è¯ä¹¦ç­¾å了的根è¯ä¹¦ï¼Œä»¥ CertAdd 指令注册到虚拟 HUB 信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表中。如果没有注册,åˆæ¬¡è¿žæŽ¥æ—¶å¯èƒ½ä¼šæ˜¾ç¤ºç¡®è®¤ä¿¡æ¯ã€‚\n验è¯è¿žæŽ¥è®¾ç½®çš„æœåŠ¡å™¨è¯ä¹¦çš„选项处于å¯åŠ¨çŠ¶æ€ï¼Œè¿žæŽ¥äº†çš„ VPN Server çš„è¯ä¹¦ä¸å¯ä¿¡æ—¶ï¼Œç«‹å³è§£é™¤è¿žæŽ¥ï¼Œåå¤é‡è¯•ã€‚
+CMD_AccountServerCertEnable_Args AccountServerCertEnable [name]
+CMD_AccountServerCertEnable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountServerCertDisable 命令
+CMD_AccountServerCertDisable ç¦ç”¨è¿žæŽ¥è®¾ç½®æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹
+CMD_AccountServerCertDisable_Help 指定注册到 VPN Client 的连接设置,其连接设置与 VPN Server 连接时,ç¦æ­¢æ£€éªŒç”±ç›®æ ‡ VPN Server æ供的 SSL è¯æ˜Žä¹¦æ˜¯å¦å¯ä¿¡çš„选项。
+CMD_AccountServerCertDisable_Args AccountServerCertDisable [name]
+CMD_AccountServerCertDisable_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountServerCertSet 命令
+CMD_AccountServerCertSet 设置连接设置的æœåŠ¡å™¨å›ºæœ‰è¯æ˜Žä¹¦
+CMD_AccountServerCertSet_Help 指定注册到 VPN Client 的连接设置,其连接设置连接到 VPN Server 时,预先注册与连接目标的 VPN Server æ交的 SSL è¯ä¹¦ç›¸åŒçš„è¯ä¹¦ã€‚\n如果å¯åŠ¨äº†è¿žæŽ¥è®¾ç½®çš„æœåŠ¡å™¨è¯ä¹¦éªŒè¯é€‰é¡¹ï¼Œå¯ä»¥é¢„先将连接目标æœåŠ¡å™¨çš„ SSL è¯ä¹¦ä»¥æ­¤æŒ‡ä»¤ä¿å­˜åœ¨è¿žæŽ¥è®¾ç½®çš„设置内,或需è¦å°†æœåŠ¡å™¨çš„ SSL è¯ä¹¦ç­¾å了的根è¯ä¹¦ï¼Œä»¥ CAAdd 指令注册到虚拟 HUB 信任的è¯æ˜Žæœºæž„çš„è¯ä¹¦åˆ—表中。\n验è¯è¿žæŽ¥è®¾ç½®çš„æœåŠ¡å™¨è¯ä¹¦çš„选项处于å¯åŠ¨çŠ¶æ€ï¼Œè¿žæŽ¥äº†çš„ VPN Server çš„è¯ä¹¦ä¸å¯ä¿¡æ—¶ï¼Œç«‹å³è§£é™¤è¿žæŽ¥ï¼Œåå¤é‡è¯•ã€‚
+CMD_AccountServerCertSet_Args AccountServerCertSet [name] [/LOADCERT:cert]
+CMD_AccountServerCertSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountServerCertSet_LOADCERT 指定以 X.509 è¯ä¹¦æ ¼å¼ä¿å­˜çš„设置æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦çš„è¯ä¹¦æ–‡ä»¶å。
+
+
+# AccountServerCertDelete 命令
+CMD_AccountServerCertDelete 删除连接设置的æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦
+CMD_AccountServerCertDelete_Help 指定注册到到 VPN Client 的连接设置,且其连接设置注册了æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦æ—¶ï¼Œåˆ é™¤è¯ä¹¦ã€‚
+CMD_AccountServerCertDelete_Args AccountServerCertDelete [name]
+CMD_AccountServerCertDelete_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountServerCertGet 命令
+CMD_AccountServerCertGet 获å–连接设置的æœåŠ¡å™¨å›ºæœ‰è¯æ˜Žä¹¦
+CMD_AccountServerCertGet_Help 指定注册到到 VPN Client 的连接设置,且其连接设置注册了æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦æ—¶ï¼ŒèŽ·å–该è¯ä¹¦å¹¶ä»¥ X.509 æ ¼å¼ä¿å­˜è¯æ˜Žä¹¦æ–‡ä»¶ã€‚
+CMD_AccountServerCertGet_Args AccountServerCertGet [name] [/SAVECERT:path]
+CMD_AccountServerCertGet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountServerCertGet_SAVECERT 指定以 X.509 è¯ä¹¦æ ¼å¼ä¿å­˜çš„æœåŠ¡å™¨å›ºæœ‰è¯ä¹¦çš„è¯ä¹¦æ–‡ä»¶å。
+
+
+# AccountDetailSet 命令
+CMD_AccountDetailSet 设置接续设置的高级通信设置
+CMD_AccountDetailSet_Help 指定注册到 VPN Client 的连接设置,并定制其连接设置与 VPN Server 通信时使用的 VPN å议的通信设置。
+CMD_AccountDetailSet_Args AccountDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:additional_interval] [/TTL:disconnect_span] [/HALF:yes|no] [/BRIDGE:yes|no] [/MONITOR:yes|no] [/NOTRACK:yes|no] [/NOQOS:yes|no]
+CMD_AccountDetailSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountDetailSet_MAXTCP VPN 通信使用的 TCP 连接数,指定从 1 到 32 的整数。在与 VPN Server 之间的 VPN 通信会è¯ä¸Šçš„æ•°æ®ä¼ é€ï¼Œé€šè¿‡ä½¿ç”¨å¤šä¸ª TCP 连接,å¯ä»¥æ高通信速度。\n注æ„: 如果连接æœåŠ¡å™¨çš„线路是高速线路时,建议 8 个左å³ï¼Œå¦‚果是拨å·ç­‰ä½Žé€Ÿçº¿è·¯æ—¶ï¼Œå»ºè®® 1 个。
+CMD_AccountDetailSet_INTERVAL 建立多个 TCP 连接进行 VPN 通信时,以秒为å•ä½æŒ‡å®šæ¯ä¸ª TCP 连接的建立间隔。规定值为 1 秒。
+CMD_AccountDetailSet_TTL 如果设置的æ¯ä¸ª TCP 连接的寿命时,从 TCP 连接的建立到断开的寿命以秒数æ¥æŒ‡å®šã€‚如果指定 "0",则寿命未被设置。
+CMD_AccountDetailSet_HALF è¦å¯åŠ¨åŠåŒå·¥æ¨¡å¼ï¼ŒæŒ‡å®š "yes"。将两个以上的 TCP 连接æ†ç»‘,进行 VPN 通信时,å¯ä»¥ä½¿ç”¨ "åŠåŒå·¥æ¨¡å¼"。å¯åŠ¨åŠåŒå·¥æ¨¡å¼ï¼Œèƒ½å¤Ÿè‡ªåŠ¨å°†å„ TCP 连接的数æ®ä¼ è¾“æ–¹å‘固定å„一åŠã€‚例如,使用 8 个 TCP 连接建立了 VPN 会è¯æ—¶ï¼Œå¯åŠ¨åŠåŒå·¥æ¨¡å¼ï¼Œåˆ™å›ºå®š 4 个 TCP 连接为上传方å‘专用,剩下 4 个 TCP 连接为下载方å‘专用,进行通信。
+CMD_AccountDetailSet_BRIDGE 与 VPN Server 以 "æ¡¥ / 路由器模å¼" 连接时,指定 "yes"。使用桥/路由器模å¼è¿žæŽ¥æ—¶ï¼ŒVPN Client 的虚拟 LAN å¡æ–¹å°†èƒ½å¤Ÿä¸Žå…¶ä»–网络进行桥或路由。然而,如果用于连接的用户的安全策略ç¦ç”¨æ¡¥æˆ–路由时,则连接失败。
+CMD_AccountDetailSet_MONITOR 与 VPN Server 以 "监控模å¼" 连接时,指定 "yes"。如果使用监测模å¼è¿žæŽ¥æ—¶ï¼Œå¯ä»¥æŽ¥æ”¶è™šæ‹Ÿ HUB 内传é€çš„所有的数æ®åŒ…。然而,用于连接的用户安全策略ä¸å…许监视模å¼æ—¶ï¼Œåˆ™è¿žæŽ¥å¤±è´¥ã€‚
+CMD_AccountDetailSet_NOTRACK 指定 "yes",ç¦ç”¨è·¯ç”±å™¨è¡¨é¡¹è°ƒèŠ‚器。通常情况下,指定 "no"。
+CMD_AccountDetailSet_NOQOS ç¦ç”¨ VoIP / QoS 功能时指定 "yes"。通常指定 "no"。
+CMD_AccountDetailSet_Eval_MaxTcp TCP 连接数请在 1 - 32 å·ä¹‹é—´æŒ‡å®šã€‚
+CMD_AccountDetailSet_Eval_Interval TCP 连接的建立间隔请指定 1 秒以上。
+CMD_AccountDetailSet_Prompt_MaxTcp 用于 VPN 通信的 TCP 连接数:
+CMD_AccountDetailSet_Prompt_Interval å„ TCP 连接的建立间隔:
+CMD_AccountDetailSet_Prompt_TTL å„ TCP 连接的寿命 (ä¸å¸¦: 0):
+CMD_AccountDetailSet_Prompt_HALF å¯ç”¨åŠåŒå·¥æ¨¡å¼ (yes/no):
+CMD_AccountDetailSet_Prompt_BRIDGE å¯ç”¨æ¡¥/è·¯ç”±å™¨æ¨¡å¼ (yes/no):
+CMD_AccountDetailSet_Prompt_MONITOR å¯ç”¨ç›‘æŽ§æ¨¡å¼ (yes/no):
+CMD_AccountDetailSet_Prompt_NOTRACK ç¦ç”¨è·¯ç”±è¡¨é¡¹è°ƒèŠ‚器 (yes/no):
+CMD_AccountDetailSet_Prompt_NOQOS ç¦ç”¨ QoS 控制功能 (yes/no):
+
+
+# AccountRename 命令
+CMD_AccountRename 更改连接设置å称
+CMD_AccountRename_Help 指定在 VPN Client 注册的连接设置,更改其连接设置å称。
+CMD_AccountRename_Args AccountRename [name] [/NEW:new_name]
+CMD_AccountRename_[name] 指定è¦æ›´æ”¹å称的连接设置的当å‰å称。
+CMD_AccountRename_NEW 指定å˜æ›´åŽçš„æ–°å称。
+CMD_AccountRename_PROMPT_OLD ç›®å‰çš„å称:
+CMD_AccountRename_PROMPT_NEW æ–°å称:
+
+
+# AccountConnect 命令
+CMD_AccountConnect 使用连接设置,开始连接 VPN Server
+CMD_AccountConnect_Help 指定注册到 VPN Client 的连接设置,并å¯åŠ¨è¿žæŽ¥è®¾ç½®è¿žæŽ¥åˆ° VPN Server 上。处于正在连接中或已连接状æ€çš„连接设置,将一直连接 VPN Server,或ä¸æ–­å°è¯•è¿žæŽ¥ VPN Server,直到使用 AccountDisconnect 指令断开连接。(但是,如果使用 AccountRetrySet 指令指定了é‡è¯•æ¬¡æ•°æ—¶ï¼Œè¿žæŽ¥å°è¯•å°†åœ¨è¾¾åˆ°è¢«æŒ‡å®šæ¬¡æ•°æ—¶ä¸­æ–­ã€‚)
+CMD_AccountConnect_Args AccountConnect [name]
+CMD_AccountConnect_[name] 指定è¦å¯åŠ¨çš„连接设置å。
+
+
+# AccountDisconnect 命令
+CMD_AccountDisconnect 断开连接中的连接设置
+CMD_AccountDisconnect_Help 指定注册到 VPN Client 的连接设置,其连接设置处于连接处ç†ä¸­æˆ–已连接的状æ€æ—¶ï¼Œç«‹å³å°†å…¶æ–­å¼€ã€‚
+CMD_AccountDisconnect_Args AccountDisconnect [name]
+CMD_AccountDisconnect_[name] 指定è¦æ–­å¼€çš„连接设置å。
+
+
+# AccountStatusGet 命令
+CMD_AccountStatusGet 获å–当å‰è¿žæŽ¥è®¾ç½®çš„状æ€
+CMD_AccountStatusGet_Help 指定注册到 VPN Client 的连接设置,且该连接设置当å‰å·²è¿žæŽ¥æ—¶ï¼ŒèŽ·å–其连接状æ€å’Œå’Œå…¶ä»–ä¿¡æ¯ã€‚
+CMD_AccountStatusGet_Args AccountStatusGet [name]
+CMD_AccountStatusGet_[name] 指定è¦èŽ·å–ä¿¡æ¯çš„连接设置å。
+
+
+# AccountNicSet 命令
+CMD_AccountNicSet 设置连接设置时使用的虚拟 LAN å¡
+CMD_AccountNicSet_Help 更改注册到 VPN 客户上的现有的连接设置用于连接 VPN Server 的虚拟 LAN å¡å。
+CMD_AccountNicSet_Args AccountNicSet [name] [/NICNAME:nicname]
+CMD_AccountNicSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountNicSet_NICNAME 指定连接 VPN Server 时使用的虚拟 LAN å¡å。
+
+
+# AccountStatusShow 命令
+CMD_AccountStatusShow 设置æˆåœ¨è¿žæŽ¥åˆ° VPN Server 时显示连接状æ€å’Œé”™è¯¯çš„ç”»é¢
+CMD_AccountStatusShow_Help 指定注册到 VPN Client 的连接设置且用其连接设置连接到 VPN Server 时,设置在计算机上显示连接状æ€å’Œé”™è¯¯ç”»é¢ã€‚
+CMD_AccountStatusShow_Args AccountStatusShow [name]
+CMD_AccountStatusShow_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountStatusHide 命令
+CMD_AccountStatusHide 设置æˆåœ¨è¿žæŽ¥åˆ° VPN Server æ—¶ä¸æ˜¾ç¤ºè¿žæŽ¥çŠ¶æ€å’Œé”™è¯¯çš„ç”»é¢
+CMD_AccountStatusHide_Help 指定注册到 VPN Client 的连接设置且用其连接设置连接到 VPN Server 时,设置在计算机上ä¸æ˜¾ç¤ºè¿žæŽ¥çŠ¶æ€å’Œé”™è¯¯ç”»é¢ã€‚
+CMD_AccountStatusHide_Args AccountStatusHide [name]
+CMD_AccountStatusHide_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountSecureCertSet 命令
+CMD_AccountSecureCertSet 将连接设置的用户认è¯ç±»åž‹è®¾ç½®ä¸ºæ™ºèƒ½å¡è®¤è¯
+CMD_AccountSecureCertSet_Help 指定注册到 VPN Client 的连设置,将其连接设置连接到 VPN Server 时的用户认è¯æ–¹æ³•è®¾ç½®ä¸º [智能å¡è®¤è¯]。此外,必须指定存储在智能å¡ä¸Šçš„è¯ä¹¦å¯¹è±¡å和密钥对象å。
+CMD_AccountSecureCertSet_Args AccountSecureCertSet [name] [/CERTNAME:cert] [/KEYNAME:key]
+CMD_AccountSecureCertSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountSecureCertSet_CERTNAME 指定存储在智能å¡ä¸­çš„è¯ä¹¦å¯¹è±¡å。
+CMD_AccountSecureCertSet_KEYNAME 指定存储在智能å¡ä¸­çš„密钥对象å。
+CMD_AccountSecureCertSet_PROMPT_CERTNAME 智能å¡è¯ä¹¦å¯¹è±¡å:
+CMD_AccountSecureCertSet_PROMPT_KEYNAME 智能å¡ç§åŒ™å¯¹è±¡å:
+
+
+# AccountRetrySet 命令
+CMD_AccountRetrySet 设置连接设置的连接失败或断开时建立é‡æ–°è¿žæŽ¥çš„次数和间隔
+CMD_AccountRetrySet_Help 指定注册到 VPN Client 的连接设置,且其连接设置试图连接到 VPN Server 时,还有连接中的与 VPN Server 的通信被断开或连接失败时,指定连接的é‡è¯•æ¬¡æ•°å’Œè¿žæŽ¥é‡è¯•çš„间隔。\n而且,如果用户认è¯ç±»åž‹ä¸º [智能å¡è®¤è¯] 时,ä¸ç®¡è¿žæŽ¥é‡è¯•æ¬¡æ•°å¦‚何设置,都将ä¸è¿›è¡Œè¿žæŽ¥é‡è¯•ã€‚
+CMD_AccountRetrySet_Args AccountRetrySet [name] [/NUM:num_retry] [/INTERVAL:retry_interval]
+CMD_AccountRetrySet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+CMD_AccountRetrySet_NUM 指定连续进行é‡æ–°è¿žæŽ¥çš„次数。 如指定 "999",é‡è¯•æ¬¡æ•°ä¸ºæ— é™æ¬¡ (永久连接)。如指定 "0",ä¸è¿›è¡Œé‡æ–°è¿žæŽ¥ã€‚
+CMD_AccountRetrySet_INTERVAL é‡æ–°è¿›è¡Œè¿žæŽ¥æ—¶ï¼Œè®¾ç½®è·ç¦»ä¸Šæ¬¡æ–­å¼€æˆ–连接失败åŽéœ€å¤šå°‘秒开始é‡æ–°è¿žæŽ¥å¤„ç†ã€‚
+CMD_AccountRetrySet_PROMPT_NUM é‡æ–°è¿žæŽ¥æ¬¡æ•° ("999" 为无é™æ¬¡):
+CMD_AccountRetrySet_PROMPY_INTERVAL é‡æ–°è¿žæŽ¥é—´éš” (秒):
+CMD_AccountRetrySet_EVAL_INTERVAL 请指定 5 秒以上的é‡æ–°è¿žæŽ¥é—´éš”。
+
+
+# AccountStartupSet 命令
+CMD_AccountStartupSet 设定连接设置的å¯åŠ¨è¿žæŽ¥
+CMD_AccountStartupSet_Help 指定注册到 VPN Client 的连接设置,并将其设定为å¯åŠ¨è¿žæŽ¥ã€‚设置为å¯åŠ¨è¿žæŽ¥çš„连接设置,在 VPN Client æœåŠ¡è¿è¡Œçš„åŒæ—¶å°†è‡ªåŠ¨å¯åŠ¨è¿žæŽ¥ç¨‹åºã€‚
+CMD_AccountStartupSet_Args AccountStartupSet [name]
+CMD_AccountStartupSet_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountStartupRemove 命令
+CMD_AccountStartupRemove 解除连接设置的å¯åŠ¨è¿žæŽ¥
+CMD_AccountStartupRemove_Help 指定注册到 VPN Client 的连接设置,并把其连接设置设置为当å‰å¯åŠ¨è¿žæŽ¥æ—¶ï¼Œè§£é™¤å¯åŠ¨è¿žæŽ¥è®¾ç½®ã€‚
+CMD_AccountStartupRemove_Args AccountStartupRemove [name]
+CMD_AccountStartupRemove_[name] 指定è¦æ›´æ”¹è®¾ç½®çš„连接设置å。
+
+
+# AccountExport 命令
+CMD_AccountExport 导出连接设置
+CMD_AccountExport_Help 指定注册到 VPN Client 的连接设置,将其连接设置的内容作为文本文件导出。因为而åŽè¦å¯¼å…¥è¢«å¯¼å‡ºçš„连接设置,å¯ä»¥å¤åˆ¶è¿žæŽ¥è®¾ç½®çš„内容。而且,因为以文本文件ä¿å­˜ï¼Œå¯ä»¥ç”¨ä¸€èˆ¬çš„文本编辑器进行编辑。\n导出目标文件,以 UTF-8 æ ¼å¼çš„文本文件ä¿å­˜ã€‚还有,如果在文件å称上添加 .vpn 的扩展å,因为能与 Windows 版 VPN Client 连接员产生关è”,会很方便。
+CMD_AccountExport_Args AccountExport [name] [/SAVEPATH:savepath]
+CMD_AccountExport_[name] 指定导出连接设置的连接设置å。
+CMD_AccountExport_SAVEPATH 指定ä¿å­˜ç›®æ ‡æ–‡ä»¶å
+CMD_AccountExport_PROMPT_SAVEPATH ä¿å­˜ç›®æ ‡æ–‡ä»¶å (推è扩展 .vpn):
+
+
+# AccountImport 命令
+CMD_AccountImport 导入连接设置
+CMD_AccountImport_Help 导入由 AccountExport 指令导出的连接设置文件,添加到 VPN 客户。
+CMD_AccountImport_Args AccountImport [path]
+CMD_AccountImport_[path] 指定导入æºæ–‡ä»¶å。
+CMD_AccountImport_PROMPT_PATH 导入æºæ–‡ä»¶å:
+CMD_AccountImport_FAILED_PARSE ä¸èƒ½æ­£ç¡®è§£æžæŒ‡å®šçš„文件。请检查该文件是å¦å·²æ­£ç¡®å¯¼å‡ºã€‚
+CMD_AccountImport_OK 连接设置 "%s" 已导入。
+
+
+
+# RemoteEnable 命令
+CMD_RemoteEnable å…许 VPN 客户æœåŠ¡çš„远程管ç†
+CMD_RemoteEnable_Help 对 VPN Client æœåŠ¡ï¼Œä»Žæœ¬åœ°ä¸»æœºä»¥å¤–的远程计算机上,å…许通过命令行管ç†è®¾æ–½æˆ– VPN Client 管ç†å™¨å‘˜è¿›è¡Œè¿žæŽ¥å’Œç®¡ç†ã€‚
+CMD_RemoteEnable_Args RemoteEnable
+
+
+# RemoteDisable 命令
+CMD_RemoteDisable ç¦æ­¢ VPN 客户æœåŠ¡çš„远程管ç†
+CMD_RemoteDisable_Help 对 VPN Client æœåŠ¡ï¼Œä»Žæœ¬åœ°ä¸»æœºä»¥å¤–的远程计算机上,ç¦æ­¢é€šè¿‡å‘½ä»¤è¡Œç®¡ç†è®¾æ–½æˆ– VPN Client 管ç†å™¨å‘˜è¿›è¡Œè¿žæŽ¥å’Œç®¡ç†ã€‚
+CMD_RemoteDisable_Args RemoteDisable
+
+
+
+
+
+
+###################################################
+# #
+# 下é¢è¿™æ˜¯VPN工具用的指令 #
+# #
+###################################################
+
+
+# MakeCert 命令
+CMD_MakeCert 创建新的 X.509 è¯ä¹¦å’Œå¯†é’¥
+CMD_MakeCert_Help 创建新的 X.509 è¯ä¹¦å’Œå¯†é’¥ï¼Œå°†å…¶ä¿å­˜ä¸ºä¸€ä¸ªæ–‡ä»¶ã€‚\nè¯ä¹¦å…¬å…±å¯†é’¥å’Œç§˜å¯†å¯†é’¥çš„生æˆç®—法使用 RSA 1024 ä½ã€‚\n作为è¯ä¹¦ç±»åž‹ï¼Œå¯ä»¥åˆ›å»ºç”±æ ¹è¯ä¹¦ (自签åè¯ä¹¦) 和其他è¯ä¹¦ç­¾åçš„æŸä¸ªè¯ä¹¦ã€‚è¦åˆ›å»ºç”±å…¶ä»–è¯ä¹¦ç­¾åçš„è¯ä¹¦ï¼Œéœ€è¦ä¸Žç”¨äºŽç­¾åçš„è¯ä¹¦ (X.509æ ¼å¼æ–‡ä»¶) 相对应的密钥文件 (Base 64 ç¼–ç )。\n\n创建的è¯ä¹¦å¯ä»¥æŒ‡å®šå称 (CN),所属机构 (O),组织å•ä½ (OU),国家 (C),州 (ST),当地 (L),åºåˆ—å·ï¼Œæœ‰æ•ˆæœŸé™ã€‚\n创建的è¯ä¹¦ä»¥ X.509 æ ¼å¼çš„文件,密钥文件以 RSA 1024 ä½çš„ Base 64 ç¼–ç æ–‡ä»¶ï¼Œè¢«åˆ†åˆ«ä¿å­˜ã€‚\n\nMakeCert 指令是一个工具,它æ供创建è¯ä¹¦æ‰€éœ€çš„最低功能。如果想创建一个真正的è¯ä¹¦ï¼Œå»ºè®®ä½¿ç”¨ OpenSSL ç­‰å…费软件和出售的 CA (认è¯æœºæž„) 软件。\n\n※注æ„: 此指令å¯ä»¥ä»Ž SoftEther VPN 命令行管ç†å·¥å…·è°ƒç”¨ã€‚虽然目å‰ä»¥ç®¡ç†æ¨¡å¼è¿žæŽ¥åˆ° VPN Server å’Œ VPN Client æ—¶å¯ä»¥è¿è¡Œï¼Œä½†è¦å®žé™…è¿è¡Œ RSA 演算,生æˆè¯ä¹¦æ•°æ®çš„,是è¿è¡Œæ­¤æŒ‡ä»¤çš„计算机,和以管ç†æ¨¡å¼è¿žæŽ¥çš„链接目标计算机没有任何关系。
+CMD_MakeCert_Args MakeCert [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l] [/SERIAL:serial] [/EXPIRES:expires] [/SIGNCERT:signcert] [/SIGNKEY:signkey] [/SAVECERT:savecert] [/SAVEKEY:savekey]
+CMD_MakeCert_CN 指定创建è¯ä¹¦çš„å称 (CN) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_O 指定创建è¯ä¹¦çš„所属机构 (O) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_OU 指定创建è¯ä¹¦çš„组织å•ä½ (OU) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_C 指定创建è¯ä¹¦çš„国家 (C) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_ST 指定创建è¯ä¹¦çš„å·ž (ST) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_L 指定创建è¯ä¹¦çš„当地 (L) 项目。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_SERIAL 指定创建è¯ä¹¦çš„åºåˆ—å·é¡¹ç›®ã€‚以 16 进制指定。还å¯ä»¥æŒ‡å®š none。
+CMD_MakeCert_EXPIRES 指定创建è¯ä¹¦çš„有效期é™ã€‚如果指定 none 或 0,将被使用 3650 天 (约 10 å¹´)。最大å¯ä»¥æŒ‡å®š 10950 天 (约 30 å¹´)。
+CMD_MakeCert_SIGNCERT æ ¹æ®çŽ°æœ‰çš„è¯ä¹¦å¯¹è¦åˆ›å»ºçš„è¯ä¹¦ç­¾å时,指定用æ¥ç­¾åçš„ X.509 å½¢å¼çš„è¯ä¹¦æ–‡ä»¶å。如果çœç•¥å‚数,将作为根è¯ä¹¦è€Œåˆ›å»ºæ²¡æœ‰ç­¾åçš„æ–°è¯ä¹¦ã€‚
+CMD_MakeCert_SIGNKEY 指定与 /SIGNCERT 指定的è¯ä¹¦ç›¸åº”的密钥 (RSA,Base 64 çš„ç¼–ç )
+CMD_MakeCert_SAVECERT 指定文件å以ä¿å­˜åˆ›å»ºçš„è¯ä¹¦ã€‚该è¯ä¹¦ä»¥åŒ…å« RSA å½¢å¼çš„ 1024 ä½å…¬å¼€å¯†é’¥çš„ X.509 文件格å¼è¢«ä¿å­˜ã€‚
+CMD_MakeCert_SAVEKEY 指定文件åä¿å­˜å¯¹åº”创建的è¯ä¹¦çš„密钥。该密钥以 RSA å½¢å¼çš„ 1024 ä½å¯†é’¥æ–‡ä»¶è¢«ä¿å­˜ã€‚
+CMD_MakeCert_PROMPT_CN 创建è¯ä¹¦çš„å称 (CN):
+CMD_MakeCert_PROMPT_O 创建è¯ä¹¦çš„所属机构 (O):
+CMD_MakeCert_PROMPT_OU 创建è¯ä¹¦çš„组织å•ä½ (OU):
+CMD_MakeCert_PROMPT_C 创建è¯ä¹¦çš„国家 (C):
+CMD_MakeCert_PROMPT_ST 创建è¯ä¹¦çš„å·ž (ST):
+CMD_MakeCert_PROMPT_L 创建è¯ä¹¦çš„当地 (L):
+CMD_MakeCert_PROMPT_SERIAL 创建è¯ä¹¦çš„åºåˆ—å· (å六进制):
+CMD_MakeCert_PROMPT_EXPIRES 创建è¯ä¹¦çš„æœ‰æ•ˆæœŸé™ (æ—¥):
+CMD_MakeCert_PROMPT_SAVECERT ä¿å­˜å·²åˆ›å»ºè¯ä¹¦çš„文件å:
+CMD_MakeCert_PROMPT_SAVEKEY ä¿å­˜å·²åˆ›å»ºå¯†é’¥çš„文件å:
+CMD_MakeCert_EVAL_EXPIRES 请指定有效期é™ä¸º %u 以上 %u 以下。
+CMD_MakeCert_ERROR_SIGNKEY 无法读å–以 /SIGNCERT å’Œ /SIGNKEY 指定的è¯æ˜Žä¹¦å’Œå¯†é’¥æˆ–组åˆä¸æ­£ç¡®ã€‚
+CMD_MakeCert_ERROR_GEN_FAILED 无法生æˆè¯ä¹¦å’Œç§é’¥ã€‚
+
+
+# TrafficClient 命令
+CMD_TrafficClient 在用户模å¼ä¸‹ï¼Œè¿è¡Œç½‘络æµé‡é€Ÿåº¦æµ‹è¯•å·¥å…·
+CMD_TrafficClient_Help è¿è¡Œé€šä¿¡åžåé‡æµ‹é‡å·¥å…·çš„客户端程åºã€‚\n通信åžåé‡æµ‹é‡å·¥å…·ï¼Œä½œä¸º TrafficClient å’Œ TrafficServer 两个指令使用,å¯ä»¥æµ‹é‡åœ¨ IP 网络上连接的 2 å°è®¡ç®—机之间å¯ä¼ é€çš„通信åžåé‡ã€‚在å¦ä¸€å°è®¡ç®—机上使用 TrafficServer 指令使通信åžåé‡æµ‹é‡å·¥å…·æœåŠ¡å™¨å¤„于待机状æ€ï¼Œç”¨ TrafficClient 指令指定并连接其æœåŠ¡å™¨çš„主机å或 IP 地å€å’Œç«¯å£å·ï¼Œæµ‹é‡é€šä¿¡é€Ÿåº¦ã€‚\nåŒæ—¶å»ºç«‹å¤šä¸ªè¿žæŽ¥ï¼Œè®¡ç®—å„连接最大é™åº¦ä¼ é€æµæ•°æ®çš„结果,åŠåœ¨æŒ‡å®šæ—¶é—´å†…能够实际传é€çš„æ•°æ®çš„比特数,以此为ä¾æ®è®¡ç®—通信åžåé‡çš„å¹³å‡å€¼ (bps),用此方法进行通信速度的测é‡ã€‚通常,用一个 TCP 连接时,由于 TCP 算法的é™åˆ¶ï¼Œå¤§å¤šæ•°æ—¶å€™åªèƒ½ç”¨æ¯”实际的网络åžåé‡æ…¢çš„速度通信。因此,建议测é‡åŒæ—¶å»ºç«‹å¤šä¸ª TCP 连接进行通信的结果。用此方法测é‡çš„åžåé‡ï¼Œä»¥å®žé™…上作为 TCP æµåˆ°è¾¾æŽ¥æ”¶æ–¹çš„æ•°æ®çš„比特长度æ¥è®¡ç®—,因此途中产生的数æ®åŒ…丢失和数æ®åŒ…æŸåä¸åŒ…括在实际到达的数æ®åŒ…中,因而能够计算出纯粹的网络最大通信带宽的近似值。\n用作为测é‡ç»“构的,在 TCP 内被传输的 TCP æµçš„大å°ï¼Œæ¥è®¡ç®—在网络上实际传输的数æ®é‡çš„近似值,将其除以时间,计算出比特æ¯ç§’ (bps)。å‡å®šè®¡ç®—的物ç†ç½‘络类型为以太网 (IEEE802.3) ,MAC 帧有效载è·çš„大å°æ˜¯ 1,500 比特 (TCP çš„ MSS 是 1,460 比特)。如果指定 /RAW 选项,ä¸ä¼šå¯¹ TCP/IP 头和 MAC 头的数æ®é‡è¿›è¡Œæ›´æ­£è®¡ç®—。\n\n※注æ„: 此指令å¯ä»¥ä»Ž SoftEther VPN 命令行管ç†å·¥å…·è°ƒç”¨ã€‚虽然目å‰ä»¥ç®¡ç†æ¨¡å¼è¿žæŽ¥åˆ° VPN Server å’Œ VPN Client æ—¶å¯ä»¥è¿è¡Œï¼Œä½†è¦å®žé™…进行通信,测é‡åžåé‡çš„,是è¿è¡Œæ­¤æŒ‡ä»¤çš„计算机,与以管ç†æ¨¡å¼è¿žæŽ¥çš„连接目标计算机没有任何关系。
+CMD_TrafficClient_Args TrafficClient [host:port] [/NUMTCP:numtcp] [/TYPE:download|upload|full] [/SPAN:span] [/DOUBLE:yes|no] [/RAW:yes|no]
+CMD_TrafficClient_[host:port] 指定通信åžåé‡æµ‹é‡æœåŠ¡å™¨ (TrafficServer) 待机时的主机å,或 IP 地å€å’Œç«¯å£å·ã€‚如果çœç•¥ç«¯å£å·ï¼Œ9821 将被使用。
+CMD_TrafficClient_NUMTCP 指定åŒæ—¶åœ¨å®¢æˆ·ç«¯å’ŒæœåŠ¡å™¨è¿›è¡Œæ•°æ®ä¼ è¾“çš„ TCP 连接数é‡ã€‚如果çœç•¥ï¼Œ32 将被使用。
+CMD_TrafficClient_TYPE 指定进行åžåé‡æµ‹é‡æ—¶çš„æ•°æ®ä¼ è¾“æµæ–¹å‘。指定下列选项之一: "download","upload" 或 "full"。指定 "download",则数æ®ä»ŽæœåŠ¡å™¨ç«¯å‘客户端传é€ã€‚指定 "upload",则数æ®ä»Žå®¢æˆ·ç«¯å‘æœåŠ¡å™¨ç«¯ä¼ é€ã€‚指定 "full",数æ®å°†åŒå‘ä¼ é€ã€‚当指定 "full" 时,NUMTCP 的值必须指定是 2 以上的å¶æ•° (åŒæ—¶è¢«è¿žæŽ¥çš„ TCP 连接中一åŠç”¨äºŽä¸‹è½½çš„æ–¹å‘,而å¦ä¸€åŠç”¨äºŽä¸Šä¼ çš„æ–¹å‘)。如果çœç•¥æ­¤å‚数,将使用 "full"。
+CMD_TrafficClient_SPAN 以秒为å•ä½æŒ‡å®šä¸ºæµ‹é‡åžåé‡è€Œè¿›è¡Œæ•°æ®ä¼ è¾“时间。如果çœç•¥æ­¤å‚数,"15秒" 将被使用。
+CMD_TrafficClient_DOUBLE 指定 "yes" 时,测é‡ç»“果的åžåé‡å°†æ˜¾ç¤ºä¸º 2 å€ã€‚在中途有网络设备等,测é‡å…¶å…¶ç½‘络设备的输入输出åˆè®¡çš„åžåé‡èƒ½åŠ›æ—¶ï¼Œæ­¤é€‰é¡¹è¢«ä½¿ç”¨ã€‚
+CMD_TrafficClient_RAW 通过指定 "yes",ä¸è¿›è¡Œä¿®æ­£ TCP/IP 头和 MAC 头的数æ®é‡è®¡ç®—。
+CMD_TrafficClient_EVAL_NUMTCP TCP 连接的数é‡è¯·åœ¨ 32 以下指定。
+CMD_TrafficClient_PROMPT_HOST 测é‡æœåŠ¡å™¨å称和端å£å· (如果çœç•¥ 9821):
+CMD_TrafficClient_ERROR_NUMTCP 当数æ®çš„æµå‘是 "full" (两个方å‘),须指定 TCP è¿žæŽ¥æ•°é‡ (/NUMTCP) 为å¶æ•°å€¼ã€‚
+CMD_TrafficClient_ERROR_HOSTPORT 主机å或端å£å·çš„指定ä¸æ­£ç¡®ã€‚
+
+
+# TrafficServer 命令
+CMD_TrafficServer 在æœåŠ¡å™¨æ¨¡å¼ä¸‹ï¼Œè¿è¡Œç½‘络æµé‡é€Ÿåº¦æµ‹è¯•å·¥å…·
+CMD_TrafficServer_Help è¿è¡Œé€šä¿¡åžåé‡æµ‹é‡å·¥å…·çš„æœåŠ¡å™¨ç¨‹åºã€‚\n通信åžåé‡æµ‹é‡å·¥å…·ï¼Œä½œä¸º TrafficClient å’Œ TrafficServer 两个指令使用,å¯ä»¥æµ‹é‡åœ¨ IP 网络上连接的 2 å°è®¡ç®—机之间å¯ä¼ é€çš„通信åžåé‡ã€‚\nè¦ä½¿æ­¤è®¡ç®—机上的 TCP 端å£å¤„于待机状æ€ï¼Œç­‰å¾…从å¦ä¸€å°è®¡ç®—机的 TrafficClient 连接,å¯åŠ¨ TrafficServer 指令并指定端å£å·ã€‚\n关于通信åžåé‡æµ‹é‡å·¥å…·çš„详细情况,输入 TrafficClient /? 将显示。\n\n※注æ„: 此指令å¯ä»¥ä»Ž SoftEther VPN 命令行管ç†å·¥å…·è°ƒç”¨ã€‚虽然目å‰ä»¥ç®¡ç†æ¨¡å¼è¿žæŽ¥ VPN Server å’Œ VPN Client æ—¶å¯ä»¥è¿è¡Œï¼Œä½†è¦è¿›è¡Œå®žé™…通信并测é‡åžåé‡çš„,是è¿è¡Œæ­¤æŒ‡ä»¤çš„计算机,与用管ç†æ¨¡å¼è¿žæŽ¥ç»ˆç«¯çš„计算机没有任何关系。
+CMD_TrafficServer_Args TrafficServer [port]
+CMD_TrafficServer_[port] 以整数指定等待连接的端å£å·ã€‚被指定的端å£ï¼Œå¦‚果已ç»ç”±å¦ä¸€ä¸ªç¨‹åºåœ¨ä½¿ç”¨ï¼Œæˆ–ä¸èƒ½æ‰“开该端å£æ—¶ï¼Œå°†å‘生错误。
+
+
+# 关于 TrafficClient / TrafficServer 的内部信æ¯å­—符串
+TT_LISTEN_FAILED ä¸èƒ½ä½¿ TCP ç«¯å£ %u 处于待机状æ€ã€‚该端å£å¯èƒ½æ­£è¢«å…¶ä»–的程åºä½¿ç”¨æˆ–打开此端å£çš„æƒé™ã€‚
+TTS_LISTEN_STOP 关闭了待机端å£ã€‚
+TTS_ENTER_TO_EXIT \n----------------------------------------\n在æœåŠ¡å™¨æ¨¡å¼ä¸‹å¼€å¯çš„网络æµé‡é€Ÿåº¦æµ‹è¯•å·¥å…·ã€‚\n\n按下 Enter 键,åœæ­¢æœåŠ¡å™¨ç¨‹åºã€‚\n----------------------------------------\n\n
+TTS_INIT è¿è¡ŒæœåŠ¡å™¨ç¨‹åº...
+TTS_LISTEN_STARTED å¯åŠ¨äº†æœåŠ¡å™¨ç¨‹åºã€‚å°† IPv4 çš„ TCP ç«¯å£ %u 处于待机状æ€ï¼Œç­‰å¾…从客户端的连接。
+TTS_LISTEN_STARTED_V6 å°† IPv6 çš„ TCP ç«¯å£ %u 处于待机状æ€ï¼Œç­‰å¾…从客户端的连接。
+TTS_LISTEN_FAILED_V6 无法打开 IPv6 TCP ç«¯å£ %u。å¦ä¸€ä¸ªåº”用程åºå¯èƒ½æ­£åœ¨ä½¿ç”¨åŒä¸€ä¸ª IPv6 TCP 端å£ï¼Œæˆ–者没有安装 IPv6 å议栈在æ“作系统上。
+TTS_STOP_INIT åœæ­¢æœåŠ¡å™¨ç¨‹åº...
+TTS_STOP_FINISHED åœæ­¢æœåŠ¡å™¨ç¨‹åºå®Œæˆäº†ã€‚
+TTS_ACCEPTED 连接 %u: 从客户端 %S çš„ç«¯å£ %u 被连接了。
+TTS_DISCONNECTED 连接 %u 个 (%S) 被中断了。
+TTS_DISCONNECT 连接 %u (%S) 中断了。
+TTC_INIT 客户端程åºå¯åŠ¨...
+TTC_FREE 客户端程åºç»ˆæ­¢äº†ã€‚
+TTC_CONNECT_START æœåŠ¡å™¨ %S (ç«¯å£ %u) 的连接将å¯åŠ¨ã€‚%u 个 TCP 连接将实现连接。
+TTC_CONNECT_FAILED %u 个 TCP 连接接续失败。
+TTC_CONNECT_NOT_SERVER 除 TrafficServer 外其他程åºåœ¨ç»ˆç«¯ TCP 端å£è¿è¡Œï¼Œæµé‡ä¸èƒ½æµ‹é‡ã€‚
+TTC_CONNECT_OK %u 个 TCP 连接数已连接。
+TTC_CONNECT_OK_2 \ æ•°æ®ä¼ è¾“æ–¹å‘: %s
+TTC_ERROR_ABORTED 与æœåŠ¡å™¨çš„ TCP 连接åˆå§‹åŒ–失败。测é‡å°†åœæ­¢ã€‚
+TTC_SUMMARY_BAR -------------------------------------------------------
+TTC_SUMMARY_TITLE 网络传输速度测试工具客户端设置å‚数。
+TTC_SUMMARY_HOST 终端主机å
+TTC_SUMMARY_PORT 终端 TCP 端å£å·
+TTC_SUMMARY_NUMTCP 建立的 TCP 连接数
+TTC_SUMMARY_TYPE æ•°æ®ä¼ è¾“æ–¹å‘
+TTC_SUMMARY_SPAN æ•°æ®ä¼ è¾“时间
+TTC_SUMMARY_ETHER 以太网帧数æ®æ ¡æ­£
+TTC_SUMMARY_DOUBLE 中继器输入输出力åˆè®¡é€Ÿåº¦çš„测é‡
+TTC_TYPE_DOWNLOAD 下载 (æœåŠ¡å™¨ -> 客户端)
+TTC_TYPE_UPLOAD 上传 (客户端 -> æœåŠ¡å™¨)
+TTC_TYPE_FULL åŒå‘ (æœåŠ¡å™¨ <--> 客户端)
+TTC_SPAN_STR %.1f 秒
+TTC_COMM_START 所有连接已ç»å»ºç«‹ï¼Œæ•°æ®ä¼ è¾“开始。\n测é‡å¼€å§‹æ—¶é—´: %s\n预计完æˆæ—¶é—´: %s\n\n测é‡è¿›è¡Œä¸­ã€‚请ç¨åŽã€‚\n(测é‡è¿›è¡Œä¸­ï¼Œè¯·ä¸è¦ä½¿ç”¨å…¶ä»–应用程åºã€‚)\n\n
+TTC_COMM_END 因为过了 %.1f 秒以上,数æ®é€šä¿¡å°†ç»ˆæ­¢ã€‚\n\n
+TTC_COMM_USER_CANCEL 由于用户å–消,数æ®é€šä¿¡å°†ç»ˆæ­¢ã€‚\n\n
+TTC_COMM_DISCONNECTED TCP 连接 %u 已被断开。
+TTC_STOPPING åœæ­¢é€šä¿¡åžåé‡æµ‹é‡å·¥å…·å®¢æˆ·ç«¯æ“作...
+TTC_ENTER_TO_EXIT \n----------------------------------------\n在客户模å¼ä¸‹å¼€å¯ç½‘络传输速度测试工具。\n\n按下Enteré”®åœæ­¢å®¢æˆ·ç«¯ç¨‹åºã€‚\n----------------------------------------\n\n
+TTC_RES_TITLE \n\n网络传输速度测试工具 \n\n
+TTC_RES_COLUMN_1 项目å称
+TTC_RES_COLUMN_2 正常查看
+TTC_RES_COLUMN_3 简化查看
+TTC_RES_SPAN 检测时的使用时间
+TTC_RES_ETHER 以太网帧数æ®æ ¡æ­£
+TTC_RES_BYTES_DOWNLOAD 下载通信数æ®é‡
+TTC_RES_BYTES_UPLOAD 上载通信数æ®é‡
+TTC_RES_BYTES_TOTAL 总通信数æ®é‡
+TTC_RES_DOUBLE 中继器输入输出总åžåé‡è®¡ç®—
+TTC_RES_BPS_DOWNLOAD 下载方å‘çš„å¹³å‡åžåé‡
+TTC_RES_BPS_UPLOAD 上传方å‘çš„å¹³å‡åžåé‡
+TTC_RES_BPS_TOTAL 总平å‡åžåé‡
+
+
+# Check 命令
+CMD_Check 检测 SoftEther VPN 是å¦èƒ½æ­£å¸¸è¿è¡Œ
+CMD_Check_Help 正在è¿è¡Œ vpncmd 的计算机上,正检测 SoftEther VPN Server / Bridge çš„è¿è¡Œå¹³å°æ˜¯å¦é€‚åˆã€‚\n通过了这一检查的系统,SoftEther VPN 软件有较高的å¯èƒ½æ€§è¿›è¡Œæ­£å¸¸è¿è¡Œã€‚此外,无法通过此检查的系统,如果使用了 SoftEther VPN 软件å¯èƒ½ä¼šå‘生一些问题。
+CMD_Check_Args Check
+
+
+# 关于系统 checker
+# (包å«ç€ä¸€éƒ¨åˆ†å¥‡æ€ªçš„字符串,ä¸è¿‡ï¼Œæ˜¯æ£€æµ‹å­—符编ç å˜æ¢ç”¨çš„)
+CHECK_TITLE ---------------------------------------------------\nSoftEther VPN è¿è¡ŒçŽ¯å¢ƒæ£€æŸ¥å·¥å…·\n\nCopyright (c) SoftEther VPN Project.\nAll Rights Reserved.\n\n
+CHECK_NOTE 如果è¿è¡Œäº†æ­¤è¿è¡ŒçŽ¯å¢ƒæ£€æµ‹å·¥å…·çš„系统通过了测试,SoftEther VPN 软件有较高的è¿è¡Œå¯èƒ½æ€§ã€‚检测å¯èƒ½éœ€è¦ä¸€å®šçš„时间。请ç¨å€™...\n\n
+CHECK_EXEC_TAG '%s' 的检测中...\n
+CHECK_PASS [åˆæ ¼] â—‹
+CHECK_FAIL [ä¸åˆæ ¼] ×
+CHECK_RESULT_1 全部检测通过,说明 SoftEther VPN Server / Bridge 在此系统上正常è¿è¡Œçš„å¯èƒ½æ€§å¾ˆé«˜ã€‚
+CHECK_RESULT_2 一部分的检测结果是ä¸åˆæ ¼ã€‚请确认系统的è¿è¡ŒçŽ¯å¢ƒã€‚如果在这个系统上实行 SoftEther VPN Server / Bridge,有å‘生问题的å¯èƒ½æ€§ã€‚
+CHECK_TEST_123456789 123456789
+
+
+CHECK_PROC_KERNEL 内核系统
+CHECK_PROC_MEMORY 存储器æ“作系统
+CHECK_PROC_STRINGS ANSI / Unicode 字符串处ç†ç³»ç»Ÿ
+CHECK_PROC_FILESYSTEM 文件系统
+CHECK_PROC_THREAD 线程处ç†ç³»ç»Ÿ
+CHECK_PROC_NETWORK 网络系统
+
+
+######################################################
+# #
+# 安装å‘导(SW)字符串 #
+# #
+######################################################
+
+SW_TITLE SoftEther VPN 安装å‘导 (版本 %S)
+SW_EXIT_CONFIRM SoftEther VPN 的安装未完æˆã€‚\r\n\r\n您确定è¦é€€å‡ºå—?
+SW_UNINSTALL_CONFIRM å¼€å¯%så¸è½½ç¨‹åºã€‚\r\n\r\n您确定è¦ç»§ç»­å—?
+
+
+SW_COMPONENT_VPNSERVER_TITLE SoftEther VPN Server
+SW_COMPONENT_VPNSERVER_DESCRIPTION 把它安装在æœåŠ¡å™¨è®¡ç®—机上作为 VPN 的中心站点。管ç†å·¥å…·ä¹Ÿä¼šåŒæ—¶å®‰è£…。
+
+SW_COMPONENT_VPNCLIENT_TITLE SoftEther VPN Client
+SW_COMPONENT_VPNCLIENT_DESCRIPTION 安装它在 VPN Client 电脑上。VPN Client å°ç”µè„‘将能连接到中心 VPN Server 了。管ç†å·¥å…·ä¹Ÿä¼šåŒæ—¶å®‰è£…。
+
+SW_COMPONENT_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SW_COMPONENT_VPNBRIDGE_DESCRIPTION 安装它在æ¯ä¸ªç«™ç‚¹çš„电脑上。æ¯ä¸ª VPN Bridge 将会建立一个通å‘中心 VPN Server çš„ VPN 连接。管ç†å·¥å…·ä¹Ÿä¼šåŒæ—¶å®‰è£…。
+
+SW_COMPONENT_VPNSMGR_TITLE SoftEther VPN Server 管ç†å·¥å…· (ä»…é™ç®¡ç†å·¥å…·)
+SW_COMPONENT_VPNSMGR_DESCRIPTION 安装的åªæœ‰ VPN Server 管ç†å·¥å…·ã€‚ä¸ä¼šå®‰è£… VPN Server æœåŠ¡ç¨‹åºã€‚您å¯ä»¥åœ¨ Windows, Linux, Mac OS X, Solaris, FreeBSD 的系统上使用此 VPN Server 管ç†å·¥å…·è¿›è¡Œè¿žæŽ¥å’Œç®¡ç†è¿œç¨‹çš„ VPN Server / Bridge 端。
+
+SW_COMPONENT_VPNCMGR_TITLE SoftEther VPN Client 管ç†å·¥å…·(ä»…é™ç®¡ç†å·¥å…·)
+SW_COMPONENT_VPNCMGR_DESCRIPTION 安装的åªæœ‰ VPN Client 管ç†å·¥å…·ã€‚ä¸ä¼šå®‰è£… VPN Client æœåŠ¡ç¨‹åºã€‚您å¯ä»¥åœ¨ Windows 或 Linux 的系统上使用此 VPN Client 管ç†å·¥å…·è¿›è¡Œè¿žæŽ¥å’Œç®¡ç†è¿œç¨‹çš„ VPN Client 。
+
+SW_WELCOME_TITLE 欢迎æ¥åˆ° SoftEther VPN 安装å‘导
+SW_MODE_TITLE 选择一个安装模å¼
+SW_NOT_ADMIN_TITLE 没有足够æƒé™
+SW_COMPONENTS_TITLE 选择安装一个软件部分
+SW_EULA_TITLE 最终用户许å¯åè®®
+SW_WARNING_TITLE é‡è¦ä¿¡æ¯
+SW_DIR_TITLE 安装目录
+SW_READY_TITLE 准备安装l
+SW_PERFORM_TITLE 安装正在进行中
+SW_ERROR_TITLE 安装结果
+SW_FINISH_TITLE 安装结æŸ
+SW_UNINST1_TITLE å¸è½½ç¨‹åºr
+SW_LANG1_TITLE SoftEther VPN : é…置显示语言
+SW_EASY1_TITLE 欢迎æ¥åˆ° SoftEther VPN Client 简å•å®‰è£…程åºåˆ›å»ºå·¥å…·
+SW_EASY2_TITLE 指定文件夹
+SW_WEB1_TITLE 欢迎æ¥åˆ° SoftEther VPN Client Web安装程åºåˆ›å»ºå·¥å…·
+SW_WEB2_TITLE 指定文件夹
+
+SW_UNINSTALLINFO_URL http://selinks.org/
+SW_UNINSTALLINFO_PUBLISHER SoftEther VPN Project
+
+
+SW_COMPONENTS_ABOUT_TAG 关于 %s
+SW_COMPONENTS_REQUIRE_ADMIN 安装需è¦ç®¡ç†å‘˜æƒé™
+SW_COMPONENTS_REQUIRE_ADMIN_TEXT 您需è¦ä¸€ä¸ªæœ‰ç®¡ç†æƒé™çš„用户æ¥é‡å¯æœ¬å®‰è£…å‘导,并以系统模å¼å®‰è£… %s。以系统模å¼å®‰è£…,请点击åŽé€€ã€‚
+SW_DIR_SELECT 请指定安装目录
+SW_DIR_MORE_THAN_110 目录å太长。\r\n最多指定 110 个字æ¯.
+SW_DIR_WRITE_ERROR 无法创建指定的目录 "%s",或在目录中写入文件失败。\r\n\r\n指定å¦å¤–一个目录。
+SW_DIR_DST_IS_SAME_TO_SRC 指定的目录 "%s" 与æºç›®å½•ç›¸åŒã€‚
+SW_DIR_IS_NOT_HDD 指定的目录 "%s" ä¸åœ¨æœ¬åœ°ç¡¬ç›˜é©±åŠ¨ä¸Šã€‚\r\n\r\nè¦ "%s" 在系统模å¼ä¸‹å®‰è£…,您必须指定一个在本地硬盘驱动上的目录。
+SW_DIR_IS_NOT_FULLPATH 目录 "%s" ä¸æ˜¯å…¨è·¯å¾„æ ¼å¼ã€‚\r\n\r\n请指定一个全路径目录。
+SW_DIR_DST_IS_OTHER_PRODUCT 指定的目录已ç»æœ‰å¦ä¸€ä¸ªéƒ¨åˆ†å·²å®‰è£…。\r\n\r\n请指定å¦å¤–一个目录。
+SW_DIR_DST_IS_NEWER 本软件的更新版本已ç»å®‰è£…到指定目录。\r\n\r\n您ä¸å¿…安装本版本。
+SW_DIR_DST_IS_NEWER_2 本软件的更新版本已ç»å®‰è£…到指定目录。\r\n\r\n本安装程åºå°†å¯¼å…¥å’Œåº”用已嵌入在简å•å®‰è£…工具中的 VPN 连接设置。程åºæ–‡ä»¶ä¸ä¼šè¢«è¦†ç›–。
+SW_DIR_DST_IS_BROKEN 无法读å–指定目录下的文件 "%s"。\r\n\r\n请指定å¦å¤–一个目录。
+SW_DIR_DST_IS_SYSTEM_MODE åŒæ ·çš„软件已ç»åœ¨æŒ‡å®šç›®å½•ä¸­ä»¥ç³»ç»Ÿæ¨¡å¼å®‰è£…。\r\n\r\n请指定å¦å¤–一个目录。
+SW_DIR_DST_IS_USER_MODE åŒæ ·çš„软件已ç»åœ¨æŒ‡å®šç›®å½•ä¸­ä»¥ç”¨æˆ·æ¨¡å¼å®‰è£…。\r\n\r\n请指定å¦å¤–一个目录。
+SW_SYSTEM_MODE_ALREADY_INSTALLED 本软件 "%s" 以系统模å¼è¢«å®‰è£…在这å°ç”µè„‘上。\r\n\r\nåŒæ ·çš„软件以用户模å¼å’Œç³»ç»Ÿæ¨¡å¼å®‰è£…在åŒä¸€å°ç”µè„‘上会å‘生冲çªã€‚\r\n\r\n您确定è¦ä»¥ç”¨æˆ·æ¨¡å¼ç»§ç»­è¿›è¡Œå®‰è£…?
+
+SW_NOT_INSTALL_SRC 安装程åºå·²åœ¨ä¸€ä¸ªå¤–部的安装æºæ‰§è¡Œã€‚\r\n\r\nä¸èƒ½å†ç»§ç»­å®‰è£…。
+SW_SETUPLOG_CORRUPTED "setuplog.dat" 文件已被破å。
+SW_MSI_UNINSTALL_FAILED 之å‰çš„版本 %s (产å“å·: "%S")已安装。 Windows安装工具å¸è½½æ—§ç‰ˆæœ¬å¤±è´¥ã€‚\r\n\r\n请您手动å¸è½½å¹¶ä¸”é‡å¯æœ¬å®‰è£…工具。
+SW_MSI_UNINSTALL_REBOOT_REQUIRED Windows 安装工具已ç»å¸è½½æ—§ç‰ˆæœ¬ %s。请é‡å¯ç”µè„‘。\r\n\r\n点击结æŸæŒ‰é’®å¹¶ä¸”手动é‡å¯ç”µè„‘,然åŽåœ¨ç”µè„‘é‡å¯åŽï¼Œé‡å¯æœ¬å®‰è£…工具。
+SW_NOTICE_VPNSERVER_IS_INSTALLED SoftEther VPN Bridge 端作为软件一部分æ¥å®‰è£…。但是,本电脑已ç»å®‰è£…了 SoftEther VPN Server。\r\n\r\n通常,您ä¸éœ€è¦åœ¨åŒä¸€å°ç”µè„‘上åŒæ—¶å®‰è£… SoftEther VPN Server 端和 SoftEther VPN Bridge 端。\r\n如果您åŒæ—¶å®‰è£…了这两个软件,那么有些冲çªå°±ä¼šå‘生,例如端å£å·é‡å¤ã€‚\r\n如果您想把 SoftEther VPN Server 端替æ¢æˆ SoftEther VPN Bridge 端,您应该退出本安装工具,å¸è½½ SoftEther VPN Server 端,并在å¸è½½æˆåŠŸåŽé‡å¯æœ¬å®‰è£…工具。\r\n\r\n您确定è¦ç»§ç»­ SoftEther VPN Bridge 端的安装å—?
+SW_NOTICE_VPNBRIDGE_IS_INSTALLED SoftEther VPN Server 端被选为一个部分æ¥å®‰è£…。但是,本电脑已安装 SoftEther VPN Bridge 端。通常,您ä¸éœ€è¦åœ¨åŒä¸€å°ç”µè„‘上åŒæ—¶å®‰è£… SoftEther VPN Server 端和 SoftEther VPN Bridge 端。\r\n如果您åŒæ—¶å®‰è£…了这两个软件,那么有些冲çªå°±ä¼šå‘生,例如端å£å·é‡å¤ã€‚\r\n如果您想把 SoftEther VPN Bridge 替æ¢æˆ SoftEther VPN Server 端,您应该退出本安装工具,å¸è½½ SoftEther VPN Bridge,并在å¸è½½æˆåŠŸåŽé‡å¯æœ¬å®‰è£…工具。\r\n\r\n您确定è¦ç»§ç»­ SoftEther VPN Server 端的安装å—?
+SW_OS_FAILED 本æ“作系统ä¸æ”¯æŒ%s.
+SW_LANG_NOT_CHANGED %s的语言设置没有改å˜ã€‚
+SW_LANG_LIST_LOAD_FAILED 载入å¯ç”¨è¯­è¨€åˆ—表失败。
+SW_LANG_OK 显示语言 %s 修改æˆåŠŸã€‚\r\nå¦‚æžœç›®å‰ %s程åºæ­£åœ¨è¿è¡Œï¼Œè¯·é€€å‡ºå¹¶é‡å¯ï¼Œä»¥æ”¹å˜æ˜¾ç¤ºè¯­è¨€ã€‚如果显示语言ä¾ç„¶æœªæ”¹å˜ï¼Œè¯·é‡å¯ Windows。\r\n
+SW_LANG_OK_SERVICE 记录æœåŠ¡ç¨‹åºçš„日志文件的语言会在é‡å¯åŽä¿®æ”¹ã€‚
+SW_LANG_OK_VPNCMGR \r\n在退出和é‡å¯ VPN Client 管ç†å™¨ä¹‹åŽï¼Œå…¶æ˜¾ç¤ºè®¾ç½®å°†ä¼šæ”¹å˜ã€‚ (包括任务托盘的彻底终止)
+SW_CHILD_PROCESS_ERROR å­è¿›ç¨‹æ‰§è¡Œå¤±è´¥ã€‚
+SW_EXE_FILTER Windows å¯æ‰§è¡Œæ–‡ä»¶ (*.EXE)|*.exe|All Files (*.*)|*.*
+SW_PERFORM_MSG_EASY_INFO 编辑 VPN Client 简å•å®‰è£…工具
+SW_EASY_FINISHED_MSG VPN Client 简å•å®‰è£…工具创建æˆåŠŸã€‚\r\n本安装工具ä¿å­˜ä¸ºå¦‚下文件å。\r\n\r\n%s\r\n\r\n您å¯ä»¥åœ¨å…¬å¸é‡Œåˆ†é…以上的文件。
+SW_EASY_ERROR_MSG VPN Client 简å•å®‰è£…工具创建失败。
+SW_OTHER_INSTANCE_EXISTS å¦å¤–一个 SoftEther VPN 安装å‘导正在è¿è¡Œä¸­\r\n\r\n您å¯ä»¥åœ¨é‚£ä¸ªå‘导退出åŽï¼Œç»§ç»­è¿è¡Œæ­¤å‘导。
+SW_PERFORM_MSG_WEB_INFO 编译 VPN Client Web安装工具
+SW_WEB_ERROR_MSG VPN Client Web 安装工具创建失败。
+SW_INSTALLER_CACHE_IS_NOT_SIGNED ç›®å‰å·²å®‰è£… SoftEther VPN Client çš„è¿™å°ç”µè„‘没有安 SoftEther å…¬å¸ç­¾ç½² Authenticode æ•°å­—è¯ä¹¦çš„æ•°å­—ç­¾å包。\r\n它有å¯èƒ½æ˜¯ä»Žä¸€ä¸ªå®¢æˆ·å®šåˆ¶çš„安装工具上安装的(例如:简å•å®‰è£…程åºç”Ÿæˆå™¨åˆ¶é€ çš„一个安装程åºã€‚)\r\n\r\n如果您继续创建 Web 安装工具,当下载的时候,会在用户界é¢ä¸Šå‡ºçŽ°ä¸€ä¸ªè­¦ç¤ºä¿¡æ¯ã€‚\r\n为é¿å…出现警示信æ¯ï¼Œæ‚¨éœ€è¦å–消本创建å‘导,从 SoftEther å…¬å¸å®˜ç½‘下载最新版本的 SoftEther VPN Client,é‡æ–°å®‰è£…并开å¯æœ¬ Web 安装工具创建器å‘导。\r\n\r\n你确定è¦ç»§ç»­åˆ›å»ºä¸€ä¸ª Web 安装工具å—?
+SW_FILE_NOT_FOUNT 没有找到文件 "%s"
+SW_WEB_FINISHED Web安装工具已创建,并ä¿å­˜ä¸º "%s"。\r\n\r\n请将 ZIP 文件解压缩,并将解压åŽçš„文件上传到 Web æœåŠ¡å™¨ï¼Œç¼–辑一个HTML文件和一个 inf 文件æ¥é€‚当替æ¢URL。\r\n\r\n部署 Web 安装程åºçš„解释说明在ZIP文件中æ述。
+
+
+
+
+SW_PERFORM_MSG_INIT_TASKS 准备任务…
+SW_PERFORM_MSG_COPY_PREPARE 准备å¤åˆ¶æ–‡ä»¶â€¦
+SW_PERFORM_MSG_WRITE_ERROR 写入目标文件 "%s" 失败。\r\n\r\nå¯èƒ½æœ‰å¦å¤–一个项目正在使用该文件。\r\n如果程åºæˆ–者æœåŠ¡%s正在è¿è¡Œï¼Œè¯·å…³é—­ï¼Œå¹¶ç‚¹å‡»é‡è¯•ã€‚
+SW_PERFORM_MSG_COPY_FILE 正在å¤åˆ¶ "%s" ...
+SW_PERFORM_MSG_SET_SECURITY 在 "%s" 设置安全系统
+SW_PERFORM_MSG_PLUGIN æ’件安装中...
+SW_PERFORM_MSG_STOP_SVC åœæ­¢ "%s" çš„æœåŠ¡
+SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK 文件 "%s" 被一个正在è¿è¡Œçš„程åºé”定。正等待解é”……
+SW_PERFORM_MSG_INSTALL_SVC 安装 %s æœåŠ¡...
+SW_PERFORM_MSG_START_SVC 开始 %s æœåŠ¡...
+SW_PERFORM_MSG_CREATE_LINKS 创建快æ·æ–¹å¼æ–‡ä»¶å¤¹â€¦â€¦
+SW_PERFORM_MSG_DELETE_LINKS 删除快æ·æ–¹å¼æ–‡ä»¶å¤¹â€¦â€¦
+SW_PERFORM_MSG_DELETE_OLD_LINKS 删除旧的快æ·æ–¹å¼æ–‡ä»¶å¤¹â€¦â€¦
+SW_PERFORM_MSG_REGISTER_UNINSTALL 在控制é¢æ¿æ³¨å†Œå¸è½½ä¿¡æ¯â€¦â€¦
+SW_PERFORM_MSG_IMPORTING_ACCOUNT 在简å•å®‰è£…工具中的导入嵌入的 VPN 连接设置...
+SW_PERFORM_MSG_DELETE_SETUP_INFO 删除安装信æ¯å’Œæ—¥å¿—...
+SW_PERFORM_MSG_WRITE_LOG 写入一个设置日志...
+SW_PERFORM_MSG_COPY_ERROR å¤åˆ¶æ–‡ä»¶ "%s" 失败。
+SW_PERFORM_MSG_CRAETE_LINK_ERROR 创建快æ·æ–¹å¼æ–‡ä»¶ "%s" 失败。\r\n\r\n您è¦é‡è¯•å—?
+SW_PERFORM_MSG_WRITE_LOG_ERROR 安装日志文件 "%s" 创建中。\r\n\r\n您è¦é‡è¯•å—?
+SW_PERFORM_MSG_STOP_SVC_ERROR 关闭 "%s" æœåŠ¡(内部å: "%S")失败。
+SW_PERFORM_MSG_START_SVC_ERROR å¼€å¯ "%s" æœåŠ¡(内部å: "%S")失败。
+SW_PERFORM_MSG_SVC_UNINSTALL_FAILED å¸è½½ "%s" æœåŠ¡(内部å: "%S")失败。
+SW_PERFORM_MSG_SVC_INSTALL_FAILED 安装 "%s" æœåŠ¡(内部å: "%S")失败。
+SW_PERFORM_MSG_SVC_USERMODE_EXEC_FAILED å¼€å¯ç”¨æˆ·æ¨¡å¼ %s æœåŠ¡å¤±è´¥ã€‚
+SW_PERFORM_MSG_UPDATING 系统设置更新中…….
+SW_PERFORM_MSG_FINISHED 安装进程结æŸã€‚
+SW_PERFORM_MSG_UNINSTALL_MSI Windows 安装工具正在å¸è½½æ—§ç‰ˆæœ¬ %s...
+SW_PERFORM_MSG_UPDATE_LANG_CONFIG 修改语言设置...
+
+SW_PERFORM_MSG_INIT_UNINST 正准备å¸è½½...
+SW_PERFORM_MSG_DELETE_PREPARE 正准备删除文件...
+SW_PERFORM_MSG_DELETE_ERROR 删除文件 "%s" 失败。\r\n\r\nå¯èƒ½æœ‰å¦å¤–一个程åºæ­£åœ¨ä½¿ç”¨è¯¥æ–‡ä»¶ã€‚\r\n如果程åºæˆ–æœåŠ¡ %s 正在è¿è¡Œï¼Œè¯·å…³é—­ï¼Œå¹¶ç‚¹å‡»é‡è¯•ã€‚
+SW_PERFORM_MSG_UNINSTALL_SVC æœåŠ¡ "%s" å¸è½½ä¸­...
+SW_PERFORM_MSG_DELETE 正在删除æœåŠ¡ "%s" ...
+SW_PERFORM_MSG_EASY_INIT 创建简å•å®‰è£…工具..
+SW_PERFORM_MSG_WEB_INIT 创建 Web 安装工具..
+SW_PERFORM_MSG_INSTALL_SELOW 一个系统还原点创建中并安装必è¦æˆåˆ†ã€‚è¿™å¯èƒ½éœ€è¦ä¸€æ®µæ—¶é—´...
+
+
+
+SW_TAG_USERNAME \ (用户模å¼)
+SW_DIRNAME_CONFIG_TOOLS é…置工具
+SW_DIRNAME_ADMIN_TOOLS 管ç†å·¥å…·
+SW_DIRNAME_LANGUAGE_TOOLS 语言设置
+
+SW_RUN_TEXT_VPNSMGR å¼€å¯ SoftEther VPN Server 管ç†å·¥å…·
+SW_RUN_TEXT_VPNCMGR å¼€å¯ SoftEther VPN Client 管ç†å·¥å…·.
+
+# --- Do not translate this section !!! stay them in English !!! ---
+SW_TAG_USERNAME_ENGLISH \ (User-Mode)
+SW_LINK_NAME_VPNSERVER_SVC SoftEther VPN Server User-mode Service
+SW_LINK_NAME_VPNBRIDGE_SVC SoftEther VPN Bridge User-mode Service
+SW_LONG_VPNSERVER SoftEther VPN Server
+SW_LONG_VPNCLIENT SoftEther VPN Client
+SW_LONG_VPNBRIDGE SoftEther VPN Bridge
+SW_LONG_VPNSMGR SoftEther VPN Server Manager
+SW_LONG_VPNCMGR SoftEther VPN Client Manager
+SW_LANG_SET_FAILED Failed to write the new language setting on lang.config file.
+# --- end of "Do not translate this section" ---
+
+
+# å¿«æ·æ–¹å¼æ–‡ä»¶å
+SW_LINK_NAME_VPNSMGR_SHORT SoftEther VPN Server 管ç†å·¥å…·
+SW_LINK_NAME_VPNSMGR_SHORT_UM SE-VPN Server Manager (User)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY SE-VPN Server Manager (Tools)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM SE-VPN Server Manager (User)
+SW_LINK_NAME_VPNSMGR_FULL SoftEther VPN Server 管ç†å·¥å…·
+SW_LINK_NAME_VPNSMGR_COMMENT 您在一个远程计算机上å¯ä»¥ç®¡ç† SoftEther VPN Server 或者 SoftEther VPN Bridge 端。
+
+SW_LINK_NAME_VPNCMGR_SHORT SoftEther VPN Client 管ç†å·¥å…·
+SW_LINK_NAME_VPNCMGR_FULL SoftEther VPN Client 管ç†å·¥å…·
+SW_LINK_NAME_VPNCMGR_COMMENT 您å¯ä»¥é€šè¿‡ä½¿ç”¨ SoftEther VPN Client 连接到 VPN Server。
+
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT SoftEther VPN Client 远程管ç†å·¥å…·
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM SE-VPN Client Remote Manager (User)
+SW_LINK_NAME_VPNCMGRTOOLS_FULL SoftEther VPN Client 远程管ç†å·¥å…·
+
+SW_LINK_NAME_VPNCMGR2_FULL 管ç†è¿œç¨‹ç”µè„‘上的 SoftEther VPN Client
+SW_LINK_NAME_VPNCMGR2_COMMENT 您å¯ä»¥å»ºç«‹ä¸€ä¸ªè¿œç¨‹è¿žæŽ¥æ¥ç®¡ç†è¿œç¨‹ç”µè„‘上的 SoftEther VPN Client 。
+
+SW_LINK_NAME_VPNCMGRTRAY_FULL SoftEther VPN Client 管ç†å·¥å…·å¯åŠ¨èœå•
+SW_LINK_NAME_VPNCMGRTRAY_COMMENT 在任务æ çš„通知区域注册一个 SoftEther VPN Client 图标。
+
+SW_LINK_NAME_EASYINSTALLER 简å•å®‰è£…工具创建工具
+SW_LINK_NAME_EASYINSTALLER_COMMENT 为公å¸ç³»ç»Ÿç®¡ç†å‘˜åˆ›å»º SoftEther VPN Client 简å•å®‰è£…工具的工具,有自动快速å¯åŠ¨åˆ°æŒ‡å®šç›®æ ‡ VPN 连接的功能。
+
+SW_LINK_NAME_WEBINSTALLER Web安装工具创建工具
+SW_LINK_NAME_WEBINSTALLER_COMMENT 为公å¸ç³»ç»Ÿç®¡ç†å‘˜åˆ›å»º SoftEther VPN Client Web安装工具(ActiveX 安装工具)的工具,有自动快速å¯åŠ¨åˆ°æŒ‡å®šç›®æ ‡ VPN 连接的功能。
+
+
+SW_LINK_NAME_VPNCMD SoftEther VPN 命令行实用工具(vpncmd)
+SW_LINK_NAME_VPNCMD_COMMENT 用 vpncmd 在命令行界é¢ç®¡ç† SoftEther VPN Server , SoftEther VPN Bridge 端和 SoftEther VPN Client 。
+SW_LINK_NAME_TRAFFIC 网络传输速度测é‡å·¥å…·
+SW_LINK_NAME_TRAFFIC_COMMENT 工具执行用 TCP/IP 连接的两å°ç”µè„‘之间的数æ®åŒ…传输,会用尽é‡å¤§çš„åžåé‡ï¼Œä»Žè€Œæµ‹é‡å‡ºç²¾ç¡®çš„网络å¯ç”¨ä¼ è¾“速度。本工具ä¸ä»…é™äºŽ VPN,也å¯ä»¥ç”¨åœ¨ç‰©ç†ç½‘络中。
+SW_LINK_NAME_TCP TCP/IP 优化实用工具
+SW_LINK_NAME_TCP_COMMENT TCP/IP 优化实用工具å¯ä»¥è°ƒèŠ‚ Windows çš„ TCP/IP å‚数,以æ高本电脑的网络通信åžåé‡ã€‚
+SW_LINK_NAME_SERVICES æœåŠ¡æ­£åœ¨æœ¬ç”µè„‘è¿è¡Œ
+SW_LINK_NAME_SERVICES_COMMENT 开始,结æŸå’Œé…ç½® Windows æœåŠ¡ã€‚您å¯ä»¥å¼€å¯å’Œå…³é—­ SoftEther VPN æœåŠ¡ã€‚
+SW_LINK_NAME_VPNSERVER_SVC_COMMENT 使用用户模å¼å¼€å¯ SoftEther VPN Server æœåŠ¡ã€‚
+SW_LINK_NAME_VPNBRIDGE_SVC_COMMENT 使用用户模å¼å¼€å¯ SoftEther VPN Bridge æœåŠ¡ã€‚
+
+SW_LINK_NAME_UNINSTALL å¸è½½ %s
+SW_LINK_NAME_UNINSTALL_COMMENT 在本电脑中å¸è½½ %s
+SW_LINK_NAME_LANGUAGE é…置显示语言
+SW_LINK_NAME_LANGUAGE_COMMENT 修改 %s 的显示语言设置。
+
+SW_LINK_NAME_DEBUG 调试信æ¯é‡‡é›†å·¥å…·
+SW_LINK_NAME_DEBUG_COMMENT 采集 SoftEther VPN 的调试信æ¯ã€‚åªæœ‰å½“您的支æŒäººå‘˜è¦æ±‚你这样åšæ—¶ï¼Œæ‰ä½¿ç”¨æ­¤å·¥å…·ã€‚
+
+
diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb
new file mode 100644
index 00000000..2e6753e9
--- /dev/null
+++ b/src/bin/hamcore/strtable_en.stb
@@ -0,0 +1,7091 @@
+# SoftEther VPN String Table
+# Copyright (c) SoftEther VPN Project. All Rights Reserved.
+#
+# http://www.softether.co.jp/
+
+
+###########################################################################
+# #
+# String data such as messages in software #
+# (Excludes dialog box resource strings) #
+# #
+###########################################################################
+
+
+
+# Environment parameters
+DEFAULT_FONT Tahoma
+DEFAULT_FONT_WIN7 Segoe UI
+DEFAULT_FONT_2 Tahoma
+DEFAULT_FONT_SIZE 8
+DEFAULE_LOCALE - - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)
+
+
+# 言語
+# (0: 日本語, 1: 英語)
+LANG 1
+LANGSTR English
+
+STRTABLE_ID SE_VPN_20121007
+
+
+# Strings for Japanese version only (not required for other language versions.)
+CM_JAPANESE_ONLY_OLD_STARTUP %s\\SoftEther VPN Client 2.0 タスクトレイ.lnk
+
+
+# Software information
+PRODUCT_NAME_VPN_CLI SoftEther VPN Client
+PRODUCT_NAME_VPN_CMGR SoftEther VPN Client Manager
+PRODUCT_NAME_VPN_SVR SoftEther VPN Server
+PRODUCT_NAME_VPN_BRIDGE SoftEther VPN Bridge
+PRODUCT_NAME_VPN_SMGR SoftEther VPN Server Manager
+PRODUCT_NAME_ELOGSVC SoftEther EtherLogger Beta Edition
+PRODUCT_NAME_ELOGMGR SoftEther EtherLogger Manager Beta Edition
+
+# Branding String for Limited Connection
+# BRANDED_C_TO_S Branded_VPN
+# BRANDED_C_FROM_S Branded_VPN
+
+# Client ID (sample)
+# CLIENT_ID 123
+
+# Family Name for Software Update Check
+PRODUCT_FAMILY_NAME SoftEther
+
+# Product information
+SE_COMPANY_URL https://selinks.org/?se
+SE_VPNAZURE_URL https://selinks.org/?vpnazure
+
+# Common strings
+COMMON_UNKNOWN (Unknown)
+
+
+# Protocol error strings
+ERR_UNKNOWN An unknown error occurred.
+ERR_0 No error.
+ERR_1 Connection to the server failed. Check network connection and make sure that address and port number of destination sever are correct.
+ERR_2 Protocol error occurred. Error was returned from the destination server.
+ERR_3 Connection was disconnected.
+ERR_4 Protocol error occurred.
+ERR_5 A client which is non-SoftEther VPN software has connected to the port.
+ERR_6 The command was canceled by user.
+ERR_7 The server denied the specified auth type.
+ERR_8 The specified Virtual Hub does not exist on the server.
+ERR_9 User authentication failed.
+ERR_10 The specified Virtual Hub is currently stopped. Wait for a while and then reconnect.
+ERR_11 The VPN session was deleted. It is possible that either the administrator disconnected the session or the connection from the client to the VPN Server was disconnected.
+ERR_12 Access was denied.
+ERR_13 Time-out occurred during VPN session communication. It is possible the connection from the client to the VPN Server was disconnected.
+ERR_14 Protocol number is invalid.
+ERR_15 There are too many TCP/IP connections.
+ERR_16 There are too many sessions connected to either the destination server or Virtual Hub.
+ERR_17 Connection to proxy server failed.
+ERR_18 An error occurred on the proxy server.
+ERR_19 User authentication failed on the proxy server.
+ERR_20 There are too many sessions by the same user. Other person might be connected to the Virtual Hub as the same user.
+ERR_21 A license error occurred on the VPN Server. Contact the VPN Server's administrator.
+ERR_22 Cannot access the Virtual Network Adapter device driver. Check the Virtual Network Adapter is installed and make sure it isn't disabled.
+ERR_23 An internal error occurred.
+ERR_24 Access to either the smart card or USB hardware token device failed.
+ERR_25 The PIN code is incorrect.
+ERR_26 The specified certificate is not stored on either the smart card or the USB hardware token device.
+ERR_27 The specified private key is not stored on either the smart card or the USB hardware token device.
+ERR_28 Write operation to the smart card or USB hardware token device failed.
+ERR_29 Object not found.
+ERR_30 A Virtual Network Adapter with the specified name already exists. Specify a different name.
+ERR_31 Installation of the Virtual Network Adapter device driver failed.
+ERR_32 You cannot use the specified name for a Virtual Network Adapter device.
+ERR_33 Unsupported.
+ERR_34 VPN Connection Setting with the specified name already exists.
+ERR_35 The specified VPN Connection Setting is currently connected.
+ERR_36 The specified VPN Connection Setting does not exist.
+ERR_37 The specified VPN Connection Setting is not connected.
+ERR_38 Invalid parameter.
+ERR_39 Error occurred on smart card or USB hardware token.
+ERR_40 Authentication of smart card or USB hardware token was selected but the device to be used has not been selected. Select this from the Smart Card menu of Connection Manager.
+ERR_41 The specified Virtual Network Adapter is being used by at least one VPN Connection Setting. \r\nEither delete the VPN Connection Setting that is using this Virtual Network Adapter or change Virtual Network Adapter that this VPN Connection Setting is using.
+ERR_42 Cannot find the Virtual Network Adapter that the specified VPN Connection Setting is using. \r\nMake sure this Virtual Network Adapter exists. Also make sure the Virtual Network Adapter device has not been disabled. \r\n\r\nIf you cannot resolve the problem, either change the Virtual Network Adapter being used by this VPN Connection Setting or create a new Virtual Network Adapter with the same name.
+ERR_43 The Virtual Network Adapter used by the specified VPN Connection Setting is already being used by another VPN Connection Setting. \r\nIf there is another VPN Connection Setting that is using the same Virtual Network Adapter, disconnect that VPN Connection Setting.
+ERR_44 The Virtual Network Adapter being used by the specified VPN Connection Setting has been disabled. \r\nBefore using this VPN Connection Setting, enable the Virtual Network Adapter.
+ERR_45 The specified value is invalid.
+ERR_46 The connection destination is not a cluster controller.
+ERR_47 Trying to connect.
+ERR_48 Connection to the cluster controller failed.
+ERR_49 The cluster controller was unable to assign a new session on a cluster.
+ERR_50 Unable to manage the Virtual Hub of the cluster member server.
+ERR_51 The user's password used to connect was blank so the connection from remote is prohibited. Blank password can be allowed only to connections from the VPN Server's localhost (127.0.0.1).
+ERR_52 Not enough privileges.
+ERR_53 Specified listener not found.
+ERR_54 The listener of the specified port number already exists.
+ERR_55 This is not a cluster member server.
+ERR_56 The specified encryption algorithm name is not supported.
+ERR_57 The Virtual Hub with the specified name already exists on the server.
+ERR_58 There are too many registered Virtual Hubs. No more can be created. Delete the old Virtual Hubs.
+ERR_59 The Cascade Connection with the specified name already exists.
+ERR_60 A Cascade Connection cannot be created on a server on a cluster.
+ERR_61 The specified Cascade Connection is offline.
+ERR_62 There are too many access lists.
+ERR_63 There are too many users.
+ERR_64 There are too many groups.
+ERR_65 The specified group does not exist.
+ERR_66 The user with the specified name already exists on the Virtual Hub.
+ERR_67 The group with the specified name already exists on the Virtual Hub.
+ERR_68 A user with the specified name exists on the server but the type of authentication is not password authentication. Unable to change the password.
+ERR_69 The user name or old password you entered is incorrect. Note that the password is case-sensitive.
+ERR_70 Saitama.
+ERR_71 SoftEther has temporarily stopped the current distribution by order of the Japan Ministry of Economy Trade and Industry.
+ERR_72 SoftEther has temporarily stopped the current distribution by order of the IPA.
+ERR_73 Unable to disconnect the Cascade Connection's session. To delete the session, stop the Cascade Connection.
+ERR_74 The VPN Connection Setting for connection with the VPN Server is incomplete. At first you have to complete the VPN Connection Setting for connection with the VPN Server.
+ERR_75 VPN Connection to the VPN Server has already started.
+ERR_76 Not connected to the VPN Server.
+ERR_77 The specified X509 certificate file does not contain a RSA 1024 bit or 2048 bit public key. SoftEther VPN software supports only RSA 1024 bit or 2048 bit certificates.
+ERR_78 Unable to disconnect the SecureNAT session. To delete the session, stop the SecureNAT function.
+ERR_79 Cannot enable the SecureNAT in a clustering environment.
+ERR_80 The SecureNAT is not operating.
+ERR_81 This VPN Connection session to the VPN Server was disconnected by the firewall device installed by the network administrator. Contact the network administrator.
+ERR_82 Unable to disconnect the Local Bridge session. To delete the session, stop the Local Bridge.
+ERR_83 The Local Bridge is not operating.
+ERR_84 Local Bridge cannot be used by the destination VPN Server. Refer to online help or other documentation for the setting method when using Local Bridge on the VPN Server you are using.
+ERR_85 Unable to trust the certificate provided by the destination server. The setting to always verify the server certificate is enabled in the VPN Connection Settings. Either register a root certificate that can be trusted or register a individual certificate.
+ERR_86 The product code of the destination server is incorrect. It is not possible to connect from this client.
+ERR_87 The client and server version is different. Update the software.
+ERR_88 Failed to add a capture device. A same capture device might be already registered.
+ERR_89 Unable to connect to the destination server from this client. A special client software is required.
+ERR_90 The specified capture device is not registered.
+ERR_91 Unable to disconnect the Virtual Layer 3 Switch session. To delete the session, stop the Virtual Layer 3 Switch.
+ERR_92 A Virtual Layer 3 Switch with the specified name already exists. Specify a different name.
+ERR_93 Specified Virtual Layer 3 Switch not found.
+ERR_94 The specified name is invalid. Check if the name contains characters that cannot be used.
+ERR_95 Failed to add the Virtual Layer 3 interface.
+ERR_96 Failed to delete the Virtual Layer 3 interface.
+ERR_97 The Virtual Layer 3 interface that is connecting to the destination Virtual Hub of the specified Virtual Layer 3 interface already exists in the Virtual Layer 3 Switch. No more than one Virtual Layer 3 interface that connects to the same Virtual Hub can be defined in a Virtual Layer 3 Switch.
+ERR_98 Failed to add routing table entry.
+ERR_99 Failed to delete routing table entry.
+ERR_100 The specified routing table entry already exists.
+ERR_101 The client clock and the server clock are not synchronized with each other. Check the time settings.
+ERR_102 Unable to start this Virtual Layer 3 Switch. \r\n\r\nTo start the Virtual Layer 3 Switch, at least 1 virtual interface must be defined in the Virtual Layer 3 Switch.
+ERR_103 Not enough Client Connection Licenses on the destination VPN Server. Contact the server administrator.
+ERR_104 Not enough Bridge Connection Licenses on the destination VPN Server. Contact the server administrator.
+ERR_105 Due to current technical difficulties, the destination VPN Server is not receiving the connection. Either wait a while, or contact the VPN Server administrator requesting that the server log file be checked.
+ERR_106 The destination VPN Server's certificate has expired. Contact the VPN Server's administrator.
+ERR_107 A connection was requested in Monitoring Mode. But the security policy for the connecting user does not permit Monitoring Mode.
+ERR_108 A connection was requested in Bridge / Router Mode. But the security policy for the connecting user forbids both bridge mode and router mode.
+ERR_109 A connection from a client IP address was denied by the Source IP Restriction List of the Virtual Hub.
+ERR_110 There are too many items.
+ERR_111 Out of memory.
+ERR_112 The specified object already exists.
+ERR_113 A fatal error occurred. It is possible that the program operation is unable to continue.
+ERR_114 The destination VPN Server has detected a software license violation. Connection is refused. Contact the VPN Server's administrator.
+ERR_115 The destination VPN Server has connected via the Internet to an important server provided by SoftEther VPN Project and cannot validate a license. Either wait a while, or contact the VPN Server administrator requesting that the server log file and the Internet connection status of the server itself be checked.
+ERR_116 A software license violation was detected on the client side. Connection is refused.
+ERR_117 The command or file name is incorrect.
+ERR_118 The license key is incorrect.
+ERR_119 No valid product license is registered on the VPN Server. Contact the VPN Server's administrator.
+ERR_120 The product license required for the VPN Server to operate as a cluster is not registered. Contact the VPN Server's administrator.
+ERR_121 This VPN Connection Setting has been installed using the "Web Installer Creation Kit" or "Simple Installer Creation Kit". The destination server is not an edition that supports the SoftEther VPN 2.0 Administration Pack. Contact the system administrator or person who created the installer.
+ERR_122 With the VPN Server SDK for .NET, it is only possible to connect to the SoftEther VPN Server edition that supports the SoftEther VPN 2.0 Administration Pack. The destination VPN Server is not an edition that supports the SoftEther VPN 2.0 Administration Pack. Contact the system administrator.
+ERR_123 Beta Version Software on the destination server is expired. Contact to system administrator of the server to download a new beta version or full version from http://selinks.org/.
+ERR_124 The VPN connection to VPN Server is refused at server side.
+ERR_125 The VPN connection to VPN Server is refused at client side.
+ERR_126 The security policy enforced the VPN session to disconnect automatically because the specific time elapsed. If you wish to continue please re-connect.
+ERR_127 The VPN Server requires the special-version VPN Client software. Consult with the administrator.
+ERR_128 The number of registered user objects exceeds the maximum number which is allowed the product license applied on the VPN Server. You cannot add user objects anymore unless you delete old one, or upgrade the edition of the product.
+ERR_129 The subscription contract has already expired before the release-date of this version of VPN Server. The customer has been authorized to use VPN Server's builds only in the period of the subscription contract. The customer has to extend the period of the subscription. The customer also be able to 'downgrade' the version of VPN Server to older version which was released before the end of the subscription. If you want to downgrade the version, older versions might be available on http://selinks.org/.
+ERR_130 We are afraid that the trial license keys cannot be obtained frequently by the same customer. Please consider to purchase the product version.
+ERR_131 Several VPN Servers on the same IP address. You can specify the destination server's private IP or hostname concretely such as "Global IP address or host name/192.168.x.x". Or if a NAT is used on the server's side, configure the NAT to open, relay or transfer appropriate ports.
+ERR_132 The key for Dynamic DNS Service duplicates to others. The key will be reset automatically.
+ERR_133 The specified Dynamic DNS hostname is already used. Please change the hostname.
+ERR_134 The specified Dynamic DNS hostname has an invalid characters. Please change the hostname.
+ERR_135 The length of the specified Dynamic DNS hostname is too long. A hostname must be equal or shorter than 31 letters.
+ERR_136 The Dynamic DNS hostname is not specified.
+ERR_137 The length of the specified Dynamic DNS hostname is too long. A hostname must be equal of longer than 3 letters.
+ERR_138 The password of the specified user in the Virtual Hub must be reset before using MS-CHAP v2 authentication. Please ask the administrator of the VPN Server to reset the password by the VPN Server Manager or vpncmd which internal version is 4.0 or greater. Or you can change the password with VPN Client by yourself.
+ERR_139 The connection to the Dynamic DNS server was disconnected.
+ERR_140 Failed to initialize the ICMP (Ping) protocol. The process of the VPN Server might be running in a normal-user privileges. In such case, run the VPN Server as a system service. (in Linux / UNIX, run it in root privileges.)
+ERR_141 Failed to open the DNS port 53. Make sure that there are no other DNS server program (for example, BIND or Microsoft DNS Server) on the same computer. If there are conflicting services stop them. Or run the VPN Server's process in root privileges on Linux / UNIX/
+ERR_142 The OpenVPN Server function is not enabled.
+ERR_143 The Certificate Authentication function and the External Server Authentication function have not been implemented on the open-source version of SoftEther VPN yet. Choose either Anonymous Authentication or Password Authentication instead.
+ERR_144 Unacceptable operation. Use the VPN Gate Control Panel to change the VPN Gate Relay Server settings.
+ERR_145 Unacceptable operation. Use the VPN Gate Utility to modify the connection setting for VPN Gate Public VPN Relay Servers.
+ERR_146 The VPN Gate Service is running inside the VPN Client program. You cannot stop the VPN Gate Service on this screen. Use the VPN Client Manager to enable or disable the VPN Gate Service.
+ERR_147 This feature is not supported. It hasn't been implemented yet on the open-source version of SoftEther VPN.
+
+# Concerning licenses
+LICENSE_INFO_URL https://selinks.org/?new_license
+LICENSE_SUPPORT_URL https://selinks.org/?q=license_info&id=%s
+LICENSE_STATUS_OK Valid
+LICENSE_STATUS_EXPIRED Expired
+LICENSE_STATUS_ID_DIFF Server ID Mismatch
+LICENSE_STATUS_DUP Duplication
+LICENSE_STATUS_INSUFFICIENT Other Licenses are Required
+LICENSE_STATUS_COMPETITION Competition with Other Licenses
+LICENSE_STATUS_NONSENSE Meaningless for Current Edition
+LICENSE_STATUS_CPU CPU Type is Incompatible
+LICENSE_STATUS_OTHERERROR Unknown Error
+
+
+# Concerning TCP optimization
+TCPOPT_NOT_SUPPORTED The TCP Optimization Utility cannot be used on this operating system.
+TCPOPT_NOT_ADMIN Users without administrator privileges cannot use the TCP Optimization Utility.
+
+
+# Windows Vista / Windows 7 / Windows 8 Optimization
+VISTA_MMCSS_MSG Do you wish to optimize Windows Vista / Windows 7 / Windows 8 for playing multimedia files with VPN? (e.g. videos, audios and streaming)
+VISTA_MMCSS_MSG_2 Optimization for Windows Vista / Windows 7 / Windows 8 with VPN has already done.\r\nDo you wish to remote optimized configuration?
+VISTA_MMCSS_MSG_3 You cannot use optimization in currently environment.
+VISTA_MMCSS_MSG_4 You must have administrator privileges for this function.\r\nPlease note that in Windows Vista / Windows 7 / Windows 8 you should use "Run as Administrators" to execute program.
+VISTA_MMCSS_MSG_5 Optimization is finished.
+VISTA_MMCSS_MSG_6 Optimization configuration is removed.
+
+
+# Concerning PKCS utility
+PKCS_UTIL_TITLE PKCS#12 Writing Utility
+PKCS_UTIL_SAVEDLG_TITLE Select the PKCS#12 file that you want to write to the USB token.
+PKCS_UTIL_READ_ERROR Unable to read the file: %s.
+PKCS_UTIL_WRITE_OK_MSG The file %s was written to the USB hardware token.
+PKCS_UTIL_DELETE_OK_MSG The PKCS#12 certificate data was deleted from the USB hardware token.
+PKCS_UTIL_SECA_FILENAME seca_p12
+PKCS_MAKE_SURE The PKCS#12 certificate data written to USB token will be deleted. \r\n Once data is deleted it cannot be restored. \r\r\n\r\r\nDo you wish to continue?
+PKCS_UTIL_BAD_FILE The specified file could not be identified as a PKCS#12 file.
+
+
+# Concerning common dialogs
+DLG_ALL_FILES All Files (*.*)|*.*
+DLG_CERT_FILES X509 Certificate Files (*.CER;*.CRT)|*.cer;*.crt|All Files (*.*)|*.*
+DLG_KEY_FILTER Private Key Files (*.KEY;*.PEM)|*.key;*.pem|All Files (*.*)|*.*
+DLG_PKCS12_FILTER PKCS#12 Files (*.P12;*.PFX)|*.p12;*.pfx|All Files (*.*)|*.*
+DLG_CERT_OR_P12_FILTER X509 Certificate Files or PKCS#12 Files (*.CER;*.CRT;*.P12;*.PFX)|*.cer;*.crt;*.p12;*.pfx|X509 Certificate Files (*.CER;*.CRT)|*.cer;*.crt|PKCS#12 Files (*.P12;*.PFX)|*.p12;*.pfx|All Files (*.*)|*.*
+DLG_CONFIG_FILES Setting Files (*.CONFIG)|*.config|All Files (*.*)|*.*
+DLG_KEY_OR_P12_FILTER Private Key Files or PKCS#12 Files (*.KEY;*.PEM;*.P12;*.PFX)|*.key;*.pem;*.p12;*.pfx|Private Key Files (*.KEY;*.PEM)|*.key;*.pem|PKCS#12 Files (*.P12;*.PFX)|*.p12;*.pfx|All Files (*.*)|*.*
+DLG_ZIP_FILER ZIP Files (*.ZIP)|*.zip|All Files (*.*)|*.*
+DLG_OPEN_CERT Select the Certificate File
+DLG_OPEN_KEY Select the Private Key File
+DLG_OPEN_KEY_WITH_CERT Select the Corresponding Private Key file
+DLG_OPEN_FILE_ERROR Unable to read the specified file: %S.
+DLG_OPEN_FILE_ERROR_W Unable to read the specified file: %s.
+DLG_BAD_P12 The file "%S" is not a valid PKCS#12 certificate file.
+DLG_BAD_P12_W The file "%s" is not a valid PKCS#12 certificate file.
+DLG_BAD_X509 The file "%S" is not a valid X509 certificate file.
+DLG_BAD_X509_W The file "%s" is not a valid X509 certificate file.
+DLG_BAD_KEY The file "%S" is not a valid RSA private key file.
+DLG_BAD_KEY_W The file "%s" is not a valid RSA private key file.
+DLG_BAD_SIGNATURE The private key does not correctly correspond with the public key contained in the specified certificate. \r\nA private key that corresponds to the certificate public key is required.
+DLG_SAVE_CERT Specify a File Name by Which to Save the Certificate
+DLG_SAVE_KEY Specify a File Name by Which to Save the Private Key
+DLG_SAVE_P12 Specify a File Name by Which to Save the Certificate and Private Key
+DLG_SAVE_FILE Specify a File Name for Saving
+DLG_SAVE_OPENVPN_CONFIG Specify a File Name to Save the ZIP File Contains OpenVPN Settings
+DLG_CERT_SAVE_OK The certificate was saved successfully.
+DLG_CERT_SAVE_ERROR Unable to save certificate.
+DLG_KEY_SAVE_OK The private key was saved successfully.
+DLG_KEY_SAVE_ERROR Unable to save private key.
+DLG_KEY_PAIR_SAVE_OK The certificate and private key were saved successfully.
+DLG_KEY_PAIR_SAVE_ERROR Unable to save the certificate and private key.
+DLG_REBOOT_INFO The computer will restart after %u seconds.
+DLG_REBOOT_INFO_2 Restarting the computer.
+DLG_REBOOT_ERROR Failed to restart the computer. \r\n\r\nPlease manually restart the computer now.
+DLG_SAVE_CONFIG Specify a File Name for Saving the Configuration
+DLG_OPEN_CONFIG Specify the Configuration File to Import
+DLG_STRING_DEFTITLE String Input
+DLG_STRING_DEFINFO Enter strings.
+DLG_ABOUT_LEGAL Legal Notices
+DLG_UPDATE_DATE \ (Released on %S)
+DLG_UPDATE_HINT Press OK to view the information of the latest update on the web browser.\r\n\r\nYou have to download and install updates manually. If you want to update software on the other computer you have to log in to the computer by Remote Desktop or SSH to perform the download and update.
+
+
+
+# Concerning competing processes
+BAD_PROCESS_TITLE Warning concerning %S
+BAD_PROCESS_MESSAGE It is possible that the software "%S" is running on this computer, which could cause problems. \r\n\r\nThere is a possibility that problems in "%S" will cause instability in VPN communication and errors. \r\n\r\nIf, by using VPN together with the software "%S" VPN becomes unstable, either stop or uninstall "%S". (Note that in some cases, because of the nature of the software, there are cases where even if you stop the software the problems will still remain on the computer.) \r\n
+
+
+# Concerning hardware tokens
+SEC_SMART_CARD Smart Card
+SEC_USB_TOKEN USB Token
+SEC_INIT_MSG_1 Insert the following smart card into the smart card reader and enter the PIN code.
+SEC_INIT_MSG_2 Connect the following USB token hardware to the computer's USB port and enter the PIN code.
+SEC_OPENING Opening Device...
+SEC_CLOSING Closing Device...
+SEC_OPEN_SESSION Opening Secure Session...
+SEC_CLOSE_SESSION Closing Secure Session...
+SEC_LOGIN Logging in to Token...
+SEC_LOGOUT Logging out from Token...
+SEC_INIT_BATCH Starting Batch Process...
+SEC_READ_DATA Reading Data...
+SEC_WRITE_DATA Writing Data...
+SEC_READ_CERT Reading Certificate...
+SEC_WRITE_CERT Writing Certificate...
+SEC_DELETE Deleting Object...
+SEC_SIGN Processing Digital Signature by Private Key...
+SEC_WRITE_KEY Writing Private Key...
+SEC_ENUM Enumerating Object...
+SEC_FINISHED The operation is complete.
+SEC_ERROR_INVALID_ID The specified security device (device %u) is invalid.
+SEC_ERROR_OPEN_DEVICE Unable to open the device %S. Make sure the device is connected to the computer.
+SEC_ERROR_OPEN_DEVICEEX Unable to open the device %S. Make sure the device is connected to the computer. \r\n\r\nIf using public key infrastructure (PKI) with special client software, it is necessary to select the smart card device in PKI Utility from the Start menu beforehand.
+SEC_ERROR_OPEN_SESSION Unable to start security session in device: %S. Make sure the correct device is selected.
+SEC_ERROR_LOGIN The entered PIN code is incorrect.
+SEC_ERROR_NOT_FOUND_1 The specified object does not exist in smart card. Make sure the correct smart card is inserted.
+SEC_ERROR_NOT_FOUND_2 The specified object does not exist in USB token hardware. Make sure the correct USB token hardware is connected.
+SEC_ERROR_SIGN_1 Either private key does not exist in smart card or digital signature operation failed. Make sure the correct smart card is inserted.
+SEC_ERROR_SIGN_2 Either private key does not exist in USB token hardware or digital signature operation failed. Make sure the correct USB token hardware is connected.
+SEC_ERROR_WRITE_1 Unable to write object to smart card. It is possible there is insufficient free memory available on smart card.
+SEC_ERROR_WRITE_2 Unable to write object to USB token hardware. It is possible there is insufficient free memory available on the USB token.
+SEC_ERROR_ENUM Enumeration of object stored in token failed.
+SEC_ERROR_DELETE Deletion of specified object failed. It is possible the specified object does not exist in the memory.
+SEC_COLUMN1 Device Name
+SEC_COLUMN2 Type
+SEC_COLUMN3 Manufacturer
+SEC_COLUMN4 DLL Name
+SEC_INVALID_ID The specified smart card device does not exist. Select the smart card type again.
+SEC_MGR_COLUMN1 Name
+SEC_MGR_COLUMN2 Type
+SEC_MGR_COLUMN3 Private
+SEC_TYPE_DATA Data
+SEC_TYPE_CERT Certificate
+SEC_TYPE_KEY Private Key
+SEC_TYPE_PUB Public Key
+SEC_YES Yes
+SEC_NO No
+SEC_NONE None
+SEC_IMPORT_DATA Select the data you want to import.
+SEC_IMPORT_CERT Select the certificate you want to import.
+SEC_IMPORT_KEY Select the private key you want to import.
+SEC_READ_FAILED Reading from specified file failed.
+SEC_DATA_TOO_BIG The specified data size is too big. Data larger than %u bytes cannot be written to the smart card.
+SEC_OBJECT_NAME_TITLE Name of object to insert
+SEC_OBJECT_NAME_INFO Specify the name of the object to be written to the new smart card. You can specify alphanumeric characters excluding double-byte and special characters for the object name. \r\n\r\nCaution: If there is an object with the same name of the same type already written on the card, that object will be overwritten.
+SEC_DELETE_MSG The selected object will be deleted from the smart card. \r\nIs this what you want to do?
+SEC_OBJECT_IMPORT_OK Object was written to smart card.
+SEC_OBJECT_EXPORT_OK The data read from the smart card was saved.
+SEC_NEW_CERT_IMPORT_OK The newly created certificate was written to the smart card.
+SEC_CURRENT_DEVICE Currently the device %S is selected.
+SEC_CURRENT_NO_DEVICE Select which smart card device to use.
+SEC_NO_SECURE_DEVICE A SoftEther VPN-compatible smart card or hardware security token device is not installed on the system. \r\n\r\nTo use a smart card or hardware token using SoftEther VPN it is necessary to install a PKCS#11-compatible device driver on Windows. In addition, it is necessary that SoftEther VPN supports the device type. \r\n\r\nMake sure a system-compatible device driver has been installed. \r\nRefer to the SoftEther VPN Project website for the list of SoftEther VPN-compatible devices. Also, it may be possible to increase the compatible devices by updating to the most recent software version.
+SEC_PIN_DEVICE_OPEN_ERR Unable to connect the device "%S". Make sure the hardware is correctly connected.
+SEC_PIN_CURRENT_BAD Current PIN code is incorrect.
+SEC_PIN_CHANGE_FAILED Changing of PIN code failed.
+SEC_PIN_OK The PIN code was changed.
+
+
+# TCP Connecion Dialog
+CONNECTDLG_CAPTION Connecting
+CONNECTDLG_MESSAGE Connecting to the server "%S" (TCP port: %u)...
+CONNECTDLG_CANCELING Aborting the connection. Please wait...
+
+
+# NIC Info Dialog
+NICINFO_1 Connected to the VPN Server.
+NICINFO_1_1 Requesting an IP address to the DHCP server in the VPN...
+NICINFO_1_2 Determining the IP address to use in the VPN...
+
+NICINFO_2 The VPN Connection is Established.
+NICINFO_2_1 Your assigned IP address is %S.
+
+NICINFO_3 The VPN Connection is Established.
+NICINFO_3_1 Your IP address %S is ready to use.
+
+
+# Concerning password input dialogs during login
+PW_RETRYCOUNT Automatic reconnection will be made after %u seconds with no input.
+PW_LOGIN_DLG_TITLE Login
+PW_TYPE_0 Anonymous Authentication
+PW_TYPE_1 Standard Password Authentication
+PW_TYPE_2 RADIUS or NT Domain Authentication
+PW_TYPE_3 Client Certificate Authentication
+PW_TYPE_4 Smart Card Authentication
+
+PW_MSG_PROXY User authentication failed on the proxy server %S. Re-enter the correct user name and password.
+PW_TYPE_PROXY Proxy Server Authentication
+
+
+# Concerning VPN connection status
+STATUS_1 Initializing...
+STATUS_2 Connecting to VPN Server "%S" via Proxy Server %S...
+STATUS_3 Authenticating User on Proxy Server %S...
+STATUS_4 Connecting to VPN Server "%S"...
+STATUS_5 Verifying Server Certificate...
+STATUS_6 Authenticating User...
+STATUS_7 Establishing VPN Session...
+STATUS_8 Connecting to VPN Server on Cluster...
+STATUS_9 VPN Session has been established.
+
+
+# Concerning certificate dialogs
+CERT_NOT_FOUND Unable to find the certificate of the certificate authority who issued this certificate on the list of trusted certificates.
+CERT_ROOT This certificate is a root certificate (self-signed certificate).
+CERT_LV_C1 Field
+CERT_LV_C2 Value
+CERT_SERIAL Serial Number
+CERT_ISSUER Issuer
+CERT_SUBJECT Subject
+CERT_NOT_BEFORE Issued at
+CERT_NOT_AFTER Expires at
+CERT_BITS Bits
+CERT_PUBLIC_KEY Public Key
+CERT_DIGEST_MD5 Digest (MD5)
+CERT_DIGEST_SHA1 Digest (SHA-1)
+CERT_NO_SERIAL There is no serial number
+CERT_BITS_FORMAT %u bits
+
+
+# Concerning certificate confirmation dialogs
+CC_DANGEROUS_MSG The server certificate that was saved on the previous VPN connection to this server (%S) does not match the current server certificate provided by the server. \r\n\r\nDigest Value (MD5) of Previous: %S\r\nDigest Value (SHA1) of Previous: %S\r\n\r\nDigest Value (MD5) of Current: %S\r\nDigest Value (SHA1) of Current: %S\r\n\r\nIt is possible the server administrator changed the certificate on the VPN Server side. However, it is also possible a man-in-the-middle attack such as spoofing is occurring. \r\nIt is strongly recommended that you ask for clarification from the administrator of VPN Server you want to connect to.
+CC_WARNING_MSG Do you want the certificate of the VPN Server you are currently connecting to be automatically trusted next time you connect to %s?\r\n\r\nDigest Value (SHA1): %S\r\nDigest Value (MD5): %S\r\n\r\nIf there is doubt regarding the authenticity of this server's certificate, contact the server's owner, by a sure and safe method, and quote the above digest value to confirm the facts. \r\n\r\nClick Yes to automatically trust this certificate if this server provides the same certificate next time you connect to it. \r\nClick No to trust the certificate for this time only and to display this warning again next time you connect to this server. \r\nClick Cancel to return to the Security Warnings window. \r\n\r\nNote: This setting can be changed on an account-by-account basis. You can make this setting in Account Properties of VPN Client Manager.
+
+
+# Errors about Windows Versions
+WINVER_TITLE Warning about Windows versions
+WINVER_ERROR_FORMAT The version and Service Pack of Windows on %s is "%S".\r\n\r\nThe latest supported version and Service Pack of Windows by %s is as follows:\r\n%S\r\nBecause the version of Windows on %s is newer than the version of Windows which %s supports, unexpected troubles or compatible issues might occur.\r\nIn order to avoid problems, it is recommended to obtain and install the latest update of %s.\r\n(It is possible to continue using the current version without updates but that is not recommended.)\r\n\r\nIf you are the administrator, you can download the latest update-patch of %s from the web site http://selinks.org/?se for free.\r\n\r\nIf you are not the administrator you should notify the VPN Server's administrator of this message.\r\n\r\n----- MSG%04u%02u -----\r\n\r\n
+WINVER_ERROR_VPNSERVER the VPN Server on the destination computer
+WINVER_ERROR_VPNBRIDGE the VPN Bridge on the destination computer
+WINVER_ERROR_VPNCLIENT the VPN Client on this local computer
+WINVER_ERROR_PC_LOCAL this local computer
+WINVER_ERROR_PC_REMOTE the remote server
+
+
+# Warning for Open-source Version
+OSS_MSG Welcome to the SoftEther VPN Server Academic Version!\r\n\r\n\r\nThis VPN Server is open-source free software developed as academic research at University of Tsukuba, Japan, and distributed from the SoftEther VPN Project (http://www.softether.org/), for free of charge for the public interests.\r\n\r\nSoftEther VPN software is distributed to public as a part of the joint-research contract between University of Tsukuba and SoftEther VPN Project. SoftEther VPN software is developed and published for JUST AN ACADEMIC RESEARCH PURPOSE. Therefore no support service are provided about SoftEther VPN software even if it contains bugs or vulnerabilities. A user will be liable for the result of use SoftEther VPN. The developers and publishers of SoftEther VPN will never be liable for either any consequences or damages.\r\n\r\nEnjoy using VPN with SoftEther VPN Server.\r\n\r\nFor more details of SoftEther VPN, visit http://www.softether.org/.\r\n\r\n
+
+
+# Virtual HUB Admin Options
+HUB_AO_CLICK Select an item to view the description here.
+HUB_AO_UNKNOWN The description of the item was not found. Refer to the documents, or speculate the meaning and purpose of the item from the name of the item.
+HUB_AO_allow_hub_admin_change_option This is a special item. If you enable (set to 1) this option, then not only the VPN Server's global administrator but also the Virtual Hub's administrator will be granted to modify the Virtual Hub Admin Options by himself.
+HUB_AO_deny_hub_admin_change_ext_option If you enable (set to 1) this option, the Virtual Hub's administrator will be forbidden to modify any values on the Virtual Hub Extended Options, then only the VPN Server's global administrator can modify them.
+HUB_AO_no_delay_jitter_packet_loss If you set this option to non-zero value, then all parameters of delay, jitter and packet-loss on the access-list entry will be ignored even if these parameters are set when the administrator adds a new access list entry. Therefore, delay, jitter and packet-loss generating function will be virtually disabled. Because the delay generating function sometimes make a high volume of load on the CPU and RAM, a Virtual Hub which is shared by several users should have this option enabled.
+HUB_AO_max_users If you set this option to non-zero value, the maximum number of user objects registered on the Virtual Hub will be limited to this value, then greater number of user objects than this value cannot be added.
+HUB_AO_max_multilogins_per_user If you set this option to non-zero value, the maximum number of VPN Sessions per an individual user object will be limited to this value, then greater number of VPN Sessions of individual user object than this value cannot be established.
+HUB_AO_max_groups If you set this option to non-zero value, then the maximum number of group objects on the Virtual Hub will be limited to this value and any more groups will not be allowed to be registered.
+HUB_AO_max_accesslists If you set this option to non-zero value, then the maximum number of access list entries on the Virtual Hub will be limited to this value and any more entries will not be allowed to be registered.
+HUB_AO_max_sessions_client_bridge_apply Only when this value is set to non-zero value, the values max_sessions_client and max_sessions_bridge will be applied.
+HUB_AO_max_sessions If you set this option to non-zero value, then the maximum number of VPN Sessions will be limited to this value.
+HUB_AO_max_sessions_client If you set this option to non-zero value, then the maximum number of VPN Client sessions will be limited to this value. No more VPN Client sessions will be allowed to establish. This option is valid only when the max_sessions_client_bridge_apply option is set to non-zero value.
+HUB_AO_max_sessions_bridge If you set this option to non-zero value, then the maximum number of VPN Bridge sessions will be limited to this value. No more VPN Bridge sessions will be allowed to establish. This option is valid only when the max_sessions_client_bridge_apply option is set to non-zero value.
+HUB_AO_max_bitrates_download If you set this option to non-zero value, then all VPN Sessions on the Virtual Hub will be mandated to have a security policy setting which the "Download Bandwidth" value is set to this value. It will limit the downloading traffic speed of each VPN Session. For example, if this value is set to 1000000, then a downloading bandwidth of each VPN Session on the Virtual Hub will be limited to 1Mbps.
+HUB_AO_max_bitrates_upload If you set this option to non-zero value, then all VPN Sessions on the Virtual Hub will be mandated to have a security policy setting which the "Download Bandwidth" value is set to this value. It will limit the uploading traffic speed of each VPN Session. For example, if this value is set to 1000000, then a uploading bandwidth of each VPN Session on the Virtual Hub will be limited to 1Mbps.
+HUB_AO_deny_empty_password If you set this option to non-zero value, no user objects will be able to have an empty password. A user who has an empty password will be forbidden to connect a VPN Session. (Exception: a VPN connection from localhost will be permitted even if the password is empty.)
+HUB_AO_deny_bridge If you set this option to non-zero value, then any VPN Sessions in Bridge Mode will not be granted to establish, regardless of the setting of existing security policy of the user. No one will be able to connect to the Virtual Hub for bridging purpose.
+HUB_AO_deny_routing If you set this option to non-zero value, then any VPN Sessions in Routing Mode will not be granted to establish, regardless of the setting of existing security policy of the user. No one will be able to connect to the Virtual Hub for routing purpose.
+HUB_AO_deny_qos If you set this option to non-zero value, then every VPN Sessions will be enforced to disable the QoS function regardless of the setting of existing security policy of the user.
+HUB_AO_deny_change_user_password If you set this option to non-zero value, then any users on the Virtual Hub will be forbidden to change its password by VPN Client's password-changing function.
+HUB_AO_no_change_users If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to add, edit or remove a user.
+HUB_AO_no_change_groups If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to add, edit or remove a group.
+HUB_AO_no_securenat If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to enable or disable the SecureNAT function.
+HUB_AO_no_securenat_enablenat If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to enable or disable the Virtual NAT function in the SecureNAT function.
+HUB_AO_no_securenat_enabledhcp If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to enable or disable the Virtual DHCP Server function in the SecureNAT function.
+HUB_AO_no_cascade If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to add, edit, remove or change the online status of a cascade connection.
+HUB_AO_no_online If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the offline Virtual Hub to the online state.
+HUB_AO_no_offline If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the online Virtual Hub to the offline state.
+HUB_AO_no_change_log_config If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the settings of logging function.
+HUB_AO_no_disconnect_session If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to disconnect a specific VPN Session.
+HUB_AO_no_delete_iptable If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to delete a specific IP address entry from the IP address table database.
+HUB_AO_no_delete_mactable If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to delete a specific MAC address entry from the MAC address table database.
+HUB_AO_no_enum_session If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to enumerate the sessions on the Virtual Hub.
+HUB_AO_no_query_session If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to specify a session and get the information of the session.
+HUB_AO_no_change_admin_password If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the administrator's password of the Virtual Hub.
+HUB_AO_no_change_log_switch_type If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the Log Switching settings on the logging function settings of the Virtual Hub.
+HUB_AO_no_change_access_list If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to modify the access list of the Virtual Hub.
+HUB_AO_no_change_access_control_list If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to modify the source IP address limit list of the Virtual Hub.
+HUB_AO_no_change_cert_list If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to modify the trusted certificate authority list of the Virtual Hub.
+HUB_AO_no_change_crl_list If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to modify the certificate revoked list of the Virtual Hub.
+HUB_AO_no_read_log_file If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to enumerate or download the log files of the Virtual Hub remotely.
+HUB_AO_no_change_msg If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to change the message which should be displayed when a VPN Client connects to the Virtual Hub.
+HUB_AO_no_access_list_include_file If you set this option to non-zero value, then the administrator of the Virtual HUB will be forbidden to specify "include:" or "exclude:" instruction as a source or a destination user field on a access list entry of the Virtual Hub.
+
+
+
+# Virtual Hub Extended Options
+HUB_AO_NoAddressPollingIPv4 If you set this option to non-zero value, then the Virtual Hub will not perform the maintenance of the IPv4 address table and the MAC address table on the hub with using sending ARP packets per 5 seconds in order to check keep-alive IPv4 devices. As a result, IPv4 devices might be deleted on the IPv4 address table and MAC address table after a particular period (from 1 to 10 minutes) will be elapsed in the case of no-communication activities via the Virtual Hub, even if it is still alive. This option can eliminate the amount of broadcast packets, however some IPv4-related security policies will not work effectively.
+HUB_AO_NoAddressPollingIPv6 If you set this option to non-zero value, then the Virtual Hub will not perform the maintenance of the IPv6 address table and the MAC address table on the hub with using sending ICMPv6 packets per 5 seconds in order to check keep-alive IPv6 devices. As a result, IPv6 devices might be deleted on the IPv6 address table and MAC address table after a particular period (from 1 to 10 minutes) will be elapsed in the case of no-communication activities via the Virtual Hub, even if it is still alive. This option can eliminate the amount of broadcast packets, however some IPv6-related security policies will not work effectively.
+HUB_AO_NoIpTable If you set this option to non-zero value, then the Virtual Hub will not construct and maintain the internal IP address table. This option can eliminate the amount of CPU and RAM usages, however some IP-related security policies will not work effectively.
+HUB_AO_NoMacAddressLog If you set this option to non-zero value, then any logs which indicate the registration of a new MAC address to the MAC address table on the Virtual Hub will not be logged to the security log.
+HUB_AO_ManageOnlyPrivateIP If you set this option to non-zero value, then the IPv4 address table of the Virtual Hub will contain only private IPv4 addresses. In this context, the private IPv4 addresses are: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 and 169.254.0.0/16. Any other IPv4 addresses will not added on the table.
+HUB_AO_ManageOnlyLocalUnicastIPv6 If you set this option to non-zero value, then the IPv6 address table of the Virtual Hub will contain only local unicast IPv6 addresses. In this context, the private IPv6 addresses are: fe80::/10. Any other IPv6 addresses will not added on the table.
+HUB_AO_DisableIPParsing If you set this option to non-zero value, then the Virtual Hub will disable the internal parsing function of IP headers in all Ethernet packets. This option can eliminate the amount of CPU and RAM usages, however the Vitual Hub will not perform building and maintenance of the IP address table internally, and some IP-related security policies will not work effectively.
+HUB_AO_YieldAfterStorePacket If you set this option to non-zero value, then the Virtual Hub sets the CPU to idle state after store-forward processing of a packet. This might results good effects to make the delay of packets shorter, however the counts of thread context switch will be increased and the performance might decline.
+HUB_AO_FilterPPPoE If you set this option to non-zero value, then the Virtual Hub discards all PPPoE (PPP over Ethernet) packets. It is convenient to split each site's PPPoE segment when making a bridge between two or more local area networks.
+HUB_AO_FilterOSPF If you set this option to non-zero value, then the Virtual Hub discards all OSPF (Open Shortest Path First) packets.
+HUB_AO_FilterIPv4 If you set this option to non-zero value, then the Virtual Hub discards all IPv4 and ARP packets.
+HUB_AO_FilterIPv6 If you set this option to non-zero value, then the Virtual Hub discards all IPv6 packets.
+HUB_AO_FilterNonIP If you set this option to non-zero value, then the Virtual Hub discards all non-IP packets (non-IPv4, ARP or IPv6 packets). Incidentally, any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets.
+HUB_AO_FilterBPDU If you set this option to non-zero value, then the Virtual Hub discards all BPDU (Bridge Protocol Data Unit) packets.
+HUB_AO_NoIPv6DefaultRouterInRAWhenIPv6 If you set this option to non-zero value, then all VPN Sessions on the Virtual Hub will have the enabled "No Default-Router on IPv6 RA (physical IPv6)" security policy. When the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router.
+HUB_AO_NoLookBPDUBridgeId If you set this option to non-zero value, then the Virtual Hub will ignore the source MAC field in a BPDU (Bridge Protocol Data Unit) packet. This value is much advanced. Do not modify it unless you are very ultra special expert of computer networking.
+HUB_AO_NoManageVlanId If you set this option to non-zero value, then the Virtual Hub will not use VLAN ID on the MAC address table. Any VLAN ID in tagged-VLAN packets will be ignored.
+HUB_AO_VlanTypeId Specify the Ethernet Type ID (TPID) of VLAN tags in decimal. The default value is 33024 (0x8100 in hex). This value is much advanced. Do not modify it unless you are very ultra special expert of computer networking.
+HUB_AO_FixForDLinkBPDU If you set this option to non-zero value, then the FixForDLinkBPDU option will be enabled. This value is much advanced. Do not modify it unless you are very ultra special expert of computer networking.
+HUB_AO_NoIPv4PacketLog If you set this option to non-zero value, then IPv4 packets via the Virtual Hub will not be logged.
+HUB_AO_NoIPv6PacketLog If you set this option to non-zero value, then IPv6 packets via the Virtual Hub will not be logged.
+HUB_AO_NoSpinLockForPacketDelay If you set this option to non-zero value, then the VPN Server will not use spin-lock mechanisms to simulate the delay of packets when the packet-delay generating function is applied to the packet. Instead, the timer interrupt by the operating system will be adopted. It will reduce the CPU time, however the resolution of generating delays will deteriorate.
+HUB_AO_BroadcastStormDetectionThreshold Specify the threshold to detect the broadcast storm per a second. When the number of broadcast packets from a particular VPN Session exceeded this threshold, packets will be regarded as broadcast storm and become subjects to be filtered. The default value (zero-value) is 32.
+HUB_AO_ClientMinimumRequiredBuild If you set this option to non-zero value, then the Virtual Hub will deny any access from VPN Client which has less build number than this value.
+HUB_AO_RequiredClientId If you set this option to non-zero value, then the Virtual Hub will deny any access from VPN Client which doesn't have the embedded "Client ID" value in the software.
+HUB_AO_AdjustTcpMssValue If you set this option to non-zero value, then the Virtual Hub will adjust MSS (Max Segment Size) values of headers of all TCP/IP packets not to exceed this value.
+HUB_AO_DisableAdjustTcpMss If you set this option to non-zero value, then any MSS (Max Segment Size) options on the Virtual Hub will be disabled. Even if the AdjustTcpMssValue option is specified, or a VPN Session is made by IPsec / L2TP / EtherIP / L2TPv3 Server Function, the adjustment of MSS will be disabled.
+HUB_AO_NoDhcpPacketLogOutsideHub If you set this option to non-zero value, then the Virtual Hub will not record non-related DHCP packets to the packet log. "Non-related DHCP packets" are DHCP packets which are not bound to any VPN Session on the Virtual Hub.
+HUB_AO_DisableHttpParsing If you set this option to non-zero value, then the Virtual Hub will not perform parsing HTTP headers in all HTTP packets. It will reduce the usage of CPU and RAM, however the HTTP access logs will not be recorded.
+HUB_AO_DisableUdpAcceleration If you set this option to non-zero value, then all UDP Acceleration Function will be disabled on the all VPN Sessions of the Virtual Hub.
+HUB_AO_DisableUdpFilterForLocalBridgeNic If you set this option to non-zero value, then the Virtual Hub disables the trouble-preventing filtering function to filter DHCP packets which might causes of network unstable. By default, a local bridge interface sometimes try to acquire an IP address from remote-side DHCP server, however such a behavior should infinite loop in the routing table. The filtering function can avoid such problems. This option can disable the filtering function.
+HUB_AO_ApplyIPv4AccessListOnArpPacket If you set this option to non-zero value, then the IPv4 access list entries will be applied on not only IPv4 packets but also ARP packets. It is convenient to filter unnecessary ARP packets which might cause troubles.
+HUB_AO_RemoveDefGwOnDhcpForLocalhost If you set this option to non-zero value, when a VPN Client on the localhost connects to the Virtual Hub and try to acquire an IP address from the DHCP Server in the segment of the Virtual Hub, corresponding DHCP reply packets will be discarded. It can prevent unexpected infinite loop of packets routing.
+HUB_AO_SecureNAT_MaxTcpSessionsPerIp If you set this option to non-zero value, then the number of TCP connections (which is not SYN_SENT) per IP state will be limited to this value.
+HUB_AO_SecureNAT_MaxTcpSynSentPerIp If you set this option to non-zero value, then the number of TCP connections (which is SYN_SENT) per IP state will be limited to this value.
+HUB_AO_SecureNAT_MaxUdpSessionsPerIp If you set this option to non-zero value, then the number of UDP sessions per IP state will be limited to this value.
+HUB_AO_SecureNAT_MaxDnsSessionsPerIp If you set this option to non-zero value, then the number of DNS sessions per IP which is not SYN_SENT state will be limited to this value.
+HUB_AO_SecureNAT_MaxIcmpSessionsPerIp If you set this option to non-zero value, then the number of ICMP sessions per IP which is not SYN_SENT state will be limited to this value.
+HUB_AO_AccessListIncludeFileCacheLifetime Specify a period in seconds to hold the cache of external user-list files which is for an access list entry which has "include:" or "exclude:" formats as its username.
+HUB_AO_DisableKernelModeSecureNAT If you set this option to non-zero value, then the Kernel-mode NAT function on the SecureNAT function will be disabled. Kernel-mode NAT is a function to accelerate the performance of the Virtual NAT function on SecureNAT. Kernel-mode NAT can work only when the VPN Server process is running with system privileges (i.e. root, SYSTEM or Administrators contexts.). If the Kernel-mode NAT causes something wrong operations, use this option to disable it.
+HUB_AO_DisableUserModeSecureNAT If you set this option to non-zero value, then the User-mode NAT function on the SecureNAT function will be disabled. User-mode NAT is a function to make the NAT possible to run as normal-user privileges.
+HUB_AO_DisableCheckMacOnLocalBridge If you set this option to non-zero value, then the MAC address duplication check will be disabled on the Local Bridge function. Some network adapters has a problem that reflects outgoing packets towards the Virtual Hub. A Virtual HUB detects such duplications automatically, and discards them. Enable this flag to disable the detection and discarding.
+HUB_AO_DisableCorrectIpOffloadChecksum If you set this option to non-zero value, then the checking and correction of IP check-sum value on the Local Bridge function. Some network adapters, which have IP, TCP or UDP header check-sum offloading engines, transmit packets with incomplete check-sum values. Such packets cannot be treated correctly by receiver-side. So the Local Bridge detects such packets and corrects its check-sum fields. Enable this flag to disable such correction.
+HUB_AO_BroadcastLimiterStrictMode If you set this option to non-zero value, then the broadcast-storm detection algorithm will compare either source or destination IP address of each packet. If any of the two fields matches, the packet will be recorded on the short-term history of broadcast-storm detection state machine.
+
+
+# Concerning failed connection dialogs
+ERRDLG_ERRMSG Error (Error Code %u):\r\n%s\r\n
+ERRDLG_RETRYCOUNT An automatic reconnection will be made after %u seconds...
+ERRDLG_INFORMATION Click Retry to start connecting again.
+ERRDLG_RETRY_INFO_1 Do you wish to retry? (%u retries / %u total retries)
+ERRDLG_RETRY_INFO_2 Do you wish to retry? (%u retries / total infinite retries)
+ERRDLG_DISCONNECTED_MSG Connection to VPN Server "%S" was disconnected.
+ERRDLG_DEVICE_ERROR The connection with the VPN Server was disconnected because the Virtual Network Adapter (device name: %S) was stopped. \r\n\r\nError code %u: %s
+
+
+# Concerning protocols
+PROTO_DIRECT_TCP Direct TCP/IP Connection
+PROTO_HTTP_PROXY Connection via HTTP Proxy
+PROTO_SOCKS_PROXY Connection via SOCKS Proxy
+PROTO_SSH Connection via SSH Server
+PROTO_UNKNOWN Unknown Protocol
+
+
+# Concerning caps
+# (Control characters)
+CAPS_YES Yes
+CAPS_NO No
+# (Title)
+CT_i_max_packet_size Maximum Ethernet Packet Size
+CT_i_max_hubs Maximum Virtual Hubs
+CT_i_max_user_creation Maximum Users on Entire VPN Server
+CT_i_max_sessions Maximum Total Sessions
+CT_i_max_clients Maximum Client Sessions
+CT_i_max_bridges Maximum Bridge Sessions
+CT_i_max_users_per_hub Maximum Users per Virtual Hub
+CT_i_max_groups_per_hub Maximum Groups per Virtual Hub
+CT_i_max_access_lists Maximum Access Lists per Virtual Hub
+CT_i_max_mac_tables Maximum MAC Address Entries per Virtual Hub
+CT_i_max_ip_tables Maximum IP Address Entries per Virtual Hub
+CT_i_max_secnat_tables Maximum SecureNAT Entries per Virtual Hub
+CT_i_max_l3_sw Maximum Virtual Layer 3 Switches
+CT_i_max_l3_if Maximum Virtual Interfaces per Layer 3 Switch
+CT_i_max_l3_table Maximum Routing Tables per Layer 3 Switch
+CT_b_bridge Works as VPN Bridge Software
+CT_b_standalone Standalone Mode
+CT_b_cluster_controller Cluster Controller Mode
+CT_b_cluster_member Cluster Member Mode
+CT_b_vpn_client_connect Accepting Connection from VPN Client / Bridge
+CT_b_local_bridge Local Bridge is Supported
+CT_b_must_install_pcap Packet Capture Driver is Not Installed
+CT_b_tap_supported Tun/Tap Device is Supported (only in Linux)
+CT_b_support_config_hub Changing Virtual Hub Settings is Supported
+CT_b_support_securenat SecureNAT is Supported
+CT_b_virtual_nat_disabled Virtual NAT is Disabled (only DHCP Enabled)
+CT_b_support_cascade Cascade Connection is Supported
+CT_b_support_cascade_cert Server Authentication for Cascade Connection is Supported
+CT_b_support_config_log Changing Settings for Saving Log is Supported
+CT_b_support_autodelete Automatic Deletion of Log Files is Supported
+CT_b_support_radius External Authentication Server is Supported
+CT_b_support_config_rw Remote Reading and Writing of Config File is Supported
+CT_b_support_hub_admin_option Virtual Hub Administration Options is Supported
+CT_b_support_cascade_client_cert Client Certificates for Cascade Connection is Supported
+CT_b_support_hide_hub Virtual Hub Enumeration Setting is Supported
+CT_b_support_cluster_admin Integrated Administration for All Cluster Nodes is Supported
+CT_b_support_cluster Operation as Part of a Cluster is Supported
+CT_b_support_cluster_controller Operating as a Cluster Controller
+CT_b_support_layer3 The Virtual Layer 3 Switch is Supported
+CT_b_support_crl Virtual Hub-Specific Certificate Revocation Lists is Supported
+CT_b_support_ac Virtual Hub-Specific Source IP Address Limit Lists is Supported
+CT_b_support_read_log Downloading of Log Files is Supported
+CT_b_support_rename_cascade Renaming of Cascade Connection is Supported
+CT_b_support_license Management of Licenses is Supported
+CT_b_support_limit_multilogin Limits for Multiple Login by Same User is Supported
+CT_b_support_qos VoIP / QoS Functions is Supported
+CT_b_support_syslog Syslog Sending Functions is Supported
+CT_b_cluster_hub_type_fixed The Virtual Hub Types in a Cluster are Fixed
+CT_b_beta_version Beta Version (Pre-release build)
+CT_b_support_check_mac Specifing MAC Address in Access Lists is Supported
+CT_b_support_check_tcp_state Checking TCP Connection State Filtering is Supported
+CT_b_support_network_connection_name Getting Network Friendly Name is Supported
+
+CT_b_support_radius_retry_interval_and_several_servers Retry Interval and Multi server is Supported in RADIUS Auth
+CT_b_support_vlan Tagged VLAN ID is Supported in MAC Address Table
+CT_b_support_hub_ext_options Virtual Hub Extended Option is Supported
+CT_b_support_policy_ver_3 Security Policy version 3 is Supported
+CT_b_support_ipv6_acl IPv6 Access List is Supported
+CT_b_support_ex_acl Delay, Jitter and Packet Loss is Supported in Access List
+CT_b_support_acl_group Conditioning by Group name is Supported in Access List
+CT_b_support_ipv6_ac IPv6 IP Access Control Lists is Supported
+CT_b_support_eth_vlan Tagged VLAN Packet Transparency Support tool is Supported
+CT_b_support_msg Message of Today function is Supported
+CT_b_vpn3 Internal Version 3.0 functions are Supported
+CT_b_vpn4 Internal Version 4.0 functions are Supported
+CT_b_support_ipsec IPsec / L2TP / EtherIP / L2TPv3 Server Functions are Supported
+CT_b_support_sstp MS-SSTP VPN Server Function is Supported
+CT_b_support_udp_acceleration UDP Acceleration Function is Supported
+CT_b_support_openvpn OpenVPN Server Function is Supported
+CT_b_support_ddns Dynamic DNS Client Function is Supported
+CT_b_support_ddns_proxy DDNS via Proxy Server is Supported
+CT_b_support_special_listener VPN over ICMP and VPN over DNS is Supported
+CT_b_support_redirect_url_acl HTTP URL Redirection in Access List is Supported
+CT_b_is_in_vm Running on VM (Virtual Machine)
+CT_b_support_azure VPN Azure is Supported
+CT_b_support_intel_aes Intel CPU AES Acceleration (AES-NI) is Active
+CT_b_using_selow_driver SoftEther Lightweight Kernel-mode Ethernet Driver is Active
+CT_b_support_vgs VPN Gate Service Server Functions are Supported
+CT_b_support_vgs_in_client VPN Gate Service Server Functions (VPN Client integrated)
+CT_b_is_softether Either Free or Open-Source Version of SoftEther VPN
+
+# Concerning policies
+POL_TITLE_STR Policy Name
+POL_VALUE_STR Current Value
+POL_TYPE_BOOL ON / OFF
+POL_TYPE_INT Integer
+POL_BOOL_ENABLE Enabled
+POL_BOOL_DISABLE -
+POL_BOOL_DISABLE_EX -
+POL_INT_ZERO -
+POL_INT_COUNT %u
+POL_INT_SEC %u seconds
+POL_INT_BPS %u bps
+POL_INT_VLAN %u
+
+# Ver 2.0
+POL_0 Allow Access
+POL_EX_0 The users defined this policy have permission to make VPN connection to VPN Server.
+POL_1 Filter DHCP Packets (IPv4)
+POL_EX_1 All IPv4 DHCP packets in sessions defined this policy will be filtered.
+POL_2 Disallow DHCP Server Operation (IPv4)
+POL_EX_2 Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients.
+POL_3 Enforce DHCP Allocated IP Addresses (IPv4)
+POL_EX_3 Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side.
+POL_4 Deny Bridge Operation
+POL_EX_4 Bridge-mode connections are denied for user sessions that have this policy setting. Even in cases when the Ethernet Bridge is configured in the client side, communication will not be possible.
+POL_5 Deny Routing Operation (IPv4)
+POL_EX_5 IPv4 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible.
+POL_6 Deny MAC Addresses Duplication
+POL_EX_6 The use of duplicating MAC addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting.
+POL_7 Deny IP Address Duplication (IPv4)
+POL_EX_7 The use of duplicating IPv4 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting.
+POL_8 Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts
+POL_EX_8 The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting.
+POL_9 Privacy Filter Mode
+POL_EX_9 All direct communication between sessions with the privacy filter mode policy setting will be filtered.
+POL_10 Deny Operation as TCP/IP Server (IPv4)
+POL_EX_10 Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4.
+POL_11 Unlimited Number of Broadcasts
+POL_EX_11 If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting.
+POL_12 Allow Monitoring Mode
+POL_EX_12 Users with this policy setting will be granted to connect to the Virtual Hub in Monitoring Mode. Sessions in Monitoring Mode are able to monitor (tap) all packets flowing through the Virtual Hub.
+POL_13 Maximum Number of TCP Connections
+POL_EX_13 For sessions with this policy setting, this sets the maximum number of physical TCP connections consists in a physical VPN session.
+POL_14 Time-out Period
+POL_EX_14 For sessions with this policy setting, this sets, in seconds, the time-out period to wait before disconnecting a session when communication trouble occurs between the VPN Client / VPN Server.
+POL_15 Maximum Number of MAC Addresses
+POL_EX_15 For sessions with this policy setting, this limits the number of MAC addresses per session.
+POL_16 Maximum Number of IP Addresses (IPv4)
+POL_EX_16 For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session.
+POL_17 Upload Bandwidth
+POL_EX_17 For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub.
+POL_18 Download Bandwidth
+POL_EX_18 For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub.
+POL_19 Deny Changing Password
+POL_EX_19 The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar.
+POL_20 Maximum Number of Multiple Logins
+POL_EX_20 Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. This security policy is only available on VPN Server 3.0 or greater, or VPN Server 2.0 with the multi-login restriction function.
+POL_21 Deny VoIP / QoS Function
+POL_EX_21 Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. This security policy is only available on VPN Server 3.0 or greater, or VPN Server 2.0 with the VoIP / QoS functions.
+
+# Ver 3.0
+POL_22 Filter RS / RA Packets (IPv6)
+POL_EX_22 All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection.
+POL_23 Filter RA Packets (IPv6)
+POL_EX_23 All ICMPv6 packets which the message-type is 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, a malicious users will be unable to spread illegal IPv6 prefix or default gateway advertisements on the network.
+POL_24 Filter DHCP Packets (IPv6)
+POL_EX_24 All IPv6 DHCP packets in sessions defined this policy will be filtered.
+POL_25 Disallow DHCP Server Operation (IPv6)
+POL_EX_25 Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients.
+POL_26 Deny Routing Operation (IPv6)
+POL_EX_26 IPv6 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible.
+POL_27 Deny IP Address Duplication (IPv6)
+POL_EX_27 The use of duplicating IPv6 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting.
+POL_28 Deny Operation as TCP/IP Server (IPv6)
+POL_EX_28 Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6.
+POL_29 Maximum Number of IP Addresses (IPv6)
+POL_EX_29 For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session.
+POL_30 Disallow Password Save in VPN Client
+POL_EX_30 For users with this policy setting, a user will be unable to save the password in VPN Client any longer. The user will be required to input passwords for every time to connect a VPN. This will improve the security. If this policy is enabled, VPN Client Version 2.0 will be denied to access.
+POL_31 VPN Client Automatic Disconnect
+POL_EX_31 For users with this policy setting, a user's VPN session will be disconnected automatically after the specific period will elapse. In this case no automatic re-connection will be performed. This can prevent a lot of inactive VPN Sessions. If this policy is enabled, VPN Client Version 2.0 will be denied to access.
+POL_32 Filter All IPv4 Packets
+POL_EX_32 All IPv4 and ARP packets in sessions defined this policy will be filtered.
+POL_33 Filter All IPv6 Packets
+POL_EX_33 All IPv6 packets in sessions defined this policy will be filtered.
+POL_34 Filter All Non-IP Packets
+POL_EX_34 All non-IP packets in sessions defined this policy will be filtered. "Non-IP packet" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets.
+POL_35 No Default-Router on IPv6 RA
+POL_EX_35 In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router.
+POL_36 No Default-Router on IPv6 RA (physical IPv6)
+POL_EX_36 In all VPN Sessions defines this policy (only when the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6), any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router.
+POL_37 VLAN ID (IEEE802.1Q)
+POL_EX_37 You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing.
+
+
+# Concerning remote connection dialog
+REMOTE_DEF_CAPTION Remote Connection
+REMOTE_DEF_TITLE Specify the computer you want to remotely connect to.
+
+
+# Concerning client notification service
+CN_TITLE SoftEther VPN Client
+
+
+# Concerning Connection Manager
+CM_TITLE SoftEther VPN Client Manager
+CM_PW_LOCALMACHINE Local Computer
+CM_NO_REMOTE The VPN Client service running on %s disallows remote connections.
+CM_CONNECT_FAILED Unable to connect to the VPN Client service operating on %s. \r\nMake sure the VPN Client service has started and is running normally.
+CM_BAD_PASSWORD The password is incorrect. Re-enter password. The password is case-sensitive so be sure to discern between upper and lower case letters.
+CM_NUM_CONN_COUNT %u VPN Sessions
+CM_CONN_NO Not Connected
+CM_PRODUCT_NAME SoftEther VPN Client Build %u
+CM_ACCOUNT_COLUMN_1 VPN Connection Setting Name
+CM_ACCOUNT_COLUMN_2 Status
+CM_ACCOUNT_COLUMN_3 VPN Server Hostname
+CM_ACCOUNT_COLUMN_3_2 Virtual Hub
+CM_ACCOUNT_COLUMN_4 Virtual Network Adapter Name
+CM_VLAN_COLUMN_1 Virtual Network Adapter Name
+CM_VLAN_COLUMN_2 Status
+CM_VLAN_COLUMN_3 MAC Address
+CM_VLAN_COLUMN_4 Version
+CM_ACCOUNT_OFFLINE Offline
+CM_ACCOUNT_ONLINE Connected
+CM_ACCOUNT_CONNECTING Connecting
+CM_VLAN_ENABLED Enabled
+CM_VLAN_DISABLED Disabled
+CM_DELETE_ACCOUNT_MSG This will delete the VPN Connection Setting "%s". Do you want to do this?
+CM_ST_ACCOUNT_NAME VPN Connection Setting Name
+CM_ST_CONNECTED Session Status
+CM_ST_CONNECTED_TRUE Connection Completed (Session Established)
+CM_ST_CONNECTED_FALSE Trying to Connect
+CM_ST_CONNECTING Connection to VPN Server Started
+CM_ST_NEGOTIATION Negotiating
+CM_ST_AUTH Authenticating User
+CM_ST_ESTABLISHED Connection is Established
+CM_ST_RETRY Retrying
+CM_ST_IDLE Idle
+CM_ST_SERVER_NAME Server Name
+CM_ST_SERVER_PORT Port Number
+CM_ST_PORT_TCP TCP Port %u
+CM_ST_SERVER_P_NAME Server Product Name
+CM_ST_SERVER_P_VER Server Version
+CM_ST_SERVER_P_BUILD Server Build
+CM_ST_START_TIME Connection Started at
+CM_ST_FIRST_ESTAB_TIME First Session was Established at
+CM_ST_NONE -
+CM_ST_CURR_ESTAB_TIME Current Session was Established at
+CM_ST_NUM_ESTABLISHED Number of Established Sessions
+CM_ST_NUM_STR %u Times
+CM_ST_HALF_CONNECTION Half Duplex TCP Connection Mode
+CM_ST_HALF_TRUE Yes (Half Duplex Mode)
+CM_ST_HALF_FALSE No (Full Duplex Mode)
+CM_ST_QOS VoIP / QoS Function
+CM_ST_QOS_TRUE Enabled
+CM_ST_QOS_FALSE Disabled
+CM_ST_NUM_TCP Number of TCP Connections
+CM_ST_NUM_TCP_UPLOAD Number of Uplink TCP Connections
+CM_ST_NUM_TCP_DOWNLOAD Number of Downlink TCP Connections
+CM_ST_MAX_TCP Maximum Number of TCP Connections
+CM_ST_VLAN_ID VLAN ID
+CM_ST_NO_VLAN -
+CM_ST_USE_ENCRYPT Encryption
+CM_ST_USE_ENCRYPT_TRUE Enabled (Algorithm: %S)
+CM_ST_USE_ENCRYPT_TRUE2 Enabled
+CM_ST_USE_ENCRYPT_FALSE Disabled (No Encryption)
+CM_ST_USE_COMPRESS Use of Compression
+CM_ST_UDP_ACCEL_ENABLED UDP Acceleration is Supported
+CM_ST_UDP_ACCEL_USING UDP Acceleration is Active
+CM_ST_RUDP TCP over UDP (NAT Traversal)
+CM_ST_UNDERLAY_PROTOCOL Physical Underlay Protocol
+CM_ST_COMPRESS_TRUE Yes (%u %%)
+CM_ST_COMPRESS_FALSE No (No Compression)
+CM_ST_SESSION_NAME Session Name
+CM_ST_CONNECTION_NAME Connection Name
+CM_ST_SESSION_KEY Session Key (160 bit)
+CM_ST_BRIDGE_MODE Bridge / Router Mode
+CM_ST_MONITOR_MODE Monitoring Mode
+CM_ST_YES Yes
+CM_ST_NO No
+CM_ST_SEND_SIZE Outgoing Data Size
+CM_ST_RECV_SIZE Incoming Data Size
+
+CM_ST_SEND_UCAST_NUM Outgoing Unicast Packets
+CM_ST_SEND_UCAST_SIZE Outgoing Unicast Total Size
+CM_ST_SEND_BCAST_NUM Outgoing Broadcast Packets
+CM_ST_SEND_BCAST_SIZE Outgoing Broadcast Total Size
+
+CM_ST_RECV_UCAST_NUM Incoming Unicast Packets
+CM_ST_RECV_UCAST_SIZE Incoming Unicast Total Size
+CM_ST_RECV_BCAST_NUM Incoming Broadcast Packets
+CM_ST_RECV_BCAST_SIZE Incoming Broadcast Total Size
+
+CM_ST_NUM_PACKET_STR %S packets
+CM_ST_SIZE_BYTE_STR %S bytes
+
+CM_NEW_ICON Add VPN Connection
+CM_VGC_ICON VPN Gate Public VPN Relay Servers
+CM_VGC_LINK VPN Gate Academic Web Site
+CM_ST_TITLE Connection Status of %s
+CM_ST_COLUMN_1 Item
+CM_ST_COLUMN_2 Status
+CM_NEW_ACCOUNT_NAME_1 New VPN Connection
+CM_NEW_ACCOUNT_NAME_2 New VPN Connection (%u)
+CM_ACCOUNT_TITLE_1 New VPN Connection Setting Properties
+CM_ACCOUNT_TITLE_2 Properties of %s
+CM_SERVER_CERT_1 &Specify Individual Cert
+CM_SERVER_CERT_2 &Delete Certificate
+CM_CLIENT_CERT_1 Specify Client &Certificate
+CM_CLIENT_CERT_2 Delete &Client Certificate
+CM_CERT_INFO Issued to: %s\r\nIssuer: %s\r\nExpiration: %s
+CM_NO_CERT You must specify a client certificate to be used for user authentication.
+CM_NO_SECURE Specify the client certificate and private key inside the smart card to be used for user authentication.
+CM_CERT_SECURE_INFO Certificate: "%S"\r\nPrivate Key: "%S"
+CM_SELECT_SECURE_DEVICE Select Smart Card
+CM_SELECT_CERT_INCARD Specify Cert and Pri&vate Key
+CM_VIEW_CLIENT_CERT &View Client Certificate
+CM_NO_VLAN Before you can create a new VPN Connection Setting you need to create a Virtual Network Adapter. \r\n\r\nDo you want to create a Virtual Network Adapter?
+CM_NO_VLAN_2 Before connecting to VPN Server you need to create a Virtual Network Adapter. \r\n\r\nDo you want to create a Virtual Network Adapter?
+CM_VLAN_REMOTE_ERROR Unable to create a Virtual Network Adapter from a remote location. \r\n\rStart the VPN Client Manager on the local computer on which the VPN Client service is running and install a Virtual Network Adapter.
+CM_9X_VLAN_INSTALL A new Virtual Network Adapter will now be created. \r\n\r\nAfter a Virtual Network Adapter is created, it is necessary to restart Windows directly afterwards. \r\nWhile the Virtual Network Adapter is being installed, you may be asked to insert the Windows installation CD-ROM. \r\n\r\nClose all currently running applications except the VPN Client Manager, have your Windows installation CD-ROM ready at hand, and click OK. \r\nClicking OK will start the installation of the Virtual Network Adapter. When this is finished, Windows will automatically restart.
+CM_9X_VLAN_ME_MESSAGE A Virtual Network Adapter has been created. After you click OK, the computer will automatically restart. \r\n\r\nAfter the computer restarts, the Install New Device wizard might appear. \r\nIf the wizard does appear, click Next for each screen until the installation is completed.
+CM_9X_VLAN_UNINSTALL To delete a Virtual Network Adapter, delete it from Network Properties. \r\n\r\nDo you want to display the Network Properties window?
+CM_PORT_1 8888 (PX-VPN Port)
+CM_PORT_2 443 (HTTPS Port)
+CM_PORT_3 992 (TELNETS Port)
+CM_PORT_4 5555 (SE-VPN Port)
+CM_RETRY_INTERVAL_ERROR Set a re-connection interval (at least 5 seconds) when VPN connection was disconnected.
+CM_DELETE_CLIENT_CERT This will delete the client certificate that has been set. Do you want to do this?
+CM_DELETE_SERVER_CERT This will delete the server individual certificate that has been set. Do you want to do this?
+CM_SET_STARTUP The VPN Connection Setting "%s" is now set as a startup connection.\r\n\r\nThis account will be connected automatically next time the computer restarts.\r\n(If you are using Windows, the automatic connection will be started in the background mode before a user logs on to Windows.)
+CM_REMOVE_STARTUP Do you wish to delete the startup connection property of VPN Connection Setting "%s"?
+CM_NO_DISCONNECT_SPAN Please set the life of the TCP connection.
+CM_HALF_MSG When using half-duplex mode, set at least 2 for the number of TCP connections.
+CM_TOO_SMALL_INTERVAL Set at least 1 second for the interval to establish a TCP connection.
+CM_DELETE_VLAN This will delete the Virtual Network Adapter "%s". Do you want to do this?
+CM_COPY_NAME_1 Copy of %s
+CM_COPY_NAME_2 Copy (%u) of %s
+CM_IMPORT_NAME_1 %s
+CM_IMPORT_NAME_2 %s (%u)
+CM_CERT_COLUMN_1 Issued to
+CM_CERT_COLUMN_2 Issuer
+CM_CERT_COLUMN_3 Expiration
+CM_CERT_DELETE_MSG Delete this certificate from the list?
+CM_PASSWORD_SET The password was set.
+CM_PASSWORD_REMOVE The password setting was deleted.
+CM_UNDER_CONSTRUCTION Incomplete.
+CM_CURRENT_ACTIVE The settings of VPN Connection Setting "%s" were saved but this VPN Connection Setting is currently online and the new settings will apply in the next connection.
+CM_DISCONNECT_ALL This will disconnect all %u VPN Connection Settings that are currently connected. \r\nIs this what you want to do?
+CM_HTTPS_MSG You have chosen to connect via an HTTP proxy server. \r\n\r\nUsual HTTP proxy servers do not allow access to a TCP port of your choice. \r\nWhen a VPN Client connects to a VPN Server via a HTTP proxy server, it is possible to connect by using HTTPS (HTTP over SSL) communication. \r\nIn this case it is recommended that you specify 443 (HTTPS Port) as the destination VPN Server port number. \r\n(If you specify a different port number, there are cases where it will not be possible to connect via an HTTP proxy server. \r\n Make sure that port 443 is enabled on the destination VPN Server.)\r\n\r\nFor detailed information contact either the system administrator or network administrator of the HTTP proxy server you plan to connect via. \r\n\r\nDo you want to change the port number specification of the destination VPN Server to 443 (HTTPS Port)?
+CM_REMOTE_WARNING You are making changes to the remote management setting that will disallow remote management. \r\n\r\nCurrently the VPN Client Manager is connected to remote computer "%S" and is controlling the VPN Client service on that computer. \r\nIf remote connection is disabled, it will no longer be possible to remotely connect to and control the VPN Client service on computer "%S" using the VPN Client Manager. \r\n\r\nDo you want to disable remote management?
+CM_KEEP_INTERVAL_MSG Set a period between %u and %u seconds in the Packet Send Interval.
+CM_REMOTE_TITLE Using the VPN Client Manager, it is possible to connect to, and remotely manage a VPN Client service operating on another computer. \r\n(Note that the VPN Client service on the remote computer must allow remote management.)
+CM_DESKTOP_LOCAL_PC Local Computer
+CM_DESKTOP_REMOTE_PC Computer %S
+CM_DESKTOP_MSG_LOCAL_TS Terminal Service (Remote Desktop) Function
+CM_DESKTOP_MSG_LOCAL_SW Switch User Function
+CM_DESKTOP_MSG_LOCAL_1 Currently %s is installed on this computer, providing an environment that permits multiple users to log on concurrently. In this case, the messages regarding progress status, error messages and other messages displayed by VPN Client will be displayed on a session called the "Console Session".
+CM_DESKTOP_MSG_LOCAL_21 Currently "Session ID: 0, User %s" is assigned as the Console Session of this computer, however because you have started VPN Client Manager on session %u, it is not possible to display the message windows such as the progress status or errors that VPN Client displays.
+CM_DESKTOP_MSG_LOCAL_22 Currently no one is logged into the Console Session "Session ID: 0" of this computer and because you have started VPN Client Manager on session %u, it is not possible to display the message windows such as the progress status or errors that VPN Client displays.
+CM_DESKTOP_MSG_LOCAL_31 It is recommended that when this computer's Console Session (Session ID: 0, User %s) is displayed, start the VPN Client Manager in that session and start the connection to the VPN Connection Setting "%s". You will be able to start a connection process by doing what you are doing now but it will be at the risk of being unable to check the progress status and error messages that may be displayed during the process.
+CM_DESKTOP_MSG_LOCAL_32 It is recommended that you first log off and then after logging in locally, start the VPN Client Manager in that session and start the connection to VPN Connection Setting "%s". You will be able to start a connection process by doing what you are doing now but it will be at the risk of being unable to check the progress status and error messages that may be displayed during the process.
+CM_DESKTOP_MSG_REMOTE_1 Because you are currently performing operation while remotely connected to VPN Client on computer %S, if the VPN Client displays any progress status or error messages during the VPN connection process to the VPN Connection Setting, you will not be able to check these messages from your current screen display.
+CM_DESKTOP_MSG_REMOTE_2 To check all the progress status, error and other message windows that VPN Client displays, you must log in locally to computer %S and display the Control Session (desktop).
+CM_DESKTOP_MSG_REMOTE_3 It is recommended that you first log in directly and locally to computer %S, and then start the VPN Client Manager in that session and start the connection to VPN Connection Setting "%s". You will be able to start a connection process by doing what you are doing now but it will be at the risk of being unable to check the progress status and error messages that may be displayed during the process.
+CM_STOP_INST_VLAN_1 To install a Virtual Network Adapter on this computer you must start the VPN Client Manager within a "Console Session". \r\n\r\nCurrently, %s is installed on this computer and the current user is not logged into the Console Session but rather is logged in as the remote session (session ID: %u). \r\nTo install a Virtual Network Adapter, VPN Client Manager must be started in the Console Session (session ID: %u, user %s is logged on). \r\n\r\nFirst log on to the computer locally by using the user switching function, or the /console switch function that is on the remote desktop, or alternatively the computer's local console device and then start the VPN Client Manager and install the Virtual Network Adapter.
+CM_STOP_INST_VLAN_2 To install a Virtual Network Adapter on this computer you must start the VPN Client Manager within a "Console Session". \r\n\r\nCurrently, %s is installed on this computer and the current user is not logged into the Console Session but rather is logged in as the remote session (session ID: %u). \r\nTo install a Virtual Network Adapter you must start the VPN Client Manager within a "Console Session". \r\n(Currently the user is not logged on to the Console Session (Session ID: 0).) \r\n\r\nFirst log on to the computer locally by using the user switching function, or the /console switch function that is on the remote desktop, or alternatively the computer's local console device and then start the VPN Client Manager and install the Virtual Network Adapter.
+CM_SHORTCUT_DESKTOP_MSG To start a connection using the shortcut to the VPN Connection Setting, you must launch the shortcut file within the "Console Session". \r\n\r\nCurrently the user is logged on as the remote session (session ID: %u) and not as the Console Session.
+CM_HTTP_PROXY_WARNING Connect via HTTP Proxy Server is selected. \r\n\r\nIn many cases, the HTTP proxy server will only allow 2 kinds of TCP port to be used for the connection to the destination server port number, HTTP protocol (TCP port number 80) and HTTPS protocol (TCP port number 443). \r\n(There are also cases when the proxy server does allow a wider choice of TCP port for connection.) \r\n\r\nWhen making a VPN connection via an HTTP proxy server that denies connections to server ports other than HTTP ports or HTTPS ports, you must specify 443 (HTTPS protocol) as the destination VPN Server port number. \r\n\r\nTo check whether the HTTP proxy server you are connecting via allows connection to ports other than port numbers 80 or 443, contact the administrator of the HTTP proxy server. \r\n\r\nCurrently, %d is specified as the destination VPN Server port number. Do you want to change the port number to 443 (HTTPS protocol)?\r\n(The port 443 of the VPN Servers you connect to must be set to listening status and ready for connection.) \r\nIf you are unsure, then contact the system administrator or the network administrator.
+CM_PASSWORD_CHANGED The password was changed.
+CM_ACCOUNT_SETTING_FILE VPN Connection Setting Files (*.VPN)|*.vpn|All Files (*.*)|*.*
+CM_ACCOUNT_SAVE_TITLE Enter a VPN Connection Setting File's File Name for the Export Destination
+CM_ACCOUNT_OPEN_TITLE Select the VPN Connection Setting File to Import
+CM_ACCOUNT_FILE_BANNER # VPN Client VPN Connection Setting File\r\n# \r\n# This file is exported using the VPN Client Manager.\r\n# The contents of this file can be edited using a text editor.\r\n# \r\n# When this file is imported to the Client Connection Manager\r\n# it can be used immediately.\r\n\r\n
+CM_FAILED_TO_OPEN_FILE Unable to open file.
+CM_FAILED_TO_SAVE_FILE Unable to save file.
+CM_ACCOUNT_PARSE_FAILED Unable to load the VPN Connection Setting from the specified file. \r\nCheck the contents of the file.
+CM_ACCOUNT_MSG_SENSITIVE This VPN Connection Setting has the username and the password.\r\nDo you want to remove these sensitive information from the exported setting file?\r\n\r\nClick Yes to remove sensitive information.\r\nIn that case a user will be required to input the username and the password when he is trying to connect to the VPN Server.\r\n\r\nClick No to stay the sensitive information remaining on the file.
+CM_SHORTCUT_FILE Shortcut Files|*.lnk
+CM_SHORTCUT_SAVE_TITLE Enter the Shortcut File Name.
+CM_SHORTCUT_UNSUPPORTED The connection shortcut function is not supported by this version of VPN Client. \r\nUpdate to a new version.
+CM_SHORTCUT_COMMENT Using the VPN Connection Setting "%s" to connect to the VPN Server.
+CM_SHORTCUT_ERROR Failed to create a shortcut.
+CM_VPN_FILE_CLICKED Do you want to import the VPN Connection File?
+CM_VPN_FILE_IMPORT_NG Unable to import the VPN Connection Setting File. Because the VPN Client setting is locked.
+CM_VLAN_INSTALLING Please Wait a While
+CM_SECURE_MUST_LOCAL It is currently not possible to configure smart card settings because you are connected to and managing a VPN Client on a remote computer.
+CM_DETAIL_MODE_LINK_STR With a Cascade Connection, Connect by Bridge / Router mode is always enabled.
+CM_TRAY_INITING SoftEther VPN Client Manager...
+CM_TRAY_NOT_CONNECTED SoftEther VPN Client Manager\r\nNot connected.
+CM_TRAY_CONNECTED_0 SoftEther VPN Client Manager\r\nActive connections to %u servers and is attempting to connect to %u servers
+CM_TRAY_CONNECTED_1 SoftEther VPN Client Manager\r\nAttempting to connect to %u servers
+CM_TRAY_CONNECTED_2 SoftEther VPN Client Manager\r\nActive connections to %u servers
+CM_TRAY_MENU_1_SHOW &Show VPN Client Manager
+CM_TRAY_MENU_1_HIDE Cl&ose VPN Client Manager
+CM_TRAY_MENU_2_QUIT E&xit VPN Client Manager Program
+CM_TRAY_MENU_CONNECT Start VPN &Connection
+CM_TRAY_MENU_DISCONNECT &Disconnect VPN Connection
+CM_TRAY_MENU_STATUS Show VPN Connec&tion Status
+CM_TRAY_MENU_DISCONNECT_ALL Disconnect &All VPN Connections
+CM_TRAY_MENU_NEW &New VPN Connection Setting...
+CM_TRAY_MENU_RECENT Recent VPN Servers...
+CM_TRAY_MENU_TRAFFIC Network &Traffic Speed Test Tool...
+CM_TRAY_MENU_NETIF Show Network &Device Status...
+CM_TRAY_MENU_ABOUT &About VPN Client Manager...
+CM_TRAY_MENU_SETTING Change Operation &Mode...
+CM_TRAY_MENU_CANCEL Close this menu
+CM_EXIT_MESSAGE This will exit the VPN Client Manager program. \r\nIs this what you want to do?
+CM_IMPORT_MESSAGE From file "%S", VPN Connection Setting "%s" was installed.
+CM_VLAN_CREATING Creating a new Virtual Network Adapter for Windows. \r\n\r\nThis process can take several seconds or over a minute. \r\nPlease wait...\r\n\r\n(Please do not perform other operations while the Virtual Network Adapter is being installed.)
+CM_SETTING_PASSWORD The setting is locked. To remove the setting-locker, you must enter a password.
+CM_EASY_MODE_NOT_ON_REMOTE Unable to connect because the VPN Client on the remote computer is running in Easy Mode.
+CM_EASY_CONNECT_BUTTON_1 Start VPN &Connection
+CM_EASY_CONNECT_BUTTON_2 &Disconnect
+CM_EASY_ACCOUNT_WARNING You can only modify Proxy Server Setting, User Authentication and Virtual Network Adapter Used because the setting is locked.
+CM_EASY_INFO_1 Select a VPN connection.
+CM_EASY_INFO_2 Click Start VPN Connection to start a VPN connection.
+CM_EASY_INFO_3 VPN connection is active. You can disconnect by clicking Disconnect.
+CM_EXT_VOICE_MSG It is possible that some of the voice message contents of the Extension Voice Guide was not played normally. \r\nIs the Extension Voice Guide enabled?
+CM_EASY_TITLE VPN Client Easy Connection Manager
+CM_EASY_CONNECTED VPN connection is active.
+CM_EASY_CONNECTING Establishing VPN connection...
+CM_PROXY_FROM_IE Currently proxy setting from Internet Explorer was loaded.
+CM_TRAY_ICON_RESTORE The icon in the task tray was deleted.\r\n\r\nTo restore the icon, run the VPN Client Manager and click Show Task-tray Icon in the View menu.
+CM_WOULDYOULOAD_IE_PROXY Currently the Internet Explorer on this computer is configured to use the proxy server "%S".\r\nDo you want to apply the current proxy settings on the new VPN connection setting?\r\n\r\nClick Yes to use the proxy settings of Internet Explorer.\r\nClick No to use direct connection to the VPN Server (does not a proxy server.)\r\nThis setting can be modified in the property screen of the connection settings any time later.
+CM_MSG_TITLE VPN Server "%S" (Virtual Hub: "%S")
+CM_JUMPLIST_RCCONNECT Recent VPN Servers
+CM_VPNGATE_MESSAGE There is the list of Public VPN Relay Servers on the VPN Gate Academic Project Web Site.\r\nAnyone on the Internet can connect a VPN connection to any VPN servers on the list.\r\n\r\nVPN Gate Academic Project is not a part of SoftEther VPN.\r\nThis icon provides just a link to http://www.vpngate.net/.\r\nYou need to install VPN Gate Plugin to connect VPN Gate.\r\n\r\nDo you want to visit http://www.vpngate.net/ (provided by University of Tsukuba) ?
+
+
+# VPN Gate Service 関係
+VGC_COLUMN_0 DDNS Hostname
+VGC_COLUMN_1 IP Address (Hostname)
+VGC_COLUMN_2 Region
+VGC_COLUMN_3 Uptime
+VGC_COLUMN_4 VPN Sessions
+VGC_COLUMN_5 Line Speed
+VGC_COLUMN_6 Ping (Google, SE)
+VGC_COLUMN_7 SSL-VPN (TCP)
+VGC_COLUMN_8 UDP Support
+VGC_COLUMN_9 Logging Policy
+VGC_COLUMN_10 Cumulative Transfers
+VGC_COLUMN_11 Cumulative Users
+VGC_COLUMN_12 Operator's Name
+VGC_COLUMN_13 Operator's Message
+VGC_COLUMN_14 Total Score
+
+VGC_LOG_PERMANENT Permanent
+VGC_LOG_2WEEKS 2 Weeks
+VGC_LOG_NONE No Logs
+
+VGC_UPTIME_MIN %u mins
+VGC_UPTIME_HOUR %u hours
+VGC_UPTIME_DAY %u days
+VGC_NUM_VPN %u sessions
+VGC_NUM_LOGIN %S logins
+
+VGC_UDP_AVAILABLE UDP OK
+
+VGC_TITLE VPN Gate Plug-in Message
+
+VGC_VER_DIFF The version of VPN Gate Client Plug-in is different from SoftEther VPN Client.\r\n\r\n- Current VPN Gate Plug-in: Build %u\r\n- Current SoftEther VPN Client: Build %u\r\n\r\nIt is recommended to download and install VPN Gate Plug-in Build %u. Otherwise, communication errors or list-update errors might be occur. If the VPN Server List updating fails many times, update the VPN Gate Plug-in version.\r\n\r\nThe latest VPN Gate Plug-in is available at http://www.vpngate.net/.\r\n(Use a mirror-site if you cannot visit the above web-site directly.)\r\n\r\n
+
+VGC_LIST_STR_OK %S Public VPN Relay Servers on the Earth! (Updated at %S)
+VGC_LIST_STR_OK_2 %S Servers (at %S) - List update failed. Try again. If fails again, download the latest VPN Gate Client.
+VGC_LIST_STR_NG List update failed. Try again. If fails again, download the latest VPN Gate Client.
+VGC_PROXY_MSG If you are using a proxy server, you might not be able to use VPN Relay Servers which don't support the TCP port 443 as "SSL-VPN Connection" from such a proxy-mandated network.
+VGC_PROXY_TITLE Notice for Proxy Server Users
+
+VGS_NO_HUB_YET In order to set the message, first you have to commit enabling the VPN Gate service. After the service will be enabled, re-open this window and set the message.
+
+VGS_STOP VPN Gate Service will stop after you click the OK button.\r\n\r\nAfter VPN Gate Service will be stopped, this computer will never accept new VPN connection requests, however, still-alive VPN Sessions might remain.\r\n (Such VPN sessions sometimes hidden from the enumeration.) \r\n\r\nTo terminate all of still-alive VPN Sessions completely, restart SoftEther VPN Server or SoftEther VPN Client service, or reboot the computer.
+
+VGS_START This will activate the VPN Gate Relay Service function.\r\n\r\nVPN Gate Relay Service function must be activated by your own risk.\r\nSome countries prohibit using of encrypted VPN by laws.\r\nFor more details about VPN Gate Relay Service please visit http://www.vpngate.net/en/join.aspx.\r\n\r\nThe VPN Gate Academic Experiment Service is operated as a research project at the graduate school on University of Tsukuba, Japan. The service is governed under the Japanese laws. Other countries' laws are none of our concerns nor responsibilities.\r\n\r\nBy nature, there are almost 200 countries in the World, with different laws. It is impossible to verify every countries' laws and regulations and make the software comply with all countries' laws in advance to release the software. If a user uses VPN Gate service in a specific country, and damaged by public servants of the authority, the developer of either the service or software will never be liable to recover or compensate such damages or criminal responsibilities.\r\nBy using this software and service, the user must observe all concerned laws and rules with user's own responsibility. The user will be completely liable to any damages and responsibilities which are results of using this software and service, regardless of either inside or outside of Japan's territory.\r\nIf you don't agree nor understand the above warnings, do not use any of VPN Gate Academic Experiment Service functions.
+
+
+# Concerning services (Win32)
+SVC_HELP *** Command Line Arguments of %s (%S) ***\r\n\r\nThis program (%s) is a process runs as a background task. Start the program by specifying the following arguments on the command line. \r\n\r\n\r\n/install : Installs %s service (service name: %S) in Windows. After this, the service will automatically start. \r\n\r\n/uninstall... Uninstalls %s service (service name: %S) from Windows. \r\n\r\n/start : Starts %s service (service name: %S). \r\n\r\n/stop : Stops %s service (service name: %S). \r\n\r\n/test : Starts %s program in test mode. (For debug)\r\n\r\n/usermode : Starts %s program in the user mode. (When possible)\r\n\r\n/usermode_showtray : When starting in the user mode, this is used to display task tray icons when they were set to be hidden on a previous occasion. \r\n\r\n/usermode_hidetray : When starting in the user mode, this sets the task tray icons to be hidden. \r\n\r\n\r\nNote: Commands related to service operation other than /test and /usermode can only be operated on Windows NT / XP / Server 2003 / Vista / Server 2008.
+SVC_NT_ONLY The service related operation commands can only operate on Windows NT / 2000 / XP / Server 2003 / Vista / Server 2008. \r\nThey do not operate on Windows 98 / Me.
+SVC_ALREADY_INSTALLED The "%s" service (service name: %S) is already installed on this computer. Do you want to uninstall it and then re-install?
+SVC_INSTALL_OK The "%s" service (Service name: %S) was successfully installed. \r\n\r\n(Execution path: %s)\r\n\r\nThe service has started.
+SVC_INSTALL_FAILED The installation of the "%s" service (service name: %S) failed.
+SVC_INSTALL_FAILED_2 The "%s" service (Service name: %S) was successfully installed. \r\n\r\n(Execution path: %s)\r\n\r\nAn attempt to start the service, however, failed.
+SVC_NOT_INSTALLED The "%s" service (service name: %S) is not yet installed on this computer. Use the /install command line argument to install it.
+SVC_START_OK The "%s" service (service name: %S) started successfully.
+SVC_START_FAILED The "%s" service (service name: %S) failed to start.
+SVR_ALREADY_START The "%s" service (service name: %S) has already started.
+SVC_STOP_OK The "%s" service (Service name: %S) was stopped.
+SVC_STOP_FAILED The "%s" service (service name: %S) failed to stop.
+SVC_ALREADY_STOP The "%s" service (service name: %S) is already stopped.
+SVC_UNINSTALL_OK The "%s" service (Service name: %S) was uninstalled.
+SVC_UNINSTALL_FAILED The uninstallation of the "%s" service (service name: %S) failed.
+SVC_NOT_FOUND Unable to find information related to service %S from the string table.
+SVC_NOT_ADMIN To install, uninstall, start or stop the service you must have administrator privileges for this computer. \r\n\r\nIf you have an administrators account for this computer, log out and log on as an administrator. \r\nIf you are unclear about administrators accounts, contact your system administrator.
+SVC_TEST_MSG The "%s" service is started in test mode. \r\n\r\nClick OK to exit the service.
+SVC_TRAY_TOOLTIP %S (User mode)
+SVC_TEST_MUTEX The executable file %s is already started.
+SVC_USERMODE_MUTEX Another process of %s is already started.
+SVC_SERVICE_MUTEX Because service %S has process %s that is already started, the service cannot start.
+SVC_USERMODE_MENU_1 &Hide Tasktray Icon
+SVC_USERMODE_MENU_2 E&xit %s
+SVC_HIDE_TRAY_MSG This will hide the tasktray icons when starting %S in user mode. \r\nBeginning from next time %S is started in user mode, icons will not be displayed in the tasktray. \r\nThe menu to exit the process will also be hidden. \r\n\r\nTo exit the process in the case of Windows 98 / Me, use the Ctrl + Alt + Del key combination and select to end the process. \r\nWhen using other operating systems, use Task Manager. \r\n\r\nTo redisplay the tasktray icons, use the /usermode_showtray option when starting in user mode next time.
+
+
+# Concerning services (UNIX)
+UNIX_SVC_HELP %S Service Program\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n\n%S Command Usage:\n %S start - Start %S Service.\n %S stop - Stop %S Service if the service is already started.\n\n
+UNIX_SVC_STARTED %S Service Started.\n
+UNIX_SVC_STOPPING Stopping %S Service...\n
+UNIX_SVC_STOPPED %S Service Stopped.\n
+UNIX_SVC_STOP_FAILED %S Service Stop Failed.\n
+UNIX_SVC_ALREADY_START %S Service is already started.\nExecute "%S stop" to stop this service.\n
+UNIX_SVC_NOT_STARTED %S Service is not yet started.\nExecute "%S start" to start this service.\n
+UNIX_SVC_ERROR_FORK Failed to create child process for %S Service.\n
+
+
+# Service definition (SoftEther VPN Client)
+SVC_VPNCLIENT_NAME vpnclient
+SVC_VPNCLIENT_TITLE SoftEther VPN Client
+SVC_VPNCLIENT_DESCRIPT This manages the Virtual Network Adapter device driver and connection service for the SoftEther VPN Client. When this service is stopped, it will not be possible to use SoftEther VPN Client on this computer to connect to a SoftEther VPN Server.
+
+
+# Service Definition (SoftEther VPN Server)
+SVC_VPNSERVER_NAME vpnserver
+SVC_VPNSERVER_TITLE SoftEther VPN Server
+SVC_VPNSERVER_DESCRIPT This manages the server processes of SoftEther VPN Server. SoftEther VPN Server provides high-performance SoftEther VPN Server functions via TCP/IP protocol. When this service is stopped, SoftEther VPN Server on this computer will stop and SoftEther VPN Client will be unable to establish a VPN connection with this computer.
+
+
+# Service Definition (SoftEther VPN Bridge)
+SVC_VPNBRIDGE_NAME vpnbridge
+SVC_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_VPNBRIDGE_DESCRIPT This manages the processes of SoftEther VPN Bridge. SoftEther VPN Bridge provides a bridging connection between the network this computer is connected to and a SoftEther VPN Server that is remotely located. When this service is stopped, SoftEther VPN Bridge on this computer will stop and it will no longer be possible to communicate via the bridge connection.
+
+
+# Service definition (SoftEther VPN Client)
+SVC_SEVPNCLIENT_NAME sevpnclient
+SVC_SEVPNCLIENT_TITLE SoftEther VPN Client
+SVC_SEVPNCLIENT_DESCRIPT This manages the Virtual Network Adapter device driver and connection service for the SoftEther VPN Client. When this service is stopped, it will not be possible to use SoftEther VPN Client on this computer to connect to a SoftEther VPN Server.
+
+
+# Service Definition (SoftEther VPN Server)
+SVC_SEVPNSERVER_NAME sevpnserver
+SVC_SEVPNSERVER_TITLE SoftEther VPN Server
+SVC_SEVPNSERVER_DESCRIPT This manages the server processes of SoftEther VPN Server. SoftEther VPN Server provides high-performance SoftEther VPN Server functions via TCP/IP protocol. When this service is stopped, SoftEther VPN Server on this computer will stop and SoftEther VPN Client will be unable to establish a VPN connection with this computer.
+
+
+# Service Definition (SoftEther VPN Bridge)
+SVC_SEVPNBRIDGE_NAME sevpnbridge
+SVC_SEVPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_SEVPNBRIDGE_DESCRIPT This manages the processes of SoftEther VPN Bridge. SoftEther VPN Bridge provides a bridging connection between the network this computer is connected to and a SoftEther VPN Server that is remotely located. When this service is stopped, SoftEther VPN Bridge on this computer will stop and it will no longer be possible to communicate via the bridge connection.
+
+
+# Service definition (SoftEther VPN User-mode Router)
+SVC_VPNROUTER_NAME vpnrouter
+SVC_VPNROUTER_TITLE SoftEther VPN Router
+SVC_VPNROUTER_DESCRIPT This manages the server processes of SoftEther VPN Router (service mode). SoftEther VPN Router is a program that provides a virtual NAT and DHCP server that operates in user mode and by using simple operations it is possible to establish a safe connection between a virtual IP network and a physical IP network. When this service is stopped, SoftEther VPN Router on this computer will stop and SoftEther VPN Client will be unable to use the routing service on this computer.
+
+
+# Service Definition (EtherLogger)
+SVC_ELOGSVC_NAME elogsvc
+SVC_ELOGSVC_TITLE SoftEther EtherLogger
+SVC_ELOGSVC_DESCRIPT SoftEther EtherLogger is a service that captures data flowing through LAN cards connected to the computer and keeps a log of the headers of the packet types specified by the administrator and all data in text file format.
+
+
+# Concerning SoftEther VPN Server Manager
+SM_TITLE SoftEther VPN Server Manager
+SM_LOCALHOST localhost (This server)
+SM_SERVER_BRIDGE_TITLE Manage VPN Bridge "%S"
+SM_S_VHUB_BRIDGE When using VPN Bridge, you manage Virtual Hub "BRIDGE" to operate management of VPN Bridge.
+SM_DISCONNECTED The management connection was disconnected.
+SM_MIKAN Under Construction.
+SM_MAIN_COLUMN_1 Setting Name
+SM_MAIN_COLUMN_2 VPN Server Hostname
+SM_MAIN_COLUMN_3 Operation Mode
+SM_MODE_SERVER Entire VPN Server
+SM_MODE_HUB Hub '%S' Only
+SM_EDIT_CAPTION_1 New Connection Setting
+SM_EDIT_CAPTION_2 Edit %s
+SM_SETTING_EXISTS A Connection Setting with the same name as Connection Setting "%s" is already registered. Specify a different name.
+SM_SETTING_DELETE_MSG This will delete the Connection Setting "%s". Do you want to do this?
+SM_PASSWORD_TYPE_STR Password for Administration Connection
+SM_HUB_COLUMN_1 Virtual Hub Name
+SM_HUB_COLUMN_2 Status
+SM_HUB_COLUMN_3 Type
+SM_HUB_COLUMN_4 User
+SM_HUB_COLUMN_5 Group
+SM_HUB_COLUMN_6 Session
+SM_HUB_COLUMN_7 MAC Tables
+SM_HUB_COLUMN_8 IP Tables
+SM_HUB_COLUMN_9 Num Logins
+SM_HUB_COLUMN_10 Last Login
+SM_HUB_COLUMN_11 Last Communication
+SM_HUB_ONLINE Online
+SM_HUB_OFFLINE Offline
+SM_HUB_STANDALONE Standalone
+SM_HUB_STATIC Static Hub
+SM_HUB_DYNAMIC Dynamic Hub
+SM_SERVER_STANDALONE Standalone Server
+SM_FARM_CONTROLLER Cluster Controller
+SM_FARM_MEMBER Cluster Member Server
+SM_INFORMATION Latest Information
+SM_HUB_STATUS_CAPTION Status of Virtual Hub "%s"
+SM_HUB_STATUS_HUBNAME Virtual Hub Name
+SM_HUB_STATUS_ONLINE Status
+SM_HUB_TYPE Type
+SM_HUB_NUM_SESSIONS Sessions
+SM_HUB_NUM_SESSIONS_CLIENT Sessions (Client)
+SM_HUB_NUM_SESSIONS_BRIDGE Sessions (Bridge)
+SM_HUB_NUM_ACCESSES Access Lists
+SM_HUB_NUM_USERS Users
+SM_HUB_NUM_GROUPS Groups
+SM_HUB_NUM_MAC_TABLES MAC Tables
+SM_HUB_NUM_IP_TABLES IP Tables
+SM_HUB_SECURE_NAT SecureNAT
+SM_HUB_SECURE_NAT_YES Enabled
+SM_HUB_SECURE_NAT_NO Disabled
+SM_HUB_NUM_LOGIN Num Logins
+SM_HUB_LAST_LOGIN_TIME Last Login
+SM_HUB_LAST_COMM_TIME Last Communication
+SM_HUB_CREATED_TIME Created at
+SM_STATUS_COLUMN_1 Item
+SM_STATUS_COLUMN_2 Value
+
+SM_ST_SEND_UCAST_NUM Outgoing Unicast Packets
+SM_ST_SEND_UCAST_SIZE Outgoing Unicast Total Size
+SM_ST_SEND_BCAST_NUM Outgoing Broadcast Packets
+SM_ST_SEND_BCAST_SIZE Outgoing Broadcast Total Size
+
+SM_ST_RECV_UCAST_NUM Incoming Unicast Packets
+SM_ST_RECV_UCAST_SIZE Incoming Unicast Total Size
+SM_ST_RECV_BCAST_NUM Incoming Broadcast Packets
+SM_ST_RECV_BCAST_SIZE Incoming Broadcast Total Size
+
+SM_ST_NUM_PACKET_STR %S packets
+SM_ST_SIZE_BYTE_STR %S bytes
+
+CM_EDIT_HUB_1 New Virtual Hub
+CM_EDIT_HUB_2 Properties of %S
+
+CM_EDIT_HUB_STANDALONE Currently the server is operating in Standalone Mode. This Virtual Hub is operating as a Standalone Hub.
+CM_EDIT_HUB_TYPE_FIXED Currently the server is operating in Cluster Mode. This Virtual Hub is of the following type, which means it is not possible to make dynamic changes.
+CM_EDIT_HUB_CREATER A new Virtual Hub '%S' was created.
+CM_OFFLINE_MSG Do you want to switch %s to offline?\r\n\r\nIf you switch the Virtual Hub to offline all sessions currently connected to the Virtual Hub will be disconnected and new sessions will be unable to connect.
+CM_DELETE_HUB_MSG Do you want to delete %S?\r\n\r\nIf you delete the Virtual Hub, all sessions currently connected to the Virtual Hub will be disconnected and new sessions will be unable to connect. \r\nThis will also delete all the Hub settings, user objects, group objects, certificates and Cascade Connections. \r\n\r\nOnce you delete the Virtual Hub, it cannot be recovered. \r\nAre you sure you want to delete it?
+CM_HUB_DELETED_MSG Virtual Hub %S was deleted.
+CM_LISTENER_COLUMN_1 Port Number
+CM_LISTENER_COLUMN_2 Status
+CM_LISTENER_TCP_PORT TCP %u
+CM_LISTENER_ONLINE Listening
+CM_LISTENER_OFFLINE Stopped
+CM_LISTENER_ERROR Error
+CM_DELETE_LISTENER_MSG This will delete the Listener (TCP port %u). From now on, it will not be possible to connect to this port. \r\nIs this what you want to do?
+CM_STOP_LISTENER_MSG This will stop the Listener (TCP port %u). Until Listener is restarted it will not be possible to connect to this port. \r\n\r\nIs this you want to do?
+CM_CLOSE_BUTTON Close
+CM_CERT_SET_MSG A new server certificate was set.
+CM_SHORTCUT_DISCONNECT There is already an active connection to the specified connection destination. \r\n\r\nDo you want to disconnect?
+
+
+SM_SERVER_STATUS Server Status
+SM_ST_SERVER_TYPE Server Type
+SM_ST_NUM_TCP Number of Active Sockets
+SM_ST_NUM_TCP_LOCAL Number of Active Sockets (This Server)
+SM_ST_NUM_TCP_REMOTE Number of Active Sockets (Other Member Servers)
+SM_ST_NUM_HUB_TOTAL Number of Virtual Hubs
+SM_ST_NUM_HUB_STATIC Number of Static Virtual Hubs
+SM_ST_NUM_HUB_DYNAMIC Number of Dynamic Virtual Hubs
+SM_ST_NUM_SESSION_TOTAL Number of Sessions
+SM_ST_NUM_SESSION_LOCAL Number of Sessions (This Server)
+SM_ST_NUM_SESSION_REMOTE Number of Sessions (Other Member Servers)
+SM_ST_NUM_MAC_TABLE Number of MAC Address Tables
+SM_ST_NUM_IP_TABLE Number of IP Address Tables
+SM_ST_NUM_USERS Number of Users
+SM_ST_NUM_GROUPS Number of Groups
+SM_ST_CLIENT_LICENSE Using Client Connection Licenses (This Server)
+SM_ST_BRIDGE_LICENSE Using Bridge Connection Licenses (This Server)
+SM_ST_CLIENT_LICENSE_EX Using Client Connection Licenses (Entire Cluster)
+SM_ST_BRIDGE_LICENSE_EX Using Bridge Connection Licenses (Entire Cluster)
+SM_ST_START_TIME Server Started at
+SM_ST_CURRENT_TIME Current Time
+SM_ST_CURRENT_TICK 64 bit High-Precision Logical System Clock
+SM_ST_TOTAL_MEMORY Total Logical Memory Size
+SM_ST_USED_MEMORY Used Logical Memory Size
+SM_ST_FREE_MEMORY Free Logical Memory Size
+SM_ST_TOTAL_PHYS Total Physical Memory Size
+SM_ST_USED_PHYS Used Physical Memory Size
+SM_ST_FREE_PHYS Free Physical Memory Size
+SM_ST_RAM_SIZE_KB %S bytes
+SM_INFO_TITLE VPN Server Version Information
+SM_INFO_PRODUCT_NAME Product Name
+SM_INFO_VERSION Version
+SM_INFO_BUILD Build
+SM_INFO_HOSTNAME Host Name
+SM_OS_SYSTEM_NAME Type of Operating System
+SM_OS_PRODUCT_NAME Product Name of Operating System
+SM_OS_SERVICE_PACK Service Pack
+SM_OS_SP_TAG Service Pack %u
+SM_OS_VENDER_NAME Operating System Vendor
+SM_OS_VERSION Operating System Version
+SM_OS_KERNEL_NAME Type of OS Kernel
+SM_OS_KERNEL_VERSION Version of OS Kernel
+SM_CONNECTION_TYPE_0 Client
+SM_CONNECTION_TYPE_1 Initializing...
+SM_CONNECTION_TYPE_2 Login
+SM_CONNECTION_TYPE_3 Additional Connection
+SM_CONNECTION_TYPE_4 Clustering RPC
+SM_CONNECTION_TYPE_5 Management RPC
+SM_CONNECTION_TYPE_6 Hub Enumeration RPC
+SM_CONNECTION_TYPE_7 Changing Password
+SM_CONNECTION_TYPE_8 MS-SSTP Connection
+SM_CONNECTION_TYPE_9 OpenVPN Connection
+SM_CONN_COLUMN_1 Connection Name
+SM_CONN_COLUMN_2 Connection Source
+SM_CONN_COLUMN_3 Connection Start
+SM_CONN_COLUMN_4 Type
+SM_HOSTNAME_AND_PORT %S: %u
+SM_CONN_DISCONNECT_MSG This will disconnect connection %s. \r\nIs this you want to do?
+SM_CONNINFO_CAPTION Connection %s Information
+SM_CONNINFO_NAME Connection Name
+SM_CONNINFO_TYPE Connection Type
+SM_CONNINFO_HOSTNAME Source Host Name
+SM_CONNINFO_IP Source IP Address
+SM_CONNINFO_PORT Source Port Number (TCP)
+SM_CONNINFO_TIME Connection Start
+SM_CONNINFO_SERVER_STR Server Product Name
+SM_CONNINFO_SERVER_VER Sever Version
+SM_CONNINFO_SERVER_BUILD Server Build Number
+SM_CONNINFO_CLIENT_STR Client Product Name
+SM_CONNINFO_CLIENT_VER Client Version
+SM_CONNINFO_CLIENT_BUILD Client Build
+SM_FARM_REBOOT_MSG You are about to change the clustering configuration. \r\n\r\nWhen you change the clustering configuration, all currently connected sessions and connections for management purposes (including this management connection) will be disconnected and the server program will restart. \r\nWhen there are many server users, it could take over a minute to restart. \r\n\r\nClick OK to automatically disconnect the connection with the server. To continue management, you will need to reconnect to the server.
+SM_FM_COLUMN_1 Type
+SM_FM_COLUMN_2 Connection Started at
+SM_FM_COLUMN_3 Host Name
+SM_FM_COLUMN_4 Point
+SM_FM_COLUMN_5 Number of Sessions
+SM_FM_COLUMN_6 Number of TCP Connections
+SM_FM_COLUMN_7 Number of Operating Hubs
+SM_FM_COLUMN_8 Using Client Connection Licenses
+SM_FM_COLUMN_9 Using Bridge Connection Licenses
+SM_FM_CONTROLLER Controller
+SM_FM_MEMBER Member
+SM_FMINFO_TYPE Server Type
+SM_FMINFO_CONNECT_TIME Connection Established at
+SM_FMINFO_IP IP Address
+SM_FMINFO_HOSTNAME Host Name
+SM_FMINFO_POINT Point
+SM_FMINFO_WEIGHT Performance Standard Ratio
+SM_FMINFO_NUM_PORT Number of Public Ports
+SM_FMINFO_PORT Public Port #%u (TCP/IP)
+SM_FMINFO_NUM_HUB Number of Running Virtual Hubs
+SM_FMINFO_HUB Virtual Hub #%u
+SM_FMINFO_HUB_TAG_1 %S (Dynamic)
+SM_FMINFO_HUB_TAG_2 %S (Static)
+SM_FMINFO_NUM_SESSION Number of Sessions
+SM_FMINFO_NUN_CONNECTION Number of TCP Connections
+SM_FMINFO_CAPTION Cluster Member Server Status
+SM_FC_STATUS_CAPTION Connection to Cluster Controller Status
+SM_FC_IP Controller IP Address
+SM_FC_PORT Controller TCP/IP Port
+SM_FC_STATUS Connection Status
+SM_FC_ONLINE Online
+SM_FC_OFFLINE Offline
+SM_FC_LAST_ERROR Last Error
+SM_FC_ERROR_TAG %s (Error Code: %u)
+SM_FC_START_TIME Connection Started at
+SM_FC_FIRST_TIME First Connection Established at
+SM_FC_CURRENT_TIME Current Connection Established at
+SM_FC_NUM_TRY Number of Connection Attempts
+SM_FC_NUM_CONNECTED Number of Successful Connections
+SM_FC_NUM_FAILED Number of Failed Connections
+SM_FC_NOT_CONNECTED (Not Connected)
+SM_CHANGE_PASSWORD_1 The passwords you entered did not match. Enter the same password in Confirm as you enter in Password.
+SM_CHANGE_PASSWORD_2 You have entered an empty password. Continue anyway?
+SM_CHANGE_PASSWORD_3 The password was changed.
+SM_USER_COLUMN_1 User Name
+SM_USER_COLUMN_2 Full Name
+SM_USER_COLUMN_3 Group Name
+SM_USER_COLUMN_4 Description
+SM_USER_COLUMN_5 Auth Method
+SM_USER_COLUMN_6 Num Logins
+SM_USER_COLUMN_7 Last Login
+SM_AUTHTYPE_0 Anonymous Authentication
+SM_AUTHTYPE_1 Password Authentication
+SM_AUTHTYPE_2 Individual Certificate Authentication
+SM_AUTHTYPE_3 Signed Certificate Authentication
+SM_AUTHTYPE_4 RADIUS Authentication
+SM_AUTHTYPE_5 NT Domain Authentication
+SM_NO_GROUP -
+SM_USER_DELETE_MSG This will delete the user "%s". Do you want to do this?
+SM_EDIT_USER_CAPTION_1 Create New User
+SM_EDIT_USER_CAPTION_2 Properties of User %S
+SM_EDIT_USER_CERT_INFO The users using 'Individual Certificate Authentication' will be allowed or denied connection depending on whether the SSL client certificate completely matches the certificate that was set for the user beforehand.
+SM_EDIT_USER_POL_DLG Security Policy of User %S
+SM_POLICY_DEF_CAPTION Security Policy
+SM_LIMIT_STR Specify an integer that is within the range %u to %u.
+SM_POLICY_INIT_TITLE Select a policy item from the list on the left.
+SM_USER_CREEATE_OK User %S was created.
+SM_USERINFO_CAPTION User "%S" Information
+SM_USERINFO_NAME User Name
+SM_USERINFO_GROUP Group Name
+SM_USERINFO_CREATE Created on
+SM_USERINFO_UPDATE Updated on
+SM_USERINFO_EXPIRE Expiration Date
+SM_USERINFO_NUMLOGIN Number of Logins
+SM_GROUPLIST_NAME Group Name
+SM_GROUPLIST_REALNAME Full Name
+SM_GROUPLIST_NOTE Description
+SM_GROUPLIST_NUMUSERS Num Users
+SM_EDIT_GROUP_CAPTION_1 Creation of New Group
+SM_EDIT_GROUP_CAPTION_2 Properties of Group %S
+SM_GROUP_CREATED Group %S was created.
+SM_GROUP_DELETE_MSG Group %S was deleted. Do you want to do this?
+SM_GROUP_POLICY_CAPTION Security Policy of Group %S
+SM_GROUP_MEMBER_STR \ (Display only users belonging to group %S)
+SM_SELECT_GROUP &Select
+SM_SELECT_NO_GROUP &None
+SM_SELECT_ALT_GROUP Select a &Group...
+SM_ACCESS_COLUMN_0 ID
+SM_ACCESS_COLUMN_1 Action
+SM_ACCESS_COLUMN_2 Status
+SM_ACCESS_COLUMN_3 Priority
+SM_ACCESS_COLUMN_4 Memo
+SM_ACCESS_COLUMN_5 Contents
+SM_ACCESS_COLUMN_6 Unique ID
+SM_ACCESS_PASS Pass
+SM_ACCESS_DISCARD Discard
+SM_ACCESS_ENABLE Enable
+SM_ACCESS_DISABLE Disable
+SM_ACCESS_PROTO_1 All IPv4 / IPv6 Protocols
+SM_ACCESS_PROTO_2 6 (TCP/IP Protocol)
+SM_ACCESS_PROTO_3 17 (UDP/IP Protocol)
+SM_ACCESS_PROTO_4 1 (ICMPv4 Protocol)
+SM_ACCESS_PROTO_5 58 (ICMPv6 Protocol)
+SM_ACCESS_PROTO_6 Specify the IP Protocol Number
+SM_SELECT_USER &Select
+SM_SELECT_NO Do&n't Select
+SM_PLEASE_SELECT Select User.
+SM_LINK_COLUMN_1 Setting Name
+SM_LINK_COLUMN_2 Status
+SM_LINK_COLUMN_3 Established at
+SM_LINK_COLUMN_4 Destination VPN Server
+SM_LINK_COLUMN_5 Virtual Hub
+SM_LINK_STATUS_OFFLINE Offline (Stopped)
+SM_LINK_STATUS_ERROR Error %u: %s
+SM_LINK_STATUS_ONLINE Online (Established)
+SM_LINK_POLICY_GROUP Cascade Connection Setting
+SM_LINK_POLICY_CAPTION Security policy settings applicable to Cascade sessions
+SM_LINK_CONNECTING Connecting
+SM_LINK_SAVE_ONLINE The Cascade Connection Setting "%s" was changed but because this Cascade Connection is currently online, the setting will not be applied until next time the connection is established.
+SM_LINK_DELETE_MSG This will delete the settings for Cascade Connection "%s". Do you want to do this?
+SM_LINK_OFFLINE_MSG Currently Cascade Connection "%s" is active. Do you want to disconnect this connection?
+SM_LINK_STATUS_CAPTION Connection status of Cascade Connection "%s"
+SM_LOG_SWITCH_0 No Switching
+SM_LOG_SWITCH_1 Switch in Every Second
+SM_LOG_SWITCH_2 Switch in Every Minute
+SM_LOG_SWITCH_3 Switch in Every Hour
+SM_LOG_SWITCH_4 Switch in Every Day
+SM_LOG_SWITCH_5 Switch in Every Month
+SM_SESS_DISCONNECT_MSG This will disconnect session "%S". Do you want to do this?
+SM_SESS_COLUMN_1 Session Name
+SM_SESS_COLUMN_2 Location
+SM_SESS_COLUMN_3 User Name
+SM_SESS_COLUMN_4 Source Host Name
+SM_SESS_COLUMN_5 TCP Connections
+SM_SESS_COLUMN_6 Transfer Bytes
+SM_SESS_COLUMN_7 Transfer Packets
+SM_SESS_COLUMN_8 VLAN ID
+SM_SESS_NORMAL Local Session
+SM_SESS_LOCAL Local Session
+SM_SESS_LOCAL_2 On '%S'
+SM_SESS_REMOTE On '%S'
+SM_SESS_LINK Cascade Connection
+SM_SESS_LINK_HOSTNAME Virtual Host
+SM_SESS_LINK_TCP None
+SM_SESS_SNAT SecureNAT Session
+SM_SESS_SNAT_HOSTNAME Virtual Host
+SM_SESS_SNAT_TCP None
+SM_SESS_BRIDGE Local Bridge Session
+SM_SESS_BRIDGE_HOSTNAME Ethernet Bridge
+SM_SESS_LAYER3_HOSTNAME Virtual Layer 3 Switch
+SM_SESS_BRIDGE_TCP None
+SM_SESS_STATUS_CAPTION VPN Session "%S" Status
+SM_SESS_STATUS_USERNAME User Name (Authentication)
+SM_SESS_STATUS_REALUSER User Name (Database)
+SM_SESS_STATUS_GROUPNAME Group Name
+SM_CLIENT_IP Source IP Address
+SM_CLIENT_HOSTNAME Source Host Name
+SM_NODE_CLIENT_NAME Client Product Name
+SM_NODE_CLIENT_VER Client Version
+SM_NODE_CLIENT_BUILD Client Build
+SM_NODE_SERVER_NAME Server Product Name
+SM_NODE_SERVER_VER Server Version
+SM_NODE_SERVER_BUILD Server Build
+SM_NODE_CLIENT_OS_NAME Client OS Name
+SM_NODE_CLIENT_OS_VER Client OS Version
+SM_NODE_CLIENT_OS_PID Client OS Product ID
+SM_NODE_CLIENT_HOST Client Host Name
+SM_NODE_CLIENT_IP Client IP Address
+SM_NODE_CLIENT_PORT Client Port
+SM_NODE_SERVER_HOST Server Host Name
+SM_NODE_SERVER_IP Server IP Address
+SM_NODE_SERVER_PORT Server Port
+SM_NODE_PROXY_HOSTNAME Proxy Host Name
+SM_NODE_PROXY_IP Proxy IP Address
+SM_NODE_PROXY_PORT Proxy Port
+SM_MAC_COLUMN_1 Session Name
+SM_MAC_COLUMN_2 MAC Address
+SM_MAC_COLUMN_3 Created at
+SM_MAC_COLUMN_4 Updated at
+SM_MAC_COLUMN_5 Location
+SM_MAC_COLUMN_1A VLAN ID
+SM_SESSION_FILTER \ (Displays only entries of session %S)
+SM_IP_COLUMN_1 Session Name
+SM_IP_COLUMN_2 IP Address
+SM_IP_COLUMN_3 Created at
+SM_IP_COLUMN_4 Updated at
+SM_IP_COLUMN_5 Location
+SM_MAC_IP_DHCP %S (DHCP)
+SM_MACIP_LOCAL On This Server
+SM_MACIP_SERVER On '%S'
+SM_SNAT_STATUS SecureNAT Operating Status
+SM_SNAT_NUM_SESSION %u Session
+SM_SNAT_NUM_CLIENT %u Client
+SM_SNAT_IS_KERNEL Kernel-mode NAT is Active
+SM_BRIDGE_TOO_OLD_VER The Local Bridge function is not supported by the version of the VPN Server that is currently connected. \r\nTry updating to a new version.
+SM_BRIDGE_UNSUPPORTED Unable to use the Local Bridge function with the operating system that this VPN Server is operating on. For the list of operating system that the Local Bridge function can be used on, refer to the online documentation of the VPN Server.
+SM_BRIDGE_WPCAP_REMOTE In order to use the Local Bridge function on this VPN Server, you must install the WinPcap software. The software WinPcap is currently not installed on the server computer. \r\n\r\nTo continue the installation of the WinPcap software, you must start SoftEther VPN Server Manager on the server computer that is running VPN Server and then while connected to localhost (location of your own computer), have the Local Bridge Function Setting window displayed. \r\nTo continue, first exit this management session, and then, after starting SoftEther VPN Server Manager on the server computer, connect to localhost and continue the setting process.
+SM_BRIDGE_WPCAP_ROOT In order to use the Local Bridge function on this VPN Server, you must install the WinPcap software. \r\n\r\nTo continue the installation you must log in to this computer as a user with administrator privileges. \r\nLog on as an administrator and start the SoftEther VPN Server Manager again.
+SM_BRIDGE_WPCAP_INSTALL In order to use the Local Bridge function on this VPN Server, you must install the WinPcap software. The software WinPcap is currently not installed on the server computer. \r\n\r\nWinPcap is an easy-to-install free software that is bundled together with the VPN Server. \r\n\r\nDo you want to begin the installation of WinPcap?
+SM_BRIDGE_WPCAP_REBOOT1 After WinPcap installation has completed, you must restart the computer before you use the Local Bridge function again. \r\n\r\nAfter you restart the computer manually and start VPN Server, configure the settings for the Local Bridge function.
+SM_BRIDGE_WPCAP_REBOOT2 After WinPcap installation has completed, you must restart the SoftEther VPN Server service before you use the Local Bridge function again. \r\n\r\nIt only takes a short time to restart the SoftEther VPN Server service, however all sessions that are currently connected to the VPN Server will be disconnected. \r\nThis management session will also be disconnected, so you will need to reconnect to continue. \r\n\r\nDo you want to restart the SoftEther VPN Server service?
+SM_BRIDGE_RESOURCE Unable to load the WinPcap driver.
+SM_BRIDGE_COLUMN_1 Number
+SM_BRIDGE_COLUMN_2 Virtual Hub Name
+SM_BRIDGE_COLUMN_3 Network Adapter or Tap Device Name
+SM_BRIDGE_COLUMN_4 Status
+SM_BRIDGE_OFFLINE Offline
+SM_BRIDGE_ONLINE Operating
+SM_BRIDGE_ERROR Error
+SM_BRIDGE_OK The Local Bridge connection definition was added.
+SM_BRIDGE_DELETE Do you want to delete the Local Bridge from Virtual Hub "%s" to device "%s"?
+SM_BRIDGE_DELETE_OK The Local Bridge was deleted.
+SM_BRIDGE_INTEL While in the condition that occurs immediately after a new bridge connection is made when bridging to a physical network adapter, depending on the type of network adapter, there are cases where it will not be possible to communicate using TCP/IP to the network adapter using a bridge connection from a computer on the virtual network. \r\n(This phenomenon is known to occur for Intel and Broadcom network adapters.) \r\n\r\n\r\nIf this issue arises, remedy the situation by restarting the computer on which VPN Server / Bridge is running. Normal communication will be possible after the computer has restarted. \r\n\r\n\r\nAlso many wireless network adapters will not respond to the sending of packets in promiscuous mode and when this occurs you will be unable to use the Local Bridge. If this issue arises, try using a regular wired network adapter instead of the wireless network adapter.
+SM_BRIDGE_VPN You are attempting to make a Local Bridge to "%S".\r\n\r\nA Local Bridge is made between a Virtual Hub and a physical network adapter in usual usage. It is unusual to make a Local Bridge to a Virtual Network Adapter.\r\nPlease make sure that it is your intention.\r\n\r\nDo you really want to continue?
+SM_BRIDGE_INFO_1 Select the Ethernet device (network adapter) for the bridge destination.
+SM_BRIDGE_INFO_2 Enter a name of the new tap device to create.
+SM_CONFIG_SAVED The configuration file was saved.
+SM_CONFIG_SAVE_FAILED Failed to save the configuration file.
+SM_CONFIG_OPEN_FAILED Unable to open the specified file.
+SM_CONFIG_CONFIRM This will apply the specified configuration file to the VPN Server. The VPN Server will automatically restart and it will start loading the new configuration file. The users who are currently connected to the VPN Server will be disconnected. This management session will also be disconnected, you will need to reconnect to the server. \r\n\r\nDo you want to proceed?
+SM_CONFIG_WRITE_OK The configuration file on the server side was overwritten.
+SM_AO_COLUMN_1 Item
+SM_AO_COLUMN_2 Value
+SM_TRUE_OR_FALSE Set either 0 (false) or 1 (true) for this item.
+SM_AO_SET_OK The Virtual Hub Administration Option was set.
+SM_EXT_OPTION_SET_OK The Virtual Hub Extended Option was set.
+SM_PASSWORD_MSG Currently an administrator password has not been set for this VPN Server. It is recommended that a password is set. \r\n\r\nDo you want to set a server administrator password?
+SM_L3_SW_COLUMN1 Layer 3 Switch Name
+SM_L3_SW_COLUMN2 Running Status
+SM_L3_SW_COLUMN3 Interfaces
+SM_L3_SW_COLUMN4 Routing Tables
+SM_L3_SW_ST_F_F Stop
+SM_L3_SW_ST_T_F Start (Error)
+SM_L3_SW_ST_T_T Start (Running)
+SM_L3_SW_DEL_MSG This will delete the Virtual Layer 3 Switch "%S". \r\nIs this you want to do?
+SM_L3_SW_IF_COLUMN1 IP Address
+SM_L3_SW_IF_COLUMN2 Subnet Mask
+SM_L3_SW_IF_COLUMN3 Virtual Hub Name
+SM_L3_SW_TABLE_COLUMN1 Network Address
+SM_L3_SW_TABLE_COLUMN2 Subnet Mask
+SM_L3_SW_TABLE_COLUMN3 Gateway Address
+SM_L3_SW_TABLE_COLUMN4 Metric
+SM_SECURE_NAT_MSG Are you sure you want to enable the SecureNAT?\r\n\r\nIf you enable the SecureNAT, a virtual router with virtual NAT function will be created that has one IP address in the Virtual Hub. This Virtual Router will interact as one computer or router with other computers that are connected to the virtual network. \r\n\r\nThe SecureNAT in the Virtual NAT enables any computers connected to the Virtual Hub to establish communication with an external network via the SecureNAT. \r\nTherefore, when SecureNAT is running on this VPN Server, there is no need to use local VPN Client to connect the self-computer's Virtual Hub.\r\n\r\n\r\nAlso, please take care that if there is already a DHCP server in a location that can be reached from a Virtual Hub Layer 2 segment, disable the DHCP server function by clicking the SecureNAT Configuration, otherwise there will be a DHCP conflict. \r\n\r\nMoreover, you can disable the NAT function and only use the DHCP server if you wish.
+SM_CRL_COLUMN_1 Certificate Summary
+SM_CRL_DELETE_MSG This will delete the selected item. Do you want to do this?
+SM_CRL_EMPTY_MSG No items have been selected. \r\nIf you add this certificate revocation entry, all certificates will be judged as invalid and all client connections that are made in certificate authentication mode will be refused. \r\n\r\nIs this you want to do?
+SM_AC_COLUMN_1 ID
+SM_AC_COLUMN_2 Priority
+SM_AC_COLUMN_3 Action
+SM_AC_COLUMN_4 Contents
+SM_AC_PASS Pass
+SM_AC_DENY Deny
+SM_LOG_FILE_COLUMN_1 Log File Name
+SM_LOG_FILE_COLUMN_2 File Size
+SM_LOG_FILE_COLUMN_3 Updated on
+SM_LOG_FILE_COLUMN_4 Location
+SM_READ_LOG_FILE_INFO_1 Please wait until processing is finished...
+SM_READ_LOG_FILE_INFO_2 %S in process, %S has finished...
+SM_READ_LOG_FILE_ERROR File was not successfully downloaded.
+SM_READ_SAVE_DLG_TITLE Specify a File Name for the Log File's Save Destination
+SM_READ_SAVE_DLG_FILTER Log Files (*.LOG)|*.log|All Files (*.*)|*.*
+SM_READ_SAVE_FAILED Failed to save the log file.
+SM_READ_SAVE_TMP_FAILED Unable to write to temporary file "%S".
+SM_READ_SAVE_OPEN_ERROR Unable to open temporary file "%S". \r\n\r\nIt is possible that the .LOG file extension is not an assigned file type in Windows.
+SM_LICENSE_COLUMN_1 Number
+SM_LICENSE_COLUMN_2 License Key
+SM_LICENSE_COLUMN_3 License Type Name
+SM_LICENSE_COLUMN_4 Status
+SM_LICENSE_COLUMN_5 Expiration Date
+SM_LICENSE_COLUMN_6 License ID
+SM_LICENSE_COLUMN_7 License Type ID
+SM_LICENSE_COLUMN_8 Server ID
+SM_LICENSE_COLUMN_9 Serial ID
+SM_LICENSE_INFINITE Infinite
+SM_LICENSE_NO_EXPIRES No Expiration
+SM_LICENSE_STATUS_EDITION Product Edition
+SM_LICENSE_STATUS_RELEASE Release Date of VPN Server
+SM_LICENSE_STATUS_SYSTEM_ID Current Server ID
+SM_LICENSE_STATUS_EXPIRES Expiration of Current Product License
+SM_LICENSE_STATUS_SUBSCRIPTION Status of Subscription Contract
+SM_LICENSE_STATUS_SUBSCRIPTION_NONEED No Need (This Edition requires no subscription keys)
+SM_LICENSE_STATUS_SUBSCRIPTION_NONE No Keys (Adding a subscription key is required)
+SM_LICENSE_STATUS_SUBSCRIPTION_VALID Subscription is Active [Until %s]
+SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED Subscription is Expired [at %s]
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD Version Allowed by Current Contract
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR Free Upgrade to Any Future Versions Released Until %s is Allowed
+SM_LICENSE_STATUS_ENTERPRISE Enterprise Functions Availability
+SM_LICENSE_STATUS_ENTERPRISE_YES Yes (Available)
+SM_LICENSE_STATUS_ENTERPRISE_NO No (Unavailable)
+SM_LICENSE_NUM_USER Allowed User Objects to Create
+SM_LICENSE_NUM_CLIENT Allowed Concurrent Clients
+SM_LICENSE_NUM_BRIDGE Allowed Concurrent Bridges
+SM_NO_LICENSE_COLUMN Caution:
+SM_NO_LICENSE Because there are no product licenses registered, this VPN Server's communication function doesn't operate.
+SM_LICENSE_DELETE_MSG Are you sure you want to delete the selected license from the VPN Server?
+SM_SYSLOG_0 Disable Syslog Send Function
+SM_SYSLOG_1 Send Server Logs by Syslog
+SM_SYSLOG_2 Send Server and Virtual Hub Security Logs by Syslog
+SM_SYSLOG_3 Send Server, Virtual Hub Security, and Packet Logs by Syslog
+SM_SETUP_INFO_1 Click Next to start Setup. Click Close if you want to exit the setup and manually configure all settings.
+SM_SETUP_INFO_2 Click Close to configuring the settings of a VPN server manually by yourself.
+SM_SETUP_BRIDGE_ONLY You are currently connected to VPN Bridge. You can only create VPN Bridge at Each Site for Multi-site VPN.
+SM_SETUP_BRIDGE_EDGE VPN Bridge at &Each Site
+SM_SETUP_WARNING The current settings of this VPN Server or VPN Bridge will be initialized. \r\nIs this you want to do?
+SM_SETUP_SELECT Select the Ethernet device to establish the bridge connection.
+SM_SETUP_NO_LICENSE_KEY Currently there is no licenses registered for this SoftEther VPN Server. \r\n\r\nFor SoftEther VPN Server to operate as a VPN server, you must enter a license key. \r\nDo you want to display the License Manager?\r\n\r\n(To use the VPN Server as a Trial Version, you have to obtain a trial key from the SoftEther VPN Project web site.\r\nClick Yes and click Obtain or Extend of License button to obtain a trial key.
+SM_HUBEXT_OPTION_TITLE Virtual Hub Extended Options
+SM_HUBEXT_OPTION_STATIC1 Virtual Hub Extended Options allows you to configure more detailed parameters of this Virtual Hub.
+SM_HUBEXT_OPTION_STATIC2 By default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options.\nHowever, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options. (View only.)
+SM_VLAN_COLUMN_0 Network Adapter Name
+SM_VLAN_COLUMN_1 Driver Type
+SM_VLAN_COLUMN_2 Driver File Name
+SM_VLAN_COLUMN_3 VLAN Transparency Setting
+SM_VLAN_COLUMN_4 GUID
+SM_VLAN_COLUMN_5 Device Instance ID
+SM_VLAN_YES Enabled
+SM_VLAN_NO Not Enabled
+SM_VLAN_MSG_1 The Windows Registry was configured to allow the network adapter "%S" to transmit / receive tagged-VLAN packets.\r\n\r\nHowever, there are some network adapters which requires additional settings on the property of the Device Manager on the local computer's Windows to set the parameters to enable Jumbo Frames. (Ethernet frames which are larger than 1,512 bytes.) Unless you enable Jumbo Frames, some large VLAN packets will be dropped. In the case if large VLAN packets always disappeared, please enable Jumbo Frames. (For example, set the maximum size to 4,088 bytes.) The Device Manager in Windows will help you to configure.\r\n\r\nThis VLAN Transparency Setting has been written to the Windows Registry, however it is not guaranteed that VLAN packets can be transmitted effectively.\r\nIf transmitting VLAN tagged packets will fail after this configuration, refer the manual of the network adapter "%S" to configure manually and adequately. Moreover, "%S" might not support the VLAN transparency setting. In that case, such a network adapter cannot be used to transmit VLAN frames. Use other products.\r\n\r\nTo apply this setting, Windows which runs VPN Server must be rebooted. Do not forget to reboot it.
+SM_VLAN_MSG_2 The Windows Registry parameters which was enabling the VLAN transparency features on the network adapter "%S" are deleted from the Registry.\r\n\r\nIf you did a Jumbo Frame enable settings last time, undo such changes manually.\r\n\r\nTo apply this setting, Windows which runs VPN Server must be rebooted. Do not forget to reboot it.
+SM_VLAN_NOTHING There are no network adapters which VLAN Transparency Setting Tool supports on the computer "%S".\r\n\r\nHowever, some network adapters are capable to transmit VLAN tagged packets by default, or can be configured to perform VLAN tagged packets by specific configuration utility provided by the vendor.\r\nBy using such network adapters, you have to configure such settings by yourself manually.
+SM_SERVER_ADMIN_MSG VPN Server / Bridge "%S"
+SM_ETHERIP_COLUMN_0 ISAKMP Phase 1 ID
+SM_ETHERIP_COLUMN_1 Virtual Hub Name
+SM_ETHERIP_COLUMN_2 User Name
+SM_ETHERIP_ADD_OK A new EtherIP / L2TPv3 client setting was registered.
+SM_IPSEC_SETUP_QUESTION This VPN Server has a function to accept IPsec / L2TP / EtherIP / L2TPv3 compatible VPN clients or VPN router products.\r\n\r\nYou can allow the VPN Server to accept connections from smartphones such as iPhone, iPad, Android, or standard VPN client functions on Mac OS X or Windows.\r\n\r\nDo you want to set up the IPsec?\r\n(IPsec settings can be configured by clicking "IPsec / L2TP Settings" button any time later.)
+SM_OPENVPN_CONFIG_SAVE_OK The ZIP file '%s' which contains the setting files for OpenVPN.\r\n\r\nOpen this ZIP file to extract sample configuration files for OpenVPN which can be used immediately and easily.\r\nYou might be required to revise the configuration file a little.\r\n\r\nFor details please read the 'readme.txt' file in the ZIP file.\r\n\r\nDo you want to open this ZIP file now?
+SM_OPENVPN_CONFIG_SAVE_NG Failed to save the ZIP file '%s'.
+SM_OPENVPN_CONFIG_OPEN_NG Failed to open the ZIP file '%s'. Please open this file manually.
+SM_DDNS_IPV4_ERROR Unable to reach the IPv4 DDNS Server.
+SM_DDNS_IPV6_ERROR Unable to reach the IPv6 DDNS Server.
+SM_DDNS_FQDN_EMPTY (None)
+SM_DDNS_OK_MSG The Dynamic DNS hostname: %S%S\r\n\r\nYou can access to the below IP address by specifying the above DNS hostname.\r\n\r\nIPv4 Address: %s\r\nIPv6 Address: %s\r\n\r\nYou can also specify the following special forms of hostnames to specify IPv4 or IPv6 as the address-type explicitly.\r\n\r\nHostname for IPv4: %S.v4%S\r\nHostname for IPv6: %S.v6%S\r\n
+SM_DDNS_OK_TITLE Dynamic DNS Function
+SM_DDNS_OK_MSG2 The Dynamic DNS hostname was changed to '%S'.\r\n\r\nClick Hint to read additional information.
+SM_IPSEC_PSK_TOO_LONG The pre-shared key (PSK) has 10 or more letters.\r\n\r\nIt is reported that several versions of Google Android has a serious bug with 10 or more letters pre-shared key.\r\nTherefore 9 or less letters are recommended for pre-shared key.\r\n\r\nDo you want to modify the pre-shared key?
+SM_ADVANCED_REDIRECT_URL_HINT_TITLE How to Use Advanced HTTP Redirection Function
+SM_ADVANCED_REDIRECT_URL_HINT Advanced HTTP Redirection (For Experts)\r\n\r\nThe string "<INFO>" is a place holder. It can embedded on the URL of redirection.\r\n\r\nEmbedded URL Example:\r\nhttp://www.google.com/search?q=<INFO>|secret\r\n\r\nWhen the client is being redirected, the actual destination URL of redirection will be replaced as follows.\r\n\r\nUsername|Session ID|IP Address|Date and Time|Hash Value\r\n\r\\nAfter Replacement Example: zurukko|SID-ZURUKKO-123|219.117.219.154|20131117100354|99707160AFE7A454042B2C47B064112D652452D7\r\n\r\nThe details of each fields are described as following.\r\n\r\nUsername: The username using for the current VPN Session will be placed.\r\n\r\nSession ID: The Session ID of the VPN Session will be placed.\r\n\r\nDate and Time: 14-digits will be placed as 'YYYYMMDDHHMMSS' format (Time zone is UTC).\r\n\r\nHash Value: A 40-characters hexadecimal strings which represent 20 bytes binary data. The binary data is the result of SHA-1 hash function to the temporary string. The temporary string is the combination of the bit-array of the above fields plus the secret string after the '|' symbol in the redirection URL. (In the above example, "secret" is the secret string.) If there are no '|' symbols in the URL, no hash value will be appended.\r\n\r\nThe Purpose of Hash Value: The secret string is effective as the secret key. Thanks to the secret key, the CGI program which receives the query strings on the redirected URL can verify the integrity of the parameters included in the URL.\r\n
+SM_ADVANCED_REDIRECT_URL_MSG An URL must start with "http://" or "https://"
+SM_DISABLE_DDNS_HINT_CAPTION Disable Dynamic DNS Function
+SM_DISABLE_DDNS_HINT To disable the Dynamic DNS Function, modify the configuration file of VPN Server.\r\n\r\nThe "declare root" directive has the "declare DDnsClient" directive. In this directive, you can switch "bool Disable" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled.\r\n
+SM_REGENERATE_CERT_MSG The certificate of VPN Server is being replaced to the new one.\r\n\r\nThis will affect all VPN Clients which are configured to verify the certificate of VPN Server.\r\nDo you want to continue?
+SM_DDNS_SERVER_CERT_MSG The DDNS hostname was changed to "%S".\r\n\r\nIf you are planning to use Microsoft SSTP VPN to connect to the VPN Server from Windows Vista or greater versions of Windows with specifying the DDNS hostname as the destination of VPN Server, the destination hostname of the VPN Server must exactly match to the CN (Common Name) field on the certificate of VPN Server due to the security.\r\n\r\nDo you want to regenerate the server certificate in order to match the CN value to "%S"?\r\n(Click No to keep using the current server certificate.)
+SM_DDNS_SERVER_CERT_OK The SSL certificate of VPN Server is now regenerated.\r\n\r\nWhen you make Microsoft SSTP VPN client connects to the VPN Server, you should specify the current DDNS hostname "%S" as the destination server hostname.\r\nYou have to also prepare the "Trusted Root Certificates" list on the Windows to add the certificate of this VPN Server beforehand.\r\n(To install a root certificate to Windows, open MMC and navigate to "Local Computer" in the "Certificates" applet. After that, you can import a certificate into the trusted root certification list.\r\n For details refer Microsoft's documents.)\r\n\r\nDo you want to save the new SSL certificate as a file in the X.509 format?
+SM_SETUP_STEP_SECURENAT This VPN Server / Bridge might be running as user-more, or by other limitations, the Virtual Hub and a physical network adapter cannot be bridged together. Instead, the SecureNAT function allows VPN Clients to communicate with other computers in the physical network. The SecureNAT function was enabled by default. You can configure or disable it.
+SM_SETUP_STEP_SECURENAT_TITLE Step 3. Bridge Virtual Hub and Physical Network
+SM_UPDATE_CHECK_TITLE_VPNSERVER %S VPN Server (on the host '%S')
+SM_UPDATE_CHECK_TITLE_VPNBRIDGE %S VPN Bridge (on the host '%S')
+SM_FACTORY_DEFAULT_WARNING This will perform a factory-reset on the VPN Server / Bridge.\r\nThe current configuration of VPN Server / Bridge will be erased, and the initial settings will be applied immediately.\r\nYou are recommended to make a backup copy of the current configuration before do a factory-reset.\r\n\r\nPress OK to perform a factory-reset. The VPN Server / Bridge will be rebooted. The current management connection will be disconnected, so please re-connect to the VPN Server / Bridge.\r\n\r\nPress Cancel to cancel the operation.
+SM_FACTORY_DEFAULT_PERFORMED The factory-reset operation is performing on the server.\r\n\r\nPress OK to exit the current session of VPN Server Manager.\r\nAfter exiting, please re-start the VPN Server Manager and connect to the VPN Server again.\r\nThen you will see the VPN Server is reset.
+SM_AZURE_STATUS_CONNECTED Status: Connected
+SM_AZURE_STATUS_NOT_CONNECTED Status: Not Connected
+SM_NO_BRIDGE_NICS No physical network adapters suitable for Local Bridge were found on the VPN server computer.\r\nIn order to create a Local Bridge, you have to install at least one physical network adapters on the computer.\r\nYou cannot use Wi-Fi adapters or 3G adapters for Local Bridge.\r\nPlease install a physical network adapter which is compatible to wired Ethernet.\r\n\r\nIf a recently-installed network adapter doesn't appear, once reboot the computer.\r\n\r\nIf the Local Bridge cannot be used anyway, you can use "SecureNAT Function" instead.\r\n\r\nIf you have a certain reason to use unusual network adapters (i.e. Wi-Fi adapters, 3G adapters or virtual adapters), set the "ShowAllInterfaces" variable on the "LocalBridgeList" directive to "true" and restart the VPN Server. Then such devices will appear on the list. (For advanced Windows users only.)
+
+
+# Concerning User-mode Router Administration Tools
+NM_TITLE deleted
+NM_CONNECT_TITLE deleted
+NM_STATUS_TAG Connection status: %s
+NM_OFFLINE You are not connected to any VPN Servers.
+NM_CONNECTING Connecting to VPN Server
+NM_CONNECTED Connected to VPN Server "%S"
+NM_CONNECT_ERROR Error number %u (%s)
+NM_ACCOUNT_TITLE deleted
+NM_STATUS User-mode Router Status
+NM_STATUS_CONNECT Connection Status
+NM_STATUS_TCP NAT TCP/IP Sessions
+NM_STATUS_UDP NAT UDP/IP Sessions
+NM_STATUS_ICMP NAT ICMP Sessions
+NM_STATUS_DNS NAT DNS Sessions
+NM_STATUS_DHCP Allocated DHCP Clients
+NM_INFO User-mode Router information
+NM_INFO_PRODUCT_NAME Product Name
+NM_INFO_VERSION_STR Version information
+NM_INFO_BUILD_INFO Build information
+NM_INFO_HOSTNAME Host name
+NM_NAT_ID ID
+NM_NAT_PROTOCOL Protocol
+NM_NAT_SRC_HOST Source Host
+NM_NAT_SRC_PORT Source Port
+NM_NAT_DST_HOST Destination Host
+NM_NAT_DST_PORT Destination Port
+NM_NAT_CREATED Session Created On
+NM_NAT_LAST_COMM Last Communication Time
+NM_NAT_SIZE Receive / Send Size
+NM_NAT_TCP_STATUS TCP Connection Status
+NM_NAT_PROTO_TCP TCP/IP
+NM_NAT_PROTO_UDP UDP/IP
+NM_NAT_PROTO_DNS DNS
+NM_NAT_PROTO_ICMP ICMP
+NAT_TCP_CONNECTING Connecting
+NAT_TCP_SEND_RESET Disconnecting
+NAT_TCP_CONNECTED Connected
+NAT_TCP_ESTABLISHED Running
+NAT_TCP_WAIT_DISCONNECT Disconnecting
+DHCP_DHCP_ID ID
+DHCP_LEASED_TIME Leased at
+DHCP_EXPIRE_TIME Expires at
+DHCP_MAC_ADDRESS MAC Address
+DHCP_IP_ADDRESS Allocated IP
+DHCP_HOSTNAME Client Host Name
+NM_PASSWORD_MSG The administration password was set.
+
+
+# Concerning version information
+ABOUT_CAPTION About %s
+BETA_EXPIRES Because the currently installed SoftEther VPN software is a beta version, you cannot use it after the provision of a newer beta version of full version. \r\nAccess http://selinks.org/ and get the latest version of SoftEther VPN software.
+
+
+# Concerning the saving of logs
+# (Common log)
+L_YES Yes
+L_NO No
+L_LINE ------------------------------------------------------
+
+# (Server log)
+LS_START_UTF8 Log Messages are written with UTF-8 Encoding Format.
+LS_START_1 The SoftEther VPN Server was started.
+LS_START_2 %S %S
+LS_START_3 %S
+LS_END_1 The SoftEther VPN Server Engine was successfully shutdown.
+LS_END_2 The Server Engine shutdown processing has started.
+LS_STOP_ALL_LISTENER All TCP listeners will be stopped.
+LS_STOP_ALL_LISTENER_2 All TCP listeners were stopped.
+LS_STOP_ALL_HUB Stopping all Virtual Hubs.
+LS_STOP_ALL_HUB_2 All Virtual Hubs were stopped.
+LS_STOP_CEDAR Shutting down the Cedar communication module.
+LS_STOP_CEDAR_2 The Cedar communication module was shut down.
+LS_STOP_FARM_MEMBER Disconnecting connection to the cluster controller.
+LS_STOP_FARM_MEMBER_2 Connection with the cluster controller was disconnected.
+LS_STOP_FARM_CONTROL Cluster controller is stopping.
+LS_STOP_FARM_CONTROL_2 Cluster controller has stopped.
+LS_ENUM_ETHERNET_1 Ethernet device was enumerated.
+LS_ENUM_ETHERNET_2 Device %u: "%S"
+LS_LOAD_CONFIG_1 Loading the configuration file.
+LS_LOAD_CONFIG_2 The configuration file was loaded.
+LS_LOAD_CONFIG_3 Configuration file does not exist. Attempting to start using initial settings.
+LS_INIT_SAVE_THREAD Starting the automatically saving background task. The interval between auto-saves is %u seconds. You can change the interval by changing the parameter AutoSaveConfigSpan in the configuration file.
+LS_BAD_CONFIG The contents of the configuration file is invalid. The loading process was terminated.
+LS_LISTENER_START_1 TCP Listener (port %u) is starting.
+LS_LISTENER_START_2 TCP Listener (port %u) was started. Now listening for connection from client.
+LS_LISTENER_START_3 Unable to set port to Listen status for TCP Listener (port %u). Attempting at fixed intervals until successful.
+LS_LISTENER_ACCEPT On the TCP Listener (Port %u), a Client (IP address %S, Host name "%S", Port number %u) has connected.
+LS_LISTENER_DISCONNECT The connection with the client (IP address %S, Port number %u) was disconnected.
+LS_LISTENER_DOS A DoS attack on the TCP Listener (port %u) was detected. The connecting source IP address is %S, port number is %u. This connection will be forcefully disconnected now.
+LS_LISTENER_MAXUEC The TCP listener is temporary suspending to accept new inward connections because the number of pending TCP connections exceeded %u. (Current value = %u)
+LS_LISTENER_STOP_1 TCP Listener (port %u) is stopping.
+LS_LISTENER_STOP_2 TCP Listener (port %u) has stopped.
+LS_HUB_START Virtual Hub "%S" was started.
+LS_HUB_STOP Virtual Hub "%S" was stopped.
+LS_HUB_MAC The MAC address of Virtual Hub "%S" is "%S".
+LS_NODE_INFO_TAG Client product name: "%S", Client version: %u, Client build number: %u, Server product name: "%S", Server version: %u, Server build number: %u, Client OS name: "%S", Client OS version: "%S", Client product ID: "%S", Client host name: "%S", Client IP address: "%S", Client port number: %u, Server host name: "%S", Server IP address: "%S", Server port number: %u, Proxy host name: "%S", Proxy IP address: "%S", Proxy port number: %u, Virtual Hub name: "%S", Client unique ID: "%S"
+LS_CONNECTION_START_1 For the client (IP address: %S, host name: "%S", port number: %u), connection "%S" has been created.
+LS_CONNECTION_END_1 Connection "%S" was terminated.
+LS_SSL_START SSL communication for connection "%S" was started. The encryption algorithm name is "%S".
+LS_CONNECTION_ERROR Connection "%S" terminated by the cause "%s" (code %u).
+LS_FARMMEMBER_NOT_ADMIN Connection "%S": The server is a cluster member but the client attempted to directly connect to the Virtual Hub "%S" while not being administrator user "%S". The user name provided by the client is "%S". Access is refused.
+LS_HUB_NOT_FOUND Connection "%S": Virtual Hub "%S" that the client is trying to connect to does not exist on the server.
+LS_IP_DENIED Connection "%S": The source IP address "%S" of the client was refused based on the Source IP Address Limit List defined for the Virtual Hub.
+LS_LICENSE_ERROR Connection "%S": Because a license-related error occurred, the client is unable to connect to the server.
+LS_BETA_EXPIRES This beta version of SoftEther VPN Server is expired. The beta version period of use has expired. Download a new beta version or full version from http://selinks.org/.
+LS_TICKET_1 A new client authentication ticket was issued for cluster member "%S". Virtual Hub "%S", User name "%S" ("%S"), Session name "%S", Ticket "%S"
+LS_TICKET_2 A new client authentication ticket was received from the cluster controller. Virtual Hub "%S", User name "%S" ("%S"), Session name "%S", Ticket "%S", Expiration %u seconds
+LS_ENUM_HUB Connection "%S": %u Virtual Hub servers have been enumerated on this server.
+LS_FARM_ACCEPT_1 Connection "%S": This server received a cluster control connection request but this server is not a cluster controller.
+LS_FARM_ACCEPT_2 Connection "%S": This server received a cluster control connection request but the authentication password was incorrect and connection was refused.
+LS_FARM_ACCEPT_3 Connection "%S": This server received a cluster control connection request. Authentication was successful.
+LS_FARM_SERV_START Connection with a cluster member was established. IP address: %S, Host name: "%S"
+LS_FARM_SERV_END Connection with cluster member "%S" was deleted.
+LS_FARM_CONNECT_1 Connection to cluster controller "%S" was started.
+LS_FARM_CONNECT_2 Connection to cluster controller "%S" was refused. Error: %s (code %u)
+LS_FARM_CONNECT_3 TCP connection to cluster controller "%S" failed. Continuing to attempt connection in intervals of %u seconds until connection is successful.
+LS_FARM_DISCONNECT Connection to the cluster controller was stopped.
+LS_FARM_START Connected to cluster controller. Operation as cluster member is starting.
+LS_LICENSE_NOT_VPNSERVER Connection "%S": License error occurred. A connection attempt was made by the VPN Client while the VPN Server product license is not registered.
+LS_LICENSE_NOT_VPNCLUSTER Connection "%S": License error occurred. The license registered on this VPN Server is of a type that prevents the use of the current clustering function and a VPN Client has attempted connection while operating in Cluster mode. You must restart the VPN Server.
+LS_LICENSE_VIOLATION Connection "%S": A license violation has occurred on the VPN Server and connections are not being received.
+LS_LICENSE_VIOLATION_DETECTED A license violation was detected. A different VPN Server is operating with the same server ID "%I64u" as this VPN Server. It is possible that there are two or more VPN Servers in the cluster that are using the same license. Check the license information of each VPN Server.
+
+
+# (OpenVPN Logs)
+LO_PREFIX_RAW OpenVPN Module:
+LO_PREFIX_SESSION OpenVPN Session %u (%r:%u -> %r:%u):
+LO_PREFIX_CHANNEL OpenVPN Session %u (%r:%u -> %r:%u) Channel %u:
+LO_NEW_CHANNEL A new channel is created.
+LO_CHANNEL_ESTABLISHED_NEWKEY The channel is established. (Trigger: Re-key completion.)
+LO_OPTION_STR_RECV Option Strings Received: "%S"
+LO_OPTION_STR_SEND Option Strings to Send: "%S"
+LO_NEW_SESSION A new session is created. Protocol: %S
+LO_INITIATE_REKEY The re-keying process is started.
+LO_CHANNEL_ESTABLISHED The channel becomes the established state.
+LO_PUSH_REPLY The full strings replied: "%S"
+LO_CHANNEL_FAILED Failed to connect a channel.
+LO_CHANNEL_DISCONNECTED_BY_HUB This OpenVPN channel is being terminated because the administrator of the Virtual Hub disconnected this the VPN Session.
+LO_DELETE_SESSION Deleting the session.
+LO_START The OpenVPN Server Module is starting.
+LO_STOP The OpenVPN Server Module is stopped.
+
+
+# (IPsec Logs)
+LI_PREFIX_RAW IPsec Module:
+LI_PREFIX_CLIENT IPsec Client %u (%S:%u -> %S:%u):
+LI_PREFIX_IKE IPsec IKE Session (IKE SA) %u (Client: %u) (%S:%u -> %S:%u):
+LI_PREFIX_IPSEC IPsec ESP Session (IPsec SA) %u (Client: %u) (%S:%u -> %S:%u):
+LI_START The IPsec ver 2.0 (ISAKMP/IKEv1) processing module is started.
+LI_STOPPING The IPsec ver 2.0 (ISAKMP/IKEv1) processing module is now terminating...
+LI_STOP The IPsec ver 2.0 (ISAKMP/IKEv1) processing module is terminated.
+LI_NUM_IPSEC_SA The number of still-alive IPsec SAs was %u.
+LI_NUM_IKE_SA The number of still-alive IKE SAs was %u.
+LI_NUM_IKE_CLIENTS The number of still-alive IPsec Clients was %u.
+LI_L2TP_SERVER_STARTED The L2TP Server Module is started.
+LI_ETHERIP_SERVER_STARTED The EtherIP Server Module is started. The Session ID of the EtherIP Session: %u
+LI_DELETE_IKE_CLIENT This IPsec Client is deleted.
+LI_DELETE_IKE_SA This IKE SA is deleted.
+LI_DELETE_IPSEC_SA This IPsec SA is deleted.
+LI_START_QM_FROM_SERVER The server initiates a QuickMode negotiation.
+LI_START_QM_FROM_CLIENT The client initiates a QuickMode negotiation.
+LI_QM_DH_ERROR Failed to calculate a Diffie-Hellman algorithm.
+LI_NEW_IKE_CLIENT A new IPsec client is created.
+LI_NEW_IKE_SA A new IKE SA (%s) is created. Initiator Cookie: 0x%I64X, Responder Cookie: 0x%I64X, DH Group: %S, Hash Algorithm: %S, Cipher Algorithm: %S, Cipher Key Size: %u bits, Lifetime: %u Kbytes or %u seconds
+LI_TAG_MAINMODE Main Mode
+LI_TAG_AGGRESSIVE Aggressive Mode
+LI_NEW_IPSEC_SA A new IPsec SA (Direction: %s) is created. SPI: 0x%X, DH Group: %S, Hash Algorithm: %S, Cipher Algorithm: %S, Cipher Key Size: %u bits, Lifetime: %u Kbytes or %u seconds
+LI_TAG_SERVER_TO_CLIENT Server -> Client
+LI_TAG_CLIENT_TO_SERVER Client -> Server
+LI_IPSEC_SA_SPI_SET The SPI which was pending is now set. New SPI: 0x%X
+LI_IPSEC_SA_ESTABLISHED This IPsec SA is established between the server and the client.
+LI_IKE_SA_ESTABLISHED This IKE SA is established between the server and the client.
+LI_IPSEC_NO_TRANSFORM There are no acceptable transform proposals from the client for establishing an IPsec SA.
+LI_IKE_NO_TRANSFORM There are no acceptable transform proposals from the client for establishing an IKE SA.
+LI_IKE_NO_NAT_T The connection cannot be accepted because this VPN client is not compatible with IPsec NAT Traversal (RFC 3947 Negotiation of NAT-Traversal in the IKE or draft-ietf-ipsec-nat-t-ike).
+LI_SET_CLIENT_ID The client ID which this client presented in the establishing phase is "%S".
+LI_CLIENT_MERGE This client (Client %u) and the other client (Client %u) is the same client. So they are merged to the client %u.
+LI_CLIENT_UPDATE The port number information of this client is updated.
+
+
+# (EtherIP Log)
+LE_PREFIX EtherIP / L2TPv3 Session %u (%S:%u -> %S:%u):
+LE_START_MODULE The EtherIP / L2TPv3 Module is started.
+LE_STOP The EtherIP / L2TPv3 Module is stopped.
+LE_NO_SETTING Error: No EtherIP / L2TPv3 setting entries for the Client ID "%S" is registered on the VPN Server. Please register an entry of a EtherIP / L2TPv3 setting on the VPN Server beforehand.
+LE_START_IPC The internal pipe was created between the EtherIP / L2TPv3 module to the Virtual Hub "%S". The using username is "%S". The IPv4 TCP MSS (Max Segment Size) to be set is %u bytes.
+LE_IPC_CONNECT_ERROR The connection from the EtherIP / L2TPv3 module to the Virtual Hub "%S" failed. Error: %u : %s
+LE_IPC_CONNECT_OK The connection from the EtherIP / L2TPv3 module to the Virtual Hub "%S" succeeded.
+LE_RECONNECT Settings of EtherIP / L2TPv3 was changed. Internal pipes is now being deleted and auto-reconnecting.
+
+
+# (PPP Log)
+LP_PREFIX %S%SPPP Session [%S:%u]:
+LP_CONNECTED A new PPP session (Upper protocol: %S) is started. IP Address of PPP Client: %S (Hostname: "%S"), Port Number of PPP Client: %u, IP Address of PPP Server: %S, Port Number of PPP Server: %u, Client Software Name: "%S", IPv4 TCP MSS (Max Segment Size): %u bytes
+LP_DISCONNECTED The PPP session is disconnected.
+LP_PAP_REJECTED The client denied to accept the authentication protocol "PAP" (Password Authentication Protocol, a clear-text password authentication protocol). Enable PAP on the client-side and retry.
+LP_PAP_MSCHAPV2_REJECTED The client denied to accept both the "PAP" (Password Authentication Protocol, a clear-text password authentication protocol) and MS-CHAP v2 Protocol. Enable either PAP or MS-CHAP v2 on the client-side and retry.
+LP_DISCONNECTED_ABNORMAL A PPP protocol error occurred, or the PPP session was disconnected.
+LP_NEXT_PROTOCOL_IS_NOT_PAP An invalid protocol (Protocol Number: 0x%x) with non-PAP (Password Authentication Protocol) control packet.
+LP_PAP_FAILED "PAP" (Password Authentication Protocol, a clear-text password authentication protocol) user authentication failed.
+LP_MSCHAPV2_FAILED "MS-CHAP v2" (Microsoft Challenge and Response Protocol Version 2.0) user authentication failed.
+LP_NEXT_PROTOCOL_IS_NOT_IPCP An invalid protocol (Protocol Number: 0x%x) with non-IPCP (IP Configuration Protocol) control packet.
+LP_DATA_TIMEOUT A timeout on the PPP data transmitting occurred. The PPP client might be disconnected from the network.
+LP_CONTROL_TIMEOUT A timeout on the PPP control transmitting occurred. No responses from the PPP client.
+LP_VPN_SESSION_TERMINATED The PPP session is disconnected because the VPN Session was disconnected by the administrator.
+LP_UPPER_PROTOCOL_DISCONNECTED The PPP session is disconnected because the upper-layer protocol "%S" was disconnected.
+LP_NORMAL_TERMINATE The PPP session is disconnected by the VPN Client's disconnecting request.
+LP_IP_ADDRESS_NOT_DETERMIND The VPN Client sent a packet though an IP address of the VPN Client hasn't been determined.
+LP_DHCP_REQUEST_TRYING Trying to request an IP address from the DHCP server.
+LP_DHCP_REQUEST_OK An IP address is assigned. IP Address of Client: %S, Subnet Mask: %S, Default Gateway: %S, Domain Name: "%S", DNS Server 1: %S, DNS Server 2: %S, WINS Server 1: %S, WINS Server 2: %S, IP Address of DHCP Server: %S, Lease Lifetime: %u seconds
+LP_DHCP_REQUEST_NG Acquiring an IP address from the DHCP server failed. To accept a PPP session, you need to have a DHCP server. Make sure that a DHCP server is working normally in the Ethernet segment which the Virtual Hub belongs to. If you do not have a DHCP server, you can use the Virtual DHCP function of the SecureNAT on the Virtual Hub instead.
+LP_DHCP_INFORM_TRYING Acquiring the IP networking information such as subnet mask and the default gateway information from the DHCP server.
+LP_DHCP_INFORM_OK The networking information was acquired. Subnet Mask: %S, Default Gateway: %S, Domain Name: "%S", DNS Server 1: %S, DNS Server 2: %S, WINS Server 1: %S, WINS Server 2: %S, IP Address of DHCP Server: %S
+LP_DHCP_INFORM_NG Acquiring the networking information from the DHCP server failed. To accept a PPP session, you need to have a DHCP server. Make sure that a DHCP server is working normally in the Ethernet segment which the Virtual Hub belongs to. If you do not have a DHCP server, you can use the Virtual DHCP function of the SecureNAT on the Virtual Hub instead.
+LP_SET_IPV4_PARAM The IP address and other network information parameters are set successfully. IP Address of Client: %S, Subnet Mask: %S, Default Gateway: %S, DNS Server 1: %S, DNS Server 2: %S, WINS Server 1: %S, WINS Server 2: %S
+
+
+# (Virtual Hub log)
+LH_ONLINE The Virtual Hub is now online.
+LH_OFFLINE The Virtual Hub is now offline.
+LH_CONNECT_CLIENT The connection "%S" (IP address: %S, Host name: %S, Port number: %u, Client name: "%S", Version: %S, Build: %u) is attempting to connect to the Virtual Hub. The auth type provided is "%s" and the user name is "%S".
+LH_AUTH_UNKNOWN Unknown auth type.
+LH_AUTH_ANONYMOUS Anonymous authentication
+LH_AUTH_PASSWORD Password authentication
+LH_AUTH_PLAIN_PASSWORD External server authentication
+LH_AUTH_CERT Certificate authentication
+LH_AUTH_TICKET Ticket authentication
+LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" was specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied.
+LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" was specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, such an external user-authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
+LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" was specified as Certificate Authentication. However, the Certificate Authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
+LH_AUTH_OK Connection "%S": Successfully authenticated as user "%S".
+LH_AUTH_OK_CERT The Virtual Hub's Security Account Manager has received the following certificate from the VPN Client and accepted its contents as the certificate for when user "%S" logs in: %s
+LH_AUTH_NG_CERT The Virtual Hub's Security Account Manager has received the following certificate but has refused its contents as the certificate for when user "%S" logs in because this certificate's contents matches the contents that are registered in the Virtual Hub's certificates revocation list: %s
+LH_AUTH_NG Connection "%S": User authentication failed. The user name that was provided was "%S".
+LH_LOCAL_ONLY Connection "%S": The remote login was refused because the password for user "%S" is blank.
+LH_POLICY_ACCESS_NG Connection "%S": Access was refused to user "%S" based on the security policy.
+LH_USER_EXPIRES Connection "%S": Access was refused to user "%S" because the expiration date has expired.
+LH_CLIENT_VERSION_OLD Connection "%S": The build number of the VPN Client is %u. Only the build %u or latest version of VPN Client is granted to access the VPN Server.
+LH_CLIENT_ID_REQUIRED Connection "%S": The Client ID which was specified by the VPN Client is %u. However, this Virtual Hub has the RequiredClientId value set to %u.
+LH_FARM_SELECT_1 Connection "%S": The cluster controller is deciding the destination cluster member of this client.
+LH_FARM_SELECT_2 Connection "%S": Failed to decide the destination cluster member server.
+LH_FARM_SELECT_3 Connection "%S": This current VPN Server was decided as the destination cluster member server. Proceeding to receive connection.
+LH_FARM_SELECT_4 Connection "%S": The server "%S" was decided as a destination cluster member server. Instructing clients to redirect connection to this server.
+LH_MAX_SESSION Connection "%S": The maximum number of sessions (%u) that can be set by the Virtual Hub was reached. Unable to create a new session.
+LH_MAX_SESSION_CLIENT Connection "%S": The maximum number of client sessions (%u) that can be set by the Virtual Hub was reached. Unable to create a new session.
+LH_MAX_SESSION_BRIDGE Connection "%S": The maximum number of bridge sessions (%u) that can be set by the Virtual Hub was reached. Unable to create a new session.
+LH_MAX_SESSION_2 Connection "%S": The maximum number of sessions (%u) that can be managed by a VPN Server was reached. Unable to create a new session.
+LH_NEW_SESSION Connection "%S": The new session "%S" was created. (IP address: %S, Port number: %u, Physical underlying protocol: "%S")
+LH_SET_SESSION Session "%S": The parameter was set. Max number of TCP connections: %u, Use of encryption: %s, Use of compression: %s, Use of Half duplex communication: %s, Timeout: %u seconds.
+LH_NODE_INFO Session "%S": VPN Client details: (%s)
+LH_INVALID_SIGNATURE Session "%S": The connected client sent invalid protocol data. Unable to establish normal communication with client. First check for problems with the connections and cabling of the network connecting the client and the server and then check there is not a special transparent packet re-writing device installed.
+LH_END_SESSION Session "%S": The session was terminated. The statistical information is as follows: Total outgoing data size: %I64u bytes, Total incoming data size: %I64u bytes.
+LH_BCAST_STORM Session "%S": A large volume of broadcast packets was detected. There are cases where packets are discarded based on the policy. The source MAC address is %S, the source IP address is %S, the destination IP address is %S. The number of broadcast packets is equal to or larger than %u items per 1 second (note this information is the result of mechanical analysis of part of the packets and could be incorrect).
+LH_DHCP_FORCE Session "%S": The packet was discarded because it was attempting to use the IP address %S, which is not a DHCP server allocated IP address.
+LH_MAC_LIMIT Session "%S": An attempt to assign a new MAC address "%S" was made but %u MAC addresses have already been assigned for this service. According to the security policy, this session is allowed to have a maximum of %u MAC addresses. The packet was discarded.
+LH_BRIDGE_LIMIT Session "%S": An attempt to assign a new MAC address "%S" was made but %u MAC addresses have already been assigned for this service. According to the security policy, this session is denied bridges and is therefore allowed to hold no more than %u MAC addresses. The packet was discarded.
+LH_MAC_REGIST Session "%S": A new MAC address "%S" was assigned.
+LH_MAC_REGIST_VLAN Session "%S": A new MAC address "%S" (VLAN ID: %u) was assigned.
+LH_IP_LIMIT Session "%S": An attempt to assign a new IP address %S was made but %u IP addresses have already been assigned for this service. According to the security policy, this session is allowed to have a maximum of %u IP addresses. The packet was discarded.
+LH_ROUTING_LIMIT Session "%S": An attempt to assign a new IP address %S was made but %u IP addresses have already been assigned for this service. According to the security policy, this session is denied routing and is therefore allowed to hold no more than %u IP addresses. The packet was discarded.
+LH_IP_CONFLICT Session "%S": An attempt to use the IP address %S was made but this IP address is already being used by another session "%S" (MAC Address: "%S"). The security policy for this session denies duplication of IP addresses that are used by other sessions. The packet was discarded. Detailed Information: CreatedTime=%I64u, UpdatedTime=%I64u, DhcpAllocated=%u, Now=%I64u
+LH_NO_SERVER Session "%S": A TCP/IP connection request (from %S:%u to %S:%u) was made to this session but because the security policy denies operation as a server, the packet was discarded.
+LH_NO_DHCP Session "%S": Host %S on this session sent a packet that allocates an IP address as a DHCP server for host %S on another session, but this session's security policy denies operation as a DHCP server. The packet was discarded.
+LH_REGIST_DHCP Session "%S": The DHCP server of host "%S" (%S) on this session allocated, for host "%S" on another session "%S", the new IP address %S.
+LH_BRIDGE_1 Session "%S": A Local Bridge connection to physical Ethernet interface "%S" was started.
+LH_BRIDGE_2 Session "%S": Because communication failed to be established with physical Ethernet interface "%S", the Local Bridge was stopped.
+LH_SET_MTU Session "%S": The physical Ethernet interface "%S" has an MTU value set to %u. It is necessary to send and receive an Ethernet packet which has %u bytes. The MTU is now changed to %u.
+LH_SET_MTU_ERROR Session "%S": The physical Ethernet interface "%S" has an MTU value set to %u. It is necessary to send and receive an Ethernet packet which has %u bytes. However, changing the MTU to %u failed. This physical Ethernet interface or device driver might be unable to process an Ethernet packet which has more 1,514 bytes (payload size: 1,500 bytes). In such case, the larger tagged-VLAN packets than 1,514 bytes cannot be transmitted. You should replace the current physical Ethernet adapter to another which supports Jumbo Frames. You can also try to update the device driver. Another possible method is to enable Jumbo Frames on the operating system or device driver settings.
+LH_START_BRIDGE The Local Bridge connection "%S" was started. The bridge session "%S" was created.
+LH_STOP_BRIDGE The Local Bridge connection "%S" was stopped.
+LH_LINK_START The Cascade Connection "%s" was established. The Cascade session "%S" was created.
+LH_LINK_STOP The Cascade Connection "%s" was stopped.
+LH_NAT_START SecureNAT was started. The SecureNAT session "%S" was created.
+LH_NAT_STOP SecureNAT stopped.
+LH_NAT_TCP_SUCCEED The connection to TCP session %u: Host "%S (%S)", Port %u was successful.
+LH_NAT_TCP_FAILED The connection to TCP session %u: Host "%S", Port %u failed.
+LH_NAT_TCP_DELETED The TCP session %u was deleted.
+LH_NAT_TCP_CREATED The TCP session %u was created. Connection source %S:%u, Connection destination %S:%u
+LH_NAT_UDP_DELETED The UDP session %u was deleted.
+LH_NAT_UDP_CREATED The UDP session %u was created. Connection source %S:%u, Connection destination %S:%u
+LH_NAT_DHCP_CREATED The DHCP entry %u was created. MAC address: %S, IP address: %S, host name: %S, expiration span: %u seconds
+LH_CHANGE_PASSWORD_1 The connection "%S" (IP address %S) connected to Virtual Hub in change password mode.
+LH_CHANGE_PASSWORD_2 Connection "%S": Changing of password failed. The specified user "%S" does not exist.
+LH_CHANGE_PASSWORD_3 Connection "%S": Changing of password failed. The auth type of user "%S" is not password authentication.
+LH_CHANGE_PASSWORD_4 Connection "%S": Changing of password failed. The old password of user "%S" is incorrect.
+LH_CHANGE_PASSWORD_5 Connection "%S": The password of user "%S" was changed.
+LH_CONNECT_1 Starting Cascade Connection "%s": connection number %u.
+LH_CONNECT_2 The Cascade Connection "%s" is connected. Session name: "%S"
+LH_CONNECT_ERROR The connection for Cascade Connection "%s" either was disconnected or it failed. Cause: %s (code %u)
+LH_POLICY_MONITOR_MODE Connection "%S": Because a user whose security policy denies permission for Monitoring Mode requested that Monitoring Mode be enabled and attempted to connect to a Virtual Hub, the connection was denied.
+LH_POLICY_BRIDGE_MODE Connection "%S": Because a user whose security policy denies both bridge connections and routing operations requested that bridge connections or routing operations be enabled and attempted to connect to the Virtual Hub, the connection was denied.
+LH_NOT_ENOUGH_CLIENT_LICENSE Connection "%S": This connection attempted to connect to the VPN Server using "client connection mode" but because this would have made the number of client connections on the entire server exceed the number of registered Client Connection Licenses, it was not possible to receive the connection for this connection. When the number of licenses for concurrent connections is insufficient, you must either disconnect another existing client connection or increase the number of licenses. There are currently %u registered Client Connection Licenses and the number of connections to servers was %u.
+LH_NOT_ENOUGH_BRIDGE_LICENSE Connection "%S": This connection attempted to connect to the VPN Server using "bridge connection mode" but because this would have made the number of bridge connections on the entire server exceed the number of registered Bridge Connection Licenses, it was not possible to receive the connection for this connection. When the number of licenses for concurrent connections is insufficient, you must either disconnect another existing client connection or increase the number of licenses. There are currently %u registered Bridge Connection Licenses and the number of connections to servers was %u.
+LH_TOO_MANY_MULTILOGINS Connection "%S": The user "%S" made a login attempt, but the security policy that applies to this user limits the maximum number of multiple logins to %u sessions. Currently the number of logins by this user is %u sessions and therefore the user was denied permission for a new VPN connection.
+LH_TOO_MANY_MULTILOGINS2 Connection "%S": The user "%S" made a login attempt, but this edition of the VPN Server permits the maximum number of multiple concurrent VPN sessions to %u sessions per user. Current number of the multiple concurrent VPN sessions of this users is %u, so no more concurrent VPN sessions cannot be permitted. If you want to support more number of multiple concurrent VPN sessions per user, please consider upgrading to Professional Edition or greater of the VPN Server.
+LH_PACKET_LOG_NO_LOG The edition of this VPN Server doesn't supports the packet logging function. No IP address nor TCP/UDP header data will be recorded. After you upgrade the edition of the VPN Server to Professional Edition or greater, all kinds of packet logs will be recorded in this file.
+LH_PACKET_LOG_NO_LOG_OSS The VPN Server is either Open-Source or Free version. It hasn't implemented the IP Address or TCP/UDP header data logging function. No IP address nor TCP/UDP header data are not be recorded here.
+LH_NO_RADIUS_SETTING The user "%S" is configured to use RADIUS authentication. However, there is no RADIUS authentication settings. The user cannot be authenticated.
+LH_KERNEL_MODE_START It has been detected that the Kernel-mode NAT for SecureNAT can be run on the interface "%S". The Kernel-mode NAT is starting. The TCP, UDP and ICMP NAT processings will be performed with high-performance via Kernel-Mode hereafter. The parameters of Kernel-mode NAT: IP Address = "%r", Subnet Mask = "%r", Default Gateway = "%r", Broadcast Address = "%r", Virtual MAC Address: "%S", DHCP Server Address: "%r", DNS Server Address: "%r"
+LH_KERNEL_MODE_STOP The Kernel-mode NAT on the interface "%S" for SecureNAT has been stopped.
+
+
+# (Administration log)
+LA_CONNECTED_1 Connection "%S" connected using server admin mode.
+LA_CONNECTED_2 Connection "%S" connected using Virtual Hub Admin Mode. The name of the Virtual Hub is "%S".
+LA_IP_DENIED Connection "%S" attempted to connect using administration mode from an IP address whose permission is denied by adminip.txt. Disconnecting.
+LA_ERROR Connection "%S" was unable to log in using administration mode. %s (Error code %u)
+LA_OK Connection "%S" successfully logged in using administration mode.
+LA_RPC_START Connection "%S" created a new remote procedure call session "%S" for the purpose of administration mode.
+LA_TAG_1 Administration mode [%S]:
+LA_TAG_2 Administration mode [%S] (Virtual Hub "%S"):
+LA_CREATE_LISTENER A new TCP listener (port number %u) was created.
+LA_DELETE_LISTENER TCP listener (port number %u) was deleted.
+LA_ENABLE_LISTENER TCP listener (port number %u) was enabled.
+LA_DISABLE_LISTENER TCP listener (port number %u) was disabled.
+LA_SET_SERVER_PASSWORD The server administrator password was set.
+LA_SET_FARM_SETTING The clustering setting was changed.
+LA_SET_SERVER_CERT The server certificates were set.
+LA_REGENERATE_SERVER_CERT The server certificate was re-generated. The new CN: "%S"
+LA_SET_SERVER_CIPHER A new encryption algorithm name for the server was set. The new encryption algorithm name is "%S".
+LA_CREATE_HUB A new Virtual Hub "%S" was created.
+LA_SET_HUB The Virtual Hub setting was changed.
+LA_DELETE_HUB The Virtual Hub "%S" was deleted.
+LA_SET_HUB_RADIUS The Virtual Hub's external RADIUS authentication server setting was changed.
+LA_DISCONNECT_CONN The client connection "%S" connected to the server was forcefully disconnected.
+LA_SET_HUB_ONLINE The Virtual Hub is now online.
+LA_SET_HUB_OFFLINE The Virtual Hub is now offline.
+LA_SET_SNAT_OPTION The SecureNAT option was set.
+LA_ENABLE_SNAT The SecureNAT function was enabled.
+LA_DISABLE_SNAT The SecureNAT function was disabled.
+LA_SET_HUB_LOG The log save setting was changed.
+LA_ADD_CA A registration of trusted root certificate was added.
+LA_DELETE_CA A registration of trusted root certificate was deleted.
+LA_CREATE_LINK The Cascade Connection "%s" was added.
+LA_SET_LINK The setting for Cascade Connection "%s" was changed.
+LA_SET_LINK_ONLINE The Cascade Connection "%s" is now online.
+LA_SET_LINK_OFFLINE The Cascade Connection "%s" is now offline.
+LA_DELETE_LINK The Cascade Connection "%s" was deleted.
+LA_RENAME_LINK The name of Cascade Connection "%s" was changed to "%s".
+LA_ADD_ACCESS An access list was added.
+LA_DELETE_ACCESS The access list was deleted.
+LA_SET_ACCESS_LIST The access list was updated. An access list of %u items was set.
+LA_SET_AC_LIST The Source IP Address Limit List was updated. Rule items for %u items were set.
+LA_CREATE_USER User "%S" was created.
+LA_SET_USER The setting of user "%S" was updated.
+LA_DELETE_USER User "%S" was deleted.
+LA_CREATE_GROUP Group "%S" was created.
+LA_SET_GROUP The setting of group "%S" was updated.
+LA_DELETE_GROUP Group "%S" was deleted.
+LA_DELETE_SESSION This session "%S" was forcefully disconnected.
+LA_SET_KEEP The server's Internet keep-alive setting was updated.
+LA_SET_SYSLOG The server's syslog send function setting was updated.
+LA_DELETE_BRIDGE The Local Bridge connection definition "%S" --> "%S" was deleted.
+LA_ADD_BRIDGE The Local Bridge connection definition "%S" --> "%S" was added.
+LA_REBOOT_SERVER There was a request to restart VPN Server.
+LA_GET_CONFIG The config file was read.
+LA_SET_CONFIG The config file was written. Restarting VPN Server.
+LA_SET_HUB_ADMIN_OPTION The administration option was set for Virtual Hub "%S".
+LA_SET_HUB_EXT_OPTION The Virtual Hub Extended Option was set for Virtual Hub "%S".
+LA_ADD_L3_SW The Virtual Layer 3 Switch "%S" was created on the server.
+LA_DEL_L3_SW The Virtual Layer 3 Switch "%S" was deleted from the server.
+LA_START_L3_SW The Virtual Layer 3 Switch "%S" was started.
+LA_STOP_L3_SW The Virtual Layer 3 Switch "%S" was stopped.
+LA_ADD_L3_IF The virtual interface for Virtual Hub "%S" was added to Virtual Layer 3 Switch "%S".
+LA_DEL_L3_IF The virtual interface for Virtual Hub "%S" was deleted from Virtual Layer 3 Switch "%S".
+LA_ADD_L3_TABLE The routing table for network "%S" was added to Virtual Layer 3 Switch "%S".
+LA_DEL_L3_TABLE The routing table for network "%S" was deleted from Virtual Layer 3 Switch "%S".
+LA_ADD_CRL A certificate was added to Certificate Revocation List.
+LA_DEL_CRL A certificate was edited in Certificate Revocation List.
+LA_SET_CRL A registered item in a registration of a list of invalid certificates was edited.
+LA_READ_LOG_FILE The log file on the server "%S" (log file "%S") was downloaded.
+LA_ADD_LICENSE_KEY A new license key "%S" was registered.
+LA_DEL_LICENSE_KEY An existing license (No. %u) was deleted.
+LA_SET_IPSEC_CONFIG The IPsec server setting was updated.
+LA_ADD_ETHERIP_ID A new EtherIP / L2TPv3 server setting (ID="%S") was added.
+LA_DEL_ETHERIP_ID The new EtherIP / L2TPv3 server setting (ID="%S") was deleted.
+LA_SET_OVPN_SSTP_CONFIG The OpenVPN and MS-SSTP VPN Server setting was updated.
+LA_DDNS_HOSTNAME_CHANGED The hostname of Dynamic DNS Function was changed to "%S".
+LA_SET_SPECIAL_LISTENER Special Listener enable / disable status is changed.
+
+# (Client log)
+LC_START_1 The SoftEther VPN Client Engine was started.
+LC_START_2 %S %S
+LC_START_3 %S
+LC_END The SoftEther VPN Client Engine was shut down.
+LC_LOAD_CONFIG_1 Loading configuration file...
+LC_LOAD_CONFIG_2 The configuration file was loaded.
+LC_LOAD_CONFIG_3 Configuration file does not exist. Applying the initial settings.
+LC_NEW_ACCOUNT A new VPN Connection Setting "%s" was created.
+LC_DELETE_ACCOUNT The VPN Connection Setting "%s" was deleted.
+LC_RENAME_ACCOUNT The name of VPN Connection Setting "%s" was changed to "%s".
+LC_CONNECT Connection processing for VPN Connection Setting "%s" was started.
+LC_CONNECT_1 VPN Connection Setting "%s": Connection operation starting (this is now %u times).
+LC_CONNECT_2 VPN Connection Setting "%s": Now connected. Session name: "%S"
+LC_CONNECT_ERROR VPN Connection Setting "%s": The connection either was disconnected or it failed. Cause: %s (code %u)
+LC_DISCONNECT Disconnecting the VPN Connection Setting "%s".
+LC_CREATE_VLAN A Virtual Network Adapter "%S" was created.
+LC_UPDATE_VLAN The Virtual Network Adapter "%S" driver was reinstalled.
+LC_DELETE_VLAN The Virtual Network Adapter "%S" was deleted.
+LC_SET_PASSWORD The password setting for connection to a client service was changed.
+LC_TAP_NOT_FOUND Cannot find the tun/tap driver for Mac OS X. Please install the tun/tap driver.
+
+# (Eraser log)
+LE_START Monitoring the directory "%S". If the amount of available free disk space becomes less than %S, the backup files for log files and configurations that are saved on the sub-directories of this directory will be automatically deleted in the order of oldest first. The amount of free disk space that determines when to start deletion can be modified by changing the "AutoDeleteCheckDiskFreeSpaceMin" item in the configuration file.
+LE_DELETE The free disk space was now less then %S so the old file "%S" was automatically deleted. The amount of free disk space that determines when to start deletion can be modified by changing the "AutoDeleteCheckDiskFreeSpaceMin" item in the configuration file.
+LE_NOT_ENOUGH_FREE <<WARNING>> If the free disk space becomes lower than %S, it will no longer be possible to automatically delete the old backup files of log files and configurations. We recommend that you immediately manually delete the unnecessary files on this computer and recover the necessary free disk space. When there is a very small amount of free disk space, computer operation can become unstable.
+
+# (Layer 3 Switch log)
+L3_SWITCH_START The Virtual Layer 3 Switch "%S" started. It will wait until the Virtual Hubs of all interfaces registered on this switch become online and then it will start operation.
+L3_SWITCH_ONLINE The Virtual Hubs of all interfaces of the Virtual Layer 3 Switch "%S" are online and the Virtual Layer 3 Switch has commenced Virtual Layer 3 Switch operation.
+L3_SWITCH_OFFLINE At least one Virtual Hub of an interface registered on Virtual Layer 3 Switch "%S" stopped, and Virtual Layer 3 Switch operation was stopped.
+L3_SWITCH_STOP The Virtual Layer 3 Switch "%S" terminated.
+
+
+# Concerning Microsoft.c
+MS_ETHERNET Ethernet Interface
+MS_TOKENRING Token Ring Interface
+MS_FDDI FDDI Interface
+MS_PPP PPP (Dialup or VPN)
+MS_LOOPBACK Loopback Interface
+MS_SLIP SLIP Interface
+MS_WLAN Wireless Network Interface
+MS_OTHER Unknown Other Interface
+MS_NON_OPERATIONAL Disabled
+MS_UNREACHABLE Not Connected
+MS_DISCONNECTED Not Connected
+MS_CONNECTING Connecting
+MS_CONNECTED Connected
+MS_OPERATIONAL Connected
+
+
+# Concerning Network Utility
+UT_SM_COLUMN_1 Item Name
+UT_SM_COLUMN_2 Value
+UT_SM_ST_TITLE Network Adapter Name
+UT_SM_ST_GUID GUID
+UT_SM_ST_TYPE Type
+UT_SM_ST_TYPE2 Physical Wired Ethernet
+UT_SM_ST_STATUS Status
+UT_SM_ST_MTU MTU
+UT_SM_ST_SPEED Link Speed
+UT_SM_ST_ADDRESS Physical Address
+UT_SM_ST_RECV_BYTES Incoming Bytes
+UT_SM_ST_RECV_BCASTS Incoming Broadcast Packets
+UT_SM_ST_RECV_UNICASTS Incoming Unicast Packets
+UT_SM_ST_SEND_BYTES Outgoing Bytes
+UT_SM_ST_SEND_BCASTS Outgoing Broadcast Packets
+UT_SM_ST_SEND_UNICASTS Outgoing Unicast Packets
+UT_SM_ST_IP IP Address %u
+UT_SM_ST_SUBNET Subnet Mask %u
+UT_SM_ST_GATEWAY Gateway %u
+UT_SM_ST_DHCP DHCP Server
+UT_SM_ST_DHCP_1 Lease Start
+UT_SM_ST_DHCP_2 Lease Limit date and time
+UT_SM_ST_WINS_1 WINS Server 1
+UT_SM_ST_WINS_2 WINS Server 2
+
+
+# Concerning EtherLogger Manager
+EM_TITLE SoftEther EtherLogger Manager
+EM_REMOTE_TITLE You can connect to and manage the SoftEther EtherLogger service. \r\nEnter the host name and IP address of the computer on which the EtherLogger service to be managed is operating. You can also concatenate the port number by using the ":" (colon).
+EM_MAIN_COLUMN_1 Network adapter name
+EM_MAIN_COLUMN_2 Status
+EM_MAIN_OK Operating
+EM_MAIN_ERROR Error
+EM_ADD_NEW Add new capture device
+EM_ADD_EDIT Edit capture settings
+EM_DELETE_CONFIRM Are you sure you want to delete capture setting "%S"?
+EM_NO_LICENSE_COLUMN Note:
+EM_NO_LICENSE Because not even one product license is registered, this SoftEther EtherLogger will not operate.
+
+EM_UNSUPPORTED Unable to use SoftEther EtherLogger on the operating system that this SoftEther EtherLogger is operating on. For the list of operating system that the SoftEther EtherLogger can be used on, please refer to the online documentation of the SoftEther EtherLogger.
+EM_WPCAP_REMOTE In order to use this SoftEther EtherLogger, you need to install WinPcap software. The software WinPcap is currently not installed on the server computer. \r\n\r\nTo continue the installation of the WinPcap software, you must start SoftEther EtherLogger Manager on the server computer that is running VPN Server and then while connected to localhost (location of your own computer), have the Local Bridge Function Setting window displayed. \r\nTo continue, first exit this management session, and then, after starting SoftEther EtherLogger Manager on the server computer, connect to localhost and continue the setting process.
+EM_WPCAP_ROOT In order to use this SoftEther EtherLogger, you need to install WinPcap software. \r\n\r\nTo continue the installation you must log in to this computer as a user with administrator privileges. \r\nLog on as an administrator and start the SoftEther VPN Server Manager again.
+EM_WPCAP_INSTALL In order to use this SoftEther EtherLogger, you need to install WinPcap software. The software WinPcap is currently not installed on the server computer. \r\n\r\nWinPcap is an easy-to-install free software that is bundled together with the VPN Server. \r\n\r\nDo you want to begin the installation of WinPcap?
+EM_WPCAP_REBOOT1 After WinPcap installation has completed, you must restart the computer before you use the SoftEther EtherLogger. \r\n\r\nAfter you restart the computer manually and start SoftEther EtherLogger, configure the settings again.
+EM_WPCAP_REBOOT2 After WinPcap is installed, you must restart the SoftEther EtherLogger service. \r\n\r\nIt only takes a short time to restart the SoftEther EtherLogger service, however all management sessions that are currently connected to the SoftEther EtherLogger will be disconnected. \r\nThis management session will also be disconnected, so you will need to reconnect to continue. \r\n\r\nDo you want to restart the SoftEther Ether Logger service?
+EM_RESOURCE Unable to read the WinPcap driver.
+
+
+###########################################################################
+# #
+# String data of dialog boxes in software #
+# #
+###########################################################################
+
+
+PREFIX D_SECURE
+CAPTION Access to %s - %S
+S_TITLE Access to %S
+S_DEVICE_INFO Device Name: %S\r\nManufacturer: %S
+IDS_STATIC1 Device Information
+S_WARNING Take care entering the PIN code because if you enter it incorrectly for a few times the device will be locked.
+IDOK &OK
+IDCANCEL Cancel
+S_PIN_CODE &PIN Code:
+
+
+PREFIX D_PKCSUTIL
+CAPTION PKCS#12 Write Utility
+S_TITLE ePass 1000 USB token PKCS#12 Write Utility
+STATIC1 By using this utility, you can write a PKCS#12 file (certificate file) of your choice to an ePass 1000 USB hardware security token. \r\n\r\nThe USB token that the certificate file is written in can be used for SoftEther VPN authentication.
+STATIC2 Write to PKCS#12 file
+STATIC3 To write an existing PKC#12 file to a USB token, click Write. \r\nNOTE: If a PKCS#12 certificate for SoftEther VPN is already stored in the USB token, it will be overwritten.
+B_WRITE &Write
+STATIC4 Erase PKCS#12 certificate from USB token.
+STATIC5 You can erase the certificate data from a USB token on which a PKCS#12 certificate for SoftEther VPN is already stored.
+B_ERASE &Erase
+IDCANCEL E&xit Utilities
+S_COPYRIGHT Copyright (c) SoftEther VPN Project.\r\nAll Rights Reserved.
+
+
+PREFIX D_PASSPHRASE
+CAPTION Private Key Passphrase
+STATIC1 The private key is protected by passphrase. \r\n\r\nEnter the passphrase to read the private key.
+STATIC2 &Passphrase:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_NM_CONNECT
+CAPTION Connect to SoftEther VPN User-mode Router
+S_TITLE Connecting to "%S"...
+
+
+PREFIX D_PASSWORD
+CAPTION Login to %S
+S_TITLE Enter your user name and password to log in to server %S. Make sure you select the correct auth type.
+STATIC1 Enter Use&r Info:
+STATIC2 Auth &Type:
+STATIC3 User &Name:
+STATIC4 &Password:
+R_NO_SAVE_PASSWORD &Do not Save Password
+S_COUNTDOWN An automatic reconnection will be made after %u seconds...
+IDOK &OK
+IDCANCEL Cancel Connection
+
+
+PREFIX D_STATUS
+CAPTION Connecting to "%s"...
+S_STATUS Initializing...
+IDCANCEL Cancel
+
+
+PREFIX D_CERT
+CAPTION Certificate
+S_TITLE The following information is available for this certificate.
+STATIC1 Basic Information of this Certificate:
+STATIC2 Issued to:
+STATIC3 Issuer:
+STATIC4 Expires at:
+STATIC5 Advanced Information of this Certificate:
+STATIC6 Certificate of Authority Who Signed This Certificate:
+S_PARENT The certificate of the certificate authority who signed this certificate is registered on the list of trusted certificates.
+S_PARENT_BUTTON_STR &View Certificate
+IDCANCEL &OK
+B_SAVE &Save to File
+
+
+PREFIX D_CHECKCERT
+CAPTION Security Alert - %s
+S_TITLE The connection to the destination VPN Server "%S" that you are currently connecting to is encrypted but the trustworthiness of the server certificate provided by the server is unknown.
+STATIC1 About the Server Certificate
+STATIC2 Establishing encrypted tunnel (SSL session) between VPN Server and VPN Client. Checking the server certificate enables to verify the authenticity of the server.
+S_MSG1 The server certificate provided by destination VPN Server "%S" is as follows.
+STATIC3 Issued to:
+STATIC4 Issuer:
+STATIC5 Expires at:
+B_SHOW &Show Certificate
+STATIC6 Digest (MD5):
+STATIC7 Digest (SHA-1):
+IDOK &Resume the Connection
+IDCANCEL &Cancel Connection
+STATIC8 There may be a problem with this certificate, such as it has not been issued by a trusted certificate authority (CA), or cert is expired.
+STATIC9 Confirm the content of this certificate and decide whether or not to connect to this VPN Server. Click Cancel Connection to abort the connection.
+
+
+PREFIX D_CONNECTERROR
+CAPTION Connect Error - %s
+S_TITLE An error occurred while connection to VPN Server "%S".
+S_COUNTDOWN Automatically reconnects after %u seconds...
+IDOK &Retry
+IDCANCEL Cancel Connection
+R_HIDE &Hide this window when connecting next time
+
+
+PREFIX D_CM_LOGIN
+CAPTION Enter Password - VPN Client Manager
+S_TITLE You must enter a client administration password to operate the VPN Client that is operating on %s. Enter the client administration password.
+STATIC1 &Password:
+STATIC2 Enter the Client Administration Password:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CONNECTION_STATUS
+S_TITLE Status of VPN Session of %s (Real Time)
+B_POLICY Security &Policy...
+B_SERVER_CERT &Server Certificate
+B_CLIENT_CERT &Client Certificate
+IDCANCEL &Close
+
+
+PREFIX D_CM_POLICY
+CAPTION Security Policy List
+S_TITLE Security policies defined for the current session %s
+IDCANCEL &Close
+
+
+PREFIX D_CM_ACCOUNT
+STATIC1 Please configure the VPN Connection Setting for VPN Server.
+S_ACCOUNT_NAME Setting &Name:
+STATIC2 Destination VPN Server:
+STATIC3 Specify the host name or IP address, and the port number and the Virtual Hub on the destination VPN Server.
+STATIC4 &Host Name:
+STATIC5 &Port Number:
+STATIC6 (TCP Port)
+STATIC7 &Virtual Hub Name:
+STATIC8 Pro&xy Server as Relay:
+STATIC9 You can connect to a VPN Server via a proxy server.
+STATIC10 Proxy &Type:
+R_DIRECT_TCP &Direct TCP/IP Connection (No Proxy)
+R_HTTPS Connect via H&TTP Proxy Server
+R_SOCKS Connect via &SOCKS Proxy Server
+B_PROXY_CONFIG P&roxy Server Setting
+STATIC11 Server Certificate Veri&fication Option:
+R_CHECK_CERT Always Verify Server &Certificate
+B_TRUST Manage Trusted CA &Certificate List
+B_SERVER_CERT &Specify Individual Cert
+B_VIEW_SERVER_CERT Show Indi&vidual Cert
+S_VLAN_GROUP Virtua&l Network Adapter to Use:
+S_POLICY_1 You can configure the security policy which will be applied to the Cascade Connection on this Virtual Hub's side.
+B_POLICY Security Po&licy
+STATIC12 User &Authentication Setting:
+STATIC13 Auth &Type:
+S_USERNAME &User Name:
+S_PASSWORD Password:
+S_CERT_INFO You must specify a client certificate to be used for user authentication.
+STATIC14 Advanc&ed Setting of Communication:
+R_RETRY Reconnects Automatically After Disconnected
+S_RETRY_NUM_1 Reconnect &Count:
+S_RETRY_NUM_2 times
+S_RETRY_SPAN_1 Reconnect Interval:
+S_RETRY_SPAN_2 seconds
+R_INFINITE &Infinite Reconnects (Keep VPN Always Online)
+R_NOTLS1 Do not use TLS &1.0
+B_DETAIL A&dvanced Settings...
+IDOK &OK
+IDCANCEL Cancel
+B_CHANGE_PASSWORD Change &Password
+S_CHANGE_PASSWORD You can change the user's password on the VPN Server.
+R_HIDE Hide Status and Errors Screens
+R_HIDE2 Hide IP Address Screens
+STATIC15 Set the user authentication information that is required when connecting to the VPN Server.
+B_REGIST_CLIENT_CERT Specify Client &Certificate
+B_IE Import I&E Proxy Server Settings
+
+
+PREFIX D_CM_PROXY
+CAPTION Proxy Server Connection Setting
+STATIC1 Enter the host name of the proxy server for relaying (HTTP proxy or SOCKS proxy), and the IP address, port, and when necessary, the user name and password.
+STATIC2 &Host Name:
+STATIC3 Port:
+STATIC4 &User Name:
+STATIC5 &Password:
+IDOK &OK
+IDCANCEL Cancel
+STATIC6 (optional)
+STATIC7 (optional)
+
+
+PREFIX D_CM_DETAIL
+CAPTION Advanced Settings
+STATIC1 Optional settings for system administrators and experts for networking, communication protocol, and security. Customize the VPN protocol communication settings.
+STATIC2 Op&timization of VPN Communication:
+STATIC3 Uses multiple physical TCP connection aggregation for a logical VPN connection to increase the communication throughput.
+STATIC4 &Number of TCP Connections:
+STATIC5 connections
+STATIC6 Note: It is recommend that about 8 connections for broadband and 1 connection for slow line (e.g. dialup).
+STATIC7 Advanced Settings:
+STATIC8 Establi&shing Interval:
+STATIC9 seconds
+R_USE_DISCONNECT Set Connection Lifetime of E&ach TCP Connection
+STATIC10 Lifetime:
+STATIC11 seconds
+STATIC12 When using two or more TCP connections, Half Duplex Mode is available. The half-duplex mode fixes the data direction as half and half for each TCP connection. For example when a VPN using 8 TCP connections is established, physical consists of the VPN tunnel will be fixed so that 4 TCP connections are dedicated to the upload direction and the other 4 connections are dedicated to the download direction.
+R_USE_HALF_CONNECTION Use &Half-Duplex Mode
+STATIC13 Encryption and &Compression:
+STATIC14 Normally the VPN session is encrypted for secure. You can disable encryption to improve the throughput. Please note that the data flows in plain over the network when disabled.
+R_USE_ENCRYPT &Encrypt VPN Session with SSL
+STATIC15 You can use data compression to save VPN communication bandwidth. Enable this option when using a slow connectivity such as dial-up or mobile connection.
+R_DISABLE_UDP Disable UD&P Acceleration
+R_USE_COMPRESS &Use Data Compression
+STATIC16 VPN Connection &Mode:
+S_MODE You can specify the following connection modes. (Options for network administrators.)
+R_BRIDGE &Bridge / Router Mode
+R_MONITOR Monitoring Mo&de
+STATIC17 Other Confi&gurations:
+R_NO_ROUTING No Adjustments of &Routing Table
+STATIC18 Keep the settings default in this dialog unless you are told to do so by a system administrator, or you have expertise for networking and security.
+STATIC19 The VoIP / QoS functions handle high priority packets such as IP telephone packets (VoIP) to be transmitted faster.
+R_DISABLE_QOS Disable VoIP / &QoS Functions
+IDOK &OK
+IDCANCEL Cancel
+S_UDPACCEL You can use data compression to save VPN communication bandwidth. Enable this option when using a slow connectivity such as dial-up or mobile connection.
+
+
+PREFIX D_CM_NEW_VLAN
+CAPTION Create New Virtual Network Adapter
+S_INFO A new Virtual Network Adapter will be created on the system.\r\nYou can specify a name for the Virtual Network Adapter, which can be a maximum of %u alphanumeric characters.
+STATIC1 Virtual Network Adapter &Name:
+IDOK &OK
+IDCANCEL Cancel
+S_WIN8 Current operating system is Windows 8. The name of a Virtual Network Adapter must be 'VPN' or 'VPN2' to 'VPN127'. (Maximum 127 adapters can be created.)
+
+
+PREFIX D_CM_TRUST
+CAPTION Manage Trusted CA Certificate List
+STATIC1 Here you can manage the list of certificate authority (CA) certificates that are trusted.\r\n\r\nYou can use the CA certificate list registered here to verify server certificates when connecting to VPN Servers.
+B_IMPORT &Add
+B_EXPORT &Export
+IDOK &View Certificate
+IDCANCEL &Close
+B_DELETE &Delete
+
+
+PREFIX D_CM_PASSWORD
+CAPTION Set Password - VPN Client Manager
+S_TITLE You can set the password to limit the SoftEther VPN Client Service.\r\nAfter setting a password, you will be asked to enter a password the next time you use the VPN Client Connect Manager to connect to the SoftEther VPN Client service.
+STATIC1 Set Client Administration Password:
+R_USE_PASSWORD &Use Password
+R_REMOTE_ONLY Only &Request Password for Remote Operation
+IDC_STATIC1 &Password:
+IDC_STATIC2 &Confirm:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CM_CONFIG
+CAPTION Optional Settings
+STATIC1 You can modify the settings for VPN Client.
+STATIC2 R&emote Management:
+STATIC3 You can remotely manage the VPN Client Service Program from another computer by using VPN Client Manager Remote Mode.
+R_ALLOW_REMOTE_CONFIG Allow &Remote Management of VPN Client Service
+S_WARNING It is recommended to set a password if you allow remote management. From the menu bar, choose Tools -> Set Password to set the password.
+STATIC4 For environments where Internet connections will automatically be disconnected when idle, you can keep alive the Internet connection by sending dummy packets to any host on the Internet.
+R_USE_KEEP_CONNECT Use &Keep Alive Internet Connection Function
+S_HOSTNAME &Host Name:
+S_PORT &Port Number:
+S_INTERVAL Packet Send &Interval:
+S_INTERVAL2 seconds
+S_PROTOCOL Pr&otocol:
+R_TCP &TCP/IP Protocol
+R_UDP &UDP/IP Protocol
+S_INFO Packets sent to keep alive the Internet connection have random bits. No personal information is sent.
+IDOK &OK
+IDCANCEL Cancel
+STATIC5 &Other Configurations:
+R_ALPHA Transparency of UI:
+STATIC6 Note: The transparency setting will be applied after the connection manager is restarted.
+STATIC7 &Keep Alive Internet Connection Function:
+
+
+PREFIX D_ABOUT
+S_INFO1 SoftEther VPN %u.0 (Ver %u.%02u, Build %u)
+S_INFO2 An Open-Source VPN Software for Academic Purpose, under the GPLv2 License.\r\nCopyright (c) 2012-%u SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.\r\nWeb Site: http://www.softether.org/\r\n%S
+S_INFO3 This product includes the following software components:\r\nBitVisor: Copyright (c) 2007, 2008 University of Tsukuba. Copyright (C) 2007, 2008 National Institute of Information and Communications Technology. All rights reserved. / Microsoft(R) C Runtime Library: (c) 2007 Microsoft Corporation. All Rights Reserved. / PKCS #11 Cryptographic Token Interface (Cryptoki): Copyright (c) RSA Security Inc. / WinPcap: Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy). All rights reserved. / libedit: Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved. / libiconv: Copyright (C) 2007 Free Software Foundation, Inc. / ncurses: Copyright (c) 1998-2005, 2006 Free Software Foundation, Inc. / OpenSSL: Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). / zlib: (C) 1995-2004 Jean-loup Gailly and Mark Adler. / Special Thanks to: Software Laboratory, Academic Computing Communication Center, Industrial Liaison and Cooperative Research Center and Professor Yasushi Shinjo in University of Tsukuba, Japan.
+S_INFO4 THIS SOFTWARE IS FREEWARE DEVELOPED UNDER THE SOFTETHER VPN PROJECT AT UNIVERSITY OF TSUKUBA, WITHOUT WARRANTY OF AND KIND. IN NO EVENT SHALL THE DEVELOPERS, COPYRIGHT OWNERS OR DISTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY IN ANY WAY OUT OF THE USE OF THIS SOFTWARE.\r\n\r\nSoftEther VPN is a work of the research and development project of Japanese Government, subsidized by Ministry of Economy, Trade and Industry of Japan, administrated by Information Promotion Agency.
+IDCANCEL &OK
+B_WEB Visit SoftEther VPN &Website...
+B_EULA &End User License
+B_IMPORTANT &Important Notices
+B_LEGAL &Legal Notices
+B_UPDATE_CONFIG &Configure Updates
+
+
+PREFIX D_REMOTE
+STATIC1 &Specify the Host Name of the Destination Computer, or IP Address:
+R_LOCAL Connect to &Local Computer (Computer Displaying this Window)
+S_HOSTNAME &Computer Name:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CM_DESKTOP
+CAPTION Connection - %s
+S_TITLE Starting connect process for VPN Connection Setting "%s".
+S_WARNING VPN Client will output to the "Console Session" window of %s, the progress status and error messages related to the process of connecting to VPN Server
+S_INFO Do you want to proceed with the connection?
+IDOK &Continue
+IDCANCEL Cancel
+
+
+PREFIX D_CM_CHANGE_PASSWORD
+CAPTION Change Password
+S_TITLE You can change the password of the user registered on server %S.
+STATIC1 Change &Password
+STATIC2 Virtual &Hub Name:
+STATIC3 &User Name:
+STATIC4 &Old Password:
+STATIC5 &New Password:
+STATIC6 &Confirm of New Password:
+IDOK &OK
+IDCANCEL Cancel
+S_STATIC Note: If authentication type is RADIUS or NT Domain Authentication, you cannot change the user's password here.
+
+
+PREFIX D_SM_MAIN
+CAPTION SoftEther VPN Server Manager
+STATIC1 Connection &Settings for VPN Server:
+STATIC2 Connection Settings for VPN Server or VPN Bridge are defined as follows. Double-click the item to connect to the server.\r\nTo add a new connection, click New Setting.
+B_NEW_SETTING &New Setting
+B_EDIT_SETTING &Edit Setting
+B_DELETE &Delete Setting
+IDOK &Connect
+B_SECURE_MANAGER &Smart Card Manager...
+B_SELECT_SECURE Select S&mart card...
+B_ABOUT &About SoftEther VPN...
+IDCANCEL E&xit SoftEther VPN Server Manager
+B_CERT_TOOL Make a Certificate
+
+
+PREFIX D_SM_EDIT_SETTING
+STATIC1 Please configure the connection setting for the VPN Server or the VPN Bridge to manage.
+STATIC2 Setting &Name:
+STATIC3 Destination VPN Server:
+STATIC4 Specify the host name or IP address, and the port number and the Virtual Hub on the destination VPN Server.
+STATIC5 &Host Name:
+R_LOCALHOST Connect to &Localhost
+STATIC6 &Port Number:
+STATIC7 (TCP Port)
+STATIC8 Pro&xy Server as Relay:
+STATIC9 You can connect to a VPN Server via a proxy server.
+STATIC10 Proxy &Type:
+R_DIRECT_TCP &Direct TCP/IP Connection (No Proxy)
+R_HTTPS Connect via H&TTP Proxy Server
+R_SOCKS Connect via S&OCKS Proxy Server
+B_PROXY_CONFIG P&roxy Server Setting
+STATIC11 Select Administration &Mode and Enter Password
+STATIC12 You can connect to VPN Server using either Server Admin Mode or Virtual Hub Admin Mode.\r\n\r\nServer Admin Mode allows you manage entire VPN Server and all Virtual Hubs. \r\n\r\nVirtual Hub Admin Mode allows you manage only one Virtual Hub for which you hold privileges.
+R_SERVER_ADMIN &Server Admin Mode
+R_HUB_ADMIN Virtual H&UB Admin Mode
+S_HUBNAME &Virtual Hub Name:
+STATIC13 Please enter the password to connect administration mode.
+S_PASSWORD &Password:
+R_NO_SAVE Do not &Save Admin's Password
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_SERVER
+CAPTION %s - SoftEther VPN Server Manager
+S_TITLE Manage VPN Server "%S"
+S_VHUB_BRIDGE Virtual Hubs Hosted by this VPN Server:
+IDOK M&anage Virtual Hub
+B_ONLINE &Online
+B_OFFLINE O&ffline
+B_HUB_STATUS View &Status
+B_CREATE &Create a Virtual Hub
+B_EDIT Prop&erties
+B_DELETE &Delete
+STATIC1 Management of &Listeners:
+STATIC2 L&istener List (TCP/IP port):
+B_CREATE_LISTENER C&reate
+B_DELETE_LISTENER Dele&te
+B_START Start
+B_STOP Sto&p
+STATIC3 VPN Server and &Network Information and Settings:
+B_SSL &Encryption and Network
+B_STATUS &View Server Status
+B_INFO About this VPN Server
+B_LICENSE Add / Delete &Licenses
+B_FARM Clustering Configuration
+B_FARM_STATUS Clustering Status
+B_CONNECTION Show List of\r\nTCP/IP Connections
+B_BRIDGE Local &Bridge Setting
+B_L3 Layer &3 Switch Setting
+B_CONFIG E&dit Config
+B_REFRESH Refres&h
+IDCANCEL E&xit
+S_BETA Beta Version (Pre-release)
+B_IPSEC IPsec / L&2TP Setting
+B_DDNS Dynamic DNS Setting
+S_DDNS Current DDNS Hostname:
+B_OPENVPN OpenVPN / MS-SSTP Setting
+B_AZURE VPN Azure Setting
+S_AZURE VPN Azure Hostname:
+B_VPNGATE VPN Gate Setting
+
+
+PREFIX D_SM_STATUS
+IDOK Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_SM_EDIT_HUB
+STATIC1 Virtual Hub &Name:
+STATIC2 Security &Settings:
+S_BOLD Administration password for this Virtual Hub.
+STATIC3 &Password:
+STATIC4 &Confirm:
+R_NO_ENUM No En&umerate to Anonymous Users
+STATIC5 V&irtual Hub Options:
+R_LIMIT_MAX_SESSION &Limit Max VPN Sessions
+S_MAX_SESSION_1 Ma&x Number of Sessions:
+S_MAX_SESSION_2 sessions
+STATIC6 (It doesn't count sessions on server side that are generated by Local Bridge, Virtual NAT or Cascade Connection.)
+STATIC7 Virtual Hub Status:
+STATIC8 Set the Virtual Hub status.
+R_ONLINE Onlin&e
+R_OFFLINE O&ffline
+STATIC9 Set Clustering:
+S_FARM_INFO Select the Virtual Hub type in the cluster.
+R_STATIC St&atic Virtual Hub
+R_DYNAMIC &Dynamic Virtual Hub
+S_AO_1 Virtual Hub Admin Option:
+S_AO_3 Display and edit the Virtual Hub administration options.
+B_ADMINOPTION Virtual Hub Admin Option
+S_ACL_3 Sou&rce IP Address Limit List
+S_ACL Allow or deny VPN connections to this Virtual Hub according to the client computer's IP address.
+B_ACL IP Access Con&trol List
+IDOK &OK
+IDCANCEL Cancel
+STATIC10 You can configure more advanced settings on the Virtual Hub Extended Option List.
+B_EXTOPTION Edit Virtual Hub Extended Option List
+S_MSG_1 Show Message when Client Connects
+S_MSG_2 Shows a message on the screen of a user when a VPN Client connects to this Virtual Hub.
+B_MSG Set the Messa&ge
+
+
+PREFIX D_SM_CREATE_LISTENER
+CAPTION Create Listener
+STATIC1 You can add a TCP/IP port number for the VPN Server to accept connections from clients. \r\n\r\nSpecify the port number to add.
+STATIC2 If the port number is already being used by another server program, the status of the new listener will be error. \r\n\r\nIn this case, stop the other program that is opening the same port.
+STATIC3 &Port Number:
+IDOK &OK
+IDCANCEL Cancel
+STATIC4 (TCP/IP Port)
+
+
+PREFIX D_SM_SSL
+CAPTION Encryption and Network Settings
+STATIC1 You can view or change settings related to encryption, communication and security for this VPN Server.
+STATIC2 Encryption &Algorithm Settings:
+STATIC3 Specify the encryption algorithm for SSL applied to the connection between this VPN Server and VPN Clients. The encryption algorithm must be compatible with SSL Version 3.
+STATIC4 En&cryption Algorithm Name:
+STATIC6 Server &Certificate Settings:
+STATIC7 Specify the X509 certificate and private key to be presented to clients by this server.
+B_IMPORT &Import
+B_EXPORT E&xport
+B_VIEW &View
+B_REGENERATE New
+STATIC8 &Keep Alive Internet Connection:
+STATIC9 For environments where Internet connections will automatically be disconnected when idle, you can keep alive the Internet connection by sending dummy packets to any host on the Internet.
+STATIC10 Server Certificate:
+R_USE_KEEP_CONNECT Use &Keep Alive Internet Connection
+S_HOSTNAME &Host Name:
+S_PORT &Port:
+S_INTERVAL Send &Interval:
+S_INTERVAL2 seconds
+S_PROTOCOL Pr&otocol:
+R_TCP &TCP/IP Protocol
+R_UDP &UDP/IP Protocol
+S_INFO Packets sent to keep alive the Internet connection have random bits. No personal information is sent.
+STATIC11 Administrator Pass&word:
+S_INFO4 You can modify an administrator password of the administrator for all Virtual Hubs and this entire VPN Server.
+B_PASSWORD Change Admin &Password
+IDOK &OK
+IDCANCEL Cancel
+IDCANCEL2 Cancel
+STATIC12 Syslog Send Function:
+STATIC13 You can transfer the entire VPN Server / Bridge Logs, Virtual Hub Administration Logs, or Virtual Hub Packet Logs by using syslog protocol instead of writing to a local disk.
+STATIC14 Syslog &Server Host Name:
+STATIC15 P&ort:
+S_OVER_FUNCS VPN over ICMP / DNS Server Function
+S_INFO5 You can establish a VPN only with ICMP or DNS packets even if there is a firewall or routers which blocks TCP/IP communications.
+B_SPECIALLISTENER VPN over ICMP / DNS Settings
+B_UPDATE_CONFIG &Update Notify Setting...
+
+
+PREFIX D_SM_SAVE_KEY_PAIR
+CAPTION Save Certificate and Private Key
+STATIC1 Select the method to save the certificate and private key.
+STATIC2 Sa&ve Method:
+R_X509_AND_KEY Save as &X509 Certificate (.CER) and Private Key File (.KEY)
+R_PKCS12 Save as &PKCA#12 File (.P12)
+R_SECURE Write to &Smart Card
+STATIC3 Saving by splitting into two files: a standard Base 64-encoded certificate file and a private key file.
+STATIC4 Saving as a PKCS#12 (Public Key Cryptography Standard #12) file. \r\nYou can store both certificate and private key in a single PKCS#12 file.
+STATIC5 When a smart card is connected to this computer, you can write the certificate and private key to a smart card.
+B_SELECT &Select Which Smart Card to Use...
+S_PASS3 Private Key P&rotection:
+S_PASS4 When saving the private key, you can set a passphrase to encrypt. You will be required to enter the passphrase when loading it.
+R_USE_PASS Set P&assphrase
+S_PASS1 Pa&ssphrase:
+S_PASS2 Con&firm:
+IDOK &OK
+IDCANCEL Cancel
+B_SECURE_MANAGER Smart Card &Manager...
+
+
+PREFIX D_SM_CONNECTION
+CAPTION Connection List
+S_TITLE The server %S has the following active connections. Connections which have been established as a VPN session are not included.
+IDOK Show Connection &Information
+B_DISCONNECT &Disconnect
+B_REFRESH Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_SM_FARM
+CAPTION Clustering Configuration
+S_TITLE You can change configuration for clustering function of VPN Server "%S".
+STATIC1 Clustering can realize load balancing and fault balance protection to bundle multiple VPN Servers.
+STATIC2 Current Mode:
+STATIC3 Clustering Se&ttings:
+R_STANDALONE &Standalone Server (No Clustering)
+R_CONTROLLER &Cluster Controller
+R_MEMBER Cluster &Member Server
+STATIC4 C&onfigurable Parameters as a Member Server:
+S_IP_1 Public &IP Address:
+S_IP_2 (When a public IP address is omitted, the IP address of the network interface used when connecting to the cluster controller will be used.)
+S_PORT_1 &Public Port List:
+S_PORT_2 (Separate multiple port numbers by a space or a comma.)
+S_CONTROLLER Controller &Host Name or IP Address:
+S_CONTROLLER_PORT Port Number of\r\nControlle&r:
+S_PORT_3 (TCP Port)
+S_PASSWORD Administration &Password:
+STATIC5 When you modify a clustering configuration, the VPN Server service restarts automatically. When this happens, all the currently connected sessions and administration-related connections will be disconnected.
+IDOK &OK
+IDCANCEL Cancel
+S_1 Standard Ratio in Cluster:
+S_2 (Standard: 100)
+R_CONTROLLER_ONLY Controller Functions Only (No VPN session in itself)
+
+
+PREFIX D_SM_FARM_MEMBER
+CAPTION Cluster Member List
+S_TITLE Currently the following Cluster Member Servers are connected to the Cluster Controller %S.
+IDOK Cluster Member Server &Information
+B_REFRESH Refres&h
+IDCANCEL E&xit
+B_CERT View Server &Certificate
+
+
+PREFIX D_SM_CHANGE_PASSWORD
+CAPTION Change Administrator Password of %S
+S_TITLE Change the administrator password of the server %S. Enter the new password and click OK.
+STATIC1 New &Password:
+STATIC2 &Confirm Password:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_HUB
+CAPTION Management of Virtual Hub - '%S'
+S_TITLE Virtual Hub '%S'
+STATIC1 Management of Security &Database:
+B_USER Manage &Users
+S_USER Add, delete or edit user accounts.
+B_GROUP Manage &Groups
+S_GROUP Add, delete or edit groups.
+B_ACCESS Manage &Access Lists
+S_ACCESS Add or delete access lists (Packet filtering rules).
+STATIC2 Virtual Hub Settings:
+B_PROPERTY Virtual Hub &Properties
+S_PROPERTY Configure this Hub.
+B_RADIUS Auth&entication Server Setting
+S_RADIUS Use external RADIUS authentication server for user authentication.
+B_LINK Manage &Cascade Connections
+S_LINK Establish Cascade Connection to Hubs on local or remote VPN Servers.
+STATIC3 Cu&rrent Status of this Virtual Hub:
+B_REFRESH Refres&h
+STATIC4 &Other Settings:
+B_LOG &Log Save Setting
+B_LOG_FILE Log File List
+S_LOG Configure settings of log saving function.
+B_CA &Trusted CA Certificates
+B_CRL Revo&ked Certs
+S_CA Manage trusted CA certificates.
+B_SNAT &Virtual NAT and Virtual DHCP Server (SecureNAT)
+S_SNAT Secure NAT is available on this Virtual Hub. You can run Virtual NAT and Virtual DHCP.
+STATIC5 VPN Sess&ions Management:
+B_SESSION Manage &Sessions
+IDCANCEL E&xit
+
+
+PREFIX D_SM_USER
+CAPTION Manage Users
+S_TITLE Virtual Hub "%S" has the following users.
+IDOK &Edit
+B_CREATE &New
+B_DELETE &Remove
+B_REFRESH &Refresh
+IDCANCEL E&xit
+B_STATUS &View User Info
+
+
+PREFIX D_SM_EDIT_USER
+IDC_STATIC1 &User Name:
+IDC_STATIC3 &Full Name:
+IDC_STATIC4 &Note:
+IDC_STATIC5 Group Name\r\n(Optional):
+B_GROUP Browse Groups...
+R_EXPIRES &Set the Expiration Date for This Account
+IDC_STATIC6 &Auth Type:
+S_RADIUS_3 RADIUS or NT Domain Authentication Settings:
+S_RADIUS_1 Login attempts by password will be verified by the external RADIUS server, Windows NT domain controller, or Active Directory controller.
+R_SET_RADIUS_USERNAME Specify User Name on Authentication Server
+S_RADIUS_2 User Name on Authentication Server:
+S_POLICY_1 Security Policy
+R_POLICY Set Securit&y Policy
+B_POLICY Security Policy
+S_PASSWORD_1 Password Authentication Settings:
+S_PASSWORD_2 &Password:
+S_PASSWORD_3 &Confirm Password:
+S_USER_CERT_1 Individual Certificate Authentication Settings:
+B_LOAD_CERT Sp&ecify Certificate
+B_VIEW_CERT &View Certificate
+B_CREATE Create Certificate
+S_ROOT_CERT_1 Signed Certificate Authentication Settings:
+S_ROOT_CERT_2 Verification of whether the client certificate is signed is based on a certificate of a CA trusted by this Virtual Hub.
+R_CN Limit Common Name (CN) Value
+R_SERIAL &Limit Values of the Certificate Serial Number
+S_ROOT_CERT_3 Note: Enter hexadecimal values. (Example: 0155ABCDEF)
+S_HINT Hint: Define a user object with username '*' (asterisk) in order to accept a login attempt of a user which does not match any of registered explicit user objects. Such a special user will use the external user-authentication server to verify the login.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_POLICY
+STATIC1 Selected &Policy:
+S_BOLD Des&cription of the policy:
+S_BOLD2 Current &Value:
+R_ENABLE &Enable the Policy
+R_DISABLE &Disable the Policy
+R_DEFINE De&fine the Policy
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_GROUP
+CAPTION Manage Groups
+S_TITLE Virtual Hub "%S" has the following groups.
+B_CREATE &New
+IDOK &Edit
+B_DELETE &Remove
+B_REFRESH &Refresh
+B_USER &Member List
+IDCANCEL E&xit
+
+
+PREFIX D_SM_EDIT_GROUP
+IDC_STATIC1 &Group Name:
+IDC_STATIC3 &Full Name:
+IDC_STATIC4 &Note:
+S_POLICY_1 Security Policy:
+R_POLICY Set this group's Securit&y Policy
+B_POLICY Security Policy
+S_POLICY_2 Statistical Information of the Group:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_ACCESS_LIST
+CAPTION Access Lists
+S_TITLE The Virtual Hub "%S" has the following access lists (packet filtering rules).
+B_ADD &New (IPv&4)
+B_ADD_V6 &New (IPv&6)
+IDOK &Edit
+B_DELETE &Delete
+B_SAVE &Save
+IDCANCEL &Cancel
+STATIC1 Items with higher priority appear higher in the list.
+STATIC2 Note: IP packets that did not match any access list items can pass.
+B_CLONE Cl&one
+B_ENABLE E&nable
+B_DISABLE D&isable
+
+
+PREFIX D_SM_EDIT_ACCESS
+CAPTION Edit Access List Item
+STATIC1 Configure the access list settings. The access list that is defined here will be applied to all IP packets passing through the Virtual Hub.
+STATIC2 Basic Settings
+STATIC3 &Memo:
+STATIC4 &Action:
+R_PASS &Pass
+R_DISCARD &Discard
+STATIC5 P&riority:
+STATIC6 (Smaller number has higher priority.)
+STATIC7 Filtering Options for IP Headers
+S_ACCESS_SRC_ALL Source IP Address:
+R_SRC_ALL Applies to All Source Addresses
+S_SRC_IP_1 IPv4 Address:
+S_SRC_IP_2 Subnet Mask:
+S_SRC_IP_3 (255.255.255.255 means a single host)
+S_SRC_IP_1_V6 IPv6 Address:
+S_SRC_IP_3_V6 (For example: "ffff:ff00::" or "/24". "/128" means a single host.)
+S_ACCESS_DST_ALL Destination IP Address:
+R_DST_ALL Applies to All Destination Addresses
+S_IP_DST_1 IPv4 Address:
+S_IP_DST_2 Subnet Mask:
+S_IP_DST_3 (255.255.255.255 means Specified host only)
+S_IP_DST_1_V6 IPv6 Address:
+S_IP_DST_3_V6 (For example: "ffff:ff00::" or "/24". "/128" means a single host.)
+STATIC9 Protocol Type:
+STATIC10 Filtering Options for TCP Headers and UDP Headers
+S_TCP_1 Minimum
+S_TCP_2 Maximum
+S_TCP_3 Source Port:
+S_TCP_5 Destination Port:
+S_TCP_7 The blank port number field matches any ports.\r\nWhen the minimum value is specified but the maximum value is not, it will apply to packets that match only the minimum value.
+STATIC11 Filtering Options for Users or Groups
+STATIC11_OLD Filtering Options for Users
+STATIC12 This access list will be applied to only packets that either specific users or groups send or receive.
+STATIC12_OLD This access list will be applied to only packets that specific users send or receive.
+STATIC13 Source Name:
+B_USER1 Browse...
+STATIC14 Destination Name:
+B_USER2 Browse...
+STATIC15 Leave these fields blank if you don't specify user nor group.
+STATIC15_OLD Leave these fields blank if you don't specify user.
+IDOK &OK
+IDCANCEL Cancel
+S_PROTOID Specify IP Protocol:
+STATIC16 Filtering Options for MAC Headers
+S_CHECK_SRC_MAC Source MAC Address:
+R_CHECK_SRC_MAC Applies to any Source Addresses
+S_SRC_MAC MAC Address:
+S_SRC_MAC_MASK Mask:
+S_CHECK_DST_MAC Destination MAC Address:
+R_CHECK_DST_MAC Applies to any Destination Addresses
+B_SIMULATION De&lay and Packet Loss...
+S_DST_MAC MAC Address:
+S_DST_MAC_MASK Mask:
+S_MAC_NOTE You can use hexadecimal number with two separators, "-" or ":", and without the separators.\r\n(FF-FF-FF-FF-FF-FF means a specified host)
+R_CHECK_TCP_STATE Verify TCP Connection State (Only TCP Packets)
+R_ESTABLISHED Established Packet
+R_UNESTABLISHED Unestablished Packet
+R_REDIRECT Redirect HTTP Request to Specific URL
+B_REDIRECT Set URL Redirect to...
+
+PREFIX D_SM_RADIUS
+CAPTION Authentication Server Settings
+S_TITLE To use an external RADIUS server to verify login attempts to the Virtual Hub "%S", specify an external RADIUS server that verifies the user name and password.
+STATIC1 RADIUS Server Settings:
+R_USE_RADIUS &Use RADIUS Authentication
+S_RADIUS_1 RADIUS &Server Host Name or IP:
+S_RADIUS_2 &Port:
+S_RADIUS3 (UDP Port)
+S_RADIUS_4 Shared S&ecret:
+S_RADIUS_5 &Confirm Shared Secret:
+S_RADIUS_6 The RADIUS server must accept requests from IP addresses of this VPN Server. Also, authentication by Password Authentication Protocol (PAP) must be enabled.
+S_RADIUS_7 milliseconds (above %u, below %u)
+S_RADIUS_8 &Retry Interval
+S_RADIUS_9 (use ',' or ';' to split multiple hostnames.)
+STATIC2 When using Windows NT Domain Controller or Windows Server Active Directory Controller as an external authentication server, you must setup the VPN Server computer to join the domain. To use NT Domain Authentication, there are no items to configure here.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_LINK
+CAPTION Cascade Connections on %S
+STATIC1 Cascade Connection can make a layer-2 Ethernet-level links between this Virtual Hub and other Virtual Hub which is located on either local or remote VPN Server.
+STATIC2 Before Using Cascade Connection
+STATIC3 Cascade Connection realizes a Layer 2 Bridge between multiple Virtual Hubs. But if the connection is incorrectly configured, an infinity loop could inadvertently be created. When using a Cascade Connection function please design the network topology with care.
+B_CREATE &New
+B_EDIT &Edit
+B_ONLINE O&nline
+B_OFFLINE O&ffline
+IDOK &Status
+B_DELETE &Delete
+B_RENAME Ren&ame
+B_REFRESH &Refresh
+IDCANCEL E&xit
+
+
+PREFIX D_SM_LOG
+CAPTION Log Save Settings
+S_TITLE You can save the security logs (such as history of user logins) of Virtual Hub "%S", and the packet logs of all packets that pass through the Virtual Hub.
+STATIC1 &Security Log:
+B_SEC Save S&ecurity Log
+S_SEC Log File S&witch Cycle:
+STATIC2 &Packet Log:
+B_PACKET Save Pack&et Log
+S_PACKET Log File S&witch Cycle:
+S_PACKET_0 TCP Connection:
+B_PACKET_0_0 Do not Save
+B_PACKET_0_1 Header Only
+B_PACKET_0_2 Headers && Payloads
+S_PACKET_1 TCP Packet:
+B_PACKET_1_0 Do not Save
+B_PACKET_1_1 Header Only
+B_PACKET_1_2 Headers && Payloads
+S_PACKET_2 DHCP Packet:
+B_PACKET_2_0 Do not Save
+B_PACKET_2_1 Header Only
+B_PACKET_2_2 Headers && Payloads
+S_PACKET_3 UDP Packet:
+B_PACKET_3_0 Do not Save
+B_PACKET_3_1 Header Only
+B_PACKET_3_2 Headers && Payloads
+S_PACKET_4 ICMP Packet:
+B_PACKET_4_0 Do not Save
+B_PACKET_4_1 Header Only
+B_PACKET_4_2 Headers && Payloads
+S_PACKET_5 IP Packet:
+B_PACKET_5_0 Do not Save
+B_PACKET_5_1 Header Only
+B_PACKET_5_2 Headers && Payloads
+S_PACKET_6 ARP Packet:
+B_PACKET_6_0 Do not Save
+B_PACKET_6_1 Header Only
+B_PACKET_6_2 Headers && Payloads
+S_PACKET_7 Ethernet\r\nPacket:
+B_PACKET_7_0 Do not Save
+B_PACKET_7_1 Header Only
+B_PACKET_7_2 Headers && Payloads
+IDOK &OK
+IDCANCEL Cancel
+STATIC3 Saving large amounts of packet logs can place a large burden on the CPU and the hard disk and it can cause lower performance of Hub and entire VPN Server. Enable logging on only the necessary packet log to save.
+
+
+PREFIX D_SM_CA
+CAPTION Manage Trusted CA Certificates
+STATIC1 You can manage the list of certificate authority (CA) certificates that are trusted by this Virtual Hub.\r\n\r\nThe list of CA certificates that is listed here is used to verify certificates when a VPN Client is connected in signed certificate authentication mode.
+B_IMPORT &Add
+IDOK &View Certificate
+IDCANCEL &Close
+B_DELETE &Delete
+
+
+PREFIX D_SM_SESSION
+CAPTION Manage Sessions - %S
+S_TITLE Virtual Hub "%S" has the following VPN sessions currently.
+STATIC1 Operations for Sessions
+IDOK Session &Information
+B_DISCONNECT &Disconnect
+B_REFRESH Refres&h
+B_SESSION_MAC_TABLE &MAC Table of Selected Session
+B_SESSION_IP_TABLE I&P Table of Selected Session
+STATIC2 &Other Administration Tasks
+B_MAC_TABLE MAC &Address Table List
+B_IP_TABLE IP Address Ta&ble List
+IDCANCEL E&xit
+S_FARM_INFO_2 The sessions displayed here are all sessions on the current cluster. To manage sessions on other cluster member servers you must connect as an administrator to those servers.
+
+
+PREFIX D_SM_MAC
+CAPTION MAC Address Table
+S_TITLE The MAC address table database on the Virtual Hub "%S" has the following entries.
+B_DELETE &Delete Selected Entry
+B_REFRESH Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_SM_IP
+CAPTION IP Address Table
+S_TITLE The IP address table database on the Virtual Hub "%S" has the following entries.
+B_DELETE &Delete Selected Entry
+B_REFRESH Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_SM_CREATE_CERT
+CAPTION Create New Certificate
+STATIC1 You can easily create certificates which is signed by self or other certificates.
+STATIC2 Certificate &Type:
+R_ROOT_CERT &Root Certificate (Self-Signed Certificate)
+R_SIGNED_CERT Certificate &Signed by Other Certificate
+S_LOAD_1 &Certificate and Private Key for Signing:
+B_LOAD &Load Certificate and Private Key
+S_LOAD_2 Click 'Load Certificate and Private Key' to specify the X509 Certificate and RSA Private Key that will user a new certificate signature.
+S_LOAD_3 Common Name (CN):
+S_LOAD_4 Organization (O):
+S_LOAD_5 Organization Unit (OU):
+S_LOAD_6 Country (C):
+S_LOAD_7 State (ST):
+S_LOAD_8 Locale (L):
+S_LOAD_11 &Serial Number:\r\n(Hexadecimal)
+S_LOAD_9 &Expires in:
+S_LOAD_10 Days
+STATIC3 To manage certificates and certificate authorities on a large scale, you should use either free software such as OpenSSL, or commercial CA (certificate authority) software.
+IDOK &OK
+IDCANCEL Cancel
+S_LOAD_12 Strength&ness:
+
+
+PREFIX D_NM_LOGIN
+CAPTION deleted
+S_TITLE deleted
+STATIC1 deleted
+STATIC2 deleted
+IDOK deleted
+IDCANCEL deleted
+
+
+PREFIX D_SPEEDMETER
+CAPTION Network Device Status
+STATIC1 Select Network Adapter:
+STATIC2 Real-time Status
+STATIC3 &Refresh
+
+
+PREFIX D_NM_MAIN
+CAPTION deleted
+STATIC1 deleted
+STATIC2 deleted
+B_SETTING Connection &Setting for VPN Server
+B_CONNECT &Connect
+B_DISCONNECT &Disconnect
+STATIC3 Operation Settings of User-mode Router
+STATIC4 You can set the operations in a virtual network of a SoftEther VPN User-mode Router.
+B_OPTION &Operation Settings of User-mode Router
+STATIC5 Operating Status of User-mode Router
+STATIC6 Displays the current operating status of the SoftEther VPN User-mode Router.
+B_NAT Virtual &NAT Status
+B_DHCP Virtual D&HCP Server Status
+B_STATUS User-mode &Router Status
+B_INFO User-mode Router &Information
+B_PASSWORD Administration &Password Setting
+B_REFRESH Refr&esh
+B_ABOUT &About...
+IDCANCEL E&xit
+
+
+PREFIX D_NM_OPTION
+CAPTION SecureNAT Configration
+S_TITLE Set how SecureNAT virtual host performs operation on the virtual network of Virtual Hub "%S".
+STATIC1 Virtual Host's Network Interface Settings:
+STATIC2 &MAC Address:
+STATIC3 I&P Address:
+STATIC4 &Subnet Mask:
+STATIC5 Virtual NAT Settings:
+R_USE_NAT Use Virtual N&AT Function
+STATIC6 M&TU Value:
+STATIC7 bytes
+STATIC8 T&CP Session Timeout:
+STATIC9 seconds
+STATIC10 &UDP Session Timeout:
+STATIC11 seconds
+R_SAVE_LOG Save NAT or DHCP Server Operations to &Log File
+STATIC12 Virtual DHCP Server Settings:
+R_USE_DHCP Use Virtual DHCP Server Fu&nctions
+STATIC13 &Distributes IP Address:
+STATIC14 to
+STATIC15 .
+STATIC16 Su&bnet Mask:
+STATIC17 L&ease Limit:
+STATIC18 seconds
+STATIC19 Options Applied to Clients (optional):
+STATIC20 De&fault Gateway\r\nAddress:
+STATIC21 DNS &Server Address 1:
+STATIC22 Domain Name:
+STATIC23 DNS &Server Address 2:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_NM_NAT
+CAPTION NAT Session Table on Virtual NAT Router
+S_TITLE There are the following TCP or UDP NAT table entries on the virtual NAT router of SecureNAT.
+B_REFRESH Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_NM_DHCP
+CAPTION IP Lease Table on Virtual DHCP Server
+S_TITLE The SecureNAT Virtual DHCP Server has allocated the following IP addresses to clients.
+B_REFRESH Refres&h
+IDCANCEL E&xit
+
+
+PREFIX D_NM_CHANGE_PASSWORD
+CAPTION Change Administrator Password of %S
+S_TITLE You can change the administrator password of SoftEther VPN User-mode Router (%S). Click OK after entering the new password.
+STATIC1 New &Password:
+STATIC2 &Confirm Your Input:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_SNAT
+CAPTION Virtual NAT and Virtual DHCP Function (SecureNAT) Setting
+S_TITLE SecureNAT enables you to operate a virtual NAT router (IP Masquerade) and DHCP Server function on a virtual network of Virtual Hub "%S".
+STATIC1 Warning about SecureNAT
+S_WARNING The SecureNAT function is recommended only for system administrators or people with a detailed knowledge of networking.
+S_WARNING2 If you use the SecureNAT correctly, it is possible to realize a safety remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrator's permission must not enable the SecureNAT. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual or online documentation.
+STATIC2 Enabling / Disabling and Changing the Setting of the SecureNAT
+STATIC3 You can enable, disable or change the settings of the SecureNAT on this Virtual Hub.
+B_ENABLE &Enable SecureNAT
+B_DISABLE &Disable SecureNAT
+B_CONFIG SecureNAT &Configuration
+STATIC4 Note: When a running SecureNAT is disabled, all active TCP and UDP sessions that are connected via SecureNAT will be terminated.
+STATIC5 View Current SecureNAT Status
+STATIC6 You can view the current SecureNAT operating status.
+B_NAT Virtual &NAT Router Status
+B_DHCP Virtual D&HCP Server Status
+B_STATUS View &SecureNAT Operating Status
+S_TSUKUBA2 SecureNAT uses technology that Daiyuu Nobori developed in 2004 at "Special Seminar on Information I" at the College of Information Science of the Third Cluster of Colleges, Tsukuba University.
+IDCANCEL E&xit
+
+
+PREFIX D_SM_BRIDGE
+CAPTION Local Bridge Settings
+STATIC1 Local Bridge can establish a Layer 2 bridge connection between a Virtual Hub on this VPN server and a physical Ethernet Device (Network Adapter). \r\nIt is also possible to create a tap device (virtual network interface) and establish a bridge connection with a Virtual Hub. (Tap is supported on Linux versions only)
+B_DELETE &Delete Local Bridge
+STATIC2 New &New Local Bridge Definition:
+STATIC3 Select the Virtual Hub to bridge.
+STATIC4 Virtual &Hub:
+STATIC5 &Type to Create:
+R_BRIDGE Bridge with &Physical Existing Network Adapter
+R_TAP Bridge with New &Tap Device
+S_ETH_1 LAN Adapter:
+S_TAP_1 New Tap &Device Name:
+S_TAP_2 (Maximum 11 Characters)
+STATIC6 Note: It is possible to establish a bridge using any operating network adapter, but in high load environments, you should prepare a network adapter dedicated for bridging.
+IDOK Cre&ate Local Bridge
+STATIC7 If a network adapter doesn't appear which is recently added on the system recently, reboot the computer and re-open this screen.
+IDCANCEL E&xit
+B_VLAN VLAN Transparency Setting Tool
+
+
+PREFIX D_WIN9X_REBOOT
+CAPTION VPN Client - Install Virtual Network Adapter
+STATIC1 The VPN Client Virtual Network Adapter was installed. \r\nIt is necessary to shutdown Windows now and restart the computer. \r\n\r\nThe computer will restart automatically. If the computer does not restart, please restart the computer manually.
+
+
+PREFIX D_EM_MAIN
+CAPTION SoftEther EtherLogger Manager
+STATIC1 SoftEther EtherLogger is a service that captures data flowing through LAN cards connected to the computer and keeps a log of the headers of the packet types specified by the administrator and all data in text file format. \r\n\r\nCurrently, the following capture devices are performing capture logging.
+B_PASSWORD Administration &Password
+B_LICENSE &License
+B_ADD &Add
+IDOK &Edit
+B_DELETE &Delete
+IDCANCEL E&xit
+
+
+PREFIX D_EM_ADD
+STATIC1 Name of Network Adapter Used for Capture:
+R_PROMISCUS Do&n't Use Promiscuous Mode During Capture
+STATIC2 &Packet Log:
+S_PACKET Log File S&witch Cycle:
+S_PACKET_0 TCP Connection Log:
+B_PACKET_0_0 Save Nothing
+B_PACKET_0_1 Header Information Only
+B_PACKET_0_2 Whole Packet Contents
+S_PACKET_1 TCP Packet Log:
+B_PACKET_1_0 Save Nothing
+B_PACKET_1_1 Header Information Only
+B_PACKET_1_2 Whole Packet Contents
+S_PACKET_2 DHCP Packet Log:
+B_PACKET_2_0 Save Nothing
+B_PACKET_2_1 Header Information Only
+B_PACKET_2_2 Whole Packet Contents
+S_PACKET_3 UDP Packet Log:
+B_PACKET_3_0 Save Nothing
+B_PACKET_3_1 Header Information Only
+B_PACKET_3_2 Whole Packet Contents
+S_PACKET_4 ICMP Packet Log:
+B_PACKET_4_0 Save Nothing
+B_PACKET_4_1 Header Information Only
+B_PACKET_4_2 Whole Packet Contents
+S_PACKET_5 IP Packet Log:
+B_PACKET_5_0 Save Nothing
+B_PACKET_5_1 Header Information Only
+B_PACKET_5_2 Whole Packet Contents
+S_PACKET_6 ARP Packet Log:
+B_PACKET_6_0 Save Nothing
+B_PACKET_6_1 Header Information Only
+B_PACKET_6_2 Whole Packet Contents
+S_PACKET_7 Ethernet\r\nPacket Log:
+B_PACKET_7_0 Save Nothing
+B_PACKET_7_1 Header Information Only
+B_PACKET_7_2 Whole Packet Contents
+IDOK &OK
+IDCANCEL Cancel
+STATIC3 Saving large volume packet logs can place a large burden on the CPU and the hard disk and it can cause lower performance of the entire system. Please configure settings so that only the necessary packet log information is saved.
+
+
+PREFIX D_EM_PASSWORD
+CAPTION Change Administrator Password
+S_TITLE You can change the administrator password. Click OK after entering the new password.
+STATIC1 New &Password:
+STATIC2 &Confirm:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_EM_LICENSE
+CAPTION Add or Delete License
+STATIC1 To use SoftEther EtherLogger you must acquire a valid license and register the license key. Using this window, you can register a new license key, delete a registered license key and display the current license list and the license mode of the SoftEther EtherLogger.
+S_BOLD &List of Currently Registered Licenses:
+B_OBTAIN &Obtain License
+STATIC2 Click Obtain License to display the website that will provide instructions on how to obtain a license.
+B_ADD &Add License Key Registration
+B_DEL &Delete
+IDOK &Information About License
+STATIC3 Select a license and click Information About License to connect to SoftEther VPN Project's website (softether.com) and view the registered information relating to the selected license.
+S_BOLD2 Current License &Mode of SoftEther EtherLogger:
+IDCANCEL E&xit
+
+
+PREFIX D_EM_LICENSE_ADD
+CAPTION Add License Key Registration
+S_INFO You can register a license key of a SoftEther EtherLogger product license.
+STATIC1 The license keys are 36 alphanumeric characters in length plus hyphens. They are key codes that certify the ownership of a license. \r\n\r\nWhen a license certificate is received together with this software, the license key is printed on this license certificate. If the license for this software was purchased online, the license key is provided by email and on the website window at the time the license is purchased. The license key may also be written down by some other method. If you don't know where the license key is written down, ask the vendor who sold you the license.
+STATIC2 &Input the License Key Correctly:
+STATIC3 Enter the license key by separating the input into 6-digit groups. You don't need to input the hyphens. It is also possible to copy && paste the license key.
+B_INFO2 This software has world-wide copyright protection. Customers can only make copies and use this software in accordance with the license conditions. Warning: Use of illegitimately obtained license keys, use of a single license on multiple servers, or unauthorized distribution of licenses is a breach of the license agreement and such action may result in civil or legal proceedings.
+IDOK &Register
+IDCANCEL Cancel
+
+PREFIX D_EM_REMOTE
+STATIC1 &Specify the Host Name of the Destination Computer, or IP Address:
+R_LOCAL Connect to &Local Computer (Computer Displaying this Window)
+S_HOSTNAME &Computer Name:
+IDOK &OK
+IDCANCEL Cancel
+B_ABOUT Version information
+
+PREFIX D_SM_CONFIG
+CAPTION Edit Config File
+IDC_INFO The current configuration of the VPN Server "%S" is as follows.\r\nYou can edit the contents of this configuration file and apply it to the VPN Server.
+B_EXPORT &Save to File
+B_IMPORT &Import File and Apply
+IDCANCEL &Close
+STATIC1 You can edit the configuration file by using any text editors. When applying the edited configuration file to the VPN Server, the VPN Server will automatically restart and launch according to the new configuration file. If an invalid configuration file is applied, errors will occur and the current setting contents will get lost, so be careful when editing the configuration file.
+B_FACTORY &Restore to Factory Default
+
+
+PREFIX D_SM_ADMIN_OPTION
+CAPTION Virtual Hub Administration Option
+S_INFO Currently the following administration options are set for the Virtual Hub "%S".
+B_ADD &Add Value
+B_EDIT &Edit Value
+B_DELETE &Delete Value
+STATIC1 The purpose of the Virtual Hub administration options is to set limitations to administrators who are in Virtual Hub Admin Mode.
+IDOK &Save
+IDCANCEL Cancel
+STATIC2 Only an administrator for this entire VPN Server may edit the Virtual Hub administration options. The individual Virtual Hub administrators are unable to change the administration options, however they are able to view them.\r\nHowever, if allow_hub_admin_change_option is set to "1", then Virtual Hub administrators are able to edit the administration options.
+S_BOLD Description:
+
+
+PREFIX D_SM_MSG
+CAPTION Set the Message
+S_MSG_2 You can set a message to display on the screen of a user when a VPN Client connects to the Virtual Hub "%S". To show a message, input the message you want to show.
+C_USEMSG Show &Message
+STATIC1 About the Message Display Funcion
+S_INFO The VPN Client must be Version 3.0 or later.\r\n\r\nSpecify a single line starts with "http://" as the message to open the default Web browser on the client instead to showing a message.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_NICINFO
+CAPTION Virtual Network Adapter "%S" Status
+IDCANCEL &Close
+
+
+PREFIX D_SM_VLAN
+CAPTION VLAN Transparency Setting Tool
+STATIC1 Some network adapters are unable to transmit tagged-VLAN packets (IEEE802.1Q) transparency. by default\r\n\r\nIf you use such a network adapter to bridge to the Virtual Hub and need to exchange Ethernet packets with VLAN tags, you have to configure the network adapter to enable processing packets for VLAN transparency.
+B_ENABLE Configure the Selected Network Adapters to VLAN Transparency
+B_DISABLE &Unset the Configuration
+STATIC2 About the VLAN Transparency Setting Tool
+S_WARNING This tool can enable or disable the transparency for tagged VLAN packets on Intel, Broadcom or Marvell's network adapters. (Only using the vendor provided drivers for Windows.)
+S_WARNING2 The above network adapters in the list means supported by this tool. No other network adapters can be configured by this tool. However, other network adapters which is not on the list might be able to support tagged VLAN packets by default or by using some configuration.\r\n\r\nSuch network adapters must be configured by the system administrator with logged on Windows.
+IDCANCEL E&xit
+
+
+PREFIX D_SM_SIMULATION
+CAPTION Delay and Packet Loss Generating Function
+STATIC1 This function can generate delays, jitters and packet losses on packets which match the condition of this access list entry when transmitted via this Virtual Hub.\r\n\r\nThis function is convenient to simulate a low-quality and slow Internet, WAN or wireless connections on the desk or laboratory. For example, you can use it to evaluate and test IP telephonies (VoIP).
+STATIC2 Generate Delays, Jitters and Packet Losses as follow:
+C_DELAY Generate &Delays
+S_DELAY The Period of Delay (0 - 10000) :
+S_DELAY2 milliseconds
+C_JITTER Generate &Jitters (Fluctuation)
+S_JITTER The Ratio of Jitter (0 - 100) :
+S_JITTER2 Percent (%)
+C_LOSS Generate Packet &Losses
+S_LOSS The Ratio of Packet Losses (0 - 100) :
+S_LOSS2 Percent (%)
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_AO_VALUE
+CAPTION Name and Value
+STATIC1 &Name:
+STATIC2 &Value:
+STATIC3 (Integer)
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_L3
+CAPTION Virtual Layer 3 Switch Setting
+STATIC1 You can define Virtual Layer 3 Switches between two or more Virtual Hubs operating on this VPN Server to achieve routing between different IP networks.
+STATIC2 The Virtual Layer 3 Switch functions are provided for network administrators or people who know a lot about networking and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions.\r\n\r\nIf the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing.
+STATIC3 Cautions about Virtual Layer 3 Switch Function
+S_BOLD Defined Virtual &Layer 3 &Switches:
+B_ADD &New
+B_START &Start
+B_STOP S&top
+IDOK &Edit
+B_DELETE &Delete
+IDCANCEL &Close
+
+
+PREFIX D_SM_L3_ADD
+CAPTION New Virtual Layer 3 Switch
+STATIC1 To create a new Virtual Layer 3 Switch, enter a name for the switch. \r\n\r\nThe Virtual Layer 3 Switch cannot have the duplicated name as another Virtual Layer 3 Switch on this VPN Server.
+STATIC2 &Name:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_L3_SW
+CAPTION Edit Virtual Layer 3 Switch "%S"
+STATIC1 You can define multiple virtual interfaces and routing tables on a Virtual Layer 3 Switch.
+STATIC2 A virtual interface is associated to a Virtual Hub and operates as a single IP host on the Virtual Hub when the Virtual Hub is running. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. \r\nIt is possible to manually set the routing table and more detailed settings.
+S_BOLD1 Virtual &Interfaces:
+B_ADD_IF &New Virtual Interface
+B_DEL_IF D&elete Virtual Interface
+S_BOLD2 Routing &Table:
+B_ADD_TABLE A&dd Routing Table Entry
+B_DEL_TABLE De&lete Routing Table Entry
+B_START &Start
+B_STOP S&top
+IDCANCEL &Close
+
+
+PREFIX D_SM_L3_SW_IF
+CAPTION Add Virtual Interface
+STATIC1 Adds a new virtual interface to the Virtual Layer 3 Switch. \r\n\r\nYou must define the IP network that the virtual interface belongs to and the IP address of the interface itself. \r\nPlease select or enter the name of the virtual Hub that the interface will attach to.
+STATIC2 Virtual Hub to &Attach
+STATIC3 Select or enter the name of the Virtual Hub that this interface will attach to.
+STATIC4 Virtual &Hub:
+STATIC5 IP A&ddress and Subnet Mask of Virtual Interface:
+STATIC6 The virtual interface must have one IP address in the Virtual Hub. You also must specify the subnet mask of an IP network that the IP address belongs to. \r\n\r\nRouting via the Virtual Layer 3 Switches attaching to multiple virtual Hubs operates based on the IP address specified here.
+S_SRC_IP_1 &IP address:
+S_SRC_IP_2 &Subnet Mask:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_L3_SW_TABLE
+CAPTION New Routing Table Entry
+STATIC1 Adds a new routing table entry to the routing table of the Virtual Layer 3 Switch. \r\n\r\nIf the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference the routing table and execute routing.
+STATIC2 Definitions of Routing Table &Entry:
+STATIC3 The virtual interface must have one IP address in the Virtual Hub. You also must specify the subnet mask of an IP network that the IP address belongs to. \r\n\r\nRouting via the Virtual Layer 3 Switches of IP spaces of multiple virtual Hubs operates based on the IP address specified here.
+S_SRC_IP_1 &Network Address:
+S_SRC_IP_2 &Subnet Mask:
+S_SRC_IP_3 &Gateway Address:
+S_SRC_IP_4 &Metric Value:
+STATIC4 Note: To specify the default gateway, specify '0.0.0.0' for both the network address and the subnet mask.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CM_SELECT_SECURE
+CAPTION Select Smart Card
+STATIC1 Select the type of smart card device to use. \r\n\r\nThe types of smart cards listed in this list have had their drivers installed on the current computer and are supported by VPN software. \r\nIf there is a type of smart card that is currently being used that does not appear in the list, it may be possible to enable use by updating the VPN software to a newer version. \r\n\r\nNote: If a driver is not displayed immediately after installation, restart Windows.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CM_SECURE_MANAGER
+CAPTION Smart Card Manager
+S_INFO Current Smart Card:\r\n\r\n%S
+B_BOLD Objects stored on the smart card:
+B_REFRESH &Refresh Object List
+B_IMPORT &Import to Card...
+B_EXPORT &Export from Card...
+B_DELETE &Delete from Card
+B_NEW_CERT &Write New Certificate and Private Key to Card...
+B_PIN &Change PIN Code...
+IDCANCEL Close
+
+
+PREFIX D_CM_SECURE_TYPE
+CAPTION Select Object Type
+STATIC Select the type of the object you want to import.
+R_CERT &Certificate
+R_KEY Private &Key
+R_DATA &Data
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_STRING
+CAPTION VPN Software
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_SELECT_KEYPAIR
+CAPTION Specify Certificate in Smart Card
+S_INFO Currently selected smart card:\r\n\r\n%S
+B_BOLD1 Select the certificate in the smart card.
+IDOK &OK
+IDCANCEL Cancel
+B_BOLD2 Select the corresponding private key.
+
+
+PREFIX D_CM_LOAD_X
+CAPTION Load Certificate
+STATIC1 Select the method to load the certificate.
+R_FROM_FILE Load Certificate from &File
+R_FROM_SECURE Load Certificate from &Smart Card
+S_FILE You can load a certificate from a file that stores certificate data (extensions: .cer, .crt, .p12, .pfx).
+S_CERT If a smart card is connected to this computer, you can load a certificate from a smart card.
+B_SELECT &Select Which Smart Card to Use...
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_CM_SECURE_PIN
+CAPTION Change PIN Code
+STATIC1 You can change the PIN code (secret number) of the smart card. \r\n\r\nTo change the PIN code, you are required to enter the current PIN code and the new PIN code twice.
+STATIC2 &Current PIN code:
+STATIC3 &New PIN Code:
+STATIC4 Con&firm New PIN:
+STATIC5 Note
+STATIC6 If you incorrectly input the current PIN a certain number of times, the smart card will be rendered unusable.
+STATIC7 Please insert the smart card and click OK.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_CRL
+CAPTION Certificates Revocation List
+STATIC1 You can manage the Certificates Revocation List on this Virtual Hub. \r\n\r\nBy adding certificates in Certificates Revocation List, the clients who provide these certificates will be denied to connect to this Virtual Hub using certificate authentication mode.
+B_ADD &Add
+IDOK &Edit
+IDCANCEL &Close
+B_DELETE &Delete
+
+
+PREFIX D_SM_EDIT_CRL
+CAPTION Revoked Certificate
+STATIC1 You can set the contents of an entry on the revocation list. \r\n\r\nWhen a user connects to a Virtual Hub in certificate authentication mode and that certificate matches one or more of the contents defined in the Certificates Revocation List, the user will be denied to connect.
+S_BOLD The certificates that matches all the fields of the items will be disabled.
+STATIC2 Contents of Certificate:
+R_CN Common Name (CN):
+R_O Organization (O):
+R_OU Organization Unit (OU):
+R_C Country (C):
+R_ST State (ST):
+R_L Locale (L):
+STATIC3 Certificate Attribute Value:
+R_SERI Serial Number (Hex):
+R_MD5_HASH MD5 Digest Value (Hex, 128 bit):
+R_SHA1_HASH SHA-1 Digest Value (Hex, 160 bit):
+STATIC4 A digest value (hash value) can identify the particular certificate exactly. If you specify a MD5 or SHA-1 digest value, you need not to specify other items.
+STATIC5 Import Values from a Certificate File
+STATIC6 If there is a certificate file that you want to disable, you can correctly specify the certificate and add it to the invalid list by importing that file. Click Load Certificate and the contents of the specified certificate file will be imported automatically.
+B_LOAD &Load Certificate...
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_AC_LIST
+CAPTION Source IP Address Limit List
+S_TITLE To allow or deny VPN connections to this VPN Server Virtual Hub "%S" according to the client computer's IP address, you can set the rules to allow or deny the connection below.
+B_ADD &New Rule
+IDOK &Edit Rule
+B_DELETE &Delete Rule
+B_SAVE &Save
+IDCANCEL &Cancel
+STATIC1 Items with higher priority appear higher in the list.
+STATIC2 If the client's IP address does not match any item in the list, VPN connection to this Virtual Hub will be allowed.
+
+
+PREFIX D_SM_AC
+CAPTION Edit Rule Entry of Source IP Address Limit List
+STATIC1 Define a rule in the IP Access Control List. The values set here will be used to decide whether to allow or deny connection from a VPN Client when this client attempts connection to the Virtual Hub.
+STATIC2 Defines of a Rule
+STATIC3 Apply this Rule when the client's IP address matches the following:
+R_SINGLE &Single IP Address
+R_MASKED &Multiple IP Addresses (Specify by IP Network Address and Mask)
+STATIC4 &Address:
+S_MASK Net Mas&k:
+STATIC5 Action
+R_PASS &Permit
+R_DENY &Deny
+STATIC6 Others
+STATIC7 P&riority:
+STATIC8 (Integer: higher priority is given to smaller numbers)
+STATIC9 IP Protocol Version
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_LOG_FILE
+CAPTION Log File List
+STATIC1 You can download log files that are saved on the server. \r\n\r\nThe administrator of the entire VPN Server is granted to download all Virtual Hub logs and server logs. Virtual Hub administrators are granted to download the log file for that Virtual Hub.
+IDOK &Download
+B_REFRESH &Refresh
+IDCANCEL Close
+
+
+PREFIX D_SM_READ_LOG_FILE
+CAPTION Download File
+S_INFO2 Downloading the file "%S" from the VPN Server. \r\nPlease wait...
+IDCANCEL &Stop Download
+
+
+PREFIX D_SM_SAVE_LOG
+CAPTION Downloaded Log File
+S_INFO The file "%S" was downloaded. \r\n\r\nYou can open or save this file.
+IDOK &Open
+B_SAVE &Save
+IDCANCEL Cancel
+
+
+PREFIX D_TCP
+CAPTION TCP Optimization Utility
+STATIC1 By optimizing the TCP/IP settings on Windows, it is possible to increase the network communication throughput of this computer. \r\n\r\nBy using this TCP Optimization Utility, you can easily configure the settings for optimize the parameters.
+STATIC2 Current TCP/IP setting parameters of Windows is as follows. By changing these values you can optimize the TCP/IP settings. Using this utility any time later you can reset the values or restore them to the previous setting.
+STATIC3 TCP/IP Communication Setting:
+STATIC4 TCP &Receiving Window Size:
+R_RECV_DISABLE Use OS &Default Value
+R_RECV_ENABLE S&et the Values Below
+S_RECV bytes
+B_RECV Default Value
+STATIC5 TCP &Sending Window Size:
+R_SEND_DISABLE Use OS Default Value
+R_SEND_ENABLE Set the Values Below
+S_SEND bytes
+B_SEND Default Value
+IDOK &OK
+IDCANCEL Cancel
+STATIC6 The changes above will take effect after Windows has rebooted. After changing the settings, you do not need to immediately reboot the computer, but until it is rebooted the TCP/IP optimized settings will not take effect.
+B_DELETE Do not Manage by this Utility
+
+
+PREFIX D_TCP_MSG
+CAPTION TCP Optimization
+STATIC1 By optimizing the TCP/IP settings on Windows, it is possible to increase the network communication throughput of this computer. Do you want to optimize the communication settings?\r\n\r\nYou can at any time in the future start the TCP Optimization Utility and optimize the communication settings or restore them to their previous values.
+STATIC2 When the TCP/IP settings are changed, the changes will take effect after Windows has restarted. After changing the settings, you do not need to immediately restart the computer, but until it is restarted the TCP/IP optimized settings will not take effect.
+R_OPTIMIZE &Automatically Optimize Communication Settings
+R_MANUAL &Manually Optimize Using TCP Optimization Utility
+R_NO &Do not Optimize
+IDOK &Next >
+IDOK3 < &Back
+
+
+PREFIX D_CM_PKCSEULA
+CAPTION Notice to Use Smart Card's Drivers
+S_INFO_1 You are attempting to access the smart card with software "%S".
+S_INFO_2 When using software "%S", if there are conditions of use for this software and the smart card that is to be used, you must agree to these conditions of use before using them. \r\n\r\nFor details please contact the vendor of software "%S" and of the smart card.
+S_INFO_3 Do you agree to the above and want to use the software "%S" and access the specified smart card?
+IDOK &Yes
+IDCANCEL &No
+
+
+PREFIX D_CM_TRAFFIC
+CAPTION Network Traffic Speed Test Tool
+STATIC1 Network Traffic Speed Test Tool performs transmitting packets between two computers connected with TCP/IP, with large amount of throughput as possible, in order to measure the actual network traffic speed available. This tool can be used for not limited VPNs, but it is useful for physical networks.
+STATIC2 Use this tool to measure the current bandwidth capacity of the network. Note that the value obtained is sometimes lower than the actual network processing capacity due to the CPU performance of both endpoints, what other programs are currently running and fluctuations in the rate of use of the network.
+S_1 Configurations:
+S_3 Which is the role of this computer?
+R_SERVER Test &Server
+R_CLIENT Test &Client
+S_4 To activate the test server, specify the listening port number.\r\nTo use it as the test client, specify the host name of the destination test server or the IP address, and port number. If necessary, configure the optional settings below.
+S_5 Destination Test Server &Hostname:
+S_6 &Port Number:
+S_7 (TCP port)
+S_8 Configure following options on the client side.
+S_9 Direction of Data Communication
+R_DOWNLOAD &Download (Incoming: from Server to Client)
+R_UPLOAD &Upload (Outgoing: from Client to Server)
+R_FULL Download and Upload (&Full-Duplex Mode: In and Out Simultaneously)
+S_10 Advanced Settings
+S_11 &Number of Concurrent Parallel TCP Connections:
+S_12 Me&asuring Period:
+S_13 seconds
+R_ETHERNET Correct L2 Throughput Assuming &Ethernet
+R_DOUBLE Relay Device Mode
+S_14 connections
+IDOK &Run
+IDCANCEL Cancel
+S_15 You can also run this tool from the vpncmd Command-line Management Utility (also available on non-Windows OS).
+
+
+PREFIX D_CM_TRAFFIC_RUN
+CAPTION Network Traffic Speed Test Tool
+S_INFO The Network Traffic Speed Test Tool is running. The operating status is as follows.
+STATIC1 To abort the Network Traffic Speed Test Tool, click Exit.
+IDCANCEL &Exit
+
+
+PREFIX D_CM_TRAFFIC_RESULT
+CAPTION Communication Traffic Measurement Results
+STATIC1 Communication traffic was measured. The results are shown below.
+IDCANCEL &Close
+
+
+PREFIX D_SM_LICENSE
+CAPTION Add or Remove License
+STATIC1 To use SoftEther VPN Server you must acquire a valid license and register the license key. You can register a new license key, delete a registered license key and display the current license list and the license mode of the VPN Server here.
+S_BOLD Currently Registered &License Keys:
+B_OBTAIN &Obtain or Extend a License
+STATIC2 Click Obtain or Extend License to visit the website that will provide instructions on how to obtain a license.
+B_ADD &Add a License Key
+B_DEL &Delete
+IDOK &Information About License
+STATIC3 Select a license and click Information About License to connect to SoftEther VPN Project's website (softether.com) and view the registered information relating to the selected license.
+S_BOLD2 Current License &Mode of SoftEther VPN Server:
+IDCANCEL E&xit
+
+
+PREFIX D_SM_LICENSE_ADD
+CAPTION Add License Keys
+S_INFO You can register a SoftEther VPN Server product license or a connection license.
+STATIC1 The license keys are 36 alphanumeric characters in length plus dashes. They are key codes that certify the ownership of a license. \r\n\r\nWhen a license certificate is received together with this software, the license key is printed on this license certificate. If the license for this software was purchased online, the license key is provided by email and on the website window at the time the license is purchased. The license key may also be written down by some other method. If you don't know where the license key is written down, ask the vendor who sold you the license.
+STATIC2 &Input the License Key Accurately:
+STATIC3 Enter the license key by separating the input into 6-digit groups. You don't need to input the dashes. It is also possible to copy && paste the license key.
+B_INFO2 This software is protected by world-wide copyright laws. Customers can only make copies and use this software in accordance with the license conditions. Warning: Use of illegitimately obtained license keys, use of a single license on multiple servers, or unauthorized distribution of licenses is a breach of the license agreement and such action may result in civil or legal proceedings.
+IDOK &Register
+IDCANCEL Cancel
+
+
+PREFIX D_FREEINFO
+CAPTION About SoftEther VPN Server Free Edition
+S_INFO_1 Thank you for trying out the SoftEther VPN Server Free Edition.
+S_INFO_2 The SoftEther VPN Server operating on destination server "%S" is the Free Edition intended for personal use. \r\nWhen using the Free Edition, you can use all the SoftEther VPN Server functions but the User Agreement prohibits the following usage.
+S_INFO_3 Use where communication for commercial purposes travels via the VPN Server.
+S_INFO_4 Note that if the software is used based on the abovementioned prohibited usage, it is a breach of the SoftEther VPN Server user agreement. The above restriction is lifted once you obtain a regular product license for SoftEther VPN Server. For details on the regular product version, please visit www.softether.com. \r\n\r\nIf this server is being used under the usage described above, please contact us via our website at www.softether.com. \r\n\r\nNote: This window will appear when connected to a Free Edition of VPN Server. This window does not appear when Editions other than the Free Editions of the software product are used. \r\nNote: Apart from this notification window, there are absolutely no differences between the Free Edition software and the product version.
+B_HIDE &Hide this window next time.
+IDCANCEL &OK
+
+
+PREFIX D_CM_SETTING
+CAPTION Switch SoftEther VPN Client Operating Mode
+STATIC1 You can use SoftEther VPN Client in either Normal Mode or Easy Mode. To switch to the other mode, check the respective checkbox below.
+R_NORMAL &Normal Mode
+R_EASY &Easy Mode
+STATIC2 When using Normal Mode, you can perform all the operations that the SoftEther VPN Client software provides. We recommend that general users and system administrators use this mode.
+STATIC3 Easy Mode only allows the most frequently used operations such as connecting to the VPN Server. We recommend this mode to beginner users.
+STATIC4 By using the Setting Locker, you can connect to a VPN Server by using a Connection Setting registered in SoftEther VPN Client, but by doing so, you are prevented from changing the parameters of Connection Settings, creating a new Connection Setting or deleting a Connection Setting.
+R_LOCK Enable Setting &Locker
+S_PASSWORD1 You can specify a password. The input of that password will be required next time to disable the Setting Locker.
+S_PASSWORD2 &Password:
+S_PASSWORD3 &Confirm:
+IDOK &OK
+IDCANCEL Cancel
+S_VGS2 You can configure the VPN Gate Academic Service settings.
+B_VGS VPN &Gate Service Settings...
+
+
+
+PREFIX D_CM_EASY
+CAPTION SoftEther VPN Client Easy Manager
+B_MODE Switch Operation &Mode
+IDCANCEL &Close
+B_STATUS View Connection &Status
+B_VGC VPN Gate Academic Project
+
+
+PREFIX D_SM_SETUP
+CAPTION SoftEther VPN Server / Bridge Easy Setup
+S_TITLE SoftEther VPN Server / Bridge Easy Setup
+IDC_STATIC_1 By using this setup you can easily setup a SoftEther VPN Server or VPN Bridge for the following use and purpose. After exiting the setup, you can use the VPN Server Manager to freely configure more advanced settings.
+S_BOLD Select the type of VPN server you want to build. Multiple types can be selected together.
+C_REMOTE &Remote Access VPN Server
+S_REMOTE_1 The Remote Access VPN Server allows VPN Client computers in remote locations to access to the existing Ethernet segments, for example company LAN.\r\nAny VPN Clients who is connecting to the VPN Server will be able to access to the network as if they are connected directly and physically to the network.
+C_SITE &Site-to-site VPN Server or VPN Bridge
+S_SITE_1 Site-to-site VPN is a VPN configuration to connect between two or more remote Ethernet segments.\r\nEach of the sites are connected together, and become the same segment at Layer-2 level. It enables any computers of each sites to communicate to each other as if there is a single network.
+S_SITE_2 Select the role of this VPN Server:
+C_CENTER VPN Server that Accepts Connection from Other Sites (&Center)
+C_EDGE VPN Server or VPN Bridge at Each Site (&Edge)
+C_OTHER &Other Advanced Configuration of VPN
+S_OTHER Select this if you are planning to build a VPN system that provides advanced functions such as a clustering function and a Virtual Layer 3 Switch function.
+IDOK &Next >
+IDCANCEL &Close
+
+
+PREFIX D_SM_SETUP_HUB
+CAPTION Easy Setup - Decide the Virtual Hub Name
+IDC_STATIC_1 You have to create one Virtual Hub on the VPN Server at least. Name the new Virtual Hub as you prefer.
+IDC_STATIC_2 Virtual Hub &Name:
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_SETUP_STEP
+CAPTION VPN Easy Setup Tasks
+IDC_STATIC_1 To complete the setup of this VPN Server / VPN Bridge, you must complete the following tasks.
+S_1_1 Step 1. Create a User to Accept VPN Connection
+S_1_2 When this VPN Server accepts a remote access VPN, or becomes the central site-to-site VPN server that accepts connections from other sites, create users to accept the VPN connection.
+B_USER Create &Users
+S_2_1 Step 2. Define a Connection to Destination VPN Server
+S_2_2 When this VPN Server is installed on a particular site (edge) of a site-to-site VPN, you have to specify the address of the center VPN Server that accepts the connections, and establish a connection to that central VPN Server.
+B_CASCADE &Configure Connection Setting
+S_3_1 Step 3. Set Local Bridge
+S_3_2 For an site-to-site VPN, use the Local Bridge Function to connect a bridge between the virtual Ethernet segment on the VPN side and the physical Ethernet segment on the local side. Select an existing Ethernet device (Network Adapter) that will be provide the bridge connection to the VPN.
+IDCANCEL &Close
+IDC_STATIC_8 Once the required settings are configured, click Close. An advanced management tool for VPN Server / VPN Bridge will be appeared. You can then configure any advanced settings as you wish.
+B_SECURENAT Configure SecureN&AT
+
+
+PREFIX D_CPU64_WARNING
+CAPTION Information on SoftEther VPN 64-bit Edition
+S_BOLD The SoftEther VPN software currently installed is the 32-bit edition, but the Windows operating system that is currently running is a 64-bit edition.
+S_INFO You can run the 32-bit edition of SoftEther VPN software on a 64-bit edition of Windows, but it will run on Window's 32-bit emulator, and this results in reduced performance. \r\nThere is also a possibility that some functions are not supported. \r\n\r\nWe strongly recommend that you install and use the 64-bit edition of SoftEther VPN software when running it on 64-bit Windows. \r\nYou can download the 64-bit edition of the SoftEther VPN software from http://selinks.org/. \r\n\r\nThis dialog box will close automatically in 30 seconds.
+IDOK &OK
+
+
+PREFIX D_ONCEMSG
+CAPTION TITLE
+C_DONTSHOWAGAIN &Do not show this message again
+IDCANCEL &OK
+
+
+PREFIX D_CONNECT
+IDCANCEL Cancel
+
+
+PREFIX D_SM_IPSEC
+CAPTION IPsec / L2TP / EtherIP / L2TPv3 Settings
+S_TITLE IPsec / L2TP / EtherIP / L2TPv3 Server Settings
+S_3 Virtual Hubs on the VPN Server can accept Remote-Access VPN connections from L2TP-compatible PCs, Mac OS X and Smartphones, and also can accept EtherIP / L2TPv3 Site-to-Site VPN Connection.
+S01 L2TP Server (Remote-Access VPN Server Function)
+S02 VPN Connections from Smartphones suchlike iPhone, iPad and Android, and also from built-in VPN Clients on Mac OS X and Windows can be accepted.
+R_L2TP_OVER_IPSEC Enable L2TP Server Function (L2TP over IP&sec)
+S03 Make VPN Connections from iPhone, iPad, Android, Windows, and Mac OS X acceptable.
+R_L2TP_RAW Enable L2TP Server Function (Raw &L2TP with No Encryptions)
+S04 It supports special VPN Clients which uses L2TP with no IPsec encryption.
+S_1 Default Virtual &Hub in a case of omitting a name of Hub on the Username:
+S_2 Users should specify their username such as "Username@Target Virtual Hub Name" to connect this L2TP Server.\r\nIf designation of a Virtual Hub is omitted, the below Hub will be used as the target.
+S05 EtherIP Server Function (Site-to-Site VPN Connection)
+S06 Router products which are compatible with EtherIP / L2TPv3 over IPsec can connect to Virtual Hub on the VPN Server and establish Layer-2 (Ethernet) Bridging.
+R_ETHERIP Enable &EtherIP / L2TPv3 over IPsec Server Function
+B_DETAIL EtherIP / L2TPv3 &Detail Settings
+S07 IPsec &Common Settings
+S_PSK IPsec &Pre-Shared Key:
+S_PSK2 IPsec Pre-Shared Key is also called "PSKs" or "Secrets". Specify it with almost eight ASCII characters, and let all VPN users know.
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_ETHERIP
+CAPTION EtherIP / L2TPv3 Server Detail Settings
+S_TITLE EtherIP / L2TPv3 Server Detail Settings
+S01 EtherIP / L2TPv3 over IPsec compatible routers can connect to Virtual Hubs on VPN Server and establish Layer-2 (Ethernet) Bridge. For instance, Cisco routers, NEC IX series and IIJ SEIL routers are recommended as compatible VPN routers.
+S02 In order to accept EtherIP / L2TPv3 protocol, define appropriate EtherIP / L2TPv3 Client Settings to identify the client site of the router beforehand. A EtherIP / L2TPv3 Client Setting must have a corresponding IPsec Phase 1 ID.
+S_BOLD &Table of IPsec Phase 1 ID and the Virtual Hub
+B_ADD &Add
+IDOK &Edit
+B_DELETE &Delete
+IDCANCEL E&xit
+
+
+PREFIX D_SM_ETHERIP_ID
+CAPTION EtherIP / L2TPv3 over IPsec Client Setting
+S01 The following Virtual Hub connection settings will be applied only when an EtherIP / L2TPv3 over IPsec Client is attempting to connect this VPN Server with an ISAKMP (IKE) Phase ID which is exactly equal to the value specified below.
+S02 ISAKMP Phase 1 &ID:
+S03 Virtual &Hub:
+S04 &Username:
+S05 &Password:
+S06 Note that the username and the password must be same as a registered on the Virtual Hub. An EtherIP / L2TPv3 Client will be regarded as it connected the Virtual Hub with the identification of the above user information.
+IDOK &OK
+IDCANCEL Cancel
+S07 The ID must be exactly same as an ID in the configuration of the EtherIP / L2TPv3 Client. You can specify IP address as well as characters as ID, if the EtherIP / L2TPv3 Client uses IP address as Phase 1 ID. You can specify '*' (asterisk) as a wildcard to match any other clients which don't match other explicit rules.
+
+
+PREFIX D_SM_OPENVPN
+CAPTION OpenVPN / MS-SSTP Settings
+S_TITLE OpenVPN / MS-SSTP VPN Clone Server Function Settings
+S_1 This VPN Server has the clone functions of OpenVPN software products by OpenVPN Technologies, Inc.\r\n\r\nAny OpenVPN Clients can connect to this VPN Server.
+R_OPENVPN Enable &OpenVPN Clone Server Function
+S_UDP UDP Ports to Listen for OpenVPN:
+B_DEFAULT Restore &Default
+S_UDP2 Multiple UDP ports can be specified with splitting by space or comma letters.\r\nOpenVPN Server Function also runs on TCP ports. Any TCP ports which are defined as listeners on the VPN Server accepts OpenVPN Protocol respectively and equally.
+S_TOOL Sample File Generating Tool for OpenVPN Clients
+S_TOOL2 Making a OpenVPN Client configuration file is a very difficult job. You can use this tool to generate an appropriate OpenVPN Client configuration file. The generated configuration sample can be used immediately.
+B_CONFIG Generate a Sample &Configuration File for OpenVPN Clients
+S_2 Microsoft SSTP VPN Clone Server Function
+S_3 This VPN Server has the clone functions of MS-SSTP VPN Server which is on Windows Server 2008 / 2012 by Microsoft Corporation.\r\nBuilt-in MS-SSTP Clients on Windows Vista / 7 / 8 / RT can connect to this VPN Server.
+R_SSTP Enable &MS-SSTP VPN Clone Server Function
+S_SSTP The value of CN (Common Name) on the SSL certificate of VPN Server must match to the hostname specified on the client, and that certificate must be in the trusted list on the client. For details refer the Microsoft's documents.
+S_4 The manner to specify a username to connect to the Virtual Hub, and the selection rule of default Hub by using these clone server functions are same to the IPsec Server functions.
+B_IPSEC I&Psec Server Configuration
+S_13 OpenVPN Clone Server Function
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_SM_DDNS
+CAPTION Dynamic DNS Function
+S_TITLE Dynamic DNS Function
+S_BOLD This VPN Server has a Built-in Dynamic DNS Function.
+S_1 The Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name.
+S_22 Also, if your ISP assigns you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address.\r\nTherefore, you need not any longer to keep static global IP addresses with expenses monthly costs.
+S_3 Moreover, this VPN Server version supports 'NAT-Traversal' function. If the VPN Server is inside the NAT and is assigned only a private IP address, you can connect to that VPN Server from the Internet side without any special settings on the NAT beforehand.
+S_4 Current &Status:
+S_STATUS3 Assigned Dynamic DNS &Hostname:
+B_HINT Hint
+S_STATUS4 Global IPv&4 Address:
+S_STATUS5 Global IPv&6 Address:
+S_5 Modify the Settings:
+S_STATUS6 &Change the Dynamic DNS Hostname:
+S_STATUS7 Hostname is with only alphabets numeric, and dashes '-'. Three letters at least.\r\nYou can change it any time later.
+IDOK Set to &Above Hostname
+B_RESTORE &Restore
+S_2 If you are not connected to IPv6 Internet, "Global IPv6 Address" should show an error.\r\nA few countries or territories might prohibit Dynamic DNS Service.
+IDCANCEL E&xit
+B_DISABLE &Disable Dynamic DNS Function
+B_PROXY Connect via &Proxy Server...
+
+
+PREFIX D_SM_SPECIALLISTENER
+CAPTION VPN over ICMP / DNS Function Settings
+S_TITLE VPN over ICMP / DNS Function
+S_1 VPN over ICMP / DNS Function
+S_2 You can establish a VPN only with ICMP or DNS packets even if there is a firewall or routers which blocks TCP/IP communications. You have to enable the following functions beforehand.
+R_OVER_ICMP Enable VPN over &ICMP Server Function
+R_OVER_DNS Enable VPN over &DNS Server Function (Uses UDP Port 53)
+IDOK &OK
+IDCANCEL Cancel
+S_3 Requires VPN Client / VPN Bridge internal version 4.0 or greater.
+S_4 Warning: Use this function for emergency only. It is helpful when a firewall or router is misconfigured to blocks TCP/IP, but either ICMP or DNS is not blocked. It is not for long-term stable using.
+
+
+PREFIX D_SM_REDIRECT
+CAPTION HTTP URL Redirection Settings
+S_1 The specified URL below will be mandatory replied to the client as a response for TCP connecting request packets which match the conditions of this access list entry via this Virtual Hub.\r\n\r\nTo use this setting, you can enforce the web browser of the VPN Client computer to show the specified web site when that web browser tries to access the specific IP address.
+S_2 Specify a URL which redirects to.
+S_BOLD2 The &URL Redirect To:
+S_3 Example:
+S_4 Simple URL Redirection:
+S_5 Advanced URL Redirection:
+B_HINT &Usage of Advanced URL Redirection Function...
+S_6 Caption
+S_BOLD This function is for TCP/IP expert administrator. Read the following instructions and be careful to set up.
+S_7 This redirection rule is not effective in the case that the destination session of a packet matches the destination username or groupname of an access list entries.
+S_8 This redirection rule is ignored for non-TCP packets if it matches the condition.
+S_9 This redirection rule always replies HTTP redirect messages. (Not limited for port 80.) If you want to apply to only port 80, set the destination port to 80 on the condition of the access list entry.
+S_10 If as the result of redirection by this rule the client attempts to access the redirected URL and such a new request matches this rule again, the redirection results will be replied for such new requests. It will cause an infinite redirection loop.
+IDOK &OK
+IDCANCEL Cancel
+S_11 The advanced redirection function can provide the VPN Session information to the CGI which is redirected to.
+
+
+PREFIX D_SW_WELCOME
+CAPTION D_SW_WELCOME
+S_WELCOME SoftEther VPN is freeware developed at University of Tsukuba, Japan. High-performance VPN with the ultimate compatibilities to many devices. Windows, Mac, smartphones, tablets (iPhone, iPad, Android, Windows RT) and Cisco or other VPN routers are supported. SoftEther VPN also accepts OpenVPN and MS-SSTP VPN clients.
+S_TITLE Extremely Powerful Open-Source VPN Software.
+
+PREFIX D_SW_MODE
+CAPTION D_SW_MODE
+R_SYSTEM &System Mode (Recommended)
+R_USER &User Mode
+S_1 Install the VPN software to this computer normally. The administrator privilege is required.
+S_USER Install the VPN software with the normal user privilege. No administrator privilege is required. Some functions such as Local Bridge will be disabled. Runs only the user "%s" is logged on Windows.
+S_2 SoftEther VPN can be installed by one of two methods.\r\n\r\nPlease select the System Mode normally.\r\n\r\nIf you cannot use the administrator privilege for some reasons, you can select the User Mode to continue the installation.
+
+
+PREFIX D_SW_NOT_ADMIN
+CAPTION D_SW_NOT_ADMIN
+S_INFO The user "%s" which is logged on Windows does not have the administrator privilege.\r\n\r\nLog off Windows, log on by the user who has the administrator privilege and restart the Setup Wizard if you want to continue the setup.
+S_INFO6 Click Finish to exit the Setup Wizard.
+S_INFO2 If you cannot use the administrator privilege, you can choose the User Mode installation.\r\nTo install the software in the User Mode, click Back.
+
+
+PREFIX D_SW_COMPONENTS
+CAPTION D_SW_COMPONENTS
+
+
+PREFIX D_SW_EULA
+CAPTION D_SW_EULA
+S_1 Please read the End User License Agreement carefully.
+B_AGREE I agree to the End User License Agreement.
+
+
+PREFIX D_SW_WARNING
+CAPTION D_SW_WARNING
+S_1 SoftEther VPN software has extremely powerful communication abilities. Before use please read the Important Notices carefully.
+
+
+PREFIX D_SW_DIR
+CAPTION D_SW_DIR
+S_INFO Please specify the directory to install %s.
+R_CUSTOM &Specify the Directory
+S_DEST &Directory:
+B_BROWSE &Browse...
+R_SHOWCUSTOM &Advanced Install Options for Experts
+R_FOR_SYSTEM Install on &Windows of this Computer Entirely
+R_FOR_USER Install only on the Environment of User "%s"
+S_WARNING Caution: Not recommended. After the user "%s" logs off Windows, %s will stop. Local Bridge function and L2TP/IPsec Function (supports for Mac and Smartphones) will be unavailabe.
+
+
+PREFIX D_SW_READY
+CAPTION D_SW_READY
+S_INFO Install of %s is ready.
+S_INFO7 Click Next to perform the install.
+
+
+PREFIX D_SW_PERFORM
+CAPTION D_SW_PERFORM
+S_INFO The setup of %s is in progress.\r\nPlease wait...
+S_INFO8 SoftEther VPN is a work of the research and development project of Japanese Government, subsidized by Ministry of Economy, Trade and Industry of Japan, administrated by Information Promotion Agency.
+
+
+PREFIX D_SW_ERROR
+CAPTION D_SW_ERROR
+S_INFO An error occureed and the setup of %s is aborted.\r\n\r\nRestart the Setup Wizard if you want to retry.
+
+
+PREFIX D_SW_FINISH
+CAPTION D_SW_FINISH
+S_INFO The setup process of %s has completed successfully.
+S_INFO8 SoftEther VPN is a work of the research and development project of Japanese Government, subsidized by Ministry of Economy, Trade and Industry of Japan, administrated by Information Promotion Agency.
+
+
+PREFIX D_SW_UNINST1
+CAPTION D_SW_UNINST1
+S_WELCOME The Setup Wizard can uninstall %s from the computer.\r\n\r\nClick Next if you want to start uninstall.
+S_TITLE %s Uninstall Wizard
+
+
+PREFIX D_SW_EASY1
+CAPTION D_SW_EASY1
+S_WELCOME Installing and setting up the VPN Clients to a lot of computers in the enterprise is a hard work.
+S_TITLE What is SoftEther VPN Client Easy Installer?
+S_WELCOME2 Easy Installer Creator is a tool for enterprise administrators. You can create a VPN Client installer with embedding a specific VPN connection setting by using Easy Installer Creator. Personal users can also exploit this tool.
+S_WELCOME3 A created Easy Installer can be distributed to employees in the enterprise by using file servers or e-mails. If a user runs the Easy Installer, VPN Client will be installed and the VPN connection setting will be imported, and then the VPN connection will be started automatically.
+
+
+PREFIX D_SW_EASY2
+CAPTION D_SW_EASY2
+S_BOLD1 Specify a VPN connection setting file (.vpn file) to embed
+S_1 Please specify a VPN connection setting file (a file which extension is .vpn) to embed on the Easy Installer. You can export a setting file by clicking Export VPN Connection Setting on the right-click menu of the target connection setting on the VPN Client Manager.
+S_18 Connection &Setting:
+B_BROWSE_SETTING &Browse...
+B_DELETE_SENSITIVE &Eliminate Username and Password from Connection Setting File
+S_BOLD2 Specify an EXE filename to be generated
+S_3 This tool will output an EXE file (executable file) which implements an Easy Installer. Please specify the output filename to be generated.
+S_19 Save &as:
+B_BROWSE_OUT B&rowse...
+B_EASYMODE Set the VPN Client Manager to &Easy Mode when Installation
+
+
+PREFIX D_SW_WEB1
+CAPTION D_SW_WEB1
+S_WELCOME You can create a SoftEther VPN Client Web Installer and upload it on the Web server in the enterprise. A user opens that web page and can install the SoftEther VPN Client automatically. You can also setup the automatic import and kick-start of a built-in VPN connection setting.
+S_TITLE What is SoftEther VPN Web Installer?
+S_WELCOME2 The generated Web Installer can be placed as HTML files on the intranet Web server. If an employee accesses to the URL of that HTML files, the SoftEther VPN Client Installer will be executed.
+S_WELCOME3 Using ActiveX Control. Internet Explorer 5.0 or greater on Windows 2000 or greater are supported. Other web browsers or older operating systems (for example Windows 98) are not supported.
+
+
+PREFIX D_SW_WEB2
+CAPTION D_SW_WEB2
+S_BOLD1 Specify a VPN connection setting file (.vpn file) to embed
+S_1 Please specify a VPN connection setting file (a file which extension is .vpn) to embed on the Web Installer. You can export a setting file by clicking Export VPN Connection Setting on the right-click menu of the target connection setting on the VPN Client Manager.
+S_18 Connection &Setting:
+B_BROWSE_SETTING &Browse...
+B_DELETE_SENSITIVE &Eliminate Username and Password from Connection Setting File
+S_BOLD2 Specify the output filename to be generated
+S_3 This tool will output a ZIP file (archive file) which contains HTML files and CAB files that should be placed on the Web server. Please specify the output filename to be generated.
+S_19 Save &as:
+B_BROWSE_OUT B&rowse...
+B_EASYMODE Set the VPN Client Manager to &Easy Mode when Installation
+
+
+PREFIX D_UPDATE_NOTICE
+CAPTION Updates of %s
+IDOK &Show the Update Information...
+B_CONFIG &Configure Update...
+IDCANCEL &Do Not Show this Message Again
+S_INFO The latest version of %s is released. You can download it and update now.
+S_PRODUCT Software:
+S_CURRENT Current Version:
+S_CURRENT_STR Ver %u.%02u.%04u%s
+S_LATEST Latest Version:
+S_LATEST_STR Ver %S%s
+
+
+PREFIX D_UPDATE_CONFIG
+CAPTION Configuration of Update Notification
+S_INFO Checks the new versions of %s periodically and popup a notification when a new version will be released.\r\n\r\nHTTPS packets will be used between this computer and the SoftEther Update server located in Tsukuba-city, Ibaraki-prefecture, Japan in order to check updates. No personal information will be sent.
+S_TITLE %s Update and Notify Settings
+S_ENABLE &Enable Update Checks
+S_DISBLE &Disable Update Checks
+IDCANCEL &Close
+
+
+PREFIX D_SM_VMBRIDGE
+CAPTION Instructions for Local Bridge on VM
+S_TITLE Using Local Bridge Function on VM
+S_1 It has been detected that the VPN Server might be running on a VM (Virtual Machine) suchlike VMware or Hyper-V. Read the following instructions carefully. If you are not using a VM, please ignore this message.
+S_2 Some VMs prohibit the "Promiscuous Mode" (MAC Address Spoofing) on the network adapters by default.\r\n\r\nIf the Promiscuous Mode (MAC Address Spoofing) is administratively disabled, the Local Bridge function between a Virtual Hub on the VPN Server and a physical network adapter on the physical computer does not work well. You should allow the Promiscuous Mode (MAC Address Spoofing) by using the configuration tool of the VM.\r\n\r\nFor details please refer the documents of your VM. If it is a shared-VM and administrated by other person, please request the administrator to permit the use of the Promiscuous (MAC Address Spoofing) Mode to your VM.
+S_BOLD Instructions
+IDCANCEL &OK
+
+
+PREFIX D_SM_AZURE
+CAPTION VPN Azure Service Settings
+S_TITLE VPN Azure Cloud VPN Service (Free)
+S_1 VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.
+S_2 You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.
+S_3 VPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Press the right button to see details and how-to-use instructions.
+B_BOLD VPN Azure Setting
+R_ENABLE &Enable VPN Azure
+R_DISABLE &Disable VPN Azure
+S_HOSTNAME_BORDER Current VPN Azure Hostname
+S_HOSTNAME_INFO The VPN Azure hostname is same to the Dynamic DNS hostname, but altering the domain suffix to "vpnazure.net".
+B_CHANGE Change &Hostname
+B_WEB How to Use VPN Azure\r\n(Visit the Web)
+IDCANCEL &OK
+
+
+PREFIX D_SM_PROXY
+CAPTION Connect via Proxy Server
+STATIC9 You can connect via a proxy server.
+STATIC10 Proxy &Type:
+R_DIRECT_TCP &Direct TCP/IP Connection (No Proxy)
+R_HTTPS Connect via H&TTP Proxy Server
+R_SOCKS Connect via S&OCKS Proxy Server
+B_PROXY_CONFIG P&roxy Server Setting
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_VGC_LIST
+CAPTION VPN Gate Academic Experimental Project Plugin for SoftEther VPN Client
+S_TITLE VPN Gate Public VPN Relay Servers
+S_INFO1 Gain freedom access to Internet by using VPN connection via Public VPN Servers provided by volunteers abound the world. Bypass your local malfunctioning firewall's packet blocking, and hide your IP address safely.
+IDOK &Connect to the VPN Server
+B_PROXY &Proxy Settings
+S_VLAN Virtual Network Adapter:
+B_WEB VPN Gate Academic\r\nWeb Site
+B_REFRESH &Refresh List
+S_REFRESH Refreshing the List...
+S_RESEARCH Academic project at University of Tsukuba, Japan.
+S_INFO9 A VPN Server with higher Line Speed (measured by Mbps) and smaller Ping result are usually more comfortable to use. You might be able to browse websites which are normally unreachable from your area if you use VPN servers that are not in your area.
+
+
+PREFIX D_VGC_PROTOCOL
+CAPTION Select VPN Protocol to Connect
+S_TITLE The Public VPN Relay Server "%S" (%S) supports both TCP and UDP as VPN protocol.
+S_INFO Select preferred VPN Protocol to use in order to connect the VPN Server "%S" (%S). In general, the TCP protocol is easy to pass through the firewall. Try the UDP protocol only if the TCP was failed.
+R_TCP Use &TCP Protocol (Ethernet over HTTPS VPN) (Recommended)
+R_UDP Use &UDP Protocol (Ethernet over UDP VPN)
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_VGS_CONFIG
+CAPTION VPN Gate Service Control Panel
+R_ENABLE &Enable the VPN Gate Relay Service and Join the VPN Gate Research as a Volunteer.
+S_TITLE Join the VPN Gate Academic Research Project?
+S_INFO1 VPN Gate is an academic experiment for the research on the 'Distributed Public VPN Relay Server' technology, operated at the Graduate School on University of Tsukuba, Japan. VPN Gate Client users can connect to VPN Gate Services running on Public VPN Relay Servers, and enjoy unrestricted Internet access via the VPN Relay Server.
+S_INFO9 When a VPN Gate Client user accesses to a server on Internet, the source IP address will be replaced to the IP address of the relaying Public VPN Server. Consequently, the VPN Gate Client user will be able to browse overseas web sites smoothly even if the user's local firewall is out of order by an unknown reason and unable to pass such an access.
+S_WARNING If you check the above checkbox and press OK, the VPN Gate Relay Service will be activated on this computer. As the result, any VPN Gate Client will be able to communicate towards the Internet via the VPN Gate Relay Service. It is secure even if your computer is on the private network (e.g. corporate network) because any accesses to private IP addresses will not be permitted to pass via the VPN Gate Relay Service.
+B_OPTION VPN Gate Service &Option Settings...
+IDOK &OK
+IDCANCEL Cancel
+B_WEB &Browse http://www.vpngate.net/ ...
+
+
+PREFIX D_VGS_OPTION
+CAPTION VPN Gate Service Options
+S_TITLE VPN Gate Service Options
+S_1 This computer will be a Public VPN Server. Please fill the operator's information of the server. The information will be published on the list at www.vpngate.net and other related services. The contact address will be also used to contact from VPN Gate Academic Project operators.
+S_2 Operator:
+S_3 &Operator of Server:
+S_19 (Up to 64 letters)
+S_20 &Abuse Report Address\r\n(e-mail addresses etc.):
+S_21 (Up to 64 letters)
+S_22 The &Message to Users:\r\n(Up to 128 letters)
+S_23 The message will be shown on the list of VPN Gate Servers. Enter an enjoyable message to let users feel pleasure.
+S_24 VPN Settings:
+R_LOG &Save VPN Packet Logs (Recommended)
+R_2WEEKS Auto Delete or Archive with Encoding for Packet Logs After &Two Weeks (Recommended)
+R_PERMANENT Make Packet Logs Occupy Free Disk Space &Permanently
+R_L2TP Enable &L2TP/IPsec VPN Server Function (Recommended)
+S_25 Allows Mac OS X, iPhone, iPad and Android clients to make a VPN connection.
+B_MESSAGE Pop-up Your Advertisement Message on the VPN Client &Screen ...
+IDOK &OK
+IDCANCEL Cancel
+
+
+PREFIX D_VGS_WARNING
+CAPTION Caution before Joining VPN Gate Academic Experiment
+S1 The VPN Gate Academic Experiment Service is operated as a research project at the graduate school on University of Tsukuba, Japan. The service is governed under the Japanese laws. Other countries' laws are none of our concerns nor responsibilities.
+S2 By nature, there are almost 200 countries in the World, with different laws. It is impossible to verify every countries' laws and regulations and make the software comply with all countries' laws in advance to release the software. If a user uses VPN Gate service in a specific country, and damaged by public servants of the authority, the developer of either the service or software will never be liable to recover or compensate such damages or criminal responsibilities.
+S3 By using this software and service, the user must observe all concerned laws and rules with user's own responsibility. The user will be completely liable to any damages and responsibilities which are results of using this software and service, regardless of either inside or outside of Japan's territory.
+S4 If you don't agree nor understand the above warnings, do not use any of VPN Gate Academic Experiment Service functions.
+S5 Note: VPN Gate is a research project for just academic purpose only. VPN Gate was developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN Gate were developed on this research project at University of Tsukuba. Any parts of VPN Gate are not developed by SoftEther VPN Project. The VPN Gate Research Project is not a subject to be led, operated, promoted nor guaranteed by SoftEther VPN Project.
+R_NEVER Do Not &Show This Message Again
+B_WEB Visit VPN Gate &Web Site...
+IDOK &Agree
+IDCANCEL &Disagree
+S_BOLD Caution! Do Not Use the VPN Gate Services in Countries where VPN Communications are Prohibited.
+
+
+
+
+###########################################################################
+# #
+#String data of menus in software #
+# #
+###########################################################################
+
+
+# Connection Manager menu
+PREFIX CM_MENU
+# [Connect] menu
+CMD_TOP_CONNECT &Connect
+CMD_CONNECT C&onnect\tEnter
+CMD_STATUS View &Status...\tCtrl+S
+CMD_DISCONNECT D&isconnect\tCtrl+D
+CMD_DISCONNECT_ALL Disconnect &All\tCtrl+I
+CMD_NEW &New VPN Connection Setting...\tCtrl+N
+CMD_CLONE &Copy\tCtrl+C
+CMD_SHORTCUT Create VPN Connection S&hortcut...
+CMD_EXPORT_ACCOUNT E&xport VPN Connection Setting...
+CMD_IMPORT_ACCOUNT Im&port VPN Connection Setting...
+CMD_STARTUP Se&t as Startup Connection\tCtrl+T
+CMD_NOSTARTUP R&emove Startup Connection
+CMD_RECENT Recent &VPN Servers
+CMD_RENAME Rena&me\tF2
+CMD_DELETE &Delete\tDel
+CMD_PROPERTY P&roperties...\tAlt+Enter
+CMD_EXIT Cl&ose Connection Manager\tAlt+F4
+CMD_QUIT E&xit Connection Manager Program\tAlt+Q
+# [Edit] menu
+CMD_TOP_EDIT &Edit
+CMD_SELECT_ALL Select &All\tCtrl+A
+CMD_SWITCH_SELECT Sw&itch Selection
+# [View] menu
+CMD_TOP_VIEW &View
+CMD_STATUSBAR Show &Status Bar
+CMD_VISTASTYLE Windows Vista / Windows 7 Styles
+CMD_SHOWPORT Show &Ports on Connection List
+CMD_TRAYICON Show Icons on &Task Tray
+CMD_ICON &Icon
+CMD_DETAIL &Detail
+CMD_GRID Display &Grid
+CMD_REFRESH &Refresh\tF5
+# [VLAN] menu
+CMD_TOP_VLAN Virtua&l Adapter
+CMD_NEW_VLAN &New Virtual Network Adapter...\tCtrl+L
+CMD_ENABLE_VLAN &Enable Virtual Network Adapter\tCtrl+E
+CMD_DISABLE_VLAN Dis&able Virtual Network Adapter\tCtrl+B
+CMD_DELETE_VLAN &Delete Virtual Network Adapter\tDel
+CMD_REINSTALL &Reinstall Driver...\tCtrl+U
+CMD_WINNET Open Windows Network Connections...\tCtrl+W
+# [Connect] menu
+CMD_TOP_SECURE &Smart Card
+CMD_SECURE_MANAGER Smart Card &Manager...\tCtrl+G
+CMD_SECURE_SELECT &Select a Smart Card to Use...
+# [Tools] menu
+CMD_TOP_TOOL &Tools
+CMD_PASSWORD Set &Password...\tCtrl+P
+CMD_TRUST Manage &Trusted CA Certificate List\tCtrl+R
+CMD_NETIF &Network Device Status...
+CMD_TCPIP TCP Optimization &Utility...
+CMD_MMCSS Optimization for Windows &Vista / 7 / 8...
+CMD_TRAFFIC Network T&raffic Speed Test Tool...\tCtrl+Q
+CMD_CM_SETTING Switch Operation &Mode...
+CMD_LANGUAGE &Language Settings...
+CMD_OPTION &Options...\tCtrl+O
+# [Voice] menu
+CMD_TOP_VOICE V&oice
+CMD_VOIDE_NONE Voice Gui&de Off
+CMD_VOICE_NORMAL &Normal Voice Guide
+CMD_VOICE_ODD Extended V&oice Guide
+# [Help] menu
+CMD_TOP_HELP &Help
+CMD_ABOUT &About...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+###########################################################################
+# #
+# Command prompt string data #
+# #
+###########################################################################
+
+PREFIX NULL
+
+# Console system general
+CON_INFILE_ERROR Error: Unable to open the specified input file "%s".
+CON_OUTFILE_ERROR Error: Unable to create the specified output file "%s".
+CON_INFILE_START The commands written in the file "%s" will be used instead of input from keyboard.
+CON_OUTFILE_START The message output to the console will be saved in the file "%s".
+CON_USER_CANCEL [EOF]
+CON_UNKNOWN_CMD "%S": Command not found. \nYou can use the HELP command to view a list of the available commands.
+CON_AMBIGIOUS_CMD "%S": The command-name is ambiguous.
+CON_AMBIGIOUS_CMD_1 The specified command name matches the following multiple commands.
+CON_AMBIGIOUS_CMD_2 Please re-specify the command name more strictly.
+CON_INVALID_PARAM The parameter "/%S" has been specified. It is not possible to specify this parameter when using the command "%S". Input "%S /HELP" to see the list of what parameters can be used.
+CON_AMBIGIOUS_PARAM "%S": The parameter name is ambiguous.
+CON_AMBIGIOUS_PARAM_1 The specified parameter name matches with the following parameters that can be specified as a parameter of command "%S".
+CON_AMBIGIOUS_PARAM_2 Please re-specify the parameter name more strictly.
+
+
+# Unknown command
+CMD_UNKNOWM There is no description for this command.
+CMD_UNKNOWN_HELP There is no detailed description for this command. If you would like to know more detail about this command, please refer to the manual or online documentation.
+CMD_UNKNOWN_ARGS There is no command execution example.
+CMD_UNKNOWN_PARAM There is no description for this parameter.
+
+
+# Strings being used within console system
+CMD_HELP_1 You can use the following %u commands:
+CMD_HELP_2 To reference the usage for each command, input "command name /?" to view a help.
+CMD_EVAL_MIN_MAX You must specify an integer in the range from %u to %u for the value.
+CMD_PROMPT Enter a value:
+CMD_EVAL_NOT_EMPTY You cannot make a blank specification.
+CMD_EVAL_SAFE The string contains unusable characters.
+CMD_EVAL_INT You must specify an integer that is not less than 1.
+CMD_HELP_TITLE Help for command "%S"
+CMD_HELP_DESCRIPTION Purpose:
+CMD_HELP_USAGE Usage:
+CMD_HELP_HELP Description:
+CMD_HELP_ARGS Parameters:
+CMD_PROPMT_PORT Input the port number:
+CMD_EVAL_PORT Port number is invalid. Specify a port number that is within the range of 1 to 65535.
+CMD_CT_STD_COLUMN_1 Item
+CMD_CT_STD_COLUMN_2 Value
+CMD_CT_STD_COLUMN_3 Description
+CMD_PARSE_IP_SUBNET_ERROR_1_6 Specify in the format of "IPv6 address/subnet mask". \nSpecify the IPv6 address by separating the hexadecimal values using colons such as "2001:200:0:1::". For the subnet mask, either specify hexadecimal values separated by colons such as "ffff:ffff:ffff:ffff::", or you can specify the bit length of subnet mask using a decimal value such as 64. \nTo specify a standalone host, specify the subnet mask as either "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" or "128". \n(Example)\n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/12\n\n
+CMD_PARSE_IP_SUBNET_ERROR_1 Specify in the format of "IPv4 address/subnet mask". \nSpecify the IPv4 address by separating the decimal values using dots such as "192.168.0.1". For the subnet mask, either specify decimal values separated by dots such as "255.255.255.0", or you can specify the bit length of subnet mask using a decimal value such as 24. \nTo specify a standalone host, specify the subnet mask as either "255.255.255.255" or "32". \n(Example)\n 192.168.0.1/24\n 192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+CMD_PARSE_IP_SUBNET_ERROR_2 The specified IP address is not a network address.
+CMD_PARSE_IP_SUBNET_ERROR_3 The specified IP address is not a network prefix address.
+CMD_EVAL_DATE_TIME_FAILED The date and time specification is invalid. \nThe date and time must be in the same format as "2005/10/08 19:30:00" where 6 integers are specified, representing year/month/day hour:minute:second separated by forward slashes, a space and then colons. Specify 4 digits for the year.
+CMD_PARSE_IP_MASK_ERROR_1_6 Specify in the format of "IPv6 address/mask". \nSpecify the IPv6 address by separating the hexadecimal values using colons such as "2001:200:0:1::". For the mask, either specify hexadecimal values separated by colons such as "ffff:ffff:ffff:ffff::", or you can specify the bit length of mask using a decimal value such as 64. \nTo specify a standalone host, specify the mask as either "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" or "128". \n(Example)\n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/12\n\n
+CMD_PARSE_IP_MASK_ERROR_1 Specify in the format of "IPv4 address/mask". \nSpecify the IPv4 address by separating the decimal values using dots such as "192.168.0.1". For the mask, either specify decimal values separated by dots such as "255.255.255.0", or you can specify the bit length of mask using a decimal value such as 24. \nTo specify a standalone host, specify the mask as either "255.255.255.255" or "32". \n(Example)\n 192.168.0.1/24\n 192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+
+
+
+# Common messages
+CMD_MSG_INVALID_HOSTNAME Specified host name is invalid.
+CMD_MSG_OK The command completed successfully.
+CMD_MSG_ALLOW Allow
+CMD_MSG_DENY Deny
+CMD_MSG_INFINITE Infinite
+CMD_MSG_ENABLE Enable
+CMD_MSG_DISABLE Disable
+CMD_MSG_LOAD_CERT_FAILED Unable to read the specified X.509 certificate file.
+CMD_MSG_SAVE_CERT_FAILED Failed to write the X.509 certificate file.
+CMD_ACCOUNT_COLUMN_NAME VPN Connection Setting Name
+CMD_ACCOUNT_COLUMN_HOSTNAME Destination VPN Server Host Name
+CMD_ACCOUNT_COLUMN_PORT Destination VPN Server Port Number
+CMD_ACCOUNT_COLUMN_HUBNAME Destination VPN Server Virtual Hub Name
+CMD_ACCOUNT_COLUMN_PROXY_TYPE Proxy Server Type
+CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME Proxy Server Host Name
+CMD_ACCOUNT_COLUMN_PROXY_PORT Proxy Server Port Number
+CMD_ACCOUNT_COLUMN_PROXY_USERNAME Proxy Server User Name
+CMD_ACCOUNT_COLUMN_SERVER_CERT_USE Verify Server Certificate
+CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME Registered Server Individual Certificate
+CMD_ACCOUNT_COLUMN_DEVICE_NAME Device Name Used for Connection
+CMD_ACCOUNT_COLUMN_AUTH_TYPE Authentication Type
+CMD_ACCOUNT_COLUMN_AUTH_USERNAME User Name
+CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME Client Certificate for Authentication Use
+CMD_ACCOUNT_COLUMN_NUMTCP Number of TCP Connections to Use in VPN Communication
+CMD_ACCOUNT_COLUMN_TCP_INTERVAL Interval between Establishing Each TCP Connection
+CMD_ACCOUNT_COLUMN_TCP_TTL Connection Life of Each TCP Connection
+CMD_ACCOUNT_COLUMN_TCP_HALF Use Half Duplex Mode
+CMD_ACCOUNT_COLUMN_ENCRYPT Encryption by SSL
+CMD_ACCOUNT_COLUMN_COMPRESS Data Compression
+CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER Connect by Bridge / Router Mode
+CMD_ACCOUNT_COLUMN_MONITOR Connect by Monitoring Mode
+CMD_ACCOUNT_COLUMN_NO_TRACKING No Adjustment for Routing Table
+CMD_ACCOUNT_COLUMN_QOS_DISABLE Do not Use QoS Control Function
+
+
+# Debugging Information Collecting Tool
+CMD_DEBUG_SOFTNAME Debugging Information Collecting Tool
+CMD_DEBUG_PRINT Debugging Information Collecting Tool\r\n\r\n
+CMD_DEBUG_NOT_2000 Windows 2000 or later is required.
+CMD_DEBUG_NOT_ADMIN You must login as Administrators on Windows to execute this command.
+CMD_DEBUG_UAC_FAILED Failed to obtain the Administrators privilege.
+CMD_DEBUG_SAVE_TITLE Specify Destination Path to Save File
+CMD_DEBUG_OK A debugging information file was saved as "%s".\r\n\r\nSend this file to your support staff.\r\nYou must verify the contents of this file before sending it to the support staff.\r\nRemove confidential information on this file with your responsibility and by yourself if there are some confidential information which you don't want to disclose it to the staff.\r\n\r\nIf you ignore the confidential information contained on the file, and you agree to send the entire file to the support staff, it means that you have agreed to disclose the entire contents of the file to the support staff.
+CMD_DEBUG_NG Failed to save the debugging information as "%s".
+
+
+
+# TEST command
+CMD_TEST Executing test operation.
+CMD_TEST_HELP This is a test command. Executing test operation. With the test command, you can specify a number of arguments. You can omit the number of arguments.
+CMD_TEST_ARGS Test [/A1:a_str] [/A2:b_str] [/A3:int_value]
+CMD_TEST_A1 Specifies parameter A1. This can be omitted.
+CMD_TEST_A2 Specifies parameter A2. If this is omitted, a prompt will be displayed to input parameter A2 when the command is executed. You cannot make a blank specification.
+CMD_TEST_A3 Specify a numeric value. You must specify an integer that is within the range of 1 to 100. Specifying an integer outside that range will cause an error message to be displayed.
+CMD_TEST_EVAL_A2 You cannot make a blank specification for parameter A2.
+CMD_IP_EVAL_FAILED The IP address is incorrectly specified.
+CMD_HOSTPORT_EVAL_FAILED The host name and port number specification is invalid. \nPlease specify using the format of host name:port number, or IP address:port number.
+CMD_PORTLIST_EVAL_FAILED The port number list specification is invalid. \nThe list must have at least one port number set, and it is also possible to set multiple port numbers. When specifying multiple port numbers, separate them using a comma such as "443,992,8888".
+CMD_PROTOCOL_EVAL_FAILED The protocol is incorrectly specified. Specify either ip, tcp, udp, icmpv4, icmpv6 or a protocol number (0 to 255) for the protocol.
+CMD_PORT_RANGE_EVAL_FAILED The port number or the port number range was incorrectly specified. If specifying only one port number, an integer must be used to specify that port number. If specifying multiple ports, specify the beginning port number and the end port number joined together by a hyphen like "80-443".
+CMD_TCP_CONNECTION_STATE_EVAL_FAILED The TCP connection state specification is invalid. Specify either "Established" or "Unestablished" and specify TCP when selecting protocol.
+CMD_MAC_ADDRESS_AND_MASK_EVAL_FAILED The MAC address and mask specification is invalid. Use hexadecimal number with the separators, "-" or ":", and without the separators. An example is "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-FF".
+CMD_EXEC_MSG_NAME %S command - %s
+CMD_ID ID
+CMD_FILE_NOT_FOUND Cannot find specified file "%s".
+CMD_FILE_NAME_EMPTY The file name is not specified.
+CMD_SAVECERTPATH Save X.509 certificate to file name:
+CMD_SAVECERT_FAILED Failed to save the certificate file.
+CMD_SAVEKEYPATH Save private key to file name:
+CMD_SAVEKEY_FAILED Failed to save the private key file.
+CMD_SAVEFILE_FAILED Failed to save the file.
+CMD_LOADFILE_FAILED Failed to open the file.
+CMD_LOADCERTPATH Read X.509 certificate from file name:
+CMD_LOADCERT_FAILED Failed to read certificate file.
+CMD_LOADKEYPATH Read private key from file name:
+CMD_LOADKEY_FAILED Failed to read private key file.
+CMD_LOADKEY_ENCRYPTED_1 The specified private key file is protected by a passphrase.
+CMD_LOADKEY_ENCRYPTED_2 Please enter the passphrase:
+CMD_LOADKEY_ENCRYPTED_3 The passphrase is incorrect.
+CMD_KEYPAIR_FAILED The X.509 certificate and private key combination was incorrectly specified. \r\nA certificate and a private key that corresponds to that certificate is required.
+CMD_CERT_NOT_EXISTS The certificate is not registered.
+CMD_NO_SETTINGS -
+CMD_DISCONNECTED_MSG \n--- Error ---\n\nThe communication session with the host you were managing was disconnected. From now on, if you run any commands an error will occur. \n\nTo reconnect to the host you were managing, first leave the prompt by inputting "EXIT" and then reconnect. \n\n
+
+
+# VPNCMD コマンド
+CMD_VPNCMD SoftEther VPN Command Line Management Utility
+CMD_VPNCMD_HELP The 'vpncmd' program is a utility that allows you to manage SoftEther VPN software by using command lines. By using vpncmd, you can connect to a VPN Client, a VPN Server or VPN Bridge that is running on a local or remote computer and manage these services. Moreover, by using VPN Tools mode, you can call the Network Traffic Speed Test Tool and the certificate creation function. These can be used even when not connected to the VPN Server or VPN Client. \nWhen using vpncmd, if the file name is specified by using the /IN and /OUT parameter, the command can be executed in a batch according to a file in which the executable commands are enumerated and the execution results can be written to a file. Normally a command prompt will appear after vpncmd is launched but when an input file is specified by the /IN parameter, the program will automatically terminate after the execution of all lines in the input file is complete. Also, when a command to execute is specified by the /CMD parameter, the program will automatically terminate after the execution of that command is complete. You cannot specify the /IN parameter and the /CMD parameter at the same time. The termination code of the vpncmd program will be the error code of the last executed command (0 in the case of successful execution). \nUnder a Windows environment, when vpncmd is launched once or more by a user with administrator privileges, it is possible to simply input 'vpncmd' to a Windows command prompt or [Run...] window to launch vpncmd. To achieve the same result under a UNIX system, you can manually set, as appropriate, the PATH environment variable.
+CMD_VPNCMD_ARGS vpncmd [host:port] [/CLIENT|/SERVER|/TOOLS] [/HUB:hub] [/ADMINHUB:adminhub] [/PASSWORD:password] [/IN:infile] [/OUT:outfile] [/CMD commands...]
+CMD_VPNCMD_[host:port] By specifying parameters in the format "host name:port number", a connection will automatically be made to that host. If this is not specified, a prompt will appear to input the connection destination. When connecting to a VPN Client, you cannot specify a port number.
+CMD_VPNCMD_CLIENT This will connect to VPN Client to do management. You cannot specify it together with /SERVER.
+CMD_VPNCMD_SERVER This will connect to VPN Server or VPN Bridge to do management. You cannot specify it together with /CLIENT.
+CMD_VPNCMD_TOOLS This will enables use of VPN Tools commands. VPN Tools include the simple certificate creation tool (MakeCert command) and the Network Traffic Speed Test Tool (SpeedTest command).
+CMD_VPNCMD_HUB When connecting to the VPN Server by "Virtual Hub Admin Mode", this specifies the Virtual Hub name 'hub'. If you specify the host name but not the /HUB parameter, connection will be by "Server Admin Mode".
+CMD_VPNCMD_ADMINHUB This will specify the name of the Virtual Hub 'adminhub' that is automatically selected after connecting to the VPN Server. If the /HUB parameter was specified, the Virtual Hub will be selected automatically and this specification will not be necessary.
+CMD_VPNCMD_PASSWORD If the administrator password is required when connecting, specify the password 'password'. When the password is not specified, a prompt to input the password will be displayed.
+CMD_VPNCMD_IN This will specify the text file 'infile' that contains the list of commands that are automatically executed after the connection is completed. If the /IN parameter is specified, the vpncmd program will terminate automatically after the execution of all commands in the file are finished. If the file contains multiple-byte characters, the encoding must be Unicode (UTF-8). This cannot be specified together with /CMD (if /CMD is specified, /IN will be ignored).
+CMD_VPNCMD_OUT You can specify the text file 'outfile' to write all strings such as onscreen prompts, message, error and execution results. Note that if the specified file already exists, the contents of the existing file will be overwritten. Output strings will be recorded using Unicode (UTF-8) encoding.
+CMD_VPNCMD_CMD If the optional command 'commands...' is included after /CMD, that command will be executed after the connection is complete and the vpncmd program will terminate after that. This cannot be specified together with /IN (if specified together with /IN, /IN will be ignored). Specify the /CMD parameter after all other vpncmd parameters.
+CMD_VPNCMD_CSV You can specify this option to enable CSV outputs. Results of each command will be printed in the CSV format. It is useful for processing the results by other programs.
+CMD_VPNCMD_CS_1 By using vpncmd program, the following can be achieved. \n\n1. Management of VPN Server or VPN Bridge \n2. Management of VPN Client\n3. Use of VPN Tools (certificate creation and Network Traffic Speed Test Tool)\n\n
+CMD_VPNCMD_CS_2 Select 1, 2 or 3:
+CMD_VPNCMD_HOST_1 Specify the host name or IP address of the computer that the destination VPN Server or VPN Bridge is operating on. \nBy specifying according to the format 'host name:port number', you can also specify the port number. \n(When the port number is unspecified, 443 is used.)\nIf nothing is input and the Enter key is pressed, the connection will be made to the port number 8888 of localhost (this computer).
+CMD_VPNCMD_HOST_2 Specify the host name or IP address of the computer that the destination VPN Client is operating on. \nIf nothing is input and Enter is pressed, connection will be made to localhost (this computer).
+CMD_VPNCMD_HOST_3 Hostname of IP Address of Destination:
+CMD_VPNCMD_HUB_1 If connecting to the server by Virtual Hub Admin Mode, please input the Virtual Hub name. \nIf connecting by server admin mode, please press Enter without inputting anything.
+CMD_VPNCMD_HUB_2 Specify Virtual Hub Name:
+CMD_VPNCMD_ABOUT SoftEther VPN Command Line Management Utility (vpncmd command)\n%S\n%S\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n
+CMD_VPNCMD_PASSWORD_1 Access was denied. Possibly the password is incorrect, or perhaps you are connecting by an incorrect admin mode. You can try inputting the password again. To cancel, press Ctrl+D.
+CMD_VPNCMD_PASSWORD_2 Password:
+CMD_VPNCMD_ERROR Error occurred. (Error code: %u)\n%s
+CMD_VPNCMD_SERVER_CONNECTED Connection was established with VPN Server "%S" (port %u).
+CMD_VPNCMD_SERVER_CONNECTED_1 You have administrator privileges for the entire VPN Server.
+CMD_VPNCMD_SERVER_CONNECTED_2 You have administrator privileges for Virtual Hub '%S' on the VPN Server.
+CMD_VPNCMD_CLIENT_NO_REMODE The destination VPN Client server does not allow administrating connections from remote computers. Launch the command line management utility or VPN Client Manager on the computer that VPN Client is running on and connect to localhost.
+CMD_VPNCMD_PWPROMPT_0 Please enter the password. To cancel press the Ctrl+D key.
+CMD_VPNCMD_PWPROMPT_1 Password:
+CMD_VPNCMD_PWPROMPT_2 Confirm input:
+CMD_VPNCMD_PWPROMPT_3 The password and the password confirmation do not match. Please input the password and confirmation again.
+CMD_VPNCMD_CLIENT_CONNECTED Connected to VPN Client "%S".
+CMD_VPNCMD_TOOLS_CONNECTED VPN Tools was launched. By inputting HELP, you can view a list of the commands that can be used.
+
+
+#######################################################
+# #
+# Management commands for VPN Server are listed below #
+# #
+#######################################################
+
+
+
+# About command
+CMD_About Display the version information
+CMD_About_HELP This displays the version information of this command line management utility. Included in the version information are the vpncmd version number, build number and build information.
+CMD_About_ARGS About
+
+
+# ServerInfoGet command
+CMD_ServerInfoGet Get server information
+CMD_ServerInfoGet_Help This allows you to obtain the server information of the currently connected VPN Server or VPN Bridge. Included in the server information are the version number, build number and build information. You can also obtain information on the current server operation mode and the information of operating system that the server is operating on.
+CMD_ServerInfoGet_Args ServerInfoGet
+
+
+# ServerStatusGet command
+CMD_ServerStatusGet Get Current Server Status
+CMD_ServerStatusGet_Help This allows you to obtain in real-time the current status of the currently connected VPN Server or VPN Bridge. You can get statistical information on data communication and the number of different kinds of objects that exist on the server. You can get information on how much memory is being used on the current computer by the OS.
+CMD_ServerStatusGet_Args ServerStatusGet
+
+
+# ListenerCreate command
+CMD_ListenerCreate Create New TCP Listener
+CMD_ListenerCreate_Help This allows you to create a new TCP Listener on the server. By creating the TCP Listener the server starts listening for a connection from clients at the specified TCP/IP port number. \nA TCP Listener that has been created can be deleted by the ListenerDelete command. \nYou can also get a list of TCP Listeners currently registered by using the ListenerList command. \nnTo execute this command, you must have VPN Server administrator privileges.
+CMD_ListenerCreate_Args ListenerCreate [port]
+CMD_ListenerCreate_[port] Using an integer, specify the newly added TCP/IP listener port number. You can also use a port number that is already being used by a different program; however the VPN Server will not be able to use it until that program ends the use of that port. Specify a port number that is within the range of 1 to 65535.
+CMD_ListenerCreate_PortPrompt Port number of newly added TCP/IP Listener:
+
+
+# ListenerDelete command
+CMD_ListenerDelete Delete TCP Listener
+CMD_ListenerDelete_Help This allows you to delete a TCP Listener that's registered on the server. When the TCP Listener is in a state of operation, the listener will automatically be deleted when its operation stops. \nYou can also get a list of TCP Listeners currently registered by using the ListenerList command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ListenerDelete_Args ListenerDelete [port]
+CMD_ListenerDelete_[port] Using an integer, specify the TCP/IP listener port number you want to delete.
+CMD_ListenerDelete_PortPrompt Port number of TCP/IP Listener:
+
+
+# ListenerList command
+CMD_ListenerList Get List of TCP Listeners
+CMD_ListenerList_Help This allows you to get a list of TCP listeners registered on the current server. You can obtain information on whether the various TCP listeners have a status of operating or error. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ListenerList_Args ListenerList
+CMD_ListenerList_Column1 TCP Port Number
+CMD_ListenerList_Column2 Status
+
+
+# ListenerEnable command
+CMD_ListenerEnable Begin TCP Listener Operation
+CMD_ListenerEnable_Help This starts the operation of stopped TCP Listeners registered on the current server. \nYou can also get a list of TCP Listeners currently registered by using the ListenerList command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ListenerEnable_Args ListenerEnable [port]
+CMD_ListenerEnable_[port] Using an integer, specify the port number of the TCP/IP listener you want to start.
+CMD_ListenerEnable_PortPrompt Port number of TCP/IP Listener to start:
+
+
+# ListenerDisable command
+CMD_ListenerDisable Stop TCP Listener Operation
+CMD_ListenerDisable_Help This stops the operation of operating TCP Listeners registered on the current server. \nYou can also get a list of TCP Listeners currently registered by using the ListenerList command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ListenerDisable_Args ListenerDisable [port]
+CMD_ListenerDisable_[port] Using an integer, specify the port number of the TCP/IP listener you want to stop.
+CMD_ListenerDisable_PortPrompt Port number of TCP/IP Listener to start:
+
+
+# ServerPasswordSet command
+CMD_ServerPasswordSet Set VPN Server Administrator Password
+CMD_ServerPasswordSet_Help This sets the VPN Server administrator password. You can specify the password as a parameter. If the password is not specified, a prompt will be displayed to input the password and password confirmation. If you include the password as a parameter, this password will be displayed momentarily on the screen, which poses a risk. We recommend that whenever possible, avoid specifying this parameter and input the password using the password prompt. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ServerPasswordSet_Args ServerPasswordSet [password]
+CMD_ServerPasswordSet_[password] This specifies a new password setting.
+
+
+# ClusterSettingGet command
+CMD_ClusterSettingGet Get Clustering Configuration of Current VPN Server
+CMD_ClusterSettingGet_Help You can use this to acquire the clustering configuration of the current VPN Server. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ClusterSettingGet_Args ClusterSettingGet
+CMD_ClusterSettingGet_Current Current Configuration
+CMD_ClusterSettingGet_None (No setting)
+CMD_ClusterSettingGet_PublicIp Public IP Address
+CMD_ClusterSettingGet_PublicPorts List of Public Ports
+CMD_ClusterSettingGet_Controller Destination Controller
+CMD_ClusterSettingGet_ControllerOnly Controller Function Only
+CMD_ClusterSettingGet_Weight Performance Standard in Cluster
+
+
+# ClusterSettingStandalone command
+CMD_ClusterSettingStandalone Set VPN Server Type as Standalone
+CMD_ClusterSettingStandalone_Help Use this to set the VPN Server type as Standalone Server. Standalone server means a VPN Server that does not belong to any cluster in its current state. When VPN Server is installed, by default it will be in standalone server mode. Unless you have particular plans to configure a cluster, we recommend the VPN Server be operated in standalone mode. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, when this command is executed, VPN Server will automatically restart. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterSettingStandalone_Args ClusterSettingStandalone
+
+
+# ClusterSettingController command
+CMD_ClusterSettingController Set VPN Server Type as Cluster Controller
+CMD_ClusterSettingController_Help Use this to set the VPN Server type as Cluster Controller. A cluster controller is the central computer of all member servers of a cluster in the case where a clustering environment is made up of multiple VPN Servers. A cluster requires one computer to serve this role. The other cluster member servers that are configured in the same cluster begin operation as a cluster member by connecting to the cluster controller. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, when this command is executed, VPN Server will automatically restart. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterSettingController_Args ClusterSettingController [/WEIGHT:weight] [/ONLY:yes|no]
+CMD_ClusterSettingController_WEIGHT This sets a value for the performance standard ratio of this VPN Server. This is the standard value for when load balancing is performed in the cluster. Normally it is 100. For example, making only one machine 200 while the other members have a status of 100, will regulate that machine to receive twice as many connections as the other members during load balancing. Specify 1 or higher for the value. If this parameter is left unspecified, 100 will be used.
+CMD_ClusterSettingController_ONLY By specifying "yes" here, the VPN Server will operate only as a controller on the cluster and it will always distribute general VPN Client connections to members other than itself. This function is used in high-load environments. If this parameter is left unspecified, "no" will be used.
+
+
+# ClusterSettingMember command
+CMD_ClusterSettingMember Set VPN Server Type as Cluster Member
+CMD_ClusterSettingMember_Help Use this to set the VPN Server type as Cluster Member Server. A cluster member server is a member computer belonging to a clustering configuration made up of multiple VPN Servers with another existing cluster controller as the center. Multiple cluster members can be added to the cluster as required. \nBefore setting the VPN Server as a cluster member server, first ask the administrator of the cluster controller to be used for the controller's IP address and port number, the public IP address and public port number (when required) of this VPN Server and the password. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, when this command is executed, VPN Server will automatically restart. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterSettingMember_Args ClusterSettingMember [server:port] [/IP:ip] [/PORTS:ports] [/PASSWORD:password] [/WEIGHT:weight]
+CMD_ClusterSettingMember_[server:port] Specify the host name or IP address, and port number of the destination cluster controller using the parameter with the format host name:port number.
+CMD_ClusterSettingMember_IP Specify the public IP address of this server. If you wish to leave public IP address unspecified, specify it like this: "/IP:none". When a public IP address is not specified, the IP address of the network interface used when connecting to the cluster controller will be automatically used.
+CMD_ClusterSettingMember_PORTS Use this to specify the list of public port numbers on this server. The list must have at least one public port number set, and it is also possible to set multiple public port numbers. When specifying multiple port numbers, separate them using a comma such as "/PORTS443,992,8888".
+CMD_ClusterSettingMember_PASSWORD Specify the password required to connect to the destination controller. It needs to be the same as an administrator password on the destination controller.
+CMD_ClusterSettingMember_WEIGHT This sets a value for the performance standard ratio of this VPN Server. This is the standard value for when load balancing is performed in the cluster. For example, making only one machine 200 while the other members have a status of 100, will regulate that machine to receive twice as many connections as the other members. Specify 1 or higher for the value. If this parameter is left unspecified, 100 will be used.
+CMD_ClusterSettingMember_Prompt_IP_1 Specify a public IP address. \nIf you wish to leave this unspecified, press Enter without inputting anything.
+CMD_ClusterSettingMember_Prompt_IP_2 Public IP Address:
+CMD_ClusterSettingMember_Prompt_PORT_1 Please specify a list of public port numbers. \nWhen specifying 2 or more port numbers, separate each entry with a comma, like: 444,992,888.
+CMD_ClusterSettingMember_Prompt_PORT_2 Public Port Number:
+CMD_ClusterSettingMember_Prompt_HOST_1 Destination Controller Host Name and Port Number:
+
+
+# ClusterMemberList command
+CMD_ClusterMemberList Get List of Cluster Members
+CMD_ClusterMemberList_Help Use this command when the VPN Server is operating as a cluster controller to get a list of the cluster member servers on the same cluster, including the cluster controller itself. \nFor each member, the following information is also listed. Type, Connection Start, Host Name, Points, Number of Session, Number of TCP Connections, Number of Operating Virtual Hubs, Using Client Connection License and Using Bridge Connection License. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterMemberList_Args ClusterMemberList
+
+
+# ClusterMemberInfoGet command
+CMD_ClusterMemberInfoGet Get Cluster Member Information
+CMD_ClusterMemberInfoGet_Help When the VPN Server is operating as a cluster controller, you can get information on cluster member servers on that cluster by specifying the IDs of the member servers. \nYou can get the following information about the specified cluster member server: Server Type, Time Connection was Established, IP Address, Host Name, Points, Public Port List, Number of Operating Virtual Hubs, First Virtual Hub, Number of Sessions and Number of TCP Connections. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterMemberInfoGet_Args ClusterMemberInfoGet [id]
+CMD_ClusterMemberInfoGet_[id] Specify the ID of the cluster member whose information you want to get. You can obtain the cluster member server ID by using the ClusterMemberList command.
+CMD_ClusterMemberInfoGet_PROMPT_ID Cluster Member ID to Get Info:
+
+
+# ClusterMemberCertGet command
+CMD_ClusterMemberCertGet Get Cluster Member Certificate
+CMD_ClusterMemberCertGet_Help When the VPN Server is operating as a cluster controller, you can get the public X.509 certificate of cluster member servers on that cluster by specifying the IDs of those member servers. You can save the certificate as an X.509 format file. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterMemberCertGet_Args ClusterMemberCertGet [id] [/SAVECERT:cert]
+CMD_ClusterMemberCertGet_[id] Specify the ID of the cluster member whose certificate you want to get. You can obtain the cluster member server ID by using the ClusterMemberList command.
+CMD_ClusterMemberCertGet_SAVECERT Specify the file path name to save the certificate you obtained. You can save the certificate in X.509 format.
+CMD_ClusterMemberCertGet_PROMPT_ID Cluster Member ID to Get Certificate:
+
+# ClusterConnectionStatusGet command
+CMD_ClusterConnectionStatusGet Get Connection Status to Cluster Controller
+CMD_ClusterConnectionStatusGet_Help Use this command when the VPN Server is operating as a cluster controller to get the status of connection to the cluster controller. \nYou can get the following information: Controller IP Address, Port Number, Connection Status, Connection Start Time, First Connection Established Time, Current Connection Established Time, Number of Connection Attempts, Number of Successful Connections, Number of Failed Connections. \nThis command cannot be run on VPN Bridge.
+CMD_ClusterConnectionStatusGet_Args ClusterConnectionStatusGet
+
+
+# Debug command
+CMD_Debug Execute a Debug Command
+CMD_Debug_Help Runs a debug command on the running VPN Server / Bridge process.\nThis command should be executed wjen the support staff requests to do so.\nMisuse of this command might cause a crash of VPN Server / Bridge running.
+CMD_Debug_Args Debug [id] [/ARG:arg]
+CMD_Debug_[id] Specify a debug command number.
+CMD_Debug_ARG Specify a string to pass to the debug command. If a string contains spaces, contains the whole command by " ".
+CMD_Debug_Msg1 Sending the debug command...
+CMD_Debug_Msg2 The debug command has executed.\nResults: \"%S\"
+
+
+# Crash command
+CMD_Crash Raise a error on the VPN Server / Bridge to terminate the process forcefully.
+CMD_Crash_Help This command will raise a fatal error (memory access violation) on the VPN Server / Bridge running process in order to crash the process. As the result, VPN Server / Bridge will be terminated and resterted if it is running as a service mode. If the VPN Server is running as a user mode, the process will not automatically restarted.\nThis command is for a situation when the VPN Server / Bridge is under a non-recoverable error or the process is in an infinite loop. This command will disconnect all VPN Sessions on the VPN Server / Bridge. All unsaved settings in the memory of VPN Server / Bridge will be lost.\nBefore run this command, run the Flush command to try to save volatile data to the configuration file.\nTo execute this command, you must have VPN Server / VPN Bridge administrator privileges.
+CMD_Crash_Args Crash [yes]
+CMD_Crash_[yes] Input "yes" for confirmation.
+CMD_Crash_Msg Sending the Crush command to the VPN Server. The VPN Server will be let to crash immediately, so you can never get the result value of this command. After this moment, vpncmd will be disconnected from the VPN Server.
+CMD_Crash_Confirm Do you really want to crash the VPN Server?\nInput "yes" if it is ok:
+CMD_Crash_Aborted The Crash command was aborted.
+
+
+# Flush command
+CMD_Flush Save All Volatile Data of VPN Server / Bridge to the Configuration File
+CMD_Flush_Help Normally, the VPN Server / VPN Bridge retains the volatile configuration data in memory. It is flushed to the disk as vpn_server.config or vpn_bridge.config periodically. The period is 300 seconds (5 minutes) by default. (The period can be altered by modifying the AutoSaveConfigSpan iten in the configuration file.) The data will be saved on the timing of shutting down normally of the VPN Server / Bridge.\nExecute the Flush command to make the VPN Server / Bridge save the settings to the file immediately. The setting data will be stored on the disk drive of the server computer. Use the Flush command in a situation that you do not have an enough time to shut down the server process normally.\nTo execute this command, you must have VPN Server administrator privileges. \nTo execute this command, you must have VPN Server / VPN Bridge administrator privileges.
+CMD_Flush_Args Flush
+CMD_Flush_Msg1 Writing volatile data from memory to the disk...\n
+CMD_Flush_Msg2 Saving completed. The file size is %S bytes.\n
+
+
+# ServerCertGet command
+CMD_ServerCertGet Get SSL Certificate of VPN Server
+CMD_ServerCertGet_Help Use this to get the SSL certificate that the VPN Server provides to the connected client. You can save the certificate as an X.509 format file.
+CMD_ServerCertGet_Args ServerCertGet [cert]
+CMD_ServerCertGet_[cert] Specify the file path name to save the certificate you obtained. You can save the certificate in X.509 format.
+
+
+# ServerKeyGet command
+CMD_ServerKeyGet Get SSL Certificate Private Key of VPN Server
+CMD_ServerKeyGet_Help Use this to get the SSL certificate private key that the VPN Server provides to the connected client. You can save the private key as a Base 64 encoded file. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ServerKeyGet_Args ServerKeyGet [key]
+CMD_ServerKeyGet_[key] Specify the file path name to save the private key you obtained. You can save the private key in a Base 64 encoded format.
+
+
+# ServerCertSet command
+CMD_ServerCertSet Set SSL Certificate and Private Key of VPN Server
+CMD_ServerCertSet_Help You can set the SSL certificate that the VPN Server provides to the connected client and the private key for that certificate. The certificate must be in X.509 format and the private key must be Base 64 encoded format. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ServerCertSet_Args ServerCertSet [/LOADCERT:cert] [/LOADKEY:key]
+CMD_ServerCertSet_LOADCERT Specify the X.509 format certificate file to use.
+CMD_ServerCertSet_LOADKEY Specify the Base 64 encoded private key file for the certificate to use.
+
+
+# ServerCipherGet command
+CMD_ServerCipherGet Get the Encrypted Algorithm Used for VPN Communication.
+CMD_ServerCipherGet_Help Use this to get the current setting of the algorithm used for the electronic signature and encrypted for SSL connection to be used for communication between the VPN Server and the connected client and the list of algorithms that can be used on the VPN Server.
+CMD_ServerCipherGet_Args ServerCipherGet
+CMD_ServerCipherGet_SERVER Encrypted Algorithm Currently Used by VPN Server:
+CMD_ServerCipherGet_CIPHERS List of Usable Encrypted Algorithm Names:
+
+# ServerCipherSet command
+CMD_ServerCipherSet Set the Encrypted Algorithm Used for VPN Communication.
+CMD_ServerCipherSet_Help Use this to set the algorithm used for the electronic signature and encrypted for SSL connections to be used for communication between the VPN Server and the connected client. \nBy specifying the algorithm name, the specified algorithm will be used later between the VPN Client and VPN Bridge connected to this server and the data will be encrypted. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ServerCipherSet_Args ServerCipherSet [name]
+CMD_ServerCipherSet_[name] This specifies the encrypted and electronic signature algorithm to set. You can obtain the list of usable algorithms by using the ServerCipherGet command.
+CMD_ServerCipherSet_PROMPT_NAME Encrypted Algorithm Name to Specify:
+
+
+# KeepEnable command
+CMD_KeepEnable Enable the Keep Alive Internet Connection Function
+CMD_KeepEnable_Help This allows you to enable the Keep Alive Internet Connection Function. By using the Keep Alive Internet Connection Function for network connection environments where connections will automatically be disconnected when there are periods of no communication that are longer than a set period, it is possible to keep alive the Internet connection by sending packets to a nominated server on the Internet at set intervals. \nYou can set a destination host name etc, by using the KeepSet command. \nTo execute this command on a VPN Server or VPN Bridge, you must have administrator privileges.
+CMD_KeepEnable_Args KeepEnable
+
+
+# KeepDisable command
+CMD_KeepDisable Disable the Keep Alive Internet Connection Function
+CMD_KeepDisable_Help This allows you to disable the Keep Alive Internet Connection Function.\nTo execute this command on a VPN Server or VPN Bridge, you must have administrator privileges.
+CMD_KeepDisable_Args KeepDisable
+
+
+# KeepSet command
+CMD_KeepSet Set the Keep Alive Internet Connection Function
+CMD_KeepSet_Help Use this to set the destination host name etc. of the Keep Alive Internet Connection Function. For network connection environments where connections will automatically be disconnected where there are periods of no communication that are longer than a set period, by using the Keep Alive Internet Connection Function, it is possible to keep alive the Internet connection by sending packets to a nominated server on the Internet at set intervals. \nWhen using this command, you can specify the following: Host Name, Port Number, Packet Send Interval, and Protocol. \nPackets sent to keep alive the Internet connection will have random content and personal information that could identify a computer or user is not sent. \nYou can use the KeepEnable command or KeepDisable command to enable/disable the Keep Alive Internet Connection Function. KeepSet does not change the enabled/disabled status. \nTo execute this command on a VPN Server or VPN Bridge, you must have administrator privileges.
+CMD_KeepSet_Args KeepSet [/HOST:host:port] [/PROTOCOL:tcp|udp] [/INTERVAL:interval]
+CMD_KeepSet_HOST Specify the host name or IP address, and port number of the destination using the format "host name:port number".
+CMD_KeepSet_PROTOCOL Specify either tcp or udp.
+CMD_KeepSet_INTERVAL Specify, in seconds, the interval between the sending of packets.
+CMD_KeepSet_PROMPT_HOST Destination Host Name/IP Address and Port Number:
+CMD_KeepSet_PROMPT_PROTOCOL tcp or udp:
+CMD_KeepSet_PROMPT_INTERVAL Interval Between Packets Sends (Seconds):
+CMD_KeepSet_EVAL_TCP_UDP Please specify "tcp" or "udp".
+
+# KeepGet command
+CMD_KeepGet Get the Keep Alive Internet Connection Function
+CMD_KeepGet_Help Use this to get the current setting contents of the Keep Alive Internet Connection Function. In addition to the destination's Host Name, Port Number, Packet Send Interval and Protocol, you can obtain the current enabled/disabled status of the Keep Alive Internet Connection Function.
+CMD_KeepGet_Args KeepGet
+CMD_KeepGet_COLUMN_1 Host Name
+CMD_KeepGet_COLUMN_2 Port Number
+CMD_KeepGet_COLUMN_3 Packet Send Interval (Sec)
+CMD_KeepGet_COLUMN_4 Protocol
+CMD_KeepGet_COLUMN_5 Current Status
+
+
+# SyslogEnable command
+CMD_SyslogEnable Set syslog Send Function
+CMD_SyslogEnable_Help Use this to set the usage of syslog send function and which syslog server to use.
+CMD_SyslogEnable_Args SyslogEnable [1|2|3] [/HOST:host:port]
+CMD_SyslogEnable_[1|2|3] Specify, using an integer, 1, 2 or 3 for the setting to use the syslog send function. \n1: Send server log by syslog. \n2: Send server and Virtual Hub security logs by syslog. \n3: Send server, Virtual Hub security, and packet logs by syslog.
+CMD_SyslogEnable_HOST Specify the host name or IP address, and port number of the syslog server using the format [host name:port number]. If the port number is omitted, 514 will be used.
+CMD_SyslogEnable_MINMAX Specify, using an integer, 1, 2 or 3 for the setting to use the syslog send function.
+CMD_SyslogEnable_Prompt_123 Setting to Use syslog Send Function (1-3):
+CMD_SyslogEnable_Prompt_HOST Specify syslog Server:
+
+
+# SyslogDisable command
+CMD_SyslogDisable Disable syslog Send Function
+CMD_SyslogDisable_Help Use this to disable the syslog send function.
+CMD_SyslogDisable_Args SyslogDisable
+
+
+# SyslogGet command
+CMD_SyslogGet Get syslog Send Function
+CMD_SyslogGet_Help This allows you to get the current setting contents of the syslog send function. You can get the usage setting of the syslog function and the host name and port number of the syslog server to use.
+CMD_SyslogGet_Args SyslogGet
+CMD_SyslogGet_COLUMN_1 Set the Use of syslog Send Function
+CMD_SyslogGet_COLUMN_2 syslog Server Host Name
+CMD_SyslogGet_COLUMN_3 syslog Server Port Number
+
+
+# ConnectionList command
+CMD_ConnectionList Get List of TCP Connections Connecting to the VPN Server
+CMD_ConnectionList_Help Use this to get a list of TCP/IP connections that are currently connecting to the VPN Server. It does not display the TCP connections that have been established as VPN sessions. To get the list of TCP/IP connections that have been established as VPN sessions, you can use the SessionList command. \nYou can get the following: Connection Name, Connection Source, Connection Start and Type.\nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ConnectionList_Args ConnectionList
+
+
+# ConnectionList command
+CMD_ConnectionGet Get Information of TCP Connections Connecting to the VPN Server
+CMD_ConnectionGet_Help Use this to get detailed information of a specific TCP/IP connection that is connecting to the VPN Server. \nYou can get the following information: Connection Name, Connection Type, Source Hostname, Source IP Address, Source Port Number (TCP), Connection Start, Server Product Name, Server Version, Server Build Number, Client Product Name, Client Version, and Client Build Number. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ConnectionGet_Args ConnectionGet [name]
+CMD_ConnectionGet_[name] This allows you to specify the name of the connection whose information you want to get. To get a list of connection names, you can use the ConnectionList command.
+CMD_ConnectionGet_PROMPT_NAME Connection Name to Get Info:
+
+# ConnectionDisconnect command
+CMD_ConnectionDisconnect Disconnect TCP Connections Connecting to the VPN Server
+CMD_ConnectionDisconnect_Help Use this to forcefully disconnect specific TCP/IP connections that are connecting to the VPN Server. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ConnectionDisconnect_Args ConnectionDisconnect [name]
+CMD_ConnectionDisconnect_[name] Specify the name of the connection to disconnect. To get a list of connection names, you can use the ConnectionList command.
+CMD_ConnectionDisconnect_PROMPT_NAME Connection Name to Disconnect:
+
+
+# BridgeDeviceList command
+CMD_BridgeDeviceList Get List of Network Adapters Usable as Local Bridge
+CMD_BridgeDeviceList_Help Use this to get a list of Ethernet devices (network adapters) that can be used as a bridge destination device as part of a Local Bridge connection. If possible, network connection name is displayed. \nYou can use a device displayed here by using the BridgeCreate command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_BridgeDeviceList_Args BridgeDeviceList
+
+
+# BridgeList command
+CMD_BridgeList Get List of Local Bridge Connection
+CMD_BridgeList_Help Use this to get a list of the currently defined Local Bridge connections. \nYou can get the Local Bridge connection Virtual Hub name and the bridge destination Ethernet device (network adapter) name or tap device name, as well as the operating status.
+CMD_BridgeList_Args BridgeList
+
+
+# BridgeCreate command
+CMD_BridgeCreate Create Local Bridge Connection
+CMD_BridgeCreate_Help Use this to create a new Local Bridge connection on the VPN Server.\nBy using a Local Bridge, you can configure a Layer 2 bridge connection between a Virtual Hub operating on this VPN server and a physical Ethernet Device (Network Adapter). \nYou can create a tap device (virtual network interface) on the system and connect a bridge between Virtual Hubs (the tap device is only supported by Linux versions). \nIt is possible to establish a bridge to an operating network adapter of your choice for the bridge destination Ethernet device (network adapter), but in high load environments, we recommend you prepare a network adapter dedicated to serve as a bridge. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_BridgeCreate_Args BridgeCreate [hubname] [/DEVICE:device_name] [/TAP:yes|no]
+CMD_BridgeCreate_[hubname] Specify the Virtual Hub to create bridge. To get a list of Virtual Hubs, you can use the HubList command. It is not essential that you specify a Virtual Hub that is currently operating. If you specify a Virtual Hub name that is not currently operating or that does not exist, the Local Bridge connection will become enabled when the actual operation of that Virtual Hub begins.
+CMD_BridgeCreate_DEVICE Specify the bridge destination Ethernet device (network adapter) or tap device name. You can get the list of Ethernet device names by using the BridgeDeviceList command.
+CMD_BridgeCreate_TAP Specify yes if you are using a tap device rather than a network adapter for the bridge destination (only supported for Linux versions). When this is omitted, it will be treated the same as when no is specified.
+CMD_BridgeCreate_PROMPT_HUBNAME Virtual Hub Name to Create Bridge:
+CMD_BridgeCreate_PROMPT_DEVICE Bridge Destination Device Name:
+CMD_BridgeCreate_PROMPT_TAP Use tap device? (yes/no):
+
+
+# BridgeDelete command
+CMD_BridgeDelete Delete Local Bridge Connection
+CMD_BridgeDelete_Help Use this to delete an existing Local Bridge connection. To get a list of current Local Bridge connections use the BridgeDeviceList command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_BridgeDelete_Args BridgeDelete [hubname] [/DEVICE:device_name]
+CMD_BridgeDelete_[hubname] Specify the Virtual Hub of the Local Bridge to delete.
+CMD_BridgeDelete_DEVICE Specify the device name (network adapter or tap device name) of the Local Bridge to delete.
+CMD_BridgeDelete_PROMPT_HUBNAME Virtual Hub Name to Delete Bridge:
+CMD_BridgeDelete_PROMPT_DEVICE Bridge Device Name to Delete:
+
+
+# Caps command
+CMD_Caps Get List of Server Functions/Capability
+CMD_Caps_Help Use this get a list of functions and capability of the VPN Server currently connected and being managed. \nThe function and capability of VPN Servers are different depending on the operating VPN server's edition and version. Sometimes commands may be included in the command line management utility that cannot operate because of the function and capability of the destination VPN Server. Using this command, you can find out the capability of the target VPN Server and report it. \nIf the version of the VPN Server is newer than the command line management utility and there are functions that the command line management utility does not recognize, you can display the contents strings (variable names) as they are.
+CMD_Caps_Args Caps
+
+
+# Reboot command
+CMD_Reboot Reboot VPN Server Service
+CMD_Reboot_Help Use this to restart the VPN Server service. \nWhen you restart the VPN Server, all currently connected sessions and TCP connections will be disconnected and no new connections will be accepted until the restart process has completed. \nBy using this command, only the VPN Server service program will be restarted and the physical computer that VPN Server is operating on does not restart. This management session will also be disconnected, so you will need to reconnect to continue management. \nAlso, by specifying the /RESTCONFIG:yes parameter, the contents of the configuration file (.config) held by the current VPN Server will be initialized. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_Reboot_Args Reboot [/RESETCONFIG:yes|no]
+CMD_Reboot_RESETCONFIG By specifying yes, the contents of the configuration file (.config) held by the current VPN Server will be initialized. Please carefully consider the implications when setting this parameter.
+
+
+# ConfigGet command
+CMD_ConfigGet Get the current configuration of the VPN Server
+CMD_ConfigGet_Help Use this to get a text file (.config file) that contains the current configuration contents of the VPN server. You can get the status on the VPN Server at the instant this command is executed. \nWhen part of the contents of the configuration file does not specify a parameter, it will be displayed on screen as it is. By specifying a save destination file name by parameter, the contents will be saved by that file name. \nYou can edit the configuration file by using a regular text editor. To write an edited configuration to the VPN Server, use the ConfigSet command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ConfigGet_Args ConfigGet [path]
+CMD_ConfigGet_[path] When you want to save the contents of the configuration file to a file, use this to specify the file name. If left unspecified, the configuration contents will be displayed on screen. If the configuration file contains multiple-byte characters, the encoding must be saved as Unicode (UTF-8).
+CMD_ConfigGet_FILENAME Config name: "%S", Size: %u
+CMD_ConfigGet_FILE_SAVE_FAILED Creation of specified file failed.
+
+
+# ConfigSet command
+CMD_ConfigSet Write Configuration File to VPN Server
+CMD_ConfigSet_Help Use this to write the configuration file to the VPN Server. By executing this command, the contents of the specified configuration file will be applied to the VPN Server and the VPN Server program will automatically restart and upon restart, operate according to the new configuration contents. \nBecause it is difficult for an administrator to write all the contents of a configuration file, we recommend you use the ConfigGet command to get the current contents of the VPN Server configuration and save it to file. You can then edit these contents in a regular text editor and then use the ConfigSet command to rewrite the contents to the VPN Server. \nThis command is for people with a detailed knowledge of the VPN Server and if an incorrectly configured configuration file is written to the VPN Server, it not only could cause errors, it could also result in the lost of the current setting data. Take special care when carrying out this action. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_ConfigSet_Args ConfigSet [path]
+CMD_ConfigSet_[path] Specify the file name of the write destination configuration file. If the write destination file contains multiple-byte characters, the encoding must be Unicode (UTF-8).
+CMD_ConfigSet_PROMPT_PATH Config file path name to upload to server:
+CMD_ConfigSet_FILE_LOAD_FAILED Reading from specified file failed.
+
+
+# RouterList command
+CMD_RouterList Get List of Virtual Layer 3 Switches
+CMD_RouterList_Help Use this to get the list of Virtual Layer 3 Switches defined on the VPN Server. You can get the following information on the Virtual Layer 3 Switches: Switch Name, Operating Status, Number of Interfaces, and Number of Routing Tables. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge.
+CMD_RouterList_Args RouterList
+
+
+# RouterAdd command
+CMD_RouterAdd Define New Virtual Layer 3 Switch
+CMD_RouterAdd_Help Use this to define a new Virtual Layer 3 Switch on the VPN Server. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \n\n[Explanation on Virtual Layer 3 Switch Function]\nYou can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. \n\n[Caution about the Virtual Layer 3 Switch Function]\nThe Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. \nIf the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network.
+CMD_RouterAdd_Args RouterAdd [name]
+CMD_RouterAdd_[name] Use this to specify the name of the newly created Virtual Layer 3 Switch name. You cannot add a name that is identical to an existing Virtual Layer 3 Switch.
+CMD_RouterAdd_PROMPT_NAME Name of Virtual Layer 3 Switch to Create:
+
+
+# RouterDelete command
+CMD_RouterDelete Delete Virtual Layer 3 Switch
+CMD_RouterDelete_Help Use this to delete an existing Virtual Layer 3 Switch that is defined on the VPN Server. When the specified Virtual Layer 3 Switch is operating, it will be automatically deleted after operation stops. \nTo get a list of existing Virtual Layer 3 Switches, use the RouterList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge.
+CMD_RouterDelete_Args RouterDelete [name]
+CMD_RouterDelete_[name] Use this to specify the name of the Virtual Layer 3 Switch to be deleted.
+CMD_RouterDelete_PROMPT_NAME Name of Virtual Layer 3 Switch to Delete:
+
+
+# RouterStart command
+CMD_RouterStart Start Virtual Layer 3 Switch Operation
+CMD_RouterStart_Help Use this to start the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently stopped. \nTo get a list of existing Virtual Layer 3 Switches, use the RouterList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \n\n[Explanation on Virtual Layer 3 Switch Function]\nYou can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. \n\n[Caution about the Virtual Layer 3 Switch Function]\nThe Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. \nIf the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network.
+CMD_RouterStart_Args RouterStart [name]
+CMD_RouterStart_[name] Use this to specify the name of the Virtual Layer 3 Switch to start.
+CMD_RouterStart_PROMPT_NAME Name of Virtual Layer 3 Switch to Start:
+
+
+# RouterStop command
+CMD_RouterStop Stop Virtual Layer 3 Switch Operation
+CMD_RouterStop_Help Use this to stop the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently operating. \nTo get a list of existing Virtual Layer 3 Switches, use the RouterList command. \nTo execute this command, you must have VPN Server administrator privileges.
+CMD_RouterStop_Args RouterStop [name]
+CMD_RouterStop_[name] Use this to specify the name of the Virtual Layer 3 Switch to stop.
+CMD_RouterStop_PROMPT_NAME Name of Virtual Layer 3 Switch to Stop:
+
+
+# RouterIfList command
+CMD_RouterIfList Get List of Interfaces Registered on the Virtual Layer 3 Switch
+CMD_RouterIfList_Help Use this to get a list of virtual interfaces when virtual interfaces have been defined on a specified Virtual Layer 3 Switch. \nYou can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. \nA virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge.
+CMD_RouterIfList_Args RouterIfList [name]
+CMD_RouterIfList_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterIfList_PROMPT_NAME Name of Virtual Layer 3 Switch:
+
+
+# RouterIfAdd command
+CMD_RouterIfAdd Add Virtual Interface to Virtual Layer 3 Switch
+CMD_RouterIfAdd_Help Use this to add to a specified Virtual Layer 3 Switch, a virtual interface that connects to a Virtual Hub operating on the same VPN Server. \nYou can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. \nA virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. \nYou must define the IP network space that the virtual interface belongs to and the IP address of the interface itself. \nAlso, you must specify the name of the Virtual Hub that the interface will connect to. \nYou can specify a Virtual Hub that currently doesn't exist for the Virtual Hub name. \nThe virtual interface must have one IP address in the Virtual Hub. You also must specify the subnet mask of an IP network that the IP address belongs to. \nRouting via the Virtual Layer 3 Switches of IP spaces of multiple virtual Hubs operates based on the IP address specified here. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \nTo execute this command, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the RouterStop command to stop it and then execute this command.
+CMD_RouterIfAdd_Args RouterIfAdd [name] [/HUB:hub] [/IP:ip/mask]
+CMD_RouterIfAdd_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterIfAdd_HUB Use this to specify the name of the Virtual Hub to be the connection destination of the virtual interface to be newly added. To get a list of Virtual Hubs, you can use the HubList command. It is not essential that you specify a Virtual Hub that is currently operating. If you specify a Virtual Hub name that is not currently operating or that does not exist, the Virtual Layer 3 Switch will become enabled when the actual operation of that Virtual Hub begins.
+CMD_RouterIfAdd_IP Using the format: "IP address/subnet mask", specify the IP address and subnet mask held by the virtual interface to be newly added. Specify the IP address by separating the decimal values using dots such as 192.168.0.1 For the subnet mask, either specify decimal values separated by dots such as 255.255.255.0, or you can specify the bit length from the header using a decimal value such as 24.
+CMD_RouterIfAdd_PROMPT_NAME Name of Virtual Layer 3 Switch:
+CMD_RouterIfAdd_PROMPT_HUB Destination Virtual Hub Name of Virtual Interface:
+CMD_RouterIfAdd_PROMPT_IP IP Address/Subnet Mask:
+
+
+# RouterIfDel command
+CMD_RouterIfDel Delete Virtual Interface of Virtual Layer 3 Switch
+CMD_RouterIfDel_Help Use this to delete a virtual interface already defined in the specified Virtual Layer 3 Switch. \nYou can get a list of the virtual interfaces currently defined, by using the RouterIfList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \nTo execute this command, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the RouterStop command to stop it and then execute this command.
+CMD_RouterIfDel_Args RouterIfDel [name] [/HUB:hub]
+CMD_RouterIfDel_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterIfDel_HUB Use this to specify the name of the Virtual Hub to be the connection destination of the virtual interface to be deleted.
+
+
+# RouterTableList command
+CMD_RouterTableList Get List of Routing Tables of Virtual Layer 3 Switch
+CMD_RouterTableList_Help Use this to get a list of routing tables when routing tables have been defined on a specified Virtual Layer 3 Switch. \nIf the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference this routing table and execute routing. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge.
+CMD_RouterTableList_Args RouterTableList [name]
+CMD_RouterTableList_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterTableList_PROMPT_NAME Name of Virtual Layer 3 Switch:
+
+
+# RouterTableAdd command
+CMD_RouterTableAdd Add Routing Table Entry for Virtual Layer 3 Switch
+CMD_RouterTableAdd_Help Here you can add a new routing table entry to the routing table of the specified Virtual Layer 3 Switch. \nIf the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference the routing table and execute routing. \nYou must specify the contents of the routing table entry to be added to the Virtual Layer 3 Switch. You must specify any IP address that belongs to the same IP network in the virtual interface of this Virtual Layer 3 Switch as the gateway address. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \nTo execute this command, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the RouterStop command to stop it and then execute this command.
+CMD_RouterTableAdd_Args RouterTableAdd [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableAdd_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterTableAdd_NETWORK Using the format: "IP address/subnet mask", specify the network address and subnet mask of the routing table entry to be newly added. Specify the network address by separating the decimal values using dots such as "192.168.0.1". For the subnet mask, either specify decimal values separated by dots such as 255.255.255.0, or you can specify the bit length from the header using a decimal value such as 24. If you specify 0.0.0.0/0.0.0.0, the default route will be used.
+CMD_RouterTableAdd_GATEWAY Specify the gateway IP address.
+CMD_RouterTableAdd_METRIC Specify a metric value. Specify an integer (1 or higher).
+CMD_RouterTableAdd_PROMPT_NAME Name of Virtual Layer 3 Switch:
+CMD_RouterTableAdd_PROMPT_NETWORK Network Address/Subnet Mask:
+CMD_RouterTableAdd_PROMPT_GATEWAY Gateway Address:
+CMD_RouterTableAdd_PROMPT_METRIC Metric Value:
+
+
+# RouterTableDel command
+CMD_RouterTableDel Delete Routing Table Entry of Virtual Layer 3 Switch
+CMD_RouterTableDel_Help Use this to delete a routing table entry that is defined in the specified Virtual Layer 3 Switch. \nYou can get a list of the already defined routing table entries by using the RouterTableList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Bridge. \nTo execute this command, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the RouterStop command to stop it and then execute this command.
+CMD_RouterTableDel_Args RouterTableDel [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableDel_[name] Use this to specify the name of the Virtual Layer 3 Switch.
+CMD_RouterTableDel_NETWORK Using the format: "IP address/subnet mask", specify the network address of the routing table entry to be deleted.
+CMD_RouterTableDel_GATEWAY Specify the gateway IP address.
+CMD_RouterTableDel_METRIC Specify a metric value. Specify an integer (1 or higher).
+
+
+# LogFileList command
+CMD_LogFileList Get List of Log Files
+CMD_LogFileList_Help Use this to display a list of log files outputted by the VPN Server that have been saved on the VPN Server computer. By specifying a log file file name displayed here and calling it using the LogFileGet command you can download the contents of the log file. \nIf you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. \nWhen connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management.
+CMD_LogFileList_Args LogFileList
+CMD_LogFileList_START Getting list of log files. This may take a while. Please wait...
+CMD_LogFileList_NUM_LOGS In total there are %u log files.
+
+
+# LogFileGet command
+CMD_LogFileGet Download Log file
+CMD_LogFileGet_Help Use this to download the log file that is saved on the VPN Server computer. To download the log file first display the list of log files using the LogFileList command and then download the log file using the LogFileGet command. If you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. When connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management. \nIf you have specified the file name as a parameter, the downloaded log file will be saved to the file of that file name. If the destination file is not specified, the log file will be displayed onscreen. \nThe size of the log file can get very big, so pay careful attention to this issue.
+CMD_LogFileGet_Args LogFileGet [name] [/SERVER:server] [/SAVEPATH:savepath]
+CMD_LogFileGet_[name] Specify the name of the log file to be downloaded. To get a list of downloadable log files, use the LogFileList command.
+CMD_LogFileGet_SERVER Use this to specify the server name when making a download request to a cluster controller. Specify the server that will be displayed by the LogFileGet command.
+CMD_LogFileGet_SAVEPATH Use this to specify the destination file name for when saving the downloaded log file. When this is left unspecified, the file will be displayed onscreen.
+CMD_LogFileGet_PROMPT_NAME Name of log file to download:
+CMD_LogFileGet_START Downloading log file. This may take a while. Please wait...
+CMD_LogFileGet_FAILED The download failed.
+CMD_LogFileGet_SAVE_FAILED Unable to write to the specified file.
+CMD_LogFileGet_FILESIZE File size of log file: %u
+
+
+# HubCreate command
+CMD_HubCreate Create New Virtual Hub
+CMD_HubCreate_Help Use this to create a new Virtual Hub on the VPN Server. \nThe created Virtual Hub will begin operation immediately. \nWhen the VPN Server is operating on a cluster, this command is only valid for the cluster controller. Also, the new Virtual Hub will operate as a dynamic Virtual Hub. You can change it to a static Virtual Hub by using the HubSetStatic command. To get a list of Virtual Hubs that are already on the VPN Server, use the HubList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge or cluster member. \nWhen issuing the command to a cluster controller on a cluster to create a Virtual Hub, use either the HubCreateStatic command or the HubCreateDynamic command (issuing the HubCreate command to a cluster controller has the same operational effect as issuing the HubCreateDynamic command).
+CMD_HubCreate_Args HubCreate [name] [/PASSWORD:password]
+CMD_HubCreate_[name] Specify the name of the Virtual Hub to create.
+CMD_HubCreate_PASSWORD Specify an administrator password when the administrator password is going to be set for the Virtual Hub to be created. If this is not specified, a prompt will appear to input the password.
+CMD_HubCreate_PROMPT_NAME Name of Virtual Hub to be created:
+
+
+# HubCreateDynamic command
+CMD_HubCreateDynamic Create New Dynamic Virtual Hub (For Clustering)
+CMD_HubCreateDynamic_Help Use this to create a new dynamic Virtual Hub on the VPN Server. \nThe created Virtual Hub will begin operation immediately. \nWhen the VPN Server is operating on a cluster, this command is only valid for the cluster controller. Also, the new Virtual Hub will operate as a dynamic Virtual Hub. You can change it to a static Virtual Hub by using the HubSetStatic command. To get a list of Virtual Hubs that are already on the VPN Server, use the HubList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge, cluster member or standalone server.
+CMD_HubCreateDynamic_Args HubCreateDynamic [name] [/PASSWORD:password]
+CMD_HubCreateDynamic_[name] Specify the name of the Virtual Hub to create.
+CMD_HubCreateDynamic_PASSWORD Specify an administrator password when the administrator password is going to be set for the Virtual Hub to be created. If this is not specified, a prompt will appear to input the password.
+
+
+# HubCreateStatic command
+CMD_HubCreateStatic Create New Static Virtual Hub (For Clustering)
+CMD_HubCreateStatic_Help Use this to create a new static Virtual Hub on the VPN Server. \nThe created Virtual Hub will begin operation immediately. \nWhen the VPN Server is operating on a cluster, this command is only valid for the cluster controller. Also, the new Virtual Hub will operate as a dynamic Virtual Hub. You can change it to a static Virtual Hub by using the HubSetStatic command. To get a list of Virtual Hubs that are already on the VPN Server, use the HubList command. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge, cluster member or standalone server.
+CMD_HubCreateStatic_Args HubCreateStatic [name] [/PASSWORD:password]
+CMD_HubCreateStatic_[name] Specify the name of the Virtual Hub to create.
+CMD_HubCreateStatic_PASSWORD Specify an administrator password when the administrator password is going to be set for the Virtual Hub to be created. If this is not specified, a prompt will appear to input the password.
+
+
+# HubDelete command
+CMD_HubDelete Delete Virtual Hub
+CMD_HubDelete_Help Use this to delete an existing Virtual Hub on the VPN Server. \nIf you delete the Virtual Hub, all sessions that are currently connected to the Virtual Hub will be disconnected and new sessions will be unable to connect to the Virtual Hub. \nAlso, this will also delete all the Hub settings, user objects, group objects, certificates and Cascade Connections. \nOnce you delete the Virtual Hub, it cannot be recovered. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge or cluster member.
+CMD_HubDelete_Args HubDelete [name]
+CMD_HubDelete_[name] Specify the name of the Virtual Hub to delete.
+CMD_HubDelete_PROMPT_NAME Name of Virtual Hub to delete:
+
+
+# HubSetStatic command
+CMD_HubSetStatic Change Virtual Hub Type to Static Virtual Hub
+CMD_HubSetStatic_Help Use this when a VPN Server is operating on a cluster and you want to change the type of the Virtual Hub to a static Virtual Hub. When the type of the Virtual Hub is changed, all sessions that are currently connected to the Virtual Hub will be disconnected. \nWhen there is a Virtual Hub operating as a static virtual Hub, a Virtual Hub with that name will be created on all the cluster member servers. A user who attempts to connect this Virtual Hub will be connected to one of the cluster members hosting this Virtual Hub as determined by an algorithm based on each server's load status. \nA static Virtual Hub, for example, could be used for a remote access VPN that allows thousands or tens of thousands of users to connect at the same time for the purpose of remotely accessing an internal company LAN from the Internet for business. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge, cluster member or standalone server. \nThis command cannot be used for VPN Servers that are newer than Build 5190.
+CMD_HubSetStatic_Args HubSetStatic [name]
+CMD_HubSetStatic_[name] Specify the name of the Virtual Hub to be set as the static Virtual Hub.
+CMD_HubChange_PROMPT_NAME Name of Virtual Hub to change setting:
+
+
+# HubSetDynamic command
+CMD_HubSetDynamic Change Virtual Hub Type to Dynamic Virtual Hub
+CMD_HubSetDynamic_Help Use this when a VPN Server is operating on a cluster and you want to change the type of the Virtual Hub to a dynamic Virtual Hub. When the type of the Virtual Hub is changed, all sessions that are currently connected to the Virtual Hub will be disconnected. \nWhen there is not even one client connected to a dynamic Virtual Hub defined on the cluster, then that Virtual Hub does not exist on any cluster member. When the first client to attempt to connect to the dynamic Virtual Hub does so, the server with the lowest load on the cluster starts hosting that Virtual Hub. When the second and subsequent clients attempt to connect to the same virtual Hub, they are automatically connected to the server hosting the Virtual Hub. When all the clients are disconnected from a particular dynamic Virtual Hub, the Virtual Hub will return to the original state of not existing on any of the servers. \nThere is a broad range of applications for dynamic Virtual Hubs, such as a Virtual Hub defined for each business section within a company so that employees can connect to the Virtual Hub of their own department to do their work in a centralized management environment that is deployed on a single cluster. \nTo execute this command, you must have VPN Server administrator privileges. \nAlso, this command does not operate on VPN Servers that are operating as a VPN Bridge, cluster member or standalone server. \nThis command cannot be used for VPN Servers that are newer than Build 5190.
+CMD_HubSetDynamic_Args HubSetDynamic [name]
+CMD_HubSetDynamic_[name] Specify the name of the Virtual Hub to be set as the dynamic Virtual Hub.
+
+
+# HubList command
+CMD_HubList Get List of Virtual Hubs
+CMD_HubList_Help Use this to get a list of existing Virtual Hubs on the VPN Server. For each Virtual Hub, you can get the following information: Virtual Hub Name, Status, Type, Number of Users, Number of Groups, Number of Sessions, Number of MAC Tables, Number of IP Tables, Number of Logins, Last Login, and Last Communication.\nNote that when connecting in Virtual Hub Admin Mode, if in the options of a Virtual Hub that you do not have administrator privileges for, the option Don't Enumerate this Virtual Hub for Anonymous Users is enabled then that Virtual Hub will not be enumerated. If you are connected in Server Admin Mode, then the list of all Virtual Hubs will be displayed. \nWhen connecting to and managing a non-cluster-controller cluster member of a clustering environment, only the Virtual Hub currently being hosted by that VPN Server will be displayed. When connecting to a cluster controller for administration purposes, all the Virtual Hubs will be displayed.
+CMD_HubList_Args HubList
+
+
+# Hub command
+CMD_Hub Select Virtual Hub to Manage
+CMD_Hub_Help Use this to select the Virtual Hub to be the target of administration. For an administration utility with the status of being connected to a VPN Server, before executing a command to set or manage a Virtual Hub, you must use the Hub command to select the Virtual Hub to manage. \nWhen in the status of being connected to a VPN Server in Virtual Hub Admin Mode, you can select a single Virtual Hub to be the target of administration but you cannot select other Virtual Hubs. When having the status of being connected to the VPN Server in Server Admin Mode, you can make all Virtual Hubs the target of administration. \nTo get a list of Virtual Hubs that currently exist on the VPN Server, use the HubList command. \nFor the VPN Bridge, you can only select the Virtual Hub that has the name "BRIDGE".
+CMD_Hub_Args Hub [name]
+CMD_Hub_[name] Specify the name of the Virtual Hub to manage. If this parameter is left unspecified, the Select Virtual Hub to Manage will be cancelled.
+CMD_Hub_Unselected The Virtual Hub selection was unselected.
+CMD_Hub_Selected The Virtual Hub "%S" was selected.
+CMD_Hub_Select_Failed When attempting to select Virtual Hub "%S" that was specified by /ADMINHUB, the following error occurred.
+CMD_Hub_Not_Selected Before executing this command, first select the Virtual Hub to manage using the Hub command.
+
+
+# Online command
+CMD_Online Switch Virtual Hub to Online
+CMD_Online_Help Use this when the Virtual Hub currently being managed is offline to switch it to online. A Virtual Hub with an offline status cannot receive VPN connections from clients. By switching the Virtual Hub to online, that Virtual Hub becomes able to receive connections from users and provide services. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_Online_Args Online
+
+
+# Offline command
+CMD_Offline Switch Virtual Hub to Offline
+CMD_Offline_Help Use this when the Virtual Hub currently being managed is online to switch it to offline. If there are sessions currently connected to the Virtual Hub, all sessions will be disconnected. A Virtual Hub with an offline status cannot receive VPN connections from clients. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_Offline_Args Offline
+
+
+# SetMaxSession command
+CMD_SetMaxSession Set the Max Number of Concurrently Connected Sessions for Virtual Hub
+CMD_SetMaxSession_Help Use this to set the maximum number of sessions that can be concurrently connected to the Virtual Hub that is currently being managed. When there are more sessions than the maximum number of concurrently connected sessions that are being connected from the VPN Client or VPN Bridge, when the maximum number of sessions is reached, clients will no longer be able to connect. This limit on the maximum number of concurrently connected sessions does not include sessions generated in the Virtual Hub by Local Bridges, Virtual NAT, and Cascade Connections. \nYou can get the current setting for the max number of concurrently connected sessions by using the OptionsGet command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SetMaxSession_Args SetMaxSession [max_session]
+CMD_SetMaxSession_[max_session] Using an integer, specify the maximum number of concurrently connected sessions to set. Specifying 0 results in a setting of unlimited.
+CMD_SetMaxSession_Prompt Max Number of Sessions:
+
+
+# SetHubPassword command
+CMD_SetHubPassword Set Virtual Hub Administrator Password
+CMD_SetHubPassword_Help Use this to set the Administrator Password for the Virtual Hub that is currently being managed. When a Virtual Hub administrator password has been set, you are able to connect to that Virtual Hub from a VPN Server connection utility in Virtual Hub Admin Mode, by specifying the password. It is also possible to make a VPN connection from a VPN client or VPN Bridge by specifying "Administrator" for the user name and the password for the Virtual Hub administrator password. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SetHubPassword_Args SetHubPassword [password]
+CMD_SetHubPassword_[password] Specify the password you wish to set. If a password is not specified by parameter, a prompt will appear to input the password.
+
+
+# SetEnumAllow command
+CMD_SetEnumAllow Allow Enumeration by Virtual Hub Anonymous Users
+CMD_SetEnumAllow_Help Use this to change the options setting of the Virtual Hub you are currently managing to allow anonymous users to enumerate this Virtual Hub. By setting this option, it makes it possible for VPN Client users to enumerate this Virtual Hub simply by inputting this VPN Server address. Also, by using the SetEnumDeny command, you can deny anonymous users the ability to enumerate. At the time a Virtual Hub is created, enumeration will be allowed. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SetEnumAllow_Args SetEnumAllow
+
+
+# SetEnumDeny command
+CMD_SetEnumDeny Deny Enumeration by Virtual Hub Anonymous Users
+CMD_SetEnumDeny_Help Use this to change the options setting of the Virtual Hub you are currently managing to prevent anonymous users from enumerating this Virtual Hub. By setting this option, the VPN Client user will be unable to enumerate this Virtual Hub even if they send a Virtual Hub enumeration request to the VPN Server. Also, by using the SetEnumAllow command, you can allow anonymous users to enumerate. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SetEnumDeny_Args SetEnumDeny
+
+
+# OptionsGet command
+CMD_OptionsGet Get Options Setting of Virtual Hubs
+CMD_OptionsGet_Help Use this to get a list of the Options setting of the Virtual Hub currently being managed. You can get the following: Allow/Deny Virtual Hub Enumeration, Maximum Concurrent Connections, Online/Offline Status, and Virtual Hub Type in Clustering Environment. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_OptionsGet_Args OptionsGet
+CMD_OptionsGet_TITLE Options Setting List of Virtual Hub "%S"
+CMD_OptionsGet_ENUM Enumeration of Virtual Hub for Anonymous User
+CMD_OptionsGet_MAXSESSIONS Max Number of Sessions
+CMD_OptionsGet_STATUS Status
+CMD_OptionsGet_TYPE Virtual Hub Type
+
+
+
+# RadiusServerSet command
+CMD_RadiusServerSet Set RADIUS Server to use for User Authentication
+CMD_RadiusServerSet_Help To accept users to the currently managed Virtual Hub in RADIUS server authentication mode, you can specify an external RADIUS server that confirms the user name and password. (You can specify multiple hostname by splitting with comma or semicolon.) \nThe RADIUS server must be set to receive requests from IP addresses of this VPN Server. Also, authentication by Password Authentication Protocol (PAP) must be enabled. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_RadiusServerSet_Args RadiusServerSet [server_name:port] [/SECRET:secret] [/RETRY_INTERVAL:interval]
+CMD_RadiusServerSet_[server_name:port] Using the format "host name:port number", specify the host name or IP address, and the UDP port number of the RADIUS server being used. If the port number is omitted, 1812 will be used. You can specify multiple hostname by splitting with comma or semicolon.
+CMD_RadiusServerSet_SECRET Specify the shared secret (password) used for communication with the RADIUS Server
+CMD_RadiusServerSet_RETRY_INTERVAL Specify the retry interval between retries in milliseconds.
+CMD_RadiusServerSet_Prompt_Host Host Number and Port Number of RADIUS Server to Use:
+CMD_RadiusServerSet_Prompt_Secret Shared Secret:
+CMD_RadiusServerSet_Prompt_RetryInterval Retry Interval (milliseconds):
+CMD_RadiusServerSet_EVAL_NUMINTERVAL The retry interval must be in from 500 to 10000 milliseconds.
+
+
+# RadiusServerDelete command
+CMD_RadiusServerDelete Delete Setting to Use RADIUS Server for User Authentication
+CMD_RadiusServerDelete_Help Use this to delete the setting related to using a RADIUS server when a user connects to the currently managed Virtual Hub in RADIUS Server Authentication Mode and disable the RADIUS authentication. To get the settings related to the current RADIUS server use the RadiusServerGet command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_RadiusServerDelete_Args RadiusServerDelete
+
+
+# RadiusServerGet command
+CMD_RadiusServerGet Get Setting of RADIUS Server Used for User Authentication
+CMD_RadiusServerGet_Help Use this to get the current settings for the RADIUS server used when a user connects to the currently managed Virtual Hub using RADIUS Server Authentication Mode. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_RadiusServerGet_Args RadiusServerGet
+CMD_RadiusServerGet_STATUS Use RADIUS Server
+CMD_RadiusServerGet_HOST RADIUS Server Host Name or IP Address:
+CMD_RadiusServerGet_PORT RADIUS Server Port Number
+CMD_RadiusServerGet_SECRET Shared Secret
+CMD_RadiusServerGet_RetryInterval Retry Interval (in milliseconds)
+
+
+# StatusGet command
+CMD_StatusGet Get Current Status of Virtual Hub
+CMD_StatusGet_Help Use this to get the current status of the Virtual Hub currently being managed. You can get the following information: Virtual Hub Type, Number of Sessions, Number of Each Type of Object, Number of Logins, Last Login, Last Communication, and Communication Statistical Data.
+CMD_StatusGet_Args StatusGet
+
+
+# LogGet command
+CMD_LogGet Get Log Save Setting of Virtual Hub
+CMD_LogGet_Help Use this to get the log save setting for the Virtual Hub that is currently being managed. You can get the setting information such as the save setting related to security logs and packet logs and information on what is saved.
+CMD_LogGet_Args LogGet
+CMD_Log_SecurityLog Save Security Log
+CMD_Log_PacketLog Save Packet Log
+CMD_Log_SwitchType Log File Switch Cycle
+CMD_Log_0 TCP Connection Log
+CMD_Log_1 TCP Packet Log
+CMD_Log_2 DHCP Log
+CMD_Log_3 UDP Log
+CMD_Log_4 ICMP Log
+CMD_Log_5 IP Log
+CMD_Log_6 ARP Log
+CMD_Log_7 Ethernet Log
+
+
+# LogEnable command
+CMD_LogEnable Enable Security Log or Packet Log
+CMD_LogEnable_Help Use this to enable a security log or packet log of the Virtual Hub currently being managed. \nTo get the current setting, you can use the LogGet command.
+CMD_LogEnable_Args LogEnable [security|packet]
+CMD_LogEnable_[security|packet] Select the type of log to enable. Specify either "security" or "packet".
+CMD_LogEnable_Prompt Select Security or Packet:
+CMD_LogEnable_Prompt_Error Invalid specification.
+
+
+# LogDisable command
+CMD_LogDisable Disable Security Log or Packet Log
+CMD_LogDisable_Help Use this to disable a security log or packet log of the Virtual Hub currently being managed. \nTo get the current setting, you can use the LogGet command.
+CMD_LogDisable_Args LogDisable [security|packet]
+CMD_LogDisable_[security|packet] Select the type of log to disable. Specify either "security" or "packet".
+
+
+# LogSwitchSet command
+CMD_LogSwitchSet Set Log File Switch Cycle
+CMD_LogSwitchSet_Help Use this to set the log file switch cycle for the security log or packet log that the currently managed Virtual Hub saves. The log file switch cycle can be changed to switch in every second, every minute, every hour, every day, every month ,or not switch. \nTo get the current setting, you can use the LogGet command.
+CMD_LogSwitchSet_Args LogSwitchSet [security|packet] [/SWITCH:sec|min|hour|day|month|none]
+CMD_LogSwitchSet_[security|packet] Select the type of log to change setting. Specify either "security" or "packet".
+CMD_LogSwitchSet_SWITCH Select the switch cycle to set. Specify sec, min, hour, day, month or none.
+CMD_LogSwitchSet_Prompt Specify sec, min, hour, day, month or none:
+
+
+# LogPacketSaveType command
+CMD_LogPacketSaveType Set Save Contents and Type of Packet to Save to Packet Log
+CMD_LogPacketSaveType_Help Use this to set the save contents of the packet log for each type of packet to be saved by the currently managed Virtual Hub. There are the following packet types: TCP Connection Log, TCP Packet Log, DHCP Packet Log, UDP Packet Log, ICMP Packet Log, IP Packet Log, ARP Packet Log, and Ethernet Packet Log.\nTo get the current setting, you can use the LogGet command.
+CMD_LogPacketSaveType_Args LogPacketSaveType [/TYPE:tcpconn|tcpdata|dhcp|udp|icmp|ip|arp|ether] [/SAVE:none|header|full]
+CMD_LogPacketSaveType_TYPE Specify tcpconn, tcpdata, dhcp, udp, icmp, ip, arp, or ether to specify the type of packet whose save contents are going to be changed.
+CMD_LogPacketSaveType_SAVE Specify the save contents of the packet log. \nSpecify either none: save nothing\nheader: header information only\nfull: all packet contents
+CMD_LogPacketSaveType_Prompt_TYPE Specify tcpconn, tcpdata, dhcp, udp, icmp, ip, arp, or ether:
+CMD_LogPacketSaveType_Prompt_SAVE Specify none, header, or full:
+
+
+# CAList command
+CMD_CAList Get List of Trusted CA Certificates
+CMD_CAList_Help Here you can manage the certificate authority certificates that are trusted by this currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_CAList_Args CAList
+CMD_CAList_COLUMN_ID ID
+
+
+# CAAdd command
+CMD_CAAdd Add Trusted CA Certificate
+CMD_CAAdd_Help Use this to add a new certificate to a list of CA certificates trusted by the currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. \nTo get a list of the current certificates you can use the CAList command. \nThe certificate you add must be saved in the X.509 file format. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_CAAdd_Args CAAdd [path]
+CMD_CAAdd_[path] Specify the file name of the X.509 certificate to register.
+CMD_CAAdd_PROMPT_PATH Name of X.509 Certificate File to Register:
+
+
+# CADelete command
+CMD_CADelete Delete Trusted CA Certificate
+CMD_CADelete_Help Use this to delete an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub. \nTo get a list of the current certificates you can use the CAList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_CADelete_Args CADelete [id]
+CMD_CADelete_[id] Specify the ID of the certificate to delete.
+CMD_CADelete_PROMPT_ID ID of Certificate to Delete:
+
+
+# CAGet command
+CMD_CAGet Get Trusted CA Certificate
+CMD_CAGet_Help Use this to get an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub and save it as a file in X.509 format. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_CAGet_Args CAGet [id] [/SAVECERT:path]
+CMD_CAGet_[id] Specify the ID of the certificate to get.
+CMD_CAGet_SAVECERT Specify the file name to save the certificate you obtained.
+CMD_CAGet_PROMPT_ID ID of Certificate to Get:
+CMD_CAGet_PROMPT_SAVECERT Name of File to Save:
+
+
+# CascadeList command
+CMD_CascadeList Get List of Cascade Connections
+CMD_CascadeList_Help Use this to get a list of Cascade Connections that are registered on the currently managed Virtual Hub. \nBy using a Cascade Connection, you can connect this Virtual Hub by Layer 2 Cascade Connection to another Virtual Hub that is operating on the same or a different computer. \n\n[Warning About Cascade Connections]\nBy connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeList_Args CascadeList
+
+
+# CascadeCreate command
+CMD_CascadeCreate Create New Cascade Connection
+CMD_CascadeCreate_Help Use this to create a new Cascade Connection on the currently managed Virtual Hub. \nBy using a Cascade Connection, you can connect this Virtual Hub by Cascade Connection to another Virtual Hub that is operating on the same or a different computer. \nTo create a Cascade Connection, you must specify the name of the Cascade Connection, destination server and destination Virtual Hub and user name. When a new Cascade Connection is created, the type of user authentication is initially set as Anonymous Authentication and the proxy server setting and the verification options of the server certificate is not set. To change these settings and other advanced settings after a Cascade Connection has been created, use the other commands that begin with the name "Cascade". \n\n[Warning About Cascade Connections]\nBy connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. \n\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeCreate_Args CascadeCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username]
+CMD_CascadeCreate_[name] Specify the name of the Cascade Connection to create.
+CMD_CascadeCreate_SERVER Specify the host name and port number of the destination VPN Server using the format [host name:port number]. You can also specify by IP address.
+CMD_CascadeCreate_HUB Specify the Virtual Hub on the destination VPN Server.
+CMD_CascadeCreate_USERNAME Specify the user name to use for user authentication when connecting to the destination VPN Server.
+CMD_CascadeCreate_Prompt_Name Cascade Connection Name:
+CMD_CascadeCreate_Prompt_Server Destination VPN Server Host Name and Port Number:
+CMD_CascadeCreate_Prompt_Hub Destination Virtual Hub Name:
+CMD_CascadeCreate_Prompt_Username Connecting User Name:
+
+
+# CascadeSet command
+CMD_CascadeSet Set the Destination for Cascade Connection
+CMD_CascadeSet_Help Use this to set the destination VPN Server host name and port number, Virtual Hub name and the user name that will use the connection for the Cascade Connection registered on the currently managed virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeSet_Args CascadeSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_CascadeSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeSet_SERVER Specify the host name and port number of the destination VPN Server using the format [host name:port number]. You can also specify by IP address.
+CMD_CascadeSet_HUB Specify the Virtual Hub on the destination VPN Server.
+
+
+# CascadeGet command
+CMD_CascadeGet Get the Cascade Connection Setting
+CMD_CascadeGet_Help Use this to get the Connection Setting of a Cascade Connection that is registered on the currently managed Virtual Hub. \nTo change the Connection Setting contents of the Cascade Connection, use the other commands that begin with the name "Cascade" after creating the Cascade Connection. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeGet_Args CascadeGet [name]
+CMD_CascadeGet_[name] Specify the name of the Cascade Connection whose setting you want to get.
+CMD_CascadeGet_Policy [Cascade Session Security Policy Setting Value]
+
+# CascadeDelete command
+CMD_CascadeDelete Delete Cascade Connection Setting
+CMD_CascadeDelete_Help Use this to delete a Cascade Connection that is registered on the currently managed Virtual Hub. If the specified Cascade Connection has a status of online, the connections will be automatically disconnected and then the Cascade Connection will be deleted. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeDelete_Args CascadeDelete [name]
+CMD_CascadeDelete_[name] Specify the name of the Cascade Connection to delete.
+
+
+# CascadeUsernameSet command
+CMD_CascadeUsernameSet Set User Name to Use Connection of Cascade Connection
+CMD_CascadeUsernameSet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to the VPN Server, use this to specify the user name required for user authentication. \nIn some cases it is necessary to specify the type of user authentication and specify the required parameters. To change this information you can use commands such as CascadeAnonymousSet, CascadePasswordSet, and CascadeCertSet. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeUsernameSet_Args CascadeUsernameSet [name] [/USERNAME:username]
+CMD_CascadeUsernameSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeUsernameSet_USERNAME Specify the user name required for user authentication when the Cascade Connection connects to the VPN Server.
+CMD_CascadeUsername_Notice The auth type for this Connection Setting is currently set as password authentication. After changing the user name, you must use the CascadePasswordSet command to reset the password.
+
+
+# CascadeAnonymousSet command
+CMD_CascadeAnonymousSet Set User Authentication Type of Cascade Connection to Anonymous Authentication
+CMD_CascadeAnonymousSet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to the VPN Server, set the user authe type to [anonymous authentication]. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeAnonymousSet_Args CascadeAnonymousSet [name]
+CMD_CascadeAnonymousSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadePasswordSet command
+CMD_CascadePasswordSet Set User Authentication Type of Cascade Connection to Password Authentication
+CMD_CascadePasswordSet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to the VPN Server, use this to set the user auth type to Password Authentication. Specify Standard Password Authentication and RADIUS or NT Domain Authentication as the password authentication type. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadePasswordSet_Args CascadePasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_CascadePasswordSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadePasswordSet_PASSWORD Specify the password to use for password authentication. If this is not specified, a prompt will appear to input the password.
+CMD_CascadePasswordSet_TYPE Specify either "standard" (Standard Password Authentication) or "radius" (RADIUS or NT Domain Authentication) as the password authentication type.
+CMD_CascadePasswordSet_Prompt_Type Specify standard or radius:
+CMD_CascadePasswordSet_Type_Invalid The standard or radius specification is invalid.
+
+
+# CascadeCertSet command
+CMD_CascadeCertSet Set User Authentication Type of Cascade Connection to Client Certificate Authentication
+CMD_CascadeCertSet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to the VPN Server, use this to set the user auth type to Client Certificate Authentication. For this certificate, you must specify a certificate file in the X.509 format and a private key file that is Base 64 encoded. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeCertSet_Args CascadeCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_CascadeCertSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeCertSet_LOADCERT Specify the X.509 format certificate file to provide for certificate authentication.
+CMD_CascadeCertSet_LOADKEY Specify the Base-64-encoded private key file name for the certificate.
+
+
+# CascadeCertGet command
+CMD_CascadeCertGet Get Client Certificate to Use for Cascade Connection
+CMD_CascadeCertGet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection uses client certificate authentication, use this to get the certificate that is provided as the client certificate and save the certificate file in X.509 format. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeCertGet_Args CascadeCertGet [name] [/SAVECERT:cert]
+CMD_CascadeCertGet_[name] Specify the name of the Cascade Connection whose setting you want to get.
+CMD_CascadeCertGet_SAVECERT Specify the file name to save the certificate you obtained in X.509 format.
+CMD_CascadeCertSet_Not_Auth_Cert The specified Cascade Connection is not in client certificate authentication mode.
+CMD_CascadeCertSet_Cert_Not_Exists The certificate is not stored in the Connection Setting of the specified Cascade Connection.
+
+
+# CascadeEncryptEnable command
+CMD_CascadeEncryptEnable Enable Encryption when Communicating by Cascade Connection
+CMD_CascadeEncryptEnable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers to be encrypted by SSL. \nNormally communication between VPN Servers is encrypted by SSL to prevent eavesdropping of information and fraud. You can also disable encryption. When encryption is disabled, the communication throughput improves but the communication data flows over the network in plain text. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeEncryptEnable_Args CascadeEncryptEnable [name]
+CMD_CascadeEncryptEnable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeEncryptDisable command
+CMD_CascadeEncryptDisable Disable Encryption when Communicating by Cascade Connection
+CMD_CascadeEncryptDisable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers not to be encrypted. \nNormally communication between VPN Servers is encrypted by SSL to prevent eavesdropping of information and fraud. You can also disable encryption. When encryption is disabled, the communication throughput improves but the communication data flows over the network in plain text. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeEncryptDisable_Args CascadeEncryptDisable [name]
+CMD_CascadeEncryptDisable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeCompressEnable command
+CMD_CascadeCompressEnable Enable Data Compression when Communicating by Cascade Connection
+CMD_CascadeCompressEnable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers to be compressed. \nIt is possible to achieve a maximum of 80% compression. Compression however places higher loads on the CPU of both the client and server machines. When the line speed is about 10 Mbps or greater, compression can lower throughput, but sometimes it can have the opposite effect. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeCompressEnable_Args CascadeCompressEnable [name]
+CMD_CascadeCompressEnable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeCompressDisable command
+CMD_CascadeCompressDisable Disable Data Compression when Communicating by Cascade Connection
+CMD_CascadeCompressDisable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers to be not compressed. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeCompressDisable_Args CascadeCompressDisable [name]
+CMD_CascadeCompressDisable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeProxyNone command
+CMD_CascadeProxyNone Specify Direct TCP/IP Connection as the Connection Method of Cascade Connection
+CMD_CascadeProxyNone_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to set Direct TCP/IP Connection as the connection method to use, in which case the connection route will not be via a proxy server. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeProxyNone_Args CascadeProxyNone [name]
+CMD_CascadeProxyNone_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeProxyHttp command
+CMD_CascadeProxyHttp Set Connection Method of Cascade Connection to be via an HTTP Proxy Server
+CMD_CascadeProxyHttp_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to set Connect via HTTP Proxy Server as the method of connection to use, which requires the specification of the host name and port number of the HTTP Proxy server to communicate via as well as a user name and password (when required). \nThe HTTP server that communication will travel via must be compatible with the CONNECT method to use HTTPS communication. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeProxyHttp_Args CascadeProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxyHttp_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeProxyHttp_SERVER Specify the host name or IP address, and port number of the on-route HTTP proxy server using the format [host name:port number].
+CMD_CascadeProxyHttp_USERNAME When user authentication is required to connect to the on-route HTTP proxy server, specify the user name. Also, specify the /PASSWORD parameter at the same time. If the parameters /USERNAME and /PASSWORD are not specified, the user authentication data will not be set.
+CMD_CascadeProxyHttp_PASSWORD When user authentication is required to connect to the on-route HTTP proxy server, specify the password. Specify this together with the /USERNAME parameter.
+CMD_CascadeProxyHttp_Prompt_Server Proxy Server Host Name and Port Number:
+
+
+
+# CascadeProxySocks command
+CMD_CascadeProxySocks Set Connection Method of Cascade Connection to be via an SOCKS Proxy Server
+CMD_CascadeProxySocks_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to set Connect via SOCKS Proxy Server as the method of connection to use, which requires the specification of the host name and port number of the SOCKS Proxy server to communicate via as well as a user name and password (when required). \nThe on-route SOCKS server must be compatible with SOCKS Version 4. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeProxySocks_Args CascadeProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxySocks_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeProxySocks_SERVER Specify the host name or IP address, and port number of the on-route SOCKS proxy server using the format "host name:port number".
+CMD_CascadeProxySocks_USERNAME When user authentication is required to connect to the on-route SOCKS proxy server, specify the user name. Also, specify the /PASSWORD parameter at the same time. If the parameters /USERNAME and /PASSWORD are not specified, the user authentication data will not be set.
+CMD_CascadeProxySocks_PASSWORD When user authentication is required to connect to the on-route SOCKS proxy server, specify the password. Specify this together with the /USERNAME parameter.
+
+
+# CascadeServerCertEnable command
+CMD_CascadeServerCertEnable Enable Cascade Connection Server Certificate Verification Option
+CMD_CascadeServerCertEnable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to enable the option to check whether the SSL certificate provided by the destination VPN Server can be trusted. \nIf this option is enabled you must either use the CascadeServerCertSet command to save the connection destination server SSL certificate beforehand in the Cascade Connection Settings beforehand, or use the CAAdd command etc. to register a root certificate containing the signed server SSL certificate in the list of Virtual Hub trusted CA certificates. \nIf the certificate of the connected VPN Server cannot be trusted under the condition where the option to verify server certificates was enabled for the Cascade Connection, the connection will be promptly cancelled and continual reattempts at connection will be made. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeServerCertEnable_Args CascadeServerCertEnable [name]
+CMD_CascadeServerCertEnable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeServerCertDisable command
+CMD_CascadeServerCertDisable Disable Cascade Connection Server Certificate Verification Option
+CMD_CascadeServerCertDisable_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to disable the option to check whether the SSL certificate provided by the destination VPN Server can be trusted. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeServerCertDisable_Args CascadeServerCertDisable [name]
+CMD_CascadeServerCertDisable_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeServerCertSet command
+CMD_CascadeServerCertSet Set the Server Individual Certificate for Cascade Connection
+CMD_CascadeServerCertSet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to a VPN Server, use this to register beforehand the same certificate as the SSL certificate provided by the destination VPN Server. \nIf the option to verify server certificates for Cascade Connections is enabled, you must either use this command to save the connection destination server SSL certificate beforehand in the Cascade Connection Settings beforehand, or use the CAAdd command etc. to register a root certificate containing the signed server SSL certificate in the list of Virtual Hub trusted CA certificates. \nIf the certificate of the connected VPN Server cannot be trusted under the condition where the option to verify server certificates was enabled for the Cascade Connection, the connection will be promptly cancelled and continual reattempts at connection will be made. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeServerCertSet_Args CascadeServerCertSet [name] [/LOADCERT:cert]
+CMD_CascadeServerCertSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeServerCertSet_LOADCERT Specify X.509 format certificate file name that the server individual certificate you wish to set is saved under.
+
+
+# CascadeServerCertDelete command
+CMD_CascadeServerCertDelete Delete the Server Individual Certificate for Cascade Connection
+CMD_CascadeServerCertDelete_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and a server individual certificate is registered for that Cascade Connection, use this to delete that server individual certificate. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeServerCertDelete_Args CascadeServerCertDelete [name]
+CMD_CascadeServerCertDelete_[name] Specify the name of the Cascade Connection whose setting you want to change.
+
+
+# CascadeServerCertGet command
+CMD_CascadeServerCertGet Get the Server Individual Certificate for Cascade Connection
+CMD_CascadeServerCertGet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and a server individual certificate is registered for that Cascade Connection, use this to get that certificate and save it as an X.509 format certificate file. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeServerCertGet_Args CascadeServerCertGet [name] [/SAVECERT:path]
+CMD_CascadeServerCertGet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeServerCertGet_SAVECERT Specify the certificate file name to save the server individual certificate in X.509 format.
+
+
+# CascadeDetailSet command
+CMD_CascadeDetailSet Set Advanced Settings for Cascade Connection
+CMD_CascadeDetailSet_Help Use this to customize the VPN protocol communication settings used when a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection connects to the VPN Server. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeDetailSet_Args CascadeDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:interval] [/TTL:disconnect_span] [/HALF:yes|no] [/NOQOS:yes|no]
+CMD_CascadeDetailSet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadeDetailSet_MAXTCP Specify, using an integer in the range 1 to 32, the number of TCP connections to be used for VPN communication. By using data transmission by multiple TCP connections for VPN communication sessions with VPN Servers it is sometimes possible to increase communication speed. \nNote: We recommend about 8 lines when the connection lines to the server are fast, and 1 line when using a slow connection such as dialup.
+CMD_CascadeDetailSet_INTERVAL When communicating by VPN by establishing multiple TCP connections, specify in seconds, the establishing interval for each TCP connection. The standard value is 1 second.
+CMD_CascadeDetailSet_TTL When specifying connection life of each TCP connection specify in seconds the keep-alive time from establishing a TCP connection until disconnection. If 0 is specified, keep-alive will not be set.
+CMD_CascadeDetailSet_HALF Specify "yes" when enabling half duplex mode. When using two or more TCP connections for VPN communication, it is possible to use Half Duplex Mode. By enabling half duplex mode it is possible to automatically fix data transmission direction as half and half for each TCP connection. In the case where a VPN using 8 TCP connections is established, for example, when half-duplex is enabled, communication can be fixes so that 4 TCP connections are dedicated to the upload direction and the other 4 connections are dedicated to the download direction.
+CMD_CascadeDetailSet_NOQOS Specify "yes" when disabling VoIP / QoS functions. Normally "no" is specified.
+CMD_CascadeDetailSet_Eval_MaxTcp Specify an integer in the range 1 to 32 for the number of TCP connections.
+CMD_CascadeDetailSet_Eval_Interval Set at least 1 second for the interval to establish a TCP connection.
+CMD_CascadeDetailSet_Prompt_MaxTcp Number of TCP Connections to Use in VPN Communication:
+CMD_CascadeDetailSet_Prompt_Interval Interval between Establishing Each TCP Connection:
+CMD_CascadeDetailSet_Prompt_TTL Connection Life of Each TCP Connection (0 for no keep-alive):
+CMD_CascadeDetailSet_Prompt_HALF Enable half-duplex mode (yes/no):
+
+
+# CascadePolicySet command
+CMD_CascadePolicySet Set Cascade Connection Session Security Policy
+CMD_CascadePolicySet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is established, use this to change the security policy contents that are applied to the session generated by the Virtual Hub. \nWhen a Virtual Hub makes a Cascade Connection to another VPN Server, a Cascade Session will be newly generated on the Virtual Hub that is the Cascade Connection source. You can use this command to set the security policy contents that will set this Cascade session. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadePolicySet_Args [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_CascadePolicySet_[name] Specify the name of the Cascade Connection whose setting you want to change.
+CMD_CascadePolicySet_NAME Specify the name of policy whose values you want to change. You can use the PolicyList command to display a list of policy names and values that can be set.
+CMD_CascadePolicySet_VALUE Specify a new policy value. If the policy is an integer value, specify an integer. Specify yes or no for Boolean types. You can view the type and value that can be set by using the PolicyList command.
+CMD_CascadePolicySet_PROMPT_POLNAME Name of Policy Whose Value you want to Change:
+CMD_CascadePolicySet_PROMPT_POLVALUE Value to newly set:
+CMD_CascadePolicySet_Invalid_Name The specified policy name "%S" is invalid. \nCheck the list of policy names that can be set using the PolicyList command.
+CMD_CascadePolicySet_Invalid_Name_For_Cadcade The specified policy name "%S" cannot be used for a Cascade Connection security policy setting.
+CMD_CascadePolicySet_Invalid_Range Specify policy "%S" within the range of %s.
+
+
+# PolicyList command
+CMD_PolicyList Display List of Security Policy Types and Settable Values
+CMD_PolicyList_Help Use this to display a list of item names, descriptions, and settable values in the security policies that can be set for VPN Server users and groups and Cascade Connections. \nBy running the PolicyList command without specifying any parameters, a list of all supported security policy names and descriptions will be displayed. \nBy specifying the name using the PolicyList command parameter, a detailed description related to this value and the type and range of the settable value will be displayed.
+CMD_PolicyList_Args PolicyList [name]
+CMD_PolicyList_[name] This allows you to specify the policy name whose description you want to display. If you don't specify a name, a list of all supported security names and descriptions will be displayed.
+CMD_PolicyList_Invalid_Name The specified policy name is invalid.
+CMD_PolicyList_Column_1 Policy name
+CMD_PolicyList_Column_2 Simple description of policy
+CMD_PolicyList_Column_3 Setting value
+CMD_PolicyList_Help_1 [Policy Name]
+CMD_PolicyList_Help_2 [Simple Description of Policy]
+CMD_PolicyList_Help_3 [Range of Settable Values]
+CMD_PolicyList_Help_4 [Default Value]
+CMD_PolicyList_Help_5 [Detailed Description of Policy]
+CMD_PolicyList_Range_Bool yes or no
+CMD_PolicyList_Range_Int_1 Range from %s to %s (0 cannot be specified)
+CMD_PolicyList_Range_Int_2 Range from %s to %s (if 0 is specified, nothing is set)
+
+
+# CascadeStatusGet command
+CMD_CascadeStatusGet Get Current Cascade Connection Status
+CMD_CascadeStatusGet_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is currently online, use this to get its connection status and other information. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeStatusGet_Args CascadeStatusGet [name]
+CMD_CascadeStatusGet_[name] Specify the name of the Cascade Connection whose information you want to get.
+
+
+# CascadeRename command
+CMD_CascadeRename Change Name of Cascade Connection
+CMD_CascadeRename_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to change the name of that Cascade Connection. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeRename_Args CascadeRename [name] [/NEW:new_name]
+CMD_CascadeRename_[name] Specify the current name of the Cascade Connection whose name you want to change.
+CMD_CascadeRename_NEW Specify the new name after the change.
+CMD_CascadeRename_PROMPT_OLD Current Name:
+CMD_CascadeRename_PROMPT_NEW New Name:
+
+
+
+# CascadeOnline command
+CMD_CascadeOnline Switch Cascade Connection to Online Status
+CMD_CascadeOnline_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to online status. The Cascade Connection that is switched to online status begins the process of connecting to the destination VPN Server in accordance with the Connection Setting. The Cascade Connection that is switched to online status will establish normal connection to the VPN Server or continue to attempt connection until it is switched to offline status. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeOnline_Args CascadeOnline [name]
+CMD_CascadeOnline_[name] Specify the name of the Cascade Connection to switch to online status.
+
+
+# CascadeOffline command
+CMD_CascadeOffline Switch Cascade Connection to Offline Status
+CMD_CascadeOffline_Help When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to offline status. The Cascade Connection that is switched to offline will not connect to the VPN Server until next time it is switched to the online status using the CascadeOnline command \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CascadeOffline_Args CascadeOffline [name]
+CMD_CascadeOffline_[name] Specify the name of the Cascade Connection to switch to offline status.
+
+
+# AccessAdd command
+CMD_AccessAdd Add Access List Rules (IPv4)
+CMD_AccessAdd_Help Use this to add a new rule to the access list of the currently managed Virtual Hub. \nThe access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define an priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the AccessAddEx command to generate delays, jitters and packet losses. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessAdd_Args AccessAdd [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished]
+CMD_AccessAdd_[pass|discard] When a packet matches this rule condition, this operation is decided. When pass is specified, the packet is allowed to pass, and when discard is specified, the packet is discarded.
+CMD_AccessAdd_MEMO Specify a description (memo) for this rule.
+CMD_AccessAdd_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values.
+CMD_AccessAdd_SRCIP Specify a source IPv4 address as a rule condition. Specify the IPv4 address in the format of "IP Address/Mask" by separating the decimal values using dots such as "192.168.0.1". For the mask, either specify decimal values separated by dots such as "255.255.255.0", or you can specify the bit length from the header using a decimal value such as "24". If you specify "0.0.0.0/0.0.0.0", this means all hosts.
+CMD_AccessAdd_DESTIP Specify a destination IPv4 address as a rule condition in the format of "IP Address/Mask". Use the same method of specification as for the /SRCIP parameter.
+CMD_AccessAdd_PROTOCOL Specify a protocol type as a rule condition. Input the IP protocol number using decimal values or specify one of the keywords "tcp" (TCP/IP protocol, no.6), "udp" (UDP/IP protocol, no.17), "icmpv4" (ICMPv4 protocol, no.1), "icmpv6" (ICMPv6 protocol, no.58) or "ip" (all protocols, no.0). Specify 0 to make the rule apply to all IP protocols.
+CMD_AccessAdd_SRCPORT If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. When specifying, do so using the following method "1-1024" (1 to 1024), "23" (only 23).
+CMD_AccessAdd_DESTPORT If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. Use the same method of specification as for the /SRCPORT parameter.
+CMD_AccessAdd_SRCUSERNAME You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAdd_DESTUSERNAME You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAdd_SRCMAC Specify destination MAC address as a rule. Specify MAC address with "-" or ":" separators and hexadecimal number like "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00". The separators are skippable.
+CMD_AccessAdd_DESTMAC Specify destination MAC address as a rule. Use the same method of specification as for the /SRCMAC parameter.
+CMD_AccessAdd_TCPSTATE Specify TCP connection state as a rule. Use Established or Unestablished.
+CMD_AccessAdd_Prompt_TYPE Pass or Discard:
+CMD_AccessAdd_Prompt_MEMO Rule Description (Memo):
+CMD_AccessAdd_Prompt_PRIORITY Rule Priority:
+CMD_AccessAdd_Eval_PRIORITY Specify an integer of 1 or higher for the priority.
+CMD_AccessAdd_Prompt_SRCIP Source IP Address ("0.0.0.0/0" specifies all):
+CMD_AccessAdd_Prompt_DESTIP Destination IP Address ("0.0.0.0/0" specifies all):
+CMD_AccessAdd_Prompt_PROTOCOL Protocol No. or Protocol Name (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd_Prompt_SRCPORT Source Port Number Range (tcp/udp only):
+CMD_AccessAdd_Prompt_DESTPORT Destination Port Number Range (tcp/udp only):
+CMD_AccessAdd_Prompt_SRCUSERNAME Source User Name (all when unspecified):
+CMD_AccessAdd_Prompt_DESTUSERNAME Destination User Name (all when unspecified):
+CMD_AccessAdd_Prompt_SRCMAC Source MAC Address and Mask (all when unspecified):
+CMD_AccessAdd_Prompt_DESTMAC Destination MAC Address and Mask (all when unspecified):
+CMD_AccessAdd_Prompt_TCPSTATE TCP Connection State (Established/Unestablished):
+
+
+# AccessAddEx command
+CMD_AccessAddEx Add Extended Access List Rules (IPv4: Delay, Jitter and Packet Loss Generating)
+CMD_AccessAddEx_Help Use this to add a new rule to the access list of the currently managed Virtual Hub. You can set to generate delays, jitters and packet losses when a packet is passing via the Virtual Hub. \nThe access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define an priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the AccessAddEx command to generate delays, jitters and packet losses. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessAddEx_Args AccessAddEx [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx_[pass|discard] When a packet matches this rule condition, this operation is decided. When pass is specified, the packet is allowed to pass, and when discard is specified, the packet is discarded. The setting of delays, jitters and packet losses is applied if the action is pass.
+CMD_AccessAddEx_MEMO Specify a description (memo) for this rule.
+CMD_AccessAddEx_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values.
+CMD_AccessAddEx_SRCIP Specify a source IPv4 address as a rule condition. Specify the IPv4 address in the format of "IP Address/Mask" by separating the decimal values using dots such as "192.168.0.1". For the mask, either specify decimal values separated by dots such as "255.255.255.0", or you can specify the bit length from the header using a decimal value such as "24". If you specify "0.0.0.0/0.0.0.0", this means all hosts.
+CMD_AccessAddEx_DESTIP Specify a destination IPv4 address as a rule condition in the format of "IP Address/Mask". Use the same method of specification as for the /SRCIP parameter.
+CMD_AccessAddEx_PROTOCOL Specify a protocol type as a rule condition. Input the IP protocol number using decimal values or specify one of the keywords "tcp" (TCP/IP protocol, no.6), "udp" (UDP/IP protocol, no.17), "icmpv4" (ICMPv4 protocol, no.1), "icmpv6" (ICMPv6 protocol, no.58) or "ip" (all protocols, no.0). Specify 0 to make the rule apply to all IP protocols.
+CMD_AccessAddEx_SRCPORT If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. When specifying, do so using the following method "1-1024" (1 to 1024), "23" (only 23).
+CMD_AccessAddEx_DESTPORT If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. Use the same method of specification as for the /SRCPORT parameter.
+CMD_AccessAddEx_SRCUSERNAME You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAddEx_DESTUSERNAME You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAddEx_SRCMAC Specify destination MAC address as a rule. Specify MAC address with "-" or ":" separators and hexadecimal number like "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00". The separators are skippable.
+CMD_AccessAddEx_DESTMAC Specify destination MAC address as a rule. Use the same method of specification as for the /SRCMAC parameter.
+CMD_AccessAddEx_TCPSTATE Specify TCP connection state as a rule. Use Established or Unestablished.
+CMD_AccessAddEx_DELAY Set this value to generate delays when packets is passing. Specify the delay period in milliseconds. Specify 0 means no delays to generate. The delays must be 10000 milliseconds at most.
+CMD_AccessAddEx_JITTER Set this value to generate jitters when packets is passing. Specify the ratio of fluctuation of jitters within 0% to 100% range. Specify 0 means no jitters to generate.
+CMD_AccessAddEx_LOSS Set this value to generate packet losses when packets is passing. Specify the ratio of packet losses within 0% to 100% range. Specify 0 means no packet losses to generate.
+CMD_AccessAddEx_Prompt_DELAY Delays to Generate (in milliseconds: 0 - 10000):
+CMD_AccessAddEx_Prompt_JITTER Fluctuation of Jitters to Generate (Percent: 0 - 100):
+CMD_AccessAddEx_Prompt_LOSS Ratio of Packet Losses (Percent: 0 - 100):
+CMD_AccessAddEx_Eval_DELAY Delays must be 10000 at maximum.
+CMD_AccessAddEx_Eval_JITTER Fluctuation of Jitters must be 100 at maximum.
+CMD_AccessAddEx_Eval_LOSS Ratio of Packet Losses must be 100 at maximum.
+
+
+# AccessAdd6 command
+CMD_AccessAdd6 Add Access List Rules (IPv6)
+CMD_AccessAdd6_Help Use this to add a new rule to the access list of the currently managed Virtual Hub. \nThe access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define an priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the AccessAddEx6 command to generate delays, jitters and packet losses. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessAdd6_Args AccessAdd6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished]
+CMD_AccessAdd6_[pass|discard] When a packet matches this rule condition, this operation is decided. When pass is specified, the packet is allowed to pass, and when discard is specified, the packet is discarded.
+CMD_AccessAdd6_MEMO Specify a description (memo) for this rule.
+CMD_AccessAdd6_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values.
+CMD_AccessAdd6_SRCIP Specify a source IPv6 address as a rule condition. Specify the IPv6 address in the format of "IP Address/Mask" by separating the hexadecimal values using colons such as "2001:200:0:1::". For the mask, either specify hexadecimal values separated by colons such as ffff:ffff:ffff:ffff::, or you can specify the bit length from the header using a decimal value such as "64". If you specify "::/0", this means all hosts.
+CMD_AccessAdd6_DESTIP Specify a destination IPv6 address as a rule condition in the format of "IP Address/Mask". Use the same method of specification as for the /SRCIP parameter.
+CMD_AccessAdd6_PROTOCOL Specify a protocol type as a rule condition. Input the IP protocol number using decimal values or specify one of the keywords "tcp" (TCP/IP protocol, no.6), "udp" (UDP/IP protocol, no.17), "icmpv4" (ICMPv4 protocol, no.1), "icmpv6" (ICMPv6 protocol, no.58) or "ip" (all protocols, no.0). Specify 0 to make the rule apply to all IP protocols.
+CMD_AccessAdd6_SRCPORT If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. When specifying, do so using the following method "1-1024" (1 to 1024), "23" (only 23).
+CMD_AccessAdd6_DESTPORT If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. Use the same method of specification as for the /SRCPORT parameter.
+CMD_AccessAdd6_SRCUSERNAME You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAdd6_DESTUSERNAME You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAdd6_SRCMAC Specify destination MAC address as a rule. Specify MAC address with "-" or ":" separators and hexadecimal number like "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00". The separators can be skipped.
+CMD_AccessAdd6_DESTMAC Specify destination MAC address as a rule. Use the same method of specification as for the /SRCMAC parameter.
+CMD_AccessAdd6_TCPSTATE Specify TCP connection state as a rule. Use Established or Unestablished.
+CMD_AccessAdd6_Prompt_TYPE Pass or Discard:
+CMD_AccessAdd6_Prompt_MEMO Rule Description (Memo):
+CMD_AccessAdd6_Prompt_PRIORITY Rule Priority:
+CMD_AccessAdd6_Eval_PRIORITY Specify an integer of 1 or higher for the priority.
+CMD_AccessAdd6_Prompt_SRCIP Source IP Address ("::/0" specifies all):
+CMD_AccessAdd6_Prompt_DESTIP Destination IP Address ("::/0" specifies all):
+CMD_AccessAdd6_Prompt_PROTOCOL Protocol No. or Protocol Name (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd6_Prompt_SRCPORT Source Port Number Range (tcp/udp only):
+CMD_AccessAdd6_Prompt_DESTPORT Destination Port Number Range (tcp/udp only):
+CMD_AccessAdd6_Prompt_SRCUSERNAME Source User Name (all when unspecified):
+CMD_AccessAdd6_Prompt_DESTUSERNAME Destination User Name (all when unspecified):
+CMD_AccessAdd6_Prompt_SRCMAC Source MAC Address and Mask (all when unspecified):
+CMD_AccessAdd6_Prompt_DESTMAC Destination MAC Address and Mask (all when unspecified):
+CMD_AccessAdd6_Prompt_TCPSTATE TCP Connection State (Established/Unestablished):
+
+
+# AccessAddEx6 command
+CMD_AccessAddEx6 Add Extended Access List Rules (IPv6: Delay, Jitter and Packet Loss Generating)
+CMD_AccessAddEx6_Help Use this to add a new rule to the access list of the currently managed Virtual Hub. You can set to generate delays, jitters and packet losses when a packet is passing via the Virtual Hub. \nThe access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define a priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the AccessAddEx6 command to generate delays, jitters and packet losses. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessAddEx6_Args AccessAddEx6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE: established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx6_[pass|discard] When a packet matches this rule condition, this operation is decided. When pass is specified, the packet is allowed to pass, and when discard is specified, the packet is discarded. The setting of delays, jitters and packet losses is applied if the action is pass.
+CMD_AccessAddEx6_MEMO Specify a description (memo) for this rule.
+CMD_AccessAddEx6_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values.
+CMD_AccessAddEx6_SRCIP Specify a source IPv6 address as a rule condition. Specify the IPv6 address in the format of "IP Address/Mask" by separating the hexadecimal values using colons such as "2001:200:0:1::". For the mask, either specify hexadecimal values separated by colons such as "ffff:ffff:ffff:ffff::", or you can specify the bit length from the header using a decimal value such as 64. If you specify "::/0", this means all hosts.
+CMD_AccessAddEx6_DESTIP Specify a destination IPv6 address as a rule condition in the format of "IP Address/Mask". Use the same method of specification as for the /SRCIP parameter.
+CMD_AccessAddEx6_PROTOCOL Specify a protocol type as a rule condition. Input the IP protocol number using decimal values or specify one of the keywords "tcp" (TCP/IP protocol, no.6), "udp" (UDP/IP protocol, no.17), "icmpv4" (ICMPv4 protocol, no.1), "icmpv6" (ICMPv6 protocol, no.58) or "ip" (all protocols, no.0). Specify 0 to make the rule apply to all IP protocols.
+CMD_AccessAddEx6_SRCPORT If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. When specifying, do so using the following method "1-1024" (1 to 1024), "23" (only 23).
+CMD_AccessAddEx6_DESTPORT If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. Use the same method of specification as for the /SRCPORT parameter.
+CMD_AccessAddEx6_SRCUSERNAME You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAddEx6_DESTUSERNAME You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name.
+CMD_AccessAddEx6_SRCMAC Specify destination MAC address as a rule. Specify MAC address with "-" or ":" separators and hexadecimal number like "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00". The separators can be skipped.
+CMD_AccessAddEx6_DESTMAC Specify destination MAC address as a rule. Use the same method of specification as for the /SRCMAC parameter.
+CMD_AccessAddEx6_TCPSTATE Specify TCP connection state as a rule. Use Established or Unestablished.
+CMD_AccessAddEx6_DELAY Set this value to generate delays when packets is passing. Specify the delay period in milliseconds. Specify 0 means no delays to generate. The delays must be 10000 milliseconds at most.
+CMD_AccessAddEx6_JITTER Set this value to generate jitters when packets is passing. Specify the ratio of fluctuation of jitters within 0% to 100% range. Specify 0 means no jitters to generate.
+CMD_AccessAddEx6_LOSS Set this value to generate packet losses when packets is passing. Specify the ratio of packet losses within 0% to 100% range. Specify 0 means no packet losses to generate.
+CMD_AccessAddEx6_Prompt_DELAY Delays to Generate (in milliseconds: 0 - 10000):
+CMD_AccessAddEx6_Prompt_JITTER Fluctuation of Jitters to Generate (Percent: 0 - 100):
+CMD_AccessAddEx6_Prompt_LOSS Ratio of Packet Losses (Percent: 0 - 100):
+CMD_AccessAddEx6_Eval_DELAY Delays must be 10000 at maximum.
+CMD_AccessAddEx6_Eval_JITTER Fluctuation of Jitters must be 100 at maximum.
+CMD_AccessAddEx6_Eval_LOSS Ratio of Packet Losses must be 100 at maximum.
+
+
+# AccessList command
+CMD_AccessList Get Access List Rule List
+CMD_AccessList_Help Use this to get a list of packet filter rules that are registered on access list of the currently managed Virtual Hub. \nThe access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define a priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessList_Args AccessList
+
+
+# AccessDelete command
+CMD_AccessDelete Delete Rule from Access List
+CMD_AccessDelete_Help Use this to specify a packet filter rule registered on the access list of the currently managed Virtual Hub and delete it. \nTo delete a rule, you must specify that rule's ID. You can display the ID by using the AccessList command. \nIf you wish not to delete the rule but to only temporarily disable it, use the AccessDisable command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessDelete_Args AccessDelete [id]
+CMD_AccessDelete_[id] Specify either the ID or the Unique ID of the rule to delete.
+CMD_Access_Prompt_ID Access List Rule ID or Unique ID:
+
+
+# AccessEnable command
+CMD_AccessEnable Enable Access List Rule
+CMD_AccessEnable_Help Use this to specify a packet filter rule registered on the access list of the currently managed Virtual Hub and enable it. The enabled rule will be used by packet filtering. \nTo enable a rule, you must specify that rule's ID. You can display the ID by using the AccessList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessEnable_Args AccessEnable [id]
+CMD_AccessEnable_[id] Specify the ID of the rule to enable.
+
+
+# AccessDisable command
+CMD_AccessDisable Disable Access List Rule
+CMD_AccessDisable_Help Use this to specify a packet filter rule registered on the access list of the currently managed Virtual Hub and disable it. The disabled rule will be used by packet filtering. \nTo disable a rule, you must specify that rule's ID. You can display the ID by using the AccessList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_AccessDisable_Args AccessDisable [id]
+CMD_AccessDisable_[id] Specify the ID of the rule to disable.
+
+
+# UserList command
+CMD_UserList Get List of Users
+CMD_UserList_Help Use this to get a list of users that are registered on the security account database of the currently managed Virtual Hub. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserList_Args UserList
+
+
+# UserCreate command
+CMD_UserCreate Create User
+CMD_UserCreate_Help Use this to create a new user in the security account database of the currently managed Virtual Hub. \nBy creating a user, the VPN Client can connect to the Virtual Hub by using the authentication information of that user. \nWhen a user is created using the UserCreate command and the auth type of that user is registered as Password Authentication, a random string will be assigned as the password. Therefore, that user will not be able to connect to the Virtual Hub in that state. After creating the user, you must always use the UserPasswordSet command to specify the user password, or alternatively use the UserAnonymousSet command, UserCertSet command, UserSignedSet command, UserRadiusSet command or UserNTLMSet command to change the user's auth type. \nNote that a user whose user name has been created as "*" (a single asterisk character) will automatically be registered as a RADIUS authentication user. For cases where there are users with "*" as the name, when a user, whose user name that was provided when a client connected to a VPN Server does not match existing user names, is able to be authenticated by a RADIUS server or NT domain controller by inputting a user name and password, the authentication settings and security policy settings will follow the setting for the user "*". \nTo change the user information of a user that has been created, use the UserSet command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserCreate_Args UserCreate [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserCreate_[name] Specify the user name of the user to be newly created.
+CMD_UserCreate_GROUP When assigning a user in a group, specify the group name. When not assigning a user to any group, specify /GROUP:none.
+CMD_UserCreate_REALNAME Specify the user's full name. If you are not specifying this, specify /REALNAME:none.
+CMD_UserCreate_NOTE Specify a description of the user. If you are not specifying this, specify /NOTE:none
+CMD_UserCreate_Prompt_NAME User Name:
+CMD_UserCreate_Prompt_GROUP Assigned Group Name:
+CMD_UserCreate_Prompt_REALNAME User Full Name:
+CMD_UserCreate_Prompt_NOTE User Description:
+
+
+# UserSet command
+CMD_UserSet Change User Information
+CMD_UserSet_Help Use this to change user information that is registered on the security account database of the currently managed Virtual Hub. \nThe user information that can be changed using this command are the three items that are specified when a new user is created using the UserCreate command: Group Name, Full Name, and Description. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserSet_Args UserSet [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserSet_GROUP When assigning a user in a group, specify the group name. When not assigning a user to any group, specify /GROUP:none.
+CMD_UserSet_REALNAME Specify the user's full name. If you are not specifying this, specify /REALNAME:none
+CMD_UserSet_NOTE Specify a description of the user. If you are not specifying this, specify /NOTE:none.
+
+
+# UserDelete command
+CMD_UserDelete Delete User
+CMD_UserDelete_Help Use this to delete a user that is registered on the security account database of the currently managed Virtual Hub. By deleting the user, that user will no long be able to connect to the Virtual Hub. \nYou can use the UserPolicySet command to instead of deleting a user, set the user to be temporarily denied from logging in. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserDelete_Args UserDelete [name]
+CMD_UserDelete_[name] Specify the name of the user to delete.
+
+
+# UserGet command
+CMD_UserGet Get User Information
+CMD_UserGet_Help Use this to get user registration information that is registered on the security account database of the currently managed Virtual Hub. \nThe information that you can get using this command are User Name, Full Name, Group Name, Expiration Date, Security Policy, and Auth Type, as well as parameters that are specified as auth type attributes and the statistical data of that user. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserGet_Args UserGet [name]
+CMD_UserGet_[name] Specify the user name of the user whose information you want to get.
+CMD_UserGet_Column_Name User Name
+CMD_UserGet_Column_RealName Full Name
+CMD_UserGet_Column_Note Description
+CMD_UserGet_Column_Group Group Name
+CMD_UserGet_Column_Expires Expiration Date
+CMD_UserGet_Column_AuthType Auth Type
+CMD_UserGet_Column_UserCert Registered User Individual Certificate
+CMD_UserGet_Column_RadiusAlias External Authentication Server Authentication User Name
+CMD_UserGet_Column_RootCert_CN Limit of Certificate CN Value
+CMD_UserGet_Column_RootCert_SERIAL Limit of Certificate Serial Number
+CMD_UserGet_Policy Security Policy Set for this User
+
+
+# UserAnonymousSet command
+CMD_UserAnonymousSet Set Anonymous Authentication for User Auth Type
+CMD_UserAnonymousSet_Help Use this to set Anonymous Authentication as the auth type for a user that is registered on the security account database of the currently managed Virtual Hub. A VPN Client that has connected to a Virtual Hub using a user name of a user set to anonymous authentication can connect to a Virtual Hub without undergoing user authentication and without conditions. The anonymous authentication function is ideally suited to public VPN Servers that are setup to allow anyone to connect via the Internet etc. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserAnonymousSet_Args UserAnonymousSet [name]
+CMD_UserAnonymousSet_[name] Specify the user name of the user whose setting you want to change.
+
+
+# UserPasswordSet command
+CMD_UserPasswordSet Set Password Authentication for User Auth Type and Set Password
+CMD_UserPasswordSet_Help Use this to set Password Authentication as the auth type for a user that is registered on the security account database of the currently managed Virtual Hub. Password Authentication requires a user-defined password to be set for the user object in the security account database of the Virtual Hub and when a user attempts to connect to the Virtual Hub using this user name, they will be prompted to input a password and if it is the matching password, connection will be allowed. \nThe user password is actually saved in hash code which means even if the VPN Server setting file is analyzed, the original password cannot be deciphered. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserPasswordSet_Args UserPasswordSet [name] [/PASSWORD:password]
+CMD_UserPasswordSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserPasswordSet_PASSWORD Specify the password to be set for the user. If this parameter is not specified a prompt will appear to input the password.
+
+
+# UserCertSet command
+CMD_UserCertSet Set Individual Certificate Authentication for User Auth Type and Set Certificate
+CMD_UserCertSet_Help Use this to set Individual Certificate Authentication as the Auth Type for a user that is registered on the security account database of the currently managed Virtual Hub. Individual Certificate Authentication requires one X.509 format certificate to be set for the user object in the security account database of the Virtual Hub and when a user attempts to connect to the Virtual Hub using this user name, an RSA algorithm is used to verify if the provided certificate matches the registered certificate and whether the client holds a private key that corresponds to that certificate and if so, connection is allowed. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserCertSet_Args UserCertSet [name] [/LOADCERT:cert]
+CMD_UserCertSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserCertSet_LOADCERT Specify the certificate to set for the user by specifying an X.509 format certificate file.
+
+
+# UserCertGet command
+CMD_UserCertGet Get Certificate Registered for Individual Certificate Authentication User
+CMD_UserCertGet_Help Use this to get an X.509 format certificate registered for a user of Individual Certificate Authentication who is registered in the security account database of the currently managed Virtual Hub and save it to file. \nIf the specified user is not set as Individual Certificate Authentication an error will occur. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserCertGet_Args UserCertGet [name] [/SAVECERT:cert]
+CMD_UserCertGet_[name] Specify the user name of the user whose information you want to get.
+CMD_UserCertGet_SAVECERT Specify the file name to save, in X.509 format, the user certificate you obtained.
+CMD_UserCertGet_Not_Cert Either the user is not set as individual certificate authentication or a unique certificate is not set.
+
+
+# UserSignedSet command
+CMD_UserSignedSet Set Signed Certificate Authentication for User Auth Type
+CMD_UserSignedSet_Help Use this to set Signed Certificate Authentication as the auth type for a user that is registered on the security account database of the currently managed Virtual Hub. When a user connects to a Virtual Hub using a user name that is set for signed certificate authentication, an RSA algorithm is used to verify whether the certificate provided by the user is signed by any of the certificates in the list of trusted CA certificates of that Virtual Hub and whether the client holds a private key that corresponds with that certificate, and if so, connection is allowed. \nIt is also possible to set the connection to be allowed only when a certificate common name (CN) and serial number that is expected for each user is registered and the contents of the certificate after the abovementioned verification is passed matches the set value. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserSignedSet_Args UserSignedSet [name] [/CN:cn] [/SERIAL:serial]
+CMD_UserSignedSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserSignedSet_CN When this parameter is set, after it has been verified that the certificate that the user provided has been signed by the trusted certificate authority, connection will only be allowed when the value of the common name (CN) of this certificate is compared with the value set by this parameter and the values match. When "none" is specified, this check is not made.
+CMD_UserSignedSet_SERIAL When this parameter is set, after it has been verified that the certificate that the user provided has been signed by the trusted certificate authority, connection will only be allowed when the value of the serial number of this certificate is compared with the value set by this parameter and the values match. When "none" is specified, this check is not made.
+CMD_UserSignedSet_Prompt_CN Limit of Common Name (CN) Value:
+CMD_UserSignedSet_Prompt_SERIAL Limit of Serial Number Value:
+
+
+# UserRadiusSet command
+CMD_UserRadiusSet Set RADIUS Authentication for User Auth Type
+CMD_UserRadiusSet_Help Use this to set RADIUS Authentication as the auth type for a user that is registered on the security account database of the currently managed Virtual Hub. When a user connects to a Virtual Hub using a user name that is set for RADIUS authentication, the user name and the user input password is sent to the RADIUS server where the RADIUS SERVER checks the user name and password, then if the verification is successful, that user is allowed VPN connection. \nIn order to user RADIUS authentication, the RADIUS server used for this verification must be set in the Virtual Hub beforehand by using the RadiusServerSet command. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserRadiusSet_Args UserRadiusSet [name] [/ALIAS:alias_name]
+CMD_UserRadiusSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserRadiusSet_ALIAS When this parameter is set, it is possible to make the user name sent to the RADIUS server different to the user name on the Virtual Hub. When this is not set, please specify /ALIAS:none (the user name on the Virtual Hub will be used). If the user name is "*", the /ALIAS parameter will be ignored. To read an explanation of the "*" user, please input UserCreate/HELP to display this information.
+CMD_UserRadiusSet_Prompt_ALIAS Alias Name for Authentication (Optional):
+
+
+# UserNTLMSet コマンド
+CMD_UserNTLMSet Set NT Domain Authentication for User Auth Type
+CMD_UserNTLMSet_Help Use this to set NT Domain Authentication as the auth type for a user that is registered on the security account database of the currently managed Virtual Hub. When a user connects to a Virtual Hub using a user name that is set for NT Domain authentication, the user name and the user input password is sent to the Windows NT / 2000 / Server 2003 / Server 2008 / Server 2008 R2 / Server 2012 Domain Controller or Active Directory Server where the server checks the user name and password, then if the verification is successful, that user is allowed VPN connection. \nTo use NT Domain authentication, the VPN Server must be operating on a Windows NT 4.0, Windows 2000, Windows XP, Windows Vista, Windows Server 2008, Windows Server 2008 R2 or Windows Server 2012 operating system that is connected to that domain. For details please contact the VPN Server's administrator. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserNTLMSet_Args UserNTLMSet [name] [/ALIAS:alias_name]
+CMD_UserNTLMSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserNTLMSet_ALIAS When this parameter is set, it is possible to make the user name sent to the NT Domain or Active Directory server different to the user name on the Virtual Hub. When this is not set, please specify /ALIAS:none (the user name on the Virtual Hub will be used). If the user name is "*", the /ALIAS parameter will be ignored. To read an explanation of the "*" user, please input UserCreate/HELP to display this information.
+
+
+# UserPolicyRemove command
+CMD_UserPolicyRemove Delete User Security Policy
+CMD_UserPolicyRemove_Help Use this to delete the security policy setting that is set for a user that is registered on the security account database of the currently managed Virtual Hub. A user who has had their security policy setting deleted will be assigned the security policy setting of the group that user is assigned to. In the cases where the user is not assigned to a group or when a security policy setting has not been set for the group, the default values (Allow Access: Enabled, Maximum Number of TCP Connections: 32, Time-out Period: 20 seconds) will be applied. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserPolicyRemove_Args UserPolicyRemove [name]
+CMD_UserPolicyRemove_[name] Specify the user name of the user whose setting you want to change.
+
+
+# UserPolicySet command
+CMD_UserPolicySet Set User Security Policy
+CMD_UserPolicySet_Help Use this to set the security policy contents that are set for a user that is registered on the security account database of the currently managed Virtual Hub. \nWhen a user has not been set a security policy, use this to change the specified values after a new default security policy has been set. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserPolicySet_Args UserPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_UserPolicySet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserPolicySet_NAME Specify the name of policy whose values you want to change. You can use the PolicyList command to display a list of policy names and values that can be set.
+CMD_UserPolicySet_VALUE Specify a new policy value. If the policy is an integer value, specify an integer. Specify yes or no for Boolean types. You can view the type and value that can be set by using the PolicyList command.
+
+
+# UserExpiresSet command
+CMD_UserExpiresSet Set User's Expiration Date
+CMD_UserExpiresSet_Help Use this to set the user's expiration date that is registered on the security account database of the currently managed Virtual Hub. A user whose expiration date has expired cannot connect to the Virtual Hub. \nTo get the list of currently registered users, use the UserList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_UserExpiresSet_Args UserExpiresSet [name] [/EXPIRES:expires]
+CMD_UserExpiresSet_[name] Specify the user name of the user whose setting you want to change.
+CMD_UserExpiresSet_EXPIRES Specify the user expiration date and time. The date and time must be in the same format as "2005/10/08 19:30:00" where 6 integers are specified, representing year/month/day hour:minute:second separated by forward slashes, a space and then colons. Specify 4 digits for the year. If you put a space in a value, the entire value must be enclosed by "". For this specification, local time (standard time for the computer on which the command line management utility is running) can be specified. By specifying /EXPIRES:none, you can remove the expiration date restriction.
+CMD_UserExpiresSet_Prompt_EXPIRES User Expiration Date (no expiration if nothing specified):
+
+
+# GroupList command
+CMD_GroupList Get List of Groups
+CMD_GroupList_Help Use this to get a list of groups that are registered on the security account database of the currently managed Virtual Hub. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupList_Args GroupList
+
+
+# GroupCreate command
+CMD_GroupCreate Create Group
+CMD_GroupCreate_Help Use this to create a new group in the security account database of the currently managed Virtual Hub. \nYou can register multiple users in a group. To register users in a group use the GroupJoin command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupCreate_Args GroupCreate [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupCreate_[name] Specify the name of the group to create.
+CMD_GroupCreate_REALNAME Specify the group's full name. For example, if the group corresponds to an actual section or department name, specify that name. If you are not specifying this, specify /REALNAME:none
+CMD_GroupCreate_NOTE Specify a description of the group. If you are not specifying this, specify /NOTE:none
+CMD_GroupCreate_Prompt_NAME Group Name:
+CMD_GroupCreate_Prompt_REALNAME Group Full Name:
+CMD_GroupCreate_Prompt_NOTE Group Description:
+
+
+# GroupSet command
+CMD_GroupSet Set Group Information
+CMD_GroupSet_Help Use this to set group information that is registered on the security account database of the currently managed Virtual Hub. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupSet_Args GroupSet [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupSet_[name] Specify the group name of the group whose setting you want to change.
+CMD_GroupSet_REALNAME Specify the group's Full name. For example, if the group corresponds to an actual section or department name, specify that name. If you are not specifying this, specify /REALNAME:none
+CMD_GroupSet_NOTE Specify a description of the group. If you are not specifying this, specify /NOTE:none.
+
+
+# GroupDelete command
+CMD_GroupDelete Delete Group
+CMD_GroupDelete_Help Use this to delete a group that is registered on the security account database of the currently managed Virtual Hub. \nWhen you delete a group all users assigned to that group will become unassigned. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupDelete_Args GroupDelete [name]
+CMD_GroupDelete_[name] Specify the name of the group to delete.
+
+
+# GroupGet command
+CMD_GroupGet Get Group Information and List of Assigned Users
+CMD_GroupGet_Help Use this to get the information of a group that is registered on the security account database of the currently managed Virtual Hub as well as a list of users assigned to that group. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupGet_Args GroupGet [name]
+CMD_GroupGet_[name] Specify the group name of the group whose information you want to get.
+CMD_GroupGet_Column_NAME Group Name
+CMD_GroupGet_Column_REALNAME Full Name
+CMD_GroupGet_Column_NOTE Description
+CMD_GroupGet_Column_POLICY This is the security policy that is set for this group.
+CMD_GroupGet_Column_MEMBERS This is a list of user names of users who are assigned to this group.
+
+
+# GroupJoin command
+CMD_GroupJoin Add User to Group
+CMD_GroupJoin_Help Use this to add a user in the security account database of the currently managed Virtual Hub to a group that is registered on that security account database. \nTo get a list of users and groups that are currently registered, use the UserList command and the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupJoin_Args GroupJoin [name] [/USERNAME:username]
+CMD_GroupJoin_[name] Specify the group name of the group to which you want to add a user.
+CMD_GroupJoin_USERNAME Specify the user name of the user you want to add to the group specified by "name".
+CMD_GroupJoin_Prompt_USERNAME Name of User to Join Group:
+
+
+# GroupUnjoin command
+CMD_GroupUnjoin Delete User from Group
+CMD_GroupUnjoin_Help Use this to delete a specified user from the group that is registered on the security account database of the currently managed Virtual Hub. By deleting a user from the group, that user becomes unassigned. \nTo get a list of users that are currently assigned to a group, use the GroupGet command. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupUnjoin_Args GroupUnjoin [name]
+CMD_GroupUnjoin_[name] Specify the name of the user to delete from the group.
+CMD_GroupUnjoin_Prompt_name Name of User to Delete from Group:
+
+
+# GroupPolicyRemove command
+CMD_GroupPolicyRemove Delete Group Security Policy
+CMD_GroupPolicyRemove_Help Use this to delete the security policy setting that is set for a group that is registered on the security account database of the currently managed Virtual Hub. Users who do not have a security policy set for the user themselves or for the group they are assigned to, will have the default values (Allow Access: Enabled, Maximum Number of TCP Connections: 32, Time-out Period: 20 seconds) applied to them. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupPolicyRemove_Args GroupPolicyRemove [name]
+CMD_GroupPolicyRemove_[name] Specify the group name of the group whose setting you want to change.
+
+
+# GroupPolicySet command
+CMD_GroupPolicySet Set Group Security Policy
+CMD_GroupPolicySet_Help Use this to set the security policy contents that are set for a group that is registered on the security account database of the currently managed Virtual Hub. \nWhen a group has not been set a security policy, use this to change the specified values after a new default security policy has been set. \nTo get the list of currently registered groups, use the GroupList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a member server on a cluster.
+CMD_GroupPolicySet_Args GroupPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_GroupPolicySet_[name] Specify the group name of the group whose setting you want to change.
+CMD_GroupPolicySet_NAME Specify the name of policy whose values you want to change. You can use the PolicyList command to display a list of policy names and values that can be set.
+CMD_GroupPolicySet_VALUE Specify a new policy value. If the policy is an integer value, specify an integer. Specify yes or no for Boolean types. You can view the type and value that can be set by using the PolicyList command.
+
+
+# SessionList command
+CMD_SessionList Get List of Connected Sessions
+CMD_SessionList_Help Use this to get a list of the sessions connected to the Virtual Hub currently being managed. In the list of sessions, the following information will be displayed for each connection: Session Name, Session Site, User Name, Source Host Name, TCP Connection, Transfer Bytes and Transfer Packets. \nIf the currently connected VPN Server is a cluster controller and the currently managed Virtual Hub is a static Virtual Hub, you can get an all-linked-together list of all sessions connected to that Virtual Hub on all cluster members. \nIn all other cases, only the list of sessions that are actually connected to the currently managed VPN Server will be obtained.
+CMD_SessionList_Args SessionList
+
+
+# SessionGet command
+CMD_SessionGet Get Session Information
+CMD_SessionGet_Help Use this to specify a session currently connected to the currently managed Virtual Hub and get the session information. The session information includes the following: source host name and user name, version information, time information, number of TCP connections, communication parameters, session key, statistical information on data transferred, and other client and server information. \nTo get the list of currently connected sessions, use the SessionList command.
+CMD_SessionGet_Args SessionGet [name]
+CMD_SessionGet_[name] Specify the session name of the session whose information you want to get.
+CMD_SessionGet_Prompt_NAME Session name:
+
+
+# SessionDisconnect command
+CMD_SessionDisconnect Disconnect Session
+CMD_SessionDisconnect_Help Use this to specify a session currently connected to the currently managed Virtual Hub and forcefully disconnect that session using manager privileges. \nNote that when communication is disconnected by settings on the source client side and the automatically reconnect option is enabled, it is possible that the client will reconnect. \nTo get the list of currently connected sessions, use the SessionList command.
+CMD_SessionDisconnect_Args SessionDisconnect [name]
+CMD_SessionDisconnect_[name] Specify the session name of the session to disconnect.
+
+
+# MacTable command
+CMD_MacTable Get the MAC Address Table Database
+CMD_MacTable_Help Use this to get the MAC address table database that is held by the currently managed Virtual Hub. \nThe MAC address table database is a table that the Virtual Hub requires to perform the action of switching Ethernet frames and the Virtual Hub decides the sorting destination session of each Ethernet frame based on the MAC address table database. The MAC address database is built by the Virtual Hub automatically analyzing the contents of the communication throughput. \nBy specifying the session name you can get the MAC address table entry that has been associated with that session.
+CMD_MacTable_Args MacTable [session_name]
+CMD_MacTable_[session_name] By specifying the session name as a parameter, you can display only the MAC address table entry that is associated with that session. When this is left unspecified, all the entries will be displayed.
+
+
+# MacDelete command
+CMD_MacDelete Delete MAC Address Table Entry
+CMD_MacDelete_Help Use this command to operate the MAC address table database held by the currently managed Virtual Hub and delete a specified MAC address table entry from the database. \nTo get the contents of the current MAC address table database use the MacTable command.
+CMD_MacDelete_Args MacDelete [id]
+CMD_MacDelete_[id] Specify the ID of the MAC address table entry to delete.
+CMD_MacDelete_Prompt ID to Delete:
+
+
+# IpTable command
+CMD_IpTable Get the IP Address Table Database
+CMD_IpTable_Help Use this to get the IP address table database that is held by the currently managed Virtual Hub. \nThe IP address table database is a table that is automatically generated by analyzing the contents of communication so that the Virtual Hub can always know which session is using which IP address and it is frequently used by the engine that applies the Virtual Hub security policy. \nBy specifying the session name you can get the IP address table entry that has been associated with that session.
+CMD_IpTable_Args IpTable [session_name]
+CMD_IpTable_[session_name] By specifying the session name as a parameter, you can display only the IP address table entry that is associated with that session. When this is left unspecified, all the entries will be displayed.
+
+
+# IpDelete command
+CMD_IpDelete Delete IP Address Table Entry
+CMD_IpDelete_Help Use this command to operate the IP address table database held by the currently managed Virtual Hub and delete a specified IP address table entry from the database. \nTo get the contents of the current IP address table database use the IpTable command.
+CMD_IpDelete_Args IpDelete [id]
+CMD_IpDelete_[id] Specify the ID of the IP address table entry to delete.
+
+
+# SecureNatEnable command
+CMD_SecureNatEnable Enable the Virtual NAT and DHCP Server Function (SecureNat Function)
+CMD_SecureNatEnable_Help Use this to enable the Virtual NAT and DHCP Server function (SecureNat Function) on the currently managed Virtual Hub and begin its operation. Before executing this command, you must first check the setting contents of the current Virtual NAT function and DHCP Server function using the SecureNatHostGet command, NatGet command and DhcpGet command. \nBy enabling the SecureNAT function, you can virtually operate a NAT router (IP masquerade) and the DHCP Server function on a virtual network on the Virtual Hub. \n\n[Warning about SecureNAT Function]\nThe SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. \nIf you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrator's permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SecureNatEnable_Args SecureNatEnable
+
+
+# SecureNatDisable command
+CMD_SecureNatDisable Disable the Virtual NAT and DHCP Server Function (SecureNat Function)
+CMD_SecureNatDisable_Help Use this to disable the Virtual NAT and DHCP Server function (SecureNat Function) on the currently managed Virtual Hub. By executing this command the Virtual NAT function immediately stops operating and the Virtual DHCP Server function deletes the DHCP lease database and stops the service. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SecureNatDisable_Args SecureNatDisable
+
+
+# SecureNatStatusGet command
+CMD_SecureNatStatusGet Get the Operating Status of the Virtual NAT and DHCP Server Function (SecureNat Function)
+CMD_SecureNatStatusGet_Help Use this to get the operating status of the Virtual NAT and DHCP Server function (SecureNat Function) when it is operating on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SecureNatStatusGet_Args SecureNatStatusGet
+
+
+# SecureNatHostGet command
+CMD_SecureNatHostGet Get Network Interface Setting of Virtual Host of SecureNAT Function
+CMD_SecureNatHostGet_Help Use this to get the virtual host network interface setting from the setting items of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. \nThe SecureNAT function holds one virtual network adapter on the L2 segment inside the Virtual Hub and it has been assigned a MAC address and an IP address. By doing this, another host connected to the same L2 segment is able to communicate with the SecureNAT virtual host as if it is an actual IP host existing on the network. \n\n[Warning about SecureNAT Function]\nThe SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. \nIf you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrators permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SecureNatHostGet_Args SecureNatHostGet
+CMD_SecureNatHostGet_Column_MAC MAC Address
+CMD_SecureNatHostGet_Column_IP IP Address
+CMD_SecureNatHostGet_Column_MASK Subnet Mask
+CMD_SecureNatHostGet_Column_LOG Save NAT and DHCP Operation Log
+
+
+# SecureNatHostSet command
+CMD_SecureNatHostSet Change Network Interface Setting of Virtual Host of SecureNAT Function
+CMD_SecureNatHostSet_Help Use this to change and save the virtual host network interface setting in the setting items of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. \nThe SecureNAT function holds one virtual network adapter on the L2 segment inside the Virtual Hub and it has been assigned a MAC address and an IP address. By doing this, another host connected to the same L2 segment is able to communicate with the SecureNAT virtual host as if it is an actual IP host existing on the network. \n\n[Warning about SecureNAT Function]\nThe SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. \nIf you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrators permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SecureNatHostSet_Args SecureNatHostSet [/MAC:mac] [/IP:ip] [/MASK:mask]
+CMD_SecureNatHostSet_MAC Specify the MAC address to assign for the virtual interface. Specify a MAC address using a string like "00-AC-01-23-45-67". When /MAC:none is specified, no changes will be made to the current setting.
+CMD_SecureNatHostSet_IP Specify the IP address to assign for the virtual interface. When /IP:none is specified, no changes will be made to the current setting.
+CMD_SecureNatHostSet_MASK Specify the subnet mask to assign for the virtual interface. When /MASK:none is specified, no changes will be made to the current setting.
+CMD_SecureNatHostSet_Prompt_MAC MAC Address:
+CMD_SecureNatHostSet_Prompt_IP IP Address:
+CMD_SecureNatHostSet_Prompt_MASK Subnet Mask:
+
+
+# NatGet command
+CMD_NatGet Get Virtual NAT Function Setting of SecureNAT Function
+CMD_NatGet_Help Use this to get the virtual NAT setting from the setting items of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_NatGet_Args NatGet
+CMD_NatGet_Column_USE Use Virtual NAT Function
+CMD_NetGet_Column_MTU MTU Value
+CMD_NatGet_Column_TCP TCP Session Timeout (Seconds)
+CMD_NatGet_Column_UDP UDP Session Timeout (Seconds)
+
+
+# NatEnable command
+CMD_NatEnable Enable Virtual NAT Function of SecureNAT Function
+CMD_NatEnable_Help Use this to enable the Virtual NAT function on the currently managed Virtual Hub. \nIf the SecureNAT function is still not operating even after this command has been used to enable the Virtual NAT function, Virtual NAT is not operating. To start the operation of the SecureNAT Function, use the SecureNatEnable command. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_NatEnable_Args NatEnable
+
+
+# NatDisable command
+CMD_NatDisable Disable Virtual NAT Function of SecureNAT Function
+CMD_NatDisable_Help Use this to disable the Virtual NAT function on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_NatDisable_Args NatDisable
+
+
+# NatSet command
+CMD_NatSet Change Virtual NAT Function Setting of SecureNAT Function
+CMD_NatSet_Help Use this to change the Virtual NAT setting of the currently managed Virtual Hub. The contents of the Virtual NAT setting includes: MTU value, TCP session timeout and UDP session timeout \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_NatSet_Args NatSet [/MTU:mtu] [/TCPTIMEOUT:tcp_timeout] [/UDPTIMEOUT:udp_timeout] [/LOG:yes|no]
+CMD_NatSet_MTU Set the MTU (Maximum transferable unit size) using an integer to specify the byte length unit. This value is the maximum payload length excluding the MAC header of the Ethernet frame that the Virtual NAT sends and the default is 1500 bytes.
+CMD_NatSet_TCPTIMEOUT This sets how many seconds a condition of non-communication continues in a TCP session that the Virtual NAT is relaying before a timeout occurs and the session is discarded.
+CMD_NatSet_UDPTIMEOUT This sets how many seconds a condition of non-communication continues in a UDP session that the Virtual NAT is relaying before a timeout occurs and the session is discarded.
+CMD_NatSet_LOG Specify whether or not to save the Virtual NAT operation in the Virtual Hub security log. Specify "yes" to save it, and "no" to not save it.
+CMD_NatSet_Prompt_MTU MTU Value:
+CMD_NatSet_Prompt_TCPTIMEOUT TCP Session Timeout (Seconds):
+CMD_NatSet_Prompt_UDPTIMEOUT UDP Session Timeout (Seconds):
+CMD_NatSet_Prompt_LOG Save Log (yes / no):
+CMD_NatSet_Eval_MTU Specify a value in the range %d to %d for the MTU value.
+CMD_NatSet_Eval_TCP Specify the number of seconds in the range %d to %d for the TCP session timeout.
+CMD_NatSet_Eval_UDP Specify the number of seconds in the range %d to %d for the UDP session timeout.
+
+
+# NatTable command
+CMD_NatTable Get Virtual NAT Function Session Table of SecureNAT Function
+CMD_NatTable_Help Use this to get the table of TCP and UDP sessions currently communicating via the Virtual NAT (NAT table) in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_NatTable_Args NatTable
+
+
+# DhcpGet command
+CMD_DhcpGet Get Virtual DHCP Server Function Setting of SecureNAT Function
+CMD_DhcpGet_Help Use this to get the virtual DHCP Server setting from the setting items of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_DhcpGet_Args DhcpGet
+CMD_DhcpGet_Column_Log Record Log of NAT and DHCP Operation
+CMD_DhcpGet_Column_USE Use Virtual DHCP Function
+CMD_DhcpGet_Column_IP1 Start Distribution Address Band
+CMD_DhcpGet_Column_IP2 End Distribution Address Band
+CMD_DhcpGet_Column_MASK Subnet Mask
+CMD_DhcpGet_Column_LEASE Lease Limit (Seconds)
+CMD_DhcpGet_Column_GW Default Gateway Address
+CMD_DhcpGet_Column_DNS DNS Server Address 1
+CMD_DhcpGet_Column_DNS2 DNS Server Address 2
+CMD_DhcpGet_Column_DOMAIN Domain Name
+
+
+# DhcpEnable command
+CMD_DhcpEnable Enable Virtual DHCP Server Function of SecureNAT Function
+CMD_DhcpEnable_Help Use this to enable the Virtual DHCP Server function on the currently managed Virtual Hub. \nIf the SecureNAT function is still not operating even after this command has been used to enable the Virtual DHCP function, Virtual DHCP Server is not operating. To start the operation of the SecureNAT Function, use the SecureNatEnable command. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_DhcpEnable_Args DhcpEnable
+
+
+# DhcpDisable command
+CMD_DhcpDisable Disable Virtual DHCP Server Function of SecureNAT Function
+CMD_DhcpDisable_Help Use this to disable the Virtual DHCP Server function on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_DhcpDisable_Args DhcpDisable
+
+
+# DhcpSet command
+CMD_DhcpSet Change Virtual DHCP Server Function Setting of SecureNAT Function
+CMD_DhcpSet_Help Use this to change the Virtual DHCP Server setting of the currently managed Virtual Hub. The Virtual DHCP Server settings include the following items: distribution address band, subnet mask, lease limit, and option values assigned to clients. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_DhcpSet_Args DhcpSet [/START:start_ip] [/END:end_ip] [/MASK:subnetmask] [/EXPIRE:sec] [/GW:gwip] [/DNS:dns] [/DNS2:dns2][/DOMAIN:domain] [/LOG:yes|no]
+CMD_DhcpSet_START Specify the start point of the address band to be distributed to the client. (Example: 192.168.30.10)
+CMD_DhcpSet_END Specify the end point of the address band to be distributed to the client. (Example: 192.168.30.200)
+CMD_DhcpSet_MASK Specify the subnet mask to be specified for the client. (Example: 255.255.255.0)
+CMD_DhcpSet_EXPIRE Specify the expiration date in second units for leasing an IP address to a client.
+CMD_DhcpSet_GW Specify the IP address of the default gateway to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify 0 or none, then the client will not be notified of the default gateway.
+CMD_DhcpSet_DNS Specify the IP address of the primary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify 0 or none, then the client will not be notified of the DNS Server address.
+CMD_DhcpSet_DNS2 Specify the IP address of the secondary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify 0 or none, then the client will not be notified of the DNS Server address.
+CMD_DhcpSet_DOMAIN Specify the domain name to be notified to the client. If you specify none, then the client will not be notified of the domain name.
+CMD_DhcpSet_LOG Specify whether or not to save the Virtual DHCP Server operation in the Virtual Hub security log. Specify "yes" to save it. This value is interlinked with the Virtual NAT Function log save setting.
+CMD_DhcpSet_Prompt_START Start Point for Distributed Address Band:
+CMD_DhcpSet_Prompt_END End Point for Distributed Address Band:
+CMD_DhcpSet_Prompt_MASK Subnet Mask:
+CMD_DhcpSet_Prompt_EXPIRE Lease Limit (Seconds):
+CMD_DhcpSet_Prompt_GW Default Gateway ('none' to not set this):
+CMD_DhcpSet_Prompt_DNS DNS Server 1 ('none' to not set this):
+CMD_DhcpSet_Prompt_DNS2 DNS Server 2 ('none' to not set this):
+CMD_DhcpSet_Prompt_DOMAIN Domain Name:
+
+
+# DhcpTable command
+CMD_DhcpTable Get Virtual DHCP Server Function Lease Table of SecureNAT Function
+CMD_DhcpTable_Help Use this to get the lease table of IP addresses, held by the Virtual DHCP Server, that are assigned to clients in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_DhcpTable_Args DhcpTable
+
+
+# AdminOptionList command
+CMD_AdminOptionList Get List of Virtual Hub Administration Options
+CMD_AdminOptionList_Help Use this to get a list of Virtual Hub administration options that are set on the currently managed Virtual Hub. \nThe purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. \nOnly an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. \nThere is an exception however. If allow_hub_admin_change_option is set to "1", even Virtual Hub administrators are able to edit the administration options. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster member.
+CMD_AdminOptionList_Args AdminOptionList
+
+
+# AdminOptionSet command
+CMD_AdminOptionSet Set Values of Virtual Hub Administration Options
+CMD_AdminOptionSet_Help Use this to change the values of Virtual Hub administration options that are set on the currently managed Virtual Hub. \nThe purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. \nOnly an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. \nThere is an exception however. If allow_hub_admin_change_option is set to "1", even Virtual Hub administrators are able to edit the administration options. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster member.
+CMD_AdminOptionSet_Args AdminOptionSet [name] [/VALUE:value]
+CMD_AdminOptionSet_[name] Specify the name of the administration option whose value you want to change. You can get a list of names by using the AdminOptionList command.
+CMD_AdminOptionSet_VALUE Specify an integer for the setting value.
+CMD_AdminOptionSet_Prompt_name Name of Administration Option to Change Value:
+CMD_AdminOptionSet_Prompt_VALUE Setting Value (Integer):
+
+
+# ExtOptionList command
+CMD_ExtOptionList Get List of Virtual Hub Extended Options
+CMD_ExtOptionList_Help Use this to get a Virtual Hub Extended Options List that is set on the currently managed Virtual Hub.\nVirtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub.\nBy default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options.\nHowever, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options.\nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster member.
+CMD_ExtOptionList_Args ExtOptionList
+
+
+# ExtOptionSet command
+CMD_ExtOptionSet Set a Value of Virtual Hub Extended Options
+CMD_ExtOptionSet_Help Use this to set a value in the Virtual Hub Extended Options List that is set on the currently managed Virtual Hub.\nVirtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub.\nBy default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options.\nHowever, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options.\nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster member.
+CMD_ExtOptionSet_Args ExtOptionSet [name] [/VALUE:value]
+CMD_ExtOptionSet_[name] Specify the name of the Virtual Hub Extended Options whose value you want to change. You can get a list of names by using the ExtOptionList command.
+CMD_ExtOptionSet_VALUE Specify an integer for the setting value.
+CMD_ExtOptionSet_Prompt_name Name of Extended Option to Change Value:
+CMD_ExtOptionSet_Prompt_VALUE Setting Value (Integer):
+
+
+# CrlList command
+CMD_CrlList Get List of Certificates Revocation List
+CMD_CrlList_Help Use this to get a Certificates Revocation List that is set on the currently managed Virtual Hub. \nBy registering certificates in the Certificates Revocation List, the clients who provide these certificates will be unable to connect to this Virtual Hub using certificate authentication mode. \nNormally with this function, in cases where the security of a private key has been compromised or where a person holding a certificate has been stripped of their privileges, by registering that certificate as invalid on the Virtual Hub, it is possible to deny user authentication when that certificate is used by a client to connect to the Virtual Hub. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CrlList_Args CrlList
+
+
+# CrlAdd command
+CMD_CrlAdd Add a Revoked Certificate
+CMD_CrlAdd_Help Use this to add a new revoked certificate definition in the Certificate Revocation List that is set on the currently managed Virtual Hub. \nSpecify the contents to be registered in the Certificate Revocation List by using the parameters of this command. When a user connects to a Virtual Hub in certificate authentication mode and that certificate matches 1 or more of the contents registered in the certificates revocation list, the user is denied connection. \nA certificate that matches all the conditions that are defined by the parameters specified by this command will be judged as invalid. \nThe items that can be set are as follows: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number (hexadecimal), MD5 Digest Value (hexadecimal, 128 bit), and SHA-1 Digest Value (hexadecimal, 160 bit). For the specification of a digest value (hash value) a certificate is optionally specified depending on the circumstances. Normally when a MD5 or SHA-1 digest value is input, it is not necessary to input the other items. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CrlAdd_Args CrlAdd [/SERIAL:serial] [/MD5:md5] [/SHA1:sha1] [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l]
+CMD_CrlAdd_SERIAL Use this parameter to specify the value for the certificate serial number (hexadecimal) when it is set as a condition.
+CMD_CrlAdd_MD5 Use this parameter to specify the value for the certificate MD5 digest value (hexadecimal, 128 bits) when it is set as a condition. If this parameter specification is other than a hexadecimal value of 32 characters (16 bytes), it will be ignored.
+CMD_CrlAdd_SHA1 Use this parameter to specify the value for the certificate SHA1 digest value (hexadecimal, 160 bits) when it is set as a condition. If this parameter specification is other than a hexadecimal value of 40 characters (16 bytes), it will be ignored.
+CMD_CrlAdd_CN Use this parameter to specify the name (CN) of the certificate when it is set as a condition.
+CMD_CrlAdd_O Use this parameter to specify the organization (O) of the certificate when it is set as a condition.
+CMD_CrlAdd_OU Use this parameter to specify the organization unit (OU) of the certificate when it is set as a condition.
+CMD_CrlAdd_C Use this parameter to specify the country (C) of the certificate when it is set as a condition.
+CMD_CrlAdd_ST Use this parameter to specify the state (ST) of the certificate when it is set as a condition.
+CMD_CrlAdd_L Use this parameter to specify the locale (L) of the certificate when it is set as a condition.
+
+
+# CrlDel command
+CMD_CrlDel Delete a Revoked Certificate
+CMD_CrlDel_Help Use this to specify and delete a revoked certificate definition from the certificate revocation list that is set on the currently managed Virtual Hub. \nTo get the list of currently registered revoked certificate definitions, use the CrlList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CrlDel_Args CrlDel [id]
+CMD_CrlDel_[id] Specify the ID of the revoked certificate definition you want to delete.
+CMD_CrlDel_Prompt_ID ID to Delete:
+
+
+# CrlGet command
+CMD_CrlGet Get a Revoked Certificate
+CMD_CrlGet_Help Use this to specify and get the contents of a revoked certificate definition from the Certificates Revocation List that is set on the currently managed Virtual Hub. \nTo get the list of currently registered revoked certificate definitions, use the CrlList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_CrlGet_Args CrlGet [id]
+CMD_CrlGet_[id] Specify the ID of the revoked certificate definition you want to get.
+CMD_CrlGet_Prompt_ID ID to Get:
+CMD_CrlGet_CN Common Name (CN)
+CMD_CrlGet_O Organization (O)
+CMD_CrlGet_OU Organization Unit (OU)
+CMD_CrlGet_C Country (C)
+CMD_CrlGet_ST State (ST)
+CMD_CrlGet_L Locale (L)
+CMD_CrlGet_SERI Serial Number (Hexadecimal)
+CMD_CrlGet_MD5_HASH MD5 Digest Value (Hexadecimal, 128 bit)
+CMD_CrlGet_SHA1_HASH SHA-1 Digest Value (Hexadecimal, 160 bit)
+
+
+# AcList command
+CMD_AcList Get List of Rule Items of Source IP Address Limit List
+CMD_AcList_Help Use this to get a list of Source IP Address Limit List rules that is set on the currently managed Virtual Hub. \nYou can allow or deny VPN connections to this Virtual Hub according to the client computer's source IP address. You can define multiple rules and set a priority for each rule. The search proceeds from the rule with the highest order or priority and based on the action of the rule that the IP address first matches, the connection from the client is either allowed or denied. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_AcList_Args AcList
+
+
+# AcAdd command
+CMD_AcAdd Add Rule to Source IP Address Limit List (IPv4)
+CMD_AcAdd_Help Use this to add a new rule to the Source IP Address Limit List that is set on the currently managed Virtual Hub. \nThe items set here will be used to decide whether to allow or deny connection from a VPN Client when this client attempts connection to the Virtual Hub. \nYou can specify a client IP address, or IP address or mask to match the rule as the contents of the rule item. By specifying an IP address only, there will only be one specified computer that will match the rule, but by specifying an IP net mask address or subnet mask address, all the computers in the range of that subnet will match the rule. \nYou can specify the priority for the rule. You can specify an integer of 1 or greater for the priority and the smaller the number, the higher the priority. \nTo get a list of the currently registered Source IP Address Limit List, use the AcList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_AcAdd_Args AcAdd [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd_[allow|deny] Set whether to "allow" or "deny" the connection from a client that matches the rule.
+CMD_AcAdd_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. The smaller the value the higher the priority.
+CMD_AcAdd_IP Using the format: "IP Address/Mask", specify the range of client IPv4 addresses. Specify the IPv4 address by separating the decimal values using dots such as "192.168.0.1". For the mask, either specify decimal values separated by dots such as "255.255.255.0", or you can specify the bit length from the header using a decimal value such as "24". To specify a single IPv4 host, specify the mask as "32" or "255.255.255.255".
+CMD_AcAdd_Prompt_AD allow or deny:
+CMD_AcAdd_Prompt_PRIORITY Priority:
+CMD_AcAdd_Prompt_IP IPv4 Address/Mask:
+CMD_AcAdd_Eval_PRIORITY Specify 1 or higher for the priority.
+
+
+# AcAdd6 command
+CMD_AcAdd6 Add Rule to Source IP Address Limit List (IPv6)
+CMD_AcAdd6_Help Use this to add a new rule to the Source IP Address Limit List that is set on the currently managed Virtual Hub. \nThe items set here will be used to decide whether to allow or deny connection from a VPN Client when this client attempts connection to the Virtual Hub. \nYou can specify a client IP address, or IP address or mask to match the rule as the contents of the rule item. By specifying an IP address only, there will only be one specified computer that will match the rule, but by specifying an IP net mask address or subnet mask address, all the computers in the range of that subnet will match the rule. \nYou can specify the priority for the rule. You can specify an integer of 1 or greater for the priority and the smaller the number, the higher the priority. \nTo get a list of the currently registered Source IP Address Limit List, use the AcList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_AcAdd6_Args AcAdd6 [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd6_[allow|deny] Set whether to "allow" or "deny" the connection from a client that matches the rule.
+CMD_AcAdd6_PRIORITY Specify an integer of 1 or higher to indicate the priority of the rule. The smaller the value the higher the priority.
+CMD_AcAdd6_IP Using the format: "IP Address/Mask", specify the range of client IPv6 addresses. Specify the IPv6 address by separating the hexadecimal values using colons such as "2001:200:0:1::". For the mask, either specify hexadecimal values separated by colons such as "ffff:ffff:ffff:ffff::", or you can specify the bit length from the header using a decimal value such as "64". To specify a single IPv6 host, specify the mask as "128" or "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".
+CMD_AcAdd6_Prompt_AD allow or deny:
+CMD_AcAdd6_Prompt_PRIORITY Priority:
+CMD_AcAdd6_Prompt_IP IPv6 Address/Mask:
+CMD_AcAdd6_Eval_PRIORITY Specify 1 or higher for the priority.
+
+
+# AcDel command
+CMD_AcDel Delete Rule from Source IP Address Limit List
+CMD_AcDel_Help Use this to delete a rule from the Source IP Address Limit List that is set on the currently managed Virtual Hub. \nTo get a list of the currently registered IP access control list, use the AcList command. \nThis command cannot be run on VPN Bridge. \nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_AcDel_Args AcDel [id]
+CMD_AcDel_[id] Specify the ID of the rule in the Source IP Address Limit List that you want to delete.
+CMD_AcDel_Prompt_ID ID of Rule to Delete:
+
+
+# LicenseAdd command
+CMD_LicenseAdd Add License Key Registration
+CMD_LicenseAdd_Help Use this to register a new license key on the SoftEther VPN Server. \nTo use SoftEther VPN Server you must acquire a valid license and register the license key. The license keys are 36 alphanumeric characters in length plus hyphens. They are key codes that certify the ownership of a license. \nWhen a license certificate is received together with this software, the license key is printed on this license certificate. If the license for this software was purchased online, the license key is provided by email and on the website window at the time the license is purchased. The license key may also be written down by some other method. If you don't know where the license key is written down, ask the vendor who sold you the license. \n\nTo get the list of currently registered licenses, use the LicenseList command. \nTo display the license status of the current VPN Server, use the LicenseStatus command. \nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_LicenseAdd_Args LicenseAdd [key]
+CMD_LicenseAdd_[key] Specify the license key to register. Specify 36 digits of alphanumeric characters and group the digits in groups of 6 separating them by hyphen.
+CMD_LicenseAdd_Prompt_Key License Key:
+
+
+# LicenseDel command
+CMD_LicenseDel Delete Registered License
+CMD_LicenseDel_Help Use this to delete a specified license from the license list that is currently registered on the SoftEther VPN Server. \n\nTo get the list of currently registered licenses, use the LicenseList command. \nTo display the license status of the current VPN Server, use the LicenseStatus command. \nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_LicenseDel_Args LicenseDel [id]
+CMD_LicenseDel_[id] Specify the license number to delete.
+CMD_LicenseDel_Prompt_ID License Number to Delete:
+
+
+# LicenseList command
+CMD_LicenseList Get List of Registered Licenses
+CMD_LicenseList_Help Use this to display a list of license information currently registered on the SoftEther VPN Server including: license key, license type name, status, expiration date, license ID, license type ID, server ID and serial ID. \n\nTo display the license status of the current VPN Server, use the LicenseStatus command. \nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_LicenseList_Args LicenseList
+
+
+# LicenseStatus command
+CMD_LicenseStatus Get License Status of Current VPN Server
+CMD_LicenseStatus_Help Use this to get and display the license status of the current SoftEther VPN Server. \nThe following current information on the SoftEther VPN Server will be displayed: product edition, server ID, product license expiration date, number of usable Client Connection Licenses and number of Bridge Connection Licenses. \n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_LicenseStatus_Args LicenseStatus
+
+
+# Commands added after SoftEther VPN 4.0
+# IPsecEnable command
+CMD_IPsecEnable Enable or Disable IPsec VPN Server Function
+CMD_IPsecEnable_Help Enable or Disable IPsec VPN Server Function on SoftEther VPN Server.\nIf you enable this function, Virtual Hubs on the VPN Server will be able to accept Remote-Access VPN connections from L2TP-compatible PCs, Mac OS X and Smartphones, and also can accept EtherIP Site-to-Site VPN Connection. VPN Connections from Smartphones suchlike iPhone, iPad and Android, and also from native VPN Clients on Mac OS X and Windows can be accepted.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_IPsecEnable_Args IPsecEnable [/L2TP:yes|no] [/L2TPRAW:yes|no] [/ETHERIP:yes|no] [/PSK:pre-shared-key] [/DEFAULTHUB:default_hub]
+CMD_IPsecEnable_L2TP Enable or Disable the L2TP over IPsec Server Function. To accept VPN connections from iPhone, iPad, Android, Windows or Mac OS X, enable this option.
+CMD_IPsecEnable_L2TPRAW Enable or Disable the L2TP Server Function (Raw L2TP with No Encryptions). To accept special VPN clients, enable this option.
+CMD_IPsecEnable_ETHERIP Enable or Disable the EtherIP / L2TPv3 over IPsec Server Function (for site-to-site VPN Server function). Router Products which are compatible with EtherIP over IPsec can connect to Virtual Hubs on the VPN Server and establish Layer-2 (Ethernet) Bridging.
+CMD_IPsecEnable_PSK Specify the IPsec Pre-Shared Key. An IPsec Pre-Shared Key is also called as "PSK" or "secret". Specify it equal or less than 8 letters, and distribute it to every users who will connect to the VPN Server. Please note: Google Android 4.0 has a bug which a Pre-Shared Key with 10 or more letters causes a unexpected behavior. For that reason, the letters of a Pre-Shared Key should be 9 or less characters.
+CMD_IPsecEnable_DEFAULTHUB Specify the default Virtual HUB in a case of omitting the name of HUB on the Username. Users should specify their username such as "Username@Target Virtual HUB Name" to connect this L2TP Server. If the designation of the Virtual Hub is omitted, the above HUB will be used as the target.
+CMD_IPsecEnable_Prompt_L2TP Enable L2TP over IPsec Server Function (yes / no):
+CMD_IPsecEnable_Prompt_L2TPRAW Enable Raw L2TP Server Function (yes / no):
+CMD_IPsecEnable_Prompt_ETHERIP Enable EtherIP / L2TPv3 over IPsec Server Function (yes / no):
+CMD_IPsecEnable_Prompt_PSK Pre Shared Key for IPsec (Recommended: 9 letters at maximum):
+CMD_IPsecEnable_Prompt_DEFAULTHUB Default Virtual HUB in a case of omitting the HUB on the Username:
+
+
+# IPsecGet command
+CMD_IPsecGet Get the Current IPsec VPN Server Settings
+CMD_IPsecGet_Help Get and view the current IPsec VPN Server settings on the SoftEther VPN Server.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_IPsecGet_Args IPsecGet
+CMD_IPsecGet_PRINT_L2TP L2TP over IPsec Server Function Enabled
+CMD_IPsecGet_PRINT_L2TPRAW Raw L2TP Server Function Enabled
+CMD_IPsecGet_PRINT_ETHERIP EtherIP / L2TPv3 over IPsec Server Function Enabled
+CMD_IPsecGet_PRINT_PSK IPsec Pre-Shared Key String
+CMD_IPsecGet_PRINT_DEFAULTHUB Name of Default Virtual Hub
+
+
+# EtherIpClientAdd command
+CMD_EtherIpClientAdd Add New EtherIP / L2TPv3 over IPsec Client Setting to Accept EthreIP / L2TPv3 Client Devices
+CMD_EtherIpClientAdd_Help Add a new setting entry to enable the EtherIP / L2TPv3 over IPsec Server Function to accept client devices.\nIn order to accept connections from routers by the EtherIP / L2TPv3 over IPsec Server Function, you have to define the relation table between an IPsec Phase 1 string which is presented by client devices of EtherIP / L2TPv3 over IPsec compatible router, and the designation of the destination Virtual Hub.\nAfter you add a definition entry by EtherIpClientAdd command, the defined connection setting to the Virtual Hub will be applied on the login-attepting session from an EtherIP / L2TPv3 over IPsec client device.\nThe username and password in an entry must be registered on the Virtual Hub. An EtherIP / L2TPv3 client will be regarded as it connected the Virtual HUB with the identification of the above user information.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_EtherIpClientAdd_Args EtherIpClientAdd [ID] [/HUB:hubname] [/USERNAME:username] [/PASSWORD:password]
+CMD_EtherIpClientAdd_[ID] Specify an ISAKMP Phase 1 ID. The ID must be exactly same as a ID in the configuration of the EtherIP / L2TPv3 Client. You can specify IP address as well as characters as ID, if the EtherIP Client uses IP address as Phase 1 ID. If you specify '*' (asterisk), it will be a wildcard to match any clients which doesn't match other explicit rules.
+CMD_EtherIpClientAdd_HUB Specify the name of the Virtual Hub to connect.
+CMD_EtherIpClientAdd_USERNAME Specify the username to login to the destination Virtual Hub.
+CMD_EtherIpClientAdd_PASSWORD Specify the password to login to the destination Virtual Hub.
+CMD_EtherIpClientAdd_Prompt_ID ISAKMP Phase 1 ID ('*' is a wildcard):
+CMD_EtherIpClientAdd_Prompt_HUB Virtual Hub Name:
+CMD_EtherIpClientAdd_Prompt_USERNAME Username to Login Virtual Hub:
+CMD_EtherIpClientAdd_Prompt_PASSWORD Password to Login Virtual Hub:
+
+
+# EtherIpClientDelete command
+CMD_EtherIpClientDelete Delete an EtherIP / L2TPv3 over IPsec Client Setting
+CMD_EtherIpClientDelete_Help This command deletes an entry to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. \n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_EtherIpClientDelete_Args EtherIpClientDelete [ID]
+CMD_EtherIpClientDelete_[ID] Specify the ISAKMP Phase 1 ID to delete.
+CMD_EtherIpClientDelete_Prompt_ID ISAKMP Phase 1 ID:
+
+
+# EtherIpClientList command
+CMD_EtherIpClientList Get the Current List of EtherIP / L2TPv3 Client Device Entry Definitions
+CMD_EtherIpClientList_Help This command gets and shows the list of entries to accept VPN clients by EtherIP / L2TPv3 over IPsec Function.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_EtherIpClientList_Args EtherIpClientList
+
+
+# OpenVpnEnable command
+CMD_OpenVpnEnable Enable / Disable OpenVPN Clone Server Function
+CMD_OpenVpnEnable_Help This VPN Server has the clone functions of OpenVPN software products by OpenVPN Technologies, Inc. Any OpenVPN Clients can connect to this VPN Server.\n\nThe manner to specify a username to connect to the Virtual Hub, and the selection rule of default Hub by using this clone server functions are same to the IPsec Server functions. For details, please see the help of the IPsecEnable command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_OpenVpnEnable_Args OpenVpnEnable [yes|no] [/PORTS:udp_port_list]
+CMD_OpenVpnEnable_[yes|no] Specify yes to enable the OpenVPN Clone Server Function. Specify no to disable.
+CMD_OpenVpnEnable_PORTS Specify UDP ports to listen for OpenVPN. Multiple UDP ports can be specified with splitting by space or comma letters, for example: "1194, 2001, 2010, 2012". The default port for OpenVPN is UDP 1194. You can specify any other UDP ports.
+CMD_OpenVpnEnable_Prompt_[yes|no] Enables OpenVPN Clone Server Function (yes / no):
+CMD_OpenVpnEnable_Prompt_PORTS UDP Ports to Listen for OpenVPN (Default: 1194 / Multiple Accepted):
+
+
+# OpenVpnGet command
+CMD_OpenVpnGet Get the Current Settings of OpenVPN Clone Server Function
+CMD_OpenVpnGet_Help Get and show the current settings of OpenVPN Clone Server Function.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_OpenVpnGet_Args OpenVpnGet
+CMD_OpenVpnGet_PRINT_Enabled OpenVPN Clone Server Enabled
+CMD_OpenVpnGet_PRINT_Ports UDP Port List
+
+# OpenVpnMakeConfig command
+CMD_OpenVpnMakeConfig Generate a Sample Setting File for OpenVPN Client
+CMD_OpenVpnMakeConfig_Help Originally, the OpenVPN Client requires a user to write a very difficult configuration file manually. This tool helps you to make a useful configuration sample. What you need to generate the configuration file for the OpenVPN Client is to run this command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_OpenVpnMakeConfig_Args OpenVpnMakeConfig [ZIP_FileName]
+CMD_OpenVpnMakeConfig_[ZIP_FileName] Specify the output setting files to be saved as ZIP compression format. If no file extension is specified, the ".zip" extension will be appended to the filename.
+CMD_OpenVpnMakeConfig_Prompt_ZIP Output Filename of Setting Files (ZIP compressed file):
+CMD_OpenVpnMakeConfig_OK The sample setting file was saved as "%s". You can unzip this file to extract setting files.\n
+CMD_OpenVpnMakeConfig_ERROR The sample setting files were unable to be saved as "%s". The filename might be invalid.\n
+
+
+# SstpEnable command
+CMD_SstpEnable Enable / Disable Microsoft SSTP VPN Clone Server Function
+CMD_SstpEnable_Help This VPN Server has the clone functions of MS-SSTP VPN Server which is on Windows Server 2008 / 2012 by Microsoft Corporation. Standard MS-SSTP Clients in Windows Vista / 7 / 8 / RT can connect to this VPN Server.\n\n[Caution]\nThe value of CN (Common Name) on the SSL certificate of VPN Server must match to the hostname specified on the client, and that certificate must be in the trusted list on the SSTP VPN client. For details refer the Microsoft's documents.\nYou can use the ServerCertRegenerate command to replace the current certificate on the VPN Server to a new self-signed certificate which has the CN (Common Name) value in the fields. In that case, you have to register such a new self-signed certificate on the SSTP VPN Client as a trusted root certificate. If you do not want to do such a bother tasks, please consider to purchase a SSL certificate provided by commercial authority such as VeriSign or GlobalSign.\n\nThe manner to specify a username to connect to the Virtual Hub, and the selection rule of default Hub by using this clone server functions are same to the IPsec Server functions. For details, please see the help of the IPsecEnable command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SstpEnable_Args SstpEnable [yes|no]
+CMD_SstpEnable_[yes|no] Specify yes to enable the Microsoft SSTP VPN Clone Server Function. Specify no to disable.
+CMD_SstpEnable_Prompt_[yes|no] Enables SSTP VPN Clone Server Function (yes / no):
+CMD_SstpEnable_PRINT_Enabled SSTP VPN Clone Server Enabled
+
+
+# SstpGet command
+CMD_SstpGet Get the Current Settings of Microsoft SSTP VPN Clone Server Function
+CMD_SstpGet_Help Get and show the current settings of Microsoft SSTP VPN Clone Server Function.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_SstpGet_Args SstpGet
+
+
+# ServerCertRegenerate command
+CMD_ServerCertRegenerate Generate New Self-Signed Certificate with Specified CN (Common Name) and Register on VPN Server
+CMD_ServerCertRegenerate_Help You can use this command to replace the current certificate on the VPN Server to a new self-signed certificate which has the CN (Common Name) value in the fields.\n\nThis command is convenient if you are planning to use Microsoft SSTP VPN Clone Server Function. Because the value of CN (Common Name) on the SSL certificate of VPN Server must match to the hostname specified on the SSTP VPN client.\nFor details please see the help of SstpEnable command.\n\nThis command will delete the existing SSL certificate of the VPN Server. It is recommended to backup the current SSL certificate and private key by using the ServerKeyGet command beforehand.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_ServerCertRegenerate_Args ServerCertRegenerate [CN]
+CMD_ServerCertRegenerate_[CN] Specify a Common Name (CN) which the new certificate will have.
+CMD_ServerCertRegenerate_Prompt_CN Value of Common Name (CN):
+
+
+# VpnOverIcmpDnsEnable command
+CMD_VpnOverIcmpDnsEnable Enable / Disable the VPN over ICMP / VPN over DNS Server Function
+CMD_VpnOverIcmpDnsEnable_Help You can establish a VPN only with ICMP or DNS packets even if there is a firewall or routers which blocks TCP/IP communications. You have to enable the following functions beforehand.\n\nWarning: Use this function for emergency only. It is helpful when a firewall or router is misconfigured to blocks TCP/IP, but either ICMP or DNS is not blocked. It is not for long-term stable using.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_VpnOverIcmpDnsEnable_Args VpnOverIcmpDnsEnable [/ICMP:yes|no] [/DNS:yes|no]
+CMD_VpnOverIcmpDnsEnable_ICMP Specify yes to enable the VPN over ICMP Server. Specify no to disable.
+CMD_VpnOverIcmpDnsEnable_DNS Specify yes to enable the VPN over DNS Server. Specify no to disable.
+CMD_VpnOverIcmpDnsEnable_Prompt_ICMP Enable VPN over ICMP Server (yes / no):
+CMD_VpnOverIcmpDnsEnable_Prompt_DNS Enable VPN over DNS Server (yes / no):
+
+
+# VpnOverIcmpDnsGet command
+CMD_VpnOverIcmpDnsGet Get Current Setting of the VPN over ICMP / VPN over DNS Function
+CMD_VpnOverIcmpDnsGet_Help Get and show the current VPN over ICMP / VPN over DNS Function status.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_VpnOverIcmpDnsGet_Args VpnOverIcmpDnsGet
+CMD_VpnOverIcmpDnsGet_PRINT_ICMP VPN over ICMP Server Enabled
+CMD_VpnOverIcmpDnsGet_PRINT_DNS VPN over DNS Server Enabled
+
+
+# DynamicDnsGetStatus command
+CMD_DynamicDnsGetStatus Show the Current Status of Dynamic DNS Function
+CMD_DynamicDnsGetStatus_Help Get and show the current status of the Dynamic DNS function.\n\nThe Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name.\nAlso, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address.\r\nTherefore, you need not any longer to keep static global IP addresses with expenses monthly costs.\n[Caution]\nTo disable the Dynamic DNS Function, modify the configuration file of VPN Server.\r\n\r\nThe "declare root" directive has the "declare DDnsClient" directive. In this directive, you can switch "bool Disable" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled.\r\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_DynamicDnsGetStatus_Args DynamicDnsGetStatus
+CMD_DynamicDnsGetStatus_PRINT_FQDN Assigned Dynamic DNS Hostname (Full)
+CMD_DynamicDnsGetStatus_PRINT_HOSTNAME Assigned Dynamic DNS Hostname (Hostname)
+CMD_DynamicDnsGetStatus_PRINT_SUFFIX DNS Suffix
+CMD_DynamicDnsGetStatus_PRINT_IPv4 Global IPv4 Address
+CMD_DynamicDnsGetStatus_PRINT_IPv6 Global IPv6 Address
+
+
+# DynamicDnsSetHostname command
+CMD_DynamicDnsSetHostname Set the Dynamic DNS Hostname
+CMD_DynamicDnsSetHostname_Help You can use this command to change the hostname assigned by the Dynamic DNS function. The currently assigned hostname can be showen by the DynamicDnsGetStatus command.\n\nThe Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name.\nAlso, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address.\r\nTherefore, you need not any longer to keep static global IP addresses with expenses monthly costs.\n[Caution]\nTo disable the Dynamic DNS Function, modify the configuration file of VPN Server.\r\n\r\nThe "declare root" directive has the "declare DDnsClient" directive. In this directive, you can switch "bool Disable" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled.\r\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.
+CMD_DynamicDnsSetHostname_Args DynamicDnsSetHostname [hostname]
+CMD_DynamicDnsSetHostname_[hostname] Specify the new hostname with 3 letters at least and 31 letters at most. Only alphabets and numerics can be used.
+CMD_DynamicDnsSetHostname_Prompt_hostname Dynamic DNS Hostname (3 - 31 letters):
+
+
+# VpnAzureGetStatus command
+CMD_VpnAzureGetStatus Show the current status of VPN Azure function
+CMD_VpnAzureGetStatus_Help Get and show the current status of the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_VpnAzureGetStatus_Args VpnAzureGetStatus
+CMD_VpnAzureGetStatus_PRINT_ENABLED VPN Azure Function is Enabled
+CMD_VpnAzureGetStatus_PRINT_CONNECTED Connection to VPN Azure Cloud Server is Established
+CMD_VpnAzureGetStatus_PRINT_HOSTNAME Hostname of this VPN Server on VPN Azure Service
+
+
+# VpnAzureSetStatus command
+CMD_VpnAzureSetEnable Enable / Disable VPN Azure Function
+CMD_VpnAzureSetEnable_Help Enable or disable the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
+CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no]
+CMD_VpnAzureSetEnable_[yes|no] Specify 'yes' to enable VPN Azure. 'no' to disable it.
+CMD_VpnAzureSetEnable_PROMPT Enable VPN Azure (yes / no):
+
+
+
+
+#######################################################
+# #
+# Management commands for VPN Client are listed below #
+# #
+#######################################################
+
+
+# VersionGet command
+CMD_VersionGet Get Version Information of VPN Client Service
+CMD_VersionGet_Help Use this to get the version information of the currently managed VPN Client Service program.
+CMD_VersionGet_Args VersionGet
+CMD_VersionGet_1 Product Name
+CMD_VersionGet_2 Version Information
+CMD_VersionGet_3 Build Information
+CMD_VersionGet_4 Process ID
+CMD_VersionGet_5 OS Type
+
+
+# PasswordSet command
+CMD_PasswordSet Set the password to connect to the VPN Client service.
+CMD_PasswordSet_Help You can make it mandatory to input a password for occasions when the Command Line Management Utility and the VPN Client Manager connect to a VPN Client service to control it. You can use this command to set the password that must be input. \nYou can also make it mandatory for this password to be input when doing remote operations (from a computer that is not localhost)
+CMD_PasswordSet_Args PasswordSet [password] [/REMOTEONLY:yes|no]
+CMD_PasswordSet_[password] Specify the password you wish to set. You can delete the password setting by specifying "none".
+CMD_PasswordSet_REMOTEONLY Specify "yes" to only require the password to be input when operation is done remotely (from a computer that is not localhost). This stops the password being required when the connection is from localhost. When this parameter is omitted, it will be regarded as "no".
+
+
+# PasswordGet command
+CMD_PasswordGet Get Password Setting to Connect to VPN Client Service
+CMD_PasswordGet_Help Use this to get the setting that determines whether to input a password for occasions when the Command Line Management Utility and the VPN Client Manager connect to a VPN Client service to control it. \nIn the case when a password is requested, it also gets the setting that determines whether this password is only requested when operation is performed remotely (from a computer that is not localhost).
+CMD_PasswordGet_Args PasswordGet
+CMD_PasswordGet_1 Set Password
+CMD_PasswordGet_2 Request Password for Remote Operation Only
+
+
+# CertList command
+CMD_CertList Get List of Trusted CA Certificates
+CMD_CertList_Help Here you can manage the list of certificate authority certificates that are trusted by VPN client. You can use the registered CA certificate list to verify server certificates when connecting to VPN Servers.
+CMD_CertList_Args CertList
+
+
+# CertAdd command
+CMD_CertAdd Add Trusted CA Certificate
+CMD_CertAdd_Help Use this to add a new certificate to a list of CA certificates trusted by the VPN Client. You can use the registered CA certificate list to verify server certificates when connecting to VPN Servers. \nTo get a list of the current certificates you can use the CertList command. \nThe certificate you add must be saved in the X.509 file format.
+CMD_CertAdd_Args CertAdd [path]
+CMD_CertAdd_[path] Specify the file name of the X.509 certificate to register.
+
+
+# CertDelete command
+CMD_CertDelete Delete Trusted CA Certificate
+CMD_CertDelete_Help Use this to delete an existing certificate from a list of CA certificates trusted by the VPN Client. \nTo get a list of the current certificates you can use the CertList command.
+CMD_CertDelete_Args CertDelete [id]
+CMD_CertDelete_[id] Specify the ID of the certificate to delete.
+
+
+# CertGet command
+CMD_CertGet Get Trusted CA Certificate
+CMD_CertGet_Help Use this to get an existing certificate from the list of CA certificates trusted by the VPN Client and save it as a file in X.509 format.
+CMD_CertGet_Args CertGet [id] [/SAVECERT:path]
+CMD_CertGet_[id] Specify the ID of the certificate to get.
+CMD_CertGet_SAVECERT Specify the file name to save the certificate you obtained.
+
+
+# SecureList command
+CMD_SecureList Get List of Usable Smart Card Types
+CMD_SecureList_Help Use this to display a list of smart cards that are supported by VPN Client. \nThe types of smart cards listed in this list have had their drivers installed on the current computer and are supported by VPN software. \r\nIf there is a type of smart card that is currently being used that does not appear in the list, it may be possible to enable use by updating the VPN software to a newer version.
+CMD_SecureList_Args SecureList
+
+
+# SecureSelect command
+CMD_SecureSelect Select the Smart Card Type to Use
+CMD_SecureSelect_Help Use this to select the type of the smart card to be used by the VPN Client. \nTo get the list of usable smart card types, use the SecureList command.
+CMD_SecureSelect_Args SecureSelect [id]
+CMD_SecureSelect_[id] Specify the ID of the smart card type.
+CMD_SecureSelect_PROMPT_ID ID of Smart Card Type to Use
+
+
+# SecureGet command
+CMD_SecureGet Get ID of Smart Card Type to Use
+CMD_SecureGet_Help Use this to get the ID of the smart card type that is set to be used for the current VPN Client. By viewing the results of the SecureList command based on this ID, you can get the type of the currently selected smart card. \nIf there is no smart card that is currently selected, 0 will be displayed for the ID.
+CMD_SecureGet_Args SecureGet
+CMD_SecureGet_Print The currently selected smart card ID is %u.
+CMD_SecureGet_NoPrint Currently, a smart card is not selected.
+
+
+# NicCreate command
+CMD_NicCreate Create New Virtual Network Adapter
+CMD_NicCreate_Help Use this to add a new Virtual Network Adapter to the system. You can give the virtual network adapter a name of your choice. \nYou can set a name that consists of alphanumeric characters for the virtual network adapter. For Windows 2000 or newer systems, this name can be up to 31 characters, but for Windows 98, 98SE and ME it can be up to 4 characters. \nIf the NicCreate command was called, a new virtual network adapter device driver will be installed on the operating system that the VPN Client is operating on. \nIn this case, depending on the operating system, a dialog box may appear to confirm if it is OK to install the device driver.
+CMD_NicCreate_Args NicCreate [name]
+CMD_NicCreate_[name] Specify the name of the virtual network adapter.
+CMD_NicCreate_PROMPT_NAME Virtual Network Adapter Name:
+
+
+# NicDelete command
+CMD_NicDelete Delete Virtual Network Adapter
+CMD_NicDelete_Help Use this to delete an existing virtual network adapter from the system. \nWhen you delete a virtual network adapter from the system, all the connections which are using that virtual network adapter will be disconnected. \nAlso, the Connection Settings that are set to use a virtual network adapter that has been deleted will have their settings automatically changed to use another virtual network adapter. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicDelete_Args NicDelete [name]
+CMD_NicDelete_[name] Specify the name of the virtual network adapter.
+
+
+# NicUpgrade command
+CMD_NicUpgrade Upgrade Virtual Network Adapter Device Driver
+CMD_NicUpgrade_Help If the device driver version of the existing virtual network adapter is old, then this upgrades to the latest device driver that was bundled with the currently operating VPN client. Even if a upgrade is not performed, the device driver will be reinstalled. \nIn this case, depending on the operating system, a dialog box may appear to confirm if it is OK to install the device driver. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicUpgrade_Args NicUpgrade [name]
+CMD_NicUpgrade_[name] Specify the name of the virtual network adapter.
+
+
+# NicGetSetting command
+CMD_NicGetSetting Get Virtual Network Adapter Setting
+CMD_NicGetSetting_Help Use this to get the MAC address setting of the existing virtual network adapter. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicGetSetting_Args NicGetSetting [name]
+CMD_NicGetSetting_[name] Specify the name of the virtual network adapter.
+CMD_NicGetSetting_1 Device Name
+CMD_NicGetSetting_2 Status
+CMD_NicGetSetting_3 MAC Address
+CMD_NicGetSetting_4 Version
+CMD_NicGetSetting_5 Driver File Name
+CMD_NicGetSetting_6 GUID
+
+
+# NicSetSetting command
+CMD_NicSetSetting Change Virtual Network Adapter Setting
+CMD_NicSetSetting_Help Use this to change the MAC address setting of the existing virtual network adapter. When this command is executed, the currently operating virtual network adapter device drivers will be restarted. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicSetSetting_Args NicSetSetting [name] [/MAC:mac]
+CMD_NicSetSetting_[name] Specify the name of the virtual network adapter.
+CMD_NicSetSetting_MAC Specify the MAC address you wish to set. \nSpecify a 6-byte hexadecimal string for the MAC address. \nExample: 00:AC:01:23:45:67 or 00-AC-01-23-45-67
+CMD_NicSetSetting_PROMPT_MAC MAC Address to Set:
+
+
+# NicEnable command
+CMD_NicEnable Enable Virtual Network Adapter
+CMD_NicEnable_Help Use this to enable an existing, disabled virtual network adapter. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicEnable_Args NicEnable [name]
+CMD_NicEnable_[name] Specify the name of the virtual network adapter.
+
+
+# NicDisable command
+CMD_NicDisable Disable Virtual Network Adapter
+CMD_NicDisable_Help Use this to disable an existing, enabled virtual network adapter. \nThis command can be used when VPN Client is operating on Windows 2000 or newer operating systems.
+CMD_NicDisable_Args NicDisable [name]
+CMD_NicDisable_[name] Specify the name of the virtual network adapter.
+
+
+# NicList command
+CMD_NicList Get List of Virtual Network Adapters
+CMD_NicList_Help This allows you to get a list of virtual network adapters registered on the current system.
+CMD_NicList_Args NicList
+
+
+# AccountList command
+CMD_AccountList Get List of VPN Connection Settings
+CMD_AccountList_Help Use this to get a list of VPN Connection Settings registered on the VPN Client.
+CMD_AccountList_Args AccountList
+
+
+# AccountCreate command
+CMD_AccountCreate Create New VPN Connection Setting
+CMD_AccountCreate_Help Use this to create a new VPN Connection Setting on the VPN Client. \nTo create a VPN Connection Setting, in addition to specifying the VPN Connection Setting name and destination server as initial parameters and the destination virtual Hub, and user name, you must also specify the name of the virtual network adapter to use. When a new VPN Connection Setting is created, the type of user authentication is initially set as Anonymous Authentication and the proxy server setting and the verification options of the server certificate is not set. To change these settings and other advanced settings after the VPN Connection Setting has been created, use the other commands that begin with the name "Account".
+CMD_AccountCreate_Args AccountCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username] [/NICNAME:nicname]
+CMD_AccountCreate_[name] Specify the name of the VPN Connection Setting to create.
+CMD_AccountCreate_SERVER Specify the host name and port number of the destination VPN Server using the format [host name:port number]. You can also specify by IP address.
+CMD_AccountCreate_HUB Specify the Virtual Hub on the destination VPN Server.
+CMD_AccountCreate_USERNAME Specify the user name to use for user authentication when connecting to the destination VPN Server.
+CMD_AccountCreate_NICNAME Specify the virtual network adapter to use to connect.
+CMD_AccountCreate_Prompt_Name Name of VPN Connection Setting:
+CMD_AccountCreate_Prompt_Server Destination VPN Server Host Name and Port Number:
+CMD_AccountCreate_Prompt_Hub Destination Virtual Hub Name:
+CMD_AccountCreate_Prompt_Username Connecting User Name:
+CMD_AccountCreate_Prompt_Nicname Used Virtual Network Adapter Name:
+
+
+# AccountSet command
+CMD_AccountSet Set the VPN Connection Setting Connection Destination
+CMD_AccountSet_Help Use this to set, for the VPN Connection Setting registered on the VPN Client, the destination VPN Server host name and port number, Virtual Hub name, user name used for connection and virtual network adapter name to use.
+CMD_AccountSet_Args AccountSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_AccountSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountSet_SERVER Specify the host name and port number of the destination VPN Server using the format "host name:port number". You can also specify by IP address.
+CMD_AccountSet_HUB Specify the Virtual Hub on the destination VPN Server.
+
+
+# AccountGet command
+CMD_AccountGet Get Setting of VPN Connection Setting
+CMD_AccountGet_Help Use this to get the VPN Connection Setting contents of a VPN Connection Setting registered on the VPN Client. \nTo change the VPN Connection Setting contents of the VPN Connection Setting, use the other commands that begin with the name "Account" after creating the VPN Connection Setting.
+CMD_AccountGet_Args AccountGet [name]
+CMD_AccountGet_[name] Specify the name of the VPN Connection Setting whose setting you want to get.
+
+
+# AccountDelete command
+CMD_AccountDelete Delete VPN Connection Setting
+CMD_AccountDelete_Help Use this to delete VPN Connection Setting that is registered on the VPN Client. If the specified VPN Connection Setting has a status of online, the connections will be automatically disconnected and then the VPN Connection Setting will be deleted.
+CMD_AccountDelete_Args AccountDelete [name]
+CMD_AccountDelete_[name] Specify the name of the VPN Connection Setting to delete.
+
+
+# AccountUsernameSet command
+CMD_AccountUsernameSet Set User Name of User to Use Connection of VPN Connection Setting
+CMD_AccountUsernameSet_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to the VPN Server, use this to specify the user name required for user authentication. \nIn some cases it is necessary to specify the type of user authentication and specify the required parameters. To change this information you can use commands such as AccountAnonymousSet, AccountPasswordSet, AccountCertSet and AccountSecureCertSet.
+CMD_AccountUsernameSet_Args AccountUsernameSet [name] [/USERNAME:username]
+CMD_AccountUsernameSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountUsernameSet_USERNAME Specify the user name required for user authentication when the VPN Connection Setting connects to the VPN Server.
+CMD_AccountUsername_Notice The auth type for this VPN Connection Setting is currently set as password authentication. After changing the user name, you must use the AccountPasswordSet command to reset the password.
+
+
+# AccountAnonymousSet command
+CMD_AccountAnonymousSet Set User Authentication Type of VPN Connection Setting to Anonymous Authentication
+CMD_AccountAnonymousSet_Help Use this to set the user auth type to [Anonymous Authentication] for when a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to the VPN Server.
+CMD_AccountAnonymousSet_Args AccountAnonymousSet [name]
+CMD_AccountAnonymousSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountPasswordSet command
+CMD_AccountPasswordSet Set User Authentication Type of VPN Connection Setting to Password Authentication
+CMD_AccountPasswordSet_Help Use this to set the user auth type to Password Authentication for when a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to the VPN Server. Specify Standard Password Authentication and RADIUS or NT Domain Authentication as the password authentication type.
+CMD_AccountPasswordSet_Args AccountPasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_AccountPasswordSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountPasswordSet_PASSWORD Specify the password to use for password authentication. If this is not specified, a prompt will appear to input the password.
+CMD_AccountPasswordSet_TYPE Specify either "standard" (Standard Password Authentication) or "radius" (RADIUS or NT Domain Authentication) as the password authentication type.
+CMD_AccountPasswordSet_Prompt_Type Specify standard or radius:
+CMD_AccountPasswordSet_Type_Invalid The standard or radius specification is invalid.
+
+
+# AccountCertSet command
+CMD_AccountCertSet Set User Authentication Type of VPN Connection Setting to Client Certificate Authentication
+CMD_AccountCertSet_Help Use this to set the user auth type to Client Certificate Authentication for when a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to the VPN Server. For this certificate, you must specify a certificate file in the X.509 format and a private key file that is Base 64 encoded.
+CMD_AccountCertSet_Args AccountCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_AccountCertSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountCertSet_LOADCERT Specify the X.509 format certificate file to provide for certificate authentication.
+CMD_AccountCertSet_LOADKEY Specify the Base-64-encoded private key file name for the certificate.
+
+
+# AccountCertGet command
+CMD_AccountCertGet Get Client Certificate to Use for Cascade Connection
+CMD_AccountCertGet_Help When a VPN Connection Setting registered on VPN Client is specified and that VPN Connection Setting uses client certificate authentication, use this to get the certificate that is provided as the client certificate and save the certificate file in X.509 format.
+CMD_AccountCertGet_Args AccountCertGet [name] [/SAVECERT:cert]
+CMD_AccountCertGet_[name] Specify the name of the VPN Connection Setting whose setting you want to get.
+CMD_AccountCertGet_SAVECERT Specify the file name to save the certificate you obtained in X.509 format.
+
+
+# AccountEncryptEnable command
+CMD_AccountEncryptEnable Enable Encryption when Communicating by VPN Connection Setting
+CMD_AccountEncryptEnable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers to be encrypted by SSL. \nNormally communication between VPN Servers is encrypted by SSL to prevent eavesdropping of information and fraud. You can also disable encryption. When encryption is disabled, the communication throughput improves but the communication data flows over the network in plain text.
+CMD_AccountEncryptEnable_Args AccountEncryptEnable [name]
+CMD_AccountEncryptEnable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountEncryptDisable command
+CMD_AccountEncryptDisable Disable Encryption when Communicating by VPN Connection Setting
+CMD_AccountEncryptDisable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers not to be encrypted. \nNormally communication between VPN Servers is encrypted by SSL to prevent eavesdropping of information and fraud. You can also disable encryption. When encryption is disabled, the communication throughput improves but the communication data flows over the network in plain text.
+CMD_AccountEncryptDisable_Args AccountEncryptDisable [name]
+CMD_AccountEncryptDisable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountCompressEnable command
+CMD_AccountCompressEnable Enable Data Compression when Communicating by VPN Connection Setting
+CMD_AccountCompressEnable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers to be compressed. \nIt is possible to achieve a maximum of 80% compression. Compression however places higher loads on the CPU of both the client and server machines. When the line speed is about 10 Mbps or greater, compression can lower throughput, but sometimes it can have the opposite effect.
+CMD_AccountCompressEnable_Args AccountCompressEnable [name]
+CMD_AccountCompressEnable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountCompressDisable command
+CMD_AccountCompressDisable Disable Data Compression when Communicating by VPN Connection Setting
+CMD_AccountCompressDisable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting is used for communication between VPN Servers via a VPN connection, use this to set the communication contents between the VPN Servers not to be compressed.
+CMD_AccountCompressDisable_Args AccountCompressDisable [name]
+CMD_AccountCompressDisable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountProxyNone command
+CMD_AccountProxyNone Specify Direct TCP/IP Connection as the Connection Method of VPN Connection Setting
+CMD_AccountProxyNone_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to set Direct TCP/IP Connection as the connection method to use, in which case the connection route will not be via a proxy server.
+CMD_AccountProxyNone_Args AccountProxyNone [name]
+CMD_AccountProxyNone_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountProxyHttp command
+CMD_AccountProxyHttp Set Connection Method of VPN Connection Setting to be via an HTTP Proxy Server
+CMD_AccountProxyHttp_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to set Connect via HTTP Proxy Server as the method of connection to use, which requires the specification of the host name and port number of the HTTP Proxy server to communicate via as well as a user name and password (when required). \nThe HTTP proxy server that communication will travel via must be compatible with the CONNECT method to use HTTPS communication.
+CMD_AccountProxyHttp_Args AccountProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxyHttp_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountProxyHttp_SERVER Specify the host name or IP address, and port number of the on-route HTTP proxy server using the format [host name:port number].
+CMD_AccountProxyHttp_USERNAME When user authentication is required to connect to the on-route HTTP proxy server, specify the user name. Also, specify the /PASSWORD parameter at the same time. If the parameters /USERNAME and /PASSWORD are not specified, the user authentication data will not be set.
+CMD_AccountProxyHttp_PASSWORD When user authentication is required to connect to the on-route HTTP proxy server, specify the password. Specify this together with the /USERNAME parameter.
+CMD_AccountProxyHttp_Prompt_Server Proxy Server Host Name and Port Number:
+
+
+
+# AccountProxySocks command
+CMD_AccountProxySocks Set Connection Method of VPN Connection Setting to be via an SOCKS Proxy Server
+CMD_AccountProxySocks_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to set Connect via SOCKS Proxy Server as the method of connection to use, which requires the specification of the host name and port number of the SOCKS Proxy server to communicate via as well as a user name and password (when required). \nThe on-route SOCKS server must be compatible with SOCKS Version 4.
+CMD_AccountProxySocks_Args AccountProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxySocks_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountProxySocks_SERVER Specify the host name or IP address, and port number of the on-route SOCKS proxy server using the format [host name:port number].
+CMD_AccountProxySocks_USERNAME When user authentication is required to connect to the on-route SOCKS proxy server, specify the user name. Also, specify the /PASSWORD parameter at the same time. If the parameters /USERNAME and /PASSWORD are not specified, the user authentication data will not be set.
+CMD_AccountProxySocks_PASSWORD When user authentication is required to connect to the on-route SOCKS proxy server, specify the password. Specify this together with the /USERNAME parameter.
+
+
+# AccountServerCertEnable command
+CMD_AccountServerCertEnable Enable VPN Connection Setting Server Certificate Verification Option
+CMD_AccountServerCertEnable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to enable the option to check whether the SSL certificate provided by the destination VPN Server can be trusted. \nIf this option is enabled, we recommend that you either use the AccountServerCertSet command to save the connection destination server SSL certificate beforehand in the VPN Connection Setting settings beforehand, or use the CertAdd command etc. to register a root certificate containing the signed server SSL certificate in the list of Virtual Hub trusted CA certificates. If it is not registered, a confirmation message sometimes is displayed on the initial connection. \nIf the certificate of the connected VPN Server cannot be trusted under the condition where the option to verify server certificates was enabled for the VPN Connection Setting, the connection will be promptly cancelled and continual reattempts at connection will be made.
+CMD_AccountServerCertEnable_Args AccountServerCertEnable [name]
+CMD_AccountServerCertEnable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountServerCertDisable command
+CMD_AccountServerCertDisable Disable VPN Connection Setting Server Certificate Verification Option
+CMD_AccountServerCertDisable_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to disable the option to check whether the SSL certificate provided by the destination VPN Server can be trusted.
+CMD_AccountServerCertDisable_Args AccountServerCertDisable [name]
+CMD_AccountServerCertDisable_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountServerCertSet command
+CMD_AccountServerCertSet Set Server Individual Certificate for VPN Connection Setting
+CMD_AccountServerCertSet_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to a VPN Server, use this to register the same certificate as the SSL certificate provided by the destination VPN Server. \nIf the option to verify server certificates for VPN Connection Settings is enabled, you must either use this command to save the connection destination server SSL certificate beforehand in the VPN Connection Setting settings beforehand, or use the CAAdd command etc. to register a root certificate containing the signed server SSL certificate in the list of Virtual Hub trusted CA certificates. \nIf the certificate of the connected VPN Server cannot be trusted under the condition where the option to verify server certificates was enabled for the VPN Connection Setting, the connection will be promptly cancelled and continual reattempts at connection will be made.
+CMD_AccountServerCertSet_Args AccountServerCertSet [name] [/LOADCERT:cert]
+CMD_AccountServerCertSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountServerCertSet_LOADCERT Specify X.509 format certificate file name that the server individual certificate you wish to set is saved under.
+
+
+# AccountServerCertDelete command
+CMD_AccountServerCertDelete Delete Server Individual Certificate for VPN Connection Setting
+CMD_AccountServerCertDelete_Help When a VPN Connection Setting registered on the VPN Client is specified and a server individual certificate is registered for that VPN Connection Setting, use this to delete that certificate.
+CMD_AccountServerCertDelete_Args AccountServerCertDelete [name]
+CMD_AccountServerCertDelete_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountServerCertGet command
+CMD_AccountServerCertGet Get Server Individual Certificate for VPN Connection Setting
+CMD_AccountServerCertGet_Help When a VPN Connection Setting is specified and a server Individual certificate is registered for that VPN Connection Setting, use this to get that certificate and save it as an X.509 format certificate file.
+CMD_AccountServerCertGet_Args AccountServerCertGet [name] [/SAVECERT:path]
+CMD_AccountServerCertGet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountServerCertGet_SAVECERT Specify the certificate file name to save the server individual certificate in X.509 format.
+
+
+# AccountDetailSet command
+CMD_AccountDetailSet Set Advanced Settings for VPN Connection Setting
+CMD_AccountDetailSet_Help Use this to customize the VPN protocol communication settings used when a VPN Connection Setting registered on a VPN Client is specified and that VPN Connection Setting connects to the VPN Server.
+CMD_AccountDetailSet_Args AccountDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:additional_interval] [/TTL:disconnect_span] [/HALF:yes|no] [/BRIDGE:yes|no] [/MONITOR:yes|no] [/NOTRACK:yes|no] [/NOQOS:yes|no]
+CMD_AccountDetailSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountDetailSet_MAXTCP Specify, using an integer in the range 1 to 32, the number of TCP connections to be used for VPN communication. By using data transmission by multiple TCP connections for VPN communication sessions with VPN Servers it is sometimes possible to increase communication speed. \nNote: We recommend about 8 lines when the connection lines to the server are fast, and 1 line when using a slow connection such as dialup.
+CMD_AccountDetailSet_INTERVAL When communicating by VPN by establishing multiple TCP connections, specify in seconds, the establishing interval for each TCP connection. The standard value is 1 second.
+CMD_AccountDetailSet_TTL When specifying connection life of each TCP connection specify in seconds the keep-alive time from establishing a TCP connection until disconnection. If 0 is specified, keep-alive will not be set.
+CMD_AccountDetailSet_HALF Specify "yes" when enabling half duplex mode. When using two or more TCP connections for VPN communication, it is possible to use Half Duplex Mode. By enabling half duplex mode it is possible to automatically fix data transmission direction as half and half for each TCP connection. In the case where a VPN using 8 TCP connections is established, for example, when half-duplex is enabled, communication can be fixes so that 4 TCP connections are dedicated to the upload direction and the other 4 connections are dedicated to the download direction.
+CMD_AccountDetailSet_BRIDGE Specify "yes" when connecting to the VPN Server using Bridge / Router Mode. When using Bridge / Router Mode to connect, it is possible to provide bridging or routing to another network on the side of the virtual network adapter of the VPN Client. However, if the security policy of the user who is being used for connection denies the use of bridges or routing, then connection will fail.
+CMD_AccountDetailSet_MONITOR Specify "yes" when connecting to the VPN Server using Monitoring Mode. When a connection is made using Monitoring Mode, you can receive all packets that flow through the Virtual Hub. However, if the security policy of the user who is being used for connection does not allow Monitoring Mode, then connection will fail.
+CMD_AccountDetailSet_NOTRACK Specify "yes" will disable the adjustments of routing table. Normally "no" is specified.
+CMD_AccountDetailSet_NOQOS Specify "yes" when disabling VoIP / QoS functions. Normally "no" is specified.
+CMD_AccountDetailSet_Eval_MaxTcp Specify an integer in the range 1 to 32 for the number of TCP connections.
+CMD_AccountDetailSet_Eval_Interval Set at least 1 second for the interval to establish a TCP connection.
+CMD_AccountDetailSet_Prompt_MaxTcp Number of TCP Connections to Use in VPN Communication:
+CMD_AccountDetailSet_Prompt_Interval Interval between Establishing Each TCP Connection:
+CMD_AccountDetailSet_Prompt_TTL Connection Life of Each TCP Connection (0 for no keep-alive):
+CMD_AccountDetailSet_Prompt_HALF Enable Half-Duplex Mode (yes/no):
+CMD_AccountDetailSet_Prompt_BRIDGE Enable Bridge / Router Mode (yes/no):
+CMD_AccountDetailSet_Prompt_MONITOR Enable Monitoring Mode (yes/no):
+CMD_AccountDetailSet_Prompt_NOTRACK Disable Adjustment of Routing Table (yes/no):
+CMD_AccountDetailSet_Prompt_NOQOS Disable QoS Control Function (yes/no):
+
+
+# AccountRename command
+CMD_AccountRename Change VPN Connection Setting Name
+CMD_AccountRename_Help Use this to specify a VPN Connection Setting registered on the VPN Client and change its name.
+CMD_AccountRename_Args AccountRename [name] [/NEW:new_name]
+CMD_AccountRename_[name] Specify the current name of the VPN Connection Setting whose name you want to change.
+CMD_AccountRename_NEW Specify the new name after the change.
+CMD_AccountRename_PROMPT_OLD Current Name:
+CMD_AccountRename_PROMPT_NEW New Name:
+
+
+# AccountConnect command
+CMD_AccountConnect Start Connection to VPN Server using VPN Connection Setting
+CMD_AccountConnect_Help Use this to specify a VPN Connection Setting registered on the VPN Client and start a connection to the VPN Server using that VPN Connection Setting. A VPN Connection Setting that has a connecting status or a connected status will continue to be connected to the VPN Server, or continue to attempt to connect to the VPN Server until the AccountDisconnect command is used to disconnect the connection (Note however, if the AccountRetrySet command is used to specify the number of retries, connection attempts will be aborted when the specified value is reached.)
+CMD_AccountConnect_Args AccountConnect [name]
+CMD_AccountConnect_[name] Specify the name of the VPN Connection Setting whose connection you want to start.
+
+
+# AccountDisconnect command
+CMD_AccountDisconnect Disconnect VPN Connection Setting During Connection
+CMD_AccountDisconnect_Help Use this to specify a VPN Connection Setting that is registered on the VPN Client and that is either in the condition of connecting or is connected, and immediately disconnect it.
+CMD_AccountDisconnect_Args AccountDisconnect [name]
+CMD_AccountDisconnect_[name] Specify the name of the VPN Connection Setting to disconnect.
+
+
+# AccountStatusGet command
+CMD_AccountStatusGet Get Current VPN Connection Setting Status
+CMD_AccountStatusGet_Help When a VPN Connection Setting that is registered on the VPN Client is specified and that VPN Connection Setting is currently connected, use this to get its connection status and other information.
+CMD_AccountStatusGet_Args AccountStatusGet [name]
+CMD_AccountStatusGet_[name] Specify the name of the VPN Connection Setting whose information you want to get.
+
+
+# AccountNicSet command
+CMD_AccountNicSet Set Virtual Network Adapter for VPN Connection Setting to Use
+CMD_AccountNicSet_Help Use this to change the Virtual Network Adapter name that the existing VPN Connection Settings registered on the VPN Client will use for the connection to a VPN Server.
+CMD_AccountNicSet_Args AccountNicSet [name] [/NICNAME:nicname]
+CMD_AccountNicSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountNicSet_NICNAME Specify the Virtual Network Adapter name to use when connecting to the VPN Server.
+
+
+# AccountStatusShow command
+CMD_AccountStatusShow Set Connection Status and Error Screen to Display when Connecting to VPN Server
+CMD_AccountStatusShow_Help When a communication setting is registered on the VPN Client and that communication setting is being used to connect to the VPN Server, use this to set the connection status and error screen to be displayed on the computer display.
+CMD_AccountStatusShow_Args AccountStatusShow [name]
+CMD_AccountStatusShow_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountStatusHide command
+CMD_AccountStatusHide Set Connection Status and Error Screen to be Hidden when Connecting to VPN Server
+CMD_AccountStatusHide_Help When a communication setting is registered on the VPN Client and that communication setting is being used to connect to the VPN Server, use this to set the connection status and error screen to not be displayed on the computer display.
+CMD_AccountStatusHide_Args AccountStatusHide [name]
+CMD_AccountStatusHide_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountSecureCertSet command
+CMD_AccountSecureCertSet Set User Authentication Type of VPN Connection Setting to Smart Card Authentication
+CMD_AccountSecureCertSet_Help Use this to set the user auth type to Smart Card Authentication for when a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting connects to the VPN Server. Also, you must specify the names of the certificate object and the private key object stored on the smart card.
+CMD_AccountSecureCertSet_Args AccountSecureCertSet [name] [/CERTNAME:cert] [/KEYNAME:key]
+CMD_AccountSecureCertSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountSecureCertSet_CERTNAME Specify the name of the certificate object stored on the smart card.
+CMD_AccountSecureCertSet_KEYNAME Specify the name of the private key object stored on the smart card. The private key must be compatible with the certificate specified by /CERTNAME.
+CMD_AccountSecureCertSet_PROMPT_CERTNAME Name of Certificate Object on Smart Card:
+CMD_AccountSecureCertSet_PROMPT_KEYNAME Name of Private Key Object on Smart Card:
+
+
+# AccountRetrySet コマンド
+CMD_AccountRetrySet Set Interval between Connection Retries for Connection Failures or Disconnections of VPN Connection Setting
+CMD_AccountRetrySet_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting attempts to connect to a VPN Server, use this to specify the interval to wait between connection attempts and the limit of how many times to retry connecting when communication with the VPN Server was disconnected or when the connection process failed. \nIf the user authentication type is Smart Card Authentication, no connection retry will be performed regardless of the Number of Connection Attempts setting.
+CMD_AccountRetrySet_Args AccountRetrySet [name] [/NUM:num_retry] [/INTERVAL:retry_interval]
+CMD_AccountRetrySet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+CMD_AccountRetrySet_NUM Specify the number of times to make consecutive retries. By specifying "999", there will be limitless attempts to reconection (always connect). By specifying "0", not attempt at reconnection will be made.
+CMD_AccountRetrySet_INTERVAL When attempting a reconnection, this sets how many seconds to wait after the previous disconnection or connection failure before starting the reconnection process.
+CMD_AccountRetrySet_PROMPT_NUM Reconection Count ("999" is unlimited):
+CMD_AccountRetrySet_PROMPY_INTERVAL Reconection Interval (Seconds):
+CMD_AccountRetrySet_EVAL_INTERVAL Specify 5 seconds or more for the retries interval.
+
+
+# AccountStartupSet command
+CMD_AccountStartupSet Set VPN Connection Setting as Startup Connection
+CMD_AccountStartupSet_Help Use this to specify a VPN Connection Setting registered on the VPN Client and set it as the startup connection. The VPN Connection Setting that is set as the startup connection will automatically start the connection process when the VPN Client service starts.
+CMD_AccountStartupSet_Args AccountStartupSet [name]
+CMD_AccountStartupSet_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountStartupRemove command
+CMD_AccountStartupRemove Remove Startup Connection of VPN Connection Setting
+CMD_AccountStartupRemove_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting is currently set as a startup connection, use this to delete the startup connection.
+CMD_AccountStartupRemove_Args AccountStartupRemove [name]
+CMD_AccountStartupRemove_[name] Specify the name of the VPN Connection Setting whose setting you want to change.
+
+
+# AccountExport command
+CMD_AccountExport Export VPN Connection Setting
+CMD_AccountExport_Help Use this to specify a VPN Connection Setting registered on the VPN Client and export its contents as a text file. By exporting a VPN Connection Setting file, and then later, importing it, you can duplicate the contents of a VPN Connection Setting. Also, because it gets saved as a text file, you can edit the contents using a conventional text editor. \nThe export destination file is saved as a UTF-8 format text file. Also, it is convenient to save the file name with the file extension .vpn as this file extension is associated to the Windows Edition VPN Client Manager.
+CMD_AccountExport_Args AccountExport [name] [/SAVEPATH:savepath]
+CMD_AccountExport_[name] Specify the name of the VPN Connection Setting to export.
+CMD_AccountExport_SAVEPATH Specify a file name for the save destination.
+CMD_AccountExport_PROMPT_SAVEPATH Save Destination File Name (recommended extension: vpn):
+
+
+# AccountImport command
+CMD_AccountImport Import VPN Connection Setting
+CMD_AccountImport_Help Use this to import the VPN Connection Setting file that was exported by the AccountExport command and add it to the VPN Client.
+CMD_AccountImport_Args AccountImport [path]
+CMD_AccountImport_[path] Specify the file name of the import source.
+CMD_AccountImport_PROMPT_PATH Import Source File Name:
+CMD_AccountImport_FAILED_PARSE Unable to correctly parse the specified file. Check if the file was exported correctly.
+CMD_AccountImport_OK The VPN Connection Setting "%s" was imported.
+
+
+
+# RemoteEnable command
+CMD_RemoteEnable Allow Remote Management of VPN Client Service
+CMD_RemoteEnable_Help Use this to allow management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager.
+CMD_RemoteEnable_Args RemoteEnable
+
+
+# RemoteDisable command
+CMD_RemoteDisable Deny Remote Management of VPN Client Service
+CMD_RemoteDisable_Help Use this to deny management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager.
+CMD_RemoteDisable_Args RemoteDisable
+
+
+
+
+
+
+###################################################
+# #
+# Commands for VPN Tools are listed below #
+# #
+###################################################
+
+
+# MakeCert command
+CMD_MakeCert Create New X.509 Certificate and Private Key
+CMD_MakeCert_Help Use this to create a new X.509 certificate and private key and save it as a file. \nThe algorithm used to create the public key and private key of the certificate is RSA 1024 bit. \nYou can choose to create a root certificate (self-signed certificate) or a certificate signed by another certificate. To create a certificate that is signed by another certificate, you require a private key file (base 64 encoded) that is compatible with the certificate that uses the signature (X.509 format file). \n\nWhen creating a certificate, you can specify the following: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number, and Expiration Date. \nThe created certificate will be saved as an X.509 format file and the private key file will be saved in a Base 64 encoded RSA 1024 bit format file. \n\nThe MakeCert command is a tool that provides the most rudimentary function for creating certificates. If you want to create a more substantial certificate, we recommend that you use either free software such as OpenSSL, or commercial CA (certificate authority) software. \n\nNote: This command can be called from the SoftEther VPN Command Line Management Utility. You can also execute this command while connected to the current VPN Server or VPN Client in Administration Mode but, what actually performs the RSA computation, generates the certificate data and saves it to file is the computer on which the command is running, and all this is executed in a context that has absolutely no relationship to the computer that is the destination of the Administration Mode connection.
+CMD_MakeCert_Args MakeCert [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l] [/SERIAL:serial] [/EXPIRES:expires] [/SIGNCERT:signcert] [/SIGNKEY:signkey] [/SAVECERT:savecert] [/SAVEKEY:savekey]
+CMD_MakeCert_CN Specify the Name (CN) item of the certificate to create. You can specify "none".
+CMD_MakeCert_O Specify the Organization (O) item of the certificate to create. You can specify "none".
+CMD_MakeCert_OU Specify the Organization Unit (OU) item of the certificate to create. You can specify "none".
+CMD_MakeCert_C Specify the Country (C) item of the certificate to create. You can specify "none".
+CMD_MakeCert_ST Specify the State (ST) item of the certificate to create. You can specify "none".
+CMD_MakeCert_L Specify the Locale (L) item of the certificate to create. You can specify "none".
+CMD_MakeCert_SERIAL Specify the Serial Number item of the certificate to create. Specify using hexadecimal values. You can specify "none".
+CMD_MakeCert_EXPIRES Specify the Expiration Date item of the certificate to create. If you specify "none" or "0", 3650 days (approx. 10 years) will be used. You can specify a maximum of 10950 days (about 30 years).
+CMD_MakeCert_SIGNCERT For cases when the certificate to be created is signed by an existing certificate, specify the X.509 format certificate file name to be used to sign the signature. When this parameter is omitted, such signature signing is not performed and the new certificate is created as a root certificate.
+CMD_MakeCert_SIGNKEY Specify a private key (RSA, base-64 encoded) that is compatible with the certificate specified by /SIGNCERT.
+CMD_MakeCert_SAVECERT Specify the file name to save the certificate you created. The certificate is saved as an X.509 file that includes a public key that is RSA format 1024 bit.
+CMD_MakeCert_SAVEKEY Specify the file name to save private key that is compatible with the certificate you created. The private key will be saved as an RSA-format 1024-bit private key file.
+CMD_MakeCert_PROMPT_CN Name of Certificate to Create (CN):
+CMD_MakeCert_PROMPT_O Organization of Certificate to Create (O):
+CMD_MakeCert_PROMPT_OU Organization Unit of Certificate to Create (OU):
+CMD_MakeCert_PROMPT_C Country of Certificate to Create (C):
+CMD_MakeCert_PROMPT_ST State of Certificate to Create (ST):
+CMD_MakeCert_PROMPT_L Locale of Certificate to Create (L):
+CMD_MakeCert_PROMPT_SERIAL Serial Number of Certificate to Create (Hexadecimal):
+CMD_MakeCert_PROMPT_EXPIRES Expiration Date of Certificate to Create (Days):
+CMD_MakeCert_PROMPT_SAVECERT File Name to Save Certificate to Create:
+CMD_MakeCert_PROMPT_SAVEKEY File Name to Save Private Key to Create:
+CMD_MakeCert_EVAL_EXPIRES Specify the Expiration Date within the range %u to %u.
+CMD_MakeCert_ERROR_SIGNKEY Either it was not possible to read the certificate or private key specified by /SIGNCERT and /SIGNKEY, or they were an invalid combination.
+CMD_MakeCert_ERROR_GEN_FAILED Creation of certificate and private key failed.
+
+
+# TrafficClient command
+CMD_TrafficClient Run Network Traffic Speed Test Tool in Client Mode
+CMD_TrafficClient_Help Use this to execute the communication throughput measurement tool's client program. \nTwo commands, TrafficClient and TrafficServer, are used for the communication throughput measurement tool to enable the measurement of communication throughput that can be transferred between two computers connected by IP network. The TrafficServer command is used first on another computer which puts the communication throughput measurement tool server in a listening condition. Then the TrafficClient command is used to connect to that server by specifying its host name or IP address and port number, which makes it possible to measure the communication speed. \nMeasurement of the communication speed is carried out by concurrently establishing multiple TCP connections and calculating the actual number of bits of data that can be transferred within a specified time based on the respective results of transferring the maximum stream data on each connection and then using that to calculate the average value (bps) of communication throughput. Normally when there is one TCP connection, it is common to only be able to achieve communication speeds slower than the actual net throughput because of limitations related to the TCP algorithm. We therefore recommend the establishment of multiple concurrent TCP connections when measuring communication results. Because the throughput that is measured using this measurement method is calculated from the bit length of the data that arrives on the receiver side as a stream by TCP, the packet loss that occurs during transfer and the packets with corrupted data are not included in the packets that actually arrive, which means it is possible to calculate a genuine value that is close to the maximum possible communication bandwidth of the network. \nUsing the measurement results, i.e. the stream size transferred by TCP, the approximate value of data volume that actually passed through the network is calculated and this is divided by time to calculate the bits per sec (bps). The calculation assumes the type of the physical network is Ethernet (IEEE802.3) and the MAC frame payload size is 1,500 bytes (TCP MSS is 1,460 bytes). By specifying the /RAW option, the calculation will not make corrections for the TCP/IP header and MAC header data volume. \n\nNote: This command can be called from the SoftEther VPN Command Line Management Utility. You can also execute this command while connected to the current VPN Server or VPN Client in Administration Mode but, what actually conducts communication and measures the throughput is the computer on which the command is running, and all this is executed in a context that has absolutely no relationship to the computer that is the destination of the Administration Mode connection.
+CMD_TrafficClient_Args TrafficClient [host:port] [/NUMTCP:numtcp] [/TYPE:download|upload|full] [/SPAN:span] [/DOUBLE:yes|no] [/RAW:yes|no]
+CMD_TrafficClient_[host:port] Specify the host name or IP address and port number that the communication throughput measurement tool server (TrafficServer) is listening for. If the port number is omitted, 9821 will be used.
+CMD_TrafficClient_NUMTCP Specify the number of TCP connections to be concurrently established between the client and the server for data transfer. If omitted, 32 will be used.
+CMD_TrafficClient_TYPE Specify the direction of data flow when throughput measurement is performed. Specify one of the following options: "download", "upload" or "full". By specifying "download" the data will be transmitted from the server side to the client side. By specifying "upload" the data will be transmitted from the client side to the server side. By specifying "full", the data will be transferred in both directions. When "full" is specified, the NUMTCP value must be an even number of two or more (half the number will be used for concurrent TCP connections in the download direction and the other half will be used in the upload direction). If this parameter is omitted, "full" will be used.
+CMD_TrafficClient_SPAN Specify, using seconds, the time span to conduct data transfer for the measurement of throughput. If this parameter is omitted, "15" will be used.
+CMD_TrafficClient_DOUBLE When "yes" is specified, the throughput of the measured result will be doubled and then displayed. This option is used for cases when a network device etc. is somewhere on the data route and the total throughput capability that is input and output by this network device is being measured.
+CMD_TrafficClient_RAW By specifying "yes", the calculation will not make corrections for the TCP/IP header and MAC header data volume.
+CMD_TrafficClient_EVAL_NUMTCP Specify a value of 32 or less for the number of TCP connections.
+CMD_TrafficClient_PROMPT_HOST Measurement Server Name and Port Number (9821 if omitted):
+CMD_TrafficClient_ERROR_NUMTCP When the data direction is "full" (both directions), you must specify an even value for the number of TCP connections (/NUMTCP).
+CMD_TrafficClient_ERROR_HOSTPORT The host name or port number is incorrectly specified.
+
+
+# TrafficServer command
+CMD_TrafficServer Run Network Traffic Speed Test Tool in Server Mode
+CMD_TrafficServer_Help Use this to execute the communication throughput measurement tool's server program. \nTwo commands, TrafficClient and TrafficServer, are used for the communication throughput measurement tool to enable the measurement of communication throughput that can be transferred between two computers connected by IP network. \nTo set the TCP port of this computer to the Listen status to listen for the connection from the TrafficClient of another computer, specify the port number and start the server program using the TrafficServer command. \nYou can display more detailed information on the communication throughput measurement tool by inputting "TrafficClient /?". \n\nNote: This command can be called from the SoftEther VPN Command Line Management Utility. You can also execute this command while connected to the current VPN Server or VPN Client in Administration Mode but, what actually conducts communication and measures the throughput is the computer on which the command is running, and all this is executed in a context that has absolutely no relationship to the computer that is the destination of the Administration Mode connection.
+CMD_TrafficServer_Args TrafficServer [port]
+CMD_TrafficServer_[port] Specify, using an integer, the port number at which to listen for the connection. If the specified port is already being used by another program, or if the port cannot be opened, an error will occur.
+
+
+# Internal message strings concerning TrafficClient / TrafficServer
+TT_LISTEN_FAILED Unable to set TCP port %u to Listen status. The port may be being used by another application or this application did not have the authority to open the port.
+TTS_LISTEN_STOP The port for listening was closed.
+TTS_ENTER_TO_EXIT \n----------------------------------------\nThe Network Traffic Speed Test Tool in Server Mode started. \n\nPress the Enter key to stop the server program. \n----------------------------------------\n\n
+TTS_INIT Starting the server program...
+TTS_LISTEN_STARTED The server program was started. Now the IPv4 TCP port %u is set to Listen status and listening for connection from the client.
+TTS_LISTEN_STARTED_V6 The IPv6 TCP Port %u is listening to accept clients.
+TTS_LISTEN_FAILED_V6 Failed to open the IPv6 TCP Port %u. Another application might be using the same IPv6 TCP Port, or the IPv6 stack is not installed on the operating system.
+TTS_STOP_INIT Stopping the server program...
+TTS_STOP_FINISHED The stopping of the server program is complete.
+TTS_ACCEPTED Connection %u: Connected from Client %S Port %u.
+TTS_DISCONNECTED Connection %u (%S) was disconnected.
+TTS_DISCONNECT Connection %u (%S) was disconnected.
+TTC_INIT Starting the client program...
+TTC_FREE The client program was terminated.
+TTC_CONNECT_START The connection to server %S (port %u) will start. %u TCP connections will be connected.
+TTC_CONNECT_FAILED The connection of TCP connection number %u failed.
+TTC_CONNECT_NOT_SERVER Because a program other than TrafficServer is operating on the destination TCP port, traffic cannot be measured.
+TTC_CONNECT_OK TCP connection number %u was connected.
+TTC_CONNECT_OK_2 \ Data transfer direction: %s
+TTC_ERROR_ABORTED The TCP connection initialization with the server failed. Measurement will stop.
+TTC_SUMMARY_BAR -------------------------------------------------------
+TTC_SUMMARY_TITLE Network Traffic Speed Test Tool Client Setting Parameters
+TTC_SUMMARY_HOST Destination Host Name
+TTC_SUMMARY_PORT Destination TCP Port Number
+TTC_SUMMARY_NUMTCP Number of TCP Connections to Establish
+TTC_SUMMARY_TYPE Data Transfer Direction
+TTC_SUMMARY_SPAN Data Transmission Time
+TTC_SUMMARY_ETHER Data Correction for Ethernet Frames
+TTC_SUMMARY_DOUBLE Measurement of Total Speed of Relay Device Input Output
+TTC_TYPE_DOWNLOAD Download (Server to Client)
+TTC_TYPE_UPLOAD Upload (Client to Server)
+TTC_TYPE_FULL Full (Server < -- > Client)
+TTC_SPAN_STR %.1f seconds
+TTC_COMM_START \nAll connections were established and so data transfer started. \nMeasurement Start Time: %s\nScheduled Finish Time: %s\n\nMeasuring in progress. Please wait... \n(Do not use any other applications while measuring is in progress.)\n\n
+TTC_COMM_END Because %.1f seconds or more have passed, the data communication will end. \n\n
+TTC_COMM_USER_CANCEL Because of cancellation by user, the data communication will end. \n\n
+TTC_COMM_DISCONNECTED The TCP connection %u was disconnected.
+TTC_STOPPING Stopping the operation of the communication throughput measurement tool client...
+TTC_ENTER_TO_EXIT \n----------------------------------------\nThe Network Traffic Speed Test Tool in Client Mode started. \n\nPress the Enter key to stop the client program. \n----------------------------------------\n\n
+TTC_RES_TITLE \n\nNetwork Traffic Speed Test Tool\n\n
+TTC_RES_COLUMN_1 Item Name
+TTC_RES_COLUMN_2 Normal View
+TTC_RES_COLUMN_3 Simplified View
+TTC_RES_SPAN Time Span for Measurement
+TTC_RES_ETHER Data Correction for Ethernet Frames
+TTC_RES_BYTES_DOWNLOAD Communication Data Volume in Download Direction
+TTC_RES_BYTES_UPLOAD Communication Data Volume in Upload Direction
+TTC_RES_BYTES_TOTAL Total Communication Data Volume
+TTC_RES_DOUBLE Relay Device Input Output Total Throughput Computation
+TTC_RES_BPS_DOWNLOAD Average Throughput in Download Direction
+TTC_RES_BPS_UPLOAD Average Throughput in Upload Direction
+TTC_RES_BPS_TOTAL Total Average Throughput
+
+
+# Check command
+CMD_Check Check whether SoftEther VPN Operation is Possible
+CMD_Check_Help Use this to check if the current computer that is running vpncmd is a suitable operation platform for SoftEther VPN Server / Bridge. \nIf this check passes on a system, it is highly likely that SoftEther VPN software will operate correctly on that system. \nAlso, if this check does not pass on a system, then this indicates that some type of trouble may arise if SoftEther VPN software is used on that system.
+CMD_Check_Args Check
+
+
+# Concerning System Checker
+# (This contains some strange character strings which are used to check character code conversion.)
+CHECK_TITLE ---------------------------------------------------\nSoftEther VPN Operation Environment Check Tool\n\nCopyright (c) SoftEther VPN Project.\nAll Rights Reserved.\n\n
+CHECK_NOTE If this operation environment check tool is run on a system and that system passes, it is highly likely that SoftEther VPN software can operate on that system. This check may take a while. Please wait...\n\n
+CHECK_EXEC_TAG Checking '%s'... \n
+CHECK_PASS Pass
+CHECK_FAIL Fail
+CHECK_RESULT_1 All checks passed. It is highly likely that SoftEther VPN Server / Bridge can operate normally on this system.
+CHECK_RESULT_2 Some checks failed. Please check the operation environment of this system. If SoftEther VPN Server / Bridge were to be executed on this system, troubles may occur.
+CHECK_TEST_123456789 123456789
+
+
+CHECK_PROC_KERNEL Kernel System
+CHECK_PROC_MEMORY Memory Operation System
+CHECK_PROC_STRINGS ANSI / Unicode string processing system
+CHECK_PROC_FILESYSTEM File system
+CHECK_PROC_THREAD Thread processing system
+CHECK_PROC_NETWORK Network system
+
+
+
+
+
+
+
+
+######################################################
+# #
+# Setup Wizard (SW) Strings #
+# #
+######################################################
+
+SW_TITLE SoftEther VPN Setup Wizard (Version %S)
+SW_EXIT_CONFIRM The setup process of SoftEther VPN hasn't been finished yet.\r\n\r\nDo you want to exit the setup?
+SW_UNINSTALL_CONFIRM Starting the uninstall process of %s.\r\n\r\nDo you want to continue?
+
+
+SW_COMPONENT_VPNSERVER_TITLE SoftEther VPN Server
+SW_COMPONENT_VPNSERVER_DESCRIPTION Install it on a server computer at the central site of VPN. The management tools will be also installed.
+
+SW_COMPONENT_VPNCLIENT_TITLE SoftEther VPN Client
+SW_COMPONENT_VPNCLIENT_DESCRIPTION Install it on VPN client comuters. A VPN client computer will be able to connect to the central VPN Server. The management tools will be also installed.
+
+SW_COMPONENT_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SW_COMPONENT_VPNBRIDGE_DESCRIPTION Install it on computers at each site. Each VPN Bridge will establish a VPN connection to the central VPN Server. The management tools will be also installed.
+
+SW_COMPONENT_VPNSMGR_TITLE SoftEther VPN Server Manager (Admin Tools Only)
+SW_COMPONENT_VPNSMGR_DESCRIPTION Only the VPN Server Manager will be installed. The VPN Server service program will not be installed. You can use the VPN Server Manager to connect and manage remote VPN Servers and VPN Bridges on other computers which run on Windows, Linux, Mac OS X, Solaris and FreeBSD.
+
+SW_COMPONENT_VPNCMGR_TITLE SoftEther VPN Client Manager (Admin Tools Only)
+SW_COMPONENT_VPNCMGR_DESCRIPTION Only the VPN Client Manager will be installed. The VPN Client service program will not be installed. You can use the VPN Client Manager to connect and manage remote VPN Clients on other computers which run on Windows and Linux.
+
+SW_WELCOME_TITLE Welcome to the SoftEther VPN Setup Wizard
+SW_MODE_TITLE Select a Setup Mode
+SW_NOT_ADMIN_TITLE Not Enough Privileges
+SW_COMPONENTS_TITLE Select Software Components to Install
+SW_EULA_TITLE End User License Agreement
+SW_WARNING_TITLE Important Notices
+SW_DIR_TITLE Directory to Install on
+SW_READY_TITLE Ready to Install
+SW_PERFORM_TITLE Setup is in Progress
+SW_ERROR_TITLE Results of Setup
+SW_FINISH_TITLE Setup Finished
+SW_UNINST1_TITLE Uninstaller
+SW_LANG1_TITLE SoftEther VPN: Configure the Display Language
+SW_EASY1_TITLE Welcome to SoftEther VPN Client Easy Installer Creator
+SW_EASY2_TITLE Specify Files
+SW_WEB1_TITLE Welcome to SoftEther VPN Client Web Installer Creator
+SW_WEB2_TITLE Specify Files
+
+SW_UNINSTALLINFO_URL http://selinks.org/
+SW_UNINSTALLINFO_PUBLISHER SoftEther VPN Project
+
+
+SW_COMPONENTS_ABOUT_TAG About %s
+SW_COMPONENTS_REQUIRE_ADMIN Installation Requires Administrators Privileges
+SW_COMPONENTS_REQUIRE_ADMIN_TEXT You have to restart the setup wizard by a user who has Administrators privileges to install %s in the System Mode. To install in the System Mode, click Back.
+SW_DIR_SELECT Please Specify the Directory to Install
+SW_DIR_MORE_THAN_110 The directory name is too long.\r\nSpecify 110 letters at most.
+SW_DIR_WRITE_ERROR Unable to create the specified directory "%s" or failed to write a file on the directory.\r\n\r\nSpecify another directory.
+SW_DIR_DST_IS_SAME_TO_SRC The specified directory "%s" is same as the source directory.
+SW_DIR_IS_NOT_HDD The specified directory "%s" is not a local hard disk drive.\r\n\r\nTo install %s in the System Mode, you have to specify a directory on a local hard disk drive.
+SW_DIR_IS_NOT_FULLPATH The directory "%s" is not a format of full path.\r\n\r\nPlease specify the full path of the directory.
+SW_DIR_DST_IS_OTHER_PRODUCT The specified directory has another component already installed.\r\n\r\nPlease specify another directory.
+SW_DIR_DST_IS_NEWER Newer version of the software has been installed on the specified directory.\r\n\r\nYou need not to install this version.
+SW_DIR_DST_IS_NEWER_2 Newer version of the software has been installed on the specified directory.\r\n\r\nThis installer will import and apply the VPN Connection Settings which is built-in on the Easy Installer. No program files will be overwritten.
+SW_DIR_DST_IS_BROKEN Unable to read a file "%s" which is on the specified directory.\r\n\r\nPlease specify another directory.
+SW_DIR_DST_IS_SYSTEM_MODE The same software is already installed on the specified directory as the System Mode.\r\n\r\nPlease specify another directory.
+SW_DIR_DST_IS_USER_MODE The same software is already installed on the specified directory as the User Mode.\r\n\r\nPlease specify another directory.
+SW_SYSTEM_MODE_ALREADY_INSTALLED The software "%s" is already installed on this computer as the System Mode.\r\n\r\nBoth the System Mode and the User Mode installation of the same software on the same computer will conflict.\r\n\r\nDo you really want to continue the installation as the User Mode?
+
+SW_NOT_INSTALL_SRC The setup program was executed from outside an install source.\r\n\r\nUnable to continue the installation.
+SW_SETUPLOG_CORRUPTED The "setuplog.dat" file is broken.
+SW_MSI_UNINSTALL_FAILED The older version of %s (Product Code: "%S") is installed. Windows Installer failed to uninstall this older version.\r\n\r\nPlease uninstall this older version manually and restart this installer again.
+SW_MSI_UNINSTALL_REBOOT_REQUIRED Windows Installer has uninstalled the older version of %s. The reboot of computer is required.\r\n\r\nPress Finish button and reboot the computer MANUALLY, and restart this installer after the reboot.
+SW_NOTICE_VPNSERVER_IS_INSTALLED SoftEther VPN Bridge is selected as a component to install. However, this computer has already had SoftEther VPN Server installed.\r\n\r\nUsually, you don't need to install both SoftEther VPN Server and SoftEther VPN Bridge on the same computer.\r\nIf you install both software, conflicts such as port number duplication will occur.\r\nif you want to replace the SoftEther VPN Server to SoftEther VPN Bridge, you should exit this installer, uninstall SoftEther VPN Server and restart this installer after that.\r\n\r\nDo you really want to continue the SoftEther VPN Bridge installation?
+SW_NOTICE_VPNBRIDGE_IS_INSTALLED SoftEther VPN Server is selected as a component to install. However, this computer has already had SoftEther VPN Bridge installed.\r\n\r\nUsually, you don't need to install both SoftEther VPN Bridge and SoftEther VPN Server on the same computer.\r\nIf you install both software, conflicts such as port number duplication will occur.\r\nif you want to replace the SoftEther VPN Server to SoftEther VPN Server, you should exit this installer, uninstall SoftEther VPN Bridge and restart this installer after that.\r\n\r\nDo you really want to continue the SoftEther VPN Server installation?
+SW_OS_FAILED This operating system doesn't support %s.
+SW_LANG_NOT_CHANGED The language settings of %s were not changed.
+SW_LANG_LIST_LOAD_FAILED Loading the available language list failed.
+SW_LANG_OK The display language of %s was changed successfully.\r\nIf %s programs are currently running, exit a program and restart it to apply the new display language. If the display language still doesn't effect, reboot Windows.\r\n
+SW_LANG_OK_SERVICE \r\nThe language of log files which the service program records will be changed to the new language after a reboot.
+SW_LANG_OK_VPNCMGR \r\nThe display setting of VPN Client Manager will be changed after exit and reboot VPN Client Manager. (Including complete termination from the task tray.)
+SW_CHILD_PROCESS_ERROR Failed to execute a child process.
+SW_EXE_FILTER Windows Executable Files (*.EXE)|*.exe|All Files (*.*)|*.*
+SW_PERFORM_MSG_EASY_INFO Compiling the VPN Client Easy Installer...
+SW_EASY_FINISHED_MSG The VPN Client Easy Installer is created successfully.\r\nThe installer is saved as the following filename.\r\n\r\n%s\r\n\r\nYou can distribute the above file in the enterprise.
+SW_EASY_ERROR_MSG Failed to create a VPN Client Easy Installer.
+SW_OTHER_INSTANCE_EXISTS Another SoftEther VPN Setup Wizard is running.\r\n\r\nYou can continue this wizard after another wizard exits.
+SW_PERFORM_MSG_WEB_INFO Compiling the VPN Client Web Installer...
+SW_WEB_ERROR_MSG Failed to create a VPN Client Web Installer.
+SW_INSTALLER_CACHE_IS_NOT_SIGNED The currently installed SoftEther VPN Client of this computer was not installed from the digital-signed package signed by an Authenticode digital certificate of SoftEther VPN Project.\r\nIt might be installed from a customized installer (for example, an installer created by Easy Installer Creator.)\r\n\r\nIf you continue to create a Web Installer, a warning message will be appeared on the user's screen when loading.\r\nTo avoid showing the warning message, you should cancel this creating wizard, download the latest version of SoftEther VPN Client from the SoftEther VPN Project's web site, re-install it and restart the Web Installer Creator wizard.\r\n\r\nDo you really to continue to create a Web Installer?
+SW_FILE_NOT_FOUNT The file "%s" not found.
+SW_WEB_FINISHED The Web Installer is created and saved as "%s".\r\n\r\nPlease extract inner files from the ZIP file, upload them into the Web server, and edit a HTML file and an inf file to replace URLs appropriately.\r\n\r\nThe explanation to deploy the Web Installer is described on the ZIP file.
+
+
+
+
+SW_PERFORM_MSG_INIT_TASKS Preparing the tasks...
+SW_PERFORM_MSG_COPY_PREPARE Preparing the copying of files...
+SW_PERFORM_MSG_WRITE_ERROR Failed to write the destination file "%s".\r\n\r\nThere might be another program who is keeping this file open.\r\nIf programs or services of %s are running, please terminate them and click Retry.
+SW_PERFORM_MSG_COPY_FILE Copying "%s" ...
+SW_PERFORM_MSG_SET_SECURITY Setting a security on "%s" ...
+SW_PERFORM_MSG_PLUGIN Installing the plugins...
+SW_PERFORM_MSG_STOP_SVC Stopping the "%s" service ...
+SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK The file "%s" is locked by a running program. Waiting to unlock...
+SW_PERFORM_MSG_INSTALL_SVC Installing the %s service...
+SW_PERFORM_MSG_START_SVC Starting the %s service...
+SW_PERFORM_MSG_CREATE_LINKS Creating shortcut files...
+SW_PERFORM_MSG_DELETE_LINKS Deleting shortcut files...
+SW_PERFORM_MSG_DELETE_OLD_LINKS Deleting old shortcut files...
+SW_PERFORM_MSG_REGISTER_UNINSTALL Registering uninstall information on the Control Panel...
+SW_PERFORM_MSG_IMPORTING_ACCOUNT Importing the Built-in VPN Connection Setting in the Easy Installer...
+SW_PERFORM_MSG_DELETE_SETUP_INFO Deleting the install information and logs...
+SW_PERFORM_MSG_WRITE_LOG Writing a setup log...
+SW_PERFORM_MSG_COPY_ERROR Copying to the file "%s" failed.
+SW_PERFORM_MSG_CRAETE_LINK_ERROR Creating the shortcut file "%s" failed.\r\n\r\nDo you want to retry?
+SW_PERFORM_MSG_WRITE_LOG_ERROR Creating the setup log file "%s".\r\n\r\nDo you want to retry?
+SW_PERFORM_MSG_STOP_SVC_ERROR Stopping the "%s" service (internal name: "%S") failed.
+SW_PERFORM_MSG_START_SVC_ERROR Starting the "%s" service (internal name: "%S") failed.
+SW_PERFORM_MSG_SVC_UNINSTALL_FAILED Uninstall of the "%s" service (internal name: "%S") failed.
+SW_PERFORM_MSG_SVC_INSTALL_FAILED Install of the "%s" service (internal name: "%S") failed.
+SW_PERFORM_MSG_SVC_USERMODE_EXEC_FAILED Starting the user-mode service "%s" failed.
+SW_PERFORM_MSG_UPDATING Updating system settings...
+SW_PERFORM_MSG_FINISHED Setup progress finished.
+SW_PERFORM_MSG_UNINSTALL_MSI Windows Installer is uninstalling the older version of %s...
+SW_PERFORM_MSG_UPDATE_LANG_CONFIG Changing the language settings...
+
+SW_PERFORM_MSG_INIT_UNINST Preparing uninstall...
+SW_PERFORM_MSG_DELETE_PREPARE Preparing to delete files...
+SW_PERFORM_MSG_DELETE_ERROR Unable to delete the file "%s".\r\n\r\nThere might be another program who is keeping this file open.\r\nIf programs or services of %s are running, please terminate them and click Retry.
+SW_PERFORM_MSG_UNINSTALL_SVC Uninstalling the "%s" service ...
+SW_PERFORM_MSG_DELETE Deleting the "%s" service ...
+SW_PERFORM_MSG_EASY_INIT Building the Easy Installer...
+SW_PERFORM_MSG_WEB_INIT Building the Web Installer...
+SW_PERFORM_MSG_INSTALL_SELOW Creating a restore point of the system and installing essential components. It may take a while...
+
+
+SW_TAG_USERNAME \ (User-mode)
+SW_DIRNAME_CONFIG_TOOLS Configuration Tools
+SW_DIRNAME_ADMIN_TOOLS Administrative Tools
+SW_DIRNAME_LANGUAGE_TOOLS Language Settings
+
+SW_RUN_TEXT_VPNSMGR Start the SoftEther VPN Server Manager.
+SW_RUN_TEXT_VPNCMGR Start the SoftEther VPN Client Manager.
+
+# --- Do not translate this section !!! stay them in English !!! ---
+SW_TAG_USERNAME_ENGLISH \ (User-Mode)
+SW_LINK_NAME_VPNSERVER_SVC SoftEther VPN Server User-mode Service
+SW_LINK_NAME_VPNBRIDGE_SVC SoftEther VPN Bridge User-mode Service
+SW_LONG_VPNSERVER SoftEther VPN Server
+SW_LONG_VPNCLIENT SoftEther VPN Client
+SW_LONG_VPNBRIDGE SoftEther VPN Bridge
+SW_LONG_VPNSMGR SoftEther VPN Server Manager
+SW_LONG_VPNCMGR SoftEther VPN Client Manager
+SW_LANG_SET_FAILED Failed to write the new language setting on lang.config file.
+# --- end of "Do not translate this section" ---
+
+
+# Shortcuts Filenames
+SW_LINK_NAME_VPNSMGR_SHORT SoftEther VPN Server Manager
+SW_LINK_NAME_VPNSMGR_SHORT_UM SE-VPN Server Manager (User)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY SE-VPN Server Manager (Tools)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM SE-VPN Server Manager (User)
+SW_LINK_NAME_VPNSMGR_FULL SoftEther VPN Server Manager
+SW_LINK_NAME_VPNSMGR_COMMENT You can manage SoftEther VPN Server or SoftEther VPN Bridge on a remote computer.
+
+SW_LINK_NAME_VPNCMGR_SHORT SoftEther VPN Client Manager
+SW_LINK_NAME_VPNCMGR_FULL SoftEther VPN Client Manager
+SW_LINK_NAME_VPNCMGR_COMMENT You can connect to a VPN Server by using SoftEther VPN Client.
+
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT SoftEther VPN Client Remote Manager
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM SE-VPN Client Remote Manager (User)
+SW_LINK_NAME_VPNCMGRTOOLS_FULL SoftEther VPN Client Remote Manager
+
+SW_LINK_NAME_VPNCMGR2_FULL Manage Remote Computer's SoftEther VPN Client
+SW_LINK_NAME_VPNCMGR2_COMMENT You can establish a remote connection to and manage a SoftEther VPN Client on a remote computer.
+
+SW_LINK_NAME_VPNCMGRTRAY_FULL SoftEther VPN Client Manager Startup
+SW_LINK_NAME_VPNCMGRTRAY_COMMENT Registers an icon of SoftEther VPN Client on the taskbar's notification area.
+
+SW_LINK_NAME_EASYINSTALLER Easy Installer Creator
+SW_LINK_NAME_EASYINSTALLER_COMMENT A tool for enterprise system administrators to create a SoftEther VPN Client Easy Installer which has a function to kick-start a VPN connection to the specific destination automatically.
+
+SW_LINK_NAME_WEBINSTALLER Web Installer Creator
+SW_LINK_NAME_WEBINSTALLER_COMMENT A tool for enterprise system administrators to create a SoftEther VPN Client Web Installer (ActiveX Installer) which has a function to kick-start a VPN connection to the specific destination automatically.
+
+
+SW_LINK_NAME_VPNCMD SoftEther VPN Command Line Utility (vpncmd)
+SW_LINK_NAME_VPNCMD_COMMENT Manage SoftEther VPN Server, SoftEther VPN Bridge and SoftEther VPN Client on the command-line interface in vpncmd.
+SW_LINK_NAME_TRAFFIC Network Traffic Speed Test Tool
+SW_LINK_NAME_TRAFFIC_COMMENT Performs transmitting packets between two computers connected with TCP/IP, with large amount of throughput as possible, in order to measure the actual network traffic speed available.
+SW_LINK_NAME_TCP TCP Optimization Utility
+SW_LINK_NAME_TCP_COMMENT TCP Optimization Utility can adjust the parameters of TCP/IP of Windows in order to increase the network communication throughput of this computer.
+SW_LINK_NAME_SERVICES Services Running on this Computer
+SW_LINK_NAME_SERVICES_COMMENT Starts, stops, and configures Windows services. You can start and stop SoftEther VPN services.
+SW_LINK_NAME_VPNSERVER_SVC_COMMENT Starts SoftEther VPN Server Service in the User Mode.
+SW_LINK_NAME_VPNBRIDGE_SVC_COMMENT Starts SoftEther VPN Bridge Service in the User Mode.
+
+SW_LINK_NAME_UNINSTALL Uninstall %s
+SW_LINK_NAME_UNINSTALL_COMMENT Uninstall %s on this computer.
+
+SW_LINK_NAME_LANGUAGE Configure Display Language
+SW_LINK_NAME_LANGUAGE_COMMENT Change the display language setting of %s.
+
+SW_LINK_NAME_DEBUG Debugging Information Collecting Tool
+SW_LINK_NAME_DEBUG_COMMENT Collects debugging information of SoftEther VPN. Use this tool only if your support staff asks you to do so.
+
+
diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb
new file mode 100644
index 00000000..6cc51bd1
--- /dev/null
+++ b/src/bin/hamcore/strtable_ja.stb
@@ -0,0 +1,7089 @@
+# SoftEther VPN String Table
+# Copyright (c) SoftEther VPN Project. All Rights Reserved.
+#
+# http://www.softether.co.jp/
+
+
+###########################################################################
+# #
+# ソフトウェア内ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ç­‰ã®æ–‡å­—列データ #
+# (ダイアログボックスリソース文字列ã¯é™¤ã) #
+# #
+###########################################################################
+
+
+
+# 環境パラメータ
+DEFAULT_FONT MS UI Gothic
+DEFAULT_FONT_HIGHDPI Meiryo UI
+DEFAULT_FONT_2 MS Gothic
+DEFAULT_FONT_SIZE 9
+DEFAULE_LOCALE å¹´ 月 æ—¥ 時 分 秒 æ—¥ 月 ç« æ°´ 木 金 土 æ—¥ 時間 分 秒 (ãªã—)
+
+
+# 言語
+# (0: 日本語, 1: 英語)
+LANG 0
+LANGSTR Japanese
+
+
+# 文字列テーブル識別å­
+STRTABLE_ID SE_VPN_20121007
+
+
+# 日本語版ã®ã¿ã®æ–‡å­—列 (ä»–ã®è¨€èªžã§ã¯ä¸è¦)
+CM_JAPANESE_ONLY_OLD_STARTUP %s\\SoftEther VPN Client 2.0 タスクトレイ.lnk
+
+# ソフトウェア情報
+PRODUCT_NAME_VPN_CLI SoftEther VPN Client
+PRODUCT_NAME_VPN_CMGR SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+PRODUCT_NAME_VPN_SVR SoftEther VPN Server
+PRODUCT_NAME_VPN_BRIDGE SoftEther VPN Bridge
+PRODUCT_NAME_VPN_SMGR SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£
+PRODUCT_NAME_ELOGSVC SoftEther EtherLogger Beta Edition
+PRODUCT_NAME_ELOGMGR SoftEther EtherLogger Manager Beta Edition
+
+# ソフトウェア更新ãƒã‚§ãƒƒã‚¯ç”¨ã® Family Name
+PRODUCT_FAMILY_NAME SoftEther
+
+
+# 接続制é™ç”¨ã®ãƒ–ランド化文字列
+# BRANDED_C_TO_S Branded_VPN
+# BRANDED_C_FROM_S Branded_VPN
+
+# クライアント ID
+# CLIENT_ID 123
+
+# プロダクト情報
+SE_COMPANY_URL https://selinks.org/?se
+SE_VPNAZURE_URL https://selinks.org/?vpnazure
+
+# 共通文字列
+COMMON_UNKNOWN (ä¸æ˜Ž)
+
+
+# プロトコルエラー文字列
+ERR_UNKNOWN ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+ERR_0 エラーã¯ã‚ã‚Šã¾ã›ã‚“。
+ERR_1 サーãƒãƒ¼ã¸ã®æŽ¥ç¶šãŒå¤±æ•—ã—ã¾ã—ãŸã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã‚„ã€æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚„ãƒãƒ¼ãƒˆç•ªå·ã‚’確èªã—ã¦ãã ã•ã„。
+ERR_2 プロトコルエラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚接続先サーãƒãƒ¼ã‹ã‚‰ã‚¨ãƒ©ãƒ¼ãŒè¿”ã•ã‚Œã¾ã—ãŸã€‚
+ERR_3 接続ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+ERR_4 プロトコルエラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+ERR_5 SoftEther VPN ソフトウェア以外ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãƒãƒ¼ãƒˆã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+ERR_6 ユーザーã«ã‚ˆã£ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚
+ERR_7 指定ã•ã‚ŒãŸèªè¨¼æ–¹æ³•ã¯ã‚µãƒ¼ãƒãƒ¼ã«ã‚ˆã£ã¦æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+ERR_8 指定ã•ã‚ŒãŸä»®æƒ³ HUB ãŒã‚µãƒ¼ãƒãƒ¼ã«å­˜åœ¨ã—ã¾ã›ã‚“。
+ERR_9 ユーザーèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_10 指定ã•ã‚ŒãŸä»®æƒ³ HUB ã¯ç¾åœ¨åœæ­¢ä¸­ã§ã™ã€‚ã—ã°ã‚‰ãå¾…ã£ã¦ã‹ã‚‰ã€å†æŽ¥ç¶šã—ã¦ãã ã•ã„。
+ERR_11 VPN セッションãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚管ç†è€…ãŒã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’切断ã—ãŸã‹ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ VPN Server ã¸ã®æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_12 アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+ERR_13 VPN セッションã®é€šä¿¡ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚クライアントã‹ã‚‰ VPN Server ã¸ã®æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_14 プロトコル番å·ãŒä¸æ­£ã§ã™ã€‚
+ERR_15 TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_16 接続先ã®ã‚µãƒ¼ãƒãƒ¼ã¾ãŸã¯ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„るセッション数ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_17 プロキシサーãƒãƒ¼ã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_18 プロキシサーãƒãƒ¼ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+ERR_19 プロキシサーãƒãƒ¼ã§ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_20 åŒä¸€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•°ãŒå¤šã™ãŽã¾ã™ã€‚ã™ã§ã«ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåŒä¸€ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã—㦠VPN 接続ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_21 VPN Server ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚VPN Server ã®ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_22 仮想 LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。仮想 LAN カードãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ãŠã‚Šã€ç„¡åŠ¹ã«ãªã£ã¦ã„ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+ERR_23 内部エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+ERR_24 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ãƒ‡ãƒã‚¤ã‚¹ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_25 PIN コードãŒé•ã„ã¾ã™ã€‚
+ERR_26 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ãƒ‡ãƒã‚¤ã‚¹ã«ã¯ã€æŒ‡å®šã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã¯æ ¼ç´ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_27 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ãƒ‡ãƒã‚¤ã‚¹ã«ã¯ã€æŒ‡å®šã•ã‚ŒãŸç§˜å¯†éµã¯æ ¼ç´ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_28 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ãƒ‡ãƒã‚¤ã‚¹ã¸ã®æ›¸ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_29 指定ã•ã‚ŒãŸã‚ªãƒ–ジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ERR_30 指定ã•ã‚ŒãŸåå‰ã®ä»®æƒ³ LAN カードã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™ã€‚別ã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。
+ERR_31 仮想 LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_32 指定ã•ã‚ŒãŸåå‰ã¯ã€ä»®æƒ³ LAN カードã®ãƒ‡ãƒã‚¤ã‚¹åã¨ã—ã¦ä½¿ç”¨ã§ãã¾ã›ã‚“。
+ERR_33 サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_34 指定ã•ã‚ŒãŸåå‰ã®æŽ¥ç¶šè¨­å®šã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚
+ERR_35 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šã¯ç¾åœ¨æŽ¥ç¶šä¸­ã§ã™ã€‚
+ERR_36 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šã¯å­˜åœ¨ã—ã¾ã›ã‚“。
+ERR_37 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šã¯æŽ¥ç¶šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_38 パラメータãŒä¸æ­£ã§ã™ã€‚
+ERR_39 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+ERR_40 スマートカードã¾ãŸã¯ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³èªè¨¼ã‚’é¸æŠžã—ã¾ã—ãŸãŒã€ä½¿ç”¨ã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。接続マãƒãƒ¼ã‚¸ãƒ£ã® [スマートカード] メニューã§é¸æŠžã—ã¦ãã ã•ã„。
+ERR_41 指定ã•ã‚ŒãŸä»®æƒ³ LAN カード㯠1 ã¤ä»¥ä¸Šã®æŽ¥ç¶šè¨­å®šã«ã‚ˆã£ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\nã“ã®ä»®æƒ³ LAN カードを使用ã—ã¦ã„る接続設定を削除ã™ã‚‹ã‹ã€æŽ¥ç¶šè¨­å®šãŒä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードを変更ã—ã¦ãã ã•ã„。
+ERR_42 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãŒä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。\r\n仮想 LAN カードãŒå­˜åœ¨ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。ã¾ãŸã€ä»®æƒ³ LAN カードデãƒã‚¤ã‚¹ãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。\r\n\r\nå•é¡ŒãŒè§£æ±ºã§ããªã„å ´åˆã¯ã€ã“ã®æŽ¥ç¶šè¨­å®šã®ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードを変更ã™ã‚‹ã‹ã€åŒã˜åå‰ã®ä»®æƒ³ LAN カードを新è¦ä½œæˆã—ã¦ãã ã•ã„。
+ERR_43 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãŒä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードã¯ã€ã™ã§ã«åˆ¥ã®æŽ¥ç¶šè¨­å®šã«ã‚ˆã£ã¦ä½¿ç”¨ä¸­ã§ã™ã€‚\r\nåŒã˜ä»®æƒ³ LAN カードを使用ã—ã¦ã„る別ã®æŽ¥ç¶šè¨­å®šãŒã‚ã‚‹å ´åˆã¯ã€ãã®æŽ¥ç¶šè¨­å®šã‚’切断ã—ã¦ãã ã•ã„。
+ERR_44 指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãŒä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\nã“ã®æŽ¥ç¶šè¨­å®šã‚’使用ã™ã‚‹å‰ã«ã€ä»®æƒ³ LAN カードを有効化ã—ã¦ã€ä½¿ç”¨å¯èƒ½ãªçŠ¶æ…‹ã«ã—ã¦ãã ã•ã„。
+ERR_45 指定ã•ã‚ŒãŸå€¤ãŒä¸æ­£ã§ã™ã€‚
+ERR_46 接続先ã¯ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+ERR_47 接続試行中ã§ã™ã€‚
+ERR_48 クラスタコントローラã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_49 クラスタコントローラã¯ã‚¯ãƒ©ã‚¹ã‚¿ä¸Šã«æ–°ã—ã„セッションを割り当ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+ERR_50 クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã®ä»®æƒ³ HUB を管ç†ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ERR_51 接続ã—よã†ã¨ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ‘スワードã¯ç©ºã®ãŸã‚ã€ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰æŽ¥ç¶šã‚’è¡Œã†ã“ã¨ã¯ã§ãã¾ã›ã‚“。空ã®ãƒ‘スワードを使ã£ã¦ã„ã‚‹å ´åˆã€VPN Server ã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚³ãƒ³ãƒ”ュータ localhost (127.0.0.1) 上ã‹ã‚‰ã®ã¿æŽ¥ç¶šã§ãã¾ã™ã€‚
+ERR_52 権é™ãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚
+ERR_53 指定ã—ãŸãƒªã‚¹ãƒŠãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ERR_54 ã™ã§ã«æŒ‡å®šã—ãŸãƒãƒ¼ãƒˆç•ªå·ã®ãƒªã‚¹ãƒŠãƒ¼ãŒå­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚
+ERR_55 クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+ERR_56 指定ã—ãŸæš—å·åŒ–アルゴリズムåã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_57 指定ã—ãŸåå‰ã®ä»®æƒ³ HUB ã¯ã™ã§ã«ã‚µãƒ¼ãƒãƒ¼ä¸Šã«å­˜åœ¨ã—ã¾ã™ã€‚
+ERR_58 登録ã•ã‚Œã¦ã„る仮想 HUB ãŒå¤šã™ãŽã¾ã™ã€‚ã“れ以上登録ã§ãã¾ã›ã‚“。å¤ã„仮想 HUB を削除ã—ã¦ãã ã•ã„。
+ERR_59 指定ã•ã‚ŒãŸåå‰ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒã™ã§ã«å­˜åœ¨ã—ã¾ã™ã€‚
+ERR_60 カスケード接続ã¯ã‚¯ãƒ©ã‚¹ã‚¿ä¸Šã®ã‚µãƒ¼ãƒãƒ¼ã«ä½œæˆã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ERR_61 指定ã•ã‚ŒãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã«ãªã£ã¦ã„ã¾ã™ã€‚
+ERR_62 登録ã•ã‚Œã¦ã„るアクセスリスト数ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_63 登録ã•ã‚Œã¦ã„るユーザー数ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_64 登録ã•ã‚Œã¦ã„るグループ数ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_65 指定ã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯å­˜åœ¨ã—ã¾ã›ã‚“。
+ERR_66 指定ã—ãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã™ã§ã«ä»®æƒ³ HUB 上ã«å­˜åœ¨ã—ã¾ã™ã€‚
+ERR_67 指定ã—ãŸåå‰ã®ã‚°ãƒ«ãƒ¼ãƒ—ãŒã™ã§ã«ä»®æƒ³ HUB 上ã«å­˜åœ¨ã—ã¾ã™ã€‚
+ERR_68 指定ã—ãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚µãƒ¼ãƒãƒ¼ä¸Šã«å­˜åœ¨ã—ã¾ã™ãŒã€èªè¨¼ã®ç¨®é¡žã¯ãƒ‘スワードèªè¨¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“。パスワードを変更ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ERR_69 入力ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯å¤ã„パスワードãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。パスワードã¯å¤§æ–‡å­—・å°æ–‡å­—を区別ã•ã‚Œã¾ã™ã€‚
+ERR_70 ã•ã„ãŸã¾ã€‚
+ERR_71 SoftEther ã¯çµŒæ¸ˆç”£æ¥­çœã®è¦è«‹ã«ã‚ˆã‚Šç¾åœ¨é…布を一時åœæ­¢ã•ã›ã¦ã„ãŸã ã„ã¦ãŠã‚Šã¾ã™ã€‚
+ERR_72 SoftEther 㯠IPA ã®è¦è«‹ã«ã‚ˆã‚Šç¾åœ¨é…布を一時åœæ­¢ã•ã›ã¦ã„ãŸã ã„ã¦ãŠã‚Šã¾ã™ã€‚
+ERR_73 カスケード接続ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯åˆ‡æ–­ã§ãã¾ã›ã‚“。セッションを削除ã™ã‚‹ã«ã¯ã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’åœæ­¢ã—ã¦ãã ã•ã„。
+ERR_74 VPN Server ã¸ã®æŽ¥ç¶šè¨­å®šãŒæœªå®Œäº†ã§ã™ã€‚先㫠VPN Server ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。
+ERR_75 ã™ã§ã« VPN Server ã¸ã®æŽ¥ç¶šã‚’開始ã—ã¦ã„ã¾ã™ã€‚
+ERR_76 VPN Server ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_77 指定ã•ã‚ŒãŸ X509 証明書ファイル㯠RSA 1024 bitã€1536 bitã€2048 bitã€3072 bit ã¾ãŸã¯ 4096 bit ã®å…¬é–‹éµã‚’æŒã£ã¦ã„ã¾ã›ã‚“。SoftEther VPN ソフトウェア㯠RSA 1024 bitã€1536 bitã€2048 bitã€3072 bit ã¾ãŸã¯ 4096 bit 証明書をサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚
+ERR_78 SecureNAT ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯åˆ‡æ–­ã§ãã¾ã›ã‚“。セッションを削除ã™ã‚‹ã«ã¯ã€SecureNAT 機能をåœæ­¢ã—ã¦ãã ã•ã„。
+ERR_79 SecureNAT 機能ã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°ç’°å¢ƒã§ã¯æœ‰åŠ¹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ERR_80 SecureNAT 機能ãŒå‹•ä½œã—ã¦ã„ã¾ã›ã‚“。
+ERR_81 ã“ã® VPN Server ã¸ã®æŽ¥ç¶šã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã£ã¦è¨­ç½®ã•ã‚Œã¦ã„るファイアウォール装置ã«ã‚ˆã£ã¦é®æ–­ã•ã‚Œã¾ã—ãŸã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_82 ローカルブリッジセッションã¯åˆ‡æ–­ã§ãã¾ã›ã‚“。セッションを削除ã™ã‚‹ã«ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能をåœæ­¢ã—ã¦ãã ã•ã„。
+ERR_83 ローカルブリッジ機能ãŒå‹•ä½œã—ã¦ã„ã¾ã›ã‚“。
+ERR_84 接続先㮠VPN Server ã§ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジãŒä½¿ç”¨ã§ãã¾ã›ã‚“。ãŠä½¿ã„ã® VPN Server ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジを使用ã™ã‚‹ãŸã‚ã®è¨­å®šæ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ˜ãƒ«ãƒ—ãªã©ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+ERR_85 接続先サーãƒãƒ¼ã®æ示ã—ãŸè¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãã¾ã›ã‚“。接続設定ã§ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’å¿…ãšæ¤œè¨¼ã™ã‚‹è¨­å®šãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚ä¿¡é ¼ã§ãるルート証明書を登録ã™ã‚‹ã‹ã€å›ºæœ‰è¨¼æ˜Žæ›¸ã‚’登録ã—ã¦ãã ã•ã„。
+ERR_86 接続先サーãƒãƒ¼ã®è£½å“コードãŒé•ã„ã¾ã™ã€‚ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰æŽ¥ç¶šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ERR_87 クライアントã¨ã‚µãƒ¼ãƒãƒ¼ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒé•ã„ã¾ã™ã€‚ソフトウェアをアップデートã—ã¦ãã ã•ã„。
+ERR_88 キャプãƒãƒ£ãƒ‡ãƒã‚¤ã‚¹ã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã™ã§ã«åŒä¸€ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ãƒ‡ãƒã‚¤ã‚¹ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_89 接続先サーãƒãƒ¼ã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰æŽ¥ç¶šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。専用クライアントソフトウェアãŒå¿…è¦ã§ã™ã€‚
+ERR_90 指定ã—ãŸã‚­ãƒ£ãƒ—ãƒãƒ£ãƒ‡ãƒã‚¤ã‚¹ã¯ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_91 仮想レイヤ 3 スイッãƒã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯åˆ‡æ–­ã§ãã¾ã›ã‚“。セッションを削除ã™ã‚‹ã«ã¯ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’åœæ­¢ã—ã¦ãã ã•ã„。
+ERR_92 指定ã•ã‚ŒãŸåå‰ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚別ã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。
+ERR_93 指定ã•ã‚ŒãŸåå‰ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ERR_94 指定ã•ã‚ŒãŸåå‰ãŒä¸æ­£ã§ã™ã€‚使用ã§ããªã„文字ãŒå«ã¾ã‚Œã¦ã„ãªã„ã‹ã©ã†ã‹ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。
+ERR_95 仮想レイヤ 3 インターフェイスã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_96 仮想レイヤ 3 インターフェイスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_97 指定ã•ã‚ŒãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 インターフェイスã®æŽ¥ç¶šå…ˆä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„る仮想レイヤ 3 インターフェイスãŒä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä¸­ã«æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚1 ã¤ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä¸­ã§ã¯ã€åŒä¸€ã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 インターフェイス㯠1 ã¤ã—ã‹å®šç¾©ã§ãã¾ã›ã‚“。
+ERR_98 ルーティングテーブルã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_99 ルーティングテーブルã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+ERR_100 指定ã•ã‚ŒãŸãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™ã€‚
+ERR_101 クライアントã¨ã‚µãƒ¼ãƒãƒ¼ã®é–“ã®æ™‚計ãŒãšã‚Œã¦ã„ã¾ã™ã€‚時刻設定を確èªã—ã¦ãã ã•ã„。
+ERR_102 ã“ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’開始ã§ãã¾ã›ã‚“。\r\n\r\n仮想レイヤ 3 スイッãƒã‚’開始ã™ã‚‹ã«ã¯ã€æœ€ä½Žã§ã‚‚ 1 ã¤ã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒå†…ã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_103 接続先㮠VPN Server ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆæŽ¥ç¶šãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ•°ãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚サーãƒãƒ¼ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_104 接続先㮠VPN Server ã®ãƒ–リッジ接続ライセンス数ãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚サーãƒãƒ¼ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_105 接続先㮠VPN Server ã¯ã€ç¾åœ¨æŠ€è¡“çš„ãªå•é¡Œã§æŽ¥ç¶šã‚’å—ã‘付ã‘ã¦ã„ã¾ã›ã‚“。ã—ã°ã‚‰ãå¾…ã¤ã‹ã€VPN Server ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ã‚µãƒ¼ãƒãƒ¼ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’確èªã™ã‚‹ã‚ˆã†è¦è«‹ã—ã¦ãã ã•ã„。
+ERR_106 接続先㮠VPN Server ã®è¨¼æ˜Žæ›¸ã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¦ã„ã¾ã™ã€‚VPN Server ã®ç®¡ç†è€…ã«ã”連絡ãã ã•ã„。
+ERR_107 モニタリングモードã§æŽ¥ç¶šã‚’è¦æ±‚ã—ã¾ã—ãŸãŒã€æŽ¥ç¶šã«ä½¿ç”¨ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã¯ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ãƒ¢ãƒ¼ãƒ‰ã‚’許å¯ã—ã¦ã„ã¾ã›ã‚“。
+ERR_108 ブリッジ / ルータモードã§æŽ¥ç¶šã‚’è¦æ±‚ã—ã¾ã—ãŸãŒã€æŽ¥ç¶šã«ä½¿ç”¨ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã¯ãƒ–リッジモードもルータモードもç¦æ­¢ã—ã¦ã„ã¾ã™ã€‚
+ERR_109 VPN Server ã®ä»®æƒ³ HUB ã®æŽ¥ç¶šå…ƒ IP 制é™ãƒªã‚¹ãƒˆã®è¨­å®šã«ã‚ˆã£ã¦ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã® IP アドレスã‹ã‚‰ã®æŽ¥ç¶šã¯æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+ERR_110 項目数ãŒå¤šã™ãŽã¾ã™ã€‚
+ERR_111 メモリãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚
+ERR_112 指定ã•ã‚ŒãŸã‚ªãƒ–ジェクトã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚
+ERR_113 致命的ãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚プログラムã®å‹•ä½œãŒç¶™ç¶šã§ããªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ERR_114 接続先 VPN Server ã§ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãƒ©ã‚¤ã‚»ãƒ³ã‚¹é•åãŒæ¤œå‡ºã•ã‚Œã¦ã„ã¾ã™ã€‚接続ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。VPN Server ã®ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_115 接続先㮠VPN Server ãŒç¾åœ¨ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ãŒæä¾›ã™ã‚‹é‡è¦ãªã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã—ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’確èªã§ããªã„状態ã§ã™ã€‚ã—ã°ã‚‰ãå¾…ã¤ã‹ã€VPN Server ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ã‚µãƒ¼ãƒãƒ¼ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ãŠã‚ˆã³ã‚µãƒ¼ãƒãƒ¼æœ¬ä½“ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã¸ã®æŽ¥ç¶šçŠ¶æ³ã‚’確èªã™ã‚‹ã‚ˆã†è¦è«‹ã—ã¦ãã ã•ã„。
+ERR_116 クライアントå´ã§ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãƒ©ã‚¤ã‚»ãƒ³ã‚¹é•åãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚接続ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。
+ERR_117 コマンドã¾ãŸã¯ãƒ•ã‚¡ã‚¤ãƒ«åãŒä¸æ­£ã§ã™ã€‚
+ERR_118 ライセンスキーãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。
+ERR_119 VPN Server ã«æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。VPN Server ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
+ERR_120 VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã™ã‚‹ãŸã‚ã«å¿…è¦ãªè£½å“ライセンスãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。VPN Server ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
+ERR_121 ã“ã® VPN Client ã®æŽ¥ç¶šè¨­å®šã¯ SoftEther VPN 2.0 Administration Pack ã«å«ã¾ã‚Œã‚‹ã€ŒWeb インストーラ作æˆã‚­ãƒƒãƒˆã€ã¾ãŸã¯ã€Œç°¡æ˜“インストーラ作æˆã‚­ãƒƒãƒˆã€ã«ã‚ˆã£ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚ŒãŸã‚‚ã®ã§ã™ãŒã€æŽ¥ç¶šå…ˆã® VPN Server 㯠SoftEther VPN 2.0 Administration Pack ã«å¯¾å¿œã—ãŸã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã§ã¯ã‚ã‚Šã¾ã›ã‚“。インストーラã®ä½œæˆå…ƒã‚„システム管ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_122 VPN Server SDK for .NET ライブラリ㯠SoftEther VPN 2.0 Administration Pack ã«å¯¾å¿œã—ãŸã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã® SoftEther VPN Server ã«ã®ã¿æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚接続先㮠VPN Server 㯠SoftEther VPN 2.0 Administration Pack ã«å¯¾å¿œã—ãŸã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã§ã¯ã‚ã‚Šã¾ã›ã‚“。システム管ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_123 接続先ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯ãƒ™ãƒ¼ã‚¿ç‰ˆã§ã€æœŸé™ãŒåˆ‡ã‚Œã¦ã„ã¾ã™ã€‚より新ã—ã„ベータ版ã¾ãŸã¯å®Œæˆç‰ˆã®æä¾›ãŒé–‹å§‹ã•ã‚ŒãŸå¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。http://selinks.org/ ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€æœ€æ–°ç‰ˆã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’入手ã™ã‚‹ã‚ˆã†ã€æŽ¥ç¶šå…ˆã®ã‚µãƒ¼ãƒãƒ¼ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
+ERR_124 VPN Server ã¸ã®æŽ¥ç¶šãŒã‚µãƒ¼ãƒå´ã§æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+ERR_125 VPN Server ã¸ã®æŽ¥ç¶šãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+ERR_126 一定時間ãŒçµŒéŽã—ãŸãŸã‚ã€ç®¡ç†è€…ã«ã‚ˆã£ã¦è¨­å®šã•ã‚ŒãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®šã«ã‚ˆã‚Šã€VPN 接続ãŒè‡ªå‹•çš„ã«åˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚続ã‘ã¦é€šä¿¡ã‚’è¡Œã„ãŸã„å ´åˆã¯ã€ã‚‚ã†ä¸€åº¦æŽ¥ç¶šã—ã¦ãã ã•ã„。
+ERR_127 ã“ã® VPN Server ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ã¯ã€VPN Server ã®ç®¡ç†è€…ãŒä½œæˆã—ãŸç‰¹åˆ¥ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Client ソフトウェアãŒå¿…è¦ã§ã™ã€‚VPN Server ã®ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ERR_128 ã“ã® VPN Server ã«ã¯ã€ã™ã§ã«ç¾åœ¨ã®è£½å“エディションã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§è¨±å®¹ã•ã‚Œã¦ã„る作æˆå¯èƒ½ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°ä»¥ä¸Šã®å€‹æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトãŒä½œæˆãƒ»ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“れ以上ã€ã“ã® VPN Server ã«æ–°ã—ã„ユーザーオブジェクトを作æˆã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。既存ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトをã„ãã¤ã‹å‰Šé™¤ã™ã‚‹ã‹ã€è£½å“エディションを Professional Edition ãªã©ä¸Šä½ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—グレードã—ã¦ãã ã•ã„。
+ERR_129 投入ã—よã†ã¨ã—ãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ã‚µãƒ–スクリプション契約ã¯ã€ã“ã® VPN Server ãŒãƒªãƒªãƒ¼ã‚¹ (ビルド) ã•ã‚ŒãŸæ—¥ã‚ˆã‚Šã‚‚å‰ã«æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¦ã„ã¾ã™ã€‚ãŠå®¢æ§˜ã¯ã€ã‚µãƒ–スクリプション契約を締çµã•ã‚Œã¦ã„ãŸæœŸé–“中ã«ãƒªãƒªãƒ¼ã‚¹ (ビルド) ã•ã‚ŒãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Server ã®ã¿ã‚’使用ã™ã‚‹æ¨©åˆ©ãŒã‚ã‚Šã¾ã™ã€‚ãŠå®¢æ§˜ãŒéŽåŽ»ã«ã‚µãƒ–スクリプション契約を締çµã•ã‚Œã¦ã„ãŸæœŸé–“中ã«ãƒªãƒªãƒ¼ã‚¹ (ビルド) ã•ã‚ŒãŸå¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Server を使用ã™ã‚‹ã‹ã€ã¾ãŸã¯ãŠå®¢æ§˜ã®ã‚µãƒ–スクリプション契約を更新ã—ã¦æ–°ã—ã„ライセンスキーをå–å¾—ã—ã¦ãã ã•ã„。ãªãŠã€å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Server ã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã™ã‚‹ãŸã‚ã«ã€http://selinks.org/ ã‹ã‚‰ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’ダウンロードã§ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+ERR_130 VPN Server ã®ä½“験版ライセンスキーを何個も連続ã—ã¦å–å¾—ã—ã€åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。製å“版ライセンスã®ã”購入をã”検討ãã ã•ã„。
+ERR_131 åŒä¸€ IP アドレスã«è¤‡æ•°ã® VPN Server ãŒã‚ã‚Šã¾ã™ã€‚NAT 使用ã®å ´åˆã¯ã€ãƒãƒ¼ãƒˆé–‹æ”¾è¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。ã¾ãŸã¯ã€ŒæŽ¥ç¶šå…ˆã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã¾ãŸã¯ãƒ›ã‚¹ãƒˆå/192.168.x.xã€ã®ã‚ˆã†ã« "/" を付加ã—ã€ã“ã®æ–‡å­—以é™ã«æŽ¥ç¶šå…ˆã‚’特定ã™ã‚‹ãƒ—ライベート IP アドレスã¾ãŸã¯ãƒ›ã‚¹ãƒˆåを指定ã—ã¦ãã ã•ã„。
+ERR_132 ダイナミック DNS サービス用ã®ãƒ›ã‚¹ãƒˆã‚­ãƒ¼ãŒé‡è¤‡ã—ã¦ã„ã¾ã™ã€‚キーã¯è‡ªå‹•çš„ã«ãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾ã™ã€‚
+ERR_133 指定ã•ã‚ŒãŸãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS ホストåã¯ã™ã§ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚別ã®ãƒ›ã‚¹ãƒˆåを指定ã—ã¦ãã ã•ã„。
+ERR_134 指定ã•ã‚ŒãŸãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS ホストåã®ä¸€éƒ¨ã«ä½¿ç”¨ã§ããªã„文字ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚別ã®ãƒ›ã‚¹ãƒˆåを指定ã—ã¦ãã ã•ã„。
+ERR_135 指定ã•ã‚ŒãŸãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS ホストåãŒé•·ã™ãŽã¾ã™ã€‚ホストå㯠31 文字以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+ERR_136 ダイナミック DNS ホストåãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ERR_137 指定ã•ã‚ŒãŸãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS ホストåãŒçŸ­ã™ãŽã¾ã™ã€‚ホストå㯠3 文字以上ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+ERR_138 仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ãƒ‘スワードã¯ã€MS-CHAP v2 èªè¨¼ã‚’è¡Œã†å‰ã«ä¸€åº¦å†è¨­å®šã•ã‚Œã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚VPN サーãƒãƒ¼ã®ç®¡ç†è€…ã«ä¾é ¼ã—ã¦ãƒ‘スワードを内部ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4.0 以é™ã® VPN サーãƒãƒ¼ãƒžãƒãƒ¼ã‚¸ãƒ£ã¾ãŸã¯ vpncmd ユーティリティを用ã„ã¦å†è¨­å®šã™ã‚‹ã‹ã€VPN Client ソフトウェアを用ã„ã¦ãƒ‘スワードを変更ã—ã¦ãã ã•ã„。
+ERR_139 ダイナミック DNS サーãƒãƒ¼ã¨ã®é–“ã®é€šä¿¡ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+ERR_140 ICMP (Ping) プロトコルをåˆæœŸåŒ–ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚VPN Server を動作ã•ã›ã¦ã„るプロセスãŒä¸€èˆ¬ãƒ¦ãƒ¼ã‚¶ãƒ¼æ¨©é™ã§å‹•ä½œã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã®ã‚ˆã†ãªå ´åˆã¯ã€VPN Server をシステムサービスã¨ã—ã¦å‹•ä½œã•ã›ã¦ãã ã•ã„ (Linux / UNIX ã®å ´åˆã¯ root 権é™ã§å‹•ä½œã•ã›ã¦ãã ã•ã„)。
+ERR_141 DNS ãƒãƒ¼ãƒˆ 53 ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã§ã™ã§ã«åˆ¥ã® DNS サーãƒãƒ¼ãƒ—ログラム (BIND ã‚„ Microsoft DNS Server ãªã©) ãŒå‹•ä½œã—ã¦ã„ãªã„ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。ã“れらã®åŒä¸€ãƒãƒ¼ãƒˆã‚’使用ã™ã‚‹ãƒ—ログラムを終了ã•ã›ã¦å†è©¦è¡Œã—ã¦ã¿ã¦ãã ã•ã„。ã¾ãŸã€Linux / UNIX ã®å ´åˆã¯ VPN Server プロセス㌠root 権é™ã§å‹•ä½œã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+ERR_142 OpenVPN サーãƒãƒ¼æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“。
+ERR_143 ユーザーèªè¨¼ã®æ–¹æ³•ã®ã†ã¡ã€Œè¨¼æ˜Žæ›¸èªè¨¼ã€ãŠã‚ˆã³ã€Œå¤–部サーãƒãƒ¼èªè¨¼ã€æ©Ÿèƒ½ã¯ã‚ªãƒ¼ãƒ—ンソース版 SoftEther VPN ã«ã¯ã¾ã å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã›ã‚“。ユーザーèªè¨¼ã®æ–¹æ³•ã¨ã—ã¦ã€ŒåŒ¿åèªè¨¼ã€ã¾ãŸã¯ã€Œãƒ‘スワードèªè¨¼ã€ã®ã„ãšã‚Œã‹ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+ERR_144 ã“ã®æ“作ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。VPN Gate 中継サーãƒãƒ¼ã«é–¢ã™ã‚‹æ“作㯠VPN Gate コントロールパãƒãƒ«ã‹ã‚‰å®Ÿè¡Œã—ã¦ãã ã•ã„。
+ERR_145 ã“ã®æ“作ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。VPN Gate 公開 VPN 中継サーãƒãƒ¼ã®æŽ¥ç¶šè¨­å®šã«é–¢ã™ã‚‹æ“作㯠VPN Gate ã®è¨­å®šç”»é¢ã‹ã‚‰å®Ÿè¡Œã—ã¦ãã ã•ã„。
+ERR_146 VPN Gate サービス㌠VPN Client 内ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®è¨­å®šç”»é¢ã‹ã‚‰ VPN Gate サービスをåœæ­¢ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。VPN Gate サービスをåœæ­¢ã™ã‚‹ã«ã¯ã€VPN Client 接続マãƒãƒ¼ã‚¸ãƒ£ã®è¨­å®šãƒ„ールを使用ã—ã¦ãã ã•ã„。
+ERR_147 ã“ã®æ©Ÿèƒ½ã¯ã‚ªãƒ¼ãƒ—ンソース版 SoftEther VPN ã«ã¯ã¾ã å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+
+
+
+# ライセンス関係
+LICENSE_INFO_URL https://selinks.org/?new_license
+LICENSE_SUPPORT_URL https://selinks.org/?q=license_info&id=%s
+LICENSE_STATUS_OK 有効
+LICENSE_STATUS_EXPIRED 有効期é™åˆ‡ã‚Œ
+LICENSE_STATUS_ID_DIFF サーãƒãƒ¼ ID ä¸ä¸€è‡´
+LICENSE_STATUS_DUP é‡è¤‡
+LICENSE_STATUS_INSUFFICIENT å¿…è¦ãªä»–ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒä¸è¶³
+LICENSE_STATUS_COMPETITION ä»–ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã¨ç«¶åˆ
+LICENSE_STATUS_NONSENSE ç¾åœ¨ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã§ã¯ç„¡æ„味
+LICENSE_STATUS_CPU CPU ã®ç¨®é¡žãŒä¸ä¸€è‡´
+LICENSE_STATUS_OTHERERROR ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ã®ãŸã‚無効
+
+
+# TCP 最é©åŒ–関係
+TCPOPT_NOT_SUPPORTED TCP/IP 通信設定最é©åŒ–ユーティリティã¯ã€ã“ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+TCPOPT_NOT_ADMIN TCP/IP 通信設定最é©åŒ–ユーティリティã¯ã€ç®¡ç†è€…権é™ã®ç„¡ã„ユーザーã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+
+
+# Windows Vista / Windows 7 / Windows 8 用最é©åŒ–関係
+VISTA_MMCSS_MSG Windows Vista / Windows 7 / Windows 8 㧠VPN 通信を経由ã—ã¦ãƒžãƒ«ãƒãƒ¡ãƒ‡ã‚£ã‚¢ãƒ•ã‚¡ã‚¤ãƒ« (ビデオやオーディオã€ã‚¹ãƒˆãƒªãƒ¼ãƒŸãƒ³ã‚°ãªã©) ã‚’å†ç”Ÿã™ã‚‹ãŸã‚ã®æœ€é©åŒ–ã‚’ã—ã¾ã™ã‹?
+VISTA_MMCSS_MSG_2 ã™ã§ã« Windows Vista / Windows 7 / Windows 8 㧠VPN 通信を経由ã—ã¦ãƒžãƒ«ãƒãƒ¡ãƒ‡ã‚£ã‚¢ãƒ•ã‚¡ã‚¤ãƒ« (ビデオやオーディオã€ã‚¹ãƒˆãƒªãƒ¼ãƒŸãƒ³ã‚°ãªã©) ã‚’å†ç”Ÿã™ã‚‹ãŸã‚ã®æœ€é©åŒ–ã®è¨­å®šãŒè¡Œã‚ã‚Œã¦ã„ã¾ã™ã€‚\r\n最é©åŒ–設定を削除ã—ã¦ã€å…ƒã«æˆ»ã—ã¾ã™ã‹?
+VISTA_MMCSS_MSG_3 ç¾åœ¨ã®ç’°å¢ƒã§ã¯ã€æœ€é©åŒ–ã®æ©Ÿèƒ½ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+VISTA_MMCSS_MSG_4 ã“ã®æ©Ÿèƒ½ã¯ã€Administrators 権é™ã§ãƒ—ログラムを起動ã—ã¦ã„ã‚‹éš›ã«ã®ã¿ä½¿ç”¨ã§ãã¾ã™ã€‚\r\nWindows Vista / Windows 7 / Windows 8 ã®å ´åˆã¯ã€[管ç†è€…ã¨ã—ã¦å®Ÿè¡Œ] 機能を使用ã—ã¦ãƒ—ログラムを実行ã—ã¦ãã ã•ã„。
+VISTA_MMCSS_MSG_5 最é©åŒ–設定ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+VISTA_MMCSS_MSG_6 最é©åŒ–設定ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚
+
+# PKCS ユーティリティ関係
+PKCS_UTIL_TITLE PKCS#12 書ãè¾¼ã¿ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£
+PKCS_UTIL_SAVEDLG_TITLE USB トークンã«æ›¸ãè¾¼ã¿ãŸã„ PKCS#12 ファイルをé¸æŠž
+PKCS_UTIL_READ_ERROR ファイル %s を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+PKCS_UTIL_WRITE_OK_MSG ファイル %s ã‚’ USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ã«æ›¸ãè¾¼ã¿ã¾ã—ãŸã€‚
+PKCS_UTIL_DELETE_OK_MSG USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ã‹ã‚‰ PKCS#12 証明書データを消去ã—ã¾ã—ãŸã€‚
+PKCS_UTIL_SECA_FILENAME seca_p12
+PKCS_MAKE_SURE USB トークン内ã«æ›¸ãè¾¼ã¾ã‚Œã¦ã„ã‚‹ PKCS#12 証明書データを消去ã—ã¾ã™ã€‚\r\n一旦消去ã—ãŸãƒ‡ãƒ¼ã‚¿ã¯ã€äºŒåº¦ã¨å¾©å…ƒã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。\r\r\n\r\r\n続行ã—ã¾ã™ã‹?
+PKCS_UTIL_BAD_FILE 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯ PKCS#12 ファイルã¨ã—ã¦èªè­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+
+
+# 共通ダイアログ関係
+DLG_ALL_FILES ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_CERT_FILES X509 証明書ファイル (*.CER;*.CRT)|*.cer;*.crt|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_KEY_FILTER 秘密éµãƒ•ã‚¡ã‚¤ãƒ« (*.KEY;*.PEM)|*.key;*.pem|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_PKCS12_FILTER PKCS#12 ファイル (*.P12;*.PFX)|*.p12;*.pfx|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_CERT_OR_P12_FILTER X509 証明書ã¾ãŸã¯ PKCS#12 ファイル (*.CER;*.CRT;*.P12;*.PFX)|*.cer;*.crt;*.p12;*.pfx|X509 証明書ファイル (*.CER;*.CRT)|*.cer;*.crt|PKCS#12 ファイル (*.P12;*.PFX)|*.p12;*.pfx|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_CONFIG_FILES 設定ファイル (*.CONFIG)|*.config|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_KEY_OR_P12_FILTER 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã¾ãŸã¯ PKCS#12 ファイル (*.KEY;*.PEM;*.P12;*.PFX)|*.key;*.pem;*.p12;*.pfx|秘密éµãƒ•ã‚¡ã‚¤ãƒ« (*.KEY;*.PEM)|*.key;*.pem|PKCS#12 ファイル (*.P12;*.PFX)|*.p12;*.pfx|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_ZIP_FILER ZIP ファイル (*.ZIP)|*.zip|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+DLG_OPEN_CERT 証明書ファイルをé¸æŠžã—ã¦ãã ã•ã„
+DLG_OPEN_KEY 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„
+DLG_OPEN_KEY_WITH_CERT 対応ã™ã‚‹ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„
+DLG_OPEN_FILE_ERROR 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ« "%S" を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+DLG_OPEN_FILE_ERROR_W 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ« "%s" を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+DLG_BAD_P12 ファイル "%S" ã¯æœ‰åŠ¹ãª PKCS#12 証明書ファイルã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_P12_W ファイル "%s" ã¯æœ‰åŠ¹ãª PKCS#12 証明書ファイルã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_X509 ファイル "%S" ã¯æœ‰åŠ¹ãª X509 証明書ファイルã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_X509_W ファイル "%s" ã¯æœ‰åŠ¹ãª X509 証明書ファイルã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_KEY ファイル "%S" ã¯æœ‰åŠ¹ãª RSA 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_KEY_W ファイル "%s" ã¯æœ‰åŠ¹ãª RSA 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+DLG_BAD_SIGNATURE 指定ã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã«å«ã¾ã‚Œã‚‹å…¬é–‹éµã¨ç§˜å¯†éµãŒæ­£ã—ã対応ã—ã¦ã„ã¾ã›ã‚“。\r\n証明書ã®å…¬é–‹éµã«å¯¾å¿œã—ãŸç§˜å¯†éµãŒå¿…è¦ã§ã™ã€‚
+DLG_SAVE_CERT 証明書をä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+DLG_SAVE_KEY 秘密éµã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+DLG_SAVE_P12 証明書ã¨ç§˜å¯†éµã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+DLG_SAVE_FILE ä¿å­˜å…ˆã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+DLG_SAVE_OPENVPN_CONFIG OpenVPN 設定ファイルを格ç´ã—㟠ZIP ファイルã®ä¿å­˜å…ˆ
+DLG_CERT_SAVE_OK 証明書を正ã—ãä¿å­˜ã—ã¾ã—ãŸã€‚
+DLG_CERT_SAVE_ERROR 証明書をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+DLG_KEY_SAVE_OK 秘密éµã‚’æ­£ã—ãä¿å­˜ã—ã¾ã—ãŸã€‚
+DLG_KEY_SAVE_ERROR 秘密éµã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+DLG_KEY_PAIR_SAVE_OK 証明書ã¨ç§˜å¯†éµã‚’æ­£ã—ãä¿å­˜ã—ã¾ã—ãŸã€‚
+DLG_KEY_PAIR_SAVE_ERROR 証明書ã¨ç§˜å¯†éµã‚’æ­£ã—ãä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+DLG_REBOOT_INFO %u 秒後ã«ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã—ã¾ã™ã€‚
+DLG_REBOOT_INFO_2 コンピュータをå†èµ·å‹•ã—ã¦ã„ã¾ã™...
+DLG_REBOOT_ERROR コンピュータã®å†èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚\r\n\r\nç›´ã¡ã«ã‚³ãƒ³ãƒ”ュータを手動ã§å†èµ·å‹•ã—ã¦ãã ã•ã„。
+DLG_SAVE_CONFIG コンフィグレーションã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+DLG_OPEN_CONFIG インãƒãƒ¼ãƒˆã™ã‚‹ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„
+DLG_STRING_DEFTITLE 文字列ã®å…¥åŠ›
+DLG_STRING_DEFINFO 文字列を入力ã—ã¦ãã ã•ã„。
+DLG_ABOUT_LEGAL 法律上ã®é€šçŸ¥
+DLG_UPDATE_DATE \ (%S ã«ãƒªãƒªãƒ¼ã‚¹)
+DLG_UPDATE_HINT [OK] をクリックã™ã‚‹ã¨ã€Web ブラウザãŒé–‹ã„ã¦æœ€æ–°ã®ã‚¢ãƒƒãƒ—デートã«é–¢ã™ã‚‹æƒ…å ±ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\r\n\r\nアップデートã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¨ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯æ‰‹å‹•ã§è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ä»–ã®ã‚³ãƒ³ãƒ”ュータ上ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ã‚¢ãƒƒãƒ—デートを行ã†å ´åˆã¯ã€ãã®ã‚³ãƒ³ãƒ”ュータã«ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—ã‚„ SSH ãªã©ã§ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¨ã‚¢ãƒƒãƒ—デート作業を行ã£ã¦ãã ã•ã„。\r\n
+
+
+# 競åˆã™ã‚‹ãƒ—ロセス関係
+BAD_PROCESS_TITLE %S ã«é–¢ã™ã‚‹è­¦å‘Š
+BAD_PROCESS_MESSAGE ã“ã®ã‚³ãƒ³ãƒ”ュータã§ã€å•é¡Œã®åŽŸå› ã¨ãªã‚‹å¯èƒ½æ€§ã®ã‚るソフトウェア "%S" ãŒå‹•ä½œã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã“ã¨ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚\r\n\r\n"%S" ã«å«ã¾ã‚Œã‚‹å•é¡ŒãŒåŽŸå› ã§ VPN 通信ãŒä¸å®‰å®šã«ãªã£ãŸã‚Šã€ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã‚Šã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nVPN をソフトウェア "%S" ã¨å…±ã«åˆ©ç”¨ã—ãŸã“ã¨ã«ã‚ˆã‚Šã€VPN ã®å‹•ä½œãŒä¸å®‰å®šã«ãªã‚‹å ´åˆã¯ã€"%S" ã‚’åœæ­¢ã™ã‚‹ã‹ã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ (ソフトウェアã®ç¨®é¡žã«ã‚ˆã£ã¦ã¯ã€åœæ­¢ã•ã›ã‚‹ã ã‘ã§ã¯ä¾ç„¶ã¨ã—ã¦ã‚³ãƒ³ãƒ”ュータã«å•é¡ŒãŒæ®‹ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã”注æ„ãã ã•ã„)。\r\n
+
+
+# ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³é–¢ä¿‚
+SEC_SMART_CARD スマートカード
+SEC_USB_TOKEN USB トークン
+SEC_INIT_MSG_1 以下ã®ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã‚’スマートカードリーダã«æŒ¿å…¥ã—ã€PIN コードを入力ã—ã¦ãã ã•ã„。
+SEC_INIT_MSG_2 以下㮠USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚’コンピュータ㮠USB ãƒãƒ¼ãƒˆã«æŽ¥ç¶šã—ã€PIN コードを入力ã—ã¦ãã ã•ã„。
+SEC_OPENING デãƒã‚¤ã‚¹ã‚’é–‹ã„ã¦ã„ã¾ã™...
+SEC_CLOSING デãƒã‚¤ã‚¹ã‚’é–‰ã˜ã¦ã„ã¾ã™...
+SEC_OPEN_SESSION セキュアセッションを開ã„ã¦ã„ã¾ã™...
+SEC_CLOSE_SESSION セキュアセッションを閉ã˜ã¦ã„ã¾ã™...
+SEC_LOGIN トークンã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã¾ã™...
+SEC_LOGOUT トークンã‹ã‚‰ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ã¦ã„ã¾ã™...
+SEC_INIT_BATCH ãƒãƒƒãƒå‡¦ç†ã‚’開始ã—ã¦ã„ã¾ã™...
+SEC_READ_DATA データを読ã¿å‡ºã—ã¦ã„ã¾ã™...
+SEC_WRITE_DATA データを書ã込んã§ã„ã¾ã™...
+SEC_READ_CERT 証明書を読ã¿è¾¼ã‚“ã§ã„ã¾ã™...
+SEC_WRITE_CERT 証明書を書ã込んã§ã„ã¾ã™...
+SEC_DELETE オブジェクトを削除ã—ã¦ã„ã¾ã™...
+SEC_SIGN 秘密éµã«ã‚ˆã‚‹ãƒ‡ã‚¸ã‚¿ãƒ«ç½²åã‚’è¡Œã£ã¦ã„ã¾ã™...
+SEC_WRITE_KEY 秘密éµã‚’書ã込んã§ã„ã¾ã™...
+SEC_ENUM オブジェクトを列挙ã—ã¦ã„ã¾ã™...
+SEC_FINISHED æ“作ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+SEC_ERROR_INVALID_ID 指定ã•ã‚ŒãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ‡ãƒã‚¤ã‚¹ (デãƒã‚¤ã‚¹ %u) ã¯ç„¡åŠ¹ã§ã™ã€‚
+SEC_ERROR_OPEN_DEVICE デãƒã‚¤ã‚¹ %S ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚デãƒã‚¤ã‚¹ãŒã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_OPEN_DEVICEEX デãƒã‚¤ã‚¹ %S ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚デãƒã‚¤ã‚¹ãŒã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。\r\n\r\nãªãŠã€ä½æ°‘基本å°å¸³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚«ãƒ¼ãƒ‰ãªã©ã®å…¬çš„個人èªè¨¼ã‚µãƒ¼ãƒ“スクライアントソフトウェア等を使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€äº‹å‰ã« [スタート] メニュー㮠[公的個人èªè¨¼ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£] ã§ä½¿ç”¨ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãƒ‡ãƒã‚¤ã‚¹ã‚’é¸æŠžã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+SEC_ERROR_OPEN_SESSION デãƒã‚¤ã‚¹ %S 内部ã§ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’開始ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚æ­£ã—ã„デãƒã‚¤ã‚¹ãŒé¸æŠžã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_LOGIN 入力ã•ã‚ŒãŸ PIN コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚
+SEC_ERROR_NOT_FOUND_1 スマートカード内ã«æŒ‡å®šã•ã‚ŒãŸã‚ªãƒ–ジェクトãŒå­˜åœ¨ã—ã¾ã›ã‚“。正ã—ã„スマートカードãŒæŒ¿å…¥ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_NOT_FOUND_2 USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢å†…ã«æŒ‡å®šã•ã‚ŒãŸã‚ªãƒ–ジェクトãŒå­˜åœ¨ã—ã¾ã›ã‚“。正ã—ã„ USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒæŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_SIGN_1 スマートカード内ã«ç§˜å¯†éµãŒå­˜åœ¨ã—ãªã„ã‹ã€ãƒ‡ã‚¸ã‚¿ãƒ«ç½²åæ“作ã«å¤±æ•—ã—ã¾ã—ãŸã€‚æ­£ã—ã„スマートカードãŒæŒ¿å…¥ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_SIGN_2 USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢å†…ã«ç§˜å¯†éµãŒå­˜åœ¨ã—ãªã„ã‹ã€ãƒ‡ã‚¸ã‚¿ãƒ«ç½²åæ“作ã«å¤±æ•—ã—ã¾ã—ãŸã€‚æ­£ã—ã„ USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒæŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_ERROR_WRITE_1 オブジェクトをスマートカードã«æ›¸ã込むã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚スマートカードã®ç©ºãメモリãŒä¸è¶³ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+SEC_ERROR_WRITE_2 オブジェクトを USB トークンãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã«æ›¸ã込むã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ スマートカードã®ç©ºãメモリãŒä¸è¶³ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+SEC_ERROR_ENUM トークン内ã«æ ¼ç´ã•ã‚Œã¦ã„るオブジェクトã®åˆ—挙ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SEC_ERROR_DELETE 指定ã•ã‚ŒãŸã‚ªãƒ–ジェクトã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚指定ã•ã‚ŒãŸã‚ªãƒ–ジェクトã¯ãƒ¡ãƒ¢ãƒªå†…ã«å­˜åœ¨ã—ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+SEC_COLUMN1 デãƒã‚¤ã‚¹å
+SEC_COLUMN2 種類
+SEC_COLUMN3 製造元
+SEC_COLUMN4 DLL å
+SEC_INVALID_ID 指定ã•ã‚ŒãŸã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãƒ‡ãƒã‚¤ã‚¹ã¯å­˜åœ¨ã—ã¾ã›ã‚“。スマートカードã®ç¨®é¡žã‚’ã‚‚ã†ä¸€åº¦é¸æŠžã—ã¦ãã ã•ã„。
+SEC_MGR_COLUMN1 åå‰
+SEC_MGR_COLUMN2 種類
+SEC_MGR_COLUMN3 プライベート
+SEC_TYPE_DATA データ
+SEC_TYPE_CERT 証明書
+SEC_TYPE_KEY 秘密éµ
+SEC_TYPE_PUB 公開éµ
+SEC_YES ã¯ã„
+SEC_NO ã„ã„ãˆ
+SEC_NONE ãªã—
+SEC_IMPORT_DATA インãƒãƒ¼ãƒˆã—ãŸã„データをé¸æŠžã—ã¦ãã ã•ã„
+SEC_IMPORT_CERT インãƒãƒ¼ãƒˆã—ãŸã„証明書をé¸æŠžã—ã¦ãã ã•ã„
+SEC_IMPORT_KEY インãƒãƒ¼ãƒˆã—ãŸã„秘密éµã‚’é¸æŠžã—ã¦ãã ã•ã„
+SEC_READ_FAILED 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SEC_DATA_TOO_BIG 指定ã•ã‚ŒãŸãƒ‡ãƒ¼ã‚¿ã®ã‚µã‚¤ã‚ºãŒå¤§ãã™ãŽã¾ã™ã€‚スマートカードã«ã¯ %u ãƒã‚¤ãƒˆã‚’超ãˆã‚‹ãƒ‡ãƒ¼ã‚¿ã‚’書ã込むã“ã¨ã¯ã§ãã¾ã›ã‚“。
+SEC_OBJECT_NAME_TITLE 挿入ã™ã‚‹ã‚ªãƒ–ジェクトã®åå‰
+SEC_OBJECT_NAME_INFO æ–°ã—ãスマートカードã«æ›¸ã込むオブジェクトã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。オブジェクトã®åå‰ã«ã¯ã€ç‰¹æ®Šãªè¨˜å·ã‚’除ãä»»æ„ã®åŠè§’文字を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nã™ã§ã«ã‚«ãƒ¼ãƒ‰ã«æ›¸ãè¾¼ã¾ã‚Œã¦ã„ã‚‹åŒã˜ç¨®é¡žã®ã‚ªãƒ–ジェクトåã¨é‡è¤‡ã™ã‚‹ã¨ä¸Šæ›¸ãã•ã‚Œã¾ã™ã®ã§æ³¨æ„ã—ã¦ãã ã•ã„。
+SEC_DELETE_MSG é¸æŠžã—ãŸã‚ªãƒ–ジェクトをスマートカードã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+SEC_OBJECT_IMPORT_OK オブジェクトをスマートカードã«æ›¸ãè¾¼ã¿ã¾ã—ãŸã€‚
+SEC_OBJECT_EXPORT_OK スマートカードã‹ã‚‰èª­ã¿å–ã£ãŸãƒ‡ãƒ¼ã‚¿ã‚’ファイルã«ä¿å­˜ã—ã¾ã—ãŸã€‚
+SEC_NEW_CERT_IMPORT_OK æ–°ã—ã生æˆã—ãŸè¨¼æ˜Žæ›¸ã‚’スマートカードã«æ›¸ãè¾¼ã¿ã¾ã—ãŸã€‚
+SEC_CURRENT_DEVICE ç¾åœ¨ã€ãƒ‡ãƒã‚¤ã‚¹ %S ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚
+SEC_CURRENT_NO_DEVICE 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãƒ‡ãƒã‚¤ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+SEC_NO_SECURE_DEVICE システム㫠SoftEther VPN ãŒå¯¾å¿œã—ãŸã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã¾ãŸã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒˆãƒ¼ã‚¯ãƒ³ãƒ‡ãƒã‚¤ã‚¹ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nSoftEther VPN ã§ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã¾ãŸã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³ã‚’利用ã™ã‚‹ã«ã¯ã€PKCS#11 ã«å¯¾å¿œã—ãŸãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŒ Windows ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€SoftEther VPN ãŒå¯¾å¿œã—ã¦ã„る種類ã®ãƒ‡ãƒã‚¤ã‚¹ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nシステムã«å¯¾å¿œã—ãŸãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。\r\nSoftEther VPN ãŒå¯¾å¿œã—ã¦ã„るデãƒã‚¤ã‚¹ã®ä¸€è¦§ã«ã¤ã„ã¦ã¯ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã® Web サイトをã”覧ãã ã•ã„。ã¾ãŸã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’最新ã®ã‚‚ã®ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šå¯¾å¿œæ©Ÿå™¨ãŒå¢—ãˆã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
+SEC_PIN_DEVICE_OPEN_ERR デãƒã‚¤ã‚¹ "%S" ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒæ­£ã—ã接続ã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’確èªã—ã¦ãã ã•ã„。
+SEC_PIN_CURRENT_BAD ç¾åœ¨ã® PIN コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚
+SEC_PIN_CHANGE_FAILED PIN コードã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SEC_PIN_OK PIN コードを変更ã—ã¾ã—ãŸã€‚
+
+
+# TCP 接続ダイアログ関係
+CONNECTDLG_CAPTION 接続中
+CONNECTDLG_MESSAGE サーãƒãƒ¼ "%S" (TCP ãƒãƒ¼ãƒˆ: %u) ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+CONNECTDLG_CANCELING 接続をキャンセルã—ã¦ã„ã¾ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+
+
+# NIC 情報ダイアログ関係
+NICINFO_1 VPN サーãƒãƒ¼ã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+NICINFO_1_1 VPN 上㮠DHCP サーãƒãƒ¼ã‹ã‚‰ IP アドレスをå–得中...
+NICINFO_1_2 VPN 内ã§ä½¿ç”¨ã™ã‚‹ IP アドレスを決定中...
+
+NICINFO_2 VPN 通信ãŒå¯èƒ½ã«ãªã‚Šã¾ã—ãŸã€‚
+NICINFO_2_1 IP アドレス %S ã®å‰²ã‚Šå½“ã¦ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+
+NICINFO_3 VPN 通信ãŒå¯èƒ½ã«ãªã‚Šã¾ã—ãŸã€‚
+NICINFO_3_1 IP アドレス %S ãŒåˆ©ç”¨å¯èƒ½ã«ãªã‚Šã¾ã—ãŸã€‚
+
+
+# ログイン時パスワード入力ダイアログ関係
+PW_RETRYCOUNT 入力ãŒè¡Œã‚ã‚Œãªã„å ´åˆã€ã‚㨠%u 秒後ã«è‡ªå‹•çš„ã«å†æŽ¥ç¶šã—ã¾ã™...
+PW_LOGIN_DLG_TITLE ログイン
+PW_TYPE_0 匿åèªè¨¼
+PW_TYPE_1 標準パスワードèªè¨¼
+PW_TYPE_2 RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼
+PW_TYPE_3 クライアント証明書èªè¨¼
+PW_TYPE_4 スマートカードèªè¨¼
+
+PW_MSG_PROXY プロキシサーãƒãƒ¼ %S ã§ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚æ­£ã—ã„ユーザーåã¨ãƒ‘スワードをå†å…¥åŠ›ã—ã¦ãã ã•ã„。
+PW_TYPE_PROXY プロキシサーãƒãƒ¼èªè¨¼
+
+
+# VPN 接続ステータス関係
+STATUS_1 åˆæœŸåŒ–中...
+STATUS_2 VPN サーãƒãƒ¼ "%S" ã«ãƒ—ロキシサーãƒãƒ¼ %S 経由ã§æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+STATUS_3 プロキシサーãƒãƒ¼ %S ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã‚’ã—ã¦ã„ã¾ã™...
+STATUS_4 VPN サーãƒãƒ¼ "%S" ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+STATUS_5 サーãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’検証ã—ã¦ã„ã¾ã™...
+STATUS_6 ユーザーèªè¨¼ã‚’è¡Œã£ã¦ã„ã¾ã™...
+STATUS_7 VPN セッションを確立ã—ã¦ã„ã¾ã™...
+STATUS_8 クラスタ内㮠VPN サーãƒãƒ¼ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+STATUS_9 VPN セッションã®ç¢ºç«‹ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+
+
+# 証明書ダイアログ関係
+CERT_NOT_FOUND ã“ã®è¨¼æ˜Žæ›¸ã‚’発行ã—ãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãる証明書ã®ãƒªã‚¹ãƒˆã‹ã‚‰è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+CERT_ROOT ã“ã®è¨¼æ˜Žæ›¸ã¯ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ (自己署å証明書) ã§ã™ã€‚
+CERT_LV_C1 フィールド
+CERT_LV_C2 値
+CERT_SERIAL シリアル番å·
+CERT_ISSUER 発行者
+CERT_SUBJECT サブジェクト
+CERT_NOT_BEFORE 有効期é™ã®é–‹å§‹
+CERT_NOT_AFTER 有効期é™ã®çµ‚了
+CERT_BITS ビット数
+CERT_PUBLIC_KEY 公開éµ
+CERT_DIGEST_MD5 ダイジェスト (MD5)
+CERT_DIGEST_SHA1 ダイジェスト (SHA-1)
+CERT_NO_SERIAL シリアル番å·ã¯ã‚ã‚Šã¾ã›ã‚“
+CERT_BITS_FORMAT %u bits
+
+
+# 証明書確èªãƒ€ã‚¤ã‚¢ãƒ­ã‚°é–¢ä¿‚
+CC_DANGEROUS_MSG å‰å›žã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ (%S) ã« VPN 接続ã—ãŸéš›ã«ä¿å­˜ã•ã‚ŒãŸã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã¨ã€ä»Šå›žã®æŽ¥ç¶šã®éš›ã«ã‚µãƒ¼ãƒãƒ¼ãŒæ示ã—ã¦ã„るサーãƒãƒ¼è¨¼æ˜Žæ›¸ãŒä¸€è‡´ã—ã¾ã›ã‚“。\r\n\r\nå‰å›žã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ (MD5) : %S\r\nå‰å›žã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ (SHA1): %S\r\n\r\n今回ã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ (MD5) : %S\r\n今回ã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ (SHA1): %S\r\n\r\nVPN Server å´ã®è¨¼æ˜Žæ›¸ãŒã‚µãƒ¼ãƒãƒ¼ç®¡ç†è€…ã«ã‚ˆã£ã¦å¤‰æ›´ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ãŒã€å ´åˆã«ã‚ˆã£ã¦ã¯ã€æˆã‚Šæ¸ˆã¾ã—ãªã©ã®ä¸­é–“攻撃をå—ã‘ã¦ã„ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚\r\n接続ã—よã†ã¨ã—ã¦ã„ã‚‹ VPN Server ã®ç®¡ç†è€…ã«è©³ç´°ã‚’å•ã„åˆã‚ã›ã‚‹ã“ã¨ã‚’å¼·ããŠå‹§ã‚ã—ã¾ã™ã€‚
+CC_WARNING_MSG ç¾åœ¨æŽ¥ç¶šã—よã†ã¨ã—ã¦ã„ã‚‹ VPN Server ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’次回 %s ã«æŽ¥ç¶šã™ã‚‹éš›ã«è‡ªå‹•çš„ã«ä¿¡é ¼ã—ã¾ã™ã‹?\r\n\r\nダイジェスト値 (SHA1): %S\r\nダイジェスト値 (MD5) : %S\r\n\r\nã“ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ãŒæ­£ã—ã„ã‚‚ã®ã§ã‚ã‚‹ã‹ã©ã†ã‹ä¸å®‰ãªå ´åˆã¯ã€ä¸Šè¨˜ã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ã‚’サーãƒãƒ¼è¨­ç½®è€…ã«å¯¾ã—ã¦å®‰å…¨ãªæ–¹æ³•ã§ç¢ºèªã—ã¦ãã ã•ã„。\r\n\r\n[ã¯ã„] をクリックã™ã‚‹ã¨ã€æ¬¡å›žã‹ã‚‰ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹éš›ã«ã“ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ãŒæ示ã•ã‚ŒãŸå ´åˆã¯ã€è‡ªå‹•çš„ã«ä¿¡é ¼ã—ã¾ã™ã€‚\r\n[ã„ã„ãˆ] をクリックã™ã‚‹ã¨ã€ä»Šå›žã®æŽ¥ç¶šã®ã¿ä¿¡é ¼ã—ã€æ¬¡å›žã®æŽ¥ç¶šã®éš›ã«ã¯å†åº¦è­¦å‘Šã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã€‚\r\n[キャンセル] をクリックã™ã‚‹ã¨ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã®è­¦å‘Šç”»é¢ã«æˆ»ã‚Šã¾ã™ã€‚\r\n\r\n※ ã“ã®è¨­å®šã¯ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã”ã¨ã«å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ—ロパティã§è¨­å®šã§ãã¾ã™ã€‚
+
+
+# 接続失敗ダイアログ関係
+ERRDLG_ERRMSG エラー (エラーコード %u) :\r\n%s\r\n
+ERRDLG_RETRYCOUNT 入力ãŒè¡Œã‚ã‚Œãªã„å ´åˆã€ã‚㨠%u 秒後ã«è‡ªå‹•çš„ã«å†æŽ¥ç¶šã—ã¾ã™...
+ERRDLG_INFORMATION [å†è©¦è¡Œ] をクリックã™ã‚‹ã¨ã€å†åº¦æŽ¥ç¶šã‚’開始ã—ã¾ã™ã€‚
+ERRDLG_RETRY_INFO_1 %u / %u 回目ã®å†è©¦è¡Œã‚’è¡Œã„ã¾ã™ã‹?
+ERRDLG_RETRY_INFO_2 %u 回目ã®å†è©¦è¡Œã‚’è¡Œã„ã¾ã™ã‹?
+ERRDLG_DISCONNECTED_MSG VPN Server "%S" ã¸ã®æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+ERRDLG_DEVICE_ERROR 仮想 LAN カード (デãƒã‚¤ã‚¹å: %S) ãŒåœæ­¢ã•ã‚ŒãŸãŸã‚ã€VPN Server ã¨ã®æŽ¥ç¶šã‚’切断ã—ã¾ã—ãŸã€‚\r\n\r\nエラーコード %u: %s
+
+
+# プロトコル関係
+PROTO_DIRECT_TCP 直接 TCP/IP 接続
+PROTO_HTTP_PROXY HTTP プロキシ経由接続
+PROTO_SOCKS_PROXY SOCKS プロキシ経由接続
+PROTO_SSH SSH サーãƒãƒ¼çµŒç”±æŽ¥ç¶š
+PROTO_UNKNOWN ä¸æ˜Žãªãƒ—ロトコル
+
+
+# Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«é–¢ã™ã‚‹ã‚¨ãƒ©ãƒ¼
+WINVER_TITLE Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«é–¢ã™ã‚‹è­¦å‘Š
+WINVER_ERROR_FORMAT %sã® Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ (ãŠã‚ˆã³ã‚µãƒ¼ãƒ“スパック番å·) ã¯ã€Œ%Sã€ã§ã™ã€‚\r\n\r\n%s ãŒå¯¾å¿œã—ã¦ã„ã‚‹ Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ (ãŠã‚ˆã³ã‚µãƒ¼ãƒ“スパック番å·) ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™:\r\n%S\r\n\r\n%sã® Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã€%s ãŒå¯¾å¿œã—ã¦ã„ã‚‹ Windows ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚ˆã‚Šã‚‚æ–°ã—ã„ãŸã‚ã€äºˆæœŸã›ã¬ä¸å…·åˆã‚„互æ›æ€§ã®å•é¡Œãªã©ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n予期ã›ã¬ä¸å…·åˆã‚„互æ›æ€§ã®å•é¡Œãªã©ã‚’é¿ã‘ã‚‹ãŸã‚ã«ã€%s ã®æ›´æ–°ç‰ˆã‚’入手ã—アップデートã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\r\n(アップデートã›ãšã«ã“ã®ã¾ã¾ä½¿ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã™ãŒã€ã§ãã‚‹ã ã‘早急ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã„ãŸã—ã¾ã™ã€‚)\r\n\r\nã‚ãªãŸãŒã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã§ã‚ã‚‹å ´åˆã¯ã€%s ã®æ›´æ–°ç‰ˆã‚¢ãƒƒãƒ—デートパッãƒã‚’ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã® Web サイト http://selinks.org/ ã‹ã‚‰ç„¡æ–™ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nã‚ãªãŸãŒã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã§ãªã„å ´åˆã¯ã€ã“ã®è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚ŒãŸæ—¨ã‚’ VPN システムã®ç®¡ç†è€…ã«ãŠä¼ãˆãã ã•ã„。\r\n\r\n----- MSG%04u%02u -----\r\n\r\n
+WINVER_ERROR_VPNSERVER 接続先サーãƒãƒ¼ã‚³ãƒ³ãƒ”ュータ㮠VPN Server
+WINVER_ERROR_VPNBRIDGE 接続先サーãƒãƒ¼ã‚³ãƒ³ãƒ”ュータ㮠VPN Bridge
+WINVER_ERROR_VPNCLIENT ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚³ãƒ³ãƒ”ュータ㮠VPN Client
+WINVER_ERROR_PC_LOCAL ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚³ãƒ³ãƒ”ュータ
+WINVER_ERROR_PC_REMOTE 接続先ã®ã‚µãƒ¼ãƒãƒ¼ã‚³ãƒ³ãƒ”ュータ
+
+
+# オープンソース版ã«é–¢ã™ã‚‹è­¦å‘Š
+OSS_MSG ã¯ã˜ã‚ã« - SoftEther VPN Server ã«ã¤ã„ã¦\r\n\r\nã“ã® VPN Server ã¯ã€ç­‘波大学ã«ãŠã„ã¦å­¦è¡“実験目的ã§é–‹ç™ºã•ã‚Œ SoftEther プロジェクト http://www.softether.org/ ã§ç„¡å„Ÿé…布ã•ã‚Œã¦ã„るオープンソースã®ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã§ã™ã€‚\r\nSoftEther VPN ソフトウェアã¯å›½ç«‹å¤§å­¦æ³•äººç­‘波大学ã¨ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã¨ã®å…±åŒç ”究契約ã®ä¸€ç’°ã¨ã—ã¦åºƒã公開ã•ã‚Œã¦ã„ã‚‹ã‚‚ã®ã§ã™ã€‚SoftEther VPN ソフトウェアã¯å­¦è¡“実験目的ã§é–‹ç™ºãƒ»å…¬é–‹ã•ã‚Œã¦ãŠã‚Šã¾ã™ã€‚SoftEther VPN ソフトウェアã«å«ã¾ã‚Œã‚‹ä¸å…·åˆç­‰ã«ã¤ã„ã¦ã®ã‚µãƒãƒ¼ãƒˆç­‰ã¯æä¾›ã•ã‚Œã¦ãŠã‚‰ãšã€åˆ©ç”¨è€…ãŒã™ã¹ã¦ã®è²¬ä»»ã‚’è² ã†ã“ã¨ã«ãªã‚Šã¾ã™ã€‚本ソフトウェアã®é–‹ç™ºè€…・é…布者ã¯ã€SoftEther VPN ソフトウェアã®åˆ©ç”¨ã®çµæžœã€åˆ©ç”¨è€…ã«ç”Ÿã˜ã‚‹æ失等ã«ã¤ã„ã¦ã€ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。\r\n\r\nã“れらã®ã“ã¨ã«åˆæ„ã„ãŸã ã„ãŸä¸Šã§ã€SoftEther VPN Server を用ã„ãŸé€šä¿¡ã‚’ãŠæ¥½ã—ã¿ãã ã•ã„。\r\n\r\nSoftEther VPN ã«ã¤ã„ã¦è©³ã—ã㯠http://www.softether.org/ ã‚’ã”å‚ç…§ãã ã•ã„。\r\n\r\n
+
+
+# 仮想 HUB 管ç†ã‚ªãƒ—ション関係
+HUB_AO_CLICK é …ç›®åã‚’ 1 ã¤é¸æŠžã™ã‚‹ã¨ã€ãã®é …ç›®åã«é–¢ã™ã‚‹èª¬æ˜Žæ–‡ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+HUB_AO_UNKNOWN ã“ã®é …ç›®ã«é–¢ã™ã‚‹èª¬æ˜Žæ–‡ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ドキュメント等をå‚ç…§ã™ã‚‹ã‹ã€é …ç›®åã‚’ã‚‚ã¨ã«æ„味・内容を推測ã—ã¦åˆ©ç”¨ã—ã¦ãã ã•ã„。
+HUB_AO_allow_hub_admin_change_option ã“ã®é …ç›®ã¯ç‰¹æ®Šã§ã™ã€‚ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€VPN Server 全体ã®ç®¡ç†è€…ã ã‘ã§ãªã仮想 HUB ã®ç®¡ç†è€…も自ら仮想 HUB 管ç†ã‚ªãƒ—ションを変更ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_deny_hub_admin_change_ext_option ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®æ‹¡å¼µã‚ªãƒ—ションã®è¨­å®šã‚’変更ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã€VPN Server 全体ã®ç®¡ç†è€…ã®ã¿ãŒä»®æƒ³ HUB ã®æ‹¡å¼µã‚ªãƒ—ションã®è¨­å®šã‚’変更ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_no_delay_jitter_packet_loss ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã‚’追加ã™ã‚‹éš›ã«é…延・ジッタ・パケットロスを生æˆã•ã›ã‚‹ãŸã‚ã®ãƒ‘ラメータãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã§ã‚ã£ã¦ã‚‚ã€ãれらã®å€¤ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€é…延・パケットロス生æˆæ©Ÿèƒ½ãŒå®Ÿè³ªçš„ã«ç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚é…延・パケットロス生æˆæ©Ÿèƒ½ã¯ VPN Server ã® CPU ãŠã‚ˆã³ãƒ¡ãƒ¢ãƒªä½¿ç”¨çŽ‡ã‚’高ãã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ãŸã‚ã€å¤šãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§å…±æœ‰ã™ã‚‹ä»®æƒ³ HUB ã®å ´åˆã¯ã€é«˜è² è·ã‚’é¿ã‘ã‚‹ãŸã‚ã«ã“ã®ã‚ªãƒ—ションを使用ã—ã¦ãã ã•ã„。
+HUB_AO_max_users ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã§ãるユーザーã®æœ€å¤§æ•°ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトを登録ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_multilogins_per_user ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 1 個ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトã«å¯¾ã—ã¦åŒæ™‚ã«ãƒ­ã‚°ã‚¤ãƒ³ã—接続å¯èƒ½ãª VPN セッション数ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上㮠VPN セッションãŒåŒä¸€ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトを用ã„㦠VPN サーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_groups ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã§ãるグループã®æœ€å¤§æ•°ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上ã®ã‚°ãƒ«ãƒ¼ãƒ—オブジェクトを登録ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_accesslists ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã§ãるアクセスリスト項目ã®æœ€å¤§æ•°ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆé …目を登録ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_sessions_client_bridge_apply ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã®ã¿ã€max_sessions_client ãŠã‚ˆã³ max_sessions_bridge ã®å€¤ãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚
+HUB_AO_max_sessions ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ãã‚‹ VPN セッション数ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上㮠VPN 接続をåŒæ™‚ã«å‡¦ç†ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_sessions_client ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ãã‚‹ VPN クライアントセッション数ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上㮠VPN 接続をåŒæ™‚ã«å‡¦ç†ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚ã“ã®é …ç›®ã¯ã€max_sessions_client_bridge_apply ㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã®ã¿æœ‰åŠ¹ã§ã™ã€‚
+HUB_AO_max_sessions_bridge ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ãã‚‹ VPN ブリッジセッション数ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«åˆ¶é™ã•ã‚Œã€ãれ以上㮠VPN 接続をåŒæ™‚ã«å‡¦ç†ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚ã“ã®é …ç›®ã¯ã€max_sessions_client_bridge_apply ㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã®ã¿æœ‰åŠ¹ã§ã™ã€‚
+HUB_AO_max_bitrates_download ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã™ã¹ã¦ã® VPN セッションã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®ã†ã¡ [ダウンロード帯域幅] ãƒãƒªã‚·ãƒ¼ã®å€¤ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«å¼·åˆ¶çš„ã«å¤‰æ›´ã•ã‚Œã€ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰é€Ÿåº¦ãŒåˆ¶é™ã•ã‚Œã¾ã™ã€‚ãŸã¨ãˆã°ã€ã“ã®å€¤ãŒ 1000000 ã«ãªã£ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«å¯¾ã™ã‚‹ã„ã‹ãªã‚‹ VPN 接続セッションã§ã‚‚ãã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰é€šä¿¡é€Ÿåº¦ã¯ 1 Mbps を超ãˆã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_max_bitrates_upload ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã™ã¹ã¦ã® VPN セッションã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®ã†ã¡ [アップロード帯域幅] ãƒãƒªã‚·ãƒ¼ã®å€¤ãŒã“ã®é …ç›®ã®æŒ‡å®šæ•°ã«å¼·åˆ¶çš„ã«å¤‰æ›´ã•ã‚Œã€ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚¢ãƒƒãƒ—ロード速度ãŒåˆ¶é™ã•ã‚Œã¾ã™ã€‚ãŸã¨ãˆã°ã€ã“ã®å€¤ãŒ 1000000 ã«ãªã£ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«å¯¾ã™ã‚‹ã„ã‹ãªã‚‹ VPN 接続セッションã§ã‚‚ãã®ã‚¢ãƒƒãƒ—ロード通信速度㯠1 Mbps を超ãˆã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_deny_empty_password ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã«ç©ºã®ãƒ‘スワードを設定ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚ã‚‚ã—空ã®ãƒ‘スワードãŒè¨­å®šã•ã‚Œã¦ã„るユーザーãŒã„ã‚‹å ´åˆã¯ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ VPN 接続を行ã†ã“ã¨ã¯ã§ãã¾ã›ã‚“ (例外ã¨ã—ã¦ã€localhost ã‹ã‚‰ã®æŽ¥ç¶šã¯å¯èƒ½ã§ã™)。
+HUB_AO_deny_bridge ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã«å¯¾ã—ã¦æŽ¥ç¶šã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã€æŽ¥ç¶šæ™‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å†…容ã«ã‹ã‹ã‚らãšå¸¸ã«ãƒ–リッジãŒç¦æ­¢ã•ã‚Œã¾ã™ã€‚ã—ãŸãŒã£ã¦ã€ã“ã®ä»®æƒ³ HUB ã«ãƒ–リッジ目的ã§æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_deny_routing ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã«å¯¾ã—ã¦æŽ¥ç¶šã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã€æŽ¥ç¶šæ™‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å†…容ã«ã‹ã‹ã‚らãšå¸¸ã«ãƒ«ãƒ¼ã‚¿å‹•ä½œãŒç¦æ­¢ã•ã‚Œã¾ã™ã€‚ã—ãŸãŒã£ã¦ã€ã“ã®ä»®æƒ³ HUB ã«ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ç›®çš„ã§æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_deny_qos ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã«å¯¾ã—ã¦æŽ¥ç¶šã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã€æŽ¥ç¶šæ™‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å†…容ã«ã‹ã‹ã‚らãšå¸¸ã« QoS 機能ãŒç¦æ­¢ã•ã‚Œã¾ã™ã€‚
+HUB_AO_deny_change_user_password ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã€Œãƒ‘スワードèªè¨¼ï½£ãƒ¢ãƒ¼ãƒ‰ã®å ´åˆã€è‡ªåˆ†ã§ãƒ‘スワードを変更ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_users ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«æ–°ã—ã„ユーザーを追加ã—ãŸã‚Šã€æ—¢å­˜ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã¾ãŸã¯ç·¨é›†ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_groups ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«æ–°ã—ã„グループを追加ã—ãŸã‚Šã€æ—¢å­˜ã®ã‚°ãƒ«ãƒ¼ãƒ—を削除ã¾ãŸã¯ç·¨é›†ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_securenat ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…㯠SecureNAT 機能を有効ã¾ãŸã¯ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_securenat_enablenat ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…㯠SecureNAT 機能ã«ãŠã‘る仮想 NAT 機能を有効ã¾ãŸã¯ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_securenat_enabledhcp ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…㯠SecureNAT 機能ã«ãŠã‘る仮想 DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_cascade ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆãƒ»å‰Šé™¤ãƒ»ç·¨é›†ã¾ãŸã¯ã‚ªãƒ³ãƒ©ã‚¤ãƒ³åŒ– / オフライン化ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_online ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã‚ªãƒ•ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã®ä»®æƒ³ HUB をオンライン化ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_offline ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã®ä»®æƒ³ HUB をオフライン化ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_log_config ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¿å­˜è¨­å®šã‚’変更ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_disconnect_session ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ VPN セッションを指定ã—ã¦å¼·åˆ¶åˆ‡æ–­ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_delete_iptable ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã® IP アドレステーブルデータベースã‹ã‚‰ IP アドレスエントリを指定ã—ã¦å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_delete_mactable ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã® MAC アドレステーブルデータベースã‹ã‚‰ MAC アドレスエントリを指定ã—ã¦å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_enum_session ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«ç¾åœ¨æŽ¥ç¶šã—ã¦ã„ã‚‹ VPN セッションã®ä¸€è¦§ã‚’列挙ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_query_session ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«ç¾åœ¨æŽ¥ç¶šã—ã¦ã„ã‚‹ VPN セッションを指定ã—ã¦ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é–¢ã™ã‚‹è©³ç´°æƒ…報をå–å¾—ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_admin_password ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ç®¡ç†è€…パスワードを変更ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_log_switch_type ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¿å­˜è¨­å®šã®ã†ã¡ã€[ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸ] 設定項目を変更ã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_access_list ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã‚’æ“作ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_access_control_list ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ã‚¢ã‚¯ã‚»ã‚¹å…ƒ IP 制é™ãƒªã‚¹ãƒˆã‚’æ“作ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_cert_list ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ã€Œä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã€ãƒªã‚¹ãƒˆã‚’æ“作ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_crl_list ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ã€Œç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã€ãƒªã‚¹ãƒˆã‚’æ“作ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_read_log_file ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’管ç†æŽ¥ç¶šã‚’通ã˜ã¦åˆ—挙ã—ãŸã‚Šã€ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰èª­ã¿å‡ºã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_change_msg ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã« VPN Client ãŒæŽ¥ç¶šã™ã‚‹éš›ã« VPN Client ã«è¡¨ç¤ºã•ã‚Œã‚‹ã¹ãメッセージを設定ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_no_access_list_include_file ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ä»®æƒ³ HUB ã«ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã‚’追加ã™ã‚‹éš›ã«é€ä¿¡å…ƒã¾ãŸã¯å®›å…ˆãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ã—㦠"include:" ã¾ãŸã¯ "exclude:" 指定ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼åリストファイルを指定ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# 仮想 HUB 拡張オプション関係
+HUB_AO_NoAddressPollingIPv4 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€é€šå¸¸ã€ä»®æƒ³ HUB ㌠5 秒ã”ã¨ã«å®Ÿæ–½ã™ã‚‹ã‚»ã‚°ãƒ¡ãƒ³ãƒˆå†…ã® MAC アドレステーブルãŠã‚ˆã³ IPv4 アドレステーブルã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ (IPv4 デãƒã‚¤ã‚¹ã®ç”Ÿå­˜ç¢ºèªã®ãŸã‚ã® ARP パケットã®é€ä¿¡) を実施ã—ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚一定時間無通信㮠IPv4 デãƒã‚¤ã‚¹ã¯ã€ä»®æƒ³ HUB ã®ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã«å­˜åœ¨ã—ã¦ã„ã¦ã‚‚ã€ä¸€å®šæ™‚é–“ (1 分~ 10 分間) ã§ãƒ†ãƒ¼ãƒ–ルã‹ã‚‰æ¶ˆåŽ»ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šãƒ–ロードキャストパケット数を削減ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€ã„ãã¤ã‹ã® IPv4 関係ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒå®Ÿè³ªçš„ã«æ©Ÿèƒ½ã—ãªããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+HUB_AO_NoAddressPollingIPv6 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€é€šå¸¸ã€ä»®æƒ³ HUB ㌠5 秒ã”ã¨ã«å®Ÿæ–½ã™ã‚‹ã‚»ã‚°ãƒ¡ãƒ³ãƒˆå†…ã® MAC アドレステーブルãŠã‚ˆã³ IPv6 アドレステーブルã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ (IPv6 デãƒã‚¤ã‚¹ã®ç”Ÿå­˜ç¢ºèªã®ãŸã‚ã® ICMPv6 パケットã®é€ä¿¡) を実施ã—ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚一定時間無通信㮠IPv6 デãƒã‚¤ã‚¹ã¯ã€ä»®æƒ³ HUB ã®ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã«å­˜åœ¨ã—ã¦ã„ã¦ã‚‚ã€ä¸€å®šæ™‚é–“ (1 分~ 10 分間) ã§ãƒ†ãƒ¼ãƒ–ルã‹ã‚‰æ¶ˆåŽ»ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šãƒ–ロードキャストパケット数を削減ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€ã„ãã¤ã‹ã® IPv6 関係ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒå®Ÿè³ªçš„ã«æ©Ÿèƒ½ã—ãªããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+HUB_AO_NoIpTable ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 㯠IP アドレステーブルを内部的ã«è‡ªå‹•æ§‹ç¯‰ã—ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Š VPN Server ã® CPU ãŠã‚ˆã³ãƒ¡ãƒ¢ãƒªã®ä½¿ç”¨é‡ã‚’削減ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€ã„ãã¤ã‹ã® IP 関係ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒå®Ÿè³ªçš„ã«æ©Ÿèƒ½ã—ãªããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+HUB_AO_NoMacAddressLog ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã€ä»®æƒ³ HUB ã® MAC アドレステーブルã«æ–°ã—ã„ MAC アドレスãŒç™»éŒ²ã•ã‚ŒãŸå ´åˆã®ãƒ­ã‚°ã‚’セキュリティログã«æ›¸ãã“ã¾ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_ManageOnlyPrivateIP ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ãŒå†…部的ã«æ§‹ç¯‰ã™ã‚‹ IPv4 アドレステーブルã«ã¯ãƒ—ライベート IPv4 アドレスã®ã¿ãŒæ ¼ç´ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ã“ã“ã§ã®ãƒ—ライベート IPv4 アドレスã¨ã¯ã€10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 ã‚’æ„味ã—ã¾ã™ã€‚ãれ以外㮠IPv4 アドレス㯠IPv4 アドレステーブルã«æ ¼ç´ã•ã‚Œãªã„よã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_ManageOnlyLocalUnicastIPv6 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ãŒå†…部的ã«æ§‹ç¯‰ã™ã‚‹ IPv6 アドレステーブルã«ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆ IPv6 アドレスã®ã¿ãŒæ ¼ç´ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ã“ã“ã§ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆ IPv6 アドレスã¨ã¯ã€fe80::/10 ã‚’æ„味ã—ã¾ã™ã€‚ãれ以外㮠IPv6 アドレス㯠IPv6 アドレステーブルã«æ ¼ç´ã•ã‚Œãªã„よã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_DisableIPParsing ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯å†…部的ã«ã™ã¹ã¦ã® Ethernet パケット㮠IP ヘッダを解釈ã—ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Š VPN Server ã® CPU ãŠã‚ˆã³ãƒ¡ãƒ¢ãƒªã®ä½¿ç”¨é‡ã‚’削減ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€ä»®æƒ³ HUB 㯠IP アドレステーブルを内部的ã«è‡ªå‹•æ§‹ç¯‰ã—ãªã„よã†ã«ãªã‚Šã€ã„ãã¤ã‹ã® IP 関係ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒå®Ÿè³ªçš„ã«æ©Ÿèƒ½ã—ãªããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+HUB_AO_YieldAfterStorePacket ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã‚ã‚‹ VPN セッションã‹ã‚‰ãƒ‘ケットをå—ã‘å–ã£ãŸå¾Œã€ãã®ãƒ‘ケットを他㮠VPN セッションã«ã‚¹ãƒˆã‚¢ãƒ»ãƒ•ã‚©ãƒ¯ãƒ¼ãƒ‰ã—ãŸç›´å¾Œã«ä¸€æ—¦ CPU を待機状態ã«è¨­å®šã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šãƒ‘ケットã®é…延ãŒè‹¥å¹²çŸ­ããªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ãŒã€ã‚¹ãƒ¬ãƒƒãƒ‰ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã‚¹ã‚¤ãƒƒãƒå›žæ•°ãŒå¢—加ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šãƒ‘フォーマンスãŒä½Žä¸‹ã™ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚
+HUB_AO_FilterPPPoE ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã® PPPoE (PPP over Ethernet) パケットを破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚複数㮠LAN åŒå£«ã‚’ブリッジ接続ã™ã‚‹å ´åˆã§ã€ä¸¡æ–¹ã® PPPoE セグメントを分割ã—ãŸã„å ´åˆã«ä¾¿åˆ©ã§ã™ã€‚
+HUB_AO_FilterOSPF ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã® OSPF (Open Shortest Path First) パケットを破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+HUB_AO_FilterIPv4 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã® IPv4 パケットãŠã‚ˆã³ ARP パケットを破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+HUB_AO_FilterIPv6 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã® IPv6 パケットを破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+HUB_AO_FilterNonIP ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã®éž IP パケット (IPv4, ARP, IPv6 以外ã®ç¨®é¡žã®ãƒ‘ケット) を破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚ãªãŠã€ä»®æƒ³ HUB を通éŽã™ã‚‹ã™ã¹ã¦ã®ã‚¿ã‚° VLAN パケットã¯éž IP パケットã¨ã—ã¦ã¿ãªã•ã‚Œã¾ã™ã€‚
+HUB_AO_FilterBPDU ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯ã™ã¹ã¦ã® BPDU (Bridge Protocol Data Unit) パケットを破棄ã—ã€è»¢é€ã—ãªã„よã†ã«ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ã™ã¹ã¦ã®ã‚¹ãƒ‘ニング・ツリーパケットãŒä¼é€ã•ã‚Œãªããªã‚Šã¾ã™ã€‚
+HUB_AO_NoIPv6DefaultRouterInRAWhenIPv6 ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã«å¯¾ã—ã¦æŽ¥ç¶šã•ã‚Œã‚‹ã™ã¹ã¦ã® VPN セッション㯠[IPv6 ルータ広告ã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿æŒ‡å®šã‚’削除 (IPv6 物ç†æŽ¥ç¶šæ™‚自動有効化)] ãƒãƒªã‚·ãƒ¼ãŒè‡ªå‹•çš„ã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚VPN Client ã¾ãŸã¯ VPN Bridge ã‹ã‚‰ VPN Server ã«å¯¾ã™ã‚‹æŽ¥ç¶šãŠã‚ˆã³é€šä¿¡ã«åˆ©ç”¨ã™ã‚‹ç‰©ç†çš„ãªãƒ—ロトコル㌠IPv6 ã®å ´åˆã«ã¯ã€ãã® VPN セッションã«å¯¾ã—ã¦ã€ä»®æƒ³ HUB ã®ä»–ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã® IPv6 ルータãŒç™ºä¿¡ã™ã‚‹ IPv6 ルータ広告メッセージã®ãƒ«ãƒ¼ã‚¿æœ‰åŠ¹æœŸé–“ã®å€¤ãŒ 0 以外ã®æ•°å€¤ã®å ´åˆã€ã“ã®å€¤ã‚’強制的㫠0 ã«æ›¸ãæ›ãˆã¦ä¼é€ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€VPN クライアントコンピュータ㌠VPN 接続ã—ãŸå…ˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«å­˜åœ¨ã™ã‚‹ãƒ«ãƒ¼ã‚¿ã‚’デフォルトルータã¨ã—ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šç‰©ç†çš„㪠IPv6 通信ãŒé€”切れã¦ã—ã¾ã†èª¤ä½œå‹•ã‚’防止ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+HUB_AO_NoLookBPDUBridgeId ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 㯠BPDU (Bridge Protocol Data Unit) パケットã®å†…容をもã¨ã« MAC アドレステーブルを構築ã™ã‚‹éš›ã« BPDU パケット内ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã«è¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹é€ä¿¡å…ƒ MAC アドレスを無視ã—ã€Ethernet ヘッダã«è¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹é€ä¿¡å…ƒ MAC アドレスをもã¨ã« MAC アドレステーブルを構築ã—ã¾ã™ã€‚ã“ã®å€¤ã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«éžå¸¸ã«è©³ã—ã„方以外ã¯å¤‰æ›´ã—ãªã„ã§ãã ã•ã„。
+HUB_AO_NoManageVlanId ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 㯠MAC アドレステーブルã®æ§‹ç¯‰ãŠã‚ˆã³æ¤œç´¢ã«ãŠã„㦠VLAN ID を管ç†ã—ãªã„よã†ã«ã—ã€ã™ã¹ã¦ã® Ethernet パケット㮠VLAN タグを無視ã—ã¾ã™ã€‚
+HUB_AO_VlanTypeId VLAN ã‚¿ã‚°ã® Ethernet Type ID (TPID) ã®å€¤ã‚’ 10 進数ã§æŒ‡å®šã—ã¾ã™ã€‚ã“ã®å€¤ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã¯ 33024 (16 進数㧠0x8100) ã§ã™ã€‚ã“ã®å€¤ã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«éžå¸¸ã«è©³ã—ã„方以外ã¯å¤‰æ›´ã—ãªã„ã§ãã ã•ã„。
+HUB_AO_FixForDLinkBPDU ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€FixForDLinkBPDU オプションãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚ã“ã®å€¤ã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«éžå¸¸ã«è©³ã—ã„方以外ã¯å¤‰æ›´ã—ãªã„ã§ãã ã•ã„。
+HUB_AO_NoIPv4PacketLog ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã‚’æµã‚Œã‚‹ã™ã¹ã¦ã® IPv4 パケットã«é–¢ã™ã‚‹ãƒ‘ケットログãŒä¿å­˜ã•ã‚Œãªã„よã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_NoIPv6PacketLog ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã‚’æµã‚Œã‚‹ã™ã¹ã¦ã® IPv6 パケットã«é–¢ã™ã‚‹ãƒ‘ケットログãŒä¿å­˜ã•ã‚Œãªã„よã†ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_NoSpinLockForPacketDelay ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ã‚ˆã£ã¦ãƒ‘ケットã«é…延を発生ã•ã›ã‚‹å ´åˆã«ãŠã„ã¦ã€é…延時間を高精細ã«ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã™ã‚‹ãŸã‚ã«ã‚¹ãƒ”ンロックを使用ã›ãšã€OS ã«ã‚ˆã‚‹ã‚¿ã‚¤ãƒžå‰²ã‚Šè¾¼ã¿ã«ã‚ˆã£ã¦é…延を発生ã•ã›ã‚‹ã‚ˆã†ã«ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Š CPU 使用率ãŒä½Žä¸‹ã—ã¾ã™ãŒã€ç™ºç”Ÿã•ã›ã‚‹ã“ã¨ãŒã§ãã‚‹é…延ã®ç²¾åº¦ã¯ä½Žããªã‚Šã¾ã™ã€‚
+HUB_AO_BroadcastStormDetectionThreshold 大é‡ã®ãƒ–ロードキャストパケットãŒä»®æƒ³ HUB ã«åŒä¸€ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‹ã‚‰æŠ•å…¥ã•ã‚ŒãŸå ´åˆã«ã€ãƒ–ロードキャストストームã§ã‚ã‚‹ã¨åˆ¤å®šã™ã‚‹ãŸã‚ã®é–¾å€¤ã‚’指定ã—ã¾ã™ã€‚1 秒間ã‚ãŸã‚Šã®ãƒ‘ケット個数を指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆ (0 ã®å ´åˆ) 㯠32 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+HUB_AO_ClientMinimumRequiredBuild ã“ã®é …目㌠1 以上ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€è¨­å®šã•ã‚Œã¦ã„る数値よりもビルド番å·ãŒå°ã•ã„ VPN Client ãŒæŽ¥ç¶šã—ã¦ããŸå ´åˆã« VPN 接続を拒å¦ã—ã¾ã™ã€‚
+HUB_AO_RequiredClientId ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ã“ã®æ•´æ•°ã¨åŒä¸€ã®ã€Œã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ IDã€ãŒåŸ‹ã‚è¾¼ã¾ã‚Œã¦ã„ã‚‹ VPN Client ソフトウェアã ã‘ãŒã“ã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ãã€ãれ以外㮠VPN Client ã¯æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚
+HUB_AO_AdjustTcpMssValue ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB を経由ã—ã¦é€šä¿¡ãŒè¡Œã‚れるã™ã¹ã¦ã® TCP/IP パケット㮠MSS (Max Segment Size) ã‚’ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸãƒã‚¤ãƒˆæ•°ä»¥ä¸‹ã«ãªã‚‹ã‚ˆã†ã«è‡ªå‹•èª¿æ•´ã—ã¾ã™ã€‚
+HUB_AO_DisableAdjustTcpMss ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«ãŠã‘ã‚‹ã„ã‹ãªã‚‹ MSS (Max Segment Size) も無効ã«ã—ã¾ã™ã€‚AdjustTcpMssValue オプションãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã‚„ã€IPsec / L2TP / EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½ã«ã‚ˆã£ã¦å—ã‘付ã‘㟠VPN 通信ãŒè¡Œã‚れる場åˆã«ãŠã„ã¦ã‚‚ã€MSS ã®èª¿æ•´ã¯è¡Œã‚ã‚Œãªããªã‚Šã¾ã™ã€‚
+HUB_AO_NoDhcpPacketLogOutsideHub ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 内ã«åˆ°é”ã—㟠DHCP ã«ã‚ˆã‚‹ IP アドレス割当パケットã®ã†ã¡ã€ã“ã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã•ã‚Œã¦ã„るセッションã¨ç„¡é–¢ä¿‚ã®ã‚‚ã®ã«ã¤ã„ã¦ãƒ­ã‚°ã‚’ä¿å­˜ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+HUB_AO_DisableHttpParsing ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB ã¯å†…部的ã«ã™ã¹ã¦ã® HTTP パケット㮠HTTP ヘッダを解釈ã—ãªã„よã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Š VPN Server ã® CPU ãŠã‚ˆã³ãƒ¡ãƒ¢ãƒªã®ä½¿ç”¨é‡ã‚’削減ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€HTTP アクセスログãŒä¿å­˜ã•ã‚Œãªããªã‚Šã¾ã™ã€‚
+HUB_AO_DisableUdpAcceleration ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦æŽ¥ç¶šã•ã‚Œã‚‹ã™ã¹ã¦ã® VPN セッションã«ãŠã„㦠UDP 高速化機能ã®ä½¿ç”¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+HUB_AO_DisableUdpFilterForLocalBridgeNic ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 内ã§ä½œæˆã•ã‚Œã‚‹ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジを構æˆã™ã‚‹ç‰©ç†çš„㪠LAN カード㌠VPN を経由ã—ã¦é éš”地㮠DHCP サーãƒãƒ¼ã‹ã‚‰ IP アドレスã®å‰²å½“ã‚’å—ã‘ã‚‹ã“ã¨ã§å‹•ä½œãŒä¸å®‰å®šã«ãªã‚‹å•é¡Œã‚’解決ã™ã‚‹ãŸã‚ã® DHCP パケットフィルタリング動作を無効ã«ã—ã¾ã™ã€‚
+HUB_AO_ApplyIPv4AccessListOnArpPacket ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 内ã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ IPv4 アクセスリストã®ãƒ«ãƒ¼ãƒ«ã‚’ ARP パケットã«ã‚‚é©ç”¨ã—ã¾ã™ã€‚ä¸è¦ãª ARP è¦æ±‚パケットをé®æ–­ã—ãŸã„å ´åˆã«ä¾¿åˆ©ã§ã™ã€‚
+HUB_AO_RemoveDefGwOnDhcpForLocalhost ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€DHCP サーãƒãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã•ã‚ŒãŸ VPN クライアント㫠IP アドレスを割当ã¦ã‚‹éš›ã«ã€å½“該 VPN クライアント㌠VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã¨åŒä¸€ã§ã‚ã‚‹å ´åˆã¯ DHCP 応答パケットã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤ã®æŒ‡å®šã‚’削除ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€æ„図ã—ãªã„ç„¡é™ãƒ«ãƒ¼ãƒ—を防止ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+HUB_AO_SecureNAT_MaxTcpSessionsPerIp ã“ã®é …目㌠0 以外ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€SecureNAT 機能を利用ã™ã‚‹ VPN クライアント 1 å°ã‚ãŸã‚Šã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•° (SYN_SENT 状態以外㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³) ã®ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸæ•°ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+HUB_AO_SecureNAT_MaxTcpSynSentPerIp ã“ã®é …目㌠0 以外ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€SecureNAT 機能を利用ã™ã‚‹ VPN クライアント 1 å°ã‚ãŸã‚Šã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•° (SYN_SENT 状態㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³) ã®ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸæ•°ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+HUB_AO_SecureNAT_MaxUdpSessionsPerIp ã“ã®é …目㌠0 以外ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€SecureNAT 機能を利用ã™ã‚‹ VPN クライアント 1 å°ã‚ãŸã‚Šã® UDP セッション数ã®ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸæ•°ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+HUB_AO_SecureNAT_MaxDnsSessionsPerIp ã“ã®é …目㌠0 以外ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€SecureNAT 機能を利用ã™ã‚‹ VPN クライアント 1 å°ã‚ãŸã‚Šã® DNS セッション数ã®ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸæ•°ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+HUB_AO_SecureNAT_MaxIcmpSessionsPerIp ã“ã®é …目㌠0 以外ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€SecureNAT 機能を利用ã™ã‚‹ VPN クライアント 1 å°ã‚ãŸã‚Šã® ICMP セッション数ã®ã“ã®é …ç›®ã§æŒ‡å®šã—ãŸæ•°ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+HUB_AO_AccessListIncludeFileCacheLifetime 仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã®ã‚¨ãƒ³ãƒˆãƒªã«ãƒ¦ãƒ¼ã‚¶ãƒ¼å㌠"include:" ã¾ãŸã¯ "exclude:" å½¢å¼ã§æŒ‡å®šã•ã‚Œã¦ãŠã‚Šã€å¤–部ファイルをå‚ç…§ã—ã¦ã„ã‚‹å ´åˆã€å½“該外部ファイルを読ã¿è¾¼ã‚“ã§ã‹ã‚‰ãƒ¡ãƒ¢ãƒªã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã™ã‚‹æ™‚間を秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚
+HUB_AO_DisableKernelModeSecureNAT ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€SecureNAT 機能ã«ãŠã‘るカーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT を無効ã«ã—ã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ã¯ã€SecureNAT ã®ä»®æƒ³ NAT 機能ã®å‹•ä½œé€Ÿåº¦ã‚’高速化ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã‚ã‚Šã€VPN Server プロセスãŒã‚·ã‚¹ãƒ†ãƒ æ¨©é™ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ãŒåŽŸå› ã§ä½•ã‚‰ã‹ã®é€šä¿¡éšœå®³ãŒç™ºç”Ÿã—ãŸå ´åˆã¯ã“ã®ã‚ªãƒ—ションを使用ã—ã¦ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT を無効ã«ã—ã¦ãã ã•ã„。
+HUB_AO_DisableUserModeSecureNAT ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€SecureNAT 機能ã«ãŠã‘るユーザーモード NAT を無効ã«ã—ã¾ã™ã€‚ユーザーモード NAT ã¯ã€SecureNAT ã®ä»®æƒ³ NAT 機能を一般ユーザー権é™ã§å‹•ä½œã•ã›ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã‚ã‚Šã€VPN Server プロセスãŒä¸€èˆ¬ãƒ¦ãƒ¼ã‚¶ãƒ¼æ¨©é™ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã§ã‚‚使用ã§ãã¾ã™ã€‚
+HUB_AO_DisableCheckMacOnLocalBridge ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã«ãŠã„㦠MAC アドレスã®é‡è¤‡ãƒã‚§ãƒƒã‚¯ã‚’無効ã«ã—ã¾ã™ã€‚一部㮠LAN カードã§ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã«ã‚ˆã£ã¦é€å‡ºã•ã‚ŒãŸãƒ‘ケット㌠LAN カード内部ã§åå°„ã—仮想 HUB ã«æˆ»ã£ã¦ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã®å ´åˆã€ä»®æƒ³ HUB 㯠MAC アドレスã®é‡è¤‡ã‚’自動的ã«æ¤œå‡ºã—ã€åå°„ã—ã¦ããŸãƒ‘ケットを破棄ã—ã¾ã™ã€‚ã“ã®ãƒ•ãƒ©ã‚°ã‚’有効ã«ã™ã‚‹ã¨ã€ã“ã®æ¤œå‡ºãƒã‚§ãƒƒã‚¯ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_DisableCorrectIpOffloadChecksum ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã«ãŠã„㦠IP ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®æ¤œæŸ»ãŠã‚ˆã³è£œæ­£å‡¦ç†ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚IP, TCP, UDP ヘッダã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®ã‚ªãƒ•ãƒ­ãƒ¼ãƒ‰æ©Ÿèƒ½ãŒæ­è¼‰ã•ã‚Œã¦ã„ã‚‹ LAN カードã‹ã‚‰é€ä¿¡ã•ã‚ŒãŸ IP パケットãŒåŒä¸€ãƒ›ã‚¹ãƒˆä¸Šã§å‹•ä½œã™ã‚‹ VPN Server ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã«å…¥åŠ›ã•ã‚ŒãŸå ´åˆã€å½“該 IP パケットã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã¯ä¸æ­£ç¢ºãªå€¤ãŒä»£å…¥ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ローカルブリッジã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ãã®ä¸æ­£ç¢ºãªå€¤ã‚’検出ã—ã€æ­£ã—ã„ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®è¨ˆç®—çµæžœã‚’代入ã—ã¾ã™ã€‚ã“ã®ãƒ•ãƒ©ã‚°ã‚’有効ã«ã™ã‚‹ã¨ã€ã“れらã®è£œæ­£å‡¦ç†ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+HUB_AO_BroadcastLimiterStrictMode ã“ã®é …目㌠1 (有効) ã®å ´åˆã¯ã€ä»®æƒ³ HUB 上ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ãŠã‘るブロードキャストストームã®æ¤œå‡ºã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã«ãŠã„ã¦ã€é€ä¿¡å…ƒ IP アドレスã¾ãŸã¯å®›å…ˆ IP アドレスã®ã„ãšã‚Œã‹ 1 個ãŒä¸€è‡´ã—ã¦ã„ã‚Œã°æ—¢å­˜ã®æ¤œå‡ºç”¨è¨˜éŒ²ã¨ãƒ’ットã—ãŸã¨ã¿ãªã—ã¾ã™ã€‚
+
+
+# Caps 関係
+# (制御文字)
+CAPS_YES ã¯ã„
+CAPS_NO ã„ã„ãˆ
+# (タイトル)
+CT_i_max_packet_size 最大 Ethernet パケットサイズ
+CT_i_max_hubs 最大仮想 HUB 数
+CT_i_max_user_creation 最大作æˆå¯èƒ½ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°
+CT_i_max_sessions 最大åŒæ™‚接続å¯èƒ½ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•°
+CT_i_max_clients 最大クライアントセッション数
+CT_i_max_bridges 最大ブリッジセッション数
+CT_i_max_users_per_hub 登録å¯èƒ½ãªæœ€å¤§ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•° / 仮想 HUB
+CT_i_max_groups_per_hub 登録å¯èƒ½ãªæœ€å¤§ã‚°ãƒ«ãƒ¼ãƒ—æ•° / 仮想 HUB
+CT_i_max_access_lists 登録å¯èƒ½ãªæœ€å¤§ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆæ•° / 仮想 HUB
+CT_i_max_mac_tables MAC アドレステーブル最大サイズ / 仮想 HUB
+CT_i_max_ip_tables IP アドレステーブル最大サイズ / 仮想 HUB
+CT_i_max_secnat_tables SecureNAT テーブル最大サイズ / 仮想 HUB
+CT_i_max_l3_sw 登録å¯èƒ½ãªæœ€å¤§ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒæ•°
+CT_i_max_l3_if 登録å¯èƒ½ãªæœ€å¤§ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹æ•° / レイヤ 3 スイッãƒ
+CT_i_max_l3_table 登録å¯èƒ½ãªæœ€å¤§ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ル数 / レイヤ 3 スイッãƒ
+CT_b_bridge VPN Bridge ソフトウェアã¨ã—ã¦å‹•ä½œ
+CT_b_standalone スタンドアロンモード
+CT_b_cluster_controller クラスタコントローラモード
+CT_b_cluster_member クラスタメンãƒãƒ¢ãƒ¼ãƒ‰
+CT_b_vpn_client_connect VPN Client / Bridge ã‹ã‚‰æŽ¥ç¶šãŒå¯èƒ½
+CT_b_local_bridge ローカルブリッジ機能ãŒä½¿ç”¨å¯èƒ½
+CT_b_must_install_pcap パケットキャプãƒãƒ£ãƒ‰ãƒ©ã‚¤ãƒãŒæœªã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«
+CT_b_tap_supported tun/tap ãŒä½¿ç”¨å¯èƒ½ (Linux ã®ã¿)
+CT_b_support_config_hub 仮想 HUB ã®è¨­å®šã®å¤‰æ›´ãŒå¯èƒ½
+CT_b_support_securenat SecureNAT 機能ãŒä½¿ç”¨å¯èƒ½
+CT_b_virtual_nat_disabled 仮想 NAT 機能ã¯ç„¡åŠ¹ (仮想 DHCP 機能ã®ã¿æœ‰åŠ¹)
+CT_b_support_cascade カスケード接続ãŒä½¿ç”¨å¯èƒ½
+CT_b_support_cascade_cert カスケード接続時ã«ã‚µãƒ¼ãƒãƒ¼èªè¨¼ãŒä½¿ç”¨å¯èƒ½
+CT_b_support_config_log ログä¿å­˜è¨­å®šã®å¤‰æ›´ãŒå¯èƒ½
+CT_b_support_autodelete ログファイルã®è‡ªå‹•å‰Šé™¤ãŒä½¿ç”¨å¯èƒ½
+CT_b_support_radius 外部èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã«ã‚ˆã‚‹èªè¨¼è¨­å®šãŒå¯èƒ½
+CT_b_support_config_rw リモート㧠Config ファイルã®èª­ã¿æ›¸ããŒå¯èƒ½
+CT_b_support_hub_admin_option 仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションãŒè¨­å®šå¯èƒ½
+CT_b_support_cascade_client_cert カスケード接続時ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ãŒä½¿ç”¨å¯èƒ½
+CT_b_support_hide_hub 匿åユーザーã¸ã®ä»®æƒ³ HUB ã®åˆ—挙をç¦æ­¢ã™ã‚‹ã“ã¨ãŒå¯èƒ½
+CT_b_support_cluster_admin 複数サーãƒãƒ¼ã«åˆ†æ•£ã—ãŸã‚¯ãƒ©ã‚¹ã‚¿ã®çµ±åˆç®¡ç†ãŒå¯èƒ½
+CT_b_support_cluster クラスタã®ä¸€éƒ¨ã¨ã—ã¦å‹•ä½œå¯èƒ½
+CT_b_support_cluster_controller クラスタコントローラã¨ã—ã¦å‹•ä½œä¸­
+CT_b_support_layer3 仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã‚’サãƒãƒ¼ãƒˆ
+CT_b_support_crl 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã‚’仮想 HUB ã”ã¨ã«è¨­å®šå¯èƒ½
+CT_b_support_ac 接続元 IP 制é™ãƒªã‚¹ãƒˆã‚’仮想 HUB ã”ã¨ã«è¨­å®šå¯èƒ½
+CT_b_support_read_log ログファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãŒå¯èƒ½
+CT_b_support_rename_cascade カスケード接続設定ã®åå‰ã®å¤‰æ›´ãŒå¯èƒ½
+CT_b_support_license ライセンス管ç†ãŒå¯èƒ½
+CT_b_support_limit_multilogin åŒä¸€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®å¤šé‡ãƒ­ã‚°ã‚¤ãƒ³æ•°ã®åˆ¶é™ã‚’設定å¯èƒ½
+CT_b_support_qos VoIP / QoS 対応機能ãŒåˆ©ç”¨å¯èƒ½
+CT_b_support_syslog syslog 機能ãŒåˆ©ç”¨å¯èƒ½
+CT_b_cluster_hub_type_fixed クラスタ内ã®ä»®æƒ³ HUB ã®ç¨®é¡žãŒå›ºå®šã•ã‚Œã¦ã„ã‚‹
+CT_b_beta_version ベータ版 (プレリリースビルド) ã§ã‚ã‚‹
+CT_b_support_check_mac アクセスリスト㧠MAC アドレスを指定å¯èƒ½
+CT_b_support_check_tcp_state TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã§ãƒ‘ケットフィルタリングãŒå¯èƒ½
+CT_b_support_network_connection_name 物ç†çš„㪠LAN カードã®åˆ¥åã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒå¯èƒ½
+CT_b_support_radius_retry_interval_and_several_servers RADIUS èªè¨¼ã§å†è©¦è¡Œé–“éš”ãŠã‚ˆã³è¤‡æ•°ã‚µãƒ¼ãƒãƒ¼æŒ‡å®šãŒå¯èƒ½
+CT_b_support_vlan MAC アドレステーブルã§ã‚¿ã‚° VLAN ã® ID を管ç†å¯èƒ½
+CT_b_support_hub_ext_options 仮想 HUB 拡張オプションをサãƒãƒ¼ãƒˆ
+CT_b_support_policy_ver_3 セキュリティãƒãƒªã‚·ãƒ¼ ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3.0 をサãƒãƒ¼ãƒˆ
+CT_b_support_ipv6_acl IPv6 アクセスリストをサãƒãƒ¼ãƒˆ
+CT_b_support_ex_acl アクセスリストã§é…延・ジッタ・パケットロスã®è¨­å®šã‚’サãƒãƒ¼ãƒˆ
+CT_b_support_acl_group アクセスリストã§ã‚°ãƒ«ãƒ¼ãƒ—åã«ã‚ˆã‚‹æ¡ä»¶ã®æŒ‡å®šã‚’サãƒãƒ¼ãƒˆ
+CT_b_support_ipv6_ac IPv6 接続元 IP 制é™ãƒªã‚¹ãƒˆã‚’サãƒãƒ¼ãƒˆ
+CT_b_support_eth_vlan ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ールをサãƒãƒ¼ãƒˆ
+CT_b_support_msg 仮想 HUB ã¸ã® VPN 接続時ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸è¡¨ç¤ºæ©Ÿèƒ½ã‚’サãƒãƒ¼ãƒˆ
+CT_b_vpn3 内部ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3.0 ã®æ–°æ©Ÿèƒ½
+CT_b_vpn4 内部ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4.0 ã®æ–°æ©Ÿèƒ½
+CT_b_support_ipsec IPsec / L2TP / EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½
+CT_b_support_sstp MS-SSTP VPN サーãƒãƒ¼æ©Ÿèƒ½
+CT_b_support_udp_acceleration UDP アクセラレーション機能
+CT_b_support_openvpn OpenVPN サーãƒãƒ¼æ©Ÿèƒ½
+CT_b_support_ddns ダイナミック DNS クライアント機能
+CT_b_support_ddns_proxy DDNS クライアントã®ãƒ—ロキシサーãƒãƒ¼çµŒç”±ã®æŽ¥ç¶š
+CT_b_support_special_listener VPN over ICMP ãŠã‚ˆã³ VPN over DNS 接続ã®å—付ã‘
+CT_b_support_redirect_url_acl アクセスリスト㧠HTTP ã® URL リダイレクト機能をサãƒãƒ¼ãƒˆ
+CT_b_is_in_vm VM (仮想マシン) 内ã§å‹•ä½œä¸­
+CT_b_support_azure VPN Azure 機能ãŒåˆ©ç”¨å¯èƒ½
+CT_b_support_intel_aes Intel CPU AES Acceleration (AES-NI) ãŒå‹•ä½œä¸­
+CT_b_using_selow_driver SoftEther 軽é‡ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ Ethernet ドライãƒã‚’使用中
+CT_b_support_vgs VPN Gate サービス サーãƒãƒ¼æ©Ÿèƒ½ãŒåˆ©ç”¨å¯èƒ½
+CT_b_support_vgs_in_client VPN Gate サービス サーãƒãƒ¼æ©Ÿèƒ½ (VPN Client çµ±åˆ)
+CT_b_is_softether 無償版ã¾ãŸã¯ã‚ªãƒ¼ãƒ—ンソース版㮠SoftEther VPN ã§ã‚ã‚‹
+
+
+# ãƒãƒªã‚·ãƒ¼é–¢ä¿‚
+POL_TITLE_STR ãƒãƒªã‚·ãƒ¼å
+POL_VALUE_STR ãƒãƒªã‚·ãƒ¼è¨­å®šå€¤
+POL_TYPE_BOOL ON / OFF åž‹
+POL_TYPE_INT 整数値型
+POL_BOOL_ENABLE 有効
+POL_BOOL_DISABLE ï¼
+POL_BOOL_DISABLE_EX ï¼
+POL_INT_ZERO ï¼
+POL_INT_COUNT %u 個
+POL_INT_SEC %u 秒
+POL_INT_BPS %u bps
+POL_INT_VLAN %u
+
+# Ver 2.0
+POL_0 アクセスを許å¯
+POL_EX_0 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーã¯ã€VPN Server ã« VPN 接続ã™ã‚‹ã“ã¨ã‚’許å¯ã•ã‚Œã¾ã™ã€‚
+POL_1 DHCP パケットをフィルタリング (IPv4)
+POL_EX_1 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã‘ã‚‹ IPv4 ã«ãŠã‘ã‚‹ DHCP パケットをã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã—ã¾ã™ã€‚
+POL_2 DHCP サーãƒãƒ¼ã®å‹•ä½œã‚’ç¦æ­¢ (IPv4)
+POL_EX_2 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«æŽ¥ç¶šã—ã¦ã„るコンピュータ㌠DHCP サーãƒãƒ¼ã¨ãªã‚Š IPv4 アドレスや DNS サーãƒãƒ¼ã®æƒ…å ±ãªã©ã‚’ IPv4 DHCP クライアントã«é…布ã™ã‚‹ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_3 DHCP ãŒå‰²ã‚Šå½“ã¦ãŸ IP アドレスを強制 (IPv4)
+POL_EX_3 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッション内㮠IPv4 コンピュータã¯ã€ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å´ã® DHCP サーãƒãƒ¼ãŒå‰²ã‚Šå½“ã¦ã‚’è¡Œã£ãŸ IPv4 アドレスã—ã‹åˆ©ç”¨ã§ããªã„よã†ã«ã—ã¾ã™ã€‚
+POL_4 ブリッジをç¦æ­¢
+POL_EX_4 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã¯ã€ãƒ–リッジ接続をç¦æ­¢ã—ã¾ã™ã€‚ユーザーã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã« Ethernet ブリッジãŒè¨­å®šã•ã‚Œã¦ã„ã¦ã‚‚ã€é€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚
+POL_5 ルータ動作をç¦æ­¢ (IPv4)
+POL_EX_5 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€IPv4 ルーティングをç¦æ­¢ã—ã¾ã™ã€‚ユーザーã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§ IP ルータãŒå‹•ä½œã—ã¦ã„ã¦ã‚‚ã€é€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚
+POL_6 MAC アドレスã®é‡è¤‡ã‚’ç¦æ­¢
+POL_EX_6 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€åˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚³ãƒ³ãƒ”ュータãŒä½¿ç”¨ä¸­ã® MAC アドレスを使用ã™ã‚‹ã“ã¨ãŒã§ããªã„よã†ã«ã—ã¾ã™ã€‚
+POL_7 IP アドレスã®é‡è¤‡ã‚’ç¦æ­¢ (IPv4)
+POL_EX_7 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€åˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚³ãƒ³ãƒ”ュータãŒä½¿ç”¨ä¸­ã® IPv4 アドレスをé‡è¤‡ã—ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªã„よã†ã«ã—ã¾ã™ã€‚
+POL_8 ARP・DHCP・ICMPv6 以外ã®ãƒ–ロードキャストをç¦æ­¢
+POL_EX_8 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«å¯¾ã—㦠IPv4 ã«ãŠã‘ã‚‹ ARP プロトコル㨠DHCP プロトコルãŠã‚ˆã³ IPv6 ã«ãŠã‘ã‚‹ ICMPv6 プロトコルã«ã‚ˆã‚‹ãƒ–ロードキャストパケット以外ã®ã™ã¹ã¦ã®ãƒ–ロードキャストパケットã®é€å—ä¿¡ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_9 プライãƒã‚·ãƒ¼ãƒ•ã‚£ãƒ«ã‚¿ãƒ¢ãƒ¼ãƒ‰
+POL_EX_9 プライãƒã‚·ãƒ¼ãƒ•ã‚£ãƒ«ã‚¿ãƒ¢ãƒ¼ãƒ‰ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッション間ã«ãŠã‘る直接的ãªé€šä¿¡ã‚’ã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã—ã¾ã™ã€‚
+POL_10 TCP/IP サーãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œã‚’ç¦æ­¢ (IPv4)
+POL_EX_10 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ã‚³ãƒ³ãƒ”ュータ㌠TCP/IP プロトコルã«ãŠã‘るサーãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œã‚’è¡Œã†ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_11 ブロードキャスト数を制é™ã—ãªã„
+POL_EX_11 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ã‚³ãƒ³ãƒ”ュータãŒé€šå¸¸ã¯è€ƒãˆã‚‰ã‚Œãªã„よã†ãªç•°å¸¸ãªæ•°ã®ãƒ–ロードキャストパケットを仮想ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é€å‡ºã—ã¦ã‚‚自動的ã«åˆ¶é™ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+POL_12 モニタリングモードを許å¯
+POL_EX_12 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーã¯ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ãƒ¢ãƒ¼ãƒ‰ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚モニタリングモードã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ä»®æƒ³ HUB 内をæµã‚Œã‚‹ã™ã¹ã¦ã®ãƒ‘ケットをモニタリング (å‚å—) ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+POL_13 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã®æœ€å¤§å€¤
+POL_EX_13 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ï¼‘ã¤ã‚ãŸã‚Šã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãる物ç†çš„㪠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã®æœ€å¤§æ•°ã‚’設定ã—ã¾ã™ã€‚
+POL_14 通信タイムアウト時間
+POL_EX_14 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã„㦠VPN Client / VPN Server é–“ã®é€šä¿¡ã«éšœå®³ãŒç™ºç”Ÿã—ãŸå ´åˆã€ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’切断ã™ã‚‹ã¾ã§ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆæ™‚間を秒å˜ä½ã§è¨­å®šã—ã¾ã™ã€‚
+POL_15 MAC アドレスã®ä¸Šé™æ•°
+POL_EX_15 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ï¼‘セッションã‚ãŸã‚Šã«ç™»éŒ²ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ MAC アドレスã®æ•°ã‚’指定ã—ã¾ã™ã€‚
+POL_16 IP アドレスã®ä¸Šé™æ•° (IPv4)
+POL_EX_16 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ï¼‘セッションã‚ãŸã‚Šã«ç™»éŒ²ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ IPv4 アドレスã®æ•°ã‚’指定ã—ã¾ã™ã€‚
+POL_17 アップロード帯域幅
+POL_EX_17 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã‘る仮想 HUB ã®å¤–å´ã‹ã‚‰ä»®æƒ³ HUB ã®å†…å´æ–¹å‘ã«å…¥ã£ã¦ãるトラフィックã®å¸¯åŸŸå¹…を制é™ã—ã¾ã™ã€‚
+POL_18 ダウンロード帯域幅
+POL_EX_18 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã‘る仮想 HUB ã®å†…å´ã‹ã‚‰ä»®æƒ³ HUB ã®å¤–å´æ–¹å‘ã«å‡ºã¦ã„ãトラフィックã®å¸¯åŸŸå¹…を制é™ã—ã¾ã™ã€‚
+POL_19 ユーザーã¯ãƒ‘スワードを変更ã§ããªã„
+POL_EX_19 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーãŒãƒ‘スワードèªè¨¼ã®å ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ãªã©ã‹ã‚‰è‡ªåˆ†ã®ãƒ‘スワードを変更ã™ã‚‹ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_20 多é‡ãƒ­ã‚°ã‚¤ãƒ³åˆ¶é™æ•°
+POL_EX_20 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーãŒè¨­å®šã•ã‚Œã¦ã„る数以上ã®åŒæ™‚ログインを行ã†ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚ブリッジモードセッションã«ã¯ã“ã®åˆ¶é™ã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“。ã“ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã¯ã€VPN Server 3.0 以é™ã€ã¾ãŸã¯å¤šé‡ãƒ­ã‚°ã‚¤ãƒ³åˆ¶é™æ©Ÿèƒ½ãŒæ­è¼‰ã•ã‚Œã¦ã„ã‚‹ VPN Server 2.0 ã§ã®ã¿æœ‰åŠ¹ã§ã™ã€‚
+POL_21 VoIP / QoS 対応機能ã®ä½¿ç”¨ã‚’ç¦æ­¢
+POL_EX_21 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザー㮠VPN 接続セッションã«ãŠã„㦠VoIP / QoS 対応機能ã®ä½¿ç”¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚ã“ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã¯ã€VPN Server 3.0 以é™ã€ã¾ãŸã¯ VoIP / QoS 対応機能ãŒæ­è¼‰ã•ã‚Œã¦ã„ã‚‹ VPN Server 2.0 ã§ã®ã¿æœ‰åŠ¹ã§ã™ã€‚
+
+# Ver 3.0
+POL_22 ルータè¦è«‹/広告パケットをフィルタリング (IPv6)
+POL_EX_22 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã‘ã‚‹ IPv6 ã«ãŠã‘ã‚‹ ICMPv6 パケットã®ã†ã¡ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ç¨®é¡žãŒ 133 (ルータè¦è«‹) ãŠã‚ˆã³ 134 (ルータ広告) ã§ã‚ã‚‹ã™ã¹ã¦ã®ãƒ‘ケットをフィルタリングã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€IPv6 クライアント㯠IPv6 ã«ãŠã‘ã‚‹ IP アドレスプレフィックス自動検出機能ãŠã‚ˆã³ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤è‡ªå‹•æ¤œå‡ºæ©Ÿèƒ½ã‚’利用ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+POL_23 ルータ広告パケットをフィルタリング (IPv6)
+POL_EX_23 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ IPv6 ルータãŒä»®æƒ³ HUB ã«å¯¾ã—ã¦ç™ºä¿¡ã—ãŸã™ã¹ã¦ã® ICMPv6 パケットã®ã†ã¡ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ç¨®é¡žãŒ 134 (ルータ広告) ã§ã‚ã‚‹ã™ã¹ã¦ã®ãƒ‘ケットをフィルタリングã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€æ‚ªæ„ã®ã‚るユーザーãŒä¸æ­£ãªãƒ—レフィックスãŠã‚ˆã³ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤æƒ…報をãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æµã™ã“ã¨ã‚’ç¦æ­¢ã§ãã¾ã™ã€‚
+POL_24 DHCP パケットをフィルタリング (IPv6)
+POL_EX_24 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«ãŠã‘ã‚‹ IPv6 ã«ãŠã‘ã‚‹ DHCP パケットをã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã—ã¾ã™ã€‚
+POL_25 DHCP サーãƒãƒ¼ã®å‹•ä½œã‚’ç¦æ­¢ (IPv6)
+POL_EX_25 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«æŽ¥ç¶šã—ã¦ã„るコンピュータ㌠DHCP サーãƒãƒ¼ã¨ãªã‚Š IPv6 アドレスや DNS サーãƒãƒ¼ã®æƒ…å ±ãªã©ã‚’ IPv6 DHCP クライアントã«é…布ã™ã‚‹ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_26 ルータ動作をç¦æ­¢ (IPv6)
+POL_EX_26 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€IPv6 ルーティングをç¦æ­¢ã—ã¾ã™ã€‚ユーザーã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§ IP ルータãŒå‹•ä½œã—ã¦ã„ã¦ã‚‚ã€é€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚
+POL_27 IP アドレスã®é‡è¤‡ã‚’ç¦æ­¢ (IPv6)
+POL_EX_27 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€åˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚³ãƒ³ãƒ”ュータãŒä½¿ç”¨ä¸­ã® IPv6 アドレスをé‡è¤‡ã—ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªã„よã†ã«ã—ã¾ã™ã€‚
+POL_28 TCP/IP サーãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œã‚’ç¦æ­¢ (IPv6)
+POL_EX_28 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ã‚³ãƒ³ãƒ”ュータ㌠TCP/IP プロトコルã«ãŠã‘るサーãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œã‚’è¡Œã†ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+POL_29 IP アドレスã®ä¸Šé™æ•° (IPv6)
+POL_EX_29 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã®ï¼‘セッションã‚ãŸã‚Šã«ç™»éŒ²ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ IPv6 アドレスã®æ•°ã‚’指定ã—ã¾ã™ã€‚IPv6 クライアントã¯ä¸€èˆ¬çš„ã«è¤‡æ•°å€‹ã® IPv6 一時アドレスを利用ã™ã‚‹ã“ã¨ãŒã‚ã‚‹ãŸã‚ã€1 セッションã‚ãŸã‚Šã«æŽ¥ç¶šã™ã‚‹ã‚³ãƒ³ãƒ”ュータã®å°æ•°ãŒ 1 å°ã ã‘ã§ã‚ã£ãŸã¨ã—ã¦ã‚‚ã€ã“ã®å€¤ã¯å°‘ãªãã¨ã‚‚ 20 以上ã«è¨­å®šã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚
+POL_30 VPN Client ã§ãƒ‘スワードã®ä¿å­˜ã‚’ç¦æ­¢
+POL_EX_30 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るユーザーã¨ã—㦠VPN 接続ã—ã¦ã㟠VPN Client ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹å¼ãŒãƒ‘スワードèªè¨¼ã§ã‚ã‚‹å ´åˆã«ãŠã„ã¦ã€ãƒ‘スワードを記憶ã—ã¦ä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ VPN 接続を行ã†éƒ½åº¦ãƒ‘スワードã®å…¥åŠ›ã‚’求ã‚られるよã†ã«ãªã‚Šã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãŒå‘上ã—ã¾ã™ã€‚ãªãŠã€ã“ã®ãƒãƒªã‚·ãƒ¼ãŒæœ‰åŠ¹ãªå ´åˆã¯ã€VPN Client ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.0 ã®å¤ã„クライアント PC ã¯æŽ¥ç¶šã‚’æ‹’å¦ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚
+POL_31 VPN Client を一定時間ã§è‡ªå‹•åˆ‡æ–­
+POL_EX_31 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã€VPN 接続ã—ã¦ã㟠VPN Client ã¯ã€æŽ¥ç¶šå¾Œã€æŒ‡å®šã•ã‚ŒãŸç§’æ•°ãŒçµŒéŽã™ã‚‹ã¨ã€è‡ªå‹•çš„ã« VPN 接続を切断ã—ã¾ã™ã€‚ã“ã®å ´åˆã¯ã€è‡ªå‹•å†æŽ¥ç¶šã¯å®Ÿæ–½ã•ã‚Œã¾ã›ã‚“。ã“ã‚Œã«ã‚ˆã‚Šã€ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã§ãªã„ユーザーã«ã‚ˆã‚‹å¤§é‡ã® VPN 接続をç¦æ­¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãªãŠã€ã“ã®ãƒãƒªã‚·ãƒ¼ãŒæœ‰åŠ¹ãªå ´åˆã¯ã€VPN Client ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.0 ã®å¤ã„クライアント PC ã¯æŽ¥ç¶šã‚’æ‹’å¦ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚
+POL_32 IPv4 パケットをã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°
+POL_EX_32 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€ã™ã¹ã¦ã® IPv4 パケットã®é€å—ä¿¡ãŒãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã•ã‚Œé®æ–­ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ARP パケットã®é€å—ä¿¡ã‚‚ç¦æ­¢ã•ã‚Œã¾ã™ã€‚
+POL_33 IPv6 パケットをã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°
+POL_EX_33 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€ã™ã¹ã¦ã® IPv6 パケットã®é€å—ä¿¡ãŒãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã•ã‚Œé®æ–­ã•ã‚Œã¾ã™ã€‚
+POL_34 éž IP パケットをã™ã¹ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°
+POL_EX_34 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€ã™ã¹ã¦ã®éž IP パケット (IPv4, ARP, IPv6 以外ã®ç¨®é¡žã®ãƒ‘ケット) ã®é€å—ä¿¡ãŒãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã•ã‚Œé®æ–­ã•ã‚Œã¾ã™ã€‚ãªãŠã€ä»®æƒ³ HUB を通éŽã™ã‚‹ã™ã¹ã¦ã®ã‚¿ã‚° VLAN パケットã¯éž IP パケットã¨ã—ã¦ã¿ãªã•ã‚Œã¾ã™ã€‚
+POL_35 IPv6 ルータ広告ã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿æŒ‡å®šã‚’削除
+POL_EX_35 ã“ã®ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã«å¯¾ã—ã¦ã€ä»®æƒ³ HUB ã®ä»–ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã® IPv6 ルータãŒç™ºä¿¡ã™ã‚‹ IPv6 ルータ広告メッセージã®ãƒ«ãƒ¼ã‚¿æœ‰åŠ¹æœŸé–“ã®å€¤ãŒ 0 以外ã®æ•°å€¤ã®å ´åˆã€ã“ã®å€¤ã‚’強制的㫠0 ã«æ›¸ãæ›ãˆã¦ä¼é€ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€VPN クライアントコンピュータ㌠VPN 接続ã—ãŸå…ˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«å­˜åœ¨ã™ã‚‹ãƒ«ãƒ¼ã‚¿ã‚’デフォルトルータã¨ã—ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šç‰©ç†çš„㪠IPv6 通信ãŒé€”切れã¦ã—ã¾ã†èª¤ä½œå‹•ã‚’防止ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+POL_36 IPv6 ルータ広告ã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿æŒ‡å®šã‚’削除 (IPv6 接続時自動有効化)
+POL_EX_36 [IPv6 ルータ広告ã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿æŒ‡å®šã‚’削除] ãƒãƒªã‚·ãƒ¼ãŒç„¡åŠ¹ã§ã‚ã‚‹å ´åˆã§ã‚‚ã€VPN Client ã¾ãŸã¯ VPN Bridge ã‹ã‚‰ VPN Server ã«å¯¾ã™ã‚‹æŽ¥ç¶šãŠã‚ˆã³é€šä¿¡ã«åˆ©ç”¨ã™ã‚‹ç‰©ç†çš„ãªãƒ—ロトコル㌠IPv6 ã®å ´åˆã«ã¯è‡ªå‹•çš„ã« [IPv6 ルータ広告ã‹ã‚‰ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿æŒ‡å®šã‚’削除] ãƒãƒªã‚·ãƒ¼ãŒæœ‰åŠ¹ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ã‚‚ã®ã¨ã¿ãªã—ã¦å‹•ä½œã™ã‚‹ã‚ˆã†ã«ã—ã¾ã™ã€‚
+POL_37 VLAN ID (IEEE802.1Q)
+POL_EX_37 ã“ã®ãƒãƒªã‚·ãƒ¼ã§ VLAN ID を設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚VLAN ID ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„るセッションã§ã¯ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«å¯¾ã—ã¦é€ä¿¡ã™ã‚‹ã™ã¹ã¦ã® Ethernet フレームã«è‡ªå‹•çš„ã« VLAN ã‚¿ã‚° (IEEE 802.1Q 準拠) ãŒä»˜åŠ ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯åŒä¸€ã® VLAN ID ãŒæ›¸ãè¾¼ã¾ã‚ŒãŸ VLAN タグ付ãã®ãƒ•ãƒ¬ãƒ¼ãƒ ã®ã¿ã‚’å—ä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ (å—ä¿¡ã®éš›ã«ã¯ã€è‡ªå‹•çš„ã« VLAN ã‚¿ã‚°ã¯é™¤åŽ»ã•ã‚Œã¾ã™)。他㮠ID ã® VLAN ã‚¿ã‚°ãŒä»˜ã„ã¦ã„ã‚‹ã‹ã€ã¾ãŸã¯ VLAN ã‚¿ã‚°ãŒä»˜ã„ã¦ã„ãªã„フレームã¯å—ä¿¡ã§ãã¾ã›ã‚“。VLAN ID ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„セッションã§ã¯ã€ã™ã¹ã¦ã® Ethernet フレームãŒé€å—ä¿¡ã§ãã€VLAN ã‚¿ã‚°ã®è‡ªå‹•ä»˜ä¸Žã‚„除去ã¯å®Ÿæ–½ã•ã‚Œã¾ã›ã‚“。ãªãŠã€ä»®æƒ³ HUB を通éŽã™ã‚‹ã™ã¹ã¦ã®ã‚¿ã‚° VLAN パケットã¯éž IP パケットã¨ã—ã¦ã¿ãªã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ã‚¿ã‚° VLAN パケットã¯ä»®æƒ³ HUB ã«ãŠã‘ã‚‹ IPv4 / IPv6 ã«é–¢ä¿‚ã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆãŠã‚ˆã³ãã®ä»–ã® IPv4 / IPv6 パケット固有ã®å‡¦ç†ã®é©ç”¨å¯¾è±¡ã¨ãªã‚Šã¾ã›ã‚“。
+
+
+# リモート接続ダイアログ関係
+REMOTE_DEF_CAPTION リモート接続
+REMOTE_DEF_TITLE リモート接続先ã®ã‚³ãƒ³ãƒ”ュータを指定ã—ã¦ãã ã•ã„。
+
+
+# クライアント通知サービス関係
+CN_TITLE SoftEther VPN Client
+
+
+# 接続マãƒãƒ¼ã‚¸ãƒ£é–¢ä¿‚
+CM_TITLE SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+CM_PW_LOCALMACHINE ã“ã®ã‚³ãƒ³ãƒ”ュータ
+CM_NO_REMOTE %s ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Client サービスã¯ã€ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰ã®æ“作を許å¯ã—ã¦ã„ã¾ã›ã‚“。
+CM_CONNECT_FAILED %s ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Client サービスã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚\r\nVPN Client サービスãŒèµ·å‹•ã—ã€æ­£ã—ã動作ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。
+CM_BAD_PASSWORD パスワードãŒèª¤ã£ã¦ã„ã¾ã™ã€‚å†åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。パスワードを入力ã™ã‚‹ã¨ãã¯å¤§æ–‡å­—ã¨å°æ–‡å­—ã«æ³¨æ„ã—ã¦ãã ã•ã„。
+CM_NUM_CONN_COUNT VPN 接続中: %u アカウント
+CM_CONN_NO 未接続
+CM_PRODUCT_NAME SoftEther VPN Client Build %u
+CM_ACCOUNT_COLUMN_1 接続設定å
+CM_ACCOUNT_COLUMN_2 状態
+CM_ACCOUNT_COLUMN_3 接続先 VPN サーãƒãƒ¼
+CM_ACCOUNT_COLUMN_3_2 仮想 HUB å
+CM_ACCOUNT_COLUMN_4 仮想 LAN カードå
+CM_VLAN_COLUMN_1 仮想 LAN カードå
+CM_VLAN_COLUMN_2 状態
+CM_VLAN_COLUMN_3 MAC アドレス
+CM_VLAN_COLUMN_4 ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+CM_ACCOUNT_OFFLINE オフライン
+CM_ACCOUNT_ONLINE 接続完了
+CM_ACCOUNT_CONNECTING 接続処ç†ä¸­
+CM_VLAN_ENABLED 有効 (使用å¯èƒ½)
+CM_VLAN_DISABLED 無効 (使用ä¸å¯)
+CM_DELETE_ACCOUNT_MSG 接続設定 "%s" を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+CM_ST_ACCOUNT_NAME 接続設定å
+CM_ST_CONNECTED セッション接続状態
+CM_ST_CONNECTED_TRUE 接続完了 (セッション確立済ã¿)
+CM_ST_CONNECTED_FALSE 接続試行中
+CM_ST_CONNECTING VPN サーãƒãƒ¼ã«æŽ¥ç¶šé–‹å§‹ä¸­
+CM_ST_NEGOTIATION ãƒã‚´ã‚·ã‚¨ãƒ¼ã‚·ãƒ§ãƒ³ä¸­
+CM_ST_AUTH ユーザーèªè¨¼ä¸­
+CM_ST_ESTABLISHED コãƒã‚¯ã‚·ãƒ§ãƒ³ç¢ºç«‹æ¸ˆã¿
+CM_ST_RETRY å†è©¦è¡Œä¸­
+CM_ST_IDLE アイドル状態
+CM_ST_SERVER_NAME サーãƒãƒ¼å
+CM_ST_SERVER_PORT ãƒãƒ¼ãƒˆç•ªå·
+CM_ST_PORT_TCP TCP ãƒãƒ¼ãƒˆ %u
+CM_ST_SERVER_P_NAME サーãƒãƒ¼è£½å“å
+CM_ST_SERVER_P_VER サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+CM_ST_SERVER_P_BUILD サーãƒãƒ¼ãƒ“ルド番å·
+CM_ST_START_TIME 接続開始時刻
+CM_ST_FIRST_ESTAB_TIME åˆå›žã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ç¢ºç«‹æ™‚刻
+CM_ST_NONE ï¼
+CM_ST_CURR_ESTAB_TIME ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ç¢ºç«‹æ™‚刻
+CM_ST_NUM_ESTABLISHED セッション確立回数
+CM_ST_NUM_STR %u 回
+CM_ST_HALF_CONNECTION åŠäºŒé‡ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãƒ¢ãƒ¼ãƒ‰
+CM_ST_HALF_TRUE ã¯ã„ (åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰)
+CM_ST_HALF_FALSE ã„ã„㈠(全二é‡ãƒ¢ãƒ¼ãƒ‰)
+CM_ST_QOS VoIP / QoS 対応機能
+CM_ST_QOS_TRUE 有効 (使用中)
+CM_ST_QOS_FALSE 無効
+CM_ST_NUM_TCP TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+CM_ST_NUM_TCP_UPLOAD ä¸Šã‚Šæ–¹å‘ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+CM_ST_NUM_TCP_DOWNLOAD ä¸‹ã‚Šæ–¹å‘ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+CM_ST_MAX_TCP TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°æœ€å¤§å€¤
+CM_ST_VLAN_ID VLAN ID
+CM_ST_NO_VLAN ï¼
+CM_ST_USE_ENCRYPT æš—å·åŒ–ã®ä½¿ç”¨
+CM_ST_USE_ENCRYPT_TRUE ã¯ã„ (æš—å·åŒ–アルゴリズム: %S)
+CM_ST_USE_ENCRYPT_TRUE2 ã¯ã„
+CM_ST_USE_ENCRYPT_FALSE ã„ã„㈠(æš—å·åŒ–ãªã—)
+CM_ST_USE_COMPRESS 圧縮ã®ä½¿ç”¨
+CM_ST_UDP_ACCEL_ENABLED UDP 高速化機能をサãƒãƒ¼ãƒˆ
+CM_ST_UDP_ACCEL_USING UDP 高速化機能を使用中
+CM_ST_RUDP TCP over UDP (NAT Traversal)
+CM_ST_UNDERLAY_PROTOCOL 物ç†é€šä¿¡ã«ä½¿ç”¨ä¸­ã®ãƒ—ロトコル
+CM_ST_COMPRESS_TRUE ã¯ã„ (ç´„ %u %%)
+CM_ST_COMPRESS_FALSE ã„ã„㈠(圧縮無ã—)
+CM_ST_SESSION_NAME セッションå
+CM_ST_CONNECTION_NAME コãƒã‚¯ã‚·ãƒ§ãƒ³å
+CM_ST_SESSION_KEY セッションキー (160bit)
+CM_ST_BRIDGE_MODE ブリッジ / ルータモード
+CM_ST_MONITOR_MODE モニタリングモード
+CM_ST_YES ã¯ã„
+CM_ST_NO ã„ã„ãˆ
+CM_ST_SEND_SIZE é€ä¿¡ãƒ‡ãƒ¼ã‚¿ã‚µã‚¤ã‚º
+CM_ST_RECV_SIZE å—信データサイズ
+
+CM_ST_SEND_UCAST_NUM é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆãƒ‘ケット数
+CM_ST_SEND_UCAST_SIZE é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆåˆè¨ˆã‚µã‚¤ã‚º
+CM_ST_SEND_BCAST_NUM é€ä¿¡ãƒ–ロードキャストパケット数
+CM_ST_SEND_BCAST_SIZE é€ä¿¡ãƒ–ロードキャストåˆè¨ˆã‚µã‚¤ã‚º
+
+CM_ST_RECV_UCAST_NUM å—信ユニキャストパケット数
+CM_ST_RECV_UCAST_SIZE å—信ユニキャストåˆè¨ˆã‚µã‚¤ã‚º
+CM_ST_RECV_BCAST_NUM å—信ブロードキャストパケット数
+CM_ST_RECV_BCAST_SIZE å—信ブロードキャストåˆè¨ˆã‚µã‚¤ã‚º
+
+CM_ST_NUM_PACKET_STR %S パケット
+CM_ST_SIZE_BYTE_STR %S ãƒã‚¤ãƒˆ
+
+CM_NEW_ICON æ–°ã—ã„接続設定ã®ä½œæˆ
+CM_VGC_ICON VPN Gate 公開 VPN 中継サーãƒãƒ¼
+CM_VGC_LINK VPN Gate 学術実験 Web サイト
+CM_ST_TITLE %s ã®æŽ¥ç¶šçŠ¶æ³
+CM_ST_COLUMN_1 é …ç›®å
+CM_ST_COLUMN_2 状æ³
+CM_NEW_ACCOUNT_NAME_1 æ–°ã—ã„接続
+CM_NEW_ACCOUNT_NAME_2 æ–°ã—ã„接続 (%u)
+CM_ACCOUNT_TITLE_1 æ–°ã—ã„接続設定ã®ãƒ—ロパティ
+CM_ACCOUNT_TITLE_2 %s ã®ãƒ—ロパティ
+CM_SERVER_CERT_1 固有証明書ã®ç™»éŒ²(&R)
+CM_SERVER_CERT_2 固有証明書ã®å‰Šé™¤(&0)
+CM_CLIENT_CERT_1 クライアント証明書ã®æŒ‡å®š(&8)
+CM_CLIENT_CERT_2 クライアント証明書ã®å‰Šé™¤(&8)
+CM_CERT_INFO 発行先: %s\r\n発行者: %s\r\n有効期é™: %s
+CM_NO_CERT ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CM_NO_SECURE ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰å†…ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã¨ç§˜å¯†éµã‚’指定ã—ã¦ãã ã•ã„。
+CM_CERT_SECURE_INFO 証明書: "%S"\r\n秘密éµ: "%S"
+CM_SELECT_SECURE_DEVICE 使用スマートカードé¸æŠž(&J)
+CM_SELECT_CERT_INCARD 証明書ã¨ç§˜å¯†éµã®æŒ‡å®š(&7)
+CM_VIEW_CLIENT_CERT クライアント証明書ã®è¡¨ç¤º(&7)
+CM_NO_VLAN æ–°ã—ã„接続設定を作æˆã™ã‚‹å‰ã«ã€ä»®æƒ³ LAN カードを作æˆã—ã¦ãã ã•ã„。\r\n\r\n仮想 LAN カードを作æˆã—ã¾ã™ã‹?
+CM_NO_VLAN_2 VPN Server ã«æŽ¥ç¶šã™ã‚‹å‰ã«ã€ä»®æƒ³ LAN カードを作æˆã—ã¦ãã ã•ã„。\r\n\r\n仮想 LAN カードを作æˆã—ã¾ã™ã‹?
+CM_VLAN_REMOTE_ERROR 仮想 LAN カードã¯ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰ä½œæˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。\r\n\rVPN Client サービスãŒå‹•ä½œã—ã¦ã„るローカルコンピュータ上㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€ä»®æƒ³ LAN カードをインストールã—ã¦ãã ã•ã„。
+CM_9X_VLAN_INSTALL æ–°ã—ã„仮想 LAN カードを作æˆã—ã¾ã™ã€‚\r\n\r\n仮想 LAN カードを作æˆã—ãŸå ´åˆã€ç›´ã¡ã« Windows ã‚’å†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\nã¾ãŸã€ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä¸­ã« Windows ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ« CD-ROM ãŒå¿…è¦ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nVPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ä»¥å¤–ã®ã™ã¹ã¦ã®ä½œæ¥­ä¸­ã®ã‚¢ãƒ—リケーションを終了ã—ã€Windows ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ« CD-ROM を用æ„ã—ã¦ã‹ã‚‰ã€[OK] をクリックã—ã¦ãã ã•ã„。\r\n[OK] をクリックã™ã‚‹ã¨ã€ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒé–‹å§‹ã•ã‚Œã¾ã™ã€‚ãã®å¾Œã€è‡ªå‹•çš„ã« Windows ãŒå†èµ·å‹•ã—ã¾ã™ã€‚
+CM_9X_VLAN_ME_MESSAGE 仮想 LAN カードを作æˆã—ã¾ã—ãŸã€‚[OK] をクリックã™ã‚‹ã¨ã€ã‚³ãƒ³ãƒ”ュータを自動的ã«å†èµ·å‹•ã—ã¾ã™ã€‚\r\n\r\nå†èµ·å‹•å¾Œã€æ–°ã—ã„デãƒã‚¤ã‚¹ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\nãã®å ´åˆã¯ã€[次ã¸] を数回クリックã—ã¦ãƒ‰ãƒ©ã‚¤ãƒã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’完了ã•ã›ã¦ãã ã•ã„。
+CM_9X_VLAN_UNINSTALL 仮想 LAN カードã®å‰Šé™¤ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ãƒ—ロパティã‹ã‚‰è¡Œã£ã¦ãã ã•ã„。\r\n\r\nãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ãƒ—ロパティ画é¢ã‚’表示ã—ã¾ã™ã‹?
+CM_PORT_1 8888 (PX-VPN ãƒãƒ¼ãƒˆ)
+CM_PORT_2 443 (HTTPS ãƒãƒ¼ãƒˆ)
+CM_PORT_3 992 (telnets ãƒãƒ¼ãƒˆ)
+CM_PORT_4 5555 (SE-VPN ãƒãƒ¼ãƒˆ)
+CM_RETRY_INTERVAL_ERROR å†æŽ¥ç¶šé–“隔㯠5 秒以上ã«è¨­å®šã—ã¦ãã ã•ã„。
+CM_DELETE_CLIENT_CERT 設定ã•ã‚Œã¦ã„るクライアント証明書を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+CM_DELETE_SERVER_CERT 設定ã•ã‚Œã¦ã„るサーãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+CM_SET_STARTUP 接続設定 "%s" をスタートアップ接続ã«è¨­å®šã—ã¾ã—ãŸã€‚\r\n\r\nã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ¬¡å›žã®ã‚³ãƒ³ãƒ”ュータ起動時ã«è‡ªå‹•çš„ã«æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚\r\n(Windows ã‚’ãŠä½¿ã„ã®å ´åˆã¯ã€Windows ã®èµ·å‹•ç›´å¾Œã«æŽ¥ç¶šãŒé–‹å§‹ã•ã‚Œã¾ã™ã€‚\r\nユーザーãŒãƒ­ã‚°ã‚ªãƒ³ã™ã‚‹å‰ã«ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚)
+CM_REMOVE_STARTUP 接続設定 "%s" ã®ã‚¹ã‚¿ãƒ¼ãƒˆã‚¢ãƒƒãƒ—接続属性を解除ã—ã¾ã™ã‹?
+CM_NO_DISCONNECT_SPAN TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ã‚’設定ã—ã¦ãã ã•ã„。
+CM_HALF_MSG åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’使用ã™ã‚‹å ´åˆã¯ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã¯ 2 以上ã«è¨­å®šã—ã¦ãã ã•ã„。
+CM_TOO_SMALL_INTERVAL TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“隔㯠1 秒以上ã«è¨­å®šã—ã¦ãã ã•ã„。
+CM_DELETE_VLAN 仮想 LAN カード "%s" を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+CM_COPY_NAME_1 コピー ~ %s
+CM_COPY_NAME_2 コピー (%u) ~ %s
+CM_IMPORT_NAME_1 %s
+CM_IMPORT_NAME_2 %s (%u)
+CM_CERT_COLUMN_1 発行先
+CM_CERT_COLUMN_2 発行者
+CM_CERT_COLUMN_3 有効期é™
+CM_CERT_DELETE_MSG ã“ã®è¨¼æ˜Žæ›¸ã‚’リストã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã‹?
+CM_PASSWORD_SET パスワードを設定ã—ã¾ã—ãŸã€‚
+CM_PASSWORD_REMOVE パスワード設定を解除ã—ã¾ã—ãŸã€‚
+CM_UNDER_CONSTRUCTION 未完æˆã§ã™ã€‚
+CM_CURRENT_ACTIVE 接続設定 "%s" ã®è¨­å®šã‚’ä¿å­˜ã—ã¾ã—ãŸãŒã€ç¾åœ¨ã“ã®æŽ¥ç¶šè¨­å®šã¯ VPN Server ã«æŽ¥ç¶šä¸­ã®ãŸã‚ã€è¨­å®šå†…容ã¯æ¬¡å›žæŽ¥ç¶šæ™‚ã¾ã§é©ç”¨ã•ã‚Œã¾ã›ã‚“。
+CM_DISCONNECT_ALL ç¾åœ¨æŽ¥ç¶šä¸­ã® %u 個ã®æŽ¥ç¶šè¨­å®šã‚’ã™ã¹ã¦åˆ‡æ–­ã—ã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+CM_HTTPS_MSG HTTP プロキシサーãƒãƒ¼çµŒç”±ã§æŽ¥ç¶šã™ã‚‹ã“ã¨ã‚’é¸æŠžã—ã¾ã—ãŸã€‚\r\n\r\n多ãã® HTTP プロキシサーãƒãƒ¼ã¯ã€ä»»æ„ã® TCP ãƒãƒ¼ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¦ã„ã¾ã›ã‚“。\r\nVPN Client ã¯ã€HTTP プロキシサーãƒãƒ¼ã‚’経由ã—㦠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã€HTTPS (HTTP over SSL) 通信を行ã£ã¦æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nã“ã®å ´åˆã¯ã€æŽ¥ç¶šå…ˆ VPN Server ã®ãƒãƒ¼ãƒˆç•ªå·ã‚’ 443 (HTTPS ãƒãƒ¼ãƒˆ) ã«è¨­å®šã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚\r\n(ä»–ã®ãƒãƒ¼ãƒˆç•ªå·ã®å ´åˆã€HTTP プロキシサーãƒãƒ¼ã‚’経由ã™ã‚‹ã“ã¨ãŒã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n 接続先 VPN Server ã§ãƒãƒ¼ãƒˆ 443 ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。)\r\n\r\n詳ã—ã„情報ã«ã¤ã„ã¦ã¯ã€çµŒç”±ã—よã†ã¨ã—ã¦ã„ã‚‹ HTTP プロキシサーãƒãƒ¼ã®ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。\r\n\r\n接続先 VPN Server ã®ãƒãƒ¼ãƒˆç•ªå·æŒ‡å®šã‚’ 443 (HTTPS ãƒãƒ¼ãƒˆ) ã«å¤‰æ›´ã—ã¾ã™ã‹?
+CM_REMOTE_WARNING [リモート管ç†ã®è¨­å®š] を許å¯ã—ãªã„設定ã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nç¾åœ¨ã€VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã¯ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータ "%S" ã«æŽ¥ç¶šã—ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ上㮠VPN Client サービスを制御ã—ã¦ã„ã¾ã™ã€‚\r\nリモート接続を無効ã«ã—ãŸå ´åˆã€ã‚³ãƒ³ãƒ”ュータ "%S" ã® VPN Client サービスã«ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã«ã‚ˆã£ã¦æŽ¥ç¶šã—ã€åˆ¶å¾¡ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚\r\n\r\nリモート管ç†ã‚’無効ã«ã—ã¾ã™ã‹?
+CM_KEEP_INTERVAL_MSG [パケットé€å‡ºé–“éš”] ã«ã¯ %u 秒ã‹ã‚‰ %u 秒ã¾ã§ã®å€¤ã‚’設定ã—ã¦ãã ã•ã„。
+CM_REMOTE_TITLE 別ã®ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Client サービスを VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‹ã‚‰æŽ¥ç¶šã—ã€ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n(ãŸã ã—ã€æŽ¥ç¶šå…ˆã®ã‚³ãƒ³ãƒ”ュータ㮠VPN Client サービスãŒãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã‚’許å¯ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚)
+CM_DESKTOP_LOCAL_PC ã“ã®ã‚³ãƒ³ãƒ”ュータ
+CM_DESKTOP_REMOTE_PC コンピュータ %S
+CM_DESKTOP_MSG_LOCAL_TS ターミナルサービス (リモートデスクトップ) 機能
+CM_DESKTOP_MSG_LOCAL_SW ユーザーã®åˆ‡ã‚Šæ›¿ãˆæ©Ÿèƒ½
+CM_DESKTOP_MSG_LOCAL_1 ç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã¯%sãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ãŠã‚Šã€è¤‡æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåŒæ™‚ã«ãƒ­ã‚°ã‚ªãƒ³ã§ãる環境ã«ãªã£ã¦ã„ã¾ã™ã€‚ã“ã®å ´åˆã€VPN Client ãŒè¡¨ç¤ºã™ã‚‹é€²è¡ŒçŠ¶æ³ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚„エラーメッセージãªã©ã¯ã€ã€Œã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã€ã¨å‘¼ã°ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸Šã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CM_DESKTOP_MSG_LOCAL_21 ç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ 「セッション ID: 0ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ %s〠ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ã¾ã™ãŒã€ã‚ãªãŸã¯ã‚»ãƒƒã‚·ãƒ§ãƒ³ %u 㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¦ã„ã‚‹ãŸã‚ã€VPN Client ãŒè¡¨ç¤ºã™ã‚‹é€²è¡ŒçŠ¶æ³ã‚„エラーãªã©ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+CM_DESKTOP_MSG_LOCAL_22 ç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ (セッション ID: 0) ã«ã¯èª°ã‚‚ログオンã—ã¦ãŠã‚‰ãšã€ã‚ãªãŸã¯ã‚»ãƒƒã‚·ãƒ§ãƒ³ %u 㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¦ã„ã‚‹ãŸã‚ã€VPN Client ãŒè¡¨ç¤ºã™ã‚‹é€²è¡ŒçŠ¶æ³ã‚„エラーãªã©ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+CM_DESKTOP_MSG_LOCAL_31 コンピュータã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ (セッション ID: 0ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ %s) を表示ã—ã¦ã‹ã‚‰ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³å†…㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€æŽ¥ç¶šè¨­å®š "%s" ã¸ã®æŽ¥ç¶šã‚’開始ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚ã“ã®ã¾ã¾æŽ¥ç¶šå‡¦ç†ã‚’開始ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ãŒã€ãã®å ´åˆã¯é€”中ã§è¡¨ç¤ºã•ã‚Œã‚‹å¯èƒ½æ€§ã®ã‚る進行状æ³ã‚„エラー メッセージをã™ã¹ã¦ç¢ºèªã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+CM_DESKTOP_MSG_LOCAL_32 一度ログオフã—ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ­ã‚°ã‚ªãƒ³ã—ç›´ã—ã¦ã‹ã‚‰ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³å†…㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€æŽ¥ç¶šè¨­å®š "%s" ã¸ã®æŽ¥ç¶šã‚’開始ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚ã“ã®ã¾ã¾æŽ¥ç¶šå‡¦ç†ã‚’開始ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ãŒã€ãã®å ´åˆã¯é€”中ã§è¡¨ç¤ºã•ã‚Œã‚‹å¯èƒ½æ€§ã®ã‚る進行状æ³ã‚„エラー メッセージをã™ã¹ã¦ç¢ºèªã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+CM_DESKTOP_MSG_REMOTE_1 ç¾åœ¨ã€ã‚³ãƒ³ãƒ”ュータ %S 上㮠VPN Client ã«å¯¾ã—ã¦ãƒªãƒ¢ãƒ¼ãƒˆæŽ¥ç¶šã—ã¦æ“作を行ã£ã¦ã„ã‚‹ãŸã‚ã€æŽ¥ç¶šè¨­å®šã¸ã® VPN 接続中㫠VPN Client ãŒé€²è¡ŒçŠ¶æ³ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚„エラーメッセージãªã©ã‚’表示ã—ãŸå ´åˆã€ãã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’ç¾åœ¨ã®ç”»é¢ã§ç¢ºèªã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CM_DESKTOP_MSG_REMOTE_2 VPN Client ãŒè¡¨ç¤ºã™ã‚‹é€²è¡ŒçŠ¶æ³ã‚„エラーãªã©ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’ã™ã¹ã¦ç¢ºèªã™ã‚‹ã«ã¯ã€ã‚³ãƒ³ãƒ”ュータ %S ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã€ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ (デスクトップ) を表示ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CM_DESKTOP_MSG_REMOTE_3 コンピュータ %S ã«ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¨ã—ã¦ç›´æŽ¥ãƒ­ãƒ¼ã‚«ãƒ«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã‹ã‚‰ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³å†…㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€æŽ¥ç¶šè¨­å®š "%s" ã¸ã®æŽ¥ç¶šã‚’開始ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚ã“ã®ã¾ã¾æŽ¥ç¶šå‡¦ç†ã‚’開始ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ãŒã€ãã®å ´åˆã¯é€”中ã§è¡¨ç¤ºã•ã‚Œã‚‹å¯èƒ½æ€§ã®ã‚る進行状æ³ã‚„エラー メッセージをã™ã¹ã¦ç¢ºèªã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+CM_STOP_INST_VLAN_1 ã“ã®ã‚³ãƒ³ãƒ”ュータã§ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã†ã«ã¯ã€ã€Œã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã€ 上㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã¯%sãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ãŠã‚Šã€ç¾åœ¨ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã¯ãªãリモートセッション (セッション ID: %u) ã¨ã—ã¦ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„ã¾ã™ã€‚\r\n仮想 LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã†ã«ã¯ã€ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ (セッション ID: %uã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ %s ãŒãƒ­ã‚°ã‚ªãƒ³ä¸­) 上㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nユーザーã®åˆ‡ã‚Šæ›¿ãˆæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã‹ã€ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—ã® /console スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã‹ã€ã¾ãŸã¯ã‚³ãƒ³ãƒ”ュータã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ãƒ‡ãƒã‚¤ã‚¹ã‚’使用ã—ã¦ã‚³ãƒ³ãƒ”ュータã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã‹ã‚‰ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã£ã¦ãã ã•ã„。
+CM_STOP_INST_VLAN_2 ã“ã®ã‚³ãƒ³ãƒ”ュータã§ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã†ã«ã¯ã€ã€Œã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã€ 上㧠VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã¯%sãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ãŠã‚Šã€ç¾åœ¨ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã¯ãªãリモートセッション (セッション ID: %u) ã¨ã—ã¦ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„ã¾ã™ã€‚\r\n仮想 LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã†ã«ã¯ã€ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸Šã§ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n(ç¾åœ¨ã€ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ (セッション ID: 0) ã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„ã¾ã›ã‚“。)\r\n\r\nユーザーã®åˆ‡ã‚Šæ›¿ãˆæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã‹ã€ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—ã® /console スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã‹ã€ã¾ãŸã¯ã‚³ãƒ³ãƒ”ュータã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ãƒ‡ãƒã‚¤ã‚¹ã‚’使用ã—ã¦ã‚³ãƒ³ãƒ”ュータã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã‹ã‚‰ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã£ã¦ãã ã•ã„。
+CM_SHORTCUT_DESKTOP_MSG 接続設定ã¸ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã‚’使用ã—ã¦æŽ¥ç¶šã‚’開始ã™ã‚‹ã«ã¯ã€ã€Œã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã€ä¸Šã§ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nç¾åœ¨ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã¯ãªãリモートセッション (セッション ID: %u) ã¨ã—ã¦ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„ã¾ã™ã€‚
+CM_HTTP_PROXY_WARNING [HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š] ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n多ãã®å ´åˆã€HTTP プロキシサーãƒãƒ¼ã¯æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã®ãƒãƒ¼ãƒˆç•ªå·ã¨ã—ã¦ã€HTTP プロトコル (TCP ãƒãƒ¼ãƒˆ 80 番) ãŠã‚ˆã³ HTTPS プロトコル (TCP ãƒãƒ¼ãƒˆ 443 番) ã® 2 種類㮠TCP ãƒãƒ¼ãƒˆã«å¯¾ã™ã‚‹æŽ¥ç¶šã®ã¿ã‚’許å¯ã—ã¦ã„ã¾ã™ã€‚\r\n(プロキシサーãƒãƒ¼ãŒä»»æ„ã® TCP ãƒãƒ¼ãƒˆã«å¯¾ã™ã‚‹æŽ¥ç¶šã‚’許å¯ã—ã¦ã„ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚)\r\n\r\nHTTP ãƒãƒ¼ãƒˆã¾ãŸã¯ HTTPS ãƒãƒ¼ãƒˆä»¥å¤–ã¸ã®ã‚µãƒ¼ãƒãƒ¼ ãƒãƒ¼ãƒˆã¸ã®æŽ¥ç¶šã‚’ç¦æ­¢ã—ã¦ã„ã‚‹ HTTP プロキシサーãƒãƒ¼ã‚’経由ã—㦠VPN 接続を行ã†å ´åˆã¯ã€æŽ¥ç¶šå…ˆ VPN Server ã®ãƒãƒ¼ãƒˆç•ªå·ã¯ 443 (HTTPS プロトコル) ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ãŒ 80 番ã¾ãŸã¯ 443 番ãƒãƒ¼ãƒˆä»¥å¤–ã¸ã®æŽ¥ç¶šã‚’許å¯ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹ã«ã¯ã€HTTP プロキシサーãƒãƒ¼ã®ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。\r\n\r\nç¾åœ¨ã€æŽ¥ç¶šå…ˆ VPN Server ã®ãƒãƒ¼ãƒˆç•ªå·ã¯ %d ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™ãŒã€ãƒãƒ¼ãƒˆç•ªå·ã‚’ 443 番 (HTTPS プロトコル) ã«å¤‰æ›´ã—ã¾ã™ã‹?\r\n(接続ã™ã‚‹ VPN Server ã®ãƒãƒ¼ãƒˆ 443 ã«ãŠã„ã¦æŽ¥ç¶šã‚’å¾…ã¡å—ã‘る設定ã«ãªã£ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚)\r\nä¸æ˜Žãªå ´åˆã¯ã€ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+CM_PASSWORD_CHANGED パスワードãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚
+CM_ACCOUNT_SETTING_FILE 接続設定ファイル (*.VPN)|*.vpn|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+CM_ACCOUNT_SAVE_TITLE エクスãƒãƒ¼ãƒˆå…ˆã®æŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«åを入力ã—ã¦ãã ã•ã„。
+CM_ACCOUNT_OPEN_TITLE インãƒãƒ¼ãƒˆã™ã‚‹æŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+CM_ACCOUNT_FILE_BANNER # VPN Client 接続設定ファイル\r\n# \r\n# ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã«ã‚ˆã£ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã•ã‚ŒãŸã‚‚ã®ã§ã™ã€‚\r\n# ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容ã¯ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ã§ç·¨é›†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n# \r\n# ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã¨ã€ã™ãã«ä½¿ç”¨ã™ã‚‹\r\n# ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\n
+CM_FAILED_TO_OPEN_FILE ファイルを開ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+CM_FAILED_TO_SAVE_FILE ファイルをä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+CM_ACCOUNT_PARSE_FAILED 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰æŽ¥ç¶šè¨­å®šã‚’読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚\r\nファイルã®å†…容を確èªã—ã¦ãã ã•ã„。
+CM_ACCOUNT_MSG_SENSITIVE ã“ã®æŽ¥ç¶šè¨­å®šã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワード情報ãŒä¿å­˜ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\nユーザーåã¨ãƒ‘スワード情報を接続設定ファイルã‹ã‚‰æ¶ˆåŽ»ã—ã¾ã™ã‹?\r\n\r\n[ã¯ã„] をクリックã™ã‚‹ã¨ã€æŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰èªè¨¼æƒ…報を削除ã—ã¾ã™ã€‚\r\nã“ã®å ´åˆã¯ã€æŽ¥ç¶šè¨­å®šã‚’インãƒãƒ¼ãƒˆã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ VPN 接続時ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードã®å…¥åŠ›ã‚’求ã‚られã¾ã™ã€‚\r\n\r\n[ã„ã„ãˆ] をクリックã™ã‚‹ã¨ã€æŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã«èªè¨¼æƒ…報を格ç´ã—ãŸã¾ã¾ã«ã—ã¾ã™ã€‚
+CM_SHORTCUT_FILE ショートカットファイル|*.lnk
+CM_SHORTCUT_SAVE_TITLE ショートカットファイルåを入力ã—ã¦ãã ã•ã„。
+CM_SHORTCUT_UNSUPPORTED ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Client ã§ã¯ã€æŽ¥ç¶šã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆæ©Ÿèƒ½ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。\r\næ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã—ã¦ãã ã•ã„。
+CM_SHORTCUT_COMMENT 接続設定「%sã€ã‚’使用ã—㦠VPN Server ã«æŽ¥ç¶šã—ã¾ã™ã€‚
+CM_SHORTCUT_ERROR ショートカットã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CM_VPN_FILE_CLICKED 接続設定ファイルをインãƒãƒ¼ãƒˆã—ã¾ã™ã‹?
+CM_VPN_FILE_IMPORT_NG 接続設定ファイルをインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。VPN Client ã®è¨­å®šãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚
+CM_VLAN_INSTALLING ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+CM_SECURE_MUST_LOCAL ç¾åœ¨ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータ㮠VPN Client サービスã«æŽ¥ç¶šã—ã¦ç®¡ç†ã—ã¦ã„ã‚‹ãŸã‚ã€ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®è¨­å®šã‚’è¡Œã†ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CM_DETAIL_MODE_LINK_STR カスケード接続ã§ã¯ã€å¸¸ã« [ブリッジ / ルータモードã§æŽ¥ç¶š] ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚
+CM_TRAY_INITING SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+CM_TRAY_NOT_CONNECTED SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£\r\n接続ã—ã¦ã„ã¾ã›ã‚“
+CM_TRAY_CONNECTED_0 SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£\r\n%u 個ã®ã‚µãƒ¼ãƒãƒ¼ã¨ã®æŽ¥ç¶šãŒå®Œäº†ã—ã€%u 個ã®ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã‚’試行ã—ã¦ã„ã¾ã™
+CM_TRAY_CONNECTED_1 SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£\r\n%u 個ã®ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã‚’試行ã—ã¦ã„ã¾ã™
+CM_TRAY_CONNECTED_2 SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£\r\n%u 個ã®ã‚µãƒ¼ãƒãƒ¼ã¨æŽ¥ç¶šãŒå®Œäº†ã—ã¦ã„ã¾ã™
+CM_TRAY_MENU_1_SHOW 接続マãƒãƒ¼ã‚¸ãƒ£ã‚’表示ã™ã‚‹(&S)
+CM_TRAY_MENU_1_HIDE 接続マãƒãƒ¼ã‚¸ãƒ£ã‚’é–‰ã˜ã‚‹(&O)
+CM_TRAY_MENU_2_QUIT 接続マãƒãƒ¼ã‚¸ãƒ£ãƒ—ログラムã®çµ‚了(&X)
+CM_TRAY_MENU_CONNECT VPN 接続を開始(&C)
+CM_TRAY_MENU_DISCONNECT VPN 接続を切断(&D)
+CM_TRAY_MENU_STATUS 接続状態を表示(&I)
+CM_TRAY_MENU_DISCONNECT_ALL ã™ã¹ã¦ã®æŽ¥ç¶šã‚’切断(&A)
+CM_TRAY_MENU_NEW 接続設定ã®æ–°è¦ä½œæˆ(&N)...
+CM_TRAY_MENU_RECENT 最近接続ã—㟠VPN サーãƒãƒ¼(&Y)
+CM_TRAY_MENU_TRAFFIC 通信スループット測定ツール(&R)...
+CM_TRAY_MENU_NETIF ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ‡ãƒã‚¤ã‚¹ã®çŠ¶æ…‹ã‚’表示(&D)...
+CM_TRAY_MENU_ABOUT 接続マãƒãƒ¼ã‚¸ãƒ£ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)...
+CM_TRAY_MENU_SETTING 動作モードã®å¤‰æ›´(&M)...
+CM_TRAY_MENU_CANCEL ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’é–‰ã˜ã‚‹
+CM_EXIT_MESSAGE VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ãƒ—ログラムを終了ã—ã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+CM_IMPORT_MESSAGE ファイル "%S" ã‹ã‚‰æŽ¥ç¶šè¨­å®š "%s" をインãƒãƒ¼ãƒˆã—ã¾ã—ãŸã€‚
+CM_VLAN_CREATING æ–°ã—ã„ VPN 用仮想 LAN カードを作æˆã—ã€Windows ã«è¿½åŠ ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nã“ã®å‡¦ç†ã«ã¯æ•°ç§’ã‹ã‚‰æ•°å秒ã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\nã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...\r\n\r\n(仮想 LAN カードã®ä½œæˆä¸­ã¯ä»–ã®æ“作ã¯ã—ãªã„ã§ãã ã•ã„。)
+CM_SETTING_PASSWORD 設定ロック機能ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚解除ã™ã‚‹ã«ã¯ãƒ‘スワードを入力ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CM_EASY_MODE_NOT_ON_REMOTE リモートコンピュータ㮠VPN Client ã®å‹•ä½œãƒ¢ãƒ¼ãƒ‰ãŒ [簡易モード] ã®ãŸã‚ã€æŽ¥ç¶šã§ãã¾ã›ã‚“。
+CM_EASY_CONNECT_BUTTON_1 VPN 接続を開始(&C)
+CM_EASY_CONNECT_BUTTON_2 切断(&D)
+CM_EASY_ACCOUNT_WARNING 設定ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€[経由ã™ã‚‹ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®š]ã€[ユーザーèªè¨¼] ãŠã‚ˆã³ [使用ã™ã‚‹ä»®æƒ³ LAN カード] ã®ã¿ãŒå¤‰æ›´ã§ãã¾ã™ã€‚
+CM_EASY_INFO_1 VPN 接続先をé¸æŠžã—ã¦ãã ã•ã„。
+CM_EASY_INFO_2 [VPN 接続を開始] ボタンをクリックã™ã‚‹ã¨ VPN 接続を開始ã—ã¾ã™ã€‚
+CM_EASY_INFO_3 VPN 接続中ã§ã™ã€‚[切断] ボタンã§åˆ‡æ–­ã§ãã¾ã™ã€‚
+CM_EXT_VOICE_MSG 拡張音声ガイドã®éŸ³å£°ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®å†…容ã¯ã€ä¸€éƒ¨æ­£å¸¸ã«å†ç”Ÿã•ã‚Œãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n拡張音声ガイドを有効ã«ã—ã¾ã™ã‹?
+CM_EASY_TITLE VPN クライアント簡易接続マãƒãƒ¼ã‚¸ãƒ£
+CM_EASY_CONNECTED VPN 接続ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+CM_EASY_CONNECTING VPN 接続ã®å®Ÿè¡Œä¸­...
+CM_PROXY_FROM_IE ç¾åœ¨ã® Internet Explorer ã®ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®šã‚’読ã¿è¾¼ã¿ã¾ã—ãŸã€‚
+CM_TRAY_ICON_RESTORE タスクトレイã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’消去ã—ã¾ã—ãŸã€‚\r\n\r\nアイコンを復活ã•ã›ã‚‹ã«ã¯ã€VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€é€šå¸¸ãƒ¢ãƒ¼ãƒ‰ã§ [表示] メニュー㮠[タスクトレイã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’表示] をクリックã—ã¦ãã ã•ã„。
+CM_WOULDYOULOAD_IE_PROXY ç¾åœ¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㯠Internet Explorer ã®è¨­å®šã§ãƒ—ロキシサーãƒãƒ¼ "%S" を使用ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n今回作æˆã™ã‚‹æ–°ã—ã„接続設定ã§ã¯ã€Internet Explorer ã®ãƒ—ロキシサーãƒãƒ¼è¨­å®šã‚’用ã„㦠VPN 接続ã™ã‚‹ã‚ˆã†ã«ã—ã¾ã™ã‹?\r\n\r\n[ã¯ã„] をクリックã™ã‚‹ã¨ã€Internet Explorer ã®ãƒ—ロキシサーãƒãƒ¼è¨­å®šã‚’使用ã—ã¾ã™ã€‚\r\n[ã„ã„ãˆ] をクリックã™ã‚‹ã¨ã€ãƒ—ロキシサーãƒãƒ¼ã‚’使用ã›ãšã«ç›´æŽ¥ VPN 接続ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚\r\nã“ã®è¨­å®šã¯ã€ã„ã¤ã§ã‚‚接続設定ã®ãƒ—ロパティ画é¢ã‹ã‚‰å¤‰æ›´ã§ãã¾ã™ã€‚
+CM_MSG_TITLE VPN サーãƒãƒ¼ "%S" (仮想 HUB: "%S")
+CM_JUMPLIST_RCCONNECT 最近ã®æŽ¥ç¶šå…ˆ
+CM_VPNGATE_MESSAGE VPN Gate 学術実験プロジェクト㮠Web サイトã«ã¯ã€å…¬é–‹ VPN 中継サーãƒãƒ¼ã®ä¸€è¦§ãŒå…¬é–‹ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\nã“れら㮠VPN サーãƒãƒ¼ã«ã¯ã€èª°ã§ã‚‚ユーザー登録ãªã—㧠VPN 接続ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nVPN Gate 学術実験プロジェクト㯠SoftEther VPN ã®ä¸€éƒ¨ã§ã¯ã‚ã‚Šã¾ã›ã‚“。\r\nã“ã®ã‚¢ã‚¤ã‚³ãƒ³ã¯ http://www.vpngate.net/ ã¸ã®ãƒªãƒ³ã‚¯ã‚’æä¾›ã—ã¦ã„ã‚‹ã«éŽãŽã¾ã›ã‚“。\r\nVPN Gate ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ã¯ã€VPN Gate Plugin をインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nhttp://www.vpngate.net/ (筑波大学ã«ãŠã‘る学術実験サイト) ã‚’é–‹ãã¾ã™ã‹?
+
+
+# VPN Gate Service 関係
+VGC_COLUMN_0 DDNS å
+VGC_COLUMN_1 IP アドレス (ホストå)
+VGC_COLUMN_2 国・地域
+VGC_COLUMN_3 起動時間
+VGC_COLUMN_4 VPN 接続数
+VGC_COLUMN_5 回線速度
+VGC_COLUMN_6 Ping (Google, SE)
+VGC_COLUMN_7 SSL-VPN (TCP)
+VGC_COLUMN_8 UDP サãƒãƒ¼ãƒˆ
+VGC_COLUMN_9 ログä¿å­˜ãƒãƒªã‚·ãƒ¼
+VGC_COLUMN_10 ç´¯ç©é€šä¿¡é‡
+VGC_COLUMN_11 ç´¯ç©ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°
+VGC_COLUMN_12 é‹å–¶è€…
+VGC_COLUMN_13 é‹å–¶è€…ã«ã‚ˆã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸
+VGC_COLUMN_14 スコア
+
+VGC_LOG_PERMANENT æ’ä¹…çš„ã«ä¿å­˜
+VGC_LOG_2WEEKS 2 週間ä¿å­˜
+VGC_LOG_NONE ログ無効
+
+VGC_UPTIME_MIN %u 分間
+VGC_UPTIME_HOUR %u 時間
+VGC_UPTIME_DAY %u 日間
+VGC_NUM_VPN %u セッション
+VGC_NUM_LOGIN %S 人
+
+VGC_UDP_AVAILABLE UDP OK
+
+VGC_TITLE VPN Gate プラグインã«é–¢ã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸
+
+VGC_VER_DIFF ã“ã® VPN Gate Client プラグインã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ SoftEther VPN Client ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ç•°ãªã£ã¦ã„ã¾ã™ã€‚\r\n\r\nç¾åœ¨ã® VPN Gate プラグイン: ビルド %u\r\nç¾åœ¨ã® SoftEther VPN Client: ビルド %u\r\n\r\nVPN Gate プラグインã®æœ€æ–°ç‰ˆ (ビルド %u) をダウンロードã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚最新版ã«ã‚¢ãƒƒãƒ—デートã—ãªã„å ´åˆã€VPN 通信エラーやリスト更新エラーãŒç™ºç”Ÿã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—何度も VPN サーãƒãƒ¼ãƒªã‚¹ãƒˆã®æ›´æ–°ã«å¤±æ•—ã™ã‚‹å ´åˆã¯ VPN Gate プラグインã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’アップデートã—ã¦ãã ã•ã„。\r\n\r\n最新版㮠VPN Gate プラグインã®å…¥æ‰‹: http://www.vpngate.net/\r\n(ã‚‚ã—上記サイトã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã§ããªã„å ´åˆã¯ãƒŸãƒ©ãƒ¼ã‚µã‚¤ãƒˆã‚’経由ã—ã¦ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。)\r\n\r\n
+
+VGC_LIST_STR_OK 地çƒä¸Šã« %S å°ã®å…¬é–‹ VPN 中継サーãƒãƒ¼ (%S ã«æ›´æ–°)
+VGC_LIST_STR_OK_2 %S å°ã®ã‚µãƒ¼ãƒãƒ¼ (%S ã«æ›´æ–°) - リストå–得失敗。最新版㮠VPN Gate Client をダウンロードã—ã¦ãã ã•ã„。
+VGC_LIST_STR_NG リストå–得失敗。最新版㮠VPN Gate Client をダウンロードã—ã¦ãã ã•ã„。
+VGC_PROXY_MSG プロキシサーãƒãƒ¼ã‚’経由ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç’°å¢ƒã®å†…部ã‹ã‚‰ã¯ã€ã€ŒSSL-VPN 接続ã€ã§ TCP ãƒãƒ¼ãƒˆ 443 ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ VPN 中継サーãƒãƒ¼ã«ã¯ã‚¢ã‚¯ã‚»ã‚¹ã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+VGC_PROXY_TITLE プロキシサーãƒãƒ¼ã«é–¢ã™ã‚‹ã”注æ„
+
+VGS_NO_HUB_YET メッセージを設定ã™ã‚‹ã«ã¯ã€æœ€åˆã«ã¾ãš VPN Gate サービス コントロールパãƒãƒ«ã§ VPN Gate サービスを有効ã«ã—㦠[OK] をクリックã—ã¦ã‹ã‚‰ã€å†åº¦ã“ã®ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’é–‹ã„ã¦ãã ã•ã„。
+
+VGS_STOP VPN Gate サービスをåœæ­¢ã—ã¾ã™ã€‚\r\n\r\nVPN Gate サービスをåœæ­¢ã™ã‚‹ã¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã¯æ–°ãŸãª VPN 接続をå—付ã‘ãªããªã‚Šã¾ã™ãŒã€ç¾åœ¨ã‚¢ã‚¯ãƒ†ã‚£ãƒ–㪠VPN セッションã¯æ®‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n(ãれら㮠VPN セッションã¯åˆ—挙ã•ã‚Œãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚)\r\n\r\nアクティブ㪠VPN セッションを削除ã™ã‚‹ãŸã‚ã«ã¯ã€VPN Gate サービスをåœæ­¢ã—ãŸå¾Œã¯ç›´ã¡ã« SoftEther VPN Server ã¾ãŸã¯ SoftEther VPN Client サービスをå†èµ·å‹•ã™ã‚‹ã‹ã€ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã—ã¦ãã ã•ã„。
+
+VGS_START VPN Gate 中継サービス機能を有効ã«ã—ã¾ã™ã€‚\r\nã“ã®ã‚³ãƒ³ãƒ”ュータ㧠VPN Gate 中継サービス機能を有効ã«ã™ã‚‹ã¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã¯ã€ä»»æ„ã® VPN Gate ユーザーã‹ã‚‰ã® VPN 接続をå—ã‘付ã‘ã€é€šä¿¡ã‚’中継ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\r\n\r\nVPN Gate 中継サービス機能ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®è²¬ä»»ã§æœ‰åŠ¹ã«ã—ã¦ãã ã•ã„。\r\n法令ã«ã‚ˆã£ã¦ VPN ã«ã‚ˆã‚‹æš—å·åŒ–通信ãŒç¦æ­¢ã•ã‚Œã¦ã„る国ãŒã‚ã‚Šã¾ã™ã€‚\r\nVPN Gate 中継サービス機能ã«ã¤ã„ã¦è©³ã—ã㯠http://www.vpngate.net/ja/join.aspx ã‚’ãŠèª­ã¿ãã ã•ã„。\r\n\r\nVPN Gate 学術実験サービスã¯ã€æ—¥æœ¬å›½ã«æ‰€åœ¨ã™ã‚‹ç­‘波大学大学院ã«ãŠã‘る研究プロジェクトã¨ã—ã¦é‹å–¶ã•ã‚Œã¦ã„るサービスã§ã™ã€‚本サービスã¯æ—¥æœ¬å›½ã®æ³•ä»¤ã«ã®ã¿æº–æ‹ ã—ã¦é‹ç”¨ã•ã‚Œã¦ãŠã‚Šã€æ—¥æœ¬å›½ä»¥å¤–ã®å›½ãƒ»åœ°åŸŸã®æ³•ä»¤ã«ã¤ã„ã¦ã¯ä¸€åˆ‡é–¢çŸ¥ã—ã¦ãŠã‚Šã¾ã›ã‚“。\r\n\r\nãã‚‚ãも世界ã«ã¯ 200 カ国近ãã®å›½ãŒå­˜åœ¨ã—ã¦ãŠã‚Šã€ãã‚Œãžã‚Œã®å›½ã«ãŠã‘る法律ã¯äº’ã„ã«ç•°ãªã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®å›½ã®æ³•å¾‹ã‚’調査ã—ãŸä¸Šã§ãれらã™ã¹ã¦ã«é©åˆã™ã‚‹ã“ã¨ã‚’ä¿è¨¼ã—ãŸã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’開発ã™ã‚‹ã“ã¨ã¯äº‹å®Ÿä¸Šä¸å¯èƒ½ã§ã™ã€‚万一ユーザーãŒæœ¬ã‚µãƒ¼ãƒ“スを特定ã®å›½ãƒ»åœ°åŸŸã®é ˜åŸŸå†…ã§åˆ©ç”¨ã—ãŸã“ã¨ã«ã‚ˆã£ã¦å…¬å‹™å“¡ã«ã‚ˆã‚Šæ³•çš„ãªãƒšãƒŠãƒ«ãƒ†ã‚£ã‚’科ã›ã‚‰ã‚Œã‚‹ãªã©ã®æ害ãŒç™ºç”Ÿã—ãŸå ´åˆã§ã‚ã£ã¦ã‚‚ã€ãƒ—ロジェクト実施者ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。\r\n本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを使用ã™ã‚‹éš›ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé©ç”¨ã•ã‚Œã‚‹ã™ã¹ã¦ã®æ³•ä»¤ã‚’ユーザーã®è²¬ä»»ã«ã‚ˆã‚Šéµå®ˆã—ã¦ãã ã•ã„。本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを日本国内・国外をå•ã‚ãšä½¿ç”¨ã•ã‚ŒãŸå ´åˆã«ç™ºç”Ÿã™ã‚‹ã™ã¹ã¦ã®æ害ã¨è²¬ä»»ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¸°è²¬ã—ã¾ã™ã€‚本学術実験ã®é‹å–¶è€…ãŠã‚ˆã³ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ä¾›çµ¦è€…ã¯ã€ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。\r\nã“れらã®æ³¨æ„事項ã«åŒæ„ã„ãŸã ã‘ãªã„å ´åˆã¯ã€VPN Gate 学術実験サービスã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½ã‚’使用ã—ãªã„ã§ãã ã•ã„。
+
+
+# サービス関係 (Win32)
+SVC_HELP [ %s (%S) ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å¼•æ•° ]\r\n\r\nã“ã®ãƒ—ログラム (%s) ã¯ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§ç¨¼å‹•ã™ã‚‹ãƒ—ロセスã§ã™ã€‚以下ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å¼•æ•°ã‚’与ãˆã¦èµ·å‹•ã—ã¦ãã ã•ã„。\r\n\r\n\r\n/install …… %s サービス (サービスå: %S) ã‚’ Windows ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚ãã®å¾Œè‡ªå‹•çš„ã«ã‚µãƒ¼ãƒ“スを起動ã—ã¾ã™ã€‚\r\n\r\n/uninstall …… %s サービス (サービスå: %S) ã‚’ Windows ã‹ã‚‰ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚\r\n\r\n/start … %s サービス (サービスå: %S) ã‚’èµ·å‹•ã—ã¾ã™ã€‚\r\n\r\n/stop … %s サービス (サービスå: %S) ã‚’åœæ­¢ã—ã¾ã™ã€‚\r\n\r\n/test … %s プログラムをテストモードã§èµ·å‹•ã—ã¾ã™ã€‚(デãƒãƒƒã‚°ç”¨)\r\n\r\n/usermode … %s プログラムをユーザーモードã§èµ·å‹•ã—ã¾ã™ã€‚(å¯èƒ½ãªå ´åˆ)\r\n\r\n/usermode_showtray … ユーザーモードã§èµ·å‹•ã™ã‚‹éš›ã€ä»¥å‰ã‚¿ã‚¹ã‚¯ãƒˆãƒ¬ã‚¤ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’éžè¡¨ç¤ºã«è¨­å®šã—ãŸã“ã¨ãŒã‚ã‚‹å ´åˆã¯ã€ã‚¢ã‚¤ã‚³ãƒ³ã‚’回復ã—ã¾ã™ã€‚\r\n\r\n/usermode_hidetray … ユーザーモードã§èµ·å‹•ã™ã‚‹éš›ã€ã‚¿ã‚¹ã‚¯ãƒˆãƒ¬ã‚¤ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’éžè¡¨ç¤ºã«ã—ã¾ã™ã€‚\r\n\r\n\r\n※ /test ãŠã‚ˆã³ /usermode 以外ã®ã‚µãƒ¼ãƒ“スæ“作系コマンド㯠Windows 98 / Me ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+SVC_NT_ONLY サービス系ã®æ“作コマンド㯠Windows 98 / Me ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+SVC_ALREADY_INSTALLED サービス %s (サービスå %S) ã¯ã™ã§ã«ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚一度アンインストールã—ã¦ã‹ã‚‰ã€å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã‹?
+SVC_INSTALL_OK サービス %s (サービスå %S) ã‚’æ­£ã—ãインストールã—ã¾ã—ãŸã€‚\r\n\r\n(実行パス: %s)\r\n\r\nサービスã®èµ·å‹•ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+SVC_INSTALL_FAILED サービス %s (サービスå %S) ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SVC_INSTALL_FAILED_2 サービス %s (サービスå %S) ã‚’æ­£ã—ãインストールã—ã¾ã—ãŸã€‚\r\n\r\n(実行パス: %s)\r\n\r\nãŸã ã—ã€ã‚µãƒ¼ãƒ“スã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SVC_NOT_INSTALLED サービス %s (サービスå %S) ã¯ã‚³ãƒ³ãƒ”ュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。/install コマンドライン引数を使用ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。
+SVC_START_OK サービス %s (サービスå %S) ã®èµ·å‹•ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+SVC_START_FAILED サービス %s (サービスå %S) ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SVR_ALREADY_START サービス %s (サービスå %S) ã¯ã™ã§ã«èµ·å‹•ã—ã¦ã„ã¾ã™ã€‚
+SVC_STOP_OK サービス %s (サービスå %S) ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+SVC_STOP_FAILED サービス %s (サービスå %S) ã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SVC_ALREADY_STOP サービス %s (サービスå %S) ã¯ã™ã§ã«åœæ­¢ã—ã¦ã„ã¾ã™ã€‚
+SVC_UNINSTALL_OK サービス %s (サービスå %S) をアンインストールã—ã¾ã—ãŸã€‚
+SVC_UNINSTALL_FAILED サービス %s (サービスå %S) ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SVC_NOT_FOUND サービス %S ã«é–¢ã™ã‚‹æƒ…å ±ãŒæ–‡å­—列テーブル内ã‹ã‚‰è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+SVC_NOT_ADMIN サービスをインストール / アンインストール / èµ·å‹• / åœæ­¢ã™ã‚‹ã«ã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠Administrators æ¨©é™ (システム管ç†è€…権é™) ãŒå¿…è¦ã§ã™ã€‚\r\n\r\nã“ã®ã‚³ãƒ³ãƒ”ュータ㮠Administrators アカウントをæŒã£ã¦ã„ã‚‹å ´åˆã¯ã€Administrators アカウントã¨ã—ã¦ãƒ­ã‚°ã‚ªãƒ³ã—ç›´ã—ã¦ãã ã•ã„。\r\nAdministrators アカウントãŒä¸æ˜Žãªå ´åˆã¯ã€ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+SVC_TEST_MSG サービス %s をテストモードã§èµ·å‹•ã—ã¦ã„ã¾ã™ã€‚\r\n\r\n[OK] をクリックã™ã‚‹ã¨çµ‚了ã—ã¾ã™ã€‚
+SVC_TRAY_TOOLTIP %S (ユーザーモード)
+SVC_TEST_MUTEX ã™ã§ã«å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ« %s ãŒèµ·å‹•ã—ã¦ã„ã¾ã™ã€‚
+SVC_USERMODE_MUTEX ã™ã§ã« %s ã®åˆ¥ã®ãƒ—ロセスãŒèµ·å‹•ã—ã¦ã„ã¾ã™ã€‚
+SVC_SERVICE_MUTEX サービス %S ã®ãƒ—ロセス %s ãŒã™ã§ã«èµ·å‹•ã—ã¦ã„ã‚‹ãŸã‚ã€ã‚µãƒ¼ãƒ“スを開始ã§ãã¾ã›ã‚“。
+SVC_USERMODE_MENU_1 タスクトレイアイコンをéžè¡¨ç¤ºã«ã™ã‚‹(&H)
+SVC_USERMODE_MENU_2 %s ã®çµ‚了(&X)
+SVC_HIDE_TRAY_MSG %S ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰èµ·å‹•æ™‚ã®ã‚¿ã‚¹ã‚¯ãƒˆãƒ¬ã‚¤ã‚¢ã‚¤ã‚³ãƒ³ã‚’éžè¡¨ç¤ºã«ã—ã¾ã™ã€‚\r\næ¬¡å›žä»¥é™ %S をユーザーモードã§èµ·å‹•ã—ãŸéš›ã«ã€ã‚¿ã‚¹ã‚¯ãƒˆãƒ¬ã‚¤ã«ã‚¢ã‚¤ã‚³ãƒ³ãŒè¡¨ç¤ºã•ã‚Œãªããªã‚Šã¾ã™ã€‚\r\nプロセスを終了ã™ã‚‹ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚‚表示ã•ã‚Œãªããªã‚Šã¾ã™ã€‚\r\n\r\nプロセスを終了ã™ã‚‹ã«ã¯ã€Windows 98 / Me ã®å ´åˆã¯ Ctrl + Alt + Del キーを押ã—㦠[プログラムã®å¼·åˆ¶çµ‚了] を使用ã—ã¦ãã ã•ã„。\r\nãれ以外㮠OS ã®å ´åˆã¯ [タスクマãƒãƒ¼ã‚¸ãƒ£] を使用ã—ã¦ãã ã•ã„。\r\n\r\nタスクトレイアイコンã®è¡¨ç¤ºã‚’復活ã•ã›ã‚‹ã«ã¯ã€æ¬¡å›žã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰èµ·å‹•æ™‚ã« /usermode_showtray オプションを使用ã—ã¦ãã ã•ã„。
+
+
+# サービス関係 (UNIX)
+UNIX_SVC_HELP %S Service Program\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n\n%S Command Usage:\n %S start - Start %S Service.\n %S stop - Stop %S Service if the service is already started.\n\n
+UNIX_SVC_STARTED %S Service Started.\n
+UNIX_SVC_STOPPING Stopping %S Service...\n
+UNIX_SVC_STOPPED %S Service Stopped.\n
+UNIX_SVC_STOP_FAILED %S Service Stop Failed.\n
+UNIX_SVC_ALREADY_START %S Service is already started.\nExecute "%S stop" to stop this service.\n
+UNIX_SVC_NOT_STARTED %S Service is not yet started.\nExecute "%S start" to start this service.\n
+UNIX_SVC_ERROR_FORK Failed to create child process for %S Service.\n
+
+
+# サービス定義 (SoftEther VPN Client)
+SVC_VPNCLIENT_NAME vpnclient
+SVC_VPNCLIENT_TITLE SoftEther VPN Client
+SVC_VPNCLIENT_DESCRIPT SoftEther VPN Client ã®ä»®æƒ³ LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŠã‚ˆã³æŽ¥ç¶šã‚µãƒ¼ãƒ“スを管ç†ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Client を使用ã—㦠SoftEther VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN Server)
+SVC_VPNSERVER_NAME vpnserver
+SVC_VPNSERVER_TITLE SoftEther VPN Server
+SVC_VPNSERVER_DESCRIPT SoftEther VPN Server サーãƒãƒ¼ プロセスを管ç†ã—ã¾ã™ã€‚SoftEther VPN Server ã¯é«˜æ€§èƒ½ã® SoftEther VPN Server 機能を TCP/IP プロトコルを通ã˜ã¦æä¾›ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Server ã¯åœæ­¢ã—ã€SoftEther VPN Client ã¯ã“ã®ã‚³ãƒ³ãƒ”ュータ㫠VPN 接続ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN Bridge)
+SVC_VPNBRIDGE_NAME vpnbridge
+SVC_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_VPNBRIDGE_DESCRIPT SoftEther VPN Bridge プロセスを管ç†ã—ã¾ã™ã€‚SoftEther VPN Bridge ã¯ã“ã®ã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¨é éš”地ã«ã‚ã‚‹ SoftEther VPN Server ã¨ã®é–“をブリッジ接続ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Bridge ã¯åœæ­¢ã—ã€ãƒ–リッジ接続を経由ã—ãŸé€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN Client)
+SVC_SEVPNCLIENT_NAME sevpnclient
+SVC_SEVPNCLIENT_TITLE SoftEther VPN Client
+SVC_SEVPNCLIENT_DESCRIPT SoftEther VPN Client ã®ä»®æƒ³ LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŠã‚ˆã³æŽ¥ç¶šã‚µãƒ¼ãƒ“スを管ç†ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Client を使用ã—㦠SoftEther VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN Server)
+SVC_SEVPNSERVER_NAME sevpnserver
+SVC_SEVPNSERVER_TITLE SoftEther VPN Server
+SVC_SEVPNSERVER_DESCRIPT SoftEther VPN Server サーãƒãƒ¼ プロセスを管ç†ã—ã¾ã™ã€‚SoftEther VPN Server ã¯é«˜æ€§èƒ½ã® SoftEther VPN Server 機能を TCP/IP プロトコルを通ã˜ã¦æä¾›ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Server ã¯åœæ­¢ã—ã€SoftEther VPN Client ã¯ã“ã®ã‚³ãƒ³ãƒ”ュータ㫠VPN 接続ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN Bridge)
+SVC_SEVPNBRIDGE_NAME sevpnbridge
+SVC_SEVPNBRIDGE_TITLE SoftEther VPN Bridge
+SVC_SEVPNBRIDGE_DESCRIPT SoftEther VPN Bridge プロセスを管ç†ã—ã¾ã™ã€‚SoftEther VPN Bridge ã¯ã“ã®ã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¨é éš”地ã«ã‚ã‚‹ SoftEther VPN Server ã¨ã®é–“をブリッジ接続ã—ã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Bridge ã¯åœæ­¢ã—ã€ãƒ–リッジ接続を経由ã—ãŸé€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (SoftEther VPN User-mode Router)
+SVC_VPNROUTER_NAME vpnrouter
+SVC_VPNROUTER_TITLE SoftEther VPN Router
+SVC_VPNROUTER_DESCRIPT SoftEther VPN Router (サービスモード) ã®ã‚µãƒ¼ãƒãƒ¼ プロセスを管ç†ã—ã¾ã™ã€‚SoftEther VPN Router ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã™ã‚‹ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼ã‚’æä¾›ã™ã‚‹ãƒ—ログラムã§ã€ä»®æƒ³ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¨ç‰©ç†çš„㪠IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¨ã®é–“ã‚’ç°¡å˜ãªæ“作ã§å®‰å…¨ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ã‚µãƒ¼ãƒ“スãŒåœæ­¢ã•ã‚ŒãŸå ´åˆã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Router ã¯åœæ­¢ã—ã€VPN Client ã¯ã“ã®ã‚³ãƒ³ãƒ”ュータã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚µãƒ¼ãƒ“スを利用ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+
+
+# サービス定義 (EtherLogger)
+SVC_ELOGSVC_NAME elogsvc
+SVC_ELOGSVC_TITLE SoftEther EtherLogger
+SVC_ELOGSVC_DESCRIPT SoftEther EtherLogger ã¯ã€ã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ LAN カードをæµã‚Œã‚‹ãƒ‡ãƒ¼ã‚¿ã‚’キャプãƒãƒ£ã—ã€ç®¡ç†è€…ãŒæŒ‡å®šã—ãŸç¨®é¡žã®ãƒ‘ケットã®ãƒ˜ãƒƒãƒ€ã¾ãŸã¯ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’テキストファイルã«ãƒ­ã‚°ã¨ã—ã¦è¨˜éŒ²ã™ã‚‹ã‚µãƒ¼ãƒ“スã§ã™ã€‚
+
+
+# SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£é–¢ä¿‚
+SM_TITLE SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£
+SM_LOCALHOST localhost (ã“ã®ã‚µãƒ¼ãƒãƒ¼)
+SM_SERVER_BRIDGE_TITLE VPN Bridge "%S" ã®ç®¡ç†
+SM_S_VHUB_BRIDGE VPN Bridge ã§ã¯ã€"BRIDGE" ã¨ã„ã†åå‰ã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦æ“作を行ã†ã“ã¨ã§ç®¡ç†ã—ã¾ã™ã€‚
+SM_DISCONNECTED 管ç†ç”¨ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+SM_MIKAN 未完æˆã§ã™ã€‚
+SM_MAIN_COLUMN_1 接続設定å
+SM_MAIN_COLUMN_2 接続先 VPN Server
+SM_MAIN_COLUMN_3 管ç†å¯¾è±¡
+SM_MODE_SERVER サーãƒãƒ¼å…¨ä½“
+SM_MODE_HUB %S
+SM_EDIT_CAPTION_1 æ–°ã—ã„接続設定ã®ä½œæˆ
+SM_EDIT_CAPTION_2 %s ã®ç·¨é›†
+SM_SETTING_EXISTS ã™ã§ã«åŒã˜åå‰ã®æŽ¥ç¶šè¨­å®š "%s" ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚別ã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。
+SM_SETTING_DELETE_MSG 接続設定 "%s" を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_PASSWORD_TYPE_STR 管ç†æŽ¥ç¶šç”¨ãƒ‘スワード
+SM_HUB_COLUMN_1 仮想 HUB å
+SM_HUB_COLUMN_2 状態
+SM_HUB_COLUMN_3 種類
+SM_HUB_COLUMN_4 ユーザー
+SM_HUB_COLUMN_5 グループ
+SM_HUB_COLUMN_6 セッション
+SM_HUB_COLUMN_7 MAC テーブル
+SM_HUB_COLUMN_8 IP テーブル
+SM_HUB_COLUMN_9 ログイン回数
+SM_HUB_COLUMN_10 最終ログイン日時
+SM_HUB_COLUMN_11 最終通信日時
+SM_HUB_ONLINE オンライン
+SM_HUB_OFFLINE オフライン
+SM_HUB_STANDALONE スタンドアロン
+SM_HUB_STATIC スタティック仮想 HUB
+SM_HUB_DYNAMIC ダイナミック仮想 HUB
+SM_SERVER_STANDALONE スタンドアロンサーãƒãƒ¼
+SM_FARM_CONTROLLER クラスタコントローラ
+SM_FARM_MEMBER クラスタメンãƒã‚µãƒ¼ãƒãƒ¼
+SM_INFORMATION 最新情報
+SM_HUB_STATUS_CAPTION 仮想 HUB "%s" ã®çŠ¶æ…‹
+SM_HUB_STATUS_HUBNAME 仮想 HUB å
+SM_HUB_STATUS_ONLINE 状態
+SM_HUB_TYPE 種類
+SM_HUB_NUM_SESSIONS セッション数
+SM_HUB_NUM_SESSIONS_CLIENT セッション数 (クライアント)
+SM_HUB_NUM_SESSIONS_BRIDGE セッション数 (ブリッジ)
+SM_HUB_NUM_ACCESSES アクセスリスト数
+SM_HUB_NUM_USERS ユーザー数
+SM_HUB_NUM_GROUPS グループ数
+SM_HUB_NUM_MAC_TABLES MAC テーブル数
+SM_HUB_NUM_IP_TABLES IP テーブル数
+SM_HUB_SECURE_NAT SecureNAT 機能
+SM_HUB_SECURE_NAT_YES 有効
+SM_HUB_SECURE_NAT_NO 無効
+SM_HUB_NUM_LOGIN ログイン回数
+SM_HUB_LAST_LOGIN_TIME 最終ログイン日時
+SM_HUB_LAST_COMM_TIME 最終通信日時
+SM_HUB_CREATED_TIME 作æˆæ—¥æ™‚
+SM_STATUS_COLUMN_1 é …ç›®
+SM_STATUS_COLUMN_2 値
+
+SM_ST_SEND_UCAST_NUM é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆãƒ‘ケット数
+SM_ST_SEND_UCAST_SIZE é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆåˆè¨ˆã‚µã‚¤ã‚º
+SM_ST_SEND_BCAST_NUM é€ä¿¡ãƒ–ロードキャストパケット数
+SM_ST_SEND_BCAST_SIZE é€ä¿¡ãƒ–ロードキャストåˆè¨ˆã‚µã‚¤ã‚º
+
+SM_ST_RECV_UCAST_NUM å—信ユニキャストパケット数
+SM_ST_RECV_UCAST_SIZE å—信ユニキャストåˆè¨ˆã‚µã‚¤ã‚º
+SM_ST_RECV_BCAST_NUM å—信ブロードキャストパケット数
+SM_ST_RECV_BCAST_SIZE å—信ブロードキャストåˆè¨ˆã‚µã‚¤ã‚º
+
+SM_ST_NUM_PACKET_STR %S パケット
+SM_ST_SIZE_BYTE_STR %S ãƒã‚¤ãƒˆ
+
+CM_EDIT_HUB_1 仮想 HUB ã®æ–°è¦ä½œæˆ
+CM_EDIT_HUB_2 %S ã®ãƒ—ロパティ
+
+CM_EDIT_HUB_STANDALONE ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã—ã¦ã„ã¾ã™ã€‚ã“ã®ä»®æƒ³ HUB ã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ HUB ã¨ã—ã¦å‹•ä½œã—ã¾ã™ã€‚
+CM_EDIT_HUB_TYPE_FIXED ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã—ã¦ã„ã¾ã™ã€‚ã“ã®ä»®æƒ³ HUB ã®ç¨®é¡žã¯ä¸‹è¨˜ã®ã¨ãŠã‚Šã§ã€å‹•çš„ãªå¤‰æ›´ã¯ã§ãã¾ã›ã‚“。
+CM_EDIT_HUB_CREATER æ–°ã—ã„仮想 HUB %S を作æˆã—ã¾ã—ãŸã€‚
+CM_OFFLINE_MSG %s をオフラインã«ã—ã¾ã™ã‹?\r\n\r\n仮想 HUB をオフラインã«ã™ã‚‹ã¨ã€ç¾åœ¨ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒåˆ‡æ–­ã•ã‚Œã€æ–°ã—ã„セッションãŒæŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚
+CM_DELETE_HUB_MSG %S を削除ã—ã¾ã™ã‹?\r\n\r\n仮想 HUB を削除ã™ã‚‹ã¨ã€ç¾åœ¨ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„るセッションãŒã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã€æ–°ãŸãªã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\r\nã¾ãŸã€ä»®æƒ³ HUB ã®ã™ã¹ã¦ã®è¨­å®šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ オブジェクトã€ã‚°ãƒ«ãƒ¼ãƒ—オブジェクトã€è¨¼æ˜Žæ›¸ã€ãŠã‚ˆã³ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚\r\n\r\n仮想 HUB を削除ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。\r\n削除ã—ã¾ã™ã‹?
+CM_HUB_DELETED_MSG 仮想 HUB %S を削除ã—ã¾ã—ãŸã€‚
+CM_LISTENER_COLUMN_1 ãƒãƒ¼ãƒˆç•ªå·
+CM_LISTENER_COLUMN_2 状態
+CM_LISTENER_TCP_PORT TCP %u
+CM_LISTENER_ONLINE 動作中
+CM_LISTENER_OFFLINE åœæ­¢ä¸­
+CM_LISTENER_ERROR エラー発生
+CM_DELETE_LISTENER_MSG リスナー (TCP ãƒãƒ¼ãƒˆ %u) を削除ã—ã¾ã™ã€‚今後ã€ã“ã®ãƒãƒ¼ãƒˆã«ã¯æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+CM_STOP_LISTENER_MSG リスナー (TCP ãƒãƒ¼ãƒˆ %u) ã‚’åœæ­¢ã—ã¾ã™ã€‚リスナーをå†é–‹ã™ã‚‹ã¾ã§ã€ã“ã®ãƒãƒ¼ãƒˆã«ã¯æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\r\n\r\nよã‚ã—ã„ã§ã™ã‹?
+CM_CLOSE_BUTTON é–‰ã˜ã‚‹
+CM_CERT_SET_MSG æ–°ã—ã„サーãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’設定ã—ã¾ã—ãŸã€‚
+CM_SHORTCUT_DISCONNECT 指定ã•ã‚ŒãŸæŽ¥ç¶šå…ˆã«ã™ã§ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™ã€‚\r\n\r\n切断ã—ã¾ã™ã‹?
+
+
+
+SM_SERVER_STATUS サーãƒãƒ¼çŠ¶æ…‹
+SM_ST_SERVER_TYPE サーãƒãƒ¼ã®ç¨®é¡ž
+SM_ST_NUM_TCP é–‹ã„ã¦ã„るソケット数
+SM_ST_NUM_TCP_LOCAL ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®ã‚½ã‚±ãƒƒãƒˆæ•°
+SM_ST_NUM_TCP_REMOTE ä»–ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã®ã‚½ã‚±ãƒƒãƒˆæ•°åˆè¨ˆ
+SM_ST_NUM_HUB_TOTAL 仮想 HUB 数
+SM_ST_NUM_HUB_STATIC スタティック仮想 HUB 数
+SM_ST_NUM_HUB_DYNAMIC ダイナミック仮想 HUB 数
+SM_ST_NUM_SESSION_TOTAL セッション数
+SM_ST_NUM_SESSION_LOCAL ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•°
+SM_ST_NUM_SESSION_REMOTE ä»–ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•°
+SM_ST_NUM_MAC_TABLE MAC アドレステーブル数
+SM_ST_NUM_IP_TABLE IP アドレステーブル数
+SM_ST_NUM_USERS ユーザー数
+SM_ST_NUM_GROUPS グループ数
+SM_ST_CLIENT_LICENSE 消費クライアント接続ライセンス数 (ã“ã®ã‚µãƒ¼ãƒãƒ¼)
+SM_ST_BRIDGE_LICENSE 消費ブリッジ接続ライセンス数 (ã“ã®ã‚µãƒ¼ãƒãƒ¼)
+SM_ST_CLIENT_LICENSE_EX 消費クライアント接続ライセンス数 (クラスタ全体)
+SM_ST_BRIDGE_LICENSE_EX 消費ブリッジ接続ライセンス数 (クラスタ全体)
+SM_ST_START_TIME サーãƒãƒ¼èµ·å‹•æ™‚刻
+SM_ST_CURRENT_TIME ç¾åœ¨æ™‚刻
+SM_ST_CURRENT_TICK 64 bit 高精度論ç†ã‚·ã‚¹ãƒ†ãƒ æ™‚刻
+SM_ST_TOTAL_MEMORY åˆè¨ˆè«–ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_USED_MEMORY 使用中ã®è«–ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_FREE_MEMORY 空ãè«–ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_TOTAL_PHYS åˆè¨ˆç‰©ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_USED_PHYS 使用中ã®ç‰©ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_FREE_PHYS 空ã物ç†ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚º
+SM_ST_RAM_SIZE_KB %S ãƒã‚¤ãƒˆ
+SM_INFO_TITLE 接続先 VPN Server ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+SM_INFO_PRODUCT_NAME 製å“å
+SM_INFO_VERSION ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+SM_INFO_BUILD ビルド情報
+SM_INFO_HOSTNAME ホストå
+SM_OS_SYSTEM_NAME オペレーティングシステム種類
+SM_OS_PRODUCT_NAME オペレーティングシステム製å“å
+SM_OS_SERVICE_PACK サービスパック
+SM_OS_SP_TAG Service Pack %u
+SM_OS_VENDER_NAME オペレーティングシステム製造元
+SM_OS_VERSION オペレーティングシステムãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_OS_KERNEL_NAME OS カーãƒãƒ«å
+SM_OS_KERNEL_VERSION OS カーãƒãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_CONNECTION_TYPE_0 クライアント
+SM_CONNECTION_TYPE_1 åˆæœŸåŒ–中
+SM_CONNECTION_TYPE_2 ログイン
+SM_CONNECTION_TYPE_3 追加接続
+SM_CONNECTION_TYPE_4 クラスタリング RPC
+SM_CONNECTION_TYPE_5 管ç†ç”¨ RPC
+SM_CONNECTION_TYPE_6 HUB 列挙 RPC
+SM_CONNECTION_TYPE_7 パスワード変更
+SM_CONNECTION_TYPE_8 MS-SSTP 接続
+SM_CONNECTION_TYPE_9 OpenVPN 接続
+SM_CONN_COLUMN_1 コãƒã‚¯ã‚·ãƒ§ãƒ³å
+SM_CONN_COLUMN_2 接続元
+SM_CONN_COLUMN_3 接続時刻
+SM_CONN_COLUMN_4 種類
+SM_HOSTNAME_AND_PORT %S:%u
+SM_CONN_DISCONNECT_MSG コãƒã‚¯ã‚·ãƒ§ãƒ³ %s を切断ã—ã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+SM_CONNINFO_CAPTION コãƒã‚¯ã‚·ãƒ§ãƒ³ %s ã®æƒ…å ±
+SM_CONNINFO_NAME コãƒã‚¯ã‚·ãƒ§ãƒ³å
+SM_CONNINFO_TYPE コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¨®é¡ž
+SM_CONNINFO_HOSTNAME 接続元ホストå
+SM_CONNINFO_IP 接続元 IP アドレス
+SM_CONNINFO_PORT 接続元ãƒãƒ¼ãƒˆç•ªå· (TCP)
+SM_CONNINFO_TIME 接続時刻
+SM_CONNINFO_SERVER_STR サーãƒãƒ¼è£½å“å
+SM_CONNINFO_SERVER_VER サーãƒãƒ¼ ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_CONNINFO_SERVER_BUILD サーãƒãƒ¼ ビルド番å·
+SM_CONNINFO_CLIENT_STR クライアント製å“å
+SM_CONNINFO_CLIENT_VER クライアントãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_CONNINFO_CLIENT_BUILD クライアントビルド番å·
+SM_FARM_REBOOT_MSG クラスタリング構æˆã‚’変更ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nクラスタリング構æˆã‚’変更ã™ã‚‹ã¨ã€ç¾åœ¨æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŠã‚ˆã³ç®¡ç†ç”¨ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ (ã“ã®ç®¡ç†ç”¨ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’å«ã‚€) ãŒã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã€ã‚µãƒ¼ãƒãƒ¼ プログラムãŒå†èµ·å‹•ã—ã¾ã™ã€‚\r\nサーãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°ãŒå¤šã„å ´åˆã¯ã€å†èµ·å‹•ã«æ•°å秒ã‹ã‹ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚\r\n\r\n[OK] をクリックã™ã‚‹ã¨ã€ã‚µãƒ¼ãƒãƒ¼ã¨ã®æŽ¥ç¶šãŒè‡ªå‹•çš„ã«åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚管ç†ã‚’継続ã™ã‚‹ã«ã¯ã€ã‚‚ã†ä¸€åº¦ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã—ç›´ã—ã¦ãã ã•ã„。
+SM_FM_COLUMN_1 種類
+SM_FM_COLUMN_2 接続時刻
+SM_FM_COLUMN_3 ホストå
+SM_FM_COLUMN_4 ãƒã‚¤ãƒ³ãƒˆ
+SM_FM_COLUMN_5 セッション数
+SM_FM_COLUMN_6 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+SM_FM_COLUMN_7 動作 HUB 数
+SM_FM_COLUMN_8 消費クライアント接続ライセンス
+SM_FM_COLUMN_9 消費ブリッジ接続ライセンス
+SM_FM_CONTROLLER コントローラ
+SM_FM_MEMBER メンãƒ
+SM_FMINFO_TYPE サーãƒãƒ¼ã®ç¨®é¡ž
+SM_FMINFO_CONNECT_TIME 接続確立時刻
+SM_FMINFO_IP IP アドレス
+SM_FMINFO_HOSTNAME ホストå
+SM_FMINFO_POINT ãƒã‚¤ãƒ³ãƒˆ
+SM_FMINFO_WEIGHT 性能基準比
+SM_FMINFO_NUM_PORT 公開ãƒãƒ¼ãƒˆæ•°
+SM_FMINFO_PORT %u 個目ã®å…¬é–‹ãƒãƒ¼ãƒˆ (TCP/IP)
+SM_FMINFO_NUM_HUB 動作ã—ã¦ã„る仮想 HUB æ•°
+SM_FMINFO_HUB %u 個目ã®ä»®æƒ³ HUB
+SM_FMINFO_HUB_TAG_1 %S (ダイナミック)
+SM_FMINFO_HUB_TAG_2 %S (スタティック)
+SM_FMINFO_NUM_SESSION セッション数
+SM_FMINFO_NUN_CONNECTION TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+SM_FMINFO_CAPTION クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã®çŠ¶æ…‹
+SM_FC_STATUS_CAPTION クラスタコントローラã¸ã®æŽ¥ç¶šçŠ¶æ…‹
+SM_FC_IP コントローラ㮠IP アドレス
+SM_FC_PORT コントローラ㮠TCP/IP ãƒãƒ¼ãƒˆç•ªå·
+SM_FC_STATUS 接続状態
+SM_FC_ONLINE オンライン
+SM_FC_OFFLINE オフライン
+SM_FC_LAST_ERROR 最後ã«ç™ºç”Ÿã—ãŸã‚¨ãƒ©ãƒ¼
+SM_FC_ERROR_TAG %s (エラーコード: %u)
+SM_FC_START_TIME 接続開始時刻
+SM_FC_FIRST_TIME 最åˆã®æŽ¥ç¶šç¢ºç«‹æˆåŠŸæ™‚刻
+SM_FC_CURRENT_TIME ç¾åœ¨ã®æŽ¥ç¶šç¢ºç«‹æˆåŠŸæ™‚刻
+SM_FC_NUM_TRY 接続試行回数
+SM_FC_NUM_CONNECTED 接続ã«æˆåŠŸã—ãŸå›žæ•°
+SM_FC_NUM_FAILED 接続ã«å¤±æ•—ã—ãŸå›žæ•°
+SM_FC_NOT_CONNECTED (未接続)
+SM_CHANGE_PASSWORD_1 確èªå…¥åŠ›ãŒãƒ‘スワードã¨ä¸€è‡´ã—ã¾ã›ã‚“。[パスワード] 㨠[確èªå…¥åŠ›] ã«ã¯åŒä¸€ã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。
+SM_CHANGE_PASSWORD_2 パスワードãŒå…¥åŠ›ã•ã‚Œã¦ã„ã¾ã›ã‚“。続行ã—ã¾ã™ã‹?
+SM_CHANGE_PASSWORD_3 パスワードを変更ã—ã¾ã—ãŸã€‚
+SM_USER_COLUMN_1 ユーザーå
+SM_USER_COLUMN_2 本å
+SM_USER_COLUMN_3 所属グループ
+SM_USER_COLUMN_4 説明
+SM_USER_COLUMN_5 èªè¨¼æ–¹æ³•
+SM_USER_COLUMN_6 ログイン回数
+SM_USER_COLUMN_7 最終ログイン日時
+SM_AUTHTYPE_0 匿åèªè¨¼
+SM_AUTHTYPE_1 パスワードèªè¨¼
+SM_AUTHTYPE_2 固有証明書èªè¨¼
+SM_AUTHTYPE_3 ç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼
+SM_AUTHTYPE_4 RADIUS èªè¨¼
+SM_AUTHTYPE_5 NT ドメインèªè¨¼
+SM_NO_GROUP ï¼
+SM_USER_DELETE_MSG ユーザー "%s" を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_EDIT_USER_CAPTION_1 ユーザーã®æ–°è¦ä½œæˆ
+SM_EDIT_USER_CAPTION_2 ユーザー %S ã®ãƒ—ロパティ
+SM_EDIT_USER_CERT_INFO [固有証明書èªè¨¼] ãŒé¸æŠžã•ã‚Œã¦ã„るユーザーã¯ã€æŽ¥ç¶šæ™‚ã« SSL クライアント証明書ãŒäºˆã‚ユーザーã”ã¨ã«è¨­å®šã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã¨å®Œå…¨ã«ä¸€è‡´ã™ã‚‹ã‹ã©ã†ã‹ã§æŽ¥ç¶šã‚’許å¯ã¾ãŸã¯æ‹’å¦ã•ã‚Œã¾ã™ã€‚
+SM_EDIT_USER_POL_DLG ユーザー %S ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼
+SM_POLICY_DEF_CAPTION セキュリティãƒãƒªã‚·ãƒ¼
+SM_LIMIT_STR %u ~ %u ã®ç¯„囲ã®æ•´æ•°å€¤ã‚’指定ã—ã¦ãã ã•ã„。
+SM_POLICY_INIT_TITLE å·¦ã®ãƒªã‚¹ãƒˆã‹ã‚‰ãƒãƒªã‚·ãƒ¼é …目をé¸æŠžã—ã¦ãã ã•ã„。
+SM_USER_CREEATE_OK ユーザー %S を作æˆã—ã¾ã—ãŸã€‚
+SM_USERINFO_CAPTION ユーザー "%S" ã®æƒ…å ±
+SM_USERINFO_NAME ユーザーå
+SM_USERINFO_GROUP グループå
+SM_USERINFO_CREATE 作æˆæ—¥æ™‚
+SM_USERINFO_UPDATE 更新日時
+SM_USERINFO_EXPIRE 有効期é™
+SM_USERINFO_NUMLOGIN ログイン回数
+SM_GROUPLIST_NAME グループå
+SM_GROUPLIST_REALNAME 本å
+SM_GROUPLIST_NOTE 説明
+SM_GROUPLIST_NUMUSERS ユーザー数
+SM_EDIT_GROUP_CAPTION_1 グループã®æ–°è¦ä½œæˆ
+SM_EDIT_GROUP_CAPTION_2 グループ %S ã®ãƒ—ロパティ
+SM_GROUP_CREATED グループ %S を作æˆã—ã¾ã—ãŸã€‚
+SM_GROUP_DELETE_MSG グループ %S を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_GROUP_POLICY_CAPTION グループ %S ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼
+SM_GROUP_MEMBER_STR \ (グループ %S ã«æ‰€å±žã—ã¦ã„るユーザーã®ã¿è¡¨ç¤º)
+SM_SELECT_GROUP é¸æŠž(&S)
+SM_SELECT_NO_GROUP ãªã—(&N)
+SM_SELECT_ALT_GROUP グループをé¸æŠž(&G)...
+SM_ACCESS_COLUMN_0 ID
+SM_ACCESS_COLUMN_1 動作
+SM_ACCESS_COLUMN_2 状態
+SM_ACCESS_COLUMN_3 優先順ä½
+SM_ACCESS_COLUMN_4 説明
+SM_ACCESS_COLUMN_5 内容
+SM_ACCESS_COLUMN_6 ユニーク ID
+SM_ACCESS_PASS 通éŽ
+SM_ACCESS_DISCARD 破棄
+SM_ACCESS_ENABLE 有効
+SM_ACCESS_DISABLE 無効
+SM_ACCESS_PROTO_1 ã™ã¹ã¦ã® IPv4 / IPv6 プロトコル
+SM_ACCESS_PROTO_2 6 (TCP/IP プロトコル)
+SM_ACCESS_PROTO_3 17 (UDP/IP プロトコル)
+SM_ACCESS_PROTO_4 1 (ICMPv4 プロトコル)
+SM_ACCESS_PROTO_5 58 (ICMPv6 プロトコル)
+SM_ACCESS_PROTO_6 IP プロトコル番å·ã‚’指定
+SM_SELECT_USER é¸æŠž(&S)
+SM_SELECT_NO é¸æŠžã—ãªã„(&N)
+SM_PLEASE_SELECT ユーザーをé¸æŠžã—ã¦ãã ã•ã„。
+SM_LINK_COLUMN_1 接続設定å
+SM_LINK_COLUMN_2 状態
+SM_LINK_COLUMN_3 接続完了時刻
+SM_LINK_COLUMN_4 接続先 VPN Server
+SM_LINK_COLUMN_5 接続先仮想 HUB
+SM_LINK_STATUS_OFFLINE オフライン (åœæ­¢ä¸­)
+SM_LINK_STATUS_ERROR エラー%u:%s
+SM_LINK_STATUS_ONLINE オンライン (接続済ã¿)
+SM_LINK_POLICY_GROUP カスケード接続ã®è¨­å®š
+SM_LINK_POLICY_CAPTION カスケードセッションã«é©ç”¨ã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®š
+SM_LINK_CONNECTING 接続処ç†ä¸­
+SM_LINK_SAVE_ONLINE カスケード接続設定 "%s" を変更ã—ã¾ã—ãŸãŒã€ç¾åœ¨ã“ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã¯ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã®ãŸã‚ã€æ¬¡å›žæŽ¥ç¶šæ™‚ã¾ã§è¨­å®šã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“。
+SM_LINK_DELETE_MSG カスケード接続 "%s" ã®è¨­å®šã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_LINK_OFFLINE_MSG カスケード接続 "%s" ã¯ç¾åœ¨æŽ¥ç¶šä¸­ã§ã™ã€‚接続を切断ã—ã¾ã™ã‹?
+SM_LINK_STATUS_CAPTION カスケード接続 "%s" ã®æŽ¥ç¶šçŠ¶æ³
+SM_LOG_SWITCH_0 切り替ãˆã‚’è¡Œã‚ãªã„
+SM_LOG_SWITCH_1 1 秒å˜ä½ã§åˆ‡ã‚Šæ›¿ãˆã‚‹
+SM_LOG_SWITCH_2 1 分å˜ä½ã§åˆ‡ã‚Šæ›¿ãˆã‚‹
+SM_LOG_SWITCH_3 1 時間å˜ä½ã§åˆ‡ã‚Šæ›¿ãˆã‚‹
+SM_LOG_SWITCH_4 1 æ—¥å˜ä½ã§åˆ‡ã‚Šæ›¿ãˆã‚‹
+SM_LOG_SWITCH_5 1 ヶ月å˜ä½ã§åˆ‡ã‚Šæ›¿ãˆã‚‹
+SM_SESS_DISCONNECT_MSG セッション "%S" を切断ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_SESS_COLUMN_1 セッションå
+SM_SESS_COLUMN_2 場所
+SM_SESS_COLUMN_3 ユーザーå
+SM_SESS_COLUMN_4 接続元ホストå
+SM_SESS_COLUMN_5 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³
+SM_SESS_COLUMN_6 転é€ãƒã‚¤ãƒˆæ•°
+SM_SESS_COLUMN_7 転é€ãƒ‘ケット数
+SM_SESS_COLUMN_8 VLAN ID
+SM_SESS_NORMAL ローカルセッション
+SM_SESS_LOCAL ローカルセッション
+SM_SESS_LOCAL_2 %S 上
+SM_SESS_REMOTE %S 上
+SM_SESS_LINK カスケード接続
+SM_SESS_LINK_HOSTNAME 仮想ホスト
+SM_SESS_LINK_TCP ãªã—
+SM_SESS_SNAT SecureNAT セッション
+SM_SESS_SNAT_HOSTNAME 仮想ホスト
+SM_SESS_SNAT_TCP ãªã—
+SM_SESS_BRIDGE ローカルブリッジセッション
+SM_SESS_BRIDGE_HOSTNAME Ethernet ブリッジ
+SM_SESS_LAYER3_HOSTNAME 仮想レイヤ 3 スイッãƒ
+SM_SESS_BRIDGE_TCP ãªã—
+SM_SESS_STATUS_CAPTION VPN セッション "%S" ã®çŠ¶æ³
+SM_SESS_STATUS_USERNAME ユーザーå (èªè¨¼)
+SM_SESS_STATUS_REALUSER ユーザーå (データベース)
+SM_SESS_STATUS_GROUPNAME グループå
+SM_CLIENT_IP 接続元 IP アドレス
+SM_CLIENT_HOSTNAME 接続元ホストå
+SM_NODE_CLIENT_NAME クライアント製å“å
+SM_NODE_CLIENT_VER クライアントãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_NODE_CLIENT_BUILD クライアントビルド番å·
+SM_NODE_SERVER_NAME サーãƒãƒ¼è£½å“å
+SM_NODE_SERVER_VER サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_NODE_SERVER_BUILD サーãƒãƒ¼ãƒ“ルド番å·
+SM_NODE_CLIENT_OS_NAME クライアント OS å
+SM_NODE_CLIENT_OS_VER クライアント OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_NODE_CLIENT_OS_PID クライアント OS プロダクト ID
+SM_NODE_CLIENT_HOST クライアントホストå
+SM_NODE_CLIENT_IP クライアント IP アドレス
+SM_NODE_CLIENT_PORT クライアントãƒãƒ¼ãƒˆç•ªå·
+SM_NODE_SERVER_HOST サーãƒãƒ¼ãƒ›ã‚¹ãƒˆå
+SM_NODE_SERVER_IP サーãƒãƒ¼ IP アドレス
+SM_NODE_SERVER_PORT サーãƒãƒ¼ãƒãƒ¼ãƒˆç•ªå·
+SM_NODE_PROXY_HOSTNAME 経由プロキシホストå
+SM_NODE_PROXY_IP 経由プロキシ IP アドレス
+SM_NODE_PROXY_PORT 経由プロキシãƒãƒ¼ãƒˆç•ªå·
+SM_MAC_COLUMN_1 セッションå
+SM_MAC_COLUMN_2 MAC アドレス
+SM_MAC_COLUMN_3 作æˆæ™‚刻
+SM_MAC_COLUMN_4 更新時刻
+SM_MAC_COLUMN_5 場所
+SM_MAC_COLUMN_1A VLAN ID
+SM_SESSION_FILTER \ (セッション %S ã®ã‚¨ãƒ³ãƒˆãƒªã®ã¿è¡¨ç¤º)
+SM_IP_COLUMN_1 セッションå
+SM_IP_COLUMN_2 IP アドレス
+SM_IP_COLUMN_3 作æˆæ™‚刻
+SM_IP_COLUMN_4 更新時刻
+SM_IP_COLUMN_5 場所
+SM_MAC_IP_DHCP %S (DHCP)
+SM_MACIP_LOCAL ã“ã®ã‚µãƒ¼ãƒãƒ¼ä¸Š
+SM_MACIP_SERVER %S 上
+SM_SNAT_STATUS SecureNAT ã®å‹•ä½œçŠ¶æ³
+SM_SNAT_NUM_SESSION %u セッション
+SM_SNAT_NUM_CLIENT %u クライアント
+SM_SNAT_IS_KERNEL カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ã§å‹•ä½œä¸­
+SM_BRIDGE_TOO_OLD_VER ç¾åœ¨æŽ¥ç¶šã—ã¦ã„ã‚‹ VPN Server ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\næ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã—ã¦ã¿ã¦ãã ã•ã„。
+SM_BRIDGE_UNSUPPORTED ã“ã® VPN Server ãŒå‹•ä½œã—ã¦ã„るオペレーティングシステム上ã§ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ローカルブリッジ機能ãŒä½¿ç”¨ã§ãるオペレーティングシステムã®ä¸€è¦§ã«ã¤ã„ã¦ã¯ã€VPN Server ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+SM_BRIDGE_WPCAP_REMOTE ã“ã® VPN Server 上ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上ã«ã¯ WinPcap ソフトウェアãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nWinPcap ソフトウェアã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã™ã‚‹ãŸã‚ã«ã¯ã€VPN Server ãŒå‹•ä½œã—ã¦ã„るサーãƒãƒ¼ コンピュータ上㧠SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€localhost (自分自身) ã«å¯¾ã—ã¦æŽ¥ç¶šã—ãŸçŠ¶æ…‹ã§ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能設定画é¢ã‚’表示ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n続行ã™ã‚‹ã«ã¯ã€ä¸€æ—¦ã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’終了ã—ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上㧠SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¦ã‹ã‚‰ã€localhost ã«å¯¾ã—ã¦æŽ¥ç¶šã—ã¦ã€è¨­å®šã‚’続行ã—ã¦ãã ã•ã„。
+SM_BRIDGE_WPCAP_ROOT ã“ã® VPN Server 上ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nインストールを継続ã™ã‚‹ã«ã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ上㧠Administrators (管ç†è€…) 権é™ã‚’æŒã£ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ãƒ­ã‚°ã‚ªãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\nAdministrators 権é™ã§ãƒ­ã‚°ã‚ªãƒ³ã—ã€ã‚‚ã†ä¸€åº¦ SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。
+SM_BRIDGE_WPCAP_INSTALL ã“ã® VPN Server 上ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上ã«ã¯ WinPcap ソフトウェアãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nWinPcap ã¯ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã§ã‚ã‚Šã€VPN Server ã®ä¸€éƒ¨ã¨ã—ã¦åŒæ¢±ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nWinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã—ã¾ã™ã‹?
+SM_BRIDGE_WPCAP_REBOOT1 WinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ãŸå¾Œã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nコンピュータを手動ã§å†èµ·å‹•ã—ã€VPN Server ãŒèµ·å‹•ã—ãŸå¾Œã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã®è¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。
+SM_BRIDGE_WPCAP_REBOOT2 WinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ãŸå¾Œã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹å ´åˆã¯ã€SoftEther VPN Server サービスをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nSoftEther VPN Server サービスã®å†èµ·å‹•ã¯çŸ­æ™‚é–“ã§å®Œäº†ã—ã¾ã™ãŒã€ç¾åœ¨ã“ã® VPN Server ã«æŽ¥ç¶šã—ã¦ã„るセッションã¯ã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚\r\nã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚‚切断ã•ã‚Œã‚‹ãŸã‚ã€ç¶šè¡Œã™ã‚‹ã«ã¯å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\r\n\r\nSoftEther VPN Server サービスをå†èµ·å‹•ã—ã¾ã™ã‹?
+SM_BRIDGE_RESOURCE WinPcap ã®ãƒ‰ãƒ©ã‚¤ãƒã‚’読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+SM_BRIDGE_COLUMN_1 番å·
+SM_BRIDGE_COLUMN_2 仮想 HUB å
+SM_BRIDGE_COLUMN_3 ブリッジ先 LAN カードã¾ãŸã¯ tap デãƒã‚¤ã‚¹å
+SM_BRIDGE_COLUMN_4 状態
+SM_BRIDGE_OFFLINE オフライン
+SM_BRIDGE_ONLINE 動作中
+SM_BRIDGE_ERROR エラー発生
+SM_BRIDGE_OK ローカルブリッジ接続ã®å®šç¾©ã‚’追加ã—ã¾ã—ãŸã€‚
+SM_BRIDGE_DELETE 仮想 HUB "%s" ã‹ã‚‰ãƒ‡ãƒã‚¤ã‚¹ "%s" ã¾ã§ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジを削除ã—ã¾ã™ã‹?
+SM_BRIDGE_DELETE_OK ローカルブリッジを削除ã—ã¾ã—ãŸã€‚
+SM_BRIDGE_INTEL 物ç†çš„㪠LAN カードã«å¯¾ã—ã¦ãƒ–リッジを行ã†å ´åˆã€æ–°ã—ã„ブリッジ接続を作æˆã—ãŸç›´å¾Œã®çŠ¶æ…‹ã§ã¯ã€ä¸€éƒ¨ã® LAN カードã§ã¯ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®ã‚³ãƒ³ãƒ”ュータã‹ã‚‰ãƒ–リッジ接続ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ LAN カード自身ã«å¯¾ã™ã‚‹ TCP/IP 通信ãŒæ­£ã—ãè¡Œãˆãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n(特ã«ã€Intel ã‚„ Broadcom 製 LAN カードãªã©ã§ã“ã®ç¾è±¡ãŒç™ºç”Ÿã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚)\r\n\r\n\r\nãã®å ´åˆã¯ã€ä¸€åº¦ VPN Server / Bridge ãŒå‹•ä½œã—ã¦ã„るコンピュータをå†èµ·å‹•ã—ã¦ãã ã•ã„。コンピュータã®å†èµ·å‹•å¾Œã«æ­£ã—ã通信ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\r\n\r\n\r\nã¾ãŸã€å¤§åŠã®ç„¡ç·š LAN アダプタã¯ãƒ—ロミスキャスモードã§ã®ãƒ‘ケットã®é€å—ä¿¡ã«å¯¾å¿œã—ã¦ã„ãªã„å ´åˆãŒå¤šã„ãŸã‚ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã«ä½¿ç”¨ã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ã‚ˆã†ãªå ´åˆã¯ã€ç„¡ç·š LAN アダプタã§ã¯ãªã通常㮠LAN カードã®ä½¿ç”¨ã‚’検討ã—ã¦ãã ã•ã„。
+SM_BRIDGE_VPN "%S" ã«å¯¾ã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚\r\n\r\n通常ã¯ã€ä»®æƒ³ HUB ã¨ç‰©ç†çš„㪠LAN カードã¨ã®é–“ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続を行ã„ã¾ã™ã€‚仮想 LAN カード等ã«å¯¾ã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続を行ã†å¿…è¦ãŒã‚ã‚‹ã“ã¨ã¯ã‚ã¾ã‚Šã‚ã‚Šã¾ã›ã‚“。\r\nã“ã‚ŒãŒæ„図ã—ãŸæ“作ã§ã‚ã‚‹ã‹ã©ã†ã‹ã€ã‚‚ã†ä¸€åº¦ç¢ºèªã—ã¦ãã ã•ã„。\r\n\r\n本当ã«ç¶šè¡Œã—ã¾ã™ã‹?
+SM_BRIDGE_INFO_1 ブリッジ先㮠Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+SM_BRIDGE_INFO_2 æ–°ã—ã作æˆã™ã‚‹ tap デãƒã‚¤ã‚¹ã®åå‰ã‚’入力ã—ã¦ãã ã•ã„。
+SM_CONFIG_SAVED コンフィグレーションファイルをä¿å­˜ã—ã¾ã—ãŸã€‚
+SM_CONFIG_SAVE_FAILED コンフィグレーションファイルã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SM_CONFIG_OPEN_FAILED 指定ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—ãŸã€‚
+SM_CONFIG_CONFIRM 指定ã•ã‚ŒãŸã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ VPN Server ã«æ›¸ãè¾¼ã¿ã¾ã™ã€‚VPN Server ã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã€æ–°ã—ã„コンフィグレーションファイルã®å†…容ã§èµ·å‹•ã—ã¾ã™ã€‚ç¾åœ¨ VPN Server ã«æŽ¥ç¶šä¸­ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ä¸€æ—¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚ã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚‚切断ã•ã‚Œã¾ã™ã®ã§ã€å†åº¦ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã—ç›´ã—ã¦ãã ã•ã„。\r\n\r\n続行ã—ã¾ã™ã‹?
+SM_CONFIG_WRITE_OK サーãƒãƒ¼å´ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’書ãæ›ãˆã¾ã—ãŸã€‚
+SM_AO_COLUMN_1 値ã®åå‰
+SM_AO_COLUMN_2 設定値
+SM_TRUE_OR_FALSE ã“ã®é …目㯠0 (false) ã¾ãŸã¯ 1 (true) ã§è¨­å®šã—ã¦ãã ã•ã„。
+SM_AO_SET_OK 仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを設定ã—ã¾ã—ãŸã€‚
+SM_EXT_OPTION_SET_OK 仮想 HUB ã®æ‹¡å¼µã‚ªãƒ—ションを設定ã—ã¾ã—ãŸã€‚
+SM_PASSWORD_MSG ç¾åœ¨ã€æŽ¥ç¶šå…ˆã® VPN Server ã«ã¯ç®¡ç†è€…パスワードãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。パスワードを設定ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚\r\n\r\nサーãƒãƒ¼ç®¡ç†è€…パスワードを設定ã—ã¾ã™ã‹ï¼Ÿ
+SM_L3_SW_COLUMN1 レイヤ 3 スイッãƒå
+SM_L3_SW_COLUMN2 動作状æ³
+SM_L3_SW_COLUMN3 インターフェイス数
+SM_L3_SW_COLUMN4 ルーティングテーブル数
+SM_L3_SW_ST_F_F åœæ­¢
+SM_L3_SW_ST_T_F 開始 (エラー)
+SM_L3_SW_ST_T_T 開始 (動作中)
+SM_L3_SW_DEL_MSG 仮想レイヤ 3 スイッム"%S" を削除ã—ã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+SM_L3_SW_IF_COLUMN1 IP アドレス
+SM_L3_SW_IF_COLUMN2 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯
+SM_L3_SW_IF_COLUMN3 仮想 HUB å
+SM_L3_SW_TABLE_COLUMN1 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹
+SM_L3_SW_TABLE_COLUMN2 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯
+SM_L3_SW_TABLE_COLUMN3 ゲートウェイアドレス
+SM_L3_SW_TABLE_COLUMN4 メトリック
+SM_SECURE_NAT_MSG SecureNAT 機能を本当ã«æœ‰åŠ¹ã«ã—ã¾ã™ã‹?\r\n\r\nSecureNAT 機能を有効ã«ã™ã‚‹ã¨ã€ä»®æƒ³ HUB ã®ä¸­ã« IP アドレスを 1 ã¤æŒã£ãŸä»®æƒ³ã® NAT 機能付ãルータãŒç”Ÿæˆã•ã‚Œã¾ã™ã€‚ã“ã®ä»®æƒ³ãƒ«ãƒ¼ã‚¿ã¯ä»®æƒ³ LAN ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるコンピュータã‹ã‚‰ã¯ 1 å°ã®ã‚³ãƒ³ãƒ”ュータã¾ãŸã¯ãƒ«ãƒ¼ã‚¿ã«è¦‹ãˆã¾ã™ã€‚\r\n\r\nSecureNAT ã®ä»®æƒ³ NAT 機能ã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ä»»æ„ã®ã‚³ãƒ³ãƒ”ュータã«å¯¾ã—ã¦ã€SecureNAT 機能を動作ã•ã›ã¦ã„るコンピュータを経由ã—ã¦å¤–部ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¨é€šä¿¡å¯èƒ½ã«ã—ã¾ã™ã€‚\r\nã—ãŸãŒã£ã¦ã€ã“ã® VPN Server 㧠SecureNAT を動作ã•ã›ãŸå ´åˆã€åŒä¸€ã®ã‚³ãƒ³ãƒ”ュータã‹ã‚‰ localhost (自分自身) ã«å¯¾ã—ã¦ä»®æƒ³ LAN カードを接続ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。(SecureNAT ãŒå‹•ä½œã—ã¦ã„るコンピュータãŒè‡ªåˆ†è‡ªèº«ã«å¯¾ã—ã¦ä»®æƒ³ LAN カードを接続ã™ã‚‹ã¨ã€è¨­å®šã«ã‚ˆã£ã¦ã¯ãƒ‘ケットãŒç„¡é™ãƒ«ãƒ¼ãƒ—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚)\r\n\r\n\r\nã¾ãŸã€ã™ã§ã«ä»®æƒ³ HUB 㮠レイヤ 2 セグメントã‹ã‚‰åˆ°é”å¯èƒ½ãªå ´æ‰€ã« DHCP サーãƒãƒ¼ãŒå­˜åœ¨ã™ã‚‹å ´åˆã¯ã€DHCP ã®ç«¶åˆãŒç™ºç”Ÿã™ã‚‹ãŸã‚ã€[SecureNAT ã®è¨­å®š] をクリックã—㦠DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’無効ã«ã—ã¦ãã ã•ã„。\r\n\r\nã¾ãŸã€NAT 機能を無効ã«ã—㦠DHCP サーãƒãƒ¼ã¨ã—ã¦ã®ã¿ä½¿ç”¨ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+SM_CRL_COLUMN_1 証明書ã®æ¦‚è¦
+SM_CRL_DELETE_MSG é¸æŠžã—ãŸé …目を削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹?
+SM_CRL_EMPTY_MSG 項目㌠1 ã¤ã‚‚é¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\nã“ã®ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã‚¨ãƒ³ãƒˆãƒªãŒè¿½åŠ ã•ã‚Œã‚‹ã¨ã€ã™ã¹ã¦ã®è¨¼æ˜Žæ›¸ãŒç„¡åŠ¹ã¨ã—ã¦åˆ¤æ–­ã•ã‚Œã€è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—よã†ã¨ã™ã‚‹ã™ã¹ã¦ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®æŽ¥ç¶šãŒæ‹’å¦ã•ã‚Œã¾ã™ã€‚\r\n\r\nよã‚ã—ã„ã§ã™ã‹?
+SM_AC_COLUMN_1 ID
+SM_AC_COLUMN_2 優先順ä½
+SM_AC_COLUMN_3 動作
+SM_AC_COLUMN_4 内容
+SM_AC_PASS 許å¯
+SM_AC_DENY æ‹’å¦
+SM_LOG_FILE_COLUMN_1 ログファイルå
+SM_LOG_FILE_COLUMN_2 ファイルサイズ
+SM_LOG_FILE_COLUMN_3 更新日時
+SM_LOG_FILE_COLUMN_4 場所
+SM_READ_LOG_FILE_INFO_1 処ç†ä¸­ã«ã¤ãã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+SM_READ_LOG_FILE_INFO_2 %S 中 %S ãŒå®Œäº†ã—ã¾ã—ãŸ...
+SM_READ_LOG_FILE_ERROR ファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¯æ­£ã—ã完了ã—ã¾ã›ã‚“ã§ã—ãŸã€‚
+SM_READ_SAVE_DLG_TITLE ログファイルã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+SM_READ_SAVE_DLG_FILTER ログファイル (*.LOG)|*.log|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+SM_READ_SAVE_FAILED ログファイルã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SM_READ_SAVE_TMP_FAILED 一時ファイル "%S" ã«æ›¸ãè¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+SM_READ_SAVE_OPEN_ERROR 一時ファイル "%S" ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚\r\n\r\næ‹¡å¼µå­ãŒ .LOG ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒ Windows ã«ã‚ˆã£ã¦é–¢é€£ä»˜ã‘られã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+SM_LICENSE_COLUMN_1 番å·
+SM_LICENSE_COLUMN_2 ライセンスキー
+SM_LICENSE_COLUMN_3 ライセンス種類å
+SM_LICENSE_COLUMN_4 状態
+SM_LICENSE_COLUMN_5 有効期é™
+SM_LICENSE_COLUMN_6 ライセンス ID
+SM_LICENSE_COLUMN_7 ライセンス種類 ID
+SM_LICENSE_COLUMN_8 サーãƒãƒ¼ ID
+SM_LICENSE_COLUMN_9 シリアル ID
+SM_LICENSE_INFINITE 無制é™
+SM_LICENSE_NO_EXPIRES 無期é™
+SM_LICENSE_STATUS_EDITION 製å“エディションå
+SM_LICENSE_STATUS_RELEASE ã“ã® VPN Server ã®ãƒªãƒªãƒ¼ã‚¹æ—¥ä»˜
+SM_LICENSE_STATUS_SYSTEM_ID ç¾åœ¨ã®ã‚µãƒ¼ãƒãƒ¼ ID
+SM_LICENSE_STATUS_EXPIRES ç¾åœ¨ã®è£½å“ライセンスã®æœ‰åŠ¹æœŸé™
+SM_LICENSE_STATUS_SUBSCRIPTION サブスクリプション契約ã®çŠ¶æ…‹
+SM_LICENSE_STATUS_SUBSCRIPTION_NONEED 契約ãªã— (ã“ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã§ã¯ã‚µãƒ–スクリプションキーã¯ä¸è¦)
+SM_LICENSE_STATUS_SUBSCRIPTION_NONE キー登録ã¾ã  (ã“ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã§ã¯ã‚µãƒ–スクリプションキーã®ç™»éŒ²ãŒå¿…é ˆ)
+SM_LICENSE_STATUS_SUBSCRIPTION_VALID 契約済㿠[契約期間: %s ã¾ã§]
+SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED 契約期é™åˆ‡ã‚Œ [契約期間: %s ã¾ã§]
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD ç¾åœ¨ã®å¥‘ç´„ã§åˆ©ç”¨å¯èƒ½ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³
+SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR %s ã¾ã§ã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹å…¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ç„¡å„Ÿã‚¢ãƒƒãƒ—グレードå¯èƒ½
+SM_LICENSE_STATUS_ENTERPRISE エンタープライズ機能ã®åˆ©ç”¨å¯å¦
+SM_LICENSE_STATUS_ENTERPRISE_YES ã¯ã„ (利用å¯èƒ½)
+SM_LICENSE_STATUS_ENTERPRISE_NO ã„ã„㈠(利用ä¸å¯èƒ½)
+SM_LICENSE_NUM_USER ユーザー作æˆå¯èƒ½æ•°
+SM_LICENSE_NUM_CLIENT クライアントåŒæ™‚接続å¯èƒ½æ•°
+SM_LICENSE_NUM_BRIDGE ブリッジåŒæ™‚接続å¯èƒ½æ•°
+SM_NO_LICENSE_COLUMN ã”注æ„:
+SM_NO_LICENSE 製å“ライセンス㌠1 ã¤ã‚‚登録ã•ã‚Œã¦ã„ãªã„ãŸã‚ã€ã“ã® VPN Server ã®é€šä¿¡æ©Ÿèƒ½ã¯å‹•ä½œã—ã¾ã›ã‚“。
+SM_LICENSE_DELETE_MSG é¸æŠžã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’ VPN Server ã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã‹?
+SM_SYSLOG_0 syslog é€ä¿¡æ©Ÿèƒ½ã‚’使用ã—ãªã„
+SM_SYSLOG_1 サーãƒãƒ¼ãƒ­ã‚°ã‚’ syslog ã§é€ä¿¡
+SM_SYSLOG_2 サーãƒãƒ¼ãŠã‚ˆã³ä»®æƒ³ HUB セキュリティログを syslog ã§é€ä¿¡
+SM_SYSLOG_3 サーãƒãƒ¼ã€ä»®æƒ³ HUB セキュリティãŠã‚ˆã³ãƒ‘ケットログを syslog ã§é€ä¿¡
+SM_SETUP_INFO_1 [次ã¸] をクリックã™ã‚‹ã¨ã€ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—を開始ã—ã¾ã™ã€‚[é–‰ã˜ã‚‹] をクリックã™ã‚‹ã¨ã€ã“ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ç”»é¢ã‚’é–‰ã˜ã€æ‰‹å‹•ã§ã™ã¹ã¦ã®è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+SM_SETUP_INFO_2 高度ãªæ©Ÿèƒ½ã‚’用ã„㟠VPN サーãƒãƒ¼ã®è¨­å®šã‚’è¡Œã†ã«ã¯ã€[é–‰ã˜ã‚‹] をクリックã—ã¦ãã ã•ã„。
+SM_SETUP_BRIDGE_ONLY ç¾åœ¨ VPN Bridge ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ãŸã‚ã€[拠点間接続 VPN] ã«ãŠã‘ã‚‹ [å„拠点ã«è¨­ç½®ã™ã‚‹ VPN Bridge] ã®ã¿ã‚’構築ã§ãã¾ã™ã€‚
+SM_SETUP_BRIDGE_EDGE å„拠点ã«è¨­ç½®ã™ã‚‹ VPN Bridge (&E)
+SM_SETUP_WARNING 続行ã™ã‚‹ã¨ã€ã“ã® VPN Server ã¾ãŸã¯ VPN Bridge ã®ç¾åœ¨ã®è¨­å®šå†…容ã¯ã€ç°¡æ˜“セットアップã§æŒ‡å®šã—ãŸå†…容ã«åˆæœŸåŒ–ã•ã‚Œã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+SM_SETUP_SELECT ブリッジ接続ã™ã‚‹ Ethernet デãƒã‚¤ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„
+SM_SETUP_NO_LICENSE_KEY ã“ã® SoftEther VPN Server ã«ã¯ã€æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nSoftEther VPN Server ㌠VPN サーãƒãƒ¼ã¨ã—ã¦å‹•ä½œã™ã‚‹ã«ã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ç™»éŒ²ãŒå¿…è¦ã§ã™ã€‚\r\nライセンスã®ç®¡ç†ç”»é¢ã‚’表示ã—ã¾ã™ã‹?\r\n\r\n(体験版ã¨ã—ã¦ä½¿ç”¨ã™ã‚‹å ´åˆã¯ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã® Web サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ä½“験版ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’å–å¾—ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n[ã¯ã„] をクリックã—ã¦ã‹ã‚‰ [ライセンスã®å…¥æ‰‹ãƒ»æ›´æ–°] ボタンをクリックã™ã‚‹ã¨ã€ä½“験版ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’入手ã§ãã¾ã™ã€‚)
+SM_HUBEXT_OPTION_TITLE 仮想 HUB 拡張オプション
+SM_HUBEXT_OPTION_STATIC1 仮想 HUB 拡張オプションを使用ã™ã‚‹ã¨ã€ã“ã®ä»®æƒ³ HUB ã«é–¢ã™ã‚‹ã‚ˆã‚Šè©³ç´°ãªè¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+SM_HUBEXT_OPTION_STATIC2 標準ã§ã¯ã€VPN Server 全体ã®ç®¡ç†è€…ãŠã‚ˆã³ä»®æƒ³ HUB 管ç†è€…ã®ä¸¡æ–¹ã¨ã‚‚ã€ä»®æƒ³ HUB 拡張オプションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nãŸã ã—ã€ä»®æƒ³ HUB 管ç†ã‚ªãƒ—ション㮠deny_hub_admin_change_ext_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã€æ‹¡å¼µã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ (設定内容を表示ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™)。
+SM_VLAN_COLUMN_0 LAN カードå
+SM_VLAN_COLUMN_1 ドライãƒç¨®é¡ž
+SM_VLAN_COLUMN_2 ドライãƒãƒ•ã‚¡ã‚¤ãƒ«å
+SM_VLAN_COLUMN_3 VLAN é€éŽè¨­å®š
+SM_VLAN_COLUMN_4 GUID
+SM_VLAN_COLUMN_5 デãƒã‚¤ã‚¹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ ID
+SM_VLAN_YES 設定済ã¿
+SM_VLAN_NO 未設定
+SM_VLAN_MSG_1 LAN カード "%S" ã§ã‚¿ã‚° VLAN パケットãŒé€éŽã™ã‚‹ã‚ˆã†ã«ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’設定ã—ã¾ã—ãŸã€‚\r\n\r\nãªãŠã€ä¸€éƒ¨ã® LAN カードã§ã¯ã€åˆ¥é€”ã€å¯¾è±¡ã® Windows コンピュータã«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã€ãƒ‡ãƒã‚¤ã‚¹ãƒžãƒãƒ¼ã‚¸ãƒ£ã‹ã‚‰ LAN カードã®ãƒ—ロパティを開ãã€ã‚¸ãƒ£ãƒ³ãƒœãƒ•ãƒ¬ãƒ¼ãƒ  (フレームサイズ㌠1,514 ãƒã‚¤ãƒˆä»¥ä¸Šã® Ethernet フレーム) ã®é€å—信を有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ジャンボフレームã®è¨­å®šã‚’è¡Œã‚ãªã„ã¨ã€ã‚¿ã‚° VLAN パケットã®ã†ã¡ãƒ•ãƒ¬ãƒ¼ãƒ ã‚µã‚¤ã‚ºãŒæœ€å¤§ã®ã‚‚ã®ã®é€å—ä¿¡ã«å¤±æ•—ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚大ããªã‚µã‚¤ã‚ºã®ãƒ‘ケットã®ã¿é€å—ä¿¡ãŒä¸å®‰å®šãªå ´åˆã¯ã€å¿…ãšã‚¸ãƒ£ãƒ³ãƒœãƒ•ãƒ¬ãƒ¼ãƒ ã‚’有効化ã—ã¦ãã ã•ã„ (例ãˆã°ã€æœ€å¤§ãƒ‘ケットサイズを 4,088 ãƒã‚¤ãƒˆã«è¨­å®šã—ã¦ãã ã•ã„) 。設定方法ã«ã¤ã„ã¦ã¯ã€Windows ã®ãƒ‡ãƒã‚¤ã‚¹ãƒžãƒãƒ¼ã‚¸ãƒ£ã‹ã‚‰ LAN カードã®è¨­å®šã‚’é–‹ãã‹ã€ã¾ãŸã¯ LAN カードã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚考ã«ã—ã¦ãã ã•ã„。\r\n\r\nãªãŠã€ä»Šå›žã®è¨­å®šå¤‰æ›´ã®å†…容㯠Windows レジストリã«æ›¸ãè¾¼ã¾ã‚Œã¾ã—ãŸãŒã€å¿…ãšã—も今回ã®è¨­å®šå¤‰æ›´ã«ã‚ˆã£ã¦ã‚¿ã‚° VLAN パケットãŒé€éŽã™ã‚‹ã‚ˆã†ã«ãªã‚‹ã“ã¨ãŒä¿è¨¼ã•ã‚Œã‚‹è¨³ã§ã¯ã‚ã‚Šã¾ã›ã‚“。\r\nã“ã®è¨­å®šã‚’è¡Œã£ãŸå¾Œã‚¿ã‚° VLAN パケットã®é€å—ä¿¡ãŒæ­£å¸¸ã«è¡Œãˆãªã„å ´åˆã¯ã€LAN カード "%S" ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦é©åˆ‡ã«æ‰‹å‹•ã§è¨­å®šã—ã¦ãã ã•ã„。ã¾ãŸã€LAN カード "%S" ãŒãã‚‚ãã‚‚ã‚¿ã‚° VLAN パケットã«å¯¾å¿œã—ã¦ã„ãªã„å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ãã®ã‚ˆã†ãªå ´åˆã¯ã€ãã® LAN カードã¯ã‚¿ã‚° VLAN パケットã®é€å—ä¿¡ã«ä½¿ç”¨ã§ãã¾ã›ã‚“ã®ã§ã€åˆ¥ã®ç¨®é¡žã® LAN カードをローカルブリッジ用ã«ã”利用ãã ã•ã„。\r\n\r\n今回ã®è¨­å®šå†…容をé©ç”¨ã™ã‚‹ãŸã‚ã«ã¯ã€å¯¾è±¡ã® Windows コンピュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚忘れãšã«å¿…ãšå†èµ·å‹•ã—ã¦ãã ã•ã„。
+SM_VLAN_MSG_2 LAN カード "%S" ã«è¨­å®šã•ã‚Œã¦ã„ãŸã‚¿ã‚° VLAN パケットãŒé€éŽã™ã‚‹ã‚ˆã†ã«ã™ã‚‹ãŸã‚ã®è¨­å®šã‚’レジストリã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚\r\n\r\nãªãŠã€ä»¥å‰ã«ã‚¿ã‚° VLAN パケットã®é€éŽã‚’実ç¾ã™ã‚‹ãŸã‚ã« LAN カードã«ã‚¸ãƒ£ãƒ³ãƒœãƒ•ãƒ¬ãƒ¼ãƒ ã‚’利用å¯èƒ½ã¨ã™ã‚‹ãŸã‚ã®è¨­å®šã‚’è¡Œã£ãŸå ´åˆã§ã€ä»Šå¾Œã‚¸ãƒ£ãƒ³ãƒœãƒ•ãƒ¬ãƒ¼ãƒ ã®åˆ©ç”¨ãŒä¸è¦ã ã¨æ€ã‚れる場åˆã¯ã€æ‰‹å‹•ã§ã‚¸ãƒ£ãƒ³ãƒœãƒ•ãƒ¬ãƒ¼ãƒ ã®è¨­å®šã‚’解除ã—ã¦ãã ã•ã„。\r\n\r\n今回ã®è¨­å®šå†…容をé©ç”¨ã™ã‚‹ãŸã‚ã«ã¯ã€å¯¾è±¡ã® Windows コンピュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚忘れãšã«å¿…ãšå†èµ·å‹•ã—ã¦ãã ã•ã„。
+SM_VLAN_NOTHING ç¾åœ¨ã€ã‚³ãƒ³ãƒ”ュータ "%S" ã«ã¯ã€ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ールãŒå¯¾å¿œã—ã¦ã„る物ç†çš„㪠LAN カード㯠1 æžšã‚‚ã‚ã‚Šã¾ã›ã‚“。\r\n\r\nãŸã ã—ã€ç¾åœ¨ã“ã®ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ールãŒå¯¾å¿œã—ã¦ã„ãªã„ LAN カードã§ã‚‚ã€ã‚¿ã‚° VLAN ãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§é€éŽå¯èƒ½ã‹ã€ã¾ãŸã¯ä½•ã‚‰ã‹ã®è¨­å®šã‚’è¡Œã†ã“ã¨ã«ã‚ˆã‚Šé€éŽå¯èƒ½ã«ãªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚\r\nãã®å ´åˆã¯ã€ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ãŒè‡ªã‚‰ Windows ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã€ãã®ã‚ˆã†ãªè¨­å®šã‚’è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+SM_SERVER_ADMIN_MSG VPN Server / Bridge "%S"
+SM_ETHERIP_COLUMN_0 ISAKMP Phase 1 ID
+SM_ETHERIP_COLUMN_1 仮想 HUB å
+SM_ETHERIP_COLUMN_2 ユーザーå
+SM_ETHERIP_ADD_OK æ–°ã—ã„ EtherIP / L2TPv3 クライアントã®æŽ¥ç¶šè¨­å®šã‚’追加ã—ã¾ã—ãŸã€‚
+SM_IPSEC_SETUP_QUESTION ã“ã® VPN Server 㯠IPsec / L2TP / EtherIP / L2TPv3 対応㮠VPN クライアントやルータ製å“ãªã©ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãる機能を有ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nã“ã® VPN Server ㌠iPhoneã€iPadã€Android ãªã©ã®ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã‚„ Mac OS Xã€Windows ãªã©ã«æ­è¼‰ã•ã‚Œã¦ã„ã‚‹ VPN クライアント機能ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãるよã†ã« IPsec ã®è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nIPsec ã®è¨­å®šã‚’è¡Œã„ã¾ã™ã‹?\r\n(ã“ã®è¨­å®šã¯å¾Œã‹ã‚‰ [IPsec / L2TP 設定] ボタンをクリックã—ã¦ã„ã¤ã§ã‚‚è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚)
+SM_OPENVPN_CONFIG_SAVE_OK OpenVPN 設定ファイルを格ç´ã—㟠ZIP ファイルを '%s' ã«ä¿å­˜ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã® ZIP ファイルを開ãã¨ã€OpenVPN クライアントã§ä½¿ç”¨ã§ãる設定ファイルã®ã‚µãƒ³ãƒ—ルãŒå±•é–‹ã§ãã¾ã™ã€‚\r\nãªãŠã€è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã¯å®Ÿéš›ã«ä½¿ç”¨ã™ã‚‹å‰ã«ã¯ç’°å¢ƒã«å¿œã˜ã¦ä¿®æ­£ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n詳ã—ã㯠ZIP ファイル内㮠'readme.txt' ファイルをãŠèª­ã¿ãã ã•ã„。\r\n\r\nã“ã® ZIP ファイルを今ã™ãé–‹ãã¾ã™ã‹?
+SM_OPENVPN_CONFIG_SAVE_NG ZIP ファイル '%s' ã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SM_OPENVPN_CONFIG_OPEN_NG ZIP ファイル '%s' ã‚’é–‹ã“ã†ã¨ã—ã¦å¤±æ•—ã—ã¾ã—ãŸã€‚手動ã§ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã„ã¦ãã ã•ã„。
+SM_DDNS_IPV4_ERROR IPv4 ã® DDNS サーãƒãƒ¼ã«åˆ°é”ã§ãã¾ã›ã‚“。
+SM_DDNS_IPV6_ERROR IPv6 ã® DDNS サーãƒãƒ¼ã«åˆ°é”ã§ãã¾ã›ã‚“。
+SM_DDNS_FQDN_EMPTY (ãªã—)
+SM_DDNS_OK_MSG ダイナミック DNS ホストå: %S%S\r\n\r\n上記㮠DNS ホストåを指定ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã“ã® VPN Server ã®ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã§ã‚る以下㮠IP アドレスã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nIPv4 アドレス: %s\r\nIPv6 アドレス: %s\r\n\r\nãªãŠã€ä»¥ä¸‹ã®ã‚ˆã†ãª DNS ホストåを指定ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€IPv4 アドレスã¾ãŸã¯ IPv6 アドレスã®ã„ãšã‚Œã‹ã®ã¿ã‚’明示的ã«å¿œç­”ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nIPv4 ã®ã¿ã‚’応答ã™ã‚‹ãƒ›ã‚¹ãƒˆå: %S.v4%S\r\nIPv6 ã®ã¿ã‚’応答ã™ã‚‹ãƒ›ã‚¹ãƒˆå: %S.v6%S\r\n
+SM_DDNS_OK_TITLE ダイナミック DNS 機能
+SM_DDNS_OK_MSG2 ダイナミック DNS ホストåã‚’ '%S' ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚\r\n\r\n[ヒント] ボタンをクリックã—ã¦è¿½åŠ æƒ…報をãŠèª­ã¿ãã ã•ã„。
+SM_IPSEC_PSK_TOO_LONG 事å‰å…±æœ‰éµ (PSK) ã®é•·ã•ãŒ 10 文字以上ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\nAndroid æºå¸¯é›»è©±ã®ä¸€éƒ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ãƒã‚°ãŒã‚ã‚Šã€äº‹å‰å…±æœ‰éµãŒ 10 文字以上ã®å ´åˆã¯ VPN 接続ãŒè¡Œãˆãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\nãã®ãŸã‚ã€äº‹å‰å…±æœ‰éµã®é•·ã•ã¯ 9 文字以下ã¨ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\r\n\r\n事å‰å…±æœ‰éµã®è¨­å®šã‚’見直ã—ã¾ã™ã‹?
+SM_ADVANCED_REDIRECT_URL_HINT_TITLE 高度㪠HTTP リダイレクション機能ã®ä½¿ã„æ–¹
+SM_ADVANCED_REDIRECT_URL_HINT 高度㪠HTTP リダイレクション機能 (上級者å‘ã‘)\r\n\r\nアクセスリスト㫠HTTP リダイレクト先㮠URL を記載ã™ã‚‹éš›ã«ã€URL ã®ä¸€éƒ¨ã¨ã—㦠<INFO> ã¨ã„ã†æ–‡å­—列を埋ã‚込むã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆã® URL ã‚’å—å–ã£ãŸ CGI ãªã©ã§ã€VPN 接続を行ã£ã¦ã„るクライアントã®æƒ…報を用ã„ãŸé«˜åº¦ãªå‡¦ç†ã‚’実行ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\n埋ã‚込㿠URL 例:\r\nhttp://www.google.com/search?q=<INFO>|secret\r\n\r\n実際ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã‚‹éš›ã«ã¯ã€å½“該文字列部分ãŒä»¥ä¸‹ã®ã‚ˆã†ãªæ–‡å­—列ã«ç½®æ›ã•ã‚Œã¾ã™ã€‚\r\n\r\nユーザーå|セッション ID|IP アドレス|日付ã¨æ™‚刻|ãƒãƒƒã‚·ãƒ¥å€¤\r\n\r\nç½®æ›å¾Œã®ä¾‹: zurukko|SID-ZURUKKO-123|219.117.219.154|20131117100354|99707160AFE7A454042B2C47B064112D652452D7\r\n\r\nã“ã“ã§ã€ä¸Šè¨˜ã®å„フィールドã®å€¤ã®å†…容ã®è©³ç´°ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚\r\n\r\nユーザーå: VPN 接続を行ã£ã¦ã„るユーザーåãŒä»£å…¥ã•ã‚Œã¾ã™ã€‚\r\n\r\nセッション ID: 当該 VPN セッション㮠ID ãŒä»£å…¥ã•ã‚Œã¾ã™ã€‚\r\n\r\n日付ã¨æ™‚刻: 'YYYYMMDDHHMMSS' ã®å½¢å¼ã§ 14 æ¡ã®æ•°å­—ãŒä»£å…¥ã•ã‚Œã¾ã™ (タイムゾーン㯠UTC)。\r\n\r\nãƒãƒƒã‚·ãƒ¥å€¤: ãƒãƒƒã‚·ãƒ¥å€¤ç›´å‰ã¾ã§ã®ä¸Šè¨˜ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã®ãƒ“ット列㫠URL 中ã®æ–‡å­— '|' 以é™ã®æœ«å°¾ã¾ã§ã®æ–‡å­—列 (上記ã®ä¾‹ã§ã¯ "secret" ã¨ã„ã†æ–‡å­—列) ã®ãƒ“ット列ã¨ã‚’連çµã— SHA-1 ãƒãƒƒã‚·ãƒ¥é–¢æ•°ã‚’é©ç”¨ã—ãŸçµæžœã® 20 ãƒã‚¤ãƒˆã‚’ 16 進数ã§è¡¨è¨˜ã—㟠40 文字ã®æ–‡å­—列。ãªãŠã€URL 中ã«æ–‡å­— '|' ãŒå­˜åœ¨ã—ãªã„å ´åˆã¯ãƒãƒƒã‚·ãƒ¥å€¤ã¯ä»˜ä¸Žã•ã‚Œã¾ã›ã‚“。\r\n\r\nãƒãƒƒã‚·ãƒ¥å€¤ã®å­˜åœ¨æ„義ã«ã¤ã„ã¦: ãƒãƒƒã‚·ãƒ¥æ–‡å­—列 (上記ã®ä¾‹ã§ã¯ "secret" ã¨ã„ã†æ–‡å­—列) ã¯ç§˜å¯†éµã¨ã—ã¦æ©Ÿèƒ½ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆã§ã‚¯ã‚¨ãƒªæ–‡å­—列をå—å–ã£ãŸ CGI ã¯å—å–ã£ãŸæ–‡å­—列ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«ã‚ˆã£ã¦ä¸æ­£ã«æ”¹ã–ã‚“ã•ã‚Œã¦ã„ãªã„ã“ã¨ã‚’確èªã§ãã¾ã™ã€‚\r\n
+SM_ADVANCED_REDIRECT_URL_MSG URL 㯠"http://" ã¾ãŸã¯ "https://" ã§å§‹ã¾ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+SM_DISABLE_DDNS_HINT_CAPTION ダイナミック DNS 機能を無効ã«ã™ã‚‹
+SM_DISABLE_DDNS_HINT ダイナミック DNS 機能を無効ã«ã™ã‚‹ã«ã¯ã€VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã¾ã™ã€‚\r\n\r\n"declare root" ディレクティブ内㫠"declare DDnsClient" ディレクティブãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ä¸­ã«ã‚ã‚‹ "bool Disable" ã®å€¤ã‚’ true ã«è¨­å®šã—㦠VPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚\r\n
+SM_REGENERATE_CERT_MSG VPN Server ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’æ–°ã—ã„ã‚‚ã®ã«ç½®æ›ã—ã¾ã™ã€‚\r\n\r\nã“ã‚Œã«ã‚ˆã‚Šã€å¤ã„サーãƒãƒ¼è¨¼æ˜Žæ›¸ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ã‚’å‰æã«è¨­å®šã•ã‚Œã¦ã„㟠VPN Client ã¯ã“ã® VPN Server ã«æŽ¥ç¶šã§ããªããªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\nよã‚ã—ã„ã§ã™ã‹?
+SM_DDNS_SERVER_CERT_MSG DDNS ホストåã‚’ "%S" ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã® VPN Server ã« Microsoft SSTP VPN プロトコルを用ã„㦠Windows Vista 以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Windows ã®çµ„ã¿è¾¼ã¿ SSTP VPN クライアントã‹ã‚‰æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€VPN クライアントå´ã§æŽ¥ç¶šå…ˆ VPN サーãƒãƒ¼åã¨ã—ã¦æŒ‡å®šã™ã‚‹ãƒ›ã‚¹ãƒˆå (DNS å) ã®æ–‡å­—列ã¨ã€ã“ã® VPN Server ã® SSL サーãƒãƒ¼è¨¼æ˜Žæ›¸ã® CN (Common Name) ã®æ–‡å­—列ã¨ãŒå®Œå…¨ä¸€è‡´ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nã“ã® VPN Server ã® SSL サーãƒãƒ¼è¨¼æ˜Žæ›¸ã® CN ㌠"%S" ã¨ãªã‚‹ã‚ˆã†ã«ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’å†ç”Ÿæˆã—ã¾ã™ã‹?\r\n([ã„ã„ãˆ] をクリックã™ã‚‹ã¨ã€ç¾åœ¨ã® SSL サーãƒãƒ¼è¨¼æ˜Žæ›¸ãŒå¼•ã続ã使用ã•ã‚Œã¾ã™ã€‚)
+SM_DDNS_SERVER_CERT_OK VPN Server ã® SSL 証明書をå†ç”Ÿæˆã—ã¾ã—ãŸã€‚\r\n\r\nã“ã® VPN Server ã« Microsoft SSTP VPN クライアントã‹ã‚‰æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€ç¾åœ¨ã® DDNS ホストå "%S" を接続先サーãƒãƒ¼åã¨ã—ã¦æŒ‡å®šã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\r\nã¾ãŸã€SSTP VPN クライアントã¨ãªã‚‹ Windows 上ã®ã€Œä¿¡é ¼ã§ãるルート証明書ã€ã«ã‚らã‹ã˜ã‚ã“ã® VPN Server ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’インストールã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n(ルート証明書を Windows ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã«ã¯ã€MMC ã®ã€Œè¨¼æ˜Žæ›¸ã€ã§ã€Œãƒ­ãƒ¼ã‚«ãƒ« コンピュータã€ã®è¨¼æ˜Žæ›¸ã‚¹ãƒˆã‚¢ã‚’é–‹ãã€ã€Œä¿¡é ¼ã§ãるルート証明書ã€ã«ã“ã® VPN Server ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’追加ã—ã¾ã™ã€‚\r\n 詳ã—ã㯠Microsoft 社ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。)\r\n\r\næ–°ã—ã„ VPN Server ã® SSL 証明書を X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã—ã¾ã™ã‹?
+SM_SETUP_STEP_SECURENAT ã“ã® VPN Server / Bridge ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§èµ·å‹•ã—ã¦ã„ã‚‹ã‹ã€OS ãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジéžå¯¾å¿œã®ãŸã‚ã€ä»®æƒ³ HUB ã¨ç‰©ç†çš„㪠LAN カードã¨ã‚’ブリッジã§ãã¾ã›ã‚“。代ã‚ã‚Šã«ã€ŒSecureNATã€æ©Ÿèƒ½ã‚’使用ã™ã‚Œã°ã€æŽ¥ç¶šã—ã¦ã㟠VPN クライアントã¯ä»®æƒ³ NAT を経由ã—㦠LAN 上ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+SM_SETUP_STEP_SECURENAT_TITLE 3. 仮想 HUB ã¨ç‰©ç†çš„㪠LAN ã¨ã®æŽ¥ç¶š
+SM_UPDATE_CHECK_TITLE_VPNSERVER %S VPN Server (サーãƒãƒ¼ '%S' 上)
+SM_UPDATE_CHECK_TITLE_VPNBRIDGE %S VPN Bridge (サーãƒãƒ¼ '%S' 上)
+SM_FACTORY_DEFAULT_WARNING VPN Server / Bridge ã®è¨­å®šã‚’リセットã—ã¾ã™ã€‚\r\nVPN Server / Bridge ã®ç¾åœ¨ã®è¨­å®šã¯æ¶ˆåŽ»ã•ã‚Œã€ç›´ã¡ã«åˆæœŸè¨­å®š (インストール直後ã®è¨­å®š) ã«æˆ»ã‚Šã¾ã™ã€‚\r\nリセットを実行ã™ã‚‹å‰ã«ã€ç¾åœ¨ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¦ãŠãã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\r\n\r\n[OK] をクリックã™ã‚‹ã¨ãƒªã‚»ãƒƒãƒˆã‚’実行ã—ã¾ã™ã€‚VPN Server / Bridge サービスã¯å†èµ·å‹•ã—ç¾åœ¨ã® VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã®æŽ¥ç¶šã¯åˆ‡æ–­ã•ã‚Œã¾ã™ã®ã§ã€ãã®å¾Œã« VPN Server / Bridge ã«å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\r\nå†æŽ¥ç¶šã‚’è¡Œã†ã¨ã€è¨­å®šãŒãƒªã‚»ãƒƒãƒˆã•ã‚ŒãŸå¾Œã® VPN Server ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚
+SM_FACTORY_DEFAULT_PERFORMED 設定ã®ãƒªã‚»ãƒƒãƒˆå‡¦ç†ã¯ã‚µãƒ¼ãƒãƒ¼ä¸Šã§é–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚\r\n\r\nOk をクリックã™ã‚‹ã¨ç¾åœ¨ã® VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’終了ã—ã¾ã™ã€‚\r\n終了ã—ãŸå¾Œã«ã€VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’å†åº¦èµ·å‹•ã—㦠VPN Server ã«å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\r\nå†æŽ¥ç¶šã™ã‚‹ã¨ã€è¨­å®šãŒãƒªã‚»ãƒƒãƒˆã•ã‚ŒãŸå¾Œã® VPN Server ãŒå‡ºç¾ã—ã¾ã™ã€‚
+SM_AZURE_STATUS_CONNECTED 状態: クラウドã«æŽ¥ç¶šå®Œäº†
+SM_AZURE_STATUS_NOT_CONNECTED 状態: クラウドã«æœªæŽ¥ç¶š
+SM_NO_BRIDGE_NICS ローカルブリッジを作æˆã™ã‚‹ã“ã¨ãŒã§ãる物ç†çš„㪠LAN カード㌠VPN サーãƒãƒ¼ã®ã‚³ãƒ³ãƒ”ュータ㫠1 枚も見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚\r\n\r\nローカルブリッジを作æˆã™ã‚‹ã«ã¯ã€ç‰©ç†çš„㪠LAN カードを 1 枚以上コンピュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\nç„¡ç·š LAN カードã€3G アダプタ等ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。\r\n通常ã®ã‚±ãƒ¼ãƒ–ル接続㮠Ethernet ã«å¯¾å¿œã—㟠LAN カードをインストールã—ã¦ãã ã•ã„。\r\n\r\n最近インストールã—㟠LAN カードãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€ä¸€åº¦ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã—ã¦ãã ã•ã„。\r\n\r\nローカルブリッジを使用ã§ããªã„å ´åˆã¯ã€ä»£ã‚ã‚Šã«ã€ŒSecureNAT 機能ã€ã®ä»®æƒ³ NAT 機能ã®ä½¿ç”¨ã‚’検討ã—ã¦ãã ã•ã„。\r\n\r\nãªãŠã€ä½•ã‚‰ã‹ã®ç†ç”±ã§ç‰©ç†çš„㪠LAN カード以外㮠LAN カード (ç„¡ç·š LANã€ä»®æƒ³ LAN ãªã©) を使用ã—ãŸã„å ´åˆã¯ã€è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã® "LocalBridgeList" ディレクティブ内㮠"ShowAllInterfaces" ã‚’ "true" ã«ã—㦠VPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã¨ã“れらã®ãƒ‡ãƒã‚¤ã‚¹ã‚‚表示ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚(上級者å‘ã‘ã€Windows ã®ã¿)
+
+
+# User-modeRouter 管ç†ãƒ„ール関係
+NM_TITLE deleted
+NM_CONNECT_TITLE deleted
+NM_STATUS_TAG 接続状æ³: %s
+NM_OFFLINE ã©ã® VPN Server ã«ã‚‚接続ã—ã¦ã„ã¾ã›ã‚“。
+NM_CONNECTING VPN Server ã«æŽ¥ç¶šä¸­
+NM_CONNECTED VPN Server "%S" ã¸ã®æŽ¥ç¶šãŒå®Œäº†
+NM_CONNECT_ERROR ã‚¨ãƒ©ãƒ¼ç•ªå· %u (%s)
+NM_ACCOUNT_TITLE deleted
+NM_STATUS User-mode Router ã®çŠ¶æ³
+NM_STATUS_CONNECT 接続状æ³
+NM_STATUS_TCP NAT TCP/IP セッション数
+NM_STATUS_UDP NAT UDP/IP セッション数
+NM_STATUS_ICMP NAT ICMP セッション数
+NM_STATUS_DNS NAT DNS セッション数
+NM_STATUS_DHCP 割り当ã¦æ¸ˆã¿ DHCP クライアント数
+NM_INFO User-mode Router ã®æƒ…å ±
+NM_INFO_PRODUCT_NAME 製å“å
+NM_INFO_VERSION_STR ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+NM_INFO_BUILD_INFO ビルド情報
+NM_INFO_HOSTNAME ホストå
+NM_NAT_ID ID
+NM_NAT_PROTOCOL プロトコル
+NM_NAT_SRC_HOST 接続元ホスト
+NM_NAT_SRC_PORT 接続元ãƒãƒ¼ãƒˆ
+NM_NAT_DST_HOST 接続先ホスト
+NM_NAT_DST_PORT 接続先ãƒãƒ¼ãƒˆ
+NM_NAT_CREATED セッション作æˆæ—¥æ™‚
+NM_NAT_LAST_COMM 最終通信時刻
+NM_NAT_SIZE å—ä¿¡ / é€ä¿¡ã‚µã‚¤ã‚º
+NM_NAT_TCP_STATUS TCP 接続状態
+NM_NAT_PROTO_TCP TCP/IP
+NM_NAT_PROTO_UDP UDP/IP
+NM_NAT_PROTO_DNS DNS
+NM_NAT_PROTO_ICMP ICMP
+NAT_TCP_CONNECTING 接続中
+NAT_TCP_SEND_RESET 切断中
+NAT_TCP_CONNECTED 接続完了
+NAT_TCP_ESTABLISHED 通信中
+NAT_TCP_WAIT_DISCONNECT 切断中
+DHCP_DHCP_ID ID
+DHCP_LEASED_TIME リース開始日時
+DHCP_EXPIRE_TIME リース期é™
+DHCP_MAC_ADDRESS MAC アドレス
+DHCP_IP_ADDRESS 割り当㦠IP
+DHCP_HOSTNAME クライアントホストå
+NM_PASSWORD_MSG 管ç†ãƒ‘スワードを設定ã—ã¾ã—ãŸã€‚
+
+
+# ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報系
+ABOUT_CAPTION %s ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+BETA_EXPIRES ç¾åœ¨ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ SoftEther VPN ソフトウェアã¯ãƒ™ãƒ¼ã‚¿ç‰ˆã§ã€æœŸé™ãŒåˆ‡ã‚Œã¦ã„ã¾ã™ã€‚より新ã—ã„ベータ版ã¾ãŸã¯å®Œæˆç‰ˆã®æä¾›ãŒé–‹å§‹ã•ã‚ŒãŸå¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。\r\nhttp://selinks.org/ ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€æœ€æ–°ç‰ˆã® SoftEther VPN ソフトウェアを入手ã—ã¦ãã ã•ã„。
+
+
+# ログä¿å­˜é–¢ä¿‚
+# (共通ログ)
+L_YES ã¯ã„
+L_NO ã„ã„ãˆ
+L_LINE ------------------------------------------------------
+
+# (サーãƒãƒ¼ ログ)
+LS_START_UTF8 Log Messages are written with UTF-8 Encoding Format.
+LS_START_1 SoftEther VPN Server エンジンを起動ã—ã¾ã—ãŸã€‚
+LS_START_2 %S %S
+LS_START_3 %S
+LS_END_1 SoftEther VPN Server エンジンã¯æ­£å¸¸ã«ã‚·ãƒ£ãƒƒãƒˆãƒ€ã‚¦ãƒ³ã•ã‚Œã¾ã—ãŸã€‚
+LS_END_2 サーãƒãƒ¼ エンジンã®ã‚·ãƒ£ãƒƒãƒˆãƒ€ã‚¦ãƒ³å‡¦ç†ã‚’開始ã—ã¦ã„ã¾ã™ã€‚
+LS_STOP_ALL_LISTENER ã™ã¹ã¦ã® TCP リスナーをåœæ­¢ã—ã¾ã™ã€‚
+LS_STOP_ALL_LISTENER_2 ã™ã¹ã¦ã® TCP リスナーã®åœæ­¢ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_STOP_ALL_HUB ã™ã¹ã¦ã®ä»®æƒ³ HUB ã‚’åœæ­¢ã—ã¦ã„ã¾ã™ã€‚
+LS_STOP_ALL_HUB_2 ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®åœæ­¢ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_STOP_CEDAR Cedar 通信モジュールをシャットダウンã—ã¦ã„ã¾ã™ã€‚
+LS_STOP_CEDAR_2 Cedar 通信モジュールをシャットダウンã—ã¾ã—ãŸã€‚
+LS_STOP_FARM_MEMBER クラスタコントローラã¸ã®æŽ¥ç¶šã‚’切断ã—ã¦ã„ã¾ã™ã€‚
+LS_STOP_FARM_MEMBER_2 クラスタコントローラã¨ã®é–“ã®æŽ¥ç¶šã®åˆ‡æ–­ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_STOP_FARM_CONTROL クラスタコントローラをåœæ­¢ã—ã¦ã„ã¾ã™ã€‚
+LS_STOP_FARM_CONTROL_2 クラスタコントローラã®åœæ­¢ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_ENUM_ETHERNET_1 Ethernet デãƒã‚¤ã‚¹ã®åˆ—挙を行ã„ã¾ã—ãŸã€‚
+LS_ENUM_ETHERNET_2 デãƒã‚¤ã‚¹ %u: "%S"
+LS_LOAD_CONFIG_1 設定ファイルã®èª­ã¿è¾¼ã¿ã‚’è¡Œã„ã¾ã™ã€‚
+LS_LOAD_CONFIG_2 設定ファイルã®èª­ã¿è¾¼ã¿ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_LOAD_CONFIG_3 設定ファイルãŒå­˜åœ¨ã—ã¾ã›ã‚“。åˆæœŸè¨­å®šã§ã®èµ·å‹•ã‚’試行ã—ã¾ã™ã€‚
+LS_INIT_SAVE_THREAD 自動設定ä¿å­˜ã®ãŸã‚ã®ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã‚¿ã‚¹ã‚¯ã‚’èµ·å‹•ã—ã¾ã™ã€‚ä¿å­˜é–“隔㯠%u 秒ã§ã™ã€‚ãªãŠã€è‡ªå‹•ä¿å­˜ã®é–“éš”ã¯ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã® AutoSaveConfigSpan パラメータã§å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+LS_BAD_CONFIG 設定ファイルã®å†…容ãŒä¸æ­£ã§ã™ã€‚読ã¿è¾¼ã¿ã‚’終了ã—ã¾ã™ã€‚
+LS_LISTENER_START_1 TCP リスナー (ãƒãƒ¼ãƒˆ %u) を開始ã—ã¦ã„ã¾ã™ã€‚
+LS_LISTENER_START_2 TCP リスナー (ãƒãƒ¼ãƒˆ %u) ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚クライアントã‹ã‚‰ã®æŽ¥ç¶šã‚’å¾…æ©Ÿã—ã¦ã„ã¾ã™ã€‚
+LS_LISTENER_START_3 TCP リスナー (ãƒãƒ¼ãƒˆ %u) ã§ãƒãƒ¼ãƒˆã‚’ Listen 状態ã«è¨­å®šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚æˆåŠŸã™ã‚‹ã¾ã§ä¸€å®šé–“éš”ã§è©¦è¡Œã—ã¾ã™ã€‚
+LS_LISTENER_ACCEPT TCP リスナー (ãƒãƒ¼ãƒˆ %u) ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ (IP アドレス %S, ホストå "%S", ãƒãƒ¼ãƒˆç•ªå· %u) ãŒæŽ¥ç¶šã—ã¾ã—ãŸã€‚
+LS_LISTENER_DISCONNECT クライアント (IP アドレス %S, ãƒãƒ¼ãƒˆç•ªå· %u) ã¨ã®é–“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯åˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+LS_LISTENER_DOS TCP リスナー (ãƒãƒ¼ãƒˆ %u) ã«å¯¾ã™ã‚‹ DoS アタックを検出ã—ã¾ã—ãŸã€‚接続元㯠IP アドレス %S, ãƒãƒ¼ãƒˆç•ªå· %u ã§ã™ã€‚ã“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯å¼·åˆ¶åˆ‡æ–­ã—ã¾ã™ã€‚
+LS_LISTENER_MAXUEC TCP リスナーãŒå‡¦ç†ã—ã¦ã„る未処ç†ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ãŒ %u ã«é”ã—㟠(ç¾åœ¨æ•° = %u) ãŸã‚ã€ä¸€æ™‚çš„ã«å—付接続数を制é™ã—ã¦ã„ã¾ã™ã€‚
+LS_LISTENER_STOP_1 TCP リスナー (ãƒãƒ¼ãƒˆ %u) ã‚’åœæ­¢ã—ã¦ã„ã¾ã™ã€‚
+LS_LISTENER_STOP_2 TCP リスナー (ãƒãƒ¼ãƒˆ %u) ã®åœæ­¢ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LS_HUB_START 仮想 HUB "%S" を開始ã—ã¾ã—ãŸã€‚
+LS_HUB_STOP 仮想 HUB "%S" ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+LS_HUB_MAC 仮想 HUB "%S" ã® MAC アドレス㯠"%S" ã§ã™ã€‚
+LS_NODE_INFO_TAG クライアント製å“å "%S", クライアントãƒãƒ¼ã‚¸ãƒ§ãƒ³ %u, ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ“ãƒ«ãƒ‰ç•ªå· %u, サーãƒãƒ¼è£½å“å "%S", サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %u, サーãƒãƒ¼ãƒ“ãƒ«ãƒ‰ç•ªå· %u, クライアント OS å "%S", クライアント OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³ "%S", クライアントプロダクト ID "%S", クライアントホストå "%S", クライアント IP アドレス "%S", クライアントãƒãƒ¼ãƒˆç•ªå· %u, サーãƒãƒ¼ãƒ›ã‚¹ãƒˆå "%S", サーãƒãƒ¼ IP アドレス "%S", サーãƒãƒ¼ãƒãƒ¼ãƒˆç•ªå· %u, プロキシホストå "%S", プロキシ IP アドレス "%S", プロキシãƒãƒ¼ãƒˆç•ªå· %u, 仮想 HUB å "%S", クライアントユニーク ID "%S"
+LS_CONNECTION_START_1 クライアント (IP アドレス %S, ホストå "%S", ãƒãƒ¼ãƒˆç•ªå· %u) ã«å¯¾å¿œã™ã‚‹ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚
+LS_CONNECTION_END_1 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ãŒçµ‚了ã—ã¾ã—ãŸã€‚
+LS_SSL_START コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ã«å¯¾ã™ã‚‹ SSL 通信ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚æš—å·åŒ–アルゴリズムå㯠"%S" ã§ã™ã€‚
+LS_CONNECTION_ERROR コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ã¯ç†ç”± "%s" (コード %u) ã§çµ‚了ã—ã¾ã—ãŸã€‚
+LS_FARMMEMBER_NOT_ADMIN コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": サーãƒãƒ¼ã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã§ã™ãŒã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ä»®æƒ³ HUB "%S" ã«ç®¡ç†è€…ユーザー "%S" 以外ã§ç›´æŽ¥æŽ¥ç¶šã—よã†ã¨è©¦ã¿ã¾ã—ãŸã€‚クライアントãŒæ示ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼å㯠"%S" ã§ã™ã€‚アクセスã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。
+LS_HUB_NOT_FOUND コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": クライアントãŒæŽ¥ç¶šã—よã†ã¨ã—ãŸä»®æƒ³ HUB "%S" ã¯ã‚µãƒ¼ãƒãƒ¼ä¸Šã«å­˜åœ¨ã—ã¾ã›ã‚“。
+LS_IP_DENIED コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": クライアントã®æŽ¥ç¶šå…ƒ IP アドレス "%S" ã¯ã€ä»®æƒ³ HUB ã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã«ã‚ˆã£ã¦æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+LS_LICENSE_ERROR コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ライセンス上ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸãŸã‚ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+LS_BETA_EXPIRES ライセンスエラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ベータ版ã®ä½¿ç”¨æœŸé™ãŒçµ‚了ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„ベータ版ã¾ãŸã¯å®Œæˆç‰ˆã‚’ http://selinks.org/ ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¦ãã ã•ã„。
+LS_TICKET_1 クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ "%S" ã«å¯¾ã—ã¦æ–°ã—ã„クライアントèªè¨¼ãƒã‚±ãƒƒãƒˆã‚’発行ã—ã¾ã—ãŸã€‚仮想 HUB "%S", ユーザーå "%S" ("%S"), セッションå "%S", ãƒã‚±ãƒƒãƒˆ "%S"
+LS_TICKET_2 クラスタコントローラã‹ã‚‰æ–°ã—ã„クライアントèªè¨¼ãƒã‚±ãƒƒãƒˆã‚’å—é ˜ã—ã¾ã—ãŸã€‚仮想 HUB "%S", ユーザーå "%S" ("%S"), セッションå "%S", ãƒã‚±ãƒƒãƒˆ "%S", æœ‰åŠ¹æœŸé™ %u 秒
+LS_ENUM_HUB コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚µãƒ¼ãƒãƒ¼ä¸Šã® %u 個ã®ä»®æƒ³ HUB を列挙ã—ã¾ã—ãŸã€‚
+LS_FARM_ACCEPT_1 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«æŽ¥ç¶šã‚’è¦æ±‚ã—ã¦ãã¾ã—ãŸãŒã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+LS_FARM_ACCEPT_2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«æŽ¥ç¶šã‚’è¦æ±‚ã—ã¦ãã¾ã—ãŸãŒã€èªè¨¼ãƒ‘スワードãŒé–“é•ã£ã¦ã„ã‚‹ãŸã‚ã€æŽ¥ç¶šã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚
+LS_FARM_ACCEPT_3 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã™ã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«æŽ¥ç¶šã‚’è¦æ±‚ã—ã¦ãã¾ã—ãŸã€‚èªè¨¼ã«æˆåŠŸã—ã¾ã—ãŸã€‚
+LS_FARM_SERV_START クラスタメンãƒã¨ã®é–“ã§æŽ¥ç¶šã‚’確立ã—ã¾ã—ãŸã€‚IP アドレス %S, ホストå "%S"
+LS_FARM_SERV_END クラスタメンム"%S" ã¨ã®é–“ã®æŽ¥ç¶šã‚’解除ã—ã¾ã—ãŸã€‚
+LS_FARM_CONNECT_1 クラスタコントローラ "%S" ã¸ã®æŽ¥ç¶šã‚’開始ã—ã¾ã—ãŸã€‚
+LS_FARM_CONNECT_2 クラスタコントローラ "%S" ã¸ã®æŽ¥ç¶šãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚エラー: %s (コード %u)
+LS_FARM_CONNECT_3 クラスタコントローラ "%S" ã¸ã® TCP 接続ã«å¤±æ•—ã—ã¾ã—ãŸã€‚接続ãŒæˆåŠŸã™ã‚‹ã¾ã§ %u 秒間隔ã§è©¦è¡Œã—ã¾ã™ã€‚
+LS_FARM_DISCONNECT クラスタコントローラã¸ã®æŽ¥ç¶šã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+LS_FARM_START クラスタコントローラã¸ã®æŽ¥ç¶šãŒå®Œäº†ã—ã¾ã—ãŸã€‚クラスタメンãƒã¨ã—ã¦ã®å‹•ä½œã‚’開始ã—ã¾ã™ã€‚
+LS_LICENSE_NOT_VPNSERVER コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ライセンスエラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚VPN Server 製å“ライセンスãŒç™»éŒ²ã•ã‚Œã¦ã„ãªã„時ã«ã€VPN Client ãŒæŽ¥ç¶šã—よã†ã¨ã—ã¾ã—ãŸã€‚
+LS_LICENSE_NOT_VPNCLUSTER コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ライセンスエラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã“ã® VPN Server ã«ã¯ç¾åœ¨ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°æ©Ÿèƒ½ã‚’使用ã§ããªã„種類ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ãŒã€ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œä¸­ã« VPN Client ãŒæŽ¥ç¶šã—よã†ã¨ã—ã¾ã—ãŸã€‚VPN Server ã‚’å†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+LS_LICENSE_VIOLATION コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": VPN Server ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹é•åãŒç™ºç”Ÿã—ã¦ã„ã‚‹ãŸã‚ã€æŽ¥ç¶šã‚’å—ã‘付ã‘られã¾ã›ã‚“。
+LS_LICENSE_VIOLATION_DETECTED ライセンスé•åを検出ã—ã¾ã—ãŸã€‚別㮠VPN Server ãŒã€ã“ã® VPN Server ã¨åŒã˜ã‚µãƒ¼ãƒãƒ¼ ID "%I64u" ã§å‹•ä½œã—ã¦ã„ã¾ã™ã€‚クラスタ内ã«åŒä¸€ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’使用ã—㟠2 å°ä»¥ä¸Šã® VPN Server ãŒå­˜åœ¨ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚å„ VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æƒ…報を確èªã—ã¦ãã ã•ã„。
+
+
+# (OpenVPN ログ)
+LO_PREFIX_RAW OpenVPN モジュール:
+LO_PREFIX_SESSION OpenVPN セッション %u (%r:%u -> %r:%u):
+LO_PREFIX_CHANNEL OpenVPN セッション %u (%r:%u -> %r:%u) ãƒãƒ£ãƒãƒ« %u:
+LO_NEW_CHANNEL æ–°ã—ã„ãƒãƒ£ãƒãƒ«ã‚’作æˆã—ã¾ã—ãŸã€‚
+LO_CHANNEL_ESTABLISHED_NEWKEY ãƒãƒ£ãƒãƒ«ãŒç¢ºç«‹çŠ¶æ…‹ã«ãªã‚Šã¾ã—㟠(原因: リキーã®å®Œäº†)。
+LO_OPTION_STR_RECV å—ä¿¡ã—ãŸã‚ªãƒ—ション文字列: "%S"
+LO_OPTION_STR_SEND é€ä¿¡ã™ã‚‹ã‚ªãƒ—ション文字列: "%S"
+LO_NEW_SESSION æ–°ã—ã„セッションを作æˆã—ã¾ã—ãŸã€‚プロトコル: %S
+LO_INITIATE_REKEY ã“ã®ãƒãƒ£ãƒãƒ«ã®ãƒªã‚­ãƒ¼ã‚’開始ã—ã¾ã™ã€‚
+LO_CHANNEL_ESTABLISHED ãƒãƒ£ãƒãƒ«ãŒç¢ºç«‹çŠ¶æ…‹ã«ãªã‚Šã¾ã—ãŸã€‚
+LO_PUSH_REPLY 応答オプション文字列ã®å…¨æ–‡: "%S"
+LO_CHANNEL_FAILED ãƒãƒ£ãƒãƒ«ã®æŽ¥ç¶šå‡¦ç†ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LO_CHANNEL_DISCONNECTED_BY_HUB 仮想 HUB ã®ç®¡ç†è€…ã«ã‚ˆã£ã¦ VPN セッションãŒåˆ‡æ–­ã•ã‚ŒãŸãŸã‚ã€ã“ã® OpenVPN ãƒãƒ£ãƒãƒ«ã‚’切断ã—ã¾ã™ã€‚
+LO_DELETE_SESSION セッションを削除ã—ã¾ã™ã€‚
+LO_START OpenVPN サーãƒãƒ¼ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’èµ·å‹•ã—ã¾ã—ãŸã€‚
+LO_STOP OpenVPN サーãƒãƒ¼ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+
+
+# (IPsec ログ)
+LI_PREFIX_RAW IPsec モジュール:
+LI_PREFIX_CLIENT IPsec クライアント %u (%S:%u -> %S:%u):
+LI_PREFIX_IKE IPsec IKE セッション (IKE SA) %u (クライアント: %u) (%S:%u -> %S:%u):
+LI_PREFIX_IPSEC IPsec ESP セッション (IPsec SA) %u (クライアント: %u) (%S:%u -> %S:%u):
+LI_START IPsec ver 2.0 (ISAKMP/IKEv1) 処ç†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’èµ·å‹•ã—ã¾ã—ãŸã€‚
+LI_STOPPING IPsec ver 2.0 (ISAKMP/IKEv1) 処ç†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®çµ‚了処ç†ã‚’開始ã—ã¦ã„ã¾ã™...
+LI_STOP IPsec ver 2.0 (ISAKMP/IKEv1) 処ç†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’終了ã—ã¾ã—ãŸã€‚
+LI_NUM_IPSEC_SA 終了時ã«æ®‹å­˜ã—ã¦ã„㟠IPsec SA ã®æ•°ã¯ %u 個ã§ã—ãŸã€‚
+LI_NUM_IKE_SA 終了時ã«æ®‹å­˜ã—ã¦ã„㟠IKE SA ã®æ•°ã¯ %u 個ã§ã—ãŸã€‚
+LI_NUM_IKE_CLIENTS 終了時ã«æ®‹å­˜ã—ã¦ã„㟠IPsec クライアントã®æ•°ã¯ %u 個ã§ã—ãŸã€‚
+LI_L2TP_SERVER_STARTED L2TP サーãƒãƒ¼ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’開始ã—ã¾ã—ãŸã€‚
+LI_ETHERIP_SERVER_STARTED EtherIP サーãƒãƒ¼ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’開始ã—ã¾ã—ãŸã€‚EtherIP セッション番å·: %u
+LI_DELETE_IKE_CLIENT ã“ã® IPsec クライアントを削除ã—ã¾ã—ãŸã€‚
+LI_DELETE_IKE_SA ã“ã® IKE SA を削除ã—ã¾ã—ãŸã€‚
+LI_DELETE_IPSEC_SA ã“ã® IPsec SA を削除ã—ã¾ã—ãŸã€‚
+LI_START_QM_FROM_SERVER サーãƒãƒ¼å´ã‹ã‚‰ QuickMode ã®æŠ˜è¡ã‚’開始ã—ã¾ã—ãŸã€‚
+LI_START_QM_FROM_CLIENT クライアントå´ã‹ã‚‰ QuickMode ã®æŠ˜è¡ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚
+LI_QM_DH_ERROR Diffie-Hellman アルゴリズムã®è¨ˆç®—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LI_NEW_IKE_CLIENT æ–°ã—ã„ IPsec クライアントを作æˆã—ã¾ã—ãŸã€‚
+LI_NEW_IKE_SA æ–°ã—ã„ IKE SA (%s) を作æˆã—ã¾ã—ãŸã€‚Initiator Cookie: 0x%I64X, Responder Cookie: 0x%I64X, DH グループ: %S, ãƒãƒƒã‚·ãƒ¥ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ : %S, æš—å·åŒ–アルゴリズム: %S, æš—å·éµã‚µã‚¤ã‚º: %u bits, 有効期é™: %u kbytes ã¾ãŸã¯ %u 秒
+LI_TAG_MAINMODE Main Mode
+LI_TAG_AGGRESSIVE Aggressive Mode
+LI_NEW_IPSEC_SA æ–°ã—ã„ IPsec SA (æ–¹å‘: %s) を作æˆã—ã¾ã—ãŸã€‚SPI: 0x%X, DH グループ: %S, ãƒãƒƒã‚·ãƒ¥ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ : %S, æš—å·åŒ–アルゴリズム: %S, æš—å·éµã‚µã‚¤ã‚º: %u bits, 有効期é™: %u kbytes ã¾ãŸã¯ %u 秒
+LI_TAG_SERVER_TO_CLIENT サーãƒãƒ¼ -> クライアント
+LI_TAG_CLIENT_TO_SERVER クライアント -> サーãƒãƒ¼
+LI_IPSEC_SA_SPI_SET ã“ã‚Œã¾ã§æœªå®šã§ã‚ã£ãŸ SPI を変更ã—ã¾ã—ãŸã€‚æ–°ã—ã„ SPI: 0x%X
+LI_IPSEC_SA_ESTABLISHED サーãƒãƒ¼ãƒ»ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆé–“ã§ã“ã® IPsec SA ãŒç¢ºç«‹ã•ã‚Œã¾ã—ãŸã€‚
+LI_IKE_SA_ESTABLISHED サーãƒãƒ¼ãƒ»ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆé–“ã§ã“ã® IKE SA ãŒç¢ºç«‹ã•ã‚Œã¾ã—ãŸã€‚
+LI_IPSEC_NO_TRANSFORM クライアントå´ã‹ã‚‰æ示ã•ã‚ŒãŸ IPsec SA 確立ã®ãŸã‚ã®ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ å€™è£œã«å—諾ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã‚‚ã®ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+LI_IKE_NO_TRANSFORM クライアントå´ã‹ã‚‰æ示ã•ã‚ŒãŸ IKE SA 確立ã®ãŸã‚ã®ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ å€™è£œã«å—諾ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã‚‚ã®ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+LI_IKE_NO_NAT_T ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ IPsec NAT Traversal (RFC 3947 Negotiation of NAT-Traversal in the IKE ã¾ãŸã¯ draft-ietf-ipsec-nat-t-ike) ã«å¯¾å¿œã—ã¦ã„ãªã„ãŸã‚ã€æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+LI_SET_CLIENT_ID ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒ IKE SA ã®ç¢ºç«‹æ™‚ã«æ示ã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ ID 㯠"%S" ã§ã™ã€‚
+LI_CLIENT_MERGE ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ (クライアント %u) ã¨æ—¢å­˜ã®åˆ¥ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ %u ã¨ã¯åŒä¸€ã§ã™ã®ã§ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ %u ã«çµåˆã•ã‚Œã¾ã—ãŸã€‚
+LI_CLIENT_UPDATE ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®ãƒãƒ¼ãƒˆç•ªå·æƒ…å ±ãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚
+
+
+# (EtherIP ログ)
+LE_PREFIX EtherIP / L2TPv3 セッション %u (%S:%u -> %S:%u):
+LE_START_MODULE EtherIP / L2TPv3 モジュールãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚
+LE_STOP EtherIP / L2TPv3 モジュールを終了ã—ã¾ã—ãŸã€‚
+LE_NO_SETTING エラー: クライアント ID "%S" ã«å¯¾ã™ã‚‹ EtherIP / L2TPv3 ã®è¨­å®šãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。EtherIP / L2TPv3 ã®è¨­å®šã‚’ VPN Server ã«ç™»éŒ²ã—ã¦ãã ã•ã„。
+LE_START_IPC EtherIP / L2TPv3 モジュールã‹ã‚‰ä»®æƒ³ HUB "%S" ã¸ã®å†…部的通信ã®æŽ¥ç¶šå‡¦ç†ã‚’開始ã—ã¾ã—ãŸã€‚使用ã™ã‚‹ãƒ¦ãƒ¼ã‚¶å㯠"%S" ã§ã™ã€‚設定ã™ã‚‹ IPv4 TCP MSS (Max Segment Size) 㯠%u bytes ã§ã™ã€‚
+LE_IPC_CONNECT_ERROR EtherIP / L2TPv3 モジュールã‹ã‚‰ä»®æƒ³ HUB "%S" ã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚エラー: %u: %s
+LE_IPC_CONNECT_OK EtherIP / L2TPv3 モジュールã‹ã‚‰ä»®æƒ³ HUB "%S" ã¸ã®æŽ¥ç¶šã«æˆåŠŸã—ã¾ã—ãŸã€‚
+LE_RECONNECT EtherIP / L2TPv3 関係ã®è¨­å®šãŒå¤‰æ›´ã•ã‚ŒãŸãŸã‚ã€å†…部的接続を一旦切断ã—ã¦å†æŽ¥ç¶šã—ã¾ã™ã€‚
+
+
+# (PPP ログ)
+LP_PREFIX %S%SPPP セッション [%S:%u]:
+LP_CONNECTED æ–°ã—ã„ PPP セッション (上ä½ãƒ—ロトコル: %S) ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚PPP クライアント IP アドレス: %S (ホストå: "%S"), PPP クライアント ãƒãƒ¼ãƒˆç•ªå·: %u, PPP サーãƒãƒ¼ IP アドレス: %S, PPP サーãƒãƒ¼ ãƒãƒ¼ãƒˆç•ªå·:%u, クライアント ソフトウェアå: "%S", IPv4 TCP MSS (Max Segment Size): %u bytes
+LP_DISCONNECTED PPP セッションã¯åˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+LP_PAP_REJECTED クライアントã¯èªè¨¼ãƒ—ロトコルã¨ã—㦠"PAP" (Password Authentication Protocolã€ã‚¯ãƒªã‚¢ãƒ†ã‚­ã‚¹ãƒˆãƒ‘スワードèªè¨¼ãƒ—ロトコル) ã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚クライアントå´ã®æŽ¥ç¶šè¨­å®šã§ PAP を有効ã«ã—ã¦å†è©¦è¡Œã—ã¦ãã ã•ã„。
+LP_PAP_MSCHAPV2_REJECTED クライアントã¯èªè¨¼ãƒ—ロトコルã¨ã—㦠"PAP" (Password Authentication Protocolã€ã‚¯ãƒªã‚¢ãƒ†ã‚­ã‚¹ãƒˆãƒ‘スワードèªè¨¼ãƒ—ロトコル) ãŠã‚ˆã³ MS-CHAP v2 プロトコルã®ä¸¡æ–¹ã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚クライアントå´ã®æŽ¥ç¶šè¨­å®šã§ PAP ã¾ãŸã¯ MS-CHAP v2 ã®ã„ãšã‚Œã‹ã‚’有効ã«ã—ã¦å†è©¦è¡Œã—ã¦ãã ã•ã„。
+LP_DISCONNECTED_ABNORMAL PPP プロトコルエラーãŒç™ºç”Ÿã—ãŸã‹ã€ã¾ãŸã¯ PPP セッションãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+LP_NEXT_PROTOCOL_IS_NOT_PAP PAP (Password Authentication Protocol) ã®åˆ¶å¾¡ãƒ‡ãƒ¼ã‚¿ä»¥å¤–ã®ä¸æ­£ãªãƒ—ロトコル (プロトコル番å·: 0x%x) ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚
+LP_PAP_FAILED "PAP" (Password Authentication Protocolã€ã‚¯ãƒªã‚¢ãƒ†ã‚­ã‚¹ãƒˆãƒ‘スワードèªè¨¼ãƒ—ロトコル) ã«ãŠã‘るユーザーèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LP_MSCHAPV2_FAILED "MS-CHAP v2" (Microsoft Challenge and Response Protocol Version 2.0ã€ãƒžã‚¤ã‚¯ãƒ­ã‚½ãƒ•ãƒˆã®æš—å·åŒ–ã•ã‚ŒãŸãƒ‘スワードèªè¨¼ãƒ—ロトコル) ã«ãŠã‘るユーザーèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LP_NEXT_PROTOCOL_IS_NOT_IPCP IPCP (IP Configuration Protocol) ã®åˆ¶å¾¡ãƒ‡ãƒ¼ã‚¿ä»¥å¤–ã®ä¸æ­£ãªãƒ—ロトコル (プロトコル番å·: 0x%x) ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚
+LP_DATA_TIMEOUT PPP データ通信ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚PPP クライアントãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‹ã‚‰åˆ‡æ–­ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+LP_CONTROL_TIMEOUT PPP コントロール通信ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚PPP クライアントã‹ã‚‰å¿œç­”ãŒã‚ã‚Šã¾ã›ã‚“。
+LP_VPN_SESSION_TERMINATED VPN セッションãŒã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã«ã‚ˆã£ã¦åˆ‡æ–­ã•ã‚ŒãŸãŸã‚ã€PPP セッションを切断ã—ã¾ã™ã€‚
+LP_UPPER_PROTOCOL_DISCONNECTED 上ä½ãƒ—ロトコル "%S" ãŒåˆ‡æ–­ã•ã‚ŒãŸãŸã‚ã€PPP セッションを切断ã—ã¾ã™ã€‚
+LP_NORMAL_TERMINATE VPN クライアントå´ã‹ã‚‰ã®åˆ‡æ–­è¦æ±‚ã«ã‚ˆã‚Šã€PPP セッションを切断ã—ã¾ã™ã€‚
+LP_IP_ADDRESS_NOT_DETERMIND VPN クライアント㮠IP アドレスãŒã¾ã æ±ºå®šã•ã‚Œã¦ã„ãªã„ã«ã‚‚ã‹ã‹ã‚らãšã€VPN クライアントãŒé€šä¿¡ã‚’è¡ŒãŠã†ã¨ã—ã¾ã—ãŸã€‚
+LP_DHCP_REQUEST_TRYING DHCP サーãƒãƒ¼ã‹ã‚‰ IP アドレスをå–å¾—ã—よã†ã¨è©¦è¡Œã—ã¦ã„ã¾ã™ã€‚
+LP_DHCP_REQUEST_OK DHCP サーãƒãƒ¼ã‹ã‚‰ IP アドレスをå–å¾—ã—ã¾ã—ãŸã€‚クライアント IP アドレス: %S, サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯: %S, デフォルトゲートウェイ: %S, ドメインå: "%S", DNS サーãƒãƒ¼ 1: %S, DNS サーãƒãƒ¼ 2: %S, WINS サーãƒãƒ¼ 1: %S, WINS サーãƒãƒ¼ 2: %S, DHCP サーãƒãƒ¼ IP アドレス: %S, リース時間: %u 秒
+LP_DHCP_REQUEST_NG DHCP サーãƒãƒ¼ã‹ã‚‰ã® IP アドレスã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚PPP ã®é€šä¿¡ã‚’å—諾ã™ã‚‹ãŸã‚ã«ã¯ DHCP サーãƒãƒ¼ãŒå¿…è¦ã§ã™ã€‚仮想 HUB ã® Ethernet セグメント上㧠DHCP サーãƒãƒ¼ãŒæ­£ã—ã動作ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。DHCP サーãƒãƒ¼ã‚’用æ„ã™ã‚‹ã“ã¨ãŒã§ããªã„å ´åˆã¯ã€ä»®æƒ³ HUB ã® SecureNAT 機能を用ã„ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+LP_DHCP_INFORM_TRYING DHCP サーãƒãƒ¼ã‹ã‚‰ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚„デフォルトゲートウェイãªã©ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æƒ…報をå–å¾—ã—よã†ã¨è©¦è¡Œã—ã¦ã„ã¾ã™ã€‚
+LP_DHCP_INFORM_OK DHCP サーãƒãƒ¼ã‹ã‚‰ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æƒ…報をå–å¾—ã—ã¾ã—ãŸã€‚サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯: %S, デフォルトゲートウェイ: %S, ドメインå: "%S", DNS サーãƒãƒ¼ 1: %S, DNS サーãƒãƒ¼ 2: %S, WINS サーãƒãƒ¼ 1: %S, WINS サーãƒãƒ¼ 2: %S, DHCP サーãƒãƒ¼ IP アドレス: %S
+LP_DHCP_INFORM_NG DHCP サーãƒãƒ¼ã‹ã‚‰ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æƒ…å ±ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚PPP ã®é€šä¿¡ã‚’å—諾ã™ã‚‹ãŸã‚ã«ã¯ DHCP サーãƒãƒ¼ãŒå¿…è¦ã§ã™ã€‚仮想 HUB ã® Ethernet セグメント上㧠DHCP サーãƒãƒ¼ãŒæ­£ã—ã動作ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。DHCP サーãƒãƒ¼ã‚’用æ„ã™ã‚‹ã“ã¨ãŒã§ããªã„å ´åˆã¯ã€ä»®æƒ³ HUB ã® SecureNAT 機能を用ã„ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+LP_SET_IPV4_PARAM クライアント㮠IP アドレスãŠã‚ˆã³ãã®ä»–ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æƒ…å ±ã®è¨­å®šãŒå®Œäº†ã—ã¾ã—ãŸã€‚クライアント IP アドレス: %S, サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯: %S, デフォルトゲートウェイ: %S, DNS サーãƒãƒ¼ 1: %S, DNS サーãƒãƒ¼ 2: %S, WINS サーãƒãƒ¼ 1: %S, WINS サーãƒãƒ¼ 2: %S
+
+
+# (仮想 HUB ログ)
+LH_ONLINE 仮想 HUB ãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ãªã‚Šã¾ã—ãŸã€‚
+LH_OFFLINE 仮想 HUB ãŒã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã«ãªã‚Šã¾ã—ãŸã€‚
+LH_CONNECT_CLIENT コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" (IP アドレス %S, ホストå %S, ãƒãƒ¼ãƒˆç•ªå· %u, クライアントå "%S", ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %S ビルド %u) ãŒä»®æƒ³ HUB ã¸ã®æŽ¥ç¶šã‚’試行ã—ã¦ã„ã¾ã™ã€‚æ示ã—ã¦ã„ã‚‹èªè¨¼æ–¹æ³•ã¯ "%s" ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼å㯠"%S" ã§ã™ã€‚
+LH_AUTH_UNKNOWN ä¸æ˜Žãªèªè¨¼ãƒ¡ã‚½ãƒƒãƒ‰
+LH_AUTH_ANONYMOUS 匿åèªè¨¼
+LH_AUTH_PASSWORD パスワードèªè¨¼
+LH_AUTH_PLAIN_PASSWORD 外部サーãƒãƒ¼èªè¨¼
+LH_AUTH_CERT 証明書èªè¨¼
+LH_AUTH_TICKET ãƒã‚±ãƒƒãƒˆèªè¨¼
+LH_AUTH_RADIUS_NOT_SUPPORT コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®èªè¨¼æ–¹æ³•ã¨ã—㦠RADIUS èªè¨¼ã¾ãŸã¯ Active Directory èªè¨¼ (NT ドメインèªè¨¼) ãŒæŒ‡å®šã•ã‚Œã¾ã—ãŸãŒã€ç¾åœ¨ã® VPN Server ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã¯ "%S" ã§ã‚ã‚‹ãŸã‚ã€RADIUS èªè¨¼ã¾ãŸã¯ Active Directory èªè¨¼ (NT ドメインèªè¨¼) を使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。接続ã¯æ‹’å¦ã•ã‚Œã¾ã™ã€‚
+LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®èªè¨¼æ–¹æ³•ã¨ã—㦠RADIUS èªè¨¼ã¾ãŸã¯ Active Directory èªè¨¼ (NT ドメインèªè¨¼) ãŒæŒ‡å®šã•ã‚Œã¾ã—ãŸãŒã€RADIUS èªè¨¼ã¾ãŸã¯ Active Directory èªè¨¼ (NT ドメインèªè¨¼) を使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。ã“ã®æ©Ÿèƒ½ã¯ã‚ªãƒ¼ãƒ—ンソース版 SoftEther VPN ã«ã¯ã¾ã å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã›ã‚“。接続ã¯æ‹’å¦ã•ã‚Œã¾ã™ã€‚
+LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®èªè¨¼æ–¹æ³•ã¨ã—ã¦è¨¼æ˜Žæ›¸èªè¨¼ãŒæŒ‡å®šã•ã‚Œã¾ã—ãŸãŒã€è¨¼æ˜Žæ›¸èªè¨¼ã‚’使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。ã“ã®æ©Ÿèƒ½ã¯ã‚ªãƒ¼ãƒ—ンソース版 SoftEther VPN ã«ã¯ã¾ã å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã›ã‚“。接続ã¯æ‹’å¦ã•ã‚Œã¾ã™ã€‚
+LH_AUTH_OK コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã¨ã—ã¦æ­£ã—ãèªè¨¼ã•ã‚Œã¾ã—ãŸã€‚
+LH_AUTH_OK_CERT 仮想 HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒžãƒãƒ¼ã‚¸ãƒ£ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ "%S" ãŒãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹éš›ã®è¨¼æ˜Žæ›¸ã¨ã—ã¦ã€æ¬¡ã®è¨¼æ˜Žæ›¸ã‚’ VPN Client ã‹ã‚‰å—ç†ã—ã€ãã®å†…容を承èªã—ã¾ã—ãŸ: %s
+LH_AUTH_NG_CERT 仮想 HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒžãƒãƒ¼ã‚¸ãƒ£ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ "%S" ãŒãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹éš›ã®è¨¼æ˜Žæ›¸ã¨ã—ã¦ã€æ¬¡ã®è¨¼æ˜Žæ›¸ã‚’ VPN Client ã‹ã‚‰å—ç†ã—ã¾ã—ãŸãŒã€ã“ã®è¨¼æ˜Žæ›¸ã¯ä»®æƒ³ HUB ã®ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ä¸€è¦§ã«ç™»éŒ²ã•ã‚Œã¦ã„る内容ã«ä¸€è‡´ã™ã‚‹ãŸã‚æ‹’å¦ã—ã¾ã—ãŸ: %s
+LH_AUTH_NG コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザーèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚æ示ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼å㯠"%S" ã§ã—ãŸã€‚
+LH_LOCAL_ONLY コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®ãƒ‘スワードãŒç©ºç™½ã®ãŸã‚ã€ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰ã®ãƒ­ã‚°ã‚¤ãƒ³ã¯æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+LH_POLICY_ACCESS_NG コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã¯ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã«ã‚ˆã£ã¦ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¦ã„ã¾ã™ã€‚
+LH_USER_EXPIRES コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¦ãŠã‚Šã€ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
+LH_CLIENT_VERSION_OLD コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": クライアントã®ãƒ“ルド番å·ã¯ %u ã§ã™ã€‚最低ã§ã‚‚ビルド %u 以上ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®ã¿æŽ¥ç¶šãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚
+LH_CLIENT_ID_REQUIRED コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": クライアントã‹ã‚‰é€ä»˜ã•ã‚ŒãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ ID 㯠%u ã§ã™ãŒã€ã“ã®ä»®æƒ³ HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ RequiredClientId ã®å€¤ã¯ %u ã§ã™ã€‚
+LH_FARM_SELECT_1 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": クラスタコントローラã¯ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®æŽ¥ç¶šå…ˆã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚’決定ã—ã¦ã„ã¾ã™ã€‚
+LH_FARM_SELECT_2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 接続先クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã®æ±ºå®šã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LH_FARM_SELECT_3 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 接続先クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦ç¾åœ¨ã®ã“ã® VPN Server ãŒæ±ºå®šã•ã‚Œã¾ã—ãŸã€‚接続å—ã‘入れを続行ã—ã¾ã™ã€‚
+LH_FARM_SELECT_4 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 接続先クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦ã‚µãƒ¼ãƒãƒ¼ "%S" ãŒæ±ºå®šã•ã‚Œã¾ã—ãŸã€‚クライアントã«å¯¾ã—ã¦ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¸æŽ¥ç¶šã‚’リダイレクトã™ã‚‹ã‚ˆã†ã«æŒ‡ç¤ºã—ã¾ã™ã€‚
+LH_MAX_SESSION コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 仮想 HUB ãŒè¨­å®šã•ã‚ŒãŸæœ€å¤§ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•° %u ã«é”ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„セッションã¯ä½œæˆã§ãã¾ã›ã‚“。
+LH_MAX_SESSION_CLIENT コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 仮想 HUB ãŒè¨­å®šã•ã‚ŒãŸæœ€å¤§ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚»ãƒƒã‚·ãƒ§ãƒ³æ•° %u ã«é”ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„セッションã¯ä½œæˆã§ãã¾ã›ã‚“。
+LH_MAX_SESSION_BRIDGE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": 仮想 HUB ãŒè¨­å®šã•ã‚ŒãŸæœ€å¤§ãƒ–リッジセッション数 %u ã«é”ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„セッションã¯ä½œæˆã§ãã¾ã›ã‚“。
+LH_MAX_SESSION_2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": VPN Server 上ã§ç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãる最大セッション数 %u ã«é”ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„セッションã¯ä½œæˆã§ãã¾ã›ã‚“。
+LH_NEW_SESSION コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": æ–°ã—ã„セッション "%S" ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚(IP アドレス %S, ãƒãƒ¼ãƒˆç•ªå· %u, 物ç†ãƒ¬ã‚¤ãƒ¤ã®ãƒ—ロトコル: "%S")
+LH_SET_SESSION セッション "%S": パラメータãŒè¨­å®šã•ã‚Œã¾ã—ãŸã€‚最大 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•° %u, æš—å·åŒ–ã®ä½¿ç”¨ %s, 圧縮ã®ä½¿ç”¨ %s, åŠäºŒé‡é€šä¿¡ã®ä½¿ç”¨ %s, タイムアウト %u 秒
+LH_NODE_INFO セッション "%S": VPN Client ã®è©³ç´°: (%s)
+LH_INVALID_SIGNATURE セッション "%S": 接続ã—ã¦ããŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒç„¡åŠ¹ãªãƒ—ロトコルデータをé€ä¿¡ã—ã¾ã—ãŸã€‚クライアントã¨ã®é€šä¿¡ãŒæ­£å¸¸ã«ã§ãã¾ã›ã‚“。クライアントã¨ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¨ã®é–“ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å›žç·šã«ç•°å¸¸ãŒç„¡ã„ã‹ã©ã†ã‹ã€ç‰¹æ®Šãªé€éŽåž‹ãƒ‘ケット書ãæ›ãˆè£…置を設置ã—ã¦ã„ãªã„ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。
+LH_END_SESSION セッション "%S": セッションãŒçµ‚了ã—ã¾ã—ãŸã€‚統計情報ã¯æ¬¡ã®é€šã‚Šã§ã™ã€‚åˆè¨ˆé€ä¿¡ãƒ‡ãƒ¼ã‚¿ã‚µã‚¤ã‚º: %I64u ãƒã‚¤ãƒˆ, åˆè¨ˆå—信データサイズ: %I64u ãƒã‚¤ãƒˆ
+LH_BCAST_STORM セッション "%S": 大é‡ã®ãƒ–ロードキャストパケットを検出ã—ã¾ã—ãŸã€‚ãƒãƒªã‚·ãƒ¼ã«å¾“ã£ã¦ãƒ‘ケットを破棄ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚é€ä¿¡å…ƒ MAC アドレス㯠%S, é€ä¿¡å…ƒ IP アドレス㯠%S, 宛先 IP アドレス㯠%S ã§ã™ã€‚ブロードキャストパケット数㯠1 秒間㫠%u 個以上ã§ã™ (ãªãŠã“ã®æƒ…å ±ã¯ãƒ‘ケットã®ä¸€éƒ¨ã‚’機械的ã«è§£æžã—ãŸçµæžœã§ã‚ã‚Šã€ä¸æ­£ç¢ºãªå ´åˆãŒã‚ã‚Šã¾ã™)。
+LH_DHCP_FORCE セッション "%S": DHCP サーãƒãƒ¼ãŒå‰²ã‚Šå½“ã¦ã¦ã„ãªã„ IP アドレス %S を使用ã—よã†ã¨ã—ãŸãŸã‚ã€ãƒ‘ケットã¯ç ´æ£„ã•ã‚Œã¾ã—ãŸã€‚
+LH_MAC_LIMIT セッション "%S": æ–°ã—ã„ MAC アドレス "%S" を関連付ã‘よã†ã¨ã—ã¾ã—ãŸãŒã€ã™ã§ã«ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã¯ %u 個㮠MAC アドレスãŒé–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚セキュリティãƒãƒªã‚·ãƒ¼ã§ã¯ã€ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯æœ€å¤§ %u 個㮠MAC アドレスをæŒã¤ã“ã¨ãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã™ã€‚パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚
+LH_BRIDGE_LIMIT セッション "%S": æ–°ã—ã„ MAC アドレス "%S" を関連付ã‘よã†ã¨ã—ã¾ã—ãŸãŒã€ã™ã§ã«ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã¯ %u 個㮠MAC アドレスãŒé–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚セキュリティãƒãƒªã‚·ãƒ¼ã§ã¯ã€ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ãƒ–リッジをç¦æ­¢ã•ã‚Œã¦ã„ã‚‹ã®ã§ã€ %u 個より多ㄠMAC アドレスをæŒã¤ã“ã¨ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚
+LH_MAC_REGIST セッション "%S": æ–°ã—ã„ MAC アドレス "%S" ãŒé–¢é€£ä»˜ã‘られã¾ã—ãŸã€‚
+LH_MAC_REGIST_VLAN セッション "%S": æ–°ã—ã„ MAC アドレス "%S" (VLAN ID: %u) ãŒé–¢é€£ä»˜ã‘られã¾ã—ãŸã€‚
+LH_IP_LIMIT セッション "%S": æ–°ã—ã„ IP アドレス %S を関連付ã‘よã†ã¨ã—ã¾ã—ãŸãŒã€ã™ã§ã«ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã¯ %u 個㮠IP アドレスãŒé–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚セキュリティãƒãƒªã‚·ãƒ¼ã§ã¯ã€ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯æœ€å¤§ %u 個㮠IP アドレスをæŒã¤ã“ã¨ãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã™ã€‚パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚
+LH_ROUTING_LIMIT セッション "%S": æ–°ã—ã„ IP アドレス %S を関連付ã‘よã†ã¨ã—ã¾ã—ãŸãŒã€ã™ã§ã«ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã¯ %u 個㮠IP アドレスãŒé–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚セキュリティãƒãƒªã‚·ãƒ¼ã§ã¯ã€ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚’ç¦æ­¢ã•ã‚Œã¦ã„ã‚‹ã®ã§ã€%u 個より多ㄠIP アドレスをæŒã¤ã“ã¨ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚
+LH_IP_CONFLICT セッション "%S": IP アドレス %S を使用ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã“ã® IP アドレスã¯æ—¢ã«åˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ "%S" (MAC アドレス: "%S") ã«ã‚ˆã£ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã«ã‚ˆã‚Šã€ä»–ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒä½¿ç”¨ä¸­ã® IP アドレスã¨ã®é‡è¤‡ã¯ç¦æ­¢ã•ã‚Œã¾ã™ã€‚パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚詳細情報: CreatedTime=%I64u, UpdatedTime=%I64u, DhcpAllocated=%u, Now=%I64u
+LH_NO_SERVER セッション "%S": ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«å¯¾ã—㦠%S:%u ã‹ã‚‰ %S:%u ã¸ã® TCP/IP 接続è¦æ±‚ãŒã‚ã‚Šã¾ã—ãŸãŒã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã«ã‚ˆã‚Šã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œãŒç¦æ­¢ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ãƒ‘ケットã¯ç ´æ£„ã•ã‚Œã¾ã—ãŸã€‚
+LH_NO_DHCP セッション "%S": ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸Šã®ãƒ›ã‚¹ãƒˆ %S ãŒåˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸Šã®ãƒ›ã‚¹ãƒˆ %S ã«å¯¾ã—㦠DHCP サーãƒãƒ¼ã¨ã—㦠IP アドレスを割り当ã¦ã‚‹ãƒ‘ケットをé€ä¿¡ã—ã¾ã—ãŸãŒã€ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã«ã‚ˆã‚Š DHCP サーãƒãƒ¼ã¨ã—ã¦ã®å‹•ä½œã¯ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚パケットã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚
+LH_REGIST_DHCP セッション "%S": ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸Šã®ãƒ›ã‚¹ãƒˆ "%S" (%S) ã® DHCP サーãƒãƒ¼ã¯ã€åˆ¥ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ "%S" 上ã®ãƒ›ã‚¹ãƒˆ "%S" ã«å¯¾ã—ã¦æ–°ã—ã„ IP アドレス %S を割り当ã¦ã¾ã—ãŸã€‚
+LH_BRIDGE_1 セッション "%S": ローカルブリッジを物ç†çš„㪠Ethernet インターフェイス "%S" ã¨ã®é–“ã§é–‹å§‹ã—ã¾ã—ãŸã€‚
+LH_BRIDGE_2 セッション "%S": 物ç†çš„㪠Ethernet インターフェイス "%S" ã¨ã®é–“ã®é€šä¿¡ã«å¤±æ•—ã—ãŸãŸã‚ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジをåœæ­¢ã—ã¾ã—ãŸã€‚
+LH_SET_MTU セッション "%S": 物ç†çš„㪠Ethernet インターフェイス "%S" ã® MTU ã¯ç¾åœ¨ %u ã§ã™ã€‚%u ãƒã‚¤ãƒˆã® Ethernet パケットをé€å—ä¿¡ã™ã‚‹ãŸã‚ã€ã“れを %u ã«è¨­å®šå¤‰æ›´ã—ã¾ã—ãŸã€‚
+LH_SET_MTU_ERROR セッション "%S": エラー: 物ç†çš„㪠Ethernet インターフェイス "%S" ã® MTU ã¯ç¾åœ¨ %u ã§ã™ã€‚%u ãƒã‚¤ãƒˆã® Ethernet パケットをé€å—ä¿¡ã™ã‚‹ãŸã‚ MTU ã‚’ %u ã«è¨­å®šã™ã‚‹ã“ã¨ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã“ã®ç‰©ç†çš„㪠Ethernet インターフェイスãŠã‚ˆã³ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŒ 1,514 ãƒã‚¤ãƒˆ (ペイロード部分: 1,500 ãƒã‚¤ãƒˆ) を超ãˆã‚‹ Ethernet パケットã®é€å—ä¿¡ã«å¯¾å¿œã—ã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã®å ´åˆã€ã‚µã‚¤ã‚ºã®å¤§ããªã‚¿ã‚° VLAN パケットã®é€å—ä¿¡ã¯ã§ãã¾ã›ã‚“。物ç†çš„㪠Ethernet インターフェイスã®ç¨®é¡žã‚’ Jumbo Frames ã«å¯¾å¿œã—ãŸã‚‚ã®ã«äº¤æ›ã™ã‚‹ã‹ã€ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã‚’アップデートã—ã¦ã¿ã¦ãã ã•ã„。ã¾ãŸã€ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã‚„デãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã®è¨­å®šã§ã€Jumbo Frames を許å¯ã—ã¦ãã ã•ã„。
+LH_START_BRIDGE ローカルブリッジ接続 "%S" を開始ã—ã¾ã—ãŸã€‚ブリッジセッション "%S" を作æˆã—ã¾ã—ãŸã€‚
+LH_STOP_BRIDGE ローカルブリッジ接続 "%S" ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+LH_LINK_START カスケード接続 "%s" ãŒç¢ºç«‹ã•ã‚Œã¾ã—ãŸã€‚カスケードセッション "%S" を作æˆã—ã¾ã—ãŸã€‚
+LH_LINK_STOP カスケード接続 "%s" ãŒåœæ­¢ã—ã¾ã—ãŸã€‚
+LH_NAT_START SecureNAT ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚SecureNAT セッション "%S" を作æˆã—ã¾ã—ãŸã€‚
+LH_NAT_STOP SecureNAT ãŒåœæ­¢ã—ã¾ã—ãŸã€‚
+LH_NAT_TCP_SUCCEED TCP セッション %u: ホスト "%S (%S)", ãƒãƒ¼ãƒˆ %u ã¸ã®æŽ¥ç¶šã«æˆåŠŸã—ã¾ã—ãŸã€‚
+LH_NAT_TCP_FAILED TCP セッション %u: ホスト "%S", ãƒãƒ¼ãƒˆ %u ã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+LH_NAT_TCP_DELETED TCP セッション %u ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚
+LH_NAT_TCP_CREATED TCP セッション %u ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚接続元 %S:%u, 接続先 %S:%u
+LH_NAT_UDP_DELETED UDP セッション %u ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚
+LH_NAT_UDP_CREATED UDP セッション %u ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚接続元 %S:%u, 接続先 %S:%u
+LH_NAT_DHCP_CREATED DHCP エントリ %u ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚MAC アドレス: %S, IP アドレス: %S, ホストå: %S, 有効期é™: %u 秒
+LH_CHANGE_PASSWORD_1 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" (IP アドレス %S) ãŒãƒ‘スワード変更モードã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+LH_CHANGE_PASSWORD_2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": パスワードã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚指定ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ "%S" ã¯å­˜åœ¨ã—ã¾ã›ã‚“。
+LH_CHANGE_PASSWORD_3 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": パスワードã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ユーザー "%S" ã®èªè¨¼æ–¹æ³•ã¯ãƒ‘スワードèªè¨¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+LH_CHANGE_PASSWORD_4 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": パスワードã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ユーザー "%S" ã®å¤ã„パスワードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚
+LH_CHANGE_PASSWORD_5 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ã®ãƒ‘スワードを変更ã—ã¾ã—ãŸã€‚
+LH_CONNECT_1 カスケード接続 "%s": %u 回目ã®æŽ¥ç¶šå‹•ä½œã‚’開始ã—ã¾ã™ã€‚
+LH_CONNECT_2 カスケード接続 "%s": 接続ãŒå®Œäº†ã—ã¾ã—ãŸã€‚セッションå: "%S"
+LH_CONNECT_ERROR カスケード接続 "%s": 接続ãŒåˆ‡æ–­ã•ã‚ŒãŸã‹ã€æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚ç†ç”±: %s (コード %u)
+LH_POLICY_MONITOR_MODE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": セキュリティãƒãƒªã‚·ãƒ¼ã§ [モニタリングモード] ãŒè¨±å¯ã•ã‚Œã¦ã„ãªã„ユーザーãŒã€ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã‚ˆã†ã«è¦æ±‚ã—ã¦ä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸãŸã‚ã€æŽ¥ç¶šã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚
+LH_POLICY_BRIDGE_MODE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": セキュリティãƒãƒªã‚·ãƒ¼ã§ [ブリッジをç¦æ­¢ã™ã‚‹] ãŠã‚ˆã³ [ルーティングをç¦æ­¢ã™ã‚‹] ã®ä¸¡æ–¹ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„るユーザーãŒã€ãƒ–リッジ / ルータモードを有効ã«ã™ã‚‹ã‚ˆã†ã«è¦æ±‚ã—ã¦ä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸãŸã‚ã€æŽ¥ç¶šã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚
+LH_NOT_ENOUGH_CLIENT_LICENSE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ VPN Server ã«ã€Œã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆæŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã€ã§æŽ¥ç¶šã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚µãƒ¼ãƒãƒ¼å…¨ä½“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆæŽ¥ç¶šæ•°ãŒç™»éŒ²ã•ã‚Œã¦ã„るクライアント接続ライセンス数を上回るãŸã‚ã€ã“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚åŒæ™‚接続ライセンス数ãŒä¸è¶³ã—ã¦ã„ã‚‹å ´åˆã¯ã€æ—¢å­˜ã®åˆ¥ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®æŽ¥ç¶šã‚’切断ã™ã‚‹ã‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ•°ã‚’増やã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るクライアント接続ライセンス数㯠%u ã§ã€ã‚µãƒ¼ãƒãƒ¼ã¸ã®æŽ¥ç¶šæ•°ã¯ %u ã§ã—ãŸã€‚
+LH_NOT_ENOUGH_BRIDGE_LICENSE コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ã“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ VPN Server ã«ã€Œãƒ–リッジ接続モードã€ã§æŽ¥ç¶šã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚µãƒ¼ãƒãƒ¼å…¨ä½“ã®ãƒ–リッジ接続数ãŒç™»éŒ²ã•ã‚Œã¦ã„るブリッジ接続ライセンス数を上回るãŸã‚ã€ã“ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚åŒæ™‚接続ライセンス数ãŒä¸è¶³ã—ã¦ã„ã‚‹å ´åˆã¯ã€æ—¢å­˜ã®åˆ¥ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®æŽ¥ç¶šã‚’切断ã™ã‚‹ã‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ•°ã‚’増やã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るブリッジ接続ライセンス数㯠%u ã§ã€ã‚µãƒ¼ãƒãƒ¼ã¸ã®æŽ¥ç¶šæ•°ã¯ %u ã§ã—ãŸã€‚
+LH_TOO_MANY_MULTILOGINS コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ãŒãƒ­ã‚°ã‚¤ãƒ³ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé©ç”¨ã•ã‚Œã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã¯å¤šé‡ãƒ­ã‚°ã‚¤ãƒ³æ•°ã®ä¸Šé™ã‚’ %u セッションã«åˆ¶é™ã—ã¦ã„ã¾ã™ã€‚ç¾åœ¨ã®ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ­ã‚°ã‚¤ãƒ³æ•°ã¯ %u セッションã§ã™ã®ã§ã€æ–°ãŸã« VPN 接続を許å¯ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+LH_TOO_MANY_MULTILOGINS2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S": ユーザー "%S" ãŒãƒ­ã‚°ã‚¤ãƒ³ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã“ã® VPN Server ã®è£½å“エディションã§ã¯ã€1 個ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトã«å¯¾ã—ã¦åŒæ™‚ã«ãƒ­ã‚°ã‚¤ãƒ³ã§ãã‚‹ VPN セッション数㯠%u セッションã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚ç¾åœ¨ã®ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ­ã‚°ã‚¤ãƒ³æ•°ã¯ %u セッションã§ã™ã®ã§ã€æ–°ãŸã« VPN 接続を許å¯ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãªãŠã€VPN Server ã® Professional Edition 以上ã®è£½å“エディションã®å ´åˆã¯ã€1 個ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ªãƒ–ジェクトã«å¯¾ã—ã¦åŒæ™‚ã«å¤šé‡ãƒ­ã‚°ã‚¤ãƒ³ãŒå¯èƒ½ã§ã™ã€‚
+LH_PACKET_LOG_NO_LOG ã“ã® VPN Server ã¯ãƒ‘ケットログã®ä¿å­˜ã«å¯¾å¿œã—ã¦ã„ãªã„製å“エディションã®ãŸã‚ã€IP アドレスや TCP/UDP ãªã©ã®ãƒ‡ãƒ¼ã‚¿ã¯ä¿å­˜ã•ã‚Œã¾ã›ã‚“。VPN Server ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã‚’ Professional Edition 以上ã«ã‚¢ãƒƒãƒ—グレードã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ‘ケットログãŒä¿å­˜ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚
+LH_PACKET_LOG_NO_LOG_OSS ã“ã® VPN Server ã¯ã‚ªãƒ¼ãƒ—ンソース版ã¾ãŸã¯ç„¡å„Ÿç‰ˆã§ã‚ã‚‹ãŸã‚ã€ãƒ‘ケットログã®ä¿å­˜ã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。ãã®ãŸã‚ã€IP アドレスや TCP/UDP ãªã©ã®ãƒ‡ãƒ¼ã‚¿ã¯ä¿å­˜ã•ã‚Œã¾ã›ã‚“。
+LH_NO_RADIUS_SETTING ã“ã®ä»®æƒ³ HUB ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ "%S" ãŒæŽ¥ç¶šã™ã‚‹ãŸã‚ã«ã¯ RADIUS èªè¨¼ã‚’è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ãŒã€RADIUS サーãƒãƒ¼ã®è¨­å®šãŒè¡Œã‚ã‚Œã¦ã„ãªã„ãŸã‚ユーザーèªè¨¼ã‚’実施ã§ãã¾ã›ã‚“。
+LH_KERNEL_MODE_START 仮想 NAT 機能ã§ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ãŒã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ "%S" 上ã§åˆ©ç”¨å¯èƒ½ã§ã‚ã‚‹ã“ã¨ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT を開始ã—ã¾ã™ã€‚今後㮠TCP, UDP ãŠã‚ˆã³ ICMP ã® NAT 処ç†ã¯ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã‚’経由ã—ã¦é«˜é€Ÿã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ã®ç‰©ç†ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã§ã®ãƒ‘ラメータ: IP アドレス = "%r", サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ = "%r", デフォルトゲートウェイ = "%r", ブロードキャストアドレス = "%r", 仮想 MAC アドレス: "%S", DHCP サーãƒãƒ¼ã‚¢ãƒ‰ãƒ¬ã‚¹: "%r", DNS サーãƒãƒ¼ã‚¢ãƒ‰ãƒ¬ã‚¹: "%r"
+LH_KERNEL_MODE_STOP 仮想 NAT 機能ã§ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ "%S" 上ã®ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+
+
+# (管ç†ãƒ­ã‚°)
+LA_CONNECTED_1 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ãŒã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+LA_CONNECTED_2 コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ãŒä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¾ã—ãŸã€‚仮想 HUB å㯠"%S" ã§ã™ã€‚
+LA_IP_DENIED コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" 㯠adminip.txt ファイルã§è¨±å¯ã•ã‚Œã¦ã„ãªã„ IP アドレスã‹ã‚‰ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—よã†ã¨ã—ã¾ã—ãŸã€‚切断ã—ã¾ã™ã€‚
+LA_ERROR コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ã¯ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã«ãƒ­ã‚°ã‚¤ãƒ³ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚%s (エラーコード %u)
+LA_OK コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ãŒç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§ã®ãƒ­ã‚°ã‚¤ãƒ³ã«æˆåŠŸã—ã¾ã—ãŸã€‚
+LA_RPC_START コãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" ã¯ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã®ãŸã‚ã®æ–°ã—ã„リモートプロシージャコールセッション "%S" を生æˆã—ã¾ã—ãŸã€‚
+LA_TAG_1 管ç†ãƒ¢ãƒ¼ãƒ‰ [%S]:
+LA_TAG_2 管ç†ãƒ¢ãƒ¼ãƒ‰ [%S] (仮想 HUB "%S"):
+LA_CREATE_LISTENER æ–°ã—ã„ TCP リスナー (ãƒãƒ¼ãƒˆç•ªå· %u) を作æˆã—ã¾ã—ãŸã€‚
+LA_DELETE_LISTENER TCP リスナー (ãƒãƒ¼ãƒˆç•ªå· %u) を削除ã—ã¾ã—ãŸã€‚
+LA_ENABLE_LISTENER TCP リスナー (ãƒãƒ¼ãƒˆç•ªå· %u) を有効化ã—ã¾ã—ãŸã€‚
+LA_DISABLE_LISTENER TCP リスナー (ãƒãƒ¼ãƒˆç•ªå· %u) を無効化ã—ã¾ã—ãŸã€‚
+LA_SET_SERVER_PASSWORD サーãƒãƒ¼ç®¡ç†è€…パスワードを設定ã—ã¾ã—ãŸã€‚
+LA_SET_FARM_SETTING クラスタリング設定を変更ã—ã¾ã—ãŸã€‚
+LA_SET_SERVER_CERT サーãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’設定ã—ã¾ã—ãŸã€‚
+LA_REGENERATE_SERVER_CERT サーãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’å†ç”Ÿæˆã—ã¾ã—ãŸã€‚æ–°ã—ã„ CN: "%S"
+LA_SET_SERVER_CIPHER サーãƒãƒ¼ã®æ–°ã—ã„æš—å·åŒ–アルゴリズムåを設定ã—ã¾ã—ãŸã€‚æ–°ã—ã„æš—å·åŒ–アルゴリズムå㯠"%S" ã§ã™ã€‚
+LA_CREATE_HUB æ–°ã—ã„仮想 HUB "%S" を作æˆã—ã¾ã—ãŸã€‚
+LA_SET_HUB 仮想 HUB ã®è¨­å®šã‚’変更ã—ã¾ã—ãŸã€‚
+LA_DELETE_HUB 仮想 HUB "%S" を削除ã—ã¾ã—ãŸã€‚
+LA_SET_HUB_RADIUS 仮想 HUB ã®å¤–部 RADIUS èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®šã‚’変更ã—ã¾ã—ãŸã€‚
+LA_DISCONNECT_CONN サーãƒãƒ¼ã«æŽ¥ç¶šã—ã¦ã„るクライアントã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ "%S" を強制切断ã—ã¾ã—ãŸã€‚
+LA_SET_HUB_ONLINE 仮想 HUB をオンラインã«ã—ã¾ã—ãŸã€‚
+LA_SET_HUB_OFFLINE 仮想 HUB をオフラインã«ã—ã¾ã—ãŸã€‚
+LA_SET_SNAT_OPTION SecureNAT オプションを設定ã—ã¾ã—ãŸã€‚
+LA_ENABLE_SNAT SecureNAT 機能を有効ã«ã—ã¾ã—ãŸã€‚
+LA_DISABLE_SNAT SecureNAT 機能を無効ã«ã—ã¾ã—ãŸã€‚
+LA_SET_HUB_LOG ログä¿å­˜è¨­å®šã‚’変更ã—ã¾ã—ãŸã€‚
+LA_ADD_CA ä¿¡é ¼ã™ã‚‹ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã®ç™»éŒ²ã‚’追加ã—ã¾ã—ãŸã€‚
+LA_DELETE_CA ä¿¡é ¼ã™ã‚‹ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã®ç™»éŒ²ã‚’削除ã—ã¾ã—ãŸã€‚
+LA_CREATE_LINK カスケード接続 "%s" を追加ã—ã¾ã—ãŸã€‚
+LA_SET_LINK カスケード接続 "%s" ã®è¨­å®šã‚’変更ã—ã¾ã—ãŸã€‚
+LA_SET_LINK_ONLINE カスケード接続 "%s" をオンラインã«ã—ã¾ã—ãŸã€‚
+LA_SET_LINK_OFFLINE カスケード接続 "%s" をオフラインã«ã—ã¾ã—ãŸã€‚
+LA_DELETE_LINK カスケード接続 "%s" を削除ã—ã¾ã—ãŸã€‚
+LA_RENAME_LINK カスケード接続 "%s" ã®åå‰ã‚’ "%s" ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚
+LA_ADD_ACCESS アクセスリストを追加ã—ã¾ã—ãŸã€‚
+LA_DELETE_ACCESS アクセスリストを削除ã—ã¾ã—ãŸã€‚
+LA_SET_ACCESS_LIST アクセスリストを更新ã—ã¾ã—ãŸã€‚%u 個ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã‚’設定ã—ã¾ã—ãŸã€‚
+LA_SET_AC_LIST 接続元 IP 制é™ãƒªã‚¹ãƒˆã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚%u 個ã®ãƒ«ãƒ¼ãƒ«é …目を設定ã—ã¾ã—ãŸã€‚
+LA_CREATE_USER ユーザー "%S" を作æˆã—ã¾ã—ãŸã€‚
+LA_SET_USER ユーザー "%S" ã®è¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_DELETE_USER ユーザー "%S" を削除ã—ã¾ã—ãŸã€‚
+LA_CREATE_GROUP グループ "%S" を作æˆã—ã¾ã—ãŸã€‚
+LA_SET_GROUP グループ "%S" ã®è¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_DELETE_GROUP グループ "%S" を削除ã—ã¾ã—ãŸã€‚
+LA_DELETE_SESSION セッション "%S" を強制切断ã—ã¾ã—ãŸã€‚
+LA_SET_KEEP サーãƒãƒ¼ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šç¶­æŒè¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_SET_SYSLOG サーãƒãƒ¼ã® syslog é€ä¿¡æ©Ÿèƒ½ã®è¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_DELETE_BRIDGE ローカルブリッジ接続定義 "%S" -> "%S" を削除ã—ã¾ã—ãŸã€‚
+LA_ADD_BRIDGE ローカルブリッジ接続定義 "%S" -> "%S" を追加ã—ã¾ã—ãŸã€‚
+LA_REBOOT_SERVER VPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã‚ˆã†ã«è¦æ±‚ã—ã¾ã—ãŸã€‚
+LA_GET_CONFIG config ファイルを読ã¿å‡ºã—ã¾ã—ãŸã€‚
+LA_SET_CONFIG config ファイルを書ãè¾¼ã¿ã¾ã—ãŸã€‚VPN Server ã‚’å†èµ·å‹•ã—ã¾ã™ã€‚
+LA_SET_HUB_ADMIN_OPTION 仮想 HUB "%S" ã®ç®¡ç†ã‚ªãƒ—ションを設定ã—ã¾ã—ãŸã€‚
+LA_SET_HUB_EXT_OPTION 仮想 HUB "%S" ã®æ‹¡å¼µã‚ªãƒ—ションを設定ã—ã¾ã—ãŸã€‚
+LA_ADD_L3_SW 仮想レイヤ 3 スイッム"%S" をサーãƒãƒ¼ã«ä½œæˆã—ã¾ã—ãŸã€‚
+LA_DEL_L3_SW 仮想レイヤ 3 スイッム"%S" をサーãƒãƒ¼ã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚
+LA_START_L3_SW 仮想レイヤ 3 スイッム"%S" を開始ã—ã¾ã—ãŸã€‚
+LA_STOP_L3_SW 仮想レイヤ 3 スイッム"%S" ã‚’åœæ­¢ã—ã¾ã—ãŸã€‚
+LA_ADD_L3_IF 仮想 HUB "%S" ã«å¯¾ã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã‚’仮想レイヤ 3 スイッム"%S" ã«è¿½åŠ ã—ã¾ã—ãŸã€‚
+LA_DEL_L3_IF 仮想 HUB "%S" ã«å¯¾ã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã‚’仮想レイヤ 3 スイッム"%S" ã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚
+LA_ADD_L3_TABLE ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ "%S" ã«å¯¾ã™ã‚‹ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを仮想レイヤ 3 スイッム"%S" ã«è¿½åŠ ã—ã¾ã—ãŸã€‚
+LA_DEL_L3_TABLE ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ "%S" ã«å¯¾ã™ã‚‹ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを仮想レイヤ 3 スイッム"%S" ã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚
+LA_ADD_CRL 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã®ç™»éŒ²ã‚’追加ã—ã¾ã—ãŸã€‚
+LA_DEL_CRL 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã®ç™»éŒ²ã‚’削除ã—ã¾ã—ãŸã€‚
+LA_SET_CRL 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã®ç™»éŒ²ã®ç™»éŒ²æ¸ˆã¿é …目を編集ã—ã¾ã—ãŸã€‚
+LA_READ_LOG_FILE サーãƒãƒ¼ "%S" 上ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ« "%S" をダウンロードã—ã¾ã—ãŸã€‚
+LA_ADD_LICENSE_KEY æ–°ã—ã„ライセンスキー "%S" を登録ã—ã¾ã—ãŸã€‚
+LA_DEL_LICENSE_KEY 既存ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ (%u 番) を削除ã—ã¾ã—ãŸã€‚
+LA_SET_IPSEC_CONFIG IPsec サーãƒãƒ¼ã®è¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_ADD_ETHERIP_ID EtherIP / L2TPv3 サーãƒãƒ¼ã®è¨­å®š (ID="%S") を追加ã—ã¾ã—ãŸã€‚
+LA_DEL_ETHERIP_ID EtherIP / L2TPv3 サーãƒãƒ¼ã®è¨­å®š (ID="%S") を削除ã—ã¾ã—ãŸã€‚
+LA_SET_OVPN_SSTP_CONFIG OpenVPN ãŠã‚ˆã³ MS-SSTP VPN サーãƒãƒ¼ã®è¨­å®šã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+LA_DDNS_HOSTNAME_CHANGED ダイナミック DNS 機能ã®ãƒ›ã‚¹ãƒˆåã‚’ "%S" ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚
+LA_SET_SPECIAL_LISTENER 特別ãªãƒªã‚¹ãƒŠã®æœ‰åŠ¹ / 無効状態を変更ã—ã¾ã—ãŸã€‚
+
+# (Client ログ)
+LC_START_1 SoftEther VPN Client エンジンを起動ã—ã¾ã—ãŸã€‚
+LC_START_2 %S %S
+LC_START_3 %S
+LC_END SoftEther VPN Client エンジンをシャットダウンã—ã¾ã—ãŸã€‚
+LC_LOAD_CONFIG_1 設定ファイルを読ã¿è¾¼ã‚“ã§ã„ã¾ã™ã€‚
+LC_LOAD_CONFIG_2 設定ファイルã®èª­ã¿è¾¼ã¿ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+LC_LOAD_CONFIG_3 設定ファイルãŒå­˜åœ¨ã—ã¾ã›ã‚“。åˆæœŸè¨­å®šã‚’作æˆã—ã¾ã™ã€‚
+LC_NEW_ACCOUNT æ–°ã—ã„接続設定 "%s" を作æˆã—ã¾ã—ãŸã€‚
+LC_DELETE_ACCOUNT 接続設定 "%s" を削除ã—ã¾ã—ãŸã€‚
+LC_RENAME_ACCOUNT 接続設定 "%s" ã®åå‰ã‚’ "%s" ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚
+LC_CONNECT 接続設定 "%s" ã¸ã®æŽ¥ç¶šå‡¦ç†ã‚’開始ã—ã¾ã—ãŸã€‚
+LC_CONNECT_1 接続設定 "%s": %u 回目ã®æŽ¥ç¶šå‹•ä½œã‚’開始ã—ã¾ã™ã€‚
+LC_CONNECT_2 接続設定 "%s": 接続ãŒå®Œäº†ã—ã¾ã—ãŸã€‚セッションå: "%S"
+LC_CONNECT_ERROR 接続設定 "%s": 接続ãŒåˆ‡æ–­ã•ã‚ŒãŸã‹ã€æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚ç†ç”±: %s (コード %u)
+LC_DISCONNECT 接続設定 "%s" を切断ã—ã¾ã™ã€‚
+LC_CREATE_VLAN 仮想 LAN カード "%S" を作æˆã—ã¾ã—ãŸã€‚
+LC_UPDATE_VLAN 仮想 LAN カード "%S" ã®ãƒ‰ãƒ©ã‚¤ãƒã‚’å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã—ãŸã€‚
+LC_DELETE_VLAN 仮想 LAN カード "%S" を削除ã—ã¾ã—ãŸã€‚
+LC_SET_PASSWORD クライアントサービスã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã®ãƒ‘スワード設定を変更ã—ã¾ã—ãŸã€‚
+LC_TAP_NOT_FOUND MacOS X 用㮠tun/tap ドライãƒãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。tun/tap ドライãƒã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã£ã¦ãã ã•ã„。
+
+# (イレーザー ログ)
+LE_START ディレクトリ "%S" ã®ç›£è¦–を開始ã—ã¾ã™ã€‚ディスクã®ç©ºã容é‡ãŒ %S 未満ã«ãªã£ãŸå ´åˆã€ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ã‚µãƒ–ディレクトリ内ã«ä¿å­˜ã•ã‚Œã¦ã„るログファイルãŠã‚ˆã³è¨­å®šã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルをã€å¤ã„順番ã«è‡ªå‹•çš„ã«å‰Šé™¤ã—ã¾ã™ã€‚削除を開始ã™ã‚‹ãƒ‡ã‚£ã‚¹ã‚¯ã®æœ€å°ç©ºã容é‡ã¯ã€è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã® "AutoDeleteCheckDiskFreeSpaceMin" é …ç›®ã§å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+LE_DELETE ディスクã®ç©ºã容é‡ãŒ %S 未満ã«ãªã£ãŸãŸã‚ã€å¤ã„ファイル "%S" を自動的ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚ãªãŠã€å‰Šé™¤ã‚’開始ã™ã‚‹ãƒ‡ã‚£ã‚¹ã‚¯ã®æœ€å°ç©ºã容é‡ã¯ã€è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã® "AutoDeleteCheckDiskFreeSpaceMin" é …ç›®ã§å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+LE_NOT_ENOUGH_FREE <<警告>> ディスクã®ç©ºã容é‡ãŒ %S 以下ã«ãªã£ã¦ã„ã¾ã™ãŒã€ã“れ以上å¤ã„ログファイルãŠã‚ˆã³è¨­å®šã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルを自動的ã«å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ç›´ã¡ã«æ‰‹å‹•ã§ã“ã®ã‚³ãƒ³ãƒ”ュータã®ä¸è¦ãªãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除ã—ã€ãƒ‡ã‚£ã‚¹ã‚¯å®¹é‡ã‚’確ä¿ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚空ãディスク容é‡ãŒæ¥µç«¯ã«å°‘ãªããªã‚‹ã¨ã€ã‚³ãƒ³ãƒ”ュータã®å‹•ä½œãŒä¸å®‰å®šã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+
+# (レイヤ 3 スイッãƒãƒ­ã‚°)
+L3_SWITCH_START 仮想レイヤ 3 スイッム"%S" ãŒèµ·å‹•ã—ã¾ã—ãŸã€‚ã“ã®ã‚¹ã‚¤ãƒƒãƒã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®ä»®æƒ³ HUB ãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ãªã‚‹ã¾ã§å¾…æ©Ÿã—ã¦ã€å‹•ä½œã‚’開始ã—ã¾ã™ã€‚
+L3_SWITCH_ONLINE 仮想レイヤ 3 スイッム"%S" ã®ã™ã¹ã¦ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®ä»®æƒ³ HUB ãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ãªã£ãŸã®ã§ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®å‹•ä½œã‚’開始ã—ã¾ã™ã€‚
+L3_SWITCH_OFFLINE 仮想レイヤ 3 スイッム"%S" ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 1 ã¤ä»¥ä¸Šã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®ä»®æƒ³ HUB ãŒåœæ­¢ã—ãŸã®ã§ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®å‹•ä½œã‚’åœæ­¢ã—ã¾ã™ã€‚
+L3_SWITCH_STOP 仮想レイヤ 3 スイッム"%S" ãŒçµ‚了ã—ã¾ã—ãŸã€‚
+
+
+# Microsoft.c 関係
+MS_ETHERNET Ethernet インターフェイス
+MS_TOKENRING トークンリングインターフェイス
+MS_FDDI FDDI インターフェイス
+MS_PPP PPP (ダイヤルアップã¾ãŸã¯ VPN)
+MS_LOOPBACK ループãƒãƒƒã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹
+MS_SLIP SLIP インターフェイス
+MS_WLAN 無線 LAN インターフェイス
+MS_OTHER ä¸æ˜Žãªç¨®é¡žã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹
+MS_NON_OPERATIONAL 無効
+MS_UNREACHABLE 未接続
+MS_DISCONNECTED 未接続
+MS_CONNECTING 接続中
+MS_CONNECTED 接続済ã¿
+MS_OPERATIONAL 接続済ã¿
+
+
+# Network Utility 関係
+UT_SM_COLUMN_1 é …ç›®å
+UT_SM_COLUMN_2 値
+UT_SM_ST_TITLE ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ€ãƒ—ã‚¿å
+UT_SM_ST_GUID GUID
+UT_SM_ST_TYPE 種類
+UT_SM_ST_TYPE2 ç‰©ç† Ethernet LAN 接続
+UT_SM_ST_STATUS 状æ³
+UT_SM_ST_MTU MTU
+UT_SM_ST_SPEED リンク速度
+UT_SM_ST_ADDRESS 物ç†ã‚¢ãƒ‰ãƒ¬ã‚¹
+UT_SM_ST_RECV_BYTES å—ä¿¡ãƒã‚¤ãƒˆæ•°
+UT_SM_ST_RECV_BCASTS å—信ブロードキャスト数
+UT_SM_ST_RECV_UNICASTS å—信ユニキャスト数
+UT_SM_ST_SEND_BYTES é€ä¿¡ãƒã‚¤ãƒˆæ•°
+UT_SM_ST_SEND_BCASTS é€ä¿¡ãƒ–ロードキャスト数
+UT_SM_ST_SEND_UNICASTS é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆæ•°
+UT_SM_ST_IP IP アドレス %u
+UT_SM_ST_SUBNET サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ %u
+UT_SM_ST_GATEWAY ゲートウェイ %u
+UT_SM_ST_DHCP DHCP サーãƒãƒ¼
+UT_SM_ST_DHCP_1 リース開始日時
+UT_SM_ST_DHCP_2 リース期é™æ—¥æ™‚
+UT_SM_ST_WINS_1 WINS サーãƒãƒ¼ 1
+UT_SM_ST_WINS_2 WINS サーãƒãƒ¼ 2
+
+
+# EtherLogger Manager 関係
+EM_TITLE SoftEther EtherLogger Manager
+EM_REMOTE_TITLE SoftEther EtherLogger サービスã«æŽ¥ç¶šã—ã€ç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n管ç†ã™ã‚‹ EtherLogger サービスãŒå‹•ä½œã—ã¦ã„るコンピュータã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスを入力ã—ã¦ãã ã•ã„。":" (コロン) ã«ç¶šã‘ã¦ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+EM_MAIN_COLUMN_1 LAN カードå
+EM_MAIN_COLUMN_2 状態
+EM_MAIN_OK 動作中
+EM_MAIN_ERROR エラー発生
+EM_ADD_NEW æ–°ã—ã„キャプãƒãƒ£ãƒ‡ãƒã‚¤ã‚¹ã®è¿½åŠ 
+EM_ADD_EDIT キャプãƒãƒ£è¨­å®šã®ç·¨é›†
+EM_DELETE_CONFIRM キャプãƒãƒ£è¨­å®š "%S" を削除ã—ã¾ã™ã‹?
+EM_NO_LICENSE_COLUMN ã”注æ„:
+EM_NO_LICENSE 製å“ライセンス㌠1 ã¤ã‚‚登録ã•ã‚Œã¦ã„ãªã„ãŸã‚ã€ã“ã® SoftEther EtherLogger ã¯å‹•ä½œã—ã¾ã›ã‚“。
+
+EM_UNSUPPORTED ã“ã® SoftEther EtherLogger ãŒå‹•ä½œã—ã¦ã„るオペレーティングシステム上ã§ã¯ã€SoftEther EtherLogger を使用ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。SoftEther EtherLogger ãŒä½¿ç”¨ã§ãるオペレーティングシステムã®ä¸€è¦§ã«ã¤ã„ã¦ã¯ã€SoftEther EtherLogger ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+EM_WPCAP_REMOTE ã“ã® SoftEther EtherLogger を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上ã«ã¯ WinPcap ソフトウェアãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nWinPcap ソフトウェアã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã™ã‚‹ãŸã‚ã«ã¯ã€VPN Server ãŒå‹•ä½œã—ã¦ã„るサーãƒãƒ¼ コンピュータ上㧠SoftEther EtherLogger Managerã‚’èµ·å‹•ã—ã€localhost (自分自身) ã«å¯¾ã—ã¦æŽ¥ç¶šã—ãŸçŠ¶æ…‹ã§ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能設定画é¢ã‚’表示ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n続行ã™ã‚‹ã«ã¯ã€ä¸€æ—¦ã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’終了ã—ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上㧠SoftEther EtherLogger Manager ã‚’èµ·å‹•ã—ã¦ã‹ã‚‰ã€localhost ã«å¯¾ã—ã¦æŽ¥ç¶šã—ã¦ã€è¨­å®šã‚’続行ã—ã¦ãã ã•ã„。
+EM_WPCAP_ROOT ã“ã® SoftEther EtherLogger を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nインストールを継続ã™ã‚‹ã«ã¯ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ上㧠Administrators (管ç†è€…) 権é™ã‚’æŒã£ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ãƒ­ã‚°ã‚ªãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\nAdministrators 権é™ã§ãƒ­ã‚°ã‚ªãƒ³ã—ã€ã‚‚ã†ä¸€åº¦ SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。
+EM_WPCAP_INSTALL ã“ã® SoftEther EtherLogger を使用ã™ã‚‹ãŸã‚ã«ã¯ã€WinPcap ソフトウェアをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ コンピュータ上ã«ã¯ WinPcap ソフトウェアãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\n\r\nWinPcap ã¯ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã§ã‚ã‚Šã€VPN Server ã®ä¸€éƒ¨ã¨ã—ã¦åŒæ¢±ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nWinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã—ã¾ã™ã‹?
+EM_WPCAP_REBOOT1 WinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ãŸå¾Œã« SoftEther EtherLogger を使用ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nコンピュータを手動ã§å†èµ·å‹•ã—ã€SoftEther EtherLogger ãŒèµ·å‹•ã—ãŸå¾Œã§ã€ã‚‚ã†ä¸€åº¦è¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。
+EM_WPCAP_REBOOT2 WinPcap ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ãŸå¾Œã«ã€SoftEther EtherLogger サービスをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nSoftEther EtherLogger サービスã®å†èµ·å‹•ã¯çŸ­æ™‚é–“ã§å®Œäº†ã—ã¾ã™ãŒã€ç¾åœ¨ã“ã® SoftEther EtherLogger ã«æŽ¥ç¶šã—ã¦ã„る管ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚\r\nã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚‚切断ã•ã‚Œã‚‹ãŸã‚ã€ç¶šè¡Œã™ã‚‹ã«ã¯å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\r\n\r\nSoftEther EtherLogger サービスをå†èµ·å‹•ã—ã¾ã™ã‹?
+EM_RESOURCE WinPcap ã®ãƒ‰ãƒ©ã‚¤ãƒã‚’読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚
+
+
+
+###########################################################################
+# #
+# ソフトウェア内ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ãƒœãƒƒã‚¯ã‚¹ã®æ–‡å­—列データ #
+# #
+###########################################################################
+
+
+PREFIX D_SECURE
+CAPTION %s - %S ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹
+S_TITLE %S ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹
+S_DEVICE_INFO デãƒã‚¤ã‚¹å: %S\r\n製造元: %S
+IDS_STATIC1 デãƒã‚¤ã‚¹æƒ…å ±
+S_WARNING 一定回数 PIN コードを間é•ãˆã‚‹ã¨ãƒ‡ãƒã‚¤ã‚¹ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã”注æ„ãã ã•ã„。
+IDOK &OK
+IDCANCEL キャンセル
+S_PIN_CODE &PIN コード:
+
+
+PREFIX D_PKCSUTIL
+CAPTION PKCS#12 書ãè¾¼ã¿ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£
+S_TITLE ePass 1000 USB トークン PKCS#12 書ãè¾¼ã¿ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£
+STATIC1 ã“ã®ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’使用ã™ã‚‹ã¨ã€ä»»æ„ã® PKCS#12 ファイル (証明書ファイル) ã‚’ ePass 1000 USB ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒˆãƒ¼ã‚¯ãƒ³ã«æ›¸ã込むã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\n証明書ファイルãŒæ›¸ãè¾¼ã¾ã‚ŒãŸ USB トークンã¯ã€SoftEther VPN ã®èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+STATIC2 PKCS#12 ファイルã®æ›¸ãè¾¼ã¿
+STATIC3 既存㮠PKCS#12 ファイルを USB トークンã«æ›¸ã込む場åˆã¯ã€[書ãè¾¼ã¿] をクリックã—ã¦ãã ã•ã„。\r\n※ ã™ã§ã« USB トークン内㫠SoftEther VPN 用㮠PKCS#12 証明書ãŒæ ¼ç´ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚
+B_WRITE 書ãè¾¼ã¿(&W)
+STATIC4 USB トークン内㮠PKCS#12 証明書ã®æ¶ˆåŽ»
+STATIC5 ã™ã§ã« SoftEther VPN 用㮠PKCS#12 証明書ãŒæ ¼ç´ã•ã‚Œã¦ã„ã‚‹ USB トークンã‹ã‚‰ã€è¨¼æ˜Žæ›¸ãƒ‡ãƒ¼ã‚¿ã‚’消去ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_ERASE 消去(&E)
+IDCANCEL ユーティリティã®çµ‚了(&X)
+S_COPYRIGHT Copyright (c) SoftEther VPN Project.\r\nAll Rights Reserved.
+
+
+PREFIX D_PASSPHRASE
+CAPTION 秘密éµã®ãƒ‘スフレーズ
+STATIC1 秘密éµã¯ãƒ‘スフレーズã«ã‚ˆã£ã¦ä¿è­·ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n秘密éµã‚’読ã¿å–ã‚‹ãŸã‚ã®ãƒ‘スフレーズを入力ã—ã¦ãã ã•ã„。
+STATIC2 パスフレーズ(&P):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_NM_CONNECT
+CAPTION SoftEther VPN User-mode Router ã¸æŽ¥ç¶š
+S_TITLE %S ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+
+
+PREFIX D_PASSWORD
+CAPTION %S ã¸ã®ãƒ­ã‚°ã‚¤ãƒ³
+S_TITLE サーãƒãƒ¼ %S ã«ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。ã¾ãŸã€æ­£ã—ã„アカウントã®ç¨®é¡žãŒé¸æŠžã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+STATIC1 ユーザー情報ã®å…¥åŠ›(&R):
+STATIC2 アカウントã®ç¨®é¡ž(&T):
+STATIC3 ユーザーå(&N):
+STATIC4 パスワード(&P):
+R_NO_SAVE_PASSWORD パスワードをä¿å­˜ã—ãªã„(&D)
+S_COUNTDOWN 入力ãŒè¡Œã‚ã‚Œãªã„å ´åˆã€ã‚㨠%u 秒後ã«è‡ªå‹•çš„ã«å†æŽ¥ç¶šã—ã¾ã™...
+IDOK &OK
+IDCANCEL 接続ã®ä¸­æ–­
+
+
+PREFIX D_STATUS
+CAPTION %s ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™...
+S_STATUS åˆæœŸåŒ–ã—ã¦ã„ã¾ã™...
+IDCANCEL キャンセル
+
+
+PREFIX D_CERT
+CAPTION 証明書
+S_TITLE ã“ã®è¨¼æ˜Žæ›¸ã«é–¢ã™ã‚‹æƒ…å ±ã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+STATIC1 証明書基本情報:
+STATIC2 発行先:
+STATIC3 発行者:
+STATIC4 有効期é™:
+STATIC5 証明書詳細情報:
+STATIC6 ã“ã®è¨¼æ˜Žæ›¸ã‚’ç½²åã—ãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸:
+S_PARENT ã“ã®è¨¼æ˜Žæ›¸ã‚’ç½²åã—ãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãる証明書ã®ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚
+S_PARENT_BUTTON_STR 証明書ã®è¡¨ç¤º(&V)
+IDCANCEL &OK
+B_SAVE ファイルã«ä¿å­˜(&S)
+
+
+PREFIX D_CHECKCERT
+CAPTION セキュリティã®è­¦å‘Š - %s
+S_TITLE ç¾åœ¨æŽ¥ç¶šã—よã†ã¨ã—ã¦ã„る接続先 VPN Server "%S" ã¨ã®é–“ã®é€šä¿¡ã¯æš—å·åŒ–ã•ã‚Œã¦ã„ã¾ã™ãŒã€ã‚µãƒ¼ãƒãƒ¼ãŒæ示ã—ãŸã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãã‚‹ã‹ã©ã†ã‹ã¯ã‚ã‹ã‚Šã¾ã›ã‚“。
+STATIC1 サーãƒãƒ¼è¨¼æ˜Žæ›¸ã«ã¤ã„ã¦
+STATIC2 VPN 通信ã§ã¯ã€ã‚µãƒ¼ãƒãƒ¼ã¨ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®é–“ã§æš—å·åŒ–通信 (SSL セッション) を確立ã—ã¾ã™ã€‚ãã®éš›ã«ã‚µãƒ¼ãƒãƒ¼ã®è¨¼æ˜Žæ›¸ã‚’確èªã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€æŽ¥ç¶šã—よã†ã¨ã—ã¦ã„るサーãƒãƒ¼ãŒæœ¬ç‰©ã‹ã©ã†ã‹ã‚’検証ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_MSG1 接続先㮠VPN Server "%S" ãŒæ示ã—ãŸã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚
+STATIC3 発行先:
+STATIC4 発行者:
+STATIC5 有効期é™:
+B_SHOW 証明書を表示ã™ã‚‹(&S)
+STATIC6 ダイジェスト (MD5):
+STATIC7 ダイジェスト (SHA-1):
+IDOK 接続を続ã‘ã‚‹(&R)
+IDCANCEL 接続をキャンセル(&C)
+STATIC8 ã“ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã¯ã€ä¿¡é ¼ã•ã‚ŒãŸè¨¼æ˜Žæ©Ÿé–¢ã«ã‚ˆã‚Šç™ºè¡Œã•ã‚Œã¦ã„ãªã„ã‹ã€æœ‰åŠ¹æœŸé™åˆ‡ã‚Œã‹ã€ãã®ä»–ã®å•é¡ŒãŒã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+STATIC9 上記ã®è¨¼æ˜Žæ›¸ã®å†…容を確èªã—ã¦ã‹ã‚‰ã€ã“ã® VPN Server ã¸ã®æŽ¥ç¶šã‚’è¡Œã†ã‹ã©ã†ã‹ã‚’決定ã—ã¦ãã ã•ã„。[接続をキャンセル] をクリックã™ã‚‹ã¨ã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¸ã®æŽ¥ç¶šã‚’中断ã—ã¾ã™ã€‚
+
+
+PREFIX D_CONNECTERROR
+CAPTION 接続エラー - %s
+S_TITLE VPN サーãƒãƒ¼ "%S" ã¨ã®é€šä¿¡ã§ä»¥ä¸‹ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+S_COUNTDOWN ã‚㨠%u 秒後ã«è‡ªå‹•çš„ã«å†æŽ¥ç¶šã—ã¾ã™...
+IDOK å†è©¦è¡Œ(&R)
+IDCANCEL 接続ã®ä¸­æ–­
+R_HIDE 今回ã®æŽ¥ç¶šæ™‚ã«ã¯ã“ã®ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’éžè¡¨ç¤ºã«ã™ã‚‹(&H)
+
+
+PREFIX D_CM_LOGIN
+CAPTION パスワードã®å…¥åŠ› - VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+S_TITLE %s 上ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Client ã‚’æ“作ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆç®¡ç†ãƒ‘スワードãŒå¿…è¦ã§ã™ã€‚クライアント管ç†ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。
+STATIC1 パスワード(&P):
+STATIC2 クライアント管ç†ãƒ‘スワードã®å…¥åŠ›:
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CONNECTION_STATUS
+S_TITLE 接続設定 %s ã® VPN セッションã®çŠ¶æ³ (リアルタイム)
+B_POLICY セキュリティãƒãƒªã‚·ãƒ¼(&P)...
+B_SERVER_CERT サーãƒãƒ¼è¨¼æ˜Žæ›¸(&S)
+B_CLIENT_CERT クライアント証明書(&E)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_CM_POLICY
+CAPTION セキュリティãƒãƒªã‚·ãƒ¼ä¸€è¦§
+S_TITLE 接続設定 %s ã®ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«è¨­å®šã•ã‚Œã¦ã„るセキュリティãƒãƒªã‚·ãƒ¼
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_CM_ACCOUNT
+STATIC1 VPN Server ã¸ã®æŽ¥ç¶šè¨­å®šã‚’è¡Œã„ã¾ã™ã€‚
+S_ACCOUNT_NAME 接続設定å(&T):
+STATIC2 接続先 VPN Server ã®æŒ‡å®š(&B):
+STATIC3 接続ã—ãŸã„ VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスã€ãƒãƒ¼ãƒˆç•ªå·ã€ãŠã‚ˆã³ä»®æƒ³ HUB åを指定ã—ã¦ãã ã•ã„。
+STATIC4 ホストå(&H):
+STATIC5 ãƒãƒ¼ãƒˆç•ªå·(&P):
+STATIC6 (TCP ãƒãƒ¼ãƒˆ)
+STATIC7 仮想 HUB å(&V):
+STATIC8 経由ã™ã‚‹ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®š(&X):
+STATIC9 プロキシサーãƒãƒ¼ã‚’経由ã—㦠VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC10 プロキシã®ç¨®é¡ž(&M):
+R_DIRECT_TCP 直接 TCP/IP 接続 (プロキシを使ã‚ãªã„) (&D)
+R_HTTPS HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&Q)
+R_SOCKS SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&S)
+B_PROXY_CONFIG プロキシサーãƒãƒ¼ã®æŽ¥ç¶šè¨­å®š(&2)
+STATIC11 サーãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ション(&F):
+R_CHECK_CERT サーãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’å¿…ãšæ¤œè¨¼ã™ã‚‹(&3)
+B_TRUST ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®ç®¡ç†(&4)
+B_SERVER_CERT 固有証明書ã®ç™»éŒ²(&R)
+B_VIEW_SERVER_CERT 固有証明書ã®è¡¨ç¤º(&5)
+S_VLAN_GROUP 使用ã™ã‚‹ä»®æƒ³ LAN カード(&L):
+S_POLICY_1 カスケード接続を行ã†éš›ã«ã€ã“ã®ä»®æƒ³ HUB å´ã§ç”Ÿæˆã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é©ç”¨ã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_POLICY セキュリティãƒãƒªã‚·ãƒ¼(&L)
+STATIC12 ユーザーèªè¨¼(&A):
+STATIC13 èªè¨¼ã®ç¨®é¡ž(&6):
+S_USERNAME ユーザーå(&U):
+S_PASSWORD パスワード(&Y):
+S_CERT_INFO ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+STATIC14 通信ã®è©³ç´°è¨­å®š(&G):
+R_RETRY VPN Server ã¨ã®é€šä¿¡ãŒåˆ‡æ–­ã•ã‚ŒãŸå ´åˆã¯å†æŽ¥ç¶šã™ã‚‹(&Z)
+S_RETRY_NUM_1 å†æŽ¥ç¶šå›žæ•°(&C):
+S_RETRY_NUM_2 回
+S_RETRY_SPAN_1 å†æŽ¥ç¶šé–“éš”(&K):
+S_RETRY_SPAN_2 秒
+R_INFINITE ç„¡é™ã«å†æŽ¥ç¶šã‚’試行ã™ã‚‹ (常時接続) (&I)
+R_NOTLS1 TLS &1.0 を使用ã—ãªã„
+B_DETAIL 高度ãªé€šä¿¡è¨­å®š(&N)...
+IDOK &OK
+IDCANCEL キャンセル
+B_CHANGE_PASSWORD パスワードã®å¤‰æ›´(&J)
+S_CHANGE_PASSWORD VPN Server å´ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ‘スワードを変更ã§ãã¾ã™ã€‚
+R_HIDE 接続中ã®ç”»é¢ã¨ã‚¨ãƒ©ãƒ¼ç”»é¢ã‚’éžè¡¨ç¤º(&W)
+R_HIDE2 IP アドレスメッセージをéžè¡¨ç¤º(&9)
+STATIC15 VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã«å¿…è¦ãªãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼æƒ…報を設定ã—ã¦ãã ã•ã„。
+B_REGIST_CLIENT_CERT クライアント証明書ã®æŒ‡å®š(&8)
+B_IE IE ã®è¨­å®šã‚’使用(&E)
+
+
+PREFIX D_CM_PROXY
+CAPTION プロキシサーãƒãƒ¼ã®æŽ¥ç¶šè¨­å®š
+STATIC1 経由ã™ã‚‹ãƒ—ロキシサーãƒãƒ¼ (HTTP プロキシã¾ãŸã¯ SOCKS プロキシ) ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスã€ãƒãƒ¼ãƒˆç•ªå·ã€ãŠã‚ˆã³å¿…è¦ãªå ´åˆã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。
+STATIC2 ホストå(&H):
+STATIC3 ãƒãƒ¼ãƒˆç•ªå·(&A):
+STATIC4 ユーザーå(&U):
+STATIC5 パスワード(&P):
+IDOK &OK
+IDCANCEL キャンセル
+STATIC6 (オプション)
+STATIC7 (オプション)
+
+
+PREFIX D_CM_DETAIL
+CAPTION 高度ãªé€šä¿¡è¨­å®š
+STATIC1 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã€é€šä¿¡ãƒ—ロトコルã€ãŠã‚ˆã³ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã«é–¢ã™ã‚‹è©³ã—ã„知識をãŠæŒã¡ã®æ–¹ã¨ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…å‘ã‘ã®ã‚ªãƒ—ションã§ã™ã€‚VPN プロトコルã®é€šä¿¡è¨­å®šã‚’カスタマイズã§ãã¾ã™ã€‚
+STATIC2 VPN 通信ã®æœ€é©åŒ–(&T):
+STATIC3 VPN Server ã¨ã®é–“ã® VPN 通信セッションã«ãŠã‘るデータä¼é€ã«è¤‡æ•°æœ¬ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€é€šä¿¡é€Ÿåº¦ã‚’å‘上ã§ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+STATIC4 VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°(&N):
+STATIC5 本
+STATIC6 ※ サーãƒãƒ¼ã¸ã®æŽ¥ç¶šå›žç·šãŒé«˜é€Ÿãªå ´åˆã¯ 8 本程度をã€ãƒ€ã‚¤ãƒ¤ãƒ«ã‚¢ãƒƒãƒ—ç­‰ã®ä½Žé€Ÿãªå ´åˆã¯ 1 本をãŠå‹§ã‚ã—ã¾ã™ã€‚
+STATIC7 詳細設定:
+STATIC8 å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“éš”(&S):
+STATIC9 秒
+R_USE_DISCONNECT å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ã‚’設定ã™ã‚‹(&A)
+STATIC10 寿命(&P):
+STATIC11 秒
+STATIC12 2 本以上㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ VPN 通信を行ã†éš›ã€ã€ŒåŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã€ã‚’使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nåŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€è‡ªå‹•çš„ã«å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ãƒ‡ãƒ¼ã‚¿ä¼é€æ–¹å‘ã‚’åŠæ•°ãšã¤å›ºå®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nãŸã¨ãˆã°ã€8 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’使用ã—㦠VPN セッションを確立ã—ãŸå ´åˆã€åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€4 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ã‚¢ãƒƒãƒ—ロード方å‘専用ã€æ®‹ã‚Šã® 4 本ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰æ–¹å‘専用ã«å›ºå®šã•ã‚Œé€šä¿¡ãŒè¡Œã‚ã‚Œã¾ã™ã€‚
+R_USE_HALF_CONNECTION åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’使用ã™ã‚‹(&H)
+STATIC13 æš—å·åŒ–ã¨åœ§ç¸®(&C):
+STATIC14 通常ã¯ã€VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã—ã¦ã€æƒ…å ±ã®ç›—è´ã‚„改ã–んを防止ã—ã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã¨ã€é€šä¿¡ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ãŒã€é€šä¿¡ãƒ‡ãƒ¼ã‚¿ã¯å¹³æ–‡ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚Œã¾ã™ã€‚
+R_USE_ENCRYPT VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã™ã‚‹(&E)
+STATIC15 データ圧縮技術を使用ã—ã¦ã€VPN 通信を圧縮ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ダイヤルアップ接続やモãƒã‚¤ãƒ«æŽ¥ç¶šãªã©ã€ä½Žé€Ÿå›žç·šã§ã®ã¿ä½¿ç”¨ã—ã¦ãã ã•ã„。
+R_DISABLE_UDP UD&P 高速化機能を無効ã«ã™ã‚‹
+R_USE_COMPRESS データ圧縮を使用ã™ã‚‹(&U)
+STATIC16 接続モードã®é¸æŠž(&M):
+S_MODE VPN Server ã«ä¸‹è¨˜ã®æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’指定ã—ã¦æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚(ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…用)
+R_BRIDGE ブリッジ / ルータモードã§æŽ¥ç¶š(&B)
+R_MONITOR モニタリングモードã§æŽ¥ç¶š(&D)
+STATIC17 ãã®ä»–ã®è¨­å®š(&G):
+R_NO_ROUTING ルーティングテーブルã®èª¿æ•´å‡¦ç†ã‚’è¡Œã‚ãªã„(&R)
+STATIC18 ã“ã®è¨­å®šç”»é¢ã®è¨­å®šé …ç›®ã¯ã€ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‹ã‚‰æŒ‡ç¤ºãŒã‚ã£ãŸå ´åˆã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚„セキュリティã«é–¢ã—ã¦è©³ã—ã„知識をãŠæŒã¡ã®å ´åˆä»¥å¤–ã¯å¤‰æ›´ã—ãªã„ã§ãã ã•ã„。
+STATIC19 VoIP / QoS 対応機能を使用ã™ã‚‹ã¨ã€IP 電話パケットãªã©ã®å„ªå…ˆåº¦ã®é«˜ã„パケットを VPN 内ã§é«˜é€Ÿã«ä¼é€ã§ãã¾ã™ã€‚
+R_DISABLE_QOS VoIP / QoS 対応機能を無効ã«ã™ã‚‹(&Q)
+IDOK &OK
+IDCANCEL キャンセル
+S_UDPACCEL データ圧縮技術を使用ã—ã¦ã€VPN 通信を圧縮ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ダイヤルアップ接続やモãƒã‚¤ãƒ«æŽ¥ç¶šãªã©ã€ä½Žé€Ÿå›žç·šã§ã®ã¿ä½¿ç”¨ã—ã¦ãã ã•ã„。
+
+
+PREFIX D_CM_NEW_VLAN
+CAPTION æ–°ã—ã„仮想 LAN カードã®ä½œæˆ
+S_INFO æ–°ã—ã„仮想 LAN カードをシステムã«è¿½åŠ ã—ã¾ã™ã€‚\r\n仮想 LAN カードã«ã¯è‹±æ•°å­— %u 文字以内ã®åå‰ã‚’付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 仮想 LAN カードã®åå‰(&N):
+IDOK &OK
+IDCANCEL キャンセル
+S_WIN8 ç¾åœ¨ã® OS 㯠Windows 8 ã§ã™ã€‚仮想 LAN カードåã«ã¯ 'VPN'ã€ã¾ãŸã¯ 'VPN2' ã‹ã‚‰ 'VPN127' ã¾ã§ã®åå‰ã‚’指定ã—ã¦ãã ã•ã„ (åˆè¨ˆ 127 個作æˆå¯èƒ½)。
+
+
+PREFIX D_CM_TRUST
+CAPTION ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®ç®¡ç†
+STATIC1 VPN Client ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’管ç†ã—ã¾ã™ã€‚\r\n\r\nã“ã“ã§ç™»éŒ²ã•ã‚ŒãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Server ã¸ã®æŽ¥ç¶šæ™‚ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãªã©ã«åˆ©ç”¨ã•ã‚Œã¾ã™ã€‚
+B_IMPORT 追加(&A)
+B_EXPORT エクスãƒãƒ¼ãƒˆ(&E)
+IDOK 証明書ã®è¡¨ç¤º(&V)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+B_DELETE 削除(&D)
+
+
+PREFIX D_CM_PASSWORD
+CAPTION パスワードã®è¨­å®š - VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+S_TITLE ã“ã® SoftEther VPN Client サービスã®åˆ¶å¾¡ã‚’è¡Œã†ãŸã‚ã®ãƒ‘スワードを設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nパスワードを設定ã™ã‚‹ã¨ã€æ¬¡å›ž VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã§ SoftEther VPN Client サービスã«æŽ¥ç¶šã™ã‚‹éš›ã«ãƒ‘スワードã®å…¥åŠ›ãŒæ±‚ã‚られã¾ã™ã€‚
+STATIC1 クライアント管ç†ãƒ‘スワードã®è¨­å®š:
+R_USE_PASSWORD パスワードを設定ã™ã‚‹(&U)
+R_REMOTE_ONLY パスワードã¯ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰æ“作を行ã†å ´åˆã®ã¿è¦æ±‚ã™ã‚‹(&R)
+IDC_STATIC1 パスワード(&P):
+IDC_STATIC2 確èªå…¥åŠ›(&E):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_CONFIG
+CAPTION オプション設定
+STATIC1 VPN Client ã®å‹•ä½œã«é–¢ã™ã‚‹è¨­å®šã‚’変更ã§ãã¾ã™ã€‚
+STATIC2 リモート管ç†ã®è¨­å®š(&E)
+STATIC3 VPN Client サービスプログラムを別ã®ã‚³ãƒ³ãƒ”ュータ上ã‹ã‚‰ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã«ã‚ˆã£ã¦ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚
+R_ALLOW_REMOTE_CONFIG VPN Client サービスã®ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã‚’許å¯ã™ã‚‹(&R)
+S_WARNING リモート管ç†ã‚’許å¯ã™ã‚‹å ´åˆã€ãƒ‘スワードを設定ã—ã¦ãŠãã“ã¨ã‚’å¼·ããŠå‹§ã‚ã—ã¾ã™ã€‚パスワード㯠[ツール] メニュー㮠[パスワードã®è¨­å®š] をクリックã—ã¦è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC4 一定期間無通信状態ãŒç¶šãã¨æŽ¥ç¶šãŒè‡ªå‹•çš„ã«åˆ‡æ–­ã•ã‚Œã‚‹ã‚ˆã†ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šç’°å¢ƒã®å ´åˆã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ä»»æ„ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ä¸€å®šé–“éš”ã”ã¨ã«ãƒ‘ケットをé€ä¿¡ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’維æŒã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+R_USE_KEEP_CONNECT インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã‚’使用ã™ã‚‹(&K)
+S_HOSTNAME ホストå(&H):
+S_PORT ãƒãƒ¼ãƒˆç•ªå·(&P):
+S_INTERVAL パケットé€å‡ºé–“éš”(&I):
+S_INTERVAL2 秒間㫠1 パケット
+S_PROTOCOL プロトコル(&C):
+R_TCP TCP/IP プロトコル(&T)
+R_UDP UDP/IP プロトコル(&U)
+S_INFO インターãƒãƒƒãƒˆæŽ¥ç¶šç¶­æŒã®ãŸã‚ã«é€ä¿¡ã•ã‚Œã‚‹ãƒ‘ケットã¯ãƒ©ãƒ³ãƒ€ãƒ ãªå†…容ã§ã‚ã‚Šã€ã‚³ãƒ³ãƒ”ュータやユーザーを識別ã™ã‚‹å€‹äººæƒ…å ±ãªã©ãŒé€ä¿¡ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
+IDOK &OK
+IDCANCEL キャンセル
+STATIC5 ãã®ä»–ã®è¨­å®š(&S)
+R_ALPHA ウインドウをåŠé€æ˜Žã«ã™ã‚‹(&A)
+STATIC6 ※ åŠé€æ˜Žã®è¨­å®šã¯æŽ¥ç¶šãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’å†èµ·å‹•ã™ã‚‹ã¾ã§é©ç”¨ã•ã‚Œã¾ã›ã‚“。
+STATIC7 インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½(&N)
+
+
+PREFIX D_ABOUT
+S_INFO1 SoftEther VPN %u.0 (Ver %u.%02u, Build %u)
+S_INFO2 An Open-Source VPN Software for Academic Purpose, under the GPLv2 License.\r\nCopyright (c) 2012-%u SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.\r\nWeb Site: http://www.softether.org/\r\n%S
+S_INFO3 This product includes the following software components:\r\nBitVisor: Copyright (c) 2007, 2008 University of Tsukuba. Copyright (C) 2007, 2008 National Institute of Information and Communications Technology. All rights reserved. / Microsoft(R) C Runtime Library: (c) 2007 Microsoft Corporation. All Rights Reserved. / PKCS #11 Cryptographic Token Interface (Cryptoki): Copyright (c) RSA Security Inc. / WinPcap: Copyright (c) 2001 - 2003 NetGroup, Politecnico di Torino (Italy). All rights reserved. / libedit: Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved. / libiconv: Copyright (C) 2007 Free Software Foundation, Inc. / ncurses: Copyright (c) 1998-2005, 2006 Free Software Foundation, Inc. / OpenSSL: Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). / zlib: (C) 1995-2004 Jean-loup Gailly and Mark Adler. / Special Thanks to: Software Laboratory, Academic Computing Communication Center, Industrial Liaison and Cooperative Research Center and Professor Yasushi Shinjo in University of Tsukuba, Japan.
+S_INFO4 本ソフトウェアã¯ç­‘波大学 SoftEther VPN プロジェクトã§é–‹ç™ºã•ã‚ŒãŸãƒ•ãƒªãƒ¼ã‚¦ã‚§ã‚¢ã§ã™ã€‚本ソフトウェアã¯ä¸€åˆ‡ã®ä¿è¨¼ãŒãªã„状態ã§æä¾›ã•ã‚Œã‚‹ã‚‚ã®ã§ã‚ã‚Šã€é–‹ç™ºãŠã‚ˆã³é…布元ã¯ä½¿ç”¨ã®çµæžœã®æ害ã«ã¤ã„ã¦ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。\r\n\r\nSoftEther VPN ソフトウェアã¯æ—¥æœ¬å›½çµŒæ¸ˆç”£æ¥­çœã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ç ”究開発プロジェクトã®æˆæžœç‰©ã§ã™ã€‚IPA (独立行政法人 情報処ç†æŽ¨é€²æ©Ÿæ§‹) ã®æœªè¸ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢å‰µé€ äº‹æ¥­ã«æŽ¡æŠžã•ã‚Œé–‹ç™ºã•ã‚Œã¾ã—ãŸã€‚詳ã—ã㯠http://www.ipa.go.jp/ ã‚’ã”覧ãã ã•ã„。
+IDCANCEL &OK
+B_WEB SoftEther VPN 㮠Web サイト(&W)...
+B_EULA 使用許諾契約書(&E)
+B_IMPORTANT é‡è¦äº‹é …説明書(&I)
+B_LEGAL 法律上ã®é€šçŸ¥(&L)
+B_UPDATE_CONFIG 更新通知設定(&C)
+
+
+PREFIX D_REMOTE
+STATIC1 接続ã™ã‚‹ã‚³ãƒ³ãƒ”ュータã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスを指定ã—ã¦ãã ã•ã„(&S):
+R_LOCAL ローカルコンピュータ (ã“ã®ç”»é¢ã‚’表示ã—ã¦ã„るコンピュータ) ã«æŽ¥ç¶š(&L)
+S_HOSTNAME コンピュータå(&C):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_DESKTOP
+CAPTION 接続 - %s
+S_TITLE 接続設定 "%s" ã®æŽ¥ç¶šå‡¦ç†ã‚’開始ã—ã¾ã™ã€‚
+S_WARNING VPN Client ã¯ã€VPN Server ã¸ã®æŽ¥ç¶šä¸­ã®é€²è¡ŒçŠ¶æ³ã‚„エラー メッセージãªã©ã‚’ã€%s㮠「コンソールセッション〠ã®ç”»é¢ä¸Šã«å‡ºåŠ›ã—ã¾ã™ã€‚
+S_INFO 接続を継続ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹?
+IDOK 継続(&C)
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_CHANGE_PASSWORD
+CAPTION パスワードã®å¤‰æ›´
+S_TITLE サーãƒãƒ¼ %S 上ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ãƒ‘スワードを変更ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 パスワードã®å¤‰æ›´(&P)
+STATIC2 仮想 HUB å(&H):
+STATIC3 ユーザーå(&U):
+STATIC4 å¤ã„パスワード(&W):
+STATIC5 æ–°ã—ã„パスワード(&N):
+STATIC6 æ–°ã—ã„パスワードã®\r\n確èªå…¥åŠ›(&C):
+IDOK &OK
+IDCANCEL キャンセル
+S_STATIC ※ [RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼] を使用ã—ã¦èªè¨¼ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ‘スワードã¯å¤‰æ›´ã§ãã¾ã›ã‚“。
+
+
+PREFIX D_SM_MAIN
+CAPTION SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£
+STATIC1 SoftEther VPN Server ã¸ã®æŽ¥ç¶šè¨­å®š(&P):
+STATIC2 以下㮠VPN Server ã¾ãŸã¯ VPN Bridge ã¸ã®æŽ¥ç¶šè¨­å®šãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚åå‰ã‚’ダブルクリックã™ã‚‹ã¨ã€ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã™ã€‚\r\næ–°ã—ã„接続を追加ã™ã‚‹ã«ã¯ [æ–°ã—ã„接続設定] をクリックã—ã¦ãã ã•ã„。
+B_NEW_SETTING æ–°ã—ã„接続設定(&N)
+B_EDIT_SETTING 接続設定ã®ç·¨é›†(&E)
+B_DELETE 接続設定ã®å‰Šé™¤(&D)
+IDOK 接続(&C)
+B_SECURE_MANAGER スマートカードマãƒãƒ¼ã‚¸ãƒ£(&S)...
+B_SELECT_SECURE スマートカードé¸æŠž(&M)...
+B_ABOUT ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)
+IDCANCEL SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã®çµ‚了(&X)
+B_CERT_TOOL 証明書作æˆãƒ„ール(&R)
+
+
+PREFIX D_SM_EDIT_SETTING
+STATIC1 管ç†ã™ã‚‹ VPN Server ã®æŽ¥ç¶šè¨­å®šã‚’è¡Œã„ã¾ã™ã€‚
+STATIC2 接続設定å(&N):
+STATIC3 接続先 VPN Server ã®æŒ‡å®š(&B):
+STATIC4 管ç†ã—ãŸã„ VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスãŠã‚ˆã²ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¦ãã ã•ã„。
+STATIC5 ホストå(&H):
+R_LOCALHOST ã“ã®ã‚³ãƒ³ãƒ”ュータ (localhost) ã«æŽ¥ç¶š(&L)
+STATIC6 ãƒãƒ¼ãƒˆç•ªå·(&P):
+STATIC7 (TCP ãƒãƒ¼ãƒˆ)
+STATIC8 経由ã™ã‚‹ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®š(&X):
+STATIC9 プロキシサーãƒãƒ¼ã‚’経由ã—㦠VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC10 プロキシã®ç¨®é¡ž(&Y):
+R_DIRECT_TCP 直接 TCP/IP 接続 (プロキシを使ã‚ãªã„) (&D)
+R_HTTPS HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&T)
+R_SOCKS SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&K)
+B_PROXY_CONFIG プロキシサーãƒãƒ¼ã®æŽ¥ç¶šè¨­å®š(&R)
+STATIC11 管ç†ãƒ¢ãƒ¼ãƒ‰ã®é¸æŠžã¨ãƒ‘スワードã®å…¥åŠ›(&M)
+STATIC12 VPN Server ã«ã¯ã€ã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã¨ä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã®ã©ã¡ã‚‰ã‹ã®ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã§ãã¾ã™ã€‚\r\n\r\nサーãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã™ã‚‹ã¨ã€VPN Server ã®è¨­å®šã¨ã™ã¹ã¦ã®ä»®æƒ³ HUB ãŒç®¡ç†ã§ãã¾ã™ã€‚\r\n\r\n仮想 HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã™ã‚‹ã¨ã€æ¨©é™ã‚’æŒã£ã¦ã„る仮想 HUB ã®ç®¡ç†ãŒã§ãã¾ã™ã€‚
+R_SERVER_ADMIN サーãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰(&S)
+R_HUB_ADMIN 仮想 HUB 管ç†ãƒ¢ãƒ¼ãƒ‰(&U)
+S_HUBNAME 仮想 HUB å(&V):
+STATIC13 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。
+S_PASSWORD 管ç†ãƒ‘スワード(&A):
+R_NO_SAVE 管ç†ãƒ‘スワードをä¿å­˜ã—ãªã„(&W)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_SERVER
+CAPTION %s - SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£
+S_TITLE VPN Server "%S" ã®ç®¡ç†
+S_VHUB_BRIDGE ã“ã®ã‚µãƒ¼ãƒãƒ¼ãŒãƒ›ã‚¹ãƒˆã—ã¦ã„る仮想 HUB (&U):
+IDOK 仮想 HUB ã®ç®¡ç†(&A)
+B_ONLINE オンライン(&O)
+B_OFFLINE オフライン(&F)
+B_HUB_STATUS 状態ã®è¡¨ç¤º(&S)
+B_CREATE 仮想 HUB ã®ä½œæˆ(&C)
+B_EDIT プロパティ(&E)
+B_DELETE 削除(&D)
+STATIC1 リスナーã®ç®¡ç†(&J)
+STATIC2 リスナー一覧 (TCP/IP ãƒãƒ¼ãƒˆ) (&I):
+B_CREATE_LISTENER æ–°è¦ä½œæˆ(&R)
+B_DELETE_LISTENER 削除(&T)
+B_START 開始(&G)
+B_STOP åœæ­¢(&P)
+STATIC3 サーãƒãƒ¼æƒ…å ±ã®å‚ç…§ãŠã‚ˆã³è¨­å®š(&N)
+B_SSL æš—å·åŒ–ã¨é€šä¿¡é–¢ä¿‚ã®è¨­å®š(&W)
+B_STATUS サーãƒãƒ¼çŠ¶æ…‹ã®è¡¨ç¤º(&V)
+B_INFO SoftEther VPN Server\r\nã«é–¢ã™ã‚‹æƒ…å ±(&Q)
+B_LICENSE ライセンスã®è¿½åŠ ã¨å‰Šé™¤(&L)
+B_FARM クラスタリング構æˆ(&M)
+B_FARM_STATUS クラスタリング状態(&Z)
+B_CONNECTION TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³\r\n一覧ã®è¡¨ç¤º(&Y)
+B_BRIDGE ローカルブリッジ設定(&B)
+B_L3 レイヤ 3 スイッãƒè¨­å®š(&3)
+B_CONFIG Config 編集(&K)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+S_BETA ベータ版 (プレリリース)
+B_IPSEC IPsec / L&2TP 設定
+B_DDNS ダイナミック DNS 設定
+S_DDNS ç¾åœ¨ã® DDNS ホストå:
+B_OPENVPN OpenVPN / MS-SSTP 設定
+B_AZURE VPN Azure 設定
+S_AZURE VPN Azure ホストå:
+B_VPNGATE VPN Gate サービス設定
+
+
+PREFIX D_SM_STATUS
+IDOK 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_EDIT_HUB
+STATIC1 仮想 HUB å(&N):
+STATIC2 セキュリティ設定(&S):
+S_BOLD ã“ã®ä»®æƒ³ HUB ã®ç®¡ç†ç”¨ãƒ‘スワード
+STATIC3 パスワード(&P):
+STATIC4 確èªå…¥åŠ›(&C):
+R_NO_ENUM 匿åユーザーã«å¯¾ã—ã¦ã“ã®ä»®æƒ³ HUB を列挙ã—ãªã„(&U)
+STATIC5 仮想 HUB オプション(&I):
+R_LIMIT_MAX_SESSION 最大åŒæ™‚接続セッション数を制é™ã™ã‚‹(&L)
+S_MAX_SESSION_1 最大åŒæ™‚接続セッション数(&Z):
+S_MAX_SESSION_2 セッション
+STATIC6 (ローカルブリッジã€ä»®æƒ³ NATã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãªã©ã«ã‚ˆã£ã¦ç”Ÿæˆã•ã‚Œã‚‹ã‚µãƒ¼ãƒãƒ¼å´ã®ä»®æƒ³ã‚»ãƒƒã‚·ãƒ§ãƒ³æ•°ã¯å«ã¾ãªã„)
+STATIC7 仮想 HUB ã®çŠ¶æ…‹(&J):
+STATIC8 仮想 HUB ã®çŠ¶æ…‹ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+R_ONLINE オンライン(&E)
+R_OFFLINE オフライン(&F)
+STATIC9 クラスタリング設定(&M):
+S_FARM_INFO クラスタ内ã§ã®ä»®æƒ³ HUB ã®ç¨®é¡žã‚’é¸æŠžã—ã¦ãã ã•ã„。
+R_STATIC スタティック仮想 HUB(&A)
+R_DYNAMIC ダイナミック仮想 HUB(&D)
+S_AO_1 仮想 HUB 管ç†ã‚ªãƒ—ション(&Y):
+S_AO_3 仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを表示ãŠã‚ˆã³ç·¨é›†ã§ãã¾ã™ã€‚
+B_ADMINOPTION 仮想 HUB 管ç†ã‚ªãƒ—ション(&K)
+S_ACL_3 接続元 IP 制é™ãƒªã‚¹ãƒˆ(&R):
+S_ACL クライアントコンピュータ㮠IP アドレスã«ã‚ˆã£ã¦ã€ã“ã®ä»®æƒ³ HUB ã¸ã® VPN 接続を許å¯ã¾ãŸã¯æ‹’å¦ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_ACL 接続元 IP 制é™ãƒªã‚¹ãƒˆ(&T)
+IDOK &OK
+IDCANCEL キャンセル
+STATIC10 仮想 HUB 拡張オプションを使用ã™ã‚‹ã¨ã€ã“ã®ä»®æƒ³ HUB ã«é–¢ã™ã‚‹ã‚ˆã‚Šè©³ç´°ãªè¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+B_EXTOPTION 仮想 HUB 拡張オプションã®ç·¨é›†(&X)
+S_MSG_1 接続時ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示
+S_MSG_2 ã“ã®ä»®æƒ³ HUB ã« VPN Client ãŒæŽ¥ç¶šã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç”»é¢ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã§ãã¾ã™ã€‚
+B_MSG メッセージã®è¨­å®š(&G)
+
+
+PREFIX D_SM_CREATE_LISTENER
+CAPTION リスナーã®æ–°è¦ä½œæˆ
+STATIC1 VPN Server ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’å¾…ã¡å—ã‘ã‚‹ TCP/IP ãƒãƒ¼ãƒˆç•ªå·ã‚’追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\næ–°ã—ã追加ã™ã‚‹ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¦ãã ã•ã„。
+STATIC2 ãƒãƒ¼ãƒˆç•ªå·ãŒã™ã§ã«åˆ¥ã®ã‚µãƒ¼ãƒãƒ¼ プログラムã«ã‚ˆã£ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹å ´åˆãªã©ã€ãƒãƒ¼ãƒˆã®ç¢ºä¿ã«å¤±æ•—ã—ãŸå ´åˆã¯ã€ãƒªã‚¹ãƒŠãƒ¼ã®çŠ¶æ…‹ãŒã‚¨ãƒ©ãƒ¼çŠ¶æ…‹ã¨ãªã‚Šã¾ã™ã€‚\r\n\r\nãã®å ´åˆã¯ã€åŒã˜ãƒãƒ¼ãƒˆç•ªå·ã‚’é–‹ã„ã¦ã„る別ã®ãƒ—ログラムをåœæ­¢ã—ã¦ãã ã•ã„。
+STATIC3 ãƒãƒ¼ãƒˆç•ªå·(&P):
+IDOK &OK
+IDCANCEL キャンセル
+STATIC4 (TCP/IP ãƒãƒ¼ãƒˆ)
+
+
+PREFIX D_SM_SSL
+CAPTION æš—å·åŒ–ã¨é€šä¿¡é–¢ä¿‚ã®è¨­å®š
+STATIC1 ã“ã® VPN Server ã®æš—å·åŒ–ã€é€šä¿¡ã€ãŠã‚ˆã³ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã«é–¢ã™ã‚‹è¨­å®šã‚’å‚ç…§ã¾ãŸã¯å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 使用ã™ã‚‹æš—å·åŒ–アルゴリズム(&A):
+STATIC3 ã“ã® VPN Server ã«æŽ¥ç¶šã—㟠VPN Client ã¨ã®é–“ã§ä½¿ç”¨ã•ã‚Œã‚‹ SSL ã«å¯¾å¿œã—ãŸæš—å·åŒ–アルゴリズムåを指定ã—ã¦ãã ã•ã„。暗å·åŒ–アルゴリズム㯠SSL ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3 ã«å¯¾å¿œã—ãŸã‚‚ã®ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+STATIC4 æš—å·åŒ–アルゴリズムå(&C):
+STATIC6 サーãƒãƒ¼è¨¼æ˜Žæ›¸(&E):
+STATIC7 ã“ã® VPN Server ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«å¯¾ã—ã¦æ示ã™ã‚‹ X509 証明書ã¨ç§˜å¯†éµã‚’指定ã—ã¦ãã ã•ã„。
+B_IMPORT インãƒãƒ¼ãƒˆ(&I)
+B_EXPORT エクスãƒãƒ¼ãƒˆ(&X)
+B_VIEW 証明書ã®è¡¨ç¤º(&V)
+B_REGENERATE æ–°è¦ä½œæˆ(&N)
+STATIC8 インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½:
+STATIC9 一定期間無通信状態ãŒç¶šãã¨æŽ¥ç¶šãŒè‡ªå‹•çš„ã«åˆ‡æ–­ã•ã‚Œã‚‹ã‚ˆã†ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šç’°å¢ƒã®å ´åˆã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ä»»æ„ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ä¸€å®šé–“éš”ã”ã¨ã«ãƒ‘ケットをé€ä¿¡ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’維æŒã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC10 サーãƒãƒ¼è¨¼æ˜Žæ›¸:
+R_USE_KEEP_CONNECT インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã‚’使用ã™ã‚‹(&K)
+S_HOSTNAME ホストå(&H):
+S_PORT ãƒãƒ¼ãƒˆç•ªå·(&F):
+S_INTERVAL パケットé€å‡ºé–“éš”(&D):
+S_INTERVAL2 秒
+S_PROTOCOL プロトコル(&L):
+R_TCP TCP/IP プロトコル(&T)
+R_UDP UDP/IP プロトコル(&U)
+S_INFO インターãƒãƒƒãƒˆæŽ¥ç¶šç¶­æŒã®ãŸã‚ã«é€ä¿¡ã•ã‚Œã‚‹ãƒ‘ケットã¯ãƒ©ãƒ³ãƒ€ãƒ ãªå†…容ã§ã‚ã‚Šã€ã‚³ãƒ³ãƒ”ュータやユーザーを識別ã™ã‚‹å€‹äººæƒ…å ±ãªã©ãŒé€ä¿¡ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
+STATIC11 管ç†è€…パスワード(&W):
+S_INFO4 ã“ã® VPN Server 全体ã¨ã™ã¹ã¦ã®ä»®æƒ³ HUB ã«å¯¾ã™ã‚‹ç®¡ç†æ¨©é™ã‚’有ã™ã‚‹ç®¡ç†è€…パスワードを設定ã¾ãŸã¯å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_PASSWORD 管ç†è€…パスワードã®å¤‰æ›´(&P)
+IDOK &OK
+IDCANCEL キャンセル
+IDCANCEL2 キャンセル
+STATIC12 syslog é€ä¿¡æ©Ÿèƒ½
+STATIC13 VPN サーãƒãƒ¼ / VPN ブリッジ全体ã®ãƒ­ã‚°ã€ä»®æƒ³ HUB ã®ç®¡ç†ãƒ­ã‚°ãŠã‚ˆã³ä»®æƒ³ HUB ã®ãƒ‘ケットログをã€ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã®ãƒ•ã‚¡ã‚¤ãƒ«ã«æ›¸ã出ã™ä»£ã‚ã‚Šã« syslog プロトコルã§è»¢é€ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC14 syslog サーãƒãƒ¼ãƒ›ã‚¹ãƒˆå(&S):
+STATIC15 ãƒãƒ¼ãƒˆç•ªå·(&R):
+S_OVER_FUNCS VPN over ICMP / DNS サーãƒãƒ¼æ©Ÿèƒ½
+S_INFO5 ファイアウォールやルータ㧠TCP/IP ã®é€šä¿¡ãŒé®æ–­ã•ã‚Œã¦ã„ã‚‹å ´åˆã§ã‚‚ã€ICMP ã¾ãŸã¯ DNS パケットã®ã¿ã‚’用ã„㦠VPN を確立ã§ãã¾ã™ã€‚
+B_SPECIALLISTENER VPN over ICMP / DNS 設定
+B_UPDATE_CONFIG 更新通知設定(&U)...
+
+
+PREFIX D_SM_SAVE_KEY_PAIR
+CAPTION 証明書ã¨ç§˜å¯†éµã®ä¿å­˜
+STATIC1 証明書ã¨ç§˜å¯†éµã‚’ä¿å­˜ã™ã‚‹æ–¹æ³•ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+STATIC2 ä¿å­˜æ–¹æ³•(&V):
+R_X509_AND_KEY X509 証明書ファイル (.CER) ã¨ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ« (.KEY) ã®çµ„åˆã›ã¨ã—ã¦ä¿å­˜ã™ã‚‹(&X)
+R_PKCS12 PKCS#12 ファイル (.P12) ã¨ã—ã¦ä¿å­˜ã™ã‚‹(&P)
+R_SECURE スマートカードã«æ›¸ã込む(&W)
+STATIC3 標準的㪠Base 64 ã«ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸè¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã¨ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã® 2 ã¤ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«åˆ†ã‘ã¦ä¿å­˜ã—ã¾ã™ã€‚
+STATIC4 PKCS#12 (Public Key Cryptography Standard #12) ファイルã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚\r\n1 ã¤ã® PKCS#12 ファイルã«ã¯ã€è¨¼æ˜Žæ›¸ã¨ç§˜å¯†éµã®ä¸¡æ–¹ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã™ã€‚
+STATIC5 ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãŒæŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰å†…ã«è¨¼æ˜Žæ›¸ã¨ç§˜å¯†éµã‚’åŒæ™‚ã«æ›¸ã込むã“ã¨ãŒã§ãã¾ã™ã€‚
+B_SELECT 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®é¸æŠž(&S)...
+S_PASS3 秘密éµã®ä¿è­·(&R)
+S_PASS4 秘密éµã‚’ä¿å­˜ã™ã‚‹éš›ã«ãƒ‘スフレーズを設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚パスフレーズを設定ã—ãŸç§˜å¯†éµã¯ã€èª­ã¿å–ã‚‹éš›ã«ãƒ‘スフレーズを入力ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+R_USE_PASS パスフレーズを設定ã™ã‚‹(&A)
+S_PASS1 パスフレーズ(&H):
+S_PASS2 確èªå…¥åŠ›(&E):
+IDOK &OK
+IDCANCEL キャンセル
+B_SECURE_MANAGER スマートカードマãƒãƒ¼ã‚¸ãƒ£(&M)...
+
+
+PREFIX D_SM_CONNECTION
+CAPTION コãƒã‚¯ã‚·ãƒ§ãƒ³ä¸€è¦§
+S_TITLE ç¾åœ¨ã€ã‚µãƒ¼ãƒãƒ¼ %S ã«æŽ¥ç¶šä¸­ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚ãŸã ã—ã€VPN セッションãŒç¢ºç«‹æ¸ˆã¿ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。
+IDOK コãƒã‚¯ã‚·ãƒ§ãƒ³ã®æƒ…報を表示(&I)
+B_DISCONNECT 切断(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_FARM
+CAPTION クラスタリング構æˆ
+S_TITLE VPN Server "%S" ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°æ§‹æˆã‚’変更ã§ãã¾ã™ã€‚
+STATIC1 複数å°ã® VPN Server ã§ã‚¯ãƒ©ã‚¹ã‚¿ã‚’構æˆã™ã‚‹ã¨ã€ãƒ­ãƒ¼ãƒ‰ãƒãƒ©ãƒ³ã‚·ãƒ³ã‚° (è² è·åˆ†æ•£) ãŠã‚ˆã³ãƒ•ã‚©ãƒ¼ãƒ«ãƒˆãƒˆãƒ¬ãƒ©ãƒ³ã‚¹ã®ç¢ºä¿ã‚’実ç¾ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 ç¾åœ¨ã®å‹•ä½œãƒ¢ãƒ¼ãƒ‰:
+STATIC3 クラスタリング構æˆã®è¨­å®š(&T):
+R_STANDALONE スタンドアロンサーãƒãƒ¼ (クラスタリング構æˆç„¡ã—) (&S)
+R_CONTROLLER クラスタコントローラ(&C)
+R_MEMBER クラスタメンãƒã‚µãƒ¼ãƒãƒ¼(&M)
+STATIC4 クラスタメンãƒã‚µãƒ¼ãƒãƒ¼æ™‚ã®è¨­å®šé …ç›®(&E):
+S_IP_1 公開 IP アドレス(&I):
+S_IP_2 (公開 IP アドレスを入力ã—ãªã„å ´åˆã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¸ã®æŽ¥ç¶šã®éš›ã«ä½¿ç”¨ã•ã‚Œã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã® IP アドレスãŒè‡ªå‹•çš„ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚)
+S_PORT_1 公開ãƒãƒ¼ãƒˆä¸€è¦§(&P):
+S_PORT_2 (複数入力ã™ã‚‹å ´åˆã¯ã‚¹ãƒšãƒ¼ã‚¹ã¾ãŸã¯ã‚«ãƒ³ãƒžã§åŒºåˆ‡ã£ã¦ãã ã•ã„。)
+S_CONTROLLER コントローラã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレス(&H):
+S_CONTROLLER_PORT コントローラã®\r\nãƒãƒ¼ãƒˆç•ªå·(&R):
+S_PORT_3 (TCP ãƒãƒ¼ãƒˆ)
+S_PASSWORD 管ç†ãƒ‘スワード(&D):
+STATIC5 クラスタリング構æˆã‚’変更ã™ã‚‹ã¨ã€VPN Server サービスãŒè‡ªå‹•çš„ã«å†èµ·å‹•ã—ã¾ã™ã€‚ãã®éš›ã€ç¾åœ¨æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŠã‚ˆã³ç®¡ç†ç”¨ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ãŒåˆ‡æ–­ã•ã‚Œã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+S_1 クラスタ内ã§ã®æ€§èƒ½åŸºæº–比(&W):
+S_2 (標準: 100)
+R_CONTROLLER_ONLY コントローラ機能ã®ã¿ (自身㯠VPN 通信を処ç†ã—ãªã„)
+
+
+PREFIX D_SM_FARM_MEMBER
+CAPTION クラスタメンãƒä¸€è¦§
+S_TITLE ç¾åœ¨ã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ© %S ã«ã¯ä»¥ä¸‹ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ãŒæŽ¥ç¶šã—ã¦ã„ã¾ã™ã€‚
+IDOK クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã®æƒ…報を表示(&I)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+B_CERT サーãƒãƒ¼è¨¼æ˜Žæ›¸ã®è¡¨ç¤º(&C)
+
+
+PREFIX D_SM_CHANGE_PASSWORD
+CAPTION %S ã®ç®¡ç†è€…パスワードã®è¨­å®š
+S_TITLE サーãƒãƒ¼ %S ã®ç®¡ç†è€…パスワードを設定ã—ã¾ã™ã€‚æ–°ã—ã„パスワードを入力ã—ã¦ã‹ã‚‰ [OK] をクリックã—ã¦ãã ã•ã„。
+STATIC1 æ–°ã—ã„パスワード(&P):
+STATIC2 確èªå…¥åŠ›(&C):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_HUB
+CAPTION 仮想 HUB ã®ç®¡ç† - %S
+S_TITLE %S ã®ç®¡ç†
+STATIC1 セキュリティデータベースã®ç®¡ç†(&D):
+B_USER ユーザーã®ç®¡ç†(&U)
+S_USER ユーザー アカウントを追加・削除・編集ã§ãã¾ã™ã€‚
+B_GROUP グループã®ç®¡ç†(&G)
+S_GROUP グループを追加・削除・編集ã§ãã¾ã™ã€‚
+B_ACCESS アクセスリストã®ç®¡ç†(&A)
+S_ACCESS アクセスリスト (パケットフィルタリングルール) を追加・削除ã§ãã¾ã™ã€‚
+STATIC2 仮想 HUB 設定(&N)
+B_PROPERTY 仮想 HUB ã®ãƒ—ロパティ(&P)
+S_PROPERTY ã“ã®ä»®æƒ³ HUB ã®è¨­å®šã‚’変更ã§ãã¾ã™ã€‚
+B_RADIUS èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®š(&E)
+S_RADIUS ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ RADIUS èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_LINK カスケード接続ã®ç®¡ç†(&C)
+S_LINK åŒä¸€ã¾ãŸã¯åˆ¥ã®ã‚µãƒ¼ãƒãƒ¼ä¸Šã®è¤‡æ•°ã®ä»®æƒ³ HUB åŒå£«ã‚’カスケード接続ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC3 ã“ã®ä»®æƒ³ HUB ã®ç¾åœ¨ã®çŠ¶æ³(&R):
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+STATIC4 ãã®ä»–ã®ç®¡ç†(&O)
+B_LOG ログä¿å­˜è¨­å®š(&L)
+B_LOG_FILE ログファイル一覧(&Q)
+S_LOG ログã®ä¿å­˜ã«é–¢ã™ã‚‹è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_CA ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸(&T)
+B_CRL 無効ãªè¨¼æ˜Žæ›¸(&K)
+S_CA ã“ã®ä»®æƒ³ HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã‚’管ç†ã—ã¾ã™ã€‚
+B_SNAT 仮想 NAT ãŠã‚ˆã³ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½(&V)
+S_SNAT ã“ã®ä»®æƒ³ HUB 内㧠SecureNAT 機能を動作ã•ã›ã¾ã™ã€‚仮想 NAT ã¨ä»®æƒ³ DHCP を稼動ã§ãã¾ã™ã€‚
+STATIC5 セッションã®ç®¡ç†(&I):
+B_SESSION セッションã®ç®¡ç†(&S)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_USER
+CAPTION ユーザーã®ç®¡ç†
+S_TITLE 仮想 HUB "%S" ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+IDOK 編集(&E)
+B_CREATE æ–°è¦ä½œæˆ(&C)
+B_DELETE 削除(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&R)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+B_STATUS ユーザー情報表示(&V)
+
+
+PREFIX D_SM_EDIT_USER
+IDC_STATIC1 ユーザーå(&U):
+IDC_STATIC3 本å(&R):
+IDC_STATIC4 説明(&N):
+IDC_STATIC5 グループå\r\n(çœç•¥å¯èƒ½):
+B_GROUP グループã®å‚ç…§(&J)...
+R_EXPIRES ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®æœ‰åŠ¹æœŸé™ã‚’設定ã™ã‚‹(&S)
+IDC_STATIC6 èªè¨¼æ–¹æ³•(&A):
+S_RADIUS_3 RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼
+S_RADIUS_1 外部㮠RADIUS サーãƒãƒ¼ã€Windows NT ドメインコントローラã€ã¾ãŸã¯ Active Directory コントローラã«ã‚ˆã£ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå…¥åŠ›ã—ãŸãƒ‘スワードãŒæ¤œè¨¼ã•ã‚Œã¾ã™ã€‚
+R_SET_RADIUS_USERNAME èªè¨¼ã‚µãƒ¼ãƒãƒ¼ä¸Šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã™ã‚‹(&K)
+S_RADIUS_2 èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã«ãŠã‘るユーザーå(&T):
+S_POLICY_1 セキュリティãƒãƒªã‚·ãƒ¼
+R_POLICY ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã‚’設定ã™ã‚‹(&Y)
+B_POLICY セキュリティãƒãƒªã‚·ãƒ¼(&M)
+S_PASSWORD_1 パスワードèªè¨¼
+S_PASSWORD_2 パスワード(&P):
+S_PASSWORD_3 パスワードã®ç¢ºèªå…¥åŠ›(&C):
+S_USER_CERT_1 固有証明書èªè¨¼
+B_LOAD_CERT 証明書ã®æŒ‡å®š(&E)
+B_VIEW_CERT 証明書ã®è¡¨ç¤º(&V)
+B_CREATE 証明書作æˆãƒ„ール(&W)
+S_ROOT_CERT_1 ç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼
+S_ROOT_CERT_2 クライアント証明書ãŒã“ã®ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’検証ã—ã¾ã™ã€‚
+R_CN 証明書㮠Common Name (CN) ã®å€¤ã‚’é™å®šã™ã‚‹(&B)
+R_SERIAL 証明書ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå·ã®å€¤ã‚’é™å®šã™ã‚‹(&L)
+S_ROOT_CERT_3 ※ 16 進数ã§å…¥åŠ›ã—ã¦ãã ã•ã„。(例: 0155ABCDEF)
+S_HINT ヒント: ユーザーå㌠'*' (アスタリスク) ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’作æˆã™ã‚‹ã¨ã€ä»–ã«æ˜Žç¤ºçš„ã«ä¸€è‡´ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®å®šç¾©ãŒãªã„ユーザーãŒæŽ¥ç¶šã—よã†ã¨ã—ãŸå ´åˆã«å¤–部èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã‚’使用ã—ãŸãƒ‘スワードèªè¨¼ã«ã‚ˆã‚‹æŽ¥ç¶šã‚’許å¯ã§ãã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_POLICY
+STATIC1 é¸æŠžã•ã‚Œã¦ã„ã‚‹ãƒãƒªã‚·ãƒ¼(&P):
+S_BOLD ã“ã®ãƒãƒªã‚·ãƒ¼ã®èª¬æ˜Ž(&C):
+S_BOLD2 設定値(&V):
+R_ENABLE ã“ã®ãƒãƒªã‚·ãƒ¼ã‚’有効ã«ã™ã‚‹(&E)
+R_DISABLE ã“ã®ãƒãƒªã‚·ãƒ¼ã‚’無効ã«ã™ã‚‹(&D)
+R_DEFINE ã“ã®ãƒãƒªã‚·ãƒ¼ã®å€¤ã‚’定義ã™ã‚‹(&F)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_GROUP
+CAPTION グループã®ç®¡ç†
+S_TITLE 仮想 HUB "%S" ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+B_CREATE æ–°è¦ä½œæˆ(&C)
+IDOK 編集(&E)
+B_DELETE 削除(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&R)
+B_USER メンãƒä¸€è¦§(&M)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_EDIT_GROUP
+IDC_STATIC1 グループå(&G):
+IDC_STATIC3 本å(&R):
+IDC_STATIC4 説明(&N):
+S_POLICY_1 セキュリティãƒãƒªã‚·ãƒ¼
+R_POLICY ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã‚’設定ã™ã‚‹(&Y)
+B_POLICY セキュリティãƒãƒªã‚·ãƒ¼(&M)
+S_POLICY_2 ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®çµ±è¨ˆæƒ…å ±
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_ACCESS_LIST
+CAPTION アクセスリスト
+S_TITLE 仮想 HUB "%S" ã«ã¯ã€ç¾åœ¨ä»¥ä¸‹ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆ (パケットフィルタリングルール) ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚
+B_ADD 追加 (IPv&4)
+B_ADD_V6 追加 (IPv&6)
+IDOK 編集(&E)
+B_DELETE 削除(&D)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL キャンセル(&C)
+STATIC1 優先順ä½ã¯ãƒªã‚¹ãƒˆã®ä¸Šã®ã‚‚ã®ã»ã©é«˜ããªã‚Šã¾ã™ã€‚
+STATIC2 VPN Server ã§ã¯ã€ã©ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆé …ç›®ã«ã‚‚一致ã—ãªã‹ã£ãŸ IP パケットã¯ã€ç„¡æ¡ä»¶ã§ä»®æƒ³ HUB を通éŽã§ãã¾ã™ã€‚
+B_CLONE クローン(&O)
+B_ENABLE 有効ã«ã™ã‚‹(&N)
+B_DISABLE 無効ã«ã™ã‚‹(&I)
+
+
+PREFIX D_SM_EDIT_ACCESS
+CAPTION アクセスリスト項目ã®ç·¨é›†
+STATIC1 アクセスリスト項目を設定ã—ã¦ãã ã•ã„。ã“ã“ã§è¨­å®šã—ãŸã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã¯ã€ä»®æƒ³ HUB 内を通éŽã™ã‚‹ã™ã¹ã¦ã® IP パケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã¾ã™ã€‚
+STATIC2 基本設定
+STATIC3 アクセスリストã®èª¬æ˜Ž(&N):
+STATIC4 動作(&A):
+R_PASS 通éŽ(&P)
+R_DISCARD 破棄(&D)
+STATIC5 優先順ä½(&R):
+STATIC6 (整数値: å°ã•ã„ã»ã©\r\n優先順ä½ãŒé«˜ããªã‚Šã¾ã™)
+STATIC7 IP ヘッダã«é–¢ã™ã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã‚ªãƒ—ション
+S_ACCESS_SRC_ALL é€ä¿¡å…ƒ IP アドレス:
+R_SRC_ALL ã™ã¹ã¦ã®é€ä¿¡å…ƒã«å¯¾ã—ã¦é©ç”¨ã™ã‚‹
+S_SRC_IP_1 IPv4 アドレス:
+S_SRC_IP_2 マスク:
+S_SRC_IP_3 (255.255.255.255: å˜ä¸€ãƒ›ã‚¹ãƒˆ)
+S_SRC_IP_1_V6 IPv6 アドレス:
+S_SRC_IP_3_V6 (マスク表記例: "ffff:ff00::" ã¾ãŸã¯ "/24"。å˜ä¸€ãƒ›ã‚¹ãƒˆã®å ´åˆã¯ "/128")
+S_ACCESS_DST_ALL 宛先 IP アドレス:
+R_DST_ALL ã™ã¹ã¦ã®å®›å…ˆã«å¯¾ã—ã¦é©ç”¨ã™ã‚‹
+S_IP_DST_1 IPv4 アドレス:
+S_IP_DST_2 マスク:
+S_IP_DST_3 (255.255.255.255: å˜ä¸€ãƒ›ã‚¹ãƒˆ)
+S_IP_DST_1_V6 IPv6 アドレス:
+S_IP_DST_3_V6 (マスク表記例: "ffff:ff00::" ã¾ãŸã¯ "/24"。å˜ä¸€ãƒ›ã‚¹ãƒˆã®å ´åˆã¯ "/128")
+STATIC9 プロトコルã®ç¨®é¡ž:
+STATIC10 TCP ヘッダã¾ãŸã¯ UDP ヘッダã«é–¢ã™ã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã‚ªãƒ—ション
+S_TCP_1 最å°å€¤
+S_TCP_2 最大値
+S_TCP_3 é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·:
+S_TCP_5 宛先ãƒãƒ¼ãƒˆç•ªå·:
+S_TCP_7 ãƒãƒ¼ãƒˆç•ªå·ãŒç©ºæ¬„ã®å ´åˆã¯ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã¾ã™ã€‚\r\n最å°å€¤ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¦æœ€å¤§å€¤ãŒæŒ‡å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯æœ€å°å€¤ã¨ä¸€è‡´ã™ã‚‹ãƒ‘ケットã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚
+STATIC11 ユーザーã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«é–¢ã™ã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã‚ªãƒ—ション
+STATIC11_OLD ユーザーã«é–¢ã™ã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã‚ªãƒ—ション
+STATIC12 ã“ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆé …目を特定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ãŒé€ä¿¡ã—ãŸãƒ‘ケットã€ã¾ãŸã¯ç‰¹å®šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚ˆã£ã¦å—ä¿¡ã•ã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦ã®ã¿é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC12_OLD ã“ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆé …目を特定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé€ä¿¡ã—ãŸãƒ‘ケットã€ã¾ãŸã¯ç‰¹å®šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã£ã¦å—ä¿¡ã•ã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦ã®ã¿é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC13 é€ä¿¡å…ƒã®åå‰:
+B_USER1 å‚ç…§...
+STATIC14 宛先ã®åå‰:
+B_USER2 å‚ç…§...
+STATIC15 ãã‚Œãžã‚Œãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åã®ã©ã¡ã‚‰ã‹ã‚’指定ã—ã¦ãã ã•ã„。指定ã—ãªã„å ´åˆã¯ç©ºæ¬„ã«ã—ã¦ãã ã•ã„。
+STATIC15_OLD ãã‚Œãžã‚Œãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¦ãã ã•ã„。指定ã—ãªã„å ´åˆã¯ç©ºæ¬„ã«ã—ã¦ãã ã•ã„。
+IDOK &OK
+IDCANCEL キャンセル
+S_PROTOID IP プロトコル番å·ã®æŒ‡å®š:
+STATIC16 MAC ヘッダã«é–¢ã™ã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã‚ªãƒ—ション
+S_CHECK_SRC_MAC é€ä¿¡å…ƒ MAC アドレス:
+R_CHECK_SRC_MAC ã™ã¹ã¦ã®é€ä¿¡å…ƒã«å¯¾ã—ã¦é©ç”¨ã™ã‚‹
+S_SRC_MAC MAC アドレス:
+S_SRC_MAC_MASK マスク:
+S_CHECK_DST_MAC 宛先 MAC アドレス:
+R_CHECK_DST_MAC ã™ã¹ã¦ã®å®›å…ˆã«å¯¾ã—ã¦é©ç”¨ã™ã‚‹
+B_SIMULATION é…延・パケットロス生æˆæ©Ÿèƒ½(&L)...
+S_DST_MAC MAC アドレス:
+S_DST_MAC_MASK マスク:
+S_MAC_NOTE MAC アドレスã¨ãƒžã‚¹ã‚¯ã« 16 進数㨠"-" ã¾ãŸã¯ ":" ã®æ–‡å­—ãŒä½¿ãˆã¾ã™ãŒã€çœç•¥ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚(FF-FF-FF-FF-FF-FF: å˜ä¸€ãƒ›ã‚¹ãƒˆ)
+R_CHECK_TCP_STATE TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’検査 (TCP パケットã®ã¿)
+R_ESTABLISHED 確立済ã¿ãƒ‘ケット
+R_UNESTABLISHED 未確立パケット
+R_REDIRECT HTTP アクセスを強制的ã«æŒ‡å®š URL ã¸ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆ
+B_REDIRECT リダイレクト先 URL...
+
+
+PREFIX D_SM_RADIUS
+CAPTION èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®š
+S_TITLE 仮想 HUB "%S" ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ RADIUS サーãƒãƒ¼èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ãŸå ´åˆã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを確èªã™ã‚‹å¤–部㮠RADIUS サーãƒãƒ¼ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 RADIUS サーãƒãƒ¼ã®è¨­å®š(&F):
+R_USE_RADIUS RADIUS èªè¨¼ã‚’使用ã™ã‚‹(&U)
+S_RADIUS_1 RADIUS サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレス(&S):
+S_RADIUS_2 ãƒãƒ¼ãƒˆç•ªå·(&P):
+S_RADIUS3 (UDP ãƒãƒ¼ãƒˆ)
+S_RADIUS_4 共有シークレット(&E):
+S_RADIUS_5 共有シークレットã®ç¢ºèªå…¥åŠ›(&C):
+S_RADIUS_6 RADIUS サーãƒãƒ¼ã¯ã€ã“ã® VPN Server ã® IP アドレスã‹ã‚‰ã®è¦æ±‚ã‚’å—ã‘付ã‘るよã†ã«è¨­å®šã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€Password Authentication Protocol (PAP) ã«ã‚ˆã‚‹èªè¨¼ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+S_RADIUS_7 ミリ秒 (%u 以上 %u 未満)
+S_RADIUS_8 å†è©¦è¡Œé–“éš”(&R):
+S_RADIUS_9 (, ã¾ãŸã¯ ; ã§è¤‡æ•°æŒ‡å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚)
+STATIC2 外部èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã¨ã—㦠Windows NT ドメインコントローラã¾ãŸã¯ Windows Server ã® Active Directory コントローラを使用ã™ã‚‹å ´åˆã¯ã€VPN Server を動作ã•ã›ã¦ã„るコンピュータをãã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«æ‰€å±žã•ã›ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚NT ドメインèªè¨¼ã‚’使用ã™ã‚‹å ´åˆã¯ã€è¨­å®šã™ã‚‹é …ç›®ã¯ã‚ã‚Šã¾ã›ã‚“。
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_LINK
+CAPTION %S 上ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶š
+STATIC1 カスケード接続を使用ã™ã‚‹ã¨ã€ã“ã®ä»®æƒ³ HUB ã‚’åŒä¸€ã¾ãŸã¯åˆ¥ã®ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã—ã¦ã„ã‚‹ä»–ã®ä»®æƒ³ HUB ã«ãƒ¬ã‚¤ãƒ¤ 2 カスケード接続ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 カスケード接続ã«ãŠã‘る警告
+STATIC3 カスケード接続を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ä»®æƒ³ HUB é–“ã§ã®ãƒ¬ã‚¤ãƒ¤ 2 ブリッジãŒå¯èƒ½ã§ã™ãŒã€æŽ¥ç¶šæ–¹æ³•ã‚’é–“é•ãˆã‚‹ã¨ã€ãƒ«ãƒ¼ãƒ—状ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆã—ã¦ã—ã¾ã†å ´åˆãŒã‚ã‚Šã¾ã™ã€‚カスケード接続機能を使用ã™ã‚‹éš›ã«ã¯ã€æ…Žé‡ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒˆãƒãƒ­ã‚¸ã‚’設計ã—ã¦ãã ã•ã„。
+B_CREATE æ–°è¦ä½œæˆ(&C)
+B_EDIT 編集(&E)
+B_ONLINE オンライン(&N)
+B_OFFLINE オフライン(&F)
+IDOK 状態(&S)
+B_DELETE 削除(&D)
+B_RENAME åå‰ã®å¤‰æ›´(&A)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&R)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_LOG
+CAPTION ログä¿å­˜è¨­å®š
+S_TITLE 仮想 HUB "%S" ã«é–¢ã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚° (ユーザーã®ãƒ­ã‚°ã‚¤ãƒ³ãªã©ã®è¨˜éŒ²) ãŠã‚ˆã³ä»®æƒ³ HUB を通éŽã™ã‚‹ã™ã¹ã¦ã®ãƒ‘ケットã«é–¢ã™ã‚‹ãƒ‘ケットログをä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 セキュリティログ(&S):
+B_SEC セキュリティログをä¿å­˜ã™ã‚‹(&E)
+S_SEC ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸ(&W):
+STATIC2 パケットログ(&P):
+B_PACKET パケットログをä¿å­˜ã™ã‚‹(&F)
+S_PACKET ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸ(&X):
+S_PACKET_0 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãƒ­ã‚°:
+B_PACKET_0_0 ä¿å­˜ç„¡ã—
+B_PACKET_0_1 ヘッダ情報ã®ã¿
+B_PACKET_0_2 パケット内容ã™ã¹ã¦
+S_PACKET_1 TCP パケットログ:
+B_PACKET_1_0 ä¿å­˜ç„¡ã—
+B_PACKET_1_1 ヘッダ情報ã®ã¿
+B_PACKET_1_2 パケット内容ã™ã¹ã¦
+S_PACKET_2 DHCP パケットログ:
+B_PACKET_2_0 ä¿å­˜ç„¡ã—
+B_PACKET_2_1 ヘッダ情報ã®ã¿
+B_PACKET_2_2 パケット内容ã™ã¹ã¦
+S_PACKET_3 UDP パケットログ:
+B_PACKET_3_0 ä¿å­˜ç„¡ã—
+B_PACKET_3_1 ヘッダ情報ã®ã¿
+B_PACKET_3_2 パケット内容ã™ã¹ã¦
+S_PACKET_4 ICMP パケットログ:
+B_PACKET_4_0 ä¿å­˜ç„¡ã—
+B_PACKET_4_1 ヘッダ情報ã®ã¿
+B_PACKET_4_2 パケット内容ã™ã¹ã¦
+S_PACKET_5 IP パケットログ:
+B_PACKET_5_0 ä¿å­˜ç„¡ã—
+B_PACKET_5_1 ヘッダ情報ã®ã¿
+B_PACKET_5_2 パケット内容ã™ã¹ã¦
+S_PACKET_6 ARP パケットログ:
+B_PACKET_6_0 ä¿å­˜ç„¡ã—
+B_PACKET_6_1 ヘッダ情報ã®ã¿
+B_PACKET_6_2 パケット内容ã™ã¹ã¦
+S_PACKET_7 Ethernet\r\nパケットログ:
+B_PACKET_7_0 ä¿å­˜ç„¡ã—
+B_PACKET_7_1 ヘッダ情報ã®ã¿
+B_PACKET_7_2 パケット内容ã™ã¹ã¦
+IDOK &OK
+IDCANCEL キャンセル
+STATIC3 大é‡ã®ãƒ‘ケットログをä¿å­˜ã—よã†ã¨ã™ã‚‹ã¨ã€CPU ãŠã‚ˆã³ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ã«å¤§ããªè² æ‹…ãŒã‹ã‹ã‚Šã€ä»®æƒ³ HUB ã‚„ VPN Server 全体ã®ãƒ‘フォーマンス低下ã®åŽŸå› ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚å¿…è¦ãªãƒ‘ケットログ情報ã®ã¿ä¿å­˜ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¦ãã ã•ã„。
+
+
+PREFIX D_SM_CA
+CAPTION ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®ç®¡ç†
+STATIC1 ã“ã®ä»®æƒ³ HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’管ç†ã—ã¾ã™ã€‚\r\n\r\nã“ã“ã§ç™»éŒ²ã•ã‚ŒãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Client ãŒç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ããŸéš›ã®è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+B_IMPORT 追加(&A)
+IDOK 証明書ã®è¡¨ç¤º(&V)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+B_DELETE 削除(&D)
+
+
+PREFIX D_SM_SESSION
+CAPTION セッションã®ç®¡ç† - %S
+S_TITLE ç¾åœ¨ã€ä»®æƒ³ HUB "%S" ã«ä»¥ä¸‹ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒæŽ¥ç¶šã—ã¦ã„ã¾ã™ã€‚
+STATIC1 セッションã«é–¢ã™ã‚‹æ“作
+IDOK セッションã®æƒ…報を表示(&I)
+B_DISCONNECT 切断(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+B_SESSION_MAC_TABLE ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã® MAC テーブル(&M)
+B_SESSION_IP_TABLE ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã® IP テーブル(&P)
+STATIC2 ãã®ä»–ã®ç®¡ç†ã‚¿ã‚¹ã‚¯
+B_MAC_TABLE MAC アドレステーブル一覧(&A)
+B_IP_TABLE IP アドレステーブル一覧(&B)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+S_FARM_INFO_2 ç¾åœ¨ã®ã‚¯ãƒ©ã‚¹ã‚¿ä¸Šã®ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’表示ã—ã¦ã„ã¾ã™ãŒã€åˆ¥ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ä¸Šã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’管ç†ã™ã‚‹ã«ã¯ãã®ã‚µãƒ¼ãƒãƒ¼ã«ç®¡ç†æŽ¥ç¶šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+
+PREFIX D_SM_MAC
+CAPTION MAC アドレステーブル
+S_TITLE 仮想 HUB "%S" 上㮠MAC アドレステーブルデータベースã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+B_DELETE é¸æŠžã—ãŸã‚¨ãƒ³ãƒˆãƒªã‚’削除(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_IP
+CAPTION IP アドレステーブル
+S_TITLE 仮想 HUB "%S" 上㮠IP アドレステーブルデータベースã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+B_DELETE é¸æŠžã—ãŸã‚¨ãƒ³ãƒˆãƒªã‚’削除(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_CREATE_CERT
+CAPTION æ–°ã—ã„証明書ã®ä½œæˆ
+STATIC1 ã“ã®ãƒ„ールを使用ã™ã‚‹ã¨ã€ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã€ã¾ãŸã¯æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã‚’ç°¡å˜ã«ä½œæˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 証明書ã®ç¨®é¡ž(&T):
+R_ROOT_CERT ルート証明書 (自己署å証明書)(&R)
+R_SIGNED_CERT ä»–ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã•ã‚ŒãŸè¨¼æ˜Žæ›¸(&S)
+S_LOAD_1 ç½²åã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã™ã‚‹è¨¼æ˜Žæ›¸ã¨ç§˜å¯†éµ(&C):
+B_LOAD 証明書ã¨ç§˜å¯†éµã®èª­ã¿è¾¼ã¿(&L)
+S_LOAD_2 [証明書ã¨ç§˜å¯†éµã®èª­ã¿è¾¼ã¿] をクリックã—ã¦ã€æ–°ã—ã„証明書ã®ç½²åã«ä½¿ã† X509 証明書㨠RSA 秘密éµã‚’指定ã—ã¦ãã ã•ã„。
+S_LOAD_3 åå‰ (CN):
+S_LOAD_4 所属機関 (O):
+S_LOAD_5 組織å˜ä½ (OU):
+S_LOAD_6 国 (C):
+S_LOAD_7 都é“府県 (ST):
+S_LOAD_8 ローカル (L):
+S_LOAD_11 シリアル番å·(S):\r\n(16進数)
+S_LOAD_9 証明書ã®æœ‰åŠ¹æœŸé–“(&E):
+S_LOAD_10 æ—¥
+STATIC3 大è¦æ¨¡ã«è¨¼æ˜Žæ›¸ãŠã‚ˆã³è¨¼æ˜Žæ©Ÿé–¢ã‚’é‹ç”¨ã™ã‚‹å ´åˆã¯ã€OpenSSL ãªã©ã®ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã‚„ã€å¸‚販㮠CA (証明機関) ソフトウェアを使用ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+S_LOAD_12 æš—å·å¼·åº¦(&N):
+
+
+PREFIX D_NM_LOGIN
+CAPTION deleted
+S_TITLE deleted
+STATIC1 deleted
+STATIC2 deleted
+IDOK deleted
+IDCANCEL deleted
+
+
+PREFIX D_SPEEDMETER
+CAPTION ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ‡ãƒã‚¤ã‚¹ã®çŠ¶æ…‹
+STATIC1 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ€ãƒ—ã‚¿ã®é¸æŠž:
+STATIC2 最新ã®çŠ¶æ³(&L)
+STATIC3 æ›´æ–°(&R)
+
+
+PREFIX D_NM_MAIN
+CAPTION deleted
+STATIC1 deleted
+STATIC2 deleted
+B_SETTING VPN Server ã¸ã®æŽ¥ç¶šã®è¨­å®š(&S)
+B_CONNECT 接続(&C)
+B_DISCONNECT 切断(&D)
+STATIC3 User-mode Router ã®å‹•ä½œã«é–¢ã™ã‚‹è¨­å®š
+STATIC4 SoftEther VPN User-mode Router ã®ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®å‹•ä½œã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_OPTION User-mode Router ã®å‹•ä½œè¨­å®š(&O)
+STATIC5 User-mode Router ã®å‹•ä½œçŠ¶æ³
+STATIC6 SoftEther VPN User-mode Router ã®ç¾åœ¨ã®å‹•ä½œçŠ¶æ³ã‚’表示ã—ã¾ã™ã€‚
+B_NAT 仮想 NAT ã®çŠ¶æ³(&N)
+B_DHCP 仮想 DHCP サーãƒãƒ¼ã®çŠ¶æ³(&H)
+B_STATUS User-mode Router ã®çŠ¶æ³(&R)
+B_INFO User-mode Router ã®æƒ…å ±(&I)
+B_PASSWORD 管ç†ãƒ‘スワードã®è¨­å®š(&P)
+B_REFRESH 最新状態ã«æ›´æ–°(&E)
+B_ABOUT ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_NM_OPTION
+CAPTION SecureNAT ã®è¨­å®š
+S_TITLE SecureNAT 仮想ホストãŒä»®æƒ³ HUB "%S" ã®ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã§ã©ã®ã‚ˆã†ãªå‹•ä½œã‚’è¡Œã†ã‹ã‚’設定ã—ã¦ãã ã•ã„。
+STATIC1 仮想ホストã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®è¨­å®š:
+STATIC2 MAC アドレス(&M):
+STATIC3 IP アドレス(&P):
+STATIC4 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯(&S):
+STATIC5 仮想 NAT ã®è¨­å®š:
+R_USE_NAT 仮想 NAT 機能を使用ã™ã‚‹(&A)
+STATIC6 M&TU 値:
+STATIC7 ãƒã‚¤ãƒˆ
+STATIC8 TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ(&C):
+STATIC9 秒
+STATIC10 UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ(&U):
+STATIC11 秒
+R_SAVE_LOG NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼ã®å‹•ä½œã‚’ログファイルã«ä¿å­˜ã™ã‚‹(&L)
+STATIC12 仮想 DHCP サーãƒãƒ¼ã®è¨­å®š:
+R_USE_DHCP 仮想 DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’使用ã™ã‚‹(&N)
+STATIC13 é…布 IP アドレス帯(&D):
+STATIC14 ã‹ã‚‰
+STATIC15 ã¾ã§
+STATIC16 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯(&B):
+STATIC17 リース期é™(&E):
+STATIC18 秒
+STATIC19 クライアントã«å‰²ã‚Šå½“ã¦ã‚‹ã‚ªãƒ—ションã®è¨­å®š (空欄ã§ã‚‚å¯):
+STATIC20 デフォルトゲートウェイã®\r\nアドレス(&F):
+STATIC21 DNS サーãƒãƒ¼ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ 1 (&V):
+STATIC22 ドメインå(&W):
+STATIC23 DNS サーãƒãƒ¼ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ 2 (&X):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_NM_NAT
+CAPTION 仮想 NAT ルータ上㮠NAT セッションテーブル
+S_TITLE ç¾åœ¨ã€SecureNAT ã®ä»®æƒ³ NAT ルータ上ã«ä»¥ä¸‹ã® TCP ã¾ãŸã¯ UDP ã® NAT テーブルエントリãŒã‚ã‚Šã¾ã™ã€‚
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_NM_DHCP
+CAPTION 仮想 DHCP サーãƒãƒ¼ä¸Šã® IP リーステーブル
+S_TITLE ç¾åœ¨ã€SecureNAT ã®ä»®æƒ³ DHCP サーãƒãƒ¼ã¯ä»¥ä¸‹ã® IP アドレスをクライアントã«é…布ã—ã¦ã„ã¾ã™ã€‚
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&H)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_NM_CHANGE_PASSWORD
+CAPTION %S ã®ç®¡ç†è€…パスワードã®å¤‰æ›´
+S_TITLE SoftEther VPN User-mode Router (%S) ã®ç®¡ç†è€…パスワードを変更ã§ãã¾ã™ã€‚æ–°ã—ã„パスワードを入力ã—ã¦ã‹ã‚‰ [OK] をクリックã—ã¦ãã ã•ã„。
+STATIC1 æ–°ã—ã„パスワード(&P):
+STATIC2 確èªå…¥åŠ›(&C):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_SNAT
+CAPTION 仮想 NAT ãŠã‚ˆã³ä»®æƒ³ DHCP 機能 (SecureNAT) ã®è¨­å®š
+S_TITLE SecureNAT 機能を有効ã«ã™ã‚‹ã¨ã€ä»®æƒ³ HUB "%S" 内ã®ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã«ãŠã„㦠NAT ルータ (IP マスカレード) ã‚„ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’仮想的ã«å‹•ä½œã•ã›ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+STATIC1 SecureNAT 機能ã«é–¢ã™ã‚‹è­¦å‘Š
+S_WARNING SecureNAT 機能ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã—ã¦è©³ã—ã„知識ã®ã‚ã‚‹æ–¹å‘ã‘ã®æ©Ÿèƒ½ã§ã™ã€‚
+S_WARNING2 SecureNAT 機能を正ã—ã使用ã™ã‚‹ã¨ã€VPN を経由ã—ãŸå®‰å…¨ãªãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ãŒå®Ÿç¾ã§ãã¾ã™ã€‚ã—ã‹ã—ã€èª¤ã£ãŸæ–¹æ³•ã§ä½¿ç”¨ã™ã‚‹ã¨ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…¨ä½“ã‚’å±é™ºãªçŠ¶æ…‹ã«ã™ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã§ãªã„å ´åˆã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®è¨±å¯ã‚’å¾—ã¦ã„ãªã„å ´åˆã¯ã€SecureNAT 機能を有効ã«ã—ãªã„ã§ãã ã•ã„。SecureNAT 機能ã«é–¢ã™ã‚‹è©³ã—ã„説明ã¯ã€VPN Server ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚„オンラインドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。
+STATIC2 SecureNAT 機能ã®æœ‰åŠ¹ / 無効ãŠã‚ˆã³è¨­å®šã®å¤‰æ›´
+STATIC3 ã“ã®ä»®æƒ³ HUB 内㧠SecureNAT 機能を有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ãŸã‚Šã€è¨­å®šã‚’変更ã§ãã¾ã™ã€‚
+B_ENABLE SecureNAT 機能を有効ã«ã™ã‚‹(&E)
+B_DISABLE SecureNAT 機能を無効ã«ã™ã‚‹(&D)
+B_CONFIG SecureNAT ã®è¨­å®š(&C)
+STATIC4 ※ 動作中㮠SecureNAT を無効ã«ã—ãŸå ´åˆã€ç¾åœ¨ SecureNAT を経由ã—ã¦æŽ¥ç¶šä¸­ã® TCP ã¾ãŸã¯ UDP セッションã¯ã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚
+STATIC5 ç¾åœ¨ã® SecureNAT ã®çŠ¶æ³ã®è¡¨ç¤º
+STATIC6 ç¾åœ¨ã® SecureNAT ã®å‹•ä½œçŠ¶æ³ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_NAT 仮想 NAT ルータã®çŠ¶æ³(&N)
+B_DHCP 仮想 DHCP サーãƒãƒ¼ã®çŠ¶æ³(&H)
+B_STATUS SecureNAT ã®å‹•ä½œçŠ¶æ³ã®è¡¨ç¤º(&S)
+S_TSUKUBA2 SecureNAT ã¯ã€ç™» å¤§éŠ ãŒç­‘波大学第三学群情報学類ã®å¹³æˆ16年度授業 "情報特別演習Ⅰ" ã§é–‹ç™ºã—ãŸæŠ€è¡“を使用ã—ã¦ã„ã¾ã™ã€‚
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_BRIDGE
+CAPTION ローカルブリッジ設定
+STATIC1 ローカルブリッジを使用ã™ã‚‹ã¨ã€ã“ã® VPN Server 上ã§å‹•ä½œã™ã‚‹ä»®æƒ³ HUB ã¨ç‰©ç†çš„㪠Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã¨ã®é–“ã§ãƒ¬ã‚¤ãƒ¤ 2 ブリッジ接続を構æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nã¾ãŸã€ã‚·ã‚¹ãƒ†ãƒ ã« tap デãƒã‚¤ã‚¹ (仮想ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹) を作æˆã—ã€ä»®æƒ³ HUB ã¨ã®é–“ã§ãƒ–リッジ接続ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚(Linux 版ã®ã¿ã‚µãƒãƒ¼ãƒˆ)
+B_DELETE ローカルブリッジã®å‰Šé™¤(&D)
+STATIC2 æ–°ã—ã„ローカルブリッジã®å®šç¾©(&N):
+STATIC3 ブリッジã™ã‚‹ä»®æƒ³ HUB ã‚’é¸æŠžã™ã‚‹ã‹ã€åå‰ã‚’入力ã—ã¦ãã ã•ã„。
+STATIC4 仮想 HUB(&H):
+STATIC5 作æˆã™ã‚‹ç¨®é¡ž(&Y):
+R_BRIDGE 物ç†çš„ãªæ—¢å­˜ã® LAN カードã¨ã®ãƒ–リッジ接続(&P)
+R_TAP æ–°ã—ã„ tap デãƒã‚¤ã‚¹ã¨ã®ãƒ–リッジ接続(&T)
+S_ETH_1 LAN カード(&L):
+S_TAP_1 æ–°ã—ã„ tap デãƒã‚¤ã‚¹å(&V):
+S_TAP_2 (11 文字以内)
+STATIC6 ※ 稼åƒä¸­ã®ä»»æ„ã® LAN カードã¨ã®é–“ã§ãƒ–リッジã§ãã¾ã™ãŒã€é«˜è² è·ç’°å¢ƒã«ãŠã„ã¦ã¯ãƒ–リッジ専用㫠LAN カードを用æ„ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+IDOK ローカルブリッジを追加(&A)
+STATIC7 最近システムã«è¿½åŠ ã•ã‚ŒãŸ LAN カードãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã—ã¦å†åº¦ã“ã®ç”»é¢ã‚’é–‹ã‘ã‚Œã°è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+IDCANCEL é–‰ã˜ã‚‹(&X)
+B_VLAN ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ール(&G)
+
+
+PREFIX D_WIN9X_REBOOT
+CAPTION VPN Client - 仮想 LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«
+STATIC1 VPN Client ã®ä»®æƒ³ LAN カードã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã„ã¾ã—ãŸã€‚\r\nç›´ã¡ã« Windows を終了ã—ã€ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nコンピュータã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã•ã‚Œã¾ã™ã€‚自動的ã«å†èµ·å‹•ã—ãªã„å ´åˆã¯ã€æ‰‹å‹•ã§å†èµ·å‹•ã‚’è¡Œã£ã¦ãã ã•ã„。
+
+
+PREFIX D_EM_MAIN
+CAPTION SoftEther EtherLogger Manager
+STATIC1 SoftEther EtherLogger ã¯ã€ã‚³ãƒ³ãƒ”ュータã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ LAN カードをæµã‚Œã‚‹ãƒ‡ãƒ¼ã‚¿ã‚’キャプãƒãƒ£ã—ã€ç®¡ç†è€…ãŒæŒ‡å®šã—ãŸç¨®é¡žã®ãƒ‘ケットã®ãƒ˜ãƒƒãƒ€ã¾ãŸã¯ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’テキストファイルã«ãƒ­ã‚°ã¨ã—ã¦è¨˜éŒ²ã™ã‚‹ã‚µãƒ¼ãƒ“スã§ã™ã€‚\r\n\r\nç¾åœ¨ã€ä»¥ä¸‹ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ãƒ‡ãƒã‚¤ã‚¹ã§ãƒ‘ケットロギングを実行ã—ã¦ã„ã¾ã™ã€‚
+B_PASSWORD 管ç†ãƒ‘スワード(&P)
+B_LICENSE ライセンス(&L)
+B_ADD 追加(&A)
+IDOK 編集(&E)
+B_DELETE 削除(&D)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_EM_ADD
+STATIC1 キャプãƒãƒ£ã«ä½¿ç”¨ã™ã‚‹ LAN カードå(&L):
+R_PROMISCUS キャプãƒãƒ£ã®éš›ã«ãƒ—ロミスキャスモードを使用ã—ãªã„(&N)
+STATIC2 パケットログ(&P):
+S_PACKET ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸ(&W):
+S_PACKET_0 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãƒ­ã‚°:
+B_PACKET_0_0 ä¿å­˜ç„¡ã—
+B_PACKET_0_1 ヘッダ情報ã®ã¿
+B_PACKET_0_2 パケット内容ã™ã¹ã¦
+S_PACKET_1 TCP パケットログ:
+B_PACKET_1_0 ä¿å­˜ç„¡ã—
+B_PACKET_1_1 ヘッダ情報ã®ã¿
+B_PACKET_1_2 パケット内容ã™ã¹ã¦
+S_PACKET_2 DHCP パケットログ:
+B_PACKET_2_0 ä¿å­˜ç„¡ã—
+B_PACKET_2_1 ヘッダ情報ã®ã¿
+B_PACKET_2_2 パケット内容ã™ã¹ã¦
+S_PACKET_3 UDP パケットログ:
+B_PACKET_3_0 ä¿å­˜ç„¡ã—
+B_PACKET_3_1 ヘッダ情報ã®ã¿
+B_PACKET_3_2 パケット内容ã™ã¹ã¦
+S_PACKET_4 ICMP パケットログ:
+B_PACKET_4_0 ä¿å­˜ç„¡ã—
+B_PACKET_4_1 ヘッダ情報ã®ã¿
+B_PACKET_4_2 パケット内容ã™ã¹ã¦
+S_PACKET_5 IP パケットログ:
+B_PACKET_5_0 ä¿å­˜ç„¡ã—
+B_PACKET_5_1 ヘッダ情報ã®ã¿
+B_PACKET_5_2 パケット内容ã™ã¹ã¦
+S_PACKET_6 ARP パケットログ:
+B_PACKET_6_0 ä¿å­˜ç„¡ã—
+B_PACKET_6_1 ヘッダ情報ã®ã¿
+B_PACKET_6_2 パケット内容ã™ã¹ã¦
+S_PACKET_7 Ethernet\r\nパケットログ:
+B_PACKET_7_0 ä¿å­˜ç„¡ã—
+B_PACKET_7_1 ヘッダ情報ã®ã¿
+B_PACKET_7_2 パケット内容ã™ã¹ã¦
+IDOK &OK
+IDCANCEL キャンセル
+STATIC3 大é‡ã®ãƒ‘ケットログをä¿å­˜ã—よã†ã¨ã™ã‚‹ã¨ã€CPU ãŠã‚ˆã³ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ã«å¤§ããªè² æ‹…ãŒã‹ã‹ã‚Šã€ã‚·ã‚¹ãƒ†ãƒ å…¨ä½“ã®ãƒ‘フォーマンス低下ã®åŽŸå› ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚å¿…è¦ãªãƒ‘ケットログ情報ã®ã¿ä¿å­˜ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¦ãã ã•ã„。
+
+
+PREFIX D_EM_PASSWORD
+CAPTION 管ç†è€…パスワードã®å¤‰æ›´
+S_TITLE 管ç†è€…パスワードを変更ã§ãã¾ã™ã€‚æ–°ã—ã„パスワードを入力ã—ã¦ã‹ã‚‰ [OK] をクリックã—ã¦ãã ã•ã„。
+STATIC1 æ–°ã—ã„パスワード(&P):
+STATIC2 確èªå…¥åŠ›(&C):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_EM_LICENSE
+CAPTION ライセンスã®è¿½åŠ ã¨å‰Šé™¤
+STATIC1 SoftEther EtherLogger を使用ã™ã‚‹ã«ã¯ã€æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’å–å¾—ã—ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’登録ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ç”»é¢ã§ã¯ã€æ–°ã—ã„ライセンスキーを登録ã—ãŸã‚Šã€ç™»éŒ²æ¸ˆã¿ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’削除ã—ãŸã‚Šã€ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ä¸€è¦§ã‚„ SoftEther EtherLogger ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰ã‚’表示ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_BOLD ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンスã®ä¸€è¦§(&L):
+B_OBTAIN ライセンスã®å…¥æ‰‹ãƒ»æ›´æ–°(&O)
+STATIC2 [ライセンスã®å…¥æ‰‹ãƒ»æ›´æ–°] をクリックã™ã‚‹ã¨ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®å…¥æ‰‹ãƒ»æ›´æ–°æ–¹æ³•ã«é–¢ã™ã‚‹èª¬æ˜ŽãŒè¨˜è¼‰ã•ã‚ŒãŸ Web サイトを表示ã—ã¾ã™ã€‚
+B_ADD æ–°ã—ã„ライセンスキーã®ç™»éŒ²(&A)
+B_DEL 削除(&D)
+IDOK ライセンスã«é–¢ã™ã‚‹æƒ…å ±(&I)
+STATIC3 ライセンスをé¸æŠžã—ã€[ライセンスã«é–¢ã™ã‚‹æƒ…å ±] をクリックã™ã‚‹ã¨ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã® Web サイト (softether.com) ã«æŽ¥ç¶šã—ã€ãã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã«é–¢ã™ã‚‹ç™»éŒ²æƒ…報を表示ã—ã¾ã™ã€‚
+S_BOLD2 ç¾åœ¨ã® SoftEther EtherLogger ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰(&M):
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_EM_LICENSE_ADD
+CAPTION æ–°ã—ã„ライセンスキーã®ç™»éŒ²
+S_INFO SoftEther EtherLogger ã®è£½å“ライセンスã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 ライセンスキーã¯ã€36 æ¡ã®è‹±æ•°å­—ãŠã‚ˆã³ãƒã‚¤ãƒ•ãƒ³ ( '-' ) ã§æ§‹æˆã•ã‚Œã¦ã„ã‚‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ‰€æœ‰ã‚’証明ã™ã‚‹ã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰ã§ã™ã€‚\r\n\r\nライセンスキーã¯ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¨å…±ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã‚’å—ã‘å–ã£ãŸå ´åˆã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã«å°åˆ·ã•ã‚Œã¦ã„ã¾ã™ã€‚本ソフトウェアã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’オンラインã§è³¼å…¥ã—ãŸå ´åˆã¯ã€è³¼å…¥æ™‚ã® Web サイトã®ç”»é¢ã‚„メールãªã©ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ãã®ä»–ã®æ–¹æ³•ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ä¸æ˜Žãªå ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®è³¼å…¥å…ƒã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+STATIC2 ライセンスキーを正確ã«å…¥åŠ›ã—ã¦ãã ã•ã„(&I):
+STATIC3 ライセンスキー㯠6 æ¡ã”ã¨ã«åŒºåˆ‡ã£ã¦å…¥åŠ›ã—ã¦ãã ã•ã„。ãƒã‚¤ãƒ•ãƒ³ã¯å…¥åŠ›ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。コピー && ペーストã§å…¥åŠ›ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚
+B_INFO2 本ソフトウェアã®è‘—作権ã¯å…¨ä¸–ç•Œã§ä¿è­·ã•ã‚Œã¦ã„ã¾ã™ã€‚ãŠå®¢æ§˜ã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹å¥‘約書ã®æ¡ä»¶ã«å¾“ã£ãŸå ´åˆã®ã¿ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’複製・使用ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ä¸æ­£ã«å…¥æ‰‹ã—ãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ä½¿ç”¨ã€è¤‡æ•°å°ã®ã‚µãƒ¼ãƒãƒ¼ã§ã®åŒä¸€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ä½¿ç”¨ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ç„¡æ–­é ’布ãªã©ã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹å¥‘約書ã«é•åã—ã€æ°‘事ã¾ãŸã¯åˆ‘事上ã®ç½°ã‚’å—ã‘ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã€ã”注æ„ãã ã•ã„。
+IDOK 登録(&R)
+IDCANCEL キャンセル
+
+PREFIX D_EM_REMOTE
+STATIC1 接続ã™ã‚‹ã‚³ãƒ³ãƒ”ュータã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスを指定ã—ã¦ãã ã•ã„(&S):
+R_LOCAL ローカルコンピュータ (ã“ã®ç”»é¢ã‚’表示ã—ã¦ã„るコンピュータ) ã«æŽ¥ç¶š(&L)
+S_HOSTNAME コンピュータå(&C):
+IDOK &OK
+IDCANCEL キャンセル
+B_ABOUT ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+
+PREFIX D_SM_CONFIG
+CAPTION Config ファイルã®ç·¨é›†
+IDC_INFO VPN Server "%S" ã®ç¾åœ¨ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã¯ä¸‹è¨˜ã®ã¨ãŠã‚Šã§ã™ã€‚\r\nã“ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容を編集ã—ã¦ã€VPN Server ã«æ›¸ã込むã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+B_EXPORT ファイルã«ä¿å­˜(&S)
+B_IMPORT ファイルã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¦æ›¸ãè¾¼ã¿(&I)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+STATIC1 コンフィグレーションファイルã¯é€šå¸¸ã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ç­‰ã§ç·¨é›†å¯èƒ½ã§ã™ã€‚編集ã—ãŸã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ VPN Server ã«æ›¸ã込んã å ´åˆã€VPN Server ã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã€æ–°ã—ã„コンフィグレーションファイルã«å¾“ã£ã¦èµ·å‹•ã—ã¾ã™ã€‚ä¸æ­£ãªã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’書ã込んã å ´åˆã¯ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã‚Šç¾åœ¨ã®è¨­å®šå†…容ãŒå¤±ã‚ã‚ŒãŸã‚Šã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã€å分注æ„ã—ã¦ãã ã•ã„。
+B_FACTORY 設定をリセットã—ã¦åˆæœŸåŒ–(&R)
+
+
+PREFIX D_SM_ADMIN_OPTION
+CAPTION 仮想 HUB 管ç†ã‚ªãƒ—ション
+S_INFO ç¾åœ¨ã€ä»®æƒ³ HUB "%S" ã«ã¯ä»¥ä¸‹ã®ç®¡ç†ã‚ªãƒ—ションãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
+B_ADD 値ã®è¿½åŠ (&A)
+B_EDIT 値ã®ç·¨é›†(&E)
+B_DELETE 値ã®å‰Šé™¤(&D)
+STATIC1 仮想 HUB 管ç†ã‚ªãƒ—ションã¯ã€VPN Server ã®ç®¡ç†è€…ãŒå„仮想 HUB ã®ç®¡ç†è€…ã«ä»®æƒ³ HUB ã®ç®¡ç†ã‚’委任ã—ã¦ã„ã‚‹å ´åˆã«ã€è¨­å®šç¯„囲を制é™ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚
+IDOK ä¿å­˜(&S)
+IDCANCEL キャンセル
+STATIC2 仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã¯ã€ã“ã® VPN Server 全体ã®ç®¡ç†æ¨©é™ã‚’æŒã£ãŸç®¡ç†è€…ã®ã¿ã§ã™ã€‚仮想 HUB ã®ç®¡ç†è€…ã¯ã€ç®¡ç†ã‚ªãƒ—ションを表示ã§ãã¾ã™ãŒã€å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。\r\nãŸã ã—ã€allow_hub_admin_change_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã§ã‚‚管ç†ã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_BOLD 説明:
+
+
+PREFIX D_SM_MSG
+CAPTION メッセージã®è¨­å®š
+S_MSG_2 仮想 HUB "%S" ã« VPN Client ãŒæŽ¥ç¶šã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç”»é¢ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã§ãã¾ã™ã€‚メッセージを表示ã™ã‚‹å ´åˆã¯ã€ä»¥ä¸‹ã«è¡¨ç¤ºã—ãŸã„メッセージã®å†…容を入力ã—ã¦ãã ã•ã„。
+C_USEMSG メッセージを表示ã™ã‚‹(&M)
+STATIC1 メッセージã®è¡¨ç¤ºæ©Ÿèƒ½ã«ã¤ã„ã¦
+S_INFO 接続元ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä½¿ç”¨ã—ã¦ã„ã‚‹ VPN Client ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒ 3.0 以é™ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nメッセージã«ã€Œhttp://ã€ã§å§‹ã¾ã‚‹ URL ã‚’ 1 è¡Œã ã‘記載ã™ã‚‹ã¨ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ä»£ã‚ã‚Šã«ãã® URL をデフォルト㮠Web ブラウザを起動ã—ã¦è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_NICINFO
+CAPTION 仮想 LAN カード "%S" ã®çŠ¶æ…‹
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_VLAN
+CAPTION ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ール
+STATIC1 LAN カードã®ç¨®é¡žã«ã‚ˆã£ã¦ã¯ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚¿ã‚° VLAN パケット (IEEE802.1Q) ã‚’é€éŽã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n仮想 HUB 㨠LAN カードをローカルブリッジ接続ã™ã‚‹å ´åˆã§ã€ç‰©ç†çš„ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‹ã‚‰ã‚¿ã‚° VLAN パケットを仮想 HUB ã«å…¥åŠ›ã—ãŸã‚Šã€ä»®æƒ³ HUB ã‹ã‚‰ã‚¿ã‚° VLAN パケットを物ç†çš„ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«å‡ºåŠ›ã—ãŸã‚Šã—ãŸã„å ´åˆã¯ã€LAN カード㫠VLAN パケットをé€éŽã™ã‚‹ãŸã‚ã®è¨­å®šã‚’è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+B_ENABLE é¸æŠžã—㟠LAN カードをタグ VLAN ãŒé€éŽå¯èƒ½ã«è¨­å®šã™ã‚‹(&C)
+B_DISABLE 設定を解除ã™ã‚‹(&U)
+STATIC2 ã‚¿ã‚° VLAN パケットé€éŽè¨­å®šãƒ„ールã«ã¤ã„ã¦
+S_WARNING ã“ã®ãƒ„ールを用ã„ã‚‹ã¨ã€Intelã€Broadcom ãŠã‚ˆã³ Marvell 製ã®æ­£è¦ãƒ‰ãƒ©ã‚¤ãƒã‚’用ã„ã¦ã„る一部㮠Windows 用 LAN カードã®ã‚¿ã‚° VLAN ã®é€éŽè¨­å®šã‚’è¡Œã£ãŸã‚Šã€è¨­å®šã‚’解除ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_WARNING2 上記ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¦ã„ã‚‹ LAN カードã¯ã€ã“ã®ãƒ„ールã«ã‚ˆã£ã¦è¨­å®šã‚’変更ã™ã‚‹ã“ã¨ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚リストã«è¡¨ç¤ºã•ã‚Œã¦ã„ãªã„ LAN カードã¯ã“ã®ãƒ„ールã«ã‚ˆã£ã¦è¨­å®šã‚’ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。リストã«ãªã„ LAN カードã§ã‚‚ã€ã‚¿ã‚° VLAN ãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§é€éŽå¯èƒ½ã‹ã€ã¾ãŸã¯ä½•ã‚‰ã‹ã®è¨­å®šã‚’è¡Œã†ã“ã¨ã«ã‚ˆã‚Šé€éŽå¯èƒ½ã«ãªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nãã®å ´åˆã¯ã€ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ãŒè‡ªã‚‰ Windows ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã€ãã®ã‚ˆã†ãªè¨­å®šã‚’è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_SIMULATION
+CAPTION é…延・パケットロス生æˆæ©Ÿèƒ½
+STATIC1 ã“ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã®æ¡ä»¶ã«ä¸€è‡´ã™ã‚‹ãƒ‘ケットãŒä»®æƒ³ HUB を通éŽã™ã‚‹å ´åˆã«ã€ãã®ãƒ‘ケットã«é…延・ジッタãŠã‚ˆã³ãƒ‘ケットロスを発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nã“ã®æ©Ÿèƒ½ã«ã‚ˆã‚Šã€ä½Žé€Ÿã§å“質ã®ä½Žã„インターãƒãƒƒãƒˆå›žç·šã‚„ WAN 回線ã€ãƒ¯ã‚¤ãƒ¤ãƒ¬ã‚¹å›žç·šãªã©ã‚’利用ã—ãŸå ´åˆã®å‹•ä½œã‚’ã€LAN 内ã®æœºä¸Šã§å®Ÿé¨“ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã¨ãˆã°ã€IP 電話 (VoIP) ç­‰ã®å‹•ä½œè©¦é¨“ã«ä¾¿åˆ©ã§ã™ã€‚
+STATIC2 発生ã•ã›ã‚‹é…延・ジッタ・パケットロスã®å†…容:
+C_DELAY é…延を発生ã•ã›ã‚‹(&D)
+S_DELAY 発生ã•ã›ã‚‹é…延ã®é‡ (0 - 10000) :
+S_DELAY2 ミリ秒 (msecs)
+C_JITTER é…延ã«ã‚¸ãƒƒã‚¿ (æºã‚‰ãŽ) を発生ã•ã›ã‚‹(&J)
+S_JITTER 発生ã•ã›ã‚‹é…延ã®æºã‚‰ãŽ (0 - 100) :
+S_JITTER2 パーセント (%)
+C_LOSS パケットロスを発生ã•ã›ã‚‹(&L)
+S_LOSS 発生ã•ã›ã‚‹ãƒ‘ケットロス率 (0 - 100) :
+S_LOSS2 パーセント (%)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_AO_VALUE
+CAPTION åå‰ã¨å€¤
+STATIC1 åå‰(&N):
+STATIC2 値(&V):
+STATIC3 (整数値)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_L3
+CAPTION 仮想レイヤ 3 スイッãƒè¨­å®š
+STATIC1 ã“ã® VPN Server 内ã§å‹•ä½œã—ã¦ã„る複数ã®ä»®æƒ³ HUB é–“ã§ä»®æƒ³ã®ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’定義ã—ã€ç•°ãªã£ãŸ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯é–“をルーティングã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŠã‚ˆã³ IP ルーティングã«é–¢ã™ã‚‹è©³ã—ã„知識をãŠæŒã¡ã®æ–¹ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚通常㮠VPN 機能を使用ã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\r\n\r\n仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å ´åˆã¯ã€IP ルーティングã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã®ä¸Šã§ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ä¸Žãˆã‚‹å½±éŸ¿ã‚’å分考慮ã—ã¦ã‹ã‚‰è¨­å®šã—ã¦ãã ã•ã„。
+STATIC3 仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã«é–¢ã™ã‚‹ã”注æ„
+S_BOLD 定義ã•ã‚Œã¦ã„る仮想レイヤ 3 スイッãƒã®ä¸€è¦§(&L):
+B_ADD æ–°è¦ä½œæˆ(&N)
+B_START 動作開始(&S)
+B_STOP 動作åœæ­¢(&T)
+IDOK 編集(&E)
+B_DELETE 削除(&D)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_L3_ADD
+CAPTION æ–°è¦ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä½œæˆ
+STATIC1 æ–°ã—ã„仮想レイヤ 3 スイッãƒã‚’作æˆã—ã¾ã™ã€‚åå‰ã‚’入力ã—ã¦ãã ã•ã„。\r\n\r\n仮想レイヤ 3 スイッãƒã®åå‰ã¯ã€æ—¢ã«ã“ã® VPN Server ã«å­˜åœ¨ã™ã‚‹ä»–ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã¨é‡è¤‡ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+STATIC2 åå‰(&N):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_L3_SW
+CAPTION 仮想レイヤ 3 スイッム"%S" ã®ç·¨é›†
+STATIC1 1 ã¤ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ã¯ã€è¤‡æ•°å€‹ã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã¨ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 仮想インターフェイスã¯ä»®æƒ³ HUB ã«é–¢é€£ä»˜ã‘られã€ä»®æƒ³ HUB ãŒå‹•ä½œã—ã¦ã„ã‚‹ã¨ãã«ä»®æƒ³ HUB 内㧠1 å°ã® IP ホストã®ã‚ˆã†ã«å‹•ä½œã—ã¾ã™ã€‚複数ã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦ãã‚Œãžã‚Œåˆ¥ã€…ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æ‰€å±žã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒå®šç¾©ã•ã‚Œã¦ã„ã‚‹ã¨ãã€ãれらã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹é–“㧠IP ルーティングãŒè‡ªå‹•çš„ã«è¡Œã‚ã‚Œã¾ã™ã€‚\r\n\r\nã¾ãŸã€ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを手動ã§è¨­å®šã—ã¦ã€ã‚ˆã‚Šç´°ã‹ã„経路設定を行ã†ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚
+S_BOLD1 仮想インターフェイス一覧(&I):
+B_ADD_IF 仮想インターフェイスã®è¿½åŠ (&A)
+B_DEL_IF 仮想インターフェイスã®å‰Šé™¤(&E)
+S_BOLD2 ルーティングテーブル(&R):
+B_ADD_TABLE ルーティングテーブルエントリã®è¿½åŠ (&D)
+B_DEL_TABLE ルーティングテーブルエントリã®å‰Šé™¤(&L)
+B_START 動作開始(&S)
+B_STOP 動作åœæ­¢(&T)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_L3_SW_IF
+CAPTION 仮想インターフェイスã®è¿½åŠ 
+STATIC1 æ–°ã—ã„仮想インターフェイスを仮想レイヤ 3 スイッãƒã«è¿½åŠ ã—ã¾ã™ã€‚\r\n\r\n仮想インターフェイスãŒæ‰€å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç©ºé–“ã¨ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹è‡ªèº«ã® IP アドレスを定義ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\nã¾ãŸã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒæŽ¥ç¶šã™ã‚‹å…ˆã®ä»®æƒ³ HUB åã‚’é¸æŠžã™ã‚‹ã‹å…¥åŠ›ã—ã¦ãã ã•ã„。\r\n仮想 HUB åã¯ç¾åœ¨å­˜åœ¨ã—ã¦ã„ãªã„仮想 HUB を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+STATIC2 接続先仮想 HUB (&A)
+STATIC3 ã“ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒæŽ¥ç¶šã™ã‚‹ä»®æƒ³ HUB ã‚’é¸æŠžã™ã‚‹ã‹ã€åå‰ã‚’入力ã—ã¦ãã ã•ã„。
+STATIC4 仮想 HUB (&H):
+STATIC5 仮想インターフェイスã®æŒã¤ IP アドレスã¨æ‰€å±žã™ã‚‹ã‚µãƒ–ãƒãƒƒãƒˆç©ºé–“(&D)
+STATIC6 仮想インターフェイスã¯ã€ä»®æƒ³ HUB 内㧠1 ã¤ã® IP アドレスをæŒã¤å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€ãã® IP アドレスã®å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹å¿…è¦ã‚‚ã‚ã‚Šã¾ã™ã€‚\r\n\r\n複数ã®ä»®æƒ³ HUB 内㮠IP 空間åŒå£«ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’経由ã—ãŸãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã¯ã€ã“ã“ã§æŒ‡å®šã—㟠IP アドレスã«åŸºã¥ã„ã¦å‹•ä½œã—ã¾ã™ã€‚
+S_SRC_IP_1 &IP アドレス:
+S_SRC_IP_2 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯(&S):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_L3_SW_TABLE
+CAPTION ルーティングテーブルエントリã®è¿½åŠ 
+STATIC1 仮想レイヤ 3 スイッãƒã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルã«æ–°ã—ã„ルーティングテーブルエントリを追加ã—ã¾ã™ã€‚\r\n\r\n仮想レイヤ 3 スイッãƒã® IP ルーティングエンジンã¯ã€IP パケットã®å®›å…ˆ IP アドレスãŒå„仮想インターフェイスã®æ‰€å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã„ãšã‚Œã«ã‚‚所属ã—ãªã„å ´åˆã€ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルをå‚ç…§ã—ã¦ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚’è¡Œã„ã¾ã™ã€‚
+STATIC2 ルーティングテーブルエントリã®å†…容(&E):
+STATIC3 仮想インターフェイスã¯ã€ä»®æƒ³ HUB 内㧠1 ã¤ã® IP アドレスをæŒã¤å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€ãã® IP アドレスã®å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹å¿…è¦ã‚‚ã‚ã‚Šã¾ã™ã€‚\r\n\r\n複数ã®ä»®æƒ³ HUB 内㮠IP 空間åŒå£«ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’経由ã—ãŸãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã¯ã€ã“ã“ã§æŒ‡å®šã—㟠IP アドレスã«åŸºã¥ã„ã¦å‹•ä½œã—ã¾ã™ã€‚
+S_SRC_IP_1 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹(&N):
+S_SRC_IP_2 サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯(&S):
+S_SRC_IP_3 ゲートウェイアドレス(&G):
+S_SRC_IP_4 メトリック値(&M):
+STATIC4 ※ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã« 0.0.0.0 ã‚’ã€ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã« 0.0.0.0 を指定ã™ã‚‹ã¨ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ãƒˆã®æ„味ã«ãªã‚Šã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_SELECT_SECURE
+CAPTION スマートカードã®é¸æŠž
+STATIC1 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ç¨®é¡žã‚’é¸æŠžã—ã¦ãã ã•ã„。\r\n\r\nスマートカードã®ç¨®é¡žã®ä¸€è¦§ã«ã¯ã€ç¾åœ¨ã‚³ãƒ³ãƒ”ュータã«ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¦ã€ã‹ã¤ VPN ソフトウェアã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„るデãƒã‚¤ã‚¹ã®ä¸€è¦§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\r\nç¾åœ¨ä½¿ç”¨ã—ã¦ã„るスマートカードã®ç¨®é¡žãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€VPN ソフトウェアをより新ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šä½¿ç”¨ã§ãるよã†ã«ãªã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚\r\n\r\n※ 導入直後ã®ãƒ‰ãƒ©ã‚¤ãƒãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€Windows ã‚’å†èµ·å‹•ã—ã¦ã¿ã¦ãã ã•ã„。
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_SECURE_MANAGER
+CAPTION スマートカードマãƒãƒ¼ã‚¸ãƒ£
+S_INFO ç¾åœ¨é¸æŠžã•ã‚Œã¦ã„るスマートカード:\r\n\r\n%S
+B_BOLD スマートカードã«æ ¼ç´ã•ã‚Œã¦ã„るオブジェクト一覧:
+B_REFRESH オブジェクトリスト更新(&R)
+B_IMPORT カードã¸æ›¸ãè¾¼ã¿(&I)...
+B_EXPORT カードã‹ã‚‰èª­ã¿è¾¼ã¿(&E)...
+B_DELETE カードã‹ã‚‰å‰Šé™¤(&D)
+B_NEW_CERT æ–°ã—ã„証明書ã¨ç§˜å¯†éµã‚’作æˆã—ã¦ã‚«ãƒ¼ãƒ‰ã«æ›¸ã込む(&N)...
+B_PIN PIN コードã®å¤‰æ›´(&C)...
+IDCANCEL é–‰ã˜ã‚‹
+
+
+PREFIX D_CM_SECURE_TYPE
+CAPTION オブジェクトã®ç¨®é¡žã®é¸æŠž
+STATIC インãƒãƒ¼ãƒˆã—ãŸã„オブジェクトã®ç¨®é¡žã‚’é¸æŠžã—ã¦ãã ã•ã„。
+R_CERT 証明書(&C)
+R_KEY 秘密éµ(&K)
+R_DATA ä»»æ„ã®ãƒ‡ãƒ¼ã‚¿(&D)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_STRING
+CAPTION VPN ソフトウェア
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_SELECT_KEYPAIR
+CAPTION スマートカード内ã®è¨¼æ˜Žæ›¸ã®æŒ‡å®š
+S_INFO ç¾åœ¨é¸æŠžã•ã‚Œã¦ã„るスマートカード:\r\n\r\n%S
+B_BOLD1 スマートカード内ã®è¨¼æ˜Žæ›¸ã‚’é¸æŠžã—ã¦ãã ã•ã„:
+IDOK &OK
+IDCANCEL キャンセル
+B_BOLD2 対応ã—ãŸç§˜å¯†éµã‚’é¸æŠžã—ã¦ãã ã•ã„:
+
+
+PREFIX D_CM_LOAD_X
+CAPTION 証明書ã®èª­ã¿è¾¼ã¿
+STATIC1 ã©ã¡ã‚‰ã®æ–¹æ³•ã§è¨¼æ˜Žæ›¸ã‚’読ã¿è¾¼ã¿ã¾ã™ã‹?
+R_FROM_FILE ファイルã‹ã‚‰è¨¼æ˜Žæ›¸ã‚’読ã¿è¾¼ã‚€(&F)
+R_FROM_SECURE スマートカードã‹ã‚‰è¨¼æ˜Žæ›¸ã‚’読ã¿è¾¼ã‚€(&R)
+S_FILE 証明書データãŒä¿å­˜ã•ã‚Œã¦ã„るファイル (æ‹¡å¼µå­ãŒ .cer, .crt, .p12, .pfx ã®ã„ãšã‚Œã‹) ã‹ã‚‰è¨¼æ˜Žæ›¸ã‚’読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_CERT ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãŒæŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰å†…ã®è¨¼æ˜Žæ›¸ã‚’読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_SELECT 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®é¸æŠž(&S)...
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_CM_SECURE_PIN
+CAPTION PIN コードã®å¤‰æ›´
+STATIC1 スマートカード㮠PIN コード (暗証番å·) を変更ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nPIN コードを変更ã™ã‚‹ã«ã¯ã€ç¾åœ¨ã® PIN コードã¨ã€æ–°ã—ã„ PIN コードを 2 回入力ã—ã¦ãã ã•ã„。設定ã—㟠PIN コードã¯å¿˜ã‚Œãªã„よã†ã«ã—ã¦ãã ã•ã„。
+STATIC2 ç¾åœ¨ã® PIN コード(&C):
+STATIC3 æ–°ã—ã„ PIN コード(&N):
+STATIC4 確èªå…¥åŠ›(&E):
+STATIC5 ã”注æ„
+STATIC6 ç¾åœ¨ã® PIN コードを一定回数間é•ãˆã‚‹ã¨ã€ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãŒä½¿ç”¨ã§ããªããªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+STATIC7 スマートカードを挿入ã—㦠[OK] をクリックã—ã¦ãã ã•ã„。
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_CRL
+CAPTION 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§
+STATIC1 ã“ã®ä»®æƒ³ HUB 内ã§ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã‚’管ç†ã—ã¾ã™ã€‚\r\n\r\n無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«è¨¼æ˜Žæ›¸ã‚’登録ã™ã‚‹ã¨ã€ãã®è¨¼æ˜Žæ›¸ã‚’æ示ã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚
+B_ADD 追加(&A)
+IDOK 編集(&E)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+B_DELETE 削除(&D)
+
+
+PREFIX D_SM_EDIT_CRL
+CAPTION 無効ãªè¨¼æ˜Žæ›¸
+STATIC1 無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«ç™»éŒ²ã™ã‚‹å†…容を設定ã—ã¾ã™ã€‚\r\n\r\n仮想 HUB ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ããŸã¨ãã€ãã®è¨¼æ˜Žæ›¸ãŒç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 1 ã¤ä»¥ä¸Šã®å†…容ã«ä¸€è‡´ã™ã‚‹å ´åˆã«ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æŽ¥ç¶šã‚’æ‹’å¦ã—ã¾ã™ã€‚
+S_BOLD 下記ã®å®šç¾©ã•ã‚ŒãŸé …ç›®ã™ã¹ã¦ã®å†…容ã«ä¸€è‡´ã™ã‚‹è¨¼æ˜Žæ›¸ã‚’無効ã¨ã—ã¾ã™ã€‚
+STATIC2 証明書ã®å†…容
+R_CN åå‰ (CN):
+R_O 所属機関 (O):
+R_OU 組織å˜ä½ (OU):
+R_C 国 (C):
+R_ST 都é“府県 (ST):
+R_L ローカル (L):
+STATIC3 証明書ã®å±žæ€§å€¤:
+R_SERI ã‚·ãƒªã‚¢ãƒ«ç•ªå· (16進数):
+R_MD5_HASH MD5 ダイジェスト値 (16進数, 128 bit):
+R_SHA1_HASH SHA-1 ダイジェスト値 (16進数, 160 bit):
+STATIC4 ダイジェスト値 (ãƒãƒƒã‚·ãƒ¥å€¤) ã®æŒ‡å®šã¯ã€è¨¼æ˜Žæ›¸ã‚’事実上一æ„ã«æŒ‡å®šã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚通常ã€MD5 ã¾ãŸã¯ SHA-1 ã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ã‚’入力ã™ã‚‹å ´åˆã¯ã€ãã®ä»–ã®é …目を入力ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。
+STATIC5 既存ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‹ã‚‰ã®æŒ‡å®š
+STATIC6 無効ã«ã—ãŸã„証明書ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚‹å ´åˆã¯ã€ãã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šè¨¼æ˜Žæ›¸ã‚’正確ã«æŒ‡å®šã—ã¦ç„¡åŠ¹ãƒªã‚¹ãƒˆã«è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚[証明書ã®èª­ã¿è¾¼ã¿] をクリックã—ã¦æŒ‡å®šã—ãŸè¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容ãŒè‡ªå‹•çš„ã«å…¥åŠ›ã•ã‚Œã¾ã™ã€‚
+B_LOAD 証明書ã®èª­ã¿è¾¼ã¿(&L)...
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_AC_LIST
+CAPTION 接続元 IP 制é™ãƒªã‚¹ãƒˆ
+S_TITLE クライアントコンピュータ㮠IP アドレスã«ã‚ˆã£ã¦ã€ã“ã® VPN Server ã®ä»®æƒ³ HUB "%S" ã¸ã® VPN 接続を許å¯ã¾ãŸã¯æ‹’å¦ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚下記ã«æŽ¥ç¶šã‚’許å¯ã¾ãŸã¯æ‹’å¦ã™ã‚‹ãƒ«ãƒ¼ãƒ«ã‚’設定ã§ãã¾ã™ã€‚
+B_ADD ルールã®è¿½åŠ (&A)
+IDOK ルールã®ç·¨é›†(&E)
+B_DELETE ルールã®å‰Šé™¤(&D)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL キャンセル(&C)
+STATIC1 優先順ä½ã¯ãƒªã‚¹ãƒˆã®ä¸Šã®ã‚‚ã®ã»ã©é«˜ããªã‚Šã¾ã™ã€‚
+STATIC2 クライアント㮠IP アドレスãŒãƒªã‚¹ãƒˆå†…ã®ã©ã®é …ç›®ã«ã‚‚一致ã—ãªã‹ã£ãŸå ´åˆã¯ã€ã“ã®ä»®æƒ³ HUB ã¸ã® VPN 接続を許å¯ã•ã‚Œã¾ã™ã€‚
+
+
+PREFIX D_SM_AC
+CAPTION 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«é …ç›®ã®ç·¨é›†
+STATIC1 IP アクセス制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«é …目を設定ã—ã¦ãã ã•ã„。ã“ã“ã§è¨­å®šã—ãŸé …ç›®ã¯ã€VPN Client ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ãã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’許å¯ã™ã‚‹ã‹æ‹’å¦ã™ã‚‹ã‹ã‚’決定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+STATIC2 ルール項目ã®å†…容
+STATIC3 クライアント㮠IP アドレスãŒä»¥ä¸‹ã®ã¨ãã«ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹:
+R_SINGLE å˜ä¸€ã® IP アドレス(&S)
+R_MASKED 複数㮠IP アドレス (IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã§æŒ‡å®š) (&M) :
+STATIC4 アドレス(&A):
+S_MASK ãƒãƒƒãƒˆãƒžã‚¹ã‚¯(&K):
+STATIC5 動作
+R_PASS 接続を許å¯ã™ã‚‹(&P)
+R_DENY 接続を拒å¦ã™ã‚‹(&D)
+STATIC6 ãã®ä»–
+STATIC7 優先順ä½(&R):
+STATIC8 (整数値: å°ã•ã„ã»ã©å„ªå…ˆé †ä½ãŒé«˜ããªã‚Šã¾ã™)
+STATIC9 IP プロトコル ãƒãƒ¼ã‚¸ãƒ§ãƒ³:
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_LOG_FILE
+CAPTION ログファイル一覧
+STATIC1 サーãƒãƒ¼ä¸Šã«ä¿å­˜ã•ã‚Œã¦ã„るログファイルを指定ã—ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nVPN Server 全体ã®ç®¡ç†è€…ã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®ãƒ­ã‚°ãŠã‚ˆã³ã‚µãƒ¼ãƒãƒ¼ ログをダウンロードã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚仮想 HUB ã®ç®¡ç†è€…ã¯ã€ãã®ä»®æƒ³ HUB ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ã¿ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãã¾ã™ã€‚
+IDOK ダウンロード(&D)
+B_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&R)
+IDCANCEL é–‰ã˜ã‚‹
+
+
+PREFIX D_SM_READ_LOG_FILE
+CAPTION ファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰
+S_INFO2 ファイル "%S" ã‚’ VPN Server ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¦ã„ã¾ã™ã€‚\r\nã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+IDCANCEL ダウンロードã®ä¸­æ­¢(&S)
+
+
+PREFIX D_SM_SAVE_LOG
+CAPTION ログファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰å®Œäº†
+S_INFO ファイル "%S" ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãŒå®Œäº†ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ãã‹ã€ä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+IDOK é–‹ã(&O)
+B_SAVE ä¿å­˜(&S)
+IDCANCEL キャンセル
+
+
+PREFIX D_TCP
+CAPTION TCP/IP 最é©åŒ–ユーティリティ
+STATIC1 Windows ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãƒ—ロトコル (TCP/IP) ã®è¨­å®šã‚’最é©åŒ–ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã“ã®ã‚³ãƒ³ãƒ”ュータã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®é€šä¿¡é€Ÿåº¦ã‚’高速化ã™ã‚‹ã“ã¨ãŒã§ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nã“ã® TCP/IP 最é©åŒ–ユーティリティを使用ã™ã‚‹ã¨ã€é€šä¿¡é€Ÿåº¦ã®æœ€é©åŒ–ã®è¨­å®šã‚’ç°¡å˜ã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 下記ã«è¡¨ç¤ºã•ã‚Œã¦ã„ã‚‹ã®ã¯ã€ç¾åœ¨ã® Windows ãŒä¿æŒã—ã¦ã„ã‚‹ TCP/IP ã®è¨­å®šå€¤ã§ã™ã€‚ã“れらã®å€¤ã‚’変更ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€TCP/IP ã®è¨­å®šã‚’最é©åŒ–ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ã“ã®ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’後ã‹ã‚‰èµ·å‹•ã™ã‚‹ã“ã¨ã§ã€ã„ã¤ã§ã‚‚値をå†è¨­å®šã—ãŸã‚Šå…ƒã«æˆ»ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC3 TCP/IP 通信設定:
+STATIC4 TCP å—信ウインドウサイズ(&R):
+R_RECV_DISABLE OS ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã‚’使用ã™ã‚‹(&D)
+R_RECV_ENABLE 下記ã®å€¤ã«è¨­å®šã™ã‚‹(&E)
+S_RECV ãƒã‚¤ãƒˆ
+B_RECV 推奨値を使用(&C)
+STATIC5 TCP é€ä¿¡ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚µã‚¤ã‚º(&S):
+R_SEND_DISABLE OS ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã‚’使用ã™ã‚‹(&I)
+R_SEND_ENABLE 下記ã®å€¤ã«è¨­å®šã™ã‚‹(&N)
+S_SEND ãƒã‚¤ãƒˆ
+B_SEND 推奨値を使用(&M)
+IDOK &OK
+IDCANCEL キャンセル
+STATIC6 TCP/IP ã®è¨­å®šã‚’変更ã—ãŸå ´åˆã¯ã€Windows ã‚’å†èµ·å‹•ã—ãŸéš›ã«è¨­å®šãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚設定変更後ã€ã™ãã«ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€å†èµ·å‹•ã™ã‚‹ã¾ã§ã¯ TCP/IP ã®æœ€é©åŒ–設定ã¯æœ‰åŠ¹ã«ãªã‚Šã¾ã›ã‚“。
+B_DELETE TCP 通信設定最é©åŒ–ユーティリティã«ã‚ˆã‚‹ç®¡ç†ã‚’è¡Œã‚ãªã„
+
+
+PREFIX D_TCP_MSG
+CAPTION TCP/IP 通信設定ã®æœ€é©åŒ–
+STATIC1 Windows ã® TCP/IP 通信設定を最é©åŒ–ã™ã‚‹ã¨ã€TCP/IP を使用ã—ãŸé€šä¿¡é€Ÿåº¦ãŒå¤§å¹…ã«å‘上ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚通信設定を最é©åŒ–ã—ã¾ã™ã‹?\r\n\r\n後ã‹ã‚‰ TCP/IP 最é©åŒ–ユーティリティを起動ã—ã¦ã€ã„ã¤ã§ã‚‚通信設定を最é©åŒ–ã—ãŸã‚Šã€å…ƒã«æˆ»ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 TCP/IP ã®è¨­å®šã‚’変更ã—ãŸå ´åˆã¯ã€Windows ã‚’å†èµ·å‹•ã—ãŸéš›ã«è¨­å®šãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚設定変更後ã€ã™ãã«ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€å†èµ·å‹•ã™ã‚‹ã¾ã§ã¯ TCP/IP ã®æœ€é©åŒ–設定ã¯æœ‰åŠ¹ã«ãªã‚Šã¾ã›ã‚“。
+R_OPTIMIZE 通信設定を自動的ã«æœ€é©åŒ–ã™ã‚‹(&A)
+R_MANUAL TCP/IP 最é©åŒ–ユーティリティを使用ã—ã¦æ‰‹å‹•ã§æœ€é©åŒ–ã™ã‚‹(&M)
+R_NO 最é©åŒ–ã¯è¡Œã‚ãªã„(&D)
+IDOK 次ã¸(&N) >
+IDOK3 < 戻る(&B)
+
+
+PREFIX D_CM_PKCSEULA
+CAPTION ソフトウェアã¨ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ä½¿ç”¨æ¡ä»¶ã«é–¢ã™ã‚‹ç¢ºèª
+S_INFO_1 ソフトウェア "%S" を使用ã—ã¦æŒ‡å®šã—ãŸã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã«ã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚
+S_INFO_2 ソフトウェア "%S" を使用ã™ã‚‹å ´åˆã¯ã€ãã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚„使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ä½¿ç”¨æ¡ä»¶ãŒã‚ã‚‹å ´åˆã¯ã€ãã‚Œã«åŒæ„ã—ãŸä¸Šã§ä½¿ç”¨ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n詳ã—ãã¯ã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ "%S" やスマートカードã®æ供元ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+S_INFO_3 上記ã«åŒæ„ã—ã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ "%S" を使用ã—ã¦æŒ‡å®šã—ãŸã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¡Œã„ã¾ã™ã‹?
+IDOK ã¯ã„(&Y)
+IDCANCEL ã„ã„ãˆ(&N)
+
+
+PREFIX D_CM_TRAFFIC
+CAPTION 通信スループット測定ツール
+STATIC1 通信スループット測定ツールを使用ã™ã‚‹ã¨ã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ 2 å°ã®ã‚³ãƒ³ãƒ”ュータ間ã§æœ€å¤§é™ã«é€šä¿¡ã‚’è¡Œã„ã€å®Ÿéš›ã®é€šä¿¡ãƒ‡ãƒ¼ã‚¿é‡ã¨é€šä¿¡æ™‚é–“ã‹ã‚‰ãã®é–“ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æœ€å¤§å¸¯åŸŸå¹… (スループット) を測定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ãƒ„ールã¯ã€VPN ã®ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã§ã‚‚ã€VPN ã¨é–¢ä¿‚ç„¡ã„物ç†çš„ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã§ã‚‚使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC2 ã“ã®ãƒ„ールを使用ã—ã¦ã€ç¾åœ¨ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®é€šä¿¡èƒ½åŠ›ã‚’測定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã ã—ã€æ¸¬å®šçµæžœã¯æ¸¬å®šã™ã‚‹ä¸¡æ–¹ã®ã‚³ãƒ³ãƒ”ュータ㮠CPU 能力や他ã«å‹•ä½œã—ã¦ã„るアプリケーションã®çŠ¶æ…‹ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ä½¿ç”¨çŽ‡ãªã©ã«ã‚ˆã£ã¦å¤‰åŒ–ã™ã‚‹ãŸã‚ã€å®Ÿéš›ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®å‡¦ç†èƒ½åŠ›ã‚ˆã‚Šã‚‚低ã„値ãŒã§ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
+S_1 動作設定
+S_3 ã“ã®ã‚³ãƒ³ãƒ”ュータã¯æ¸¬å®šã‚µãƒ¼ãƒãƒ¼ã¾ãŸã¯æ¸¬å®šã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®ã©ã¡ã‚‰ã§ã™ã‹?
+R_SERVER 測定サーãƒãƒ¼(&S)
+R_CLIENT 測定クライアント(&C)
+S_4 測定サーãƒãƒ¼ã®å ´åˆã¯ã€å¾…ã¡å—ã‘ã‚‹ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚\r\n測定クライアントã®å ´åˆã¯ã€æŽ¥ç¶šå…ˆã®æ¸¬å®šã‚µãƒ¼ãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã€å¿…è¦ãªå ´åˆã¯å¿…è¦ãªã‚ªãƒ—ションを設定ã—ã¾ã™ã€‚
+S_5 接続先ã®æ¸¬å®šã‚µãƒ¼ãƒãƒ¼å(&H):
+S_6 ãƒãƒ¼ãƒˆç•ªå·(&P):
+S_7 (TCP ãƒãƒ¼ãƒˆ)
+S_8 下記ã®ã‚ªãƒ—ションã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§è¨­å®šã—ã¾ã™ã€‚
+S_9 データ通信ã®æ–¹å‘
+R_DOWNLOAD 測定サーãƒãƒ¼ã‹ã‚‰æ¸¬å®šã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«ä¼é€ (ダウンロード) (&D)
+R_UPLOAD 測定クライアントã‹ã‚‰æ¸¬å®šã‚µãƒ¼ãƒãƒ¼ã«ä¼é€ (アップロード) (&U)
+R_FULL åŒæ–¹å‘ã«ä¼é€ (ダウンロードã¨ã‚¢ãƒƒãƒ—ロードをåŒæ™‚ã«å®Ÿè¡Œ) (&F)
+S_10 通信ã®è©³ç´°è¨­å®š
+S_11 並列接続ã—ã¦ãƒ‡ãƒ¼ã‚¿ä¼é€ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°(&N):
+S_12 データä¼é€æ™‚é–“ (計測時間) (&A):
+S_13 秒間
+R_ETHERNET Ethernet ã¨ä»®å®šã—ã¦ãƒ¬ã‚¤ãƒ¤ 2 ã§ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットを算出(&E)
+R_DOUBLE 中継機器能力測定モード(&B)
+S_14 コãƒã‚¯ã‚·ãƒ§ãƒ³
+IDOK 実行(&R)
+IDCANCEL キャンセル
+S_15 通信スループット測定ツール㯠vpncmd コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‹ã‚‰å®Ÿè¡Œã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ (Windows 以外㮠OS ã§ã‚‚使用å¯èƒ½ã§ã™)。
+
+
+PREFIX D_CM_TRAFFIC_RUN
+CAPTION 通信トラフィック測定ツール
+S_INFO ç¾åœ¨ã€é€šä¿¡ãƒˆãƒ©ãƒ•ã‚£ãƒƒã‚¯æ¸¬å®šãƒ„ールを実行ã—ã¦ã„ã¾ã™ã€‚下記ã«å‹•ä½œçŠ¶æ³ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+STATIC1 通信トラフィック測定ツールを終了ã—ã¦ã“ã®ç”»é¢ã‚’é–‰ã˜ã‚‹ã«ã¯ã€[終了] をクリックã—ã¦ãã ã•ã„。
+IDCANCEL 終了(&X)
+
+
+PREFIX D_CM_TRAFFIC_RESULT
+CAPTION 通信トラフィック測定çµæžœ
+STATIC1 通信トラフィックã®æ¸¬å®šãŒå®Œäº†ã—ã¾ã—ãŸã€‚çµæžœã¯æ¬¡ã®ã¨ãŠã‚Šã§ã™ã€‚
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_LICENSE
+CAPTION ライセンスã®è¿½åŠ ã¨å‰Šé™¤
+STATIC1 SoftEther VPN Server を使用ã™ã‚‹ã«ã¯ã€æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’å–å¾—ã—ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’登録ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ç”»é¢ã§ã¯ã€æ–°ã—ã„ライセンスキーを登録ã—ãŸã‚Šã€ç™»éŒ²æ¸ˆã¿ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’削除ã—ãŸã‚Šã€ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ä¸€è¦§ã‚„ VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰ã‚’表示ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_BOLD ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンスã®ä¸€è¦§(&L):
+B_OBTAIN ライセンスã®å…¥æ‰‹ãƒ»æ›´æ–°(&O)
+STATIC2 [ライセンスã®å…¥æ‰‹ãƒ»æ›´æ–°] をクリックã™ã‚‹ã¨ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®å…¥æ‰‹ãƒ»æ›´æ–°æ–¹æ³•ã«é–¢ã™ã‚‹èª¬æ˜ŽãŒè¨˜è¼‰ã•ã‚ŒãŸ Web サイトを表示ã—ã¾ã™ã€‚
+B_ADD æ–°ã—ã„ライセンスキーã®ç™»éŒ²(&A)
+B_DEL 削除(&D)
+IDOK ライセンスã«é–¢ã™ã‚‹æƒ…å ±(&I)
+STATIC3 ライセンスをé¸æŠžã—ã€[ライセンスã«é–¢ã™ã‚‹æƒ…å ±] をクリックã™ã‚‹ã¨ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã® Web サイト (softether.com) ã«æŽ¥ç¶šã—ã€ãã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã«é–¢ã™ã‚‹ç™»éŒ²æƒ…報を表示ã—ã¾ã™ã€‚
+S_BOLD2 ç¾åœ¨ã® SoftEther VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰(&M):
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_LICENSE_ADD
+CAPTION æ–°ã—ã„ライセンスキーã®ç™»éŒ²
+S_INFO SoftEther VPN Server ã®è£½å“ライセンスã¾ãŸã¯æŽ¥ç¶šãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC1 ライセンスキーã¯ã€36 æ¡ã®è‹±æ•°å­—ãŠã‚ˆã³ãƒã‚¤ãƒ•ãƒ³ ( '-' ) ã§æ§‹æˆã•ã‚Œã¦ã„ã‚‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ‰€æœ‰ã‚’証明ã™ã‚‹ã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰ã§ã™ã€‚\r\n\r\nライセンスキーã¯ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¨å…±ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã‚’å—ã‘å–ã£ãŸå ´åˆã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã«å°åˆ·ã•ã‚Œã¦ã„ã¾ã™ã€‚本ソフトウェアã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’オンラインã§è³¼å…¥ã—ãŸå ´åˆã¯ã€è³¼å…¥æ™‚ã® Web サイトã®ç”»é¢ã‚„メールãªã©ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ãã®ä»–ã®æ–¹æ³•ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ä¸æ˜Žãªå ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®è³¼å…¥å…ƒã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+STATIC2 ライセンスキーを正確ã«å…¥åŠ›ã—ã¦ãã ã•ã„(&I):
+STATIC3 ライセンスキー㯠6 æ¡ã”ã¨ã«åŒºåˆ‡ã£ã¦å…¥åŠ›ã—ã¦ãã ã•ã„。ãƒã‚¤ãƒ•ãƒ³ã¯å…¥åŠ›ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。コピー && ペーストã§å…¥åŠ›ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚
+B_INFO2 本ソフトウェアã®è‘—作権ã¯å…¨ä¸–ç•Œã§ä¿è­·ã•ã‚Œã¦ã„ã¾ã™ã€‚ãŠå®¢æ§˜ã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹å¥‘約書ã®æ¡ä»¶ã«å¾“ã£ãŸå ´åˆã®ã¿ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’複製・使用ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ä¸æ­£ã«å…¥æ‰‹ã—ãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ä½¿ç”¨ã€è¤‡æ•°å°ã®ã‚µãƒ¼ãƒãƒ¼ã§ã®åŒä¸€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ä½¿ç”¨ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã®ç„¡æ–­é ’布ãªã©ã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹å¥‘約書ã«é•åã—ã€æ°‘事ã¾ãŸã¯åˆ‘事上ã®ç½°ã‚’å—ã‘ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã€ã”注æ„ãã ã•ã„。
+IDOK 登録(&R)
+IDCANCEL キャンセル
+
+
+PREFIX D_FREEINFO
+CAPTION SoftEther VPN Server Free Edition ã«ã¤ã„ã¦
+S_INFO_1 SoftEther VPN Server Free Edition ã‚’ã”利用ã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
+S_INFO_2 接続先ã®ã‚µãƒ¼ãƒãƒ¼ "%S" ã§ç¨¼å‹•ã—ã¦ã„ã‚‹ SoftEther VPN Server ã¯å€‹äººåˆ©ç”¨ã‚’目的ã¨ã—㟠Free Edition ã§ã™ã€‚\r\nFree Edition ã§ã¯ SoftEther VPN Server ã®ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒä½¿ç”¨ã§ãã¾ã™ãŒã€ä¸‹è¨˜ã®åˆ©ç”¨æ–¹æ³•ã¯ä½¿ç”¨æ¨©è¨±è«¾å¥‘ç´„ã«ã‚ˆã£ã¦ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚
+S_INFO_3 ・ VPN Server を経由ã—ã¦ã€æ¥­å‹™ã®ãŸã‚ã®é€šä¿¡ãŒè¡Œã‚れるよã†ãªä½¿ç”¨æ–¹æ³•ã€‚
+S_INFO_4 上記ã®ç¦æ­¢ã•ã‚Œã¦ã„る使用方法ã§ä½¿ç”¨ã—ãŸå ´åˆã¯ã€SoftEther VPN Server 使用権許諾契約é•åã¨ãªã‚Šã¾ã™ã®ã§ã”注æ„ãã ã•ã„。SoftEther VPN Server ã®é€šå¸¸è£½å“版ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’入手ã—ã¦ã„ãŸã ãã“ã¨ã«ã‚ˆã‚Šã€ä¸Šè¨˜ã®ã‚ˆã†ãªåˆ¶é™ã¯ç„¡ããªã‚Šã¾ã™ã€‚ 通常製å“版ã«ã¤ã„ã¦ã¯ã€www.softether.com ã‚’ã”覧ãã ã•ã„。\r\n\r\nã‚‚ã—ã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ã‚’上記ã®ã‚ˆã†ãªä½¿ç”¨æ–¹æ³•ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€www.softether.com ã¾ã§ã”連絡ã„ãŸã ãã¾ã™ã‚ˆã†ãŠé¡˜ã„ã„ãŸã—ã¾ã™ã€‚\r\n\r\n※ ã“ã®ç”»é¢ã¯ã€Free Edition ã® VPN Server ã«æŽ¥ç¶šã—ãŸéš›ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚Free Edition 以外ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³è£½å“ã§ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。\r\n※ Free Edition ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯ã€è£½å“版ã¨æ¯”較ã—ã¦ã“ã®ãŠçŸ¥ã‚‰ã›ç”»é¢ãŒè¡¨ç¤ºã•ã‚Œã‚‹ä»¥å¤–ã®é•ã„ã¯å…¨ãã‚ã‚Šã¾ã›ã‚“。
+B_HIDE 次回ã‹ã‚‰ã“ã®ãŠçŸ¥ã‚‰ã›ã‚’表示ã—ãªã„(&H)
+IDCANCEL &OK
+
+
+PREFIX D_CM_SETTING
+CAPTION SoftEther VPN Client 動作モード変更
+STATIC1 SoftEther VPN Client ã¯ã€Œé€šå¸¸ãƒ¢ãƒ¼ãƒ‰ã€ã¾ãŸã¯ã€Œç°¡æ˜“モードã€ã§ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚使用ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã‚’切り替ãˆã‚‹ã«ã¯ã€ä¸‹è¨˜ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+R_NORMAL 通常モード(&N)
+R_EASY 簡易モード(&E)
+STATIC2 [通常モード] 㯠SoftEther VPN Client ソフトウェアã®ã™ã¹ã¦ã®æ“作を行ã†ã“ã¨ãŒã§ãる動作モードã§ã™ã€‚一般的ãªãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚„システム管ç†è€…ã«ãŠå‹§ã‚ã—ã¾ã™ã€‚
+STATIC3 [簡易モード] 㯠VPN Server ã¸ã®æŽ¥ç¶šãªã©ã®æœ€ã‚‚よã使用ã™ã‚‹æ“作ã—ã‹ã§ããªã„動作モードã§ã™ã€‚VPN ã«ã¤ã„ã¦è©³ã—ã„知識をãŠæŒã¡ã§ãªã„ユーザーã«ãŠå‹§ã‚ã—ã¾ã™ã€‚
+STATIC4 [設定ロック機能] を使用ã™ã‚‹ã¨ã€SoftEther VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を使ã£ã¦ VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ãŒã€æŽ¥ç¶šè¨­å®šã®å†…容を変更ã—ãŸã‚Šã€æ–°ã—ã接続設定を作æˆã—ãŸã‚Šã€å‰Šé™¤ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚
+R_LOCK 設定ロック機能を使ã†(&L)
+S_PASSWORD1 パスワードを指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚パスワードを指定ã™ã‚‹ã¨ã€å¾Œã‹ã‚‰è¨­å®šãƒ­ãƒƒã‚¯æ©Ÿèƒ½ã‚’無効ã«ã™ã‚‹éš›ã«ãƒ‘スワードã®å…¥åŠ›ãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚
+S_PASSWORD2 パスワード(&P):
+S_PASSWORD3 確èªå…¥åŠ›(&C):
+IDOK &OK
+IDCANCEL キャンセル
+S_VGS2 VPN Gate 学術実験サービスã®è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_VGS VPN &Gate サービスã®è¨­å®š...
+
+
+PREFIX D_CM_EASY
+CAPTION SoftEther VPN クライアント簡易接続マãƒãƒ¼ã‚¸ãƒ£
+B_MODE 動作モードã®å¤‰æ›´(&M)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+B_STATUS 接続状æ³ã®è¡¨ç¤º(&S)
+B_VGC VPN Gate 学術実験
+
+
+PREFIX D_SM_SETUP
+CAPTION SoftEther VPN Server / Bridge 簡易セットアップ
+S_TITLE SoftEther VPN Server / Bridge 簡易セットアップ
+IDC_STATIC_1 ã“ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—プログラムを使用ã™ã‚‹ã¨ã€SoftEther VPN Server ã¾ãŸã¯ VPN Bridge を以下ã®ç”¨é€”や目的ã®ãŸã‚ã«ç°¡å˜ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚セットアップ終了後ã¯ã€VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’用ã„ã¦ã€ã‚ˆã‚Šè©³ç´°ãªè¨­å®šã‚’自由ã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_BOLD 構築ã—よã†ã¨ã—ã¦ã„ã‚‹ VPN サーãƒãƒ¼ã®ç¨®é¡žã‚’é¸æŠžã—ã¦ãã ã•ã„。複数ã®ç”¨é€”ã®ãŸã‚ã® VPN サーãƒãƒ¼ã‚’構築ã—よã†ã¨ã—ã¦ã„ã‚‹å ´åˆã¯ã€è¤‡æ•°ã®ç¨®é¡žã‚’é¸æŠžã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+C_REMOTE リモートアクセス VPN サーãƒãƒ¼(&R)
+S_REMOTE_1 リモートアクセス VPN ã¯ã€ãŸã¨ãˆã°ç¤¾å†… LAN ãªã©ã®æ—¢å­˜ã® Ethernet セグメントã«å¯¾ã—ã¦ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãªã©ã‚’経由ã—ã¦é éš”地㮠VPN クライアントコンピュータ㌠VPN 接続ã™ã‚‹ã“ã¨ãŒã§ãる形態㮠VPN 構æˆã§ã™ã€‚\r\nVPN Server ã«æŽ¥ç¶šã—㟠VPN クライアントコンピュータã¯ã€ç¤¾å†…ã® Ethernet ã«å¯¾ã—ã¦ç›´æŽ¥ LAN ケーブルã§æŽ¥ç¶šã—ã¦ã„ã‚‹ã®ã¨åŒç­‰ã®çŠ¶æ…‹ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+C_SITE 拠点間接続 VPN サーãƒãƒ¼ã¾ãŸã¯ãƒ–リッジ(&S)
+S_SITE_1 拠点間接続 VPN ã¯ã€æ—¢å­˜ã® 2 箇所以上ã®æ‹ ç‚¹ã® Ethernet セグメントåŒå£«ã‚’ VPN 接続ã™ã‚‹å½¢æ…‹ã® VPN 構æˆã§ã™ã€‚\r\nVPN 接続ã•ã‚ŒãŸãã‚Œãžã‚Œã®æ‹ ç‚¹åŒå£«ã¯ãƒ¬ã‚¤ãƒ¤ 2 レベルã§åŒä¸€ã®ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã¨ãªã‚Šã¾ã™ã®ã§ã€å„拠点内ã®ã‚³ãƒ³ãƒ”ュータåŒå£«ãŒåŒä¸€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã«ã‚ã‚‹ã‚‚ã®ã¨ã—ã¦é€šä¿¡ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+S_SITE_2 ã“ã® VPN Server ã®å½¹å‰²ã‚’é¸æŠžã—ã¦ãã ã•ã„:
+C_CENTER 拠点間接続 VPN ã®ä¸­å¿ƒã¨ãªã‚Šã€ä»–拠点ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘入れる VPN Server (&M)
+C_EDGE å„拠点ã«è¨­ç½®ã™ã‚‹ VPN Server ã¾ãŸã¯ VPN Bridge (&E)
+C_OTHER 高度ãªæ©Ÿèƒ½ã‚’用ã„㟠VPN (&O)
+S_OTHER クラスタリング機能や仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ãªã©ã®é«˜åº¦ãªæ©Ÿèƒ½ã‚’æä¾›ã™ã‚‹ VPN システムを構築ã™ã‚‹å ´åˆã€‚
+IDOK 次ã¸(&N)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_SETUP_HUB
+CAPTION 簡易セットアップ - 仮想 HUB åã®æ±ºå®š
+IDC_STATIC_1 VPN Server 上ã«ä»®æƒ³ HUB ã‚’ 1 個作æˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚仮想 HUB ã®åå‰ã¯è‡ªç”±ã«æŒ‡å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+IDC_STATIC_2 仮想 HUB å(&N):
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_SETUP_STEP
+CAPTION 簡易セットアップã®å®Ÿè¡Œ
+IDC_STATIC_1 ã“ã® VPN Server / VPN Bridge ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—を完了ã™ã‚‹ã«ã¯ã€ä¸‹è¨˜ã®ã‚¿ã‚¹ã‚¯ã®ã†ã¡å¿…è¦ãªã‚‚ã®ã‚’実行ã—ã¦ãã ã•ã„。
+S_1_1 1. VPN 接続をå—ã‘入れるãŸã‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ä½œæˆ
+S_1_2 ã“ã® VPN Server ãŒãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ VPN ã‚’å—ã‘入れる場åˆã€ã¾ãŸã¯æ‹ ç‚¹é–“接続 VPN ã«ãŠã„ã¦ä¸­å¿ƒã¨ãªã‚Šä»–拠点ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘入れる場åˆã¯ã€VPN 接続をå—ã‘入れるãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’作æˆã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+B_USER ユーザーを作æˆã™ã‚‹(&U)
+S_2_1 2. 接続先㮠VPN Server ã¸ã®æŽ¥ç¶šè¨­å®š
+S_2_2 拠点間接続 VPN ã«ãŠã‘ã‚‹å„拠点ã«è¨­ç½®ã™ã‚‹ VPN Server ã¾ãŸã¯ VPN Bridge ã®å ´åˆã¯ã€å„ VPN 拠点ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã€ä¸­å¿ƒã¨ãªã‚‹ VPN Server ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãªã©ã‚’入力ã—ã¦ã€ãã® VPN Server ã¸ã®æŽ¥ç¶šã‚’確立ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+B_CASCADE 接続先㮠VPN Server ã¸ã®æŽ¥ç¶šè¨­å®šã‚’è¡Œã†(&O)
+S_3_1 3. ローカルブリッジã®è¨­å®š
+S_3_2 VPN 経由㧠LAN ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãŸã‚ã«ã¯ã€VPN å´ã®ä»®æƒ³çš„㪠Ethernet セグメントã¨ç‰©ç†çš„㪠Ethernet セグメントã¨ã®é–“を「ローカルブリッジ接続ã€æ©Ÿèƒ½ã§ãƒ–リッジ接続ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nVPN ã«å¯¾ã—ã¦ãƒ–リッジ接続ã™ã‚‹æ—¢å­˜ã® Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+IDCANCEL é–‰ã˜ã‚‹(&C)
+IDC_STATIC_8 å¿…è¦ãªè¨­å®šãŒã™ã¹ã¦å®Œäº†ã—ãŸã‚‰ã€[é–‰ã˜ã‚‹] をクリックã—ã¦ãã ã•ã„。VPN Server / VPN Bridge ã®è©³ç´°ãªç®¡ç†ç”»é¢ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ãã®å¾Œã¯å¿…è¦ãªå ´åˆã«è©³ç´°ãªè¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。
+B_SECURENAT SecureN&AT 機能ã®è¨­å®šã‚’è¡Œã†
+
+
+PREFIX D_CPU64_WARNING
+CAPTION SoftEther VPN ã® 64 bit 版ã«é–¢ã™ã‚‹æƒ…å ±
+S_BOLD インストールã•ã‚ŒãŸ SoftEther VPN ソフトウェア㯠32 bit 版ã§ã™ãŒã€ç¾åœ¨å®Ÿè¡Œã•ã‚Œã¦ã„ã‚‹ Windows オペレーティングシステム㯠64 bit 版ã§ã™ã€‚
+S_INFO 64 bit 版 Windows 上㧠32 bit 版㮠SoftEther VPN ソフトウェアを実行ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã™ãŒã€Windows ãŒæ­è¼‰ã—ã¦ã„ã‚‹ 32 bit エミュレータ上ã§å‹•ä½œã™ã‚‹ã“ã¨ã«ãªã‚‹ãŸã‚ã€ãƒ‘フォーマンスãŒä½Žä¸‹ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\nã¾ãŸã€ä¸€éƒ¨ã®æ©Ÿèƒ½ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n64 bit 版 Windows 上ã§ã¯ SoftEther VPN ソフトウェア㮠64 bit 版をインストールã—ã¦ä½¿ç”¨ã•ã‚Œã‚‹ã“ã¨ã‚’å¼·ã推奨ã—ã¾ã™ã€‚\r\nSoftEther VPN ソフトウェア㮠64 bit 版㯠http://selinks.org/ よりダウンロードã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nã“ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ãƒœãƒƒã‚¯ã‚¹ã¯ã€30 秒後ã«è‡ªå‹•çš„ã«é–‰ã˜ã¾ã™ã€‚
+IDOK &OK
+
+
+PREFIX D_ONCEMSG
+CAPTION TITLE
+C_DONTSHOWAGAIN 今後ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„(&D)
+IDCANCEL &OK
+
+
+PREFIX D_CONNECT
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_IPSEC
+CAPTION IPsec / L2TP / EtherIP / L2TPv3 設定
+S_TITLE IPsec / L2TP / EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®š
+S_3 ã“ã® VPN Server 上ã®ä»®æƒ³ HUB ã¯ã€L2TP ã«å¯¾å¿œã—㟠PC ã‚„ Mac OS Xã€ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ç­‰ã‹ã‚‰ãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ VPN 接続をå—ã‘付ã‘ãŸã‚Šã€EtherIP / L2TPv3 ã«å¯¾å¿œã—ãŸå¸‚販ã®ãƒ«ãƒ¼ã‚¿ç­‰ã‹ã‚‰æ‹ ç‚¹é–“ VPN 接続をå—ã‘付ã‘ãŸã‚Šã§ãã¾ã™ã€‚
+S01 L2TP サーãƒãƒ¼æ©Ÿèƒ½ (リモートアクセス VPN サーãƒãƒ¼æŽ¥ç¶š)
+S02 iPhoneã€iPadã€Android ç­‰ã®ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã‚„ Mac OS Xã€Windows 等㮠OS 付属ã®æ¨™æº– VPN クライアントã‹ã‚‰ VPN 接続ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+R_L2TP_OVER_IPSEC L2TP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ (L2TP over IP&sec)
+S03 iPhoneã€iPadã€Androidã€Windowsã€Mac OS X ã‹ã‚‰ã® VPN 接続をå—ã‘付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+R_L2TP_RAW L2TP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ (æš—å·åŒ–ã•ã‚Œã¦ã„ãªã„ &L2TP)
+S04 IPsec を用ã„ãªã„ L2TP を使用ã™ã‚‹ç‰¹æ®Šãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚’サãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚
+S_1 接続時ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§ä»®æƒ³ HUB åãŒçœç•¥ã•ã‚ŒãŸå ´åˆã«æŽ¥ç¶šã™ã‚‹ä»®æƒ³ HUB ã®é¸æŠž(&H):
+S_2 L2TPã€OpenVPN ãŠã‚ˆã³ MS-SSTP VPN 接続時ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å㯠"仮想HUBå\\ユーザーå" ã¾ãŸã¯ "ユーザーå@仮想HUBå" ã®ã‚ˆã†ã«æŒ‡å®šã—ã¦ãã ã•ã„。ãªãŠã€ä»®æƒ³ HUB åã®æŒ‡å®šãŒçœç•¥ã•ã‚ŒãŸå ´åˆã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§æŽ¥ç¶šã™ã‚‹ä»®æƒ³ HUB を設定ã—ã¦ãŠãã“ã¨ãŒã§ãã¾ã™ã€‚
+S05 EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½ (拠点間接続 VPN サーãƒãƒ¼æ©Ÿèƒ½)
+S06 EtherIP / L2TPv3 over IPsec ã«å¯¾å¿œã—ãŸå¸‚販ã®ãƒ«ãƒ¼ã‚¿è£½å“ã¯ã€ã“ã® VPN Server ã®ä»®æƒ³ HUB ã«ãƒ¬ã‚¤ãƒ¤ 2 (Ethernet) ã§ãƒ–リッジ接続ã§ãã¾ã™ã€‚
+R_ETHERIP &EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½æœ‰åŠ¹
+B_DETAIL サーãƒãƒ¼æ©Ÿèƒ½ã®è©³ç´°è¨­å®š(&D)
+S07 IPsec 共通設定(&C)
+S_PSK IPsec 事å‰å…±æœ‰éµ(&P):
+S_PSK2 IPsec 事å‰å…±æœ‰éµã¯ã€ã€ŒPSK (Pre-Shared Key)ã€ã¾ãŸã¯ã€Œã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã€ã¨å‘¼ã°ã‚Œã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚8 文字程度ã§è¨­å®šã—ã€VPN を利用ã™ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é…布ã—ã¦ãã ã•ã„。
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_ETHERIP
+CAPTION EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½ã®è©³ç´°è¨­å®š
+S_TITLE EtherIP / L2TPv3 サーãƒãƒ¼æ©Ÿèƒ½
+S01 VPN Server ã« EtherIP / L2TPv3 over IPsec ã«å¯¾å¿œã—ãŸå¸‚販ã®ãƒ«ãƒ¼ã‚¿æ©Ÿå™¨ã‹ã‚‰ãƒ¬ã‚¤ãƒ¤ 2 Ethernet ブリッジ接続を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nCisco 社ã®ãƒ«ãƒ¼ã‚¿ã‚„ NEC 製㮠IX ルータã€IIJ 製㮠SEIL ルータ等ãŒãŠå‹§ã‚ã§ã™ã€‚
+S02 EtherIP / L2TPv3 ã«ã‚ˆã‚‹æŽ¥ç¶šã‚’å—ã‘付ã‘ã‚‹ã«ã¯ã€äºˆã‚ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã¨ãªã‚‹ EtherIP / L2TPv3 対応ルータãŒã“ã® VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã® IPsec Phase 1 ID 文字列ã¨ã€æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB ã®æƒ…å ±ã®å¯¾å¿œè¡¨ã‚’定義ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+S_BOLD IPsec Phase 1 ID ã¨æŽ¥ç¶šå…ˆä»®æƒ³ HUB ã¨ã®å¯¾å¿œè¡¨(&T):
+B_ADD 追加(&A)
+IDOK 編集(&E)
+B_DELETE 削除(&D)
+IDCANCEL é–‰ã˜ã‚‹(&X)
+
+
+PREFIX D_SM_ETHERIP_ID
+CAPTION EtherIP / L2TPv3 over IPsec クライアント定義
+S01 EtherIP / L2TPv3 over IPsec クライアントãŒã“ã® VPN Server ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã® ISAKMP (IKE) Phase 1 ã®ã‚¤ãƒ‹ã‚·ã‚¨ãƒ¼ã‚¿ ID 文字列ãŒä»¥ä¸‹ã«ä¸€è‡´ã™ã‚‹å ´åˆã«ã€æ¬¡ã®ä»®æƒ³ HUB ã¸ã®æŽ¥ç¶šè¨­å®šã‚’é©ç”¨ã—ã¾ã™ã€‚
+S02 ISAKMP Phase 1 &ID:
+S03 接続先ã®ä»®æƒ³ &HUB:
+S04 ユーザーå(&U):
+S05 パスワード(&P):
+S06 ユーザーåã¨ãƒ‘スワードã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚EtherIP / L2TPv3 クライアントã¯ã€ä¸Šè¨˜ã§å…¥åŠ›ã•ã‚ŒãŸæƒ…å ±ã§è­˜åˆ¥ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ¨©é™ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ãŸã‚‚ã®ã¨ã¿ãªã•ã‚Œã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+S07 (ID ã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã®ãƒ«ãƒ¼ã‚¿ã®æŽ¥ç¶šè¨­å®šã§è¨­å®šã™ã‚‹ã‚‚ã®ã¨åŒä¸€ã®æ–‡å­—列を指定ã—ã¦ãã ã•ã„。文字列ã®ã»ã‹ã€ID ã®ç¨®é¡žãŒ IP アドレスã®å ´åˆã¯ IP アドレスも指定ã§ãã¾ã™ã€‚)\r\n\r\nãªãŠã€'*' (アスタリスク) を指定ã™ã‚‹ã¨ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰æŒ‡å®šã¨ãªã‚Šã€ä»–ã®æ˜Žç¤ºçš„ãªãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã—ãªã„ã™ã¹ã¦ã®æŽ¥ç¶šå…ƒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚
+
+
+PREFIX D_SM_OPENVPN
+CAPTION OpenVPN / MS-SSTP 設定
+S_TITLE OpenVPN / MS-SSTP VPN サーãƒãƒ¼æ©Ÿèƒ½è¨­å®š
+S_1 OpenVPN 社㮠OpenVPN ソフトウェア製å“ã¨åŒç­‰ã® VPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’æ­è¼‰ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nOpenVPN クライアントã‹ã‚‰ã“ã® VPN Server ã«æŽ¥ç¶šã§ãã¾ã™ã€‚
+R_OPENVPN &OpenVPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹
+S_UDP OpenVPN サービスをæä¾›ã™ã‚‹ &UDP ãƒãƒ¼ãƒˆ:
+B_DEFAULT 標準ã«æˆ»ã™(&D)
+S_UDP2 UDP ãƒãƒ¼ãƒˆã¯è¤‡æ•°æŒ‡å®šã§ãã¾ã™ã€‚複数指定ã™ã‚‹å ´åˆã¯ã‚¹ãƒšãƒ¼ã‚¹ã¾ãŸã¯ã‚«ãƒ³ãƒžã§åŒºåˆ‡ã£ã¦ãã ã•ã„。\r\nOpenVPN サーãƒãƒ¼æ©Ÿèƒ½ã¯ TCP ãƒãƒ¼ãƒˆã§ã‚‚有効ã«ãªã‚Šã¾ã™ã€‚ã“ã®å ´åˆã€ã“ã® VPN Server ã«ç¾åœ¨ä½œæˆã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã® TCP リスナãƒãƒ¼ãƒˆã§ OpenVPN プロトコルãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚
+S_TOOL OpenVPN クライアント用サンプル設定ファイル自動作æˆãƒ„ール
+S_TOOL2 本æ¥ã€OpenVPN クライアントを使ã†ãŸã‚ã«ã¯è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’手動ã§è¨˜è¿°ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã€ã“ã‚Œã¯é›£æ˜“度ãŒé«˜ã„作業ã§ã™ã€‚ã—ã‹ã—ã€ä»¥ä¸‹ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã ã‘ã§ã“ã® VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãる基本的㪠OpenVPN クライアント用ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’自動的ã«ç”Ÿæˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+B_CONFIG OpenVPN クライアント用ã®ã‚µãƒ³ãƒ—ル設定ファイルを生æˆ(&C)
+S_2 Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½
+S_3 Microsoft 社㮠Windows Server 2008 / 2012 製å“ã«æ­è¼‰ã•ã‚Œã¦ã„ã‚‹ MS-SSTP VPN サーãƒãƒ¼æ©Ÿèƒ½ã¨äº’æ›æ€§ãŒã‚る機能をæ­è¼‰ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nWindows Vista / 7 / 8 / RT ã«æ¨™æº–æ­è¼‰ã® MS-SSTP クライアントã‹ã‚‰ã“ã® VPN Server ã«æŽ¥ç¶šã§ãã¾ã™ã€‚
+R_SSTP &MS-SSTP VPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹
+S_SSTP VPN Server ã® SSL 証明書㮠CN ã®å€¤ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§æŒ‡å®šã™ã‚‹ãƒ›ã‚¹ãƒˆåã¨ä¸€è‡´ã—ã€ã‹ã¤ãã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚詳ã—ã㯠Microsoft 社ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+S_4 ã“れらã®äº’æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹å ´åˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®æŒ‡å®šæ–¹æ³•ã€ãŠã‚ˆã³ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆä»®æƒ³ HUB ã®é¸æŠžè¦å‰‡ã¯ã€IPsec サーãƒãƒ¼æ©Ÿèƒ½ã¨åŒæ§˜ã§ã™ã€‚
+B_IPSEC I&Psec サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®š
+S_13 OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_SM_DDNS
+CAPTION ダイナミック DNS 機能
+S_TITLE ダイナミック DNS 機能
+S_BOLD ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Server ã«ã¯ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
+S_1 ダイナミック DNS ã«ã‚ˆã‚Šã€ã“ã® VPN Server コンピュータã«æ°¸ç¶šçš„ãªå›ºæœ‰ã® DNS ホストåãŒå‰²å½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç‹¬è‡ªã§ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’所有ã—ã¦ã„ãªãã¦ã‚‚ã€VPN Client ã‚„ VPN Bridge ãªã©ã®è¨­å®šç”»é¢ä¸Šã§ VPN Server ã® IP アドレスã®ä»£ã‚ã‚Šã« DNS ホストåã«ã‚ˆã£ã¦ VPN Server を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_22 ã¾ãŸã€IP アドレスãŒå¤‰åŒ–ã™ã‚‹å¯èƒ½æ€§ãŒã‚る一般的㪠ISP を用ã„㦠VPN Server をインターãƒãƒƒãƒˆã«æŽ¥ç¶šã™ã‚‹å ´åˆã§ã‚‚ã€IP アドレスãŒå¤‰åŒ–ã™ã‚Œã°è‡ªå‹•çš„ã« DNS ホストã«å¯¾å¿œã™ã‚‹ IP アドレスãŒæ›´æ–°ã•ã‚Œã¾ã™ã®ã§ã€å¯å¤‰ IP アドレスã§ã‚‚ VPN Server ã‚’é‹ç”¨ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\r\nã“ã‚Œã«ã‚ˆã‚Šã€é«˜ä¾¡ãªæœˆé¡æ–™é‡‘ãŒå¿…è¦ãªå›ºå®šã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã®ã‚µãƒ¼ãƒ“スを契約ã™ã‚‹å¿…è¦ãŒãªããªã‚Šã¾ã™ã€‚
+S_3 ã•ã‚‰ã«ã€ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® VPN Server 㯠NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã‚’サãƒãƒ¼ãƒˆã—ã¦ãŠã‚Šã€VPN Server ㌠NAT ã®å†…å´ã«ã‚りプライベート IP アドレスã—ã‹æŒã£ã¦ã„ãªã„å ´åˆã§ã‚‚ã€NAT 上ã§ç‰¹åˆ¥ãªè¨­å®šã‚’ã™ã‚‹ã“ã¨ãªãã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆå´ã‹ã‚‰ã® VPN 接続をå—付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_4 ç¾åœ¨ã®çŠ¶æ…‹(&S):
+S_STATUS3 割当ã¦ã‚‰ã‚Œã¦ã„るダイナミック DNS ホストå(&H):
+B_HINT ヒント
+S_STATUS4 グローãƒãƒ« IPv&4 アドレス:
+S_STATUS5 グローãƒãƒ« IPv&6 アドレス:
+S_5 設定ã®å¤‰æ›´(&M):
+S_STATUS6 ダイナミック DNS ホストåã®å¤‰æ›´(&C):
+S_STATUS7 3 文字以上 31 文字以内ã®åŠè§’英数字ãŠã‚ˆã³ãƒã‚¤ãƒ•ãƒ³ '-' ãŒä½¿ç”¨ã§ãã¾ã™ã€‚\r\n変更ã¯ä½•åº¦ã§ã‚‚å¯èƒ½ã§ã™ã€‚
+IDOK 上記㮠DNS ホストåã«å¤‰æ›´ã™ã‚‹(&A)
+B_RESTORE 変更å‰ã«æˆ»ã™(&R)
+S_2 IPv6 インターãƒãƒƒãƒˆã«æŽ¥ç¶šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ä¸Šè¨˜ã® [IPv6 アドレス] ã®æ¬„ã«ã‚¨ãƒ©ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ãŒã€ç•°å¸¸ã§ã¯ã‚ã‚Šã¾ã›ã‚“。一部ã®å›½ãƒ»åœ°åŸŸã§ã¯ã€è¡Œæ”¿æ©Ÿé–¢ã«ã‚ˆã‚‹åˆ¶é™ã«ã‚ˆã‚Šã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サービスãŒåˆ©ç”¨ã§ããªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+IDCANCEL é–‰ã˜ã‚‹(&X)
+B_DISABLE ダイナミック DNS 機能を無効ã«ã™ã‚‹(&D)
+B_PROXY プロキシサーãƒãƒ¼çµŒç”±ã§æŽ¥ç¶š(&P)
+
+
+PREFIX D_SM_SPECIALLISTENER
+CAPTION VPN over ICMP / DNS 機能ã®è¨­å®š
+S_TITLE VPN over ICMP / DNS 機能
+S_1 VPN over ICMP / DNS 機能
+S_2 ファイアウォールやルータ等ã®æ•…障やéŽè² è·ã€è¨­å®šãƒŸã‚¹ç­‰ã«ã‚ˆã‚Š TCP/IP 通信ãŒé®æ–­ã•ã‚Œã¦ã„る環境ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‹ã‚‰ã§ã‚‚ã€ICMP (Ping) ã¾ãŸã¯ DNS パケットã®é€šä¿¡ãŒå¯èƒ½ã§ã‚ã‚Œã°ã€ã“ã® VPN Server ã¨ã®é–“㧠VPN 通信を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®ãŸã‚ã«ã¯ã€äºˆã‚以下ã®æ©Ÿèƒ½ã‚’有効ã«ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+R_OVER_ICMP VPN over &ICMP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹
+R_OVER_DNS VPN over &DNS サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ (UDP ãƒãƒ¼ãƒˆ 53 を使用ã—ã¾ã™)
+IDOK &OK
+IDCANCEL キャンセル
+S_3 接続元㮠VPN Client ã¾ãŸã¯ VPN Bridge ã¯å†…部ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4.0 以é™ãŒå¿…è¦ã§ã™ã€‚
+S_4 警告: ã“ã‚Œã¯ã€ãƒ•ã‚¡ã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚„ルータ等ãŒä¸€æ™‚çš„ã«ä¸èª¿ã¨ãªã£ã¦ãŠã‚Š ICMP ã¾ãŸã¯ DNS ã®ã¿å®‰å®šã—ãŸé€šä¿¡ãŒå¯èƒ½ãªç’°å¢ƒã§ VPN 通信を確立ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚緊急時ãªã©ã«ã¯æœ‰ç›Šã§ã™ãŒã€é•·æœŸé–“ã®åˆ©ç”¨ã«ã¯é©ã•ãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+
+
+PREFIX D_SM_REDIRECT
+CAPTION HTTP URL リダイレクション設定
+S_1 仮想 HUB を経由ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãŒã“ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸå ´åˆã€ãã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’用ã„ã¦ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒä½•ã‚‰ã‹ã®é€šä¿¡ã‚’è¡ŒãŠã†ã¨ã™ã‚‹ã¨ã€å¼·åˆ¶çš„ã«ä»¥ä¸‹ã«è¨­å®šã•ã‚ŒãŸ URL 文字列をクライアントã«å¯¾ã—ã¦å¿œç­”ã—ã¾ã™ã€‚\r\n\r\nã“ã‚Œã«ã‚ˆã‚Šã€VPN クライアント上ã§èµ·å‹•ã—ã¦ã„ã‚‹ Web ブラウザãŒç‰¹å®šã® IP アドレスã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãŸå ´åˆãªã©ã«ä»»æ„ã® Web ページをãã® Web ブラウザ上ã«è¡¨ç¤ºã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+S_2 リダイレクト先 URL ã®å…¥åŠ›:
+S_BOLD2 リダイレクト先 &URL:
+S_3 入力例:
+S_4 å˜ç´”㪠URL リダイレクション:
+S_5 高度㪠URL リダイレクション:
+B_HINT 高度㪠URL リダイレクション機能ã®ä½¿ã„æ–¹(&U)...
+S_6 ã”注æ„
+S_BOLD ã“ã®æ©Ÿèƒ½ã¯ TCP/IP ã«è©³ã—ã„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…å‘ã‘ã®æ©Ÿèƒ½ã§ã™ã€‚以下ã®æ³¨æ„事項をよã読ã¿ã€æ…Žé‡ã«è¨­å®šã—ã¦ãã ã•ã„。
+S_7 アクセスリストã®æ¡ä»¶ã«å®›å…ˆã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã§å½“該アクセスリストãŒãƒ‘ケットã«ä¸€è‡´ã—ãŸå ´åˆã¯ã“ã®æ©Ÿèƒ½ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚
+S_8 TCP 以外ã®ãƒ‘ケットãŒã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ä¸€è‡´ã—ãŸå ´åˆã¯ã“ã®æ©Ÿèƒ½ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚
+S_9 ã™ã¹ã¦ã® TCP パケットã«å¯¾ã—㦠HTTP リダイレクト応答を返ã—ã¾ã™ (ãƒãƒ¼ãƒˆ 80 ã«é™å®šã•ã‚Œã¾ã›ã‚“)。ãŸã¨ãˆã°ãƒãƒ¼ãƒˆ 80 ã«é™å®šã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã®æ¡ä»¶ã§å®›å…ˆãƒãƒ¼ãƒˆã‚’ TCP 80 ã«é™å®šã—ã¦ãã ã•ã„。
+S_10 リダイレクト先㮠URL ã«å¯¾ã—ã¦ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã—ãŸçµæžœãŒå†åº¦ã“ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ä¸€è‡´ã—ãŸå ´åˆã¯ã€å½“該アクセスè¦æ±‚ã«å¯¾ã—ã¦å†åº¦ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³å¿œç­”ãŒè¿”ä¿¡ã•ã‚Œã¾ã™ã€‚ã“ã®å ´åˆã¯ç„¡é™ã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³ã®ç¹°ã‚Šè¿”ã—ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+IDOK &OK
+IDCANCEL キャンセル
+S_11 高度ãªãƒªãƒ€ã‚¤ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³æ©Ÿèƒ½ã¯ã€ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆ CGI ã« VPN セッション情報をæä¾›ã§ãã¾ã™ã€‚
+
+
+PREFIX D_SW_WELCOME
+CAPTION D_SW_WELCOME
+S_WELCOME SoftEther VPN ã¯ç­‘波大学ã§é–‹ç™ºã•ã‚ŒãŸã€Windows ã‚„ Mac ãªã©ã®ã‚³ãƒ³ãƒ”ュータãŠã‚ˆã³ iPhone, iPad, Android, Windows RT ãªã©ã®ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã‚„タブレットã€Cisco ãªã©ã®ã‚µãƒ¼ãƒ‰ãƒ‘ーティ製 VPN ルータã€OpenVPN ã‚„ MS-SSTP ãªã©ã®æ—¢å­˜ã® VPN プロトコルã¨ã‚‚互æ›æ€§ãŒã‚る安全ã§é«˜æ€§èƒ½ãªã‚ªãƒ¼ãƒ—ンソース VPN ソフトウェアã§ã™ã€‚
+S_TITLE ã™ã¹ã¦ã®ä¸»è¦ãªãƒ‡ãƒã‚¤ã‚¹ã«å¯¾å¿œã™ã‚‹ã‚ªãƒ¼ãƒ—ンソース VPN ソフトウェア
+
+
+PREFIX D_SW_MODE
+CAPTION D_SW_MODE
+R_SYSTEM システムモード (推奨) (&S)
+R_USER ユーザーモード (&U)
+S_1 ã“ã®ã‚³ãƒ³ãƒ”ュータã«é€šå¸¸ã®æ–¹æ³•ã§ VPN ソフトウェアをインストールã—ã¾ã™ã€‚ã“ã®ã‚³ãƒ³ãƒ”ュータã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+S_USER 一般ユーザー権é™ã§ VPN ソフトウェアをインストールã—ã¾ã™ã€‚管ç†è€…権é™ã¯ä¸è¦ã§ã™ãŒã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジãªã©ã®ä¸€éƒ¨ã®æ©Ÿèƒ½ãŒåˆ©ç”¨ã§ãã¾ã›ã‚“。ユーザー "%s" ㌠Windows ã«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„ã‚‹é–“ã ã‘使用ã§ãã¾ã™ã€‚
+S_2 SoftEther VPN 㯠2 種類ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—モードã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚\r\n\r\n通常ã¯ã€Œã‚·ã‚¹ãƒ†ãƒ ãƒ¢ãƒ¼ãƒ‰ã€ã‚’é¸æŠžã—ã¦ãã ã•ã„。\r\n\r\n何らã‹ã®ç†ç”±ã§ç®¡ç†è€…権é™ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ããªã„å ´åˆã¯ã€ã€Œãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã€ã‚’é¸æŠžã™ã‚Œã°ä¸€èˆ¬ãƒ¦ãƒ¼ã‚¶ãƒ¼æ¨©é™ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+
+
+PREFIX D_SW_NOT_ADMIN
+CAPTION D_SW_NOT_ADMIN
+S_INFO ç¾åœ¨ Windows ã«ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã„るユーザー "%s" ã«ã¯ç®¡ç†è€…æ¨©é™ (Administrators 権é™) ãŒã‚ã‚Šã¾ã›ã‚“。\r\n\r\nセットアップを続行ã™ã‚‹ã«ã¯ã€ä¸€åº¦ Windows ã‹ã‚‰ãƒ­ã‚°ã‚ªãƒ•ã—ã€ã“ã®ã‚³ãƒ³ãƒ”ュータã®ç®¡ç†è€…権é™ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ãƒ­ã‚°ã‚ªãƒ³ã—ã¦ã‹ã‚‰å†åº¦ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ— ウィザードを起動ã—ã¦ãã ã•ã„。
+S_INFO6 「完了ã€ã‚’クリックã™ã‚‹ã¨ã€ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ— ウィザードを終了ã—ã¾ã™ã€‚
+S_INFO2 管ç†è€…権é™ãŒç„¡ã„å ´åˆã§ã‚‚ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\nユーザーモードã§ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’インストールã™ã‚‹ã«ã¯ã€ã€Œæˆ»ã‚‹ã€ã‚’クリックã—ã¦ãã ã•ã„。
+
+
+PREFIX D_SW_COMPONENTS
+CAPTION D_SW_COMPONENTS
+
+
+PREFIX D_SW_EULA
+CAPTION D_SW_EULA
+S_1 使用許諾契約書を注æ„ã—ã¦ãŠèª­ã¿ãã ã•ã„。
+B_AGREE 使用許諾契約書ã«åŒæ„ã—ã¾ã™(&A)
+
+
+PREFIX D_SW_WARNING
+CAPTION D_SW_WARNING
+S_1 SoftEther VPN ソフトウェアã¯éžå¸¸ã«å¼·åŠ›ãªé€šä¿¡æ©Ÿèƒ½ã‚’有ã—ã¦ã„ã‚‹ãŸã‚ã€ã”利用ã«ã‚ãŸã£ã¦ã¯ä¸‹è¨˜ã®é‡è¦äº‹é …説明書をよããŠèª­ã¿ãã ã•ã„。
+
+
+PREFIX D_SW_DIR
+CAPTION D_SW_DIR
+S_INFO 「%s〠ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。
+R_CUSTOM インストール先を変更(&S)
+S_DEST インストール先(&D):
+B_BROWSE å‚ç…§(&B)...
+R_SHOWCUSTOM 上級者ã®ãŸã‚ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚ªãƒ—ション(&A)
+R_FOR_SYSTEM ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠Windows ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«(&Y)
+R_FOR_USER ユーザー "%s" ã®ç’°å¢ƒã«ã®ã¿ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«(&U)
+S_WARNING ã”注æ„: 推奨ã•ã‚Œã¾ã›ã‚“。ユーザー "%s" ㌠Windows ã‹ã‚‰ãƒ­ã‚°ã‚ªãƒ•ã™ã‚‹ã¨ã€%s ã®å‹•ä½œã¯åœæ­¢ã—ã¾ã™ã€‚ã¾ãŸã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能や L2TP/IPsec 機能 (Mac やスマートフォンã‹ã‚‰ã®æŽ¥ç¶š) ãªã©ã¯å‹•ä½œã—ã¾ã›ã‚“。
+
+
+PREFIX D_SW_READY
+CAPTION D_SW_READY
+S_INFO 「%s〠ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã®æº–å‚™ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+S_INFO7 「次ã¸ã€ã‚’クリックã™ã‚‹ã¨ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å‡¦ç†ã‚’開始ã—ã¾ã™ã€‚
+
+
+
+PREFIX D_SW_PERFORM
+CAPTION D_SW_PERFORM
+S_INFO %s ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ãŒé€²è¡Œä¸­ã§ã™ã€‚\r\n完了ã¾ã§ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+S_INFO8 SoftEther VPN ã¯æ—¥æœ¬å›½çµŒæ¸ˆç”£æ¥­çœã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ç ”究開発プロジェクトã®æˆæžœç‰©ã§ã™ã€‚IPA (独立行政法人 情報処ç†æŽ¨é€²æ©Ÿæ§‹) ã®æœªè¸ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢å‰µé€ äº‹æ¥­ã«æŽ¡æŠžã•ã‚Œé–‹ç™ºã•ã‚Œã¾ã—ãŸã€‚詳ã—ã㯠http://www.ipa.go.jp/ ã‚’ã”覧ãã ã•ã„。
+
+PREFIX D_SW_ERROR
+CAPTION D_SW_ERROR
+S_INFO エラーãŒç™ºç”Ÿã—ãŸãŸã‚ã€%s ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—を完了ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚\r\n\r\nå†è©¦è¡Œã™ã‚‹ã«ã¯ã€ã‚‚ã†ä¸€åº¦ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ— ウィザードを起動ã—ã¦ãã ã•ã„。
+
+
+PREFIX D_SW_FINISH
+CAPTION D_SW_FINISH
+S_INFO %s ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—処ç†ãŒæ­£å¸¸ã«å®Œäº†ã—ã¾ã—ãŸã€‚
+S_INFO8 SoftEther VPN ã¯æ—¥æœ¬å›½çµŒæ¸ˆç”£æ¥­çœã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ç ”究開発プロジェクトã®æˆæžœç‰©ã§ã™ã€‚IPA (独立行政法人 情報処ç†æŽ¨é€²æ©Ÿæ§‹) ã®æœªè¸ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢å‰µé€ äº‹æ¥­ã«æŽ¡æŠžã•ã‚Œé–‹ç™ºã•ã‚Œã¾ã—ãŸã€‚詳ã—ã㯠http://www.ipa.go.jp/ ã‚’ã”覧ãã ã•ã„。
+
+PREFIX D_SW_UNINST1
+CAPTION D_SW_UNINST1
+S_WELCOME ã“ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ウィザードを使用ã™ã‚‹ã¨ã€%s をコンピュータã‹ã‚‰ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\r\n\r\nアンインストールを開始ã™ã‚‹ã«ã¯ã€ã€Œæ¬¡ã¸ã€ã‚’クリックã—ã¦ãã ã•ã„。
+S_TITLE %s ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«
+
+
+
+PREFIX D_SW_EASY1
+CAPTION D_SW_EASY1
+S_WELCOME ä¼æ¥­å†…ã®å¤šãã®æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚³ãƒ³ãƒ”ュータ㫠VPN Client をインストールã™ã‚‹éš›ã«ã€1 å°ãšã¤ VPN 接続設定を実施ã™ã‚‹ã®ã¯å¤§å¤‰ã§ã™ã€‚
+S_TITLE SoftEther VPN Client 簡易インストーラã¨ã¯
+S_WELCOME2 「簡易インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã€ã¯ã€ä¼æ¥­ã®ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…å‘ã‘ã®ãƒ„ールã§ã™ã€‚「簡易インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã€ã‚’使用ã™ã‚Œã°ã€ã‚らã‹ã˜ã‚指定ã—ãŸæŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’埋ã‚è¾¼ã‚“ã  VPN Client ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’作æˆã§ãã¾ã™ã€‚ã‚‚ã¡ã‚ã‚“ã€å€‹äººã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚‚使用ã§ãã¾ã™ã€‚
+S_WELCOME3 作æˆã—ãŸã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã¯ã€ç¤¾å†…ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚µãƒ¼ãƒãƒ¼ã‚„メールãªã©ã‚’用ã„ã¦ç¤¾å“¡ã«é…布ã§ãã¾ã™ã€‚インストーラを実行ã™ã‚‹ã¨ VPN Client ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã€è‡ªå‹•çš„ã«æŽ¥ç¶šè¨­å®šãŒã‚¤ãƒ³ãƒãƒ¼ãƒˆã•ã‚Œã¦ãã®æŽ¥ç¶šè¨­å®šã‚’用ã„㟠VPN 接続ãŒé–‹å§‹ã•ã‚Œã¾ã™ã€‚
+
+
+PREFIX D_SW_EASY2
+CAPTION D_SW_EASY2
+S_BOLD1 埋ã‚è¾¼ã¿ãŸã„接続設定ファイル (.vpn ファイル) を指定ã—ã¦ãã ã•ã„
+S_1 簡易インストーラã«åŸ‹ã‚è¾¼ã¿ãŸã„接続設定ファイル (æ‹¡å¼µå­ãŒ .vpn ã®ãƒ•ã‚¡ã‚¤ãƒ«) を指定ã—ã¦ãã ã•ã„。接続設定ファイルã¯ã€VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£å†…ã®æŽ¥ç¶šè¨­å®šã‚’å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€ŒæŽ¥ç¶šè¨­å®šã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ã‚’クリックã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚
+S_18 接続設定(&S):
+B_BROWSE_SETTING å‚ç…§(&B)...
+B_DELETE_SENSITIVE 接続設定ファイル内ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを格ç´ã—ãªã„(&E)
+S_BOLD2 生æˆã•ã‚Œã‚‹ EXE ファイルã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+S_3 ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¯ã€ç°¡æ˜“インストーラã¨ã—㦠EXE ファイル (実行å¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«) を生æˆã—ã¾ã™ã€‚生æˆã•ã‚Œã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜ã™ã‚‹ãŸã‚ã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„。
+S_19 ファイルå(&A):
+B_BROWSE_OUT å‚ç…§(&R)...
+B_EASYMODE VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’簡易モードã«è¨­å®šã™ã‚‹(&E)
+
+
+PREFIX D_SW_WEB1
+CAPTION D_SW_WEB1
+S_WELCOME SoftEther VPN Client Web インストーラを作æˆã™ã‚‹ã¨ã€Web ブラウザを開ã特定ã®ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€SoftEther VPN Client を自動的ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®éš›ã«ã€äºˆã‚設定ã—ã¦ãŠã„ãŸæŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’インãƒãƒ¼ãƒˆã—㦠VPN 接続を開始ã•ã›ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+S_TITLE SoftEther VPN Client Web インストーラã¨ã¯
+S_WELCOME2 作æˆã—㟠Web インストーラã¯ã€ç¤¾å†…å‘ã‘ã® Web サーãƒãƒ¼ãªã©ã« HTML ファイルã¨ã—ã¦è¨­ç½®ã§ãã¾ã™ã€‚設置ã•ã‚ŒãŸ HTML ファイル㮠URL ã«ç¤¾å“¡ãŒã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ã€SoftEther VPN Client ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ãŒèµ·å‹•ã—ã¾ã™ã€‚
+S_WELCOME3 ActiveX コントロールを使用ã—ã¦ã„ã¾ã™ã€‚クライアントブラウザ㯠Internet Explorer 5.0 以é™ã€ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã¯ Windows 2000 以é™ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚IE 以外ã®ãƒ–ラウザや Windows 98 ãªã©ã®å¤ã„ OS ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¾ã›ã‚“。
+
+
+PREFIX D_SW_WEB2
+CAPTION D_SW_WEB2
+S_BOLD1 埋ã‚è¾¼ã¿ãŸã„接続設定ファイル (.vpn ファイル) を指定ã—ã¦ãã ã•ã„
+S_1 Web インストーラã«åŸ‹ã‚è¾¼ã¿ãŸã„接続設定ファイル (æ‹¡å¼µå­ãŒ .vpn ã®ãƒ•ã‚¡ã‚¤ãƒ«) を指定ã—ã¦ãã ã•ã„。接続設定ファイルã¯ã€VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£å†…ã®æŽ¥ç¶šè¨­å®šã‚’å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€ŒæŽ¥ç¶šè¨­å®šã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ã‚’クリックã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚
+S_18 接続設定(&S):
+B_BROWSE_SETTING å‚ç…§(&B)...
+B_DELETE_SENSITIVE 接続設定ファイル内ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを格ç´ã—ãªã„(&E)
+S_BOLD2 生æˆã•ã‚Œã‚‹ Web サーãƒãƒ¼è¨­ç½®ç”¨ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+S_3 ã“ã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¯ã€Web サーãƒãƒ¼ã«è¨­ç½®ã™ã‚‹ãŸã‚ã® HTML ファイルや CAB ファイルãŒæ ¼ç´ã•ã‚ŒãŸ ZIP ファイル (アーカイブファイル) を生æˆã—ã¾ã™ã€‚生æˆã•ã‚Œã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜ã™ã‚‹ãŸã‚ã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„。
+S_19 ファイルå(&A):
+B_BROWSE_OUT å‚ç…§(&R)...
+B_EASYMODE VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’簡易モードã«è¨­å®šã™ã‚‹(&E)
+
+
+PREFIX D_UPDATE_NOTICE
+CAPTION %s ã®ã‚¢ãƒƒãƒ—デート
+IDOK 更新 Web サイトを表示(&S)...
+B_CONFIG アップデート通知設定(&C)...
+IDCANCEL 今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„(&I)
+S_INFO %s ã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ã¾ã™ã€‚今ã™ãダウンロードã—ã¦ã‚¢ãƒƒãƒ—デートã§ãã¾ã™ã€‚
+S_PRODUCT ソフトウェア:
+S_CURRENT ç¾åœ¨ä½¿ç”¨ä¸­ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³:
+S_CURRENT_STR Ver %u.%02u.%04u%s
+S_LATEST 最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³:
+S_LATEST_STR Ver %S%s
+
+
+PREFIX D_UPDATE_CONFIG
+CAPTION アップデート通知ã®è¨­å®š
+S_INFO %s ã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ãªã„ã‹ã©ã†ã‹å®šæœŸçš„ã«ãƒã‚§ãƒƒã‚¯ã—ã€ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ãŸå ´åˆã¯é€šçŸ¥ç”»é¢ã‚’表示ã—ã¾ã™ã€‚\r\n\r\nアップデートãƒã‚§ãƒƒã‚¯ã®ãŸã‚ã«æ—¥æœ¬ã®èŒ¨åŸŽçœŒã¤ãã°å¸‚ã«è¨­ç½®ã•ã‚Œã¦ã„ã‚‹ SoftEther Update サーãƒãƒ¼ã¨ã®é–“㧠HTTPS 通信を行ã„ã¾ã™ã€‚ãŠå®¢æ§˜ã®å€‹äººæƒ…å ±ãŒé€ä¿¡ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
+S_TITLE %s ã®ã‚¢ãƒƒãƒ—デートãƒã‚§ãƒƒã‚¯ã¨é€šçŸ¥ã®è¨­å®š
+S_ENABLE アップデートãƒã‚§ãƒƒã‚¯ã‚’有効ã«ã™ã‚‹(&E)
+S_DISBLE アップデートãƒã‚§ãƒƒã‚¯ã‚’無効ã«ã™ã‚‹(&D)
+IDCANCEL é–‰ã˜ã‚‹(&C)
+
+
+PREFIX D_SM_VMBRIDGE
+CAPTION VM 内ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジを使用ã™ã‚‹å ´åˆã®æ³¨æ„事項
+S_TITLE VM 内ã§ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã®ä½¿ç”¨
+S_1 VPN Server ㌠VMware ã‚„ Hyper-V ãªã©ã® VM (仮想マシン) 内ã§å‹•ä½œã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚以下ã®æ³¨æ„事項をよããŠèª­ã¿ãã ã•ã„。VM を使用ã—ã¦ã„ãªã„å ´åˆã¯ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ç„¡è¦–ã—ã¦ãã ã•ã„。
+S_2 VM ã§ã¯ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆè¨­å®šã§ LAN カードã®ã€Œãƒ—ロミスキャスモードã€(MAC アドレス スプーフィング) ã§ã®é€šä¿¡ãŒç¦æ­¢ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nVM 内ã§å‹•ä½œã™ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã¨ãƒ›ã‚¹ãƒˆãƒžã‚·ãƒ³ã«è£…ç€ã•ã‚Œã¦ã„る物ç†çš„㪠LAN カードã¨ã®é–“ã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジを行ã†å ´åˆã€ãƒ—ロミスキャスモード (MAC アドレス スプーフィング) ãŒç¦æ­¢ã•ã‚Œã¦ã„ã‚‹ã¨æ­£å¸¸ã«é€šä¿¡ãŒã§ãã¾ã›ã‚“。ã“ã®ã‚ˆã†ãªå ´åˆã¯ã€VM ã®è¨­å®šãƒ„ールを用ã„ã¦ãƒ—ロミスキャスモード (MAC アドレス スプーフィング) を有効ã«ã—ã¦ãã ã•ã„。\r\n\r\n詳ã—ãã¯ã€VM ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。他ã®ç®¡ç†è€…ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¦ã„る共有 VM ã®å ´åˆã¯ã€ç®¡ç†è€…ã«ãƒ—ロミスキャスモード (MAC アドレス スプーフィング) を許å¯ã™ã‚‹ã‚ˆã†è¦è«‹ã—ã¦ãã ã•ã„。
+S_BOLD 注æ„事項
+IDCANCEL &OK
+
+
+PREFIX D_SM_AZURE
+CAPTION VPN Azure サービスã®è¨­å®š
+S_TITLE VPN Azure クラウド型 VPN サービス (無料)
+S_1 VPN Azure ã«ã‚ˆã‚Šã€ä¼šç¤¾ã®ãƒ‘ソコンã«è‡ªå®…や外出先ã®ãƒ‘ソコンã‹ã‚‰éžå¸¸ã«ç°¡å˜ã« VPN 接続ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚VPN 接続中ã¯ä¼šç¤¾ã®ãƒ‘ソコンを経由ã—ã¦ã€ç¤¾å†… LAN ã®ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã«ã‚‚アクセスã§ãã¾ã™ã€‚
+S_2 会社ã®ãƒ‘ソコン (VPN Server) ã«ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã¯ä¸è¦ã§ã™ã€‚ファイアウォールや NAT ã®å†…å´ã§ã‚ã£ã¦ã‚‚動作ã—ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹è¨­å®šã¯ä¸€åˆ‡å¿…è¦ã‚ã‚Šã¾ã›ã‚“。VPN クライアントã¨ãªã‚‹è‡ªå®…ã®ãƒ‘ソコンã§ã¯ã€Windows ã«æ¨™æº–付属㮠SSTP VPN クライアントを使用ã§ãã¾ã™ã€‚
+S_3 VPN Azure ã¯ã€SoftEther VPN Server ã‚’ãŠä½¿ã„ã®æ–¹ã¯ã©ãªãŸã§ã‚‚ç„¡æ–™ã§åˆ©ç”¨ã§ãるクラウド VPN サービスã§ã™ã€‚ソフトイーサ株å¼ä¼šç¤¾ã«ã‚ˆã£ã¦é‹å–¶ã•ã‚Œã¦ã„ã¾ã™ã€‚使ã„方を表示ã™ã‚‹ã«ã¯ã€å³ã®ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。
+B_BOLD VPN Azure 設定
+R_ENABLE VPN Azure を有効ã«ã™ã‚‹(&E)
+R_DISABLE VPN Azure を無効ã«ã™ã‚‹(&D)
+S_HOSTNAME_BORDER ç¾åœ¨ã® VPN Azure ホストå
+S_HOSTNAME_INFO VPN Azure ホストåã¯ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サービスã®ãƒ›ã‚¹ãƒˆåã®ãƒ‰ãƒ¡ã‚¤ãƒ³éƒ¨åˆ†ã‚’ "vpnazure.net" ã«å¤‰æ›´ã—ãŸã‚‚ã®ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+B_CHANGE ホストåã®å¤‰æ›´(&H)
+B_WEB VPN Azure ã®ä½¿ã„æ–¹\r\n(Web サイトを表示)
+IDCANCEL &OK
+
+
+PREFIX D_SM_PROXY
+CAPTION プロキシサーãƒãƒ¼çµŒç”±ã®æŽ¥ç¶š
+STATIC9 プロキシサーãƒãƒ¼ã‚’経由ã—ã¦ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+STATIC10 プロキシã®ç¨®é¡ž(&Y):
+R_DIRECT_TCP 直接 TCP/IP 接続 (プロキシを使ã‚ãªã„) (&D)
+R_HTTPS HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&T)
+R_SOCKS SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š(&K)
+B_PROXY_CONFIG プロキシサーãƒãƒ¼ã®æŽ¥ç¶šè¨­å®š(&R)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_VGC_LIST
+CAPTION VPN Gate 学術実験プロジェクト プラグイン for SoftEther VPN Client
+S_TITLE VPN Gate 公開 VPN 中継サーãƒãƒ¼ä¸€è¦§
+S_INFO1 世界中ã®ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã«ã‚ˆã£ã¦ç„¡å„Ÿæä¾›ã•ã‚Œã¦ã„ã‚‹ VPN サーãƒãƒ¼ã« VPN 接続ã™ã‚‹ã¨ã€ãã® VPN サーãƒãƒ¼ã‚’経由ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«è‡ªç”±ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ローカルã®ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã®åˆ¶ç´„を回é¿ã—ãŸã‚Šã€è‡ªåˆ†ã® IP アドレスを秘匿ã—ãŸã‚Šã§ãã¾ã™ã€‚
+IDOK é¸æŠžã—㟠VPN サーãƒãƒ¼ã«æŽ¥ç¶š(&C)
+B_PROXY プロキシ設定(&P)
+S_VLAN 仮想 LAN カード:
+B_WEB VPN Gate 学術実験\r\nWeb サイト
+B_REFRESH リストを更新(&R)
+S_REFRESH リストを更新中...
+S_RESEARCH 筑波大学ã«ãŠã‘る学術研究プロジェクト
+S_INFO9 回線速度 (Mbps) ãŒé«˜é€Ÿã§ Ping ã®å€¤ãŒå°ã•ãª VPN サーãƒãƒ¼ã»ã©å¿«é©ã§ã™ã€‚ã¾ãŸã€æµ·å¤–ã«è¨­ç½®ã•ã‚Œã¦ã„ã‚‹ VPN サーãƒãƒ¼ã‚’経由ã™ã‚Œã°ã€æ™®æ®µã‚ãªãŸã®å›½ã‹ã‚‰é–²è¦§ã§ããªã„ Web サイトやコンテンツãŒè¦‹ãˆã‚‹ã‚ˆã†ã«ãªã‚‹ã‹ã‚‚知れã¾ã›ã‚“。
+
+
+PREFIX D_VGC_PROTOCOL
+CAPTION 接続ã«ä½¿ç”¨ã™ã‚‹ VPN プロトコルã®é¸æŠž
+S_TITLE 公開 VPN 中継サーãƒãƒ¼ "%S" (%S) 㯠TCP 㨠UDP ã®ä¸¡æ–¹ã® VPN プロトコルをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚
+S_INFO VPN サーãƒãƒ¼ "%S" (%S) ã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ VPN プロトコルをé¸æŠžã—ã¦ãã ã•ã„。一般的㫠TCP ã®ã»ã†ãŒãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã‚’通éŽã—ã‚„ã™ã„ã§ã™ãŒã€TCP ã§æ­£å¸¸ã«ä½¿ç”¨ã§ããªã‹ã£ãŸå ´åˆã¯ä»£ã‚ã‚Šã« UDP ã‚’ãŠè©¦ã—ãã ã•ã„。
+R_TCP &TCP を使用 (Ethernet over HTTPS VPN) (推奨)
+R_UDP &UDP を使用 (Ethernet over UDP VPN)
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_VGS_CONFIG
+CAPTION VPN Gate サービス コントロールパãƒãƒ«
+R_ENABLE VPN Gate 中継サービスを有効ã«ã—ã€ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã¨ã—ã¦å®Ÿé¨“ã«å‚加ã™ã‚‹(&E)
+S_TITLE VPN Gate 学術実験ã«å‚加ã—ã¾ã™ã‹?
+S_INFO1 VPN Gate ã¯ç­‘波大学大学院ã«ãŠã‘る学術的ãªç ”究ã¨ã—ã¦å®Ÿæ–½ã•ã‚Œã¦ã„ã‚‹ã€åˆ†æ•£åž‹å…¬é–‹ VPN 中継サーãƒãƒ¼ã®é‹ç”¨ã«é–¢ã™ã‚‹å®Ÿé¨“ã§ã™ã€‚VPN Gate クライアントã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€å…¬é–‹ VPN 中継サーãƒãƒ¼ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã™ã‚‹ VPN Gate サービスã«æŽ¥ç¶šã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãã® VPN サービスを経由ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚
+S_INFO9 VPN Gate クライアントã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚µãƒ¼ãƒãƒ¼ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã¯ã€ã‚¢ã‚¯ã‚»ã‚¹å…ƒã® IP アドレスãŒå…¬é–‹ VPN 中継サーãƒãƒ¼ã®ã‚³ãƒ³ãƒ”ュータ㮠IP アドレスã«å¤‰åŒ–ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€VPN Gate クライアントã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ãŸã¨ãˆã°ãƒ­ãƒ¼ã‚«ãƒ«ã®ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ãŒæ•…éšœã—ã¦ã„ã‚‹ãŸã‚アクセスã§ããªã„海外㮠Web サイトã«ã‚¹ãƒ ãƒ¼ã‚ºã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+S_WARNING ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã—㦠[OK] をクリックã™ã‚‹ã¨ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ上㧠VPN Gate 中継サービスãŒå‹•ä½œã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ä»»æ„ã® VPN Gate クライアントãŒå½“該 VPN Gate 中継サービスを経由ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«å‘ã‹ã£ã¦é€šä¿¡ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚VPN Gate 中継サービスãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã§ã‚‚ã€ã“ã®ã‚³ãƒ³ãƒ”ュータãŒæŽ¥ç¶šã•ã‚Œã¦ã„る社内 LAN ãªã©ã®ãƒ—ライベート IP アドレスã«å¯¾ã™ã‚‹ VPN 通信㯠VPN Gate 中継サービスを経由ã—ãªã„ãŸã‚安全ã§ã™ã€‚
+B_OPTION VPN Gate サービスã®ã‚ªãƒ—ション設定(&O)...
+IDOK &OK
+IDCANCEL キャンセル
+B_WEB http://www.vpngate.net/ ã‚’é–‹ã(&B)...
+
+
+PREFIX D_VGS_OPTION
+CAPTION VPN Gate サービスã®ã‚ªãƒ—ション設定
+S_TITLE VPN Gate サービスã®ã‚ªãƒ—ション設定
+S_1 VPN Gate サービスをã“ã®ã‚³ãƒ³ãƒ”ュータã§å‹•ä½œã•ã›ã‚‹å ´åˆã€ã“ã®ã‚³ãƒ³ãƒ”ュータã¯å…¬é–‹ VPN サーãƒãƒ¼ã«ãªã‚Šã¾ã™ã€‚サーãƒãƒ¼ã®é‹å–¶è€…情報を入力ã—ã¦ãã ã•ã„。入力ã•ã‚ŒãŸé‹å–¶è€…情報ã¯ã€www.vpngate.net 上ã®ã‚µãƒ¼ãƒãƒ¼ä¸€è¦§è¡¨ãªã©ã«å…¬é–‹ã•ã‚Œã€èª°ã§ã‚‚閲覧ã§ãã¾ã™ã€‚ã¾ãŸã€VPN Gate 実験ã«é–¢ã™ã‚‹é€£çµ¡å…ˆã¨ã—ã¦ä½¿ç”¨ã„ãŸã—ã¾ã™ã€‚
+S_2 é‹å–¶è€…情報:
+S_3 ã“ã® VPN Gate サービスã®é‹å–¶è€…(&O):
+S_19 (64 文字以内)
+S_20 ä¸æ­£åˆ©ç”¨ãŒã‚ã£ãŸã¨ãã®é€šå ±å…ˆ\r\n(メールアドレス等) (&A):
+S_21 (64 文字以内)
+S_22 利用者ã¸ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸(&M):\r\n(128 文字以内)
+S_23 利用者ã¸ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ã€VPN Gate サーãƒãƒ¼ä¸€è¦§è¡¨ã®å†…ã§è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚楽ã—ã„メッセージを入力ã™ã‚‹ã¨ã€å¿ƒç†çš„ã«è‰¯å¥½ãªæ°—æŒã¡ã«ãªã‚Šã¾ã™ã€‚
+S_24 VPN 通信設定:
+R_LOG VPN 通信ã®ãƒ‘ケットログをä¿å­˜ã™ã‚‹(&S) (推奨)
+R_2WEEKS 2 週間以上経éŽã—ãŸãƒ‘ケットログã¯è‡ªå‹•å‰Šé™¤ã¾ãŸã¯ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰å¾Œã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã™ã‚‹(&T) (推奨)
+R_PERMANENT パケットログã¯ãƒ‡ã‚£ã‚¹ã‚¯å®¹é‡ãŒè¨±ã™é™ã‚Šæ’ä¹…çš„ã«ä¿å­˜ã™ã‚‹(&P)
+R_L2TP &L2TP/IPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ (推奨)
+S_25 Mac OS Xã€iPhone / iPadã€Android ãªã©ã‹ã‚‰ã® VPN 接続をå¯èƒ½ã«ã—ã¾ã™ã€‚
+B_MESSAGE VPN Client ㌠VPN 接続ã—ã¦ããŸéš›ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ PC ã®ç”»é¢ä¸Šã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹(&S)...
+IDOK &OK
+IDCANCEL キャンセル
+
+
+PREFIX D_VGS_WARNING
+CAPTION VPN Gate 学術実験ã¸ã®å‚加å‰ã®ã”注æ„
+S1 VPN Gate 学術実験サービスã¯ã€æ—¥æœ¬å›½ã«æ‰€åœ¨ã™ã‚‹ç­‘波大学大学院ã«ãŠã‘る研究プロジェクトã¨ã—ã¦é‹å–¶ã•ã‚Œã¦ã„るサービスã§ã™ã€‚本サービスã¯æ—¥æœ¬å›½ã®æ³•ä»¤ã«ã®ã¿æº–æ‹ ã—ã¦é‹ç”¨ã•ã‚Œã¦ãŠã‚Šã€æ—¥æœ¬å›½ä»¥å¤–ã®å›½ãƒ»åœ°åŸŸã®æ³•ä»¤ã«ã¤ã„ã¦ã¯ä¸€åˆ‡é–¢çŸ¥ã—ã¦ãŠã‚Šã¾ã›ã‚“。
+S2 ãã‚‚ãも世界ã«ã¯ 200 カ国近ãã®å›½ãŒå­˜åœ¨ã—ã¦ãŠã‚Šã€ãã‚Œãžã‚Œã®å›½ã«ãŠã‘る法律ã¯äº’ã„ã«ç•°ãªã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®å›½ã®æ³•å¾‹ã‚’調査ã—ãŸä¸Šã§ãれらã™ã¹ã¦ã«é©åˆã™ã‚‹ã“ã¨ã‚’ä¿è¨¼ã—ãŸã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’開発ã™ã‚‹ã“ã¨ã¯äº‹å®Ÿä¸Šä¸å¯èƒ½ã§ã™ã€‚万一ユーザーãŒæœ¬ã‚µãƒ¼ãƒ“スを特定ã®å›½ãƒ»åœ°åŸŸã®é ˜åŸŸå†…ã§åˆ©ç”¨ã—ãŸã“ã¨ã«ã‚ˆã£ã¦å…¬å‹™å“¡ã«ã‚ˆã‚Šæ³•çš„ãªãƒšãƒŠãƒ«ãƒ†ã‚£ã‚’科ã›ã‚‰ã‚Œã‚‹ãªã©ã®æ害ãŒç™ºç”Ÿã—ãŸå ´åˆã§ã‚ã£ã¦ã‚‚ã€ãƒ—ロジェクト実施者ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+S3 本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを使用ã™ã‚‹éš›ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé©ç”¨ã•ã‚Œã‚‹ã™ã¹ã¦ã®æ³•ä»¤ã‚’ユーザーã®è²¬ä»»ã«ã‚ˆã‚Šéµå®ˆã—ã¦ãã ã•ã„。本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを日本国内・国外をå•ã‚ãšä½¿ç”¨ã•ã‚ŒãŸå ´åˆã«ç™ºç”Ÿã™ã‚‹ã™ã¹ã¦ã®æ害ã¨è²¬ä»»ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¸°è²¬ã—ã¾ã™ã€‚本学術実験ã®é‹å–¶è€…ãŠã‚ˆã³ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ä¾›çµ¦è€…ã¯ã€ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+S4 ã“れらã®æ³¨æ„事項ã«åŒæ„ã„ãŸã ã‘ãªã„å ´åˆã¯ã€VPN Gate 学術実験サービスã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½ã‚’使用ã—ãªã„ã§ãã ã•ã„。
+S5 VPN Gate ã¯ç­‘波大学大学院ã«ãŠã‘る学術目的ã®ç ”究プロジェクトã§ã™ã€‚VPN Gate ソフトウェアã¯ãƒ•ãƒªãƒ¼ã‚¦ã‚§ã‚¢ã§ã‚ã‚‹ SoftEther VPN ãŠã‚ˆã³ã‚ªãƒ¼ãƒ—ンソースã§ã‚ã‚‹ UT-VPN ã‚’æ‹¡å¼µã™ã‚‹ãƒ—ラグインã®å½¢ã§é–‹ç™ºã•ã‚Œã¦ã„ã¾ã™ãŒã€ã“ã‚Œã¯æœ¬ç ”究プロジェクトã«ãŠã„ã¦é–‹ç™ºã•ã‚ŒãŸã‚‚ã®ã§ã‚ã‚Šã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã«ã‚ˆã£ã¦é–‹ç™ºã•ã‚ŒãŸã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“。本研究ã¯ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ãŒä¸»å®°ã€æŽ¨é€²ã¾ãŸã¯ä¿è¨¼ã™ã‚‹ã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+R_NEVER 今後ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„(&S)
+B_WEB VPN Gate 学術実験 &Web サイト...
+IDOK åŒæ„ã™ã‚‹(&A)
+IDCANCEL åŒæ„ã—ãªã„(&D)
+S_BOLD VPN 通信ãŒç¦æ­¢ã•ã‚Œã¦ã„る国・地域ã§ã¯ VPN Gate を使用ã—ãªã„ã§ãã ã•ã„。
+
+
+
+
+###########################################################################
+# #
+# ソフトウェア内ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®æ–‡å­—列データ #
+# #
+###########################################################################
+
+
+# 接続マãƒãƒ¼ã‚¸ãƒ£ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼
+PREFIX CM_MENU
+# [接続] メニュー
+CMD_TOP_CONNECT 接続(&C)
+CMD_CONNECT 接続(&O)\tEnter
+CMD_STATUS 状態ã®è¡¨ç¤º(&S)...\tCtrl+S
+CMD_DISCONNECT 切断(&I)\tCtrl+D
+CMD_DISCONNECT_ALL ã™ã¹ã¦ã®æŽ¥ç¶šã‚’切断(&A)\tCtrl+I
+CMD_RENAME åå‰ã®å¤‰æ›´(&M)\tF2
+CMD_NEW 接続設定ã®æ–°è¦ä½œæˆ(&N)...\tCtrl+N
+CMD_CLONE コピーã®ä½œæˆ(&C)\tCtrl+C
+CMD_SHORTCUT 接続ショートカットã®ä½œæˆ(&H)...
+CMD_EXPORT_ACCOUNT 接続設定ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&F)...
+CMD_IMPORT_ACCOUNT 接続設定ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ(&P)...
+CMD_STARTUP スタートアップ接続ã«è¨­å®š(&T)\tCtrl+T
+CMD_NOSTARTUP スタートアップ接続を解除(&E)
+CMD_RECENT 最近接続ã—㟠&VPN サーãƒãƒ¼
+CMD_DELETE 削除(&D)\tDel
+CMD_PROPERTY プロパティ(&R)...\tAlt+Enter
+CMD_EXIT 接続マãƒãƒ¼ã‚¸ãƒ£ã‚’é–‰ã˜ã‚‹(&O)\tAlt+F4
+CMD_QUIT 接続マãƒãƒ¼ã‚¸ãƒ£ãƒ—ログラムã®çµ‚了(&X)\tAlt+Q
+# [編集] メニュー
+CMD_TOP_EDIT 編集(&E)
+CMD_SELECT_ALL ã™ã¹ã¦é¸æŠž(&A)\tCtrl+A
+CMD_SWITCH_SELECT é¸æŠžã®åˆ‡ã‚Šæ›¿ãˆ(&I)
+# [表示] メニュー
+CMD_TOP_VIEW 表示(&V)
+CMD_STATUSBAR ステータスãƒãƒ¼ã®è¡¨ç¤º(&S)
+CMD_VISTASTYLE Windows Vista / Windows 7 スタイル(&Y)
+CMD_SHOWPORT ãƒãƒ¼ãƒˆç•ªå·ã‚’接続設定一覧ã«è¡¨ç¤º(&P)
+CMD_TRAYICON タスクトレイã®ã‚¢ã‚¤ã‚³ãƒ³ã®è¡¨ç¤º(&T)
+CMD_ICON アイコン(&I)
+CMD_DETAIL 詳細(&D)
+CMD_GRID 罫線を表示(&G)
+CMD_REFRESH 最新ã®çŠ¶æ…‹ã«æ›´æ–°(&R)\tF5
+# [仮想 LAN] メニュー
+CMD_TOP_VLAN 仮想 &LAN
+CMD_NEW_VLAN æ–°è¦ä»®æƒ³ LAN カードã®ä½œæˆ(&C)...\tCtrl+L
+CMD_ENABLE_VLAN 仮想 LAN カードã®æœ‰åŠ¹åŒ–(&E)\tCtrl+E
+CMD_DISABLE_VLAN 仮想 LAN カードã®ç„¡åŠ¹åŒ–(&S)\tCtrl+B
+CMD_DELETE_VLAN 仮想 LAN カードã®å‰Šé™¤(&D)\tDel
+CMD_REINSTALL ドライãƒã®å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«(&U)...\tCtrl+U
+CMD_WINNET &Windows ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã®è¨­å®š...\tCtrl+W
+# [スマートカード] メニュー
+CMD_TOP_SECURE スマートカード(&S)
+CMD_SECURE_MANAGER スマートカードマãƒãƒ¼ã‚¸ãƒ£(&M)...\tCtrl+G
+CMD_SECURE_SELECT 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®é¸æŠž(&S)...
+# [ツール] メニュー
+CMD_TOP_TOOL ツール(&T)
+CMD_PASSWORD パスワードã®è¨­å®š(&P)...\tCtrl+P
+CMD_TRUST ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®ç®¡ç†(&T)...\tCtrl+R
+CMD_NETIF ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ‡ãƒã‚¤ã‚¹ã®çŠ¶æ…‹(&N)...
+CMD_TCPIP TCP/IP 最é©åŒ–ユーティリティ(&U)...
+CMD_MMCSS Windows Vista / Windows 7 / Windows 8 ã®ãŸã‚ã®æœ€é©åŒ–機能(&V)...
+CMD_TRAFFIC 通信スループット測定ツール(&R)...\tCtrl+Q
+CMD_CM_SETTING 動作モードã®å¤‰æ›´(&M)...
+CMD_LANGUAGE 表示言語ã®å¤‰æ›´(&L)...
+CMD_OPTION オプション設定(&O)...\tCtrl+O
+# [音声ガイド] メニュー
+CMD_TOP_VOICE 音声ガイド(&O)
+CMD_VOIDE_NONE 音声ガイド OFF(&D)
+CMD_VOICE_NORMAL 標準ã®éŸ³å£°ã‚¬ã‚¤ãƒ‰(&N)
+CMD_VOICE_ODD 拡張音声ガイド(&O)
+# [ヘルプ] メニュー
+CMD_TOP_HELP ヘルプ(&H)
+CMD_ABOUT ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+###########################################################################
+# #
+# コマンドプロンプトã®æ–‡å­—列データ #
+# #
+###########################################################################
+
+PREFIX NULL
+
+# コンソールシステム全般系
+CON_INFILE_ERROR エラー: 指定ã•ã‚ŒãŸå…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ« "%s" ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“。
+CON_OUTFILE_ERROR エラー: 指定ã•ã‚ŒãŸå‡ºåŠ›ãƒ•ã‚¡ã‚¤ãƒ« "%s" を作æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+CON_INFILE_START ファイル "%s" ã«è¨˜è¿°ã•ã‚Œã¦ã„るコマンドをã€ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã‹ã‚‰ã®å…¥åŠ›ã®ä»£ã‚ã‚Šã«ä½¿ç”¨ã—ã¾ã™ã€‚
+CON_OUTFILE_START ç”»é¢ã«å‡ºåŠ›ã•ã‚ŒãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ã€ãƒ•ã‚¡ã‚¤ãƒ« "%s" ã«ã‚‚ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+CON_USER_CANCEL [EOF]
+CON_UNKNOWN_CMD "%S": コマンドãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。\nHELP コマンドã§ä½¿ç”¨ã§ãるコマンド一覧を表示ã§ãã¾ã™ã€‚
+CON_AMBIGIOUS_CMD "%S": コマンドãŒæ›–昧ã§ã™ã€‚
+CON_AMBIGIOUS_CMD_1 指定ã•ã‚ŒãŸã‚³ãƒžãƒ³ãƒ‰åã¯ã€æ¬¡ã®è¤‡æ•°ã®ã‚³ãƒžãƒ³ãƒ‰ã«ä¸€è‡´ã—ã¾ã™:
+CON_AMBIGIOUS_CMD_2 より厳密ã«ã‚³ãƒžãƒ³ãƒ‰åを指定ã—ç›´ã—ã¦ãã ã•ã„。
+CON_INVALID_PARAM パラメータ "/%S" ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™ã€‚コマンド "%S" ã§ã¯ãã®ã‚ˆã†ãªãƒ‘ラメータã¯æŒ‡å®šã§ãã¾ã›ã‚“。詳ã—ã㯠"%S /HELP" ã¨å…¥åŠ›ã—ã¦ä½¿ç”¨ã§ãるパラメータ一覧を確èªã—ã¦ãã ã•ã„。
+CON_AMBIGIOUS_PARAM "/%S": パラメータåãŒæ›–昧ã§ã™ã€‚
+CON_AMBIGIOUS_PARAM_1 指定ã•ã‚ŒãŸãƒ‘ラメータåã¯ã€ã‚³ãƒžãƒ³ãƒ‰ "%S" ã®ãƒ‘ラメータã¨ã—ã¦æŒ‡å®šå¯èƒ½ãªæ¬¡ã®è¤‡æ•°ã®ãƒ‘ラメータã«ä¸€è‡´ã—ã¾ã™:
+CON_AMBIGIOUS_PARAM_2 より厳密ã«ãƒ‘ラメータåを指定ã—ç›´ã—ã¦ãã ã•ã„。
+
+
+# ä¸æ˜Žãªã‚³ãƒžãƒ³ãƒ‰
+CMD_UNKNOWM ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«é–¢ã™ã‚‹èª¬æ˜Žã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_UNKNOWN_HELP ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«é–¢ã™ã‚‹è©³ç´°ãªèª¬æ˜Žã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å‹•ä½œã«ã¤ã„ã¦è©³ã—ã知りãŸã„å ´åˆã¯ã€ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚„オンラインドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。
+CMD_UNKNOWN_ARGS コマンドã®å®Ÿè¡Œä¾‹ã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_UNKNOWN_PARAM ã“ã®ãƒ‘ラメータã«é–¢ã™ã‚‹èª¬æ˜Žã¯ã‚ã‚Šã¾ã›ã‚“。
+
+
+# コンソールシステム内部ã§ä½¿ç”¨ã—ã¦ã„る文字列
+CMD_HELP_1 下記㮠%u 個ã®ã‚³ãƒžãƒ³ãƒ‰ãŒä½¿ç”¨ã§ãã¾ã™:
+CMD_HELP_2 ãã‚Œãžã‚Œã®ã‚³ãƒžãƒ³ãƒ‰ã®ä½¿ç”¨æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€"コマンドå /?" ã¨å…¥åŠ›ã™ã‚‹ã¨ãƒ˜ãƒ«ãƒ—ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_EVAL_MIN_MAX 値㯠%u 以上 %u 以下ã®æ•´æ•°ã§æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_PROMPT 値を入力ã—ã¦ãã ã•ã„ :
+CMD_EVAL_NOT_EMPTY 空白を指定ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_EVAL_SAFE 使用ã§ããªã„文字ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚
+CMD_EVAL_INT 1 以上ã®æ•´æ•°ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_HELP_TITLE コマンド "%S" ã®ãƒ˜ãƒ«ãƒ—
+CMD_HELP_DESCRIPTION [目的]
+CMD_HELP_USAGE [使用方法]
+CMD_HELP_HELP [説明]
+CMD_HELP_ARGS [パラメータ]
+CMD_PROPMT_PORT ãƒãƒ¼ãƒˆç•ªå·ã‚’入力ã—ã¦ãã ã•ã„ :
+CMD_EVAL_PORT ãƒãƒ¼ãƒˆç•ªå·ãŒä¸æ­£ã§ã™ã€‚ãƒãƒ¼ãƒˆç•ªå·ã¯ 1 以上 65535 以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_CT_STD_COLUMN_1 é …ç›®
+CMD_CT_STD_COLUMN_2 値
+CMD_CT_STD_COLUMN_3 説明
+CMD_PARSE_IP_SUBNET_ERROR_1_6 "IPv6 アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯" ã®å½¢å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。\nIPv6 アドレス㯠2001:200:0:1:: ã®ã‚ˆã†ã« 16 進数をコロンã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã¯ ffff:ffff:ffff:ffff:: ã®ã‚ˆã†ã« IPv6 å½¢å¼ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€64 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚\nå˜ä¸€ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ã¾ãŸã¯ 128 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚\n(例)\n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/128\n\n
+CMD_PARSE_IP_SUBNET_ERROR_1 "IPv4 アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯" ã®å½¢å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。\nIPv4 アドレス㯠192.168.0.1 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã¯ 255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚\nå˜ä¸€ã®ãƒ›ã‚¹ãƒˆã‚’指定ã™ã‚‹ã«ã¯ã€ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’ 255.255.255.255 ã¾ãŸã¯ 32 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚\n(例)\n192.168.0.1/24\n192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+CMD_PARSE_IP_SUBNET_ERROR_2 指定ã•ã‚ŒãŸ IP アドレスã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_PARSE_IP_SUBNET_ERROR_3 指定ã•ã‚ŒãŸ IP アドレスã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ—レフィックスアドレスã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_EVAL_DATE_TIME_FAILED 日付ã¨æ™‚刻ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚\n"2005/10/08 19:30:00" ã®ã‚ˆã†ã«ã€å¹´ãƒ»æœˆãƒ»æ—¥ãƒ»æ™‚・分・秒 ã® 6 個ã®æ•´æ•°ã‚’スペースã€ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã¾ãŸã¯ã‚³ãƒ­ãƒ³ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¦ãã ã•ã„。年㯠4 æ¡ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_PARSE_IP_MASK_ERROR_1_6 "IPv6 アドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。\nIPv6 アドレス㯠2001:200:0:1:: ã®ã‚ˆã†ã« 16 進数をコロンã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠ffff:ffff:ffff:ffff:: ã®ã‚ˆã†ã« IPv6 å½¢å¼ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€64 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚\nå˜ä¸€ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ã¾ãŸã¯ 128 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚\n(例)\n2001:200:0:1::/64\n2001:200:0:1::/ffff:ffff:ffff:ffff::\n2001:200:0:1::5/128\n\n
+CMD_PARSE_IP_MASK_ERROR_1 "IPv4 アドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。\nIPv4 アドレス㯠192.168.0.1 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚\nå˜ä¸€ã®ãƒ›ã‚¹ãƒˆã‚’指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ 255.255.255.255 ã¾ãŸã¯ 32 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚\n(例)\n192.168.0.1/24\n192.168.0.1/255.255.255.0\n192.168.0.5/255.255.255.255\n\n
+
+
+# 共通メッセージ
+CMD_MSG_INVALID_HOSTNAME ホストåã®æŒ‡å®šãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。
+CMD_MSG_OK コマンドã¯æ­£å¸¸ã«çµ‚了ã—ã¾ã—ãŸã€‚
+CMD_MSG_ALLOW 許å¯
+CMD_MSG_DENY ç¦æ­¢
+CMD_MSG_INFINITE 無制é™
+CMD_MSG_ENABLE 有効
+CMD_MSG_DISABLE 無効
+CMD_MSG_LOAD_CERT_FAILED 指定ã•ã‚ŒãŸ X.509 証明書ファイルを読ã¿è¾¼ã‚ã¾ã›ã‚“。
+CMD_MSG_SAVE_CERT_FAILED X.509 証明書ファイルã®æ›¸ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_ACCOUNT_COLUMN_NAME 接続設定å
+CMD_ACCOUNT_COLUMN_HOSTNAME 接続先 VPN Server ã®ãƒ›ã‚¹ãƒˆå
+CMD_ACCOUNT_COLUMN_PORT 接続先 VPN Server ã®ãƒãƒ¼ãƒˆç•ªå·
+CMD_ACCOUNT_COLUMN_HUBNAME 接続先 VPN Server ã®ä»®æƒ³ HUB å
+CMD_ACCOUNT_COLUMN_PROXY_TYPE 経由ã™ã‚‹ãƒ—ロキシサーãƒãƒ¼ã®ç¨®é¡ž
+CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆå
+CMD_ACCOUNT_COLUMN_PROXY_PORT プロキシサーãƒãƒ¼ã®ãƒãƒ¼ãƒˆç•ªå·
+CMD_ACCOUNT_COLUMN_PROXY_USERNAME プロキシサーãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å
+CMD_ACCOUNT_COLUMN_SERVER_CERT_USE サーãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼
+CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME 登録ã•ã‚Œã¦ã„るサーãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸
+CMD_ACCOUNT_COLUMN_DEVICE_NAME 接続ã«ä½¿ç”¨ã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹å
+CMD_ACCOUNT_COLUMN_AUTH_TYPE èªè¨¼ã®ç¨®é¡ž
+CMD_ACCOUNT_COLUMN_AUTH_USERNAME ユーザーå
+CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME èªè¨¼ã«ä½¿ç”¨ã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸
+CMD_ACCOUNT_COLUMN_NUMTCP VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+CMD_ACCOUNT_COLUMN_TCP_INTERVAL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“éš”
+CMD_ACCOUNT_COLUMN_TCP_TTL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½
+CMD_ACCOUNT_COLUMN_TCP_HALF åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã®ä½¿ç”¨
+CMD_ACCOUNT_COLUMN_ENCRYPT SSL ã«ã‚ˆã‚‹æš—å·åŒ–
+CMD_ACCOUNT_COLUMN_COMPRESS データ圧縮
+CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER ブリッジ / ルータモードã§æŽ¥ç¶š
+CMD_ACCOUNT_COLUMN_MONITOR モニタリングモードã§æŽ¥ç¶š
+CMD_ACCOUNT_COLUMN_NO_TRACKING ルーティングテーブルを調整ã—ãªã„
+CMD_ACCOUNT_COLUMN_QOS_DISABLE QoS 制御機能を使用ã—ãªã„
+
+
+# デãƒãƒƒã‚°æƒ…報書ã出ã—コマンド
+CMD_DEBUG_SOFTNAME SoftEther VPN デãƒãƒƒã‚°æƒ…å ±åŽé›†ãƒ„ール
+CMD_DEBUG_PRINT SoftEther VPN デãƒãƒƒã‚°æƒ…å ±åŽé›†ãƒ„ール\r\n\r\n
+CMD_DEBUG_NOT_2000 ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ Windows 2000 以é™ã§ã®ã¿ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_DEBUG_NOT_ADMIN ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’èµ·å‹•ã™ã‚‹ã«ã¯ã€Windows ã«ç®¡ç†è€…権é™ã§ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_DEBUG_UAC_FAILED 管ç†è€…権é™ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_DEBUG_SAVE_TITLE デãƒãƒƒã‚°æƒ…å ±ã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¦ãã ã•ã„
+CMD_DEBUG_OK デãƒãƒƒã‚°æƒ…報ファイルを "%s" ã«ä¿å­˜ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’サãƒãƒ¼ãƒˆæ‹…当者ã®æŒ‡ç¤ºã«å¾“ã£ã¦ã‚µãƒãƒ¼ãƒˆæ‹…当者ã«ãŠé€ã‚Šãã ã•ã„。\r\nãªãŠã€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ãŠé€ã‚Šã„ãŸã ãå‰ã«å¿…ãšãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容をã”確èªãã ã•ã„。\r\nã‚‚ã—ファイルã®å†…容ã«ç§˜å¯†æƒ…å ±ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã§ã€ãã®æƒ…報をファイルã®é€ä»˜å…ˆã®æ‹…当者ã«é–‹ç¤ºã—ãŸããªã„ã¨ãŠè€ƒãˆã®å ´åˆã¯ã€å½“該秘密情報ã®éƒ¨åˆ†ã®ã¿ã‚’ã‚ãªãŸã®è²¬ä»»ã«ãŠã„ã¦æ‰‹å‹•ã§é™¤åŽ»ã—ã¦ã‹ã‚‰å†åº¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ ZIP ã§åœ§ç¸®ã—ãŠé€ã‚Šãã ã•ã„。\r\n\r\n秘密情報ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã«ã‚‚é–¢ã‚らãšã€ãれを削除ã›ãšã«ã‚µãƒãƒ¼ãƒˆæ‹…当者ã«ãŠé€ã‚Šã„ãŸã ã„ãŸå ´åˆã€å½“該秘密情報をサãƒãƒ¼ãƒˆæ‹…当者ã«é–‹ç¤ºã™ã‚‹ã“ã¨ã«ã¤ã„ã¦åŒæ„ã•ã‚ŒãŸã‚‚ã®ã¨ã¿ãªã•ã‚Œã¾ã™ã®ã§ã”注æ„ãã ã•ã„。
+CMD_DEBUG_NG デãƒãƒƒã‚°æƒ…報ファイルを "%s" ã«ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+
+
+# TEST コマンド
+CMD_TEST 実験的ãªå‹•ä½œã‚’è¡Œã„ã¾ã™ã€‚
+CMD_TEST_HELP テストコマンドã§ã™ã€‚実験的ãªå‹•ä½œã‚’è¡Œã„ã¾ã™ã€‚Test コマンドã¯ã„ãã¤ã‹ã®å¼•æ•°ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã„ãã¤ã‹ã®å¼•æ•°ã¯çœç•¥ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_TEST_ARGS Test [/A1:a_str] [/A2:b_str] [/A3:int_value]
+CMD_TEST_A1 パラメータ A1 を指定ã—ã¾ã™ã€‚çœç•¥ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_TEST_A2 パラメータ A2 を指定ã—ã¾ã™ã€‚çœç•¥ã™ã‚‹ã¨ã€å®Ÿè¡Œæ™‚ã«ãƒ‘ラメータ A2 を入力ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚空白を指定ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_TEST_A3 数値を指定ã—ã¾ã™ã€‚1 以上 100 以下ã®æ•´æ•°ã‚’指定ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ãれ以外ã®æ•´æ•°ã‚’指定ã—ãŸå ´åˆã¯ã€ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_TEST_EVAL_A2 パラメータ A2 ã«ç©ºç™½ã‚’指定ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_IP_EVAL_FAILED IP アドレスã®æŒ‡å®šãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。
+CMD_HOSTPORT_EVAL_FAILED ホストåã¨ãƒãƒ¼ãƒˆç•ªå·ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚\nホストå:ãƒãƒ¼ãƒˆç•ªå· ã¾ãŸã¯ IPアドレス:ãƒãƒ¼ãƒˆç•ªå· ã®ã‚ˆã†ãªå½¢å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_PORTLIST_EVAL_FAILED ãƒãƒ¼ãƒˆç•ªå·ã®ä¸€è¦§ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚\nãƒãƒ¼ãƒˆç•ªå·ã¯å°‘ãªãã¨ã‚‚ 1 ã¤ä»¥ä¸Šè¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã€è¤‡æ•°å€‹è¨­å®šã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚ãã®å ´åˆã¯ã€"443,992,8888" ã®ã‚ˆã†ã«ã‚«ãƒ³ãƒžè¨˜å·ã§åŒºåˆ‡ã£ã¦ãã ã•ã„。
+CMD_PROTOCOL_EVAL_FAILED プロトコルã®æŒ‡å®šãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。プロトコル㯠ip, tcp, udp, icmpv4, icmpv6 ã¾ãŸã¯ãƒ—ãƒ­ãƒˆã‚³ãƒ«ç•ªå· (0 ã‹ã‚‰ 255 ã¾ã§) を指定ã—ã¦ãã ã•ã„。
+CMD_PORT_RANGE_EVAL_FAILED ãƒãƒ¼ãƒˆç•ªå·ã¾ãŸã¯ãƒãƒ¼ãƒˆç•ªå·ã®ç¯„囲ã®æŒ‡å®šãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。ãƒãƒ¼ãƒˆç•ªå·ã‚’ 1 ã¤ã ã‘指定ã™ã‚‹å ´åˆã¯ãã®ãƒãƒ¼ãƒˆç•ªå·ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。複数ã®ãƒãƒ¼ãƒˆã‚’指定ã™ã‚‹å ´åˆã¯ç¯„囲ã®é–‹å§‹ãƒãƒ¼ãƒˆç•ªå·ã¨çµ‚了ãƒãƒ¼ãƒˆç•ªå·ã‚’ 80-443 ã®ã‚ˆã†ã«ãƒã‚¤ãƒ•ãƒ³ã§ã¤ãªã„ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_TCP_CONNECTION_STATE_EVAL_FAILED TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’指定ã™ã‚‹å ´åˆã¯ã€"Established" ã¾ãŸã¯ "Unestablished" を指定ã—ã¦ãã ã•ã„。プロトコルã®æŒ‡å®šã§ tcp ã‚’é¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_MAC_ADDRESS_AND_MASK_EVAL_FAILED MAC アドレスã¨ãƒžã‚¹ã‚¯ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚MAC アドレスã¨ãƒžã‚¹ã‚¯ã«ã¯ã€16 進数ã§æŒ‡å®šã—ã¦ãã ã•ã„。"-" ã‚„ ":" ã®åŒºåˆ‡ã‚ŠãŒä½¿ç”¨å‡ºæ¥ã¾ã™ãŒã€çœç•¥ã‚‚ã§ãã¾ã™ã€‚例ãˆã° "00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-FF" ã®ã‚ˆã†ã«æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_EXEC_MSG_NAME %S コマンド - %s
+CMD_ID ID
+CMD_FILE_NOT_FOUND 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ« "%s" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+CMD_FILE_NAME_EMPTY ファイルåãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+CMD_SAVECERTPATH X.509 証明書ã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_SAVECERT_FAILED 証明書ファイルã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_SAVEKEYPATH 秘密éµã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_SAVEKEY_FAILED 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_SAVEFILE_FAILED ファイルã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_LOADFILE_FAILED ファイルã®ã‚ªãƒ¼ãƒ—ンã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_LOADCERTPATH 読ã¿è¾¼ã‚€ X.509 証明書ã®ãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_LOADCERT_FAILED 証明書ファイルã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_LOADKEYPATH 読ã¿è¾¼ã‚€ç§˜å¯†éµã®ãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_LOADKEY_FAILED 秘密éµãƒ•ã‚¡ã‚¤ãƒ«ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_LOADKEY_ENCRYPTED_1 指定ã•ã‚ŒãŸç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã¯ãƒ‘スフレーズã«ã‚ˆã£ã¦ä¿è­·ã•ã‚Œã¦ã„ã¾ã™ã€‚
+CMD_LOADKEY_ENCRYPTED_2 パスフレーズを入力ã—ã¦ãã ã•ã„:
+CMD_LOADKEY_ENCRYPTED_3 パスフレーズãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚
+CMD_KEYPAIR_FAILED 指定ã•ã‚ŒãŸ X.509 証明書ã¨ç§˜å¯†éµã®çµ„åˆã›ã¯æ­£ã—ãã‚ã‚Šã¾ã›ã‚“。証明書ã¨ãã®è¨¼æ˜Žæ›¸ã«å¯¾å¿œã—ãŸç§˜å¯†éµãŒå¿…è¦ã§ã™ã€‚
+CMD_CERT_NOT_EXISTS 証明書ã¯ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+CMD_NO_SETTINGS ï¼
+CMD_DISCONNECTED_MSG \n--- エラー ---\n\n管ç†å¯¾è±¡ã®ãƒ›ã‚¹ãƒˆã¨ã®é€šä¿¡ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚ã“ã®å¾Œã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ã‚‚エラーã«ãªã‚Šã¾ã™ã€‚\n\n管ç†å¯¾è±¡ã®ãƒ›ã‚¹ãƒˆã«å†æŽ¥ç¶šã™ã‚‹ã«ã¯ã€EXIT ã¨å…¥åŠ›ã—ã¦ä¸€åº¦ãƒ—ロンプトã‹ã‚‰æŠœã‘ã¦ã‹ã‚‰å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\n\n
+
+
+# VPNCMD コマンド
+CMD_VPNCMD SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£
+CMD_VPNCMD_HELP vpncmd プログラムã¯ã€SoftEther VPN ソフトウェアをコマンドラインã§ç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãるユーティリティã§ã™ã€‚vpncmd を使用ã™ã‚‹ã¨ã€ãƒ­ãƒ¼ã‚«ãƒ«ã¾ãŸã¯ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Clientã€VPN Serverã€ãŠã‚ˆã³ VPN Bridge ã«æŽ¥ç¶šã—ã¦ãれらã®ã‚µãƒ¼ãƒ“スを管ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€VPN Tools モードを使用ã—ã¦ã€VPN Server ã‚„ VPN Client ã«æŽ¥ç¶šã—ã¦ã„ãªãã¦ã‚‚使用ã§ãる証明書ã®ä½œæˆã‚„速度測定機能ãªã©ã‚’呼ã³å‡ºã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚\nvpncmd ã§ã¯ã€/IN ãŠã‚ˆã³ /OUT パラメータã¨ã—ã¦ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ãŸå ´åˆã€å®Ÿè¡Œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã‚’列挙ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã«å¾“ã£ã¦ã‚³ãƒžãƒ³ãƒ‰ã‚’一括実行ã—ãŸã‚Šã€å®Ÿè¡Œçµæžœã‚’ファイルã«æ›¸ã出ã™ã“ã¨ãŒã§ãã¾ã™ã€‚通常ã€vpncmd ã‚’èµ·å‹•ã—ãŸå ´åˆã¯ã‚³ãƒžãƒ³ãƒ‰ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ãŒã€/IN パラメータã§å…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ãŸå ´åˆã¯å…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®ã™ã¹ã¦ã®è¡Œã®å®Ÿè¡ŒãŒå®Œäº†ã™ã‚‹ã¨è‡ªå‹•çš„ã«çµ‚了ã—ã¾ã™ã€‚ã¾ãŸã€/CMD パラメータã§å®Ÿè¡Œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã‚’指定ã—ãŸå ´åˆã€ãã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡ŒãŒå®Œäº†ã™ã‚‹ã¨è‡ªå‹•çš„ã«çµ‚了ã—ã¾ã™ã€‚/IN パラメータ㨠/CMD パラメータã¯åŒæ™‚ã«æŒ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。vpncmd プログラムã®çµ‚了コードã¯ã€æœ€å¾Œã«å®Ÿè¡Œã—ãŸã‚³ãƒžãƒ³ãƒ‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ (æˆåŠŸã—ãŸå ´åˆã¯ 0) ã¨ãªã‚Šã¾ã™ã€‚\nWindows 環境ã§ã¯ã€ç®¡ç†è€…権é™ã§ 1 度以上 vpncmd ã‚’èµ·å‹•ã™ã‚‹ã¨ã€æ¬¡å›žã‹ã‚‰ Windows ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ—ロンプトや [ファイルåを指定ã—ã¦å®Ÿè¡Œ] ã‚’é–‹ã„㦠vpncmd ã¨å…¥åŠ›ã™ã‚‹ã ã‘㧠vpncmd ã‚’èµ·å‹•ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚UNIX システムã§åŒæ§˜ã®ã“ã¨ã‚’実ç¾ã™ã‚‹ãŸã‚ã«ã¯ã€PATH 環境変数を手動ã§é©åˆ‡ã«è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_VPNCMD_ARGS vpncmd [host:port] [/CLIENT|/SERVER|/TOOLS] [/HUB:hub] [/ADMINHUB:adminhub] [/PASSWORD:password] [/IN:infile] [/OUT:outfile] [/CMD commands...]
+CMD_VPNCMD_[host:port] [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã®ãƒ‘ラメータを指定ã™ã‚‹ã¨ã€ãã®ãƒ›ã‚¹ãƒˆã«è‡ªå‹•çš„ã«æŽ¥ç¶šã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€æŽ¥ç¶šå…ˆã‚’入力ã™ã‚‹ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚VPN Client ã«æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€ãƒãƒ¼ãƒˆç•ªå·ã¯æŒ‡å®šã§ãã¾ã›ã‚“。
+CMD_VPNCMD_CLIENT VPN Client ã«æŽ¥ç¶šã—ã¦ç®¡ç†ã‚’è¡Œã„ã¾ã™ã€‚/SERVER ã¨å…±ã«æŒ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_VPNCMD_SERVER VPN Server ã¾ãŸã¯ VPN Bridge ã«æŽ¥ç¶šã—ã¦ç®¡ç†ã‚’è¡Œã„ã¾ã™ã€‚/CLIENT ã¨å…±ã«æŒ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_VPNCMD_TOOLS VPN Tools ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã§ãるプロンプトを表示ã—ã¾ã™ã€‚ã“ã‚Œã«ã¯ã€è¨¼æ˜Žæ›¸ç°¡æ˜“作æˆãƒ„ール (MakeCert コマンド) ãŠã‚ˆã³é€šä¿¡é€Ÿåº¦æ¸¬å®šãƒ„ール (SpeedTest コマンド) ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚
+CMD_VPNCMD_HUB VPN Server ã«ã€Œä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã€ã§æŽ¥ç¶šã™ã‚‹éš›ã®ä»®æƒ³ HUB å 'hub' を指定ã—ã¾ã™ã€‚ホストåを指定ã—㦠/HUB パラメータを指定ã—ãªã„å ´åˆã¯ã€ã€Œã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã€ã§æŽ¥ç¶šã—ã¾ã™ã€‚
+CMD_VPNCMD_ADMINHUB VPN Server ã«æŽ¥ç¶šã—ãŸå¾Œã«è‡ªå‹•çš„ã«é¸æŠžã™ã‚‹ä»®æƒ³ HUB å 'adminhub' を指定ã—ã¾ã™ã€‚/HUB パラメータを指定ã—ãŸå ´åˆã¯ã€ãã®ä»®æƒ³ HUB ãŒè‡ªå‹•çš„ã«é¸æŠžã•ã‚Œã¾ã™ã®ã§ã€æŒ‡å®šã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_VPNCMD_PASSWORD 接続ã™ã‚‹éš›ã«ç®¡ç†ãƒ‘スワードãŒå¿…è¦ãªå ´åˆã¯ã€ãƒ‘スワード 'password' を指定ã—ã¾ã™ã€‚パスワードãŒæŒ‡å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€å…¥åŠ›ã™ã‚‹ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_VPNCMD_IN 接続ãŒå®Œäº†ã—ãŸå¾Œã«è‡ªå‹•çš„ã«å®Ÿè¡Œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã®ä¸€è¦§ãŒè¨˜è¼‰ã•ã‚ŒãŸãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«å 'infile' を指定ã—ã¾ã™ã€‚/IN パラメータãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«å†…ã®ã™ã¹ã¦ã®è¡Œã®å®Ÿè¡ŒãŒå®Œäº†ã—ãŸå¾Œã«è‡ªå‹•çš„ã« vpncmd プログラムã¯çµ‚了ã—ã¾ã™ã€‚ファイルã«å¤šãƒã‚¤ãƒˆæ–‡å­—ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€Unicode (UTF-8) ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚/CMD ã¨å…±ã«æŒ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ (/CMD ã¨å…±ã«æŒ‡å®šã—ãŸå ´åˆã¯ /IN ã¯ç„¡è¦–ã•ã‚Œã¾ã™)。
+CMD_VPNCMD_OUT ç”»é¢ã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ—ロンプトã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã€ã‚¨ãƒ©ãƒ¼ã€å®Ÿè¡Œçµæžœãªã©ã®ã™ã¹ã¦ã®æ–‡å­—列を書ã出ã™ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«å 'outfile' を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚æ—¢ã«å­˜åœ¨ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ãŸå ´åˆã€ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容ã¯ä¸Šæ›¸ãã•ã‚Œã¾ã™ã®ã§ã”注æ„ãã ã•ã„。多ãƒã‚¤ãƒˆæ–‡å­—ã¯ã€Unicode (UTF-8) ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦è¨˜éŒ²ã•ã‚Œã¾ã™ã€‚
+CMD_VPNCMD_CMD /CMD ã®å¾Œã«ä»»æ„ã®ã‚³ãƒžãƒ³ãƒ‰ 'commands...' を記述ã™ã‚‹ã¨ã€æŽ¥ç¶šãŒå®Œäº†ã—ãŸå¾Œã«ãã®ã‚³ãƒžãƒ³ãƒ‰ãŒå®Ÿè¡Œã•ã‚Œã€ãã®å¾Œ vpncmd プログラムã¯çµ‚了ã—ã¾ã™ã€‚/IN ã¨å…±ã«æŒ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ (/IN ã¨å…±ã«æŒ‡å®šã—ãŸå ´åˆã¯ /IN ã¯ç„¡è¦–ã•ã‚Œã¾ã™)。/CMD パラメータã¯ä»–ã®ã™ã¹ã¦ã® vpncmd ã®ãƒ‘ラメータよりも後ã«æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_VPNCMD_CSV å„コマンドãŒçµæžœã‚’ CSV å½¢å¼ã§å‡ºåŠ›ã™ã‚‹ã‚ˆã†ã«ã—ã¾ã™ã€‚ä»–ã®ãƒ—ログラムã«ã‚ˆã£ã¦å‡ºåŠ›çµæžœã‚’自動処ç†ã™ã‚‹éš›ã«ä¾¿åˆ©ã§ã™ã€‚
+CMD_VPNCMD_CS_1 vpncmd プログラムを使ã£ã¦ä»¥ä¸‹ã®ã“ã¨ãŒã§ãã¾ã™ã€‚\n\n1. VPN Server ã¾ãŸã¯ VPN Bridge ã®ç®¡ç†\n2. VPN Client ã®ç®¡ç†\n3. VPN Tools コマンドã®ä½¿ç”¨ (証明書作æˆã‚„通信速度測定)\n\n
+CMD_VPNCMD_CS_2 1 - 3 ã‚’é¸æŠž:
+CMD_VPNCMD_HOST_1 接続先㮠VPN Server ã¾ãŸã¯ VPN Bridge ãŒå‹•ä½œã—ã¦ã„るコンピュータ㮠IP アドレスã¾ãŸã¯ãƒ›ã‚¹ãƒˆåを指定ã—ã¦ãã ã•ã„。\n'ホストå:ãƒãƒ¼ãƒˆç•ªå·' ã®å½¢å¼ã§æŒ‡å®šã™ã‚‹ã¨ã€ãƒãƒ¼ãƒˆç•ªå·ã‚‚指定ã§ãã¾ã™ã€‚\n(ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ãªã„å ´åˆã¯ 443 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚)\n何も入力ã›ãšã« Enter を押ã™ã¨ã€localhost (ã“ã®ã‚³ãƒ³ãƒ”ュータ) ã®ãƒãƒ¼ãƒˆ 443 ã«æŽ¥ç¶šã—ã¾ã™ã€‚
+CMD_VPNCMD_HOST_2 接続先㮠VPN Client ãŒå‹•ä½œã—ã¦ã„るコンピュータ㮠IP アドレスã¾ãŸã¯ãƒ›ã‚¹ãƒˆåを指定ã—ã¦ãã ã•ã„。\n何も入力ã›ãšã« Enter を押ã™ã¨ã€localhost (ã“ã®ã‚³ãƒ³ãƒ”ュータ) ã«æŽ¥ç¶šã—ã¾ã™ã€‚
+CMD_VPNCMD_HOST_3 接続先ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレス:
+CMD_VPNCMD_HUB_1 サーãƒãƒ¼ã«ä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB åを入力ã—ã¦ãã ã•ã„。\nサーãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ã€ä½•ã‚‚入力ã›ãšã« Enter を押ã—ã¦ãã ã•ã„。
+CMD_VPNCMD_HUB_2 接続先ã®ä»®æƒ³ HUB åを入力:
+CMD_VPNCMD_ABOUT SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ (vpncmd コマンド)\n%S\n%S\nCopyright (c) SoftEther VPN Project. All Rights Reserved.\n
+CMD_VPNCMD_PASSWORD_1 アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚パスワードãŒé–“é•ã£ã¦ã„ã‚‹ã‹ã€æŽ¥ç¶šã™ã‚‹ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ãŒæ­£ã—ããªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚パスワードをもã†ä¸€åº¦å…¥åŠ›ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚キャンセルã™ã‚‹å ´åˆã¯ã€Ctrl + D を押ã—ã¦ãã ã•ã„。
+CMD_VPNCMD_PASSWORD_2 パスワード:
+CMD_VPNCMD_ERROR エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚(エラーコード: %u)\n%s
+CMD_VPNCMD_SERVER_CONNECTED VPN Server "%S" (ãƒãƒ¼ãƒˆ %u) ã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+CMD_VPNCMD_SERVER_CONNECTED_1 VPN Server 全体ã®ç®¡ç†æ¨©é™ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_VPNCMD_SERVER_CONNECTED_2 VPN Server 内ã®ä»®æƒ³ HUB '%S' ã«å¯¾ã™ã‚‹ç®¡ç†æ¨©é™ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_VPNCMD_CLIENT_NO_REMODE 接続先㮠VPN Client サービスã¯ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータã‹ã‚‰ã®ç®¡ç†æŽ¥ç¶šã‚’許å¯ã—ã¦ã„ã¾ã›ã‚“。VPN Client ãŒå‹•ä½œã—ã¦ã„るコンピュータ上ã§ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã¾ãŸã¯ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã€localhost ã«å¯¾ã—ã¦æŽ¥ç¶šã—ã¦ãã ã•ã„。
+CMD_VPNCMD_PWPROMPT_0 パスワードを入力ã—ã¦ãã ã•ã„。キャンセルã™ã‚‹ã«ã¯ Ctrl+D キーを押ã—ã¦ãã ã•ã„。
+CMD_VPNCMD_PWPROMPT_1 パスワード:
+CMD_VPNCMD_PWPROMPT_2 確èªå…¥åŠ› :
+CMD_VPNCMD_PWPROMPT_3 入力ã•ã‚ŒãŸãƒ‘スワードã¨ç¢ºèªå…¥åŠ›ãŒç•°ãªã‚Šã¾ã™ã€‚ã‚‚ã†ä¸€åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。
+CMD_VPNCMD_CLIENT_CONNECTED VPN Client "%S" ã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚
+CMD_VPNCMD_TOOLS_CONNECTED VPN Tools ã‚’èµ·å‹•ã—ã¾ã—ãŸã€‚HELP ã¨å…¥åŠ›ã™ã‚‹ã¨ã€ä½¿ç”¨ã§ãるコマンド一覧ãŒè¡¨ç¤ºã§ãã¾ã™ã€‚
+
+
+######################################################
+# #
+# ã“ã“ã‹ã‚‰ä¸‹ã¯ VPN Server 用ã®ç®¡ç†ã‚³ãƒžãƒ³ãƒ‰ #
+# #
+######################################################
+
+
+
+# About コマンド
+CMD_About ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã®è¡¨ç¤º
+CMD_About_HELP ã“ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を表示ã—ã¾ã™ã€‚ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã«ã¯ã€vpncmd ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã€ãƒ“ルド番å·ã€ãƒ“ルド情報ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚
+CMD_About_ARGS About
+
+
+# ServerInfoGet コマンド
+CMD_ServerInfoGet サーãƒãƒ¼æƒ…å ±ã®å–å¾—
+CMD_ServerInfoGet_Help ç¾åœ¨æŽ¥ç¶šã—ã¦ã„ã‚‹ VPN Server ã¾ãŸã¯ VPN Bridge ã®ã‚µãƒ¼ãƒãƒ¼æƒ…報をå–å¾—ã—ã¾ã™ã€‚サーãƒãƒ¼ã®æƒ…å ±ã«ã¯ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã€ãƒ“ルド番å·ã€ãƒ“ルド情報ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚ã¾ãŸã€ç¾åœ¨ã®ã‚µãƒ¼ãƒãƒ¼ã®å‹•ä½œãƒ¢ãƒ¼ãƒ‰ã‚„動作ã—ã¦ã„るオペレーティングシステムã®æƒ…å ±ãªã©ã‚‚å–å¾—ã§ãã¾ã™ã€‚
+CMD_ServerInfoGet_Args ServerInfoGet
+
+
+# ServerStatusGet コマンド
+CMD_ServerStatusGet サーãƒãƒ¼ã®ç¾åœ¨ã®çŠ¶æ…‹ã®å–å¾—
+CMD_ServerStatusGet_Help ç¾åœ¨æŽ¥ç¶šã—ã¦ã„ã‚‹ VPN Server ã¾ãŸã¯ VPN Bridge ã®ç¾åœ¨ã®çŠ¶æ…‹ã‚’リアルタイムã«å–å¾—ã—ã¾ã™ã€‚サーãƒãƒ¼ä¸Šã«å­˜åœ¨ã™ã‚‹å„種オブジェクトã®å€‹æ•°ã‚„ã€ãƒ‡ãƒ¼ã‚¿é€šä¿¡ã®çµ±è¨ˆæƒ…å ±ãªã©ã‚’å–å¾—ã§ãã¾ã™ã€‚ã¾ãŸã€OS ã«ã‚ˆã£ã¦ã¯ç¾åœ¨ã‚³ãƒ³ãƒ”ュータã§ä½¿ç”¨ã•ã‚Œã¦ã„るメモリé‡ãªã©ã‚’å–å¾—ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_ServerStatusGet_Args ServerStatusGet
+
+
+# ListenerCreate コマンド
+CMD_ListenerCreate TCP リスナーã®è¿½åŠ 
+CMD_ListenerCreate_Help サーãƒãƒ¼ã«æ–°ã—ã„ TCP リスナーを追加ã—ã¾ã™ã€‚TCP リスナーを追加ã™ã‚‹ã¨ã€ã‚µãƒ¼ãƒãƒ¼ã¯æŒ‡å®šã—㟠TCP/IP ãƒãƒ¼ãƒˆç•ªå·ã§ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã®å¾…機を開始ã—ã¾ã™ã€‚\n一度追加ã—㟠TCP リスナーã¯ã€ListenerDelete コマンドã§å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nãªãŠã€ç¾åœ¨ã®ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーã®ä¸€è¦§ã¯ã€ListenerList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ListenerCreate_Args ListenerCreate [port]
+CMD_ListenerCreate_[port] æ–°ã—ã追加ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚ã™ã§ã«åˆ¥ã®ãƒ—ログラムãŒä½¿ç”¨ã—ã¦ã„ã‚‹ãƒãƒ¼ãƒˆç•ªå·ã‚’使用ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ãŒã€ãã®ãƒ—ログラムãŒãƒãƒ¼ãƒˆã®ä½¿ç”¨ã‚’終了ã™ã‚‹ã¾ã§ã€VPN Server ã¯ãã®ãƒãƒ¼ãƒˆã‚’使用ã§ãã¾ã›ã‚“。ãƒãƒ¼ãƒˆç•ªå·ã¯ 1 以上 65535 以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_ListenerCreate_PortPrompt æ–°ã—ã追加ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·:
+
+
+# ListenerDelete コマンド
+CMD_ListenerDelete TCP リスナーã®å‰Šé™¤
+CMD_ListenerDelete_Help サーãƒãƒ¼ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーを削除ã—ã¾ã™ã€‚TCP リスナーãŒå‹•ä½œçŠ¶æ…‹ã«ã‚ã‚‹å ´åˆã¯ã€è‡ªå‹•çš„ã«å‹•ä½œã‚’åœæ­¢ã—ã¦ã‹ã‚‰ãƒªã‚¹ãƒŠãƒ¼ãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚\nãªãŠã€ç¾åœ¨ã®ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーã®ä¸€è¦§ã¯ã€ListenerList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ListenerDelete_Args ListenerDelete [port]
+CMD_ListenerDelete_[port] 削除ã—ãŸã„ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·ã‚’ã€æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_ListenerDelete_PortPrompt 削除ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·:
+
+
+# ListenerList コマンド
+CMD_ListenerList TCP リスナー一覧ã®å–å¾—
+CMD_ListenerList_Help ç¾åœ¨ã‚µãƒ¼ãƒãƒ¼ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚å„ TCP リスナーãŒå‹•ä½œä¸­ã€ã¾ãŸã¯ã‚¨ãƒ©ãƒ¼çŠ¶æ…‹ã§ã‚ã‚‹ã‹ã©ã†ã‹ã®æƒ…報もå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ListenerList_Args ListenerList
+CMD_ListenerList_Column1 TCP ãƒãƒ¼ãƒˆç•ªå·
+CMD_ListenerList_Column2 状態
+
+
+# ListenerEnable コマンド
+CMD_ListenerEnable TCP リスナーã®å‹•ä½œé–‹å§‹
+CMD_ListenerEnable_Help ç¾åœ¨ã‚µãƒ¼ãƒãƒ¼ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーãŒåœæ­¢ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã®å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nãªãŠã€ç¾åœ¨ã®ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーã®ä¸€è¦§ã¯ã€ListenerList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ListenerEnable_Args ListenerEnable [port]
+CMD_ListenerEnable_[port] 開始ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·ã‚’ã€æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_ListenerEnable_PortPrompt 開始ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·:
+
+
+# ListenerDisable コマンド
+CMD_ListenerDisable TCP リスナーã®å‹•ä½œåœæ­¢
+CMD_ListenerDisable_Help ç¾åœ¨ã‚µãƒ¼ãƒãƒ¼ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã®å‹•ä½œã‚’åœæ­¢ã—ã¾ã™ã€‚\nãªãŠã€ç¾åœ¨ã®ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ TCP リスナーã®ä¸€è¦§ã¯ã€ListenerList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ListenerDisable_Args ListenerDisable [port]
+CMD_ListenerDisable_[port] åœæ­¢ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·ã‚’ã€æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_ListenerDisable_PortPrompt 開始ã™ã‚‹ TCP/IP リスナーã®ãƒãƒ¼ãƒˆç•ªå·:
+
+
+# ServerPasswordSet コマンド
+CMD_ServerPasswordSet VPN Server ã®ç®¡ç†è€…パスワードã®è¨­å®š
+CMD_ServerPasswordSet_Help VPN Server ã®ç®¡ç†è€…パスワードを設定ã—ã¾ã™ã€‚パラメータã¨ã—ã¦ãƒ‘スワードを指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚パラメータを指定ã—ãªã„å ´åˆã¯ã€ãƒ‘スワードã¨ã€ãã®ç¢ºèªå…¥åŠ›ã‚’è¡Œãªã†ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚パスワードをパラメータã«ä¸ŽãˆãŸå ´åˆã€ãã®ãƒ‘スワードãŒä¸€æ™‚çš„ã«ç”»é¢ã«è¡¨ç¤ºã•ã‚Œã‚‹ãŸã‚å±é™ºã§ã™ã€‚ã§ãã‚‹é™ã‚Šã€ãƒ‘ラメータを指定ã›ãšã«ã€ãƒ‘スワードプロンプトを用ã„ã¦ãƒ‘スワードを入力ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ServerPasswordSet_Args ServerPasswordSet [password]
+CMD_ServerPasswordSet_[password] æ–°ã—ã設定ã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚
+
+
+# ClusterSettingGet コマンド
+CMD_ClusterSettingGet ç¾åœ¨ã® VPN Server ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°æ§‹æˆã®å–å¾—
+CMD_ClusterSettingGet_Help ç¾åœ¨ã® VPN Server ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°æ§‹æˆã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ClusterSettingGet_Args ClusterSettingGet
+CMD_ClusterSettingGet_Current ç¾åœ¨ã®æ§‹æˆ
+CMD_ClusterSettingGet_None (設定無ã—)
+CMD_ClusterSettingGet_PublicIp 公開 IP アドレス
+CMD_ClusterSettingGet_PublicPorts 公開ãƒãƒ¼ãƒˆä¸€è¦§
+CMD_ClusterSettingGet_Controller 接続先コントローラ
+CMD_ClusterSettingGet_ControllerOnly コントローラ機能ã®ã¿
+CMD_ClusterSettingGet_Weight クラスタ内ã§ã®æ€§èƒ½åŸºæº–値
+
+
+# ClusterSettingStandalone コマンド
+CMD_ClusterSettingStandalone VPN Server ã®ç¨®é¡žã‚’スタンドアロンã«è¨­å®š
+CMD_ClusterSettingStandalone_Help VPN Server ã®ç¨®é¡žã‚’ã€ã€Œã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ã€ã«è¨­å®šã—ã¾ã™ã€‚スタンドアロンサーãƒãƒ¼ã¨ã¯ã€ã„ãšã‚Œã®ã‚¯ãƒ©ã‚¹ã‚¿ã«ã‚‚属ã—ã¦ã„ãªã„状態㮠VPN Server ã‚’æ„味ã—ã¾ã™ã€‚VPN Server をインストールã—ãŸçŠ¶æ…‹ã§ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã«ãªã‚Šã¾ã™ã€‚特ã«ã‚¯ãƒ©ã‚¹ã‚¿ã‚’構æˆã™ã‚‹äºˆå®šãŒãªã„å ´åˆã¯ã€ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã•ã›ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€VPN Server ã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterSettingStandalone_Args ClusterSettingStandalone
+
+
+# ClusterSettingController コマンド
+CMD_ClusterSettingController VPN Server ã®ç¨®é¡žã‚’クラスタコントローラã«è¨­å®š
+CMD_ClusterSettingController_Help VPN Server ã®ç¨®é¡žã‚’ã€ã€Œã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã€ã«è¨­å®šã—ã¾ã™ã€‚クラスタコントローラã¨ã¯ã€è¤‡æ•°å°ã® VPN Server ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°ã‚’構築ã™ã‚‹å ´åˆã«ãŠã‘ã‚‹ã€å„クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã®ä¸­å¿ƒã¨ãªã‚‹ã‚³ãƒ³ãƒ”ュータã§ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã« 1 å°å¿…è¦ã§ã™ã€‚åŒä¸€ã‚¯ãƒ©ã‚¹ã‚¿ã‚’構æˆã™ã‚‹ä»–ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã¨ã—ã¦ã®å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€VPN Server ã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterSettingController_Args ClusterSettingController [/WEIGHT:weight] [/ONLY:yes|no]
+CMD_ClusterSettingController_WEIGHT ã“ã® VPN Server ã®æ€§èƒ½åŸºæº–比ã®å€¤ã‚’設定ã—ã¾ã™ã€‚クラスタ内ã§ãƒ­ãƒ¼ãƒ‰ãƒãƒ©ãƒ³ã‚·ãƒ³ã‚°ã‚’è¡Œã†éš›ã«åŸºæº–ã¨ãªã‚‹å€¤ã§ã™ã€‚通常㯠100 ã§ã™ã€‚ãŸã¨ãˆã°ã€ä»–ã®ãƒ¡ãƒ³ãƒãŒ 100 ã®çŠ¶æ…‹ã§ã€1 å°ã ã‘ 200 ã«ã™ã‚‹ã¨ã€ä»–ã®ãƒ¡ãƒ³ãƒã® 2 å€æŽ¥ç¶šã‚’å—ã‘æŒã¤ã‚ˆã†ã«ãƒ­ãƒ¼ãƒ‰ãƒãƒ©ãƒ³ã‚·ãƒ³ã‚°æ™‚ã«èª¿æ•´ã•ã‚Œã¾ã™ã€‚値㯠1 以上ã§æŒ‡å®šã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€100 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_ClusterSettingController_ONLY "yes" を指定ã™ã‚‹ã¨ã€VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¨ã—ã¦ã®æ©Ÿèƒ½ã®ã¿ã‚’動作ã•ã›ã€ä¸€èˆ¬ã® VPN Client ã®æŽ¥ç¶šã¯ã€è‡ªåˆ†è‡ªèº«ä»¥å¤–ã®ãƒ¡ãƒ³ãƒã«å¿…ãšæŒ¯ã‚Šåˆ†ã‘るよã†ã«ãªã‚Šã¾ã™ã€‚ã“ã®æ©Ÿèƒ½ã¯ã€è² è·ãŒé«˜ã„環境ã§ä½¿ç”¨ã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€"no" ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+
+
+# ClusterSettingMember コマンド
+CMD_ClusterSettingMember VPN Server ã®ç¨®é¡žã‚’クラスタメンãƒã«è¨­å®š
+CMD_ClusterSettingMember_Help VPN Server ã®ç¨®é¡žã‚’ã€ã€Œã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã€ã«è¨­å®šã—ã¾ã™ã€‚クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã¨ã¯ã€è¤‡æ•°å°ã® VPN Server ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°ã‚’構築ã™ã‚‹å ´åˆã«ãŠã‘ã‚‹ã€ç‰¹å®šã®æ—¢å­˜ã®ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãŒä¸­å¿ƒã¨ãªã£ã¦æ§‹æˆã•ã‚Œã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ã«å±žã™ã‚‹ä»–ã®ãƒ¡ãƒ³ãƒã‚³ãƒ³ãƒ”ュータã§ã€ã‚¯ãƒ©ã‚¹ã‚¿ã«å¿…è¦ãªã ã‘複数追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nクラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—㦠VPN Server を設定ã™ã‚‹ã«ã¯ã€äº‹å‰ã«å‚加ã™ã‚‹äºˆå®šã®ã‚¯ãƒ©ã‚¹ã‚¿ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã®ç®¡ç†è€…ã«ã€ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã® IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã€ã“ã® VPN Server ã®å…¬é–‹ IP アドレスãŠã‚ˆã³å…¬é–‹ãƒãƒ¼ãƒˆç•ªå· (å¿…è¦ãªå ´åˆ)ã€ãŠã‚ˆã³ãƒ‘スワードをå•ã„åˆã‚ã›ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€VPN Server ã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterSettingMember_Args ClusterSettingMember [server:port] [/IP:ip] [/PORTS:ports] [/PASSWORD:password] [/WEIGHT:weight]
+CMD_ClusterSettingMember_[server:port] [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã®ãƒ‘ラメータã§ã€æŽ¥ç¶šå…ˆã®ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã€ãŠã‚ˆã³ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_ClusterSettingMember_IP ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®å…¬é–‹ IP アドレスを指定ã—ã¾ã™ã€‚公開 IP アドレスを指定ã—ãªã„å ´åˆã€"/IP:none" ã®ã‚ˆã†ã«æŒ‡å®šã—ã¦ãã ã•ã„。公開 IP アドレスを指定ã—ãªã‘ã‚Œã°ã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¸ã®æŽ¥ç¶šã®éš›ã«ä½¿ç”¨ã•ã‚Œã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã® IP アドレスãŒè‡ªå‹•çš„ã«ä½¿ã‚ã‚Œã¾ã™ã€‚
+CMD_ClusterSettingMember_PORTS ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®å…¬é–‹ãƒãƒ¼ãƒˆç•ªå·ã®ä¸€è¦§ã‚’指定ã—ã¾ã™ã€‚公開ãƒãƒ¼ãƒˆç•ªå·ã¯ã€å°‘ãªãã¨ã‚‚ 1 ã¤ä»¥ä¸Šè¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã€è¤‡æ•°å€‹è¨­å®šã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚ãã®å ´åˆã¯ã€"/PORTS:443,992,8888" ã®ã‚ˆã†ã«ã‚«ãƒ³ãƒžè¨˜å·ã§åŒºåˆ‡ã£ã¦ãã ã•ã„。
+CMD_ClusterSettingMember_PASSWORD 接続先ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã®ãƒ‘スワードを指定ã—ã¾ã™ã€‚接続先ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã®ç®¡ç†ãƒ‘スワードã¨åŒä¸€ã§ã™ã€‚
+CMD_ClusterSettingMember_WEIGHT ã“ã® VPN Server ã®æ€§èƒ½åŸºæº–比ã®å€¤ã‚’設定ã—ã¾ã™ã€‚クラスタ内ã§ã€ãƒ­ãƒ¼ãƒ‰ãƒãƒ©ãƒ³ã‚·ãƒ³ã‚°ã‚’è¡Œã†éš›ã®åŸºæº–ã¨ãªã‚‹å€¤ã§ã™ã€‚ãŸã¨ãˆã°ã€ä»–ã®ãƒ¡ãƒ³ãƒãŒ 100 ã®çŠ¶æ…‹ã§ã€1 å°ã ã‘ 200 ã«ã™ã‚‹ã¨ã€ä»–ã®ãƒ¡ãƒ³ãƒã® 2 å€ã®æŽ¥ç¶šã‚’å—ã‘æŒã¤ã‚ˆã†ã«èª¿æ•´ã•ã‚Œã¾ã™ã€‚値㯠1 以上ã§æŒ‡å®šã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€100 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_ClusterSettingMember_Prompt_IP_1 公開 IP アドレスを指定ã—ã¦ãã ã•ã„。\n指定ã—ãªã„å ´åˆã¯ã€ä½•ã‚‚入力ã›ãšã« Enter を押ã—ã¦ãã ã•ã„。
+CMD_ClusterSettingMember_Prompt_IP_2 公開 IP アドレス:
+CMD_ClusterSettingMember_Prompt_PORT_1 公開ãƒãƒ¼ãƒˆç•ªå·ã®ä¸€è¦§ã‚’指定ã—ã¦ãã ã•ã„。\n2 個以上ã®ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã™ã‚‹å ´åˆã¯ã€443,992,8888 ã®ã‚ˆã†ã«ã‚«ãƒ³ãƒžè¨˜å·ã§åŒºåˆ‡ã£ã¦ãã ã•ã„。
+CMD_ClusterSettingMember_Prompt_PORT_2 公開ãƒãƒ¼ãƒˆç•ªå·:
+CMD_ClusterSettingMember_Prompt_HOST_1 接続先コントローラã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+
+
+# ClusterMemberList コマンド
+CMD_ClusterMemberList クラスタメンãƒã®ä¸€è¦§ã®å–å¾—
+CMD_ClusterMemberList_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ãã®ã‚¯ãƒ©ã‚¹ã‚¿å†…ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã®ä¸€è¦§ã‚’ã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©è‡ªèº«ã‚’å«ã‚ã¦å–å¾—ã—ã¾ã™ã€‚\nå„メンãƒæ¯Žã«ã€[種類]ã€[接続時刻]ã€[ホストå]ã€[ãƒã‚¤ãƒ³ãƒˆ]ã€[セッション数]ã€[TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°]ã€[動作仮想 HUB æ•°]ã€[消費クライアント接続ライセンス]ã€[消費ブリッジ接続ライセンス] ã®ä¸€è¦§ã‚‚å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterMemberList_Args ClusterMemberList
+
+
+# ClusterMemberInfoGet コマンド
+CMD_ClusterMemberInfoGet クラスタメンãƒã®æƒ…å ±ã®å–å¾—
+CMD_ClusterMemberInfoGet_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ãã®ã‚¯ãƒ©ã‚¹ã‚¿å†…ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã® ID を指定ã—ã¦ã€ãã®ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã®æƒ…報をå–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n指定ã•ã‚ŒãŸã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã® [サーãƒãƒ¼ã®ç¨®é¡ž]ã€[接続確立時刻]ã€[IP アドレス]ã€[ホストå]ã€[ãƒã‚¤ãƒ³ãƒˆ]ã€[公開ãƒãƒ¼ãƒˆã®ä¸€è¦§]ã€[動作ã—ã¦ã„る仮想 HUB æ•°]ã€[1 個目ã®ä»®æƒ³ HUB]ã€[セッション数]ã€[TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°] ãŒå–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterMemberInfoGet_Args ClusterMemberInfoGet [id]
+CMD_ClusterMemberInfoGet_[id] 情報をå–å¾—ã™ã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã® ID を指定ã—ã¾ã™ã€‚クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã® ID ã¯ã€ClusterMemberList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_ClusterMemberInfoGet_PROMPT_ID 情報をå–å¾—ã™ã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã® ID:
+
+
+# ClusterMemberCertGet コマンド
+CMD_ClusterMemberCertGet クラスタメンãƒã®è¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_ClusterMemberCertGet_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ãã®ã‚¯ãƒ©ã‚¹ã‚¿å†…ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã® ID を指定ã—ã¦ã€ãã®ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã®å…¬é–‹ã—ã¦ã„ã‚‹ X.509 証明書をå–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚証明書ã¯ã€X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterMemberCertGet_Args ClusterMemberCertGet [id] [/SAVECERT:cert]
+CMD_ClusterMemberCertGet_[id] 証明書をå–å¾—ã™ã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã® ID を指定ã—ã¾ã™ã€‚クラスタメンãƒã‚µãƒ¼ãƒãƒ¼ã® ID ã¯ã€ClusterMemberList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_ClusterMemberCertGet_SAVECERT å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘スåを指定ã—ã¾ã™ã€‚証明書㯠X.509 å½¢å¼ã§ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+CMD_ClusterMemberCertGet_PROMPT_ID 証明書をå–å¾—ã™ã‚‹ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã® ID:
+
+# ClusterConnectionStatusGet コマンド
+CMD_ClusterConnectionStatusGet クラスタコントローラã¸ã®æŽ¥ç¶šçŠ¶æ…‹ã®å–å¾—
+CMD_ClusterConnectionStatusGet_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã¸ã®æŽ¥ç¶šçŠ¶æ…‹ã‚’å–å¾—ã—ã¾ã™ã€‚\nå–å¾—ã§ãる情報ã«ã¯ã€[コントローラ㮠IP アドレス]ã€[ãƒãƒ¼ãƒˆç•ªå·]ã€[接続状態]ã€[接続開始時刻]ã€[最åˆã®æŽ¥ç¶šç¢ºç«‹æˆåŠŸæ™‚刻]ã€[ç¾åœ¨ã®æŽ¥ç¶šæˆåŠŸç¢ºç«‹æ™‚刻]ã€[接続試行回数]ã€[接続ã«æˆåŠŸã—ãŸå›žæ•°]ã€[接続ã«å¤±æ•—ã—ãŸå›žæ•°] ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ClusterConnectionStatusGet_Args ClusterConnectionStatusGet
+
+
+# Debug コマンド
+CMD_Debug デãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œ
+CMD_Debug_Help VPN Server / Bridge ã®å®Ÿè¡Œä¸­ã®ãƒ—ロセスã§ãƒ‡ãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã‹ã‚‰ã®ã‚µãƒãƒ¼ãƒˆã®æŒ‡ç¤ºãŒã‚ã£ãŸå ´åˆã®ã¿ä½¿ç”¨ã—ã¦ãã ã•ã„。\nむやã¿ã«ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã™ã‚‹ã¨ã€å‹•ä½œä¸­ã® VPN Server / Bridge ãŒåœæ­¢ã™ã‚‹åŽŸå› ã«ãªã‚Šã¾ã™ã€‚
+CMD_Debug_Args Debug [id] [/ARG:arg]
+CMD_Debug_[id] デãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ç•ªå·ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_Debug_ARG デãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ã«æ¸¡ã™æ–‡å­—列を指定ã—ã¾ã™ã€‚スペースをå«ã‚€å ´åˆã¯ã€" " ã§å›²ã‚“ã§ãã ã•ã„。
+CMD_Debug_Msg1 デãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ã‚’é€ä¿¡ä¸­...
+CMD_Debug_Msg2 デãƒãƒƒã‚°ã‚³ãƒžãƒ³ãƒ‰ã®å‹•ä½œãŒå®Œäº†ã—ã¾ã—ãŸã€‚\n戻り値: \"%S\"
+
+# Crash コマンド
+CMD_Crash VPN Server / Bridge プロセスã§ã‚¨ãƒ©ãƒ¼ã‚’発生ã•ã›ãƒ—ロセスを強制終了ã™ã‚‹
+CMD_Crash_Help VPN Server / Bridge ã®å®Ÿè¡Œä¸­ã®ãƒ—ロセスã§è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ (メモリä¿è­·é•åãªã©) を発生ã•ã›ã€ãƒ—ロセスをクラッシュã•ã›ã¾ã™ã€‚ãã®çµæžœã€VPN Server / Bridge ãŒã‚µãƒ¼ãƒ“スモードã§èµ·å‹•ã—ã¦ã„ã‚‹å ´åˆã¯ã€è‡ªå‹•çš„ã«ãƒ—ロセスãŒå†èµ·å‹•ã—ã¾ã™ã€‚VPN Server ãŒãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§èµ·å‹•ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãƒ—ロセスã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Server / Bridge ã§ä½•ã‚‰ã‹ã®å›žå¾©ä¸èƒ½ãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã‚Šã€ãƒ—ロセスãŒæš´èµ°ã—ãŸã‚Šã—ã¦ã„ã‚‹ã¨ãã«ã€ã™ãã«ãƒ—ロセスをå†èµ·å‹•ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„よã†ãªå ´åˆã«åˆ©ç”¨ã—ã¦ãã ã•ã„。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€ç¾åœ¨ VPN Server / Bridge ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã® VPN セッションã¯åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€VPN Server ãŒãƒ¡ãƒ¢ãƒªå†…ã«ä¿æœ‰ã—ã¦ã„る未ä¿å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¯ã™ã¹ã¦å¤±ã‚ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹å‰ã«ã€Flush コマンドを実行ã—ã¦VPN Server / Bridge ã®æœªä¿å­˜ã®è¨­å®šãƒ‡ãƒ¼ã‚¿ã‚’設定ファイルã«å¼·åˆ¶ä¿å­˜ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Server / Bridge 全体ã®ç®¡ç†è€…ã®ã¿ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚
+CMD_Crash_Args Crash [yes]
+CMD_Crash_[yes] 確èªã®ãŸã‚ã€"yes" ã¨æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_Crash_Msg VPN Server ã«ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ コマンドをé€ä¿¡ã—ã¦ã„ã¾ã™ã€‚VPN Server ã¯ç›´ã¡ã«ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã™ã‚‹ãŸã‚ã€ã‚³ãƒžãƒ³ãƒ‰ãŒæˆåŠŸã—ãŸã‹ã©ã†ã‹ã®æˆ»ã‚Šå€¤ã¯å–å¾—ã§ãã¾ã›ã‚“。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ãŸå¾Œã¯ã€vpncmd 㯠VPN Server ã¨ã®é–“ã®æŽ¥ç¶šã‚’切断ã•ã‚Œã¾ã™ã€‚
+CMD_Crash_Confirm 本当㫠VPN Server をクラッシュã•ã›ã¾ã™ã‹?\nよã‚ã—ã„å ´åˆã¯ "yes" ã¨å…¥åŠ›ã—ã¦ãã ã•ã„:
+CMD_Crash_Aborted Crash コマンドã¯ä¸­æ­¢ã•ã‚Œã¾ã—ãŸã€‚
+
+
+# Flush コマンド
+CMD_Flush VPN Server / Bridge ã®æœªä¿å­˜ã®è¨­å®šãƒ‡ãƒ¼ã‚¿ã‚’設定ファイルã«å¼·åˆ¶ä¿å­˜ã™ã‚‹
+CMD_Flush_Help 通常ã€VPN Server / Bridge ã¯è¨­å®šå†…容をメモリ内ã«ä¿æŒã—ã€vpn_server.config ã¾ãŸã¯ vpn_bridge.config ファイルã«å®šæœŸçš„ã«ä¿å­˜ã—ã¾ã™ã€‚ã“れらã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã¸ã®ä¿å­˜å‡¦ç†ã¯ã€é€šå¸¸ã€300 秒 (5 分) ã”ã¨ã«è‡ªå‹•çš„ã«è¡Œã‚ã‚Œã¾ã™ (ã“ã®é–“éš”ã¯ã€è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã® AutoSaveConfigSpan 項目を編集ã™ã‚‹ã“ã¨ã§å¤‰æ›´ã§ãã¾ã™)。ãªãŠã€VPN Server / Bridge サービスãŒæ­£å¸¸çµ‚了ã—よã†ã¨ã™ã‚‹éš›ã«ã‚‚ã“れらã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã¯è‡ªå‹•çš„ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚\nFlush コマンドを実行ã™ã‚‹ã¨ã€VPN Server / Bridge ã¯ã€ã™ãã«è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã¸ã®ä¿å­˜å‡¦ç†ã‚’実施ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ç¾åœ¨ã®æœ€æ–°ã®è¨­å®šãƒ‡ãƒ¼ã‚¿ãŒå¿…ãšã‚µãƒ¼ãƒãƒ¼ã‚³ãƒ³ãƒ”ュータã®ãƒ‡ã‚£ã‚¹ã‚¯ãƒ‰ãƒ©ã‚¤ãƒ–ã«ãƒ•ãƒ©ãƒƒã‚·ãƒ¥ã•ã‚Œã¾ã™ã€‚ãŸã¨ãˆã°ã€ã‚„むを得ãšã‚µãƒ¼ãƒ“スプロセスを正常終了ã™ã‚‹æ™‚間的余裕ãŒãªã„å ´åˆã¯ã€Flush コマンドを用ã„ã¦ãƒ‡ãƒ¼ã‚¿ã‚’強制ä¿å­˜ã—ã¦ã‹ã‚‰ã€ã‚µãƒ¼ãƒ“スプロセスやサーãƒãƒ¼ã‚³ãƒ³ãƒ”ュータを強制シャットダウンã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Server / Bridge 全体ã®ç®¡ç†è€…ã®ã¿ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚
+CMD_Flush_Args Flush
+CMD_Flush_Msg1 メモリ上ã®è¨­å®šãƒ‡ãƒ¼ã‚¿ã‚’ディスクã«æ›¸ã込んã§ã„ã¾ã™...\n
+CMD_Flush_Msg2 書ãè¾¼ã¿ã«æˆåŠŸã—ã¾ã—ãŸã€‚ファイルサイズ㯠%S bytes ã§ã™ã€‚\n
+
+
+# ServerCertGet コマンド
+CMD_ServerCertGet VPN Server ã® SSL 証明書ã®å–å¾—
+CMD_ServerCertGet_Help VPN Server ãŒã€æŽ¥ç¶šã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«å¯¾ã—ã¦æ示ã™ã‚‹ SSL 証明書をå–å¾—ã—ã¾ã™ã€‚証明書ã¯ã€X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_ServerCertGet_Args ServerCertGet [cert]
+CMD_ServerCertGet_[cert] å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘スåを指定ã—ã¾ã™ã€‚証明書㯠X.509 å½¢å¼ã§ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+
+
+# ServerKeyGet コマンド
+CMD_ServerKeyGet VPN Server ã® SSL 証明書ã®ç§˜å¯†éµã®å–å¾—
+CMD_ServerKeyGet_Help VPN Server ãŒæŽ¥ç¶šã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«å¯¾ã—ã¦æ示ã™ã‚‹ SSL 証明書ã®ç§˜å¯†éµã‚’å–å¾—ã—ã¾ã™ã€‚秘密éµã¯ã€Base 64 ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ServerKeyGet_Args ServerKeyGet [key]
+CMD_ServerKeyGet_[key] å–å¾—ã—ãŸç§˜å¯†éµã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘スåを指定ã—ã¾ã™ã€‚秘密éµã¯ Base 64 エンコードã•ã‚Œã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+
+
+# ServerCertSet コマンド
+CMD_ServerCertSet VPN Server ã® SSL 証明書ã¨ç§˜å¯†éµã®è¨­å®š
+CMD_ServerCertSet_Help VPN Server ãŒæŽ¥ç¶šã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«å¯¾ã—ã¦æ示ã™ã‚‹ SSL 証明書ã¨ã€ãã®è¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµã‚’設定ã—ã¾ã™ã€‚証明書㯠X.509 å½¢å¼ã€ç§˜å¯†éµã¯ Base 64 エンコードã•ã‚ŒãŸå½¢å¼ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ServerCertSet_Args ServerCertSet [/LOADCERT:cert] [/LOADKEY:key]
+CMD_ServerCertSet_LOADCERT 使用ã™ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¾ã™ã€‚
+CMD_ServerCertSet_LOADKEY 使用ã™ã‚‹ Base 64 エンコードã•ã‚ŒãŸã€è¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¾ã™ã€‚
+
+
+# ServerCipherGet コマンド
+CMD_ServerCipherGet VPN 通信ã§ä½¿ç”¨ã•ã‚Œã‚‹æš—å·åŒ–アルゴリズムã®å–å¾—
+CMD_ServerCipherGet_Help VPN Server ã¨ã€æŽ¥ç¶šã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¨ã®é–“ã§é€šä¿¡ã«ä½¿ç”¨ã™ã‚‹ SSL コãƒã‚¯ã‚·ãƒ§ãƒ³ã«ãŠã‘ã‚‹æš—å·åŒ–ã€ãŠã‚ˆã³é›»å­ç½²åã«ç”¨ã„られるアルゴリズムã®ç¾åœ¨ã®è¨­å®šã¨ã€VPN Server 上ã§ä½¿ç”¨å¯èƒ½ãªã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚
+CMD_ServerCipherGet_Args ServerCipherGet
+CMD_ServerCipherGet_SERVER VPN Server ã§ç¾åœ¨ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹æš—å·åŒ–アルゴリズム:
+CMD_ServerCipherGet_CIPHERS 使用å¯èƒ½ãªæš—å·åŒ–アルゴリズムåã®ä¸€è¦§:
+
+# ServerCipherSet コマンド
+CMD_ServerCipherSet VPN 通信ã§ä½¿ç”¨ã•ã‚Œã‚‹æš—å·åŒ–アルゴリズムã®è¨­å®š
+CMD_ServerCipherSet_Help VPN Server ã¨ã€æŽ¥ç¶šã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¨ã®é–“ã§é€šä¿¡ã«ä½¿ç”¨ã™ã‚‹ SSL コãƒã‚¯ã‚·ãƒ§ãƒ³ã«ãŠã‘ã‚‹æš—å·åŒ–ã€ãŠã‚ˆã³é›»å­ç½²åã«ç”¨ã„られるアルゴリズムを設定ã—ã¾ã™ã€‚\nアルゴリズムåを指定ã™ã‚‹ã¨ã€ä»¥å¾Œã“ã® VPN Server ã«æŽ¥ç¶šã—㟠VPN Client ã‚„ã€VPN Bridge ã¨ã®é–“ã§ã€æŒ‡å®šã—ãŸã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ãŒä½¿ç”¨ã•ã‚Œã€ãƒ‡ãƒ¼ã‚¿ãŒæš—å·åŒ–ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ServerCipherSet_Args ServerCipherSet [name]
+CMD_ServerCipherSet_[name] 設定ã™ã‚‹ã‚‹æš—å·åŒ–ãŠã‚ˆã³é›»å­ç½²åアルゴリズムを指定ã—ã¾ã™ã€‚使用å¯èƒ½ãªã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã®ä¸€è¦§ã¯ã€ServerCipherGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_ServerCipherSet_PROMPT_NAME 指定ã™ã‚‹æš—å·åŒ–アルゴリズムå:
+
+
+# KeepEnable コマンド
+CMD_KeepEnable インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã®æœ‰åŠ¹åŒ–
+CMD_KeepEnable_Help [インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] を有効ã«ã—ã¾ã™ã€‚[インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] を使用ã™ã‚‹ã¨ã€ä¸€å®šæœŸé–“無通信状態ãŒç¶šãã¨ã€è‡ªå‹•çš„ã«æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚Œã‚‹ã‚ˆã†ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šç’°å¢ƒã®å ´åˆã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ä»»æ„ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ä¸€å®šé–“éš”ã”ã¨ã«ãƒ‘ケットをé€ä¿¡ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’維æŒã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n接続先ã®ãƒ›ã‚¹ãƒˆåãªã©ã«ã¤ã„ã¦ã¯ã€KeepSet コマンドã§è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nVPN Server ã¾ãŸã¯ VPN Bridge ã§ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_KeepEnable_Args KeepEnable
+
+
+# KeepDisable コマンド
+CMD_KeepDisable インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã®ç„¡åŠ¹åŒ–
+CMD_KeepDisable_Help [インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] を無効ã«ã—ã¾ã™ã€‚\nVPN Server ã¾ãŸã¯ VPN Bridge ã§ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_KeepDisable_Args KeepDisable
+
+
+# KeepSet コマンド
+CMD_KeepSet インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã®è¨­å®š
+CMD_KeepSet_Help [インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] ã®æŽ¥ç¶šå…ˆãƒ›ã‚¹ãƒˆåãªã©ã®è¨­å®šã‚’è¡Œãªã„ã¾ã™ã€‚一定期間無通信状態ãŒç¶šãã¨è‡ªå‹•çš„ã«æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚Œã‚‹ã‚ˆã†ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šç’°å¢ƒã§ã€[インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] を使用ã™ã‚‹ã¨ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ä»»æ„ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ã€ä¸€å®šé–“éš”ã”ã¨ã«ãƒ‘ケットをé€ä¿¡ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’維æŒã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã¯ã€é€šä¿¡å…ˆã® [ホストå]ã€[ãƒãƒ¼ãƒˆç•ªå·]ã€[パケットé€å‡ºé–“éš”]ã€ãŠã‚ˆã³ [プロトコル] を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nインターãƒãƒƒãƒˆæŽ¥ç¶šç¶­æŒã®ãŸã‚ã«é€ä¿¡ã•ã‚Œã‚‹ãƒ‘ケットã¯ã€ãƒ©ãƒ³ãƒ€ãƒ ãªå†…容ã§ã‚ã‚Šã€ã‚³ãƒ³ãƒ”ュータやユーザーを識別ã™ã‚‹å€‹äººæƒ…å ±ãªã©ãŒé€ä¿¡ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。\nインターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã¯ã€KeepEnable コマンドã€ã¾ãŸã¯ KeepDisable コマンドを用ã„ã¦ã€æœ‰åŠ¹åŒ– / 無効化ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚KeepSet ã¯æœ‰åŠ¹ / 無効ã®çŠ¶æ…‹ã‚’変更ã—ã¾ã›ã‚“。\nVPN Server ã¾ãŸã¯ VPN Bridge ã§ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_KeepSet_Args KeepSet [/HOST:host:port] [/PROTOCOL:tcp|udp] [/INTERVAL:interval]
+CMD_KeepSet_HOST [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€é€šä¿¡å…ˆã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_KeepSet_PROTOCOL tcp ã¾ãŸã¯ udp を指定ã—ã¾ã™ã€‚
+CMD_KeepSet_INTERVAL パケットをé€å‡ºã™ã‚‹é–“隔を秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_KeepSet_PROMPT_HOST 通信先ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·:
+CMD_KeepSet_PROMPT_PROTOCOL tcp ã¾ãŸã¯ udp:
+CMD_KeepSet_PROMPT_INTERVAL パケットをé€å‡ºã™ã‚‹é–“éš” (秒å˜ä½):
+CMD_KeepSet_EVAL_TCP_UDP "tcp" ã¾ãŸã¯ "udp" を指定ã—ã¦ãã ã•ã„。
+
+# KeepGet コマンド
+CMD_KeepGet インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã®å–å¾—
+CMD_KeepGet_Help [インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] ã®ã€ç¾åœ¨ã®è¨­å®šå†…容をå–å¾—ã—ã¾ã™ã€‚通信先㮠[ホストå]ã€[ãƒãƒ¼ãƒˆç•ªå·]ã€[パケットé€å‡ºé–“éš”]ã€ãŠã‚ˆã³ [プロトコル] ã«åŠ ãˆã¦ã€ç¾åœ¨ã® [インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½] ã®æœ‰åŠ¹çŠ¶æ…‹ãŒå–å¾—ã§ãã¾ã™ã€‚
+CMD_KeepGet_Args KeepGet
+CMD_KeepGet_COLUMN_1 ホストå
+CMD_KeepGet_COLUMN_2 ãƒãƒ¼ãƒˆç•ªå·
+CMD_KeepGet_COLUMN_3 パケットé€å‡ºé–“éš” (秒)
+CMD_KeepGet_COLUMN_4 プロトコル
+CMD_KeepGet_COLUMN_5 ç¾åœ¨ã®çŠ¶æ…‹
+
+
+# SyslogEnable コマンド
+CMD_SyslogEnable syslog é€ä¿¡æ©Ÿèƒ½ã®è¨­å®š
+CMD_SyslogEnable_Help syslog é€ä¿¡æ©Ÿèƒ½ã®ä½¿ç”¨æ–¹æ³•ã¨ä½¿ç”¨ã™ã‚‹ syslog サーãƒãƒ¼ã‚’設定ã—ã¾ã™ã€‚
+CMD_SyslogEnable_Args SyslogEnable [1|2|3] [/HOST:host:port]
+CMD_SyslogEnable_[1|2|3] syslog é€ä¿¡æ©Ÿèƒ½ä½¿ç”¨è¨­å®šã‚’ 1 ~ 3 ã®ã„ãšã‚Œã‹ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚\n1: サーãƒãƒ¼ãƒ­ã‚°ã‚’ syslog ã§é€ä¿¡ã€‚\n2: サーãƒãƒ¼ãŠã‚ˆã³ä»®æƒ³ HUB セキュリティログを syslog ã§é€ä¿¡ã€‚\n3: サーãƒãƒ¼ã€ä»®æƒ³ HUB セキュリティãŠã‚ˆã³ãƒ‘ケットログを syslog ã§é€ä¿¡ã€‚
+CMD_SyslogEnable_HOST [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€syslog サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãƒãƒ¼ãƒˆç•ªå·ã‚’çœç•¥ã™ã‚‹ã¨ 514 を使用ã—ã¾ã™ã€‚
+CMD_SyslogEnable_MINMAX syslog é€ä¿¡æ©Ÿèƒ½ä½¿ç”¨è¨­å®šã¯ 1 ~ 3 ã®ã„ãšã‚Œã‹ã®æ•´æ•°ã‚’指定ã—ã¦ãã ã•ã„。
+CMD_SyslogEnable_Prompt_123 syslog é€ä¿¡æ©Ÿèƒ½ä½¿ç”¨è¨­å®š (1 ~ 3):
+CMD_SyslogEnable_Prompt_HOST syslog サーãƒãƒ¼ã®æŒ‡å®š:
+
+
+# SyslogDisable コマンド
+CMD_SyslogDisable syslog é€ä¿¡æ©Ÿèƒ½ã®ç„¡åŠ¹åŒ–
+CMD_SyslogDisable_Help syslog é€ä¿¡æ©Ÿèƒ½ã‚’使用ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+CMD_SyslogDisable_Args SyslogDisable
+
+
+# SyslogGet コマンド
+CMD_SyslogGet syslog é€ä¿¡æ©Ÿèƒ½ã®å–å¾—
+CMD_SyslogGet_Help syslog é€ä¿¡æ©Ÿèƒ½ã®ç¾åœ¨ã®è¨­å®šå†…容をå–å¾—ã—ã¾ã™ã€‚syslog 機能ã®ä½¿ç”¨æ–¹æ³•ã®è¨­å®šã€ãŠã‚ˆã³ä½¿ç”¨ã™ã‚‹ syslog サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ãŒå–å¾—ã§ãã¾ã™ã€‚
+CMD_SyslogGet_Args SyslogGet
+CMD_SyslogGet_COLUMN_1 syslog é€ä¿¡æ©Ÿèƒ½ä½¿ç”¨è¨­å®š
+CMD_SyslogGet_COLUMN_2 syslog サーãƒãƒ¼ãƒ›ã‚¹ãƒˆå
+CMD_SyslogGet_COLUMN_3 syslog サーãƒãƒ¼ãƒãƒ¼ãƒˆç•ªå·
+
+
+# ConnectionList コマンド
+CMD_ConnectionList VPN Server ã«æŽ¥ç¶šä¸­ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ä¸€è¦§ã®å–å¾—
+CMD_ConnectionList_Help ç¾åœ¨ã€VPN Server ã«æŽ¥ç¶šä¸­ã® TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚ãŸã ã—ã€VPN セッションã¨ã—ã¦ç¢ºç«‹ã•ã‚ŒãŸ TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。VPN セッションã¨ã—ã¦ç¢ºç«‹ã•ã‚ŒãŸ TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ä¸€è¦§ã¯ã€SessionList コマンドを用ã„ã¦å–å¾—ã§ãã¾ã™ã€‚\n[コãƒã‚¯ã‚·ãƒ§ãƒ³å]ã€[接続元]ã€[接続時刻] ãŠã‚ˆã³ [種類] ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ConnectionList_Args ConnectionList
+
+
+# ConnectionGet コマンド
+CMD_ConnectionGet VPN Server ã«æŽ¥ç¶šä¸­ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®æƒ…å ±ã®å–å¾—
+CMD_ConnectionGet_Help VPN Server ã«æŽ¥ç¶šä¸­ã®æŒ‡å®šã•ã‚ŒãŸ TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³ã«é–¢ã™ã‚‹è©³ç´°ãªæƒ…報をå–å¾—ã—ã¾ã™ã€‚\n[コãƒã‚¯ã‚·ãƒ§ãƒ³å]ã€[コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¨®é¡ž]ã€[接続元ホストå]ã€[接続元 IP アドレス]ã€[接続元ãƒãƒ¼ãƒˆç•ªå· (TCP)]ã€[接続時刻]ã€[サーãƒãƒ¼è£½å“å]ã€[サーãƒãƒ¼ ãƒãƒ¼ã‚¸ãƒ§ãƒ³]ã€[サーãƒãƒ¼ ビルド番å·]ã€[クライアント製å“å]ã€[クライアントãƒãƒ¼ã‚¸ãƒ§ãƒ³]ã€[クライアントビルド番å·] ãŒå–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ConnectionGet_Args ConnectionGet [name]
+CMD_ConnectionGet_[name] 情報をå–å¾—ã™ã‚‹ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³åを指定ã—ã¾ã™ã€‚コãƒã‚¯ã‚·ãƒ§ãƒ³åã®ä¸€è¦§ã¯ã€ConnectionList コマンドã§å–å¾—ã§ãã¾ã™ã€‚
+CMD_ConnectionGet_PROMPT_NAME 情報をå–å¾—ã™ã‚‹ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³å:
+
+# ConnectionDisconnect コマンド
+CMD_ConnectionDisconnect VPN Server ã«æŽ¥ç¶šä¸­ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®åˆ‡æ–­
+CMD_ConnectionDisconnect_Help VPN Server ã«æŽ¥ç¶šä¸­ã®æŒ‡å®šã•ã‚ŒãŸ TCP/IP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’強制的ã«åˆ‡æ–­ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ConnectionDisconnect_Args ConnectionDisconnect [name]
+CMD_ConnectionDisconnect_[name] 切断ã™ã‚‹ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³åを指定ã—ã¾ã™ã€‚コãƒã‚¯ã‚·ãƒ§ãƒ³åã®ä¸€è¦§ã¯ ConnectionList コマンドã§å–å¾—ã§ãã¾ã™ã€‚
+CMD_ConnectionDisconnect_PROMPT_NAME 切断ã™ã‚‹ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³å:
+
+
+# BridgeDeviceList コマンド
+CMD_BridgeDeviceList ローカルブリッジã«ä½¿ç”¨ã§ãã‚‹ LAN カード一覧ã®å–å¾—
+CMD_BridgeDeviceList_Help ローカルブリッジ接続ã§ã€ãƒ–リッジ先ã®ãƒ‡ãƒã‚¤ã‚¹ã¨ã—ã¦ä½¿ç”¨ã§ãã‚‹ Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã“ã§è¡¨ç¤ºã•ã‚Œã‚‹ãƒ‡ãƒã‚¤ã‚¹åã¯ã€BridgeCreate コマンドã§ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_BridgeDeviceList_Args BridgeDeviceList
+
+
+# BridgeList コマンド
+CMD_BridgeList ローカルブリッジ接続ã®ä¸€è¦§ã®å–å¾—
+CMD_BridgeList_Help ç¾åœ¨å®šç¾©ã•ã‚Œã¦ã„るローカルブリッジ接続ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nローカルブリッジ接続ã®ä»®æƒ³ HUB åã¨ã€ãƒ–リッジ先㮠Ethernet デãƒã‚¤ã‚¹ (LAN カード) åã€ã¾ãŸã¯ tap デãƒã‚¤ã‚¹åãŠã‚ˆã³å‹•ä½œçŠ¶æ³ãŒå–å¾—ã§ãã¾ã™ã€‚
+CMD_BridgeList_Args BridgeList
+
+
+# BridgeCreate コマンド
+CMD_BridgeCreate ローカルブリッジ接続ã®ä½œæˆ
+CMD_BridgeCreate_Help æ–°ã—ã„ローカルブリッジ接続を VPN Server 上ã«ä½œæˆã—ã¾ã™ã€‚\nローカルブリッジを使用ã™ã‚‹ã¨ã€ã“ã® VPN Server 上ã§å‹•ä½œã™ã‚‹ä»®æƒ³ HUB ã¨ã€ç‰©ç†çš„㪠Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã¨ã®é–“ã§ãƒ¬ã‚¤ãƒ¤ 2 ブリッジ接続を構æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nシステム㫠tap デãƒã‚¤ã‚¹ (仮想ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹) を作æˆã—ã€ä»®æƒ³ HUB ã¨ã®é–“ã§ãƒ–リッジ接続ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ (tap デãƒã‚¤ã‚¹ã¯ Linux 版ã®ã¿ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™)。\nブリッジ先㮠Ethernet デãƒã‚¤ã‚¹ (LAN カード) ã«ã¯ã€ç¨¼åƒä¸­ã®ä»»æ„ã® LAN カードã¨ã®é–“ã§ãƒ–リッジã§ãã¾ã™ãŒã€é«˜è² è·ç’°å¢ƒã«ãŠã„ã¦ã¯ãƒ–リッジ専用㫠LAN カードを用æ„ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_BridgeCreate_Args BridgeCreate [hubname] [/DEVICE:device_name] [/TAP:yes|no]
+CMD_BridgeCreate_[hubname] ブリッジã™ã‚‹ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚仮想 HUB ã®ä¸€è¦§ã¯ã€HubList コマンドã§å–å¾—ã§ãã¾ã™ã€‚ãŸã ã—ã€å¿…ãšã—ã‚‚ç¾åœ¨å‹•ä½œã—ã¦ã„る仮想 HUB åを指定ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。ç¾åœ¨å‹•ä½œã—ã¦ã„ãªã„ã€ã¾ãŸã¯å­˜åœ¨ã—ãªã„仮想 HUB åを指定ã™ã‚‹ã¨ã€ãã®ä»®æƒ³ HUB ãŒå®Ÿéš›ã«å‹•ä½œã‚’開始ã—ãŸéš›ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続ãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+CMD_BridgeCreate_DEVICE ブリッジ先㮠Ethernet デãƒã‚¤ã‚¹ (LAN カード) åã€ã¾ãŸã¯ tap デãƒã‚¤ã‚¹åを指定ã—ã¾ã™ã€‚Ethernet デãƒã‚¤ã‚¹åã®ä¸€è¦§ã¯ã€BridgeDeviceList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_BridgeCreate_TAP ブリッジ先ã¨ã—㦠LAN カードã§ã¯ãªãã€tap デãƒã‚¤ã‚¹ã‚’使用ã™ã‚‹å ´åˆã¯ yes を指定ã—ã¾ã™ (Linux 版ã®ã¿ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¾ã™)。çœç•¥ã—ãŸå ´åˆã¯ no ã¨è¦‹ãªã•ã‚Œã¾ã™ã€‚
+CMD_BridgeCreate_PROMPT_HUBNAME ブリッジã™ã‚‹ä»®æƒ³ HUB å:
+CMD_BridgeCreate_PROMPT_DEVICE ブリッジ先ã®ãƒ‡ãƒã‚¤ã‚¹å:
+CMD_BridgeCreate_PROMPT_TAP tap デãƒã‚¤ã‚¹ã‚’使用ã—ã¾ã™ã‹ (yes/no):
+
+
+# BridgeDelete コマンド
+CMD_BridgeDelete ローカルブリッジ接続ã®å‰Šé™¤
+CMD_BridgeDelete_Help 既存ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続を削除ã—ã¾ã™ã€‚ç¾åœ¨ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ接続ã®ä¸€è¦§ã¯ã€BridgeDeviceList コマンドã§å–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_BridgeDelete_Args BridgeDelete [hubname] [/DEVICE:device_name]
+CMD_BridgeDelete_[hubname] 削除ã™ã‚‹ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã®ã€ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚
+CMD_BridgeDelete_DEVICE 削除ã™ã‚‹ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã®ã€ãƒ‡ãƒã‚¤ã‚¹å (LAN カードåã¾ãŸã¯ tap デãƒã‚¤ã‚¹å) を指定ã—ã¾ã™ã€‚
+CMD_BridgeDelete_PROMPT_HUBNAME 削除ã™ã‚‹ãƒ–リッジã®ä»®æƒ³ HUB å:
+CMD_BridgeDelete_PROMPT_DEVICE 削除ã™ã‚‹ãƒ–リッジã®ãƒ‡ãƒã‚¤ã‚¹å:
+
+
+# Caps コマンド
+CMD_Caps サーãƒãƒ¼ã®æ©Ÿèƒ½ãƒ»èƒ½åŠ›ä¸€è¦§ã®å–å¾—
+CMD_Caps_Help ç¾åœ¨æŽ¥ç¶šã—ã¦ç®¡ç†ã—ã¦ã„ã‚‹ VPN Server ã®æŒã¤æ©Ÿèƒ½ã¨èƒ½åŠ›ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nVPN Server ã®æ©Ÿèƒ½ã‚„能力ã¯ã€å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ã‚¨ãƒ‡ã‚£ã‚·ãƒ§ãƒ³ã‚„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚ˆã£ã¦ç•°ãªã‚Šã¾ã™ã€‚コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã«ã‚るコマンドã§ã‚‚ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ©Ÿèƒ½ã‚„能力ã«ã‚ˆã£ã¦ã¯å‹•ä½œã—ãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€æŽ¥ç¶šå…ˆã® VPN Server ã®èƒ½åŠ›ã‚’調査ã—ã¦å ±å‘Šã—ã¾ã™ã€‚\nVPN Server ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æ–¹ãŒã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚ˆã‚Šã‚‚æ–°ã—ãã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ãŒæŠŠæ¡ã—ã¦ã„ãªã„機能ãŒã‚ã‚‹å ´åˆã¯ã€ãã®å†…部文字列 (変数å) ãŒã€ãã®ã¾ã¾è¡¨ç¤ºã•ã‚Œã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_Caps_Args Caps
+
+
+# Reboot コマンド
+CMD_Reboot VPN Server サービスã®å†èµ·å‹•
+CMD_Reboot_Help VPN Server サービスをå†èµ·å‹•ã—ã¾ã™ã€‚\nVPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã¨ã€ç¾åœ¨æŽ¥ç¶šã—ã¦ã„るセッションや TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã€å†èµ·å‹•ãŒå®Œäº†ã™ã‚‹ã¾ã§æ–°ãŸãªæŽ¥ç¶šã¯å—ã‘付ã‘ãªããªã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã¯ã€VPN Server サービスプログラムã®ã¿ãŒå†èµ·å‹•ã•ã‚Œã€VPN Server ãŒå‹•ä½œã—ã¦ã„る物ç†çš„ãªã‚³ãƒ³ãƒ”ュータãŒå†èµ·å‹•ã™ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã®ç®¡ç†ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚‚切断ã•ã‚Œã‚‹ãŸã‚ã€ç®¡ç†ã‚’続行ã™ã‚‹ã«ã¯å†æŽ¥ç¶šã—ã¦ãã ã•ã„。\nã¾ãŸã€/RESETCONFIG:yes パラメータを指定ã™ã‚‹ã¨ã€ç¾åœ¨ã® VPN Server ãŒæŒã£ã¦ã„るコンフィグレーションファイル (.config) ã®å†…容をåˆæœŸåŒ–ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_Reboot_Args Reboot [/RESETCONFIG:yes|no]
+CMD_Reboot_RESETCONFIG yes を指定ã™ã‚‹ã¨ã€ç¾åœ¨ã® VPN Server ãŒæŒã£ã¦ã„るコンフィグレーションファイル (.config) ã®å†…容をåˆæœŸåŒ–ã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータã¯æ…Žé‡ã«è¨­å®šã—ã¦ãã ã•ã„。
+
+
+# ConfigGet コマンド
+CMD_ConfigGet VPN Server ã®ç¾åœ¨ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å–å¾—
+CMD_ConfigGet_Help VPN Server ã®ã€ç¾åœ¨ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å†…容を構造化ã—ãŸãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ« (.config ファイル) ã¨ã—ã¦å–å¾—ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ãŸçž¬é–“ã® VPN Server 内ã®çŠ¶æ…‹ãŒå–å¾—ã§ãã¾ã™ã€‚\nコンフィグレーションファイルã®å†…容ã¯ã€ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ç”»é¢ä¸Šã«ãã®ã¾ã¾è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚パラメータã§ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã™ã‚‹ã¨ã€ãã®ãƒ•ã‚¡ã‚¤ãƒ«åã§å†…容ãŒä¿å­˜ã•ã‚Œã¾ã™ã€‚\nコンフィグレーションファイルã¯ã€é€šå¸¸ã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ç­‰ã§ç·¨é›†å¯èƒ½ã§ã™ã€‚編集ã—ãŸã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ VPN Server ã«æ›¸ã込むã«ã¯ã€ConfigSet コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ConfigGet_Args ConfigGet [path]
+CMD_ConfigGet_[path] コンフィグレーションファイルã®å†…容をファイルã«ä¿å­˜ã—ãŸã„å ´åˆã¯ã€ãã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚何も指定ã—ãªã„å ´åˆã¯ã€ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å†…容ã¯ç”»é¢ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚コンフィグレーションファイルã«ãƒžãƒ«ãƒãƒã‚¤ãƒˆæ–‡å­—ãŒå«ã¾ã‚Œã‚‹å ´åˆã¯ã€Unicode (UTF-8) ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+CMD_ConfigGet_FILENAME Config å: "%S", サイズ: %u
+CMD_ConfigGet_FILE_SAVE_FAILED 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+
+
+# ConfigSet コマンド
+CMD_ConfigSet VPN Server ã¸ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®æ›¸ãè¾¼ã¿
+CMD_ConfigSet_Help VPN Server ã«ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’書ãè¾¼ã¿ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€æŒ‡å®šã—ãŸã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容㌠VPN Server ã«é©ç”¨ã•ã‚Œã€VPN Server プログラムã¯è‡ªå‹•çš„ã«å†èµ·å‹•ã•ã‚Œã€æ–°ã—ã„コンフィグレーションã®å†…容ã«å¾“ã£ã¦å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nコンフィグレーションファイルã¯ã€ã™ã¹ã¦ã®å†…容を管ç†è€…ãŒè¨˜è¿°ã™ã‚‹ã®ã¯å›°é›£ã§ã‚ã‚‹ãŸã‚ã€ConfigGet コマンドã§ã€ã¾ãšç¾åœ¨ã® VPN Server ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å†…容をå–å¾—ã—ã¦ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã—ã€ãã®å†…容を通常ã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ãªã©ã§ç·¨é›†ã—ãŸã‚‚ã®ã‚’ ConfigSet コマンド㧠VPN Server ã«æ›¸ã戻ã™ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Server ã«é–¢ã™ã‚‹è©³ã—ã„知識をãŠæŒã¡ã®æ–¹ã®ãŸã‚ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã‚ã‚Šã€ä¸æ­£ãªã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’書ã込んã å ´åˆã¯ã€ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã‚Šç¾åœ¨ã®è¨­å®šå†…容ãŒå¤±ã‚ã‚ŒãŸã‚Šã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã€å分注æ„ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_ConfigSet_Args ConfigSet [path]
+CMD_ConfigSet_[path] 書ã込むコンフィグレーションファイルã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚書ã込むファイルã«ãƒžãƒ«ãƒãƒã‚¤ãƒˆæ–‡å­—ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€Unicode (UTF-8) ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_ConfigSet_PROMPT_PATH サーãƒãƒ¼ã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ Config ファイルã®ãƒ‘スå:
+CMD_ConfigSet_FILE_LOAD_FAILED 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+
+
+# RouterList コマンド
+CMD_RouterList 仮想レイヤ 3 スイッãƒä¸€è¦§ã®å–å¾—
+CMD_RouterList_Help VPN Server 上ã«å®šç¾©ã•ã‚Œã¦ã„る仮想レイヤ 3 スイッãƒã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚仮想レイヤ 3 スイッãƒã® [スイッãƒå]ã€[動作状æ³]ã€[インターフェイス数]ã€[ルーティングテーブル数] ãŒå–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_RouterList_Args RouterList
+
+
+# RouterAdd コマンド
+CMD_RouterAdd æ–°ã—ã„仮想レイヤ 3 スイッãƒã®å®šç¾©
+CMD_RouterAdd_Help VPN Server 上ã«ã€æ–°ã—ã„仮想レイヤ 3 スイッãƒã‚’定義ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\n\n[仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã«ã¤ã„ã¦ã®èª¬æ˜Ž]\nã“ã® VPN Server 内ã§å‹•ä½œã—ã¦ã„る複数ã®ä»®æƒ³ HUB é–“ã§ã€ä»®æƒ³ã®ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’定義ã—ã€ç•°ãªã£ãŸ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯é–“をルーティングã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\n[仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã«é–¢ã™ã‚‹ã”注æ„]\n仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŠã‚ˆã³ IP ルーティングã«é–¢ã™ã‚‹è©³ã—ã„知識をãŠæŒã¡ã®æ–¹ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚通常㮠VPN 機能を使用ã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\n仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å ´åˆã¯ã€IP ルーティングã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã®ä¸Šã§ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ä¸Žãˆã‚‹å½±éŸ¿ã‚’å分考慮ã—ã¦ã‹ã‚‰è¨­å®šã—ã¦ãã ã•ã„。
+CMD_RouterAdd_Args RouterAdd [name]
+CMD_RouterAdd_[name] æ–°ã—ã作æˆã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚æ—¢ã«å­˜åœ¨ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã¨åŒä¸€ã®åå‰ã‚’付ã‘ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_RouterAdd_PROMPT_NAME 作æˆã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰:
+
+
+# RouterDelete コマンド
+CMD_RouterDelete 仮想レイヤ 3 スイッãƒã®å‰Šé™¤
+CMD_RouterDelete_Help VPN Server 上ã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€æ—¢å­˜ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’削除ã—ã¾ã™ã€‚指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒå‹•ä½œä¸­ã®å ´åˆã¯ã€è‡ªå‹•çš„ã«å‹•ä½œã‚’åœæ­¢ã—ã¦ã‹ã‚‰å‰Šé™¤ã‚’è¡Œãªã„ã¾ã™ã€‚\n既存ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€RouterList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_RouterDelete_Args RouterDelete [name]
+CMD_RouterDelete_[name] 削除ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterDelete_PROMPT_NAME 削除ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰:
+
+
+# RouterStart コマンド
+CMD_RouterStart 仮想レイヤ 3 スイッãƒã®å‹•ä½œã®é–‹å§‹
+CMD_RouterStart_Help VPN Server 上ã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€æ—¢å­˜ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®å‹•ä½œãŒåœæ­¢ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã®å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\n既存ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€RouterList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\n\n[仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã«ã¤ã„ã¦ã®èª¬æ˜Ž]\nã“ã® VPN Server 内ã§å‹•ä½œã—ã¦ã„ã‚‹ã€è¤‡æ•°ã®ä»®æƒ³ HUB é–“ã§ä»®æƒ³ã®ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’定義ã—ã€ç•°ãªã£ãŸ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯é–“をルーティングã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\n[仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã«é–¢ã™ã‚‹ã”注æ„]\n仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŠã‚ˆã³ IP ルーティングã«é–¢ã™ã‚‹è©³ã—ã„知識をãŠæŒã¡ã®æ–¹ã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚通常㮠VPN 機能を使用ã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\n仮想レイヤ 3 スイッãƒæ©Ÿèƒ½ã‚’使用ã™ã‚‹å ´åˆã¯ã€IP ルーティングã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã®ä¸Šã§ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ä¸Žãˆã‚‹å½±éŸ¿ã‚’å分考慮ã—ã¦ã‹ã‚‰è¨­å®šã—ã¦ãã ã•ã„。
+CMD_RouterStart_Args RouterStart [name]
+CMD_RouterStart_[name] 開始ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterStart_PROMPT_NAME 開始ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰:
+
+
+# RouterStop コマンド
+CMD_RouterStop 仮想レイヤ 3 スイッãƒã®å‹•ä½œã®åœæ­¢
+CMD_RouterStop_Help VPN Server 上ã«å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€æ—¢å­˜ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®å‹•ä½œãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã®å‹•ä½œã‚’åœæ­¢ã—ã¾ã™ã€‚\n既存ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€RouterList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚
+CMD_RouterStop_Args RouterStop [name]
+CMD_RouterStop_[name] åœæ­¢ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterStop_PROMPT_NAME åœæ­¢ã™ã‚‹ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®åå‰:
+
+
+# RouterIfList コマンド
+CMD_RouterIfList 仮想レイヤ 3 スイッãƒã«ç™»éŒ²ã•ã‚Œã¦ã„るインターフェイス一覧ã®å–å¾—
+CMD_RouterIfList_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒå®šç¾©ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\n1 ã¤ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ã¯ã€è¤‡æ•°å€‹ã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã¨ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n仮想インターフェイスã¯ä»®æƒ³ HUB ã«é–¢é€£ä»˜ã‘られã€ä»®æƒ³ HUB ãŒå‹•ä½œã—ã¦ã„ã‚‹ã¨ãã«ã€ä»®æƒ³ HUB 内㧠1 å°ã® IP ホストã®ã‚ˆã†ã«å‹•ä½œã—ã¾ã™ã€‚複数ã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦ã€ãã‚Œãžã‚Œåˆ¥ã€…ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æ‰€å±žã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒå®šç¾©ã•ã‚Œã¦ã„ã‚‹ã¨ãã€ãれらã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹é–“㧠IP ルーティングãŒè‡ªå‹•çš„ã«è¡Œã‚ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_RouterIfList_Args RouterIfList [name]
+CMD_RouterIfList_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterIfList_PROMPT_NAME 仮想レイヤ 3 スイッãƒã®åå‰:
+
+
+# RouterIfAdd コマンド
+CMD_RouterIfAdd 仮想レイヤ 3 スイッãƒã¸ã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®è¿½åŠ 
+CMD_RouterIfAdd_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ã€åŒã˜ VPN Server 上ã§å‹•ä½œã—ã¦ã„る仮想 HUB ã¸æŽ¥ç¶šã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã‚’追加ã—ã¾ã™ã€‚\n1 ã¤ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ã¯ã€è¤‡æ•°å€‹ã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã¨ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルを定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n仮想インターフェイスã¯ä»®æƒ³ HUB ã«é–¢é€£ä»˜ã‘られã€ä»®æƒ³ HUB ãŒå‹•ä½œã—ã¦ã„ã‚‹ã¨ãã«ã€ä»®æƒ³ HUB 内㧠1 å°ã® IP ホストã®ã‚ˆã†ã«å‹•ä½œã—ã¾ã™ã€‚複数ã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦ã€ãã‚Œãžã‚Œåˆ¥ã€…ã® IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æ‰€å±žã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒå®šç¾©ã•ã‚Œã¦ã„ã‚‹ã¨ãã€ãれらã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹é–“㧠IP ルーティングãŒè‡ªå‹•çš„ã«è¡Œã‚ã‚Œã¾ã™ã€‚\n仮想インターフェイスãŒæ‰€å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç©ºé–“ã¨ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹è‡ªèº«ã® IP アドレスを定義ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã¾ãŸã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒæŽ¥ç¶šã™ã‚‹å…ˆã®ä»®æƒ³ HUB åを指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n仮想 HUB åã«ã¯ç¾åœ¨å­˜åœ¨ã—ã¦ã„ãªã„仮想 HUB を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚\n仮想インターフェイスã¯ã€ä»®æƒ³ HUB 内㧠1 ã¤ã® IP アドレスをæŒã¤å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€ãã® IP アドレスã®å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹å¿…è¦ã‚‚ã‚ã‚Šã¾ã™ã€‚\n複数ã®ä»®æƒ³ HUB 内㮠IP 空間åŒå£«ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã‚’経由ã—ãŸãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã¯ã€ã“ã“ã§æŒ‡å®šã—㟠IP アドレスã«åŸºã¥ã„ã¦å‹•ä½œã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€æ“作対象ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒåœæ­¢ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—åœæ­¢ã—ã¦ã„ãªã„å ´åˆã¯ã€RouterStop コマンドã§åœæ­¢ã•ã›ã¦ã‹ã‚‰ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ãã ã•ã„。
+CMD_RouterIfAdd_Args RouterIfAdd [name] [/HUB:hub] [/IP:ip/mask]
+CMD_RouterIfAdd_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterIfAdd_HUB æ–°ã—ã追加ã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB åを指定ã—ã¾ã™ã€‚仮想 HUB ã®ä¸€è¦§ã¯ã€HubList コマンドã§å–å¾—ã§ãã¾ã™ã€‚ãŸã ã—ã€å¿…ãšã—ã‚‚ç¾åœ¨å‹•ä½œã—ã¦ã„る仮想 HUB åを指定ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。ç¾åœ¨å‹•ä½œã—ã¦ã„ãªã„ã€ã¾ãŸã¯å­˜åœ¨ã—ãªã„仮想 HUB åを指定ã™ã‚‹ã¨ã€ãã®ä»®æƒ³ HUB ãŒå®Ÿéš›ã«å‹•ä½œã‚’開始ã—ãŸéš›ã«ã€ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+CMD_RouterIfAdd_IP [IP アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯] ã®å½¢å¼ã§ã€æ–°ã—ã追加ã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®æŒã¤ IP アドレスã¨ã€ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã—ã¾ã™ã€‚IP アドレス㯠192.168.0.1 ã®ã‚ˆã†ã«ã€10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã¯ 255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚
+CMD_RouterIfAdd_PROMPT_NAME 仮想レイヤ 3 スイッãƒã®åå‰:
+CMD_RouterIfAdd_PROMPT_HUB 仮想インターフェイスã®æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB å:
+CMD_RouterIfAdd_PROMPT_IP IP アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯:
+
+
+# RouterIfDel コマンド
+CMD_RouterIfDel 仮想レイヤ 3 スイッãƒã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®å‰Šé™¤
+CMD_RouterIfDel_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒå†…ã«ã€ã™ã§ã«å®šç¾©ã•ã‚Œã¦ã„る仮想インターフェイスを削除ã—ã¾ã™ã€‚\nç¾åœ¨å®šç¾©ã•ã‚Œã¦ã„る仮想インターフェイスã®ä¸€è¦§ã¯ã€RouterIfList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€æ“作対象ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒåœæ­¢ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—åœæ­¢ã—ã¦ã„ãªã„å ´åˆã¯ã€RouterStop コマンドã§åœæ­¢ã•ã›ã¦ã‹ã‚‰ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ãã ã•ã„。
+CMD_RouterIfDel_Args RouterIfDel [name] [/HUB:hub]
+CMD_RouterIfDel_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterIfDel_HUB 削除ã™ã‚‹ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB åを指定ã—ã¾ã™ã€‚
+
+
+# RouterTableList コマンド
+CMD_RouterTableList 仮想レイヤ 3 スイッãƒã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ル一覧ã®å–å¾—
+CMD_RouterTableList_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã«ã€ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルãŒå®šç¾©ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\n仮想レイヤ 3 スイッãƒã® IP ルーティングエンジンã¯ã€IP パケットã®å®›å…ˆ IP アドレスãŒã€å„仮想インターフェイスã®æ‰€å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã„ãšã‚Œã«ã‚‚所属ã—ãªã„å ´åˆã¯ã€ã“ã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルをå‚ç…§ã—ã¦ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚’è¡Œã„ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_RouterTableList_Args RouterTableList [name]
+CMD_RouterTableList_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterTableList_PROMPT_NAME 仮想レイヤ 3 スイッãƒã®åå‰:
+
+
+# RouterTableAdd コマンド
+CMD_RouterTableAdd 仮想レイヤ 3 スイッãƒã¸ã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルエントリã®è¿½åŠ 
+CMD_RouterTableAdd_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルã«ã€æ–°ã—ã„ルーティングテーブルエントリを追加ã—ã¾ã™ã€‚\n仮想レイヤ 3 スイッãƒã® IP ルーティングエンジンã¯ã€IP パケットã®å®›å…ˆ IP アドレスãŒã€å„仮想インターフェイスã®æ‰€å±žã™ã‚‹ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã„ãšã‚Œã«ã‚‚所属ã—ãªã„å ´åˆã€ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルをå‚ç…§ã—ã¦ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚’è¡Œã„ã¾ã™ã€‚\n仮想レイヤ 3 スイッãƒã«è¿½åŠ ã™ã‚‹ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルã®ã‚¨ãƒ³ãƒˆãƒªã®å†…容を指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ゲートウェイアドレスã¨ã—ã¦ã¯ã€ã“ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒã®ä»®æƒ³ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®ã†ã¡ã€ã„ãšã‚Œã‹ã¨åŒã˜ IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æ‰€å±žã™ã‚‹ IP アドレスを指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€æ“作対象ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒåœæ­¢ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—åœæ­¢ã—ã¦ã„ãªã„å ´åˆã¯ã€RouterStop コマンドã§åœæ­¢ã•ã›ã¦ã‹ã‚‰ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ãã ã•ã„。
+CMD_RouterTableAdd_Args RouterTableAdd [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableAdd_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterTableAdd_NETWORK [IP アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯] ã®å½¢å¼ã§ã€æ–°ã—ã追加ã™ã‚‹ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルエントリã®ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã—ã¾ã™ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã€192.168.0.1 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã¯ã€255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚0.0.0.0/0.0.0.0 を指定ã™ã‚‹ã¨ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ãƒˆã®æ„味ã«ãªã‚Šã¾ã™ã€‚
+CMD_RouterTableAdd_GATEWAY ゲートウェイ㮠IP アドレスを指定ã—ã¾ã™ã€‚
+CMD_RouterTableAdd_METRIC メトリック値を指定ã—ã¾ã™ã€‚1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_RouterTableAdd_PROMPT_NAME 仮想レイヤ 3 スイッãƒã®åå‰:
+CMD_RouterTableAdd_PROMPT_NETWORK ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯:
+CMD_RouterTableAdd_PROMPT_GATEWAY ゲートウェイアドレス:
+CMD_RouterTableAdd_PROMPT_METRIC メトリック値:
+
+
+# RouterTableDel コマンド
+CMD_RouterTableDel 仮想レイヤ 3 スイッãƒã®ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルエントリã®å‰Šé™¤
+CMD_RouterTableDel_Help 指定ã—ãŸä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒå†…ã«å®šç¾©ã•ã‚Œã¦ã„るルーティングテーブルã®ã‚¨ãƒ³ãƒˆãƒªã‚’削除ã—ã¾ã™ã€‚\nã™ã§ã«å®šç¾©ã•ã‚Œã¦ã„るルーティンクテーブルエントリã®ä¸€è¦§ã¯ã€RouterTableList コマンドã§å–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€æ“作対象ã®ä»®æƒ³ãƒ¬ã‚¤ãƒ¤ 3 スイッãƒãŒåœæ­¢ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—åœæ­¢ã—ã¦ã„ãªã„å ´åˆã¯ã€RouterStop コマンドã§åœæ­¢ã•ã›ã¦ã‹ã‚‰ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ãã ã•ã„。
+CMD_RouterTableDel_Args RouterTableDel [name] [/NETWORK:ip/mask] [/GATEWAY:gwip] [/METRIC:metric]
+CMD_RouterTableDel_[name] 仮想レイヤ 3 スイッãƒã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterTableDel_NETWORK [IP アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯] ã®å½¢å¼ã§ã€å‰Šé™¤ã™ã‚‹ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ†ãƒ¼ãƒ–ルエントリã®ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’指定ã—ã¾ã™ã€‚
+CMD_RouterTableDel_GATEWAY ゲートウェイ㮠IP アドレスを指定ã—ã¾ã™ã€‚
+CMD_RouterTableDel_METRIC メトリック値を指定ã—ã¾ã™ã€‚1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+# LogFileList コマンド
+CMD_LogFileList ログファイル一覧ã®å–å¾—
+CMD_LogFileList_Help VPN Server ã®ã‚³ãƒ³ãƒ”ュータ上ã«ä¿å­˜ã•ã‚Œã¦ã„ã‚‹ã€VPN Server ãŒå‡ºåŠ›ã—ãŸãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚ã“ã“ã§è¡¨ç¤ºã•ã‚Œã‚‹ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—㦠LogFileGet コマンドを呼ã³å‡ºã™ã“ã¨ã«ã‚ˆã‚Šã€ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容をダウンロードã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚\nVPN Server ã«ã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®ãƒ‘ケットログã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã€ãŠã‚ˆã³ VPN Server ã®ã‚µãƒ¼ãƒãƒ¼ ログを表示ã¾ãŸã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n仮想 HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ç®¡ç†å¯¾è±¡ã®ä»®æƒ³ HUB ã®ãƒ‘ケットログã¨ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã®ã¿ã‚’表示ã¾ãŸã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_LogFileList_Args LogFileList
+CMD_LogFileList_START ログファイル一覧をå–å¾—ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã«ã¯ã€æ™‚é–“ãŒã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+CMD_LogFileList_NUM_LOGS 全部㧠%u 個ã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚Šã¾ã™ã€‚
+
+
+# LogFileGet コマンド
+CMD_LogFileGet ログファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰
+CMD_LogFileGet_Help VPN Server ã®ã‚³ãƒ³ãƒ”ュータ上ã«ä¿å­˜ã•ã‚Œã¦ã„るログファイルをダウンロードã—ã¾ã™ã€‚ログファイルをダウンロードã™ã‚‹ã«ã¯ã€ã¾ãš LogFileList コマンドã§ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¸€è¦§ã‚’表示ã—ã¦ã‹ã‚‰ã€æ¬¡ã« LogFileGet コマンドã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚VPN Server ã«ã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®ãƒ‘ケットログã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã€ãŠã‚ˆã³ VPN Server ã®ã‚µãƒ¼ãƒãƒ¼ ログを表示ã¾ãŸã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚仮想 HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ç®¡ç†å¯¾è±¡ã®ä»®æƒ³ HUB ã®ãƒ‘ケットログã¨ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã®ã¿ã‚’表示ã€ã¾ãŸã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nパラメータã¨ã—ã¦ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ãŸå ´åˆã¯ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€ãã®ãƒ•ã‚¡ã‚¤ãƒ«åã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚ファイルåを指定ã—ãªã‹ã£ãŸå ´åˆã¯ã€ç”»é¢ä¸Šã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\nログファイルã®ã‚µã‚¤ã‚ºã¯ã€å·¨å¤§ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã®ã§ã€æ³¨æ„ã—ã¦ãã ã•ã„。
+CMD_LogFileGet_Args LogFileGet [name] [/SERVER:server] [/SAVEPATH:savepath]
+CMD_LogFileGet_[name] ダウンロードã™ã‚‹ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚LogFileList コマンドã§ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãるログファイルåã®ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã™ã€‚
+CMD_LogFileGet_SERVER クラスタコントローラã«å¯¾ã—ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰è¦æ±‚ã‚’è¡Œã†å ´åˆã¯ã€ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ãŒä¿å­˜ã•ã‚Œã¦ã„るサーãƒãƒ¼åを指定ã—ã¾ã™ã€‚LogFileGet コマンドã§è¡¨ç¤ºã•ã‚Œã‚‹ã‚µãƒ¼ãƒãƒ¼ã‚’指定ã—ã¦ãã ã•ã„。
+CMD_LogFileGet_SAVEPATH ダウンロードã—ãŸãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ä¿å­˜ã™ã‚‹å ´åˆã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ç”»é¢ä¸Šã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_LogFileGet_PROMPT_NAME ダウンロードã™ã‚‹ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_LogFileGet_START ログファイルをダウンロードã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã«ã¯ã€æ™‚é–“ãŒã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...
+CMD_LogFileGet_FAILED ダウンロードã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+CMD_LogFileGet_SAVE_FAILED 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã«æ›¸ãè¾¼ã‚ã¾ã›ã‚“。
+CMD_LogFileGet_FILESIZE ログファイルã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚º: %u
+
+
+# HubCreate コマンド
+CMD_HubCreate æ–°ã—ã„仮想 HUB ã®ä½œæˆ
+CMD_HubCreate_Help VPN Server 上ã«æ–°ã—ã„仮想 HUB を作æˆã—ã¾ã™ã€‚\n作æˆã—ãŸä»®æƒ³ HUB ã¯ã€ç›´ã¡ã«å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nVPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«å¯¾ã—ã¦ã®ã¿æœ‰åŠ¹ã§ã™ã€‚ã¾ãŸã€æ–°ã—ã„仮想 HUB ã¯ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ä»®æƒ³ HUB ã¨ã—ã¦å‹•ä½œã—ã¾ã™ã€‚HubSetStatic コマンドã§ã€ã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ä»®æƒ³ HUB ã«å¤‰æ›´ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã™ã§ã« VPN Server 上ã«å­˜åœ¨ã™ã‚‹ä»®æƒ³ HUB ã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€HubList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nãªãŠã€ã‚¯ãƒ©ã‚¹ã‚¿ä¸Šã§ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«å¯¾ã—ã¦ä»®æƒ³ HUB ã®ä½œæˆã‚³ãƒžãƒ³ãƒ‰ã‚’発行ã™ã‚‹å ´åˆã¯ã€HubCreateStatic コマンドã¾ãŸã¯ HubCreateDynamic コマンドを使用ã—ã¦ãã ã•ã„ (クラスタコントローラã«å¯¾ã—㦠HubCreate コマンドを使用ã™ã‚‹ã¨ HubCreateDynamic コマンドã¨åŒç­‰ã«å‹•ä½œã—ã¾ã™)。
+CMD_HubCreate_Args HubCreate [name] [/PASSWORD:password]
+CMD_HubCreate_[name] 作æˆã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_HubCreate_PASSWORD 作æˆã™ã‚‹ä»®æƒ³ HUB ã®ç®¡ç†ãƒ‘スワードを設定ã™ã‚‹å ´åˆã¯ã€ãã®ç®¡ç†ãƒ‘スワードを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€å…¥åŠ›ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_HubCreate_PROMPT_NAME 作æˆã™ã‚‹ä»®æƒ³ HUB ã®åå‰:
+
+
+# HubCreateDynamic コマンド
+CMD_HubCreateDynamic æ–°ã—ã„ダイナミック仮想 HUB ã®ä½œæˆ (クラスタリング用)
+CMD_HubCreateDynamic_Help VPN Server 上ã«æ–°ã—ã„ダイナミック仮想 HUB を作æˆã—ã¾ã™ã€‚\n作æˆã—ãŸä»®æƒ³ HUB ã¯ã€ç›´ã¡ã«å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nVPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«å¯¾ã—ã¦ã®ã¿æœ‰åŠ¹ã§ã™ã€‚ã¾ãŸã€æ–°ã—ã„仮想 HUB ã¯ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ä»®æƒ³ HUB ã¨ã—ã¦å‹•ä½œã—ã¾ã™ã€‚HubSetStatic コマンドã§ã€ã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ä»®æƒ³ HUB ã«å¤‰æ›´ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã™ã§ã« VPN Server 上ã«å­˜åœ¨ã™ã‚‹ä»®æƒ³ HUB ã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€HubList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã€ã¾ãŸã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_HubCreateDynamic_Args HubCreateDynamic [name] [/PASSWORD:password]
+CMD_HubCreateDynamic_[name] 作æˆã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_HubCreateDynamic_PASSWORD 作æˆã™ã‚‹ä»®æƒ³ HUB ã®ç®¡ç†ãƒ‘スワードを設定ã™ã‚‹å ´åˆã¯ã€ãã®ç®¡ç†ãƒ‘スワードを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€å…¥åŠ›ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# HubCreateStatic コマンド
+CMD_HubCreateStatic æ–°ã—ã„スタティック仮想 HUB ã®ä½œæˆ (クラスタリング用)
+CMD_HubCreateStatic_Help VPN Server 上ã«æ–°ã—ã„スタティック仮想 HUB を作æˆã—ã¾ã™ã€‚\n作æˆã—ãŸä»®æƒ³ HUB ã¯ã€ç›´ã¡ã«å‹•ä½œã‚’開始ã—ã¾ã™ã€‚\nVPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«å¯¾ã—ã¦ã®ã¿æœ‰åŠ¹ã§ã™ã€‚ã¾ãŸã€æ–°ã—ã„仮想 HUB ã¯ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ä»®æƒ³ HUB ã¨ã—ã¦å‹•ä½œã—ã¾ã™ã€‚HubSetStatic コマンドã§ã€ã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ä»®æƒ³ HUB ã«å¤‰æ›´ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã™ã§ã« VPN Server 上ã«å­˜åœ¨ã™ã‚‹ä»®æƒ³ HUB ã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€HubList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã€ã¾ãŸã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_HubCreateStatic_Args HubCreateStatic [name] [/PASSWORD:password]
+CMD_HubCreateStatic_[name] 作æˆã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_HubCreateStatic_PASSWORD 作æˆã™ã‚‹ä»®æƒ³ HUB ã®ç®¡ç†ãƒ‘スワードを設定ã™ã‚‹å ´åˆã¯ã€ãã®ç®¡ç†ãƒ‘スワードを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€å…¥åŠ›ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# HubDelete コマンド
+CMD_HubDelete 仮想 HUB ã®å‰Šé™¤
+CMD_HubDelete_Help VPN Server 上ã®ã€æ—¢å­˜ã®ä»®æƒ³ HUB を削除ã—ã¾ã™ã€‚\n仮想 HUB を削除ã™ã‚‹ã¨ã€ç¾åœ¨ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„るセッションãŒã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã€æ–°ãŸãªã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\nã¾ãŸã€ä»®æƒ³ HUB ã®ã™ã¹ã¦ã®è¨­å®šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ オブジェクトã€ã‚°ãƒ«ãƒ¼ãƒ—オブジェクトã€è¨¼æ˜Žæ›¸ã€ãŠã‚ˆã³ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚\n仮想 HUB を削除ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridgeã€ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。
+CMD_HubDelete_Args HubDelete [name]
+CMD_HubDelete_[name] 削除ã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_HubDelete_PROMPT_NAME 削除ã™ã‚‹ä»®æƒ³ HUB ã®åå‰:
+
+
+# HubSetStatic コマンド
+CMD_HubSetStatic 仮想 HUB ã®ç¨®é¡žã‚’スタティック仮想 HUB ã«å¤‰æ›´
+CMD_HubSetStatic_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ä»®æƒ³ HUB ã®ç¨®é¡žã‚’ã€ã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ä»®æƒ³ HUB ã«è¨­å®šã—ã¾ã™ã€‚仮想 HUB ã®ç¨®é¡žã‚’変更ã™ã‚‹ã¨ã€ç¾åœ¨ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ä¸€æ—¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚\nスタティック仮想 HUB ã¨ã—ã¦å‹•ä½œã—ã¦ã„る仮想 HUB ãŒã‚ã‚‹å ´åˆã€ã™ã¹ã¦ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ä¸Šã§ã€ãã®åå‰ã®ä»®æƒ³ HUB ãŒç”Ÿæˆã•ã‚Œã¾ã™ã€‚ãã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€å„サーãƒãƒ¼ã®è² è·çŠ¶æ³ã‚’å…ƒã«ã—ãŸã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã«ã‚ˆã£ã¦ã€ãã®ä»®æƒ³ HUB をホスティングã—ã¦ã„ã‚‹ã€ã„ãšã‚Œã‹ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã«æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚\nスタティック仮想 HUB ã¯ã€ä¸€ä¾‹ã¨ã—ã¦ã€ä¼æ¥­ã«ãŠã‘るインターãƒãƒƒãƒˆã‹ã‚‰ç¤¾å†… LAN ã¸ã®ãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ç”¨é€”ã«ãŠã„ã¦ã€åŒæ™‚ã«æ•°åƒï½žæ•°ä¸‡å˜ä½ã®å¤§é‡ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåŒæ™‚ã«æŽ¥ç¶šã™ã‚‹å¯èƒ½æ€§ãŒã‚るリモートアクセス VPN 用ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã€ã¾ãŸã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ãƒ“ルド 5190 より新ã—ã„ VPN Server ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+CMD_HubSetStatic_Args HubSetStatic [name]
+CMD_HubSetStatic_[name] スタティック仮想 HUB ã«è¨­å®šã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_HubChange_PROMPT_NAME 設定を変更ã™ã‚‹ä»®æƒ³ HUB ã®åå‰:
+
+
+# HubSetDynamic コマンド
+CMD_HubSetDynamic 仮想 HUB ã®ç¨®é¡žã‚’ダイナミック仮想 HUB ã«å¤‰æ›´
+CMD_HubSetDynamic_Help VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿å†…ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ä»®æƒ³ HUB ã®ç¨®é¡žã‚’ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ä»®æƒ³ HUB ã«è¨­å®šã—ã¾ã™ã€‚仮想 HUB ã®ç¨®é¡žã‚’変更ã™ã‚‹ã¨ã€ç¾åœ¨ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯ä¸€æ—¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚\nクラスタ内ã«å®šç¾©ã•ã‚Œã¦ã„るダイナミック仮想 HUB ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒ 1 å°ã‚‚接続ã—ã¦ã„ãªã„ã¨ãã€ãã®ä»®æƒ³ HUB ã¯ã©ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒä¸Šã«ã‚‚存在ã—ã¾ã›ã‚“。ダイナミック仮想 HUB ã« 1 å°ç›®ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒæŽ¥ç¶šã—よã†ã¨ã™ã‚‹ã¨ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§æœ€ã‚‚è² è·ã®ä½Žã„サーãƒãƒ¼ãŒãã®ä»®æƒ³ HUB をホスティングã—ã¾ã™ã€‚2 å°ç›®ä»¥é™ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã™ã‚‹ã¨ã€ä»®æƒ³ HUB をホスティングã—ã¦ã„るサーãƒãƒ¼ã«è‡ªå‹•çš„ã«æŽ¥ç¶šã—ã¾ã™ã€‚å„ダイナミック仮想 HUB ã¯ã€ã™ã¹ã¦ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒåˆ‡æ–­ã™ã‚‹ã¨ã€ã©ã®ã‚µãƒ¼ãƒãƒ¼ã«ã‚‚実体ãŒå­˜åœ¨ã—ãªã„状態ã«æˆ»ã‚Šã¾ã™ã€‚\nダイナミック仮想 HUB ã®å¿œç”¨ä¾‹ã¯å¹…広ãã€ãŸã¨ãˆã°ç¤¾å†…ã«ãŠã„ã¦éƒ¨èª²æ¯Žã«ä»®æƒ³ HUB を定義ã—ã¦ãŠãã€å„社員ãŒè‡ªåˆ†ãŒæ‰€å±žã—ã¦ã„る部課ã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ã¦ä½œæ¥­ã‚’è¡Œã†ã¨ã„ã£ãŸã“ã¨ã‚’ã€å˜ä¸€ã®ã‚¯ãƒ©ã‚¹ã‚¿ã‚’設置ã™ã‚‹ã ã‘ã§ã€é›†ä¸­ç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã¾ãŸã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ VPN Bridge ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã€ã¾ãŸã¯ã‚¹ã‚¿ãƒ³ãƒ‰ã‚¢ãƒ­ãƒ³ã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ãƒ“ルド 5190 より新ã—ã„ VPN Server ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+CMD_HubSetDynamic_Args HubSetDynamic [name]
+CMD_HubSetDynamic_[name] ダイナミック仮想 HUB ã«è¨­å®šã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# HubList コマンド
+CMD_HubList 仮想 HUB ã®ä¸€è¦§ã®å–å¾—
+CMD_HubList_Help VPN Server 内ã®ã€æ—¢å­˜ã®ä»®æƒ³ HUB ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚ãã‚Œãžã‚Œã®ä»®æƒ³ HUB ã«ã¤ã„ã¦ã€[仮想 HUB å]ã€[状態]ã€[種類]ã€[ユーザー数]ã€[グループ数]ã€[セッション数]ã€[MAC テーブル数]ã€[IP テーブル数]ã€[ログイン回数]ã€[最終ログイン日時]ã€[最終通信日時] ã‚’å–å¾—ã§ãã¾ã™ã€‚\nãŸã ã—ã€ä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ç®¡ç†æ¨©é™ã®ãªã„仮想 HUB ã®ã‚ªãƒ—ションã§ã€åŒ¿åユーザーã«å¯¾ã—ã¦ä»®æƒ³ HUB を列挙ã—ãªã„オプションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€ãã®ä»®æƒ³ HUB ã¯åˆ—挙ã•ã‚Œã¾ã›ã‚“。サーãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®ä¸€è¦§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\nクラスタリング環境ã«ãŠã‘るクラスタコントローラ以外ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã«æŽ¥ç¶šã—ã¦ç®¡ç†ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã® VPN Server ãŒã€ç¾åœ¨ãƒ›ã‚¹ãƒ†ã‚£ãƒ³ã‚°ã—ã¦ã„る仮想 HUB ã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚クラスタコントローラã«æŽ¥ç¶šã—ã¦ç®¡ç†ã—ã¦ã„ã‚‹å ´åˆã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_HubList_Args HubList
+
+
+# Hub コマンド
+CMD_Hub 管ç†ã™ã‚‹ä»®æƒ³ HUB ã®é¸æŠž
+CMD_Hub_Help 管ç†å¯¾è±¡ã®ä»®æƒ³ HUB ã‚’é¸æŠžã—ã¾ã™ã€‚VPN Server ã«æŽ¥ç¶šã—ãŸçŠ¶æ…‹ã®ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã§ã¯ã€ä»®æƒ³ HUB ã«é–¢ã™ã‚‹è¨­å®šãƒ»ç®¡ç†ã‚’è¡Œãªã†ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹å‰ã«ã€ç®¡ç†ã‚’è¡Œãªã†ä»®æƒ³ HUB ã‚’ Hub コマンドã§é¸æŠžã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nVPN Server ã«ä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„る状態ã§ã¯ã€ç®¡ç†å¯¾è±¡ã¨ãªã£ã¦ã„ã‚‹ 1 ã¤ã®ä»®æƒ³ HUB ã‚’é¸æŠžã™ã‚‹ã“ã¨ãŒã§ãã€ä»–ã®ä»®æƒ³ HUB ã‚’é¸æŠžã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。VPN Server ã«ã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„る状態ã§ã¯ã€ã™ã¹ã¦ã®ä»®æƒ³ HUB ã®ç®¡ç†ã‚’è¡Œãªã†ã“ã¨ãŒã§ãã¾ã™ã€‚\nç¾åœ¨ã‚µãƒ¼ãƒãƒ¼ä¸Šã«å­˜åœ¨ã™ã‚‹ä»®æƒ³ HUB ã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€HubList コマンドを使用ã—ã¾ã™ã€‚\nVPN Bridge ã§ã¯ã€"BRIDGE" ã¨ã„ã†åå‰ã®ä»®æƒ³ HUB 以外をé¸æŠžã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+CMD_Hub_Args Hub [name]
+CMD_Hub_[name] 管ç†ã™ã‚‹ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚パラメータを指定ã—ã¦ã„ãªã„å ´åˆã¯ã€ç®¡ç†å¯¾è±¡ã®ä»®æƒ³ HUB ã®é¸æŠžã‚’解除ã—ã¾ã™ã€‚
+CMD_Hub_Unselected 仮想 HUB ã®é¸æŠžã‚’解除ã—ã¾ã—ãŸã€‚
+CMD_Hub_Selected 仮想 HUB "%S" ã‚’é¸æŠžã—ã¾ã—ãŸã€‚
+CMD_Hub_Select_Failed /ADMINHUB ã§æŒ‡å®šã•ã‚ŒãŸä»®æƒ³ HUB "%S" ã‚’é¸æŠžã—よã†ã¨ã—ã¦ã€ä¸‹è¨˜ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
+CMD_Hub_Not_Selected ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹å‰ã«ã€Hub コマンドã§ç®¡ç†å¯¾è±¡ã®ä»®æƒ³ HUB ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+
+
+# Online コマンド
+CMD_Online 仮想 HUB をオンラインã«ã™ã‚‹
+CMD_Online_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã«ãªã£ã¦ã„ã‚‹å ´åˆã¯ã€ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ã—ã¾ã™ã€‚オフライン状態ã®ä»®æƒ³ HUB ã¯ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã® VPN 接続をå—ã‘付ã‘ã¾ã›ã‚“。仮想 HUB をオンライン化ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€ãã®ä»®æƒ³ HUB ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—ã‘付ã‘ãŸã‚Šã€ã‚µãƒ¼ãƒ“スをæä¾›ã—ãŸã‚Šã™ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_Online_Args Online
+
+
+# Offline コマンド
+CMD_Offline 仮想 HUB をオフラインã«ã™ã‚‹
+CMD_Offline_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ãªã£ã¦ã„ã‚‹å ´åˆã¯ã€ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã«ã—ã¾ã™ã€‚仮想 HUB ã«æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒã‚ã‚‹å ´åˆã¯ã€ã™ã¹ã¦åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚オフライン状態ã®ä»®æƒ³ HUB ã¯ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã® VPN 接続をå—ã‘付ã‘ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_Offline_Args Offline
+
+
+# SetMaxSession コマンド
+CMD_SetMaxSession 仮想 HUB ã®æœ€å¤§åŒæ™‚接続セッション数を設定ã™ã‚‹
+CMD_SetMaxSession_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€æœ€å¤§åŒæ™‚接続セッション数を設定ã—ã¾ã™ã€‚最大åŒæ™‚接続セッション数を越ãˆãŸã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒã€VPN Client ã‚„ VPN Bridge ã‹ã‚‰æŽ¥ç¶šã•ã‚ŒãŸå ´åˆã€æœ€å¤§åŒæ™‚接続セッション数を上回ã£ãŸæ™‚点ã§ã€ãれ以上クライアントã¯æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚ã“ã®æœ€å¤§åŒæ™‚接続セッション数ã®åˆ¶é™ã«ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã€ä»®æƒ³ NATã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãªã©ã«ã‚ˆã£ã¦ä»®æƒ³ HUB 内ã«ç”Ÿæˆã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯å«ã¾ã‚Œã¾ã›ã‚“。\nç¾åœ¨ã®æœ€å¤§åŒæ™‚接続セッション数ã®è¨­å®šã¯ã€OptionsGet コマンドã«ã‚ˆã£ã¦å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SetMaxSession_Args SetMaxSession [max_session]
+CMD_SetMaxSession_[max_session] 設定ã™ã‚‹æœ€å¤§åŒæ™‚接続セッション数をã€æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚0 を指定ã™ã‚‹ã¨ã€ç„¡åˆ¶é™ã«ãªã‚Šã¾ã™ã€‚
+CMD_SetMaxSession_Prompt 最大åŒæ™‚接続セッション数:
+
+
+# SetHubPassword コマンド
+CMD_SetHubPassword 仮想 HUB ã®ç®¡ç†ãƒ‘スワードを設定ã™ã‚‹
+CMD_SetHubPassword_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ç®¡ç†ãƒ‘スワードを設定ã—ã¾ã™ã€‚仮想 HUB ã®ç®¡ç†ãƒ‘スワードãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã€ãã®ä»®æƒ³ HUB ã«å¯¾ã—ã¦ã€VPN Server ã®æŽ¥ç¶šãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‹ã‚‰ã€ä»®æƒ³ HUB 管ç†ãƒ¢ãƒ¼ãƒ‰ã§ãƒ‘スワードを指定ã—ã¦æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€VPN Client ã‚„ VPN Bridge ãªã©ã‹ã‚‰ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ "Administrator"ã€ãƒ‘スワードを仮想 HUB ã®ç®¡ç†è€…パスワードã«æŒ‡å®šã—㦠VPN 接続ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SetHubPassword_Args SetHubPassword [password]
+CMD_SetHubPassword_[password] 設定ã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚パラメータã§ãƒ‘スワードを指定ã—ãªã„å ´åˆã¯ã€ãƒ‘スワードを入力ã™ã‚‹ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# SetEnumAllow コマンド
+CMD_SetEnumAllow 仮想 HUB ã®åŒ¿åユーザーã¸ã®åˆ—挙ã®è¨±å¯è¨­å®š
+CMD_SetEnumAllow_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚ªãƒ—ション設定を変更ã—ã€åŒ¿åユーザーã«å¯¾ã—ã¦ã€ã“ã®ä»®æƒ³ HUB を列挙ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションを設定ã™ã‚‹ã¨ã€VPN Client ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€ã“ã® VPN Server ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã™ã‚‹ã ã‘ã§ã“ã®ä»®æƒ³ HUB を列挙ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ã¾ãŸã€SetEnumDeny コマンドを使用ã™ã‚‹ã¨ã€åŒ¿åユーザーã¸ã®åˆ—挙をç¦æ­¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚仮想 HUB ã¯ã€ä½œæˆã•ã‚ŒãŸæ™‚点ã§ã¯åˆ—挙ãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SetEnumAllow_Args SetEnumAllow
+
+
+# SetEnumDeny コマンド
+CMD_SetEnumDeny 仮想 HUB ã®åŒ¿åユーザーã¸ã®åˆ—挙ã®ç¦æ­¢è¨­å®š
+CMD_SetEnumDeny_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚ªãƒ—ション設定を変更ã—ã€åŒ¿åユーザーã«å¯¾ã—ã¦ã€ã“ã®ä»®æƒ³ HUB を列挙ã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションを設定ã™ã‚‹ã¨ã€VPN Client ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã€VPN Server ã«å¯¾ã—ã¦ä»®æƒ³ HUB ã®åˆ—挙をè¦æ±‚ã—ãŸå ´åˆã§ã‚‚ã€ã“ã®ä»®æƒ³ HUB ã¯åˆ—挙ã•ã‚Œãªã„よã†ã«ãªã‚Šã¾ã™ã€‚ã¾ãŸã€SetEnumAllow コマンドを使用ã™ã‚‹ã¨ã€åŒ¿åユーザーã¸ã®åˆ—挙を許å¯ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SetEnumDeny_Args SetEnumDeny
+
+
+# OptionsGet コマンド
+CMD_OptionsGet 仮想 HUB ã®ã‚ªãƒ—ション設定ã®å–å¾—
+CMD_OptionsGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚ªãƒ—ション設定ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚仮想 HUB ã®åˆ—挙ã®è¨±å¯ / ç¦æ­¢ã®è¨­å®šã€æœ€å¤§åŒæ™‚接続数ã€ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ / オフライン状態ã€ãŠã‚ˆã³ã‚¯ãƒ©ã‚¹ã‚¿ãƒªãƒ³ã‚°ç’°å¢ƒã«ãŠã‘る仮想 HUB ã®ç¨®é¡žã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_OptionsGet_Args OptionsGet
+CMD_OptionsGet_TITLE 仮想 HUB "%S" ã®ã‚ªãƒ—ション設定一覧
+CMD_OptionsGet_ENUM 匿åユーザーã«å¯¾ã™ã‚‹ä»®æƒ³ HUB ã®åˆ—挙
+CMD_OptionsGet_MAXSESSIONS 最大åŒæ™‚接続セッション数
+CMD_OptionsGet_STATUS 状態
+CMD_OptionsGet_TYPE 仮想 HUB ã®ç¨®é¡ž
+
+
+
+# RadiusServerSet コマンド
+CMD_RadiusServerSet ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼ã®è¨­å®š
+CMD_RadiusServerSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ RADIUS サーãƒãƒ¼èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ãŸå ´åˆã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードを確èªã™ã‚‹ãŸã‚ã®å¤–部㮠RADIUS サーãƒãƒ¼ã‚’指定ã—ã¾ã™ã€‚\nRadius サーãƒãƒ¼ã¯ã€ã“ã® VPN Server ã® IP アドレスã‹ã‚‰ã®è¦æ±‚ã‚’å—ã‘付ã‘るよã†ã«è¨­å®šã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€Password Authentication Protocol (PAP) ã«ã‚ˆã‚‹èªè¨¼ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_RadiusServerSet_Args RadiusServerSet [server_name:port] [/SECRET:secret] [/RETRY_INTERVAL:interval]
+CMD_RadiusServerSet_[server_name:port] [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレス㨠UDP ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãƒãƒ¼ãƒˆç•ªå·ã‚’çœç•¥ã—ãŸå ´åˆã¯ã€1812 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_RadiusServerSet_SECRET RADIUS サーãƒãƒ¼ã¨ã®é–“ã§ã®é€šä¿¡ã«ä½¿ç”¨ã™ã‚‹å…±æœ‰ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ (パスワード) を指定ã—ã¾ã™ã€‚
+CMD_RadiusServerSet_RETRY_INTERVAL RADIUS サーãƒãƒ¼ã¨ã®é–“ã§ã®é€šä¿¡ã«ä½¿ç”¨ã™ã‚‹å†è©¦è¡Œé–“隔をミリ秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_RadiusServerSet_Prompt_Host 使用ã™ã‚‹ RADIUS サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+CMD_RadiusServerSet_Prompt_Secret 共有シークレット:
+CMD_RadiusServerSet_Prompt_RetryInterval å†è©¦è¡Œé–“éš” (ミリ秒å˜ä½):
+CMD_RadiusServerSet_EVAL_NUMINTERVAL å†è©¦è¡Œé–“隔㯠500 ã‹ã‚‰ 10000 ミリ秒ã®ç¯„囲ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+# RadiusServerDelete コマンド
+CMD_RadiusServerDelete ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼è¨­å®šã®å‰Šé™¤
+CMD_RadiusServerDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ RADIUS サーãƒãƒ¼èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ãŸå ´åˆã«ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼ã«é–¢ã™ã‚‹è¨­å®šã‚’削除ã—ã€RADIUS èªè¨¼ã‚’使用ã§ããªã„よã†ã«ã—ã¾ã™ã€‚ç¾åœ¨ã® RADIUS サーãƒãƒ¼ã«é–¢ã™ã‚‹è¨­å®šã¯ã€RadiusServerGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_RadiusServerDelete_Args RadiusServerDelete
+
+
+# RadiusServerGet コマンド
+CMD_RadiusServerGet ユーザーèªè¨¼ã«ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼è¨­å®šã®å–å¾—
+CMD_RadiusServerGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ RADIUS サーãƒãƒ¼èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ãŸå ´åˆã«ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼ã«ã¤ã„ã¦ã®ç¾åœ¨ã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_RadiusServerGet_Args RadiusServerGet
+CMD_RadiusServerGet_STATUS RADIUS サーãƒãƒ¼ã®ä½¿ç”¨
+CMD_RadiusServerGet_HOST RADIUS サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレス
+CMD_RadiusServerGet_PORT RADIUS サーãƒãƒ¼ã®ãƒãƒ¼ãƒˆç•ªå·
+CMD_RadiusServerGet_SECRET 共有シークレット
+CMD_RadiusServerGet_RetryInterval å†è©¦è¡Œé–“éš” (ミリ秒å˜ä½)
+
+
+# StatusGet コマンド
+CMD_StatusGet 仮想 HUB ã®ç¾åœ¨ã®çŠ¶æ³ã®å–å¾—
+CMD_StatusGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ç¾åœ¨ã®çŠ¶æ³ã‚’å–å¾—ã—ã¾ã™ã€‚仮想 HUB ã®ç¨®é¡žã‚„セッション数ã€å„種オブジェクト数ã€ãƒ­ã‚°ã‚¤ãƒ³å›žæ•°ã€æœ€çµ‚ログイン日時ã¨æœ€çµ‚通信日時ã€é€šä¿¡ã®çµ±è¨ˆãƒ‡ãƒ¼ã‚¿ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_StatusGet_Args StatusGet
+
+
+# LogGet コマンド
+CMD_LogGet 仮想 HUB ã®ãƒ­ã‚°ä¿å­˜è¨­å®šã®å–å¾—
+CMD_LogGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ãƒ­ã‚°ä¿å­˜è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚セキュリティログã¨ãƒ‘ケットログã«é–¢ã™ã‚‹ä¿å­˜è¨­å®šã‚„ã€ä¿å­˜å¯¾è±¡ãªã©ã®è¨­å®šæƒ…å ±ãŒå–å¾—ã§ãã¾ã™ã€‚
+CMD_LogGet_Args LogGet
+CMD_Log_SecurityLog セキュリティログã®ä¿å­˜
+CMD_Log_PacketLog パケットログã®ä¿å­˜
+CMD_Log_SwitchType ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸ
+CMD_Log_0 TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãƒ­ã‚°
+CMD_Log_1 TCP パケットログ
+CMD_Log_2 DHCP ログ
+CMD_Log_3 UDP ログ
+CMD_Log_4 ICMP ログ
+CMD_Log_5 IP ログ
+CMD_Log_6 ARP ログ
+CMD_Log_7 Ethernet ログ
+
+
+# LogEnable コマンド
+CMD_LogEnable セキュリティログã¾ãŸã¯ãƒ‘ケットログã®æœ‰åŠ¹åŒ–
+CMD_LogEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã¾ãŸã¯ãƒ‘ケットログを有効化ã—ã¾ã™ã€‚\nç¾åœ¨ã®è¨­å®šã¯ã€LogGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_LogEnable_Args LogEnable [security|packet]
+CMD_LogEnable_[security|packet] 有効化ã™ã‚‹ãƒ­ã‚°ã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚"security" ã¾ãŸã¯ "packet" ã®ã„ãšã‚Œã‹ã‚’指定ã—ã¾ã™ã€‚
+CMD_LogEnable_Prompt security ã¾ãŸã¯ packet ã‚’é¸æŠž:
+CMD_LogEnable_Prompt_Error 指定ãŒä¸æ­£ã§ã™ã€‚
+
+
+# LogDisable コマンド
+CMD_LogDisable セキュリティログã¾ãŸã¯ãƒ‘ケットログã®ç„¡åŠ¹åŒ–
+CMD_LogDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã¾ãŸã¯ãƒ‘ケットログを無効化ã—ã¾ã™ã€‚\nç¾åœ¨ã®è¨­å®šã¯ã€LogGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_LogDisable_Args LogDisable [security|packet]
+CMD_LogDisable_[security|packet] 無効化ã™ã‚‹ãƒ­ã‚°ã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚"security" ã¾ãŸã¯ "packet" ã®ã„ãšã‚Œã‹ã‚’指定ã—ã¾ã™ã€‚
+
+
+# LogSwitchSet コマンド
+CMD_LogSwitchSet ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸã®è¨­å®š
+CMD_LogSwitchSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿å­˜ã™ã‚‹ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã¾ãŸã¯ãƒ‘ケットログã®ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸã‚’設定ã—ã¾ã™ã€‚ログファイルã®åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸã¯ã€1 秒å˜ä½ã€1 分å˜ä½ã€1 時間å˜ä½ã€1 æ—¥å˜ä½ã€1 ヶ月å˜ä½ã€ã¾ãŸã¯åˆ‡ã‚Šæ›¿ãˆã‚’è¡Œã‚ãªã„よã†ã«å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nç¾åœ¨ã®è¨­å®šã¯ã€LogGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_LogSwitchSet_Args LogSwitchSet [security|packet] [/SWITCH:sec|min|hour|day|month|none]
+CMD_LogSwitchSet_[security|packet] 設定を変更ã™ã‚‹ãƒ­ã‚°ã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚"security" ã¾ãŸã¯ "packet" ã®ã„ãšã‚Œã‹ã‚’指定ã—ã¾ã™ã€‚
+CMD_LogSwitchSet_SWITCH 設定ã™ã‚‹åˆ‡ã‚Šæ›¿ãˆå‘¨æœŸã‚’é¸æŠžã—ã¾ã™ã€‚secã€minã€hourã€dayã€monthã€none ã‹ã‚‰æŒ‡å®šã—ã¾ã™ã€‚
+CMD_LogSwitchSet_Prompt sec, min, hour, day, month, none を指定:
+
+
+# LogPacketSaveType コマンド
+CMD_LogPacketSaveType パケットログã«ä¿å­˜ã™ã‚‹ãƒ‘ケットã®ç¨®é¡žã¨ä¿å­˜å†…容ã®è¨­å®š
+CMD_LogPacketSaveType_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã§ä¿å­˜ã™ã‚‹ã€ãƒ‘ケットログã®ä¿å­˜å†…容をã€ãƒ‘ケットã®ç¨®é¡žã”ã¨ã«è¨­å®šã—ã¾ã™ã€‚パケットã®ç¨®é¡žã«ã¯ã€[TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãƒ­ã‚°]ã€[TCP パケットログ]ã€[DHCP パケットログ]ã€[UDP パケットログ]ã€[ICMP パケットログ]ã€[IP パケットログ]ã€[ARP パケットログ]ã€[Ethernet パケットログ] ãŒã‚ã‚Šã¾ã™ã€‚\nç¾åœ¨ã®è¨­å®šã¯ã€LogGet コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_LogPacketSaveType_Args LogPacketSaveType [/TYPE:tcpconn|tcpdata|dhcp|udp|icmp|ip|arp|ether] [/SAVE:none|header|full]
+CMD_LogPacketSaveType_TYPE ä¿å­˜å†…容ã®å¤‰æ›´å¯¾ç§°ã®ãƒ‘ケットã®ç¨®é¡žã‚’ã€tcpconnã€tcpdataã€dhcpã€udpã€icmpã€ipã€arpã€ether ã®ä¸­ã‹ã‚‰æŒ‡å®šã—ã¾ã™ã€‚
+CMD_LogPacketSaveType_SAVE パケットログã®ä¿å­˜å†…容を指定ã—ã¾ã™ã€‚\nnone : ä¿å­˜ç„¡ã—\nheader: ヘッダ情報ã®ã¿\nfull : パケット内容ã™ã¹ã¦\nã®ã„ãšã‚Œã‹ã‚’指定ã—ã¾ã™ã€‚
+CMD_LogPacketSaveType_Prompt_TYPE tcpconn, tcpdata, dhcp, udp, icmp, ip, arp, ether を指定:
+CMD_LogPacketSaveType_Prompt_SAVE none, header, full を指定:
+
+
+# CAList コマンド
+CMD_CAList ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã®å–å¾—
+CMD_CAList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã‚’管ç†ã—ã¾ã™ã€‚登録ã•ã‚Œã¦ã„る証明機関ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Client ãŒç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ããŸéš›ã®è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CAList_Args CAList
+CMD_CAList_COLUMN_ID ID
+
+
+# CAAdd コマンド
+CMD_CAAdd ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®è¿½åŠ 
+CMD_CAAdd_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€æ–°ã—ã„証明書を追加ã—ã¾ã™ã€‚登録ã•ã‚Œã¦ã„る証明機関ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Client ãŒã€ç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ããŸéš›ã®è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nç¾åœ¨ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€CAList コマンドを使用ã—ã¾ã™ã€‚\n証明書を追加ã™ã‚‹ã«ã¯ã€ãã®è¨¼æ˜Žæ›¸ãŒ X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CAAdd_Args CAAdd [path]
+CMD_CAAdd_[path] 登録ã™ã‚‹ X.509 証明書ファイルåを指定ã—ã¾ã™ã€‚
+CMD_CAAdd_PROMPT_PATH 登録ã™ã‚‹ X.509 証明書ファイルå:
+
+
+# CADelete コマンド
+CMD_CADelete ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®å‰Šé™¤
+CMD_CADelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‹ã‚‰ã€æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã‚’削除ã—ã¾ã™ã€‚\nç¾åœ¨ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€CAList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CADelete_Args CADelete [id]
+CMD_CADelete_[id] 削除ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID を指定ã—ã¾ã™ã€‚
+CMD_CADelete_PROMPT_ID 削除ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID:
+
+
+# CAGet コマンド
+CMD_CAGet ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_CAGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§å†…ã®æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã€X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CAGet_Args CAGet [id] [/SAVECERT:path]
+CMD_CAGet_[id] å–å¾—ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID を指定ã—ã¾ã™ã€‚
+CMD_CAGet_SAVECERT å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_CAGet_PROMPT_ID å–å¾—ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID:
+CMD_CAGet_PROMPT_SAVECERT ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«å:
+
+
+# CascadeList コマンド
+CMD_CascadeList カスケード接続一覧ã®å–å¾—
+CMD_CascadeList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nカスケード接続を使用ã™ã‚‹ã¨ã€ã“ã®ä»®æƒ³ HUB ã‚’åŒä¸€ã¾ãŸã¯åˆ¥ã®ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã—ã¦ã„ã‚‹ä»–ã®ä»®æƒ³ HUB ã«ã€ãƒ¬ã‚¤ãƒ¤ 2 カスケード接続ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\n[カスケード接続ã«ãŠã‘る警告]\nカスケード接続を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ä»®æƒ³ HUB é–“ã§ã®ãƒ¬ã‚¤ãƒ¤ 2 ブリッジãŒå¯èƒ½ã§ã™ãŒã€æŽ¥ç¶šæ–¹æ³•ã‚’é–“é•ãˆã‚‹ã¨ã€ãƒ«ãƒ¼ãƒ—状ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆã—ã¦ã—ã¾ã†å ´åˆãŒã‚ã‚Šã¾ã™ã€‚カスケード接続機能を使用ã™ã‚‹éš›ã«ã¯ã€æ…Žé‡ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒˆãƒãƒ­ã‚¸ã‚’設計ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeList_Args CascadeList
+
+
+# CascadeCreate コマンド
+CMD_CascadeCreate æ–°ã—ã„カスケード接続ã®ä½œæˆ
+CMD_CascadeCreate_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ã€æ–°ã—ã„カスケード接続を作æˆã—ã¾ã™ã€‚\nカスケード接続を使用ã™ã‚‹ã¨ã€ã“ã®ä»®æƒ³ HUB ã‚’åŒä¸€ã¾ãŸã¯åˆ¥ã®ã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã—ã¦ã„ã‚‹ä»–ã®ä»®æƒ³ HUB ã«ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nカスケード接続を作æˆã™ã‚‹ã«ã¯ã€åˆæœŸãƒ‘ラメータã¨ã—ã¦ã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã¨æŽ¥ç¶šå…ˆã®ã‚µãƒ¼ãƒãƒ¼ãŠã‚ˆã³æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUBã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚æ–°ã—ã„カスケード接続を作æˆã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã¯ [匿åèªè¨¼] ã«åˆæœŸè¨­å®šã•ã‚Œã€ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®šã¨ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã¯è¨­å®šã•ã‚Œã¾ã›ã‚“。ã“れらã®è¨­å®šã‚„ãã®ä»–ã®è©³ç´°è¨­å®šã‚’変更ã™ã‚‹ã«ã¯ã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆã—ãŸå¾Œã« "Cascade" ã¨ã„ã†åå‰ã§å§‹ã¾ã‚‹ä»–ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚\n\n[カスケード接続ã«ãŠã‘る警告]\nカスケード接続を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ä»®æƒ³ HUB é–“ã§ã®ãƒ¬ã‚¤ãƒ¤ 2 ブリッジãŒå¯èƒ½ã§ã™ãŒã€æŽ¥ç¶šæ–¹æ³•ã‚’é–“é•ãˆã‚‹ã¨ã€ãƒ«ãƒ¼ãƒ—状ã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆã—ã¦ã—ã¾ã†å ´åˆãŒã‚ã‚Šã¾ã™ã€‚カスケード接続機能を使用ã™ã‚‹éš›ã«ã¯ã€æ…Žé‡ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒˆãƒãƒ­ã‚¸ã‚’設計ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeCreate_Args CascadeCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username]
+CMD_CascadeCreate_[name] 作æˆã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeCreate_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚IP アドレスã§æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_CascadeCreate_HUB 接続先㮠VPN Server 内ã®ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚
+CMD_CascadeCreate_USERNAME 接続先㮠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã§ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_CascadeCreate_Prompt_Name カスケード接続ã®åå‰:
+CMD_CascadeCreate_Prompt_Server 接続先 VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+CMD_CascadeCreate_Prompt_Hub 接続先仮想 HUB å:
+CMD_CascadeCreate_Prompt_Username 接続ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼å:
+
+
+# CascadeSet コマンド
+CMD_CascadeSet カスケード接続ã®æŽ¥ç¶šå…ˆã®è¨­å®š
+CMD_CascadeSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続ã®ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ä»®æƒ³ HUB åã€ãŠã‚ˆã³æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを設定ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeSet_Args CascadeSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_CascadeSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeSet_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚IP アドレスã§æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_CascadeSet_HUB 接続先㮠VPN Server 内ã®ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚
+
+
+# CascadeGet コマンド
+CMD_CascadeGet カスケード接続ã®è¨­å®šã®å–å¾—
+CMD_CascadeGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続ã®æŽ¥ç¶šè¨­å®šå†…容をå–å¾—ã—ã¾ã™ã€‚\nãªãŠã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®æŽ¥ç¶šè¨­å®šå†…容を変更ã™ã‚‹ã«ã¯ã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’作æˆã—ãŸå¾Œã« "Cascade" ã¨ã„ã†åå‰ã§å§‹ã¾ã‚‹ã€ä»–ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeGet_Args CascadeGet [name]
+CMD_CascadeGet_[name] 設定をå–å¾—ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeGet_Policy [カスケードセッションã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼è¨­å®šå€¤]
+
+# CascadeDelete コマンド
+CMD_CascadeDelete カスケード接続ã®å‰Šé™¤
+CMD_CascadeDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を削除ã—ã¾ã™ã€‚指定ã•ã‚ŒãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã§ã‚ã‚‹å ´åˆã¯ã€è‡ªå‹•çš„ã«æŽ¥ç¶šã‚’切断ã—ã¦ã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeDelete_Args CascadeDelete [name]
+CMD_CascadeDelete_[name] 削除ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeUsernameSet コマンド
+CMD_CascadeUsernameSet カスケード接続ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®è¨­å®š
+CMD_CascadeUsernameSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¿…è¦ãªãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚\nãªãŠã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’指定ã—ãŸã‚Šã€å¿…è¦ãªãƒ‘ラメータを指定ã—ãŸã‚Šã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“れらã®æƒ…報を変更ã™ã‚‹ã«ã¯ã€CascadeAnonymousSetã€CascadePasswordSetã€CascadeCertSet ãªã©ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeUsernameSet_Args CascadeUsernameSet [name] [/USERNAME:username]
+CMD_CascadeUsernameSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeUsernameSet_USERNAME カスケード接続㌠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¿…è¦ãªãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_CascadeUsername_Notice ã“ã®æŽ¥ç¶šè¨­å®šã®èªè¨¼æ–¹æ³•ã¯ã€ç¾åœ¨ãƒ‘スワードèªè¨¼ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚ユーザーåを変更ã—ãŸå¾Œã€CascadePasswordSet コマンドã§ãƒ‘スワードを設定ã—ç›´ã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+
+# CascadeAnonymousSet コマンド
+CMD_CascadeAnonymousSet カスケード接続ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’匿åèªè¨¼ã«è¨­å®š
+CMD_CascadeAnonymousSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ [匿åèªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeAnonymousSet_Args CascadeAnonymousSet [name]
+CMD_CascadeAnonymousSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadePasswordSet コマンド
+CMD_CascadePasswordSet カスケード接続ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’パスワードèªè¨¼ã«è¨­å®š
+CMD_CascadePasswordSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ [パスワードèªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚パスワードèªè¨¼ã®ç¨®é¡žã«ã¯ã€[標準パスワードèªè¨¼] 㨠[RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼] を指定ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadePasswordSet_Args CascadePasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_CascadePasswordSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadePasswordSet_PASSWORD パスワードèªè¨¼ã§ä½¿ç”¨ã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ãƒ‘スワードを入力ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_CascadePasswordSet_TYPE パスワードèªè¨¼ã®ç¨®é¡žã¨ã—ã¦ã€"standard" (標準パスワードèªè¨¼)ã€ã¾ãŸã¯ "radius" (RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼) ã®ã©ã¡ã‚‰ã‹ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadePasswordSet_Prompt_Type standard ã¾ãŸã¯ radius ã®æŒ‡å®š:
+CMD_CascadePasswordSet_Type_Invalid standard ã¾ãŸã¯ radius ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚
+
+
+# CascadeCertSet コマンド
+CMD_CascadeCertSet カスケード接続ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’クライアント証明書èªè¨¼ã«è¨­å®š
+CMD_CascadeCertSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ [クライアント証明書èªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚証明書ã¨ã—ã¦ã¯ã€X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã€Base 64 ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸå¯¾å¿œã—ãŸç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeCertSet_Args CascadeCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_CascadeCertSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeCertSet_LOADCERT 証明書èªè¨¼ã§æ示ã™ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_CascadeCertSet_LOADKEY 証明書ã«å¯¾å¿œã—㟠Base 64 å½¢å¼ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# CascadeCertGet コマンド
+CMD_CascadeCertGet カスケード接続ã«ç”¨ã„るクライアント証明書ã®å–å¾—
+CMD_CascadeCertGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸èªè¨¼ã‚’使用ã™ã‚‹å ´åˆã¯ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã¨ã—ã¦æ示ã™ã‚‹è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã¦ã€è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeCertGet_Args CascadeCertGet [name] [/SAVECERT:cert]
+CMD_CascadeCertGet_[name] 設定をå–å¾—ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeCertGet_SAVECERT å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_CascadeCertSet_Not_Auth_Cert 指定ã—ãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+CMD_CascadeCertSet_Cert_Not_Exists 指定ã—ãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®æŽ¥ç¶šè¨­å®šã«è¨¼æ˜Žæ›¸ãŒæ ¼ç´ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+
+
+# CascadeEncryptEnable コマンド
+CMD_CascadeEncryptEnable カスケード接続ã®é€šä¿¡æ™‚ã®æš—å·åŒ–ã®æœ‰åŠ¹åŒ–
+CMD_CascadeEncryptEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を SSL ã§æš—å·åŒ–ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚\n通常ã¯ã€VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã—ã¦ã€æƒ…å ±ã®ç›—è´ã‚„改ã–んを防止ã—ã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã¨ã€é€šä¿¡ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ãŒã€é€šä¿¡ãƒ‡ãƒ¼ã‚¿ã¯å¹³æ–‡ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeEncryptEnable_Args CascadeEncryptEnable [name]
+CMD_CascadeEncryptEnable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeEncryptDisable コマンド
+CMD_CascadeEncryptDisable カスケード接続ã®é€šä¿¡æ™‚ã®æš—å·åŒ–ã®ç„¡åŠ¹åŒ–
+CMD_CascadeEncryptDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã« VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を暗å·åŒ–ã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚\n通常ã¯ã€VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã—ã¦ã€æƒ…å ±ã®ç›—è´ã‚„改ã–んを防止ã—ã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã¨ã€é€šä¿¡ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ãŒã€é€šä¿¡ãƒ‡ãƒ¼ã‚¿ã¯å¹³æ–‡ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeEncryptDisable_Args CascadeEncryptDisable [name]
+CMD_CascadeEncryptDisable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeCompressEnable コマンド
+CMD_CascadeCompressEnable カスケード接続ã®é€šä¿¡æ™‚ã®ãƒ‡ãƒ¼ã‚¿åœ§ç¸®ã®æœ‰åŠ¹åŒ–
+CMD_CascadeCompressEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を圧縮ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚\n最大ã§ç´„ 80 % 程度ã®åœ§ç¸®ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã ã—ã€åœ§ç¸®ã‚’è¡Œã†ã¨ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŠã‚ˆã³ã‚µãƒ¼ãƒãƒ¼ã®ä¸¡æ–¹ã§ CPU è² è·ãŒé«˜ããªã‚Šã¾ã™ã€‚回線速度ãŒç´„ 10 Mbps 以上ã®å ´åˆã¯ã€åœ§ç¸®ã‚’è¡Œã†ã¨ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒä½Žä¸‹ã—ã€é€†åŠ¹æžœã¨ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeCompressEnable_Args CascadeCompressEnable [name]
+CMD_CascadeCompressEnable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeCompressDisable コマンド
+CMD_CascadeCompressDisable カスケード接続ã®é€šä¿¡æ™‚ã®ãƒ‡ãƒ¼ã‚¿åœ§ç¸®ã®ç„¡åŠ¹åŒ–
+CMD_CascadeCompressDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を圧縮ã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeCompressDisable_Args CascadeCompressDisable [name]
+CMD_CascadeCompressDisable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeProxyNone コマンド
+CMD_CascadeProxyNone カスケード接続ã®æŽ¥ç¶šæ–¹æ³•ã‚’直接 TCP/IP 接続ã«è¨­å®š
+CMD_CascadeProxyNone_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [直接 TCP/IP 接続] ã«è¨­å®šã—ã€ãƒ—ロキシサーãƒãƒ¼ã‚’経由ã—ãªã„よã†ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeProxyNone_Args CascadeProxyNone [name]
+CMD_CascadeProxyNone_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeProxyHttp コマンド
+CMD_CascadeProxyHttp カスケード接続ã®æŽ¥ç¶šæ–¹æ³•ã‚’ HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶šã«è¨­å®š
+CMD_CascadeProxyHttp_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š] ã«è¨­å®šã—ã€çµŒç”±ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワード (å¿…è¦ãªå ´åˆ) を指定ã—ã¾ã™ã€‚\n経由ã™ã‚‹ HTTP サーãƒãƒ¼ã¯ã€HTTPS 通信をã™ã‚‹ãŸã‚ã® CONNECT メソッドã«å¯¾å¿œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeProxyHttp_Args CascadeProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxyHttp_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeProxyHttp_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€çµŒç”±ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeProxyHttp_USERNAME 経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚ã¾ãŸã€åŒæ™‚ã« /PASSWORD パラメータも指定ã—ã¾ã™ã€‚/USERNAME 㨠/PASSWORD パラメータãŒæŒ‡å®šã•ã‚Œãªã„å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãƒ‡ãƒ¼ã‚¿ã‚’設定ã—ã¾ã›ã‚“。
+CMD_CascadeProxyHttp_PASSWORD 経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ‘スワードを指定ã—ã¾ã™ã€‚/USERNAME パラメータã¨å…±ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_CascadeProxyHttp_Prompt_Server プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+
+
+
+# CascadeProxySocks コマンド
+CMD_CascadeProxySocks カスケード接続ã®æŽ¥ç¶šæ–¹æ³•ã‚’ SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶šã«è¨­å®š
+CMD_CascadeProxySocks_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š] ã«è¨­å®šã—ã€çµŒç”±ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワード (å¿…è¦ãªå ´åˆ) を指定ã—ã¾ã™ã€‚\n経由ã™ã‚‹ SOCKS サーãƒãƒ¼ã¯ã€SOCKS ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4 ã«å¯¾å¿œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeProxySocks_Args CascadeProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_CascadeProxySocks_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeProxySocks_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€çµŒç”±ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeProxySocks_USERNAME 経由ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚ã¾ãŸã€åŒæ™‚ã« /PASSWORD パラメータも指定ã—ã¾ã™ã€‚/USERNAME 㨠/PASSWORD パラメータãŒæŒ‡å®šã•ã‚Œãªã„å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãƒ‡ãƒ¼ã‚¿ã‚’設定ã—ã¾ã›ã‚“。
+CMD_CascadeProxySocks_PASSWORD 経由ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ‘スワードを指定ã—ã¾ã™ã€‚/USERNAME パラメータã¨å…±ã«æŒ‡å®šã—ã¾ã™ã€‚
+
+
+# CascadeServerCertEnable コマンド
+CMD_CascadeServerCertEnable カスケード接続ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã®æœ‰åŠ¹åŒ–
+CMD_CascadeServerCertEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ãŒä¿¡é ¼ã§ãã‚‹ã‹ã©ã†ã‹æ¤œæŸ»ã™ã‚‹ã‚ªãƒ—ションを有効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書をã‚らã‹ã˜ã‚ CascadeServerCertSet コマンドã§ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šè¨­å®šå†…ã«ä¿å­˜ã—ã¦ãŠãã‹ã€ã¾ãŸã¯ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€ã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書を署åã—ãŸãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã‚’ CAAdd コマンドãªã©ã§ç™»éŒ²ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nカスケード接続ã®ã€ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„る状態ã§æŽ¥ç¶šã—㟠VPN Server ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ããªã„å ´åˆã€ç›´ã¡ã«æŽ¥ç¶šã‚’解除ã—ã¦å†è©¦è¡Œã‚’ç¹°ã‚Šè¿”ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeServerCertEnable_Args CascadeServerCertEnable [name]
+CMD_CascadeServerCertEnable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeServerCertDisable コマンド
+CMD_CascadeServerCertDisable カスケード接続ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã®ç„¡åŠ¹åŒ–
+CMD_CascadeServerCertDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ãŒã€ä¿¡é ¼ã§ãã‚‹ã‹ã©ã†ã‹æ¤œæŸ»ã™ã‚‹ã‚ªãƒ—ションを無効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeServerCertDisable_Args CascadeServerCertDisable [name]
+CMD_CascadeServerCertDisable_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeServerCertSet コマンド
+CMD_CascadeServerCertSet カスケード接続ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®è¨­å®š
+CMD_CascadeServerCertSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ã¨åŒã˜è¨¼æ˜Žæ›¸ã‚’ã‚らã‹ã˜ã‚登録ã—ã¾ã™ã€‚\nカスケード接続ã®ã€ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書をã€ã‚らã‹ã˜ã‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šè¨­å®šå†…ã«ä¿å­˜ã—ã¦ãŠãã‹ã€ã¾ãŸã¯ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€ã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書を署åã—ãŸãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã‚’ CAAdd コマンドãªã©ã§ç™»éŒ²ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nカスケード接続ã®ã€ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„る状態ã§æŽ¥ç¶šã—㟠VPN Server ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ããªã„å ´åˆã€ç›´ã¡ã«æŽ¥ç¶šã‚’解除ã—ã¦å†è©¦è¡Œã‚’ç¹°ã‚Šè¿”ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeServerCertSet_Args CascadeServerCertSet [name] [/LOADCERT:cert]
+CMD_CascadeServerCertSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeServerCertSet_LOADCERT 設定ã™ã‚‹ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒä¿å­˜ã•ã‚Œã¦ã„ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# CascadeServerCertDelete コマンド
+CMD_CascadeServerCertDelete カスケード接続ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®å‰Šé™¤
+CMD_CascadeServerCertDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã«ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãれを削除ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeServerCertDelete_Args CascadeServerCertDelete [name]
+CMD_CascadeServerCertDelete_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeServerCertGet コマンド
+CMD_CascadeServerCertGet カスケード接続ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_CascadeServerCertGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã«ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã¦ã€X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeServerCertGet_Args CascadeServerCertGet [name] [/SAVECERT:path]
+CMD_CascadeServerCertGet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeServerCertGet_SAVECERT サーãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã™ã‚‹è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# CascadeDetailSet コマンド
+CMD_CascadeDetailSet カスケード接続ã®é«˜åº¦ãªé€šä¿¡è¨­å®šã®è¨­å®š
+CMD_CascadeDetailSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒ VPN Server ã¨é€šä¿¡ã™ã‚‹éš›ã«ä½¿ç”¨ã•ã‚Œã‚‹ã€VPN プロトコルã®é€šä¿¡è¨­å®šã‚’カスタマイズã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeDetailSet_Args CascadeDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:interval] [/TTL:disconnect_span] [/HALF:yes|no] [/NOQOS:yes|no]
+CMD_CascadeDetailSet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeDetailSet_MAXTCP VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã‚’ã€1 以上 32 以下ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚VPN Server ã¨ã®é–“ã® VPN 通信セッションã«ãŠã‘るデータä¼é€ã«ã€è¤‡æ•°æœ¬ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€é€šä¿¡é€Ÿåº¦ã‚’å‘上ã§ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\n注æ„: サーãƒãƒ¼ã¸ã®æŽ¥ç¶šå›žç·šãŒé«˜é€Ÿãªå ´åˆã¯ 8 本程度をã€ãƒ€ã‚¤ãƒ¤ãƒ«ã‚¢ãƒƒãƒ—ç­‰ã®ä½Žé€Ÿãªå ´åˆã¯ 1 本をãŠå‹§ã‚ã—ã¾ã™ã€‚
+CMD_CascadeDetailSet_INTERVAL 複数㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’確立ã—㦠VPN 通信を行ã†ã¨ãã€å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“隔を秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚è¦å®šå€¤ã¯ 1 秒ã§ã™ã€‚
+CMD_CascadeDetailSet_TTL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ã‚’設定ã™ã‚‹å ´åˆã¯ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãŒç¢ºç«‹ã•ã‚Œã¦ã‹ã‚‰åˆ‡æ–­ã•ã‚Œã‚‹ã¾ã§ã®å¯¿å‘½ã‚’ã€ç§’æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚0 を指定ã™ã‚‹ã¨ã€å¯¿å‘½ã¯è¨­å®šã•ã‚Œã¾ã›ã‚“。
+CMD_CascadeDetailSet_HALF åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚2 本以上㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ VPN 通信を行ã†éš›ã€ã€ŒåŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã€ã‚’使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€è‡ªå‹•çš„ã«å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ãƒ‡ãƒ¼ã‚¿ä¼é€æ–¹å‘ã‚’åŠæ•°ãšã¤å›ºå®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã¨ãˆã°ã€8 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’使用ã—㦠VPN セッションを確立ã—ãŸå ´åˆã€åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€4 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ã‚¢ãƒƒãƒ—ロード方å‘専用ã€æ®‹ã‚Šã® 4 本ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰æ–¹å‘専用ã«å›ºå®šã•ã‚Œé€šä¿¡ãŒè¡Œã‚ã‚Œã¾ã™ã€‚
+CMD_CascadeDetailSet_NOQOS VoIP / QoS 対応機能を無効ã«ã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚通常㯠"no" を指定ã—ã¾ã™ã€‚
+CMD_CascadeDetailSet_Eval_MaxTcp TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã¯ 1 ã‹ã‚‰ 32 ã®é–“ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_CascadeDetailSet_Eval_Interval TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“隔㯠1 秒以上を指定ã—ã¦ãã ã•ã„。
+CMD_CascadeDetailSet_Prompt_MaxTcp VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°:
+CMD_CascadeDetailSet_Prompt_Interval å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“éš”:
+CMD_CascadeDetailSet_Prompt_TTL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ (0 ã§ç„¡ã—):
+CMD_CascadeDetailSet_Prompt_HALF åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ (yes/no):
+
+
+# CascadePolicySet コマンド
+CMD_CascadePolicySet カスケード接続セッションã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®š
+CMD_CascadePolicySet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒç¢ºç«‹ã—ãŸéš›ã«ã€ä»®æƒ³ HUB ã§ç”Ÿæˆã•ã‚Œã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é©ç”¨ã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å†…容を変更ã—ã¾ã™ã€‚\n仮想 HUB ãŒåˆ¥ã® VPN Server ã«ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã™ã‚‹ã¨ã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šå…ƒã®ä»®æƒ³ HUB ã«ã¯ã€Œã‚«ã‚¹ã‚±ãƒ¼ãƒ‰ã‚»ãƒƒã‚·ãƒ§ãƒ³ã€ãŒæ–°ã—ã生æˆã•ã‚Œã¾ã™ã€‚ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«è¨­å®šã™ã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å†…容をã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadePolicySet_Args [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_CascadePolicySet_[name] 設定を変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadePolicySet_NAME 値を変更ã™ã‚‹ãƒãƒªã‚·ãƒ¼ã®åå‰ã‚’指定ã—ã¾ã™ã€‚ãƒãƒªã‚·ãƒ¼ã®åå‰ã¨ã€è¨­å®šã§ãる値ã®ä¸€è¦§ã¯ PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_CascadePolicySet_VALUE ãƒãƒªã‚·ãƒ¼ã®æ–°ã—ã„値を指定ã—ã¾ã™ã€‚ãã®ãƒãƒªã‚·ãƒ¼ãŒæ•°å€¤åž‹ã®å ´åˆã¯æ•´æ•°ã‚’指定ã—ã¾ã™ã€‚ブール型ã®å ´åˆã¯ yes ã¾ãŸã¯ no を指定ã—ã¾ã™ã€‚設定ã§ãã‚‹åž‹ã¨å€¤ã¯ PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_CascadePolicySet_PROMPT_POLNAME 値を変更ã™ã‚‹ãƒãƒªã‚·ãƒ¼ã®åå‰:
+CMD_CascadePolicySet_PROMPT_POLVALUE æ–°ã—ã設定ã™ã‚‹å€¤:
+CMD_CascadePolicySet_Invalid_Name 指定ã•ã‚ŒãŸãƒãƒªã‚·ãƒ¼å "%S" ã¯ä¸æ­£ã§ã™ã€‚\nPolicyList コマンドã§è¨­å®šã§ãã‚‹ãƒãƒªã‚·ãƒ¼åã®ä¸€è¦§ã‚’確èªã—ã¦ãã ã•ã„。
+CMD_CascadePolicySet_Invalid_Name_For_Cadcade 指定ã•ã‚ŒãŸãƒãƒªã‚·ãƒ¼å "%S" ã¯ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼è¨­å®šã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。
+CMD_CascadePolicySet_Invalid_Range ãƒãƒªã‚·ãƒ¼ "%S" 㯠%s ã®ç¯„囲ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+# PolicyList コマンド
+CMD_PolicyList セキュリティãƒãƒªã‚·ãƒ¼ã®ç¨®é¡žã¨è¨­å®šå¯èƒ½å€¤ã®ä¸€è¦§ã‚’表示
+CMD_PolicyList_Help VPN Server ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚„グループã€ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã«å¯¾ã—ã¦è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãるセキュリティãƒãƒªã‚·ãƒ¼å†…ã®é …ç›®ã®åå‰ã€èª¬æ˜Žã€ãŠã‚ˆã³è¨­å®šã§ãる値ã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚\nPolicyList コマンドã«ä½•ã‚‚引数を指定ã›ãšã«èµ·å‹•ã™ã‚‹ã¨ã€ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®åå‰ã¨èª¬æ˜Žã®ä¸€è¦§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\nPolicyList コマンドã®å¼•æ•°ã§åå‰ã‚’指定ã™ã‚‹ã¨ã€ãã®å€¤ã«é–¢ã™ã‚‹è©³ç´°ãªèª¬æ˜Žã¨ã€è¨­å®šã§ãる値ã®åž‹ãŠã‚ˆã³ç¯„囲ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_PolicyList_Args PolicyList [name]
+CMD_PolicyList_[name] 説明を表示ã™ã‚‹ãƒãƒªã‚·ãƒ¼åを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®åå‰ã¨ã€èª¬æ˜Žã®ä¸€è¦§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_PolicyList_Invalid_Name 指定ã•ã‚ŒãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼åãŒä¸æ­£ã§ã™ã€‚
+CMD_PolicyList_Column_1 ãƒãƒªã‚·ãƒ¼å
+CMD_PolicyList_Column_2 ãƒãƒªã‚·ãƒ¼ã®ç°¡æ˜“説明
+CMD_PolicyList_Column_3 設定値
+CMD_PolicyList_Help_1 [ãƒãƒªã‚·ãƒ¼å]
+CMD_PolicyList_Help_2 [ãƒãƒªã‚·ãƒ¼ã®ç°¡æ˜“説明]
+CMD_PolicyList_Help_3 [設定ã§ãる値ã®ç¯„囲]
+CMD_PolicyList_Help_4 [デフォルト値]
+CMD_PolicyList_Help_5 [ãƒãƒªã‚·ãƒ¼ã®è©³ç´°èª¬æ˜Ž]
+CMD_PolicyList_Range_Bool ã¯ã„ (Yes) ã¾ãŸã¯ ã„ã„㈠(No)
+CMD_PolicyList_Range_Int_1 %s 以上 %s 以下 (0 ã¯æŒ‡å®šã§ããªã„)
+CMD_PolicyList_Range_Int_2 %s 以上 %s 以下 (ãŸã ã— 0 を指定ã™ã‚‹ã¨è¨­å®šç„¡ã—)
+
+
+# CascadeStatusGet コマンド
+CMD_CascadeStatusGet カスケード接続ã®ç¾åœ¨ã®çŠ¶æ…‹ã®å–å¾—
+CMD_CascadeStatusGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šãŒç¾åœ¨ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã§ã‚ã‚‹å ´åˆã¯ã€ãã®æŽ¥ç¶šçŠ¶æ…‹ã‚„ãã®ä»–ã®æƒ…報をå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeStatusGet_Args CascadeStatusGet [name]
+CMD_CascadeStatusGet_[name] 情報をå–å¾—ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeRename コマンド
+CMD_CascadeRename カスケード接続ã®åå‰ã®å¤‰æ›´
+CMD_CascadeRename_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’変更ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeRename_Args CascadeRename [name] [/NEW:new_name]
+CMD_CascadeRename_[name] åå‰ã‚’変更ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®ç¾åœ¨ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeRename_NEW 変更後ã®æ–°ã—ã„åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_CascadeRename_PROMPT_OLD ç¾åœ¨ã®åå‰:
+CMD_CascadeRename_PROMPT_NEW æ–°ã—ã„åå‰:
+
+
+
+# CascadeOnline コマンド
+CMD_CascadeOnline カスケード接続ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã¸ã®è¨­å®š
+CMD_CascadeOnline_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’オンライン化ã—ã¾ã™ã€‚オンライン状態ã«ãªã£ãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã¯ã€æŽ¥ç¶šè¨­å®šã«å¾“ã£ã¦ã€æŽ¥ç¶šå…ˆã® VPN Server ã¸ã®æŽ¥ç¶šå‡¦ç†ã‚’開始ã—ã¾ã™ã€‚オンライン状態ã«ãªã£ãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã¯ã€CascadeOffline コマンドã§ã‚ªãƒ•ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã«è¨­å®šã™ã‚‹ã¾ã§ã€VPN Server ã«å¸¸æ™‚接続ã¾ãŸã¯æŽ¥ç¶šã‚’試行ã—続ã‘ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeOnline_Args CascadeOnline [name]
+CMD_CascadeOnline_[name] オンライン状態ã«ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# CascadeOffline コマンド
+CMD_CascadeOffline カスケード接続ã®ã‚ªãƒ•ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã¸ã®è¨­å®š
+CMD_CascadeOffline_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„るカスケード接続を指定ã—ã€ãã®ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã‚’オフライン化ã—ã¾ã™ã€‚オフライン化ã•ã‚ŒãŸã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã¯ã€æ¬¡ã« CascadeOnline コマンドã§ã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã«è¨­å®šã™ã‚‹ã¾ã§ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã—ã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CascadeOffline_Args CascadeOffline [name]
+CMD_CascadeOffline_[name] オフライン状態ã«ã™ã‚‹ã‚«ã‚¹ã‚±ãƒ¼ãƒ‰æŽ¥ç¶šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccessAdd コマンド
+CMD_AccessAdd アクセスリストã¸ã®ãƒ«ãƒ¼ãƒ«ã®è¿½åŠ  (IPv4)
+CMD_AccessAdd_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ã€æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚\nアクセスリストã¨ã¯ã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã‚‹ãƒ‘ケットフィルタルールã®é›†åˆã§ã™ã€‚アクセスリストã«ã¯è¤‡æ•°ã®ãƒ«ãƒ¼ãƒ«ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã€å„ルールã”ã¨ã«å„ªå…ˆé †ä½ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã¹ã¦ã®ãƒ‘ケットã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るルールã§æŒ‡å®šã•ã‚ŒãŸæ¡ä»¶ã«ã€æœ€åˆã«ä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã§è¦å®šã•ã‚Œã¦ã„る動作ã§ã€é€šéŽã¾ãŸã¯ç ´æ£„ãŒæ±ºå®šã•ã‚Œã¾ã™ã€‚ã©ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ã‚‚一致ã—ãªã‹ã£ãŸãƒ‘ケットã¯ã€æš—é»™ã§é€šéŽã‚’許å¯ã•ã‚Œã¾ã™ã€‚ãªãŠã€AccessAddEx コマンドを使用ã™ã‚‹ã“ã¨ã§ã€é€šéŽæ™‚ã«é…延・ジッタ・パケットロスを発生ã•ã›ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessAdd_Args AccessAdd [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/TCPSTATE:established|unestablished]
+CMD_AccessAdd_[pass|discard] パケットãŒã€ã“ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸå ´åˆã®å‹•ä½œã‚’決定ã—ã¾ã™ã€‚pass を指定ã™ã‚‹ã¨ [通éŽ] ã‚’ã€discard を指定ã™ã‚‹ã¨ [破棄] ã‚’æ„味ã—ã¾ã™ã€‚
+CMD_AccessAdd_MEMO ルールã®èª¬æ˜Ž (メモ) を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚優先順ä½ã¯å°ã•ã„ã‚‚ã®ã»ã©å„ªå…ˆåº¦ãŒé«˜ããªã‚Šã¾ã™ã€‚
+CMD_AccessAdd_SRCIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ IPv4 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚IP アドレス㯠192.168.0.1 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚0.0.0.0/0.0.0.0 を指定ã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ›ã‚¹ãƒˆã‚’示ã—ã¾ã™ã€‚
+CMD_AccessAdd_DESTIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ IPv4 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚指定方法㯠/SRCIP パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd_PROTOCOL ルールã®æ¡ä»¶ã¨ã—ã¦ã€ãƒ—ロトコルã®ç¨®é¡žã‚’指定ã—ã¾ã™ã€‚IP プロトコル番å·ã‚’ 10 進数ã§å…¥åŠ›ã™ã‚‹ã‹ã€"tcp" (TCP/IP プロトコルã€6 番)ã€"udp" (UDP/IP プロトコルã€17番)ã€"icmpv4" (ICMPv4 プロトコルã€1 番)ã€"icmpv6" (ICMPv6 プロトコルã€58 番)ã€"ip" (ã™ã¹ã¦ã® IP プロトコルã€0 番) ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’指定ã—ã¾ã™ã€‚ã™ã¹ã¦ã® IP プロトコルを対象ã¨ã™ã‚‹ã«ã¯ 0 を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd_SRCPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆç•ªå·ãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚指定方法ã¯ã€"1-1024" (1 番以上 1024 番以下)ã€"23" (23 番ã®ã¿) ãªã©ã®ã‚ˆã†ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAdd_DESTPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚指定方法㯠/SRCPORT パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd_SRCUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦é€ä¿¡ã•ã‚ŒãŸãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAdd_DESTUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒå—ä¿¡ã™ã‚‹ãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAdd_SRCMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ MAC アドレスを指定ã—ã¾ã™ã€‚MAC アドレス㯠00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00 ã®ã‚ˆã†ã« 16 進数㨠"-" ã‹ ":" ã®åŒºåˆ‡ã‚Šæ–‡å­—を使用ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚区切り文字ã¯çœç•¥ã§ãã¾ã™ã€‚
+CMD_AccessAdd_DESTMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ MAC アドレスを指定ã—ã¾ã™ã€‚指定方法ã¯ã€/SRCMAC パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd_TCPSTATE ルールã®æ¡ä»¶ã¨ã—ã¦ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’指定ã—ã¾ã™ã€‚ Established ã¾ãŸã¯ Unestablished を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd_Prompt_TYPE pass ã¾ãŸã¯ discard:
+CMD_AccessAdd_Prompt_MEMO ルールã®èª¬æ˜Ž (メモ):
+CMD_AccessAdd_Prompt_PRIORITY ルールã®å„ªå…ˆé †ä½:
+CMD_AccessAdd_Eval_PRIORITY 優先順ä½ã¯ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_AccessAdd_Prompt_SRCIP é€ä¿¡å…ƒ IP アドレス (0.0.0.0/0 ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_DESTIP 宛先 IP アドレス (0.0.0.0/0 ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_PROTOCOL プロトコル番å·ã¾ãŸã¯ãƒ—ロトコルå (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd_Prompt_SRCPORT é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã®ç¯„囲 (tcp/udp ã®å ´åˆã®ã¿):
+CMD_AccessAdd_Prompt_DESTPORT 宛先ãƒãƒ¼ãƒˆç•ªå·ã®ç¯„囲 (tcp/udp ã®å ´åˆã®ã¿):
+CMD_AccessAdd_Prompt_SRCUSERNAME é€ä¿¡ãƒ¦ãƒ¼ã‚¶ãƒ¼å (無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_DESTUSERNAME å—信ユーザーå (無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_SRCMAC é€ä¿¡å…ƒ MAC アドレスã¨ãƒžã‚¹ã‚¯(無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_DESTMAC 宛先 MAC アドレスã¨ãƒžã‚¹ã‚¯(無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd_Prompt_TCPSTATE TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ (Established/Unestablished):
+
+
+# AccessAddEx コマンド
+CMD_AccessAddEx アクセスリストã¸ã®ãƒ«ãƒ¼ãƒ«ã®è¿½åŠ  (IPv4, é…延・ジッタ・パケットロス設定å¯èƒ½)
+CMD_AccessAddEx_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ã€æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚通éŽæ™‚ã«é…延・ジッタ・パケットロスを発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nアクセスリストã¨ã¯ã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã‚‹ãƒ‘ケットフィルタルールã®é›†åˆã§ã™ã€‚アクセスリストã«ã¯è¤‡æ•°ã®ãƒ«ãƒ¼ãƒ«ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã€å„ルールã”ã¨ã«å„ªå…ˆé †ä½ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã¹ã¦ã®ãƒ‘ケットã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るルールã§æŒ‡å®šã•ã‚ŒãŸæ¡ä»¶ã«ã€æœ€åˆã«ä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã§è¦å®šã•ã‚Œã¦ã„る動作ã§ã€é€šéŽã¾ãŸã¯ç ´æ£„ãŒæ±ºå®šã•ã‚Œã¾ã™ã€‚ã©ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ã‚‚一致ã—ãªã‹ã£ãŸãƒ‘ケットã¯ã€æš—é»™ã§é€šéŽã‚’許å¯ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessAddEx_Args AccessAddEx [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/TCPSTATE:established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx_[pass|discard] パケットãŒã€ã“ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸå ´åˆã®å‹•ä½œã‚’決定ã—ã¾ã™ã€‚pass を指定ã™ã‚‹ã¨ [通éŽ] ã‚’ã€discard を指定ã™ã‚‹ã¨ [破棄] ã‚’æ„味ã—ã¾ã™ã€‚é…延・ジッタ・パケットロス設定ã¯ã€pass ã®å ´åˆã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_AccessAddEx_MEMO ルールã®èª¬æ˜Ž (メモ) を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚優先順ä½ã¯å°ã•ã„ã‚‚ã®ã»ã©å„ªå…ˆåº¦ãŒé«˜ããªã‚Šã¾ã™ã€‚
+CMD_AccessAddEx_SRCIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ IPv4 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚IP アドレス㯠192.168.0.1 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã§ãã¾ã™ã€‚0.0.0.0/0.0.0.0 を指定ã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ›ã‚¹ãƒˆã‚’示ã—ã¾ã™ã€‚
+CMD_AccessAddEx_DESTIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ IPv4 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚指定方法㯠/SRCIP パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx_PROTOCOL ルールã®æ¡ä»¶ã¨ã—ã¦ã€ãƒ—ロトコルã®ç¨®é¡žã‚’指定ã—ã¾ã™ã€‚IP プロトコル番å·ã‚’ 10 進数ã§å…¥åŠ›ã™ã‚‹ã‹ã€"tcp" (TCP/IP プロトコルã€6 番)ã€"udp" (UDP/IP プロトコルã€17番)ã€"icmpv4" (ICMPv4 プロトコルã€1 番)ã€"icmpv6" (ICMPv6 プロトコルã€58 番)ã€"ip" (ã™ã¹ã¦ã® IP プロトコルã€0 番) ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’指定ã—ã¾ã™ã€‚ã™ã¹ã¦ã® IP プロトコルを対象ã¨ã™ã‚‹ã«ã¯ 0 を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx_SRCPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆç•ªå·ãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚指定方法ã¯ã€"1-1024" (1 番以上 1024 番以下)ã€"23" (23 番ã®ã¿) ãªã©ã®ã‚ˆã†ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAddEx_DESTPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚指定方法㯠/SRCPORT パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx_SRCUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦é€ä¿¡ã•ã‚ŒãŸãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx_DESTUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒå—ä¿¡ã™ã‚‹ãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx_SRCMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ MAC アドレスを指定ã—ã¾ã™ã€‚MAC アドレス㯠00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00 ã®ã‚ˆã†ã« 16 進数㨠"-" ã‹ ":" ã®åŒºåˆ‡ã‚Šæ–‡å­—を使用ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚区切り文字ã¯çœç•¥ã§ãã¾ã™ã€‚
+CMD_AccessAddEx_DESTMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ MAC アドレスを指定ã—ã¾ã™ã€‚指定方法ã¯ã€/SRCMAC パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx_TCPSTATE ルールã®æ¡ä»¶ã¨ã—ã¦ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’指定ã—ã¾ã™ã€‚Established ã¾ãŸã¯ Unestablished を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx_DELAY ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«é…延を発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚発生ã•ã›ãŸã„é…延時間をミリ秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€é…延ã¯ç™ºç”Ÿã—ã¾ã›ã‚“。é…延㯠10000 ミリ秒以下ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccessAddEx_JITTER ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«ã‚¸ãƒƒã‚¿ã‚’発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚é…延ã®å€¤ã«å¯¾ã—ã¦ã‚¸ãƒƒã‚¿ã®æºã‚‰ãŽã‚’ 0% ~ 100% ã®ãƒ‘ーセント数値ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€ã‚¸ãƒƒã‚¿ã¯ç™ºç”Ÿã—ã¾ã›ã‚“。
+CMD_AccessAddEx_LOSS ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«ãƒ‘ケットロスを発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚パケットãŒç ´æ£„ã•ã‚Œã‚‹å¯èƒ½æ€§ã‚’ 0% ~ 100% ã®ãƒ‘ーセント数値ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€ãƒ‘ケットロスã¯ç™ºç”Ÿã—ã¾ã›ã‚“。
+
+CMD_AccessAddEx_Prompt_DELAY 発生ã•ã›ã‚‹é…延 (ミリ秒å˜ä½: 0 - 10000):
+CMD_AccessAddEx_Prompt_JITTER 発生ã•ã›ã‚‹ã‚¸ãƒƒã‚¿ã®æºã‚‰ãŽ (パーセントå˜ä½: 0 - 100):
+CMD_AccessAddEx_Prompt_LOSS 発生ã•ã›ã‚‹ãƒ‘ケットロス率 (パーセントå˜ä½: 0 - 100):
+CMD_AccessAddEx_Eval_DELAY é…延㯠0 - 10000 ã®æ•´æ•°ã§è¨­å®šã—ã¦ãã ã•ã„。
+CMD_AccessAddEx_Eval_JITTER ジッタã®æºã‚‰ãŽã¯ 0 - 100 ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_AccessAddEx_Eval_LOSS パケットロス率㯠0 - 100 ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+
+# AccessAdd6 コマンド
+CMD_AccessAdd6 アクセスリストã¸ã®ãƒ«ãƒ¼ãƒ«ã®è¿½åŠ  (IPv6)
+CMD_AccessAdd6_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ã€æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚\nアクセスリストã¨ã¯ã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã‚‹ãƒ‘ケットフィルタルールã®é›†åˆã§ã™ã€‚アクセスリストã«ã¯è¤‡æ•°ã®ãƒ«ãƒ¼ãƒ«ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã€å„ルールã”ã¨ã«å„ªå…ˆé †ä½ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã¹ã¦ã®ãƒ‘ケットã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るルールã§æŒ‡å®šã•ã‚ŒãŸæ¡ä»¶ã«ã€æœ€åˆã«ä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã§è¦å®šã•ã‚Œã¦ã„る動作ã§ã€é€šéŽã¾ãŸã¯ç ´æ£„ãŒæ±ºå®šã•ã‚Œã¾ã™ã€‚ã©ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ã‚‚一致ã—ãªã‹ã£ãŸãƒ‘ケットã¯ã€æš—é»™ã§é€šéŽã‚’許å¯ã•ã‚Œã¾ã™ã€‚ãªãŠã€AccessAddEx6 コマンドを使用ã™ã‚‹ã“ã¨ã§ã€é€šéŽæ™‚ã«é…延・ジッタ・パケットロスを発生ã•ã›ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessAdd6_Args AccessAdd6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/TCPSTATE:established|unestablished]
+CMD_AccessAdd6_[pass|discard] パケットãŒã€ã“ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸå ´åˆã®å‹•ä½œã‚’決定ã—ã¾ã™ã€‚pass を指定ã™ã‚‹ã¨ [通éŽ] ã‚’ã€discard を指定ã™ã‚‹ã¨ [破棄] ã‚’æ„味ã—ã¾ã™ã€‚
+CMD_AccessAdd6_MEMO ルールã®èª¬æ˜Ž (メモ) を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd6_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚優先順ä½ã¯å°ã•ã„ã‚‚ã®ã»ã©å„ªå…ˆåº¦ãŒé«˜ããªã‚Šã¾ã™ã€‚
+CMD_AccessAdd6_SRCIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ IPv6 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚IPv6 アドレス㯠2001:200:0:1:: ã®ã‚ˆã†ã« 16 進数をコロンã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠ffff:ffff:ffff:ffff:: ã®ã‚ˆã†ã« IPv6 å½¢å¼ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€64 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã—ã¾ã™ã€‚å˜ä¸€ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ã¾ãŸã¯ 128 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚ã™ã¹ã¦ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€"::/0" ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAdd6_DESTIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ IPv6 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚指定方法㯠/SRCIP パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd6_PROTOCOL ルールã®æ¡ä»¶ã¨ã—ã¦ã€ãƒ—ロトコルã®ç¨®é¡žã‚’指定ã—ã¾ã™ã€‚IP プロトコル番å·ã‚’ 10 進数ã§å…¥åŠ›ã™ã‚‹ã‹ã€"tcp" (TCP/IP プロトコルã€6 番)ã€"udp" (UDP/IP プロトコルã€17番)ã€"icmpv4" (ICMPv4 プロトコルã€1 番)ã€"icmpv6" (ICMPv6 プロトコルã€58 番)ã€"ip" (ã™ã¹ã¦ã® IP プロトコルã€0 番) ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’指定ã—ã¾ã™ã€‚ã™ã¹ã¦ã® IP プロトコルを対象ã¨ã™ã‚‹ã«ã¯ 0 を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd6_SRCPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆç•ªå·ãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚指定方法ã¯ã€"1-1024" (1 番以上 1024 番以下)ã€"23" (23 番ã®ã¿) ãªã©ã®ã‚ˆã†ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAdd6_DESTPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚指定方法㯠/SRCPORT パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd6_SRCUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦é€ä¿¡ã•ã‚ŒãŸãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAdd6_DESTUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒå—ä¿¡ã™ã‚‹ãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAdd6_SRCMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ MAC アドレスを指定ã—ã¾ã™ã€‚MAC アドレス㯠00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00 ã®ã‚ˆã†ã« 16 進数㨠"-" ã‹ ":" ã®åŒºåˆ‡ã‚Šæ–‡å­—を使用ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚区切り文字ã¯çœç•¥ã§ãã¾ã™ã€‚
+CMD_AccessAdd6_DESTMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ MAC アドレスを指定ã—ã¾ã™ã€‚指定方法ã¯ã€/SRCMAC パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAdd6_TCPSTATE ルールã®æ¡ä»¶ã¨ã—ã¦ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’指定ã—ã¾ã™ã€‚ Established ã¾ãŸã¯ Unestablished を指定ã—ã¾ã™ã€‚
+CMD_AccessAdd6_Prompt_TYPE pass ã¾ãŸã¯ discard:
+CMD_AccessAdd6_Prompt_MEMO ルールã®èª¬æ˜Ž (メモ):
+CMD_AccessAdd6_Prompt_PRIORITY ルールã®å„ªå…ˆé †ä½:
+CMD_AccessAdd6_Eval_PRIORITY 優先順ä½ã¯ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_AccessAdd6_Prompt_SRCIP é€ä¿¡å…ƒ IPv6 アドレス (::/0 ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_DESTIP 宛先 IPv6 アドレス (::/0 ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_PROTOCOL プロトコル番å·ã¾ãŸã¯ãƒ—ロトコルå (tcp/udp/icmpv4/icmpv6/ip):
+CMD_AccessAdd6_Prompt_SRCPORT é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã®ç¯„囲 (tcp/udpã®å ´åˆã®ã¿):
+CMD_AccessAdd6_Prompt_DESTPORT 宛先ãƒãƒ¼ãƒˆç•ªå·ã®ç¯„囲 (tcp/udpã®å ´åˆã®ã¿):
+CMD_AccessAdd6_Prompt_SRCUSERNAME é€ä¿¡ãƒ¦ãƒ¼ã‚¶ãƒ¼å (無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_DESTUSERNAME å—信ユーザーå (無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_SRCMAC é€ä¿¡å…ƒ MAC アドレスã¨ãƒžã‚¹ã‚¯(無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_DESTMAC 宛先 MAC アドレスã¨ãƒžã‚¹ã‚¯(無指定ã§ã™ã¹ã¦):
+CMD_AccessAdd6_Prompt_TCPSTATE TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹(Established/Unestablished):
+
+
+# AccessAddEx6 コマンド
+CMD_AccessAddEx6 アクセスリストã¸ã®ãƒ«ãƒ¼ãƒ«ã®è¿½åŠ  (IPv6, é…延・ジッタ・パケットロス設定å¯èƒ½)
+CMD_AccessAddEx6_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ã€æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚通éŽæ™‚ã«é…延・ジッタ・パケットロスを発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nアクセスリストã¨ã¯ã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã‚‹ãƒ‘ケットフィルタルールã®é›†åˆã§ã™ã€‚アクセスリストã«ã¯è¤‡æ•°ã®ãƒ«ãƒ¼ãƒ«ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã€å„ルールã”ã¨ã«å„ªå…ˆé †ä½ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã¹ã¦ã®ãƒ‘ケットã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るルールã§æŒ‡å®šã•ã‚ŒãŸæ¡ä»¶ã«ã€æœ€åˆã«ä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã§è¦å®šã•ã‚Œã¦ã„る動作ã§ã€é€šéŽã¾ãŸã¯ç ´æ£„ãŒæ±ºå®šã•ã‚Œã¾ã™ã€‚ã©ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ã‚‚一致ã—ãªã‹ã£ãŸãƒ‘ケットã¯ã€æš—é»™ã§é€šéŽã‚’許å¯ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessAddEx6_Args AccessAddEx6 [pass|discard] [/MEMO:memo] [/PRIORITY:priority] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/SRCMAC:mac/mask] [/DESTMAC:mac/mask] [/SRCIP:ip/mask] [/DESTIP:ip/mask] [/PROTOCOL:tcp|udp|icmpv4|icmpv6|ip|num] [/SRCPORT:start-end] [/DESTPORT:start-end] [/SRCUSERNAME:username] [/DESTUSERNAME:username] [/TCPSTATE:established|unestablished] [/DELAY:delay_millisec] [/JITTER:jitter_percent] [/LOSS:loss_percent]
+CMD_AccessAddEx6_[pass|discard] パケットãŒã€ã“ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸå ´åˆã®å‹•ä½œã‚’決定ã—ã¾ã™ã€‚pass を指定ã™ã‚‹ã¨ [通éŽ] ã‚’ã€discard を指定ã™ã‚‹ã¨ [破棄] ã‚’æ„味ã—ã¾ã™ã€‚é…延・ジッタ・パケットロス設定ã¯ã€pass ã®å ´åˆã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_AccessAddEx6_MEMO ルールã®èª¬æ˜Ž (メモ) を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx6_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚優先順ä½ã¯å°ã•ã„ã‚‚ã®ã»ã©å„ªå…ˆåº¦ãŒé«˜ããªã‚Šã¾ã™ã€‚
+CMD_AccessAddEx6_SRCIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ IPv6 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚IPv6 アドレス㯠2001:200:0:1:: ã®ã‚ˆã†ã« 16 進数をコロンã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠ffff:ffff:ffff:ffff:: ã®ã‚ˆã†ã« IPv6 å½¢å¼ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€64 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã—ã¾ã™ã€‚å˜ä¸€ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ã¾ãŸã¯ 128 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚ã™ã¹ã¦ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€"::/0" ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAddEx6_DESTIP ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ IPv6 アドレスを "IPアドレス/マスク" ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™ã€‚指定方法㯠/SRCIP パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx6_PROTOCOL ルールã®æ¡ä»¶ã¨ã—ã¦ã€ãƒ—ロトコルã®ç¨®é¡žã‚’指定ã—ã¾ã™ã€‚IP プロトコル番å·ã‚’ 10 進数ã§å…¥åŠ›ã™ã‚‹ã‹ã€"tcp" (TCP/IP プロトコルã€6 番)ã€"udp" (UDP/IP プロトコルã€17番)ã€"icmpv4" (ICMPv4 プロトコルã€1 番)ã€"icmpv6" (ICMPv6 プロトコルã€58 番)ã€"ip" (ã™ã¹ã¦ã® IP プロトコルã€0 番) ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’指定ã—ã¾ã™ã€‚ã™ã¹ã¦ã® IP プロトコルを対象ã¨ã™ã‚‹ã«ã¯ 0 を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx6_SRCPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆç•ªå·ãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚指定方法ã¯ã€"1-1024" (1 番以上 1024 番以下)ã€"23" (23 番ã®ã¿) ãªã©ã®ã‚ˆã†ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccessAddEx6_DESTPORT プロトコル㌠TCP/IP ã¾ãŸã¯ UDP/IP ã®å ´åˆã¯ã€ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãれ以外ã®ãƒ—ロトコルã®å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚指定方法㯠/SRCPORT パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx6_SRCUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦é€ä¿¡ã•ã‚ŒãŸãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx6_DESTUSERNAME ルールã®æ¡ä»¶ã¨ã—ã¦ã€æŒ‡å®šã•ã‚ŒãŸåå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒå—ä¿¡ã™ã‚‹ãƒ‘ケットã®ã¿ã«ã€ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx6_SRCMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€é€ä¿¡å…ƒ MAC アドレスを指定ã—ã¾ã™ã€‚MAC アドレス㯠00-AC-84-EA-33-BC/FF-FF-FF-FF-FF-00 ã®ã‚ˆã†ã« 16 進数㨠"-" ã‹ ":" ã®åŒºåˆ‡ã‚Šæ–‡å­—を使用ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚区切り文字ã¯çœç•¥ã§ãã¾ã™ã€‚
+CMD_AccessAddEx6_DESTMAC ルールã®æ¡ä»¶ã¨ã—ã¦ã€å®›å…ˆ MAC アドレスを指定ã—ã¾ã™ã€‚指定方法ã¯ã€/SRCMAC パラメータã¨åŒæ§˜ã§ã™ã€‚
+CMD_AccessAddEx6_TCPSTATE ルールã®æ¡ä»¶ã¨ã—ã¦ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®çŠ¶æ…‹ã‚’指定ã—ã¾ã™ã€‚ Established ã¾ãŸã¯ Unestablished を指定ã—ã¾ã™ã€‚
+CMD_AccessAddEx6_DELAY ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«é…延を発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚発生ã•ã›ãŸã„é…延時間をミリ秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€é…延ã¯ç™ºç”Ÿã—ã¾ã›ã‚“。ジッタ㯠10000 ミリ秒以下ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccessAddEx6_JITTER ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«ã‚¸ãƒƒã‚¿ã‚’発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚é…延ã®å€¤ã«å¯¾ã—ã¦ã‚¸ãƒƒã‚¿ã®æºã‚‰ãŽã‚’ 0% ~ 100% ã®ãƒ‘ーセント数値ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€ã‚¸ãƒƒã‚¿ã¯ç™ºç”Ÿã—ã¾ã›ã‚“。
+CMD_AccessAddEx6_LOSS ã“ã®ãƒ«ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ãƒ‘ケットãŒé€šéŽã™ã‚‹å ´åˆã«ãƒ‘ケットロスを発生ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚パケットãŒç ´æ£„ã•ã‚Œã‚‹å¯èƒ½æ€§ã‚’ 0% ~ 100% ã®ãƒ‘ーセント数値ã§æŒ‡å®šã—ã¾ã™ã€‚無指定ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€ãƒ‘ケットロスã¯ç™ºç”Ÿã—ã¾ã›ã‚“。
+
+CMD_AccessAddEx6_Prompt_DELAY 発生ã•ã›ã‚‹é…延 (ミリ秒å˜ä½: 0 - 10000):
+CMD_AccessAddEx6_Prompt_JITTER 発生ã•ã›ã‚‹ã‚¸ãƒƒã‚¿ã®æºã‚‰ãŽ (パーセントå˜ä½: 0 - 100):
+CMD_AccessAddEx6_Prompt_LOSS 発生ã•ã›ã‚‹ãƒ‘ケットロス率 (パーセントå˜ä½: 0 - 100):
+CMD_AccessAddEx6_Eval_DELAY é…延㯠0 - 10000 ã®æ•´æ•°ã§è¨­å®šã—ã¦ãã ã•ã„。
+CMD_AccessAddEx6_Eval_JITTER ジッタã®æºã‚‰ãŽã¯ 0 - 100 ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_AccessAddEx6_Eval_LOSS パケットロス率㯠0 - 100 ã®æ•´æ•°ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+
+
+
+# AccessList コマンド
+CMD_AccessList アクセスリストã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã®å–å¾—
+CMD_AccessList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ã€ãƒ‘ケットフィルタルールã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nアクセスリストã¨ã¯ã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ãƒ‘ケットã«å¯¾ã—ã¦é©ç”¨ã•ã‚Œã‚‹ãƒ‘ケットフィルタルールã®é›†åˆã§ã™ã€‚アクセスリストã«ã¯è¤‡æ•°ã®ãƒ«ãƒ¼ãƒ«ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã€ãƒ«ãƒ¼ãƒ«æ¯Žã«å„ªå…ˆé †ä½ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã¹ã¦ã®ãƒ‘ケットã¯ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るルールã§æŒ‡å®šã•ã‚ŒãŸæ¡ä»¶ã«ã€æœ€åˆã«ä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã§è¦å®šã•ã‚Œã¦ã„る動作ã§ã€é€šéŽã¾ãŸã¯ç ´æ£„ãŒæ±ºå®šã•ã‚Œã¾ã™ã€‚ã©ã®ãƒ«ãƒ¼ãƒ«ã®æ¡ä»¶ã«ã‚‚一致ã—ãªã‹ã£ãŸãƒ‘ケットã¯ã€æš—é»™ã§é€šéŽã‚’許å¯ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessList_Args AccessList
+
+
+# AccessDelete コマンド
+CMD_AccessDelete アクセスリストã‹ã‚‰ãƒ«ãƒ¼ãƒ«ã‚’削除
+CMD_AccessDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ã€ãƒ‘ケットフィルタルールを指定ã—ã¦å‰Šé™¤ã—ã¾ã™ã€‚\nルールを削除ã™ã‚‹ã«ã¯ã€ãã®ãƒ«ãƒ¼ãƒ«ã® ID を指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ID 㯠AccessList コマンドã§è¡¨ç¤ºã§ãã¾ã™ã€‚\nãªãŠã€ãƒ«ãƒ¼ãƒ«ã‚’削除ã—ãªãã¦ã‚‚一時的ã«ç„¡åŠ¹åŒ–ã™ã‚‹ã«ã¯ AccessDisable コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessDelete_Args AccessDelete [id]
+CMD_AccessDelete_[id] 削除ã™ã‚‹ãƒ«ãƒ¼ãƒ«ã® ID ã¾ãŸã¯ãƒ¦ãƒ‹ãƒ¼ã‚¯ ID を指定ã—ã¾ã™ã€‚
+CMD_Access_Prompt_ID アクセスリストã®ãƒ«ãƒ¼ãƒ« ID ã¾ãŸã¯ãƒ¦ãƒ‹ãƒ¼ã‚¯ ID:
+
+
+# AccessEnable コマンド
+CMD_AccessEnable アクセスリストã®ãƒ«ãƒ¼ãƒ«ã®æœ‰åŠ¹åŒ–
+CMD_AccessEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るパケットフィルタルールを指定ã—ã¦æœ‰åŠ¹åŒ–ã—ã¾ã™ã€‚有効化ã—ãŸãƒ«ãƒ¼ãƒ«ã¯ã€ãƒ‘ケットフィルタリングã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nルールを有効化ã™ã‚‹ã«ã¯ã€ãã®ãƒ«ãƒ¼ãƒ«ã® ID を指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ID 㯠AccessList コマンドã§è¡¨ç¤ºã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessEnable_Args AccessEnable [id]
+CMD_AccessEnable_[id] 有効化ã™ã‚‹ãƒ«ãƒ¼ãƒ«ã® ID を指定ã—ã¾ã™ã€‚
+
+
+# AccessDisable コマンド
+CMD_AccessDisable アクセスリストã®ãƒ«ãƒ¼ãƒ«ã®ç„¡åŠ¹åŒ–
+CMD_AccessDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„るパケットフィルタルールを指定ã—ã¦ç„¡åŠ¹åŒ–ã—ã¾ã™ã€‚無効化ã—ãŸãƒ«ãƒ¼ãƒ«ã¯ã€ãƒ‘ケットフィルタリングã«ä½¿ç”¨ã•ã‚Œãªããªã‚Šã¾ã™ã€‚\nルールを無効化ã™ã‚‹ã«ã¯ã€ãã®ãƒ«ãƒ¼ãƒ«ã® ID を指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ID 㯠AccessList コマンドã§è¡¨ç¤ºã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AccessDisable_Args AccessDisable [id]
+CMD_AccessDisable_[id] 無効化ã™ã‚‹ãƒ«ãƒ¼ãƒ«ã® ID を指定ã—ã¾ã™ã€‚
+
+
+# UserList コマンド
+CMD_UserList ユーザー一覧ã®å–å¾—
+CMD_UserList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザー一覧をå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserList_Args UserList
+
+
+# UserCreate コマンド
+CMD_UserCreate ユーザーã®ä½œæˆ
+CMD_UserCreate_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ–°ã—ã„ユーザーを作æˆã—ã¾ã™ã€‚\nユーザーを作æˆã™ã‚‹ã¨ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®èªè¨¼æƒ…å ±ã«å¾“ã£ã¦ã€VPN Client ãŒã“ã®ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\nUserCreate コマンドを使用ã—ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’作æˆã—ãŸå ´åˆã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®èªè¨¼æ–¹æ³•ã¯ [パスワードèªè¨¼] ã¨ã—ã¦ç™»éŒ²ã•ã‚Œã€ãƒ‘スワードã¨ã—ã¦ãƒ©ãƒ³ãƒ€ãƒ ãªæ–‡å­—列ãŒå‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã—ãŸãŒã£ã¦ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ãã®ã¾ã¾ã§ã¯ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ユーザーを作æˆã—ãŸå¾Œã€å¿…ãš UserPasswordSet コマンドã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ‘スワードを指定ã™ã‚‹ã‹ã€UserAnonymousSet コマンドã€UserCertSet コマンドã€UserSignedSet コマンドã€UserRadiusSet コマンドã¾ãŸã¯ UserNTLMSet コマンドã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®èªè¨¼æ–¹æ³•ã‚’変更ã—ã¦ãã ã•ã„。\nãŸã ã—ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ "*" (アスタリスク 1 文字) ã¨ã—ã¦ä½œæˆã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€è‡ªå‹•çš„ã« RADIUS èªè¨¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã—ã¦ç™»éŒ²ã•ã‚Œã¾ã™ã€‚"*" ã¨ã„ã†åå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå­˜åœ¨ã™ã‚‹å ´åˆã«é™ã‚Šã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒ VPN Server ã«æŽ¥ç¶šã—ãŸéš›ã«æ示ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼åãŒæ—¢å­˜ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ä¸€è‡´ã—ãªã„ユーザーã¯ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå…¥åŠ›ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードã«ã‚ˆã£ã¦ã€RADIUS サーãƒãƒ¼ã¾ãŸã¯ NT ドメインコントローラã«ã‚ˆã£ã¦èªè¨¼ã•ã‚Œã‚‹ã“ã¨ãŒã§ãã€ãã®å ´åˆã®èªè¨¼è¨­å®šã‚„セキュリティãƒãƒªã‚·ãƒ¼ã®è¨­å®šã¯ "*" ユーザーã«è¨­å®šã«æº–æ‹ ã—ã¾ã™ã€‚\n一度作æˆã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼æƒ…報を変更ã™ã‚‹ã«ã¯ã€UserSet コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserCreate_Args UserCreate [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserCreate_[name] æ–°ã—ã作æˆã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserCreate_GROUP ユーザーをグループã«å‚加ã•ã›ã‚‹å ´åˆã€ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚ユーザーをã©ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚‚所属ã•ã›ãªã„å ´åˆã¯ /GROUP:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_UserCreate_REALNAME ユーザーã®æœ¬åを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/REALNAME:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_UserCreate_NOTE ユーザーã®èª¬æ˜Žã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/NOTE:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_UserCreate_Prompt_NAME ユーザーå:
+CMD_UserCreate_Prompt_GROUP å‚加ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—å:
+CMD_UserCreate_Prompt_REALNAME ユーザーã®æœ¬å:
+CMD_UserCreate_Prompt_NOTE ユーザーã®èª¬æ˜Ž:
+
+
+# UserSet コマンド
+CMD_UserSet ユーザー情報ã®å¤‰æ›´
+CMD_UserSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®æƒ…報を変更ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§å¤‰æ›´ã§ãるユーザーã®æƒ…å ±ã¯ã€UserCreate コマンドã§ã€æ–°ã—ãユーザーを作æˆã™ã‚‹ã¨ãã«æŒ‡å®šã™ã‚‹ã€Œã‚°ãƒ«ãƒ¼ãƒ—åã€ã€ã€Œæœ¬åã€ãŠã‚ˆã³ã€Œèª¬æ˜Žã€ã® 3 é …ç›®ã§ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserSet_Args UserSet [name] [/GROUP:group] [/REALNAME:realname] [/NOTE:note]
+CMD_UserSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserSet_GROUP ユーザーをグループã«å‚加ã•ã›ã‚‹å ´åˆã€ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚ユーザーをã©ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚‚所属ã•ã›ãªã„å ´åˆã¯ /GROUP:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_UserSet_REALNAME ユーザーã®æœ¬åを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/REALNAME:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_UserSet_NOTE ユーザーã®èª¬æ˜Žã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/NOTE:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+
+
+# UserDelete コマンド
+CMD_UserDelete ユーザーã®å‰Šé™¤
+CMD_UserDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーを削除ã—ã¾ã™ã€‚ユーザーを削除ã™ã‚‹ã¨ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\nUserPolicySet コマンドを使用ã™ã‚‹ã¨ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã—ãªãã¦ã‚‚ã€ä¸€æ™‚çš„ã«ãƒ­ã‚°ã‚¤ãƒ³ã‚’ç¦æ­¢ã™ã‚‹ã‚ˆã†ã«è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserDelete_Args UserDelete [name]
+CMD_UserDelete_[name] 削除ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+
+
+# UserGet コマンド
+CMD_UserGet ユーザー情報ã®å–å¾—
+CMD_UserGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ç™»éŒ²æƒ…報を所得ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§å–å¾—ã§ãる情報ã¯ã€ã€Œãƒ¦ãƒ¼ã‚¶ãƒ¼åã€ã€ã€Œæœ¬åã€ã€ã€Œèª¬æ˜Žã€ã€ã€Œæ‰€å±žã‚°ãƒ«ãƒ¼ãƒ—ã€ã€ã€Œæœ‰åŠ¹æœŸé™ã€ã€ã€Œã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã€ã€ã€Œèªè¨¼æ–¹æ³•ã€ã€ãŠã‚ˆã³è¨­å®šã•ã‚Œã¦ã„ã‚‹èªè¨¼æ–¹æ³•ã®å±žæ€§ã¨ã—ã¦æŒ‡å®šã•ã‚Œã¦ã„るパラメータã«åŠ ãˆã¦ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®çµ±è¨ˆãƒ‡ãƒ¼ã‚¿ã§ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserGet_Args UserGet [name]
+CMD_UserGet_[name] 情報をå–å¾—ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserGet_Column_Name ユーザーå
+CMD_UserGet_Column_RealName 本å
+CMD_UserGet_Column_Note 説明
+CMD_UserGet_Column_Group グループå
+CMD_UserGet_Column_Expires 有効期é™
+CMD_UserGet_Column_AuthType èªè¨¼æ–¹æ³•
+CMD_UserGet_Column_UserCert 登録済ã¿ãƒ¦ãƒ¼ã‚¶ãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸
+CMD_UserGet_Column_RadiusAlias 外部èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã®èªè¨¼ãƒ¦ãƒ¼ã‚¶ãƒ¼å
+CMD_UserGet_Column_RootCert_CN 証明書㮠CN ã®å€¤ã®é™å®š
+CMD_UserGet_Column_RootCert_SERIAL 証明書ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå·ã®é™å®š
+CMD_UserGet_Policy ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«è¨­å®šã•ã‚ŒãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼
+
+
+# UserAnonymousSet コマンド
+CMD_UserAnonymousSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’匿åèªè¨¼ã«è¨­å®š
+CMD_UserAnonymousSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「匿åèªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚匿åèªè¨¼ã«è¨­å®šã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã—㟠VPN Client ã¯ã€ã„ã‹ãªã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã‚‚å—ã‘ãšã«ç„¡æ¡ä»¶ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚匿åèªè¨¼æ©Ÿèƒ½ã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãªã©ã§åºƒã誰ã§ã‚‚接続ã§ãるよã†ãªè¨­å®šã§å…¬é–‹ã™ã‚‹ VPN Server ã«æœ€é©ã§ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserAnonymousSet_Args UserAnonymousSet [name]
+CMD_UserAnonymousSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+
+
+# UserPasswordSet コマンド
+CMD_UserPasswordSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’パスワードèªè¨¼ã«è¨­å®šã—パスワードを設定
+CMD_UserPasswordSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「パスワードèªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚パスワードèªè¨¼ã¨ã¯ã€ä»®æƒ³ HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ オブジェクトã«å¯¾ã—ã¦ä»»æ„ã®ãƒ‘スワードを設定ã—ã¦ãŠãã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ãƒ‘スワードã®å…¥åŠ›ã‚’求ã‚ã€ãã®ãƒ‘スワードãŒä¸€è‡´ã—ãŸå ´åˆã«æŽ¥ç¶šã‚’許å¯ã™ã‚‹èªè¨¼æ–¹æ³•ã§ã™ã€‚\n実際ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ‘スワードã¯ãƒãƒƒã‚·ãƒ¥åŒ–ã•ã‚Œä¿å­˜ã•ã‚Œã‚‹ã®ã§ã€VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’解æžã—ã¦ã‚‚å…ƒã®ãƒ‘スワードã¯ã‚ã‹ã‚Šã¾ã›ã‚“。\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserPasswordSet_Args UserPasswordSet [name] [/PASSWORD:password]
+CMD_UserPasswordSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserPasswordSet_PASSWORD ユーザーã«å¯¾ã—ã¦è¨­å®šã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ã€ãƒ‘スワードを入力ã™ã‚‹ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# UserCertSet コマンド
+CMD_UserCertSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’固有証明書èªè¨¼ã«è¨­å®šã—証明書を設定
+CMD_UserCertSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「固有証明書èªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚固有証明書èªè¨¼ã¨ã¯ã€ä»®æƒ³ HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ オブジェクトã«å¯¾ã—㦠1 ã¤ã® X.509 証明書を設定ã—ã¦ãŠãã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ã€æ示ã—ãŸè¨¼æ˜Žæ›¸ãŒç™»éŒ²ã•ã‚Œã¦ã„る証明書ã¨ä¸€è‡´ã—ã€ã‹ã¤ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãã®è¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµã‚’ä¿æŒã—ã¦ã„ã‚‹ã‹ã‚’ RSA アルゴリズムã§æ¤œè¨¼ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦æŽ¥ç¶šã‚’許å¯ã™ã‚‹èªè¨¼æ–¹æ³•ã§ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserCertSet_Args UserCertSet [name] [/LOADCERT:cert]
+CMD_UserCertSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserCertSet_LOADCERT ユーザーã«å¯¾ã—ã¦è¨­å®šã™ã‚‹è¨¼æ˜Žæ›¸ã‚’ X.509 証明書ファイルåã§æŒ‡å®šã—ã¾ã™ã€‚
+
+
+# UserCertGet コマンド
+CMD_UserCertGet 固有証明書èªè¨¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç™»éŒ²ã•ã‚Œã¦ã„る証明書ã®å–å¾—
+CMD_UserCertGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„る「固有証明書èªè¨¼ã€ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¯¾ã—ã¦è¨­å®šã•ã‚Œã¦ã„ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã€ãƒ•ã‚¡ã‚¤ãƒ«ã«ä¿å­˜ã—ã¾ã™ã€‚\n指定ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã€Œå›ºæœ‰è¨¼æ˜Žæ›¸èªè¨¼ã€ã¨ã—ã¦è¨­å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserCertGet_Args UserCertGet [name] [/SAVECERT:cert]
+CMD_UserCertGet_[name] 情報をå–å¾—ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserCertGet_SAVECERT å–å¾—ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®è¨¼æ˜Žæ›¸ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_UserCertGet_Not_Cert ユーザーã¯å›ºæœ‰è¨¼æ˜Žæ›¸èªè¨¼ã§ãªã„ã‹ã€å›ºæœ‰è¨¼æ˜Žæ›¸ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+
+
+# UserSignedSet コマンド
+CMD_UserSignedSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’ç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ã«è¨­å®š
+CMD_UserSignedSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「署å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚ç½²å済ã¿è¨¼æ˜Žæ›¸èªè¨¼ã«è¨­å®šã•ã‚Œã¦ã„るユーザーåã§ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ示ã—ãŸè¨¼æ˜Žæ›¸ãŒãã®ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®ä¸€è¦§å†…ã®è¨¼æ˜Žæ›¸ã®ã„ãšã‚Œã‹ã«ã‚ˆã£ã¦ç½²åã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ãŒæ¤œæŸ»ã•ã‚Œã€ã‹ã¤ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãã®è¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµã‚’ä¿æŒã—ã¦ã„ã‚‹ã‹ã‚’ RSA アルゴリズムã§æ¤œè¨¼ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦æŽ¥ç¶šã‚’許å¯ã™ã‚‹èªè¨¼æ–¹æ³•ã§ã™ã€‚\nã¾ãŸã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã”ã¨ã«æœŸå¾…ã™ã‚‹è¨¼æ˜Žæ›¸ã® Common Name (CN)ã€ãŠã‚ˆã³ã‚·ãƒªã‚¢ãƒ«ç•ªå·ã‚’登録ã—ã¦ãŠãã€å‰è¨˜ã®æ¤œè¨¼ã‚’通éŽã—ãŸå¾Œè¨¼æ˜Žæ›¸ã®å†…容ãŒè¨­å®šã•ã‚ŒãŸå€¤ã«ä¸€è‡´ã—ãŸå ´åˆã«ã®ã¿æŽ¥ç¶šã‚’許å¯ã™ã‚‹ã‚ˆã†ã«ã™ã‚‹è¨­å®šã‚‚å¯èƒ½ã§ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserSignedSet_Args UserSignedSet [name] [/CN:cn] [/SERIAL:serial]
+CMD_UserSignedSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserSignedSet_CN ã“ã®ãƒ‘ラメータを指定ã—ãŸå ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ示ã—ãŸè¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãる証明機関ã«ã‚ˆã£ã¦ç½²åã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’検証ã—ãŸå¾Œã«ã€ãã®è¨¼æ˜Žæ›¸ã® Common Name (CN) ã®å€¤ã‚’ã€ã“ã®ãƒ‘ラメータã«ã‚ˆã£ã¦è¨­å®šã•ã‚ŒãŸå€¤ã¨æ¯”較ã—ã¦ä¸€è‡´ã—ã¦ã„ã‚‹å ´åˆã®ã¿æŽ¥ç¶šã‚’許å¯ã—ã¾ã™ã€‚"none" を指定ã—ãŸå ´åˆã¯ã€ã“ã®ãƒã‚§ãƒƒã‚¯ã¯è¡Œã‚ã‚Œã¾ã›ã‚“。
+CMD_UserSignedSet_SERIAL ã“ã®ãƒ‘ラメータを指定ã—ãŸå ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ示ã—ãŸè¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ãる証明機関ã«ã‚ˆã£ã¦ç½²åã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’検証ã—ãŸå¾Œã«ã€ãã®è¨¼æ˜Žæ›¸ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå·ã®å€¤ã‚’ã€ã“ã®ãƒ‘ラメータã«ã‚ˆã£ã¦è¨­å®šã•ã‚ŒãŸå€¤ã¨æ¯”較ã—ã¦ä¸€è‡´ã—ã¦ã„ã‚‹å ´åˆã®ã¿æŽ¥ç¶šã‚’許å¯ã—ã¾ã™ã€‚"none" を指定ã—ãŸå ´åˆã¯ã€ã“ã®ãƒã‚§ãƒƒã‚¯ã¯è¡Œã‚ã‚Œã¾ã›ã‚“。
+CMD_UserSignedSet_Prompt_CN Common Name (CN) ã®å€¤ã‚’é™å®š:
+CMD_UserSignedSet_Prompt_SERIAL シリアル番å·ã®å€¤ã‚’é™å®š:
+
+
+# UserRadiusSet コマンド
+CMD_UserRadiusSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’ RADIUS èªè¨¼ã«è¨­å®š
+CMD_UserRadiusSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「RADIUS èªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚RADIUS èªè¨¼ã«è¨­å®šã•ã‚Œã¦ã„るユーザーåã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå…¥åŠ›ã—ãŸãƒ‘スワード㌠RADIUS サーãƒãƒ¼ã«é€ä¿¡ã•ã‚Œã€RADIUS サーãƒãƒ¼ãŒãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードã®ãƒã‚§ãƒƒã‚¯ã‚’è¡Œã£ãŸå¾Œã«èªè¨¼ãŒæˆåŠŸã™ã‚‹ã¨ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã® VPN 接続ãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚\nRadius èªè¨¼ã‚’使用ã™ã‚‹ã«ã¯ã€ã‚らã‹ã˜ã‚ RadiusServerSet コマンドを使用ã—ã¦ä½¿ç”¨ã™ã‚‹ RADIUS サーãƒãƒ¼ã‚’仮想 HUB ã«è¨­å®šã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserRadiusSet_Args UserRadiusSet [name] [/ALIAS:alias_name]
+CMD_UserRadiusSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserRadiusSet_ALIAS ã“ã®ãƒ‘ラメータãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã€RADIUS サーãƒãƒ¼ã«å¯¾ã—ã¦é€ä¿¡ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ã€ä»®æƒ³ HUB 上ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ã¯åˆ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã«ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚設定ã—ãªã„å ´åˆã¯ã€/ALIAS:none ã¨æŒ‡å®šã—ã¦ãã ã•ã„ (仮想 HUB 上ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åãŒä½¿ç”¨ã•ã‚Œã¾ã™)。ユーザーå㌠"*" ã®å ´åˆã¯ /ALIAS パラメータã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚"*" ユーザーã«ã¤ã„ã¦ã®èª¬æ˜Žã¯ã€UserCreate /HELP ã¨å…¥åŠ›ã™ã‚‹ã¨è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_UserRadiusSet_Prompt_ALIAS èªè¨¼ç”¨ã‚¨ã‚¤ãƒªã‚¢ã‚¹å (オプション):
+
+
+# UserNTLMSet コマンド
+CMD_UserNTLMSet ユーザーã®èªè¨¼æ–¹æ³•ã‚’ NT ドメインèªè¨¼ã«è¨­å®š
+CMD_UserNTLMSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®èªè¨¼æ–¹æ³•ã‚’「NT ドメインèªè¨¼ã€ã«è¨­å®šã—ã¾ã™ã€‚NT ドメインèªè¨¼ã«è¨­å®šã•ã‚Œã¦ã„るユーザーåã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå…¥åŠ›ã—ãŸãƒ‘スワード㌠Windows NT / 2000 / Server 2003 / Server 2008 / Server 2008 R2 / Server 2012 ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã€ã¾ãŸã¯ Active Directory サーãƒãƒ¼ã«é€ä¿¡ã•ã‚Œã€èªè¨¼ã‚µãƒ¼ãƒãƒ¼ãŒãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードã®ãƒã‚§ãƒƒã‚¯ã‚’è¡Œã£ãŸå¾Œã«èªè¨¼ãŒæˆåŠŸã™ã‚‹ã¨ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã® VPN 接続ãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚\nNT ドメインèªè¨¼ã‚’使用ã™ã‚‹ã«ã¯ã€VPN Server ãŒãã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ Windows NT 4.0, Windows 2000, Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008, Windows 7, Windows Server 2008 R2, Windows 8, Windows Server 2012 ã®ã„ãšã‚Œã‹ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ä¸Šã§å‹•ä½œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚詳ã—ã㯠VPN Server ã®ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserNTLMSet_Args UserNTLMSet [name] [/ALIAS:alias_name]
+CMD_UserNTLMSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserNTLMSet_ALIAS ã“ã®ãƒ‘ラメータãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã€NT ドメインã¾ãŸã¯ Active Directory ã«å¯¾ã—ã¦é€ä¿¡ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ã€ä»®æƒ³ HUB 上ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ã¯åˆ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã«ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚設定ã—ãªã„å ´åˆã¯ã€/ALIAS:none ã¨æŒ‡å®šã—ã¦ãã ã•ã„ (仮想 HUB 上ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åãŒä½¿ç”¨ã•ã‚Œã¾ã™)。ユーザーå㌠"*" ã®å ´åˆã¯ /ALIAS パラメータã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚"*" ユーザーã«ã¤ã„ã¦ã®èª¬æ˜Žã¯ã€UserCreate /HELP ã¨å…¥åŠ›ã™ã‚‹ã¨è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# UserPolicyRemove コマンド
+CMD_UserPolicyRemove ユーザーã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å‰Šé™¤
+CMD_UserPolicyRemove_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã«å¯¾ã—ã¦è¨­å®šã•ã‚Œã¦ã„ã‚‹ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®šã‚’削除ã—ã¾ã™ã€‚セキュリティãƒãƒªã‚·ãƒ¼ã®è¨­å®šãŒå‰Šé™¤ã•ã‚Œã¦ã„るユーザーã¯ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ‰€å±žã—ã¦ã„るグループã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®šãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚グループã«æ‰€å±žã—ã¦ã„ãªã„ã‹ã€ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å€¤ (アクセスを許å¯: 有効ã€TCP 接続数ã®æœ€å¤§å€¤: 32 個ã€ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆæ™‚é–“: 20 秒) ã«å¾“ã„ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserPolicyRemove_Args UserPolicyRemove [name]
+CMD_UserPolicyRemove_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+
+
+# UserPolicySet コマンド
+CMD_UserPolicySet ユーザーã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®š
+CMD_UserPolicySet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã«å¯¾ã—ã¦è¨­å®šã•ã‚Œã¦ã„るセキュリティãƒãƒªã‚·ãƒ¼ã®å†…容を変更ã—ã¾ã™ã€‚\nユーザーã«ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€æ–°ã—ã„デフォルトã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã‚’設定ã—ã¦ã‹ã‚‰ã€æŒ‡å®šã•ã‚ŒãŸå€¤ã‚’変更ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserPolicySet_Args UserPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_UserPolicySet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserPolicySet_NAME 値を変更ã™ã‚‹ãƒãƒªã‚·ãƒ¼ã®åå‰ã‚’指定ã—ã¾ã™ã€‚ãƒãƒªã‚·ãƒ¼ã®åå‰ã¨è¨­å®šã§ãる値ã®ä¸€è¦§ã¯ PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_UserPolicySet_VALUE ãƒãƒªã‚·ãƒ¼ã®æ–°ã—ã„値を指定ã—ã¾ã™ã€‚ãã®ãƒãƒªã‚·ãƒ¼ãŒæ•°å€¤åž‹ã®å ´åˆã¯æ•´æ•°ã‚’指定ã—ã¾ã™ã€‚ブール型ã®å ´åˆã¯ yes ã¾ãŸã¯ no を指定ã—ã¾ã™ã€‚設定ã§ãã‚‹åž‹ã¨å€¤ã¯ã€PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+
+# UserExpiresSet コマンド
+CMD_UserExpiresSet ユーザーã®æœ‰åŠ¹æœŸé™ã®è¨­å®š
+CMD_UserExpiresSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®æœ‰åŠ¹æœŸé™ã‚’設定ã—ã¾ã™ã€‚有効期é™ãŒçµ‚了ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€ä»®æƒ³ HUB ã«æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€UserList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_UserExpiresSet_Args UserExpiresSet [name] [/EXPIRES:expires]
+CMD_UserExpiresSet_[name] 設定を変更ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_UserExpiresSet_EXPIRES ユーザーã®æœ‰åŠ¹æœŸé™ã®æ—¥æ™‚を指定ã—ã¾ã™ã€‚"2005/10/08 19:30:00" ã®ã‚ˆã†ã«ã€å¹´ãƒ»æœˆãƒ»æ—¥ãƒ»æ™‚・分・秒 ã® 6 個ã®æ•´æ•°ã‚’スペースã€ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã¾ãŸã¯ã‚³ãƒ­ãƒ³ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¦ãã ã•ã„。年㯠4 æ¡ã§æŒ‡å®šã—ã¦ãã ã•ã„。値ã«ã‚¹ãƒšãƒ¼ã‚¹ã‚’入れる場åˆã¯ã€å€¤å…¨ä½“ã‚’ "" ã§å›²ã‚€å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚指定ã¯ãƒ­ãƒ¼ã‚«ãƒ«æ™‚刻 (コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’実行ã—ã¦ã„るコンピュータã®åŸºæº–時刻) ã§æŒ‡å®šã§ãã¾ã™ã€‚/EXPIRES:none ã¨æŒ‡å®šã™ã‚‹ã¨ã€æœ‰åŠ¹æœŸé™ã¯è§£é™¤ã•ã‚Œã¾ã™ã€‚
+CMD_UserExpiresSet_Prompt_EXPIRES ユーザーã®æœ‰åŠ¹æœŸé™ (無指定ã§ç„¡æœŸé™):
+
+
+# GroupList コマンド
+CMD_GroupList グループ一覧ã®å–å¾—
+CMD_GroupList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループ一覧をå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupList_Args GroupList
+
+
+# GroupCreate コマンド
+CMD_GroupCreate グループã®ä½œæˆ
+CMD_GroupCreate_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ–°ã—ã„グループを作æˆã—ã¾ã™ã€‚\nグループã«ã¯è¤‡æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’登録ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’登録ã™ã‚‹ã«ã¯ã€GroupJoin コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupCreate_Args GroupCreate [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupCreate_[name] 作æˆã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_GroupCreate_REALNAME グループã®æœ¬åを指定ã—ã¾ã™ã€‚ãŸã¨ãˆã°ã€ã‚°ãƒ«ãƒ¼ãƒ—ãŒå®Ÿéš›ã®éƒ¨èª²åã«å¯¾å¿œã™ã‚‹å ´åˆã¯ã€ãã®åå‰ã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/REALNAME:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_GroupCreate_NOTE グループã®èª¬æ˜Žã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/NOTE:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_GroupCreate_Prompt_NAME グループå:
+CMD_GroupCreate_Prompt_REALNAME グループã®æœ¬å:
+CMD_GroupCreate_Prompt_NOTE グループã®èª¬æ˜Ž:
+
+
+# GroupSet コマンド
+CMD_GroupSet グループ情報ã®è¨­å®š
+CMD_GroupSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã®æƒ…報を設定ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupSet_Args GroupSet [name] [/REALNAME:realname] [/NOTE:note]
+CMD_GroupSet_[name] 設定を変更ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_GroupSet_REALNAME グループã®æœ¬åを指定ã—ã¾ã™ã€‚ãŸã¨ãˆã°ã€ã‚°ãƒ«ãƒ¼ãƒ—ãŒå®Ÿéš›ã®éƒ¨èª²åã«å¯¾å¿œã™ã‚‹å ´åˆã¯ã€ãã®åå‰ã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/REALNAME:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+CMD_GroupSet_NOTE グループã®èª¬æ˜Žã‚’指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€/NOTE:none ã¨æŒ‡å®šã—ã¾ã™ã€‚
+
+
+# GroupDelete コマンド
+CMD_GroupDelete グループã®å‰Šé™¤
+CMD_GroupDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループを削除ã—ã¾ã™ã€‚\nグループを削除ã™ã‚‹ã¨ã€ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã™ã¹ã¦ç„¡æ‰€å±žã«ãªã‚Šã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupDelete_Args GroupDelete [name]
+CMD_GroupDelete_[name] 削除ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™
+
+
+# GroupGet コマンド
+CMD_GroupGet グループ情報ã¨æ‰€å±žã—ã¦ã„るユーザー一覧ã®å–å¾—
+CMD_GroupGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã®æƒ…å ±ã¨ã€ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupGet_Args GroupGet [name]
+CMD_GroupGet_[name] 情報をå–å¾—ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_GroupGet_Column_NAME グループå
+CMD_GroupGet_Column_REALNAME 本å
+CMD_GroupGet_Column_NOTE 説明
+CMD_GroupGet_Column_POLICY ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«è¨­å®šã•ã‚Œã¦ã„るセキュリティãƒãƒªã‚·ãƒ¼
+CMD_GroupGet_Column_MEMBERS ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„るユーザーåã®ä¸€è¦§
+
+
+# GroupJoin コマンド
+CMD_GroupJoin グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加
+CMD_GroupJoin_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã«ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るユーザーã¨ã‚°ãƒ«ãƒ¼ãƒ—ã®ä¸€è¦§ã¯ã€UserList コマンド㨠GroupList コマンドã§å–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupJoin_Args GroupJoin [name] [/USERNAME:username]
+CMD_GroupJoin_[name] ユーザーを追加ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_GroupJoin_USERNAME name ã§æŒ‡å®šã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã«è¿½åŠ ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_GroupJoin_Prompt_USERNAME グループã«å‚加ã•ã›ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼å:
+
+
+# GroupUnjoin コマンド
+CMD_GroupUnjoin グループã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除
+CMD_GroupUnjoin_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã‹ã‚‰ã€æŒ‡å®šã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã—ã¾ã™ã€‚グループã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå‰Šé™¤ã•ã‚Œã‚‹ã¨ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ç„¡æ‰€å±žã¨ãªã‚Šã¾ã™ã€‚\nグループã«ç¾åœ¨æ‰€å±žã—ã¦ã„るユーザーã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupGet コマンドを使用ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupUnjoin_Args GroupUnjoin [name]
+CMD_GroupUnjoin_[name] グループã‹ã‚‰å‰Šé™¤ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_GroupUnjoin_Prompt_name グループã‹ã‚‰å‰Šé™¤ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼å:
+
+
+# GroupPolicyRemove コマンド
+CMD_GroupPolicyRemove グループã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®å‰Šé™¤
+CMD_GroupPolicyRemove_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã«å¯¾ã—ã¦è¨­å®šã•ã‚Œã¦ã„るセキュリティãƒãƒªã‚·ãƒ¼ã®è¨­å®šã‚’削除ã—ã¾ã™ã€‚所属ã—ã¦ã„るグループã«ã‚‚ユーザー本体ã«ã‚‚セキュリティãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„ユーザーã¯ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å€¤ (アクセスを許å¯: 有効ã€TCP 接続数ã®æœ€å¤§å€¤: 32 個ã€ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆæ™‚é–“: 20 秒) ã«å¾“ã„ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupPolicyRemove_Args GroupPolicyRemove [name]
+CMD_GroupPolicyRemove_[name] 設定を変更ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+
+
+# GroupPolicySet コマンド
+CMD_GroupPolicySet グループã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã®è¨­å®š
+CMD_GroupPolicySet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã®ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã«å¯¾ã—ã¦è¨­å®šã•ã‚Œã¦ã„るセキュリティãƒãƒªã‚·ãƒ¼ã®å†…容を変更ã—ã¾ã™ã€‚\nグループã«ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€æ–°ã—ã„デフォルトã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã‚’設定ã—ã¦ã‹ã‚‰ã€æŒ‡å®šã•ã‚ŒãŸå€¤ã‚’変更ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るグループã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GroupList コマンドを使用ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_GroupPolicySet_Args GroupPolicySet [name] [/NAME:policy_name] [/VALUE:num|yes|no]
+CMD_GroupPolicySet_[name] 設定を変更ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—åを指定ã—ã¾ã™ã€‚
+CMD_GroupPolicySet_NAME 値を変更ã™ã‚‹ãƒãƒªã‚·ãƒ¼ã®åå‰ã‚’指定ã—ã¾ã™ã€‚ãƒãƒªã‚·ãƒ¼ã®åå‰ã¨è¨­å®šã§ãる値ã®ä¸€è¦§ã¯ã€PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_GroupPolicySet_VALUE ãƒãƒªã‚·ãƒ¼ã®æ–°ã—ã„値を指定ã—ã¾ã™ã€‚ãã®ãƒãƒªã‚·ãƒ¼ãŒæ•°å€¤åž‹ã®å ´åˆã¯æ•´æ•°ã‚’指定ã—ã¾ã™ã€‚ブール型ã®å ´åˆã¯ yes ã¾ãŸã¯ no を指定ã—ã¾ã™ã€‚設定ã§ãã‚‹åž‹ã¨å€¤ã¯ã€PolicyList コマンドã§è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+
+# SessionList コマンド
+CMD_SessionList 接続中ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸€è¦§ã®å–å¾—
+CMD_SessionList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚セッション一覧ã«ã¯ã€å„コãƒã‚¯ã‚·ãƒ§ãƒ³ã”ã¨ã® [セッションå]ã€[セッションã®å ´æ‰€]ã€[ユーザーå]ã€[接続元ホストå]ã€[TCP コãƒã‚¯ã‚·ãƒ§ãƒ³]ã€[転é€ãƒã‚¤ãƒˆæ•°]ã€[転é€ãƒ‘ケット数] ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\nç¾åœ¨æŽ¥ç¶šä¸­ã® VPN Server ãŒã‚¯ãƒ©ã‚¹ã‚¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã§ã€ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ä»®æƒ³ HUB ã®å ´åˆã¯ã€ã™ã¹ã¦ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã®å½“該仮想 HUB ã«æŽ¥ç¶šã—ã¦ã„るセッション一覧ãŒã™ã¹ã¦çµåˆã•ã‚Œã¦å–å¾—ã•ã‚Œã¾ã™ã€‚\nãれ以外ã®å ´åˆã¯ã€ç¾åœ¨ç®¡ç†ã—ã¦ã„ã‚‹ VPN Server ã«å®Ÿéš›ã«æŽ¥ç¶šã—ã¦ã„るセッション一覧ã®ã¿ãŒå–å¾—ã•ã‚Œã¾ã™ã€‚
+CMD_SessionList_Args SessionList
+
+
+# SessionGet コマンド
+CMD_SessionGet セッション情報ã®å–å¾—
+CMD_SessionGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’指定ã—ã¦ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®æƒ…報をå–å¾—ã—ã¾ã™ã€‚セッション情報ã«ã¯ã€æŽ¥ç¶šå…ƒãƒ›ã‚¹ãƒˆåやユーザーåã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã€æ™‚刻情報ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã€é€šä¿¡ãƒ‘ラメータã€ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚­ãƒ¼ã€é€å—ä¿¡ã—ãŸãƒ‡ãƒ¼ã‚¿ã®çµ±è¨ˆæƒ…å ±ã€ãã®ä»–ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚„サーãƒãƒ¼ã®æƒ…å ±ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚\nç¾åœ¨æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€SessionList コマンドを使用ã—ã¦ãã ã•ã„。
+CMD_SessionGet_Args SessionGet [name]
+CMD_SessionGet_[name] 情報をå–å¾—ã™ã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³åを指定ã—ã¾ã™ã€‚
+CMD_SessionGet_Prompt_NAME セッションå:
+
+
+# SessionDisconnect コマンド
+CMD_SessionDisconnect セッションã®åˆ‡æ–­
+CMD_SessionDisconnect_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’指定ã—ã¦ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’管ç†è€…権é™ã§å¼·åˆ¶åˆ‡æ–­ã—ã¾ã™ã€‚\nãŸã ã—ã€æŽ¥ç¶šå…ƒã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã®è¨­å®šã§é€šä¿¡ãŒåˆ‡æ–­ã•ã‚ŒãŸå ´åˆã¯è‡ªå‹•çš„ã«å†æŽ¥ç¶šã™ã‚‹ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ã‚‚ã†ä¸€åº¦æŽ¥ç¶šã—ã¦ãã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\nç¾åœ¨æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€SessionList コマンドを使用ã—ã¦ãã ã•ã„。
+CMD_SessionDisconnect_Args SessionDisconnect [name]
+CMD_SessionDisconnect_[name] 切断ã™ã‚‹ã‚»ãƒƒã‚·ãƒ§ãƒ³åを指定ã—ã¾ã™ã€‚
+
+
+# MacTable コマンド
+CMD_MacTable MAC アドレステーブルデータベースã®å–å¾—
+CMD_MacTable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿æŒã—ã¦ã„ã‚‹ MAC アドレステーブルデータベースをå–å¾—ã—ã¾ã™ã€‚\nMAC アドレステーブルデータベースã¯ã€ä»®æƒ³ HUB ㌠Ethernet フレームã®ã‚¹ã‚¤ãƒƒãƒãƒ³ã‚°å‹•ä½œã‚’è¡Œã†ãŸã‚ã«å¿…è¦ãªãƒ†ãƒ¼ãƒ–ルã§ã€ä»®æƒ³ HUB 㯠MAC アドレステーブルデータベースã«åŸºã¥ã„ã¦ã€å„ Ethernet フレームã®æŒ¯ã‚Šåˆ†ã‘先セッションを決定ã—ã¾ã™ã€‚MAC アドレスデータベースã¯ã€ä»®æƒ³ HUB ãŒæµã‚Œã‚‹é€šä¿¡ã®å†…容を自動的ã«åˆ†æžã—ã¦æ§‹ç¯‰ã—ã¾ã™ã€‚\nセッションåを指定ã—ã¦ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ MAC アドレステーブルエントリをå–å¾—ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MacTable_Args MacTable [session_name]
+CMD_MacTable_[session_name] 引数ã¨ã—ã¦ã‚»ãƒƒã‚·ãƒ§ãƒ³åを指定ã™ã‚‹ã¨ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ MAC アドレステーブルエントリã®ã¿ã‚’表示ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ã‚¨ãƒ³ãƒˆãƒªãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# MacDelete コマンド
+CMD_MacDelete MAC アドレステーブルエントリã®å‰Šé™¤
+CMD_MacDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿æŒã—ã¦ã„ã‚‹ MAC アドレステーブルデータベースをæ“作ã—ã€æŒ‡å®šã•ã‚ŒãŸ MAC アドレステーブルエントリをデータベースã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚\nç¾åœ¨ã® MAC アドレステーブルデータベースã®å†…容をå–å¾—ã™ã‚‹ã«ã¯ã€MacTable コマンドを使用ã—ã¦ãã ã•ã„。
+CMD_MacDelete_Args MacDelete [id]
+CMD_MacDelete_[id] 削除ã™ã‚‹ MAC アドレステーブルエントリ㮠ID を指定ã—ã¾ã™ã€‚
+CMD_MacDelete_Prompt 削除ã™ã‚‹ ID:
+
+
+# IpTable コマンド
+CMD_IpTable IP アドレステーブルデータベースã®å–å¾—
+CMD_IpTable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿æŒã—ã¦ã„ã‚‹ IP アドレステーブルデータベースをå–å¾—ã—ã¾ã™ã€‚\nIP アドレステーブルデータベースã¯ã€ã©ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒã©ã® IP アドレスを使用ã—ã¦ã„ã‚‹ã‹ã‚’常ã«ä»®æƒ³ HUB ãŒæŠŠæ¡ã™ã‚‹ãŸã‚ã«ã€è‡ªå‹•çš„ã«é€šä¿¡å†…容を分æžã—ã¦ç”Ÿæˆã•ã‚Œã‚‹ãƒ†ãƒ¼ãƒ–ルã§ã€ä»®æƒ³ HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼é©ç”¨ã‚¨ãƒ³ã‚¸ãƒ³ã«ã‚ˆã£ã¦é »ç¹ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚\nセッションåを指定ã—ã¦ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ IP アドレステーブルエントリをå–å¾—ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_IpTable_Args IpTable [session_name]
+CMD_IpTable_[session_name] 引数ã¨ã—ã¦ã‚»ãƒƒã‚·ãƒ§ãƒ³åを指定ã™ã‚‹ã¨ã€ãã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ IP アドレステーブルエントリã®ã¿ã‚’表示ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ã™ã¹ã¦ã®ã‚¨ãƒ³ãƒˆãƒªãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+
+
+# IpDelete コマンド
+CMD_IpDelete IP アドレステーブルエントリã®å‰Šé™¤
+CMD_IpDelete_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ãŒä¿æŒã—ã¦ã„ã‚‹ IP アドレステーブルデータベースをæ“作ã—ã€æŒ‡å®šã•ã‚ŒãŸ IP アドレステーブルエントリをデータベースã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚\nç¾åœ¨ã® IP アドレステーブルデータベースã®å†…容をå–å¾—ã™ã‚‹ã«ã¯ã€IpTable コマンドを使用ã—ã¦ãã ã•ã„。
+CMD_IpDelete_Args IpDelete [id]
+CMD_IpDelete_[id] 削除ã™ã‚‹ IP アドレステーブルエントリ㮠ID を指定ã—ã¾ã™ã€‚
+
+
+# SecureNatEnable コマンド
+CMD_SecureNatEnable 仮想 NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®æœ‰åŠ¹åŒ–
+CMD_SecureNatEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) を有効化ã—ã€å‹•ä½œã‚’開始ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹å‰ã«ã€å¿…ãš SecureNatHostGet コマンドã€NatGet コマンドãŠã‚ˆã³ DhcpGet コマンドã§ã€ç¾åœ¨ã®ä»®æƒ³ NAT 機能ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šå†…容を確èªã—ã¦ãã ã•ã„。\nSecureNAT 機能を有効ã«ã™ã‚‹ã¨ã€ä»®æƒ³ HUB 内ã®ä»®æƒ³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ãŠã„㦠NAT ルータ (IP マスカレード) ã‚„ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’仮想的ã«å‹•ä½œã•ã›ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\n\n[SecureNAT 機能ã«é–¢ã™ã‚‹è­¦å‘Š]\nSecureNAT 機能ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã—ã¦è©³ã—ã„知識ã®ã‚ã‚‹æ–¹å‘ã‘ã®æ©Ÿèƒ½ã§ã™ã€‚\nSecureNAT 機能を正ã—ã使用ã™ã‚‹ã¨ã€VPN を経由ã—ãŸå®‰å…¨ãªãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ãŒå®Ÿç¾ã§ãã¾ã™ã€‚ã—ã‹ã—ã€èª¤ã£ãŸæ–¹æ³•ã§ä½¿ç”¨ã™ã‚‹ã¨ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…¨ä½“ã‚’å±é™ºãªçŠ¶æ…‹ã«ã™ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã§ãªã„å ´åˆã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®è¨±å¯ã‚’å¾—ã¦ã„ãªã„å ´åˆã¯ã€SecureNAT 機能を有効ã«ã—ãªã„ã§ãã ã•ã„。SecureNAT 機能ã«é–¢ã™ã‚‹è©³ã—ã„説明ã¯ã€VPN Server ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚„オンラインドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SecureNatEnable_Args SecureNatEnable
+
+
+# SecureNatDisable コマンド
+CMD_SecureNatDisable 仮想 NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®ç„¡åŠ¹åŒ–
+CMD_SecureNatDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) を無効化ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€ä»®æƒ³ NAT 機能ã¯ç›´ã¡ã«å‹•ä½œã‚’åœæ­¢ã—ã€ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã¯ä¿æŒã—ã¦ã„ã‚‹ DHCP リースデータベースを削除ã—サービスをåœæ­¢ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SecureNatDisable_Args SecureNatDisable
+
+
+# SecureNatStatusGet コマンド
+CMD_SecureNatStatusGet 仮想 NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®å‹•ä½œçŠ¶æ³ã®å–å¾—
+CMD_SecureNatStatusGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã®å‹•ä½œçŠ¶æ³ã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SecureNatStatusGet_Args SecureNatStatusGet
+
+
+# SecureNatHostGet コマンド
+CMD_SecureNatHostGet SecureNAT 機能ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹è¨­å®šã®å–å¾—
+CMD_SecureNatHostGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®è¨­å®šé …ç›®ã®å†…ã€ä»®æƒ³ãƒ›ã‚¹ãƒˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\nSecureNAT 機能ã¯ã€ä»®æƒ³ HUB ã®å†…部ã§ã€L2 セグメント内㧠1 æžšã®ä»®æƒ³çš„㪠LAN カードをæŒã¡ã€MAC アドレス㨠IP アドレスを割り当ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã£ã¦ã€åŒä¸€ L2 セグメントã«æŽ¥ç¶šã—ã¦ã„ã‚‹ä»–ã®ãƒ›ã‚¹ãƒˆã¯ã€ã¾ã‚‹ã§å®Ÿéš›ã® IP ホストãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã«å­˜åœ¨ã—ã¦ã„ã‚‹ã‹ã®ã‚ˆã†ã« SecureNAT ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã¨é€šä¿¡ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚\n\n[SecureNAT 機能ã«é–¢ã™ã‚‹è­¦å‘Š]\nSecureNAT 機能ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã—ã¦è©³ã—ã„知識ã®ã‚ã‚‹æ–¹å‘ã‘ã®æ©Ÿèƒ½ã§ã™ã€‚\nSecureNAT 機能を正ã—ã使用ã™ã‚‹ã¨ã€VPN を経由ã—ãŸå®‰å…¨ãªãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ãŒå®Ÿç¾ã§ãã¾ã™ã€‚ã—ã‹ã—ã€èª¤ã£ãŸæ–¹æ³•ã§ä½¿ç”¨ã™ã‚‹ã¨ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…¨ä½“ã‚’å±é™ºãªçŠ¶æ…‹ã«ã™ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã§ãªã„å ´åˆã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®è¨±å¯ã‚’å¾—ã¦ã„ãªã„å ´åˆã¯ã€SecureNAT 機能を有効ã«ã—ãªã„ã§ãã ã•ã„。SecureNAT 機能ã«é–¢ã™ã‚‹è©³ã—ã„説明ã¯ã€VPN Server ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚„オンラインドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SecureNatHostGet_Args SecureNatHostGet
+CMD_SecureNatHostGet_Column_MAC MAC アドレス
+CMD_SecureNatHostGet_Column_IP IP アドレス
+CMD_SecureNatHostGet_Column_MASK サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯
+CMD_SecureNatHostGet_Column_LOG NAT ãŠã‚ˆã³ DHCP ã®å‹•ä½œã®ãƒ­ã‚°ä¿å­˜
+
+
+# SecureNatHostSet コマンド
+CMD_SecureNatHostSet SecureNAT 機能ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹è¨­å®šã®å¤‰æ›´
+CMD_SecureNatHostSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®è¨­å®šé …ç›®ã®å†…ã€ä»®æƒ³ãƒ›ã‚¹ãƒˆã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã®è¨­å®šã‚’変更ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚\nSecureNAT 機能ã¯ã€ä»®æƒ³ HUB ã®å†…部ã§ã€L2 セグメント内㧠1 æžšã®ä»®æƒ³çš„㪠LAN カードをæŒã¡ã€MAC アドレス㨠IP アドレスを割り当ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã£ã¦ã€åŒä¸€ L2 セグメントã«æŽ¥ç¶šã—ã¦ã„ã‚‹ä»–ã®ãƒ›ã‚¹ãƒˆã¯ã€ã¾ã‚‹ã§å®Ÿéš›ã® IP ホストãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã«å­˜åœ¨ã—ã¦ã„ã‚‹ã‹ã®ã‚ˆã†ã« SecureNAT ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã¨é€šä¿¡ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚\n\n[SecureNAT 機能ã«é–¢ã™ã‚‹è­¦å‘Š]\nSecureNAT 機能ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã‚„ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã—ã¦è©³ã—ã„知識ã®ã‚ã‚‹æ–¹å‘ã‘ã®æ©Ÿèƒ½ã§ã™ã€‚\nSecureNAT 機能を正ã—ã使用ã™ã‚‹ã¨ã€VPN を経由ã—ãŸå®‰å…¨ãªãƒªãƒ¢ãƒ¼ãƒˆã‚¢ã‚¯ã‚»ã‚¹ãŒå®Ÿç¾ã§ãã¾ã™ã€‚ã—ã‹ã—ã€èª¤ã£ãŸæ–¹æ³•ã§ä½¿ç”¨ã™ã‚‹ã¨ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…¨ä½“ã‚’å±é™ºãªçŠ¶æ…‹ã«ã™ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«é–¢ã™ã‚‹å分ãªçŸ¥è­˜ã‚’ãŠæŒã¡ã§ãªã„å ´åˆã‚„ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®è¨±å¯ã‚’å¾—ã¦ã„ãªã„å ´åˆã¯ã€SecureNAT 機能を有効ã«ã—ãªã„ã§ãã ã•ã„。SecureNAT 機能ã«é–¢ã™ã‚‹è©³ã—ã„説明ã¯ã€VPN Server ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚„オンラインドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SecureNatHostSet_Args SecureNatHostSet [/MAC:mac] [/IP:ip] [/MASK:mask]
+CMD_SecureNatHostSet_MAC 仮想インターフェイスã«å‰²ã‚Šå½“ã¦ã‚‹ MAC アドレスを指定ã—ã¾ã™ã€‚MAC アドレス㯠"00-AC-01-23-45-67" ã®ã‚ˆã†ã«æ–‡å­—列ã§æŒ‡å®šã—ã¾ã™ã€‚/MAC:none を指定ã™ã‚‹ã¨ã€ç¾åœ¨ã®è¨­å®šã‚’変更ã—ã¾ã›ã‚“。
+CMD_SecureNatHostSet_IP 仮想インターフェイスã«å‰²ã‚Šå½“ã¦ã‚‹ IP アドレスを指定ã—ã¾ã™ã€‚/IP:none を指定ã™ã‚‹ã¨ã€ç¾åœ¨ã®è¨­å®šã‚’変更ã—ã¾ã›ã‚“。
+CMD_SecureNatHostSet_MASK 仮想インターフェイスã«å‰²ã‚Šå½“ã¦ã‚‹ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã—ã¾ã™ã€‚/MASK:none を指定ã™ã‚‹ã¨ã€ç¾åœ¨ã®è¨­å®šã‚’変更ã—ã¾ã›ã‚“。
+CMD_SecureNatHostSet_Prompt_MAC MAC アドレス:
+CMD_SecureNatHostSet_Prompt_IP IP アドレス:
+CMD_SecureNatHostSet_Prompt_MASK サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯:
+
+
+# NatGet コマンド
+CMD_NatGet SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã®è¨­å®šã®å–å¾—
+CMD_NatGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®è¨­å®šé …ç›®ã®å†…ã€ä»®æƒ³ NAT ã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_NatGet_Args NatGet
+CMD_NatGet_Column_USE 仮想 NAT 機能を使用ã™ã‚‹
+CMD_NetGet_Column_MTU MTU 値
+CMD_NatGet_Column_TCP TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ (秒)
+CMD_NatGet_Column_UDP UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ (秒)
+
+
+# NatEnable コマンド
+CMD_NatEnable SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã®æœ‰åŠ¹åŒ–
+CMD_NatEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT 機能を有効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’用ã„ã¦ä»®æƒ³ NAT 機能を有効ã«ã—ã¦ã‚‚ã€SecureNAT 機能ãŒå‹•ä½œã—ã¦ã„ãªã„å ´åˆã¯ã€ä»®æƒ³ NAT ã¯å‹•ä½œã—ã¾ã›ã‚“。SecureNAT 機能ã®å‹•ä½œã‚’開始ã™ã‚‹ã«ã¯ã€SecureNatEnable コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_NatEnable_Args NatEnable
+
+
+# NatDisable コマンド
+CMD_NatDisable SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã®ç„¡åŠ¹åŒ–
+CMD_NatDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT 機能を無効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_NatDisable_Args NatDisable
+
+
+# NatSet コマンド
+CMD_NatSet SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã®è¨­å®šã®å¤‰æ›´
+CMD_NatSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã®ä»®æƒ³ NAT ã®è¨­å®šã‚’変更ã—ã¾ã™ã€‚仮想 NAT ã®è¨­å®šã«ã¯ã€MTU 値ã€TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆæ™‚é–“ã€UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆæ™‚é–“ãŒå«ã¾ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_NatSet_Args NatSet [/MTU:mtu] [/TCPTIMEOUT:tcp_timeout] [/UDPTIMEOUT:udp_timeout] [/LOG:yes|no]
+CMD_NatSet_MTU MTU (最大転é€å¯èƒ½ãƒ¦ãƒ‹ãƒƒãƒˆã‚µã‚¤ã‚º) ã‚’ã€ãƒã‚¤ãƒˆæ•°å˜ä½ã®æ•´æ•°ã§è¨­å®šã—ã¾ã™ã€‚ã“ã®å€¤ã¯ã€ä»®æƒ³ NAT ãŒé€å‡ºã™ã‚‹ Ethernet フレーム㮠MAC ヘッダを除ã„ãŸãƒšã‚¤ãƒ­ãƒ¼ãƒ‰ã®æœ€å¤§é•·ã§ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã¯ 1500 ãƒã‚¤ãƒˆã§ã™ã€‚
+CMD_NatSet_TCPTIMEOUT 仮想 NAT ãŒä¸­ç¶™ã™ã‚‹ TCP セッションã§ã€ä½•ç§’間無通信状態ãŒç¶šã‘ã°ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—セッションを破棄ã™ã‚‹ã‹ã‚’設定ã—ã¾ã™ã€‚
+CMD_NatSet_UDPTIMEOUT 仮想 NAT ãŒä¸­ç¶™ã™ã‚‹ UDP セッションã§ã€ä½•ç§’間無通信状態ãŒç¶šã‘ã°ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—セッションを破棄ã™ã‚‹ã‹ã‚’設定ã—ã¾ã™ã€‚
+CMD_NatSet_LOG 仮想 NAT ã®å‹•ä½œã‚’ã€ä»®æƒ³ HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã«ä¿å­˜ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚"yes" を指定ã™ã‚‹ã¨ä¿å­˜ã•ã‚Œã€"no" を指定ã™ã‚‹ã¨ä¿å­˜ã—ã¾ã›ã‚“。
+CMD_NatSet_Prompt_MTU MTU 値:
+CMD_NatSet_Prompt_TCPTIMEOUT TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆç§’æ•°:
+CMD_NatSet_Prompt_UDPTIMEOUT UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆç§’æ•°:
+CMD_NatSet_Prompt_LOG ログã®ä¿å­˜ (yes / no):
+CMD_NatSet_Eval_MTU MTU 値㯠%d ã‹ã‚‰ %d ã®é–“ã§è¨­å®šã—ã¦ãã ã•ã„。
+CMD_NatSet_Eval_TCP TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆç§’数㯠%d ã‹ã‚‰ %d ã®é–“ã§è¨­å®šã—ã¦ãã ã•ã„。
+CMD_NatSet_Eval_UDP UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆç§’数㯠%d ã‹ã‚‰ %d ã®é–“ã§è¨­å®šã—ã¦ãã ã•ã„。
+
+
+# NatTable コマンド
+CMD_NatTable SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ†ãƒ¼ãƒ–ルã®å–å¾—
+CMD_NatTable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ä»®æƒ³ NAT 機能ãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ä»®æƒ³ NAT を経由ã—ã¦ç¾åœ¨é€šä¿¡ä¸­ã® TCPã€ãŠã‚ˆã³ UDP ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ†ãƒ¼ãƒ–ル (NAT テーブル) ã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_NatTable_Args NatTable
+
+
+# DhcpGet コマンド
+CMD_DhcpGet SecureNAT 機能ã®ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã®å–å¾—
+CMD_DhcpGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ NAT ãŠã‚ˆã³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ (SecureNAT 機能) ã®è¨­å®šé …ç›®ã®å†…ã€ä»®æƒ³ DHCP サーãƒãƒ¼ã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DhcpGet_Args DhcpGet
+CMD_DhcpGet_Column_Log NAT ãŠã‚ˆã³ DHCP 動作ã®ãƒ­ã‚°è¨˜éŒ²
+CMD_DhcpGet_Column_USE 仮想 DHCP 機能を使用ã™ã‚‹
+CMD_DhcpGet_Column_IP1 é…布アドレス帯ã®é–‹å§‹
+CMD_DhcpGet_Column_IP2 é…布アドレス帯ã®çµ‚了
+CMD_DhcpGet_Column_MASK サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯
+CMD_DhcpGet_Column_LEASE ãƒªãƒ¼ã‚¹æœŸé™ (秒)
+CMD_DhcpGet_Column_GW デフォルトゲートウェイアドレス
+CMD_DhcpGet_Column_DNS DNS サーãƒãƒ¼ アドレス 1
+CMD_DhcpGet_Column_DNS2 DNS サーãƒãƒ¼ アドレス 2
+CMD_DhcpGet_Column_DOMAIN ドメインå
+
+
+# DhcpEnable コマンド
+CMD_DhcpEnable SecureNAT 機能ã®ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®æœ‰åŠ¹åŒ–
+CMD_DhcpEnable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’用ã„ã¦ä»®æƒ³ DHCP 機能を有効ã«ã—ã¦ã‚‚ã€SecureNAT 機能ãŒå‹•ä½œã—ã¦ã„ãªã„å ´åˆã¯ã€ä»®æƒ³ DHCP サーãƒãƒ¼ã¯å‹•ä½œã—ã¾ã›ã‚“。SecureNAT 機能ã®å‹•ä½œã‚’開始ã™ã‚‹ã«ã¯ã€SecureNatEnable コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DhcpEnable_Args DhcpEnable
+
+
+# DhcpDisable コマンド
+CMD_DhcpDisable SecureNAT 機能ã®ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®ç„¡åŠ¹åŒ–
+CMD_DhcpDisable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ã€ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’無効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DhcpDisable_Args DhcpDisable
+
+
+# DhcpSet コマンド
+CMD_DhcpSet SecureNAT 機能ã®ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã®å¤‰æ›´
+CMD_DhcpSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã®ã€ä»®æƒ³ DHCP サーãƒãƒ¼ã®è¨­å®šã‚’変更ã—ã¾ã™ã€‚仮想 DHCP サーãƒãƒ¼ã®è¨­å®šã«ã¯ã€é…布 IP アドレス帯ã€ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã€ãƒªãƒ¼ã‚¹æœŸé™ã€ãŠã‚ˆã³ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«å‰²ã‚Šå½“ã¦ã‚‹ã‚ªãƒ—ション値ãŒå«ã¾ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DhcpSet_Args DhcpSet [/START:start_ip] [/END:end_ip] [/MASK:subnetmask] [/EXPIRE:sec] [/GW:gwip] [/DNS:dns] [/DNS2:dns2] [/DOMAIN:domain] [/LOG:yes|no]
+CMD_DhcpSet_START クライアントã«å¯¾ã—ã¦é…布ã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹å¸¯ã®é–‹å§‹ç‚¹ã‚’指定ã—ã¾ã™ã€‚(例: 192.168.30.10)
+CMD_DhcpSet_END クライアントã«å¯¾ã—ã¦é…布ã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹å¸¯ã®çµ‚了点を指定ã—ã¾ã™ã€‚(例: 192.168.30.200)
+CMD_DhcpSet_MASK クライアントã«å¯¾ã—ã¦æŒ‡å®šã™ã‚‹ã‚µãƒ–ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ã‚’指定ã—ã¾ã™ã€‚(例: 255.255.255.0)
+CMD_DhcpSet_EXPIRE クライアントã«å¯¾ã—㦠IP アドレスをリースã™ã‚‹éš›ã®æœ‰åŠ¹æœŸé™ã‚’秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_DhcpSet_GW クライアントã«å¯¾ã—ã¦é€šçŸ¥ã™ã‚‹ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤ã® IP アドレスを指定ã—ã¾ã™ã€‚SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã¨å…±ã«æœ‰åŠ¹ã«ã—ã¦ä½¿ç”¨ã™ã‚‹å ´åˆã¯ã€SecureNAT ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã® IP アドレスを指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚0 ã¾ãŸã¯ none を指定ã™ã‚‹ã¨ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤ã‚’クライアントã«å¯¾ã—ã¦é€šçŸ¥ã—ã¾ã›ã‚“。
+CMD_DhcpSet_DNS クライアントã«å¯¾ã—ã¦é€šçŸ¥ã™ã‚‹ DNS サーãƒãƒ¼ (プライマリ) ã® IP アドレスを指定ã—ã¾ã™ã€‚SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã¨å…±ã«æœ‰åŠ¹ã«ã—ã¦ä½¿ç”¨ã™ã‚‹å ´åˆã¯ã€SecureNAT ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã® IP アドレスを指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚0 ã¾ãŸã¯ none を指定ã™ã‚‹ã¨ã€DNS サーãƒãƒ¼ アドレスをクライアントã«å¯¾ã—ã¦é€šçŸ¥ã—ã¾ã›ã‚“。
+CMD_DhcpSet_DNS2 クライアントã«å¯¾ã—ã¦é€šçŸ¥ã™ã‚‹ DNS サーãƒãƒ¼ (セカンダリ) ã® IP アドレスを指定ã—ã¾ã™ã€‚SecureNAT 機能ã®ä»®æƒ³ NAT 機能ã¨å…±ã«æœ‰åŠ¹ã«ã—ã¦ä½¿ç”¨ã™ã‚‹å ´åˆã¯ã€SecureNAT ã®ä»®æƒ³ãƒ›ã‚¹ãƒˆã® IP アドレスを指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚0 ã¾ãŸã¯ none を指定ã™ã‚‹ã¨ã€DNS サーãƒãƒ¼ アドレスをクライアントã«å¯¾ã—ã¦é€šçŸ¥ã—ã¾ã›ã‚“。
+CMD_DhcpSet_DOMAIN クライアントã«å¯¾ã—ã¦é€šçŸ¥ã™ã‚‹ãƒ‰ãƒ¡ã‚¤ãƒ³åを指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã¨ã€ãƒ‰ãƒ¡ã‚¤ãƒ³åをクライアントã«å¯¾ã—ã¦é€šçŸ¥ã—ã¾ã›ã‚“。
+CMD_DhcpSet_LOG 仮想 DHCP サーãƒãƒ¼ã®å‹•ä½œã‚’仮想 HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã«ä¿å­˜ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚"yes" を指定ã™ã‚‹ã¨ä¿å­˜ã—ã¾ã™ã€‚ã“ã®å€¤ã¯ã€ä»®æƒ³ NAT 機能ã®ãƒ­ã‚°ä¿å­˜è¨­å®šã¨é€£å‹•ã—ã¦ã„ã¾ã™ã€‚
+CMD_DhcpSet_Prompt_START é…布ã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹å¸¯ã®é–‹å§‹ç‚¹:
+CMD_DhcpSet_Prompt_END é…布ã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹å¸¯ã®çµ‚了点:
+CMD_DhcpSet_Prompt_MASK サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯:
+CMD_DhcpSet_Prompt_EXPIRE ãƒªãƒ¼ã‚¹æœŸé™ (秒):
+CMD_DhcpSet_Prompt_GW デフォルトゲートウェイ (未設定å¯):
+CMD_DhcpSet_Prompt_DNS DNS サーãƒãƒ¼ 1 (未設定å¯):
+CMD_DhcpSet_Prompt_DNS2 DNS サーãƒãƒ¼ 2 (未設定å¯):
+CMD_DhcpSet_Prompt_DOMAIN ドメインå:
+
+
+# DhcpTable コマンド
+CMD_DhcpTable SecureNAT 機能ã®ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ã®ãƒªãƒ¼ã‚¹ãƒ†ãƒ¼ãƒ–ルã®å–å¾—
+CMD_DhcpTable_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB 内ã§ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½ãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã€ä»®æƒ³ DHCP サーãƒãƒ¼ãŒä¿æŒã—ã¦ã„るクライアントã«å¯¾ã—ã¦å‰²ã‚Šå½“ã¦ãŸ IP アドレスã®ãƒªãƒ¼ã‚¹ãƒ†ãƒ¼ãƒ–ルをå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DhcpTable_Args DhcpTable
+
+
+# AdminOptionList コマンド
+CMD_AdminOptionList 仮想 HUB 管ç†ã‚ªãƒ—ションã®ä¸€è¦§ã®å–å¾—
+CMD_AdminOptionList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る仮想 HUB 管ç†ã‚ªãƒ—ションã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\n仮想 HUB 管ç†ã‚ªãƒ—ションã¯ã€VPN Server ã®ç®¡ç†è€…ãŒå„仮想 HUB ã®ç®¡ç†è€…ã«ä»®æƒ³ HUB ã®ç®¡ç†ã‚’委任ã—ã¦ã„ã‚‹å ´åˆã«ã€è¨­å®šç¯„囲を制é™ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚\n仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを追加・編集ãŠã‚ˆã³å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã¯ã€ã“ã® VPN Server 全体ã®ç®¡ç†æ¨©é™ã‚’æŒã£ãŸç®¡ç†è€…ã®ã¿ã§ã™ã€‚仮想 HUB ã®ç®¡ç†è€…ã¯ã€ç®¡ç†ã‚ªãƒ—ションを表示ã§ãã¾ã™ãŒã€å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。\nãŸã ã—ã€allow_hub_admin_change_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã§ã‚‚管ç†ã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AdminOptionList_Args AdminOptionList
+
+
+# AdminOptionSet コマンド
+CMD_AdminOptionSet 仮想 HUB 管ç†ã‚ªãƒ—ションã®å€¤ã®è¨­å®š
+CMD_AdminOptionSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る仮想 HUB 管ç†ã‚ªãƒ—ションã®å€¤ã‚’変更ã—ã¾ã™ã€‚\n仮想 HUB 管ç†ã‚ªãƒ—ションã¯ã€VPN Server ã®ç®¡ç†è€…ãŒå„仮想 HUB ã®ç®¡ç†è€…ã«ä»®æƒ³ HUB ã®ç®¡ç†ã‚’委任ã—ã¦ã„ã‚‹å ´åˆã«ã€è¨­å®šç¯„囲を制é™ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚\n仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを追加・編集ãŠã‚ˆã³å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã¯ã€ã“ã® VPN Server 全体ã®ç®¡ç†æ¨©é™ã‚’æŒã£ãŸç®¡ç†è€…ã®ã¿ã§ã™ã€‚仮想 HUB ã®ç®¡ç†è€…ã¯ã€ç®¡ç†ã‚ªãƒ—ションを表示ã§ãã¾ã™ãŒã€å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。\nãŸã ã—ã€allow_hub_admin_change_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã§ã‚‚管ç†ã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AdminOptionSet_Args AdminOptionSet [name] [/VALUE:value]
+CMD_AdminOptionSet_[name] 値を変更ã™ã‚‹ç®¡ç†ã‚ªãƒ—ションåを指定ã—ã¾ã™ã€‚AdminOptionList コマンドã§åå‰ã®ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã™ã€‚
+CMD_AdminOptionSet_VALUE 設定ã™ã‚‹å€¤ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AdminOptionSet_Prompt_name 値を変更ã™ã‚‹ç®¡ç†ã‚ªãƒ—ションå:
+CMD_AdminOptionSet_Prompt_VALUE 設定ã™ã‚‹å€¤ (æ•´æ•°):
+
+
+# ExtOptionList コマンド
+CMD_ExtOptionList 仮想 HUB 拡張オプションã®ä¸€è¦§ã®å–å¾—
+CMD_ExtOptionList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る仮想 HUB 拡張オプションã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\n仮想 HUB 拡張オプションã¯ã€ä»®æƒ³ HUB ã«é–¢ã™ã‚‹ã‚ˆã‚Šè©³ç´°ãªè¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãる機能ã§ã™ã€‚\n仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを追加・編集ãŠã‚ˆã³å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã¯ã€ã“ã® VPN Server 全体ã®ç®¡ç†æ¨©é™ã‚’æŒã£ãŸç®¡ç†è€…ãŠã‚ˆã³ä»®æƒ³ HUB ã®ç®¡ç†è€…ã§ã™ã€‚\nãŸã ã—ã€ä»®æƒ³ HUB 管ç†ã‚ªãƒ—ション㮠deny_hub_admin_change_ext_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã€æ‹¡å¼µã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ExtOptionList_Args ExtOptionList
+
+
+# ExtOptionSet コマンド
+CMD_ExtOptionSet 仮想 HUB 管ç†ã‚ªãƒ—ションã®å€¤ã®è¨­å®š
+CMD_ExtOptionSet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る仮想 HUB 拡張オプションã®å€¤ã‚’設定ã—ã¾ã™ã€‚\n仮想 HUB 拡張オプションã¯ã€ä»®æƒ³ HUB ã«é–¢ã™ã‚‹ã‚ˆã‚Šè©³ç´°ãªè¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãる機能ã§ã™ã€‚\n仮想 HUB ã®ç®¡ç†ã‚ªãƒ—ションを追加・編集ãŠã‚ˆã³å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã¯ã€ã“ã® VPN Server 全体ã®ç®¡ç†æ¨©é™ã‚’æŒã£ãŸç®¡ç†è€…ãŠã‚ˆã³ä»®æƒ³ HUB ã®ç®¡ç†è€…ã§ã™ã€‚\nãŸã ã—ã€ä»®æƒ³ HUB 管ç†ã‚ªãƒ—ション㮠deny_hub_admin_change_ext_option ㌠1 ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ HUB ã®ç®¡ç†è€…ã¯ã€æ‹¡å¼µã‚ªãƒ—ションを編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿å†…ã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¡ãƒ³ãƒã‚µãƒ¼ãƒãƒ¼ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ExtOptionSet_Args ExtOptionSet [name] [/VALUE:value]
+CMD_ExtOptionSet_[name] 値を変更ã™ã‚‹æ‹¡å¼µã‚ªãƒ—ションåを指定ã—ã¾ã™ã€‚ExtOptionList コマンドã§åå‰ã®ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã™ã€‚
+CMD_ExtOptionSet_VALUE 設定ã™ã‚‹å€¤ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚
+CMD_ExtOptionSet_Prompt_name 値を変更ã™ã‚‹æ‹¡å¼µã‚ªãƒ—ションå:
+CMD_ExtOptionSet_Prompt_VALUE 設定ã™ã‚‹å€¤ (æ•´æ•°):
+
+
+# CrlList コマンド
+CMD_CrlList 無効ãªè¨¼æ˜Žæ›¸ãƒªã‚¹ãƒˆã®ä¸€è¦§ã®å–å¾—
+CMD_CrlList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ã€ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ãƒªã‚¹ãƒˆã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\n無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«è¨¼æ˜Žæ›¸ã‚’登録ã™ã‚‹ã¨ã€ãã®è¨¼æ˜Žæ›¸ã‚’æ示ã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ã€ã“ã®ä»®æƒ³ HUB ã«è¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã§ããªããªã‚Šã¾ã™ã€‚\n通常ã€ã“ã®æ©Ÿèƒ½ã¯ç§˜å¯†éµãŒæ¼æ´©ã—ãŸã‚Šã€è¨¼æ˜Žæ›¸ã‚’ä¿æœ‰ã™ã‚‹è€…ã®æ¨©é™ãŒå¤±åŠ¹ã—ãŸå ´åˆã«ã€å½“該証明書を無効ã¨ã—ã¦ä»®æƒ³ HUB ã«ç™»éŒ²ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãã®è¨¼æ˜Žæ›¸ã‚’用ã„㦠VPN Client ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã‚’æ‹’å¦ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CrlList_Args CrlList
+
+
+# CrlAdd コマンド
+CMD_CrlAdd 無効ãªè¨¼æ˜Žæ›¸ã®è¿½åŠ 
+CMD_CrlAdd_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る無効ãªè¨¼æ˜Žæ›¸ãƒªã‚¹ãƒˆã«ã€æ–°ã—ã„無効ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ã‚’追加ã—ã¾ã™ã€‚\n無効ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«ç™»éŒ²ã™ã‚‹å†…容をã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®ãƒ‘ラメータã§æŒ‡å®šã—ã¾ã™ã€‚仮想 HUB ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¨¼æ˜Žæ›¸èªè¨¼ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ããŸã¨ãã€ãã®è¨¼æ˜Žæ›¸ãŒç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®ä¸€è¦§ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 1 ã¤ä»¥ä¸Šã®å†…容ã«ä¸€è‡´ã™ã‚‹å ´åˆã«ã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æŽ¥ç¶šã‚’æ‹’å¦ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§æŒ‡å®šã—ãŸãƒ‘ラメータã§å®šç¾©ã•ã‚Œã‚‹ã™ã¹ã¦ã®æ¡ä»¶ã«ä¸€è‡´ã—ãŸè¨¼æ˜Žæ›¸ãŒã€ç„¡åŠ¹ã¨ã—ã¦åˆ¤å®šã•ã‚Œã¾ã™ã€‚\n設定ã§ãã‚‹é …ç›®ã¯ã€[åå‰ (CN)]ã€[所属機関 (O)]ã€[組織å˜ä½ (OU)]ã€[国 (C)]ã€[都é“府県 (ST)]ã€[ローカル (L)]ã€[ã‚·ãƒªã‚¢ãƒ«ç•ªå· (16進数)]ã€[MD5 ダイジェスト値 (16進数, 128 bit)]ã€[SHA-1 ダイジェスト値 (16進数, 160 bit)] ã§ã™ã€‚ダイジェスト値 (ãƒãƒƒã‚·ãƒ¥å€¤) ã®æŒ‡å®šã¯ã€è¨¼æ˜Žæ›¸ã‚’事実上一æ„ã«æŒ‡å®šã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚通常ã€MD5 ã¾ãŸã¯ SHA-1 ã®ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆå€¤ã‚’入力ã™ã‚‹å ´åˆã¯ã€ãã®ä»–ã®é …目を入力ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CrlAdd_Args CrlAdd [/SERIAL:serial] [/MD5:md5] [/SHA1:sha1] [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l]
+CMD_CrlAdd_SERIAL æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå· (16進数) を設定ã™ã‚‹å ´åˆã¯ã“ã®ãƒ‘ラメータã§å€¤ã‚’指定ã—ã¾ã™ã€‚
+CMD_CrlAdd_MD5 æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã® MD5 ダイジェスト値 (16進数, 128 bit) を設定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’指定ã—ã¾ã™ã€‚16 進数㧠32 文字 (16 Bytes) ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚
+CMD_CrlAdd_SHA1 æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã® SHA1 ダイジェスト値 (16進数, 160 bit) を設定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’指定ã—ã¾ã™ã€‚16 進数㧠40 文字 (20 Bytes) ã®ãƒ‘ラメータを指定ã—ãªã„å ´åˆã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚
+CMD_CrlAdd_CN æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®åå‰ (CN) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+CMD_CrlAdd_O æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®æ‰€å±žæ©Ÿé–¢ (O) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+CMD_CrlAdd_OU æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®çµ„ç¹”å˜ä½ (OU) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+CMD_CrlAdd_C æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®å›½ (C) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+CMD_CrlAdd_ST æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®éƒ½é“府県 (ST) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+CMD_CrlAdd_L æ¡ä»¶ã¨ã—ã¦è¨¼æ˜Žæ›¸ã®ãƒ­ãƒ¼ã‚«ãƒ« (L) を指定ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒ‘ラメータã§å€¤ã‚’設定ã—ã¾ã™ã€‚
+
+
+# CrlDel コマンド
+CMD_CrlDel 無効ãªè¨¼æ˜Žæ›¸ã®å‰Šé™¤
+CMD_CrlDel_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る無効ãªè¨¼æ˜Žæ›¸ã®ãƒªã‚¹ãƒˆã‹ã‚‰ã€ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ã‚’指定ã—ã¦å‰Šé™¤ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„る無効ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ä¸€è¦§ã¯ã€CrlList コマンドã§å–å¾—ã§ãã¾ã™\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CrlDel_Args CrlDel [id]
+CMD_CrlDel_[id] 削除ã™ã‚‹ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ã® ID を指定ã—ã¾ã™ã€‚
+CMD_CrlDel_Prompt_ID 削除ã™ã‚‹ ID:
+
+
+# CrlGet コマンド
+CMD_CrlGet 無効ãªè¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_CrlGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„る無効ãªè¨¼æ˜Žæ›¸ã®ãƒªã‚¹ãƒˆã‹ã‚‰ã€ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ã‚’指定ã—ã¦ã€ãã®å®šç¾©å†…容をå–å¾—ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„る無効ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ä¸€è¦§ã¯ã€CrlList コマンドã§å–å¾—ã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_CrlGet_Args CrlGet [id]
+CMD_CrlGet_[id] å–å¾—ã™ã‚‹ç„¡åŠ¹ãªè¨¼æ˜Žæ›¸ã®å®šç¾©ã® ID を指定ã—ã¾ã™ã€‚
+CMD_CrlGet_Prompt_ID å–å¾—ã™ã‚‹ ID:
+CMD_CrlGet_CN åå‰ (CN)
+CMD_CrlGet_O 所属機関 (O)
+CMD_CrlGet_OU 組織å˜ä½ (OU)
+CMD_CrlGet_C 国 (C)
+CMD_CrlGet_ST 都é“府県 (ST)
+CMD_CrlGet_L ローカル (L)
+CMD_CrlGet_SERI ã‚·ãƒªã‚¢ãƒ«ç•ªå· (16進数)
+CMD_CrlGet_MD5_HASH MD5 ダイジェスト値 (16進数, 128 bit)
+CMD_CrlGet_SHA1_HASH SHA-1 ダイジェスト値 (16進数, 160 bit)
+
+
+# AcList コマンド
+CMD_AcList 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã®å–å¾—
+CMD_AcList_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚\nクライアントコンピュータã®æŽ¥ç¶šå…ƒ IP アドレスã«ã‚ˆã£ã¦ã€ã“ã®ä»®æƒ³ HUB ã¸ã® VPN 接続をã€è¨±å¯ã¾ãŸã¯æ‹’å¦ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚複数ã®ãƒ«ãƒ¼ãƒ«ã‚’定義ã™ã‚‹ã“ã¨ãŒã§ãã€å„ルールã«ã¯å„ªå…ˆé †ä½ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚優先順ä½ãŒé«˜ã„ルールã‹ã‚‰æ¤œç´¢ã‚’è¡Œã„ã€æœ€åˆã« IP アドレスãŒä¸€è‡´ã—ãŸãƒ«ãƒ¼ãƒ«ã®å‹•ä½œã«åŸºã¥ã„ã¦ã€ãã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’ã€è¨±å¯ã¾ãŸã¯æ‹’å¦ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AcList_Args AcList
+
+
+# AcAdd コマンド
+CMD_AcAdd 接続元 IP 制é™ãƒªã‚¹ãƒˆã«ãƒ«ãƒ¼ãƒ«ã‚’追加 (IPv4)
+CMD_AcAdd_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã«æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚\nã“ã“ã§è¨­å®šã—ãŸé …ç›®ã¯ã€VPN Client ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ã€ãã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’許å¯ã™ã‚‹ã‹æ‹’å¦ã™ã‚‹ã‹ã‚’決定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nルール項目ã®å†…容ã¨ã—ã¦ã€ãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã® IP アドレスã€ã¾ãŸã¯ IP アドレスã¨ãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚IP アドレスã®ã¿ã‚’指定ã™ã‚‹ã¨ã€å˜ä¸€ã®æŒ‡å®šã—ãŸã‚³ãƒ³ãƒ”ュータã®ã¿ãŒãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ãŒã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹ã¨ã€ãã®ã‚µãƒ–ãƒãƒƒãƒˆã®ç¯„囲内ã®ã™ã¹ã¦ã®ã‚³ãƒ³ãƒ”ュータãŒãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚\nルールã«ã¯å„ªå…ˆé †ä½ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚優先順ä½ã¯ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã€å€¤ãŒå°ã•ã„ã»ã©å„ªå…ˆé †ä½ã¯é«˜ã評価ã•ã‚Œã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€AcList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AcAdd_Args AcAdd [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd_[allow|deny] ルールã«ä¸€è‡´ã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’許å¯ã™ã‚‹ ("allow") ã‹æ‹’å¦ã™ã‚‹ ("deny") ã‹ã‚’設定ã—ã¾ã™ã€‚
+CMD_AcAdd_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚値ãŒå°ã•ã„ã»ã©å„ªå…ˆé †ä½ã¯é«˜ã評価ã•ã‚Œã¾ã™ã€‚
+CMD_AcAdd_IP [IP アドレス/マスク] ã®å½¢å¼ã§ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ IPv4 アドレスã®ç¯„囲を指定ã—ã¾ã™ã€‚IPv4 アドレス㯠192.168.0.1 ã®ã‚ˆã†ã«ã€10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠255.255.255.0 ã®ã‚ˆã†ã« 10 進数をドットã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€24 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã—ã¾ã™ã€‚å˜ä¸€ã® IPv4 ホストを指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ 255.255.255.255 ã¾ãŸã¯ 32 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AcAdd_Prompt_AD allow ã¾ãŸã¯ deny:
+CMD_AcAdd_Prompt_PRIORITY 優先順ä½:
+CMD_AcAdd_Prompt_IP IPv4 アドレス/マスク:
+CMD_AcAdd_Eval_PRIORITY 優先順ä½ã¯ 1 以上ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+# AcAdd6 コマンド
+CMD_AcAdd6 接続元 IP 制é™ãƒªã‚¹ãƒˆã«ãƒ«ãƒ¼ãƒ«ã‚’追加 (IPv6)
+CMD_AcAdd6_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã«æ–°ã—ã„ルールを追加ã—ã¾ã™ã€‚\nã“ã“ã§è¨­å®šã—ãŸé …ç›®ã¯ã€VPN Client ãŒä»®æƒ³ HUB ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã«ã€ãã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’許å¯ã™ã‚‹ã‹æ‹’å¦ã™ã‚‹ã‹ã‚’決定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\nルール項目ã®å†…容ã¨ã—ã¦ã€ãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã® IP アドレスã€ã¾ãŸã¯ IP アドレスã¨ãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚IP アドレスã®ã¿ã‚’指定ã™ã‚‹ã¨ã€å˜ä¸€ã®æŒ‡å®šã—ãŸã‚³ãƒ³ãƒ”ュータã®ã¿ãŒãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ãŒã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒžã‚¹ã‚¯ã‚’指定ã™ã‚‹ã¨ã€ãã®ã‚µãƒ–ãƒãƒƒãƒˆã®ç¯„囲内ã®ã™ã¹ã¦ã®ã‚³ãƒ³ãƒ”ュータãŒãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚\nルールã«ã¯å„ªå…ˆé †ä½ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚優先順ä½ã¯ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã€å€¤ãŒå°ã•ã„ã»ã©å„ªå…ˆé †ä½ã¯é«˜ã評価ã•ã‚Œã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€AcList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AcAdd6_Args AcAdd6 [allow|deny] [/PRIORITY:priority] [/IP:ip/mask]
+CMD_AcAdd6_[allow|deny] ルールã«ä¸€è‡´ã—ãŸã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’許å¯ã™ã‚‹ ("allow") ã‹æ‹’å¦ã™ã‚‹ ("deny") ã‹ã‚’設定ã—ã¾ã™ã€‚
+CMD_AcAdd6_PRIORITY ルールã®å„ªå…ˆé †ä½ã‚’ 1 以上ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚値ãŒå°ã•ã„ã»ã©å„ªå…ˆé †ä½ã¯é«˜ã評価ã•ã‚Œã¾ã™ã€‚
+CMD_AcAdd6_IP [IP アドレス/マスク] ã®å½¢å¼ã§ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ IPv6 アドレスã®ç¯„囲を指定ã—ã¾ã™ã€‚IPv6 アドレス㯠2001:200:0:1:: ã®ã‚ˆã†ã« 16 進数をコロンã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚マスク㯠ffff:ffff:ffff:ffff:: ã®ã‚ˆã†ã« IPv6 å½¢å¼ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã™ã‚‹ã‹ã€64 ã®ã‚ˆã†ã«å…ˆé ­ã‹ã‚‰ã®ãƒ“ット長を 10 進数ã§æŒ‡å®šã—ã¾ã™ã€‚å˜ä¸€ã® IPv6 ホストを指定ã™ã‚‹ã«ã¯ã€ãƒžã‚¹ã‚¯ã‚’ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ã¾ãŸã¯ 128 ã¨ã—ã¦æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AcAdd6_Prompt_AD allow ã¾ãŸã¯ deny:
+CMD_AcAdd6_Prompt_PRIORITY 優先順ä½:
+CMD_AcAdd6_Prompt_IP IPv6 アドレス/サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯:
+CMD_AcAdd6_Eval_PRIORITY 優先順ä½ã¯ 1 以上ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+# AcDel コマンド
+CMD_AcDel 接続元 IP 制é™ãƒªã‚¹ãƒˆå†…ã®ãƒ«ãƒ¼ãƒ«ã®å‰Šé™¤
+CMD_AcDel_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„る仮想 HUB ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ã‚’削除ã—ã¾ã™ã€‚\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ 接続元 IP 制é™ãƒªã‚¹ãƒˆã®ãƒ«ãƒ¼ãƒ«ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€AcList コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_AcDel_Args AcDel [id]
+CMD_AcDel_[id] 削除ã™ã‚‹æŽ¥ç¶šå…ƒ IP 制é™ãƒªã‚¹ãƒˆå†…ã®ãƒ«ãƒ¼ãƒ«ã® ID を指定ã—ã¾ã™ã€‚
+CMD_AcDel_Prompt_ID 削除ã™ã‚‹ãƒ«ãƒ¼ãƒ«ã® ID:
+
+
+# LicenseAdd コマンド
+CMD_LicenseAdd æ–°ã—ã„ライセンスキーã®ç™»éŒ²
+CMD_LicenseAdd_Help SoftEther VPN Server ã«ã€æ–°ã—ã„ライセンスキーを登録ã—ã¾ã™ã€‚\nSoftEther VPN Server を使用ã™ã‚‹ã«ã¯ã€æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’å–å¾—ã—ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’登録ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ライセンスキーã¯ã€36 æ¡ã®è‹±æ•°å­—ãŠã‚ˆã³ãƒã‚¤ãƒ•ãƒ³ ( '-' ) ã§æ§‹æˆã•ã‚Œã¦ã„ã‚‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ‰€æœ‰ã‚’証明ã™ã‚‹ã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰ã§ã™ã€‚\nライセンスキーã¯ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¨å…±ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã‚’å—ã‘å–ã£ãŸå ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è¨¼æ›¸ã«å°åˆ·ã•ã‚Œã¦ã„ã¾ã™ã€‚本ソフトウェアã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’オンラインã§è³¼å…¥ã—ãŸå ´åˆã¯ã€è³¼å…¥æ™‚ã® Web サイトã®ç”»é¢ã‚„メールãªã©ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€ãã®ä»–ã®æ–¹æ³•ã§ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ä¸æ˜Žãªå ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®è³¼å…¥å…ƒã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。\n\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンスã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€LicenseList コマンドを使用ã—ã¾ã™ã€‚\nç¾åœ¨ã® VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹çŠ¶æ…‹ã‚’表示ã™ã‚‹ã«ã¯ã€LicenseStatus コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_LicenseAdd_Args LicenseAdd [key]
+CMD_LicenseAdd_[key] 登録ã™ã‚‹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’指定ã—ã¾ã™ã€‚36 æ¡ã®è‹±æ•°å­—ã‚’ã€6 æ¡ã”ã¨ã«ãƒã‚¤ãƒ•ãƒ³ã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_LicenseAdd_Prompt_Key ライセンスキー:
+
+
+# LicenseDel コマンド
+CMD_LicenseDel 登録ã•ã‚Œã¦ã„るライセンスã®å‰Šé™¤
+CMD_LicenseDel_Help SoftEther VPN Server ã«ã€ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンス一覧ã‹ã‚‰ã€æŒ‡å®šã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’削除ã—ã¾ã™ã€‚\n\nç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンスã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€LicenseList コマンドを使用ã—ã¾ã™ã€‚\nç¾åœ¨ã® VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹çŠ¶æ…‹ã‚’表示ã™ã‚‹ã«ã¯ã€LicenseStatus コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_LicenseDel_Args LicenseDel [id]
+CMD_LicenseDel_[id] 削除ã™ã‚‹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_LicenseDel_Prompt_ID 削除ã™ã‚‹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ç•ªå·:
+
+
+# LicenseList コマンド
+CMD_LicenseList 登録ã•ã‚Œã¦ã„るライセンス一覧ã®å–å¾—
+CMD_LicenseList_Help SoftEther VPN Server ã«ã€ç¾åœ¨ç™»éŒ²ã•ã‚Œã¦ã„るライセンスã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ç¨®é¡žåã€çŠ¶æ…‹ã€æœ‰åŠ¹æœŸé™ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ IDã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ç¨®é¡ž IDã€ã‚µãƒ¼ãƒãƒ¼ ID ãŠã‚ˆã³ã‚·ãƒªã‚¢ãƒ« ID ã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚\n\nç¾åœ¨ã® VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹çŠ¶æ…‹ã‚’表示ã™ã‚‹ã«ã¯ã€LicenseStatus コマンドを使用ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_LicenseList_Args LicenseList
+
+
+# LicenseStatus コマンド
+CMD_LicenseStatus ç¾åœ¨ã® VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹çŠ¶æ…‹ã®å–å¾—
+CMD_LicenseStatus_Help ç¾åœ¨ã® SoftEther VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹çŠ¶æ…‹ã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\nSoftEther VPN Server ã®ç¾åœ¨ã®è£½å“エディションåã€ã‚µãƒ¼ãƒãƒ¼ IDã€è£½å“ライセンスã®æœ‰åŠ¹æœŸé™ã€ãŠã‚ˆã³åˆ©ç”¨å¯èƒ½ãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆæŽ¥ç¶šãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ•°ã¨ãƒ–リッジ接続ライセンス数ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_LicenseStatus_Args LicenseStatus
+
+
+## SoftEther VPN 4.0 ã§æ–°ãŸã«è¿½åŠ ã•ã‚ŒãŸã‚³ãƒžãƒ³ãƒ‰
+
+# IPsecEnable コマンド
+CMD_IPsecEnable IPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã®æœ‰åŠ¹åŒ– / 無効化
+CMD_IPsecEnable_Help SoftEther VPN Server ã® IPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 / 無効化ã—ã¾ã™ã€‚\nIPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã¨ã€VPN Server 上ã®ä»®æƒ³ HUB ã¯ã€IPsec / L2TP / EtherIP / L2TPv3 ã«å¯¾å¿œã—㟠PC ã‚„ Mac OS Xã€ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã€ãƒ«ãƒ¼ã‚¿ç­‰ã‹ã‚‰ã® VPN 接続をå—付ã‘ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_IPsecEnable_Args IPsecEnable [/L2TP:yes|no] [/L2TPRAW:yes|no] [/ETHERIP:yes|no] [/PSK:pre-shared-key] [/DEFAULTHUB:default_hub]
+CMD_IPsecEnable_L2TP L2TP over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«è¨­å®šã—ã¾ã™ã€‚iPhoneã€iPadã€Androidã€Windowsã€Mac OS X ã‹ã‚‰ã® VPN 接続をå—付ã‘ã‚‹ã«ã¯ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã—ã¦ãã ã•ã„。
+CMD_IPsecEnable_L2TPRAW IPsec を用ã„ãªã„ L2TP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«è¨­å®šã—ã¾ã™ã€‚特殊ãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹å ´åˆã®ã¿æœ‰åŠ¹ã«ã—ã¦ãã ã•ã„。
+CMD_IPsecEnable_ETHERIP EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ (拠点間接続 VPN サーãƒãƒ¼æ©Ÿèƒ½) を有効ã¾ãŸã¯ç„¡åŠ¹ã«è¨­å®šã—ã¾ã™ã€‚EtherIP / L2TPv3 over IPsec ã«å¯¾å¿œã—ãŸå¸‚販ã®ãƒ«ãƒ¼ã‚¿è£½å“ã¯ã€ã“ã® VPN Server ã®ä»®æƒ³ HUB ã«ãƒ¬ã‚¤ãƒ¤ 2 (Ethernet) ã§ãƒ–リッジ接続ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+CMD_IPsecEnable_PSK IPsec 事å‰å…±æœ‰éµã‚’設定ã—ã¾ã™ã€‚IPsec 事å‰å…±æœ‰éµã¯ã€ã€ŒPSK (Pre-Shared Key)ã€ã¾ãŸã¯ã€Œã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã€ã¨å‘¼ã°ã‚Œã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚8 文字程度ã§è¨­å®šã—ã€VPN を利用ã™ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é…布ã—ã¦ãã ã•ã„。Google Android 4.0 ã«ã¯ãƒã‚°ãŒã‚ã‚Šã€PSK ã®æ–‡å­—数㌠10 文字を超ãˆãŸå ´åˆã¯ VPN 通信ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ãã®ãŸã‚ã€PSK ã®æ–‡å­—数㯠9 文字以下ã«ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚
+CMD_IPsecEnable_DEFAULTHUB 接続時ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã«ãŠã„ã¦ä»®æƒ³ HUB åãŒçœç•¥ã•ã‚ŒãŸå ´åˆã«æŽ¥ç¶šã™ã‚‹ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚通常ã€L2TP, OpenVPN ãŠã‚ˆã³ MS-SSTP VPN 接続時ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å㯠"仮想HUBå\\ユーザーå" ã¾ãŸã¯ "ユーザーå@仮想HUBå" ã®ã‚ˆã†ã«æŒ‡å®šã•ã‚Œã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã‚‚ã—ユーザーãŒä»®æƒ³ HUB åã®æŒ‡å®šã‚’çœç•¥ã—ãŸå ´åˆã¯ã€DEFAULTHUB パラメータã¨ã—ã¦æŒ‡å®šã•ã‚Œã¦ã„る仮想 HUB ãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ä»®æƒ³ HUB ã¨ã—ã¦é¸æŠžã•ã‚Œã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚
+CMD_IPsecEnable_Prompt_L2TP L2TP over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効 (yes / no):
+CMD_IPsecEnable_Prompt_L2TPRAW Raw L2TP サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効 (yes / no):
+CMD_IPsecEnable_Prompt_ETHERIP EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効 (yes / no):
+CMD_IPsecEnable_Prompt_PSK IPsec 事å‰å…±æœ‰éµã®æ–‡å­—列 (9 文字以下を推奨):
+CMD_IPsecEnable_Prompt_DEFAULTHUB VPN 接続時ã«ä»®æƒ³ HUB åãŒçœç•¥ã•ã‚ŒãŸå ´åˆã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆä»®æƒ³ HUB å:
+
+
+# IPsecGet コマンド
+CMD_IPsecGet IPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã®ç¾åœ¨ã®è¨­å®šã®å–å¾—
+CMD_IPsecGet_Help SoftEther VPN Server ã® IPsec VPN サーãƒãƒ¼æ©Ÿèƒ½ã®ç¾åœ¨ã®è¨­å®šã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_IPsecGet_Args IPsecGet
+CMD_IPsecGet_PRINT_L2TP L2TP over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã¯æœ‰åŠ¹
+CMD_IPsecGet_PRINT_L2TPRAW Raw L2TP サーãƒãƒ¼æ©Ÿèƒ½ã¯æœ‰åŠ¹
+CMD_IPsecGet_PRINT_ETHERIP EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã¯æœ‰åŠ¹
+CMD_IPsecGet_PRINT_PSK IPsec 事å‰å…±æœ‰éµã®æ–‡å­—列
+CMD_IPsecGet_PRINT_DEFAULTHUB デフォルト仮想 HUB å
+
+
+# EtherIpClientAdd コマンド
+CMD_EtherIpClientAdd EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã®è¿½åŠ 
+CMD_EtherIpClientAdd_Help EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã‚’追加ã—ã¾ã™ã€‚\nEtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã«ãƒ«ãƒ¼ã‚¿ç­‰ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ã«ã¯ã€äºˆã‚クライアントå´ã¨ãªã‚‹ EtherIP / L2TPv3 over IPsec 対応ルータ㌠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã® IPsec Phase 1 文字列ã¨ã€æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUB ã®æƒ…å ±ã®å¯¾å¿œè¡¨ã‚’定義ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\nEtherIpClientAdd コマンドを用ã„ã¦å®šç¾©ã‚’追加ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€EtherIP / L2TPv3 over IPsec クライアントãŒã“ã® VPN Server ã«æŽ¥ç¶šã—よã†ã¨ã—ãŸéš›ã® ISAKMP (IKE) Phase 1 ã®ã‚¤ãƒ‹ã‚·ã‚¨ãƒ¼ã‚¿ ID 文字列ãŒå®šç¾©ã«ä¸€è‡´ã™ã‚‹å ´åˆã«ã€å®šç¾©ã•ã‚Œã¦ã„る仮想 HUB ã¸ã®æŽ¥ç¶šè¨­å®šãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚\nユーザーåã¨ãƒ‘スワードã¯ã€ä»®æƒ³ HUB ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚EtherIP / L2TPv3 クライアントã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§å…¥åŠ›ã•ã‚ŒãŸæƒ…å ±ã§è­˜åˆ¥ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ¨©é™ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã—ãŸã‚‚ã®ã¨ã¿ãªã•ã‚Œã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_EtherIpClientAdd_Args EtherIpClientAdd [ID] [/HUB:hubname] [/USERNAME:username] [/PASSWORD:password]
+CMD_EtherIpClientAdd_[ID] ISAKMP Phase 1 ID を指定ã—ã¾ã™ã€‚ID ã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã®ãƒ«ãƒ¼ã‚¿ã®æŽ¥ç¶šè¨­å®šã§è¨­å®šã™ã‚‹ã‚‚ã®ã¨åŒä¸€ã®æ–‡å­—列を指定ã—ã¦ãã ã•ã„。文字列ã®ã»ã‹ã€ID ã®ç¨®é¡žãŒ IP アドレスã®å ´åˆã¯ IP アドレスも指定ã§ãã¾ã™ã€‚ãªãŠã€'*' (アスタリスク) を指定ã™ã‚‹ã¨ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰æŒ‡å®šã¨ãªã‚Šã€ä»–ã®æ˜Žç¤ºçš„ãªãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã—ãªã„ã™ã¹ã¦ã®æŽ¥ç¶šå…ƒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒå¯¾è±¡ã¨ãªã‚Šã¾ã™ã€‚
+CMD_EtherIpClientAdd_HUB 接続先ã®ä»®æƒ³ HUB ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_EtherIpClientAdd_USERNAME 接続先ã®ä»®æƒ³ HUB ã«ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_EtherIpClientAdd_PASSWORD 接続先ã®ä»®æƒ³ HUB ã«ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã®ãƒ‘スワードを指定ã—ã¾ã™ã€‚
+CMD_EtherIpClientAdd_Prompt_ID ISAKMP Phase 1 ID ('*' ã§ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰æŒ‡å®š):
+CMD_EtherIpClientAdd_Prompt_HUB 接続先ã®ä»®æƒ³ HUB ã®åå‰:
+CMD_EtherIpClientAdd_Prompt_USERNAME 仮想 HUB ログイン用ユーザーå:
+CMD_EtherIpClientAdd_Prompt_PASSWORD 仮想 HUB ログイン用パスワード:
+
+
+# EtherIpClientDelete コマンド
+CMD_EtherIpClientDelete EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã®å‰Šé™¤
+CMD_EtherIpClientDelete_Help EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã®å®šç¾©æ¸ˆã¿é …目を削除ã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_EtherIpClientDelete_Args EtherIpClientDelete [ID]
+CMD_EtherIpClientDelete_[ID] ISAKMP Phase 1 ID を指定ã—ã¾ã™ã€‚
+CMD_EtherIpClientDelete_Prompt_ID ISAKMP Phase 1 ID:
+
+
+# EtherIpClientList コマンド
+CMD_EtherIpClientList EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã®ä¸€è¦§è¡¨ç¤º
+CMD_EtherIpClientList_Help EtherIP / L2TPv3 over IPsec サーãƒãƒ¼æ©Ÿèƒ½ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã®æŽ¥ç¶šã‚’å—付ã‘ã‚‹ãŸã‚ã®æŽ¥ç¶šè¨­å®šã®å®šç¾©æ¸ˆã¿ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_EtherIpClientList_Args EtherIpClientList
+
+
+# OpenVpnEnable コマンド
+CMD_OpenVpnEnable OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 / 無効化
+CMD_OpenVpnEnable_Help SoftEther VPN Server ã«ã¯ OpenVPN 社㮠OpenVPN ソフトウェア製å“ã¨åŒç­‰ã® VPN サーãƒãƒ¼æ©Ÿèƒ½ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚OpenVPN サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã¨ã€OpenVPN クライアントã‹ã‚‰ OpenVPN サーãƒãƒ¼ã«æŽ¥ç¶šã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\n\nOpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹å ´åˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®æŒ‡å®šæ–¹æ³•ã€ãŠã‚ˆã³ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆä»®æƒ³ HUB ã®é¸æŠžè¦å‰‡ã¯ã€IPsec サーãƒãƒ¼æ©Ÿèƒ½ã¨åŒæ§˜ã§ã™ã€‚詳ã—ã㯠IPsecEnable コマンドã®ãƒ˜ãƒ«ãƒ—ã‚’å‚ç…§ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_OpenVpnEnable_Args OpenVpnEnable [yes|no] [/PORTS:udp_port_list]
+CMD_OpenVpnEnable_[yes|no] OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹å ´åˆã¯ yesã€ç„¡åŠ¹ã«ã™ã‚‹å ´åˆã¯ no を指定ã—ã¾ã™ã€‚
+CMD_OpenVpnEnable_PORTS OpenVPN サービスをæä¾›ã™ã‚‹ UDP ãƒãƒ¼ãƒˆã®ä¸€è¦§ã‚’指定ã—ã¦ãã ã•ã„。UDP ãƒãƒ¼ãƒˆã¯è¤‡æ•°æŒ‡å®šã§ãã¾ã™ã€‚複数指定ã™ã‚‹å ´åˆã¯ 1194, 2001, 2010, 2012 ã®ã‚ˆã†ã«ã‚«ãƒ³ãƒž (,) ã§åŒºåˆ‡ã£ã¦ãã ã•ã„。OpenVPN ã¯æ¨™æº–ã§ã¯ UDP 1194 ãƒãƒ¼ãƒˆã‚’使用ã—ã¾ã™ãŒã€ãã®ä»–ã®ä»»æ„ã® UDP ãƒãƒ¼ãƒˆã‚’指定ã§ãã¾ã™ã€‚
+CMD_OpenVpnEnable_Prompt_[yes|no] OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 (yes / no):
+CMD_OpenVpnEnable_Prompt_PORTS UDP ãƒãƒ¼ãƒˆç•ªå·ã®ä¸€è¦§ (標準㯠1194 / 複数指定å¯):
+
+
+# OpenVpnGet コマンド
+CMD_OpenVpnGet OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã®ç¾åœ¨ã®è¨­å®šã‚’å–å¾—
+CMD_OpenVpnGet_Help ç¾åœ¨ã® OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_OpenVpnGet_Args OpenVpnGet
+CMD_OpenVpnGet_PRINT_Enabled OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ãŒæœ‰åŠ¹
+CMD_OpenVpnGet_PRINT_Ports UDP ãƒãƒ¼ãƒˆç•ªå·ä¸€è¦§
+
+# OpenVpnMakeConfig コマンド
+CMD_OpenVpnMakeConfig OpenVPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã«æŽ¥ç¶šå¯èƒ½ãªã‚µãƒ³ãƒ—ル㮠OpenVPN 設定ファイルã®ç”Ÿæˆ
+CMD_OpenVpnMakeConfig_Help 本æ¥ã€OpenVPN クライアントを使ã†ãŸã‚ã«ã¯è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’手動ã§è¨˜è¿°ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ãŒã€ã“ã‚Œã¯é›£æ˜“度ãŒé«˜ã„作業ã§ã™ã€‚ã—ã‹ã—ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã™ã‚Œã°ã“ã® VPN Server ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãる基本的㪠OpenVPN クライアント用ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’自動的ã«ç”Ÿæˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_OpenVpnMakeConfig_Args OpenVpnMakeConfig [ZIP_FileName]
+CMD_OpenVpnMakeConfig_[ZIP_FileName] ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦å‡ºåŠ›ã•ã‚Œã‚‹è¨­å®šãƒ•ã‚¡ã‚¤ãƒ« (ZIP 圧縮形å¼) ã®ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚æ‹¡å¼µå­ãŒæŒ‡å®šã•ã‚Œã¦ã„ãªã„å ´åˆã¯è‡ªå‹•çš„ã« ".zip" ãŒä»˜åŠ ã•ã‚Œã¾ã™ã€‚
+CMD_OpenVpnMakeConfig_Prompt_ZIP 設定ファイルをä¿å­˜ã™ã‚‹å…ˆã®ãƒ•ã‚¡ã‚¤ãƒ«å (ZIP 圧縮形å¼):
+CMD_OpenVpnMakeConfig_OK サンプル設定ファイルを "%s" ファイルã«ä¿å­˜ã—ã¾ã—ãŸã€‚ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ unzip コマンドãªã©ã‚’用ã„ã¦å±•é–‹ã—ã¦ä½¿ç”¨ã§ãã¾ã™ã€‚\n
+CMD_OpenVpnMakeConfig_ERROR サンプル設定ファイルを "%s" ファイルã«ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ファイルåãŒæ­£ã—ããªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\n
+
+
+# SstpEnable コマンド
+CMD_SstpEnable Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 / 無効化
+CMD_SstpEnable_Help SoftEther VPN Server ã«ã¯ Microsoft 社㮠Windows Server 2008 / 2012 製å“ã«æ­è¼‰ã•ã‚Œã¦ã„ã‚‹ MS-SSTP VPN サーãƒãƒ¼æ©Ÿèƒ½ã¨äº’æ›æ€§ãŒã‚る機能ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã¨ã€Windows Vista / 7 / 8 / RT ã«æ¨™æº–æ­è¼‰ã® MS-SSTP クライアントã‹ã‚‰ã“ã® VPN Server ã«æŽ¥ç¶šã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\n\n[ã”注æ„]\nVPN Server ã® SSL 証明書㮠CN ã®å€¤ãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã§æŒ‡å®šã™ã‚‹ãƒ›ã‚¹ãƒˆåã¨ä¸€è‡´ã—ã€ã‹ã¤ãã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚詳ã—ã㯠Microsoft 社ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„。\n指定ã•ã‚ŒãŸ CN ã®å€¤ã‚’æŒã¤æ–°ã—ã„ SSL 証明書 (自己署å証明書) を生æˆã—㦠VPN Server ã®ç¾åœ¨ã®è¨¼æ˜Žæ›¸ã¨ç½®æ›ã™ã‚‹ãŸã‚ã«ã¯ã€ServerCertRegenerate コマンドを使用ã—ã¦ãã ã•ã„。ã“ã®å ´åˆã¯ã€å½“該証明書を SSTP VPN クライアントã®ã‚³ãƒ³ãƒ”ュータã®ä¿¡é ¼ã•ã‚Œã‚‹ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã¨ã—ã¦ç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ã‚ˆã†ãªæ‰‹é–“ã‚’ã‹ã‘ãŸããªã„å ´åˆã¯ã€ä»£ã‚ã‚Šã« VeriSign ã‚„ GlobalSign 社ãªã©ã®å¸‚販ã®è¨¼æ˜Žæ›¸æ¥­è€…ã® SSL 証明書ã®å–得を検討ã—ã¦ãã ã•ã„。\n\nMicrosoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã§ä»®æƒ³ HUB ã«æŽ¥ç¶šã™ã‚‹å ´åˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®æŒ‡å®šæ–¹æ³•ã€ãŠã‚ˆã³ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆä»®æƒ³ HUB ã®é¸æŠžè¦å‰‡ã¯ã€IPsec サーãƒãƒ¼æ©Ÿèƒ½ã¨åŒæ§˜ã§ã™ã€‚詳ã—ã㯠IPsecEnable コマンドã®ãƒ˜ãƒ«ãƒ—ã‚’å‚ç…§ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SstpEnable_Args SstpEnable [yes|no]
+CMD_SstpEnable_[yes|no] Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹å ´åˆã¯ yesã€ç„¡åŠ¹ã«ã™ã‚‹å ´åˆã¯ no を指定ã—ã¾ã™ã€‚
+CMD_SstpEnable_Prompt_[yes|no] SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 (yes / no):
+CMD_SstpEnable_PRINT_Enabled SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ãŒæœ‰åŠ¹
+
+
+# SstpGet コマンド
+CMD_SstpGet Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã®ç¾åœ¨ã®è¨­å®šã‚’å–å¾—
+CMD_SstpGet_Help ç¾åœ¨ã® Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_SstpGet_Args SstpGet
+
+
+# ServerCertRegenerate コマンド
+CMD_ServerCertRegenerate 指定ã•ã‚ŒãŸ CN (Common Name) ã‚’æŒã¤è‡ªå·±ç½²å証明書を新ãŸã«ä½œæˆã— VPN Server ã«ç™»éŒ²
+CMD_ServerCertRegenerate_Help SoftEther VPN Server ã® SSL-VPN 機能ã§æ示ã•ã‚Œã‚‹ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã‚’ã€æ–°ãŸã«ä½œæˆã™ã‚‹è¨¼æ˜Žæ›¸ã«ç½®ãæ›ãˆã¾ã™ã€‚æ–°ãŸãªè¨¼æ˜Žæ›¸ã¯è‡ªå·±ç½²å証明書ã¨ã—ã¦ç”Ÿæˆã•ã‚Œã€CN (Common Name) ã®å€¤ã‚’ä»»æ„ã®æ–‡å­—列ã«è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€Microsoft SSTP VPN 互æ›ã‚µãƒ¼ãƒãƒ¼æ©Ÿèƒ½ã‚’使用ã—よã†ã¨ã™ã‚‹å ´åˆã«ä¾¿åˆ©ã§ã™ã€‚ãªãœãªã‚‰ã°ã€SSTP VPN クライアント (Windows Vista / 7 / 8 / RT ã«æ¨™æº–æ­è¼‰) ã¯æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書㮠CN (Common Name) ã®å€¤ãŒæŽ¥ç¶šå…ˆã¨ã—ã¦æŒ‡å®šã•ã‚Œã¦ã„るホストå文字列ã¨å®Œå…¨ã«ä¸€è‡´ã™ã‚‹ã‹ã©ã†ã‹ã‚’検証ã—ã€ã‚‚ã—一致ã—ãªã„å ´åˆã¯æŽ¥ç¶šã‚’キャンセルã™ã‚‹ãŸã‚ã§ã™ã€‚\n詳ã—ã㯠SstpEnable コマンドã®ãƒ˜ãƒ«ãƒ—ã‚’å‚ç…§ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€æ—¢å­˜ã® VPN Server ã® SSL 証明書を削除ã—ã¾ã™ã€‚ServerCertGet コマンドãŠã‚ˆã³ ServerKeyGet コマンドを用ã„ã¦ã€ç¾åœ¨ã®è¨¼æ˜Žæ›¸ã¨ç§˜å¯†éµã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¦ãŠãã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_ServerCertRegenerate_Args ServerCertRegenerate [CN]
+CMD_ServerCertRegenerate_[CN] æ–°ãŸã«ç”Ÿæˆã™ã‚‹è‡ªå·±ç½²å証明書㮠Common Name (CN) ã®å€¤ã‚’指定ã—ã¾ã™ã€‚
+CMD_ServerCertRegenerate_Prompt_CN Common Name (CN) ã®å€¤:
+
+
+# VpnOverIcmpDnsEnable コマンド
+CMD_VpnOverIcmpDnsEnable VPN over ICMP / VPN over DNS サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効化 / 無効化
+CMD_VpnOverIcmpDnsEnable_Help ファイアウォールやルータ等ã®æ•…障やéŽè² è·ã€è¨­å®šãƒŸã‚¹ç­‰ã«ã‚ˆã‚Š TCP/IP 通信ãŒã§ããªã„環境ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‹ã‚‰ã§ã‚‚ã€ICMP (Ping) ã¾ãŸã¯ DNS パケットã®é€šä¿¡ãŒå¯èƒ½ã§ã‚ã‚Œã°ã€VPN Server 㨠VPN Client ã¨ã®é–“㧠VPN 通信を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®ãŸã‚ã«ã¯ã€äºˆã‚ VPN over ICMP / VPN over DNS サーãƒãƒ¼æ©Ÿèƒ½ã‚’有効ã«ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n\n警告: ã“ã®æ©Ÿèƒ½ã¯ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã‚„ルータ等ãŒä¸€æ™‚çš„ã«ä¸èª¿ã¨ãªã£ã¦ãŠã‚Š ICMP ã¾ãŸã¯ DNS ã®ã¿å®‰å®šã—ãŸé€šä¿¡ãŒå¯èƒ½ãªç’°å¢ƒã§ VPN 通信を確立ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã‚。緊急時ãªã©ã«ã¯æœ‰ç›Šã§ã™ãŒã€é•·æœŸé–“ã®åˆ©ç”¨ã«ã¯é©ã—ãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\n\n接続元㮠VPN Client ã¾ãŸã¯ VPN Bridge ã¯å†…部ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4.0 以é™ãŒå¿…è¦ã§ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_VpnOverIcmpDnsEnable_Args VpnOverIcmpDnsEnable [/ICMP:yes|no] [/DNS:yes|no]
+CMD_VpnOverIcmpDnsEnable_ICMP VPN over ICMP サーãƒãƒ¼ã‚’有効ã«ã™ã‚‹ã«ã¯ yesã€ç„¡åŠ¹ã«ã™ã‚‹ã«ã¯ no を指定ã—ã¾ã™ã€‚
+CMD_VpnOverIcmpDnsEnable_DNS VPN over DNS サーãƒãƒ¼ã‚’有効ã«ã™ã‚‹ã«ã¯ yesã€ç„¡åŠ¹ã«ã™ã‚‹ã«ã¯ no を指定ã—ã¾ã™ã€‚
+CMD_VpnOverIcmpDnsEnable_Prompt_ICMP VPN over ICMP サーãƒãƒ¼ã‚’有効 (yes / no):
+CMD_VpnOverIcmpDnsEnable_Prompt_DNS VPN over DNS サーãƒãƒ¼ã‚’有効 (yes / no):
+
+
+# VpnOverIcmpDnsGet コマンド
+CMD_VpnOverIcmpDnsGet ç¾åœ¨ã® VPN over ICMP / VPN over DNS サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã‚’å–å¾—
+CMD_VpnOverIcmpDnsGet_Help ç¾åœ¨ã® VPN over ICMP / VPN over DNS サーãƒãƒ¼æ©Ÿèƒ½ã®è¨­å®šã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_VpnOverIcmpDnsGet_Args VpnOverIcmpDnsGet
+CMD_VpnOverIcmpDnsGet_PRINT_ICMP VPN over ICMP サーãƒãƒ¼ãŒæœ‰åŠ¹
+CMD_VpnOverIcmpDnsGet_PRINT_DNS VPN over DNS サーãƒãƒ¼ãŒæœ‰åŠ¹
+
+
+# DynamicDnsGetStatus コマンド
+CMD_DynamicDnsGetStatus ダイナミック DNS 機能ã®ç¾åœ¨ã®çŠ¶æ…‹ã®å–å¾—
+CMD_DynamicDnsGetStatus_Help ダイナミック DNS 機能ã®ç¾åœ¨ã®çŠ¶æ…‹ã‚’å–å¾—ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n\nダイナミック DNS ã«ã‚ˆã‚‹ã€VPN Server コンピュータã«æ°¸ç¶šçš„ãªå›ºæœ‰ã® DNS ホストåãŒå‰²å½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç‹¬è‡ªã§ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’所有ã—ã¦ã„ãªãã¦ã‚‚ã€VPN Client ã‚„ VPN Bridge ãªã©ã®è¨­å®šç”»é¢ä¸ŠãŒ VPN Server ã® IP アドレスã®ä»£ã‚ã‚Šã« DNS ホストåã«ã‚ˆã£ã¦ VPN Server を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã¾ãŸã€IP アドレスãŒå¤‰åŒ–ã™ã‚‹å¯èƒ½æ€§ãŒã‚る一般的㪠ISP を用ã„㦠VPN Server をインターãƒãƒƒãƒˆã«æŽ¥ç¶šã™ã‚‹å ´åˆã§ã‚‚ã€IP アドレスãŒå¤‰åŒ–ã™ã‚Œã°è‡ªå‹•çš„ã« DNS ホストå対応ã™ã‚‹ IP アドレスãŒæ›´æ–°ã•ã‚Œã¾ã™ã®ã§ã€å¯å¤‰ IP アドレスã§ã‚‚ VPN Server ã‚’é‹ç”¨ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\nã“ã‚Œã«ã‚ˆã‚Šã€é«˜ä¾¡ãªæœˆé¡æ–™é‡‘ãŒå¿…è¦ãªå›ºå®šã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã®ã‚µãƒ¼ãƒ“スを契約ã™ã‚‹å¿…è¦ãŒãªããªã‚Šã¾ã™ã€‚\n\n[注æ„]\nダイナミック DNS 機能を無効ã«ã™ã‚‹ã«ã¯ã€VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã¾ã™ã€‚\n"declare root" ディレクティブ内㫠"declare DDnsClient" ディレクティブãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ä¸­ã«ã‚ã‚‹ "bool Disable" ã®å€¤ã‚’ true ã«è¨­å®šã—㦠VPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DynamicDnsGetStatus_Args DynamicDnsGetStatus
+CMD_DynamicDnsGetStatus_PRINT_FQDN 割当ダイナミック DNS ホストå (完全)
+CMD_DynamicDnsGetStatus_PRINT_HOSTNAME 割当ダイナミック DNS ホストå (ホストå)
+CMD_DynamicDnsGetStatus_PRINT_SUFFIX DNS サフィックス
+CMD_DynamicDnsGetStatus_PRINT_IPv4 グローãƒãƒ« IPv4 アドレス
+CMD_DynamicDnsGetStatus_PRINT_IPv6 グローãƒãƒ« IPv6 アドレス
+
+
+# DynamicDnsSetHostname コマンド
+CMD_DynamicDnsSetHostname ダイナミック DNS ホストåã®è¨­å®š
+CMD_DynamicDnsSetHostname_Help ダイナミック DNS 機能㧠VPN Server ãŒä½¿ç”¨ã™ã‚‹ãƒ›ã‚¹ãƒˆåを設定ã—ã¾ã™ã€‚ç¾åœ¨å‰²å½“ã¦ã‚‰ã‚Œã¦ã„るホストå㯠DynamicDnsGetStatus コマンドã§ç¢ºèªã§ãã¾ã™ã€‚\n\nダイナミック DNS ã«ã‚ˆã‚‹ã€VPN Server コンピュータã«æ°¸ç¶šçš„ãªå›ºæœ‰ã® DNS ホストåãŒå‰²å½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç‹¬è‡ªã§ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’所有ã—ã¦ã„ãªãã¦ã‚‚ã€VPN Client ã‚„ VPN Bridge ãªã©ã®è¨­å®šç”»é¢ä¸ŠãŒ VPN Server ã® IP アドレスã®ä»£ã‚ã‚Šã« DNS ホストåã«ã‚ˆã£ã¦ VPN Server を指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã¾ãŸã€IP アドレスãŒå¤‰åŒ–ã™ã‚‹å¯èƒ½æ€§ãŒã‚る一般的㪠ISP を用ã„㦠VPN Server をインターãƒãƒƒãƒˆã«æŽ¥ç¶šã™ã‚‹å ´åˆã§ã‚‚ã€IP アドレスãŒå¤‰åŒ–ã™ã‚Œã°è‡ªå‹•çš„ã« DNS ホストå対応ã™ã‚‹ IP アドレスãŒæ›´æ–°ã•ã‚Œã¾ã™ã®ã§ã€å¯å¤‰ IP アドレスã§ã‚‚ VPN Server ã‚’é‹ç”¨ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\nã“ã‚Œã«ã‚ˆã‚Šã€é«˜ä¾¡ãªæœˆé¡æ–™é‡‘ãŒå¿…è¦ãªå›ºå®šã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã®ã‚µãƒ¼ãƒ“スを契約ã™ã‚‹å¿…è¦ãŒãªããªã‚Šã¾ã™ã€‚\n\n[注æ„]\nダイナミック DNS 機能を無効ã«ã™ã‚‹ã«ã¯ã€VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã¾ã™ã€‚\n"declare root" ディレクティブ内㫠"declare DDnsClient" ディレクティブãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ä¸­ã«ã‚ã‚‹ "bool Disable" ã®å€¤ã‚’ true ã«è¨­å®šã—㦠VPN Server ã‚’å†èµ·å‹•ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_DynamicDnsSetHostname_Args DynamicDnsSetHostname [hostname]
+CMD_DynamicDnsSetHostname_[hostname] æ–°ã—ã„ホストåã‚’ 3 文字以上 31 文字以下ã®åŠè§’英数字ãŠã‚ˆã³ãƒã‚¤ãƒ•ãƒ³ '-' ã§æŒ‡å®šã—ã¾ã™ã€‚変更ã¯ä½•åº¦ã§ã‚‚å¯èƒ½ã§ã™ã€‚
+CMD_DynamicDnsSetHostname_Prompt_hostname ダイナミック DNS ホストå (3 - 31 文字):
+
+
+# VpnAzureGetStatus コマンド
+CMD_VpnAzureGetStatus VPN Azure 機能ã®ç¾åœ¨ã®çŠ¶æ…‹ã®å–å¾—
+CMD_VpnAzureGetStatus_Help VPN Azure 機能ã®ç¾åœ¨ã®çŠ¶æ…‹ã‚’å–å¾—ã—ã¾ã™ã€‚\n\nVPN Azure ã«ã‚ˆã‚Šã€ä¼šç¤¾ã®ãƒ‘ソコンã«è‡ªå®…や外出先ã®ãƒ‘ソコンã‹ã‚‰éžå¸¸ã«ç°¡å˜ã« VPN 接続ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚VPN 接続中ã¯ä¼šç¤¾ã®ãƒ‘ソコンを経由ã—ã¦ã€ç¤¾å†… LAN ã®ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã«ã‚‚アクセスã§ãã¾ã™ã€‚\n会社ã®ãƒ‘ソコン (VPN Server) ã«ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã¯ä¸è¦ã§ã™ã€‚ファイアウォールや NAT ã®å†…å´ã§ã‚ã£ã¦ã‚‚動作ã—ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹è¨­å®šã¯ä¸€åˆ‡å¿…è¦ã‚ã‚Šã¾ã›ã‚“。VPN クライアントã¨ãªã‚‹è‡ªå®…ã®ãƒ‘ソコンã§ã¯ã€Windows ã«æ¨™æº–付属㮠SSTP VPN クライアントを使用ã§ãã¾ã™ã€‚\nVPN Azure ã¯ã€SoftEther VPN Server ã‚’ãŠä½¿ã„ã®æ–¹ã¯ã©ãªãŸã§ã‚‚ç„¡æ–™ã§åˆ©ç”¨ã§ãるクラウド VPN サービスã§ã™ã€‚ソフトイーサ株å¼ä¼šç¤¾ã«ã‚ˆã£ã¦é‹å–¶ã•ã‚Œã¦ã„ã¾ã™ã€‚使ã„方㯠http://www.vpnazure.net/ ã«æŽ²è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚\n\nVPN Azure ホストåã¯ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サービスã®ãƒ›ã‚¹ãƒˆåã®ãƒ‰ãƒ¡ã‚¤ãƒ³éƒ¨åˆ†ã‚’ "vpnazure.net" ã«å¤‰æ›´ã—ãŸã‚‚ã®ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚ホストåを変更ã™ã‚‹ã«ã¯ DynamicDnsSetHostname コマンドを使用ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_VpnAzureGetStatus_Args VpnAzureGetStatus
+CMD_VpnAzureGetStatus_PRINT_ENABLED VPN Azure 機能ãŒæœ‰åŠ¹
+CMD_VpnAzureGetStatus_PRINT_CONNECTED VPN Azure クラウドサーãƒãƒ¼ã¸æŽ¥ç¶šå®Œäº†
+CMD_VpnAzureGetStatus_PRINT_HOSTNAME VPN Azure サービス上ã§ã®ãƒ›ã‚¹ãƒˆå
+
+
+# VpnAzureSetStatus コマンド
+CMD_VpnAzureSetEnable VPN Azure 機能ã®æœ‰åŠ¹åŒ– / 無効化
+CMD_VpnAzureSetEnable_Help VPN Azure 機能を有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã¾ã™ã€‚\n\nVPN Azure ã«ã‚ˆã‚Šã€ä¼šç¤¾ã®ãƒ‘ソコンã«è‡ªå®…や外出先ã®ãƒ‘ソコンã‹ã‚‰éžå¸¸ã«ç°¡å˜ã« VPN 接続ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚VPN 接続中ã¯ä¼šç¤¾ã®ãƒ‘ソコンを経由ã—ã¦ã€ç¤¾å†… LAN ã®ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã«ã‚‚アクセスã§ãã¾ã™ã€‚\n会社ã®ãƒ‘ソコン (VPN Server) ã«ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã¯ä¸è¦ã§ã™ã€‚ファイアウォールや NAT ã®å†…å´ã§ã‚ã£ã¦ã‚‚動作ã—ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹è¨­å®šã¯ä¸€åˆ‡å¿…è¦ã‚ã‚Šã¾ã›ã‚“。VPN クライアントã¨ãªã‚‹è‡ªå®…ã®ãƒ‘ソコンã§ã¯ã€Windows ã«æ¨™æº–付属㮠SSTP VPN クライアントを使用ã§ãã¾ã™ã€‚\nVPN Azure ã¯ã€SoftEther VPN Server ã‚’ãŠä½¿ã„ã®æ–¹ã¯ã©ãªãŸã§ã‚‚ç„¡æ–™ã§åˆ©ç”¨ã§ãるクラウド VPN サービスã§ã™ã€‚ソフトイーサ株å¼ä¼šç¤¾ã«ã‚ˆã£ã¦é‹å–¶ã•ã‚Œã¦ã„ã¾ã™ã€‚使ã„方㯠http://www.vpnazure.net/ ã«æŽ²è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚\n\nVPN Azure ホストåã¯ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サービスã®ãƒ›ã‚¹ãƒˆåã®ãƒ‰ãƒ¡ã‚¤ãƒ³éƒ¨åˆ†ã‚’ "vpnazure.net" ã«å¤‰æ›´ã—ãŸã‚‚ã®ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚ホストåを変更ã™ã‚‹ã«ã¯ DynamicDnsSetHostname コマンドを使用ã—ã¦ãã ã•ã„。\n\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€VPN Server ã®ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Bridge ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ã¨ã—ã¦å‹•ä½œã—ã¦ã„ã‚‹ VPN Server ã®ä»®æƒ³ HUB ã§ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。
+CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no]
+CMD_VpnAzureSetEnable_[yes|no] VPN Azure 機能を有効ã«ã™ã‚‹ã«ã¯ yesã€ç„¡åŠ¹ã«ã™ã‚‹ã«ã¯ no を指定ã—ã¾ã™ã€‚
+CMD_VpnAzureSetEnable_PROMPT VPN Azure 機能を有効 (yes / no):
+
+
+
+######################################################
+# #
+# ã“ã“ã‹ã‚‰ä¸‹ã¯ VPN Client 用ã®ç®¡ç†ã‚³ãƒžãƒ³ãƒ‰ #
+# #
+######################################################
+
+
+# VersionGet コマンド
+CMD_VersionGet VPN Client サービスã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã®å–å¾—
+CMD_VersionGet_Help ç¾åœ¨ç®¡ç†ã—ã¦ã„ã‚‹ VPN Client サービスプログラムã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報をå–å¾—ã—ã¾ã™ã€‚
+CMD_VersionGet_Args VersionGet
+CMD_VersionGet_1 製å“å
+CMD_VersionGet_2 ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±
+CMD_VersionGet_3 ビルド情報
+CMD_VersionGet_4 プロセス ID
+CMD_VersionGet_5 OS ã®ç¨®é¡ž
+
+
+# PasswordSet コマンド
+CMD_PasswordSet VPN Client サービスã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã®ãƒ‘スワードã®è¨­å®š
+CMD_PasswordSet_Help VPN Client サービスã«ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚„ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ãªã©ã‹ã‚‰æŽ¥ç¶šã—ã¦åˆ¶å¾¡ã‚’è¡Œã†éš›ã«ã€ãƒ‘スワードã®å…¥åŠ›ã‚’求ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’用ã„ã¦ã€å…¥åŠ›ã‚’求ã‚るパスワードを設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nパスワードã¯ã€ãƒªãƒ¢ãƒ¼ãƒˆ (localhost 以外ã®ã‚³ãƒ³ãƒ”ュータ) ã‹ã‚‰æ“作を行ã†å ´åˆã®ã¿å…¥åŠ›ã•ã›ã‚‹ã“ã¨ã‚’è¦æ±‚ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_PasswordSet_Args PasswordSet [password] [/REMOTEONLY:yes|no]
+CMD_PasswordSet_[password] 設定ã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚"none" ã¨æŒ‡å®šã™ã‚‹ã¨ã€ãƒ‘スワードã®è¨­å®šã‚’削除ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_PasswordSet_REMOTEONLY yes を指定ã™ã‚‹ã¨ã€ãƒ‘スワードã¯ãƒªãƒ¢ãƒ¼ãƒˆ (localhost 以外ã®ã‚³ãƒ³ãƒ”ュータ) ã‹ã‚‰æ“作を行ã†å ´åˆã®ã¿è¦æ±‚ã•ã‚Œã€localhost ã‹ã‚‰ã®æŽ¥ç¶šæ™‚ã«ã¯è¦æ±‚ã•ã‚Œãªããªã‚Šã¾ã™ã€‚ã“ã®ãƒ‘ラメータをçœç•¥ã—ãŸå ´åˆã¯ã€"no" ã¨è¦‹ãªã—ã¾ã™ã€‚
+
+
+# PasswordGet コマンド
+CMD_PasswordGet VPN Client サービスã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã®ãƒ‘スワードã®è¨­å®šã®å–å¾—
+CMD_PasswordGet_Help VPN Client サービスã«ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚„ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ãªã©ã‹ã‚‰æŽ¥ç¶šã—ã¦åˆ¶å¾¡ã‚’è¡Œã†éš›ã«ã€ãƒ‘スワードã®å…¥åŠ›ã‚’求ã‚るよã†ã«ãªã£ã¦ã„ã‚‹ã‹ã©ã†ã‹ã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\nã¾ãŸã€ãƒ‘スワードをè¦æ±‚ã™ã‚‹å ´åˆã«ã¤ã„ã¯ã€ãƒªãƒ¢ãƒ¼ãƒˆ (localhost 以外ã®ã‚³ãƒ³ãƒ”ュータ) ã‹ã‚‰æ“作を行ã†å ´åˆã®ã¿å…¥åŠ›ã•ã›ã‚‹è¨­å®šã«ãªã£ã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚‚å–å¾—ã—ã¾ã™ã€‚
+CMD_PasswordGet_Args PasswordGet
+CMD_PasswordGet_1 パスワードã®è¨­å®š
+CMD_PasswordGet_2 リモートã‹ã‚‰ã®æŽ¥ç¶šæ™‚ã®ã¿ãƒ‘スワードをè¦æ±‚
+
+
+# CertList コマンド
+CMD_CertList ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã®å–å¾—
+CMD_CertList_Help VPN Client ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’管ç†ã—ã¾ã™ã€‚登録ã•ã‚Œã¦ã„る証明機関ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Server ã¸ã®æŽ¥ç¶šæ™‚ã®ã€ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãªã©ã«åˆ©ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_CertList_Args CertList
+
+
+# CertAdd コマンド
+CMD_CertAdd ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®è¿½åŠ 
+CMD_CertAdd_Help VPN Client ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€æ–°ã—ã„証明書を追加ã—ã¾ã™ã€‚登録ã•ã‚ŒãŸè¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã¯ã€VPN Server ã¸ã®æŽ¥ç¶šæ™‚ã®ã€ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãªã©ã«åˆ©ç”¨ã•ã‚Œã¾ã™ã€‚\nç¾åœ¨ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€CertList コマンドを使用ã—ã¾ã™ã€‚\n証明書を追加ã™ã‚‹ã«ã¯ã€ãã®è¨¼æ˜Žæ›¸ãŒ X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_CertAdd_Args CertAdd [path]
+CMD_CertAdd_[path] 登録ã™ã‚‹ X.509 証明書ファイルåを指定ã—ã¾ã™ã€‚
+
+
+# CertDelete コマンド
+CMD_CertDelete ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®å‰Šé™¤
+CMD_CertDelete_Help VPN Client ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‹ã‚‰ã€æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã‚’削除ã—ã¾ã™ã€‚\nç¾åœ¨ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€CertList コマンドを使用ã—ã¾ã™ã€‚
+CMD_CertDelete_Args CertDelete [id]
+CMD_CertDelete_[id] 削除ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID を指定ã—ã¾ã™ã€‚
+
+
+# CertGet コマンド
+CMD_CertGet ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_CertGet_Help VPN Client ãŒä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§å†…ã®ã€æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã€X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚
+CMD_CertGet_Args CertGet [id] [/SAVECERT:path]
+CMD_CertGet_[id] å–å¾—ã™ã‚‹è¨¼æ˜Žæ›¸ã® ID を指定ã—ã¾ã™ã€‚
+CMD_CertGet_SAVECERT å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# SecureList コマンド
+CMD_SecureList 使用ã§ãるスマートカードã®ç¨®é¡žã®ä¸€è¦§ã®å–å¾—
+CMD_SecureList_Help VPN Client ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„るスマートカードã®ç¨®é¡žã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚\nスマートカードã®ç¨®é¡žã®ä¸€è¦§ã«ã¯ã€ç¾åœ¨ã‚³ãƒ³ãƒ”ュータã«ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¦ã€ã‹ã¤ VPN ソフトウェアã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„るデãƒã‚¤ã‚¹ã®ä¸€è¦§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\r\nç¾åœ¨ä½¿ç”¨ã—ã¦ã„るスマートカードã®ç¨®é¡žãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€VPN ソフトウェアをより新ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šä½¿ç”¨ã§ãるよã†ã«ãªã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
+CMD_SecureList_Args SecureList
+
+
+# SecureSelect コマンド
+CMD_SecureSelect 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ç¨®é¡žã®é¸æŠž
+CMD_SecureSelect_Help VPN Client ã§ä½¿ç”¨ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚\n使用ã§ãるスマートカードã®ç¨®é¡žã®ä¸€è¦§ã¯ã€SecureList コマンドã§å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+CMD_SecureSelect_Args SecureSelect [id]
+CMD_SecureSelect_[id] スマートカードã®ç¨®é¡žã® ID を指定ã—ã¾ã™ã€‚
+CMD_SecureSelect_PROMPT_ID 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ç¨®é¡žã® ID:
+
+
+# SecureGet コマンド
+CMD_SecureGet 使用ã™ã‚‹ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ç¨®é¡žã® ID ã®å–å¾—
+CMD_SecureGet_Help ç¾åœ¨ VPN Client ã§ä½¿ç”¨ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„るスマートカードã®ç¨®é¡žã® ID ã‚’å–å¾—ã—ã¾ã™ã€‚ã“ã® ID を元㫠SecureList コマンドã®çµæžœã‚’見るã“ã¨ã«ã‚ˆã£ã¦ã€ç¾åœ¨é¸æŠžã•ã‚Œã¦ã„るスマートカードã®ç¨®é¡žãŒå–å¾—ã§ãã¾ã™ã€‚\nç¾åœ¨ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€ID ㌠0 ã¨è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_SecureGet_Args SecureGet
+CMD_SecureGet_Print ç¾åœ¨é¸æŠžã•ã‚Œã¦ã„るスマートカード ID 㯠%u ã§ã™ã€‚
+CMD_SecureGet_NoPrint ç¾åœ¨ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã¯é¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。
+
+
+# NicCreate コマンド
+CMD_NicCreate æ–°è¦ä»®æƒ³ LAN カードã®ä½œæˆ
+CMD_NicCreate_Help æ–°ã—ã„仮想 LAN カードをシステムã«è¿½åŠ ã—ã¾ã™ã€‚仮想 LAN カードã«ã¯ä»»æ„ã®åå‰ã‚’付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nãŸã ã—ã€ä»®æƒ³ LAN カードåã«ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる文字ã¯è‹±æ•°å­—ã®ã¿ã§ã€Windows 2000 以é™ã®ã‚·ã‚¹ãƒ†ãƒ ã§ã¯ 31 文字ã¾ã§ã€Windows 98, 98 SE ãŠã‚ˆã³ ME ã§ã¯ 4 文字ã¾ã§è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nNicCreate コマンドを呼ã³å‡ºã—ãŸå ´åˆã€VPN Client ãŒå‹•ä½œã—ã¦ã„るオペレーティングシステムã«ã€æ–°ã—ã„仮想 LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã™ã€‚\nã“ã®å ´åˆã€ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã«ã‚ˆã£ã¦ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã‚’インストールã—ã¦ã‚‚良ã„ã‹ã©ã†ã‹ç¢ºèªã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ãƒœãƒƒã‚¯ã‚¹ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+CMD_NicCreate_Args NicCreate [name]
+CMD_NicCreate_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_NicCreate_PROMPT_NAME 仮想 LAN カードã®åå‰:
+
+
+# NicDelete コマンド
+CMD_NicDelete 仮想 LAN カードã®å‰Šé™¤
+CMD_NicDelete_Help 既存ã®ä»®æƒ³ LAN カードをシステムã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚\nシステムã‹ã‚‰ä»®æƒ³ LAN カードを削除ã™ã‚‹ã¨ã€ãã®ä»®æƒ³ LAN カードを使用ã—ã¦ã„ãŸæŽ¥ç¶šã¯åˆ‡æ–­ã•ã‚Œã¾ã™ã€‚\nã¾ãŸã€å‰Šé™¤ã•ã‚ŒãŸä»®æƒ³ LAN カードを使用ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„ãŸæŽ¥ç¶šè¨­å®šã¯ã€åˆ¥ã®ä»®æƒ³ LAN カードを使用ã™ã‚‹ã‚ˆã†ã«è‡ªå‹•çš„ã«è¨­å®šå¤‰æ›´ã•ã‚Œã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicDelete_Args NicDelete [name]
+CMD_NicDelete_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# NicUpgrade コマンド
+CMD_NicUpgrade 仮想 LAN カードã®ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã®ã‚¢ãƒƒãƒ—グレード
+CMD_NicUpgrade_Help 既存ã®ä»®æƒ³ LAN カードã®ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã„å ´åˆã€ç¾åœ¨å‹•ä½œã—ã¦ã„ã‚‹ VPN Client ã«åŒæ¢±ã•ã‚Œã¦ã„る最新ã®ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã«ã‚¢ãƒƒãƒ—グレードã—ã¾ã™ã€‚アップグレードãŒè¡Œã‚ã‚Œãªã„å ´åˆã§ã‚‚ã€ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã‚’å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚\nオペレーティングシステムã«ã‚ˆã£ã¦ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã‚’インストールã—ã¦ã‚‚良ã„ã‹ã©ã†ã‹ç¢ºèªã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ãƒœãƒƒã‚¯ã‚¹ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicUpgrade_Args NicUpgrade [name]
+CMD_NicUpgrade_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# NicGetSetting コマンド
+CMD_NicGetSetting 仮想 LAN カードã®è¨­å®šã®å–å¾—
+CMD_NicGetSetting_Help 既存ã®ä»®æƒ³ LAN カード㮠MAC アドレス設定をå–å¾—ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicGetSetting_Args NicGetSetting [name]
+CMD_NicGetSetting_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_NicGetSetting_1 デãƒã‚¤ã‚¹å
+CMD_NicGetSetting_2 状態
+CMD_NicGetSetting_3 MAC アドレス
+CMD_NicGetSetting_4 ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+CMD_NicGetSetting_5 ドライãƒãƒ•ã‚¡ã‚¤ãƒ«å
+CMD_NicGetSetting_6 GUID
+
+
+# NicSetSetting コマンド
+CMD_NicSetSetting 仮想 LAN カードã®è¨­å®šã®å¤‰æ›´
+CMD_NicSetSetting_Help 既存ã®ä»®æƒ³ LAN カード㮠MAC アドレス設定を変更ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ã€ç¾åœ¨å‹•ä½œä¸­ã®ä»®æƒ³ LAN カードデãƒã‚¤ã‚¹ãƒ‰ãƒ©ã‚¤ãƒã¯å†èµ·å‹•ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicSetSetting_Args NicSetSetting [name] [/MAC:mac]
+CMD_NicSetSetting_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_NicSetSetting_MAC 設定ã™ã‚‹ MAC アドレスを指定ã—ã¾ã™ã€‚\nMAC アドレスã¯ã€6 ãƒã‚¤ãƒˆåˆ†ã® 16 進数を文字列ã§æŒ‡å®šã—ã¦ãã ã•ã„。\n例: 00:AC:01:23:45:67 ã¾ãŸã¯ 00-AC-01-23-45-67
+CMD_NicSetSetting_PROMPT_MAC 設定ã™ã‚‹ MAC アドレス:
+
+
+# NicEnable コマンド
+CMD_NicEnable 仮想 LAN カードã®æœ‰åŠ¹åŒ–
+CMD_NicEnable_Help 既存ã®ä»®æƒ³ LAN カードãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€æœ‰åŠ¹åŒ–ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicEnable_Args NicEnable [name]
+CMD_NicEnable_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# NicDisable コマンド
+CMD_NicDisable 仮想 LAN カードã®ç„¡åŠ¹åŒ–
+CMD_NicDisable_Help 既存ã®ä»®æƒ³ LAN カードãŒæœ‰åŠ¹åŒ–ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ç„¡åŠ¹åŒ–ã—ã¾ã™ã€‚\nã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€VPN Client ㌠Windows 2000 以é™ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§å‹•ä½œã—ã¦ã„ã‚‹å ´åˆã«ä½¿ç”¨ã§ãã¾ã™ã€‚
+CMD_NicDisable_Args NicDisable [name]
+CMD_NicDisable_[name] 仮想 LAN カードã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# NicList コマンド
+CMD_NicList 仮想 LAN カード一覧ã®å–å¾—
+CMD_NicList_Help ç¾åœ¨ã‚·ã‚¹ãƒ†ãƒ ã«ç™»éŒ²ã•ã‚Œã¦ã„る仮想 LAN カードã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚
+CMD_NicList_Args NicList
+
+
+# AccountList コマンド
+CMD_AccountList 接続設定一覧ã®å–å¾—
+CMD_AccountList_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定ã®ä¸€è¦§ã‚’å–å¾—ã—ã¾ã™ã€‚
+CMD_AccountList_Args AccountList
+
+
+# AccountCreate コマンド
+CMD_AccountCreate æ–°ã—ã„接続設定ã®ä½œæˆ
+CMD_AccountCreate_Help VPN Client ã«æ–°ã—ã„接続設定を作æˆã—ã¾ã™ã€‚\n接続設定を作æˆã™ã‚‹ã«ã¯ã€åˆæœŸãƒ‘ラメータã¨ã—ã¦æŽ¥ç¶šè¨­å®šã®åå‰ã¨æŽ¥ç¶šå…ˆã®ã‚µãƒ¼ãƒãƒ¼ã€ãŠã‚ˆã³æŽ¥ç¶šå…ˆã®ä»®æƒ³ HUBã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã«åŠ ãˆã¦ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードåを指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚æ–°ã—ã„接続設定を作æˆã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã¯ [匿åèªè¨¼] ã«åˆæœŸè¨­å®šã•ã‚Œã€ãƒ—ロキシサーãƒãƒ¼ã®è¨­å®šã¨ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã¯è¨­å®šã•ã‚Œã¾ã›ã‚“。ã“れらã®è¨­å®šã‚„ãã®ä»–ã®è©³ç´°è¨­å®šã‚’変更ã™ã‚‹ã«ã¯ã€æŽ¥ç¶šè¨­å®šã‚’作æˆã—ãŸå¾Œã«ã€"Account" ã¨ã„ã†åå‰ã§å§‹ã¾ã‚‹ä»–ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚
+CMD_AccountCreate_Args AccountCreate [name] [/SERVER:hostname:port] [/HUB:hubname] [/USERNAME:username] [/NICNAME:nicname]
+CMD_AccountCreate_[name] 作æˆã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountCreate_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ã€ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚IP アドレスã§æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_AccountCreate_HUB 接続先㮠VPN Server 内ã®ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚
+CMD_AccountCreate_USERNAME 接続先㮠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã§ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_AccountCreate_NICNAME 接続ã«ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードåを指定ã—ã¾ã™ã€‚
+CMD_AccountCreate_Prompt_Name 接続設定ã®åå‰:
+CMD_AccountCreate_Prompt_Server 接続先 VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+CMD_AccountCreate_Prompt_Hub 接続先仮想 HUB å:
+CMD_AccountCreate_Prompt_Username 接続ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼å:
+CMD_AccountCreate_Prompt_Nicname 使用ã™ã‚‹ä»®æƒ³ LAN カードå:
+
+
+# AccountSet コマンド
+CMD_AccountSet 接続設定ã®æŽ¥ç¶šå…ˆã®è¨­å®š
+CMD_AccountSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定ã®ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ä»®æƒ³ HUB åã€ãŠã‚ˆã³æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã«åŠ ãˆã¦ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードåを設定ã—ã¾ã™ã€‚
+CMD_AccountSet_Args AccountSet [name] [/SERVER:hostname:port] [/HUB:hubname]
+CMD_AccountSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountSet_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€æŽ¥ç¶šå…ˆã® VPN Server ã®ãƒ›ã‚¹ãƒˆåã¨ã€ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚IP アドレスã§æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_AccountSet_HUB 接続先㮠VPN Server 内ã®ä»®æƒ³ HUB を指定ã—ã¾ã™ã€‚
+
+
+# AccountGet コマンド
+CMD_AccountGet 接続設定ã®è¨­å®šã®å–å¾—
+CMD_AccountGet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定ã®æŽ¥ç¶šè¨­å®šå†…容をå–å¾—ã—ã¾ã™ã€‚\nãªãŠã€æŽ¥ç¶šè¨­å®šã®æŽ¥ç¶šè¨­å®šå†…容を変更ã™ã‚‹ã«ã¯ã€æŽ¥ç¶šè¨­å®šã‚’作æˆã—ãŸå¾Œã«ã€"Account" ã¨ã„ã†åå‰ã§å§‹ã¾ã‚‹ä»–ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚
+CMD_AccountGet_Args AccountGet [name]
+CMD_AccountGet_[name] 設定をå–å¾—ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountDelete コマンド
+CMD_AccountDelete 接続設定ã®å‰Šé™¤
+CMD_AccountDelete_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を削除ã—ã¾ã™ã€‚指定ã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ…‹ã§ã‚ã‚‹å ´åˆã¯ã€è‡ªå‹•çš„ã«æŽ¥ç¶šã‚’切断ã—ã¦ã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚
+CMD_AccountDelete_Args AccountDelete [name]
+CMD_AccountDelete_[name] 削除ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountUsernameSet コマンド
+CMD_AccountUsernameSet 接続設定ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®è¨­å®š
+CMD_AccountUsernameSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¿…è¦ãªãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚\nãªãŠã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’指定ã—ãŸã‚Šã€å¿…è¦ãªãƒ‘ラメータを指定ã—ãŸã‚Šã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“れらã®æƒ…報を変更ã™ã‚‹ã«ã¯ã€AccountAnonymousSetã€AccountPasswordSetã€AccountCertSetã€AccountSecureCertSet ãªã©ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¾ã™ã€‚
+CMD_AccountUsernameSet_Args AccountUsernameSet [name] [/USERNAME:username]
+CMD_AccountUsernameSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountUsernameSet_USERNAME 接続設定㌠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã«å¿…è¦ãªãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚
+CMD_AccountUsername_Notice ã“ã®æŽ¥ç¶šè¨­å®šã®èªè¨¼æ–¹æ³•ã¯ã€ç¾åœ¨ãƒ‘スワードèªè¨¼ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚ユーザーåを変更ã—ãŸå¾Œã€AccountPasswordSet コマンドã§ãƒ‘スワードを設定ã—ç›´ã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+
+# AccountAnonymousSet コマンド
+CMD_AccountAnonymousSet 接続設定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’匿åèªè¨¼ã«è¨­å®š
+CMD_AccountAnonymousSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ã€[匿åèªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚
+CMD_AccountAnonymousSet_Args AccountAnonymousSet [name]
+CMD_AccountAnonymousSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountPasswordSet コマンド
+CMD_AccountPasswordSet 接続設定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’パスワードèªè¨¼ã«è¨­å®š
+CMD_AccountPasswordSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ã€[パスワードèªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚パスワードèªè¨¼ã®ç¨®é¡žã«ã¯ã€[標準パスワードèªè¨¼] 㨠[RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼] を指定ã—ã¾ã™ã€‚
+CMD_AccountPasswordSet_Args AccountPasswordSet [name] [/PASSWORD:password] [/TYPE:standard|radius]
+CMD_AccountPasswordSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountPasswordSet_PASSWORD パスワードèªè¨¼ã§ä½¿ç”¨ã™ã‚‹ãƒ‘スワードを指定ã—ã¾ã™ã€‚指定ã—ãªã„å ´åˆã¯ã€ãƒ‘スワードを入力ã™ã‚‹ãŸã‚ã®ãƒ—ロンプトãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+CMD_AccountPasswordSet_TYPE パスワードèªè¨¼ã®ç¨®é¡žã¨ã—ã¦ã€"standard" (標準パスワードèªè¨¼) ã¾ãŸã¯ "radius" (RADIUS ã¾ãŸã¯ NT ドメインèªè¨¼) ã®ã€ã©ã¡ã‚‰ã‹ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountPasswordSet_Prompt_Type standard ã¾ãŸã¯ radius ã®æŒ‡å®š:
+CMD_AccountPasswordSet_Type_Invalid standard ã¾ãŸã¯ radius ã®æŒ‡å®šãŒä¸æ­£ã§ã™ã€‚
+
+
+# AccountCertSet コマンド
+CMD_AccountCertSet 接続設定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’クライアント証明書èªè¨¼ã«è¨­å®š
+CMD_AccountCertSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ã€[クライアント証明書èªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚証明書ã¨ã—ã¦ã¯ã€X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã€Base 64 ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸå¯¾å¿œã—ãŸç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountCertSet_Args AccountCertSet [name] [/LOADCERT:cert] [/LOADKEY:key]
+CMD_AccountCertSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountCertSet_LOADCERT 証明書èªè¨¼ã§æ示ã™ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_AccountCertSet_LOADKEY 証明書ã«å¯¾å¿œã—㟠Base 64 å½¢å¼ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# AccountCertGet コマンド
+CMD_AccountCertGet 接続設定ã«ç”¨ã„るクライアント証明書ã®å–å¾—
+CMD_AccountCertGet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸èªè¨¼ã‚’使用ã™ã‚‹å ´åˆã¯ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã¨ã—ã¦æ示ã™ã‚‹è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã¦ã€è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã—ã¾ã™ã€‚
+CMD_AccountCertGet_Args AccountCertGet [name] [/SAVECERT:cert]
+CMD_AccountCertGet_[name] 設定をå–å¾—ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountCertGet_SAVECERT å–å¾—ã—ãŸè¨¼æ˜Žæ›¸ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# AccountEncryptEnable コマンド
+CMD_AccountEncryptEnable 接続設定ã®é€šä¿¡æ™‚ã®æš—å·åŒ–ã®æœ‰åŠ¹åŒ–
+CMD_AccountEncryptEnable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を SSL ã§æš—å·åŒ–ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚\n通常ã¯ã€VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã—ã¦ã€æƒ…å ±ã®ç›—è´ã‚„改ã–んを防止ã—ã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã¨ã€é€šä¿¡ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ãŒã€é€šä¿¡ãƒ‡ãƒ¼ã‚¿ã¯å¹³æ–‡ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚Œã¾ã™ã€‚
+CMD_AccountEncryptEnable_Args AccountEncryptEnable [name]
+CMD_AccountEncryptEnable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountEncryptDisable コマンド
+CMD_AccountEncryptDisable 接続設定ã®é€šä¿¡æ™‚ã®æš—å·åŒ–ã®ç„¡åŠ¹åŒ–
+CMD_AccountEncryptDisable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を暗å·åŒ–ã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚\n通常ã¯ã€VPN Server ã¨ã®é–“ã®é€šä¿¡ã‚’ SSL ã§æš—å·åŒ–ã—ã¦ã€æƒ…å ±ã®ç›—è´ã‚„改ã–んを防止ã—ã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚æš—å·åŒ–を無効ã«ã™ã‚‹ã¨ã€é€šä¿¡ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ãŒã€é€šä¿¡ãƒ‡ãƒ¼ã‚¿ã¯å¹³æ–‡ã§ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚Œã¾ã™ã€‚
+CMD_AccountEncryptDisable_Args AccountEncryptDisable [name]
+CMD_AccountEncryptDisable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountCompressEnable コマンド
+CMD_AccountCompressEnable 接続設定ã®é€šä¿¡æ™‚ã®ãƒ‡ãƒ¼ã‚¿åœ§ç¸®ã®æœ‰åŠ¹åŒ–
+CMD_AccountCompressEnable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を圧縮ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚\n最大ã§ç´„ 80 % 程度ã®åœ§ç¸®ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã ã—ã€åœ§ç¸®ã‚’è¡Œã†ã¨ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŠã‚ˆã³ã‚µãƒ¼ãƒãƒ¼ã®ä¸¡æ–¹ã§ CPU è² è·ãŒé«˜ããªã‚Šã¾ã™ã€‚回線速度ãŒç´„ 10 Mbps 以上ã®å ´åˆã¯ã€åœ§ç¸®ã‚’è¡Œã†ã¨ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒä½Žä¸‹ã—ã€é€†åŠ¹æžœã¨ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountCompressEnable_Args AccountCompressEnable [name]
+CMD_AccountCompressEnable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountCompressDisable コマンド
+CMD_AccountCompressDisable 接続設定ã®é€šä¿¡æ™‚ã®ãƒ‡ãƒ¼ã‚¿åœ§ç¸®ã®ç„¡åŠ¹åŒ–
+CMD_AccountCompressDisable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¨ã®é–“㧠VPN 接続を行ãªã£ã¦é€šä¿¡ã‚’ã™ã‚‹éš›ã«ã€VPN Server ã¨ã®é–“ã®é€šä¿¡å†…容を圧縮ã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚
+CMD_AccountCompressDisable_Args AccountCompressDisable [name]
+CMD_AccountCompressDisable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountProxyNone コマンド
+CMD_AccountProxyNone 接続設定ã®æŽ¥ç¶šæ–¹æ³•ã‚’直接 TCP/IP 接続ã«è¨­å®š
+CMD_AccountProxyNone_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [直接 TCP/IP 接続] ã«è¨­å®šã—ã€ãƒ—ロキシサーãƒãƒ¼ã‚’経由ã—ãªã„よã†ã«ã—ã¾ã™ã€‚
+CMD_AccountProxyNone_Args AccountProxyNone [name]
+CMD_AccountProxyNone_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountProxyHttp コマンド
+CMD_AccountProxyHttp 接続設定ã®æŽ¥ç¶šæ–¹æ³•ã‚’ HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶šã«è¨­å®š
+CMD_AccountProxyHttp_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [HTTP プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š] ã«è¨­å®šã—ã€çµŒç”±ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワード (å¿…è¦ãªå ´åˆ) を指定ã—ã¾ã™ã€‚\n経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã¯ã€HTTPS 通信をã™ã‚‹ãŸã‚ã® CONNECT メソッドã«å¯¾å¿œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountProxyHttp_Args AccountProxyHttp [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxyHttp_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountProxyHttp_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€çµŒç”±ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountProxyHttp_USERNAME 経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚ã¾ãŸã€åŒæ™‚ã« /PASSWORD パラメータも指定ã—ã¾ã™ã€‚/USERNAME 㨠/PASSWORD パラメータãŒæŒ‡å®šã•ã‚Œãªã„å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãƒ‡ãƒ¼ã‚¿ã‚’設定ã—ã¾ã›ã‚“。
+CMD_AccountProxyHttp_PASSWORD 経由ã™ã‚‹ HTTP プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ‘スワードを指定ã—ã¾ã™ã€‚/USERNAME パラメータã¨å…±ã«æŒ‡å®šã—ã¾ã™ã€‚
+CMD_AccountProxyHttp_Prompt_Server プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·:
+
+
+
+# AccountProxySocks コマンド
+CMD_AccountProxySocks 接続設定ã®æŽ¥ç¶šæ–¹æ³•ã‚’ SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶šã«è¨­å®š
+CMD_AccountProxySocks_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ä½¿ç”¨ã™ã‚‹æŽ¥ç¶šæ–¹æ³•ã‚’ [SOCKS プロキシサーãƒãƒ¼çµŒç”±æŽ¥ç¶š] ã«è¨­å®šã—ã€çµŒç”±ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ãƒãƒ¼ãƒˆç•ªå·ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワード (å¿…è¦ãªå ´åˆ) を指定ã—ã¾ã™ã€‚\n経由ã™ã‚‹ SOCKS サーãƒãƒ¼ã¯ã€SOCKS ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 4 ã«å¯¾å¿œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountProxySocks_Args AccountProxySocks [name] [/SERVER:hostname:port] [/USERNAME:username] [/PASSWORD:password]
+CMD_AccountProxySocks_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountProxySocks_SERVER [ホストå:ãƒãƒ¼ãƒˆç•ªå·] ã®å½¢å¼ã§ã€çµŒç”±ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountProxySocks_USERNAME 経由ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åを指定ã—ã¾ã™ã€‚ã¾ãŸã€åŒæ™‚ã« /PASSWORD パラメータも指定ã—ã¾ã™ã€‚/USERNAME 㨠/PASSWORD パラメータãŒæŒ‡å®šã•ã‚Œãªã„å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãƒ‡ãƒ¼ã‚¿ã‚’設定ã—ã¾ã›ã‚“。
+CMD_AccountProxySocks_PASSWORD 経由ã™ã‚‹ SOCKS プロキシサーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ãŒå¿…è¦ãªå ´åˆã€ãƒ‘スワードを指定ã—ã¾ã™ã€‚/USERNAME パラメータã¨å…±ã«æŒ‡å®šã—ã¾ã™ã€‚
+
+
+# AccountServerCertEnable コマンド
+CMD_AccountServerCertEnable 接続設定ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã®æœ‰åŠ¹åŒ–
+CMD_AccountServerCertEnable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ãŒä¿¡é ¼ã§ãã‚‹ã‹ã©ã†ã‹æ¤œæŸ»ã™ã‚‹ã‚ªãƒ—ションを有効ã«ã—ã¾ã™ã€‚\nã“ã®ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書をã€ã‚らã‹ã˜ã‚ AccountServerCertSet コマンドã§æŽ¥ç¶šè¨­å®šè¨­å®šå†…ã«ä¿å­˜ã—ã¦ãŠãã‹ã€ã¾ãŸã¯ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€ã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書を署åã—ãŸãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã‚’ CertAdd コマンドãªã©ã§ç™»éŒ²ã—ã¦ãŠãã“ã¨ã‚’推奨ã—ã¾ã™ã€‚登録ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€åˆå›žæŽ¥ç¶šæ™‚ã«ç¢ºèªã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\n接続設定ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„る状態ã§ã€æŽ¥ç¶šã—㟠VPN Server ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ããªã„å ´åˆã€ç›´ã¡ã«æŽ¥ç¶šã‚’解除ã—ã¦å†è©¦è¡Œã‚’ç¹°ã‚Šè¿”ã—ã¾ã™ã€‚
+CMD_AccountServerCertEnable_Args AccountServerCertEnable [name]
+CMD_AccountServerCertEnable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountServerCertDisable コマンド
+CMD_AccountServerCertDisable 接続設定ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションã®ç„¡åŠ¹åŒ–
+CMD_AccountServerCertDisable_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ãŒä¿¡é ¼ã§ãã‚‹ã‹ã©ã†ã‹æ¤œæŸ»ã™ã‚‹ã‚ªãƒ—ションを無効ã«ã—ã¾ã™ã€‚
+CMD_AccountServerCertDisable_Args AccountServerCertDisable [name]
+CMD_AccountServerCertDisable_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountServerCertSet コマンド
+CMD_AccountServerCertSet 接続設定ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®è¨­å®š
+CMD_AccountServerCertSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šå…ˆã® VPN Server ã®æ示ã™ã‚‹ SSL 証明書ã¨åŒã˜è¨¼æ˜Žæ›¸ã‚’ã‚らã‹ã˜ã‚登録ã—ã¾ã™ã€‚\n接続設定ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€æŽ¥ç¶šå…ˆã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書をã‚らã‹ã˜ã‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§æŽ¥ç¶šè¨­å®šè¨­å®šå†…ã«ä¿å­˜ã—ã¦ãŠãã‹ã€ã¾ãŸã¯ä»®æƒ³ HUB ã®ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ©Ÿé–¢ã®è¨¼æ˜Žæ›¸ä¸€è¦§ã«ã€ã‚µãƒ¼ãƒãƒ¼ã® SSL 証明書を署åã—ãŸãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ã‚’ CAAdd コマンドãªã©ã§ç™»éŒ²ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n接続設定ã®ã‚µãƒ¼ãƒãƒ¼è¨¼æ˜Žæ›¸ã®æ¤œè¨¼ã‚ªãƒ—ションãŒæœ‰åŠ¹ã«ãªã£ã¦ã„る状態ã§ã€æŽ¥ç¶šã—㟠VPN Server ã®è¨¼æ˜Žæ›¸ãŒä¿¡é ¼ã§ããªã„å ´åˆã€ç›´ã¡ã«æŽ¥ç¶šã‚’解除ã—ã¦å†è©¦è¡Œã‚’ç¹°ã‚Šè¿”ã—ã¾ã™ã€‚
+CMD_AccountServerCertSet_Args AccountServerCertSet [name] [/LOADCERT:cert]
+CMD_AccountServerCertSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountServerCertSet_LOADCERT 設定ã™ã‚‹ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒä¿å­˜ã•ã‚Œã¦ã„ã‚‹ã€X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# AccountServerCertDelete コマンド
+CMD_AccountServerCertDelete 接続設定ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®å‰Šé™¤
+CMD_AccountServerCertDelete_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã«ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãれを削除ã—ã¾ã™ã€‚
+CMD_AccountServerCertDelete_Args AccountServerCertDelete [name]
+CMD_AccountServerCertDelete_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountServerCertGet コマンド
+CMD_AccountServerCertGet 接続設定ã®ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã®å–å¾—
+CMD_AccountServerCertGet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã«ã‚µãƒ¼ãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ãã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã—ã¦ã€X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚
+CMD_AccountServerCertGet_Args AccountServerCertGet [name] [/SAVECERT:path]
+CMD_AccountServerCertGet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountServerCertGet_SAVECERT サーãƒãƒ¼å›ºæœ‰è¨¼æ˜Žæ›¸ã‚’ X.509 å½¢å¼ã§ä¿å­˜ã™ã‚‹è¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+
+
+# AccountDetailSet コマンド
+CMD_AccountDetailSet 接続設定ã®é«˜åº¦ãªé€šä¿¡è¨­å®šã®è¨­å®š
+CMD_AccountDetailSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¨é€šä¿¡ã™ã‚‹éš›ã«ä½¿ç”¨ã•ã‚Œã‚‹ VPN プロトコルã®é€šä¿¡è¨­å®šã‚’カスタマイズã—ã¾ã™ã€‚
+CMD_AccountDetailSet_Args AccountDetailSet [name] [/MAXTCP:max_connection] [/INTERVAL:additional_interval] [/TTL:disconnect_span] [/HALF:yes|no] [/BRIDGE:yes|no] [/MONITOR:yes|no] [/NOTRACK:yes|no] [/NOQOS:yes|no]
+CMD_AccountDetailSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_MAXTCP VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã‚’ã€1 以上 32 以下ã®æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚VPN Server ã¨ã®é–“ã® VPN 通信セッションã«ãŠã‘るデータä¼é€ã«ã€è¤‡æ•°æœ¬ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€é€šä¿¡é€Ÿåº¦ã‚’å‘上ã§ãã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\n注æ„: サーãƒãƒ¼ã¸ã®æŽ¥ç¶šå›žç·šãŒé«˜é€Ÿãªå ´åˆã¯ 8 本程度をã€ãƒ€ã‚¤ãƒ¤ãƒ«ã‚¢ãƒƒãƒ—ç­‰ã®ä½Žé€Ÿãªå ´åˆã¯ 1 本をãŠå‹§ã‚ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_INTERVAL 複数㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’確立ã—㦠VPN 通信を行ã†ã¨ãã€å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“隔を秒å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚è¦å®šå€¤ã¯ 1 秒ã§ã™ã€‚
+CMD_AccountDetailSet_TTL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ã‚’設定ã™ã‚‹å ´åˆã¯ã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ãŒç¢ºç«‹ã•ã‚Œã¦ã‹ã‚‰åˆ‡æ–­ã•ã‚Œã‚‹ã¾ã§ã®å¯¿å‘½ã‚’ã€ç§’æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚0 を指定ã™ã‚‹ã¨ã€å¯¿å‘½ã¯è¨­å®šã•ã‚Œã¾ã›ã‚“。
+CMD_AccountDetailSet_HALF åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚2 本以上㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’æŸã­ã¦ VPN 通信を行ã†éš›ã€ã€ŒåŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã€ã‚’使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€è‡ªå‹•çš„ã«å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ãƒ‡ãƒ¼ã‚¿ä¼é€æ–¹å‘ã‚’ã€åŠæ•°ãšã¤å›ºå®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã¨ãˆã°ã€8 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’使用ã—㦠VPN セッションを確立ã—ãŸå ´åˆã€åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ã¨ã€4 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ã‚¢ãƒƒãƒ—ロード方å‘専用ã€æ®‹ã‚Šã® 4 本ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰æ–¹å‘専用ã«å›ºå®šã•ã‚Œé€šä¿¡ãŒè¡Œã‚ã‚Œã¾ã™ã€‚
+CMD_AccountDetailSet_BRIDGE VPN Server ã«ã€Œãƒ–リッジ / ルータモードã€ã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚ブリッジ / ルータモードを使用ã—ã¦æŽ¥ç¶šã—ãŸå ´åˆã€VPN Client ã®ä»®æƒ³ LAN カードã®å´ã§ã€åˆ¥ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ãƒ–リッジã—ãŸã‚Šãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ãŸã ã—ã€æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã§ã€ãƒ–リッジã¾ãŸã¯ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãŒç¦æ­¢ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_MONITOR VPN Server ã«ã€Œãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ãƒ¢ãƒ¼ãƒ‰ã€ã§æŽ¥ç¶šã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚モニタリングモードを使用ã—ã¦æŽ¥ç¶šã—ãŸå ´åˆã€ä»®æƒ³ HUB 内をæµã‚Œã‚‹ã™ã¹ã¦ã®ãƒ‘ケットをå—ä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã ã—ã€æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒãƒªã‚·ãƒ¼ã§ã€ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ãƒ¢ãƒ¼ãƒ‰ãŒè¨±å¯ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_NOTRACK ルーティングテーブルã®èª¿æ•´å‡¦ç†ã‚’è¡Œã‚ãªã„å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚通常㯠"no" を指定ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_NOQOS VoIP / QoS 対応機能を無効ã«ã™ã‚‹å ´åˆã¯ "yes" を指定ã—ã¾ã™ã€‚通常㯠"no" を指定ã—ã¾ã™ã€‚
+CMD_AccountDetailSet_Eval_MaxTcp TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã¯ 1 ã‹ã‚‰ 32 ã®é–“ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_AccountDetailSet_Eval_Interval TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“隔㯠1 秒以上を指定ã—ã¦ãã ã•ã„。
+CMD_AccountDetailSet_Prompt_MaxTcp VPN 通信ã«ä½¿ç”¨ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°:
+CMD_AccountDetailSet_Prompt_Interval å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ç¢ºç«‹é–“éš”:
+CMD_AccountDetailSet_Prompt_TTL å„ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®å¯¿å‘½ (0 ã§ç„¡ã—):
+CMD_AccountDetailSet_Prompt_HALF åŠäºŒé‡ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã™ã‚‹ (yes/no):
+CMD_AccountDetailSet_Prompt_BRIDGE ブリッジ/ルータモードを有効ã«ã™ã‚‹ (yes/no):
+CMD_AccountDetailSet_Prompt_MONITOR モニタリングモードを有効ã«ã™ã‚‹ (yes/no):
+CMD_AccountDetailSet_Prompt_NOTRACK ルーティングテーブル調整処ç†ã‚’無効化ã™ã‚‹ (yes/no):
+CMD_AccountDetailSet_Prompt_NOQOS QoS 制御機能を無効化ã™ã‚‹ (yes/no):
+
+
+# AccountRename コマンド
+CMD_AccountRename 接続設定ã®åå‰ã®å¤‰æ›´
+CMD_AccountRename_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã®åå‰ã‚’変更ã—ã¾ã™ã€‚
+CMD_AccountRename_Args AccountRename [name] [/NEW:new_name]
+CMD_AccountRename_[name] åå‰ã‚’変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®ç¾åœ¨ã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountRename_NEW 変更後ã®æ–°ã—ã„åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountRename_PROMPT_OLD ç¾åœ¨ã®åå‰:
+CMD_AccountRename_PROMPT_NEW æ–°ã—ã„åå‰:
+
+
+# AccountConnect コマンド
+CMD_AccountConnect 接続設定を使用ã—㦠VPN Server ã¸æŽ¥ç¶šã‚’開始
+CMD_AccountConnect_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã‚’使用ã—㦠VPN Server ã¸ã®æŽ¥ç¶šã‚’開始ã—ã¾ã™ã€‚接続処ç†ä¸­ã€ã¾ãŸã¯æŽ¥ç¶šæ¸ˆã¿ã®çŠ¶æ…‹ã«ãªã£ãŸæŽ¥ç¶šè¨­å®šã¯ã€AccountDisconnect コマンドã§åˆ‡æ–­ã™ã‚‹ã¾ã§ VPN Server ã«å¸¸æ™‚接続ã€ã¾ãŸã¯æŽ¥ç¶šã‚’試行ã—続ã‘ã¾ã™ (ãŸã ã— AccountRetrySet コマンドã§å†è©¦è¡Œå›žæ•°ã‚’指定ã—ã¦ã‚ã‚‹å ´åˆã¯ã€æŒ‡å®šã•ã‚ŒãŸå›žæ•°ã§è©¦è¡Œã‚’中断ã—ã¾ã™)。
+CMD_AccountConnect_Args AccountConnect [name]
+CMD_AccountConnect_[name] 接続を開始ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountDisconnect コマンド
+CMD_AccountDisconnect 接続中ã®æŽ¥ç¶šè¨­å®šã®åˆ‡æ–­
+CMD_AccountDisconnect_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒæŽ¥ç¶šå‡¦ç†ä¸­ã€ã¾ãŸã¯æŽ¥ç¶šæ¸ˆã¿ã®çŠ¶æ…‹ã§ã‚ã‚‹å ´åˆã¯ç›´ã¡ã«åˆ‡æ–­ã—ã¾ã™ã€‚
+CMD_AccountDisconnect_Args AccountDisconnect [name]
+CMD_AccountDisconnect_[name] 切断ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountStatusGet コマンド
+CMD_AccountStatusGet 接続設定ã®ç¾åœ¨ã®çŠ¶æ…‹ã®å–å¾—
+CMD_AccountStatusGet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒç¾åœ¨æŽ¥ç¶šæ¸ˆã¿ã§ã‚ã‚‹å ´åˆã¯ã€ãã®æŽ¥ç¶šçŠ¶æ…‹ã‚„ãã®ä»–ã®æƒ…報をå–å¾—ã—ã¾ã™ã€‚
+CMD_AccountStatusGet_Args AccountStatusGet [name]
+CMD_AccountStatusGet_[name] 情報をå–å¾—ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountNicSet コマンド
+CMD_AccountNicSet 接続設定ã§ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードã®è¨­å®š
+CMD_AccountNicSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る既存ã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードåを変更ã—ã¾ã™ã€‚
+CMD_AccountNicSet_Args AccountNicSet [name] [/NICNAME:nicname]
+CMD_AccountNicSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountNicSet_NICNAME VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã«ä½¿ç”¨ã™ã‚‹ä»®æƒ³ LAN カードåを指定ã—ã¾ã™ã€‚
+
+
+# AccountStatusShow コマンド
+CMD_AccountStatusShow VPN Server ã¸ã®æŽ¥ç¶šä¸­ã«æŽ¥ç¶šçŠ¶æ³ã‚„エラー画é¢ã‚’表示ã™ã‚‹ã‚ˆã†ã«è¨­å®š
+CMD_AccountStatusShow_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã‚’用ã„㦠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šçŠ¶æ³ã‚„エラー画é¢ãªã©ã‚’コンピュータã®ãƒ‡ã‚£ã‚¹ãƒ—レイ上ã«è¡¨ç¤ºã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã¾ã™ã€‚
+CMD_AccountStatusShow_Args AccountStatusShow [name]
+CMD_AccountStatusShow_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountStatusHide コマンド
+CMD_AccountStatusHide VPN Server ã¸ã®æŽ¥ç¶šä¸­ã«æŽ¥ç¶šçŠ¶æ³ã‚„エラー画é¢ã‚’表示ã—ãªã„よã†ã«è¨­å®š
+CMD_AccountStatusHide_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã‚’用ã„㦠VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã«ã€æŽ¥ç¶šçŠ¶æ³ã‚„エラー画é¢ãªã©ã‚’コンピュータã®ãƒ‡ã‚£ã‚¹ãƒ—レイ上ã«è¡¨ç¤ºã—ãªã„よã†ã«è¨­å®šã—ã¾ã™ã€‚
+CMD_AccountStatusHide_Args AccountStatusHide [name]
+CMD_AccountStatusHide_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountSecureCertSet コマンド
+CMD_AccountSecureCertSet 接続設定ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žã‚’スマートカードèªè¨¼ã«è¨­å®š
+CMD_AccountSecureCertSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã™ã‚‹éš›ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®æ–¹æ³•ã‚’ [スマートカードèªè¨¼] ã«è¨­å®šã—ã¾ã™ã€‚ã¾ãŸã€ã‚¹ãƒžãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰å†…ã«æ ¼ç´ã•ã‚Œã¦ã„る証明書オブジェクトã¨ç§˜å¯†éµã‚ªãƒ–ジェクトã®åå‰ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountSecureCertSet_Args AccountSecureCertSet [name] [/CERTNAME:cert] [/KEYNAME:key]
+CMD_AccountSecureCertSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountSecureCertSet_CERTNAME スマートカード内ã«æ ¼ç´ã•ã‚Œã¦ã„る証明書オブジェクトã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountSecureCertSet_KEYNAME スマートカード内ã«æ ¼ç´ã•ã‚Œã¦ã„る秘密éµã‚ªãƒ–ジェクトã®åå‰ã‚’指定ã—ã¾ã™ã€‚/CERTNAME ã§æŒ‡å®šã—ãŸè¨¼æ˜Žæ›¸ã«å¯¾å¿œã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_AccountSecureCertSet_PROMPT_CERTNAME スマートカード内証明書オブジェクトã®åå‰:
+CMD_AccountSecureCertSet_PROMPT_KEYNAME スマートカード内秘密éµã‚ªãƒ–ジェクトã®åå‰:
+
+
+# AccountRetrySet コマンド
+CMD_AccountRetrySet 接続設定ã®æŽ¥ç¶šå¤±æ•—ã¾ãŸã¯åˆ‡æ–­æ™‚ã®å†è©¦è¡Œå›žæ•°ã¨é–“éš”ã®è¨­å®š
+CMD_AccountRetrySet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒ VPN Server ã«æŽ¥ç¶šã—よã†ã¨ã™ã‚‹éš›ã€ã¾ãŸã¯æŽ¥ç¶šä¸­ã« VPN Server ã¨ã®é€šä¿¡ãŒåˆ‡æ–­ã•ã‚ŒãŸã‚Šã€æŽ¥ç¶šã«å¤±æ•—ã—ãŸã‚Šã—ãŸå ´åˆã«ã€æŽ¥ç¶šã‚’å†è©¦è¡Œã™ã‚‹å›žæ•°ã¨æŽ¥ç¶šå†è©¦è¡Œé–“隔を指定ã—ã¾ã™ã€‚\nãªãŠã€ãƒ¦ãƒ¼ã‚¶ãƒ¼èªè¨¼ã®ç¨®é¡žãŒ [スマートカードèªè¨¼] ã®å ´åˆã¯ã€æŽ¥ç¶šè©¦è¡Œå›žæ•°ã®è¨­å®šã«ã‹ã‹ã‚らãšã€å†è©¦è¡Œã¯è¡Œã„ã¾ã›ã‚“。
+CMD_AccountRetrySet_Args AccountRetrySet [name] [/NUM:num_retry] [/INTERVAL:retry_interval]
+CMD_AccountRetrySet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+CMD_AccountRetrySet_NUM 連続ã—ã¦å†æŽ¥ç¶šã‚’è¡Œã†å›žæ•°ã‚’指定ã—ã¾ã™ã€‚"999" ã¨æŒ‡å®šã™ã‚‹ã¨ã€ç„¡é™ã«å†æŽ¥ç¶šã‚’試行ã—ã¾ã™ (常時接続)。0 を指定ã™ã‚‹ã¨å†æŽ¥ç¶šã‚’è¡Œã„ã¾ã›ã‚“。
+CMD_AccountRetrySet_INTERVAL å†æŽ¥ç¶šã‚’è¡Œã†å ´åˆã€å‰å›žæŽ¥ç¶šãŒåˆ‡æ–­ã¾ãŸã¯æŽ¥ç¶šå¤±æ•—ã—ã¦ã‹ã‚‰ã€ä½•ç§’後ã«å†æŽ¥ç¶šå‡¦ç†ã‚’開始ã™ã‚‹ã‹ã‚’設定ã—ã¾ã™ã€‚
+CMD_AccountRetrySet_PROMPT_NUM å†æŽ¥ç¶šå›žæ•° ("999" ã§ç„¡é™):
+CMD_AccountRetrySet_PROMPY_INTERVAL å†æŽ¥ç¶šé–“éš” (秒):
+CMD_AccountRetrySet_EVAL_INTERVAL å†æŽ¥ç¶šé–“隔㯠5 秒以上ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+
+
+# AccountStartupSet コマンド
+CMD_AccountStartupSet 接続設定をスタートアップ接続ã«è¨­å®š
+CMD_AccountStartupSet_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã‚’スタートアップ接続ã«è¨­å®šã—ã¾ã™ã€‚スタートアップ接続ã«è¨­å®šã•ã‚Œã¦ã„る接続設定ã¯ã€VPN Client サービスãŒèµ·å‹•ã™ã‚‹ã¨åŒæ™‚ã«è‡ªå‹•çš„ã«æŽ¥ç¶šå‡¦ç†ã‚’開始ã—ã¾ã™ã€‚
+CMD_AccountStartupSet_Args AccountStartupSet [name]
+CMD_AccountStartupSet_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountStartupRemove コマンド
+CMD_AccountStartupRemove 接続設定ã®ã‚¹ã‚¿ãƒ¼ãƒˆã‚¢ãƒƒãƒ—接続を解除
+CMD_AccountStartupRemove_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šãŒç¾åœ¨ã‚¹ã‚¿ãƒ¼ãƒˆã‚¢ãƒƒãƒ—接続ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ã‚¹ã‚¿ãƒ¼ãƒˆã‚¢ãƒƒãƒ—接続設定を解除ã—ã¾ã™ã€‚
+CMD_AccountStartupRemove_Args AccountStartupRemove [name]
+CMD_AccountStartupRemove_[name] 設定を変更ã™ã‚‹æŽ¥ç¶šè¨­å®šã®åå‰ã‚’指定ã—ã¾ã™ã€‚
+
+
+# AccountExport コマンド
+CMD_AccountExport 接続設定ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ
+CMD_AccountExport_Help VPN Client ã«ç™»éŒ²ã•ã‚Œã¦ã„る接続設定を指定ã—ã€ãã®æŽ¥ç¶šè¨­å®šã®å†…容をã€ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚エクスãƒãƒ¼ãƒˆã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’後ã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€æŽ¥ç¶šè¨­å®šã®å†…容を複製ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã§ä¿å­˜ã•ã‚Œã‚‹ãŸã‚ã€ä¸€èˆ¬çš„ãªãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ã§ç·¨é›†ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚\nエクスãƒãƒ¼ãƒˆå…ˆã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€UTF-8 å½¢å¼ã®ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚ãªãŠã€ãƒ•ã‚¡ã‚¤ãƒ«åã« .vpn ã¨ã„ã†æ‹¡å¼µå­ã‚’付ã‘ã‚‹ã¨ã€Windows 版 VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã¨é–¢é€£ä»˜ã‘ã•ã‚Œã‚‹ã®ã§ä¾¿åˆ©ã§ã™ã€‚
+CMD_AccountExport_Args AccountExport [name] [/SAVEPATH:savepath]
+CMD_AccountExport_[name] 接続設定をエクスãƒãƒ¼ãƒˆã™ã‚‹æŽ¥ç¶šè¨­å®šåを指定ã—ã¾ã™ã€‚
+CMD_AccountExport_SAVEPATH ä¿å­˜å…ˆã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_AccountExport_PROMPT_SAVEPATH ä¿å­˜å…ˆãƒ•ã‚¡ã‚¤ãƒ«å (æ‹¡å¼µå­ã¯ .vpn を推奨):
+
+
+# AccountImport コマンド
+CMD_AccountImport 接続設定ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ
+CMD_AccountImport_Help AccountExport コマンドã«ã‚ˆã£ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã•ã‚ŒãŸæŽ¥ç¶šè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’インãƒãƒ¼ãƒˆã—ã€VPN Client ã«è¿½åŠ ã—ã¾ã™ã€‚
+CMD_AccountImport_Args AccountImport [path]
+CMD_AccountImport_[path] インãƒãƒ¼ãƒˆå…ƒã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚
+CMD_AccountImport_PROMPT_PATH インãƒãƒ¼ãƒˆå…ƒãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_AccountImport_FAILED_PARSE 指定ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ­£ã—ã解æžã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚æ­£ã—ãエクスãƒãƒ¼ãƒˆã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。
+CMD_AccountImport_OK 接続設定 "%s" ã¨ã—ã¦ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã—ãŸã€‚
+
+
+
+# RemoteEnable コマンド
+CMD_RemoteEnable VPN Client サービスã®ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã®è¨±å¯
+CMD_RemoteEnable_Help VPN Client サービスã«ã€localhost 以外ã®ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータã‹ã‚‰ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã¾ãŸã¯ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã§ãƒªãƒ¢ãƒ¼ãƒˆæŽ¥ç¶šã—ã¦ç®¡ç†ã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™ã€‚
+CMD_RemoteEnable_Args RemoteEnable
+
+
+# RemoteDisable コマンド
+CMD_RemoteDisable VPN Client サービスã®ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†ã®ç¦æ­¢
+CMD_RemoteDisable_Help VPN Client サービスã«ã€localhost 以外ã®ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒ³ãƒ”ュータã‹ã‚‰ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ç®¡ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã¾ãŸã¯ VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã§ãƒªãƒ¢ãƒ¼ãƒˆæŽ¥ç¶šã—ã¦ç®¡ç†ã™ã‚‹ã“ã¨ã‚’ç¦æ­¢ã—ã¾ã™ã€‚
+CMD_RemoteDisable_Args RemoteDisable
+
+
+
+
+
+
+###################################################
+# #
+# ã“ã“ã‹ã‚‰ä¸‹ã¯ VPN Tools 用ã®ã‚³ãƒžãƒ³ãƒ‰ #
+# #
+###################################################
+
+
+# MakeCert コマンド
+CMD_MakeCert æ–°ã—ã„ X.509 証明書ã¨ç§˜å¯†éµã®ä½œæˆ
+CMD_MakeCert_Help æ–°ã—ã„ X.509 証明書ã¨ç§˜å¯†éµã‚’作æˆã—ã€ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚\n証明書ã®å…¬é–‹éµã¨ç§˜å¯†éµã®ç”Ÿæˆã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã«ã¯ã€RSA 1024 bit ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚\n証明書ã®ç¨®é¡žã¨ã—ã¦ã€ãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ (自己署å証明書) ã¨ä»–ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã®ã©ã¡ã‚‰ã§ã‚‚作æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ä»–ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ç½²åã«ä½¿ç”¨ã™ã‚‹è¨¼æ˜Žæ›¸ (X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«) ã¨å¯¾å¿œã™ã‚‹ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ« (Base 64 エンコード) ãŒå¿…è¦ã§ã™ã€‚\n\n作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã«ã¯ã€åå‰ (CN)ã€æ‰€å±žæ©Ÿé–¢ (O)ã€çµ„ç¹”å˜ä½ (OU)ã€å›½ (C)ã€éƒ½é“府県 (ST)ã€ãƒ­ãƒ¼ã‚«ãƒ« (L)ã€ã‚·ãƒªã‚¢ãƒ«ç•ªå·ã€æœ‰åŠ¹æœŸé™ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n作æˆã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã¯ X.509 å½¢å¼ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ã€ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã¯ RSA 1024 bit å½¢å¼ã® Base 64 エンコードã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ãã‚Œãžã‚Œä¿å­˜ã•ã‚Œã¾ã™ã€‚\n\nMakeCert コマンドã¯ã€è¨¼æ˜Žæ›¸ã‚’作æˆã™ã‚‹ãŸã‚ã®å¿…è¦æœ€ä½Žé™ã®æ©Ÿèƒ½ã‚’用æ„ã—ãŸãƒ„ールã§ã™ã€‚本格的ãªè¨¼æ˜Žæ›¸ã‚’作æˆã—ãŸã„å ´åˆã¯ã€OpenSSL ãªã©ã®ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã‚„ã€å¸‚販㮠CA (証明機関) ソフトウェアを使用ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚\n\n※注æ„: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‹ã‚‰å‘¼ã³å‡ºã™ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ç¾åœ¨ VPN Server ã‚„ VPN Client ã«ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã‚‚実行ã§ãã¾ã™ãŒã€å®Ÿéš›ã« RSA 演算を行ã„ã€è¨¼æ˜Žæ›¸ãƒ‡ãƒ¼ã‚¿ã‚’生æˆã—ファイルã«ä¿å­˜ã™ã‚‹ã®ã¯ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ã„るコンピュータã§ã‚ã‚Šã€ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šå…ˆã®ã‚³ãƒ³ãƒ”ュータã¨ã¯ä¸€åˆ‡é–¢ä¿‚ãªã„コンテキストã§å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚
+CMD_MakeCert_Args MakeCert [/CN:cn] [/O:o] [/OU:ou] [/C:c] [/ST:st] [/L:l] [/SERIAL:serial] [/EXPIRES:expires] [/SIGNCERT:signcert] [/SIGNKEY:signkey] [/SAVECERT:savecert] [/SAVEKEY:savekey]
+CMD_MakeCert_CN 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®åå‰ (CN) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_O 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®æ‰€å±žæ©Ÿé–¢ (O) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_OU 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®çµ„ç¹”å˜ä½ (OU) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_C 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®å›½ (C) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_ST 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®éƒ½é“府県 (ST) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_L 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®ãƒ­ãƒ¼ã‚«ãƒ« (L) 項目を指定ã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_SERIAL 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå·é …目を指定ã—ã¾ã™ã€‚16 進数ã§æŒ‡å®šã—ã¾ã™ã€‚none を指定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+CMD_MakeCert_EXPIRES 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®æœ‰åŠ¹æœŸé™ã‚’指定ã—ã¾ã™ã€‚none ã¾ãŸã¯ 0 を指定ã™ã‚‹ã¨ã€3650 æ—¥ (ç´„ 10 å¹´) ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚最大 10950 æ—¥ (ç´„ 30 å¹´) ã¾ã§æŒ‡å®šã§ãã¾ã™ã€‚
+CMD_MakeCert_SIGNCERT 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã‚’ã€æ—¢å­˜ã®è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ç½²åã™ã‚‹å ´åˆã¯ã€ç½²åã«ä½¿ç”¨ã™ã‚‹ X.509 å½¢å¼ã®è¨¼æ˜Žæ›¸ã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚パラメータをçœç•¥ã—ãŸå ´åˆã¯ã€ç½²åã¯è¡Œã‚ãšæ–°ã—ã„証明書をルート証明書ã¨ã—ã¦ä½œæˆã—ã¾ã™ã€‚
+CMD_MakeCert_SIGNKEY /SIGNCERT ã§æŒ‡å®šã—ãŸè¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµ (RSA, Base-64 エンコード) を指定ã—ã¾ã™ã€‚
+CMD_MakeCert_SAVECERT 作æˆã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚証明書㯠RSA å½¢å¼ã® 1024 bit ã®å…¬é–‹éµã‚’å«ã‚“ã  X.509 ファイルã¨ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+CMD_MakeCert_SAVEKEY 作æˆã—ãŸè¨¼æ˜Žæ›¸ã«å¯¾å¿œã™ã‚‹ç§˜å¯†éµã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚秘密éµã¯ RSA å½¢å¼ã® 1024 bit ã®ç§˜å¯†éµãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+CMD_MakeCert_PROMPT_CN 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®åå‰ (CN):
+CMD_MakeCert_PROMPT_O 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®æ‰€å±žæ©Ÿé–¢ (O):
+CMD_MakeCert_PROMPT_OU 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®çµ„ç¹”å˜ä½ (OU):
+CMD_MakeCert_PROMPT_C 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®å›½ (C):
+CMD_MakeCert_PROMPT_ST 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®éƒ½é“府県 (ST):
+CMD_MakeCert_PROMPT_L 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®ãƒ­ãƒ¼ã‚«ãƒ« (L):
+CMD_MakeCert_PROMPT_SERIAL 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®ã‚·ãƒªã‚¢ãƒ«ç•ªå· (16 進数):
+CMD_MakeCert_PROMPT_EXPIRES 作æˆã™ã‚‹è¨¼æ˜Žæ›¸ã®æœ‰åŠ¹æœŸé™ (æ—¥):
+CMD_MakeCert_PROMPT_SAVECERT 作æˆã—ãŸè¨¼æ˜Žæ›¸ã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_MakeCert_PROMPT_SAVEKEY 作æˆã—ãŸç§˜å¯†éµã‚’ä¿å­˜ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«å:
+CMD_MakeCert_EVAL_EXPIRES 有効期é™ã¯ %u 以上 %u 以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_MakeCert_ERROR_SIGNKEY /SIGNCERT 㨠/SIGNKEY ã§æŒ‡å®šã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã¾ãŸã¯ç§˜å¯†éµãŒèª­ã¿è¾¼ã‚ãªã„ã‹ã€çµ„ã¿åˆã‚ã›ãŒä¸æ­£ã§ã™ã€‚
+CMD_MakeCert_ERROR_GEN_FAILED 証明書ã¨ç§˜å¯†éµã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+
+
+# TrafficClient コマンド
+CMD_TrafficClient 通信スループット測定ツールクライアントã®å®Ÿè¡Œ
+CMD_TrafficClient_Help 通信スループット測定ツールã®ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ—ログラムを実行ã—ã¾ã™ã€‚\n通信スループット測定ツール㯠TrafficClient 㨠TrafficServer ã® 2 ã¤ã®ã‚³ãƒžãƒ³ãƒ‰ã¨ã—ã¦åˆ©ç”¨ã—ã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã§æŽ¥ç¶šã•ã‚ŒãŸ 2 å°ã®ã‚³ãƒ³ãƒ”ュータã®é–“ã§ä¼é€ã™ã‚‹ã“ã¨ãŒã§ãる通信スループットを計測ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã™ã§ã«åˆ¥ã®ã‚³ãƒ³ãƒ”ュータ上ã§ã€TrafficServer コマンドを用ã„ã¦é€šä¿¡ã‚¹ãƒ«ãƒ¼ãƒ—ット測定ツールサーãƒãƒ¼ã‚’å¾…æ©Ÿã•ã›ã¦ãŠãã€TrafficClient コマンドã§ã€ãã®ã‚µãƒ¼ãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¦æŽ¥ç¶šã—ã€é€šä¿¡é€Ÿåº¦ã‚’測定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n通信速度ã®æ¸¬å®šã¯ã€åŒæ™‚ã«è¤‡æ•°æœ¬ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’確立ã—ã€ãã‚Œãžã‚Œã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã§æœ€å¤§é™ã«ã‚¹ãƒˆãƒªãƒ¼ãƒ ãƒ‡ãƒ¼ã‚¿ã‚’ä¼é€ã—ãŸçµæžœã€æŒ‡å®šã•ã‚ŒãŸæ™‚間内ã«å®Ÿéš›ã«ä¼é€ã™ã‚‹ã“ã¨ãŒã§ããŸãƒ‡ãƒ¼ã‚¿ã®ãƒ“ット数を計算ã—ã€ãれを元ã«é€šä¿¡ã‚¹ãƒ«ãƒ¼ãƒ—ットã®å¹³å‡å€¤ (bps) を算出ã™ã‚‹æ–¹æ³•ã§è¡Œã‚ã‚Œã¾ã™ã€‚通常ã€1 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’用ã„ãŸå ´åˆã¯ TCP ã®ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ä¸Šã®é™ç•Œã«ã‚ˆã‚Šã€å®Ÿéš›ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¹ãƒ«ãƒ¼ãƒ—ットよりもé…ã„速度ã§ã—ã‹é€šä¿¡ã§ããªã„å ´åˆãŒå¤šã„ãŸã‚ã€è¤‡æ•°æœ¬ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’åŒæ™‚ã«ç¢ºç«‹ã—ã¦é€šä¿¡ã—ãŸçµæžœã‚’測定ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚ã“ã®æ¸¬å®šæ–¹æ³•ã«ã‚ˆã£ã¦è¨ˆæ¸¬ã•ã‚ŒãŸã‚¹ãƒ«ãƒ¼ãƒ—ットã¯å®Ÿéš›ã« TCP ã§ã‚¹ãƒˆãƒªãƒ¼ãƒ ã¨ã—ã¦å—ä¿¡å´ã«å±Šã„ãŸãƒ‡ãƒ¼ã‚¿ã®ãƒ“ット長ã‹ã‚‰è¨ˆç®—ã•ã‚Œã‚‹ãŸã‚ã€é€”中ã§ç™ºç”Ÿã—ãŸãƒ‘ケットロスやデータ破æã—ãŸãƒ‘ケットã¯ã€å®Ÿéš›ã«å±Šã„ãŸãƒ‘ケットã«ã¯å«ã¾ã‚Œãšã€ç´”粋ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æœ€å¤§é€šä¿¡å¯èƒ½å¸¯åŸŸå¹…ã«è¿‘ã„値を算出ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n測定çµæžœã¨ã—㦠TCP 内ã§ä¼é€ã•ã‚ŒãŸã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚µã‚¤ã‚ºã‹ã‚‰ã€å®Ÿéš›ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã‚’æµã‚ŒãŸãƒ‡ãƒ¼ã‚¿é‡ã®è¿‘似値を計算ã—ã€ãれを時間ã§å‰²ã£ã¦ãƒ“ット毎秒 (bps) を算出ã—ã¾ã™ã€‚物ç†çš„ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ç¨®é¡žã¯ Ethernet (IEEE802.3) ã§ã€MAC フレームã®ãƒšã‚¤ãƒ­ãƒ¼ãƒ‰ã‚µã‚¤ã‚ºã¯ 1,500 Bytes (TCP ã® MSS 㯠1,460 Bytes) ã¨ä»®å®šã—ã¦è¨ˆç®—ãŒè¡Œã‚ã‚Œã¾ã™ã€‚/RAW オプションを指定ã™ã‚‹ã¨ã€TCP/IP ヘッダや MAC ヘッダã®ãƒ‡ãƒ¼ã‚¿é‡ã‚’補正ã™ã‚‹è¨ˆç®—ã¯è¡Œã‚ã‚Œã¾ã›ã‚“。\n\n※注æ„: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‹ã‚‰å‘¼ã³å‡ºã™ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ç¾åœ¨ VPN Server ã‚„ VPN Client ã«ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã‚‚実行ã§ãã¾ã™ãŒã€å®Ÿéš›ã«é€šä¿¡ã‚’è¡Œã£ã¦ã‚¹ãƒ«ãƒ¼ãƒ—ットを測定ã™ã‚‹ã®ã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ã„るコンピュータã§ã‚ã‚Šã€ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šå…ˆã®ã‚³ãƒ³ãƒ”ュータã¨ã¯ä¸€åˆ‡é–¢ä¿‚ãªã„コンテキストã§å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚
+CMD_TrafficClient_Args TrafficClient [host:port] [/NUMTCP:numtcp] [/TYPE:download|upload|full] [/SPAN:span] [/DOUBLE:yes|no] [/RAW:yes|no]
+CMD_TrafficClient_[host:port] 通信スループット測定ツールサーãƒãƒ¼ (TrafficServer) ãŒå¾…æ©Ÿã—ã¦ã„るホストåã€ã¾ãŸã¯ IP アドレスã¨ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¾ã™ã€‚ãƒãƒ¼ãƒˆç•ªå·ã‚’çœç•¥ã—ãŸå ´åˆã¯ã€9821 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_TrafficClient_NUMTCP åŒæ™‚ã«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¨ã‚µãƒ¼ãƒãƒ¼ã¨ã®é–“ã§ç¢ºç«‹ã•ã‚Œãƒ‡ãƒ¼ã‚¿ãŒä¼é€ã•ã‚Œã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã‚’指定ã—ã¾ã™ã€‚çœç•¥ã—ãŸå ´åˆã¯ 32 ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_TrafficClient_TYPE スループット測定を行ã†éš›ã®ã€ãƒ‡ãƒ¼ã‚¿ã®æµã‚Œã‚‹æ–¹å‘を指定ã—ã¾ã™ã€‚"download"ã€"upload"ã€"full" ã®ã†ã¡ 1 ã¤ã‚’指定ã—ã¾ã™ã€‚download を指定ã™ã‚‹ã¨ã€ã‚µãƒ¼ãƒãƒ¼å´ã‹ã‚‰ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã«ãƒ‡ãƒ¼ã‚¿ãŒä¼é€ã•ã‚Œã¾ã™ã€‚upload を指定ã™ã‚‹ã¨ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã‹ã‚‰ã‚µãƒ¼ãƒãƒ¼å´ã«ãƒ‡ãƒ¼ã‚¿ãŒä¼é€ã•ã‚Œã¾ã™ã€‚full を指定ã™ã‚‹ã¨ã€åŒæ–¹å‘ã«ãƒ‡ãƒ¼ã‚¿ãŒä¼é€ã•ã‚Œã¾ã™ã€‚full を指定ã™ã‚‹å ´åˆã¯ã€NUMTCP ã®å€¤ã¯ 2 以上ã®å¶æ•°ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ (åŒæ™‚ã«æŽ¥ç¶šã•ã‚Œã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®ã†ã¡åŠæ•°ãŒãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰æ–¹å‘ã€æ®‹ã‚Šã®åŠæ•°ãŒã‚¢ãƒƒãƒ—ロード方å‘ã«ä½¿ç”¨ã•ã‚Œã¾ã™)。ã“ã®ãƒ‘ラメータをçœç•¥ã—ãŸå ´åˆã¯ full ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_TrafficClient_SPAN スループットを測定ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ¼ã‚¿ä¼é€ã‚’è¡Œã†æ™‚é–“ã‚’ã€ç§’æ•°å˜ä½ã§æŒ‡å®šã—ã¾ã™ã€‚ã“ã®ãƒ‘ラメータをçœç•¥ã—ãŸå ´åˆã¯ 15 秒ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+CMD_TrafficClient_DOUBLE "yes" を指定ã—ãŸå ´åˆã€è¨ˆæ¸¬ã—ãŸçµæžœã®ã‚¹ãƒ«ãƒ¼ãƒ—ットを 2 å€ã«ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯ã€é€”中ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è£…ç½®ãªã©ãŒã‚ã‚Šã€ãã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è£…ç½®ãŒå…¥å‡ºåŠ›ã—ãŸåˆè¨ˆã®ã‚¹ãƒ«ãƒ¼ãƒ—ット能力を測定ã™ã‚‹å ´åˆã«ä½¿ç”¨ã—ã¾ã™ã€‚
+CMD_TrafficClient_RAW "yes" を指定ã™ã‚‹ã¨ã€TCP/IP ヘッダや MAC ヘッダã®ãƒ‡ãƒ¼ã‚¿é‡ã‚’補正ã™ã‚‹è¨ˆç®—ã‚’è¡Œã„ã¾ã›ã‚“。
+CMD_TrafficClient_EVAL_NUMTCP TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°ã¯ 32 以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+CMD_TrafficClient_PROMPT_HOST 測定サーãƒãƒ¼åã¨ãƒãƒ¼ãƒˆç•ªå· (çœç•¥ã—ãŸå ´åˆã¯ 9821):
+CMD_TrafficClient_ERROR_NUMTCP データã®æµã‚Œã‚‹æ–¹å‘㌠"full" (åŒæ–¹å‘) ã®å ´åˆã€TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•° (/NUMTCP) ã¯å¶æ•°ã®å€¤ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_TrafficClient_ERROR_HOSTPORT ホストåã¾ãŸã¯ãƒãƒ¼ãƒˆç•ªå·ã®æŒ‡å®šãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。
+
+
+# TrafficServer コマンド
+CMD_TrafficServer 通信スループット測定ツールサーãƒãƒ¼ã®å®Ÿè¡Œ
+CMD_TrafficServer_Help 通信スループット測定ツールã®ã‚µãƒ¼ãƒãƒ¼ãƒ—ログラムを実行ã—ã¾ã™ã€‚\n通信スループット測定ツールã¯ã€TrafficClient 㨠TrafficServer ã® 2 ã¤ã®ã‚³ãƒžãƒ³ãƒ‰ã¨ã—ã¦åˆ©ç”¨ã—ã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã§æŽ¥ç¶šã•ã‚ŒãŸ 2 å°ã®ã‚³ãƒ³ãƒ”ュータã®é–“ã§ä¼é€ã™ã‚‹ã“ã¨ãŒã§ãる通信スループットを計測ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\nã“ã®ã‚³ãƒ³ãƒ”ュータ上㮠TCP ãƒãƒ¼ãƒˆã‚’待機状態ã«ã—ã¦ã€åˆ¥ã®ã‚³ãƒ³ãƒ”ュータã‹ã‚‰ã® TrafficClient ã‹ã‚‰ã®æŽ¥ç¶šã‚’å¾…ã¡å—ã‘ã‚‹ã«ã¯ã€TrafficServer コマンドã«ãƒãƒ¼ãƒˆç•ªå·ã‚’指定ã—ã¦èµ·å‹•ã—ã¾ã™ã€‚\n通信スループット測定ツールã«é–¢ã™ã‚‹è©³ç´°ã¯ã€TrafficClient /? ã¨å…¥åŠ›ã™ã‚‹ã¨è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\n\n※注æ„: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‹ã‚‰å‘¼ã³å‡ºã™ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ç¾åœ¨ VPN Server ã‚„ VPN Client ã«ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šã—ã¦ã„ã‚‹å ´åˆã‚‚実行ã§ãã¾ã™ãŒã€å®Ÿéš›ã«é€šä¿¡ã‚’è¡Œã£ã¦ã‚¹ãƒ«ãƒ¼ãƒ—ットを測定ã™ã‚‹ã®ã¯ã€ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¦ã„るコンピュータã§ã‚ã‚Šã€ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã§æŽ¥ç¶šå…ˆã®ã‚³ãƒ³ãƒ”ュータã¨ã¯ä¸€åˆ‡é–¢ä¿‚ãªã„コンテキストã§å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚
+CMD_TrafficServer_Args TrafficServer [port]
+CMD_TrafficServer_[port] 接続を待ã¡å—ã‘ã‚‹ãƒãƒ¼ãƒˆç•ªå·ã‚’æ•´æ•°ã§æŒ‡å®šã—ã¾ã™ã€‚指定ã•ã‚ŒãŸãƒãƒ¼ãƒˆãŒã€ã™ã§ã«åˆ¥ã®ãƒ—ログラムã«ã‚ˆã£ã¦ä½¿ç”¨ä¸­ã®å ´åˆã‚„ã€ãƒãƒ¼ãƒˆã‚’é–‹ãã“ã¨ãŒã§ããªã„å ´åˆã¯ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã™ã€‚
+
+
+# TrafficClient / TrafficServer 系内部メッセージ文字列
+TT_LISTEN_FAILED TCP ãƒãƒ¼ãƒˆ %u を待機状態ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãƒãƒ¼ãƒˆãŒä»–ã®ã‚¢ãƒ—リケーションã«ã‚ˆã£ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ã‹ã€ãƒãƒ¼ãƒˆã‚’é–‹ã権é™ãŒç„¡ã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+TTS_LISTEN_STOP å¾…æ©Ÿãƒãƒ¼ãƒˆã‚’é–‰ã˜ã¾ã—ãŸã€‚
+TTS_ENTER_TO_EXIT \n----------------------------------------\n通信スループット測定ツールã®ã‚µãƒ¼ãƒãƒ¼ãƒ—ログラムを起動ã—ã¾ã—ãŸã€‚\n\nEnter キーを押ã™ã¨ã€ã‚µãƒ¼ãƒãƒ¼ãƒ—ログラムをåœæ­¢ã—ã¾ã™ã€‚\n----------------------------------------\n\n
+TTS_INIT サーãƒãƒ¼ãƒ—ログラムを起動ã—ã¦ã„ã¾ã™...
+TTS_LISTEN_STARTED サーãƒãƒ¼ãƒ—ログラムを起動ã—ã¾ã—ãŸã€‚IPv4 TCP ãƒãƒ¼ãƒˆ %u を待機状態ã«ã—ã¦ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’å¾…æ©Ÿã—ã¦ã„ã¾ã™ã€‚
+TTS_LISTEN_STARTED_V6 IPv6 TCP ãƒãƒ¼ãƒˆ %u を待機状態ã«ã—ã¦ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‹ã‚‰ã®æŽ¥ç¶šã‚’å¾…æ©Ÿã—ã¦ã„ã¾ã™ã€‚
+TTS_LISTEN_FAILED_V6 IPv6 TCP ãƒãƒ¼ãƒˆ %u を待機状態ã«ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ä»–ã®ã‚¢ãƒ—リケーションãŒåŒä¸€ IPv6 TCP ãƒãƒ¼ãƒˆã‚’使用ã—ã¦ã„ã‚‹ã‹ã€IPv6 スタックãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+TTS_STOP_INIT サーãƒãƒ¼ãƒ—ログラムをåœæ­¢ã—ã¦ã„ã¾ã™...
+TTS_STOP_FINISHED サーãƒãƒ¼ãƒ—ログラムã®åœæ­¢ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+TTS_ACCEPTED コãƒã‚¯ã‚·ãƒ§ãƒ³ %u: クライアント %S ã®ãƒãƒ¼ãƒˆ %u ã‹ã‚‰æŽ¥ç¶šã•ã‚Œã¾ã—ãŸã€‚
+TTS_DISCONNECTED コãƒã‚¯ã‚·ãƒ§ãƒ³ %u (%S) ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+TTS_DISCONNECT コãƒã‚¯ã‚·ãƒ§ãƒ³ %u (%S) を切断ã—ã¾ã—ãŸã€‚
+TTC_INIT クライアントプログラムを起動ã—ã¦ã„ã¾ã™...
+TTC_FREE クライアントプログラムãŒçµ‚了ã—ã¾ã—ãŸã€‚
+TTC_CONNECT_START サーãƒãƒ¼ %S (ãƒãƒ¼ãƒˆ %u) ã¸ã®æŽ¥ç¶šã‚’開始ã—ã¾ã™ã€‚%u 本㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’接続ã—ã¾ã™ã€‚
+TTC_CONNECT_FAILED %u 本目㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+TTC_CONNECT_NOT_SERVER 接続先㮠TCP ãƒãƒ¼ãƒˆã§ TrafficServer 以外ã®ãƒ—ログラムãŒå‹•ä½œã—ã¦ã„ã‚‹ãŸã‚ã€ãƒˆãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚’計測ã§ãã¾ã›ã‚“。
+TTC_CONNECT_OK %u 本目㮠TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’接続ã—ã¾ã—ãŸã€‚
+TTC_CONNECT_OK_2 \ データä¼é€æ–¹å‘: %s
+TTC_ERROR_ABORTED サーãƒãƒ¼ã¨ã®é–“ã® TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸã€‚計測を中止ã—ã¾ã™ã€‚
+TTC_SUMMARY_BAR -------------------------------------------------------
+TTC_SUMMARY_TITLE 通信スループット測定ツールクライアント 設定内容
+TTC_SUMMARY_HOST 接続先ã®ãƒ›ã‚¹ãƒˆå
+TTC_SUMMARY_PORT 接続先㮠TCP ãƒãƒ¼ãƒˆç•ªå·
+TTC_SUMMARY_NUMTCP 確立ã™ã‚‹ TCP コãƒã‚¯ã‚·ãƒ§ãƒ³æ•°
+TTC_SUMMARY_TYPE データä¼é€æ–¹å‘
+TTC_SUMMARY_SPAN データä¼é€æ™‚é–“
+TTC_SUMMARY_ETHER Ethernet フレーム用ã«ãƒ‡ãƒ¼ã‚¿è£œæ­£
+TTC_SUMMARY_DOUBLE 中継機器ã®å…¥å‡ºåŠ›åˆè¨ˆé€Ÿåº¦ã®è¨ˆæ¸¬
+TTC_TYPE_DOWNLOAD ダウンロード (サーãƒãƒ¼ -> クライアント)
+TTC_TYPE_UPLOAD アップロード (クライアント -> サーãƒãƒ¼)
+TTC_TYPE_FULL åŒæ–¹å‘ (サーãƒãƒ¼ <--> クライアント)
+TTC_SPAN_STR %.1f 秒
+TTC_COMM_START \nã™ã¹ã¦ã®ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ãŒç¢ºç«‹ã•ã‚ŒãŸã®ã§ã€ãƒ‡ãƒ¼ã‚¿é€å—信を開始ã—ã¾ã—ãŸã€‚\n測定開始時刻: %s\n完了予定時刻: %s\n\n計測中ã§ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。\n(測定中ã¯ä»–ã®ã‚¢ãƒ—リケーションを使用ã—ãªã„ã§ãã ã•ã„。)\n\n
+TTC_COMM_END %.1f 秒以上ãŒçµŒéŽã—ãŸã®ã§ã€ãƒ‡ãƒ¼ã‚¿é€šä¿¡ã‚’終了ã—ã¾ã™ã€‚\n\n
+TTC_COMM_USER_CANCEL ユーザーã«ã‚ˆã£ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚ŒãŸã®ã§ã€ãƒ‡ãƒ¼ã‚¿é€šä¿¡ã‚’終了ã—ã¾ã™ã€‚\n\n
+TTC_COMM_DISCONNECTED TCP コãƒã‚¯ã‚·ãƒ§ãƒ³ %u ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚
+TTC_STOPPING 通信スループット測定ツールクライアントã®å‹•ä½œã‚’åœæ­¢ã—ã¦ã„ã¾ã™...
+TTC_ENTER_TO_EXIT \n----------------------------------------\n通信スループット測定ツールã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ—ログラムを起動ã—ã¾ã—ãŸã€‚\n\nEnter キーを押ã™ã¨ã€ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãƒ—ログラムをåœæ­¢ã—ã¾ã™ã€‚\n----------------------------------------\n\n
+TTC_RES_TITLE \n\n通信スループット測定ツールã«ã‚ˆã‚‹æ¸¬å®šçµæžœ\n\n
+TTC_RES_COLUMN_1 é …ç›®å
+TTC_RES_COLUMN_2 通常ã®è¡¨ç¤º
+TTC_RES_COLUMN_3 çœç•¥è¡¨ç¤º
+TTC_RES_SPAN 測定ã«ä½¿ç”¨ã—ãŸæ™‚é–“
+TTC_RES_ETHER Ethernet フレーム用ã«ãƒ‡ãƒ¼ã‚¿è£œæ­£
+TTC_RES_BYTES_DOWNLOAD ダウンロード方å‘ã®é€šä¿¡ãƒ‡ãƒ¼ã‚¿é‡
+TTC_RES_BYTES_UPLOAD アップロード方å‘ã®é€šä¿¡ãƒ‡ãƒ¼ã‚¿é‡
+TTC_RES_BYTES_TOTAL åˆè¨ˆé€šä¿¡ãƒ‡ãƒ¼ã‚¿é‡
+TTC_RES_DOUBLE 中継機器入出力åˆè¨ˆã‚¹ãƒ«ãƒ¼ãƒ—ット算出
+TTC_RES_BPS_DOWNLOAD ダウンロード方å‘ã®å¹³å‡ã‚¹ãƒ«ãƒ¼ãƒ—ット
+TTC_RES_BPS_UPLOAD アップロード方å‘ã®å¹³å‡ã‚¹ãƒ«ãƒ¼ãƒ—ット
+TTC_RES_BPS_TOTAL åˆè¨ˆå¹³å‡ã‚¹ãƒ«ãƒ¼ãƒ—ット
+
+
+# Check コマンド
+CMD_Check SoftEther VPN ã®å‹•ä½œãŒå¯èƒ½ã‹ã©ã†ã‹ãƒã‚§ãƒƒã‚¯ã™ã‚‹
+CMD_Check_Help ç¾åœ¨ vpncmd を動作ã•ã›ã¦ã„るコンピュータãŒã€SoftEther VPN Server / Bridge ã®å‹•ä½œãƒ—ラットフォームã¨ã—ã¦é©åˆ‡ã§ã‚ã‚‹ã‹ã©ã†ã‹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¾ã™ã€‚\nã“ã®ãƒã‚§ãƒƒã‚¯ã‚’通éŽã—ãŸã‚·ã‚¹ãƒ†ãƒ ä¸Šã§ã¯ã€SoftEther VPN ソフトウェアãŒæ­£ã—ã動作ã™ã‚‹å¯èƒ½æ€§ãŒé«˜ã„ã¨æ€ã‚ã‚Œã¾ã™ã€‚\nã¾ãŸã€ã“ã®ãƒã‚§ãƒƒã‚¯ã‚’通éŽã§ããªã„システム上ã§ã¯ã€SoftEther VPN ソフトウェアを使用ã—ãŸå ´åˆã«ã€ä½•ã‚‰ã‹ã®å•é¡ŒãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+CMD_Check_Args Check
+
+
+# システムãƒã‚§ãƒƒã‚«é–¢ä¿‚
+# (一部奇妙ãªæ–‡å­—列ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ãŒã€æ–‡å­—コード変æ›ã®ãƒã‚§ãƒƒã‚¯ç”¨ã§ã™)
+CHECK_TITLE ---------------------------------------------------\nSoftEther VPN 動作環境ãƒã‚§ãƒƒã‚¯ãƒ„ール\n\nCopyright (c) SoftEther VPN Project.\nAll Rights Reserved.\n\n
+CHECK_NOTE ã“ã®å‹•ä½œç’°å¢ƒãƒã‚§ãƒƒã‚¯ãƒ„ールを実行ã—ãŸã‚·ã‚¹ãƒ†ãƒ ãŒãƒ†ã‚¹ãƒˆã«åˆæ ¼ã—ãŸå ´åˆã¯ã€SoftEther VPN ソフトウェアãŒå‹•ä½œã™ã‚‹å¯èƒ½æ€§ãŒé«˜ã„ã§ã™ã€‚ãƒã‚§ãƒƒã‚¯ã«ã¯ã—ã°ã‚‰ã時間ãŒã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ãã®ã¾ã¾ãŠå¾…ã¡ãã ã•ã„...\n\n
+CHECK_EXEC_TAG '%s' ã®ãƒã‚§ãƒƒã‚¯ä¸­...\n
+CHECK_PASS [åˆæ ¼] â—‹
+CHECK_FAIL [ä¸åˆæ ¼] ×
+CHECK_RESULT_1 ã™ã¹ã¦ã®ãƒã‚§ãƒƒã‚¯ã«åˆæ ¼ã—ã¾ã—ãŸã€‚ã“ã®ã‚·ã‚¹ãƒ†ãƒ ä¸Šã§ SoftEther VPN Server / Bridge ãŒæ­£ã—ã動作ã™ã‚‹å¯èƒ½æ€§ãŒé«˜ã„ã¨æ€ã‚ã‚Œã¾ã™ã€‚
+CHECK_RESULT_2 一部ã®ãƒã‚§ãƒƒã‚¯çµæžœã¯ä¸åˆæ ¼ã§ã—ãŸã€‚システムã®å‹•ä½œç’°å¢ƒã‚’確èªã—ã¦ãã ã•ã„。ã“ã®ã‚·ã‚¹ãƒ†ãƒ ä¸Šã§ SoftEther VPN Server / Bridge を実行ã—ãŸå ´åˆã€å•é¡ŒãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+CHECK_TEST_123456789 123456789
+
+
+CHECK_PROC_KERNEL カーãƒãƒ«ç³»
+CHECK_PROC_MEMORY メモリæ“作系
+CHECK_PROC_STRINGS ANSI / Unicode 文字列処ç†ç³»
+CHECK_PROC_FILESYSTEM ファイルシステム
+CHECK_PROC_THREAD スレッド処ç†ã‚·ã‚¹ãƒ†ãƒ 
+CHECK_PROC_NETWORK ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚·ã‚¹ãƒ†ãƒ 
+
+
+
+
+
+
+######################################################
+# #
+# Setup Wizard (SW) Strings #
+# #
+######################################################
+
+SW_TITLE SoftEther VPN セットアップ ウィザード (ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %S)
+SW_EXIT_CONFIRM SoftEther VPN ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã¯å®Œäº†ã—ã¦ã„ã¾ã›ã‚“。\r\n\r\nセットアップ ウィザードを終了ã—ã¾ã™ã‹?
+SW_UNINSTALL_CONFIRM %s ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å‡¦ç†ã‚’開始ã—ã¾ã™ã€‚\r\n\r\nよã‚ã—ã„ã§ã™ã‹?
+
+
+SW_COMPONENT_VPNSERVER_TITLE SoftEther VPN Server
+SW_COMPONENT_VPNSERVER_DESCRIPTION センター拠点ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚VPN を構築ã™ã‚‹éš›ã«ã‚»ãƒ³ã‚¿ãƒ¼å´ã¨ãªã‚‹æ‹ ç‚¹ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。管ç†ãƒ„ールもインストールã•ã‚Œã¾ã™ã€‚
+
+SW_COMPONENT_VPNCLIENT_TITLE SoftEther VPN Client
+SW_COMPONENT_VPNCLIENT_DESCRIPTION VPN クライアントã¨ãªã‚‹ PC ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚センター拠点ã§ç¨¼åƒã—ã¦ã„ã‚‹ VPN Server ã«å¯¾ã—ã¦ã“ã®ã‚³ãƒ³ãƒ”ュータを VPN 接続ã™ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。管ç†ãƒ„ールもインストールã•ã‚Œã¾ã™ã€‚
+
+SW_COMPONENT_VPNBRIDGE_TITLE SoftEther VPN Bridge
+SW_COMPONENT_VPNBRIDGE_DESCRIPTION ブランãƒæ‹ ç‚¹ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚ã“ã®æ‹ ç‚¹ã®ç‰©ç†çš„㪠LAN ã«ã‚るコンピュータã™ã¹ã¦ã‚’センター拠点ã«ã‚ã‚‹ VPN Server を経由ã—ã¦é€šä¿¡ã§ãるよã†ã«ã™ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。管ç†ãƒ„ールもインストールã•ã‚Œã¾ã™ã€‚
+
+SW_COMPONENT_VPNSMGR_TITLE SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ (管ç†ãƒ„ールã®ã¿)
+SW_COMPONENT_VPNSMGR_DESCRIPTION ã“ã® PC ã« VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã®ã¿ã‚’インストールã—ã¾ã™ã€‚VPN Server 本体ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã›ã‚“。別ã®ã‚³ãƒ³ãƒ”ュータ㮠Windows / Linux / Mac OS X / Solaris / FreeBSD ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Server / VPN Bridge をリモート管ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+SW_COMPONENT_VPNCMGR_TITLE SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ (管ç†ãƒ„ールã®ã¿)
+SW_COMPONENT_VPNCMGR_DESCRIPTION ã“ã® PC ã« VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã®ã¿ã‚’インストールã—ã¾ã™ã€‚VPN Client 本体ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã›ã‚“。別ã®ã‚³ãƒ³ãƒ”ュータ㮠Windows / Linux ã§å‹•ä½œã—ã¦ã„ã‚‹ VPN Client をリモート管ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+SW_WELCOME_TITLE SoftEther VPN セットアップ ウィザードã¸ã‚ˆã†ã“ã
+SW_MODE_TITLE セットアップモードã®é¸æŠž
+SW_NOT_ADMIN_TITLE 権é™ãŒä¸è¶³ã—ã¦ã„ã¾ã™
+SW_COMPONENTS_TITLE インストールã™ã‚‹ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®é¸æŠž
+SW_EULA_TITLE 使用許諾契約書
+SW_WARNING_TITLE é‡è¦äº‹é …説明書
+SW_DIR_TITLE インストール先ディレクトリ
+SW_READY_TITLE インストール準備ã®å®Œäº†
+SW_PERFORM_TITLE セットアップã®é€²è¡Œä¸­
+SW_ERROR_TITLE セットアップã®çµæžœ
+SW_FINISH_TITLE セットアップãŒå®Œäº†ã—ã¾ã—ãŸ
+SW_UNINST1_TITLE アンインストールã®é–‹å§‹
+SW_LANG1_TITLE SoftEther VPN: Configure the Display Language (言語設定ã®å¤‰æ›´)
+SW_EASY1_TITLE SoftEther VPN Client 簡易インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¸ã‚ˆã†ã“ã
+SW_EASY2_TITLE ファイルã®æŒ‡å®š
+SW_WEB1_TITLE SoftEther VPN Client Web インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã¸ã‚ˆã†ã“ã
+SW_WEB2_TITLE ファイルã®æŒ‡å®š
+
+
+SW_UNINSTALLINFO_URL http://selinks.org/
+SW_UNINSTALLINFO_PUBLISHER SoftEther VPN Project
+
+
+SW_COMPONENTS_ABOUT_TAG 「%sã€ã¨ã¯
+SW_COMPONENTS_REQUIRE_ADMIN インストールã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™
+SW_COMPONENTS_REQUIRE_ADMIN_TEXT 「%sã€ã‚’インストールã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒã‚るユーザーã«ã‚ˆã£ã¦ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã‚’èµ·å‹•ã—ã€ã€Œã‚·ã‚¹ãƒ†ãƒ ãƒ¢ãƒ¼ãƒ‰ã€ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚システムモードã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã«ã¯ã€ã€Œæˆ»ã‚‹ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。
+SW_DIR_SELECT インストール先ディレクトリをé¸æŠžã—ã¦ãã ã•ã„
+SW_DIR_MORE_THAN_110 インストール先ディレクトリåãŒé•·ã™ãŽã¾ã™ã€‚\r\n110 文字以下ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+SW_DIR_WRITE_ERROR 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª "%s" を作æˆã™ã‚‹ã“ã¨ãŒã§ããªã„ã‹ã€å½“該ディレクトリã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’書ã込むã“ã¨ãŒã§ãã¾ã›ã‚“。\r\n\r\nä»–ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。
+SW_DIR_DST_IS_SAME_TO_SRC 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª "%s" ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å…ƒã¨åŒä¸€ã§ã™ã€‚
+SW_DIR_IS_NOT_HDD 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª "%s" ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ãƒ‰ãƒ©ã‚¤ãƒ–ã§ã¯ã‚ã‚Šã¾ã›ã‚“。\r\n\r\nシステムモード㧠%s をインストールã™ã‚‹ãŸã‚ã«ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+SW_DIR_IS_NOT_FULLPATH ディレクトリå "%s" ã¯ãƒ•ãƒ«ãƒ‘ス形å¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“。\r\n\r\nフルパス形å¼ã§æŒ‡å®šã—ã¦ãã ã•ã„。
+SW_DIR_DST_IS_OTHER_PRODUCT 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯åˆ¥ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆãŒã™ã§ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n別ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。
+SW_DIR_DST_IS_NEWER 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã‚ˆã‚Šæ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒã™ã§ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\nã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã†å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。
+SW_DIR_DST_IS_NEWER_2 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã‚ˆã‚Šæ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒã™ã§ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\nã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã§ã¯ç°¡æ˜“インストール機能ã«ã‚ˆã‚‹ VPN ã®æŽ¥ç¶šè¨­å®šã®é©ç”¨ã®ã¿ã‚’è¡Œã„ã€ãƒ—ログラムファイルã®ä¸Šæ›¸ãã¯è¡Œã„ã¾ã›ã‚“。
+SW_DIR_DST_IS_BROKEN 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ« "%s" を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。\r\n\r\n別ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。
+SW_DIR_DST_IS_SYSTEM_MODE 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã™ã§ã«æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒã‚·ã‚¹ãƒ†ãƒ ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n別ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。
+SW_DIR_DST_IS_USER_MODE 指定ã•ã‚ŒãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã™ã§ã«æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n別ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’指定ã—ã¦ãã ã•ã„。
+SW_SYSTEM_MODE_ALREADY_INSTALLED ソフトウェア 「%s〠ã¯ã™ã§ã«ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã‚·ã‚¹ãƒ†ãƒ ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\nåŒä¸€ã‚³ãƒ³ãƒ”ュータã«åŒä¸€ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’システムモードã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã®ä¸¡æ–¹ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ç«¶åˆãŒç™ºç”Ÿã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\n本当ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’実行ã—ã¾ã™ã‹?
+
+SW_NOT_INSTALL_SRC セットアッププログラムãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚½ãƒ¼ã‚¹ä»¥å¤–ã‹ã‚‰èµ·å‹•ã•ã‚Œã¾ã—ãŸã€‚\r\n\r\nインストールを続行ã§ãã¾ã›ã‚“。
+SW_SETUPLOG_CORRUPTED setuplog.dat ファイルãŒç ´æã—ã¦ã„ã¾ã™ã€‚
+SW_MSI_UNINSTALL_FAILED %s ã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ (製å“コード: "%S") ã‚’ Windows Installer ã§ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’手動ã§ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã‹ã‚‰ã€å†åº¦ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。
+SW_MSI_UNINSTALL_REBOOT_REQUIRED %s ã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ Windows Installer ã§ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã—ãŸã€‚コンピュータã®å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚\r\n\r\n「完了ã€ã‚’クリックã—ã¦ã‹ã‚‰æ‰‹å‹•ã§ã‚³ãƒ³ãƒ”ュータをå†èµ·å‹•ã—ã€ãã®å¾Œã‚‚ã†ä¸€åº¦ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。
+SW_NOTICE_VPNSERVER_IS_INSTALLED コンãƒãƒ¼ãƒãƒ³ãƒˆã¨ã—㦠SoftEther VPN Bridge ãŒé¸æŠžã•ã‚Œã¾ã—ãŸãŒã€ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã¯ã™ã§ã« SoftEther VPN Server ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n通常ã€åŒä¸€ã®ã‚³ãƒ³ãƒ”ュータ㫠SoftEther VPN Server 㨠SoftEther VPN Bridge ã®ä¸¡æ–¹ã‚’インストールã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\r\n両方をインストールã™ã‚‹ã¨ãƒãƒ¼ãƒˆç•ªå·ã®ç«¶åˆãªã©ãŒç™ºç”Ÿã—ã€ä¸å…·åˆã®åŽŸå› ã¨ãªã‚Šã¾ã™ã€‚\r\nã‚‚ã— SoftEther VPN Server ã‚’ SoftEther VPN Bridge ã«å…¥ã‚Œæ›¿ãˆã‚‹å ´åˆã¯ã€ä¸€ç«¯ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’終了ã—ã€SoftEther VPN Server をアンインストールã—ã¦ã‹ã‚‰å†åº¦ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。\r\n\r\nSoftEther VPN Bridge ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã—ã¾ã™ã‹?
+SW_NOTICE_VPNBRIDGE_IS_INSTALLED コンãƒãƒ¼ãƒãƒ³ãƒˆã¨ã—㦠SoftEther VPN Server ãŒé¸æŠžã•ã‚Œã¾ã—ãŸãŒã€ã“ã®ã‚³ãƒ³ãƒ”ュータã«ã¯ã™ã§ã« SoftEther VPN Bridge ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™ã€‚\r\n\r\n通常ã€åŒä¸€ã®ã‚³ãƒ³ãƒ”ュータ㫠SoftEther VPN Server 㨠SoftEther VPN Bridge ã®ä¸¡æ–¹ã‚’インストールã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。\r\n両方をインストールã™ã‚‹ã¨ãƒãƒ¼ãƒˆç•ªå·ã®ç«¶åˆãªã©ãŒç™ºç”Ÿã—ã€ä¸å…·åˆã®åŽŸå› ã¨ãªã‚Šã¾ã™ã€‚\r\nã‚‚ã— SoftEther VPN Bridge ã‚’ SoftEther VPN Server ã«å…¥ã‚Œæ›¿ãˆã‚‹å ´åˆã¯ã€ä¸€ç«¯ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’終了ã—ã€SoftEther VPN Bridge をアンインストールã—ã¦ã‹ã‚‰å†åº¦ã“ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。\r\n\r\nSoftEther VPN Server ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã—ã¾ã™ã‹?
+SW_OS_FAILED %s ã¯ã“ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã›ã‚“。
+SW_LANG_NOT_CHANGED %s ã®è¨€èªžè¨­å®šã¯å¤‰æ›´ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚
+SW_LANG_LIST_LOAD_FAILED 言語一覧データã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_LANG_OK %s ã®è¡¨ç¤ºè¨€èªžã®å¤‰æ›´ãŒå®Œäº†ã—ã¾ã—ãŸã€‚\r\n%s ã®ãƒ—ログラムãŒèµ·å‹•ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãƒ—ログラムを一度終了ã—ã¦ã‹ã‚‰å†èµ·å‹•ã™ã‚‹ã¨æ–°ã—ã„表示言語ãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚表示言語ãŒå¤‰åŒ–ã—ãªã„å ´åˆã¯ã€Windows ã‚’å†èµ·å‹•ã—ã¦ã¿ã¦ãã ã•ã„。\r\n
+SW_LANG_OK_SERVICE \r\nサービスãŒå‹•ä½œã—ã¦ã„ã‚‹å ´åˆã¯ã€ã‚µãƒ¼ãƒ“スã®å‡ºåŠ›ã™ã‚‹ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã®è¨€èªžè¨­å®šã¯ã‚µãƒ¼ãƒ“スをå†èµ·å‹•ã—ãŸå¾Œã«é©ç”¨ã•ã‚Œã¾ã™ã€‚
+SW_LANG_OK_VPNCMGR \r\nVPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã®è¡¨ç¤ºè¨€èªžã¯ã€VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’終了 (タスクトレイã«å¸¸é§ã•ã›ã¦ã„ã‚‹å ´åˆã¯å®Œå…¨ã«çµ‚了) ã—ã¦ã‹ã‚‰å†èµ·å‹•ã—ãŸå¾Œã«é©ç”¨ã•ã‚Œã¾ã™ã€‚
+SW_CHILD_PROCESS_ERROR å­ãƒ—ロセスを起動ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+SW_EXE_FILTER Windows 実行å¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ« (*.EXE)|*.exe|ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« (*.*)|*.*
+SW_PERFORM_MSG_EASY_INFO VPN Client ã®ç°¡æ˜“インストーラをコンパイル中...
+SW_EASY_FINISHED_MSG VPN Client ã®ç°¡æ˜“インストーラã®ç”ŸæˆãŒå®Œäº†ã—ã¾ã—ãŸã€‚\r\n簡易インストーラã¯ã€ä»¥ä¸‹ã®ãƒ•ã‚¡ã‚¤ãƒ«åã§ä¿å­˜ã•ã‚Œã¾ã—ãŸã€‚\r\n\r\n%s\r\n\r\n上記ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’組織内ã§é…布ã—ã¦ä½¿ç”¨ã§ãã¾ã™ã€‚
+SW_EASY_ERROR_MSG VPN Client ã®ç°¡æ˜“インストーラã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_OTHER_INSTANCE_EXISTS ã™ã§ã«ä»–ã® SoftEther VPN セットアップウィザードãŒèµ·å‹•ã—ã¦ã„ã¾ã™ã€‚\r\n\r\nä»–ã«èµ·å‹•ã—ã¦ã„るセットアップウィザードを確èªã—ã€ãã®ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã‚’終了ã•ã›ã¦ã‹ã‚‰ç¶šè¡Œã—ã¦ãã ã•ã„。
+SW_PERFORM_MSG_WEB_INFO VPN Client 㮠Web インストーラをコンパイル中...
+SW_WEB_ERROR_MSG VPN Client ã® Web インストーラã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_INSTALLER_CACHE_IS_NOT_SIGNED ç¾åœ¨ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ SoftEther VPN Client ã¯ã€SoftEther VPN Project ã®æœ‰åŠ¹ãª Authenticode デジタル証明書ã§ç½²åã•ã‚ŒãŸãƒ‘ッケージã‹ã‚‰ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。\r\nカスタマイズã•ã‚ŒãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‹ã‚‰ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\nãŸã¨ãˆã°ã€ã€Œç°¡æ˜“インストーラ作æˆã‚­ãƒƒãƒˆã€ã«ã‚ˆã£ã¦ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºã•ã‚ŒãŸã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’用ã„ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n\r\nã“ã®ã¾ã¾ã®çŠ¶æ…‹ã§ Web インストーラを作æˆã™ã‚‹ã¨ã€ä½œæˆã—ãŸã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã‚’ロードã—よã†ã¨ã—ãŸéš›ã«ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã®è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚\r\n警告メッセージを表示ã—ãªã„よã†ã«ã™ã‚‹ãŸã‚ã«ã¯ã€ä¸€ç«¯ Web インストーラã®ä½œæˆã‚’キャンセルã—ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µç¤¾ã® Web サイトã‹ã‚‰æœ€æ–°ã® SoftEther VPN Client パッケージをダウンロードã—ã¦å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã‹ã‚‰å†åº¦ Web インストーラを作æˆã—ã¦ãã ã•ã„。\r\n\r\nã“ã®ã¾ã¾ç¶šè¡Œã—ã¾ã™ã‹?
+SW_FILE_NOT_FOUNT ファイル "%s" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+SW_WEB_FINISHED 生æˆã•ã‚ŒãŸ Web インストーラを格ç´ã—ãŸãƒ•ã‚¡ã‚¤ãƒ« "%s" ã‚’ä¿å­˜ã—ã¾ã—ãŸã€‚\r\n\r\nã“ã® ZIP ファイルを展開ã—ã€ä¸­èº«ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ Web サーãƒãƒ¼ã«è¨­ç½®ã—㦠HTML ファイルや inf ファイル内㮠URL ã‚’é©åˆ‡ã«æ›¸ãæ›ãˆã¦ãã ã•ã„。\r\n\r\nWeb インストーラã®é…置方法ã«é–¢ã™ã‚‹èª¬æ˜Žã¯ ZIP ファイル内ã«è¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
+
+
+
+SW_PERFORM_MSG_INIT_TASKS タスクを準備ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_COPY_PREPARE ファイルã®ã‚³ãƒ”ーã®æº–備をã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_WRITE_ERROR インストール先ファイル "%s" ã«æ›¸ã込むã“ã¨ãŒã§ãã¾ã›ã‚“。\r\n\r\nã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã„ã¦ã„るプログラムãŒå®Ÿè¡Œä¸­ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n「%sã€é–¢ä¿‚ã®ãƒ—ログラムやサービスãŒèµ·å‹•ã—ã¦ã„ã‚‹å ´åˆã¯ã€çµ‚了ã—ã¦ã‹ã‚‰ã€Œå†è©¦è¡Œã€ã‚’クリックã—ã¦ãã ã•ã„。
+SW_PERFORM_MSG_COPY_FILE "%s" をコピーã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_SET_SECURITY "%s" ã«ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚’設定ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_PLUGIN プラグインをインストールã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_STOP_SVC サービス 「%s〠をåœæ­¢ä¸­...
+SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK ファイル "%s" ãŒå®Ÿè¡Œä¸­ã®ãƒ—ログラムã«ã‚ˆã£ã¦ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚ロックãŒè§£é™¤ã•ã‚Œã‚‹ã¾ã§å¾…機中...
+SW_PERFORM_MSG_INSTALL_SVC サービス 「%s〠をインストール中...
+SW_PERFORM_MSG_START_SVC サービス 「%s〠を開始中...
+SW_PERFORM_MSG_CREATE_LINKS ショートカットファイルを作æˆä¸­...
+SW_PERFORM_MSG_DELETE_LINKS ショートカットファイルを削除中...
+SW_PERFORM_MSG_DELETE_OLD_LINKS å¤ã„ショートカットファイルを削除中...
+SW_PERFORM_MSG_REGISTER_UNINSTALL アンインストール情報をコントロールパãƒãƒ«ã«ç™»éŒ²ä¸­...
+SW_PERFORM_MSG_IMPORTING_ACCOUNT 簡易インストーラã«å†…蔵ã•ã‚Œã¦ã„る接続設定をインãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_DELETE_SETUP_INFO インストール情報ãŠã‚ˆã³ãƒ­ã‚°ã‚’削除中...
+SW_PERFORM_MSG_WRITE_LOG セットアップログを書ã出ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_COPY_ERROR ファイル "%s" ã¸ã®ã‚³ãƒ”ーã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_CRAETE_LINK_ERROR ショートカットファイル "%s" ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚\r\n\r\nå†è©¦è¡Œã—ã¾ã™ã‹?
+SW_PERFORM_MSG_WRITE_LOG_ERROR セットアップログファイル "%s" ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚\r\n\r\nå†è©¦è¡Œã—ã¾ã™ã‹?
+SW_PERFORM_MSG_STOP_SVC_ERROR サービス 「%s〠(内部å: "%S") ã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_START_SVC_ERROR サービス 「%s〠(内部å: "%S") ã®é–‹å§‹ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_SVC_UNINSTALL_FAILED サービス 「%s〠(内部å: "%S") ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_SVC_INSTALL_FAILED サービス 「%s〠(内部å: "%S") ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_SVC_USERMODE_EXEC_FAILED ユーザーモードサービス "%s" ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_UPDATING システム設定を更新ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_FINISHED セットアップ処ç†ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+SW_PERFORM_MSG_UNINSTALL_MSI %s ã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ Windows Installer を用ã„ã¦ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_UPDATE_LANG_CONFIG 言語設定を変更ã—ã¦ã„ã¾ã™...
+
+SW_PERFORM_MSG_INIT_UNINST アンインストールã®æº–備をã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_DELETE_PREPARE ファイルã®å‰Šé™¤ã®æº–備をã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_DELETE_ERROR ファイル "%s" を削除ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。\r\n\r\nã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã„ã¦ã„るプログラムãŒå®Ÿè¡Œä¸­ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚\r\n「%sã€é–¢ä¿‚ã®ãƒ—ログラムやサービスãŒèµ·å‹•ã—ã¦ã„ã‚‹å ´åˆã¯ã€çµ‚了ã—ã¦ã‹ã‚‰ã€Œå†è©¦è¡Œã€ã‚’クリックã—ã¦ãã ã•ã„。
+SW_PERFORM_MSG_UNINSTALL_SVC サービス 「%s〠をアンインストール中...
+SW_PERFORM_MSG_DELETE "%s" を削除ã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_EASY_INIT 簡易インストーラをビルドã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_WEB_INIT Web インストーラをビルドã—ã¦ã„ã¾ã™...
+SW_PERFORM_MSG_INSTALL_SELOW システムã®å¾©å…ƒãƒã‚¤ãƒ³ãƒˆã‚’作æˆã—ã€å¿…è¦ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’インストールã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã«ã¯æ•°åˆ†é–“ã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™...
+
+
+SW_TAG_USERNAME \ (ユーザー)
+SW_DIRNAME_CONFIG_TOOLS 構æˆãƒ„ール
+SW_DIRNAME_ADMIN_TOOLS 管ç†è€…用ツール
+SW_DIRNAME_LANGUAGE_TOOLS Language Settings
+
+SW_RUN_TEXT_VPNSMGR SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¾ã™ã€‚
+SW_RUN_TEXT_VPNCMGR SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£ã‚’èµ·å‹•ã—ã¾ã™ã€‚
+
+# Do not translate this section !!!
+SW_TAG_USERNAME_ENGLISH \ (User-Mode)
+SW_LINK_NAME_VPNSERVER_SVC SoftEther VPN Server User-mode Service
+SW_LINK_NAME_VPNBRIDGE_SVC SoftEther VPN Bridge User-mode Service
+SW_LONG_VPNSERVER SoftEther VPN Server
+SW_LONG_VPNCLIENT SoftEther VPN Client
+SW_LONG_VPNBRIDGE SoftEther VPN Bridge
+SW_LONG_VPNSMGR SoftEther VPN Server Manager
+SW_LONG_VPNCMGR SoftEther VPN Client Manager
+SW_LANG_SET_FAILED Failed to write the new language setting on lang.config file.
+
+# ショートカットå
+SW_LINK_NAME_VPNSMGR_SHORT SoftEther VPN サーãƒãƒ¼ç®¡ç†
+SW_LINK_NAME_VPNSMGR_SHORT_UM SE-VPN サーãƒãƒ¼ç®¡ç† (ユーザー)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY SE-VPN サーãƒãƒ¼ç®¡ç† (ツール)
+SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM SE-VPN サーãƒãƒ¼ç®¡ç† (ツール・ユーザー)
+SW_LINK_NAME_VPNSMGR_FULL SoftEther VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£
+SW_LINK_NAME_VPNSMGR_COMMENT ローカルã¾ãŸã¯ãƒªãƒ¢ãƒ¼ãƒˆ コンピュータ上ã§å‹•ä½œã—ã¦ã„ã‚‹ SoftEther VPN Server ãŠã‚ˆã³ SoftEther VPN Bridge を管ç†ã™ã‚‹ãŸã‚ã®ç®¡ç†ãƒ„ールã§ã™ã€‚
+
+SW_LINK_NAME_VPNCMGR_SHORT SoftEther VPN クライアント接続
+SW_LINK_NAME_VPNCMGR_FULL SoftEther VPN クライアント接続マãƒãƒ¼ã‚¸ãƒ£
+SW_LINK_NAME_VPNCMGR_COMMENT SoftEther VPN Client を使用ã—㦠VPN サーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT SoftEther VPN クライアント リモート管ç†
+SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM SE-VPN クライアント ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç† (ユーザー)
+SW_LINK_NAME_VPNCMGRTOOLS_FULL SoftEther VPN クライアント リモート管ç†
+
+SW_LINK_NAME_VPNCMGR2_FULL 別ã®ã‚³ãƒ³ãƒ”ュータ㮠SoftEther VPN Client ã®ç®¡ç†
+SW_LINK_NAME_VPNCMGR2_COMMENT 別ã®ã‚³ãƒ³ãƒ”ュータ上㮠SoftEther VPN Client プログラムã«ãƒªãƒ¢ãƒ¼ãƒˆæŽ¥ç¶šã—ã¦ç®¡ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+SW_LINK_NAME_VPNCMGRTRAY_FULL SoftEther VPN Client Manager Startup
+SW_LINK_NAME_VPNCMGRTRAY_COMMENT SoftEther VPN Client ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’タスクãƒãƒ¼ã®é€šçŸ¥é ˜åŸŸã«è¡¨ç¤ºã—ã¾ã™ã€‚
+
+SW_LINK_NAME_EASYINSTALLER 簡易インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰
+SW_LINK_NAME_EASYINSTALLER_COMMENT 自動的ã«ç‰¹å®šã®æŽ¥ç¶šå…ˆã« VPN 接続を開始ã™ã‚‹æ©Ÿèƒ½ã‚’æ­è¼‰ã—㟠SoftEther VPN Client ã®ç°¡æ˜“インストーラを作æˆã™ã‚‹ç®¡ç†è€…å‘ã‘ã®ãƒ„ールã§ã™ã€‚
+
+SW_LINK_NAME_WEBINSTALLER Web インストーラ作æˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰
+SW_LINK_NAME_WEBINSTALLER_COMMENT 自動的ã«ç‰¹å®šã®æŽ¥ç¶šå…ˆã« VPN 接続を開始ã™ã‚‹æ©Ÿèƒ½ã‚’æ­è¼‰ã—㟠SoftEther VPN Client ã® Web インストーラ (ActiveX インストーラ)を作æˆã™ã‚‹ç®¡ç†è€…å‘ã‘ã®ãƒ„ールã§ã™ã€‚
+
+SW_LINK_NAME_VPNCMD SoftEther VPN コマンドライン管ç†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ (vpncmd)
+SW_LINK_NAME_VPNCMD_COMMENT vpncmd を使用ã—ã¦ã€SoftEther VPN Server, SoftEther VPN Bridge ãŠã‚ˆã³ SoftEther VPN Client をコマンドライン・インターフェイスã§ç®¡ç†ã—ã¾ã™ã€‚
+SW_LINK_NAME_TRAFFIC 通信スループット測定ツール
+SW_LINK_NAME_TRAFFIC_COMMENT 通信スループット測定ツールを使用ã—ã¦ã€IP ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã«ã‚ã‚‹ 2 å°ã®ã‚³ãƒ³ãƒ”ュータ間ã§æœ€å¤§é™ã«é€šä¿¡ã‚’è¡Œã„ã€é€šä¿¡é€Ÿåº¦ã‚’ç°¡å˜ã«æ¸¬å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+SW_LINK_NAME_TCP TCP 通信設定最é©åŒ–ユーティリティ
+SW_LINK_NAME_TCP_COMMENT TCP/IP 通信設定を調整ã—ã¦ã€ã“ã®ã‚³ãƒ³ãƒ”ュータ㮠TCP/IP プロトコルを使用ã—ãŸé€šä¿¡é€Ÿåº¦ã‚’å‘上ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+SW_LINK_NAME_SERVICES ã“ã®ã‚³ãƒ³ãƒ”ュータã§å‹•ä½œä¸­ã®ã‚µãƒ¼ãƒ“ス一覧
+SW_LINK_NAME_SERVICES_COMMENT ç¾åœ¨ Windows 上ã§å‹•ä½œã—ã¦ã„るサービス一覧を表示ã—ã¾ã™ã€‚SoftEther VPN 関係ã®ã‚µãƒ¼ãƒ“スã®å‹•ä½œã‚’開始ã¾ãŸã¯åœæ­¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+SW_LINK_NAME_VPNSERVER_SVC_COMMENT SoftEther VPN Server サービスをユーザーモードã§èµ·å‹•ã—ã¾ã™ã€‚
+SW_LINK_NAME_VPNBRIDGE_SVC_COMMENT SoftEther VPN Bridge サービスをユーザーモードã§èµ·å‹•ã—ã¾ã™ã€‚
+
+SW_LINK_NAME_UNINSTALL %s ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«
+SW_LINK_NAME_UNINSTALL_COMMENT インストールã•ã‚Œã¦ã„ã‚‹ %s をアンインストールã—ã¾ã™ã€‚
+
+SW_LINK_NAME_LANGUAGE Configure Display Language (言語設定)
+SW_LINK_NAME_LANGUAGE_COMMENT %s ã®è¡¨ç¤ºè¨€èªžã‚’変更ã—ã¾ã™ã€‚
+
+SW_LINK_NAME_DEBUG デãƒãƒƒã‚°æƒ…å ±åŽé›†ãƒ„ール
+SW_LINK_NAME_DEBUG_COMMENT SoftEther VPN ã®ãƒ‡ãƒãƒƒã‚°æƒ…報をåŽé›†ã—ã¾ã™ã€‚サãƒãƒ¼ãƒˆæ‹…当者ã‹ã‚‰ä¾é ¼ãŒã‚ã£ãŸå ´åˆã®ã¿ä½¿ç”¨ã—ã¦ãã ã•ã„。
+
+
diff --git a/src/bin/hamcore/time.htm b/src/bin/hamcore/time.htm
new file mode 100644
index 00000000..8b1afe35
--- /dev/null
+++ b/src/bin/hamcore/time.htm
@@ -0,0 +1,168 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="ja">
+<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
+<title>Œ»ÝŽž‚͉½Žž‚Å‚µ‚傤‚©H</title>
+<STYLE type="text/css">
+<!--
+BODY, TR, TABLE, TD, H1, H2, H3, H4, P, LI, DIV
+{
+ font-family:"Verdana", "Geneva", "Arial", "Helvetica", "sans-serif", "‚l‚r ‚oƒSƒVƒbƒN", "MS UI Gothic";
+ font-size:10pt;
+ line-height:1.6em;
+}
+
+BODY
+{
+ color:#000000;
+ background-color:#FFFFFF;
+ margin-left:5px;
+ margin-top:5px;
+ padding-left:5px;
+ padding-top:5px;
+ border-collapse:collapse;
+}
+
+TABLE
+{
+ border:0px;
+ margin-left:0px;
+ margin-top:0px;
+ padding-left:0px;
+ padding-top:0px;
+ background-color:#FFFFFF;
+}
+
+A:visited
+{
+ color:#0000FF;
+}
+
+A:hover
+{
+ color:#FF6600;
+}
+
+P A, LI A, TD A
+{
+ color:#0000FF;
+ margin:0px 2px 0px 2px;
+}
+
+P
+{
+ margin:0px;
+ padding-top: 5px;
+ padding-right: 0px;
+ padding-bottom: 5px;
+ padding-left: 0px;
+}
+
+H1, H2, H3, H4
+{
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ font-weight:bold;
+}
+
+IMG
+{
+ border:0px;
+ margin:0px;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+}
+
+H2
+{
+ font-size:12pt;
+ margin:6px 0px 5px 0px;
+ padding-top: 3px;
+ padding-right: 3px;
+ padding-bottom: 3px;
+ padding-left: 3px;
+ background-repeat:repeat-y;
+ border-right:2px dotted #5F81CA;
+ border-bottom:2px dotted #3F61AA;
+}
+UL
+{
+ margin:0px;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 5px;
+ padding-left: 1.5em;
+}
+
+UL LI
+{
+ margin:8px 0px 8px 0px;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+}
+
+UL LI H4
+{
+ color:#000000;
+ font-weight:bold;
+}
+
+UL LI P
+{
+ margin:6px 6px 0px 5px;
+}
+
+HR
+{
+ color: #ddddee;
+ background-color: #ddddee;
+ height: 4px;
+ border-color: #eeeeee #7777dd #7777dd #eeeeee;
+ border-width: 1px;
+ border-style: solid;
+}
+
+-->
+</STYLE>
+</head>
+
+<body>
+
+<table width="584">
+ <tr>
+ <td>
+ <h2>Œ»ÝŽž‚͉½Žž‚Å‚µ‚傤‚©H</h2>
+ <p><b>‚±‚̃y[ƒW‚ÍAŒ»ÝŽž‚ðƒŠƒAƒ‹ƒ^ƒCƒ€‚Å•\Ž¦‚·‚邽‚ß‚Ì Web ƒy[ƒW‚Å‚·B</b></p>
+ <ul>
+ <li type="square"><font size="3" color="#008000"><b>
+ Œ»ÝŽž‚ð’m‚邱‚Æ‚ÍAŽÐ‰ï¶Šˆ‚Ìã‚Å‚Æ‚Ä‚à–ð‚É—§‚¿‚Ü‚·B</b></font></li>
+ </ul>
+ <p>‚±‚̃y[ƒW‚Í HTTPS Web ƒT[ƒo[‚É‚æ‚Á‚ăzƒXƒg‚³‚ê‚Ä‚¢‚Ü‚·Bhttps ƒvƒƒgƒRƒ‹ (’Êí‚̓|[ƒg 80)
+ ‚Å‚±‚̃y[ƒW‚ɃAƒNƒZƒX‚·‚邱‚Æ‚ÅAŒ»ÝŽž‚ð’m‚邱‚Æ‚ª‚Å‚«‚Ü‚·B<p align="center"><font size="5">Œ»ÝŽž:
+ <font face="Arial Black">$NOW$</font></font><p>@<p>
+ Œ»ÝŽž‚Ì•\Ž¦‚ðXV‚µ‚½‚¢ê‡‚ÍAƒy[ƒW‚ðÄ“Ç‚Ýž‚Ý‚µ‚Ä‚­‚¾‚³‚¢B<h2>‚Æ‚Ä‚à–ð‚É—§‚‚¨Š©‚߃Šƒ“ƒNW‚Å‚·</h2>
+ <ul>
+ <li><a target="_blank" href="http://www.yahoo.co.jp/">Yahoo! JAPAN</a></li>
+ <li><a target="_blank" href="http://www.google.co.jp/">Google</a></li>
+ <li><a target="_blank" href="http://www.softether.com/jp/">
+ ƒ\ƒtƒgƒC[ƒTŠ”Ž®‰ïŽÐ</a></li>
+ <li><a target="_blank" href="http://www.tsukuba.ac.jp/">‘—§‘åŠw–@l’}”g‘åŠw</a></li>
+ </ul>
+ <p>@</td>
+ </tr>
+</table>
+
+<hr>
+<address>
+ <font size="3">HTTPS Server at $HOST$ Port $PORT$</font></address>
+
+</body>
+
+</html>
diff --git a/src/bin/hamcore/vpn16.exe b/src/bin/hamcore/vpn16.exe
new file mode 100644
index 00000000..3ece95d9
--- /dev/null
+++ b/src/bin/hamcore/vpn16.exe
Binary files differ
diff --git a/src/bin/hamcore/vpn_driver.inf b/src/bin/hamcore/vpn_driver.inf
new file mode 100644
index 00000000..14e1fad6
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver.inf
@@ -0,0 +1,107 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = $MONTH$/$DAY$/$YEAR$, $VER_MAJOR$.$VER_MINOR$.0.$VER_BUILD$
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+$TAG_SYS_NAME$ = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+$TAG_SYS_NAME$, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_$TAG_INSTANCE_NAME$
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_$TAG_INSTANCE_NAME$"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , $TAG_SYS_NAME$
+HKR, NDIS, LogDriverName, , "Neo_$TAG_INSTANCE_NAME$"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\$TAG_SYS_NAME$
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\Neo_$TAG_INSTANCE_NAME$.sys"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_$TAG_INSTANCE_NAME$"
+Neo.Service.DispName = "VPN Client Device Driver - $TAG_INSTANCE_NAME$"
+Neo.Service.Desc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "$TAG_MAC_ADDRESS$"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/vpn_driver.sys b/src/bin/hamcore/vpn_driver.sys
new file mode 100644
index 00000000..58d09d24
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver.sys
Binary files differ
diff --git a/src/bin/hamcore/vpn_driver6.sys b/src/bin/hamcore/vpn_driver6.sys
new file mode 100644
index 00000000..47ab9f5d
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver6.sys
Binary files differ
diff --git a/src/bin/hamcore/vpn_driver6_x64.sys b/src/bin/hamcore/vpn_driver6_x64.sys
new file mode 100644
index 00000000..c8d78de0
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver6_x64.sys
Binary files differ
diff --git a/src/bin/hamcore/vpn_driver_9x.inf b/src/bin/hamcore/vpn_driver_9x.inf
new file mode 100644
index 00000000..512456fa
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver_9x.inf
@@ -0,0 +1,111 @@
+; VPN Client Device Driver for Windows 98 Second Edition / Windows Millennium Edition
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = $MONTH$/$DAY$/$YEAR$, $VER_MAJOR$.$VER_MINOR$.0.$VER_BUILD$
+
+[Manufacturer]
+%CompanyName% = SoftEther
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+$TAG_SYS_NAME$ = 1
+
+[DestinationDirs]
+DefaultDestDir = 11
+Neo.CopyFiles.Sys = 11
+
+[Neo.CopyFiles.Sys]
+$TAG_SYS_NAME$, , , 2
+
+[SoftEther]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_$TAG_INSTANCE_NAME$
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , MediaType, 0, 1
+HKR, , AdapterType, 0, 5
+HKR, , BusType, 0, 5
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, , DriverVersion, 0, "3.0.0.6631"
+HKR, , NeoVersion, 0, "3.0.0.6631"
+HKR, , DevLoader, , "*ndis"
+HKR, , DeviceVxDs, , "$TAG_SYS_NAME$"
+HKR, , MatchingDeviceId, , "NeoAdapter_$TAG_INSTANCE_NAME$"
+HKR, , EnumPropPages, 0, "netdi.dll,EnumPropPages"
+HKR, NDIS, LogDriverName, , "Neo_$TAG_INSTANCE_NAME$"
+HKR, NDIS, MajorNdisVersion, 1, 03
+HKR, NDIS, MinorNdisVersion, 1, 0A
+HKR, Ndi, DeviceID, , "NeoAdapter_$TAG_INSTANCE_NAME$"
+HKR, Ndi\Interfaces, DefUpper, , "ndis3"
+HKR, Ndi\Interfaces, UpperRange, , "ndis3"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "1000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %11%\$TAG_SYS_NAME$
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis3"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\$TAG_SYS_NAME$"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_$TAG_INSTANCE_NAME$"
+Neo.Service.DispName = "VPN Client Device Driver - $TAG_INSTANCE_NAME$"
+Neo.Service.Desc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "$TAG_MAC_ADDRESS$"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/vpn_driver_9x.sys b/src/bin/hamcore/vpn_driver_9x.sys
new file mode 100644
index 00000000..f6f7c23f
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver_9x.sys
Binary files differ
diff --git a/src/bin/hamcore/vpn_driver_x64.inf b/src/bin/hamcore/vpn_driver_x64.inf
new file mode 100644
index 00000000..d06467aa
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver_x64.inf
@@ -0,0 +1,107 @@
+; VPN Client Device Driver for Windows 2000 and Greater
+;
+; Copyright (c) SoftEther VPN Project at University of Tsukuba, Japan. All Rights Reserved.
+; http://www.softether.org/
+
+[Version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider = %CompanyName%
+DriverVer = $MONTH$/$DAY$/$YEAR$, $VER_MAJOR$.$VER_MINOR$.0.$VER_BUILD$
+
+[Manufacturer]
+%CompanyName% = SoftEther, NTamd64
+
+[SourceDisksNames]
+1=%DiskDescription%, "", ,
+
+[SourceDisksFiles]
+$TAG_SYS_NAME$ = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+Neo.CopyFiles.Sys = 12
+
+[Neo.CopyFiles.Sys]
+$TAG_SYS_NAME$, , , 2
+
+[SoftEther.NTamd64]
+%NeoAdapter.DeviceDesc% = NeoAdapter.Install, NeoAdapter_$TAG_INSTANCE_NAME$
+
+[NeoAdapter.Install]
+Characteristics = 0x1
+AddReg = Neo.Reg, NeoAdapter.Ndi
+CopyFiles = Neo.CopyFiles.Sys
+*IfType = 6
+*MediaType = 0
+*PhysicalMediaType = 0
+
+[NeoAdapter.Install.Services]
+AddService = %Neo.Service.Name%, 2, Neo.Service, Neo.EventLog, , %Neo, EventLog.Name%
+
+[NeoAdapter.Ndi]
+HKR, , NetworkAddress, 0, %DefaultAddress%
+HKR, Ndi, DeviceID, , "NeoAdapter_$TAG_INSTANCE_NAME$"
+HKR, , DevLoader, , ndis
+HKR, , DeviceVxDs, , $TAG_SYS_NAME$
+HKR, NDIS, LogDriverName, , "Neo_$TAG_INSTANCE_NAME$"
+HKR, NDIS, MajorNdisVersion, 1, 5
+HKR, NDIS, MinorNdisVersion, 1, 0
+HKR, Ndi\Interfaces, DefUpper, , "ndis5"
+HKR, Ndi\Interfaces, UpperRange, , "ndis5"
+HKR, Ndi\Interfaces, LowerRange, , "ethernet"
+HKR, Ndi\Interfaces, DefLower, , "ethernet"
+HKR, Ndi\Install, ndis5, , "Neo.CopyFiles.Sys"
+HKR, Ndi\Params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
+HKR, Ndi\Params\NetworkAddress, type, 0, "edit"
+HKR, Ndi\Params\NetworkAddress, LimitText, 0, "12"
+HKR, Ndi\Params\NetworkAddress, UpperCase, 0, "1"
+HKR, Ndi\Params\NetworkAddress, default, 0, %DefaultAddress%
+HKR, Ndi\Params\NetworkAddress, optional, 0, "0"
+HKR, Ndi\Params\MaxSpeed, ParamDesc, 0, %MaxSpeed%
+HKR, Ndi\Params\MaxSpeed, type, 0, "int"
+HKR, Ndi\Params\MaxSpeed, default, 0, "100"
+HKR, Ndi\Params\MaxSpeed, min, 0, "0"
+HKR, Ndi\Params\MaxSpeed, max, 0, "2000"
+HKR, Ndi\Params\MaxSpeed, step, 0, "1"
+HKR, Ndi\Params\MaxSpeed, Base, 0, "10"
+HKR, Ndi\Params\KeepLink, ParamDesc, 0, %KeepLink%
+HKR, Ndi\Params\KeepLink, type, 0, "enum"
+HKR, Ndi\Params\KeepLink\enum, "1", 0, %On%
+HKR, Ndi\Params\KeepLink\enum, "0", 0, %Off%
+HKR, Ndi\Params\KeepLink, default, 0, "0"
+
+
+[Neo.Service]
+DisplayName = %Neo.Service.DispName%
+Description = %Neo.Service.Desc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\$TAG_SYS_NAME$
+LoadOrderGroup = NDIS
+
+[Neo.Reg]
+HKR, Ndi, Service, 0, Neo.Service.Name
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+
+[Neo.EventLog]
+HKR, , EventMessageFile, 0x00020000, "%11%\IoLogMsg.dll;%12%\$TAG_SYS_NAME$"
+HKR, , TypesSupported, 0x00010001, 7
+
+[Strings]
+CompanyName = "SoftEther VPN Project"
+DiskDescription = "VPN Client Device Driver Install Disk"
+Neo.Service.Name = "Neo_$TAG_INSTANCE_NAME$"
+Neo.Service.DispName = "VPN Client Device Driver - $TAG_INSTANCE_NAME$"
+Neo.Service.Desc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+NeoAdapter.DeviceDesc = "VPN Client Adapter - $TAG_INSTANCE_NAME$"
+Neo.EventLog.Name = "Neo"
+NetworkAddress = "MAC Address"
+DefaultAddress = "$TAG_MAC_ADDRESS$"
+MaxSpeed = "Indicate Speed (Mbps)"
+KeepLink = "Keep Link"
+On = "On"
+Off = "Off"
diff --git a/src/bin/hamcore/vpn_driver_x64.sys b/src/bin/hamcore/vpn_driver_x64.sys
new file mode 100644
index 00000000..d269ca82
--- /dev/null
+++ b/src/bin/hamcore/vpn_driver_x64.sys
Binary files differ
diff --git a/src/bin/hamcore/vpninstall_cn.inf b/src/bin/hamcore/vpninstall_cn.inf
new file mode 100644
index 00000000..126d5f34
--- /dev/null
+++ b/src/bin/hamcore/vpninstall_cn.inf
@@ -0,0 +1,30 @@
+# SoftEther VPN Client 自动安装设定文件
+# (为了 VPN Client Web 安装程åºçš„æ ·å“设定文件)
+#
+# Copyright (c) SoftEther Project at University of Tsukuba, Japan.
+# All Rights Reserved.
+#
+# 制作简易 Web 安装程åºçš„时候,请编辑这个文件的内容。
+#
+# ※ 如果在这个文件内包å«ä¸­æ–‡ç­‰çš„ 2 字节字符,
+# 字符编ç è¯·ä½¿ç”¨ UTF-8。
+#
+# 文字 "#" 在 (sharp) 开始的行是评语。
+
+
+# vpninstall.exe 版本å·
+# (请在 vpninstall.exe 文件的 [属性] ç”»é¢ç¡®è®¤ã€‚
+# 请在这里输入文件版本的末尾的 4 ä½æ•´æ•°ã€‚)
+VpnInstallBuild $VER_BUILD$
+VpnClientBuild $VER_BUILD$
+
+
+# 有关Windows 事情的 VPN Client 包装文件的信æ¯
+# ※ 请指定 Web æœåŠ¡å™¨ä¸Šçš„ URL。盘上的传çƒåä¸èƒ½æŒ‡å®šã€‚
+VpnClientPath http://example.com/any_folder/$PACKAGE_FILENAME$
+
+# 是ä¸æ˜¯è¦ VPN Client 的安装完æˆç´§æŽ¥ä¹‹åŽçš„åŠ¨ä½œæ–¹å¼ "简å•æ¨¡å¼" å’Œ "标准模å¼" 的哪边。
+# 写 true çš„è¯ "标准模å¼",那个以外的情况æˆä¸º "简å•æ¨¡å¼"。
+NormalMode $NORMAL_MODE$
+
+
diff --git a/src/bin/hamcore/vpninstall_en.inf b/src/bin/hamcore/vpninstall_en.inf
new file mode 100644
index 00000000..bf41ca57
--- /dev/null
+++ b/src/bin/hamcore/vpninstall_en.inf
@@ -0,0 +1,30 @@
+# SoftEther VPN Client Web Installer Configuration File
+# (The sample file for VPN Client Web Installer)
+#
+# Copyright (c) SoftEther Project at University of Tsukuba, Japan.
+# All Rights Reserved.
+#
+# Modify the contents of this file to deploy a Web Installer.
+#
+# Note: Encoding format must be UTF-8.
+#
+# Lines start with "#" are comments.
+
+
+# vpninstall.exe Build Number
+# (Retrieve the build number which is four-digit number.
+# You can see it in vpninstall.exe property screen by Windows Explorer.)
+VpnInstallBuild $VER_BUILD$
+VpnClientBuild $VER_BUILD$
+
+
+# VPN Client Package File for Windows URL
+# You must specify the URL (HTTP, HTTPS or FTP). Local filename is not allowed.
+VpnClientPath http://example.com/any_folder/$PACKAGE_FILENAME$
+
+
+# Specify "true" to use the Normal Mode, otherwise "Easy Mode" as the initial mode
+# of VPN Client Manager.
+NormalMode $NORMAL_MODE$
+
+
diff --git a/src/bin/hamcore/vpninstall_ja.inf b/src/bin/hamcore/vpninstall_ja.inf
new file mode 100644
index 00000000..a6730a04
--- /dev/null
+++ b/src/bin/hamcore/vpninstall_ja.inf
@@ -0,0 +1,35 @@
+# SoftEther VPN Client Web インストーラ設定ファイル
+# (VPN クライアント Web インストーラ用ã®ã‚µãƒ³ãƒ—ル設定ファイル)
+#
+# Copyright (c) SoftEther Project at University of Tsukuba, Japan.
+# All Rights Reserved.
+#
+# Web インストーラを作æˆã™ã‚‹éš›ã¯ã€ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容を編集ã—ã¦ãã ã•ã„。
+#
+# ※ ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«å†…ã«æ—¥æœ¬èªžãªã©ã® 2 ãƒã‚¤ãƒˆæ–‡å­—列をå«ã‚ã‚‹å ´åˆã¯ã€
+# エンコード方å¼ã¯ UTF-8 を使用ã—ã¦ä¿å­˜ã—ã¦ãã ã•ã„。
+#
+# 文字 "#" (シャープ) ã§ã¯ã˜ã¾ã‚‹è¡Œã¯ã‚³ãƒ¡ãƒ³ãƒˆã§ã™ã€‚
+
+
+# vpninstall.exe 自体ã®ãƒ“ルド番å·
+# (設置ã™ã‚‹ vpninstall.exe ã® [プロパティ] ã‚’ Windows エクスプローラãªã©
+# ã§ç¢ºèªã—ã€[ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±] 内㮠[ファイルãƒãƒ¼ã‚¸ãƒ§ãƒ³] ã®æœ«å°¾ã® 4 æ¡ã®
+# æ•´æ•°ã‚’ã“ã“ã«è¨˜å…¥ã—ã¾ã™)
+VpnInstallBuild $VER_BUILD$
+VpnClientBuild $VER_BUILD$
+
+
+# Windows 用㮠VPN Client パッケージファイルã«é–¢ã™ã‚‹æƒ…å ±
+# ※ Web インストーラã®å ´åˆã¯ã€ã“ã“ã§æŒ‡å®šã™ã‚‹ãƒ‘ス㯠HTTPã€HTTPS ã¾ãŸã¯ FTP
+# ã® URL ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šãªã©ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ•ã‚¡ã‚¤ãƒ«
+# を指定ã™ã‚‹ã“ã¨ã¯ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ä¸Šã®ç†ç”±ã«ã‚ˆã‚Šç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚
+VpnClientPath http://example.com/any_folder/$PACKAGE_FILENAME$
+
+
+# VPN Client ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å®Œäº†å¾Œã®å‹•ä½œãƒ¢ãƒ¼ãƒ‰ã‚’「簡易モードã€ã¨ã€Œé€šå¸¸ãƒ¢ãƒ¼ãƒ‰ã€ã®
+# ã©ã¡ã‚‰ã«ã™ã‚‹ã‹ã‚’é¸æŠžã—ã¾ã™ã€‚true ã¨æ›¸ãã¨ã€Œé€šå¸¸ãƒ¢ãƒ¼ãƒ‰ã€ã€ãれ以外ã®å ´åˆã¯
+# 「簡易モードã€ã«ãªã‚Šã¾ã™ã€‚
+NormalMode $NORMAL_MODE$
+
+
diff --git a/src/bin/hamcore/vpnweb_sample_cn.htm b/src/bin/hamcore/vpnweb_sample_cn.htm
new file mode 100644
index 00000000..73390e37
--- /dev/null
+++ b/src/bin/hamcore/vpnweb_sample_cn.htm
@@ -0,0 +1,71 @@
+<HTML>
+<HEAD>
+ <TITLE>VPN Client Web Installer Deployment Page Sample HTML</TITLE>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <META http-equiv="Content-Language" content="ja">
+ <style type="text/css">
+ <!--
+BODY, TABLE, TR, TABLE, TD, H1, H2, H3, H4, P, LI, DIV
+{
+ font-family: "Arial", "Geneva", "Helvetica", "sans-serif", "MS PGothic", "MS UI Gothic", "Osaka";
+ font-size:small;
+ line-height:1.2em;
+}
+ -->
+ </style>
+</HEAD>
+<BODY>
+
+<h3>VPN Client Web Installer Deployment Page Sample HTML File</h3>
+<p>This HTML file is a sample.<br>
+To create a Web Installer using "SoftEther VPN Client Web Installer", please refer the following explanation and the HTML source of this file.</p>
+<table border="1" cellspacing="0" cellpadding="4" style="border-collapse: collapse" bordercolor="#008000" id="table1">
+ <tr>
+ <td style="font-family: Consolas, Courier New, MS Gothic; font-size: 10pt">&lt;OBJECT ID=&quot;VpnWebInstaller&quot;<br>
+&nbsp;&nbsp;&nbsp; CLASSID=&quot;CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2&quot;<br>
+&nbsp;&nbsp;&nbsp; CODEBASE=&quot;vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerExeUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.exe</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerInfUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.inf</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;SettingUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/auto_setting.vpn</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;LanguageID&quot; VALUE=&quot;<b><font color="#008000">EN</font></b>&quot;&gt;<br>
+ &lt;/OBJECT&gt;</td>
+ </tr>
+</table>
+<p>To create a web page which boot the VPN Client Web Installer, insert HTML codes as the above. The HTML code refers the path of the ActiveX control, and the parameters which will be passed to the ActiveX.</p>
+<p>You have to modify the strings which are emphasized in green fonts above according to the environment of the web server which you deploy on.<br>
+(Notice that the above sample won't work staying in the ogriginal code, because the original sample specifies the example URLs.)<br>
+<br>
+For details, refer the online manuals or <b> <a target="_blank" href="http://www.softether.org/">http://www.softether.org/</a></b>.<br>
+<br>
+<b><font color="#808000">Note: the parameters &quot;SettingUrl&quot; and &quot;LanguageID&quot; are optional.</font></b></p>
+<p> </p>
+
+
+<!-- The below code is an example to embed the ActiveX control. -->
+<h3>The below code is an example to embed the ActiveX control.</h3>
+<p>Notice: This HTML file is a sample. Parameters for vpnweb.cab control are dummy.<BR>Therefore, after you click Start VPN Connection button, you will get an error message.</p>
+<table border="1" cellspacing="1" cellpadding="6" style="border-collapse: collapse" width="450" bordercolor="#808000" id="table2">
+ <tr>
+ <td align="center" valign="top">
+
+<OBJECT ID="VpnWebInstaller"
+ CLASSID="CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2"
+ CODEBASE="vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$">
+ <PARAM NAME="InstallerExeUrl" VALUE="http://example.com/any_folder/vpninstall.exe">
+ <PARAM NAME="InstallerInfUrl" VALUE="http://example.com/any_folder/vpninstall.inf">
+ <PARAM NAME="SettingUrl" VALUE="http://example.com/any_folder/auto_setting.vpn">
+ <PARAM NAME="LanguageID" VALUE="EN">
+</OBJECT>
+
+ </td>
+ </tr>
+</table>
+ <p>If the VPN Client Web Installer ActiveX Control is not displayed on the above brown rectangle, verity the requirements, and make sure that your Web browser allows ActiveX control.</p>
+
+
+<p> </p>
+<p align="right"><i>Copyright (c) SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.</i></p>
+
+
+</BODY>
+</HTML>
diff --git a/src/bin/hamcore/vpnweb_sample_en.htm b/src/bin/hamcore/vpnweb_sample_en.htm
new file mode 100644
index 00000000..73390e37
--- /dev/null
+++ b/src/bin/hamcore/vpnweb_sample_en.htm
@@ -0,0 +1,71 @@
+<HTML>
+<HEAD>
+ <TITLE>VPN Client Web Installer Deployment Page Sample HTML</TITLE>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <META http-equiv="Content-Language" content="ja">
+ <style type="text/css">
+ <!--
+BODY, TABLE, TR, TABLE, TD, H1, H2, H3, H4, P, LI, DIV
+{
+ font-family: "Arial", "Geneva", "Helvetica", "sans-serif", "MS PGothic", "MS UI Gothic", "Osaka";
+ font-size:small;
+ line-height:1.2em;
+}
+ -->
+ </style>
+</HEAD>
+<BODY>
+
+<h3>VPN Client Web Installer Deployment Page Sample HTML File</h3>
+<p>This HTML file is a sample.<br>
+To create a Web Installer using "SoftEther VPN Client Web Installer", please refer the following explanation and the HTML source of this file.</p>
+<table border="1" cellspacing="0" cellpadding="4" style="border-collapse: collapse" bordercolor="#008000" id="table1">
+ <tr>
+ <td style="font-family: Consolas, Courier New, MS Gothic; font-size: 10pt">&lt;OBJECT ID=&quot;VpnWebInstaller&quot;<br>
+&nbsp;&nbsp;&nbsp; CLASSID=&quot;CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2&quot;<br>
+&nbsp;&nbsp;&nbsp; CODEBASE=&quot;vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerExeUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.exe</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerInfUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.inf</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;SettingUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/auto_setting.vpn</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;LanguageID&quot; VALUE=&quot;<b><font color="#008000">EN</font></b>&quot;&gt;<br>
+ &lt;/OBJECT&gt;</td>
+ </tr>
+</table>
+<p>To create a web page which boot the VPN Client Web Installer, insert HTML codes as the above. The HTML code refers the path of the ActiveX control, and the parameters which will be passed to the ActiveX.</p>
+<p>You have to modify the strings which are emphasized in green fonts above according to the environment of the web server which you deploy on.<br>
+(Notice that the above sample won't work staying in the ogriginal code, because the original sample specifies the example URLs.)<br>
+<br>
+For details, refer the online manuals or <b> <a target="_blank" href="http://www.softether.org/">http://www.softether.org/</a></b>.<br>
+<br>
+<b><font color="#808000">Note: the parameters &quot;SettingUrl&quot; and &quot;LanguageID&quot; are optional.</font></b></p>
+<p> </p>
+
+
+<!-- The below code is an example to embed the ActiveX control. -->
+<h3>The below code is an example to embed the ActiveX control.</h3>
+<p>Notice: This HTML file is a sample. Parameters for vpnweb.cab control are dummy.<BR>Therefore, after you click Start VPN Connection button, you will get an error message.</p>
+<table border="1" cellspacing="1" cellpadding="6" style="border-collapse: collapse" width="450" bordercolor="#808000" id="table2">
+ <tr>
+ <td align="center" valign="top">
+
+<OBJECT ID="VpnWebInstaller"
+ CLASSID="CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2"
+ CODEBASE="vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$">
+ <PARAM NAME="InstallerExeUrl" VALUE="http://example.com/any_folder/vpninstall.exe">
+ <PARAM NAME="InstallerInfUrl" VALUE="http://example.com/any_folder/vpninstall.inf">
+ <PARAM NAME="SettingUrl" VALUE="http://example.com/any_folder/auto_setting.vpn">
+ <PARAM NAME="LanguageID" VALUE="EN">
+</OBJECT>
+
+ </td>
+ </tr>
+</table>
+ <p>If the VPN Client Web Installer ActiveX Control is not displayed on the above brown rectangle, verity the requirements, and make sure that your Web browser allows ActiveX control.</p>
+
+
+<p> </p>
+<p align="right"><i>Copyright (c) SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.</i></p>
+
+
+</BODY>
+</HTML>
diff --git a/src/bin/hamcore/vpnweb_sample_ja.htm b/src/bin/hamcore/vpnweb_sample_ja.htm
new file mode 100644
index 00000000..270a72b8
--- /dev/null
+++ b/src/bin/hamcore/vpnweb_sample_ja.htm
@@ -0,0 +1,72 @@
+<HTML>
+<HEAD>
+ <TITLE>VPN クライアント Web インストーラ設置ページ サンプル</TITLE>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <META http-equiv="Content-Language" content="ja">
+ <style type="text/css">
+ <!--
+BODY, TABLE, TR, TABLE, TD, H1, H2, H3, H4, P, LI, DIV
+{
+ font-family: "Meiryo UI", "Meiryo", "Tahoma", "Verdana", "Arial", "Geneva", "Helvetica", "sans-serif", "MS PGothic", "MS UI Gothic", "Osaka";
+ font-size:small;
+ line-height:1.6em;
+}
+ -->
+ </style>
+</HEAD>
+<BODY>
+
+<h3>VPN クライアント Web インストーラ設置ページã®ã‚µãƒ³ãƒ—ル HTML ファイル</h3>
+<p>ã“ã® HTML ファイルã¯ã‚µãƒ³ãƒ—ルã§ã™ã€‚<br>
+「SoftEther VPN クライアント Web インストーラã€ãƒ—ログラムを用ã„㦠Web インストーラを作æˆã™ã‚‹å ´åˆã¯ã€ä¸‹è¨˜ã®äº‹é …ã¨æœ¬ HTML
+ファイルã®å†…容 (HTML ソースコード) ã‚’å‚考ã«ã—ã¦ãã ã•ã„。</p>
+<table border="1" cellspacing="0" cellpadding="4" style="border-collapse: collapse" bordercolor="#008000" id="table1">
+ <tr>
+ <td style="font-family: Consolas, Courier New, MS Gothic; font-size: 10pt">&lt;OBJECT ID=&quot;VpnWebInstaller&quot;<br>
+&nbsp;&nbsp;&nbsp; CLASSID=&quot;CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2&quot;<br>
+&nbsp;&nbsp;&nbsp; CODEBASE=&quot;vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerExeUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.exe</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;InstallerInfUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/vpninstall.inf</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;SettingUrl&quot; VALUE=&quot;<b><font color="#008000">http://example.com/any_folder/auto_setting.vpn</font></b>&quot;&gt;<br>
+&nbsp;&nbsp;&nbsp; &lt;PARAM NAME=&quot;LanguageID&quot; VALUE=&quot;<b><font color="#008000">JA</font></b>&quot;&gt;<br>
+ &lt;/OBJECT&gt;</td>
+ </tr>
+</table>
+<p>VPN クライアント Web インストーラを呼ã³å‡ºã™ãŸã‚ã® Web ページを作æˆã™ã‚‹ãŸã‚ã«ã¯ã€Web インストーラを実行ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã™ã‚‹ ActiveX コントロールã¨ãã®ãƒ‘ラメータを指定ã™ã‚‹ãŸã‚ã«ã€HTML ファイル中ã«ä¸Šè¨˜ã®ã‚ˆã†ãªã‚³ãƒ¼ãƒ‰ã‚’挿入ã—ã¦ãã ã•ã„。</p>
+<p>ãã®éš›ã€ä¸Šè¨˜ã«ãŠã„ã¦ç·‘色ã®ãƒ•ã‚©ãƒ³ãƒˆã§å¼·èª¿ã•ã‚Œã¦ã„る部分をã€è¨­ç½®ã™ã‚‹ Web サーãƒãƒ¼ãªã©ã®ç’°å¢ƒã«ã‚ã‚ã›ã¦è¨­å®šã—ã¦ãã ã•ã„。<br>
+(上記ã®ã‚µãƒ³ãƒ—ルã®ã¾ã¾ã§ã¯å­˜åœ¨ã—ãªã„ URL を指ã—ã¦ã„ã‚‹ãŸã‚ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©ã¯æ­£å¸¸ã«å‹•ä½œã—ã¾ã›ã‚“。)<br>
+<br>
+詳細ã«ã¤ã„ã¦ã¯æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã«åŒæ¢±ã•ã‚Œã¦ã„るオンラインマニュアルã¾ãŸã¯ <b> <a target="_blank" href="http://www.softether.org/">http://www.softether.org/</a></b> ã‚’ã”確èªãã ã•ã„。<br>
+<br>
+<b><font color="#808000">※ パラメータ &quot;SettingUrl&quot;, &quot;LanguageID&quot; ã«ã¤ã„ã¦ã¯ã€æŒ‡å®šã—ãªãã¦ã‚‚動作ã—ã¾ã™ã€‚</font></b></p>
+<p> </p>
+
+
+<!-- 下記ã«å®Ÿéš›ã« ActiveX コントロールを埋ã‚込んã ä¾‹ã§ã™ã€‚ -->
+<h3>下記ã«å®Ÿéš›ã« ActiveX コントロールを埋ã‚込んã ä¾‹ã‚’示ã—ã¾ã™</h3>
+<p>ã”注æ„: ã“ã® HTML ファイルã¯ã‚µãƒ³ãƒ—ルã§ã‚ã‚Šã€vpnweb.cab ã«å¯¾ã—ã¦æ¸¡ã•ã‚Œã‚‹ãƒ‘ラメータã®å†…容ã¨ã—ã¦ã¯ãƒ€ãƒŸãƒ¼ã® URL ãŒå…¥ã£ã¦ã„ã¾ã™ã€‚<br>ãã®ãŸã‚「VPN 接続ã®é–‹å§‹ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ãŸå ´åˆã§ã‚‚ VPN クライアントソフトウェアã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ç­‰ã®å‡¦ç†ã¯é–‹å§‹ã•ã‚Œã¾ã›ã‚“。</p>
+<table border="1" cellspacing="1" cellpadding="6" style="border-collapse: collapse" width="450" bordercolor="#808000" id="table2">
+ <tr>
+ <td align="center" valign="top">
+
+<OBJECT ID="VpnWebInstaller"
+ CLASSID="CLSID:64F1A16B-C3EE-484C-B551-35338A9BB6D2"
+ CODEBASE="vpnweb.cab#Version=$VER_MAJOR$,$VER_MINOR$,0,$VER_BUILD$">
+ <PARAM NAME="InstallerExeUrl" VALUE="http://example.com/any_folder/vpninstall.exe">
+ <PARAM NAME="InstallerInfUrl" VALUE="http://example.com/any_folder/vpninstall.inf">
+ <PARAM NAME="SettingUrl" VALUE="http://example.com/any_folder/auto_setting.vpn">
+ <PARAM NAME="LanguageID" VALUE="JA">
+</OBJECT>
+
+ </td>
+ </tr>
+</table>
+ <p>※ 上記ã®èŒ¶è‰²ã®æž å†…ã« VPN クライアント Web インストーラ㮠ActiveX コントロールãŒè¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ã€å‹•ä½œç’°å¢ƒã‚’確èªã—ã¦ãã ã•ã„。ã¾ãŸ Web ブラウザ㌠ActiveX コントロールをå—ã‘入れる設定ã«ãªã£ã¦ã„ã‚‹ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。</p>
+
+
+<p> </p>
+<p align="right"><i>Copyright (c) SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.</i></p>
+
+
+</BODY>
+</HTML>
diff --git a/src/bin/hamcore/warning_cn.txt b/src/bin/hamcore/warning_cn.txt
new file mode 100644
index 00000000..433ca635
--- /dev/null
+++ b/src/bin/hamcore/warning_cn.txt
@@ -0,0 +1,137 @@
+关于 SoftEther VPN çš„é‡è¦å£°æ˜Ž
+
+嵌入在本软件的 VPN 通信功能比以往任何时候都è¦å¼ºå¤§ã€‚这个强大的 VPN 能力将为您带æ¥å·¨å¤§çš„好处。然而,如果你滥用此软件, IT å¯èƒ½ä¼šæŸå®³ä½ è‡ªå·±ã€‚为了é¿å…这样的风险,本文档为愿æ„使用本软件的客户公布了é‡è¦æ示。下é¢çš„说明是éžå¸¸é‡è¦çš„。仔细阅读并ç†è§£å®ƒã€‚
+
+
+1. VPN 通信åè®®
+1.1. SoftEther VPN åè®®
+SoftEther VPN å¯ä»¥è¿›è¡Œ VPN 通信。ä¸åŒäºŽä¼ ç»Ÿçš„ VPN å议, SoftEther VPN 有一个全新设计的 "SoftEther VPN åè®® (SE-VPN åè®®)" 的实现。SE-VPN å议将任何以太网数æ®åŒ…å°è£…è¿› HTTPS (HTTP over SSL) 连接。因此 SE-VPN åè®®å¯ä»¥è¶Šè¿‡é˜²ç«å¢™é€šä¿¡ï¼Œå³ä½¿é˜²ç«å¢™è¢«ç½‘络管ç†å‘˜é…置阻止传统的 VPN æ•°æ®åŒ…。SE-VPN åè®®çš„è®¾è®¡å’Œå®žæ–½ä»¥ç¬¦åˆ TLS 1.0 (RFC 5246) å’Œ HTTPS (RFC 2818)。然é¢ï¼Œæœ‰æ—¶å¯¹ RFC 有ä¸åŒçš„行为。如果你是一个网络管ç†å‘˜ï¼Œè¦åœ¨é˜²ç«å¢™ä¸Šé˜»æ­¢ SE-VPN å议,你å¯ä»¥åœ¨é˜²ç«å¢™ä¸Šé‡‡å– "白åå•" 策略,æ¥è¿‡æ»¤ä»»ä½•åœ¨è¾¹ç•Œä¸Šçš„ TCP 或 UDP æ•°æ®åŒ…,除了明确å…许到特定网站和æœåŠ¡å™¨çš„æ•°æ®åŒ…。
+
+1.2. NAT ç©¿é€åŠŸèƒ½
+一般æ¥è¯´ï¼Œå¦‚果你使用传统的 VPN 系统,你必须è¦æ±‚网络管ç†å‘˜æŠŠ NAT 或防ç«å¢™è®¾ç½®ä¸º "打开" 或 "中继" 特定的 TCP 或 UDP 端å£ã€‚然而,也有需è¦ä»¥æŸç§æ–¹å¼æ¶ˆé™¤ç½‘络管ç†å‘˜çš„è¿™ç§å·¥ä½œæˆæœ¬ã€‚为了满足这ç§éœ€æ±‚, SoftEther VPN 有一个新实施的 "NAT 穿越" 功能。NAT 穿越默认情况下是å¯ç”¨çš„。一个在 NAT 或防ç«å¢™åŽé¢ã€åœ¨ç”µè„‘上è¿è¡Œçš„ SoftEther VPN æœåŠ¡å™¨å¯ä»¥æŽ¥å—æ¥è‡ªäº’è”网的 VPN 连接,在防ç«å¢™æˆ– NAT 上没有任何特殊的é…置。如果你想ç¦ç”¨ NAT 穿越功能,修改 SoftEther VPN æœåŠ¡å™¨ä¸Šçš„é…置文件 "DisableNatTraversal" 为 "true" 。为了在客户端ç¦ç”¨å®ƒï¼Œåœ¨ç›®æ ‡ä¸»æœºæ·»åŠ  "/ tcp" åŽç¼€ã€‚
+
+1.3. åŠ¨æ€ DNS 功能
+传统的 VPN 系统在 VPN æœåŠ¡å™¨ä¸Šéœ€è¦ä¸€ä¸ªé™æ€å…¨çƒ IP 地å€ã€‚é‰´äºŽå…¨çƒ IP 地å€çš„短缺, SoftEther å…¬å¸åœ¨ SoftEther VPN æœåŠ¡å™¨ä¸Šå®žæ–½äº† "åŠ¨æ€ DNS 功能" ã€‚åŠ¨æ€ DNS 是默认å¯ç”¨çš„ã€‚åŠ¨æ€ DNS 功能通知计算机的当å‰å…¨çƒ IP 地å€åˆ°ç”± SoftEther å…¬å¸æ“ä½œçš„åŠ¨æ€ DNS æœåŠ¡å™¨ã€‚一个全çƒå”¯ä¸€ä¸»æœºå (FQDN) ,如 "abc.softether.net" ( "ABC" éšæ¯ä¸ªç”¨æˆ·å”¯ä¸€è€Œä¸åŒ) 将在 VPN æœåŠ¡å™¨ä¸Šè¢«æŒ‡å®šã€‚如果你告诉一个 VPN 用户这个唯一的主机å,用户å¯ä»¥åœ¨ VPN 客户端上将其指定为目标 VPN æœåŠ¡å™¨çš„主机å,将能连接到 VPN æœåŠ¡å™¨ã€‚äº‹å…ˆæ— éœ€çŸ¥é“ IP 地å€ã€‚如果 VPN æœåŠ¡å™¨çš„ IP 地å€å˜åŒ–äº†ï¼Œç›¸å…³åŠ¨æ€ DNS æœåŠ¡çš„主机å注册的 IP 地å€ä¼šè‡ªåŠ¨æ”¹å˜ã€‚通过这ç§æœºåˆ¶ï¼Œä¸å†éœ€è¦æ¯æœˆå‘ ISP 缴费的全çƒé™æ€ IP 地å€ã€‚您å¯ä»¥ä½¿ç”¨å¸¦åŠ¨æ€ IP 地å€çš„ã€æ¶ˆè´¹è€…级ã€å»‰ä»·çš„互è”网连接,æ¥æ“作一个ä¼ä¸šçº§çš„ VPN 系统。如果你想ç¦ç”¨åŠ¨æ€ DNS ,把 SoftEther VPN æœåŠ¡å™¨é…置文件中的 "DDnsClient" 指令的 "Disabled" 项目指定为 "true" 。* 中åŽäººæ°‘共和国的居民请注æ„:如果你的 VPN æœåŠ¡å™¨è¿è¡Œåœ¨ä¸­åŽäººæ°‘共和国, DNS åŽç¼€å°†è¢«æ›¿æ¢ä¸º "sedns.cn" 域å。 "sedns.cn" 域åæœåŠ¡ç”± "北京大游索易科技有é™å…¬å¸" 拥有和è¿è¥çš„,它是一个中国本地的ä¼ä¸šã€‚
+
+1.4. VPN over ICMP / VPN over DNS 功能
+如果你想在 SoftEther VPN 客户端 / 网桥和 SoftEther VPN æœåŠ¡å™¨ä¹‹é—´å»ºç«‹ä¸€ä¸ª VPN 连接,但如果 TCP å’Œ UDP æ•°æ®åŒ…被防ç«å¢™ç¦æ­¢é€šè¿‡ï¼Œé‚£ä¹ˆä½ å¯ä»¥æŠŠæœ‰æ•ˆè½½è·å°è£…è¿› "ICMP" (被称为 Ping) 或 "DNS" æ•°æ®åŒ…。通过使用 ICMP 或 DNS ,å³ä½¿é˜²ç«å¢™æˆ–路由器阻止æ¯ä¸ª TCP 或 UDP 连接,此功能å¯ä»¥å®žçŽ° VPN 连接。VPN over ICMP/ VPN over DNS 功能尽å¯èƒ½çš„设计符åˆæ ‡å‡† ICMP å’Œ DNS 规范,但有时也ä¸å®Œå…¨ç¬¦åˆä»–们的行为。因此,一些劣质路由器å¯èƒ½ä¼šå¯¼è‡´å†…存溢出或当有很多 ICMP 或 DNS æ•°æ®åŒ…通过时产生麻烦,这ç§è·¯ç”±å™¨æœ‰æ—¶æ­»æœºæˆ–é‡æ–°å¯åŠ¨ã€‚它å¯èƒ½ä¼šå½±å“在åŒä¸€ç½‘络上的其他用户。为了é¿å…这样的风险,在 VPN 客户端指定的目标主机å上附加åŽç¼€ "/tcp" ,ç¦ç”¨ VPN over ICMP / DNS 功能。
+
+1.5. VPN Azure 云æœåŠ¡
+如果您的 SoftEther VPN æœåŠ¡å™¨æ”¾ç½®åœ¨ NAT 或防ç«å¢™åŽé¢ï¼Œç”±äºŽæŸç§åŽŸå› ï¼Œä½ ä¸èƒ½ä½¿ç”¨ NAT ç©¿é€åŠŸèƒ½ã€åŠ¨æ€ DNS 功能或 VPN over ICMP/DNS 功能,您å¯ä»¥ä½¿ç”¨ VPN Azure Clouse æœåŠ¡ã€‚ SoftEther å…¬å¸åœ¨äº’è”网上è¿è¡Œ VPN Azure 云。VPN æœåŠ¡å™¨è¿žæŽ¥åˆ° VPN Azure 云,主机å "abc.vpnazure.net" ( "abc" 是一个唯一的主机å) 通过 VPN Azure 云å¯ä»¥è¢«æŒ‡å®šè¿žæŽ¥åˆ° VPN æœåŠ¡å™¨ã€‚实际上,这样的一个主机å指å‘一个由 SoftEther å…¬å¸æ‰€æ“作的云æœåŠ¡å™¨çš„å…¨çƒ IP 地å€ã€‚如果一个 VPN 客户端连接到一个 VPN Azure 主机,那么 VPN Azure 主机转播在 VPN 客户端和 VPN æœåŠ¡å™¨ä¹‹é—´çš„所有æµé‡ã€‚VPN Azure 在默认情况下是ç¦ç”¨çš„。您å¯ä»¥é€šè¿‡ä½¿ç”¨ VPN æœåŠ¡å™¨é…置工具很容易地激活它。
+
+1.6. UDP 加速
+SoftEther VPN 具有 UDP 加速功能。如果一个 VPN 是由两个站点组æˆæ£€æµ‹åˆ° UDP 通é“已建立, UDP 将自动使用。通过此功能, UDP çš„åžåé‡å¢žåŠ äº†ã€‚如果直接的 UDP 通é“已被建立,直接的 UDP æ•°æ®åŒ…将被使用。但是,如果有一些障ç¢ï¼Œå¦‚防ç«å¢™æˆ– NAT , "UDP 冲孔" 技术将被使用。 "UDP 冲孔" 使用 SoftEther å…¬å¸åœ¨äº’è”网上æ“作的云æœåŠ¡å™¨ã€‚UDP 加速通过在 VPN 客户端一侧进行设置在任何时候å¯ä»¥è¢«ç¦ç”¨ã€‚
+
+
+2. VPN 软件
+2.1. SoftEther VPN 客户端
+如果您在 Windows 上使用 SoftEther VPN 客户端,虚拟网络适é…器设备驱动程åºå°†å®‰è£…在 Windows 上。虚拟网络适é…器作为一个内核模å¼é©±åŠ¨ç¨‹åºå®žæ–½åœ¨ Windows 上。驱动程åºæ˜¯æ•°å­—ç­¾å的,由 VeriSign , Inc 所签å‘çš„è¯ä¹¦ï¼Œè¿˜ç”± Symantec Corporation (赛门é“å…‹å…¬å¸) 签署。问你è¦ç¡®ä¿å®‰è£…驱动程åºçš„一æ¡æ¶ˆæ¯å¯èƒ½ä¼šå¼¹å‡ºåœ¨å±å¹•ä¸Šã€‚如果å¯èƒ½çš„è¯ï¼Œ SoftEther VPN 客户端å¯èƒ½ä¼šå“应消æ¯ã€‚SoftEther VPN 客户端还优化了在 Windows 上 MMCSS (多媒体类计划程åºæœåŠ¡) çš„é…置。您以åŽå¯ä»¥æ’¤æ¶ˆ MMCSS 的优化。
+
+2.2. SoftEther VPN æœåŠ¡å™¨ / 网桥
+如果您使用 SoftEther VPN æœåŠ¡å™¨ / 网桥在 Windows 上的 "本地网桥" 功能,你必须在电脑上安装低级别的以太网数æ®åŒ…处ç†é©±åŠ¨ç¨‹åºã€‚驱动程åºæ˜¯æ•°å­—ç­¾å的,由 VeriSign , Inc 所签å‘çš„è¯ä¹¦ï¼Œè¿˜ç”± Symantec Corporation (赛门é“å…‹å…¬å¸) 签署。SoftEther VPN æœåŠ¡å™¨ / 网桥在物ç†ç½‘络适é…器本地网桥功能中å¯ä»¥ç¦ç”¨ TCP / IP å¸è½½ç‰¹æ€§ã€‚在 Windows Vista /2008 或更高版本, VPN æœåŠ¡å™¨å¯ä»¥æ³¨å…¥ä¸€ä¸ªç¬¦åˆ Windows è¿‡æ»¤å¹³å° (WPF) 规范的数æ®åŒ…过滤驱动程åºè‡³å†…核以æä¾› IPsec 功能。数æ®åŒ…过滤驱动程åºå°†è¢«åŠ è½½ä»…当å¯ç”¨ IPsec 功能时。一旦您å¯ç”¨ SoftEther VPN æœåŠ¡å™¨çš„ IPsec 功能, Windows 内置的 IPsec 功能将被ç¦ç”¨ã€‚在您ç¦ç”¨äº† SoftEther VPN æœåŠ¡å™¨çš„ IPsec 功能之åŽï¼Œé‚£ä¹ˆ Windows 内置的 IPsec 功能将å¤è‹ã€‚为了æ供本地桥功能, SoftEther VPN æœåŠ¡å™¨ / 网桥在æ“作系统上ç¦ç”¨ TCP / IP å¸è½½åŠŸèƒ½ã€‚
+
+2.3. 用户模å¼å®‰è£…
+您å¯ä»¥åœ¨ Windows 以 "用户模å¼" 安装 SoftEther VPN æœåŠ¡å™¨å’Œ SoftEther VPN 网桥。æ¢å¥è¯è¯´ï¼Œå³ä½¿ä½ æ²¡æœ‰ Windows 系统管ç†å‘˜çš„æƒé™ï¼Œä½ å¯ä»¥ä½œä¸ºä¸€ä¸ªæ™®é€šç”¨æˆ·å®‰è£… SoftEther VPN。用户模å¼å®‰è£…å°†ç¦ç”¨ä¸€äº›åŠŸèƒ½ï¼Œä½†å…¶ä»–大部分功能都能正常工作。因此,例如,雇员å¯ä»¥åœ¨åŠžå…¬å®¤ç½‘络中的计算机上安装 SoftEther VPN æœåŠ¡å™¨ç«¯ï¼Œä»–将能够从他家连接到æœåŠ¡å™¨ã€‚为了由用户自己实现这样的系统,在技术观点上无须系统管ç†å‘˜æƒé™ã€‚然而,è¿åå…¬å¸è§„定未ç»æŽˆæƒåœ¨è®¡ç®—机上安装软件å¯èƒ½ä¼šè¢«è§†ä¸ºä¸å—欢迎的行为。如果你是一å雇员属于该公å¸ï¼Œè¯¥å…¬å¸çš„政策ç¦æ­¢å®‰è£…软件或未ç»å…许进行互è”网通信,你必须事先从网络管ç†å‘˜æˆ–您公å¸çš„总è£èŽ·å¾—许å¯ï¼Œå†å®‰è£… SoftEther VPN。如果您以用户模å¼å®‰è£… VPN æœåŠ¡å™¨ / 网桥,图标将出现在 Windows 任务托盘。如果您觉得该图标妨ç¢ä½ äº†ï¼Œä½ å¯ä»¥æ“作将其éšè—。然而,你ä¸èƒ½åˆ©ç”¨æ­¤éšè—功能在其他人的电脑上安装 VPN æœåŠ¡å™¨ä½œä¸ºé—´è°è½¯ä»¶ã€‚è¿™ç§è¡Œä¸ºå¯èƒ½æ˜¯è¿å刑法的犯罪。
+
+2.4. ä¿æŒæ´»è·ƒåŠŸèƒ½
+默认情况下, SoftEther VPN æœåŠ¡å™¨å’Œ SoftEther VPN 网桥有ä¿æŒæ´»è·ƒçš„功能。此功能的目的是为了维æŒäº’连网线路的活跃。该功能定期å‘é€å¸¦æœ‰éšæœº - 字节 - 数组 - 有效载è·çš„ UDP æ•°æ®åŒ…。此功能为é¿å…移动或拨å·è¿žæŽ¥çš„自动断开是éžå¸¸æœ‰ç”¨çš„。您å¯ä»¥éšæ—¶ç¦ç”¨ä¿æŒæ´»è·ƒåŠŸèƒ½ã€‚
+
+2.5. å¸è½½
+SoftEther VPN 软件的å¸è½½è¿‡ç¨‹å°†åˆ é™¤æ‰€æœ‰ç¨‹åºæ–‡ä»¶ã€‚然而,éžç¨‹åºæ–‡ä»¶ (如程åºè¿è¡Œæ‰€äº§ç”Ÿçš„文件和数æ®) å°†ä¸ä¼šè¢«åˆ é™¤ã€‚由于技术原因,å¸è½½ç¨‹åºçš„ exe 和资æºæ–‡ä»¶å¯èƒ½ä»ç„¶å­˜åœ¨ã€‚这些剩余的文件决ä¸ä¼šå½±å“使用计算机,但是你å¯ä»¥æ‰‹åŠ¨åˆ é™¤å®ƒã€‚内核模å¼é©±åŠ¨ç¨‹åºå¯èƒ½ä¸ä¼šè¢«åˆ é™¤ï¼Œä½†æ˜¯è¿™æ ·çš„驱动程åºåœ¨ Windows 下次å¯åŠ¨æ—¶ä¸ä¼šè¢«åŠ è½½ã€‚您å¯ä»¥ä½¿ç”¨ Windows çš„ "sc" 命令手动删除内核模å¼é©±åŠ¨ç¨‹åºã€‚
+
+2.6. 安全
+你应该在安装åŽåœ¨ SoftEther VPN æœåŠ¡å™¨ / 网桥设置管ç†å‘˜çš„密ç ã€‚如果你没有åšåˆ°è¿™ä¸€ç‚¹ï¼Œå…¶ä»–人未ç»æ‚¨è®¸å¯å¯ä»¥è®¿é—® SoftEther VPN æœåŠ¡å™¨ / 网桥,并å¯ä»¥è®¾ç½®å¯†ç ã€‚这个警告å¯èƒ½ä¹Ÿé€‚用于 Linux 版本的 SoftEther VPN 客户端。
+
+2.7. 自动更新通知
+Windows 版的 SoftEther VPN 软件有自动更新通知功能。它定期访问 SoftEther æ›´æ–°æœåŠ¡å™¨æ£€æŸ¥æ˜¯å¦å‘布了最新版本的软件。如果最新版已å‘布,通知消æ¯å°†åœ¨å±å¹•ä¸Šå¼¹å‡ºã€‚为了达到这个目的,版本ã€è¯­è¨€è®¾ç½®ã€æ‚¨çš„计算机的 IP 地å€ã€å”¯ä¸€æ ‡è¯†ç¬¦ã€è¿žæŽ¥åˆ° VPN æœåŠ¡å™¨çš„主机å将被å‘é€åˆ° SoftEther çš„æ›´æ–°æœåŠ¡å™¨ã€‚任何个人信æ¯å°†ä¸è¢«å‘é€ã€‚默认情况下自动更新通知是å¯ç”¨çš„,然而你å¯ä»¥åœ¨é…ç½®å±å¹•ä¸Šç¦ç”¨å®ƒã€‚通过 VPN æœåŠ¡å™¨ç®¡ç†å™¨ï¼Œè®¾ç½®æ˜¯å¦æ‰“开或关闭将被å•ç‹¬ä¿å­˜å¯¹åº”æ¯ä¸ªç›®æ ‡ VPN æœåŠ¡å™¨ã€‚
+
+2.8. 虚拟 NAT 功能
+虚拟 HUB 在 SoftEther VPN æœåŠ¡å™¨ / 网桥上有 "虚拟 NAT 功能" 。虚拟 NAT 功能å¯ä»¥é€šè¿‡ VPN 客户端的多个ç§æœ‰ IP 地å€å…±äº«åŒä¸€ä¸ªç‰©ç†ç½‘络上的å•ä¸€ IP 地å€ã€‚有两ç§è™šæ‹Ÿ NAT çš„æ“作模å¼:用户模å¼å’Œå†…核模å¼ã€‚在用户模å¼ä¸‹è¿è¡Œï¼Œè™šæ‹Ÿ NAT 共享主æ“作系统上分é…的一个 IP 地å€ã€‚ä¸åŒäºŽç”¨æˆ·æ¨¡å¼ï¼Œå†…核模å¼çš„æ“作试图找到物ç†ç½‘络上的 DHCP æœåŠ¡å™¨ã€‚如果有两个或以上的物ç†ç½‘络,æ¯ä¸ªç½‘段上的 DHCP æœåŠ¡å™¨ä¼šè¢«è‡ªåŠ¨è¿žç»­å¯»æ‰¾ã€‚如果å‘现 DHCP æœåŠ¡å™¨ï¼Œå¹¶èŽ·å–一个 IP 地å€ï¼Œ IP 地å€å°†è¢«è™šæ‹Ÿ NAT 使用。在这ç§æƒ…况下,作为 DHCP 客户端的 IP æ¡ç›®å°†è¢«ç™»è®°åœ¨ç‰©ç† DHCP æœåŠ¡å™¨çš„ IP 池。为了在互连网中和主机进行通信,物ç†é»˜è®¤ç½‘关和 DNS æœåŠ¡å™¨å°†è¢«è™šæ‹Ÿ NAT 使用。在内核模å¼çš„æ“作中,虚拟 HUB 上有一个è¿è¡Œåœ¨ç‰©ç†ä»¥å¤ªç½‘段上的虚拟 MAC 地å€ã€‚
+为了检查到互è”网的连通性, SoftEther VPN 定期å‘é€ DNS 查询数æ®åŒ…ï¼Œä»¥è§£æž "www.yahoo.com" 或 "www.baidu.com" 主机的 IP 地å€ï¼Œå¹¶å°è¯•è¿žæŽ¥åˆ°è¿™æ ·ç»“æžœ IP 地å€çš„ TCP 80 端å£ï¼Œè¿›è¡Œè¿žé€šæ€§æ£€æŸ¥ã€‚
+
+2.9. 内核模å¼ç»„件的无人值守安装
+当 SoftEther VPN 检测到需è¦åœ¨ Windows 安装内核模å¼ç»„件, Windows 系统将出现一æ¡ç¡®è®¤æ¶ˆæ¯ã€‚在此之际, SoftEther VPN 软件将切æ¢åˆ°æ— äººå€¼å®ˆçš„安装模å¼ï¼Œä»¥å›žåº” "是" 到 Windows。当从é¥è¿œåœ°ç‚¹è¿›è¡Œè¿œç¨‹ç®¡ç†æ—¶ï¼Œè¿™ä¸ªè§£å†³æ–¹æ¡ˆå¯ä»¥é˜²æ­¢é”死。
+
+2.10. Windows 防ç«å¢™
+SoftEther VPN 软件将其自身注册为一个安全程åºã€‚这样的æ¡ç›®åœ¨å¸è½½åŽä»è¢«ä¿ç•™ã€‚您å¯ä»¥ä»Ž Windows 的控制é¢æ¿ä¸­æ‰‹åŠ¨åˆ é™¤å®ƒã€‚
+
+
+3. 互连网æœåŠ¡
+3.1. SoftEther å…¬å¸æ供的互连网æœåŠ¡
+SoftEther å…¬å¸åœ¨äº’è”网上æä¾›äº†åŠ¨æ€ DNSã€NAT ç©¿é€ã€å’Œ VPN Azure æœåŠ¡å™¨æœåŠ¡ã€‚这些æœåŠ¡éƒ½æ˜¯å…费的。客户通过使用 SoftEther VPN 软件,ç»ç”±äº’è”网访问这些æœåŠ¡ã€‚这些æœåŠ¡è®¡åˆ’将在以åŽå‘布的 "SoftEther VPN" çš„å¼€æºç‰ˆæœ¬ä¸­ä¹Ÿæ供。
+
+3.2. å‘é€çš„ä¿¡æ¯å’Œéšç§ä¿æŠ¤
+为了使用上述æœåŠ¡ï¼Œ SoftEther VPN 软件å¯ä»¥ä»Žå®¢æˆ·çš„计算机到由 SoftEther å…¬å¸æ“作的云æœåŠ¡å‘é€ IP 地å€ã€ä¸»æœºåã€VPN 软件的版本。这些信æ¯çš„å‘é€æ˜¯è¦ä½¿ç”¨è¿™äº›æœåŠ¡çš„最少必须内容。无任何个人信æ¯å°†è¢«å‘é€ã€‚ SoftEther å…¬å¸è®°å½•æŽ¥æ”¶åˆ°çš„最少信æ¯åœ¨äº‘æœåŠ¡æœåŠ¡å™¨çš„日志文件为 90 天。这些日志将被用于故障排除和其他åˆæ³•æ´»åŠ¨ã€‚SoftEther å…¬å¸å¯ä»¥æ供日志给属于法院ã€è­¦å¯Ÿå±€å’Œæ£€å¯Ÿé™¢çš„日本政府的公务人员,以éµå®ˆå½“局的命令。(æ¯ä¸€ä¸ªæ—¥æœ¬å…¬åŠ¡äººå‘˜æœ‰è´£ä»»æ ¹æ®æ³•å¾‹å¯†åˆ‡ä¿å­˜è¿™äº›ä¿¡æ¯ã€‚) 此外, IP 地å€æˆ–其他信æ¯å°†è¿›è¡Œç»Ÿè®¡å¤„ç†ï¼Œå¹¶æ供给公众,而ä¸æ˜¯æš´éœ²æ¯ä¸€ä¸ªå…·ä½“çš„ IP 地å€ï¼Œä»¥è¿›è¡Œç ”究活动的å‘布。
+
+3.3. 通过 VPN Azure æœåŠ¡çš„通信数æ®
+ä¸ç®¡ä»¥ä¸Š 3.2 的规则,如果客户使用 VPN Azure 云æœåŠ¡çš„å‘é€æˆ–接收 VPN æ•°æ®åŒ…,实际的有效载è·å°†åœ¨å¾ˆçŸ­çš„时间通过æœåŠ¡å™¨çš„易失性存储器存储和转å‘。这样的行为自然需è¦æä¾› "VPN 中继æœåŠ¡" 。无有效载è·å°†è¢«è®°å½•åœ¨ "固定的" 储存设备,如硬盘驱动器。然而, "窃å¬ç½ªçŠ¯ç¨‹åºæ³•" (日本在 1999 å¹´ 8 月 18 æ—¥è£å†³çš„第 137 个立法) è¦æ±‚电信公å¸å…许日本政府当局进行在线窃å¬ã€‚物ç†æ”¾ç½®åœ¨æ—¥æœ¬çš„ VPN Azure æœåŠ¡å™¨ä¹Ÿæ˜¯æœä»ŽäºŽè¿™ä¸ªæ³•å¾‹ã€‚
+
+3.4. 符åˆæ—¥æœ¬ç”µä¿¡æ³•
+SoftEther å…¬å¸ç¬¦åˆæ—¥æœ¬ç”µä¿¡æ³•å¿…è¦æ—¶é€šè¿‡äº’è”网æ供在线æœåŠ¡ã€‚
+
+3.5. å…费和学术实验æœåŠ¡
+SoftEther 作为学术实验æœåŠ¡æä¾›åŠ¨æ€ DNSã€NAT ç©¿é€å’Œ VPN Azure。因此,æœåŠ¡å¯ä»¥è¢«ç”¨äºŽå…费。这些æœåŠ¡ä¸æ˜¯ "SoftEther VPN 软件产å“" 的一部分。这些æœåŠ¡ä¸æ供任何ä¿è¯ã€‚这些æœåŠ¡ç”±äºŽæŠ€æœ¯æˆ–æ“作问题å¯èƒ½ä¼šè¢«æš‚åœæˆ–终止。在这ç§æƒ…况下,用户将无法使用这些æœåŠ¡ã€‚用户必须了解这些风险,并承认由用户自行承担这样的风险。SoftEther 永远ä¸ä¼šå¯¹ç»“æžœã€æˆ–使用的æŸå®³ã€æˆ–æœåŠ¡æ— æ³•ä½¿ç”¨æ‰¿æ‹…任何责任。å³ä½¿ç”¨æˆ·å·²ç»æ”¯ä»˜ SoftEther VPN 商业版的许å¯è´¹ç”¨ï¼Œå› ä¸ºæ”¯ä»˜çš„费用ä¸åŒ…å«è¿™äº›æœåŠ¡çš„任何费用。因此,如果在线æœåŠ¡å°†åœæ­¢æˆ–终止, SoftEther å…¬å¸å°†ä¸æ供任何退款或æŸå®³çš„è¡¥å¿ã€‚
+
+3.6. DNS 代ç†äº‘æœåŠ¡å™¨
+在æŸäº›åœ°åŒºï¼Œå½“用户使用互连网,通过 ISP 线路时,一个 DNS 查询有时æŸå或丢失。如果 SoftEther VPN çš„æœåŠ¡å™¨ã€å®¢æˆ·ç«¯æˆ–网桥检测到访问实际的 VPN æœåŠ¡å™¨å¯èƒ½ä¸ç¨³å®šçš„å¯èƒ½æ€§ï¼Œé‚£ä¹ˆ DNS 查询将被转移到由 SoftEther å…¬å¸è¿è¡Œçš„ DNS 代ç†äº‘æœåŠ¡å™¨ã€‚DNS 代ç†äº‘æœåŠ¡å™¨å°†å›žç­”纠正一个 IP 地å€å“应 DNS 查询。
+
+
+4. 一般注æ„事项
+4.1. 需è¦ç½‘络管ç†å‘˜çš„批准
+SoftEther VPN 具有强大的功能,ä¸éœ€è¦ç½‘络管ç†å‘˜çš„特殊设置。例如,您ä¸å¿…è¦æ±‚管ç†å‘˜é…置现有的防ç«å¢™ä»¥ "打开" TCP / UDP 端å£ã€‚这些性能特点是为了以下目的:消除网络管ç†å‘˜çš„工作时间和æˆæœ¬ï¼Œå¹¶é¿å…误é…置风险,如在防ç«å¢™ä¸Šæ‰“开特定的异常端å£çš„任务。然而,在安装 SoftEther VPN å‰ï¼Œå±žäºŽå…¬å¸çš„任何员工必须获得网络管ç†å‘˜çš„批准。如果您的网络管ç†å‘˜å¿½ç•¥æ供这样的批准,你å¯ä»¥è€ƒè™‘获得上级领导的批准。(例如,该公å¸æ€»è£ã€‚) 如果您没有获得公å¸é¢†å¯¼çš„批准使用 SoftEther VPN ,你å¯èƒ½æœ‰ä¸åˆ©çš„æ¡ä»¶ã€‚SoftEther å…¬å¸å°†ä¸ä¼šå¯¹ä½¿ç”¨ SoftEther VPN 的结果或æŸå®³æ‰¿æ‹…责任。
+
+4.2. éµå®ˆè´µå›½çš„法律
+如果您所在国家的法律ç¦æ­¢åŠ å¯†çš„使用,你自己必须ç¦ç”¨ SoftEther VPN 的加密功能。åŒæ ·ï¼Œåœ¨ä¸€äº›å›½å®¶æˆ–地区, SoftEther VPN çš„æŸäº›åŠŸèƒ½å¯èƒ½ä¼šè¢«æ³•å¾‹ç¦æ­¢ä½¿ç”¨ã€‚其他国家的法律与 SoftEther å…¬å¸æ— å…³ï¼Œå› ä¸º SoftEther å…¬å¸æ˜¯ä¸€ä¸ªåœ¨ç‰©ç†ä¸Šä½äºŽå¹¶æ³¨å†ŒäºŽæ—¥æœ¬çš„ä¼ä¸šã€‚例如,å¯èƒ½å­˜åœ¨ä¸€ç§é£Žé™©ï¼Œå³ SoftEther VPN 的一部分与åªåœ¨æŸäº›ç‰¹å®šåŒºåŸŸæœ‰æ•ˆçš„现有专利冲çªã€‚SoftEther å…¬å¸æ²¡æœ‰åœ¨æ—¥æœ¬å›ºæœ‰é¢†åœŸä¹‹å¤–这些特定区域的利益。因此,如果你想在日本以外的地区使用 SoftEther VPN ,你必须è¦å°å¿ƒä¸è¦ä¾µçŠ¯ç¬¬ä¸‰äººçš„æƒåˆ©ã€‚在您在这样的地区实际使用之å‰ï¼Œæ‚¨å¿…须验è¯åœ¨è¿™äº›ç‰¹å®šåŒºåŸŸä½¿ç”¨ SoftEther VPN çš„åˆæ³•æ€§ã€‚本æ¥ï¼Œåœ¨ä¸–界上有近 200 个国家,æ¯ä¸ªå›½å®¶çš„法律都是ä¸åŒçš„。这几乎是ä¸å¯èƒ½çš„事先验è¯æ¯ä¸€ä¸ªå›½å®¶çš„法律和法规,使软件符åˆæ‰€æœ‰å›½å®¶çš„法律,å†å‘布软件。因此 SoftEther å…¬å¸å·²æ ¸å®ž SoftEther VPN 仅对日本法律和法规的åˆæ³•æ€§ã€‚如果用户在一个特定的国家使用 SoftEther VPN , SoftEther å…¬å¸å°†ä¸ä¼šèµ”å¿æ”¿åºœå½“局的æŸå®³ï¼Œä¹Ÿä¸ä¼šæ‰¿æ‹…æ¢å¤æˆ–èµ”å¿æ­¤ç±»æŸå®³æˆ–刑事法律责任。
+
+
+5. VPN Gate 学术实验项目
+(本章仅适用于 SoftEther VPN è½¯ä»¶åŒ…ï¼Œå…¶ä¸­åŒ…å« VPN Gate 学术实验项目的扩展æ’件。)
+5.1. 关于 VPN Gate 学术实验项目
+VPN Gate 学术实验项目是一个在线æœåŠ¡ï¼Œç”±æ—¥æœ¬ç­‘波大学研究生院为学术研究目的è¿è¥ã€‚本研究的目的是è¦æ‰©å¤§æˆ‘们对 "å…¨çƒåˆ†å¸ƒå¼å…¬å…± VPN 中继æœåŠ¡å™¨" 技术 (Global Distributed Public VPN Relay Server, GDPVRS) 的认识。有关详细信æ¯ï¼Œè¯·è®¿é—® http://www.vpngate.net/。
+
+5.2. 关于 VPN Gate æœåŠ¡
+SoftEther VPN æœåŠ¡å™¨å’Œ SoftEther VPN 客户端å¯èƒ½å«æœ‰ "VPN Gate æœåŠ¡" 程åºã€‚然而, VPN Gate æœåŠ¡åœ¨é»˜è®¤æƒ…况下是ç¦ç”¨çš„。
+VPN Gate æœåŠ¡é€šè¿‡å®‰è£…了 SoftEther VPN æœåŠ¡å™¨æˆ– SoftEther VPN 客户端的计算机所有者的志愿目的被激活并å¯ç”¨ã€‚在您激活 VPN Gate æœåŠ¡ä»¥åŽï¼Œè®¡ç®—机将作为全çƒåˆ†å¸ƒå¼å…¬å…± VPN 中继æœåŠ¡å™¨çš„一部分开始æœåŠ¡ã€‚计算机的 IP 地å€ã€ä¸»æœºå和相关信æ¯å°†è¢«å‘é€å¹¶åœ¨ VPN Gate 学术实验项目的æœåŠ¡å™¨ç›®å½•æ³¨å†Œï¼Œè¿™äº›ä¿¡æ¯å°†è¢«å…¬å¸ƒï¼Œå¹¶å‘公众披露。这一机制将å…许任何 VPN Gate 客户端软件的用户连接到您计算机上è¿è¡Œçš„ VPN Gate æœåŠ¡ã€‚当在 VPN Gate 客户端和你的 VPN Gate æœåŠ¡ä¹‹é—´å»ºç«‹ä¸€ä¸ª VPN 会è¯ï¼Œ VPN Gate 客户端的用户å¯ä»¥å‘é€ / 接收å‘互è”网ç»ç”± VPN Gate æœåŠ¡çš„任何 IP æ•°æ®åŒ…。VPN Gate æœåŠ¡çš„ä¸»æœºçš„å…¨çƒ IP 地å€å°†ä½œä¸º VPN Gate 客户端å¯åŠ¨çš„è¿™ç§é€šä¿¡çš„æº IP 地å€è¢«ä½¿ç”¨ã€‚
+VPN Gate æœåŠ¡å°†å‘é€ä¸€äº›ä¿¡æ¯è‡³ VPN Gate 学术实验æœåŠ¡ç›®å½•æœåŠ¡å™¨ã€‚这些信æ¯åŒ…括第 5.5 节中æè¿°çš„è¿è¥å•†çš„ä¿¡æ¯ã€æ—¥å¿—设置ã€æ­£å¸¸è¿è¡Œæ—¶é—´ã€æ“作系统版本ã€å议类型ã€ç«¯å£å·ã€è´¨é‡ä¿¡æ¯ã€ç»Ÿè®¡ä¿¡æ¯ã€VPN Gate 客户端的日志历å²æ•°æ® (包括日期,IP 地å€ï¼Œç‰ˆæœ¬å·å’Œ ID) 和软件的版本。这些信æ¯å°†è¢«æ‰¹éœ²åœ¨ç›®å½•ä¸Šã€‚VPN Gate æœåŠ¡ä»Žç›®å½•æœåŠ¡å™¨æŽ¥æ”¶åˆ°ä¸€ä¸ªå¯†é’¥ä»¥è¿›è¡Œåœ¨ 5.9 章中æè¿°çš„ç¼–ç ã€‚
+
+5.3. VPN Gate æœåŠ¡è¡Œä¸ºçš„详细信æ¯
+如果您手动å¯ç”¨ VPN Gate æœåŠ¡ï¼Œåœ¨é»˜è®¤æƒ…况下是ç¦ç”¨çš„, "VPNGATE" 虚拟 Hub 将在 SoftEther VPN æœåŠ¡å™¨ä¸Šè¢«åˆ›å»ºã€‚如果您使用的是 SoftEther VPN 客户端,并å°è¯•æ¿€æ´» VPN Gate æœåŠ¡ï¼Œç›¸å½“于 SoftEther VPN æœåŠ¡å™¨çš„程åºåœ¨ SoftEther VPN 客户端的åŒä¸€è¿›ç¨‹å°†è¢«è°ƒç”¨ï¼Œè™šæ‹Ÿ HUB "VPNGATE" 将被创建。虚拟 HUB "VPNGATE" 包å«ä¸€ä¸ªé»˜è®¤æƒ…况下å为 "VPN" 的用户,此用户å…许在互è”网上的任何人建立 VPN 连接到虚拟 HUB。一旦 VPN 客户端连接到虚拟 HUB "VPNGATE" ,用户与互è”网之间的任何通信将穿过虚拟 Hub ,使用è¿è¡Œæœ‰ SoftEther VPN æœåŠ¡å™¨ (或 SoftEther VPN 客户端) 的计算机上的物ç†ç½‘络接å£å‘é€ / 接收。这将导致以下结果,目标主机通过 VPN 客户端确定通信的æºå‘起是从 VPN Gate æœåŠ¡çš„主机的 IP 地å€æŒ‡å®šçš„。ä¸è¿‡ï¼Œä¸ºäº†å®‰å…¨ï¼Œç›®çš„地是在 192.168.0.0/255.255.0.0 , 172.16.0.0/255.240.0.0 或 10.0.0.0/255.0.0.0 以内的任何数æ®åŒ…将被虚拟 HUB "VPNGATE" 拦截,以ä¿æŠ¤æ‚¨çš„本地网络。因此,如果在您的ä¼ä¸šç½‘络或ç§äººç½‘络è¿è¡Œ VPN Gate æœåŠ¡ï¼Œè¿™æ˜¯å®‰å…¨çš„,因为匿å VPN 客户端用户将ä¸è¢«å…许访问这些ç§äººç½‘络。VPN Gate æœåŠ¡ä¹Ÿå¯ä½œä¸ºä¸­ç»§è®¿é—® VPN Gate 目录æœåŠ¡å™¨ã€‚
+为了使 VPN Gate æœåŠ¡ç†Ÿæ‚‰é˜²ç«å¢™å’Œ NAT ,通过使用 1.2 ç« æè¿°çš„ NAT ç©¿é€åŠŸèƒ½æ‰“开一个 UDP 端å£ã€‚还打开了一些 TCP 端å£å¹¶ç›‘å¬ï¼Œä¸€äº› TCP å’Œ UDP 端å£å°†è¢«æŒ‡å®šä¸ºæœ¬åœ°è·¯ç”±å™¨è¦æ±‚的通用å³æ’å³ç”¨ (UPnP) 传输æ¡ç›®çš„目标端å£ã€‚UPnP 请求数æ®åŒ…将被定期å‘é€ã€‚有些路由器在设备上永久ä¿æŒä¸€ä¸ªå¼€æ”¾çš„ TCP/UDP 端å£ã€‚如果你想关闭他们,å¯ä»¥æ‰‹åŠ¨å…³é—­ã€‚
+VPN Gate æœåŠ¡è¿˜æ供了镜åƒç½‘站功能 www.vpngate.net。这是一ç§æœºåˆ¶ï¼Œå°†çš„最新内容 www.vpngate.net 的副本被托管的镜åƒç«™ç‚¹å¾®å°çš„ HTTP æœåŠ¡å™¨ä¸Šè¿è¡Œçš„ VPN Gate æœåŠ¡ç¨‹åºã€‚它都将自己注册上镜的站点列表中 www.vpngate.net。然而,它从æ¥ä¸å‘ www.vpngate.net 任何其他通讯中继。
+
+5.4. 互è”网之间ç»ç”± VPN Gate æœåŠ¡çš„通信
+VPN Gate æœåŠ¡æ供了一个用户与互è”网之间的路由,通过使用 2.8 章虚拟 NAT 功能。VPN Gate æœåŠ¡å‘é€ Ping 查询数æ®åŒ…到ä½äºŽç­‘波大学的æœåŠ¡å™¨ï¼Œå’Œè¢«ç¡®å®šä¸º 8.8.8.8 的谷歌公共 DNS æœåŠ¡å™¨ï¼Œä»¥æ£€æŸ¥æ‚¨çš„互è”网线路的最新质é‡ã€‚VPN Gate æœåŠ¡è¿˜å‘é€å’ŒæŽ¥æ”¶å¤§é‡çš„éšæœºæ•°æ®åŒ…到 / 从筑波大学的速度测试æœåŠ¡å™¨ä¸Šã€‚这些高质é‡çš„æ•°æ®å°†è‡ªåŠ¨åœ°ã€å®šæœŸåœ°è¢«æŠ¥å‘Šç»™ VPN Gate 目录æœåŠ¡å™¨ã€‚结果将被ä¿å­˜å¹¶å‘公众披露。这些定期的查询通信被调整,尽é‡ä¸å ç”¨äº’è”网线路,但在æŸäº›æƒ…况下å¯èƒ½ä¼šå ç”¨çº¿è·¯ã€‚
+
+5.5. VPN Gate æœåŠ¡çš„è¿è¥å•†ä¿¡æ¯
+如果您激活您计算机上的 VPN Gate æœåŠ¡ï¼Œæ­¤è®¡ç®—机将æˆä¸ºå…¨çƒåˆ†å¸ƒå¼å…¬å…± VPN 中继æœåŠ¡å™¨çš„一部分。因此,您的 VPN Gate æœåŠ¡çš„è¿è¥å•†ç®¡ç†ä¿¡æ¯åº”被报告和注册到 VPN Gate æœåŠ¡ç›®å½•é‡Œã€‚è¿è¥å•†çš„ä¿¡æ¯åŒ…å«äº†è¿è¥å•†çš„å称ã€æ»¥ç”¨æŠ¥å‘Šã€è”系的 e-mail 地å€ã€‚这些信æ¯å¯ä»¥è¢«è¾“入到å±å¹•ä¸Šçš„ VPN Gate é…置里。输入的信æ¯å°†è¢«å‘é€åˆ° VPN Gate 目录æœåŠ¡å™¨ï¼Œä¿å­˜å¹¶å‘公众披露。所以,你必须è¦å°å¿ƒåœ°è¾“入信æ¯ã€‚顺便说一下,直到你指定æŸå称作为è¿è¥å•†çš„ä¿¡æ¯ï¼Œè®¡ç®—机的主机å会被自动使用作为è¿è¥å•†å称的字段,通过在主机ååŽé™„加 "'s owner" 字符串。
+
+5.6. éµå®ˆæ³•å¾‹è¿è¥ VPN Gate æœåŠ¡
+在æŸäº›å›½å®¶æˆ–地区,正打算激活和è¿è¡Œ VPN Gate æœåŠ¡çš„用户,他被强制è¦æ±‚从 / 到政府获得许å¯æˆ–注册æœåŠ¡ã€‚如果您所在的地区有这样的规定,你必须在激活 VPN Gate æœåŠ¡ä¹‹å‰ï¼Œæå‰å®Œæˆå¼ºåˆ¶æµç¨‹ã€‚无论是 VPN Gate 学术实验项目的开å‘者和è¿è¥å•†å¯¹äºŽå‘生的未能éµå®ˆå½“地法律的法律 / 刑事责任或æŸå®³éƒ½ä¸æ‰¿æ‹…任何责任。
+
+5.7. ä¿æŠ¤é€šä¿¡çš„éšç§
+大多数国家有一个法律è¦æ±‚通信æœåŠ¡çš„è¿è¥å•†ï¼ŒåŒ…括 VPN Gate æœåŠ¡è¿è¥å•†ï¼Œä»¥ä¿éšœç¬¬ä¸‰æ–¹çš„通信éšç§ã€‚当您è¿è¥ VPN Gate æœåŠ¡æ—¶ï¼Œä½ å¿…须始终ä¿æŠ¤ç”¨æˆ·çš„éšç§ã€‚
+
+5.8. æ•°æ®åŒ…日志
+æ•°æ®åŒ…日志功能在 VPN Gate æœåŠ¡ä¸Šå®žæ–½ã€‚它记录通过虚拟 HUB ä¼ è¾“çš„ä¸»è¦ TCP/IP æ•°æ®åŒ…的基本包头。此功能将有助于了解连接您的 VPN Gate æœåŠ¡ç”¨æˆ·çš„通信å‘起者的 "原始 IP 地å€" ,通过检查数æ®åŒ…日志和连接日志。数æ®åŒ…日志记录的仅为åˆæ³•è°ƒæŸ¥çš„目的。ä¸ä¼šå·çœ‹ï¼Œä¹Ÿä¸ä¼šæ³„æ¼æ•°æ®åŒ…日志,除éžæ­£å½“的目的。这ç§è¡Œä¸ºå°†è¿å 5.7 章。
+
+5.9. æ•°æ®åŒ…日志的自动存档和编ç åŠŸèƒ½
+VPN Gate 学术实验æœåŠ¡æ˜¯æ ¹æ®æ—¥æœ¬å®ªæ³•å’Œæ³•å¾‹è¿è¥å’Œè¿è¡Œçš„。日本宪法法律è¦æ±‚严格ä¿æŠ¤é€šä¿¡çš„éšç§æƒã€‚由于这项æœåŠ¡æ˜¯æ ¹æ®æ—¥æœ¬çš„规则, VPN Gate æœåŠ¡çš„程åºå®žçŽ°äº†æ­¤ "自动日志文件编ç " çš„ä¿æŠ¤æœºåˆ¶ï¼Œå¹¶é»˜è®¤å¯ç”¨ã€‚
+默认情况下, VPN Gate æœåŠ¡å½“å‰è‡ªåŠ¨é…置编ç å·²ç»è¿‡åŽ»äº†ä¸¤å‘¨æˆ–以上的数æ®åŒ…日志文件。为了ä¿æŠ¤é€šä¿¡éšç§ï¼Œå¦‚果一个数æ®åŒ…日志文件一旦被编ç ï¼Œå³ä½¿æ˜¯æœ¬åœ°è®¡ç®—机管ç†å‘˜ä¹Ÿæ— æ³•æ£€æŸ¥æ•°æ®åŒ…日志文件。这ç§æœºåˆ¶ä¿æŠ¤ VPN Gate æœåŠ¡æœ€ç»ˆç”¨æˆ·çš„éšç§ã€‚
+您å¯ä»¥æ›´æ”¹ VPN Gate æœåŠ¡çš„设置,ç¦ç”¨æ­¤é¡¹è‡ªåŠ¨ç¼–ç åŠŸèƒ½ã€‚然åŽæ•°æ®åŒ…日志文件将永远ä¸ä¼šè¢«ç¼–ç ï¼Œå³ä½¿ä¸¤ä¸ªæ˜ŸæœŸå·²è¿‡åŽ»ã€‚在这样的é…置中,所有数æ®åŒ…日志将以纯文本形å¼ä¿ç•™åœ¨ç£ç›˜ä¸Šã€‚因此,你必须è¦æ³¨æ„ä¸è¦ä¾µçŠ¯ç”¨æˆ·çš„éšç§ã€‚
+如果你负责解ç å·²ç¼–ç çš„æ•°æ®åŒ…日志文件 (例如:一个 VPN Gate æœåŠ¡çš„用户éžæ³•æ»¥ç”¨ä½ çš„ VPN Gate æœåŠ¡ï¼Œä½ å¿…须解ç æ•°æ®åŒ…日志以符åˆæ³•å¾‹) ,请è”系日本筑波大学研究生院 VPN Gate 学术实验æœåŠ¡çš„管ç†å‘˜ã€‚ä½ å¯ä»¥ä»Ž http://www.vpngate.net/ 找到è”系地å€ã€‚æ ¹æ®æ³•å¾‹å¦‚果有从法院或其他å¸æ³•å½“局适当的和法律的è¦æ±‚, VPN Gate æœåŠ¡çš„管ç†å‘˜å°†å“应解ç æ•°æ®åŒ…日志。
+
+5.10. 在日本领土æ“作 VPN Gate æœåŠ¡çš„注æ„事项
+当一个用户在日本领土æ“作 VPN Gate æœåŠ¡æ—¶ï¼Œè¿™ç§è¡Œä¸ºä¼šæ ¹æ®æ—¥æœ¬ç”µä¿¡æ³•åŠ ä»¥è§„范,æ“作å—æ³•å¾‹ç®¡è¾–ã€‚ç„¶è€Œï¼Œåœ¨è¿™æ ·çš„æƒ…å†µä¸‹ï¼Œæ ¹æ® "日本电信业务竞争手册 [补充版本]" ,éžè¥åˆ©æ€§çš„通信业务ä¸è¢«è®¤ä¸ºæ˜¯ "电信业务" 。因此,通常 VPN Gate æœåŠ¡çš„è¿è¥å•†ä¸å—制于 "电信业务ç»è¥è€…" ,ä¸å¼ºåˆ¶è¦æ±‚到政府注册。å³ä¾¿å¦‚此,ä¿æŠ¤é€šä¿¡éšç§çš„åˆæ³•æ€§ä»å¼ºåˆ¶å®žè¡Œã€‚作为一个结论,如果你在日本领土è¿è¥ VPN Gate æœåŠ¡ï¼Œä½ ä¸èƒ½æ³„露ç»ç”±ä½ æ“作的 VPN Gate æœåŠ¡ä¼ é€çš„通讯秘密。
+
+5.11. VPN Gate 客户端
+如果 SoftEther VPN å®¢æˆ·ç«¯åŒ…å« VPN Gate 客户端æ’件,你å¯ä»¥åœ¨äº’è”网上用它æ¥èŽ·å¾—当å‰æ“作的 VPN Gate æœåŠ¡çš„æœåŠ¡å™¨åˆ—表,使一个 VPN 连接到列表上的特定æœåŠ¡å™¨ã€‚
+VPN Gate 客户端始终定期ä¿æŒ VPN Gate æœåŠ¡çš„最新列表。è¦å°å¿ƒï¼Œå¦‚果你使用的是按使用é‡ä»˜è´¹çš„互è”网线路。
+当您å¯åŠ¨ VPN Gate 客户端软件,è¦æ±‚你激活或ä¸æ˜¯ VPN Gate æœåŠ¡çš„å±å¹•å°†å‡ºçŽ°ã€‚VPN Gate æœåŠ¡çš„详细信æ¯ï¼Œè¯·é˜…读上述å„节。
+
+5.12. 在加入或使用 VPN Gate 学术实验项目之å‰çš„注æ„事项
+VPN Gate 学术实验æœåŠ¡æ˜¯ä½œä¸ºæ—¥æœ¬ç­‘波大学研究生院的一个研究项目è¿è¥çš„。该æœåŠ¡å—日本法律管ç†ã€‚其他国家的法律ä¸å—我们关注也ä¸æ‰¿æ‹…责任。
+从本质上讲,在世界上有近 200 个国家,都有ä¸åŒçš„法律。ä¸å¯èƒ½åœ¨è½¯ä»¶å‘布å‰åŽ»éªŒè¯æ¯ä¸€ä¸ªå›½å®¶çš„法律和法规,并使我们的软件符åˆæ‰€æœ‰å›½å®¶çš„法律。如果用户在一个特定的国家使用 VPN Gate æœåŠ¡ï¼ŒæŸå公务人员的æƒåŠ›ï¼ŒæœåŠ¡æˆ–软件的开å‘者将永远ä¸ä¼šè´Ÿè´£æ¢å¤æˆ–è¡¥å¿ç­‰æŸå®³æˆ–刑事责任。
+通过使用本软件和æœåŠ¡ï¼Œç”¨æˆ·æœ‰è‡ªå·±çš„义务必须éµå®ˆæ‰€æœ‰ç›¸å…³çš„法律和规则。用户将完全承担任何æŸå¤±å’Œä½¿ç”¨æœ¬è½¯ä»¶åŠæœåŠ¡å¯¼è‡´çš„责任,无论日本领土以内还是以外。
+如果你ä¸åŒæ„也ä¸ç†è§£ä¸Šè¿°è­¦å‘Šï¼Œä¸è¦ä½¿ç”¨ä»»ä½• VPN Gate 学术实验æœåŠ¡åŠŸèƒ½ã€‚
+VPN Gate 仅仅是学术目的的一个研究项目。VPN Gate 是作为 SoftEtherVPN å’Œ UT-VPN 的一个æ’件被开å‘的。然而, VPN Gate çš„æ¯ä¸€éƒ¨åˆ†éƒ½æ˜¯åœ¨ç­‘波大学的这一研究项目被开å‘的。VPN Gate 的任何部分都ä¸æ˜¯ SoftEther å…¬å¸å¼€å‘的。VPN Gate 研究项目ä¸æ˜¯ç”± SoftEther å…¬å¸å¼•å¯¼ã€ç»è¥ï¼ŒæŽ¨å¹¿å’Œä¿è¯çš„。
+
diff --git a/src/bin/hamcore/warning_en.txt b/src/bin/hamcore/warning_en.txt
new file mode 100644
index 00000000..527c2ac1
--- /dev/null
+++ b/src/bin/hamcore/warning_en.txt
@@ -0,0 +1,136 @@
+THE IMPORTANT NOTICES ABOUT SOFTETHER VPN
+
+FUNCTIONS OF VPN COMMUNICATIONS EMBEDDED ON THIS SOFTWARE ARE VERY POWERFUL THAN EVER. THIS STRONG VPN ABILITY WILL BRING YOU HUGE BENEFITS. HOWEVER, IF YOU MISUSE THIS SOFTWARE, IT MIGHT DAMAGES YOURSELF. IN ORDER TO AVOID SUCH RISKS, THIS DOCUMENT ACCOUNTS IMPORTANT NOTICES FOR CUSTOMERS WHO ARE WILLING TO USE THIS SOFTWARE. THE FOLLOWING INSTRUCTIONS ARE VERY IMPORTANT. READ AND UNDERSTAND IT CAREFULLY. ADDITIONALLY, IF YOU ARE PLANNING TO USE THE DYNAMIC DNS, THE NAT TRAVERSAL OR THE VPN AZURE FUNCTIONS, READ THE SECTION 3.5 CAREFULLY. THESE FUNCTIONS ARE FREE SERVICES PROVIDED VIA THE INTERNET, ARE NOT GUARANTEED, AND ARE NOT INTENDED TO BE USED FOR BUSINESS OR COMMERCIAL USE. DO NOT USE THESE SERVICES FOR YOUR BUSINESS OR COMMERCIAL USE.
+
+
+1. VPN Communication Protocols
+1.1. SoftEther VPN Protocol
+SoftEther VPN can perform VPN communication. Unlike traditional VPN protocols, SoftEther VPN has an implementation of the newly-designed "SoftEther VPN Protocol (SE-VPN Protocol)" . SE-VPN protocol encapsulates any Ethernet packets into a HTTPS (HTTP over SSL) connection. Therefore SE-VPN protocol can communicate beyond firewalls even if the firewall is configured to block traditional VPN packets by network administrator. SE-VPN protocol is designed and implemented to comply TLS 1.0 (RFC 5246) and HTTPS (RFC 2818). However, it sometimes have different behavior to RFCs. If you are a network administrator and want to block SE-VPN protocols on the firewall, you can adopt a "white-list" policy on the firewall to filter any TCP or UDP packets on the border except explicitly allowed packets towards specific web sites and servers.
+
+1.2. NAT Traversal Function
+Generally, if you use traditional VPN systems you have to request a network administrator to make the NAT or firewall to "open" or "relay" specific TCP or UDP ports. However, there are demands somehow to eliminate such working costs on network administrators. In order to satisfy such demands, SoftEther VPN has the newly-implemented "NAT Traversal" function. NAT Traversal is enabled by default. A SoftEther VPN Server running on the computer behind NAT or firewall can accept VPN connections from the Internet, without any special configurations on firewalls or NATs. If you want to disable the NAT Traversal function, modify the "DisableNatTraversal" to "true" on the configuration file of SoftEther VPN Server. In order to disable it on the client-side, append "/tcp" suffix on the destination hostname.
+
+1.3. Dynamic DNS Function
+Traditional legacy VPN system requires a static global IP address on the VPN server. In consideration of shortage of global IP addresses, SoftEther Corporation implements the "Dynamic DNS Function" on SoftEther VPN Server. Dynamic DNS is enabled by default. Dynamic DNS function notify the current global IP address of the PC to the Dynamic DNS Servers which are operated by SoftEther Corporation. A globally-unique hostname (FQDN) such as "abc.softether.net" ( "abc" varies as unique per a user) will be assigned on the VPN Server. If you tell this unique hostname to a VPN user, the user can specify it as the destination VPN Sever hostname on the VPN Client and will be able to connect the VPN Server. No IP addresses are required to know beforehand. If the IP address of the VPN Server varies, the registered IP address related to the hostname of Dynamic DNS service will be changed automatically. By this mechanism, no longer need a static global IP address which costs monthly to ISPs. You can use consumer-level inexpensive Internet connection with dynamic IP address in order to operate an enterprise-level VPN system. If you want to disable Dynamic DNS, specify "true" on the "Disabled" items of the "DDnsClient" directive on the SoftEther VPN Server configuration file. * Note for residents in People's Republic of China: If your VPN Server is running on the People's Republic of China, the DNS suffix will be replaced to "sedns.cn" domain. The "sedns.cn" domain is the service possessed and operated by "Beijing Daiyuu SoftEther Technology Co., Ltd" which is a Chinese-local enterprise.
+
+1.4. VPN over ICMP / VPN over DNS functions
+If you want to make a VPN connection between SoftEther VPN Client / Bridge and SoftEther VPN Server, but if TCP and UDP packets are prohibited by the firewall, then you can encapsulates payloads into "ICMP" (as known as Ping) or "DNS" packets. This function can realize a VPN connection by using ICMP or DNS even if the firewall or router blocks every TCP or UDP connections. VPN over ICMP / VPN over DNS functions are designed to comply standard ICMP and DNS specifications as possible, however it sometimes has a behavior not to fully comply them. Therefore, few poor-quality routers may be caused a memory-overflow or something troubles when a lot of ICMP or DNS packets are passed, and such routers sometimes freezes or reboots. It might affects other users on the same network. To avoid such risks, append the suffix "/tcp" on the destination hostname which is specified on the VPN-client side to disable VPN over ICMP / DNS functions.
+
+1.5. VPN Azure Cloud Service
+If your SoftEther VPN Server is placed behind the NAT or firwall, and by some reason you cannot use NAT Traversal function, Dynamic DNS function or VPN over ICMP/DNS function, you can use VPN Azure Clouse Service. SoftEther Corporation operates VPN Azure Cloud on Internet. After the VPN Server makes a connection to the VPN Azure Cloud, the hostname "abc.vpnazure.net" ( "abc" is a unique hostname) can be specified to connect to the VPN Server via the VPN Azure Cloud. Practically, such a hostname is pointing a global IP address of one of cloud servers which are operated by SoftEther Corporation. If A VPN Client connects to such a VPN Azure host, then the VPN Azure host will relay all traffics between the VPN Client and the VPN Server. VPN Azure is disabled by default. You can activate it easily by using VPN Server Configuration Tool.
+
+1.6. UDP Acceleration
+SoftEther VPN has the UDP Acceleration Function. If a VPN consists of two sites detects that UDP channel can be established, UDP will be automatically used. By this function, throughput of UDP increases. If direct UDP channel can be established, direct UDP packets will be used. However, if there is something obstacles such as firewalls or NATs, the "UDP Hole Punching" technology will be used, instead. The "UDP Hole Punching" uses the cloud servers which SoftEther Corporation operates on Internet. UDP Acceleration can be disabled anytime by setting up so on the VPN-client side.
+
+
+2. VPN Software
+2.1. SoftEther VPN Client
+If you use SoftEther VPN Client on Windows, the Virtual Network Adapter device driver will be installed on Windows. The Virtual Network Adapter is implemented as a kernel-mode driver for Windows. The driver is digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed by Symantec Corporation. A message to ask you want to sure install the driver might be popped up on the screen. SoftEther VPN Client may response the message if possible. SoftEther VPN Client also optimizes the configuration of MMCSS (Multimedia Class Scheduler Service) on Windows. You can undo the optimizations of MMCSS afterwards.
+
+2.2. SoftEther VPN Server / Bridge
+If you use SoftEther VPN Server / Bridge on Windows with "Local Bridge" functions, you have to install the low-level Ethernet packet processing driver on the computer. The driver is digitally-signed by a certificate issued by VeriSign, Inc. and also sub-signed by Symantec Corporation. SoftEther VPN Server / Bridge may disable the TCP/IP offloading features on the physical network adapter for Local Bridge function. In Windows Vista / 2008 or greater version, VPN Server may inject a packet-filter driver which complies Windows Filter Platform (WPF) specification into the kernel in order to provide IPsec function. The packet-filter driver will be loaded available only if IPsec function is enabled. Once you enables IPsec function of SoftEther VPN Server, the built-in IPsec function of Windows will be disabled. After you disabled IPsec function of SoftEther VPN Server, then the built-in IPsec function of Windows will revive. In order to provide the Local Bridge function, SoftEther VPN Server / Bridge disables the TCP/IP offloading function on the operating system.
+
+2.3. User-mode Installation
+You can install SoftEther VPN Server and SoftEther VPN Bridge as "User-mode" on Windows. In other words, even if you don't have Windows system administrator's privileges, you can install SoftEther VPN as a normal user. User-mode install will disable a few functions, however other most functions work well. Therefore, for example, an employee can install SoftEther VPN Server on the computer in the office network, and he will be able to connect to the server from his home. In order to realize such a system by user-self, no system administrative privileges are required in the view-point of technical. However, breaking rules of the company to install software on the computer without authority might be regarded as an unfavorable behavior. If you are an employee and belong to the company, and the company-policy prohibits installing software or making communications towards Internet without permission, you have to obtain a permission from the network administrator or the executive officer of your company in advance to install SoftEther VPN. If you install VPN Server / Bridge as User-mode, an icon will be appeared on the Windows task-tray. If you feel that the icon disturbs you, you can hide it by your operation. However, you must not exploit this hiding function to install VPN Server on other person's computer as a spyware. Such behavior might be an offence against the criminal law.
+
+2.4. Keep Alive Function
+SoftEther VPN Server and SoftEther VPN Bridge has Keep Alive Function by default. The purpose of this function is to sustain the Internet line active. The function transmits UDP packets with a random-byte-array-payload periodically. This function is useful to avoid automatic disconnection on mobile or dial-up connections. You can disable Keep Alive Function anytime.
+
+2.5. Uninstallation
+The uninstallation process of SoftEther VPN software will delete all program files. However, non-program files (such as files and data which are generated by running of programs) ) will not be deleted. For technical reason, the exe and resource files of uninstaller might remain. Such remaining files never affects to use the computer, however you can delete it manually. Kernel-mode drivers might not be deleted, however such drivers will not be loaded after the next boot of Windows. You can use "sc" command of Windows to delete kernel-mode drivers manually.
+
+2.6. Security
+You should set the administrator's password on SoftEther VPN Server / Bridge after installation. If you neglect to do it, another person can access to SoftEther VPN Server / Bridge and can set the password without your permission. This caution might be also applied on SoftEther VPN Client for Linux.
+
+2.7. Automatic Update Notification
+SoftEther VPN software for Windows has an automatic update notification function. It accesses to the SoftEther Update server periodically to check whether or not the latest version of software is released. If the latest version is released, the notification message will be popped up on the screen. In order to achieve this purpose, the version, language settings, the unique identifier, the IP address of your computer and the hostname of VPN Server which is connected to will be sent to the SoftEther Update server. No personal information will be sent. Automatic Update Notification is enabled by default, however you can disable it on the configuration screen. The setting whether turned on or turned off will be saved individually corresponding to each destination VPN server, by VPN Server Manager.
+
+2.8. Virtual NAT Function
+A Virtual Hub on SoftEther VPN Server / Bridge has "Virtual NAT Function" . Virtual NAT Function can share a single IP address on the physical network by multiple private IP address of VPN Clients. There are two operation mode of Virtual NAT: User-mode and Kernel-mode. In the user-mode operation, Virtual NAT shares an IP address which is assigned on the host operating system. Unlike user-mode, the kernel-mode operation attempts to find DHCP servers on the physical network. If there are two or more physical networks, a DHCP server will be sought automatically for each segments serially. If a DHCP server found, and an IP address is acquired, the IP address will be used by the Virtual NAT. In this case, an IP entry as a DHCP client will be registered on the IP pool of the physical DHCP Server. The physical default gateway and the DNS server will be used by the Virtual NAT in order to communicate with hosts in Internet. In kernel-mode operation, a Virtual Hub has a virtual MAC address which is operating on the physical Ethernet segment. In order to check the connectivity to Internet, SoftEther VPN periodically sends DNS query packet to resolve the IP address of host "www.yahoo.com" or "www.baidu.com" , and attempts to connect to the TCP port 80 of such a resulted IP address for connectivity check.
+
+2.9. Unattended Installation of Kernel-mode Components
+When SoftEther VPN will detect a necessity to install the kernel-mode components on Windows, a confirmation message will be appeared by Windows system. In this occasion, SoftEther VPN software will switch to the Unattended Installation mode in order to respond "Yes" to Windows. This is a solution to prevent dead-locks when a remote-administration is performed from remote place.
+
+2.10. Windows Firewall
+SoftEther VPN software will register itself as a safe-program. Such an entry will be remain after the uninstallation. You can remove it manually from the Control Panel of Windows.
+
+
+3. Internet Services
+3.1. Internet Services which are provided by SoftEther Corporation
+SoftEther Corporation provides Dynamic DNS, NAT Traversal and VPN Azure server services on the Internet. These services are free of charge. Customers can access to the services by using SoftEther VPN software, via Internet. These service will be planned to be available from Open-Source version of "SoftEther VPN" which will be released in the future.
+
+3.2. Sent Information and Privacy Protection
+SoftEther VPN software may send an IP address, hostname, the version of VPN software on the customer's computer to the cloud service operated by SoftEther Corporation, in order to use the above services. These sending of information are minimal necessary to use the services. No personal information will be sent. SoftEther Corporation records log files of the cloud service servers for 90 days at least with the received information. Such logs will be used for troubleshooting and other legitimate activities. SoftEther Corporation may provide logs to a public servant of Japanese government who are belonging to courts, police stations and the prosecutor's office, in order to comply such authorities' order. (Every Japanese public servants are liable by law to keep the information close.) Moreover, the IP addresses or other information will be processed statistically and provided to the public, not to expose the each concrete IP address, in order to release the release of research activities.
+
+3.3. Communication Data via VPN Azure Service
+Regardless of the above 3.2 rule, if the customer sends or receives VPN packets using VPN Azure Cloud Service, the actual payloads will stored and forwarded via the volatile memory of the servers for very short period. Such a behavior is naturally needed to provide the "VPN relay service" . No payloads will be recorded on "fixed" storages such as hard-drives. However, the "Wiretapping for Criminals Procedures Act" (The 137th legislation ruled on August 18, 1999 in Japan) requires telecommunication companies to allow the Japanese government authority to conduct a wire-tapping on the line. VPN Azure Servers which are physically placed on Japan are subjects of this law.
+
+3.4. Comply to Japanese Telecommunication Laws
+SoftEther Corporation complies with Japanese Telecommunication Laws as necessary to provide online services via Internet.
+
+3.5. Free and Academic Experiment Services
+SoftEther provides Dynamic DNS, NAT Traversal and VPN Azure as academic experiment services. Therefore, there services can be used for free of charge. These services are not parts of "SoftEther VPN Software Products" . These services are provided without any warranty. The services may be suspended or discontinued by technical or operational matters. In such occasions, users will not be able to use the services. A user have to understand such risks, and to acknowledge that such risks are borne by a user-self. SoftEther will never be liable to results or damages of use or unable-to-use of the service. Even if the user has already paid the license-fee of the commercial version of SoftEther VPN, such paid fees don't include any fees of these services. Therefore, if the online services will stop or be discontinued, no refunds or recoveries of damages will be provided by SoftEther Corporation.
+
+3.6. DNS Proxy Cloud Servers
+In some regions, when a user uses Internet, a DNS query sometimes broken or lost when it is passing through the ISP line. If SoftEther VPN Server, Client or Bridge detects a possibility that the accessing to the actual VPN server might be unstable, then DNS queries will be also transferred to the DNS proxy cloud servers which are operated by SoftEther Corporation. A DNS proxy cloud server will respond DNS queries with answering correct a IP address.
+
+
+4. General Cautions
+4.1. Needs an Approval from Network Administrator
+SoftEther VPN has powerful functions which don't require special settings by network administrators. For example, you need not to ask the administrator to configure the existing firewall in order to "open" a TCP/UDP port. Such characteristic features are for the purpose to eliminate working times and costs of network administrators, and avoid misconfiguration-risks around the tasks to open specific exception ports on the firewall. However, any employees belong to the company have to obtain an approval from the network administrator before installs SoftEther VPN. If your network administrator neglects to provide such an approval, you can consider to take an approval from an upper authority. (For example, executive officer of the company.) If you use SoftEther VPN without any approvals from the authority of your company, you might have disadvantage. SoftEther Corporation will be never liable for results or damages of using SoftEther VPN.
+
+4.2. Observe Laws of Your Country
+If your country's law prohibits the use of encryption, you have to disable the encryption function of SoftEther VPN by yourself. Similarly, in some countries or regions, some functions of SoftEther VPN might be prohibited to use by laws. Other countries' laws are none of SoftEther Corporation's concern because SoftEther Corporation is an enterprise which is located and registered in Japan physically. For example, there might be a risk that a part of SoftEther VPN conflicts an existing patent which is valid only on the specific region. SoftEther Corporation has no interests in such specific region outside Japan's territory. Therefore, if you want to use SoftEther VPN in regions outside Japan, you have to be careful not to violate third-person's rights. You have to verify the legitimacy of the use of SoftEther VPN in the specific region before you actually use it in such region. By nature, there are almost 200 countries in the World, and each country's law is different each other. It is practically impossible to verify every countries' laws and regulations and make the software comply with all countries' laws in advance to release the software. Therefore SoftEther Corporation has verified the legitimacy of SoftEther VPN against the laws and regulations of only Japan. If a user uses SoftEther VPN in a specific country, and damaged by public servants of the government authority, SoftEther Corporation will never be liable to recover or compensate such damages or criminal responsibilities.
+
+
+5. VPN Gate Academic Experiment Project
+(This chapter applies only on SoftEther VPN software package which contains the extension plug-in for VPN Gate Academic Experiment Project.)
+5.1. About VPN Gate Academic Experiment Project
+VPN Gate Academic Experiment Project is an online service operated for just the academic research purpose at the graduate school of University of Tsukuba, Japan. The purpose of this research is to expend our knowledge about the "Global Distributed Public VPN Relay Server" (GDPVRS) technology. For details, please visit http://www.vpngate.net/.
+
+5.2. About VPN Gate Service
+SoftEther VPN Server and SoftEther VPN Client may contain "VPN Gate Service" program. However, VPN Gate Service is disabled by default.
+VPN Gate Service should be activated and enabled by the voluntary intention of the owner of the computer which SoftEther VPN Server or SoftEther VPN Client is installed on. After you activate VPN Gate Service, the computer will be start to serve as a part of the Global Distributed Public VPN Relay Servers. The IP address, hostname and related information of the computer will be sent and registered to the directory server of VPN Gate Academic Experiment Project, and they will be published and disclosed to the public. This mechanism will allow any VPN Gate Client software's user to connect to the VPN Gate Service running on your computer. While the VPN session between a VPN Gate Client and your VPN Gate Service is established, the VPN Gate Client's user can send/receive any IP packets towards the Internet via the VPN Gate Service. The global IP address of the VPN Gate Service's hosing computer will be used as the source IP address of such communications which a VPN Gate Client initiates.
+VPN Gate Service will send some information to the VPN Gate Academic Experiment Service Directory Server. The information includes the operator's information which described in section 5.5, logging settings, uptime, operating system version, type of protocol, port numbers, quality information, statistical information, VPN Gate clients' log history data (includes dates, IP addresses, version numbers and IDs) and the version of the software. These information will be exposed on the directory. VPN Gate Service also receives a key for encoding which is described on the chapter 5.9 from the directory server.
+
+5.3. Details of VPN Gate Service's Behavior
+If you enable VPN Gate Service manually, which is disabled by default, the "VPNGATE" Virtual Hub will be created on the SoftEther VPN Server. If you are using SoftEther VPN Client and attempt to active VPN Gate Service on it, an equivalent program to SoftEther VPN Server will be invoked on the same process of SoftEther VPN Client, and the "VPNGATE" Virtual Hub will be created. The "VPNGATE" Virtual Hub contains a user named "VPN" by default which permits anyone on the Internet to make a VPN connection to the Virtual Hub. Once a VPN Client connects to the "VPNGATE" Virtual Hub, any communication between the user and the Internet will pass through the Virtual Hub, and transmitted/received using the physical network interface on the computer which SoftEther VPN Server (or SoftEther VPN Client) is running on. This will cause the result that a destination host specified by the VPN Client will identify that the source of the communication has initiated from the VPN Gate Service's hosting computer's IP address. However, for safety, any packets which destinations are within 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0 or 10.0.0.0/255.0.0.0 will be blocked by the "VPNGATE" Virtual Hub in order to protect your local network. Therefore, if you run VPN Gate Service on your corporate network or private network, it is safe because anonymous VPN Client users will not be permitted to access such private networks. VPN Gate Service also serves as relay for accessing to the VPN Gate Directory Server.
+In order to make VPN Gate Service familiar with firewalls and NATs, it opens an UDP port by using the NAT Traversal function which is described on the section 1.2. It also opens and listens on some TCP ports, and some TCP and UDP ports will be specified as the target port of Universal Plug and Play (UPnP) Port Transfer entries which are requested to your local routers. UPnP request packets will be sent periodically. Some routers keep such an opened TCP/UDP port permanently on the device. If you wish to close them, do it manually.
+VPN Gate Service also provides the mirror-site function for www.vpngate.net. This is a mechanism that a copy of the latest contents from www.vpngate.net will be hosted by the mirror-site tiny HTTP server which is running on the VPN Gate Service program. It will register itself on the mirror-sites list in www.vpngate.net. However, it never relays any other communications which are not towards www.vpngate.net.
+
+5.4. Communication between Internet via VPN Gate Service
+VPN Gate Service provides a routing between users and the Internet, by using the Virtual NAT Function which is described on the section 2.8. VPN Gate Service sends polling Ping packets to the server which is located on University of Tsukuba, and the Google Public DNS Server which is identified as 8.8.8.8, in order to check the latest quality of your Internet line. VPN Gate Service also sends and receives a lot of random packets to/from the Speed Test Server on University of Tsukuba. These quality data will be reported to VPN Gate Directory Server, automatically and periodically. The result will be saved and disclosed to the public. These periodical polling communication are adjusted not to occupy the Internet line, however in some circumstances they might occupy the line.
+
+5.5. Operator's Information of VPN Gate Service
+If you activate VPN Gate Service on your computer, the computer will be a part of the Global Distributed Public VPN Relay Servers. Therefore, the Operator's administrative information of your VPN Gate Service should be reported and registered on the VPN Gate Service Directory. Operator's information contains the name of the operator and the abuse-reporting contact e-mail address. These information can be inputted on the screen if the VPN Gate configuration. Inputted information will be transmitted to the VPN Gate Directory Server, stored and disclosed to the public. So you have to be careful to input information. By the way, until you specify something as the operator's information, the computer's hostname will be used automatically as the field of the name of the operator, by appending the "'s owner" string after the hostname.
+
+5.6. Observe Laws to Operate VPN Gate Service
+In some countries or regions, a user who is planning to activate and operate VPN Gate Service, he are mandated to obtain a license or register a service from/to the government. If your region has such a regulation, you must fulfill mandated process before activating VPN Gate Service in advance. Neither the developers nor operators of the VPN Gate Academic Experiment Project will be liable for legal/criminal responsibilities or damages which are occurred from failure to comply your local laws.
+
+5.7. Protect Privacy of Communication
+Most of countries have a law which requires communication service's operators, including VPN Gate Service operators, to protect the privacy of communication of third-persons. When you operate VPN Gate Service, you must always protect user's privacy.
+
+5.8. Packet Logs
+The packet logging function is implemented on VPN Gate Service. It records essential headers of major TCP/IP packets which are transmitted via the Virtual Hub. This function will be helpful to investigate the "original IP address" of the initiator of communication who was a connected user of your VPN Gate Service, by checking the packet logs and the connection logs. The packet logs are recorded only for such legitimate investigates purpose. Do not peek nor leak packet logs except the rightful purpose. Such act will be violate the section 5.7.
+
+5.9. Packet Logs Automatic Archiving and Encoding Function
+The VPN Gate Academic Experiment Service is operated and running under the Japanese constitution and laws. The Japanese constitution laws demand strictly protection over the privacy of communication. Because this service is under Japanese rules, the program of VPN Gate Service implements this "Automatic Log File Encoding" protection mechanism, and enabled by default.
+The VPN Gate Service is currently configured to encode packet log files which has passed two or more weeks automatically, by default. In order to protect privacy of communication, if a packet log file is once encoded, even the administrator of the local computer cannot censor the packet log file. This mechanism protects privacy of end-users of VPN Gate Service.
+You can change the VPN Gate Service setting to disable this automatic encoding function. Then packet log files will never be encoded even after two weeks passed. In such a configuration, all packet logs will remain as plain-text on the disk. Therefore you have to take care not to violate user's privacy.
+If you are liable to decode an encoded packet log files (for example: a VPN Gate Service's user illegally abused your VPN Gate Service and you have to decode the packet logs in order to comply the laws), contact the administrator of the VPN Gate Academic Experiment Service at Graduate School of University of Tsukuba, Japan. You can find the contact address at http://www.vpngate.net/. The administrator of VPN Gate Service will respond to decode the packet logs if there is an appropriate and legal request from court or other judicial authorities, according to laws.
+
+5.10. Caution if You Operate VPN Gate Service in the Japan's Territories
+When a user operates VPN Gate Service in the Japan's territories, such an act may be regulated under the Japanese Telecommunication Laws if the operation is a subject to the law. However, in such a circumstance, according to the "Japanese Telecommunication Business Compete Manual [supplemental version]" , non- profitable operations of communications are not identified as a "telecommunication business" . So usual operators of VPN Gate Service are not subjects to "telecommunication business operators" , and not be mandated to register to the government. Even so, legalities to protect the privacy of communication still imposed. As a conclusion, if you operate VPN Gate Service in the Japan's Territories, you must not leak the secrets of communications which are transmitted via your operating VPN Gate Service.
+
+5.11. VPN Gate Client
+If SoftEther VPN Client contains the VPN Gate Client plug-in, you can use it to obtain the list of current operating VPN Gate Service servers in the Internet, and make a VPN connection to a specific server on the list.
+VPN Gate Client always keeps the latest list of the VPN Gate Services periodically. Be careful if you are using a pay-per-use Internet line.
+When you start the VPN Gate Client software, the screen which asks you activate or not VPN Gate Service will be appeared. For details of VPN Gate Service, read the above sections.
+
+5.12. Caution before Joining or Exploiting VPN Gate Academic Experiment Project
+The VPN Gate Academic Experiment Service is operated as a research project at the graduate school on University of Tsukuba, Japan. The service is governed under the Japanese laws. Other countries' laws are none of our concerns nor responsibilities.
+By nature, there are almost 200 countries in the World, with different laws. It is impossible to verify every countries' laws and regulations and make the software comply with all countries' laws in advance to release the software. If a user uses VPN Gate service in a specific country, and damaged by public servants of the authority, the developer of either the service or software will never be liable to recover or compensate such damages or criminal responsibilities.
+By using this software and service, the user must observe all concerned laws and rules with user's own responsibility. The user will be completely liable to any damages and responsibilities which are results of using this software and service, regardless of either inside or outside of Japan's territory.
+If you don't agree nor understand the above warnings, do not use any of VPN Gate Academic Experiment Service functions.
+VPN Gate is a research project for just academic purpose only. VPN Gate was developed as a plug-in for SoftEther VPN and UT-VPN. However, all parts of VPN Gate were developed on this research project at University of Tsukuba. Any parts of VPN Gate are not developed by SoftEther Corporation. The VPN Gate Research Project is not a subject to be led, operated, promoted nor guaranteed by SoftEther Corporation.
+
diff --git a/src/bin/hamcore/warning_ja.txt b/src/bin/hamcore/warning_ja.txt
new file mode 100644
index 00000000..cf96f0ad
--- /dev/null
+++ b/src/bin/hamcore/warning_ja.txt
@@ -0,0 +1,139 @@
+SoftEther VPN ã«é–¢ã™ã‚‹é‡è¦äº‹é …説明書
+
+本ソフトウェア㮠VPN 通信機能ã¯ã‹ã¤ã¦ãªã„ã»ã©æ¥µã‚ã¦å¼·åŠ›ã§ã‚ã‚Šã€æ­£ã—ã„使ã„æ–¹ã«ã‚ˆã‚ŠãŠå®¢æ§˜ã¯å¤§ããªåˆ©ä¾¿æ€§ã¨åˆ©ç›Šã‚’手ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã—ã‹ã—ã€èª¤ã£ãŸä½¿ã„方を行ã†ã¨ä¸åˆ©ç›ŠãŒç™ºç”Ÿã™ã‚‹å±é™ºã‚‚ã‚ã‚Šã¾ã™ã€‚ãã®ã‚ˆã†ãªå±é™ºã‚’é¿ã‘ã‚‹ãŸã‚ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ã”使用ã«éš›ã—ã¦ãŠå®¢æ§˜ãŒäº‹å‰ã«èª¬æ˜Žã‚’å—ã‘ã‚‹ã¹ã事項を以下ã«è¨˜è¼‰ã„ãŸã—ã¾ã™ã€‚ã“ã®å†…容ã¯å¤§å¤‰é‡è¦ã§ã™ã‹ã‚‰ã€å分ç†è§£ã•ã‚Œã‚‹ã‚ˆã†ãŠé¡˜ã„ã„ãŸã—ã¾ã™ã€‚ã¾ãŸã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNSã€NAT トラãƒãƒ¼ã‚µãƒ«ã¾ãŸã¯ VPN Azure 機能をã”使用ã„ãŸã ãå‰ã«ã¯ä¸‹è¨˜ã® 3.5 節ã®æ³¨æ„書ãをよããŠèª­ã¿ãã ã•ã„。ã“ã® 3 ã¤ã®æ©Ÿèƒ½ã¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆçµŒç”±ã§æä¾›ã•ã‚Œã‚‹ç„¡å„Ÿã®ç„¡ä¿è¨¼ã®å­¦è¡“実験サービスã§ã‚ã‚Šã€éšœå®³ã®ç™ºç”ŸãŒè¨±ã•ã‚Œãªã„よã†ãªæ¥­å‹™ã«ãŠã„ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ã¯æƒ³å®šã•ã‚Œã¦ãŠã‚Šã¾ã›ã‚“。
+
+
+1. VPN 通信ã«ã¤ã„ã¦
+1.1. SoftEther VPN プロトコルã«ã¤ã„ã¦
+SoftEther VPN 㯠VPN 通信を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚ä¼çµ±çš„㪠VPN プロトコルã¨ã¯ç•°ãªã‚Šã€SoftEther VPN ã«ã¯æ–°ãŸã«è¨­è¨ˆã•ã‚ŒãŸã€ŒSoftEther VPN プロトコル (SE-VPN プロトコル) ã€ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚SE-VPN プロトコルã¯ä»»æ„ã®ãƒ‘ケットを HTTPS (HTTP over SSL) パケットã«ã‚«ãƒ—セル化ã—ã¦é€å—ä¿¡ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€æ—¢å­˜ã®ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã£ã¦é€šå¸¸ã® VPN プロトコルを通éŽã—ãªã„よã†ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã§ã‚ã£ã¦ã‚‚ã€SE-VPN プロトコルã¯å¤§æŠµã®å ´åˆã¯é€šéŽã—ã¾ã™ã€‚SE-VPN プロトコル㯠TLS 1.0 (RFC 5246) ãŠã‚ˆã³ HTTPS (RFC 2818) ã«æº–æ‹ ã™ã‚‹ã‚ˆã†ã«å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã™ãŒã€ä¸€éƒ¨éžæº–æ‹ ã®å‹•ä½œã‚’è¡Œã†å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ã‚‚ã—ã‚ãªãŸãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã§ã‚ã‚Šã€ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã§ SE-VPN プロトコルã®é€šä¿¡ã‚’é®æ–­ã—ãŸã„ã¨å¸Œæœ›ã•ã‚Œã‚‹å ´åˆã¯ã€ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã«ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆãƒ«ãƒ¼ãƒ«ã‚’é©ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€å¢ƒç•Œä¸Šã‚’æµã‚Œã‚‹ã™ã¹ã¦ã®ç„¡è¨±å¯ã® TCP ãŠã‚ˆã³ UDP パケットをé®æ–­ã—ã€ä¸€éƒ¨è¨±å¯ã—㟠Web サイトやサーãƒãƒ¼ç­‰ã¨ã®é–“ã®é€šä¿¡ã®ã¿è¨±å¯ã™ã‚‹ã‚ˆã†ã«è¨­å®šã™ã‚‹ã“ã¨ã§ãã®å¸Œæœ›ã‚’実ç¾ã§ãã¾ã™ã€‚
+
+1.2. NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã«ã¤ã„ã¦
+従æ¥ã® VPN システムã®å ´åˆã€NAT やファイアウォールã®å†…å´ã« VPN サーãƒãƒ¼ã‚’設置ã™ã‚‹å ´åˆã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ä¾é ¼ã—㦠NAT やファイアウォールã«ãŠã„ã¦ã€Œãƒãƒ¼ãƒˆé–‹æ”¾ã€ã‚„「ãƒãƒ¼ãƒˆè»¢é€ã€ã¨ã„ã£ãŸè¨­å®šã‚’è¡Œã£ã¦ã‚‚らã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã—ã‹ã—ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ãã®ã‚ˆã†ãªæ‰‹é–“ã‚’ã‹ã‘ãšã«ç¤¾å†…ã®è‡ªåˆ†ã®ã‚³ãƒ³ãƒ”ュータ㫠VPN サーãƒãƒ¼ã‚’インストールã—社外ã‹ã‚‰æŽ¥ç¶šã—ãŸã„ã¨ã„ã†éœ€è¦ã«å¿œãˆã‚‹ãŸã‚ã€SoftEther VPN ã«ã¯å¼·åŠ›ãªã€ŒNAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã€ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ SoftEther VPN Server ã¯ã€ãŸã¨ãˆ NAT やファイアウォールã®å†…å´ã§ã‚ã£ã¦ã‚‚ã€ç‰¹åˆ¥ãªè¨­å®šãªã—ã«ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆå´ã‹ã‚‰ VPN 接続をå—付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã‚’サーãƒãƒ¼å´ã§ç„¡åŠ¹ã«ã™ã‚‹ã«ã¯ã€SoftEther VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã®ã€ŒDisableNatTraversalã€é …ç›®ã®å€¤ã‚’「trueã€ã«å¤‰æ›´ã—ã¦ãã ã•ã„。クライアントå´ã§ç„¡åŠ¹ã«ã™ã‚‹ã«ã¯ã€æŽ¥ç¶šå…ˆã® VPN サーãƒãƒ¼ã®ãƒ›ã‚¹ãƒˆåã®å¾Œã«ã€Œ/tcpã€ã¨ã„ã†ã‚µãƒ•ã‚£ãƒƒã‚¯ã‚¹ã‚’追加ã—ã¦ãã ã•ã„。
+
+1.3. ダイナミック DNS 機能ã«ã¤ã„ã¦
+従æ¥ã® VPN システムã®å ´åˆã€VPN サーãƒãƒ¼ã«ã¯å›ºå®šã®ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスを割当ã¦ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã—ãŸã€‚ソフトイーサ社ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã®æž¯æ¸‡ã«é…æ…®ã™ã‚‹ãŸã‚ã€SoftEther VPN Server ã«ã€Œãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ã€ã‚’æ­è¼‰ã—ã¾ã—ãŸã€‚ダイナミック DNS 機能ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚ダイナミック DNS 機能ã¯ç¾åœ¨ã® SoftEther VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã®ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスをã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µç¤¾ãŒé‹ç”¨ã™ã‚‹ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サーãƒãƒ¼ã«å¯¾ã—ã¦å®šæœŸçš„ã«é€šçŸ¥ã—ã¾ã™ã€‚ã“ã®éš›ã«ã€ã€Œabc.softether.net〠( "abc" 部分ã¯åˆ©ç”¨è€…ãŒå¤‰æ›´å¯èƒ½ãªä»»æ„ã®ãƒ¦ãƒ‹ãƒ¼ã‚¯ãª ID) ã¨ã„ã†å…¨ä¸–ç•Œã‹ã‚‰åˆ©ç”¨å¯èƒ½ãªãƒ›ã‚¹ãƒˆå (FQDN) ãŒå‰²å½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ホストåを知らã•ã‚ŒãŸ VPN ã®åˆ©ç”¨è€…ã¯ã€ãƒ›ã‚¹ãƒˆåを指定ã™ã‚‹ã ã‘ã§ã€ç¾åœ¨ã® IP アドレスを知らãªãã¦ã‚‚ã„ã¤ã§ã‚‚ VPN サーãƒãƒ¼ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚IP アドレスãŒå¤‰åŒ–ã—ãŸå ´åˆã¯ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS サービスã®ãƒ›ã‚¹ãƒˆåã«å¯¾å¿œã™ã‚‹ IP アドレスãŒè‡ªå‹•çš„ã«å¤‰åŒ–ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€å›ºå®šã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスãŒä¸è¦ã«ãªã‚Šã€æ¯Žæœˆç™ºç”Ÿã™ã‚‹é«˜é¡ãª ISP ã¸ã®é€šä¿¡ã‚³ã‚¹ãƒˆã‚’削減ã§ãã€æ³•äººåˆ©ç”¨ã§ã‚ã£ã¦ã‚‚コンシューマå‘ã‘ã®å®‰ä¾¡ãªå¯å¤‰ IP アドレス接続ãŒåˆ©ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ダイナミック DNS 機能を無効ã«ã™ã‚‹ã«ã¯ã€SoftEther VPN Server ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã®ã€ŒDDnsClientã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒ†ã‚£ãƒ–内ã®ã€ŒDisabledã€é …ç›®ã®å€¤ã‚’「trueã€ã«å¤‰æ›´ã—ã¦ãã ã•ã„。中è¯äººæ°‘共和国ã§ã”利用ã•ã‚Œã‚‹å ´åˆã®æ³¨æ„: DNS サフィックスã¯ä¸­è¯äººæ°‘共和国内ã§åˆ©ç”¨ã™ã‚‹å ´åˆã¯ã€Œsedns.cnã€ã¨ã„ã†ãƒ‰ãƒ¡ã‚¤ãƒ³åã«ç½®æ›ã•ã‚Œã¾ã™ã€‚sedns.cn ドメインã¯ä¸­å›½ä¼æ¥­ (北京大游索易有é™å…¬å¸) ãŒé‹å–¶ãƒ»ç®¡ç†ã—ã¦ã„るサービスã§ã™ã€‚
+
+1.4. VPN over ICMP 機能ãŠã‚ˆã³ VPN over DNS 機能ã«ã¤ã„ã¦
+SoftEther VPN Client / Bridge ㌠SoftEther VPN Server ã¨ã®é–“㧠VPN 通信を行ãŠã†ã¨ã™ã‚‹å ´åˆã€TCP 㨠UDP ã®ä¸¡æ–¹ã®ãƒ—ロトコルãŒé€šä¿¡ã§ããªã„å ´åˆã®ãŸã‚ã«ã€VPN を「ICMP〠(ã„ã‚ゆる Ping) ãŠã‚ˆã³ã€ŒDNSã€ãƒ‘ケットã«ã‚«ãƒ—セル化ã—ã¦é€šä¿¡ã™ã‚‹æ©Ÿèƒ½ãŒå®Ÿè£…ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®æ©Ÿèƒ½ã«ã‚ˆã‚Šã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯çµŒè·¯ä¸Šã®ãƒ«ãƒ¼ã‚¿ã‚„ファイアウォールãªã©ãŒ TCP ã‚„ UDP ã®é€šä¿¡ã‚’é®æ–­ã—ã¦ã—ã¾ã†å ´åˆã§ã‚‚ã€ICMP ã¾ãŸã¯ DNS ã®é€šä¿¡ãŒå¯èƒ½ã§ã‚れ㰠VPN 接続を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚VPN over ICMP 機能ãŠã‚ˆã³ VPN over DNS 機能ã¯ã€ICMP ã‚„ DNS ã®è¦æ ¼ã«ã§ãã‚‹é™ã‚Šæº–æ‹ ã™ã‚‹ã‚ˆã†ã«è¨­è¨ˆã•ã‚Œã¦ã„ã¾ã™ãŒã€ä¸€éƒ¨éžæº–æ‹ ã®å‹•ä½œã‚’è¡Œã†å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚一部ã®è¨­è¨ˆä¸è‰¯ã®ãƒ«ãƒ¼ã‚¿ã¯å¤§é‡ã® ICMP ã‚„ DNS パケットãŒé€šéŽã™ã‚‹ã¨ãƒ¡ãƒ¢ãƒªã‚ªãƒ¼ãƒãƒ¼ãƒ•ãƒ­ãƒ¼ãªã©ã‚’発生ã—ã€ãƒ•ãƒªãƒ¼ã‚ºã—ãŸã‚Šå†èµ·å‹•ã—ãŸã‚Šã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã¯ä»–ã®åˆ©ç”¨è€…ã«ã‚‚悪影響を与ãˆã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®ã‚ˆã†ãªãƒªã‚¹ã‚¯ã‚’é¿ã‘ã‚‹ãŸã‚ã« VPN over ICMP 機能ãŠã‚ˆã³ VPN over DNS 機能を無効ã«ã™ã‚‹ã«ã¯ã€VPN 接続元ã®å´ã§æŽ¥ç¶šå…ˆã®ãƒ›ã‚¹ãƒˆå文字列ã®å¾Œã«ã€Œ/tcpã€ã¨ã„ã†ã‚µãƒ•ã‚£ãƒƒã‚¯ã‚¹ã‚’追加ã—ã¦ãã ã•ã„。
+
+1.5. VPN Azure クラウドサービスã«ã¤ã„ã¦
+SoftEther VPN Server ㌠NAT やファイアウォールã®å†…å´ã«ã‚ã‚Šã€ä½•ã‚‰ã‹ã®ç†ç”±ã§ NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã€ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNS 機能ãŠã‚ˆã³ VPN over ICMP/DNS 機能を利用ã§ããªã„å ´åˆã¯ã€VPN Azure クラウドサービスを利用ã§ãã¾ã™ã€‚ソフトイーサ社ã¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã§ VPN Azure クラウドをé‹ç”¨ã—ã¦ã„ã¾ã™ã€‚VPN Server 㯠VPN Azure クラウドã«ä¸€åº¦æŽ¥ç¶šã™ã‚Œã°ã€ãれ以é™ã¯ã€Œabc.vpnazure.net〠(abc ã¯ãƒ¦ãƒ‹ãƒ¼ã‚¯ãªãƒ›ã‚¹ãƒˆå) ã¨ã„ã†ãƒ›ã‚¹ãƒˆåãŒå‰²å½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã®ãƒ›ã‚¹ãƒˆåã¯å®Ÿéš›ã«ã¯ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µãŒé‹å–¶ã™ã‚‹ã‚¯ãƒ©ã‚¦ãƒ‰ã‚µãƒ¼ãƒãƒ¼ã®ã‚°ãƒ­ãƒ¼ãƒãƒ« IP アドレスã«é–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚VPN クライアントã¯ã“ã® VPN Azure ホストã«å¯¾ã—ã¦æŽ¥ç¶šã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€VPN Azure ã¯é€šä¿¡ã‚’折り返ã—中継ã—㦠VPN サーãƒãƒ¼ã«å±Šã‘ã¾ã™ã€‚VPN Azure 機能ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€VPN Server 管ç†ãƒ„ールã§ç°¡å˜ã«æœ‰åŠ¹åŒ–ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+1.6. UDP 高速化機能ã«ã¤ã„ã¦
+SoftEther VPN ã«ã¯ UDP 高速化機能ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚VPN を構築ã™ã‚‹ 2 拠点間㧠UDP ãƒãƒ£ãƒãƒ«ã®æ§‹ç¯‰ãŒå¯èƒ½ã§ã‚ã‚‹ã“ã¨ãŒæ¤œå‡ºã•ã‚ŒãŸå ´åˆã¯ã€è‡ªå‹•çš„ã« UDP ã«ã‚ˆã‚‹é€šä¿¡ã‚’è¡Œã„ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Š VPN ã®ã‚¹ãƒ«ãƒ¼ãƒ—ットãŒå‘上ã—ã¾ã™ã€‚UDP ãƒãƒ£ãƒãƒ«ã®æ§‹ç¯‰ã®éš›ã«ã¯ã€ç›´æŽ¥çš„㪠UDP パケットã®ä¼é€ãŒå¯èƒ½ãªå ´åˆã¯ãれを使ã„ã¾ã™ãŒã€é€”中㫠NAT やファイアウォールãŒã‚ã‚‹ã“ã¨ãŒæ¤œå‡ºã•ã‚ŒãŸå ´åˆã¯ä»£ã‚ã‚Šã«ã€ŒUDP ホールパンãƒãƒ³ã‚°ã€ã‚’使用ã—ã¾ã™ã€‚UDP ホールパンãƒãƒ³ã‚°ãŒä½¿ç”¨ã•ã‚Œã‚‹å ´åˆã«ã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µç¤¾ãŒé‹å–¶ã™ã‚‹ UDP ホールパンãƒãƒ³ã‚°ã‚µãƒ¼ãƒãƒ¼ãŒåˆ©ç”¨ã•ã‚Œã¾ã™ã€‚UDP 高速化機能ã¯ã€VPN 接続元ã®å´ã®è¨­å®šã§ã„ã¤ã§ã‚‚無効ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+
+2. VPN ソフトウェアã«ã¤ã„ã¦
+2.1. SoftEther VPN Client
+SoftEther VPN Client ã‚’ Windows ã§ä½¿ç”¨ã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ LAN カードをコンピュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚仮想 LAN カード㯠Windows 上ã§å‹•ä½œã™ã‚‹ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ãƒ‰ãƒ©ã‚¤ãƒã¨ã—ã¦å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã™ã€‚当該ドライãƒã¯ VeriSign 社ã®ç™ºè¡Œã™ã‚‹è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ãƒ‡ã‚¸ã‚¿ãƒ«ç½²åã•ã‚Œã¦ãŠã‚Šã€Symantec 社ã«ã‚ˆã‚‹å‰¯ç½²åã‚‚ã•ã‚Œã¦ã„ã¾ã™ã€‚ドライãƒã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ™‚ã«ã¯æœ¬å½“ã«ãƒ‰ãƒ©ã‚¤ãƒã‚’インストールã™ã‚‹ã‹ã©ã†ã‹ã®ç¢ºèªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚SoftEther VPN Client ã¯å¯èƒ½ãªå ´åˆã¯è‡ªå‹•çš„ã«å½“該確èªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã«å¿œç­”ã—ã¾ã™ã€‚SoftEther VPN Client ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ™‚ã«é€šä¿¡ã‚’最é©åŒ–ã™ã‚‹ãŸã‚ Windows ã® MMCSS (Multimedia Class Scheduler Service) ã®è¨­å®šã‚’最é©åŒ–ã—ã¾ã™ã€‚MMCSS ã®è¨­å®šã®æœ€é©åŒ–ã¯å¾Œã‹ã‚‰å…ƒã«æˆ»ã™ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+2.2. SoftEther VPN Server / Bridge
+SoftEther VPN Server / Bridge ã‚’ Windows ã§ä½¿ç”¨ã™ã‚‹å ´åˆã§ã€Œãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能ã€ã‚’使用ã™ã‚‹å ´åˆã¯ã€ä½Žãƒ¬ã‚¤ãƒ¤ Ethernet パケットé€å—信ドライãƒã‚’コンピュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚当該ドライãƒã¯ VeriSign 社ã®ç™ºè¡Œã™ã‚‹è¨¼æ˜Žæ›¸ã«ã‚ˆã£ã¦ãƒ‡ã‚¸ã‚¿ãƒ«ç½²åã•ã‚Œã¦ãŠã‚Šã€Symantec 社ã«ã‚ˆã‚‹å‰¯ç½²åã‚‚ã•ã‚Œã¦ã„ã¾ã™ã€‚SoftEther VPN Server / Bridge ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジã®ãŸã‚ã«ç‰©ç†çš„㪠LAN カード㮠TCP/IP オフローディング機能を無効ã«ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚Windows Vista / 2008 以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€VPN Server ㌠IPsec 機能をæä¾›ã™ã‚‹ãŸã‚ã« Windows Filter Platform (WFP) ã«é©åˆã—ãŸãƒ‘ケットフィルタドライãƒã‚’カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã«æŒ¿å…¥ã—ã¾ã™ã€‚ã“ã®ãƒ‘ケットフィルタドライãƒã¯ IPsec 機能を有効ã«ã—ãŸå ´åˆã®ã¿ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¾ã™ã€‚SoftEther VPN Server ã® IPsec 機能を有効ã«ã™ã‚‹ã¨ã€Windows 標準㮠IPsec 機能ã¯åˆ©ç”¨ã§ããªããªã‚Šã¾ã™ã€‚ãŸã ã—ã€SoftEther VPN Server ã® IPsec 機能を無効ã«ã™ã‚‹ã¨ã€ã“ã®ç¾è±¡ã¯å…ƒã«æˆ»ã‚Šã¾ã™ã€‚SoftEther VPN Server / Bridge ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒ–リッジ機能を使用ã™ã‚‹ãŸã‚ã« OS ã® TCP/IP オフローディング機能を無効ã«è¨­å®šã—ã¾ã™ã€‚
+
+2.3. ユーザーモードã§ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«
+SoftEther VPN Server ãŠã‚ˆã³ SoftEther VPN Bridge 㯠Windows ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¤ã¾ã‚Šã€ç¤¾å†… PC ãªã©ã§ Windows ã®ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…権é™ã‚’æŒã£ã¦ã„ãªã„一般ユーザーã§ã‚ã£ã¦ã‚‚インストールを行ãˆã¾ã™ã€‚ユーザーモードã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã†ã¨ä¸€éƒ¨ã®æ©Ÿèƒ½ãŒåˆ¶é™ã•ã‚Œã¾ã™ãŒã€å¤§éƒ¨åˆ†ã®æ©Ÿèƒ½ã¯æ­£å¸¸ã«å‹•ä½œã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãŸã¨ãˆã°ç¤¾å“¡ãŒç¤¾å†… PC ã«ä¸€èˆ¬ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã—㦠VPN Server をインストールã—ã€è‡ªå®…ã‹ã‚‰ç¤¾å†… LAN ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚技術的ã«ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…特権ã¯ä¸€åˆ‡ä¸è¦ã§ã™ãŒã€ã ã‹ã‚‰ã¨ã„ã£ã¦ä¼æ¥­ã®è¦å‰‡ã«åã—ã¦å‹æ‰‹ã« VPN サーãƒãƒ¼ã‚’構築ã™ã‚‹ã“ã¨ã¯å¥½ã¾ã—ããªã„å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ã‚ãªãŸãŒä¼æ¥­ã«æ‰€å±žã™ã‚‹ç¤¾å“¡ã®å ´åˆã§ã€ä¼æ¥­ã®è¦å‰‡ã§ç„¡æ–­ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚„外部ã¨ã®é€šä¿¡ãŒç¦æ­¢ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€äº‹å‰ã«ä¼æ¥­ã®çµŒå–¶è€…ã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã‹ã‚‰æ˜Žç¤ºçš„ãªåŒæ„ã‚’å¾—ã¦ã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’è¡Œã£ã¦ãã ã•ã„。ユーザーモード㧠VPN Server / VPN Bridge ãŒå‹•ä½œã—ã¦ã„ã‚‹é–“ã¯ã€Windows ã®ã‚¿ã‚¹ã‚¯ãƒˆãƒ¬ã‚¤ã«ã‚¢ã‚¤ã‚³ãƒ³ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ã‚¢ã‚¤ã‚³ãƒ³ãŒé‚ªé­”ã§ã‚ã‚‹ã¨æ„Ÿã˜ã‚‹å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã‚‹æ“作ã«ã‚ˆã‚Šéžè¡¨ç¤ºã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ãŸã ã—ã€ã“ã®æ©Ÿèƒ½ã‚’悪用ã—ã¦ä»–人ã®ã‚³ãƒ³ãƒ”ュータ㫠VPN Server ã‚’å‹æ‰‹ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã€ã‚¹ãƒ‘イウェアã¨ã—ã¦åˆ©ç”¨ã—ã¦ã¯ãªã‚Šã¾ã›ã‚“。ãã®ã‚ˆã†ãªè¡Œç‚ºã¯æ³•å¾‹ã«é•åã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚
+
+2.4. キープアライブ通信
+SoftEther VPN Server ãŠã‚ˆã³ SoftEther VPN Bridge ã§ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆå›žç·šã‚’活性化ã—ãŸã¾ã¾ã«ã—ã¦ãŠããŸã‚ã®ã‚­ãƒ¼ãƒ—アライブ通信機能ãŒæœ‰åŠ¹ã«ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®æ©Ÿèƒ½ã«ã‚ˆã‚Šã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«å¯¾ã—ã¦å®šæœŸçš„ã«ãƒ©ãƒ³ãƒ€ãƒ ãªå†…容㮠UDP パケットをé€ä¿¡ã—ã¾ã™ã€‚ã“ã®æ©Ÿèƒ½ã¯ã€ãƒ¢ãƒã‚¤ãƒ«å›žç·šã‚„ダイヤルアップ回線ãªã©ãŒè‡ªå‹•çš„ã«åˆ‡æ–­ã•ã‚Œã¦ã—ã¾ã†ã“ã¨ã‚’防止ã™ã‚‹ãŸã‚ã«æœ‰ç›Šã§ã™ã€‚キープアライブ通信機能ã¯ã„ã¤ã§ã‚‚無効ã«ã§ãã¾ã™ã€‚
+
+2.5. アンインストール
+SoftEther VPN ソフトウェアをアンインストールã™ã‚‹å ´åˆã¯ã€ãƒ—ログラムファイルã¯ã™ã¹ã¦å‰Šé™¤ã•ã‚Œã¾ã™ã€‚ãŸã ã—ã€ãƒ—ログラムファイル以外ã®ãƒ•ã‚¡ã‚¤ãƒ« (ãŸã¨ãˆã°ãƒ—ログラムã®å‹•ä½œã«ã‚ˆã£ã¦ä½œæˆã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚„データ) ã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“。ã¾ãŸã€æŠ€è¡“çš„ãªç†ç”±ã«ã‚ˆã‚Šã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ©æœ¬ä½“ã® EXE ファイルãŠã‚ˆã³ãƒªã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚‚削除ã•ã‚Œãšã«æ®‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“れらã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ®‹ç•™ã™ã‚‹ã“ã¨ã¯ã‚³ãƒ³ãƒ”ュータã®åˆ©ç”¨ä¸Šæ‚ªå½±éŸ¿ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãŠå¥½ã¿ã«å¿œã˜ã¦æ‰‹å‹•ã§å‰Šé™¤ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã¾ãŸã€ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ãƒ‰ãƒ©ã‚¤ãƒã‚‚削除ã•ã‚Œãªã„å ´åˆãŒã‚ã‚Šã¾ã™ãŒã€æ¬¡å›ž Windows 起動時ã‹ã‚‰ä¸»è¦ã‚³ãƒ¼ãƒ‰ã¯ãƒ¡ãƒ¢ãƒªã«ãƒ­ãƒ¼ãƒ‰ã•ã‚Œãšç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ãƒ‰ãƒ©ã‚¤ãƒã‚‚ Windows ã®ã€Œscã€ã‚³ãƒžãƒ³ãƒ‰ã‚’用ã„ã¦ãŠå¥½ã¿ã«å¿œã˜ã¦æ‰‹å‹•ã§å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+2.6. セキュリティ
+SoftEther VPN Server / Bridge をインストールã—ãŸå¾Œã¯ã€é€Ÿã‚„ã‹ã«ç®¡ç†è€…パスワードを設定ã—ã¦ãã ã•ã„。管ç†è€…パスワードãŒç©ºç™½ã®ã¾ã¾æ”¾ç½®ã™ã‚‹ã¨ã€ç¬¬ä¸‰è€…ãŒå‹æ‰‹ã«ç®¡ç†è€…モード㧠SoftEther VPN Server / Bridge ã«æŽ¥ç¶šã—ã¦ç®¡ç†è€…パスワードを設定ã—ãŸã‚Šã€è¨­å®šã‚’変更ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®æ³¨æ„事項ã¯ã€Linux 版㮠SoftEther VPN Client ã«ã‚‚é©ç”¨ã•ã‚Œã¾ã™ã€‚
+
+2.7. アップデート通知機能
+Windows 版㮠SoftEther VPN ソフトウェアã«ã¯ã€ã‚¢ãƒƒãƒ—デート通知機能ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚ソフトイーサ社㮠SoftEther Update サーãƒãƒ¼ã«å¯¾ã—ã¦å®šæœŸçš„ã« HTTP ã§é€šä¿¡ã‚’è¡Œã„ã€æœ€æ–°ç‰ˆã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ãªã„ã‹ã©ã†ã‹ã‚’確èªã—ã¾ã™ã€‚ã‚‚ã—最新版ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãã®æ—¨ã‚’ç”»é¢ä¸Šã«è¡¨ç¤ºã—ã¾ã™ã€‚ã“ã®ç›®çš„ã‚’é”æˆã™ã‚‹ãŸã‚ã«ã€ç¾åœ¨ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€è¨€èªžã€å›ºæœ‰è­˜åˆ¥å­ã€IP アドレスãŠã‚ˆã³æŽ¥ç¶šå…ˆ VPN サーãƒãƒ¼ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒ SoftEther Update サーãƒãƒ¼ã«å¯¾ã—ã¦é€ä¿¡ã•ã‚Œã¾ã™ã€‚個人情報ã¯ä¸€åˆ‡é€ä¿¡ã•ã‚Œã¾ã›ã‚“。アップデート通知機能ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€è¨­å®šç”»é¢ã‹ã‚‰ã‚ªãƒ•ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚オン / オフã®è¨­å®šã¯ã€VPN サーãƒãƒ¼ç®¡ç†ãƒžãƒãƒ¼ã‚¸ãƒ£ã®å ´åˆã¯æŽ¥ç¶šå…ˆã® VPN サーãƒãƒ¼ã”ã¨ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+
+2.8. 仮想 NAT 機能
+SoftEther VPN Server / VPN Bridge ã®ä»®æƒ³ HUB ã«ã¯ã€Œä»®æƒ³ NAT 機能ã€ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚仮想 NAT 機能ã¯ã€1 個ã®ç‰©ç†çš„㪠IP アドレスをã€è¤‡æ•°å€‹ã®ä»®æƒ³çš„ãªãƒ—ライベート IP アドレスを割当ã¦ã‚‰ã‚ŒãŸ VPN Client ã§å…±æœ‰ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚仮想 NAT 機能ã®å‹•ä½œãƒ¢ãƒ¼ãƒ‰ã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã¨ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã® 2 種類ãŒã‚ã‚Šã¾ã™ã€‚ユーザーモードã§å‹•ä½œã™ã‚‹å ´åˆã€NAT ã®å¤–å´ã®ç‰©ç†çš„㪠IP アドレスã¯ã€VPN Server を動作ã•ã›ã‚‹ã‚³ãƒ³ãƒ”ュータ㮠OS ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ãŒæŒã¤ IP アドレスを共有ã—ã¾ã™ã€‚ã“ã‚Œã¨ç•°ãªã‚Šã€ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã™ã‚‹å ´åˆã¯ã€VPN Server ã¯ã‚³ãƒ³ãƒ”ュータã«è£…ç€ã•ã‚Œã¦ã„る物ç†çš„㪠Ethernet ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ€ãƒ—タをスキャンã—ã€åˆ©ç”¨å¯èƒ½ãª IP アドレスを 1 個ã€ç‰©ç†çš„㪠Ethernet セグメント上㮠DHCP サーãƒãƒ¼ã‹ã‚‰å–å¾—ã—よã†ã¨è©¦ã¿ã¾ã™ã€‚IP アドレスã®å–å¾—ã«æˆåŠŸã—ãŸå ´åˆã¯ã€ãã® IP アドレスãŒä»®æƒ³ NAT ã«ã‚ˆã£ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚ã“ã®å ´åˆã€ç‰©ç†çš„㪠DHCP サーãƒãƒ¼ä¸Šã® IP プール㫠DHCP クライアントエントリãŒä½œæˆã•ã‚Œã¾ã™ã€‚物ç†çš„㪠Ethernet セグメント上ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤ãŠã‚ˆã³ DNS サーãƒãƒ¼ãŒä»®æƒ³ NAT を経由ã—ãŸã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã¨ã®é–“ã®é€šä¿¡ã®ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã§å‹•ä½œã™ã‚‹å ´åˆã¯ã€ä»®æƒ³ NAT ã¯ç‰©ç†çš„㪠Ethernet セグメント上㧠1 個ã®ä»®æƒ³ MAC アドレスをæŒã¡ã¾ã™ã€‚カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ NAT ã®å‹•ä½œãŒå¯èƒ½ã‹ã©ã†ã‹ã‚’判断ã™ã‚‹ãŸã‚ã€VPN Server ã¯å®šæœŸçš„ã«ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã¸ã®æŽ¥ç¶šæ€§ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¾ã™ã€‚接続性ã®ãƒã‚§ãƒƒã‚¯ã®ãŸã‚ã«ã¯ã€www.yahoo.com ã¾ãŸã¯ www.baidu.com ã¨ã„ã†ãƒ›ã‚¹ãƒˆåã¸ã® DNS クエリã®å¿œç­”ã®æ¤œæŸ»ã¨ã€å¿œç­”ã•ã‚ŒãŸ IPv4 アドレス宛㮠TCP ãƒãƒ¼ãƒˆ 80 ã¸ã®æŽ¥ç¶šã®æ¤œæŸ»ãŒå®Ÿæ–½ã•ã‚Œã¾ã™ã€‚
+
+2.9. カーãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®è‡ªå‹•ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—
+SoftEther VPN ソフトウェア㌠Windows ã«ã‚«ãƒ¼ãƒãƒ«ãƒ¢ãƒ¼ãƒ‰ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã‚’インストールã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã“ã¨ãŒæ¤œå‡ºã•ã‚ŒãŸå ´åˆã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã†ã‹å¦ã‹ã‚’確èªã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒ Windows ã«ã‚ˆã£ã¦è¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã®å ´åˆã€SoftEther VPN ソフトウェアã¯è‡ªå‹•çš„ã«ç„¡äººã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—モードã«ç§»è¡Œã—ã€Windows ã«å¯¾ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’è¡Œã†æ—¨ã‚’応答ã—ã¾ã™ã€‚ã“ã‚Œã¯ã€ãƒªãƒ¢ãƒ¼ãƒˆã‹ã‚‰ SoftEther VPN ソフトウェアを管ç†ã™ã‚‹éš›ã«ãƒªãƒ¢ãƒ¼ãƒˆç®¡ç†é€šä¿¡ãŒåˆ‡æ–­ã•ã‚Œã€ãƒ‡ãƒƒãƒ‰ãƒ­ãƒƒã‚¯ãŒç™ºç”Ÿã—ã¦ã—ã¾ã†ã“ã¨ã‚’防止ã™ã‚‹ãŸã‚ã®æŽªç½®ã§ã™ã€‚
+
+
+2.10. Windows Firewall ã¸ã®ç™»éŒ²
+SoftEther VPN ソフトウェアã¯ã€Windows Firewall ã«å¯¾ã—㦠SoftEther VPN ソフトウェアを安全ãªãƒ—ログラムã¨ã—ã¦è‡ªå‹•çš„ã«ç™»éŒ²ã—ã¾ã™ã€‚ã“ã®ç™»éŒ²ã¯ã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å¾Œã‚‚残存ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚登録を解除ã—ãŸã„å ´åˆã¯ã€Windows ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ãƒ‘ãƒãƒ«ã‚’用ã„ã¦æ‰‹å‹•ã§è¨­å®šã—ã¦ãã ã•ã„。
+
+3. インターãƒãƒƒãƒˆã‚µãƒ¼ãƒ“スã«ã¤ã„ã¦
+3.1. ソフトイーサ社ãŒæä¾›ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã‚µãƒ¼ãƒ“スã®å†…容
+ソフトイーサ社ã¯ã€ã€Œãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNSã€ã€ã€ŒNAT トラãƒãƒ¼ã‚µãƒ«ã€ãŠã‚ˆã³ã€ŒVPN Azureã€ã‚µãƒ¼ãƒ“スを無償ã§æä¾›ã—ã¾ã™ã€‚ã“れらã®ã‚µãƒ¼ãƒ“スã«ã¯ SoftEther VPN ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢å†…ã®å®Ÿè£…を通ã˜ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆçµŒç”±ã§ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“れらã®ã‚µãƒ¼ãƒ“スã¯ä»Šå¾Œå…¬é–‹ã•ã‚Œã‚‹äºˆå®šã®ã‚ªãƒ¼ãƒ—ンソース版「SoftEther VPNã€ã‹ã‚‰ã‚‚利用å¯èƒ½ã«ãªã‚‹äºˆå®šã§ã™ã€‚
+
+3.2. é€ä¿¡ã•ã‚Œã‚‹æƒ…å ±ã¨ãƒ—ライãƒã‚·ãƒ¼ã®ä¿è­·
+SoftEther VPN ソフトウェアã¯ã€ä¸Šè¨˜ã®ã‚µãƒ¼ãƒ“スを利用ã™ã‚‹ãŸã‚ã«ã€ã‚³ãƒ³ãƒ”ュータ㮠IP アドレスã€ãƒ›ã‚¹ãƒˆåã€VPN ソフトウェアã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報をソフトイーサ社ã®ç®¡ç†ã™ã‚‹ã‚¯ãƒ©ã‚¦ãƒ‰ã‚µãƒ¼ãƒ“ス上ã«é€ä¿¡ã—ã¾ã™ã€‚ã“れらã®æƒ…å ±ã¯ä¸Šè¨˜ã‚µãƒ¼ãƒ“スを実ç¾ã™ã‚‹ãŸã‚ã«æœ€ä½Žé™å¿…è¦ãªã‚‚ã®ã§ã™ã€‚一切ã®å€‹äººæƒ…å ±ã¯é€ä¿¡ã•ã‚Œã¾ã›ã‚“。ソフトイーサ社ã¯ã‚¯ãƒ©ã‚¦ãƒ‰ã‚µãƒ¼ãƒ“ス上ã«è“„ç©ã•ã‚ŒãŸä¸Šè¨˜ã® IP アドレス等ã®æƒ…報を最低 90 日間ログã«è¨˜éŒ²ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã¯ã‚µãƒ¼ãƒ“スã®åˆ©ç”¨ã«æŠ€è¡“çš„ãªå•é¡ŒãŒç™ºç”Ÿã—ãŸå ´åˆã®åŽŸå› ç©¶æ˜Žã®ãŸã‚ã«åˆ©ç”¨ã•ã‚Œã¾ã™ã€‚ソフトイーサ社ã¯å½“該ログ情報を日本国ã®è£åˆ¤æ‰€ã¾ãŸã¯æœæŸ»æ©Ÿé–¢ã«ã‚ˆã‚‹å‘½ä»¤ã«å¾“ã†ãŸã‚ã«ã“れらã®æ©Ÿé–¢ã®å…¬å‹™å“¡ (日本国ã®å…¬å‹™å“¡ã¯æ—¥æœ¬å›½ã®æ³•å¾‹ã«ã‚ˆã‚Šå®ˆç§˜ç¾©å‹™ã‚’è² ã‚ã•ã‚Œã¦ã„ã¾ã™) ã«é–‹ç¤ºã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€IP アドレスãªã©ã®æƒ…å ±ã¯çµ±è¨ˆå‡¦ç†ã•ã‚Œã€ãã®çµ±è¨ˆçµæžœã¯å€‹åˆ¥ã®å…·ä½“的㪠IP アドレスãŒåˆ¤åˆ¥ã§ããªã„よã†ã«ã•ã‚ŒãŸä¸Šã§ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã§ç ”究æˆæžœã¨ã—ã¦å…¬è¡¨ã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
+
+3.3. VPN Azure を経由ã—ãŸé€šä¿¡ãƒ‡ãƒ¼ã‚¿
+ãŠå®¢æ§˜ãŒ VPN Azure クラウドサービスを経由ã—㦠VPN 通信を行ã†å ´åˆã€3.2 ã®è¦å®šã«ã‹ã‹ã‚らãšã€ãŠå®¢æ§˜ã®å®Ÿéš›ã®é€šä¿¡ãƒšã‚¤ãƒ­ãƒ¼ãƒ‰ãŒ VPN Azure クラウドサービスを構æˆã™ã‚‹ã‚µãƒ¼ãƒãƒ¼ä¸Šã®ãƒ¡ãƒ¢ãƒªã«ã”ã短ã„時間蓄ç©ã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ã“れ㯠VPN Azure サービスをæä¾›ã™ã‚‹ãŸã‚ã«å½“然ã«å¿…è¦ãªã“ã¨ã§ã‚ã‚Šã¾ã™ãŒã€é€šä¿¡å†…容ã¯ãƒ‡ã‚£ã‚¹ã‚¯ãªã©ã®å›ºå®šé ˜åŸŸã«è¨˜éŒ²ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。ãŸã ã—ã€æ—¥æœ¬å›½ã®ã€ŒçŠ¯ç½ªæœæŸ»ã®ãŸã‚ã®é€šä¿¡å‚å—ã«é–¢ã™ã‚‹æ³•å¾‹ (å¹³æˆ 11 å¹´ 8 月 18 日法律第 137 å·) ã€ãŒå®šã‚ã‚‹è£åˆ¤å®˜ã®ä»¤çŠ¶ã‚’æºè¡Œã—ãŸæœæŸ»å®˜ã‹ã‚‰ã®è¦è«‹ãŒã‚ã£ãŸå ´åˆã¯å½“該通信ãŒæ—¥æœ¬å›½æ”¿åºœã®å…¬å‹™å“¡ (日本国ã®å…¬å‹™å“¡ã¯æ—¥æœ¬å›½ã®æ³•å¾‹ã«ã‚ˆã‚Šå®ˆç§˜ç¾©å‹™ã‚’è² ã‚ã•ã‚Œã¦ã„ã¾ã™) ã«ã‚ˆã£ã¦å‚å—ã•ã‚Œè¨˜éŒ²ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ã“ã®è¦å®šã¯ã€VPN Azure サービスã®ã‚µãƒ¼ãƒãƒ¼ãŒç‰©ç†çš„ã«æ—¥æœ¬å›½ã«å­˜åœ¨ã—ã¦ã„ã‚‹å ´åˆã«ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚
+
+3.4. 電気通信事業法ã®é©ç”¨
+ソフトイーサ社ã¯ä¸Šè¨˜ã®ã‚µãƒ¼ãƒ“スを日本国内ã§é‹ç”¨ã™ã‚‹å ´åˆã«ãŠã„ã¦é›»æ°—通信事業法ã®è¦å®šã‚’å—ã‘ã‚‹ã¹ãå ´åˆã«ã¤ã„ã¦ã¯é›»æ°—通信事業法ã®è¦å®šã«å¾“ã„ã€ç·å‹™å¤§è‡£ã«å±Šå‡ºã¾ãŸã¯ç”³è«‹ã‚’è¡Œã£ã¦ãŠã‚Šã¾ã™ã€‚
+
+3.5. ç„¡å„Ÿã§å­¦è¡“実験目的ã®ã‚µãƒ¼ãƒ“ス
+ソフトイーサã¯ã€Œãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ DNSã€ã€ã€ŒNAT トラãƒãƒ¼ã‚µãƒ«ã€ãŠã‚ˆã³ã€ŒVPN Azureã€ã‚’学術実験目的ã§ç ”究開発ã—é‹å–¶ã—ã¦ã„ã¾ã™ã€‚ãã®ãŸã‚ã€ã“れらã®ã‚µãƒ¼ãƒ“スã¯ã™ã¹ã¦ç„¡æ–™ã§ã”利用ã„ãŸã ã‘ã¾ã™ã€‚ã“れらã®ã‚µãƒ¼ãƒ“スã¯ã€ŒSoftEther VPN ソフトウェア製å“ã€ã®ä¸€éƒ¨ã§ã¯ãªãã€ä»˜éšã™ã‚‹ã‚‚ã®ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。ã“れらã®ã‚µãƒ¼ãƒ“スã¯ä¸€åˆ‡ã®ä¿è¨¼ãŒãªã„状態ã§æä¾›ã•ã‚Œã‚‹ã‚‚ã®ã§ã™ã€‚実験ã®ä¼‘æ­¢ã€ä¸­æ­¢ã‚„実験中ã®æŠ€è¡“çš„å•é¡Œã®ç™ºç”Ÿã«ã‚ˆã£ã¦ã‚µãƒ¼ãƒ“スãŒä¸­æ–­ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ãã®å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚µãƒ¼ãƒ“スを利用ã§ããªããªã‚Šã¾ã™ã€‚ユーザーã¯ã“ã®ã‚ˆã†ãªãƒªã‚¹ã‚¯ãŒã‚ã‚‹ã“ã¨ã€ãŠã‚ˆã³ãã®ãƒªã‚¹ã‚¯ã‚’ユーザー自身ãŒè² æ‹…ã™ã‚‹ã“ã¨ã‚’承諾ã„ãŸã ã„ãŸä¸Šã§ã“れらã®ã‚µãƒ¼ãƒ“スをã”利用ãã ã•ã„。ソフトイーサ社ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã“れらã®ã‚µãƒ¼ãƒ“スを利用ã—ãŸçµæžœã€ã¾ãŸã¯åˆ©ç”¨ã§ããªã‹ã£ãŸçµæžœã«ã¤ã„ã¦ä¸€åˆ‡ã®è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。仮ã«ãŠå®¢æ§˜ãŒ SoftEther VPN ソフトウェアã®å•†ç”¨è£½å“を購入ã•ã‚Œã€SoftEther VPN ソフトウェアã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ–™é‡‘ã‚’ãŠå®¢æ§˜ãŒã™ã§ã«ãŠæ”¯æ‰•ã„ã„ãŸã ã„ã¦ã„ã‚‹å ´åˆã§ã‚ã£ã¦ã‚‚ã€å½“該料金ã«ã¯ã“れらã®ã‚µãƒ¼ãƒ“スã®å¯¾ä¾¡ã¯å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“。ã“れらã®ã‚µãƒ¼ãƒ“スãŒä¸­æ–­ã—ãŸã‚Šåˆ©ç”¨ä¸èƒ½ã«ãªã£ãŸã‚Šã—ãŸå ´åˆã§ã‚ã£ã¦ã‚‚ã€SoftEther VPN ソフトウェアã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æ–™é‡‘ã¯ä¸€åˆ‡è¿”金ã•ã‚Œãšã€ãã®ä»–ã®æ害賠償もæä¾›ã•ã‚Œã¾ã›ã‚“。
+
+3.6. DNS プロキシ
+ã„ãã¤ã‹ã®åœ°åŸŸã§ã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã‚’利用ã™ã‚‹éš›ã€DNS クエリã«ã‚ˆã‚‹ IP アドレスã®å–å¾—ãŒå›žç·šã®é€šä¿¡ä¸è‰¯ã«ã‚ˆã‚Šã—ã°ã—ã°èª¤ã£ãŸå€¤ã‚’è¿”ã™ã‚ˆã†ã§ã™ã€‚SoftEther VPN Server, Client ã¾ãŸã¯ Bridge を使用ã—ã¦ã„ã‚‹å ´åˆã§ã€æœ¬æ¥ã® DNS サーãƒãƒ¼ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒã§ããªã„ã€ã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã®é€”中ã®çµŒè·¯ã® DNS サーãƒãƒ¼ãŒå‹•ä½œä¸è‰¯ã‚’èµ·ã“ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹å ´åˆãŒæ¤œå‡ºã•ã‚ŒãŸã¨ãã¯ã€DNS クエリã¯ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µãŒé‹å–¶ã™ã‚‹ DNS プロキシサーãƒãƒ¼ã«è»¢é€ã•ã‚Œã¾ã™ã€‚DNS プロキシサーãƒãƒ¼ã¯æœ¬æ¥ã® DNS サーãƒãƒ¼ã«å¯¾ã—ã¦ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¡Œã„ã€æ­£ç¢ºãª IP アドレスをå–å¾—ã—ã¦ãã® IP アドレスを呼出ã—å…ƒã«è¿”ä¿¡ã—ã¾ã™ã€‚
+
+
+4. ãã®ä»–ã®æ³¨æ„事項
+4.1. ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹æ‰¿è«¾ã®å¿…è¦æ€§
+SoftEther VPN ã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹ç‰¹åˆ¥ãªè¨­å®šã‚’å¿…è¦ã¨ã›ãšã«å‹•ä½œã™ã‚‹ã‚ˆã†ã«ãƒ‘ワフルãªæ©Ÿèƒ½ãŒå®Ÿè£…ã•ã‚Œã¦ã„ã¾ã™ã€‚ãŸã¨ãˆã°ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã®è¨­å®šã®å¤‰æ›´ã‚’ä¾é ¼ã—ãªãã¦ã‚‚ VPN 通信を行ã†ã“ã¨ãŒã§ãã¾ã™ã€‚SoftEther VPN ã®ã“ã†ã—ãŸç‰¹å¾´ã¯ã€ã‚ãã¾ã§ã‚‚技術的ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«ã‚ˆã‚‹æ‰‹é–“やコスト削減ã™ã‚‹ãŸã‚ã€ã¾ãŸã¯ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«è¨­å®šã®å¤‰æ›´ã«ä¼´ã†è¨­å®šãƒŸã‚¹ãªã©ã®å±é™ºã‚’防止ã™ã‚‹ãŸã‚ã®ã‚‚ã®ã§ã™ã€‚ä¼æ¥­ã«æ‰€å±žã™ã‚‹ç¤¾å“¡ã¯ã€SoftEther VPN ã‚’ä¼æ¥­ã®ç®¡ç†ã™ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¾ãŸã¯ä½¿ç”¨ã™ã‚‹å ´åˆã«ã‚ãŸã£ã¦ã¯ã€å¿…ãšäº‹å‰ã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã®è¨±è«¾ã‚’å¾—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。もã—ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ãŒãã®ã‚ˆã†ãªæ‰¿è«¾ã‚’æä¾›ã—ãªã„å ´åˆã¯ã€ä»£ã‚ã‚Šã«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…よりもより上ä½ã®æ¨©é™ã‚’æŒã£ãŸçµŒå–¶è€…ã‹ã‚‰è¨±è«¾ã‚’å¾—ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。ã“れらã®æ­£å½“ãªè¨±è«¾ãŒãªã„状態㧠SoftEther VPN を使用ã™ã‚‹ã“ã¨ã¯ã€ãŠå®¢æ§˜ã«ã¨ã£ã¦ä¸åˆ©ç›Šãªçµæžœã¨ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ソフトイーサ社㯠SoftEther VPN ã®ä½¿ç”¨ã«ã‚ˆã£ã¦ãŠå®¢æ§˜ã«ç”Ÿã˜ãŸä¸€åˆ‡ã®è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+
+4.2. å„地域ã«ãŠã‘る法律ã®éµå®ˆ
+VPN 通信ã®ã‚ˆã†ãªæš—å·åŒ–通信ãŒæ³•å¾‹ã§ç¦æ­¢ã•ã‚Œã¦ã„る国・地域ã§ã¯ã€SoftEther VPN を使用ã™ã‚‹å ´åˆã¯å¿…ãšæš—å·åŒ–機能をオフã«ã—ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。ã“ã®ä»–ã€ä¸€éƒ¨ã®å›½ãƒ»åœ°åŸŸã§ã¯ç‰¹å®šã®æ–¹æ³•ã§ã® SoftEther VPN ã®åˆ©ç”¨ãŒæ³•å¾‹ã«ã‚ˆã£ã¦ç¦æ­¢ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ソフトイーサ社ã¯æ—¥æœ¬å›½ã«æ‰€åœ¨ã™ã‚‹æ³•äººã§ã™ã®ã§ã€ä»–ã®å›½ãƒ»åœ°åŸŸã«åˆ¶å®šã•ã‚Œã¦ã„る法令ã«ã¤ã„ã¦ã¯ä¸€åˆ‡é–¢çŸ¥ã—ã¦ãŠã‚Šã¾ã›ã‚“。ãŸã¨ãˆã°ã€SoftEther VPN ã®ä¸€éƒ¨ã®æ©Ÿèƒ½ãŒç‰¹å®šã®å›½ãƒ»åœ°åŸŸã§ã®ã¿æœ‰åŠ¹ãªç‰¹è¨±æ¨©ã‚’侵害ã—ã¦ã„ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚ソフトイーサ社ã¯ãã®å›½ãƒ»åœ°åŸŸã«é–¢ã—ã¦ç‰¹æ®µã®é–¢å¿ƒã¯ã‚ã‚Šã¾ã›ã‚“。ã—ãŸãŒã£ã¦ã€SoftEther VPN ã®æ©Ÿèƒ½ãŒãŠå®¢æ§˜ã®å±…ä½ã—ã¦ã„る国・地域ã«ãŠã„ã¦æ³•çš„ã«åˆ©ç”¨å¯èƒ½ã§ã‚ã‚‹ã‹ã©ã†ã‹ã¯ã€ãŠå®¢æ§˜ã”自身ã«ã‚ˆã£ã¦äº‹å‰ã«å分検証ã®ä¸Šã”利用ãã ã•ã„。ãã‚‚ãも世界ã«ã¯ 200 カ国近ãã®å›½ãŒå­˜åœ¨ã—ã¦ãŠã‚Šã€ãã‚Œãžã‚Œã®å›½ã«ãŠã‘る法律ã¯äº’ã„ã«ç•°ãªã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®å›½ã®æ³•å¾‹ã‚’調査ã—ãŸä¸Šã§ãれらã™ã¹ã¦ã«é©åˆã™ã‚‹ã“ã¨ã‚’ä¿è¨¼ã—ãŸã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’リリースã™ã‚‹ã“ã¨ã¯äº‹å®Ÿä¸Šä¸å¯èƒ½ã§ã™ã€‚ソフトイーサ社ã¯æ—¥æœ¬å›½ã®æ³•å¾‹ã®ã¿ã‚’調査ã—ã€æ—¥æœ¬å›½ã®æ³•å¾‹ä¸‹ã§ãŠã„ã¦é©æ³•ã«åˆ©ç”¨å¯èƒ½ãªã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’æä¾›ã™ã‚‹ã“ã¨ã®ã¿ã‚’目的ã«ç ”究開発を行ã£ã¦ãŠã‚Šã¾ã™ã€‚万一ãŠå®¢æ§˜ãŒ SoftEther VPN ã®æ©Ÿèƒ½ã‚’ãŠå®¢æ§˜ã®å±…ä½ã—ã¦ã„る国・地域ã®é ˜åŸŸå†…ã§åˆ©ç”¨ã•ã‚ŒãŸã“ã¨ã«ã‚ˆã£ã¦å›½å®¶æ¨©åŠ›ã«ã‚ˆã‚Šæ³•çš„ãªãƒšãƒŠãƒ«ãƒ†ã‚£ã‚’科ã›ã‚‰ã‚Œã‚‹ãªã©ã®æ害ãŒç™ºç”Ÿã—ãŸå ´åˆã§ã‚ã£ã¦ã‚‚ã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µç¤¾ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+
+
+5. VPN Gate 学術実験プロジェクト
+(ã“ã®ç« ã¯ VPN Gate 学術実験プロジェクトã«é–¢ã™ã‚‹æ©Ÿèƒ½æ‹¡å¼µãƒ—ラグインãŒå«ã¾ã‚Œã¦ã„ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® SoftEther VPN ã«ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚商用版㮠SoftEther VPN ソフトウェアã«ã¯ VPN Gate 機能拡張プラグインã¯å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“ã®ã§ã€ã“ã®ç« ã®å†…容ã¯é–¢ä¿‚ã‚ã‚Šã¾ã›ã‚“。)
+5.1. VPN Gate 学術実験プロジェクトã«ã¤ã„ã¦
+VPN Gate 学術実験プロジェクトã¯ã€æ—¥æœ¬ã«æ‰€åœ¨ã™ã‚‹ç­‘波大学大学院ã«ãŠã‘る学術的ãªç ”究を目的ã¨ã—ã¦å®Ÿæ–½ã•ã‚Œã¦ã„るオンラインサービスã§ã™ã€‚本研究ã¯ã€ã‚°ãƒ­ãƒ¼ãƒãƒ«ãªåˆ†æ•£åž‹å…¬é–‹ VPN 中継サーãƒãƒ¼ã«é–¢ã™ã‚‹çŸ¥è¦‹ã‚’å¾—ã‚‹ã“ã¨ã‚’目的ã¨ã—ã¦ã„ã¾ã™ã€‚詳ã—ã㯠http://www.vpngate.net/ ã‚’ã”å‚ç…§ãã ã•ã„。
+
+5.2. VPN Gate サービスã«ã¤ã„ã¦
+SoftEther VPN Server ãŠã‚ˆã³ SoftEther VPN Client ã«ã¯ã€ŒVPN Gate サービスã€ã¨å‘¼ã°ã‚Œã‚‹ãƒ—ログラムãŒåŒæ¢±ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ãŸã ã—ã€VPN Gate サービスã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ç„¡åŠ¹ã¨ãªã£ã¦ã„ã¾ã™ã€‚
+VPN Gate サービスã¯ã€SoftEther VPN Server ã¾ãŸã¯ SoftEther VPN Client をインストールã™ã‚‹ã‚³ãƒ³ãƒ”ュータã®æ‰€æœ‰è€…ãŒã€è‡ªã‚‰ã®æ„æ€ã«åŸºã¥ãã€VPN Gate 学術実験ã«å‚加ã•ã‚Œã‚‹å ´åˆã«ã®ã¿æœ‰åŠ¹ã«ã—ã¦ãã ã•ã„。VPN Gate サービスを有効ã«ã™ã‚‹ã¨ã€ã‚³ãƒ³ãƒ”ュータ㯠VPN Gate 学術実験サービスã«ãŠã‘るグローãƒãƒ«ãªåˆ†æ•£åž‹å…¬é–‹ VPN 中継サーãƒãƒ¼ã¨ã—ã¦å‹•ä½œã‚’開始ã—ã¾ã™ã€‚ãã—ã¦ã€ã‚³ãƒ³ãƒ”ュータ㮠IP アドレスやホストåãªã©ã®æƒ…å ±ãŒç­‘波大学内ã§é‹ç”¨ã•ã‚Œã¦ã„ã‚‹ VPN Gate 学術実験サービスã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ç™»éŒ²ã•ã‚Œã€å…¬è¡†ã®é–²è¦§ã«ä¾›ã•ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ä¸–界中ã«ã‚ã‚‹ VPN Gate Client ã¨å‘¼ã°ã‚Œã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯å½“該 VPN Gate サービスãŒç¨¼åƒã—ã¦ã„ã‚‹ VPN サーãƒãƒ¼ã‚³ãƒ³ãƒ”ュータã«å¯¾ã—㦠VPN 接続を行ã†ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚VPN 接続ãŒç¶™ç¶šã—ã¦ã„る期間中ã¯ã€VPN Gate Client ã®ã‚³ãƒ³ãƒ”ュータã¯ã™ã¹ã¦ã®é€šä¿¡ã‚’ VPN Gate サービスを経由ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã¨ã®é–“ã§è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®éš›ã¯ã€VPN Gate サービスを動作ã•ã›ã¦ã„るコンピュータã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã«ãŠã‘るグローãƒãƒ« IP アドレスãŒã€å½“該通信ã®ç™ºä¿¡å…ƒã® IP アドレスã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+VPN Gate サービスã¯ã€VPN Gate 学術実験サービスã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦ã€5.5 ã®é‹å–¶è€…情報ã€ãƒ­ã‚°è¨­å®šã€èµ·å‹•æ™‚é–“ã€OS ã®ç¨®é¡žã€ãƒ—ロトコルã®ç¨®é¡žã€ãƒãƒ¼ãƒˆç•ªå·ã€å›žç·šå“質情報ã€çµ±è¨ˆæƒ…å ±ã€VPN Gate クライアントã‹ã‚‰ã®æŽ¥ç¶šãƒ­ã‚° (日時ã€IP アドレスã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã€ID) ãŠã‚ˆã³ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報をé€ä¿¡ã—ã¾ã™ã€‚ã“れらã®æƒ…å ±ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªä¸Šã§å…¬è¡†ã®é–²è¦§ã«ä¾›ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€VPN Gate サービス㯠5.9 ã§èª¬æ˜Žã•ã‚Œã¦ã„る機能ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã®ãŸã‚ã®ã‚­ãƒ¼ã‚’ VPN Gate 学術実験サービスã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰å—ä¿¡ã—ã¾ã™ã€‚
+
+5.3. VPN Gate サービスã®å‹•ä½œã®è©³ç´°
+デフォルトã§ç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã‚‹ VPN Gate サービスをユーザーã®æ“作ã«ã‚ˆã‚Šæœ‰åŠ¹ã«ã™ã‚‹ã¨ã€SoftEther VPN Server 内㫠"VPNGATE" ã¨ã„ã†å称ã®ä»®æƒ³ HUB ãŒä½œæˆã•ã‚Œã¾ã™ã€‚SoftEter VPN Client 上ã«ãŠã„㦠VPN Gate サービスを有効ã«ã—よã†ã¨ã™ã‚‹ã¨ã€ã¾ãš SoftEther VPN Client 内ã®åŒä¸€ãƒ—ロセス上ã§ç°¡æ˜“çš„ã«å‹•ä½œã™ã‚‹ SoftEther VPN Server ã¨åŒç­‰ã®ãƒ—ログラムãŒèµ·å‹•ã—ã€ãã®ä¸­ã§ "VPNGATE" ã¨ã„ã†å称ã®ä»®æƒ³ HUB ãŒä½œæˆã•ã‚Œã¾ã™ã€‚当該仮想 HUB ã«ã¯ "VPN" ã¨ã„ã†åå‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒä½œæˆã•ã‚Œã€åŒ¿åã§ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®èª°ã§ã‚‚ãŒå½“該仮想 HUB ã« VPN 接続を行ã†ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ã„ã£ãŸã‚“ "VPNGATE" 仮想 HUB ã«æŽ¥ç¶šã—㟠VPN クライアントコンピュータãŒé–‹å§‹ã—ãŸã™ã¹ã¦ã®é€šä¿¡ã¯ "VPNGATE" 仮想 HUB を通éŽã—ã€SoftEther VPN Server (ã¾ãŸã¯ SoftEther VPN Client) ãŒå‹•ä½œã—ã¦ã„るコンピュータã®ç‰©ç†çš„ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã‚’経由ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«å¯¾ã—ã¦ä¼é€ã•ã‚Œã¾ã™ã€‚ãã®ãŸã‚ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®å®›å…ˆãƒ›ã‚¹ãƒˆã¯ã€ã‚ãŸã‹ã‚‚当該通信㌠SoftEther VPN Server ãŒå‹•ä½œã—ã¦ã„るコンピュータã‹ã‚‰ç™ºä¿¡ã•ã‚ŒãŸã‚‚ã®ã§ã‚ã‚‹ã‹ã®ã‚ˆã†ã«è­˜åˆ¥ã™ã‚‹ã“ã¨ã¨ãªã‚Šã¾ã™ã€‚ãŸã ã—ã€å®›å…ˆãŒ 192.168.0.0/255.255.0.0, 172.16.0.0/255.240.0.0 ãŠã‚ˆã³ 10.0.0.0/255.0.0.0 å®›ã®ãƒ‘ケットã¯ãƒ—ライベートãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ (ãŸã¨ãˆã°ç¤¾å†… LAN ãªã©) ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ã‚‚ã®ã¨è¦‹ãªã•ã‚Œã€"VPNGATE" 仮想 HUB を経由ã—ã¦ä¼é€ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。VPN Gate サービスを社内 LAN ãªã©ã«ã‚るコンピュータã§å‹•ä½œã•ã›ã¦ã‚‚ã€VPN Gate ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¯¾ã—ã¦ç¤¾å†… LAN 上ã®ä»–ã®ã‚³ãƒ³ãƒ”ュータã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚’許ã™ã“ã¨ã«ã¯ãªã‚‰ãªã„ãŸã‚安全ã§ã™ã€‚VPN Gate サービスã¯ã¾ãŸã€VPN Gate ディレクトリサーãƒãƒ¼ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã®ä¸­ç¶™ã‚‚実施ã—ã¾ã™ã€‚
+VPN Gate サービスã¯ã€ãƒ•ã‚¡ã‚¤ã‚¢ã‚¦ã‚©ãƒ¼ãƒ«ã‚„ NAT ãªã©ã¨å…±ã«è‰¯å¥½ã«å‹•ä½œã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ã™ã‚‹ãŸã‚ã€1.2 ã§è§£èª¬ã•ã‚Œã¦ã„ã‚‹ NAT トラãƒãƒ¼ã‚µãƒ«æ©Ÿèƒ½ã‚’用ã„㦠UDP ãƒãƒ¼ãƒˆã‚’é–‹ãã¾ã™ã€‚ã¾ãŸã€ã„ãã¤ã‹ã® TCP ãƒãƒ¼ãƒˆã‚’ Listen 状態ã¨ã—ã€ã„ãã¤ã‹ã® TCP ãƒãƒ¼ãƒˆãŠã‚ˆã³ UDP ãƒãƒ¼ãƒˆã«ã¤ã„㦠Universal Plug and Play (UPnP) プロトコルを用ã„ã¦å®šæœŸçš„ã«ãƒ­ãƒ¼ã‚«ãƒ«ã®ãƒ«ãƒ¼ã‚¿ã«å¯¾ã—ã¦ãƒãƒ¼ãƒˆé–‹æ”¾ã‚’è¦æ±‚ã—ã¾ã™ã€‚ルータã®æŒ™å‹•ã«ã‚ˆã£ã¦ã¯ã€ãƒãƒ¼ãƒˆã¯ VPN Gate サービスã®åœæ­¢å¾Œã‚‚開放ã•ã‚Œç¶šã‘ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã®ã§ã€UPnP ãƒãƒ¼ãƒˆã‚’é–‰ã˜ãŸã„å ´åˆã¯æ‰‹å‹•ã§é–‰ã˜ã¦ãã ã•ã„。
+VPN Gate サービスã¯ã¾ãŸã€www.vpngate.net ã®ãƒŸãƒ©ãƒ¼ã‚µã‚¤ãƒˆæ©Ÿèƒ½ã‚‚æä¾›ã—ã¾ã™ã€‚ã“ã‚Œã¯ã€VPN Gate Web サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¯¾ã—㦠www.vpngate.net ã®ã‚µã‚¤ãƒˆã®ã‚³ãƒ”ーã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ã€ç°¡æ˜“的㪠HTTP サーãƒãƒ¼ã‚’経由ã—ã¦ãƒ›ã‚¹ãƒˆã™ã‚‹ä»•çµ„ã¿ã§ã™ã€‚簡易的㪠HTTP サーãƒãƒ¼æ©Ÿèƒ½ã¯ VPN Gate サービスã®ãƒ—ログラムã®ä¸€éƒ¨ã¨ã—ã¦ç¨¼åƒã—ã€è‡ªåˆ†è‡ªèº«ã‚’ www.vpngate.net ã®ãƒŸãƒ©ãƒ¼ã‚µã‚¤ãƒˆä¸€è¦§ãƒšãƒ¼ã‚¸ã«è‡ªå‹•çš„ã«ç™»éŒ²ã—ã¾ã™ã€‚ãŸã ã—ã€www.vpngate.net 以外ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã™ã‚‹ä¸­ç¶™é€šä¿¡ã¯ã‚µãƒãƒ¼ãƒˆã—ã¾ã›ã‚“。
+
+5.4. VPN Gate サービスã«ãŠã‘るインターãƒãƒƒãƒˆã¨ã®é–“ã®é€šä¿¡
+VPN Gate サービスã¯ã€Œ2.8. 仮想 NAT 機能ã€ã§èª¬æ˜Žã•ã‚Œã¦ã„る機能を用ã„ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é€šä¿¡ã‚’インターãƒãƒƒãƒˆã«å¯¾ã—ã¦ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã—ã¾ã™ã€‚ã¾ãŸã€VPN Gate サービスã¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆå›žç·šã®å“質を調査ã™ã‚‹ãŸã‚ã€ä¸€å®šæ™‚é–“ã”ã¨ã«ç­‘波大学ã«è¨­ç½®ã•ã‚Œã¦ã„ã‚‹ Ping サーãƒãƒ¼ãŠã‚ˆã³ Google 社ã«è¨­ç½®ã•ã‚Œã¦ã„ã‚‹ Public DNS Server (IP アドレス: 8.8.8.8) ã«å¯¾ã—㦠Ping パケットをé€ä¿¡ã—ã¾ã™ã€‚ã¾ãŸã€ç­‘波大学ã«è¨­ç½®ã•ã‚Œã¦ã„る通信速度測定サーãƒãƒ¼ã«å¯¾ã—㦠TCP ã§ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’確立ã—ã€æ•°å秒程度ã®é€šä¿¡ã‚’è¡Œã„ã¾ã™ã€‚ã“れらã®å“質データã¯æ¸¬å®šå¾Œã«è‡ªå‹•çš„ã« VPN Gate 学術実験プロジェクトã®ä¸­å¤®ã‚µãƒ¼ãƒãƒ¼ã«ä¼é€ã•ã‚Œä¿å­˜ã•ã‚Œã¾ã™ã€‚ãã®çµæžœã¯å…¬è¡†ã®é–²è¦§ã«ä¾›ã•ã‚Œã¾ã™ã€‚ã“れらã®å®šæœŸçš„ãªé€šä¿¡ã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«å½±éŸ¿ã‚’ã§ãã‚‹ã ã‘与ãˆãªã„よã†ã«ã™ã‚‹ãŸã‚最å°é‡ã«èª¿æ•´ã•ã‚Œã¦ã„ã¾ã™ãŒã€å›žç·šã‚’圧迫ã™ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
+
+5.5. VPN Gate サービスã®é‹å–¶è€…情報
+VPN Gate 学術実験プロジェクトã«å‚加ã—ãŸã‚³ãƒ³ãƒ”ュータ上ã§å‹•ä½œã™ã‚‹ VPN Gate サービスã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã§å…¬è¡†ã«å¯¾ã—ã¦ã‚µãƒ¼ãƒ“スをæä¾›ã™ã‚‹åˆ†æ•£ãƒŽãƒ¼ãƒ‰ã®ä¸€å“¡ã¨ãªã‚Šã¾ã™ã€‚ã—ãŸãŒã£ã¦ã€å½“該コンピュータã®ç®¡ç†è€…ã¯ã‚µãƒ¼ãƒãƒ¼ã®é‹å–¶è€…情報をé©åˆ‡ã«ç”³å‘Šã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。é‹å–¶è€…情報ã«ã¯ã€é‹å–¶è€…æ°åãŠã‚ˆã³ä¸æ­£åˆ©ç”¨ç­‰ãŒã‚ã£ãŸå ´åˆã®é€£çµ¡å…ˆãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å«ã¿ã¾ã™ã€‚é‹å–¶è€…情報㯠VPN Gate サービスã®è¨­å®šç”»é¢ã‹ã‚‰ã„ã¤ã§ã‚‚入力ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚入力ã•ã‚ŒãŸé‹å–¶è€…情報ã¯è‡ªå‹•çš„ã« VPN Gate 学術実験プロジェクトã®ä¸­å¤®ã‚µãƒ¼ãƒãƒ¼ã«ä¼é€ã•ã‚Œä¿å­˜ã•ã‚Œã¾ã™ã€‚ãã®çµæžœã¯å…¬è¡†ã®é–²è¦§ã«ä¾›ã•ã‚Œã¾ã™ã®ã§ã€å…¥åŠ›ã®éš›ã«ã¯å分注æ„ã—ã¦ãã ã•ã„。ãªãŠã€å…¥åŠ›ãŒãªã„å ´åˆã¯é‹å–¶è€…情報ã¨ã—ã¦ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚³ãƒ³ãƒ”ュータã®ãƒ›ã‚¹ãƒˆåã®å¾Œã« "'s owner" ã¨ã„ã†æ–‡å­—列を付加ã—ãŸæ–‡å­—ãŒä½¿ç”¨ã•ã‚Œã¾ã™ã€‚
+
+5.6. VPN Gate サービスをé‹å–¶ã™ã‚‹å ´åˆã®æ³•ä»¤ã®éµå®ˆ
+ユーザー㌠VPN Gate サービスをé‹å–¶ã™ã‚‹å ´åˆã€å›½ãƒ»åœ°åŸŸã«ã‚ˆã£ã¦ã¯ãã®ã‚ˆã†ãªã‚µãƒ¼ãƒ“スをé‹å–¶ã™ã‚‹ã“ã¨ã«ã¤ã„ã¦äºˆã‚行政機関ã«ã‚ˆã‚‹è¨±å¯ã‚’å¾—ã‚‹ã‹ã€ã¾ãŸã¯è¡Œæ”¿æ©Ÿé–¢ã«äº‹å‰ã«å±Šã‘出る必è¦ãŒã‚ã‚‹è¦å®šãŒã‚ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ãã®ã‚ˆã†ãªè¦å®šãŒå­˜åœ¨ã™ã‚‹å ´åˆã¯ã€VPN Gate サービスを有効ã«ã™ã‚‹å‰ã«å¿…ãšæ³•ä»¤ã«ã‚ˆã£ã¦è¦æ±‚ã•ã‚Œã¦ã„る手続ãを履行ã—ã¦ãã ã•ã„。本ソフトウェアã®é–‹ç™ºè€…ã¾ãŸã¯ VPN Gate 学術実験プロジェクトã®å®Ÿæ–½è€…ã¯ã€VPN Gate サービスを稼åƒã•ã›ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ³•ä»¤ã«ãŠã„ã¦è¦å®šã•ã‚Œã¦ã„る義務を履行ã—ãªã‹ã£ãŸã“ã¨ã«ã‚ˆã£ã¦ç”Ÿã˜ãŸæ³•çš„責任ã¾ãŸã¯æ害ã«ã¤ã„ã¦ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“ã®ã§ã”注æ„ãã ã•ã„。
+
+5.7. 通信ã®ç§˜å¯†ã®ä¿è­·
+多ãã®å›½ã®æ³•ä»¤ã«ãŠã„ã¦ã€VPN Gate サービスã®é‹å–¶è€…ã¯ã€VPN Gate サービスã®å†…部を通éŽã—ãŸç¬¬ä¸‰è€…ã®é€šä¿¡ã«ã¤ã„ã¦ãã®ç§˜å¯†ã‚’ä¿è­·ã™ã‚‹ã“ã¨ãŒè¦æ±‚ã•ã‚Œã‚‹ã“ã¨ã¨ãªã‚Šã¾ã™ã®ã§ã€ã”注æ„ãã ã•ã„。
+
+5.8. パケットログ
+VPN Gate サービスを経由ã—ã¦ä¼é€ã•ã‚Œã‚‹ä¸»è¦ãªé€šä¿¡ãƒ‘ケットã®é‡è¦ãªãƒ˜ãƒƒãƒ€éƒ¨åˆ†ã‚’記録ã™ã‚‹ã€Œãƒ‘ケットログã€æ©Ÿèƒ½ãŒ VPN Gate サービスã®ãƒ—ログラムã«å®Ÿè£…ã•ã‚Œã¦ã„ã¾ã™ã€‚パケットログã¯ã€VPN Gate サービスを経由ã—ã¦ç¬¬ä¸‰è€…ãŒé•æ³•ãªé€šä¿¡ã‚’è¡Œã£ãŸå ´åˆã«ã€ãã®äº‹å®Ÿã‚’記録ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½ã§ã™ã€‚パケットログ㨠VPN 接続ã®å—付ログをå‚ç…§ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€å½“該通信を行ã£ãŸè€…ã®åŽŸ IP アドレスを特定ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚ã“ã®ã‚ˆã†ãªèª¿æŸ»ãªã©ã®æ­£å½“ãªç›®çš„ã®ãŸã‚ã ã‘ã«ãƒ‘ケットログを使用ã—ã¦ãã ã•ã„。パケットログを正当ãªç›®çš„以外ã®ãŸã‚ã«é–²è¦§ã—ãŸã‚Šã€å†…容をæ¼æ´©ã—ãŸã‚Šã™ã‚‹ã“ã¨ã¯ã€5.7 ã®è¦å®šã«åã™ã‚‹ã“ã¨ã¨ãªã‚Šã¾ã™ã€‚
+
+5.9. パケットログã®è‡ªå‹•ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–機能
+VPN Gate 学術実験プロジェクトã¯æ—¥æœ¬å›½æ†²æ³•ãŠã‚ˆã³æ³•å¾‹ã«å¾“ã£ã¦é‹å–¶ã•ã‚Œã¦ã„ã¾ã™ã€‚日本国憲法や法令ã¯ã€é€šä¿¡ã®ç§˜å¯†ã«ã¤ã„ã¦éžå¸¸ã«åŽ³ã—ã„ä¿è­·ã‚’è¦æ±‚ã—ã¦ã„ã¾ã™ã€‚日本国ã«ãŠã‘るルールã«å¾“ã†ãŸã‚ã«ã€VPN Gate サービスã®ãƒ—ログラムã«ã¯ã€Œè‡ªå‹•ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã€æ©Ÿèƒ½ãŒæ­è¼‰ã•ã‚Œã¦ãŠã‚Šã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚
+デフォルトã§ã¯ã€VPN Gate サービスã®ç¾åœ¨ã®è¨­å®šã¯ã€2 週間以上ãŒçµŒéŽã—ãŸãƒ‘ケットログファイルを自動的ã«ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã—ã¦ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã™ã‚‹ã‚ˆã†ã«ãªã£ã¦ã„ã¾ã™ã€‚VPN Gate サービスを経由ã—ã¦é€šä¿¡ã‚’è¡Œã£ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é€šä¿¡ã®ç§˜å¯†ã‚’ä¿è­·ã™ã‚‹ãŸã‚ã€ä¸€æ—¦ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€VPN Gate サービスãŒå‹•ä½œã—ã¦ã„るコンピュータã®ç®¡ç†è€…ã§ã‚ã£ã¦ã‚‚閲覧ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ã“ã‚Œã«ã‚ˆã‚Š VPN Gate サービスを利用ã™ã‚‹ã‚¨ãƒ³ãƒ‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ライãƒã‚·ãƒ¼ãŒä¿ãŸã‚Œã¾ã™ã€‚
+パケットログファイルãŒç”Ÿæˆå¾Œ 2 週間以上経éŽã—ãŸå¾Œã§ã‚‚自動的ã«ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œãªã„よã†ã«ã™ã‚‹ãŸã‚ã«ã¯ã€VPN Gate サービスã®è¨­å®šã‚’変更ã—ã¦ãã ã•ã„。ã“ã®å ´åˆã¯ã€ãƒ‘ケットログファイルã¯æ’ä¹…çš„ã«ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã«å¹³æ–‡ã§æ®‹ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚ã—ãŸãŒã£ã¦ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é€šä¿¡ã®ç§˜å¯†ã‚’侵害ã—ãªã„よã†ã«å分ã”注æ„ãã ã•ã„。
+VPN Gate サービスを経由ã—ã¦ã‚¨ãƒ³ãƒ‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé•æ³•è¡Œç‚ºã‚’è¡Œã£ãŸéš›ãªã©ã€ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚ŒãŸãƒ‘ケットログファイルをデコードã—通信内容を復元ã™ã‚‹å¿…è¦ãŒç”Ÿã˜ãŸå ´åˆã¯ã€ç­‘波大学大学院 VPN Gate 学術実験プロジェクトã®é‹å–¶è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。連絡方法㯠http://www.vpngate.net/ ã«è¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚プロジェクトã®é‹å–¶è€…ã¯ã€æ—¢å­˜ã®æ³•ä»¤ã«å¾“ã„ã€è£åˆ¤æ‰€ãªã©ã®å¸æ³•æ©Ÿé–¢ã«ã‚ˆã‚‹è¦è«‹ãŠã‚ˆã³ã“ã‚Œã«æº–ã˜ã‚‹è¦è«‹ãŒã‚ã£ãŸå ´åˆã«ãƒ‡ã‚³ãƒ¼ãƒ‰ã«å¿œã˜ã¾ã™ã€‚
+
+5.10. 日本国ã®é ˜åŸŸå†…㧠VPN Gate サービスをé‹å–¶ã™ã‚‹å ´åˆã®æ³¨æ„点
+ユーザーãŒæ—¥æœ¬å›½ã®é ˜åŸŸå†…㧠VPN Gate サービスをé‹å–¶ã™ã‚‹å ´åˆã«ãŠã„ã¦ã€ãã®è¡Œç‚ºãŒé›»æ°—通信役務を他人ã®éœ€è¦ã«å¿œãšã‚‹ãŸã‚ã«æä¾›ã™ã‚‹äº‹æ¥­ã«è©²å½“ã™ã‚‹å ´åˆã¯ã€å½“該 VPN Gate サービスã®æ供行為ã¯é›»æ°—通信事業法 (昭和 59 å¹´ 12 月 25 日法律第 86 å·) ã«ãŠã‘る「電気通信事業ã€ã«è©²å½“ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãŸã ã—ã€ãã®ã‚ˆã†ãªå ´åˆã§ã‚ã£ã¦ã‚‚ã€ã€Œé›»æ°—通信事業å‚入マニュアル[追補版]ã€(å¹³æˆ 17 å¹´ 8 月 18 日発行 ç·å‹™çœé›»æ°—通信事業部データ通信課) ã«ã‚ˆã‚Œã°ã€åŽç›ŠãŒç”Ÿã˜ãªã„å ´åˆã¯é›»æ°—通信事業者ã«ã¯è©²å½“ã—ãªã„ã“ã¨ã¨ãªã‚Šã¾ã™ã€‚従ã£ã¦ã€åŽç›Šç›®çš„ã«ãŠã„ã¦ç¨¼åƒã•ã›ã‚‹å ´åˆã‚’除ãã€VPN Gate サービスを稼åƒã•ã›ã¦ã‚‚登録・届出ãŒå¿…è¦ãªã€Œé›»æ°—通信事業者ã€ã«ã¯è©²å½“ã—ã¾ã›ã‚“。ãŸã¨ãˆé›»æ°—通信事業者ã«è©²å½“ã—ãªã„å ´åˆã«ãŠã„ã¦ã‚‚ã€é›»æ°—通信事業法ã§è¦å®šã•ã‚Œã¦ã„る「秘密ã®ä¿è­·ã€ã®ç¾©å‹™ã¯ç”Ÿã˜ã‚‹ã“ã¨ã¨ãªã‚Šã¾ã™ã€‚ã“れらã®ã“ã¨ã‹ã‚‰ã€æ—¥æœ¬å›½ã®é ˜åŸŸå†…㧠VPN Gate サービスをé‹å–¶ã™ã‚‹å ´åˆã«ãŠã„ã¦ã¯ã€VPN Gate サービスã®é‹å–¶è€…ã¯è‡ªå·±ã®ç®¡ç†ã™ã‚‹ VPN Gate サービスを経由ã—ã¦è¡Œã‚ã‚ŒãŸç¬¬ä¸‰è€…ã®é€šä¿¡å†…容ã®ç§˜å¯†ã‚’æ¼æ´©ã—ã¦ã¯ãªã‚Šã¾ã›ã‚“。
+ã“ã®ç¯€ã«ãŠã‘る注æ„事項ã¯ã€æ—¥æœ¬å›½ã®é ˜åŸŸå¤–ã«ãŠã„ã¦ã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“。
+
+5.11. VPN Gate クライアント
+SoftEther VPN Client ã« VPN Gate クライアントプラグインãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ SoftEther VPN Client を使用ã—ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã§ç¨¼åƒã—ã¦ã„ã‚‹ VPN Gate サービスã®ä¸€è¦§ã‚’å–å¾—ã—ã€ã„ãšã‚Œã‹ã® VPN Gate サービスã®ã‚µãƒ¼ãƒãƒ¼ã‚’指定ã—ã¦ãã®ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+VPN Gate クライアントã¯èµ·å‹•ä¸­ã¯å¸¸æ™‚ã€VPN Gate サービスã®ã‚µãƒ¼ãƒãƒ¼ã®ä¸€è¦§ã‚’å–å¾—ã™ã‚‹ãŸã‚ã®é€šä¿¡ã‚’インターãƒãƒƒãƒˆä¸Šã®ãƒ›ã‚¹ãƒˆã¨ã®é–“ã§ä¸€å®šæ™‚é–“ã”ã¨ã«è¡Œã„ã¾ã™ã€‚ãã®ãŸã‚ã€é€šä¿¡é‡ã¾ãŸã¯é€šä¿¡æ™‚é–“ã«å¿œã˜ã¦èª²é‡‘ãŒç™ºç”Ÿã™ã‚‹ã‚ˆã†ãªã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šå›žç·šã‚’利用中ã®å ´åˆã¯å分ã”注æ„ãã ã•ã„。
+VPN Gate クライアントを起動ã™ã‚‹éš›ã«ã¯ã€VPN Gate サービスを有効ã«ã™ã‚‹ã‹ã©ã†ã‹ã‚’é¸æŠžã™ã‚‹ç”»é¢ãŒè¡¨ç¤ºã•ã‚Œã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚VPN Gate サービスã«ã¤ã„ã¦ã¯ä¸Šè¨˜ã®èª¬æ˜Žã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+
+5.12. VPN Gate 学術実験ã¸ã®å‚加ã¾ãŸã¯ä½¿ç”¨å‰ã®ã”注æ„
+VPN Gate 学術実験サービスã¯ã€æ—¥æœ¬å›½ã«æ‰€åœ¨ã™ã‚‹ç­‘波大学大学院ã«ãŠã‘る研究プロジェクトã¨ã—ã¦é‹å–¶ã•ã‚Œã¦ã„るサービスã§ã™ã€‚本サービスã¯æ—¥æœ¬å›½ã®æ³•ä»¤ã«ã®ã¿æº–æ‹ ã—ã¦é‹ç”¨ã•ã‚Œã¦ãŠã‚Šã€æ—¥æœ¬å›½ä»¥å¤–ã®å›½ãƒ»åœ°åŸŸã®æ³•ä»¤ã«ã¤ã„ã¦ã¯ä¸€åˆ‡é–¢çŸ¥ã—ã¦ãŠã‚Šã¾ã›ã‚“。
+ãã‚‚ãも世界ã«ã¯ 200 カ国近ãã®å›½ãŒå­˜åœ¨ã—ã¦ãŠã‚Šã€ãã‚Œãžã‚Œã®å›½ã«ãŠã‘る法律ã¯äº’ã„ã«ç•°ãªã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®å›½ã®æ³•å¾‹ã‚’調査ã—ãŸä¸Šã§ãれらã™ã¹ã¦ã«é©åˆã™ã‚‹ã“ã¨ã‚’ä¿è¨¼ã—ãŸã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’開発ã™ã‚‹ã“ã¨ã¯äº‹å®Ÿä¸Šä¸å¯èƒ½ã§ã™ã€‚万一ユーザーãŒæœ¬ã‚µãƒ¼ãƒ“スを特定ã®å›½ãƒ»åœ°åŸŸã®é ˜åŸŸå†…ã§åˆ©ç”¨ã—ãŸã“ã¨ã«ã‚ˆã£ã¦å…¬å‹™å“¡ã«ã‚ˆã‚Šæ³•çš„ãªãƒšãƒŠãƒ«ãƒ†ã‚£ã‚’科ã›ã‚‰ã‚Œã‚‹ãªã©ã®æ害ãŒç™ºç”Ÿã—ãŸå ´åˆã§ã‚ã£ã¦ã‚‚ã€ãƒ—ロジェクト実施者ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを使用ã™ã‚‹éš›ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé©ç”¨ã•ã‚Œã‚‹ã™ã¹ã¦ã®æ³•ä»¤ã‚’ユーザーã®è²¬ä»»ã«ã‚ˆã‚Šéµå®ˆã—ã¦ãã ã•ã„。本ソフトウェアã¾ãŸã¯ã‚µãƒ¼ãƒ“スを日本国内・国外をå•ã‚ãšä½¿ç”¨ã•ã‚ŒãŸå ´åˆã«ç™ºç”Ÿã™ã‚‹ã™ã¹ã¦ã®æ害ã¨è²¬ä»»ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¸°è²¬ã—ã¾ã™ã€‚本学術実験ã®é‹å–¶è€…ãŠã‚ˆã³ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ä¾›çµ¦è€…ã¯ã€ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“。
+ã“れらã®æ³¨æ„事項ã«åŒæ„ã„ãŸã ã‘ãªã„å ´åˆã¯ã€VPN Gate 学術実験サービスã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½ã‚’使用ã—ãªã„ã§ãã ã•ã„。
+VPN Gate ã¯ç­‘波大学大学院ã«ãŠã‘る学術目的ã®ç ”究プロジェクトã§ã™ã€‚VPN Gate ソフトウェアã¯ãƒ•ãƒªãƒ¼ã‚¦ã‚§ã‚¢ã§ã‚ã‚‹ SoftEther VPN ãŠã‚ˆã³ã‚ªãƒ¼ãƒ—ンソースã§ã‚ã‚‹ UT-VPN ã‚’æ‹¡å¼µã™ã‚‹ãƒ—ラグインã®å½¢ã§é–‹ç™ºã•ã‚Œã¦ã„ã¾ã™ãŒã€ã“ã‚Œã¯æœ¬ç ”究プロジェクトã«ãŠã„ã¦é–‹ç™ºã•ã‚ŒãŸã‚‚ã®ã§ã‚ã‚Šã€ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ã«ã‚ˆã£ã¦é–‹ç™ºã•ã‚ŒãŸã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“。本研究ã¯ã‚½ãƒ•ãƒˆã‚¤ãƒ¼ã‚µæ ªå¼ä¼šç¤¾ãŒä¸»å®°ã€æŽ¨é€²ã¾ãŸã¯ä¿è¨¼ã™ã‚‹ã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+VPN 通信ãŒç¦æ­¢ã•ã‚Œã¦ã„る国・地域ã§ã¯ VPN Gate を使用ã—ãªã„ã§ãã ã•ã„。
+
+
diff --git a/src/bin/hamcore/webui/cryptcom.cgi b/src/bin/hamcore/webui/cryptcom.cgi
new file mode 100644
index 00000000..587ddf4d
--- /dev/null
+++ b/src/bin/hamcore/webui/cryptcom.cgi
@@ -0,0 +1,49 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+<title>Virtual HUB page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>æš—å·åŒ–ã¨é€šä¿¡é–¢ä¿‚ã®è¨­å®š</h2>
+
+<form method="get" action="cryptcom.cgi">
+
+<h3>使用ã™ã‚‹æš—å·åŒ–アルゴリズム</h3>
+æš—å·åŒ–アルゴリズムå<select name="CRYPT" value="{CRYPT}">
+<!--CRYPT_TMPL<option value="{CRYPTTYPE}">{CRYPTTYPE}CRYPT_TMPL-->
+<!--CRYPTLIST-->
+<p/>
+<h3>サーãƒãƒ¼è¨¼æ˜Žæ›¸</h3>
+サーãƒãƒ¼è¨¼æ˜Žæ›¸ï¼š{SERVERCERT}
+<table>
+<tr>
+<td>証明書ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ</td><td>証明書ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ</td><td>証明書ã®è¡¨ç¤º</td>
+</tr>
+</table>
+
+<h3>syslog é€ä¿¡æ©Ÿèƒ½</h3>
+<select name="SYSLOG">
+<option value="">
+</select>
+
+<h3>インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½</h3>
+<input type="checkbox" CHECKED>インターãƒãƒƒãƒˆæŽ¥ç¶šã®ç¶­æŒæ©Ÿèƒ½ã‚’使用ã™ã‚‹
+<table border=2>
+<tr><td>ホストå</td><td><input type=text name="HOSTNAME" value="{HOSTNAME}"></td></tr>
+<tr><td>ãƒãƒ¼ãƒˆç•ªå·</td><td><input type=text name="PORTNUM" value="{PORTNUM}"></td></tr>
+<tr><td>パケットé€å‡ºé–“éš”</td><td><input type=text name="INTERVAL" value="{INTERVAL}">秒</td></tr>
+プロトコル
+<input type="radio" name="proto" value="TCP">TCP/IP <input type="radio" name="proto" value="UDP">UDP/IP
+</table>
+
+<h3>管ç†ãƒ‘スワード</h3>
+管ç†ãƒ‘スワードã®å¤‰æ›´
+<br/>
+<tr>
+<td><input type=hidden name=KEY value="{SESSIONKEY}"><input type=hidden name=CMD value="SAVE"><input type=submit value="設定をä¿å­˜ã™ã‚‹"></td>
+</tr>
+</form>
+<br>
+<a href="{LINK_SERVER}?KEY={SESSIONKEY}">サーãƒãƒ¼ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+
+</body></html>
+
diff --git a/src/bin/hamcore/webui/edituser.cgi b/src/bin/hamcore/webui/edituser.cgi
new file mode 100644
index 00000000..d9103cd1
--- /dev/null
+++ b/src/bin/hamcore/webui/edituser.cgi
@@ -0,0 +1,32 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>User page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>ユーザーã®ç·¨é›†</h2>
+
+<form action="{LINK_EDITUSER}" method=get>
+<input type=hidden name=KEY value={SESSIONKEY}>
+<input type=hidden name=HUB value={HUBNAME}>
+<input type=hidden name=CMD value={CMDNAME}>
+<!--{USERNAMEHIDDEN}input type=hidden name=USER value={USERNAME}{USERNAMEHIDDEN}-->
+
+<table border=2>
+<tr><td>ユーザーå:</td><td>{USERNAME}<!--{USERNAMEINPUT}input type=text name="USER"{USERNAMEINPUT}--></td></tr>
+<tr><td>本å:</td><td>{REALNAME}</td></tr>
+<tr><td>説明:</td><td>{NOTETEXT}</td></tr>
+<tr><td>グループå:</td><td>{GROUPNAME}</td></tr>
+<tr><td>アカウントã®æœ‰åŠ¹æœŸé™ï¼š</td><td>{EXPIREDATE}</td></tr>
+<tr><td>èªè¨¼æ–¹æ³•ï¼š</td><td>
+ <input type=radio name=AUTHTYPE value="ANONYMOUS" {SELANONYM}>匿åèªè¨¼<br>
+ <input type=radio name=AUTHTYPE value="PASSWORD" {SELPASSWD}>パスワードèªè¨¼
+</td></tr>
+<tr><td>パスワード:</td><td><input type=password name="PASSWORD" value="{PASSWORD}"></td></tr>
+<tr><td>パスワード(確èª):</td><td><input type=password name="PASSWORD2" value="{PASSWORD}"></td></tr>
+</table>
+<input type=submit name="set" value="設定ã™ã‚‹">
+<br>
+<a href="{LINK_USER}?KEY={SESSIONKEY}&HUB={HUBNAME}">仮想 HUB「{HUBNAME}ã€ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ä¸€è¦§ã«æˆ»ã‚‹</a>
+</form>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/error.cgi b/src/bin/hamcore/webui/error.cgi
new file mode 100644
index 00000000..79908bd3
--- /dev/null
+++ b/src/bin/hamcore/webui/error.cgi
@@ -0,0 +1,6 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Redirect</title><link rel=stylesheet type=text/css href=/webui/webui.css></head><body>
+ERRMSG
+<p><H3>ブラウザã®æˆ»ã‚‹ãƒœã‚¿ãƒ³ã§æˆ»ã£ã¦ãã ã•ã„。</H3></p>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/hub.cgi b/src/bin/hamcore/webui/hub.cgi
new file mode 100644
index 00000000..2e85c617
--- /dev/null
+++ b/src/bin/hamcore/webui/hub.cgi
@@ -0,0 +1,51 @@
+<html>
+<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+<title>Virtual HUB page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>仮想 HUB ã®ç®¡ç†</h2>
+
+
+<h3>管ç†ã‚³ãƒžãƒ³ãƒ‰</h3>
+<table>
+<tr><td><!--ENABLE_ONLINEa href="{LINK_HUB}?HUB={HUBNAME}&CMD=ONLINE&KEY={SESSIONKEY}"ENABLE_ONLINE-->オンライン<!--ENABLE_ONLINE/aENABLE_ONLINE-->
+<!--ENABLE_OFFLINEa href="{LINK_HUB}?HUB={HUBNAME}&CMD=OFFLINE&KEY={SESSIONKEY}"ENABLE_OFFLINE-->オフライン<ENABLE_OFFLINE/aENABLE_OFFLINE--></td></tr>
+<tr><td><a href="{LINK_USER}?HUB={HUBNAME}&KEY={SESSIONKEY}">ユーザーã®ç®¡ç†</a></td></tr>
+<tr><td><a href="{LINK_SECURENAT}?KEY={SESSIONKEY}&HUB={HUBNAME}">仮想 NAT ãŠã‚ˆã³ä»®æƒ³ DHCP サーãƒãƒ¼æ©Ÿèƒ½</td></tr>
+<tr><td><a href="{LINK_SESSION}?HUB={HUBNAME}&KEY={SESSIONKEY}">セッションã®ç®¡ç†</a></td></tr>
+</table>
+
+
+<h3>仮想 HUB ã®çŠ¶æ…‹</h3>
+<table border=2>
+<tr><td>仮想 HUB å</td><td>{HUBNAME}</td></tr>
+<tr><td>状態</td><td>{HUBSTATE}</td></tr>
+<tr><td>種類</td><td>{HUBTYPE}</td></tr>
+<tr><td>SecureNAT 機能</td><td>{HUBSNAT}</td></tr>
+<tr><td>セッション数</td><td>{HUBSESSIONS}</td></tr>
+<tr><td>アクセスリスト数</td><td>{HUBACLS}</td></tr>
+<tr><td>ユーザー数</td><td>{HUBUSERS}</td></tr>
+<tr><td>グループ数</td><td>{HUBGROUPS}</td></tr>
+<tr><td>MAC テーブルエントリ数</td><td>{HUBMACTBLS}</td></tr>
+<tr><td>IP テーブルエントリ数</td><td>{HUBIPTBLS}</td></tr>
+<tr><td>ログイン回数</td><td>{HUBLOGINS}</td></tr>
+<tr><td>最終ログイン日時</td><td>{HUBLASTLOGIN}</td></tr>
+<tr><td>最終通信日時</td><td>{HUBLASTCOMM}</td></tr>
+<tr><td>é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆãƒ‘ケット数</td><td>{HUBTXUNIPKTS}</td></tr>
+<tr><td>é€ä¿¡ãƒ¦ãƒ‹ã‚­ãƒ£ã‚¹ãƒˆåˆè¨ˆã‚µã‚¤ã‚º</td><td>{HUBTXUNISIZE}</td></tr>
+<tr><td>é€ä¿¡ãƒ–ロードキャストパケット数</td><td>{HUBTXBRPKTS}</td></tr>
+<tr><td>é€ä¿¡ãƒ–ロードキャストåˆè¨ˆã‚µã‚¤ã‚º</td><td>{HUBTXBRSIZE}</td></tr>
+<tr><td>å—信ユニキャストパケット数</td><td>{HUBRXUNIPKTS}</td></tr>
+<tr><td>å—信ユニキャストåˆè¨ˆã‚µã‚¤ã‚º</td><td>{HUBRXUNISIZE}</td></tr>
+<tr><td>å—信ブロードキャストパケット数</td><td>{HUBRXBRPKTS}</td></tr>
+<tr><td>å—信ブロードキャストåˆè¨ˆã‚µã‚¤ã‚º</td><td>{HUBRXBRSIZE}</td></tr>
+</table>
+
+<br>
+<a href="{LINK_SERVER}?KEY=SESSIONKEY">サーãƒãƒ¼ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+
+</body></html>
+
+<!--STRMAP:HUB_ONLINE:オンライン,HUB_OFFLINE:オフライン,SECNAT_ON:有効,SECNAT_OFF:無効:STRMAP-->
+
diff --git a/src/bin/hamcore/webui/license.cgi b/src/bin/hamcore/webui/license.cgi
new file mode 100644
index 00000000..b259d1a0
--- /dev/null
+++ b/src/bin/hamcore/webui/license.cgi
@@ -0,0 +1,36 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Virtual HUB page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>ライセンスã®è¿½åŠ ã¨å‰Šé™¤</h2>
+
+<h3>登録ã•ã‚Œã¦ã„るライセンスã®ä¸€è¦§</h3>
+<table border=2>
+<tr><td>番å·</td><td>ライセンスキー</td><td>ライセンス種類å</td><td>状態</td><td>有効期é™</td><td>ライセンス ID</td>
+<td>ライセンス種類 ID</td><td>サーãƒãƒ¼ ID</td><td>シリアル ID</td></tr>
+<!--LICENSES_TMPL:<tr><td><a href="{LINK_LICENSE}?KEY={SESSIONKEY}&CMD=DEL&ID={ID}">削除</a></td><td>{LICENSEKEY}</td><td>{LICENSENAME}</td><td>{STATUS}</td><td>{EXPIRES}</td><td>{LICENSEID}</td><td>{PRODUCTID}</td><td>{SYSTEMID}</td><td>{SERIALID}</td></tr>:LICENSES_TMPL-->
+<!--LICENSES-->
+</table>
+
+<h3>ç¾åœ¨ã® PacketiX VPN Server ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰</h3>
+<table border=2>
+<tr><td>製å“エディションå</td><td>{LSEDITIONNAME}</td></tr>
+<tr><td>ç¾åœ¨ã®ã‚µãƒ¼ãƒãƒ¼ ID</td><td>{LSSERVERID}</td></tr>
+<tr><td>ç¾åœ¨ã®è£½å“ライセンスã®æœ‰åŠ¹æœŸé™</td><td>{LSEXPIRES}</td></tr>
+<tr><td>クライアント接続ライセンス数</td><td>{LSNUMCLIENTS}</td></tr>
+<tr><td>ブリッジ接続ライセンス数</td><td>{LSNUMBRIDGES}</td></tr>
+</table>
+
+<h3>ライセンスã®è¿½åŠ </h3>
+<form method=get action="{LINK_LICENSE}">
+<tr><td>ライセンスキーを入力ã—ã¦ãã ã•ã„:</td><td><input type=text name="KEYSTRINGS" maxlength="41"></td></tr>
+<input type=hidden name=KEY value="{SESSIONKEY}">
+<input type=hidden name=CMD value="ADD"><input type=submit value="追加">
+</form>
+
+<br>
+<a href="{LINK_SERVER}?KEY={SESSIONKEY}">サーãƒãƒ¼ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+
+</body></html>
+<!--STRMAP:NOEXPIRE:無期é™,LICENSE_INFINITE:無制é™-->
diff --git a/src/bin/hamcore/webui/listener.cgi b/src/bin/hamcore/webui/listener.cgi
new file mode 100644
index 00000000..973d9849
--- /dev/null
+++ b/src/bin/hamcore/webui/listener.cgi
@@ -0,0 +1,13 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Lisner Creation</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+リスナーを作æˆã—ã¾ã™ã€‚
+<form method=get action="ACTION">
+ãƒãƒ¼ãƒˆç•ªå·ï¼š<input type=text name=PORT>
+<input type=hidden name=KEY value="SESSIONKEY">
+<input type=hidden name=CMD value="CREATE">
+<input type=submit value="作æˆ">
+</form>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/localbridge.cgi b/src/bin/hamcore/webui/localbridge.cgi
new file mode 100644
index 00000000..c3c54db5
--- /dev/null
+++ b/src/bin/hamcore/webui/localbridge.cgi
@@ -0,0 +1,52 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Virtual HUB page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>ローカルブリッジ接続ã®è¨­å®š</h2>
+
+<h3>ローカルブリッジ接続ã®ä¸€è¦§</h3>
+<table border=2>
+<tr><td><!--番å·--></td><td>仮想 HUB å</td><td>ブリッジ先 LAN カードåˆã¯ tap デãƒã‚¤ã‚¹å</td><td>状態</td></tr>
+<!--LBLIST_TMPL<tr><td><a href="{LINK_LOCALBRIDGE}?KEY={SESSIONKEY}&CMD=DEL&LISTID={LISTID}">削除</a></td><td>{HUBNAME}</td><td>{DEVICENAME}</td><td>{STATUS}</td></tr>LBLIST_TMPL-->
+<!--LBLIST-->
+</table>
+
+<h3>æ–°ã—ã„ローカルブリッジã®å®šç¾©</h3>
+<form method=get action="{LINK_LOCALBRIDGE}">
+<table>
+<tr>
+<td>仮想 HUB å:</td><td><select name="LBHUBNAME">
+<!--HUBS_TMPL<option value="{LBHUBNAME}">{LBHUBNAME}HUBS_TMPL-->
+<!--HUBS-->
+</select>
+</td>
+</tr>
+<tr>
+<td>作æˆã™ã‚‹ç¨®é¡žï¼š</td>
+<td><input type="radio" name=TAPMODE value="NO" checked>物ç†çš„ãªæ—¢å­˜ã® LAN カードã¨ã®ãƒ–リッジ接続<br>
+<input type="radio" name=TAPMODE value="YES">æ–°ã—ã„ tap デãƒã‚¤ã‚¹ã¨ã®ãƒ–リッジ接続</td>
+</tr>
+<tr>
+<td>デãƒã‚¤ã‚¹å:</td>
+<td><select name="DEVID">
+<!--LBDEVLIST_TMPL<option value="{DEVID}">{ABLEDEVICE}LBDEVLIST_TMPL-->
+<!--LBDEVLIST-->
+</select>
+</td>
+</tr>
+<tr>
+<td>æ–°ã—ã„ tap デãƒã‚¤ã‚¹å</td><td><input type=text name="TAPNMAME" maxlength="11"></td>
+</tr>
+<tr>
+<td><input type=hidden name=KEY value="{SESSIONKEY}"><input type=hidden name=CMD value="CREATE"><input type=submit value="追加"></td>
+</tr>
+</table>
+</form>
+
+<br>
+<a href="{LINK_SERVER}?KEY={SESSIONKEY}">サーãƒãƒ¼ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+
+</body></html>
+
+<!--STRMAP:BRIDGE_ONLINE:オンライン,BRIDGE_OFFLINE:オフライン,BRIDGE_ERROR:エラー発生-->
diff --git a/src/bin/hamcore/webui/login.cgi b/src/bin/hamcore/webui/login.cgi
new file mode 100644
index 00000000..aef1c24d
--- /dev/null
+++ b/src/bin/hamcore/webui/login.cgi
@@ -0,0 +1,17 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Login page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+<center>
+<H2>PacketiX VPN Server Web UI ログインページ.</H2>
+<form action="ACTION" method="get">
+<table>
+<tr><td align=right>仮想 HUB å:</td><td><input type="text" name="HUB" value=HUBNAME></td></tr>
+<tr><td></td><td><font color=red size =2>※仮想 HUB åを空欄ã«ã™ã‚‹ã¨ã‚µãƒ¼ãƒãƒ¼ç®¡ç†ãƒ¢ãƒ¼ãƒ‰ã«ãªã‚Šã¾ã™ã€‚</font></td></tr>
+<tr><td align=right>パスワード:</td><td><input type="password" name="PASS"></td></tr>
+</table><input type="submit" value="ログイン">
+</form>
+<font color="red"><!--ERR1--></font>
+</center>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/newhub.cgi b/src/bin/hamcore/webui/newhub.cgi
new file mode 100644
index 00000000..74cff864
--- /dev/null
+++ b/src/bin/hamcore/webui/newhub.cgi
@@ -0,0 +1,18 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Lisner Creation</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+<h2>æ–°ã—ã„仮想 HUB ã®ä½œæˆ</h2>
+<form method=get action="{LINK_NEWHUB}">
+<table>
+<tr><td>作æˆã™ã‚‹ä»®æƒ³ HUB ã®åå‰ï¼š</td><td><input type=text name=NAME></td></tr>
+<tr><td>管ç†ãƒ‘スワード:</td><td><input type=password name=PASSWD></td></tr>
+<tr><td>管ç†ãƒ‘スワード(確èªï¼‰ï¼š</td><td><input type=password name=PASSWD2></td></tr>
+</table>
+<input type=hidden name=KEY value="{SESSIONKEY}">
+<input type=hidden name=CMD value="CREATE">
+<input type=submit value="作æˆ">
+</form>
+<a href="{LINK_SERVER}?KEY={SESSIONKEY}">サーãƒãƒ¼ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/redirect.cgi b/src/bin/hamcore/webui/redirect.cgi
new file mode 100644
index 00000000..f825b7ea
--- /dev/null
+++ b/src/bin/hamcore/webui/redirect.cgi
@@ -0,0 +1,5 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Redirect</title><meta http-equiv="refresh" CONTENT="0;URL=REDIRECT_TO"></head><body>
+<H2>Redirect to:<a href="REDIRECT_TO">REDIRECT_TO</a></H2>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/securenat.cgi b/src/bin/hamcore/webui/securenat.cgi
new file mode 100644
index 00000000..04e73c2b
--- /dev/null
+++ b/src/bin/hamcore/webui/securenat.cgi
@@ -0,0 +1,59 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+<title>Virtual HUB page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>仮想 NAT ãŠã‚ˆã³ä»®æƒ³ DHCP 機能 (Secure NAT) ã®è¨­å®š</h2>
+
+<h3>SecureNAT 機能ã®æœ‰åŠ¹ / 無効ã®è¨­å®š</h3>
+<table border=2>
+<tr><td>SecureNAT 機能:</td><td>
+<!--ENABLESNATa href="{LINK_SECURENAT}?HUB={HUBNAME}&CMD=ENABLE&KEY={SESSIONKEY}"ENABLESNAT-->有効<!--ENABLESNAT/aENABLESNAT-->
+<!--DISABLESNATa href="{LINK_SECURENAT}?HUB={HUBNAME}&CMD=DISABLE&KEY={SESSIONKEY}"DISABLESNAT-->無効<!--DISABLESNAT/aDISABLESNAT-->
+</td></table>
+
+<h2>SecureNAT オプションã®è¨­å®š</h2>
+<form method="get" action="{LINK_SECURENAT}">
+<h3>仮想 ホストã®è¨­å®š</h3>
+<table border=2>
+<tr><td>MAC アドレス</td><td><input type=text name="HOSTMAC" value="{HOSTMAC}" maxlength="17"></td></tr>
+<tr><td>IP アドレス</td><td><input type=text name="HOSTIP" value="{HOSTIP}" maxlength="15"></td></tr>
+<tr><td>サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯</td><td><input type=text name="HOSTMASK" value="{HOSTMASK}" maxlength="15"></td></tr>
+</table>
+
+<h3>仮想 NAT ã®è¨­å®š</h3>
+<input type="checkbox" name="NATCHECK" value="on" {NATCHECK}>仮想 NAT 機能を使用ã™ã‚‹
+<table border=2>
+<tr><td>MTU 値</td><td><input type=text name="NATMTU" value="{NATMTU}">ãƒã‚¤ãƒˆ</td></tr>
+<tr><td>TCP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ</td><td><input type=text name="NATTCPTIMEOUT" value="{NATTCPTIMEOUT}">秒</td></tr>
+<tr><td>UDP セッションã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ</td><td><input type=text name="NATUDPTIMEOUT" value="{NATUDPTIMEOUT}">秒</td></tr>
+</table>
+<input type=checkbox name="NATSAVELOG" value="on" {NATSAVELOG}>仮想 NAT ã®å‹•ä½œã‚’ã€ä»®æƒ³ HUB ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã«ä¿å­˜ã™ã‚‹
+
+<h3>仮想 DHCP サーãƒãƒ¼ã®è¨­å®š</h3>
+<input type="checkbox" name="DHCPCHECK" value="on" {DHCPCHECK}>仮想 DHCP サーãƒãƒ¼æ©Ÿèƒ½ã‚’使用ã™ã‚‹
+<table border=2>
+<tr><td>é…布 IP アドレス帯</td><td><input type=text name="DHCPIPS" value="{DHCPIPS}">ã‹ã‚‰</td></tr>
+<tr><td> </td><td><input type=text name="DHCPIPE" value="{DHCPIPE}">ã¾ã§</td></tr>
+<tr><td>サブãƒãƒƒãƒˆãƒžã‚¹ã‚¯</td><td><input type=text name="DHCPMASK" value="{DHCPMASK}"></td></tr>
+<tr><td>リース期é™</td><td><input type=text name="DHCPEXPIRE" value="{DHCPEXPIRE}">秒</td></tr>
+</table>
+
+<h4>クライアントã«å‰²ã‚Šå½“ã¦ã‚‹ã‚ªãƒ—ションã®è¨­å®š</h4>
+<table border=2>
+<tr><td>デフォルトゲートウェイã®ã‚¢ãƒ‰ãƒ¬ã‚¹</td><td><input type=text name="DHCPGW" value="{DHCPGW}"></td></tr>
+<tr><td>DNS サーãƒãƒ¼ã®ã‚¢ãƒ‰ãƒ¬ã‚¹</td><td><input type=text name="DHCPDNS" value="{DHCPDNS}"></td></tr>
+<tr><td>ドメインå</td><td><input type=text name="DHCPDOMAIN" value="{DHCPDOMAIN}"></td></tr>
+</table>
+
+<input type=hidden name=KEY value="{SESSIONKEY}">
+<input type=hidden name=HUB value="{HUBNAME}">
+<input type=hidden name=CMD value="SAVE">
+<input type=submit value="設定をä¿å­˜ã™ã‚‹">
+</form>
+
+<p>
+<a href="{LINK_HUB}?HUB={HUBNAME}&KEY={SESSIONKEY}">仮想 HUB ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹</a>
+
+</body></html>
+
diff --git a/src/bin/hamcore/webui/server.cgi b/src/bin/hamcore/webui/server.cgi
new file mode 100644
index 00000000..371f789b
--- /dev/null
+++ b/src/bin/hamcore/webui/server.cgi
@@ -0,0 +1,42 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>Server page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+<h2>VPN サーãƒãƒ¼ã®ç®¡ç†</h2>
+
+<h3>仮想 HUB ã®ä¸€è¦§</h3>
+<table border=2><tr><td><a href="{LINK_NEWHUB}?KEY={SESSIONKEY}">æ–°è¦ä½œæˆ</a>
+</td><td>仮想 HUB å</td><td>状態</td><td>種類</td><td>ユーザー</td><td>グループ</td><td>セッション</td>
+<td>MAC</td><td>IP</td><td>ログイン回数</td><td>最終ログイン日時</td><td>最終通信日時</td></tr>
+<!--HUBS_TMPL:<tr><td><a href="{LINK_HUB}?KEY={SESSIONKEY}&HUB={HUBNAME}&CMD=DELETE">削除</a></td><td><a href="{LINK_HUB}?KEY={SESSIONKEY}&HUB={HUBNAME}">{HUBNAME}</a></td><td>{HUBSTATE}</td><td>{HUBTYPE}</td><td>{HUBUSERS}</td><td>{HUBGROUPS}</td><td>{HUBSESSIONS}</td><td>{HUBMACS}</td><td>{HUBIPS}</td><td>{HUBLOGINS}</td><td>{HUBLASTLOGINDATE}</td><td>{HUBLASTCOMMDATE}</td></tr>:HUBS_TMPL-->
+<!--HUBS-->
+</table>
+<br>
+<h3>リスナーã®ä¸€è¦§</h3>
+<table>
+<tr><td>
+<table border=2><tr><td>ãƒãƒ¼ãƒˆç•ªå·</td><td>状態</td><td><a href="{LISTENER_LINK}?KEY={SESSIONKEY}&CMD=CREATE">æ–°è¦ä½œæˆ</a></td></tr>
+<!--LISTENER_TMPL:<tr><td>TCP {PORTNUM}</td><td>{PORT_STATE}</td><td>
+<a href="{LISTENER_LINK}?KEY={SESSIONKEY}&CMD=DEL&PORT={PORTNUM}">削除</a>
+<!--STARTAa href="{LISTENER_LINK}?KEY={SESSIONKEY}&CMD=START&PORT={PORTNUM}"STARTA-->開始<!--STARTA/aSTARTA-->
+<!--STOPAa href="{LISTENER_LINK}?KEY={SESSIONKEY}&CMD=STOP&PORT={PORTNUM}"STOPA-->åœæ­¢<!--STOPA/aSTOPA--></td></tr>
+:LISTENER_TMPL-->
+<!--LISTENERS-->
+</table>
+</td>
+<td>
+<table border=2>
+<!--
+<tr><td><a href="{LISTENER_LINK}?KEY={SESSIONKEY}">æš—å·åŒ–ã¨ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®è¨­å®š</a></td></tr>
+<tr><td><a href="{LISTENER_LINK}?KEY={SESSIONKEY}">サーãƒãƒ¼çŠ¶æ…‹</a></td></tr>
+-->
+<tr><td><a href="{LINK_LICENSE}?KEY={SESSIONKEY}">ライセンスã®ç®¡ç†</a></td></tr>
+<tr><td><a href="{LINK_LOCALBRIDGE}?KEY={SESSIONKEY}">ローカルブリッジã®è¨­å®š</a></td></tr>
+</table>
+</td>
+</tr>
+</table>
+
+</body></html>
+
+<!--STRMAP:HUB_ONLINE:オンライン,HUB_OFFLINE:オフライン,HUB_STANDALONE:スタンドアロン,HUB_DYNAMIC:ダイナミック,HUB_STATIC:スタティック,LISTENER_ONLINE:動作中,LISTENER_OFFLINE:åœæ­¢ä¸­,LISTENER_ERROR:エラー:STRMAP-->
diff --git a/src/bin/hamcore/webui/session.cgi b/src/bin/hamcore/webui/session.cgi
new file mode 100644
index 00000000..36a6a104
--- /dev/null
+++ b/src/bin/hamcore/webui/session.cgi
@@ -0,0 +1,16 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>User page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>仮想 HUB「{HUBNAME}ã€ã«æŽ¥ç¶šä¸­ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³</h2>
+
+<table border=2>
+<tr><td>コマンド</td><td>セッションå</td><td>接続ã—ã¦ã„るサーãƒãƒ¼</td><td>ユーザーå</td><td>接続元ホストå</td><td>TCP コãƒã‚¯ã‚·ãƒ§ãƒ³</td><td>転é€ãƒã‚¤ãƒˆæ•°</td><td>転é€ãƒ‘ケット数</td></tr>
+<!--SESSION_TMPL:<tr><td><a href="{LINK_SESSION}?HUB={HUBNAME}&KEY={SESSIONKEY}&CMD=DEL&SESSION={SESSION}">切断</a></td><td>{SESSION_NAME}</td><td>{SESSION_SERVER}</td><td>{SESSION_USER}</td><td>{SESSION_HOST}</td><td>{SESSION_TCP}</td><td>{SESSION_BYTES}</td><td>{SESSION_PKTS}</td></tr>:SESSION_TMPL-->
+<!--SESSIONS-->
+</table>
+<p>
+<a href="{LINK_HUB}?KEY={SESSIONKEY}&HUB={HUBNAME}">仮想 HUB「{HUBNAME}ã€ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹ã€‚</a>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/user.cgi b/src/bin/hamcore/webui/user.cgi
new file mode 100644
index 00000000..7a17b6d0
--- /dev/null
+++ b/src/bin/hamcore/webui/user.cgi
@@ -0,0 +1,18 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<title>User page</title>
+<link rel=stylesheet type=text/css href=/webui/webui.css>
+</head><body>
+
+<h2>仮想 HUB「{HUBNAME}ã€ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç®¡ç†</h2>
+<table border=2><tr><td><a href="{LINK_EDITUSER}?KEY={SESSIONKEY}&HUB={HUBNAME}">æ–°è¦ä½œæˆ</a></td><td>ユーザーå</td><td>本å</td><td>所属グループ</td><td>説明</td>
+<td>èªè¨¼æ–¹æ³•</td><td>ログイン回数</td><td>最終ログイン日時</td></tr>
+<!--USER_TMPL:<tr><td><a href="{LINK_EDITUSER}?USER=%S&HUB={HUBNAME}&KEY={SESSIONKEY}">編集</a>
+ <a href="{LINK_USER}?CMD=DEL&USER=%S&HUB={HUBNAME}&KEY={SESSIONKEY}">削除</a></td>
+<td>%S</td><td>%s</td><td>%S</td><td>%s</td>
+<td>%s</td><td>%d</td><td>%s</td></tr>-->
+<!--USERS-->
+</table>
+<br>
+<a href="{LINK_HUB}?KEY={SESSIONKEY}&HUB={HUBNAME}">仮想 HUB「{HUBNAME}ã€ã®ç®¡ç†ç”»é¢ã«æˆ»ã‚‹ã€‚</a>
+</body></html>
+
diff --git a/src/bin/hamcore/webui/webui.css b/src/bin/hamcore/webui/webui.css
new file mode 100644
index 00000000..cd115aac
--- /dev/null
+++ b/src/bin/hamcore/webui/webui.css
@@ -0,0 +1,3 @@
+body{
+ background:white;
+}
diff --git a/src/bin/hamcore/winpcap_installer.exe b/src/bin/hamcore/winpcap_installer.exe
new file mode 100644
index 00000000..550dff8b
--- /dev/null
+++ b/src/bin/hamcore/winpcap_installer.exe
Binary files differ
diff --git a/src/bin/hamcore/winpcap_installer_win9x.exe b/src/bin/hamcore/winpcap_installer_win9x.exe
new file mode 100644
index 00000000..de146520
--- /dev/null
+++ b/src/bin/hamcore/winpcap_installer_win9x.exe
Binary files differ
diff --git a/src/bin/install_src.dat b/src/bin/install_src.dat
new file mode 100644
index 00000000..92781ffa
--- /dev/null
+++ b/src/bin/install_src.dat
@@ -0,0 +1 @@
+“c’†I \ No newline at end of file
diff --git a/src/bin/vpnweb.cab b/src/bin/vpnweb.cab
new file mode 100644
index 00000000..d71cec20
--- /dev/null
+++ b/src/bin/vpnweb.cab
Binary files differ
diff --git a/src/bin/vpnweb.ocx b/src/bin/vpnweb.ocx
new file mode 100644
index 00000000..72b4c6ab
--- /dev/null
+++ b/src/bin/vpnweb.ocx
Binary files differ
diff --git a/src/configure b/src/configure
new file mode 100755
index 00000000..6b7bfb2e
--- /dev/null
+++ b/src/configure
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+echo 'Move to the parent directory and run ./configure script as following:'
+echo
+echo '$ cd ..'
+echo '$ ./configure'
+echo
+echo 'Good luck!'
+echo
+
diff --git a/src/makefiles/freebsd_32bit.mak b/src/makefiles/freebsd_32bit.mak
new file mode 100644
index 00000000..aca1db5c
--- /dev/null
+++ b/src/makefiles/freebsd_32bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=FreeBSD, bits=32bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_BSD -DBRIDGE_BPF -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_BSD -DBRIDGE_BPF -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/freebsd_64bit.mak b/src/makefiles/freebsd_64bit.mak
new file mode 100644
index 00000000..f005c431
--- /dev/null
+++ b/src/makefiles/freebsd_64bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=FreeBSD, bits=64bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_BSD -DBRIDGE_BPF -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char -m64
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -m64 -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_BSD -DBRIDGE_BPF -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char -m64
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -m64 -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/linux_32bit.mak b/src/makefiles/linux_32bit.mak
new file mode 100644
index 00000000..f7781c27
--- /dev/null
+++ b/src/makefiles/linux_32bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Linux, bits=32bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_LINUX -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -lm -ldl -lrt -lpthread -lssl -lcrypto -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_LINUX -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -lm -ldl -lrt -lpthread -lssl -lcrypto -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/linux_64bit.mak b/src/makefiles/linux_64bit.mak
new file mode 100644
index 00000000..3d7b3cc0
--- /dev/null
+++ b/src/makefiles/linux_64bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Linux, bits=64bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_LINUX -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char -m64
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -m64 -lm -ldl -lrt -lpthread -lssl -lcrypto -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_LINUX -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char -m64
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -m64 -lm -ldl -lrt -lpthread -lssl -lcrypto -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/macos_32bit.mak b/src/makefiles/macos_32bit.mak
new file mode 100644
index 00000000..d74fafef
--- /dev/null
+++ b/src/makefiles/macos_32bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Mac OS X, bits=32bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_MACOS -DBRIDGE_PCAP -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz -lpcap
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_MACOS -DBRIDGE_PCAP -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz -lpcap
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/macos_64bit.mak b/src/makefiles/macos_64bit.mak
new file mode 100644
index 00000000..c7ccc472
--- /dev/null
+++ b/src/makefiles/macos_64bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Mac OS X, bits=64bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_MACOS -DBRIDGE_PCAP -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char -m64
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -m64 -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz -lpcap
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_MACOS -DBRIDGE_PCAP -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char -m64
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -m64 -lm -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz -lpcap
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/solaris_32bit.mak b/src/makefiles/solaris_32bit.mak
new file mode 100644
index 00000000..bf327336
--- /dev/null
+++ b/src/makefiles/solaris_32bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Solaris, bits=32bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_SOLARIS -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -lm -lrt -lnsl -lsocket -ldl -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_SOLARIS -DNO_VLAN -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -lm -lrt -lnsl -lsocket -ldl -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/makefiles/solaris_64bit.mak b/src/makefiles/solaris_64bit.mak
new file mode 100644
index 00000000..1860deb0
--- /dev/null
+++ b/src/makefiles/solaris_64bit.mak
@@ -0,0 +1,440 @@
+# SoftEther VPN Source Code
+#
+# Copyright (c) 2012-2014 SoftEther VPN Project at University of Tsukuba, Japan.
+# Copyright (c) 2012-2014 Daiyuu Nobori.
+# All Rights Reserved.
+#
+# http://www.softether.org/
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License version 2
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Platform: os=Solaris, bits=64bit
+
+# Variables
+CC=gcc
+
+OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_SOLARIS -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char -m64
+
+OPTIONS_LINK_DEBUG=-g -fsigned-char -m64 -lm -lrt -lnsl -lsocket -ldl -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+OPTIONS_COMPILE_RELEASE=-DNDEBUG -DVPN_SPEED -DUNIX -DUNIX_SOLARIS -DNO_VLAN -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -O2 -fsigned-char -m64
+
+OPTIONS_LINK_RELEASE=-O2 -fsigned-char -m64 -lm -lrt -lnsl -lsocket -ldl -lpthread -lssl -lcrypto -liconv -lreadline -lncurses -lz
+
+INSTALL_BINDIR=/usr/bin/
+INSTALL_VPNSERVER_DIR=/usr/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
+INSTALL_VPNCMD_DIR=/usr/vpncmd/
+
+ifeq ($(DEBUG),YES)
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
+ OPTIONS_LINK=$(OPTIONS_LINK_DEBUG)
+else
+ OPTIONS_COMPILE=$(OPTIONS_COMPILE_RELEASE)
+ OPTIONS_LINK=$(OPTIONS_LINK_RELEASE)
+endif
+
+# Files
+HEADERS_MAYAQUA=src/Mayaqua/Cfg.h src/Mayaqua/cryptoki.h src/Mayaqua/Encrypt.h src/Mayaqua/FileIO.h src/Mayaqua/intelaes/iaesni.h src/Mayaqua/Internat.h src/Mayaqua/Kernel.h src/Mayaqua/Mayaqua.h src/Mayaqua/MayaType.h src/Mayaqua/Memory.h src/Mayaqua/Microsoft.h src/Mayaqua/Network.h src/Mayaqua/Object.h src/Mayaqua/OS.h src/Mayaqua/Pack.h src/Mayaqua/pkcs11.h src/Mayaqua/pkcs11f.h src/Mayaqua/pkcs11t.h src/Mayaqua/Secure.h src/Mayaqua/Str.h src/Mayaqua/Table.h src/Mayaqua/TcpIp.h src/Mayaqua/Tick64.h src/Mayaqua/Tracking.h src/Mayaqua/TunTap.h src/Mayaqua/Unix.h src/Mayaqua/Win32.h src/Mayaqua/zlib/zconf.h src/Mayaqua/zlib/zlib.h
+HEADERS_CEDAR=src/Cedar/Account.h src/Cedar/Admin.h src/Cedar/AzureClient.h src/Cedar/AzureServer.h src/Cedar/Bridge.h src/Cedar/BridgeUnix.h src/Cedar/BridgeWin32.h src/Cedar/Cedar.h src/Cedar/CedarPch.h src/Cedar/CedarType.h src/Cedar/Client.h src/Cedar/CM.h src/Cedar/CMInner.h src/Cedar/Command.h src/Cedar/Connection.h src/Cedar/Console.h src/Cedar/Database.h src/Cedar/DDNS.h src/Cedar/EM.h src/Cedar/EMInner.h src/Cedar/EtherLog.h src/Cedar/Hub.h src/Cedar/Interop_OpenVPN.h src/Cedar/Interop_SSTP.h src/Cedar/IPsec.h src/Cedar/IPsec_EtherIP.h src/Cedar/IPsec_IKE.h src/Cedar/IPsec_IkePacket.h src/Cedar/IPsec_IPC.h src/Cedar/IPsec_L2TP.h src/Cedar/IPsec_PPP.h src/Cedar/IPsec_Win7.h src/Cedar/IPsec_Win7Inner.h src/Cedar/Layer3.h src/Cedar/Link.h src/Cedar/Listener.h src/Cedar/Logging.h src/Cedar/Nat.h src/Cedar/NativeStack.h src/Cedar/netcfgn.h src/Cedar/netcfgx.h src/Cedar/NM.h src/Cedar/NMInner.h src/Cedar/NullLan.h src/Cedar/Protocol.h src/Cedar/Radius.h src/Cedar/Remote.h src/Cedar/Sam.h src/Cedar/SecureInfo.h src/Cedar/SecureNAT.h src/Cedar/SeLowUser.h src/Cedar/Server.h src/Cedar/Session.h src/Cedar/SM.h src/Cedar/SMInner.h src/Cedar/SW.h src/Cedar/SWInner.h src/Cedar/UdpAccel.h src/Cedar/UT.h src/Cedar/VG.h src/Cedar/Virtual.h src/Cedar/VLan.h src/Cedar/VLanUnix.h src/Cedar/VLanWin32.h src/Cedar/WaterMark.h src/Cedar/WebUI.h src/Cedar/Win32Com.h src/Cedar/winpcap/bittypes.h src/Cedar/winpcap/bucket_lookup.h src/Cedar/winpcap/count_packets.h src/Cedar/winpcap/Devioctl.h src/Cedar/winpcap/Gnuc.h src/Cedar/winpcap/ip6_misc.h src/Cedar/winpcap/memory_t.h src/Cedar/winpcap/normal_lookup.h src/Cedar/winpcap/Ntddndis.h src/Cedar/winpcap/Ntddpack.h src/Cedar/winpcap/Packet32.h src/Cedar/winpcap/pcap.h src/Cedar/winpcap/pcap-bpf.h src/Cedar/winpcap/pcap-int.h src/Cedar/winpcap/pcap-stdinc.h src/Cedar/winpcap/pthread.h src/Cedar/winpcap/remote-ext.h src/Cedar/winpcap/sched.h src/Cedar/winpcap/semaphore.h src/Cedar/winpcap/tcp_session.h src/Cedar/winpcap/time_calls.h src/Cedar/winpcap/tme.h src/Cedar/winpcap/Win32-Extensions.h src/Cedar/WinUi.h src/Cedar/Wpc.h
+OBJECTS_MAYAQUA=tmp/objs/Mayaqua/Cfg.o tmp/objs/Mayaqua/Encrypt.o tmp/objs/Mayaqua/FileIO.o tmp/objs/Mayaqua/Internat.o tmp/objs/Mayaqua/Kernel.o tmp/objs/Mayaqua/Mayaqua.o tmp/objs/Mayaqua/Memory.o tmp/objs/Mayaqua/Microsoft.o tmp/objs/Mayaqua/Network.o tmp/objs/Mayaqua/Object.o tmp/objs/Mayaqua/OS.o tmp/objs/Mayaqua/Pack.o tmp/objs/Mayaqua/Secure.o tmp/objs/Mayaqua/Str.o tmp/objs/Mayaqua/Table.o tmp/objs/Mayaqua/TcpIp.o tmp/objs/Mayaqua/Tick64.o tmp/objs/Mayaqua/Tracking.o tmp/objs/Mayaqua/Unix.o tmp/objs/Mayaqua/Win32.o
+OBJECTS_CEDAR=tmp/objs/Cedar/Account.o tmp/objs/Cedar/Admin.o tmp/objs/Cedar/AzureClient.o tmp/objs/Cedar/AzureServer.o tmp/objs/Cedar/Bridge.o tmp/objs/Cedar/BridgeUnix.o tmp/objs/Cedar/BridgeWin32.o tmp/objs/Cedar/Cedar.o tmp/objs/Cedar/CedarPch.o tmp/objs/Cedar/Client.o tmp/objs/Cedar/CM.o tmp/objs/Cedar/Command.o tmp/objs/Cedar/Connection.o tmp/objs/Cedar/Console.o tmp/objs/Cedar/Database.o tmp/objs/Cedar/DDNS.o tmp/objs/Cedar/EM.o tmp/objs/Cedar/EtherLog.o tmp/objs/Cedar/Hub.o tmp/objs/Cedar/Interop_OpenVPN.o tmp/objs/Cedar/Interop_SSTP.o tmp/objs/Cedar/IPsec.o tmp/objs/Cedar/IPsec_EtherIP.o tmp/objs/Cedar/IPsec_IKE.o tmp/objs/Cedar/IPsec_IkePacket.o tmp/objs/Cedar/IPsec_IPC.o tmp/objs/Cedar/IPsec_L2TP.o tmp/objs/Cedar/IPsec_PPP.o tmp/objs/Cedar/IPsec_Win7.o tmp/objs/Cedar/Layer3.o tmp/objs/Cedar/Link.o tmp/objs/Cedar/Listener.o tmp/objs/Cedar/Logging.o tmp/objs/Cedar/Nat.o tmp/objs/Cedar/NativeStack.o tmp/objs/Cedar/NM.o tmp/objs/Cedar/NullLan.o tmp/objs/Cedar/Protocol.o tmp/objs/Cedar/Radius.o tmp/objs/Cedar/Remote.o tmp/objs/Cedar/Sam.o tmp/objs/Cedar/SecureInfo.o tmp/objs/Cedar/SecureNAT.o tmp/objs/Cedar/SeLowUser.o tmp/objs/Cedar/Server.o tmp/objs/Cedar/Session.o tmp/objs/Cedar/SM.o tmp/objs/Cedar/SW.o tmp/objs/Cedar/UdpAccel.o tmp/objs/Cedar/UT.o tmp/objs/Cedar/VG.o tmp/objs/Cedar/Virtual.o tmp/objs/Cedar/VLan.o tmp/objs/Cedar/VLanUnix.o tmp/objs/Cedar/VLanWin32.o tmp/objs/Cedar/WaterMark.o tmp/objs/Cedar/WebUI.o tmp/objs/Cedar/WinUi.o tmp/objs/Cedar/Wpc.o
+
+# Build Action
+default: build
+
+build: $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) bin/vpnserver/vpnserver bin/vpnclient/vpnclient bin/vpnbridge/vpnbridge bin/vpncmd/vpncmd
+
+# Mayaqua Kernel Code
+tmp/objs/Mayaqua/Cfg.o: src/Mayaqua/Cfg.c $(HEADERS_MAYAQUA)
+ @mkdir -p tmp/
+ @mkdir -p tmp/objs/
+ @mkdir -p tmp/objs/Mayaqua/
+ @mkdir -p tmp/objs/Cedar/
+ @mkdir -p tmp/as/
+ @mkdir -p bin/
+ @mkdir -p bin/vpnserver/
+ @mkdir -p bin/vpnclient/
+ @mkdir -p bin/vpnbridge/
+ @mkdir -p bin/vpncmd/
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Cfg.c -o tmp/objs/Mayaqua/Cfg.o
+
+tmp/objs/Mayaqua/Encrypt.o: src/Mayaqua/Encrypt.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Encrypt.c -o tmp/objs/Mayaqua/Encrypt.o
+
+tmp/objs/Mayaqua/FileIO.o: src/Mayaqua/FileIO.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/FileIO.c -o tmp/objs/Mayaqua/FileIO.o
+
+tmp/objs/Mayaqua/Internat.o: src/Mayaqua/Internat.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Internat.c -o tmp/objs/Mayaqua/Internat.o
+
+tmp/objs/Mayaqua/Kernel.o: src/Mayaqua/Kernel.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Kernel.c -o tmp/objs/Mayaqua/Kernel.o
+
+tmp/objs/Mayaqua/Mayaqua.o: src/Mayaqua/Mayaqua.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Mayaqua.c -o tmp/objs/Mayaqua/Mayaqua.o
+
+tmp/objs/Mayaqua/Memory.o: src/Mayaqua/Memory.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Memory.c -o tmp/objs/Mayaqua/Memory.o
+
+tmp/objs/Mayaqua/Microsoft.o: src/Mayaqua/Microsoft.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Microsoft.c -o tmp/objs/Mayaqua/Microsoft.o
+
+tmp/objs/Mayaqua/Network.o: src/Mayaqua/Network.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Network.c -o tmp/objs/Mayaqua/Network.o
+
+tmp/objs/Mayaqua/Object.o: src/Mayaqua/Object.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Object.c -o tmp/objs/Mayaqua/Object.o
+
+tmp/objs/Mayaqua/OS.o: src/Mayaqua/OS.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/OS.c -o tmp/objs/Mayaqua/OS.o
+
+tmp/objs/Mayaqua/Pack.o: src/Mayaqua/Pack.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Pack.c -o tmp/objs/Mayaqua/Pack.o
+
+tmp/objs/Mayaqua/Secure.o: src/Mayaqua/Secure.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Secure.c -o tmp/objs/Mayaqua/Secure.o
+
+tmp/objs/Mayaqua/Str.o: src/Mayaqua/Str.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Str.c -o tmp/objs/Mayaqua/Str.o
+
+tmp/objs/Mayaqua/Table.o: src/Mayaqua/Table.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Table.c -o tmp/objs/Mayaqua/Table.o
+
+tmp/objs/Mayaqua/TcpIp.o: src/Mayaqua/TcpIp.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/TcpIp.c -o tmp/objs/Mayaqua/TcpIp.o
+
+tmp/objs/Mayaqua/Tick64.o: src/Mayaqua/Tick64.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tick64.c -o tmp/objs/Mayaqua/Tick64.o
+
+tmp/objs/Mayaqua/Tracking.o: src/Mayaqua/Tracking.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Tracking.c -o tmp/objs/Mayaqua/Tracking.o
+
+tmp/objs/Mayaqua/Unix.o: src/Mayaqua/Unix.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Unix.c -o tmp/objs/Mayaqua/Unix.o
+
+tmp/objs/Mayaqua/Win32.o: src/Mayaqua/Win32.c $(HEADERS_MAYAQUA)
+ $(CC) $(OPTIONS_COMPILE) -c src/Mayaqua/Win32.c -o tmp/objs/Mayaqua/Win32.o
+
+# Cedar Communication Module Code
+tmp/objs/Cedar/Account.o: src/Cedar/Account.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Account.c -o tmp/objs/Cedar/Account.o
+
+tmp/objs/Cedar/Admin.o: src/Cedar/Admin.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Admin.c -o tmp/objs/Cedar/Admin.o
+
+tmp/objs/Cedar/AzureClient.o: src/Cedar/AzureClient.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureClient.c -o tmp/objs/Cedar/AzureClient.o
+
+tmp/objs/Cedar/AzureServer.o: src/Cedar/AzureServer.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/AzureServer.c -o tmp/objs/Cedar/AzureServer.o
+
+tmp/objs/Cedar/Bridge.o: src/Cedar/Bridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) src/Cedar/BridgeUnix.c
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Bridge.c -o tmp/objs/Cedar/Bridge.o
+
+tmp/objs/Cedar/BridgeUnix.o: src/Cedar/BridgeUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeUnix.c -o tmp/objs/Cedar/BridgeUnix.o
+
+tmp/objs/Cedar/BridgeWin32.o: src/Cedar/BridgeWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/BridgeWin32.c -o tmp/objs/Cedar/BridgeWin32.o
+
+tmp/objs/Cedar/Cedar.o: src/Cedar/Cedar.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Cedar.c -o tmp/objs/Cedar/Cedar.o
+
+tmp/objs/Cedar/CedarPch.o: src/Cedar/CedarPch.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CedarPch.c -o tmp/objs/Cedar/CedarPch.o
+
+tmp/objs/Cedar/Client.o: src/Cedar/Client.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Client.c -o tmp/objs/Cedar/Client.o
+
+tmp/objs/Cedar/CM.o: src/Cedar/CM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/CM.c -o tmp/objs/Cedar/CM.o
+
+tmp/objs/Cedar/Command.o: src/Cedar/Command.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Command.c -o tmp/objs/Cedar/Command.o
+
+tmp/objs/Cedar/Connection.o: src/Cedar/Connection.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Connection.c -o tmp/objs/Cedar/Connection.o
+
+tmp/objs/Cedar/Console.o: src/Cedar/Console.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Console.c -o tmp/objs/Cedar/Console.o
+
+tmp/objs/Cedar/Database.o: src/Cedar/Database.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Database.c -o tmp/objs/Cedar/Database.o
+
+tmp/objs/Cedar/DDNS.o: src/Cedar/DDNS.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/DDNS.c -o tmp/objs/Cedar/DDNS.o
+
+tmp/objs/Cedar/EM.o: src/Cedar/EM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EM.c -o tmp/objs/Cedar/EM.o
+
+tmp/objs/Cedar/EtherLog.o: src/Cedar/EtherLog.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/EtherLog.c -o tmp/objs/Cedar/EtherLog.o
+
+tmp/objs/Cedar/Hub.o: src/Cedar/Hub.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Hub.c -o tmp/objs/Cedar/Hub.o
+
+tmp/objs/Cedar/Interop_OpenVPN.o: src/Cedar/Interop_OpenVPN.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_OpenVPN.c -o tmp/objs/Cedar/Interop_OpenVPN.o
+
+tmp/objs/Cedar/Interop_SSTP.o: src/Cedar/Interop_SSTP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Interop_SSTP.c -o tmp/objs/Cedar/Interop_SSTP.o
+
+tmp/objs/Cedar/IPsec.o: src/Cedar/IPsec.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec.c -o tmp/objs/Cedar/IPsec.o
+
+tmp/objs/Cedar/IPsec_EtherIP.o: src/Cedar/IPsec_EtherIP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_EtherIP.c -o tmp/objs/Cedar/IPsec_EtherIP.o
+
+tmp/objs/Cedar/IPsec_IKE.o: src/Cedar/IPsec_IKE.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IKE.c -o tmp/objs/Cedar/IPsec_IKE.o
+
+tmp/objs/Cedar/IPsec_IkePacket.o: src/Cedar/IPsec_IkePacket.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IkePacket.c -o tmp/objs/Cedar/IPsec_IkePacket.o
+
+tmp/objs/Cedar/IPsec_IPC.o: src/Cedar/IPsec_IPC.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_IPC.c -o tmp/objs/Cedar/IPsec_IPC.o
+
+tmp/objs/Cedar/IPsec_L2TP.o: src/Cedar/IPsec_L2TP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_L2TP.c -o tmp/objs/Cedar/IPsec_L2TP.o
+
+tmp/objs/Cedar/IPsec_PPP.o: src/Cedar/IPsec_PPP.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_PPP.c -o tmp/objs/Cedar/IPsec_PPP.o
+
+tmp/objs/Cedar/IPsec_Win7.o: src/Cedar/IPsec_Win7.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/IPsec_Win7.c -o tmp/objs/Cedar/IPsec_Win7.o
+
+tmp/objs/Cedar/Layer3.o: src/Cedar/Layer3.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Layer3.c -o tmp/objs/Cedar/Layer3.o
+
+tmp/objs/Cedar/Link.o: src/Cedar/Link.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Link.c -o tmp/objs/Cedar/Link.o
+
+tmp/objs/Cedar/Listener.o: src/Cedar/Listener.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Listener.c -o tmp/objs/Cedar/Listener.o
+
+tmp/objs/Cedar/Logging.o: src/Cedar/Logging.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Logging.c -o tmp/objs/Cedar/Logging.o
+
+tmp/objs/Cedar/Nat.o: src/Cedar/Nat.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Nat.c -o tmp/objs/Cedar/Nat.o
+
+tmp/objs/Cedar/NativeStack.o: src/Cedar/NativeStack.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NativeStack.c -o tmp/objs/Cedar/NativeStack.o
+
+tmp/objs/Cedar/NM.o: src/Cedar/NM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NM.c -o tmp/objs/Cedar/NM.o
+
+tmp/objs/Cedar/NullLan.o: src/Cedar/NullLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/NullLan.c -o tmp/objs/Cedar/NullLan.o
+
+tmp/objs/Cedar/Protocol.o: src/Cedar/Protocol.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Protocol.c -o tmp/objs/Cedar/Protocol.o
+
+tmp/objs/Cedar/Radius.o: src/Cedar/Radius.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Radius.c -o tmp/objs/Cedar/Radius.o
+
+tmp/objs/Cedar/Remote.o: src/Cedar/Remote.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Remote.c -o tmp/objs/Cedar/Remote.o
+
+tmp/objs/Cedar/Sam.o: src/Cedar/Sam.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Sam.c -o tmp/objs/Cedar/Sam.o
+
+tmp/objs/Cedar/SecureInfo.o: src/Cedar/SecureInfo.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureInfo.c -o tmp/objs/Cedar/SecureInfo.o
+
+tmp/objs/Cedar/SecureNAT.o: src/Cedar/SecureNAT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SecureNAT.c -o tmp/objs/Cedar/SecureNAT.o
+
+tmp/objs/Cedar/SeLowUser.o: src/Cedar/SeLowUser.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SeLowUser.c -o tmp/objs/Cedar/SeLowUser.o
+
+tmp/objs/Cedar/Server.o: src/Cedar/Server.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Server.c -o tmp/objs/Cedar/Server.o
+
+tmp/objs/Cedar/Session.o: src/Cedar/Session.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Session.c -o tmp/objs/Cedar/Session.o
+
+tmp/objs/Cedar/SM.o: src/Cedar/SM.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SM.c -o tmp/objs/Cedar/SM.o
+
+tmp/objs/Cedar/SW.o: src/Cedar/SW.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/SW.c -o tmp/objs/Cedar/SW.o
+
+tmp/objs/Cedar/UdpAccel.o: src/Cedar/UdpAccel.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UdpAccel.c -o tmp/objs/Cedar/UdpAccel.o
+
+tmp/objs/Cedar/UT.o: src/Cedar/UT.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/UT.c -o tmp/objs/Cedar/UT.o
+
+tmp/objs/Cedar/VG.o: src/Cedar/VG.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VG.c -o tmp/objs/Cedar/VG.o
+
+tmp/objs/Cedar/Virtual.o: src/Cedar/Virtual.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Virtual.c -o tmp/objs/Cedar/Virtual.o
+
+tmp/objs/Cedar/VLan.o: src/Cedar/VLan.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLan.c -o tmp/objs/Cedar/VLan.o
+
+tmp/objs/Cedar/VLanUnix.o: src/Cedar/VLanUnix.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanUnix.c -o tmp/objs/Cedar/VLanUnix.o
+
+tmp/objs/Cedar/VLanWin32.o: src/Cedar/VLanWin32.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/VLanWin32.c -o tmp/objs/Cedar/VLanWin32.o
+
+tmp/objs/Cedar/WaterMark.o: src/Cedar/WaterMark.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WaterMark.c -o tmp/objs/Cedar/WaterMark.o
+
+tmp/objs/Cedar/WebUI.o: src/Cedar/WebUI.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WebUI.c -o tmp/objs/Cedar/WebUI.o
+
+tmp/objs/Cedar/WinUi.o: src/Cedar/WinUi.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/WinUi.c -o tmp/objs/Cedar/WinUi.o
+
+tmp/objs/Cedar/Wpc.o: src/Cedar/Wpc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/Cedar/Wpc.c -o tmp/objs/Cedar/Wpc.o
+
+# vpnserver
+bin/vpnserver/vpnserver: tmp/as/vpnserver.a bin/vpnserver/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnserver.a $(OPTIONS_LINK) -o bin/vpnserver/vpnserver
+
+tmp/as/vpnserver.a: tmp/objs/vpnserver.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnserver.a
+ ar r tmp/as/vpnserver.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnserver.o
+ ranlib tmp/as/vpnserver.a
+
+bin/vpnserver/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnserver/hamcore.se2
+
+tmp/objs/vpnserver.o: src/vpnserver/vpnserver.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnserver/vpnserver.c -o tmp/objs/vpnserver.o
+
+# vpnclient
+bin/vpnclient/vpnclient: tmp/as/vpnclient.a bin/vpnclient/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnclient.a $(OPTIONS_LINK) -o bin/vpnclient/vpnclient
+
+tmp/as/vpnclient.a: tmp/objs/vpnclient.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnclient.a
+ ar r tmp/as/vpnclient.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnclient.o
+ ranlib tmp/as/vpnclient.a
+
+bin/vpnclient/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnclient/hamcore.se2
+
+tmp/objs/vpnclient.o: src/vpnclient/vpncsvc.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnclient/vpncsvc.c -o tmp/objs/vpnclient.o
+
+# vpnbridge
+bin/vpnbridge/vpnbridge: tmp/as/vpnbridge.a bin/vpnbridge/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpnbridge.a $(OPTIONS_LINK) -o bin/vpnbridge/vpnbridge
+
+tmp/as/vpnbridge.a: tmp/objs/vpnbridge.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpnbridge.a
+ ar r tmp/as/vpnbridge.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpnbridge.o
+ ranlib tmp/as/vpnbridge.a
+
+bin/vpnbridge/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpnbridge/hamcore.se2
+
+tmp/objs/vpnbridge.o: src/vpnbridge/vpnbridge.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpnbridge/vpnbridge.c -o tmp/objs/vpnbridge.o
+
+# vpncmd
+bin/vpncmd/vpncmd: tmp/as/vpncmd.a bin/vpncmd/hamcore.se2 $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) tmp/as/vpncmd.a $(OPTIONS_LINK) -o bin/vpncmd/vpncmd
+
+tmp/as/vpncmd.a: tmp/objs/vpncmd.o $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ rm -f tmp/as/vpncmd.a
+ ar r tmp/as/vpncmd.a $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR) tmp/objs/vpncmd.o
+ ranlib tmp/as/vpncmd.a
+
+bin/vpncmd/hamcore.se2: src/bin/BuiltHamcoreFiles/unix/hamcore.se2
+ cp src/bin/BuiltHamcoreFiles/unix/hamcore.se2 bin/vpncmd/hamcore.se2
+
+tmp/objs/vpncmd.o: src/vpncmd/vpncmd.c $(HEADERS_MAYAQUA) $(HEADERS_CEDAR) $(OBJECTS_MAYAQUA) $(OBJECTS_CEDAR)
+ $(CC) $(OPTIONS_COMPILE) -c src/vpncmd/vpncmd.c -o tmp/objs/vpncmd.o
+
+# Install
+install: $(INSTALL_BINDIR)vpnserver $(INSTALL_BINDIR)vpnbridge $(INSTALL_BINDIR)vpnclient $(INSTALL_BINDIR)vpncmd
+ @echo
+ @echo "--------------------------------------------------------------------"
+ @echo "Installation completed successfully."
+ @echo
+ @echo "Execute 'vpnserver start' to run the SoftEther VPN Server background service."
+ @echo "Execute 'vpnbridge start' to run the SoftEther VPN Bridge background service."
+ @echo "Execute 'vpnclient start' to run the SoftEther VPN Client background service."
+ @echo "Execute 'vpncmd' to run SoftEther VPN Command-Line Utility to configure VPN Server, VPN Bridge or VPN Client."
+ @echo "--------------------------------------------------------------------"
+ @echo
+
+$(INSTALL_BINDIR)vpnserver: bin/vpnserver/hamcore.se2 bin/vpnserver/vpnserver
+ @mkdir -p $(INSTALL_VPNSERVER_DIR)
+ cp bin/vpnserver/hamcore.se2 $(INSTALL_VPNSERVER_DIR)hamcore.se2
+ cp bin/vpnserver/vpnserver $(INSTALL_VPNSERVER_DIR)vpnserver
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnserver
+ echo $(INSTALL_VPNSERVER_DIR)vpnserver '"$$@"' >> $(INSTALL_BINDIR)vpnserver
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnserver
+ chmod 755 $(INSTALL_BINDIR)vpnserver
+
+$(INSTALL_BINDIR)vpnbridge: bin/vpnbridge/hamcore.se2 bin/vpnbridge/vpnbridge
+ @mkdir -p $(INSTALL_VPNBRIDGE_DIR)
+ cp bin/vpnbridge/hamcore.se2 $(INSTALL_VPNBRIDGE_DIR)hamcore.se2
+ cp bin/vpnbridge/vpnbridge $(INSTALL_VPNBRIDGE_DIR)vpnbridge
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnbridge
+ echo $(INSTALL_VPNBRIDGE_DIR)vpnbridge '"$$@"' >> $(INSTALL_BINDIR)vpnbridge
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnbridge
+ chmod 755 $(INSTALL_BINDIR)vpnbridge
+
+$(INSTALL_BINDIR)vpnclient: bin/vpnclient/hamcore.se2 bin/vpnclient/vpnclient
+ @mkdir -p $(INSTALL_VPNCLIENT_DIR)
+ cp bin/vpnclient/hamcore.se2 $(INSTALL_VPNCLIENT_DIR)hamcore.se2
+ cp bin/vpnclient/vpnclient $(INSTALL_VPNCLIENT_DIR)vpnclient
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpnclient
+ echo $(INSTALL_VPNCLIENT_DIR)vpnclient '"$$@"' >> $(INSTALL_BINDIR)vpnclient
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpnclient
+ chmod 755 $(INSTALL_BINDIR)vpnclient
+
+$(INSTALL_BINDIR)vpncmd: bin/vpncmd/hamcore.se2 bin/vpncmd/vpncmd
+ @mkdir -p $(INSTALL_VPNCMD_DIR)
+ cp bin/vpncmd/hamcore.se2 $(INSTALL_VPNCMD_DIR)hamcore.se2
+ cp bin/vpncmd/vpncmd $(INSTALL_VPNCMD_DIR)vpncmd
+ echo "#!/bin/sh" > $(INSTALL_BINDIR)vpncmd
+ echo $(INSTALL_VPNCMD_DIR)vpncmd '"$$@"' >> $(INSTALL_BINDIR)vpncmd
+ echo 'exit $$?' >> $(INSTALL_BINDIR)vpncmd
+ chmod 755 $(INSTALL_BINDIR)vpncmd
+
+# Clean
+clean:
+ -rm -f $(OBJECTS_MAYAQUA)
+ -rm -f $(OBJECTS_CEDAR)
+ -rm -f tmp/objs/vpnserver.o
+ -rm -f tmp/as/vpnserver.a
+ -rm -f bin/vpnserver/vpnserver
+ -rm -f tmp/objs/vpnclient.o
+ -rm -f tmp/as/vpnclient.a
+ -rm -f bin/vpnclient/vpnclient
+ -rm -f tmp/objs/vpnbridge.o
+ -rm -f tmp/as/vpnbridge.a
+ -rm -f bin/vpnbridge/vpnbridge
+ -rm -f tmp/objs/vpncmd.o
+ -rm -f tmp/as/vpncmd.a
+ -rm -f bin/vpncmd/vpncmd
+
+# Help Strings
+help:
+ @echo "make [DEBUG=YES]"
+ @echo "make install"
+ @echo "make clean"
+
diff --git a/src/vpnbrand/resource.h b/src/vpnbrand/resource.h
new file mode 100644
index 00000000..7a516431
--- /dev/null
+++ b/src/vpnbrand/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnbrand.rc
+//
+#define IDI_ICON1 101
+#define ICO_VPNBRAND 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnbrand/vpnbrand.c b/src/vpnbrand/vpnbrand.c
new file mode 100644
index 00000000..5bd2e539
--- /dev/null
+++ b/src/vpnbrand/vpnbrand.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main()
+{
+ printf("VPN Branding Kit was obsolete. Customize SoftEther VPN by modifying the source code.\n");
+ return 0;
+}
diff --git a/src/vpnbrand/vpnbrand.h b/src/vpnbrand/vpnbrand.h
new file mode 100644
index 00000000..b87b22f1
--- /dev/null
+++ b/src/vpnbrand/vpnbrand.h
@@ -0,0 +1,113 @@
+// SoftEther VPN Source Code
+// Hamster Test Code
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// BrandingKit.h
+// Header file of BrandingKit.c
+
+
+#ifndef BRANDINGKIT_H
+
+#define BRANDINGKIT_H
+
+//HAMCORE entry
+typedef struct HAMCORE_ENTRY{
+ char name[MAX_SIZE];
+ UINT size;
+ UINT compsize;
+ void *compdata;
+} HAMCORE_ENTRY;
+
+
+// HAMCORE file
+typedef struct HAMCORE_FILE{
+ UINT NumEntries;
+ HAMCORE_ENTRY *Entries;
+ char *body;
+} HAMCORE_FILE;
+
+// Function prototype
+int main(int argc, char *argv[]);
+
+// BRANDINGKIT_H
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnbrand/vpnbrand.ico b/src/vpnbrand/vpnbrand.ico
new file mode 100644
index 00000000..8ebc8e00
--- /dev/null
+++ b/src/vpnbrand/vpnbrand.ico
Binary files differ
diff --git a/src/vpnbrand/vpnbrand.rc b/src/vpnbrand/vpnbrand.rc
new file mode 100644
index 00000000..119ff7d3
--- /dev/null
+++ b/src/vpnbrand/vpnbrand.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+ICO_VPNBRAND ICON "vpnbrand.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnbrand/vpnbrand.vcproj b/src/vpnbrand/vpnbrand.vcproj
new file mode 100644
index 00000000..aa1018ed
--- /dev/null
+++ b/src/vpnbrand/vpnbrand.vcproj
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnbrand"
+ ProjectGUID="{ABAB0B91-91DD-4FF4-9773-18B37A820B9F}"
+ RootNamespace="vpnbrand"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbrand.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbrand_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbrand.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbrand_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpnbrand.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnbrand.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpnbrand.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnbrand.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnbridge/resource.h b/src/vpnbridge/resource.h
new file mode 100644
index 00000000..53759f1f
--- /dev/null
+++ b/src/vpnbridge/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnbridge.rc
+//
+#define IDI_ICON1 101
+#define IDI_MAIN 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnbridge/vpnbridge.c b/src/vpnbridge/vpnbridge.c
new file mode 100644
index 00000000..14aef6c1
--- /dev/null
+++ b/src/vpnbridge/vpnbridge.c
@@ -0,0 +1,141 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpnbridge.c
+// VPN Bridge Service Program
+
+#include <GlobalConst.h>
+
+#define VPN_EXE
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include "../PenCore/resource.h"
+#endif // WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// Process start function
+void StartProcess()
+{
+ // Start the server
+ InitCedar();
+ StInit();
+ StStartServer(true);
+}
+
+// Process stop function
+void StopProcess()
+{
+ // Stop the server
+ StStopServer();
+ StFree();
+ FreeCedar();
+}
+
+// WinMain function
+int main(int argc, char *argv[])
+{
+ VgUseStaticLink();
+
+#ifdef OS_WIN32
+ return MsService(GC_SVC_NAME_VPNBRIDGE, StartProcess, StopProcess, ICO_BRIDGE, argv[0]);
+#else // OS_WIN32
+ return UnixService(argc, argv, "vpnbridge", StartProcess, StopProcess);
+#endif // OS_WIN32
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnbridge/vpnbridge.ico b/src/vpnbridge/vpnbridge.ico
new file mode 100644
index 00000000..451a0547
--- /dev/null
+++ b/src/vpnbridge/vpnbridge.ico
Binary files differ
diff --git a/src/vpnbridge/vpnbridge.rc b/src/vpnbridge/vpnbridge.rc
new file mode 100644
index 00000000..06e6da7a
--- /dev/null
+++ b/src/vpnbridge/vpnbridge.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAIN ICON "vpnbridge.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnbridge/vpnbridge.vcproj b/src/vpnbridge/vpnbridge.vcproj
new file mode 100644
index 00000000..3a059dd9
--- /dev/null
+++ b/src/vpnbridge/vpnbridge.vcproj
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnbridge"
+ ProjectGUID="{BA0DBC31-5BBF-41BF-A2DB-7B6F3F71E919}"
+ RootNamespace="vpnbridge"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbridge.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbridge_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbridge.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnbridge_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpnbridge.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpnbridge.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnbridge.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnclient/Machine.ico b/src/vpnclient/Machine.ico
new file mode 100644
index 00000000..1919d045
--- /dev/null
+++ b/src/vpnclient/Machine.ico
Binary files differ
diff --git a/src/vpnclient/resource.h b/src/vpnclient/resource.h
new file mode 100644
index 00000000..cfc07d3c
--- /dev/null
+++ b/src/vpnclient/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnclient.rc
+//
+#define IDI_ICON1 101
+#define IDI_MAIN 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnclient/vpnclient.rc b/src/vpnclient/vpnclient.rc
new file mode 100644
index 00000000..8493f080
--- /dev/null
+++ b/src/vpnclient/vpnclient.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAIN ICON "Machine.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnclient/vpnclient.vcproj b/src/vpnclient/vpnclient.vcproj
new file mode 100644
index 00000000..6e27a5b5
--- /dev/null
+++ b/src/vpnclient/vpnclient.vcproj
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnclient"
+ ProjectGUID="{D7216F25-434B-45D3-BA48-6772AF997C84}"
+ RootNamespace="vpnclient"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnclient.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnclient_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnclient.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnclient_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpncsvc.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpncsvc.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Machine.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnclient.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnclient/vpncsvc.c b/src/vpnclient/vpncsvc.c
new file mode 100644
index 00000000..a9fa16ee
--- /dev/null
+++ b/src/vpnclient/vpncsvc.c
@@ -0,0 +1,128 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncsvc.c
+// VPN Client Service Program
+
+#include <GlobalConst.h>
+
+#define VPN_EXE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// Process start function
+void StartProcess()
+{
+ // Start the client
+ InitCedar();
+ CtStartClient();
+}
+
+// Process termination function
+void StopProcess()
+{
+ // Stop the client
+ CtStopClient();
+ FreeCedar();
+}
+
+// WinMain function
+int main(int argc, char *argv[])
+{
+#ifdef OS_WIN32
+
+ return MsService(GC_SVC_NAME_VPNCLIENT, StartProcess, StopProcess, ICO_MACHINE, argv[0]);
+#else // OS_WIN32
+ return UnixService(argc, argv, "vpnclient", StartProcess, StopProcess);
+#endif // OS_WIN32
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnclient/vpncsvc.h b/src/vpnclient/vpncsvc.h
new file mode 100644
index 00000000..e8a6bd7a
--- /dev/null
+++ b/src/vpnclient/vpncsvc.h
@@ -0,0 +1,98 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncsvc.h
+// Header of vpncsvc.c
+
+#ifndef VPNCSVC_H
+#define VPNCSVC_H
+
+// Function prototype
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow);
+void StartProcess();
+void StopProcess();
+
+
+#endif // VPNCSVC_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpncmd/resource.h b/src/vpncmd/resource.h
new file mode 100644
index 00000000..d0e03622
--- /dev/null
+++ b/src/vpncmd/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpncmd.rc
+//
+#define IDI_ICON1 101
+#define IDI_VPNCMD 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpncmd/vpncmd.c b/src/vpncmd/vpncmd.c
new file mode 100644
index 00000000..4c85cc26
--- /dev/null
+++ b/src/vpncmd/vpncmd.c
@@ -0,0 +1,176 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncmd.c
+// VPN Command Line Management Utility
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#endif // WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// main function
+int main(int argc, char *argv[])
+{
+ wchar_t *s;
+ UINT ret;
+
+#ifdef OS_WIN32
+ SetConsoleTitleA(CEDAR_PRODUCT_STR " VPN Command Line Utility");
+#endif // OS_WIN32
+
+ InitMayaqua(false, false, argc, argv);
+ InitCedar();
+
+ s = GetCommandLineUniStr();
+
+ if (s == NULL)
+ {
+ s = CopyUniStr(L"");
+ }
+
+ if (UniStrCmpi(s, L"exit") != 0)
+ {
+ UINT size = UniStrSize(s) + 64;
+ wchar_t *tmp;
+
+ tmp = Malloc(size);
+ UniFormat(tmp, size, L"vpncmd %s", s);
+ ret = CommandMain(tmp);
+
+ Free(tmp);
+ }
+
+#ifdef OS_WIN32
+ {
+ UINT i;
+ LIST *o = MsGetProcessList();
+ bool b = false;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+
+ if (EndWith(p->ExeFilename, "\\cmd.exe") || EndWith(p->ExeFilename, "\\command.com"))
+ {
+ b = true;
+ break;
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ if (b == false)
+ {
+ if (ret != ERR_NO_ERROR)
+ {
+ SleepThread(1000);
+ }
+ }
+ }
+#endif // OS_WIN32
+
+ Free(s);
+
+ FreeCedar();
+ FreeMayaqua();
+ return ret;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpncmd/vpncmd.ico b/src/vpncmd/vpncmd.ico
new file mode 100644
index 00000000..83e14e02
--- /dev/null
+++ b/src/vpncmd/vpncmd.ico
Binary files differ
diff --git a/src/vpncmd/vpncmd.rc b/src/vpncmd/vpncmd.rc
new file mode 100644
index 00000000..a06de98d
--- /dev/null
+++ b/src/vpncmd/vpncmd.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_VPNCMD ICON "vpncmd.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpncmd/vpncmd.vcproj b/src/vpncmd/vpncmd.vcproj
new file mode 100644
index 00000000..2dbd9eb8
--- /dev/null
+++ b/src/vpncmd/vpncmd.vcproj
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpncmd"
+ ProjectGUID="{83438AC3-5329-4337-89BC-5B69EBAE4B6E}"
+ RootNamespace="vpncmd"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_USE_32BIT_TIME_T"
+ StringPooling="false"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmd.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;CPU_64"
+ StringPooling="false"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmd_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ MinimalRebuild="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmd.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ MinimalRebuild="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmd_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpncmd.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpncmd.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpncmd.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpncmdsys/resource.h b/src/vpncmdsys/resource.h
new file mode 100644
index 00000000..a5e09bba
--- /dev/null
+++ b/src/vpncmdsys/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpncmdsys.rc
+//
+#define IDI_ICON1 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpncmdsys/vpncmdsys.c b/src/vpncmdsys/vpncmdsys.c
new file mode 100644
index 00000000..7a5bccb7
--- /dev/null
+++ b/src/vpncmdsys/vpncmdsys.c
@@ -0,0 +1,274 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncmdsys.c
+// vpncmd bootstrup
+
+#include <GlobalConst.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <locale.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "vpncmdsys.h"
+
+static UINT ret_code = 0;
+
+// Get whether the system is a Windows NT
+bool IsWindowsNt()
+{
+ OSVERSIONINFO info;
+
+ ZeroMemory(&info, sizeof(info));
+ info.dwOSVersionInfoSize = sizeof(info);
+
+ if (GetVersionEx(&info) == false)
+ {
+ return false;
+ }
+
+ if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Execute a child process
+bool ExecProcess(char *exe_name, wchar_t *args_w)
+{
+ bool ret;
+ wchar_t exe_name_w[MAX_SIZE];
+ char args[MAX_SIZE];
+ STARTUPINFO info;
+ STARTUPINFOW info_w;
+ PROCESS_INFORMATION proc;
+ // Validate arguments
+ if (exe_name == NULL || args_w == NULL)
+ {
+ return false;
+ }
+
+ ZeroMemory(exe_name_w, sizeof(exe_name_w));
+ ZeroMemory(args, sizeof(args));
+ mbstowcs(exe_name_w, exe_name, strlen(exe_name));
+ wcstombs(args, args_w, sizeof(args));
+
+ ZeroMemory(&info, sizeof(info));
+ info.cb = sizeof(info);
+
+ ZeroMemory(&info_w, sizeof(info_w));
+ info_w.cb = sizeof(info_w);
+
+ ZeroMemory(&proc, sizeof(proc));
+
+ if (IsWindowsNt() == false)
+ {
+ ret = CreateProcess(exe_name, args, NULL, NULL, false, NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &proc);
+ }
+ else
+ {
+ ret = CreateProcessW(exe_name_w, args_w, NULL, NULL, false, NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info_w, &proc);
+ }
+
+ if (ret)
+ {
+ WaitForSingleObject(proc.hProcess, INFINITE);
+
+ GetExitCodeProcess(proc.hProcess, &ret_code);
+ }
+
+ return ret;
+}
+
+// Entry point
+int main(int argc, char *argv[])
+{
+ HKEY hKey;
+ bool ok = false;
+ char error[MAX_SIZE];
+ wchar_t *current_args;
+ bool flag = false;
+ bool break_now = false;
+
+ error[0] = 0;
+
+ setlocale(LC_ALL, "");
+
+ current_args = GetCommandLineW();
+
+ // Remove the program name portion from the command line string
+ while (true)
+ {
+ switch (*current_args)
+ {
+ case L'\"':
+ if (flag == false)
+ {
+ flag = true;
+ }
+ else
+ {
+ flag = false;
+ }
+ break;
+
+ case L' ':
+ case L'\t':
+ case 0:
+ if (flag == false)
+ {
+ break_now = true;
+ }
+ break;
+ }
+ if (break_now)
+ {
+ break;
+ }
+ current_args++;
+ }
+
+ while (true)
+ {
+ if (*current_args == L' ' || *current_args == L'\t')
+ {
+ current_args++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ strcpy(error, "VPN Command Line Tools is not Installed.\nPlease reinstall programs.");
+
+ // Get the path of the vpncmd.exe from the registry
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, &hKey) == 0)
+ {
+ DWORD type = REG_SZ;
+ DWORD size = 4096;
+ char buf[4096];
+
+ if (RegQueryValueEx(hKey, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, NULL, &type, (LPBYTE)buf, &size) == 0)
+ {
+ wchar_t args[MAX_SIZE];
+
+ swprintf(args, sizeof(args), L"\"%S\" %s", buf, current_args);
+ if (ExecProcess(buf, args) == false)
+ {
+ //sprintf(error, "Failed to execute \"%S\".", buf);
+ }
+ else
+ {
+ ok = true;
+ }
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ if (ok == false)
+ {
+ printf("%s\n", error);
+ }
+
+ return ret_code;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpncmdsys/vpncmdsys.h b/src/vpncmdsys/vpncmdsys.h
new file mode 100644
index 00000000..89767a32
--- /dev/null
+++ b/src/vpncmdsys/vpncmdsys.h
@@ -0,0 +1,96 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncmdsys.h
+// Header of VPN vpncmdsys.c
+
+// Function prototypes
+int main(int argc, char *argv[]);
+bool ExecProcess(char *exe_name, wchar_t *args_w);
+bool IsWindowsNt();
+
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpncmdsys/vpncmdsys.ico b/src/vpncmdsys/vpncmdsys.ico
new file mode 100644
index 00000000..83e14e02
--- /dev/null
+++ b/src/vpncmdsys/vpncmdsys.ico
Binary files differ
diff --git a/src/vpncmdsys/vpncmdsys.rc b/src/vpncmdsys/vpncmdsys.rc
new file mode 100644
index 00000000..c40298f7
--- /dev/null
+++ b/src/vpncmdsys/vpncmdsys.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON "vpncmdsys.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpncmdsys/vpncmdsys.vcproj b/src/vpncmdsys/vpncmdsys.vcproj
new file mode 100644
index 00000000..6d1da5bd
--- /dev/null
+++ b/src/vpncmdsys/vpncmdsys.vcproj
@@ -0,0 +1,258 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpncmdsys"
+ ProjectGUID="{78CD48D9-0B4B-43B1-A1D1-E079362B6864}"
+ RootNamespace="vpncmdsys"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\vpncmdsys.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\vpncmdsys_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="1"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpncmdsys.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpncmdsys.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpncmdsys.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpncmdsys.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpncmgr/Server.ico b/src/vpncmgr/Server.ico
new file mode 100644
index 00000000..b569c128
--- /dev/null
+++ b/src/vpncmgr/Server.ico
Binary files differ
diff --git a/src/vpncmgr/Server_Offline.ico b/src/vpncmgr/Server_Offline.ico
new file mode 100644
index 00000000..86cdc0e2
--- /dev/null
+++ b/src/vpncmgr/Server_Offline.ico
Binary files differ
diff --git a/src/vpncmgr/VPN.ico b/src/vpncmgr/VPN.ico
new file mode 100644
index 00000000..b366131e
--- /dev/null
+++ b/src/vpncmgr/VPN.ico
Binary files differ
diff --git a/src/vpncmgr/resource.h b/src/vpncmgr/resource.h
new file mode 100644
index 00000000..198603e5
--- /dev/null
+++ b/src/vpncmgr/resource.h
@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpncmgr.rc
+//
+#define IDI_ICON1 101
+#define IDI_VPN 101
+#define IDI_ICON2 102
+#define IDI_SERVER 102
+#define IDI_ICON3 103
+#define IDI_SERVER_OFF 103
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpncmgr/vpncmgr.c b/src/vpncmgr/vpncmgr.c
new file mode 100644
index 00000000..97a4a634
--- /dev/null
+++ b/src/vpncmgr/vpncmgr.c
@@ -0,0 +1,126 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncmgr.c
+// VPN Client connection manager program
+
+#include <GlobalConst.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+
+
+// WinMain function
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ InitMayaqua(false, false, 0, NULL);
+ InitCedar();
+
+
+ //Set Application ID
+ //if(JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM) != S_OK)
+ {
+ }
+
+ CMExec();
+ FreeCedar();
+ FreeMayaqua();
+ return 0;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpncmgr/vpncmgr.rc b/src/vpncmgr/vpncmgr.rc
new file mode 100644
index 00000000..e7e8933f
--- /dev/null
+++ b/src/vpncmgr/vpncmgr.rc
@@ -0,0 +1,74 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_VPN ICON "VPN.ico"
+IDI_SERVER ICON "Server.ico"
+IDI_SERVER_OFF ICON "Server_Offline.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpncmgr/vpncmgr.vcproj b/src/vpncmgr/vpncmgr.vcproj
new file mode 100644
index 00000000..a71c8a7d
--- /dev/null
+++ b/src/vpncmgr/vpncmgr.vcproj
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpncmgr"
+ ProjectGUID="{92B04960-1AA9-4A7A-B75C-1403046F25B3}"
+ RootNamespace="vpncmgr"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmgr.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmgr_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmgr.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpncmgr_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpncmgr.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Server.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Server_Offline.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\VPN.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpncmgr.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpndrvinst/resource.h b/src/vpndrvinst/resource.h
new file mode 100644
index 00000000..e0df5b0d
--- /dev/null
+++ b/src/vpndrvinst/resource.h
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpndrvinst.rc
+//
+#define IDR_TEST1 101
+#define IDI_ICON1 102
+#define IDI_CERT 102
+#define IDI_ICON2 103
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpndrvinst/vpndrvinst.c b/src/vpndrvinst/vpndrvinst.c
new file mode 100644
index 00000000..0cf8680d
--- /dev/null
+++ b/src/vpndrvinst/vpndrvinst.c
@@ -0,0 +1,340 @@
+// SoftEther VPN Source Code
+// Hamster Test Code
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Ham.c
+// Hamster Test Program
+
+#include <GlobalConst.h>
+
+#define HAM_C
+
+#ifdef WIN32
+#define HAM_WIN32
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <windows.h>
+#include <DbgHelp.h>
+#include <Iphlpapi.h>
+#include <wtsapi32.h>
+#include "../pencore/resource.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <math.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "vpndrvinst.h"
+
+void disablevlan(UINT num, char **arg)
+{
+ bool ok;
+ if (num < 1)
+ {
+ return;
+ }
+
+ ok = MsDisableVLan(arg[0]);
+
+ if (ok == false)
+ {
+ _exit(1);
+ }
+ else
+ {
+ _exit(0);
+ }
+}
+
+void enablevlan(UINT num, char **arg)
+{
+ bool ok;
+ if (num < 1)
+ {
+ return;
+ }
+
+ ok = MsEnableVLan(arg[0]);
+
+ if (ok == false)
+ {
+ _exit(1);
+ }
+ else
+ {
+ _exit(0);
+ }
+}
+
+void instvlan(UINT num, char **arg)
+{
+ KAKUSHI *k = NULL;
+ MS_DRIVER_VER ver;
+ bool ok;
+ if (num < 1)
+ {
+ return;
+ }
+
+ InitWinUi(L"VPN", _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ if (MsIsNt())
+ {
+ k = InitKakushi();
+ }
+
+ CiInitDriverVerStruct(&ver);
+
+ ok = MsInstallVLan(VLAN_ADAPTER_NAME_TAG, VLAN_CONNECTION_NAME, arg[0], &ver);
+
+ FreeKakushi(k);
+
+ FreeWinUi();
+
+ if (ok == false)
+ {
+ _exit(1);
+ }
+ else
+ {
+ _exit(0);
+ }
+}
+
+void upgradevlan(UINT num, char **arg)
+{
+ bool ok;
+ KAKUSHI *k = NULL;
+ MS_DRIVER_VER ver;
+ if (num < 1)
+ {
+ return;
+ }
+
+ InitWinUi(L"VPN", _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
+
+ if (MsIsNt())
+ {
+ k = InitKakushi();
+ }
+
+ CiInitDriverVerStruct(&ver);
+
+ ok = MsUpgradeVLan(VLAN_ADAPTER_NAME_TAG, VLAN_CONNECTION_NAME, arg[0], &ver);
+
+ FreeKakushi(k);
+
+ FreeWinUi();
+
+ if (ok == false)
+ {
+ _exit(1);
+ }
+ else
+ {
+ _exit(0);
+ }
+}
+
+void uninstvlan(UINT num, char **arg)
+{
+ bool ok;
+ if (num < 1)
+ {
+ return;
+ }
+
+ ok = MsUninstallVLan(arg[0]);
+
+ if (ok == false)
+ {
+ _exit(1);
+ }
+ else
+ {
+ _exit(0);
+ }
+}
+
+TEST_LIST test_list[] =
+{
+ {"instvlan", instvlan},
+ {"uninstvlan", uninstvlan},
+ {"upgradevlan", upgradevlan},
+ {"enablevlan", enablevlan},
+ {"disablevlan", disablevlan},
+};
+
+// Main function
+void MainFunction(char *cmd)
+{
+ char tmp[MAX_SIZE];
+ bool first = true;
+ bool exit_now = false;
+
+ while (true)
+ {
+ if (first && StrLen(cmd) != 0 && g_memcheck == false)
+ {
+ first = false;
+ StrCpy(tmp, sizeof(tmp), cmd);
+ exit_now = true;
+ Print("%s\n", cmd);
+ }
+ else
+ {
+ _exit(0);
+ }
+ Trim(tmp);
+ if (StrLen(tmp) != 0)
+ {
+ UINT i, num;
+ bool b = false;
+ TOKEN_LIST *token = ParseCmdLine(tmp);
+ char *cmd = token->Token[0];
+
+ num = sizeof(test_list) / sizeof(TEST_LIST);
+ for (i = 0;i < num;i++)
+ {
+ if (!StrCmpi(test_list[i].command_str, cmd))
+ {
+ char **arg = Malloc(sizeof(char *) * (token->NumTokens - 1));
+ UINT j;
+ for (j = 0;j < token->NumTokens - 1;j++)
+ {
+ arg[j] = CopyStr(token->Token[j + 1]);
+ }
+ test_list[i].proc(token->NumTokens - 1, arg);
+ for (j = 0;j < token->NumTokens - 1;j++)
+ {
+ Free(arg[j]);
+ }
+ Free(arg);
+ b = true;
+ _exit(1);
+ break;
+ }
+ }
+ FreeToken(token);
+
+ if (exit_now)
+ {
+ break;
+ }
+ }
+ }
+}
+
+// winmain function
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ InitMayaqua(false, false, 0, NULL);
+ EnableProbe(false);
+ InitCedar();
+ SetHamMode();
+ MainFunction(cmdline);
+ FreeCedar();
+ FreeMayaqua();
+
+ return 0;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpndrvinst/vpndrvinst.h b/src/vpndrvinst/vpndrvinst.h
new file mode 100644
index 00000000..bece8a58
--- /dev/null
+++ b/src/vpndrvinst/vpndrvinst.h
@@ -0,0 +1,108 @@
+// SoftEther VPN Source Code
+// Hamster Test Code
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Ham.h
+// Header file of Ham.c
+
+
+// List of test functions
+typedef void (TEST_PROC)(UINT num, char **arg);
+
+typedef struct TEST_LIST
+{
+ char *command_str;
+ TEST_PROC *proc;
+} TEST_LIST;
+
+// function prototypes
+void disablevlan(UINT num, char **arg);
+void enablevlan(UINT num, char **arg);
+void instvlan(UINT num, char **arg);
+void upgradevlan(UINT num, char **arg);
+void uninstvlan(UINT num, char **arg);
+
+void MainFunction(char *cmd);
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow);
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpndrvinst/vpndrvinst.ico b/src/vpndrvinst/vpndrvinst.ico
new file mode 100644
index 00000000..0310b265
--- /dev/null
+++ b/src/vpndrvinst/vpndrvinst.ico
Binary files differ
diff --git a/src/vpndrvinst/vpndrvinst.rc b/src/vpndrvinst/vpndrvinst.rc
new file mode 100644
index 00000000..deedb19b
--- /dev/null
+++ b/src/vpndrvinst/vpndrvinst.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON2 ICON "vpndrvinst.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpndrvinst/vpndrvinst.vcproj b/src/vpndrvinst/vpndrvinst.vcproj
new file mode 100644
index 00000000..26f24cb3
--- /dev/null
+++ b/src/vpndrvinst/vpndrvinst.vcproj
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpndrvinst"
+ ProjectGUID="{CF2B20BF-9799-40EF-A987-9E4C25E68E1C}"
+ RootNamespace="vpndrvinst"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\driver_installer.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ IgnoreAllDefaultLibraries="false"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="1"
+ Profile="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_admin.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir);$(SolutionDir)Mayaqua"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\driver_installer_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ IgnoreAllDefaultLibraries="false"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="2"
+ TargetMachine="17"
+ Profile="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_admin.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpndrvinst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpndrvinst.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpndrvinst.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpndrvinst.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpninstall/resource.h b/src/vpninstall/resource.h
new file mode 100644
index 00000000..2d22abfa
--- /dev/null
+++ b/src/vpninstall/resource.h
@@ -0,0 +1,86 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpninstall.rc
+//
+#define IDI_ICON1 101
+#define IDI_MAIN 101
+#define IDS_STRING102 102
+#define IDS_TITLE 102
+#define IDS_FONT 103
+#define IDS_FONT_SIZE 104
+#define IDS_INF_LOAD_FAILED 105
+#define IDS_DIFF_CPU 106
+#define IDS_INSTANCE_EXISTS 107
+#define IDS_BAD_OS 108
+#define IDS_CPU_NOT_SUPPORTED 109
+#define IDS_DOWNLOADING 110
+#define IDS_DOWNLOADSTART 111
+#define IDS_TEMP_ERROR 112
+#define IDS_DOWNLOAD_ERROR 113
+#define IDS_DOWNLOADING2 114
+#define IDS_DOWNLOADING3 115
+#define IDS_INSTALLSTART 116
+#define IDS_INSTALLSTART_ERROR 117
+#define IDS_SECURITY_ERROR 118
+#define IDS_SIGN_WARNING 119
+#define IDS_SIGN_WARNING_TITLE 120
+#define IDS_TITLE_VPNSMGR 121
+#define IDS_VPNSMGR_EXEC_ERROR 122
+#define IDS_DLG_TITLE 123
+#define IDS_INSTALL_DLG__STATUS_INIT 124
+#define IDS_INSTALL_CANCEL 125
+#define IDS_EULA_NOTICE1 126
+#define IDS_EULA_NOTICE2 127
+#define IDS_EULA_NOTICE3 128
+#define IDS_EULA_AGREE 129
+#define IDS_EULA_DISAGREE 130
+#define S_TITLE 1001
+#define P_PROGRESS 1002
+#define S_STATUS 1003
+#define S_SIZEINFO 1005
+#define E_EULA 1006
+#define S_BOLD 1008
+#define S_EULA_NOTICE1 1009
+#define S_EULA_NOTICE3 1010
+#define IDS_TITLE_EN 1102
+#define IDS_FONT_EN 1103
+#define IDS_FONT_SIZE_EN 1104
+#define IDS_INF_LOAD_FAILED_EN 1105
+#define IDS_DIFF_CPU_EN 1106
+#define IDS_INSTANCE_EXISTS_EN 1107
+#define IDS_BAD_OS_EN 1108
+#define IDS_CPU_NOT_SUPPORTED_EN 1109
+#define IDS_DOWNLOADING_EN 1110
+#define IDS_DOWNLOADSTART_EN 1111
+#define IDS_TEMP_ERROR_EN 1112
+#define IDS_DOWNLOAD_ERROR_EN 1113
+#define IDS_DOWNLOADING2_EN 1114
+#define IDS_DOWNLOADING3_EN 1115
+#define IDS_INSTALLSTART_EN 1116
+#define IDS_INSTALLSTART_ERROR_EN 1117
+#define IDS_SECURITY_ERROR_EN 1118
+#define IDS_SIGN_WARNING_EN 1119
+#define IDS_SIGN_WARNING_TITLE_EN 1120
+#define IDS_TITLE_VPNSMGR_EN 1121
+#define IDS_VPNSMGR_EXEC_ERROR_EN 1122
+#define IDS_DLG_TITLE_EN 1123
+#define IDS_INSTALL_DLG__STATUS_INIT_EN 1124
+#define IDS_INSTALL_CANCEL_EN 1125
+#define IDS_EULA_NOTICE1_EN 1126
+#define IDS_EULA_NOTICE2_EN 1127
+#define IDS_EULA_NOTICE3_EN 1128
+#define IDS_EULA_AGREE_EN 1129
+#define IDS_EULA_DISAGREE_EN 1130
+#define D_INSTALL 2007
+#define D_EULA 2008
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 123
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1011
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpninstall/vpninstall.c b/src/vpninstall/vpninstall.c
new file mode 100644
index 00000000..4fe8fb3a
--- /dev/null
+++ b/src/vpninstall/vpninstall.c
@@ -0,0 +1,1639 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpninstall.c
+// VPN Client Web Installer Bootstrap
+
+#include <GlobalConst.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Msiquery.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+#include "vpninstall.h"
+#include "resource.h"
+
+#pragma comment(lib, "wininet.lib")
+
+static bool is_debug = true;
+static LIST *string_table = NULL;
+static VI_SETTING setting;
+static bool sleep_before_exit = false;
+static int skip = 0;
+
+// Convert the URL to the file name
+char *ViUrlToFileName(char *url)
+{
+ UINT i, len;
+ char *ret = url;
+ bool b = true;
+ len = lstrlen(url);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = url[i];
+
+ if (c == '?' || c == '#')
+ {
+ b = false;
+ }
+
+ if (b)
+ {
+ if (c == '/' || c == '\\')
+ {
+ if (lstrlen(url + i + 1) > 1)
+ {
+ ret = url + i + 1;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Check the signature of the EXE file, and displays a warning if dangerous
+bool ViCheckExeSign(HWND hWnd, wchar_t *exew)
+{
+ wchar_t tmp[2048];
+ bool danger = true;
+ wchar_t *warningMessage = _U(IDS_SIGN_WARNING+skip);
+ wchar_t *warningMessageTitle = _U(IDS_SIGN_WARNING_TITLE+skip);
+ // Validate arguments
+ if (hWnd == NULL || exew == NULL)
+ {
+ return false;
+ }
+
+ if (MsCheckFileDigitalSignatureW(hWnd, exew, &danger))
+ {
+ if (danger == false)
+ {
+ // Safe
+ return true;
+ }
+ else
+ {
+ wchar_t filename[MAX_PATH];
+
+ GetFileNameFromFilePathW(filename, sizeof(filename), exew);
+
+ // Show the message because there is potentially dangerous
+ swprintf(tmp, sizeof(tmp) / 2, warningMessage,
+ filename, filename, filename);
+
+ if (MessageBoxW(hWnd, tmp, warningMessageTitle,
+ MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION) == IDOK)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+ else
+ {
+ // Danger
+ return false;
+ }
+}
+
+// Start the installation process
+void ViInstallProcessStart(HWND hWnd, VI_INSTALL_DLG *d)
+{
+ wchar_t *exew;
+ bool ok;
+ char instdir[MAX_PATH];
+ char hamcore[MAX_PATH];
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ ViGenerateVpnSMgrTempDirName(instdir, sizeof(instdir), ViGetSuitableArchForCpu()->Build);
+ ConbinePath(hamcore, sizeof(hamcore), instdir, "hamcore.se2");
+
+ exew = setting.DownloadedInstallerPathW;
+ d->NoClose = true;
+
+ Hide(hWnd, IDCANCEL);
+ SetPos(hWnd, P_PROGRESS, 100);
+ Hide(hWnd, P_PROGRESS);
+ Hide(hWnd, S_SIZEINFO);
+ SetText(hWnd, S_STATUS, _U(IDS_INSTALLSTART+skip));
+
+ ok = true;
+
+ if (setting.DownloadNotRequired == false)
+ {
+ if (setting.WebMode && ViCheckExeSign(hWnd, exew) == false)
+ {
+ // The digital signature is not reliable
+ ok = false;
+ }
+ else
+ {
+ // Installation
+ HANDLE hProcess;
+ SHELLEXECUTEINFOW info;
+
+ // Run
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = L"open";
+ info.lpFile = exew;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = L"/HIDESTARTCOMMAND:1 /DISABLEAUTOIMPORT:1 /ISWEBINSTALLER:1";
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteExW(&info) == false)
+ {
+ MsgBox(hWnd, MB_ICONSTOP, _U(IDS_INSTALLSTART_ERROR+skip));
+ ok = false;
+ }
+ else
+ {
+ hProcess = info.hProcess;
+
+ // Wait for the install process to complete
+ while (true)
+ {
+ if (WaitForSingleObject(hProcess, 50) != WAIT_TIMEOUT)
+ {
+ break;
+ }
+
+ DoEvents(hWnd);
+ }
+ CloseHandle(hProcess);
+ }
+ }
+ }
+
+ if (ok && d->WindowsShutdowning == false)
+ {
+ VI_SETTING_ARCH *a = ViGetSuitableArchForCpu();
+ wchar_t arg[MAX_PATH];
+ wchar_t exe[MAX_PATH];
+ char *arg1 = "/easy";
+ // Hide the screen
+ Hide(hWnd, 0);
+
+ if (setting.NormalMode)
+ {
+ arg1 = "/normal";
+ }
+
+ // (Just in case) start the VPN Client service
+ if (MsIsServiceRunning("vpnclient") == false)
+ {
+ MsStartService("vpnclient");
+ }
+
+ // Wait for that the service becomes available
+ SwWaitForVpnClientPortReady(0);
+
+ if (UniIsEmptyStr(setting.DownloadedSettingPathW) == false)
+ {
+ // Start a connection by importing the configuration file into the VPN Client
+ UniFormat(arg, sizeof(arg), L"%S \"%s\"", arg1, setting.DownloadedSettingPathW);
+ }
+ else
+ {
+ // Just start the Connection Manager
+ UniFormat(arg, sizeof(arg), L"%S", arg1);
+ }
+
+ // Get the installation state
+ ViLoadCurrentInstalledStatusForArch(a);
+
+ if (a->CurrentInstalled)
+ {
+ HANDLE h;
+ wchar_t filename[MAX_PATH];
+
+ StrToUni(filename, sizeof(filename), a->VpnCMgrExeFileName);
+
+ ConbinePathW(exe, sizeof(exe), a->CurrentInstalledPathW, filename);
+
+ // Start the Connection Manager
+ h = MsRunAsUserExW(exe, arg, false);
+ if (h != NULL)
+ {
+ if (UniIsEmptyStr(setting.DownloadedSettingPathW) == false)
+ {
+ sleep_before_exit = true;
+ }
+
+ CloseHandle(h);
+ }
+ }
+ }
+
+ d->NoClose = false;
+ Close(hWnd);
+}
+
+// End User License Agreement dialog
+UINT ViEulaDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ wchar_t *text = (wchar_t *)param;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ SetText(hWnd, 0, _U(IDS_DLG_TITLE+skip));
+ SetText(hWnd, S_EULA_NOTICE1, _U(IDS_EULA_NOTICE1+skip));
+ SetText(hWnd, S_BOLD, _U(IDS_EULA_NOTICE2+skip));
+ SetText(hWnd, S_EULA_NOTICE3, _U(IDS_EULA_NOTICE3+skip));
+ SetText(hWnd, IDOK, _U(IDS_EULA_AGREE+skip));
+ SetText(hWnd, IDCANCEL, _U(IDS_EULA_DISAGREE+skip));
+
+ DlgFont(hWnd, S_BOLD, 0, true);
+ SetText(hWnd, E_EULA, text);
+ Focus(hWnd, E_EULA);
+ SendMsg(hWnd, E_EULA, EM_SETSEL, 0, 0);
+ Center(hWnd);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog(hWnd, 1);
+ break;
+
+ case IDCANCEL:
+ Close(hWnd);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd, 0);
+ break;
+ }
+
+ return 0;
+}
+
+// Display the End User License Agreement
+bool ViEulaDlg(HWND hWnd, wchar_t *text)
+{
+ // Validate arguments
+ if (text == NULL)
+ {
+ return false;
+ }
+
+ if (Dialog(hWnd, D_EULA, ViEulaDlgProc, text) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Extract the license agreement from the EXE file
+wchar_t *ViExtractEula(char *exe)
+{
+ BUF *b;
+ UINT tmp_size;
+ char *tmp;
+ wchar_t *ret;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return false;
+ }
+
+ b = ViExtractResource(exe, RT_RCDATA, "LICENSE");
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = b->Size + 1;
+ tmp = ZeroMalloc(tmp_size);
+
+ Copy(tmp, b->Buf, b->Size);
+ FreeBuf(b);
+
+ ret = CopyStrToUni(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Extract the Cabinet file from the EXE file
+bool ViExtractCabinetFile(char *exe, char *cab)
+{
+ BUF *b;
+ // Validate arguments
+ if (exe == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ b = ViExtractResource(exe, RT_RCDATA, "CABINET");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBuf(b, cab) == false)
+ {
+ FreeBuf(b);
+
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Extract the resource from the EXE file
+BUF *ViExtractResource(char *exe, char *type, char *name)
+{
+ HINSTANCE h;
+ HRSRC hr;
+ HGLOBAL hg;
+ UINT size;
+ void *data;
+ BUF *buf;
+ // Validate arguments
+ if (exe == NULL || type == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ hr = FindResourceA(h, name, type);
+ if (hr == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ hg = LoadResource(h, hr);
+ if (hg == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ size = SizeofResource(h, hr);
+ data = (void *)LockResource(hg);
+
+ buf = NewBuf();
+ WriteBuf(buf, data, size);
+
+ FreeResource(hg);
+ FreeLibrary(h);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Open the file
+VI_FILE *ViOpenFile(char *path)
+{
+ VI_FILE *f;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return NULL;
+ }
+
+ if (ViIsInternetFile(path))
+ {
+ HINTERNET hHttpFile;
+ HINTERNET hInternet = InternetOpenA(DEFAULT_USER_AGENT,
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL, NULL, 0);
+ UINT size;
+ UINT sizesize;
+
+ if (hInternet == NULL)
+ {
+ return NULL;
+ }
+
+ hHttpFile = InternetOpenUrlA(hInternet, path, NULL, 0,
+ INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0);
+
+ if (hHttpFile == NULL)
+ {
+ InternetCloseHandle(hInternet);
+ return NULL;
+ }
+
+ size = 0;
+ sizesize = sizeof(size);
+
+ if (StartWith(path, "ftp://"))
+ {
+ // ftp
+ DWORD high = 0;
+
+ size = FtpGetFileSize(hHttpFile, &high);
+ }
+ else
+ {
+ UINT errorcode = 0;
+ UINT errorcode_size = sizeof(errorcode);
+
+ // http
+ if (HttpQueryInfo(hHttpFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
+ &size, &sizesize, NULL) == false)
+ {
+ size = 0;
+ }
+
+ if (HttpQueryInfo(hHttpFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
+ &errorcode, &errorcode_size, NULL) == false ||
+ (errorcode / 100) != 2)
+ {
+ // HTTP getting error
+ InternetCloseHandle(hInternet);
+ InternetCloseHandle(hHttpFile);
+ return NULL;
+ }
+ }
+
+ f = ZeroMalloc(sizeof(VI_FILE));
+ f->InternetFile = true;
+ f->hInternet = hInternet;
+ f->hHttpFile = hHttpFile;
+ f->FileSize = size;
+
+ return f;
+ }
+ else
+ {
+ IO *io;
+ char fullpath[MAX_PATH];
+ char exedir[MAX_PATH];
+
+ GetExeDir(exedir, sizeof(exedir));
+
+ ConbinePath(fullpath, sizeof(fullpath), exedir, path);
+
+ io = FileOpen(fullpath, false);
+ if (io == NULL)
+ {
+ return NULL;
+ }
+
+ f = ZeroMalloc(sizeof(VI_FILE));
+ f->InternetFile = false;
+ f->FileSize = FileSize(io);
+ f->io = io;
+
+ return f;
+ }
+}
+
+// Get the file size
+UINT ViGetFileSize(VI_FILE *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ return f->FileSize;
+}
+
+// Read from the file
+UINT ViReadFile(VI_FILE *f, void *buf, UINT size)
+{
+ // Validate arguments
+ if (f == NULL || buf == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (f->InternetFile == false)
+ {
+ UINT readsize = MIN(size, f->FileSize - f->IoReadFileSize);
+ bool ret;
+
+ if (readsize == 0)
+ {
+ return 0;
+ }
+
+ ret = FileRead(f->io, buf, readsize);
+
+ if (ret == false)
+ {
+ return INFINITE;
+ }
+
+ f->IoReadFileSize += readsize;
+
+ return readsize;
+ }
+ else
+ {
+ UINT readsize = 0;
+
+ if (InternetReadFile(f->hHttpFile, buf, size, &readsize) == false)
+ {
+ return INFINITE;
+ }
+
+ return readsize;
+ }
+}
+
+// Close the file
+void ViCloseFile(VI_FILE *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ if (f->InternetFile == false)
+ {
+ FileClose(f->io);
+ }
+ else
+ {
+ InternetCloseHandle(f->hHttpFile);
+ InternetCloseHandle(f->hInternet);
+ }
+
+ Free(f);
+}
+
+// Determine whether the specified file name is the file on the Internet
+bool ViIsInternetFile(char *path)
+{
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ if (StartWith(path, "http://") || StartWith(path, "https://") || StartWith(path, "ftp://"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Installer dialog initialization
+void ViInstallDlgOnInit(HWND hWnd, VI_INSTALL_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ d->hWnd = hWnd;
+
+ SetIcon(hWnd, 0, IDI_MAIN);
+
+ SetText(hWnd, 0, _U(IDS_DLG_TITLE+skip));
+ SetText(hWnd, S_TITLE, _U(IDS_DLG_TITLE+skip));
+
+ SetText(hWnd, S_STATUS, _U(IDS_INSTALL_DLG__STATUS_INIT+skip));
+ SetText(hWnd, IDCANCEL, _U(IDS_INSTALL_CANCEL+skip));
+
+ DlgFont(hWnd, S_TITLE+skip, 12, true);
+ SetRange(hWnd, P_PROGRESS, 0, 100);
+ SetPos(hWnd, P_PROGRESS, 0);
+
+ SetTimer(hWnd, 1, 22, NULL);
+}
+
+// Start the download thread
+void ViDownloadThreadStart(VI_INSTALL_DLG *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ d->DownloadStarted = true;
+ d->DownloadThread = NewThread(ViDownloadThread, d);
+}
+
+
+// Stop the download thread
+void ViDownloadThreadStop(VI_INSTALL_DLG *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ if (d->DownloadStarted == false)
+ {
+ return;
+ }
+
+ d->DownloadStarted = false;
+ d->Halt = true;
+
+ while (true)
+ {
+ if (WaitThread(d->DownloadThread, 50))
+ {
+ break;
+ }
+
+ DoEvents(NULL);
+ }
+
+ ReleaseThread(d->DownloadThread);
+}
+
+// Download thread
+void ViDownloadThread(THREAD *thread, void *param)
+{
+ VI_INSTALL_DLG *d;
+ VI_SETTING_ARCH *a;
+ HWND hWnd;
+ UINT num_files = 2;
+ VI_DOWNLOAD_FILE files[2];
+ VI_DOWNLOAD_FILE *f;
+ UINT i;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ d = (VI_INSTALL_DLG *)param;
+ hWnd = d->hWnd;
+
+ Zero(files, sizeof(files));
+
+ a = ViGetSuitableArchForCpu();
+
+ // File body
+ f = &files[0];
+ StrCpy(f->SrcPath, sizeof(f->SrcPath), a->Path);
+
+ // Configuration file
+ if (IsEmptyStr(setting.SettingPath) == false)
+ {
+ f = &files[1];
+ StrCpy(f->SrcPath, sizeof(f->SrcPath), setting.SettingPath);
+ }
+ else
+ {
+ // No configuration file
+ num_files = 1;
+ }
+
+ for (i = 0;i < num_files;i++)
+ {
+ bool b = true;
+
+ if (i == 0 && setting.DownloadNotRequired)
+ {
+ b = false;
+ }
+
+ if (b)
+ {
+ wchar_t tmp[MAX_SIZE];
+ IO *dest = NULL;
+ VI_FILE *down;
+ UINT ret;
+ UINT totalsize;
+ UINT currentsize;
+ wchar_t filename_w[MAX_PATH];
+
+ f = &files[i];
+ GetFileNameFromFilePath(f->FileName, sizeof(f->FileName), f->SrcPath);
+ MakeSafeFileName(f->FileName, sizeof(f->FileName), f->FileName);
+
+ StrToUni(filename_w, sizeof(filename_w), f->FileName);
+ ConbinePathW(f->DestPathW, sizeof(f->DestPathW), MsGetMyTempDirW(), filename_w);
+
+ ViInstallDlgSetPos(hWnd, 0);
+ UniFormat(tmp, sizeof(tmp), _U(IDS_DOWNLOADSTART+skip), f->FileName);
+ ViInstallDlgSetText(d, hWnd, S_STATUS, tmp);
+
+ down = ViOpenFile(f->SrcPath);
+ if (down == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _U(IDS_DOWNLOAD_ERROR+skip), f->FileName);
+
+ ViInstallDlgCancel(hWnd);
+ return;
+ }
+
+ dest = FileCreateW(f->DestPathW);
+ if (dest == NULL)
+ {
+ MsgBoxEx(hWnd, MB_ICONSTOP, _U(IDS_TEMP_ERROR+skip), f->DestPathW);
+
+ ViCloseFile(down);
+ ViInstallDlgCancel(hWnd);
+ return;
+ }
+
+ totalsize = ViGetFileSize(down);
+ currentsize = 0;
+
+ UniFormat(tmp, sizeof(tmp), _U(IDS_DOWNLOADING3+skip), f->FileName);
+ ViInstallDlgSetText(d, hWnd, S_STATUS, tmp);
+
+ while (true)
+ {
+ UINT pos = 0;
+
+ if (d->Halt)
+ {
+ // User cancel
+ FileClose(dest);
+ ViCloseFile(down);
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), _U(IDS_DOWNLOADING3+skip), f->FileName);
+
+ ViInstallDlgSetText(d, hWnd, IDS_DOWNLOADING3+skip, tmp);
+ ret = ViReadFile(down, d->Buf, d->BufSize);
+
+ if (ret == INFINITE)
+ {
+ // Communication error
+ MsgBoxEx(hWnd, MB_ICONSTOP, _U(IDS_DOWNLOAD_ERROR+skip), f->FileName);
+
+ FileClose(dest);
+ ViCloseFile(down);
+ ViInstallDlgCancel(hWnd);
+
+ return;
+ }
+
+ // Draw progress
+ currentsize += ret;
+
+ if (totalsize != 0)
+ {
+ UniFormat(tmp, sizeof(tmp), _U(IDS_DOWNLOADING+skip),
+ ((float)totalsize) / 1024.0f / 1024.0f,
+ ((float)currentsize) / 1024.0f / 1024.0f);
+
+ pos = (UINT)(((float)currentsize) * 100.0f / ((float)totalsize));
+ }
+ else
+ {
+ UniFormat(tmp, sizeof(tmp), _U(IDS_DOWNLOADING2+skip),
+ ((float)currentsize) / 1024.0f / 1024.0f);
+ pos = (UINT)(((float)currentsize) * 100.0f / (1024.0f * 1024.0f * 10.0f));
+ }
+
+ ViInstallDlgSetText(d, hWnd, S_SIZEINFO, tmp);
+ ViInstallDlgSetPos(hWnd, pos);
+
+ if (ret == 0)
+ {
+ // Download Complete
+ break;
+ }
+ else
+ {
+ FileWrite(dest, d->Buf, ret);
+ }
+ }
+
+ ViCloseFile(down);
+ FileClose(dest);
+ }
+ }
+
+ UniStrCpy(setting.DownloadedInstallerPathW, sizeof(setting.DownloadedInstallerPathW),
+ files[0].DestPathW);
+
+ if (num_files >= 2)
+ {
+ UniStrCpy(setting.DownloadedSettingPathW, sizeof(setting.DownloadedSettingPathW),
+ files[1].DestPathW);
+ }
+
+ PostMessageA(hWnd, WM_VI_DOWNLOAD_FINISHED, 0, 0);
+}
+
+// Operation of the progress bar
+void ViInstallDlgSetPos(HWND hWnd, UINT pos)
+{
+ PostMessage(hWnd, WM_VI_SETPOS, 0, pos);
+}
+
+// Set the text
+void ViInstallDlgSetText(VI_INSTALL_DLG *d, HWND hWnd, UINT id, wchar_t *text)
+{
+ DWORD value = 0;
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ if (d->Halt)
+ {
+ return;
+ }
+
+ SendMessageTimeout(hWnd, WM_VI_SETTEXT, id, (LPARAM)text, SMTO_BLOCK, 200, &value);
+}
+
+// Cancel
+void ViInstallDlgCancel(HWND hWnd)
+{
+ PostMessageA(hWnd, WM_VI_CANCEL, 0, 0);
+}
+
+// Installer operation start
+void ViInstallDlgOnStart(HWND hWnd, VI_INSTALL_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ // Start the download thread
+ ViDownloadThreadStart(d);
+}
+
+// Cancel the installation
+void ViInstallDlgOnClose(HWND hWnd, VI_INSTALL_DLG *d)
+{
+ // Validate arguments
+ if (hWnd == NULL || d == NULL)
+ {
+ return;
+ }
+
+ if (d->DialogCanceling)
+ {
+ return;
+ }
+ if (d->NoClose)
+ {
+ return;
+ }
+
+ d->DialogCanceling = true;
+
+ // Disable the cancel button
+ Disable(hWnd, IDCANCEL);
+
+ // Stop the download thread if it runs
+ ViDownloadThreadStop(d);
+
+ // Exit the dialog
+ EndDialog(hWnd, 0);
+}
+
+// Installer procedure
+UINT ViInstallDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
+{
+ VI_INSTALL_DLG *d = (VI_INSTALL_DLG *)param;
+ UINT pos;
+ wchar_t *text;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ViInstallDlgOnInit(hWnd, param);
+ break;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ ViInstallDlgOnStart(hWnd, d);
+ break;
+ }
+ break;
+
+ case WM_VI_SETPOS:
+ // Setting the progress bar
+ pos = (UINT)lParam;
+ SetPos(hWnd, P_PROGRESS, MAKESURE(pos, 0, 100));
+ break;
+
+ case WM_VI_SETTEXT:
+ // Set the string
+ text = (wchar_t *)lParam;
+ SetText(hWnd, (UINT)wParam, text);
+ break;
+
+ case WM_VI_CANCEL:
+ // There was a cancellation from the thread side
+ ViInstallDlgOnClose(hWnd, d);
+ break;
+
+ case WM_VI_DOWNLOAD_FINISHED:
+ // Download Complete
+ ViInstallProcessStart(hWnd, d);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ ViInstallDlgOnClose(hWnd, d);
+ break;
+ }
+ break;
+
+ case WM_QUERYENDSESSION:
+ d->WindowsShutdowning = true;
+ break;
+
+ case WM_CLOSE:
+ break;
+ }
+
+ return 0;
+}
+
+// Show the dialog
+void ViInstallDlg()
+{
+ VI_INSTALL_DLG d;
+
+ Zero(&d, sizeof(d));
+
+ d.BufSize = 65535;
+ d.Buf = Malloc(d.BufSize);
+
+ Dialog(NULL, D_INSTALL, ViInstallDlgProc, &d);
+
+ Free(d.Buf);
+}
+
+// Read the inf file from the buffer
+bool ViLoadInfFromBuf(VI_SETTING *set, BUF *buf)
+{
+ bool ret;
+ if (set == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(set, sizeof(VI_SETTING));
+
+ SeekBuf(buf, 0, 0);
+ while (true)
+ {
+ char *tmp = CfgReadNextLine(buf);
+ TOKEN_LIST *tokens;
+
+ if (tmp == NULL)
+ {
+ break;
+ }
+
+ tokens = ParseToken(tmp, " \t");
+
+ if (tokens != NULL)
+ {
+ if (tokens->NumTokens >= 2)
+ {
+ if (StartWith(tokens->Token[0], "#") == false
+ || StartWith(tokens->Token[0], "//") == false)
+ {
+ char *name, *value;
+ name = tokens->Token[0];
+ value = tokens->Token[1];
+
+ if (StrCmpi(name, "VpnInstallBuild") == 0)
+ {
+ set->VpnInstallBuild = ToInt(value);
+ }
+ else if (StrCmpi(name, "NormalMode") == 0)
+ {
+ set->NormalMode = ToBool(value);
+ }
+ else if (StrCmpi(name, "VpnSettingPath") == 0)
+ {
+ StrCpy(set->SettingPath, sizeof(set->SettingPath), value);
+ }
+ else if (StrCmpi(name, "VpnClientBuild") == 0)
+ {
+ set->x86.Build = ToInt(value);
+ }
+ else if (StrCmpi(name, "VpnClientPath") == 0)
+ {
+ StrCpy(set->x86.Path, sizeof(set->x86.Path), value);
+ }
+ }
+ }
+ FreeToken(tokens);
+ }
+
+ Free(tmp);
+ }
+
+ ret = false;
+
+ StrCpy(set->x86.VpnCMgrExeFileName, sizeof(set->x86.VpnCMgrExeFileName), (MsIsX64() ? "vpncmgr_x64.exe" : "vpncmgr.exe"));
+
+ if (set->VpnInstallBuild != 0)
+ {
+ if (set->x86.Build != 0 && IsEmptyStr(set->x86.Path) == false)
+ {
+ set->x86.Supported = true;
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Read the inf file
+bool ViLoadInf(VI_SETTING *set, char *filename)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (set == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = ViLoadInfFromBuf(set, b);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the product information from the Msi
+bool ViMsiGetProductInfo(char *product_code, char *name, char *buf, UINT size)
+{
+ UINT ret;
+ char tmp[MAX_SIZE];
+ DWORD sz;
+ // Validate arguments
+ if (product_code == NULL || name == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ sz = sizeof(tmp);
+
+ ret = MsiGetProductInfoA(product_code, name, tmp, &sz);
+ if (ret != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ StrCpy(buf, size, tmp);
+
+ return true;
+}
+
+// Extract the build number from the version string
+UINT ViVersionStrToBuild(char *str)
+{
+ TOKEN_LIST *t;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ t = ParseToken(str, ".");
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+
+ if (t->NumTokens == 3)
+ {
+ ret = ToInt(t->Token[2]);
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Get the current installation state for the given architecture
+void ViLoadCurrentInstalledStatusForArch(VI_SETTING_ARCH *a)
+{
+ char tmp[MAX_SIZE];
+ UINT build;
+ wchar_t *dir;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+ if (a->Supported == false)
+ {
+ // Unsupported
+ return;
+ }
+
+ // Read from the registry
+ Format(tmp, sizeof(tmp), "%s\\%s", SW_REG_KEY, "vpnclient");
+
+ build = MsRegReadIntEx2(REG_LOCAL_MACHINE, tmp, "InstalledBuild", false, true);
+
+ dir = MsRegReadStrEx2W(REG_LOCAL_MACHINE, tmp, "InstalledDir", false, true);
+
+ if (build == 0 || UniIsEmptyStr(dir))
+ {
+ // Not installed
+ a->CurrentInstalled = false;
+ }
+ else
+ {
+ // Installed
+ a->CurrentInstalled = true;
+ a->CurrentInstalledBuild = build;
+
+ UniStrCpy(a->CurrentInstalledPathW, sizeof(a->CurrentInstalledPathW), dir);
+ }
+
+ Free(dir);
+}
+
+// Get the best architecture for the current CPU
+VI_SETTING_ARCH *ViGetSuitableArchForCpu()
+{
+ return &setting.x86;
+}
+
+// Get the current installation state
+void ViLoadCurrentInstalledStates()
+{
+ ViLoadCurrentInstalledStatusForArch(&setting.x86);
+}
+
+// Main process
+void ViMain()
+{
+ char tmp[MAX_PATH];
+ UINT ostype = GetOsInfo()->OsType;
+ VI_SETTING_ARCH *suitable;
+ TOKEN_LIST *t;
+ UINT i;
+
+ if (OS_IS_WINDOWS_NT(ostype) == false ||
+ GET_KETA(ostype, 100) <= 1)
+ {
+ // The OS is too old
+ MsgBox(NULL, MB_ICONEXCLAMATION, _U(IDS_BAD_OS+skip));
+ return;
+ }
+
+ Zero(&setting, sizeof(setting));
+
+ // Read the inf file
+ Format(tmp, sizeof(tmp), "%s\\%s", MsGetExeDirName(), VI_INF_FILENAME);
+ if (ViLoadInf(&setting, tmp) == false)
+ {
+ // Failure
+ MsgBoxEx(NULL, MB_ICONSTOP, _U(IDS_INF_LOAD_FAILED+skip), VI_INF_FILENAME);
+ return;
+ }
+
+ ViSetSkip();
+
+ // Parse the command line options
+ t = GetCommandLineToken();
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (IsEmptyStr(s) == false)
+ {
+ if (StartWith(s, "/") || StartWith(s, "-"))
+ {
+ if (StrCmpi(&s[1], "web") == 0)
+ {
+ setting.WebMode = true;
+ }
+ }
+ else
+ {
+ StrCpy(setting.SettingPath, sizeof(setting.SettingPath), s);
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ suitable = ViGetSuitableArchForCpu();
+
+ // Security check
+ if (setting.WebMode)
+ {
+ bool ok = true;
+
+ if (ViIsInternetFile(suitable->Path) == false)
+ {
+ ok = false;
+ }
+
+ if (IsEmptyStr(setting.SettingPath) == false)
+ {
+ if (ViIsInternetFile(setting.SettingPath) == false)
+ {
+ ok = false;
+ }
+ }
+
+ if (ok == false)
+ {
+ // Security breach
+ MsgBox(NULL, MB_ICONEXCLAMATION, _U(IDS_SECURITY_ERROR+skip));
+ return;
+ }
+ }
+
+ // Get the current installation state
+ ViLoadCurrentInstalledStates();
+
+ if (suitable->Supported == false)
+ {
+ // This CPU isn't supported
+ MsgBox(NULL, MB_ICONEXCLAMATION, _U(IDS_CPU_NOT_SUPPORTED+skip));
+ return;
+ }
+
+ if (suitable->CurrentInstalled && suitable->Build <= suitable->CurrentInstalledBuild)
+ {
+ // Do not download client software since it has already been installed
+ setting.DownloadNotRequired = true;
+ }
+
+ // Show the dialog
+ ViInstallDlg();
+}
+
+// Generate the temporary directory name for vpnsmgr
+void ViGenerateVpnSMgrTempDirName(char *name, UINT size, UINT build)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Format(name, size, "%s\\px_" GC_SW_SOFTETHER_PREFIX "vpnsmgr_%u", MsGetTempDir(), build);
+}
+
+// Compare the string resources
+int ViCompareString(void *p1, void *p2)
+{
+ VI_STRING *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ s1 = *(VI_STRING **)p1;
+ s2 = *(VI_STRING **)p2;
+
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ if (s1->Id > s2->Id)
+ {
+ return 1;
+ }
+ else if (s1->Id < s2->Id)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Reading a string resource
+wchar_t *ViLoadString(HINSTANCE hInst, UINT id)
+{
+ wchar_t *ret = NULL;
+
+ if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
+ {
+ char *a = ViLoadStringA(hInst, id);
+ if (a != NULL)
+ {
+ ret = CopyStrToUni(a);
+ Free(a);
+ }
+ }
+ else
+ {
+ UINT tmp_size = 60000;
+ wchar_t *tmp = Malloc(tmp_size);
+
+ if (LoadStringW(hInst, id, tmp, tmp_size) != 0)
+ {
+ ret = CopyUniStr(tmp);
+ }
+
+ Free(tmp);
+ }
+
+ return ret;
+}
+char *ViLoadStringA(HINSTANCE hInst, UINT id)
+{
+ UINT tmp_size = 60000;
+ char *tmp = Malloc(tmp_size);
+ char *ret = NULL;
+
+ if (LoadStringA(hInst, id, tmp, tmp_size) != 0)
+ {
+ ret = CopyStr(tmp);
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Acquisition of string
+wchar_t *ViGetString(UINT id)
+{
+ VI_STRING t, *s;
+ wchar_t *ret = NULL;
+
+ Zero(&t, sizeof(t));
+ t.Id = id;
+
+ LockList(string_table);
+ {
+ s = Search(string_table, &t);
+
+ if (s != NULL)
+ {
+ ret = s->String;
+ }
+ }
+ UnlockList(string_table);
+
+ return ret;
+}
+char *ViGetStringA(UINT id)
+{
+ VI_STRING t, *s;
+ char *ret = NULL;
+
+ Zero(&t, sizeof(t));
+ t.Id = id;
+
+ LockList(string_table);
+ {
+ s = Search(string_table, &t);
+
+ if (s != NULL)
+ {
+ ret = s->StringA;
+ }
+ }
+ UnlockList(string_table);
+
+ return ret;
+}
+
+// Calculate the difference between the the current language configuration and the base of the string table
+void ViSetSkip()
+{
+ skip = 0;
+
+ if (MsIsCurrentUserLocaleIdJapanese() == false)
+ {
+ skip = MESSAGE_OFFSET_EN - MESSAGE_OFFSET_JP;
+ }
+}
+
+// Read the string table
+void ViLoadStringTables()
+{
+ UINT i, n;
+ HINSTANCE hInst = GetModuleHandle(NULL);
+
+ string_table = NewList(ViCompareString);
+
+ n = 0;
+ for (i = 1;;i++)
+ {
+ wchar_t *str = ViLoadString(hInst, i);
+ if (str != NULL)
+ {
+ VI_STRING *s;
+ n = 0;
+
+ s = ZeroMalloc(sizeof(VI_STRING));
+ s->Id = i;
+ s->String = str;
+ s->StringA = CopyUniToStr(str);
+
+ Insert(string_table, s);
+ }
+ else
+ {
+ n++;
+ if (n >= 1500)
+ {
+ break;
+ }
+ }
+ }
+}
+
+// Release the string table
+void ViFreeStringTables()
+{
+ UINT i;
+ if (string_table == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(string_table);i++)
+ {
+ VI_STRING *s = LIST_DATA(string_table, i);
+
+ Free(s->String);
+ Free(s->StringA);
+ Free(s);
+ }
+
+ ReleaseList(string_table);
+ string_table = NULL;
+}
+
+// WinMain function
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ INSTANCE *instance;
+ is_debug = false;
+ MayaquaMinimalMode();
+ InitMayaqua(false, is_debug, 0, NULL);
+ InitCedar();
+ ViSetSkip();
+ ViLoadStringTables();
+ InitWinUi(_U(IDS_TITLE+skip), _A(IDS_FONT+skip), ToInt(_A(IDS_FONT_SIZE+skip)));
+ instance = NewSingleInstance(VI_INSTANCE_NAME);
+ if (instance == NULL)
+ {
+ MsgBox(NULL, MB_ICONINFORMATION, _U(IDS_INSTANCE_EXISTS+skip));
+ }
+ else
+ {
+ ViMain();
+ FreeSingleInstance(instance);
+ if (sleep_before_exit)
+ {
+ SleepThread(60 * 1000);
+ }
+ }
+ FreeWinUi();
+ ViFreeStringTables();
+ FreeCedar();
+ FreeMayaqua();
+ return 0;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpninstall/vpninstall.h b/src/vpninstall/vpninstall.h
new file mode 100644
index 00000000..72348c82
--- /dev/null
+++ b/src/vpninstall/vpninstall.h
@@ -0,0 +1,212 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpninstall.h
+// Header of vpninstall.c
+
+#ifndef VPNINSTALL_H
+#define VPNINSTALL_H
+
+// Constants
+#define VI_INF_FILENAME "vpninstall.inf"
+#define VI_INSTANCE_NAME "VpnAutoInstaller"
+#define WM_VI_SETPOS (WM_APP + 41)
+#define WM_VI_SETTEXT (WM_APP + 42)
+#define WM_VI_CANCEL (WM_APP + 43)
+#define WM_VI_DOWNLOAD_FINISHED (WM_APP + 44)
+#define MESSAGE_OFFSET_JP IDS_TITLE
+#define MESSAGE_OFFSET_EN IDS_TITLE_EN
+
+// Macro
+#define _U(id) (ViGetString(id))
+#define _A(id) (ViGetStringA(id))
+
+
+// Type declaration
+typedef struct VI_STRING
+{
+ UINT Id;
+ wchar_t *String;
+ char *StringA;
+} VI_STRING;
+
+typedef struct VI_SETTING_ARCH
+{
+ bool Supported;
+ UINT Build;
+ char Path[MAX_SIZE];
+ char VpnCMgrExeFileName[MAX_PATH];
+ bool CurrentInstalled;
+ wchar_t CurrentInstalledPathW[MAX_PATH];
+ UINT CurrentInstalledBuild;
+} VI_SETTING_ARCH;
+
+typedef struct VI_SETTING
+{
+ UINT VpnInstallBuild;
+ VI_SETTING_ARCH x86;
+ char SettingPath[MAX_SIZE];
+ wchar_t DownloadedSettingPathW[MAX_PATH];
+ wchar_t DownloadedInstallerPathW[MAX_PATH];
+ bool DownloadNotRequired;
+ bool WebMode;
+ bool NormalMode;
+} VI_SETTING;
+
+typedef struct VI_INSTALL_DLG
+{
+ HWND hWnd;
+ bool DownloadStarted;
+ THREAD *DownloadThread;
+ bool DialogCanceling;
+ UINT BufSize;
+ void *Buf;
+ bool Halt;
+ bool NoClose;
+ bool WindowsShutdowning;
+} VI_INSTALL_DLG;
+
+typedef struct VI_FILE
+{
+ bool InternetFile;
+ UINT FileSize;
+ HINTERNET hInternet;
+ HINTERNET hHttpFile;
+ UINT IoReadFileSize;
+ IO *io;
+} VI_FILE;
+
+typedef struct VI_DOWNLOAD_FILE
+{
+ char SrcPath[MAX_SIZE];
+ char FileName[MAX_PATH];
+ wchar_t DestPathW[MAX_SIZE];
+} VI_DOWNLOAD_FILE;
+
+// Function prototype
+int main(int argc, char *argv[]);
+void ViLoadStringTables();
+void ViFreeStringTables();
+wchar_t *ViLoadString(HINSTANCE hInst, UINT id);
+char *ViLoadStringA(HINSTANCE hInst, UINT id);
+int ViCompareString(void *p1, void *p2);
+wchar_t *ViGetString(UINT id);
+char *ViGetStringA(UINT id);
+void ViMain();
+bool ViLoadInf(VI_SETTING *set, char *filename);
+bool ViLoadInfFromBuf(VI_SETTING *set, BUF *buf);
+void ViLoadCurrentInstalledStates();
+void ViLoadCurrentInstalledStatusForArch(VI_SETTING_ARCH *a);
+bool ViMsiGetProductInfo(char *product_code, char *name, char *buf, UINT size);
+UINT ViVersionStrToBuild(char *str);
+VI_SETTING_ARCH *ViGetSuitableArchForCpu();
+void ViInstallDlg();
+UINT ViInstallDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+void ViInstallDlgOnInit(HWND hWnd, VI_INSTALL_DLG *d);
+void ViInstallDlgOnStart(HWND hWnd, VI_INSTALL_DLG *d);
+void ViInstallDlgOnClose(HWND hWnd, VI_INSTALL_DLG *d);
+VI_FILE *ViOpenFile(char *path);
+UINT ViGetFileSize(VI_FILE *f);
+UINT ViReadFile(VI_FILE *f, void *buf, UINT size);
+void ViCloseFile(VI_FILE *f);
+bool ViIsInternetFile(char *path);
+void ViDownloadThreadStart(VI_INSTALL_DLG *d);
+void ViDownloadThreadStop(VI_INSTALL_DLG *d);
+void ViDownloadThread(THREAD *thread, void *param);
+void ViInstallDlgSetPos(HWND hWnd, UINT pos);
+void ViInstallDlgSetText(VI_INSTALL_DLG *d, HWND hWnd, UINT id,wchar_t *text);
+void ViInstallDlgCancel(HWND hWnd);
+void ViInstallProcessStart(HWND hWnd, VI_INSTALL_DLG *d);
+bool ViExtractCabinetFile(char *exe, char *cab);
+wchar_t *ViExtractEula(char *exe);
+BUF *ViExtractResource(char *exe, char *type, char *name);
+bool ViEulaDlg(HWND hWnd, wchar_t *text);
+UINT ViEulaDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
+bool ViCheckExeSign(HWND hWnd, wchar_t *exew);
+char *ViUrlToFileName(char *url);
+void ViGenerateVpnSMgrTempDirName(char *name, UINT size, UINT build);
+void ViSetSkip();
+
+#endif // VPNINSTALL_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpninstall/vpninstall.ico b/src/vpninstall/vpninstall.ico
new file mode 100644
index 00000000..7db8891a
--- /dev/null
+++ b/src/vpninstall/vpninstall.ico
Binary files differ
diff --git a/src/vpninstall/vpninstall.rc b/src/vpninstall/vpninstall.rc
new file mode 100644
index 00000000..0baf8281
--- /dev/null
+++ b/src/vpninstall/vpninstall.rc
@@ -0,0 +1,221 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAIN ICON "vpninstall.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+D_INSTALL DIALOGEX 0, 0, 311, 123
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ ICON IDI_MAIN,IDC_STATIC,7,7,20,20
+ LTEXT "VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA",S_TITLE,33,7,259,19,WS_TABSTOP
+ CONTROL "",P_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,55,297,14
+ LTEXT "‰Šú‰»’†...",S_STATUS,7,34,297,19
+ PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹(&C)",IDCANCEL,127,100,59,16
+ RTEXT "",S_SIZEINFO,165,74,139,12
+END
+
+D_EULA DIALOGEX 0, 0, 218, 216
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA"
+FONT 9, "MS UI Gothic", 400, 0, 0x80
+BEGIN
+ LTEXT "ŽŸ‚ÌŽg—p‹–‘øŒ_–ñ‘‚ð‚¨“Ç‚Ý‚­‚¾‚³‚¢BPageDown ƒL[‚ðŽg‚Á‚ăXƒNƒ[ƒ‹‚µ‚Ä‚­‚¾‚³‚¢B",S_EULA_NOTICE1,7,7,204,19
+ EDITTEXT E_EULA,7,27,204,115,ES_MULTILINE | ES_READONLY | ES_WANTRETURN | WS_VSCROLL
+ LTEXT "Žg—p‹–‘øŒ_–ñ‘‚É“¯ˆÓ‚³‚ê‚Ü‚·‚©?",S_BOLD,7,146,204,18
+ LTEXT "[“¯ˆÓ‚µ‚Ü‚¹‚ñ] ‚ðƒNƒŠƒbƒN‚·‚é‚ƃCƒ“ƒXƒg[ƒ‹‚𒆎~‚µ‚Ü‚·BƒCƒ“ƒXƒg[ƒ‹‚·‚é‚É‚ÍA‚±‚ÌŒ_–ñ‚É“¯ˆÓ‚µ‚Ä‚­‚¾‚³‚¢B",S_EULA_NOTICE3,7,165,204,26
+ DEFPUSHBUTTON "“¯ˆÓ‚µ‚Ü‚·(&A)",IDOK,95,192,56,17
+ PUSHBUTTON "“¯ˆÓ‚µ‚Ü‚¹‚ñ(&D)",IDCANCEL,155,192,56,17
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ D_INSTALL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 304
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 116
+ END
+
+ D_EULA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 211
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 209
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_TITLE "VPN ƒNƒ‰ƒCƒAƒ“ƒg Web ƒCƒ“ƒXƒg[ƒ‰"
+ IDS_FONT "MS UI Gothic"
+ IDS_FONT_SIZE "9"
+ IDS_INF_LOAD_FAILED "‰Šú‰»ƒtƒ@ƒCƒ‹ '%S' ‚Ì“Ç‚Ýž‚Ý‚ÉŽ¸”s‚µ‚Ü‚µ‚½B\r\nƒtƒ@ƒCƒ‹‚ªŒ©‚‚©‚ç‚È‚¢‚©A“à—e‚ª³‚µ‚­‚È‚¢‰Â”\«‚ª‚ ‚è‚Ü‚·B"
+ IDS_DIFF_CPU "‚±‚̃VƒXƒeƒ€‚É‚·‚Å‚É•Ê‚Ì CPU ƒA[ƒLƒeƒNƒ`ƒƒ—p‚Ì VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA‚ªƒCƒ“ƒXƒg[ƒ‹‚³‚ê‚Ä‚¢‚Ü‚·B\r\nƒRƒ“ƒgƒ[ƒ‹ƒpƒlƒ‹‚Ì [ƒvƒƒOƒ‰ƒ€‚̒ljÁ‚Æíœ] ‚ðŽg—p‚µ‚ÄAƒCƒ“ƒXƒg[ƒ‹‚³‚ê‚Ä‚¢‚é•Ê‚̃o[ƒWƒ‡ƒ“‚Ì VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA‚ðƒAƒ“ƒCƒ“ƒXƒg[ƒ‹‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_INSTANCE_EXISTS "‚·‚łɕʂ̊ȈՃCƒ“ƒXƒg[ƒ‰‚ª‹N“®‚µ‚Ä‚¢‚Ü‚·B"
+ IDS_BAD_OS "ŠÈˆÕƒCƒ“ƒXƒg[ƒ‰‚Í Windows 2000 ˆÈ~‚Ì OS ‚Å“®ì‚µ‚Ü‚·B\r\n‚»‚êˆÈŠO‚̃IƒyƒŒ[ƒeƒBƒ“ƒOƒVƒXƒeƒ€‚É VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA‚ðƒCƒ“ƒXƒg[ƒ‹‚·‚éꇂÍAŽè“®‚ŃCƒ“ƒXƒg[ƒ‰ƒvƒƒOƒ‰ƒ€‚ð‹N“®‚µ‚ăCƒ“ƒXƒg[ƒ‹‚ðŽÀs‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_CPU_NOT_SUPPORTED "Œ»Ý‚̃VƒXƒeƒ€‚Ì CPU ƒA[ƒLƒeƒNƒ`ƒƒ‚ɑΉž‚µ‚½ VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA‚ÍAVPN ƒNƒ‰ƒCƒAƒ“ƒgŠÈˆÕƒCƒ“ƒXƒg[ƒ‰‚ł̓Tƒ|[ƒg‚³‚ê‚Ä‚¢‚Ü‚¹‚ñB\r\nŽè“®‚ŃCƒ“ƒXƒg[ƒ‹‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B"
+ IDS_DOWNLOADING "(%.2f MB ’† %.2f MB Š®—¹)"
+ IDS_DOWNLOADSTART "ƒtƒ@ƒCƒ‹ '%S' ‚̃_ƒEƒ“ƒ[ƒh‚ðŠJŽn‚µ‚Ä‚¢‚Ü‚·..."
+END
+
+STRINGTABLE
+BEGIN
+ IDS_TEMP_ERROR "ˆêŽžƒtƒ@ƒCƒ‹ '%s' ‚Ì쬂Ɏ¸”s‚µ‚Ü‚µ‚½B"
+ IDS_DOWNLOAD_ERROR "ƒtƒ@ƒCƒ‹ '%S' ‚̃_ƒEƒ“ƒ[ƒh‚ÉŽ¸”s‚µ‚Ü‚µ‚½B"
+ IDS_DOWNLOADING2 "(%.2f MB Š®—¹)"
+ IDS_DOWNLOADING3 "ƒtƒ@ƒCƒ‹ '%S' ‚ðƒ_ƒEƒ“ƒ[ƒh‚µ‚Ä‚¢‚Ü‚·B‚µ‚΂炭‚¨‘Ò‚¿‚­‚¾‚³‚¢..."
+ IDS_INSTALLSTART "‰æ–Ê‚É•\Ž¦‚³‚ꂽ VPN Client ƒCƒ“ƒXƒg[ƒ‰‚ÌŽwŽ¦‚É]‚Á‚ăCƒ“ƒXƒg[ƒ‹‚ðŠ®—¹‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_INSTALLSTART_ERROR "ƒCƒ“ƒXƒg[ƒ‹‚ÌŠJŽn‚ÉŽ¸”s‚µ‚Ü‚µ‚½B"
+ IDS_SECURITY_ERROR "ƒZƒLƒ…ƒŠƒeƒB‚ð•ÛŒì‚·‚邽‚ßAWeb Œo—R‚̃Cƒ“ƒXƒg[ƒ‹Žž‚̓[ƒJƒ‹ƒtƒ@ƒCƒ‹‚ðƒCƒ“ƒXƒg[ƒ‹Œ³ƒtƒ@ƒCƒ‹‚Æ‚µ‚ÄŽw’è‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñB\r\ninf ƒtƒ@ƒCƒ‹‚Ì“à—e‚âŽw’肵‚½ƒpƒX‚È‚Ç‚ðŠm”F‚µ‚Ä‚­‚¾‚³‚¢B\r\n\r\nƒCƒ“ƒXƒg[ƒ‰‚ðI—¹‚µ‚Ü‚·B"
+ IDS_SIGN_WARNING "ƒCƒ“ƒ^[ƒlƒbƒg‚©‚玩“®‚Ń_ƒEƒ“ƒ[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹ '%s' ‚ÍAM—Š‚Å‚«‚é”­sŒ³‚É‚æ‚Á‚Ä“dŽq–¼‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ‚Å‚µ‚½B\r\nŒ»Ý‚±‚̃ƒbƒZ[ƒW‚ð•\Ž¦‚µ‚Ä‚¢‚éƒvƒƒOƒ‰ƒ€‚ÌŠJ”­Œ³‚¨‚æ‚Ñ”z•zŒ³‚ÍAƒCƒ“ƒ^[ƒlƒbƒg‚©‚玩“®‚Ń_ƒEƒ“ƒ[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹ '%s' ‚ªˆÀ‘S‚Å‚ ‚é‚©‚Ç‚¤‚©‚ð•ÛØ‚Å‚«‚¸A‰¼‚ɃZƒLƒ…ƒŠƒeƒBãŠëŒ¯‚ȃR[ƒh‚ªŠÜ‚Ü‚ê‚Ä‚¢‚½ê‡‚Å‚àÓ”C‚𕉂¢‚Ü‚¹‚ñB\r\n\r\n‚±‚̃tƒ@ƒCƒ‹‚ðŽÀs‚·‚邱‚Ƃ̓ZƒLƒ…ƒŠƒeƒBㄧ‚³‚ê‚Ü‚¹‚ñB‚±‚̃tƒ@ƒCƒ‹‚ðM—Š‚·‚邱‚Æ‚ª‚Å‚«‚é‚©‚Ç‚¤‚©Td‚É”»’f‚µ‚Ä‚­‚¾‚³‚¢B\r\n\r\nƒ†[ƒU[‚Ì”»’f‚ÆÓ”C‚É‚æ‚è [OK] ‚ðƒNƒŠƒbƒN‚·‚é‚ÆAƒCƒ“ƒXƒg[ƒ‹ˆ—‚ð‘±s‚µ‚Ü‚·B[ƒLƒƒƒ“ƒZƒ‹] ‚ðƒNƒŠƒbƒN‚·‚é‚ÆAƒCƒ“ƒXƒg[ƒ‹ˆ—‚ð’†’f‚µ‚Ü‚·B\r\n\r\n¦ ‚±‚̃ƒbƒZ[ƒW‚ÍAƒtƒ@ƒCƒ‹ '%s' ‚ð—LŒø‚ȃR[ƒh–¼—pØ–¾‘‚É‚æ‚Á‚Ä–¼‚·‚邱‚Æ‚É‚æ‚è•\Ž¦‚³‚ê‚È‚­‚È‚è‚Ü‚·B"
+ IDS_SIGN_WARNING_TITLE "ƒZƒLƒ…ƒŠƒeƒB‚ÉŠÖ‚·‚éŒx"
+ IDS_TITLE_VPNSMGR "VPN ƒT[ƒo[ŠÇ—ƒ}ƒl[ƒWƒƒŠÈˆÕƒCƒ“ƒXƒg[ƒ‰"
+ IDS_VPNSMGR_EXEC_ERROR "VPN ƒT[ƒo[ŠÇ—ƒ}ƒl[ƒWƒƒ‚Ì‹N“®‚ÉŽ¸”s‚µ‚Ü‚µ‚½B\r\nŽè“®‚Å VPN ƒT[ƒo[ŠÇ—ƒ}ƒl[ƒWƒƒ‚ðƒCƒ“ƒXƒg[ƒ‹‚µŽÀs‚µ‚Ä‚Ý‚Ä‚­‚¾‚³‚¢B"
+ IDS_DLG_TITLE "VPN ƒNƒ‰ƒCƒAƒ“ƒgƒ\ƒtƒgƒEƒFƒA"
+ IDS_INSTALL_DLG__STATUS_INIT "‰Šú‰»’†"
+ IDS_INSTALL_CANCEL "ƒLƒƒƒ“ƒZƒ‹"
+ IDS_EULA_NOTICE1 "ŽŸ‚ÌŽg—p‹–‘øŒ_–ñ‘‚ð‚¨“Ç‚Ý‚­‚¾‚³‚¢BPageDown ƒL[‚ðŽg‚Á‚ăXƒNƒ[ƒ‹‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_EULA_NOTICE2 "Žg—p‹–‘øŒ_–ñ‘‚É“¯ˆÓ‚³‚ê‚Ü‚·‚©?"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_EULA_NOTICE3 "[“¯ˆÓ‚µ‚Ü‚¹‚ñ] ‚ðƒNƒŠƒbƒN‚·‚é‚ƃCƒ“ƒXƒg[ƒ‹‚𒆎~‚µ‚Ü‚·BƒCƒ“ƒXƒg[ƒ‹‚·‚é‚É‚ÍA‚±‚ÌŒ_–ñ‚É“¯ˆÓ‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_EULA_AGREE "“¯ˆÓ‚µ‚Ü‚·"
+ IDS_EULA_DISAGREE "“¯ˆÓ‚µ‚Ü‚¹‚ñ"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_TITLE_EN "VPN Client Web Installer"
+ IDS_FONT_EN "Arial"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_FONT_SIZE_EN "8"
+ IDS_INF_LOAD_FAILED_EN "Failed to load initial configuration file '%S'.\r\nThe cause may be that threre are not the file or the description is invalid."
+ IDS_DIFF_CPU_EN "There already is VPN Client software for another CPU architecture installed on this system.\r\nUninstall that VPN Client software with [Add or Remove Programs] in Control Panel."
+ IDS_INSTANCE_EXISTS_EN "Another easy installer is already running."
+ IDS_BAD_OS_EN "The easy installer runs on Windows 2000 or greater.\r\nTo install VPN Client software for other operating systems, please install the software manually from a file. "
+ IDS_CPU_NOT_SUPPORTED_EN
+ "The VPN Client Easy Installer is not supported for this CPU architecture on this system.\r\nPlease install VPN Client software manually from an installation file. "
+ IDS_DOWNLOADING_EN "(Total:%.2f MB - Downloaded:%.2f MB)"
+ IDS_DOWNLOADSTART_EN "Starting download file '%S'..."
+ IDS_TEMP_ERROR_EN "Failed to create temporary file '%s'."
+ IDS_DOWNLOAD_ERROR_EN "Failed to download file '%S'."
+ IDS_DOWNLOADING2_EN "(Downloaded: %.2f)"
+ IDS_DOWNLOADING3_EN "Downloading file '%S'. Please wait."
+ IDS_INSTALLSTART_EN "Complete the VPN Client Installer displayed on the screen."
+ IDS_INSTALLSTART_ERROR_EN "Failed to start installation."
+ IDS_SECURITY_ERROR_EN "For security reasons, a local file cannot be used as the installation soruce during Web-based installation.\r\nConfirm the inf file of context and check the path specified in the inf file. \r\nInstallaion process aborted."
+ IDS_SIGN_WARNING_EN "The automatically downloaded file '%s' from the Internet is not digitally signed with a trusted certificate.\r\nThe developer and publisher do not guarantee that the downloaded file '%s' is safe and do not take responsibility in case of unsafe code included in the file.\r\n\r\nWe recommend to abort the installation by clicking [Cancel]. Proceed the installation by clicking [OK] at your own risk.\r\n\r\nNotice: the message will not be disappered when the file '%s' is signed by valid code signing certificate authentication."
+END
+
+STRINGTABLE
+BEGIN
+ IDS_SIGN_WARNING_TITLE_EN "Security Alert"
+ IDS_TITLE_VPNSMGR_EN "VPN Server Manager Easy Installer"
+ IDS_VPNSMGR_EXEC_ERROR_EN
+ "Failed to start VPN Server Manager.\r\nTry installing VPN Server Manager manually."
+ IDS_DLG_TITLE_EN "VPN Client Software"
+ IDS_INSTALL_DLG__STATUS_INIT_EN "Initializing..."
+ IDS_INSTALL_CANCEL_EN "Cancel"
+ IDS_EULA_NOTICE1_EN "Please read the following license agreement. Press the PAGE DOWN key to see the rest of the agreement."
+ IDS_EULA_NOTICE2_EN "Do you accept all of the terms of the preceding License Agreement?"
+ IDS_EULA_NOTICE3_EN "If you choose No, the installation will abort. To install you must accept this agreement."
+ IDS_EULA_AGREE_EN "Agree"
+ IDS_EULA_DISAGREE_EN "Disagree"
+END
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpninstall/vpninstall.vcproj b/src/vpninstall/vpninstall.vcproj
new file mode 100644
index 00000000..09b5b99c
--- /dev/null
+++ b/src/vpninstall/vpninstall.vcproj
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpninstall"
+ ProjectGUID="{F2C40D5C-1C86-43D8-B3FE-8E8F8B488432}"
+ RootNamespace="vpninstall"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpninstall.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="msi.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpninstall.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpninstall.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpninstall.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpninstall.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpninstall.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnserver/Server.ico b/src/vpnserver/Server.ico
new file mode 100644
index 00000000..ead07097
--- /dev/null
+++ b/src/vpnserver/Server.ico
Binary files differ
diff --git a/src/vpnserver/resource.h b/src/vpnserver/resource.h
new file mode 100644
index 00000000..4e838a5f
--- /dev/null
+++ b/src/vpnserver/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnserver.rc
+//
+#define IDI_ICON1 101
+#define IDI_SERVER 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnserver/vpnserver.c b/src/vpnserver/vpnserver.c
new file mode 100644
index 00000000..34610a7d
--- /dev/null
+++ b/src/vpnserver/vpnserver.c
@@ -0,0 +1,141 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpnserver.c
+// VPN Server service program
+
+#include <GlobalConst.h>
+
+#define VPN_EXE
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include "../PenCore/resource.h"
+#endif // WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// Process starting function
+void StartProcess()
+{
+ // Start the server
+ InitCedar();
+ StInit();
+ StStartServer(false);
+}
+
+// Process termination function
+void StopProcess()
+{
+ // Stop the server
+ StStopServer();
+ StFree();
+ FreeCedar();
+}
+
+// WinMain function
+int main(int argc, char *argv[])
+{
+ VgUseStaticLink();
+
+#ifdef OS_WIN32
+
+ return MsService(GC_SVC_NAME_VPNSERVER, StartProcess, StopProcess, ICO_CASCADE, argv[0]);
+#else // OS_WIN32
+ return UnixService(argc, argv, "vpnserver", StartProcess, StopProcess);
+#endif // OS_WIN32
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnserver/vpnserver.rc b/src/vpnserver/vpnserver.rc
new file mode 100644
index 00000000..03b7af53
--- /dev/null
+++ b/src/vpnserver/vpnserver.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SERVER ICON "Server.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnserver/vpnserver.vcproj b/src/vpnserver/vpnserver.vcproj
new file mode 100644
index 00000000..c6152bc5
--- /dev/null
+++ b/src/vpnserver/vpnserver.vcproj
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnserver"
+ ProjectGUID="{7CF21BD6-659F-449C-91CB-CE52AABAD22D}"
+ RootNamespace="vpnserver"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnserver.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnserver_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnserver.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnserver_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpnserver.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\Server.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnserver.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnsetup/Installer.ico b/src/vpnsetup/Installer.ico
new file mode 100644
index 00000000..b274e4c6
--- /dev/null
+++ b/src/vpnsetup/Installer.ico
Binary files differ
diff --git a/src/vpnsetup/resource.h b/src/vpnsetup/resource.h
new file mode 100644
index 00000000..1406aa4e
--- /dev/null
+++ b/src/vpnsetup/resource.h
@@ -0,0 +1,33 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnsetup.rc
+//
+#define IDI_ICON1 101
+#define IDI_ICON2 103
+#define IDI_VPNSVR 103
+#define IDI_VPNSETUP 103
+#define IDI_SETUP_MAIN 103
+#define IDI_SETUP_INTERNET 104
+#define IDI_SETUP_PROTOCOL 105
+#define IDI_SETUP_SWITCH 106
+#define IDI_ICON3 107
+#define IDI_SETUP_MACHINE 107
+#define IDI_ICON4 108
+#define IDI_ICON5 109
+#define IDI_ICON6 110
+#define IDI_ICON7 111
+#define IDI_ICON8 112
+#define IDI_ICON9 113
+#define IDI_ICON10 115
+#define IDI_ICON11 120
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 121
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnsetup/vpnsetup.c b/src/vpnsetup/vpnsetup.c
new file mode 100644
index 00000000..701a9f07
--- /dev/null
+++ b/src/vpnsetup/vpnsetup.c
@@ -0,0 +1,120 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#include <GlobalConst.h>
+
+// vpnsetup.c
+// VPN Setup Wizard
+
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// WinMain function
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ UINT ret;
+
+ VgUseStaticLink();
+
+ ret = SWExec();
+
+ ExitProcess(ret);
+
+ return (int)ret;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnsetup/vpnsetup.ico b/src/vpnsetup/vpnsetup.ico
new file mode 100644
index 00000000..2cf9d172
--- /dev/null
+++ b/src/vpnsetup/vpnsetup.ico
Binary files differ
diff --git a/src/vpnsetup/vpnsetup.rc b/src/vpnsetup/vpnsetup.rc
new file mode 100644
index 00000000..be68c92f
--- /dev/null
+++ b/src/vpnsetup/vpnsetup.rc
@@ -0,0 +1,174 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SETUP_MAIN ICON "vpnsetup.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ 10001, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 254
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 68
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+10001 DIALOGEX 0, 0, 261, 75
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "SoftEther Installer"
+FONT 9, "MS PGothic", 400, 0, 0x80
+BEGIN
+ ICON IDI_ICON10,IDC_STATIC,7,7,20,20,WS_TABSTOP
+ LTEXT "ƒCƒ“ƒXƒg[ƒ‹‚Ì€”õ’†...",IDC_STATIC,30,7,189,20
+ DEFPUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,195,52,59,16
+END
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SETUP_INTERNET ICON "..\\PenCore\\Internet.ico"
+IDI_SETUP_PROTOCOL ICON "..\\PenCore\\Protocol.ico"
+IDI_SETUP_SWITCH ICON "..\\PenCore\\Switch.ico"
+IDI_SETUP_MACHINE ICON "..\\PenCore\\Machine.ico"
+IDI_ICON4 ICON "..\\PenCore\\VPNSvr.ico"
+IDI_ICON5 ICON "..\\PenCore\\VPN.ico"
+IDI_ICON6 ICON "..\\PenCore\\Cascade.ico"
+IDI_ICON7 ICON "..\\PenCore\\UserAdmin.ico"
+IDI_ICON8 ICON "..\\PenCore\\Internet.ico"
+IDI_ICON9 ICON "..\\PenCore\\Language.ico"
+IDI_ICON10 ICON "Installer.ico"
+IDI_ICON11 ICON "..\\PenCore\\EasyInstaller.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ 10002, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 254
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 68
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+10002 DIALOGEX 0, 0, 261, 75
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "SoftEther Installer"
+FONT 8, "Arial", 400, 0, 0x0
+BEGIN
+ ICON IDI_ICON10,IDC_STATIC,7,7,20,20,WS_TABSTOP
+ LTEXT "Preparing to install...",IDC_STATIC,33,7,189,20
+ DEFPUSHBUTTON "Cancel",IDCANCEL,195,54,59,14
+END
+
+#endif // English resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnsetup/vpnsetup.vcproj b/src/vpnsetup/vpnsetup.vcproj
new file mode 100644
index 00000000..e5ced52b
--- /dev/null
+++ b/src/vpnsetup/vpnsetup.vcproj
@@ -0,0 +1,481 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnsetup"
+ ProjectGUID="{58FEB572-E43A-439E-9A2C-E19DE3CB1401}"
+ RootNamespace="vpnsetup"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsetup.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:FileCopy &quot;$(TargetPath)&quot; /DEST:&quot;$(SolutionDir)bin\hamcore\vpnsetup_nosign.exe&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsetup_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsetup.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:FileCopy &quot;$(TargetPath)&quot; /DEST:&quot;$(SolutionDir)bin\hamcore\vpnsetup_nosign.exe&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsetup_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpnsetup.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath="..\PenCore\Cascade.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\EasyInstaller.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Installer.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\Internet.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\Language.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\Machine.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\Protocol.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\Switch.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\UserAdmin.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\VPN.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnsetup.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnsetup.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\PenCore\VPNSvr.ico"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\..\..\..\..\TMP\cpntest\hamcore.se2"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnsmgr/VPNSvr.ico b/src/vpnsmgr/VPNSvr.ico
new file mode 100644
index 00000000..9585574a
--- /dev/null
+++ b/src/vpnsmgr/VPNSvr.ico
Binary files differ
diff --git a/src/vpnsmgr/resource.h b/src/vpnsmgr/resource.h
new file mode 100644
index 00000000..f3acecf5
--- /dev/null
+++ b/src/vpnsmgr/resource.h
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnsmgr.rc
+//
+#define IDI_ICON1 101
+#define IDI_ICON2 103
+#define IDI_VPNSVR 103
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/vpnsmgr/vpnsmgr.c b/src/vpnsmgr/vpnsmgr.c
new file mode 100644
index 00000000..2ecc4432
--- /dev/null
+++ b/src/vpnsmgr/vpnsmgr.c
@@ -0,0 +1,117 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpncmgr.c
+// VPN Client connection manager program
+
+#include <GlobalConst.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Cedar/Cedar.h>
+
+// WinMain function
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ InitMayaqua(false, false, 0, NULL);
+ InitCedar();
+ SMExec();
+ FreeCedar();
+ FreeMayaqua();
+ return 0;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnsmgr/vpnsmgr.ico b/src/vpnsmgr/vpnsmgr.ico
new file mode 100644
index 00000000..b569c128
--- /dev/null
+++ b/src/vpnsmgr/vpnsmgr.ico
Binary files differ
diff --git a/src/vpnsmgr/vpnsmgr.rc b/src/vpnsmgr/vpnsmgr.rc
new file mode 100644
index 00000000..5fd26d16
--- /dev/null
+++ b/src/vpnsmgr/vpnsmgr.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_VPNSVR ICON "VPNSvr.ico"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnsmgr/vpnsmgr.vcproj b/src/vpnsmgr/vpnsmgr.vcproj
new file mode 100644
index 00000000..d53d0b64
--- /dev/null
+++ b/src/vpnsmgr/vpnsmgr.vcproj
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnsmgr"
+ ProjectGUID="{A4DC7ACC-9FED-418F-92B2-6BE3EF39DC86}"
+ RootNamespace="vpnsmgr"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsmgr.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsmgr_x64.exe"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsmgr.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetPE4 &quot;$(TargetPath)&quot;&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_user.manifest&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\vpnsmgr_x64.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ DelayLoadDLLs="setupapi.dll;advapi32.dll;user32.dll"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="100000"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x64_user.manifest"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vpnsmgr.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\vpnsmgr.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnsmgr.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNSvr.ico"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnweb/VPN.ico b/src/vpnweb/VPN.ico
new file mode 100644
index 00000000..eb968602
--- /dev/null
+++ b/src/vpnweb/VPN.ico
Binary files differ
diff --git a/src/vpnweb/VPNSvr.ico b/src/vpnweb/VPNSvr.ico
new file mode 100644
index 00000000..44b3f02e
--- /dev/null
+++ b/src/vpnweb/VPNSvr.ico
Binary files differ
diff --git a/src/vpnweb/VpnWebControl.bmp b/src/vpnweb/VpnWebControl.bmp
new file mode 100644
index 00000000..6857a6d0
--- /dev/null
+++ b/src/vpnweb/VpnWebControl.bmp
Binary files differ
diff --git a/src/vpnweb/VpnWebControl.cpp b/src/vpnweb/VpnWebControl.cpp
new file mode 100644
index 00000000..fb298b96
--- /dev/null
+++ b/src/vpnweb/VpnWebControl.cpp
@@ -0,0 +1,4 @@
+// VpnWebControl.cpp : CVpnWebControl
+#include "stdafx.h"
+#include "VpnWebControl.h"
+
diff --git a/src/vpnweb/VpnWebControl.h b/src/vpnweb/VpnWebControl.h
new file mode 100644
index 00000000..6c25bb8f
--- /dev/null
+++ b/src/vpnweb/VpnWebControl.h
@@ -0,0 +1,382 @@
+#pragma once
+#include "resource.h"
+#include <atlctl.h>
+#include "vpnweb.h"
+#include "vpnwebdlg.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "DCOM is not supported."
+#endif
+
+
+// CVpnWebControl
+class ATL_NO_VTABLE CVpnWebControl :
+ public CComObjectRootEx<CComSingleThreadModel>,
+ public IDispatchImpl<IVpnWebControl, &IID_IVpnWebControl, &LIBID_vpnwebLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+ public IPersistStreamInitImpl<CVpnWebControl>,
+ public IOleControlImpl<CVpnWebControl>,
+ public IOleObjectImpl<CVpnWebControl>,
+ public IOleInPlaceActiveObjectImpl<CVpnWebControl>,
+ public IViewObjectExImpl<CVpnWebControl>,
+ public IOleInPlaceObjectWindowlessImpl<CVpnWebControl>,
+ public ISupportErrorInfo,
+ public IPersistStorageImpl<CVpnWebControl>,
+ public IPersistPropertyBagImpl<CVpnWebControl>,
+ public ISpecifyPropertyPagesImpl<CVpnWebControl>,
+ public IQuickActivateImpl<CVpnWebControl>,
+ public IObjectSafetyImpl<CVpnWebControl, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>,
+#ifndef _WIN32_WCE
+ public IDataObjectImpl<CVpnWebControl>,
+#endif
+ public IProvideClassInfo2Impl<&CLSID_VpnWebControl, NULL, &LIBID_vpnwebLib>,
+#ifdef _WIN32_WCE
+ public IObjectSafetyImpl<CVpnWebControl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
+#endif
+ public CComCoClass<CVpnWebControl, &CLSID_VpnWebControl>,
+ public CComControl<CVpnWebControl>
+{
+public:
+
+ HWND hDlg;
+
+ CVpnWebControl()
+ {
+ hDlg = NULL;
+ SIZE dlgSize;
+
+ GetVpnWebDlgSize(&dlgSize);
+
+ m_bWindowOnly = TRUE;
+ m_bAutoSize = TRUE;
+ m_bRecomposeOnResize = TRUE;
+ m_bResizeNatural = TRUE;
+
+ setSize(dlgSize.cx, dlgSize.cy);
+ }
+
+ DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
+ OLEMISC_CANTLINKINSIDE |
+ OLEMISC_INSIDEOUT |
+ OLEMISC_ACTIVATEWHENVISIBLE |
+ OLEMISC_SETCLIENTSITEFIRST
+ )
+
+ DECLARE_REGISTRY_RESOURCEID(IDR_VPNWEBCONTROL)
+
+
+ BEGIN_COM_MAP(CVpnWebControl)
+ COM_INTERFACE_ENTRY(IVpnWebControl)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(IViewObjectEx)
+ COM_INTERFACE_ENTRY(IViewObject2)
+ COM_INTERFACE_ENTRY(IViewObject)
+ COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceObject)
+ COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
+ COM_INTERFACE_ENTRY(IOleControl)
+ COM_INTERFACE_ENTRY(IOleObject)
+ COM_INTERFACE_ENTRY(IPersistStreamInit)
+ COM_INTERFACE_ENTRY(IPersistPropertyBag)
+ COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+ COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
+ COM_INTERFACE_ENTRY(IQuickActivate)
+ COM_INTERFACE_ENTRY(IPersistStorage)
+ COM_INTERFACE_ENTRY(IObjectSafety)
+#ifndef _WIN32_WCE
+ COM_INTERFACE_ENTRY(IDataObject)
+#endif
+ COM_INTERFACE_ENTRY(IProvideClassInfo)
+ COM_INTERFACE_ENTRY(IProvideClassInfo2)
+#ifdef _WIN32_WCE
+ COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
+#endif
+ END_COM_MAP()
+
+ BEGIN_PROP_MAP(CVpnWebControl)
+ //PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
+ //PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
+ PROP_ENTRY("InstallerExeUrl", 1, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("InstallerInfUrl", 2, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("SettingUrl", 3, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("VpnServerManagerMode", 4, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("VpnServerHostname", 5, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("VpnServerHubName", 6, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("VpnServerPassword", 7, CVpnWebControl::GetObjectCLSID())
+
+ PROP_ENTRY("LanguageID", 8, CVpnWebControl::GetObjectCLSID())
+ PROP_ENTRY("LanguageID", 9, CVpnWebControl::GetObjectCLSID())
+
+ END_PROP_MAP()
+
+
+ BEGIN_MSG_MAP(CVpnWebControl)
+ MESSAGE_HANDLER(WM_CREATE, OnCreate)
+ CHAIN_MSG_MAP(CComControl<CVpnWebControl>)
+ DEFAULT_REFLECTION_HANDLER()
+ END_MSG_MAP()
+ // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
+
+ // ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
+ {
+ static const IID* arr[] =
+ {
+ &IID_IVpnWebControl,
+ };
+
+ for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i], riid))
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+/*
+ // IObjectSafety
+ STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwSupportedOptions, DWORD dwEnabledOptions)
+ {
+ if (riid == IID_IPersistPropertyBag)
+ {
+ if (dwEnabledOptions != INTERFACESAFE_FOR_UNTRUSTED_CALLER)
+ {
+ return E_FAIL;
+ }
+ return S_OK;
+ }
+ return IObjectSafetyImpl<CVpnWebControl,
+ INTERFACESAFE_FOR_UNTRUSTED_CALLER>::SetInterfaceSafetyOptions(riid,
+ dwSupportedOptions, dwEnabledOptions);
+ }*/
+
+ // IViewObjectEx
+ DECLARE_VIEW_STATUS(0)
+
+ void setSize(UINT width, UINT height)
+ {
+ SIZEL src;
+
+ ZeroMemory(&src, sizeof(src));
+
+ src.cx = width;
+ src.cy = height;
+
+ AtlPixelToHiMetric(&src, &m_sizeNatural);
+ AtlPixelToHiMetric(&src, &m_sizeExtent);
+ }
+
+private:
+ CComBSTR m_installer_exe_url, m_installer_inf_url, m_setting_url,
+ m_vpnserver_manager_mode, m_vpnserver_hostname, m_vpnserver_hubname,
+ m_vpnserver_password;
+ CComBSTR m_language_id;
+
+ // IVpnWebControl
+public:
+ LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+ {
+ RECT rc;
+ GetWindowRect(&rc);
+ rc.right -= rc.left;
+ rc.bottom -= rc.top;
+ rc.top = rc.left = 0;
+
+ VPNWEBDLG_INIT init;
+ ZeroMemory(&init, sizeof(init));
+ init.hControlWnd = m_hWnd;
+
+ CW2A installer_exe_url(m_installer_exe_url);
+ CW2A installer_inf_url(m_installer_inf_url);
+ CW2A setting_url(m_setting_url);
+ CW2A vpnserver_manager_mode(m_vpnserver_manager_mode);
+ CW2A vpnserver_hostname(m_vpnserver_hostname);
+ CW2A vpnserver_hubname(m_vpnserver_hubname);
+ CW2A vpnserver_password(m_vpnserver_password);
+ CW2A language_id(m_language_id);
+
+ if (installer_exe_url != NULL)
+ {
+ if (lstrlen(installer_exe_url) <= 256)
+ {
+ lstrcpy(init.InstallerExeUrl, installer_exe_url);
+ }
+ }
+
+ if (installer_inf_url != NULL)
+ {
+ if (lstrlen(installer_inf_url) <= 256)
+ {
+ lstrcpy(init.InstallerInfUrl, installer_inf_url);
+ }
+ }
+
+ if (setting_url != NULL)
+ {
+ if (lstrlen(setting_url) <= 256)
+ {
+ lstrcpy(init.SettingUrl, setting_url);
+ }
+ }
+
+ if (vpnserver_manager_mode != NULL)
+ {
+ init.VpnServerManagerMode = (BOOL)strtod(vpnserver_manager_mode, NULL);
+ }
+
+ if( m_language_id!=NULL ){
+ if (lstrlen(language_id) <= 32)
+ {
+ lstrcpy(init.LanguageId, language_id);
+ }
+ }
+ if (init.VpnServerManagerMode)
+ {
+ if (vpnserver_hostname != NULL)
+ {
+ if (lstrlen(vpnserver_hostname) <= 256)
+ {
+ lstrcpy(init.VpnServerHostname, vpnserver_hostname);
+ }
+ }
+
+ if (vpnserver_hubname != NULL)
+ {
+ if (lstrlen(vpnserver_hubname) <= 256)
+ {
+ lstrcpy(init.VpnServerHubName, vpnserver_hubname);
+ }
+ }
+
+ if (vpnserver_password != NULL)
+ {
+ if (lstrlen(vpnserver_password) <= 256)
+ {
+ lstrcpy(init.VpnServerPassword, vpnserver_password);
+ }
+ }
+ }
+
+ hDlg = InitVpnWebDlg(&init);
+
+ return 0;
+ }
+
+ HRESULT OnDraw(ATL_DRAWINFO& di)
+ {
+ return S_OK;
+ }
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ FreeVpnWebDlg();
+ }
+
+ STDMETHODIMP get_InstallerExeUrl(BSTR* pVal)
+ {
+ *pVal = m_installer_exe_url.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_InstallerExeUrl(BSTR newVal)
+ {
+ m_installer_exe_url = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_InstallerInfUrl(BSTR* pVal)
+ {
+ *pVal = m_installer_inf_url.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_InstallerInfUrl(BSTR newVal)
+ {
+ m_installer_inf_url = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_SettingUrl(BSTR* pVal)
+ {
+ *pVal = m_setting_url.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_SettingUrl(BSTR newVal)
+ {
+ m_setting_url = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_VpnServerManagerMode(BSTR* pVal)
+ {
+ *pVal = m_vpnserver_manager_mode.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_VpnServerManagerMode(BSTR newVal)
+ {
+ m_vpnserver_manager_mode = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_VpnServerHostname(BSTR* pVal)
+ {
+ *pVal = m_vpnserver_hostname.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_VpnServerHostname(BSTR newVal)
+ {
+ m_vpnserver_hostname = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_VpnServerHubName(BSTR* pVal)
+ {
+ *pVal = m_vpnserver_hubname.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_VpnServerHubName(BSTR newVal)
+ {
+ m_vpnserver_hubname = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_VpnServerPassword(BSTR* pVal)
+ {
+ *pVal = m_vpnserver_password.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_VpnServerPassword(BSTR newVal)
+ {
+ m_vpnserver_password = newVal;
+ return S_OK;
+ }
+
+ STDMETHODIMP get_LanguageID(BSTR* pVal)
+ {
+ *pVal = m_language_id.Copy();
+ return S_OK;
+ }
+
+ STDMETHODIMP put_LanguageID(BSTR newVal)
+ {
+ m_language_id = newVal;
+ return S_OK;
+ }
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(VpnWebControl), CVpnWebControl)
diff --git a/src/vpnweb/VpnWebControl.rgs b/src/vpnweb/VpnWebControl.rgs
new file mode 100644
index 00000000..a143dc71
--- /dev/null
+++ b/src/vpnweb/VpnWebControl.rgs
@@ -0,0 +1,34 @@
+HKCR
+{
+ vpnweb.VpnWebControl.1 = s 'VpnWebControl Class'
+ {
+ CLSID = s '{64F1A16B-C3EE-484C-B551-35338A9BB6D2}'
+ }
+ vpnweb.VpnWebControl = s 'VpnWebControl Class'
+ {
+ CLSID = s '{64F1A16B-C3EE-484C-B551-35338A9BB6D2}'
+ CurVer = s 'vpnweb.VpnWebControl.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {64F1A16B-C3EE-484C-B551-35338A9BB6D2} = s 'VpnWebControl Class'
+ {
+ ProgID = s 'vpnweb.VpnWebControl.1'
+ VersionIndependentProgID = s 'vpnweb.VpnWebControl'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ ForceRemove 'Control'
+ ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 102'
+ 'MiscStatus' = s '0'
+ {
+ '1' = s '%OLEMISC%'
+ }
+ 'TypeLib' = s '{D8FDDBA5-B33F-4B0A-8162-A771ECD32B04}'
+ 'Version' = s '1.0'
+ }
+ }
+}
diff --git a/src/vpnweb/dlldata.c b/src/vpnweb/dlldata.c
new file mode 100644
index 00000000..714d7e30
--- /dev/null
+++ b/src/vpnweb/dlldata.c
@@ -0,0 +1,38 @@
+/*********************************************************
+ DllData file -- generated by MIDL compiler
+
+ DO NOT ALTER THIS FILE
+
+ This file is regenerated by MIDL on every IDL file compile.
+
+ To completely reconstruct this file, delete it and rerun MIDL
+ on all the IDL files in this DLL, specifying this file for the
+ /dlldata command line option
+
+*********************************************************/
+
+#define PROXY_DELEGATION
+
+#include <rpcproxy.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXTERN_PROXY_FILE( vpnweb )
+
+
+PROXYFILE_LIST_START
+/* Start of list */
+ REFERENCE_PROXY_FILE( vpnweb ),
+/* End of list */
+PROXYFILE_LIST_END
+
+
+DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
+
+#ifdef __cplusplus
+} /*extern "C" */
+#endif
+
+/* end of generated dlldata file */
diff --git a/src/vpnweb/resource.h b/src/vpnweb/resource.h
new file mode 100644
index 00000000..3ce75431
--- /dev/null
+++ b/src/vpnweb/resource.h
@@ -0,0 +1,80 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vpnweb.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_VPNWEB 101
+#define IDB_VPNWEBCONTROL 102
+#define IDR_VPNWEBCONTROL 103
+#define IDD_VPNWEBDLG 201
+#define IDC_PROGRESS1 201
+#define P_PROGRESS 201
+#define IDI_VPN 202
+#define S_INFO 202
+#define S_INFO2 203
+#define IDC_BUTTON1 204
+#define IDI_ICON1 204
+#define IDI_SERVER 204
+#define S_ICON_VPN 205
+#define S_ICON_SERVER 206
+#define B_START 207
+#define IDS_MESSAGE_APPTITLE 10001
+#define IDS_STRING10002 10002
+#define IDS_STRING10003 10003
+#define IDS_STRING10004 10004
+#define IDS_STRING10005 10005
+#define IDS_STRING10006 10006
+#define IDS_STRING10007 10007
+#define IDS_STRING10008 10008
+#define IDS_STRING10009 10009
+#define IDS_STRING10010 10010
+#define IDS_STRING10011 10011
+#define IDS_STRING10012 10012
+#define IDS_STRING10013 10013
+#define IDS_STRING10014 10014
+#define IDS_STRING10015 10015
+#define IDS_STRING10016 10016
+#define IDS_STRING10017 10017
+#define IDS_STRING10018 10018
+#define IDS_STRING10019 10019
+#define IDS_MESSAGE_APPTITLE_EN 11001
+#define IDS_STRING11002 11002
+#define IDS_STRING10020 11003
+#define IDS_STRING11003 11003
+#define IDS_STRING10021 11004
+#define IDS_STRING11004 11004
+#define IDS_STRING10022 11005
+#define IDS_STRING11005 11005
+#define IDS_STRING10023 11006
+#define IDS_STRING11006 11006
+#define IDS_STRING10024 11007
+#define IDS_STRING11007 11007
+#define IDS_STRING10025 11008
+#define IDS_STRING11008 11008
+#define IDS_STRING10026 11009
+#define IDS_STRING11009 11009
+#define IDS_STRING10027 11010
+#define IDS_STRING11010 11010
+#define IDS_STRING10028 11011
+#define IDS_STRING11011 11011
+#define IDS_STRING10029 11012
+#define IDS_STRING11012 11012
+#define IDS_STRING101 11013
+#define IDS_STRING11013 11013
+#define IDS_STRING11014 11014
+#define IDS_STRING11015 11015
+#define IDS_STRING11016 11016
+#define IDS_STRING11017 11017
+#define IDS_STRING11018 11018
+#define IDS_STRING11019 11019
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 205
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 206
+#define _APS_NEXT_SYMED_VALUE 104
+#endif
+#endif
diff --git a/src/vpnweb/stdafx.cpp b/src/vpnweb/stdafx.cpp
new file mode 100644
index 00000000..a27b824d
--- /dev/null
+++ b/src/vpnweb/stdafx.cpp
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/src/vpnweb/stdafx.h b/src/vpnweb/stdafx.h
new file mode 100644
index 00000000..d5dd2200
--- /dev/null
+++ b/src/vpnweb/stdafx.h
@@ -0,0 +1,35 @@
+#include <GlobalConst.h>
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+#ifndef WINVER
+#define WINVER 0x0502
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0502
+#endif
+
+#ifndef _WIN32_WINDOWS
+#define _WIN32_WINDOWS 0x0410
+#endif
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0600
+#endif
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
+
+
+#include "resource.h"
+#include <atlbase.h>
+#include <atlcom.h>
+
+using namespace ATL;
+
diff --git a/src/vpnweb/vpnweb.cpp b/src/vpnweb/vpnweb.cpp
new file mode 100644
index 00000000..bdb0f4fc
--- /dev/null
+++ b/src/vpnweb/vpnweb.cpp
@@ -0,0 +1,61 @@
+#include "stdafx.h"
+#include "resource.h"
+#include "vpnweb.h"
+
+extern "C" {
+HINSTANCE hDllInstance;
+}
+
+
+class CvpnwebModule : public CAtlDllModuleT< CvpnwebModule >
+{
+public :
+ DECLARE_LIBID(LIBID_vpnwebLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_VPNWEB, "{7CE8BF01-70D6-48F6-A83A-69CA03D885C9}")
+};
+
+CvpnwebModule _AtlModule;
+
+
+#ifdef _MANAGED
+#pragma managed(push, off)
+#endif
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ hDllInstance = hInstance;
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+#ifdef _MANAGED
+#pragma managed(pop)
+#endif
+
+
+
+
+STDAPI DllCanUnloadNow(void)
+{
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+STDAPI DllRegisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllRegisterServer();
+ return hr;
+}
+
+
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+ return hr;
+}
+
diff --git a/src/vpnweb/vpnweb.def b/src/vpnweb/vpnweb.def
new file mode 100644
index 00000000..58c191f3
--- /dev/null
+++ b/src/vpnweb/vpnweb.def
@@ -0,0 +1,7 @@
+LIBRARY "vpnweb.ocx"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/src/vpnweb/vpnweb.h b/src/vpnweb/vpnweb.h
new file mode 100644
index 00000000..568a52a6
--- /dev/null
+++ b/src/vpnweb/vpnweb.h
@@ -0,0 +1,380 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0500 */
+/* at Sat Jan 04 19:11:13 2014
+ */
+/* Compiler settings for .\vpnweb.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 440
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __vpnweb_h__
+#define __vpnweb_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IVpnWebControl_FWD_DEFINED__
+#define __IVpnWebControl_FWD_DEFINED__
+typedef interface IVpnWebControl IVpnWebControl;
+#endif /* __IVpnWebControl_FWD_DEFINED__ */
+
+
+#ifndef __VpnWebControl_FWD_DEFINED__
+#define __VpnWebControl_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class VpnWebControl VpnWebControl;
+#else
+typedef struct VpnWebControl VpnWebControl;
+#endif /* __cplusplus */
+
+#endif /* __VpnWebControl_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#ifndef __IVpnWebControl_INTERFACE_DEFINED__
+#define __IVpnWebControl_INTERFACE_DEFINED__
+
+/* interface IVpnWebControl */
+/* [unique][helpstring][nonextensible][dual][uuid][object] */
+
+
+EXTERN_C const IID IID_IVpnWebControl;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("BEAC96A9-05ED-46B3-975C-4462E83878F5")
+ IVpnWebControl : public IDispatch
+ {
+ public:
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_InstallerExeUrl(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_InstallerExeUrl(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_InstallerInfUrl(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_InstallerInfUrl(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SettingUrl(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SettingUrl(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VpnServerManagerMode(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VpnServerManagerMode(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VpnServerHostname(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VpnServerHostname(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VpnServerHubName(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VpnServerHubName(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VpnServerPassword(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VpnServerPassword(
+ /* [in] */ BSTR newVal) = 0;
+
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_LanguageID(
+ /* [retval][out] */ BSTR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_LanguageID(
+ /* [in] */ BSTR newVal) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IVpnWebControlVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IVpnWebControl * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IVpnWebControl * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IVpnWebControl * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
+ IVpnWebControl * This,
+ /* [out] */ UINT *pctinfo);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
+ IVpnWebControl * This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo **ppTInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
+ IVpnWebControl * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR *rgszNames,
+ /* [range][in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID *rgDispId);
+
+ /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ IVpnWebControl * This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS *pDispParams,
+ /* [out] */ VARIANT *pVarResult,
+ /* [out] */ EXCEPINFO *pExcepInfo,
+ /* [out] */ UINT *puArgErr);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InstallerExeUrl )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InstallerExeUrl )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InstallerInfUrl )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InstallerInfUrl )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SettingUrl )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SettingUrl )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VpnServerManagerMode )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VpnServerManagerMode )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VpnServerHostname )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VpnServerHostname )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VpnServerHubName )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VpnServerHubName )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VpnServerPassword )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VpnServerPassword )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LanguageID )(
+ IVpnWebControl * This,
+ /* [retval][out] */ BSTR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LanguageID )(
+ IVpnWebControl * This,
+ /* [in] */ BSTR newVal);
+
+ END_INTERFACE
+ } IVpnWebControlVtbl;
+
+ interface IVpnWebControl
+ {
+ CONST_VTBL struct IVpnWebControlVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IVpnWebControl_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IVpnWebControl_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IVpnWebControl_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IVpnWebControl_GetTypeInfoCount(This,pctinfo) \
+ ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) )
+
+#define IVpnWebControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
+
+#define IVpnWebControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
+
+#define IVpnWebControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
+
+
+#define IVpnWebControl_get_InstallerExeUrl(This,pVal) \
+ ( (This)->lpVtbl -> get_InstallerExeUrl(This,pVal) )
+
+#define IVpnWebControl_put_InstallerExeUrl(This,newVal) \
+ ( (This)->lpVtbl -> put_InstallerExeUrl(This,newVal) )
+
+#define IVpnWebControl_get_InstallerInfUrl(This,pVal) \
+ ( (This)->lpVtbl -> get_InstallerInfUrl(This,pVal) )
+
+#define IVpnWebControl_put_InstallerInfUrl(This,newVal) \
+ ( (This)->lpVtbl -> put_InstallerInfUrl(This,newVal) )
+
+#define IVpnWebControl_get_SettingUrl(This,pVal) \
+ ( (This)->lpVtbl -> get_SettingUrl(This,pVal) )
+
+#define IVpnWebControl_put_SettingUrl(This,newVal) \
+ ( (This)->lpVtbl -> put_SettingUrl(This,newVal) )
+
+#define IVpnWebControl_get_VpnServerManagerMode(This,pVal) \
+ ( (This)->lpVtbl -> get_VpnServerManagerMode(This,pVal) )
+
+#define IVpnWebControl_put_VpnServerManagerMode(This,newVal) \
+ ( (This)->lpVtbl -> put_VpnServerManagerMode(This,newVal) )
+
+#define IVpnWebControl_get_VpnServerHostname(This,pVal) \
+ ( (This)->lpVtbl -> get_VpnServerHostname(This,pVal) )
+
+#define IVpnWebControl_put_VpnServerHostname(This,newVal) \
+ ( (This)->lpVtbl -> put_VpnServerHostname(This,newVal) )
+
+#define IVpnWebControl_get_VpnServerHubName(This,pVal) \
+ ( (This)->lpVtbl -> get_VpnServerHubName(This,pVal) )
+
+#define IVpnWebControl_put_VpnServerHubName(This,newVal) \
+ ( (This)->lpVtbl -> put_VpnServerHubName(This,newVal) )
+
+#define IVpnWebControl_get_VpnServerPassword(This,pVal) \
+ ( (This)->lpVtbl -> get_VpnServerPassword(This,pVal) )
+
+#define IVpnWebControl_put_VpnServerPassword(This,newVal) \
+ ( (This)->lpVtbl -> put_VpnServerPassword(This,newVal) )
+
+#define IVpnWebControl_get_LanguageID(This,pVal) \
+ ( (This)->lpVtbl -> get_LanguageID(This,pVal) )
+
+#define IVpnWebControl_put_LanguageID(This,newVal) \
+ ( (This)->lpVtbl -> put_LanguageID(This,newVal) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IVpnWebControl_INTERFACE_DEFINED__ */
+
+
+
+#ifndef __vpnwebLib_LIBRARY_DEFINED__
+#define __vpnwebLib_LIBRARY_DEFINED__
+
+/* library vpnwebLib */
+/* [helpstring][version][uuid] */
+
+
+EXTERN_C const IID LIBID_vpnwebLib;
+
+EXTERN_C const CLSID CLSID_VpnWebControl;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("64F1A16B-C3EE-484C-B551-35338A9BB6D2")
+VpnWebControl;
+#endif
+#endif /* __vpnwebLib_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * );
+unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * );
+unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * );
+void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/vpnweb/vpnweb.idl b/src/vpnweb/vpnweb.idl
new file mode 100644
index 00000000..8e13438c
--- /dev/null
+++ b/src/vpnweb/vpnweb.idl
@@ -0,0 +1,51 @@
+#include "olectl.h"
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(BEAC96A9-05ED-46B3-975C-4462E83878F5),
+ dual,
+ nonextensible,
+ helpstring("IVpnWebControl Interface"),
+ pointer_default(unique)
+]
+interface IVpnWebControl : IDispatch{
+ [propget, id(1), helpstring("InstallerExeUrl Property")] HRESULT InstallerExeUrl([out, retval] BSTR* pVal);
+ [propput, id(1), helpstring("InstallerExeUrl Property")] HRESULT InstallerExeUrl([in] BSTR newVal);
+ [propget, id(2), helpstring("InstallerInfUrl Property")] HRESULT InstallerInfUrl([out, retval] BSTR* pVal);
+ [propput, id(2), helpstring("InstallerInfUrl Property")] HRESULT InstallerInfUrl([in] BSTR newVal);
+ [propget, id(3), helpstring("SettingUrl Property")] HRESULT SettingUrl([out, retval] BSTR* pVal);
+ [propput, id(3), helpstring("SettingUrl Property")] HRESULT SettingUrl([in] BSTR newVal);
+ [propget, id(4), helpstring("VpnServerManagerMode Property")] HRESULT VpnServerManagerMode([out, retval] BSTR* pVal);
+ [propput, id(4), helpstring("VpnServerManagerMode Property")] HRESULT VpnServerManagerMode([in] BSTR newVal);
+ [propget, id(5), helpstring("VpnServerHostname Property")] HRESULT VpnServerHostname([out, retval] BSTR* pVal);
+ [propput, id(5), helpstring("VpnServerHostname Property")] HRESULT VpnServerHostname([in] BSTR newVal);
+ [propget, id(6), helpstring("VpnServerHubName Property")] HRESULT VpnServerHubName([out, retval] BSTR* pVal);
+ [propput, id(6), helpstring("VpnServerHubName Property")] HRESULT VpnServerHubName([in] BSTR newVal);
+ [propget, id(7), helpstring("VpnServerPassword Property")] HRESULT VpnServerPassword([out, retval] BSTR* pVal);
+ [propput, id(7), helpstring("VpnServerPassword Property")] HRESULT VpnServerPassword([in] BSTR newVal);
+ [propget, id(8), helpstring("Language Property")] HRESULT LanguageID([out, retval] BSTR* pVal);
+ [propput, id(8), helpstring("Language Property")] HRESULT LanguageID([in] BSTR newVal);
+};
+
+[
+ uuid(D8FDDBA5-B33F-4B0A-8162-A771ECD32B04),
+ version(1.0),
+ helpstring("VPN Client Web Installer Version Library")
+]
+library vpnwebLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(64F1A16B-C3EE-484C-B551-35338A9BB6D2),
+ control,
+ helpstring("VPN Client Web Installer")
+ ]
+ coclass VpnWebControl
+ {
+ [default] interface IVpnWebControl;
+ };
+
+
+};
diff --git a/src/vpnweb/vpnweb.rc b/src/vpnweb/vpnweb.rc
new file mode 100644
index 00000000..9ea19494
--- /dev/null
+++ b/src/vpnweb/vpnweb.rc
@@ -0,0 +1,188 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "1 TYPELIB ""vpnweb.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_VPNWEB REGISTRY "vpnweb.rgs"
+IDR_VPNWEBCONTROL REGISTRY "VpnWebControl.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_VPNWEBCONTROL BITMAP "VpnWebControl.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_VPNWEBDLG DIALOGEX 0, 0, 240, 84
+STYLE DS_SETFONT | WS_CHILD
+FONT 11, "Segoe UI", 400, 0, 0x0
+BEGIN
+ ICON IDI_VPN,S_ICON_VPN,2,4,16,13
+ LTEXT "‚¨‘Ò‚¿‚­‚¾‚³‚¢...",S_INFO,26,4,209,59
+ CONTROL "",P_PROGRESS,"msctls_progress32",WS_BORDER,2,66,233,12
+ LTEXT "[VPN Ú‘±‚ÌŠJŽn] ƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚·‚é‚ÆAVPN Ú‘±‚ðŠJŽn‚µ‚Ü‚·B",S_INFO2,26,4,209,46
+ DEFPUSHBUTTON "VPN Ú‘±‚ÌŠJŽn",B_START,68,51,107,23
+ ICON IDI_SERVER,S_ICON_SERVER,2,4,16,13
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_VPNWEBDLG, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ TOPMARGIN, 3
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_VPN ICON "VPN.ico"
+IDI_SERVER ICON "VPNSvr.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "vpnweb"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_MESSAGE_APPTITLE "VPN ƒ\ƒtƒgƒEƒFƒA Web ƒCƒ“ƒXƒg[ƒ‰"
+ IDS_STRING10002 "VPN ƒ\ƒtƒgƒEƒFƒA Web ƒCƒ“ƒXƒg[ƒ‰‚ÍA‚±‚̃IƒyƒŒ[ƒeƒBƒ“ƒOƒVƒXƒeƒ€‚ðƒTƒ|[ƒg‚µ‚Ä‚¢‚Ü‚¹‚ñBWeb ƒCƒ“ƒXƒg[ƒ‰‚Í Windows 2000 / XP / Server 2003 / Vista / Server 2008 / 7 / Server 2008 R2 ‚ɑΉž‚µ‚Ä‚¢‚Ü‚·BŽè“®‚Å VPN ƒ\ƒtƒgƒEƒFƒA‚ðƒCƒ“ƒXƒg[ƒ‹‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_STRING10003 "VPN ƒ\ƒtƒgƒEƒFƒA‚Ìî•ñ‚ðŠm”F‚µ‚Ä‚¢‚Ü‚·..."
+ IDS_STRING10004 "ƒtƒ@ƒCƒ‹ %S ‚̃_ƒEƒ“ƒ[ƒh‚ÉŽ¸”s‚µ‚Ü‚µ‚½B\r\nVPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹‚𒆎~‚µ‚Ü‚·B"
+ IDS_STRING10005 "ƒtƒ@ƒCƒ‹ %S ‚Ì“à—e‚ª³‚µ‚­‚ ‚è‚Ü‚¹‚ñB\r\nVPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹‚𒆎~‚µ‚Ü‚·B"
+ IDS_STRING10006 "ˆêŽžƒtƒ@ƒCƒ‹ %s ‚ð쬂ł«‚Ü‚¹‚ñ‚Å‚µ‚½B"
+ IDS_STRING10007 "•K—v‚ȃf[ƒ^‚̎擾‚Æ VPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹’†...\r\n‚¨‘Ò‚¿‚­‚¾‚³‚¢B\r\n\r\n‚¨‹q—l‚̃Rƒ“ƒsƒ…[ƒ^‚ÌŒÂlî•ñ‚È‚Ç‚ªƒCƒ“ƒ^[ƒlƒbƒg‚É‘—M‚³‚ê‚邱‚Æ‚Í‚ ‚è‚Ü‚¹‚ñB"
+ IDS_STRING10008 "ƒvƒƒZƒX %S ‚ð‹N“®‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½B\r\nVPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹‚𒆎~‚µ‚Ü‚·B"
+ IDS_STRING10009 "VPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹ˆ—‚ðŠJŽn‚µ‚Ä‚¢‚Ü‚·..."
+ IDS_STRING10010 "VPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹ˆ—‚Ü‚½‚ÍÚ‘±ˆ—‚ͳí‚ÉŠJŽn‚³‚ê‚Ü‚µ‚½B\r\n\r\n‚±‚̃y[ƒW‚ð•Â‚¶‚é‚©A•Ê‚̃y[ƒW‚Ɉړ®‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B"
+ IDS_STRING10011 "ƒCƒ“ƒ^[ƒlƒbƒg‚©‚玩“®‚Ń_ƒEƒ“ƒ[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹ %S ‚ÍAM—Š‚Å‚«‚é”­sŒ³‚É‚æ‚Á‚Ä“dŽq–¼‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ‚Å‚µ‚½B\r\nŒ»Ý‚±‚̃ƒbƒZ[ƒW‚ð•\Ž¦‚µ‚Ä‚¢‚éƒvƒƒOƒ‰ƒ€‚ÌŠJ”­Œ³‚¨‚æ‚Ñ”z•zŒ³‚ÍAƒCƒ“ƒ^[ƒlƒbƒg‚©‚玩“®‚Ń_ƒEƒ“ƒ[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹ %S ‚ªˆÀ‘S‚Å‚ ‚é‚©‚Ç‚¤‚©‚ð•ÛØ‚Å‚«‚¸A‰¼‚ɃZƒLƒ…ƒŠƒeƒBãŠëŒ¯‚ȃR[ƒh‚ªŠÜ‚Ü‚ê‚Ä‚¢‚½ê‡‚Å‚àÓ”C‚𕉂¢‚Ü‚¹‚ñB\r\n\r\n‚±‚̃tƒ@ƒCƒ‹‚ðŽÀs‚·‚邱‚Ƃ̓ZƒLƒ…ƒŠƒeƒBㄧ‚³‚ê‚Ü‚¹‚ñB‚±‚̃tƒ@ƒCƒ‹‚ðM—Š‚·‚邱‚Æ‚ª‚Å‚«‚é‚©‚Ç‚¤‚©Td‚É”»’f‚µ‚Ä‚­‚¾‚³‚¢B\r\n\r\nƒ†[ƒU[‚Ì”»’f‚ÆÓ”C‚É‚æ‚è [OK] ‚ðƒNƒŠƒbƒN‚·‚é‚ÆAƒCƒ“ƒXƒg[ƒ‹ˆ—‚ð‘±s‚µ‚Ü‚·B[ƒLƒƒƒ“ƒZƒ‹] ‚ðƒNƒŠƒbƒN‚·‚é‚ÆAƒCƒ“ƒXƒg[ƒ‹ˆ—‚ð’†’f‚µ‚Ü‚·B\r\n\r\n¦ ‚±‚̃ƒbƒZ[ƒW‚ÍAƒtƒ@ƒCƒ‹ %S ‚ð—LŒø‚ȃR[ƒh–¼—pØ–¾‘‚É‚æ‚Á‚Ä–¼‚·‚邱‚Æ‚É‚æ‚è•\Ž¦‚³‚ê‚È‚­‚È‚è‚Ü‚·B"
+ IDS_STRING10012 "ƒZƒLƒ…ƒŠƒeƒB‚ÉŠÖ‚·‚éŒx"
+ IDS_STRING10013 "VPN ƒ\ƒtƒgƒEƒFƒA‚̃Cƒ“ƒXƒg[ƒ‹‚ÍAƒ†[ƒU[‚É‚æ‚Á‚ăLƒƒƒ“ƒZƒ‹‚³‚ê‚Ü‚µ‚½B"
+ IDS_STRING10014 "[‰¼‘z HUB ‚ÌŠÇ—] ƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚·‚é‚ÆAVPN ƒT[ƒo[ŠÇ—ƒ}ƒl[ƒWƒƒ‚ð‹N“®‚µ‚ĉ¼‘z HUB ‚ÌŠÇ—‚ðŠJŽn‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B"
+ IDS_STRING10015 "‰¼‘z HUB ‚ÌŠÇ—"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_MESSAGE_APPTITLE_EN "VPN Software Web Installer"
+ IDS_STRING11002 "This web installer is not supported by this operating system. Windows 2000, XP, 2003, Vista, Server 2008, 7 or Server 2008 R2 required. Please install VPN software manually."
+ IDS_STRING11003 "Verifying VPN Software..."
+ IDS_STRING11004 "Failed to download file %S.\r\nInstallation of VPN software aborted."
+ IDS_STRING11005 "Invalid file %S. \r\nInstallation of VPN software aborted."
+ IDS_STRING11006 "Failed to create temporary file %s."
+ IDS_STRING11007 "Getting data and installing VPN software...\r\nPlease wait.\r\n\r\nAny of your private infomation is not sent to the Internet."
+END
+
+STRINGTABLE
+BEGIN
+ IDS_STRING11008 "Failed to start process %S. Installation of VPN software aborted."
+ IDS_STRING11009 "Starting installation of VPN Software."
+ IDS_STRING11010 "Installation process finished. Connection process are started correctly.\r\n\r\nYou can now close your browser or move the other pages."
+ IDS_STRING11011 "The automatically downloaded file %S from the Internet is not digitally signed with a trusted certificate.\r\nThe developer and publisher do not guarantee that the downloaded file %S is safe and do not take responsibility in case of unsafe code included in the file.\r\n\r\nWe recommend to abort the installation by clicking [Cancel]. Proceed the installation by clicking [OK] at your own risk.\r\n\r\nNotice: the message will not be disappered when the file %S is signed by valid code signing certificate authentication."
+ IDS_STRING11012 "Security Alert"
+ IDS_STRING11013 "Installation cancelled by user."
+ IDS_STRING11014 "Press [Manage Virtual HUB] button to manage Virtual HUB with VPN Server Manager started."
+ IDS_STRING11015 "Manage Virtual HUB"
+ IDS_STRING11016 "You can now close your browser or move the other pages.\r\n\r\nWhen VPN Server Manager displayed, reload this page on web browser."
+ IDS_STRING11017 "Invalid Parameters for the ActiveX control.\r\n\r\nPlease check the <object> tag entry in the HTML file."
+ IDS_STRING11018 "Press Start VPN Connection to start the VPN connection."
+ IDS_STRING11019 "Start VPN Connection"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_STRING10016 "‚±‚̃y[ƒW‚ð•Â‚¶‚é‚©A•Ê‚̃y[ƒW‚Ɉړ®‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B\r\n\r\n‚à‚¤ˆê“x VPN ƒT[ƒo[ŠÇ—ƒ}ƒl[ƒWƒƒ‚ð•\Ž¦‚·‚é‚É‚ÍAWeb ƒuƒ‰ƒEƒU‚Å‚±‚̃y[ƒW‚ðÄ•\Ž¦ (XV) ‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_STRING10017 "VPN ƒ\ƒtƒgƒEƒFƒA Web ƒCƒ“ƒXƒg[ƒ‰‚Ì ActiveX ƒRƒ“ƒgƒ[ƒ‹‚ɑ΂µ‚ăpƒ‰ƒ[ƒ^‚ª“KØ‚ÉŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñB\r\n\r\nHTML ƒtƒ@ƒCƒ‹“à‚Ì <object> ƒ^ƒO‚Ì‹Lq‚ðŠm”F‚µ‚Ä‚­‚¾‚³‚¢B"
+ IDS_STRING10018 "[VPN Ú‘±‚ÌŠJŽn] ƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚·‚é‚ÆAVPN Ú‘±‚ðŠJŽn‚µ‚Ü‚·B"
+ IDS_STRING10019 "VPN Ú‘±‚ÌŠJŽn"
+END
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "vpnweb.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/vpnweb/vpnweb.rgs b/src/vpnweb/vpnweb.rgs
new file mode 100644
index 00000000..14bb7951
--- /dev/null
+++ b/src/vpnweb/vpnweb.rgs
@@ -0,0 +1,11 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'vpnweb'
+ 'vpnweb.ocx'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
diff --git a/src/vpnweb/vpnweb.vcproj b/src/vpnweb/vpnweb.vcproj
new file mode 100644
index 00000000..5945f2aa
--- /dev/null
+++ b/src/vpnweb/vpnweb.vcproj
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vpnweb"
+ ProjectGUID="{1F58A797-A861-4256-9262-CE97B923016B}"
+ RootNamespace="vpnweb"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ GenerateStublessProxies="true"
+ HeaderFileName="vpnweb.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="vpnweb_i.c"
+ ProxyFileName="vpnweb_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T;_USRDLL"
+ MinimalRebuild="true"
+ ExceptionHandling="1"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="2"
+ DisableSpecificWarnings="4995;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\not_signed\vpnweb.ocx"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ ModuleDefinitionFile="vpnweb.def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="0"
+ ImportLibrary=""
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_admin.manifest&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:no&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVpnWebOcxCab &quot;$(TargetPath)&quot; /DEST:&quot;$(OutDir)\not_signed\vpnweb.cab&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="1"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ GenerateStublessProxies="true"
+ HeaderFileName="vpnweb.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="vpnweb_i.c"
+ ProxyFileName="vpnweb_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;VPN_SPEED;_USRDLL"
+ StringPooling="false"
+ ExceptionHandling="1"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="2"
+ DisableSpecificWarnings="4995;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\not_signed\vpnweb.ocx"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib&quot;"
+ GenerateManifest="false"
+ AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;x86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ ModuleDefinitionFile="vpnweb.def"
+ DelayLoadDLLs=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="2"
+ StackReserveSize="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ ImportLibrary=""
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SetManifest &quot;$(TargetPath)&quot; /MANIFEST:x86_admin.manifest&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:no&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVpnWebOcxCab &quot;$(TargetPath)&quot; /DEST:&quot;$(OutDir)\not_signed\vpnweb.cab&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.def"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb_i.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\VpnWebControl.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnwebdlg.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VpnWebControl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnwebdlg.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnwebdlg_inner.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\VPN.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\VPNSvr.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\vpnweb.rgs"
+ >
+ </File>
+ <File
+ RelativePath=".\VpnWebControl.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\VpnWebControl.rgs"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/vpnweb/vpnweb_i.c b/src/vpnweb/vpnweb_i.c
new file mode 100644
index 00000000..a697e54f
--- /dev/null
+++ b/src/vpnweb/vpnweb_i.c
@@ -0,0 +1,85 @@
+
+
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+ /* File created by MIDL compiler version 7.00.0500 */
+/* at Sat Jan 04 19:11:13 2014
+ */
+/* Compiler settings for .\vpnweb.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include <rpc.h>
+#include <rpcndr.h>
+
+#ifdef _MIDL_USE_GUIDDEF_
+
+#ifndef INITGUID
+#define INITGUID
+#include <guiddef.h>
+#undef INITGUID
+#else
+#include <guiddef.h>
+#endif
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
+
+#else // !_MIDL_USE_GUIDDEF_
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+
+#endif !_MIDL_USE_GUIDDEF_
+
+MIDL_DEFINE_GUID(IID, IID_IVpnWebControl,0x2C954023,0x34FF,0x490B,0x86,0x1F,0x71,0xB0,0xCE,0xBC,0x03,0xB7);
+
+
+MIDL_DEFINE_GUID(IID, LIBID_vpnwebLib,0x17F2E666,0x4CC2,0x49AC,0x81,0x08,0xFA,0x82,0x9F,0x3C,0xAC,0xFD);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_VpnWebControl,0x7CF3E7C4,0x6112,0x4D72,0xA0,0xCD,0xD0,0xAD,0x7E,0xEB,0x54,0x67);
+
+#undef MIDL_DEFINE_GUID
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/src/vpnweb/vpnweb_p.c b/src/vpnweb/vpnweb_p.c
new file mode 100644
index 00000000..df03dabe
--- /dev/null
+++ b/src/vpnweb/vpnweb_p.c
@@ -0,0 +1,783 @@
+
+
+/* this ALWAYS GENERATED file contains the proxy stub code */
+
+
+ /* File created by MIDL compiler version 7.00.0500 */
+/* at Sat Jan 04 19:11:13 2014
+ */
+/* Compiler settings for .\vpnweb.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#if !defined(_M_IA64) && !defined(_M_AMD64)
+
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+
+#pragma warning( disable: 4211 ) /* redefine extern to static */
+#pragma warning( disable: 4232 ) /* dllimport identity*/
+#pragma warning( disable: 4024 ) /* array to pointer mapping*/
+#pragma warning( disable: 4152 ) /* function/data pointer conversion in expression */
+#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */
+
+#pragma optimize("", off )
+
+#define USE_STUBLESS_PROXY
+
+
+/* verify that the <rpcproxy.h> version is high enough to compile this file*/
+#ifndef __REDQ_RPCPROXY_H_VERSION__
+#define __REQUIRED_RPCPROXY_H_VERSION__ 440
+#endif
+
+
+#include "rpcproxy.h"
+#ifndef __RPCPROXY_H_VERSION__
+#error this stub requires an updated version of <rpcproxy.h>
+#endif // __RPCPROXY_H_VERSION__
+
+
+#include "vpnweb.h"
+
+#define TYPE_FORMAT_STRING_SIZE 55
+#define PROC_FORMAT_STRING_SIZE 449
+#define EXPR_FORMAT_STRING_SIZE 1
+#define TRANSMIT_AS_TABLE_SIZE 0
+#define WIRE_MARSHAL_TABLE_SIZE 1
+
+typedef struct _vpnweb_MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } vpnweb_MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _vpnweb_MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } vpnweb_MIDL_PROC_FORMAT_STRING;
+
+typedef struct _vpnweb_MIDL_EXPR_FORMAT_STRING
+ {
+ long Pad;
+ unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
+ } vpnweb_MIDL_EXPR_FORMAT_STRING;
+
+
+static RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
+
+
+extern const vpnweb_MIDL_TYPE_FORMAT_STRING vpnweb__MIDL_TypeFormatString;
+extern const vpnweb_MIDL_PROC_FORMAT_STRING vpnweb__MIDL_ProcFormatString;
+extern const vpnweb_MIDL_EXPR_FORMAT_STRING vpnweb__MIDL_ExprFormatString;
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+extern const MIDL_SERVER_INFO IVpnWebControl_ServerInfo;
+extern const MIDL_STUBLESS_PROXY_INFO IVpnWebControl_ProxyInfo;
+
+
+extern const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ];
+
+#if !defined(__RPC_WIN32__)
+#error Invalid build platform for this stub.
+#endif
+
+#if !(TARGET_IS_NT40_OR_LATER)
+#error You need a Windows NT 4.0 or later to run this stub because it uses these features:
+#error -Oif or -Oicf, [wire_marshal] or [user_marshal] attribute.
+#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
+#error This app will fail with the RPC_X_WRONG_STUB_VERSION error.
+#endif
+
+
+static const vpnweb_MIDL_PROC_FORMAT_STRING vpnweb__MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure get_InstallerExeUrl */
+
+ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x7 ), /* 7 */
+/* 8 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 10 */ NdrFcShort( 0x0 ), /* 0 */
+/* 12 */ NdrFcShort( 0x8 ), /* 8 */
+/* 14 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 16 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 18 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 20 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 22 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 24 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 26 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_InstallerExeUrl */
+
+/* 28 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 30 */ NdrFcLong( 0x0 ), /* 0 */
+/* 34 */ NdrFcShort( 0x8 ), /* 8 */
+/* 36 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 38 */ NdrFcShort( 0x0 ), /* 0 */
+/* 40 */ NdrFcShort( 0x8 ), /* 8 */
+/* 42 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 44 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 46 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 48 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 50 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 52 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 54 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_InstallerInfUrl */
+
+/* 56 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 58 */ NdrFcLong( 0x0 ), /* 0 */
+/* 62 */ NdrFcShort( 0x9 ), /* 9 */
+/* 64 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 66 */ NdrFcShort( 0x0 ), /* 0 */
+/* 68 */ NdrFcShort( 0x8 ), /* 8 */
+/* 70 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 72 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 74 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 76 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 78 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 80 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 82 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_InstallerInfUrl */
+
+/* 84 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 86 */ NdrFcLong( 0x0 ), /* 0 */
+/* 90 */ NdrFcShort( 0xa ), /* 10 */
+/* 92 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 94 */ NdrFcShort( 0x0 ), /* 0 */
+/* 96 */ NdrFcShort( 0x8 ), /* 8 */
+/* 98 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 100 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 102 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 104 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 106 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 108 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 110 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_SettingUrl */
+
+/* 112 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 114 */ NdrFcLong( 0x0 ), /* 0 */
+/* 118 */ NdrFcShort( 0xb ), /* 11 */
+/* 120 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 122 */ NdrFcShort( 0x0 ), /* 0 */
+/* 124 */ NdrFcShort( 0x8 ), /* 8 */
+/* 126 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 128 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 130 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 132 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 134 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 136 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 138 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_SettingUrl */
+
+/* 140 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 142 */ NdrFcLong( 0x0 ), /* 0 */
+/* 146 */ NdrFcShort( 0xc ), /* 12 */
+/* 148 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 150 */ NdrFcShort( 0x0 ), /* 0 */
+/* 152 */ NdrFcShort( 0x8 ), /* 8 */
+/* 154 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 156 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 158 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 160 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 162 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 164 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 166 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_VpnServerManagerMode */
+
+/* 168 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 170 */ NdrFcLong( 0x0 ), /* 0 */
+/* 174 */ NdrFcShort( 0xd ), /* 13 */
+/* 176 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 178 */ NdrFcShort( 0x0 ), /* 0 */
+/* 180 */ NdrFcShort( 0x8 ), /* 8 */
+/* 182 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 184 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 186 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 188 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 190 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 192 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 194 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_VpnServerManagerMode */
+
+/* 196 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 198 */ NdrFcLong( 0x0 ), /* 0 */
+/* 202 */ NdrFcShort( 0xe ), /* 14 */
+/* 204 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 206 */ NdrFcShort( 0x0 ), /* 0 */
+/* 208 */ NdrFcShort( 0x8 ), /* 8 */
+/* 210 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 212 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 214 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 216 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 218 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 220 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 222 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_VpnServerHostname */
+
+/* 224 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 226 */ NdrFcLong( 0x0 ), /* 0 */
+/* 230 */ NdrFcShort( 0xf ), /* 15 */
+/* 232 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 234 */ NdrFcShort( 0x0 ), /* 0 */
+/* 236 */ NdrFcShort( 0x8 ), /* 8 */
+/* 238 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 240 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 242 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 244 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 246 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 248 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 250 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_VpnServerHostname */
+
+/* 252 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 254 */ NdrFcLong( 0x0 ), /* 0 */
+/* 258 */ NdrFcShort( 0x10 ), /* 16 */
+/* 260 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 262 */ NdrFcShort( 0x0 ), /* 0 */
+/* 264 */ NdrFcShort( 0x8 ), /* 8 */
+/* 266 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 268 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 270 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 272 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 274 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 276 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 278 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_VpnServerHubName */
+
+/* 280 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 282 */ NdrFcLong( 0x0 ), /* 0 */
+/* 286 */ NdrFcShort( 0x11 ), /* 17 */
+/* 288 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 290 */ NdrFcShort( 0x0 ), /* 0 */
+/* 292 */ NdrFcShort( 0x8 ), /* 8 */
+/* 294 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 296 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 298 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 300 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 302 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 304 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 306 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_VpnServerHubName */
+
+/* 308 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 310 */ NdrFcLong( 0x0 ), /* 0 */
+/* 314 */ NdrFcShort( 0x12 ), /* 18 */
+/* 316 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 318 */ NdrFcShort( 0x0 ), /* 0 */
+/* 320 */ NdrFcShort( 0x8 ), /* 8 */
+/* 322 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 324 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 326 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 328 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 330 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 332 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 334 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_VpnServerPassword */
+
+/* 336 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 338 */ NdrFcLong( 0x0 ), /* 0 */
+/* 342 */ NdrFcShort( 0x13 ), /* 19 */
+/* 344 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 346 */ NdrFcShort( 0x0 ), /* 0 */
+/* 348 */ NdrFcShort( 0x8 ), /* 8 */
+/* 350 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 352 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 354 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 356 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 358 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 360 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 362 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_VpnServerPassword */
+
+/* 364 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 366 */ NdrFcLong( 0x0 ), /* 0 */
+/* 370 */ NdrFcShort( 0x14 ), /* 20 */
+/* 372 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 374 */ NdrFcShort( 0x0 ), /* 0 */
+/* 376 */ NdrFcShort( 0x8 ), /* 8 */
+/* 378 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 380 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 382 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 384 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 386 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 388 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 390 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure get_LanguageID */
+
+/* 392 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 394 */ NdrFcLong( 0x0 ), /* 0 */
+/* 398 */ NdrFcShort( 0x15 ), /* 21 */
+/* 400 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 402 */ NdrFcShort( 0x0 ), /* 0 */
+/* 404 */ NdrFcShort( 0x8 ), /* 8 */
+/* 406 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+/* 408 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+/* 410 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 412 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+/* 414 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 416 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 418 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_LanguageID */
+
+/* 420 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 422 */ NdrFcLong( 0x0 ), /* 0 */
+/* 426 */ NdrFcShort( 0x16 ), /* 22 */
+/* 428 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 430 */ NdrFcShort( 0x0 ), /* 0 */
+/* 432 */ NdrFcShort( 0x8 ), /* 8 */
+/* 434 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+/* 436 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+/* 438 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 440 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+/* 442 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 444 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 446 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const vpnweb_MIDL_TYPE_FORMAT_STRING vpnweb__MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x4, /* FC_RP [alloced_on_stack] */
+/* 4 */ NdrFcShort( 0x1a ), /* Offset= 26 (30) */
+/* 6 */
+ 0x13, 0x0, /* FC_OP */
+/* 8 */ NdrFcShort( 0xc ), /* Offset= 12 (20) */
+/* 10 */
+ 0x1b, /* FC_CARRAY */
+ 0x1, /* 1 */
+/* 12 */ NdrFcShort( 0x2 ), /* 2 */
+/* 14 */ 0x9, /* Corr desc: FC_ULONG */
+ 0x0, /* */
+/* 16 */ NdrFcShort( 0xfffc ), /* -4 */
+/* 18 */ 0x6, /* FC_SHORT */
+ 0x5b, /* FC_END */
+/* 20 */
+ 0x17, /* FC_CSTRUCT */
+ 0x3, /* 3 */
+/* 22 */ NdrFcShort( 0x8 ), /* 8 */
+/* 24 */ NdrFcShort( 0xfff2 ), /* Offset= -14 (10) */
+/* 26 */ 0x8, /* FC_LONG */
+ 0x8, /* FC_LONG */
+/* 28 */ 0x5c, /* FC_PAD */
+ 0x5b, /* FC_END */
+/* 30 */ 0xb4, /* FC_USER_MARSHAL */
+ 0x83, /* 131 */
+/* 32 */ NdrFcShort( 0x0 ), /* 0 */
+/* 34 */ NdrFcShort( 0x4 ), /* 4 */
+/* 36 */ NdrFcShort( 0x0 ), /* 0 */
+/* 38 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (6) */
+/* 40 */
+ 0x12, 0x0, /* FC_UP */
+/* 42 */ NdrFcShort( 0xffea ), /* Offset= -22 (20) */
+/* 44 */ 0xb4, /* FC_USER_MARSHAL */
+ 0x83, /* 131 */
+/* 46 */ NdrFcShort( 0x0 ), /* 0 */
+/* 48 */ NdrFcShort( 0x4 ), /* 4 */
+/* 50 */ NdrFcShort( 0x0 ), /* 0 */
+/* 52 */ NdrFcShort( 0xfff4 ), /* Offset= -12 (40) */
+
+ 0x0
+ }
+ };
+
+static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ] =
+ {
+
+ {
+ BSTR_UserSize
+ ,BSTR_UserMarshal
+ ,BSTR_UserUnmarshal
+ ,BSTR_UserFree
+ }
+
+ };
+
+
+
+/* Object interface: IUnknown, ver. 0.0,
+ GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IDispatch, ver. 0.0,
+ GUID={0x00020400,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IVpnWebControl, ver. 0.0,
+ GUID={0x2C954023,0x34FF,0x490B,{0x86,0x1F,0x71,0xB0,0xCE,0xBC,0x03,0xB7}} */
+
+#pragma code_seg(".orpc")
+static const unsigned short IVpnWebControl_FormatStringOffsetTable[] =
+ {
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ 0,
+ 28,
+ 56,
+ 84,
+ 112,
+ 140,
+ 168,
+ 196,
+ 224,
+ 252,
+ 280,
+ 308,
+ 336,
+ 364,
+ 392,
+ 420
+ };
+
+static const MIDL_STUBLESS_PROXY_INFO IVpnWebControl_ProxyInfo =
+ {
+ &Object_StubDesc,
+ vpnweb__MIDL_ProcFormatString.Format,
+ &IVpnWebControl_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0
+ };
+
+
+static const MIDL_SERVER_INFO IVpnWebControl_ServerInfo =
+ {
+ &Object_StubDesc,
+ 0,
+ vpnweb__MIDL_ProcFormatString.Format,
+ &IVpnWebControl_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0,
+ 0};
+CINTERFACE_PROXY_VTABLE(23) _IVpnWebControlProxyVtbl =
+{
+ &IVpnWebControl_ProxyInfo,
+ &IID_IVpnWebControl,
+ IUnknown_QueryInterface_Proxy,
+ IUnknown_AddRef_Proxy,
+ IUnknown_Release_Proxy ,
+ 0 /* (void *) (INT_PTR) -1 /* IDispatch::GetTypeInfoCount */ ,
+ 0 /* (void *) (INT_PTR) -1 /* IDispatch::GetTypeInfo */ ,
+ 0 /* (void *) (INT_PTR) -1 /* IDispatch::GetIDsOfNames */ ,
+ 0 /* IDispatch_Invoke_Proxy */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_InstallerExeUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_InstallerExeUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_InstallerInfUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_InstallerInfUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_SettingUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_SettingUrl */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_VpnServerManagerMode */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_VpnServerManagerMode */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_VpnServerHostname */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_VpnServerHostname */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_VpnServerHubName */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_VpnServerHubName */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_VpnServerPassword */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_VpnServerPassword */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::get_LanguageID */ ,
+ (void *) (INT_PTR) -1 /* IVpnWebControl::put_LanguageID */
+};
+
+
+static const PRPC_STUB_FUNCTION IVpnWebControl_table[] =
+{
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2,
+ NdrStubCall2
+};
+
+CInterfaceStubVtbl _IVpnWebControlStubVtbl =
+{
+ &IID_IVpnWebControl,
+ &IVpnWebControl_ServerInfo,
+ 23,
+ &IVpnWebControl_table[-3],
+ CStdStubBuffer_DELEGATING_METHODS
+};
+
+static const MIDL_STUB_DESC Object_StubDesc =
+ {
+ 0,
+ NdrOleAllocate,
+ NdrOleFree,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ vpnweb__MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x20000, /* Ndr library version */
+ 0,
+ 0x70001f4, /* MIDL Version 7.0.500 */
+ 0,
+ UserMarshalRoutines,
+ 0, /* notify & notify_flag routine table */
+ 0x1, /* MIDL flag */
+ 0, /* cs routines */
+ 0, /* proxy/server info */
+ 0
+ };
+
+const CInterfaceProxyVtbl * _vpnweb_ProxyVtblList[] =
+{
+ ( CInterfaceProxyVtbl *) &_IVpnWebControlProxyVtbl,
+ 0
+};
+
+const CInterfaceStubVtbl * _vpnweb_StubVtblList[] =
+{
+ ( CInterfaceStubVtbl *) &_IVpnWebControlStubVtbl,
+ 0
+};
+
+PCInterfaceName const _vpnweb_InterfaceNamesList[] =
+{
+ "IVpnWebControl",
+ 0
+};
+
+const IID * _vpnweb_BaseIIDList[] =
+{
+ &IID_IDispatch,
+ 0
+};
+
+
+#define _vpnweb_CHECK_IID(n) IID_GENERIC_CHECK_IID( _vpnweb, pIID, n)
+
+int __stdcall _vpnweb_IID_Lookup( const IID * pIID, int * pIndex )
+{
+
+ if(!_vpnweb_CHECK_IID(0))
+ {
+ *pIndex = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+const ExtendedProxyFileInfo vpnweb_ProxyFileInfo =
+{
+ (PCInterfaceProxyVtblList *) & _vpnweb_ProxyVtblList,
+ (PCInterfaceStubVtblList *) & _vpnweb_StubVtblList,
+ (const PCInterfaceName * ) & _vpnweb_InterfaceNamesList,
+ (const IID ** ) & _vpnweb_BaseIIDList,
+ & _vpnweb_IID_Lookup,
+ 1,
+ 2,
+ 0, /* table of [async_uuid] interfaces */
+ 0, /* Filler1 */
+ 0, /* Filler2 */
+ 0 /* Filler3 */
+};
+#pragma optimize("", on )
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+
+#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/
+
diff --git a/src/vpnweb/vpnwebdlg.c b/src/vpnweb/vpnwebdlg.c
new file mode 100644
index 00000000..5bb2b7fc
--- /dev/null
+++ b/src/vpnweb/vpnwebdlg.c
@@ -0,0 +1,1581 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpnwebdlg.c
+// VPN Client Web Installer
+
+#include <GlobalConst.h>
+
+#define VPNWEBDLG_C
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <winsock2.h>
+#include <windows.h>
+#include <Wintrust.h>
+#include <Softpub.h>
+#include <wincrypt.h>
+#include <wininet.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <locale.h>
+#include <Msi.h>
+#include <Msiquery.h>
+#include "vpnwebdlg.h"
+#include "vpnwebdlg_inner.h"
+#include "resource.h"
+
+#pragma comment(lib, "wininet.lib")
+
+static VPNWEBDLG_INIT data;
+static bool inited = false;
+static VW_TASK task;
+static bool clicked_flag = false;
+
+// Check the signature of the EXE file, and displays a warning if dangerous
+bool VwCheckExeSign(HWND hWnd, char *exe)
+{
+ wchar_t tmp[2048];
+ bool danger = true;
+ wchar_t *warningMessage = msgWarning;
+ wchar_t *warningMessageTitle = msgWarningTitle;
+ // Validate arguments
+ if (hWnd == NULL || exe == NULL)
+ {
+ return false;
+ }
+
+ if (VwCheckFileDigitalSignature(hWnd, exe, &danger))
+ {
+ if (danger == false)
+ {
+ // Safe
+ return true;
+ }
+ else
+ {
+ // Show the message because there is potentially dangerous
+ swprintf(tmp, sizeof(tmp) / 2, warningMessage,
+ VwUrlToFileName(exe), VwUrlToFileName(exe), VwUrlToFileName(exe));
+
+ if (MessageBoxW(hWnd, tmp, warningMessageTitle,
+ MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION) == IDOK)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+ else
+ {
+ // Danger
+ return false;
+ }
+}
+
+// Check the digital signature of the file
+bool VwCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger)
+{
+ HRESULT ret = S_OK;
+ wchar_t tmp[MAX_PATH];
+ LONG (WINAPI *_WinVerifyTrust)(HWND, GUID *, LPVOID) = NULL;
+ HINSTANCE hDll;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (danger != NULL)
+ {
+ *danger = false;
+ }
+
+ swprintf(tmp, sizeof(tmp), L"%S", name);
+
+ hDll = LoadLibrary("Wintrust.dll");
+ if (hDll == NULL)
+ {
+ return false;
+ }
+
+ _WinVerifyTrust =
+ (LONG (__stdcall *)(HWND,GUID *,LPVOID))
+ GetProcAddress(hDll, "WinVerifyTrust");
+ if (_WinVerifyTrust == NULL)
+ {
+ FreeLibrary(hDll);
+ return false;
+ }
+ else
+ {
+ GUID action_id = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+ WINTRUST_FILE_INFO file;
+ WINTRUST_DATA data;
+
+ Zero(&file, sizeof(file));
+ file.cbStruct = sizeof(file);
+ file.pcwszFilePath = tmp;
+
+ Zero(&data, sizeof(data));
+ data.cbStruct = sizeof(data);
+ data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
+ data.dwUIChoice = (hWnd != NULL ? WTD_UI_NOGOOD : WTD_UI_NONE);
+ data.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
+ data.dwUnionChoice = WTD_CHOICE_FILE;
+ data.pFile = &file;
+
+ ret = _WinVerifyTrust(hWnd, &action_id, &data);
+
+ if (ret == ERROR_SUCCESS && danger != NULL)
+ {
+ if (hWnd != NULL)
+ {
+ if (VwCheckFileDigitalSignature(NULL, name, NULL) == false)
+ {
+ // It's a dangerous file, but the user selected the [OK]
+ *danger = true;
+ }
+ }
+ }
+ }
+
+ FreeLibrary(hDll);
+
+ if (ret != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Task execution thread
+DWORD CALLBACK VwTaskThread(void *param)
+{
+ HWND hWnd = data.hWnd;
+ VW_FILE *f;
+
+ // Download the Inf file
+ f = VwOpenFile(data.InstallerInfUrl);
+
+ if (f == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ swprintf(tmp, sizeof(tmp) / 2, msgInfDownloadFailed, VwUrlToFileName(data.InstallerInfUrl));
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+ else
+ {
+ UINT size = 0;
+ UINT bufsize = 0;
+ UINT readsize = 1024;
+ UINT build = 0;
+ char *buf;
+
+ // Read all the contents of the file
+ buf = ZeroMalloc(size);
+
+ while (true)
+ {
+ UINT ret;
+
+ bufsize = size + readsize;
+ buf = ReAlloc(buf, bufsize);
+ ret = VwReadFile(f, buf + size, readsize);
+
+ if (ret == INFINITE || size >= 65536 || task.Halt)
+ {
+ wchar_t tmp[MAX_SIZE];
+ // Download Failed
+ Free(buf);
+ VwCloseFile(f);
+ swprintf(tmp, sizeof(tmp) / 2, msgInfDownloadFailed, VwUrlToFileName(data.InstallerInfUrl));
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+ else if (ret == 0)
+ {
+ // Download Complete
+ break;
+ }
+ else
+ {
+ size += ret;
+ }
+ }
+
+ VwCloseFile(f);
+
+ bufsize = size + 1;
+ buf = ReAlloc(buf, bufsize);
+ buf[size] = 0;
+
+ build = VwGetBuildFromVpnInstallInf(buf);
+ if (build == 0)
+ {
+ wchar_t tmp[MAX_SIZE];
+ // Build number incorrect
+ Free(buf);
+ swprintf(tmp, sizeof(tmp) / 2, msgBadInfFile, VwUrlToFileName(data.InstallerInfUrl));
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+ else
+ {
+ char tmpdir[MAX_SIZE];
+ char wintmp[MAX_SIZE];
+ char temp_vpninstaller_exe[MAX_SIZE];
+ char temp_vpninstaller_exe_tmp[MAX_SIZE];
+ char temp_vpninstaller_inf[MAX_SIZE];
+ HANDLE h;
+
+ GetTempPath(sizeof(wintmp), wintmp);
+
+ if (lstrlen(wintmp) >= 1)
+ {
+ if (wintmp[lstrlen(wintmp) - 1] == '\\')
+ {
+ wintmp[lstrlen(wintmp) - 1] = 0;
+ }
+ }
+
+ // Generate a temporary directory name
+ _snprintf(tmpdir, sizeof(tmpdir), "%s\\vpninstall_%u", wintmp, build);
+
+ // Generate a temporary file name
+ _snprintf(temp_vpninstaller_exe, sizeof(temp_vpninstaller_exe),
+ "%s\\%s", tmpdir, VPNINSTALL_EXE_FILENAME);
+ _snprintf(temp_vpninstaller_exe_tmp, sizeof(temp_vpninstaller_exe_tmp),
+ "%s\\%s", tmpdir, VPNINSTALL_EXE_FILENAME_TMP);
+ _snprintf(temp_vpninstaller_inf, sizeof(temp_vpninstaller_inf),
+ "%s\\%s", tmpdir, VPNINSTALL_INF_FILENAME);
+
+ // Create a directory
+ MakeDir(tmpdir);
+
+ // Save the inf file
+ h = FileCreate(temp_vpninstaller_inf);
+ if (h == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ // File creation failure
+ Free(buf);
+ swprintf(tmp, sizeof(tmp) / 2, msgWriteFailed, VPNINSTALL_INF_FILENAME);
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+
+ FileWrite(h, buf, lstrlen(buf));
+ FileClose(h);
+
+ Free(buf);
+
+ // Download the vpninstall.exe
+ h = FileOpen(temp_vpninstaller_exe, false);
+ if (h == NULL)
+ {
+ UCHAR *buffer;
+ UINT buffer_size = 65536;
+ UINT total_size, current_size;
+
+ // Perform the download so download unfinished
+ VwPrint(hWnd, msgDownloading);
+ Show(hWnd, P_PROGRESS);
+ SetPos(hWnd, P_PROGRESS, 0);
+
+ f = VwOpenFile(data.InstallerExeUrl);
+ if (f == NULL)
+ {
+ // Download Failed
+ wchar_t tmp[MAX_SIZE];
+
+ swprintf(tmp, sizeof(tmp) / 2, msgInfDownloadFailed, VwUrlToFileName(data.InstallerExeUrl));
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+
+ total_size = VwGetFileSize(f);
+ if (total_size == 0)
+ {
+ total_size = 2 * 1024 * 1024;
+ }
+ current_size = 0;
+
+ h = FileCreate(temp_vpninstaller_exe_tmp);
+ if (h == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ // File creation failure
+ swprintf(tmp, sizeof(tmp) / 2, msgWriteFailed, VPNINSTALL_EXE_FILENAME);
+ VwPrint(hWnd, tmp);
+ VwCloseFile(f);
+ return 0;
+ }
+
+ buffer = ZeroMalloc(buffer_size);
+
+ while (true)
+ {
+ UINT ret;
+
+ ret = VwReadFile(f, buffer, buffer_size);
+
+ if (ret == INFINITE || task.Halt || current_size >= (8 * 1024 * 1024))
+ {
+ // Download Failed
+ wchar_t tmp[MAX_SIZE];
+
+DOWNLOAD_FAILED:
+ swprintf(tmp, sizeof(tmp) / 2, msgInfDownloadFailed, VwUrlToFileName(data.InstallerExeUrl));
+ VwPrint(hWnd, tmp);
+ Free(buffer);
+ FileClose(h);
+ VwCloseFile(f);
+ return 0;
+ }
+ else if (ret == 0)
+ {
+ // Download Complete
+ break;
+ }
+ else
+ {
+ UINT pos = 0;
+ current_size += ret;
+
+ pos = (UINT)((float)current_size * 100.0f / (float)total_size);
+ SetPos(hWnd, P_PROGRESS, pos);
+
+ if (FileWrite(h, buffer, ret) == false)
+ {
+ goto DOWNLOAD_FAILED;
+ }
+ }
+ }
+
+ Free(buffer);
+ FileClose(h);
+ VwCloseFile(f);
+
+ Hide(hWnd, P_PROGRESS);
+
+ // Rename the file
+ if (MoveFile(temp_vpninstaller_exe_tmp, temp_vpninstaller_exe) == false)
+ {
+ // Download Failed
+ wchar_t tmp[MAX_SIZE];
+ swprintf(tmp, sizeof(tmp) / 2, msgInfDownloadFailed, VwUrlToFileName(data.InstallerExeUrl));
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+ }
+ else
+ {
+ // Download has already been completed
+ FileClose(h);
+ }
+
+ VwPrint(hWnd, msgProcessCreating);
+
+ if (VwCheckExeSign(hWnd, temp_vpninstaller_exe))
+ {
+ // Starting the vpninstall.exe
+ STARTUPINFO info;
+ PROCESS_INFORMATION ret;
+ char cmdline[MAX_SIZE];
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = SW_SHOWDEFAULT;
+
+ if (data.VpnServerManagerMode == FALSE)
+ {
+ if (lstrlen(data.SettingUrl) == 0)
+ {
+ _snprintf(cmdline, sizeof(cmdline) - 1,
+ "\"%s\" /web", temp_vpninstaller_exe);
+ }
+ else
+ {
+ _snprintf(cmdline, sizeof(cmdline) - 1,
+ "\"%s\" /web \"%s\"", temp_vpninstaller_exe, data.SettingUrl);
+ }
+ }
+ else
+ {
+ char args[MAX_SIZE];
+
+ _snprintf(args, sizeof(args) - 1,
+ "\"\"%s\"\" /HUB:\"\"%s\"\" /PASSWORD:\"\"%s\"\" /HWND:%I64u",
+ data.VpnServerHostname,
+ data.VpnServerHubName,
+ data.VpnServerPassword,
+ (UINT64)/*data.hControlWnd*/0ULL);
+
+ _snprintf(cmdline, sizeof(cmdline) - 1,
+ "\"%s\" /web \"%s\"", temp_vpninstaller_exe, args);
+ }
+
+ if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
+ NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &ret) == false)
+ {
+ // Process startup failure
+ wchar_t tmp[MAX_SIZE];
+ swprintf(tmp, sizeof(tmp) / 2, msgProcessFailed, VPNINSTALL_EXE_FILENAME);
+ VwPrint(hWnd, tmp);
+ return 0;
+ }
+
+ if (data.VpnServerManagerMode == FALSE)
+ {
+ VwPrint(hWnd, msgProcessCreated);
+ }
+ else
+ {
+ VwPrint(hWnd, msgProcessCreatedForVpnServer);
+ }
+ }
+ else
+ {
+ VwPrint(hWnd, msgUserCancal);
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Get the build number from file vpninstall.inf
+UINT VwGetBuildFromVpnInstallInf(char *buf)
+{
+ UINT i, len;
+ char tmp[MAX_SIZE];
+ UINT wp;
+ char seps[] = " \t";
+
+ len = lstrlen(buf);
+
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ char c = buf[i];
+
+ if (c == 13 || c == 10)
+ {
+ tmp[wp] = 0;
+ wp = 0;
+
+ if (lstrlen(tmp) >= 1)
+ {
+ char *token = strtok(tmp, seps);
+ if (token != NULL && lstrcmpi(token, VPNINSTALL_INF_BUILDTAG) == 0)
+ {
+ token = strtok(NULL, seps);
+ if (token != NULL)
+ {
+ return (UINT)strtod(token, NULL);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((wp + 2) < sizeof(tmp))
+ {
+ tmp[wp++] = c;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Convert the URL to the file name
+char *VwUrlToFileName(char *url)
+{
+ UINT i, len;
+ char *ret = url;
+ bool b = true;
+ len = lstrlen(url);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = url[i];
+
+ if (c == '?' || c == '#')
+ {
+ b = false;
+ }
+
+ if (b)
+ {
+ if (c == '/' || c == '\\')
+ {
+ if (lstrlen(url + i + 1) > 1)
+ {
+ ret = url + i + 1;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Initialization
+void VwOnInit(HWND hWnd)
+{
+ inited = false;
+ if (IsSupportedOs() == false)
+ {
+ // The OS is unsupported
+ Hide(hWnd, P_PROGRESS);
+ SetDlgItemTextA(hWnd, S_INFO, msgNotSupported);
+ return;
+ }
+
+ if(data.VpnServerManagerMode == FALSE)
+ {
+ SetText(hWnd, S_INFO2, msgStartTextForVpnClient);
+ SetText(hWnd, B_START, msgButtonForVpnClient);
+ }
+ else
+ {
+ SetText(hWnd, S_INFO2, msgStartTextForVpnServer);
+ SetText(hWnd, B_START, msgButtonForVpnServer);
+ }
+
+ if (lstrlen(data.InstallerExeUrl) == 0 || lstrlen(data.InstallerInfUrl) == 0)
+ {
+ // Parameter is not specified
+ Hide(hWnd, P_PROGRESS);
+ SetDlgItemTextA(hWnd, S_INFO, msgNoParam);
+ return;
+ }
+
+ if (data.VpnServerManagerMode == FALSE)
+ {
+ Show(hWnd, S_ICON_VPN);
+ Hide(hWnd, S_ICON_SERVER);
+ }
+ else
+ {
+ Show(hWnd, S_ICON_SERVER);
+ Hide(hWnd, S_ICON_VPN);
+
+
+ }
+
+ Hide(hWnd, P_PROGRESS);
+ Hide(hWnd, S_INFO);
+ Show(hWnd, S_INFO2);
+ Show(hWnd, B_START);
+ clicked_flag = false;
+
+ Zero(&task, sizeof(task));
+}
+
+// Release
+void VwOnFree(HWND hWnd)
+{
+ if (inited == false)
+ {
+ return;
+ }
+
+ task.Halt = true;
+
+ if (task.Thread != NULL)
+ {
+ while (true)
+ {
+ if (WaitForSingleObject(task.Thread, 30) != WAIT_TIMEOUT)
+ {
+ break;
+ }
+ DoEvents(hWnd);
+ }
+ CloseHandle(task.Thread);
+ task.Thread = NULL;
+ }
+}
+
+// Show the string
+void VwPrint(HWND hWnd, wchar_t *str)
+{
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ SetText(hWnd, S_INFO, str);
+}
+
+// Dialog procedure
+INT_PTR CALLBACK VpnWebDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ VwOnInit(hWnd);
+ break;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case B_START:
+ if (clicked_flag == false)
+ {
+ clicked_flag = true;
+ SetTimer(hWnd, 1, 1, NULL);
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ VwOnFree(hWnd);
+ break;
+
+ case WM_CLOSE:
+ return 1;
+
+ case WM_TIMER:
+ switch (wParam)
+ {
+ case 1:
+ KillTimer(hWnd, 1);
+ inited = true;
+ Hide(hWnd, B_START);
+ Hide(hWnd, S_INFO2);
+ Show(hWnd, S_INFO);
+ VwPrint(hWnd, msgInfDownloag);
+ task.Thread = VwNewThread(VwTaskThread, NULL);
+ break;
+
+ case 2:
+ KillTimer(hWnd, 2);
+ SendMessage(hWnd, WM_COMMAND, B_START, 0);
+ break;
+ }
+ break;
+
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ return (UINT)GetStockObject(WHITE_BRUSH);
+ }
+
+ return 0;
+}
+
+// Set the string to window
+void SetText(HWND hWnd, UINT id, wchar_t *str)
+{
+ wchar_t tmp[512];
+ // Validate arguments
+ if (hWnd == NULL || str == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ GetWindowTextW(DlgItem(hWnd, id), tmp, sizeof(tmp) - 1);
+
+ if (lstrcmpW(tmp, str) == 0)
+ {
+ return;
+ }
+
+ SetWindowTextW(DlgItem(hWnd, id), str);
+}
+
+// Check whether the OS is supported
+bool IsSupportedOs()
+{
+ OSVERSIONINFO ver;
+
+ Zero(&ver, sizeof(ver));
+
+ ver.dwOSVersionInfoSize = sizeof(ver);
+ if (GetVersionExA(&ver) == false)
+ {
+ return false;
+ }
+
+ if (ver.dwMajorVersion <= 4)
+ {
+ return false;
+ }
+
+ if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || ver.dwPlatformId == VER_PLATFORM_WIN32s)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Show a message box
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg)
+{
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = L"MessageBox";
+ }
+
+ return MessageBoxW(hWnd, msg, msgAppTitle, flag);
+}
+
+// Create a directory
+bool MakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return CreateDirectory(name, NULL);
+}
+
+// Create a file
+HANDLE FileCreate(char *name)
+{
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == NULL || h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ return h;
+}
+
+// Open the file
+HANDLE FileOpen(char *name, bool write_mode)
+{
+ HANDLE h;
+ DWORD lock_mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (write_mode)
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ else
+ {
+ lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+
+ h = CreateFile(name,
+ (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
+ lock_mode,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ return h;
+}
+
+// Close the file
+void FileClose(HANDLE h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ FlushFileBuffers(h);
+
+ CloseHandle(h);
+}
+
+// Read from the file
+bool FileRead(HANDLE h, void *buf, UINT size)
+{
+ UINT read_size;
+ // Validate arguments
+ if (h == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ if (ReadFile(h, buf, size, &read_size, NULL) == false)
+ {
+ return false;
+ }
+
+ if (read_size != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write to the file
+bool FileWrite(HANDLE h, void *buf, UINT size)
+{
+ DWORD write_size;
+ // Validate arguments
+ if (h == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ if (WriteFile(h, buf, size, &write_size, NULL) == false)
+ {
+ return false;
+ }
+
+ if (write_size != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the file size
+UINT64 FileSize(HANDLE h)
+{
+ UINT64 ret;
+ DWORD tmp;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return 0;
+ }
+
+ tmp = 0;
+ ret = GetFileSize(h, &tmp);
+ if (ret == (DWORD)-1)
+ {
+ return 0;
+ }
+
+ if (tmp != 0)
+ {
+ ret += (UINT64)tmp * 4294967296ULL;
+ }
+
+ return ret;
+}
+
+// Open the Internet file
+VW_FILE *VwOpenFile(char *path)
+{
+ VW_FILE *f;
+ HINTERNET hHttpFile;
+ HINTERNET hInternet = InternetOpenA(
+ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)",
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL, NULL, 0);
+ UINT size;
+ UINT sizesize;
+ char tmp[8];
+ // Validate arguments
+ if (path == NULL)
+ {
+ return NULL;
+ }
+
+ if (hInternet == NULL)
+ {
+ return NULL;
+ }
+
+ hHttpFile = InternetOpenUrlA(hInternet, path, NULL, 0,
+ INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0);
+
+ if (hHttpFile == NULL)
+ {
+ InternetCloseHandle(hInternet);
+ return NULL;
+ }
+
+ size = 0;
+ sizesize = sizeof(size);
+
+ ZeroMemory(tmp, sizeof(tmp));
+
+ if (strlen(path) >= 6)
+ {
+ CopyMemory(tmp, path, 6);
+ }
+
+ if (lstrcmpi(tmp, "ftp://") == 0)
+ {
+ // ftp
+ DWORD high = 0;
+
+ size = FtpGetFileSize(hHttpFile, &high);
+ }
+ else
+ {
+ UINT errorcode = 0;
+ UINT errorcode_size = sizeof(errorcode);
+
+ // http
+ if (HttpQueryInfo(hHttpFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
+ &size, &sizesize, NULL) == false)
+ {
+ size = 0;
+ }
+
+ if (HttpQueryInfo(hHttpFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
+ &errorcode, &errorcode_size, NULL) == false ||
+ (errorcode / 100) != 2)
+ {
+ // HTTP getting error
+ InternetCloseHandle(hInternet);
+ InternetCloseHandle(hHttpFile);
+ return NULL;
+ }
+ }
+
+ f = ZeroMalloc(sizeof(VW_FILE));
+ f->hInternet = hInternet;
+ f->hHttpFile = hHttpFile;
+ f->FileSize = size;
+
+ return f;
+}
+
+// Get the Internet file size
+UINT VwGetFileSize(VW_FILE *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ return f->FileSize;
+}
+
+// Read from the Internet file
+UINT VwReadFile(VW_FILE *f, void *buf, UINT size)
+{
+ UINT readsize = 0;
+ // Validate arguments
+ if (f == NULL || buf == NULL)
+ {
+ return INFINITE;
+ }
+
+ if (InternetReadFile(f->hHttpFile, buf, size, &readsize) == false)
+ {
+ return INFINITE;
+ }
+
+ return readsize;
+}
+
+// Close the Internet file
+void VwCloseFile(VW_FILE *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ InternetCloseHandle(f->hHttpFile);
+ InternetCloseHandle(f->hInternet);
+
+ Free(f);
+}
+
+// Memory reallocation
+void *ReAlloc(void *p, UINT size)
+{
+ void *ret;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ ret = realloc(p, size);
+ if (ret == NULL)
+ {
+ _exit(0);
+ }
+
+ return ret;
+}
+
+// Memory allocation
+void *ZeroMalloc(UINT size)
+{
+ void *p;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ p = malloc(size);
+ if (p == NULL)
+ {
+ _exit(0);
+ }
+
+ Zero(p, size);
+
+ return p;
+}
+
+// Memory clear
+void Zero(void *p, UINT size)
+{
+ if (p != NULL)
+ {
+ ZeroMemory(p, size);
+ }
+}
+
+// Memory release
+void Free(void *p)
+{
+ if (p != NULL)
+ {
+ free(p);
+ }
+}
+
+// Thread creation
+HANDLE VwNewThread(LPTHREAD_START_ROUTINE start, void *param)
+{
+ HANDLE h;
+ DWORD id;
+ // Validate arguments
+ if (start == NULL)
+ {
+ return NULL;
+ }
+
+ h = (HANDLE)_beginthreadex(NULL, 0, start, param, 0, &id);
+
+ return h;
+}
+
+// Thread release
+void VwFreeThread(HANDLE h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(h);
+}
+
+// Dialog procedure that does not do anything
+INT_PTR CALLBACK VpnWebDummyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+// Initialization of the dialog
+HWND InitVpnWebDlg(VPNWEBDLG_INIT *init)
+{
+ HWND hWnd;
+ // Validate arguments
+ if (init == NULL)
+ {
+ return NULL;
+ }
+
+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
+ setlocale(LC_ALL, "");
+
+ ZeroMemory(&data, sizeof(data));
+ CopyMemory(&data, init, sizeof(data));
+
+ LoadTables(data.LanguageId);
+
+ hWnd = CreateDialog(hDllInstance, MAKEINTRESOURCE(IDD_VPNWEBDLG),
+ data.hControlWnd, VpnWebDlgProc);
+
+ data.hWnd = hWnd;
+
+ ShowWindow(hWnd, SW_SHOW);
+
+ return hWnd;
+}
+
+// Exit the dialog
+void FreeVpnWebDlg()
+{
+ DestroyWindow(data.hWnd);
+}
+
+// Get the size of the dialog
+void GetVpnWebDlgSize(SIZE *size)
+{
+ HWND hWnd;
+ RECT rect;
+ // Validate arguments
+ if (size == NULL)
+ {
+ return;
+ }
+
+ hWnd = CreateDialog(hDllInstance, MAKEINTRESOURCE(IDD_VPNWEBDLG),
+ GetDesktopWindow(), VpnWebDummyDlgProc);
+
+ ZeroMemory(&rect, sizeof(rect));
+ GetWindowRect(hWnd, &rect);
+
+ DestroyWindow(hWnd);
+
+ size->cx = rect.right - rect.left;
+ size->cy = rect.bottom - rect.top;
+}
+
+
+// Get the item in the dialog
+HWND DlgItem(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ if (id == 0)
+ {
+ return hWnd;
+ }
+ else
+ {
+ return GetDlgItem(hWnd, id);
+ }
+}
+
+// Hide the window
+void Hide(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsShow(hWnd, id))
+ {
+ ShowWindow(DlgItem(hWnd, id), SW_HIDE);
+ }
+}
+
+// Display the window
+void Show(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsHide(hWnd, id))
+ {
+ ShowWindow(DlgItem(hWnd, id), SW_SHOW);
+ }
+}
+
+// Changing the visibility setting
+void SetShow(HWND hWnd, UINT id, bool b)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (b)
+ {
+ Show(hWnd, id);
+ }
+ else
+ {
+ Hide(hWnd, id);
+ }
+}
+
+// Get whether the window is shown
+bool IsShow(HWND hWnd, UINT id)
+{
+ return IsHide(hWnd, id) ? false : true;
+}
+
+// Get whether the window is hidden
+bool IsHide(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return true;
+ }
+
+ if (GetStyle(hWnd, id) & WS_VISIBLE)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Remove the window style
+void RemoveExStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetExStyle(hWnd, id);
+ if ((old & style) == 0)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old & ~style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Set the window style
+void SetExStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetExStyle(hWnd, id);
+ if (old & style)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old | style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Get the window style
+UINT GetExStyle(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return GetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE);
+}
+
+// Remove the window style
+void RemoveStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetStyle(hWnd, id);
+ if ((old & style) == 0)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old & ~style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Set the window style
+void SetStyle(HWND hWnd, UINT id, UINT style)
+{
+ UINT old;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ old = GetStyle(hWnd, id);
+ if (old & style)
+ {
+ return;
+ }
+
+ SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old | style);
+ Refresh(DlgItem(hWnd, id));
+}
+
+// Get the window style
+UINT GetStyle(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return GetWindowLong(DlgItem(hWnd, id), GWL_STYLE);
+}
+
+// Update the window
+void Refresh(HWND hWnd)
+{
+ HWND parent;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ DoEvents(hWnd);
+ UpdateWindow(hWnd);
+ DoEvents(hWnd);
+
+ parent = GetParent(hWnd);
+ if (parent != NULL)
+ {
+ Refresh(parent);
+ }
+}
+
+// Handle the event
+void DoEvents(HWND hWnd)
+{
+ MSG msg;
+
+ if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ UpdateWindow(hWnd);
+
+ if (hWnd)
+ {
+ DoEvents(NULL);
+ }
+}
+
+// Disable the window
+void Disable(HWND hWnd, UINT id)
+{
+ SetEnable(hWnd, id, false);
+}
+
+// Enable the window
+void Enable(HWND hWnd, UINT id)
+{
+ SetEnable(hWnd, id, true);
+}
+
+// Set the enabled state of the window
+void SetEnable(HWND hWnd, UINT id, bool b)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ if (b == false)
+ {
+ if (IsEnable(hWnd, id))
+ {
+ EnableWindow(DlgItem(hWnd, id), false);
+ Refresh(DlgItem(hWnd, id));
+ }
+ }
+ else
+ {
+ if (IsDisable(hWnd, id))
+ {
+ EnableWindow(DlgItem(hWnd, id), true);
+ Refresh(DlgItem(hWnd, id));
+ }
+ }
+}
+
+// Examine whether the Window is disabled
+bool IsDisable(HWND hWnd, UINT id)
+{
+ return IsEnable(hWnd, id) ? false : true;
+}
+
+// Examine whether the window is enabled
+bool IsEnable(HWND hWnd, UINT id)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return false;
+ }
+
+ return IsWindowEnabled(DlgItem(hWnd, id));
+}
+
+// Set the position of the progress bar
+void SetPos(HWND hWnd, UINT id, UINT pos)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, PBM_SETPOS, pos, 0);
+}
+
+// Set the range of the progress bar
+void SetRange(HWND hWnd, UINT id, UINT start, UINT end)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ SendMsg(hWnd, id, PBM_SETRANGE32, start, end);
+}
+
+// Transmit a message to the control
+UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ return (UINT)SendMessageA(DlgItem(hWnd, id), msg, wParam, lParam);
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnweb/vpnwebdlg.h b/src/vpnweb/vpnwebdlg.h
new file mode 100644
index 00000000..74158820
--- /dev/null
+++ b/src/vpnweb/vpnwebdlg.h
@@ -0,0 +1,122 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpnwebdlg.h
+// Header of vpnwebdlg.c
+
+#ifndef VPNWEBDLG_H
+#define VPNWEBDLG_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern HINSTANCE hDllInstance;
+
+typedef struct VPNWEBDLG_INIT
+{
+ char InstallerExeUrl[512];
+ char InstallerInfUrl[512];
+ char SettingUrl[512];
+ BOOL VpnServerManagerMode;
+ char VpnServerHostname[512];
+ char VpnServerHubName[512];
+ char VpnServerPassword[512];
+
+ char LanguageId[32];
+ HWND hControlWnd;
+ HWND hWnd;
+} VPNWEBDLG_INIT;
+
+HWND InitVpnWebDlg(VPNWEBDLG_INIT *init);
+void FreeVpnWebDlg();
+void GetVpnWebDlgSize(SIZE *size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // VPNWEBDLG_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/vpnweb/vpnwebdlg_inner.h b/src/vpnweb/vpnwebdlg_inner.h
new file mode 100644
index 00000000..9cb215b4
--- /dev/null
+++ b/src/vpnweb/vpnwebdlg_inner.h
@@ -0,0 +1,255 @@
+// SoftEther VPN Source Code
+// Cedar Communication Module
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// vpnwebdlg.h
+// Header of vpnwebdlg.c (Inner)
+
+
+#define VPNINSTALL_EXE_FILENAME "vpninstall.exe"
+#define VPNINSTALL_EXE_FILENAME_TMP "vpninstall.exe.tmp"
+#define VPNINSTALL_INF_FILENAME "vpninstall.inf"
+#define VPNINSTALL_INF_BUILDTAG "VpnInstallBuild"
+
+#include "resource.h"
+extern HINSTANCE hDllInstance;
+#define MESSAGE_OFFSET_JP IDS_MESSAGE_APPTITLE
+#define MESSAGE_OFFSET_EN IDS_MESSAGE_APPTITLE_EN
+#define MESSAGE_OFFSET_RES1 12000
+#define MESSAGE_OFFSET_RES2 13000
+
+static wchar_t *msgAppTitle = NULL;
+static char *msgNotSupported = NULL;
+static wchar_t *msgInfDownloag = NULL;
+static wchar_t *msgInfDownloadFailed = NULL;
+static wchar_t *msgBadInfFile = NULL;
+static wchar_t *msgWriteFailed = NULL;
+static wchar_t *msgDownloading = NULL;
+static wchar_t *msgProcessFailed = NULL;
+static wchar_t *msgProcessCreating =NULL;
+static wchar_t *msgProcessCreated = NULL;
+static wchar_t *msgWarning = NULL;
+static wchar_t *msgWarningTitle = NULL;
+static wchar_t *msgUserCancal = NULL;
+static wchar_t *msgStartTextForVpnServer = NULL;
+static wchar_t *msgButtonForVpnServer = NULL;
+static wchar_t *msgProcessCreatedForVpnServer = NULL;
+static wchar_t *msgStartTextForVpnClient = NULL;
+static wchar_t *msgButtonForVpnClient = NULL;
+static char *msgNoParam = NULL;
+
+static void **_messages;
+
+typedef enum MessageType {
+ _e_msgAppTitle,_e_msgNotSupported,_e_msgInfDownloag,_e_msgInfDownloadFailed,
+ _e_msgBadInfFile,_e_msgWriteFailed,_e_msgDownloading,_e_msgProcessFailed,
+ _e_msgProcessCreating,_e_msgProcessCreated,_e_msgWarning,_e_msgWarningTitle,
+ _e_msgUserCancal,_e_msgStartTextForVpnServer,_e_msgButtonForVpnServer,_e_msgProcessCreatedForVpnServer,
+ _e_msgNoParam, _e_msgStartTextForVpnClient, _e_msgButtonForVpnClient, _e_msgEnd} MessageType_t;
+
+ int currentPage=MESSAGE_OFFSET_EN;
+
+int GetLocalizedMessageOffset(){
+ return currentPage;
+}
+wchar_t *LoadMessageW(enum MessageType e){
+ wchar_t *pTmp=(wchar_t*)calloc(sizeof(wchar_t),1024);
+ LoadStringW(hDllInstance,GetLocalizedMessageOffset()+e,pTmp,1024);
+ return pTmp;
+}
+char *LoadMessageA(enum MessageType e){
+ char *pTmp=(char*)calloc(sizeof(char),1024);
+ LoadStringA(hDllInstance,GetLocalizedMessageOffset()+e,pTmp,1024);
+ return pTmp;
+}
+void FreeMessage(void *p){
+ free(p);
+}
+int LoadTables(char *pTag){
+ if( stricmp(pTag,"JP")==0 || stricmp(pTag,"JA")==0){
+ currentPage=MESSAGE_OFFSET_JP;
+
+ }else if( stricmp(pTag,"EN")==0)
+ {
+ currentPage=MESSAGE_OFFSET_EN;
+ }
+// currentPage=MESSAGE_OFFSET_EN;
+
+ msgAppTitle=LoadMessageW(_e_msgAppTitle);
+ msgNotSupported=LoadMessageA(_e_msgNotSupported);
+ msgInfDownloag=LoadMessageW(_e_msgInfDownloag);
+ msgInfDownloadFailed=LoadMessageW(_e_msgInfDownloadFailed);
+ msgBadInfFile=LoadMessageW(_e_msgBadInfFile);
+ msgWriteFailed=LoadMessageW(_e_msgWriteFailed);
+ msgDownloading=LoadMessageW(_e_msgDownloading);
+ msgProcessFailed=LoadMessageW(_e_msgProcessFailed);
+ msgProcessCreating=LoadMessageW(_e_msgProcessCreating);
+ msgProcessCreated=LoadMessageW(_e_msgProcessCreated);
+ msgWarning=LoadMessageW(_e_msgWarning);
+ msgWarningTitle=LoadMessageW(_e_msgWarningTitle);
+ msgUserCancal=LoadMessageW(_e_msgUserCancal);
+ msgStartTextForVpnServer=LoadMessageW(_e_msgStartTextForVpnServer);
+ msgButtonForVpnServer=LoadMessageW(_e_msgButtonForVpnServer);
+ msgProcessCreatedForVpnServer=LoadMessageW(_e_msgProcessCreatedForVpnServer);
+ msgNoParam=LoadMessageA(_e_msgNoParam);
+ msgStartTextForVpnClient=LoadMessageW(_e_msgStartTextForVpnClient);
+ msgButtonForVpnClient=LoadMessageW(_e_msgButtonForVpnClient);
+ return 0;
+
+}
+
+#define false 0
+#define true 1
+#define bool UINT
+#define MAX_SIZE 512
+
+typedef struct VW_FILE
+{
+ UINT FileSize;
+ HINTERNET hInternet;
+ HINTERNET hHttpFile;
+} VW_FILE;
+
+typedef struct VW_TASK
+{
+ HANDLE Thread;
+ bool Halt;
+} VW_TASK;
+
+
+INT_PTR CALLBACK VpnWebDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK VpnWebDummyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void VwOnInit(HWND hWnd);
+void VwOnFree(HWND hWnd);
+HANDLE VwNewThread(LPTHREAD_START_ROUTINE start, void *param);
+void VwFreeThread(HANDLE h);
+void VwCloseFile(VW_FILE *f);
+UINT VwReadFile(VW_FILE *f, void *buf, UINT size);
+UINT VwGetFileSize(VW_FILE *f);
+VW_FILE *VwOpenFile(char *path);
+void VwPrint(HWND hWnd, wchar_t *str);
+DWORD CALLBACK VwTaskThread(void *param);
+char *VwUrlToFileName(char *url);
+UINT VwGetBuildFromVpnInstallInf(char *buf);
+bool VwCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger);
+bool VwCheckExeSign(HWND hWnd, char *exe);
+
+void *ZeroMalloc(UINT size);
+void Free(void *p);
+void *ReAlloc(void *p, UINT size);
+void Zero(void *p, UINT size);
+HANDLE FileCreate(char *name);
+HANDLE FileOpen(char *name, bool write_mode);
+void FileClose(HANDLE h);
+bool FileRead(HANDLE h, void *buf, UINT size);
+bool FileWrite(HANDLE h, void *buf, UINT size);
+UINT64 FileSize(HANDLE h);
+bool MakeDir(char *name);
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg);
+void Hide(HWND hWnd, UINT id);
+void Show(HWND hWnd, UINT id);
+void SetShow(HWND hWnd, UINT id, bool b);
+bool IsShow(HWND hWnd, UINT id);
+bool IsHide(HWND hWnd, UINT id);
+void RemoveExStyle(HWND hWnd, UINT id, UINT style);
+void SetExStyle(HWND hWnd, UINT id, UINT style);
+UINT GetExStyle(HWND hWnd, UINT id);
+void RemoveStyle(HWND hWnd, UINT id, UINT style);
+void SetStyle(HWND hWnd, UINT id, UINT style);
+UINT GetStyle(HWND hWnd, UINT id);
+void Refresh(HWND hWnd);
+void DoEvents(HWND hWnd);
+void Disable(HWND hWnd, UINT id);
+void Enable(HWND hWnd, UINT id);
+void SetEnable(HWND hWnd, UINT id, bool b);
+bool IsDisable(HWND hWnd, UINT id);
+bool IsEnable(HWND hWnd, UINT id);
+HWND DlgItem(HWND hWnd, UINT id);
+bool IsSupportedOs();
+void SetText(HWND hWnd, UINT id, wchar_t *str);
+UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam);
+void SetRange(HWND hWnd, UINT id, UINT start, UINT end);
+void SetPos(HWND hWnd, UINT id, UINT pos);
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/